|
From: Jeremy F. <je...@go...> - 2004-02-29 23:14:44
|
On Sat, 2004-02-28 at 12:54, Robert Walsh wrote:
> > Any other show-stoppers?
>
> If your code overrides operator new(), then 73655 is going to bite you.
> I don't know how common this is, but it's definitely stopping us from
> using Valgrind on our compiler at the moment.
>
> I think I know how to fix this - I just haven't sat down and thought it
> through yet. Drop me an email if you want to hear to gory details.
The bug is that Valgrind shouldn't be going around overriding symbols
any old place - it should be overriding them in specific libraries. The
new symbol intercept mechanism is careful to specify the intercepts in
terms of library/symbol, so that this is the case.
In this mechanism is the intercepts are provided by the library through
various client calls (for example, the init function in
vg_preloadmemcheck.so says "I override malloc!", etc). This keeps
things nice and modular, since the library which does the override tells
Valgrind about it itself, without having to scatter the knowledge
around.
The problem is that it relies on the init functions being run really
early - before any other code is run. It is *not* OK to use glibc
malloc for a while, and then intercept it with the Valgrind malloc -
things will get very confused.
So the quick fix is to make the intercept functions also globally
visible to the linker, so ld.so's override machinery can see it. This
happens early enough, but it causes unintended functions to be
overridden - in this case, operator new().
The correct fix needs to have two properties to be really satisfying:
1. the libraries containing intercepts must be self-describing, so
that there's no external knowledge of what functions they want
to intercept
2. it needs to take effect as soon as the library is mapped in,
before any code is run
The current code satisfies 1, but not 2.
I tried an experiment with adding a special valgrind-specific section to
intercept-containing .so files (.valgrind.intercept), which contains the
library and symbol name of the intercepted function, and the pointer to
the intercepting function. The idea is that when we see the client map
in a file which we identify as an ELF .so file, we check for a
.valgrind.intercept section, and set up the intercepts so described.
This problem with this scheme is that it is complex and ELF-specific.
The complexity comes from the fact that we need to interpret relocation
information to understand the string references in the
.valgrind.intercept section. Also, since an ELF file is mapped in with
several mmap calls, we need to delay evaluation until all the relevent
mmaps have been performed (normally this isn't an issue, since they
symtab is entirely contained within one mmaped chunk, and needs no
relocation; in the .valgrind.intercept case, we need to inspect the data
section for the strings making up the intercept description).
I guess the alternative to self-description is having a single source
file which is compiled for Valgrind-internal use and for client use,
containing the appropriate parts for each. At least this would
centralize things into a single source file, even if it has pieces
scattered between core and client. But it still has issues about when
to trigger the registration of the intercepts.
J
|