|
25 | 25 | #include <cstdio>
|
26 | 26 | #include <cstdlib>
|
27 | 27 | #include <cstring>
|
| 28 | +#include <filesystem> |
28 | 29 | #include <iomanip>
|
29 | 30 | #include <memory>
|
30 | 31 | #include <set>
|
@@ -293,15 +294,51 @@ static int GdbserverMain(int argc, char **argv) {
|
293 | 294 | opts.addPositional("[host]:port", "the [host]:port to connect to");
|
294 | 295 |
|
295 | 296 | int idx = opts.parse(argc, argv);
|
| 297 | + |
| 298 | + enum class channel_type { |
| 299 | + file_descriptor, |
| 300 | + named_pipe, |
| 301 | + network, |
| 302 | + }; |
| 303 | + channel_type connection_type = channel_type::network; |
| 304 | + int fd = -1; |
| 305 | + |
| 306 | +#if defined(OS_POSIX) |
| 307 | + if (const std::string &arg = opts.getString("fd"); !arg.empty()) { |
| 308 | + connection_type = channel_type::file_descriptor; |
| 309 | + fd = atoi(arg.c_str()); |
| 310 | + if (fd < 0) { |
| 311 | + DS2LOG(Error, "invalid file descriptor %s", arg.c_str()); |
| 312 | + connection_type = channel_type::network; |
| 313 | + } |
| 314 | + } |
| 315 | +#endif |
| 316 | + |
| 317 | + // This is used for llgs testing. We determine a port number dynamically and |
| 318 | + // write it back to the FIFO passed as argument for the test harness to use |
| 319 | + // it. |
| 320 | + const std::string &pipe = opts.getString("named-pipe"); |
| 321 | + if (!pipe.empty()) |
| 322 | + connection_type = channel_type::named_pipe; |
| 323 | + |
| 324 | + const std::string &address = opts.getPositional("[host]:port"); |
| 325 | + |
| 326 | + switch (connection_type) { |
| 327 | + case channel_type::file_descriptor: |
296 | 328 | #if defined(OS_POSIX)
|
297 |
| - int fd = |
298 |
| - opts.getString("fd").empty() ? -1 : atoi(opts.getString("fd").c_str()); |
299 |
| - if (fd >= 0) { |
300 | 329 | CloseFD(fd);
|
301 |
| - } else { |
| 330 | + break; |
| 331 | +#else |
| 332 | + (void)fd; |
| 333 | + DS2BUG("connecting with file descriptor is not supported on this platform"); |
| 334 | +#endif |
| 335 | + default: |
| 336 | +#if defined(OS_POSIX) |
302 | 337 | CloseFD();
|
303 |
| - } |
304 | 338 | #endif
|
| 339 | + break; |
| 340 | + } |
| 341 | + |
305 | 342 | HandleSharedOptions(opts);
|
306 | 343 |
|
307 | 344 | // Target debug program and arguments.
|
@@ -345,50 +382,44 @@ static int GdbserverMain(int argc, char **argv) {
|
345 | 382 | opts.usageDie("either a program or target PID is required in gdb mode");
|
346 | 383 | }
|
347 | 384 |
|
348 |
| - // This is used for llgs testing. We determine a port number dynamically and |
349 |
| - // write it back to the FIFO passed as argument for the test harness to use |
350 |
| - // it. |
351 |
| - std::string namedPipePath = opts.getString("named-pipe"); |
352 |
| - |
353 | 385 | bool reverse = opts.getBool("reverse-connect");
|
354 | 386 |
|
355 | 387 | std::unique_ptr<Socket> socket;
|
356 | 388 |
|
| 389 | + switch (connection_type) { |
| 390 | + case channel_type::named_pipe: |
357 | 391 | #if defined(OS_POSIX)
|
358 |
| - if (fd >= 0) { |
359 |
| - socket = CreateFDSocket(fd); |
360 |
| - } else { |
| 392 | + if (fd >= 0) |
| 393 | + DS2LOG(Error, "named pipe should not be used with fd option"); |
361 | 394 | #endif
|
362 |
| - if (opts.getPositional("[host]:port").empty()) { |
363 |
| - // If we have a named pipe, set the port to 0 to indicate that we should |
364 |
| - // dynamically allocate it and write it back to the FIFO. |
365 |
| - socket = CreateTCPSocket( |
366 |
| - gDefaultHost, namedPipePath.empty() ? gDefaultPort : "0", reverse); |
367 |
| - } else { |
368 |
| - socket = CreateSocket(opts.getPositional("[host]:port"), reverse); |
| 395 | + [[fallthrough]]; |
| 396 | + case channel_type::network: |
| 397 | + // If we have a named pipe, set the port to 0 to indicate that we should |
| 398 | + // dynamically allocate it and write it back to the FIFO. |
| 399 | + socket = address.empty() |
| 400 | + ? CreateTCPSocket(gDefaultHost, |
| 401 | + pipe.empty() ? gDefaultPort : "0", reverse) |
| 402 | + : CreateSocket(address, reverse); |
| 403 | + if (connection_type == channel_type::named_pipe) { |
| 404 | + std::string port = socket->port(); |
| 405 | + FILE *named_pipe = ::fopen(pipe.c_str(), "a"); |
| 406 | + if (named_pipe) { |
| 407 | + ::fwrite(port.c_str(), 1, port.length() + 1, named_pipe); |
| 408 | + ::fclose(named_pipe); |
| 409 | + } else { |
| 410 | + DS2LOG(Error, "unable to open %s: %s", pipe.c_str(), strerror(errno)); |
| 411 | + } |
369 | 412 | }
|
370 |
| -#if defined(OS_POSIX) |
371 |
| - } |
372 |
| -#endif |
| 413 | + break; |
373 | 414 |
|
374 |
| - if (!namedPipePath.empty()) { |
| 415 | + case channel_type::file_descriptor: |
375 | 416 | #if defined(OS_POSIX)
|
376 |
| - if (fd >= 0) { |
377 |
| - DS2LOG(Error, "named pipe should not be used with fd option"); |
378 |
| - } |
| 417 | + socket = CreateFDSocket(fd); |
| 418 | +#else |
| 419 | + (void)fd; |
| 420 | + DS2BUG("connecting with file descriptor is not supported on this platform"); |
379 | 421 | #endif
|
380 |
| - |
381 |
| - std::string realPort = socket->port(); |
382 |
| - FILE *namedPipe = fopen(namedPipePath.c_str(), "a"); |
383 |
| - if (namedPipe == nullptr) { |
384 |
| - DS2LOG(Error, "unable to open %s: %s", namedPipePath.c_str(), |
385 |
| - strerror(errno)); |
386 |
| - } else { |
387 |
| - // Write the null terminator to the file. This follows the llgs |
388 |
| - // behavior. |
389 |
| - fwrite(realPort.c_str(), 1, realPort.length() + 1, namedPipe); |
390 |
| - fclose(namedPipe); |
391 |
| - } |
| 422 | + break; |
392 | 423 | }
|
393 | 424 |
|
394 | 425 | if (gDaemonize) {
|
|
0 commit comments