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
(7) |
2
(9) |
3
(7) |
4
(5) |
5
(5) |
6
(16) |
|
7
(20) |
8
(9) |
9
(15) |
10
(11) |
11
(13) |
12
(12) |
13
(10) |
|
14
(13) |
15
(6) |
16
(10) |
17
(12) |
18
(17) |
19
(3) |
20
(10) |
|
21
(11) |
22
(7) |
23
(6) |
24
(7) |
25
(5) |
26
(5) |
27
(14) |
|
28
(6) |
29
(4) |
30
(5) |
|
|
|
|
|
From: <sv...@va...> - 2008-09-09 23:10:24
|
Author: sewardj
Date: 2008-09-10 00:10:30 +0100 (Wed, 10 Sep 2008)
New Revision: 8595
Log:
Add a TyEntIndexCache type and mechanism, to speed up indexing
by compilation-unit offset, in type-entity arrays. For a large
test case, the cache achieves a hit rate of 82%.
Modified:
branches/YARD/coregrind/m_debuginfo/debuginfo.c
branches/YARD/coregrind/m_debuginfo/priv_tytypes.h
branches/YARD/coregrind/m_debuginfo/readdwarf3.c
branches/YARD/coregrind/m_debuginfo/storage.c
branches/YARD/coregrind/m_debuginfo/tytypes.c
branches/YARD/coregrind/m_main.c
Modified: branches/YARD/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/YARD/coregrind/m_debuginfo/debuginfo.c 2008-09-09 18:18:26 UTC (rev 8594)
+++ branches/YARD/coregrind/m_debuginfo/debuginfo.c 2008-09-09 23:10:30 UTC (rev 8595)
@@ -844,7 +844,7 @@
di = debugInfo_list;
while (di) {
di2 = di->next;
- VG_(printf)("XXX rm %p\n", di);
+ VG_(printf)("VG_(di_discard_ALL_debuginfo): deleting di %p\n", di);
free_DebugInfo( di );
di = di2;
}
Modified: branches/YARD/coregrind/m_debuginfo/priv_tytypes.h
===================================================================
--- branches/YARD/coregrind/m_debuginfo/priv_tytypes.h 2008-09-09 18:18:26 UTC (rev 8594)
+++ branches/YARD/coregrind/m_debuginfo/priv_tytypes.h 2008-09-09 23:10:30 UTC (rev 8595)
@@ -144,13 +144,6 @@
void ML_(pp_TyEnt_C_ishly)( XArray* /* of TyEnt */ tyents,
UWord cuOff );
-/* 'ents' is an XArray of TyEnts, sorted by their .cuOff fields. Find
- the entry which has .cuOff field as specified. Returns NULL if not
- found. Asserts if more than one entry has the specified .cuOff
- value. */
-TyEnt* ML_(TyEnts__index_by_cuOff) ( XArray* /* of TyEnt */ ents,
- UWord cuOff_to_find );
-
/* Generates a total ordering on TyEnts based only on their .cuOff
fields. */
Word ML_(TyEnt__cmp_by_cuOff_only) ( TyEnt* te1, TyEnt* te2 );
@@ -179,6 +172,40 @@
UWord ty_cuOff,
OffT offset );
+
+/* A fast-lookup cache for ML_(TyEnts__index_by_cuOff). Nothing
+ particularly surprising here; it's 2 way set associative, with some
+ number of ways, doesn't particularly have to be a power of 2. In
+ order to have a way to indicate an invalid entry, we set the second
+ value of the pair to NULL, and keep checking for it, since
+ unfortunately there's no obvious cuOff number that we could put in
+ the first word of the pair that could indicate an invalid entry.
+
+ 4096 arrived at as the best value for an E6600 loading Qt-4.4.1
+ Designer and all associated libraries, compiled by gcc-4.3.1,
+ -g -O, 64-bit, which is at least a moderately good stress test,
+ with the largest library being about 150MB.*/
+
+#define N_TYENT_INDEX_CACHE 4096
+
+typedef
+ struct {
+ struct { UWord cuOff0; TyEnt* ent0;
+ UWord cuOff1; TyEnt* ent1; }
+ ce[N_TYENT_INDEX_CACHE];
+ }
+ TyEntIndexCache;
+
+void ML_(TyEntIndexCache__invalidate) ( TyEntIndexCache* cache );
+
+/* 'ents' is an XArray of TyEnts, sorted by their .cuOff fields. Find
+ the entry which has .cuOff field as specified. Returns NULL if not
+ found. Asserts if more than one entry has the specified .cuOff
+ value. */
+TyEnt* ML_(TyEnts__index_by_cuOff) ( XArray* /* of TyEnt */ ents,
+ TyEntIndexCache* cache,
+ UWord cuOff_to_find );
+
#endif /* ndef __PRIV_TYTYPES_H */
/*--------------------------------------------------------------------*/
Modified: branches/YARD/coregrind/m_debuginfo/readdwarf3.c
===================================================================
--- branches/YARD/coregrind/m_debuginfo/readdwarf3.c 2008-09-09 18:18:26 UTC (rev 8594)
+++ branches/YARD/coregrind/m_debuginfo/readdwarf3.c 2008-09-09 23:10:30 UTC (rev 8595)
@@ -2222,7 +2222,7 @@
typeE.cuOff = posn;
typeE.tag = Te_TyEnum;
typeE.Te.TyEnum.atomRs
- = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ptD.1",
+ = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ptD.enum_type.1",
ML_(dinfo_free),
sizeof(UWord) );
while (True) {
@@ -2233,7 +2233,7 @@
cc, c_die, False/*td3*/, form );
if (attr == DW_AT_name && ctsMemSzB > 0) {
typeE.Te.TyEnum.name
- = ML_(dinfo_strdup)( "di.readdwarf3.enum_type.1",
+ = ML_(dinfo_strdup)( "di.readdwarf3.pTD.enum_type.2",
(UChar*)(UWord)cts );
}
if (attr == DW_AT_byte_size && ctsSzB > 0) {
@@ -2262,7 +2262,7 @@
cc, c_die, False/*td3*/, form );
if (attr == DW_AT_name && ctsMemSzB > 0) {
atomE.Te.Atom.name
- = ML_(dinfo_strdup)( "di.readdwarf3.enumerator.1",
+ = ML_(dinfo_strdup)( "di.readdwarf3.pTD.enumerator.1",
(UChar*)(UWord)cts );
}
if (attr == DW_AT_const_value && ctsSzB > 0) {
@@ -2301,12 +2301,12 @@
typeE.tag = Te_TyStOrUn;
typeE.Te.TyStOrUn.name = NULL;
typeE.Te.TyStOrUn.fieldRs
- = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.struct_type.1",
+ = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.pTD.struct_type.1",
ML_(dinfo_free),
sizeof(UWord) );
typeE.Te.TyStOrUn.complete = True;
typeE.Te.TyStOrUn.isStruct = dtag == DW_TAG_structure_type
- || dtag == DW_TAG_class_type;
+ || dtag == DW_TAG_class_type;
while (True) {
DW_AT attr = (DW_AT) get_ULEB128( c_abbv );
DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
@@ -2431,7 +2431,7 @@
typeE.tag = Te_TyArray;
typeE.Te.TyArray.typeR = D3_INVALID_CUOFF;
typeE.Te.TyArray.boundRs
- = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ptD.3",
+ = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ptD.array_type.1",
ML_(dinfo_free),
sizeof(UWord) );
while (True) {
@@ -2672,10 +2672,11 @@
static UWord chase_cuOff ( Bool* changed,
XArray* /* of TyEnt */ ents,
+ TyEntIndexCache* ents_cache,
UWord cuOff )
{
TyEnt* ent;
- ent = ML_(TyEnts__index_by_cuOff)( ents, cuOff );
+ ent = ML_(TyEnts__index_by_cuOff)( ents, ents_cache, cuOff );
if (!ent) {
VG_(printf)("chase_cuOff: no entry for 0x%05lx\n", cuOff);
@@ -2697,6 +2698,7 @@
static
void chase_cuOffs_in_XArray ( Bool* changed,
XArray* /* of TyEnt */ ents,
+ TyEntIndexCache* ents_cache,
/*MOD*/XArray* /* of UWord */ cuOffs )
{
Bool b2 = False;
@@ -2704,7 +2706,7 @@
for (i = 0; i < n; i++) {
Bool b = False;
UWord* p = VG_(indexXA)( cuOffs, i );
- *p = chase_cuOff( &b, ents, *p );
+ *p = chase_cuOff( &b, ents, ents_cache, *p );
if (b)
b2 = True;
}
@@ -2712,6 +2714,7 @@
}
static Bool TyEnt__subst_R_fields ( XArray* /* of TyEnt */ ents,
+ TyEntIndexCache* ents_cache,
/*MOD*/TyEnt* te )
{
Bool b, changed = False;
@@ -2719,7 +2722,8 @@
case Te_EMPTY:
break;
case Te_INDIR:
- te->Te.INDIR.indR = chase_cuOff( &b, ents, te->Te.INDIR.indR );
+ te->Te.INDIR.indR
+ = chase_cuOff( &b, ents, ents_cache, te->Te.INDIR.indR );
if (b) changed = True;
break;
case Te_UNKNOWN:
@@ -2727,7 +2731,8 @@
case Te_Atom:
break;
case Te_Field:
- te->Te.Field.typeR = chase_cuOff( &b, ents, te->Te.Field.typeR );
+ te->Te.Field.typeR
+ = chase_cuOff( &b, ents, ents_cache, te->Te.Field.typeR );
if (b) changed = True;
break;
case Te_Bound:
@@ -2735,31 +2740,35 @@
case Te_TyBase:
break;
case Te_TyPorR:
- te->Te.TyPorR.typeR = chase_cuOff( &b, ents, te->Te.TyPorR.typeR );
+ te->Te.TyPorR.typeR
+ = chase_cuOff( &b, ents, ents_cache, te->Te.TyPorR.typeR );
if (b) changed = True;
break;
case Te_TyTyDef:
- te->Te.TyTyDef.typeR = chase_cuOff( &b, ents, te->Te.TyTyDef.typeR );
+ te->Te.TyTyDef.typeR
+ = chase_cuOff( &b, ents, ents_cache, te->Te.TyTyDef.typeR );
if (b) changed = True;
break;
case Te_TyStOrUn:
- chase_cuOffs_in_XArray( &b, ents, te->Te.TyStOrUn.fieldRs );
+ chase_cuOffs_in_XArray( &b, ents, ents_cache, te->Te.TyStOrUn.fieldRs );
if (b) changed = True;
break;
case Te_TyEnum:
- chase_cuOffs_in_XArray( &b, ents, te->Te.TyEnum.atomRs );
+ chase_cuOffs_in_XArray( &b, ents, ents_cache, te->Te.TyEnum.atomRs );
if (b) changed = True;
break;
case Te_TyArray:
- te->Te.TyArray.typeR = chase_cuOff( &b, ents, te->Te.TyArray.typeR );
+ te->Te.TyArray.typeR
+ = chase_cuOff( &b, ents, ents_cache, te->Te.TyArray.typeR );
if (b) changed = True;
- chase_cuOffs_in_XArray( &b, ents, te->Te.TyArray.boundRs );
+ chase_cuOffs_in_XArray( &b, ents, ents_cache, te->Te.TyArray.boundRs );
if (b) changed = True;
break;
case Te_TyFn:
break;
case Te_TyQual:
- te->Te.TyQual.typeR = chase_cuOff( &b, ents, te->Te.TyQual.typeR );
+ te->Te.TyQual.typeR
+ = chase_cuOff( &b, ents, ents_cache, te->Te.TyQual.typeR );
if (b) changed = True;
break;
case Te_TyVoid:
@@ -2777,7 +2786,8 @@
(which should not itself be an indirection). In summary, this
routine shorts out all references to indirection nodes. */
static
-Word dedup_types_substitution_pass ( /*MOD*/XArray* /* of TyEnt */ ents )
+Word dedup_types_substitution_pass ( /*MOD*/XArray* /* of TyEnt */ ents,
+ TyEntIndexCache* ents_cache )
{
Word i, n, nChanged = 0;
Bool b;
@@ -2787,7 +2797,7 @@
vg_assert(ent->tag != Te_EMPTY);
/* We have to substitute everything, even indirections, so as to
ensure that chains of indirections don't build up. */
- b = TyEnt__subst_R_fields( ents, ent );
+ b = TyEnt__subst_R_fields( ents, ents_cache, ent );
if (b)
nChanged++;
}
@@ -2861,9 +2871,12 @@
static
-void dedup_types ( Bool td3, /*MOD*/XArray* /* of TyEnt */ ents )
+void dedup_types ( Bool td3,
+ /*MOD*/XArray* /* of TyEnt */ ents,
+ TyEntIndexCache* ents_cache )
{
Word m, n, i, nDel, nSubst, nThresh;
+ if (0) td3 = True;
n = VG_(sizeXA)( ents );
@@ -2884,7 +2897,7 @@
the array, until there are no more changes. */
do {
nDel = dedup_types_commoning_pass ( ents );
- nSubst = dedup_types_substitution_pass ( ents );
+ nSubst = dedup_types_substitution_pass ( ents, ents_cache );
vg_assert(nDel >= 0 && nSubst >= 0);
TRACE_D3(" %ld deletions, %ld substitutions\n", nDel, nSubst);
} while (nDel > nThresh || nSubst > nThresh);
@@ -2900,7 +2913,8 @@
ent = VG_(indexXA)( ents, i );
if (ent->tag != Te_INDIR) continue;
m++;
- ind = ML_(TyEnts__index_by_cuOff)( ents, ent->Te.INDIR.indR );
+ ind = ML_(TyEnts__index_by_cuOff)( ents, ents_cache,
+ ent->Te.INDIR.indR );
vg_assert(ind);
vg_assert(ind->tag != Te_INDIR);
}
@@ -2925,7 +2939,8 @@
__attribute__((noinline))
static void resolve_variable_types (
void (*barf)( HChar* ) __attribute__((noreturn)),
- /*R-O*/XArray* /* of TyEnt */ tyents,
+ /*R-O*/XArray* /* of TyEnt */ ents,
+ /*MOD*/TyEntIndexCache* ents_cache,
/*MOD*/XArray* /* of TempVar* */ vars
)
{
@@ -2935,9 +2950,11 @@
TempVar* var = *(TempVar**)VG_(indexXA)( vars, i );
/* This is the stated type of the variable. But it might be
an indirection, so be careful. */
- TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, var->typeR );
+ TyEnt* ent = ML_(TyEnts__index_by_cuOff)( ents, ents_cache,
+ var->typeR );
if (ent && ent->tag == Te_INDIR) {
- ent = ML_(TyEnts__index_by_cuOff)( tyents, ent->Te.INDIR.indR );
+ ent = ML_(TyEnts__index_by_cuOff)( ents, ents_cache,
+ ent->Te.INDIR.indR );
vg_assert(ent);
vg_assert(ent->tag != Te_INDIR);
}
@@ -3109,6 +3126,8 @@
XArray* /* of GExpr* */ gexprs;
XArray* /* of TempVar* */ tempvars;
WordFM* /* of (XArray* of AddrRange, void) */ rangestree;
+ TyEntIndexCache* tyents_cache = NULL;
+ TyEntIndexCache* tyents_to_keep_cache = NULL;
TempVar *varp, *varp2;
GExpr* gexpr;
Cursor abbv; /* for showing .debug_abbrev */
@@ -3292,7 +3311,7 @@
delete this tree, and the XArrays attached to it, at the end of
this function. */
rangestree = VG_(newFM)( ML_(dinfo_zalloc),
- "di.readdwarf3.ndrw.1b (rangestree)",
+ "di.readdwarf3.ndrw.2 (rangestree)",
ML_(dinfo_free),
(Word(*)(UWord,UWord))cmp__XArrays_of_AddrRange );
@@ -3300,13 +3319,13 @@
DebugInfo; instead their contents are handed to ML_(addVar) and
the list elements are then deleted. */
tempvars = VG_(newXA)( ML_(dinfo_zalloc),
- "di.readdwarf3.ndrw.2 (TempVar*s array)",
+ "di.readdwarf3.ndrw.3 (TempVar*s array)",
ML_(dinfo_free),
sizeof(TempVar*) );
/* List of GExprs we're accumulating. These wind up in the
DebugInfo. */
- gexprs = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ndrw.3",
+ gexprs = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ndrw.4",
ML_(dinfo_free), sizeof(GExpr*) );
/* We need a D3TypeParser to keep track of partially constructed
@@ -3394,7 +3413,7 @@
etc. */
vg_assert(!varparser.filenameTable );
varparser.filenameTable
- = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ndrw.4",
+ = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ndrw.5",
ML_(dinfo_free),
sizeof(UChar*) );
vg_assert(varparser.filenameTable);
@@ -3441,7 +3460,10 @@
TRACE_D3("------ Compressing type entries ------\n");
}
- dedup_types( td3, tyents );
+ tyents_cache = ML_(dinfo_zalloc)( "di.readdwarf3.ndrw.6",
+ sizeof(TyEntIndexCache) );
+ ML_(TyEntIndexCache__invalidate)( tyents_cache );
+ dedup_types( td3, tyents, tyents_cache );
if (td3) {
TRACE_D3("\n");
ML_(pp_TyEnts)(tyents, "After type entity (TyEnt) compression");
@@ -3449,7 +3471,7 @@
TRACE_D3("\n");
TRACE_D3("------ Resolving the types of variables ------\n" );
- resolve_variable_types( barf, tyents, tempvars );
+ resolve_variable_types( barf, tyents, tyents_cache, tempvars );
/* Copy all the non-INDIR tyents into a new table. For large
.so's, about 90% of the tyents will by now have been resolved to
@@ -3457,7 +3479,7 @@
them. */
tyents_to_keep
= VG_(newXA)( ML_(dinfo_zalloc),
- "di.readdwarf3.ndrw.6 (TyEnt to-keep array)",
+ "di.readdwarf3.ndrw.7 (TyEnt to-keep array)",
ML_(dinfo_free), sizeof(TyEnt) );
n = VG_(sizeXA)( tyents );
for (i = 0; i < n; i++) {
@@ -3468,6 +3490,8 @@
VG_(deleteXA)( tyents );
tyents = NULL;
+ ML_(dinfo_free)( tyents_cache );
+ tyents_cache = NULL;
/* Sort tyents_to_keep so we can lookup in it. A complete (if
minor) waste of time, since tyents itself is sorted, but
@@ -3479,6 +3503,12 @@
);
VG_(sortXA)( tyents_to_keep );
+ /* Enable cacheing on tyents_to_keep */
+ tyents_to_keep_cache
+ = ML_(dinfo_zalloc)( "di.readdwarf3.ndrw.8",
+ sizeof(TyEntIndexCache) );
+ ML_(TyEntIndexCache__invalidate)( tyents_to_keep_cache );
+
/* And record the tyents in the DebugInfo. We do this before
starting to hand variables to ML_(addVar), since if ML_(addVar)
wants to do debug printing (of the types of said vars) then it
@@ -3510,7 +3540,7 @@
ascending order, there is no need to sort the array after
construction. The ascendingness is however asserted for. */
dioff_lookup_tab
- = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ndrw.5",
+ = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.ndrw.9",
ML_(dinfo_free),
sizeof(TempVar*) );
vg_assert(dioff_lookup_tab);
@@ -3623,7 +3653,9 @@
the type didn't get resolved. Really, in that case
something's broken earlier on, and should be fixed, rather
than just skipping the variable. */
- ent = ML_(TyEnts__index_by_cuOff)( tyents_to_keep, varp->typeR );
+ ent = ML_(TyEnts__index_by_cuOff)( tyents_to_keep,
+ tyents_to_keep_cache,
+ varp->typeR );
/* The next two assertions should be guaranteed by
our previous call to resolve_variable_types. */
vg_assert(ent);
@@ -3746,6 +3778,15 @@
key-finalizer. */
VG_(deleteFM)( rangestree, (void(*)(UWord))VG_(deleteXA), NULL );
+ /* and the tyents_to_keep cache */
+ ML_(dinfo_free)( tyents_to_keep_cache );
+ tyents_to_keep_cache = NULL;
+
+ /* and the file name table (just the array, not the entries
+ themselves). */
+ vg_assert(varparser.filenameTable);
+ VG_(deleteXA)( varparser.filenameTable );
+
/* record the GExprs in di so they can be freed later */
vg_assert(!di->admin_gexprs);
di->admin_gexprs = gexprs;
Modified: branches/YARD/coregrind/m_debuginfo/storage.c
===================================================================
--- branches/YARD/coregrind/m_debuginfo/storage.c 2008-09-09 18:18:26 UTC (rev 8594)
+++ branches/YARD/coregrind/m_debuginfo/storage.c 2008-09-09 23:10:30 UTC (rev 8595)
@@ -751,7 +751,7 @@
vg_assert(name);
vg_assert(gexpr);
- ent = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, typeR);
+ ent = ML_(TyEnts__index_by_cuOff)( di->admin_tyents, NULL, typeR );
tl_assert(ent);
vg_assert(ML_(TyEnt__is_type)(ent));
Modified: branches/YARD/coregrind/m_debuginfo/tytypes.c
===================================================================
--- branches/YARD/coregrind/m_debuginfo/tytypes.c 2008-09-09 18:18:26 UTC (rev 8594)
+++ branches/YARD/coregrind/m_debuginfo/tytypes.c 2008-09-09 23:10:30 UTC (rev 8595)
@@ -198,7 +198,7 @@
static void pp_TyBound_C_ishly ( XArray* tyents, UWord cuOff )
{
- TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, cuOff );
+ TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, NULL, cuOff );
if (!ent) {
VG_(printf)("**bounds-have-invalid-cuOff**");
return;
@@ -220,7 +220,7 @@
void ML_(pp_TyEnt_C_ishly)( XArray* /* of TyEnt */ tyents,
UWord cuOff )
{
- TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, cuOff );
+ TyEnt* ent = ML_(TyEnts__index_by_cuOff)( tyents, NULL, cuOff );
if (!ent) {
VG_(printf)("**type-has-invalid-cuOff**");
return;
@@ -292,12 +292,60 @@
found. Asserts if more than one entry has the specified .cuOff
value. */
+void ML_(TyEntIndexCache__invalidate) ( TyEntIndexCache* cache )
+{
+ Word i;
+ for (i = 0; i < N_TYENT_INDEX_CACHE; i++) {
+ cache->ce[i].cuOff0 = 0; /* not actually necessary */
+ cache->ce[i].ent0 = NULL; /* "invalid entry" */
+ cache->ce[i].cuOff1 = 0; /* not actually necessary */
+ cache->ce[i].ent1 = NULL; /* "invalid entry" */
+ }
+}
+
TyEnt* ML_(TyEnts__index_by_cuOff) ( XArray* /* of TyEnt */ ents,
+ TyEntIndexCache* cache,
UWord cuOff_to_find )
{
Bool found;
Word first, last;
- TyEnt key;
+ TyEnt key, *res;
+
+ /* crude stats, aggregated over all caches */
+ static UWord cacheQs = 0 - 1;
+ static UWord cacheHits = 0;
+
+ if (0 && 0 == (cacheQs & 0xFFFF))
+ VG_(printf)("cache: %'lu queries, %'lu misses\n",
+ cacheQs, cacheQs - cacheHits);
+
+ if (LIKELY(cache != NULL)) {
+ UWord h = cuOff_to_find % (UWord)N_TYENT_INDEX_CACHE;
+ cacheQs++;
+ // dude, like, way 0, dude.
+ if (cache->ce[h].cuOff0 == cuOff_to_find && cache->ce[h].ent0 != NULL) {
+ // dude, way 0 is a total hit!
+ cacheHits++;
+ return cache->ce[h].ent0;
+ }
+ // dude, check out way 1, dude.
+ if (cache->ce[h].cuOff1 == cuOff_to_find && cache->ce[h].ent1 != NULL) {
+ // way 1 hit
+ UWord tc;
+ TyEnt* te;
+ cacheHits++;
+ // dude, way 1 is the new way 0. move with the times, dude.
+ tc = cache->ce[h].cuOff0;
+ te = cache->ce[h].ent0;
+ cache->ce[h].cuOff0 = cache->ce[h].cuOff1;
+ cache->ce[h].ent0 = cache->ce[h].ent1;
+ cache->ce[h].cuOff1 = tc;
+ cache->ce[h].ent1 = te;
+ return cache->ce[h].ent0;
+ }
+ }
+
+ /* We'll have to do it the hard way */
key.cuOff = cuOff_to_find;
key.tag = Te_EMPTY;
found = VG_(lookupXA)( ents, &key, &first, &last );
@@ -308,7 +356,21 @@
/* If this fails, the array is invalid in the sense that there is
more than one entry with .cuOff == cuOff_to_find. */
vg_assert(first == last);
- return (TyEnt*)VG_(indexXA)( ents, first );
+ res = (TyEnt*)VG_(indexXA)( ents, first );
+
+ if (LIKELY(cache != NULL) && LIKELY(res != NULL)) {
+ /* this is a bit stupid, computing this twice. Oh well.
+ Perhaps some magic gcc transformation will common them up.
+ re "res != NULL", since .ent of NULL denotes 'invalid entry',
+ we can't cache the result when res == NULL. */
+ UWord h = cuOff_to_find % (UWord)N_TYENT_INDEX_CACHE;
+ cache->ce[h].cuOff1 = cache->ce[h].cuOff0;
+ cache->ce[h].ent1 = cache->ce[h].ent0;
+ cache->ce[h].cuOff0 = cuOff_to_find;
+ cache->ce[h].ent0 = res;
+ }
+
+ return res;
}
@@ -566,7 +628,7 @@
{
Word i;
MaybeUWord eszB;
- TyEnt* ent = ML_(TyEnts__index_by_cuOff)(tyents, cuOff);
+ TyEnt* ent = ML_(TyEnts__index_by_cuOff)(tyents, NULL, cuOff);
TyEnt* ent2;
vg_assert(ent);
vg_assert(ML_(TyEnt__is_type)(ent));
@@ -577,7 +639,8 @@
case Te_TyQual:
return ML_(sizeOfType)( tyents, ent->Te.TyQual.typeR );
case Te_TyTyDef:
- ent2 = ML_(TyEnts__index_by_cuOff)(tyents, ent->Te.TyTyDef.typeR);
+ ent2 = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
+ ent->Te.TyTyDef.typeR);
vg_assert(ent2);
if (ent2->tag == Te_UNKNOWN)
return mk_MaybeUWord_Nothing(); /*UNKNOWN*/
@@ -592,7 +655,8 @@
case Te_TyEnum:
return mk_MaybeUWord_Just( ent->Te.TyEnum.szB );
case Te_TyArray:
- ent2 = ML_(TyEnts__index_by_cuOff)(tyents, ent->Te.TyArray.typeR);
+ ent2 = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
+ ent->Te.TyArray.typeR);
vg_assert(ent2);
if (ent2->tag == Te_UNKNOWN)
return mk_MaybeUWord_Nothing(); /*UNKNOWN*/
@@ -601,7 +665,7 @@
UWord bo_cuOff
= *(UWord*)VG_(indexXA)(ent->Te.TyArray.boundRs, i);
TyEnt* bo
- = ML_(TyEnts__index_by_cuOff)( tyents, bo_cuOff );
+ = ML_(TyEnts__index_by_cuOff)( tyents, NULL, bo_cuOff );
vg_assert(bo);
vg_assert(bo->tag == Te_Bound);
if (!(bo->Te.Bound.knownL && bo->Te.Bound.knownU))
@@ -643,7 +707,7 @@
sizeof(UChar) );
vg_assert(xa);
- ty = ML_(TyEnts__index_by_cuOff)(tyents, ty_cuOff);
+ ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL, ty_cuOff);
while (True) {
vg_assert(ty);
@@ -673,7 +737,7 @@
if ((!fieldRs) || VG_(sizeXA)(fieldRs) == 0) goto done;
for (i = 0; i < VG_(sizeXA)( fieldRs ); i++ ) {
fieldR = *(UWord*)VG_(indexXA)( fieldRs, i );
- field = ML_(TyEnts__index_by_cuOff)(tyents, fieldR);
+ field = ML_(TyEnts__index_by_cuOff)(tyents, NULL, fieldR);
vg_assert(field);
vg_assert(field->tag == Te_Field);
vg_assert(field->Te.Field.loc);
@@ -719,7 +783,8 @@
VG_(addBytesToXA)( xa, field->Te.Field.name,
VG_(strlen)(field->Te.Field.name) );
offset -= offMin;
- ty = ML_(TyEnts__index_by_cuOff)(tyents, field->Te.Field.typeR );
+ ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
+ field->Te.Field.typeR );
tl_assert(ty);
if (ty->tag == Te_UNKNOWN) goto done;
/* keep going; look inside the field. */
@@ -734,7 +799,8 @@
TyEnt* bound;
/* Just deal with the simple, common C-case: 1-D array,
zero based, known size. */
- elemTy = ML_(TyEnts__index_by_cuOff)(tyents, ty->Te.TyArray.typeR);
+ elemTy = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
+ ty->Te.TyArray.typeR);
vg_assert(elemTy);
if (elemTy->tag == Te_UNKNOWN) goto done;
vg_assert(ML_(TyEnt__is_type)(elemTy));
@@ -742,7 +808,7 @@
goto done;
if (VG_(sizeXA)( ty->Te.TyArray.boundRs ) != 1) goto done;
boundR = *(UWord*)VG_(indexXA)( ty->Te.TyArray.boundRs, 0 );
- bound = ML_(TyEnts__index_by_cuOff)(tyents, boundR);
+ bound = ML_(TyEnts__index_by_cuOff)(tyents, NULL, boundR);
vg_assert(bound);
vg_assert(bound->tag == Te_Bound);
if (!(bound->Te.Bound.knownL && bound->Te.Bound.knownU
@@ -767,14 +833,16 @@
}
case Te_TyQual: {
- ty = ML_(TyEnts__index_by_cuOff)(tyents, ty->Te.TyQual.typeR);
+ ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
+ ty->Te.TyQual.typeR);
tl_assert(ty);
if (ty->tag == Te_UNKNOWN) goto done;
break;
}
case Te_TyTyDef: {
- ty = ML_(TyEnts__index_by_cuOff)(tyents, ty->Te.TyTyDef.typeR);
+ ty = ML_(TyEnts__index_by_cuOff)(tyents, NULL,
+ ty->Te.TyTyDef.typeR);
tl_assert(ty);
if (ty->tag == Te_UNKNOWN) goto done;
break;
Modified: branches/YARD/coregrind/m_main.c
===================================================================
--- branches/YARD/coregrind/m_main.c 2008-09-09 18:18:26 UTC (rev 8594)
+++ branches/YARD/coregrind/m_main.c 2008-09-09 23:10:30 UTC (rev 8595)
@@ -2081,7 +2081,7 @@
/* Show a profile of the heap(s) at shutdown. Optionally, first
throw away all the debug info, as that makes it easy to spot
- leaks in the debuginfo reader. */
+ leaks in the debuginfo reader (for debugging only!) */
if (VG_(clo_profile_heap)) {
if (0) VG_(di_discard_ALL_debuginfo)();
VG_(print_arena_cc_analysis)();
|
|
From: <sv...@va...> - 2008-09-09 18:18:16
|
Author: bart Date: 2008-09-09 19:18:26 +0100 (Tue, 09 Sep 2008) New Revision: 8594 Log: Added more comments. Modified: trunk/drd/tests/pth_inconsistent_cond_wait.c Modified: trunk/drd/tests/pth_inconsistent_cond_wait.c =================================================================== --- trunk/drd/tests/pth_inconsistent_cond_wait.c 2008-09-09 18:11:40 UTC (rev 8593) +++ trunk/drd/tests/pth_inconsistent_cond_wait.c 2008-09-09 18:18:26 UTC (rev 8594) @@ -37,21 +37,33 @@ pthread_t tid1; pthread_t tid2; + /* Initialize synchronization objects. */ sem_init(&s_sem, 0, 0); pthread_cond_init(&s_cond, 0); pthread_mutex_init(&s_mutex1, 0); pthread_mutex_init(&s_mutex2, 0); + + /* Create two threads. */ pthread_create(&tid1, 0, &thread1, 0); pthread_create(&tid2, 0, &thread2, 0); + + /* Wait until both threads have called sem_post(). */ sem_wait(&s_sem); sem_wait(&s_sem); + + /* Wait until both threads are waiting inside pthread_cond_wait(). */ pthread_mutex_lock(&s_mutex1); pthread_mutex_lock(&s_mutex2); pthread_mutex_unlock(&s_mutex2); pthread_mutex_unlock(&s_mutex1); + + /* Signal s_cond twice. */ pthread_cond_signal(&s_cond); pthread_cond_signal(&s_cond); + + /* Join both threads. */ pthread_join(tid1, 0); pthread_join(tid2, 0); + return 0; } |
|
From: <sv...@va...> - 2008-09-09 18:11:33
|
Author: bart
Date: 2008-09-09 19:11:40 +0100 (Tue, 09 Sep 2008)
New Revision: 8593
Log:
Make sure that atomic_var.c compiles without warnings in case HAVE_BUILTIN_ATOMIC has not been defined.
Modified:
trunk/drd/tests/atomic_var.c
Modified: trunk/drd/tests/atomic_var.c
===================================================================
--- trunk/drd/tests/atomic_var.c 2008-09-09 11:10:29 UTC (rev 8592)
+++ trunk/drd/tests/atomic_var.c 2008-09-09 18:11:40 UTC (rev 8593)
@@ -26,6 +26,7 @@
#endif
+#ifdef HAVE_BUILTIN_ATOMIC
static int s_x = 0;
/* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
static char s_dummy[512];
@@ -45,6 +46,7 @@
fprintf(stderr, "y = %d\n", s_y);
return 0;
}
+#endif
int main(int argc, char** argv)
{
@@ -59,14 +61,14 @@
for (i = 0; i < n_threads; i++)
pthread_join(tid[i], 0);
fprintf(stderr, "Test finished.\n");
+
+ /* Suppress the compiler warning about s_dummy not being used. */
+ s_dummy[0]++;
#else
fprintf(stderr,
"Sorry, but your compiler does not have built-in support for atomic"
" operations.\n");
#endif
- /* Suppress the compiler warning about s_dummy not being used. */
- s_dummy[0]++;
-
return 0;
}
|
|
From: Bart V. A. <bar...@gm...> - 2008-09-09 15:12:46
|
On Tue, Sep 9, 2008 at 4:56 PM, John Ripley <joh...@gm...> wrote: > > Hi Evan - great to see you've done a lot of work on this! I've > unfortunately not got around to trying it due to cross-compile issues > (grr gen-offsets grr) and having broken my ARM environment... will > remedy that soon. There is a patch available that solves the trouble with genoffsets and cross-compilation. This patch will be applied at an appropriate time to the official VEX distribution. See also http://bugs.kde.org/show_bug.cgi?id=162295 for more information about this patch. Bart. |
|
From: John R. <joh...@gm...> - 2008-09-09 14:56:27
|
Hi Evan - great to see you've done a lot of work on this! I've unfortunately not got around to trying it due to cross-compile issues (grr gen-offsets grr) and having broken my ARM environment... will remedy that soon. I think it's probably not worth bothering with most of the optimizations such as addressing modes. They're not going to give an order of magnitude improvement, and there's a lot of other stuff to fix first. PC-relative constant pools may also be a bit tricky. The absolute worst case on ARM is 4 instructions per 32 bit constant, but most cases can be reduced to 1-2 using rotation, as you say. Inline immediates also avoid a load-use-stall, so the performance difference won't actually be huge (sometimes better!) Anyway, just thought I'd add at least one voice of encouragement here :) I have a lot of things I'd like to run through Valgrind on ARM. 2008/9/8 Evan Geller <Eva...@pa...>: > So, here's the ARM support patch for Valgrind. It's pretty incomplete, but it will run some basic applications. Here are some of the known issues, first the more apparent ones: > > * No floating point, VFP, or neon support. This can be compiled around. > > * Random instructions aren't implemented, or are partially implemented. Hence you might see a "long multiply accumulate is unsupported." You're welcome to implement them :) > > * Some bugs in memcheck. The suppressions file just isn't being read. I'll look into this. Basically it results in a slew of > > ==1172== Conditional jump or move depends on uninitialised value(s) > ==1172== at 0x100000000000: _dl_relocate_object (in /lib/ld-2.5.so) > ==1172== by 0x100000000000: dl_main (in /lib/ld-2.5.so) > > These can be safely ignored. The second bug is the "0x100000000000," still working on that... > > * Stack unwinding is very hacky. If it hits a variadic function, or custom code, or anything like that, it will choke. > > Some of the more internal issues: > > * No test suites. Hehhh.... > > * Lots of random stubbed out stuff. > > * Not yet handling all the possible optimizations for all the addressing modes. Most just fall through to registers. > > * I mistakenly pulled the literal case from VEX. Really this isn't much of an issue since either we do a mov/orr/orr/orr or a load/branch... and neither are very good. What's /really/ needed for ARM is literal pool support in VEX. In other words, try to coerce the immediate into a rotated immediate, if that doesn't work, try and do it with a move-negate, (etc.), if all else fails, reserve a spot in the literal pool to hold the value, and generate a pc-relative load. When enough instructions are generated that the size of a the add/sub operand of a pc relative load of one of the previous pc-rel loads isn't big enough to refer to it's immediate in the lit pool, we spill out the literal pool and fix up the previous pc-relative loads to point into the pool. In the mean time, mov/orr/orr/orr isn't toooo bad. > > Anywho. Have fun guys! > > ------------------------------------------------------------------------- > 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... > https://lists.sourceforge.net/lists/listinfo/valgrind-developers > > |
|
From: <sv...@va...> - 2008-09-09 11:10:21
|
Author: sewardj
Date: 2008-09-09 12:10:29 +0100 (Tue, 09 Sep 2008)
New Revision: 8592
Log:
Merge the h_ and sg_ instrumenters, so that the combined tool
actually does something sane.
Modified:
branches/PTRCHECK/exp-ptrcheck.supp
branches/PTRCHECK/exp-ptrcheck/h_main.c
branches/PTRCHECK/exp-ptrcheck/h_main.h
branches/PTRCHECK/exp-ptrcheck/pc_common.c
branches/PTRCHECK/exp-ptrcheck/pc_main.c
branches/PTRCHECK/exp-ptrcheck/sg_main.c
branches/PTRCHECK/exp-ptrcheck/sg_main.h
Modified: branches/PTRCHECK/exp-ptrcheck/h_main.c
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/h_main.c 2008-09-09 08:49:35 UTC (rev 8591)
+++ branches/PTRCHECK/exp-ptrcheck/h_main.c 2008-09-09 11:10:29 UTC (rev 8592)
@@ -234,6 +234,8 @@
#include "h_list.h"
#include "h_main.h"
+#include "sg_main.h" // sg_instrument_*, and struct _SGEnv
+
#include "pc_common.h"
@@ -2821,6 +2823,17 @@
/*--- Instrumentation ---*/
/*--------------------------------------------------------------------*/
+/* The h_ instrumenter that follows is complex, since it deals with
+ shadow value computation.
+
+ It also needs to generate instrumentation for the sg_ side of
+ things. That's relatively straightforward. However, rather than
+ confuse the code herein any further, we simply delegate the problem
+ to sg_main.c, by using the four functions
+ sg_instrument_{init,fini,IRStmt,final_jump}. These four completely
+ abstractify the sg_ instrumentation. See comments in sg_main.c's
+ instrumentation section for further details. */
+
/* Carries around state during Ptrcheck instrumentation. */
typedef
struct {
@@ -4140,7 +4153,6 @@
}
-static
IRSB* h_instrument ( VgCallbackClosure* closure,
IRSB* sbIn,
VexGuestLayout* layout,
@@ -4150,16 +4162,8 @@
Bool verboze = 0||False;
Int i /*, j*/;
PCEnv pce;
+ struct _SGEnv* sgenv;
- if (0) { /* See comment-ref below KLUDGE01. */
- /* FIXME: race! */
- static Bool init_kludge_done = False;
- if (!init_kludge_done) {
- init_kludge_done = True;
- init_shadow_registers(0);
- }
- }
-
if (gWordTy != hWordTy) {
/* We don't currently support this case. */
VG_(tool_panic)("host/guest word size mismatch");
@@ -4187,6 +4191,10 @@
for (i = 0; i < pce.n_originalTmps; i++)
pce.tmpMap[i] = IRTemp_INVALID;
+ /* Also set up for the sg_ instrumenter. See comments
+ at the top of this instrumentation section for details. */
+ sgenv = sg_instrument_init();
+
/* Stay sane. These two should agree! */
tl_assert(layout->total_sizeB == MC_SIZEOF_GUEST_STATE);
@@ -4246,9 +4254,21 @@
tl_assert(i < sbIn->stmts_used);
tl_assert(sbIn->stmts[i]->tag == Ist_IMark);
- for (/*use current i*/; i < sbIn->stmts_used; i++)
+ for (/*use current i*/; i < sbIn->stmts_used; i++) {
+ /* generate sg_ instrumentation for this stmt */
+ sg_instrument_IRStmt( sgenv, pce.bb, sbIn->stmts[i],
+ layout, gWordTy, hWordTy );
+ /* generate h_ instrumentation for this stmt */
schemeS( &pce, sbIn->stmts[i] );
+ }
+ /* generate sg_ instrumentation for the final jump */
+ sg_instrument_final_jump( sgenv, pce.bb, sbIn->next, sbIn->jumpkind,
+ layout, gWordTy, hWordTy );
+
+ /* and finalise .. */
+ sg_instrument_fini( sgenv );
+
return pce.bb;
}
@@ -4264,12 +4284,6 @@
seglist = ISList__construct();
init_lossage();
-
- // init_shadow_registers();
- // This is deferred until we are asked to instrument the
- // first SB. Very ugly, but necessary since right now we can't
- // ask what the current ThreadId is. See comment-ref KLUDGE01
- // above.
}
void h_post_clo_init ( void )
Modified: branches/PTRCHECK/exp-ptrcheck/h_main.h
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/h_main.h 2008-09-09 08:49:35 UTC (rev 8591)
+++ branches/PTRCHECK/exp-ptrcheck/h_main.h 2008-09-09 11:10:29 UTC (rev 8592)
@@ -77,6 +77,13 @@
void h_pre_syscall ( ThreadId tid, UInt syscallno );
void h_post_syscall ( ThreadId tid, UInt syscallno, SysRes res );
+/* Note that this also does the sg_ instrumentation. */
+IRSB* h_instrument ( VgCallbackClosure* closure,
+ IRSB* sbIn,
+ VexGuestLayout* layout,
+ VexGuestExtents* vge,
+ IRType gWordTy, IRType hWordTy );
+
#endif
/*--------------------------------------------------------------------*/
Modified: branches/PTRCHECK/exp-ptrcheck/pc_common.c
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/pc_common.c 2008-09-09 08:49:35 UTC (rev 8591)
+++ branches/PTRCHECK/exp-ptrcheck/pc_common.c 2008-09-09 11:10:29 UTC (rev 8592)
@@ -157,6 +157,7 @@
{
XError xe;
VG_(memset)(&xe, 0, sizeof(xe));
+ xe.tag = XE_SorG;
xe.XE.SorG.addr = addr;
xe.XE.SorG.sszB = sszB;
VG_(strncpy)( &xe.XE.SorG.expect[0],
Modified: branches/PTRCHECK/exp-ptrcheck/pc_main.c
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/pc_main.c 2008-09-09 08:49:35 UTC (rev 8591)
+++ branches/PTRCHECK/exp-ptrcheck/pc_main.c 2008-09-09 11:10:29 UTC (rev 8592)
@@ -60,11 +60,6 @@
// //
//////////////////////////////////////////////////////////////
-static void pc_instrument ( void )
-{
- tl_assert(0);
-}
-
static void pc_fini ( Int exitcode ) {
h_fini( exitcode );
sg_fini( exitcode );
@@ -143,7 +138,7 @@
VG_(details_bug_reports_to) (VG_BUGS_TO);
VG_(basic_tool_funcs) (pc_post_clo_init,
- pc_instrument,
+ h_instrument,
pc_fini);
VG_(needs_malloc_replacement)( h_replace_malloc,
Modified: branches/PTRCHECK/exp-ptrcheck/sg_main.c
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/sg_main.c 2008-09-09 08:49:35 UTC (rev 8591)
+++ branches/PTRCHECK/exp-ptrcheck/sg_main.c 2008-09-09 11:10:29 UTC (rev 8592)
@@ -69,7 +69,7 @@
&& tid != VG_INVALID_THREADID;
}
-static void* pc_malloc ( SizeT n ) {
+static void* sg_malloc ( SizeT n ) {
void* p;
tl_assert(n > 0);
p = VG_(malloc)( n );
@@ -77,19 +77,12 @@
return p;
}
-static void pc_free ( void* p ) {
+static void sg_free ( void* p ) {
tl_assert(p);
VG_(free)(p);
}
-#define MK_XAMAGIC(_c3,_c2,_c1,_c0) \
- ( ( ((UInt)(_c3)) << 24 ) | ( ((UInt)(_c2)) << 16 ) | \
- ( ((UInt)(_c1)) << 8 ) | ( ((UInt)(_c0)) << 0 ) )
-
-#define StackBlock_XAMAGIC MK_XAMAGIC('S','B','l','k')
-
-
/* Compare the intervals [a1,a1+n1) and [a2,a2+n2). Return -1 if the
first interval is lower, 1 if the first interval is higher, and 0
if there is any overlap. Redundant paranoia with casting is there
@@ -255,7 +248,7 @@
static void init_StackBlocks_set ( void )
{
tl_assert(!frameBlocks_set);
- frameBlocks_set = VG_(newFM)( pc_malloc, pc_free,
+ frameBlocks_set = VG_(newFM)( sg_malloc, sg_free,
(Word(*)(UWord,UWord))StackBlocks__cmp );
tl_assert(frameBlocks_set);
}
@@ -411,7 +404,7 @@
static void init_GlobalBlock_set ( void )
{
tl_assert(!globalBlock_set);
- globalBlock_set = VG_(newFM)( pc_malloc, pc_free,
+ globalBlock_set = VG_(newFM)( sg_malloc, sg_free,
(Word(*)(UWord,UWord))GlobalBlock__cmp );
tl_assert(globalBlock_set);
}
@@ -436,7 +429,7 @@
} else {
/* no. clone it, store the clone and return the clone's
address. */
- GlobalBlock* clone = pc_malloc( sizeof(GlobalBlock) );
+ GlobalBlock* clone = sg_malloc( sizeof(GlobalBlock) );
tl_assert(clone);
*clone = *orig;
VG_(addToFM)( globalBlock_set, (UWord)clone, 0 );
@@ -536,7 +529,7 @@
Addr addr = *(Addr*)VG_(indexXA)( bases, i );
StackBlock* descr = (StackBlock*)VG_(indexXA)( descrs, i );
tl_assert(descr->szB > 0);
- nyu = pc_malloc( sizeof(StackTreeNode) );
+ nyu = sg_malloc( sizeof(StackTreeNode) );
nyu->addr = addr;
nyu->szB = descr->szB;
nyu->descr = descr;
@@ -573,7 +566,7 @@
tl_assert(b);
tl_assert(oldV == 0);
tl_assert(nd == (StackTreeNode*)oldK);
- pc_free(nd);
+ sg_free(nd);
}
}
@@ -581,7 +574,7 @@
static void delete_StackTree__kFin ( UWord keyW ) {
StackTreeNode* nd = (StackTreeNode*)keyW;
tl_assert(nd);
- pc_free(nd);
+ sg_free(nd);
}
static void delete_StackTree__vFin ( UWord valW ) {
tl_assert(valW == 0);
@@ -593,7 +586,7 @@
}
static WordFM* new_StackTree ( void ) {
- return VG_(newFM)( pc_malloc, pc_free,
+ return VG_(newFM)( sg_malloc, sg_free,
(Word(*)(UWord,UWord))cmp_intervals_StackTreeNode );
}
@@ -678,7 +671,7 @@
GlobalTreeNode *nyu, *nd;
UWord keyW, valW;
tl_assert(descr->szB > 0);
- nyu = pc_malloc( sizeof(GlobalTreeNode) );
+ nyu = sg_malloc( sizeof(GlobalTreeNode) );
nyu->addr = descr->addr;
nyu->szB = descr->szB;
nyu->descr = descr;
@@ -699,7 +692,7 @@
&& 0 == VG_(strcmp)(nd->descr->name, nyu->descr->name)
&& 0 == VG_(strcmp)(nd->descr->soname, nyu->descr->soname)) {
/* exact duplicate; ignore it */
- pc_free(nyu);
+ sg_free(nyu);
return;
}
/* else fall through; the assertion below will catch it */
@@ -977,7 +970,7 @@
siTrees[i] = NULL;
}
invalidate_all_QCaches();
- giTree = VG_(newFM)( pc_malloc, pc_free,
+ giTree = VG_(newFM)( sg_malloc, sg_free,
(Word(*)(UWord,UWord))cmp_intervals_GlobalTreeNode );
}
@@ -1127,7 +1120,7 @@
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. */
+ number of sg_malloc/sg_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 */
@@ -1247,7 +1240,7 @@
old_size = sf->htab_size;
new_size = 2 * old_size;
old_htab = sf->htab;
- new_htab = pc_malloc( new_size * sizeof(IInstance) );
+ new_htab = sg_malloc( new_size * sizeof(IInstance) );
for (i = 0; i < new_size; i++) {
new_htab[i].insn_addr = 0; /* NOT IN USE */
}
@@ -1276,7 +1269,7 @@
}
/* all entries copied; free old table. */
if (old_htab != &sf->htab_fixed[0])
- pc_free(old_htab);
+ sg_free(old_htab);
sf->htab = new_htab;
sf->htab_size = new_size;
/* check sf->htab_used is correct. Optional and a bit expensive
@@ -1398,7 +1391,7 @@
XArray* res;
Word i, n = VG_(sizeXA)( blocks );
tl_assert(n > 0);
- res = VG_(newXA)( pc_malloc, pc_free, sizeof(Addr) );
+ res = VG_(newXA)( sg_malloc, sg_free, sizeof(Addr) );
for (i = 0; i < n; i++) {
StackBlock* blk = VG_(indexXA)( blocks, i );
Addr ea = calculate_StackBlock_EA( blk, sp, fp );
@@ -1773,7 +1766,7 @@
if (caller->inner) {
callee = caller->inner;
} else {
- callee = pc_malloc(sizeof(StackFrame));
+ callee = sg_malloc(sizeof(StackFrame));
VG_(memset)(callee, 0, sizeof(StackFrame));
callee->outer = caller;
caller->inner = callee;
@@ -1853,7 +1846,7 @@
//VG_(printf)("UNWIND dump %p\n", innermost->creation_sp);
tl_assert(innermost->htab);
if (innermost->htab != &innermost->htab_fixed[0])
- pc_free(innermost->htab);
+ sg_free(innermost->htab);
/* be on the safe side */
innermost->creation_sp = 0;
innermost->htab = NULL;
@@ -1921,6 +1914,32 @@
call helperc__mem_access
*/
+/* A complication: sg_ instrumentation and h_ instrumentation need to
+ be interleaved. Since the latter is a lot more complex than the
+ former, we split the sg_ instrumentation here into four functions
+ and let the h_ instrumenter call the four functions as it goes.
+ Hence the h_ instrumenter drives the sg_ instrumenter.
+
+ To make this viable, the sg_ instrumenter carries what running
+ state it needs in 'struct _SGEnv'. This is exported only
+ abstractly from this file.
+*/
+
+struct _SGEnv {
+ /* the current insn's IP */
+ Addr64 curr_IP;
+ /* whether the above is actually known */
+ Bool curr_IP_known;
+ /* if we find a mem ref, is it the first for this insn? Used for
+ detecting insns which make more than one memory ref, a situation
+ we basically can't really handle properly; and so we ignore all
+ but the first ref. */
+ Bool firstRef;
+};
+
+
+/* --- Helper fns for instrumentation --- */
+
static IRTemp gen_Get_SP ( IRSB* bbOut,
VexGuestLayout* layout,
Int hWordTy_szB )
@@ -2012,138 +2031,138 @@
}
-static
-IRSB* sg_instrument ( VgCallbackClosure* closure,
- IRSB* sbIn,
- VexGuestLayout* layout,
- VexGuestExtents* vge,
- IRType gWordTy, IRType hWordTy )
+/* --- Instrumentation main (4 fns) --- */
+
+struct _SGEnv * sg_instrument_init ( void )
{
- Int i;
- IRSB* sbOut;
+ struct _SGEnv * env = sg_malloc(sizeof(struct _SGEnv));
+ tl_assert(env);
+ env->curr_IP = 0;
+ env->curr_IP_known = False;
+ env->firstRef = True;
+ return env;
+}
- Addr curr_IP = 0;
- Bool curr_IP_known = False;
+void sg_instrument_fini ( struct _SGEnv * env )
+{
+ sg_free(env);
+}
- Bool firstRef = True;
+/* Add instrumentation for 'st' to 'sbOut', and possibly modify 'env'
+ as required. This must be called before 'st' itself is added to
+ 'sbOut'. */
+void sg_instrument_IRStmt ( /*MOD*/struct _SGEnv * env,
+ /*MOD*/IRSB* sbOut,
+ IRStmt* st,
+ VexGuestLayout* layout,
+ IRType gWordTy, IRType hWordTy )
+{
+ tl_assert(st);
+ tl_assert(isFlatIRStmt(st));
+ switch (st->tag) {
+ case Ist_NoOp:
+ case Ist_AbiHint:
+ case Ist_Put:
+ case Ist_PutI:
+ case Ist_MBE:
+ /* None of these can contain any memory references. */
+ break;
- if (gWordTy != hWordTy) {
- /* We don't currently support this case. */
- VG_(tool_panic)("host/guest word size mismatch");
- }
+ case Ist_Exit:
+ tl_assert(st->Ist.Exit.jk != Ijk_Call);
+ /* else we must deal with a conditional call */
+ break;
- /* Set up BB */
- sbOut = emptyIRSB();
- sbOut->tyenv = deepCopyIRTypeEnv(sbIn->tyenv);
- sbOut->next = deepCopyIRExpr(sbIn->next);
- sbOut->jumpkind = sbIn->jumpkind;
+ case Ist_IMark:
+ env->curr_IP_known = True;
+ env->curr_IP = (Addr)st->Ist.IMark.addr;
+ env->firstRef = True;
+ break;
- // Copy verbatim any IR preamble preceding the first IMark
- i = 0;
- while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
- addStmtToIRSB( sbOut, sbIn->stmts[i] );
- i++;
- }
-
- for (/*use current i*/; i < sbIn->stmts_used; i++) {
- IRStmt* st = sbIn->stmts[i];
- tl_assert(st);
- tl_assert(isFlatIRStmt(st));
- switch (st->tag) {
- case Ist_NoOp:
- case Ist_AbiHint:
- case Ist_Put:
- case Ist_PutI:
- case Ist_MBE:
- /* None of these can contain any memory references. */
- break;
-
- case Ist_Exit:
- tl_assert(st->Ist.Exit.jk != Ijk_Call);
- /* else we must deal with a conditional call */
- break;
-
- case Ist_IMark:
- curr_IP_known = True;
- curr_IP = (Addr)st->Ist.IMark.addr;
- firstRef = True;
- break;
-
- case Ist_Store:
- tl_assert(curr_IP_known);
- if (firstRef) {
+ case Ist_Store:
+ tl_assert(env->curr_IP_known);
+ if (env->firstRef) {
instrument_mem_access(
sbOut,
st->Ist.Store.addr,
- sizeofIRType(typeOfIRExpr(sbIn->tyenv, st->Ist.Store.data)),
+ sizeofIRType(typeOfIRExpr(sbOut->tyenv, st->Ist.Store.data)),
True/*isStore*/,
sizeofIRType(hWordTy),
- curr_IP, layout
+ env->curr_IP, layout
);
- firstRef = False;
- }
- break;
+ env->firstRef = False;
+ }
+ break;
- case Ist_WrTmp: {
- IRExpr* data = st->Ist.WrTmp.data;
- if (data->tag == Iex_Load) {
- tl_assert(curr_IP_known);
- if (firstRef) {
+ case Ist_WrTmp: {
+ IRExpr* data = st->Ist.WrTmp.data;
+ if (data->tag == Iex_Load) {
+ tl_assert(env->curr_IP_known);
+ if (env->firstRef) {
instrument_mem_access(
sbOut,
data->Iex.Load.addr,
sizeofIRType(data->Iex.Load.ty),
False/*!isStore*/,
sizeofIRType(hWordTy),
- curr_IP, layout
+ env->curr_IP, layout
);
- firstRef = False;
- }
+ env->firstRef = False;
}
- break;
}
+ break;
+ }
- case Ist_Dirty: {
- Int dataSize;
- IRDirty* d = st->Ist.Dirty.details;
- if (d->mFx != Ifx_None) {
- /* This dirty helper accesses memory. Collect the
- details. */
- tl_assert(curr_IP_known);
- if (firstRef) {
+ case Ist_Dirty: {
+ Int dataSize;
+ IRDirty* d = st->Ist.Dirty.details;
+ if (d->mFx != Ifx_None) {
+ /* This dirty helper accesses memory. Collect the
+ details. */
+ tl_assert(env->curr_IP_known);
+ if (env->firstRef) {
tl_assert(d->mAddr != NULL);
tl_assert(d->mSize != 0);
dataSize = d->mSize;
if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
instrument_mem_access(
sbOut, d->mAddr, dataSize, False/*!isStore*/,
- sizeofIRType(hWordTy), curr_IP, layout
+ sizeofIRType(hWordTy), env->curr_IP, layout
);
}
if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
instrument_mem_access(
sbOut, d->mAddr, dataSize, True/*isStore*/,
- sizeofIRType(hWordTy), curr_IP, layout
+ sizeofIRType(hWordTy), env->curr_IP, layout
);
}
- firstRef = False;
- }
- } else {
- tl_assert(d->mAddr == NULL);
- tl_assert(d->mSize == 0);
+ env->firstRef = False;
}
- break;
+ } else {
+ tl_assert(d->mAddr == NULL);
+ tl_assert(d->mSize == 0);
}
+ break;
+ }
- default:
- tl_assert(0);
+ default:
+ tl_assert(0);
- } /* switch (st->tag) */
+ } /* switch (st->tag) */
+}
- addStmtToIRSB( sbOut, st );
- } /* iterate over sbIn->stmts */
- if (sbIn->jumpkind == Ijk_Call) {
+/* Add instrumentation for the final jump of an IRSB 'sbOut', and
+ possibly modify 'env' as required. This must be the last
+ instrumentation statement in the block. */
+void sg_instrument_final_jump ( /*MOD*/struct _SGEnv * env,
+ /*MOD*/IRSB* sbOut,
+ IRExpr* next,
+ IRJumpKind jumpkind,
+ VexGuestLayout* layout,
+ IRType gWordTy, IRType hWordTy )
+{
+ if (jumpkind == Ijk_Call) {
// Assumes x86 or amd64
IRTemp sp_post_call_insn, fp_post_call_insn;
XArray* frameBlocks;
@@ -2153,8 +2172,8 @@
= gen_Get_SP( sbOut, layout, sizeofIRType(hWordTy) );
fp_post_call_insn
= gen_Get_FP( sbOut, layout, sizeofIRType(hWordTy) );
- tl_assert(curr_IP_known);
- frameBlocks = get_StackBlocks_for_IP( curr_IP );
+ tl_assert(env->curr_IP_known);
+ frameBlocks = get_StackBlocks_for_IP( env->curr_IP );
tl_assert(frameBlocks);
if (VG_(sizeXA)(frameBlocks) == 0)
frameBlocks = NULL;
@@ -2163,7 +2182,7 @@
IRExpr_RdTmp(sp_post_call_insn),
IRExpr_RdTmp(fp_post_call_insn),
/* assume the call doesn't change FP */
- sbIn->next,
+ next,
mkIRExpr_HWord( (HWord)frameBlocks ),
mkIRExpr_HWord( sizeofIRType(gWordTy) )
);
@@ -2174,8 +2193,6 @@
args );
addStmtToIRSB( sbOut, IRStmt_Dirty(di) );
}
-
- return sbOut;
}
@@ -2197,7 +2214,7 @@
infinity, so it can never be removed. */
static StackFrame* new_root_StackFrame ( void )
{
- StackFrame* sframe = pc_malloc(sizeof(StackFrame));
+ StackFrame* sframe = sg_malloc(sizeof(StackFrame));
VG_(memset)( sframe, 0, sizeof(*sframe) );
sframe->creation_sp = ~0UL;
@@ -2248,7 +2265,7 @@
while (frame) {
frame2 = frame->inner;
if (frame2) tl_assert(1 + frame->depth == frame2->depth);
- pc_free(frame);
+ sg_free(frame);
frame = frame2;
}
shadowStacks[child] = NULL;
@@ -2289,13 +2306,13 @@
// //
//////////////////////////////////////////////////////////////
-/* CALLED indirectly FROM GENERATED CODE */
+/* CALLED indirectly FROM GENERATED CODE. Calls here are created by
+ sp-change analysis, as requested in pc_pre_clo_int(). */
void sg_die_mem_stack ( Addr old_SP, SizeT len ) {
ThreadId tid = VG_(get_running_tid)();
shadowStack_unwind( tid, old_SP+len );
}
-
void sg_pre_clo_init ( void ) {
ourGlobals_init();
init_StackBlocks_set();
Modified: branches/PTRCHECK/exp-ptrcheck/sg_main.h
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/sg_main.h 2008-09-09 08:49:35 UTC (rev 8591)
+++ branches/PTRCHECK/exp-ptrcheck/sg_main.h 2008-09-09 11:10:29 UTC (rev 8592)
@@ -48,6 +48,28 @@
Bool rr, Bool ww, Bool xx, ULong di_handle );
void sg_die_mem_munmap ( Addr a, SizeT len );
+/* These really ought to be moved elsewhere, so that we don't have to
+ include this file in h_main.c. See comments in sg_main.c and
+ h_main.c for what this is about. */
+
+struct _SGEnv; /* abstract export */
+
+struct _SGEnv * sg_instrument_init ( void );
+
+void sg_instrument_fini ( struct _SGEnv * env );
+
+void sg_instrument_IRStmt ( /*MOD*/struct _SGEnv * env,
+ /*MOD*/IRSB* sbOut,
+ IRStmt* st,
+ VexGuestLayout* layout,
+ IRType gWordTy, IRType hWordTy );
+
+void sg_instrument_final_jump ( /*MOD*/struct _SGEnv * env,
+ /*MOD*/IRSB* sbOut,
+ IRExpr* next,
+ IRJumpKind jumpkind,
+ VexGuestLayout* layout,
+ IRType gWordTy, IRType hWordTy );
#endif
/*--------------------------------------------------------------------*/
Modified: branches/PTRCHECK/exp-ptrcheck.supp
===================================================================
--- branches/PTRCHECK/exp-ptrcheck.supp 2008-09-09 08:49:35 UTC (rev 8591)
+++ branches/PTRCHECK/exp-ptrcheck.supp 2008-09-09 11:10:29 UTC (rev 8592)
@@ -1,13 +1,13 @@
{
lib-X11-used-old-pointer-after-realloc-1
- exp-ptrcheck:LoadStore
+ exp-ptrcheck:Heap
fun:strlen
obj:/usr/lib*/libX11.so*
obj:/usr/lib*/libX11.so*
}
{
lib-X11-used-old-pointer-after-realloc-2
- exp-ptrcheck:LoadStore
+ exp-ptrcheck:Heap
obj:/usr/lib*/libX11.so*
obj:/usr/lib*/libX11.so*
}
|
|
From: <sv...@va...> - 2008-09-09 08:49:26
|
Author: sewardj Date: 2008-09-09 09:49:35 +0100 (Tue, 09 Sep 2008) New Revision: 8591 Log: Merge, from svn://svn.valgrind.org/branches/SGCHECK, core changes needed to support the sg_ part of this tool, mostly: * query functions for finding out the stack and global blocks visible at any given program counter value * add a ULong abstract handle to the DebugInfo structure, and use it to provide a mechanism whereby tools can reliably know when the debuginfo has been updated (and so query the new debuginfo if they want) This is believed to comprise essentially r8529, r8531, r8557, r8559. Modified: branches/PTRCHECK/coregrind/m_debuginfo/d3basics.c branches/PTRCHECK/coregrind/m_debuginfo/debuginfo.c branches/PTRCHECK/coregrind/m_debuginfo/priv_d3basics.h branches/PTRCHECK/coregrind/m_debuginfo/priv_misc.h branches/PTRCHECK/coregrind/m_debuginfo/priv_storage.h branches/PTRCHECK/coregrind/m_debuginfo/priv_tytypes.h branches/PTRCHECK/coregrind/m_main.c branches/PTRCHECK/coregrind/m_syswrap/syswrap-generic.c branches/PTRCHECK/coregrind/m_tooliface.c branches/PTRCHECK/coregrind/m_wordfm.c branches/PTRCHECK/coregrind/pub_core_debuginfo.h branches/PTRCHECK/coregrind/pub_core_tooliface.h branches/PTRCHECK/drd/drd_main.c branches/PTRCHECK/helgrind/hg_main.c branches/PTRCHECK/include/pub_tool_debuginfo.h branches/PTRCHECK/include/pub_tool_tooliface.h branches/PTRCHECK/include/pub_tool_wordfm.h branches/PTRCHECK/memcheck/mc_main.c Modified: branches/PTRCHECK/coregrind/m_debuginfo/d3basics.c =================================================================== --- branches/PTRCHECK/coregrind/m_debuginfo/d3basics.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_debuginfo/d3basics.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -38,10 +38,12 @@ #include "pub_core_libcassert.h" #include "pub_core_libcprint.h" #include "pub_core_options.h" +#include "pub_core_xarray.h" #include "pub_core_vki.h" /* VKI_PROT_READ */ #include "pub_core_aspacemgr.h" /* VG_(is_valid_for_client) */ +#include "priv_misc.h" #include "priv_d3basics.h" /* self */ HChar* ML_(pp_DW_children) ( DW_children hashch ) @@ -673,6 +675,147 @@ } +/* Evaluate a very simple Guarded (DWARF3) expression. The expression + is expected to denote a constant, with no reference to any + registers nor to any frame base expression. The expression is + expected to have at least one guard. If there is more than one + guard, all the sub-expressions are evaluated and compared. The + address ranges on the guards are ignored. GXR_Failure is returned + in the following circumstances: + * no guards + * any of the subexpressions require a frame base expression + * any of the subexpressions denote a register location + * any of the subexpressions do not produce a manifest constant + * there's more than one subexpression, all of which successfully + evaluate to a constant, but they don't all produce the same constant. + */ +GXResult ML_(evaluate_trivial_GX)( GExpr* gx, Addr data_bias ) +{ + GXResult res; + Addr aMin, aMax; + UChar uc; + UShort nbytes; + Word i, nGuards; + MaybeUWord *muw, *muw2; + + HChar* badness = NULL; + UChar* p = &gx->payload[0]; + XArray* results = VG_(newXA)( ML_(dinfo_zalloc), ML_(dinfo_free), + sizeof(MaybeUWord) ); + + uc = *p++; /*biasMe*/ + vg_assert(uc == 0 || uc == 1); + /* in fact it's senseless to evaluate if the guards need biasing. + So don't. */ + vg_assert(uc == 0); + + nGuards = 0; + while (True) { + MaybeUWord thisResult; + uc = *p++; + if (uc == 1) /*isEnd*/ + break; + vg_assert(uc == 0); + aMin = * (Addr*)p; p += sizeof(Addr); + aMax = * (Addr*)p; p += sizeof(Addr); + nbytes = * (UShort*)p; p += sizeof(UShort); + nGuards++; + if (0) VG_(printf)(" guard %ld: %#lx %#lx\n", + nGuards, aMin,aMax); + + thisResult.b = False; + thisResult.w = 0; + + /* Peer at this particular subexpression, to see if it's + obviously a constant. */ + if (nbytes == 1 + sizeof(Addr) && *p == DW_OP_addr) { + thisResult.b = True; + thisResult.w = *(Addr*)(p+1) + data_bias; + } + else if (nbytes == 2 + sizeof(Addr) + && *p == DW_OP_addr + && *(p + 1 + sizeof(Addr)) == DW_OP_GNU_push_tls_address) { + if (!badness) + badness = "trivial GExpr is DW_OP_addr plus trailing junk"; + } + else if (nbytes >= 1 && *p >= DW_OP_reg0 && *p <= DW_OP_reg31) { + if (!badness) + badness = "trivial GExpr denotes register (1)"; + } + else if (nbytes >= 1 && *p == DW_OP_fbreg) { + if (!badness) + badness = "trivial GExpr requires fbGX"; + } + else if (nbytes >= 1 && *p >= DW_OP_breg0 && *p <= DW_OP_breg31) { + if (!badness) + badness = "trivial GExpr requires register value"; + } + else if (nbytes >= 1 && *p == DW_OP_regx) { + if (!badness) + badness = "trivial GExpr denotes register (2)"; + } + else { + VG_(printf)(" ML_(evaluate_trivial_GX): unhandled:\n "); + ML_(pp_GX)( gx ); + VG_(printf)("\n"); + tl_assert(0); + } + + VG_(addToXA)( results, &thisResult ); + + p += (UWord)nbytes; + } + + res.kind = GXR_Failure; + + tl_assert(nGuards == VG_(sizeXA)( results )); + tl_assert(nGuards >= 0); + if (nGuards == 0) { + tl_assert(!badness); + res.word = (UWord)"trivial GExpr has no guards (!)"; + VG_(deleteXA)( results ); + return res; + } + + for (i = 0; i < nGuards; i++) { + muw = VG_(indexXA)( results, i ); + if (muw->b == False) + break; + } + + vg_assert(i >= 0 && i <= nGuards); + if (i < nGuards) { + /* at least one subexpression failed to produce a manifest constant. */ + vg_assert(badness); + res.word = (UWord)badness; + VG_(deleteXA)( results ); + return res; + } + + /* All the subexpressions produced a constant, but did they all produce + the same one? */ + muw = VG_(indexXA)( results, 0 ); + tl_assert(muw->b == True); /* we just established that all exprs are ok */ + + for (i = 1; i < nGuards; i++) { + muw2 = VG_(indexXA)( results, i ); + tl_assert(muw2->b == True); + if (muw2->w != muw->w) { + res.word = (UWord)"trivial GExpr: subexpressions disagree"; + VG_(deleteXA)( results ); + return res; + } + } + + /* Well, we have success. All subexpressions evaluated, and + they all agree. Hurrah. */ + res.kind = GXR_Value; + res.word = muw->w; + VG_(deleteXA)( results ); + return res; +} + + void ML_(pp_GXResult) ( GXResult res ) { switch (res.kind) { Modified: branches/PTRCHECK/coregrind/m_debuginfo/debuginfo.c =================================================================== --- branches/PTRCHECK/coregrind/m_debuginfo/debuginfo.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_debuginfo/debuginfo.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -156,6 +156,11 @@ /*--- Notification (acquire/discard) helpers ---*/ /*------------------------------------------------------------*/ +/* Gives out unique abstract handles for allocated DebugInfos. See + comment in priv_storage.h, declaration of struct _DebugInfo, for + details. */ +static ULong handle_counter = 1; + /* Allocate and zero out a new DebugInfo record. */ static DebugInfo* alloc_DebugInfo( const UChar* filename, @@ -167,6 +172,7 @@ vg_assert(filename); di = ML_(dinfo_zalloc)(sizeof(DebugInfo)); + di->handle = handle_counter++; di->filename = ML_(dinfo_strdup)(filename); di->memname = memname ? ML_(dinfo_strdup)(memname) : NULL; @@ -490,14 +496,22 @@ will try load debug info if the mapping at 'a' belongs to Valgrind; whereas normally (False) it will not do that. This allows us to carefully control when the thing will read symbols from the - Valgrind executable itself. */ + Valgrind executable itself. -void VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ) + If a call to VG_(di_notify_mmap) causes debug info to be read, then + the returned ULong is an abstract handle which can later be used to + refer to the debuginfo read as a result of this specific mapping, + in later queries to m_debuginfo. In this case the handle value + will be one or above. If the returned value is zero, no debug info + was read. */ + +ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ) { NSegment const * seg; HChar* filename; Bool ok, is_rx_map, is_rw_map; DebugInfo* di; + ULong di_handle; SysRes fd; Int nread; HChar buf1k[1024]; @@ -523,12 +537,12 @@ /* Ignore non-file mappings */ if ( ! (seg->kind == SkFileC || (seg->kind == SkFileV && allow_SkFileV)) ) - return; + return 0; /* If the file doesn't have a name, we're hosed. Give up. */ filename = VG_(am_get_filename)( (NSegment*)seg ); if (!filename) - return; + return 0; if (debug) VG_(printf)("di_notify_mmap-2: %s\n", filename); @@ -550,13 +564,13 @@ fake_di.filename = filename; ML_(symerr)(&fake_di, True, "failed to stat64/stat this file"); } - return; + return 0; } /* Finally, the point of all this stattery: if it's not a regular file, don't try to read debug info from it. */ if (! VKI_S_ISREG(statbuf.st_mode)) - return; + return 0; /* no uses of statbuf below here. */ @@ -572,25 +586,25 @@ fake_di.filename = filename; ML_(symerr)(&fake_di, True, "can't open file to inspect ELF header"); } - return; + return 0; } nread = VG_(read)( fd.res, buf1k, sizeof(buf1k) ); VG_(close)( fd.res ); if (nread == 0) - return; + return 0; if (nread < 0) { DebugInfo fake_di; VG_(memset)(&fake_di, 0, sizeof(fake_di)); fake_di.filename = filename; ML_(symerr)(&fake_di, True, "can't read file to inspect ELF header"); - return; + return 0; } vg_assert(nread > 0 && nread <= sizeof(buf1k) ); /* We're only interested in mappings of ELF object files. */ if (!ML_(is_elf_object_file)( buf1k, (SizeT)nread )) - return; + return 0; /* Now we have to guess if this is a text-like mapping, a data-like mapping, neither or both. The rules are: @@ -645,7 +659,7 @@ /* If it is neither text-ish nor data-ish, we're not interested. */ if (!(is_rx_map || is_rw_map)) - return; + return 0; /* See if we have a DebugInfo for this filename. If not, create one. */ @@ -676,48 +690,58 @@ } } - if (di->have_rx_map && di->have_rw_map && !di->have_dinfo) { + /* If we don't have an rx and rw mapping, or if we already have + debuginfo for this mapping for whatever reason, go no + further. */ + if ( ! (di->have_rx_map && di->have_rw_map && !di->have_dinfo) ) + return 0; - vg_assert(di->filename); - TRACE_SYMTAB("\n"); - TRACE_SYMTAB("------ start ELF OBJECT " - "------------------------------\n"); - TRACE_SYMTAB("------ name = %s\n", di->filename); - TRACE_SYMTAB("\n"); + /* Ok, so, finally, let's try to read the debuginfo. */ + vg_assert(di->filename); + TRACE_SYMTAB("\n"); + TRACE_SYMTAB("------ start ELF OBJECT " + "------------------------------\n"); + TRACE_SYMTAB("------ name = %s\n", di->filename); + TRACE_SYMTAB("\n"); - /* We're going to read symbols and debug info for the avma - ranges [rx_map_avma, +rx_map_size) and [rw_map_avma, - +rw_map_size). First get rid of any other DebugInfos which - overlap either of those ranges (to avoid total confusion). */ - discard_DebugInfos_which_overlap_with( di ); + /* We're going to read symbols and debug info for the avma + ranges [rx_map_avma, +rx_map_size) and [rw_map_avma, + +rw_map_size). First get rid of any other DebugInfos which + overlap either of those ranges (to avoid total confusion). */ + discard_DebugInfos_which_overlap_with( di ); - /* .. and acquire new info. */ - ok = ML_(read_elf_debug_info)( di ); + /* .. and acquire new info. */ + ok = ML_(read_elf_debug_info)( di ); - if (ok) { - TRACE_SYMTAB("\n------ Canonicalising the " - "acquired info ------\n"); - /* prepare read data for use */ - ML_(canonicaliseTables)( di ); - /* notify m_redir about it */ - TRACE_SYMTAB("\n------ Notifying m_redir ------\n"); - VG_(redir_notify_new_DebugInfo)( di ); - /* Note that we succeeded */ - di->have_dinfo = True; - } else { - TRACE_SYMTAB("\n------ ELF reading failed ------\n"); - /* Something went wrong (eg. bad ELF file). Should we delete - this DebugInfo? No - it contains info on the rw/rx - mappings, at least. */ - } + if (ok) { - TRACE_SYMTAB("\n"); - TRACE_SYMTAB("------ name = %s\n", di->filename); - TRACE_SYMTAB("------ end ELF OBJECT " - "------------------------------\n"); - TRACE_SYMTAB("\n"); + TRACE_SYMTAB("\n------ Canonicalising the " + "acquired info ------\n"); + /* prepare read data for use */ + ML_(canonicaliseTables)( di ); + /* notify m_redir about it */ + TRACE_SYMTAB("\n------ Notifying m_redir ------\n"); + VG_(redir_notify_new_DebugInfo)( di ); + /* Note that we succeeded */ + di->have_dinfo = True; + tl_assert(di->handle > 0); + di_handle = di->handle; + } else { + TRACE_SYMTAB("\n------ ELF reading failed ------\n"); + /* Something went wrong (eg. bad ELF file). Should we delete + this DebugInfo? No - it contains info on the rw/rx + mappings, at least. */ + di_handle = 0; } + + TRACE_SYMTAB("\n"); + TRACE_SYMTAB("------ name = %s\n", di->filename); + TRACE_SYMTAB("------ end ELF OBJECT " + "------------------------------\n"); + TRACE_SYMTAB("\n"); + + return di_handle; } @@ -1867,7 +1891,6 @@ dname1[n_dname-1] = dname2[n_dname-1] = 0; } - /* Determine if data_addr is a local variable in the frame characterised by (ip,sp,fp), and if so write its description into dname{1,2}[0..n_dname-1], and return True. If not, return @@ -2023,7 +2046,7 @@ scope. */ for (di = debugInfo_list; di != NULL; di = di->next) { OSet* global_scope; - Int gs_size; + Word gs_size; Addr zero; DiAddrRange* global_arange; Word i; @@ -2197,6 +2220,373 @@ } +////////////////////////////////////////////////////////////////// +// // +// Support for other kinds of queries to the Dwarf3 var info // +// // +////////////////////////////////////////////////////////////////// + +/* Figure out if the variable 'var' has a location that is linearly + dependent on a stack pointer value, or a frame pointer value, and + if it is, add a description of it to 'blocks'. Otherwise ignore + it. If 'arrays_only' is True, also ignore it unless it has an + array type. */ + +static +void analyse_deps ( /*MOD*/XArray* /* of FrameBlock */ blocks, + Addr ip, Addr data_bias, DiVariable* var, + Bool arrays_only ) +{ + GXResult res_sp_6k, res_sp_7k, res_fp_6k, res_fp_7k; + RegSummary regs; + MaybeUWord muw; + Bool isVec; + + Bool debug = False; + if (0&&debug) + VG_(printf)("adeps: var %s\n", var->name ); + + /* Figure out how big the variable is. */ + muw = ML_(sizeOfType)(var->type); + /* if this var has a type whose size is unknown or zero, it should + never have been added. ML_(addVar) should have rejected it. */ + vg_assert(muw.b == True); + vg_assert(muw.w > 0); + + /* skip if non-array and we're only interested in arrays */ + isVec = var->type->tag == Ty_Array; + if (arrays_only && !isVec) return; + + if (0) {ML_(pp_Type_C_ishly)(var->type); + VG_(printf)(" %s\n", var->name);} + + /* Do some test evaluations of the variable's location expression, + in order to guess whether it is sp-relative, fp-relative, or + none. A crude hack, which can be interpreted roughly as finding + the first derivative of the location expression w.r.t. the + supplied frame and stack pointer values. */ + regs.fp = 0; + regs.ip = ip; + regs.sp = 6 * 1024; + res_sp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, data_bias ); + + regs.fp = 0; + regs.ip = ip; + regs.sp = 7 * 1024; + res_sp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, data_bias ); + + regs.fp = 6 * 1024; + regs.ip = ip; + regs.sp = 0; + res_fp_6k = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, data_bias ); + + regs.fp = 7 * 1024; + regs.ip = ip; + regs.sp = 0; + res_fp_7k = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, data_bias ); + + vg_assert(res_sp_6k.kind == res_sp_7k.kind); + vg_assert(res_sp_6k.kind == res_fp_6k.kind); + vg_assert(res_sp_6k.kind == res_fp_7k.kind); + + if (res_sp_6k.kind == GXR_Value) { + StackBlock block; + GXResult res; + UWord sp_delta = res_sp_7k.word - res_sp_6k.word; + UWord fp_delta = res_fp_7k.word - res_fp_6k.word; + tl_assert(sp_delta == 0 || sp_delta == 1024); + tl_assert(fp_delta == 0 || fp_delta == 1024); + + if (sp_delta == 0 && fp_delta == 0) { + /* depends neither on sp nor fp, so it can't be a stack + local. Ignore it. */ + } + else + if (sp_delta == 1024 && fp_delta == 0) { + regs.sp = regs.fp = 0; + regs.ip = ip; + res = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, data_bias ); + tl_assert(res.kind == GXR_Value); + if (debug) + VG_(printf)(" %5ld .. %5ld (sp) %s\n", + res.word, res.word + muw.w - 1, var->name); + block.base = res.word; + block.szB = muw.w; + block.spRel = True; + block.isVec = isVec; + VG_(memset)( &block.name[0], 0, sizeof(block.name) ); + if (var->name) + VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 ); + block.name[ sizeof(block.name)-1 ] = 0; + VG_(addToXA)( blocks, &block ); + } + else + if (sp_delta == 0 && fp_delta == 1024) { + regs.sp = regs.fp = 0; + regs.ip = ip; + res = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, data_bias ); + tl_assert(res.kind == GXR_Value); + if (debug) + VG_(printf)(" %5ld .. %5ld (FP) %s\n", + res.word, res.word + muw.w - 1, var->name); + block.base = res.word; + block.szB = muw.w; + block.spRel = False; + block.isVec = isVec; + VG_(memset)( &block.name[0], 0, sizeof(block.name) ); + if (var->name) + VG_(strncpy)( &block.name[0], var->name, sizeof(block.name)-1 ); + block.name[ sizeof(block.name)-1 ] = 0; + VG_(addToXA)( blocks, &block ); + } + else { + vg_assert(0); + } + } +} + + +/* Get an XArray of StackBlock which describe the stack (auto) blocks + for this ip. The caller is expected to free the XArray at some + point. If 'arrays_only' is True, only array-typed blocks are + returned; otherwise blocks of all types are returned. */ + +void* /* really, XArray* of StackBlock */ + VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only ) +{ + /* This is a derivation of consider_vars_in_frame() above. */ + Word i; + DebugInfo* di; + RegSummary regs; + Bool debug = False; + + XArray* res = VG_(newXA)( ML_(dinfo_zalloc), ML_(dinfo_free), + sizeof(StackBlock) ); + + static UInt n_search = 0; + static UInt n_steps = 0; + n_search++; + if (debug) + VG_(printf)("QQQQ: dgsbai: ip %#lx\n", ip); + /* first, find the DebugInfo that pertains to 'ip'. */ + for (di = debugInfo_list; di; di = di->next) { + n_steps++; + /* text segment missing? unlikely, but handle it .. */ + if (!di->text_present || di->text_size == 0) + continue; + /* Ok. So does this text mapping bracket the ip? */ + if (di->text_avma <= ip && ip < di->text_avma + di->text_size) + break; + } + + /* Didn't find it. Strange -- means ip is a code address outside + of any mapped text segment. Unlikely but not impossible -- app + could be generating code to run. */ + if (!di) + return res; /* currently empty */ + + if (0 && ((n_search & 0x1) == 0)) + VG_(printf)("VG_(di_get_stack_blocks_at_ip): %u searches, " + "%u DebugInfos looked at\n", + n_search, n_steps); + /* Start of performance-enhancing hack: once every ??? (chosen + hackily after profiling) successful searches, move the found + DebugInfo one step closer to the start of the list. This makes + future searches cheaper. */ + if ((n_search & 0xFFFF) == 0) { + /* Move si one step closer to the start of the list. */ + move_DebugInfo_one_step_forward( di ); + } + /* End of performance-enhancing hack. */ + + /* any var info at all? */ + if (!di->varinfo) + return res; /* currently empty */ + + /* Work through the scopes from most deeply nested outwards, + looking for code address ranges that bracket 'ip'. The + variables on each such address range found are in scope right + now. Don't descend to level zero as that is the global + scope. */ + regs.ip = ip; + regs.sp = 0; + regs.fp = 0; + + /* "for each scope, working outwards ..." */ + for (i = VG_(sizeXA)(di->varinfo) - 1; i >= 1; i--) { + XArray* vars; + Word j; + DiAddrRange* arange; + OSet* this_scope + = *(OSet**)VG_(indexXA)( di->varinfo, i ); + if (debug) + VG_(printf)("QQQQ: considering scope %ld\n", (Word)i); + if (!this_scope) + continue; + /* Find the set of variables in this scope that + bracket the program counter. */ + arange = VG_(OSetGen_LookupWithCmp)( + this_scope, &ip, + ML_(cmp_for_DiAddrRange_range) + ); + if (!arange) + continue; + /* stay sane */ + vg_assert(arange->aMin <= arange->aMax); + /* It must bracket the ip we asked for, else + ML_(cmp_for_DiAddrRange_range) is somehow broken. */ + vg_assert(arange->aMin <= ip && ip <= arange->aMax); + /* It must have an attached XArray of DiVariables. */ + vars = arange->vars; + vg_assert(vars); + /* But it mustn't cover the entire address range. We only + expect that to happen for the global scope (level 0), which + we're not looking at here. Except, it may cover the entire + address range, but in that case the vars array must be + empty. */ + vg_assert(! (arange->aMin == (Addr)0 + && arange->aMax == ~(Addr)0 + && VG_(sizeXA)(vars) > 0) ); + for (j = 0; j < VG_(sizeXA)( vars ); j++) { + DiVariable* var = (DiVariable*)VG_(indexXA)( vars, j ); + if (debug) + VG_(printf)("QQQQ: var:name=%s %#lx-%#lx %#lx\n", + var->name,arange->aMin,arange->aMax,ip); + analyse_deps( res, ip, di->data_bias, var, arrays_only ); + } + } + + return res; +} + + +/* Get an array of GlobalBlock which describe the global blocks owned + by the shared object characterised by the given di_handle. Asserts + if the handle is invalid. The caller is responsible for freeing + the array at some point. If 'arrays_only' is True, only + array-typed blocks are returned; otherwise blocks of all types are + returned. */ + +void* /* really, XArray* of GlobalBlock */ + VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle, + Bool arrays_only ) +{ + /* This is a derivation of consider_vars_in_frame() above. */ + + DebugInfo* di; + XArray* gvars; /* XArray* of GlobalBlock */ + Word nScopes, scopeIx; + + /* The first thing to do is find the DebugInfo that + pertains to 'di_handle'. */ + tl_assert(di_handle > 0); + for (di = debugInfo_list; di; di = di->next) { + if (di->handle == di_handle) + break; + } + + /* If this fails, we were unable to find any DebugInfo with the + given handle. This is considered an error on the part of the + caller. */ + tl_assert(di != NULL); + + /* we'll put the collected variables in here. */ + gvars = VG_(newXA)( ML_(dinfo_zalloc), ML_(dinfo_free), sizeof(GlobalBlock) ); + tl_assert(gvars); + + /* any var info at all? */ + if (!di->varinfo) + return gvars; + + /* we'll iterate over all the variables we can find, even if + it seems senseless to visit stack-allocated variables */ + /* Iterate over all scopes */ + nScopes = VG_(sizeXA)( di->varinfo ); + for (scopeIx = 0; scopeIx < nScopes; scopeIx++) { + + /* Iterate over each (code) address range at the current scope */ + DiAddrRange* range; + OSet* /* of DiAddrInfo */ scope + = *(OSet**)VG_(indexXA)( di->varinfo, scopeIx ); + tl_assert(scope); + VG_(OSetGen_ResetIter)(scope); + while ( (range = VG_(OSetGen_Next)(scope)) ) { + + /* Iterate over each variable in the current address range */ + Word nVars, varIx; + tl_assert(range->vars); + nVars = VG_(sizeXA)( range->vars ); + for (varIx = 0; varIx < nVars; varIx++) { + + Bool isVec; + GXResult res; + MaybeUWord muw; + GlobalBlock gb; + DiVariable* var = VG_(indexXA)( range->vars, varIx ); + tl_assert(var->name); + if (0) VG_(printf)("at depth %ld var %s ", scopeIx, var->name ); + + /* Now figure out if this variable has a constant address + (that is, independent of FP, SP, phase of moon, etc), + and if so, what the address is. Any variable with a + constant address is deemed to be a global so we collect + it. */ + if (0) { VG_(printf)("EVAL: "); ML_(pp_GX)(var->gexpr); + VG_(printf)("\n"); } + res = ML_(evaluate_trivial_GX)( var->gexpr, di->data_bias ); + + /* Not a constant address => not interesting */ + if (res.kind != GXR_Value) { + if (0) VG_(printf)("FAIL\n"); + continue; + } + + /* Ok, it's a constant address. See if we want to collect + it. */ + if (0) VG_(printf)("%#lx\n", res.word); + + /* Figure out how big the variable is. */ + muw = ML_(sizeOfType)(var->type); + + /* if this var has a type whose size is unknown or zero, + it should never have been added. ML_(addVar) should + have rejected it. */ + vg_assert(muw.b == True); + vg_assert(muw.w > 0); + + /* skip if non-array and we're only interested in + arrays */ + isVec = var->type->tag == Ty_Array; + if (arrays_only && !isVec) continue; + + /* Ok, so collect it! */ + tl_assert(var->name); + tl_assert(di->soname); + if (0) VG_(printf)("XXXX %s %s %d\n", var->name, + var->fileName?(HChar*)var->fileName + :"??",var->lineNo); + VG_(memset)(&gb, 0, sizeof(gb)); + gb.addr = res.word; + gb.szB = muw.w; + gb.isVec = isVec; + VG_(strncpy)(&gb.name[0], var->name, sizeof(gb.name)-1); + VG_(strncpy)(&gb.soname[0], di->soname, sizeof(gb.soname)-1); + tl_assert(gb.name[ sizeof(gb.name)-1 ] == 0); + tl_assert(gb.soname[ sizeof(gb.soname)-1 ] == 0); + + VG_(addToXA)( gvars, &gb ); + + } /* for (varIx = 0; varIx < nVars; varIx++) */ + + } /* while ( (range = VG_(OSetGen_Next)(scope)) ) */ + + } /* for (scopeIx = 0; scopeIx < nScopes; scopeIx++) */ + + return gvars; +} + + + /*------------------------------------------------------------*/ /*--- DebugInfo accessor functions ---*/ /*------------------------------------------------------------*/ Modified: branches/PTRCHECK/coregrind/m_debuginfo/priv_d3basics.h =================================================================== --- branches/PTRCHECK/coregrind/m_debuginfo/priv_d3basics.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_debuginfo/priv_d3basics.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -635,6 +635,15 @@ Addr data_bias, Bool push_initial_zero ); +/* Evaluate a very simple Guarded (DWARF3) expression. The expression + is expected to denote a constant, with no reference to any + registers nor to any frame base expression. GXR_Failure is + returned if there is more than one guard, or none, a register + location is denoted, a frame base expression is required, or the + expression is not manifestly a constant. The range of addresses + covered by the guard is also ignored. */ +GXResult ML_(evaluate_trivial_GX)( GExpr* gx, Addr data_bias ); + #endif /* ndef __PRIV_D3BASICS_H */ /*--------------------------------------------------------------------*/ Modified: branches/PTRCHECK/coregrind/m_debuginfo/priv_misc.h =================================================================== --- branches/PTRCHECK/coregrind/m_debuginfo/priv_misc.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_debuginfo/priv_misc.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -42,7 +42,11 @@ void ML_(dinfo_free)( void* v ); UChar* ML_(dinfo_strdup)( const UChar* str ); +/* A handy type, a la Haskell's Maybe type. Yes, I know, C sucks. + Been there. Done that. Seen the movie. Got the T-shirt. Etc. */ +typedef struct { UWord w; Bool b; } MaybeUWord; + #endif /* ndef __PRIV_MISC_H */ /*--------------------------------------------------------------------*/ Modified: branches/PTRCHECK/coregrind/m_debuginfo/priv_storage.h =================================================================== --- branches/PTRCHECK/coregrind/m_debuginfo/priv_storage.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_debuginfo/priv_storage.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -248,6 +248,16 @@ struct _DebugInfo* next; /* list of DebugInfos */ Bool mark; /* marked for deletion? */ + /* An abstract handle, which can be used by entities outside of + m_debuginfo to (in an abstract datatype sense) refer to this + struct _DebugInfo. A .handle of zero is invalid; valid handles + are 1 and above. The same handle is never issued twice (in any + given run of Valgrind), so a handle becomes invalid when the + associated struct _DebugInfo is discarded, and remains invalid + forever thereafter. The .handle field is set as soon as this + structure is allocated. */ + ULong handle; + /* Used for debugging only - indicate what stuff to dump whilst reading stuff into the seginfo. Are computed as early in the lifetime of the DebugInfo as possible -- at the point when it is Modified: branches/PTRCHECK/coregrind/m_debuginfo/priv_tytypes.h =================================================================== --- branches/PTRCHECK/coregrind/m_debuginfo/priv_tytypes.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_debuginfo/priv_tytypes.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -153,9 +153,6 @@ /* How big is this type? (post-resolved only) If .b in the returned struct is False, the size is unknown. */ /* FIXME: check all pointers before dereferencing */ - -typedef struct { UWord w; Bool b; } MaybeUWord; - MaybeUWord ML_(sizeOfType)( Type* ty ); /* Describe where in the type 'offset' falls. Caller must Modified: branches/PTRCHECK/coregrind/m_main.c =================================================================== --- branches/PTRCHECK/coregrind/m_main.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_main.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -1125,6 +1125,11 @@ static IIFinaliseImageInfo the_iifii; +/* A simple pair structure, used for conveying debuginfo handles to + calls to VG_TRACK(new_mem_startup, ...). */ +typedef struct { Addr a; ULong ull; } Addr_n_ULong; + + /* --- Forwards decls to do with shutdown --- */ static void final_tidyup(ThreadId tid); @@ -1185,6 +1190,7 @@ Int loglevel, i; Bool logging_to_fd; struct vki_rlimit zero = { 0, 0 }; + XArray* addr2dihandle = NULL; //============================================================ // @@ -1711,11 +1717,28 @@ // p: setup_code_redirect_table [so that redirs can be recorded] // p: mallocfree // p: probably: setup fds and process CLOs, so that logging works + // + // While doing this, make a note of the debuginfo-handles that + // come back from VG_(di_notify_mmap)/VG_(di_aix5_notify_segchange). + // Later, in "Tell the tool about the initial client memory permissions" + // (just below) we can then hand these handles off to the tool in + // calls to VG_TRACK(new_mem_startup, ...). This gives the tool the + // opportunity to make further queries to m_debuginfo before the + // client is started, if it wants. We put this information into an + // XArray, each handle along with the associated segment start address, + // and search the XArray for the handles later, when calling + // VG_TRACK(new_mem_startup, ...). //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Load initial debug info\n"); + + tl_assert(!addr2dihandle); + addr2dihandle = VG_(newXA)( VG_(malloc), VG_(free), sizeof(Addr_n_ULong) ); + tl_assert(addr2dihandle); + # if defined(VGO_linux) { Addr* seg_starts; Int n_seg_starts; + Addr_n_ULong anu; seg_starts = get_seg_starts( &n_seg_starts ); vg_assert(seg_starts && n_seg_starts >= 0); @@ -1723,14 +1746,22 @@ /* show them all to the debug info reader. allow_SkFileV has to be True here so that we read info from the valgrind executable itself. */ - for (i = 0; i < n_seg_starts; i++) - VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ ); + for (i = 0; i < n_seg_starts; i++) { + anu.ull = VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ ); + /* anu.ull holds the debuginfo handle returned by di_notify_mmap, + if any. */ + if (anu.ull > 0) { + anu.a = seg_starts[i]; + VG_(addToXA)( addr2dihandle, &anu ); + } + } VG_(free)( seg_starts ); } # elif defined(VGO_aix5) { AixCodeSegChange* changes; Int changes_size, changes_used; + Addr_n_ULong anu; /* Find out how many AixCodeSegChange records we will need, and acquire them. */ @@ -1743,17 +1774,23 @@ vg_assert(changes_used >= 0 && changes_used <= changes_size); /* And notify m_debuginfo of the changes. */ - for (i = 0; i < changes_used; i++) - VG_(di_aix5_notify_segchange)( - changes[i].code_start, - changes[i].code_len, - changes[i].data_start, - changes[i].data_len, - changes[i].file_name, - changes[i].mem_name, - changes[i].is_mainexe, - changes[i].acquire - ); + for (i = 0; i < changes_used; i++) { + anu.ull = VG_(di_aix5_notify_segchange)( + changes[i].code_start, + changes[i].code_len, + changes[i].data_start, + changes[i].data_len, + changes[i].file_name, + changes[i].mem_name, + changes[i].is_mainexe, + changes[i].acquire + ); + if (anu.ull > 0) { + tl_assert(changes[i].acquire); + anu.a = changes[i].code_start; /* is this correct? */ + VG_(addToXA)( addr2dihandle, &anu ); + } + } VG_(free)(changes); } @@ -1797,11 +1834,18 @@ // p: mallocfree // p: setup_client_stack // p: setup_client_dataseg + // + // For each segment we tell the client about, look up in + // addr2dihandle as created above, to see if there's a debuginfo + // handle associated with the segment, that we can hand along + // to the tool, to be helpful. //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Tell tool about initial permissions\n"); { Addr* seg_starts; Int n_seg_starts; + tl_assert(addr2dihandle); + /* Mark the main thread as running while we tell the tool about the client memory so that the tool can associate that memory with the main thread. */ @@ -1813,9 +1857,11 @@ /* show interesting ones to the tool */ for (i = 0; i < n_seg_starts; i++) { + Word j, n; NSegment const* seg = VG_(am_find_nsegment)( seg_starts[i] ); vg_assert(seg); + vg_assert(seg->start == seg_starts[i] ); if (seg->kind == SkFileC || seg->kind == SkAnonC) { VG_(debugLog)(2, "main", "tell tool about %010lx-%010lx %c%c%c\n", @@ -1823,12 +1869,28 @@ seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-', seg->hasX ? 'x' : '-' ); + /* search addr2dihandle to see if we have an entry + matching seg->start. */ + n = VG_(sizeXA)( addr2dihandle ); + for (j = 0; j < n; j++) { + Addr_n_ULong* anl = VG_(indexXA)( addr2dihandle, j ); + if (anl->a == seg->start) { + tl_assert(anl->ull > 0); /* check it's a valid handle */ + break; + } + } + vg_assert(j >= 0 && j <= n); VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start, - seg->hasR, seg->hasW, seg->hasX ); + seg->hasR, seg->hasW, seg->hasX, + /* and the retrieved debuginfo handle, if any */ + j < n + ? ((Addr_n_ULong*)VG_(indexXA)( addr2dihandle, j ))->ull + : 0 ); } } VG_(free)( seg_starts ); + VG_(deleteXA)( addr2dihandle ); /* Also do the initial stack permissions. */ { NSegment const* seg @@ -1865,7 +1927,8 @@ - (Addr)&VG_(trampoline_stuff_start), False, /* readable? */ False, /* writable? */ - True /* executable? */ ); + True /* executable? */, + 0 /* di_handle: no associated debug info */ ); /* Clear the running thread indicator */ VG_(running_tid) = VG_INVALID_THREADID; Modified: branches/PTRCHECK/coregrind/m_syswrap/syswrap-generic.c =================================================================== --- branches/PTRCHECK/coregrind/m_syswrap/syswrap-generic.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_syswrap/syswrap-generic.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -65,7 +65,8 @@ void notify_aspacem_of_mmap(Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset); static -void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, Off64T offset); +void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, Off64T offset, + ULong di_handle); /* Returns True iff address range is something the client can @@ -151,13 +152,22 @@ /* When a client mmap has been successfully done, this function must be called. It notifies both aspacem and the tool of the new mapping. -*/ + + JRS 2008-Aug-14: But notice this is *very* obscure. The only place + it is called from is POST(sys_io_setup). In particular, + ML_(generic_PRE_sys_mmap), further down in this file, is the + "normal case" handler for client mmap. But it doesn't call this + function; instead it does the relevant notifications itself. Here, + we just pass di_handle=0 to notify_tool_of_mmap as we have no + better information. But really this function should be done away + with; problem is I don't understand what POST(sys_io_setup) does or + how it works. */ void ML_(notify_aspacem_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset ) { notify_aspacem_of_mmap(a, len, prot, flags, fd, offset); - notify_tool_of_mmap(a, len, prot, offset); + notify_tool_of_mmap(a, len, prot, offset, 0/*di_handle*/); } static @@ -179,7 +189,8 @@ } static -void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, Off64T offset) +void notify_tool_of_mmap(Addr a, SizeT len, UInt prot, Off64T offset, + ULong di_handle) { Bool rr, ww, xx; @@ -192,7 +203,7 @@ ww = toBool(prot & VKI_PROT_WRITE); xx = toBool(prot & VKI_PROT_EXEC); - VG_TRACK( new_mem_mmap, a, len, rr, ww, xx ); + VG_TRACK( new_mem_mmap, a, len, rr, ww, xx, di_handle ); } /* Expand (or shrink) an existing mapping, potentially moving it at @@ -332,7 +343,8 @@ MIN_SIZET(old_len,new_len) ); if (new_len > old_len) VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len, - old_seg->hasR, old_seg->hasW, old_seg->hasX ); + old_seg->hasR, old_seg->hasW, old_seg->hasX, + 0/*di_handle*/ ); VG_TRACK(die_mem_munmap, old_addr, old_len); if (d) { VG_(discard_translations)( old_addr, old_len, "do_remap(1)" ); @@ -375,7 +387,8 @@ if (ok) { VG_TRACK( new_mem_mmap, needA, needL, old_seg->hasR, - old_seg->hasW, old_seg->hasX ); + old_seg->hasW, old_seg->hasX, + 0/*di_handle*/ ); if (d) VG_(discard_translations)( needA, needL, "do_remap(3)" ); return VG_(mk_SysRes_Success)( old_addr ); @@ -395,7 +408,8 @@ MIN_SIZET(old_len,new_len) ); if (new_len > old_len) VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len, - old_seg->hasR, old_seg->hasW, old_seg->hasX ); + old_seg->hasR, old_seg->hasW, old_seg->hasX, + 0/*di_handle*/ ); VG_TRACK(die_mem_munmap, old_addr, old_len); if (d) { VG_(discard_translations)( old_addr, old_len, "do_remap(4)" ); @@ -434,7 +448,8 @@ if (!ok) goto eNOMEM; VG_TRACK( new_mem_mmap, needA, needL, - old_seg->hasR, old_seg->hasW, old_seg->hasX ); + old_seg->hasR, old_seg->hasW, old_seg->hasX, + 0/*di_handle*/ ); if (d) VG_(discard_translations)( needA, needL, "do_remap(6)" ); return VG_(mk_SysRes_Success)( old_addr ); @@ -1722,7 +1737,8 @@ /* we don't distinguish whether it's read-only or * read-write -- it doesn't matter really. */ - VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False ); + VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False, + 0/*di_handle*/ ); if (d) VG_(discard_translations)( (Addr64)res, (ULong)VG_PGROUNDUP(segmentSize), @@ -1937,6 +1953,7 @@ } if (!sres.isError) { + ULong di_handle; /* Notify aspacem. */ notify_aspacem_of_mmap( (Addr)sres.res, /* addr kernel actually assigned */ @@ -1947,13 +1964,15 @@ arg6 /* offset */ ); /* Load symbols? */ - VG_(di_notify_mmap)( (Addr)sres.res, False/*allow_SkFileV*/ ); + di_handle = VG_(di_notify_mmap)( (Addr)sres.res, False/*allow_SkFileV*/ ); /* Notify the tool. */ notify_tool_of_mmap( (Addr)sres.res, /* addr kernel actually assigned */ arg2, /* length */ arg3, /* prot */ - arg6 /* offset */ + arg6, /* offset */ + di_handle /* so the tool can refer to the read debuginfo later, + if it wants. */ ); } Modified: branches/PTRCHECK/coregrind/m_tooliface.c =================================================================== --- branches/PTRCHECK/coregrind/m_tooliface.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_tooliface.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -340,10 +340,10 @@ VG_(tdict).fn = f; \ } -DEF0(track_new_mem_startup, Addr, SizeT, Bool, Bool, Bool) +DEF0(track_new_mem_startup, Addr, SizeT, Bool, Bool, Bool, ULong) DEF0(track_new_mem_stack_signal, Addr, SizeT, UInt) DEF0(track_new_mem_brk, Addr, SizeT, UInt) -DEF0(track_new_mem_mmap, Addr, SizeT, Bool, Bool, Bool) +DEF0(track_new_mem_mmap, Addr, SizeT, Bool, Bool, Bool, ULong) DEF0(track_copy_mem_remap, Addr, Addr, SizeT) DEF0(track_change_mem_mprotect, Addr, SizeT, Bool, Bool, Bool) Modified: branches/PTRCHECK/coregrind/m_wordfm.c =================================================================== --- branches/PTRCHECK/coregrind/m_wordfm.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/m_wordfm.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -415,6 +415,39 @@ } } +static +Bool 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, and we + cannot give any meaningful values for the bounds. (Well, + maybe we could, but we're not gonna. Ner!) */ + return False; + } + *kMinP = lowerBound; + *kMaxP = upperBound; + return True; +} + // Clear the iterator stack. static void stackClear(WordFM* fm) { @@ -568,7 +601,7 @@ } /* Add (k,v) to fm. */ -void VG_(addToFM) ( WordFM* fm, UWord k, UWord v ) +Bool VG_(addToFM) ( WordFM* fm, UWord k, UWord v ) { MaybeWord oldV; AvlNode* node; @@ -582,6 +615,7 @@ // fm->vFin( oldV.w ); if (oldV.b) fm->dealloc(node); + return oldV.b; } // Delete key from fm, returning associated key and val if found @@ -618,6 +652,15 @@ } } +// See comment in pub_tool_wordfm.h for explanation +Bool VG_(findBoundsFM)( WordFM* fm, + /*OUT*/UWord* kMinP, /*OUT*/UWord* kMaxP, + UWord minKey, UWord maxKey, UWord key ) +{ + return 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/PTRCHECK/coregrind/pub_core_debuginfo.h =================================================================== --- branches/PTRCHECK/coregrind/pub_core_debuginfo.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/pub_core_debuginfo.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -45,9 +45,16 @@ allow_SkFileV is True, it will try load debug info if the mapping at 'a' belongs to Valgrind; whereas normally (False) it will not do that. This allows us to carefully control when the thing will read - symbols from the Valgrind executable itself. */ + symbols from the Valgrind executable itself. + + If a call to VG_(di_notify_mmap) causes debug info to be read, then + the returned ULong is an abstract handle which can later be used to + refer to the debuginfo read as a result of this specific mapping, + in later queries to m_debuginfo. In this case the handle value + will be one or above. If the returned value is zero, no debug info + was read. */ #if defined(VGO_linux) -extern void VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ); +extern ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV ); extern void VG_(di_notify_munmap)( Addr a, SizeT len ); @@ -59,17 +66,20 @@ parameters describe a code segment and its associated data segment, that have recently been mapped in -- so we need to read debug info for it -- or conversely, have recently been dumped, in which case - the relevant debug info has to be unloaded. */ -extern void VG_(di_aix5_notify_segchange)( - Addr code_start, - Word code_len, - Addr data_start, - Word data_len, - UChar* file_name, - UChar* mem_name, - Bool is_mainexe, - Bool acquire - ); + the relevant debug info has to be unloaded. + + The returned ULong has the same meaning as documented for + VG_(di_notify_mmap) just above. */ +extern ULong VG_(di_aix5_notify_segchange)( + Addr code_start, + Word code_len, + Addr data_start, + Word data_len, + UChar* file_name, + UChar* mem_name, + Bool is_mainexe, + Bool acquire + ); #endif extern Bool VG_(get_fnname_nodemangle)( Addr a, Modified: branches/PTRCHECK/coregrind/pub_core_tooliface.h =================================================================== --- branches/PTRCHECK/coregrind/pub_core_tooliface.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/coregrind/pub_core_tooliface.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -161,10 +161,10 @@ IRSB* (*tool_final_IR_tidy_pass) (IRSB*); // -- Event tracking functions ------------------------------------ - void (*track_new_mem_startup) (Addr, SizeT, Bool, Bool, Bool); + void (*track_new_mem_startup) (Addr, SizeT, Bool, Bool, Bool, ULong); void (*track_new_mem_stack_signal)(Addr, SizeT, ThreadId); void (*track_new_mem_brk) (Addr, SizeT, ThreadId); - void (*track_new_mem_mmap) (Addr, SizeT, Bool, Bool, Bool); + void (*track_new_mem_mmap) (Addr, SizeT, Bool, Bool, Bool, ULong); void (*track_copy_mem_remap) (Addr src, Addr dst, SizeT); void (*track_change_mem_mprotect) (Addr, SizeT, Bool, Bool, Bool); Modified: branches/PTRCHECK/drd/drd_main.c =================================================================== --- branches/PTRCHECK/drd/drd_main.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/drd/drd_main.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -548,7 +548,8 @@ static void drd_start_using_mem_w_perms(const Addr a, const SizeT len, - const Bool rr, const Bool ww, const Bool xx) + const Bool rr, const Bool ww, const Bool xx, + ULong di_handle) { thread_set_vg_running_tid(VG_(get_running_tid)()); Modified: branches/PTRCHECK/helgrind/hg_main.c =================================================================== --- branches/PTRCHECK/helgrind/hg_main.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/helgrind/hg_main.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -5435,7 +5435,7 @@ static void evh__new_mem_w_perms ( Addr a, SizeT len, - Bool rr, Bool ww, Bool xx ) { + Bool rr, Bool ww, Bool xx, ULong di_handle ) { if (SHOW_EVENTS >= 1) VG_(printf)("evh__new_mem_w_perms(%p, %lu, %d,%d,%d)\n", (void*)a, len, (Int)rr, (Int)ww, (Int)xx ); Modified: branches/PTRCHECK/include/pub_tool_debuginfo.h =================================================================== --- branches/PTRCHECK/include/pub_tool_debuginfo.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/include/pub_tool_debuginfo.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -105,6 +105,48 @@ */ extern Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf); + +/* Get an XArray of StackBlock which describe the stack (auto) blocks + for this ip. The caller is expected to free the XArray at some + point. If 'arrays_only' is True, only array-typed blocks are + returned; otherwise blocks of all types are returned. */ + +typedef + struct { + OffT base; /* offset from sp or fp */ + SizeT szB; /* size in bytes */ + Bool spRel; /* True => sp-rel, False => fp-rel */ + Bool isVec; /* does block have an array type, or not? */ + HChar name[16]; /* first 15 chars of name (asciiz) */ + } + StackBlock; + +extern void* /* really, XArray* of StackBlock */ + VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only ); + + +/* Get an array of GlobalBlock which describe the global blocks owned + by the shared object characterised by the given di_handle. Asserts + if the handle is invalid. The caller is responsible for freeing + the array at some point. If 'arrays_only' is True, only + array-typed blocks are returned; otherwise blocks of all types are + returned. */ + +typedef + struct { + Addr addr; + SizeT szB; + Bool isVec; /* does block have an array type, or not? */ + HChar name[16]; /* first 15 chars of name (asciiz) */ + HChar soname[16]; /* first 15 chars of name (asciiz) */ + } + GlobalBlock; + +extern void* /* really, XArray* of GlobalBlock */ +VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle, + Bool arrays_only ); + + /*====================================================================*/ /*=== Obtaining segment information ===*/ /*====================================================================*/ Modified: branches/PTRCHECK/include/pub_tool_tooliface.h =================================================================== --- branches/PTRCHECK/include/pub_tool_tooliface.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/include/pub_tool_tooliface.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -471,15 +471,24 @@ These ones occur at startup, upon some signals, and upon some syscalls. - For the new_mem_brk and new_mem_stack_signal, the supplied ThreadId + For new_mem_brk and new_mem_stack_signal, the supplied ThreadId indicates the thread for whom the new memory is being allocated. + + For new_mem_startup and new_mem_mmap, the di_handle argument is a + handle which can be used to retrieve debug info associated with the + mapping or allocation (because it is of a file that Valgrind has + decided to read debug info from). If the value is zero, there is + no associated debug info. If the value exceeds zero, it can be + supplied as an argument to selected queries in m_debuginfo. */ void VG_(track_new_mem_startup) (void(*f)(Addr a, SizeT len, - Bool rr, Bool ww, Bool xx)); + Bool rr, Bool ww, Bool xx, + ULong di_handle)); void VG_(track_new_mem_stack_signal)(void(*f)(Addr a, SizeT len, ThreadId tid)); void VG_(track_new_mem_brk) (void(*f)(Addr a, SizeT len, ThreadId tid)); void VG_(track_new_mem_mmap) (void(*f)(Addr a, SizeT len, - Bool rr, Bool ww, Bool xx)); + Bool rr, Bool ww, Bool xx, + ULong di_handle)); void VG_(track_copy_mem_remap) (void(*f)(Addr from, Addr to, SizeT len)); void VG_(track_change_mem_mprotect) (void(*f)(Addr a, SizeT len, Modified: branches/PTRCHECK/include/pub_tool_wordfm.h =================================================================== --- branches/PTRCHECK/include/pub_tool_wordfm.h 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/include/pub_tool_wordfm.h 2008-09-09 08:49:35 UTC (rev 8591) @@ -86,8 +86,9 @@ /* Add (k,v) to fm. If a binding for k already exists, it is updated to map to this new v. In that case we should really return the - previous v so that caller can finalise it. Oh well. */ -void VG_(addToFM) ( WordFM* fm, UWord k, UWord v ); + previous v so that caller can finalise it. Oh well. Returns + True if a binding for k already exists. */ +Bool VG_(addToFM) ( WordFM* fm, UWord k, UWord v ); // Delete key from fm, returning associated key and val if found Bool VG_(delFromFM) ( WordFM* fm, @@ -97,6 +98,19 @@ 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. 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. +// +// If the operation was successful (that is, the given key is not +// present), True is returned. If the given key is in fact present, +// False is returned, and *kMinP and *kMaxP are undefined. +Bool 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 ); Modified: branches/PTRCHECK/memcheck/mc_main.c =================================================================== --- branches/PTRCHECK/memcheck/mc_main.c 2008-09-09 08:42:32 UTC (rev 8590) +++ branches/PTRCHECK/memcheck/mc_main.c 2008-09-09 08:49:35 UTC (rev 8591) @@ -3654,7 +3654,8 @@ } static -void mc_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx ) +void mc_new_mem_startup( Addr a, SizeT len, + Bool rr, Bool ww, Bool xx, ULong di_handle ) { /* Ignore the permissions, just make it defined. Seems to work... */ // Because code is defined, initialised variables get put in the data @@ -3673,7 +3674,8 @@ } static -void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx ) +void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx, + ULong di_handle ) { MC_(make_mem_defined)(a, len); } |
|
From: <sv...@va...> - 2008-09-09 08:42:23
|
Author: sewardj Date: 2008-09-09 09:42:32 +0100 (Tue, 09 Sep 2008) New Revision: 8590 Log: Pass --warn-common to the linker; I think this causes it to warn about certain kinds of linkage duplication/anomalies. Modified: branches/PTRCHECK/Makefile.tool.am Modified: branches/PTRCHECK/Makefile.tool.am =================================================================== --- branches/PTRCHECK/Makefile.tool.am 2008-09-09 08:35:09 UTC (rev 8589) +++ branches/PTRCHECK/Makefile.tool.am 2008-09-09 08:42:32 UTC (rev 8590) @@ -92,7 +92,8 @@ TOOL_LDADD_COMMON = -lgcc TOOL_LDFLAGS_COMMON_LINUX = -static \ -Wl,-defsym,valt_load_address=@VALT_LOAD_ADDRESS@ \ - -nodefaultlibs -nostartfiles -u _start + -nodefaultlibs -nostartfiles -u _start \ + -Wl,--warn-common TOOL_LDFLAGS_COMMON_AIX5 = -static -Wl,-e_start_valgrind |
|
From: <sv...@va...> - 2008-09-09 08:35:07
|
Author: sewardj
Date: 2008-09-09 09:35:09 +0100 (Tue, 09 Sep 2008)
New Revision: 8589
Log:
Fix up enough plumbing so this at least compiles.
Added:
branches/PTRCHECK/exp-ptrcheck/h_main.h
branches/PTRCHECK/exp-ptrcheck/pc_common.c
branches/PTRCHECK/exp-ptrcheck/pc_common.h
branches/PTRCHECK/exp-ptrcheck/pc_main.c
branches/PTRCHECK/exp-ptrcheck/sg_main.h
Modified:
branches/PTRCHECK/exp-ptrcheck/Makefile.am
branches/PTRCHECK/exp-ptrcheck/h_list.c
branches/PTRCHECK/exp-ptrcheck/h_main.c
branches/PTRCHECK/exp-ptrcheck/sg_main.c
Modified: branches/PTRCHECK/exp-ptrcheck/Makefile.am
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/Makefile.am 2008-09-08 18:43:53 UTC (rev 8588)
+++ branches/PTRCHECK/exp-ptrcheck/Makefile.am 2008-09-09 08:35:09 UTC (rev 8589)
@@ -21,7 +21,7 @@
endif
-VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON = pc_intercepts.c
+VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON = h_intercepts.c
vgpreload_exp_ptrcheck_x86_linux_so_SOURCES = $(VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON)
vgpreload_exp_ptrcheck_x86_linux_so_CPPFLAGS = $(AM_CPPFLAGS_X86_LINUX)
@@ -79,7 +79,8 @@
-EXP_PTRCHECK_SOURCES_COMMON = pc_list.c pc_main.c
+EXP_PTRCHECK_SOURCES_COMMON = \
+ pc_common.c h_list.c h_main.c sg_main.c pc_main.c
exp_ptrcheck_x86_linux_SOURCES = $(EXP_PTRCHECK_SOURCES_COMMON)
exp_ptrcheck_x86_linux_CPPFLAGS = $(AM_CPPFLAGS_X86_LINUX)
@@ -123,5 +124,5 @@
exp_ptrcheck_ppc64_aix5_LDADD = $(TOOL_LDADD_PPC64_AIX5)
exp_ptrcheck_ppc64_aix5_LDFLAGS = $(TOOL_LDFLAGS_PPC64_AIX5)
-noinst_HEADERS = pc_list.h
+noinst_HEADERS = h_list.h h_main.h sg_main.h pc_common.h
Modified: branches/PTRCHECK/exp-ptrcheck/h_list.c
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/h_list.c 2008-09-08 18:43:53 UTC (rev 8588)
+++ branches/PTRCHECK/exp-ptrcheck/h_list.c 2008-09-09 08:35:09 UTC (rev 8589)
@@ -46,7 +46,7 @@
#include "pub_tool_execontext.h"
#include "pub_tool_hashtable.h"
-#include "pc_list.h"
+#include "h_list.h"
#ifdef OUTSIDE_PTRCHECK
#include <assert.h>
Modified: branches/PTRCHECK/exp-ptrcheck/h_main.c
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/h_main.c 2008-09-08 18:43:53 UTC (rev 8588)
+++ branches/PTRCHECK/exp-ptrcheck/h_main.c 2008-09-09 08:35:09 UTC (rev 8589)
@@ -9,8 +9,13 @@
This file is part of Ptrcheck, a Valgrind tool for checking pointer
use in programs.
+ Initial version (Annelid):
+
Copyright (C) 2003-2008 Nicholas Nethercote
nj...@va...
+
+ Valgrind-3.X port:
+
Copyright (C) 2008-2008 OpenWorks Ltd
in...@op...
@@ -224,10 +229,14 @@
#include "pub_tool_threadstate.h" // VG_(get_running_tid)
#include "pub_tool_oset.h"
#include "pub_tool_vkiscnums.h"
+#include "pub_tool_machine.h"
-#include "pc_list.h"
+#include "h_list.h"
+#include "h_main.h"
+#include "pc_common.h"
+
/*------------------------------------------------------------*/
/*--- Debug/trace options ---*/
/*------------------------------------------------------------*/
@@ -239,47 +248,11 @@
/*------------------------------------------------------------*/
-/*--- Command line options ---*/
-/*------------------------------------------------------------*/
-
-static Bool clo_partial_loads_ok = True; /* user visible */
-static Bool clo_lossage_check = False; /* dev flag only */
-
-static Bool pc_process_cmd_line_options(Char* arg)
-{
- VG_BOOL_CLO(arg, "--partial-loads-ok", clo_partial_loads_ok)
- else VG_BOOL_CLO(arg, "--lossage-check", clo_lossage_check)
- else
- return VG_(replacement_malloc_process_cmd_line_option)(arg);
-
- return True;
-}
-
-static void pc_print_usage(void)
-{
- VG_(printf)(
- " --partial-loads-ok=no|yes same as for Memcheck [yes]\n"
- );
- VG_(replacement_malloc_print_usage)();
-}
-
-static void pc_print_debug_usage(void)
-{
- VG_(printf)(
- " --lossage-check=no|yes gather stats for quality control [no]\n"
- );
- VG_(replacement_malloc_print_debug_usage)();
-}
-
-
-/*------------------------------------------------------------*/
/*--- Segments ---*/
/*------------------------------------------------------------*/
-// Choose values that couldn't possibly be pointers
-#define NONPTR ((Seg)0xA1)
-#define UNKNOWN ((Seg)0xB2)
-#define BOTTOM ((Seg)0xC3)
+// NONPTR, UNKNOWN, BOTTOM defined in h_main.h since
+// pc_common.c needs to see them, for error processing
static ISList* seglist = NULL;
@@ -635,420 +608,41 @@
}
-/*--------------------------------------------------------------------*/
-/*--- Error handling ---*/
-/*--------------------------------------------------------------------*/
-
-typedef
- enum {
- /* Possible data race */
- LoadStoreSupp,
- ArithSupp,
- SysParamSupp,
- }
- PtrcheckSuppKind;
-
-/* What kind of error it is. */
-typedef
- enum {
- LoadStoreErr, // mismatched ptr/addr segments on load/store
- ArithErr, // bad arithmetic between two segment pointers
- SysParamErr, // block straddling >1 segment passed to syscall
- }
- PtrcheckErrorKind;
-
-
-// These ones called from generated code.
-
-typedef
- struct {
- Addr a;
- UInt size;
- Seg vseg;
- Bool is_write;
- Char descr1[96];
- Char descr2[96];
- Char datasym[96];
- OffT datasymoff;
- }
- LoadStoreExtra;
-
-typedef
- struct {
- Seg seg1;
- Seg seg2;
- const HChar* opname; // user-understandable text name
- }
- ArithExtra;
-
-typedef
- struct {
- CorePart part;
- Addr lo;
- Addr hi;
- Seg seglo;
- Seg seghi;
- }
- SysParamExtra;
-
-
-static
-void record_loadstore_error( Addr a, UInt size, Seg vseg, Bool is_write )
-{
- LoadStoreExtra extra = {
- .a = a, .size = size, .vseg = vseg, .is_write = is_write
- };
- extra.descr1[0] = extra.descr2[0] = extra.datasym[0] = 0;
- extra.datasymoff = 0;
- VG_(maybe_record_error)( VG_(get_running_tid)(), LoadStoreErr,
- /*a*/0, /*str*/NULL, /*extra*/(void*)&extra);
-}
-
-static void
-record_arith_error( Seg seg1, Seg seg2, HChar* opname )
-{
- ArithExtra extra = {
- .seg1 = seg1, .seg2 = seg2, .opname = opname
- };
- VG_(maybe_record_error)( VG_(get_running_tid)(), ArithErr,
- /*a*/0, /*str*/NULL, /*extra*/(void*)&extra);
-}
-
-static void record_sysparam_error( ThreadId tid, CorePart part, Char* s,
- Addr lo, Addr hi, Seg seglo, Seg seghi )
-{
- SysParamExtra extra = {
- .part = part, .lo = lo, .hi = hi, .seglo = seglo, .seghi = seghi
- };
- VG_(maybe_record_error)( tid, SysParamErr, /*a*/(Addr)0, /*str*/s,
- /*extra*/(void*)&extra);
-}
-
-static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
-{
- tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
-
- // Nb: ok to compare string pointers, rather than string contents,
- // because the same static strings are shared.
-
- switch (VG_(get_error_kind)(e1)) {
-
- case LoadStoreErr:
- tl_assert( VG_(get_error_string)(e1) == NULL );
- tl_assert( VG_(get_error_string)(e2) == NULL );
- return True;
-
- case SysParamErr:
- case ArithErr:
- return True;
-
- default:
- VG_(tool_panic)("eq_Error: unrecognised error kind");
- }
-}
-
-static Char* readwrite(Bool is_write)
-{
- return ( is_write ? "write" : "read" );
-}
-
-static inline
-Bool is_known_segment(Seg seg)
-{
- return (UNKNOWN != seg && BOTTOM != seg && NONPTR != seg);
-}
-
-static void pp_Error ( Error* err )
-{
- switch (VG_(get_error_kind)(err)) {
- //----------------------------------------------------------
- case LoadStoreErr: {
- LoadStoreExtra* extra = (LoadStoreExtra*)VG_(get_error_extra)(err);
- Char *place, *legit, *how_invalid;
- Addr a = extra->a;
- Seg vseg = extra->vseg;
-
- tl_assert(is_known_segment(vseg) || NONPTR == vseg);
-
- if (NONPTR == vseg) {
- // Access via a non-pointer
- VG_(message)(Vg_UserMsg, "Invalid %s of size %u",
- readwrite(extra->is_write), extra->size);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- VG_(message)(Vg_UserMsg,
- " Address %#lx is not derived from any known block", a);
-
- } else {
- // Access via a pointer, but outside its range.
- Int cmp;
- UWord miss_size;
- Seg__cmp(vseg, a, &cmp, &miss_size);
- if (cmp < 0) place = "before";
- else if (cmp == 0) place = "inside";
- else place = "after";
- how_invalid = ( ( Seg__is_freed(vseg) && 0 != cmp )
- ? "Doubly-invalid" : "Invalid" );
- legit = ( Seg__is_freed(vseg) ? "once-" : "" );
-
- VG_(message)(Vg_UserMsg, "%s %s of size %u", how_invalid,
- readwrite(extra->is_write), extra->size);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-
- VG_(message)(Vg_UserMsg,
- " Address %#lx is %lu bytes %s the accessing pointer's",
- a, miss_size, place);
- VG_(message)(Vg_UserMsg,
- " %slegitimate range, a block of size %lu %s",
- legit, Seg__size(vseg), Seg__status_str(vseg) );
- VG_(pp_ExeContext)(Seg__where(vseg));
- }
- if (extra->descr1[0] != 0)
- VG_(message)(Vg_UserMsg, " %s", extra->descr1);
- if (extra->descr2[0] != 0)
- VG_(message)(Vg_UserMsg, " %s", extra->descr2);
- if (extra->datasym[0] != 0)
- VG_(message)(Vg_UserMsg, " Address 0x%llx is %llu bytes "
- "inside data symbol \"%s\"",
- (ULong)extra->a, (ULong)extra->datasymoff,
- extra->datasym);
- break;
- }
-
- //----------------------------------------------------------
- case ArithErr: {
- ArithExtra* extra = VG_(get_error_extra)(err);
- Seg seg1 = extra->seg1;
- Seg seg2 = extra->seg2;
- Char* which;
-
- tl_assert(BOTTOM != seg1);
- tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
-
- VG_(message)(Vg_UserMsg, "Invalid arguments to %s", extra->opname);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-
- if (seg1 != seg2) {
- if (NONPTR == seg1) {
- VG_(message)(Vg_UserMsg, " First arg not a pointer");
- } else if (UNKNOWN == seg1) {
- VG_(message)(Vg_UserMsg, " First arg may be a pointer");
- } else {
- VG_(message)(Vg_UserMsg, " First arg derived from address %#lx of "
- "%lu-byte block %s",
- Seg__a(seg1), Seg__size(seg1),
- Seg__status_str(seg1) );
- VG_(pp_ExeContext)(Seg__where(seg1));
- }
- which = "Second arg";
- } else {
- which = "Both args";
- }
- if (NONPTR == seg2) {
- VG_(message)(Vg_UserMsg, " %s not a pointer", which);
- } else {
- VG_(message)(Vg_UserMsg, " %s derived from address %#lx of "
- "%lu-byte block %s",
- which, Seg__a(seg2), Seg__size(seg2),
- Seg__status_str(seg2));
- VG_(pp_ExeContext)(Seg__where(seg2));
- }
- break;
- }
-
- //----------------------------------------------------------
- case SysParamErr: {
- SysParamExtra* extra = (SysParamExtra*)VG_(get_error_extra)(err);
- Addr lo = extra->lo;
- Addr hi = extra->hi;
- Seg seglo = extra->seglo;
- Seg seghi = extra->seghi;
- Char* s = VG_(get_error_string) (err);
- Char* what;
-
- tl_assert(BOTTOM != seglo && BOTTOM != seghi);
-
- if (Vg_CoreSysCall == extra->part) what = "Syscall param ";
- else VG_(tool_panic)("bad CorePart");
-
- if (seglo == seghi) {
- // freed block
- tl_assert(is_known_segment(seglo));
- tl_assert(Seg__is_freed(seglo));
- VG_(message)(Vg_UserMsg, "%s%s contains unaddressable byte(s)",
- what, s);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-
- VG_(message)(Vg_UserMsg, " Address %#lx is %ld bytes inside a "
- "%ld-byte block %s",
- lo, lo-Seg__a(seglo), Seg__size(seglo),
- Seg__status_str(seglo) );
- VG_(pp_ExeContext)(Seg__where(seglo));
-
- } else {
- // mismatch
- VG_(message)(Vg_UserMsg, "%s%s is non-contiguous", what, s);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-
- if (UNKNOWN == seglo) {
- VG_(message)(Vg_UserMsg, " First byte is not inside a known block");
- } else {
- VG_(message)(Vg_UserMsg, " First byte (%#lx) is %ld bytes inside a "
- "%ld-byte block %s",
- lo, lo-Seg__a(seglo), Seg__size(seglo),
- Seg__status_str(seglo) );
- VG_(pp_ExeContext)(Seg__where(seglo));
- }
-
- if (UNKNOWN == seghi) {
- VG_(message)(Vg_UserMsg, " Last byte is not inside a known block");
- } else {
- VG_(message)(Vg_UserMsg, " Last byte (%#lx) is %ld bytes inside a "
- "%ld-byte block %s",
- hi, hi-Seg__a(seghi), Seg__size(seghi),
- Seg__status_str(seghi));
- VG_(pp_ExeContext)(Seg__where(seghi));
- }
- }
- break;
- }
-
- default:
- VG_(tool_panic)("pp_Error: unrecognised error kind");
- }
-}
-
-static UInt update_Error_extra ( Error* err )
-{
- switch (VG_(get_error_kind)(err)) {
- case LoadStoreErr: {
- LoadStoreExtra* ex = (LoadStoreExtra*)VG_(get_error_extra)(err);
- tl_assert(ex);
- tl_assert(sizeof(ex->descr1) == sizeof(ex->descr2));
- tl_assert(sizeof(ex->descr1) > 0);
- tl_assert(sizeof(ex->datasym) > 0);
- VG_(memset)(&ex->descr1, 0, sizeof(ex->descr1));
- VG_(memset)(&ex->descr2, 0, sizeof(ex->descr2));
- VG_(memset)(&ex->datasym, 0, sizeof(ex->datasym));
- ex->datasymoff = 0;
- if (VG_(get_data_description)( &ex->descr1[0], &ex->descr2[0],
- sizeof(ex->descr1)-1, ex->a )) {
- tl_assert(ex->descr1[sizeof(ex->descr1)-1] == 0);
- tl_assert(ex->descr1[sizeof(ex->descr2)-1] == 0);
- }
- else
- if (VG_(get_datasym_and_offset)( ex->a, &ex->datasym[0],
- sizeof(ex->datasym)-1,
- &ex->datasymoff )) {
- tl_assert(ex->datasym[sizeof(ex->datasym)-1] == 0);
- }
- return sizeof(LoadStoreExtra);
- }
- case ArithErr:
- return sizeof(ArithExtra);
- case SysParamErr:
- return sizeof(SysParamExtra);
- default:
- VG_(tool_panic)("update_extra");
- }
-}
-
-static Bool is_recognised_suppression ( Char* name, Supp *su )
-{
- SuppKind skind;
-
- if (VG_STREQ(name, "LoadStore")) skind = LoadStoreSupp;
- else if (VG_STREQ(name, "Arith")) skind = ArithSupp;
- else if (VG_STREQ(name, "SysParam")) skind = SysParamSupp;
- else
- return False;
-
- VG_(set_supp_kind)(su, skind);
- return True;
-}
-
-static Bool read_extra_suppression_info ( Int fd, Char* buf,
- Int nBuf, Supp* su )
-{
- Bool eof;
-
- if (VG_(get_supp_kind)(su) == SysParamSupp) {
- eof = VG_(get_line) ( fd, buf, nBuf );
- if (eof) return False;
- VG_(set_supp_string)(su, VG_(strdup)(buf));
- }
- return True;
-}
-
-static Bool error_matches_suppression (Error* err, Supp* su)
-{
- ErrorKind ekind = VG_(get_error_kind )(err);
-
- switch (VG_(get_supp_kind)(su)) {
- case LoadStoreSupp: return (ekind == LoadStoreErr);
- case ArithSupp: return (ekind == ArithErr);
- case SysParamSupp: return (ekind == SysParamErr);
- default:
- VG_(printf)("Error:\n"
- " unknown suppression type %d\n",
- VG_(get_supp_kind)(su));
- VG_(tool_panic)("unknown suppression type in "
- "SK_(error_matches_suppression)");
- }
-}
-
-static Char* get_error_name ( Error* err )
-{
- switch (VG_(get_error_kind)(err)) {
- case LoadStoreErr: return "LoadStore";
- case ArithErr: return "Arith";
- case SysParamErr: return "SysParam";
- default: VG_(tool_panic)("get_error_name: unexpected type");
- }
-}
-
-static void print_extra_suppression_info ( Error* err )
-{
- if (SysParamErr == VG_(get_error_kind)(err)) {
- VG_(printf)(" %s\n", VG_(get_error_string)(err));
- }
-}
-
-
/*------------------------------------------------------------*/
/*--- malloc() et al replacements ---*/
/*------------------------------------------------------------*/
-static void* pc_replace_malloc ( ThreadId tid, SizeT n )
+void* h_replace_malloc ( ThreadId tid, SizeT n )
{
return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
/*is_zeroed*/False );
}
-static void* pc_replace___builtin_new ( ThreadId tid, SizeT n )
+void* h_replace___builtin_new ( ThreadId tid, SizeT n )
{
return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
/*is_zeroed*/False );
}
-static void* pc_replace___builtin_vec_new ( ThreadId tid, SizeT n )
+void* h_replace___builtin_vec_new ( ThreadId tid, SizeT n )
{
return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment),
/*is_zeroed*/False );
}
-static void* pc_replace_memalign ( ThreadId tid, SizeT align, SizeT n )
+void* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n )
{
return alloc_and_new_mem_heap ( tid, n, align,
/*is_zeroed*/False );
}
-static void* pc_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 )
+void* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 )
{
return alloc_and_new_mem_heap ( tid, nmemb*size1, VG_(clo_alignment),
/*is_zeroed*/True );
}
-static void pc_replace_free ( ThreadId tid, void* p )
+void h_replace_free ( ThreadId tid, void* p )
{
// Should arguably check here if p.vseg matches the segID of the
// pointed-to block... unfortunately, by this stage, we don't know what
@@ -1066,17 +660,17 @@
handle_free_heap(tid, p);
}
-static void pc_replace___builtin_delete ( ThreadId tid, void* p )
+void h_replace___builtin_delete ( ThreadId tid, void* p )
{
handle_free_heap(tid, p);
}
-static void pc_replace___builtin_vec_delete ( ThreadId tid, void* p )
+void h_replace___builtin_vec_delete ( ThreadId tid, void* p )
{
handle_free_heap(tid, p);
}
-static void* pc_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size )
+void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size )
{
Seg seg;
@@ -1157,7 +751,8 @@
//zz set_mem( a, len, NONPTR );
//zz }
-static void new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
+void h_new_mem_startup( Addr a, SizeT len,
+ Bool rr, Bool ww, Bool xx, ULong di_handle )
{
if (0) VG_(printf)("new_mem_startup(%#lx,%lu)\n", a, len);
set_mem_unknown( a, len );
@@ -1188,7 +783,8 @@
// Not quite right: if you mmap a segment into a specified place, it could
// be legitimate to do certain arithmetic with the pointer that it wouldn't
// otherwise. Hopefully this is rare, though.
-static void new_mem_mmap( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
+void h_new_mem_mmap( Addr a, SizeT len,
+ Bool rr, Bool ww, Bool xx, ULong di_handle )
{
if (0) VG_(printf)("new_mem_mmap(%#lx,%lu)\n", a, len);
//zz #if 0
@@ -1263,7 +859,7 @@
//zz // VG_(skin_panic)("can't handle die_mem_brk()");
//zz }
-static void die_mem_munmap( Addr a, SizeT len )
+void h_die_mem_munmap( Addr a, SizeT len )
{
// handle_free_munmap( (void*)a, len );
}
@@ -1315,29 +911,29 @@
/* First identify the case where start and end are in different
segments but s and e don't both fall in either. */
if ( ! ((s_in_seglo && e_in_seglo) || (s_in_seghi && e_in_seghi)) ) {
- record_sysparam_error(tid, part, str, s, e, seglo, seghi);
+ h_record_sysparam_error(tid, part, str, s, e, seglo, seghi);
}
/* Now we know that s and e are both in the same known segment.
Identify the case where that segment is freed. */
else if (s_in_seglo && Seg__is_freed(seglo)) {
tl_assert(e_in_seglo);
- record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN);
+ h_record_sysparam_error(tid, part, str, s, e, seglo, UNKNOWN);
}
else if (s_in_seghi && Seg__is_freed(seghi)) {
tl_assert(e_in_seghi);
- record_sysparam_error(tid, part, str, s, e, seghi, UNKNOWN);
+ h_record_sysparam_error(tid, part, str, s, e, seghi, UNKNOWN);
}
}
}
-static void pre_mem_access ( CorePart part, ThreadId tid, Char* s,
- Addr base, SizeT size )
+void h_pre_mem_access ( CorePart part, ThreadId tid, Char* s,
+ Addr base, SizeT size )
{
pre_mem_access2( part, tid, s, base, base + size - 1 );
}
-static
-void pre_mem_read_asciiz ( CorePart part, ThreadId tid, Char* s, Addr lo )
+void h_pre_mem_read_asciiz ( CorePart part, ThreadId tid,
+ Char* s, Addr lo )
{
Addr hi = lo;
@@ -2101,9 +1697,8 @@
}
}
-static
-void post_reg_write_demux ( CorePart part, ThreadId tid,
- OffT guest_state_offset, SizeT size)
+void h_post_reg_write_demux ( CorePart part, ThreadId tid,
+ OffT guest_state_offset, SizeT size)
{
if (0)
VG_(printf)("post_reg_write_demux: tid %d part %d off %ld size %ld\n",
@@ -2133,19 +1728,18 @@
}
}
-static
-void post_reg_write_clientcall(ThreadId tid, OffT guest_state_offset,
- SizeT size, Addr f )
+void h_post_reg_write_clientcall(ThreadId tid, OffT guest_state_offset,
+ SizeT size, Addr f )
{
UWord p;
// Having to do this is a bit nasty...
- if (f == (Addr)pc_replace_malloc
- || f == (Addr)pc_replace___builtin_new
- || f == (Addr)pc_replace___builtin_vec_new
- || f == (Addr)pc_replace_calloc
- || f == (Addr)pc_replace_memalign
- || f == (Addr)pc_replace_realloc)
+ if (f == (Addr)h_replace_malloc
+ || f == (Addr)h_replace___builtin_new
+ || f == (Addr)h_replace___builtin_vec_new
+ || f == (Addr)h_replace_calloc
+ || f == (Addr)h_replace_memalign
+ || f == (Addr)h_replace_realloc)
{
// We remembered the last added segment; make sure it's the right one.
/* What's going on: at this point, the scheduler has just called
@@ -2174,9 +1768,9 @@
guest_state_offset, size, (UWord)last_seg_added );
}
}
- else if (f == (Addr)pc_replace_free
- || f == (Addr)pc_replace___builtin_delete
- || f == (Addr)pc_replace___builtin_vec_delete
+ else if (f == (Addr)h_replace_free
+ || f == (Addr)h_replace___builtin_delete
+ || f == (Addr)h_replace___builtin_vec_delete
// || f == (Addr)VG_(cli_block_size)
|| f == (Addr)VG_(message))
{
@@ -2237,7 +1831,7 @@
/*--- System calls ---*/
/*--------------------------------------------------------------------*/
-static void pre_syscall ( ThreadId tid, UInt syscallno )
+void h_pre_syscall ( ThreadId tid, UInt syscallno )
{
//zz #if 0
//zz UInt mmap_flags;
@@ -2265,7 +1859,7 @@
//zz return NULL;
}
-static void post_syscall ( ThreadId tid, UInt syscallno, SysRes res )
+void h_post_syscall ( ThreadId tid, UInt syscallno, SysRes res )
{
switch (syscallno) {
@@ -2621,7 +2215,7 @@
static __inline__
void check_load_or_store(Bool is_write, Addr m, UInt sz, Seg mptr_vseg)
{
- if (clo_lossage_check) {
+ if (h_clo_lossage_check) {
Seg seg;
stats__tot_mem_refs++;
if (ISList__findI0( seglist, (Addr)m, &seg )) {
@@ -2637,7 +2231,7 @@
if (UNKNOWN == mptr_vseg
|| BOTTOM == mptr_vseg || NONPTR == mptr_vseg) {
ExeContext* ec;
- Char buf[100];
+ Char buf[100];
static UWord xx = 0;
stats__refs_lost_seg++;
ec = VG_(record_ExeContext)( VG_(get_running_tid)(), 0 );
@@ -2672,7 +2266,7 @@
// do nothing
} else if (NONPTR == mptr_vseg) {
- record_loadstore_error( m, sz, mptr_vseg, is_write );
+ h_record_heap_error( m, sz, mptr_vseg, is_write );
} else {
// check all segment ranges in the circle
@@ -2687,7 +2281,7 @@
// gcc's/glibc's habits of doing word-sized accesses that read past
// the ends of arrays/strings.
if (!is_write && sz == sizeof(UWord)
- && clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) {
+ && h_clo_partial_loads_ok && SHMEM_IS_WORD_ALIGNED(m)) {
mhi = m;
} else {
mhi = m+sz-1;
@@ -2711,7 +2305,7 @@
// warnings, since the first one mentions that the block has been
// freed.
if ( ! is_ok || Seg__is_freed(curr) )
- record_loadstore_error( m, sz, mptr_vseg, is_write );
+ h_record_heap_error( m, sz, mptr_vseg, is_write );
}
}
@@ -3056,7 +2650,7 @@
}
#define BINERROR(opname) \
- record_arith_error(seg1, seg2, opname); \
+ h_record_arith_error(seg1, seg2, opname); \
out = NONPTR
@@ -3218,7 +2812,7 @@
checkSeg(seg2);
# endif
if (is_known_segment(seg1) && is_known_segment(seg2))
- record_arith_error(seg1, seg2, "Mul32/Mul64");
+ h_record_arith_error(seg1, seg2, "Mul32/Mul64");
return NONPTR;
}
@@ -4547,11 +4141,11 @@
static
-IRSB* pc_instrument ( VgCallbackClosure* closure,
- IRSB* sbIn,
- VexGuestLayout* layout,
- VexGuestExtents* vge,
- IRType gWordTy, IRType hWordTy )
+IRSB* h_instrument ( VgCallbackClosure* closure,
+ IRSB* sbIn,
+ VexGuestLayout* layout,
+ VexGuestExtents* vge,
+ IRType gWordTy, IRType hWordTy )
{
Bool verboze = 0||False;
Int i /*, j*/;
@@ -4663,88 +4257,8 @@
/*--- Initialisation ---*/
/*--------------------------------------------------------------------*/
-static void pc_post_clo_init ( void ); /* just below */
-static void pc_fini ( Int exitcode ); /* just below */
-
-static void pc_pre_clo_init ( void )
+void h_pre_clo_init ( void )
{
- VG_(details_name) ("exp-ptrcheck");
- VG_(details_version) (NULL);
- VG_(details_description) ("a pointer-use checker");
- VG_(details_copyright_author)(
- "Copyright (C) 2003-2008, and GNU GPL'd, by Nicholas Nethercote.");
- VG_(details_bug_reports_to) ("nj...@va...");
-
- VG_(basic_tool_funcs)( pc_post_clo_init,
- pc_instrument,
- pc_fini );
-
- VG_(needs_malloc_replacement)( pc_replace_malloc,
- pc_replace___builtin_new,
- pc_replace___builtin_vec_new,
- pc_replace_memalign,
- pc_replace_calloc,
- pc_replace_free,
- pc_replace___builtin_delete,
- pc_replace___builtin_vec_delete,
- pc_replace_realloc,
- 0 /* no need for client heap redzones */ );
-
- VG_(needs_core_errors) ();
- VG_(needs_tool_errors) (eq_Error,
- pp_Error,
- True,/*show TIDs for errors*/
- update_Error_extra,
- is_recognised_suppression,
- read_extra_suppression_info,
- error_matches_suppression,
- get_error_name,
- print_extra_suppression_info);
-
- VG_(needs_syscall_wrapper)( pre_syscall,
- post_syscall );
-
- VG_(needs_command_line_options)(pc_process_cmd_line_options,
- pc_print_usage,
- pc_print_debug_usage);
-
- VG_(needs_var_info)();
-
-//zz // No needs
-//zz VG_(needs_core_errors) ();
-//zz VG_(needs_skin_errors) ();
-//zz VG_(needs_shadow_regs) ();
-//zz VG_(needs_command_line_options)();
-//zz VG_(needs_syscall_wrapper) ();
-//zz VG_(needs_sanity_checks) ();
-//zz
-//zz // Memory events to track
- VG_(track_new_mem_startup) ( new_mem_startup );
-//zz VG_(track_new_mem_stack_signal) ( NULL );
-//zz VG_(track_new_mem_brk) ( new_mem_brk );
- VG_(track_new_mem_mmap) ( new_mem_mmap );
-//zz
-//zz VG_(track_copy_mem_remap) ( copy_mem_remap );
-//zz VG_(track_change_mem_mprotect) ( NULL );
-//zz
-//zz VG_(track_die_mem_stack_signal) ( NULL );
-//zz VG_(track_die_mem_brk) ( die_mem_brk );
- VG_(track_die_mem_munmap) ( die_mem_munmap );
-
- VG_(track_pre_mem_read) ( pre_mem_access );
- VG_(track_pre_mem_read_asciiz) ( pre_mem_read_asciiz );
- VG_(track_pre_mem_write) ( pre_mem_access );
-//zz VG_(track_post_mem_write) ( post_mem_write );
-
- // Register events to track
-//zz VG_(track_post_regs_write_init) ( post_regs_write_init );
-//zz VG_(track_post_reg_write_syscall_return) ( post_reg_write_nonptr );
-//zz VG_(track_post_reg_write_deliver_signal) ( post_reg_write_nonptr_or_unknown );
-//zz VG_(track_post_reg_write_pthread_return) ( post_reg_write_nonptr_or_unknown );
-//zz VG_(track_post_reg_write_clientreq_return) ( post_reg_write_nonptr );
- VG_(track_post_reg_write_clientcall_return) ( post_reg_write_clientcall );
- VG_(track_post_reg_write)( post_reg_write_demux );
-
// Other initialisation
init_shadow_memory();
seglist = ISList__construct();
@@ -4758,7 +4272,7 @@
// above.
}
-static void pc_post_clo_init ( void )
+void h_post_clo_init ( void )
{
}
@@ -4766,9 +4280,9 @@
/*--- Finalisation ---*/
/*--------------------------------------------------------------------*/
-static void pc_fini ( Int exitcode )
+void h_fini ( Int exitcode )
{
- if (clo_lossage_check) {
+ if (h_clo_lossage_check) {
VG_(message)(Vg_UserMsg, "");
VG_(message)(Vg_UserMsg, "%12lld total memory references",
stats__tot_mem_refs);
@@ -4784,7 +4298,6 @@
}
}
-VG_DETERMINE_INTERFACE_VERSION(pc_pre_clo_init)
/*--------------------------------------------------------------------*/
/*--- end h_main.c ---*/
Added: branches/PTRCHECK/exp-ptrcheck/h_main.h
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/h_main.h (rev 0)
+++ branches/PTRCHECK/exp-ptrcheck/h_main.h 2008-09-09 08:35:09 UTC (rev 8589)
@@ -0,0 +1,84 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Ptrcheck: a pointer-use checker. ---*/
+/*--- Exports for heap access checking. ---*/
+/*--- h_main.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Ptrcheck, a Valgrind tool for checking pointer
+ use in programs.
+
+ Copyright (C) 2003-2008 Nicholas Nethercote
+ nj...@va...
+ Copyright (C) 2008-2008 OpenWorks Ltd
+ in...@op...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __H_MAIN_H
+
+#define __H_MAIN_H
+
+// Choose values that couldn't possibly be pointers
+#define NONPTR ((Seg)0xA1)
+#define UNKNOWN ((Seg)0xB2)
+#define BOTTOM ((Seg)0xC3)
+
+static inline Bool is_known_segment(Seg seg) {
+ return (UNKNOWN != seg && BOTTOM != seg && NONPTR != seg);
+}
+
+void h_pre_clo_init ( void );
+void h_post_clo_init ( void );
+void h_fini ( Int exitcode );
+
+void* h_replace_malloc ( ThreadId tid, SizeT n );
+void* h_replace___builtin_new ( ThreadId tid, SizeT n );
+void* h_replace___builtin_vec_new ( ThreadId tid, SizeT n );
+void* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n );
+void* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 );
+void h_replace_free ( ThreadId tid, void* p );
+void h_replace___builtin_delete ( ThreadId tid, void* p );
+void h_replace___builtin_vec_delete ( ThreadId tid, void* p );
+void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size );
+
+void h_new_mem_startup( Addr a, SizeT len,
+ Bool rr, Bool ww, Bool xx, ULong di_handle );
+void h_new_mem_mmap( Addr a, SizeT len,
+ Bool rr, Bool ww, Bool xx, ULong di_handle );
+void h_die_mem_munmap( Addr a, SizeT len );
+void h_pre_mem_access ( CorePart part, ThreadId tid, Char* s,
+ Addr base, SizeT size );
+void h_pre_mem_read_asciiz ( CorePart part, ThreadId tid,
+ Char* s, Addr lo );
+
+void h_post_reg_write_demux ( CorePart part, ThreadId tid,
+ OffT guest_state_offset, SizeT size);
+void h_post_reg_write_clientcall(ThreadId tid, OffT guest_state_offset,
+ SizeT size, Addr f );
+
+void h_pre_syscall ( ThreadId tid, UInt syscallno );
+void h_post_syscall ( ThreadId tid, UInt syscallno, SysRes res );
+
+#endif
+
+/*--------------------------------------------------------------------*/
+/*--- end h_main.h ---*/
+/*--------------------------------------------------------------------*/
Added: branches/PTRCHECK/exp-ptrcheck/pc_common.c
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/pc_common.c (rev 0)
+++ branches/PTRCHECK/exp-ptrcheck/pc_common.c 2008-09-09 08:35:09 UTC (rev 8589)
@@ -0,0 +1,544 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Ptrcheck: a pointer-use checker. ---*/
+/*--- Provides stuff shared between sg_ and h_ subtools. ---*/
+/*--- pc_common.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Ptrcheck, a Valgrind tool for checking pointer
+ use in programs.
+
+ Copyright (C) 2008-2008 OpenWorks Ltd
+ in...@op...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+
+ Neither the names of the U.S. Department of Energy nor the
+ University of California nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without prior written permission.
+*/
+
+#include "pub_tool_basics.h"
+#include "pub_tool_libcbase.h"
+#include "pub_tool_libcprint.h"
+#include "pub_tool_mallocfree.h"
+#include "pub_tool_libcassert.h"
+#include "pub_tool_options.h"
+#include "pub_tool_replacemalloc.h"
+#include "pub_tool_execontext.h"
+#include "pub_tool_tooliface.h" // CorePart
+#include "pub_tool_threadstate.h" // VG_(get_running_tid)
+#include "pub_tool_debuginfo.h"
+
+#include "h_list.h" // Seg
+#include "h_main.h" // NONPTR, BOTTOM, UNKNOWN
+
+#include "pc_common.h" // self
+
+
+//////////////////////////////////////////////////////////////
+// //
+// Command line options //
+// //
+//////////////////////////////////////////////////////////////
+
+Bool h_clo_partial_loads_ok = True; /* user visible */
+Bool h_clo_lossage_check = False; /* dev flag only */
+
+Bool pc_process_cmd_line_options(Char* arg)
+{
+ VG_BOOL_CLO(arg, "--partial-loads-ok", h_clo_partial_loads_ok)
+ else VG_BOOL_CLO(arg, "--lossage-check", h_clo_lossage_check)
+ else
+ return VG_(replacement_malloc_process_cmd_line_option)(arg);
+
+ return True;
+}
+
+void pc_print_usage(void)
+{
+ VG_(printf)(
+ " --partial-loads-ok=no|yes same as for Memcheck [yes]\n"
+ );
+ VG_(replacement_malloc_print_usage)();
+}
+
+void pc_print_debug_usage(void)
+{
+ VG_(printf)(
+ " --lossage-check=no|yes gather stats for quality control [no]\n"
+ );
+ VG_(replacement_malloc_print_debug_usage)();
+}
+
+
+
+//////////////////////////////////////////////////////////////
+// //
+// Error management //
+// //
+//////////////////////////////////////////////////////////////
+
+/* What kind of error it is. */
+typedef
+ enum {
+ XE_SorG=1202, // sg: stack or global array inconsistency
+ XE_Heap, // h: mismatched ptr/addr segments on load/store
+ XE_Arith, // h: bad arithmetic between two segment pointers
+ XE_SysParam // h: block straddling >1 segment passed to syscall
+ }
+ XErrorTag;
+
+typedef
+ enum {
+ XS_SorG=2021,
+ XS_Heap,
+ XS_Arith,
+ XS_SysParam
+ }
+ XSuppTag;
+
+typedef
+ struct {
+ XErrorTag tag;
+ union {
+ struct {
+ Addr addr;
+ SSizeT sszB; /* -ve is write, +ve is read */
+ HChar expect[128];
+ HChar actual[128];
+ } SorG;
+ struct {
+ Addr addr;
+ SSizeT sszB; /* -ve is write, +ve is read */
+ Seg vseg;
+ Char descr1[96];
+ Char descr2[96];
+ Char datasym[96];
+ OffT datasymoff;
+ } Heap;
+ struct {
+ Seg seg1;
+ Seg seg2;
+ const HChar* opname; // user-understandable text name
+ } Arith;
+ struct {
+ CorePart part;
+ Addr lo;
+ Addr hi;
+ Seg seglo;
+ Seg seghi;
+ } SysParam;
+ } XE;
+ }
+ XError;
+
+
+void sg_record_error_SorG ( ThreadId tid,
+ Addr addr, SSizeT sszB,
+ HChar* expect, HChar* actual )
+{
+ XError xe;
+ VG_(memset)(&xe, 0, sizeof(xe));
+ xe.XE.SorG.addr = addr;
+ xe.XE.SorG.sszB = sszB;
+ VG_(strncpy)( &xe.XE.SorG.expect[0],
+ expect, sizeof(xe.XE.SorG.expect) );
+ VG_(strncpy)( &xe.XE.SorG.actual[0],
+ actual, sizeof(xe.XE.SorG.actual) );
+ xe.XE.SorG.expect[ sizeof(xe.XE.SorG.expect)-1 ] = 0;
+ xe.XE.SorG.actual[ sizeof(xe.XE.SorG.actual)-1 ] = 0;
+ VG_(maybe_record_error)( tid, XE_SorG, 0, NULL, &xe );
+}
+
+void h_record_heap_error( Addr a, SizeT size, Seg vseg, Bool is_write )
+{
+ XError xe;
+ tl_assert(size > 0);
+ VG_(memset)(&xe, 0, sizeof(xe));
+ xe.tag = XE_Heap;
+ xe.XE.Heap.addr = a;
+ xe.XE.Heap.sszB = is_write ? -size : size;
+ xe.XE.Heap.vseg = vseg;
+ VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Heap,
+ /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
+}
+
+void h_record_arith_error( Seg seg1, Seg seg2, HChar* opname )
+{
+ XError xe;
+ VG_(memset)(&xe, 0, sizeof(xe));
+ xe.tag = XE_Arith;
+ xe.XE.Arith.seg1 = seg1;
+ xe.XE.Arith.seg2 = seg2;
+ xe.XE.Arith.opname = opname;
+ VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Arith,
+ /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
+}
+
+void h_record_sysparam_error( ThreadId tid, CorePart part, Char* s,
+ Addr lo, Addr hi, Seg seglo, Seg seghi )
+{
+ XError xe;
+ VG_(memset)(&xe, 0, sizeof(xe));
+ xe.tag = XE_SysParam;
+ xe.XE.SysParam.part = part;
+ xe.XE.SysParam.lo = lo;
+ xe.XE.SysParam.hi = hi;
+ xe.XE.SysParam.seglo = seglo;
+ xe.XE.SysParam.seghi = seghi;
+ VG_(maybe_record_error)( tid, XE_SysParam, /*a*/(Addr)0, /*str*/s,
+ /*extra*/(void*)&xe);
+}
+
+
+Bool pc_eq_Error ( VgRes res, Error* e1, Error* e2 )
+{
+ XError *xe1, *xe2;
+ tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
+ tl_assert(VG_(get_error_string)(e1) == NULL);
+ tl_assert(VG_(get_error_string)(e2) == NULL);
+
+ xe1 = (XError*)VG_(get_error_extra)(e1);
+ xe2 = (XError*)VG_(get_error_extra)(e2);
+ tl_assert(xe1);
+ tl_assert(xe2);
+
+ if (xe1->tag != xe2->tag)
+ return False;
+
+ switch (xe1->tag) {
+ case XE_SorG:
+ return //xe1->XE.SorG.addr == xe2->XE.SorG.addr
+ //&&
+ xe1->XE.SorG.sszB == xe2->XE.SorG.sszB
+ && 0 == VG_(strncmp)( &xe1->XE.SorG.expect[0],
+ &xe2->XE.SorG.expect[0],
+ sizeof(xe1->XE.SorG.expect) )
+ && 0 == VG_(strncmp)( &xe1->XE.SorG.actual[0],
+ &xe2->XE.SorG.actual[0],
+ sizeof(xe1->XE.SorG.actual) );
+ case XE_Heap:
+ case XE_Arith:
+ case XE_SysParam:
+ return True;
+ default:
+ VG_(tool_panic)("eq_Error: unrecognised error kind");
+ }
+}
+
+
+static Char* readwrite(SSizeT sszB)
+{
+ return ( sszB < 0 ? "write" : "read" );
+}
+
+static Word Word__abs ( Word w ) {
+ return w < 0 ? -w : w;
+}
+
+void pc_pp_Error ( Error* err )
+{
+ XError *xe = (XError*)VG_(get_error_extra)(err);
+ tl_assert(xe);
+
+ switch (VG_(get_error_kind)(err)) {
+
+ //----------------------------------------------------------
+ case XE_SorG:
+ tl_assert(xe);
+ VG_(message)(Vg_UserMsg, "Invalid %s of size %ld",
+ xe->XE.SorG.sszB < 0 ? "write" : "read",
+ Word__abs(xe->XE.SorG.sszB) );
+ VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+ VG_(message)(Vg_UserMsg, " Address %#lx expected vs actual:",
+ xe->XE.SorG.addr);
+ VG_(message)(Vg_UserMsg, " Expected: %s", &xe->XE.SorG.expect[0] );
+ VG_(message)(Vg_UserMsg, " Actual: %s", &xe->XE.SorG.actual[0] );
+ break;
+
+ //----------------------------------------------------------
+ case XE_Heap: {
+ Char *place, *legit, *how_invalid;
+ Addr a = xe->XE.Heap.addr;
+ Seg vseg = xe->XE.Heap.vseg;
+
+ tl_assert(is_known_segment(vseg) || NONPTR == vseg);
+
+ if (NONPTR == vseg) {
+ // Access via a non-pointer
+ VG_(message)(Vg_UserMsg, "Invalid %s of size %ld",
+ readwrite(xe->XE.Heap.sszB),
+ xe->XE.Heap.sszB);
+ VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+ VG_(message)(Vg_UserMsg,
+ " Address %#lx is not derived from any known block", a);
+
+ } else {
+ // Access via a pointer, but outside its range.
+ Int cmp;
+ UWord miss_size;
+ Seg__cmp(vseg, a, &cmp, &miss_size);
+ if (cmp < 0) place = "before";
+ else if (cmp == 0) place = "inside";
+ else place = "after";
+ how_invalid = ( ( Seg__is_freed(vseg) && 0 != cmp )
+ ? "Doubly-invalid" : "Invalid" );
+ legit = ( Seg__is_freed(vseg) ? "once-" : "" );
+
+ VG_(message)(Vg_UserMsg, "%s %s of size %ld", how_invalid,
+ readwrite(xe->XE.Heap.sszB),
+ xe->XE.Heap.sszB);
+ VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+
+ VG_(message)(Vg_UserMsg,
+ " Address %#lx is %lu bytes %s the accessing pointer's",
+ a, miss_size, place);
+ VG_(message)(Vg_UserMsg,
+ " %slegitimate range, a block of size %lu %s",
+ legit, Seg__size(vseg), Seg__status_str(vseg) );
+ VG_(pp_ExeContext)(Seg__where(vseg));
+ }
+ if (xe->XE.Heap.descr1[0] != 0)
+ VG_(message)(Vg_UserMsg, " %s", xe->XE.Heap.descr1);
+ if (xe->XE.Heap.descr2[0] != 0)
+ VG_(message)(Vg_UserMsg, " %s", xe->XE.Heap.descr2);
+ if (xe->XE.Heap.datasym[0] != 0)
+ VG_(message)(Vg_UserMsg, " Address 0x%llx is %llu bytes "
+ "inside data symbol \"%s\"",
+ (ULong)xe->XE.Heap.addr,
+ (ULong)xe->XE.Heap.datasymoff,
+ xe->XE.Heap.datasym);
+ break;
+ }
+
+ //----------------------------------------------------------
+ case XE_Arith: {
+ Seg seg1 = xe->XE.Arith.seg1;
+ Seg seg2 = xe->XE.Arith.seg2;
+ Char* which;
+
+ tl_assert(BOTTOM != seg1);
+ tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
+
+ VG_(message)(Vg_UserMsg, "Invalid arguments to %s", xe->XE.Arith.opname);
+ VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+
+ if (seg1 != seg2) {
+ if (NONPTR == seg1) {
+ VG_(message)(Vg_UserMsg, " First arg not a pointer");
+ } else if (UNKNOWN == seg1) {
+ VG_(message)(Vg_UserMsg, " First arg may be a pointer");
+ } else {
+ VG_(message)(Vg_UserMsg, " First arg derived from address %#lx of "
+ "%lu-byte block %s",
+ Seg__a(seg1), Seg__size(seg1),
+ Seg__status_str(seg1) );
+ VG_(pp_ExeContext)(Seg__where(seg1));
+ }
+ which = "Second arg";
+ } else {
+ which = "Both args";
+ }
+ if (NONPTR == seg2) {
+ VG_(message)(Vg_UserMsg, " %s not a pointer", which);
+ } else {
+ VG_(message)(Vg_UserMsg, " %s derived from address %#lx of "
+ "%lu-byte block %s",
+ which, Seg__a(seg2), Seg__size(seg2),
+ Seg__status_str(seg2));
+ VG_(pp_ExeContext)(Seg__where(seg2));
+ }
+ break;
+ }
+
+ //----------------------------------------------------------
+ case XE_SysParam: {
+ Addr lo = xe->XE.SysParam.lo;
+ Addr hi = xe->XE.SysParam.hi;
+ Seg seglo = xe->XE.SysParam.seglo;
+ Seg seghi = xe->XE.SysParam.seghi;
+ Char* s = VG_(get_error_string) (err);
+ Char* what;
+
+ tl_assert(BOTTOM != seglo && BOTTOM != seghi);
+
+ if (Vg_CoreSysCall == xe->XE.SysParam.part)
+ what = "Syscall param ";
+ else VG_(tool_panic)("bad CorePart");
+
+ if (seglo == seghi) {
+ // freed block
+ tl_assert(is_known_segment(seglo));
+ tl_assert(Seg__is_freed(seglo));
+ VG_(message)(Vg_UserMsg, "%s%s contains unaddressable byte(s)",
+ what, s);
+ VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+
+ VG_(message)(Vg_UserMsg, " Address %#lx is %ld bytes inside a "
+ "%ld-byte block %s",
+ lo, lo-Seg__a(seglo), Seg__size(seglo),
+ Seg__status_str(seglo) );
+ VG_(pp_ExeContext)(Seg__where(seglo));
+
+ } else {
+ // mismatch
+ VG_(message)(Vg_UserMsg, "%s%s is non-contiguous", what, s);
+ VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+
+ if (UNKNOWN == seglo) {
+ VG_(message)(Vg_UserMsg, " First byte is not inside a known block");
+ } else {
+ VG_(message)(Vg_UserMsg, " First byte (%#lx) is %ld bytes inside a "
+ "%ld-byte block %s",
+ lo, lo-Seg__a(seglo), Seg__size(seglo),
+ Seg__status_str(seglo) );
+ VG_(pp_ExeContext)(Seg__where(seglo));
+ }
+
+ if (UNKNOWN == seghi) {
+ VG_(message)(Vg_UserMsg, " Last byte is not inside a known block");
+ } else {
+ VG_(message)(Vg_UserMsg, " Last byte (%#lx) is %ld bytes inside a "
+ "%ld-byte block %s",
+ hi, hi-Seg__a(seghi), Seg__size(seghi),
+ Seg__status_str(seghi));
+ VG_(pp_ExeContext)(Seg__where(seghi));
+ }
+ }
+ break;
+ }
+
+ default:
+ VG_(tool_panic)("pp_Error: unrecognised error kind");
+ }
+}
+
+
+UInt pc_update_Error_extra ( Error* err )
+{
+ XError *xe = (XError*)VG_(get_error_extra)(err);
+ tl_assert(xe);
+ switch (xe->tag) {
+ case XE_SorG:
+ return sizeof(XError);
+ case XE_Heap: {
+ tl_assert(sizeof(xe->XE.Heap.descr1) == sizeof(xe->XE.Heap.descr2));
+ tl_assert(sizeof(xe->XE.Heap.descr1) > 0);
+ tl_assert(sizeof(xe->XE.Heap.datasym) > 0);
+ VG_(memset)(&xe->XE.Heap.descr1, 0, sizeof(xe->XE.Heap.descr1));
+ VG_(memset)(&xe->XE.Heap.descr2, 0, sizeof(xe->XE.Heap.descr2));
+ VG_(memset)(&xe->XE.Heap.datasym, 0, sizeof(xe->XE.Heap.datasym));
+ xe->XE.Heap.datasymoff = 0;
+ if (VG_(get_data_description)( &xe->XE.Heap.descr1[0],
+ &xe->XE.Heap.descr2[0],
+ sizeof(xe->XE.Heap.descr1)-1,
+ xe->XE.Heap.addr )) {
+ tl_assert(xe->XE.Heap.descr1[sizeof(xe->XE.Heap.descr1)-1] == 0);
+ tl_assert(xe->XE.Heap.descr1[sizeof(xe->XE.Heap.descr2)-1] == 0);
+ }
+ else
+ if (VG_(get_datasym_and_offset)( xe->XE.Heap.addr,
+ &xe->XE.Heap.datasym[0],
+ sizeof(xe->XE.Heap.datasym)-1,
+ &xe->XE.Heap.datasymoff )) {
+ tl_assert(xe->XE.Heap.datasym[sizeof(xe->XE.Heap.datasym)-1] == 0);
+ }
+ return sizeof(XError);
+ }
+ case XE_Arith:
+ return sizeof(XError);
+ case XE_SysParam:
+ return sizeof(XError);
+ default:
+ VG_(tool_panic)("update_extra");
+ }
+}
+
+Bool pc_is_recognised_suppression ( Char* name, Supp *su )
+{
+ SuppKind skind;
+
+ if (VG_STREQ(name, "SorG")) skind = XS_SorG;
+ else if (VG_STREQ(name, "Heap")) skind = XS_Heap;
+ else if (VG_STREQ(name, "Arith")) skind = XS_Arith;
+ else if (VG_STREQ(name, "SysParam")) skind = XS_SysParam;
+ else
+ return False;
+
+ VG_(set_supp_kind)(su, skind);
+ return True;
+}
+
+Bool pc_read_extra_suppression_info ( Int fd, Char* buf,
+ Int nBuf, Supp* su )
+{
+ Bool eof;
+ if (VG_(get_supp_kind)(su) == XS_SysParam) {
+ eof = VG_(get_line) ( fd, buf, nBuf );
+ if (eof) return False;
+ VG_(set_supp_string)(su, VG_(strdup)(buf));
+ }
+ return True;
+}
+
+Bool pc_error_matches_suppression (Error* err, Supp* su)
+{
+ ErrorKind ekind = VG_(get_error_kind)(err);
+ switch (VG_(get_supp_kind)(su)) {
+ case XS_SorG: return ekind == XE_SorG;
+ case XS_Heap: return ekind == XE_Heap;
+ case XS_Arith: return ekind == XE_Arith;
+ case XS_SysParam: return ekind == XE_SysParam;
+ default:
+ VG_(printf)("Error:\n"
+ " unknown suppression type %d\n",
+ VG_(get_supp_kind)(su));
+ VG_(tool_panic)("unknown suppression type in "
+ "pc_error_matches_suppression");
+ }
+}
+
+Char* pc_get_error_name ( Error* err )
+{
+ XError *xe = (XError*)VG_(get_error_extra)(err);
+ tl_assert(xe);
+ switch (xe->tag) {
+ case XE_SorG: return "SorG";
+ case XE_Heap: return "Heap";
+ case XE_Arith: return "Arith";
+ case XE_SysParam: return "SysParam";
+ default: VG_(tool_panic)("get_error_name: unexpected type");
+ }
+}
+
+void pc_print_extra_suppression_info ( Error* err )
+{
+ if (XE_SysParam == VG_(get_error_kind)(err)) {
+ VG_(printf)(" %s\n", VG_(get_error_string)(err));
+ }
+}
+
+
+
+
+/*--------------------------------------------------------------------*/
+/*--- end pc_common.c ---*/
+/*--------------------------------------------------------------------*/
Added: branches/PTRCHECK/exp-ptrcheck/pc_common.h
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/pc_common.h (rev 0)
+++ branches/PTRCHECK/exp-ptrcheck/pc_common.h 2008-09-09 08:35:09 UTC (rev 8589)
@@ -0,0 +1,70 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Ptrcheck: a pointer-use checker. ---*/
+/*--- Exports for stuff shared between sg_ and h_ subtools. ---*/
+/*--- pc_common.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Ptrcheck, a Valgrind tool for checking pointer
+ use in programs.
+
+ Copyright (C) 2008-2008 OpenWorks Ltd
+ in...@op...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PC_COMMON_H
+
+#define __PC_COMMON_H
+
+void sg_record_error_SorG ( ThreadId tid,
+ Addr addr, SSizeT sszB,
+ HChar* expect, HChar* actual );
+
+void h_record_heap_error( Addr a, SizeT size, Seg vseg, Bool is_write );
+
+void h_record_arith_error( Seg seg1, Seg seg2, HChar* opname );
+
+void h_record_sysparam_error( ThreadId tid, CorePart part, Char* s,
+ Addr lo, Addr hi, Seg seglo, Seg seghi );
+
+Bool pc_eq_Error ( VgRes res, Error* e1, Error* e2 );
+void pc_pp_Error ( Error* err );
+UInt pc_update_Error_extra ( Error* err );
+Bool pc_is_recognised_suppression ( Char* name, Supp *su );
+Bool pc_read_extra_suppression_info ( Int fd, Char* buf,
+ Int nBuf, Supp* su );
+Bool pc_error_matches_suppression (Error* err, Supp* su);
+Char* pc_get_error_name ( Error* err );
+void pc_print_extra_suppression_info ( Error* err );
+
+extern Bool h_clo_partial_loads_ok;
+extern Bool h_clo_lossage_check;
+
+Bool pc_process_cmd_line_options(Char* arg);
+void pc_print_usage(void);
+void pc_print_debug_usage(void);
+
+
+#endif
+
+/*--------------------------------------------------------------------*/
+/*--- end pc_common.h ---*/
+/*--------------------------------------------------------------------*/
Added: branches/PTRCHECK/exp-ptrcheck/pc_main.c
===================================================================
--- branches/PTRCHECK/exp-ptrcheck/pc_main.c (rev 0)
+++ branches/PTRCHECK/exp-ptrcheck/pc_main.c 2008-09-09 08:35:09 UTC (rev 8589)
@@ -0,0 +1,207 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Ptrcheck: a pointer-use checker. ---*/
+/*--- This file coordinates the h_ and sg_ subtools. ---*/
+/*--- pc_main.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Ptrcheck, a Valgrind tool for checking pointer
+ use in programs.
+
+ Copyright (C) 2008-2008 OpenWorks Ltd
+ in...@op...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+
+ Neither the names of the U.S. Department of Energy nor the
+ University of California nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without prior written permission.
+*/
+
+#include "pub_tool_basics.h"
+#include "pub_tool_libcassert.h"
+#include "pub_tool_execontext.h"
+#include "pub_tool_toolifa...
[truncated message content] |
|
From: <bar...@gm...> - 2008-09-09 07:50:57
|
Nightly build on georgia-tech-cellbuzz ( IBM BladeCenter QS20 ) started at 2008-09-09 03:00:01 EDT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... done Regression test results follow == 368 tests, 21 stderr failures, 11 stdout failures, 1 post failure == drd/tests/pth_create_chain (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc07_hbl1 (stderr) helgrind/tests/tc08_hbl2 (stderr) helgrind/tests/tc11_XCHG (stderr) helgrind/tests/tc20_verifywrap (stderr) massif/tests/long-names (post) memcheck/tests/deep_templates (stdout) memcheck/tests/file_locking (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (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/zeropage (stdout) none/tests/async-sigs (stdout) none/tests/blockfault (stderr) none/tests/faultstatus (stderr) none/tests/fdleak_cmsg (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) none/tests/ppc32/jm-fp (stdout) none/tests/ppc32/jm-vmx (stdout) none/tests/ppc32/round (stdout) none/tests/ppc32/test_gx (stdout) none/tests/ppc64/jm-fp (stdout) none/tests/ppc64/jm-vmx (stdout) none/tests/ppc64/round (stdout) |
|
From: Tom H. <th...@cy...> - 2008-09-09 03:11:51
|
Nightly build on alvis ( i686, Red Hat 7.3 ) started at 2008-09-09 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 == 346 tests, 60 stderr failures, 1 stdout failure, 29 post failures == 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) 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) 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) 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) |
|
From: Tom H. <th...@cy...> - 2008-09-09 02:55:50
|
Nightly build on aston ( x86_64, Fedora Core 5 ) started at 2008-09-09 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 == 444 tests, 8 stderr failures, 2 stdout failures, 0 post failures == helgrind/tests/tc08_hbl2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) 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) ================================================= == 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 == 444 tests, 7 stderr failures, 1 stdout failure, 0 post failures == helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) 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) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Tue Sep 9 03:38:33 2008 --- new.short Tue Sep 9 03:56:00 2008 *************** *** 8,11 **** ! == 444 tests, 7 stderr failures, 1 stdout failure, 0 post failures == helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) --- 8,13 ---- ! == 444 tests, 8 stderr failures, 2 stdout failures, 0 post failures == ! helgrind/tests/tc08_hbl2 (stdout) helgrind/tests/tc20_verifywrap (stderr) + helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-09-09 02:51:57
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2008-09-09 03:05:05 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 438 tests, 7 stderr failures, 2 stdout failures, 0 post failures == helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) 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/blockfault (stderr) none/tests/mremap2 (stdout) |
|
From: Tom H. <th...@cy...> - 2008-09-09 02:46:00
|
Nightly build on trojan ( x86_64, Fedora Core 6 ) started at 2008-09-09 03:25:06 BST Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 442 tests, 9 stderr failures, 5 stdout failures, 0 post failures == helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) 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/blockfault (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap2 (stdout) ================================================= == 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 == 442 tests, 10 stderr failures, 5 stdout failures, 0 post failures == helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) 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/blockfault (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap2 (stdout) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Tue Sep 9 03:35:48 2008 --- new.short Tue Sep 9 03:46:07 2008 *************** *** 8,11 **** ! == 442 tests, 10 stderr failures, 5 stdout failures, 0 post failures == ! helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc20_verifywrap (stderr) --- 8,10 ---- ! == 442 tests, 9 stderr failures, 5 stdout failures, 0 post failures == helgrind/tests/tc20_verifywrap (stderr) |
|
From: Tom H. <th...@cy...> - 2008-09-09 02:23:41
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2008-09-09 03:00:04 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 == 444 tests, 31 stderr failures, 3 stdout failures, 0 post failures == 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) 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) |