Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #93, СЕНТЯБРЬ 2006 г.

Погружение в технику и философию gdb

Крис Касперски

Хакер, номер #093, стр. 093-122-5


(gdb) display/3i $pc

1: x/3i $pc

0x200008: mov $0x2a,%bl

0x20000a: jmp 0x200040

0x20000f: add %al,(%edx)

(gdb) ni

0x0020000a in ?? ()

...

Для автоматического отображения значения регистров достаточно дать команду "display регистр", где регистр — $eax, $ebx, $ecx и т.д. Для регистра-указателя текущего положения стека существует специальное имя — $sp, которое можно использовать наравне с $esp (точно так же, как $pc <--> $eip). Автоматических отображений может быть создано сколько угодно, и любое из них всегда может быть удалено командой "undisplay n1 n2 .. nn", где nx – номер отображения, который можно узнать по команде "info display". Временно выключить отображение помогает команда "disable display n1 n2 ... nn", а "enable display" – включает обратно.

[переключение режима дизассемблирования]

По умолчанию gdb использует синтаксис AT&T, но может выводить инструкции и в формате Intel. Для этого достаточно дать команду "set disassembly-flavor intel", а чтобы вернуться назад: "set disassembly-flavor att". Для наглядности сравним с предыдущим листингом.

(gdb) set disassembly-flavor intel

(gdb) display/3i $pc

1: x/3i $pc

0x200008: mov bl,0x2a

0x20000a: jmp 0x200040

0x20000f: add BYTE PTR [edx],al

(gdb) ni

0x0020000a in ?? ()

...

[перенаправление ввода/вывода]

По умолчанию gdb связывает со стандартным вводом/выводом отлаживаемой программы текущую консоль, в результате чего сообщения программы перемешиваются с сообщениями отладчика. Чтобы навести порядок, необходимо перенаправить ввод/вывод программы на отдельную консоль, что осуществляется командой "tty консоль". Открываем новую консоль, даем *nix-команду "tty" для определения ее имени (получаем, например, "/dev/ps/6"), возвращаемся к консоли отладчика и говорим:

(gdb) tty /dev/ps/6

[вывод выражения на экран]

Для вывода выражений используется команда "print" (псевдоним "p"). Продемонстрируем некоторые ее возможности:

# gdb в качестве простейшего калькулятора

(gdb) p 2*2

$1 = 4

(gdb) p $1 + 3

$2 = 7

# вывод значения $sp

(gdb) p $sp

$3 = (void *) 0xbffffb40

# вывод ячейки, на которую указывает $sp в hex-формате

(gdb) p/x *(unsigned int*) $sp

$4 = 0x1

# вывод ячейки, на которую указывает $sp в unsigned dec-формате

(gdb) p/u *(unsigned int*) $sp

$5 = 1

# вывод содержимого ячейки в dec-формате (по умолчанию)

(gdb) p *0xbffffB3F

$6 = 256

# вывод содержимого ячейки в hex-формате

(gdb) p/x *0xbffffB3F

$7 = 0x100

Как видно, при каждом выводе значения "print" создает переменную, которую затем с успехом можно использовать в последующих выражениях. Также доступна функция "printf" со стандартным набором спецификаторов, она особенно удобна в командных файлах. Например, следующая запись выводит значение сразу трех регистров (обрати внимание на отсутствие круглых скобок вокруг нее!):

Назад на стр. 093-122-4  Содержание  Вперед на стр. 093-122-6