Watching reads/writes on optimized variables?

Hi guys,

I'm trying to use watchpoints to detect user-space reads/writes of an
arbitrary C/C++ program variable.

For example:
   void foo() {
      int x; // <-- I'm interested in 'x'
      x = 10; // <-- I want to detect this

      for (int i = 0; i < 4; ++i) {
         x = i; // <-- And this
         bar(x);
      }

      x = 20; // <-- and this
      bar(x);
      baz( &x ); // <-- and any updates to 'x' during this call
   }

My concern is that the clang+LLVM will sometimes model "x" using a
register or constant, rather than with memory. And so a watchpoint
might miss some reads/writes to "x".

Does anyone know of a way to minimize or eliminate this problem?

Ideas I've considered so far:

* Compiling the whole program with "-O0". This might be enough, but
I'm not sure.

* Add the "volatile" qualifier to "x". This might solve the problem,
but could require countless additions of "volatile" elsewhere as well.

* Adding a statement of the form "my_dummy_func( &x )". Assuming this
reliably causes a memory allocation for "x", this might help. But I
wouldn't expect it to reliably preclude "x"'s value from being modeled
with a register or constant at certain locations in the object code.

I don't mind modifying compiler/linker flags, but I'd prefer to not
modify the source code. I should be able to use most versions of GCC
and/or Clang/LLVM/LLDB.

Thanks,
Christian

Hi guys,

I'm trying to use watchpoints to detect user-space reads/writes of an
arbitrary C/C++ program variable.

For example:
  void foo() {
     int x; // <-- I'm interested in 'x'
     x = 10; // <-- I want to detect this

     for (int i = 0; i < 4; ++i) {
        x = i; // <-- And this
        bar(x);
     }

     x = 20; // <-- and this
     bar(x);
     baz( &x ); // <-- and any updates to 'x' during this call
  }

My concern is that the clang+LLVM will sometimes model "x" using a
register or constant, rather than with memory. And so a watchpoint
might miss some reads/writes to "x".

Does anyone know of a way to minimize or eliminate this problem?

Just take the address of your variable at some point in your code and it will force it into memory.

Hi Greg,

Does anyone know of a way to minimize or eliminate this problem?

Just take the address of your variable at some point in your code and it will force it into memory.

Thanks for your idea. I can see why taking the variable's address (in
an expression that's not optimized away) would prompt llvm to allocate
genuine stack space for it.

However, I'm still concerned about the following scenario:

   int foo() {
      int x;
      dummy_func(&x); // <-- your idea, AFAICT
      x = 10;
      f(x);
      x = 20;
      g(x);
      return x;
   }

I suspect it's still possible that the optimizer will (conceptually) replace:
      x = 10;
      f(x);
      x = 20;
      g(x);
      return x;
with:
      f(10);
      f(20);
      return 20;

It's pretty important to me that at debug-time I detect the fact that
"X=10" and "X=20" (conceptually) were executed and modified the value
of "x". (Whatever approach I use also needs to detect access to "x"
which occur via aliasing.)

- Christian

Maybe the volatile keyword?

volatile int x = 10;