问题
following short c program:
void foo(int a, int b) {
printf("a = %p b = %p\n", &a, &b);
}
main() {
foo(1, 2);
}
ok, now I used gdb to view this program. I got as output:
a = 0x7fff5fbff9ac b = 0x7fff5fbff9a8
and stopped execution after the output (in foo()). now I examined 0x7fff5fbff9ac and the content was:
1....correct
then 0x7fff5fbff9a8 and the content:
2...correct
now I wanted to view the return address of the function and examined (a + 4 bytes) with:
x/g 0x7fff5fbff9b1 (8 bytes!! address, therefore "g" (giant word))
and its content was:
(gdb) x/g 0x7fff5fbff9b1
0x7fff5fbff9b1: 0xd700007fff5fbff9
BUT: THIS IS NOT THE RETURN ADR FROM MAIN! where is my fault?
回答1:
There are a whole bunch of faulty assumptions in your question.
You're assuming that integer arguments are passed on the stack immediately above the return address (as they are in many--not all--x86 ABIs under the default calling conventions). If this were the case, then immediately following the call, your stack would look like this:
// stack frame of main( )
// ...
value of b
value of a
return address <--- stack pointer
However, your assumption is incorrect. You have compiled your code into a 64-bit executable (as evidenced by the size of the pointer you are printing). Per the OS X ABI, in a 64-bit Intel executable, the first few integer arguments are passed in register, not on the stack. Thus, immediately following the call, the stack actually looks like this:
// stack frame of main( )
// ...
return address <--- stack pointer
Since you take the address of a
and b
, they will be written to the stack at some point before the call to printf( )
(unless the compiler is really clever, and realizes that it doesn't actually need to hand printf( )
valid pointers because it won't use the value pointed to, but that would be pretty evil as optimizations go), but you really don't know where they will be relative to the return address; in fact, because the 64-bit ABI provides a red zone, you don't even know whether they're above or below the stack pointer. Thus, at the time that you print out the address of a and b, your stack looks like this:
// stack frame of main( )
// ...
return address |
// ... |
// a and b are somewhere down here | <-- stack pointer points somewhere in here
// ... |
In general, the C language standard says nothing about stack layouts, or even that there needs to be a stack at all. You cannot get this sort of information in any portable fashion from C code.
回答2:
Firstly, &a + 4
is 0x7FFF5FBFF9B0
, so you are looking one byte offset from where you think you are.
Secondly, the saved frame pointer lies between a
and the return address, and this is the value you are seeing.
回答3:
What you are doing wrong is making a whole bunch of incorrect and random assumptions about the layout of the stack frame on your given platform. Where did you get that weird idea about "a + 4
bytes" location supposedly holding the return address?
If you really want to do this, get the documentation for your platform (or do some reverse engineering) to find out where and how exactly the return address is stored. Making random guesses and then asking other people why your random guesses do not produce results you for some reason expect is not exactly a productive way to do it.
来源:https://stackoverflow.com/questions/4390659/c-return-address-of-function-mac