393 {
394
395 pid_t attach_pid = 0;
396 std::string attach_name;
397 bool wait_for = false;
399
400 for (int i = 1; i < argc; i++) {
401 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
402 printUsage(argv[0]);
403 return 0;
404 } else if (strcmp(argv[i], "--attach") == 0 && i + 1 < argc) {
405
406 unsigned long pid_val = 0;
408 fprintf(stderr, "Error: Invalid PID value\n");
409 return 1;
410 }
411 attach_pid = static_cast<pid_t>(pid_val);
412 } else if (strcmp(argv[i], "--attach-name") == 0 && i + 1 < argc) {
413 attach_name = argv[++i];
414 } else if (strcmp(argv[i], "--wait") == 0) {
415 wait_for = true;
416 } else if (strcmp(argv[i], "--port") == 0 && i + 1 < argc) {
417
419 fprintf(stderr, "Error: Invalid port number (must be 1-65535)\n");
420 return 1;
421 }
422 } else {
423 fprintf(stderr, "Unknown option: %s\n", argv[i]);
424 printUsage(argv[0]);
425 return 1;
426 }
427 }
428
429
430 if (attach_pid == 0 && attach_name.empty()) {
431 fprintf(stderr, "Error: Must specify --attach <pid> or --attach-name <name>\n\n");
432 printUsage(argv[0]);
433 return 1;
434 }
435
436
437 signal(SIGINT, signalHandler);
438 signal(SIGTERM, signalHandler);
439#ifndef _WIN32
440 signal(SIGPIPE, SIG_IGN);
441#endif
442
443
445 g_controller = &controller;
446
448 fprintf(stderr,
"Error: Failed to initialize LLDB: %s\n", controller.
lastError().c_str());
449 return 1;
450 }
451
452
453 fprintf(stderr, "[ascii-query-server] Attaching to ");
454 if (attach_pid > 0) {
455 fprintf(stderr, "PID %llu...\n", static_cast<unsigned long long>(attach_pid));
456 if (!controller.
attach(attach_pid)) {
457 fprintf(stderr,
"Error: Failed to attach: %s\n", controller.
lastError().c_str());
458 return 1;
459 }
460 } else {
461 fprintf(stderr, "process '%s'%s...\n", attach_name.c_str(), wait_for ? " (waiting)" : "");
463 fprintf(stderr,
"Error: Failed to attach: %s\n", controller.
lastError().c_str());
464 return 1;
465 }
466 }
467
468 fprintf(stderr,
"[ascii-query-server] Attached to %s (PID %llu)\n", controller.
targetName().c_str(),
469 static_cast<unsigned long long>(controller.
targetPid()));
470
471
473 fprintf(stderr, "[ascii-query-server] Resuming target...\n");
475 }
476
477
479 g_server = &server;
480
481 setupRoutes(server, controller);
482
483
484 if (!server.
start(port)) {
485 fprintf(stderr,
"Error: Failed to start HTTP server: %s\n", server.
lastError().c_str());
487 return 1;
488 }
489
490 fprintf(stderr, "[ascii-query-server] HTTP server listening on http://localhost:%d\n", port);
491 fprintf(stderr, "[ascii-query-server] Press Ctrl+C to stop\n");
492
493
494 while (!g_shutdown_requested && controller.
isAttached()) {
495#ifdef _WIN32
496 Sleep(100);
497#else
498 usleep(100000);
499#endif
502 fprintf(stderr, "[ascii-query-server] Target %s, shutting down\n",
504 break;
505 }
506 }
507
508
509 fprintf(stderr, "[ascii-query-server] Shutting down...\n");
513
514 fprintf(stderr, "[ascii-query-server] Done\n");
515 return 0;
516}
Simple single-threaded HTTP server.
bool start(uint16_t port)
Start the server.
const std::string & lastError() const
Get the last error message.
void stop()
Stop the server.
bool attachByName(const std::string &process_name, bool wait_for=false)
Attach to a process by name.
pid_t targetPid() const
Get the PID of the attached process.
std::string targetName() const
Get the name of the attached process.
const std::string & lastError() const
Get the last error message.
bool initialize()
Initialize LLDB. Must be called before any other methods.
void shutdown()
Shutdown LLDB and release resources.
bool isAttached() const
Check if attached to a process.
bool resume()
Resume the target process.
void detach()
Detach from the current process.
bool attach(pid_t pid)
Attach to a process by PID.
ProcessState state() const
Get the current process state.
ProcessState
Process state enumeration.
@ Exited
Process has exited.
@ Crashed
Process crashed.
@ Stopped
Process is stopped (breakpoint, signal, etc.)
asciichat_error_t parse_ulong(const char *str, unsigned long *out_value, unsigned long min_value, unsigned long max_value)
Parse unsigned long integer with range validation.
asciichat_error_t parse_port(const char *str, uint16_t *out_port)
Parse port number (1-65535) from string.