Debuggolás: gdb¶
Fordítás¶
Fordítsuk a terminálból a debuggolandó kódot a gcc pelda.c -o pelda -Wall -m32 -g utasítással.
A -g a debug ("hibakövetési") kapcsoló. Debug információk kerülnek a lefordított binárisba, így könnyebb lesz a debuggolás. A példák kedvéért a -m32 kapcsolóval fordítsunk 32 bites kódot.
Elindítás¶
GDB elindítása és a cél program betöltése¶
gdb ./pelda
Ha nem -g kapcsolóval volt a program fordítva, akkor a betöltéskor kiírt logok között azt látjuk, hogy no debugging symbols found (amitől a debuggolás még elindítható, csak kevésbé lesz informatív)
Elindítás Text User Interface-el együtt (TUI)¶
gdb ./pelda -tui
Kettéosztott terminál ablak segítségével a forráskódot is látni fogjuk futás közben! Használata néha bug-os lehet.

A program gépi kódjának megnézése¶
disassemble: az aktuális függvény gépi kódja. Kis nyíl jelöli éppen melyik utasításnál lévő breakpointban vagyunk.disassemble function: A kért függvény gépi kódjának megnézésedisas: rövidített írásmóddisas /m funcname: a C utasítások és a hozzájuk tartozó gépi utasítások együtt nézhetőek
Program összes függvényének listázása¶
info functions [regexp]
Opcionálisan megadható egy reguláris kifejezés a találatok szűrésére
Breakpoint elhelyezése¶
-
break function: breakpoint elhelyezése függvénynél -
b function: rövidített írásmód -
b linenum: adott sorhoz (b filename:linenumtöbb fájl esetén) -
Adott sor-pozícióhoz képesti eltolással:
b +/-OFFSET -
b *addr: ahol addr az utasításnak pl. a disassemble segítségével megtudott címe.Pl.
break *0x0000000000400722
Breakpointok listázása¶
info breakpoints
Breakpoint ki/be kapcsolása illetve törlése¶
disable N: adott sorszámú breakpoint kikapcsolása (dis N)enable N: adott sorszámú breakpoint visszakapcsolása (en N)clear function, clear linenum, clear filename:linenumbreakpoint törléshezdelete: az összes breakpoint letörlése
A betöltött célprogram elindítása¶
run (r)
Használható arra is, hogy az aktuális debug sessiont újraindítsuk.
Következő sor végrehajtása¶
step (s)next (n): a különbség, hogy nem lép bele függvényhívásokbas Nvagyn N: egyszerre N darab sort lépünkfinish: az aktuális függvényből való visszatérés helyére ugrik. Ha volt visszatérési érték, akkor kiírja.
Következő gépi utasítás végrehajtása¶
Ezekkel a parancsokkal assembly utasítás szintén tudunk lépdelni a kódban.
stepi (si)nexti (ni): a különbség, hogy nem lép bele függvényhívásokba
Breakpoint utáni újraindítás¶
continue (c)c N: ahol N megadja, hányszor ne álljon meg a gdb az aktuális breakpointnál
Backtrace¶
Breakpointnál vagy hiba (pl segmentation fault) esetén megnézhetjük hogyan jutott el a program az adott (hibás) sor lefutásához.
backtrace (bt): az aktuális stack frame-től kezdve visszafelé haladva kiírja az összes frame-et, ami a stack-en van. Ha túl sokáig tart CTRL+C-vel le lehet állítani a kiíratást.bt n: csak az utolsó n darab frame-t írja kibt -n: csak az első n darab frame-t írja kibt full: a frame-k lokális változóit is kiíratja. Kombinálható az előző két utasítással.
Információk kiíratása¶
-
info registers
Első oszlop: a regiszter neve, második oszlop: tartalom hexadecimális formában, harmadik oszlop: tartalom olvasható formában. Nézzük meg az EIP regiszter tartalmát.
-
layout regs info variables: globális és statikus változók értékeiinfo locals: lokális változók értékeiprint symbol: adott szimbólum értéke- röviden:
p symbol p valtozonevp fuggveny::valtozonevp $eax
- röviden:
info address symbol: adott szimbólum memóriacímeinfo frame: az aktuális frame adatai (argumentumok, lokális változók, ebp, eip értékei)x 0x080485e9: az x utasítással egy konkrét memóriacím tartalmát nézhetjük megx/16 address: 16 érték legyen megjelenítve az adresstől kezdve (növekvő memóriacímek irányába)x/-16 address: ugyanez, csak a 16 érték csökkenő memóriacímek irányába megy (gdb 8-tól működik)- Kiíratási módosítók megadása is lehetséges:
x/16x address: 16 hexadecimális érték kiíratásax/16xg address: 16 db 64 bites hexadecimális érték kiíratásax/16c address: 16 karakter kiíratásax/s address: C sztringként értelmezi az adott memóriaterületetx/d address: előjeles, decimális értékként való megjelenítésx/i address: utasításként próbálja értelmezni a memóriaterületet
- Verem tetjének megtekintése:
x/20x $esp
Változáskövetés¶
watch symbol: változó, regiszter, memóriacím (vagy komplexebb kifejezés) értékének a váltazása esetén álljon meg a program futása (mint egy breakpoint érték változása alapján). Többszálú program esetén minden szálon van változásfigyelés.info watchpoints: listázásukrwatch symbol: megállítja a program futását, ha a szimbólumot olvastákawatch symbol: megállítja a program futását, ha a szimbólumot írták vagy olvasták
Feltételes breakpointok elhelyezése¶
Használhatjuk a célnyelv utasításait, szimbólumait, hogy a breakpointokat feltételekhez kössük! Meglévő breakpointhoz is tudunk az azonosító száma alapján utólag feltételt rakni (pl. info breakpoints-al kideríthető)
break file.c:20 if i == 112: breakpoint a 20-as soron, ha az i 112break file.c:17 if strcmp(input, "password") == 0: breakpoint a 17-es soron, ha a string értéke passwordcond 8 *p == 78: új feltétel a 8-as breakpointhozcond 8: a 8-as breakpoint feltételének törlése
Függvényhívás¶
Lehetőségünk van kézzel meghívni a célprogram valamely függvényét (pl. ha direkt írtunk egyet debug céllal) Paramétereket is adhatunk meg neki.
call segedfgv()
.gdbinit használata¶
GDB konfigurációs fájl, mely a gdb indításakor automatikusan betöltődik. Segítségével lehet kicsit automatizálni a debuggolást. Helyei lehetnek:
- /etc/gdbinit: rendszerszintű beállítások
- ~/.gdbinit: user szintű beállítások
- ./.gdbinit: csak az adott munkakönyvtárból futó gdb-re vonatkozik. A lokális gdgbinit betöltése ki lehet kapcsolva, ekkor a megjelenő hibaüzenetek alapján lehet megoldást keresni (hozzáadni a biztonsági kivételt vagy teljesen kikapcsolni ezt az ellenőrzést)
Egy példafájl tartalma:
1 2 3 4 5 6 7 8 9 10 11 | |
Ha elkészítettük ezt a fájlt már csak el kell indítani a gdb-t (és nem is kell most neki megadni kézzel a célprogramot). A gdbinit fájlban saját segédfüggvényeket is létrehozhatunk. Például:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Ha így adjuk meg a gdbinit fájlunkat a breakpoint elérésekor automatikusan lefut majd a prnt tartalma. De kézzel is meghívhatjuk.