有没有办法找出机器指令的地址,被某些信号打断了?假设我们在所确立的处理程序sigaction(),并拥有所有访问过siginfo_t和ucontext_t.据我所知,man page对此一无所知.
让我们看看下面的 linux 和 x86 架构示例
#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;
}
Run Code Online (Sandbox Code Playgroud)
现在编译并运行并查看反编译的信任集。
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
Run Code Online (Sandbox Code Playgroud)
在对象转储中
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>
Run Code Online (Sandbox Code Playgroud)
在 40065b 地址处有哪些机器代码以及您的哪一行代码完成了此操作。
在这里,我为您提供了示例代码,其中发生分段并且在系统的 Seg 故障信号上将调用一个处理程序,并且我已获取最后执行的机器周期的地址并打印该地址。为了改变该地址,我还显示了该代码的对象转储和分段错误行的机器指令匹配。
我想这就是你想要的。
不便携。但这是针对 x86_64 的:
该结构ucontext_t包含寄存器的值REG_RIP,它应该保存您要查找的值。这是从叹息处理程序返回后将执行的第一条指令。
其他架构应该有类似的寄存器(x86_32 上的 EIP 等)。