|
From: <sv...@va...> - 2015-11-15 16:50:54
|
Author: mjw
Date: Sun Nov 15 16:50:43 2015
New Revision: 15726
Log:
BZ#355188 valgrind should intercept all malloc related global functions.
This implements the interception of all globally public allocation
functions by default. It works by adding a flag to the spec to say the
interception only applies to global functions. Which is set for the
somalloc spec. The librarypath to match is set to "*" unless the user
overrides it. Then each DiSym keeps track of whether the symbol is local
or global. For a spec which has isGlobal set only isGlobal symbols will
match.
Note that because of padding to keep the addresses in DiSym aligned the
addition of the extra bool isGlobal doesn't actually grow the struct.
The comments explain how the struct could be made more compact on 32bit
systems, but this isn't as easy on 64bit systems. So I didn't try to do
that in this patch.
For ELF symbols keeping track of which are global is trivial. For pdb I
had to guess and made only the "Public" symbols global. I don't know
how/if macho keeps track of global symbols or not. For now I just mark
all of them local (which just means things work as previously on platforms
that use machos, no non-system symbols are matches by default for somalloc
unless the user explicitly tells which library name to match).
Included are two testcases for shared libraries (wrapmalloc) and staticly
linked (wrapmallocstatic) malloc/free overrides that depend on the new
default. One existing testcase (new_override) was adjusted to explicitly
not use the new somalloc default because it depends on a user defined
new implementation that has side-effects and should explicitly not be
intercepted.
Added:
trunk/memcheck/tests/wrapmalloc.c
trunk/memcheck/tests/wrapmalloc.stderr.exp
trunk/memcheck/tests/wrapmalloc.stdout.exp
trunk/memcheck/tests/wrapmalloc.vgtest
trunk/memcheck/tests/wrapmallocso.c
trunk/memcheck/tests/wrapmallocstatic.c
trunk/memcheck/tests/wrapmallocstatic.stderr.exp
trunk/memcheck/tests/wrapmallocstatic.stdout.exp
trunk/memcheck/tests/wrapmallocstatic.vgtest
Modified:
trunk/NEWS
trunk/coregrind/m_debuginfo/debuginfo.c
trunk/coregrind/m_debuginfo/priv_storage.h
trunk/coregrind/m_debuginfo/readelf.c
trunk/coregrind/m_debuginfo/readmacho.c
trunk/coregrind/m_debuginfo/readpdb.c
trunk/coregrind/m_debuginfo/storage.c
trunk/coregrind/m_redir.c
trunk/coregrind/m_replacemalloc/vg_replace_malloc.c
trunk/coregrind/pub_core_debuginfo.h
trunk/docs/xml/manual-core.xml
trunk/include/pub_tool_redir.h
trunk/memcheck/tests/Makefile.am
trunk/memcheck/tests/new_override.vgtest
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Nov 15 16:50:43 2015
@@ -17,6 +17,14 @@
* ==================== OTHER CHANGES ====================
+* Replacement/wrapping of malloc/new related functions is now done not just
+ for system libraries by default, but for any globally defined malloc/new
+ related function (both in shared libraries and staticly linked alternative
+ malloc implementations). To only intercept malloc/new related functions in
+ system libraries use --soname-synonyms=somalloc=nouserintercepts (where
+ "nouserintercepts" can be any non-existing library name).
+ This new functionality is not implemented for darwin/macosx.
+
* ==================== FIXED BUGS ====================
The following bugs have been fixed or resolved. Note that "n-i-bz"
@@ -42,6 +50,7 @@
354392 unhandled amd64-solaris syscall: 171
354797 Added vbit tester support for PPC 64 isa 2.07 iops
354933 Fix documentation of --kernel-variant=android-no-hw-tls option
+355188 valgrind should intercept all malloc related global functions
Release 3.11.0 (22 September 2015)
Modified: trunk/coregrind/m_debuginfo/debuginfo.c
==============================================================================
--- trunk/coregrind/m_debuginfo/debuginfo.c (original)
+++ trunk/coregrind/m_debuginfo/debuginfo.c Sun Nov 15 16:50:43 2015
@@ -4306,7 +4306,8 @@
/*OUT*/const HChar** pri_name,
/*OUT*/const HChar*** sec_names,
/*OUT*/Bool* isText,
- /*OUT*/Bool* isIFunc )
+ /*OUT*/Bool* isIFunc,
+ /*OUT*/Bool* isGlobal )
{
vg_assert(idx >= 0 && idx < si->symtab_used);
if (avmas) *avmas = si->symtab[idx].avmas;
@@ -4315,6 +4316,7 @@
if (sec_names) *sec_names = si->symtab[idx].sec_names;
if (isText) *isText = si->symtab[idx].isText;
if (isIFunc) *isIFunc = si->symtab[idx].isIFunc;
+ if (isGlobal) *isGlobal = si->symtab[idx].isGlobal;
}
Modified: trunk/coregrind/m_debuginfo/priv_storage.h
==============================================================================
--- trunk/coregrind/m_debuginfo/priv_storage.h (original)
+++ trunk/coregrind/m_debuginfo/priv_storage.h Sun Nov 15 16:50:43 2015
@@ -75,14 +75,18 @@
the macros defined in pub_core_debuginfo.h */
const HChar* pri_name; /* primary name, never NULL */
const HChar** sec_names; /* NULL, or a NULL term'd array of other names */
- // XXX: this could be shrunk (on 32-bit platforms) by using 30
- // bits for the size and 1 bit each for isText and isIFunc. If you
- // do this, make sure that all assignments to the latter two use
- // 0 or 1 (or True or False), and that a positive number larger
- // than 1 is never used to represent True.
+ // XXX: DiSym could be shrunk (on 32-bit platforms to exactly 16
+ // bytes, on 64-bit platforms the first 3 pointers already add
+ // up to 24 bytes, so size plus bits will extend to 32 bytes
+ // anyway) by using 29 bits for the size and 1 bit each for
+ // isText, isIFunc and isGlobal. If you do this, make sure that
+ // all assignments to the latter two 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 */
Bool isText;
Bool isIFunc; /* symbol is an indirect function? */
+ Bool isGlobal; /* Is this symbol globally visible? */
}
DiSym;
Modified: trunk/coregrind/m_debuginfo/readelf.c
==============================================================================
--- trunk/coregrind/m_debuginfo/readelf.c (original)
+++ trunk/coregrind/m_debuginfo/readelf.c Sun Nov 15 16:50:43 2015
@@ -241,7 +241,8 @@
Bool* from_opd_out, /* ppc64be-linux only: did we deref an
.opd entry? */
Bool* is_text_out, /* is this a text symbol? */
- Bool* is_ifunc /* is this a STT_GNU_IFUNC function ?*/
+ Bool* is_ifunc_out, /* is this a STT_GNU_IFUNC function ?*/
+ Bool* is_global_out /* is this a global symbol ?*/
)
{
Bool plausible;
@@ -259,7 +260,8 @@
SET_TOCPTR_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
SET_LOCAL_EP_AVMA(*sym_avmas_out, 0); /* default to unknown/inapplicable */
*from_opd_out = False;
- *is_ifunc = False;
+ *is_ifunc_out = False;
+ *is_global_out = False;
/* Get the symbol size, but restrict it to fit in a signed 32 bit
int. Also, deal with the stupid case of negative size by making
@@ -373,10 +375,14 @@
/* Check for indirect functions. */
if (*is_text_out
&& ELFXX_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) {
- *is_ifunc = True;
+ *is_ifunc_out = True;
}
# endif
+ if (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL) {
+ *is_global_out = True;
+ }
+
# if defined(VGP_ppc64be_linux)
/* Allow STT_NOTYPE in the very special case where we're running on
ppc64be-linux and the symbol is one which the .opd-chasing hack
@@ -777,6 +783,7 @@
SymAVMAs sym_avmas_really;
Int sym_size = 0;
Bool from_opd = False, is_text = False, is_ifunc = False;
+ Bool is_global = False;
DiOffT sym_name_really = DiOffT_INVALID;
sym_avmas_really.main = 0;
SET_TOCPTR_AVMA(sym_avmas_really, 0);
@@ -787,7 +794,7 @@
&sym_name_really,
&sym_avmas_really,
&sym_size,
- &from_opd, &is_text, &is_ifunc)) {
+ &from_opd, &is_text, &is_ifunc, &is_global)) {
DiSym disym;
VG_(memset)(&disym, 0, sizeof(disym));
@@ -799,6 +806,7 @@
disym.size = sym_size;
disym.isText = is_text;
disym.isIFunc = is_ifunc;
+ disym.isGlobal = is_global;
if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
vg_assert(disym.pri_name);
vg_assert(GET_TOCPTR_AVMA(disym.avmas) == 0);
@@ -847,6 +855,7 @@
Bool from_opd;
Bool is_text;
Bool is_ifunc;
+ Bool is_global;
}
TempSym;
@@ -911,6 +920,7 @@
SymAVMAs sym_avmas_really;
Int sym_size = 0;
Bool from_opd = False, is_text = False, is_ifunc = False;
+ Bool is_global = False;
DiOffT sym_name_really = DiOffT_INVALID;
DiSym disym;
VG_(memset)(&disym, 0, sizeof(disym));
@@ -923,7 +933,7 @@
&sym_name_really,
&sym_avmas_really,
&sym_size,
- &from_opd, &is_text, &is_ifunc)) {
+ &from_opd, &is_text, &is_ifunc, &is_global)) {
/* Check if we've seen this (name,addr) key before. */
key.addr = sym_avmas_really.main;
@@ -996,6 +1006,7 @@
elem->from_opd = from_opd;
elem->is_text = is_text;
elem->is_ifunc = is_ifunc;
+ elem->is_global = is_global;
VG_(OSetGen_Insert)(oset, elem);
if (di->trace_symtab) {
HChar* str = ML_(img_strdup)(escn_strtab->img, "di.respl.2",
@@ -1034,14 +1045,17 @@
disym.size = elem->size;
disym.isText = elem->is_text;
disym.isIFunc = elem->is_ifunc;
+ disym.isGlobal = elem->is_global;
if (cstr) { ML_(dinfo_free)(cstr); cstr = NULL; }
vg_assert(disym.pri_name != NULL);
ML_(addSym) ( di, &disym );
if (di->trace_symtab) {
- VG_(printf)(" rec(%c) [%4ld]: "
+ VG_(printf)(" rec(%c%c%c) [%4ld]: "
" val %#010lx, toc %#010lx, sz %4d %s\n",
disym.isText ? 't' : 'd',
+ disym.isIFunc ? 'i' : '-',
+ disym.isGlobal ? 'g' : 'l',
i,
disym.avmas.main,
GET_TOCPTR_AVMA(disym.avmas),
Modified: trunk/coregrind/m_debuginfo/readmacho.c
==============================================================================
--- trunk/coregrind/m_debuginfo/readmacho.c (original)
+++ trunk/coregrind/m_debuginfo/readmacho.c Sun Nov 15 16:50:43 2015
@@ -365,6 +365,7 @@
di->text_avma+di->text_size - sym_addr;
disym.isText = True;
disym.isIFunc = False;
+ disym.isGlobal = False;
// Lots of user function names get prepended with an underscore. Eg. the
// function 'f' becomes the symbol '_f'. And the "below main"
// function is called "start". So we skip the leading underscore, and
Modified: trunk/coregrind/m_debuginfo/readpdb.c
==============================================================================
--- trunk/coregrind/m_debuginfo/readpdb.c (original)
+++ trunk/coregrind/m_debuginfo/readpdb.c Sun Nov 15 16:50:43 2015
@@ -1272,6 +1272,7 @@
// FIXME: .namelen is sizeof(.data) including .name[]
vsym.isText = (sym->generic.id == S_PUB_V1);
vsym.isIFunc = False;
+ vsym.isGlobal = True;
ML_(addSym)( di, &vsym );
n_syms_read++;
}
@@ -1299,6 +1300,7 @@
vsym.isText = !!(IMAGE_SCN_CNT_CODE
& sectp[sym->data_v2.segment-1].Characteristics);
vsym.isIFunc = False;
+ vsym.isGlobal = True;
ML_(addSym)( di, &vsym );
n_syms_read++;
}
@@ -1332,6 +1334,7 @@
vsym.isText = !!(IMAGE_SCN_CNT_CODE
& sectp[sym->data_v2.segment-1].Characteristics);
vsym.isIFunc = False;
+ vsym.isGlobal = True;
ML_(addSym)( di, &vsym );
n_syms_read++;
}
@@ -1365,6 +1368,7 @@
vsym.size = sym->proc_v1.proc_len;
vsym.isText = True;
vsym.isIFunc = False;
+ vsym.isGlobal = sym->generic.id == S_GPROC_V1;
if (debug)
VG_(umsg)(" Adding function %s addr=%#lx length=%u\n",
symname, vsym.avmas.main, vsym.size );
@@ -1386,6 +1390,7 @@
vsym.size = sym->proc_v2.proc_len;
vsym.isText = True;
vsym.isIFunc = False;
+ vsym.isGlobal = sym->generic.id == S_GPROC_V2;
if (debug)
VG_(umsg)(" Adding function %s addr=%#lx length=%u\n",
symname, vsym.avmas.main, vsym.size );
@@ -1408,6 +1413,7 @@
vsym.size = sym->proc_v3.proc_len;
vsym.isText = 1;
vsym.isIFunc = False;
+ vsym.isGlobal = sym->generic.id == S_GPROC_V3;
ML_(addSym)( di, &vsym );
n_syms_read++;
}
Modified: trunk/coregrind/m_debuginfo/storage.c
==============================================================================
--- trunk/coregrind/m_debuginfo/storage.c (original)
+++ trunk/coregrind/m_debuginfo/storage.c Sun Nov 15 16:50:43 2015
@@ -98,10 +98,11 @@
vg_assert(sym->pri_name);
if (sec_names)
vg_assert(sec_names);
- VG_(printf)( "%5d: %c%c %#8lx .. %#8lx (%u) %s%s",
+ VG_(printf)( "%5d: %c%c%c %#8lx .. %#8lx (%u) %s%s",
idx,
sym->isText ? 'T' : '-',
sym->isIFunc ? 'I' : '-',
+ sym->isGlobal ? 'G' : '-',
sym->avmas.main,
sym->avmas.main + sym->size - 1, sym->size,
sym->pri_name, sec_names ? " " : "" );
@@ -1646,7 +1647,7 @@
Word i, j, n_truncated;
Addr sta1, sta2, end1, end2, toc1, toc2;
const HChar *pri1, *pri2, **sec1, **sec2;
- Bool ist1, ist2, isf1, isf2;
+ Bool ist1, ist2, isf1, isf2, isg1, isg2;
# define SWAP(ty,aa,bb) \
do { ty tt = (aa); (aa) = (bb); (bb) = tt; } while (0)
@@ -1693,6 +1694,8 @@
}
/* mark w as an IFunc if either w or r are */
di->symtab[w].isIFunc = di->symtab[w].isIFunc || di->symtab[r].isIFunc;
+ /* likewise for global symbols */
+ di->symtab[w].isGlobal = di->symtab[w].isGlobal || di->symtab[r].isGlobal;
/* and use ::pri_names to indicate this slot is no longer in use */
di->symtab[r].pri_name = NULL;
if (di->symtab[r].sec_names) {
@@ -1796,6 +1799,7 @@
sec1 = di->symtab[i].sec_names;
ist1 = di->symtab[i].isText;
isf1 = di->symtab[i].isIFunc;
+ isg1 = di->symtab[i].isGlobal;
sta2 = di->symtab[i+1].avmas.main;
end2 = sta2 + di->symtab[i+1].size - 1;
@@ -1805,6 +1809,7 @@
sec2 = di->symtab[i+1].sec_names;
ist2 = di->symtab[i+1].isText;
isf2 = di->symtab[i+1].isIFunc;
+ isg2 = di->symtab[i+1].isGlobal;
if (sta1 < sta2) {
end1 = sta2 - 1;
@@ -1814,7 +1819,7 @@
sta1 = end2 + 1;
SWAP(Addr,sta1,sta2); SWAP(Addr,end1,end2); SWAP(Addr,toc1,toc2);
SWAP(const HChar*,pri1,pri2); SWAP(const HChar**,sec1,sec2);
- SWAP(Bool,ist1,ist2); SWAP(Bool,isf1,isf2);
+ SWAP(Bool,ist1,ist2); SWAP(Bool,isf1,isf2); SWAP(Bool, isg1, isg2);
} else
if (end1 < end2) {
sta2 = end1 + 1;
@@ -1831,6 +1836,7 @@
di->symtab[i].sec_names = sec1;
di->symtab[i].isText = ist1;
di->symtab[i].isIFunc = isf1;
+ di->symtab[i].isGlobal = isg1;
di->symtab[i+1].avmas.main = sta2;
di->symtab[i+1].size = end2 - sta2 + 1;
@@ -1840,6 +1846,7 @@
di->symtab[i+1].sec_names = sec2;
di->symtab[i+1].isText = ist2;
di->symtab[i+1].isIFunc = isf2;
+ di->symtab[i+1].isGlobal = isg2;
vg_assert(sta1 <= sta2);
vg_assert(di->symtab[i].size > 0);
Modified: trunk/coregrind/m_redir.c
==============================================================================
--- trunk/coregrind/m_redir.c (original)
+++ trunk/coregrind/m_redir.c Sun Nov 15 16:50:43 2015
@@ -233,6 +233,7 @@
HChar* from_fnpatt; /* from fnname pattern */
Addr to_addr; /* where redirecting to */
Bool isWrap; /* wrap or replacement? */
+ Bool isGlobal; /* must the symbol to replace be global? */
Int becTag; /* 0 through 9999. Behavioural equivalance class tag.
If two wrappers have the same (non-zero) tag, they
are promising that they behave identically. */
@@ -388,7 +389,7 @@
void VG_(redir_notify_new_DebugInfo)( const DebugInfo* newdi )
{
- Bool ok, isWrap;
+ Bool ok, isWrap, isGlobal;
Int i, nsyms, becTag, becPrio;
Spec* specList;
Spec* spec;
@@ -518,13 +519,14 @@
for (i = 0; i < nsyms; i++) {
VG_(DebugInfo_syms_getidx)( newdi, i, &sym_avmas,
NULL, &sym_name_pri, &sym_names_sec,
- &isText, NULL );
+ &isText, NULL, NULL );
/* Set up to conveniently iterate over all names for this symbol. */
const HChar* twoslots[2];
const HChar** names_init =
alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
const HChar** names;
for (names = names_init; *names; names++) {
+ isGlobal = False;
ok = VG_(maybe_Z_demangle)( *names,
&demangled_sopatt,
&demangled_fnpatt,
@@ -579,15 +581,12 @@
have a matching lib synonym, then replace the sopatt.
Otherwise, just ignore this redirection spec. */
- if (!VG_(clo_soname_synonyms))
- continue; // No synonyms => skip the redir.
-
/* Search for a matching synonym=newname*/
SizeT const sopatt_syn_len
= VG_(strlen)(demangled_sopatt+VG_SO_SYN_PREFIX_LEN);
HChar const* last = VG_(clo_soname_synonyms);
- while (*last) {
+ while (last != NULL && *last) {
HChar const* first = last;
last = advance_to_equal(first);
@@ -611,6 +610,17 @@
last++;
}
+ // If the user didn't set it then somalloc is special. We
+ // want to match public/global symbols that match the
+ // fnpatt everywhere.
+ if (replaced_sopatt == NULL
+ && VG_(strcmp) ( demangled_sopatt, SO_SYN_MALLOC_NAME ) == 0)
+ {
+ replaced_sopatt = VG_(strdup)("m_redir.rnnD.1", "*");
+ demangled_sopatt = replaced_sopatt;
+ isGlobal = True;
+ }
+
// If we have not replaced the sopatt, then skip the redir.
if (replaced_sopatt == NULL)
continue;
@@ -621,6 +631,7 @@
spec->from_fnpatt = dinfo_strdup("redir.rnnD.3", demangled_fnpatt);
spec->to_addr = sym_avmas.main;
spec->isWrap = isWrap;
+ spec->isGlobal = isGlobal;
spec->becTag = becTag;
spec->becPrio = becPrio;
/* check we're not adding manifestly stupid destinations */
@@ -653,7 +664,7 @@
for (i = 0; i < nsyms; i++) {
VG_(DebugInfo_syms_getidx)( newdi, i, &sym_avmas,
NULL, &sym_name_pri, &sym_names_sec,
- &isText, NULL );
+ &isText, NULL, NULL );
const HChar* twoslots[2];
const HChar** names_init =
alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
@@ -785,7 +796,7 @@
)
{
Spec* sp;
- Bool anyMark, isText, isIFunc;
+ Bool anyMark, isText, isIFunc, isGlobal;
Active act;
Int nsyms, i;
SymAVMAs sym_avmas;
@@ -813,7 +824,7 @@
for (i = 0; i < nsyms; i++) {
VG_(DebugInfo_syms_getidx)( di, i, &sym_avmas,
NULL, &sym_name_pri, &sym_names_sec,
- &isText, &isIFunc );
+ &isText, &isIFunc, &isGlobal );
const HChar* twoslots[2];
const HChar** names_init =
alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
@@ -827,7 +838,8 @@
for (sp = specs; sp; sp = sp->next) {
if (!sp->mark)
continue; /* soname doesn't match */
- if (VG_(string_match)( sp->from_fnpatt, *names )) {
+ if (VG_(string_match)( sp->from_fnpatt, *names )
+ && (sp->isGlobal == False || isGlobal == True)) {
/* got a new binding. Add to collection. */
act.from_addr = sym_avmas.main;
act.to_addr = sp->to_addr;
@@ -1220,6 +1232,7 @@
spec->from_fnpatt = CONST_CAST(HChar *,fnpatt);
spec->to_addr = to_addr;
spec->isWrap = False;
+ spec->isGlobal = False;
spec->mandatory = mandatory;
/* VARIABLE PARTS */
spec->mark = False; /* not significant */
@@ -1719,7 +1732,7 @@
const HChar** sym_names_sec = NULL;
VG_(DebugInfo_syms_getidx)( di, j, NULL,
NULL, &sym_name_pri, &sym_names_sec,
- &isText, NULL );
+ &isText, NULL, NULL );
const HChar* twoslots[2];
const HChar** names_init =
alloc_symname_array(sym_name_pri, sym_names_sec, &twoslots[0]);
@@ -1773,10 +1786,11 @@
static void show_spec ( const HChar* left, const Spec* spec )
{
VG_(message)( Vg_DebugMsg,
- "%s%-25s %-30s %s-> (%04d.%d) 0x%08lx\n",
+ "%s%-25s %-30s %s%s-> (%04d.%d) 0x%08lx\n",
left,
spec->from_sopatt, spec->from_fnpatt,
spec->isWrap ? "W" : "R",
+ spec->isGlobal ? "G" : "L",
spec->becTag, spec->becPrio,
spec->to_addr );
}
Modified: trunk/coregrind/m_replacemalloc/vg_replace_malloc.c
==============================================================================
--- trunk/coregrind/m_replacemalloc/vg_replace_malloc.c (original)
+++ trunk/coregrind/m_replacemalloc/vg_replace_malloc.c Sun Nov 15 16:50:43 2015
@@ -291,7 +291,6 @@
// For some lines, we will also define a replacement function
// whose only purpose is to be a soname synonym place holder
// that can be replaced using --soname-synonyms.
-#define SO_SYN_MALLOC VG_SO_SYN(somalloc)
// malloc
#if defined(VGO_linux)
Modified: trunk/coregrind/pub_core_debuginfo.h
==============================================================================
--- trunk/coregrind/pub_core_debuginfo.h (original)
+++ trunk/coregrind/pub_core_debuginfo.h Sun Nov 15 16:50:43 2015
@@ -216,7 +216,8 @@
/*OUT*/const HChar** pri_name,
/*OUT*/const HChar*** sec_names,
/*OUT*/Bool* isText,
- /*OUT*/Bool* isIFunc );
+ /*OUT*/Bool* isIFunc,
+ /*OUT*/Bool* isGlobal );
/* ppc64-linux only: find the TOC pointer (R2 value) that should be in
force at the entry point address of the function containing
guest_code_addr. Returns 0 if not known. */
Modified: trunk/docs/xml/manual-core.xml
==============================================================================
--- trunk/docs/xml/manual-core.xml (original)
+++ trunk/docs/xml/manual-core.xml Sun Nov 15 16:50:43 2015
@@ -2315,18 +2315,26 @@
<option><![CDATA[--soname-synonyms=syn1=pattern1,syn2=pattern2,...]]></option>
</term>
<listitem>
- <para>When a shared library is loaded, Valgrind checks for
- functions in the library that must be replaced or wrapped.
- For example, Memcheck replaces all malloc related
- functions (malloc, free, calloc, ...) with its own versions.
- Such replacements are done by default only in shared libraries whose
- soname matches a predefined soname pattern (e.g.
- <varname>libc.so*</varname> on linux).
- By default, no replacement is done for a statically linked
- library or for alternative libraries such as tcmalloc.
+ <para>When a shared library is loaded, Valgrind checks for
+ functions in the library that must be replaced or wrapped. For
+ example, Memcheck replaces some string and memory functions
+ (strchr, strlen, strcpy, memchr, memcpy, memmove, etc.) with its
+ own versions. Such replacements are normally done only in shared
+ libraries whose soname matches a predefined soname pattern (e.g.
+ <varname>libc.so*</varname> on linux). By default, no
+ replacement is done for a statically linked library or for
+ alternative libraries, except for the allocation functions
+ (malloc, free, calloc, memalign, realloc, operator new, operator
+ delete, etc.) Such allocation functions are intercepted by
+ default in any shared library or in the executable if they are
+ exported as global symbols. This means that if a replacement
+ allocation library such as tcmalloc is found, its functions are
+ also intercepted by default.
+
In some cases, the replacements allow
<option>--soname-synonyms</option> to specify one additional
- synonym pattern, giving flexibility in the replacement. </para>
+ synonym pattern, giving flexibility in the replacement. Or to
+ prevent interception of all public allocation symbols.</para>
<para>Currently, this flexibility is only allowed for the
malloc related functions, using the
@@ -2339,27 +2347,31 @@
<listitem>
<para>Alternate malloc library: to replace the malloc
- related functions in an alternate library with
- soname <varname>mymalloclib.so</varname>, give the
+ related functions in a specific alternate library with
+ soname <varname>mymalloclib.so</varname> (and not in any
+ others), give the
option <option>--soname-synonyms=somalloc=mymalloclib.so</option>.
A pattern can be used to match multiple libraries sonames.
For
example, <option>--soname-synonyms=somalloc=*tcmalloc*</option>
- will match the soname of all variants of the tcmalloc library
- (native, debug, profiled, ... tcmalloc variants). </para>
+ will match the soname of all variants of the tcmalloc
+ library (native, debug, profiled, ... tcmalloc
+ variants). </para>
<para>Note: the soname of a elf shared library can be
retrieved using the readelf utility. </para>
</listitem>
<listitem>
- <para>Replacements in a statically linked library are done by
- using the <varname>NONE</varname> pattern. For example, if
- you link with <varname>libtcmalloc.a</varname>, memcheck
- will properly work when you give the
- option <option>--soname-synonyms=somalloc=NONE</option>. Note
- that a NONE pattern will match the main executable and any
- shared library having no soname. </para>
+ <para>Replacements in a statically linked library are done
+ by using the <varname>NONE</varname> pattern. For example,
+ if you link with <varname>libtcmalloc.a</varname>, and only
+ want to intercept the malloc related functions in the
+ executable (and standard libraries) themselves, but not any
+ other shared libraries, you can give the
+ option <option>--soname-synonyms=somalloc=NONE</option>.
+ Note that a NONE pattern will match the main executable and
+ any shared library having no soname. </para>
</listitem>
<listitem>
@@ -2369,6 +2381,17 @@
</para>
</listitem>
+ <listitem>
+ <para>To only intercept allocation symbols in the default
+ system libraries, but not in any other shared library or the
+ executable defining public malloc or operator new related
+ functions use a non-existing library name
+ like <option>--soname-synonyms=somalloc=nouserintercepts</option>
+ (where <varname>nouserintercepts</varname> can be any
+ non-existing library name).
+ </para>
+ </listitem>
+
</itemizedlist>
</listitem>
</varlistentry>
Modified: trunk/include/pub_tool_redir.h
==============================================================================
--- trunk/include/pub_tool_redir.h (original)
+++ trunk/include/pub_tool_redir.h Sun Nov 15 16:50:43 2015
@@ -345,6 +345,12 @@
#define VG_SO_SYN_PREFIX "VgSoSyn"
#define VG_SO_SYN_PREFIX_LEN 7
+// Special soname synonym place holder for the malloc symbols that can
+// be replaced using --soname-synonyms. Otherwise will match all
+// public symbols in any shared library/executable.
+#define SO_SYN_MALLOC VG_SO_SYN(somalloc)
+#define SO_SYN_MALLOC_NAME "VgSoSynsomalloc"
+
#endif // __PUB_TOOL_REDIR_H
/*--------------------------------------------------------------------*/
Modified: trunk/memcheck/tests/Makefile.am
==============================================================================
--- trunk/memcheck/tests/Makefile.am (original)
+++ trunk/memcheck/tests/Makefile.am Sun Nov 15 16:50:43 2015
@@ -291,6 +291,9 @@
wrap7.vgtest wrap7.stdout.exp wrap7.stderr.exp \
wrap8.vgtest wrap8.stdout.exp wrap8.stderr.exp \
wrap8.stdout.exp-ppc64 wrap8.stderr.exp-ppc64 \
+ wrapmalloc.vgtest wrapmalloc.stdout.exp wrapmalloc.stderr.exp \
+ wrapmallocstatic.vgtest wrapmallocstatic.stdout.exp \
+ wrapmallocstatic.stderr.exp \
writev1.stderr.exp writev1.stderr.exp-solaris writev1.vgtest \
xml1.stderr.exp xml1.stdout.exp xml1.vgtest xml1.stderr.exp-s390x-mvc \
threadname.vgtest threadname.stderr.exp \
@@ -375,6 +378,7 @@
wcs \
xml1 \
wrap1 wrap2 wrap3 wrap4 wrap5 wrap6 wrap7 wrap7so.so wrap8 \
+ wrapmalloc wrapmallocso.so wrapmallocstatic \
writev1
if !SOLARIS_SUN_STUDIO_AS
@@ -570,4 +574,26 @@
-Wl,-soname -Wl,wrap7so.so
endif
+# Build shared object for wrapmalloc
+wrapmalloc_SOURCES = wrapmalloc.c
+wrapmalloc_DEPENDENCIES = wrapmallocso.so
+if VGCONF_OS_IS_DARWIN
+ wrapmalloc_LDADD = `pwd`/wrapmallocso.so
+ wrapmalloc_LDFLAGS = $(AM_FLAG_M3264_PRI)
+else
+ wrapmalloc_LDADD = wrapmallocso.so
+ wrapmalloc_LDFLAGS = $(AM_FLAG_M3264_PRI) \
+ -Wl,-rpath,$(top_builddir)/memcheck/tests
+endif
+
+wrapmallocso_so_SOURCES = wrapmallocso.c
+wrapmallocso_so_CFLAGS = $(AM_CFLAGS) -fpic
+if VGCONF_OS_IS_DARWIN
+ wrapmallocso_so_LDFLAGS = -fpic $(AM_FLAG_M3264_PRI) -dynamic \
+ -dynamiclib -all_load
+else
+ wrapmallocso_so_LDFLAGS = -fpic $(AM_FLAG_M3264_PRI) -shared \
+ -Wl,-soname -Wl,wrapmallocso.so
+endif
+
xml1_CFLAGS = $(AM_CFLAGS) -D_GNU_SOURCE
Modified: trunk/memcheck/tests/new_override.vgtest
==============================================================================
--- trunk/memcheck/tests/new_override.vgtest (original)
+++ trunk/memcheck/tests/new_override.vgtest Sun Nov 15 16:50:43 2015
@@ -1,2 +1,6 @@
prog: new_override
+# Don't override the user defined somalloc functions in this test.
+# The test depends on some side effects and initializing memory done by
+# the user overidden operator new.
+vgopts: --soname-synonyms=somalloc=nouseroverride
stderr_filter: filter_allocs
Added: trunk/memcheck/tests/wrapmalloc.c
==============================================================================
--- trunk/memcheck/tests/wrapmalloc.c (added)
+++ trunk/memcheck/tests/wrapmalloc.c Sun Nov 15 16:50:43 2015
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Test that a program that has malloc/free interposed in a shared
+ library is also intercepted. */
+
+int main ( void )
+{
+ printf ("start\n");
+ void *p = malloc (1024);
+ free (p);
+ printf ("done\n");
+ return 0;
+}
Added: trunk/memcheck/tests/wrapmalloc.stderr.exp
==============================================================================
--- trunk/memcheck/tests/wrapmalloc.stderr.exp (added)
+++ trunk/memcheck/tests/wrapmalloc.stderr.exp Sun Nov 15 16:50:43 2015
@@ -0,0 +1,10 @@
+
+
+HEAP SUMMARY:
+ in use at exit: 0 bytes in 0 blocks
+ total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
+
+For a detailed leak analysis, rerun with: --leak-check=full
+
+For counts of detected and suppressed errors, rerun with: -v
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Added: trunk/memcheck/tests/wrapmalloc.stdout.exp
==============================================================================
--- trunk/memcheck/tests/wrapmalloc.stdout.exp (added)
+++ trunk/memcheck/tests/wrapmalloc.stdout.exp Sun Nov 15 16:50:43 2015
@@ -0,0 +1,2 @@
+start
+done
Added: trunk/memcheck/tests/wrapmalloc.vgtest
==============================================================================
--- trunk/memcheck/tests/wrapmalloc.vgtest (added)
+++ trunk/memcheck/tests/wrapmalloc.vgtest Sun Nov 15 16:50:43 2015
@@ -0,0 +1,2 @@
+prog: wrapmalloc
+
Added: trunk/memcheck/tests/wrapmallocso.c
==============================================================================
--- trunk/memcheck/tests/wrapmallocso.c (added)
+++ trunk/memcheck/tests/wrapmallocso.c Sun Nov 15 16:50:43 2015
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Fake malloc/free functions that just print something. When run
+ under memcheck these functions will be intercepted and not print
+ anything. */
+
+void *malloc ( size_t size )
+{
+ printf ("malloc\n");
+ return NULL;
+}
+
+void free (void *ptr)
+{
+ printf ("free\n");
+}
Added: trunk/memcheck/tests/wrapmallocstatic.c
==============================================================================
--- trunk/memcheck/tests/wrapmallocstatic.c (added)
+++ trunk/memcheck/tests/wrapmallocstatic.c Sun Nov 15 16:50:43 2015
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Test that a program that has malloc/free interposed in the
+ executable is also intercepted. */
+
+int main ( void )
+{
+ printf ("start\n");
+ void *p = malloc (1024);
+ free (p);
+ printf ("done\n");
+ return 0;
+}
+
+/* Fake malloc/free functions that just print something. When run
+ under memcheck these functions will be intercepted and not print
+ anything. */
+
+void *malloc ( size_t size )
+{
+ printf ("malloc\n");
+ return NULL;
+}
+
+void free (void *ptr)
+{
+ printf ("free\n");
+}
Added: trunk/memcheck/tests/wrapmallocstatic.stderr.exp
==============================================================================
--- trunk/memcheck/tests/wrapmallocstatic.stderr.exp (added)
+++ trunk/memcheck/tests/wrapmallocstatic.stderr.exp Sun Nov 15 16:50:43 2015
@@ -0,0 +1,10 @@
+
+
+HEAP SUMMARY:
+ in use at exit: 0 bytes in 0 blocks
+ total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
+
+For a detailed leak analysis, rerun with: --leak-check=full
+
+For counts of detected and suppressed errors, rerun with: -v
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Added: trunk/memcheck/tests/wrapmallocstatic.stdout.exp
==============================================================================
--- trunk/memcheck/tests/wrapmallocstatic.stdout.exp (added)
+++ trunk/memcheck/tests/wrapmallocstatic.stdout.exp Sun Nov 15 16:50:43 2015
@@ -0,0 +1,2 @@
+start
+done
Added: trunk/memcheck/tests/wrapmallocstatic.vgtest
==============================================================================
--- trunk/memcheck/tests/wrapmallocstatic.vgtest (added)
+++ trunk/memcheck/tests/wrapmallocstatic.vgtest Sun Nov 15 16:50:43 2015
@@ -0,0 +1,2 @@
+prog: wrapmallocstatic
+
|
|
From: Ivo R. <iv...@iv...> - 2015-11-16 12:31:04
|
Hi Mark,
Please could you help me with the necessary changes to unbreak the Solaris
build.
My understanding is that the following piece of code in m_redir.c is
crucial:
// If the user didn't set it then somalloc is special. We
// want to match public/global symbols that match the
// fnpatt everywhere.
if (replaced_sopatt == NULL
&& VG_(strcmp) ( demangled_sopatt, SO_SYN_MALLOC_NAME ) == 0)
{
replaced_sopatt = VG_(strdup)("m_redir.rnnD.1", "*");
demangled_sopatt = replaced_sopatt;
isGlobal = True;
}
So I read it that if the user did not set any --soname-synonyms then the
current functionality
instructs the redirection module to intercept all public somalloc functions
in all libraries/binaries.
I need to exclude runtime linker on Solaris from this equation. More
precisely,
I think instead of "*" I need something like: "*" except VG_Z_LD_SO_1
library
as listed in pub_tool_redir.h. I did not figure how this can accomplished,
yet.
Please could you shed some light in how to do this? The reason why to
exclude
Solaris runtime linker is because the library has public functions called
malloc/free/... but with different semantics and different behaviour than
the standard ones from libc and friends.
Kind regards,
I.
2015-11-15 17:50 GMT+01:00 <sv...@va...>:
> Author: mjw
> Date: Sun Nov 15 16:50:43 2015
> New Revision: 15726
>
> Log:
> BZ#355188 valgrind should intercept all malloc related global functions.
>
> This implements the interception of all globally public allocation
> functions by default. It works by adding a flag to the spec to say the
> interception only applies to global functions. Which is set for the
> somalloc spec. The librarypath to match is set to "*" unless the user
> overrides it. Then each DiSym keeps track of whether the symbol is local
> or global. For a spec which has isGlobal set only isGlobal symbols will
> match.
>
> Note that because of padding to keep the addresses in DiSym aligned the
> addition of the extra bool isGlobal doesn't actually grow the struct.
> The comments explain how the struct could be made more compact on 32bit
> systems, but this isn't as easy on 64bit systems. So I didn't try to do
> that in this patch.
>
> For ELF symbols keeping track of which are global is trivial. For pdb I
> had to guess and made only the "Public" symbols global. I don't know
> how/if macho keeps track of global symbols or not. For now I just mark
> all of them local (which just means things work as previously on platforms
> that use machos, no non-system symbols are matches by default for somalloc
> unless the user explicitly tells which library name to match).
>
> Included are two testcases for shared libraries (wrapmalloc) and staticly
> linked (wrapmallocstatic) malloc/free overrides that depend on the new
> default. One existing testcase (new_override) was adjusted to explicitly
> not use the new somalloc default because it depends on a user defined
> new implementation that has side-effects and should explicitly not be
> intercepted.
>
> Added:
> trunk/memcheck/tests/wrapmalloc.c
> trunk/memcheck/tests/wrapmalloc.stderr.exp
> trunk/memcheck/tests/wrapmalloc.stdout.exp
> trunk/memcheck/tests/wrapmalloc.vgtest
> trunk/memcheck/tests/wrapmallocso.c
> trunk/memcheck/tests/wrapmallocstatic.c
> trunk/memcheck/tests/wrapmallocstatic.stderr.exp
> trunk/memcheck/tests/wrapmallocstatic.stdout.exp
> trunk/memcheck/tests/wrapmallocstatic.vgtest
> Modified:
> trunk/NEWS
> trunk/coregrind/m_debuginfo/debuginfo.c
> trunk/coregrind/m_debuginfo/priv_storage.h
> trunk/coregrind/m_debuginfo/readelf.c
> trunk/coregrind/m_debuginfo/readmacho.c
> trunk/coregrind/m_debuginfo/readpdb.c
> trunk/coregrind/m_debuginfo/storage.c
> trunk/coregrind/m_redir.c
> trunk/coregrind/m_replacemalloc/vg_replace_malloc.c
> trunk/coregrind/pub_core_debuginfo.h
> trunk/docs/xml/manual-core.xml
> trunk/include/pub_tool_redir.h
> trunk/memcheck/tests/Makefile.am
> trunk/memcheck/tests/new_override.vgtest
>
> Modified: trunk/NEWS
>
> ==============================================================================
> --- trunk/NEWS (original)
> +++ trunk/NEWS Sun Nov 15 16:50:43 2015
> @@ -17,6 +17,14 @@
>
> * ==================== OTHER CHANGES ====================
>
> +* Replacement/wrapping of malloc/new related functions is now done not
> just
> + for system libraries by default, but for any globally defined malloc/new
> + related function (both in shared libraries and staticly linked
> alternative
> + malloc implementations). To only intercept malloc/new related functions
> in
> + system libraries use --soname-synonyms=somalloc=nouserintercepts (where
> + "nouserintercepts" can be any non-existing library name).
> + This new functionality is not implemented for darwin/macosx.
> +
> * ==================== FIXED BUGS ====================
>
> The following bugs have been fixed or resolved. Note that "n-i-bz"
> @@ -42,6 +50,7 @@
> 354392 unhandled amd64-solaris syscall: 171
> 354797 Added vbit tester support for PPC 64 isa 2.07 iops
> 354933 Fix documentation of --kernel-variant=android-no-hw-tls option
> +355188 valgrind should intercept all malloc related global functions
>
|
|
From: Mark W. <mj...@re...> - 2015-11-16 12:55:40
|
Hi Ivo,
On Mon, 2015-11-16 at 13:29 +0100, Ivo Raisr wrote:
> Please could you help me with the necessary changes to unbreak the Solaris
> build.
> My understanding is that the following piece of code in m_redir.c is
> crucial:
>
> // If the user didn't set it then somalloc is special. We
> // want to match public/global symbols that match the
> // fnpatt everywhere.
> if (replaced_sopatt == NULL
> && VG_(strcmp) ( demangled_sopatt, SO_SYN_MALLOC_NAME ) == 0)
> {
> replaced_sopatt = VG_(strdup)("m_redir.rnnD.1", "*");
> demangled_sopatt = replaced_sopatt;
> isGlobal = True;
> }
>
> So I read it that if the user did not set any --soname-synonyms then the
> current functionality
> instructs the redirection module to intercept all public somalloc functions
> in all libraries/binaries.
Yes, indeed.
> I need to exclude runtime linker on Solaris from this equation. More
> precisely,
> I think instead of "*" I need something like: "*" except VG_Z_LD_SO_1
> library
> as listed in pub_tool_redir.h. I did not figure how this can accomplished,
> yet.
> Please could you shed some light in how to do this?
The spec matcher uses string_match, which calls generic_match, to do a
pattern match on a sequence. See include/pub_tool_seqmatch.h for a
description. It seems very flexible, but I don't believe that does
negative matching though. So you might just have to explicitly filter
out the solaris ld.so when Spec from_sopatt equals "*" and isGlobal ==
True. That seems a reasonable thing to do in general, the dynamic linker
is special and we probably never want to match generic global symbols in
it, so maybe do it for any ld.so (I don't immediately see how to get the
ld.so name for the binary/platform though). You will want to tweak the
start of generate_and_add_actives in m_redir.c where it sets the
sp->mark using string_match.
> The reason why to
> exclude
> Solaris runtime linker is because the library has public functions called
> malloc/free/... but with different semantics and different behaviour than
> the standard ones from libc and friends.
If it does then it really shouldn't make those public global symbols.
Maybe you can tweak ld.so to make those functions static/private? That
of course doesn't help with older systems, but might help in the future
not having to special case the Solaris ld.so.
Cheers,
Mark
|
|
From: Ivo R. <iv...@iv...> - 2015-11-16 20:35:37
|
2015-11-16 13:55 GMT+01:00 Mark Wielaard <mj...@re...>: > > I need to exclude runtime linker on Solaris from this equation. More > > precisely, > > I think instead of "*" I need something like: "*" except VG_Z_LD_SO_1 > > library > > as listed in pub_tool_redir.h. I did not figure how this can > accomplished, > > yet. > > Please could you shed some light in how to do this? > > The spec matcher uses string_match, which calls generic_match, to do a > pattern match on a sequence. See include/pub_tool_seqmatch.h for a > description. It seems very flexible, but I don't believe that does > negative matching though. So you might just have to explicitly filter > out the solaris ld.so when Spec from_sopatt equals "*" and isGlobal == > True. That seems a reasonable thing to do in general, the dynamic linker > is special and we probably never want to match generic global symbols in > it, so maybe do it for any ld.so (I don't immediately see how to get the > ld.so name for the binary/platform though). You will want to tweak the > start of generate_and_add_actives in m_redir.c where it sets the > sp->mark using string_match. > Hi Mark, Thank you a lot for an explanation and guidance. Please have a look at the patch attached to bug: 355454 do not intercept malloc related symbols from the runtime linker https://bugs.kde.org/show_bug.cgi?id=355454 Currently it filters out only Solaris runtime linker. Linux runtime linkers could be filtered out as well but I am not sure which ones are relevant. There are just too many in pub_tool_redir.h... Cheers, I. |
|
From: Mark W. <mj...@re...> - 2015-11-17 09:41:50
|
On Mon, 2015-11-16 at 21:35 +0100, Ivo Raisr wrote: > Thank you a lot for an explanation and guidance. > Please have a look at the patch attached to bug: > 355454 do not intercept malloc related symbols from the runtime linker > https://bugs.kde.org/show_bug.cgi?id=355454 Yes, that looks like the right way to fix this. I would expand the comment a bit to make sure people looking at it later know what it really refers to. Maybe start with "When searching for global public symbols (like for the somalloc synonym symbols), exclude...". > Currently it filters out only Solaris runtime linker. Linux runtime linkers > could > be filtered out as well but I am not sure which ones are relevant. There > are just > too many in pub_tool_redir.h... Yeah, it seems that is a bit of a mess :{ Every platform/arch combination seems to invent their own name for the dynamic linker. I don't believe there is an easy way to catch them all. Independent from this fix we might want to introduce a new redir function Bool VG_(is_soname_ld_so) (const HChar* soname) that a tool can use to test whether the so they are looking at is the dynamic loader. See helgrind/hg_main.c (is_in_dynamic_linker_shared_object) for another use. Thanks, Mark |
|
From: Ivo R. <iv...@iv...> - 2015-11-18 05:21:15
|
2015-11-17 10:41 GMT+01:00 Mark Wielaard <mj...@re...>: > > > 355454 do not intercept malloc related symbols from the runtime linker > > https://bugs.kde.org/show_bug.cgi?id=355454 > > Yes, that looks like the right way to fix this. > I would expand the comment a bit to make sure people looking at it later > know what it really refers to. Maybe start with "When searching for > global public symbols (like for the somalloc synonym symbols), > exclude...". > Comment reworded. Also documentation amended. > Independent from this fix we might want to introduce a new redir > function Bool VG_(is_soname_ld_so) (const HChar* soname) that a tool can > use to test whether the so they are looking at is the dynamic loader. > This is a necessary refactoring for this fix. Please find another patch under https://bugs.kde.org/show_bug.cgi?id=355454 which targets all platforms. I. |
|
From: Mark W. <mj...@re...> - 2015-11-18 10:00:24
|
On Wed, 2015-11-18 at 06:21 +0100, Ivo Raisr wrote: > Please find another patch under https://bugs.kde.org/show_bug.cgi?id=355454 > which targets all platforms. This looks good to me. Thanks, Mark |