|
From: Nicholas N. <nj...@ca...> - 2003-11-19 15:48:27
|
On Wed, 19 Nov 2003, Josef Weidendorfer wrote:
> just looked at this strange piece of code.
> Now I know why Intel refuses to support nested functions in their
> compilers ;-)
>
> When GCC-compiled code needs a function pointer for a nested function, it
> seems to produce dynamically some trampoline code on the stack, and uses the
> start address of this piece of code as the function pointer (don't ask me
> why).
>
> Note that the function pointer for the nested function will point to the same
> address of dynamically produced code. Valgrind's instrumentation engine
> doesn't detect that the code on stack is changed inbetween, and uses
> the same instrumented version both times.
>
> The code works as expected if you change call_func() this way:
> =============================================
> #include <valgrind/valgrind.h>
> ...
> static void call_func(void (*sel)(void))
> {
> sel();
> VALGRIND_DISCARD_TRANSLATIONS(sel,20);
> }
> =============================================
Yes. Or, if the code is changed a bit so that the on-stack code doesn't
happen to be at the same address.
> Note that VG would be quite slow if it had to check if a write instruction
> is about to change already instrumented code (Wasn't this the
> case in the first days of VG?).
Alternatively, one could invalidate any code on the stack when it shrinks,
but that would hurt performance too.
The support for self-modifying code was removed because, IIRC, it was
clunky and rarely needed, and the VALGRIND_DISCARD_TRANSLATIONS macro was
good enough for eg. JIT-compilers and other programs that generate code at
runtime.
But if runtime code-generation occurs and the user doesn't even realise
it, that's bad.
Hmm.
N
|