aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-03-20 11:40:34 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-05-14 11:43:05 +0000
commit349cc55c9796c4596a5b9904cd3281af295f878f (patch)
tree410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
parentcb2ae6163174b90e999326ecec3699ee093a5d43 (diff)
parentc0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff)
Diffstat (limited to 'contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp166
1 files changed, 139 insertions, 27 deletions
diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
index 7aaba3731500..5fd1718e8484 100644
--- a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
@@ -159,7 +159,12 @@ protected:
// If our listener is nullptr, users aren't allows to launch
ModuleSP exe_module_sp = target->GetExecutableModule();
- if (exe_module_sp == nullptr) {
+ // If the target already has an executable module, then use that. If it
+ // doesn't then someone must be trying to launch using a path that will
+ // make sense to the remote stub, but doesn't exist on the local host.
+ // In that case use the ExecutableFile that was set in the target's
+ // ProcessLaunchInfo.
+ if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) {
result.AppendError("no file in target, create a debug target using the "
"'target create' command");
return false;
@@ -170,8 +175,6 @@ protected:
if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
return false;
- llvm::StringRef target_settings_argv0 = target->GetArg0();
-
// Determine whether we will disable ASLR or leave it in the default state
// (i.e. enabled if the platform supports it). First check if the process
// launch options explicitly turn on/off
@@ -216,14 +219,22 @@ protected:
m_options.launch_info.GetEnvironment().insert(target_env.begin(),
target_env.end());
+ llvm::StringRef target_settings_argv0 = target->GetArg0();
+
if (!target_settings_argv0.empty()) {
m_options.launch_info.GetArguments().AppendArgument(
target_settings_argv0);
- m_options.launch_info.SetExecutableFile(
- exe_module_sp->GetPlatformFileSpec(), false);
+ if (exe_module_sp)
+ m_options.launch_info.SetExecutableFile(
+ exe_module_sp->GetPlatformFileSpec(), false);
+ else
+ m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false);
} else {
- m_options.launch_info.SetExecutableFile(
- exe_module_sp->GetPlatformFileSpec(), true);
+ if (exe_module_sp)
+ m_options.launch_info.SetExecutableFile(
+ exe_module_sp->GetPlatformFileSpec(), true);
+ else
+ m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true);
}
if (launch_args.GetArgumentCount() == 0) {
@@ -250,11 +261,20 @@ protected:
llvm::StringRef data = stream.GetString();
if (!data.empty())
result.AppendMessage(data);
- const char *archname =
- exe_module_sp->GetArchitecture().GetArchitectureName();
- result.AppendMessageWithFormat(
- "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
- exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
+ // If we didn't have a local executable, then we wouldn't have had an
+ // executable module before launch.
+ if (!exe_module_sp)
+ exe_module_sp = target->GetExecutableModule();
+ if (!exe_module_sp) {
+ result.AppendWarning("Could not get executable module after launch.");
+ } else {
+
+ const char *archname =
+ exe_module_sp->GetArchitecture().GetArchitectureName();
+ result.AppendMessageWithFormat(
+ "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
+ exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
+ }
result.SetStatus(eReturnStatusSuccessFinishResult);
result.SetDidChangeProcessState(true);
} else {
@@ -398,9 +418,10 @@ protected:
}
StreamString stream;
+ ProcessSP process_sp;
const auto error = target->Attach(m_options.attach_info, &stream);
if (error.Success()) {
- ProcessSP process_sp(target->GetProcessSP());
+ process_sp = target->GetProcessSP();
if (process_sp) {
result.AppendMessage(stream.GetString());
result.SetStatus(eReturnStatusSuccessFinishNoResult);
@@ -452,8 +473,13 @@ protected:
// This supports the use-case scenario of immediately continuing the
// process once attached.
- if (m_options.attach_info.GetContinueOnceAttached())
- m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
+ if (m_options.attach_info.GetContinueOnceAttached()) {
+ // We have made a process but haven't told the interpreter about it yet,
+ // so CheckRequirements will fail for "process continue". Set the override
+ // here:
+ ExecutionContext exe_ctx(process_sp);
+ m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result);
+ }
return result.Succeeded();
}
@@ -1166,7 +1192,9 @@ protected:
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"}};
+ "Create a corefile with only modified memory saved"},
+ {eSaveCoreStackOnly, "stack",
+ "Create a corefile with only stack memory saved"}};
static constexpr OptionEnumValues SaveCoreStyles() {
return OptionEnumValues(g_corefile_save_style);
@@ -1178,12 +1206,13 @@ static constexpr OptionEnumValues SaveCoreStyles() {
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 [-s corefile-style] FILE",
- eCommandRequiresProcess | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched) {}
+ : CommandObjectParsed(
+ interpreter, "process save-core",
+ "Save the current process as a core file using an "
+ "appropriate file type.",
+ "process save-core [-s corefile-style -p plugin-name] FILE",
+ eCommandRequiresProcess | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched) {}
~CommandObjectProcessSaveCore() override = default;
@@ -1206,6 +1235,9 @@ public:
Status error;
switch (short_option) {
+ case 'p':
+ m_requested_plugin_name = option_arg.str();
+ break;
case 's':
m_requested_save_core_style =
(lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
@@ -1221,10 +1253,12 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_requested_save_core_style = eSaveCoreUnspecified;
+ m_requested_plugin_name.clear();
}
// Instance variables to hold the values for command options.
SaveCoreStyle m_requested_save_core_style;
+ std::string m_requested_plugin_name;
};
protected:
@@ -1235,13 +1269,15 @@ protected:
FileSpec output_file(command.GetArgumentAtIndex(0));
SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
Status error =
- PluginManager::SaveCore(process_sp, output_file, corefile_style);
+ PluginManager::SaveCore(process_sp, output_file, corefile_style,
+ m_options.m_requested_plugin_name);
if (error.Success()) {
- if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) {
+ if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly ||
+ corefile_style == SaveCoreStyle::eSaveCoreStackOnly) {
result.AppendMessageWithFormat(
- "\nModified-memory only corefile "
- "created. This corefile may not show \n"
- "library/framework/app binaries "
+ "\nModified-memory or stack-memory only corefile "
+ "created. This corefile may \n"
+ "not show library/framework/app binaries "
"on a different system, or when \n"
"those binaries have "
"been updated/modified. Copies are not included\n"
@@ -1641,6 +1677,80 @@ 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() : Options() { 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:
@@ -1678,6 +1788,8 @@ 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(