Jakie są najlepsze sposoby automatyzacji sesji debugowania GDB?

Czy GDB ma wbudowany mechanizm skryptowy, czy mam zakodować skrypt expect, czy jest jeszcze lepsze rozwiązanie?

Za każdym razem będę wysyłał tę samą sekwencję poleceń i będę zapisywał wyjście każdego polecenia do pliku(najprawdopodobniej używając wbudowanego mechanizmu logowania GDB, chyba że ktoś ma lepszy pomysł).

3 answers

gdb wykonuje plik .gdbinit Po uruchomieniu. Możesz więc dodać swoje polecenia do tego pliku i sprawdzić, czy jest to dla Ciebie OK. Jest to przykład .gdbinit w celu wydrukowania backtrace dla wszystkich wywołań f():

set pagination off
set logging file gdb.txt
set logging on
file a.out
b f
commands
bt
continue
end
info breakpoints
r
set logging off
quit
 49
Author: Sergei Kurenkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 05:13:45

Właśnie przechodziłam przez coś podobnego i wymyśliłam podstawowy przykład - i wiedząc, że wkrótce o tym zapomnę, pomyślałam, że lepiej to wrzucę :) więc wrzucę to tutaj, ponieważ wygląda na związane z pytaniem.

Zasadniczo, w tym przykładzie chciałem uzyskać pewne wartości zmiennych w poszczególnych miejscach kodu; i mieć je wyjściowe, dopóki program się nie zawiesi. Więc tutaj jest najpierw mały program, który jest gwarantowane awarii w kilku krokach, test.c:

#include <stdio.h>
#include <stdlib.h>

int icount = 1; // default value

main(int argc, char *argv[])
{
  int i;

  if (argc == 2) {
    icount = atoi(argv[1]);
  }

  i = icount;
  while (i > -1) {
    int b = 5 / i;
    printf(" 5 / %d = %d \n", i, b );
    i = i - 1;
  }

  printf("Finished\n");
  return 0;
}

Jedynym powodem, dla którego program akceptuje argumenty linii poleceń, jest możliwość wyboru liczby kroków przed awarią-i pokazania, że gdb ignoruje --args w trybie wsadowym. To kompiluję z:

gcc -g test.c -o test.exe

Następnie przygotowuję następujący skrypt - główną sztuczką jest przypisanie command do każdego breakpoint, co ostatecznie continue (patrz również Automatyzacja gdb: show backtrace przy każdym wywołaniu funkcji puts ). Ten skrypt nazywam test.gdb:

# http://sourceware.org/gdb/wiki/FAQ: to disable the
# "---Type <return> to continue, or q <return> to quit---"
# in batch mode:
set width 0
set height 0
set verbose off

# at entry point - cmd1
b main
commands 1
  print argc
  continue
end

# printf line - cmd2
b test.c:17
commands 2
  p i
  p b
  continue
end

# int b = line - cmd3
b test.c:16
commands 3
  p i
  p b
  continue
end

# show arguments for program
show args
printf "Note, however: in batch mode, arguments will be ignored!\n"

# note: even if arguments are shown;
# must specify cmdline arg for "run"
# when running in batch mode! (then they are ignored)
# below, we specify command line argument "2":
run 2     # run

#start # alternative to run: runs to main, and stops
#continue

Zauważ, że jeśli zamierzasz używać go w trybie wsadowym, musisz "uruchomić" skrypt na końcu, za pomocą run lub start lub czegoś podobnego.

Z tym skryptem w miejscu, mogę wywołać gdb w trybie wsadowym-który wygeneruje następujące wyjście w terminalu:

$ gdb --batch --command=test.gdb --args ./test.exe 5
Breakpoint 1 at 0x804844d: file test.c, line 10.
Breakpoint 2 at 0x8048485: file test.c, line 17.
Breakpoint 3 at 0x8048473: file test.c, line 16.
Argument list to give program being debugged when it is started is "5".
Note, however: in batch mode, arguments will be ignored!

Breakpoint 1, main (argc=2, argv=0xbffff424) at test.c:10
10    if (argc == 2) {
$1 = 2

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$2 = 2
$3 = 134513899

Breakpoint 2, main (argc=2, argv=0xbffff424) at test.c:17
17      printf(" 5 / %d = %d \n", i, b );
$4 = 2
$5 = 2
 5 / 2 = 2 

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$6 = 1
$7 = 2

Breakpoint 2, main (argc=2, argv=0xbffff424) at test.c:17
17      printf(" 5 / %d = %d \n", i, b );
$8 = 1
$9 = 5
 5 / 1 = 5 

Breakpoint 3, main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;
$10 = 0
$11 = 5

Program received signal SIGFPE, Arithmetic exception.
0x0804847d in main (argc=2, argv=0xbffff424) at test.c:16
16      int b = 5 / i;

Zauważ, że podczas gdy podajemy argument linii poleceń 5, pętla nadal obraca się tylko dwa razy( tak jak jest specyfikacja run w skrypcie gdb); jeśli run nie miał żadnych argumenty, obraca się tylko raz (domyślna wartość programu) potwierdzając, że --args ./test.exe 5 jest ignorowany.

Jednak, ponieważ teraz jest to wyjście w jednym wywołaniu i bez żadnej interakcji użytkownika, wyjście wiersza poleceń może być łatwo przechwycone w pliku tekstowym za pomocą przekierowania

]}
gdb --batch --command=test.gdb --args ./test.exe 5 > out.txt

Jest też przykład użycia Pythona do automatyzacji gdb w c-GDB auto stepping - automatyczny Wydruk linii, podczas wolnego biegu?

Hope this pomaga,
Zdrowie!

 69
Author: sdaau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:46

Jeśli a-x z plikiem jest dla Ciebie za dużo, po prostu użyj opcji multiple-ex. jest to przykład do śledzenia uruchomionego programu pokazującego (i zapisującego) backtrace w przypadku awarii

sudo gdb -p $(pidof my-app) -batch \
  -ex "set logging on" \
  -ex continue \
  -ex "bt full" \
  -ex quit
 3
Author: Treviño,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-21 20:38:40