xref: /openbsd-src/gnu/llvm/lldb/tools/lldb-server/lldb-gdbserver.cpp (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 //===-- lldb-gdbserver.cpp --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <cerrno>
10 #include <cstdint>
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
14 
15 #ifndef _WIN32
16 #include <csignal>
17 #include <unistd.h>
18 #endif
19 
20 #include "Acceptor.h"
21 #include "LLDBServerUtilities.h"
22 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h"
23 #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
24 #include "lldb/Host/Config.h"
25 #include "lldb/Host/ConnectionFileDescriptor.h"
26 #include "lldb/Host/FileSystem.h"
27 #include "lldb/Host/Pipe.h"
28 #include "lldb/Host/Socket.h"
29 #include "lldb/Host/StringConvert.h"
30 #include "lldb/Host/common/NativeProcessProtocol.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Utility/Status.h"
33 #include "llvm/ADT/StringRef.h"
34 #include "llvm/Option/ArgList.h"
35 #include "llvm/Option/OptTable.h"
36 #include "llvm/Option/Option.h"
37 #include "llvm/Support/Errno.h"
38 #include "llvm/Support/WithColor.h"
39 
40 #if defined(__linux__)
41 #include "Plugins/Process/Linux/NativeProcessLinux.h"
42 #elif defined(__FreeBSD__)
43 #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
44 #elif defined(__NetBSD__)
45 #include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
46 #elif defined(__OpenBSD__)
47 #include "Plugins/Process/OpenBSD/NativeProcessOpenBSD.h"
48 #elif defined(_WIN32)
49 #include "Plugins/Process/Windows/Common/NativeProcessWindows.h"
50 #endif
51 
52 #ifndef LLGS_PROGRAM_NAME
53 #define LLGS_PROGRAM_NAME "lldb-server"
54 #endif
55 
56 #ifndef LLGS_VERSION_STR
57 #define LLGS_VERSION_STR "local_build"
58 #endif
59 
60 using namespace llvm;
61 using namespace lldb;
62 using namespace lldb_private;
63 using namespace lldb_private::lldb_server;
64 using namespace lldb_private::process_gdb_remote;
65 
66 namespace {
67 #if defined(__linux__)
68 typedef process_linux::NativeProcessLinux::Factory NativeProcessFactory;
69 #elif defined(__FreeBSD__)
70 typedef process_freebsd::NativeProcessFreeBSD::Factory NativeProcessFactory;
71 #elif defined(__NetBSD__)
72 typedef process_netbsd::NativeProcessNetBSD::Factory NativeProcessFactory;
73 #elif defined(__OpenBSD__)
74 typedef process_openbsd::NativeProcessOpenBSD::Factory NativeProcessFactory;
75 #elif defined(_WIN32)
76 typedef NativeProcessWindows::Factory NativeProcessFactory;
77 #else
78 // Dummy implementation to make sure the code compiles
79 class NativeProcessFactory : public NativeProcessProtocol::Factory {
80 public:
81   llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
82   Launch(ProcessLaunchInfo &launch_info,
83          NativeProcessProtocol::NativeDelegate &delegate,
84          MainLoop &mainloop) const override {
85     llvm_unreachable("Not implemented");
86   }
87   llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
88   Attach(lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &delegate,
89          MainLoop &mainloop) const override {
90     llvm_unreachable("Not implemented");
91   }
92 };
93 #endif
94 }
95 
96 #ifndef _WIN32
97 // Watch for signals
98 static int g_sighup_received_count = 0;
99 
100 static void sighup_handler(MainLoopBase &mainloop) {
101   ++g_sighup_received_count;
102 
103   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
104   LLDB_LOGF(log, "lldb-server:%s swallowing SIGHUP (receive count=%d)",
105             __FUNCTION__, g_sighup_received_count);
106 
107   if (g_sighup_received_count >= 2)
108     mainloop.RequestTermination();
109 }
110 #endif // #ifndef _WIN32
111 
112 void handle_attach_to_pid(GDBRemoteCommunicationServerLLGS &gdb_server,
113                           lldb::pid_t pid) {
114   Status error = gdb_server.AttachToProcess(pid);
115   if (error.Fail()) {
116     fprintf(stderr, "error: failed to attach to pid %" PRIu64 ": %s\n", pid,
117             error.AsCString());
118     exit(1);
119   }
120 }
121 
122 void handle_attach_to_process_name(GDBRemoteCommunicationServerLLGS &gdb_server,
123                                    const std::string &process_name) {
124   // FIXME implement.
125 }
126 
127 void handle_attach(GDBRemoteCommunicationServerLLGS &gdb_server,
128                    const std::string &attach_target) {
129   assert(!attach_target.empty() && "attach_target cannot be empty");
130 
131   // First check if the attach_target is convertible to a long. If so, we'll use
132   // it as a pid.
133   char *end_p = nullptr;
134   const long int pid = strtol(attach_target.c_str(), &end_p, 10);
135 
136   // We'll call it a match if the entire argument is consumed.
137   if (end_p &&
138       static_cast<size_t>(end_p - attach_target.c_str()) ==
139           attach_target.size())
140     handle_attach_to_pid(gdb_server, static_cast<lldb::pid_t>(pid));
141   else
142     handle_attach_to_process_name(gdb_server, attach_target);
143 }
144 
145 void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server,
146                    llvm::ArrayRef<llvm::StringRef> Arguments) {
147   ProcessLaunchInfo info;
148   info.GetFlags().Set(eLaunchFlagStopAtEntry | eLaunchFlagDebug |
149                       eLaunchFlagDisableASLR);
150   info.SetArguments(Args(Arguments), true);
151 
152   llvm::SmallString<64> cwd;
153   if (std::error_code ec = llvm::sys::fs::current_path(cwd)) {
154     llvm::errs() << "Error getting current directory: " << ec.message() << "\n";
155     exit(1);
156   }
157   FileSpec cwd_spec(cwd);
158   FileSystem::Instance().Resolve(cwd_spec);
159   info.SetWorkingDirectory(cwd_spec);
160   info.GetEnvironment() = Host::GetEnvironment();
161 
162   gdb_server.SetLaunchInfo(info);
163 
164   Status error = gdb_server.LaunchProcess();
165   if (error.Fail()) {
166     llvm::errs() << llvm::formatv("error: failed to launch '{0}': {1}\n",
167                                   Arguments[0], error);
168     exit(1);
169   }
170 }
171 
172 Status writeSocketIdToPipe(Pipe &port_pipe, const std::string &socket_id) {
173   size_t bytes_written = 0;
174   // Write the port number as a C string with the NULL terminator.
175   return port_pipe.Write(socket_id.c_str(), socket_id.size() + 1,
176                          bytes_written);
177 }
178 
179 Status writeSocketIdToPipe(const char *const named_pipe_path,
180                            const std::string &socket_id) {
181   Pipe port_name_pipe;
182   // Wait for 10 seconds for pipe to be opened.
183   auto error = port_name_pipe.OpenAsWriterWithTimeout(named_pipe_path, false,
184                                                       std::chrono::seconds{10});
185   if (error.Fail())
186     return error;
187   return writeSocketIdToPipe(port_name_pipe, socket_id);
188 }
189 
190 Status writeSocketIdToPipe(lldb::pipe_t unnamed_pipe,
191                            const std::string &socket_id) {
192   Pipe port_pipe{LLDB_INVALID_PIPE, unnamed_pipe};
193   return writeSocketIdToPipe(port_pipe, socket_id);
194 }
195 
196 void ConnectToRemote(MainLoop &mainloop,
197                      GDBRemoteCommunicationServerLLGS &gdb_server,
198                      bool reverse_connect, llvm::StringRef host_and_port,
199                      const char *const progname, const char *const subcommand,
200                      const char *const named_pipe_path, pipe_t unnamed_pipe,
201                      int connection_fd) {
202   Status error;
203 
204   std::unique_ptr<Connection> connection_up;
205   if (connection_fd != -1) {
206     // Build the connection string.
207     char connection_url[512];
208     snprintf(connection_url, sizeof(connection_url), "fd://%d", connection_fd);
209 
210     // Create the connection.
211 #if LLDB_ENABLE_POSIX && !defined _WIN32
212     ::fcntl(connection_fd, F_SETFD, FD_CLOEXEC);
213 #endif
214     connection_up.reset(new ConnectionFileDescriptor);
215     auto connection_result = connection_up->Connect(connection_url, &error);
216     if (connection_result != eConnectionStatusSuccess) {
217       fprintf(stderr, "error: failed to connect to client at '%s' "
218                       "(connection status: %d)\n",
219               connection_url, static_cast<int>(connection_result));
220       exit(-1);
221     }
222     if (error.Fail()) {
223       fprintf(stderr, "error: failed to connect to client at '%s': %s\n",
224               connection_url, error.AsCString());
225       exit(-1);
226     }
227   } else if (!host_and_port.empty()) {
228     // Parse out host and port.
229     std::string final_host_and_port;
230     std::string connection_host;
231     std::string connection_port;
232     uint32_t connection_portno = 0;
233 
234     // If host_and_port starts with ':', default the host to be "localhost" and
235     // expect the remainder to be the port.
236     if (host_and_port[0] == ':')
237       final_host_and_port.append("localhost");
238     final_host_and_port.append(host_and_port.str());
239 
240     // Note: use rfind, because the host/port may look like "[::1]:12345".
241     const std::string::size_type colon_pos = final_host_and_port.rfind(':');
242     if (colon_pos != std::string::npos) {
243       connection_host = final_host_and_port.substr(0, colon_pos);
244       connection_port = final_host_and_port.substr(colon_pos + 1);
245       connection_portno = StringConvert::ToUInt32(connection_port.c_str(), 0);
246     }
247 
248 
249     if (reverse_connect) {
250       // llgs will connect to the gdb-remote client.
251 
252       // Ensure we have a port number for the connection.
253       if (connection_portno == 0) {
254         fprintf(stderr, "error: port number must be specified on when using "
255                         "reverse connect\n");
256         exit(1);
257       }
258 
259       // Build the connection string.
260       char connection_url[512];
261       snprintf(connection_url, sizeof(connection_url), "connect://%s",
262                final_host_and_port.c_str());
263 
264       // Create the connection.
265       connection_up.reset(new ConnectionFileDescriptor);
266       auto connection_result = connection_up->Connect(connection_url, &error);
267       if (connection_result != eConnectionStatusSuccess) {
268         fprintf(stderr, "error: failed to connect to client at '%s' "
269                         "(connection status: %d)\n",
270                 connection_url, static_cast<int>(connection_result));
271         exit(-1);
272       }
273       if (error.Fail()) {
274         fprintf(stderr, "error: failed to connect to client at '%s': %s\n",
275                 connection_url, error.AsCString());
276         exit(-1);
277       }
278     } else {
279       std::unique_ptr<Acceptor> acceptor_up(
280           Acceptor::Create(final_host_and_port, false, error));
281       if (error.Fail()) {
282         fprintf(stderr, "failed to create acceptor: %s\n", error.AsCString());
283         exit(1);
284       }
285       error = acceptor_up->Listen(1);
286       if (error.Fail()) {
287         fprintf(stderr, "failed to listen: %s\n", error.AsCString());
288         exit(1);
289       }
290       const std::string socket_id = acceptor_up->GetLocalSocketId();
291       if (!socket_id.empty()) {
292         // If we have a named pipe to write the socket id back to, do that now.
293         if (named_pipe_path && named_pipe_path[0]) {
294           error = writeSocketIdToPipe(named_pipe_path, socket_id);
295           if (error.Fail())
296             fprintf(stderr, "failed to write to the named pipe \'%s\': %s\n",
297                     named_pipe_path, error.AsCString());
298         }
299         // If we have an unnamed pipe to write the socket id back to, do that
300         // now.
301         else if (unnamed_pipe != LLDB_INVALID_PIPE) {
302           error = writeSocketIdToPipe(unnamed_pipe, socket_id);
303           if (error.Fail())
304             fprintf(stderr, "failed to write to the unnamed pipe: %s\n",
305                     error.AsCString());
306         }
307       } else {
308         fprintf(stderr,
309                 "unable to get the socket id for the listening connection\n");
310       }
311 
312       Connection *conn = nullptr;
313       error = acceptor_up->Accept(false, conn);
314       if (error.Fail()) {
315         printf("failed to accept new connection: %s\n", error.AsCString());
316         exit(1);
317       }
318       connection_up.reset(conn);
319     }
320   }
321   error = gdb_server.InitializeConnection(std::move(connection_up));
322   if (error.Fail()) {
323     fprintf(stderr, "Failed to initialize connection: %s\n",
324             error.AsCString());
325     exit(-1);
326   }
327   printf("Connection established.\n");
328 }
329 
330 namespace {
331 enum ID {
332   OPT_INVALID = 0, // This is not an option ID.
333 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
334                HELPTEXT, METAVAR, VALUES)                                      \
335   OPT_##ID,
336 #include "LLGSOptions.inc"
337 #undef OPTION
338 };
339 
340 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
341 #include "LLGSOptions.inc"
342 #undef PREFIX
343 
344 const opt::OptTable::Info InfoTable[] = {
345 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
346                HELPTEXT, METAVAR, VALUES)                                      \
347   {                                                                            \
348       PREFIX,      NAME,      HELPTEXT,                                        \
349       METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
350       PARAM,       FLAGS,     OPT_##GROUP,                                     \
351       OPT_##ALIAS, ALIASARGS, VALUES},
352 #include "LLGSOptions.inc"
353 #undef OPTION
354 };
355 
356 class LLGSOptTable : public opt::OptTable {
357 public:
358   LLGSOptTable() : OptTable(InfoTable) {}
359 
360   void PrintHelp(llvm::StringRef Name) {
361     std::string Usage =
362         (Name + " [options] [[host]:port] [[--] program args...]").str();
363     OptTable::printHelp(llvm::outs(), Usage.c_str(), "lldb-server");
364     llvm::outs() << R"(
365 DESCRIPTION
366   lldb-server connects to the LLDB client, which drives the debugging session.
367   If no connection options are given, the [host]:port argument must be present
368   and will denote the address that lldb-server will listen on. [host] defaults
369   to "localhost" if empty. Port can be zero, in which case the port number will
370   be chosen dynamically and written to destinations given by --named-pipe and
371   --pipe arguments.
372 
373   If no target is selected at startup, lldb-server can be directed by the LLDB
374   client to launch or attach to a process.
375 
376 )";
377   }
378 };
379 } // namespace
380 
381 int main_gdbserver(int argc, char *argv[]) {
382   Status error;
383   MainLoop mainloop;
384 #ifndef _WIN32
385   // Setup signal handlers first thing.
386   signal(SIGPIPE, SIG_IGN);
387   MainLoop::SignalHandleUP sighup_handle =
388       mainloop.RegisterSignal(SIGHUP, sighup_handler, error);
389 #endif
390 
391   const char *progname = argv[0];
392   const char *subcommand = argv[1];
393   std::string attach_target;
394   std::string named_pipe_path;
395   std::string log_file;
396   StringRef
397       log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"
398   lldb::pipe_t unnamed_pipe = LLDB_INVALID_PIPE;
399   bool reverse_connect = false;
400   int connection_fd = -1;
401 
402   // ProcessLaunchInfo launch_info;
403   ProcessAttachInfo attach_info;
404 
405   LLGSOptTable Opts;
406   llvm::BumpPtrAllocator Alloc;
407   llvm::StringSaver Saver(Alloc);
408   bool HasError = false;
409   opt::InputArgList Args = Opts.parseArgs(argc - 1, argv + 1, OPT_UNKNOWN,
410                                           Saver, [&](llvm::StringRef Msg) {
411                                             WithColor::error() << Msg << "\n";
412                                             HasError = true;
413                                           });
414   std::string Name =
415       (llvm::sys::path::filename(argv[0]) + " g[dbserver]").str();
416   std::string HelpText =
417       "Use '" + Name + " --help' for a complete list of options.\n";
418   if (HasError) {
419     llvm::errs() << HelpText;
420     return 1;
421   }
422 
423   if (Args.hasArg(OPT_help)) {
424     Opts.PrintHelp(Name);
425     return 0;
426   }
427 
428 #ifndef _WIN32
429   if (Args.hasArg(OPT_setsid)) {
430     // Put llgs into a new session. Terminals group processes
431     // into sessions and when a special terminal key sequences
432     // (like control+c) are typed they can cause signals to go out to
433     // all processes in a session. Using this --setsid (-S) option
434     // will cause debugserver to run in its own sessions and be free
435     // from such issues.
436     //
437     // This is useful when llgs is spawned from a command
438     // line application that uses llgs to do the debugging,
439     // yet that application doesn't want llgs receiving the
440     // signals sent to the session (i.e. dying when anyone hits ^C).
441     {
442       const ::pid_t new_sid = setsid();
443       if (new_sid == -1) {
444         WithColor::warning()
445             << llvm::formatv("failed to set new session id for {0} ({1})\n",
446                              LLGS_PROGRAM_NAME, llvm::sys::StrError());
447       }
448     }
449   }
450 #endif
451 
452   log_file = Args.getLastArgValue(OPT_log_file).str();
453   log_channels = Args.getLastArgValue(OPT_log_channels);
454   named_pipe_path = Args.getLastArgValue(OPT_named_pipe).str();
455   reverse_connect = Args.hasArg(OPT_reverse_connect);
456   attach_target = Args.getLastArgValue(OPT_attach).str();
457   if (Args.hasArg(OPT_pipe)) {
458     uint64_t Arg;
459     if (!llvm::to_integer(Args.getLastArgValue(OPT_pipe), Arg)) {
460       WithColor::error() << "invalid '--pipe' argument\n" << HelpText;
461       return 1;
462     }
463     unnamed_pipe = (pipe_t)Arg;
464   }
465   if (Args.hasArg(OPT_fd)) {
466     if (!llvm::to_integer(Args.getLastArgValue(OPT_fd), connection_fd)) {
467       WithColor::error() << "invalid '--fd' argument\n" << HelpText;
468       return 1;
469     }
470   }
471 
472   if (!LLDBServerUtilities::SetupLogging(
473           log_file, log_channels,
474           LLDB_LOG_OPTION_PREPEND_TIMESTAMP |
475               LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION))
476     return -1;
477 
478   std::vector<llvm::StringRef> Inputs;
479   for (opt::Arg *Arg : Args.filtered(OPT_INPUT))
480     Inputs.push_back(Arg->getValue());
481   if (opt::Arg *Arg = Args.getLastArg(OPT_REM)) {
482     for (const char *Val : Arg->getValues())
483       Inputs.push_back(Val);
484   }
485   if (Inputs.empty() && connection_fd == -1) {
486     WithColor::error() << "no connection arguments\n" << HelpText;
487     return 1;
488   }
489 
490   NativeProcessFactory factory;
491   GDBRemoteCommunicationServerLLGS gdb_server(mainloop, factory);
492 
493   llvm::StringRef host_and_port;
494   if (!Inputs.empty()) {
495     host_and_port = Inputs.front();
496     Inputs.erase(Inputs.begin());
497   }
498 
499   // Any arguments left over are for the program that we need to launch. If
500   // there
501   // are no arguments, then the GDB server will start up and wait for an 'A'
502   // packet
503   // to launch a program, or a vAttach packet to attach to an existing process,
504   // unless
505   // explicitly asked to attach with the --attach={pid|program_name} form.
506   if (!attach_target.empty())
507     handle_attach(gdb_server, attach_target);
508   else if (!Inputs.empty())
509     handle_launch(gdb_server, Inputs);
510 
511   // Print version info.
512   printf("%s-%s\n", LLGS_PROGRAM_NAME, LLGS_VERSION_STR);
513 
514   ConnectToRemote(mainloop, gdb_server, reverse_connect, host_and_port,
515                   progname, subcommand, named_pipe_path.c_str(),
516                   unnamed_pipe, connection_fd);
517 
518   if (!gdb_server.IsConnected()) {
519     fprintf(stderr, "no connection information provided, unable to run\n");
520     return 1;
521   }
522 
523   Status ret = mainloop.Run();
524   if (ret.Fail()) {
525     fprintf(stderr, "lldb-server terminating due to error: %s\n",
526             ret.AsCString());
527     return 1;
528   }
529   fprintf(stderr, "lldb-server exiting...\n");
530 
531   return 0;
532 }
533