2008-12-18 7 views
15

Tengo una aplicación C linux (A) que genera otro proceso (P) cuando se inicia. Cuando quiero depurar PI inicio A como de costumbre y me conecto con ddd/gdb a P.¿Cómo depurar el punto de entrada del proceso fork-exec en GDB?

Problemas aparecen cuando quiero depurar el punto de entrada (inicio de main) de P. Si sigo el enfoque habitual cuando Conecto el depurador a P ya es tarde. La solución que encontré fue insertar un sueño al principio de la parte principal de P, así que tengo tiempo para conectarme con gdb, pero esta no es una solución muy elegante.

También he intentado usar asm("int $3") pero parece que no funciona.

¿Tiene alguna idea de cómo podría resolver este problema? (preferiblemente sin alterar el código de A o P)

Respuesta

19

que puedes usar esta opción:

set follow-fork-modemode

Dónde modo es uno de parent, child o ask.

Para seguir el padre (este es el valor predeterminado) usan:

set follow-fork-mode parent 

Para acompañar al niño:

set follow-fork-mode child 

Para que el depurador puede pedir cada vez:

set follow-fork-mode ask 

Así que básicamente comenzarías conectando gdb a A, luego configura gdb para seguir al niño, y luego cuando A genera P, se conectará gdb a P y desprenderse de A.

0

Debería poder hacerlo haciendo uso de las funciones de depuración remota de gdb, específicamente gdbserver. En efecto, inicie (P) usando gdbserver. Estos enlaces tienen información más detallada:

+0

gdbserver permite la depuración remota pero no resuelve el problema en cuestión, que es más un caso de cómo GDB sigue fork/clone. –

+0

No creo que este sea un caso de depuración remota. Se trata más sobre qué proceso sigue gdb en un tenedor. –

6

Además de la Nathan Fellman's answer, catchpoints son útiles, i.g .:

catch exec 

Catchpoint funciona como un punto de interrupción. Cada vez que se detecta una llamada a exec() syscall, GDB se detiene. Esto le permite establecer cualquier punto de interrupción (por ejemplo, break main) en cualquier ejecutable recién cargado antes de continuar. Otro punto de referencia catch fork funciona de manera similar para fork() syscall detección.

Es especialmente conveniente:

  • cuando ambos padres y el niño tiene que ser seguido (set detach-on-fork off);
  • cuando el padre procesa las horquillas a menudo cargando varios archivos ejecutables.
-1

establecer un punto de interrupción en main(), también se romperá en main() del programa ejecutado.

+1

No, no lo hará :( –

0

exec parte con file + break main

El tenedor se parte se explicó en: https://stackoverflow.com/a/377295/895245

Ahora para la exec:

A.C.:

#include <unistd.h> 

int main(void) { 
    execl("./b", "./b", "ab", "cd", (char*)NULL); 
    return 1; 
} 

b.c:

#include <stdio.h> 

int main(int argc, char **argv) { 
    printf("%s\n", argv[0]); 
    printf("%s\n", argv[1]); 
} 

continuación:

gcc -g a.c -o a 
gcc -g b.c -o b 
gdb -nh -q a 

Ahora, en la sesión interactiva:

Reading symbols from a...done. 
(gdb) start 
Temporary breakpoint 1 at 0x4004ea: file a.c, line 4. 
Starting program: /home/cirsan01/test/gdb-exec/a 

Temporary breakpoint 1, main() at a.c:4 
4   execl("./b", "./b", "ab", "cd", (char*)NULL); 
(gdb) file b 
A program is being debugged already. 
Are you sure you want to change the file? (y or n) y 
Load new symbol table from "b"? (y or n) y 
Reading symbols from b...done. 
(gdb) b main 
Breakpoint 2 at 0x4004f5: file b.c, line 4. 
(gdb) n 

Breakpoint 2, main (argc=0, argv=0x7fffffffa570) at b.c:4 
4    printf("%s\n", argv[1]); 
(gdb) n 
process 4877 is executing new program: /home/cirsan01/test/gdb-exec/b 

Breakpoint 2, main (argc=3, argv=0x7fffffffa598) at b.c:4 
4    printf("%s\n", argv[1]); 
(gdb) n 
ab 
5    printf("%s\n", argv[2]); 
(gdb) n 
cd 
6  } 
(gdb) 

sólo hay que asegurarse de que se sube a la exec antes de archivo correr, posiblemente con un b execl , ya que después de eso usarás símbolos del nuevo archivo.

Probado en Ubuntu 14.04, gdb 7.7.1.

Cuestiones relacionadas