linux - picard - Manejo de señal con qemu-usuario
musicbrainz picard español (2)
En mi máquina tengo un binario aarch64, que está compilado estáticamente. Lo ejecuto usando qemu-aarch64-static con la bandera -g 6566
. En otra terminal, inicio gdb-multiarch
y me conecto como target remote localhost:6566
.
Espero que el binario eleve una señal para la cual tengo un controlador definido en el binario. Establecí un punto de interrupción en el controlador desde dentro de gdb-multiarch
después de conectarme con el control remoto. Sin embargo, cuando surge la señal, el punto de corte no se golpea en gdb-multiarch. En cambio, en la terminal que ejecuta el binario, recibo un mensaje en la línea de:
[1] + 8388 suspended (signal) qemu-aarch64-static -g 6566 ./testbinary
¿Por qué pasó esto? ¿Cómo puedo establecer un punto de interrupción en el controlador y depurarlo? He intentado SIGCHLD y SIGFPE.
Esto funciona para mí con un QEMU reciente:
$ 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
y luego en otra ventana:
$ 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)
Como puede ver, gdb obtiene el control de inmediato, el proceso recibe la señal y luego otra vez cuando llegamos al punto de interrupción para la función del controlador.
Por cierto, (entero) dividir por cero no es una manera confiable de provocar una señal. Este es un comportamiento indefinido en C, y la implementación es libre de hacer lo más conveniente. En x86 esto generalmente resulta en un SIGFPE. En ARM, normalmente encontrará que el resultado es cero y la ejecución continuará sin señal. (Esta es una manifestación del comportamiento diferente de las instrucciones de hardware subyacentes para la división entre las dos arquitecturas).
estaba haciendo un poco de I + D por su respuesta y encuentro la respuesta siguiente
"Internamente, los malos accesos a la memoria provocan que la excepción Mach EXC_BAD_ACCESS se envíe al programa. Normalmente, esto se traduce a una señal SIGBUS UNIX. Sin embargo, gdb intercepta las excepciones Mach directamente antes de la traducción de la señal. La solución es darle a gdb el comando establezca dont-handle-bad-access 1 antes de ejecutar su programa. Luego se usa el mecanismo normal y se respetan los puntos de interrupción dentro de su manejador de señales ".
El enlace es gdb: establece un punto de interrupción para un manejador SIGBUS Tal vez lo ayude al considerar que qemu no cambia la funcionalidad de las operaciones básicas