33 return sc.
module_sp->GetFileSpec().GetFilename().AsCString(
nullptr);
77 bool check_source_line_info =
true) {
93 Block *inline_block_a =
98 if (inline_block_a != inline_block_b)
102 if (!check_source_line_info)
107 if (curr_line_valid && prev_line_valid)
110 return curr_line_valid == prev_line_valid;
117 m_s.Format(
"thread #{0}: tid = {1}\n", thread.GetIndexID(), thread.GetID());
123 const std::vector<TraceDumper::FunctionCallUP> &forest)
override {
124 for (
size_t i = 0; i < forest.size(); i++) {
125 m_s.Format(
"\n[call tree #{0}]\n", i);
140 m_s.Format(
"{0}`(none)", module_name);
154 m_s <<
" ...missing instructions\n";
156 m_s.Format(
" {0}: ", item.
id);
162 m_s <<
"[unavailable]";
167 switch (*item.
event) {
169 m_s.Format(
" [new CPU={0}]",
170 item.
cpu_id ? std::to_string(*item.
cpu_id) :
"unavailable");
183 }
else if (item.
error) {
207 if (
segment.GetOwningCall().IsError()) {
208 m_s <<
"<tracing errors>";
214 &
m_s,
segment.GetFirstInstructionSymbolInfo().exe_ctx.GetTargetPtr(),
215 segment.GetFirstInstructionSymbolInfo().address,
227 &
m_s,
segment.GetFirstInstructionSymbolInfo().exe_ctx.GetTargetPtr(),
228 segment.GetLastInstructionSymbolInfo().address,
238 m_s <<
"tracing error";
246 m_s << module_name <<
"`(none)";
266 m_s.Format(
" [{0}, {1}]\n",
segment.GetFirstInstructionID(),
267 segment.GetLastInstructionID());
313 options.pretty_print_json ? 2 : 0) {
320 const std::vector<TraceDumper::FunctionCallUP> &forest)
override {
321 for (
size_t i = 0; i < forest.size(); i++) {
328 m_j.attributeObject(
"untracedPrefixSegment", [&] {
329 m_j.attributeObject(
"nestedCall", [&] {
337 m_j.attributeArray(
"tracedSegments", [&] {
341 m_j.attribute(
"firstInstructionId",
342 std::to_string(
segment.GetFirstInstructionID()));
343 m_j.attribute(
"lastInstructionId",
344 std::to_string(
segment.GetLastInstructionID()));
358 switch (*item.
event) {
381 item.
symbol_info->sc.GetFunctionName().AsCString(
nullptr)));
385 m_j.attribute(
"mnemonic",
389 instruction->GetControlFlowKind(&exe_ctx);
390 m_j.attribute(
"controlFlowKind",
393 instruction_control_flow_kind)));
401 item.
symbol_info->sc.line_entry.GetFile().GetPath().c_str()));
410 m_j.attribute(
"id", item.
id);
413 ? std::optional<std::string>(
419 }
else if (item.
error) {
420 m_j.attribute(
"error", *item.
error);
433static std::unique_ptr<TraceDumper::OutputWriter>
436 return std::unique_ptr<TraceDumper::OutputWriter>(
439 return std::unique_ptr<TraceDumper::OutputWriter>(
458 m_cursor_sp->Seek((m_options.forwards ? 1 : -1) * *m_options.skip,
459 lldb::eTraceCursorSeekTypeCurrent);
481 return prev_symbol_context;
490static std::tuple<DisassemblerSP, InstructionSP>
497 .GetInstructionAtAddress(symbol_info.
address))
498 return std::make_tuple(prev_symbol_info.
disassembler, instruction);
505 disassembler->GetInstructionList().GetInstructionAtAddress(
507 return std::make_tuple(disassembler, instruction);
517 nullptr,
nullptr,
nullptr, target, range);
518 return std::make_tuple(
520 disassembler ? disassembler->GetInstructionList().GetInstructionAtAddress(
542 std::optional<lldb::user_id_t> last_id;
545 thread_sp->GetProcess()->GetTarget().CalculateExecutionContext(exe_ctx);
547 for (
size_t insn_seen = 0; insn_seen < count &&
m_cursor_sp->HasValue();
555 switch (*item.
event) {
582 prev_symbol_info = symbol_info;
610 std::function<
void(
const FunctionCall &function_call)> callback)
const {
624 m_nested_call = std::make_unique<FunctionCall>(cursor_sp, symbol_info);
665const std::deque<TraceDumper::FunctionCall::TracedSegment> &
675const std::optional<TraceDumper::FunctionCall::UntracedPrefixSegment> &
716 std::vector<TraceDumper::FunctionCallUP> &roots) {
737 std::make_unique<TraceDumper::FunctionCall>(cursor_sp, symbol_info);
739 new_root->SetUntracedPrefixSegment(std::move(roots.back()));
742 roots.emplace_back(std::move(new_root));
743 return *roots.back();
776 std::vector<TraceDumper::FunctionCallUP> &roots) {
777 if (!last_function_call || last_function_call->
IsError()) {
780 std::make_unique<TraceDumper::FunctionCall>(cursor_sp, symbol_info));
781 return *roots.back();
786 eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol,
793 cursor_sp, symbol_info);
802 return *last_function_call;
810 insn ? insn->GetControlFlowKind(&exe_ctx)
818 cursor_sp, symbol_info);
825 *last_function_call, symbol_info, cursor_sp, roots);
833 if (prev_symbol_info.
sc.
block &&
836 *last_function_call, symbol_info, cursor_sp, roots);
842 cursor_sp, symbol_info);
863 std::vector<TraceDumper::FunctionCallUP> &roots) {
864 if (last_function_call && last_function_call->
IsError()) {
867 return *last_function_call;
869 roots.emplace_back(std::make_unique<TraceDumper::FunctionCall>(
871 return *roots.back();
875static std::vector<TraceDumper::FunctionCallUP>
879 std::vector<TraceDumper::FunctionCallUP> roots;
884 for (; cursor_sp->HasValue(); cursor_sp->Next()) {
885 if (cursor_sp->IsError()) {
888 prev_symbol_info = {};
889 }
else if (cursor_sp->IsInstruction()) {
891 exe_ctx, cursor_sp->GetLoadAddress(), prev_symbol_info);
894 exe_ctx, last_function_call, prev_symbol_info, symbol_info, cursor_sp,
896 prev_symbol_info = symbol_info;
901 last_function_call =
nullptr;
902 prev_symbol_info = {};
912 thread_sp->GetProcess()->GetTarget().CalculateExecutionContext(exe_ctx);
static std::vector< TraceDumper::FunctionCallUP > CreateFunctionCallForest(TraceCursorSP &cursor_sp, const ExecutionContext &exe_ctx)
static bool IsLineEntryValid(const LineEntry &line_entry)
static bool IsSameInstructionSymbolContext(const TraceDumper::SymbolInfo &prev_insn, const TraceDumper::SymbolInfo &insn, bool check_source_line_info=true)
Compare the symbol contexts of the provided SymbolInfo objects.
static std::unique_ptr< TraceDumper::OutputWriter > CreateWriter(Stream &s, const TraceDumperOptions &options, Thread &thread)
static const char * GetModuleName(const SymbolContext &sc)
static TraceDumper::FunctionCall & AppendInstructionToFunctionCallForest(const ExecutionContext &exe_ctx, TraceDumper::FunctionCall *last_function_call, const TraceDumper::SymbolInfo &prev_symbol_info, const TraceDumper::SymbolInfo &symbol_info, const TraceCursorSP &cursor_sp, std::vector< TraceDumper::FunctionCallUP > &roots)
Append an instruction to a function call forest.
static TraceDumper::SymbolInfo CalculateSymbolInfo(const ExecutionContext &exe_ctx, lldb::addr_t load_address, const TraceDumper::SymbolInfo &prev_symbol_info)
static std::tuple< DisassemblerSP, InstructionSP > CalculateDisass(const TraceDumper::SymbolInfo &symbol_info, const TraceDumper::SymbolInfo &prev_symbol_info, const ExecutionContext &exe_ctx)
Find the disassembler for the given address reusing the previous instruction's disassembler when poss...
static TraceDumper::FunctionCall & AppendReturnedInstructionToFunctionCallForest(TraceDumper::FunctionCall &last_function_call, const TraceDumper::SymbolInfo &symbol_info, const TraceCursorSP &cursor_sp, std::vector< TraceDumper::FunctionCallUP > &roots)
Given an instruction that happens after a return, find the ancestor function call that owns it.
static bool FileLineAndColumnMatches(const LineEntry &a, const LineEntry &b)
static SymbolContext CalculateSymbolContext(const Address &address, const SymbolContext &prev_symbol_context)
Find the symbol context for the given address reusing the previous instruction's symbol context when ...
static std::optional< const char * > ToOptionalString(const char *s)
TraceDumper::FunctionCall & AppendErrorToFunctionCallForest(TraceDumper::FunctionCall *last_function_call, TraceCursorSP &cursor_sp, std::vector< TraceDumper::FunctionCallUP > &roots)
Append an error to a function call forest.
void FunctionCallForest(const std::vector< TraceDumper::FunctionCallUP > &forest) override
Dump a function call forest.
void TraceItem(const TraceDumper::TraceItem &item) override
Dump a trace item (instruction, error or event).
bool m_was_prev_instruction_an_error
TraceDumperOptions m_options
OutputWriterCLI(Stream &s, const TraceDumperOptions &options, Thread &thread)
void DumpSegmentContext(const TraceDumper::FunctionCall::TracedSegment &segment)
void DumpFunctionCallTree(const TraceDumper::FunctionCall &function_call)
void NoMoreData() override
Notify this writer that the cursor ran out of data.
void DumpUntracedContext(const TraceDumper::FunctionCall &function_call)
void DumpInstruction(const TraceDumper::TraceItem &item)
void DumpEvent(const TraceDumper::TraceItem &item)
void TraceItem(const TraceDumper::TraceItem &item) override
Dump a trace item (instruction, error or event).
OutputWriterJSON(Stream &s, const TraceDumperOptions &options)
void DumpFunctionCallTree(const TraceDumper::FunctionCall &function_call)
void FunctionCallForest(const std::vector< TraceDumper::FunctionCallUP > &forest) override
Dump a function call forest.
TraceDumperOptions m_options
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
bool Contains(const Address &so_addr) const
Check if a section offset address is contained in this range.
A section + offset based address class.
bool SetLoadAddress(lldb::addr_t load_addr, Target *target, bool allow_section_end=false)
Set the address to represent load_addr.
uint32_t CalculateSymbolContext(SymbolContext *sc, lldb::SymbolContextItem resolve_scope=lldb::eSymbolContextEverything) const
Reconstruct a symbol context from an address.
An architecture specification class.
uint32_t GetMaximumOpcodeByteSize() const
A class that describes a single lexical block.
Block * GetContainingInlinedBlock()
Get the inlined block that contains this block.
static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch, const char *plugin_name, const char *flavor, const char *cpu, const char *features, Target &target, llvm::ArrayRef< AddressRange > disasm_ranges, bool force_live_memory=false)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Target * GetTargetPtr() const
Returns a pointer to the target object.
Target & GetTargetRef() const
Returns a reference to the target object.
lldb::DisassemblerSP GetInstructions(const ExecutionContext &exe_ctx, const char *flavor, bool force_live_memory=false)
static const char * GetNameForInstructionControlFlowKind(lldb::InstructionControlFlowKind instruction_control_flow_kind)
A stream class that can stream formatted output to a file.
Defines a symbol context baton that can be handed other debug core functions.
Function * function
The Function for a given query.
ConstString GetFunctionName(Mangled::NamePreference preference=Mangled::ePreferDemangled) const
Find a name of the innermost function for the symbol context.
Block * block
The Block for a given query.
lldb::ModuleSP module_sp
The Module for a given query.
bool DumpStopContext(Stream *s, ExecutionContextScope *exe_scope, const Address &so_addr, bool show_fullpaths, bool show_module, bool show_inlined_frames, bool show_function_arguments, bool show_function_name, bool show_function_display_name=false, std::optional< Stream::HighlightSettings > settings=std::nullopt) const
Dump the stop context in this object to a Stream.
bool GetAddressRange(uint32_t scope, uint32_t range_idx, bool use_inline_block_range, AddressRange &range) const
Get the address range contained within a symbol context.
Symbol * symbol
The Symbol for a given query.
LineEntry line_entry
The LineEntry for a given query.
const ArchSpec & GetArchitecture() const
static const char * EventKindToString(lldb::TraceEvent event_kind)
FunctionCall & CreateNestedCall(const lldb::TraceCursorSP &cursor_sp, const SymbolInfo &symbol_info)
Create a nested call at the end of this segment.
const SymbolInfo & GetFirstInstructionSymbolInfo() const
SymbolInfo m_first_symbol_info
The symbol information of the delimiting instructions.
const SymbolInfo & GetLastInstructionSymbolInfo() const
FunctionCallUP m_nested_call
An optional nested call starting at the end of this segment.
FunctionCall & m_owning_call
void AppendInsn(const lldb::TraceCursorSP &cursor_sp, const SymbolInfo &symbol_info)
Append a new instruction to this segment.
const FunctionCall & GetOwningCall() const
SymbolInfo m_last_symbol_info
lldb::user_id_t GetFirstInstructionID() const
lldb::user_id_t GetLastInstructionID() const
void IfNestedCall(std::function< void(const FunctionCall &function_call)> callback) const
Executed the given callback if there's a nested call at the end of this segment.
lldb::user_id_t m_last_insn_id
lldb::user_id_t m_first_insn_id
Delimiting instruction IDs taken chronologically.
const FunctionCall & GetNestedCall() const
FunctionCallUP m_nested_call
const std::deque< TracedSegment > & GetTracedSegments() const
void SetParentCall(FunctionCall &parent_call)
FunctionCall * m_parent_call
The parent call, which might be null.
void SetUntracedPrefixSegment(FunctionCallUP &&nested_call)
Create an untraced segment for this call that jumps to the provided nested call.
FunctionCall * GetParentCall() const
std::optional< UntracedPrefixSegment > m_untraced_prefix_segment
An optional untraced segment that precedes all the traced segments.
const SymbolInfo & GetSymbolInfo() const
TracedSegment & GetLastTracedSegment()
std::deque< TracedSegment > m_traced_segments
The traced segments in order.
FunctionCall(const lldb::TraceCursorSP &cursor_sp, const SymbolInfo &symbol_info)
Create a new function call given an instruction.
bool m_is_error
Whether this call represents a list of consecutive errors.
const std::optional< UntracedPrefixSegment > & GetUntracedPrefixSegment() const
void AppendSegment(const lldb::TraceCursorSP &cursor_sp, const SymbolInfo &symbol_info)
Append a new traced segment to this function call.
Interface used to abstract away the format in which the instruction information will be dumped.
std::optional< lldb::user_id_t > DumpInstructions(size_t count)
Dump count instructions of the thread trace starting at the current cursor position.
TraceDumper(lldb::TraceCursorSP cursor_sp, Stream &s, const TraceDumperOptions &options)
Create a instruction dumper for the cursor.
std::unique_ptr< FunctionCall > FunctionCallUP
lldb::TraceCursorSP m_cursor_sp
std::unique_ptr< OutputWriter > m_writer_up
TraceDumperOptions m_options
TraceItem CreatRawTraceItem()
Create a trace item for the current position without symbol information.
void DumpFunctionCalls()
Dump all function calls forwards chronologically and hierarchically.
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::Thread > ThreadSP
@ eTraceEventSyncPoint
The underlying tracing technology emitted a synchronization event used by trace processors.
@ eTraceEventCPUChanged
Event due to CPU change for a thread.
@ eTraceEventHWClockTick
Event due to a CPU HW clock tick.
@ eTraceEventDisabledHW
Tracing was disable for some time due to a hardware trigger.
@ eTraceEventDisabledSW
Tracing was disabled for some time due to a software trigger.
std::shared_ptr< lldb_private::Instruction > InstructionSP
std::shared_ptr< lldb_private::Disassembler > DisassemblerSP
InstructionControlFlowKind
Architecture-agnostic categorization of instructions for traversing the control flow of a trace.
@ eInstructionControlFlowKindReturn
The instruction is a near (function) return.
@ eInstructionControlFlowKindOther
The instruction is something not listed below, i.e.
@ eInstructionControlFlowKindFarCall
The instruction is a call-like far transfer.
@ eInstructionControlFlowKindFarReturn
The instruction is a return-like far transfer.
@ eInstructionControlFlowKindCall
The instruction is a near (function) call.
@ eTraceCursorSeekTypeEnd
The end of the trace, i.e the most recent item.
@ eTraceCursorSeekTypeBeginning
The beginning of the trace, i.e the oldest item.
std::shared_ptr< lldb_private::TraceCursor > TraceCursorSP
A line table entry class.
uint16_t column
The column number of the source line, or zero if there is no column information.
bool IsValid() const
Check if a line entry object is valid.
uint32_t line
The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line number information.
const FileSpec & GetFile() const
Helper to access the file.
Class that holds the configuration used by TraceDumper for traversing and dumping instructions.
bool json
Dump in json format.
Helper struct that holds symbol, disassembly and address information of an instruction.
lldb_private::ExecutionContext exe_ctx
lldb::InstructionSP instruction
lldb::DisassemblerSP disassembler
Helper struct that holds all the information we know about a trace item.
std::optional< uint64_t > hw_clock
std::optional< SymbolInfo > symbol_info
std::optional< std::string > sync_point_metadata
std::optional< lldb::cpu_id_t > cpu_id
lldb::addr_t load_address
std::optional< llvm::StringRef > error
std::optional< SymbolInfo > prev_symbol_info
std::optional< lldb::TraceEvent > event
std::optional< double > timestamp