514 lines
19 KiB
Diff
514 lines
19 KiB
Diff
--- valgrind/memcheck/mc_replace_strmem.c (revision 10919)
|
|
+++ valgrind/memcheck/mc_replace_strmem.c (revision 10923)
|
|
@@ -116,6 +116,7 @@ Bool is_overlap ( void* dst, const void*
|
|
STRRCHR(VG_Z_LIBC_SONAME, strrchr)
|
|
STRRCHR(VG_Z_LIBC_SONAME, rindex)
|
|
#if defined(VGO_linux)
|
|
+STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
|
|
STRRCHR(VG_Z_LD_LINUX_SO_2, rindex)
|
|
#elif defined(VGO_darwin)
|
|
STRRCHR(VG_Z_DYLD, strrchr)
|
|
@@ -140,6 +141,7 @@ STRRCHR(VG_Z_DYLD, rindex)
|
|
STRCHR(VG_Z_LIBC_SONAME, strchr)
|
|
STRCHR(VG_Z_LIBC_SONAME, index)
|
|
#if defined(VGO_linux)
|
|
+STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
|
|
STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
|
|
STRCHR(VG_Z_LD_LINUX_SO_2, index)
|
|
STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
|
|
@@ -172,7 +174,9 @@ STRCHR(VG_Z_DYLD, index)
|
|
}
|
|
|
|
STRCAT(VG_Z_LIBC_SONAME, strcat)
|
|
-
|
|
+#if defined(VGO_linux)
|
|
+STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
|
|
+#endif
|
|
|
|
#define STRNCAT(soname, fnname) \
|
|
char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
|
|
@@ -257,6 +261,9 @@ STRLCAT(VG_Z_DYLD, strlcat)
|
|
}
|
|
|
|
STRNLEN(VG_Z_LIBC_SONAME, strnlen)
|
|
+#if defined(VGO_linux)
|
|
+STRNLEN(VG_Z_LIBC_SONAME, __GI_strnlen)
|
|
+#endif
|
|
|
|
|
|
// Note that this replacement often doesn't get used because gcc inlines
|
|
@@ -274,6 +281,7 @@ STRNLEN(VG_Z_LIBC_SONAME, strnlen)
|
|
|
|
STRLEN(VG_Z_LIBC_SONAME, strlen)
|
|
#if defined(VGO_linux)
|
|
+STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
|
|
STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
|
|
STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
|
|
#endif
|
|
@@ -301,7 +309,9 @@ STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen
|
|
}
|
|
|
|
STRCPY(VG_Z_LIBC_SONAME, strcpy)
|
|
-#if defined(VGO_darwin)
|
|
+#if defined(VGO_linux)
|
|
+STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
|
|
+#elif defined(VGO_darwin)
|
|
STRCPY(VG_Z_DYLD, strcpy)
|
|
#endif
|
|
|
|
@@ -327,7 +337,9 @@ STRCPY(VG_Z_DYLD, strcpy)
|
|
}
|
|
|
|
STRNCPY(VG_Z_LIBC_SONAME, strncpy)
|
|
-#if defined(VGO_darwin)
|
|
+#if defined(VGO_linux)
|
|
+STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
|
|
+#elif defined(VGO_darwin)
|
|
STRNCPY(VG_Z_DYLD, strncpy)
|
|
#endif
|
|
|
|
@@ -384,7 +396,9 @@ STRLCPY(VG_Z_DYLD, strlcpy)
|
|
}
|
|
|
|
STRNCMP(VG_Z_LIBC_SONAME, strncmp)
|
|
-#if defined(VGO_darwin)
|
|
+#if defined(VGO_linux)
|
|
+STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
|
|
+#elif defined(VGO_darwin)
|
|
STRNCMP(VG_Z_DYLD, strncmp)
|
|
#endif
|
|
|
|
@@ -411,6 +425,7 @@ STRNCMP(VG_Z_DYLD, strncmp)
|
|
|
|
STRCMP(VG_Z_LIBC_SONAME, strcmp)
|
|
#if defined(VGO_linux)
|
|
+STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
|
|
STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
|
|
STRCMP(VG_Z_LD64_SO_1, strcmp)
|
|
#endif
|
|
@@ -557,6 +572,7 @@ MEMCMP(VG_Z_DYLD, bcmp)
|
|
|
|
STPCPY(VG_Z_LIBC_SONAME, stpcpy)
|
|
#if defined(VGO_linux)
|
|
+STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
|
|
STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
|
|
STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
|
|
#elif defined(VGO_darwin)
|
|
@@ -709,7 +725,9 @@ GLIBC232_STRCHRNUL(VG_Z_LIBC_SONAME, str
|
|
}
|
|
|
|
GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr)
|
|
-
|
|
+#if defined (VGO_linux)
|
|
+GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr)
|
|
+#endif
|
|
|
|
/* glibc variant of strcpy that checks the dest is big enough.
|
|
Copied from glibc-2.5/debug/test-strcpy_chk.c. */
|
|
--- valgrind/include/pub_tool_debuginfo.h (revision 10919)
|
|
+++ valgrind/include/pub_tool_debuginfo.h (revision 10923)
|
|
@@ -212,7 +212,8 @@ void VG_(DebugInfo_syms_getidx) ( const
|
|
/*OUT*/Addr* tocptr,
|
|
/*OUT*/UInt* size,
|
|
/*OUT*/HChar** name,
|
|
- /*OUT*/Bool* isText );
|
|
+ /*OUT*/Bool* isText,
|
|
+ /*OUT*/Bool* isIFunc );
|
|
|
|
/* A simple enumeration to describe the 'kind' of various kinds of
|
|
segments that arise from the mapping of object files. */
|
|
--- valgrind/coregrind/vg_preloaded.c (revision 10919)
|
|
+++ valgrind/coregrind/vg_preloaded.c (revision 10923)
|
|
@@ -47,12 +47,12 @@
|
|
#include "pub_core_debuginfo.h" // Needed for pub_core_redir.h
|
|
#include "pub_core_redir.h" // For VG_NOTIFY_ON_LOAD
|
|
|
|
+#if defined(VGO_linux) || defined(VGO_aix5)
|
|
+
|
|
/* ---------------------------------------------------------------------
|
|
Hook for running __libc_freeres once the program exits.
|
|
------------------------------------------------------------------ */
|
|
|
|
-#if defined(VGO_linux) || defined(VGO_aix5)
|
|
-
|
|
void VG_NOTIFY_ON_LOAD(freeres)( void );
|
|
void VG_NOTIFY_ON_LOAD(freeres)( void )
|
|
{
|
|
@@ -68,6 +68,31 @@ void VG_NOTIFY_ON_LOAD(freeres)( void )
|
|
*(int *)0 = 'x';
|
|
}
|
|
|
|
+/* ---------------------------------------------------------------------
|
|
+ Wrapper for indirect functions which need to be redirected.
|
|
+ ------------------------------------------------------------------ */
|
|
+
|
|
+void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void);
|
|
+void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void)
|
|
+{
|
|
+ OrigFn fn;
|
|
+ Addr result = 0;
|
|
+ int res;
|
|
+
|
|
+ /* Call the original indirect function and get it's result */
|
|
+ VALGRIND_GET_ORIG_FN(fn);
|
|
+ CALL_FN_W_v(result, fn);
|
|
+
|
|
+ /* Ask the valgrind core running on the real CPU (as opposed to this
|
|
+ code which runs on the emulated CPU) to update the redirection that
|
|
+ led to this function. This client request eventually gives control to
|
|
+ the function VG_(redir_add_ifunc_target) in m_redir.c */
|
|
+ VALGRIND_DO_CLIENT_REQUEST(res, 0,
|
|
+ VG_USERREQ__ADD_IFUNC_TARGET,
|
|
+ fn.nraddr, result, 0, 0, 0);
|
|
+ return result;
|
|
+}
|
|
+
|
|
#elif defined(VGO_darwin)
|
|
|
|
/* ---------------------------------------------------------------------
|
|
--- valgrind/coregrind/pub_core_clreq.h (revision 10919)
|
|
+++ valgrind/coregrind/pub_core_clreq.h (revision 10923)
|
|
@@ -50,6 +50,9 @@ typedef
|
|
/* Internal equivalent of VALGRIND_PRINTF . */
|
|
VG_USERREQ__INTERNAL_PRINTF = 0x3103,
|
|
|
|
+ /* Add a target for an indirect function redirection. */
|
|
+ VG_USERREQ__ADD_IFUNC_TARGET = 0x3104,
|
|
+
|
|
} Vg_InternalClientRequest;
|
|
|
|
// Function for printing from code within Valgrind, but which runs on the
|
|
--- valgrind/coregrind/m_debuginfo/debuginfo.c (revision 10919)
|
|
+++ valgrind/coregrind/m_debuginfo/debuginfo.c (revision 10923)
|
|
@@ -3435,14 +3435,16 @@ void VG_(DebugInfo_syms_getidx) ( const
|
|
/*OUT*/Addr* tocptr,
|
|
/*OUT*/UInt* size,
|
|
/*OUT*/HChar** name,
|
|
- /*OUT*/Bool* isText )
|
|
+ /*OUT*/Bool* isText,
|
|
+ /*OUT*/Bool* isIFunc )
|
|
{
|
|
vg_assert(idx >= 0 && idx < si->symtab_used);
|
|
- if (avma) *avma = si->symtab[idx].addr;
|
|
- if (tocptr) *tocptr = si->symtab[idx].tocptr;
|
|
- if (size) *size = si->symtab[idx].size;
|
|
- if (name) *name = (HChar*)si->symtab[idx].name;
|
|
- if (isText) *isText = si->symtab[idx].isText;
|
|
+ if (avma) *avma = si->symtab[idx].addr;
|
|
+ if (tocptr) *tocptr = si->symtab[idx].tocptr;
|
|
+ if (size) *size = si->symtab[idx].size;
|
|
+ if (name) *name = (HChar*)si->symtab[idx].name;
|
|
+ if (isText) *isText = si->symtab[idx].isText;
|
|
+ if (isIFunc) *isIFunc = si->symtab[idx].isIFunc;
|
|
}
|
|
|
|
|
|
--- valgrind/coregrind/m_debuginfo/readelf.c (revision 10919)
|
|
+++ valgrind/coregrind/m_debuginfo/readelf.c (revision 10923)
|
|
@@ -214,7 +214,8 @@ Bool get_elf_symbol_info (
|
|
used on entry */
|
|
Bool* from_opd_out, /* ppc64-linux only: did we deref an
|
|
.opd entry? */
|
|
- Bool* is_text_out /* is this a text symbol? */
|
|
+ Bool* is_text_out, /* is this a text symbol? */
|
|
+ Bool* is_ifunc /* is this a STT_GNU_IFUNC function ?*/
|
|
)
|
|
{
|
|
Bool plausible;
|
|
@@ -232,6 +233,7 @@ Bool get_elf_symbol_info (
|
|
*sym_size_out = (Int)sym->st_size;
|
|
*sym_tocptr_out = 0; /* unknown/inapplicable */
|
|
*from_opd_out = False;
|
|
+ *is_ifunc = False;
|
|
|
|
/* Figure out if we're interested in the symbol. Firstly, is it of
|
|
the right flavour? */
|
|
@@ -243,6 +245,9 @@ Bool get_elf_symbol_info (
|
|
&&
|
|
(ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
|
|
|| ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
|
|
+#ifdef STT_GNU_IFUNC
|
|
+ || ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC
|
|
+#endif
|
|
);
|
|
|
|
/* Work out the svma and bias for each section as it will appear in
|
|
@@ -325,6 +330,14 @@ Bool get_elf_symbol_info (
|
|
*sym_avma_out += text_bias;
|
|
}
|
|
|
|
+# ifdef STT_GNU_IFUNC
|
|
+ /* Check for indirect functions. */
|
|
+ if (*is_text_out
|
|
+ && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
|
|
+ *is_ifunc = True;
|
|
+ }
|
|
+# endif
|
|
+
|
|
# if defined(VGP_ppc64_linux)
|
|
/* Allow STT_NOTYPE in the very special case where we're running on
|
|
ppc64-linux and the symbol is one which the .opd-chasing hack
|
|
@@ -570,7 +583,7 @@ void read_elf_symtab__normal(
|
|
Char *sym_name, *sym_name_really;
|
|
Int sym_size;
|
|
Addr sym_tocptr;
|
|
- Bool from_opd, is_text;
|
|
+ Bool from_opd, is_text, is_ifunc;
|
|
DiSym risym;
|
|
ElfXX_Sym *sym;
|
|
|
|
@@ -602,13 +615,14 @@ void read_elf_symtab__normal(
|
|
&sym_avma_really,
|
|
&sym_size,
|
|
&sym_tocptr,
|
|
- &from_opd, &is_text)) {
|
|
+ &from_opd, &is_text, &is_ifunc)) {
|
|
|
|
- risym.addr = sym_avma_really;
|
|
- risym.size = sym_size;
|
|
- risym.name = ML_(addStr) ( di, sym_name_really, -1 );
|
|
- risym.tocptr = sym_tocptr;
|
|
- risym.isText = is_text;
|
|
+ risym.addr = sym_avma_really;
|
|
+ risym.size = sym_size;
|
|
+ risym.name = ML_(addStr) ( di, sym_name_really, -1 );
|
|
+ risym.tocptr = sym_tocptr;
|
|
+ risym.isText = is_text;
|
|
+ risym.isIFunc = is_ifunc;
|
|
vg_assert(risym.name != NULL);
|
|
vg_assert(risym.tocptr == 0); /* has no role except on ppc64-linux */
|
|
ML_(addSym) ( di, &risym );
|
|
@@ -646,6 +660,7 @@ typedef
|
|
Int size;
|
|
Bool from_opd;
|
|
Bool is_text;
|
|
+ Bool is_ifunc;
|
|
}
|
|
TempSym;
|
|
|
|
@@ -671,7 +686,7 @@ void read_elf_symtab__ppc64_linux(
|
|
Char *sym_name, *sym_name_really;
|
|
Int sym_size;
|
|
Addr sym_tocptr;
|
|
- Bool from_opd, modify_size, modify_tocptr, is_text;
|
|
+ Bool from_opd, modify_size, modify_tocptr, is_text, is_ifunc;
|
|
DiSym risym;
|
|
ElfXX_Sym *sym;
|
|
OSet *oset;
|
|
@@ -713,7 +728,7 @@ void read_elf_symtab__ppc64_linux(
|
|
&sym_avma_really,
|
|
&sym_size,
|
|
&sym_tocptr,
|
|
- &from_opd, &is_text)) {
|
|
+ &from_opd, &is_text, &is_ifunc)) {
|
|
|
|
/* Check if we've seen this (name,addr) key before. */
|
|
key.addr = sym_avma_really;
|
|
@@ -785,6 +800,7 @@ void read_elf_symtab__ppc64_linux(
|
|
elem->size = sym_size;
|
|
elem->from_opd = from_opd;
|
|
elem->is_text = is_text;
|
|
+ elem->is_ifunc = is_ifunc;
|
|
VG_(OSetGen_Insert)(oset, elem);
|
|
if (di->trace_symtab) {
|
|
VG_(printf)(" to-oset [%4ld]: "
|
|
@@ -808,11 +824,12 @@ void read_elf_symtab__ppc64_linux(
|
|
VG_(OSetGen_ResetIter)( oset );
|
|
|
|
while ( (elem = VG_(OSetGen_Next)(oset)) ) {
|
|
- risym.addr = elem->key.addr;
|
|
- risym.size = elem->size;
|
|
- risym.name = ML_(addStr) ( di, elem->key.name, -1 );
|
|
- risym.tocptr = elem->tocptr;
|
|
- risym.isText = elem->is_text;
|
|
+ risym.addr = elem->key.addr;
|
|
+ risym.size = elem->size;
|
|
+ risym.name = ML_(addStr) ( di, elem->key.name, -1 );
|
|
+ risym.tocptr = elem->tocptr;
|
|
+ risym.isText = elem->is_text;
|
|
+ risym.isIFunc = elem->is_ifunc;
|
|
vg_assert(risym.name != NULL);
|
|
|
|
ML_(addSym) ( di, &risym );
|
|
--- valgrind/coregrind/m_debuginfo/priv_storage.h (revision 10919)
|
|
+++ valgrind/coregrind/m_debuginfo/priv_storage.h (revision 10923)
|
|
@@ -48,15 +48,16 @@
|
|
/* A structure to hold an ELF/XCOFF symbol (very crudely). */
|
|
typedef
|
|
struct {
|
|
- Addr addr; /* lowest address of entity */
|
|
- Addr tocptr; /* ppc64-linux only: value that R2 should have */
|
|
- UChar *name; /* name */
|
|
+ Addr addr; /* lowest address of entity */
|
|
+ Addr tocptr; /* ppc64-linux only: value that R2 should have */
|
|
+ UChar *name; /* name */
|
|
// XXX: this could be shrunk (on 32-bit platforms) by using 31 bits for
|
|
// the size and 1 bit for the isText. If you do this, make sure that
|
|
// all assignments to isText use 0 or 1 (or True or False), and that a
|
|
// positive number larger than 1 is never used to represent True.
|
|
- UInt size; /* size in bytes */
|
|
+ UInt size; /* size in bytes */
|
|
Bool isText;
|
|
+ Bool isIFunc; /* symbol is an indirect function? */
|
|
}
|
|
DiSym;
|
|
|
|
--- valgrind/coregrind/m_redir.c (revision 10919)
|
|
+++ valgrind/coregrind/m_redir.c (revision 10923)
|
|
@@ -268,12 +268,15 @@ typedef
|
|
TopSpec* parent_spec; /* the TopSpec which supplied the Spec */
|
|
TopSpec* parent_sym; /* the TopSpec which supplied the symbol */
|
|
Bool isWrap; /* wrap or replacement? */
|
|
+ Bool isIFunc; /* indirect function? */
|
|
}
|
|
Active;
|
|
|
|
/* The active set is a fast lookup table */
|
|
static OSet* activeSet = NULL;
|
|
|
|
+/* Wrapper routine for indirect functions */
|
|
+static Addr iFuncWrapper;
|
|
|
|
/*------------------------------------------------------------*/
|
|
/*--- FWDses ---*/
|
|
@@ -350,8 +353,8 @@ void VG_(redir_notify_new_DebugInfo)( De
|
|
|
|
nsyms = VG_(DebugInfo_syms_howmany)( newsi );
|
|
for (i = 0; i < nsyms; i++) {
|
|
- VG_(DebugInfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,
|
|
- NULL, &sym_name, &isText );
|
|
+ VG_(DebugInfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,
|
|
+ NULL, &sym_name, &isText, NULL );
|
|
ok = VG_(maybe_Z_demangle)( sym_name, demangled_sopatt, N_DEMANGLED,
|
|
demangled_fnpatt, N_DEMANGLED, &isWrap );
|
|
/* ignore data symbols */
|
|
@@ -388,8 +391,8 @@ void VG_(redir_notify_new_DebugInfo)( De
|
|
|
|
if (check_ppcTOCs) {
|
|
for (i = 0; i < nsyms; i++) {
|
|
- VG_(DebugInfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,
|
|
- NULL, &sym_name, &isText );
|
|
+ VG_(DebugInfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,
|
|
+ NULL, &sym_name, &isText, NULL );
|
|
ok = isText
|
|
&& VG_(maybe_Z_demangle)(
|
|
sym_name, demangled_sopatt, N_DEMANGLED,
|
|
@@ -470,6 +473,30 @@ void VG_(redir_notify_new_DebugInfo)( De
|
|
|
|
#undef N_DEMANGLED
|
|
|
|
+/* Add a new target for an indirect function. Adds a new redirection
|
|
+ for the indirection function with address old_from that redirects
|
|
+ the ordinary function with address new_from to the target address
|
|
+ of the original redirection. */
|
|
+
|
|
+void VG_(redir_add_ifunc_target)( Addr old_from, Addr new_from )
|
|
+{
|
|
+ Active *old, new;
|
|
+
|
|
+ old = VG_(OSetGen_Lookup)(activeSet, &old_from);
|
|
+ vg_assert(old);
|
|
+ vg_assert(old->isIFunc);
|
|
+
|
|
+ new = *old;
|
|
+ new.from_addr = new_from;
|
|
+ new.isIFunc = False;
|
|
+ maybe_add_active (new);
|
|
+
|
|
+ if (VG_(clo_trace_redir)) {
|
|
+ VG_(message)( Vg_DebugMsg,
|
|
+ "Adding redirect for indirect function 0x%llx from 0x%llx -> 0x%llx\n",
|
|
+ (ULong)old_from, (ULong)new_from, (ULong)new.to_addr );
|
|
+ }
|
|
+}
|
|
|
|
/* Do one element of the basic cross product: add to the active set,
|
|
all matches resulting from comparing all the given specs against
|
|
@@ -487,7 +514,7 @@ void generate_and_add_actives (
|
|
)
|
|
{
|
|
Spec* sp;
|
|
- Bool anyMark, isText;
|
|
+ Bool anyMark, isText, isIFunc;
|
|
Active act;
|
|
Int nsyms, i;
|
|
Addr sym_addr;
|
|
@@ -513,7 +540,7 @@ void generate_and_add_actives (
|
|
nsyms = VG_(DebugInfo_syms_howmany)( di );
|
|
for (i = 0; i < nsyms; i++) {
|
|
VG_(DebugInfo_syms_getidx)( di, i, &sym_addr, NULL, NULL,
|
|
- &sym_name, &isText );
|
|
+ &sym_name, &isText, &isIFunc );
|
|
|
|
/* ignore data symbols */
|
|
if (!isText)
|
|
@@ -539,6 +566,7 @@ void generate_and_add_actives (
|
|
act.parent_spec = parent_spec;
|
|
act.parent_sym = parent_sym;
|
|
act.isWrap = sp->isWrap;
|
|
+ act.isIFunc = isIFunc;
|
|
sp->done = True;
|
|
maybe_add_active( act );
|
|
}
|
|
@@ -780,7 +808,9 @@ Addr VG_(redir_do_lookup) ( Addr orig, B
|
|
|
|
vg_assert(r->to_addr != 0);
|
|
if (isWrap)
|
|
- *isWrap = r->isWrap;
|
|
+ *isWrap = r->isWrap || r->isIFunc;
|
|
+ if (r->isIFunc)
|
|
+ return iFuncWrapper;
|
|
return r->to_addr;
|
|
}
|
|
|
|
@@ -800,6 +830,7 @@ static void add_hardwired_active ( Addr
|
|
act.parent_spec = NULL;
|
|
act.parent_sym = NULL;
|
|
act.isWrap = False;
|
|
+ act.isIFunc = False;
|
|
maybe_add_active( act );
|
|
}
|
|
|
|
@@ -1096,6 +1127,8 @@ void handle_maybe_load_notifier( const U
|
|
|
|
if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(freeres))) == 0)
|
|
VG_(client___libc_freeres_wrapper) = addr;
|
|
+ else if (VG_(strcmp)(symbol, VG_STRINGIFY(VG_NOTIFY_ON_LOAD(ifunc_wrapper))) == 0)
|
|
+ iFuncWrapper = addr;
|
|
else
|
|
vg_assert2(0, "unrecognised load notification function: %s", symbol);
|
|
}
|
|
--- valgrind/coregrind/pub_core_redir.h (revision 10919)
|
|
+++ valgrind/coregrind/pub_core_redir.h (revision 10923)
|
|
@@ -58,6 +58,8 @@ extern void VG_(redir_notify_delete_Debu
|
|
/* Initialise the module, and load initial "hardwired" redirects. */
|
|
extern void VG_(redir_initialise)( void );
|
|
|
|
+/* Notify the module of a new target for an indirect function. */
|
|
+extern void VG_(redir_add_ifunc_target)( Addr old_from, Addr new_from );
|
|
|
|
//--------------------------------------------------------------------
|
|
// Queries
|
|
--- valgrind/coregrind/m_scheduler/scheduler.c (revision 10919)
|
|
+++ valgrind/coregrind/m_scheduler/scheduler.c (revision 10923)
|
|
@@ -89,6 +89,7 @@
|
|
#include "pub_core_debuginfo.h" // VG_(di_notify_pdb_debuginfo)
|
|
#include "priv_sema.h"
|
|
#include "pub_core_scheduler.h" // self
|
|
+#include "pub_core_redir.h"
|
|
|
|
|
|
/* ---------------------------------------------------------------------
|
|
@@ -1399,6 +1400,11 @@ void do_client_request ( ThreadId tid )
|
|
SET_CLREQ_RETVAL( tid, count );
|
|
break; }
|
|
|
|
+ case VG_USERREQ__ADD_IFUNC_TARGET: {
|
|
+ VG_(redir_add_ifunc_target)( arg[1], arg[2] );
|
|
+ SET_CLREQ_RETVAL( tid, 0);
|
|
+ break; }
|
|
+
|
|
case VG_USERREQ__PRINTF_BACKTRACE: {
|
|
Int count =
|
|
VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], (void*)arg[2] );
|