JosephTremoulet created this revision.
JosephTremoulet added reviewers: jasonmolenda, clayborg.
Herald added a reviewer: jfb.
Herald added a project: LLDB.

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 a RegisterContextLLDB now
that we have it in four places.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64993

Files:
  lldb/include/lldb/Target/StackFrame.h
  lldb/include/lldb/Target/Unwind.h
  lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
  lldb/source/Plugins/Process/Utility/HistoryUnwind.h
  lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
  lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
  lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
  lldb/source/Plugins/Process/Utility/UnwindLLDB.h
  lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
  lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
  lldb/source/Target/StackFrame.cpp
  lldb/source/Target/StackFrameList.cpp

Index: lldb/source/Target/StackFrameList.cpp
===================================================================
--- lldb/source/Target/StackFrameList.cpp
+++ lldb/source/Target/StackFrameList.cpp
@@ -394,11 +394,13 @@
     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());
   }
@@ -448,6 +450,7 @@
     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;
     if (idx == 0) {
       // We might have already created frame zero, only create it if we need
       // to.
@@ -455,8 +458,9 @@
         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.
@@ -467,7 +471,7 @@
 
           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 {
@@ -475,8 +479,9 @@
         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();
@@ -485,7 +490,7 @@
       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,
@@ -527,10 +532,11 @@
       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;
@@ -661,11 +667,13 @@
       Unwind *unwinder = m_thread.GetUnwinder();
       if (unwinder) {
         addr_t pc, cfa;
-        if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) {
+        bool behaves_like_zeroth_frame;
+        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;
Index: lldb/source/Target/StackFrame.cpp
===================================================================
--- lldb/source/Target/StackFrame.cpp
+++ lldb/source/Target/StackFrame.cpp
@@ -50,14 +50,16 @@
 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.
@@ -74,15 +76,17 @@
 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());
@@ -98,7 +102,8 @@
 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),
@@ -106,9 +111,10 @@
            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());
@@ -288,7 +294,7 @@
     // 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);
Index: lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
===================================================================
--- lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
+++ lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
@@ -26,7 +26,8 @@
   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;
Index: lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
+++ lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
@@ -43,9 +43,8 @@
   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 @@
 
     pc = m_cursors[idx].pc;
     cfa = m_cursors[idx].fp;
+    behaves_like_zeroth_frame = (idx == 0);
 
     return true;
   }
Index: lldb/source/Plugins/Process/Utility/UnwindLLDB.h
===================================================================
--- lldb/source/Plugins/Process/Utility/UnwindLLDB.h
+++ lldb/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -73,7 +73,8 @@
   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;
Index: lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -395,7 +395,8 @@
   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;
@@ -410,6 +411,24 @@
   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;
Index: lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -120,6 +120,16 @@
   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 PropagateTrapHandlerFlag(lldb::UnwindPlanSP unwind_plan);
+
+  /// Set the symbol context and address range to the function of the given
+  /// pc, and return whether a valid context was found.
+  bool TryResolveSymbolContextAndAddressRange(
+      lldb_private::Address pc, lldb_private::SymbolContext &sym_ctx,
+      lldb_private::AddressRange &addr_range);
+
   // 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,
Index: lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -150,15 +150,9 @@
     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 = TryResolveSymbolContextAndAddressRange(
+      m_current_pc, m_sym_ctx, addr_range);
 
   if (m_sym_ctx.symbol) {
     UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'",
@@ -172,9 +166,6 @@
                  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 +427,9 @@
     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 = TryResolveSymbolContextAndAddressRange(
+      m_current_pc, m_sym_ctx, addr_range);
 
   if (m_sym_ctx.symbol) {
     UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc,
@@ -467,11 +443,6 @@
                  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 +483,9 @@
     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 = TryResolveSymbolContextAndAddressRange(
+        temporary_pc, m_sym_ctx, addr_range);
+
     UnwindLogMsg("Symbol is now %s",
                  GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
   }
@@ -573,6 +535,7 @@
     active_row =
         m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
     row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind();
+    PropagateTrapHandlerFlag(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 +548,7 @@
     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();
+      PropagateTrapHandlerFlag(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(),
@@ -628,6 +592,37 @@
                (uint64_t)m_afa);
 }
 
+bool RegisterContextLLDB::TryResolveSymbolContextAndAddressRange(
+    lldb_private::Address pc, lldb_private::SymbolContext &sym_ctx,
+    lldb_private::AddressRange &addr_range) {
+  ModuleSP pc_module_sp = pc.GetModule();
+
+  // Can't resolve context without a module.
+  if (!pc_module_sp)
+    return false;
+
+  // 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 caller will handle the case by
+  // decrementing pc and recomputing the symbol context.
+  constexpr bool resolve_tail_call_address = false;
+  constexpr SymbolContextItem resolve_scope =
+      eSymbolContextFunction | eSymbolContextSymbol;
+  uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress(
+      pc, resolve_scope, 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) {
+    return sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range);
+  }
+
+  addr_range.Clear();
+  return false;
+}
+
 bool RegisterContextLLDB::CheckIfLoopingStack() {
   // If we have a bad stack setup, we can get the same CFA value multiple times
   // -- or even more devious, we can actually oscillate between two CFA values.
@@ -1708,6 +1703,7 @@
     // We've copied the fallback unwind plan into the full - now clear the
     // fallback.
     m_fallback_unwind_plan_sp.reset();
+    PropagateTrapHandlerFlag(m_full_unwind_plan_sp);
   }
 
   return true;
@@ -1751,6 +1747,8 @@
 
     m_cfa = new_cfa;
 
+    PropagateTrapHandlerFlag(m_full_unwind_plan_sp);
+
     UnwindLogMsg("switched unconditionally to the fallback unwindplan %s",
                  m_full_unwind_plan_sp->GetSourceName().GetCString());
     return true;
@@ -1758,6 +1756,47 @@
   return false;
 }
 
+void RegisterContextLLDB::PropagateTrapHandlerFlag(
+    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.
+    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 = TryResolveSymbolContextAndAddressRange(
+        m_current_pc, 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) {
Index: lldb/source/Plugins/Process/Utility/HistoryUnwind.h
===================================================================
--- lldb/source/Plugins/Process/Utility/HistoryUnwind.h
+++ lldb/source/Plugins/Process/Utility/HistoryUnwind.h
@@ -29,7 +29,8 @@
   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:
Index: lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
+++ lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
@@ -51,13 +51,15 @@
 }
 
 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;
Index: lldb/include/lldb/Target/Unwind.h
===================================================================
--- lldb/include/lldb/Target/Unwind.h
+++ lldb/include/lldb/Target/Unwind.h
@@ -37,9 +37,10 @@
     lldb::addr_t cfa;
     lldb::addr_t pc;
     uint32_t idx;
+    bool behaves_like_zeroth_frame;
 
     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 @@
   }
 
   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 @@
   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;
Index: lldb/include/lldb/Target/StackFrame.h
===================================================================
--- lldb/include/lldb/Target/StackFrame.h
+++ lldb/include/lldb/Target/StackFrame.h
@@ -108,17 +108,19 @@
   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 @@
   /// 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 @@
   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
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to