C编程手动增加信号处理程序的PC

时间:2018-01-23 15:23:34

标签: c signals

我是C编程的新手,在进行练习时仅使用标志的地址来增加分段故障信号处理程序的PC时会遇到问题。通过引用标志符号,我已经获得了代码堆栈中的标志地址,但是我怎么知道应该将它增加多少到PC存储指令指针以手动推进程序计数器的位置?

void segf_handler(int signum)
{
int address=&signum;

}
int main()
{
int n = 0;

signal(SIGSEGV, segment_fault_handler);

n = *( (int *) 0 );

printf("recover from segfault\n");

return 0;
}

谢谢!

1 个答案:

答案 0 :(得分:1)

为了能够访问已保存PC的位置,您必须使用sigaction和三参数信号处理程序:

#include <stdio.h>
#include <signal.h>
#include <ucontext.h>

void segf_handler(int sig, siginfo_t *info, void *cx_)
{
    ucontext_t *cx = cx_;

    /* Extremely OS- and architecture-specific manipulation
       of the data pointed to by `cx` goes here */
}

int *volatile cause_crash = 0;

int main(void)
{
    struct sigaction sa;
    sigfillset(&sa.sa_mask);
    sa.sa_sigaction = segf_handler;
    sa.sa_flags = SA_RESTART | SA_SIGINFO;
    if (sigaction(SIGSEGV, &sa, 0)) {
        perror("sigaction");
        return 1;
    }
    *cause_crash = 0;
    puts("recovered from segfault");
    return 0;
}

保存的PC将在cx指向的数据中某处,您可以操纵它来更改正常控制将恢复的位置。 info指向的数据还将包含尝试执行此类操作的程序的有用详细信息,例如(对于SIGSEGV)错误指令尝试访问的错误地址。

不幸的是,我无法告诉您在哪里可以找到PC,因为ucontext_t的内容并非标准化 ,并且与CPU和操作系统,你没有告诉我们任何一个。

请注意,sigaction不是任何C标准版本的一部分。除了ucontext_t的内容之外,上述代码使用的所有内容都是POSIX.1-1996的一部分,因此您可以指望它可以处理您可能正在使用的任何内容除外< / em>适用于某些嵌入式操作系统和Windows。特别是,在Windows上,你需要做一些完全不同的,我不能很好地理解这些

另请注意,如果您的导师告诉您可以使用signal和/或单参数信号处理程序访问已保存的PC,那么他们就错了,如果他们需要你做这个练习的一部分,然后这是一个不正确的要求,在这两种情况下你都可以告诉他们我这么说。