forked from OSchip/llvm-project
[lldb] Port lldb gdb-server to libOption
The existing help text was very terse and was missing several important options. In the new version, I add a short description of each option and a slightly longer description of the tool as a whole. The new option list does not include undocumented no-op options: --debug and --verbose. It also does not include undocumented short aliases for long options, with two exceptions: -h, because it's well-known; and -S (--setsid), as it's used in one test. Using these options will now produce an error. I believe that is acceptable as users aren't generally invoking lldb-server directly, and the only way to learn about the short aliases was by looking at the source. Differential Revision: https://reviews.llvm.org/D89477
This commit is contained in:
parent
0784e17f1b
commit
fa5fa63fd1
lldb
include/lldb/Utility
source/Utility
test/Shell/lldb-server
tools/lldb-server
|
@ -66,6 +66,7 @@ public:
|
||||||
|
|
||||||
Args(const Args &rhs);
|
Args(const Args &rhs);
|
||||||
explicit Args(const StringList &list);
|
explicit Args(const StringList &list);
|
||||||
|
explicit Args(llvm::ArrayRef<llvm::StringRef> args);
|
||||||
|
|
||||||
Args &operator=(const Args &rhs);
|
Args &operator=(const Args &rhs);
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,11 @@ Args::Args(const StringList &list) : Args() {
|
||||||
AppendArgument(arg);
|
AppendArgument(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Args::Args(llvm::ArrayRef<llvm::StringRef> args) : Args() {
|
||||||
|
for (llvm::StringRef arg : args)
|
||||||
|
AppendArgument(arg);
|
||||||
|
}
|
||||||
|
|
||||||
Args &Args::operator=(const Args &rhs) {
|
Args &Args::operator=(const Args &rhs) {
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
RUN: lldb-server gdbserver --fd 2>&1 | FileCheck --check-prefixes=FD1,ALL %s
|
||||||
|
FD1: error: --fd: missing argument
|
||||||
|
|
||||||
|
RUN: lldb-server gdbserver --fd three 2>&1 | FileCheck --check-prefixes=FD2,ALL %s
|
||||||
|
FD2: error: invalid '--fd' argument
|
||||||
|
|
||||||
|
RUN: lldb-server gdbserver --bogus 2>&1 | FileCheck --check-prefixes=BOGUS,ALL %s
|
||||||
|
BOGUS: error: unknown argument '--bogus'
|
||||||
|
|
||||||
|
RUN: lldb-server gdbserver 2>&1 | FileCheck --check-prefixes=CONN,ALL %s
|
||||||
|
CONN: error: no connection arguments
|
||||||
|
|
||||||
|
ALL: Use '{{.*}} g[dbserver] --help' for a complete list of options.
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
set(LLVM_TARGET_DEFINITIONS LLGSOptions.td)
|
||||||
|
tablegen(LLVM LLGSOptions.inc -gen-opt-parser-defs)
|
||||||
|
add_public_tablegen_target(LLGSOptionsTableGen)
|
||||||
|
set_target_properties(LLGSOptionsTableGen PROPERTIES FOLDER "lldb misc")
|
||||||
|
|
||||||
set(LLDB_PLUGINS)
|
set(LLDB_PLUGINS)
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
|
||||||
|
@ -53,8 +58,13 @@ add_lldb_tool(lldb-server
|
||||||
${LLDB_SYSTEM_LIBS}
|
${LLDB_SYSTEM_LIBS}
|
||||||
|
|
||||||
LINK_COMPONENTS
|
LINK_COMPONENTS
|
||||||
|
Option
|
||||||
Support
|
Support
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_dependencies(lldb-server
|
||||||
|
LLGSOptionsTableGen
|
||||||
|
${tablegen_deps}
|
||||||
|
)
|
||||||
target_include_directories(lldb-server PRIVATE "${LLDB_SOURCE_DIR}/source")
|
target_include_directories(lldb-server PRIVATE "${LLDB_SOURCE_DIR}/source")
|
||||||
target_link_libraries(lldb-server PRIVATE ${LLDB_SYSTEM_LIBS})
|
target_link_libraries(lldb-server PRIVATE ${LLDB_SYSTEM_LIBS})
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
include "llvm/Option/OptParser.td"
|
||||||
|
|
||||||
|
class F<string name>: Flag<["--", "-"], name>;
|
||||||
|
class R<list<string> prefixes, string name>
|
||||||
|
: Option<prefixes, name, KIND_REMAINING_ARGS>;
|
||||||
|
|
||||||
|
multiclass SJ<string name, string help> {
|
||||||
|
def NAME: Separate<["--", "-"], name>,
|
||||||
|
HelpText<help>;
|
||||||
|
def NAME # _eq: Joined<["--", "-"], name # "=">,
|
||||||
|
Alias<!cast<Separate>(NAME)>;
|
||||||
|
}
|
||||||
|
|
||||||
|
def grp_connect : OptionGroup<"connection">, HelpText<"CONNECTION">;
|
||||||
|
|
||||||
|
defm fd: SJ<"fd", "Communicate over the given file descriptor.">,
|
||||||
|
MetaVarName<"<fd>">,
|
||||||
|
Group<grp_connect>;
|
||||||
|
|
||||||
|
defm named_pipe: SJ<"named-pipe", "Write port lldb-server will listen on to the given named pipe.">,
|
||||||
|
MetaVarName<"<name>">,
|
||||||
|
Group<grp_connect>;
|
||||||
|
|
||||||
|
defm pipe: SJ<"pipe", "Write port lldb-server will listen on to the given file descriptor.">,
|
||||||
|
MetaVarName<"<fd>">,
|
||||||
|
Group<grp_connect>;
|
||||||
|
|
||||||
|
def reverse_connect: F<"reverse-connect">,
|
||||||
|
HelpText<"Connect to the client instead of passively waiting for a connection. In this case [host]:port denotes the remote address to connect to.">,
|
||||||
|
Group<grp_connect>;
|
||||||
|
|
||||||
|
def grp_general : OptionGroup<"general options">, HelpText<"GENERAL OPTIONS">;
|
||||||
|
|
||||||
|
defm log_channels: SJ<"log-channels", "Channels to log. A colon-separated list of entries. Each entry starts with a channel followed by a space-separated list of categories.">,
|
||||||
|
MetaVarName<"<channel1 categories...:channel2 categories...>">,
|
||||||
|
Group<grp_general>;
|
||||||
|
|
||||||
|
defm log_file: SJ<"log-file", "Destination file to log to. If empty, log to stderr.">,
|
||||||
|
MetaVarName<"<file>">,
|
||||||
|
Group<grp_general>;
|
||||||
|
|
||||||
|
def setsid: F<"setsid">, HelpText<"Run lldb-server in a new session.">,
|
||||||
|
Group<grp_general>;
|
||||||
|
def: Flag<["-"], "S">, Alias<setsid>,
|
||||||
|
Group<grp_general>;
|
||||||
|
|
||||||
|
def help: F<"help">, HelpText<"Prints out the usage information for lldb-server.">,
|
||||||
|
Group<grp_general>;
|
||||||
|
def: Flag<["-"], "h">, Alias<help>,
|
||||||
|
Group<grp_general>;
|
||||||
|
|
||||||
|
def grp_target : OptionGroup<"target selection">, HelpText<"TARGET SELECTION">;
|
||||||
|
|
||||||
|
defm attach: SJ<"attach", "Attach to the process given by a (numeric) process id or a name.">,
|
||||||
|
MetaVarName<"<pid-or-name>">,
|
||||||
|
Group<grp_target>;
|
||||||
|
|
||||||
|
def REM : R<["--"], "">, HelpText<"Launch program for debugging.">,
|
||||||
|
MetaVarName<"program args">,
|
||||||
|
Group<grp_target>;
|
||||||
|
|
||||||
|
def: F<"native-regs">; // Noop. Present for backwards compatibility only.
|
|
@ -17,7 +17,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "Acceptor.h"
|
#include "Acceptor.h"
|
||||||
#include "LLDBServerUtilities.h"
|
#include "LLDBServerUtilities.h"
|
||||||
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
|
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
|
||||||
|
@ -25,8 +24,6 @@
|
||||||
#include "lldb/Host/Config.h"
|
#include "lldb/Host/Config.h"
|
||||||
#include "lldb/Host/ConnectionFileDescriptor.h"
|
#include "lldb/Host/ConnectionFileDescriptor.h"
|
||||||
#include "lldb/Host/FileSystem.h"
|
#include "lldb/Host/FileSystem.h"
|
||||||
#include "lldb/Host/HostGetOpt.h"
|
|
||||||
#include "lldb/Host/OptionParser.h"
|
|
||||||
#include "lldb/Host/Pipe.h"
|
#include "lldb/Host/Pipe.h"
|
||||||
#include "lldb/Host/Socket.h"
|
#include "lldb/Host/Socket.h"
|
||||||
#include "lldb/Host/StringConvert.h"
|
#include "lldb/Host/StringConvert.h"
|
||||||
|
@ -34,7 +31,11 @@
|
||||||
#include "lldb/Target/Process.h"
|
#include "lldb/Target/Process.h"
|
||||||
#include "lldb/Utility/Status.h"
|
#include "lldb/Utility/Status.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Option/ArgList.h"
|
||||||
|
#include "llvm/Option/OptTable.h"
|
||||||
|
#include "llvm/Option/Option.h"
|
||||||
#include "llvm/Support/Errno.h"
|
#include "llvm/Support/Errno.h"
|
||||||
|
#include "llvm/Support/WithColor.h"
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#include "Plugins/Process/Linux/NativeProcessLinux.h"
|
#include "Plugins/Process/Linux/NativeProcessLinux.h"
|
||||||
|
@ -88,31 +89,6 @@ public:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// option descriptors for getopt_long_only()
|
|
||||||
|
|
||||||
static int g_debug = 0;
|
|
||||||
static int g_verbose = 0;
|
|
||||||
|
|
||||||
static struct option g_long_options[] = {
|
|
||||||
{"debug", no_argument, &g_debug, 1},
|
|
||||||
{"verbose", no_argument, &g_verbose, 1},
|
|
||||||
{"log-file", required_argument, nullptr, 'l'},
|
|
||||||
{"log-channels", required_argument, nullptr, 'c'},
|
|
||||||
{"attach", required_argument, nullptr, 'a'},
|
|
||||||
{"named-pipe", required_argument, nullptr, 'N'},
|
|
||||||
{"pipe", required_argument, nullptr, 'U'},
|
|
||||||
{"native-regs", no_argument, nullptr,
|
|
||||||
'r'}, // Specify to use the native registers instead of the gdb defaults
|
|
||||||
// for the architecture. NOTE: this is a do-nothing arg as it's
|
|
||||||
// behavior is default now. FIXME remove call from lldb-platform.
|
|
||||||
{"reverse-connect", no_argument, nullptr,
|
|
||||||
'R'}, // Specifies that llgs attaches to the client address:port rather
|
|
||||||
// than llgs listening for a connection from address on port.
|
|
||||||
{"setsid", no_argument, nullptr,
|
|
||||||
'S'}, // Call setsid() to make llgs run in its own session.
|
|
||||||
{"fd", required_argument, nullptr, 'F'},
|
|
||||||
{nullptr, 0, nullptr, 0}};
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// Watch for signals
|
// Watch for signals
|
||||||
static int g_sighup_received_count = 0;
|
static int g_sighup_received_count = 0;
|
||||||
|
@ -129,20 +105,6 @@ static void sighup_handler(MainLoopBase &mainloop) {
|
||||||
}
|
}
|
||||||
#endif // #ifndef _WIN32
|
#endif // #ifndef _WIN32
|
||||||
|
|
||||||
static void display_usage(const char *progname, const char *subcommand) {
|
|
||||||
fprintf(stderr, "Usage:\n %s %s "
|
|
||||||
"[--log-file log-file-name] "
|
|
||||||
"[--log-channels log-channel-list] "
|
|
||||||
"[--setsid] "
|
|
||||||
"[--fd file-descriptor]"
|
|
||||||
"[--named-pipe named-pipe-path] "
|
|
||||||
"[--native-regs] "
|
|
||||||
"[--attach pid] "
|
|
||||||
"[[HOST]:PORT] "
|
|
||||||
"[-- PROGRAM ARG1 ARG2 ...]\n",
|
|
||||||
progname, subcommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_attach_to_pid(GDBRemoteCommunicationServerLLGS &gdb_server,
|
void handle_attach_to_pid(GDBRemoteCommunicationServerLLGS &gdb_server,
|
||||||
lldb::pid_t pid) {
|
lldb::pid_t pid) {
|
||||||
Status error = gdb_server.AttachToProcess(pid);
|
Status error = gdb_server.AttachToProcess(pid);
|
||||||
|
@ -176,12 +138,12 @@ void handle_attach(GDBRemoteCommunicationServerLLGS &gdb_server,
|
||||||
handle_attach_to_process_name(gdb_server, attach_target);
|
handle_attach_to_process_name(gdb_server, attach_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, int argc,
|
void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server,
|
||||||
const char *const argv[]) {
|
llvm::ArrayRef<llvm::StringRef> Arguments) {
|
||||||
ProcessLaunchInfo info;
|
ProcessLaunchInfo info;
|
||||||
info.GetFlags().Set(eLaunchFlagStopAtEntry | eLaunchFlagDebug |
|
info.GetFlags().Set(eLaunchFlagStopAtEntry | eLaunchFlagDebug |
|
||||||
eLaunchFlagDisableASLR);
|
eLaunchFlagDisableASLR);
|
||||||
info.SetArguments(const_cast<const char **>(argv), true);
|
info.SetArguments(Args(Arguments), true);
|
||||||
|
|
||||||
llvm::SmallString<64> cwd;
|
llvm::SmallString<64> cwd;
|
||||||
if (std::error_code ec = llvm::sys::fs::current_path(cwd)) {
|
if (std::error_code ec = llvm::sys::fs::current_path(cwd)) {
|
||||||
|
@ -198,7 +160,7 @@ void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, int argc,
|
||||||
Status error = gdb_server.LaunchProcess();
|
Status error = gdb_server.LaunchProcess();
|
||||||
if (error.Fail()) {
|
if (error.Fail()) {
|
||||||
llvm::errs() << llvm::formatv("error: failed to launch '{0}': {1}\n",
|
llvm::errs() << llvm::formatv("error: failed to launch '{0}': {1}\n",
|
||||||
argv[0], error);
|
Arguments[0], error);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,7 +191,7 @@ Status writeSocketIdToPipe(lldb::pipe_t unnamed_pipe,
|
||||||
|
|
||||||
void ConnectToRemote(MainLoop &mainloop,
|
void ConnectToRemote(MainLoop &mainloop,
|
||||||
GDBRemoteCommunicationServerLLGS &gdb_server,
|
GDBRemoteCommunicationServerLLGS &gdb_server,
|
||||||
bool reverse_connect, const char *const host_and_port,
|
bool reverse_connect, llvm::StringRef host_and_port,
|
||||||
const char *const progname, const char *const subcommand,
|
const char *const progname, const char *const subcommand,
|
||||||
const char *const named_pipe_path, pipe_t unnamed_pipe,
|
const char *const named_pipe_path, pipe_t unnamed_pipe,
|
||||||
int connection_fd) {
|
int connection_fd) {
|
||||||
|
@ -258,7 +220,7 @@ void ConnectToRemote(MainLoop &mainloop,
|
||||||
connection_url, error.AsCString());
|
connection_url, error.AsCString());
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
} else if (host_and_port && host_and_port[0]) {
|
} else if (!host_and_port.empty()) {
|
||||||
// Parse out host and port.
|
// Parse out host and port.
|
||||||
std::string final_host_and_port;
|
std::string final_host_and_port;
|
||||||
std::string connection_host;
|
std::string connection_host;
|
||||||
|
@ -269,7 +231,7 @@ void ConnectToRemote(MainLoop &mainloop,
|
||||||
// expect the remainder to be the port.
|
// expect the remainder to be the port.
|
||||||
if (host_and_port[0] == ':')
|
if (host_and_port[0] == ':')
|
||||||
final_host_and_port.append("localhost");
|
final_host_and_port.append("localhost");
|
||||||
final_host_and_port.append(host_and_port);
|
final_host_and_port.append(host_and_port.str());
|
||||||
|
|
||||||
// Note: use rfind, because the host/port may look like "[::1]:12345".
|
// Note: use rfind, because the host/port may look like "[::1]:12345".
|
||||||
const std::string::size_type colon_pos = final_host_and_port.rfind(':');
|
const std::string::size_type colon_pos = final_host_and_port.rfind(':');
|
||||||
|
@ -361,7 +323,57 @@ void ConnectToRemote(MainLoop &mainloop,
|
||||||
printf("Connection established.\n");
|
printf("Connection established.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// main
|
namespace {
|
||||||
|
enum ID {
|
||||||
|
OPT_INVALID = 0, // This is not an option ID.
|
||||||
|
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||||
|
HELPTEXT, METAVAR, VALUES) \
|
||||||
|
OPT_##ID,
|
||||||
|
#include "LLGSOptions.inc"
|
||||||
|
#undef OPTION
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
|
||||||
|
#include "LLGSOptions.inc"
|
||||||
|
#undef PREFIX
|
||||||
|
|
||||||
|
const opt::OptTable::Info InfoTable[] = {
|
||||||
|
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||||
|
HELPTEXT, METAVAR, VALUES) \
|
||||||
|
{ \
|
||||||
|
PREFIX, NAME, HELPTEXT, \
|
||||||
|
METAVAR, OPT_##ID, opt::Option::KIND##Class, \
|
||||||
|
PARAM, FLAGS, OPT_##GROUP, \
|
||||||
|
OPT_##ALIAS, ALIASARGS, VALUES},
|
||||||
|
#include "LLGSOptions.inc"
|
||||||
|
#undef OPTION
|
||||||
|
};
|
||||||
|
|
||||||
|
class LLGSOptTable : public opt::OptTable {
|
||||||
|
public:
|
||||||
|
LLGSOptTable() : OptTable(InfoTable) {}
|
||||||
|
|
||||||
|
void PrintHelp(llvm::StringRef Name) {
|
||||||
|
std::string Usage =
|
||||||
|
(Name + " [options] [[host]:port] [[--] program args...]").str();
|
||||||
|
OptTable::PrintHelp(llvm::outs(), Usage.c_str(), "lldb-server");
|
||||||
|
llvm::outs() << R"(
|
||||||
|
DESCRIPTION
|
||||||
|
lldb-server connects to the LLDB client, which drives the debugging session.
|
||||||
|
If no connection options are given, the [host]:port argument must be present
|
||||||
|
and will denote the address that lldb-server will listen on. [host] defaults
|
||||||
|
to "localhost" if empty. Port can be zero, in which case the port number will
|
||||||
|
be chosen dynamically and written to destinations given by --named-pipe and
|
||||||
|
--pipe arguments.
|
||||||
|
|
||||||
|
If no target is selected at startup, lldb-server can be directed by the LLDB
|
||||||
|
client to launch or attach to a process.
|
||||||
|
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int main_gdbserver(int argc, char *argv[]) {
|
int main_gdbserver(int argc, char *argv[]) {
|
||||||
Status error;
|
Status error;
|
||||||
MainLoop mainloop;
|
MainLoop mainloop;
|
||||||
|
@ -374,10 +386,6 @@ int main_gdbserver(int argc, char *argv[]) {
|
||||||
|
|
||||||
const char *progname = argv[0];
|
const char *progname = argv[0];
|
||||||
const char *subcommand = argv[1];
|
const char *subcommand = argv[1];
|
||||||
argc--;
|
|
||||||
argv++;
|
|
||||||
int long_option_index = 0;
|
|
||||||
int ch;
|
|
||||||
std::string attach_target;
|
std::string attach_target;
|
||||||
std::string named_pipe_path;
|
std::string named_pipe_path;
|
||||||
std::string log_file;
|
std::string log_file;
|
||||||
|
@ -390,94 +398,69 @@ int main_gdbserver(int argc, char *argv[]) {
|
||||||
// ProcessLaunchInfo launch_info;
|
// ProcessLaunchInfo launch_info;
|
||||||
ProcessAttachInfo attach_info;
|
ProcessAttachInfo attach_info;
|
||||||
|
|
||||||
bool show_usage = false;
|
LLGSOptTable Opts;
|
||||||
int option_error = 0;
|
llvm::BumpPtrAllocator Alloc;
|
||||||
#if __GLIBC__
|
llvm::StringSaver Saver(Alloc);
|
||||||
optind = 0;
|
bool HasError = false;
|
||||||
#else
|
opt::InputArgList Args = Opts.parseArgs(argc - 1, argv + 1, OPT_UNKNOWN,
|
||||||
optreset = 1;
|
Saver, [&](llvm::StringRef Msg) {
|
||||||
optind = 1;
|
WithColor::error() << Msg << "\n";
|
||||||
#endif
|
HasError = true;
|
||||||
|
});
|
||||||
std::string short_options(OptionParser::GetShortOptionString(g_long_options));
|
std::string Name =
|
||||||
|
(llvm::sys::path::filename(argv[0]) + " g[dbserver]").str();
|
||||||
while ((ch = getopt_long_only(argc, argv, short_options.c_str(),
|
std::string HelpText =
|
||||||
g_long_options, &long_option_index)) != -1) {
|
"Use '" + Name + " --help' for a complete list of options.\n";
|
||||||
switch (ch) {
|
if (HasError) {
|
||||||
case 0: // Any optional that auto set themselves will return 0
|
llvm::errs() << HelpText;
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
case 'l': // Set Log File
|
|
||||||
if (optarg && optarg[0])
|
|
||||||
log_file.assign(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c': // Log Channels
|
|
||||||
if (optarg && optarg[0])
|
|
||||||
log_channels = StringRef(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'N': // named pipe
|
|
||||||
if (optarg && optarg[0])
|
|
||||||
named_pipe_path = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'U': // unnamed pipe
|
|
||||||
if (optarg && optarg[0])
|
|
||||||
unnamed_pipe = (pipe_t)StringConvert::ToUInt64(optarg, -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
// Do nothing, native regs is the default these days
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'R':
|
|
||||||
reverse_connect = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'F':
|
|
||||||
connection_fd = StringConvert::ToUInt32(optarg, -1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
case 'S':
|
|
||||||
// Put llgs into a new session. Terminals group processes
|
|
||||||
// into sessions and when a special terminal key sequences
|
|
||||||
// (like control+c) are typed they can cause signals to go out to
|
|
||||||
// all processes in a session. Using this --setsid (-S) option
|
|
||||||
// will cause debugserver to run in its own sessions and be free
|
|
||||||
// from such issues.
|
|
||||||
//
|
|
||||||
// This is useful when llgs is spawned from a command
|
|
||||||
// line application that uses llgs to do the debugging,
|
|
||||||
// yet that application doesn't want llgs receiving the
|
|
||||||
// signals sent to the session (i.e. dying when anyone hits ^C).
|
|
||||||
{
|
|
||||||
const ::pid_t new_sid = setsid();
|
|
||||||
if (new_sid == -1) {
|
|
||||||
llvm::errs() << llvm::formatv(
|
|
||||||
"failed to set new session id for {0} ({1})\n", LLGS_PROGRAM_NAME,
|
|
||||||
llvm::sys::StrError());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case 'a': // attach {pid|process_name}
|
|
||||||
if (optarg && optarg[0])
|
|
||||||
attach_target = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h': /* fall-through is intentional */
|
|
||||||
case '?':
|
|
||||||
show_usage = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_usage || option_error) {
|
if (Args.hasArg(OPT_help)) {
|
||||||
display_usage(progname, subcommand);
|
Opts.PrintHelp(Name);
|
||||||
exit(option_error);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (Args.hasArg(OPT_setsid)) {
|
||||||
|
// Put llgs into a new session. Terminals group processes
|
||||||
|
// into sessions and when a special terminal key sequences
|
||||||
|
// (like control+c) are typed they can cause signals to go out to
|
||||||
|
// all processes in a session. Using this --setsid (-S) option
|
||||||
|
// will cause debugserver to run in its own sessions and be free
|
||||||
|
// from such issues.
|
||||||
|
//
|
||||||
|
// This is useful when llgs is spawned from a command
|
||||||
|
// line application that uses llgs to do the debugging,
|
||||||
|
// yet that application doesn't want llgs receiving the
|
||||||
|
// signals sent to the session (i.e. dying when anyone hits ^C).
|
||||||
|
{
|
||||||
|
const ::pid_t new_sid = setsid();
|
||||||
|
if (new_sid == -1) {
|
||||||
|
WithColor::warning()
|
||||||
|
<< llvm::formatv("failed to set new session id for {0} ({1})\n",
|
||||||
|
LLGS_PROGRAM_NAME, llvm::sys::StrError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
log_file = Args.getLastArgValue(OPT_log_file).str();
|
||||||
|
log_channels = Args.getLastArgValue(OPT_log_channels);
|
||||||
|
named_pipe_path = Args.getLastArgValue(OPT_named_pipe).str();
|
||||||
|
reverse_connect = Args.hasArg(OPT_reverse_connect);
|
||||||
|
attach_target = Args.getLastArgValue(OPT_attach).str();
|
||||||
|
if (Args.hasArg(OPT_pipe)) {
|
||||||
|
if (!llvm::to_integer(Args.getLastArgValue(OPT_pipe), unnamed_pipe)) {
|
||||||
|
WithColor::error() << "invalid '--pipe' argument\n" << HelpText;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Args.hasArg(OPT_fd)) {
|
||||||
|
if (!llvm::to_integer(Args.getLastArgValue(OPT_fd), connection_fd)) {
|
||||||
|
WithColor::error() << "invalid '--fd' argument\n" << HelpText;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LLDBServerUtilities::SetupLogging(
|
if (!LLDBServerUtilities::SetupLogging(
|
||||||
|
@ -486,30 +469,26 @@ int main_gdbserver(int argc, char *argv[]) {
|
||||||
LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION))
|
LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
Log *log(lldb_private::GetLogIfAnyCategoriesSet(GDBR_LOG_PROCESS));
|
std::vector<llvm::StringRef> Inputs;
|
||||||
if (log) {
|
for (opt::Arg *Arg : Args.filtered(OPT_INPUT))
|
||||||
LLDB_LOGF(log, "lldb-server launch");
|
Inputs.push_back(Arg->getValue());
|
||||||
for (int i = 0; i < argc; i++) {
|
if (opt::Arg *Arg = Args.getLastArg(OPT_REM)) {
|
||||||
LLDB_LOGF(log, "argv[%i] = '%s'", i, argv[i]);
|
for (const char *Val : Arg->getValues())
|
||||||
}
|
Inputs.push_back(Val);
|
||||||
}
|
}
|
||||||
|
if (Inputs.empty() && connection_fd == -1) {
|
||||||
// Skip any options we consumed with getopt_long_only.
|
WithColor::error() << "no connection arguments\n" << HelpText;
|
||||||
argc -= optind;
|
return 1;
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
if (argc == 0 && connection_fd == -1) {
|
|
||||||
fputs("No arguments\n", stderr);
|
|
||||||
display_usage(progname, subcommand);
|
|
||||||
exit(255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeProcessFactory factory;
|
NativeProcessFactory factory;
|
||||||
GDBRemoteCommunicationServerLLGS gdb_server(mainloop, factory);
|
GDBRemoteCommunicationServerLLGS gdb_server(mainloop, factory);
|
||||||
|
|
||||||
const char *const host_and_port = argv[0];
|
llvm::StringRef host_and_port;
|
||||||
argc -= 1;
|
if (!Inputs.empty()) {
|
||||||
argv += 1;
|
host_and_port = Inputs.front();
|
||||||
|
Inputs.erase(Inputs.begin());
|
||||||
|
}
|
||||||
|
|
||||||
// Any arguments left over are for the program that we need to launch. If
|
// Any arguments left over are for the program that we need to launch. If
|
||||||
// there
|
// there
|
||||||
|
@ -520,8 +499,8 @@ int main_gdbserver(int argc, char *argv[]) {
|
||||||
// explicitly asked to attach with the --attach={pid|program_name} form.
|
// explicitly asked to attach with the --attach={pid|program_name} form.
|
||||||
if (!attach_target.empty())
|
if (!attach_target.empty())
|
||||||
handle_attach(gdb_server, attach_target);
|
handle_attach(gdb_server, attach_target);
|
||||||
else if (argc > 0)
|
else if (!Inputs.empty())
|
||||||
handle_launch(gdb_server, argc, argv);
|
handle_launch(gdb_server, Inputs);
|
||||||
|
|
||||||
// Print version info.
|
// Print version info.
|
||||||
printf("%s-%s\n", LLGS_PROGRAM_NAME, LLGS_VERSION_STR);
|
printf("%s-%s\n", LLGS_PROGRAM_NAME, LLGS_VERSION_STR);
|
||||||
|
@ -532,7 +511,6 @@ int main_gdbserver(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (!gdb_server.IsConnected()) {
|
if (!gdb_server.IsConnected()) {
|
||||||
fprintf(stderr, "no connection information provided, unable to run\n");
|
fprintf(stderr, "no connection information provided, unable to run\n");
|
||||||
display_usage(progname, subcommand);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue