繁体   English   中英

本地var和EBP在堆栈上是什么?

[英]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

那将是填充 您的编译器可能会在8字节边界上对齐 EBP ,因为从处理器的角度来看,对齐的内存几乎总是更容易,更快捷地使用。 某些数据类型甚至需要正确对齐才能工作。

当您仅在缓冲区中分配8个字节时,您看不到任何填充,因为在这种情况下, EBP已正确对齐。

通常,为了能够使用SSE指令,gcc将堆栈对齐为16的倍数。 读取main电源的拆卸将很有帮助。

众所周知,GCC在某种程度上对堆栈使用感到满意。 它通常保留比严格需要更多的堆栈空间。 另外,即使没有必要,它也会尝试实现16字节堆栈对齐。 第一条指令(保留40字节,然后%esp对齐至16的倍数)似乎发生了这种情况。

但是,您显示的代码包含一些奇怪的事情,尤其是从偏移量9到27的序列:这是从%esp减去16的漫长而缓慢的复杂方法,而这可以在单个操作码中完成。 此时从%esp减去一些字节是合乎逻辑的,以便为调用外部函数( puts() )做准备,而count(16)尊重对齐方式,但是为什么要这么奇怪呢?

可能有可能打算以某种方式(例如在链接时)修补此序列,以支持堆栈粉碎检测代码或某种性能分析代码。 我无法在自己的系统上重现此内容。 您应该指定所使用的gcc和libc的版本,确切的编译标志以及Linux发行版(因为发行商默认情况下会激活某些选项)。 “ 2.6.9”是内核版本,它与手头的问题没有任何关系(它只是告诉我们系统已经很旧了)。

您应该真正包括一个附件转储而不是一个纯十六进制转储。 但它很可能是两件事之一:

  1. 恢复堆栈帧
  2. 进行堆栈检查以确保没有故障

开始处可能还包含堆栈对齐,从而迫使上述一项或多项

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM