[lldb][trace] Add a basic function call dump [2] - Implement the reconstruction algorithm

This diff implements the reconstruction algorithm for the call tree and
add tests.

See TraceDumper.h for documentation and explanations.

One important detail is that the tree objects are in TraceDumper, even
though Trace.h is a better home. I'm leaving that as future work.

Another detail is that this code is as slow as dumping the entire
symolicated trace, which is not that bad tbh. The reason is that we use
symbols throughout the algorithm and we are not being careful about
memory and speed. This is also another area for future improvement.

Lastly, I made sure that incomplete traces work, i.e. you start tracing
very deep in the stack or failures randomly appear in the trace.

Differential Revision: https://reviews.llvm.org/D135917
This commit is contained in:
Walter Erquinigo
2022-10-10 12:57:13 -07:00
parent 566146c03b
commit 840d861d6e
7 changed files with 898 additions and 40 deletions

View File

@@ -2128,11 +2128,11 @@ public:
switch (short_option) {
case 'j': {
m_json = true;
m_dumper_options.json = true;
break;
}
case 'J': {
m_pretty_json = true;
m_dumper_options.pretty_print_json = true;
break;
}
case 'F': {
@@ -2146,8 +2146,7 @@ public:
}
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_json = false;
m_pretty_json = false;
m_dumper_options = {};
m_output_file = llvm::None;
}
@@ -2158,8 +2157,7 @@ public:
static const size_t kDefaultCount = 20;
// Instance variables to hold the values for command options.
bool m_json;
bool m_pretty_json;
TraceDumperOptions m_dumper_options;
llvm::Optional<FileSpec> m_output_file;
};
@@ -2187,10 +2185,30 @@ protected:
result.AppendError("invalid thread\n");
return false;
}
result.AppendMessageWithFormatv(
"json = {0}, pretty_json = {1}, file = {2}, thread = {3}",
m_options.m_json, m_options.m_pretty_json, !!m_options.m_output_file,
thread_sp->GetID());
llvm::Expected<TraceCursorSP> cursor_or_error =
m_exe_ctx.GetTargetSP()->GetTrace()->CreateNewCursor(*thread_sp);
if (!cursor_or_error) {
result.AppendError(llvm::toString(cursor_or_error.takeError()));
return false;
}
TraceCursorSP &cursor_sp = *cursor_or_error;
llvm::Optional<StreamFile> out_file;
if (m_options.m_output_file) {
out_file.emplace(m_options.m_output_file->GetPath().c_str(),
File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate,
lldb::eFilePermissionsFileDefault);
}
m_options.m_dumper_options.forwards = true;
TraceDumper dumper(std::move(cursor_sp),
out_file ? *out_file : result.GetOutputStream(),
m_options.m_dumper_options);
dumper.DumpFunctionCalls();
return true;
}