代码之家  ›  专栏  ›  技术社区  ›  holmes

有人知道是否有人集成了libsegfault.so和gdbserver,以便让gdb在运行中连接到崩溃的程序?

  •  6
  • holmes  · 技术社区  · 15 年前

    上面提到了 http://sourceware.org/ml/gdb/2007-06/msg00360.html 以前。
    但似乎没有人真正实现这种想法。
    实现这一点有什么障碍吗?

    我的要求如下:

    1. 能够插入任何ELF二进制可执行文件(例如使用ld_preload)
    2. 二进制文件可以是多线程可执行文件
    3. 二进制文件可以链接到包含主函数的库
    4. 这应该适用于除x86以外的各种CPU体系结构(至少是MIPS、ARM、PPC)

    所以如果已经有了这样的解决方案,我想要一个链接,但是如果还没有,我想知道为什么它还没有实现为一个轮子。
    可能只是没人不需要它…但我认为作为一个标准,这是非常有用的。

    任何技术或政治问题,除了把代码放在一起是需要的。

    1 回复  |  直到 15 年前
        1
  •  9
  •   ephemient    15 年前

    看起来不太难。

    $ ./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;
    }