diff options
author | emaste <emaste@FreeBSD.org> | 2013-12-03 18:51:59 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2013-12-03 18:51:59 +0000 |
commit | 0f31a1ef7ecf609d469ee5b34b3f0cb24ae3492d (patch) | |
tree | b2051e4e4856cc58ac7e2d20242b870b4f355ca1 /tools | |
parent | c727fe695d28799acb499e9961f11ec07d4f9fe2 (diff) | |
download | FreeBSD-src-0f31a1ef7ecf609d469ee5b34b3f0cb24ae3492d.zip FreeBSD-src-0f31a1ef7ecf609d469ee5b34b3f0cb24ae3492d.tar.gz |
Import lldb as of SVN r196259 (git 3be86e5)
(A number of files not required for the FreeBSD build have been removed.)
Sponsored by: DARPA, AFRL
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lldb-platform/lldb-platform.cpp | 215 |
1 files changed, 131 insertions, 84 deletions
diff --git a/tools/lldb-platform/lldb-platform.cpp b/tools/lldb-platform/lldb-platform.cpp index 007e69c..bc9d629 100644 --- a/tools/lldb-platform/lldb-platform.cpp +++ b/tools/lldb-platform/lldb-platform.cpp @@ -21,11 +21,15 @@ // C++ Includes // Other libraries and framework includes +#include "lldb/lldb-private-log.h" #include "lldb/Core/Error.h" #include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/ConnectionMachPort.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" using namespace lldb; @@ -44,24 +48,32 @@ static struct option g_long_options[] = { "debug", no_argument, &g_debug, 1 }, { "verbose", no_argument, &g_verbose, 1 }, { "stay-alive", no_argument, &g_stay_alive, 1 }, - { "log-file", required_argument, NULL, 'l' }, - { "log-flags", required_argument, NULL, 'f' }, { "listen", required_argument, NULL, 'L' }, + { "port-offset", required_argument, NULL, 'p' }, + { "gdbserver-port", required_argument, NULL, 'P' }, + { "min-gdbserver-port", required_argument, NULL, 'm' }, + { "max-gdbserver-port", required_argument, NULL, 'M' }, + { "lldb-command", required_argument, NULL, 'c' }, { NULL, 0, NULL, 0 } }; +#if defined (__APPLE__) +#define LOW_PORT (IPPORT_RESERVED) +#define HIGH_PORT (IPPORT_HIFIRSTAUTO) +#else +#define LOW_PORT (1024u) +#define HIGH_PORT (49151u) +#endif + + //---------------------------------------------------------------------- // Watch for signals //---------------------------------------------------------------------- -int g_sigpipe_received = 0; void signal_handler(int signo) { switch (signo) { - case SIGPIPE: - g_sigpipe_received = 1; - break; case SIGHUP: // Use SIGINT first, if that does not work, use SIGHUP as a last resort. // And we should not call exit() here because it results in the global destructors @@ -86,130 +98,165 @@ int main (int argc, char *argv[]) { const char *progname = argv[0]; - signal (SIGPIPE, signal_handler); + signal (SIGPIPE, SIG_IGN); signal (SIGHUP, signal_handler); int long_option_index = 0; - StreamSP log_stream_sp; - Args log_args; Error error; std::string listen_host_port; int ch; - Debugger::Initialize(); + Debugger::Initialize(NULL); + + lldb::DebuggerSP debugger_sp = Debugger::CreateInstance (); + + debugger_sp->SetInputFileHandle(stdin, false); + debugger_sp->SetOutputFileHandle(stdout, false); + debugger_sp->SetErrorFileHandle(stderr, false); -// ConnectionMachPort a; -// ConnectionMachPort b; -// -// lldb::ConnectionStatus status; -// const char *bootstrap_service_name = "HelloWorld"; -// status = a.BootstrapCheckIn(bootstrap_service_name, &error); -// -// if (status != eConnectionStatusSuccess) -// { -// fprintf(stderr, "%s", error.AsCString()); -// return 1; -// } -// status = b.BootstrapLookup (bootstrap_service_name, &error); -// if (status != eConnectionStatusSuccess) -// { -// fprintf(stderr, "%s", error.AsCString()); -// return 2; -// } -// -// if (a.Write ("hello", 5, status, &error) == 5) -// { -// char buf[32]; -// memset(buf, 0, sizeof(buf)); -// if (b.Read (buf, 5, status, &error)) -// { -// printf("read returned bytes: %s", buf); -// } -// else -// { -// fprintf(stderr, "%s", error.AsCString()); -// return 4; -// } -// } -// else -// { -// fprintf(stderr, "%s", error.AsCString()); -// return 3; -// } + GDBRemoteCommunicationServer::PortMap gdbserver_portmap; + int min_gdbserver_port = 0; + int max_gdbserver_port = 0; + uint16_t port_offset = 0; + + std::vector<std::string> lldb_commands; + bool show_usage = false; + int option_error = 0; - while ((ch = getopt_long_only(argc, argv, "l:f:L:", g_long_options, &long_option_index)) != -1) + std::string short_options(OptionParser::GetShortOptionString(g_long_options)); + +#if __GLIBC__ + optind = 0; +#else + optreset = 1; + optind = 1; +#endif + + while ((ch = getopt_long_only(argc, argv, short_options.c_str(), g_long_options, &long_option_index)) != -1) { -// DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", -// ch, (uint8_t)ch, -// g_long_options[long_option_index].name, -// g_long_options[long_option_index].has_arg ? '=' : ' ', -// optarg ? optarg : ""); switch (ch) { case 0: // Any optional that auto set themselves will return 0 break; - case 'l': // Set Log File - if (optarg && optarg[0]) + case 'L': + listen_host_port.append (optarg); + break; + + case 'p': { - if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0)) + char *end = NULL; + long tmp_port_offset = strtoul(optarg, &end, 0); + if (end && *end == '\0') { - log_stream_sp.reset (new StreamFile (stdout, false)); + if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT) + { + port_offset = (uint16_t)tmp_port_offset; + } + else + { + fprintf (stderr, "error: port offset %li is not in the valid user port range of %u - %u\n", tmp_port_offset, LOW_PORT, HIGH_PORT); + option_error = 5; + } } - else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0)) + else { - log_stream_sp.reset (new StreamFile (stderr, false)); + fprintf (stderr, "error: invalid port offset string %s\n", optarg); + option_error = 4; } - else + } + break; + + case 'P': + case 'm': + case 'M': + { + char *end = NULL; + long portnum = strtoul(optarg, &end, 0); + if (end && *end == '\0') { - FILE *log_file = fopen(optarg, "w"); - if (log_file) + if (LOW_PORT <= portnum && portnum <= HIGH_PORT) { - setlinebuf(log_file); - log_stream_sp.reset (new StreamFile (log_file, true)); + if (ch == 'P') + gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID; + else if (ch == 'm') + min_gdbserver_port = portnum; + else + max_gdbserver_port = portnum; } else { - const char *errno_str = strerror(errno); - fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error"); + fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT); + option_error = 1; } - } - + else + { + fprintf (stderr, "error: invalid port number string %s\n", optarg); + option_error = 2; + } } break; - - case 'f': // Log Flags - if (optarg && optarg[0]) - log_args.AppendArgument(optarg); - break; - - case 'L': - listen_host_port.append (optarg); + + case 'c': + lldb_commands.push_back(optarg); break; case 'h': /* fall-through is intentional */ case '?': - display_usage(progname); + show_usage = true; break; } } + + // Make a port map for a port range that was specified. + if (min_gdbserver_port < max_gdbserver_port) + { + for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port) + gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID; + } + else if (min_gdbserver_port != max_gdbserver_port) + { + fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port); + option_error = 3; + + } + // Print usage and exit if no listening port is specified. if (listen_host_port.empty()) - display_usage(progname); + show_usage = true; - if (log_stream_sp) + if (show_usage || option_error) { - if (log_args.GetArgumentCount() == 0) - log_args.AppendArgument("default"); - ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args.GetConstArgumentVector(), log_stream_sp.get()); + display_usage(progname); + exit(option_error); } - + // Skip any options we consumed with getopt_long_only argc -= optind; argv += optind; + // Execute any LLDB commands that we were asked to evaluate. + for (const auto &lldb_command : lldb_commands) + { + lldb_private::CommandReturnObject result; + printf("(lldb) %s\n", lldb_command.c_str()); + debugger_sp->GetCommandInterpreter().HandleCommand(lldb_command.c_str(), eLazyBoolNo, result); + const char *output = result.GetOutputData(); + if (output && output[0]) + puts(output); + } + do { GDBRemoteCommunicationServer gdb_server (true); + + if (port_offset > 0) + gdb_server.SetPortOffset(port_offset); + + if (!gdbserver_portmap.empty()) + { + gdb_server.SetPortMap(std::move(gdbserver_portmap)); + } + if (!listen_host_port.empty()) { std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); |