GDB für Fortgeschrittene

Letzte Änderung: 2010-10-11

Inhalt

1   GDB Kommandos aus Datei lesen

Falls es eine Datei .gdbinit gibt, wird diese beim Starten von GDB ausgeführt. Die Datei kann entweder im aktuellen Verzeichnis oder im Home-Verzeichnis des Anwenders liegen. Wenn man diese Datei ignorieren will, dann muss man gdb mit der Option --nx starten. Wenn man gezielt eine bestimmte Datei mit eigenem Namen beim Start von GDB ausführen will, muss man GDB so starten:

gdb -x meine-gdb-kommandos.txt

Praktisch finde ich die GDB Einstellung set history .... Damit kann man die aktuelle Sitzung mitprotokollieren. Mit (gdb) help set history bekommt man mehr dazu heraus. Gibt man im einfachsten Fall nur gdb history save an, so wird die Datei .gdb_history angelegt. Sie enthält alle Kommandos, die man während der Debug-Sitzung eingegeben hat.

2   Eigene Funktionen definieren

Man kann in einer GDB Kommandodatei auch eigenen Funktionen definieren. Ein paar Beispiele sieht man in gdbinit.txt.

3   Memory Layout beim Start (Bartlett, Kap. 9)

Irgend ein simples hello.c schreiben, z.B.

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

int main(int argc, char **argv)
{
    printf("Hello World");
    return 0;
}

Dann das Programm übersetzen:

gcc -g -o hello hello.c

Danach mit gdb untersuchen:

gdb hello
(gdb) br _start
(gdb) run param1 param2

# das ist der Wert von esp
(gdb) p/x $esp
$1 = 0xbfb151d0

# esp zeigt auf die Anzahl der Parameter
(gdb) x/1xw $esp
0xbf92e7d0:     0x00000003

# auf esp+4 liegt ein Zeiger auf den Programmnamen
(gdb) x/1xw $esp+4
0xbf92e7d4:     0xbf93080b
(gdb) x/s 0xbf93080b
0xbf93080b:      "/home/hhoegl/hello"

# auf esp+8 liegt ein Zeiger auf das Arg 1
(gdb) x/1xw $esp+8
0xbf92e7d8:     0xbf93081e
(gdb) x/s 0xbf93081e
0xbf93081e:      "param1"

# auf esp+12 liegt ein Zeiger auf das Arg 2
...

# auf esp+16 ist 0
...

# auf esp+20 beginnt das Environment
 "MANPATH=/home/hhoegl/local/man/:/home/hhoegl/local/share/man/:/usr/share/man"
# Das Environment endet mit einer Null.

# Statt der umstaendlichen "zweistufigen" Umsetzung mit "x/1xw" und
# "x/s" kann man auch Dereferenzierungen wie in C verwenden:
(gdb) x/s *(char**)($esp+20)
# Lies:
# char* = ist ein Zeiger auf ein oder mehrere Zeichen
# char** = ist ein Zeiger der wiederum auf einen Zeiger auf Zeichen zeigt
# *(char**) = der Zeiger auf Zeiger ist einmal dereferenziert worden,
#     d.h. man moechte den Zeiger auf die Zeichen haben