It's mentioned in http://sourceware.org/ml/gdb/2007-06/msg00360.html before.
But no one seemed to have actually implemented this kind of idea.
Is there any obstacles for realizing this?
My requirements are the following:
So if there's already a solution like this, I wanted a link, but if there isn't yet, I wanted to know why it's not already implemented as a wheel.
It might be just that no one didn't needed it... but I think this is quite useful to prepare as a standard.
Any technical or political issue other than just putting it together code is wanted.
gdbserver is a control program for Unix-like systems, which allows you to connect your program with a remote GDB via target remote ---but without linking in the usual debugging stub.
gdbserver runs on the target, not the host. Terminating it is target dependent. For example, if your target is UNIX-ish, you could remote login and use ps and kill from a target shell. For any type of target, rebooting should kill gdbserver .
To start gdbserver without supplying an initial command to run or process ID to attach, use the --multi command line option. Then you can connect using target extended-remote and start the program you want to debug. In multi-process mode gdbserver does not automatically exit unless you use the option --once .
Doesn't seem too hard.
$ ./a.out Caught signal at 0x400966: Segmentation fault Segmentation fault $ GDB_COMM=:1024 ./a.out Caught signal at 0x400966: Segmentation fault Attached; pid = 2369 Listening on port 1024
$ gdb ./a.out Reading symbols from /home/me/a.out...done. (gdb) target remote :1024 Remote debugging using :1024
#define _XOPEN_SOURCE 500
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
static char *gdb_comm;
static void segv_handler(int sig, siginfo_t *si, void *uc) {
pid_t child;
char msg[84], pid[20];
char *const argv[] = {"gdbserver", gdb_comm, "--attach", pid, NULL};
sprintf(msg, "Caught signal at %p", si->si_addr);
psignal(si->si_signo, msg);
if (gdb_comm && *gdb_comm) {
switch ((child = fork())) {
case 0:
sprintf(pid, "%ld", (long)getppid());
execvp(argv[0], argv);
perror("Failed to start gdbserver");
_exit(-1);
case -1:
perror("failed to fork");
default:
waitpid(child, NULL, 0);
break;
}
}
}
int main(int argc, char **argv) {
static struct sigaction segv_action = {
.sa_sigaction = segv_handler,
.sa_flags = SA_RESETHAND | SA_SIGINFO,
};
gdb_comm = getenv("GDB_COMM");
sigaction(SIGILL, &segv_action, NULL);
sigaction(SIGFPE, &segv_action, NULL);
sigaction(SIGSEGV, &segv_action, NULL);
sigaction(SIGBUS, &segv_action, NULL);
*(int *)main = 0;
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With