在我的机器上,我有一个静态编译的aarch64二进制文件。我使用带有-g 6566
标志的qemu-aarch64-static来运行它。在另一个终端上,我启动gdb-multiarch
并连接target remote localhost:6566
。
我期望二进制文件引发一个信号,我在二进制文件中定义了一个处理程序。连接到远程后,我在gdb-multiarch
内部的处理程序上设置了一个断点。然而,当信号出现时,gdb-multiarch上的断点没有被击中。相反,在运行二进制文件的终端上,我得到如下一行的消息:-
[1] + 8388 suspended (signal) qemu-aarch64-static -g 6566 ./testbinary
为什么会发生这种情况?我如何在处理程序上设置断点并调试它?我试过SIGCHLD和SIGFPE
这适用于我最近的QEMU:
$ cat sig.c
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
void handler(int sig) {
printf("In signal handler, signal %dn", sig);
return;
}
int main(void) {
printf("hello worldn");
signal(SIGUSR1, handler);
raise(SIGUSR1);
printf("donen");
return 0;
}
$ aarch64-linux-gnu-gcc -g -Wall -o sig sig.c -static
$ qemu-aarch64 -g 6566 ./sig
,然后在另一个窗口:
$ gdb-multiarch
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
[etc]
(gdb) set arch aarch64
The target architecture is assumed to be aarch64
(gdb) file /tmp/sigs/sig
Reading symbols from /tmp/sigs/sig...done.
(gdb) target remote :6566
Remote debugging using :6566
0x0000000000400c98 in _start ()
(gdb) break handler
Breakpoint 1 at 0x400e44: file sig.c, line 6.
(gdb) c
Continuing.
Program received signal SIGUSR1, User defined signal 1.
0x0000000000405c68 in raise ()
(gdb) c
Continuing.
Breakpoint 1, handler (sig=10) at sig.c:6
6 printf("In signal handler, signal %dn", sig);
(gdb)
正如您所看到的,gdb在进程接收到信号时立即获得控制,然后在我们到达处理程序函数的断点时再次获得控制。
顺便说一下,(整数)除以零并不是激发信号的可靠方法。这在C中是未定义的行为,并且实现可以自由地做最方便的事情。在x86上,这通常会导致SIGFPE。在ARM上,您通常会发现结果为零,并且在没有信号的情况下继续执行。(这是在两个体系结构之间划分的底层硬件指令的不同行为的表现)
我正在为你的答案做一些研究,并找到了以下答案
"在内部,错误的内存访问导致Mach异常EXC_BAD_ACCESS被发送给程序。通常,这被转换成SIGBUS UNIX信号。然而,gdb在信号转换之前直接拦截Mach异常。解决方案是在运行程序之前给gdb命令set don -handle-bad-access 1。然后使用正常的机制,并尊重信号处理程序中的断点。"
链接是gdb:设置SIGBUS处理程序的断点考虑到qemu不会改变基本操作