|
From: Bart V. A. <bar...@gm...> - 2006-12-29 09:45:41
|
Does anyone know where I can find comprehensive documentation of how ELF
shared library symbols are resolved at runtime ? When running drd on C++
programs drd reports data races on calls to a.o. 'operator new(unsigned)'
(_Znwj) and 'operator delete(void*)' (_ZdlPv). After having traced all
accesses to the memory location on which the data race occurred
(0x08049874), it turned out that the race is caused by the dynamic loader. I
don't think I can suppress this race using Valgrind's suppression mechanism
because the race is reported before the _dl* function names appear in the
call stack. If I understand more about dynamic loading, maybe I can find out
the address of the conflicting location before the _dl* functions are
called.
Bart.
$ cat new_delete.cpp
#include <pthread.h>
void* thread_func(void*)
{
delete new int;
return 0;
}
int main(int argc, char** argv)
{
pthread_t tid;
pthread_create(&tid, 0, thread_func, 0);
delete new int;
pthread_join(tid, 0);
return 0;
}
$ VALGRIND_LIB=.in_place coregrind/valgrind --suppressions=drd/default.supp
--tool=drd --trace-address=134518912 drd/tests/new_delete
==22662== drd, a data race detector.
==22662== Copyright (C) 2006, and GNU GPL'd, by Bart Van Assche.
THIS SOFTWARE IS A PROTOTYPE, AND IS NOT YET RELEASED
==22662== Using LibVEX rev 1680, a library for dynamic binary translation.
==22662== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==22662== Using valgrind-3.3.0.SVN, a dynamic binary instrumentation
framework.
==22662== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==22662== For more details, rerun with: -v
==22662==
==22662== load 0x8049880 size 4 thread 1
==22662== at 0x400A613: _dl_relocate_object (in /lib/ld-2.4.so)
==22662== by 0x4004777: dl_main (in /lib/ld-2.4.so)
==22662== by 0x40131CA: _dl_sysdep_start (in /lib/ld-2.4.so)
==22662== by 0x40011F3: _dl_start (in /lib/ld-2.4.so)
==22662== by 0x4000846: (within /lib/ld-2.4.so)
==22662== store 0x8049880 size 4 thread 1
==22662== at 0x400A613: _dl_relocate_object (in /lib/ld-2.4.so)
==22662== by 0x4004777: dl_main (in /lib/ld-2.4.so)
==22662== by 0x40131CA: _dl_sysdep_start (in /lib/ld-2.4.so)
==22662== by 0x40011F3: _dl_start (in /lib/ld-2.4.so)
==22662== by 0x4000846: (within /lib/ld-2.4.so)
==22662== load 0x8049880 size 4 thread 2
==22662== at 0x80484B8: (within
/home/bart/software/valgrind-svn/drd/tests/new_delete)
==22662== by 0x4022E2C: vg_thread_wrapper (drd_preloaded.c:133)
==22662== by 0x404434A: start_thread (in /lib/libpthread-2.4.so)
==22662== by 0x421C65D: clone (in /lib/libc-2.4.so)
==22662== store 0x8049880 size 4 thread 2
==22662== at 0x400D274: _dl_fixup (in /lib/ld-2.4.so)
==22662== by 0x401262F: _dl_runtime_resolve (in /lib/ld-2.4.so)
==22662== by 0x4022E2C: vg_thread_wrapper (drd_preloaded.c:133)
==22662== by 0x404434A: start_thread (in /lib/libpthread-2.4.so)
==22662== by 0x421C65D: clone (in /lib/libc-2.4.so)
==22662== Conflicting load by thread 1 at 0x08049874 size 4
==22662== at 0x8048488: (within
/home/bart/software/valgrind-svn/drd/tests/new_delete)
==22662== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==22662== Allocation context: drd/tests/new_delete, NONE:Data
==22662== Other segment start (thread 2)
==22662== (thread finished, call stack no longer available)
==22662== Other segment end (thread 2)
==22662== (thread finished, call stack no longer available)
==22662== load 0x8049880 size 4 thread 1
==22662== at 0x80484B8: (within
/home/bart/software/valgrind-svn/drd/tests/new_delete)
==22662== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==22662==
==22662== Conflicting load by thread 1 at 0x08049880 size 4
==22662== at 0x80484B8: (within
/home/bart/software/valgrind-svn/drd/tests/new_delete)
==22662== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==22662== Allocation context: drd/tests/new_delete, NONE:Data
==22662== Other segment start (thread 2)
==22662== (thread finished, call stack no longer available)
==22662== Other segment end (thread 2)
==22662== (thread finished, call stack no longer available)
==22662==
==22662== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 3)
|
Bart Van Assche wrote: > Does anyone know where I can find comprehensive documentation of how ELF > shared library symbols are resolved at runtime ? The source code to glibc may well be the only place that is detailed enough to answer questions that are necessary to resolve issues regarding races. The ELF section of http://people.redhat.com/drepper/ points to some papers that may help. When running drd on C++ > programs drd reports data races on calls to a.o. 'operator new(unsigned)' > (_Znwj) and 'operator delete(void*)' (_ZdlPv). After having traced all > accesses to the memory location on which the data race occurred > (0x08049874), it turned out that the race is caused by the dynamic > loader. In some of my own code dynamic linking code I have knowingly allowed controlled races between processors [threads], and between instruction and data caches of the same processor. The end result is the same (a value in memory changes only from A to B); the race affects only the time required by any one thread and the propagation delay of visibility by other threads. Threads which "lose" the race also store the same value B into the location which originally contained A. The number of races is limited to the product of the number of processors [threads] and the number of symbol resolutions. In each case the time penalty due to the race is bounded [loop-free code], the "window of opportunity" is bounded by system context switching, and the probability of anything other than the fastest outcome is not large. By contrast, the penalty in time and space and complexity for a race-free algorithm [any mutual exclusion at all] is large. dlclose() might interfere, but only because the same logical race is already present independent of the algorithm used for symbol resolution. Calling dlclose() while any other thread could begin a dynamic resolution [that might be affected by the dlclose()] is itself a [logical] race. -- |
|
From: Julian S. <js...@ac...> - 2006-12-29 19:21:25
|
On Friday 29 December 2006 09:45, Bart Van Assche wrote:
> Does anyone know where I can find comprehensive documentation of how ELF
> shared library symbols are resolved at runtime ? When running drd on C++
> programs drd reports data races on calls to a.o. 'operator new(unsigned)'
> (_Znwj) and 'operator delete(void*)' (_ZdlPv). After having traced all
> accesses to the memory location on which the data race occurred
> (0x08049874), it turned out that the race is caused by the dynamic loader.
> I don't think I can suppress this race using Valgrind's suppression
> mechanism because the race is reported before the _dl* function names
> appear in the call stack.
You can't even really assume that you will ever get the _dl* function names;
some distros are very aggressive in stripping every possible name out of
ld.so and glibc.so for that matter.
One way out of this is to use sonames (shared object "names") in the
suppressions, rather than function names. It's crude but it works.
Here's an example:
{
Fedora-Core-5-hack2a
Memcheck:Cond
obj:/lib*/ld-2.4*so
obj:/lib*/ld-2.4*so
obj:/lib*/ld-2.4*so
obj:/lib*/ld-2.4*so
}
All .so's should have a soname, but it isn't the file name. To find the
soname for "foo.so" do readelf -a foo.so | grep soname.
Sounds like you have done considerable work since the 13 Dec drd snapshot?
Will you make a new patch soon?
J
|
|
From: Josef W. <Jos...@gm...> - 2006-12-29 20:12:18
|
On Friday 29 December 2006 10:45, Bart Van Assche wrote: > ==22662== load 0x8049880 size 4 thread 1 > ==22662== at 0x400A613: _dl_relocate_object (in /lib/ld-2.4.so) > ==22662== by 0x4004777: dl_main (in /lib/ld-2.4.so) > ==22662== by 0x40131CA: _dl_sysdep_start (in /lib/ld-2.4.so) > ==22662== by 0x40011F3: _dl_start (in /lib/ld-2.4.so) > ==22662== by 0x4000846: (within /lib/ld-2.4.so) > ==22662== store 0x8049880 size 4 thread 1 > ==22662== at 0x400A613: _dl_relocate_object (in /lib/ld-2.4.so) > ==22662== by 0x4004777: dl_main (in /lib/ld-2.4.so) > ==22662== by 0x40131CA: _dl_sysdep_start (in /lib/ld-2.4.so) > ==22662== by 0x40011F3: _dl_start (in /lib/ld-2.4.so) > ==22662== by 0x4000846: (within /lib/ld-2.4.so) > ==22662== load 0x8049880 size 4 thread 2 > ==22662== at 0x80484B8: (within > /home/bart/software/valgrind-svn/drd/tests/new_delete) > ==22662== by 0x4022E2C: vg_thread_wrapper (drd_preloaded.c:133) > ==22662== by 0x404434A: start_thread (in /lib/libpthread-2.4.so) > ==22662== by 0x421C65D: clone (in /lib/libc-2.4.so) > ==22662== store 0x8049880 size 4 thread 2 > ==22662== at 0x400D274: _dl_fixup (in /lib/ld-2.4.so) > ==22662== by 0x401262F: _dl_runtime_resolve (in /lib/ld-2.4.so) > ==22662== by 0x4022E2C: vg_thread_wrapper (drd_preloaded.c:133) > ==22662== by 0x404434A: start_thread (in /lib/libpthread-2.4.so) > ==22662== by 0x421C65D: clone (in /lib/libc-2.4.so) Why is this a race at all? The accesses in thread 1 are before main() is called, and only there is the 2nd thread created, which does the other accesses. Josef |
|
From: Bart V. A. <bar...@gm...> - 2006-12-31 09:48:21
|
On 12/29/06, Josef Weidendorfer <Jos...@gm...> wrote:
>
> Why is this a race at all?
> The accesses in thread 1 are before main() is called, and only there
> is the 2nd thread created, which does the other accesses.
>
> Josef
>
I don't know why, but some of the call stacks printed by Valgrind's core are
wrong. The load reported by drd as conflicting happened after
pthread_create(), not before main(). This is made clear by some tracing I
added to the test program:
$ cat drd/tests/new_delete.cpp
#include <iostream>
#include <pthread.h>
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;
}
$ VALGRIND_LIB=.in_place coregrind/valgrind --tool=drd
--trace-address=$((0x08049BE4)) drd/tests/new_delete
==5994== drd, a data race detector.
==5994== Copyright (C) 2006, and GNU GPL'd, by Bart Van Assche.
THIS SOFTWARE IS A PROTOTYPE, AND IS NOT YET RELEASED
==5994== Using LibVEX rev 1680, a library for dynamic binary translation.
==5994== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==5994== Using valgrind-3.3.0.SVN, a dynamic binary instrumentation
framework.
==5994== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==5994== For more details, rerun with: -v
==5994==
==5994== load 0x8049BE4 size 4 thread 1
==5994== at 0x400A613: _dl_relocate_object (in /lib/ld-2.4.so)
==5994== by 0x4004777: dl_main (in /lib/ld-2.4.so)
==5994== by 0x40131CA: _dl_sysdep_start (in /lib/ld-2.4.so)
==5994== by 0x40011F3: _dl_start (in /lib/ld-2.4.so)
==5994== by 0x4000846: (within /lib/ld-2.4.so)
==5994== store 0x8049BE4 size 4 thread 1
==5994== at 0x400A613: _dl_relocate_object (in /lib/ld-2.4.so)
==5994== by 0x4004777: dl_main (in /lib/ld-2.4.so)
==5994== by 0x40131CA: _dl_sysdep_start (in /lib/ld-2.4.so)
==5994== by 0x40011F3: _dl_start (in /lib/ld-2.4.so)
==5994== by 0x4000846: (within /lib/ld-2.4.so)
main, before pthread_create()
==5994== load 0x8049BE4 size 4 thread 2
==5994== at 0x8048654: (within
/home/bart/software/valgrind-svn/drd/tests/new_delete)
==5994== by 0x4022E1C: vg_thread_wrapper (drd_preloaded.c:133)
==5994== by 0x404434A: start_thread (in /lib/libpthread-2.4.so)
==5994== by 0x421C65D: clone (in /lib/libc-2.4.so)
==5994== store 0x8049BE4 size 4 thread 2
==5994== at 0x400D274: _dl_fixup (in /lib/ld-2.4.so)
==5994== by 0x401262F: _dl_runtime_resolve (in /lib/ld-2.4.so)
==5994== by 0x4022E1C: vg_thread_wrapper (drd_preloaded.c:133)
==5994== by 0x404434A: start_thread (in /lib/libpthread-2.4.so)
==5994== by 0x421C65D: clone (in /lib/libc-2.4.so)
main, after pthread_create()
==5994== load 0x8049BE4 size 4 thread 1
==5994== at 0x8048654: (within
/home/bart/software/valgrind-svn/drd/tests/new_delete)
==5994== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==5994== Conflicting load by thread 1 at 0x08049BE4 size 4
==5994== at 0x8048654: (within
/home/bart/software/valgrind-svn/drd/tests/new_delete)
==5994== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==5994== Allocation context: drd/tests/new_delete, NONE:Data
==5994== Other segment start (thread 2)
==5994== (thread finished, call stack no longer available)
==5994== Other segment end (thread 2)
==5994== (thread finished, call stack no longer available)
==5994==
==5994== Conflicting load by thread 1 at 0x08049BF0 size 4
==5994== at 0x8048684: (within
/home/bart/software/valgrind-svn/drd/tests/new_delete)
==5994== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==5994== Allocation context: drd/tests/new_delete, NONE:Data
==5994== Other segment start (thread 2)
==5994== (thread finished, call stack no longer available)
==5994== Other segment end (thread 2)
==5994== (thread finished, call stack no longer available)
main, before pthread_join()
==5994==
==5994== Conflicting load by thread 1 at 0x0401B310 size 4
==5994== at 0x40094E8: _dl_lookup_symbol_x (in /lib/ld-2.4.so)
==5994== by 0x400D24C: _dl_fixup (in /lib/ld-2.4.so)
==5994== by 0x401262F: _dl_runtime_resolve (in /lib/ld-2.4.so)
==5994== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==5994== Allocation context: _rtld_local (offset 752, size 1524) in /lib/ld-
2.4.so, ld-linux.so.2:Data
==5994== Other segment start (thread 2)
==5994== (thread finished, call stack no longer available)
==5994== Other segment end (thread 2)
==5994== (thread finished, call stack no longer available)
==5994==
==5994== Conflicting store by thread 1 at 0x0401B310 size 4
==5994== at 0x40094E8: _dl_lookup_symbol_x (in /lib/ld-2.4.so)
==5994== by 0x400D24C: _dl_fixup (in /lib/ld-2.4.so)
==5994== by 0x401262F: _dl_runtime_resolve (in /lib/ld-2.4.so)
==5994== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==5994== Allocation context: _rtld_local (offset 752, size 1524) in /lib/ld-
2.4.so, ld-linux.so.2:Data
==5994== Other segment start (thread 2)
==5994== (thread finished, call stack no longer available)
==5994== Other segment end (thread 2)
==5994== (thread finished, call stack no longer available)
==5994==
==5994== Conflicting store by thread 1 at 0x0401E4AD size 1
==5994== at 0x40096D9: _dl_lookup_symbol_x (in /lib/ld-2.4.so)
==5994== by 0x400D24C: _dl_fixup (in /lib/ld-2.4.so)
==5994== by 0x401262F: _dl_runtime_resolve (in /lib/ld-2.4.so)
==5994== by 0x417487B: (below main) (in /lib/libc-2.4.so)
==5994== Allocation context: heap
==5994== Other segment start (thread 2)
==5994== (thread finished, call stack no longer available)
==5994== Other segment end (thread 2)
==5994== (thread finished, call stack no longer available)
==5994==
==5994== Conflicting store by thread 1 at 0x04A81D9C size 4
==5994== at 0x40455ED: pthread_join (in /lib/libpthread-2.4.so)
==5994== by 0x4021F6E: pthread_join (drd_preloaded.c:220)
==5994== by 0x80488AE: main (new_delete.cpp:18)
==5994== Allocation context: stack of thread 2, offset -612
==5994== Other segment start (thread 2)
==5994== (thread finished, call stack no longer available)
==5994== Other segment end (thread 2)
==5994== (thread finished, call stack no longer available)
==5994==
==5994== Conflicting load by thread 1 at 0x04A81C04 size 4
==5994== at 0x40442A8: __free_tcb (in /lib/libpthread-2.4.so)
==5994== by 0x4045670: pthread_join (in /lib/libpthread-2.4.so)
==5994== by 0x4021F6E: pthread_join (drd_preloaded.c:220)
==5994== by 0x80488AE: main (new_delete.cpp:18)
==5994== Allocation context: stack of thread 2, offset -1020
==5994== Other segment start (thread 2)
==5994== (thread finished, call stack no longer available)
==5994== Other segment end (thread 2)
==5994== (thread finished, call stack no longer available)
==5994==
==5994== Conflicting store by thread 1 at 0x04A81C04 size 4
==5994== at 0x40442A8: __free_tcb (in /lib/libpthread-2.4.so)
==5994== by 0x4045670: pthread_join (in /lib/libpthread-2.4.so)
==5994== by 0x4021F6E: pthread_join (drd_preloaded.c:220)
==5994== by 0x80488AE: main (new_delete.cpp:18)
==5994== Allocation context: stack of thread 2, offset -1020
==5994== Other segment start (thread 2)
==5994== (thread finished, call stack no longer available)
==5994== Other segment end (thread 2)
==5994== (thread finished, call stack no longer available)
main, after pthread_join()
==5994==
==5994== ERROR SUMMARY: 8 errors from 8 contexts (suppressed: 0 from 0)
Bart.
|
|
From: Bart V. A. <bar...@gm...> - 2006-12-31 17:49:08
|
On 12/29/06, John Reiser <jr...@bi...> wrote: > > Bart Van Assche wrote: > > Does anyone know where I can find comprehensive documentation of how ELF > > shared library symbols are resolved at runtime ? > > The source code to glibc may well be the only place that is detailed > enough > to answer questions that are necessary to resolve issues regarding races. > The ELF section of http://people.redhat.com/drepper/ points to some > papers > that may help. > Thanks for the URL. Ulrich Drepper has a paper about DSO's (dynamic shared objects) that explains the GOT (global offset table) and the PLT (procedure linkage table). Apparently the data races that were detected and that I would like to suppress are caused by lazy relocation of symbols in shared libraries. Each time a function in a shared library is called, this happens via an indirect jump in the GOT (at least on IA-32). The first time a shared library function is called, the corresponding entry in the GOT is filled in. There is one GOT entry per shared library function, and these entries are shared over threads. Does anyone have a suggestion on how I can find out the address range of all GOT entries ? Then I can easily suppress data races triggered on the GOT. Bart. |
Bart Van Assche wrote: > There is one GOT entry per shared library function, and these entries are > shared over threads. Does anyone have a suggestion on how I can find out > the address range of all GOT entries ? Then I can easily suppress data > races triggered on the GOT. Such entries are marked with a relocation type such as R_386_JUMP_SLOT in a table described by DT_JMPREL and DT_PLTRELSZ, which can be found in a PT_DYNAMIC segment. Peruse the output from an example such as: readelf --headers --dynamic --reloc /bin/date and refer to #include <elf.h> for declarations. There can be adventure here. Both ld-linux.so and prelink may relocate various items at varying times, and in the past the conventions have changed from one release of glibc to another. -- |
|
From: Tom H. <to...@co...> - 2006-12-31 19:03:40
|
In message <e2e...@ma...>
"Bart Van Assche" <bar...@gm...> wrote:
> Thanks for the URL. Ulrich Drepper has a paper about DSO's (dynamic shared
> objects) that explains the GOT (global offset table) and the PLT (procedure
> linkage table). Apparently the data races that were detected and that I
> would like to suppress are caused by lazy relocation of symbols in shared
> libraries. Each time a function in a shared library is called, this happens
> via an indirect jump in the GOT (at least on IA-32). The first time a shared
> library function is called, the corresponding entry in the GOT is filled in.
> There is one GOT entry per shared library function, and these entries are
> shared over threads. Does anyone have a suggestion on how I can find out the
> address range of all GOT entries ? Then I can easily suppress data races
> triggered on the GOT.
You mean PLT I think, not GOT - the GOT is for global data access and
the PLT is for function calls.
The ELF reader in m_debuginfo already detects the PLT and GOT so you
would need to make it record that information somewhere I guess.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Bart V. A. <bar...@gm...> - 2007-01-01 10:05:31
|
On 12/31/06, Tom Hughes <to...@co...> wrote: > > In message <e2e...@ma...> > "Bart Van Assche" <bar...@gm...> wrote: > > > Thanks for the URL. Ulrich Drepper has a paper about DSO's (dynamic > shared > > objects) that explains the GOT (global offset table) and the PLT > (procedure > > linkage table). Apparently the data races that were detected and that I > > would like to suppress are caused by lazy relocation of symbols in > shared > > libraries. Each time a function in a shared library is called, this > happens > > via an indirect jump in the GOT (at least on IA-32). The first time a > shared > > library function is called, the corresponding entry in the GOT is filled > in. > > There is one GOT entry per shared library function, and these entries > are > > shared over threads. Does anyone have a suggestion on how I can find out > the > > address range of all GOT entries ? Then I can easily suppress data races > > triggered on the GOT. > > You mean PLT I think, not GOT - the GOT is for global data access and > the PLT is for function calls. > > The ELF reader in m_debuginfo already detects the PLT and GOT so you > would need to make it record that information somewhere I guess. > > Tom > >From the output of objdump -d: 080486e4 <_Znwj@plt>: 80486e4: ff 25 00 9d 04 08 jmp *0x8049d00 80486ea: 68 38 00 00 00 push $0x38 80486ef: e9 70 ff ff ff jmp 8048664 <_init+0x18> >From the output of readelf -a: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [22] .got PROGBITS 08049cd4 000cd4 000004 04 WA 0 0 4 [23] .got.plt PROGBITS 08049cd8 000cd8 000044 04 WA 0 0 4 Conflicting accesses were reported on location 0x8049d00 (size 4). Is my conclusion correct that this data resides in the .got.plt section ? I don't think it is possible to add a tracking function in the ELF reader, since the executable file is loaded before the Valgrind tool is loaded ? There is already an interface for iterating over segments: VG_(seginfo_syms_howmany)() and VG_(seginfo_syms_getidx)(). Would it be possible to make the .got.plt section information available via these functions ? All I need is the start address and the size of the .got.plt section. And what about DSO's loaded after program start by dlopen() calls ? Should a tracking function be added for this, or should I add wrappers for dlopen() and dlclose() in the drd tool ? Bart. |
|
From: Tom H. <to...@co...> - 2007-01-01 10:12:19
|
In message <e2e...@ma...>
"Bart Van Assche" <bar...@gm...> wrote:
> > You mean PLT I think, not GOT - the GOT is for global data access and
> > the PLT is for function calls.
> >
> > The ELF reader in m_debuginfo already detects the PLT and GOT so you
> > would need to make it record that information somewhere I guess.
>
> From the output of objdump -d:
>
> 080486e4 <_Znwj@plt>:
> 80486e4: ff 25 00 9d 04 08 jmp *0x8049d00
> 80486ea: 68 38 00 00 00 push $0x38
> 80486ef: e9 70 ff ff ff jmp 8048664 <_init+0x18>
>
> From the output of readelf -a:
>
> Section Headers:
> [Nr] Name Type Addr Off Size ES Flg Lk
> Inf Al
> [22] .got PROGBITS 08049cd4 000cd4 000004 04 WA 0
> 0 4
> [23] .got.plt PROGBITS 08049cd8 000cd8 000044 04 WA 0
> 0 4
>
> Conflicting accesses were reported on location 0x8049d00 (size 4). Is my
> conclusion correct that this data resides in the .got.plt section ?
Correct - that section is the PLT section. I'm not sure why ELF gives
the section that name but it is normally known as the PLT and the .got
section is known as the GOT.
> I don't think it is possible to add a tracking function in the ELF reader,
> since the executable file is loaded before the Valgrind tool is loaded ?
>
> There is already an interface for iterating over segments:
> VG_(seginfo_syms_howmany)() and VG_(seginfo_syms_getidx)(). Would it be
> possible to make the .got.plt section information available via these
> functions ? All I need is the start address and the size of the .got.plt
> section.
Actually, the information is already there by the looks of it - you
just need to call VG_(seginfo_sect_kind) and see if the resulting
value is Vg_SectPLT or not.
> And what about DSO's loaded after program start by dlopen() calls ? Should a
> tracking function be added for this, or should I add wrappers for dlopen()
> and dlclose() in the drd tool ?
The segment infomation will be updated automatically when a DSO is
loaded, so using the seginfo calls should handle all that transparently.
The only thing you might need to do is that if you are caching anything
relating to whether an address is in a PLT or not you will need to watch
for unmaps of that address range and discard that cached data.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Tom H. <to...@co...> - 2007-01-01 10:18:26
|
In message <755...@lo...>
Tom Hughes <to...@co...> wrote:
> In message <e2e...@ma...>
> "Bart Van Assche" <bar...@gm...> wrote:
>
> > > You mean PLT I think, not GOT - the GOT is for global data access and
> > > the PLT is for function calls.
> > >
> > > The ELF reader in m_debuginfo already detects the PLT and GOT so you
> > > would need to make it record that information somewhere I guess.
> >
> > From the output of objdump -d:
> >
> > 080486e4 <_Znwj@plt>:
> > 80486e4: ff 25 00 9d 04 08 jmp *0x8049d00
> > 80486ea: 68 38 00 00 00 push $0x38
> > 80486ef: e9 70 ff ff ff jmp 8048664 <_init+0x18>
> >
> > From the output of readelf -a:
> >
> > Section Headers:
> > [Nr] Name Type Addr Off Size ES Flg Lk
> > Inf Al
> > [22] .got PROGBITS 08049cd4 000cd4 000004 04 WA 0
> > 0 4
> > [23] .got.plt PROGBITS 08049cd8 000cd8 000044 04 WA 0
> > 0 4
> >
> > Conflicting accesses were reported on location 0x8049d00 (size 4). Is my
> > conclusion correct that this data resides in the .got.plt section ?
>
> Correct - that section is the PLT section. I'm not sure why ELF gives
> the section that name but it is normally known as the PLT and the .got
> section is known as the GOT.
Ah hang on... The PLT itself is .plt - the .got.plt section is the
table used to cache the result of resolving the function name to an
address.
> > I don't think it is possible to add a tracking function in the ELF reader,
> > since the executable file is loaded before the Valgrind tool is loaded ?
> >
> > There is already an interface for iterating over segments:
> > VG_(seginfo_syms_howmany)() and VG_(seginfo_syms_getidx)(). Would it be
> > possible to make the .got.plt section information available via these
> > functions ? All I need is the start address and the size of the .got.plt
> > section.
>
> Actually, the information is already there by the looks of it - you
> just need to call VG_(seginfo_sect_kind) and see if the resulting
> value is Vg_SectPLT or not.
So I think what you need to do is to see whether the instruction
doing the access is in the PLT rather than whether the address
being accessed is in the PLT.
Either that or valgrind needs to be extended to track the .got.plt
section in the seginfo as well as the .plt and .got sections.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Bart V. A. <bar...@gm...> - 2007-01-01 10:50:41
|
On 1/1/07, Tom Hughes <to...@co...> wrote: > > In message <755...@lo...> > Tom Hughes <to...@co...> wrote: ... > Ah hang on... The PLT itself is .plt - the .got.plt section is the > table used to cache the result of resolving the function name to an > address. ... > So I think what you need to do is to see whether the instruction > doing the access is in the PLT rather than whether the address > being accessed is in the PLT. > > Either that or valgrind needs to be extended to track the .got.plt > section in the seginfo as well as the .plt and .got sections. > > Tom What I need is the address where the .got.plt section is loaded, and the size of this section. Does this mean Valgrind has to be extended ? If I should do this, where should I start ? Bart. |
|
From: Tom H. <to...@co...> - 2007-01-01 11:58:10
|
In message <e2e...@ma...>
"Bart Van Assche" <bar...@gm...> wrote:
> On 1/1/07, Tom Hughes <to...@co...> wrote:
> >
> > In message <755...@lo...>
> > Tom Hughes <to...@co...> wrote:
>
> ...
>
> > Ah hang on... The PLT itself is .plt - the .got.plt section is the
> > table used to cache the result of resolving the function name to an
> > address.
>
> ...
>
> > So I think what you need to do is to see whether the instruction
> > doing the access is in the PLT rather than whether the address
> > being accessed is in the PLT.
> >
> > Either that or valgrind needs to be extended to track the .got.plt
> > section in the seginfo as well as the .plt and .got sections.
>
>
> What I need is the address where the .got.plt section is loaded, and the
> size of this section. Does this mean Valgrind has to be extended ? If I
> should do this, where should I start ?
Is it not possible to check it the other way? Based on the address of
the faulting instruction?
If it isn't then look at readelf.c and debuginfo.c where they record
the address of the .plt and .got sections in the SegInfo structure and
then use it to return a segment kind from that function and extend it
to track the .got.plt section as well and return a new segment type.
Tom
--
Tom Hughes (to...@co...)
http://www.compton.nu/
|
|
From: Bart V. A. <bar...@gm...> - 2007-01-01 16:08:33
|
On 1/1/07, Tom Hughes <to...@co...> wrote: > > Is it not possible to check it the other way? Based on the address of > the faulting instruction? > > If it isn't then look at readelf.c and debuginfo.c where they record > the address of the .plt and .got sections in the SegInfo structure and > then use it to return a segment kind from that function and extend it > to track the .got.plt section as well and return a new segment type. > > Tom > A nice solution would be not to instrument any code in the .plt section from within the drd tool. Do you know whether the original (untranslated) instruction address is accessible from within a tool's instrumentation function, such that it can be passed to VG_(seginfo_sect_kind)() ? Bart. |
|
From: Julian S. <js...@ac...> - 2007-01-01 17:34:18
|
> A nice solution would be not to instrument any code in the .plt section > from within the drd tool. Do you know whether the original (untranslated) > instruction address is accessible from within a tool's instrumentation > function, such that it can be passed to VG_(seginfo_sect_kind)() ? Yes, the IR for each instruction begins with an Ist_IMark which says exactly the address and size of the instruction. Search for "IMark" in libvex_ir.h. J |