Как рассчитать кадр стека в сборке в GDB? - PullRequest
0 голосов
/ 09 мая 2018

Я пытаюсь исследовать отладку ассемблерного кода (x86, 32-битный, C исходный код).

Я хотел бы понять, как я могу вычислить фактический размер стекового фрейма конкретной функции в моем коде сборки при использовании gdb.

Является ли размер кадра, абсолютная разница между %esp и %ebp суммированным с каждым значением, которое влияет на %esp, до того, как все всплывет?

pushl   %ebp
movl    %esp, %ebp
subl    $24, %esp
subl    $48, 8(%ebp)

Программное обеспечение: GNU gdb (Debian 7.12-6) 7.12.0.20161007-git

gcc -m32 -fno-asynchronous-unwind-tables -fno-pic -S main.c
gcc -c -m32 main.s -o main.out
gcc -g -m32 main.s -o main.out
gcc -m32 -g -o main main.s
as -a main.s

Буду благодарен, если кто-нибудь сможет мне помочь.

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

В идеальном мире локальные переменные будут расположены с постоянным смещением от EBP, чтобы вы могли определить размер кадра стека.Однако компилятор и оптимизации слишком важны, и один из сценариев может заключаться в том, что EBP используется в качестве GPR ( Попытка понять параметр gcc -fomit-frame-pointer ).Может ли статический анализ стать хорошим решением?

0 голосов
/ 09 мая 2018

Нет, ты не можешь.

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

Фактическая технология компилятора настолько продвинута, что даже стандартные функции прологов и эпилогов могут быть изменены для наиболее агрессивной оптимизации, что еще более усложняет разматывание кадра.

Действует только на базовом кадре, что в случае 32-битного кода X86 соответствует значению, сохраненному в регистре %ebp, недостаточно.

Самая последняя эволюция, как сказал @Jester, продемонстрировала, что даже %ebp не требуется для разматывания стека исключений, а агрессивные переключатели оптимизации в компиляторах, как -fomit-frame-pointer в GCC, больше не сохраняют его в стеке (см. libunwind ниже).

Чтобы получить доступ к предыдущему кадру, начиная с удержания адреса базового кадра в %ebp, вам нужна ширина стека кадра стека для относительной функции, включая все операции стека.

Эта информация обычно хранится в определенном разделе исполняемого файла, как правило, с использованием списка записей о стековых операциях. Разделы:

  1. .pdata для исполняемых файлов Microsoft PE
  2. .eh_frame и .eh_frame_hdr для формата ELF (Linux).

В зависимости от того, с какой ОС вы хотите работать, вы можете получить дополнительную информацию, начиная с https://www -user.tu-chemnitz.de / ~ heha / viewchm.php / hs / Win32SEH.chm / Win32SEH.htm для исполняемых файлов Microsoft.

Для системы на базе Linux вы можете начать поиск здесь https://gnu.wildebeest.org/blog/mjw/2007/08/23/stack-unwinding/ и в конечном итоге получить подробное описание отладчика DWARF http://wiki.dwarfstd.org/index.php?title=Special:SpecialPages, и https://www.nongnu.org/libunwind/ для технически подробного погружения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...