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