diff options
| -rw-r--r-- | lldb/include/lldb/Core/Address.h | 17 | ||||
| -rw-r--r-- | lldb/include/lldb/Target/StackFrame.h | 15 | ||||
| -rw-r--r-- | lldb/include/lldb/Target/Unwind.h | 10 | ||||
| -rw-r--r-- | lldb/lit/Unwind/Inputs/trap_frame_sym_ctx.s | 42 | ||||
| -rw-r--r-- | lldb/lit/Unwind/trap_frame_sym_ctx.test | 21 | ||||
| -rw-r--r-- | lldb/source/Core/Address.cpp | 18 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp | 4 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/HistoryUnwind.h | 3 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | 105 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h | 4 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp | 21 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/UnwindLLDB.h | 3 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp | 6 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h | 3 | ||||
| -rw-r--r-- | lldb/source/Target/StackFrame.cpp | 30 | ||||
| -rw-r--r-- | lldb/source/Target/StackFrameList.cpp | 34 | 
16 files changed, 249 insertions, 87 deletions
diff --git a/lldb/include/lldb/Core/Address.h b/lldb/include/lldb/Core/Address.h index 080c00e7632..07bb450d609 100644 --- a/lldb/include/lldb/Core/Address.h +++ b/lldb/include/lldb/Core/Address.h @@ -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 diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 4e6e79befc6..d2e5795162c 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -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 ®_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 ®_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 diff --git a/lldb/include/lldb/Target/Unwind.h b/lldb/include/lldb/Target/Unwind.h index a648e063e34..652918ddad4 100644 --- a/lldb/include/lldb/Target/Unwind.h +++ b/lldb/include/lldb/Target/Unwind.h @@ -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; diff --git a/lldb/lit/Unwind/Inputs/trap_frame_sym_ctx.s b/lldb/lit/Unwind/Inputs/trap_frame_sym_ctx.s new file mode 100644 index 00000000000..bbced6656cf --- /dev/null +++ b/lldb/lit/Unwind/Inputs/trap_frame_sym_ctx.s @@ -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 diff --git a/lldb/lit/Unwind/trap_frame_sym_ctx.test b/lldb/lit/Unwind/trap_frame_sym_ctx.test new file mode 100644 index 00000000000..10f7892e928 --- /dev/null +++ b/lldb/lit/Unwind/trap_frame_sym_ctx.test @@ -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 diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index 0da83eb98ed..84ff4ec5b07 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -261,6 +261,24 @@ bool Address::ResolveAddressUsingFileSections(addr_t file_addr,    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()); diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp index 7d473bff820..83fdb011f5a 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -51,13 +51,15 @@ HistoryUnwind::DoCreateRegisterContextForFrame(StackFrame *frame) {  }  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; diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.h b/lldb/source/Plugins/Process/Utility/HistoryUnwind.h index 6c4522e6b35..4d16608bd8c 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.h +++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.h @@ -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: diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 62f38dcd85a..27341267a8a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -150,15 +150,8 @@ void RegisterContextLLDB::InitializeZerothFrame() {      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::InitializeZerothFrame() {                   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::InitializeNonZerothFrame() {      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::InitializeNonZerothFrame() {                   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::InitializeNonZerothFrame() {      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::InitializeNonZerothFrame() {      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::InitializeNonZerothFrame() {      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::TryFallbackUnwindPlan() {      // 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::ForceSwitchToFallbackUnwindPlan() {      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::ForceSwitchToFallbackUnwindPlan() {    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) { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h index 64dd394d233..1ca663906ed 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -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, diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp index 4b135351593..74fc90e8854 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -390,7 +390,8 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) {    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(uint32_t idx, addr_t &cfa, addr_t &pc) {    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; diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h index c512929c185..ff5db39730b 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h @@ -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; diff --git a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp index 7dc5a5f5fdd..558edeec1a3 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp @@ -43,9 +43,8 @@ uint32_t UnwindMacOSXFrameBackchain::DoGetFrameCount() {    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::DoGetFrameInfoAtIndex(uint32_t idx,      pc = m_cursors[idx].pc;      cfa = m_cursors[idx].fp; +    behaves_like_zeroth_frame = (idx == 0);      return true;    } diff --git a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h index 2208bcc2f2e..f0bde90a53b 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h +++ b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h @@ -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; diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 1bc8165d76b..5e5a596e471 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -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 &thread_sp, user_id_t frame_idx,  StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,                         user_id_t unwind_frame_index,                         const RegisterContextSP ®_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 &thread_sp, user_id_t frame_idx,  StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,                         user_id_t unwind_frame_index,                         const RegisterContextSP ®_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 &thread_sp, user_id_t frame_idx,             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(SymbolContextItem resolve_scope) {      // 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); diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp index 0723ed0b5a2..69445624a53 100644 --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -397,11 +397,13 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {      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(uint32_t end_idx) {      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(uint32_t end_idx) {          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(uint32_t end_idx) {            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(uint32_t end_idx) {          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(uint32_t end_idx) {        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(uint32_t end_idx) {        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::GetFrameAtIndex(uint32_t idx) {        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;  | 

