为什么我不能拦截子进程的段错误信号?

时间:2013-04-30 04:03:41

标签: linux debugging gdb signals

我正在尝试监视子进程的段错误错误,但这不起作用。

我总是收到ABRT信号。

我看到gdb可以捕获段错误,所以我的代码出了什么问题?

        pid_t child;
        int wstatus, signum;
        struct user_regs_struct regs;

        child = fork();
        if (child == 0)
        {
                ptrace(PTRACE_TRACEME, 0, NULL, NULL);
                char buf[10];
                // make it always crash
                strcpy (buf, "aaaaaaabbbbbbbbbbbaaaaaaaaaaaaaaaa");
                printf ("Buf is %s\n", buf);

                exit(0);
        }

        while(1)
        {
                wait(&wstatus);
                if (WIFEXITED(wstatus) || WIFSIGNALED(wstatus))
                        break;

                signum = WSTOPSIG(wstatus);
                ptrace(PTRACE_GETREGS, child, NULL, &regs);

                printf ("signal: %d, eip: 0x%08lx\n", signum, regs.eip);
                ptrace(PTRACE_CONT, child, NULL, signum);
        }

1 个答案:

答案 0 :(得分:2)

  

我的代码出了什么问题

当孩子发出信号(WIFSIGNALED)时,你的代码就会突破循环。既然你期望捕捉到一个信号(最有可能是SIGSEGV),也许你不应该在孩子发出信号时突然出现这个问题?

我已经看了你的代码了。目前尚不清楚为什么你的孩子在崩溃。也许您正在使用-fstack-protector或其他类似内容构建它?

这是一个完整的可编译测试用例(你应该已经提到你的问题中),这确实崩溃了(注意:从孩子那里删除了exit):

#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>

int main()
{
    pid_t child;
    int wstatus, signum;
    struct user_regs_struct regs;

    child = fork();
    if (child == 0)
    {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        char buf[10];
        // make it always crash
        strcpy (buf, "aaaaaaabbbbbbbbbbbaaaaaaaaaaaaaaaa");

        printf ("Buf is %s\n", buf);
    }

    while(1)
    {
        wait(&wstatus);
        if (WIFEXITED(wstatus))
            break;

        signum = WSTOPSIG(wstatus);
        ptrace(PTRACE_GETREGS, child, NULL, &regs);

        printf ("signal: %d, eip: 0x%08lx\n", signum, regs.eip);
        ptrace(PTRACE_CONT, child, NULL, signum);
    }
    return wstatus;
}
  

并获得无限循环

你通常 应该获得一个无限循环:你正在恢复孩子,它重新执行当前的指令,这应该再次触发完全相同的信号。

这不是我的系统上面的程序发生的事情,但我目前无法解释我在观察的内容:

$ ./a.out
Buf is aaaaaaabbbbbbbbbbbaaaaaaaaaaaaaaaa
signal: 159, eip: 0x08049ff4
signal: 159, eip: 0x08049ff4
...
signal: 159, eip: 0x08049ff4
*** stack smashing detected ***: ./a.out terminated
signal: 11, eip: 0xf759fb19
signal: 0, eip: 0xf759fb19
signal: 0, eip: 0xf759fb19
...