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;
123 const std::vector<TraceDumper::FunctionCallUP> &forest)
override {
124 for (
size_t i = 0; i < forest.size(); i++) {
154 m_s <<
" ...missing instructions\n";
160 ? formatv(
"{0:3} ns", *item.
timestamp).str()
166 switch (*item.
event) {
169 item.
cpu_id ? std::to_string(*item.
cpu_id) :
"unavailable");
182 }
else if (item.
error) {
207 m_s <<
"<tracing errors>";
237 m_s <<
"tracing error";
245 m_s << module_name <<
"`(none)";
265 m_s.
Format(
" [{0}, {1}]\n", segment.GetFirstInstructionID(),
266 segment.GetLastInstructionID());
312 options.pretty_print_json ? 2 : 0) {
319 const std::vector<TraceDumper::FunctionCallUP> &forest)
override {
320 for (
size_t i = 0; i < forest.size(); i++) {
327 m_j.attributeObject(
"untracedPrefixSegment", [&] {
328 m_j.attributeObject(
"nestedCall", [&] {
336 m_j.attributeArray(
"tracedSegments", [&] {
340 m_j.attribute(
"firstInstructionId",
341 std::to_string(segment.GetFirstInstructionID()));
342 m_j.attribute(
"lastInstructionId",
343 std::to_string(segment.GetLastInstructionID()));
344 segment.IfNestedCall(
357 switch (*item.
event) {
383 m_j.attribute(
"mnemonic",
387 instruction->GetControlFlowKind(&exe_ctx);
388 m_j.attribute(
"controlFlowKind",
391 instruction_control_flow_kind)));
399 item.
symbol_info->sc.line_entry.GetFile().GetPath().c_str()));
408 m_j.attribute(
"id", item.
id);
411 ? std::optional<std::string>(
417 }
else if (item.
error) {
418 m_j.attribute(
"error", *item.error);
420 DumpInstruction(item);
431static std::unique_ptr<TraceDumper::OutputWriter>
434 return std::unique_ptr<TraceDumper::OutputWriter>(
437 return std::unique_ptr<TraceDumper::OutputWriter>(
443 : m_cursor_sp(std::move(cursor_sp)), m_options(options),
445 s, m_options, *m_cursor_sp->GetExecutionContextRef().GetThreadSP())) {
479 return prev_symbol_context;
488static std::tuple<DisassemblerSP, InstructionSP>
495 .GetInstructionAtAddress(symbol_info.
address))
496 return std::make_tuple(prev_symbol_info.
disassembler, instruction);
503 disassembler->GetInstructionList().GetInstructionAtAddress(
505 return std::make_tuple(disassembler, instruction);
515 nullptr,
nullptr,
nullptr, target, range);
516 return std::make_tuple(
518 disassembler ? disassembler->GetInstructionList().GetInstructionAtAddress(
540 std::optional<lldb::user_id_t> last_id;
543 thread_sp->GetProcess()->GetTarget().CalculateExecutionContext(exe_ctx);
545 for (
size_t insn_seen = 0; insn_seen < count &&
m_cursor_sp->HasValue();
553 switch (*item.
event) {
580 prev_symbol_info = symbol_info;
599 return m_first_insn_id;
604 return m_last_insn_id;
608 std::function<
void(
const FunctionCall &function_call)> callback)
const {
610 callback(*m_nested_call);
615 return m_owning_call;
622 m_nested_call = std::make_unique<FunctionCall>(cursor_sp, symbol_info);
623 m_nested_call->SetParentCall(m_owning_call);
624 return *m_nested_call;
630 return m_first_symbol_info;
635 return m_last_symbol_info;
640 return *m_nested_call;
663const std::deque<TraceDumper::FunctionCall::TracedSegment> &
673const std::optional<TraceDumper::FunctionCall::UntracedPrefixSegment> &
714 std::vector<TraceDumper::FunctionCallUP> &roots) {
735 std::make_unique<TraceDumper::FunctionCall>(cursor_sp, symbol_info);
737 new_root->SetUntracedPrefixSegment(std::move(roots.back()));
740 roots.emplace_back(std::move(new_root));
741 return *roots.back();
774 std::vector<TraceDumper::FunctionCallUP> &roots) {
775 if (!last_function_call || last_function_call->
IsError()) {
778 std::make_unique<TraceDumper::FunctionCall>(cursor_sp, symbol_info));
779 return *roots.back();
784 eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol,
791 cursor_sp, symbol_info);
800 return *last_function_call;
808 insn ? insn->GetControlFlowKind(&exe_ctx)
816 cursor_sp, symbol_info);
823 *last_function_call, symbol_info, cursor_sp, roots);
831 if (prev_symbol_info.
sc.
block &&
834 *last_function_call, symbol_info, cursor_sp, roots);
840 cursor_sp, symbol_info);
861 std::vector<TraceDumper::FunctionCallUP> &roots) {
862 if (last_function_call && last_function_call->
IsError()) {
865 return *last_function_call;
867 roots.emplace_back(std::make_unique<TraceDumper::FunctionCall>(
869 return *roots.back();
873static std::vector<TraceDumper::FunctionCallUP>
877 std::vector<TraceDumper::FunctionCallUP> roots;
882 for (; cursor_sp->HasValue(); cursor_sp->Next()) {
883 if (cursor_sp->IsError()) {
886 prev_symbol_info = {};
887 }
else if (cursor_sp->IsInstruction()) {
889 exe_ctx, cursor_sp->GetLoadAddress(), prev_symbol_info);
892 exe_ctx, last_function_call, prev_symbol_info, symbol_info, cursor_sp,
894 prev_symbol_info = symbol_info;
899 last_function_call =
nullptr;
900 prev_symbol_info = {};
910 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, const AddressRange &disasm_range, 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.
void Format(const char *format, Args &&... args)
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
void IndentMore(unsigned amount=2)
Increment the current indentation level.
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
uint32_t GetIndexID() 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
const SymbolInfo & GetLastInstructionSymbolInfo() const
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
const FunctionCall & GetNestedCall() const
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.
@ eTraceCursorSeekTypeCurrent
The current position in the trace.
@ 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 show_control_flow_kind
For each instruction, print the instruction kind.
bool only_events
Dump events and none of the instructions.
bool show_timestamps
For each trace item, print the corresponding timestamp in nanoseconds if available.
std::optional< uint64_t > id
Optional custom id to start traversing from.
std::optional< size_t > skip
Optional number of instructions to skip from the starting position of the cursor.
bool json
Dump in json format.
bool show_events
Dump the events that happened between instructions.
bool raw
Dump only instruction addresses without disassembly nor symbol information.
bool forwards
If true, the cursor will be iterated forwards starting from the oldest instruction.
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
lldb::user_id_t GetID() const
Get accessor for the user ID.