[Lldb-commits] [lldb] r367691 - Fix PC adjustment in StackFrame::GetSymbolContext

Joseph Tremoulet via lldb-commits lldb-commits at lists.llvm.org
Fri Aug 2 09:53:43 PDT 2019


Author: josepht
Date: Fri Aug  2 09:53:42 2019
New Revision: 367691

URL: http://llvm.org/viewvc/llvm-project?rev=367691&view=rev
Log:
Fix PC adjustment in StackFrame::GetSymbolContext

Summary:
Update StackFrame::GetSymbolContext to mirror the logic in
RegisterContextLLDB::InitializeNonZerothFrame that knows not to do the
pc decrement when the given frame is a signal trap handler frame or the
parent of one, because the pc may not follow a call in these frames.
Accomplish this by adding a behaves_like_zeroth_frame field to
lldb_private::StackFrame, set to true for the zeroth frame, for
signal handler frames, and for parents of signal handler frames.

Also add logic to propagate the signal handler flag from UnwindPlan to
the FrameType on the RegisterContextLLDB it generates, and factor out a
helper to resolve symbol and address range for an Address now that we
need to invoke it in four places.

Reviewers: jasonmolenda, clayborg, jfb

Reviewed By: jasonmolenda

Subscribers: labath, dexonsmith, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D64993

Added:
    lldb/trunk/lit/Unwind/Inputs/trap_frame_sym_ctx.s
    lldb/trunk/lit/Unwind/trap_frame_sym_ctx.test
Modified:
    lldb/trunk/include/lldb/Core/Address.h
    lldb/trunk/include/lldb/Target/StackFrame.h
    lldb/trunk/include/lldb/Target/Unwind.h
    lldb/trunk/source/Core/Address.cpp
    lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.cpp
    lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
    lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp
    lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h
    lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
    lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
    lldb/trunk/source/Target/StackFrame.cpp
    lldb/trunk/source/Target/StackFrameList.cpp

Modified: lldb/trunk/include/lldb/Core/Address.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Address.h?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Address.h (original)
+++ lldb/trunk/include/lldb/Core/Address.h Fri Aug  2 09:53:42 2019
@@ -338,6 +338,23 @@ public:
   bool ResolveAddressUsingFileSections(lldb::addr_t addr,
                                        const SectionList *sections);
 
+  /// Resolve this address to its containing function and optionally get
+  /// that function's address range.
+  ///
+  /// \param[out] sym_ctx
+  ///     The symbol context describing the function in which this address lies
+  ///
+  /// \parm[out] addr_range_ptr
+  ///     Pointer to the AddressRange to fill in with the function's address
+  ///     range.  Caller may pass null if they don't need the address range.
+  ///
+  /// \return
+  ///     Returns \b false if the function/symbol could not be resolved
+  ///     or if the address range was requested and could not be resolved;
+  ///     returns \b true otherwise.
+  bool ResolveFunctionScope(lldb_private::SymbolContext &sym_ctx,
+                            lldb_private::AddressRange *addr_range_ptr = nullptr);
+
   /// Set the address to represent \a load_addr.
   ///
   /// The address will attempt to find a loaded section within \a target that

Modified: lldb/trunk/include/lldb/Target/StackFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StackFrame.h?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StackFrame.h (original)
+++ lldb/trunk/include/lldb/Target/StackFrame.h Fri Aug  2 09:53:42 2019
@@ -108,17 +108,19 @@ public:
   StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
              lldb::user_id_t concrete_frame_idx, lldb::addr_t cfa,
              bool cfa_is_valid, lldb::addr_t pc, Kind frame_kind,
-             const SymbolContext *sc_ptr);
+             bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr);
 
   StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
              lldb::user_id_t concrete_frame_idx,
              const lldb::RegisterContextSP &reg_context_sp, lldb::addr_t cfa,
-             lldb::addr_t pc, const SymbolContext *sc_ptr);
+             lldb::addr_t pc, bool behaves_like_zeroth_frame,
+             const SymbolContext *sc_ptr);
 
   StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
              lldb::user_id_t concrete_frame_idx,
              const lldb::RegisterContextSP &reg_context_sp, lldb::addr_t cfa,
-             const Address &pc, const SymbolContext *sc_ptr);
+             const Address &pc, bool behaves_like_zeroth_frame,
+             const SymbolContext *sc_ptr);
 
   ~StackFrame() override;
 
@@ -367,6 +369,12 @@ public:
   /// may have limited support for inspecting variables.
   bool IsArtificial() const;
 
+  /// Query whether this frame behaves like the zeroth frame, in the sense
+  /// that its pc value might not immediately follow a call (and thus might
+  /// be the first address of its function).  True for actual frame zero as
+  /// well as any other frame with the same trait.
+  bool BehavesLikeZerothFrame() const;
+
   /// Query this frame to find what frame it is in this Thread's
   /// StackFrameList.
   ///
@@ -511,6 +519,7 @@ private:
   bool m_cfa_is_valid; // Does this frame have a CFA?  Different from CFA ==
                        // LLDB_INVALID_ADDRESS
   Kind m_stack_frame_kind;
+  bool m_behaves_like_zeroth_frame;
   lldb::VariableListSP m_variable_list_sp;
   ValueObjectList m_variable_list_value_objects; // Value objects for each
                                                  // variable in

Modified: lldb/trunk/include/lldb/Target/Unwind.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Unwind.h?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Unwind.h (original)
+++ lldb/trunk/include/lldb/Target/Unwind.h Fri Aug  2 09:53:42 2019
@@ -37,9 +37,10 @@ public:
     lldb::addr_t cfa;
     lldb::addr_t pc;
     uint32_t idx;
+    bool behaves_like_zeroth_frame = (end_idx == 0);
 
     for (idx = 0; idx < end_idx; idx++) {
-      if (!DoGetFrameInfoAtIndex(idx, cfa, pc)) {
+      if (!DoGetFrameInfoAtIndex(idx, cfa, pc, behaves_like_zeroth_frame)) {
         break;
       }
     }
@@ -47,9 +48,9 @@ public:
   }
 
   bool GetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
-                           lldb::addr_t &pc) {
+                           lldb::addr_t &pc, bool &behaves_like_zeroth_frame) {
     std::lock_guard<std::recursive_mutex> guard(m_unwind_mutex);
-    return DoGetFrameInfoAtIndex(frame_idx, cfa, pc);
+    return DoGetFrameInfoAtIndex(frame_idx, cfa, pc, behaves_like_zeroth_frame);
   }
 
   lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame) {
@@ -66,7 +67,8 @@ protected:
   virtual uint32_t DoGetFrameCount() = 0;
 
   virtual bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
-                                     lldb::addr_t &pc) = 0;
+                                     lldb::addr_t &pc,
+                                     bool &behaves_like_zeroth_frame) = 0;
 
   virtual lldb::RegisterContextSP
   DoCreateRegisterContextForFrame(StackFrame *frame) = 0;

Added: lldb/trunk/lit/Unwind/Inputs/trap_frame_sym_ctx.s
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Unwind/Inputs/trap_frame_sym_ctx.s?rev=367691&view=auto
==============================================================================
--- lldb/trunk/lit/Unwind/Inputs/trap_frame_sym_ctx.s (added)
+++ lldb/trunk/lit/Unwind/Inputs/trap_frame_sym_ctx.s Fri Aug  2 09:53:42 2019
@@ -0,0 +1,42 @@
+        .text
+        .globl  bar
+bar:
+        .cfi_startproc
+        leal    (%edi, %edi), %eax
+        ret
+        .cfi_endproc
+
+        .globl  asm_main
+asm_main:
+        .cfi_startproc
+        pushq   %rbp
+        .cfi_def_cfa_offset 16
+        .cfi_offset %rbp, -16
+        movq    %rsp, %rbp
+        .cfi_def_cfa_register %rbp
+        movl    $47, %edi
+
+        # install tramp as return address
+        # (similar to signal return trampolines on some platforms)
+        leaq    tramp, %rax
+        pushq   %rax
+        jmp     bar # call, with return address pointing to tramp
+
+        popq    %rbp
+        .cfi_def_cfa %rsp, 8
+        ret
+        .cfi_endproc
+
+        .globl  tramp
+tramp:
+        .cfi_startproc
+        .cfi_signal_frame
+        # Emit cfi to line up with the frame created by asm_main
+        .cfi_def_cfa_offset 16
+        .cfi_offset %rbp, -16
+        .cfi_def_cfa_register %rbp
+        # copy asm_main's epilog to clean up the frame
+        popq    %rbp
+        .cfi_def_cfa %rsp, 8
+        ret
+        .cfi_endproc

Added: lldb/trunk/lit/Unwind/trap_frame_sym_ctx.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Unwind/trap_frame_sym_ctx.test?rev=367691&view=auto
==============================================================================
--- lldb/trunk/lit/Unwind/trap_frame_sym_ctx.test (added)
+++ lldb/trunk/lit/Unwind/trap_frame_sym_ctx.test Fri Aug  2 09:53:42 2019
@@ -0,0 +1,21 @@
+# Test that symbol contexts for trap handler frames are set correctly even when
+# the pc is at the start of the function.
+
+# UNSUPPORTED: system-windows
+# REQUIRES: target-x86_64, native
+
+# RUN: %clang %p/Inputs/call-asm.c %p/Inputs/trap_frame_sym_ctx.s -o %t
+# RUN: %lldb %t -s %s -o exit | FileCheck %s
+
+settings append target.trap-handler-names tramp
+
+breakpoint set -n bar
+# CHECK: Breakpoint 1: where = {{.*}}`bar
+
+process launch
+# CHECK: stop reason = breakpoint 1.1
+
+thread backtrace
+# CHECK: frame #0: {{.*}}`bar
+# CHECK: frame #1: {{.*}}`tramp
+# CHECK: frame #2: {{.*}}`main

Modified: lldb/trunk/source/Core/Address.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Address.cpp?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Core/Address.cpp (original)
+++ lldb/trunk/source/Core/Address.cpp Fri Aug  2 09:53:42 2019
@@ -261,6 +261,24 @@ bool Address::ResolveAddressUsingFileSec
   return false; // Failed to resolve this address to a section offset value
 }
 
+/// if "addr_range_ptr" is not NULL, then fill in with the address range of the function.
+bool Address::ResolveFunctionScope(SymbolContext &sym_ctx,
+                                   AddressRange *addr_range_ptr) {
+  constexpr SymbolContextItem resolve_scope =
+    eSymbolContextFunction | eSymbolContextSymbol;
+
+  if (!(CalculateSymbolContext(&sym_ctx, resolve_scope) & resolve_scope)) {
+    if (addr_range_ptr)
+      addr_range_ptr->Clear();
+   return false;
+  }
+
+  if (!addr_range_ptr)
+    return true;
+
+  return sym_ctx.GetAddressRange(resolve_scope, 0, false, *addr_range_ptr);
+}
+
 ModuleSP Address::GetModule() const {
   lldb::ModuleSP module_sp;
   SectionSP section_sp(GetSection());

Modified: lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.cpp?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.cpp Fri Aug  2 09:53:42 2019
@@ -51,13 +51,15 @@ HistoryUnwind::DoCreateRegisterContextFo
 }
 
 bool HistoryUnwind::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
-                                          lldb::addr_t &pc) {
+                                          lldb::addr_t &pc,
+                                          bool &behaves_like_zeroth_frame) {
   // FIXME do not throw away the lock after we acquire it..
   std::unique_lock<std::recursive_mutex> guard(m_unwind_mutex);
   guard.unlock();
   if (frame_idx < m_pcs.size()) {
     cfa = frame_idx;
     pc = m_pcs[frame_idx];
+    behaves_like_zeroth_frame = (frame_idx == 0);
     return true;
   }
   return false;

Modified: lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.h?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/HistoryUnwind.h Fri Aug  2 09:53:42 2019
@@ -29,7 +29,8 @@ protected:
   DoCreateRegisterContextForFrame(StackFrame *frame) override;
 
   bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
-                             lldb::addr_t &pc) override;
+                             lldb::addr_t &pc,
+                             bool &behaves_like_zeroth_frame) override;
   uint32_t DoGetFrameCount() override;
 
 private:

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Fri Aug  2 09:53:42 2019
@@ -150,15 +150,8 @@ void RegisterContextLLDB::InitializeZero
     UnwindLogMsg("using architectural default unwind method");
   }
 
-  // We require either a symbol or function in the symbols context to be
-  // successfully filled in or this context is of no use to us.
-  const SymbolContextItem resolve_scope =
-      eSymbolContextFunction | eSymbolContextSymbol;
-  if (pc_module_sp.get() && (pc_module_sp->ResolveSymbolContextForAddress(
-                                 m_current_pc, resolve_scope, m_sym_ctx) &
-                             resolve_scope)) {
-    m_sym_ctx_valid = true;
-  }
+  AddressRange addr_range;
+  m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range);
 
   if (m_sym_ctx.symbol) {
     UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'",
@@ -172,9 +165,6 @@ void RegisterContextLLDB::InitializeZero
                  current_pc);
   }
 
-  AddressRange addr_range;
-  m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range);
-
   if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
     m_frame_type = eTrapHandlerFrame;
   } else {
@@ -436,24 +426,8 @@ void RegisterContextLLDB::InitializeNonZ
     return;
   }
 
-  bool resolve_tail_call_address = false; // m_current_pc can be one past the
-                                          // address range of the function...
-  // If the saved pc does not point to a function/symbol because it is beyond
-  // the bounds of the correct function and there's no symbol there, we do
-  // *not* want ResolveSymbolContextForAddress to back up the pc by 1, because
-  // then we might not find the correct unwind information later. Instead, let
-  // ResolveSymbolContextForAddress fail, and handle the case via
-  // decr_pc_and_recompute_addr_range below.
-  const SymbolContextItem resolve_scope =
-      eSymbolContextFunction | eSymbolContextSymbol;
-  uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress(
-      m_current_pc, resolve_scope, m_sym_ctx, resolve_tail_call_address);
-
-  // We require either a symbol or function in the symbols context to be
-  // successfully filled in or this context is of no use to us.
-  if (resolve_scope & resolved_scope) {
-    m_sym_ctx_valid = true;
-  }
+  AddressRange addr_range;
+  m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range);
 
   if (m_sym_ctx.symbol) {
     UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc,
@@ -467,11 +441,6 @@ void RegisterContextLLDB::InitializeNonZ
                  pc);
   }
 
-  AddressRange addr_range;
-  if (!m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range)) {
-    m_sym_ctx_valid = false;
-  }
-
   bool decr_pc_and_recompute_addr_range;
 
   if (!m_sym_ctx_valid) {
@@ -512,18 +481,8 @@ void RegisterContextLLDB::InitializeNonZ
     Address temporary_pc;
     temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget());
     m_sym_ctx.Clear(false);
-    m_sym_ctx_valid = false;
-    SymbolContextItem resolve_scope =
-        eSymbolContextFunction | eSymbolContextSymbol;
-
-    ModuleSP temporary_module_sp = temporary_pc.GetModule();
-    if (temporary_module_sp &&
-        temporary_module_sp->ResolveSymbolContextForAddress(
-            temporary_pc, resolve_scope, m_sym_ctx) &
-            resolve_scope) {
-      if (m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range))
-        m_sym_ctx_valid = true;
-    }
+    m_sym_ctx_valid = temporary_pc.ResolveFunctionScope(m_sym_ctx, &addr_range);
+
     UnwindLogMsg("Symbol is now %s",
                  GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
   }
@@ -573,6 +532,7 @@ void RegisterContextLLDB::InitializeNonZ
     active_row =
         m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
     row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind();
+    PropagateTrapHandlerFlagFromUnwindPlan(m_fast_unwind_plan_sp);
     if (active_row.get() && log) {
       StreamString active_row_strm;
       active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread,
@@ -585,6 +545,7 @@ void RegisterContextLLDB::InitializeNonZ
     if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) {
       active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(valid_offset);
       row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
+      PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
       if (active_row.get() && log) {
         StreamString active_row_strm;
         active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
@@ -1708,6 +1669,7 @@ bool RegisterContextLLDB::TryFallbackUnw
     // We've copied the fallback unwind plan into the full - now clear the
     // fallback.
     m_fallback_unwind_plan_sp.reset();
+    PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
   }
 
   return true;
@@ -1751,6 +1713,8 @@ bool RegisterContextLLDB::ForceSwitchToF
 
     m_cfa = new_cfa;
 
+    PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
+
     UnwindLogMsg("switched unconditionally to the fallback unwindplan %s",
                  m_full_unwind_plan_sp->GetSourceName().GetCString());
     return true;
@@ -1758,6 +1722,53 @@ bool RegisterContextLLDB::ForceSwitchToF
   return false;
 }
 
+void RegisterContextLLDB::PropagateTrapHandlerFlagFromUnwindPlan(
+    lldb::UnwindPlanSP unwind_plan) {
+  if (unwind_plan->GetUnwindPlanForSignalTrap() != eLazyBoolYes) {
+    // Unwind plan does not indicate trap handler.  Do nothing.  We may
+    // already be flagged as trap handler flag due to the symbol being
+    // in the trap handler symbol list, and that should take precedence.
+    return;
+  } else if (m_frame_type != eNormalFrame) {
+    // If this is already a trap handler frame, nothing to do.
+    // If this is a skip or debug or invalid frame, don't override that.
+    return;
+  }
+
+  m_frame_type = eTrapHandlerFrame;
+
+  if (m_current_offset_backed_up_one != m_current_offset) {
+    // We backed up the pc by 1 to compute the symbol context, but
+    // now need to undo that because the pc of the trap handler
+    // frame may in fact be the first instruction of a signal return
+    // trampoline, rather than the instruction after a call.  This
+    // happens on systems where the signal handler dispatch code, rather
+    // than calling the handler and being returned to, jumps to the
+    // handler after pushing the address of a return trampoline on the
+    // stack -- on these systems, when the handler returns, control will
+    // be transferred to the return trampoline, so that's the best
+    // symbol we can present in the callstack.
+    UnwindLogMsg("Resetting current offset and re-doing symbol lookup; "
+                 "old symbol was %s",
+                 GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
+    m_current_offset_backed_up_one = m_current_offset;
+
+    AddressRange addr_range;
+    m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range);
+
+    UnwindLogMsg("Symbol is now %s",
+                 GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
+
+    ExecutionContext exe_ctx(m_thread.shared_from_this());
+    Process *process = exe_ctx.GetProcessPtr();
+    Target *target = &process->GetTarget();
+
+    m_start_pc = addr_range.GetBaseAddress();
+    m_current_offset =
+        m_current_pc.GetLoadAddress(target) - m_start_pc.GetLoadAddress(target);
+  }
+}
+
 bool RegisterContextLLDB::ReadFrameAddress(
     lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa,
     addr_t &address) {

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h Fri Aug  2 09:53:42 2019
@@ -120,6 +120,10 @@ private:
   bool IsTrapHandlerSymbol(lldb_private::Process *process,
                            const lldb_private::SymbolContext &m_sym_ctx) const;
 
+  /// Check if the given unwind plan indicates a signal trap handler, and
+  /// update frame type and symbol context if so.
+  void PropagateTrapHandlerFlagFromUnwindPlan(lldb::UnwindPlanSP unwind_plan);
+
   // Provide a location for where THIS function saved the CALLER's register
   // value
   // Or a frame "below" this one saved it, i.e. a function called by this one,

Modified: lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp Fri Aug  2 09:53:42 2019
@@ -390,7 +390,8 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *ab
   return true;
 }
 
-bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc) {
+bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc,
+                                       bool &behaves_like_zeroth_frame) {
   if (m_frames.size() == 0) {
     if (!AddFirstFrame())
       return false;
@@ -405,6 +406,24 @@ bool UnwindLLDB::DoGetFrameInfoAtIndex(u
   if (idx < m_frames.size()) {
     cfa = m_frames[idx]->cfa;
     pc = m_frames[idx]->start_pc;
+    if (idx == 0) {
+      // Frame zero always behaves like it.
+      behaves_like_zeroth_frame = true;
+    } else if (m_frames[idx - 1]->reg_ctx_lldb_sp->IsTrapHandlerFrame()) {
+      // This could be an asynchronous signal, thus the
+      // pc might point to the interrupted instruction rather
+      // than a post-call instruction
+      behaves_like_zeroth_frame = true;
+    } else if (m_frames[idx]->reg_ctx_lldb_sp->IsTrapHandlerFrame()) {
+      // This frame may result from signal processing installing
+      // a pointer to the first byte of a signal-return trampoline
+      // in the return address slot of the frame below, so this
+      // too behaves like the zeroth frame (i.e. the pc might not
+      // be pointing just past a call in it)
+      behaves_like_zeroth_frame = true;
+    } else {
+      behaves_like_zeroth_frame = false;
+    }
     return true;
   }
   return false;

Modified: lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.h Fri Aug  2 09:53:42 2019
@@ -73,7 +73,8 @@ protected:
   uint32_t DoGetFrameCount() override;
 
   bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
-                             lldb::addr_t &start_pc) override;
+                             lldb::addr_t &start_pc,
+                             bool &behaves_like_zeroth_frame) override;
 
   lldb::RegisterContextSP
   DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;

Modified: lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp Fri Aug  2 09:53:42 2019
@@ -43,9 +43,8 @@ uint32_t UnwindMacOSXFrameBackchain::DoG
   return m_cursors.size();
 }
 
-bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(uint32_t idx,
-                                                       addr_t &cfa,
-                                                       addr_t &pc) {
+bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(
+    uint32_t idx, addr_t &cfa, addr_t &pc, bool &behaves_like_zeroth_frame) {
   const uint32_t frame_count = GetFrameCount();
   if (idx < frame_count) {
     if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS)
@@ -55,6 +54,7 @@ bool UnwindMacOSXFrameBackchain::DoGetFr
 
     pc = m_cursors[idx].pc;
     cfa = m_cursors[idx].fp;
+    behaves_like_zeroth_frame = (idx == 0);
 
     return true;
   }

Modified: lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h Fri Aug  2 09:53:42 2019
@@ -26,7 +26,8 @@ protected:
   uint32_t DoGetFrameCount() override;
 
   bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
-                             lldb::addr_t &pc) override;
+                             lldb::addr_t &pc,
+                             bool &behaves_like_zeroth_frame) override;
 
   lldb::RegisterContextSP
   DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;

Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Fri Aug  2 09:53:42 2019
@@ -51,14 +51,16 @@ using namespace lldb_private;
 StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
                        user_id_t unwind_frame_index, addr_t cfa,
                        bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,
+                       bool behaves_like_zeroth_frame,
                        const SymbolContext *sc_ptr)
     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
       m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),
       m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(),
       m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid),
-      m_stack_frame_kind(kind), m_variable_list_sp(),
-      m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
-      m_mutex() {
+      m_stack_frame_kind(kind),
+      m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
+      m_variable_list_sp(), m_variable_list_value_objects(),
+      m_recognized_frame_sp(), m_disassembly(), m_mutex() {
   // If we don't have a CFA value, use the frame index for our StackID so that
   // recursive functions properly aren't confused with one another on a history
   // stack.
@@ -75,15 +77,17 @@ StackFrame::StackFrame(const ThreadSP &t
 StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
                        user_id_t unwind_frame_index,
                        const RegisterContextSP &reg_context_sp, addr_t cfa,
-                       addr_t pc, const SymbolContext *sc_ptr)
+                       addr_t pc, bool behaves_like_zeroth_frame,
+                       const SymbolContext *sc_ptr)
     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
       m_concrete_frame_index(unwind_frame_index),
       m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr),
       m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),
       m_frame_base_error(), m_cfa_is_valid(true),
-      m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(),
-      m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
-      m_mutex() {
+      m_stack_frame_kind(StackFrame::Kind::Regular),
+      m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
+      m_variable_list_sp(), m_variable_list_value_objects(),
+      m_recognized_frame_sp(), m_disassembly(), m_mutex() {
   if (sc_ptr != nullptr) {
     m_sc = *sc_ptr;
     m_flags.Set(m_sc.GetResolvedMask());
@@ -99,7 +103,8 @@ StackFrame::StackFrame(const ThreadSP &t
 StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
                        user_id_t unwind_frame_index,
                        const RegisterContextSP &reg_context_sp, addr_t cfa,
-                       const Address &pc_addr, const SymbolContext *sc_ptr)
+                       const Address &pc_addr, bool behaves_like_zeroth_frame,
+                       const SymbolContext *sc_ptr)
     : m_thread_wp(thread_sp), m_frame_index(frame_idx),
       m_concrete_frame_index(unwind_frame_index),
       m_reg_context_sp(reg_context_sp),
@@ -107,9 +112,10 @@ StackFrame::StackFrame(const ThreadSP &t
            nullptr),
       m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(),
       m_frame_base_error(), m_cfa_is_valid(true),
-      m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(),
-      m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
-      m_mutex() {
+      m_stack_frame_kind(StackFrame::Kind::Regular),
+      m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),
+      m_variable_list_sp(), m_variable_list_value_objects(),
+      m_recognized_frame_sp(), m_disassembly(), m_mutex() {
   if (sc_ptr != nullptr) {
     m_sc = *sc_ptr;
     m_flags.Set(m_sc.GetResolvedMask());
@@ -289,7 +295,7 @@ StackFrame::GetSymbolContext(SymbolConte
     // following the function call instruction...
 
     Address lookup_addr(GetFrameCodeAddress());
-    if (m_frame_index > 0 && lookup_addr.IsValid()) {
+    if (!m_behaves_like_zeroth_frame && lookup_addr.IsValid()) {
       addr_t offset = lookup_addr.GetOffset();
       if (offset > 0) {
         lookup_addr.SetOffset(offset - 1);

Modified: lldb/trunk/source/Target/StackFrameList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrameList.cpp?rev=367691&r1=367690&r2=367691&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrameList.cpp (original)
+++ lldb/trunk/source/Target/StackFrameList.cpp Fri Aug  2 09:53:42 2019
@@ -397,11 +397,13 @@ void StackFrameList::SynthesizeTailCallF
     bool cfa_is_valid = false;
     addr_t pc =
         callee->GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
+    constexpr bool behaves_like_zeroth_frame = false;
     SymbolContext sc;
     callee->CalculateSymbolContext(&sc);
     auto synth_frame = std::make_shared<StackFrame>(
         m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa,
-        cfa_is_valid, pc, StackFrame::Kind::Artificial, &sc);
+        cfa_is_valid, pc, StackFrame::Kind::Artificial,
+        behaves_like_zeroth_frame, &sc);
     m_frames.push_back(synth_frame);
     LLDB_LOG(log, "Pushed frame {0}", callee->GetDisplayName());
   }
@@ -451,6 +453,7 @@ void StackFrameList::GetFramesUpTo(uint3
     uint32_t idx = m_concrete_frames_fetched++;
     lldb::addr_t pc = LLDB_INVALID_ADDRESS;
     lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
+    bool behaves_like_zeroth_frame = (idx == 0);
     if (idx == 0) {
       // We might have already created frame zero, only create it if we need
       // to.
@@ -458,8 +461,9 @@ void StackFrameList::GetFramesUpTo(uint3
         RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
 
         if (reg_ctx_sp) {
-          const bool success =
-              unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+          const bool success = unwinder &&
+                               unwinder->GetFrameInfoAtIndex(
+                                   idx, cfa, pc, behaves_like_zeroth_frame);
           // There shouldn't be any way not to get the frame info for frame
           // 0. But if the unwinder can't make one, lets make one by hand
           // with the SP as the CFA and see if that gets any further.
@@ -470,7 +474,7 @@ void StackFrameList::GetFramesUpTo(uint3
 
           unwind_frame_sp = std::make_shared<StackFrame>(
               m_thread.shared_from_this(), m_frames.size(), idx, reg_ctx_sp,
-              cfa, pc, nullptr);
+              cfa, pc, behaves_like_zeroth_frame, nullptr);
           m_frames.push_back(unwind_frame_sp);
         }
       } else {
@@ -478,8 +482,9 @@ void StackFrameList::GetFramesUpTo(uint3
         cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
       }
     } else {
-      const bool success =
-          unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+      const bool success = unwinder &&
+                           unwinder->GetFrameInfoAtIndex(
+                               idx, cfa, pc, behaves_like_zeroth_frame);
       if (!success) {
         // We've gotten to the end of the stack.
         SetAllFramesFetched();
@@ -488,7 +493,7 @@ void StackFrameList::GetFramesUpTo(uint3
       const bool cfa_is_valid = true;
       unwind_frame_sp = std::make_shared<StackFrame>(
           m_thread.shared_from_this(), m_frames.size(), idx, cfa, cfa_is_valid,
-          pc, StackFrame::Kind::Regular, nullptr);
+          pc, StackFrame::Kind::Regular, behaves_like_zeroth_frame, nullptr);
 
       // Create synthetic tail call frames between the previous frame and the
       // newly-found frame. The new frame's index may change after this call,
@@ -530,10 +535,11 @@ void StackFrameList::GetFramesUpTo(uint3
       while (unwind_sc.GetParentOfInlinedScope(
           curr_frame_address, next_frame_sc, next_frame_address)) {
         next_frame_sc.line_entry.ApplyFileMappings(target_sp);
-        StackFrameSP frame_sp(
-            new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx,
-                           unwind_frame_sp->GetRegisterContextSP(), cfa,
-                           next_frame_address, &next_frame_sc));
+        behaves_like_zeroth_frame = false;
+        StackFrameSP frame_sp(new StackFrame(
+            m_thread.shared_from_this(), m_frames.size(), idx,
+            unwind_frame_sp->GetRegisterContextSP(), cfa, next_frame_address,
+            behaves_like_zeroth_frame, &next_frame_sc));
 
         m_frames.push_back(frame_sp);
         unwind_sc = next_frame_sc;
@@ -664,11 +670,13 @@ StackFrameSP StackFrameList::GetFrameAtI
       Unwind *unwinder = m_thread.GetUnwinder();
       if (unwinder) {
         addr_t pc, cfa;
-        if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) {
+        bool behaves_like_zeroth_frame = (idx == 0);
+        if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc,
+                                          behaves_like_zeroth_frame)) {
           const bool cfa_is_valid = true;
           frame_sp = std::make_shared<StackFrame>(
               m_thread.shared_from_this(), idx, idx, cfa, cfa_is_valid, pc,
-              StackFrame::Kind::Regular, nullptr);
+              StackFrame::Kind::Regular, behaves_like_zeroth_frame, nullptr);
 
           Function *function =
               frame_sp->GetSymbolContext(eSymbolContextFunction).function;




More information about the lldb-commits mailing list