1061da546Spatrick //===-- lldb-gdbserver.cpp --------------------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9*a0747c9fSpatrick #include <cerrno> 10*a0747c9fSpatrick #include <cstdint> 11*a0747c9fSpatrick #include <cstdio> 12*a0747c9fSpatrick #include <cstdlib> 13*a0747c9fSpatrick #include <cstring> 14061da546Spatrick 15061da546Spatrick #ifndef _WIN32 16*a0747c9fSpatrick #include <csignal> 17061da546Spatrick #include <unistd.h> 18061da546Spatrick #endif 19061da546Spatrick 20061da546Spatrick #include "Acceptor.h" 21061da546Spatrick #include "LLDBServerUtilities.h" 22061da546Spatrick #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h" 23061da546Spatrick #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" 24061da546Spatrick #include "lldb/Host/Config.h" 25061da546Spatrick #include "lldb/Host/ConnectionFileDescriptor.h" 26061da546Spatrick #include "lldb/Host/FileSystem.h" 27061da546Spatrick #include "lldb/Host/Pipe.h" 28061da546Spatrick #include "lldb/Host/Socket.h" 29061da546Spatrick #include "lldb/Host/StringConvert.h" 30061da546Spatrick #include "lldb/Host/common/NativeProcessProtocol.h" 31061da546Spatrick #include "lldb/Target/Process.h" 32061da546Spatrick #include "lldb/Utility/Status.h" 33061da546Spatrick #include "llvm/ADT/StringRef.h" 34*a0747c9fSpatrick #include "llvm/Option/ArgList.h" 35*a0747c9fSpatrick #include "llvm/Option/OptTable.h" 36*a0747c9fSpatrick #include "llvm/Option/Option.h" 37061da546Spatrick #include "llvm/Support/Errno.h" 38*a0747c9fSpatrick #include "llvm/Support/WithColor.h" 39061da546Spatrick 40061da546Spatrick #if defined(__linux__) 41061da546Spatrick #include "Plugins/Process/Linux/NativeProcessLinux.h" 42*a0747c9fSpatrick #elif defined(__FreeBSD__) 43*a0747c9fSpatrick #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h" 44061da546Spatrick #elif defined(__NetBSD__) 45061da546Spatrick #include "Plugins/Process/NetBSD/NativeProcessNetBSD.h" 46adae0cfdSpatrick #elif defined(__OpenBSD__) 47adae0cfdSpatrick #include "Plugins/Process/OpenBSD/NativeProcessOpenBSD.h" 48061da546Spatrick #elif defined(_WIN32) 49061da546Spatrick #include "Plugins/Process/Windows/Common/NativeProcessWindows.h" 50061da546Spatrick #endif 51061da546Spatrick 52061da546Spatrick #ifndef LLGS_PROGRAM_NAME 53061da546Spatrick #define LLGS_PROGRAM_NAME "lldb-server" 54061da546Spatrick #endif 55061da546Spatrick 56061da546Spatrick #ifndef LLGS_VERSION_STR 57061da546Spatrick #define LLGS_VERSION_STR "local_build" 58061da546Spatrick #endif 59061da546Spatrick 60061da546Spatrick using namespace llvm; 61061da546Spatrick using namespace lldb; 62061da546Spatrick using namespace lldb_private; 63061da546Spatrick using namespace lldb_private::lldb_server; 64061da546Spatrick using namespace lldb_private::process_gdb_remote; 65061da546Spatrick 66061da546Spatrick namespace { 67061da546Spatrick #if defined(__linux__) 68061da546Spatrick typedef process_linux::NativeProcessLinux::Factory NativeProcessFactory; 69*a0747c9fSpatrick #elif defined(__FreeBSD__) 70*a0747c9fSpatrick typedef process_freebsd::NativeProcessFreeBSD::Factory NativeProcessFactory; 71061da546Spatrick #elif defined(__NetBSD__) 72061da546Spatrick typedef process_netbsd::NativeProcessNetBSD::Factory NativeProcessFactory; 73adae0cfdSpatrick #elif defined(__OpenBSD__) 74adae0cfdSpatrick typedef process_openbsd::NativeProcessOpenBSD::Factory NativeProcessFactory; 75061da546Spatrick #elif defined(_WIN32) 76061da546Spatrick typedef NativeProcessWindows::Factory NativeProcessFactory; 77061da546Spatrick #else 78061da546Spatrick // Dummy implementation to make sure the code compiles 79061da546Spatrick class NativeProcessFactory : public NativeProcessProtocol::Factory { 80061da546Spatrick public: 81061da546Spatrick llvm::Expected<std::unique_ptr<NativeProcessProtocol>> 82061da546Spatrick Launch(ProcessLaunchInfo &launch_info, 83061da546Spatrick NativeProcessProtocol::NativeDelegate &delegate, 84061da546Spatrick MainLoop &mainloop) const override { 85061da546Spatrick llvm_unreachable("Not implemented"); 86061da546Spatrick } 87061da546Spatrick llvm::Expected<std::unique_ptr<NativeProcessProtocol>> 88061da546Spatrick Attach(lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &delegate, 89061da546Spatrick MainLoop &mainloop) const override { 90061da546Spatrick llvm_unreachable("Not implemented"); 91061da546Spatrick } 92061da546Spatrick }; 93061da546Spatrick #endif 94061da546Spatrick } 95061da546Spatrick 96061da546Spatrick #ifndef _WIN32 97061da546Spatrick // Watch for signals 98061da546Spatrick static int g_sighup_received_count = 0; 99061da546Spatrick 100061da546Spatrick static void sighup_handler(MainLoopBase &mainloop) { 101061da546Spatrick ++g_sighup_received_count; 102061da546Spatrick 103061da546Spatrick Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); 104061da546Spatrick LLDB_LOGF(log, "lldb-server:%s swallowing SIGHUP (receive count=%d)", 105061da546Spatrick __FUNCTION__, g_sighup_received_count); 106061da546Spatrick 107061da546Spatrick if (g_sighup_received_count >= 2) 108061da546Spatrick mainloop.RequestTermination(); 109061da546Spatrick } 110061da546Spatrick #endif // #ifndef _WIN32 111061da546Spatrick 112061da546Spatrick void handle_attach_to_pid(GDBRemoteCommunicationServerLLGS &gdb_server, 113061da546Spatrick lldb::pid_t pid) { 114061da546Spatrick Status error = gdb_server.AttachToProcess(pid); 115061da546Spatrick if (error.Fail()) { 116061da546Spatrick fprintf(stderr, "error: failed to attach to pid %" PRIu64 ": %s\n", pid, 117061da546Spatrick error.AsCString()); 118061da546Spatrick exit(1); 119061da546Spatrick } 120061da546Spatrick } 121061da546Spatrick 122061da546Spatrick void handle_attach_to_process_name(GDBRemoteCommunicationServerLLGS &gdb_server, 123061da546Spatrick const std::string &process_name) { 124061da546Spatrick // FIXME implement. 125061da546Spatrick } 126061da546Spatrick 127061da546Spatrick void handle_attach(GDBRemoteCommunicationServerLLGS &gdb_server, 128061da546Spatrick const std::string &attach_target) { 129061da546Spatrick assert(!attach_target.empty() && "attach_target cannot be empty"); 130061da546Spatrick 131061da546Spatrick // First check if the attach_target is convertible to a long. If so, we'll use 132061da546Spatrick // it as a pid. 133061da546Spatrick char *end_p = nullptr; 134061da546Spatrick const long int pid = strtol(attach_target.c_str(), &end_p, 10); 135061da546Spatrick 136061da546Spatrick // We'll call it a match if the entire argument is consumed. 137061da546Spatrick if (end_p && 138061da546Spatrick static_cast<size_t>(end_p - attach_target.c_str()) == 139061da546Spatrick attach_target.size()) 140061da546Spatrick handle_attach_to_pid(gdb_server, static_cast<lldb::pid_t>(pid)); 141061da546Spatrick else 142061da546Spatrick handle_attach_to_process_name(gdb_server, attach_target); 143061da546Spatrick } 144061da546Spatrick 145*a0747c9fSpatrick void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, 146*a0747c9fSpatrick llvm::ArrayRef<llvm::StringRef> Arguments) { 147061da546Spatrick ProcessLaunchInfo info; 148061da546Spatrick info.GetFlags().Set(eLaunchFlagStopAtEntry | eLaunchFlagDebug | 149061da546Spatrick eLaunchFlagDisableASLR); 150*a0747c9fSpatrick info.SetArguments(Args(Arguments), true); 151061da546Spatrick 152061da546Spatrick llvm::SmallString<64> cwd; 153061da546Spatrick if (std::error_code ec = llvm::sys::fs::current_path(cwd)) { 154061da546Spatrick llvm::errs() << "Error getting current directory: " << ec.message() << "\n"; 155061da546Spatrick exit(1); 156061da546Spatrick } 157061da546Spatrick FileSpec cwd_spec(cwd); 158061da546Spatrick FileSystem::Instance().Resolve(cwd_spec); 159061da546Spatrick info.SetWorkingDirectory(cwd_spec); 160061da546Spatrick info.GetEnvironment() = Host::GetEnvironment(); 161061da546Spatrick 162061da546Spatrick gdb_server.SetLaunchInfo(info); 163061da546Spatrick 164061da546Spatrick Status error = gdb_server.LaunchProcess(); 165061da546Spatrick if (error.Fail()) { 166061da546Spatrick llvm::errs() << llvm::formatv("error: failed to launch '{0}': {1}\n", 167*a0747c9fSpatrick Arguments[0], error); 168061da546Spatrick exit(1); 169061da546Spatrick } 170061da546Spatrick } 171061da546Spatrick 172061da546Spatrick Status writeSocketIdToPipe(Pipe &port_pipe, const std::string &socket_id) { 173061da546Spatrick size_t bytes_written = 0; 174061da546Spatrick // Write the port number as a C string with the NULL terminator. 175061da546Spatrick return port_pipe.Write(socket_id.c_str(), socket_id.size() + 1, 176061da546Spatrick bytes_written); 177061da546Spatrick } 178061da546Spatrick 179061da546Spatrick Status writeSocketIdToPipe(const char *const named_pipe_path, 180061da546Spatrick const std::string &socket_id) { 181061da546Spatrick Pipe port_name_pipe; 182061da546Spatrick // Wait for 10 seconds for pipe to be opened. 183061da546Spatrick auto error = port_name_pipe.OpenAsWriterWithTimeout(named_pipe_path, false, 184061da546Spatrick std::chrono::seconds{10}); 185061da546Spatrick if (error.Fail()) 186061da546Spatrick return error; 187061da546Spatrick return writeSocketIdToPipe(port_name_pipe, socket_id); 188061da546Spatrick } 189061da546Spatrick 190061da546Spatrick Status writeSocketIdToPipe(lldb::pipe_t unnamed_pipe, 191061da546Spatrick const std::string &socket_id) { 192061da546Spatrick Pipe port_pipe{LLDB_INVALID_PIPE, unnamed_pipe}; 193061da546Spatrick return writeSocketIdToPipe(port_pipe, socket_id); 194061da546Spatrick } 195061da546Spatrick 196061da546Spatrick void ConnectToRemote(MainLoop &mainloop, 197061da546Spatrick GDBRemoteCommunicationServerLLGS &gdb_server, 198*a0747c9fSpatrick bool reverse_connect, llvm::StringRef host_and_port, 199061da546Spatrick const char *const progname, const char *const subcommand, 200061da546Spatrick const char *const named_pipe_path, pipe_t unnamed_pipe, 201061da546Spatrick int connection_fd) { 202061da546Spatrick Status error; 203061da546Spatrick 204061da546Spatrick std::unique_ptr<Connection> connection_up; 205061da546Spatrick if (connection_fd != -1) { 206061da546Spatrick // Build the connection string. 207061da546Spatrick char connection_url[512]; 208061da546Spatrick snprintf(connection_url, sizeof(connection_url), "fd://%d", connection_fd); 209061da546Spatrick 210061da546Spatrick // Create the connection. 211061da546Spatrick #if LLDB_ENABLE_POSIX && !defined _WIN32 212061da546Spatrick ::fcntl(connection_fd, F_SETFD, FD_CLOEXEC); 213061da546Spatrick #endif 214061da546Spatrick connection_up.reset(new ConnectionFileDescriptor); 215061da546Spatrick auto connection_result = connection_up->Connect(connection_url, &error); 216061da546Spatrick if (connection_result != eConnectionStatusSuccess) { 217061da546Spatrick fprintf(stderr, "error: failed to connect to client at '%s' " 218061da546Spatrick "(connection status: %d)\n", 219061da546Spatrick connection_url, static_cast<int>(connection_result)); 220061da546Spatrick exit(-1); 221061da546Spatrick } 222061da546Spatrick if (error.Fail()) { 223061da546Spatrick fprintf(stderr, "error: failed to connect to client at '%s': %s\n", 224061da546Spatrick connection_url, error.AsCString()); 225061da546Spatrick exit(-1); 226061da546Spatrick } 227*a0747c9fSpatrick } else if (!host_and_port.empty()) { 228061da546Spatrick // Parse out host and port. 229061da546Spatrick std::string final_host_and_port; 230061da546Spatrick std::string connection_host; 231061da546Spatrick std::string connection_port; 232061da546Spatrick uint32_t connection_portno = 0; 233061da546Spatrick 234061da546Spatrick // If host_and_port starts with ':', default the host to be "localhost" and 235061da546Spatrick // expect the remainder to be the port. 236061da546Spatrick if (host_and_port[0] == ':') 237061da546Spatrick final_host_and_port.append("localhost"); 238*a0747c9fSpatrick final_host_and_port.append(host_and_port.str()); 239061da546Spatrick 240*a0747c9fSpatrick // Note: use rfind, because the host/port may look like "[::1]:12345". 241*a0747c9fSpatrick const std::string::size_type colon_pos = final_host_and_port.rfind(':'); 242061da546Spatrick if (colon_pos != std::string::npos) { 243061da546Spatrick connection_host = final_host_and_port.substr(0, colon_pos); 244061da546Spatrick connection_port = final_host_and_port.substr(colon_pos + 1); 245061da546Spatrick connection_portno = StringConvert::ToUInt32(connection_port.c_str(), 0); 246061da546Spatrick } 247061da546Spatrick 248061da546Spatrick 249061da546Spatrick if (reverse_connect) { 250061da546Spatrick // llgs will connect to the gdb-remote client. 251061da546Spatrick 252061da546Spatrick // Ensure we have a port number for the connection. 253061da546Spatrick if (connection_portno == 0) { 254061da546Spatrick fprintf(stderr, "error: port number must be specified on when using " 255061da546Spatrick "reverse connect\n"); 256061da546Spatrick exit(1); 257061da546Spatrick } 258061da546Spatrick 259061da546Spatrick // Build the connection string. 260061da546Spatrick char connection_url[512]; 261061da546Spatrick snprintf(connection_url, sizeof(connection_url), "connect://%s", 262061da546Spatrick final_host_and_port.c_str()); 263061da546Spatrick 264061da546Spatrick // Create the connection. 265061da546Spatrick connection_up.reset(new ConnectionFileDescriptor); 266061da546Spatrick auto connection_result = connection_up->Connect(connection_url, &error); 267061da546Spatrick if (connection_result != eConnectionStatusSuccess) { 268061da546Spatrick fprintf(stderr, "error: failed to connect to client at '%s' " 269061da546Spatrick "(connection status: %d)\n", 270061da546Spatrick connection_url, static_cast<int>(connection_result)); 271061da546Spatrick exit(-1); 272061da546Spatrick } 273061da546Spatrick if (error.Fail()) { 274061da546Spatrick fprintf(stderr, "error: failed to connect to client at '%s': %s\n", 275061da546Spatrick connection_url, error.AsCString()); 276061da546Spatrick exit(-1); 277061da546Spatrick } 278061da546Spatrick } else { 279061da546Spatrick std::unique_ptr<Acceptor> acceptor_up( 280061da546Spatrick Acceptor::Create(final_host_and_port, false, error)); 281061da546Spatrick if (error.Fail()) { 282061da546Spatrick fprintf(stderr, "failed to create acceptor: %s\n", error.AsCString()); 283061da546Spatrick exit(1); 284061da546Spatrick } 285061da546Spatrick error = acceptor_up->Listen(1); 286061da546Spatrick if (error.Fail()) { 287061da546Spatrick fprintf(stderr, "failed to listen: %s\n", error.AsCString()); 288061da546Spatrick exit(1); 289061da546Spatrick } 290061da546Spatrick const std::string socket_id = acceptor_up->GetLocalSocketId(); 291061da546Spatrick if (!socket_id.empty()) { 292061da546Spatrick // If we have a named pipe to write the socket id back to, do that now. 293061da546Spatrick if (named_pipe_path && named_pipe_path[0]) { 294061da546Spatrick error = writeSocketIdToPipe(named_pipe_path, socket_id); 295061da546Spatrick if (error.Fail()) 296061da546Spatrick fprintf(stderr, "failed to write to the named pipe \'%s\': %s\n", 297061da546Spatrick named_pipe_path, error.AsCString()); 298061da546Spatrick } 299061da546Spatrick // If we have an unnamed pipe to write the socket id back to, do that 300061da546Spatrick // now. 301061da546Spatrick else if (unnamed_pipe != LLDB_INVALID_PIPE) { 302061da546Spatrick error = writeSocketIdToPipe(unnamed_pipe, socket_id); 303061da546Spatrick if (error.Fail()) 304061da546Spatrick fprintf(stderr, "failed to write to the unnamed pipe: %s\n", 305061da546Spatrick error.AsCString()); 306061da546Spatrick } 307061da546Spatrick } else { 308061da546Spatrick fprintf(stderr, 309061da546Spatrick "unable to get the socket id for the listening connection\n"); 310061da546Spatrick } 311061da546Spatrick 312061da546Spatrick Connection *conn = nullptr; 313061da546Spatrick error = acceptor_up->Accept(false, conn); 314061da546Spatrick if (error.Fail()) { 315061da546Spatrick printf("failed to accept new connection: %s\n", error.AsCString()); 316061da546Spatrick exit(1); 317061da546Spatrick } 318061da546Spatrick connection_up.reset(conn); 319061da546Spatrick } 320061da546Spatrick } 321061da546Spatrick error = gdb_server.InitializeConnection(std::move(connection_up)); 322061da546Spatrick if (error.Fail()) { 323061da546Spatrick fprintf(stderr, "Failed to initialize connection: %s\n", 324061da546Spatrick error.AsCString()); 325061da546Spatrick exit(-1); 326061da546Spatrick } 327061da546Spatrick printf("Connection established.\n"); 328061da546Spatrick } 329061da546Spatrick 330*a0747c9fSpatrick namespace { 331*a0747c9fSpatrick enum ID { 332*a0747c9fSpatrick OPT_INVALID = 0, // This is not an option ID. 333*a0747c9fSpatrick #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 334*a0747c9fSpatrick HELPTEXT, METAVAR, VALUES) \ 335*a0747c9fSpatrick OPT_##ID, 336*a0747c9fSpatrick #include "LLGSOptions.inc" 337*a0747c9fSpatrick #undef OPTION 338*a0747c9fSpatrick }; 339*a0747c9fSpatrick 340*a0747c9fSpatrick #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; 341*a0747c9fSpatrick #include "LLGSOptions.inc" 342*a0747c9fSpatrick #undef PREFIX 343*a0747c9fSpatrick 344*a0747c9fSpatrick const opt::OptTable::Info InfoTable[] = { 345*a0747c9fSpatrick #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 346*a0747c9fSpatrick HELPTEXT, METAVAR, VALUES) \ 347*a0747c9fSpatrick { \ 348*a0747c9fSpatrick PREFIX, NAME, HELPTEXT, \ 349*a0747c9fSpatrick METAVAR, OPT_##ID, opt::Option::KIND##Class, \ 350*a0747c9fSpatrick PARAM, FLAGS, OPT_##GROUP, \ 351*a0747c9fSpatrick OPT_##ALIAS, ALIASARGS, VALUES}, 352*a0747c9fSpatrick #include "LLGSOptions.inc" 353*a0747c9fSpatrick #undef OPTION 354*a0747c9fSpatrick }; 355*a0747c9fSpatrick 356*a0747c9fSpatrick class LLGSOptTable : public opt::OptTable { 357*a0747c9fSpatrick public: 358*a0747c9fSpatrick LLGSOptTable() : OptTable(InfoTable) {} 359*a0747c9fSpatrick 360*a0747c9fSpatrick void PrintHelp(llvm::StringRef Name) { 361*a0747c9fSpatrick std::string Usage = 362*a0747c9fSpatrick (Name + " [options] [[host]:port] [[--] program args...]").str(); 363*a0747c9fSpatrick OptTable::printHelp(llvm::outs(), Usage.c_str(), "lldb-server"); 364*a0747c9fSpatrick llvm::outs() << R"( 365*a0747c9fSpatrick DESCRIPTION 366*a0747c9fSpatrick lldb-server connects to the LLDB client, which drives the debugging session. 367*a0747c9fSpatrick If no connection options are given, the [host]:port argument must be present 368*a0747c9fSpatrick and will denote the address that lldb-server will listen on. [host] defaults 369*a0747c9fSpatrick to "localhost" if empty. Port can be zero, in which case the port number will 370*a0747c9fSpatrick be chosen dynamically and written to destinations given by --named-pipe and 371*a0747c9fSpatrick --pipe arguments. 372*a0747c9fSpatrick 373*a0747c9fSpatrick If no target is selected at startup, lldb-server can be directed by the LLDB 374*a0747c9fSpatrick client to launch or attach to a process. 375*a0747c9fSpatrick 376*a0747c9fSpatrick )"; 377*a0747c9fSpatrick } 378*a0747c9fSpatrick }; 379*a0747c9fSpatrick } // namespace 380*a0747c9fSpatrick 381061da546Spatrick int main_gdbserver(int argc, char *argv[]) { 382061da546Spatrick Status error; 383061da546Spatrick MainLoop mainloop; 384061da546Spatrick #ifndef _WIN32 385061da546Spatrick // Setup signal handlers first thing. 386061da546Spatrick signal(SIGPIPE, SIG_IGN); 387061da546Spatrick MainLoop::SignalHandleUP sighup_handle = 388061da546Spatrick mainloop.RegisterSignal(SIGHUP, sighup_handler, error); 389061da546Spatrick #endif 390061da546Spatrick 391061da546Spatrick const char *progname = argv[0]; 392061da546Spatrick const char *subcommand = argv[1]; 393061da546Spatrick std::string attach_target; 394061da546Spatrick std::string named_pipe_path; 395061da546Spatrick std::string log_file; 396061da546Spatrick StringRef 397061da546Spatrick log_channels; // e.g. "lldb process threads:gdb-remote default:linux all" 398061da546Spatrick lldb::pipe_t unnamed_pipe = LLDB_INVALID_PIPE; 399061da546Spatrick bool reverse_connect = false; 400061da546Spatrick int connection_fd = -1; 401061da546Spatrick 402061da546Spatrick // ProcessLaunchInfo launch_info; 403061da546Spatrick ProcessAttachInfo attach_info; 404061da546Spatrick 405*a0747c9fSpatrick LLGSOptTable Opts; 406*a0747c9fSpatrick llvm::BumpPtrAllocator Alloc; 407*a0747c9fSpatrick llvm::StringSaver Saver(Alloc); 408*a0747c9fSpatrick bool HasError = false; 409*a0747c9fSpatrick opt::InputArgList Args = Opts.parseArgs(argc - 1, argv + 1, OPT_UNKNOWN, 410*a0747c9fSpatrick Saver, [&](llvm::StringRef Msg) { 411*a0747c9fSpatrick WithColor::error() << Msg << "\n"; 412*a0747c9fSpatrick HasError = true; 413*a0747c9fSpatrick }); 414*a0747c9fSpatrick std::string Name = 415*a0747c9fSpatrick (llvm::sys::path::filename(argv[0]) + " g[dbserver]").str(); 416*a0747c9fSpatrick std::string HelpText = 417*a0747c9fSpatrick "Use '" + Name + " --help' for a complete list of options.\n"; 418*a0747c9fSpatrick if (HasError) { 419*a0747c9fSpatrick llvm::errs() << HelpText; 420*a0747c9fSpatrick return 1; 421*a0747c9fSpatrick } 422061da546Spatrick 423*a0747c9fSpatrick if (Args.hasArg(OPT_help)) { 424*a0747c9fSpatrick Opts.PrintHelp(Name); 425*a0747c9fSpatrick return 0; 426*a0747c9fSpatrick } 427061da546Spatrick 428061da546Spatrick #ifndef _WIN32 429*a0747c9fSpatrick if (Args.hasArg(OPT_setsid)) { 430061da546Spatrick // Put llgs into a new session. Terminals group processes 431061da546Spatrick // into sessions and when a special terminal key sequences 432061da546Spatrick // (like control+c) are typed they can cause signals to go out to 433061da546Spatrick // all processes in a session. Using this --setsid (-S) option 434061da546Spatrick // will cause debugserver to run in its own sessions and be free 435061da546Spatrick // from such issues. 436061da546Spatrick // 437061da546Spatrick // This is useful when llgs is spawned from a command 438061da546Spatrick // line application that uses llgs to do the debugging, 439061da546Spatrick // yet that application doesn't want llgs receiving the 440061da546Spatrick // signals sent to the session (i.e. dying when anyone hits ^C). 441061da546Spatrick { 442061da546Spatrick const ::pid_t new_sid = setsid(); 443061da546Spatrick if (new_sid == -1) { 444*a0747c9fSpatrick WithColor::warning() 445*a0747c9fSpatrick << llvm::formatv("failed to set new session id for {0} ({1})\n", 446*a0747c9fSpatrick LLGS_PROGRAM_NAME, llvm::sys::StrError()); 447061da546Spatrick } 448061da546Spatrick } 449*a0747c9fSpatrick } 450061da546Spatrick #endif 451061da546Spatrick 452*a0747c9fSpatrick log_file = Args.getLastArgValue(OPT_log_file).str(); 453*a0747c9fSpatrick log_channels = Args.getLastArgValue(OPT_log_channels); 454*a0747c9fSpatrick named_pipe_path = Args.getLastArgValue(OPT_named_pipe).str(); 455*a0747c9fSpatrick reverse_connect = Args.hasArg(OPT_reverse_connect); 456*a0747c9fSpatrick attach_target = Args.getLastArgValue(OPT_attach).str(); 457*a0747c9fSpatrick if (Args.hasArg(OPT_pipe)) { 458*a0747c9fSpatrick uint64_t Arg; 459*a0747c9fSpatrick if (!llvm::to_integer(Args.getLastArgValue(OPT_pipe), Arg)) { 460*a0747c9fSpatrick WithColor::error() << "invalid '--pipe' argument\n" << HelpText; 461*a0747c9fSpatrick return 1; 462061da546Spatrick } 463*a0747c9fSpatrick unnamed_pipe = (pipe_t)Arg; 464061da546Spatrick } 465*a0747c9fSpatrick if (Args.hasArg(OPT_fd)) { 466*a0747c9fSpatrick if (!llvm::to_integer(Args.getLastArgValue(OPT_fd), connection_fd)) { 467*a0747c9fSpatrick WithColor::error() << "invalid '--fd' argument\n" << HelpText; 468*a0747c9fSpatrick return 1; 469*a0747c9fSpatrick } 470061da546Spatrick } 471061da546Spatrick 472061da546Spatrick if (!LLDBServerUtilities::SetupLogging( 473061da546Spatrick log_file, log_channels, 474061da546Spatrick LLDB_LOG_OPTION_PREPEND_TIMESTAMP | 475061da546Spatrick LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION)) 476061da546Spatrick return -1; 477061da546Spatrick 478*a0747c9fSpatrick std::vector<llvm::StringRef> Inputs; 479*a0747c9fSpatrick for (opt::Arg *Arg : Args.filtered(OPT_INPUT)) 480*a0747c9fSpatrick Inputs.push_back(Arg->getValue()); 481*a0747c9fSpatrick if (opt::Arg *Arg = Args.getLastArg(OPT_REM)) { 482*a0747c9fSpatrick for (const char *Val : Arg->getValues()) 483*a0747c9fSpatrick Inputs.push_back(Val); 484061da546Spatrick } 485*a0747c9fSpatrick if (Inputs.empty() && connection_fd == -1) { 486*a0747c9fSpatrick WithColor::error() << "no connection arguments\n" << HelpText; 487*a0747c9fSpatrick return 1; 488061da546Spatrick } 489061da546Spatrick 490061da546Spatrick NativeProcessFactory factory; 491061da546Spatrick GDBRemoteCommunicationServerLLGS gdb_server(mainloop, factory); 492061da546Spatrick 493*a0747c9fSpatrick llvm::StringRef host_and_port; 494*a0747c9fSpatrick if (!Inputs.empty()) { 495*a0747c9fSpatrick host_and_port = Inputs.front(); 496*a0747c9fSpatrick Inputs.erase(Inputs.begin()); 497*a0747c9fSpatrick } 498061da546Spatrick 499061da546Spatrick // Any arguments left over are for the program that we need to launch. If 500061da546Spatrick // there 501061da546Spatrick // are no arguments, then the GDB server will start up and wait for an 'A' 502061da546Spatrick // packet 503061da546Spatrick // to launch a program, or a vAttach packet to attach to an existing process, 504061da546Spatrick // unless 505061da546Spatrick // explicitly asked to attach with the --attach={pid|program_name} form. 506061da546Spatrick if (!attach_target.empty()) 507061da546Spatrick handle_attach(gdb_server, attach_target); 508*a0747c9fSpatrick else if (!Inputs.empty()) 509*a0747c9fSpatrick handle_launch(gdb_server, Inputs); 510061da546Spatrick 511061da546Spatrick // Print version info. 512061da546Spatrick printf("%s-%s\n", LLGS_PROGRAM_NAME, LLGS_VERSION_STR); 513061da546Spatrick 514061da546Spatrick ConnectToRemote(mainloop, gdb_server, reverse_connect, host_and_port, 515061da546Spatrick progname, subcommand, named_pipe_path.c_str(), 516061da546Spatrick unnamed_pipe, connection_fd); 517061da546Spatrick 518061da546Spatrick if (!gdb_server.IsConnected()) { 519061da546Spatrick fprintf(stderr, "no connection information provided, unable to run\n"); 520061da546Spatrick return 1; 521061da546Spatrick } 522061da546Spatrick 523061da546Spatrick Status ret = mainloop.Run(); 524061da546Spatrick if (ret.Fail()) { 525061da546Spatrick fprintf(stderr, "lldb-server terminating due to error: %s\n", 526061da546Spatrick ret.AsCString()); 527061da546Spatrick return 1; 528061da546Spatrick } 529061da546Spatrick fprintf(stderr, "lldb-server exiting...\n"); 530061da546Spatrick 531061da546Spatrick return 0; 532061da546Spatrick } 533