|
From: Bart V. A. <bar...@gm...> - 2006-12-31 18:14:33
|
Valgrind's core has the nice feature that dynamic memory allocation calls
can be easily intercepted (via VG_(needs_malloc_replacement)(...)). But is
it normal that via this mechanism malloc() calls performed by /lib/ld-
linux.so are not intercepted ?
Consider the following program:
#include <iostream>
#include <mcheck.h>
#include <pthread.h>
static void init() __attribute__((constructor));
static void init()
{
putenv("MALLOC_TRACE=new_delete-mtrace.txt");
mtrace();
}
void* thread_func(void*)
{
delete new int;
return 0;
}
int main(int argc, char** argv)
{
pthread_t tid;
std::cout << "main, before pthread_create()\n" << std::flush;
pthread_create(&tid, 0, thread_func, 0);
std::cout << "main, after pthread_create()\n" << std::flush;
delete new int;
std::cout << "main, before pthread_join()\n" << std::flush;
pthread_join(tid, 0);
std::cout << "main, after pthread_join()\n" << std::flush;
return 0;
}
This program produces the following output:
$ cat new_delete-mtrace.txt
= Start
@ /lib/ld-linux.so.2:[0xb7fe33b8] + 0x804a4b8 0x88
@ /usr/local/lib/libstdc++.so.6:(_Znwj+0x27)[0xb7f76f47] + 0x804a548 0x4
@ /usr/local/lib/libstdc++.so.6:(_ZdlPv+0x21)[0xb7f757e1] - 0x804a548
@ /usr/local/lib/libstdc++.so.6:(_Znwj+0x27)[0xb7f76f47] + 0x804a548 0x4
@ /usr/local/lib/libstdc++.so.6:(_ZdlPv+0x21)[0xb7f757e1] - 0x804a548
@ /lib/libc.so.6:(clearenv+0x7e)[0xb7da1b6e] - 0x804a008
Is it normal that Valgrind's malloc() replacement is not triggered for the
first allocation from /lib/ld-linux.so.2 ?
Bart.
|
|
From: Julian S. <js...@ac...> - 2006-12-31 19:18:47
|
> can be easily intercepted (via VG_(needs_malloc_replacement)(...)). But is > it normal that via this mechanism malloc() calls performed by /lib/ld- > linux.so are not intercepted ? Unfortunately there will be an initial section of the program for which these intercepts do not apply. The replacement functions live in drd/vgpreload_drd-<arch>-linux.so (by analogy with memcheck's ones). At startup, V loads the executable into memory - that is, maps its text and data sections, and those of its ELF interpreter, but that's all. It then starts running the ELF interpreter on the simulated CPU, and that takes care of loading/linking all the other .so's. V doesn't have any further involvement, which is nice, since ELF linking/loading is a nightmare of complexity. Except .. the preload .so's, drd/vgpreload_drd-<arch>-linux.so et al. These need to be incorporated into the memory image of the client program. V can't do that directly, so what it does is to add the name of this .so to the LD_PRELOAD env var handed to the client. This causes its dynamic linker to load in the preload. As soon as the preload is loaded (via an mmap syscall) V reads its symbol tables, notes the malloc replacements, and routes all subsequent malloc/free calls to them. But by then it may be that ld.so has already called malloc/free. I think that explains what you are seeing. I hope that makes sense. Loading the executable and getting started is one of the most hairy parts of the system. Does the lack of intercepts right from the start cause a problem for drd? J |
|
From: Bart V. A. <bar...@gm...> - 2007-01-01 09:53:50
|
On 12/31/06, Julian Seward <js...@ac...> wrote: > > > > can be easily intercepted (via VG_(needs_malloc_replacement)(...)). But > is > > it normal that via this mechanism malloc() calls performed by /lib/ld- > > linux.so are not intercepted ? > > Unfortunately there will be an initial section of the program for which > these intercepts do not apply. > > The replacement functions live in drd/vgpreload_drd-<arch>-linux.so > (by analogy with memcheck's ones). > > At startup, V loads the executable into memory - that is, maps its text > and data sections, and those of its ELF interpreter, but that's all. It > then starts running the ELF interpreter on the simulated CPU, and that > takes > care of loading/linking all the other .so's. V doesn't have any further > involvement, which is nice, since ELF linking/loading is a nightmare of > complexity. > > Except .. the preload .so's, drd/vgpreload_drd-<arch>-linux.so et al. > These need to be incorporated into the memory image of the client > program. V can't do that directly, so what it does is to add the name > of this .so to the LD_PRELOAD env var handed to the client. This causes > its dynamic linker to load in the preload. > > As soon as the preload is loaded (via an mmap syscall) V reads its symbol > tables, notes the malloc replacements, and routes all subsequent > malloc/free > calls to them. But by then it may be that ld.so has already called > malloc/free. > > I think that explains what you are seeing. I hope that makes sense. > Loading the executable and getting started is one of the most hairy > parts of the system. > > Does the lack of intercepts right from the start cause a problem for drd? > > J > This does not cause a real problem for the drd tool. The drd tool tries to print the allocation context every time a conflicting access is detected, and I noticed that frequently the drd tool was unable to find the allocation context. That is why I compared the output triggered by mtrace() with tracing output added in the malloc wrappers. After that I found out that the conflicting accesses were related to the PLT /GOT mechanism, and not to malloc() calls performed from within ld-linux.so. Bart. |