|
From: Johan B. <jb...@gm...> - 2009-11-15 13:06:07
|
Hi Tom,
This commit broke all the redirection functionality on Darwin.
Attached patch fixes it. (trivial. don't forget to initialize the
isIFunc field + add assert to make it not happen again)
/Johan
On Thu, Oct 29, 2009 at 10:27 AM, <sv...@va...> wrote:
> Author: tom
> Date: 2009-10-29 09:27:11 +0000 (Thu, 29 Oct 2009)
> New Revision: 10920
>
> Log:
> Add support for ELF indirect functions. These are symbols of
> type STT_GNU_IFUNC which, instead of pointing directly at the
> function, point at a routine which will return the address of
> the real function. Redirection of indirect functions is handled
> by valgrind as follows:
>
> - When a redirection specification matches an indirect
> function symbol an active redirection is added in the
> normal way, but with the isIFunc flag set.
>
> - When a call is made to an address which matches an
> active redirection with the isIFunc flag set the call
> is redirected, but not to the target address of the
> redirection - instead it is sent to a small wrapper
> routine that is preloaded into the client.
>
> - The wrapper routine calls the original client routine
> and collects the result, which it reports to valgrind
> using a client request, and then returns the result to
> the caller.
>
> - When valgrind gets the client request it looks up the
> active redirection for the indirect function and then
> adds a new active redirection which redirects from the
> address returned by the indirection function to the
> redirection target. This new redirection does not have
> the isIFunc flag set so behaves as a normal redirection.
>
> In addition to the above we also add a few new redirections to
> memcheck to capture internal calls made by glibc to things like
> strlen, as these internal calls do not go through the indirect
> function and instead go direct to the chosen implementation.
>
> Based on a patch from Dodji Seketeli and comments from Jakub
> Jelinek, this commit closes bug 206013.
>
>
> Modified:
> trunk/coregrind/m_debuginfo/debuginfo.c
> trunk/coregrind/m_debuginfo/priv_storage.h
> trunk/coregrind/m_debuginfo/readelf.c
> trunk/coregrind/m_redir.c
> trunk/coregrind/m_scheduler/scheduler.c
> trunk/coregrind/pub_core_clreq.h
> trunk/coregrind/pub_core_redir.h
> trunk/coregrind/vg_preloaded.c
> trunk/include/pub_tool_debuginfo.h
> trunk/memcheck/mc_replace_strmem.c
>
>
> Modified: trunk/coregrind/m_debuginfo/debuginfo.c
> ===================================================================
> --- trunk/coregrind/m_debuginfo/debuginfo.c 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/coregrind/m_debuginfo/debuginfo.c 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -3435,14 +3435,16 @@
> /*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;
> }
>
>
>
> Modified: trunk/coregrind/m_debuginfo/priv_storage.h
> ===================================================================
> --- trunk/coregrind/m_debuginfo/priv_storage.h 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/coregrind/m_debuginfo/priv_storage.h 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -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;
>
>
> Modified: trunk/coregrind/m_debuginfo/readelf.c
> ===================================================================
> --- trunk/coregrind/m_debuginfo/readelf.c 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/coregrind/m_debuginfo/readelf.c 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -214,7 +214,8 @@
> 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 @@
> *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 @@
> &&
> (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 @@
> *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 @@
> 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 @@
> &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 @@
> Int size;
> Bool from_opd;
> Bool is_text;
> + Bool is_ifunc;
> }
> TempSym;
>
> @@ -671,7 +686,7 @@
> 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 @@
> &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 @@
> 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 @@
> 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 );
>
> Modified: trunk/coregrind/m_redir.c
> ===================================================================
> --- trunk/coregrind/m_redir.c 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/coregrind/m_redir.c 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -268,12 +268,15 @@
> 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 @@
>
> 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 @@
>
> 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,7 +473,31 @@
>
> #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
> all the symbols in the given seginfo. If a conflicting binding
> @@ -487,7 +514,7 @@
> )
> {
> Spec* sp;
> - Bool anyMark, isText;
> + Bool anyMark, isText, isIFunc;
> Active act;
> Int nsyms, i;
> Addr sym_addr;
> @@ -513,7 +540,7 @@
> 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 @@
> 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 @@
>
> 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;
> }
>
> @@ -1096,6 +1126,8 @@
>
> 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);
> }
>
> Modified: trunk/coregrind/m_scheduler/scheduler.c
> ===================================================================
> --- trunk/coregrind/m_scheduler/scheduler.c 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/coregrind/m_scheduler/scheduler.c 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -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 @@
> 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] );
>
> Modified: trunk/coregrind/pub_core_clreq.h
> ===================================================================
> --- trunk/coregrind/pub_core_clreq.h 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/coregrind/pub_core_clreq.h 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -50,6 +50,9 @@
> /* 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
>
> Modified: trunk/coregrind/pub_core_redir.h
> ===================================================================
> --- trunk/coregrind/pub_core_redir.h 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/coregrind/pub_core_redir.h 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -58,6 +58,8 @@
> /* 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
>
> Modified: trunk/coregrind/vg_preloaded.c
> ===================================================================
> --- trunk/coregrind/vg_preloaded.c 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/coregrind/vg_preloaded.c 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -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 @@
> *(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)
>
> /* ---------------------------------------------------------------------
>
> Modified: trunk/include/pub_tool_debuginfo.h
> ===================================================================
> --- trunk/include/pub_tool_debuginfo.h 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/include/pub_tool_debuginfo.h 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -212,7 +212,8 @@
> /*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. */
>
> Modified: trunk/memcheck/mc_replace_strmem.c
> ===================================================================
> --- trunk/memcheck/mc_replace_strmem.c 2009-10-29 09:01:39 UTC (rev 10919)
> +++ trunk/memcheck/mc_replace_strmem.c 2009-10-29 09:27:11 UTC (rev 10920)
> @@ -116,6 +116,7 @@
> 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 @@
> 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,8 +174,10 @@
> }
>
> 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) \
> ( char* dst, const char* src, SizeT n ); \
> @@ -257,6 +261,9 @@
> }
>
> 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 @@
>
> 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 @@
> }
>
> 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 @@
> }
>
> 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 @@
> }
>
> 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 @@
>
> 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 @@
>
> 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,8 +725,10 @@
> }
>
> 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. */
> #define GLIBC25___STRCPY_CHK(soname,fnname) \
>
>
> ------------------------------------------------------------------------------
> Come build with us! The BlackBerry(R) Developer Conference in SF, CA
> is the only developer event you need to attend this year. Jumpstart your
> developing skills, take BlackBerry mobile applications to market and stay
> ahead of the curve. Join us from November 9 - 12, 2009. Register now!
> http://p.sf.net/sfu/devconference
> _______________________________________________
> Valgrind-developers mailing list
> Val...@li...
> https://lists.sourceforge.net/lists/listinfo/valgrind-developers
>
|