Stack frame

A stack frame is a portion of memory that is used by a program to store local variables and information about the current state of a subroutine. In most programming languages, a stack frame is created each time a subroutine is called, and is destroyed when it returns.

#include <stdio.h>

void HelloWorld(void){
  printf("World !\n");
}

int main(void) {
  printf("Hello ");
  HelloWorld();
  return 0;
}

In this example, when the process enter into the HelloWorld function, there is two stack frame into the stack, one for the main function and another for the HelloWorld function.

During the execution, the "Base pointer" register (for example EBP in x86 architecture) point the bottom of the current stack frame and the "stack pointer" register (for example ESP in x86 architecture) point to the top of the stack which is also the top of the current stack frame.

                     |----------------------------------|
                     |               ^                  |
                     |               |                  |
                     | ...                              |
   stack pointer --> | +------------------------------+ | 
                     | |                              | |
                     | |     HelloWord stack frame    | |
                     | |                              | |
   Base Pointer  --> | +------------------------------+ | 
                     | +------------------------------+ | 
                     | |                              | |
                     | |       main stack frame       | |
                     | |                              | |
                     | +------------------------------+ |
                     |  ...                             |
                     |----------------------------------|

Prologue

The prologue of a function is the code that is executed at the beginning of the function, before any other function's code.

Code example

Here is the assembly code of the main function :

Into the main function, when the Addition function need to be executed, the call instruction is executed, and in fact the process execute the two followed instruction :

At this moment, the instruction pointer is saved onto the stack

Before that, the process will store the function parameters onto the stack.

Note that the saved Instruction Pointer value point to *main+45that directly follow the call of the Addition Function

At the jmp instruction, the Intruction Pointer will now point at the beggining of the Addition function (0x56556199)

Here is the assembly code of the Addition function :

At the begining of the fonction, there is two instructions. This is the prologue :

  1. The first one saved the current base pointer value onto the stack

  2. The second set the base pointer value as the stack pointer value. At this moment base pointer and stack pointer have the same value, this is the begining of the stack frame.

Note, if the process have to push a local variable into the stack, the stack pointer will take some marge after setting the ebp register.

Here is the stack state after the execution of theses instructions

Now Base Pointer poit to 0xffffd270 and Stack Pointer will point "0xffffd264"

To summarize:

  1. A function will call a child function

  2. The process store the address of the next instuction of the current function onto the stack

  3. The process go to the frst instruction of the child function ( at this moment a new stack frame will be create )

  4. the process store the adress of the parent bottom stack frame onto the stack

  5. the process set the "Base Pointer" registry at the same value as the "Stack Pointer" registry ( the stack frame is now created )

Epilogue

At the end of a function there is some instruction to reset the Base Pointer at the parent bottom stack frame address value and to reset the instruction pointer at the next instruction of the parent function.

  1. At the end of the execution of a function, the last value into the stack frame is the base address of the parent function stack frame

  2. The process will pop this value into EBP in order to restore the parent function stack frame

  3. Now the process is back into the parent function stack frame and the top value is the saved EIP

  4. The process will pop this value into EIP in order to restore the instruction pointer and then continue the execution flow into the parent function

Resume

The program is read instruction by instruction. During a call , the current instruction Pointer (EIP) is pushed onto the stack, and then control is transferred to the address given by the call. Here, a new stack frame is set onto the stack and the instructions of the function are executed one after the other until it will finish and then trash this stack frame and return to the parent function with the RET instruction that retrieves the previously recorded EIP value, in order to return to where the program was, without losing the thread!

Last updated