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?