Linux qemu用户的信号处理

Linux qemu用户的信号处理,linux,gdb,signals,qemu,signal-handling,Linux,Gdb,Signals,Qemu,Signal Handling,在我的机器上,我有一个aarch64二进制文件,它是静态编译的。我使用带有-g6566标志的qemu-aarch64-static运行它。在另一个终端中,我启动gdb-multiarch,并作为目标远程本地主机:6566连接 我希望二进制文件会发出一个信号,我在二进制文件中为其定义了一个处理程序。连接到remote后,我从内部gdb multiarch在处理程序上设置了一个断点。但是,当信号出现时,断点不会在gdb multiarch上命中。相反,在运行二进制文件的终端上,我会收到一条如下消息:

在我的机器上,我有一个aarch64二进制文件,它是静态编译的。我使用带有
-g6566
标志的qemu-aarch64-static运行它。在另一个终端中,我启动
gdb-multiarch
,并作为
目标远程本地主机:6566
连接

我希望二进制文件会发出一个信号,我在二进制文件中为其定义了一个处理程序。连接到remote后,我从内部
gdb multiarch
在处理程序上设置了一个断点。但是,当信号出现时,断点不会在gdb multiarch上命中。相反,在运行二进制文件的终端上,我会收到一条如下消息:-

[1]     + 8388 suspended (signal)  qemu-aarch64-static -g 6566 ./testbinary

为什么会发生这种情况?如何在处理程序上设置断点并对其进行调试?我试过SIGCHLD和SIGFPE。

我在为你的答案做一些研发,并找到了以下答案

“在内部,坏内存访问导致Mach异常EXC_bad_ACCESS被发送到程序。通常,这会转换为SIGBUS UNIX信号。然而,gdb在信号转换之前直接拦截马赫数异常。解决方案是在运行程序之前,为gdb提供命令集dont handle bad access 1。然后使用正常的机制,信号处理程序中的断点将得到尊重。”

链接是
考虑到qemu不会改变基本操作的功能,这可能会对您有所帮助

这对我最近的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在进程接收到信号后立即获得控制权,然后在到达处理程序函数的断点时再次获得控制权


顺便说一句,(整数)除以零并不是引发信号的可靠方式。这在C中是未定义的行为,实现可以自由地做最方便的事情。在x86上,这通常会导致SIGFPE。在ARM上,您通常会发现结果为零,执行将在没有信号的情况下继续。(这是两种体系结构之间划分的底层硬件指令的不同行为的表现。)

你到底想捕获什么信号?
SIGCHLD
SIGFPE
是在非常不同的条件下产生的,我不知道你是如何尝试这两种方法的,因为它们之间没有任何关系。显示处理程序代码以及如何设置它们。我已经为单独的二进制文件尝试了这两种方法。对于SIGCHLD二进制文件来说,fork、parent对于SIGFPE,我执行一个故意除以0的除法。处理程序被添加为signal(SIGCHLD,handler)或signal(SIGFPE,handler)。
$ 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)