6

I'm writing a function called at the end of a recursive chain. This function needs to figure out where it is in memory at the instance of when it's being called. The code is as follows:

void recover ()
{
     int * x = (int *)&x;
}

The problem is the program just skips over this statement as if it was never written. I've verified this in GDP. Can you think of any reason why this line is being ignored?

Thanks!

prestige13
  • 71
  • 4
  • 6
    What do you expect this statement to do? As written, the function does nothing, and this is what you see. Any half-decent compiler would optimize this whole function away. – void_ptr Nov 13 '15 at 01:48
  • `printf("Function at address: 0x%x\n", recover);` – karlphillip Nov 13 '15 at 01:50
  • Well I need this memory address so I can access it in GDP and effectively use it to backtrace the previous function calls. My end goal is to find the original arguments passed into function foo in which recover() is called – prestige13 Nov 13 '15 at 01:52
  • You can switch to assembly view and examine the registers instead, although I am not familiar with GDP capabilities. – void_ptr Nov 13 '15 at 01:55
  • What is this GDP you are talking about? Are you sure you aren't actually referring to gdb? In that case, you can just look at esp (or rsp on x86_64) to see where you are in the stack - even more simply, `bt` will show you the values of all the arguments of the callers. Also, marking the variable as `volatile` may protect it from the optimizer. But more in general, what are you trying to achieve with all this stuff? Keep in mind that dabbling with the stack is all UB. – Matteo Italia Nov 13 '15 at 01:59
  • you should probably change `recover ()` to `recover (void)`. Also, if you're just trying to figure out the address of stack, check the base pointer register (or whatever equivalent your architecture has). – Bobby Sacamano Nov 13 '15 at 02:00
  • So the only problem with looking at the machine code in gdb is that I actually need a reference point to recover's position in the stack in my recover function. Using gdb I will be able to figure out the distance of recover from each passed in argument and implement this into my code. I hope this makes sense – prestige13 Nov 13 '15 at 02:44

3 Answers3

9

Declare the variable as volatile. It should prevent compiler optimizations.

volatile int * x = (int *)&x;
nnn
  • 3,980
  • 1
  • 13
  • 17
6

If you are compiling with optimization turned on, then this code is probably optimized out due to no effect on the program. Use -O0 option.

ysap
  • 7,723
  • 7
  • 59
  • 122
4

The code you wrote is probably undefined behavior since you're casting a pointer to a pointer to an int to a pointer to an int.

A pointer can't conceptually point to itself since you would never be able to achieve the right level of indirection. Here's why:

Declaration      |  Type     | Type after using the & operator
--------------------------------------------------------------
int   x;         |  int      | &x is an (int*)
int*  x;         |  int *    | &x is an (int**)
int** x;         |  int **   | &x is an (int***)

However, a void* is the only type of pointer I can think of that might be allowed to break this rule, but I'm not sure if it would be legal according to the standard.

I would propose you write the following instead of what you have:

int* recover ()
{
    int local = 0;
    return &local;
}

And compile it with no optimizations like @ysap suggests.

Still from your example it seems like you're trying to figure out where the top of the stack is and that is very easily done in assembly. All you need to do is read the stack pointer. However, this isn't so cleanly exposed in C. Though GCC does have some helper functions for similar tasks I haven't found one for the stack pointer.

I would personally resort to inline assembly since whatever is written will probably not be portable anyway.

Additionally, if I'm understanding your question right it is most likely a duplicate of this question so it would pay to read those answers as well.

Edit: It should be equivalent to return the address of the frame of the current function which can be done by using a GCC builtin function __builtin_frame_address (unsigned int level) linked earlier. The code would look like this:

int* recover()
{
    return (int*)__builtin_frame_address(0);
}
Community
  • 1
  • 1
nonsensickle
  • 4,438
  • 2
  • 34
  • 61