(gdb) disas foo
Dump of assembler code for function foo:
0x00000000004004a8 <foo+0>: push %rbp
0x00000000004004a9 <foo+1>: mov %rsp,%rbp
0x00000000004004ac <foo+4>: mov 0x13c(%rip),%eax # 0x4005ee <__dso_handle+30>
0x00000000004004b2 <foo+10>: mov %eax,-0x10(%rbp)
0x00000000004004b5 <foo+13>: lea -0x10(%rbp),%rax
0x00000000004004b9 <foo+17>: add $0x18,%rax
0x00000000004004bd <foo+21>: mov %rax,%rdx
0x00000000004004c0 <foo+24>: mov $0x400498,%eax
0x00000000004004c5 <foo+29>: mov %eax,(%rdx)
0x00000000004004c7 <foo+31>: leaveq
0x00000000004004c8 <foo+32>: retq
(gdb) l foo
8 void foo() {
9 char overme[4] = "WOW";
10 *(int*)(overme+24) = (int)bad;
11 }
Why not just 8 bytes?
The compiler is maintaining a 16-byte alignment of the stack pointer when a function is called, adding padding to the stack as necessary. The compiler knows that the stack will always be aligned correctly, so it can emit instructions with alignment requirements without risk of triggering their fault conditions.
This effectively means that the address of the memory your data resides in needs to be divisible by the number of bytes required by the instruction. So in your case the alignment is 16 bytes (128 bits), which means the memory address of your data needs to be a multiple of 16.
64-bit aligned is 8 bytes aligned). A memory access is said to be aligned when the data being accessed is n bytes long and the datum address is n-byte aligned. When a memory access is not aligned, it is said to be misaligned. Note that by definition byte memory accesses are always aligned.
The GNU documentation states that malloc is aligned to 16 byte multiples on 64 bit systems.
gcc is not "assigning" this space to the variable. Rather, the x86_64 abi requires the stack pointer to always be 16-byte-aligned at function calls, in case the callee uses vectorized SSE math. It's a really stupid and wasteful requirement (the callee should ensure the alignment if it needs it), but that's the standard, and gcc follows the standard. You can fix it with -mpreferred-stack-boundary=3
(8 byte alignment, the minimum for 64-bit).
It is 8 bytes, not 16. The LEA instruction doesn't show anything alignment related, -0x10 is just an offset applied to the value of the RBP register. Probably to generate the address of a small local array. If the code generator uses any SIMD instructions then 16 could be relevant. None of which is visible in a two-liner question.
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