[英]what's this between local var and EBP on the stack?
对于这个简单的代码:
void main(){
char buf[12];
buf[11]='\xff';
puts(buf);
}
我使用gdb调试此代码并获取其堆栈信息,如下所示:
0xbffff480: 0x40158ff4 0x40158ff4 0xff0494dc 0x40158ff4
0xbffff490: 0x00000000 0x40016ca0 0xbffff4f8 0x40045de3
0xbffff480是“ buf”开始的位置,最后两个单词是EBP和RET,但是buf和EBP之间到底是什么? 显然,我没有任何其他本地var。 我还尝试了是否为堆栈上的buf分配8个字节,它只是从EBP继续,但是如果我分配9个或更多字节,则它之间总是有一些东西。 有人可以向我解释一下吗? 非常感谢! 我在Linux 2.6.9上
主拆卸:
0x080483c4 <main+0>: push %ebp
0x080483c5 <main+1>: mov %esp,%ebp
0x080483c7 <main+3>: sub $0x28,%esp
0x080483ca <main+6>: and $0xfffffff0,%esp
0x080483cd <main+9>: mov $0x0,%eax
0x080483d2 <main+14>: add $0xf,%eax
0x080483d5 <main+17>: add $0xf,%eax
0x080483d8 <main+20>: shr $0x4,%eax
0x080483db <main+23>: shl $0x4,%eax
0x080483de <main+26>: sub %eax,%esp
0x080483e0 <main+28>: movb $0xff,0xfffffff3(%ebp)
0x080483e4 <main+32>: lea 0xffffffe8(%ebp),%eax
0x080483e7 <main+35>: mov %eax,(%esp)
0x080483ea <main+38>: call 0x80482e4
0x080483ef <main+43>: leave
0x080483f0 <main+44>: ret
通常,为了能够使用SSE指令,gcc将堆栈对齐为16的倍数。 读取main
电源的拆卸将很有帮助。
众所周知,GCC在某种程度上对堆栈使用感到满意。 它通常保留比严格需要更多的堆栈空间。 另外,即使没有必要,它也会尝试实现16字节堆栈对齐。 第一条指令(保留40字节,然后%esp对齐至16的倍数)似乎发生了这种情况。
但是,您显示的代码包含一些奇怪的事情,尤其是从偏移量9到27的序列:这是从%esp减去16的漫长而缓慢的复杂方法,而这可以在单个操作码中完成。 此时从%esp减去一些字节是合乎逻辑的,以便为调用外部函数( puts()
)做准备,而count(16)尊重对齐方式,但是为什么要这么奇怪呢?
可能有可能打算以某种方式(例如在链接时)修补此序列,以支持堆栈粉碎检测代码或某种性能分析代码。 我无法在自己的系统上重现此内容。 您应该指定所使用的gcc
和libc的版本,确切的编译标志以及Linux发行版(因为发行商默认情况下会激活某些选项)。 “ 2.6.9”是内核版本,它与手头的问题没有任何关系(它只是告诉我们系统已经很旧了)。
您应该真正包括一个附件转储而不是一个纯十六进制转储。 但它很可能是两件事之一:
开始处可能还包含堆栈对齐,从而迫使上述一项或多项
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.