我正在尝试探索汇编代码(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如果有人能帮助我,我将不胜感激。
发布于 2018-05-09 19:23:58
不你不能。
堆栈帧从第一个参数被推送到堆栈上的点一直延伸到由于任何操作或指令而对堆栈进行的最后一次修改。即,使用alloca()或压入寄存器,或简单地将寄存器存储在预先分配的堆栈位置中,为动态变量分配空间。
实际的编译器技术是如此先进,甚至可以修改标准函数的前言和结尾,以进行最积极的优化,从而使框架展开更加复杂。
仅作用于基础帧是不够的,在32位X86代码对应于存储在%ebp寄存器中的值的情况下。
正如@Jester所说,最新的发展表明,即使是%ebp也不是异常堆栈展开所必需的,编译器中的积极优化开关,如GCC中的-fomit-frame-pointer,不再将其保存在堆栈上(参见下面的libunwind )。
要访问前一帧,从%ebp中保留的基帧地址开始,您需要相对函数的堆栈帧的堆栈宽度,包括所有堆栈操作。
此信息通常存储在可执行文件的特定部分中,通常使用有关堆栈操作的记录列表。这些部分包括:
用于微软PE executables
.eh_frame的.pdata和用于ELF格式(Linux)的.eh_frame_hdr。根据你想在哪种操作系统上工作,你可以从微软可执行文件的https://www-user.tu-chemnitz.de/~heha/viewchm.php/hs/Win32SEH.chm/Win32SEH.htm获取更多信息。
对于基于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/的详细技术细节。
发布于 2018-05-09 21:24:55
在理想情况下,局部变量将以与EBP的固定偏移量定位,因此您可以计算出堆栈帧的大小。然而,编译器和优化太重要了,其中一个场景可能是EBP被用作GPR (Trying to understand gcc option -fomit-frame-pointer)。静态分析可能是一个很好的解决方案吗?
https://stackoverflow.com/questions/50251637
复制相似问题