有没有办法找出机器指令的地址,被某些信号打断了?假设我们处于由sigaction()
建立的处理程序,并且拥有通过siginfo_t
和ucontext_t
的所有访问权限。
据我所知,手册页中没有任何内容。
答案 0 :(得分:3)
不便携。但这适用于x86_64:
结构ucontext_t
包含寄存器REG_RIP
的值,它应该包含您要查找的值。这是从sighandler返回后将执行的第一条指令。
其他架构应该有类似的寄存器(x86_32上的EIP等)。
答案 1 :(得分:2)
让我们看一下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;
}
现在编译并运行并查看已编译的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故障信号上将调用一个处理程序,并且我已经获取了上次执行的机器周期的地址并打印该地址。为了改变该地址,我还展示了该代码的对象转储和分段falt line的机器指令匹配。
我认为这就是你想要的。