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:
Stack AlignmentCaller vs. Callee
Consider a vulnerable C code snippet:
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:
Push
arg3
onto the stack.Push
arg2
onto the stack.Push
arg1
onto the stack.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.
Push
old rbp
(therbp
of the caller) onto the stack, so that the caller can reconstruct its stack frame when the callee returns.
Pictorially:
Prologue vs. Epilogue
Prologue
Epilogue
Reference
Last updated