views:

212

answers:

1

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:

  1. Being able to plugin to any elf binary executable (ex. by using LD_PRELOAD)
  2. The binary may be a multithreaded executable
  3. The binary may link to a library that contain main function
  4. This should work in various cpu architecture other than x86 (MIPS, ARM, PPC at least)

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.

+2  A: 

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;
}
ephemient
Thank you for your answer, but this is not what I was expected as an answer. I think I've questioned that "if someone had integrated libsegfault.so and gdbserver". I wanted a reason why this was not done yet, or a correct (adequate) integration between libsegfault.so and gdbserver. Sorry for my question for not being detailed enough, but the requirements are: 1. Being able to plugin by LD_PRELOAD to any program2. The program may be a multithreaded program3. The program may link to a library that contain main function
holmes
This is just a proof-of-concept, to demonstrate that I do not believe there are any significant obstacles to implementing this. It should not be difficult to adapt the ideas to your specifications, and all the syscalls needed here are async-safe, so it should be okay in a multi-threaded program.
ephemient
Well, I think this is obvious.I thought there might be some other technical or political problem to put them together in glibc.
holmes