Author: njn
Date: 2005-06-16 04:56:58 +0100 (Thu, 16 Jun 2005)
New Revision: 3916
Log:
A cleanup of the redirection stuff.
- Renamed VG_INTERCEPT as VG_REPLACE_FUNCTION to make its purpose
clearer.
- Renamed VG_WRAPPER as VG_NOTIFY_ON_LOAD to make its purpose cleare.
Started calling that stuff "load notification".
- Moved various things into m_redir.c, a much more sensible place for
them. This reduced the number of exported functions overall. Renamed
intercept_demangle() as Z_decode() as part of this.
- Improved the documentation of this stuff, especially in
pub_core_redir.c.
- Got --run-libc-freeres=3Dyes working again. It was doing nothing.
- Renamed vg_inject.so as vg_preload_core.so to match
vg_preload_<tool>.so
- Renamed vg_intercept.c as vg_preloaded.c. (I kept the "vg_" prefix
because this filename can appear in stack traces, so the "vg_" is a
useful hint for users that it belongs to Valgrind.)
- Removed all the Memcheck-specific calls to add_redirect_sym_to_sym()
from VG_(setup_redirect_table)(), instead using VG_REPLACE_FUNCTION in
mac_replace_strmem.c, just like vg_replace_malloc.c. This is the
right way to do it. This required moving some of
coregrind/pub_core_redir.h into the newly added
include/pub_tool_redir.h. add_redirect_sym_to_sym() is no longer
used...
- Now only handing off symbols to m_redir for inspection/decoding after
they have been deemed to be interesting by the symbol table reader.
- Factored out commonality between the add_redirect_*_to_* functions
into add_redirect_X_to_X().
- Added "Zh", meaning '-' ('h' for "hyphen"), to the Z-decoding scheme,
to handle sonames like "ld-linux-x86-64.so.2".
- Added a FAQ explaining the newly found issue of glibc aliasing=20
sometimes causing the wrong function name to appear in stack traces.
- Added a new regtest strchr.c. It's possible this will fail on some
platforms. If so, an alternative output file can be provided, but
I'd like to see it in practice first.
It's possible that there will be minor breakage on other
platforms/setups, but it should be minimal and easily fixable.
Plus some ordinary cleanups in symtab.c:
- Removed the old optimisation from VG_(addStr)() whereby it kept track
of the previous 5 added strings and avoiding duplicating any of them.
Turns out it was barely having any effect any more, and just
complicated things.
- Made read_symtab() more readable, by introducing a new variable
"sym_name" and introducing the auxiliary function
is_symbol_interesting().
- renamed the module variable 'segInfo' as 'segInfo_list' to make it
more obvious it's a module variable and not just some ordinary local
variable (which was an easy mistake to make).
-------------------------------------------------------------------------=
----
XXX: [later] remove add_redirect_sym_to_sym, and everything related to
X_to_sym? (ie. only need X_to_addr)
XXX: better function names? all those 'resolved' names...
[later...]
Added:
trunk/coregrind/vg_preloaded.c
trunk/include/pub_tool_redir.h
trunk/memcheck/tests/memcmptest.stderr.exp2
trunk/memcheck/tests/strchr.c
trunk/memcheck/tests/strchr.vgtest
Removed:
trunk/coregrind/vg_intercept.c
Modified:
trunk/FAQ.txt
trunk/coregrind/Makefile.am
trunk/coregrind/core.h
trunk/coregrind/m_debuginfo/symtab.c
trunk/coregrind/m_libcproc.c
trunk/coregrind/m_main.c
trunk/coregrind/m_redir.c
trunk/coregrind/m_replacemalloc/vg_replace_malloc.c
trunk/coregrind/m_syscalls/syscalls-generic.c
trunk/coregrind/pub_core_main.h
trunk/coregrind/pub_core_redir.h
trunk/docs/xml/FAQ.xml
trunk/include/Makefile.am
trunk/memcheck/mac_replace_strmem.c
trunk/memcheck/tests/Makefile.am
trunk/memcheck/tests/memcmptest.c
trunk/tests/filter_stderr_basic
Modified: trunk/FAQ.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/FAQ.txt 2005-06-15 21:34:35 UTC (rev 3915)
+++ trunk/FAQ.txt 2005-06-16 03:56:58 UTC (rev 3916)
@@ -245,6 +245,18 @@
by 0x1D65E007: ???
by 0x8049EE6: main (main.cpp:24)
=20
+------------------------------------------------------------------------=
-----
+4.4. The stack traces given by Memcheck (or another tool) seem to
+ have the wrong function name in them. What's happening?
+
+Occasionally Valgrind stack traces get the wrong function names.
+This is caused by glibc using aliases to effectively give one function
+two names. Most of the time Valgrind chooses a suitable name, but
+very occasionally it gets it wrong.
+
+Examples we know of are printing 'bcmp' instead of 'memcmp', 'index'
+instead of 'strchr', and 'rindex' instead of 'strrchr'.
+
-----------------------------------------------------------------
5. Memcheck doesn't find my bug
-----------------------------------------------------------------
Modified: trunk/coregrind/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/Makefile.am 2005-06-15 21:34:35 UTC (rev 3915)
+++ trunk/coregrind/Makefile.am 2005-06-16 03:56:58 UTC (rev 3916)
@@ -32,7 +32,7 @@
=20
val_PROGRAMS =3D \
stage2 \
- vg_inject.so
+ vg_preload_core.so
=20
noinst_HEADERS =3D \
core.h \
@@ -167,12 +167,12 @@
stage2_LDADD=3D $(stage2_extra) \
-ldl
=20
-vg_inject_so_SOURCES =3D vg_intercept.c
-vg_inject_so_CFLAGS =3D $(AM_CFLAGS) -fpic
-vg_inject_so_LDADD =3D -ldl
-vg_inject_so_LDFLAGS =3D \
+vg_preload_core_so_SOURCES =3D vg_preloaded.c
+vg_preload_core_so_CFLAGS =3D $(AM_CFLAGS) -fpic
+vg_preload_core_so_LDADD =3D -ldl
+vg_preload_core_so_LDFLAGS =3D \
-shared \
- -Wl,--soname,vg_inject.so \
+ -Wl,--soname,vg_preload_core.so \
-Wl,-z,initfirst
=20
MANUAL_DEPS =3D $(noinst_HEADERS) $(include_HEADERS)
Modified: trunk/coregrind/core.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/core.h 2005-06-15 21:34:35 UTC (rev 3915)
+++ trunk/coregrind/core.h 2005-06-16 03:56:58 UTC (rev 3916)
@@ -49,10 +49,6 @@
=20
#include "pub_core_scheduler.h" // for types 'ThreadArchState'
=20
-/* ---------------------------------------------------------------------
- Exports of vg_intercept.c
- ------------------------------------------------------------------ */
-
/* These are the internal client request codes. The publically-visible
request codes are also defined in valgrind.h, and similar headers for
some tools. */
@@ -67,18 +63,6 @@
A synonym for exit. */
#define VG_USERREQ__LIBC_FREERES_DONE 0x3029
=20
-/* Intercept prefix stuff. See
- coregrind/m_replace_malloc/vg_replace_malloc.c for details. */
-#define VG_INTERCEPT(name) _vgi_##name
-#define VG_INTERCEPT_PREFIX "_vgi_"
-#define VG_INTERCEPT_PREFIX_LEN 5
-
-/* Not sure what these are for. Todo: clarify */
-#define VG_WRAPPER_PREFIX "_vgw_"
-#define VG_WRAPPER_PREFIX_LEN 5
-#define VG_WRAPPER(name) _vgw_##name
-#define VG_WRAPPER_ALIAS(name) "_vgw_" #name
-
/* ---------------------------------------------------------------------
Exports of vg_syscall.S
------------------------------------------------------------------ */
Modified: trunk/coregrind/m_debuginfo/symtab.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/symtab.c 2005-06-15 21:34:35 UTC (rev 391=
5)
+++ trunk/coregrind/m_debuginfo/symtab.c 2005-06-16 03:56:58 UTC (rev 391=
6)
@@ -47,7 +47,7 @@
=20
#include <elf.h> /* ELF defns */
=20
-static SegInfo* segInfo =3D NULL;
+static SegInfo* segInfo_list =3D NULL;
=20
/*------------------------------------------------------------*/
/*--- 32/64-bit parameterisation ---*/
@@ -89,9 +89,6 @@
/*--- ---*/
/*------------------------------------------------------------*/
=20
-static Bool
-intercept_demangle(const Char*, Char*, Int);
-
/* Majorly rewritten Sun 3 Feb 02 to enable loading symbols from
dlopen()ed libraries, which is something that KDE3 does a lot.
=20
@@ -132,42 +129,16 @@
=20
Char *VG_(addStr) ( SegInfo* si, Char* str, Int len )
{
-# define EMPTY NULL
-# define NN 5
- =20
- /* prevN[0] has the most recent, prevN[NN-1] the least recent */
- static Char *prevN[NN] =3D { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY };
- static SegInfo* curr_si =3D NULL;
struct strchunk *chunk;
- Int i, space_needed;
+ Int space_needed;
+ Char* p;
=20
if (len =3D=3D -1)
len =3D VG_(strlen)(str);
=20
- /* Avoid gratuitous duplication: if we saw 'str' within the last NN,
- * within this segment, return that index. Saves about 200KB in glib=
c,
- * extra time taken is too small to measure. --NJN 2002-Aug-30 */
- if (curr_si =3D=3D si) {
- for (i =3D NN-1; i >=3D 0; i--) {
- if (EMPTY !=3D prevN[i]=20
- && NULL !=3D si->strchunks
- && 0 =3D=3D VG_(memcmp)(str, prevN[i], len+1)) {
- return prevN[i];
- }
- }
- } else {
- /* New segment */
- curr_si =3D si;
- for (i =3D 0; i < NN; i++) prevN[i] =3D EMPTY;
- }
- /* Shuffle prevous ones along, put new one in. */
- for (i =3D NN-1; i > 0; i--)
- prevN[i] =3D prevN[i-1];
-
-# undef EMPTY
-
space_needed =3D 1 + len;
=20
+ // Allocate a new strtab chunk if necessary
if (si->strchunks =3D=3D NULL ||=20
(si->strchunks->strtab_used + space_needed) > STRCHUNKSIZE) {
chunk =3D VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*chunk));
@@ -177,16 +148,15 @@
}
chunk =3D si->strchunks;
=20
- prevN[0] =3D &chunk->strtab[chunk->strtab_used];
- VG_(memcpy)(prevN[0], str, len);
+ p =3D &chunk->strtab[chunk->strtab_used];
+ VG_(memcpy)(p, str, len);
chunk->strtab[chunk->strtab_used+len] =3D '\0';
chunk->strtab_used +=3D space_needed;
=20
- return prevN[0];
+ return p;
}
=20
/* Add a symbol to the symbol table. */
-
static __inline__
void addSym ( SegInfo* si, RiSym* sym )
{
@@ -532,6 +502,11 @@
"foo@GLIBC_2.4.2" is considered shorter than "foobar"), but if two
symbols have the same length, the one with the version string is
preferred. If all else fails, use alphabetical ordering.
+
+ Very occasionally this goes wrong (eg. 'memcmp' and 'bcmp' are aliase=
s
+ in glibc, we choose the 'bcmp' symbol because it's shorter, so we
+ can misdescribe memcmp() as bcmp()). This is hard to avoid. It's
+ mentioned in the FAQ file.
*/
static RiSym *prefersym(RiSym *a, RiSym *b)
{
@@ -550,6 +525,8 @@
if (vpb)
vlenb =3D vpb - b->name;
=20
+ TRACE_SYMTAB("choosing between '%s' and '%s'\n", a->name, b->name);
+
/* Select the shortest unversioned name */
if (vlena < vlenb)
return a;
@@ -584,24 +561,10 @@
=20
VG_(ssort)(si->symtab, si->symtab_used, sizeof(*si->symtab), compare_=
RiSym);
=20
- for (i =3D 0; i < si->symtab_used; i++) {
- if(VG_(strncmp)(si->symtab[i].name, VG_INTERCEPT_PREFIX,
- VG_INTERCEPT_PREFIX_LEN) =3D=3D 0) {
- int len =3D VG_(strlen)(si->symtab[i].name);
- char *buf =3D VG_(arena_malloc)(VG_AR_SYMTAB, len), *colon;
- intercept_demangle(si->symtab[i].name, buf, len);
- colon =3D buf + VG_(strlen)(buf) - 1;
- while(*colon !=3D ':') colon--;
- VG_(strncpy_safely)(si->symtab[i].name, colon+1, len);
- VG_(arena_free)(VG_AR_SYMTAB, buf);
- }
- }
-
cleanup_more:
=20
- /* If two symbols have identical address ranges, favour the
- one with the longer name (unless the extra length is junk)
- */
+ /* If two symbols have identical address ranges, we pick one
+ using prefersym() (see it for details). */
do {
n_merged =3D 0;
j =3D si->symtab_used;
@@ -784,7 +747,7 @@
static=20
void canonicaliseLoctab ( SegInfo* si )
{
- Int i, j;
+ Int i, j;
=20
# define SWAP(ty,aa,bb) \
do { ty tt =3D (aa); (aa) =3D (bb); (bb) =3D tt; } while (0);
@@ -952,133 +915,67 @@
return False;
}
=20
-/* Demangle an intercept symbol into library:func form
- eg "_vgi_libcZdsoZd6__ZdlPv" --> "libc.so.6:_ZdlPv"
- Uses the Z-encoding scheme described in vg_replace_malloc.c.
- Returns True if demangle OK, False otherwise.
- */
-
-static Bool
-intercept_demangle(const Char* symbol, Char* result, Int nbytes)
+static Bool is_interesting_symbol(SegInfo* si, ElfXX_Sym* sym,=20
+ Char* sym_name, Addr sym_addr)
{
-# define EMIT(ch) \
- do { \
- if (j >=3D nbytes) \
- result[j-1] =3D 0; \
- else \
- result[j++] =3D ch; \
- } while (0)
+ /* Figure out if we're interested in the symbol.
+ Firstly, is it of the right flavour? */
+ if ( ! ( (ELFXX_ST_BIND(sym->st_info) =3D=3D STB_GLOBAL ||
+ ELFXX_ST_BIND(sym->st_info) =3D=3D STB_LOCAL ||
+ ELFXX_ST_BIND(sym->st_info) =3D=3D STB_WEAK)
+ &&
+ (ELFXX_ST_TYPE(sym->st_info) =3D=3D STT_FUNC ||
+ (VG_(needs).data_syms=20
+ && ELFXX_ST_TYPE(sym->st_info) =3D=3D STT_OBJECT))
+ )
+ )
+ return False;
=20
- Bool error =3D False;
- Int i, j =3D 0;
- Int len =3D VG_(strlen)(symbol);
- if (0) VG_(printf)("idm: %s\n", symbol);
+ /* Secondly, if it's apparently in a GOT or PLT, it's really
+ a reference to a symbol defined elsewhere, so ignore it. */
+ if (si->got_start !=3D 0
+ && sym_addr >=3D si->got_start=20
+ && sym_addr < si->got_start + si->got_size) {
+ TRACE_SYMTAB("ignore -- in GOT: %s\n", sym_name);
+ return False;
+ }
+ if (si->plt_start !=3D 0
+ && sym_addr >=3D si->plt_start
+ && sym_addr < si->plt_start + si->plt_size) {
+ TRACE_SYMTAB("ignore -- in PLT: %s\n", sym_name);
+ return False;
+ }
=20
- i =3D VG_INTERCEPT_PREFIX_LEN;
-
- /* Chew though the Z-encoded soname part. */
- while (True) {
-
- if (i >=3D len)=20
- break;
-
- if (symbol[i] =3D=3D '_')
- /* We found the underscore following the Z-encoded soname.
- Just copy the rest literally. */
- break;
-
- if (symbol[i] !=3D 'Z') {
- EMIT(symbol[i]);
- i++;
- continue;
- }
-
- /* We've got a Z-escape. Act accordingly. */
- i++;
- if (i >=3D len) {
- /* Hmm, Z right at the end. Something's wrong. */
- error =3D True;
- EMIT('Z');
- break;
- }
- switch (symbol[i]) {
- case 'a': EMIT('*'); break;
- case 'p': EMIT('+'); break;
- case 'c': EMIT(':'); break;
- case 'd': EMIT('.'); break;
- case 'u': EMIT('_'); break;
- case 's': EMIT(' '); break;
- case 'Z': EMIT('Z'); break;
- default: error =3D True; EMIT('Z'); EMIT(symbol[i]); break;
- }
- i++;
+ /* Don't bother if nameless, or zero-sized. */
+ if (sym->st_name =3D=3D (ElfXX_Word)NULL
+ || /* VG_(strlen)(sym_name) =3D=3D 0 */
+ /* equivalent but cheaper ... */
+ sym_name[0] =3D=3D 0
+ || sym->st_size =3D=3D 0) {
+ TRACE_SYMTAB("ignore -- size=3D0: %s\n", sym_name);
+ return False;
}
=20
- if (error || i >=3D len || symbol[i] !=3D '_') {
- /* Something's wrong. Give up. */
- VG_(message)(Vg_UserMsg, "intercept: error demangling: %s", symbol=
);
- EMIT(0);
+ /* This seems to significantly reduce the number of junk
+ symbols, and particularly reduces the number of
+ overlapping address ranges. Don't ask me why ... */
+ if ((Int)sym->st_value =3D=3D 0) {
+ TRACE_SYMTAB( "ignore -- valu=3D0: %s\n", sym_name);
return False;
}
=20
- /* Copy the rest of the string verbatim. */
- i++;
- EMIT(':');
- while (True) {
- if (i >=3D len)
- break;
- EMIT(symbol[i]);
- i++;
+ /* If no part of the symbol falls within the mapped range,
+ ignore it. */
+ if (sym_addr+sym->st_size <=3D si->start
+ || sym_addr >=3D si->start+si->size) {
+ TRACE_SYMTAB( "ignore -- outside mapped range\n" );
+ return False;
}
=20
- EMIT(0);
- if (0) VG_(printf)("%s\n", result);
+ // It is an interesting symbol!
return True;
-
-# undef EMIT
}
=20
-static
-void handle_intercept( SegInfo* si, Char* symbol, ElfXX_Sym* sym)
-{
- Bool ok;
- Int len =3D VG_(strlen)(symbol) + 1 - VG_INTERCEPT_PREFIX_LEN;
- Char *lib =3D VG_(arena_malloc)(VG_AR_SYMTAB, len+8);
- Char *func;
-
- /* Put "soname:" at the start of lib. */
- lib[0] =3D 's';
- lib[1] =3D 'o';
- lib[2] =3D 'n';
- lib[3] =3D 'a';
- lib[4] =3D 'm';
- lib[5] =3D 'e';
- lib[6] =3D ':';
- lib[7] =3D 0;
-
- ok =3D intercept_demangle(symbol, lib+7, len);
- if (ok) {
- func =3D lib + VG_(strlen)(lib)-1;
-
- while(*func !=3D ':') func--;
- *func =3D '\0';
-
- if (0) VG_(printf)("lib A%sZ, func A%sZ\n", lib, func+1);
- VG_(add_redirect_sym_to_addr)(lib, func+1, si->offset + sym->st_va=
lue);
- }
-
- VG_(arena_free)(VG_AR_SYMTAB, lib);
-}
-
-//static
-//void handle_wrapper( SegInfo* si, Char* symbol, ElfXX_Sym* sym)
-//{
-// if (VG_(strcmp)(symbol, STR(VG_WRAPPER(freeres))) =3D=3D 0)
-// VGA_(intercept_libc_freeres_wrapper)((Addr)(si->offset + sym->st=
_value));
-// else if (VG_(strcmp)(symbol, STR(VG_WRAPPER(pthread_startfunc_wrapp=
er))) =3D=3D 0)
-// VG_(pthread_startfunc_wrapper)((Addr)(si->offset + sym->st_value=
));
-//}
-
/* Read a symbol table (normal or dynamic) */
static
void read_symtab( SegInfo* si, Char* tab_name, Bool do_intercepts,
@@ -1087,9 +984,10 @@
{
Int i;
Addr sym_addr;
+ Char* sym_name;
RiSym risym;
- Char* t0;
Char* name;
+ ElfXX_Sym* sym;
=20
if (o_strtab =3D=3D NULL || o_symtab =3D=3D NULL) {
Char buf[80];
@@ -1105,8 +1003,8 @@
/* Perhaps should start at i =3D 1; ELF docs suggest that entry
0 always denotes 'unknown symbol'. */
for (i =3D 1; i < (Int)(o_symtab_sz/sizeof(ElfXX_Sym)); i++) {
- ElfXX_Sym* sym =3D & o_symtab[i];
-# if 1
+ sym =3D & o_symtab[i];
+ sym_name =3D (Char*)(o_strtab + sym->st_name);
sym_addr =3D si->offset + sym->st_value;
=20
if (VG_(clo_trace_symtab)) {
@@ -1132,107 +1030,32 @@
VG_(printf)(
": value %p, size %d, name %s\n",
sym_addr, sym->st_size,
- ( sym->st_name=20
- ? ((Char*)o_strtab+sym->st_name)=20
- : (Char*)"NONAME" ) );=20
+ ( sym->st_name ? sym_name : (Char*)"NONAME" ) );=20
} =20
-# endif
=20
- /*
- * Is this symbol a magic valgrind-intercept symbol? If so,
- * hand this off to the interceptinator.
- */
- if (do_intercepts) {
- if (VG_(strncmp)((Char*)o_strtab+sym->st_name,
- VG_INTERCEPT_PREFIX,
- VG_INTERCEPT_PREFIX_LEN) =3D=3D 0) {
- handle_intercept(si, (Char*)o_strtab+sym->st_name, sym);
- }=20
- //else if (VG_(strncmp)((Char*)o_strtab+sym->st_name,
- // VG_WRAPPER_PREFIX,
- // VG_WRAPPER_PREFIX_LEN) =3D=3D 0) {
- // handle_wrapper(si, (Char*)o_strtab+sym->st_name, sym);
- //}
- }
+ // Record interesting symbols in our symtab.
+ if ( is_interesting_symbol(si, sym, sym_name, sym_addr) ) {
+ vg_assert(sym->st_name !=3D 0);
+ vg_assert(sym_name[0] !=3D 0);
+ name =3D VG_(addStr) ( si, sym_name, -1 );
+ vg_assert(name !=3D NULL);
=20
- /* Figure out if we're interested in the symbol.
- Firstly, is it of the right flavour? */
- if ( ! ( (ELFXX_ST_BIND(sym->st_info) =3D=3D STB_GLOBAL ||
- ELFXX_ST_BIND(sym->st_info) =3D=3D STB_LOCAL ||
- ELFXX_ST_BIND(sym->st_info) =3D=3D STB_WEAK)
- &&
- (ELFXX_ST_TYPE(sym->st_info) =3D=3D STT_FUNC ||
- (VG_(needs).data_syms=20
- && ELFXX_ST_TYPE(sym->st_info) =3D=3D STT_OBJECT))
- )
- )
- continue;
+ /*
+ * Is this symbol a magic valgrind-intercept symbol? If so,
+ * hand this off to the redir module. =20
+ *
+ * Note: this function can change the symbol name just added to
+ * the string table. Importantly, it never makes it bigger.
+ */
+ if (do_intercepts) {
+ VG_(maybe_redir_or_notify)( name, sym_addr );
+ }
=20
- /* Secondly, if it's apparently in a GOT or PLT, it's really
- a reference to a symbol defined elsewhere, so ignore it. */
- if (si->got_start !=3D 0
- && sym_addr >=3D si->got_start=20
- && sym_addr < si->got_start + si->got_size) {
- TRACE_SYMTAB("in GOT: %s\n", o_strtab+sym->st_name);
- continue;
+ risym.addr =3D sym_addr;
+ risym.size =3D sym->st_size;
+ risym.name =3D name;
+ addSym ( si, &risym );
}
- if (si->plt_start !=3D 0
- && sym_addr >=3D si->plt_start
- && sym_addr < si->plt_start + si->plt_size) {
- TRACE_SYMTAB("in PLT: %s\n", o_strtab+sym->st_name);
- continue;
- }
-
- /* Don't bother if nameless, or zero-sized. */
- if (sym->st_name =3D=3D (ElfXX_Word)NULL
- || /* VG_(strlen)(o_strtab+sym->st_name) =3D=3D 0 */
- /* equivalent but cheaper ... */
- * ((UChar*)(o_strtab+sym->st_name)) =3D=3D 0
- || sym->st_size =3D=3D 0) {
- TRACE_SYMTAB("size=3D0: %s\n", o_strtab+sym->st_name);
- continue;
- }
-
-# if 0
- /* Avoid _dl_ junk. (Why?) */
- /* 01-02-24: disabled until I find out if it really helps. */
- if (VG_(strncmp)("_dl_", o_strtab+sym->st_name, 4) =3D=3D 0
- || VG_(strncmp)("_r_debug",=20
- o_strtab+sym->st_name, 8) =3D=3D 0) {
- TRACE_SYMTAB("_dl_ junk: %s\n", o_strtab+sym->st_name);
- continue;
- }
-# endif
-
- /* This seems to significantly reduce the number of junk
- symbols, and particularly reduces the number of
- overlapping address ranges. Don't ask me why ... */
- if ((Int)sym->st_value =3D=3D 0) {
- TRACE_SYMTAB( "valu=3D0: %s\n", o_strtab+sym->st_name);
- continue;
- }
-
- /* If no part of the symbol falls within the mapped range,
- ignore it. */
- if (sym_addr+sym->st_size <=3D si->start
- || sym_addr >=3D si->start+si->size) {
- TRACE_SYMTAB( "outside mapped range" );
- continue;
- }
-
- /* If we reach here, it's an interesting symbol; record it. */
- t0 =3D sym->st_name=20
- ? (Char*)(o_strtab+sym->st_name)=20
- : (Char*)"NONAME";
- name =3D VG_(addStr) ( si, t0, -1 );
- vg_assert(name !=3D NULL
- /* && 0=3D=3DVG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
- /* VG_(printf)("%p + %d: %p %s\n", si->start,=20
- (Int)sym->st_value, sym_addr, t0 ); */
- risym.addr =3D sym_addr;
- risym.size =3D sym->st_size;
- risym.name =3D name;
- addSym ( si, &risym );
}
}
=20
@@ -1840,15 +1663,19 @@
segment list, even if it is a bad ELF file. Ironically,
running this under valgrind itself hides the problem, because
it doesn't recycle pointers... */
+ // [Nb: the prevN optimization has now been removed from addStr().
+ // However, when I try reactivating this path of the branch I get
+ // seg faults... --njn 13-Jun-2005]
freeSegInfo( si );
} else {
- si->next =3D segInfo;
- segInfo =3D si;
+ // Prepend si to segInfo_list
+ si->next =3D segInfo_list;
+ segInfo_list =3D si;
=20
- canonicaliseSymtab ( si );
- canonicaliseLoctab ( si );
+ canonicaliseSymtab ( si );
+ canonicaliseLoctab ( si );
canonicaliseScopetab ( si );
- canonicaliseCfiSI ( si );
+ canonicaliseCfiSI ( si );
=20
/* do redirects */
VG_(resolve_seg_redirs)( si );
@@ -1870,7 +1697,7 @@
SegInfo *prev, *curr;
=20
prev =3D NULL;
- curr =3D segInfo;
+ curr =3D segInfo_list;
while (True) {
if (curr =3D=3D NULL) break;
if (start =3D=3D curr->start) break;
@@ -1890,7 +1717,7 @@
vg_assert(prev =3D=3D NULL || prev->next =3D=3D curr);
=20
if (prev =3D=3D NULL) {
- segInfo =3D curr->next;
+ segInfo_list =3D curr->next;
} else {
prev->next =3D curr->next;
}
@@ -2034,7 +1861,7 @@
=20
VGP_PUSHCC(VgpSearchSyms);
=20
- for (si =3D segInfo; si !=3D NULL; si =3D si->next) {
+ for (si =3D segInfo_list; si !=3D NULL; si =3D si->next) {
if (si->start <=3D ptr && ptr < si->start+si->size) {
lno =3D search_one_loctab ( si, ptr );
if (lno =3D=3D -1) goto not_found;
@@ -2087,7 +1914,7 @@
=20
VGP_PUSHCC(VgpSearchSyms);
=20
- for (si =3D segInfo; si !=3D NULL; si =3D si->next) {
+ for (si =3D segInfo_list; si !=3D NULL; si =3D si->next) {
if (si->start <=3D ptr && ptr < si->start+si->size) {
scno =3D search_one_scopetab ( si, ptr );
if (scno =3D=3D -1) goto not_found;
@@ -2215,7 +2042,7 @@
{
SegInfo* si;
=20
- for (si =3D segInfo; si !=3D NULL; si =3D si->next) {
+ for (si =3D segInfo_list; si !=3D NULL; si =3D si->next) {
if (si->start <=3D a && a < si->start+si->size) {
VG_(strncpy_safely)(buf, si->filename, nbuf);
return True;
@@ -2230,7 +2057,7 @@
{
SegInfo* si;
=20
- for (si =3D segInfo; si !=3D NULL; si =3D si->next) {
+ for (si =3D segInfo_list; si !=3D NULL; si =3D si->next) {
if (si->start <=3D a && a < si->start+si->size) {
return si;
}
@@ -2633,7 +2460,7 @@
=20
if (0) VG_(printf)("search for %p\n", *ipP);
=20
- for (si =3D segInfo; si !=3D NULL; si =3D si->next) {
+ for (si =3D segInfo_list; si !=3D NULL; si =3D si->next) {
/* Use the per-SegInfo summary address ranges to skip
inapplicable SegInfos quickly. */
if (si->cfisi_used =3D=3D 0)
@@ -2706,7 +2533,7 @@
const SegInfo* VG_(next_seginfo)(const SegInfo* si)
{
if (si =3D=3D NULL)
- return segInfo;
+ return segInfo_list;
return si->next;
}
=20
@@ -2735,7 +2562,7 @@
SegInfo* si;
VgSectKind ret =3D Vg_SectUnknown;
=20
- for(si =3D segInfo; si !=3D NULL; si =3D si->next) {
+ for(si =3D segInfo_list; si !=3D NULL; si =3D si->next) {
if (a >=3D si->start && a < (si->start + si->size)) {
if (0)
VG_(printf)("addr=3D%p si=3D%p %s got=3D%p %d plt=3D%p %d data=3D%=
p %d bss=3D%p %d\n",
Modified: trunk/coregrind/m_libcproc.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_libcproc.c 2005-06-15 21:34:35 UTC (rev 3915)
+++ trunk/coregrind/m_libcproc.c 2005-06-16 03:56:58 UTC (rev 3916)
@@ -202,7 +202,7 @@
buf =3D VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
=20
// Remove Valgrind-specific entries from LD_*.
- VG_(sprintf)(buf, "%s*/vg_inject.so", VG_(libdir));
+ VG_(sprintf)(buf, "%s*/vg_preload_core.so", VG_(libdir));
mash_colon_env(ld_preload_str, buf);
VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
mash_colon_env(ld_preload_str, buf);
Modified: trunk/coregrind/m_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_main.c 2005-06-15 21:34:35 UTC (rev 3915)
+++ trunk/coregrind/m_main.c 2005-06-16 03:56:58 UTC (rev 3916)
@@ -644,7 +644,7 @@
=20
/* Prepare the client's environment. This is basically a copy of our
environment, except:
- LD_PRELOAD=3D$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL=
.so:)?$LD_PRELOAD
+ LD_PRELOAD=3D$VALGRINDLIB/vg_preload_core.so:($VALGRINDLIB/vgpreloa=
d_TOOL.so:)?$LD_PRELOAD
=20
If this is missing, then it is added.
=20
@@ -655,32 +655,32 @@
*/
static char **fix_environment(char **origenv, const char *preload)
{
- static const char inject_so[] =3D "vg_inject.so";
+ static const char preload_core_so[] =3D "vg_preload_core.so";
static const char ld_preload[] =3D "LD_PRELOAD=3D";
static const char valgrind_clo[] =3D VALGRINDCLO "=3D";
static const int ld_preload_len =3D sizeof(ld_preload)-1;
static const int valgrind_clo_len =3D sizeof(valgrind_clo)-1;
int ld_preload_done =3D 0;
- char *inject_path;
- int inject_path_len;
+ char *preload_core_path;
+ int preload_core_path_len;
int vgliblen =3D strlen(VG_(libdir));
char **cpp;
char **ret;
int envc;
const int preloadlen =3D (preload =3D=3D NULL) ? 0 : strlen(preload);
=20
- /* Find the vg_inject.so; also make room for the tool preload
+ /* Find the vg_preload_core.so; also make room for the tool preload
library */
- inject_path_len =3D sizeof(inject_so) + vgliblen + preloadlen + 16;
- inject_path =3D malloc(inject_path_len);
- vg_assert(inject_path);
+ preload_core_path_len =3D sizeof(preload_core_so) + vgliblen + preloa=
dlen + 16;
+ preload_core_path =3D malloc(preload_core_path_len);
+ vg_assert(preload_core_path);
=20
if (preload)
- snprintf(inject_path, inject_path_len, "%s/%s:%s",=20
- VG_(libdir), inject_so, preload);
+ snprintf(preload_core_path, preload_core_path_len, "%s/%s:%s",=20
+ VG_(libdir), preload_core_so, preload);
else
- snprintf(inject_path, inject_path_len, "%s/%s",=20
- VG_(libdir), inject_so);
+ snprintf(preload_core_path, preload_core_path_len, "%s/%s",=20
+ VG_(libdir), preload_core_so);
=20
/* Count the original size of the env */
envc =3D 0; /* trailing NULL */
@@ -701,12 +701,12 @@
/* Walk over the new environment, mashing as we go */
for (cpp =3D ret; cpp && *cpp; cpp++) {
if (memcmp(*cpp, ld_preload, ld_preload_len) =3D=3D 0) {
- int len =3D strlen(*cpp) + inject_path_len;
+ int len =3D strlen(*cpp) + preload_core_path_len;
char *cp =3D malloc(len);
vg_assert(cp);
=20
snprintf(cp, len, "%s%s:%s",
- ld_preload, inject_path, (*cpp)+ld_preload_len);
+ ld_preload, preload_core_path, (*cpp)+ld_preload_len);
=20
*cpp =3D cp;
=20
@@ -718,17 +718,16 @@
=20
/* Add the missing bits */
if (!ld_preload_done) {
- int len =3D ld_preload_len + inject_path_len;
+ int len =3D ld_preload_len + preload_core_path_len;
char *cp =3D malloc(len);
vg_assert(cp);
=20
- snprintf(cp, len, "%s%s",
- ld_preload, inject_path);
+ snprintf(cp, len, "%s%s", ld_preload, preload_core_path);
=20
ret[envc++] =3D cp;
}
=20
- free(inject_path);
+ free(preload_core_path);
ret[envc] =3D NULL;
=20
return ret;
@@ -2798,7 +2797,7 @@
called at program exit. */
static Addr __libc_freeres_wrapper;
=20
-void VGA_(intercept_libc_freeres_wrapper)(Addr addr)
+void VG_(set_libc_freeres_wrapper_addr)(Addr addr)
{
__libc_freeres_wrapper =3D addr;
}
Modified: trunk/coregrind/m_redir.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_redir.c 2005-06-15 21:34:35 UTC (rev 3915)
+++ trunk/coregrind/m_redir.c 2005-06-16 03:56:58 UTC (rev 3916)
@@ -35,6 +35,7 @@
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
#include "pub_core_libcprint.h"
+#include "pub_core_main.h"
#include "pub_core_mallocfree.h"
#include "pub_core_options.h"
#include "pub_core_redir.h"
@@ -311,26 +312,27 @@
}
}
=20
-/* Redirect a lib/symbol reference to a function at lib/symbol */
-static void add_redirect_sym_to_sym(const Char *from_lib, const Char *fr=
om_sym,
- const Char *to_lib, const Char *to_sym)
+static void add_redirect_X_to_X(
+ const Char *from_lib, const Char *from_sym, Addr from_addr,
+ const Char *to_lib, const Char *to_sym, Addr to_addr
+)
{
CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
=20
redir->type =3D R_REDIRECT;
=20
- redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
- redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
- redir->from_addr =3D 0;
+ if (from_lib) redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, fr=
om_lib);
+ if (from_sym) redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, fr=
om_sym);
+ redir->from_addr =3D from_addr;
=20
- redir->to_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, to_lib);
- redir->to_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, to_sym);
- redir->to_addr =3D 0;
+ if (to_lib) redir->to_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, to=
_lib);
+ if (to_sym) redir->to_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, to=
_sym);
+ redir->to_addr =3D to_addr;
=20
if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
VG_(message)(Vg_UserMsg,=20
- "REDIRECT %s(%s) to %s(%s)",
- from_lib, from_sym, to_lib, to_sym);
+ "REDIRECT %s:%s(%p) to %s:%s(%p)",
+ from_lib, from_sym, from_addr, to_lib, to_sym, to_add=
r);
=20
/* Check against all existing segments to see if this redirection
can be resolved immediately */
@@ -341,57 +343,26 @@
}
}
=20
+/* Redirect a lib/symbol reference to a function at lib/symbol */
+__attribute__((unused))
+static void add_redirect_sym_to_sym(const Char *from_lib, const Char *fr=
om_sym,
+ const Char *to_lib, const Char *to_sym)
+{
+ add_redirect_X_to_X(from_lib, from_sym, 0, to_lib, to_sym, 0);
+}
+
/* Redirect a lib/symbol reference to a function at addr */
-void VG_(add_redirect_sym_to_addr)(const Char *from_lib, const Char *fro=
m_sym,
- Addr to_addr)
+static void add_redirect_sym_to_addr(const Char *from_lib, const Char *f=
rom_sym,
+ Addr to_addr)
{
- CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
-
- redir->type =3D R_REDIRECT;
-
- redir->from_lib =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
- redir->from_sym =3D VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
- redir->from_addr =3D 0;
-
- redir->to_lib =3D NULL;
- redir->to_sym =3D NULL;
- redir->to_addr =3D to_addr;
-
- if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
- VG_(message)(Vg_UserMsg,=20
- "REDIRECT %s(%s) to %p",
- from_lib, from_sym, to_addr);
-
- /* Check against all existing segments to see if this redirection
- can be resolved immediately */
- if (!resolve_redir_allsegs(redir)) {
- /* nope, add to list */
- redir->next =3D unresolved_redir;
- unresolved_redir =3D redir;
- }
+ add_redirect_X_to_X(from_lib, from_sym, 0, NULL, NULL, to_addr);
}
=20
/* Redirect a function at from_addr to a function at to_addr */
-void VG_(add_redirect_addr_to_addr)(Addr from_addr, Addr to_addr)
+__attribute__((unused)) // It is used, but not on all platforms...
+static void add_redirect_addr_to_addr(Addr from_addr, Addr to_addr)
{
- CodeRedirect *redir =3D VG_(SkipNode_Alloc)(&sk_resolved_redir);
-
- redir->type =3D R_REDIRECT;
-
- redir->from_lib =3D NULL;
- redir->from_sym =3D NULL;
- redir->from_addr =3D from_addr;
-
- redir->to_lib =3D NULL;
- redir->to_sym =3D NULL;
- redir->to_addr =3D to_addr;
-
- if (VG_(clo_verbosity) >=3D 2 && VG_(clo_trace_redir))
- VG_(message)(Vg_UserMsg,=20
- "REDIRECT %p to %p",
- from_addr, to_addr);
-
- add_resolved(redir);
+ add_redirect_X_to_X(NULL, NULL, from_addr, NULL, NULL, to_addr);
}
=20
CodeRedirect *VG_(add_wrapper)(const Char *from_lib, const Char *from_sy=
m,
@@ -443,76 +414,182 @@
=20
void VG_(setup_code_redirect_table) ( void )
{
- /* Overenthusiastic use of PLT bypassing by the glibc people also
- means we need to patch the following functions to our own
- implementations of said, in mac_replace_strmem.c.
- */
- add_redirect_sym_to_sym("soname:libc.so.6", "stpcpy",
- "*vgpreload_memcheck.so*", "stpcpy");
+#if defined(VGP_x86_linux)
+ /* Redirect _dl_sysinfo_int80, which is glibc's default system call
+ routine, to the routine in our trampoline page so that the
+ special sysinfo unwind hack in m_stacktrace.c will kick in. */
+ add_redirect_sym_to_addr("soname:ld-linux.so.2", "_dl_sysinfo_int80",
+ VG_(client_trampoline_code)+VG_(tramp_syscal=
l_offset));
+#elif defined(VGP_amd64_linux)
+ /* Redirect vsyscalls to local versions */
+ add_redirect_addr_to_addr(0xFFFFFFFFFF600000ULL,
+ VG_(client_trampoline_code)+VG_(tramp_getti=
meofday_offset));
+ add_redirect_addr_to_addr(0xFFFFFFFFFF600400ULL,
+ VG_(client_trampoline_code)+VG_(tramp_time_=
offset));
+#else
+# error Unknown platform
+#endif
+}
=20
- add_redirect_sym_to_sym("soname:ld-linux.so.2", "strlen",
- "*vgpreload_memcheck.so*", "strlen");
- add_redirect_sym_to_sym("soname:libc.so.6", "strlen",
- "*vgpreload_memcheck.so*", "strlen");
+/* Z-decode a symbol into library:func form, eg=20
+ =20
+ _vgi_libcZdsoZd6__ZdlPv --> libc.so.6:_ZdlPv
=20
- add_redirect_sym_to_sym("soname:libc.so.6", "strnlen",
- "*vgpreload_memcheck.so*", "strnlen");
+ Uses the Z-encoding scheme described in pub_core_redir.h.
+ Returns True if demangle OK, False otherwise.
+*/
+static Bool Z_decode(const Char* symbol, Char* result, Int nbytes)
+{
+# define EMIT(ch) \
+ do { \
+ if (j >=3D nbytes) \
+ result[j-1] =3D 0; \
+ else \
+ result[j++] =3D ch; \
+ } while (0)
=20
- add_redirect_sym_to_sym("soname:ld-linux.so.2", "stpcpy",
- "*vgpreload_memcheck.so*", "stpcpy");
- add_redirect_sym_to_sym("soname:libc.so.6", "stpcpy",
- "*vgpreload_memcheck.so*", "stpcpy");
+ Bool error =3D False;
+ Int i, j =3D 0;
+ Int len =3D VG_(strlen)(symbol);
+ if (0) VG_(printf)("idm: %s\n", symbol);
=20
- add_redirect_sym_to_sym("soname:libc.so.6", "strchr",
- "*vgpreload_memcheck.so*", "strchr");
- add_redirect_sym_to_sym("soname:ld-linux.so.2", "strchr",
- "*vgpreload_memcheck.so*", "strchr");
+ i =3D VG_REPLACE_FUNCTION_PREFIX_LEN;
=20
- /* apparently index is the same thing as strchr */
- add_redirect_sym_to_sym("soname:ld-linux.so.2", "index",
- "*vgpreload_memcheck.so*", "strchr");
+ /* Chew though the Z-encoded soname part. */
+ while (True) {
=20
- add_redirect_sym_to_sym("soname:libc.so.6", "strchrnul",
- "*vgpreload_memcheck.so*", "glibc232_strchrnu=
l");
+ if (i >=3D len)=20
+ break;
=20
- add_redirect_sym_to_sym("soname:libc.so.6", "rawmemchr",
- "*vgpreload_memcheck.so*", "glibc232_rawmemch=
r");
+ if (symbol[i] =3D=3D '_')
+ /* We found the underscore following the Z-encoded soname.
+ Just copy the rest literally. */
+ break;
=20
- /* amd64-linux (glibc 2.3.3, SuSE 9.2) */
- /* apparently index is the same thing as strchr */
- add_redirect_sym_to_sym("soname:libc.so.6", "index",
- "*vgpreload_memcheck.so*", "strchr");
- add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "index",
- "*vgpreload_memcheck.so*", "strchr");
+ if (symbol[i] !=3D 'Z') {
+ EMIT(symbol[i]);
+ i++;
+ continue;
+ }
=20
- add_redirect_sym_to_sym("soname:libc.so.6", "strcpy",
- "*vgpreload_memcheck.so*", "strcpy");
+ /* We've got a Z-escape. Act accordingly. */
+ i++;
+ if (i >=3D len) {
+ /* Hmm, Z right at the end. Something's wrong. */
+ error =3D True;
+ EMIT('Z');
+ break;
+ }
+ switch (symbol[i]) {
+ case 'a': EMIT('*'); break;
+ case 'p': EMIT('+'); break;
+ case 'c': EMIT(':'); break;
+ case 'd': EMIT('.'); break;
+ case 'u': EMIT('_'); break;
+ case 'h': EMIT('-'); break;
+ case 's': EMIT(' '); break;
+ case 'Z': EMIT('Z'); break;
+ default: error =3D True; EMIT('Z'); EMIT(symbol[i]); break;
+ }
+ i++;
+ }
=20
- add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "strcmp",
- "*vgpreload_memcheck.so*", "strcmp");
- add_redirect_sym_to_sym("soname:libc.so.6", "strcmp",
- "*vgpreload_memcheck.so*", "strcmp");
+ if (error || i >=3D len || symbol[i] !=3D '_') {
+ /* Something's wrong. Give up. */
+ VG_(message)(Vg_UserMsg, "intercept: error demangling: %s", symbol=
);
+ EMIT(0);
+ return False;
+ }
=20
- add_redirect_sym_to_sym("soname:ld-linux-x86-64.so.2", "strlen",
- "*vgpreload_memcheck.so*", "strlen");
+ /* Copy the rest of the string verbatim. */
+ i++;
+ EMIT(':');
+ while (True) {
+ if (i >=3D len)
+ break;
+ EMIT(symbol[i]);
+ i++;
+ }
=20
-#if defined(VGP_x86_linux)
- /* Redirect _dl_sysinfo_int80, which is glibc's default system call
- routine, to the routine in our trampoline page so that the
- special sysinfo unwind hack in m_stacktrace.c will kick in. */
- VG_(add_redirect_sym_to_addr)("soname:ld-linux.so.2", "_dl_sysinfo_in=
t80",
- VG_(client_trampoline_code)+VG_(tramp_s=
yscall_offset));
-#elif defined(VGP_amd64_linux)
- /* Redirect vsyscalls to local versions */
- VG_(add_redirect_addr_to_addr)(0xFFFFFFFFFF600000ULL,
- VG_(client_trampoline_code)+VG_(tramp_=
gettimeofday_offset));
- VG_(add_redirect_addr_to_addr)(0xFFFFFFFFFF600400ULL,
- VG_(client_trampoline_code)+VG_(tramp_=
time_offset));
-#else
-# error Unknown platform
-#endif
+ EMIT(0);
+ if (0) VG_(printf)("%s\n", result);
+ return True;
+
+# undef EMIT
}
=20
+// Nb: this can change the string pointed to by 'symbol'.
+static void handle_replacement_function( Char* symbol, Addr addr )
+{
+ Bool ok;
+ Int len =3D VG_(strlen)(symbol) + 1 - VG_REPLACE_FUNCTION_PREFIX_LE=
N;
+ Char *lib =3D VG_(arena_malloc)(VG_AR_SYMTAB, len+8);
+ Char *func;
+
+ // Put "soname:" at the start of lib
+ VG_(strcpy)(lib, "soname:");
+
+ ok =3D Z_decode(symbol, lib+7, len);
+ if (ok) {
+ // lib is "soname:<libname>:<fnname>". Split the string at the 2n=
d ':'.
+ func =3D lib + VG_(strlen)(lib)-1;
+ while(*func !=3D ':') func--;
+ *func =3D '\0';
+ func++; // Move past the '\0'
+
+ // Now lib is "soname:<libname>" and func is "<fnname>".
+ if (0) VG_(printf)("lib A%sZ, func A%sZ\n", lib, func);
+ add_redirect_sym_to_addr(lib, func, addr);
+
+ // Overwrite the given Z-encoded name with just the fnname.
+ VG_(strcpy)(symbol, func);
+ }
+
+ VG_(arena_free)(VG_AR_SYMTAB, lib);
+}
+
+// This is specifically for stringifying VG_(x) function names. We
+// need to do two macroexpansions to get the VG_ macro expanded before
+// stringifying.
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+static void handle_load_notifier( Char* symbol, Addr addr )
+{
+ if (VG_(strcmp)(symbol, STR(VG_NOTIFY_ON_LOAD(freeres))) =3D=3D 0)
+ VG_(set_libc_freeres_wrapper_addr)(addr);
+// else if (VG_(strcmp)(symbol, STR(VG_WRAPPER(pthread_startfunc_wrapp=
er))) =3D=3D 0)
+// VG_(pthread_startfunc_wrapper)((Addr)(si->offset + sym->st_value=
));
+ else
+ vg_assert2(0, "unrecognised load notification function: %s", symbo=
l);
+}
+
+static Bool is_replacement_function(Char* s)
+{
+ return (0 =3D=3D VG_(strncmp)(s,
+ VG_REPLACE_FUNCTION_PREFIX,
+ VG_REPLACE_FUNCTION_PREFIX_LEN));
+}
+
+static Bool is_load_notifier(Char* s)
+{
+ return (0 =3D=3D VG_(strncmp)(s,
+ VG_NOTIFY_ON_LOAD_PREFIX,
+ VG_NOTIFY_ON_LOAD_PREFIX_LEN));
+}
+
+// Call this for each symbol loaded. It determines if we need to do
+// anything special with it. It can modify 'symbol' in-place.
+void VG_(maybe_redir_or_notify) ( Char* symbol, Addr addr )
+{
+ if (is_replacement_function(symbol))
+ handle_replacement_function(symbol, addr);
+ else=20
+ if (is_load_notifier(symbol))
+ handle_load_notifier(symbol, addr);
+}
+
+
//:: /*------------------------------------------------------------*/
//:: /*--- General function wrapping. ---*/
//:: /*------------------------------------------------------------*/
Modified: trunk/coregrind/m_replacemalloc/vg_replace_malloc.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_replacemalloc/vg_replace_malloc.c 2005-06-15 21:34:=
35 UTC (rev 3915)
+++ trunk/coregrind/m_replacemalloc/vg_replace_malloc.c 2005-06-16 03:56:=
58 UTC (rev 3916)
@@ -30,75 +30,28 @@
*/
=20
/* ---------------------------------------------------------------------
- All the code in this file runs on the SIMULATED CPU. It is intended
- for various reasons as drop-in replacements for malloc() and friends.
- These functions have global scope, but are not intended to be called
- directly. See the comments in coregrind/vg_intercept.c for the
- gory details.
+ ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. =20
+ =20
+ These functions are drop-in replacements for malloc() and friends.
+ They have global scope, but are not intended to be called directly.
+ See pub_core_redir.h for the gory details.
=20
- This file can be linked into the injected so file for any tool that
- wishes to know about calls to malloc(). The tool must define all
+ This file can be linked into the vg_preload_<tool>.so file for any to=
ol
+ that wishes to know about calls to malloc(). The tool must define al=
l
the functions that will be called via 'info'.
=20
- It's called vg_replace_malloc.c because this filename appears in stac=
k
- traces, so we want it to be something that should be obvious what it
- means to users.
+ It is called vg_replace_malloc.c because this filename appears in sta=
ck
+ traces, so we want the name to be (hopefully!) meaningful to users.
------------------------------------------------------------------ */
=20
-#include "valgrind.h" /* for VALGRIND_NON_SIMD_CALL[12] */
+#include "valgrind.h" // for VALGRIND_NON_SIMD_CALL[12]
#include "core.h"
+#include "pub_core_debuginfo.h" // needed for pub_core_redir.h :(
#include "pub_core_mallocfree.h" // for VG_MIN_MALLOC_SZB, VG_AR_CLIE=
NT
+#include "pub_core_redir.h" // for VG_REPLACE_FUNCTION
#include "pub_core_replacemalloc.h"
=20
-/* The general idea is: you can write a function like this:
-
- retty ENCODE(foo, bar) ( ... args ... )
- {
- ... body ...
- }
-
- If foo is a Z-encoded soname and bar is an unencoded fn name, then
- the core's symbol-table reading machinery and redirection machinery
- will conspire to cause calls to the function 'bar' in object with
- soname 'foo' to actually be routed to the function written here.
- We use this below to define dozens of replacements of malloc, free,
- etc.
-
- The soname must be a Z-encoded bit of text because sonames can
- contain dots etc which are not valid symbol names. However, it is
- better not to Z-encode the function name, because C++ function names
- are already mangled, and we don't want our own Z encoding to interact
- badly with them; furthermore there's no point, because mangled C++
- function names are by definition already valid symbol names.
- =20
- It is important that the Z-encoded soname contains no unencoded=20
- underscores, since the intercept-handlers in vg_symtab2.c detect
- the end of the soname by looking for the first trailing underscore.
-*/
-
-/* We use a Z-encoding scheme here, a la GHC. This is just about
- readable enough to make a preprocessor unnecessary.
-
- The intercept-me function names are encoded as
-
- _vgi_zEncodedSoname_fnname
-
- where soname is Z-encoded but fnname isn't.
-
- The Z-encoding scheme is as follows:
-
- * --> Za (asterisk)
- + --> Zp
- : --> Zc
- . --> Zd
- _ --> Zu
- (space) --> Zs
- Z --> ZZ
-*/
-
-#define ENCODE(libname,fnname) VG_INTERCEPT(libname##_##fnname)
-
-/* Some handy mangled names */
+/* Some handy Z-encoded names */
#define m_libstc_plus_plus_star libstdcZpZpZa // libstdc++*
#define m_libc_dot_so_dot_6 libcZdsoZd6 // libc.so.6
//#define m_libpgc_dot_so libpgcZdso // libpgc.so
@@ -167,8 +120,8 @@
*/
#define ALLOC_or_NULL(soname, fnname, vg_replacement) \
\
- void* ENCODE(soname,fnname) (SizeT n); \
- void* ENCODE(soname,fnname) (SizeT n) \
+ void* VG_REPLACE_FUNCTION(soname,fnname) (SizeT n); \
+ void* VG_REPLACE_FUNCTION(soname,fnname) (SizeT n) \
{ \
void* v; \
\
@@ -187,8 +140,8 @@
*/
#define ALLOC_or_BOMB(soname, fnname, vg_replacement) \
\
- void* ENCODE(soname,fnname) (SizeT n); \
- void* ENCODE(soname,fnname) (SizeT n) \
+ void* VG_REPLACE_FUNCTION(soname,fnname) (SizeT n); \
+ void* VG_REPLACE_FUNCTION(soname,fnname) (SizeT n) \
{ \
void* v; \
\
@@ -251,7 +204,7 @@
#endif
=20
=20
-// operator new[](unsigned int), , unmangled for some bizarre reason
+// operator new[](unsigned int), unmangled for some bizarre reason
ALLOC_or_BOMB(m_libstc_plus_plus_star, __builtin_vec_new, __builtin_vec_=
new );
ALLOC_or_BOMB(m_libc_dot_so_dot_6, __builtin_vec_new, __builtin_vec_=
new );
=20
@@ -285,8 +238,8 @@
*/
#define FREE(soname, fnname, vg_replacement) \
\
- void ENCODE(soname,fnname) (void *p); \
- void ENCODE(soname,fnname) (void *p) \
+ void VG_REPLACE_FUNCTION(soname,fnname) (void *p); \
+ void VG_REPLACE_FUNCTION(soname,fnname) (void *p) \
{ \
MALLOC_TRACE(#vg_replacement "(%p)", p ); \
if (p =3D=3D NULL) \
@@ -328,8 +281,8 @@
=20
#define CALLOC(soname, fnname) \
\
- void* ENCODE(soname,fnname) ( SizeT nmemb, SizeT size ); \
- void* ENCODE(soname,fnname) ( SizeT nmemb, SizeT size ) \
+ void* VG_REPLACE_FUNCTION(soname,fnname) ( SizeT nmemb, SizeT size );=
\
+ void* VG_REPLACE_FUNCTION(soname,fnname) ( SizeT nmemb, SizeT size ) =
\
{ \
void* v; \
\
@@ -346,8 +299,8 @@
=20
#define REALLOC(soname, fnname) \
\
- void* ENCODE(soname,fnname) ( void* ptrV, SizeT new_size ); \
- void* ENCODE(soname,fnname) ( void* ptrV, SizeT new_size ) \
+ void* VG_REPLACE_FUNCTION(soname,fnname) ( void* ptrV, SizeT new_size=
);\
+ void* VG_REPLACE_FUNCTION(soname,fnname) ( void* ptrV, SizeT new_size=
) \
{ \
void* v; \
\
@@ -356,9 +309,9 @@
if (ptrV =3D=3D NULL) \
/* We need to call a malloc-like function; so let's use \
one which we know exists. */ \
- return ENCODE(libcZdsoZd6,malloc) (new_size); \
+ return VG_REPLACE_FUNCTION(libcZdsoZd6,malloc) (new_size); \
if (new_size <=3D 0) { \
- ENCODE(libcZdsoZd6,free)(ptrV); \
+ VG_REPLACE_FUNCTION(libcZdsoZd6,free)(ptrV); \
if (info.clo_trace_malloc) \
internal_printf(" =3D 0" ); \
return NULL; \
@@ -374,8 +327,8 @@
=20
#define MEMALIGN(soname, fnname) \
\
- void* ENCODE(soname,fnname) ( SizeT alignment, SizeT n ); \
- void* ENCODE(soname,fnname) ( SizeT alignment, SizeT n ) \
+ void* VG_REPLACE_FUNCTION(soname,fnname) ( SizeT alignment, SizeT n )=
; \
+ void* VG_REPLACE_FUNCTION(soname,fnname) ( SizeT alignment, SizeT n )=
\
{ \
void* v; \
\
@@ -400,10 +353,10 @@
=20
#define VALLOC(soname, fnname) \
\
- void* ENCODE(soname,fnname) ( SizeT size ); \
- void* ENCODE(soname,fnname) ( SizeT size ) \
+ void* VG_REPLACE_FUNCTION(soname,fnname) ( SizeT size ); \
+ void* VG_REPLACE_FUNCTION(soname,fnname) ( SizeT size ) \
{ \
- return ENCODE(libcZdsoZd6,memalign)(VKI_PAGE_SIZE, size); \
+ return VG_REPLACE_FUNCTION(libcZdsoZd6,memalign)(VKI_PAGE_SIZE, si=
ze); \
}
=20
VALLOC(m_libc_dot_so_dot_6, valloc);
@@ -413,8 +366,8 @@
=20
#define MALLOPT(soname, fnname) \
\
- int ENCODE(soname, fnname) ( int cmd, int value ); \
- int ENCODE(soname, fnname) ( int cmd, int value ) \
+ int VG_REPLACE_FUNCTION(soname, fnname) ( int cmd, int value ); \
+ int VG_REPLACE_FUNCTION(soname, fnname) ( int cmd, int value ) \
{ \
/* In glibc-2.2.4, 1 denotes a successful return value for \
mallopt */ \
@@ -426,8 +379,8 @@
=20
#define POSIX_MEMALIGN(soname, fnname) \
\
- int ENCODE(soname, fnname) ( void **memptr, SizeT alignment, SizeT si=
ze ); \
- int ENCODE(soname, fnname) ( void **memptr, SizeT alignment, SizeT si=
ze ) \
+ int VG_REPLACE_FUNCTION(soname, fnname) ( void **memptr, SizeT alignm=
ent, SizeT size ); \
+ int VG_REPLACE_FUNCTION(soname, fnname) ( void **memptr, SizeT alignm=
ent, SizeT size ) \
{ \
void *mem; \
\
@@ -437,7 +390,7 @@
|| (alignment & (alignment - 1)) !=3D 0) \
return VKI_EINVAL; \
\
- mem =3D ENCODE(libcZdsoZd6,memalign)(alignment, size); \
+ mem =3D VG_REPLACE_FUNCTION(libcZdsoZd6,memalign)(alignment, size)=
; \
\
if (mem !=3D NULL) { \
*memptr =3D mem; \
@@ -452,8 +405,8 @@
=20
#define MALLOC_USABLE_SIZE(soname, fnname) \
\
- int ENCODE(soname, fnname) ( void* p ); \
- int ENCODE(soname, fnname) ( void* p ) \
+ int VG_REPLACE_FUNCTION(soname, fnname) ( void* p ); \
+ int VG_REPLACE_FUNCTION(soname, fnname) ( void* p ) \
{ \
SizeT pszB; \
\
@@ -483,8 +436,8 @@
=20
#define PANIC(soname, fnname) \
\
- void ENCODE(soname, fnname) ( void ); \
- void ENCODE(soname, fnname) ( void ) \
+ void VG_REPLACE_FUNCTION(soname, fnname) ( void ); \
+ void VG_REPLACE_FUNCTION(soname, fnname) ( void ) \
{ \
panic(#fnname); \
}
@@ -516,8 +469,8 @@
=20
#define MALLINFO(soname, fnname) \
\
- struct mallinfo ENCODE(soname, fnname) ( void ); \
- struct mallinfo ENCODE(soname, fnname) ( void ) \
+ struct mallinfo VG_REPLACE_FUNCTION(soname, fnname) ( void ); \
+ struct mallinfo VG_REPLACE_FUNCTION(soname, fnname) ( void ) \
{ \
/* Should really try to return something a bit more meaningful */ =
\
UInt i; \
Modified: trunk/coregrind/m_syscalls/syscalls-generic.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_syscalls/syscalls-generic.c 2005-06-15 21:34:35 UTC=
(rev 3915)
+++ trunk/coregrind/m_syscalls/syscalls-generic.c 2005-06-16 03:56:58 UTC=
(rev 3916)
@@ -2320,8 +2320,8 @@
VG_(reap_threads)(tid);
=20
{ // Remove the valgrind-specific stuff from the environment so the
- // child doesn't get vg_inject.so, vgpreload.so, etc. This is
- // done unconditionally, since if we are tracing the child,
+ // child doesn't get vg_preload_core.so, vg_preload_TOOL.so, etc. =20
+ // This is done unconditionally, since if we are tracing the child,
// stage1/2 will set up the appropriate client environment.
Char** envp =3D (Char**)ARG3;
if (envp !=3D NULL) {
Modified: trunk/coregrind/pub_core_main.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_main.h 2005-06-15 21:34:35 UTC (rev 3915)
+++ trunk/coregrind/pub_core_main.h 2005-06-16 03:56:58 UTC (rev 3916)
@@ -54,8 +54,8 @@
/* 64-bit counter for the number of basic blocks done. */
extern ULong VG_(bbs_done);
=20
-// Set up the libc freeres wrapper (XXX: currently unused -- ?!)
-extern void VGA_(intercept_libc_freeres_wrapper)(Addr);
+// Set up the libc freeres wrapper=20
+extern void VG_(set_libc_freeres_wrapper_addr)(Addr);
=20
#endif // __PUB_CORE_MAIN_H
=20
Modified: trunk/coregrind/pub_core_redir.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_redir.h 2005-06-15 21:34:35 UTC (rev 3915)
+++ trunk/coregrind/pub_core_redir.h 2005-06-16 03:56:58 UTC (rev 3916)
@@ -33,26 +33,69 @@
=20
//--------------------------------------------------------------------
// PURPOSE: This module deals with:
-// - code redirection: intercepting calls to client functions, and
+// - code replacement: intercepting calls to client functions, and
// pointing them to a different piece of code.
+// - loading notification: telling the core where certain client-space
+// functions are when they get loaded.
// - function wrapping: add calls to code before and after client
// functions execute, for inspection and/or modification.
//
-// Nb: It's possible that this should be two modules.
+// It's possible that this should be two or three modules.
//--------------------------------------------------------------------
=20
-/* Redirection machinery */
+#include "pub_tool_redir.h"
+
+//--------------------------------------------------------------------
+// General
+//--------------------------------------------------------------------
+
+// This module needs be told about all the symbols that get loaded, so=20
+// it can check if it needs to do anything special. This is the functio=
n
+// that does that checking. It modifies 'symbol' in-place by Z-decoding
+// it if necessary.
+void VG_(maybe_redir_or_notify) ( Char* symbol, Addr addr );
+
+//--------------------------------------------------------------------
+// Code replacement
+//--------------------------------------------------------------------
+
+// See include/pub_tool_redir.h for details on how to do code replacemen=
t.
+
+// This is the crucial redirection function. It answers the question:=20
+// should this code address be redirected somewhere else? It's used jus=
t
+// before translating a basic block.
extern Addr VG_(code_redirect) ( Addr orig );
=20
/* Set up some default redirects */
extern void VG_(setup_code_redirect_table) ( void );
=20
-extern void VG_(add_redirect_sym_to_addr)(const Char *from_lib,
- const Char *from_sym,
- Addr to_addr);
-extern void VG_(add_redirect_addr_to_addr)(Addr from_addr, Addr to_addr)=
;
extern void VG_(resolve_seg_redirs)(SegInfo *si);
=20
+
+//--------------------------------------------------------------------
+// Loading notification
+//--------------------------------------------------------------------
+
+/* Functions named with this macro have the property that the core will
+ be told what their address is when they are loaded. This can be usef=
ul
+ if the core wants...
[truncated message content] |