I have the following C code compiled with GCC and disassembled to assembly in gdb. I’m using a Macbook pro with 64bit Intel i5 processor. In the ‘main()’ the ‘char* name[2]’ has 2 char pointers which should let the stack pointer decrease by 2 words(16 bytes)? However, when I disassembled in gdb it decreases by 20…Can some one help me understand?
C code:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char* name[2];
name[0] = "/bin/sh";
name[1]= NULL;
execve(name[0],name,NULL);
}
gdb disassembled code:
GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Thu Nov 3 21:59:02 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000100000ee0 <main+0>: push %rbp
0x0000000100000ee1 <main+1>: mov %rsp,%rbp
0x0000000100000ee4 <main+4>: sub $0x20,%rsp
0x0000000100000ee8 <main+8>: lea -0x18(%rbp),%rax
0x0000000100000eec <main+12>: lea 0x61(%rip),%rcx # 0x100000f54
0x0000000100000ef3 <main+19>: mov %rcx,-0x18(%rbp)
0x0000000100000ef7 <main+23>: movq $0x0,-0x10(%rbp)
0x0000000100000eff <main+31>: mov -0x18(%rbp),%rcx
0x0000000100000f03 <main+35>: mov $0x0,%rdx
0x0000000100000f0d <main+45>: mov %rcx,%rdi
0x0000000100000f10 <main+48>: mov %rax,%rsi
0x0000000100000f13 <main+51>: callq 0x100000f22 <dyld_stub_execve>
0x0000000100000f18 <main+56>: mov -0x4(%rbp),%eax
0x0000000100000f1b <main+59>: add $0x20,%rsp
0x0000000100000f1f <main+63>: pop %rbp
0x0000000100000f20 <main+64>: retq
End of assembler dump.
So, reading the assembly, name[0] is at -0x18 on the stack and name1 is at -0x10. Also, as noted before, -0x4 is used for the return value.
That leaves 12 bytes, since 0x20 is actually 32. The range -32 to -24 and the range -8 to -4.
-8 to -4 is definitely alignment, and I’m going to guess -32 to -24 is as well (for 16 byte alignment).
Edit: Note that actually 48 bytes is subtracted. The callq instruction to call into main subtracts 8 bytes from RSP, and
push %rbpanother 8.Verified 16 byte alignment: x86-64 System V ABI section 3.2.2 (direct link to PDF of an old version)