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
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
1
(1) |
2
(3) |
3
(1) |
4
(2) |
|
5
|
6
|
7
(4) |
8
|
9
(2) |
10
|
11
(2) |
|
12
|
13
(3) |
14
(7) |
15
(4) |
16
(2) |
17
|
18
|
|
19
|
20
(1) |
21
(2) |
22
|
23
|
24
|
25
|
|
26
|
27
(1) |
28
|
29
|
30
|
|
|
|
From: Philippe W. <phi...@so...> - 2017-11-07 20:45:07
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=4d621f651033304e3f9d57f673dc872b662c2871 commit 4d621f651033304e3f9d57f673dc872b662c2871 Author: Philippe Waroquiers <phi...@sk...> Date: Sat Nov 4 23:31:19 2017 +0100 Move or conditionalise on CHECK_CEM some expensive asserts * Some RCEC related asserts checking there was no corruption are on hot paths => make these checks only when CHECK_CEM is set. * Move an expensive assert where the event is inserted, as it is useless to check this when searching for an already existing event : it is enough to ensure that an invalid szB cannot be inserted, and so will not be found, and so assert will trigger in the insertion logic. Diff: --- helgrind/libhb_core.c | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/helgrind/libhb_core.c b/helgrind/libhb_core.c index 7fbcdda..792a374 100644 --- a/helgrind/libhb_core.c +++ b/helgrind/libhb_core.c @@ -4305,8 +4305,10 @@ static UWord RCEC_referenced = 0; /* True if the frames of ec1 and ec2 are different. */ static Bool RCEC__differs_by_frames ( RCEC* ec1, RCEC* ec2 ) { Word i; - tl_assert(ec1 && ec1->magic == RCEC_MAGIC); - tl_assert(ec2 && ec2->magic == RCEC_MAGIC); + if (CHECK_CEM) { + tl_assert(ec1 && ec1->magic == RCEC_MAGIC); + tl_assert(ec2 && ec2->magic == RCEC_MAGIC); + } if (ec1->frames_hash != ec2->frames_hash) return True; for (i = 0; i < N_FRAMES; i++) { if (ec1->frames[i] != ec2->frames[i]) return True; @@ -4318,7 +4320,8 @@ static Bool RCEC__differs_by_frames ( RCEC* ec1, RCEC* ec2 ) { static void ctxt__rcdec ( RCEC* ec ) { stats__ctxt_rcdec_calls++; - tl_assert(ec && ec->magic == RCEC_MAGIC); + if (CHECK_CEM) + tl_assert(ec && ec->magic == RCEC_MAGIC); tl_assert(ec->rc > 0); ec->rc--; if (ec->rc == 0) @@ -4327,7 +4330,8 @@ static void ctxt__rcdec ( RCEC* ec ) static void ctxt__rcinc ( RCEC* ec ) { - tl_assert(ec && ec->magic == RCEC_MAGIC); + if (CHECK_CEM) + tl_assert(ec && ec->magic == RCEC_MAGIC); if (ec->rc == 0) RCEC_referenced++; ec->rc++; @@ -4389,8 +4393,14 @@ static RCEC* ctxt__find_or_add ( RCEC* example ) { UWord hent; RCEC* copy; - tl_assert(example && example->magic == RCEC_MAGIC); - tl_assert(example->rc == 0); + + if (CHECK_CEM) { + /* Note that the single caller of ctxt__find_or_add always provides + &thr->cached_rcec as argument. The sanity of thr->cached_rcec is always + checked with a thread terminates. */ + tl_assert(example && example->magic == RCEC_MAGIC); + tl_assert(example->rc == 0); + } /* Search the hash table to see if we already have it. */ stats__ctxt_tab_qs++; @@ -4398,7 +4408,8 @@ static RCEC* ctxt__find_or_add ( RCEC* example ) copy = contextTab[hent]; while (1) { if (!copy) break; - tl_assert(copy->magic == RCEC_MAGIC); + if (CHECK_CEM) + tl_assert(copy->magic == RCEC_MAGIC); stats__ctxt_tab_cmps++; if (!RCEC__differs_by_frames(copy, example)) break; copy = copy->next; @@ -4892,10 +4903,6 @@ static void event_map_bind ( Addr a, SizeT szB, Bool isW, Thr* thr ) rcec = get_RCEC( thr ); - tl_assert (szB == 4 || szB == 8 ||szB == 1 || szB == 2); - // Check for most frequent cases first - // Note: we could support a szB up to 1 << (32 - SCALARTS_N_THRBITS - 1) - /* Look in the oldrefHT to see if we already have a record for this address/thr/sz/isW. */ example.ga = a; @@ -4927,6 +4934,11 @@ static void event_map_bind ( Addr a, SizeT szB, Bool isW, Thr* thr ) OldRef_newest(ref); } else { + tl_assert (szB == 4 || szB == 8 ||szB == 1 || szB == 2); + // We only need to check the size the first time we insert a ref. + // Check for most frequent cases first + // Note: we could support a szB up to 1 << (32 - SCALARTS_N_THRBITS - 1) + /* We don't have a record for this address+triple. Create a new one. */ stats__ctxt_neq_tsw_neq_rcec++; ref = alloc_or_reuse_OldRef(); @@ -5909,7 +5921,8 @@ void zsm_swrite64 ( Addr a, SVal svNew ) { tno = get_treeno(a); //toff = get_tree_offset(a); /* == 0, unused */ cl->descrs[tno] = TREE_DESCR_64; - tl_assert(svNew != SVal_INVALID); + if (CHECK_ZSM) + tl_assert(svNew != SVal_INVALID); /* EXPENSIVE */ cl->svals[cloff + 0] = svNew; cl->svals[cloff + 1] = SVal_INVALID; cl->svals[cloff + 2] = SVal_INVALID; @@ -6862,6 +6875,12 @@ void libhb_async_exit ( Thr* thr ) tl_assert(!thr->llexit_done); thr->llexit_done = True; + /* Check nobody messed up with the cached_rcec */ + tl_assert (thr->cached_rcec.magic == RCEC_MAGIC); + tl_assert (thr->cached_rcec.rc == 0); + tl_assert (thr->cached_rcec.rcX == 0); + tl_assert (thr->cached_rcec.next == NULL); + /* Just to be sure, declare the cached stack invalid. */ set_cached_rcec_validity(thr, False); |
|
From: Julian S. <se...@so...> - 2017-11-07 14:12:33
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=d813fb74af762393a43dd9c70882e655f35ec2ca commit d813fb74af762393a43dd9c70882e655f35ec2ca Author: Julian Seward <js...@ac...> Date: Tue Nov 7 15:01:51 2017 +0100 s390_irgen_EX_SS: add initialisations so as to remove (false positive) warnings from gcc-7.x. When compiling guest_s390_toIR.c for a 32-bit target (a configuration in which it will never be used, but never mind), gcc-7.x notices that sizeof(ss.dec) is larger than sizeof(ss.bytes), so the initialisation of ss.bytes leaves ss.dec.b2 and ss.dec.d2 uninitialised. This patch causes both variants to be initialised. When built for a 64 bit target, the existing initialisation of ss.bytes covers ss.dec completely, so there is no error. Diff: --- VEX/priv/guest_s390_toIR.c | 1 + 1 file changed, 1 insertion(+) diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 14c8950..b36b85e 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -11078,6 +11078,7 @@ s390_irgen_EX_SS(UChar r, IRTemp addr2, stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_CMLEN), mkU64(4))); restart_if(mkexpr(cond)); + ss.dec.op = ss.dec.l = ss.dec.b1 = ss.dec.d1 = ss.dec.b2 = ss.dec.d2 = 0; ss.bytes = last_execute_target; assign(start1, binop(Iop_Add64, mkU64(ss.dec.d1), ss.dec.b1 != 0 ? get_gpr_dw0(ss.dec.b1) : mkU64(0))); |
|
From: Julian S. <se...@so...> - 2017-11-07 13:19:49
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=7dd9a7f8b3118c25014b0a77aff899e517c46bcd commit 7dd9a7f8b3118c25014b0a77aff899e517c46bcd Author: Julian Seward <js...@ac...> Date: Tue Nov 7 14:18:16 2017 +0100 Add -finline-functions to standard build flags, so gcc will consider all functions as candidates for inlining. Diff: --- Makefile.all.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.all.am b/Makefile.all.am index faa170d..29e0407 100644 --- a/Makefile.all.am +++ b/Makefile.all.am @@ -97,7 +97,7 @@ clean-noinst_DSYMS: # -fno-builtin is important for defeating LLVM's idiom recognition # that somehow causes VG_(memset) to get into infinite recursion. AM_CFLAGS_BASE = \ - -O2 -g \ + -O2 -finline-functions -g \ -std=gnu99 \ -Wall \ -Wmissing-prototypes \ |
|
From: Ivo R. <ir...@so...> - 2017-11-04 13:32:03
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=c46053cc386be5757420abbd4b8a8cc6219ed33f commit c46053cc386be5757420abbd4b8a8cc6219ed33f Author: Ivo Raisr <iv...@iv...> Date: Sat Nov 4 14:29:48 2017 +0100 Optionally exit on the first error with --exit-on-first-error=<yes|no>. Fixes BZ#385939. Slightly modified patch by: Fauchet Gauthier <gau...@fr...> Diff: --- NEWS | 1 + coregrind/m_errormgr.c | 15 ++++- coregrind/m_main.c | 9 ++- coregrind/m_options.c | 1 + coregrind/pub_core_options.h | 2 + docs/xml/manual-core.xml | 13 +++++ memcheck/tests/Makefile.am | 4 ++ memcheck/tests/exit_on_first_error.stderr.exp | 9 +++ memcheck/tests/exit_on_first_error.vgtest | 2 + .../tests/exit_on_first_error_with_xml.stderr.exp | 67 ++++++++++++++++++++++ memcheck/tests/exit_on_first_error_with_xml.vgtest | 4 ++ none/tests/cmdline1.stdout.exp | 1 + none/tests/cmdline2.stdout.exp | 3 +- 13 files changed, 126 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index d6acccd..436e287 100644 --- a/NEWS +++ b/NEWS @@ -74,6 +74,7 @@ where XXXXXX is the bug number as listed below. 385334 PPC64, fix vpermr, xxperm, xxpermr mask value. 385868 glibc ld.so _dl_runtime_resolve_avx_slow conditional jump warning. 385912 none/tests/rlimit_nofile fails on newer glibc/kernel. +385939 Optionally exit on the first error 386397 PPC64, valgrind truncates powerpc timebase to 32-bits. n-i-bz Fix missing workq_ops operations (macOS) diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c index fd900ee..c1f8006 100644 --- a/coregrind/m_errormgr.c +++ b/coregrind/m_errormgr.c @@ -511,11 +511,10 @@ Bool VG_(is_action_requested) ( const HChar* action, Bool* clo ) } -/* Do text-mode actions on error, that is, immediately after an error - is printed. These are: +/* Do actions on error, that is, immediately after an error is printed. + These are: * possibly, call the GDB server * possibly, generate a suppression. - Note this should not be called in XML mode! */ static void do_actions_on_error(const Error* err, Bool allow_db_attach) @@ -540,6 +539,14 @@ void do_actions_on_error(const Error* err, Bool allow_db_attach) } if (VG_(clo_gen_suppressions) == 1 && !still_noisy) VG_(clo_gen_suppressions) = 0; + + if (VG_(clo_exit_on_first_error)) { + if (VG_(clo_xml)) + VG_(printf_xml)("</valgrindoutput>\n"); + VG_(umsg)("\n"); + VG_(umsg)("Exit program on first error (--exit-on-first-error=yes)\n"); + VG_(client_exit)( VG_(clo_error_exitcode) ); + } } @@ -566,6 +573,8 @@ void do_actions_on_error(const Error* err, Bool allow_db_attach) * prints the tool-specific parts of the message + In both modes: + * calls do_actions_on_error. This optionally does a gdbserver call and optionally prints a suppression; both of these may require user input. */ diff --git a/coregrind/m_main.c b/coregrind/m_main.c index a37bbb6..4526b12 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -125,6 +125,7 @@ static void usage_NORETURN ( Bool debug_help ) " --demangle=no|yes automatically demangle C++ names? [yes]\n" " --num-callers=<number> show <number> callers in stack traces [12]\n" " --error-limit=no|yes stop showing new errors if too many? [yes]\n" +" --exit-on-first-error=no|yes exit code on the first error found? [no]\n" " --error-exitcode=<number> exit code to return if errors found [0=disable]\n" " --error-markers=<begin>,<end> add lines with begin/end markers before/after\n" " each error output in plain text mode [none]\n" @@ -252,7 +253,7 @@ static void usage_NORETURN ( Bool debug_help ) " --core-redzone-size=<number> set minimum size of redzones added before/after\n" " heap blocks allocated for Valgrind internal use (in bytes) [4]\n" " --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n" -" --sym-offsets=yes|no show syms in form 'name+offset' ? [no]\n" +" --sym-offsets=yes|no show syms in form 'name+offset'? [no]\n" " --command-line-only=no|yes only use command line options [no]\n" "\n" " Vex options for all Valgrind tools:\n" @@ -601,6 +602,7 @@ void main_process_cmd_line_options( void ) else if VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle)) {} else if VG_STR_CLO (arg, "--soname-synonyms",VG_(clo_soname_synonyms)) {} else if VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit)) {} + else if VG_BOOL_CLO(arg, "--exit-on-first-error", VG_(clo_exit_on_first_error)) {} else if VG_INT_CLO (arg, "--error-exitcode", VG_(clo_error_exitcode)) {} else if VG_STR_CLO (arg, "--error-markers", tmp_str) { Int m; @@ -934,6 +936,11 @@ void main_process_cmd_line_options( void ) "Can't use --gen-suppressions= with %s\n" "because it doesn't generate errors.\n", VG_(details).name); } + if ((VG_(clo_exit_on_first_error)) && + (VG_(clo_error_exitcode)==0)) { + VG_(fmsg_bad_option)("--exit-on-first-error=yes", + "You must define a non nul exit error code, with --error-exitcode=...\n"); + } # if !defined(VGO_darwin) if (VG_(clo_resync_filter) != 0) { diff --git a/coregrind/m_options.c b/coregrind/m_options.c index 1bf2cc0..bae161b 100644 --- a/coregrind/m_options.c +++ b/coregrind/m_options.c @@ -52,6 +52,7 @@ VexRegisterUpdates VG_(clo_px_file_backed) = VexRegUpd_INVALID; Bool VG_(clo_error_limit) = True; Int VG_(clo_error_exitcode) = 0; HChar *VG_(clo_error_markers)[2] = {NULL, NULL}; +Bool VG_(clo_exit_on_first_error) = False; #if defined(VGPV_arm_linux_android) \ || defined(VGPV_x86_linux_android) \ diff --git a/coregrind/pub_core_options.h b/coregrind/pub_core_options.h index 88eeaf4..cc6bb83 100644 --- a/coregrind/pub_core_options.h +++ b/coregrind/pub_core_options.h @@ -44,6 +44,8 @@ extern const HChar *VG_(clo_toolname); /* Should we stop collecting errors if too many appear? default: YES */ extern Bool VG_(clo_error_limit); +/* Should we exit if an error appears? default: NO */ +extern Bool VG_(clo_exit_on_first_error); /* Alternative exit code to hand to parent if errors were found. default: 0 (no, return the application's exit code in the normal way. */ diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml index 4cd26a5..ff596b5 100644 --- a/docs/xml/manual-core.xml +++ b/docs/xml/manual-core.xml @@ -1180,6 +1180,19 @@ that can report errors, e.g. Memcheck, but not Cachegrind.</para> </listitem> </varlistentry> + <varlistentry id="opt.exit-on-first-error" xreflabel="--exit-on-first-error"> + <term> + <option><![CDATA[--exit-on-first-error=<yes|no> [default: no] ]]></option> + </term> + <listitem> + <para>If this option is enabled, Valgrind exits on the first error. + A nonzero exit value must be defined using + <computeroutput>--error-exitcode</computeroutput> option. + Useful if you are running regression tests or have some other + automated test machinery.</para> + </listitem> + </varlistentry> + <varlistentry id="opt.error-markers" xreflabel="--error-markers"> <term> <option><![CDATA[--error-markers=<begin>,<end> [default: none]]]></option> diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index b9ba67b..dbbeabf 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -80,6 +80,10 @@ EXTRA_DIST = \ atomic_incs.stdout.exp-32bit atomic_incs.stdout.exp-64bit \ badaddrvalue.stderr.exp \ badaddrvalue.stdout.exp badaddrvalue.vgtest \ + exit_on_first_error.stderr.exp \ + exit_on_first_error.vgtest \ + exit_on_first_error_with_xml.stderr.exp \ + exit_on_first_error_with_xml.vgtest \ badfree-2trace.stderr.exp badfree-2trace.vgtest \ badfree.stderr.exp badfree.vgtest \ badfree3.stderr.exp badfree3.vgtest \ diff --git a/memcheck/tests/exit_on_first_error.stderr.exp b/memcheck/tests/exit_on_first_error.stderr.exp new file mode 100644 index 0000000..f086181 --- /dev/null +++ b/memcheck/tests/exit_on_first_error.stderr.exp @@ -0,0 +1,9 @@ + +Invalid write of size 1 + ... + Address 0x........ is 1 bytes before a block of size 8 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + ... + + +Exit program on first error (--exit-on-first-error=yes) diff --git a/memcheck/tests/exit_on_first_error.vgtest b/memcheck/tests/exit_on_first_error.vgtest new file mode 100644 index 0000000..8ce05b1 --- /dev/null +++ b/memcheck/tests/exit_on_first_error.vgtest @@ -0,0 +1,2 @@ +prog: badaddrvalue +vgopts: --exit-on-first-error=yes --error-exitcode=3 diff --git a/memcheck/tests/exit_on_first_error_with_xml.stderr.exp b/memcheck/tests/exit_on_first_error_with_xml.stderr.exp new file mode 100644 index 0000000..3a02ca5 --- /dev/null +++ b/memcheck/tests/exit_on_first_error_with_xml.stderr.exp @@ -0,0 +1,67 @@ +<?xml version="1.0"?> + +<valgrindoutput> + +<protocolversion>4</protocolversion> +<protocoltool>memcheck</protocoltool> + +<preamble> + <line>...</line> + <line>...</line> + <line>...</line> + <line>...</line> +</preamble> + +<pid>...</pid> +<ppid>...</ppid> +<tool>memcheck</tool> + +<args> + <vargv>...</vargv> + <argv> + <exe>./badaddrvalue</exe> + </argv> +</args> + +<status> + <state>RUNNING</state> + <time>...</time> +</status> + +<error> + <unique>0x........</unique> + <tid>...</tid> + <kind>InvalidWrite</kind> + <what>Invalid write of size 1</what> + <stack> + <frame> + <ip>0x........</ip> + <obj>...</obj> + <fn>main</fn> + <dir>...</dir> + <file>badaddrvalue.c</file> + <line>...</line> + </frame> + </stack> + <auxwhat>Address 0x........ is 1 bytes before a block of size 8 alloc'd</auxwhat> + <stack> + <frame> + <ip>0x........</ip> + <obj>...</obj> + <fn>malloc</fn> + <dir>...</dir> + <file>vg_replace_malloc.c</file> + <line>...</line> + </frame> + <frame> + <ip>0x........</ip> + <obj>...</obj> + <fn>main</fn> + <dir>...</dir> + <file>badaddrvalue.c</file> + <line>...</line> + </frame> + </stack> +</error> + +</valgrindoutput> diff --git a/memcheck/tests/exit_on_first_error_with_xml.vgtest b/memcheck/tests/exit_on_first_error_with_xml.vgtest new file mode 100644 index 0000000..9247bf8 --- /dev/null +++ b/memcheck/tests/exit_on_first_error_with_xml.vgtest @@ -0,0 +1,4 @@ +prog: badaddrvalue +vgopts: --exit-on-first-error=yes --error-exitcode=3 --xml=yes --xml-fd=2 --log-file=/dev/null +stderr_filter: filter_xml + diff --git a/none/tests/cmdline1.stdout.exp b/none/tests/cmdline1.stdout.exp index e35b382..2485119 100644 --- a/none/tests/cmdline1.stdout.exp +++ b/none/tests/cmdline1.stdout.exp @@ -39,6 +39,7 @@ usage: valgrind [options] prog-and-args --demangle=no|yes automatically demangle C++ names? [yes] --num-callers=<number> show <number> callers in stack traces [12] --error-limit=no|yes stop showing new errors if too many? [yes] + --exit-on-first-error=no|yes exit code on the first error found? [no] --error-exitcode=<number> exit code to return if errors found [0=disable] --error-markers=<begin>,<end> add lines with begin/end markers before/after each error output in plain text mode [none] diff --git a/none/tests/cmdline2.stdout.exp b/none/tests/cmdline2.stdout.exp index 21bec9f..df8f85a 100644 --- a/none/tests/cmdline2.stdout.exp +++ b/none/tests/cmdline2.stdout.exp @@ -39,6 +39,7 @@ usage: valgrind [options] prog-and-args --demangle=no|yes automatically demangle C++ names? [yes] --num-callers=<number> show <number> callers in stack traces [12] --error-limit=no|yes stop showing new errors if too many? [yes] + --exit-on-first-error=no|yes exit code on the first error found? [no] --error-exitcode=<number> exit code to return if errors found [0=disable] --error-markers=<begin>,<end> add lines with begin/end markers before/after each error output in plain text mode [none] @@ -164,7 +165,7 @@ usage: valgrind [options] prog-and-args --core-redzone-size=<number> set minimum size of redzones added before/after heap blocks allocated for Valgrind internal use (in bytes) [4] --wait-for-gdb=yes|no pause on startup to wait for gdb attach - --sym-offsets=yes|no show syms in form 'name+offset' ? [no] + --sym-offsets=yes|no show syms in form 'name+offset'? [no] --command-line-only=no|yes only use command line options [no] Vex options for all Valgrind tools: |
|
From: Philippe W. <phi...@so...> - 2017-11-04 07:37:11
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=1eb5ea2afed92e38a15159cdef559785166a02a9 commit 1eb5ea2afed92e38a15159cdef559785166a02a9 Author: Philippe Waroquiers <phi...@sk...> Date: Sat Nov 4 08:32:03 2017 +0100 Small optimisation in helgrind address description Searching if an addr is in a malloc-ed client block is expensive (linear search) So, before scanning the list of malloc block, check that the address is in a client heap segment : this is a fast operation (it has a small cache, and for cache miss, does a dichotomic search) and avoids scanning a often big list (for big applications). Diff: --- helgrind/hg_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index 0f8c946..95945f3 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -4385,6 +4385,12 @@ Bool HG_(mm_find_containing_block)( /*OUT*/ExeContext** where, Int i; const Int n_fast_check_words = 16; + /* Before searching the list of allocated blocks in hg_mallocmeta_table, + first verify that data_addr is in a heap client segment. */ + const NSegment *s = VG_(am_find_nsegment) (data_addr); + if (s == NULL || !s->isCH) + return False; + /* First, do a few fast searches on the basis that data_addr might be exactly the start of a block or up to 15 words inside. This can happen commonly via the creq |
|
From: Petar J. <pe...@so...> - 2017-11-03 18:12:04
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=95038d380d60e7af2d04ffdd8432fdebed1990aa commit 95038d380d60e7af2d04ffdd8432fdebed1990aa Author: Petar Jovanovic <mip...@gm...> Date: Fri Nov 3 19:10:04 2017 +0100 mips: finetune tests that print FCSR Bits 18 (NAN2008) and 19 (ABS2008) in FCSR are preset by hardware and can differ between platforms. Hence, we should clear these bits before printing FCSR value in order to have the same output on different platforms. This fixes several failures (tests modified by this change) that occur on MIPS P5600 board. The P5600 is a core that implements MIPS32 Release 5 arch. Diff: --- none/tests/mips32/round.c | 38 +++++++++++++++---------- none/tests/mips32/round_fpu64.c | 30 ++++++++++++-------- none/tests/mips32/test_fcsr.c | 13 ++++++++- none/tests/mips64/round.c | 62 ++++++++++++++++++++++++----------------- none/tests/mips64/test_fcsr.c | 13 ++++++++- 5 files changed, 103 insertions(+), 53 deletions(-) diff --git a/none/tests/mips32/round.c b/none/tests/mips32/round.c index feba168..052508d 100644 --- a/none/tests/mips32/round.c +++ b/none/tests/mips32/round.c @@ -2,6 +2,16 @@ #include <stdio.h> +/* + * Bits 18 (NAN2008) and 19 (ABS2008) are preset by hardware and may differ + * between platforms. Hence a macro to clear them before printing FCSR + * values. + */ +#define FCSR_NAN2008 1 << 18 +#define FCSR_ABS2008 1 << 19 +#define FLAGS_RM_MASK 0xFFFFFFFF & ~(FCSR_ABS2008 | FCSR_NAN2008) +#define CLEAR_PRESETBITS_FCSR(fcsr) (fcsr & FLAGS_RM_MASK) + typedef enum { CEILWS=0, CEILWD, FLOORWS, FLOORWD, @@ -174,42 +184,42 @@ int directedRoundingMode(flt_dir_op_t op) { case CEILWS: UNOPfw("ceil.w.s"); printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CEILWD: UNOPdw("ceil.w.d"); printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case FLOORWS: UNOPfw("floor.w.s"); printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case FLOORWD: UNOPdw("floor.w.d"); printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case ROUNDWS: UNOPfw("round.w.s"); printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case ROUNDWD: UNOPdw("round.w.d"); printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case TRUNCWS: UNOPfw("trunc.w.s"); printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case TRUNCWD: UNOPdw("trunc.w.d"); printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; default: printf("error\n"); @@ -237,32 +247,32 @@ int FCSRRoundingMode(flt_round_op_t op1) case CVTDS: UNOPfd("cvt.d.s"); printf("%s %lf %lf\n", flt_round_op_names[op1], fd_d, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTDW: UNOPwd("cvt.d.w"); printf("%s %lf %d\n", flt_round_op_names[op1], fd_d, fs_w[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTSD: UNOPdf("cvt.s.d"); printf("%s %f %lf\n", flt_round_op_names[op1], fd_f, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTSW: UNOPwf("cvt.s.w"); printf("%s %f %d\n", flt_round_op_names[op1], fd_f, fs_w[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTWS: UNOPfw("cvt.w.s"); printf("%s %d %f\n", flt_round_op_names[op1], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTWD: UNOPdw("cvt.w.d"); printf("%s %d %lf\n", flt_round_op_names[op1], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; default: printf("error\n"); diff --git a/none/tests/mips32/round_fpu64.c b/none/tests/mips32/round_fpu64.c index e35c8b5..970dd05 100644 --- a/none/tests/mips32/round_fpu64.c +++ b/none/tests/mips32/round_fpu64.c @@ -8,7 +8,15 @@ #define MAX_ARR 24 #define PERROR \ printf("This test is testing mips32r2 instructions in fpu64 mode.\n"); -#define FLAGS_RM_MASK 0xFFFFFFFF +/* + * Bits 18 (NAN2008) and 19 (ABS2008) are preset by hardware and may differ + * between platforms. Hence a macro to clear them before printing FCSR + * values. + */ +#define FCSR_NAN2008 1 << 18 +#define FCSR_ABS2008 1 << 19 +#define FLAGS_RM_MASK 0xFFFFFFFF & ~(FCSR_ABS2008 | FCSR_NAN2008) +#define CLEAR_PRESETBITS_FCSR(fcsr) (fcsr & FLAGS_RM_MASK) typedef enum { CVTLS, CVTLD, ROUNDLS, ROUNDLD, @@ -122,61 +130,61 @@ int FCSRRoundingMode(flt_round_op_t op) UNOPsl("cvt.l.s"); printf("%s %lld %f\n", flt_round_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTLD: UNOPdl("cvt.l.d"); printf("%s %lld %lf\n", flt_round_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case ROUNDLS: UNOPsl("round.l.s"); printf("%s %lld %f\n", flt_round_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case ROUNDLD: UNOPdl("round.l.d"); printf("%s %lld %lf\n", flt_round_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case TRUNCLS: UNOPsl("trunc.l.s"); printf("%s %lld %f\n", flt_round_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case TRUNCLD: UNOPdl("trunc.l.d"); printf("%s %lld %lf\n", flt_round_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case FLOORLS: UNOPsl("floor.l.s"); printf("%s %lld %f\n", flt_round_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case FLOORLD: UNOPdl("floor.l.d"); printf("%s %lld %lf\n", flt_round_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CEILLS: UNOPsl("ceil.l.s"); printf("%s %lld %f\n", flt_round_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CEILLD: UNOPdl("ceil.l.d"); printf("%s %lld %lf\n", flt_round_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; default: printf("error\n"); diff --git a/none/tests/mips32/test_fcsr.c b/none/tests/mips32/test_fcsr.c index 6bb03a0..c422482 100644 --- a/none/tests/mips32/test_fcsr.c +++ b/none/tests/mips32/test_fcsr.c @@ -2,6 +2,16 @@ #include <stdio.h> +/* + * Bits 18 (NAN2008) and 19 (ABS2008) are preset by hardware and may differ + * between platforms. Hence a macro to clear them before printing FCSR + * values. + */ +#define FCSR_NAN2008 1 << 18 +#define FCSR_ABS2008 1 << 19 +#define FLAGS_RM_MASK 0xFFFFFFFF & ~(FCSR_ABS2008 | FCSR_NAN2008) +#define CLEAR_PRESETBITS_FCSR(fcsr) (fcsr & FLAGS_RM_MASK) + int main () { int out [] = {0, 0}; @@ -22,7 +32,8 @@ int main () : "r" (in), "r" (out) : "a1", "a2", "t0", "$f0", "$f1" ); - printf("FCSR::1: 0x%x, 2: 0x%x\n", out[0], out[1]); + printf("FCSR::1: 0x%x, 2: 0x%x\n", CLEAR_PRESETBITS_FCSR(out[0]), + CLEAR_PRESETBITS_FCSR(out[1])); return 0; } #else diff --git a/none/tests/mips64/round.c b/none/tests/mips64/round.c index 4634057..1894de1 100644 --- a/none/tests/mips64/round.c +++ b/none/tests/mips64/round.c @@ -2,6 +2,16 @@ #include "rounding_mode.h" #include "macro_fpu.h" +/* + * Bits 18 (NAN2008) and 19 (ABS2008) are preset by hardware and may differ + * between platforms. Hence a macro to clear them before printing FCSR + * values. + */ +#define FCSR_NAN2008 1 << 18 +#define FCSR_ABS2008 1 << 19 +#define FLAGS_RM_MASK 0xFFFFFFFF & ~(FCSR_ABS2008 | FCSR_NAN2008) +#define CLEAR_PRESETBITS_FCSR(fcsr) (fcsr & FLAGS_RM_MASK) + #if defined(__mips_hard_float) int directedRoundingMode(flt_dir_op_t op) { int fd_w = 0; @@ -14,82 +24,82 @@ int directedRoundingMode(flt_dir_op_t op) { case CEILWS: UNOPfw("ceil.w.s"); printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CEILWD: UNOPdw("ceil.w.d"); printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case FLOORWS: UNOPfw("floor.w.s"); printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case FLOORWD: UNOPdw("floor.w.d"); printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case ROUNDWS: UNOPfw("round.w.s"); printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case ROUNDWD: UNOPdw("round.w.d"); printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case TRUNCWS: UNOPfw("trunc.w.s"); printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case TRUNCWD: UNOPdw("trunc.w.d"); printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CEILLS: UNOPsl("ceil.l.s"); printf("%s %lld %f\n", flt_dir_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CEILLD: UNOPdl("ceil.l.d"); printf("%s %lld %lf\n", flt_dir_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case FLOORLS: UNOPsl("floor.l.s"); printf("%s %lld %f\n", flt_dir_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case FLOORLD: UNOPdl("floor.l.d"); printf("%s %lld %lf\n", flt_dir_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case ROUNDLS: UNOPsl("round.l.s"); printf("%s %lld %f\n", flt_dir_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case ROUNDLD: UNOPdl("round.l.d"); printf("%s %lld %lf\n", flt_dir_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case TRUNCLS: UNOPsl("trunc.l.s"); printf("%s %lld %f\n", flt_dir_op_names[op], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case TRUNCLD: UNOPdl("trunc.l.d"); printf("%s %lld %lf\n", flt_dir_op_names[op], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; default: printf("error\n"); @@ -118,52 +128,52 @@ int FCSRRoundingMode(flt_round_op_t op1) case CVTDS: UNOPfd("cvt.d.s"); printf("%s %lf %lf\n", flt_round_op_names[op1], fd_d, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTDW: UNOPwd("cvt.d.w"); printf("%s %lf %d\n", flt_round_op_names[op1], fd_d, fs_w[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTSD: UNOPdf("cvt.s.d"); printf("%s %f %lf\n", flt_round_op_names[op1], fd_f, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTSW: UNOPwf("cvt.s.w"); printf("%s %f %d\n", flt_round_op_names[op1], fd_f, fs_w[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTWS: UNOPfw("cvt.w.s"); printf("%s %d %f\n", flt_round_op_names[op1], fd_w, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTWD: UNOPdw("cvt.w.d"); printf("%s %d %lf\n", flt_round_op_names[op1], fd_w, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTDL: UNOPld("cvt.d.l"); printf("%s %lf %ld\n", flt_round_op_names[op1], fd_d, fs_l[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTLS: UNOPsl("cvt.l.s"); printf("%s %lld %f\n", flt_round_op_names[op1], fd_l, fs_f[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTLD: UNOPdl("cvt.l.d"); printf("%s %lld %lf\n", flt_round_op_names[op1], fd_l, fs_d[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; case CVTSL: UNOPls("cvt.s.l"); printf("%s %f %ld\n", flt_round_op_names[op1], fd_f, fs_l[i]); - printf("fcsr: 0x%x\n", fcsr); + printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr)); break; default: printf("error\n"); diff --git a/none/tests/mips64/test_fcsr.c b/none/tests/mips64/test_fcsr.c index 742bb83..07e5e8c 100644 --- a/none/tests/mips64/test_fcsr.c +++ b/none/tests/mips64/test_fcsr.c @@ -1,5 +1,15 @@ #include <stdio.h> +/* + * Bits 18 (NAN2008) and 19 (ABS2008) are preset by hardware and may differ + * between platforms. Hence a macro to clear them before printing FCSR + * values. + */ +#define FCSR_NAN2008 1 << 18 +#define FCSR_ABS2008 1 << 19 +#define FLAGS_RM_MASK 0xFFFFFFFF & ~(FCSR_ABS2008 | FCSR_NAN2008) +#define CLEAR_PRESETBITS_FCSR(fcsr) (fcsr & FLAGS_RM_MASK) + int main () { #if defined(__mips_hard_float) @@ -22,7 +32,8 @@ int main () : "r" (out) : "a1", "a2", "t0", "$f0" ); - printf("FCSR::1: 0x%lx, 2: 0x%lx\n", out[0], out[1]); + printf("FCSR::1: 0x%lx, 2: 0x%lx\n", CLEAR_PRESETBITS_FCSR(out[0]), + CLEAR_PRESETBITS_FCSR(out[1])); #endif return 0; } |
|
From: Philippe W. <phi...@so...> - 2017-11-02 20:51:22
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=b8fa6c086f8b2a6a6addcbcd0a8472c09730e7e7 commit b8fa6c086f8b2a6a6addcbcd0a8472c09730e7e7 Author: Philippe Waroquiers <phi...@sk...> Date: Thu Nov 2 21:50:48 2017 +0100 Improve the NEWS entry for --delta-stacktrace flag. Diff: --- NEWS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index dc6cbad..d6acccd 100644 --- a/NEWS +++ b/NEWS @@ -23,9 +23,9 @@ support for X86/macOS 10.13, AMD64/macOS 10.13. * Helgrind: - - Addition of a flag --delta-stacktrace=no|yes [yes on linux amd64/x86], specifying - how full history stack traces are computed. Using yes can speed up Helgrind by - 25%. + - Addition of a flag --delta-stacktrace=no|yes [yes on linux amd64/x86], + specifying how full history stack traces are computed. Using yes can speed + up Helgrind by 25% when using --history-level=full. * ==================== OTHER CHANGES ==================== |
|
From: Philippe W. <phi...@so...> - 2017-11-02 20:42:21
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=619fb35df7b3fba514da7298c8b428d1ec490f93 commit 619fb35df7b3fba514da7298c8b428d1ec490f93 Author: Philippe Waroquiers <phi...@sk...> Date: Thu Nov 2 21:33:35 2017 +0100 Fix 376257 - helgrind history full speed up using a cached stack This patch implements the flag --delta-stacktrace=yes/no. Yes indicates to calculate the full history stack traces by changing just the last frame if no call/return instruction was executed. This can speed up helgrind by up to 25%. This flags is currently set to yes only on linux x86 and amd64, as some platform dependent validation of the used heuristics is needed before setting the default to yes on a platform. See function check_cached_rcec_ok in libhb_core.c for more details about how to validate/check the behaviour on a new platform. Diff: --- NEWS | 6 + coregrind/m_debuginfo/debuginfo.c | 6 + coregrind/m_machine.c | 9 + coregrind/m_stacktrace.c | 35 +++- coregrind/pub_core_libcassert.h | 14 -- helgrind/docs/hg-manual.xml | 52 ++++++ helgrind/hg_basics.c | 7 + helgrind/hg_basics.h | 10 + helgrind/hg_lock_n_thread.h | 5 + helgrind/hg_main.c | 191 ++++++++++++++++--- helgrind/libhb_core.c | 383 ++++++++++++++++++++++++++++++++++---- include/pub_tool_debuginfo.h | 3 + include/pub_tool_libcassert.h | 14 ++ include/pub_tool_machine.h | 3 + include/pub_tool_stacktrace.h | 11 ++ 15 files changed, 664 insertions(+), 85 deletions(-) diff --git a/NEWS b/NEWS index c9961b4..dc6cbad 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,11 @@ support for X86/macOS 10.13, AMD64/macOS 10.13. * ==================== TOOL CHANGES ==================== +* Helgrind: + + - Addition of a flag --delta-stacktrace=no|yes [yes on linux amd64/x86], specifying + how full history stack traces are computed. Using yes can speed up Helgrind by + 25%. * ==================== OTHER CHANGES ==================== @@ -39,6 +44,7 @@ To see details of a given bug, visit where XXXXXX is the bug number as listed below. 255603 exp-sgcheck Assertion '!already_present' failed +376257 helgrind history full speed up using a cached stack 379373 Fix syscall param msg->desc.port.name points to uninitialised byte(s) on macOS 10.12 379748 Fix missing pselect syscall (OS X 10.11) diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 3817ecf..e5ce4be 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -2729,6 +2729,12 @@ static inline CFSI_m_CacheEnt* cfsi_m_cache__find ( Addr ip ) } } +Bool VG_(has_CF_info)(Addr a) +{ + return cfsi_m_cache__find (a) != NULL; +} + + inline static Addr compute_cfa ( const D3UnwindRegs* uregs, diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 395989b..e9fefac 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -46,6 +46,8 @@ #define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR) #define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR) +#define STACK_PTR_S1(regs) ((regs).vex_shadow1.VG_STACK_PTR) + Addr VG_(get_IP) ( ThreadId tid ) { return INSTR_PTR( VG_(threads)[tid].arch ); } @@ -56,6 +58,13 @@ Addr VG_(get_FP) ( ThreadId tid ) { return FRAME_PTR( VG_(threads)[tid].arch ); } +Addr VG_(get_SP_s1) ( ThreadId tid ) { + return STACK_PTR_S1( VG_(threads)[tid].arch ); +} +void VG_(set_SP_s1) ( ThreadId tid, Addr sp ) { + STACK_PTR_S1( VG_(threads)[tid].arch ) = sp; +} + void VG_(set_IP) ( ThreadId tid, Addr ip ) { INSTR_PTR( VG_(threads)[tid].arch ) = ip; } diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index 41064af..787368b 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -1478,11 +1478,14 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, /*--- Exported functions. ---*/ /*------------------------------------------------------------*/ -UInt VG_(get_StackTrace) ( ThreadId tid, - /*OUT*/StackTrace ips, UInt max_n_ips, - /*OUT*/StackTrace sps, - /*OUT*/StackTrace fps, - Word first_ip_delta ) +UInt VG_(get_StackTrace_with_deltas)( + ThreadId tid, + /*OUT*/StackTrace ips, UInt n_ips, + /*OUT*/StackTrace sps, + /*OUT*/StackTrace fps, + Word first_ip_delta, + Word first_sp_delta + ) { /* Get the register values with which to start the unwind. */ UnwindStartRegs startRegs; @@ -1524,8 +1527,9 @@ UInt VG_(get_StackTrace) ( ThreadId tid, VG_(stack_limits)( (Addr)startRegs.r_sp, &stack_lowest_byte, &stack_highest_byte ); - /* Take into account the first_ip_delta. */ - startRegs.r_pc += (Long)(Word)first_ip_delta; + /* Take into account the first_ip_delta and first_sp_delta. */ + startRegs.r_pc += (Long)first_ip_delta; + startRegs.r_sp += (Long)first_sp_delta; if (0) VG_(printf)("tid %u: stack_highest=0x%08lx ip=0x%010llx " @@ -1533,12 +1537,27 @@ UInt VG_(get_StackTrace) ( ThreadId tid, tid, stack_highest_byte, startRegs.r_pc, startRegs.r_sp); - return VG_(get_StackTrace_wrk)(tid, ips, max_n_ips, + return VG_(get_StackTrace_wrk)(tid, ips, n_ips, sps, fps, &startRegs, stack_highest_byte); } +UInt VG_(get_StackTrace) ( ThreadId tid, + /*OUT*/StackTrace ips, UInt max_n_ips, + /*OUT*/StackTrace sps, + /*OUT*/StackTrace fps, + Word first_ip_delta ) +{ + return VG_(get_StackTrace_with_deltas) (tid, + ips, max_n_ips, + sps, + fps, + first_ip_delta, + 0 /* first_sp_delta */ + ); +} + static void printIpDesc(UInt n, Addr ip, void* uu_opaque) { InlIPCursor *iipc = VG_(new_IIPC)(ip); diff --git a/coregrind/pub_core_libcassert.h b/coregrind/pub_core_libcassert.h index 1ea5192..2737f9c 100644 --- a/coregrind/pub_core_libcassert.h +++ b/coregrind/pub_core_libcassert.h @@ -79,20 +79,6 @@ extern void VG_(unimplemented) ( const HChar* format, ... ) __attribute__((__noreturn__)) PRINTF_CHECK(1, 2); -/* Show the state of various threads related information, such - as the guest stacktrace for each thread. - Mostly for debugging V. - The following activates optional output: - host_stacktrace : shows the host stacktrace. - stack_usage True means: - shows how much of the valgrind stack was used. - shows the client stack range - exited_thread_slots : show information for thread slots that were used - but the thread has now exited. */ -extern void VG_(show_sched_status) ( Bool host_stacktrace, - Bool stack_usage, - Bool exited_threads); - #endif // __PUB_CORE_LIBCASSERT_H /*--------------------------------------------------------------------*/ diff --git a/helgrind/docs/hg-manual.xml b/helgrind/docs/hg-manual.xml index c47126d..8a1d916 100644 --- a/helgrind/docs/hg-manual.xml +++ b/helgrind/docs/hg-manual.xml @@ -1149,6 +1149,58 @@ unlock(mx) unlock(mx) <option>--history-level=none</option>.</para> </listitem> </varlistentry> + + <varlistentry id="opt.delta-stacktrace" + xreflabel="--delta-stacktrace"> + <term> + <option><![CDATA[--delta-stacktrace=no|yes + [default: yes on linux amd64/x86] ]]></option> + </term> + <listitem> + <para>This flag only has any effect + at <option>--history-level=full</option>.</para> + <para><option>--delta-stacktrace</option> configures the way Helgrind + captures the stacktraces for the + option <option>--history-level=full</option>. Such a stacktrace is + typically needed each time a new piece of memory is read or written in a + basic block of instructions. </para> + <para><option>--delta-stacktrace=no</option> causes + Helgrind to compute a full history stacktrace from the unwind info + each time a stacktrace is needed.</para> + <para><option>--delta-stacktrace=yes</option> indicates to Helgrind to + derive a new stacktrace from the previous stacktrace, as long as there + was no call instruction, no return instruction, or any other instruction + changing the call stack since the previous stacktrace was captured. If + no such instruction was executed, the new stacktrace can be derived from + the previous stacktrace by just changing the top frame to the current + program counter. This option can speed up Helgrind by 25% when + using <option>--history-level=full</option>. </para> + <para>The following aspects have to be considered when + using <option>--delta-stacktrace=yes</option> : + <itemizedlist> + <listitem>In some cases (for example in a function prologue), the + valgrind unwinder might not properly unwind the stack, due to some + limitations and/or due to wrong unwind info. When using + --delta-stacktrace=yes, the wrong stack trace captured in the + function prologue will be kept till the next call or return. + </listitem> + <listitem>On the other hand, --delta-stacktrace=yes sometimes helps to + obtain a correct stacktrace, for example when the unwind info allows + a correct stacktrace to be done in the beginning of the sequence, + but not later on in the instruction sequence.</listitem> + <listitem>Determining which instructions are changing the callstack is + partially based on platform dependent heuristics, which have to be + tuned/validated specifically for the platform. Also, unwinding in a + function prologue must be good enough to allow using + --delta-stacktrace=yes. Currently, the option --delta-stacktrace=yes + has been reasonably validated only on linux x86 32 bits and linux + amd64 64 bits. For more details about how to validate + --delta-stacktrace=yes, see debug option --hg-sanity-flags and the + function check_cached_rcec_ok in libhb_core.c.</listitem> + </itemizedlist> + </para> + </listitem> + </varlistentry> <varlistentry id="opt.conflict-cache-size" xreflabel="--conflict-cache-size"> diff --git a/helgrind/hg_basics.c b/helgrind/hg_basics.c index 7c6a941..a397a5c 100644 --- a/helgrind/hg_basics.c +++ b/helgrind/hg_basics.c @@ -75,6 +75,13 @@ Bool HG_(clo_cmp_race_err_addrs) = False; UWord HG_(clo_history_level) = 2; +#if (defined(VGA_x86) || defined(VGA_amd64)) && defined(VGO_linux) +// Set to true on setup where it was (reasonably) validated. +Bool HG_(clo_delta_stacktrace) = True; +#else +Bool HG_(clo_delta_stacktrace) = False; +#endif + UWord HG_(clo_conflict_cache_size) = 2000000; UWord HG_(clo_sanity_flags) = 0; diff --git a/helgrind/hg_basics.h b/helgrind/hg_basics.h index b50d48e..8b58bfd 100644 --- a/helgrind/hg_basics.h +++ b/helgrind/hg_basics.h @@ -93,6 +93,16 @@ extern Bool HG_(clo_cmp_race_err_addrs); very useful). */ extern UWord HG_(clo_history_level); +/* For full history level, determines how the stack trace is computed. + no : a stacktrace is always computed from scratch, typically + using the unwind information. + yes : a stacktrace might be derived from a previous captured stacktrace, + by applying a delta to the inner frame. This can significantly + speed up --history-level=full. Typically, a delta can be applied + if there was no 'flow call control' instruction (call, return, ...) + executed since the previous captured stacktrace. */ +extern Bool HG_(clo_delta_stacktrace); + /* When doing "full" history collection, this determines the size of the conflicting-access cache, measured in terms of maximum possible number of elements in the previous-access map. Must be between 10k diff --git a/helgrind/hg_lock_n_thread.h b/helgrind/hg_lock_n_thread.h index 30ee02b..f74babf 100644 --- a/helgrind/hg_lock_n_thread.h +++ b/helgrind/hg_lock_n_thread.h @@ -92,6 +92,11 @@ typedef /* Place where parent was when this thread was created. */ ExeContext* created_at; Bool announced; + /* != 0 if SP fixup needed for unwind : it contains a delta SP value + to use when evh__mem_help_c(read|write)_X is called in the + 'middle of an instruction' (e.g. in a push) + after the SP was changed, but before the push has been completed. */ + Word first_sp_delta; /* Index for generating references in error messages. */ Int errmsg_index; diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index b956c38..0f8c946 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -183,6 +183,7 @@ static Thread* mk_Thread ( Thr* hbthr ) { thread->coretid = VG_INVALID_THREADID; thread->created_at = NULL; thread->announced = False; + thread->first_sp_delta = 0; thread->errmsg_index = indx++; thread->admin = admin_threads; thread->synchr_nesting = 0; @@ -1975,6 +1976,19 @@ void evh__mem_help_cwrite_4(Addr a) { LIBHB_CWRITE_4(hbthr, a); } +/* Same as evh__mem_help_cwrite_4 but unwind will use a first_sp_delta of + one word. */ +static VG_REGPARM(1) +void evh__mem_help_cwrite_4_fixupSP(Addr a) { + Thread* thr = get_current_Thread_in_C_C(); + Thr* hbthr = thr->hbthr; + + thr->first_sp_delta = sizeof(Word); + if (LIKELY(thr->synchr_nesting == 0)) + LIBHB_CWRITE_4(hbthr, a); + thr->first_sp_delta = 0; +} + static VG_REGPARM(1) void evh__mem_help_cwrite_8(Addr a) { Thread* thr = get_current_Thread_in_C_C(); @@ -1983,6 +1997,19 @@ void evh__mem_help_cwrite_8(Addr a) { LIBHB_CWRITE_8(hbthr, a); } +/* Same as evh__mem_help_cwrite_8 but unwind will use a first_sp_delta of + one word. */ +static VG_REGPARM(1) +void evh__mem_help_cwrite_8_fixupSP(Addr a) { + Thread* thr = get_current_Thread_in_C_C(); + Thr* hbthr = thr->hbthr; + + thr->first_sp_delta = sizeof(Word); + if (LIKELY(thr->synchr_nesting == 0)) + LIBHB_CWRITE_8(hbthr, a); + thr->first_sp_delta = 0; +} + static VG_REGPARM(2) void evh__mem_help_cwrite_N(Addr a, SizeT size) { Thread* thr = get_current_Thread_in_C_C(); @@ -4428,8 +4455,13 @@ static void instrument_mem_access ( IRSB* sbOut, IRExpr* addr, Int szB, Bool isStore, + Bool fixupSP_needed, Int hWordTy_szB, Int goff_sp, + Int goff_sp_s1, + /* goff_sp_s1 is the offset in guest + state where the cachedstack validity + is stored. */ IRExpr* guard ) /* NULL => True */ { IRType tyAddr = Ity_INVALID; @@ -4465,13 +4497,27 @@ static void instrument_mem_access ( IRSB* sbOut, argv = mkIRExprVec_1( addr ); break; case 4: - hName = "evh__mem_help_cwrite_4"; - hAddr = &evh__mem_help_cwrite_4; + if (fixupSP_needed) { + /* Unwind has to be done with a SP fixed up with one word. + See Ist_Put heuristic in hg_instrument. */ + hName = "evh__mem_help_cwrite_4_fixupSP"; + hAddr = &evh__mem_help_cwrite_4_fixupSP; + } else { + hName = "evh__mem_help_cwrite_4"; + hAddr = &evh__mem_help_cwrite_4; + } argv = mkIRExprVec_1( addr ); break; case 8: - hName = "evh__mem_help_cwrite_8"; - hAddr = &evh__mem_help_cwrite_8; + if (fixupSP_needed) { + /* Unwind has to be done with a SP fixed up with one word. + See Ist_Put heuristic in hg_instrument. */ + hName = "evh__mem_help_cwrite_8_fixupSP"; + hAddr = &evh__mem_help_cwrite_8_fixupSP; + } else { + hName = "evh__mem_help_cwrite_8"; + hAddr = &evh__mem_help_cwrite_8; + } argv = mkIRExprVec_1( addr ); break; default: @@ -4522,6 +4568,17 @@ static void instrument_mem_access ( IRSB* sbOut, hName, VG_(fnptr_to_fnentry)( hAddr ), argv ); + if (HG_(clo_delta_stacktrace)) { + /* memory access helper might read the shadow1 SP offset, that + indicates if the cached stacktrace is valid. */ + di->fxState[0].fx = Ifx_Read; + di->fxState[0].offset = goff_sp_s1; + di->fxState[0].size = hWordTy_szB; + di->fxState[0].nRepeats = 0; + di->fxState[0].repeatLen = 0; + di->nFxState = 1; + } + if (! HG_(clo_check_stack_refs)) { /* We're ignoring memory references which are (obviously) to the stack. In fact just skip stack refs that are within 4 pages @@ -4609,6 +4666,19 @@ static Bool is_in_dynamic_linker_shared_object( Addr ga ) } static +void addInvalidateCachedStack (IRSB* bbOut, + Int goff_sp_s1, + Int hWordTy_szB) +{ + /* Invalidate cached stack: Write 0 in the shadow1 offset 0 */ + addStmtToIRSB( bbOut, + IRStmt_Put(goff_sp_s1, + hWordTy_szB == 4 ? + mkU32(0) : mkU64(0))); + /// ???? anything more efficient than assign a Word??? +} + +static IRSB* hg_instrument ( VgCallbackClosure* closure, IRSB* bbIn, const VexGuestLayout* layout, @@ -4623,7 +4693,15 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, Bool inLDSO = False; Addr inLDSOmask4K = 1; /* mismatches on first check */ - const Int goff_sp = layout->offset_SP; + // Set to True when SP must be fixed up when taking a stack trace for the + // mem accesses in the rest of the instruction + Bool fixupSP_needed = False; + + const Int goff_SP = layout->offset_SP; + /* SP in shadow1 indicates if cached stack is valid. + We have to invalidate the cached stack e.g. when seeing call or ret. */ + const Int goff_SP_s1 = layout->total_sizeB + layout->offset_SP; + const Int hWordTy_szB = sizeofIRType(hWordTy); if (gWordTy != hWordTy) { /* We don't currently support this case. */ @@ -4661,17 +4739,45 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, tl_assert(st); tl_assert(isFlatIRStmt(st)); switch (st->tag) { + case Ist_Exit: + /* No memory reference, but if we do anything else than + Ijk_Boring, indicate to helgrind that the previously + recorded stack is invalid. + For Ijk_Boring, also invalidate the stack if the exit + instruction has no CF info. This heuristic avoids cached + stack trace mismatch in some cases such as longjmp + implementation. Similar logic below for the bb exit. */ + if (HG_(clo_delta_stacktrace) + && (st->Ist.Exit.jk != Ijk_Boring || ! VG_(has_CF_info)(cia))) + addInvalidateCachedStack(bbOut, goff_SP_s1, hWordTy_szB); + break; case Ist_NoOp: case Ist_AbiHint: + /* None of these can contain any memory references. */ + break; case Ist_Put: + /* This cannot contain any memory references. */ + /* If we see a put to SP, from now on in this instruction, + the SP needed to unwind has to be fixed up by one word. + This very simple heuristic ensures correct unwinding in the + typical case of a push instruction. If we need to cover more + cases, then we need to better track how the SP is modified by + the instruction (and calculate a precise sp delta), rather than + assuming that the SP is decremented by a Word size. */ + if (HG_(clo_delta_stacktrace) && st->Ist.Put.offset == goff_SP) { + fixupSP_needed = True; + } + break; case Ist_PutI: - case Ist_Exit: - /* None of these can contain any memory references. */ + /* This cannot contain any memory references. */ break; case Ist_IMark: + fixupSP_needed = False; + /* no mem refs, but note the insn address. */ cia = st->Ist.IMark.addr; + /* Don't instrument the dynamic linker. It generates a lot of races which we just expensively suppress, so it's pointless. @@ -4717,8 +4823,8 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, cas->addr, (isDCAS ? 2 : 1) * sizeofIRType(typeOfIRExpr(bbIn->tyenv, cas->dataLo)), - False/*!isStore*/, - sizeofIRType(hWordTy), goff_sp, + False/*!isStore*/, fixupSP_needed, + hWordTy_szB, goff_SP, goff_SP_s1, NULL/*no-guard*/ ); } @@ -4738,8 +4844,8 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, bbOut, st->Ist.LLSC.addr, sizeofIRType(dataTy), - False/*!isStore*/, - sizeofIRType(hWordTy), goff_sp, + False/*!isStore*/, fixupSP_needed, + hWordTy_szB, goff_SP, goff_SP_s1, NULL/*no-guard*/ ); } @@ -4756,8 +4862,8 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, bbOut, st->Ist.Store.addr, sizeofIRType(typeOfIRExpr(bbIn->tyenv, st->Ist.Store.data)), - True/*isStore*/, - sizeofIRType(hWordTy), goff_sp, + True/*isStore*/, fixupSP_needed, + hWordTy_szB, goff_SP, goff_SP_s1, NULL/*no-guard*/ ); } @@ -4770,9 +4876,9 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, IRType type = typeOfIRExpr(bbIn->tyenv, data); tl_assert(type != Ity_INVALID); instrument_mem_access( bbOut, addr, sizeofIRType(type), - True/*isStore*/, - sizeofIRType(hWordTy), - goff_sp, sg->guard ); + True/*isStore*/, fixupSP_needed, + hWordTy_szB, + goff_SP, goff_SP_s1, sg->guard ); break; } @@ -4784,9 +4890,9 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, typeOfIRLoadGOp(lg->cvt, &typeWide, &type); tl_assert(type != Ity_INVALID); instrument_mem_access( bbOut, addr, sizeofIRType(type), - False/*!isStore*/, - sizeofIRType(hWordTy), - goff_sp, lg->guard ); + False/*!isStore*/, fixupSP_needed, + hWordTy_szB, + goff_SP, goff_SP_s1, lg->guard ); break; } @@ -4798,8 +4904,8 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, bbOut, data->Iex.Load.addr, sizeofIRType(data->Iex.Load.ty), - False/*!isStore*/, - sizeofIRType(hWordTy), goff_sp, + False/*!isStore*/, fixupSP_needed, + hWordTy_szB, goff_SP, goff_SP_s1, NULL/*no-guard*/ ); } @@ -4819,16 +4925,20 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) { if (!inLDSO) { instrument_mem_access( - bbOut, d->mAddr, dataSize, False/*!isStore*/, - sizeofIRType(hWordTy), goff_sp, NULL/*no-guard*/ + bbOut, d->mAddr, dataSize, + False/*!isStore*/, fixupSP_needed, + hWordTy_szB, goff_SP, goff_SP_s1, + NULL/*no-guard*/ ); } } if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) { if (!inLDSO) { instrument_mem_access( - bbOut, d->mAddr, dataSize, True/*isStore*/, - sizeofIRType(hWordTy), goff_sp, NULL/*no-guard*/ + bbOut, d->mAddr, dataSize, + True/*isStore*/, fixupSP_needed, + hWordTy_szB, goff_SP, goff_SP_s1, + NULL/*no-guard*/ ); } } @@ -4849,6 +4959,11 @@ IRSB* hg_instrument ( VgCallbackClosure* closure, addStmtToIRSB( bbOut, st ); } /* iterate over bbIn->stmts */ + // See above the case Ist_Exit: + if (HG_(clo_delta_stacktrace) + && (bbOut->jumpkind != Ijk_Boring || ! VG_(has_CF_info)(cia))) + addInvalidateCachedStack(bbOut, goff_SP_s1, hWordTy_szB); + return bbOut; } @@ -5588,6 +5703,9 @@ static Bool hg_process_cmd_line_option ( const HChar* arg ) else if VG_XACT_CLO(arg, "--history-level=full", HG_(clo_history_level), 2); + else if VG_BOOL_CLO(arg, "--delta-stacktrace", + HG_(clo_delta_stacktrace)) {} + else if VG_BINT_CLO(arg, "--conflict-cache-size", HG_(clo_conflict_cache_size), 10*1000, 150*1000*1000) {} @@ -5642,6 +5760,10 @@ static void hg_print_usage ( void ) " full: show both stack traces for a data race (can be very slow)\n" " approx: full trace for one thread, approx for the other (faster)\n" " none: only show trace for one thread in a race (fastest)\n" +" --delta-stacktrace=no|yes [yes on linux amd64/x86]\n" +" no : always compute a full history stacktrace from unwind info\n" +" yes : derive a stacktrace from the previous stacktrace\n" +" if there was no call/return or similar instruction\n" " --conflict-cache-size=N size of 'full' history cache [2000000]\n" " --check-stack-refs=no|yes race-check reads and writes on the\n" " main stack and thread stacks? [yes]\n" @@ -5660,7 +5782,7 @@ static void hg_print_debug_usage ( void ) VG_(printf)(" --hg-sanity-flags values:\n"); VG_(printf)(" 010000 after changes to " "lock-order-acquisition-graph\n"); - VG_(printf)(" 001000 at memory accesses (NB: not currently used)\n"); + VG_(printf)(" 001000 at memory accesses\n"); VG_(printf)(" 000100 at mem permission setting for " "ranges >= %d bytes\n", SCE_BIGRANGE_T); VG_(printf)(" 000010 at lock/unlock events\n"); @@ -5775,8 +5897,10 @@ void for_libhb__get_stacktrace ( Thr* hbt, Addr* frames, UWord nRequest ) thr = libhb_get_Thr_hgthread( hbt ); tl_assert(thr); tid = map_threads_maybe_reverse_lookup_SLOW(thr); - nActual = (UWord)VG_(get_StackTrace)( tid, frames, (UInt)nRequest, - NULL, NULL, 0 ); + nActual = (UWord)VG_(get_StackTrace_with_deltas) + ( tid, frames, (UInt)nRequest, + NULL, NULL, 0, + thr->first_sp_delta); tl_assert(nActual <= nRequest); for (; nActual < nRequest; nActual++) frames[nActual] = 0; @@ -5802,6 +5926,17 @@ static void hg_post_clo_init ( void ) { Thr* hbthr_root; + if (HG_(clo_delta_stacktrace) + && VG_(clo_vex_control).guest_chase_thresh != 0) { + if (VG_(clo_verbosity) >= 2) + VG_(message)(Vg_UserMsg, + "helgrind --delta-stacktrace=yes only works with " + "--vex-guest-chase-thresh=0\n" + "=> (re-setting it to 0\n"); + VG_(clo_vex_control).guest_chase_thresh = 0; + } + + ///////////////////////////////////////////// hbthr_root = libhb_init( for_libhb__get_stacktrace, for_libhb__get_EC ); diff --git a/helgrind/libhb_core.c b/helgrind/libhb_core.c index 4e102ab..7fbcdda 100644 --- a/helgrind/libhb_core.c +++ b/helgrind/libhb_core.c @@ -35,6 +35,7 @@ #include "pub_tool_libcassert.h" #include "pub_tool_libcbase.h" #include "pub_tool_libcprint.h" +#include "pub_tool_machine.h" #include "pub_tool_mallocfree.h" #include "pub_tool_wordfm.h" #include "pub_tool_hashtable.h" @@ -45,6 +46,8 @@ #include "pub_tool_stacktrace.h" #include "pub_tool_execontext.h" #include "pub_tool_errormgr.h" +#include "pub_tool_debuginfo.h" +#include "pub_tool_gdbserver.h" #include "pub_tool_options.h" // VG_(clo_stats) #include "hg_basics.h" #include "hg_wordset.h" @@ -92,6 +95,8 @@ # define CHECK_ZSM 0 /* don't sanity-check CacheLine stuff */ #endif +/* Define to 1 to activate tracing cached rcec. */ +#define DEBUG_CACHED_RCEC 0 ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// @@ -281,6 +286,23 @@ typedef #define N_KWs_N_STACKs_PER_THREAD 62500 +#define N_FRAMES 8 +// (UInt) `echo "Reference Counted Execution Context" | md5sum` +#define RCEC_MAGIC 0xab88abb2UL + +/* RCEC usage is commented more in details in the section 'Change-event map2' + later in this file */ +typedef + struct _RCEC { + UWord magic; /* sanity check only */ + struct _RCEC* next; + UWord rc; + UWord rcX; /* used for crosschecking */ + UWord frames_hash; /* hash of all the frames */ + UWord frames[N_FRAMES]; + } + RCEC; + struct _Thr { /* Current VTSs for this thread. They change as we go along. viR is the VTS to be used for reads, viW for writes. Usually they @@ -317,6 +339,14 @@ struct _Thr { Thread should be merged into a single structure. */ Thread* hgthread; + /* cached_rcec maintains the last RCEC that was retrieved for this thread. */ + RCEC cached_rcec; // cached_rcec value, not ref-counted. + /* The shadow register vex_shadow1 SP register (SP_s1) is used to maintain + the validity of the cached rcec. + If SP_s1 is 0, then the cached rcec is invalid (cannot be used). + If SP_S1 is != 0, then the cached rcec is valid. The valid cached rcec + can be used to generate a new RCEC by changing just the last frame. */ + /* The ULongs (scalar Kws) in this accumulate in strictly increasing order, without duplicates. This is important because we need to be able to find a given scalar Kw in this array @@ -4018,6 +4048,19 @@ static Thr* Thr__from_ThrID ( UInt thrid ) { return thr; } +/* True if the cached rcec for thr is valid and can be used to build the + current stack trace just by changing the last frame to the current IP. */ +static inline Bool cached_rcec_valid(Thr *thr) +{ + UWord cached_stackvalid = VG_(get_SP_s1) (thr->hgthread->coretid); + return cached_stackvalid != 0; +} +/* Set the validity of the cached rcec of thr. */ +static inline void set_cached_rcec_validity(Thr *thr, Bool valid) +{ + VG_(set_SP_s1) (thr->hgthread->coretid, valid); +} + static Thr* Thr__new ( void ) { Thr* thr = HG_(zalloc)( "libhb.Thr__new.1", sizeof(Thr) ); @@ -4031,6 +4074,11 @@ static Thr* Thr__new ( void ) = VG_(newXA)( HG_(zalloc), "libhb.Thr__new.3 (local_Kws_and_stacks)", HG_(free), sizeof(ULong_n_EC) ); + /* Make an 'empty' cached rcec in thr. */ + thr->cached_rcec.magic = RCEC_MAGIC; + thr->cached_rcec.rc = 0; + thr->cached_rcec.rcX = 0; + thr->cached_rcec.next = NULL; /* Add this Thr* <-> ThrID binding to the mapping, and cross-check */ @@ -4234,25 +4282,9 @@ static UWord stats__ctxt_tab_cmps = 0; //// Part (1): A hash table of RCECs /// -#define N_FRAMES 8 - -// (UInt) `echo "Reference Counted Execution Context" | md5sum` -#define RCEC_MAGIC 0xab88abb2UL - //#define N_RCEC_TAB 98317 /* prime */ #define N_RCEC_TAB 196613 /* prime */ -typedef - struct _RCEC { - UWord magic; /* sanity check only */ - struct _RCEC* next; - UWord rc; - UWord rcX; /* used for crosschecking */ - UWord frames_hash; /* hash of all the frames */ - UWord frames[N_FRAMES]; - } - RCEC; - //////////// BEGIN RCEC pool allocator static PoolAlloc* rcec_pool_allocator; static RCEC* alloc_RCEC ( void ) { @@ -4270,21 +4302,18 @@ static RCEC** contextTab = NULL; /* hash table of RCEC*s */ /* Count of allocated RCEC having ref count > 0 */ static UWord RCEC_referenced = 0; -/* Gives an arbitrary total order on RCEC .frames fields */ -static Word RCEC__cmp_by_frames ( RCEC* ec1, RCEC* ec2 ) { +/* True if the frames of ec1 and ec2 are different. */ +static Bool RCEC__differs_by_frames ( RCEC* ec1, RCEC* ec2 ) { Word i; tl_assert(ec1 && ec1->magic == RCEC_MAGIC); tl_assert(ec2 && ec2->magic == RCEC_MAGIC); - if (ec1->frames_hash < ec2->frames_hash) return -1; - if (ec1->frames_hash > ec2->frames_hash) return 1; + if (ec1->frames_hash != ec2->frames_hash) return True; 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 True; } - return 0; + return False; } - /* Dec the ref of this RCEC. */ static void ctxt__rcdec ( RCEC* ec ) { @@ -4371,7 +4400,7 @@ static RCEC* ctxt__find_or_add ( RCEC* example ) if (!copy) break; tl_assert(copy->magic == RCEC_MAGIC); stats__ctxt_tab_cmps++; - if (0 == RCEC__cmp_by_frames(copy, example)) break; + if (!RCEC__differs_by_frames(copy, example)) break; copy = copy->next; } @@ -4402,23 +4431,293 @@ static inline UWord ROLW ( UWord w, Int n ) return w; } +static UWord stats__cached_rcec_identical = 0; +static UWord stats__cached_rcec_updated = 0; +static UWord stats__cached_rcec_fresh = 0; +static UWord stats__cached_rcec_diff = 0; +static UWord stats__cached_rcec_diff_known_reason = 0; + +/* Check if the cached rcec in thr corresponds to the current + stacktrace of the thread. Returns True if ok, False otherwise. + This is just used for debugging the cached rcec logic, activated + using --hg-sanity-flags=xx1xxx i.e. SCE_ACCESS flag. + When this flag is activated, a call to this function will happen each time + a stack trace is needed for a memory access. */ +__attribute__((noinline)) +static Bool check_cached_rcec_ok (Thr* thr, Addr previous_frame0) +{ + Bool ok = True; + UInt i; + UWord frames[N_FRAMES]; + UWord sps[N_FRAMES]; + UWord fps[N_FRAMES]; + + for (i = 0; i < N_FRAMES; i++) + frames[i] = sps[i] = fps[i] = 0; + VG_(get_StackTrace)( thr->hgthread->coretid, &frames[0], N_FRAMES, + &sps[0], &fps[0], 0); + for (i = 0; i < N_FRAMES; i++) { + if ( thr->cached_rcec.frames[i] != frames[i] ) { + /* There are a bunch of "normal" reasons for which a stack + derived from the cached rcec differs from frames. */ + const HChar *reason = NULL; + + /* Old linkers (e.g. RHEL5) gave no cfi unwind information in the PLT + section (fix was added in binutils around June 2011). + Without PLT unwind info, stacktrace in the PLT section are + missing an entry. E.g. the cached stacktrace is: + ==4463== at 0x2035C0: ___tls_get_addr (dl-tls.c:753) + ==4463== by 0x33B7F9: __libc_thread_freeres + (in /lib/libc-2.11.2.so) + ==4463== by 0x39BA4F: start_thread (pthread_create.c:307) + ==4463== by 0x2F107D: clone (clone.S:130) + while the 'check stacktrace' is + ==4463== at 0x2035C0: ___tls_get_addr (dl-tls.c:753) + ==4463== by 0x33B82D: strerror_thread_freeres + (in /lib/libc-2.11.2.so) + ==4463== by 0x33B7F9: __libc_thread_freeres + (in /lib/libc-2.11.2.so) + ==4463== by 0x39BA4F: start_thread (pthread_create.c:307) + ==4463== by 0x2F107D: clone (clone.S:130) + No cheap/easy way to detect or fix that. */ + + /* It seems that sometimes, the CFI unwind info looks wrong + for a 'ret' instruction. E.g. here is the unwind info + for a 'retq' on gcc20 (amd64, Debian 7) + [0x4e3ddfe .. 0x4e3ddfe]: let cfa=oldSP+48 in RA=*(cfa+-8) + SP=cfa+0 BP=*(cfa+-24) + This unwind info looks doubtful, as the RA should be at oldSP. + No easy way to detect this problem. + This gives a difference between cached rcec and + current stack trace: the cached rcec is correct. */ + + /* When returning from main, unwind info becomes erratic. + So, by default, only report errors for main and above, + unless asked to show below main. */ + if (reason == NULL) { + UInt fr_main; + Vg_FnNameKind fr_kind; + for (fr_main = 0; fr_main < N_FRAMES; fr_main++) { + fr_kind = VG_(get_fnname_kind_from_IP) + (frames[fr_main]); + if (fr_kind == Vg_FnNameMain || fr_kind == Vg_FnNameBelowMain) + break; + } + UInt kh_main; + Vg_FnNameKind kh_kind; + for (kh_main = 0; kh_main < N_FRAMES; kh_main++) { + kh_kind = VG_(get_fnname_kind_from_IP) + (thr->cached_rcec.frames[kh_main]); + if (kh_kind == Vg_FnNameMain || kh_kind == Vg_FnNameBelowMain) + break; + } + if (kh_main == fr_main + && kh_kind == fr_kind + && (kh_main < i || (kh_main == i + && kh_kind == Vg_FnNameBelowMain))) { + // found main or below main before the difference + reason = "Below main"; + } + } + + /* We have places where the stack is missing some internal + pthread functions. For such stacktraces, GDB reports only + one function, telling: + #0 0xf7fa81fe in _L_unlock_669 () + from /lib/i386-linux-gnu/libpthread.so.0 + Backtrace stopped: previous frame identical to + this frame (corrupt stack?) + + This is when sps and fps are identical. + The cached stack trace is then + ==3336== at 0x40641FE: _L_unlock_669 + (pthread_mutex_unlock.c:310) + ==3336== by 0x40302BE: pthread_mutex_unlock + (hg_intercepts.c:710) + ==3336== by 0x80486AF: main (cond_timedwait_test.c:14) + while the 'check stacktrace' is + ==3336== at 0x40641FE: _L_unlock_669 + (pthread_mutex_unlock.c:310) + ==3336== by 0x4064206: _L_unlock_669 + (pthread_mutex_unlock.c:310) + ==3336== by 0x4064132: __pthread_mutex_unlock_usercnt + (pthread_mutex_unlock.c:57) + ==3336== by 0x40302BE: pthread_mutex_unlock + (hg_intercepts.c:710) + ==3336== by 0x80486AF: main (cond_timedwait_test.c:14) */ + if (reason == NULL) { + if ((i > 0 + && sps[i] == sps[i-1] && fps[i] == fps[i-1]) + || (i < N_FRAMES-1 + && sps[i] == sps[i+1] && fps[i] == fps[i+1])) { + reason = "previous||next frame: identical sp and fp"; + } + } + if (reason == NULL) { + if ((i > 0 + && fps[i] == fps[i-1]) + || (i < N_FRAMES-1 + && fps[i] == fps[i+1])) { + reason = "previous||next frame: identical fp"; + } + } + + /* When we have a read or write 'in the middle of a push instruction', + then the normal backtrace is not very good, while the helgrind + stacktrace is better, as it undoes the not yet fully finished + push instruction before getting the stacktrace. */ + if (reason == NULL && thr->hgthread->first_sp_delta != 0) { + reason = "fixupSP probably needed for check stacktrace"; + } + + /* Unwinding becomes hectic when running the exit handlers. + None of GDB, cached stacktrace and check stacktrace corresponds. + So, if we find __run_exit_handlers, ignore the difference. */ + if (reason == NULL) { + const HChar *fnname; + for (UInt f = 0; f < N_FRAMES; f++) { + if (VG_(get_fnname)( frames[f], &fnname) + && VG_(strcmp) ("__run_exit_handlers", fnname) == 0) { + reason = "exit handlers"; + break; + } + } + } + + // Show what we have found for this difference + if (reason == NULL) { + ok = False; + stats__cached_rcec_diff++; + } else { + ok = True; + stats__cached_rcec_diff_known_reason++; + } + if (!ok || VG_(clo_verbosity) > 2) { + Bool save_show_below_main = VG_(clo_show_below_main); + VG_(clo_show_below_main) = True; + /* The below error msg reports an unexpected diff in 'frame %d'. + The (maybe wrong) pc found in the cached stacktrace is + 'cached_pc %p' while an unwind gives the (maybe wrong) + 'check_pc %p'. + After, 'previous_frame0 %p' tells where the cached stacktrace + was taken. + This is then followed by the full resulting cache stack trace + and the full stack trace found doing unwind. + Such a diff can have various origins: + * a bug in the unwinder, when the cached stack trace was taken + at 'previous_frame0' + * a bug in the unwinder, when the check stack trace was taken + (i.e. at current pc). + * a missing 'invalidate cache stack trace' somewhere in the + instructions between 'previous_frame0' and current_pc. + To investigate the last case, typically, disass the range of + instructions where an invalidate cached stack might miss. */ + VG_(printf)("%s diff tid %d frame %d " + "cached_pc %p check_pc %p\n", + reason ? reason : "unexpected", + thr->hgthread->coretid, + i, + (void*)thr->cached_rcec.frames[i], + (void*)frames[i]); + VG_(printf)("cached stack trace previous_frame0 %p\n", + (void*)previous_frame0); + VG_(pp_StackTrace)(&previous_frame0, 1); + VG_(printf)("resulting cached stack trace:\n"); + VG_(pp_StackTrace)(thr->cached_rcec.frames, N_FRAMES); + VG_(printf)("check stack trace:\n"); + VG_(pp_StackTrace)(frames, N_FRAMES); + + VG_(show_sched_status) (False, // host_stacktrace + False, // stack_usage + False); // exited_threads + if (VG_(clo_vgdb_error) == 1234567890) // HACK TO ALLOW TO DEBUG + VG_(gdbserver) ( thr->hgthread->coretid ); + VG_(clo_show_below_main) = save_show_below_main; + } + break; // Stop giving more errors for this stacktrace. + } + } + return ok; +} + __attribute__((noinline)) static RCEC* get_RCEC ( Thr* thr ) { - UWord hash, i; - RCEC example; - example.magic = RCEC_MAGIC; - example.rc = 0; - example.rcX = 0; - example.next = NULL; - main_get_stacktrace( thr, &example.frames[0], N_FRAMES ); + UInt i; + UWord hash; + Addr previous_frame0 = 0; // Assignment needed to silence gcc + RCEC *res; + const Bool thr_cached_rcec_valid = cached_rcec_valid(thr); + const Addr cur_ip = VG_(get_IP)(thr->hgthread->coretid); + + if (DEBUG_CACHED_RCEC) + VG_(printf)("get rcec tid %d at IP %p SP %p" + " first_sp_delta %ld cached valid %d\n", + thr->hgthread->coretid, + (void*)cur_ip, + (void*)VG_(get_SP)(thr->hgthread->coretid), + thr->hgthread->first_sp_delta, thr_cached_rcec_valid); + + /* If we have a valid cached rcec, derive the new rcec from the cached one + and update the cached one. + Otherwise, compute a fresh rcec. */ + + if (thr_cached_rcec_valid) { + /* Update the stacktrace of the cached rcec with the current IP */ + previous_frame0 = thr->cached_rcec.frames[0]; + thr->cached_rcec.frames[0] = cur_ip; + +# if defined(VGP_x86_linux) + // See m_stacktrace.c kludge + extern Addr VG_(client__dl_sysinfo_int80); + /// #include pub_core_clientstate needed for the above ???? + /// or move the above into a pub_tool_??? tool_stacktrace.h maybe ???? + if (VG_(client__dl_sysinfo_int80) != 0 /* we know its address */ + && cur_ip >= VG_(client__dl_sysinfo_int80) + && cur_ip < VG_(client__dl_sysinfo_int80)+3 + ) { + thr->cached_rcec.frames[0] + = (ULong) *(Addr*)(UWord)VG_(get_SP)(thr->hgthread->coretid); + } +# endif + + if (previous_frame0 == thr->cached_rcec.frames[0]) + stats__cached_rcec_identical++; + else + stats__cached_rcec_updated++; + } else { + /* Compute a fresh stacktrace. */ + main_get_stacktrace( thr, &thr->cached_rcec.frames[0], N_FRAMES ); + if (DEBUG_CACHED_RCEC) { + Bool save_show_below_main = VG_(clo_show_below_main); + VG_(clo_show_below_main) = True; + VG_(printf)("caching stack trace:\n"); + VG_(pp_StackTrace)(&thr->cached_rcec.frames[0], N_FRAMES); + VG_(clo_show_below_main) = save_show_below_main; + } + stats__cached_rcec_fresh++; + } + hash = 0; for (i = 0; i < N_FRAMES; i++) { - hash ^= example.frames[i]; + hash ^= thr->cached_rcec.frames[i]; hash = ROLW(hash, 19); } - example.frames_hash = hash; - return ctxt__find_or_add( &example ); + thr->cached_rcec.frames_hash = hash; + res = ctxt__find_or_add( &thr->cached_rcec ); + + if (UNLIKELY(HG_(clo_sanity_flags) & SCE_ACCESS) + && thr_cached_rcec_valid) { + /* In case the cached and check differ, invalidate the cached rcec. + We have less duplicated diffs reported afterwards. */ + if (!check_cached_rcec_ok (thr, previous_frame0)) + set_cached_rcec_validity(thr, False); + } else { + if (HG_(clo_delta_stacktrace) && !thr_cached_rcec_valid) + set_cached_rcec_validity(thr, True); + } + + return res; } /////////////////////////////////////////////////////// @@ -6478,6 +6777,17 @@ void libhb_shutdown ( Bool show_stats ) (UWord)N_RCEC_TAB, stats__ctxt_tab_curr, RCEC_referenced, stats__ctxt_tab_max ); + VG_(printf) (" libhb: stats__cached_rcec " + "identical %'lu updated %'lu fresh %'lu\n", + stats__cached_rcec_identical, stats__cached_rcec_updated, + stats__cached_rcec_fresh); + if (stats__cached_rcec_diff > 0) + VG_(printf) (" libhb: stats__cached_rcec diff unk reason%'lu\n", + stats__cached_rcec_diff); + if (stats__cached_rcec_diff_known_reason > 0) + VG_(printf) (" libhb: stats__cached_rcec diff known reason %'lu\n", + stats__cached_rcec_diff_known_reason); + { # define MAXCHAIN 10 UInt chains[MAXCHAIN+1]; // [MAXCHAIN] gets all chains >= MAXCHAIN @@ -6552,6 +6862,9 @@ void libhb_async_exit ( Thr* thr ) tl_assert(!thr->llexit_done); thr->llexit_done = True; + /* Just to be sure, declare the cached stack invalid. */ + set_cached_rcec_validity(thr, False); + /* free up Filter and local_Kws_n_stacks (well, actually not the latter ..) */ tl_assert(thr->filter); diff --git a/include/pub_tool_debuginfo.h b/include/pub_tool_debuginfo.h index 6250e1b..86ab238 100644 --- a/include/pub_tool_debuginfo.h +++ b/include/pub_tool_debuginfo.h @@ -150,6 +150,9 @@ Bool VG_(get_data_description)( Addr data_addr ); +/* True if we have some Call Frame unwindo debuginfo for Addr a */ +extern Bool VG_(has_CF_info)(Addr a); + /* Succeeds if the address is within a shared object or the main executable. It first searches if Addr a belongs to the text segment of debug info. If not found, it asks the address space manager whether it diff --git a/include/pub_tool_libcassert.h b/include/pub_tool_libcassert.h index 1b9dd7f..41af2d2 100644 --- a/include/pub_tool_libcassert.h +++ b/include/pub_tool_libcassert.h @@ -61,6 +61,20 @@ extern void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file Int line, const HChar* fn, const HChar* format, ... ); +/* Show the state of various threads related information, such + as the guest stacktrace for each thread. + Mostly for debugging V. + The following activates optional output: + host_stacktrace : shows the host stacktrace. + stack_usage True means: + shows how much of the valgrind stack was used. + shows the client stack range + exited_thread_slots : show information for thread slots that were used + but the thread has now exited. */ +extern void VG_(show_sched_status) ( Bool host_stacktrace, + Bool stack_usage, + Bool exited_threads); + #endif // __PUB_TOOL_LIBCBASSERT_H /*--------------------------------------------------------------------*/ diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h index 07b7b95..fab8ee4 100644 --- a/include/pub_tool_machine.h +++ b/include/pub_tool_machine.h @@ -114,6 +114,9 @@ Addr VG_(get_IP) ( ThreadId tid ); Addr VG_(get_SP) ( ThreadId tid ); +// Get and set the shadow1 SP register +Addr VG_(get_SP_s1) ( ThreadId tid ); +void VG_(set_SP_s1) ( ThreadId tid, Addr sp ); // For get/set, 'area' is where the asked-for guest state will be copied // into/from. If shadowNo == 0, the real (non-shadow) guest state is diff --git a/include/pub_tool_stacktrace.h b/include/pub_tool_stacktrace.h index c442d39..848d026 100644 --- a/include/pub_tool_stacktrace.h +++ b/include/pub_tool_stacktrace.h @@ -64,6 +64,17 @@ extern UInt VG_(get_StackTrace) ( ThreadId tid, /*OUT*/StackTrace fps, Word first_ip_delta ); +// Same as VG_(get_StackTrace), but applies a delta to the first SP used for +// unwinding the first frame. +extern UInt VG_(get_StackTrace_with_deltas)( + ThreadId tid, + /*OUT*/StackTrace ips, UInt n_ips, + /*OUT*/StackTrace sps, + /*OUT*/StackTrace fps, + Word first_ip_delta, + Word first_sp_delta + ); + // Apply a function to every element in the StackTrace. The parameter // 'n' gives the index of the passed ip. 'opaque' is an arbitrary // pointer provided to each invocation of 'action' (a poor man's |
|
From: Ivo R. <iv...@iv...> - 2017-11-02 10:37:16
|
2017-10-27 16:17 GMT+02:00 Phil Longstaff <plo...@sa...>: > Yes, https://bitbucket.org/stass/valgrind-freebsd provides the freebsd port that I am using. > > Thanks for answering my questions. I will need to look at whether I can afford to provide maintenance. That does not need to be just you. Hopefully there are a lot of FreeBSD knowledgeable folks so a small community will gather around the FreeBSD port. At the end whole Valgrind community will benefit. I. |
|
From: <sv...@va...> - 2017-11-01 02:30:35
|
Author: iraisr
Date: Wed Nov 1 02:30:23 2017
New Revision: 531
Log:
Add a section about experimental tools.
Fixes BZ#386318
Patch by: Дилян Палаузов <dil...@ae...>
Modified:
trunk/info/tools.html
Modified: trunk/info/tools.html
==============================================================================
--- trunk/info/tools.html (original)
+++ trunk/info/tools.html Wed Nov 1 02:30:23 2017
@@ -12,6 +12,7 @@
<li><a href="#massif">Massif</a></li>
<li><a href="#helgrind">Helgrind</a></li>
<li><a href="#drd">DRD</a></li>
+ <li><a href="#experimental">Experimental Tools</a></li>
<li><a href="#others">Other Tools</a></li>
</ul>
</div>
@@ -119,6 +120,26 @@
for testing and demonstrative purposes.</p>
+<a name="experimental"></a>
+<h3>Experimental Tools</h3>
+<h4>DHAT</h4>
+<p>DHAT is a tool for examining how programs use their heap allocations. It
+tracks the allocated blocks, and inspects every memory access to find which
+block, if any, it is to.</p>
+
+<h4>BBV</h4>
+<p>A basic block is a linear section of code with one entry point and one exit
+point. A basic block vector (BBV) is a list of all basic blocks entered during
+program execution, and a count of how many times each basic block was run.</p>
+
+<p>BBV is a tool that generates basic block vectors for use with the SimPoint
+analysis tool.</p>
+
+<h4>SGCheck</h4>
+<p>SGCheck is a tool for finding overruns of stack and global arrays. It works
+by using a heuristic approach derived from an observation about the likely forms
+of stack and global array accesses.</p>
+
<a name="others"></a>
<h3>Other Tools</h3>
|