linux - 使用qemu-user进行信号处理

在我的机器上,我有一个AARCH64二进制文件,它是静态编译的。我使用带有-g 6566标志的qemu-aarch64-static运行它。在另一个终端中,我启动并作为gdb-multiarch连接。
我希望二进制文件发出一个信号,我在二进制文件中定义了一个处理程序。在连接到远程服务器之后,我在处理程序内部设置了一个断点。然而,当信号出现时,断点不会击中gdb多拱门。相反,在运行二进制文件的终端上,我会得到一条消息,其内容如下:

[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 %d\n", sig);
     return;
}

int main(void) {
    printf("hello world\n");
    signal(SIGUSR1, handler);
    raise(SIGUSR1);
    printf("done\n");
    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 %d\n", sig);
(gdb)

如您所见,gdb在进程收到信号后立即获得控制权,然后在我们到达处理程序函数的断点时再次获得控制权。
顺便说一下,(整数)除以零不是一个可靠的方法来触发信号。这是C中未定义的行为,实现可以自由地做最方便的事情。在x86上,这通常会导致sigfpe。在ARM上,您通常会发现结果为零,执行将在没有信号的情况下继续。(这是两种架构之间划分的底层硬件指令的不同行为的表现。)