33 return sc.
module_sp->GetFileSpec().GetFilename().AsCString();
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) {
384 m_j.attribute(
"mnemonic",
388 instruction->GetControlFlowKind(&exe_ctx);
389 m_j.attribute(
"controlFlowKind",
392 instruction_control_flow_kind)));
400 item.
symbol_info->sc.line_entry.GetFile().GetPath().c_str()));
409 m_j.attribute(
"id", item.
id);
412 ? std::optional<std::string>(
418 }
else if (item.
error) {
419 m_j.attribute(
"error", *item.
error);
432static std::unique_ptr<TraceDumper::OutputWriter>
435 return std::unique_ptr<TraceDumper::OutputWriter>(
438 return std::unique_ptr<TraceDumper::OutputWriter>(
457 m_cursor_sp->Seek((m_options.forwards ? 1 : -1) * *m_options.skip,
458 lldb::eTraceCursorSeekTypeCurrent);
480 return prev_symbol_context;
489static std::tuple<DisassemblerSP, InstructionSP>
496 .GetInstructionAtAddress(symbol_info.
address))
497 return std::make_tuple(prev_symbol_info.
disassembler, instruction);
504 disassembler->GetInstructionList().GetInstructionAtAddress(
506 return std::make_tuple(disassembler, instruction);
516 nullptr,
nullptr,
nullptr, target, range);
517 return std::make_tuple(
519 disassembler ? disassembler->GetInstructionList().GetInstructionAtAddress(
541 std::optional<lldb::user_id_t> last_id;
544 thread_sp->GetProcess()->GetTarget().CalculateExecutionContext(exe_ctx);
546 for (
size_t insn_seen = 0; insn_seen < count &&
m_cursor_sp->HasValue();
554 switch (*item.
event) {
581 prev_symbol_info = symbol_info;
609 std::function<
void(
const FunctionCall &function_call)> callback)
const {
623 m_nested_call = std::make_unique<FunctionCall>(cursor_sp, symbol_info);
664const std::deque<TraceDumper::FunctionCall::TracedSegment> &
674const std::optional<TraceDumper::FunctionCall::UntracedPrefixSegment> &
715 std::vector<TraceDumper::FunctionCallUP> &roots) {
736 std::make_unique<TraceDumper::FunctionCall>(cursor_sp, symbol_info);
738 new_root->SetUntracedPrefixSegment(std::move(roots.back()));
741 roots.emplace_back(std::move(new_root));
742 return *roots.back();
775 std::vector<TraceDumper::FunctionCallUP> &roots) {
776 if (!last_function_call || last_function_call->
IsError()) {
779 std::make_unique<TraceDumper::FunctionCall>(cursor_sp, symbol_info));
780 return *roots.back();
785 eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol,
792 cursor_sp, symbol_info);
801 return *last_function_call;
809 insn ? insn->GetControlFlowKind(&exe_ctx)
817 cursor_sp, symbol_info);
824 *last_function_call, symbol_info, cursor_sp, roots);
832 if (prev_symbol_info.
sc.
block &&
835 *last_function_call, symbol_info, cursor_sp, roots);
841 cursor_sp, symbol_info);
862 std::vector<TraceDumper::FunctionCallUP> &roots) {
863 if (last_function_call && last_function_call->
IsError()) {
866 return *last_function_call;
868 roots.emplace_back(std::make_unique<TraceDumper::FunctionCall>(
870 return *roots.back();
874static std::vector<TraceDumper::FunctionCallUP>
878 std::vector<TraceDumper::FunctionCallUP> roots;
883 for (; cursor_sp->HasValue(); cursor_sp->Next()) {
884 if (cursor_sp->IsError()) {
887 prev_symbol_info = {};
888 }
else if (cursor_sp->IsInstruction()) {
890 exe_ctx, cursor_sp->GetLoadAddress(), prev_symbol_info);
893 exe_ctx, last_function_call, prev_symbol_info, symbol_info, cursor_sp,
895 prev_symbol_info = symbol_info;
900 last_function_call =
nullptr;
901 prev_symbol_info = {};
911 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.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
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