xref: /openbsd-src/gnu/llvm/lldb/tools/lldb-server/lldb-gdbserver.cpp (revision 101d251d5caf88a9341f3045ab62e122abae1b90)
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 
9a0747c9fSpatrick #include <cerrno>
10a0747c9fSpatrick #include <cstdint>
11a0747c9fSpatrick #include <cstdio>
12a0747c9fSpatrick #include <cstdlib>
13a0747c9fSpatrick #include <cstring>
14061da546Spatrick 
15061da546Spatrick #ifndef _WIN32
16a0747c9fSpatrick #include <csignal>
17061da546Spatrick #include <unistd.h>
18061da546Spatrick #endif
19061da546Spatrick 
20061da546Spatrick #include "LLDBServerUtilities.h"
21061da546Spatrick #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
22061da546Spatrick #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
23061da546Spatrick #include "lldb/Host/Config.h"
24061da546Spatrick #include "lldb/Host/ConnectionFileDescriptor.h"
25061da546Spatrick #include "lldb/Host/FileSystem.h"
26061da546Spatrick #include "lldb/Host/Pipe.h"
27061da546Spatrick #include "lldb/Host/Socket.h"
28061da546Spatrick #include "lldb/Host/common/NativeProcessProtocol.h"
29061da546Spatrick #include "lldb/Target/Process.h"
30*101d251dSrobert #include "lldb/Utility/LLDBLog.h"
31061da546Spatrick #include "lldb/Utility/Status.h"
32061da546Spatrick #include "llvm/ADT/StringRef.h"
33a0747c9fSpatrick #include "llvm/Option/ArgList.h"
34a0747c9fSpatrick #include "llvm/Option/OptTable.h"
35a0747c9fSpatrick #include "llvm/Option/Option.h"
36061da546Spatrick #include "llvm/Support/Errno.h"
37a0747c9fSpatrick #include "llvm/Support/WithColor.h"
38061da546Spatrick 
39061da546Spatrick #if defined(__linux__)
40061da546Spatrick #include "Plugins/Process/Linux/NativeProcessLinux.h"
41a0747c9fSpatrick #elif defined(__FreeBSD__)
42a0747c9fSpatrick #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
43061da546Spatrick #elif defined(__NetBSD__)
44061da546Spatrick #include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
45adae0cfdSpatrick #elif defined(__OpenBSD__)
46adae0cfdSpatrick #include "Plugins/Process/OpenBSD/NativeProcessOpenBSD.h"
47061da546Spatrick #elif defined(_WIN32)
48061da546Spatrick #include "Plugins/Process/Windows/Common/NativeProcessWindows.h"
49061da546Spatrick #endif
50061da546Spatrick 
51061da546Spatrick #ifndef LLGS_PROGRAM_NAME
52061da546Spatrick #define LLGS_PROGRAM_NAME "lldb-server"
53061da546Spatrick #endif
54061da546Spatrick 
55061da546Spatrick #ifndef LLGS_VERSION_STR
56061da546Spatrick #define LLGS_VERSION_STR "local_build"
57061da546Spatrick #endif
58061da546Spatrick 
59061da546Spatrick using namespace llvm;
60061da546Spatrick using namespace lldb;
61061da546Spatrick using namespace lldb_private;
62061da546Spatrick using namespace lldb_private::lldb_server;
63061da546Spatrick using namespace lldb_private::process_gdb_remote;
64061da546Spatrick 
65061da546Spatrick namespace {
66061da546Spatrick #if defined(__linux__)
67061da546Spatrick typedef process_linux::NativeProcessLinux::Factory NativeProcessFactory;
68a0747c9fSpatrick #elif defined(__FreeBSD__)
69a0747c9fSpatrick typedef process_freebsd::NativeProcessFreeBSD::Factory NativeProcessFactory;
70061da546Spatrick #elif defined(__NetBSD__)
71061da546Spatrick typedef process_netbsd::NativeProcessNetBSD::Factory NativeProcessFactory;
72adae0cfdSpatrick #elif defined(__OpenBSD__)
73adae0cfdSpatrick typedef process_openbsd::NativeProcessOpenBSD::Factory NativeProcessFactory;
74061da546Spatrick #elif defined(_WIN32)
75061da546Spatrick typedef NativeProcessWindows::Factory NativeProcessFactory;
76061da546Spatrick #else
77061da546Spatrick // Dummy implementation to make sure the code compiles
78061da546Spatrick class NativeProcessFactory : public NativeProcessProtocol::Factory {
79061da546Spatrick public:
80061da546Spatrick   llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
81061da546Spatrick   Launch(ProcessLaunchInfo &launch_info,
82061da546Spatrick          NativeProcessProtocol::NativeDelegate &delegate,
83061da546Spatrick          MainLoop &mainloop) const override {
84061da546Spatrick     llvm_unreachable("Not implemented");
85061da546Spatrick   }
86061da546Spatrick   llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
87061da546Spatrick   Attach(lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &delegate,
88061da546Spatrick          MainLoop &mainloop) const override {
89061da546Spatrick     llvm_unreachable("Not implemented");
90061da546Spatrick   }
91061da546Spatrick };
92061da546Spatrick #endif
93061da546Spatrick }
94061da546Spatrick 
95061da546Spatrick #ifndef _WIN32
96061da546Spatrick // Watch for signals
97061da546Spatrick static int g_sighup_received_count = 0;
98061da546Spatrick 
sighup_handler(MainLoopBase & mainloop)99061da546Spatrick static void sighup_handler(MainLoopBase &mainloop) {
100061da546Spatrick   ++g_sighup_received_count;
101061da546Spatrick 
102*101d251dSrobert   Log *log = GetLog(LLDBLog::Process);
103061da546Spatrick   LLDB_LOGF(log, "lldb-server:%s swallowing SIGHUP (receive count=%d)",
104061da546Spatrick             __FUNCTION__, g_sighup_received_count);
105061da546Spatrick 
106061da546Spatrick   if (g_sighup_received_count >= 2)
107061da546Spatrick     mainloop.RequestTermination();
108061da546Spatrick }
109061da546Spatrick #endif // #ifndef _WIN32
110061da546Spatrick 
handle_attach_to_pid(GDBRemoteCommunicationServerLLGS & gdb_server,lldb::pid_t pid)111061da546Spatrick void handle_attach_to_pid(GDBRemoteCommunicationServerLLGS &gdb_server,
112061da546Spatrick                           lldb::pid_t pid) {
113061da546Spatrick   Status error = gdb_server.AttachToProcess(pid);
114061da546Spatrick   if (error.Fail()) {
115061da546Spatrick     fprintf(stderr, "error: failed to attach to pid %" PRIu64 ": %s\n", pid,
116061da546Spatrick             error.AsCString());
117061da546Spatrick     exit(1);
118061da546Spatrick   }
119061da546Spatrick }
120061da546Spatrick 
handle_attach_to_process_name(GDBRemoteCommunicationServerLLGS & gdb_server,const std::string & process_name)121061da546Spatrick void handle_attach_to_process_name(GDBRemoteCommunicationServerLLGS &gdb_server,
122061da546Spatrick                                    const std::string &process_name) {
123061da546Spatrick   // FIXME implement.
124061da546Spatrick }
125061da546Spatrick 
handle_attach(GDBRemoteCommunicationServerLLGS & gdb_server,const std::string & attach_target)126061da546Spatrick void handle_attach(GDBRemoteCommunicationServerLLGS &gdb_server,
127061da546Spatrick                    const std::string &attach_target) {
128061da546Spatrick   assert(!attach_target.empty() && "attach_target cannot be empty");
129061da546Spatrick 
130061da546Spatrick   // First check if the attach_target is convertible to a long. If so, we'll use
131061da546Spatrick   // it as a pid.
132061da546Spatrick   char *end_p = nullptr;
133061da546Spatrick   const long int pid = strtol(attach_target.c_str(), &end_p, 10);
134061da546Spatrick 
135061da546Spatrick   // We'll call it a match if the entire argument is consumed.
136061da546Spatrick   if (end_p &&
137061da546Spatrick       static_cast<size_t>(end_p - attach_target.c_str()) ==
138061da546Spatrick           attach_target.size())
139061da546Spatrick     handle_attach_to_pid(gdb_server, static_cast<lldb::pid_t>(pid));
140061da546Spatrick   else
141061da546Spatrick     handle_attach_to_process_name(gdb_server, attach_target);
142061da546Spatrick }
143061da546Spatrick 
handle_launch(GDBRemoteCommunicationServerLLGS & gdb_server,llvm::ArrayRef<llvm::StringRef> Arguments)144a0747c9fSpatrick void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server,
145a0747c9fSpatrick                    llvm::ArrayRef<llvm::StringRef> Arguments) {
146061da546Spatrick   ProcessLaunchInfo info;
147061da546Spatrick   info.GetFlags().Set(eLaunchFlagStopAtEntry | eLaunchFlagDebug |
148061da546Spatrick                       eLaunchFlagDisableASLR);
149a0747c9fSpatrick   info.SetArguments(Args(Arguments), true);
150061da546Spatrick 
151061da546Spatrick   llvm::SmallString<64> cwd;
152061da546Spatrick   if (std::error_code ec = llvm::sys::fs::current_path(cwd)) {
153061da546Spatrick     llvm::errs() << "Error getting current directory: " << ec.message() << "\n";
154061da546Spatrick     exit(1);
155061da546Spatrick   }
156061da546Spatrick   FileSpec cwd_spec(cwd);
157061da546Spatrick   FileSystem::Instance().Resolve(cwd_spec);
158061da546Spatrick   info.SetWorkingDirectory(cwd_spec);
159061da546Spatrick   info.GetEnvironment() = Host::GetEnvironment();
160061da546Spatrick 
161061da546Spatrick   gdb_server.SetLaunchInfo(info);
162061da546Spatrick 
163061da546Spatrick   Status error = gdb_server.LaunchProcess();
164061da546Spatrick   if (error.Fail()) {
165061da546Spatrick     llvm::errs() << llvm::formatv("error: failed to launch '{0}': {1}\n",
166a0747c9fSpatrick                                   Arguments[0], error);
167061da546Spatrick     exit(1);
168061da546Spatrick   }
169061da546Spatrick }
170061da546Spatrick 
writeSocketIdToPipe(Pipe & port_pipe,llvm::StringRef socket_id)171*101d251dSrobert Status writeSocketIdToPipe(Pipe &port_pipe, llvm::StringRef socket_id) {
172061da546Spatrick   size_t bytes_written = 0;
173061da546Spatrick   // Write the port number as a C string with the NULL terminator.
174*101d251dSrobert   return port_pipe.Write(socket_id.data(), socket_id.size() + 1, bytes_written);
175061da546Spatrick }
176061da546Spatrick 
writeSocketIdToPipe(const char * const named_pipe_path,llvm::StringRef socket_id)177061da546Spatrick Status writeSocketIdToPipe(const char *const named_pipe_path,
178*101d251dSrobert                            llvm::StringRef socket_id) {
179061da546Spatrick   Pipe port_name_pipe;
180061da546Spatrick   // Wait for 10 seconds for pipe to be opened.
181061da546Spatrick   auto error = port_name_pipe.OpenAsWriterWithTimeout(named_pipe_path, false,
182061da546Spatrick                                                       std::chrono::seconds{10});
183061da546Spatrick   if (error.Fail())
184061da546Spatrick     return error;
185061da546Spatrick   return writeSocketIdToPipe(port_name_pipe, socket_id);
186061da546Spatrick }
187061da546Spatrick 
writeSocketIdToPipe(lldb::pipe_t unnamed_pipe,llvm::StringRef socket_id)188061da546Spatrick Status writeSocketIdToPipe(lldb::pipe_t unnamed_pipe,
189*101d251dSrobert                            llvm::StringRef socket_id) {
190061da546Spatrick   Pipe port_pipe{LLDB_INVALID_PIPE, unnamed_pipe};
191061da546Spatrick   return writeSocketIdToPipe(port_pipe, socket_id);
192061da546Spatrick }
193061da546Spatrick 
ConnectToRemote(MainLoop & mainloop,GDBRemoteCommunicationServerLLGS & gdb_server,bool reverse_connect,llvm::StringRef host_and_port,const char * const progname,const char * const subcommand,const char * const named_pipe_path,pipe_t unnamed_pipe,int connection_fd)194061da546Spatrick void ConnectToRemote(MainLoop &mainloop,
195061da546Spatrick                      GDBRemoteCommunicationServerLLGS &gdb_server,
196a0747c9fSpatrick                      bool reverse_connect, llvm::StringRef host_and_port,
197061da546Spatrick                      const char *const progname, const char *const subcommand,
198061da546Spatrick                      const char *const named_pipe_path, pipe_t unnamed_pipe,
199061da546Spatrick                      int connection_fd) {
200061da546Spatrick   Status error;
201061da546Spatrick 
202061da546Spatrick   std::unique_ptr<Connection> connection_up;
203*101d251dSrobert   std::string url;
204*101d251dSrobert 
205061da546Spatrick   if (connection_fd != -1) {
206*101d251dSrobert     url = llvm::formatv("fd://{0}", connection_fd).str();
207061da546Spatrick 
208061da546Spatrick     // Create the connection.
209061da546Spatrick #if LLDB_ENABLE_POSIX && !defined _WIN32
210061da546Spatrick     ::fcntl(connection_fd, F_SETFD, FD_CLOEXEC);
211061da546Spatrick #endif
212a0747c9fSpatrick   } else if (!host_and_port.empty()) {
213*101d251dSrobert     llvm::Expected<std::string> url_exp =
214*101d251dSrobert         LLGSArgToURL(host_and_port, reverse_connect);
215*101d251dSrobert     if (!url_exp) {
216*101d251dSrobert       llvm::errs() << llvm::formatv("error: invalid host:port or URL '{0}': "
217*101d251dSrobert                                     "{1}\n",
218*101d251dSrobert                                     host_and_port,
219*101d251dSrobert                                     llvm::toString(url_exp.takeError()));
220061da546Spatrick       exit(-1);
221061da546Spatrick     }
222*101d251dSrobert 
223*101d251dSrobert     url = std::move(url_exp.get());
224061da546Spatrick   }
225*101d251dSrobert 
226*101d251dSrobert   if (!url.empty()) {
227*101d251dSrobert     // Create the connection or server.
228*101d251dSrobert     std::unique_ptr<ConnectionFileDescriptor> conn_fd_up{
229*101d251dSrobert         new ConnectionFileDescriptor};
230*101d251dSrobert     auto connection_result = conn_fd_up->Connect(
231*101d251dSrobert         url,
232*101d251dSrobert         [named_pipe_path, unnamed_pipe](llvm::StringRef socket_id) {
233*101d251dSrobert           // If we have a named pipe to write the socket id back to, do that
234*101d251dSrobert           // now.
235061da546Spatrick           if (named_pipe_path && named_pipe_path[0]) {
236*101d251dSrobert             Status error = writeSocketIdToPipe(named_pipe_path, socket_id);
237061da546Spatrick             if (error.Fail())
238*101d251dSrobert               llvm::errs() << llvm::formatv(
239*101d251dSrobert                   "failed to write to the named peipe '{0}': {1}\n",
240061da546Spatrick                   named_pipe_path, error.AsCString());
241061da546Spatrick           }
242*101d251dSrobert           // If we have an unnamed pipe to write the socket id back to, do
243*101d251dSrobert           // that now.
244061da546Spatrick           else if (unnamed_pipe != LLDB_INVALID_PIPE) {
245*101d251dSrobert             Status error = writeSocketIdToPipe(unnamed_pipe, socket_id);
246061da546Spatrick             if (error.Fail())
247*101d251dSrobert               llvm::errs() << llvm::formatv(
248*101d251dSrobert                   "failed to write to the unnamed pipe: {0}\n", error);
249061da546Spatrick           }
250*101d251dSrobert         },
251*101d251dSrobert         &error);
252061da546Spatrick 
253061da546Spatrick     if (error.Fail()) {
254*101d251dSrobert       llvm::errs() << llvm::formatv(
255*101d251dSrobert           "error: failed to connect to client at '{0}': {1}\n", url, error);
256*101d251dSrobert       exit(-1);
257061da546Spatrick     }
258*101d251dSrobert     if (connection_result != eConnectionStatusSuccess) {
259*101d251dSrobert       llvm::errs() << llvm::formatv(
260*101d251dSrobert           "error: failed to connect to client at '{0}' "
261*101d251dSrobert           "(connection status: {1})\n",
262*101d251dSrobert           url, static_cast<int>(connection_result));
263*101d251dSrobert       exit(-1);
264061da546Spatrick     }
265*101d251dSrobert     connection_up = std::move(conn_fd_up);
266061da546Spatrick   }
267061da546Spatrick   error = gdb_server.InitializeConnection(std::move(connection_up));
268061da546Spatrick   if (error.Fail()) {
269*101d251dSrobert     llvm::errs() << llvm::formatv("failed to initialize connection\n", error);
270061da546Spatrick     exit(-1);
271061da546Spatrick   }
272*101d251dSrobert   llvm::outs() << "Connection established.\n";
273061da546Spatrick }
274061da546Spatrick 
275a0747c9fSpatrick namespace {
276a0747c9fSpatrick enum ID {
277a0747c9fSpatrick   OPT_INVALID = 0, // This is not an option ID.
278a0747c9fSpatrick #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
279a0747c9fSpatrick                HELPTEXT, METAVAR, VALUES)                                      \
280a0747c9fSpatrick   OPT_##ID,
281a0747c9fSpatrick #include "LLGSOptions.inc"
282a0747c9fSpatrick #undef OPTION
283a0747c9fSpatrick };
284a0747c9fSpatrick 
285*101d251dSrobert #define PREFIX(NAME, VALUE)                                                    \
286*101d251dSrobert   constexpr llvm::StringLiteral NAME##_init[] = VALUE;                         \
287*101d251dSrobert   constexpr llvm::ArrayRef<llvm::StringLiteral> NAME(                          \
288*101d251dSrobert       NAME##_init, std::size(NAME##_init) - 1);
289a0747c9fSpatrick #include "LLGSOptions.inc"
290a0747c9fSpatrick #undef PREFIX
291a0747c9fSpatrick 
292*101d251dSrobert static constexpr opt::OptTable::Info InfoTable[] = {
293a0747c9fSpatrick #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
294a0747c9fSpatrick                HELPTEXT, METAVAR, VALUES)                                      \
295a0747c9fSpatrick   {                                                                            \
296a0747c9fSpatrick       PREFIX,      NAME,      HELPTEXT,                                        \
297a0747c9fSpatrick       METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
298a0747c9fSpatrick       PARAM,       FLAGS,     OPT_##GROUP,                                     \
299a0747c9fSpatrick       OPT_##ALIAS, ALIASARGS, VALUES},
300a0747c9fSpatrick #include "LLGSOptions.inc"
301a0747c9fSpatrick #undef OPTION
302a0747c9fSpatrick };
303a0747c9fSpatrick 
304*101d251dSrobert class LLGSOptTable : public opt::GenericOptTable {
305a0747c9fSpatrick public:
LLGSOptTable()306*101d251dSrobert   LLGSOptTable() : opt::GenericOptTable(InfoTable) {}
307a0747c9fSpatrick 
PrintHelp(llvm::StringRef Name)308a0747c9fSpatrick   void PrintHelp(llvm::StringRef Name) {
309a0747c9fSpatrick     std::string Usage =
310a0747c9fSpatrick         (Name + " [options] [[host]:port] [[--] program args...]").str();
311a0747c9fSpatrick     OptTable::printHelp(llvm::outs(), Usage.c_str(), "lldb-server");
312a0747c9fSpatrick     llvm::outs() << R"(
313a0747c9fSpatrick DESCRIPTION
314a0747c9fSpatrick   lldb-server connects to the LLDB client, which drives the debugging session.
315a0747c9fSpatrick   If no connection options are given, the [host]:port argument must be present
316a0747c9fSpatrick   and will denote the address that lldb-server will listen on. [host] defaults
317a0747c9fSpatrick   to "localhost" if empty. Port can be zero, in which case the port number will
318a0747c9fSpatrick   be chosen dynamically and written to destinations given by --named-pipe and
319a0747c9fSpatrick   --pipe arguments.
320a0747c9fSpatrick 
321a0747c9fSpatrick   If no target is selected at startup, lldb-server can be directed by the LLDB
322a0747c9fSpatrick   client to launch or attach to a process.
323a0747c9fSpatrick 
324a0747c9fSpatrick )";
325a0747c9fSpatrick   }
326a0747c9fSpatrick };
327a0747c9fSpatrick } // namespace
328a0747c9fSpatrick 
main_gdbserver(int argc,char * argv[])329061da546Spatrick int main_gdbserver(int argc, char *argv[]) {
330061da546Spatrick   Status error;
331061da546Spatrick   MainLoop mainloop;
332061da546Spatrick #ifndef _WIN32
333061da546Spatrick   // Setup signal handlers first thing.
334061da546Spatrick   signal(SIGPIPE, SIG_IGN);
335061da546Spatrick   MainLoop::SignalHandleUP sighup_handle =
336061da546Spatrick       mainloop.RegisterSignal(SIGHUP, sighup_handler, error);
337061da546Spatrick #endif
338061da546Spatrick 
339061da546Spatrick   const char *progname = argv[0];
340061da546Spatrick   const char *subcommand = argv[1];
341061da546Spatrick   std::string attach_target;
342061da546Spatrick   std::string named_pipe_path;
343061da546Spatrick   std::string log_file;
344061da546Spatrick   StringRef
345061da546Spatrick       log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"
346061da546Spatrick   lldb::pipe_t unnamed_pipe = LLDB_INVALID_PIPE;
347061da546Spatrick   bool reverse_connect = false;
348061da546Spatrick   int connection_fd = -1;
349061da546Spatrick 
350061da546Spatrick   // ProcessLaunchInfo launch_info;
351061da546Spatrick   ProcessAttachInfo attach_info;
352061da546Spatrick 
353a0747c9fSpatrick   LLGSOptTable Opts;
354a0747c9fSpatrick   llvm::BumpPtrAllocator Alloc;
355a0747c9fSpatrick   llvm::StringSaver Saver(Alloc);
356a0747c9fSpatrick   bool HasError = false;
357a0747c9fSpatrick   opt::InputArgList Args = Opts.parseArgs(argc - 1, argv + 1, OPT_UNKNOWN,
358a0747c9fSpatrick                                           Saver, [&](llvm::StringRef Msg) {
359a0747c9fSpatrick                                             WithColor::error() << Msg << "\n";
360a0747c9fSpatrick                                             HasError = true;
361a0747c9fSpatrick                                           });
362a0747c9fSpatrick   std::string Name =
363a0747c9fSpatrick       (llvm::sys::path::filename(argv[0]) + " g[dbserver]").str();
364a0747c9fSpatrick   std::string HelpText =
365a0747c9fSpatrick       "Use '" + Name + " --help' for a complete list of options.\n";
366a0747c9fSpatrick   if (HasError) {
367a0747c9fSpatrick     llvm::errs() << HelpText;
368a0747c9fSpatrick     return 1;
369a0747c9fSpatrick   }
370061da546Spatrick 
371a0747c9fSpatrick   if (Args.hasArg(OPT_help)) {
372a0747c9fSpatrick     Opts.PrintHelp(Name);
373a0747c9fSpatrick     return 0;
374a0747c9fSpatrick   }
375061da546Spatrick 
376061da546Spatrick #ifndef _WIN32
377a0747c9fSpatrick   if (Args.hasArg(OPT_setsid)) {
378061da546Spatrick     // Put llgs into a new session. Terminals group processes
379061da546Spatrick     // into sessions and when a special terminal key sequences
380061da546Spatrick     // (like control+c) are typed they can cause signals to go out to
381061da546Spatrick     // all processes in a session. Using this --setsid (-S) option
382061da546Spatrick     // will cause debugserver to run in its own sessions and be free
383061da546Spatrick     // from such issues.
384061da546Spatrick     //
385061da546Spatrick     // This is useful when llgs is spawned from a command
386061da546Spatrick     // line application that uses llgs to do the debugging,
387061da546Spatrick     // yet that application doesn't want llgs receiving the
388061da546Spatrick     // signals sent to the session (i.e. dying when anyone hits ^C).
389061da546Spatrick     {
390061da546Spatrick       const ::pid_t new_sid = setsid();
391061da546Spatrick       if (new_sid == -1) {
392a0747c9fSpatrick         WithColor::warning()
393a0747c9fSpatrick             << llvm::formatv("failed to set new session id for {0} ({1})\n",
394a0747c9fSpatrick                              LLGS_PROGRAM_NAME, llvm::sys::StrError());
395061da546Spatrick       }
396061da546Spatrick     }
397a0747c9fSpatrick   }
398061da546Spatrick #endif
399061da546Spatrick 
400a0747c9fSpatrick   log_file = Args.getLastArgValue(OPT_log_file).str();
401a0747c9fSpatrick   log_channels = Args.getLastArgValue(OPT_log_channels);
402a0747c9fSpatrick   named_pipe_path = Args.getLastArgValue(OPT_named_pipe).str();
403a0747c9fSpatrick   reverse_connect = Args.hasArg(OPT_reverse_connect);
404a0747c9fSpatrick   attach_target = Args.getLastArgValue(OPT_attach).str();
405a0747c9fSpatrick   if (Args.hasArg(OPT_pipe)) {
406a0747c9fSpatrick     uint64_t Arg;
407a0747c9fSpatrick     if (!llvm::to_integer(Args.getLastArgValue(OPT_pipe), Arg)) {
408a0747c9fSpatrick       WithColor::error() << "invalid '--pipe' argument\n" << HelpText;
409a0747c9fSpatrick       return 1;
410061da546Spatrick     }
411a0747c9fSpatrick     unnamed_pipe = (pipe_t)Arg;
412061da546Spatrick   }
413a0747c9fSpatrick   if (Args.hasArg(OPT_fd)) {
414a0747c9fSpatrick     if (!llvm::to_integer(Args.getLastArgValue(OPT_fd), connection_fd)) {
415a0747c9fSpatrick       WithColor::error() << "invalid '--fd' argument\n" << HelpText;
416a0747c9fSpatrick       return 1;
417a0747c9fSpatrick     }
418061da546Spatrick   }
419061da546Spatrick 
420061da546Spatrick   if (!LLDBServerUtilities::SetupLogging(
421061da546Spatrick           log_file, log_channels,
422061da546Spatrick           LLDB_LOG_OPTION_PREPEND_TIMESTAMP |
423061da546Spatrick               LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION))
424061da546Spatrick     return -1;
425061da546Spatrick 
426a0747c9fSpatrick   std::vector<llvm::StringRef> Inputs;
427a0747c9fSpatrick   for (opt::Arg *Arg : Args.filtered(OPT_INPUT))
428a0747c9fSpatrick     Inputs.push_back(Arg->getValue());
429a0747c9fSpatrick   if (opt::Arg *Arg = Args.getLastArg(OPT_REM)) {
430a0747c9fSpatrick     for (const char *Val : Arg->getValues())
431a0747c9fSpatrick       Inputs.push_back(Val);
432061da546Spatrick   }
433a0747c9fSpatrick   if (Inputs.empty() && connection_fd == -1) {
434a0747c9fSpatrick     WithColor::error() << "no connection arguments\n" << HelpText;
435a0747c9fSpatrick     return 1;
436061da546Spatrick   }
437061da546Spatrick 
438061da546Spatrick   NativeProcessFactory factory;
439061da546Spatrick   GDBRemoteCommunicationServerLLGS gdb_server(mainloop, factory);
440061da546Spatrick 
441a0747c9fSpatrick   llvm::StringRef host_and_port;
442a0747c9fSpatrick   if (!Inputs.empty()) {
443a0747c9fSpatrick     host_and_port = Inputs.front();
444a0747c9fSpatrick     Inputs.erase(Inputs.begin());
445a0747c9fSpatrick   }
446061da546Spatrick 
447061da546Spatrick   // Any arguments left over are for the program that we need to launch. If
448061da546Spatrick   // there
449061da546Spatrick   // are no arguments, then the GDB server will start up and wait for an 'A'
450061da546Spatrick   // packet
451061da546Spatrick   // to launch a program, or a vAttach packet to attach to an existing process,
452061da546Spatrick   // unless
453061da546Spatrick   // explicitly asked to attach with the --attach={pid|program_name} form.
454061da546Spatrick   if (!attach_target.empty())
455061da546Spatrick     handle_attach(gdb_server, attach_target);
456a0747c9fSpatrick   else if (!Inputs.empty())
457a0747c9fSpatrick     handle_launch(gdb_server, Inputs);
458061da546Spatrick 
459061da546Spatrick   // Print version info.
460061da546Spatrick   printf("%s-%s\n", LLGS_PROGRAM_NAME, LLGS_VERSION_STR);
461061da546Spatrick 
462061da546Spatrick   ConnectToRemote(mainloop, gdb_server, reverse_connect, host_and_port,
463061da546Spatrick                   progname, subcommand, named_pipe_path.c_str(),
464061da546Spatrick                   unnamed_pipe, connection_fd);
465061da546Spatrick 
466061da546Spatrick   if (!gdb_server.IsConnected()) {
467061da546Spatrick     fprintf(stderr, "no connection information provided, unable to run\n");
468061da546Spatrick     return 1;
469061da546Spatrick   }
470061da546Spatrick 
471061da546Spatrick   Status ret = mainloop.Run();
472061da546Spatrick   if (ret.Fail()) {
473061da546Spatrick     fprintf(stderr, "lldb-server terminating due to error: %s\n",
474061da546Spatrick             ret.AsCString());
475061da546Spatrick     return 1;
476061da546Spatrick   }
477061da546Spatrick   fprintf(stderr, "lldb-server exiting...\n");
478061da546Spatrick 
479061da546Spatrick   return 0;
480061da546Spatrick }
481