diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -30,7 +30,6 @@ #include "lldb/Host/HostThread.h" #include "lldb/Host/ProcessLaunchInfo.h" #include "lldb/Host/ProcessRunLock.h" -#include "lldb/Interpreter/Options.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/InstrumentationRuntime.h" @@ -230,32 +229,6 @@ StructuredData::DictionarySP m_scripted_process_dictionary_sp; }; -class ProcessLaunchCommandOptions : public Options { -public: - ProcessLaunchCommandOptions() : Options() { - // Keep default values of all options in one place: OptionParsingStarting - // () - OptionParsingStarting(nullptr); - } - - ~ProcessLaunchCommandOptions() override = default; - - Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, - ExecutionContext *execution_context) override; - - void OptionParsingStarting(ExecutionContext *execution_context) override { - launch_info.Clear(); - disable_aslr = eLazyBoolCalculate; - } - - llvm::ArrayRef GetDefinitions() override; - - // Instance variables to hold the values for command options. - - ProcessLaunchInfo launch_info; - lldb_private::LazyBool disable_aslr; -}; - // This class tracks the Modification state of the process. Things that can // currently modify the program are running the program (which will up the // StopID) and writing memory (which will up the MemoryID.) diff --git a/lldb/source/Commands/CMakeLists.txt b/lldb/source/Commands/CMakeLists.txt --- a/lldb/source/Commands/CMakeLists.txt +++ b/lldb/source/Commands/CMakeLists.txt @@ -38,6 +38,7 @@ CommandObjectVersion.cpp CommandObjectWatchpoint.cpp CommandObjectWatchpointCommand.cpp + CommandOptionsProcessLaunch.cpp LINK_LIBS lldbBase diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "CommandObjectPlatform.h" +#include "CommandOptionsProcessLaunch.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" @@ -1083,7 +1084,7 @@ return result.Succeeded(); } - ProcessLaunchCommandOptions m_options; + CommandOptionsProcessLaunch m_options; }; // "platform process list" diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -8,6 +8,7 @@ #include "CommandObjectProcess.h" #include "CommandObjectProcessScripted.h" +#include "CommandOptionsProcessLaunch.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointSite.h" @@ -253,7 +254,7 @@ return result.Succeeded(); } - ProcessLaunchCommandOptions m_options; + CommandOptionsProcessLaunch m_options; }; #define LLDB_OPTIONS_process_attach diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.h b/lldb/source/Commands/CommandOptionsProcessLaunch.h new file mode 100644 --- /dev/null +++ b/lldb/source/Commands/CommandOptionsProcessLaunch.h @@ -0,0 +1,49 @@ +//===-- CommandOptionsProcessLaunch.h -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_COMMANDS_COMMANDOPTIONSPROCESSLAUNCH_H +#define LLDB_SOURCE_COMMANDS_COMMANDOPTIONSPROCESSLAUNCH_H + +#include "lldb/Host/ProcessLaunchInfo.h" +#include "lldb/Interpreter/Options.h" + +namespace lldb_private { + +// CommandOptionsProcessLaunch + +class CommandOptionsProcessLaunch : public lldb_private::Options { +public: + CommandOptionsProcessLaunch() : lldb_private::Options() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } + + ~CommandOptionsProcessLaunch() override = default; + + lldb_private::Status + SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + lldb_private::ExecutionContext *execution_context) override; + + void OptionParsingStarting( + lldb_private::ExecutionContext *execution_context) override { + launch_info.Clear(); + disable_aslr = lldb_private::eLazyBoolCalculate; + } + + llvm::ArrayRef GetDefinitions() override; + + // Instance variables to hold the values for command options. + + lldb_private::ProcessLaunchInfo launch_info; + lldb_private::LazyBool disable_aslr; +}; // CommandOptionsProcessLaunch + +}; // namespace lldb_private + +#endif // LLDB_SOURCE_COMMANDS_COMMANDOPTIONSPROCESSLAUNCH_H diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp new file mode 100644 --- /dev/null +++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp @@ -0,0 +1,147 @@ +//===-- CommandOptionsProcessLaunch.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CommandOptionsProcessLaunch.h" + +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandCompletions.h" +#include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Target.h" + +#include "llvm/ADT/ArrayRef.h" + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; + +#define LLDB_OPTIONS_process_launch +#include "CommandOptions.inc" + +Status CommandOptionsProcessLaunch::SetOptionValue( + uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 's': // Stop at program entry point + launch_info.GetFlags().Set(eLaunchFlagStopAtEntry); + break; + + case 'i': // STDIN for read only + { + FileAction action; + if (action.Open(STDIN_FILENO, FileSpec(option_arg), true, false)) + launch_info.AppendFileAction(action); + break; + } + + case 'o': // Open STDOUT for write only + { + FileAction action; + if (action.Open(STDOUT_FILENO, FileSpec(option_arg), false, true)) + launch_info.AppendFileAction(action); + break; + } + + case 'e': // STDERR for write only + { + FileAction action; + if (action.Open(STDERR_FILENO, FileSpec(option_arg), false, true)) + launch_info.AppendFileAction(action); + break; + } + + case 'p': // Process plug-in name + launch_info.SetProcessPluginName(option_arg); + break; + + case 'n': // Disable STDIO + { + FileAction action; + const FileSpec dev_null(FileSystem::DEV_NULL); + if (action.Open(STDIN_FILENO, dev_null, true, false)) + launch_info.AppendFileAction(action); + if (action.Open(STDOUT_FILENO, dev_null, false, true)) + launch_info.AppendFileAction(action); + if (action.Open(STDERR_FILENO, dev_null, false, true)) + launch_info.AppendFileAction(action); + break; + } + + case 'w': + launch_info.SetWorkingDirectory(FileSpec(option_arg)); + break; + + case 't': // Open process in new terminal window + launch_info.GetFlags().Set(eLaunchFlagLaunchInTTY); + break; + + case 'a': { + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + PlatformSP platform_sp = + target_sp ? target_sp->GetPlatform() : PlatformSP(); + launch_info.GetArchitecture() = + Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg); + } break; + + case 'A': // Disable ASLR. + { + bool success; + const bool disable_aslr_arg = + OptionArgParser::ToBoolean(option_arg, true, &success); + if (success) + disable_aslr = disable_aslr_arg ? eLazyBoolYes : eLazyBoolNo; + else + error.SetErrorStringWithFormat( + "Invalid boolean value for disable-aslr option: '%s'", + option_arg.empty() ? "" : option_arg.str().c_str()); + break; + } + + case 'X': // shell expand args. + { + bool success; + const bool expand_args = + OptionArgParser::ToBoolean(option_arg, true, &success); + if (success) + launch_info.SetShellExpandArguments(expand_args); + else + error.SetErrorStringWithFormat( + "Invalid boolean value for shell-expand-args option: '%s'", + option_arg.empty() ? "" : option_arg.str().c_str()); + break; + } + + case 'c': + if (!option_arg.empty()) + launch_info.SetShell(FileSpec(option_arg)); + else + launch_info.SetShell(HostInfo::GetDefaultShell()); + break; + + case 'v': + launch_info.GetEnvironment().insert(option_arg); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option character '%c'", + short_option); + break; + } + return error; +} + +llvm::ArrayRef CommandOptionsProcessLaunch::GetDefinitions() { + return llvm::makeArrayRef(g_process_launch_options); +} diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -644,6 +644,37 @@ Desc<"Shell interpreter path. This is the binary used to run the command.">; } +let Command = "process launch" in { + def process_launch_stop_at_entry : Option<"stop-at-entry", "s">, + Desc<"Stop at the entry point of the program when launching a process.">; + def process_launch_disable_aslr : Option<"disable-aslr", "A">, Arg<"Boolean">, + Desc<"Set whether to disable address space layout randomization when launching a process.">; + def process_launch_plugin : Option<"plugin", "P">, Arg<"Plugin">, + Desc<"Name of the process plugin you want to use.">; + def process_launch_working_dir : Option<"working-dir", "w">, Arg<"DirectoryName">, + Desc<"Set the current working directory to when running the inferior.">; + def process_launch_arch : Option<"arch", "a">, Arg<"Architecture">, + Desc<"Set the architecture for the process to launch when ambiguous.">; + def process_launch_environment : Option<"environment", "v">, + Arg<"None">, Desc<"Specify an environment variable name/value string " + "(--environment NAME=VALUE). Can be specified multiple times for subsequent " + "environment entries.">; + def process_launch_shell : Option<"shell", "c">, GroupRange<1,3>, + OptionalArg<"Filename">, Desc<"Run the process in a shell (not supported on all platforms).">; + def process_launch_stdin : Option<"stdin", "i">, Group<1>, + Arg<"Filename">, Desc<"Redirect stdin for the process to .">; + def process_launch_stdout : Option<"stdout", "o">, Group<1>, + Arg<"Filename">, Desc<"Redirect stdout for the process to .">; + def process_launch_stderr : Option<"stderr", "e">, Group<1>, + Arg<"Filename">, Desc<"Redirect stderr for the process to .">; + def process_launch_tty : Option<"tty", "t">, Group<2>, + Desc<"Start the process in a terminal (not supported on all platforms).">; + def process_launch_no_stdio : Option<"no-stdio", "n">, Group<3>, + Desc<"Do not set up for terminal I/O to go to running process.">; + def process_launch_shell_expand_args : Option<"shell-expand-args", "X">, Group<4>, + Arg<"Boolean">, Desc<"Set whether to shell expand arguments to the process when launching.">; +} + let Command = "process attach" in { def process_attach_continue : Option<"continue", "c">, Desc<"Immediately continue the process once attached.">; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -307,175 +307,6 @@ nullptr, ePropertyOSPluginReportsAllThreads, does_report); } -Status ProcessLaunchCommandOptions::SetOptionValue( - uint32_t option_idx, llvm::StringRef option_arg, - ExecutionContext *execution_context) { - Status error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) { - case 's': // Stop at program entry point - launch_info.GetFlags().Set(eLaunchFlagStopAtEntry); - break; - - case 'i': // STDIN for read only - { - FileAction action; - if (action.Open(STDIN_FILENO, FileSpec(option_arg), true, false)) - launch_info.AppendFileAction(action); - break; - } - - case 'o': // Open STDOUT for write only - { - FileAction action; - if (action.Open(STDOUT_FILENO, FileSpec(option_arg), false, true)) - launch_info.AppendFileAction(action); - break; - } - - case 'e': // STDERR for write only - { - FileAction action; - if (action.Open(STDERR_FILENO, FileSpec(option_arg), false, true)) - launch_info.AppendFileAction(action); - break; - } - - case 'p': // Process plug-in name - launch_info.SetProcessPluginName(option_arg); - break; - - case 'n': // Disable STDIO - { - FileAction action; - const FileSpec dev_null(FileSystem::DEV_NULL); - if (action.Open(STDIN_FILENO, dev_null, true, false)) - launch_info.AppendFileAction(action); - if (action.Open(STDOUT_FILENO, dev_null, false, true)) - launch_info.AppendFileAction(action); - if (action.Open(STDERR_FILENO, dev_null, false, true)) - launch_info.AppendFileAction(action); - break; - } - - case 'w': - launch_info.SetWorkingDirectory(FileSpec(option_arg)); - break; - - case 't': // Open process in new terminal window - launch_info.GetFlags().Set(eLaunchFlagLaunchInTTY); - break; - - case 'a': { - TargetSP target_sp = - execution_context ? execution_context->GetTargetSP() : TargetSP(); - PlatformSP platform_sp = - target_sp ? target_sp->GetPlatform() : PlatformSP(); - launch_info.GetArchitecture() = - Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg); - } break; - - case 'A': // Disable ASLR. - { - bool success; - const bool disable_aslr_arg = - OptionArgParser::ToBoolean(option_arg, true, &success); - if (success) - disable_aslr = disable_aslr_arg ? eLazyBoolYes : eLazyBoolNo; - else - error.SetErrorStringWithFormat( - "Invalid boolean value for disable-aslr option: '%s'", - option_arg.empty() ? "" : option_arg.str().c_str()); - break; - } - - case 'X': // shell expand args. - { - bool success; - const bool expand_args = - OptionArgParser::ToBoolean(option_arg, true, &success); - if (success) - launch_info.SetShellExpandArguments(expand_args); - else - error.SetErrorStringWithFormat( - "Invalid boolean value for shell-expand-args option: '%s'", - option_arg.empty() ? "" : option_arg.str().c_str()); - break; - } - - case 'c': - if (!option_arg.empty()) - launch_info.SetShell(FileSpec(option_arg)); - else - launch_info.SetShell(HostInfo::GetDefaultShell()); - break; - - case 'v': - launch_info.GetEnvironment().insert(option_arg); - break; - - default: - error.SetErrorStringWithFormat("unrecognized short option character '%c'", - short_option); - break; - } - return error; -} - -static constexpr OptionDefinition g_process_launch_options[] = { - {LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument, - nullptr, {}, 0, eArgTypeNone, - "Stop at the entry point of the program when launching a process."}, - {LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', - OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, - "Set whether to disable address space layout randomization when launching " - "a process."}, - {LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, - nullptr, {}, 0, eArgTypePlugin, - "Name of the process plugin you want to use."}, - {LLDB_OPT_SET_ALL, false, "working-dir", 'w', - OptionParser::eRequiredArgument, nullptr, {}, 0, - eArgTypeDirectoryName, - "Set the current working directory to when running the inferior."}, - {LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument, - nullptr, {}, 0, eArgTypeArchitecture, - "Set the architecture for the process to launch when ambiguous."}, - {LLDB_OPT_SET_ALL, false, "environment", 'v', - OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, - "Specify an environment variable name/value string (--environment " - "NAME=VALUE). Can be specified multiple times for subsequent environment " - "entries."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "shell", 'c', - OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeFilename, - "Run the process in a shell (not supported on all platforms)."}, - - {LLDB_OPT_SET_1, false, "stdin", 'i', OptionParser::eRequiredArgument, - nullptr, {}, 0, eArgTypeFilename, - "Redirect stdin for the process to ."}, - {LLDB_OPT_SET_1, false, "stdout", 'o', OptionParser::eRequiredArgument, - nullptr, {}, 0, eArgTypeFilename, - "Redirect stdout for the process to ."}, - {LLDB_OPT_SET_1, false, "stderr", 'e', OptionParser::eRequiredArgument, - nullptr, {}, 0, eArgTypeFilename, - "Redirect stderr for the process to ."}, - - {LLDB_OPT_SET_2, false, "tty", 't', OptionParser::eNoArgument, nullptr, - {}, 0, eArgTypeNone, - "Start the process in a terminal (not supported on all platforms)."}, - - {LLDB_OPT_SET_3, false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr, - {}, 0, eArgTypeNone, - "Do not set up for terminal I/O to go to running process."}, - {LLDB_OPT_SET_4, false, "shell-expand-args", 'X', - OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, - "Set whether to shell expand arguments to the process when launching."}, -}; - -llvm::ArrayRef ProcessLaunchCommandOptions::GetDefinitions() { - return llvm::makeArrayRef(g_process_launch_options); -} - ProcessSP Process::FindPlugin(lldb::TargetSP target_sp, llvm::StringRef plugin_name, ListenerSP listener_sp,