这是我的代码
#include <stdio.h>
char func_with_ret()
{
return 1;
}
void func_1()
{
char buf[16];
func_with_ret();
}
void func_2()
{
char buf[16];
getchar();
}
int main()
{
func_1();
func_2();
}
Run Code Online (Sandbox Code Playgroud)
以下是gdb对func_1和func_2的反汇编代码.
Dump of assembler code for function func_1:
0x08048427 <+0>: push ebp
0x08048428 <+1>: mov ebp,esp
0x0804842a <+3>: sub esp,0x10
0x0804842d <+6>: call 0x804841d <func_with_ret>
0x08048432 <+11>: leave
0x08048433 <+12>: ret
Dump of assembler code for function func_2:
0x08048434 <+0>: push ebp
0x08048435 <+1>: mov ebp,esp
0x08048437 <+3>: sub esp,0x18
0x0804843a <+6>: call 0x80482f0 <getchar@plt>
0x0804843f <+11>: leave
0x08048440 <+12>: ret
Run Code Online (Sandbox Code Playgroud)
在func_1中,缓冲区分配给0x10(16)字节,但在func_2中,它被分配为0x18(24)字节,为什么?
编辑:@Attie弄清楚两者的缓冲区大小实际上是相同的,但是func_2中的奇怪的8字节堆栈空间不知道它来自何处.
我刚刚尝试重现此内容,请参见下文:
编译x86-64(没有乐趣):
$ gcc p.c -g -o p -O0 -fno-stack-protector
$ objdump -d p
p: file format elf64-x86-64
[...]
0000000000400538 <func_1>:
400538: 55 push %rbp
400539: 48 89 e5 mov %rsp,%rbp
40053c: 48 83 ec 10 sub $0x10,%rsp
400540: b8 00 00 00 00 mov $0x0,%eax
400545: e8 e3 ff ff ff callq 40052d <func_with_ret>
40054a: c9 leaveq
40054b: c3 retq
000000000040054c <func_2>:
40054c: 55 push %rbp
40054d: 48 89 e5 mov %rsp,%rbp
400550: 48 83 ec 10 sub $0x10,%rsp
400554: e8 c7 fe ff ff callq 400420 <getchar@plt>
400559: c9 leaveq
40055a: c3 retq
Run Code Online (Sandbox Code Playgroud)
编译i386(成功):
$ gcc p.c -g -o p -O0 -fno-stack-protector -m32
$ objdump -d p
p: file format elf32-i386
[...]
08048427 <func_1>:
8048427: 55 push %ebp
8048428: 89 e5 mov %esp,%ebp
804842a: 83 ec 10 sub $0x10,%esp
804842d: e8 eb ff ff ff call 804841d <func_with_ret>
8048432: c9 leave
8048433: c3 ret
08048434 <func_2>:
8048434: 55 push %ebp
8048435: 89 e5 mov %esp,%ebp
8048437: 83 ec 18 sub $0x18,%esp
804843a: e8 b1 fe ff ff call 80482f0 <getchar@plt>
804843f: c9 leave
8048440: c3 ret
Run Code Online (Sandbox Code Playgroud)
这似乎与以下任何一项都无关:
getchar()是一个库函数,因此我们调用 PLT(过程链接表)。main()但是,如果将缓冲区的大小增加 1,17则堆栈使用量将分别增加到 32 和 40 字节(从 16 和 24 字节)。差异是 16 个字节,用于对齐,如此处回答所回答的。
我无法回答为什么在进入时堆栈对齐似乎偏离了 8 个字节func_2()。
如果您更新func_1()并func_2()拥有一个 15 字节缓冲区和一个单字节变量,并向其中写入数据,那么您可以看到这些项目在堆栈帧中的位置:
void func_1(void) {
char buf[15];
char x;
buf[0] = 0xaa;
x = 0x55;
func_with_ret();
}
void func_2(void) {
char buf[15];
char x;
buf[0] = 0xaa;
x = 0x55;
getchar();
}
Run Code Online (Sandbox Code Playgroud)
void func_1(void) {
char buf[15];
char x;
buf[0] = 0xaa;
x = 0x55;
func_with_ret();
}
void func_2(void) {
char buf[15];
char x;
buf[0] = 0xaa;
x = 0x55;
getchar();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
161 次 |
| 最近记录: |