Я пытаюсь разобраться в исполняемом коде, который GCC (4.4.3) генерирует для машины x86_64, работающей под Ubuntu Linux.В частности, я не понимаю, как код отслеживает кадры стека.В прежние времена в 32-битном коде я привык видеть этот «пролог» практически во всех функциях:
push %ebp
movl %esp, %ebp
Затем в конце функции будет «эпилог»., "либо
sub $xx, %esp # Where xx is a number based on GCC's accounting.
pop %ebp
ret
, либо просто
leave
ret
, которая выполняет то же самое:
- Установите указатель стека на верхнюю часть текущего кадра,чуть ниже обратного адреса
- Восстановите старое значение Frame Pointer.
В 64-битном коде, как я вижу это через разборку objdump, многие функции не следуют этому соглашению.- они не нажимают% rbp, а затем сохраняют% rsp в% rbp. Как отладчик, такой как GDB, создает обратную трассировку?
Моя настоящая цель заключается в том, чтобы попытаться найти разумный адрес, который можно рассматривать какtop (самый высокий адрес) пользовательского стека, когда выполнение достигает начала произвольной функции дальше в программе, где, возможно, указатель стека переместился вниз.Например, для «top» идеальным будет исходный адрес argv, но у меня нет доступа к нему из произвольной функции, вызываемой main.Сначала я подумал, что мог бы использовать старый метод обратной трассировки: погоня за сохраненными значениями Frame Pointer до тех пор, пока сохраненное значение не станет равным 0, а затем следующее значение может считаться самым высоким практическим значением.(Это не то же самое, что получить адрес argv, но он будет полезен, скажем, для определения значения указателя стека в _start или любых других вызовов _start [например, __libc_start_main].) Теперь я не знаю, какполучить эквивалентный адрес в 64-битном коде.
Спасибо.