有没有办法找出被某些信号中断的机器指令的地址?假设我们在由
就我所看,手册上没有提到这一点。
sigaction()
建立的处理程序中,并且可以访问传递的siginfo_t
和ucontext_t
。就我所看,手册上没有提到这一点。
#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;
}
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 fault信号中调用了一个处理程序,在其中获取了最后一个执行的机器周期的地址并打印该地址。为了验证该地址,我还展示了该代码的对象转储,并且分段故障行的机器指令匹配。
我认为这就是你想要的。
不具备可移植性。但这是针对x86_64的:
ucontext_t
结构包含寄存器REG_RIP
的值,该寄存器应该保存您要查找的值。这是从信号处理程序返回后将执行的第一条指令。
其他架构应该有类似的寄存器(在x86_32上为EIP等)。
uc_link
列表以查看其他上下文。但我们没有迹象知道何时停止。 - Sergio
void*
转换为任何其他数据指针。 - Maxim Egorushkin