I try to achieve the following: I'm having a pointer p
pointing to an address holding again an address (this address is also a valid address). Now I want to have another pointer pp
pointing to the address which is the content of p
. So I'm doing the following:
// Retrieve the start address
unsigned long long *p = getInitialAddress();
// Let pp point to next address
unsigned long long *pp = (unsigned long long*)(*p);
// Print address
printf("0x%llx %p\n", *p, pp);
This prints for example: 0x7fffedc47a70 0x7fffedc47a70
which is the desired result.
However, putting another printf
into the code, like this:
// Retrieve the start address
unsigned long long *p = getInitialAddress();
// Print
printf("%p 0x%llx\n", p, *p);
// Let pp point to next address
unsigned long long *pp = (unsigned long long*)(*p);
// Print address
printf("0x%llx %p\n", *p, pp);
Leads to:
0x7fffacea3660 0x7fffacea3680
0x0 (nil)
And this is not the correct result, because it should be
0x7fffacea3660 0x7fffacea3680
0x7fffacea3680 0x7fffacea3680
So does the printf
alter something within the pointers or what is wrong?
Edit: Complete code
unsigned long long* readRBP();
int main(void) {
// Retrieve the start address
unsigned long long *p = readRBP();
// Print
printf("%p 0x%llx\n", p, *p);
// Let pp point to next address
unsigned long long *pp = (unsigned long long*)(*p);
// Print address
printf("0x%llx %p\n", *p, pp);
return 0;
}
unsigned long long* readRBP() {
unsigned long long rbp;
__asm__ volatile("mov %%rbp, $0" : "=r"(rbp));
return (unsigned long long*)rbp;
}
This gets the rbp (Stack base pointer). The content of this pointer is the pointer to the next rbp and so on. This rbp is from readRBP()
itself, the next rbp belongs to main
and the next one after main is 0x0
, i. e. the very beginning.
The value that readRBP
returns is the base pointer for the readRBP
function. You then call printf
which creates its own stack frame. And that stack frame obliterates the data at *p
.
To see that this is so you can write your code this way round:
int main(void) {
// Retrieve the start address
unsigned long long *p = readRBP();
unsigned long long pContents = *p
unsigned long long *pp = (unsigned long long*)(*p);
// Print
printf("%p 0x%llx %p\n", p, pContents, pp);
return 0;
}
In other words you gather up all the information into the stack frame of main
, before you stomp on it by calling printf
.