I have recently exploited a dangerous program and found something interesting about the difference between versions of gcc on x86-64 architecture.
Note:
Wrongful usage of
getsis not the issue here.If we replace
getswith any other functions, the problem doesn't change.
This is the source code I use:
#include <stdio.h>
int main()
{
    char buf[16];
    gets(buf);
    return 0;
}
I use gcc.godbolt.org to disassemble the program with flag -m32 -fno-stack-protector -z execstack -g.
At the disassembled code, when gcc with version >= 4.9.0:
lea     ecx, [esp+4]            # begin of main
and     esp, -16
push    DWORD PTR [ecx-4]       # push esp
push    ebp
mov     ebp, esp
/* between these comment is not related to the question
push    ecx
sub     esp, 20
sub     esp, 12
lea     eax, [ebp-24]
push    eax
call    gets
add     esp, 16
mov     eax, 0
*/
mov     ebp, esp            
mov     ecx, DWORD PTR [ebp-4]  # ecx = saved esp
leave
lea     esp, [ecx-4]
ret                             # end of main
But gcc with version < 4.9.0 just:
push    ebp                     # begin of main
mov     ebp, esp
/* between these comment is not related to the question
and     esp, -16
sub     esp, 32
lea     eax, [esp+16]
mov     DWORD PTR [esp], eax
call    gets
mov     eax, 0
*/
leave
ret                             # end of main
My question is: What is the causes of this difference on the disassembled code and its benefits? Does it have a name for this technique?
                        
I can't say for sure without the actual values in:
but this looks a lot like extra code to align the stack to a larger value than the ABI requires.
Edit: The value is -16, which is 32-bit
0xFFFFFFF0or 64-bit0xFFFFFFFFFFFFFFF0so this is indeed stack alignment to 16 bytes, likely meant for use of SSE instructions. As mentioned in comments, there is more code in the >= 4.9.0 version because it also aligns the frame pointer instead of only the stack pointer.