Как разобрать диапазон памяти с помощью GDB? - PullRequest
58 голосов
/ 06 августа 2009

Я пытаюсь разобрать программу, чтобы увидеть инструкцию по сборке системного вызова (я полагаю, инструкцию INT) и обработчик с GDB, и написал небольшую программу (см. Ниже), которая открывает и закрывает файл.

Мне удалось выполнить вызов fopen с помощью GDB, пока он не выполнил вызов.

Когда я попытался сказать GDB «дизассемблировать 0x ....» (адрес вызова), он ответил: «Нет функции, содержащей указанный адрес.»

Можно ли заставить GDB разбирать (или отображать в ассемблере как можно лучше) этот адрес памяти? Если так, то как?

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

int main() {
    FILE* f;
    f = fopen("main.c", "r");
    if (!f) { 
      perror("open");
      return -1;
    }
    fclose(f);
    return 0;
}

Ответы [ 8 ]

93 голосов
/ 09 октября 2009

Да, дизассемблирование - не лучшая команда для использования здесь. Вам нужна команда "x / i" (проверьте как инструкции):

(gdb) x/i 0xdeadbeef
45 голосов
/ 07 августа 2009

Вы хотите только разобрать свой фактический основной? Если так, попробуйте это:

(gdb) info line main 
(gdb) disas STARTADDRESS ENDADDRESS

Вот так:

USER@MACHINE /cygdrive/c/prog/dsa
$ gcc-3.exe -g main.c

USER@MACHINE /cygdrive/c/prog/dsa
$ gdb a.exe
GNU gdb 6.8.0.20080328-cvs (cygwin-special)
...
(gdb) info line main
Line 3 of "main.c" starts at address 0x401050 <main> and ends at 0x401075 <main+
(gdb) disas 0x401050 0x401075
Dump of assembler code from 0x401050 to 0x401075:
0x00401050 <main+0>:    push   %ebp
0x00401051 <main+1>:    mov    %esp,%ebp
0x00401053 <main+3>:    sub    $0x18,%esp
0x00401056 <main+6>:    and    $0xfffffff0,%esp
0x00401059 <main+9>:    mov    $0x0,%eax
0x0040105e <main+14>:   add    $0xf,%eax
0x00401061 <main+17>:   add    $0xf,%eax
0x00401064 <main+20>:   shr    $0x4,%eax
0x00401067 <main+23>:   shl    $0x4,%eax
0x0040106a <main+26>:   mov    %eax,-0xc(%ebp)
0x0040106d <main+29>:   mov    -0xc(%ebp),%eax
0x00401070 <main+32>:   call   0x4010c4 <_alloca>
End of assembler dump.

Однако я не вижу ваш системный вызов прерывания. (Прошло некоторое время с тех пор, как я в последний раз пытался сделать системный вызов в ассемблере. Хотя INT 21h, в последний раз я вспоминаю

30 голосов
/ 07 августа 2009

Это не прямой ответ на ваш вопрос, но, поскольку вы, похоже, просто хотите разобрать двоичный файл, возможно, вы могли бы просто использовать objdump:

objdump -d program

Это должно дать вам его разборку. Вы можете добавить -S, если хотите, чтобы он был аннотирован.

7 голосов
/ 25 января 2010

fopen () - это функция библиотеки C, поэтому вы не увидите в своем коде никаких инструкций syscall, только обычный вызов функции. В какой-то момент он вызывает open (2), но делает это через батут. Существует просто переход на страницу VDSO, которая предоставляется ядром для каждого процесса. Затем VDSO предоставляет код для выполнения системного вызова. На современных процессорах будут использоваться инструкции SYSCALL или SYSENTER, но вы также можете использовать INT 80h на процессорах x86.

6 голосов
/ 18 сентября 2009

Вы можете принудительно вывести gcc на код сборки, добавив ключ -S

gcc -S hello.c
3 голосов
/ 22 октября 2009

Если все, что вам нужно, это увидеть разборку с помощью вызова INTC, используйте objdump -d, как кто-то упоминал, но используйте опцию -static при компиляции. В противном случае функция fopen не компилируется в elf и связывается во время выполнения.

1 голос
/ 26 февраля 2015

GDB disassemble имеет / m для включения исходного кода вместе с инструкциями. Это эквивалентно objdump -S, с дополнительным преимуществом ограничения только одной интересующей функции (или диапазона адресов).

1 голос
/ 23 июля 2014

Вам не нужно использовать GDB. GCC сделает это.

 gcc -S foo.c

Это создаст foo.s, который является сборкой.

gcc -m32 -c -g -Wa,-a,-ad foo.c > foo.lst

Приведенная выше версия создаст файл со списком, в котором будет создан как C, так и сборка. GCC FAQ

...