poulecaca
poulecaca

Reputation: 1

What is gcc doing with my stack?

EDIT The real question is at the end of the post I'm trying to undestand how gcc manage the stack size but I have some question I don't find the answer.

Gcc does something weird when I call a function in another one. It allocates extra bytes and I don't understand what for.

Here is the simpliest C code ever :

int f(){
    int i =12;
    return 0;
}


int main(void){
    f();
    return 0;
}

and then the disass of f() that gdb produces :

0x08048386 <+0>:     push   %ebp
0x08048387 <+1>:     mov    %esp,%ebp
0x08048389 <+3>:     sub    $0x10,%esp <- this part
0x0804838c <+6>:     movl   $0xc,-0x4(%ebp)
0x08048393 <+13>:    mov    $0x0,%eax
0x08048398 <+18>:    leave  
0x08048399 <+19>:    ret  

Here ok I undestand. gcc makes 16 bytes alignement stack as i is an int (so 4 bytes) gcc allocates 16 bytes on the stack for i.

But As soon as I call a function in f() I don't get what gcc is doing. Here is the new C code :

int g(int i){
    i=12;
    return i;
}

int f(){
    int i =12;
    g(i);
    return 0;
}


int main(void){
    f();
    return 0;
}

And then the f() disass :

0x08048386 <+0>:     push   %ebp
0x08048387 <+1>:     mov    %esp,%ebp
0x08048389 <+3>:     sub    $0x14,%esp <- Here is my understanding
0x0804838c <+6>:     movl   $0xc,-0x4(%ebp)
0x08048393 <+13>:    mov    -0x4(%ebp),%eax
0x08048396 <+16>:    mov    %eax,(%esp)
0x08048399 <+19>:    call   0x8048374 <g>
0x0804839e <+24>:    mov    $0x0,%eax
0x080483a3 <+29>:    leave  
0x080483a4 <+30>:    ret

Then gcc allocates 4 extra bytes whereas there is no more change than f() is calling g().

And this can be worst when I play with more functions.

So any of you have any idea what are this extra bytes for and what is gcc's stack allocation policy ?

Thank you in advance.

EDIT: real question

Ok sorry I wrote the question too fast in fact it's ok with the sub 0x14 %esp my real understanding is with this piece of code :

int f(){
    char i[5];
    char j[5];
    i[4]=0;
    j[4]=0;
    strcpy(i,j);
    return 0;
}


int main(void){
    f();
    return 0;
}

And then f()'s disass :

0x080483a4 <+0>:     push   %ebp
0x080483a5 <+1>:     mov    %esp,%ebp
0x080483a7 <+3>:     sub    $0x28,%esp
0x080483aa <+6>:     movb   $0x0,-0x9(%ebp)
0x080483ae <+10>:    movb   $0x0,-0xe(%ebp)
0x080483b2 <+14>:    lea    -0x12(%ebp),%eax
0x080483b5 <+17>:    mov    %eax,0x4(%esp)
0x080483b9 <+21>:    lea    -0xd(%ebp),%eax
0x080483bc <+24>:    mov    %eax,(%esp)
0x080483bf <+27>:    call   0x80482d8 <strcpy@plt>
0x080483c4 <+32>:    mov    $0x0,%eax
0x080483c9 <+37>:    leave  
0x080483ca <+38>:    ret

The stack look like something like that :

[oldip][oldebp][Extra(8B)][Arrays(10B)][Rearrange stack(14B)][Argument1(4B)][Argument2(4B)]

Here we see that 8 extra bytes come between the saved ebp and the local variables. So here is really my understanding.

Sorry for having posting too fast and still thanks for your quick answer.

Upvotes: 0

Views: 902

Answers (2)

old_timer
old_timer

Reputation: 71546

I would think in the first case the 4 bytes are for the one parameter needed when calling g(). and in the second case two 4 byte words needed for the two parameters when calling strcpy(). call a dummy function with three parameters and see if it changes to 12 bytes.

Upvotes: 0

secmask
secmask

Reputation: 8107

0x08048386 <+0>:     push   %ebp
0x08048387 <+1>:     mov    %esp,%ebp
0x08048389 <+3>:     sub    $0x14,%esp <- include 0x10 bytes for stack alignment and 4 byte for 1 parameter
0x0804838c <+6>:     movl   $0xc,-0x4(%ebp)
0x08048393 <+13>:    mov    -0x4(%ebp),%eax
0x08048396 <+16>:    mov    %eax,(%esp)
0x08048399 <+19>:    call   0x8048374 <g>
0x0804839e <+24>:    mov    $0x0,%eax
0x080483a3 <+29>:    leave  
0x080483a4 <+30>:    ret

as you can see, it allocate 16 bytes included i and stack alignment, plus 4 byte for one parameter, the stack will look like this.

00 7f 7c 13              --> return from call address
00 00 00 00              --> this one for parameter when call g(i)  --> low address
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 0C ---> i       (ignore about edian)        --> high address 

Upvotes: 0

Related Questions