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