Reputation: 389
I'm not sure if I'm delusional, but I'm near certain calls used to fail on System V Linux x86_64 if they weren't aligned upon entry (i.e. you'd purposely disalign the stack before a call
so it's aligned upon entry).
For example (this now works):
.data
str: .asciz "string literal"
.text
.globl main
main:
lea str(%rip), %rdi
call puts@plt
xor %eax, %eax
ret
I'm near certain this used to fail, can someone explain if I am: delusional (i.e. this has always worked), misunderstanding the semantics of stack alignment, unaware of (somewhat recent?) changes in something, somewhere?
Previously I'd always purposely disaligned using a push
(as per the common prologue) or simply sub $8, %rsp
, but now code I write without doing that seems to work just fine?
Is this a nuance or is this behaviour now acceptable?
Upvotes: 1
Views: 126
Reputation: 12455
You're not delusional. The x86-64 SysV ABI requires that the stack be aligned to 16 before calling an external function, implying that the stack pointer value mod 16 is 8 on entry to a function, and that it must be adjusted by an odd multiple of 8 to realign it prior to calling another function. However, this is not strictly enforced. The call itself won't ever fault, nor will most types of instructions used to access the stack. It only causes a fault if the called function accesses a value on the stack using an instruction that requires alignment, such as certain SSE instructions (including SSE extensions and AVX).
The implementations of some library functions always perform such an access, so they will always fault on an unaligned stack. Some other library functions may perform such accesses to the stack depending on the data they are passed, and some don't ever use such accesses, and will not fault regardless of stack alignment. However, it is unwise to rely on any of this, since the implementations can change. Always align your stack before making a call.
Upvotes: 4