persona0220 created this revision.
persona0220 added reviewers: jj10306, wallace.
Herald added a project: All.
persona0220 requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
This diff is created on top of D137614 <https://reviews.llvm.org/D137614>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D139969
Files:
lldb/include/lldb/Target/TraceDumper.h
lldb/source/Commands/CommandObjectThread.cpp
lldb/source/Target/TraceDumper.cpp
Index: lldb/source/Target/TraceDumper.cpp
===================================================================
--- lldb/source/Target/TraceDumper.cpp
+++ lldb/source/Target/TraceDumper.cpp
@@ -340,7 +340,7 @@
}
}
-TraceDumper::TraceItem TraceDumper::CreatRawTraceItem() {
+TraceDumper::TraceItem TraceDumper::CreateRawTraceItem() {
TraceItem item = {};
item.id = m_cursor_sp->GetId();
@@ -428,7 +428,7 @@
m_cursor_sp->Next()) {
last_id = m_cursor_sp->GetId();
- TraceItem item = CreatRawTraceItem();
+ TraceItem item = CreateRawTraceItem();
if (m_cursor_sp->IsEvent() && m_options.show_events) {
item.event = m_cursor_sp->GetEventType();
@@ -469,246 +469,390 @@
return last_id;
}
-TraceCallGraphDumper::TraceCallGraphDumper(
- const TraceCursorSP &cursor_sp, const TraceCallGraphSP &call_graph_sp,
- Stream &s)
- : m_cursor_sp(cursor_sp), m_graph_sp(call_graph_sp), m_s(s),
- m_exe_ctx(cursor_sp->GetExecutionContextRef()) {}
-
// Overload pattern-based syntax sugar for easier variant matching.
template <typename... Ts> struct match : Ts... { using Ts::operator()...; };
template <class... Ts> match(Ts...) -> match<Ts...>;
-/// Utility for indenting and writing to a stream in one line.
-static Stream &WithIndent(Stream &s) {
- s.Indent();
- return s;
-}
+class GraphOutputWriterCLI : public TraceCallGraphDumper::OutputWriter {
+public:
+ GraphOutputWriterCLI(const TraceCursorSP &cursor_sp,
+ const TraceCallGraphSP &call_graph_sp, Stream &s)
+ : m_cursor_sp(cursor_sp), m_graph_sp(call_graph_sp),
+ m_exe_ctx(cursor_sp->GetExecutionContextRef()), m_s(s) {};
+
+ /// Utility for indenting and writing to a stream in one line.
+ Stream &WithIndent() {
+ m_s.Indent();
+ return m_s;
+ }
-/// RAII-based utility for handling indentation and de-indentation of a stream.
-struct AddIndent {
- AddIndent(Stream &s) : m_s(s) { m_s.IndentMore(); }
- ~AddIndent() { m_s.IndentLess(); }
+ /// RAII-based utility for handling indentation and de-indentation of a stream.
+ struct AddIndent {
+ AddIndent(Stream &s) : m_s(s) { m_s.IndentMore(); }
+ ~AddIndent() { m_s.IndentLess(); }
-private:
- Stream &m_s;
-};
+ private:
+ Stream &m_s;
+ };
-void TraceCallGraphDumper::Dump() {
- Thread &thread = m_exe_ctx.GetThreadRef();
- m_s.Format("thread #{0}: tid = {1}\n", thread.GetIndexID(), thread.GetID());
+ void Dump() override {
+ Thread &thread = m_exe_ctx.GetThreadRef();
+ llvm::ArrayRef<TraceCallTreeUP> trees = m_graph_sp->GetTrees();
+ m_s.Format("thread #{0}: tid = {1}\n", thread.GetIndexID(), thread.GetID());
- llvm::ArrayRef<TraceCallTreeUP> trees = m_graph_sp->GetTrees();
- AddIndent _(m_s);
- for (size_t i = 0; i < trees.size(); i++) {
- m_s << "\n";
- std::visit(
- match{[&](TraceErrorSegment &errors) {
- WithIndent(m_s).Format("<subtrace #{0}: tracing errors>\n", i);
- DumpErrorSegment(errors);
- },
- [&](TraceInstructionCallTree &tree) {
- WithIndent(m_s).Format("<subtrace #{0}: instructions>\n", i);
- DumpCall(tree.GetRootCall());
- }},
- *trees[i]);
+ AddIndent _(m_s);
+ for (size_t i = 0; i < trees.size(); i++) {
+ m_s << "\n";
+ std::visit(
+ match{[&](TraceErrorSegment &errors) {
+ WithIndent().Format("<subtrace #{0}: tracing errors>\n", i);
+ DumpErrorSegment(errors);
+ },
+ [&](TraceInstructionCallTree &tree) {
+ WithIndent().Format("<subtrace #{0}: instructions>\n", i);
+ AddIndent _(m_s);
+ DumpCall(tree.GetRootCall());
+ }},
+ *trees[i]);
+ }
}
-}
-void TraceCallGraphDumper::DumpErrorSegment(TraceErrorSegment &error_segment) {
- AddIndent _(m_s);
-
- auto print_error = [&](lldb::user_id_t error_id) {
- m_cursor_sp->GoToId(error_id);
- WithIndent(m_s).Format("|{0}: {1}\n", error_id, m_cursor_sp->GetError());
- };
+private:
+ static const char *ToDisplayString(const ModuleSP &module_sp) {
+ if (const char *str = module_sp->GetFileSpec().GetFilename().AsCString())
+ return str;
+ return "(none)";
+ }
- auto [from, to] = error_segment.GetRange();
- print_error(from);
- if (from != to) {
- uint64_t remaining = error_segment.GetErrorCount() - 2;
- if (remaining >= 2) {
- WithIndent(m_s).Format("| ... {0} error{1}\n", remaining,
- remaining == 1 ? "" : "s");
+ void DumpErrorSegment(TraceErrorSegment &error_segment) override {
+ AddIndent _(m_s);
+
+ auto print_error = [&](lldb::user_id_t error_id) {
+ m_cursor_sp->GoToId(error_id);
+ WithIndent().Format("|{0}: {1}\n", error_id, m_cursor_sp->GetError());
+ };
+
+ auto [from, to] = error_segment.GetRange();
+ print_error(from);
+ if (from != to) {
+ uint64_t remaining = error_segment.GetErrorCount() - 2;
+ if (remaining >= 2) {
+ WithIndent().Format("| ... {0} error{1}\n", remaining,
+ remaining == 1 ? "" : "s");
+ }
+ print_error(to);
}
- print_error(to);
}
-}
-static const char *ToDisplayString(const ModuleSP &module_sp) {
- if (const char *str = module_sp->GetFileSpec().GetFilename().AsCString())
- return str;
- return "(none)";
-}
-
-void TraceCallGraphDumper::DumpCallWrapper(
- std::function<void()> call_description_dumper,
- std::function<void(const TraceCursor &cursor)> insn_description_dumper,
- TraceCall &call_wrapper) {
+ void DumpCall(TraceCall &call) override {
+ std::visit(
+ match{[&](TraceCallInlinedFunction &call) {
+ DumpInlinedFunctionCall(call);
+ },
+ [&](TraceCallFunction &call) { DumpFunctionCall(call); },
+ [&](TraceCallSymbol &call) { DumpSymbolCall(call); },
+ [&](TraceCallSection &call) { DumpSectionCall(call); },
+ [&](TraceCallUnknownRegion &call) { DumpUnknownRegion(call); }},
+ call);
+ }
- WithIndent(m_s) << "-> ";
- call_description_dumper();
- m_s << "\n";
+ void DumpCallWrapper(
+ std::function<void()> call_description_dumper,
+ std::function<void(const TraceCursor &cursor)> insn_description_dumper,
+ TraceCall &call_wrapper) {
- auto dump_insn = [&](lldb::user_id_t id) {
- m_cursor_sp->GoToId(id);
- WithIndent(m_s).Format(" |{0}: {1:x+16}", id,
- m_cursor_sp->GetLoadAddress());
- insn_description_dumper(*m_cursor_sp);
+ WithIndent() << "-> ";
+ call_description_dumper();
m_s << "\n";
- };
- std::visit(
- [&](auto &&call) {
- for (const TraceCallSegmentUP &segment_up : call.GetSegments()) {
- AddIndent _(m_s);
- if (auto range = segment_up->GetRange()) {
- auto [from, to] = *range;
- dump_insn(from);
- if (from != to) {
- uint64_t mid_instructions =
- segment_up->GetExclusiveInsnCount() - 2;
- if (mid_instructions >= 1) {
- WithIndent(m_s).Format(" |... {0} instruction{1}\n",
- mid_instructions,
- mid_instructions == 1 ? "" : "s");
+ auto dump_insn = [&](lldb::user_id_t id) {
+ m_cursor_sp->GoToId(id);
+ WithIndent().Format(" |{0}: {1:x+16}", id,
+ m_cursor_sp->GetLoadAddress());
+ insn_description_dumper(*m_cursor_sp);
+ m_s << "\n";
+ };
+
+ std::visit(
+ [&](auto &&call) {
+ for (const TraceCallSegmentUP &segment_up : call.GetSegments()) {
+ AddIndent _(m_s);
+ if (auto range = segment_up->GetRange()) {
+ auto [from, to] = *range;
+ dump_insn(from);
+ if (from != to) {
+ uint64_t mid_instructions =
+ segment_up->GetExclusiveInsnCount() - 2;
+ if (mid_instructions >= 1) {
+ WithIndent().Format(" |... {0} instruction{1}\n",
+ mid_instructions,
+ mid_instructions == 1 ? "" : "s");
+ }
+ dump_insn(to);
}
- dump_insn(to);
+ }
+ if (TraceCall *child_call = segment_up->GetChildCall()) {
+ AddIndent _(m_s);
+ DumpCall(*child_call);
}
}
- if (TraceCall *child_call = segment_up->GetChildCall()) {
- DumpCall(*child_call);
- }
- }
- },
- call_wrapper);
-}
+ },
+ call_wrapper);
+ }
-void TraceCallGraphDumper::DumpSectionCall(TraceCallSection &call) {
- Target &target = m_exe_ctx.GetTargetRef();
- lldb::addr_t inlined_function_base_address =
- call.GetSection()->GetLoadBaseAddress(&target);
-
- DumpCallWrapper([&] { call.GetSection()->DumpName(m_s.AsRawOstream()); },
- [&](const TraceCursor &insn) {
- if (inlined_function_base_address != LLDB_INVALID_ADDRESS)
- m_s.Format(" <+{0}>", insn.GetLoadAddress() -
- inlined_function_base_address);
- },
- call.GetWrappingCall());
-}
+ void DumpSectionCall(TraceCallSection &call) {
+ Target &target = m_exe_ctx.GetTargetRef();
+ lldb::addr_t inlined_function_base_address =
+ call.GetSection()->GetLoadBaseAddress(&target);
+
+ DumpCallWrapper([&] { call.GetSection()->DumpName(m_s.AsRawOstream()); },
+ [&](const TraceCursor &insn) {
+ if (inlined_function_base_address != LLDB_INVALID_ADDRESS)
+ m_s.Format(" <+{0}>", insn.GetLoadAddress() -
+ inlined_function_base_address);
+ },
+ call.GetWrappingCall());
+ }
-void TraceCallGraphDumper::DumpInlinedFunctionCall(
- TraceCallInlinedFunction &call) {
- Block &inlined_block = call.GetInlinedBlock();
- Target &target = m_exe_ctx.GetTargetRef();
-
- lldb::addr_t inlined_function_base_address = LLDB_INVALID_ADDRESS;
- if (AddressRange range; inlined_block.GetRangeAtIndex(0, range))
- inlined_function_base_address =
- range.GetBaseAddress().GetLoadAddress(&target);
-
- DumpCallWrapper(
- [&] {
- m_s.Format("[inlined] {0}`{1}",
- ToDisplayString(call.GetOwningFunctionCall()
- .GetFunction()
- .CalculateSymbolContextModule()),
- inlined_block.GetInlinedFunctionInfo()->GetName());
- },
- [&](const TraceCursor &insn) {
- lldb::addr_t load_address = insn.GetLoadAddress();
- AddressRange range;
- if (inlined_function_base_address != LLDB_INVALID_ADDRESS)
- m_s.Format(" <+{0}>", load_address - inlined_function_base_address);
-
- Address addr;
- if (target.ResolveLoadAddress(load_address, addr)) {
- LineEntry line_entry;
- addr.CalculateSymbolContextLineEntry(line_entry);
-
- if (line_entry.IsValid()) {
- m_s << " at ";
- line_entry.DumpStopContext(&m_s, /*show_fullpaths*/ false);
+ void DumpInlinedFunctionCall(
+ TraceCallInlinedFunction &call) {
+ Block &inlined_block = call.GetInlinedBlock();
+ Target &target = m_exe_ctx.GetTargetRef();
+
+ lldb::addr_t inlined_function_base_address = LLDB_INVALID_ADDRESS;
+ if (AddressRange range; inlined_block.GetRangeAtIndex(0, range))
+ inlined_function_base_address =
+ range.GetBaseAddress().GetLoadAddress(&target);
+
+ DumpCallWrapper(
+ [&] {
+ m_s.Format("[inlined] {0}`{1}",
+ ToDisplayString(call.GetOwningFunctionCall()
+ .GetFunction()
+ .CalculateSymbolContextModule()),
+ inlined_block.GetInlinedFunctionInfo()->GetName());
+ },
+ [&](const TraceCursor &insn) {
+ lldb::addr_t load_address = insn.GetLoadAddress();
+ AddressRange range;
+ if (inlined_function_base_address != LLDB_INVALID_ADDRESS)
+ m_s.Format(" <+{0}>", load_address - inlined_function_base_address);
+
+ Address addr;
+ if (target.ResolveLoadAddress(load_address, addr)) {
+ LineEntry line_entry;
+ addr.CalculateSymbolContextLineEntry(line_entry);
+
+ if (line_entry.IsValid()) {
+ m_s << " at ";
+ line_entry.DumpStopContext(&m_s, false);
+ }
}
- }
- },
- call.GetWrappingCall());
-}
+ },
+ call.GetWrappingCall());
+ }
-void TraceCallGraphDumper::DumpFunctionCall(TraceCallFunction &call) {
- Function &function = call.GetFunction();
- Target &target = m_exe_ctx.GetTargetRef();
- lldb::addr_t function_base_address =
- function.GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
-
- DumpCallWrapper(
- [&] {
- m_s.Format("{0}`{1}",
- ToDisplayString(function.CalculateSymbolContextModule()),
- function.GetName());
- },
- [&](const TraceCursor &insn) {
- lldb::addr_t load_address = insn.GetLoadAddress();
- if (function_base_address != LLDB_INVALID_ADDRESS)
- m_s.Format(" <+{0}>", load_address - function_base_address);
-
- Address addr;
- if (target.ResolveLoadAddress(load_address, addr)) {
- LineEntry line_entry;
- addr.CalculateSymbolContextLineEntry(line_entry);
- if (line_entry.IsValid()) {
- m_s << " at ";
- line_entry.DumpStopContext(&m_s, /*show_fullpaths*/ false);
+ void DumpFunctionCall(TraceCallFunction &call) {
+ Function &function = call.GetFunction();
+ Target &target = m_exe_ctx.GetTargetRef();
+ lldb::addr_t function_base_address =
+ function.GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
+
+ DumpCallWrapper(
+ [&] {
+ m_s.Format("{0}`{1}",
+ ToDisplayString(function.CalculateSymbolContextModule()),
+ function.GetName());
+ },
+ [&](const TraceCursor &insn) {
+ lldb::addr_t load_address = insn.GetLoadAddress();
+ if (function_base_address != LLDB_INVALID_ADDRESS)
+ m_s.Format(" <+{0}>", load_address - function_base_address);
+
+ Address addr;
+ if (target.ResolveLoadAddress(load_address, addr)) {
+ LineEntry line_entry;
+ addr.CalculateSymbolContextLineEntry(line_entry);
+ if (line_entry.IsValid()) {
+ m_s << " at ";
+ line_entry.DumpStopContext(&m_s, false);
+ }
}
- }
- },
- call.GetWrappingCall());
-}
-
-void TraceCallGraphDumper::DumpSymbolCall(TraceCallSymbol &call) {
- Symbol &symbol = call.GetSymbol();
- Target &target = m_exe_ctx.GetTargetRef();
+ },
+ call.GetWrappingCall());
+ }
- DumpCallWrapper(
- [&] {
- m_s.Format("{0}`{1}",
- ToDisplayString(symbol.CalculateSymbolContextModule()),
- symbol.GetName());
- },
- [&](const TraceCursor &insn) {
- lldb::addr_t load_address = insn.GetLoadAddress();
- lldb::addr_t symbol_offset =
- load_address - symbol.GetLoadAddress(&target);
- m_s.Format(" <+{0}>", symbol_offset);
-
- Address addr;
- if (target.ResolveLoadAddress(load_address, addr)) {
- LineEntry line_entry;
- addr.CalculateSymbolContextLineEntry(line_entry);
- if (line_entry.IsValid()) {
- m_s << " at ";
- line_entry.DumpStopContext(&m_s, /*show_fullpaths*/ false);
+ void DumpSymbolCall(TraceCallSymbol &call) {
+ Symbol &symbol = call.GetSymbol();
+ Target &target = m_exe_ctx.GetTargetRef();
+
+ DumpCallWrapper(
+ [&] {
+ m_s.Format("{0}`{1}",
+ ToDisplayString(symbol.CalculateSymbolContextModule()),
+ symbol.GetName());
+ },
+ [&](const TraceCursor &insn) {
+ lldb::addr_t load_address = insn.GetLoadAddress();
+ lldb::addr_t symbol_offset =
+ load_address - symbol.GetLoadAddress(&target);
+ m_s.Format(" <+{0}>", symbol_offset);
+
+ Address addr;
+ if (target.ResolveLoadAddress(load_address, addr)) {
+ LineEntry line_entry;
+ addr.CalculateSymbolContextLineEntry(line_entry);
+ if (line_entry.IsValid()) {
+ m_s << " at ";
+ line_entry.DumpStopContext(&m_s, false);
+ }
}
+ },
+ call.GetWrappingCall());
+ }
+
+ void DumpUnknownRegion(TraceCallUnknownRegion &call) {
+ DumpCallWrapper([&] { m_s << "unknown region"; },
+ [&](const TraceCursor &insn) {}, call.GetWrappingCall());
+ }
+
+ lldb::TraceCursorSP m_cursor_sp;
+ lldb::TraceCallGraphSP m_graph_sp;
+ ExecutionContext m_exe_ctx;
+ Stream &m_s;
+};
+
+class GraphOutputWriterJSON : public TraceCallGraphDumper::OutputWriter {
+ /* schema:
+ [ // array
+ {
+ "error": {
+ "from": decimal,
+ "to": decimal,
+ } || // each element in the array is either error or call
+ "function | inline | section | symbol | unknown": { // type of call
+ "segments": [ // child calls
+ {
+ "function | inline | section | symbol | unknown": { // nested
+ ...
+ }
+ } || // each element in the segments is either nested call or insns
+ {
+ "from": start instruction id of this call
+ "to": end instruction id of this call
+ }
+ ...
+ ]
+ }
}
},
- call.GetWrappingCall());
-}
+ ...
+ ]
+ */
+public:
+ GraphOutputWriterJSON(const TraceCursorSP &cursor_sp,
+ const TraceCallGraphSP &call_graph_sp, Stream &s, unsigned indent_size)
+ : m_graph_sp(call_graph_sp), m_s(s),
+ m_j(m_s.AsRawOstream(), indent_size) {
+ m_j.arrayBegin();
+ };
+
+ ~GraphOutputWriterJSON() { m_j.arrayEnd(); }
+
+ void Dump() override {
+ llvm::ArrayRef<TraceCallTreeUP> trees = m_graph_sp->GetTrees();
+
+ for (size_t i = 0; i < trees.size(); i++) {
+ std::visit(
+ match{[&](TraceErrorSegment &errors) {
+ m_j.object([&] {
+ DumpErrorSegment(errors);
+ });
+ },
+ [&](TraceInstructionCallTree &tree) {
+ m_j.object([&] {
+ DumpCall(tree.GetRootCall());
+ });
+ }},
+ *trees[i]);
+ }
+ }
+
+private:
+ void DumpErrorSegment(TraceErrorSegment &error_segment) override {
+ auto range = error_segment.GetRange();
+ m_j.attributeObject("error", [&] {
+ m_j.attribute("from", range.first);
+ m_j.attribute("to", range.second);
+ });
+ }
+
+ void DumpCall(TraceCall &call) override {
+ std::visit(
+ match{[&](TraceCallInlinedFunction &call) {
+ DumpCallWrapper("inline", call.GetWrappingCall());
+ },
+ [&](TraceCallFunction &call) {
+ DumpCallWrapper("function", call.GetWrappingCall());
+ },
+ [&](TraceCallSymbol &call) {
+ DumpCallWrapper("symbol", call.GetWrappingCall());
+ },
+ [&](TraceCallSection &call) {
+ DumpCallWrapper("section", call.GetWrappingCall());
+ },
+ [&](TraceCallUnknownRegion &call) {
+ DumpCallWrapper("unknown", call.GetWrappingCall());
+ }},
+ call);
+ }
+
+ void DumpCallWrapper(const char* name, TraceCall &call_wrapper) {
+ m_j.attributeObject(name, [&] {
+ std::visit(
+ [&](auto &&call) {
+ m_j.attributeArray("segments", [&] {
+ for (const TraceCallSegmentUP &segment_up : call.GetSegments()) {
+ // traced segments
+ if (auto range = segment_up->GetRange()) {
+ m_j.object([&] {
+ m_j.attribute("from", range->first);
+ m_j.attribute("to", range->second);
+ });
+ }
-void TraceCallGraphDumper::DumpUnknownRegion(TraceCallUnknownRegion &call) {
- DumpCallWrapper([&] { m_s << "unknown region"; },
- [&](const TraceCursor &insn) {}, call.GetWrappingCall());
+ // nested
+ if (TraceCall *child_call = segment_up->GetChildCall()) {
+ m_j.object([&] {
+ DumpCall(*child_call);
+ });
+ }
+ }
+ });
+ },
+ call_wrapper);
+ });
+ }
+
+ lldb::TraceCallGraphSP m_graph_sp;
+ Stream &m_s;
+ json::OStream m_j;
+};
+
+TraceCallGraphDumper::TraceCallGraphDumper(
+ const TraceCursorSP &cursor_sp, const TraceCallGraphSP &call_graph_sp,
+ Stream &s, const PrintStyle &print_style) {
+ if (print_style == PrintStyle::JSON)
+ m_writer_up = std::unique_ptr<TraceCallGraphDumper::OutputWriter>(
+ new GraphOutputWriterJSON(cursor_sp, call_graph_sp, s, 0));
+ else if (print_style == PrintStyle::PrettyJSON)
+ m_writer_up = std::unique_ptr<TraceCallGraphDumper::OutputWriter>(
+ new GraphOutputWriterJSON(cursor_sp, call_graph_sp, s, 2));
+ else
+ m_writer_up = std::unique_ptr<TraceCallGraphDumper::OutputWriter>(
+ new GraphOutputWriterCLI(cursor_sp, call_graph_sp, s));
}
-void TraceCallGraphDumper::DumpCall(TraceCall &call) {
- AddIndent _(m_s);
- std::visit(
- match{[&](TraceCallInlinedFunction &call) {
- DumpInlinedFunctionCall(call);
- },
- [&](TraceCallFunction &call) { DumpFunctionCall(call); },
- [&](TraceCallSymbol &call) { DumpSymbolCall(call); },
- [&](TraceCallSection &call) { DumpSectionCall(call); },
- [&](TraceCallUnknownRegion &call) { DumpUnknownRegion(call); }},
- call);
+void TraceCallGraphDumper::Dump() {
+ m_writer_up->Dump();
}
Index: lldb/source/Commands/CommandObjectThread.cpp
===================================================================
--- lldb/source/Commands/CommandObjectThread.cpp
+++ lldb/source/Commands/CommandObjectThread.cpp
@@ -2116,8 +2116,6 @@
class CommandObjectTraceDumpFunctionCalls : public CommandObjectParsed {
public:
- enum class PrintStyle { Normal, JSON, PrettyJSON };
-
class CommandOptions : public Options {
public:
CommandOptions() { OptionParsingStarting(nullptr); }
@@ -2234,7 +2232,8 @@
File::eOpenOptionTruncate);
}
TraceCallGraphDumper(*cursor_sp, *graph_sp,
- out_file ? *out_file : result.GetOutputStream())
+ out_file ? *out_file : result.GetOutputStream(),
+ m_options.m_options.print_style)
.Dump();
return true;
Index: lldb/include/lldb/Target/TraceDumper.h
===================================================================
--- lldb/include/lldb/Target/TraceDumper.h
+++ lldb/include/lldb/Target/TraceDumper.h
@@ -46,6 +46,9 @@
llvm::Optional<size_t> skip = llvm::None;
};
+/// Simpler dumper options for TraceCallGraphDumper.
+enum class PrintStyle { Normal, JSON, PrettyJSON };
+
/// Class used to dump the instructions of a \a TraceCursor using its current
/// state and granularity.
class TraceDumper {
@@ -119,7 +122,7 @@
private:
/// Create a trace item for the current position without symbol information.
- TraceItem CreatRawTraceItem();
+ TraceItem CreateRawTraceItem();
lldb::TraceCursorSP m_cursor_sp;
TraceDumperOptions m_options;
@@ -130,34 +133,27 @@
class TraceCallGraphDumper {
public:
TraceCallGraphDumper(const lldb::TraceCursorSP &cursor_sp,
- const lldb::TraceCallGraphSP &call_graph_sp, Stream &s);
+ const lldb::TraceCallGraphSP &call_graph_sp, Stream &s,
+ const PrintStyle &print_style);
void Dump();
-private:
- void DumpErrorSegment(TraceErrorSegment &error_segment);
-
- void DumpCall(TraceCall &call);
-
- void DumpFunctionCall(TraceCallFunction &call);
-
- void DumpSymbolCall(TraceCallSymbol &call);
-
- void DumpInlinedFunctionCall(TraceCallInlinedFunction &call);
+ /// Interface used to abstract away the format in which the call graph
+ /// will be dumped.
+ class OutputWriter {
+ public:
+ virtual ~OutputWriter() = default;
- void DumpSectionCall(TraceCallSection &call);
+ /// Dump a call graph (call tree or error)
+ virtual void Dump() = 0;
- void DumpUnknownRegion(TraceCallUnknownRegion &call);
+ private:
+ virtual void DumpErrorSegment(TraceErrorSegment &error_segment) = 0;
- void DumpCallWrapper(
- std::function<void()> call_description_dumper,
- std::function<void(const TraceCursor &insn)> insn_description_dumper,
- TraceCall &call_wrapper);
+ virtual void DumpCall(TraceCall &call);
+ };
- lldb::TraceCursorSP m_cursor_sp;
- lldb::TraceCallGraphSP m_graph_sp;
- Stream &m_s;
- ExecutionContext m_exe_ctx;
+ std::unique_ptr<OutputWriter> m_writer_up;
};
} // namespace lldb_private
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits