Linux信号处理。 如何得到中断指令的地址?

有什么方法可以找出机器指令的地址,这是由一些信号中断? 假设我们处于由sigaction()build立的处理程序,并且具有对传递的siginfo_tucontext_t所有访问权限。 据我看到,手册没有提到这一点。

不便携式。 但是这是为x86_64:

结构体ucontext_t包含寄存器REG_RIP的值,它应该包含你所寻找的值。 这是第一条指令,从sighandler返回后将被执行。

其他体系结构应该具有类似的寄存器(x86_32上的EIP等)。

让我们看看下面的例子为Linux和x86 architure

 #include<stdio.h> #define __USE_GNU #include<signal.h> #include<ucontext.h> void myhandle(int mysignal, siginfo_t *si, void* arg) { ucontext_t *context = (ucontext_t *)arg; printf("Address from where crash happen is %x \n",context->uc_mcontext.gregs[REG_RIP]); context->uc_mcontext.gregs[REG_RIP] = context->uc_mcontext.gregs[REG_RIP] + 0x04 ; } int main(int argc, char *argv[]) { struct sigaction action; action.sa_sigaction = &myhandle; action.sa_flags = SA_SIGINFO; sigaction(11,&action,NULL); printf("Before segfault\n"); int *a=NULL; int b; b =*a; // Here crash will hapen printf("I am still alive\n"); return 0; } 

现在编译并运行,看看discompiled instrustion集。

 jeegar@jeegar:~/stackoverflow$ gcc -g test1.c -o test1.o jeegar@jeegar:~/stackoverflow$ ./test1.o Before segfault Signal is 11 Address from where crash happen is 40065b I am still alive jeegar@jeegar:~/stackoverflow$ objdump -S test1.o 

这里在对象转储

  printf("Before segfault\n"); 400645: bf a8 07 40 00 mov $0x4007a8,%edi 40064a: e8 21 fe ff ff callq 400470 <puts@plt> int *a=NULL; 40064f: 48 c7 45 f0 00 00 00 movq $0x0,-0x10(%rbp) 400656: 00 int b; b =*a; // Here crash will hapen 400657: 48 8b 45 f0 mov -0x10(%rbp),%rax 40065b: 8b 00 mov (%rax),%eax 40065d: 89 45 fc mov %eax,-0x4(%rbp) printf("I am still alive\n"); 400660: bf b8 07 40 00 mov $0x4007b8,%edi 400665: e8 06 fe ff ff callq 400470 <puts@plt> 

在40065b地址哪台机器代码在那里,你的代码的哪一行已经完成了。


在这里,我已经给你和示例代码,在发生分割和系统的Seg故障信号一个处理程序将被调用,在那里我已经取得了最后一个执行机器周期的地址,并打印该地址。 为了使地址变化,我还显示了该代码的对象转储和分割线条的机器指令匹配。

我想这是你想要的。