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
(9) |
2
(19) |
|
3
(5) |
4
(20) |
5
(5) |
6
(9) |
7
(6) |
8
(8) |
9
(5) |
|
10
(5) |
11
(5) |
12
(7) |
13
(7) |
14
(6) |
15
(5) |
16
(5) |
|
17
(5) |
18
(7) |
19
(21) |
20
(9) |
21
(6) |
22
(8) |
23
(6) |
|
24
(9) |
25
(9) |
26
(8) |
27
(19) |
28
(15) |
29
(8) |
30
(5) |
|
31
(6) |
|
|
|
|
|
|
|
From: <sv...@va...> - 2008-08-28 10:26:31
|
Author: sewardj
Date: 2008-08-28 11:26:40 +0100 (Thu, 28 Aug 2008)
New Revision: 8555
Log:
Performance improvements for the instruction-instance hash tables.
Split find_or_create_IInstance into fast and slow sections, and inline
the fast section.
Modified:
branches/SGCHECK/exp-sgcheck/sg_main.c
Modified: branches/SGCHECK/exp-sgcheck/sg_main.c
===================================================================
--- branches/SGCHECK/exp-sgcheck/sg_main.c 2008-08-27 17:41:56 UTC (rev 8554)
+++ branches/SGCHECK/exp-sgcheck/sg_main.c 2008-08-28 10:26:40 UTC (rev 8555)
@@ -983,7 +983,12 @@
static ULong stats__Invars_preened = 0;
static ULong stats__Invars_changed = 0;
static ULong stats__t_i_b_empty = 0;
+static ULong stats__htab_fast = 0;
+static ULong stats__htab_searches = 0;
+static ULong stats__htab_probes = 0;
+static ULong stats__htab_resizes = 0;
+
/* A dynamic instance of an instruction */
typedef
struct {
@@ -996,7 +1001,7 @@
IInstance;
-#define N_HTAB_FIXED 16
+#define N_HTAB_FIXED 64
typedef
struct _StackFrame {
@@ -1116,8 +1121,14 @@
}
+/* XXX this should be >> 2 on ppc32/64 since the bottom two bits
+ of the ip are guaranteed to be zero */
+inline static UWord compute_II_hash ( Addr ip, UWord htab_size ) {
+ return (ip >> 0) & (htab_size - 1);
+}
+
__attribute__((noinline))
-static void initialise_hash_table ( StackFrame* sf )
+static void initialise_II_hash_table ( StackFrame* sf )
{
UWord i;
sf->htab_size = N_HTAB_FIXED; /* initial hash table size */
@@ -1130,7 +1141,7 @@
__attribute__((noinline))
-static void resize_hash_table ( StackFrame* sf )
+static void resize_II_hash_table ( StackFrame* sf )
{
UWord i, j, ix, old_size, new_size;
IInstance *old_htab, *new_htab, *old;
@@ -1147,7 +1158,7 @@
old = &old_htab[i];
if (old->insn_addr == 0 /* NOT IN USE */)
continue;
- ix = (old->insn_addr >> 0) & (new_size - 1);
+ ix = compute_II_hash(old->insn_addr, new_size);
/* find out where to put this, in the new table */
j = new_size;
while (1) {
@@ -1175,9 +1186,9 @@
but anyway: */
j = 0;
for (i = 0; i < new_size; i++) {
- if (new_htab[i].insn_addr != 0) {
- j++;
- }
+ if (new_htab[i].insn_addr != 0) {
+ j++;
+ }
}
tl_assert(j == sf->htab_used);
if (0) VG_(printf)("resized tab for SF %p to %lu\n", sf, new_size);
@@ -1185,24 +1196,34 @@
__attribute__((noinline))
-static IInstance* find_or_create_IInstance (
+static IInstance* find_or_create_IInstance_SLOW (
StackFrame* sf,
Addr ip,
XArray* /* StackBlock */ ip_frameblocks
)
{
UWord i, ix;
- start_over:
+
+ stats__htab_searches++;
+
tl_assert(sf);
tl_assert(sf->htab);
- if (0) VG_(printf)("XXX ip %#lx size %lu used %lu\n",
- ip, sf->htab_size, sf->htab_used);
+ /* Make sure the table loading doesn't get too high. */
+ if (UNLIKELY(2 * sf->htab_used >= 1 * sf->htab_size)) {
+ stats__htab_resizes++;
+ resize_II_hash_table(sf);
+ }
tl_assert(2 * sf->htab_used <= sf->htab_size);
- ix = (ip >> 0) & (sf->htab_size - 1);
+ ix = compute_II_hash(ip, sf->htab_size);
i = sf->htab_size;
while (1) {
+ stats__htab_probes++;
+ /* Note that because of the way the fast-case handler works,
+ these two tests are actually redundant in the first iteration
+ of this loop. (Except they aren't redundant if the code just
+ above resized the table first. :-) */
if (sf->htab[ix].insn_addr == ip)
return &sf->htab[ix];
if (sf->htab[ix].insn_addr == 0)
@@ -1218,14 +1239,8 @@
if (ix == sf->htab_size) ix = 0;
}
- /* So now we've found a free slot at ix, and we can use that.
- Except, first check if we need to resize the table. If so,
- resize it, and start all over again. */
+ /* So now we've found a free slot at ix, and we can use that. */
tl_assert(sf->htab[ix].insn_addr == 0);
- if (2 * sf->htab_used >= 1 * sf->htab_size) {
- resize_hash_table(sf);
- goto start_over;
- }
/* Add a new record in this slot. */
tl_assert(ip != 0); /* CAN'T REPRESENT THIS */
@@ -1237,6 +1252,35 @@
}
+inline
+static IInstance* find_or_create_IInstance (
+ StackFrame* sf,
+ Addr ip,
+ XArray* /* StackBlock */ ip_frameblocks
+ )
+{
+ UWord ix = compute_II_hash(ip, sf->htab_size);
+ /* Is it in the first slot we come to? */
+ if (LIKELY(sf->htab[ix].insn_addr == ip)) {
+ stats__htab_fast++;
+ return &sf->htab[ix];
+ }
+ /* If the first slot we come to is empty, bag it. */
+ if (LIKELY(sf->htab[ix].insn_addr == 0)) {
+ stats__htab_fast++;
+ tl_assert(ip != 0);
+ sf->htab[ix].insn_addr = ip;
+ sf->htab[ix].blocks = ip_frameblocks;
+ sf->htab[ix].invar.tag = Inv_Unset;
+ sf->htab_used++;
+ return &sf->htab[ix];
+ }
+ /* Otherwise we hand off to the slow case, which searches other
+ slots, and optionally resizes the table if necessary. */
+ return find_or_create_IInstance_SLOW( sf, ip, ip_frameblocks );
+}
+
+
__attribute__((noinline))
static Addr calculate_StackBlock_EA ( StackBlock* descr,
Addr sp, Addr fp ) {
@@ -1304,7 +1348,8 @@
static UWord ctr = 0;
stats__qcache_queries++;
for (i = 0; i < cache->nInUse; i++) {
-tl_assert(cache->elems[i].addr + cache->elems[i].szB != 0);
+ if (0) /* expensive in a loop like this */
+ tl_assert(cache->elems[i].addr + cache->elems[i].szB != 0);
stats__qcache_probes++;
if (is_subinterval_of(cache->elems[i].addr,
cache->elems[i].szB, ea, szB)) {
@@ -1437,8 +1482,8 @@
tl_assert(uMin <= uMax);
tl_assert(uMin <= ea && ea+szB-1 <= uMax);
/* Finally, we can park [uMin,uMax] in the cache. However,
- if uMin is 0 and uMax is ~0, we can't represent the
- difference; hence fudge uMax. */
+ if uMax is ~0, we can't represent the difference; hence
+ fudge uMax. */
if (uMin < uMax && uMax == ~(UWord)0)
uMax--;
cache->elems[ip].addr = uMin;
@@ -1603,7 +1648,7 @@
}
/* This sets up .htab, .htab_size and .htab_used */
- initialise_hash_table( callee );
+ initialise_II_hash_table( callee );
callee->creation_sp = sp_post_call_insn;
callee->sp_at_call = 0; // not actually required ..
@@ -2023,7 +2068,7 @@
sframe->creation_sp = ~0UL;
/* This sets up .htab, .htab_size and .htab_used */
- initialise_hash_table( sframe );
+ initialise_II_hash_table( sframe );
/* ->depth, ->outer, ->inner are 0, NULL, NULL */
@@ -2301,13 +2346,15 @@
stats__Invars_preened, stats__Invars_changed);
VG_(message)(Vg_DebugMsg,
" t_i_b_MT: %'12llu", stats__t_i_b_empty);
- VG_(message)(Vg_DebugMsg,
- " qcache: %'12llu queries", stats__qcache_queries );
- VG_(message)(Vg_DebugMsg,
- " qcache: %'12llu probes", stats__qcache_probes );
- VG_(message)(Vg_DebugMsg,
- " qcache: %'12llu misses", stats__qcache_misses );
- VG_(message)(Vg_DebugMsg, "");
+ VG_(message)(Vg_DebugMsg,
+ " qcache: %'llu searches, %'llu probes, %'llu misses",
+ stats__qcache_queries, stats__qcache_probes, stats__qcache_misses);
+ VG_(message)(Vg_DebugMsg,
+ "htab-fast: %'llu hits",
+ stats__htab_fast);
+ VG_(message)(Vg_DebugMsg,
+ "htab-slow: %'llu searches, %'llu probes, %'llu resizes",
+ stats__htab_searches, stats__htab_probes, stats__htab_resizes);
}
static void sg_pre_clo_init(void)
|
|
From: Evan G. <th...@gm...> - 2008-08-28 06:18:29
|
No. Not yet. It's been my internship project for the past few months. I'll tar up my source tree and put it on a server by next friday for people to play with. I just want to tie up some loose ends. One warning though, it's not at all complete. It supports no floating point, no VFP (though it understands enough VFP to fake it so that setjmp and longjmp can do their context switches), clone() isn't implemented, there's bugs here and there, stack unwinding is really hacky (It works mostly with gcc generated code, up until the unwinder hits a variadic function), it only supports ARM, no thumb/thumbEE, etc, etc. However, I've had no problems running it on busybox. So, if you build for v4 with softfloat, most stuff should work. Maaaybe v6 since gcc seems to only like certain instructions like uxth/clz which are implemented. Anywho. I'll post it next week. /eazg On Aug 27, 2008, at 11:02 PM, Bart Van Assche wrote: > On Thu, Aug 28, 2008 at 4:39 AM, Evan Geller <th...@gm...> > wrote: >> My port is nearly done, minus floating point and VFP and neon and >> some other >> stuff, but it runs plenty of stuff just fine. Yes memcheck works >> fine too. >> Please don't start a port now :) It'd be a shame to have two >> separate ARM >> ports. > > Is the source code of this port already publicly available ? > > Bart. |
|
From: Bart V. A. <bar...@gm...> - 2008-08-28 06:02:19
|
On Thu, Aug 28, 2008 at 4:39 AM, Evan Geller <th...@gm...> wrote: > My port is nearly done, minus floating point and VFP and neon and some other > stuff, but it runs plenty of stuff just fine. Yes memcheck works fine too. > Please don't start a port now :) It'd be a shame to have two separate ARM > ports. Is the source code of this port already publicly available ? Bart. |
|
From: Tom H. <th...@cy...> - 2008-08-28 03:07:43
|
Nightly build on alvis ( i686, Red Hat 7.3 ) started at 2008-08-28 03:15:02 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 == 346 tests, 60 stderr failures, 1 stdout failure, 29 post failures == memcheck/tests/file_locking (stderr) memcheck/tests/leak-0 (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-regroot (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/long_namespace_xml (stderr) memcheck/tests/malloc_free_fill (stderr) memcheck/tests/origin1-yes (stderr) memcheck/tests/origin4-many (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/varinfo1 (stderr) memcheck/tests/varinfo2 (stderr) memcheck/tests/varinfo3 (stderr) memcheck/tests/varinfo4 (stderr) memcheck/tests/varinfo5 (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/bug152022 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) memcheck/tests/x86/xor-undef-x86 (stderr) memcheck/tests/xml1 (stderr) massif/tests/alloc-fns-A (post) massif/tests/alloc-fns-B (post) massif/tests/basic (post) massif/tests/basic2 (post) massif/tests/big-alloc (post) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) massif/tests/custom_alloc (post) massif/tests/deep-A (post) massif/tests/deep-B (stderr) massif/tests/deep-B (post) massif/tests/deep-C (stderr) massif/tests/deep-C (post) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/insig (post) massif/tests/long-names (post) massif/tests/long-time (post) massif/tests/new-cpp (post) massif/tests/null (post) massif/tests/one (post) massif/tests/overloaded-new (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) massif/tests/realloc (stderr) massif/tests/realloc (post) massif/tests/thresholds_0_0 (post) massif/tests/thresholds_0_10 (post) massif/tests/thresholds_10_0 (post) massif/tests/thresholds_10_10 (post) massif/tests/thresholds_5_0 (post) massif/tests/thresholds_5_10 (post) massif/tests/zero1 (post) massif/tests/zero2 (post) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) none/tests/shell (stderr) none/tests/shell_valid1 (stderr) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (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/hg06_readshared (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc02_simple_tls (stderr) helgrind/tests/tc03_re_excl (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc07_hbl1 (stderr) helgrind/tests/tc08_hbl2 (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc11_XCHG (stderr) helgrind/tests/tc12_rwl_trivial (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc18_semabuse (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) helgrind/tests/tc24_nonzero_sem (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 == 345 tests, 60 stderr failures, 1 stdout failure, 29 post failures == memcheck/tests/file_locking (stderr) memcheck/tests/leak-0 (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-regroot (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/long_namespace_xml (stderr) memcheck/tests/malloc_free_fill (stderr) memcheck/tests/origin1-yes (stderr) memcheck/tests/origin4-many (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/varinfo1 (stderr) memcheck/tests/varinfo2 (stderr) memcheck/tests/varinfo3 (stderr) memcheck/tests/varinfo4 (stderr) memcheck/tests/varinfo5 (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/bug152022 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) memcheck/tests/x86/xor-undef-x86 (stderr) memcheck/tests/xml1 (stderr) massif/tests/alloc-fns-A (post) massif/tests/alloc-fns-B (post) massif/tests/basic (post) massif/tests/basic2 (post) massif/tests/big-alloc (post) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) massif/tests/custom_alloc (post) massif/tests/deep-A (post) massif/tests/deep-B (stderr) massif/tests/deep-B (post) massif/tests/deep-C (stderr) massif/tests/deep-C (post) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/insig (post) massif/tests/long-names (post) massif/tests/long-time (post) massif/tests/new-cpp (post) massif/tests/null (post) massif/tests/one (post) massif/tests/overloaded-new (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) massif/tests/realloc (stderr) massif/tests/realloc (post) massif/tests/thresholds_0_0 (post) massif/tests/thresholds_0_10 (post) massif/tests/thresholds_10_0 (post) massif/tests/thresholds_10_10 (post) massif/tests/thresholds_5_0 (post) massif/tests/thresholds_5_10 (post) massif/tests/zero1 (post) massif/tests/zero2 (post) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) none/tests/shell (stderr) none/tests/shell_valid1 (stderr) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (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/hg06_readshared (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc02_simple_tls (stderr) helgrind/tests/tc03_re_excl (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc07_hbl1 (stderr) helgrind/tests/tc08_hbl2 (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc11_XCHG (stderr) helgrind/tests/tc12_rwl_trivial (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc18_semabuse (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) helgrind/tests/tc24_nonzero_sem (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Thu Aug 28 03:47:57 2008 --- new.short Thu Aug 28 04:07:52 2008 *************** *** 8,10 **** ! == 345 tests, 60 stderr failures, 1 stdout failure, 29 post failures == memcheck/tests/file_locking (stderr) --- 8,10 ---- ! == 346 tests, 60 stderr failures, 1 stdout failure, 29 post failures == memcheck/tests/file_locking (stderr) |
|
From: Tom H. <th...@cy...> - 2008-08-28 02:54:30
|
Nightly build on aston ( x86_64, Fedora Core 5 ) started at 2008-08-28 03:20:04 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 == 444 tests, 8 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) 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/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 == 443 tests, 8 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/file_locking (stderr) 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) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Thu Aug 28 03:37:19 2008 --- new.short Thu Aug 28 03:54:39 2008 *************** *** 8,10 **** ! == 443 tests, 8 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/file_locking (stderr) --- 8,10 ---- ! == 444 tests, 8 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) *************** *** 15,16 **** --- 15,17 ---- none/tests/mremap2 (stdout) + helgrind/tests/tc08_hbl2 (stdout) helgrind/tests/tc20_verifywrap (stderr) |
|
From: Tom H. <th...@cy...> - 2008-08-28 02:44:46
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2008-08-28 03:05:09 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 == 438 tests, 6 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) memcheck/tests/malloc_free_fill (stderr) 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) ================================================= == 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 == 437 tests, 6 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) memcheck/tests/malloc_free_fill (stderr) 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) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Thu Aug 28 03:21:30 2008 --- new.short Thu Aug 28 03:44:52 2008 *************** *** 8,10 **** ! == 437 tests, 6 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) --- 8,10 ---- ! == 438 tests, 6 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) |
|
From: Tom H. <th...@cy...> - 2008-08-28 02:42:00
|
Nightly build on trojan ( x86_64, Fedora Core 6 ) started at 2008-08-28 03:25:04 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 == 442 tests, 8 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) memcheck/tests/malloc_free_fill (stderr) 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) ================================================= == 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 == 441 tests, 8 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) memcheck/tests/malloc_free_fill (stderr) 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 Thu Aug 28 03:33:30 2008 --- new.short Thu Aug 28 03:42:07 2008 *************** *** 8,10 **** ! == 441 tests, 8 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) --- 8,10 ---- ! == 442 tests, 8 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) |
|
From: Evan G. <th...@gm...> - 2008-08-28 02:39:05
|
My port is nearly done, minus floating point and VFP and neon and some other stuff, but it runs plenty of stuff just fine. Yes memcheck works fine too. Please don't start a port now :) It'd be a shame to have two separate ARM ports. And for the record it's a huge amount of work. Ivan's code isn't working either, since the flags aren't being set properly, and removing the flag thunks slows things down. Currently the flags are being calculated in IR but I plan to make that a helper. The tree is pretty dirty right now, I might just post a tarball somewhere so people can play with it. I haven't really talked to anyone from the valgrind project about actually integrating it in. The code is just really hashy right now, but it works. I'll try and have it up by next friday :-D /eazg ~~~~ Hi all: We are also trying to port Valgrind to ARM. We are not sure whether we shall proceed because right now we have no idea how much time it is going to take. I've read the following Documentation: 1) Valgrind: A Framework for Heavyweight Dynamic Binary Instrumentation; 2) How to Shadow Every Byte of Memory Used by a Program; Here's my understanding and questions about porting Valgrind to ARM. Please correct me if I am wrong: How Valgrind works: Valgrind core will first convert the user executable into a standard Valgrind intermediate code (somewhat similar to the JAVA byte code). After that, Valgrind will do some optimization on the intermediate code. Then the Valgrind tools such as memcheck will instrument (massage) the intermediate code to implement the tools' own functionality, e.g., memory leak detection. Since this step is based on intermediate code (architecture independent), theoretically, we don't need to do extra work on Valgrind tools. When Valgrind tools finish massaging the intermediate code, Valgrind core will optimize the intermediate code again, allocate architecture dependant registers, and then convert the optimized intermediate code back to the architecture specific machine code (ARM binary code). To port Valgrind to ARM, we need to do the following: a) Convert ARM executable to IR code. This part is already available inVEX/priv/guest-arm/toIR.c and Ivan has the path for it. This is the client's side. b) Convert the optimized Valgrind intermediate code back to the ARM binary executable. There's a lot of work to do here inVEX/priv/host-arm/hdefs.c. Basically we have to implement corresponding functions for ARM as listed in vex_main.c for PPC32: case VexArchPPC32: mode64 = False; getAllocableRegs_PPC ( &n_available_real_regs,&available_real_regs, mode64 ); isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr; getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool))getRegUsage_PPCInstr; mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr; genSpill = (HInstr*(*)(HReg,Int,Bool)) genSpill_PPC; genReload = (HInstr*(*)(HReg,Int,Bool)) genReload_PPC; ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr; ppReg = (void(*)(HReg)) ppHRegPPC;iselSB = iselSB_PPC; emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*))emit_PPCInstr; host_is_bigendian = True; host_word_type = Ity_I32; vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps)); vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */ break; Of course we need to implement other functions such as scheduler, dispatcher, c_main startup code, etc..., but the above mentioned two parts are the key steps to the porting. My biggest concern is that according to my understanding, porting to ARM does not require extra work on memcheck, callgrind, helgrind and other Valgrind tools since these tools work on Valgrind IR code and the IR code is architecture independent. Can anyone tell me whether the porting requires extra work on Valgrind tools? Thanks Shachen _________________________________________________________________ ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ Valgrind-developers mailing list Val...@li...<mailto: Val...@li...> https://lists.sourceforge.net/lists/listinfo/valgrind-developers -- --- Evan Geller th...@gm... -- --- Evan Geller th...@gm... |
|
From: Tom H. <th...@cy...> - 2008-08-28 02:24:02
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2008-08-28 03:00: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 == 444 tests, 31 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) 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) ================================================= == 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 == 443 tests, 31 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) 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) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Thu Aug 28 03:11:59 2008 --- new.short Thu Aug 28 03:24:07 2008 *************** *** 8,10 **** ! == 443 tests, 31 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) --- 8,10 ---- ! == 444 tests, 31 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) |
|
From: Ashley P. <api...@co...> - 2008-08-27 21:17:59
|
On Tue, 2008-08-26 at 14:05 -0700, Dave Nomura wrote: > Is there a *.xsd or *.dtd that describes the XML that is output by the > --xml option? > > Are there any consumers of valgrind's xml in the valgrind source tree? I create a utility for converting back from xml output to what the native output would have been normally. I was then able to extend this to work in parallel, effectively merging multiple processes into a single error file showing the sum of the errors. At the time I had this working well enough so that you could hook it into the valgrind test suite and run the tests in XML mode, use my tool to convert it to text and check the results normally. I think there were about three tests failing this way and they were due to mal-formed XML rather than my conversion program. It's still being run as part of the nightly tests by my now ex employer. The tool is open-source however and I'd like to get it into shape and contributed however have lacked the time to do so. > Is there any documentation or suggestions for developing an XML consumer > of valgrind --xml ? I used perl, the XML::Simple module "just works" for me and allows me to get on with the interesting part of the code, the problem with this however is on large input files it can get quite slow. I got most of the way to doing it nativity in XML::Parser however this has sat idle for months now. The speed increase was from a small number of minutes to a small number of seconds for 1MB xml files. Ashley Pittman. |
|
From: Steve V.
|
This patch implements a valgrind specific clone flag (VKI_CLONE_CHILD_LETGO),
which instructs valgrind to run the child nativley. It is only implemented
for fork like clones and on x86 (currently).
Index: valgrind/coregrind/m_syswrap/syswrap-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-linux.c 2008-08-22 10:06:17.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-linux.c 2008-08-22 10:17:23.000000000 -0700
@@ -339,6 +339,14 @@
VG_(do_atfork_child)(tid);
+ if (flags & VKI_CLONE_CHILD_LETGO) {
+#if defined(VGP_x86_linux)
+ letgo_vex_x86_linux(&ctst->arch.vex, tid);
+ /* NORETURN */
+#else
+ VG_(message)(Vg_UserMsg, "CLONE_CHILD_LETGO is not yet implmented on this platform; ignoring.");
+#endif
+ }
/* restore signal mask */
VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
Index: valgrind/coregrind/m_syswrap/syswrap-x86-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-x86-linux.c 2008-08-22 10:06:17.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-x86-linux.c 2008-08-22 10:50:25.000000000 -0700
@@ -190,6 +190,83 @@
// forward declarations
static void setup_child ( ThreadArchState*, ThreadArchState*, Bool );
static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
+static SysRes propagate_thread_area(ThreadId tid, VexGuestArchState *vex);
+SysRes letgo_vex_x86_linux(VexGuestArchState *vex, ThreadId tid);
+
+static SysRes propagate_thread_area(ThreadId tid, VexGuestArchState *vex)
+{
+ VexGuestX86SegDescr * sdp;
+ vki_modify_ldt_t ud;
+ SysRes res;
+
+ if (! vex->guest_GS)
+ return VG_(mk_SysRes_Success)( 0 );
+
+ VG_(memset)(&ud, 0, sizeof(ud));
+ sdp = (vex->guest_GS >> 3) + ((VexGuestX86SegDescr*)vex->guest_GDT);
+
+ ud.entry_number = -1;
+ ud.base_addr = sdp->LdtEnt.Bits.BaseLow | (sdp->LdtEnt.Bits.BaseMid << 16)
+ | (sdp->LdtEnt.Bits.BaseHi << 24);
+ ud.limit = sdp->LdtEnt.Bits.LimitLow | (sdp->LdtEnt.Bits.LimitHi << 16);
+ ud.seg_32bit = sdp->LdtEnt.Bits.Default_Big;
+ ud.contents = sdp->LdtEnt.Bits.Type >> 2;
+ ud.read_exec_only = 1 ^ (1 & (sdp->LdtEnt.Bits.Type >> 1));
+ ud.limit_in_pages = sdp->LdtEnt.Bits.Granularity;
+ ud.seg_not_present = 0;
+ ud.useable = 1;
+
+ res = VG_(do_syscall1)( __NR_set_thread_area, (UWord)&ud);
+ if (res.isError) {
+ VG_(printf)("propagate_thread_area set_thread_area failed\n");
+ } else {
+ vex->guest_GS = 3 | (ud.entry_number << 3);
+ }
+ return res;
+}
+
+SysRes letgo_vex_x86_linux(VexGuestArchState *vex, ThreadId tid)
+{
+ vki_sigset_t clear;
+ unsigned long * vex_stack;
+ unsigned short es;
+ SysRes res;
+
+ res = propagate_thread_area(tid, vex);
+ if (res.isError)
+ return res;
+
+ /* Put EIP and a PUSHAD frame on the vex stack */
+ vex->guest_ESP -= sizeof(unsigned long *);
+ vex_stack = ((unsigned long *) vex->guest_ESP) - 8;
+ vex_stack[8] = vex->guest_EIP;
+ vex_stack[7] = 0; /* return value of clone*/
+ vex_stack[6] = vex->guest_ECX;
+ vex_stack[5] = vex->guest_EDX;
+ vex_stack[4] = vex->guest_EBX;
+ vex_stack[3] = vex->guest_ESP;
+ vex_stack[2] = vex->guest_EBP;
+ vex_stack[1] = vex->guest_ESI;
+ vex_stack[0] = vex->guest_EDI;
+
+ es = vex->guest_ES;
+ if (es == 0)
+ asm("mov %%ds, %0\n" : "=r"(es));
+
+ VG_(sigemptyset)(&clear);
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &clear, NULL);
+
+ /* Set the segment regs, change to the vex stack, restore regs and return */
+ asm("mov %0, %%es\n"
+ "mov %1, %%fs\n"
+ "mov %2, %%gs\n"
+ "movl %3, %%esp\n"
+ "popa\n"
+ "ret\n"
+ :: "r"(es), "r"(vex->guest_FS), "r"(vex->guest_GS), "r"(vex_stack) );
+
+ return VG_(mk_SysRes_Error)(-1); /* Make gcc happy */
+}
/*
When a client clones, we need to keep track of the new thread. This means:
@@ -901,6 +978,11 @@
goto reject;
}
+ /* Can't let a child run wild in a shared address space */
+ if ((cloneflags & (VKI_CLONE_VM | VKI_CLONE_VFORK | VKI_CLONE_CHILD_LETGO))
+ == (VKI_CLONE_VM | VKI_CLONE_CHILD_LETGO))
+ goto reject;
+
/* Only look at the flags we really care about */
switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
| VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Index: valgrind/include/vki/vki-linux.h
===================================================================
--- valgrind.orig/include/vki/vki-linux.h 2008-08-22 10:04:48.000000000 -0700
+++ valgrind/include/vki/vki-linux.h 2008-08-22 10:06:30.000000000 -0700
@@ -322,6 +322,7 @@
#define VKI_CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */
#define VKI_CLONE_DETACHED 0x00400000 /* Unused, ignored */
#define VKI_CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */
+#define VKI_CLONE_CHILD_LETGO 0x80000000 /* do not track fork like children*/
struct vki_sched_param {
int sched_priority;
Index: valgrind/memcheck/tests/x86/clone-fork-child-letgo.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ valgrind/memcheck/tests/x86/clone-fork-child-letgo.c 2008-08-22 10:06:30.000000000 -0700
@@ -0,0 +1,62 @@
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int fn_child(void *argp)
+{
+ int *const p = (int *)argp;
+ printf("child stack=%p\n", &argp);
+ fflush(stdout);
+ if (p[1]) {
+ return p[0];
+ }
+ else {
+ return p[1];
+ }
+}
+
+typedef void (*sighandler_t)(int);
+
+void handler(int signo)
+{
+ printf("handler signo=%d\n", signo);
+}
+
+int my_clone(int (*fn)(void *), void *stack, unsigned xflags, void *arg)
+{
+/* The flags lack CLONE_VM, so the clone() is like a fork().
+ * A new process gets created, not a new thread.
+ */
+ int pid = clone(fn, stack,
+ xflags | SIGCHLD, arg, 0,0,0);
+ if (pid < 0)
+ perror("clone failed");
+ //waitpid(pid, &status, 0);
+ //printf("status= %x\n", status);
+ return 0;
+}
+
+#define L_STACKS (1024*1024)
+
+#define CLONE_CHILD_LETGO 0x80000000
+
+int main(int argc, char *argv[])
+{
+ int x[2];
+/* Space for two stacks. */
+ void *const stack = mmap((void *)0x300000, L_STACKS, PROT_READ|PROT_WRITE,
+ MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+
+ x[0]= 12345; /* x[1] undefined */
+ signal(SIGCHLD, handler);
+
+/* Stack uses second half of mmap()ed space. */
+ my_clone(fn_child, L_STACKS + stack, 0, x);
+
+/* Stack uses first half of mmap()ed space. */
+ my_clone(fn_child, (L_STACKS>>1) + stack, CLONE_CHILD_LETGO, x);
+ return 0;
+}
Index: valgrind/memcheck/tests/x86/clone-fork-child-letgo.stderr.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ valgrind/memcheck/tests/x86/clone-fork-child-letgo.stderr.exp 2008-08-22 10:06:30.000000000 -0700
@@ -0,0 +1,9 @@
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: fn_child (clone-fork-child-letgo.c:13)
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
+malloc/free: in use at exit: 0 bytes in 0 blocks.
+malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
+For a detailed leak analysis, rerun with: --leak-check=yes
+For counts of detected errors, rerun with: -v
Index: valgrind/memcheck/tests/x86/clone-fork-child-letgo.stdout.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ valgrind/memcheck/tests/x86/clone-fork-child-letgo.stdout.exp 2008-08-22 10:06:30.000000000 -0700
@@ -0,0 +1,2 @@
+child stack=0x37fff0
+child stack=0x3ffff0
Index: valgrind/memcheck/tests/x86/clone-fork-child-letgo.vgtest
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ valgrind/memcheck/tests/x86/clone-fork-child-letgo.vgtest 2008-08-22 10:06:30.000000000 -0700
@@ -0,0 +1 @@
+prog: clone-fork-child-letgo
Index: valgrind/memcheck/tests/x86/Makefile.am
===================================================================
--- valgrind.orig/memcheck/tests/x86/Makefile.am 2008-08-22 10:04:48.000000000 -0700
+++ valgrind/memcheck/tests/x86/Makefile.am 2008-08-22 10:06:30.000000000 -0700
@@ -7,6 +7,7 @@
EXTRA_DIST = $(noinst_SCRIPTS) \
bug133694.vgtest bug133694.stderr.exp bug133694.stdout.exp \
bug152022.vgtest bug152022.stderr.exp bug152022.stdout.exp \
+ clone-fork-child-letgo.vgtest clone-fork-child-letgo.stderr.exp clone-fork-child-letgo.stdout.exp \
espindola2.vgtest espindola2.stderr.exp \
fpeflags.stderr.exp fpeflags.vgtest \
fxsave.vgtest fxsave.stdout.exp fxsave.stderr.exp \
@@ -35,6 +36,7 @@
check_PROGRAMS = \
bug133694 \
bug152022 \
+ clone-fork-child-letgo \
espindola2 \
fxsave \
int3-x86 \
Index: valgrind/coregrind/m_syswrap/priv_syswrap-linux.h
===================================================================
--- valgrind.orig/coregrind/m_syswrap/priv_syswrap-linux.h 2008-08-22 10:06:03.000000000 -0700
+++ valgrind/coregrind/m_syswrap/priv_syswrap-linux.h 2008-08-22 10:34:21.000000000 -0700
@@ -40,6 +40,10 @@
void (*f)(Word), Word arg1 );
extern SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags, Addr child_esp,
Int* parent_tidptr, Int* child_tidptr );
+#if defined(VGP_x86_linux)
+extern SysRes letgo_vex_x86_linux(VexGuestArchState *vex, ThreadId tid);
+#endif
+
// Linux-specific (but non-arch-specific) syscalls
|
|
From: Steve V.
|
This patch handles more combinations of flag arguments to clone(),
specifically more variations of VKI_CLONE_FILES and VKI_CLONE_FS are allowed.
Index: valgrind/coregrind/m_syswrap/syswrap-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-linux.c 2008-08-21 16:13:08.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-linux.c 2008-08-21 16:28:12.000000000 -0700
@@ -307,7 +307,7 @@
SysRes res;
if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM
- | VKI_CLONE_FILES | VKI_CLONE_VFORK))
+ | VKI_CLONE_VFORK))
return VG_(mk_SysRes_Error)( VKI_EINVAL );
/* Block all signals during fork, so that we can fix things up in
Index: valgrind/coregrind/m_syswrap/syswrap-x86-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-x86-linux.c 2008-08-21 16:06:25.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-x86-linux.c 2008-08-21 16:32:26.000000000 -0700
@@ -905,6 +905,7 @@
switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
| VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
+ case VKI_CLONE_VM | VKI_CLONE_FILES:
/* thread creation */
SET_STATUS_from_SysRes(
do_clone(tid,
@@ -915,6 +916,7 @@
(vki_modify_ldt_t *)ARG4)); /* set_tls */
break;
+ case VKI_CLONE_FILES: /* fork with shared fd's */
case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
/* FALLTHROUGH - assume vfork == fork */
cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
|
|
From: Steve V.
|
Valgrind currently ignores the child_sp parameter to clone when the flags
make it a fork like clone. This patch passes the child_sp down and uses
it to update the stack pointer in the new child.
Index: valgrind/coregrind/m_syswrap/priv_syswrap-linux.h
===================================================================
--- valgrind.orig/coregrind/m_syswrap/priv_syswrap-linux.h 2008-08-21 16:05:14.000000000 -0700
+++ valgrind/coregrind/m_syswrap/priv_syswrap-linux.h 2008-08-21 16:06:25.000000000 -0700
@@ -38,7 +38,7 @@
extern Addr ML_(allocstack) ( ThreadId tid );
extern void ML_(call_on_new_stack_0_1) ( Addr stack, Addr retaddr,
void (*f)(Word), Word arg1 );
-extern SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
+extern SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags, Addr child_esp,
Int* parent_tidptr, Int* child_tidptr );
Index: valgrind/coregrind/m_syswrap/syswrap-amd64-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-amd64-linux.c 2008-08-21 16:05:14.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-amd64-linux.c 2008-08-21 16:06:25.000000000 -0700
@@ -432,6 +432,7 @@
SET_STATUS_from_SysRes(
ML_(do_fork_clone)(tid,
cloneflags, /* flags */
+ (Addr)ARG2, /* child ESP */
(Int *)ARG3, /* parent_tidptr */
(Int *)ARG4)); /* child_tidptr */
break;
Index: valgrind/coregrind/m_syswrap/syswrap-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-linux.c 2008-08-21 16:05:14.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-linux.c 2008-08-21 16:13:08.000000000 -0700
@@ -51,6 +51,8 @@
#include "pub_core_signals.h"
#include "pub_core_syscall.h"
#include "pub_core_syswrap.h"
+#include "pub_core_machine.h" // VG_STACK_PTR
+
#include "priv_types_n_macros.h"
#include "priv_syswrap-generic.h"
@@ -297,7 +299,7 @@
/* Do a clone which is really a fork() */
-SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
+SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags, Addr child_esp,
Int* parent_tidptr, Int* child_tidptr )
{
vki_sigset_t fork_saved_mask;
@@ -331,6 +333,10 @@
if (!res.isError && res.res == 0) {
/* child */
+ ThreadState *const ctst = VG_(get_ThreadState)(tid);
+ if (child_esp) /* Set the stack pointer */
+ ctst->arch.vex.VG_STACK_PTR = child_esp;
+
VG_(do_atfork_child)(tid);
/* restore signal mask */
Index: valgrind/coregrind/m_syswrap/syswrap-ppc32-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-ppc32-linux.c 2008-08-21 16:05:14.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-ppc32-linux.c 2008-08-21 16:06:25.000000000 -0700
@@ -1005,6 +1005,7 @@
SET_STATUS_from_SysRes(
ML_(do_fork_clone)(tid,
cloneflags, /* flags */
+ (Addr)ARG2, /* child SP */
(Int *)ARG3, /* parent_tidptr */
(Int *)ARG5)); /* child_tidptr */
break;
Index: valgrind/coregrind/m_syswrap/syswrap-ppc64-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-ppc64-linux.c 2008-08-21 16:05:14.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-ppc64-linux.c 2008-08-21 16:06:25.000000000 -0700
@@ -984,6 +984,7 @@
SET_STATUS_from_SysRes(
ML_(do_fork_clone)(tid,
cloneflags, /* flags */
+ (Addr)ARG2, /* child SP */
(Int *)ARG3, /* parent_tidptr */
(Int *)ARG5)); /* child_tidptr */
break;
Index: valgrind/coregrind/m_syswrap/syswrap-x86-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-x86-linux.c 2008-08-21 16:05:14.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-x86-linux.c 2008-08-21 16:06:25.000000000 -0700
@@ -923,6 +923,7 @@
SET_STATUS_from_SysRes(
ML_(do_fork_clone)(tid,
cloneflags, /* flags */
+ (Addr)ARG2, /* child ESP */
(Int *)ARG3, /* parent_tidptr */
(Int *)ARG5)); /* child_tidptr */
break;
Index: valgrind/none/tests/x86/clone-fork-child-sp.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ valgrind/none/tests/x86/clone-fork-child-sp.c 2008-08-21 16:06:25.000000000 -0700
@@ -0,0 +1,37 @@
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int fn_child(void *argp)
+{
+ int *const p = (int *)argp;
+ printf("child stack=%p arg=%d\n", &argp, *p);
+ fflush(stdout);
+ return 0;
+}
+
+typedef void (*sighandler_t)(int);
+
+void handler(int signo)
+{
+ printf("handler signo=%d\n", signo);
+}
+
+int x = 39;
+
+int main(int argc, char *argv[])
+{
+ int status = 0;
+ sighandler_t rv = signal(SIGCHLD, handler);
+ void *stack = mmap((void *)0x300000, 4096, PROT_READ|PROT_WRITE,
+ MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ int pid = clone(fn_child, 4096+ stack, 0 | SIGCHLD, &x, 0,0,0);
+ if (pid < 0)
+ perror("clone failed");
+ waitpid(pid, &status, 0);
+ printf("status= %x\n", status);
+ return 0;
+}
Index: valgrind/none/tests/x86/clone-fork-child-sp.stderr.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ valgrind/none/tests/x86/clone-fork-child-sp.stderr.exp 2008-08-21 16:06:25.000000000 -0700
@@ -0,0 +1,3 @@
+
+
+
Index: valgrind/none/tests/x86/clone-fork-child-sp.stdout.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ valgrind/none/tests/x86/clone-fork-child-sp.stdout.exp 2008-08-21 16:06:25.000000000 -0700
@@ -0,0 +1,3 @@
+child stack=0x300ff0 arg=39
+handler signo=17
+status= 0
Index: valgrind/none/tests/x86/clone-fork-child-sp.vgtest
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ valgrind/none/tests/x86/clone-fork-child-sp.vgtest 2008-08-21 16:06:25.000000000 -0700
@@ -0,0 +1 @@
+prog: clone-fork-child-sp
Index: valgrind/none/tests/x86/Makefile.am
===================================================================
--- valgrind.orig/none/tests/x86/Makefile.am 2008-08-21 16:05:14.000000000 -0700
+++ valgrind/none/tests/x86/Makefile.am 2008-08-21 16:06:25.000000000 -0700
@@ -47,6 +47,8 @@
movx.stderr.exp movx.stdout.exp movx.vgtest \
pushpopseg.stderr.exp pushpopseg.stdout.exp pushpopseg.vgtest \
sbbmisc.stderr.exp sbbmisc.stdout.exp sbbmisc.vgtest \
+ clone-fork-child-sp.stderr.exp clone-fork-child-sp.stdout.exp \
+ clone-fork-child-sp.vgtest \
seg_override.stderr.exp seg_override.stdout.exp seg_override.vgtest \
sigcontext.stdout.exp sigcontext.stderr.exp sigcontext.vgtest \
smc1.stderr.exp smc1.stdout.exp smc1.vgtest \
@@ -68,6 +70,7 @@
getseg incdec_alt $(INSN_TESTS) \
jcxz \
lahf looper movx int pushpopseg sbbmisc \
+ clone-fork-child-sp \
seg_override sigcontext smc1 yield
if BUILD_SSSE3_TESTS
check_PROGRAMS += ssse3_misaligned
|
|
From: Steve V.
|
do_clone() uses the passed stack pointer to guess at the scope of the
new stack and registers it. Somtimes this guess is bad enough to cause
problems. This patch will first check to see if the passed stack pointer
is already part of a registered stack. If it is, use that stack and don't
register a new stack. (Bug 168538)
Index: valgrind/coregrind/m_stacks.c
===================================================================
--- valgrind.orig/coregrind/m_stacks.c 2008-08-21 15:42:21.000000000 -0700
+++ valgrind/coregrind/m_stacks.c 2008-08-21 15:44:17.000000000 -0700
@@ -171,6 +171,17 @@
}
/*
+ * Lookup the passed stack pointer and try to determine if it points to
+ * an already registered stack.
+ */
+Bool VG_(is_stack_registered)(Addr sp)
+{
+ if (find_stack_by_addr(sp) == NULL)
+ return False;
+ return True;
+}
+
+/*
* Register a new stack from start - end. This is invoked from the
* VALGRIND_STACK_REGISTER client request, and is also called just before
* we start the client running, to register the main process stack.
Index: valgrind/coregrind/m_syswrap/syswrap-x86-linux.c
===================================================================
--- valgrind.orig/coregrind/m_syswrap/syswrap-x86-linux.c 2008-08-21 15:42:44.000000000 -0700
+++ valgrind/coregrind/m_syswrap/syswrap-x86-linux.c 2008-08-21 15:44:17.000000000 -0700
@@ -260,11 +260,12 @@
ctst->sig_mask = ptst->sig_mask;
ctst->tmp_sig_mask = ptst->sig_mask;
- /* We don't really know where the client stack is, because its
- allocated by the client. The best we can do is look at the
- memory mappings and try to derive some useful information. We
- assume that esp starts near its highest possible value, and can
- only go down to the start of the mmaped segment. */
+ /* Unless the client stack is already registered, we don't really know
+ where it is, because it's allocated by the client. The best we can
+ do is look at the memory mappings and try to derive some useful
+ information. We assume that esp starts near its highest possible
+ value, and can only go down to the start of the mmaped segment. */
+ if (!VG_(is_stack_registered)((Addr)esp)) {
seg = VG_(am_find_nsegment)((Addr)esp);
if (seg && seg->kind != SkResvn) {
ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(esp);
@@ -280,6 +281,11 @@
ctid, esp);
ctst->client_stack_szB = 0;
}
+ } else {
+ if (debug)
+ VG_(printf)("tid %d: client stack already registered (%#lx)\n",
+ ctid, esp);
+ }
/* Assume the clone will succeed, and tell any tool that wants to
know that this thread has come into existence. We cannot defer
Index: valgrind/coregrind/pub_core_stacks.h
===================================================================
--- valgrind.orig/coregrind/pub_core_stacks.h 2008-08-21 15:42:21.000000000 -0700
+++ valgrind/coregrind/pub_core_stacks.h 2008-08-21 15:44:17.000000000 -0700
@@ -40,6 +40,7 @@
extern void VG_(deregister_stack) ( UWord id );
extern void VG_(change_stack) ( UWord id, Addr start, Addr end );
extern void VG_(stack_limits) ( Addr SP, Addr *start, Addr *end );
+extern Bool VG_(is_stack_registered) ( Addr SP );
extern VG_REGPARM(3)
void VG_(unknown_SP_update) ( Addr old_SP, Addr new_SP, UInt otag );
|
|
From: Steve V.
|
This patch allows the stack to be in a mem-mapped file.
Index: valgrind/coregrind/m_signals.c
===================================================================
--- valgrind.orig/coregrind/m_signals.c 2008-08-21 15:42:14.000000000 -0700
+++ valgrind/coregrind/m_signals.c 2008-08-21 17:44:07.000000000 -0700
@@ -1667,7 +1667,7 @@
= seg ? VG_(am_next_nsegment)( (NSegment*)seg, True/*fwds*/ )
: NULL;
- if (seg && seg->kind == SkAnonC)
+ if (seg && (seg->kind == SkAnonC || seg->kind == SkFileC))
/* addr is already mapped. Nothing to do. */
return True;
|
|
From: Steve V.
|
The following patches enables Valgrind to produce useful results for User Mode Linux. At a high level, there are three changes: additional heuristics for dealing with stacks, a couple more combinations of clone flags, and special clone flag to disown a child ASAP. Please consider these patches for merging or send feedback about what prevents them from being merged. Thanks, Steve |
|
From: Bart V. A. <bar...@gm...> - 2008-08-27 18:19:31
|
On Mon, Aug 25, 2008 at 4:15 PM, Denys Vlasenko <dvl...@re...> wrote: > Please comment or apply. Please review commits r8553 and r8554 (trunk). Bart. |
|
From: <sv...@va...> - 2008-08-27 17:41:49
|
Author: bart
Date: 2008-08-27 18:41:56 +0100 (Wed, 27 Aug 2008)
New Revision: 8554
Log:
Enabled capget and capset system calls for amd64, ppc32 and ppc64.
Modified:
trunk/coregrind/m_syswrap/syswrap-amd64-linux.c
trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c
Modified: trunk/coregrind/m_syswrap/syswrap-amd64-linux.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-amd64-linux.c 2008-08-27 17:41:06 UTC (rev 8553)
+++ trunk/coregrind/m_syswrap/syswrap-amd64-linux.c 2008-08-27 17:41:56 UTC (rev 8554)
@@ -1165,8 +1165,8 @@
LINX_(__NR_setfsgid, sys_setfsgid), // 123
GENX_(__NR_getsid, sys_getsid), // 124
- // LINXY(__NR_capget, sys_capget), // 125
- // LINX_(__NR_capset, sys_capset), // 126
+ LINXY(__NR_capget, sys_capget), // 125
+ LINX_(__NR_capset, sys_capset), // 126
LINXY(__NR_rt_sigpending, sys_rt_sigpending), // 127
LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait),// 128
LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 129
Modified: trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c 2008-08-27 17:41:06 UTC (rev 8553)
+++ trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c 2008-08-27 17:41:56 UTC (rev 8554)
@@ -1691,9 +1691,8 @@
GENX_(__NR_pwrite64, sys_pwrite64_on32bitplat), // 180
GENX_(__NR_chown, sys_chown), // 181
GENXY(__NR_getcwd, sys_getcwd), // 182
-//.. LINXY(__NR_capget, sys_capget), // 183
-//..
-//.. LINX_(__NR_capset, sys_capset), // 184
+ LINXY(__NR_capget, sys_capget), // 183
+ LINX_(__NR_capset, sys_capset), // 184
GENXY(__NR_sigaltstack, sys_sigaltstack), // 185
LINXY(__NR_sendfile, sys_sendfile), // 186
//.. GENXY(__NR_getpmsg, sys_getpmsg), // 187
Modified: trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c 2008-08-27 17:41:06 UTC (rev 8553)
+++ trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c 2008-08-27 17:41:56 UTC (rev 8554)
@@ -1359,8 +1359,8 @@
// _____(__NR_pwrite64, sys_pwrite64), // 180
GENX_(__NR_chown, sys_chown), // 181
GENXY(__NR_getcwd, sys_getcwd), // 182
-// _____(__NR_capget, sys_capget), // 183
-// _____(__NR_capset, sys_capset), // 184
+ LINXY(__NR_capget, sys_capget), // 183
+ LINX_(__NR_capset, sys_capset), // 184
GENXY(__NR_sigaltstack, sys_sigaltstack), // 185
LINXY(__NR_sendfile, sys_sendfile), // 186
|
|
From: <sv...@va...> - 2008-08-27 17:41:00
|
Author: bart
Date: 2008-08-27 18:41:06 +0100 (Wed, 27 Aug 2008)
New Revision: 8553
Log:
Added regression test for Linux' capget system call.
Added:
trunk/memcheck/tests/linux-capget.c
trunk/memcheck/tests/linux-capget.stderr.exp
trunk/memcheck/tests/linux-capget.vgtest
Modified:
trunk/memcheck/tests/Makefile.am
Modified: trunk/memcheck/tests/Makefile.am
===================================================================
--- trunk/memcheck/tests/Makefile.am 2008-08-27 13:35:02 UTC (rev 8552)
+++ trunk/memcheck/tests/Makefile.am 2008-08-27 17:41:06 UTC (rev 8553)
@@ -66,6 +66,7 @@
leak-tree.stderr.exp2 leak-tree.stderr.exp64 \
leak-regroot.vgtest leak-regroot.stderr.exp \
leakotron.vgtest leakotron.stdout.exp leakotron.stderr.exp \
+ linux-capget linux-capget.stderr.exp \
linux-syslog-syscall linux-syslog-syscall.stderr.exp \
linux-syscalls-2007 linux-syscalls-2007.stderr.exp \
linux-timerfd-syscall linux-timerfd-syscall.stderr.exp \
@@ -190,6 +191,7 @@
file_locking \
fprw fwrite hello inits inline \
leak-0 leak-cycle leak-pool leak-tree leak-regroot leakotron \
+ linux-capget \
linux-syslog-syscall \
linux-syscalls-2007 \
linux-timerfd-syscall \
Added: trunk/memcheck/tests/linux-capget.c
===================================================================
--- trunk/memcheck/tests/linux-capget.c (rev 0)
+++ trunk/memcheck/tests/linux-capget.c 2008-08-27 17:41:06 UTC (rev 8553)
@@ -0,0 +1,50 @@
+#if defined(linux)
+
+
+#include <stdio.h> /* printf() */
+#include <unistd.h> /* syscall() */
+#include <sys/syscall.h> /* __NR_capget */
+#include <linux/capability.h> /* _LINUX_CAPABILITY_VERSION */
+
+
+int main()
+{
+ struct __user_cap_header_struct h;
+ struct __user_cap_data_struct d;
+ int syscall_result;
+
+ h.version = _LINUX_CAPABILITY_VERSION;
+ h.pid = 0;
+ syscall_result = syscall(__NR_capget, &h, &d);
+ if (syscall_result >= 0)
+ {
+ fprintf(stderr,
+ "capget result:\n"
+ "effective %#x\n"
+ "permitted %#x\n"
+ "inheritable %#x\n",
+ d.effective,
+ d.permitted,
+ d.inheritable);
+ }
+ else
+ {
+ perror("capget");
+ }
+ return 0;
+}
+
+
+#else
+
+
+#include <stdio.h>
+
+int main()
+{
+ fprintf(stderr, "This program is Linux-specific\n");
+ return 0;
+}
+
+
+#endif
Added: trunk/memcheck/tests/linux-capget.stderr.exp
===================================================================
--- trunk/memcheck/tests/linux-capget.stderr.exp (rev 0)
+++ trunk/memcheck/tests/linux-capget.stderr.exp 2008-08-27 17:41:06 UTC (rev 8553)
@@ -0,0 +1,11 @@
+
+capget result:
+effective 0
+permitted 0
+inheritable 0
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
+malloc/free: in use at exit: ... bytes in ... blocks.
+malloc/free: ... allocs, ... frees, ... bytes allocated.
+For a detailed leak analysis, rerun with: --leak-check=yes
+For counts of detected errors, rerun with: -v
Added: trunk/memcheck/tests/linux-capget.vgtest
===================================================================
--- trunk/memcheck/tests/linux-capget.vgtest (rev 0)
+++ trunk/memcheck/tests/linux-capget.vgtest 2008-08-27 17:41:06 UTC (rev 8553)
@@ -0,0 +1,2 @@
+prog: linux-capget
+stderr_filter: filter_allocs
|
|
From: <sv...@va...> - 2008-08-27 13:34:53
|
Author: sewardj
Date: 2008-08-27 14:35:02 +0100 (Wed, 27 Aug 2008)
New Revision: 8552
Log:
Avoid a large amount of dynamic memory allocation for
instruction-instance hash tables, by using, in the first instance, a
fixed table that lives inside the StackFrame structure.
Modified:
branches/SGCHECK/exp-sgcheck/sg_main.c
Modified: branches/SGCHECK/exp-sgcheck/sg_main.c
===================================================================
--- branches/SGCHECK/exp-sgcheck/sg_main.c 2008-08-27 13:08:26 UTC (rev 8551)
+++ branches/SGCHECK/exp-sgcheck/sg_main.c 2008-08-27 13:35:02 UTC (rev 8552)
@@ -996,6 +996,8 @@
IInstance;
+#define N_HTAB_FIXED 16
+
typedef
struct _StackFrame {
/* The sp when the frame was created, so we know when to get rid
@@ -1019,6 +1021,11 @@
that an IInstance with a .insn_addr of zero is interpreted to
mean that hash table slot is unused. This means we can't
store an IInstance for address zero. */
+ /* Note that htab initially points to htab_fixed. If htab_fixed
+ turns out not to be big enough then htab is made to point to
+ dynamically allocated memory. But it's often the case that
+ htab_fixed is big enough, so this optimisation saves a huge
+ number of pc_malloc/pc_free call pairs. */
IInstance* htab;
UWord htab_size; /* size of hash table, MAY ONLY BE A POWER OF 2 */
UWord htab_used; /* number of hash table slots currently in use */
@@ -1027,6 +1034,8 @@
Addr sp_at_call;
Addr fp_at_call;
XArray* /* of Addr */ blocks_added_by_call;
+ /* See comment just above */
+ IInstance htab_fixed[N_HTAB_FIXED];
}
StackFrame;
@@ -1111,8 +1120,8 @@
static void initialise_hash_table ( StackFrame* sf )
{
UWord i;
- sf->htab_size = 16; /* initial hash table size */
- sf->htab = pc_malloc(sf->htab_size * sizeof(IInstance));
+ sf->htab_size = N_HTAB_FIXED; /* initial hash table size */
+ sf->htab = &sf->htab_fixed[0];
tl_assert(sf->htab);
sf->htab_used = 0;
for (i = 0; i < sf->htab_size; i++)
@@ -1158,7 +1167,8 @@
tl_assert(new_htab[ix].insn_addr != 0);
}
/* all entries copied; free old table. */
- pc_free(old_htab);
+ if (old_htab != &sf->htab_fixed[0])
+ pc_free(old_htab);
sf->htab = new_htab;
sf->htab_size = new_size;
/* check sf->htab_used is correct. Optional and a bit expensive
@@ -1663,7 +1673,8 @@
if (sp_now <= innermost->creation_sp) break;
//VG_(printf)("UNWIND dump %p\n", innermost->creation_sp);
tl_assert(innermost->htab);
- pc_free(innermost->htab);
+ if (innermost->htab != &innermost->htab_fixed[0])
+ pc_free(innermost->htab);
/* be on the safe side */
innermost->creation_sp = 0;
innermost->htab = NULL;
|
|
From: <sv...@va...> - 2008-08-27 13:08:18
|
Author: sewardj
Date: 2008-08-27 14:08:26 +0100 (Wed, 27 Aug 2008)
New Revision: 8551
Log:
Performance improvements for call-intensive code:
* make the instr-instance hash table have a much bigger initial
size, so it doesn't have to be resized so much
* for call instructions, if there are no blocks visible in the local
frame at the point of the call instruction, pass NULL pointers
around appropriately, rather than empty XArrays -- a common case.
Modified:
branches/SGCHECK/exp-sgcheck/sg_main.c
Modified: branches/SGCHECK/exp-sgcheck/sg_main.c
===================================================================
--- branches/SGCHECK/exp-sgcheck/sg_main.c 2008-08-27 10:57:08 UTC (rev 8550)
+++ branches/SGCHECK/exp-sgcheck/sg_main.c 2008-08-27 13:08:26 UTC (rev 8551)
@@ -824,6 +824,7 @@
QCache;
static void QCache__invalidate ( QCache* qc ) {
+ tl_assert(qc->nInUse >= 0);
qc->nInUse = 0;
}
@@ -1110,7 +1111,7 @@
static void initialise_hash_table ( StackFrame* sf )
{
UWord i;
- sf->htab_size = 4; /* initial hash table size */
+ sf->htab_size = 16; /* initial hash table size */
sf->htab = pc_malloc(sf->htab_size * sizeof(IInstance));
tl_assert(sf->htab);
sf->htab_used = 0;
@@ -1243,8 +1244,10 @@
Addr sp, Addr fp
)
{
- XArray* res = VG_(newXA)( pc_malloc, pc_free, sizeof(Addr) );
+ XArray* res;
Word i, n = VG_(sizeXA)( blocks );
+ tl_assert(n > 0);
+ res = VG_(newXA)( pc_malloc, pc_free, sizeof(Addr) );
for (i = 0; i < n; i++) {
StackBlock* blk = VG_(indexXA)( blocks, i );
Addr ea = calculate_StackBlock_EA( blk, sp, fp );
@@ -1352,10 +1355,14 @@
out:
{ Word i;
QCache* cache = &qcaches[tid];
- Word ip = cache->nInUse/2;
+ Word ip = cache->nInUse / 2; /* doesn't seem critical */
- if (0) QCache__pp(cache, "before upd");
+ static UWord ctr = 0;
+ Bool show = False;
+ if (0 == (ctr++ & 0x1FFFFF)) show = True;
+ if (show) QCache__pp(cache, "before upd");
+
if (cache->nInUse < N_QCACHE)
cache->nInUse++;
for (i = cache->nInUse-1; i > ip; i--) {
@@ -1434,7 +1441,7 @@
tl_assert(0);
}
- if (0) QCache__pp(cache, "after upd");
+ if (show) QCache__pp(cache, "after upd");
}
}
@@ -1534,7 +1541,6 @@
tl_assert(caller);
if (caller->outer) { /* "this is not the outermost frame" */
- tl_assert(descrs_at_call_insn);
tl_assert(caller->outer->inner == caller);
tl_assert(caller->outer->depth >= 0);
tl_assert(1 + caller->outer->depth == caller->depth);
@@ -1546,15 +1552,17 @@
caller->fp_at_call = fp_at_call_insn;
if (descrs_at_call_insn) {
+ tl_assert( VG_(sizeXA)(descrs_at_call_insn) > 0 );
caller->blocks_added_by_call
= calculate_StackBlock_EAs( descrs_at_call_insn,
sp_at_call_insn, fp_at_call_insn );
- add_blocks_to_StackTree( siTrees[tid],
- descrs_at_call_insn,
- caller->blocks_added_by_call,
- caller->depth /* stack depth at which
- these blocks are
- considered to exist*/ );
+ if (caller->blocks_added_by_call)
+ add_blocks_to_StackTree( siTrees[tid],
+ descrs_at_call_insn,
+ caller->blocks_added_by_call,
+ caller->depth /* stack depth at which
+ these blocks are
+ considered to exist*/ );
if (1) {
UWord s = VG_(sizeFM)( siTrees[tid] );
UWord g = VG_(sizeFM)( giTree );
@@ -1671,11 +1679,13 @@
the call. */
if (innermost->outer) { /* not at the outermost frame */
- tl_assert(innermost->blocks_added_by_call != NULL);
- del_blocks_from_StackTree( siTrees[tid],
- innermost->blocks_added_by_call );
- VG_(deleteXA)( innermost->blocks_added_by_call );
- innermost->blocks_added_by_call = NULL;
+ if (innermost->blocks_added_by_call == NULL) {
+ } else {
+ del_blocks_from_StackTree( siTrees[tid],
+ innermost->blocks_added_by_call );
+ VG_(deleteXA)( innermost->blocks_added_by_call );
+ innermost->blocks_added_by_call = NULL;
+ }
}
/* That completes the required tidying of the interval tree
associated with the frame we just removed. */
@@ -1956,6 +1966,8 @@
tl_assert(curr_IP_known);
frameBlocks = get_StackBlocks_for_IP( curr_IP );
tl_assert(frameBlocks);
+ if (VG_(sizeXA)(frameBlocks) == 0)
+ frameBlocks = NULL;
args
= mkIRExprVec_5(
IRExpr_RdTmp(sp_post_call_insn),
|
|
From: <sv...@va...> - 2008-08-27 11:16:38
|
Author: sewardj
Date: 2008-08-27 11:57:08 +0100 (Wed, 27 Aug 2008)
New Revision: 8550
Log:
Add a per-thread query cache, which substantially improves performance
by avoiding searching in the interval trees. Unfortunately does not
improve performance as much as is really required, and is rather
complex.
Modified:
branches/SGCHECK/coregrind/m_wordfm.c
branches/SGCHECK/exp-sgcheck/sg_main.c
branches/SGCHECK/include/pub_tool_wordfm.h
Modified: branches/SGCHECK/coregrind/m_wordfm.c
===================================================================
--- branches/SGCHECK/coregrind/m_wordfm.c 2008-08-26 15:33:36 UTC (rev 8549)
+++ branches/SGCHECK/coregrind/m_wordfm.c 2008-08-27 10:57:08 UTC (rev 8550)
@@ -415,6 +415,36 @@
}
}
+static
+void avl_find_bounds ( AvlNode* t,
+ /*OUT*/UWord* kMinP, /*OUT*/UWord* kMaxP,
+ UWord minKey, UWord maxKey, UWord key,
+ Word(*kCmp)(UWord,UWord) )
+{
+ UWord lowerBound = minKey;
+ UWord upperBound = maxKey;
+ while (t) {
+ Word cmpresS = kCmp ? kCmp(t->key, key)
+ : cmp_unsigned_Words(t->key, key);
+ if (cmpresS < 0) {
+ lowerBound = t->key;
+ t = t->child[1];
+ continue;
+ }
+ if (cmpresS > 0) {
+ upperBound = t->key;
+ t = t->child[0];
+ continue;
+ }
+ /* We should never get here. If we do, it means the given key
+ is actually present in the tree, which means the original
+ call was invalid -- an error on the caller's part. */
+ tl_assert(0);
+ }
+ *kMinP = lowerBound;
+ *kMaxP = upperBound;
+}
+
// Clear the iterator stack.
static void stackClear(WordFM* fm)
{
@@ -619,6 +649,14 @@
}
}
+// See comment in pub_tool_wordfm.h for explanation
+void VG_(findBoundsFM)( WordFM* fm,
+ /*OUT*/UWord* kMinP, /*OUT*/UWord* kMaxP,
+ UWord minKey, UWord maxKey, UWord key )
+{
+ avl_find_bounds( fm->root, kMinP, kMaxP, minKey, maxKey, key, fm->kCmp );
+}
+
UWord VG_(sizeFM) ( WordFM* fm )
{
// Hmm, this is a bad way to do this
Modified: branches/SGCHECK/exp-sgcheck/sg_main.c
===================================================================
--- branches/SGCHECK/exp-sgcheck/sg_main.c 2008-08-26 15:33:36 UTC (rev 8549)
+++ branches/SGCHECK/exp-sgcheck/sg_main.c 2008-08-27 10:57:08 UTC (rev 8550)
@@ -117,11 +117,22 @@
return aBig <= aSmall && aSmall + nSmall <= aBig + nBig;
}
+inline
static Word Word__abs ( Word w ) {
return w < 0 ? -w : w;
}
+inline
+static Addr Addr__min ( Addr a1, Addr a2 ) {
+ return a1 < a2 ? a1 : a2;
+}
+inline
+static Addr Addr__max ( Addr a1, Addr a2 ) {
+ return a1 < a2 ? a2 : a1;
+}
+
+
//////////////////////////////////////////////////////////////
// //
// StackBlocks Persistent Cache //
@@ -647,10 +658,194 @@
//////////////////////////////////////////////////////////////
// //
+// Invar //
+// //
+//////////////////////////////////////////////////////////////
+
+/* An invariant, as resulting from watching the destination of a
+ memory referencing instruction. Initially is Inv_Unset until the
+ instruction makes a first access. */
+
+typedef
+ enum {
+ Inv_Unset=1, /* not established yet */
+ Inv_Unknown, /* unknown location */
+ Inv_Stack0, /* array-typed stack block in innermost frame */
+ Inv_StackN, /* array-typed stack block in non-innermost frame */
+ Inv_Global, /* array-typed global block */
+ }
+ InvarTag;
+
+typedef
+ struct {
+ InvarTag tag;
+ union {
+ struct {
+ } Unset;
+ struct {
+ } Unknown;
+ struct {
+ Addr addr;
+ SizeT szB;
+ StackBlock* descr;
+ } Stack0; /* innermost stack frame */
+ struct {
+ /* Pointer to a node in the interval tree for
+ this thread. */
+ StackTreeNode* nd;
+ } StackN; /* non-innermost stack frame */
+ struct {
+ /* Pointer to a GlobalBlock in the interval tree of
+ global blocks. */
+ GlobalTreeNode* nd;
+ } Global;
+ }
+ Inv;
+ }
+ Invar;
+
+/* Partial debugging printing for an Invar. */
+static void pp_Invar ( Invar* i )
+{
+ switch (i->tag) {
+ case Inv_Unset:
+ VG_(printf)("Unset");
+ break;
+ case Inv_Unknown:
+ VG_(printf)("Unknown");
+ break;
+ case Inv_Stack0:
+ VG_(printf)("Stack0 [%#lx,+%lu)",
+ i->Inv.Stack0.addr, i->Inv.Stack0.szB);
+ break;
+ case Inv_StackN:
+ VG_(printf)("StackN [%#lx,+%lu)",
+ i->Inv.StackN.nd->addr, i->Inv.StackN.nd->szB);
+ break;
+ case Inv_Global:
+ VG_(printf)("Global [%#lx,+%lu)",
+ i->Inv.Global.nd->addr, i->Inv.Global.nd->szB);
+ break;
+ default:
+ tl_assert(0);
+ }
+}
+
+/* Compare two Invars for equality. */
+static Bool eq_Invar ( Invar* i1, Invar* i2 )
+{
+ tl_assert(i1->tag != Inv_Unset);
+ tl_assert(i2->tag != Inv_Unset);
+ if (i1->tag != i2->tag)
+ return False;
+ switch (i1->tag) {
+ case Inv_Unknown:
+ return True;
+ case Inv_Stack0:
+ return i1->Inv.Stack0.addr == i2->Inv.Stack0.addr
+ && i1->Inv.Stack0.szB == i2->Inv.Stack0.szB;
+ case Inv_StackN:
+ return i1->Inv.StackN.nd == i2->Inv.StackN.nd;
+ case Inv_Global:
+ return i1->Inv.Global.nd == i2->Inv.Global.nd;
+ default:
+ tl_assert(0);
+ }
+ /*NOTREACHED*/
+ tl_assert(0);
+}
+
+/* Print selected parts of an Invar, suitable for use in error
+ messages. */
+static void show_Invar( HChar* buf, Word nBuf, Invar* inv, Word depth )
+{
+ HChar* str;
+ tl_assert(nBuf >= 96);
+ buf[0] = 0;
+ switch (inv->tag) {
+ case Inv_Unknown:
+ VG_(sprintf)(buf, "%s", "unknown");
+ break;
+ case Inv_Stack0:
+ str = "array";
+ VG_(sprintf)(buf, "stack %s \"%s\" in this frame",
+ str, inv->Inv.Stack0.descr->name );
+ break;
+ case Inv_StackN:
+ str = "array";
+ VG_(sprintf)(buf, "stack %s \"%s\" in frame %lu back from here",
+ str, inv->Inv.StackN.nd->descr->name,
+ depth - inv->Inv.StackN.nd->depth );
+ break;
+ case Inv_Global:
+ str = "array";
+ VG_(sprintf)(buf, "global %s \"%s\" in object with soname \"%s\"",
+ str, inv->Inv.Global.nd->descr->name,
+ inv->Inv.Global.nd->descr->soname );
+ break;
+ case Inv_Unset:
+ VG_(sprintf)(buf, "%s", "Unset!");
+ break;
+ default:
+ tl_assert(0);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////
+// //
// our globals //
// //
//////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////
+///
+
+#define N_QCACHE 16
+
+/* Powers of two only, else the result will be chaos */
+#define QCACHE_ADVANCE_EVERY 16
+
+/* Per-thread query cache. Note that the invar can only be Inv_StackN
+ (but not Inv_Stack0), Inv_Global or Inv_Unknown. */
+typedef
+ struct {
+ Addr addr;
+ SizeT szB;
+ Invar inv;
+ }
+ QCElem;
+
+typedef
+ struct {
+ Word nInUse;
+ QCElem elems[N_QCACHE];
+ }
+ QCache;
+
+static void QCache__invalidate ( QCache* qc ) {
+ qc->nInUse = 0;
+}
+
+static void QCache__pp ( QCache* qc, HChar* who )
+{
+ Word i;
+ VG_(printf)("<<< QCache with %ld elements (%s)\n", qc->nInUse, who);
+ for (i = 0; i < qc->nInUse; i++) {
+ VG_(printf)(" [%#lx,+%#lx) ", qc->elems[i].addr, qc->elems[i].szB);
+ pp_Invar(&qc->elems[i].inv);
+ VG_(printf)("\n");
+ }
+ VG_(printf)(">>>\n");
+}
+
+static ULong stats__qcache_queries = 0;
+static ULong stats__qcache_misses = 0;
+static ULong stats__qcache_probes = 0;
+
+///
+//////////////////////////////////////////////////////////////
+
/* Each thread has:
* a shadow stack of StackFrames, which is a double-linked list
* an stack block interval tree
@@ -659,12 +854,23 @@
static WordFM* /* StackTreeNode */ siTrees[VG_N_THREADS];
+static QCache qcaches[VG_N_THREADS];
+
+
/* Additionally, there is one global variable interval tree
for the entire process.
*/
static WordFM* /* GlobalTreeNode */ giTree;
+static void invalidate_all_QCaches ( void )
+{
+ Word i;
+ for (i = 0; i < VG_N_THREADS; i++) {
+ QCache__invalidate( &qcaches[i] );
+ }
+}
+
static void ourGlobals_init ( void )
{
Word i;
@@ -672,6 +878,7 @@
shadowStacks[i] = NULL;
siTrees[i] = NULL;
}
+ invalidate_all_QCaches();
giTree = VG_(newFM)( pc_malloc, pc_free,
(Word(*)(UWord,UWord))cmp_intervals_GlobalTreeNode );
}
@@ -757,120 +964,12 @@
Inv_Unknown. */
tl_assert(len > 0);
preen_Invars( a, len, False/*!isHeap*/ );
+ invalidate_all_QCaches();
}
//////////////////////////////////////////////////////////////
// //
-// Invar //
-// //
-//////////////////////////////////////////////////////////////
-
-/* An invariant, as resulting from watching the destination of a
- memory referencing instruction. Initially is Inv_Unset until the
- instruction makes a first access. */
-
-typedef
- enum {
- Inv_Unset=1, /* not established yet */
- Inv_Unknown, /* unknown location */
- Inv_Stack0, /* array-typed stack block in innermost frame */
- Inv_StackN, /* array-typed stack block in non-innermost frame */
- Inv_Global, /* array-typed global block */
- }
- InvarTag;
-
-typedef
- struct {
- InvarTag tag;
- union {
- struct {
- } Unset;
- struct {
- } Unknown;
- struct {
- Addr addr;
- SizeT szB;
- StackBlock* descr;
- } Stack0; /* innermost stack frame */
- struct {
- /* Pointer to a node in the interval tree for
- this thread. */
- StackTreeNode* nd;
- } StackN; /* non-innermost stack frame */
- struct {
- /* Pointer to a GlobalBlock in the interval tree of
- global blocks. */
- GlobalTreeNode* nd;
- } Global;
- }
- Inv;
- }
- Invar;
-
-/* Compare two Invars for equality. */
-static Bool eq_Invar ( Invar* i1, Invar* i2 )
-{
- tl_assert(i1->tag != Inv_Unset);
- tl_assert(i2->tag != Inv_Unset);
- if (i1->tag != i2->tag)
- return False;
- switch (i1->tag) {
- case Inv_Unknown:
- return True;
- case Inv_Stack0:
- return i1->Inv.Stack0.addr == i2->Inv.Stack0.addr
- && i1->Inv.Stack0.szB == i2->Inv.Stack0.szB;
- case Inv_StackN:
- return i1->Inv.StackN.nd == i2->Inv.StackN.nd;
- case Inv_Global:
- return i1->Inv.Global.nd == i2->Inv.Global.nd;
- default:
- tl_assert(0);
- }
- /*NOTREACHED*/
- tl_assert(0);
-}
-
-/* Print selected parts of an Invar, suitable for use in error
- messages. */
-static void show_Invar( HChar* buf, Word nBuf, Invar* inv, Word depth )
-{
- HChar* str;
- tl_assert(nBuf >= 96);
- buf[0] = 0;
- switch (inv->tag) {
- case Inv_Unknown:
- VG_(sprintf)(buf, "%s", "unknown");
- break;
- case Inv_Stack0:
- str = "array";
- VG_(sprintf)(buf, "stack %s \"%s\" in this frame",
- str, inv->Inv.Stack0.descr->name );
- break;
- case Inv_StackN:
- str = "array";
- VG_(sprintf)(buf, "stack %s \"%s\" in frame %lu back from here",
- str, inv->Inv.StackN.nd->descr->name,
- depth - inv->Inv.StackN.nd->depth );
- break;
- case Inv_Global:
- str = "array";
- VG_(sprintf)(buf, "global %s \"%s\" in object with soname \"%s\"",
- str, inv->Inv.Global.nd->descr->name,
- inv->Inv.Global.nd->descr->soname );
- break;
- case Inv_Unset:
- VG_(sprintf)(buf, "%s", "Unset!");
- break;
- default:
- tl_assert(0);
- }
-}
-
-
-//////////////////////////////////////////////////////////////
-// //
// StackFrame //
// //
//////////////////////////////////////////////////////////////
@@ -1185,6 +1284,32 @@
}
}
}
+
+ /* Look in this thread's query cache */
+ { Word i;
+ QCache* cache = &qcaches[tid];
+ static UWord ctr = 0;
+ stats__qcache_queries++;
+ for (i = 0; i < cache->nInUse; i++) {
+tl_assert(cache->elems[i].addr + cache->elems[i].szB != 0);
+ stats__qcache_probes++;
+ if (is_subinterval_of(cache->elems[i].addr,
+ cache->elems[i].szB, ea, szB)) {
+ if (i > 0
+ && (ctr++ & (QCACHE_ADVANCE_EVERY-1)) == 0) {
+ QCElem tmp;
+ tmp = cache->elems[i-1];
+ cache->elems[i-1] = cache->elems[i];
+ cache->elems[i] = tmp;
+ i--;
+ }
+ *inv = cache->elems[i].inv;
+ return;
+ }
+ }
+ stats__qcache_misses++;
+ }
+
/* Ok, so it's not a block in the top frame. Perhaps it's a block
in some calling frame? Consult this thread's stack-block
interval tree to find out. */
@@ -1199,8 +1324,8 @@
/* found it */
inv->tag = Inv_StackN;
inv->Inv.StackN.nd = nd;
- stats__classify_StackN++;
- return;
+ stats__classify_StackN++;
+ goto out;
}
}
/* Not in a stack block. Try the global pool. */
@@ -1212,16 +1337,106 @@
nd = NULL;
}
if (nd) {
- /* found it */
+ /* found it */
inv->tag = Inv_Global;
inv->Inv.Global.nd = nd;
stats__classify_Global++;
- return;
+ goto out;
}
}
/* No idea - give up. */
inv->tag = Inv_Unknown;
stats__classify_Unknown++;
+
+ /* Update the cache */
+ out:
+ { Word i;
+ QCache* cache = &qcaches[tid];
+ Word ip = cache->nInUse/2;
+
+ if (0) QCache__pp(cache, "before upd");
+
+ if (cache->nInUse < N_QCACHE)
+ cache->nInUse++;
+ for (i = cache->nInUse-1; i > ip; i--) {
+ cache->elems[i] = cache->elems[i-1];
+ }
+
+ switch (inv->tag) {
+ case Inv_Global:
+ cache->elems[ip].addr = inv->Inv.Global.nd->addr;
+ cache->elems[ip].szB = inv->Inv.Global.nd->szB;
+ cache->elems[ip].inv = *inv;
+ break;
+ case Inv_StackN:
+ cache->elems[ip].addr = inv->Inv.StackN.nd->addr;
+ cache->elems[ip].szB = inv->Inv.StackN.nd->szB;
+ cache->elems[ip].inv = *inv;
+ break;
+ case Inv_Unknown: {
+ /* This is more complex. We need to figure out the
+ intersection of the "holes" in the global and stack
+ interval trees into which [ea,ea+szB) falls. */
+ StackTreeNode sNegInf, sPosInf, sKey, *sLB, *sUB;
+ GlobalTreeNode gNegInf, gPosInf, gKey, *gLB, *gUB;
+ Addr gMin, gMax, sMin, sMax, uMin, uMax;
+ sNegInf.addr = 0;
+ sNegInf.szB = 1;
+ sPosInf.addr = ~(UWord)0;
+ sPosInf.szB = 1;
+ gNegInf.addr = 0;
+ gNegInf.szB = 1;
+ gPosInf.addr = ~(UWord)0;
+ gPosInf.szB = 1;
+ sKey.addr = ea;
+ sKey.szB = szB;
+ gKey.addr = ea;
+ gKey.szB = szB;
+ if (0) VG_(printf)("Tree sizes %ld %ld\n",
+ VG_(sizeFM)(siTrees[tid]), VG_(sizeFM)(giTree));
+ VG_(findBoundsFM)( siTrees[tid],
+ (UWord*)&sLB, (UWord*)&sUB,
+ (UWord)&sNegInf, (UWord)&sPosInf,
+ (UWord)&sKey );
+ VG_(findBoundsFM)( giTree,
+ (UWord*)&gLB, (UWord*)&gUB,
+ (UWord)&gNegInf, (UWord)&gPosInf,
+ (UWord)&gKey );
+ sMin = sLB == &sNegInf ? 0 : (sLB->addr + sLB->szB);
+ sMax = sUB == &sPosInf ? ~(UWord)0 : (sUB->addr - 1);
+ gMin = gLB == &gNegInf ? 0 : (gLB->addr + gLB->szB);
+ gMax = gUB == &gPosInf ? ~(UWord)0 : (gUB->addr - 1);
+ if (0) VG_(printf)("sMin %lx sMax %lx gMin %lx gMax %lx\n",
+ sMin, sMax, gMin, gMax);
+ /* [sMin,sMax] and [gMin,gMax] must both contain
+ [ea,ea+szB) (right?) That implies they must overlap at
+ at least over [ea,ea+szB). */
+ tl_assert(sMin <= ea && ea+szB-1 <= sMax);
+ tl_assert(gMin <= ea && ea+szB-1 <= gMax);
+ /* So now compute their intersection. */
+ uMin = Addr__max( sMin, gMin );
+ uMax = Addr__min( sMax, gMax );
+ if (0) VG_(printf)("uMin %lx uMax %lx\n", uMin, uMax);
+ tl_assert(uMin <= uMax);
+ tl_assert(uMin <= ea && ea+szB-1 <= uMax);
+ /* Finally, we can park [uMin,uMax] in the cache. However,
+ if uMin is 0 and uMax is ~0, we can't represent the
+ difference; hence fudge uMax. */
+ if (uMin < uMax && uMax == ~(UWord)0)
+ uMax--;
+ cache->elems[ip].addr = uMin;
+ cache->elems[ip].szB = uMax - uMin + 1;
+ cache->elems[ip].inv = *inv;
+ break;
+ }
+ default:
+ /* We should only be caching info for the above 3 cases */
+ tl_assert(0);
+ }
+
+ if (0) QCache__pp(cache, "after upd");
+
+ }
}
@@ -1340,7 +1555,7 @@
caller->depth /* stack depth at which
these blocks are
considered to exist*/ );
- if (0) {
+ if (1) {
UWord s = VG_(sizeFM)( siTrees[tid] );
UWord g = VG_(sizeFM)( giTree );
Bool sb = s > stats__max_sitree_size;
@@ -1377,8 +1592,12 @@
callee->fp_at_call = 0; // .. these 3 initialisations are ..
callee->blocks_added_by_call = NULL; // .. just for cleanness
+ /* record the new running stack frame */
shadowStacks[tid] = callee;
+ /* and this thread's query cache is now invalid */
+ QCache__invalidate( &qcaches[tid] );
+
if (0)
{ Word d = callee->depth;
HChar fnname[80];
@@ -1420,10 +1639,11 @@
__attribute__((noinline))
static void shadowStack_unwind ( ThreadId tid, Addr sp_now )
{
- StackFrame* innermost;
+ StackFrame *innermost, *innermostOrig;
tl_assert(is_sane_TId(tid));
innermost = shadowStacks[tid];
tl_assert(innermost);
+ innermostOrig = innermost;
//VG_(printf)("UNWIND sp_new = %p\n", sp_now);
while (1) {
if (!innermost->outer)
@@ -1472,7 +1692,12 @@
}
tl_assert(innermost);
- shadowStacks[tid] = innermost;
+
+ if (innermost != innermostOrig) {
+ shadowStacks[tid] = innermost;
+ /* this thread's query cache is now invalid */
+ QCache__invalidate( &qcaches[tid] );
+ }
}
@@ -2052,7 +2277,13 @@
"%'llu Invars preened, of which %'llu changed",
stats__Invars_preened, stats__Invars_changed);
VG_(message)(Vg_DebugMsg,
- " t_i_b_MT: %'12llu", stats__t_i_b_empty);
+ " t_i_b_MT: %'12llu", stats__t_i_b_empty);
+ VG_(message)(Vg_DebugMsg,
+ " qcache: %'12llu queries", stats__qcache_queries );
+ VG_(message)(Vg_DebugMsg,
+ " qcache: %'12llu probes", stats__qcache_probes );
+ VG_(message)(Vg_DebugMsg,
+ " qcache: %'12llu misses", stats__qcache_misses );
VG_(message)(Vg_DebugMsg, "");
}
Modified: branches/SGCHECK/include/pub_tool_wordfm.h
===================================================================
--- branches/SGCHECK/include/pub_tool_wordfm.h 2008-08-26 15:33:36 UTC (rev 8549)
+++ branches/SGCHECK/include/pub_tool_wordfm.h 2008-08-27 10:57:08 UTC (rev 8550)
@@ -98,6 +98,16 @@
Bool VG_(lookupFM) ( WordFM* fm,
/*OUT*/UWord* keyP, /*OUT*/UWord* valP, UWord key );
+// Find the closest key values bracketing the given key, assuming the
+// given key is not present in the map (this is asserted for). minKey
+// and maxKey are the minimum and maximum possible key values. The
+// resulting bracket values are returned in *kMinP and *kMaxP. It
+// follows that if fm is empty then the returned values are simply
+// minKey and maxKey.
+void VG_(findBoundsFM)( WordFM* fm,
+ /*OUT*/UWord* kMinP, /*OUT*/UWord* kMaxP,
+ UWord minKey, UWord maxKey, UWord key );
+
// How many elements are there in fm?
UWord VG_(sizeFM) ( WordFM* fm );
|
|
From: Julian S. <js...@ac...> - 2008-08-27 07:09:36
|
On Tuesday 26 August 2008, Dave Nomura wrote: > Is there a *.xsd or *.dtd that describes the XML that is output by the > --xml option? No; but there is docs/internals/xml-output.txt which describes it. > Are there any consumers of valgrind's xml in the valgrind source tree? No. > Other consumers? Two, afaik: * Valkyie, a Qt-based GUI: http://www.open-works.net/projects/valkyrie.html * Memcheckview, a(nother) Qt-based GUI: https://computation.llnl.gov/casc/tool_gear/memcheckview.html > Is there any documentation or suggestions for developing an XML consumer > of valgrind --xml ? I don't think so. Both of the above tools use a Qt class for parsing the XML. I don't know any details though. J |
|
From: Tom H. <th...@cy...> - 2008-08-27 03:08:01
|
Nightly build on alvis ( i686, Red Hat 7.3 ) started at 2008-08-27 03:15: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 == 345 tests, 60 stderr failures, 1 stdout failure, 29 post failures == memcheck/tests/file_locking (stderr) memcheck/tests/leak-0 (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-regroot (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/long_namespace_xml (stderr) memcheck/tests/malloc_free_fill (stderr) memcheck/tests/origin1-yes (stderr) memcheck/tests/origin4-many (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/varinfo1 (stderr) memcheck/tests/varinfo2 (stderr) memcheck/tests/varinfo3 (stderr) memcheck/tests/varinfo4 (stderr) memcheck/tests/varinfo5 (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/bug152022 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) memcheck/tests/x86/xor-undef-x86 (stderr) memcheck/tests/xml1 (stderr) massif/tests/alloc-fns-A (post) massif/tests/alloc-fns-B (post) massif/tests/basic (post) massif/tests/basic2 (post) massif/tests/big-alloc (post) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) massif/tests/custom_alloc (post) massif/tests/deep-A (post) massif/tests/deep-B (stderr) massif/tests/deep-B (post) massif/tests/deep-C (stderr) massif/tests/deep-C (post) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/insig (post) massif/tests/long-names (post) massif/tests/long-time (post) massif/tests/new-cpp (post) massif/tests/null (post) massif/tests/one (post) massif/tests/overloaded-new (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) massif/tests/realloc (stderr) massif/tests/realloc (post) massif/tests/thresholds_0_0 (post) massif/tests/thresholds_0_10 (post) massif/tests/thresholds_10_0 (post) massif/tests/thresholds_10_10 (post) massif/tests/thresholds_5_0 (post) massif/tests/thresholds_5_10 (post) massif/tests/zero1 (post) massif/tests/zero2 (post) none/tests/blockfault (stderr) none/tests/mremap2 (stdout) none/tests/shell (stderr) none/tests/shell_valid1 (stderr) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (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/hg06_readshared (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc02_simple_tls (stderr) helgrind/tests/tc03_re_excl (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc07_hbl1 (stderr) helgrind/tests/tc08_hbl2 (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc11_XCHG (stderr) helgrind/tests/tc12_rwl_trivial (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc18_semabuse (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) helgrind/tests/tc24_nonzero_sem (stderr) |
|
From: Tom H. <th...@cy...> - 2008-08-27 02:56:14
|
Nightly build on aston ( x86_64, Fedora Core 5 ) started at 2008-08-27 03:20: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 == 443 tests, 8 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) 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/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 == 443 tests, 8 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/file_locking (stderr) 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) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Wed Aug 27 03:38:24 2008 --- new.short Wed Aug 27 03:56:23 2008 *************** *** 8,10 **** ! == 443 tests, 8 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/file_locking (stderr) --- 8,10 ---- ! == 443 tests, 8 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/file_locking (stderr) *************** *** 15,16 **** --- 15,17 ---- none/tests/mremap2 (stdout) + helgrind/tests/tc08_hbl2 (stdout) helgrind/tests/tc20_verifywrap (stderr) |