diff options
28 files changed, 567 insertions, 115 deletions
diff --git a/lldb/include/lldb/Core/VMRange.h b/lldb/include/lldb/Core/VMRange.h index c0bba12c3a9..c6ce3029de6 100644 --- a/lldb/include/lldb/Core/VMRange.h +++ b/lldb/include/lldb/Core/VMRange.h @@ -148,6 +148,11 @@ public: static bool ContainsRange(const VMRange::collection& coll, const VMRange& range); + // Returns a valid index into coll when a match is found, else UINT32_MAX + // is returned + static uint32_t + FindRangeIndexThatContainsValue (const VMRange::collection& coll, lldb::addr_t value); + protected: lldb::addr_t m_base_addr; lldb::addr_t m_byte_size; diff --git a/lldb/include/lldb/Symbol/Block.h b/lldb/include/lldb/Symbol/Block.h index 3e599930994..c55b1a2c208 100644 --- a/lldb/include/lldb/Symbol/Block.h +++ b/lldb/include/lldb/Symbol/Block.h @@ -181,6 +181,9 @@ public: //------------------------------------------------------------------ Block * GetParent () const; + + Block * + GetInlinedParent () const; //------------------------------------------------------------------ /// Get the sibling block for this block. @@ -243,6 +246,11 @@ public: /// If \b true, all variables from all parent blocks will be /// added to the variable list. /// + /// @param[in] stop_if_block_is_inlined_function + /// If \b true, all variables from all parent blocks will be + /// added to the variable list until there are no parent blocks + /// or the parent block has inlined function info. + /// /// @param[in/out] variable_list /// All variables in this block, and optionally all parent /// blocks will be added to this list. @@ -252,7 +260,10 @@ public: /// variable_list. //------------------------------------------------------------------ uint32_t - AppendVariables(bool can_create, bool get_parent_variables, VariableList *variable_list); + AppendVariables (bool can_create, + bool get_parent_variables, + bool stop_if_block_is_inlined_function, + VariableList *variable_list); //------------------------------------------------------------------ /// Get accessor for any inlined function information. @@ -352,6 +363,10 @@ public: Block * FindBlockByID (lldb::user_id_t block_id); + bool + GetRangeContainingAddress (const Address& addr, AddressRange &range); + + protected: typedef std::vector<lldb::BlockSP> collection; //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h index b2ba0e53c81..51e76dbf783 100644 --- a/lldb/include/lldb/Symbol/Function.h +++ b/lldb/include/lldb/Symbol/Function.h @@ -241,6 +241,9 @@ public: void DumpStopContext (Stream *s) const; + const ConstString & + GetName () const; + //------------------------------------------------------------------ /// Get accessor for the call site declaration information. /// diff --git a/lldb/include/lldb/Symbol/SymbolContext.h b/lldb/include/lldb/Symbol/SymbolContext.h index 6ba985dd016..246a3fc5a6e 100644 --- a/lldb/include/lldb/Symbol/SymbolContext.h +++ b/lldb/include/lldb/Symbol/SymbolContext.h @@ -163,7 +163,8 @@ public: DumpStopContext (Stream *s, ExecutionContextScope *exe_scope, const Address &so_addr, - bool show_module = true) const; + bool show_module, + bool show_inlined_frames) const; //------------------------------------------------------------------ /// Get the address range contained within a symbol context. @@ -190,6 +191,10 @@ public: lldb::DescriptionLevel level, Process *process) const; + uint32_t + GetResolvedMask () const; + + //------------------------------------------------------------------ /// Find a function matching the given name, working out from this /// symbol context. diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 0c46ec278eb..a030080aa75 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -27,15 +27,15 @@ namespace lldb_private { class StackFrame : - public UserID, public ExecutionContextScope { public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - StackFrame (lldb::user_id_t frame_idx, Thread &thread, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr = NULL); - StackFrame (lldb::user_id_t frame_idx, Thread &thread, lldb::RegisterContextSP ®_context_sp, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr = NULL); + StackFrame (lldb::user_id_t frame_idx, lldb::user_id_t concrete_frame_idx, Thread &thread, lldb::addr_t cfa, uint32_t inline_height, lldb::addr_t pc, const SymbolContext *sc_ptr); + StackFrame (lldb::user_id_t frame_idx, lldb::user_id_t concrete_frame_idx, Thread &thread, const lldb::RegisterContextSP ®_context_sp, lldb::addr_t cfa, uint32_t inline_height, lldb::addr_t pc, const SymbolContext *sc_ptr); + StackFrame (lldb::user_id_t frame_idx, lldb::user_id_t concrete_frame_idx, Thread &thread, const lldb::RegisterContextSP ®_context_sp, lldb::addr_t cfa, uint32_t inline_height, const Address& pc, const SymbolContext *sc_ptr); virtual ~StackFrame (); Thread & @@ -64,6 +64,12 @@ public: RegisterContext * GetRegisterContext (); + const lldb::RegisterContextSP & + GetRegisterContextSP () const + { + return m_reg_context_sp; + } + VariableList * GetVariableList (); @@ -79,6 +85,17 @@ public: void Dump (Stream *strm, bool show_frame_index); + uint32_t + GetFrameIndex () const + { + return m_frame_index; + } + + uint32_t + GetConcreteFrameIndex () const + { + return m_concrete_frame_index; + } //------------------------------------------------------------------ // lldb::ExecutionContextScope pure virtual functions //------------------------------------------------------------------ @@ -108,6 +125,8 @@ private: // For StackFrame only //------------------------------------------------------------------ Thread &m_thread; + uint32_t m_frame_index; + uint32_t m_concrete_frame_index; lldb::RegisterContextSP m_reg_context_sp; StackID m_id; Address m_pc; // PC as a section/offset address diff --git a/lldb/include/lldb/Target/StackID.h b/lldb/include/lldb/Target/StackID.h index cf02be1c925..3d55a232fde 100644 --- a/lldb/include/lldb/Target/StackID.h +++ b/lldb/include/lldb/Target/StackID.h @@ -26,20 +26,34 @@ public: // Constructors and Destructors //------------------------------------------------------------------ StackID (); - explicit StackID (lldb::addr_t cfa); - StackID (const Address& start_address, lldb::addr_t cfa); + explicit StackID (lldb::addr_t cfa, uint32_t inline_id); + StackID (const Address& start_address, lldb::addr_t cfa, uint32_t inline_id); StackID (const StackID& rhs); virtual ~StackID(); const Address& - GetStartAddress() const; + GetStartAddress() const + { + return m_start_address; + } void - SetStartAddress(const Address& start_address); + SetStartAddress(const Address& start_address) + { + m_start_address = start_address; + } lldb::addr_t - GetCallFrameAddress() const; + GetCallFrameAddress() const + { + return m_cfa; + } + uint32_t + GetInlineHeight () const + { + return m_inline_height; + } //------------------------------------------------------------------ // Operators //------------------------------------------------------------------ @@ -53,7 +67,10 @@ protected: Address m_start_address; // The address range for the function for this frame lldb::addr_t m_cfa; // The call frame address (stack pointer) value // at the beginning of the function that uniquely - // identifies this frame + // identifies this frame (along with m_inline_height below) + uint32_t m_inline_height; // The inline height of a stack frame. Zero is the actual + // value for the place where a thread stops, 1 and above + // are for the inlined frames above the concrete base frame. }; bool operator== (const StackID& lhs, const StackID& rhs); diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index a66bded7a88..33525858e7e 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -328,7 +328,8 @@ public: virtual void ClearStackFrames () { - m_frames.Clear(); + m_concrete_frames.Clear(); + m_inlined_frames.Clear(); } void @@ -665,6 +666,13 @@ protected: virtual lldb_private::Unwind * GetUnwinder () = 0; + typedef struct InlinedFrameInfo + { + uint32_t concrete_frame_index; + uint32_t inline_height; + Block *block; + } InlinedFrameInfo; + typedef std::vector<InlinedFrameInfo> InlinedFrameInfoCollection; //------------------------------------------------------------------ // Classes that inherit from Process can see and modify these //------------------------------------------------------------------ @@ -678,9 +686,11 @@ protected: plan_stack m_immediate_plan_stack; ///< The plans that need to get executed before any other work gets done. plan_stack m_completed_plan_stack; ///< Plans that have been completed by this stop. They get deleted when the thread resumes. plan_stack m_discarded_plan_stack; ///< Plans that have been discarded by this stop. They get deleted when the thread resumes. - mutable Mutex m_state_mutex; ///< Multithreaded protection for m_state. - StackFrameList m_frames; ///< The stack frames that get lazily populated after a thread stops. - uint32_t m_current_frame_idx;///< The current frame for this thread + mutable Mutex m_state_mutex; ///< Multithreaded protection for m_state. + StackFrameList m_concrete_frames; ///< The stack frames that get lazily populated after a thread stops. + StackFrameList m_inlined_frames; ///< The stack frames that get lazily populated after a thread stops. + InlinedFrameInfoCollection m_inlined_frame_info; + bool m_show_inlined_frames; int m_resume_signal; ///< The signal that should be used when continuing this thread. lldb::StateType m_resume_state; ///< The state that indicates what this thread should do when the process is resumed. std::auto_ptr<lldb_private::Unwind> m_unwinder_ap; diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp index 2ca8e76a478..e7485cc1d4e 100644 --- a/lldb/source/API/SBBlock.cpp +++ b/lldb/source/API/SBBlock.cpp @@ -39,7 +39,8 @@ SBBlock::AppendVariables (bool can_create, bool get_parent_variables, lldb_priva { if (IsValid()) { - m_opaque_ptr->AppendVariables (can_create, get_parent_variables, var_list); + bool show_inline = true; + m_opaque_ptr->AppendVariables (can_create, get_parent_variables, show_inline, var_list); } } diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index b8c2f700fb2..53307718143 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -116,7 +116,7 @@ uint32_t SBFrame::GetFrameID () const { if (m_opaque_sp) - return m_opaque_sp->GetID(); + return m_opaque_sp->GetFrameIndex (); else return UINT32_MAX; } diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index c5285fdbd41..087e29e0cf7 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -288,7 +288,7 @@ SBThread::DisplaySingleFrameForCurrentContext (FILE *out, frame_idx, GetThreadID(), (long long)pc); - sc->DumpStopContext (&str, &m_opaque_sp->GetProcess(), *frame.GetPCAddress()); + sc->DumpStopContext (&str, &m_opaque_sp->GetProcess(), *frame.GetPCAddress(), true, false); fprintf (out, "\n"); success = true; } diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp index f266142598c..f2e338c4587 100644 --- a/lldb/source/Breakpoint/BreakpointLocation.cpp +++ b/lldb/source/Breakpoint/BreakpointLocation.cpp @@ -285,7 +285,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) if (level == lldb::eDescriptionLevelFull) { s->PutCString("where = "); - sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address); + sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, true, false); } else { diff --git a/lldb/source/Commands/CommandObjectImage.cpp b/lldb/source/Commands/CommandObjectImage.cpp index a5d1f332a9f..c9a22543a6f 100644 --- a/lldb/source/Commands/CommandObjectImage.cpp +++ b/lldb/source/Commands/CommandObjectImage.cpp @@ -341,7 +341,7 @@ DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolCont strm.PutCString(" in "); } } - sc.DumpStopContext(&strm, interpreter.GetDebugger().GetExecutionContext().process, sc.line_entry.range.GetBaseAddress()); + sc.DumpStopContext(&strm, interpreter.GetDebugger().GetExecutionContext().process, sc.line_entry.range.GetBaseAddress(), true, false); } } strm.IndentLess (); diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 380aaa5a969..82749c08b5a 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -162,7 +162,7 @@ lldb_private::DisplayFramesForExecutionContext true, // Dump the stop reason? true, // Dump the thread name? true, // Dump the queue name? - 0); // Dump info for stack frame zero + num_frames > 1 ? UINT32_MAX : first_frame); // Dump info for the first stack frame if we are showing only on frame strm.EOL(); strm.IndentMore(); diff --git a/lldb/source/Commands/CommandObjectVariable.cpp b/lldb/source/Commands/CommandObjectVariable.cpp index 7a6592b9b84..79677e23e17 100644 --- a/lldb/source/Commands/CommandObjectVariable.cpp +++ b/lldb/source/Commands/CommandObjectVariable.cpp @@ -255,7 +255,7 @@ public: s.Printf ("Variable{0x%8.8x}: ", variable->GetID()); if (!expr_success) - s.Printf ("%s = ERROR (%s)", variable->GetName().AsCString(NULL), expr_error.AsCString()); + s.Printf ("%s = ERROR: %s\n", variable->GetName().AsCString(NULL), expr_error.AsCString()); else { Value::ValueType expr_value_type = expr_result.GetValueType(); @@ -318,8 +318,8 @@ public: } break; } + s.EOL(); } - s.EOL(); } } @@ -484,9 +484,10 @@ public: { VariableList variable_list; + bool show_inlined = true; // TODO: Get this from the process SymbolContext frame_sc = exe_ctx.frame->GetSymbolContext (eSymbolContextEverything); if (exe_ctx.frame && frame_sc.block) - frame_sc.block->AppendVariables(true, true, &variable_list); + frame_sc.block->AppendVariables(true, true, show_inlined, &variable_list); VariableSP var_sp; ValueObjectSP valobj_sp; //ValueObjectList &valobj_list = exe_ctx.frame->GetValueObjectList(); diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index 235f9b3e833..d7931364d7b 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -553,7 +553,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum #endif Address cstr_addr(*this); cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size); - func_sc.DumpStopContext(s, exe_scope, so_addr, true); + func_sc.DumpStopContext(s, exe_scope, so_addr, true, false); if (ReadAddress (exe_scope, cstr_addr, pointer_size, so_addr)) { #if VERBOSE_OUTPUT @@ -636,7 +636,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum if (pointer_sc.function || pointer_sc.symbol) { s->PutCString(": "); - pointer_sc.DumpStopContext(s, exe_scope, so_addr, false); + pointer_sc.DumpStopContext(s, exe_scope, so_addr, false, false); } } } @@ -675,7 +675,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum { // We have a function or a symbol from the same // sections as this address. - sc.DumpStopContext(s, exe_scope, *this, show_module); + sc.DumpStopContext(s, exe_scope, *this, show_module, false); } else { diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 5674dde79f6..49c131a1361 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -238,7 +238,7 @@ Disassembler::Disassemble if (offset != 0) strm.EOL(); - sc.DumpStopContext(&strm, process, addr); + sc.DumpStopContext(&strm, process, addr, true, false); if (sc.comp_unit && sc.line_entry.IsValid()) { diff --git a/lldb/source/Core/VMRange.cpp b/lldb/source/Core/VMRange.cpp index 44b9975a810..0631069bb38 100644 --- a/lldb/source/Core/VMRange.cpp +++ b/lldb/source/Core/VMRange.cpp @@ -40,6 +40,17 @@ VMRange::ContainsRange(const VMRange::collection& coll, const VMRange& range) return false; } +uint32_t +VMRange::FindRangeIndexThatContainsValue (const VMRange::collection& coll, lldb::addr_t value) +{ + ValueInRangeUnaryPredicate in_range_predicate(value); + VMRange::const_iterator begin = coll.begin(); + VMRange::const_iterator end = coll.end(); + VMRange::const_iterator pos = std::find_if (begin, end, in_range_predicate); + if (pos != end) + return std::distance (begin, pos); + return UINT32_MAX; +} void VMRange::Dump(Stream *s, lldb::addr_t offset, uint32_t addr_width) const diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 2ed5127c82e..1f63b95d259 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -791,7 +791,7 @@ DWARFExpression::Evaluate } } if (error_ptr) - error_ptr->SetErrorStringWithFormat("Out of scope.\n", pc); + error_ptr->SetErrorStringWithFormat("Out of scope."); return false; } @@ -995,7 +995,7 @@ DWARFExpression::Evaluate // 1 - uint8_t that specifies the size of the data to dereference. // DESCRIPTION: Behaves like the DW_OP_xderef operation: the entry at // the top of the stack is treated as an address. The second stack - // entry is treated as an “address space identifier” for those + // entry is treated as an "address space identifier" for those // architectures that support multiple address spaces. The top two // stack elements are popped, a data item is retrieved through an // implementation-defined address calculation and pushed as the new diff --git a/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.cpp b/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.cpp index 1b6fa58dcd4..e080bc39479 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindLibUnwind.cpp @@ -65,7 +65,7 @@ UnwindLibUnwind::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc) RegisterContext * UnwindLibUnwind::CreateRegisterContextForFrame (StackFrame *frame) { - uint32_t idx = frame->GetID(); + uint32_t idx = frame->GetConcreteFrameIndex (); const uint32_t frame_count = GetFrameCount(); if (idx < frame_count) return new LibUnwindRegisterContext (m_thread, frame, m_cursors[idx]); diff --git a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp index 1605a75ec7a..29bc89e63fa 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp @@ -66,7 +66,7 @@ UnwindMacOSXFrameBackchain::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr RegisterContext * UnwindMacOSXFrameBackchain::CreateRegisterContextForFrame (StackFrame *frame) { - uint32_t idx = frame->GetID(); + uint32_t idx = frame->GetConcreteFrameIndex (); const uint32_t frame_count = GetFrameCount(); if (idx < frame_count) return new RegisterContextMacOSXFrameBackchain (m_thread, frame, m_cursors[idx]); diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 66cf0b06027..f1847d861da 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -177,11 +177,11 @@ ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame) uint32_t frame_idx = 0; if (frame) - frame_idx = frame->GetID(); + frame_idx = frame->GetFrameIndex (); if (frame_idx == 0) return new GDBRemoteRegisterContext (*this, frame, GetGDBProcess().m_register_info, read_all_registers_at_once); - else if (m_unwinder_ap.get() && frame_idx < m_unwinder_ap->GetFrameCount()) + else if (m_unwinder_ap.get()) return m_unwinder_ap->CreateRegisterContextForFrame (frame); return NULL; } diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp index 28da776d567..8256aa7e199 100644 --- a/lldb/source/Symbol/Block.cpp +++ b/lldb/source/Symbol/Block.cpp @@ -225,6 +225,52 @@ Block::GetParent () const return NULL; } +Block * +Block::GetInlinedParent () const +{ + Block *parent_block = GetParent (); + if (parent_block) + { + if (parent_block->InlinedFunctionInfo()) + return parent_block; + else + return parent_block->GetInlinedParent(); + } + return NULL; +} + + +bool +Block::GetRangeContainingAddress (const Address& addr, AddressRange &range) +{ + SymbolContext sc; + CalculateSymbolContext(&sc); + if (sc.function) + { + const AddressRange &func_range = sc.function->GetAddressRange(); + if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) + { + const addr_t addr_offset = addr.GetOffset(); + const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); + if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) + { + addr_t offset = addr_offset - func_offset; + + uint32_t range_idx = VMRange::FindRangeIndexThatContainsValue (m_ranges, offset); + if (range_idx < m_ranges.size()) + { + range.GetBaseAddress() = func_range.GetBaseAddress(); + range.GetBaseAddress().SetOffset(func_offset + m_ranges[range_idx].GetBaseAddress()); + range.SetByteSize(m_ranges[range_idx].GetByteSize()); + return true; + } + } + } + } + range.Clear(); + return false; +} + void Block::AddRange(addr_t start_offset, addr_t end_offset) { @@ -330,22 +376,32 @@ Block::GetVariableList (bool get_child_variables, bool can_create) } uint32_t -Block::AppendVariables (bool can_create, bool get_parent_variables, VariableList *variable_list) +Block::AppendVariables +( + bool can_create, + bool get_parent_variables, + bool stop_if_block_is_inlined_function, + VariableList *variable_list +) { uint32_t num_variables_added = 0; VariableListSP variable_list_sp(GetVariableList(false, can_create)); + bool is_inlined_function = InlinedFunctionInfo() != NULL; if (variable_list_sp.get()) { num_variables_added = variable_list_sp->GetSize(); variable_list->AddVariables(variable_list_sp.get()); } - + if (get_parent_variables) { + if (stop_if_block_is_inlined_function && is_inlined_function) + return num_variables_added; + Block* parent_block = GetParent(); if (parent_block) - num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, variable_list); + num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, stop_if_block_is_inlined_function, variable_list); } return num_variables_added; } diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index 73a09eae24f..5f9adbbbe12 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -148,6 +148,16 @@ InlineFunctionInfo::DumpStopContext (Stream *s) const s->PutCString (m_name.AsCString()); } + +const ConstString & +InlineFunctionInfo::GetName () const +{ + if (m_mangled) + return m_mangled.GetName(); + return m_name; +} + + Declaration & InlineFunctionInfo::GetCallSite () { diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index 268caf200a8..db0bccb726e 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -114,7 +114,8 @@ SymbolContext::DumpStopContext Stream *s, ExecutionContextScope *exe_scope, const Address &addr, - bool show_module + bool show_module, + bool show_inlined_frames ) const { if (show_module && module_sp) @@ -127,6 +128,30 @@ SymbolContext::DumpStopContext if (function->GetMangled().GetName()) function->GetMangled().GetName().Dump(s); + + if (show_inlined_frames && block) + { + InlineFunctionInfo *inline_info = block->InlinedFunctionInfo(); + if (inline_info == NULL) + { + Block *parent_inline_block = block->GetInlinedParent(); + if (parent_inline_block) + inline_info = parent_inline_block->InlinedFunctionInfo(); + } + + if (inline_info) + { + s->PutCString(" [inlined] "); + inline_info->GetName().Dump(s); + + if (line_entry.IsValid()) + { + s->PutCString(" at "); + line_entry.DumpStopContext(s); + } + return; + } + } const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset(); if (function_offset) s->Printf(" + %llu", function_offset); @@ -237,6 +262,19 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Process * } } +uint32_t +SymbolContext::GetResolvedMask () const +{ + uint32_t resolved_mask = 0; + if (target_sp) resolved_mask |= eSymbolContextTarget; + if (module_sp) resolved_mask |= eSymbolContextModule; + if (comp_unit) resolved_mask |= eSymbolContextCompUnit; + if (function) resolved_mask |= eSymbolContextFunction; + if (block) resolved_mask |= eSymbolContextBlock; + if (line_entry.IsValid()) resolved_mask |= eSymbolContextLineEntry; + if (symbol) resolved_mask |= eSymbolContextSymbol; + return resolved_mask; +} void diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 95299bfce64..1f72c318f9c 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -35,38 +35,118 @@ using namespace lldb_private; #define FRAME_IS_OBSOLETE (GOT_FRAME_BASE << 1) #define RESOLVED_VARIABLES (FRAME_IS_OBSOLETE << 1) -StackFrame::StackFrame (lldb::user_id_t frame_idx, Thread &thread, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr) : - UserID (frame_idx), +StackFrame::StackFrame +( + lldb::user_id_t frame_idx, + lldb::user_id_t concrete_frame_index, + Thread &thread, + lldb::addr_t cfa, + uint32_t inline_height, + lldb::addr_t pc, + const SymbolContext *sc_ptr +) : + m_frame_index (frame_idx), + m_concrete_frame_index (concrete_frame_index), m_thread (thread), - m_reg_context_sp(), - m_id(cfa), - m_pc(NULL, pc), - m_sc(), - m_flags(), - m_frame_base(), - m_frame_base_error(), + m_reg_context_sp (), + m_id (cfa, inline_height), + m_pc (NULL, pc), + m_sc (), + m_flags (), + m_frame_base (), + m_frame_base_error (), m_variable_list_sp (), m_value_object_list () { if (sc_ptr != NULL) + { m_sc = *sc_ptr; + m_flags.Set(m_sc.GetResolvedMask ()); + } } -StackFrame::StackFrame (lldb::user_id_t frame_idx, Thread &thread, RegisterContextSP ®_context_sp, lldb::addr_t cfa, lldb::addr_t pc, const SymbolContext *sc_ptr) : - UserID (frame_idx), +StackFrame::StackFrame +( + lldb::user_id_t frame_idx, + lldb::user_id_t concrete_frame_index, + Thread &thread, + const RegisterContextSP ®_context_sp, + lldb::addr_t cfa, + uint32_t inline_height, + lldb::addr_t pc, + const SymbolContext *sc_ptr +) : + m_frame_index (frame_idx), + m_concrete_frame_index (concrete_frame_index), m_thread (thread), - m_reg_context_sp(reg_context_sp), - m_id(cfa), - m_pc(NULL, pc), - m_sc(), - m_flags(), - m_frame_base(), - m_frame_base_error(), + m_reg_context_sp (reg_context_sp), + m_id (cfa, inline_height), + m_pc (NULL, pc), + m_sc (), + m_flags (), + m_frame_base (), + m_frame_base_error (), m_variable_list_sp (), m_value_object_list () { if (sc_ptr != NULL) + { m_sc = *sc_ptr; + m_flags.Set(m_sc.GetResolvedMask ()); + } + + if (reg_context_sp && !m_sc.target_sp) + { + m_sc.target_sp = reg_context_sp->GetThread().GetProcess().GetTarget().GetSP(); + m_flags.Set (eSymbolContextTarget); + } +} + +StackFrame::StackFrame +( + lldb::user_id_t frame_idx, + lldb::user_id_t concrete_frame_index, + Thread &thread, + const RegisterContextSP ®_context_sp, + lldb::addr_t cfa, + uint32_t inline_height, + const Address& pc_addr, + const SymbolContext *sc_ptr +) : + m_frame_index (frame_idx), + m_concrete_frame_index (concrete_frame_index), + m_thread (thread), + m_reg_context_sp (reg_context_sp), + m_id (cfa, inline_height), + m_pc (pc_addr), + m_sc (), + m_flags (), + m_frame_base (), + m_frame_base_error (), + m_variable_list_sp (), + m_value_object_list () +{ + if (sc_ptr != NULL) + { + m_sc = *sc_ptr; + m_flags.Set(m_sc.GetResolvedMask ()); + } + + if (m_sc.target_sp.get() == NULL && reg_context_sp) + { + m_sc.target_sp = reg_context_sp->GetThread().GetProcess().GetTarget().GetSP(); + m_flags.Set (eSymbolContextTarget); + } + + if (m_sc.module_sp.get() == NULL && pc_addr.GetSection()) + { + Module *pc_module = pc_addr.GetSection()->GetModule(); + if (pc_module) + { + m_sc.module_sp = pc_module->GetSP(); + m_flags.Set (eSymbolContextModule); + } + } } @@ -213,7 +293,7 @@ StackFrame::GetSymbolContext (uint32_t resolve_scope) // instruction following the function call instruction... Address lookup_addr(GetPC()); - if (GetID() > 0 && lookup_addr.IsValid()) + if (m_frame_index > 0 && lookup_addr.IsValid()) { addr_t offset = lookup_addr.GetOffset(); if (offset > 0) @@ -225,11 +305,65 @@ StackFrame::GetSymbolContext (uint32_t resolve_scope) // We have something in our stack frame symbol context, lets check // if we haven't already tried to lookup one of those things. If we // haven't then we will do the query. - if ((m_sc.comp_unit == NULL && (resolve_scope & eSymbolContextCompUnit ) && m_flags.IsClear(eSymbolContextCompUnit )) || - (m_sc.function == NULL && (resolve_scope & eSymbolContextFunction ) && m_flags.IsClear(eSymbolContextFunction )) || - (m_sc.block == NULL && (resolve_scope & eSymbolContextBlock ) && m_flags.IsClear(eSymbolContextBlock )) || - (m_sc.symbol == NULL && (resolve_scope & eSymbolContextSymbol ) && m_flags.IsClear(eSymbolContextSymbol )) || - (!m_sc.line_entry.IsValid() && (resolve_scope & eSymbolContextLineEntry) && m_flags.IsClear(eSymbolContextLineEntry ))) + + uint32_t actual_resolve_scope = 0; + + if (resolve_scope & eSymbolContextCompUnit) + { + if (m_flags.IsClear (eSymbolContextCompUnit)) + { + if (m_sc.comp_unit) + m_flags.Set (eSymbolContextCompUnit); + else + actual_resolve_scope |= eSymbolContextCompUnit; + } + } + + if (resolve_scope & eSymbolContextFunction) + { + if (m_flags.IsClear (eSymbolContextFunction)) + { + if (m_sc.function) + m_flags.Set (eSymbolContextFunction); + else + actual_resolve_scope |= eSymbolContextFunction; + } + } + + if (resolve_scope & eSymbolContextBlock) + { + if (m_flags.IsClear (eSymbolContextBlock)) + { + if (m_sc.block) + m_flags.Set (eSymbolContextBlock); + else + actual_resolve_scope |= eSymbolContextBlock; + } + } + + if (resolve_scope & eSymbolContextSymbol) + { + if (m_flags.IsClear (eSymbolContextSymbol)) + { + if (m_sc.symbol) + m_flags.Set (eSymbolContextSymbol); + else + actual_resolve_scope |= eSymbolContextSymbol; + } + } + + if (resolve_scope & eSymbolContextLineEntry) + { + if (m_flags.IsClear (eSymbolContextLineEntry)) + { + if (m_sc.line_entry.IsValid()) + m_flags.Set (eSymbolContextLineEntry); + else + actual_resolve_scope |= eSymbolContextLineEntry; + } + } + + if (actual_resolve_scope) { // We might be resolving less information than what is already // in our current symbol context so resolve into a temporary @@ -237,7 +371,10 @@ StackFrame::GetSymbolContext (uint32_t resolve_scope) // already found in "m_sc" SymbolContext sc; // Set flags that indicate what we have tried to resolve - const uint32_t resolved = m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, resolve_scope, sc); + const uint32_t resolved = m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc); + // Only replace what we didn't already have as we may have + // information for an inlined function scope that won't match + // what a standard lookup by address would match if (resolved & eSymbolContextCompUnit) m_sc.comp_unit = sc.comp_unit; if (resolved & eSymbolContextFunction) m_sc.function = sc.function; if (resolved & eSymbolContextBlock) m_sc.block = sc.block; @@ -387,10 +524,13 @@ StackFrame::Dump (Stream *strm, bool show_frame_index) return; if (show_frame_index) - strm->Printf("frame #%u: ", GetID()); + strm->Printf("frame #%u: ", m_frame_index); strm->Printf("pc = 0x%0*llx", m_thread.GetProcess().GetAddressByteSize() * 2, GetRegisterContext()->GetPC()); SymbolContext sc (GetSymbolContext(eSymbolContextEverything)); strm->PutCString(", where = "); - sc.DumpStopContext(strm, &m_thread.GetProcess(), GetPC()); + // TODO: need to get the + const bool show_module = true; + const bool show_inline = true; + sc.DumpStopContext(strm, &m_thread.GetProcess(), GetPC(), show_module, show_inline); } diff --git a/lldb/source/Target/StackID.cpp b/lldb/source/Target/StackID.cpp index 6f903aed6da..78543fa41f2 100644 --- a/lldb/source/Target/StackID.cpp +++ b/lldb/source/Target/StackID.cpp @@ -21,22 +21,25 @@ using namespace lldb_private; //---------------------------------------------------------------------- StackID::StackID() : m_start_address(), - m_cfa() + m_cfa (0), + m_inline_height (0) { } //---------------------------------------------------------------------- // StackID constructor with args //---------------------------------------------------------------------- -StackID::StackID (const Address& start_address, lldb::addr_t cfa) : +StackID::StackID (const Address& start_address, lldb::addr_t cfa, uint32_t inline_id) : m_start_address (start_address), - m_cfa (cfa) + m_cfa (cfa), + m_inline_height (inline_id) { } -StackID::StackID (lldb::addr_t cfa) : +StackID::StackID (lldb::addr_t cfa, uint32_t inline_id) : m_start_address (), - m_cfa (cfa) + m_cfa (cfa), + m_inline_height (inline_id) { } @@ -45,7 +48,8 @@ StackID::StackID (lldb::addr_t cfa) : //---------------------------------------------------------------------- StackID::StackID(const StackID& rhs) : m_start_address (rhs.m_start_address), - m_cfa (rhs.m_cfa) + m_cfa (rhs.m_cfa), + m_inline_height (rhs.m_inline_height) { } @@ -59,6 +63,7 @@ StackID::operator=(const StackID& rhs) { m_start_address = rhs.m_start_address; m_cfa = rhs.m_cfa; + m_inline_height = rhs.m_inline_height; } return *this; } @@ -70,36 +75,20 @@ StackID::~StackID() { } - -const Address& -StackID::GetStartAddress() const -{ - return m_start_address; -} - -void -StackID::SetStartAddress(const Address& start_address) -{ - m_start_address = start_address; -} - -lldb::addr_t -StackID::GetCallFrameAddress() const -{ - return m_cfa; -} - - bool lldb_private::operator== (const StackID& lhs, const StackID& rhs) { - return lhs.GetCallFrameAddress() == rhs.GetCallFrameAddress() && lhs.GetStartAddress() == rhs.GetStartAddress(); + return lhs.GetCallFrameAddress() == rhs.GetCallFrameAddress() && + lhs.GetInlineHeight() == rhs.GetInlineHeight() && + lhs.GetStartAddress() == rhs.GetStartAddress(); } bool lldb_private::operator!= (const StackID& lhs, const StackID& rhs) { - return lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress() || lhs.GetStartAddress() != rhs.GetStartAddress(); + return lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress() || + lhs.GetInlineHeight() != rhs.GetInlineHeight() || + lhs.GetStartAddress() != rhs.GetStartAddress(); } bool diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index c8ed3c568c4..3d206ea5d33 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -156,16 +156,22 @@ Target::CreateBreakpoint (const FileSpec *containingModule, const FileSpec &file BreakpointSP -Target::CreateBreakpoint (lldb::addr_t load_addr, bool internal) +Target::CreateBreakpoint (lldb::addr_t addr, bool internal) { - BreakpointSP bp_sp; Address so_addr; // Attempt to resolve our load address if possible, though it is ok if // it doesn't resolve to section/offset. Process *process = GetProcessSP().get(); - if (process && process->ResolveLoadAddress(load_addr, so_addr)) - bp_sp = CreateBreakpoint(so_addr, internal); + // Try and resolve as a load address if possible + if (process) + process->ResolveLoadAddress(addr, so_addr); + if (!so_addr.IsValid()) + { + // The address didn't resolve, so just set this as an absolute address + so_addr.SetOffset (addr); + } + BreakpointSP bp_sp (CreateBreakpoint(so_addr, internal)); return bp_sp; } diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index efbcad7fa4d..0a6cc828329 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -49,8 +49,10 @@ Thread::Thread (Process &process, lldb::tid_t tid) : m_immediate_plan_stack(), m_completed_plan_stack(), m_state_mutex (Mutex::eMutexTypeRecursive), - m_frames (), - m_current_frame_idx (0), + m_concrete_frames (), + m_inlined_frames (), + m_inlined_frame_info (), + m_show_inlined_frames (true), m_resume_signal (LLDB_INVALID_SIGNAL_NUMBER), m_resume_state (eStateRunning), m_unwinder_ap () @@ -798,7 +800,69 @@ Thread::GetStackFrameCount() { Unwind *unwinder = GetUnwinder (); if (unwinder) - return unwinder->GetFrameCount(); + { + if (m_show_inlined_frames) + { + if (m_inlined_frame_info.empty()) + { + // If we are going to show inlined stack frames as actual frames, + // we need to calculate all concrete frames first, then iterate + // through all of them and count up how many inlined functions are + // in each frame. We can then fill in m_inlined_frame_info with + // the concrete frame index and inlined depth + const uint32_t concrete_frame_count = unwinder->GetFrameCount(); + + addr_t pc, cfa; + InlinedFrameInfo inlined_frame_info; + + StackFrameSP frame_sp; + for (uint32_t idx=0; idx<concrete_frame_count; ++idx) + { + if (idx == 0) + { + GetRegisterContext(); + assert (m_reg_context_sp.get()); + frame_sp.reset (new StackFrame (0, 0, *this, m_reg_context_sp, m_reg_context_sp->GetSP(), 0, m_reg_context_sp->GetPC(), NULL)); + } + else + { + const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc); + assert (success); + frame_sp.reset (new StackFrame (m_inlined_frame_info.size(), idx, *this, cfa, 0, pc, NULL)); + } + m_concrete_frames.SetFrameAtIndex(idx, frame_sp); + Block *block = frame_sp->GetSymbolContext (eSymbolContextBlock).block; + + inlined_frame_info.concrete_frame_index = idx; + inlined_frame_info.inline_height = 0; + inlined_frame_info.block = block; + m_inlined_frame_info.push_back (inlined_frame_info); + + if (block) + { + Block *inlined_block; + if (block->InlinedFunctionInfo()) + inlined_block = block; + else + inlined_block = block->GetInlinedParent (); + + while (inlined_block) + { + inlined_frame_info.block = inlined_block; + inlined_frame_info.inline_height++; + m_inlined_frame_info.push_back (inlined_frame_info); + inlined_block = inlined_block->GetInlinedParent (); + } + } + } + } + return m_inlined_frame_info.size(); + } + else + { + return unwinder->GetFrameCount(); + } + } return 0; } @@ -806,7 +870,12 @@ lldb::StackFrameSP Thread::GetStackFrameAtIndex (uint32_t idx) { - StackFrameSP frame_sp (m_frames.GetFrameAtIndex(idx)); + StackFrameSP frame_sp; + + if (m_show_inlined_frames) + frame_sp = m_inlined_frames.GetFrameAtIndex(idx); + else + frame_sp = m_concrete_frames.GetFrameAtIndex(idx); if (frame_sp.get()) return frame_sp; @@ -827,38 +896,95 @@ Thread::GetStackFrameAtIndex (uint32_t idx) // context with the stack frame at index zero. GetRegisterContext(); assert (m_reg_context_sp.get()); - frame_sp.reset (new StackFrame (idx, *this, m_reg_context_sp, m_reg_context_sp->GetSP(), m_reg_context_sp->GetPC())); + frame_sp.reset (new StackFrame (0, 0, *this, m_reg_context_sp, m_reg_context_sp->GetSP(), 0, m_reg_context_sp->GetPC(), NULL)); } else if (idx < GetStackFrameCount()) { - Unwind *unwinder = GetUnwinder (); - if (unwinder) + if (m_show_inlined_frames) { - addr_t pc, cfa; - if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) - frame_sp.reset (new StackFrame (idx, *this, cfa, pc)); + if (m_inlined_frame_info[idx].inline_height == 0) + { + // Same as the concrete stack frame if block is NULL + frame_sp = m_concrete_frames.GetFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index); + } + else + { + // We have blocks that were above an inlined function. Inlined + // functions are represented as blocks with non-NULL inline + // function info. Here we must reconstruct a frame by looking + // at the block + StackFrameSP previous_frame_sp (GetStackFrameAtIndex (idx-1)); + + SymbolContext inline_sc; + + Block *inlined_parent_block = m_inlined_frame_info[idx].block->GetInlinedParent(); + + if (inlined_parent_block) + inlined_parent_block->CalculateSymbolContext (&inline_sc); + else + { + Block *parent_block = m_inlined_frame_info[idx].block->GetParent(); + parent_block->CalculateSymbolContext(&inline_sc); + } + + InlineFunctionInfo* inline_info = m_inlined_frame_info[idx].block->InlinedFunctionInfo(); + assert (inline_info); + inline_sc.line_entry.range.GetBaseAddress() = previous_frame_sp->GetPC(); + inline_sc.line_entry.file = inline_info->GetCallSite().GetFile(); + inline_sc.line_entry.line = inline_info->GetCallSite().GetLine(); + inline_sc.line_entry.column = inline_info->GetCallSite().GetColumn(); + + StackFrameSP concrete_frame_sp (m_concrete_frames.GetFrameAtIndex (m_inlined_frame_info[idx].concrete_frame_index)); + assert (previous_frame_sp.get()); + AddressRange range; + m_inlined_frame_info[idx].block->GetRangeContainingAddress (previous_frame_sp->GetPC(), range); + + frame_sp.reset (new StackFrame (idx, + m_inlined_frame_info[idx].concrete_frame_index, + *this, + concrete_frame_sp->GetRegisterContextSP (), + concrete_frame_sp->GetStackID().GetCallFrameAddress(), // CFA + m_inlined_frame_info[idx].inline_height, // Inline height + range.GetBaseAddress(), + &inline_sc)); // The symbol context for this inline frame + + } + + } + else + { + Unwind *unwinder = GetUnwinder (); + if (unwinder) + { + addr_t pc, cfa; + if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) + frame_sp.reset (new StackFrame (idx, idx, *this, cfa, 0, pc, NULL)); + } } } - m_frames.SetFrameAtIndex(idx, frame_sp); + if (m_show_inlined_frames) + m_inlined_frames.SetFrameAtIndex(idx, frame_sp); + else + m_concrete_frames.SetFrameAtIndex(idx, frame_sp); return frame_sp; } lldb::StackFrameSP Thread::GetCurrentFrame () { - return GetStackFrameAtIndex (m_frames.GetCurrentFrameIndex()); + return GetStackFrameAtIndex (m_concrete_frames.GetCurrentFrameIndex()); } uint32_t Thread::SetCurrentFrame (lldb_private::StackFrame *frame) { - return m_frames.SetCurrentFrame(frame); + return m_concrete_frames.SetCurrentFrame(frame); } void -Thread::SetCurrentFrameByIndex (uint32_t frame_idx) +Thread::SetCurrentFrameByIndex (uint32_t idx) { - m_frames.SetCurrentFrameByIndex(frame_idx); + m_concrete_frames.SetCurrentFrameByIndex(idx); } void @@ -868,14 +994,14 @@ Thread::DumpInfo bool show_stop_reason, bool show_name, bool show_queue, - uint32_t frame_idx + uint32_t idx ) { strm.Printf("thread #%u: tid = 0x%4.4x", GetIndexID(), GetID()); - if (frame_idx != LLDB_INVALID_INDEX32) + if (idx != LLDB_INVALID_INDEX32) { - StackFrameSP frame_sp(GetStackFrameAtIndex (frame_idx)); + StackFrameSP frame_sp(GetStackFrameAtIndex (idx)); if (frame_sp) { strm.PutCString(", "); |