rpms/valgrind/F-12 valgrind-3.5.0-ifunc.patch, NONE, 1.1 valgrind-3.5.0-inotify-init1.patch, NONE, 1.1 valgrind-3.5.0-mmap-mprotect.patch, NONE, 1.1 valgrind.spec, 1.67, 1.68
Jakub Jelinek
jakub at fedoraproject.org
Mon Oct 12 15:18:45 UTC 2009
Author: jakub
Update of /cvs/pkgs/rpms/valgrind/F-12
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv3635
Modified Files:
valgrind.spec
Added Files:
valgrind-3.5.0-ifunc.patch valgrind-3.5.0-inotify-init1.patch
valgrind-3.5.0-mmap-mprotect.patch
Log Message:
3.5.0-2
valgrind-3.5.0-ifunc.patch:
coregrind/m_debuginfo/debuginfo.c | 14 ++--
coregrind/m_debuginfo/priv_storage.h | 1
coregrind/m_debuginfo/readelf.c | 22 +++++--
coregrind/m_demangle/demangle.c | 52 ++++++++++++----
coregrind/m_redir.c | 109 +++++++++++++++++++++++++++++++----
coregrind/m_scheduler/scheduler.c | 6 +
coregrind/pub_core_clreq.h | 5 +
coregrind/pub_core_demangle.h | 3
coregrind/pub_core_redir.h | 3
coregrind/vg_preloaded.c | 27 ++++++++
include/pub_tool_debuginfo.h | 3
include/pub_tool_redir.h | 25 +++++++-
memcheck/mc_replace_strmem.c | 24 ++++++-
13 files changed, 251 insertions(+), 43 deletions(-)
--- NEW FILE valgrind-3.5.0-ifunc.patch ---
commit 27dc1029d4bca6409d0ed990264592dc75761cd0
Author: Dodji Seketeli <dodji at redhat.com>
Date: Wed Oct 7 16:09:30 2009 +0200
Candidate patch for vgbz 206013
This patch
1/ Intercepts the call to the indirect function of type STT_GNU_IFUNC
and gets the returned function pointer
2/ Redirects the returned function pointer to whatever function the
indirect function was redirected to.
To do this, we first makes valgrind recognize STT_GNU_IFUNC functions.
Then we wrap all indirect functions by a magic wrapper that does 1/ and 2/
Please find below a detailed GNU style ChangeLog accompanying the patch.
* coregrind/m_debuginfo/priv_storage.h (struct DiSym): Add an
isIndirectFunc field to indicate if the symbol is an indirect
function.
* coregrind/m_debuginfo/readelf.c (get_elf_symbol_info):
Return a boolean to say if the symbol is an indirect function.
This is only on non-ppc64 linux systems only.
(read_elf_symtab__normal): Add indirect function flag to symbols.
(read_elf_symtab__ppc64_linux): Ignore indirect function stuff for
linux ppc64 for now.
* include/pub_tool_debuginfo.h (VG_(DebugInfo_syms_getidx)): Return a
boolean to say if the symbol is an indirect function.
* coregrind/m_debuginfo/debuginfo.c (VG_(DebugInfo_syms_getidx)):
Likewise.
* coregrind/pub_core_demangle.h (VG_(maybe_Z_demangle)): Add a boolean
indicated if the demangled symbol is an indirect function redirection
specification.
* coregrind/m_demangle/demangle.c (VG_(demangle)): Ignore indirect
functions demangling here.
(VG_(maybe_Z_demangle)): Add support for demangling indirect functions
wrapping/redirecting.
* include/pub_tool_redir.h: Add macros to define an indirection
function wrap or replacement.
* coregrind/m_redir.c (struct Spec): Add isIFunc to flag the
redirection specification as being related to an indirect function.
(struct Active): Likewise.
(iFuncToDirectFuncSet): New ordered set that holds
indirect function -> target mappings. Target here is the function
which the indirection function points to. The type of the mapping is
the struct IFuncToDirectFuncEntry.
(VG_(redir_notify_new_DebugInfo)): Update the list of redirection
specifications whenever a redirection specification symbol related
to an indirection (set with e.g VG_WRAP_I_FUNCTION_ZZ) appears.
function appears.
(VG_(redir_change_ifunc_target)): New function.
(generate_and_add_actives): Apply indirect function redirections
to indirect functions only. Also, consider cases where we are
requested a strlen -> vg_strlen redirection. Now, if strlen happens to
be an indirect function pointing to strlen_target, we need be able to
later set a strlen_target --> vg_strlen redirection. Here "later"
means once we have intercepted the strlen call by the runtime linker
to get the pointer to strlen_target. So we now store the strlen ->
vg_strlen redirection request in the iFuncToDirectFuncSet set so that
we can get it later.
* coregrind/m_scheduler/scheduler.c (do_client_request): Add a new
VG_USERREQ__CHANGE_IFUNC_REDIR_TARGET.
* coregrind/pub_core_clreq.h (enum Vg_InternalClientRequest): Add
VG_USERREQ__CHANGE_IFUNC_REDIR_TARGET.
* coregrind/vg_preloaded.c:
(VG_WRAP_I_FUNCTION_ZZ(VG_Z_LIBC_SONAME, Za) (void)): New indirect
function redirection.
* memcheck/mc_replace_strmem.c: Add a bunch of __GI_* replacement
functions.
diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index eed2ab1..c9a2e4e 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -3435,14 +3435,16 @@ void VG_(DebugInfo_syms_getidx) ( const DebugInfo *si,
/*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].isIndirectFunc;
}
diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
index f6e6e82..53223ad 100644
--- a/coregrind/m_debuginfo/priv_storage.h
+++ b/coregrind/m_debuginfo/priv_storage.h
@@ -57,6 +57,7 @@ typedef
// positive number larger than 1 is never used to represent True.
UInt size; /* size in bytes */
Bool isText;
+ Bool isIndirectFunc; /* true if symbol is of STT_GNU_IFUNC type */
}
DiSym;
diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
index 02cea02..51f3ddd 100644
--- a/coregrind/m_debuginfo/readelf.c
+++ b/coregrind/m_debuginfo/readelf.c
@@ -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_indirect_function /* is this a STT_GNU_IFUNC function ?*/
)
{
Bool plausible;
@@ -232,6 +233,8 @@ Bool get_elf_symbol_info (
*sym_size_out = (Int)sym->st_size;
*sym_tocptr_out = 0; /* unknown/inapplicable */
*from_opd_out = False;
+ if (is_indirect_function)
+ *is_indirect_function = False;
/* Figure out if we're interested in the symbol. Firstly, is it of
the right flavour? */
@@ -243,6 +246,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
@@ -324,6 +330,13 @@ Bool get_elf_symbol_info (
*is_text_out = True;
*sym_avma_out += text_bias;
}
+#ifdef STT_GNU_IFUNC
+ if (is_indirect_function
+ && *is_text_out
+ && ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
+ *is_indirect_function = True;
+ }
+#endif
# if defined(VGP_ppc64_linux)
/* Allow STT_NOTYPE in the very special case where we're running on
@@ -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_indirect_func = False;
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_indirect_func)) {
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.isIndirectFunc = is_indirect_func;
vg_assert(risym.name != NULL);
vg_assert(risym.tocptr == 0); /* has no role except on ppc64-linux */
ML_(addSym) ( di, &risym );
@@ -713,7 +727,7 @@ void read_elf_symtab__ppc64_linux(
&sym_avma_really,
&sym_size,
&sym_tocptr,
- &from_opd, &is_text)) {
+ &from_opd, &is_text,NULL)) {
/* Check if we've seen this (name,addr) key before. */
key.addr = sym_avma_really;
diff --git a/coregrind/m_demangle/demangle.c b/coregrind/m_demangle/demangle.c
index 262fcfc..3ae050a 100644
--- a/coregrind/m_demangle/demangle.c
+++ b/coregrind/m_demangle/demangle.c
@@ -100,7 +100,8 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
interested in that). */
if (do_z_demangling) {
if (VG_(maybe_Z_demangle)( orig, NULL,0,/*soname*/
- z_demangled, N_ZBUF, NULL)) {
+ z_demangled, N_ZBUF, NULL,
+ NULL)) {
orig = z_demangled;
}
}
@@ -146,7 +147,8 @@ void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
Bool VG_(maybe_Z_demangle) ( const HChar* sym,
/*OUT*/HChar* so, Int soLen,
/*OUT*/HChar* fn, Int fnLen,
- /*OUT*/Bool* isWrap )
+ /*OUT*/Bool* isWrap,
+ /*OUT*/Bool* isIFunc)
{
# define EMITSO(ch) \
do { \
@@ -167,15 +169,20 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym,
} \
} while (0)
- Bool error, oflow, valid, fn_is_encoded, is_VG_Z_prefixed;
- Int soi, fni, i;
+ Bool error, oflow, valid, indirect, fn_is_encoded,
+ is_VG_Z_prefixed;
+ Int soi, fni, i, encoded_index, wrap_index, soname_index;
vg_assert(soLen > 0 || (soLen == 0 && so == NULL));
vg_assert(fnLen > 0);
error = False;
oflow = False;
+ indirect = False;
soi = 0;
fni = 0;
+ encoded_index = 5;
+ wrap_index = 3;
+ soname_index = 7;
valid = sym[0] == '_'
&& sym[1] == 'v'
@@ -184,29 +191,46 @@ Bool VG_(maybe_Z_demangle) ( const HChar* sym,
&& sym[4] == 'Z'
&& (sym[5] == 'Z' || sym[5] == 'U')
&& sym[6] == '_';
- if (!valid)
- return False;
- fn_is_encoded = sym[5] == 'Z';
+ if (!valid) {
+ valid = sym[0] == '_'
+ && sym[1] == 'v'
+ && sym[2] == 'g'
+ && sym[3] == 'i'
+ && (sym[4] == 'r' || sym[4] == 'w' || sym[4] == 'n')
+ && sym[5] == 'Z'
+ && (sym[6] == 'Z' || sym[6] == 'U')
+ && sym[7] == '_';
+ if (!valid)
+ return False;
+ encoded_index = 6;
+ wrap_index = 4;
+ soname_index = 8;
+ indirect = True;
+ }
+
+ fn_is_encoded = sym[encoded_index] == 'Z';
if (isWrap)
- *isWrap = sym[3] == 'w';
+ *isWrap = sym[wrap_index] == 'w';
+ if (isIFunc)
+ *isIFunc = indirect;
/* Now check the soname prefix isn't "VG_Z_", as described in
pub_tool_redir.h. */
+ i = soname_index;
is_VG_Z_prefixed =
- sym[ 7] == 'V' &&
- sym[ 8] == 'G' &&
- sym[ 9] == '_' &&
- sym[10] == 'Z' &&
- sym[11] == '_';
+ sym[i] == 'V' &&
+ sym[i+1] == 'G' &&
+ sym[i+2] == '_' &&
+ sym[i+3] == 'Z' &&
+ sym[i+4] == '_';
if (is_VG_Z_prefixed) {
vg_assert2(0, "symbol with a 'VG_Z_' prefix: %s.\n"
"see pub_tool_redir.h for an explanation.", sym);
}
/* Now scan the Z-encoded soname. */
- i = 7;
while (True) {
if (sym[i] == '_')
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 98a502f..0140fc0 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -223,6 +223,7 @@ typedef
HChar* from_fnpatt; /* from fnname pattern */
Addr to_addr; /* where redirecting to */
Bool isWrap; /* wrap or replacement? */
+ Bool isIFunc; /* an indirect function? */
const HChar** mandatory; /* non-NULL ==> abort V and print the
strings if from_sopatt is loaded but
from_fnpatt cannot be found */
@@ -268,12 +269,20 @@ 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;
}
Active;
+typedef
+ struct {
+ Addr indirect_func;
+ Addr direct_func;
+ }
+ IFuncToDirectFuncEntry;
+
/* The active set is a fast lookup table */
static OSet* activeSet = NULL;
-
+static OSet* iFuncToDirectFuncSet = NULL;
/*------------------------------------------------------------*/
/*--- FWDses ---*/
@@ -317,7 +326,7 @@ void generate_and_add_actives (
void VG_(redir_notify_new_DebugInfo)( DebugInfo* newsi )
{
- Bool ok, isWrap;
+ Bool ok, isWrap, isIFuncRedirect = False;
Int i, nsyms;
Spec* specList;
Spec* spec;
@@ -350,10 +359,16 @@ void VG_(redir_notify_new_DebugInfo)( DebugInfo* newsi )
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 );
- ok = VG_(maybe_Z_demangle)( sym_name, demangled_sopatt, N_DEMANGLED,
- demangled_fnpatt, N_DEMANGLED, &isWrap );
+ 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,
+ &isIFuncRedirect );
/* ignore data symbols */
if (!isText)
continue;
@@ -378,6 +393,7 @@ void VG_(redir_notify_new_DebugInfo)( DebugInfo* newsi )
vg_assert(spec->from_fnpatt);
spec->to_addr = sym_addr;
spec->isWrap = isWrap;
+ spec->isIFunc = isIFuncRedirect;
/* check we're not adding manifestly stupid destinations */
vg_assert(is_plausible_guest_addr(sym_addr));
spec->next = specList;
@@ -388,12 +404,15 @@ void VG_(redir_notify_new_DebugInfo)( DebugInfo* newsi )
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,
- demangled_fnpatt, N_DEMANGLED, &isWrap );
+ demangled_fnpatt, N_DEMANGLED, &isWrap,
+ NULL );
if (!ok)
/* not a redirect. Ignore. */
continue;
@@ -470,6 +489,38 @@ void VG_(redir_notify_new_DebugInfo)( DebugInfo* newsi )
#undef N_DEMANGLED
+/* Consider the redirection old_from --> somefunction;
+ In that redirection, old_from is the address of an indirect function.
+ The target of that redirection was certainly a function declared with
+ VG_WRAP_I_FUNCTION_ZZ (look in vg_preloaded.c for instance).
+ This function then setups a new redirection new_from -> ifunc_target,
+ where ifunc_target is the target of the indirect function which address
+ is old_from. */
+void VG_(redir_change_ifunc_target)(Addr old_from,
+ Addr new_from)
+{
+ Active *old, new;
+ IFuncToDirectFuncEntry *e;
+
+ old = VG_(OSetGen_Lookup)(activeSet, &old_from);
+ vg_assert(old);
+ vg_assert(old->isIFunc);
+
+ e = VG_(OSetGen_Lookup)(iFuncToDirectFuncSet, &old_from);
+
+ new = *old;
+ if (e) {
+ new.from_addr = new_from;
+ new.to_addr = e->direct_func;
+ if (VG_(clo_trace_redir))
+ VG_(message) (Vg_DebugMsg, "changed redir (%lx)[indired]->(%lx) "
+ "to (%lx) -> (%lx))\n",
+ old_from, old->to_addr,
+ new_from, e->direct_func);
+ new.isIFunc = False;
+ maybe_add_active (new);
+ }
+}
/* 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 +538,7 @@ void generate_and_add_actives (
)
{
Spec* sp;
- Bool anyMark, isText;
+ Bool anyMark, isText, isIFunc = False;
Active act;
Int nsyms, i;
Addr sym_addr;
@@ -513,7 +564,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)
@@ -533,13 +584,47 @@ void generate_and_add_actives (
if (!sp->mark)
continue; /* soname doesn't match */
if (VG_(string_match)( sp->from_fnpatt, sym_name )) {
+ if (!isIFunc && sp->isIFunc)
+ continue;
+ sp->done = True;
+ if (isIFunc && !sp->isIFunc) {
+ IFuncToDirectFuncEntry *e;
+ /* So we are facing a redirection spec
+ indirect function -> direct function.
+ We need to store that mapping in iFuncToDirectFuncSet so
+ that later once the indirect function's relocations are
+ processed by the dynamic linker on the client, we
+ can set up a redirection from the target of the indirect
+ function to sp->to_addr. */
+ if (!iFuncToDirectFuncSet) {
+ iFuncToDirectFuncSet =
+ VG_(OSetGen_Create)(offsetof (IFuncToDirectFuncEntry,
+ indirect_func),
+ NULL /*ptr compare*/,
+ dinfo_zalloc,
+ "redir.ri.2",
+ dinfo_free);
+ vg_assert (iFuncToDirectFuncSet);
+ }
+ e = VG_(OSetGen_Lookup)(iFuncToDirectFuncSet, &sym_addr);
+ if (e)
+ continue;
+ e = VG_(OSetGen_AllocNode)(iFuncToDirectFuncSet,
+ sizeof (IFuncToDirectFuncEntry));
+ vg_assert (e);
+ e->indirect_func = sym_addr;
+ e->direct_func = sp->to_addr;
+ VG_(OSetGen_Insert)(iFuncToDirectFuncSet, e);
+ continue;
+ }
/* got a new binding. Add to collection. */
act.from_addr = sym_addr;
act.to_addr = sp->to_addr;
act.parent_spec = parent_spec;
act.parent_sym = parent_sym;
act.isWrap = sp->isWrap;
- sp->done = True;
+ if (isIFunc)
+ act.isIFunc = True;
maybe_add_active( act );
}
} /* for (sp = specs; sp; sp = sp->next) */
diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
index 295e0ab..4083034 100644
--- a/coregrind/m_scheduler/scheduler.c
+++ b/coregrind/m_scheduler/scheduler.c
@@ -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__CHANGE_IFUNC_REDIR_TARGET: {
+ VG_(redir_change_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] );
diff --git a/coregrind/pub_core_clreq.h b/coregrind/pub_core_clreq.h
index 563904b..f881ffe 100644
--- a/coregrind/pub_core_clreq.h
+++ b/coregrind/pub_core_clreq.h
@@ -50,6 +50,11 @@ typedef
/* Internal equivalent of VALGRIND_PRINTF . */
VG_USERREQ__INTERNAL_PRINTF = 0x3103,
+ /* Update an indirect function redirection.
+ Read VG_(redir_change_ifunc_target) in
+ coregrind/m_redir.c for more. */
+ VG_USERREQ__CHANGE_IFUNC_REDIR_TARGET = 0x3104,
+
} Vg_InternalClientRequest;
// Function for printing from code within Valgrind, but which runs on the
diff --git a/coregrind/pub_core_demangle.h b/coregrind/pub_core_demangle.h
index bac72c0..738cbc1 100644
--- a/coregrind/pub_core_demangle.h
+++ b/coregrind/pub_core_demangle.h
@@ -59,7 +59,8 @@ extern
Bool VG_(maybe_Z_demangle) ( const HChar* sym,
/*OUT*/HChar* so, Int soLen,
/*OUT*/HChar* fn, Int fnLen,
- /*OUT*/Bool* isWrap );
+ /*OUT*/Bool* isWrap,
+ /*OUT*/Bool* isIFunc );
#endif // __PUB_CORE_DEMANGLE_H
diff --git a/coregrind/pub_core_redir.h b/coregrind/pub_core_redir.h
index c993c27..025789d 100644
--- a/coregrind/pub_core_redir.h
+++ b/coregrind/pub_core_redir.h
@@ -59,6 +59,9 @@ extern void VG_(redir_notify_delete_DebugInfo)( DebugInfo* );
extern void VG_(redir_initialise)( void );
+extern void VG_(redir_change_ifunc_target)( Addr old_from,
+ Addr new_from );
+
//--------------------------------------------------------------------
// Queries
//--------------------------------------------------------------------
diff --git a/coregrind/vg_preloaded.c b/coregrind/vg_preloaded.c
index 6f0f049..28e6c7d 100644
--- a/coregrind/vg_preloaded.c
+++ b/coregrind/vg_preloaded.c
@@ -68,6 +68,33 @@ void VG_NOTIFY_ON_LOAD(freeres)( void )
*(int *)0 = 'x';
}
+/* Wrap all indirect functions defined in glibc by this one.
+ This function then calls the original indirect function, gets its result
+ (which is a pointer to the function that should really be used in lieu
+ of the indirect function) and then asks valgrind core
+ (running on the real CPU) to update the redirection "ifunc -> this function".
+
+*/
+void * VG_WRAP_I_FUNCTION_ZZ(VG_Z_LIBC_SONAME, Za) (void);
+void * VG_WRAP_I_FUNCTION_ZZ(VG_Z_LIBC_SONAME, Za) (void)
+{
+ OrigFn fn;
+ Addr result = 0;
+ int res;
+
+ 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_change_ifunc_target) in m_redir.c */
+ VALGRIND_DO_CLIENT_REQUEST(res, 0,
+ VG_USERREQ__CHANGE_IFUNC_REDIR_TARGET,
+ fn.nraddr, result, 0, 0, 0);
+ return result;
+}
+
#elif defined(VGO_darwin)
/* ---------------------------------------------------------------------
diff --git a/include/pub_tool_debuginfo.h b/include/pub_tool_debuginfo.h
index a02b790..85129ce 100644
--- a/include/pub_tool_debuginfo.h
+++ b/include/pub_tool_debuginfo.h
@@ -212,7 +212,8 @@ void VG_(DebugInfo_syms_getidx) ( const DebugInfo *di,
/*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. */
diff --git a/include/pub_tool_redir.h b/include/pub_tool_redir.h
index 3d3b516..ff6af2e 100644
--- a/include/pub_tool_redir.h
+++ b/include/pub_tool_redir.h
@@ -51,6 +51,16 @@
sure you use the VG_REPLACE_FN_ macros and not the VG_WRAP_FN_
macros.
+ Indirect functions
+ ~~~~~~~~~~~~~~~~~
+
+ An indirect function is an ELF function symbol whose st_info is STT_GNU_IFUNC
+ instead of STT_FUNC. To make a long story short, it points to a target
+ function which control is eventually transfered to.
+ More on those at http://www.x86-64.org/pipermail/discuss/2009-June/010553.html.
+ Replacing or wrapping indirect functions need special care.
+ More about it below in "indirect function wrapping and replacing".
+
Replacement
~~~~~~~~~~~
To write a replacement function, do this:
@@ -126,7 +136,8 @@
~~~~~~~~~~
Z-encoding details: the scheme is like GHC's. It is just about
readable enough to make a preprocessor unnecessary. First the
- "_vgrZU_" or "_vgrZZ_" prefix is added, and then the following
+ "_vgrZU_" or "_vgrZZ_" or (for indirect functions) "_vgirZU_"/"_vgirZZ_"
+ prefix is added, and then the following
characters are transformed.
* --> Za (asterisk)
@@ -143,6 +154,17 @@
Z --> ZZ (Z)
Everything else is left unchanged.
+
+ Indirect function wrapping
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ VG_WRAP_I_FUNCTION_ZZ is a macro (similar to VG_WRAP_FUNCTION_ZZ) that
+ wraps functions only. It does not have any effect on regular (STT_FUNC) functions.
+ Beware, the use of VG_WRAP_I_FUNCTION_ZZ in coregrin/vg_preloaded.c makes
+ the wrapping function match all the indirect functions of the C library.
+ So no other use of that macro should be necessary to match
+ indirect functions of the C library.
+
*/
/* If you change these, the code in VG_(maybe_Z_demangle) needs to be
@@ -158,6 +180,7 @@
#define VG_WRAP_FUNCTION_ZU(soname,fnname) VG_CONCAT4(_vgwZU_,soname,_,fnname)
#define VG_WRAP_FUNCTION_ZZ(soname,fnname) VG_CONCAT4(_vgwZZ_,soname,_,fnname)
+#define VG_WRAP_I_FUNCTION_ZZ(soname,fnname) VG_CONCAT4(_vgiwZZ_,soname,_,fnname)
/* --------- Some handy Z-encoded names. --------- */
diff --git a/memcheck/mc_replace_strmem.c b/memcheck/mc_replace_strmem.c
index c15717a..2bfe40b 100644
--- a/memcheck/mc_replace_strmem.c
+++ b/memcheck/mc_replace_strmem.c
@@ -116,6 +116,7 @@ Bool is_overlap ( void* dst, const void* src, SizeT dstlen, SizeT srclen )
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)
valgrind-3.5.0-inotify-init1.patch:
b/coregrind/m_syswrap/priv_syswrap-linux.h | 1
b/coregrind/m_syswrap/syswrap-amd64-linux.c | 4 +--
b/coregrind/m_syswrap/syswrap-linux.c | 18 +++++++++++++++
b/coregrind/m_syswrap/syswrap-x86-linux.c | 4 +--
valgrind-3.5.0/coregrind/m_syswrap/syswrap-ppc32-linux.c | 4 +--
valgrind-3.5.0/coregrind/m_syswrap/syswrap-ppc64-linux.c | 4 +--
6 files changed, 27 insertions(+), 8 deletions(-)
--- NEW FILE valgrind-3.5.0-inotify-init1.patch ---
commit 4b8a2fd25a4227f0b1411bee12add2d5c887c6a2
Author: Dodji Seketeli <dodji at redhat.com>
Date: Mon Oct 5 13:45:38 2009 +0200
Add a wrapper for inotify_init1 (vgbz #202315)
* coregrind/m_syswrap/priv_syswrap-linux.h: Declare the
sys_inotify_init1 wrapper.
* coregrind/m_syswrap/syswrap-linux.c: Add pre/post handlers for
the sys_inotify_init1 syscall.
* coregrind/m_syswrap/syswrap-amd64-linux.c: Insert the
sys_inotify_init1 wrapper in the wrappers table for the amd64 arch.
* coregrind/m_syswrap/syswrap-x86-linux.c: Likewise for the x86_32
arch.
diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
index fed3ba6..894678d 100644
--- a/coregrind/m_syswrap/priv_syswrap-linux.h
+++ b/coregrind/m_syswrap/priv_syswrap-linux.h
@@ -116,6 +116,7 @@ DECL_TEMPLATE(linux, sys_set_mempolicy);
DECL_TEMPLATE(linux, sys_get_mempolicy);
DECL_TEMPLATE(linux, sys_inotify_init);
+DECL_TEMPLATE(linux, sys_inotify_init1);
DECL_TEMPLATE(linux, sys_inotify_add_watch);
DECL_TEMPLATE(linux, sys_inotify_rm_watch);
diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c
index 605d844..bb28073 100644
--- a/coregrind/m_syswrap/syswrap-amd64-linux.c
+++ b/coregrind/m_syswrap/syswrap-amd64-linux.c
@@ -1374,8 +1374,8 @@ const SyscallTableEntry ML_(syscall_table)[] = {
LINX_(__NR_eventfd2, sys_eventfd2), // 290
LINXY(__NR_epoll_create1, sys_epoll_create1), // 291
// (__NR_dup3, sys_ni_syscall) // 292
- LINXY(__NR_pipe2, sys_pipe2) // 293
- // (__NR_inotify_init1, sys_ni_syscall) // 294
+ LINXY(__NR_pipe2, sys_pipe2), // 293
+ LINXY(__NR_inotify_init1, sys_inotify_init1), // 294
};
const UInt ML_(syscall_table_size) =
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 7f81262..895bc54 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -1526,6 +1526,24 @@ POST(sys_inotify_init)
}
}
+PRE(sys_inotify_init1)
+{
+ PRINT("sys_inotify_init ( %ld )", ARG1);
+ PRE_REG_READ1(long, "inotify_init", int, flag);
+}
+
+POST(sys_inotify_init1)
+{
+ vg_assert(SUCCESS);
+ if (!ML_(fd_allowed)(RES, "inotify_init", tid, True)) {
+ VG_(close)(RES);
+ SET_STATUS_Failure( VKI_EMFILE );
+ } else {
+ if (VG_(clo_track_fds))
+ ML_(record_fd_open_nameless) (tid, RES);
+ }
+}
+
PRE(sys_inotify_add_watch)
{
PRINT( "sys_inotify_add_watch ( %ld, %#lx, %lx )", ARG1,ARG2,ARG3);
diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c
index 90eb512..180e36b 100644
--- a/coregrind/m_syswrap/syswrap-x86-linux.c
+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
@@ -2253,8 +2253,8 @@ const SyscallTableEntry ML_(syscall_table)[] = {
LINXY(__NR_epoll_create1, sys_epoll_create1), // 329
// (__NR_dup3, sys_ni_syscall) // 330
- LINXY(__NR_pipe2, sys_pipe2) // 331
- // (__NR_inotify_init1, sys_ni_syscall) // 332
+ LINXY(__NR_pipe2, sys_pipe2), // 331
+ LINKX_(__NR_inotify_init1, sys_inotify_init1) // 332
};
const UInt ML_(syscall_table_size) =
--- valgrind-3.5.0/coregrind/m_syswrap/syswrap-ppc32-linux.c.jj 2009-10-09 12:52:04.000000000 +0200
+++ valgrind-3.5.0/coregrind/m_syswrap/syswrap-ppc32-linux.c 2009-10-12 16:14:33.000000000 +0200
@@ -1866,8 +1866,8 @@ const SyscallTableEntry ML_(syscall_tabl
LINX_(__NR_eventfd2, sys_eventfd2), // 314
LINXY(__NR_epoll_create1, sys_epoll_create1), // 315
// (__NR_dup3, sys_ni_syscall) // 316
- LINXY(__NR_pipe2, sys_pipe2) // 317
- // (__NR_inotify_init1, sys_ni_syscall) // 318
+ LINXY(__NR_pipe2, sys_pipe2), // 317
+ LINX_(__NR_inotify_init1, sys_inotify_init1) // 318
};
const UInt ML_(syscall_table_size) =
--- valgrind-3.5.0/coregrind/m_syswrap/syswrap-ppc64-linux.c.jj 2009-10-09 12:52:04.000000000 +0200
+++ valgrind-3.5.0/coregrind/m_syswrap/syswrap-ppc64-linux.c 2009-10-12 16:14:55.000000000 +0200
@@ -1506,8 +1506,8 @@ const SyscallTableEntry ML_(syscall_tabl
LINX_(__NR_eventfd2, sys_eventfd2), // 314
LINXY(__NR_epoll_create1, sys_epoll_create1), // 315
// (__NR_dup3, sys_ni_syscall) // 316
- LINXY(__NR_pipe2, sys_pipe2) // 317
- // (__NR_inotify_init1, sys_ni_syscall) // 318
+ LINXY(__NR_pipe2, sys_pipe2), // 317
+ LINX_(__NR_inotify_init1, sys_inotify_init1) // 318
};
const UInt ML_(syscall_table_size) =
valgrind-3.5.0-mmap-mprotect.patch:
mc_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- NEW FILE valgrind-3.5.0-mmap-mprotect.patch ---
Temporarily revert a Darwin specific change that broke mmap PROT_NONE followed by
mprotect PROT_READ|PROT_WRITE.
http://bugs.kde.org/show_bug.cgi?id=210268
--- valgrind-3.5.0/memcheck/mc_main.c.jj 2009-10-09 12:51:59.000000000 +0200
+++ valgrind-3.5.0/memcheck/mc_main.c 2009-10-12 17:13:26.000000000 +0200
@@ -3705,7 +3705,7 @@ static
void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx,
ULong di_handle )
{
- if (rr || ww || xx)
+ if (1 || rr || ww || xx)
MC_(make_mem_defined)(a, len);
else
MC_(make_mem_noaccess)(a, len);
Index: valgrind.spec
===================================================================
RCS file: /cvs/pkgs/rpms/valgrind/F-12/valgrind.spec,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -p -r1.67 -r1.68
--- valgrind.spec 21 Aug 2009 14:48:26 -0000 1.67
+++ valgrind.spec 12 Oct 2009 15:18:45 -0000 1.68
@@ -1,12 +1,15 @@
Summary: Tool for finding memory management bugs in programs
Name: valgrind
Version: 3.5.0
-Release: 1
+Release: 2
Epoch: 1
Source0: http://www.valgrind.org/downloads/valgrind-%{version}.tar.bz2
Patch1: valgrind-3.5.0-cachegrind-improvements.patch
Patch2: valgrind-3.5.0-openat.patch
Patch3: valgrind-3.5.0-glibc-2.10.1.patch
+Patch4: valgrind-3.5.0-ifunc.patch
+Patch5: valgrind-3.5.0-inotify-init1.patch
+Patch6: valgrind-3.5.0-mmap-mprotect.patch
License: GPLv2
URL: http://www.valgrind.org/
Group: Development/Debuggers
@@ -63,6 +66,9 @@ or valgrind plugins.
%patch1 -p1
%patch2 -p1
%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
%build
%ifarch x86_64 ppc64
@@ -155,6 +161,11 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/pkgconfig/*
%changelog
+* Mon Oct 12 2009 Jakub Jelinek <jakub at redhat.com> 3.5.0-2
+- add STT_GNU_IFUNC support (Dodji Seketeli, #518247)
+- wrap inotify_init1 syscall (Dodji Seketeli, #527198)
+- fix mmap/mprotect handling in memcheck (KDE#210268)
+
* Fri Aug 21 2009 Jakub Jelinek <jakub at redhat.com> 3.5.0-1
- update to 3.5.0
More information about the fedora-extras-commits
mailing list