Here is my code
#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();
}
Here is the disassembly code by gdb for func_1 and 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
In func_1, buffer is allocated for 0x10(16) bytes, but in func_2 , it is allocated for 0x18(24) bytes, why?
Edit: @Attie figure out that buffer size is actually the same for both, but there's strange 8-byte stack spaces in func_2 don't know where it comes from.
I have just tried to reproduce this, see below:
Compiling for x86-64
(no joy):
$ 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
Compiling for i386
(success):
$ 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
This doesn't appear to be related to any of the following:
getchar()
is a library function, and thus we are calling into the PLT (Procedure Linkage Table).main()
If you however increase the size of your buffer by one, to 17
, then the stack usage increases to 32 and 40 bytes (from 16 and 24 bytes) respectively. The difference is 16 bytes, which is used for alignment, as answered here.
I can't answer why the stack alignment appears to be off by 8-bytes upon entering func_2()
though.
If you update func_1()
and func_2()
to have a 15-byte buffer, and a single byte variable, and write data to them, then you can see where these items are in the stack frame:
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();
}
08048434 <func_1>:
8048434: 55 push %ebp
8048435: 89 e5 mov %esp,%ebp
8048437: 83 ec 10 sub $0x10,%esp
804843a: c6 45 f0 aa movb $0xaa,-0x10(%ebp)
804843e: c6 45 ff 55 movb $0x55,-0x1(%ebp)
8048442: e8 d6 ff ff ff call 804841d <func_with_ret>
8048447: c9 leave
8048448: c3 ret
08048449 <func_2>:
8048449: 55 push %ebp
804844a: 89 e5 mov %esp,%ebp
804844c: 83 ec 18 sub $0x18,%esp
804844f: c6 45 e8 aa movb $0xaa,-0x18(%ebp)
8048453: c6 45 f7 55 movb $0x55,-0x9(%ebp)
8048457: e8 94 fe ff ff call 80482f0 <getchar@plt>
804845c: c9 leave
804845d: c3 ret
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With