You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(32) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
1
(29) |
2
(23) |
3
(17) |
|
4
(19) |
5
(7) |
6
(11) |
7
(8) |
8
(6) |
9
(12) |
10
(23) |
|
11
(16) |
12
(21) |
13
(27) |
14
(35) |
15
(17) |
16
(6) |
17
(11) |
|
18
(13) |
19
(7) |
20
(12) |
21
(11) |
22
(9) |
23
|
24
(8) |
|
25
(15) |
26
(9) |
27
(14) |
28
(17) |
29
(41) |
30
(17) |
31
(15) |
|
From: Tom H. <th...@cy...> - 2008-05-06 03:04:53
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2008-05-06 03:05:06 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 423 tests, 4 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-05-06 02:55:46
|
Nightly build on aston ( x86_64, Fedora Core 5 ) started at 2008-05-06 03:20:06 BST Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 429 tests, 7 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 429 tests, 6 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc08_hbl2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Tue May 6 03:38:18 2008 --- new.short Tue May 6 03:55:50 2008 *************** *** 8,10 **** ! == 429 tests, 6 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/malloc_free_fill (stderr) --- 8,10 ---- ! == 429 tests, 7 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/malloc_free_fill (stderr) *************** *** 14,17 **** none/tests/mremap2 (stdout) - helgrind/tests/tc08_hbl2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) --- 14,17 ---- none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) + helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-05-06 02:41:24
|
Nightly build on trojan ( x86_64, Fedora Core 6 ) started at 2008-05-06 03:25:03 BST Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 427 tests, 7 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/bug133694 (stdout) memcheck/tests/x86/bug133694 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap2 (stdout) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 427 tests, 6 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/bug133694 (stdout) memcheck/tests/x86/bug133694 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Tue May 6 03:33:21 2008 --- new.short Tue May 6 03:41:30 2008 *************** *** 8,10 **** ! == 427 tests, 6 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 427 tests, 7 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) *************** *** 17,18 **** --- 17,19 ---- none/tests/mremap2 (stdout) + helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc20_verifywrap (stderr) |
|
From: Tom H. <th...@cy...> - 2008-05-06 02:38:05
|
Nightly build on dellow ( x86_64, Fedora 8 ) started at 2008-05-06 03:10:05 BST Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 423 tests, 7 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 423 tests, 8 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) none/tests/pth_cvsimple (stdout) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Tue May 6 03:24:34 2008 --- new.short Tue May 6 03:38:07 2008 *************** *** 8,10 **** ! == 423 tests, 8 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 423 tests, 7 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) *************** *** 14,17 **** none/tests/mremap2 (stdout) - none/tests/pth_cvsimple (stdout) - helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc18_semabuse (stderr) --- 14,15 ---- |
|
From: Tom H. <th...@cy...> - 2008-05-06 02:22:32
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2008-05-06 03:00:02 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 429 tests, 30 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_switch (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) none/tests/amd64/insn_ssse3 (stdout) none/tests/amd64/insn_ssse3 (stderr) none/tests/amd64/ssse3_misaligned (stderr) none/tests/blockfault (stderr) none/tests/fdleak_fcntl (stderr) none/tests/mremap2 (stdout) none/tests/x86/insn_ssse3 (stdout) none/tests/x86/insn_ssse3 (stderr) none/tests/x86/ssse3_misaligned (stderr) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) |
|
From: <sv...@va...> - 2008-05-05 09:48:54
|
Author: sewardj
Date: 2008-05-05 10:48:56 +0100 (Mon, 05 May 2008)
New Revision: 8007
Log:
Add comments giving an overview of the origin tracking implementation.
Also, rename "ocache" to "ocacheL1" to be more consistent with the
comments and the rest of the otag cache code.
Modified:
trunk/memcheck/mc_main.c
Modified: trunk/memcheck/mc_main.c
===================================================================
--- trunk/memcheck/mc_main.c 2008-05-04 23:06:28 UTC (rev 8006)
+++ trunk/memcheck/mc_main.c 2008-05-05 09:48:56 UTC (rev 8007)
@@ -77,6 +77,15 @@
/*------------------------------------------------------------*/
+/*--- Comments on the origin tracking implementation ---*/
+/*------------------------------------------------------------*/
+
+/* See detailed comment entitled
+ AN OVERVIEW OF THE ORIGIN TRACKING IMPLEMENTATION
+ which is contained further on in this file. */
+
+
+/*------------------------------------------------------------*/
/*--- V bits and A bits ---*/
/*------------------------------------------------------------*/
@@ -1712,8 +1721,8 @@
/*--- Origin tracking stuff - cache basics ---*/
/*------------------------------------------------------------*/
-/* Some background comments on the origin tracking implementation
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+/* AN OVERVIEW OF THE ORIGIN TRACKING IMPLEMENTATION
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note that this implementation draws inspiration from the "origin
tracking by value piggybacking" scheme described in "Tracking Bad
@@ -1722,28 +1731,224 @@
Kathryn McKinley, OOPSLA07, Montreal, Oct 2007) but in fact it is
implemented completely differently.
- This implementation tracks the defining point of all values using
- so called "origin tags", which are 32-bit integers, rather than
- using the values themselves to encode the origins. The latter,
- so-called value piggybacking", is what the OOPSLA07 paper
+ Origin tags and ECUs -- about the shadow values
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This implementation tracks the defining point of all uninitialised
+ values using so called "origin tags", which are 32-bit integers,
+ rather than using the values themselves to encode the origins. The
+ latter, so-called value piggybacking", is what the OOPSLA07 paper
describes.
Origin tags, as tracked by the machinery below, are 32-bit unsigned
- ints (UInts), regardless of the machine's word size.
+ ints (UInts), regardless of the machine's word size. Each tag
+ comprises an upper 30-bit ECU field and a lower 2-bit
+ 'kind' field. The ECU field is a number given out by m_execontext
+ and has a 1-1 mapping with ExeContext*s. An ECU can be used
+ directly as an origin tag (otag), but in fact we want to put
+ additional information 'kind' field to indicate roughly where the
+ tag came from. This helps print more understandable error messages
+ for the user -- it has no other purpose. In summary:
+ * Both ECUs and origin tags are represented as 32-bit words
+
+ * m_execontext and the core-tool interface deal purely in ECUs.
+ They have no knowledge of origin tags - that is a purely
+ Memcheck-internal matter.
+
+ * all valid ECUs have the lowest 2 bits zero and at least
+ one of the upper 30 bits nonzero (see VG_(is_plausible_ECU))
+
+ * to convert from an ECU to an otag, OR in one of the MC_OKIND_
+ constants defined in mc_include.h.
+
+ * to convert an otag back to an ECU, AND it with ~3
+
+ One important fact is that no valid otag is zero. A zero otag is
+ used by the implementation to indicate "no origin", which could
+ mean that either the value is defined, or it is undefined but the
+ implementation somehow managed to lose the origin.
+
+ The ECU used for memory created by malloc etc is derived from the
+ stack trace at the time the malloc etc happens. This means the
+ mechanism can show the exact allocation point for heap-created
+ uninitialised values.
+
+ In contrast, it is simply too expensive to create a complete
+ backtrace for each stack allocation. Therefore we merely use a
+ depth-1 backtrace for stack allocations, which can be done once at
+ translation time, rather than N times at run time. The result of
+ this is that, for stack created uninitialised values, Memcheck can
+ only show the allocating function, and not what called it.
+ Furthermore, compilers tend to move the stack pointer just once at
+ the start of the function, to allocate all locals, and so in fact
+ the stack origin almost always simply points to the opening brace
+ of the function. Net result is, for stack origins, the mechanism
+ can tell you in which function the undefined value was created, but
+ that's all. Users will need to carefully check all locals in the
+ specified function.
+
+ Shadowing registers and memory
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Memory is shadowed using a two level cache structure (ocacheL1 and
+ ocacheL2). Memory references are first directed to ocacheL1. This
+ is a traditional 2-way set associative cache with 32-byte lines and
+ approximate LRU replacement within each set.
+
+ A naive implementation would require storing one 32 bit otag for
+ each byte of memory covered, a 4:1 space overhead. Instead, there
+ is one otag for every 4 bytes of memory covered, plus a 4-bit mask
+ that shows which of the 4 bytes have that shadow value and which
+ have a shadow value of zero (indicating no origin). Hence a lot of
+ space is saved, but the cost is that only one different origin per
+ 4 bytes of address space can be represented. This is a source of
+ imprecision, but how much of a problem it really is remains to be
+ seen.
+
+ A cache line that contains all zeroes ("no origins") contains no
+ useful information, and can be ejected from the L1 cache "for
+ free", in the sense that a read miss on the L1 causes a line of
+ zeroes to be installed. However, ejecting a line containing
+ nonzeroes risks losing origin information permanently. In order to
+ prevent such lossage, ejected nonzero lines are placed in a
+ secondary cache (ocacheL2), which is an OSet (AVL tree) of cache
+ lines. This can grow arbitrarily large, and so should ensure that
+ Memcheck runs out of memory in preference to losing useful origin
+ info due to cache size limitations.
+
+ Shadowing registers is a bit tricky, because the shadow values are
+ 32 bits, regardless of the size of the register. That gives a
+ problem for registers smaller than 32 bits. The solution is to
+ find spaces in the guest state that are unused, and use those to
+ shadow guest state fragments smaller than 32 bits. For example, on
+ ppc32/64, each vector register is 16 bytes long. If 4 bytes of the
+ shadow are allocated for the register's otag, then there are still
+ 12 bytes left over which could be used to shadow 3 other values.
+
+ This implies there is some non-obvious mapping from guest state
+ (start,length) pairs to the relevant shadow offset (for the origin
+ tags). And it is unfortunately guest-architecture specific. The
+ mapping is contained in mc_machine.c, which is quite lengthy but
+ straightforward.
+
+ Instrumenting the IR
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Instrumentation is largely straightforward, and done by the
+ functions schemeE and schemeS in mc_translate.c. These generate
+ code for handling the origin tags of expressions (E) and statements
+ (S) respectively. The rather strange names are a reference to the
+ "compilation schemes" shown in Simon Peyton Jones' book "The
+ Implementation of Functional Programming Languages" (Prentice Hall,
+ 1987, see
+ http://research.microsoft.com/~simonpj/papers/slpj-book-1987/index.htm).
+
+ schemeS merely arranges to move shadow values around the guest
+ state to track the incoming IR. schemeE is largely trivial too.
+ The only significant point is how to compute the otag corresponding
+ to binary (or ternary, quaternary, etc) operator applications. The
+ rule is simple: just take whichever value is larger (32-bit
+ unsigned max). Constants get the special value zero. Hence this
+ rule always propagates a nonzero (known) otag in preference to a
+ zero (unknown, or more likely, value-is-defined) tag, as we want.
+ If two different undefined values are inputs to a binary operator
+ application, then which is propagated is arbitrary, but that
+ doesn't matter, since the program is erroneous in using either of
+ the values, and so there's no point in attempting to propagate
+ both.
+
+ Since constants are abstracted to (otag) zero, much of the
+ instrumentation code can be folded out without difficulty by the
+ generic post-instrumentation IR cleanup pass, using these rules:
+ Max32U(0,x) -> x, Max32U(x,0) -> x, Max32(x,y) where x and y are
+ constants is evaluated at JIT time. And the resulting dead code
+ removal. In practice this causes surprisingly few Max32Us to
+ survive through to backend code generation.
+
+ Integration with the V-bits machinery
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This is again largely straightforward. Mostly the otag and V bits
+ stuff are independent. The only point of interaction is when the V
+ bits instrumenter creates a call to a helper function to report an
+ uninitialised value error -- in that case it must first use schemeE
+ to get hold of the origin tag expression for the value, and pass
+ that to the helper too.
+
+ There is the usual stuff to do with setting address range
+ permissions. When memory is painted undefined, we must also know
+ the origin tag to paint with, which involves some tedious plumbing,
+ particularly to do with the fast case stack handlers. When memory
+ is painted defined or noaccess then the origin tags must be forced
+ to zero.
+
+ One of the goals of the implementation was to ensure that the
+ non-origin tracking mode isn't slowed down at all. To do this,
+ various functions to do with memory permissions setting (again,
+ mostly pertaining to the stack) are duplicated for the with- and
+ without-otag case.
+
+ Dealing with stack redzones, and the NIA cache
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This is one of the few non-obvious parts of the implementation.
+
+ Some ABIs (amd64-ELF, ppc64-ELF, ppc32/64-XCOFF) define a small
+ reserved area below the stack pointer, that can be used as scratch
+ space by compiler generated code for functions. In the Memcheck
+ sources this is referred to as the "stack redzone". The important
+ thing here is that such redzones are considered volatile across
+ function calls and returns. So Memcheck takes care to mark them as
+ undefined for each call and return, on the afflicted platforms.
+ Past experience shows this is essential in order to get reliable
+ messages about uninitialised values that come from the stack.
+
+ So the question is, when we paint a redzone undefined, what origin
+ tag should we use for it? Consider a function f() calling g(). If
+ we paint the redzone using an otag derived from the ExeContext of
+ the CALL/BL instruction in f, then any errors in g causing it to
+ use uninitialised values that happen to lie in the redzone, will be
+ reported as having their origin in f. Which is highly confusing.
+
+ The same applies for returns: if, on a return, we paint the redzone
+ using a origin tag derived from the ExeContext of the RET/BLR
+ instruction in g, then any later errors in f causing it to use
+ uninitialised values in the redzone, will be reported as having
+ their origin in g. Which is just as confusing.
+
+ To do it right, in both cases we need to use an origin tag which
+ pertains to the instruction which dynamically follows the CALL/BL
+ or RET/BLR. In short, one derived from the NIA - the "next
+ instruction address".
+
+ To make this work, Memcheck's redzone-painting helper,
+ MC_(helperc_MAKE_STACK_UNINIT), now takes a third argument, the
+ NIA. It converts the NIA to a 1-element ExeContext, and uses that
+ ExeContext's ECU as the basis for the otag used to paint the
+ redzone. The expensive part of this is converting an NIA into an
+ ECU, since this happens once for every call and every return. So
+ we use a simple 511-line, 2-way set associative cache
+ (nia_to_ecu_cache) to cache the mappings, and that knocks most of
+ the cost out.
+
+ Further background comments
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
> Question: why is otag a UInt? Wouldn't a UWord be better? Isn't
> it really just the address of the relevant ExeContext?
Well, it's not the address, but a value which has a 1-1 mapping
with ExeContexts, and is guaranteed not to be zero, since zero
denotes (to memcheck) "unknown origin or defined value". So these
- UInts are just numbers starting at 1; each ExeContext is given a
- number when it is created.
+ UInts are just numbers starting at 4 and incrementing by 4; each
+ ExeContext is given a number when it is created. (*** NOTE this
+ confuses otags and ECUs; see comments above ***).
Making these otags 32-bit regardless of the machine's word size
makes the 64-bit implementation easier (next para). And it doesn't
really limit us in any way, since for the tags to overflow would
- require that the program somehow caused 2^32-1 different
+ require that the program somehow caused 2^30-1 different
ExeContexts to be created, in which case it is probably in deep
trouble. Not to mention V will have soaked up many tens of
gigabytes of memory merely to store them all.
@@ -1788,7 +1993,9 @@
information. Interestingly, a line containing all zeroes can be
evicted "free" from the cache, since it contains no useful
information, so there is scope perhaps for some cleverer cache
- management schemes.
+ management schemes. (*** NOTE, with the introduction of the
+ second level origin tag cache, ocacheL2, this is no longer a
+ problem. ***)
* The origin cache only stores one otag per 32-bits of address
space, plus 4 bits indicating which of the 4 bytes has that tag
@@ -1896,24 +2103,24 @@
}
OCache;
-static OCache* ocache = NULL;
-static UWord ocache_event_ctr = 0;
+static OCache* ocacheL1 = NULL;
+static UWord ocacheL1_event_ctr = 0;
static void init_ocacheL2 ( void ); /* fwds */
static void init_OCache ( void )
{
UWord line, set;
tl_assert(MC_(clo_mc_level) >= 3);
- tl_assert(ocache == NULL);
- ocache = VG_(am_shadow_alloc)(sizeof(OCache));
- if (ocache == NULL) {
- VG_(out_of_memory_NORETURN)( "memcheck:allocate the OCache",
+ tl_assert(ocacheL1 == NULL);
+ ocacheL1 = VG_(am_shadow_alloc)(sizeof(OCache));
+ if (ocacheL1 == NULL) {
+ VG_(out_of_memory_NORETURN)( "memcheck:allocating ocacheL1",
sizeof(OCache) );
}
- tl_assert(ocache != NULL);
+ tl_assert(ocacheL1 != NULL);
for (set = 0; set < OC_N_SETS; set++) {
for (line = 0; line < OC_LINES_PER_SET; line++) {
- ocache->set[set].line[line].tag = 1/*invalid*/;
+ ocacheL1->set[set].line[line].tag = 1/*invalid*/;
}
}
init_ocacheL2();
@@ -2023,18 +2230,18 @@
/* we already tried line == 0; skip therefore. */
for (line = 1; line < OC_LINES_PER_SET; line++) {
- if (ocache->set[setno].line[line].tag == tag) {
+ if (ocacheL1->set[setno].line[line].tag == tag) {
if (line == 1) {
stats_ocacheL1_found_at_1++;
} else {
stats_ocacheL1_found_at_N++;
}
- if (UNLIKELY(0 == (ocache_event_ctr++
+ if (UNLIKELY(0 == (ocacheL1_event_ctr++
& ((1<<OC_MOVE_FORWARDS_EVERY_BITS)-1)))) {
- moveLineForwards( &ocache->set[setno], line );
+ moveLineForwards( &ocacheL1->set[setno], line );
line--;
}
- return &ocache->set[setno].line[line];
+ return &ocacheL1->set[setno].line[line];
}
}
@@ -2046,7 +2253,7 @@
tl_assert(line > 0);
/* First, move the to-be-ejected line to the L2 cache. */
- victim = &ocache->set[setno].line[line];
+ victim = &ocacheL1->set[setno].line[line];
c = classify_OCacheLine(victim);
switch (c) {
case 'e':
@@ -2081,19 +2288,19 @@
inL2 = ocacheL2_find_tag( tag );
if (inL2) {
/* We're in luck. It's in the L2. */
- ocache->set[setno].line[line] = *inL2;
+ ocacheL1->set[setno].line[line] = *inL2;
} else {
/* Missed at both levels of the cache hierarchy. We have to
declare it as full of zeroes (unknown origins). */
stats__ocacheL2_misses++;
- zeroise_OCacheLine( &ocache->set[setno].line[line], tag );
+ zeroise_OCacheLine( &ocacheL1->set[setno].line[line], tag );
}
/* Move it one forwards */
- moveLineForwards( &ocache->set[setno], line );
+ moveLineForwards( &ocacheL1->set[setno], line );
line--;
- return &ocache->set[setno].line[line];
+ return &ocacheL1->set[setno].line[line];
}
static INLINE OCacheLine* find_OCacheLine ( Addr a )
@@ -2109,8 +2316,8 @@
tl_assert(0 == (tag & (4 * OC_W32S_PER_LINE - 1)));
}
- if (LIKELY(ocache->set[setno].line[0].tag == tag)) {
- return &ocache->set[setno].line[0];
+ if (LIKELY(ocacheL1->set[setno].line[0].tag == tag)) {
+ return &ocacheL1->set[setno].line[0];
}
return find_OCacheLine_SLOW( a );
@@ -5264,10 +5471,10 @@
if we need it. */
if (MC_(clo_mc_level) >= 3) {
init_OCache();
- tl_assert(ocache != NULL);
+ tl_assert(ocacheL1 != NULL);
tl_assert(ocacheL2 != NULL);
} else {
- tl_assert(ocache == NULL);
+ tl_assert(ocacheL1 == NULL);
tl_assert(ocacheL2 == NULL);
}
}
@@ -5390,7 +5597,7 @@
" niacache: %,12lu refs %,12lu misses",
stats__nia_cache_queries, stats__nia_cache_misses);
} else {
- tl_assert(ocache == NULL);
+ tl_assert(ocacheL1 == NULL);
tl_assert(ocacheL2 == NULL);
}
}
@@ -5518,10 +5725,10 @@
/* This is small. Always initialise it. */
init_nia_to_ecu_cache();
- /* We can't initialise ocache/ocacheL2 yet, since we don't know if
- we need to, since the command line args haven't been processed
- yet. Hence defer it to mc_post_clo_init. */
- tl_assert(ocache == NULL);
+ /* We can't initialise ocacheL1/ocacheL2 yet, since we don't know
+ if we need to, since the command line args haven't been
+ processed yet. Hence defer it to mc_post_clo_init. */
+ tl_assert(ocacheL1 == NULL);
tl_assert(ocacheL2 == NULL);
/* Check some important stuff. See extensive comments above
|
|
From: Tom H. <th...@cy...> - 2008-05-05 03:13:35
|
Nightly build on aston ( x86_64, Fedora Core 5 ) started at 2008-05-05 03:20:20 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 429 tests, 6 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-05-05 02:59:48
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2008-05-05 03:05:20 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 423 tests, 4 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-05-05 02:52:12
|
Nightly build on trojan ( x86_64, Fedora Core 6 ) started at 2008-05-05 03:25:10 BST Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 427 tests, 7 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/bug133694 (stdout) memcheck/tests/x86/bug133694 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap2 (stdout) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 427 tests, 6 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/bug133694 (stdout) memcheck/tests/x86/bug133694 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Mon May 5 03:39:48 2008 --- new.short Mon May 5 03:52:17 2008 *************** *** 8,10 **** ! == 427 tests, 6 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 427 tests, 7 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) *************** *** 17,18 **** --- 17,19 ---- none/tests/mremap2 (stdout) + helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc20_verifywrap (stderr) |
|
From: Tom H. <th...@cy...> - 2008-05-05 02:45:15
|
Nightly build on dellow ( x86_64, Fedora 8 ) started at 2008-05-05 03:10:12 BST Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 423 tests, 7 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 423 tests, 8 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Mon May 5 03:25:38 2008 --- new.short Mon May 5 03:45:19 2008 *************** *** 8,10 **** ! == 423 tests, 8 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 423 tests, 7 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) *************** *** 14,16 **** none/tests/mremap2 (stdout) - helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc18_semabuse (stderr) --- 14,15 ---- |
|
From: Tom H. <th...@cy...> - 2008-05-05 02:23:37
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2008-05-05 03:00:05 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 429 tests, 30 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_switch (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) none/tests/amd64/insn_ssse3 (stdout) none/tests/amd64/insn_ssse3 (stderr) none/tests/amd64/ssse3_misaligned (stderr) none/tests/blockfault (stderr) none/tests/fdleak_fcntl (stderr) none/tests/mremap2 (stdout) none/tests/x86/insn_ssse3 (stdout) none/tests/x86/insn_ssse3 (stderr) none/tests/x86/ssse3_misaligned (stderr) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) |
|
From: Julian S. <js...@ac...> - 2008-05-05 00:05:59
|
> slower. With regard to future NPTL versions: the approach to suppress > all errors in libpthread is not future-proof. If some day some of the > NPTL-functions that access thread-private data are implemented as > inline functions, suppressing data races on the basis of call stack > pattern matching won't work anymore. Hmm, good point. I hadn't thought of that. > VG_(get_StackTrace)() returns values in sps[] that are not valid stack > pointers for the relevant thread. I did not expect this this behavior > from VG_(get_StackTrace)(). If this is the intended behavior of > VG_(get_StackTrace)(), can you please document this behavior ? Will do. J |
|
From: Julian S. <js...@ac...> - 2008-05-04 23:59:38
|
One of the kinds of errors that Memcheck finds is dangerous uses of uninitialised values, usually when they get used in an if-statement. This is a useful facility, but it is also the single most complained about aspect of Memcheck. The problem is that the point where Memcheck reports the error is often a long way after the heap or stack allocation that created the uninitialised value. And so it can be very difficult to find the root cause of the problem. Memcheck will now optionally track these origins, and, when reporting an uninitialised value error, it can show the origin too. If the origin is a heap allocation, it shows where the block was allocated. If the origin was a stack allocation, it will tell you the function that did the allocation. A couple of simple examples are shown below. Of course there's no free lunch: Memcheck's speed is approximately halved, and memory consumption increases by a minimum of 100MB. But in initial testing, on a large C++ codebase, it has proven effective. You can try out this functionality using the SVN trunk: svn co svn://svn.valgrind.org/valgrind/trunk cd trunk ./autogen.sh ./configure --prefix=... and then run with --track-origins=yes. This functionality was inspired by the work of Bond, Nethercote, et al, as reported in the paper "Tracking Bad Apples: Reporting the Origin of Null and Undefined Value Errors" (http://www.valgrind.org/docs/origin-tracking2007.pdf), but the actual implementation is very different from that described in the paper. Feedback, comments, bug reports welcome. J Simple example of an uninitialised value use originating from a heap block: Conditional jump or move depends on uninitialised value(s) at 0x400ACB: main (origin1-yes.c:64) Uninitialised value was created by a heap allocation at 0x4C234BB: malloc (vg_replace_malloc.c:207) by 0x400A9B: main (origin1-yes.c:61) And one from a stack allocation (a local, or "auto" variable): Conditional jump or move depends on uninitialised value(s) at 0x400944: main (origin3-no.c:33) Uninitialised value was created by a stack allocation at 0x4008B4: main (origin3-no.c:15) An example from the opposite end of the size/triviality spectrum: Use of uninitialised value of size 8 at 0x4F277E7: BitmapReadAccess::SetPixelFor_24BIT_TC_BGR (bmpacc2.cxx:195) by 0x4F1A8CE: Bitmap::ImplConvertUp (bmpacc.hxx:542) by 0x4F1B9D3: Bitmap::Convert (bitmap3.cxx:365) Uninitialised value was created by a heap allocation at 0x4C22DDB: malloc (vg_replace_malloc.c:207) by 0x719B4FA: rtl_allocateMemory (alloc_global.c:311) by 0x470BDA: allocate (operators_new_delete.cxx:160) by 0x470C4A: operator new[](unsigned long) (operators_new_delete.cxx:239) by 0xEBCAABC: X11SalBitmap::ImplCreateDIB (salbmp.cxx:194) |
|
From: <sv...@va...> - 2008-05-04 23:06:26
|
Author: sewardj
Date: 2008-05-05 00:06:28 +0100 (Mon, 05 May 2008)
New Revision: 8006
Log:
Add documentation on the new --track-origins=no|yes [no] flag.
Modified:
trunk/memcheck/docs/mc-manual.xml
Modified: trunk/memcheck/docs/mc-manual.xml
===================================================================
--- trunk/memcheck/docs/mc-manual.xml 2008-05-04 11:59:01 UTC (rev 8005)
+++ trunk/memcheck/docs/mc-manual.xml 2008-05-04 23:06:28 UTC (rev 8006)
@@ -60,6 +60,78 @@
<!-- start of xi:include in the manpage -->
<variablelist id="mc.opts.list">
+ <varlistentry id="opt.undef-value-errors" xreflabel="--undef-value-errors">
+ <term>
+ <option><![CDATA[--undef-value-errors=<yes|no> [default: yes] ]]></option>
+ </term>
+ <listitem>
+ <para>Controls whether <constant>memcheck</constant> reports
+ uses of undefined value errors. Set this to
+ <varname>no</varname> if you don't want to see undefined value
+ errors. It also has the side effect of speeding up
+ <constant>memcheck</constant> somewhat.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="opt.track-origins" xreflabel="--track-origins">
+ <term>
+ <option><![CDATA[--track-origins=<yes|no> [default: no] ]]></option>
+ </term>
+ <listitem>
+ <para>Controls whether <constant>memcheck</constant> tracks
+ the origin of uninitialised values. By default, it does not,
+ which means that although it can tell you that an
+ uninitialised value is being used in a dangerous way, it
+ cannot tell you where the uninitialised value came from. This
+ often makes it difficult to track down the root problem.
+ </para>
+ <para>When set
+ to <varname>yes</varname>, <constant>memcheck</constant> keeps
+ track of the origins of all uninitialised values. Then, when
+ an uninitialised value error is
+ reported, <constant>memcheck</constant> will try to show the
+ origin of the value. An origin can be one of the following
+ four places: a heap block, a stack allocation, a client
+ request, or miscellaneous other sources (eg, a call
+ to <varname>brk</varname>).
+ </para>
+ <para>For uninitialised values originating from a heap
+ block, <constant>memcheck</constant> shows where the block was
+ allocated. For uninitialised values originating from a stack
+ allocation, <constant>memcheck</constant> can tell you which
+ function allocated the value, but no more than that -- typically
+ it shows you the source location of the opening brace of the
+ function. So you should carefully check that all of the
+ function's local variables are initialised properly.
+ </para>
+ <para>Performance overhead: origin tracking is expensive. It
+ halves <constant>memcheck</constant>'s speed and increases
+ memory use by a minimum of 100MB, and possibly more.
+ Nevertheless it can drastically reduce the effort required to
+ identify the root cause of uninitialised value errors, and so
+ is often a programmer productivity win, despite running
+ more slowly.
+ </para>
+ <para>Accuracy: <constant>memcheck</constant> tracks origins
+ quite accurately. To avoid very large space and time
+ overheads, some approximations are made. It is possible,
+ although unlikely, that
+ <constant>memcheck</constant> will report an incorrect origin,
+ or not be able to identify any origin.
+ </para>
+ <para>Note that the combination
+ <option>--track-origins=yes</option>
+ and <option>--undef-value-errors=no</option> is
+ nonsensical. <constant>memcheck</constant> checks for and
+ rejects this combination at startup.
+ </para>
+ <para>Origin tracking is a new feature, introduced in Valgrind
+ version 3.4.0.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="opt.leak-check" xreflabel="--leak-check">
<term>
<option><![CDATA[--leak-check=<no|summary|yes|full> [default: summary] ]]></option>
@@ -193,20 +265,6 @@
</listitem>
</varlistentry>
- <varlistentry id="opt.undef-value-errors" xreflabel="--undef-value-errors">
- <term>
- <option><![CDATA[--undef-value-errors=<yes|no> [default: yes] ]]></option>
- </term>
- <listitem>
- <para>Controls whether <constant>memcheck</constant> detects
- dangerous uses of undefined value errors. Set this to
- <varname>no</varname> if you don't like seeing undefined value
- errors; it also has the side effect of speeding
- <constant>memcheck</constant> up somewhat.
- </para>
- </listitem>
- </varlistentry>
-
<varlistentry id="opt.malloc-fill" xreflabel="--malloc-fill">
<term>
<option><![CDATA[--malloc-fill=<hexnumber> ]]></option>
@@ -356,6 +414,11 @@
</listitem>
</itemizedlist>
+<para>To see information on the sources of uninitialised data in your
+program, use the <option>--track-origins=yes</option> flag. This
+makes Memcheck run more slowly, but can make it much easier to track down
+the root causes of uninitialised value errors.</para>
+
</sect2>
|
|
From: Nuno L. <nun...@sa...> - 2008-05-04 13:50:09
|
> That worked, yes!
> Now I just get the following:
>
> $ cat exp-drd/tests/fp_race.stderr.diff
> 1a2,8
>>
>> WARNING: DRD has only been tested on x86-linux and amd64-linux.
>>
>> get_Dwarf_Reg(ppc64-linux)(31)
>> get_Dwarf_Reg(ppc64-linux)(31)
>> get_Dwarf_Reg(ppc64-linux)(31)
>> get_Dwarf_Reg(ppc64-linux)(31)
These prints are weird. They come from the following code:
/* FIXME: duplicates logic in readdwarf.c: copy_convert_CfiExpr_tree
and {FP,SP}_REG decls */
static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, RegSummary* regs )
{
vg_assert(regs);
# elif defined(VGP_ppc64_linux)
if (regno == 1/*SP*/) { *a = regs->sp; return True; }
VG_(printf)("get_Dwarf_Reg(ppc64-linux)(%ld)\n", regno);
if (regno == 31) return False;
vg_assert(0);
# endif
return False;
}
Shouldn't that printf be moved after the regno == 31 test?
> Otherwise tests seem to be working. Now I'm rebuilding the latest SVN
> trunk
> after Bart's changes to check if it works as well.
Ok, so latest svn version seems to be working fine! Thanks for fixing the
problem :)
Nuno
|
|
From: Nuno L. <nun...@sa...> - 2008-05-04 12:36:20
|
> This strikes me as much safer:
>
> if (0) {
> husa = (nframes >= 1 ? sps[nframes - 1] : VG_(get_SP)(vg_tid));
> } else {
> UInt i;
> tl_assert(nframes >= 1 && nframes <= n_ips);
> husa = sps[0];
> for (i = 1; i < nframes; i++) {
> if (sps[i] == 0) break;
> if (sps[i] > husa) husa = sps[i];
> }
> }
>
> This produces husa = 0xFEA04940, the assertion does not fail, and drd
> does not go into outer space. (It was taking about 1GB just to run
> /bin/ls before this).
>
> Nuno, can you try that?
That worked, yes!
Now I just get the following:
$ cat exp-drd/tests/fp_race.stderr.diff
1a2,8
>
> WARNING: DRD has only been tested on x86-linux and amd64-linux.
>
> get_Dwarf_Reg(ppc64-linux)(31)
> get_Dwarf_Reg(ppc64-linux)(31)
> get_Dwarf_Reg(ppc64-linux)(31)
> get_Dwarf_Reg(ppc64-linux)(31)
10a18,21
> get_Dwarf_Reg(ppc64-linux)(31)
> get_Dwarf_Reg(ppc64-linux)(31)
> get_Dwarf_Reg(ppc64-linux)(31)
> get_Dwarf_Reg(ppc64-linux)(31)
Otherwise tests seem to be working. Now I'm rebuilding the latest SVN trunk
after Bart's changes to check if it works as well.
Nuno
|
|
From: Bart V. A. <bar...@gm...> - 2008-05-04 12:00:23
|
On Sun, May 4, 2008 at 11:26 AM, Julian Seward <js...@ac...> wrote: > >> As you know on Linux the NPTL allocates space on the top of the stack >> for NPTL-private data. This data is accessed by more than one thread. >> In order to avoid false positives on this NPTL-private data I let DRD >> suppress data race reports on data accesses in the NPTL-private data >> area. > > What happens if NPTL puts some thread private data in some other > place? Then DRD complains again. I saw the same problem in > Helgrind but simply decided to suppress all errors that it > reports inside libpthread. One of the design goals of the NPTL was to make the creation of new threads as fast as possible. That is why the NPTL puts thread-private data on thread stacks instead of allocating these via a separate memory allocation. Any other approach would make the NPTL slightly slower. With regard to future NPTL versions: the approach to suppress all errors in libpthread is not future-proof. If some day some of the NPTL-functions that access thread-private data are implemented as inline functions, suppressing data races on the basis of call stack pattern matching won't work anymore. > nframes = 6 > sps[0] = 0xFEA04790 > sps[1] = 0xFEA048D0 > sps[2] = 0xFEA048E0 > sps[3] = 0xFEA04910 > sps[4] = 0xFEA04940 > sps[5] = 0x0 > sps[6] = 0x0 > sps[7] = 0x0 > sps[8] = 0x46AAD70 > sps[9] = 0xFFFFFFFF Thanks for the workaround -- by this time I have checked in a slightly modified variant of the workaround. But the above output confirms that VG_(get_StackTrace)() returns values in sps[] that are not valid stack pointers for the relevant thread. I did not expect this this behavior from VG_(get_StackTrace)(). If this is the intended behavior of VG_(get_StackTrace)(), can you please document this behavior ? Bart. |
|
From: <sv...@va...> - 2008-05-04 11:59:04
|
Author: bart
Date: 2008-05-04 12:59:01 +0100 (Sun, 04 May 2008)
New Revision: 8005
Log:
Make sure that the return value of highest_used_stack_address() is a valid stack pointer.
Modified:
trunk/exp-drd/drd_clientreq.c
Modified: trunk/exp-drd/drd_clientreq.c
===================================================================
--- trunk/exp-drd/drd_clientreq.c 2008-05-04 08:10:24 UTC (rev 8004)
+++ trunk/exp-drd/drd_clientreq.c 2008-05-04 11:59:01 UTC (rev 8005)
@@ -91,20 +91,35 @@
{
UInt nframes;
const UInt n_ips = 10;
+ UInt i;
Addr ips[n_ips], sps[n_ips];
Addr husa;
nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, 0, 0);
+ tl_assert(1 <= nframes && nframes <= n_ips);
- /* Paranoia ... */
+ /* A hack to work around VG_(get_StackTrace)()'s behavior that sometimes */
+ /* the topmost stackframes it returns are bogus (this occurs sometimes */
+ /* at least on amd64, ppc32 and ppc64). */
+
+ husa = sps[0];
+
tl_assert(VG_(thread_get_stack_max)(vg_tid)
- - VG_(thread_get_stack_size)(vg_tid) <= VG_(get_SP)(vg_tid)
- && VG_(get_SP)(vg_tid) < VG_(thread_get_stack_max)(vg_tid));
+ - VG_(thread_get_stack_size)(vg_tid) <= husa
+ && husa < VG_(thread_get_stack_max)(vg_tid));
- husa = (nframes >= 1 ? sps[nframes - 1] : VG_(get_SP)(vg_tid));
+ for (i = 1; i < nframes; i++)
+ {
+ if (sps[i] == 0)
+ break;
+ if (husa < sps[i] && sps[i] < VG_(thread_get_stack_max)(vg_tid))
+ husa = sps[i];
+ }
+
tl_assert(VG_(thread_get_stack_max)(vg_tid)
- VG_(thread_get_stack_size)(vg_tid) <= husa
&& husa < VG_(thread_get_stack_max)(vg_tid));
+
return husa;
}
|
|
From: Julian S. <js...@ac...> - 2008-05-04 09:31:23
|
> As you know on Linux the NPTL allocates space on the top of the stack
> for NPTL-private data. This data is accessed by more than one thread.
> In order to avoid false positives on this NPTL-private data I let DRD
> suppress data race reports on data accesses in the NPTL-private data
> area.
What happens if NPTL puts some thread private data in some other
place? Then DRD complains again. I saw the same problem in
Helgrind but simply decided to suppress all errors that it
reports inside libpthread.
But anyway. I think
husa = (nframes >= 1 ? sps[nframes - 1] : VG_(get_SP)(vg_tid));
is not good. I added this
VG_(printf)("\n\ngetting stack for tid %d\n", (Int)vg_tid);
VG_(pp_ExeContext)( VG_(record_ExeContext)( vg_tid, 0 ));
just before your call to VG_(get_StackTrace), and
VG_(printf)("nframes = %d\n", nframes);
{Int i; for (i = 0; i < 10; i++)
VG_(printf)("sps[%d] = %p\n", i, sps[i]);}
just after. What it shows is:
getting stack for tid 1
==27412== at 0xFF7C4D8: init (drd_pthread_intercepts.c:244)
==27412== by 0xFF7CDD4:
(within /home/sewardj/VgTRUNK/trunk/exp-drd/vgpreload_exp-drd-ppc32-linux.so)
==27412== by 0xFF75D3C:
(within /home/sewardj/VgTRUNK/trunk/exp-drd/vgpreload_exp-drd-ppc32-linux.so)
==27412== by 0xFFCEC28: call_init (in /lib/ld-2.7.so)
==27412== by 0xFFCEDAC: _dl_init (in /lib/ld-2.7.so)
==27412== by 0xFFD70A0: _start (in /lib/ld-2.7.so)
nframes = 6
sps[0] = 0xFEA04790
sps[1] = 0xFEA048D0
sps[2] = 0xFEA048E0
sps[3] = 0xFEA04910
sps[4] = 0xFEA04940
sps[5] = 0x0
sps[6] = 0x0
sps[7] = 0x0
sps[8] = 0x46AAD70
sps[9] = 0xFFFFFFFF
So you get husa = sps[n_frames - 1] = sps[5] = 0, which is bogus.
This strikes me as much safer:
if (0) {
husa = (nframes >= 1 ? sps[nframes - 1] : VG_(get_SP)(vg_tid));
} else {
UInt i;
tl_assert(nframes >= 1 && nframes <= n_ips);
husa = sps[0];
for (i = 1; i < nframes; i++) {
if (sps[i] == 0) break;
if (sps[i] > husa) husa = sps[i];
}
}
This produces husa = 0xFEA04940, the assertion does not fail, and drd
does not go into outer space. (It was taking about 1GB just to run
/bin/ls before this).
Nuno, can you try that?
J
|
|
From: Bart V. A. <bar...@gm...> - 2008-05-04 08:41:50
|
On Sun, May 4, 2008 at 10:19 AM, Julian Seward <js...@ac...> wrote: > > Can you clarify the link between this mechanism for finding the highest > address in a stack, and why drd takes lots of memory on ppc? I assume > you have some hypothesis in mind, but I don't know what it is. As you know on Linux the NPTL allocates space on the top of the stack for NPTL-private data. This data is accessed by more than one thread. In order to avoid false positives on this NPTL-private data I let DRD suppress data race reports on data accesses in the NPTL-private data area. There is no easy way to find out where this area is allocated, so what happens in DRD is to suppress all accesses to data in the range (highest_used_stack_address() .. (top of stack)). This address range contains a little bit more than the NPTL-private data area, but it contains at least that area. Suppression happens by setting one bit in a bitmap for every address to be suppressed. So my hypothesis about the cause of the out-of-memory error on ppc is that the function highest_used_stack_address() was returning a pointer that was far out of range of the stack addreses. The following error message confirms that VG_(get_StackTrace)() returns a stack pointer that is out of range (see also the source code of highest_used_stack_address() in the source file exp-drd/drd_clientreq.c): exp-drd: drd_clientreq.c:107 (highest_used_stack_address): Assertion 'VG_(thread_get_stack_max)(vg_tid) - VG_(thread_get_stack_size)(vg_tid) <= husa && husa < VG_(thread_get_stack_max)(vg_tid)' failed. Do you already have a clue about why VG_(get_StackTrace)() shows such behavior on ppc ? Bart. |
|
From: Julian S. <js...@ac...> - 2008-05-04 08:24:43
|
> Thanks. I see a mysterious line in the ppc64 output, that does not
> appear in the amd64 output:
>
> --22020:1:signals extending a stack base 0x7fefff000 down by 4096
>
> The address 0x7fefff000 looks to me like an address on Valgrind's
> stack. Is it normal that VG_(extend_stack)() gets called when
> Valgrind's stack is extended ? Shouldn't this function be called only
> for client stacks ?
I think it is a client stack. From earlier in the trace there is:
--22020:1:initimg Setup client stack: size will be 8388608
and then
--22020:1:sched sched_init_phase2: tid_main=1, cls_end=0x7ff000fff,
cls_sz=8388608
so the first thread's client stack is placed ending at 0x7ff000fff,
and so 0x7fefff000 is just 1fff (2 pages) before the end.
Also this is visible from the printed-out map:
--22020:1:aspacem 20: RSVN 07fe801000-07feffefff 8380416 ----- SmUpper
--22020:1:aspacem 21: anon 07fefff000-07ff000fff 8192 rwx--
Sections with lowercase names ("anon") belong to the client, and those
with uppercase names ("RSVN") belong to Valgrind. What this shows is
that there is an 8k client stack area belonging to the client and
immediately before it a "reservation" of 8388608 - 8192 == 8380416
belonging to Valgrind. The reservation is the place where V will expand
the stack into, on demand.
------
To answer your question re running_tid=1, at least in this example,
I would guess there is only one thread (no others have been created
yet) and so no ambiguity. In the kind of crash message that Nuno posted,
there is only one thread stack ("Thread 1: status = VgTs_Runnable" ..),
and so this is the root thread, not one created by pthread_create. If
there is > 1 thread then there would be > 1 thread stack shown.
------
Can you clarify the link between this mechanism for finding the highest
address in a stack, and why drd takes lots of memory on ppc? I assume
you have some hypothesis in mind, but I don't know what it is.
J
|
|
From: <sv...@va...> - 2008-05-04 08:14:20
|
Author: bart
Date: 2008-05-04 09:10:24 +0100 (Sun, 04 May 2008)
New Revision: 8004
Log:
Fixed compiler warnings.
Modified:
trunk/memcheck/tests/oset_test.c
Modified: trunk/memcheck/tests/oset_test.c
===================================================================
--- trunk/memcheck/tests/oset_test.c 2008-05-04 08:09:44 UTC (rev 8003)
+++ trunk/memcheck/tests/oset_test.c 2008-05-04 08:10:24 UTC (rev 8004)
@@ -45,8 +45,13 @@
return seed;
}
+static void* allocate_node(SizeT szB)
+{ return malloc(szB); }
+static void free_node(void* p)
+{ return free(p); }
+
//---------------------------------------------------------------------------
// Word example
//---------------------------------------------------------------------------
@@ -78,8 +83,8 @@
// Create a static OSet of Ints. This one uses fast (built-in)
// comparisons.
OSet* oset = VG_(OSetGen_Create)(0,
- NULL,
- malloc, free);
+ NULL,
+ allocate_node, free_node);
// Try some operations on an empty OSet to ensure they don't screw up.
vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
@@ -212,7 +217,7 @@
// Create a static OSet of Ints. This one uses fast (built-in)
// comparisons.
- OSet* oset = VG_(OSetWord_Create)(malloc, free);
+ OSet* oset = VG_(OSetWord_Create)(allocate_node, free_node);
// Try some operations on an empty OSet to ensure they don't screw up.
vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
@@ -370,7 +375,7 @@
// comparisons.
OSet* oset = VG_(OSetGen_Create)(offsetof(Block, first),
blockCmp,
- malloc, free);
+ allocate_node, free_node);
// Try some operations on an empty OSet to ensure they don't screw up.
vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
|
|
From: <sv...@va...> - 2008-05-04 08:13:48
|
Author: bart Date: 2008-05-04 09:09:44 +0100 (Sun, 04 May 2008) New Revision: 8003 Log: Disable gcc warnings about shadowed variables when compiling varinfo2.c. Modified: trunk/memcheck/tests/Makefile.am Modified: trunk/memcheck/tests/Makefile.am =================================================================== --- trunk/memcheck/tests/Makefile.am 2008-05-04 07:47:21 UTC (rev 8002) +++ trunk/memcheck/tests/Makefile.am 2008-05-04 08:09:44 UTC (rev 8003) @@ -248,7 +248,7 @@ # To make it a bit more realistic, have some optimisation enabled # for the varinfo tests. We still expect sane results. varinfo1_CFLAGS = $(AM_FLAG_M3264_PRI) $(AM_CFLAGS) -O -g -varinfo2_CFLAGS = $(AM_FLAG_M3264_PRI) $(AM_CFLAGS) -O -g +varinfo2_CFLAGS = $(AM_FLAG_M3264_PRI) $(AM_CFLAGS) -O -g -Wno-shadow varinfo3_CFLAGS = $(AM_FLAG_M3264_PRI) $(AM_CFLAGS) -O -g varinfo4_CFLAGS = $(AM_FLAG_M3264_PRI) $(AM_CFLAGS) -O -g varinfo5_CFLAGS = $(AM_FLAG_M3264_PRI) $(AM_CFLAGS) -O -g |
|
From: <sv...@va...> - 2008-05-04 07:47:17
|
Author: bart
Date: 2008-05-04 08:47:21 +0100 (Sun, 04 May 2008)
New Revision: 8002
Log:
Suppressed most output while the regression test is run.
Modified:
trunk/exp-drd/tests/drd_bitmap_test.c
trunk/exp-drd/tests/drd_bitmap_test.stdout.exp
trunk/exp-drd/tests/drd_bitmap_test.vgtest
Modified: trunk/exp-drd/tests/drd_bitmap_test.c
===================================================================
--- trunk/exp-drd/tests/drd_bitmap_test.c 2008-05-04 07:46:20 UTC (rev 8001)
+++ trunk/exp-drd/tests/drd_bitmap_test.c 2008-05-04 07:47:21 UTC (rev 8002)
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "coregrind/m_oset.c"
#include "exp-drd/drd_bitmap.c"
#include "exp-drd/pub_drd_bitmap.h"
@@ -24,69 +25,130 @@
{ return memcmp(s1, s2, n); }
UInt VG_(printf)(const HChar *format, ...)
{ UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); return ret; }
+UInt VG_(message)(VgMsgKind kind, const HChar* format, ...)
+{ UInt ret; va_list vargs; va_start(vargs, format); ret = vprintf(format, vargs); va_end(vargs); printf("\n"); return ret; }
Bool drd_is_suppressed(const Addr a1, const Addr a2)
{ assert(0); }
-/* Unit test */
+/* Actual unit test */
+
+static int s_verbose = 1;
+
static
struct { Addr address; SizeT size; BmAccessTypeT access_type; }
- s_args[] = {
- { 0, 1, eLoad },
- { 666, 4, eLoad },
- { 667, 2, eStore },
- { 1024, 1, eStore },
- { 0xffffUL, 1, eStore },
- { 0x0001ffffUL, 1, eLoad },
- { 0x00ffffffUL, 1, eLoad },
- { 0xffffffffUL, 1, eStore },
+ s_test1_args[] = {
+ { 0, 1, eLoad },
+ { 666, 4, eLoad },
+ { 667, 2, eStore },
+ { 1024, 1, eStore },
+ { 0xffffULL, 1, eStore },
+ { 0x0001ffffULL, 1, eLoad },
+ { 0x00ffffffULL, 1, eLoad },
+ { 0xfffffffeULL - ADDR0_COUNT, 1, eStore },
+#if defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
+ { 0xffffffffULL - ADDR0_COUNT, 1, eStore },
+ { 0xffffffffULL, 1, eStore },
+ { 0x100000000ULL, 1, eStore },
+ { -2ULL - ADDR0_COUNT, 1, eStore },
+#endif
};
-void bm_test(void)
+void bm_test1(void)
{
struct bitmap* bm;
struct bitmap* bm2;
unsigned i, j;
- VG_(printf)("Start of DRD BM unit test.\n");
-
bm = bm_new();
- for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
+ for (i = 0; i < sizeof(s_test1_args)/sizeof(s_test1_args[0]); i++)
{
bm_access_range(bm,
- s_args[i].address,
- s_args[i].address + s_args[i].size,
- s_args[i].access_type);
+ s_test1_args[i].address,
+ s_test1_args[i].address + s_test1_args[i].size,
+ s_test1_args[i].access_type);
}
- VG_(printf)("Map contents -- should contain 10 addresses:\n");
- bm_print(bm);
+ if (s_verbose)
+ {
+ VG_(printf)("Bitmap contents:\n");
+ bm_print(bm);
+ }
- for (i = 0; i < sizeof(s_args)/sizeof(s_args[0]); i++)
+ for (i = 0; i < sizeof(s_test1_args)/sizeof(s_test1_args[0]); i++)
{
- for (j = 0; j < s_args[i].size; j++)
+ for (j = 0; j < s_test1_args[i].size; j++)
{
- tl_assert(bm_has_1(bm, s_args[i].address + j, s_args[i].access_type));
+ tl_assert(bm_has_1(bm,
+ s_test1_args[i].address + j,
+ s_test1_args[i].access_type));
}
}
- VG_(printf)("Merge result:\n");
+ if (s_verbose)
+ VG_(printf)("Merge result:\n");
bm2 = bm_new();
bm_merge2(bm2, bm);
bm_merge2(bm2, bm);
- bm_print(bm);
+ if (s_verbose)
+ bm_print(bm2);
+ //assert(bm_equal(bm, bm2));
+ assert(bm_equal(bm2, bm));
- VG_(printf)("Deleting bitmap bm\n");
+ if (s_verbose)
+ VG_(printf)("Deleting bitmap bm\n");
bm_delete(bm);
- VG_(printf)("Deleting bitmap bm2\n");
+ if (s_verbose)
+ VG_(printf)("Deleting bitmap bm2\n");
bm_delete(bm2);
+}
- VG_(printf)("End of DRD BM unit test.\n");
+/* Test whether bm_equal() works correctly. */
+void bm_test2()
+{
+ struct bitmap* bm1;
+ struct bitmap* bm2;
+
+ bm1 = bm_new();
+ bm2 = bm_new();
+ bm_access_load_1(bm1, 7);
+ bm_access_load_1(bm2, ADDR0_COUNT + 7);
+ assert(! bm_equal(bm1, bm2));
+ assert(! bm_equal(bm2, bm1));
+ bm_access_load_1(bm2, 7);
+ assert(! bm_equal(bm1, bm2));
+ assert(! bm_equal(bm2, bm1));
+ bm_access_store_1(bm1, ADDR0_COUNT + 7);
+ assert(! bm_equal(bm1, bm2));
+ assert(! bm_equal(bm2, bm1));
+ bm_delete(bm1);
+ bm_delete(bm2);
}
int main(int argc, char** argv)
{
- bm_test();
+ int optchar;
+
+ while ((optchar = getopt(argc, argv, "q")) != EOF)
+ {
+ switch (optchar)
+ {
+ case 'q':
+ s_verbose = 0;
+ break;
+ default:
+ fprintf(stderr, "Usage: %s [-q].\n", argv[0]);
+ break;
+ }
+ }
+
+ VG_(printf)("Start of DRD BM unit test.\n");
+
+ bm_test1();
+ bm_test2();
+
+ VG_(printf)("End of DRD BM unit test.\n");
+
return 0;
}
Modified: trunk/exp-drd/tests/drd_bitmap_test.stdout.exp
===================================================================
--- trunk/exp-drd/tests/drd_bitmap_test.stdout.exp 2008-05-04 07:46:20 UTC (rev 8001)
+++ trunk/exp-drd/tests/drd_bitmap_test.stdout.exp 2008-05-04 07:47:21 UTC (rev 8002)
@@ -1,26 +1,2 @@
Start of DRD BM unit test.
-Map contents -- should contain 10 addresses:
-0x00000000 R
-0x0000029a R
-0x0000029b W R
-0x0000029c W R
-0x0000029d R
-0x00000400 W
-0x0000ffff W
-0x0001ffff R
-0x00ffffff R
-0xffffffff W
-Merge result:
-0x00000000 R
-0x0000029a R
-0x0000029b W R
-0x0000029c W R
-0x0000029d R
-0x00000400 W
-0x0000ffff W
-0x0001ffff R
-0x00ffffff R
-0xffffffff W
-Deleting bitmap bm
-Deleting bitmap bm2
End of DRD BM unit test.
Modified: trunk/exp-drd/tests/drd_bitmap_test.vgtest
===================================================================
--- trunk/exp-drd/tests/drd_bitmap_test.vgtest 2008-05-04 07:46:20 UTC (rev 8001)
+++ trunk/exp-drd/tests/drd_bitmap_test.vgtest 2008-05-04 07:47:21 UTC (rev 8002)
@@ -1,2 +1,3 @@
prereq: ./supported_libpthread
prog: drd_bitmap_test
+args: -q
|
|
From: <sv...@va...> - 2008-05-04 07:46:16
|
Author: bart
Date: 2008-05-04 08:46:20 +0100 (Sun, 04 May 2008)
New Revision: 8001
Log:
Renamed bm_compare() into bm_equal(). Fixed a bug in bm_equal().
Modified:
trunk/exp-drd/drd_bitmap.c
trunk/exp-drd/drd_thread.c
trunk/exp-drd/pub_drd_bitmap.h
Modified: trunk/exp-drd/drd_bitmap.c
===================================================================
--- trunk/exp-drd/drd_bitmap.c 2008-05-03 09:35:01 UTC (rev 8000)
+++ trunk/exp-drd/drd_bitmap.c 2008-05-04 07:46:20 UTC (rev 8001)
@@ -115,6 +115,11 @@
tl_assert(bm);
tl_assert(a1 < a2);
+ /* The current implementation of bm_access_range does not work for the */
+ /* ADDR0_COUNT highest addresses in the address range. At least on Linux */
+ /* this is not a problem since the upper part of the address space is */
+ /* reserved for the kernel. */
+ tl_assert(a2 + ADDR0_COUNT > a2);
for (b = a1; b < a2; b = b_next)
{
@@ -748,14 +753,17 @@
/** Return true if the two bitmaps *lhs and *rhs are identical, and false
* if not.
*/
-Bool bm_compare(struct bitmap* const lhs,
- const struct bitmap* const rhs)
+Bool bm_equal(struct bitmap* const lhs, const struct bitmap* const rhs)
{
struct bitmap2* bm2l;
struct bitmap2ref* bm2l_ref;
struct bitmap2* bm2r;
const struct bitmap2ref* bm2r_ref;
+ /* It's not possible to have two independent iterators over the same OSet, */
+ /* so complain if lhs == rhs. */
+ tl_assert(lhs != rhs);
+
VG_(OSetGen_ResetIter)(lhs->oset);
VG_(OSetGen_ResetIter)(rhs->oset);
@@ -766,28 +774,48 @@
tl_assert(bm_has_any_access(lhs,
bm2l->addr << ADDR0_BITS,
(bm2l->addr + 1) << ADDR0_BITS));
+#if 0
+ VG_(message)(Vg_DebugMsg, "bm_equal: at 0x%lx", bm2l->addr << ADDR0_BITS);
+#endif
+
bm2r_ref = VG_(OSetGen_Next)(rhs->oset);
if (bm2r_ref == 0)
+ {
+#if 0
+ VG_(message)(Vg_DebugMsg, "bm_equal: no match found");
+#endif
return False;
+ }
bm2r = bm2r_ref->bm2;
tl_assert(bm2r);
tl_assert(bm_has_any_access(rhs,
bm2r->addr << ADDR0_BITS,
(bm2r->addr + 1) << ADDR0_BITS));
- if (bm2l->addr != bm2r->addr
- || VG_(memcmp)(&bm2l->bm1, &bm2r->bm1, sizeof(bm2l->bm1)) != 0)
+
+ if (bm2l != bm2r
+ && (bm2l->addr != bm2r->addr
+ || VG_(memcmp)(&bm2l->bm1, &bm2r->bm1, sizeof(bm2l->bm1)) != 0))
{
+#if 0
+ VG_(message)(Vg_DebugMsg, "bm_equal: rhs 0x%lx -- returning false",
+ bm2r->addr << ADDR0_BITS);
+#endif
return False;
}
- bm2r = VG_(OSetGen_Next)(rhs->oset);
- if (bm2r)
- {
- tl_assert(bm_has_any_access(rhs,
- bm2r->addr << ADDR0_BITS,
- (bm2r->addr + 1) << ADDR0_BITS));
- return False;
- }
}
+ bm2r = VG_(OSetGen_Next)(rhs->oset);
+ if (bm2r)
+ {
+ tl_assert(bm_has_any_access(rhs,
+ bm2r->addr << ADDR0_BITS,
+ (bm2r->addr + 1) << ADDR0_BITS));
+#if 0
+ VG_(message)(Vg_DebugMsg,
+ "bm_equal: remaining rhs 0x%lx -- returning false",
+ bm2r->addr << ADDR0_BITS);
+#endif
+ return False;
+ }
return True;
}
@@ -874,13 +902,13 @@
unsigned b;
for (b = 0; b < BITS_PER_UWORD; b++)
{
- UWord const access
+ UWord const access_mask
= ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
| ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
| ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
| ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
Addr const a = MAKE_ADDRESS(bm2l->addr, k * BITS_PER_UWORD | b);
- if (HAS_RACE(access) && ! drd_is_suppressed(a, a + 1))
+ if (HAS_RACE(access_mask) && ! drd_is_suppressed(a, a + 1))
{
return 1;
}
Modified: trunk/exp-drd/drd_thread.c
===================================================================
--- trunk/exp-drd/drd_thread.c 2008-05-03 09:35:01 UTC (rev 8000)
+++ trunk/exp-drd/drd_thread.c 2008-05-04 07:46:20 UTC (rev 8001)
@@ -918,7 +918,7 @@
return True;
thread_compute_danger_set(&computed_danger_set, tid);
- result = bm_compare(s_danger_set, computed_danger_set);
+ result = bm_equal(s_danger_set, computed_danger_set);
bm_delete(computed_danger_set);
return result;
}
Modified: trunk/exp-drd/pub_drd_bitmap.h
===================================================================
--- trunk/exp-drd/pub_drd_bitmap.h 2008-05-03 09:35:01 UTC (rev 8000)
+++ trunk/exp-drd/pub_drd_bitmap.h 2008-05-04 07:46:20 UTC (rev 8001)
@@ -102,8 +102,7 @@
Bool bm_store_8_has_conflict_with(const struct bitmap* const bm,const Addr a1);
Bool bm_store_has_conflict_with(const struct bitmap* const bm,
const Addr a1, const Addr a2);
-Bool bm_compare(struct bitmap* const lhs,
- const struct bitmap* const rhs);
+Bool bm_equal(struct bitmap* const lhs, const struct bitmap* const rhs);
void bm_swap(struct bitmap* const bm1, struct bitmap* const bm2);
void bm_merge2(struct bitmap* const lhs,
const struct bitmap* const rhs);
|