Я пытаюсь понять смысл исполняемого кода, который генерирует 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 accounting.
pop %ebp
ret
или просто
leave
ret
который выполняет одно и то же:
- Установите указатель стека в верхнюю часть текущего кадра, чуть ниже обратный адрес
- Восстановить прежнее значение указателя фрейма.
В 64-битном коде, поскольку я вижу это через дизассемблер objdump, многие функции не следуют этому соглашению - они не нажимают% rbp, а затем сохраняют% rsp на% rbp. Как отладчик вроде GDB создает трассировка?
Моя реальная цель здесь - попытаться выяснить разумный адрес, который будет рассмотрен как верхний (самый высокий адрес) пользовательского стека, когда выполнение достигнет начала произвольной функции дальше в программу, где, возможно, указатель стека двинулся вниз. Например, для "top" исходный адрес argv был бы идеальным, но у меня нет доступа к нему из произвольной функции, которая вызывает основные вызовы. Сначала я подумал, что могу использовать старый метод backtrace: преследуя сохраненные значения указателя кадров до тех пор, пока не будет сохранено значение 0, затем следующий, который после этого может считаться наивысшим практическим значением. (Это не то же самое, что получить адрес argv, но он будет делать - скажем, чтобы узнать значение указателя стека в _start или любые другие вызовы _start [например, __libc_start_main].) Теперь я не знаю, как получить эквивалентный адрес в 64-битном коде.
Спасибо.