aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-08-22 19:00:43 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-11-13 20:39:49 +0000
commitfe6060f10f634930ff71b7c50291ddc610da2475 (patch)
tree1483580c790bd4d27b6500a7542b5ee00534d3cc /contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
parentb61bce17f346d79cecfd8f195a64b10f77be43b1 (diff)
parent344a3780b2e33f6ca763666c380202b18aab72a3 (diff)
Diffstat (limited to 'contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp221
1 files changed, 176 insertions, 45 deletions
diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
index 35835f638557..7aaba3731500 100644
--- a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectProcess.h"
+#include "CommandObjectTrace.h"
#include "CommandOptionsProcessLaunch.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -17,6 +18,7 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
@@ -27,6 +29,8 @@
#include "lldb/Utility/Args.h"
#include "lldb/Utility/State.h"
+#include <bitset>
+
using namespace lldb;
using namespace lldb_private;
@@ -77,7 +81,6 @@ protected:
result.AppendErrorWithFormat(
"Failed to detach from process: %s\n",
detach_error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
Status destroy_error(process->Destroy(false));
@@ -87,7 +90,6 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to kill process: %s\n",
destroy_error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
}
@@ -108,7 +110,14 @@ public:
interpreter, "process launch",
"Launch the executable in the debugger.", nullptr,
eCommandRequiresTarget, "restart"),
- m_options() {
+ m_options(),
+ m_class_options("scripted process", true, 'C', 'k', 'v', 0),
+ m_all_options() {
+ m_all_options.Append(&m_options);
+ m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
+ LLDB_OPT_SET_ALL);
+ m_all_options.Finalize();
+
CommandArgumentEntry arg;
CommandArgumentData run_args_arg;
@@ -135,7 +144,7 @@ public:
request, nullptr);
}
- Options *GetOptions() override { return &m_options; }
+ Options *GetOptions() override { return &m_all_options; }
const char *GetRepeatCommand(Args &current_command_args,
uint32_t index) override {
@@ -153,7 +162,6 @@ protected:
if (exe_module_sp == nullptr) {
result.AppendError("no file in target, create a debug target using the "
"'target create' command");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -180,6 +188,15 @@ protected:
disable_aslr = target->GetDisableASLR();
}
+ if (!m_class_options.GetName().empty()) {
+ m_options.launch_info.SetProcessPluginName("ScriptedProcess");
+ m_options.launch_info.SetScriptedProcessClassName(
+ m_class_options.GetName());
+ m_options.launch_info.SetScriptedProcessDictionarySP(
+ m_class_options.GetStructuredData());
+ target->SetProcessLaunchInfo(m_options.launch_info);
+ }
+
if (disable_aslr)
m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
else
@@ -243,16 +260,16 @@ protected:
} else {
result.AppendError(
"no error returned from Target::Launch, and target has no process");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
CommandOptionsProcessLaunch m_options;
+ OptionGroupPythonClassWithDict m_class_options;
+ OptionGroupOptions m_all_options;
};
#define LLDB_OPTIONS_process_attach
@@ -377,11 +394,9 @@ protected:
if (command.GetArgumentCount()) {
result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
- m_interpreter.UpdateExecutionContext(nullptr);
StreamString stream;
const auto error = target->Attach(m_options.attach_info, &stream);
if (error.Success()) {
@@ -393,11 +408,9 @@ protected:
} else {
result.AppendError(
"no error returned from Target::Attach, and target has no process");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
if (!result.Succeeded())
@@ -517,7 +530,6 @@ protected:
result.AppendErrorWithFormat(
"The '%s' command does not take any arguments.\n",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -589,13 +601,11 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to resume process: %s.\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat(
"Process cannot be continued from its current state (%s).\n",
StateAsCString(state));
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -687,7 +697,6 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
return false;
}
return result.Succeeded();
@@ -759,7 +768,6 @@ protected:
result.AppendErrorWithFormat(
"'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -769,7 +777,6 @@ protected:
"Process %" PRIu64
" is currently being debugged, kill the process before connecting.\n",
process->GetID());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -791,7 +798,6 @@ protected:
error);
if (error.Fail() || process_sp == nullptr) {
result.AppendError(error.AsCString("Error connecting to the process"));
- result.SetStatus(eReturnStatusFailed);
return false;
}
return true;
@@ -931,7 +937,6 @@ protected:
result.AppendErrorWithFormat("failed to load '%s': %s",
image_path.str().c_str(),
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
return result.Succeeded();
@@ -983,7 +988,6 @@ protected:
if (entry.ref().getAsInteger(0, image_token)) {
result.AppendErrorWithFormat("invalid image index argument '%s'",
entry.ref().str().c_str());
- result.SetStatus(eReturnStatusFailed);
break;
} else {
Status error(process->GetTarget().GetPlatform()->UnloadImage(
@@ -995,7 +999,6 @@ protected:
} else {
result.AppendErrorWithFormat("failed to unload image: %s",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
break;
}
}
@@ -1040,7 +1043,7 @@ public:
UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
int signo = signals->GetFirstSignalNumber();
while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
- request.AddCompletion(signals->GetSignalAsCString(signo), "");
+ request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo));
signo = signals->GetNextSignalNumber(signo);
}
}
@@ -1062,7 +1065,6 @@ protected:
if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
command.GetArgumentAtIndex(0));
- result.SetStatus(eReturnStatusFailed);
} else {
Status error(process->Signal(signo));
if (error.Success()) {
@@ -1070,14 +1072,12 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
}
} else {
result.AppendErrorWithFormat(
"'%s' takes exactly one signal number argument:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1102,7 +1102,6 @@ protected:
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
result.AppendError("no process to halt");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1114,12 +1113,10 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to halt process: %s\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1144,7 +1141,6 @@ protected:
Process *process = m_exe_ctx.GetProcessPtr();
if (process == nullptr) {
result.AppendError("no process to kill");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1155,12 +1151,10 @@ protected:
} else {
result.AppendErrorWithFormat("Failed to kill process: %s\n",
error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
}
@@ -1169,45 +1163,109 @@ protected:
// CommandObjectProcessSaveCore
#pragma mark CommandObjectProcessSaveCore
+static constexpr OptionEnumValueElement g_corefile_save_style[] = {
+ {eSaveCoreFull, "full", "Create a core file with all memory saved"},
+ {eSaveCoreDirtyOnly, "modified-memory",
+ "Create a corefile with only modified memory saved"}};
+
+static constexpr OptionEnumValues SaveCoreStyles() {
+ return OptionEnumValues(g_corefile_save_style);
+}
+
+#define LLDB_OPTIONS_process_save_core
+#include "CommandOptions.inc"
+
class CommandObjectProcessSaveCore : public CommandObjectParsed {
public:
CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "process save-core",
"Save the current process as a core file using an "
"appropriate file type.",
- "process save-core FILE",
+ "process save-core [-s corefile-style] FILE",
eCommandRequiresProcess | eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched) {}
~CommandObjectProcessSaveCore() override = default;
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions()
+ : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {}
+
+ ~CommandOptions() override = default;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_process_save_core_options);
+ }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ const int short_option = m_getopt_table[option_idx].val;
+ Status error;
+
+ switch (short_option) {
+ case 's':
+ m_requested_save_core_style =
+ (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
+ option_arg, GetDefinitions()[option_idx].enum_values,
+ eSaveCoreUnspecified, error);
+ break;
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+
+ return {};
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_requested_save_core_style = eSaveCoreUnspecified;
+ }
+
+ // Instance variables to hold the values for command options.
+ SaveCoreStyle m_requested_save_core_style;
+ };
+
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
ProcessSP process_sp = m_exe_ctx.GetProcessSP();
if (process_sp) {
if (command.GetArgumentCount() == 1) {
FileSpec output_file(command.GetArgumentAtIndex(0));
- Status error = PluginManager::SaveCore(process_sp, output_file);
+ SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
+ Status error =
+ PluginManager::SaveCore(process_sp, output_file, corefile_style);
if (error.Success()) {
+ if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) {
+ result.AppendMessageWithFormat(
+ "\nModified-memory only corefile "
+ "created. This corefile may not show \n"
+ "library/framework/app binaries "
+ "on a different system, or when \n"
+ "those binaries have "
+ "been updated/modified. Copies are not included\n"
+ "in this corefile. Use --style full to include all "
+ "process memory.\n");
+ }
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
result.AppendErrorWithFormat(
"Failed to save core file for process: %s\n", error.AsCString());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
m_cmd_name.c_str(), m_cmd_syntax.c_str());
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("invalid process");
- result.SetStatus(eReturnStatusFailed);
return false;
}
return result.Succeeded();
}
+
+ CommandOptions m_options;
};
// CommandObjectProcessStatus
@@ -1231,7 +1289,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_verbose(false) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -1259,7 +1317,7 @@ public:
}
// Instance variables to hold the values for command options.
- bool m_verbose;
+ bool m_verbose = false;
};
protected:
@@ -1269,7 +1327,6 @@ protected:
if (command.GetArgumentCount()) {
result.AppendError("'process status' takes no arguments");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1286,10 +1343,21 @@ protected:
num_frames, num_frames_with_source, stop_format);
if (m_options.m_verbose) {
+ addr_t code_mask = process->GetCodeAddressMask();
+ addr_t data_mask = process->GetDataAddressMask();
+ if (code_mask != 0) {
+ int bits = std::bitset<64>(~code_mask).count();
+ result.AppendMessageWithFormat(
+ "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
+ result.AppendMessageWithFormat(
+ "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
+ result.AppendMessageWithFormat(
+ "Number of bits used in addressing (code): %d\n", bits);
+ }
+
PlatformSP platform_sp = process->GetTarget().GetPlatform();
if (!platform_sp) {
result.AppendError("Couldn'retrieve the target's platform");
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1298,7 +1366,6 @@ protected:
if (!expected_crash_info) {
result.AppendError(llvm::toString(expected_crash_info.takeError()));
- result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
}
@@ -1467,7 +1534,6 @@ protected:
if (!process_sp) {
result.AppendError("No current process; cannot handle signals until you "
"have a valid process.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1479,7 +1545,6 @@ protected:
!VerifyCommandOptionValue(m_options.stop, stop_action)) {
result.AppendError("Invalid argument for command option --stop; must be "
"true or false.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1487,7 +1552,6 @@ protected:
!VerifyCommandOptionValue(m_options.notify, notify_action)) {
result.AppendError("Invalid argument for command option --notify; must "
"be true or false.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1495,7 +1559,6 @@ protected:
!VerifyCommandOptionValue(m_options.pass, pass_action)) {
result.AppendError("Invalid argument for command option --pass; must be "
"true or false.\n");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -1559,6 +1622,71 @@ protected:
CommandOptions m_options;
};
+// Next are the subcommands of CommandObjectMultiwordProcessTrace
+
+// CommandObjectProcessTraceStart
+class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {
+public:
+ CommandObjectProcessTraceStart(CommandInterpreter &interpreter)
+ : CommandObjectTraceProxy(
+ /*live_debug_session_only*/ true, interpreter,
+ "process trace start",
+ "Start tracing this process with the corresponding trace "
+ "plug-in.",
+ "process trace start [<trace-options>]") {}
+
+protected:
+ lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
+ return trace.GetProcessTraceStartCommand(m_interpreter);
+ }
+};
+
+// CommandObjectProcessTraceStop
+class CommandObjectProcessTraceStop : public CommandObjectParsed {
+public:
+ CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process trace stop",
+ "Stop tracing this process. This does not affect "
+ "traces started with the "
+ "\"thread trace start\" command.",
+ "process trace stop",
+ eCommandRequiresProcess | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused |
+ eCommandProcessMustBeTraced) {}
+
+ ~CommandObjectProcessTraceStop() override = default;
+
+ 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->Stop())
+ result.AppendError(toString(std::move(err)));
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ return result.Succeeded();
+ }
+};
+
+// CommandObjectMultiwordProcessTrace
+class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
+public:
+ CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "trace", "Commands for tracing the current process.",
+ "process trace <subcommand> [<subcommand objects>]") {
+ LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
+ interpreter)));
+ LoadSubCommand("stop", CommandObjectSP(
+ new CommandObjectProcessTraceStop(interpreter)));
+ }
+
+ ~CommandObjectMultiwordProcessTrace() override = default;
+};
+
// CommandObjectMultiwordProcess
CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
@@ -1595,6 +1723,9 @@ CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
interpreter)));
+ LoadSubCommand(
+ "trace",
+ CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
}
CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;