Author: bart
Date: 2009-05-09 10:55:46 +0100 (Sat, 09 May 2009)
New Revision: 9802
Log:
Merged trunk revisions r9731:9796.
Added:
branches/DRDDEV/coregrind/m_aspacehl.c
branches/DRDDEV/coregrind/pub_core_aspacehl.h
branches/DRDDEV/include/pub_tool_aspacehl.h
branches/DRDDEV/memcheck/perf/
Removed:
branches/DRDDEV/memcheck/tests/mempool.stderr.exp64
branches/DRDDEV/memcheck/tests/post-syscall.stderr.exp2
branches/DRDDEV/memcheck/tests/post-syscall.stdout.exp
branches/DRDDEV/memcheck/tests/sigkill.stderr.exp2
branches/DRDDEV/memcheck/tests/sigkill.stderr.exp3
Modified:
branches/DRDDEV/configure.in
branches/DRDDEV/coregrind/Makefile.am
branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-common.c
branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-linux.c
branches/DRDDEV/coregrind/m_aspacemgr/priv_aspacemgr.h
branches/DRDDEV/coregrind/m_coredump/coredump-elf.c
branches/DRDDEV/coregrind/m_demangle/demangle.c
branches/DRDDEV/coregrind/m_errormgr.c
branches/DRDDEV/coregrind/m_execontext.c
branches/DRDDEV/coregrind/m_hashtable.c
branches/DRDDEV/coregrind/m_libcfile.c
branches/DRDDEV/coregrind/m_main.c
branches/DRDDEV/coregrind/m_signals.c
branches/DRDDEV/coregrind/m_stacktrace.c
branches/DRDDEV/coregrind/m_ume/priv_ume.h
branches/DRDDEV/coregrind/pub_core_ume.h
branches/DRDDEV/drd/drd_strmem_intercepts.c
branches/DRDDEV/drd/tests/rwlock_test.c
branches/DRDDEV/exp-ptrcheck/h_intercepts.c
branches/DRDDEV/helgrind/hg_intercepts.c
branches/DRDDEV/helgrind/libhb_core.c
branches/DRDDEV/include/Makefile.am
branches/DRDDEV/include/pub_tool_hashtable.h
branches/DRDDEV/include/pub_tool_oset.h
branches/DRDDEV/include/pub_tool_redir.h
branches/DRDDEV/massif/perf/Makefile.am
branches/DRDDEV/memcheck/Makefile.am
branches/DRDDEV/memcheck/mc_errors.c
branches/DRDDEV/memcheck/mc_include.h
branches/DRDDEV/memcheck/mc_leakcheck.c
branches/DRDDEV/memcheck/mc_replace_strmem.c
branches/DRDDEV/memcheck/tests/Makefile.am
branches/DRDDEV/memcheck/tests/leak-cases-full.stderr.exp
branches/DRDDEV/memcheck/tests/leak-cycle.stderr.exp
branches/DRDDEV/memcheck/tests/memalign2.c
branches/DRDDEV/memcheck/tests/mempool.c
branches/DRDDEV/memcheck/tests/mempool.stderr.exp
branches/DRDDEV/memcheck/tests/post-syscall.c
branches/DRDDEV/memcheck/tests/post-syscall.stderr.exp
branches/DRDDEV/memcheck/tests/post-syscall.vgtest
branches/DRDDEV/none/tests/Makefile.am
Modified: branches/DRDDEV/configure.in
===================================================================
--- branches/DRDDEV/configure.in 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/configure.in 2009-05-09 09:55:46 UTC (rev 9802)
@@ -1751,6 +1751,7 @@
memcheck/tests/x86/Makefile
memcheck/tests/linux/Makefile
memcheck/tests/x86-linux/Makefile
+ memcheck/perf/Makefile
memcheck/docs/Makefile
cachegrind/Makefile
cachegrind/tests/Makefile
Modified: branches/DRDDEV/coregrind/Makefile.am
===================================================================
--- branches/DRDDEV/coregrind/Makefile.am 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/Makefile.am 2009-05-09 09:55:46 UTC (rev 9802)
@@ -102,6 +102,7 @@
noinst_HEADERS = \
+ pub_core_aspacehl.h \
pub_core_aspacemgr.h \
pub_core_basics.h \
pub_core_basics_asm.h \
@@ -221,6 +222,7 @@
m_vkiscnums.c \
m_wordfm.c \
m_xarray.c \
+ m_aspacehl.c \
m_aspacemgr/aspacemgr-common.c \
m_debuginfo/misc.c \
m_debuginfo/d3basics.c \
Copied: branches/DRDDEV/coregrind/m_aspacehl.c (from rev 9796, trunk/coregrind/m_aspacehl.c)
===================================================================
--- branches/DRDDEV/coregrind/m_aspacehl.c (rev 0)
+++ branches/DRDDEV/coregrind/m_aspacehl.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -0,0 +1,71 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Services layered on top of m_aspacemgr. m_aspacehl.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2009 Julian Seward
+ js...@ac...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_mallocfree.h"
+
+#include "pub_core_aspacehl.h"
+
+// Extract from aspacem a vector of the current segment start
+// addresses. The vector is dynamically allocated and should be freed
+// by the caller when done. REQUIRES m_mallocfree to be running.
+// Writes the number of addresses required into *n_acquired.
+Addr* VG_(get_segment_starts) ( /*OUT*/Int* n_acquired )
+{
+ Addr* starts;
+ Int n_starts, r = 0;
+
+ n_starts = 1;
+ while (True) {
+ starts = VG_(malloc)( "main.gss.1", n_starts * sizeof(Addr) );
+ if (starts == NULL)
+ break;
+ r = VG_(am_get_segment_starts)( starts, n_starts );
+ if (r >= 0)
+ break;
+ VG_(free)(starts);
+ n_starts *= 2;
+ }
+
+ if (starts == NULL) {
+ *n_acquired = 0;
+ return NULL;
+ }
+
+ *n_acquired = r;
+ return starts;
+}
+
+
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Modified: branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-common.c
===================================================================
--- branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-common.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-common.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -253,6 +253,12 @@
return res.isError ? -1 : res.res;
}
+Int ML_(am_fcntl) ( Int fd, Int cmd, Addr arg )
+{
+ SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
+ return res.isError ? -1 : res.res;
+}
+
/* Get the dev, inode and mode info for a file descriptor, if
possible. Returns True on success. */
Bool ML_(am_get_fd_d_i_m)( Int fd,
@@ -284,7 +290,30 @@
return False;
}
+Bool ML_(am_resolve_filename) ( Int fd, /*OUT*/HChar* buf, Int nbuf )
+{
+#if defined(VGO_linux)
+ Int i;
+ HChar tmp[64];
+ for (i = 0; i < nbuf; i++) buf[i] = 0;
+ ML_(am_sprintf)(tmp, "/proc/self/fd/%d", fd);
+ if (ML_(am_readlink)(tmp, buf, nbuf) > 0 && buf[0] == '/')
+ return True;
+ else
+ return False;
+#elif defined(VGO_aix5)
+ I_die_here; /* maybe just return False? */
+ return False;
+
+# else
+# error Unknown OS
+# endif
+}
+
+
+
+
/*-----------------------------------------------------------------*/
/*--- ---*/
/*--- Manage stacks for Valgrind itself. ---*/
Modified: branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-linux.c
===================================================================
--- branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-linux.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-linux.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -338,39 +338,6 @@
/*-----------------------------------------------------------------*/
/*--- ---*/
-/*--- Functions for finding information about file descriptors. ---*/
-/*--- ---*/
-/*-----------------------------------------------------------------*/
-
-/* Extract the device, inode and mode numbers for a fd. */
-static
-Bool get_inode_for_fd ( Int fd, /*OUT*/ULong* dev,
- /*OUT*/ULong* ino, /*OUT*/UInt* mode )
-{
- return ML_(am_get_fd_d_i_m)(fd, dev, ino, mode);
-}
-
-/* Given a file descriptor, attempt to deduce its filename. To do
- this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
- or if it doesn't exist, we return False. */
-static
-Bool get_name_for_fd ( Int fd, /*OUT*/HChar* buf, Int nbuf )
-{
- Int i;
- HChar tmp[64];
-
- ML_(am_sprintf)(tmp, "/proc/self/fd/%d", fd);
- for (i = 0; i < nbuf; i++) buf[i] = 0;
-
- if (ML_(am_readlink)(tmp, buf, nbuf) > 0 && buf[0] == '/')
- return True;
- else
- return False;
-}
-
-
-/*-----------------------------------------------------------------*/
-/*--- ---*/
/*--- SegName array management. ---*/
/*--- ---*/
/*-----------------------------------------------------------------*/
@@ -1959,12 +1926,12 @@
if (!(flags & VKI_MAP_ANONYMOUS)) {
// Nb: We ignore offset requests in anonymous mmaps (see bug #126722)
seg.offset = offset;
- if (get_inode_for_fd(fd, &dev, &ino, &mode)) {
+ if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) {
seg.dev = dev;
seg.ino = ino;
seg.mode = mode;
}
- if (get_name_for_fd(fd, buf, VKI_PATH_MAX)) {
+ if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
seg.fnIdx = allocate_segname( buf );
}
}
@@ -2174,12 +2141,12 @@
seg.hasR = toBool(prot & VKI_PROT_READ);
seg.hasW = toBool(prot & VKI_PROT_WRITE);
seg.hasX = toBool(prot & VKI_PROT_EXEC);
- if (get_inode_for_fd(fd, &dev, &ino, &mode)) {
+ if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) {
seg.dev = dev;
seg.ino = ino;
seg.mode = mode;
}
- if (get_name_for_fd(fd, buf, VKI_PATH_MAX)) {
+ if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
seg.fnIdx = allocate_segname( buf );
}
add_segment( &seg );
@@ -2449,12 +2416,12 @@
seg.hasR = toBool(prot & VKI_PROT_READ);
seg.hasW = toBool(prot & VKI_PROT_WRITE);
seg.hasX = toBool(prot & VKI_PROT_EXEC);
- if (get_inode_for_fd(fd, &dev, &ino, &mode)) {
+ if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) {
seg.dev = dev;
seg.ino = ino;
seg.mode = mode;
}
- if (get_name_for_fd(fd, buf, VKI_PATH_MAX)) {
+ if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) {
seg.fnIdx = allocate_segname( buf );
}
add_segment( &seg );
Modified: branches/DRDDEV/coregrind/m_aspacemgr/priv_aspacemgr.h
===================================================================
--- branches/DRDDEV/coregrind/m_aspacemgr/priv_aspacemgr.h 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_aspacemgr/priv_aspacemgr.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -43,7 +43,7 @@
#include "pub_core_debuglog.h" // VG_(debugLog)
-#include "pub_core_libcbase.h" // VG_(strlen), VG_(strcmp)
+#include "pub_core_libcbase.h" // VG_(strlen), VG_(strcmp), VG_(strncpy)
// VG_IS_PAGE_ALIGNED
// VG_PGROUNDDN, VG_PGROUNDUP
@@ -109,14 +109,18 @@
extern void ML_(am_close) ( Int fd );
extern Int ML_(am_read) ( Int fd, void* buf, Int count);
extern Int ML_(am_readlink) ( HChar* path, HChar* buf, UInt bufsiz );
+extern Int ML_(am_fcntl) ( Int fd, Int cmd, Addr arg );
/* Get the dev, inode and mode info for a file descriptor, if
possible. Returns True on success. */
extern
Bool ML_(am_get_fd_d_i_m)( Int fd,
- /*OUT*/ULong* dev,
- /*OUT*/ULong* ino, /*OUT*/UInt* mode );
+ /*OUT*/ULong* dev,
+ /*OUT*/ULong* ino, /*OUT*/UInt* mode );
+extern
+Bool ML_(am_resolve_filename) ( Int fd, /*OUT*/HChar* buf, Int nbuf );
+
/* ------ Implemented seperately in aspacemgr-{linux,aix5}.c ------ */
/* Do a sanity check (/proc/self/maps sync check) */
Modified: branches/DRDDEV/coregrind/m_coredump/coredump-elf.c
===================================================================
--- branches/DRDDEV/coregrind/m_coredump/coredump-elf.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_coredump/coredump-elf.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -30,6 +30,7 @@
#include "pub_core_basics.h"
#include "pub_core_vki.h"
+#include "pub_core_aspacehl.h"
#include "pub_core_aspacemgr.h"
#include "pub_core_libcbase.h"
#include "pub_core_machine.h"
@@ -65,39 +66,6 @@
#error VG_WORDSIZE needs to ==4 or ==8
#endif
-/* TODO: GIVE THIS A PROPER HOME
- TODO: MERGE THIS WITH DUPLICATES IN m_main.c and mc_leakcheck.c
- Extract from aspacem a vector of the current segment start
- addresses. The vector is dynamically allocated and should be freed
- by the caller when done. REQUIRES m_mallocfree to be running.
- Writes the number of addresses required into *n_acquired. */
-
-static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
-{
- Addr* starts;
- Int n_starts, r = 0;
-
- n_starts = 1;
- while (True) {
- starts = VG_(malloc)( "coredump-elf.gss.1", n_starts * sizeof(Addr) );
- if (starts == NULL)
- break;
- r = VG_(am_get_segment_starts)( starts, n_starts );
- if (r >= 0)
- break;
- VG_(free)(starts);
- n_starts *= 2;
- }
-
- if (starts == NULL) {
- *n_acquired = 0;
- return NULL;
- }
-
- *n_acquired = r;
- return starts;
-}
-
/* If true, then this Segment may be mentioned in the core */
static Bool may_dump(const NSegment *seg)
{
@@ -342,7 +310,7 @@
}
/* Get the segments */
- seg_starts = get_seg_starts(&n_seg_starts);
+ seg_starts = VG_(get_segment_starts)(&n_seg_starts);
/* First, count how many memory segments to dump */
num_phdrs = 1; /* start with notes */
Modified: branches/DRDDEV/coregrind/m_demangle/demangle.c
===================================================================
--- branches/DRDDEV/coregrind/m_demangle/demangle.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_demangle/demangle.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -167,7 +167,7 @@
} \
} while (0)
- Bool error, oflow, valid, fn_is_encoded;
+ Bool error, oflow, valid, fn_is_encoded, is_VG_Z_prefixed;
Int soi, fni, i;
vg_assert(soLen > 0 || (soLen == 0 && so == NULL));
@@ -192,6 +192,19 @@
if (isWrap)
*isWrap = sym[3] == 'w';
+ /* Now check the soname prefix isn't "VG_Z_", as described in
+ pub_tool_redir.h. */
+ is_VG_Z_prefixed =
+ sym[ 7] == 'V' &&
+ sym[ 8] == 'G' &&
+ sym[ 9] == '_' &&
+ sym[10] == 'Z' &&
+ sym[11] == '_';
+ 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) {
Modified: branches/DRDDEV/coregrind/m_errormgr.c
===================================================================
--- branches/DRDDEV/coregrind/m_errormgr.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_errormgr.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -415,12 +415,7 @@
static void gen_suppression(Error* err)
{
ExeContext* ec = VG_(get_error_where)(err);
- Int stop_at = VG_(clo_backtrace_size);
- /* At most VG_MAX_SUPP_CALLERS names */
- if (stop_at > VG_MAX_SUPP_CALLERS) stop_at = VG_MAX_SUPP_CALLERS;
- vg_assert(stop_at > 0);
-
//(example code, see comment on CoreSuppKind above)
if (0) {
//if (0) ThreadErr == err->ekind) {
@@ -443,7 +438,8 @@
// Print stack trace elements
VG_(apply_StackTrace)(printSuppForIp,
- VG_(get_ExeContext_StackTrace)(ec), stop_at);
+ VG_(get_ExeContext_StackTrace)(ec),
+ VG_(get_ExeContext_n_ips)(ec));
VG_(printf)("}\n");
}
Modified: branches/DRDDEV/coregrind/m_execontext.c
===================================================================
--- branches/DRDDEV/coregrind/m_execontext.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_execontext.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -319,7 +319,7 @@
first_ip_delta );
}
- return record_ExeContext_wrk2 ( &ips[0], n_ips );
+ return record_ExeContext_wrk2 ( ips, n_ips );
}
/* Do the second part of getting a stack trace: ips[0 .. n_ips-1]
Modified: branches/DRDDEV/coregrind/m_hashtable.c
===================================================================
--- branches/DRDDEV/coregrind/m_hashtable.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_hashtable.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -190,10 +190,9 @@
return NULL;
}
-/* Allocates a suitably-sized array, copies all the hashtable elements
- into it, then returns both the array and the size of it. This is
- used by the memory-leak detector. The array must be freed with
- VG_(free).
+/* Allocates a suitably-sized array, copies pointers to all the hashtable
+ elements into it, then returns both the array and the size of it. The
+ array must be freed with VG_(free).
*/
VgHashNode** VG_(HT_to_array) ( VgHashTable table, /*OUT*/ UInt* n_elems )
{
@@ -201,12 +200,7 @@
VgHashNode** arr;
VgHashNode* node;
- *n_elems = 0;
- for (i = 0; i < table->n_chains; i++) {
- for (node = table->chains[i]; node != NULL; node = node->next) {
- (*n_elems)++;
- }
- }
+ *n_elems = table->n_elements;
if (*n_elems == 0)
return NULL;
Modified: branches/DRDDEV/coregrind/m_libcfile.c
===================================================================
--- branches/DRDDEV/coregrind/m_libcfile.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_libcfile.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -82,11 +82,13 @@
return True;
else
return False;
+
# elif defined(VGO_aix5)
I_die_here; /* maybe just return False? */
return False;
+
# else
-# error "need fd-to-filename for this OS"
+# error Unknown OS
# endif
}
Modified: branches/DRDDEV/coregrind/m_main.c
===================================================================
--- branches/DRDDEV/coregrind/m_main.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_main.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -35,6 +35,7 @@
#include "pub_core_xarray.h"
#include "pub_core_clientstate.h"
#include "pub_core_aspacemgr.h"
+#include "pub_core_aspacehl.h"
#include "pub_core_commandline.h"
#include "pub_core_debuglog.h"
#include "pub_core_errormgr.h"
@@ -1122,40 +1123,6 @@
/* --- end of Forwards decls to do with shutdown --- */
-/* TODO: GIVE THIS A PROPER HOME
- TODO: MERGE THIS WITH DUPLICATE IN mc_leakcheck.c and coredump-elf.c.
- Extract from aspacem a vector of the current segment start
- addresses. The vector is dynamically allocated and should be freed
- by the caller when done. REQUIRES m_mallocfree to be running.
- Writes the number of addresses required into *n_acquired. */
-
-static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
-{
- Addr* starts;
- Int n_starts, r = 0;
-
- n_starts = 1;
- while (True) {
- starts = VG_(malloc)( "main.gss.1", n_starts * sizeof(Addr) );
- if (starts == NULL)
- break;
- r = VG_(am_get_segment_starts)( starts, n_starts );
- if (r >= 0)
- break;
- VG_(free)(starts);
- n_starts *= 2;
- }
-
- if (starts == NULL) {
- *n_acquired = 0;
- return NULL;
- }
-
- *n_acquired = r;
- return starts;
-}
-
-
/* By the time we get to valgrind_main, the_iicii should already have
been filled in with any important details as required by whatever
OS we have been built for.
@@ -1730,7 +1697,7 @@
Int n_seg_starts;
Addr_n_ULong anu;
- seg_starts = get_seg_starts( &n_seg_starts );
+ seg_starts = VG_(get_segment_starts)( &n_seg_starts );
vg_assert(seg_starts && n_seg_starts >= 0);
/* show them all to the debug info reader. allow_SkFileV has to
@@ -1842,7 +1809,7 @@
tl_assert(VG_(running_tid) == VG_INVALID_THREADID);
VG_(running_tid) = tid_main;
- seg_starts = get_seg_starts( &n_seg_starts );
+ seg_starts = VG_(get_segment_starts)( &n_seg_starts );
vg_assert(seg_starts && n_seg_starts >= 0);
/* show interesting ones to the tool */
Modified: branches/DRDDEV/coregrind/m_signals.c
===================================================================
--- branches/DRDDEV/coregrind/m_signals.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_signals.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -42,7 +42,7 @@
client process stack, it is extended in the same way the kernel
would, and the fault is never reported to the client program.
- 2. Asynchronous varients of the above signals: If the kernel tries
+ 2. Asynchronous variants of the above signals: If the kernel tries
to deliver a sync signal while it is blocked, it just kills the
process. Therefore, we can't block those signals if we want to be
able to report on bugs in Valgrind. This means that we're also
@@ -79,6 +79,124 @@
always unblocked).
*/
+/*
+ Some more details...
+
+ First off, we take note of the client's requests (via sys_sigaction
+ and sys_sigprocmask) to set the signal state (handlers for each
+ signal, which are process-wide, + a mask for each signal, which is
+ per-thread). This info is duly recorded in the SCSS (static Client
+ signal state) in m_signals.c, and if the client later queries what
+ the state is, we merely fish the relevant info out of SCSS and give
+ it back.
+
+ However, we set the real signal state in the kernel to something
+ entirely different. This is recorded in SKSS, the static Kernel
+ signal state. What's nice (to the extent that anything is nice w.r.t
+ signals) is that there's a pure function to calculate SKSS from SCSS,
+ calculate_SKSS_from_SCSS. So when the client changes SCSS then we
+ recompute the associated SKSS and apply any changes from the previous
+ SKSS through to the kernel.
+
+ Now, that said, the general scheme we have now is, that regardless of
+ what the client puts into the SCSS (viz, asks for), what we would
+ like to do is as follows:
+
+ (1) run code on the virtual CPU with all signals blocked
+
+ (2) at convenient moments for us (that is, when the VCPU stops, and
+ control is back with the scheduler), ask the kernel "do you have
+ any signals for me?" and if it does, collect up the info, and
+ deliver them to the client (by building sigframes).
+
+ And that's almost what we do. The signal polling is done by
+ VG_(poll_signals), which calls through to VG_(sigtimedwait_zero) to
+ do the dirty work. (of which more later).
+
+ By polling signals, rather than catching them, we get to deal with
+ them only at convenient moments, rather than having to recover from
+ taking a signal while generated code is running.
+
+ Now unfortunately .. the above scheme only works for so-called async
+ signals. An async signal is one which isn't associated with any
+ particular instruction, eg Control-C (SIGINT). For those, it doesn't
+ matter if we don't deliver the signal to the client immediately; it
+ only matters that we deliver it eventually. Hence polling is OK.
+
+ But the other group -- sync signals -- are all related by the fact
+ that they are various ways for the host CPU to fail to execute an
+ instruction: SIGILL, SIGSEGV, SIGFPU. And they can't be deferred,
+ because obviously if a host instruction can't execute, well then we
+ have to immediately do Plan B, whatever that is.
+
+ So the next approximation of what happens is:
+
+ (1) run code on vcpu with all async signals blocked
+
+ (2) at convenient moments (when NOT running the vcpu), poll for async
+ signals.
+
+ (1) and (2) together imply that if the host does deliver a signal to
+ async_signalhandler while the VCPU is running, something's
+ seriously wrong.
+
+ (3) when running code on vcpu, don't block sync signals. Instead
+ register sync_signalhandler and catch any such via that. Of
+ course, that means an ugly recovery path if we do -- the
+ sync_signalhandler has to longjump, exiting out of the generated
+ code, and the assembly-dispatcher thingy that runs it, and gets
+ caught in m_scheduler, which then tells m_signals to deliver the
+ signal.
+
+ Now naturally (ha ha) even that might be tolerable, but there's
+ something worse: dealing with signals delivered to threads in
+ syscalls.
+
+ Obviously from the above, SKSS's signal mask (viz, what we really run
+ with) is way different from SCSS's signal mask (viz, what the client
+ thread thought it asked for). (eg) It may well be that the client
+ did not block control-C, so that it just expects to drop dead if it
+ receives ^C whilst blocked in a syscall, but by default we are
+ running with all async signals blocked, and so that signal could be
+ arbitrarily delayed, or perhaps even lost (not sure).
+
+ So what we have to do, when doing any syscall which SfMayBlock, is to
+ quickly switch in the SCSS-specified signal mask just before the
+ syscall, and switch it back just afterwards, and hope that we don't
+ get caught up in some wierd race condition. This is the primary
+ purpose of the ultra-magical pieces of assembly code in
+ coregrind/m_syswrap/syscall-<plat>.S
+
+ -----------
+
+ The ways in which V can come to hear of signals that need to be
+ forwarded to the client as are follows:
+
+ sync signals: can arrive at any time whatsoever. These are caught
+ by sync_signalhandler
+
+ async signals:
+
+ if running generated code
+ then these are blocked, so we don't expect to catch them in
+ async_signalhandler
+
+ else
+ if thread is blocked in a syscall marked SfMayBlock
+ then signals may be delivered to async_sighandler, since we
+ temporarily unblocked them for the duration of the syscall,
+ by using the real (SCSS) mask for this thread
+
+ else we're doing misc housekeeping activities (eg, making a translation,
+ washing our hair, etc). As in the normal case, these signals are
+ blocked, but we can and do poll for them using VG_(poll_signals).
+
+ Now, re VG_(poll_signals), it polls the kernel by doing
+ VG_(sigtimedwait_zero). This is trivial on Linux, since it's just a
+ syscall. But on Darwin and AIX, we have to cobble together the
+ functionality in a tedious, longwinded and probably error-prone way.
+ */
+
#include "pub_core_basics.h"
#include "pub_core_vki.h"
#include "pub_core_vkiscnums.h"
@@ -1757,12 +1875,12 @@
}
static
-void sync_signalhandler_from_outside ( ThreadId tid,
+void sync_signalhandler_from_user ( ThreadId tid,
Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc )
{
ThreadId qtid;
- /* If some user-process sent us a sync signal (ie, they're not the result
+ /* If some user-process sent us a sync signal (ie. it's not the result
of a faulting instruction), then how we treat it depends on when it
arrives... */
@@ -1890,7 +2008,7 @@
}
static
-void sync_signalhandler_from_inside ( ThreadId tid,
+void sync_signalhandler_from_kernel ( ThreadId tid,
Int sigNo, vki_siginfo_t *info, struct vki_ucontext *uc )
{
/* Check to see if some part of Valgrind itself is interested in faults.
@@ -1963,7 +2081,7 @@
vki_siginfo_t *info, struct vki_ucontext *uc )
{
ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)());
- Bool from_outside;
+ Bool from_user;
if (0)
VG_(printf)("sync_sighandler(%d, %p, %p)\n", sigNo, info, uc);
@@ -1978,14 +2096,14 @@
info->si_code = sanitize_si_code(info->si_code);
- from_outside = !is_signal_from_kernel(info->si_code);
+ from_user = !is_signal_from_kernel(info->si_code);
if (VG_(clo_trace_signals)) {
VG_DMSG("sync signal handler: "
"signal=%d, si_code=%d, EIP=%#lx, eip=%#lx, from %s",
sigNo, info->si_code, VG_(get_IP)(tid),
VG_UCONTEXT_INSTR_PTR(uc),
- ( from_outside ? "outside" : "inside" ));
+ ( from_user ? "user" : "kernel" ));
}
vg_assert(sigNo >= 1 && sigNo <= VG_(max_signal));
@@ -2005,10 +2123,10 @@
(Why do we care?) If the signal is from the user rather than the
kernel, then treat it more like an async signal than a sync signal --
that is, merely queue it for later delivery. */
- if (from_outside) {
- sync_signalhandler_from_outside(tid, sigNo, info, uc);
+ if (from_user) {
+ sync_signalhandler_from_user(tid, sigNo, info, uc);
} else {
- sync_signalhandler_from_inside( tid, sigNo, info, uc);
+ sync_signalhandler_from_kernel( tid, sigNo, info, uc);
}
}
Modified: branches/DRDDEV/coregrind/m_stacktrace.c
===================================================================
--- branches/DRDDEV/coregrind/m_stacktrace.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_stacktrace.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -48,7 +48,7 @@
/*--- Exported functions. ---*/
/*------------------------------------------------------------*/
-/* Take a snapshot of the client's stack, putting the up to 'n_ips'
+/* Take a snapshot of the client's stack, putting up to 'max_n_ips'
IPs into 'ips'. In order to be thread-safe, we pass in the
thread's IP SP, FP if that's meaningful, and LR if that's
meaningful. Returns number of IPs put in 'ips'.
@@ -58,7 +58,7 @@
traces on ppc64-linux and has no effect on other platforms.
*/
UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
- /*OUT*/Addr* ips, UInt n_ips,
+ /*OUT*/Addr* ips, UInt max_n_ips,
/*OUT*/Addr* sps, /*OUT*/Addr* fps,
Addr ip, Addr sp, Addr fp, Addr lr,
Addr fp_min, Addr fp_max_orig )
@@ -82,7 +82,7 @@
vg_assert(sizeof(Addr) == sizeof(UWord));
vg_assert(sizeof(Addr) == sizeof(void*));
- /* Snaffle IPs from the client's stack into ips[0 .. n_ips-1],
+ /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
stopping when the trail goes cold, which we guess to be
when FP is not a reasonable stack location. */
@@ -94,9 +94,9 @@
fp_max -= sizeof(Addr);
if (debug)
- VG_(printf)("n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
+ VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
"fp_max=0x%lx ip=0x%lx fp=0x%lx\n",
- n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
+ max_n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
/* Assertion broken before main() is reached in pthreaded programs; the
* offending stack traces only have one item. --njn, 2002-aug-16 */
@@ -143,7 +143,7 @@
*/
while (True) {
- if (i >= n_ips)
+ if (i >= max_n_ips)
break;
/* Try to derive a new (ip,sp,fp) triple from the current
@@ -156,10 +156,18 @@
fails, and is expensive. */
/* Deal with frames resulting from functions which begin "pushl%
ebp ; movl %esp, %ebp" which is the ABI-mandated preamble. */
- if (fp_min <= fp && fp <= fp_max
- - 1 * sizeof(UWord)/*see comment below*/) {
+ if (fp_min <= fp &&
+ fp <= fp_max - 1 * sizeof(UWord)/*see comment below*/)
+ {
/* fp looks sane, so use it. */
ip = (((UWord*)fp)[1]);
+ // We stop if we hit a zero (the traditional end-of-stack
+ // marker) or a one -- these correspond to recorded IPs of 0 or -1.
+ // The latter because r8818 (in this file) changes the meaning of
+ // entries [1] and above in a stack trace, by subtracting 1 from
+ // them. Hence stacks that used to end with a zero value now end in
+ // -1 and so we must detect that too.
+ if (0 == ip || 1 == ip) break;
sp = fp + sizeof(Addr) /*saved %ebp*/
+ sizeof(Addr) /*ra*/;
fp = (((UWord*)fp)[0]);
@@ -175,6 +183,7 @@
/* That didn't work out, so see if there is any CF info to hand
which can be used. */
if ( VG_(use_CF_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
+ if (0 == ip || 1 == ip) break;
if (sps) sps[i] = sp;
if (fps) fps[i] = fp;
ips[i++] = ip - 1; /* -1: refer to calling insn, not the RA */
@@ -186,6 +195,7 @@
/* And, similarly, try for MSVC FPO unwind info. */
if ( VG_(use_FPO_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
+ if (0 == ip || 1 == ip) break;
if (sps) sps[i] = sp;
if (fps) fps[i] = fp;
ips[i++] = ip;
@@ -227,15 +237,15 @@
*/
while (True) {
- if (i >= n_ips)
+ if (i >= max_n_ips)
break;
- /* Try to derive a new (ip,sp,fp) triple from the current
- set. */
+ /* Try to derive a new (ip,sp,fp) triple from the current set. */
/* First off, see if there is any CFI info to hand which can
be used. */
if ( VG_(use_CF_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
+ if (0 == ip || 1 == ip) break;
if (sps) sps[i] = sp;
if (fps) fps[i] = fp;
ips[i++] = ip - 1; /* -1: refer to calling insn, not the RA */
@@ -260,6 +270,7 @@
if (fp_min <= fp && fp <= fp_max - 1 * sizeof(UWord)) {
/* fp looks sane, so use it. */
ip = (((UWord*)fp)[1]);
+ if (0 == ip || 1 == ip) break;
sp = fp + sizeof(Addr) /*saved %rbp*/
+ sizeof(Addr) /*ra*/;
fp = (((UWord*)fp)[0]);
@@ -286,6 +297,7 @@
*/
if (fp_min <= sp && sp < fp_max) {
ip = ((UWord*)sp)[0];
+ if (0 == ip || 1 == ip) break;
if (sps) sps[i] = sp;
if (fps) fps[i] = fp;
ips[i++] = ip == 0
@@ -377,7 +389,7 @@
const Int lr_offset = 1;
# endif
- if (i >= n_ips)
+ if (i >= max_n_ips)
break;
/* Try to derive a new (ip,fp) pair from the current set. */
@@ -413,6 +425,7 @@
}
# endif
+ if (0 == ip || 1 == ip) break;
fp = (((UWord*)fp)[0]);
if (sps) sps[i] = fp; /* NB. not sp */
if (fps) fps[i] = fp;
@@ -439,7 +452,7 @@
}
UInt VG_(get_StackTrace) ( ThreadId tid,
- /*OUT*/StackTrace ips, UInt n_ips,
+ /*OUT*/StackTrace ips, UInt max_n_ips,
/*OUT*/StackTrace sps,
/*OUT*/StackTrace fps,
Word first_ip_delta )
@@ -491,7 +504,7 @@
"sp=0x%08lx fp=0x%08lx\n",
tid, stack_highest_word, ip, sp, fp);
- return VG_(get_StackTrace_wrk)(tid, ips, n_ips,
+ return VG_(get_StackTrace_wrk)(tid, ips, max_n_ips,
sps, fps,
ip, sp, fp, lr, sp,
stack_highest_word);
@@ -527,15 +540,15 @@
}
/* Get and immediately print a StackTrace. */
-void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt n_ips )
+void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt max_n_ips )
{
- Addr ips[n_ips];
- UInt n_ips_obtained
- = VG_(get_StackTrace)(tid, ips, n_ips,
+ Addr ips[max_n_ips];
+ UInt n_ips
+ = VG_(get_StackTrace)(tid, ips, max_n_ips,
NULL/*array to dump SP values in*/,
NULL/*array to dump FP values in*/,
0/*first_ip_delta*/);
- VG_(pp_StackTrace)(ips, n_ips_obtained);
+ VG_(pp_StackTrace)(ips, n_ips);
}
@@ -563,13 +576,7 @@
action(i, ip);
i++;
- // re 'while' condition: stop if we hit a zero value (the traditional
- // end-of-stack marker) or a ~0 value. The latter because r8818
- // (in this file) changes the meaning of entries [1] and above in a
- // stack trace, by subtracting 1 from them. Hence stacks that used
- // to end with a zero value now end in -1 and so we must detect
- // that too.
- } while (i < n_ips && ips[i] != 0 && ips[i] != ~(Addr)0 && !main_done);
+ } while (i < n_ips && !main_done);
#undef MYBUF_LEN
}
Modified: branches/DRDDEV/coregrind/m_ume/priv_ume.h
===================================================================
--- branches/DRDDEV/coregrind/m_ume/priv_ume.h 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/m_ume/priv_ume.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -30,17 +30,6 @@
#ifndef __PRIV_UME_H
#define __PRIV_UME_H
-#if defined(VGO_linux)
-# define HAVE_ELF
-# define HAVE_SCRIPT
-
-#elif defined(VGO_aix5)
-// The AIX port doesn't use UME.
-
-#else
-#error unknown architecture
-#endif
-
extern int VG_(do_exec_inner)(const HChar *exe, ExeInfo *info);
#if defined(HAVE_ELF)
Copied: branches/DRDDEV/coregrind/pub_core_aspacehl.h (from rev 9796, trunk/coregrind/pub_core_aspacehl.h)
===================================================================
--- branches/DRDDEV/coregrind/pub_core_aspacehl.h (rev 0)
+++ branches/DRDDEV/coregrind/pub_core_aspacehl.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -0,0 +1,46 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Services layered on top of m_aspacemgr. pub_core_aspacehl.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2009-2009 Julian Seward
+ js...@ac...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_ASPACEHL_H
+#define __PUB_CORE_ASPACEHL_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This module contains services that would be in m_aspacemgr,
+// except that they use dynamic memory management or something similar
+// that we don't allow in m_aspacemgr. The "hl" is short for "high level".
+//--------------------------------------------------------------------
+
+#include "pub_tool_aspacehl.h"
+
+#endif // __PUB_CORE_ASPACEHL_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Modified: branches/DRDDEV/coregrind/pub_core_ume.h
===================================================================
--- branches/DRDDEV/coregrind/pub_core_ume.h 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/coregrind/pub_core_ume.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -36,6 +36,17 @@
// and exec'ing.
//--------------------------------------------------------------------
+#if defined(VGO_linux)
+# define HAVE_ELF
+# define HAVE_SCRIPT
+
+#elif defined(VGO_aix5)
+// The AIX port doesn't use UME.
+
+#else
+#error unknown architecture
+#endif
+
/*------------------------------------------------------------*/
/*--- Loading files ---*/
/*------------------------------------------------------------*/
Modified: branches/DRDDEV/drd/drd_strmem_intercepts.c
===================================================================
--- branches/DRDDEV/drd/drd_strmem_intercepts.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/drd/drd_strmem_intercepts.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -65,8 +65,10 @@
}
STRLEN(VG_Z_LIBC_SONAME, strlen)
+#if defined(VGO_linux)
STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
+#endif
/*--------------------------------------------------------------------*/
/*--- end ---*/
Modified: branches/DRDDEV/drd/tests/rwlock_test.c
===================================================================
--- branches/DRDDEV/drd/tests/rwlock_test.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/drd/tests/rwlock_test.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -36,6 +36,7 @@
pthread_t tid[thread_count];
int i;
+ pthread_rwlock_init(&s_rwlock, NULL);
for (i = 0; i < thread_count; i++)
{
pthread_create(&tid[i], 0, thread_func, 0);
Modified: branches/DRDDEV/exp-ptrcheck/h_intercepts.c
===================================================================
--- branches/DRDDEV/exp-ptrcheck/h_intercepts.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/exp-ptrcheck/h_intercepts.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -71,9 +71,11 @@
}
STRLEN(VG_Z_LIBC_SONAME, strlen)
+#if defined(VGO_linux)
STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
STRLEN(VG_Z_LD_SO_1, strlen)
+#endif
#define STRCMP(soname, fnname) \
@@ -97,8 +99,10 @@
}
STRCMP(VG_Z_LIBC_SONAME, strcmp)
+#if defined(VGO_linux)
STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
STRCMP(VG_Z_LD64_SO_1, strcmp)
+#endif
#define MEMCPY(soname, fnname) \
@@ -144,8 +148,10 @@
}
MEMCPY(VG_Z_LIBC_SONAME, memcpy)
+#if defined(VGO_linux)
MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
+#endif
/* Copy SRC to DEST, returning the address of the terminating '\0' in
@@ -161,8 +167,10 @@
}
STPCPY(VG_Z_LIBC_SONAME, stpcpy)
+#if defined(VGO_linux)
STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy)
STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy)
+#endif
/*--------------------------------------------------------------------*/
Modified: branches/DRDDEV/helgrind/hg_intercepts.c
===================================================================
--- branches/DRDDEV/helgrind/hg_intercepts.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/helgrind/hg_intercepts.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -1608,11 +1608,13 @@
// Apparently index() is the same thing as strchr()
STRCHR(VG_Z_LIBC_SONAME, strchr)
+STRCHR(VG_Z_LIBC_SONAME, index)
+#if defined(VGO_linux)
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)
-STRCHR(VG_Z_LIBC_SONAME, index)
-STRCHR(VG_Z_LD_LINUX_SO_2, index)
STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
+#endif
// Note that this replacement often doesn't get used because gcc inlines
@@ -1629,8 +1631,10 @@
}
STRLEN(VG_Z_LIBC_SONAME, strlen)
+#if defined(VGO_linux)
STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
+#endif
#define STRCPY(soname, fnname) \
@@ -1669,8 +1673,10 @@
}
STRCMP(VG_Z_LIBC_SONAME, strcmp)
+#if defined(VGO_linux)
STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
STRCMP(VG_Z_LD64_SO_1, strcmp)
+#endif
#define MEMCPY(soname, fnname) \
@@ -1716,8 +1722,10 @@
}
MEMCPY(VG_Z_LIBC_SONAME, memcpy)
+#if defined(VGO_linux)
MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
+#endif
/* icc9 blats these around all over the place. Not only in the main
executable but various .so's. They are highly tuned and read
memory beyond the source boundary (although work correctly and
Modified: branches/DRDDEV/helgrind/libhb_core.c
===================================================================
--- branches/DRDDEV/helgrind/libhb_core.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/helgrind/libhb_core.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -2729,7 +2729,8 @@
struct _RCEC* next;
UWord rc;
UWord rcX; /* used for crosschecking */
- UWord frames[1 + N_FRAMES]; /* first word is hash of all the rest */
+ UWord frames_hash; /* hash of all the frames */
+ UWord frames[N_FRAMES];
}
RCEC;
@@ -2741,11 +2742,11 @@
Word i;
tl_assert(ec1 && ec1->magic == RCEC_MAGIC);
tl_assert(ec2 && ec2->magic == RCEC_MAGIC);
- if (ec1->frames[0] < ec2->frames[0]) return -1;
- if (ec1->frames[0] > ec2->frames[0]) return 1;
- for (i = 1; i < 1 + N_FRAMES; i++) {
+ if (ec1->frames_hash < ec2->frames_hash) return -1;
+ if (ec1->frames_hash > ec2->frames_hash) return 1;
+ for (i = 0; i < N_FRAMES; i++) {
if (ec1->frames[i] < ec2->frames[i]) return -1;
- if (ec1->frames[i] > ec2->frames[i]) return 1;
+ if (ec1->frames[i] > ec2->frames[i]) return 1;
}
return 0;
}
@@ -2841,7 +2842,7 @@
/* Search the hash table to see if we already have it. */
stats__ctxt_tab_qs++;
- hent = example->frames[0] % N_RCEC_TAB;
+ hent = example->frames_hash % N_RCEC_TAB;
copy = contextTab[hent];
while (1) {
if (!copy) break;
@@ -2886,13 +2887,13 @@
example.magic = RCEC_MAGIC;
example.rc = 0;
example.rcX = 0;
- main_get_stacktrace( thr, &example.frames[1], N_FRAMES );
+ main_get_stacktrace( thr, &example.frames[0], N_FRAMES );
hash = 0;
- for (i = 1; i < 1 + N_FRAMES; i++) {
+ for (i = 0; i < N_FRAMES; i++) {
hash ^= example.frames[i];
hash = ROLW(hash, 19);
}
- example.frames[0] = hash;
+ example.frames_hash = hash;
return ctxt__find_or_add( &example );
}
@@ -3183,15 +3184,18 @@
tl_assert(i >= 0 && i <= N_OLDREF_ACCS);
if (i < N_OLDREF_ACCS) {
+ Int n, maxNFrames;
/* return with success */
tl_assert(cand_thr);
tl_assert(cand_rcec);
tl_assert(cand_rcec->magic == RCEC_MAGIC);
tl_assert(cand_szB >= 1);
- *resEC = VG_(make_ExeContext_from_StackTrace)(
- &cand_rcec->frames[1],
- min_UInt(N_FRAMES, VG_(clo_backtrace_size))
- );
+ /* Count how many non-zero frames we have. */
+ maxNFrames = min_UInt(N_FRAMES, VG_(clo_backtrace_size));
+ for (n = 0; n < maxNFrames; n++) {
+ if (0 == cand_rcec->frames[n]) break;
+ }
+ *resEC = VG_(make_ExeContext_from_StackTrace)(cand_rcec->frames, n);
*resThr = cand_thr;
*resSzB = cand_szB;
*resIsW = cand_isW;
Modified: branches/DRDDEV/include/Makefile.am
===================================================================
--- branches/DRDDEV/include/Makefile.am 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/include/Makefile.am 2009-05-09 09:55:46 UTC (rev 9802)
@@ -6,6 +6,7 @@
incinc_HEADERS = \
pub_tool_basics.h \
pub_tool_basics_asm.h \
+ pub_tool_aspacehl.h \
pub_tool_aspacemgr.h \
pub_tool_clientstate.h \
pub_tool_clreq.h \
Copied: branches/DRDDEV/include/pub_tool_aspacehl.h (from rev 9796, trunk/include/pub_tool_aspacehl.h)
===================================================================
--- branches/DRDDEV/include/pub_tool_aspacehl.h (rev 0)
+++ branches/DRDDEV/include/pub_tool_aspacehl.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -0,0 +1,44 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Services layered on top of m_aspacemgr. pub_tool_aspacehl.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2009-2009 Julian Seward
+ js...@ac...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_ASPACEHL_H
+#define __PUB_TOOL_ASPACEHL_H
+
+// Extract from aspacem a vector of the current segment start
+// addresses. The vector is dynamically allocated and should be freed
+// by the caller when done. REQUIRES m_mallocfree to be running.
+// Writes the number of addresses required into *n_acquired.
+extern Addr* VG_(get_segment_starts) ( /*OUT*/Int* n_acquired );
+
+#endif // __PUB_TOOL_ASPACEHL_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Modified: branches/DRDDEV/include/pub_tool_hashtable.h
===================================================================
--- branches/DRDDEV/include/pub_tool_hashtable.h 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/include/pub_tool_hashtable.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -67,10 +67,9 @@
/* Removes a VgHashNode from the table. Returns NULL if not found. */
extern void* VG_(HT_remove) ( VgHashTable table, UWord key );
-/* Allocates a suitably-sized array, copies all the hashtable elements
- into it, then returns both the array and the size of it. This is
- used by the memory-leak detector. The array must be freed with
- VG_(free). */
+/* Allocates a suitably-sized array, copies pointers to all the hashtable
+ elements into it, then returns both the array and the size of it. The
+ array must be freed with VG_(free). */
extern VgHashNode** VG_(HT_to_array) ( VgHashTable t, /*OUT*/ UInt* n_elems );
/* Reset the table's iterator to point to the first element. */
Modified: branches/DRDDEV/include/pub_tool_oset.h
===================================================================
--- branches/DRDDEV/include/pub_tool_oset.h 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/include/pub_tool_oset.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -72,9 +72,9 @@
typedef struct _OSet OSet;
-// - Cmp: returns -1, 0 or 1 if key is <, == or > elem.
+// - Cmp: returns -1, 0 or 1 if key is <, == or > elem.
// - Alloc: allocates a chunk of memory.
-// - Free: frees a chunk of memory allocated with Alloc.
+// - Free: frees a chunk of memory allocated with Alloc.
typedef Word (*OSetCmp_t) ( const void* key, const void* elem );
typedef void* (*OSetAlloc_t) ( HChar* ec, SizeT szB );
@@ -219,6 +219,11 @@
// * ResetIter: Each OSet has an iterator. This resets it to point to the
// first element in the OSet.
//
+// * ResetIterAt: Like ResetIter, but instead of resetting the iterator to the
+// smallest element, it resets the iterator to point to the smallest element
+// in the set whose key is greater-than-or-equal to the given key. (In many
+// cases this will be the element whose key equals that of the given key.)
+//
// * Next: Returns a pointer to the element pointed to by the OSet's
// iterator, and advances the iterator by one; the elements are visited
// in order. Or, returns NULL if the iterator has reached the OSet's end.
@@ -238,19 +243,15 @@
extern Word VG_(OSetGen_Size) ( const OSet* os );
extern void VG_(OSetGen_Insert) ( OSet* os, void* elem );
-extern Bool VG_(OSetGen_Contains) ( const OSet* os, const void* key );
-extern void* VG_(OSetGen_Lookup) ( const OSet* os, const void* key );
+extern Bool VG_(OSetGen_Contains) ( const OSet* os, const void* key );
+extern void* VG_(OSetGen_Lookup) ( const OSet* os, const void* key );
extern void* VG_(OSetGen_LookupWithCmp)( OSet* os,
const void* key, OSetCmp_t cmp );
-extern void* VG_(OSetGen_Remove) ( OSet* os, const void* key );
+extern void* VG_(OSetGen_Remove) ( OSet* os, const void* key );
extern void VG_(OSetGen_ResetIter) ( OSet* os );
+extern void VG_(OSetGen_ResetIterAt) ( OSet* os, const void* key );
extern void* VG_(OSetGen_Next) ( OSet* os );
-// set up 'oset' for iteration so that the first key subsequently
-// produced VG_(OSetGen_Next) is the smallest key in the map
-// >= start_at. Naturally ">=" is defined by the comparison
-// function supplied to VG_(OSetGen_Create).
-extern void VG_(OSetGen_ResetIterAt) ( OSet* oset, const void* key );
#endif // __PUB_TOOL_OSET_H
Modified: branches/DRDDEV/include/pub_tool_redir.h
===================================================================
--- branches/DRDDEV/include/pub_tool_redir.h 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/include/pub_tool_redir.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -160,6 +160,15 @@
/* --------- Some handy Z-encoded names. --------- */
+// Nb: ALL THESE NAMES MUST BEGIN WITH "VG_Z_". Why? If we applied
+// conditional compilation inconsistently we could accidentally use an
+// undefined constant like VG_Z_LIBC_DOT_A, resulting in a bogus Z-encoded
+// name like "_vgrZU_VG_Z_LIBC_DOT_A_foo". This can't be detected at
+// compile-time, because both the constant's name and its value are
+// identifiers. However, by always using "VG_Z_" as a prefix, we can do a
+// run-time check and abort if any name has "VG_Z_" in it, because that
+// indicates that the constant has been used without being defined.
+
/* --- Soname of the standard C library. --- */
#if defined(VGO_linux)
@@ -175,8 +184,7 @@
/* --- Soname of the GNU C++ library. --- */
-// DDD: this one and those below should probably be conditionally compiled,
-// as should all the redirects in the tools that use them.
+// Valid on all platforms(?)
#define VG_Z_LIBSTDCXX_SONAME libstdcZpZpZa // libstdc++*
/* --- Soname of XLC's C++ library. --- */
@@ -192,12 +200,13 @@
/* --- Sonames for Linux ELF linkers. --- */
+#if defined(VGO_linux)
#define VG_Z_LD_LINUX_SO_2 ldZhlinuxZdsoZd2 // ld-linux.so.2
#define VG_Z_LD_LINUX_X86_64_SO_2 ldZhlinuxZhx86Zh64ZdsoZd2 // ld-linux-x86-64.so.2
#define VG_Z_LD64_SO_1 ld64ZdsoZd1 // ld64.so.1
#define VG_Z_LD_SO_1 ldZdsoZd1 // ld.so.1
+#endif
-
#endif // __PUB_TOOL_REDIR_H
/*--------------------------------------------------------------------*/
Modified: branches/DRDDEV/massif/perf/Makefile.am
===================================================================
--- branches/DRDDEV/massif/perf/Makefile.am 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/massif/perf/Makefile.am 2009-05-09 09:55:46 UTC (rev 9802)
@@ -1,6 +1,5 @@
-# For AM_FLAG_M3264_PRI
-include $(top_srcdir)/Makefile.flags.am
+include $(top_srcdir)/Makefile.tool-tests.am
EXTRA_DIST = \
many-xpts.vgperf
@@ -8,6 +7,6 @@
check_PROGRAMS = \
many-xpts
-AM_CFLAGS = -Winline -Wall -Wshadow -g -O $(AM_FLAG_M3264_PRI)
-AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_builddir)/include
-AM_CXXFLAGS = $(AM_CFLAGS)
+AM_CFLAGS += -O $(AM_FLAG_M3264_PRI)
+AM_CXXFLAGS += -O $(AM_FLAG_M3264_PRI)
+
Modified: branches/DRDDEV/memcheck/Makefile.am
===================================================================
--- branches/DRDDEV/memcheck/Makefile.am 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/memcheck/Makefile.am 2009-05-09 09:55:46 UTC (rev 9802)
@@ -1,5 +1,7 @@
include $(top_srcdir)/Makefile.tool.am
+SUBDIRS += perf
+
noinst_PROGRAMS =
if VGCONF_PLATFORMS_INCLUDE_X86_LINUX
noinst_PROGRAMS += memcheck-x86-linux vgpreload_memcheck-x86-linux.so
Modified: branches/DRDDEV/memcheck/mc_errors.c
===================================================================
--- branches/DRDDEV/memcheck/mc_errors.c 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/memcheck/mc_errors.c 2009-05-09 09:55:46 UTC (rev 9802)
@@ -569,7 +569,7 @@
if (VG_(clo_xml)) {
VG_(message_no_f_c)(Vg_UserMsg, " <kind>%t</kind>",
- xml_leak_kind(lr->state));
+ xml_leak_kind(lr->key.state));
} else {
VG_(message)(Vg_UserMsg, "");
}
@@ -581,7 +581,7 @@
xpre,
lr->szB + lr->indirect_szB, lr->szB, lr->indirect_szB,
lr->num_blocks,
- str_leak_lossmode(lr->state), n_this_record, n_total_records,
+ str_leak_lossmode(lr->key.state), n_this_record, n_total_records,
xpost
);
if (VG_(clo_xml)) {
@@ -597,7 +597,7 @@
"%s%'lu bytes in %'u blocks are %s in loss record %'u of %'u%s",
xpre,
lr->szB, lr->num_blocks,
- str_leak_lossmode(lr->state), n_this_record, n_total_records,
+ str_leak_lossmode(lr->key.state), n_this_record, n_total_records,
xpost
);
if (VG_(clo_xml)) {
@@ -607,7 +607,7 @@
lr->num_blocks);
}
}
- VG_(pp_ExeContext)(lr->allocated_at);
+ VG_(pp_ExeContext)(lr->key.allocated_at);
break;
}
@@ -811,7 +811,7 @@
extra.Err.Leak.lr = lr;
return
VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
- lr->allocated_at, print_record,
+ lr->key.allocated_at, print_record,
/*allow_GDB_attach*/False, /*count_error*/False );
}
Modified: branches/DRDDEV/memcheck/mc_include.h
===================================================================
--- branches/DRDDEV/memcheck/mc_include.h 2009-05-08 11:53:38 UTC (rev 9801)
+++ branches/DRDDEV/memcheck/mc_include.h 2009-05-09 09:55:46 UTC (rev 9802)
@@ -230,13 +230,15 @@
typedef
enum {
- Unreached =0, // Not reached, ie. leaked.
- // (At best, only reachable from itself via a cycle.
- IndirectLeak =1, // Leaked, but reachable from another leaked block
+ // Nb: the order is important -- it dictates the order of loss records
+ // of equal sizes.
+ Reachable =0, // Definitely reachable from root-set.
+ Possible =1, // Possibly reachable from root-set; involves at
+ // least one interior-pointer along the way.
+ IndirectLeak =2, // Leaked, but reachable from another leaked block
// (be it Unreached or IndirectLeak).
- Possible =2, // Possibly reachable from root-set; involves at
- // least one interior-pointer along the way.
- Reachable =3 // Definitely reachable from root-set.
+ Unreached =3, // Not...
[truncated message content] |