1 //===-- lldb-platform.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 #if defined(__APPLE__) 11 #include <netinet/in.h> 12 #endif 13 #include <csignal> 14 #include <cstdint> 15 #include <cstdio> 16 #include <cstdlib> 17 #include <cstring> 18 #if !defined(_WIN32) 19 #include <sys/wait.h> 20 #endif 21 #include <fstream> 22 #include <optional> 23 24 #include "llvm/Support/FileSystem.h" 25 #include "llvm/Support/ScopedPrinter.h" 26 #include "llvm/Support/WithColor.h" 27 #include "llvm/Support/raw_ostream.h" 28 29 #include "Acceptor.h" 30 #include "LLDBServerUtilities.h" 31 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h" 32 #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" 33 #include "lldb/Host/ConnectionFileDescriptor.h" 34 #include "lldb/Host/HostGetOpt.h" 35 #include "lldb/Host/OptionParser.h" 36 #include "lldb/Host/Socket.h" 37 #include "lldb/Host/common/TCPSocket.h" 38 #include "lldb/Utility/FileSpec.h" 39 #include "lldb/Utility/LLDBLog.h" 40 #include "lldb/Utility/Status.h" 41 42 using namespace lldb; 43 using namespace lldb_private; 44 using namespace lldb_private::lldb_server; 45 using namespace lldb_private::process_gdb_remote; 46 using namespace llvm; 47 48 // option descriptors for getopt_long_only() 49 50 #ifdef _WIN32 51 typedef pipe_t shared_fd_t; 52 const shared_fd_t kInvalidSharedFD = LLDB_INVALID_PIPE; 53 #else 54 typedef NativeSocket shared_fd_t; 55 const shared_fd_t kInvalidSharedFD = Socket::kInvalidSocketValue; 56 #endif 57 58 class SharedSocket { 59 public: 60 SharedSocket(Connection *conn, Status &error) { 61 m_fd = kInvalidSharedFD; 62 63 const Socket *socket = 64 static_cast<const Socket *>(conn->GetReadObject().get()); 65 if (socket == nullptr) { 66 error = Status("invalid conn socket"); 67 return; 68 } 69 70 #ifdef _WIN32 71 m_socket = socket->GetNativeSocket(); 72 73 // Create a pipe to transfer WSAPROTOCOL_INFO to the child process. 74 error = m_socket_pipe.CreateNew(true); 75 if (error.Fail()) 76 return; 77 78 m_fd = m_socket_pipe.GetReadPipe(); 79 #else 80 m_fd = socket->GetNativeSocket(); 81 error = Status(); 82 #endif 83 } 84 85 shared_fd_t GetSendableFD() { return m_fd; } 86 87 Status CompleteSending(lldb::pid_t child_pid) { 88 #ifdef _WIN32 89 // Transfer WSAPROTOCOL_INFO to the child process. 90 m_socket_pipe.CloseReadFileDescriptor(); 91 92 WSAPROTOCOL_INFO protocol_info; 93 if (::WSADuplicateSocket(m_socket, child_pid, &protocol_info) == 94 SOCKET_ERROR) { 95 int last_error = ::WSAGetLastError(); 96 return Status("WSADuplicateSocket() failed, error: %d", last_error); 97 } 98 99 size_t num_bytes; 100 Status error = 101 m_socket_pipe.WriteWithTimeout(&protocol_info, sizeof(protocol_info), 102 std::chrono::seconds(10), num_bytes); 103 if (error.Fail()) 104 return error; 105 if (num_bytes != sizeof(protocol_info)) 106 return Status("WriteWithTimeout(WSAPROTOCOL_INFO) failed: %d bytes", 107 num_bytes); 108 #endif 109 return Status(); 110 } 111 112 static Status GetNativeSocket(shared_fd_t fd, NativeSocket &socket) { 113 #ifdef _WIN32 114 socket = Socket::kInvalidSocketValue; 115 // Read WSAPROTOCOL_INFO from the parent process and create NativeSocket. 116 WSAPROTOCOL_INFO protocol_info; 117 { 118 Pipe socket_pipe(fd, LLDB_INVALID_PIPE); 119 size_t num_bytes; 120 Status error = 121 socket_pipe.ReadWithTimeout(&protocol_info, sizeof(protocol_info), 122 std::chrono::seconds(10), num_bytes); 123 if (error.Fail()) 124 return error; 125 if (num_bytes != sizeof(protocol_info)) { 126 return Status( 127 "socket_pipe.ReadWithTimeout(WSAPROTOCOL_INFO) failed: % d bytes", 128 num_bytes); 129 } 130 } 131 socket = ::WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, 132 FROM_PROTOCOL_INFO, &protocol_info, 0, 0); 133 if (socket == INVALID_SOCKET) { 134 return Status("WSASocket(FROM_PROTOCOL_INFO) failed: error %d", 135 ::WSAGetLastError()); 136 } 137 return Status(); 138 #else 139 socket = fd; 140 return Status(); 141 #endif 142 } 143 144 private: 145 #ifdef _WIN32 146 Pipe m_socket_pipe; 147 NativeSocket m_socket; 148 #endif 149 shared_fd_t m_fd; 150 }; 151 152 static int g_debug = 0; 153 static int g_verbose = 0; 154 static int g_server = 0; 155 156 static struct option g_long_options[] = { 157 {"debug", no_argument, &g_debug, 1}, 158 {"verbose", no_argument, &g_verbose, 1}, 159 {"log-file", required_argument, nullptr, 'l'}, 160 {"log-channels", required_argument, nullptr, 'c'}, 161 {"listen", required_argument, nullptr, 'L'}, 162 {"port-offset", required_argument, nullptr, 'p'}, 163 {"gdbserver-port", required_argument, nullptr, 'P'}, 164 {"min-gdbserver-port", required_argument, nullptr, 'm'}, 165 {"max-gdbserver-port", required_argument, nullptr, 'M'}, 166 {"socket-file", required_argument, nullptr, 'f'}, 167 {"server", no_argument, &g_server, 1}, 168 {"child-platform-fd", required_argument, nullptr, 2}, 169 {nullptr, 0, nullptr, 0}}; 170 171 #if defined(__APPLE__) 172 #define LOW_PORT (IPPORT_RESERVED) 173 #define HIGH_PORT (IPPORT_HIFIRSTAUTO) 174 #else 175 #define LOW_PORT (1024u) 176 #define HIGH_PORT (49151u) 177 #endif 178 179 #if !defined(_WIN32) 180 // Watch for signals 181 static void signal_handler(int signo) { 182 switch (signo) { 183 case SIGHUP: 184 // Use SIGINT first, if that does not work, use SIGHUP as a last resort. 185 // And we should not call exit() here because it results in the global 186 // destructors to be invoked and wreaking havoc on the threads still 187 // running. 188 llvm::errs() << "SIGHUP received, exiting lldb-server...\n"; 189 abort(); 190 break; 191 } 192 } 193 #endif 194 195 static void display_usage(const char *progname, const char *subcommand) { 196 fprintf(stderr, "Usage:\n %s %s [--log-file log-file-name] [--log-channels " 197 "log-channel-list] [--port-file port-file-path] --server " 198 "--listen port\n", 199 progname, subcommand); 200 exit(0); 201 } 202 203 static Status save_socket_id_to_file(const std::string &socket_id, 204 const FileSpec &file_spec) { 205 FileSpec temp_file_spec(file_spec.GetDirectory().GetStringRef()); 206 Status error(llvm::sys::fs::create_directory(temp_file_spec.GetPath())); 207 if (error.Fail()) 208 return Status("Failed to create directory %s: %s", 209 temp_file_spec.GetPath().c_str(), error.AsCString()); 210 211 Status status; 212 if (auto Err = llvm::writeToOutput(file_spec.GetPath(), 213 [&socket_id](llvm::raw_ostream &OS) { 214 OS << socket_id; 215 return llvm::Error::success(); 216 })) 217 return Status("Failed to atomically write file %s: %s", 218 file_spec.GetPath().c_str(), 219 llvm::toString(std::move(Err)).c_str()); 220 return status; 221 } 222 223 static void client_handle(GDBRemoteCommunicationServerPlatform &platform, 224 const lldb_private::Args &args) { 225 if (!platform.IsConnected()) 226 return; 227 228 if (args.GetArgumentCount() > 0) { 229 lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 230 std::optional<uint16_t> port; 231 std::string socket_name; 232 Status error = platform.LaunchGDBServer(args, 233 "", // hostname 234 pid, port, socket_name); 235 if (error.Success()) 236 platform.SetPendingGdbServer(pid, *port, socket_name); 237 else 238 fprintf(stderr, "failed to start gdbserver: %s\n", error.AsCString()); 239 } 240 241 bool interrupt = false; 242 bool done = false; 243 Status error; 244 while (!interrupt && !done) { 245 if (platform.GetPacketAndSendResponse(std::nullopt, error, interrupt, 246 done) != 247 GDBRemoteCommunication::PacketResult::Success) 248 break; 249 } 250 251 printf("Disconnected.\n"); 252 } 253 254 static GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap; 255 static std::mutex gdbserver_portmap_mutex; 256 257 static void spawn_process_reaped(lldb::pid_t pid, int signal, int status) { 258 std::lock_guard<std::mutex> guard(gdbserver_portmap_mutex); 259 gdbserver_portmap.FreePortForProcess(pid); 260 } 261 262 static Status spawn_process(const char *progname, Connection *conn, 263 uint16_t gdb_port, uint16_t port_offset, 264 const lldb_private::Args &args, 265 const std::string &log_file, 266 const StringRef log_channels) { 267 Status error; 268 SharedSocket shared_socket(conn, error); 269 if (error.Fail()) 270 return error; 271 272 ProcessLaunchInfo launch_info; 273 274 FileSpec self_spec(progname, FileSpec::Style::native); 275 launch_info.SetExecutableFile(self_spec, true); 276 Args &self_args = launch_info.GetArguments(); 277 self_args.AppendArgument(llvm::StringRef("platform")); 278 self_args.AppendArgument(llvm::StringRef("--child-platform-fd")); 279 self_args.AppendArgument(llvm::to_string(shared_socket.GetSendableFD())); 280 if (gdb_port) { 281 self_args.AppendArgument(llvm::StringRef("--gdbserver-port")); 282 self_args.AppendArgument(llvm::to_string(gdb_port)); 283 } 284 if (port_offset > 0) { 285 self_args.AppendArgument(llvm::StringRef("--port-offset")); 286 self_args.AppendArgument(llvm::to_string(port_offset)); 287 } 288 if (!log_file.empty()) { 289 self_args.AppendArgument(llvm::StringRef("--log-file")); 290 self_args.AppendArgument(log_file); 291 } 292 if (!log_channels.empty()) { 293 self_args.AppendArgument(llvm::StringRef("--log-channels")); 294 self_args.AppendArgument(log_channels); 295 } 296 if (args.GetArgumentCount() > 0) { 297 self_args.AppendArgument("--"); 298 self_args.AppendArguments(args); 299 } 300 301 launch_info.SetLaunchInSeparateProcessGroup(false); 302 launch_info.SetMonitorProcessCallback(&spawn_process_reaped); 303 304 // Copy the current environment. 305 launch_info.GetEnvironment() = Host::GetEnvironment(); 306 307 launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO); 308 309 // Close STDIN, STDOUT and STDERR. 310 launch_info.AppendCloseFileAction(STDIN_FILENO); 311 launch_info.AppendCloseFileAction(STDOUT_FILENO); 312 launch_info.AppendCloseFileAction(STDERR_FILENO); 313 314 // Redirect STDIN, STDOUT and STDERR to "/dev/null". 315 launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false); 316 launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true); 317 launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true); 318 319 std::string cmd; 320 self_args.GetCommandString(cmd); 321 322 error = Host::LaunchProcess(launch_info); 323 if (error.Fail()) 324 return error; 325 326 lldb::pid_t child_pid = launch_info.GetProcessID(); 327 if (child_pid == LLDB_INVALID_PROCESS_ID) 328 return Status("invalid pid"); 329 330 LLDB_LOG(GetLog(LLDBLog::Platform), "lldb-platform launched '{0}', pid={1}", 331 cmd, child_pid); 332 333 { 334 std::lock_guard<std::mutex> guard(gdbserver_portmap_mutex); 335 gdbserver_portmap.AssociatePortWithProcess(gdb_port, child_pid); 336 } 337 338 error = shared_socket.CompleteSending(child_pid); 339 if (error.Fail()) { 340 Host::Kill(child_pid, SIGTERM); 341 return error; 342 } 343 344 return Status(); 345 } 346 347 // main 348 int main_platform(int argc, char *argv[]) { 349 const char *progname = argv[0]; 350 const char *subcommand = argv[1]; 351 argc--; 352 argv++; 353 #if !defined(_WIN32) 354 signal(SIGPIPE, SIG_IGN); 355 signal(SIGHUP, signal_handler); 356 #endif 357 int long_option_index = 0; 358 Status error; 359 std::string listen_host_port; 360 int ch; 361 362 std::string log_file; 363 StringRef 364 log_channels; // e.g. "lldb process threads:gdb-remote default:linux all" 365 366 shared_fd_t fd = kInvalidSharedFD; 367 368 int min_gdbserver_port = 0; 369 int max_gdbserver_port = 0; 370 uint16_t port_offset = 0; 371 372 FileSpec socket_file; 373 bool show_usage = false; 374 int option_error = 0; 375 int socket_error = -1; 376 377 std::string short_options(OptionParser::GetShortOptionString(g_long_options)); 378 379 #if __GLIBC__ 380 optind = 0; 381 #else 382 optreset = 1; 383 optind = 1; 384 #endif 385 386 while ((ch = getopt_long_only(argc, argv, short_options.c_str(), 387 g_long_options, &long_option_index)) != -1) { 388 switch (ch) { 389 case 0: // Any optional that auto set themselves will return 0 390 break; 391 392 case 'L': 393 listen_host_port.append(optarg); 394 break; 395 396 case 'l': // Set Log File 397 if (optarg && optarg[0]) 398 log_file.assign(optarg); 399 break; 400 401 case 'c': // Log Channels 402 if (optarg && optarg[0]) 403 log_channels = StringRef(optarg); 404 break; 405 406 case 'f': // Socket file 407 if (optarg && optarg[0]) 408 socket_file.SetFile(optarg, FileSpec::Style::native); 409 break; 410 411 case 'p': { 412 if (!llvm::to_integer(optarg, port_offset)) { 413 WithColor::error() << "invalid port offset string " << optarg << "\n"; 414 option_error = 4; 415 break; 416 } 417 if (port_offset < LOW_PORT || port_offset > HIGH_PORT) { 418 WithColor::error() << llvm::formatv( 419 "port offset {0} is not in the " 420 "valid user port range of {1} - {2}\n", 421 port_offset, LOW_PORT, HIGH_PORT); 422 option_error = 5; 423 } 424 } break; 425 426 case 'P': 427 case 'm': 428 case 'M': { 429 uint16_t portnum; 430 if (!llvm::to_integer(optarg, portnum)) { 431 WithColor::error() << "invalid port number string " << optarg << "\n"; 432 option_error = 2; 433 break; 434 } 435 if (portnum < LOW_PORT || portnum > HIGH_PORT) { 436 WithColor::error() << llvm::formatv( 437 "port number {0} is not in the " 438 "valid user port range of {1} - {2}\n", 439 portnum, LOW_PORT, HIGH_PORT); 440 option_error = 1; 441 break; 442 } 443 if (ch == 'P') 444 gdbserver_portmap.AllowPort(portnum); 445 else if (ch == 'm') 446 min_gdbserver_port = portnum; 447 else 448 max_gdbserver_port = portnum; 449 } break; 450 451 case 2: { 452 uint64_t _fd; 453 if (!llvm::to_integer(optarg, _fd)) { 454 WithColor::error() << "invalid fd " << optarg << "\n"; 455 option_error = 6; 456 } else 457 fd = (shared_fd_t)_fd; 458 } break; 459 460 case 'h': /* fall-through is intentional */ 461 case '?': 462 show_usage = true; 463 break; 464 } 465 } 466 467 if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0)) 468 return -1; 469 470 // Make a port map for a port range that was specified. 471 if (min_gdbserver_port && min_gdbserver_port < max_gdbserver_port) { 472 gdbserver_portmap = GDBRemoteCommunicationServerPlatform::PortMap( 473 min_gdbserver_port, max_gdbserver_port); 474 } else if (min_gdbserver_port || max_gdbserver_port) { 475 WithColor::error() << llvm::formatv( 476 "--min-gdbserver-port ({0}) is not lower than " 477 "--max-gdbserver-port ({1})\n", 478 min_gdbserver_port, max_gdbserver_port); 479 option_error = 3; 480 } 481 482 // Print usage and exit if no listening port is specified. 483 if (listen_host_port.empty() && fd == kInvalidSharedFD) 484 show_usage = true; 485 486 if (show_usage || option_error) { 487 display_usage(progname, subcommand); 488 exit(option_error); 489 } 490 491 // Skip any options we consumed with getopt_long_only. 492 argc -= optind; 493 argv += optind; 494 lldb_private::Args inferior_arguments; 495 inferior_arguments.SetArguments(argc, const_cast<const char **>(argv)); 496 497 if (fd != kInvalidSharedFD) { 498 // Child process will handle the connection and exit. 499 Log *log = GetLog(LLDBLog::Platform); 500 if (!listen_host_port.empty()) { 501 LLDB_LOGF(log, "lldb-platform child: " 502 "ambiguous parameters --listen and --child-platform-fd"); 503 return socket_error; 504 } 505 506 NativeSocket socket; 507 error = SharedSocket::GetNativeSocket(fd, socket); 508 if (error.Fail()) { 509 LLDB_LOGF(log, "lldb-platform child: %s", error.AsCString()); 510 return socket_error; 511 } 512 513 Connection *conn = 514 new ConnectionFileDescriptor(new TCPSocket(socket, true, false)); 515 GDBRemoteCommunicationServerPlatform platform(Socket::ProtocolTcp, "tcp"); 516 if (port_offset > 0) 517 platform.SetPortOffset(port_offset); 518 platform.SetPortMap(std::move(gdbserver_portmap)); 519 platform.SetConnection(std::unique_ptr<Connection>(conn)); 520 client_handle(platform, inferior_arguments); 521 return 0; 522 } 523 524 const bool children_inherit_listen_socket = false; 525 // the test suite makes many connections in parallel, let's not miss any. 526 // The highest this should get reasonably is a function of the number 527 // of target CPUs. For now, let's just use 100. 528 const int backlog = 100; 529 530 std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create( 531 listen_host_port, children_inherit_listen_socket, error)); 532 if (error.Fail()) { 533 fprintf(stderr, "failed to create acceptor: %s", error.AsCString()); 534 exit(socket_error); 535 } 536 537 error = acceptor_up->Listen(backlog); 538 if (error.Fail()) { 539 printf("failed to listen: %s\n", error.AsCString()); 540 exit(socket_error); 541 } 542 if (socket_file) { 543 error = 544 save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file); 545 if (error.Fail()) { 546 fprintf(stderr, "failed to write socket id to %s: %s\n", 547 socket_file.GetPath().c_str(), error.AsCString()); 548 return 1; 549 } 550 } 551 552 GDBRemoteCommunicationServerPlatform platform( 553 acceptor_up->GetSocketProtocol(), acceptor_up->GetSocketScheme()); 554 if (port_offset > 0) 555 platform.SetPortOffset(port_offset); 556 557 do { 558 const bool children_inherit_accept_socket = true; 559 Connection *conn = nullptr; 560 error = acceptor_up->Accept(children_inherit_accept_socket, conn); 561 if (error.Fail()) { 562 WithColor::error() << error.AsCString() << '\n'; 563 exit(socket_error); 564 } 565 printf("Connection established.\n"); 566 567 if (g_server) { 568 std::optional<uint16_t> available_port; 569 { 570 std::lock_guard<std::mutex> guard(gdbserver_portmap_mutex); 571 auto port = gdbserver_portmap.GetNextAvailablePort(); 572 if (port) 573 available_port = *port; 574 else 575 llvm::consumeError(port.takeError()); 576 } 577 if (!available_port) { 578 fprintf(stderr, 579 "no available gdbserver port for connection - dropping...\n"); 580 } else { 581 error = spawn_process(progname, conn, *available_port, port_offset, 582 inferior_arguments, log_file, log_channels); 583 if (error.Fail()) { 584 { 585 586 std::lock_guard<std::mutex> guard(gdbserver_portmap_mutex); 587 gdbserver_portmap.FreePort(*available_port); 588 } 589 LLDB_LOGF(GetLog(LLDBLog::Platform), "spawn_process failed: %s", 590 error.AsCString()); 591 WithColor::error() 592 << "spawn_process failed: " << error.AsCString() << "\n"; 593 } 594 } 595 // Parent doesn't need a connection to the lldb client 596 delete conn; 597 598 // Parent will continue to listen for new connections. 599 continue; 600 } else { 601 // If not running as a server, this process will not accept 602 // connections while a connection is active. 603 acceptor_up.reset(); 604 605 // When not running in server mode, use all available ports 606 platform.SetPortMap(std::move(gdbserver_portmap)); 607 } 608 609 platform.SetConnection(std::unique_ptr<Connection>(conn)); 610 client_handle(platform, inferior_arguments); 611 } while (g_server); 612 613 fprintf(stderr, "lldb-server exiting...\n"); 614 615 return 0; 616 } 617