[lldb/Commands] Refactor ProcessLaunchCommandOptions to use TableGen (NFC)

This patch refactors the current implementation of
`ProcessLaunchCommandOptions` to be generated by TableGen.

The patch also renames the class to `CommandOptionsProcessLaunch` to
align better with the rest of the codebase style and moves it to
separate files.

Differential Review: https://reviews.llvm.org/D95059

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>
This commit is contained in:
Med Ismail Bennani 2021-01-20 18:33:00 +01:00
parent 4c1eaf26ae
commit 7169d3a315
8 changed files with 232 additions and 198 deletions

View File

@ -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"
@ -210,32 +209,6 @@ protected:
// call SBProcess::Stop() to cancel attach)
};
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<OptionDefinition> 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.)

View File

@ -37,6 +37,7 @@ add_lldb_library(lldbCommands
CommandObjectVersion.cpp
CommandObjectWatchpoint.cpp
CommandObjectWatchpointCommand.cpp
CommandOptionsProcessLaunch.cpp
LINK_LIBS
lldbBase

View File

@ -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 @@ protected:
return result.Succeeded();
}
ProcessLaunchCommandOptions m_options;
CommandOptionsProcessLaunch m_options;
};
// "platform process list"

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "CommandObjectProcess.h"
#include "CommandOptionsProcessLaunch.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
@ -251,7 +252,7 @@ protected:
return result.Succeeded();
}
ProcessLaunchCommandOptions m_options;
CommandOptionsProcessLaunch m_options;
};
#define LLDB_OPTIONS_process_attach

View File

@ -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() ? "<null>" : 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() ? "<null>" : 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<OptionDefinition> CommandOptionsProcessLaunch::GetDefinitions() {
return llvm::makeArrayRef(g_process_launch_options);
}

View File

@ -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<lldb_private::OptionDefinition> 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

View File

@ -644,6 +644,37 @@ let Command = "platform shell" in {
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 <path> 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 <filename>.">;
def process_launch_stdout : Option<"stdout", "o">, Group<1>,
Arg<"Filename">, Desc<"Redirect stdout for the process to <filename>.">;
def process_launch_stderr : Option<"stderr", "e">, Group<1>,
Arg<"Filename">, Desc<"Redirect stderr for the process to <filename>.">;
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.">;

View File

@ -307,175 +307,6 @@ void ProcessProperties::SetOSPluginReportsAllThreads(bool does_report) {
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() ? "<null>" : 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() ? "<null>" : 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 <path> 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 <filename>."},
{LLDB_OPT_SET_1, false, "stdout", 'o', OptionParser::eRequiredArgument,
nullptr, {}, 0, eArgTypeFilename,
"Redirect stdout for the process to <filename>."},
{LLDB_OPT_SET_1, false, "stderr", 'e', OptionParser::eRequiredArgument,
nullptr, {}, 0, eArgTypeFilename,
"Redirect stderr for the process to <filename>."},
{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<OptionDefinition> ProcessLaunchCommandOptions::GetDefinitions() {
return llvm::makeArrayRef(g_process_launch_options);
}
ProcessSP Process::FindPlugin(lldb::TargetSP target_sp,
llvm::StringRef plugin_name,
ListenerSP listener_sp,