The GNU return address documentation states that __builtin_return_address(1)
yields the return address of the caller of the current function.
Could someone expand on what this description means? After doing some testing, I realized it doesn't seem to be doing what I expect it to do (so I may not be understanding it correctly).
For example, I made the following very simple test code to further understand how this function work (as well as the others):
#include <stdio.h>
#include <stdint.h>
void foo(uint64_t x, uint64_t y){
void *ptr = __builtin_extract_return_addr(__builtin_return_address(0));
void *ptr2 = __builtin_extract_return_addr(__builtin_return_address(1));
printf("ret_addr(0)=%p\nret_addr(1)=%p\n", ptr, ptr2);
return;
}
int main(int argc, char **argv)
{
foo(1,1);
foo(1,1);
}
Disassembled code (for reference)
0000000000400536 <main>:
400536: 55 push %rbp
------- skipped -------
40054f: e8 93 ff ff ff callq 4004e7 <foo>
400554: be 01 00 00 00 mov $0x1,%esi
------- skipped -------
40055e: e8 84 ff ff ff callq 4004e7 <foo>
400563: b8 00 00 00 00 mov $0x0,%eax
------- skipped -------
Upon executing this code, the following is outputted:
ret_addr(0)=0x400554
ret_addr(1)=0x7f609c67cb97
ret_addr(0)=0x400563
ret_addr(1)=0x7f609c67cb97
So from this, I was a bit confused and wanted to ask for clarification.
I can see that __builtin_return_address(0) [ret_addr(0)]
works fine as it returns the correct return address value of 0x400554 and 0x400563.
However, for __bulitin_return_address(1) [ret_addr(1)]
, shouldn't the returned value be 0x40054f and 0x40055e? because those two addresses are the callq 4004e7 <foo>
instruction as shown in the disassembled code (and this is what I am understanding from the description).
Instead, I get some garbage value of 0x7f609c67cb97, and this value is the same for both foo functions, which even for garbage value, I would expect both to be different.
So to summarize, what is the purpose of __builtin_return_address(1)
function? Is it supposed to return the exact address of the caller of the current function? (rather than simply finding the return address). If not, is it possible to find such an address? (I am thinking this may be a bit too difficult)
I believe my question is sort of similar to this: Getting the caller's Return Address.