aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Commands
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-14 18:50:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-14 18:50:02 +0000
commit1f917f69ff07f09b6dbb670971f57f8efe718b84 (patch)
tree99293cbc1411737cd995dac10a99b2c40ef0944c /lldb/source/Commands
parent145449b1e420787bb99721a429341fa6be3adfb6 (diff)
Diffstat (limited to 'lldb/source/Commands')
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.cpp8
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.h1
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp128
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp69
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp33
-rw-r--r--lldb/source/Commands/CommandObjectTrace.cpp116
-rw-r--r--lldb/source/Commands/Options.td28
7 files changed, 258 insertions, 125 deletions
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp
index 9d081c83c0fb..6c33edc8a3a8 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.cpp
+++ b/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -65,6 +65,10 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
show_bytes = true;
break;
+ case 'k':
+ show_control_flow_kind = true;
+ break;
+
case 's': {
start_addr = OptionArgParser::ToAddress(execution_context, option_arg,
LLDB_INVALID_ADDRESS, &error);
@@ -154,6 +158,7 @@ void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
ExecutionContext *execution_context) {
show_mixed = false;
show_bytes = false;
+ show_control_flow_kind = false;
num_lines_context = 0;
num_instructions = 0;
func_name.clear();
@@ -493,6 +498,9 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
if (m_options.show_bytes)
options |= Disassembler::eOptionShowBytes;
+ if (m_options.show_control_flow_kind)
+ options |= Disassembler::eOptionShowControlFlowKind;
+
if (m_options.raw)
options |= Disassembler::eOptionRawOuput;
diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h
index a4b3df8724da..b5146863628d 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.h
+++ b/lldb/source/Commands/CommandObjectDisassemble.h
@@ -46,6 +46,7 @@ public:
bool show_mixed; // Show mixed source/assembly
bool show_bytes;
+ bool show_control_flow_kind;
uint32_t num_lines_context = 0;
uint32_t num_instructions = 0;
bool raw;
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index c76ae99057f2..d36a574aba7d 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -579,14 +579,14 @@ protected:
}
}
}
-
+
Target *target = m_exe_ctx.GetTargetPtr();
BreakpointIDList run_to_bkpt_ids;
// Don't pass an empty run_to_breakpoint list, as Verify will look for the
// default breakpoint.
if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)
CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
- m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
+ m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
BreakpointName::Permissions::disablePerm);
if (!result.Succeeded()) {
return false;
@@ -604,7 +604,7 @@ protected:
std::vector<break_id_t> bkpts_disabled;
std::vector<BreakpointID> locs_disabled;
if (num_run_to_bkpt_ids != 0) {
- // Go through the ID's specified, and separate the breakpoints from are
+ // Go through the ID's specified, and separate the breakpoints from are
// the breakpoint.location specifications since the latter require
// special handling. We also figure out whether there's at least one
// specifier in the set that is enabled.
@@ -613,22 +613,22 @@ protected:
std::unordered_set<break_id_t> bkpts_with_locs_seen;
BreakpointIDList with_locs;
bool any_enabled = false;
-
+
for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) {
BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx);
break_id_t bp_id = bkpt_id.GetBreakpointID();
break_id_t loc_id = bkpt_id.GetLocationID();
- BreakpointSP bp_sp
+ BreakpointSP bp_sp
= bkpt_list.FindBreakpointByID(bp_id);
- // Note, VerifyBreakpointOrLocationIDs checks for existence, so we
+ // Note, VerifyBreakpointOrLocationIDs checks for existence, so we
// don't need to do it again here.
if (bp_sp->IsEnabled()) {
if (loc_id == LLDB_INVALID_BREAK_ID) {
- // A breakpoint (without location) was specified. Make sure that
+ // A breakpoint (without location) was specified. Make sure that
// at least one of the locations is enabled.
size_t num_locations = bp_sp->GetNumLocations();
for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
- BreakpointLocationSP loc_sp
+ BreakpointLocationSP loc_sp
= bp_sp->GetLocationAtIndex(loc_idx);
if (loc_sp->IsEnabled()) {
any_enabled = true;
@@ -641,7 +641,7 @@ protected:
if (loc_sp->IsEnabled())
any_enabled = true;
}
-
+
// Then sort the bp & bp.loc entries for later use:
if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
bkpts_seen.insert(bkpt_id.GetBreakpointID());
@@ -653,14 +653,14 @@ protected:
}
// Do all the error checking here so once we start disabling we don't
// have to back out half-way through.
-
+
// Make sure at least one of the specified breakpoints is enabled.
if (!any_enabled) {
result.AppendError("at least one of the continue-to breakpoints must "
"be enabled.");
return false;
}
-
+
// Also, if you specify BOTH a breakpoint and one of it's locations,
// we flag that as an error, since it won't do what you expect, the
// breakpoint directive will mean "run to all locations", which is not
@@ -671,7 +671,7 @@ protected:
"one of its locations: {0}", bp_id);
}
}
-
+
// Now go through the breakpoints in the target, disabling all the ones
// that the user didn't mention:
for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) {
@@ -695,7 +695,7 @@ protected:
BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx);
tmp_id.SetBreakpointLocationID(loc_idx);
size_t position = 0;
- if (!with_locs.FindBreakpointID(tmp_id, &position)
+ if (!with_locs.FindBreakpointID(tmp_id, &position)
&& loc_sp->IsEnabled()) {
locs_disabled.push_back(tmp_id);
loc_sp->SetEnabled(false);
@@ -723,20 +723,20 @@ protected:
Status error;
// For now we can only do -b with synchronous:
bool old_sync = GetDebugger().GetAsyncExecution();
-
+
if (run_to_bkpt_ids.GetSize() != 0) {
GetDebugger().SetAsyncExecution(false);
synchronous_execution = true;
- }
+ }
if (synchronous_execution)
error = process->ResumeSynchronous(&stream);
else
error = process->Resume();
-
+
if (run_to_bkpt_ids.GetSize() != 0) {
GetDebugger().SetAsyncExecution(old_sync);
- }
-
+ }
+
// Now re-enable the breakpoints we disabled:
BreakpointList &bkpt_list = target->GetBreakpointList();
for (break_id_t bp_id : bkpts_disabled) {
@@ -745,10 +745,10 @@ protected:
bp_sp->SetEnabled(true);
}
for (const BreakpointID &bkpt_id : locs_disabled) {
- BreakpointSP bp_sp
+ BreakpointSP bp_sp
= bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID());
if (bp_sp) {
- BreakpointLocationSP loc_sp
+ BreakpointLocationSP loc_sp
= bp_sp->FindLocationByID(bkpt_id.GetLocationID());
if (loc_sp)
loc_sp->SetEnabled(true);
@@ -1731,7 +1731,7 @@ protected:
bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
Target &target = GetSelectedOrDummyTarget();
- // Any signals that are being set should be added to the Target's
+ // Any signals that are being set should be added to the Target's
// DummySignals so they will get applied on rerun, etc.
// If we have a process, however, we can do a more accurate job of vetting
// the user's options.
@@ -1761,8 +1761,8 @@ protected:
"true or false.\n");
return false;
}
-
- bool no_actions = (stop_action == -1 && pass_action == -1
+
+ bool no_actions = (stop_action == -1 && pass_action == -1
&& notify_action == -1);
if (m_options.only_target_values && !no_actions) {
result.AppendError("-t is for reporting, not setting, target values.");
@@ -1832,9 +1832,9 @@ protected:
}
auto set_lazy_bool = [] (int action) -> LazyBool {
LazyBool lazy;
- if (action == -1)
+ if (action == -1)
lazy = eLazyBoolCalculate;
- else if (action)
+ else if (action)
lazy = eLazyBoolYes;
else
lazy = eLazyBoolNo;
@@ -1876,7 +1876,7 @@ protected:
PrintSignalInformation(result.GetOutputStream(), signal_args,
num_signals_set, signals_sp);
else
- target.PrintDummySignals(result.GetOutputStream(),
+ target.PrintDummySignals(result.GetOutputStream(),
signal_args);
if (num_signals_set > 0)
@@ -1909,80 +1909,6 @@ protected:
}
};
-// CommandObjectProcessTraceSave
-#define LLDB_OPTIONS_process_trace_save
-#include "CommandOptions.inc"
-
-#pragma mark CommandObjectProcessTraceSave
-
-class CommandObjectProcessTraceSave : public CommandObjectParsed {
-public:
- class CommandOptions : public Options {
- public:
- CommandOptions() { OptionParsingStarting(nullptr); }
-
- Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override {
- Status error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option) {
-
- case 'd': {
- m_directory.SetFile(option_arg, FileSpec::Style::native);
- FileSystem::Instance().Resolve(m_directory);
- break;
- }
- default:
- llvm_unreachable("Unimplemented option");
- }
- return error;
- }
-
- void OptionParsingStarting(ExecutionContext *execution_context) override{};
-
- llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
- return llvm::makeArrayRef(g_process_trace_save_options);
- };
-
- FileSpec m_directory;
- };
-
- Options *GetOptions() override { return &m_options; }
- CommandObjectProcessTraceSave(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "process trace save",
- "Save the trace of the current process in the specified directory. "
- "The directory will be created if needed. "
- "This will also create a file <directory>/trace.json with the main "
- "properties of the trace session, along with others files which "
- "contain the actual trace data. The trace.json file can be used "
- "later as input for the \"trace load\" command to load the trace "
- "in LLDB",
- "process trace save [<cmd-options>]",
- eCommandRequiresProcess | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
- eCommandProcessMustBeTraced) {}
-
- ~CommandObjectProcessTraceSave() override = default;
-
-protected:
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- ProcessSP process_sp = m_exe_ctx.GetProcessSP();
-
- TraceSP trace_sp = process_sp->GetTarget().GetTrace();
-
- if (llvm::Error err = trace_sp->SaveLiveTraceToDisk(m_options.m_directory))
- result.AppendError(toString(std::move(err)));
- else
- result.SetStatus(eReturnStatusSuccessFinishResult);
-
- return result.Succeeded();
- }
-
- CommandOptions m_options;
-};
-
// CommandObjectProcessTraceStop
class CommandObjectProcessTraceStop : public CommandObjectParsed {
public:
@@ -2020,8 +1946,6 @@ public:
: CommandObjectMultiword(
interpreter, "trace", "Commands for tracing the current process.",
"process trace <subcommand> [<subcommand objects>]") {
- LoadSubCommand("save", CommandObjectSP(
- new CommandObjectProcessTraceSave(interpreter)));
LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
interpreter)));
LoadSubCommand("stop", CommandObjectSP(
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 2b71f1bc7bc8..51978878c8b9 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -47,12 +47,18 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Timer.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private-enumerations.h"
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
@@ -2155,6 +2161,59 @@ protected:
}
};
+class CommandObjectTargetModulesDumpClangPCMInfo : public CommandObjectParsed {
+public:
+ CommandObjectTargetModulesDumpClangPCMInfo(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "target modules dump pcm-info",
+ "Dump information about the given clang module (pcm).") {
+ // Take a single file argument.
+ CommandArgumentData arg{eArgTypeFilename, eArgRepeatPlain};
+ m_arguments.push_back({arg});
+ }
+
+ ~CommandObjectTargetModulesDumpClangPCMInfo() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ if (command.GetArgumentCount() != 1) {
+ result.AppendErrorWithFormat("'%s' takes exactly one pcm path argument.",
+ m_cmd_name.c_str());
+ return false;
+ }
+
+ const char *pcm_path = command.GetArgumentAtIndex(0);
+ FileSpec pcm_file{pcm_path};
+
+ if (pcm_file.GetFileNameExtension().GetStringRef() != ".pcm") {
+ result.AppendError("file must have a .pcm extension");
+ return false;
+ }
+
+ if (!FileSystem::Instance().Exists(pcm_file)) {
+ result.AppendError("pcm file does not exist");
+ return false;
+ }
+
+ clang::CompilerInstance compiler;
+ compiler.createDiagnostics();
+
+ const char *clang_args[] = {"clang", pcm_path};
+ compiler.setInvocation(clang::createInvocation(clang_args));
+
+ clang::DumpModuleInfoAction dump_module_info;
+ dump_module_info.OutputStream = &result.GetOutputStream().AsRawOstream();
+ // DumpModuleInfoAction requires ObjectFilePCHContainerReader.
+ compiler.getPCHContainerOperations()->registerReader(
+ std::make_unique<clang::ObjectFilePCHContainerReader>());
+
+ if (compiler.ExecuteAction(dump_module_info))
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ return result.Succeeded();
+ }
+};
+
#pragma mark CommandObjectTargetModulesDumpClangAST
// Clang AST dumping command
@@ -2406,10 +2465,10 @@ public:
CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
: CommandObjectMultiword(
interpreter, "target modules dump",
- "Commands for dumping information about one or "
- "more target modules.",
+ "Commands for dumping information about one or more target "
+ "modules.",
"target modules dump "
- "[headers|symtab|sections|ast|symfile|line-table] "
+ "[objfile|symtab|sections|ast|symfile|line-table|pcm-info] "
"[<file1> <file2> ...]") {
LoadSubCommand("objfile",
CommandObjectSP(
@@ -2429,6 +2488,10 @@ public:
LoadSubCommand("line-table",
CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
interpreter)));
+ LoadSubCommand(
+ "pcm-info",
+ CommandObjectSP(
+ new CommandObjectTargetModulesDumpClangPCMInfo(interpreter)));
}
~CommandObjectTargetModulesDump() override = default;
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 993523e06736..ad49d27bb9a7 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -1033,11 +1033,21 @@ protected:
line_table->FindLineEntryByAddress(fun_end_addr, function_start,
&end_ptr);
+ // Since not all source lines will contribute code, check if we are
+ // setting the breakpoint on the exact line number or the nearest
+ // subsequent line number and set breakpoints at all the line table
+ // entries of the chosen line number (exact or nearest subsequent).
for (uint32_t line_number : line_numbers) {
+ LineEntry line_entry;
+ bool exact = false;
uint32_t start_idx_ptr = index_ptr;
+ start_idx_ptr = sc.comp_unit->FindLineEntry(
+ index_ptr, line_number, nullptr, exact, &line_entry);
+ if (start_idx_ptr != UINT32_MAX)
+ line_number = line_entry.line;
+ exact = true;
+ start_idx_ptr = index_ptr;
while (start_idx_ptr <= end_ptr) {
- LineEntry line_entry;
- const bool exact = false;
start_idx_ptr = sc.comp_unit->FindLineEntry(
start_idx_ptr, line_number, nullptr, exact, &line_entry);
if (start_idx_ptr == UINT32_MAX)
@@ -2164,6 +2174,10 @@ public:
m_dumper_options.forwards = true;
break;
}
+ case 'k': {
+ m_dumper_options.show_control_flow_kind = true;
+ break;
+ }
case 't': {
m_dumper_options.show_tsc = true;
break;
@@ -2337,6 +2351,10 @@ public:
m_verbose = true;
break;
}
+ case 'j': {
+ m_json = true;
+ break;
+ }
default:
llvm_unreachable("Unimplemented option");
}
@@ -2345,6 +2363,7 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_verbose = false;
+ m_json = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -2353,15 +2372,9 @@ public:
// Instance variables to hold the values for command options.
bool m_verbose;
+ bool m_json;
};
- bool DoExecute(Args &command, CommandReturnObject &result) override {
- Target &target = m_exe_ctx.GetTargetRef();
- result.GetOutputStream().Format("Trace technology: {0}\n",
- target.GetTrace()->GetPluginName());
- return CommandObjectIterateOverThreads::DoExecute(command, result);
- }
-
CommandObjectTraceDumpInfo(CommandInterpreter &interpreter)
: CommandObjectIterateOverThreads(
interpreter, "thread trace dump info",
@@ -2383,7 +2396,7 @@ protected:
ThreadSP thread_sp =
m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
trace_sp->DumpTraceInfo(*thread_sp, result.GetOutputStream(),
- m_options.m_verbose);
+ m_options.m_verbose, m_options.m_json);
return true;
}
diff --git a/lldb/source/Commands/CommandObjectTrace.cpp b/lldb/source/Commands/CommandObjectTrace.cpp
index 17aded9ed2a0..227de2de7065 100644
--- a/lldb/source/Commands/CommandObjectTrace.cpp
+++ b/lldb/source/Commands/CommandObjectTrace.cpp
@@ -30,6 +30,108 @@ using namespace lldb;
using namespace lldb_private;
using namespace llvm;
+// CommandObjectTraceSave
+#define LLDB_OPTIONS_trace_save
+#include "CommandOptions.inc"
+
+#pragma mark CommandObjectTraceSave
+
+class CommandObjectTraceSave : public CommandObjectParsed {
+public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() { OptionParsingStarting(nullptr); }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'c': {
+ m_compact = true;
+ break;
+ }
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_compact = false;
+ };
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_trace_save_options);
+ };
+
+ bool m_compact;
+ };
+
+ Options *GetOptions() override { return &m_options; }
+
+ CommandObjectTraceSave(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "trace save",
+ "Save the trace of the current target in the specified directory, "
+ "which will be created if needed. "
+ "This directory will contain a trace bundle, with all the "
+ "necessary files the reconstruct the trace session even on a "
+ "different computer. "
+ "Part of this bundle is the bundle description file with the name "
+ "trace.json. This file can be used by the \"trace load\" command "
+ "to load this trace in LLDB."
+ "Note: if the current target contains information of multiple "
+ "processes or targets, they all will be included in the bundle.",
+ "trace save [<cmd-options>] <bundle_directory>",
+ eCommandRequiresProcess | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
+ eCommandProcessMustBeTraced) {
+ CommandArgumentData bundle_dir{eArgTypeDirectoryName, eArgRepeatPlain};
+ m_arguments.push_back({bundle_dir});
+ }
+
+ void
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
+ request, nullptr);
+ }
+
+ ~CommandObjectTraceSave() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ if (command.size() != 1) {
+ result.AppendError("a single path to a directory where the trace bundle "
+ "will be created is required");
+ return false;
+ }
+
+ FileSpec bundle_dir(command[0].ref());
+ FileSystem::Instance().Resolve(bundle_dir);
+
+ ProcessSP process_sp = m_exe_ctx.GetProcessSP();
+
+ TraceSP trace_sp = process_sp->GetTarget().GetTrace();
+
+ if (llvm::Expected<FileSpec> desc_file =
+ trace_sp->SaveToDisk(bundle_dir, m_options.m_compact)) {
+ result.AppendMessageWithFormatv(
+ "Trace bundle description file written to: {0}", *desc_file);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ } else {
+ result.AppendError(toString(desc_file.takeError()));
+ }
+
+ return result.Succeeded();
+ }
+
+ CommandOptions m_options;
+};
+
// CommandObjectTraceLoad
#define LLDB_OPTIONS_trace_load
#include "CommandOptions.inc"
@@ -75,11 +177,19 @@ public:
: CommandObjectParsed(
interpreter, "trace load",
"Load a post-mortem processor trace session from a trace bundle.",
- "trace load") {
- CommandArgumentData session_file_arg{eArgTypePath, eArgRepeatPlain};
+ "trace load <trace_description_file>") {
+ CommandArgumentData session_file_arg{eArgTypeFilename, eArgRepeatPlain};
m_arguments.push_back({session_file_arg});
}
+ void
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
+ request, nullptr);
+ }
+
~CommandObjectTraceLoad() override = default;
Options *GetOptions() override { return &m_options; }
@@ -284,6 +394,8 @@ CommandObjectTrace::CommandObjectTrace(CommandInterpreter &interpreter)
CommandObjectSP(new CommandObjectTraceLoad(interpreter)));
LoadSubCommand("dump",
CommandObjectSP(new CommandObjectTraceDump(interpreter)));
+ LoadSubCommand("save",
+ CommandObjectSP(new CommandObjectTraceSave(interpreter)));
LoadSubCommand("schema",
CommandObjectSP(new CommandObjectTraceSchema(interpreter)));
}
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index 7755daa878be..7981917fd8b5 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -300,6 +300,11 @@ let Command = "breakpoint command delete" in {
let Command = "disassemble" in {
def disassemble_options_bytes : Option<"bytes", "b">,
Desc<"Show opcode bytes when disassembling.">;
+ def disassemble_options_kind : Option<"kind", "k">,
+ Desc<"Show instruction control flow kind. Refer to the enum "
+ "`InstructionControlFlowKind` for a list of control flow kind. "
+ "As an important note, far jumps, far calls and far returns often indicate "
+ "calls to and from kernel.">;
def disassemble_options_context : Option<"context", "C">, Arg<"NumLines">,
Desc<"Number of context lines of source to show.">;
def disassemble_options_mixed : Option<"mixed", "m">,
@@ -783,14 +788,6 @@ let Command = "process save_core" in {
"This allows core files to be saved in different formats.">;
}
-let Command = "process trace save" in {
- def process_trace_save_directory: Option<"directory", "d">,
- Group<1>,
- Arg<"Value">, Required,
- Desc<"The directory where the trace will be saved."
- "It will be created if it does not exist.">;
-}
-
let Command = "script import" in {
def script_import_allow_reload : Option<"allow-reload", "r">, Group<1>,
Desc<"Allow the script to be loaded even if it was already loaded before. "
@@ -1150,6 +1147,11 @@ let Command = "thread trace dump instructions" in {
def thread_trace_dump_instructions_pretty_print: Option<"pretty-json", "J">,
Group<1>,
Desc<"Dump in JSON format but pretty printing the output for easier readability.">;
+ def thread_trace_dump_instructions_show_kind : Option<"kind", "k">, Group<1>,
+ Desc<"Show instruction control flow kind. Refer to the enum "
+ "`InstructionControlFlowKind` for a list of control flow kind. "
+ "As an important note, far jumps, far calls and far returns often indicate "
+ "calls to and from kernel.">;
def thread_trace_dump_instructions_show_tsc : Option<"tsc", "t">, Group<1>,
Desc<"For each instruction, print the corresponding timestamp counter if "
"available.">;
@@ -1167,6 +1169,8 @@ let Command = "thread trace dump instructions" in {
let Command = "thread trace dump info" in {
def thread_trace_dump_info_verbose : Option<"verbose", "v">, Group<1>,
Desc<"show verbose thread trace dump info">;
+ def thread_trace_dump_info_json: Option<"json", "j">, Group<1>,
+ Desc<"Dump in JSON format.">;
}
let Command = "type summary add" in {
@@ -1349,6 +1353,14 @@ let Command = "trace load" in {
"implementation.">;
}
+let Command = "trace save" in {
+ def trace_save_compact: Option<"compact", "c">,
+ Group<1>,
+ Desc<"Try not to save to disk information irrelevant to the traced "
+ "processes. Each trace plug-in implements this in a different "
+ "fashion.">;
+}
+
let Command = "trace dump" in {
def trace_dump_verbose : Option<"verbose", "v">, Group<1>,
Desc<"Show verbose trace information.">;