Uživatelské nástroje

Nástroje pro tento web


gdb

Toto je starší verze dokumentu!


GDB

Výpis paměti

  • seznam dostupných proměnných na daném break pointu, lze zjistit pomoci info locals
  • vypsat hodnotu proměnné/struktury lze pomocí print nebo zkráceně p
  • výpis bloku paměti se dělá pomocí x
x/nfu addr
x addr
x 
  • přičemž:
    • n - počet prvků k vypsání (normálně číslo)
    • f - formát zobrazení (x - hexa, s - string, i - instrukce)
    • u - velikost (b bajt, h 2B, w 4B, g 8B)
    • addr - adresa v paměti (buď přímo nebo přes název proměnné. Lze použít i operátory */&)

Příklady

Kdo zapísuje do proměné?

  • cílem bylo zjistit, kdo mi přepisuje globální proměnou LogFacility, čimž program začal logovat do jiného souboru než jsem původně zamýšlel
  • binárka by měla být zkompilovaná s debug symoboly
  • spustění gdb a navěšení na běžící proces (s PID 2453)
# gdb
(gdb) attach 2453
  • po attach je program zastaven, je možné vypsat informace o současném stavu.
  • Pozor! Program se po attach zastaví a čeká.
  • backtrace - informace o volání a obsah zásobníku (zobrazený výpis je bohužel zrovna bez debug symbolů)
(gdb) bt
#0  0x00002b3f9dd525a5 in gcheckglo4k () from /usr/cachesys/bin/libcachet.so
#1  0x00002b3f9dd4f6ad in getloc () from /usr/cachesys/bin/libcachet.so
#2  0x00002b3f9dd90350 in gsetjrn () from /usr/cachesys/bin/libcachet.so
#3  0x00002b3f9dd8f7ce in gset () from /usr/cachesys/bin/libcachet.so
#4  0x00002b3f9e0f3af2 in Cgset () from /usr/cachesys/bin/libcachet.so
#5  0x00002b3f9da192ff in ZCdisp () from /usr/cachesys/bin/libcachet.so
#6  0x00002b3f9e961668 in ?? ()
#7  0x000000000afd5738 in ?? ()
#8  0x00007fff00000000 in ?? ()
#9  0x00002b3f9e142e77 in ?? () from /usr/cachesys/bin/libcachet.so
#10 0x0000000000000000 in ?? ()
  • vypsání lokálních proměných
(gdb) info locals
  • vypsání globálních/statických proměných začínajících na LogF
(gdb) info variables LogF
All variables matching regular expression "LogF":

Non-debugging symbols:
0x000000376a951120  LogFile
0x000000376a951124  LogFacility
  • vypsání hodnoty proměné
(gdb) print LogFacility
$1 = 8
  • obsah proměné je možné přepsat (ale to teď není potřeba)
(gdb) set variable LogFacility = 24
(gdb) print LogFacility
$2 = 24
  • nastavíme watchpoint na proměnou LogFacility. Pokud někdo zapíše do proměné a hodnota se změní, program se zastaví.
watch LogFacility
  • do watchpoint/breakpoint lze zadat libovolné příkazy, které se mají provést. Umožňuje to vypsat nepříklad informace o stavu programu nebo i něco změnit. Do příkazů lze psát přímo C kód. V mém případě jsem pouze potřeboval zjístit, kdo do proměné zapsal a pokračovat dál.
commands
bt
print LogFacility
continue
end
  • nastavení watchpointu/breakpointu lze zkontrolovat pomocí
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       hw watchpoint  keep y                      LogFacility
        bt
        print LogFacility
        continue
  • nyní by mělo stačit program odpauzovat a počkat na výsledek. GDB ale může běh programu zastavit i z jiných důvodů, jako například při chybě, signálu, …
  • nejdříve jsem narazil na problém s vlákny. Program vytvářel několik vláken, ve kterých spouštěl pouze jednu funkci. Vlákno často skončilo dřív, než gdb stihl vyčíst informace o vlákně a zobrazoval chybu
[New Thread 0x7fe1aea75950 (LWP 26614)]
  Cannot get thread event message: debugger service failed
  • řesení bylo vypnout zobrazování informací o threads (starší verze GDB nemusí podporovat)
set print thread-events off
  • pak mi to vyskočilo po signal handleru
Program received signal SIGUSR1, User defined signal 1.
0x000000376a20fdd5 in __tls_get_addr () from /lib64/ld-linux-x86-64.so.2
  • GDB vidí signály a může zastavit při signálu, vytisknout, poslat programu nebo schovat signál před programem
  • aktuální stav signálu lze zjístit
(gdb) info signals
Signal        Stop      Print   Pass to program Description

SIGHUP        Yes       Yes     Yes             Hangup
SIGINT        Yes       Yes     No              Interrupt
SIGQUIT       Yes       Yes     Yes             Quit
SIGILL        Yes       Yes     Yes             Illegal instruction
SIGTRAP       Yes       Yes     No              Trace/breakpoint trap
...
SIGUSR1       Yes       Yes     Yes             User defined signal 1
...
  • změnit chování lze takto
(gdb) handle SIGUSR1 nostop
  • breakpoint se odstraní pomocí delete
(gdb) delete
Delete all breakpoints? (y or n) y

coredump smazané binárky

  • při upgrade balíčku (rpm/deb) s binárkou se typicky stává, že spuštěný proces zůstane běžet nad binárkou starou
  • nebo pokud se zavolá rm na binárku spuštěného procesu
  • nebo pokud chce někdo chránit spuštěný kód (vir)
  • procesu pak nelze vytvořit coredump (debugovat přes gdb)
# gcore 15659
core.YGsoec:4: Error in sourced command file:
/home/dev/bin/daemon/destinyd (deleted): No such file or directory.
gcore: failed to create core.15659

# ls -l /proc/15659/exe
lrwxrwxrwx. 1 root root 0 Mar 12 21:33 /proc/15659/exe -> /home/dev/bin/daemon/destinyd (deleted)
  • řešení
# gdb -p 15659 /proc/15659/exe
  • obraz lze vytvořit pomocí
(gdb) generate-core-file
(gdb) detach
  • v core dump je rovněž kód binárky (ale pouze ten, co byl aktivně v paměti)
  • přístup do paměti binárky, které už nejsou v aktivní paměti, končí segmentation fault

Zdroje

gdb.1448292771.txt.gz · Poslední úprava: (upraveno mimo DokuWiki)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki