Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why gcc disassembler allocating extra space for local variable?

I have written simple function in C,

void GetInput()
{
    char buffer[8];
    gets(buffer);
    puts(buffer);
}

When I disassemble it in gdb's disassembler, it gives following disassembly.

   0x08048464 <+0>: push   %ebp
   0x08048465 <+1>: mov    %esp,%ebp
   0x08048467 <+3>: sub    $0x10,%esp
   0x0804846a <+6>: mov    %gs:0x14,%eax
   0x08048470 <+12>:    mov    %eax,-0x4(%ebp)
   0x08048473 <+15>:    xor    %eax,%eax
=> 0x08048475 <+17>:    lea    -0xc(%ebp),%eax
   0x08048478 <+20>:    mov    %eax,(%esp)
   0x0804847b <+23>:    call   0x8048360 <gets@plt>
   0x08048480 <+28>:    lea    -0xc(%ebp),%eax
   0x08048483 <+31>:    mov    %eax,(%esp)
   0x08048486 <+34>:    call   0x8048380 <puts@plt>
   0x0804848b <+39>:    mov    -0x4(%ebp),%eax
   0x0804848e <+42>:    xor    %gs:0x14,%eax
   0x08048495 <+49>:    je     0x804849c <GetInput+56>
   0x08048497 <+51>:    call   0x8048370 <__stack_chk_fail@plt>
   0x0804849c <+56>:    leave  
   0x0804849d <+57>:    ret    

Now please look at line number three, 0x08048467 <+3>: sub $0x10,%esp, I have only 8 bytes allocated as local variable, then why compiler is allocating 16 bytes(0x10).

Secondly, what is meaning of xor %gs:0x14,%eax.

@Edit: If it is optimization, is there any way to stop it.

Thanks.

like image 439
Pranit Kothari Avatar asked Jan 01 '14 03:01

Pranit Kothari


3 Answers

Two things:

  1. The compiler may reserve space for intermediate expressions to which you did not give names in the source code (or conversely not allocate space for local variables that can live entirely in registers). The list of stack slots in the binary does not have to match the list of local variables in the source code.
  2. On some platforms, the compiler has to keep the stack pointer aligned. For the particular example in your question, it is likely that the compiler is striving to keep the stack pointer aligned to a boundary of 16 bytes.

Regarding your other question that you should have asked separately, xor %gs:0x14,%eax is clearly part of a stack protection mechanism, enabled by default. If you are using GCC, turn it off with -fno-stack-protector.

like image 117
Pascal Cuoq Avatar answered Nov 19 '22 01:11

Pascal Cuoq


Besides the other answers already given, gcc will prefer to keep the stack 16-byte aligned for storing SSE values on the stack since some (all?) of the SSE instructions require their memory argument to be 16-byte aligned.

like image 5
Geoff Reedy Avatar answered Nov 19 '22 01:11

Geoff Reedy


This more builds upon Pascal's answer, but in this case, it's probably because of the stack protection mechanism.

You allocate 8 bytes, which is fair enough and taken into account with the stack pointer. In addition, the current stack protection address is saved to %ebp, which points to the top of the current stack frame on the following lines

0x0804846a <+6>: mov    %gs:0x14,%eax
0x08048470 <+12>:    mov    %eax,-0x4(%ebp)

This appears to take a four bytes. Given this, the other four bytes are probably for alignment of some form, or are taken up with some other stack information on the following lines:

=> 0x08048475 <+17>:    lea    -0xc(%ebp),%eax
   0x08048478 <+20>:    mov    %eax,(%esp)
like image 4
slugonamission Avatar answered Nov 19 '22 02:11

slugonamission