# Stack Frame

## Motivation: Function Call

Before `functionA` calls `functionB`, we have to save some information of `functionA` in order to recover its context when it returns:

* Function arguments
* Return address (the next RIP address when functionA returns)
* Register values

In OS, this functionality is implemented using **stack**.

## Stack

The stack is typically structured as a linear sequence of memory allocations known as stack frames. Each time a function is called, the stack will automatically allocate a new stack frame. As the function executes, it will use the given stack frame to store and operate upon its local variables. Once the function returns, this memory will automatically get released back to the stack.

The stack fulfils four main uses:

* Track the "callstack" of a program. return values are "pushed" to the stack during a call and "popped" during a ret
* Contain local variables of functions.
* Provide scratch space (to alleviate register exhaustion).
* Pass function arguments (always on x86, only for functions with "many" arguments on other architectures).

Relevant registers (amd64):

* rsp
* rbp

Relevant instructions (amd64)

* push
* pop

## Calling Convention

The **cdecl** (which stands for **C declaration**) is a calling convention that originates from Microsoft's compiler for the C programming language and is used by many C compilers for the x86 architecture. In cdecl, subroutine arguments are passed on the stack.

**Key Ideas:**

* Arguments are pushed onto the stack **from right to left**.
* Return value is stored in `$rax`.

Also, the calling convention specifies stack alignment. Read this section to learn more:

{% content-ref url="../../pwn/linux-exploitation/rop/stack-alignment" %}
[stack-alignment](../../pwn/linux-exploitation/rop/stack-alignment)
{% endcontent-ref %}

## Caller vs. Callee

Consider a vulnerable C code snippet:

```c
int foo(int arg1, int arg2, int arg3)
{
    char buffer[64] = {0};
    gets(buffer);
    return 0;
}
```

Suppose the main function calls `foo()`, then the main function is the caller and foo() is the callee. When function call is happening, the caller is going to:

1. Push `arg3` onto the stack.
2. Push `arg2` onto the stack.
3. Push `arg1` onto the stack.
4. Push return address (the address of the next instruction when the callee returns) onto the stack, so the CPU knows what to do next when the callee returns.
5. Push `old rbp` (the `rbp` of the caller) onto the stack, so that the caller can reconstruct its stack frame when the callee returns.

Pictorially:

```
|      ...       | Low address
|     buffer     |
|      ...       |
|     old rbp    |
| return address |
|     arg1       |
|     arg2       |
|     arg3       | High address
```

## Prologue vs. Epilogue

### Prologue







### Epilogue









## Reference

{% embed url="https://en.wikipedia.org/wiki/X86_calling_conventions" %}
x86 calling convention - Wikipedia
{% endembed %}
