为什么缓冲区末尾和保存的帧指针之间有8个字节?

时间:2014-04-12 02:28:12

标签: c++ c linux gcc stack-overflow

我正在为课程作业进行堆栈式练习,我已经完成了作业,但有一个方面我不明白。

以下是目标计划:

#include <stdio.h>                                             
#include <stdlib.h>                                            
#include <string.h>                                            

int bar(char *arg, char *out)                                  
{                                                              
  strcpy(out, arg);                                            
  return 0;                                                    
}                                                              

void foo(char *argv[])                                         
{                                                              
  char buf[256];                                               
  bar(argv[1], buf);                                           
}                                                              

int main(int argc, char *argv[])                               
{                                                              
  if (argc != 2)                                               
    {                                                          
      fprintf(stderr, "target1: argc != 2\n");                 
      exit(EXIT_FAILURE);                                      
    }                                                          
  foo(argv);                                                   
  return 0;                                                    
}                                                              

以下是用于编译它的命令,在运行x86的{​​{1}}虚拟机上,Ubuntu 12.04已禁用。

ASLR

当我查看堆栈中此程序的内存时,我发现gcc -ggdb -m32 -g -std=c99 -D_GNU_SOURCE -fno-stack-protector -m32 target1.c -o target1 execstack -s target1 的地址为buf。此外,保存的帧指针存储在0xbffffc40,返回地址存储在0xbffffd48

这些具体地址不相关,但我观察到即使0xbffffd4c只有buf长度,距离256也是如此。符号上,此计算为0xbffffd48 - 0xbffffc40 = 264

为什么$fp - buf的末尾与堆栈中存储的帧指针之间有8个额外字节?

以下是函数buf的一些反汇编。我已经检查了它,但我没有看到该内存区域的任何明显用法,除非它是隐式的(即某些指令的副作用)。

foo

1 个答案:

答案 0 :(得分:3)

Basile Starynkevitch因提及alignment而获奖。

事实证明gcc 4.7.2默认将帧边界与4字边界对齐。在32位仿真硬件上,即16字节。由于保存的帧指针和保存的指令指针只占用8个字节,编译器在buf结束后再放入8个字节,使堆栈帧的顶部与16字节边界对齐。

使用以下附加编译器标志,8个字节消失,因为8个字节足以对齐2个字的边界。

-mpreferred-stack-boundary=2