Find out function arguments value from stack pointer

arguments, c, c++, linux, stack-trace

Solution

You must know the calling convention to know what order the arguments are pushed onto the stack, or even if they are on the stack. Many pass the first few arguments in registers. Even on x86, you have fastcall, pascal, register, stdcall and cdecl, just to name a few.

EDIT: Don't forget that `printf` is also a function, and local variables also go on the stack. So, in your sample app, you have your parameters (since it's cdecl), then your locals, then your function saved state and return address, then parameters to `printf` (maybe, not sure if it's `cdecl` or `fastcall`), then `printf`'s locals by the time anything actually makes it to the screen.

Problem

Given stack pointer value, is it possible to determine the value of the passed arguments to the function? Where are the arguments stored in the stack frame. Lets say, executing `gcc` compiled ELF binary on `x86` architecture on Linux platform: ``` int foo(int a, int b) { ... } ``` `foo(a,b)` is called from `main()` and I know the stack pointer(SP) value which is pointing to `foo()` now. How can I retrive the value of arguments `a` and `b`? EDIT: If stack grows from smaller address to larger address, and arguments are passed right to left using `cdecl`, can I obtain args value like this: ``` b = *(SP + 1); a = *(SP + 2); ``` EDIT: The following program prints the value of functions args `a`, `b` using above arch and specifications. ``` void foo(int a, int b) { int i; register int stackptr asm("sp"); int *sp = (int *)stackptr; printf("\n\ta=%d b=%d\n", a, b); for (i=0; i<16; i++) { printf("*(sp + %d) = %d\n", i, *(sp +i)); } } int main() { foo(3, 8); foo(9, 2); foo(1, 4); return 0; } ``` The output of above code is: ``` a=3 b=8 *(sp + 0) = 134514016 *(sp + 1) = 0 *(sp + 2) = 0 *(sp + 3) = 134513373 *(sp + 4) = 8239384 *(sp + 5) = 134513228 *(sp + 6) = 6 *(sp + 7) = -1076716032 *(sp + 8) = 134513456 *(sp + 9) = 0 *(sp + 10) = -1076715960 *(sp + 11) = 134513759 *(sp + 12) = 3 //value of arg a *(sp + 13) = 8 //value of arg b *(sp + 14) = 134513817 *(sp + 15) = 10612724 a=9 b=2 *(sp + 0) = 134514016 *(sp + 1) = 0 *(sp + 2) = 0 *(sp + 3) = 134513373 *(sp + 4) = 8239384 *(sp + 5) = 134513228 *(sp + 6) = 6 *(sp + 7) = -1076716032 *(sp + 8) = 134513456 *(sp + 9) = 0 *(sp + 10) = -1076715960 *(sp + 11) = 134513779 *(sp + 12) = 9 //value of arg a *(sp + 13) = 2 //value of arg b *(sp + 14) = 134513817 *(sp + 15) = 10612724 a=1 b=4 *(sp + 0) = 134514016 *(sp + 1) = 0 *(sp + 2) = 0 *(sp + 3) = 134513373 *(sp + 4) = 8239384 *(sp + 5) = 134513228 *(sp + 6) = 6 *(sp + 7) = -1076716032 *(sp + 8) = 134513456 *(sp + 9) = 0 *(sp + 10) = -1076715960 *(sp + 11) = 134513799 *(sp + 12) = 1 //value of arg a *(sp + 13) = 4 //value of arg b *(sp + 14) = 134513817 *(sp + 15) = 10612724 ``` Why function arguments are stored from offset 12 of SP? Also notice values at offset 0 to 10 are always same, and value at offset 11 increases by 20 on each invocation of function `foo()`. UPDATE: I found that `gcc` has in-build function to retrieve frame pointer address ``` void * __builtin_frame_address (unsigned int level) ``` When I print values at offsets starting from `__builtin_frame_address(0)` the function arguments start from `offset 2`. How can I confirm that this behavior is always consistent?

Original source