JosephTremoulet updated this revision to Diff 212615.
JosephTremoulet added a comment.

- Move resolution helper from RegisterContextLLDB to lldb_private::Address
- Defensively initialize out arguments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64993/new/

https://reviews.llvm.org/D64993

Files:
  lldb/include/lldb/Core/Address.h
  lldb/include/lldb/Target/StackFrame.h
  lldb/include/lldb/Target/Unwind.h
  lldb/source/Core/Address.cpp
  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 = (idx == 0);
     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 = (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;
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,10 @@
   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);
+
   // 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,8 @@
     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 @@
                  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 @@
     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 @@
                  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 @@
     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 @@
     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 +545,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(),
@@ -1708,6 +1669,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 +1713,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 +1722,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 = 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) {
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/source/Core/Address.cpp
===================================================================
--- lldb/source/Core/Address.cpp
+++ lldb/source/Core/Address.cpp
@@ -261,6 +261,24 @@
   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());
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 = (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 @@
   }
 
   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
Index: lldb/include/lldb/Core/Address.h
===================================================================
--- lldb/include/lldb/Core/Address.h
+++ lldb/include/lldb/Core/Address.h
@@ -338,6 +338,23 @@
   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
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to