You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
1
(1) |
2
(4) |
3
(3) |
4
(6) |
5
(14) |
6
(10) |
7
(4) |
|
8
(2) |
9
(4) |
10
(7) |
11
(8) |
12
(5) |
13
(11) |
14
(4) |
|
15
(4) |
16
(9) |
17
(6) |
18
|
19
|
20
|
21
|
|
22
(3) |
23
(1) |
24
(7) |
25
(12) |
26
(8) |
27
(13) |
28
(4) |
|
29
(3) |
30
(4) |
|
|
|
|
|
|
From: Tom H. <th...@cy...> - 2009-11-14 03:50:36
|
Nightly build on vauxhall ( x86_64, Fedora 11 ) Started at 2009-11-14 03:20:05 GMT Ended at 2009-11-14 03:50:18 GMT 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 == 541 tests, 6 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc23_bogus_condwait (stderr) exp-ptrcheck/tests/bad_percentify (stderr) |
|
From: Tom H. <th...@cy...> - 2009-11-14 03:49:31
|
Nightly build on lloyd ( x86_64, Fedora 7 ) Started at 2009-11-14 03:05:03 GMT Ended at 2009-11-14 03:49:11 GMT 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 == 531 tests, 1 stderr failure, 0 stdout failures, 0 post failures == helgrind/tests/tc06_two_races_xml (stderr) |
|
From: Tom H. <th...@cy...> - 2009-11-14 03:36:01
|
Nightly build on mg ( x86_64, Fedora 9 ) Started at 2009-11-14 03:10:04 GMT Ended at 2009-11-14 03:35:44 GMT 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 == 538 tests, 2 stderr failures, 0 stdout failures, 0 post failures == helgrind/tests/pth_spinlock (stderr) helgrind/tests/tc06_two_races_xml (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 538 tests, 1 stderr failure, 0 stdout failures, 0 post failures == helgrind/tests/tc06_two_races_xml (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Sat Nov 14 03:23:00 2009 --- new.short Sat Nov 14 03:35:43 2009 *************** *** 8,10 **** ! == 538 tests, 1 stderr failure, 0 stdout failures, 0 post failures == helgrind/tests/tc06_two_races_xml (stderr) --- 8,11 ---- ! == 538 tests, 2 stderr failures, 0 stdout failures, 0 post failures == ! helgrind/tests/pth_spinlock (stderr) helgrind/tests/tc06_two_races_xml (stderr) |
|
From: Tom H. <to...@co...> - 2009-11-13 17:58:42
|
On 13/11/09 18:08, Julian Seward wrote: >> This is also I think the main problem that Jakub was having with PPC of >> it not unwinding enough registers and it not being easy to add extra >> registers to the set being unwound. > > Uh, so we're trying to support CFI unwinding on PPC too, now? This > seems like a good thing to me. However, I've been scratching my head, > trying to figure out how to generalise the type DiCfSI (the unwind > summary record) and VG_(use_CF_info) (the function that uses it) > so as to be more general, yet not more expensive in time or space. > For a large program, there are zillions of DiCfSI records sloshing > around, and looking them up causes noticable L2 misses. Jakub tried to get CFI unwinding working and gave up - he talks about it on one of the bugs. There are a few bits of the work he did in the patches I committed but most of it he reverted and just fixed up that one unwind bug in the traditional unwinder. Tom -- Tom Hughes (to...@co...) http://www.compton.nu/ |
|
From: Julian S. <js...@ac...> - 2009-11-13 17:54:49
|
> > * Dwarf CFI reading for ARM: it's apparently necessary to > > simultaneously unwind r15, r14, r13, r12 and r11. Omitting any of > > those can cause the next level of the unwind to fail. The CFI > > unwinder and associated data types have been changed to match this > > (is platform specific; need to figure out a way to merge this > > cleanly with the amd64 unwind stuff). > > I think you're supposed to unwind all the registers to be honest which > is probably where the problem starts. Yes, indeed. I've been reluctant to go down that road because it increases the costs of unwinding, which start to become significant on memcheck in malloc/free intensive code and are very evident in Helgrind, which unwinds very often. It's a dog of a problem. If you can think of a better way to be both general and fast ... > need all those on ARM though - well except r12 maybe (that's the static > base pointer isn't it?). I get the impression frame pointers on arm went the way of the dodo around the time Thumb was introduced. Possibly because Thumb only allows 8 registers, so tying one up becomes a more expensive proposition. > This is also I think the main problem that Jakub was having with PPC of > it not unwinding enough registers and it not being easy to add extra > registers to the set being unwound. Uh, so we're trying to support CFI unwinding on PPC too, now? This seems like a good thing to me. However, I've been scratching my head, trying to figure out how to generalise the type DiCfSI (the unwind summary record) and VG_(use_CF_info) (the function that uses it) so as to be more general, yet not more expensive in time or space. For a large program, there are zillions of DiCfSI records sloshing around, and looking them up causes noticable L2 misses. > Jakub's stuff that I committed also does this so there will definitely > be some merging to do there. Yes, I saw that too. For some reason I didn't yet figure out, the .debug_frame reading stuff works for .so's even though I didn't make any effort to add text_bias values or any such onto the address range covered by each DiCfSI. J |
|
From: Tom H. <to...@co...> - 2009-11-13 17:28:10
|
On 13/11/09 17:21, sv...@va... wrote: > * an abstraction level upgrade. In many places to do with unwinding, > we pass around values for the instruction pointer, stack pointer, > frame pointer and link register. Considering that the only fields > common to all platforms are the first two (IP and SP), this rapidly > becomes confusing (eg, what value should we pass for the link > register on amd64? for the frame pointer on arm? does it matter?) > > Such ad-hoc-ery is now replaced with a struct UnwindStartRegs, which > holds the specific values needed for unwinding on a given platform. > Much passing around of ip/sp/fp/lr is now replaced by a single > UnwindStartRegs*. > > In the places where unwinding is started, we now have to create an > UnwindStartRegs rather than said values. That's certainly good, and I suspect may help with getting it working with PPC as well. > * Dwarf CFI reading for ARM: it's apparently necessary to > simultaneously unwind r15, r14, r13, r12 and r11. Omitting any of > those can cause the next level of the unwind to fail. The CFI > unwinder and associated data types have been changed to match this > (is platform specific; need to figure out a way to merge this > cleanly with the amd64 unwind stuff). I think you're supposed to unwind all the registers to be honest which is probably where the problem starts. It doesn't surprise me that you need all those on ARM though - well except r12 maybe (that's the static base pointer isn't it?). This is also I think the main problem that Jakub was having with PPC of it not unwinding enough registers and it not being easy to add extra registers to the set being unwound. > * ML_(read_callframe_info_dwarf3): handle .debug_frame sections (for > arm-ELF). These are unfortunately slightly different from the > .eh_frame sections used for amd64-ELF. Jakub's stuff that I committed also does this so there will definitely be some merging to do there. > * coregrind/m_stacktrace.c: split the main function, > VG_(get_StackTrace_wrk) into completely separate instances for the > different targets. Maintaining just one big function is too > unwieldy. Yes, that bent my brain when I was trying to understand that one line change to the PPC unwind logic... Splitting it is definitely a good idea. Tom -- Tom Hughes (to...@co...) http://www.compton.nu/ |
|
From: <sv...@va...> - 2009-11-13 17:21:18
|
Author: sewardj
Date: 2009-11-13 17:21:04 +0000 (Fri, 13 Nov 2009)
New Revision: 10940
Log:
Make CFI based stack unwinding (apparently) work on ARM. This
completely breaks the amd64 unwinder for the time being, and contains
just as many arm-specific kludges as the amd64 version contains
amd64-specific kludges. This will be tidied up in future commits. It
also doesn't take into account recent work by Jacob Jelink, and will
need rebasing before merging to trunk.
Changes:
* an abstraction level upgrade. In many places to do with unwinding,
we pass around values for the instruction pointer, stack pointer,
frame pointer and link register. Considering that the only fields
common to all platforms are the first two (IP and SP), this rapidly
becomes confusing (eg, what value should we pass for the link
register on amd64? for the frame pointer on arm? does it matter?)
Such ad-hoc-ery is now replaced with a struct UnwindStartRegs, which
holds the specific values needed for unwinding on a given platform.
Much passing around of ip/sp/fp/lr is now replaced by a single
UnwindStartRegs*.
In the places where unwinding is started, we now have to create an
UnwindStartRegs rather than said values.
* Dwarf CFI reading for ARM: it's apparently necessary to
simultaneously unwind r15, r14, r13, r12 and r11. Omitting any of
those can cause the next level of the unwind to fail. The CFI
unwinder and associated data types have been changed to match this
(is platform specific; need to figure out a way to merge this
cleanly with the amd64 unwind stuff).
* ML_(read_callframe_info_dwarf3): handle .debug_frame sections (for
arm-ELF). These are unfortunately slightly different from the
.eh_frame sections used for amd64-ELF.
* coregrind/m_stacktrace.c: split the main function,
VG_(get_StackTrace_wrk) into completely separate instances for the
different targets. Maintaining just one big function is too
unwieldy.
Also (on ARM) remove lengthy machinery for trying to do unwinding by
analysing the machine code. I think that's not necessary because
the CFI mechanism should handle all required cases.
Modified:
branches/ARM/coregrind/m_debuginfo/debuginfo.c
branches/ARM/coregrind/m_debuginfo/priv_readdwarf.h
branches/ARM/coregrind/m_debuginfo/priv_storage.h
branches/ARM/coregrind/m_debuginfo/readdwarf.c
branches/ARM/coregrind/m_debuginfo/readelf.c
branches/ARM/coregrind/m_debuginfo/storage.c
branches/ARM/coregrind/m_libcassert.c
branches/ARM/coregrind/m_machine.c
branches/ARM/coregrind/m_signals.c
branches/ARM/coregrind/m_stacktrace.c
branches/ARM/coregrind/pub_core_basics.h
branches/ARM/coregrind/pub_core_debuginfo.h
branches/ARM/coregrind/pub_core_libcassert.h
branches/ARM/coregrind/pub_core_machine.h
branches/ARM/coregrind/pub_core_stacktrace.h
Modified: branches/ARM/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/ARM/coregrind/m_debuginfo/debuginfo.c 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_debuginfo/debuginfo.c 2009-11-13 17:21:04 UTC (rev 10940)
@@ -1821,9 +1821,10 @@
a CfiExpr into one convenient struct. */
typedef
struct {
- Addr ipHere;
- Addr spHere;
- Addr fpHere;
+ Addr r15Here;
+ Addr r14Here;
+ Addr r13Here;
+ Addr r12Here;
Addr min_accessible;
Addr max_accessible;
}
@@ -1855,9 +1856,10 @@
/*NOTREACHED*/
case Cex_CfiReg:
switch (e->Cex.CfiReg.reg) {
- case Creg_IP: return (Addr)eec->ipHere;
- case Creg_SP: return (Addr)eec->spHere;
- case Creg_FP: return (Addr)eec->fpHere;
+ case Creg_R15: return (Addr)eec->r15Here;
+ case Creg_R14: return (Addr)eec->r14Here;
+ case Creg_R13: return (Addr)eec->r13Here;
+ case Creg_R12: return (Addr)eec->r12Here;
default: goto unhandled;
}
/*NOTREACHED*/
@@ -2003,22 +2005,26 @@
}
-/* The main function for DWARF2/3 CFI-based stack unwinding.
- Given an IP/SP/FP triple, produce the IP/SP/FP values for the
- previous frame, if possible. */
-/* Returns True if OK. If not OK, *{ip,sp,fp}P are not changed. */
+/* The main function for DWARF2/3 CFI-based stack unwinding. Given an
+ R15/R14/R13/R12/R11 set, produce the R15/R14/R13/R12/R11 values for
+ the previous frame, if possible. */
+/* Returns True if OK. If not OK, *{r15,r14,r13,r12,r11}P are not
+ changed. */
/* NOTE: this function may rearrange the order of entries in the
DebugInfo list. */
-Bool VG_(use_CF_info) ( /*MOD*/Addr* ipP,
- /*MOD*/Addr* spP,
- /*MOD*/Addr* fpP,
+Bool VG_(use_CF_info) ( /*MOD*/Addr* r15P,
+ /*MOD*/Addr* r14P,
+ /*MOD*/Addr* r13P,
+ /*MOD*/Addr* r12P,
+ /*MOD*/Addr* r11P,
Addr min_accessible,
Addr max_accessible )
{
Bool ok;
DebugInfo* di;
DiCfSI* cfsi = NULL;
- Addr cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
+ Addr r15Here, r14Here, r13Here, r12Here, r11Here, cfa;
+ Addr r15Prev, r14Prev, r13Prev, r12Prev, r11Prev;
CfiExprEvalContext eec;
@@ -2027,16 +2033,16 @@
if (0 && 0 == (n_q & 0x1FFFFF))
VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
- { UWord hash = (*ipP) % N_CFSI_CACHE;
+ { UWord hash = (*r15P) % N_CFSI_CACHE;
CFSICacheEnt* ce = &cfsi_cache[hash];
- if (LIKELY(ce->ip == *ipP) && LIKELY(ce->di != NULL)) {
+ if (LIKELY(ce->ip == *r15P) && LIKELY(ce->di != NULL)) {
/* found an entry in the cache .. */
} else {
/* not found in cache. Search and update. */
n_m++;
- ce->ip = *ipP;
- find_DiCfSI( &ce->di, &ce->ix, *ipP );
+ ce->ip = *r15P;
+ find_DiCfSI( &ce->di, &ce->ix, *r15P );
}
if (UNLIKELY(ce->di == (DebugInfo*)1)) {
@@ -2058,30 +2064,36 @@
ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
}
- ipPrev = spPrev = fpPrev = 0;
+ r15Prev = r14Prev = r13Prev = r12Prev = r11Prev = 0;
- ipHere = *ipP;
- spHere = *spP;
- fpHere = *fpP;
+ r15Here = *r15P;
+ r14Here = *r14P;
+ r13Here = *r13P;
+ r12Here = *r12P;
+ r11Here = *r11P;
/* First compute the CFA. */
cfa = 0;
switch (cfsi->cfa_how) {
- case CFIC_SPREL:
- cfa = cfsi->cfa_off + spHere;
+ case CFIC_R13REL:
+ cfa = cfsi->cfa_off + r13Here;
break;
- case CFIC_FPREL:
- cfa = cfsi->cfa_off + fpHere;
+ case CFIC_R12REL:
+ cfa = cfsi->cfa_off + r12Here;
break;
+ case CFIC_R11REL:
+ cfa = cfsi->cfa_off + r11Here;
+ break;
case CFIC_EXPR:
if (0) {
VG_(printf)("CFIC_EXPR: ");
ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
VG_(printf)("\n");
}
- eec.ipHere = ipHere;
- eec.spHere = spHere;
- eec.fpHere = fpHere;
+ eec.r15Here = r15Here;
+ eec.r14Here = r14Here;
+ eec.r13Here = r13Here;
+ eec.r12Here = r12Here;
eec.min_accessible = min_accessible;
eec.max_accessible = max_accessible;
ok = True;
@@ -2116,9 +2128,10 @@
case CFIR_EXPR: \
if (0) \
ML_(ppCfiExpr)(di->cfsi_exprs,_off); \
- eec.ipHere = ipHere; \
- eec.spHere = spHere; \
- eec.fpHere = fpHere; \
+ eec.r15Here = r15Here; \
+ eec.r14Here = r14Here; \
+ eec.r13Here = r13Here; \
+ eec.r12Here = r12Here; \
eec.min_accessible = min_accessible; \
eec.max_accessible = max_accessible; \
ok = True; \
@@ -2130,15 +2143,19 @@
} \
} while (0)
- COMPUTE(ipPrev, ipHere, cfsi->ra_how, cfsi->ra_off);
- COMPUTE(spPrev, spHere, cfsi->sp_how, cfsi->sp_off);
- COMPUTE(fpPrev, fpHere, cfsi->fp_how, cfsi->fp_off);
+ COMPUTE(r15Prev, r15Here, cfsi->ra_how, cfsi->ra_off);
+ COMPUTE(r14Prev, r14Here, cfsi->r14_how, cfsi->r14_off);
+ COMPUTE(r13Prev, r13Here, cfsi->r13_how, cfsi->r13_off);
+ COMPUTE(r12Prev, r12Here, cfsi->r12_how, cfsi->r12_off);
+ COMPUTE(r11Prev, r11Here, cfsi->r11_how, cfsi->r11_off);
# undef COMPUTE
- *ipP = ipPrev;
- *spP = spPrev;
- *fpP = fpPrev;
+ *r15P = r15Prev;
+ *r14P = r14Prev;
+ *r13P = r13Prev;
+ *r12P = r12Prev;
+ *r11P = r11Prev;
return True;
}
Modified: branches/ARM/coregrind/m_debuginfo/priv_readdwarf.h
===================================================================
--- branches/ARM/coregrind/m_debuginfo/priv_readdwarf.h 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_debuginfo/priv_readdwarf.h 2009-11-13 17:21:04 UTC (rev 10940)
@@ -62,9 +62,10 @@
-------------------- */
extern
void ML_(read_callframe_info_dwarf3)
- ( /*OUT*/struct _DebugInfo* di, UChar* ehframe );
+ ( /*OUT*/struct _DebugInfo* di,
+ HChar* xxframe_name,
+ UChar* xxframe_image, SizeT xxframe_size, Addr xxframe_avma );
-
#endif /* ndef __PRIV_READDWARF_H */
/*--------------------------------------------------------------------*/
Modified: branches/ARM/coregrind/m_debuginfo/priv_storage.h
===================================================================
--- branches/ARM/coregrind/m_debuginfo/priv_storage.h 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_debuginfo/priv_storage.h 2009-11-13 17:21:04 UTC (rev 10940)
@@ -98,39 +98,42 @@
/* --------------------- CF INFO --------------------- */
/* A structure to summarise DWARF2/3 CFA info for the code address
- range [base .. base+len-1]. In short, if you know (sp,fp,ip) at
- some point and ip is in the range [base .. base+len-1], it tells
- you how to calculate (sp,fp) for the caller of the current frame
- and also ra, the return address of the current frame.
+ range [base .. base+len-1]. In short, if you know
+ (r15,r14,r13,r12,r11) at some point and r15 is in the range [base
+ .. base+len-1], it tells you how to calculate (r14,r13,r12,r11) for
+ the caller of the current frame and also ra, the return address of
+ the current frame.
First off, calculate CFA, the Canonical Frame Address, thusly:
cfa = case cfa_how of
- CFIC_SPREL -> sp + cfa_off
- CFIC_FPREL -> fp + cfa_off
- CFIR_EXPR -> expr whose index is in cfa_off
+ CFIC_R13REL -> r13 + cfa_off
+ CFIC_R12REL -> r12 + cfa_off
+ CFIC_R11REL -> r11 + cfa_off
+ CFIR_EXPR -> expr whose index is in cfa_off
Once that is done, the previous frame's sp/fp values and this
frame's ra value can be calculated like this:
- old_sp/fp/ra
- = case sp/fp/ra_how of
+ old_r14/r13/r12/r11/ra
+ = case r14/r13/r12/r11/ra_how of
CFIR_UNKNOWN -> we don't know, sorry
- CFIR_SAME -> same as it was before (sp/fp only)
- CFIR_CFAREL -> cfa + sp/fp/ra_off
- CFIR_MEMCFAREL -> *( cfa + sp/fp/ra_off )
- CFIR_EXPR -> expr whose index is in sp/fp/ra_off
+ CFIR_SAME -> same as it was before (r14/r13/r12/r11 only)
+ CFIR_CFAREL -> cfa + r14/r13/r12/r11/ra_off
+ CFIR_MEMCFAREL -> *( cfa + r14/r13/r12/r11/ra_off )
+ CFIR_EXPR -> expr whose index is in r14/r13/r12/r11/ra_off
*/
-#define CFIC_SPREL ((UChar)1)
-#define CFIC_FPREL ((UChar)2)
-#define CFIC_EXPR ((UChar)3)
+#define CFIC_R13REL ((UChar)1)
+#define CFIC_R12REL ((UChar)2)
+#define CFIC_R11REL ((UChar)3)
+#define CFIC_EXPR ((UChar)4)
-#define CFIR_UNKNOWN ((UChar)4)
-#define CFIR_SAME ((UChar)5)
-#define CFIR_CFAREL ((UChar)6)
-#define CFIR_MEMCFAREL ((UChar)7)
-#define CFIR_EXPR ((UChar)8)
+#define CFIR_UNKNOWN ((UChar)5)
+#define CFIR_SAME ((UChar)6)
+#define CFIR_CFAREL ((UChar)7)
+#define CFIR_MEMCFAREL ((UChar)8)
+#define CFIR_EXPR ((UChar)9)
typedef
struct {
@@ -138,12 +141,16 @@
UInt len;
UChar cfa_how; /* a CFIC_ value */
UChar ra_how; /* a CFIR_ value */
- UChar sp_how; /* a CFIR_ value */
- UChar fp_how; /* a CFIR_ value */
+ UChar r14_how; /* a CFIR_ value */
+ UChar r13_how; /* a CFIR_ value */
+ UChar r12_how; /* a CFIR_ value */
+ UChar r11_how; /* a CFIR_ value */
Int cfa_off;
Int ra_off;
- Int sp_off;
- Int fp_off;
+ Int r14_off;
+ Int r13_off;
+ Int r12_off;
+ Int r11_off;
}
DiCfSI;
@@ -159,9 +166,10 @@
typedef
enum {
- Creg_SP=0x213,
- Creg_FP,
- Creg_IP
+ Creg_R13=0x213,
+ Creg_R12,
+ Creg_R15,
+ Creg_R14
}
CfiReg;
Modified: branches/ARM/coregrind/m_debuginfo/readdwarf.c
===================================================================
--- branches/ARM/coregrind/m_debuginfo/readdwarf.c 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_debuginfo/readdwarf.c 2009-11-13 17:21:04 UTC (rev 10940)
@@ -1493,9 +1493,26 @@
/*------------------------------------------------------------*/
-/*--- Read call-frame info from an .eh_frame section ---*/
+/*--- Read call-frame info from .{eh,debug}_frame sections ---*/
/*------------------------------------------------------------*/
+/* Note that various variables are called xx_frame. This means they
+ refer to either .eh_frame things or .debug_frame things. Which one
+ is taken care of by the caller of the main routine,
+ ML_(read_callframe_info_dwarf3) and so the rest of the frame
+ reading code does not have to worry about which it is. This also
+ means it's wrong to look at the .eh_frame specific fields in the
+ DebugInfo* which we're passed; and none of the code should do that.
+
+ FIXME: actually we need to know, because .eh_frame is slightly
+ different (and extended) from .debug_frame.
+
+ On amd64-linux, unwind info is in .eh_frame. If we're using it for
+ x86-linux, then it's also in .eh_frame.
+
+ On arm-linux, unwind info is in .debug_frame.
+*/
+
/* Sources of info:
The DWARF3 spec, available from http://www.dwarfstd.org/Download.php
@@ -1783,7 +1800,7 @@
# define SP_REG 1
# define RA_REG_DEFAULT 8 // CAB: What's a good default ?
#elif defined(VGP_arm_linux)
-# define FP_REG 11
+# define FP_REG 12
# define SP_REG 13
# define RA_REG_DEFAULT 14 //???
#elif defined(VGP_x86_darwin)
@@ -2006,10 +2023,18 @@
ctx->state[j].cfa_off = 0;
ctx->state[j].cfa_expr_ix = 0; */
for (i = 0; i < N_CFI_REGS; i++) {
- if (RR_Undef != 0)
- ctx->state[j].reg[i].tag = RR_Undef;
+ ctx->state[j].reg[i].tag = RR_Undef;
/* ctx->state[j].reg[i].arg = 0; */
}
+// all callee-saved registers (or at least the ones we are summarising for)
+// should start out as RR_Same, on arm
+ctx->state[j].reg[11].tag = RR_Same;
+
+//ctx->state[j].reg[13].tag = RR_Same;
+
+ctx->state[j].reg[14].tag = RR_Same;
+ ctx->state[j].reg[12].tag = RR_Same; // this can't be right though.
+ // R12 (IP) isn't callee saved.
}
}
@@ -2019,8 +2044,8 @@
typedef
struct {
UChar encoding;
- UChar* ehframe_image;
- Addr ehframe_avma;
+ UChar* xxframe_image;
+ Addr xxframe_avma;
Addr text_bias;
}
AddressDecodingInfo;
@@ -2034,12 +2059,16 @@
si->len = 0;
si->cfa_how = 0;
si->ra_how = 0;
- si->sp_how = 0;
- si->fp_how = 0;
+ si->r14_how = 0;
+ si->r13_how = 0;
+ si->r12_how = 0;
+ si->r11_how = 0;
si->cfa_off = 0;
si->ra_off = 0;
- si->sp_off = 0;
- si->fp_off = 0;
+ si->r14_off = 0;
+ si->r13_off = 0;
+ si->r12_off = 0;
+ si->r11_off = 0;
}
@@ -2094,12 +2123,16 @@
ML_(ppCfiExpr)(dst, conv);
} else
if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
- si->cfa_how = CFIC_SPREL;
+ si->cfa_how = CFIC_R13REL;
si->cfa_off = ctxs->cfa_off;
} else
if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
- si->cfa_how = CFIC_FPREL;
+ si->cfa_how = CFIC_R12REL;
si->cfa_off = ctxs->cfa_off;
+ } else
+ if (ctxs->cfa_is_regoff && ctxs->cfa_reg == 11/*??_REG*/) {
+ si->cfa_how = CFIC_R11REL;
+ si->cfa_off = ctxs->cfa_off;
} else {
why = 1;
goto failed;
@@ -2142,26 +2175,51 @@
why = 2; goto failed; /* otherwise give up */ \
}
- SUMMARISE_HOW(si->ra_how, si->ra_off,
- ctxs->reg[ctx->ra_reg] );
- SUMMARISE_HOW(si->fp_how, si->fp_off,
- ctxs->reg[FP_REG] );
+ SUMMARISE_HOW(si->r14_how, si->r14_off,
+ ctxs->reg[14] );
+ //SUMMARISE_HOW(si->r13_how, si->r13_off,
+ // ctxs->reg[13] );
+
+ SUMMARISE_HOW(si->r12_how, si->r12_off,
+ ctxs->reg[FP_REG] );
+
+ SUMMARISE_HOW(si->r11_how, si->r11_off,
+ ctxs->reg[11/*FP_REG*/] );
+
+ if (ctxs->reg[14/*LR*/].tag == RR_Same
+ && ctx->ra_reg == 14/*as we expect it always to be*/) {
+ /* Generate a trivial CfiExpr, which merely says "r14". First
+ ensure this DebugInfo has a cfsi_expr array in which to park
+ it. */
+ if (!debuginfo->cfsi_exprs)
+ debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
+ "di.ccCt.2a",
+ ML_(dinfo_free),
+ sizeof(CfiExpr) );
+ si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs, Creg_R14);
+ si->ra_how = CFIR_EXPR;
+ } else {
+ /* Just summarise it in the normal way */
+ SUMMARISE_HOW(si->ra_how, si->ra_off,
+ ctxs->reg[ctx->ra_reg] );
+ }
+
# undef SUMMARISE_HOW
/* on x86/amd64, it seems the old %{e,r}sp value before the call is
always the same as the CFA. Therefore ... */
- si->sp_how = CFIR_CFAREL;
- si->sp_off = 0;
+ si->r13_how = CFIR_CFAREL;
+ si->r13_off = 0;
/* also, gcc says "Undef" for %{e,r}bp when it is unchanged. So
.. */
- if (ctxs->reg[FP_REG].tag == RR_Undef)
- si->fp_how = CFIR_SAME;
+ //if (ctxs->reg[FP_REG].tag == RR_Undef)
+ // si->r12_how = CFIR_SAME;
/* knock out some obviously stupid cases */
- if (si->ra_how == CFIR_SAME)
- { why = 3; goto failed; }
+ //if (si->ra_how == CFIR_SAME)
+ // { why = 3; goto failed; }
/* bogus looking range? Note, we require that the difference is
representable in 32 bits. */
@@ -2228,11 +2286,11 @@
/* This is the only place where the conversion can fail. */
dwreg = src->Cex.DwReg.reg;
if (dwreg == SP_REG)
- return ML_(CfiExpr_CfiReg)( dstxa, Creg_SP );
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_R13 );
if (dwreg == FP_REG)
- return ML_(CfiExpr_CfiReg)( dstxa, Creg_FP );
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_R12 );
if (dwreg == srcuc->ra_reg)
- return ML_(CfiExpr_CfiReg)( dstxa, Creg_IP ); /* correct? */
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_R15 ); /* correct? */
/* else we must fail - can't represent the reg */
return -1;
default:
@@ -2422,8 +2480,8 @@
Addr base;
Word offset;
UChar encoding = adi->encoding;
- UChar* ehframe_image = adi->ehframe_image;
- Addr ehframe_avma = adi->ehframe_avma;
+ UChar* xxframe_image = adi->xxframe_image;
+ Addr xxframe_avma = adi->xxframe_avma;
vg_assert((encoding & DW_EH_PE_indirect) == 0);
@@ -2434,7 +2492,7 @@
base = adi->text_bias;
break;
case DW_EH_PE_pcrel:
- base = ehframe_avma + ( data - ehframe_image );
+ base = xxframe_avma + ( data - xxframe_image );
break;
case DW_EH_PE_datarel:
vg_assert(0);
@@ -2449,7 +2507,7 @@
break;
case DW_EH_PE_aligned:
base = 0;
- offset = data - ehframe_image;
+ offset = data - xxframe_image;
if ((offset % sizeof(Addr)) != 0) {
*nbytes = sizeof(Addr) - (offset % sizeof(Addr));
data += *nbytes;
@@ -3450,23 +3508,57 @@
void ML_(read_callframe_info_dwarf3)
- ( /*OUT*/struct _DebugInfo* di, UChar* ehframe_image )
+ ( /*OUT*/struct _DebugInfo* di,
+ HChar* xxframe_name,
+ UChar* xxframe_image, SizeT xxframe_size, Addr xxframe_avma )
{
Int nbytes;
HChar* how = NULL;
Int n_CIEs = 0;
- UChar* data = ehframe_image;
-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
- /* These targets don't use CFI-based stack unwinding. */
- return;
+ /* Read Dwarf3 CFI unwind data from the section described by
+ xxframe_{image,size,avma}. In practice that means either
+ .eh_frame or .debug_frame. It appears that .eh_frame is
+ sometimes mapped, but .debug_frame never is. Hence for
+ .eh_frame, xxframe_avma can be nonzero, but for .debug_frame it
+ must be zero.
+
+ A consequence of this is that, inside this CFI reader, we must
+ not longer refer directly to any di->ehframe_ or di->debugframe_
+ fields in the reader, after this point. */
+
+ /* On amd64-linux and x86-linux, we read .eh_frame and ignore
+ .debug_frame. On arm-linux, we read .debug_frame and read
+ .eh_frame. We could loosen these restrictions so as to allow
+ reading from both sections, if required. For the time being,
+ though, just use one or the other. FIXME: is this correct for
+ Darwin too? */
+# if defined(VGP_amd64_linux) || defined(VGP_x86_linux) \
+ || defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
+ if (0 != VG_(strcmp)(xxframe_name, ".eh_frame"))
+ return; /* skip anything except .eh_frame */
+
+# elif defined(VGP_arm_linux)
+ if (0 != VG_(strcmp)(xxframe_name, ".debug_frame"))
+ return; /* skip anything except .debug_frame */
+ vg_assert(xxframe_avma == 0);
+
+# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+ return; /* these don't use CFI-based stack unwinding */
+
+# else
+ /* new platform; need to make a decision about it. */
+# error "Unsupported platform"
# endif
+ /* Right. Finally, we're all set up to read the CFI described by
+ xxframe_{image,size,avma}. */
+ UChar* data = xxframe_image;
+
if (di->trace_cfi) {
VG_(printf)("\n-----------------------------------------------\n");
VG_(printf)("CFI info: szB %ld, _avma %#lx, _image %p\n",
- di->ehframe_size, di->ehframe_avma,
- ehframe_image );
+ xxframe_size, xxframe_avma, xxframe_image );
VG_(printf)("CFI info: name %s\n",
di->filename );
}
@@ -3499,12 +3591,12 @@
Bool dw64;
/* Are we done? */
- if (data == ehframe_image + di->ehframe_size)
+ if (data == xxframe_image + xxframe_size)
return;
/* Overshot the end? Means something is wrong */
- if (data > ehframe_image + di->ehframe_size) {
- how = "overran the end of .eh_frame";
+ if (data > xxframe_image + xxframe_size) {
+ how = "overran the end of .eh_frame or .debug_frame";
goto bad;
}
@@ -3513,9 +3605,9 @@
ciefde_start = data;
if (di->trace_cfi)
- VG_(printf)("\ncie/fde.start = %p (ehframe_image + 0x%lx)\n",
+ VG_(printf)("\ncie/fde.start = %p (xxframe_image + 0x%lx)\n",
ciefde_start,
- ciefde_start - ehframe_image + 0UL);
+ ciefde_start - xxframe_image + 0UL);
ciefde_len = (ULong) read_UInt(data); data += sizeof(UInt);
if (di->trace_cfi)
@@ -3528,7 +3620,7 @@
if (ciefde_len == 0) {
if (di->ddump_frames)
VG_(printf)("%08lx ZERO terminator\n\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image));
+ ((Addr)ciefde_start) - ((Addr)xxframe_image));
return;
}
@@ -3555,7 +3647,8 @@
VG_(printf)("cie.pointer = %lld\n", cie_pointer);
/* If cie_pointer is zero, we've got a CIE; else it's an FDE. */
- if (cie_pointer == 0) {
+ if (//cie_pointer == 0 || // XXX eh_frame
+ cie_pointer == 0xFFFFFFFFULL) { //XXX debug_frame
Int this_CIE;
UChar cie_version;
@@ -3577,13 +3670,14 @@
n_CIEs++;
init_CIE( &the_CIEs[this_CIE] );
- /* Record its offset. This is how we will find it again
- later when looking at an FDE. */
- the_CIEs[this_CIE].offset = (ULong)(ciefde_start - ehframe_image);
+ /* Record its offset relative to the start of the image.
+ This is how we will find it again later when looking at an
+ FDE. */
+ the_CIEs[this_CIE].offset = (ULong)(ciefde_start - xxframe_image);
if (di->ddump_frames)
VG_(printf)("%08lx %08lx %08lx CIE\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image),
+ ((Addr)ciefde_start) - ((Addr)xxframe_image),
(Addr)ciefde_len,
(Addr)(UWord)cie_pointer );
@@ -3706,7 +3800,7 @@
}
if (the_CIEs[this_CIE].ilen < 0
- || the_CIEs[this_CIE].ilen > di->ehframe_size) {
+ || the_CIEs[this_CIE].ilen > xxframe_size) {
how = "implausible # cie initial insns";
goto bad;
}
@@ -3721,8 +3815,8 @@
if (di->trace_cfi || di->ddump_frames) {
AddressDecodingInfo adi;
adi.encoding = the_CIEs[this_CIE].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.xxframe_image = xxframe_image;
+ adi.xxframe_avma = xxframe_avma;
adi.text_bias = di->text_debug_bias;
show_CF_instructions( the_CIEs[this_CIE].instrs,
the_CIEs[this_CIE].ilen, &adi,
@@ -3750,10 +3844,13 @@
/* Find the relevant CIE. The CIE we want is located
cie_pointer bytes back from here. */
+ // XXX eh_frame
/* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
- look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt))
- - ehframe_image)
- - cie_pointer;
+ // look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt))
+ // - xxframe_image)
+ // - cie_pointer;
+ // XXX debug_frame
+ look_for = cie_pointer;
for (cie = 0; cie < n_CIEs; cie++) {
if (0) VG_(printf)("look for %lld %lld\n",
@@ -3768,8 +3865,8 @@
}
adi.encoding = the_CIEs[cie].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.xxframe_image = xxframe_image;
+ adi.xxframe_avma = xxframe_avma;
adi.text_bias = di->text_debug_bias;
fde_initloc = read_encoded_Addr(&nbytes, &adi, data);
data += nbytes;
@@ -3777,8 +3874,8 @@
VG_(printf)("fde.initloc = %#lx\n", fde_initloc);
adi.encoding = the_CIEs[cie].address_encoding & 0xf;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.xxframe_image = xxframe_image;
+ adi.xxframe_avma = xxframe_avma;
adi.text_bias = di->text_debug_bias;
/* WAS (incorrectly):
@@ -3804,7 +3901,7 @@
if (di->ddump_frames)
VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image),
+ ((Addr)ciefde_start) - ((Addr)xxframe_image),
(Addr)ciefde_len,
(Addr)(UWord)cie_pointer,
(Addr)look_for,
@@ -3831,7 +3928,7 @@
VG_(printf)("fde.ilen = %d\n", (Int)fde_ilen);
}
- if (fde_ilen < 0 || fde_ilen > di->ehframe_size) {
+ if (fde_ilen < 0 || fde_ilen > xxframe_size) {
how = "implausible # fde insns";
goto bad;
}
@@ -3839,8 +3936,8 @@
data += fde_ilen;
adi.encoding = the_CIEs[cie].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.xxframe_image = xxframe_image;
+ adi.xxframe_avma = xxframe_avma;
adi.text_bias = di->text_debug_bias;
if (di->trace_cfi)
Modified: branches/ARM/coregrind/m_debuginfo/readelf.c
===================================================================
--- branches/ARM/coregrind/m_debuginfo/readelf.c 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_debuginfo/readelf.c 2009-11-13 17:21:04 UTC (rev 10940)
@@ -1657,7 +1657,7 @@
}
}
-# undef BAD
+# undef BAD
}
@@ -2002,11 +2002,21 @@
False, opd_img);
}
- /* Read .eh_frame (call-frame-info) if any */
+ /* Read call-frame-info in .eh_frame and/or .debug_frame,
+ if any */
if (ehframe_img) {
vg_assert(ehframe_sz == di->ehframe_size);
- ML_(read_callframe_info_dwarf3)( di, ehframe_img );
+ ML_(read_callframe_info_dwarf3)(
+ di, ".eh_frame",
+ ehframe_img, ehframe_sz, di->ehframe_avma
+ );
}
+ if (debug_frame_img) {
+ ML_(read_callframe_info_dwarf3)(
+ di, ".debug_frame",
+ debug_frame_img, debug_frame_sz, 0/*AVMA*/
+ );
+ }
/* Read the stabs and/or dwarf2 debug information, if any. It
appears reading stabs stuff on amd64-linux doesn't work, so
Modified: branches/ARM/coregrind/m_debuginfo/storage.c
===================================================================
--- branches/ARM/coregrind/m_debuginfo/storage.c 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_debuginfo/storage.c 2009-11-13 17:21:04 UTC (rev 10940)
@@ -126,12 +126,15 @@
VG_(printf)("[%#lx .. %#lx]: ", si->base,
si->base + (UWord)si->len - 1);
switch (si->cfa_how) {
- case CFIC_SPREL:
- VG_(printf)("let cfa=oldSP+%d", si->cfa_off);
+ case CFIC_R13REL:
+ VG_(printf)("let cfa=oldR13+%d", si->cfa_off);
break;
- case CFIC_FPREL:
- VG_(printf)("let cfa=oldFP+%d", si->cfa_off);
+ case CFIC_R12REL:
+ VG_(printf)("let cfa=oldR12+%d", si->cfa_off);
break;
+ case CFIC_R11REL:
+ VG_(printf)("let cfa=oldR11+%d", si->cfa_off);
+ break;
case CFIC_EXPR:
VG_(printf)("let cfa={");
ML_(ppCfiExpr)(exprs, si->cfa_off);
@@ -143,10 +146,14 @@
VG_(printf)(" in RA=");
SHOW_HOW(si->ra_how, si->ra_off);
- VG_(printf)(" SP=");
- SHOW_HOW(si->sp_how, si->sp_off);
- VG_(printf)(" FP=");
- SHOW_HOW(si->fp_how, si->fp_off);
+ VG_(printf)(" R14=");
+ SHOW_HOW(si->r14_how, si->r14_off);
+ VG_(printf)(" R13=");
+ SHOW_HOW(si->r13_how, si->r13_off);
+ VG_(printf)(" R12=");
+ SHOW_HOW(si->r12_how, si->r12_off);
+ VG_(printf)(" R11=");
+ SHOW_HOW(si->r11_how, si->r11_off);
VG_(printf)("\n");
# undef SHOW_HOW
}
@@ -574,9 +581,10 @@
static void ppCfiReg ( CfiReg reg )
{
switch (reg) {
- case Creg_SP: VG_(printf)("SP"); break;
- case Creg_FP: VG_(printf)("FP"); break;
- case Creg_IP: VG_(printf)("IP"); break;
+ case Creg_R13: VG_(printf)("R13"); break;
+ case Creg_R12: VG_(printf)("R12"); break;
+ case Creg_R15: VG_(printf)("R15"); break;
+ case Creg_R14: VG_(printf)("R14"); break;
default: vg_assert(0);
}
}
Modified: branches/ARM/coregrind/m_libcassert.c
===================================================================
--- branches/ARM/coregrind/m_libcassert.c 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_libcassert.c 2009-11-13 17:21:04 UTC (rev 10940)
@@ -45,59 +45,94 @@
Assertery.
------------------------------------------------------------------ */
-#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
-# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
- asm("call 0f;" \
- "0: popl %0;" \
- "movl %%esp, %1;" \
- "movl %%ebp, %2;" \
- : "=r" (pc),\
- "=r" (sp),\
- "=r" (fp));
-#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
-# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
- asm("leaq 0(%%rip), %0;" \
- "movq %%rsp, %1;" \
- "movq %%rbp, %2;" \
- : "=r" (pc),\
- "=r" (sp),\
- "=r" (fp));
+#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
+# define GET_STARTREGS(srP) \
+ { UInt eip, esp, ebp; \
+ __asm__ __volatile__( \
+ "call 0f;" \
+ "0: popl %0;" \
+ "movl %%esp, %1;" \
+ "movl %%ebp, %2;" \
+ : "=r" (eip), "=r" (esp), "=r" (ebp) \
+ : /* reads none */ \
+ : "memory" \
+ ); \
+ srP->r_pc = (ULong)eip; \
+ srP->r_sp = (ULong)esp; \
+ srP->misc.X86.r_ebp = ebp; \
+ }
+#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
+# define GET_STARTREGS(srP) \
+ { ULong rip, rsp, rbp; \
+ __asm__ __volatile__( \
+ "leaq 0(%%rip), %0;" \
+ "movq %%rsp, %1;" \
+ "movq %%rbp, %2;" \
+ : "=r" (rip), "=r" (rsp), "=r" (rbp) \
+ : /* reads none */ \
+ : "memory" \
+ ); \
+ srP->r_pc = rip; \
+ srP->r_sp = rsp; \
+ srP->misc.AMD64.r_rbp = rbp; \
+ }
#elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5)
-# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
- asm("mflr 0;" /* r0 = lr */ \
- "bl m_libcassert_get_ip;" /* lr = pc */ \
- "m_libcassert_get_ip:\n" \
- "mflr %0;" \
- "mtlr 0;" /* restore lr */ \
- "mr %1,1;" \
- "mr %2,1;" \
- : "=r" (pc), \
- "=r" (sp), \
- "=r" (fp) \
- : /* reads none */ \
- : "r0" /* trashed */ );
+# define GET_STARTREGS(srP) \
+ { UInt cia, r1, lr; \
+ __asm__ __volatile__( \
+ "mflr 0;" /* r0 = lr */ \
+ "bl m_libcassert_get_ip;" /* lr = pc */ \
+ "m_libcassert_get_ip:\n" \
+ "mflr %0;" /* %0 = pc */ \
+ "mtlr 0;" /* restore lr */ \
+ "mr %1,1;" /* %1 = r1 */ \
+ "mr %2,0;" /* %2 = lr */ \
+ : "=r" (cia), "=r" (r1), "=r" (lr) \
+ : /* reads none */ \
+ : "r0" /* trashed */ \
+ ); \
+ srP->r_pc = (ULong)cia; \
+ srP->r_sp = (ULong)r1; \
+ srP->misc.PPC32.lr = lr; \
+ }
#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
-# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
- asm("mflr 0;" /* r0 = lr */ \
- "bl .m_libcassert_get_ip;" /* lr = pc */ \
- ".m_libcassert_get_ip:\n" \
- "mflr %0;" \
- "mtlr 0;" /* restore lr */ \
- "mr %1,1;" \
- "mr %2,1;" \
- : "=r" (pc), \
- "=r" (sp), \
- "=r" (fp) \
- : /* reads none */ \
- : "r0" /* trashed */ );
+# define GET_STARTREGS(srP) \
+ { ULong cia, r1, lr; \
+ __asm__ __volatile__( \
+ "mflr 0;" /* r0 = lr */ \
+ "bl .m_libcassert_get_ip;" /* lr = pc */ \
+ ".m_libcassert_get_ip:\n" \
+ "mflr %0;" /* %0 = pc */ \
+ "mtlr 0;" /* restore lr */ \
+ "mr %1,1;" /* %1 = r1 */ \
+ "mr %2,0;" /* %2 = lr */ \
+ : "=r" (cia), "=r" (r1), "=r" (lr) \
+ : /* reads none */ \
+ : "r0" /* trashed */ \
+ ); \
+ srP->r_pc = cia; \
+ srP->r_sp = r1; \
+ srP->misc.PPC64.lr = lr; \
+ }
#elif defined(VGP_arm_linux)
-# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
- asm("mov %0, pc;" \
- "mov %1, sp;" \
- "mov %2, fp;" \
- : "=r" (pc), \
- "=r" (sp), \
- "=r" (fp));
+# define GET_STARTREGS(srP) \
+ { UInt block[5]; \
+ __asm__ __volatile__( \
+ "str r15, [%0, #+0];" \
+ "str r14, [%0, #+4];" \
+ "str r13, [%0, #+8];" \
+ "str r12, [%0, #+12];" \
+ "str r11, [%0, #+16];" \
+ : /* out */ \
+ : /* in */ "r"(&block[0]) \
+ : /* trash */ "memory" \
+ ); \
+ (srP)->r_pc = block[0] - 8; \
+ (srP)->r_sp = block[1]; \
+ (srP)->misc.ARM.r14 = block[2]; \
+ (srP)->misc.ARM.r12 = block[3]; \
+ (srP)->misc.ARM.r11 = block[4]; \
+ }
#else
# error Unknown platform
#endif
@@ -137,8 +172,8 @@
}
__attribute__ ((noreturn))
-static void report_and_quit ( const Char* report,
- Addr ip, Addr sp, Addr fp, Addr lr )
+static void report_and_quit ( const Char* report,
+ UnwindStartRegs* startRegsIN )
{
Addr stacktop;
Addr ips[BACKTRACE_DEPTH];
@@ -149,8 +184,13 @@
// If necessary, fake up an ExeContext which is of our actual real CPU
// state. Could cause problems if we got the panic/exception within the
// execontext/stack dump/symtab code. But it's better than nothing.
- if (0 == ip && 0 == sp && 0 == fp) {
- GET_REAL_PC_SP_AND_FP(ip, sp, fp);
+ UnwindStartRegs startRegs;
+ VG_(memset)(&startRegs, 0, sizeof(startRegs));
+
+ if (startRegsIN == NULL) {
+ GET_STARTREGS(&startRegs);
+ } else {
+ startRegs = *startRegsIN;
}
stacktop = tst->os_state.valgrind_stack_init_SP;
@@ -161,7 +201,7 @@
ips, BACKTRACE_DEPTH,
NULL/*array to dump SP values in*/,
NULL/*array to dump FP values in*/,
- ip, sp, fp, lr, sp, stacktop
+ &startRegs, stacktop
);
VG_(clo_xml) = False;
VG_(pp_StackTrace) (ips, n_ips);
@@ -222,32 +262,32 @@
if (!VG_STREQ(buf, ""))
VG_(printf)("%s: %s\n", component, buf );
- report_and_quit(bugs_to, 0,0,0,0);
+ report_and_quit(bugs_to, NULL);
}
__attribute__ ((noreturn))
static void panic ( Char* name, Char* report, Char* str,
- Addr ip, Addr sp, Addr fp, Addr lr )
+ UnwindStartRegs* startRegs )
{
if (VG_(clo_xml))
VG_(printf_xml)("</valgrindoutput>\n");
VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
- report_and_quit(report, ip, sp, fp, lr);
+ report_and_quit(report, startRegs);
}
-void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp, Addr lr )
+void VG_(core_panic_at) ( Char* str, UnwindStartRegs* startRegs )
{
- panic("valgrind", VG_BUGS_TO, str, ip, sp, fp, lr);
+ panic("valgrind", VG_BUGS_TO, str, startRegs);
}
void VG_(core_panic) ( Char* str )
{
- VG_(core_panic_at)(str, 0,0,0,0);
+ VG_(core_panic_at)(str, NULL);
}
void VG_(tool_panic) ( Char* str )
{
- panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0,0);
+ panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
}
/* Print some helpful-ish text about unimplemented things, and give up. */
Modified: branches/ARM/coregrind/m_machine.c
===================================================================
--- branches/ARM/coregrind/m_machine.c 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_machine.c 2009-11-13 17:21:04 UTC (rev 10940)
@@ -81,6 +81,45 @@
INSTR_PTR( VG_(threads)[tid].arch ) = ip;
}
+
+void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
+ ThreadId tid )
+{
+# if defined(VGA_x86)
+ regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_EIP;
+ regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_ESP;
+ regs->misc.X86.r_ebp
+ = VG_(threads)[tid].arch.vex.guest_EBP;
+# elif defined(VGA_amd64)
+ regs->r_pc = VG_(threads)[tid].arch.vex.guest_RIP;
+ regs->r_pc = VG_(threads)[tid].arch.vex.guest_RSP;
+ regs->misc.AMD64.r_rbp
+ = VG_(threads)[tid].arch.vex.guest_RBP;
+# elif defined(VGA_ppc32)
+ regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_CIA;
+ regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_R1;
+ regs->misc.PPC32.r_lr
+ = VG_(threads)[tid].arch.vex.guest_LR;
+# elif defined(VGA_ppc64)
+ regs->r_pc = VG_(threads)[tid].arch.vex.guest_CIA;
+ regs->r_sp = VG_(threads)[tid].arch.vex.guest_R1;
+ regs->misc.PPC64.r_lr
+ = VG_(threads)[tid].arch.vex.guest_LR;
+# elif defined(VGA_arm)
+ regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_R15;
+ regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_R13;
+ regs->misc.ARM.r14
+ = VG_(threads)[tid].arch.vex.guest_R14;
+ regs->misc.ARM.r12
+ = VG_(threads)[tid].arch.vex.guest_R12;
+ regs->misc.ARM.r11
+ = VG_(threads)[tid].arch.vex.guest_R11;
+# else
+# error "Unknown arch"
+# endif
+}
+
+
void VG_(set_syscall_return_shadows) ( ThreadId tid,
/* shadow vals for the result */
UWord s1res, UWord s2res,
Modified: branches/ARM/coregrind/m_signals.c
===================================================================
--- branches/ARM/coregrind/m_signals.c 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_signals.c 2009-11-13 17:21:04 UTC (rev 10940)
@@ -360,11 +360,16 @@
#elif defined(VGP_arm_linux)
# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.arm_pc)
# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.arm_sp)
-# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.arm_fp)
# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
/* Convert the value in uc_mcontext.rax into a SysRes. */ \
VG_(mk_SysRes_arm_linux)( (uc)->uc_mcontext.arm_r0 )
-# define VG_UCONTEXT_LINK_REG(uc) ((uc)->uc_mcontext.arm_lr)
+# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \
+ { (srP)->r_pc = (uc)->uc_mcontext.arm_pc; \
+ (srP)->r_sp = (uc)->uc_mcontext.arm_sp; \
+ (srP)->misc.ARM.r14 = (uc)->uc_mcontext.arm_lr; \
+ (srP)->misc.ARM.r12 = (uc)->uc_mcontext.arm_ip; \
+ (srP)->misc.ARM.r11 = (uc)->uc_mcontext.arm_fp; \
+ }
#elif defined(VGP_ppc32_aix5)
@@ -2312,11 +2317,11 @@
// tid = VG_(master_tid);
vg_assert(tid != 0);
- VG_(core_panic_at)("Killed by fatal signal",
- VG_UCONTEXT_INSTR_PTR(uc),
- VG_UCONTEXT_STACK_PTR(uc),
- VG_UCONTEXT_FRAME_PTR(uc),
- VG_UCONTEXT_LINK_REG(uc));
+ UnwindStartRegs startRegs;
+ VG_(memset)(&startRegs, 0, sizeof(startRegs));
+
+ VG_UCONTEXT_TO_UnwindStartRegs(&startRegs, uc);
+ VG_(core_panic_at)("Killed by fatal signal", &startRegs);
}
}
Modified: branches/ARM/coregrind/m_stacktrace.c
===================================================================
--- branches/ARM/coregrind/m_stacktrace.c 2009-11-12 13:28:34 UTC (rev 10939)
+++ branches/ARM/coregrind/m_stacktrace.c 2009-11-13 17:21:04 UTC (rev 10940)
@@ -44,8 +44,11 @@
#include "pub_core_clientstate.h" // VG_(client__dl_sysinfo_int80)
#include "pub_core_trampoline.h"
+
/*------------------------------------------------------------*/
-/*--- Exported functions. ---*/
+/*--- ---*/
+/*--- BEGIN platform-dependent unwinder worker functions ---*/
+/*--- ---*/
/*------------------------------------------------------------*/
/* Take a snapshot of the client's stack, putting up to 'max_n_ips'
@@ -57,23 +60,17 @@
first parameter, else send zero. This helps generate better stack
traces on ppc64-linux and has no effect on other platforms.
*/
+
+/* ------------------------ x86 ------------------------- */
+
+#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
+
UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
/*OUT*/Addr* ips, UInt max_n_ips,
/*OUT*/Addr* sps, /*OUT*/Addr* fps,
Addr ip, Addr sp, Addr fp, Addr lr,
Addr fp_min, Addr fp_max_orig )
{
-# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
- || defined(VGP_ppc32_aix5) \
- || defined(VGP_ppc64_aix5)
- Bool lr_is_first_RA = False;
-# endif
-# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5) \
- || defined(VGP_ppc32_aix5)
- Word redir_stack_size = 0;
- Word redirs_used = 0;
-# endif
-
Bool debug = False;
Int i;
Addr fp_max;
@@ -103,7 +100,7 @@
/* vg_assert(fp_min <= fp_max);*/
// On Darwin, this kicks in for pthread-related stack traces, so they're
// only 1 entry long which is wrong.
-#if !defined(VGO_darwin)
+# if !defined(VGO_darwin)
if (fp_min + 512 >= fp_max) {
/* If the stack limits look bogus, don't poke around ... but
don't bomb out either. */
@@ -112,17 +109,8 @@
ips[0] = ip;
return 1;
}
-#endif
+# endif
- /* Otherwise unwind the stack in a platform-specific way. Trying
- to merge the x86, amd64, ppc32 and ppc64 logic into a single
- piece of code is just too confusing and difficult to
- performance-tune. */
-
-# if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
-
- /*--------------------- x86 ---------------------*/
-
/* fp is %ebp. sp is %esp. ip is %eip. */
if (sps) sps[0] = sp;
@@ -213,10 +201,62 @@
break;
}
-# elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
+ n_found = i;
+ return n_found;
+}
- /*--------------------- amd64 ---------------------*/
+#endif
+/* ----------------------- amd64 ------------------------ */
+
+#if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
+
+UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
+ /*OUT*/Addr* ips, UInt max_n_ips,
+ /*OUT*/Addr* sps, /*OUT*/Addr* fps,
+ Addr ip, Addr sp, Addr fp, Addr lr,
+ Addr fp_min, Addr fp_max_orig )
+{
+ Bool debug = False;
+ Int i;
+ Addr fp_max;
+ UInt n_found = 0;
+
+ vg_assert(sizeof(Addr) == sizeof(UWord));
+ vg_assert(sizeof(Addr) == sizeof(void*));
+
+ /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
+ stopping when the trail goes cold, which we guess to be
+ when FP is not a reasonable stack location. */
+
+ // JRS 2002-sep-17: hack, to round up fp_max to the end of the
+ // current page, at least. Dunno if it helps.
+ // NJN 2002-sep-17: seems to -- stack traces look like 1.0.X again
+ fp_max = VG_PGROUNDUP(fp_max_orig);
+ if (fp_max >= sizeof(Addr))
+ fp_max -= sizeof(Addr);
+
+ if (debug)
+ VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
+ "fp_max=0x%lx ip=0x%lx fp=0x%lx\n",
+ max_n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
+
+ /* Assertion broken before main() is reached in pthreaded programs; the
+ * offending stack traces only have one item. --njn, 2002-aug-16 */
+ /* vg_assert(fp_min <= fp_max);*/
+ // On Darwin, this kicks in for pthread-related stack traces, so they're
+ // only 1 entry long which is wrong.
+# if !defined(VGO_darwin)
+ if (fp_min + 512 >= fp_max) {
+ /* If the stack limits look bogus, don't poke around ... but
+ don't bomb out either. */
+ if (sps) sps[0] = sp;
+ if (fps) fps[0] = fp;
+ ips[0] = ip;
+ return 1;
+ }
+# endif
+
/* fp is %rbp. sp is %rsp. ip is %rip. */
ips[0] = ip;
@@ -319,11 +359,65 @@
break;
}
-# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
- || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ n_found = i;
+ return n_found;
+}
- /*--------------------- ppc32/64 ---------------------*/
+#endif
+/* -----------------------ppc32/64 ---------------------- */
+
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
+ || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+
+UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
+ /*OUT*/Addr* ips, UInt max_n_ips,
+ /*OUT*/Addr* sps, /*OUT*/Addr* fps,
+ Addr ip, Addr sp, Addr fp, Addr lr,
+ Addr fp_min, Addr fp_max_orig )
+{
+ Bool lr_is_first_RA = False;
+# if defined(VG_PLAT_USES_PPCTOC)
+ Word redir_stack_size = 0;
+ Word redirs_used = 0;
+# endif
+
+ Bool debug = False;
+ Int i;
+ Addr fp_max;
+ UInt n_found = 0;
+
+ vg_assert(sizeof(Addr) == sizeof(UWord));
+ vg_assert(sizeof(Addr) == sizeof(void*));
+
+ /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
+ stopping when the trail goes cold, which we guess to be
+ when FP is not a reasonable stack location. */
+
+ // JRS 2002-sep-17: hack, to round up fp_max to the end of the
+ // current page, at least. Dunno if it helps.
+ // NJN 2002-sep-17: seems to -- stack traces look like 1.0.X again
+ fp_max = VG_PGROUNDUP(fp_max_orig);
+ if (fp_max >= sizeof(Addr))
+ fp_max -= sizeof(Addr);
+
+ if (debug)
+ VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
+ "fp_max=0x%lx ip=0x%lx fp=0x%lx\n",
+ max_n_ips, fp_min, fp_max_orig, fp_max, ip, fp);
+
+ /* Assertion broken before main() is reached in pthreaded programs; the
+ * offending stack traces only have one item. --njn, 2002-aug-16 */
+ /* vg_assert(fp_min <= fp_max);*/
+ if (fp_min + 512 >= fp_max) {
+ /* If the stack limits look bogus, don't poke around ... but
+ don't bomb out either. */
+ if (sps) sps[0] = sp;
+ if (fps) fps[0] = fp;
+ ips[0] = ip;
+ return 1;
+ }
+
/* fp is %r1. ip is %cia. Note, ppc uses r1 as both the stack and
frame pointers. */
@@ -386,8 +480,7 @@
/* On ppc64-linux (ppc64-elf, really), and on AIX, the lr save
slot is 2 words back from sp, whereas on ppc32-elf(?) it's
only one word back. */
-# if defined(VGP_ppc64_linux) \
- || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+# if defined(VG_PLAT_USES_PPCTOC)
const Int lr_offset = 2;
# else
const Int lr_offset = 1;
@@ -447,304 +540,124 @@
}
}
+ n_found = i;
+ return n_found;
+}
-# elif defined(VGP_arm_linux)
- if (sps) sps[0] = sp;
- if (fps) fps[0] = fp;
- ips[0] = ip;
- i = 1;
+#endif
+/* ------------------------ arm ------------------------- */
- while (True) {
- Addr prologue;
- Addr scanaddr;
- UInt *idx;
- Int sp_delta = 0; //Offset to old SP from SP, used to recover SP for most functions
+#if defined(VGP_arm_linux)
- //Set if we spot LR being pushed on the stack
- Bool tracking_lr = False;
- Int lr_sp_delta = 0; // <input sp - lr_sp_delta = lr>, only valid if tracking_lr is true
+UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
+ /*OUT*/Addr* ips, UInt max_n_ips,
+ /*OUT*/Addr* sps, /*OUT*/Addr* fps,
+ UnwindStartRegs* startRegs,
+ Addr fp_max_orig )
+{
+ Bool debug = False;
+ Int i;
+ Addr fp_max;
+ UInt n_found = 0;
- //Set if we spot FP being pushed on the stack.
- Bool tracking_fp = False;
- Int fp_sp_delta = 0; //
+ vg_assert(sizeof(Addr) == sizeof(UWord));
+ vg_assert(sizeof(Addr) == sizeof(void*));
- //We also save offsets from FP
- //We use this if we can, as variadic functions will fail with SP method.
- Int fp_lr_offset = 0; // Offset to LR from FP.
- Int fp_sp_offset = 0; // Offset to old SP from FP.
- Int fp_fp_offset = 0; // Offset to old FP from FP.
+ Addr r15 = startRegs->r_pc;
+ Addr r13 = startRegs->r_sp;
+ Addr r14 = startRegs->misc.ARM.r14;
+ Addr r12 = startRegs->misc.ARM.r12;
+ Addr r11 = startRegs->misc.ARM.r11;
+ Addr fp_min = r13;
- Bool fp_modified = False; //did anything in the prologue write to FP?
+ /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
+ stopping when the trail goes cold, which we guess to be
+ when FP is not a reasonable stack location. */
- /* This one is pretty dirty
- * It seems libc has a tendency of not using standard prologues at all, when it is about to execute a syscall.
- * In many cases following LR is enough, but we also need to know if the stack was modified.
- *
- * If we detect we are trying to generate a stacktrace from a syscall AND we didn't find any "standard" prologue,
- * try instead to search backwards from IP, to locate any operations that modify SP (and pick up LR,FP if we find them)
- *
- * Not being able to do stacktraces from syscalls decreases the usefulness of memcheck quite a bit, so we go to length to
- * hack around it. (gdb does not)
- *
- */
- Bool reverse = 0;
- Bool svc_hack = 0;
+ // JRS 2002-sep-17: hack, to round up fp_max to the end of the
+ // current page, at least. Dunno if it helps.
+ // NJN 2002-sep-17: seems to -- stack traces look like 1.0.X again
+ fp_max = VG_PGROUNDUP(fp_max_orig);
+ if (fp_max >= sizeof(Addr))
+ fp_max -= sizeof(Addr);
- if(debug) {
- VG_(printf)("i: %d, ip: 0x%x, sp: 0x%x, fp: 0x%x\n",i,(unsigned int)ip,(unsigned int)sp,(unsigned int)fp);
- }
+ if (debug)
+ VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
+ "fp_max=0x%lx r15=0x%lx r13=0x%lx\n",
+ max_n_ips, fp_min, fp_max_orig, fp_max, r15, r13);
- if (i >= max_n_ips)
- break;
+ /* Assertion broken before main() is reached in pthreaded programs; the
+ * offending stack traces only have one item. --njn, 2002-aug-16 */
+ /* vg_assert(fp_min <= fp_max);*/
+ // On Darwin, this kicks in for pthread-related stack traces, so they're
+ // only 1 entry long which is wrong.
+ if (fp_min + 512 >= fp_max) {
+ /* If the stack limits look bogus, don't poke around ... but
+ don't bomb out either. */
+ if (sps) sps[0] = r13;
+ if (fps) fps[0] = 0;
+ ips[0] = r15;
+ return 1;
+ }
- prologue = 0; //VG_(get_fnaddr)(ip);
- if(prologue != 0){
- scanaddr = prologue;
- /* Stack unwinding on ARM is EXTREMELY gnarley. We scan
- * through the function looking for stuff that affects the stack
- * pointer in order to figure out what the frame looks like. A lot of this
- * has been taken from GDB and then hacked up. We really only care about
- * the EABI calling convention here (feel free to support more ^_^) which is
- *
- * push {..., lr}
- * ...
- * sub sp, sp, #??
- *
- * for functions of fixed arity, and
- *
- * xxx
- * xxx
- * xxx
- *
- * for variadic functions. To make sure we don't slam into the next function,
- * we only scan the range between the beginning of the function and the point at
- * which we called the child, since in order to call the child, the prologue must
- * have executed to make sure the function can get back. If this is the lowest frame,
- * we do the same only between [the function's entry, the current pc)
- */
+ /* */
-//See comment above regarding retry, 'reverse' and svc_hack
- if(*(UInt*)(ip-4) == 0xEF000000) {
- svc_hack = True;
- }
-retry:
+ if (sps) sps[0] = r13;
+ if (fps) fps[0] = 0;
+ ips[0] = r15;
+ i = 1;
- for(idx=(UInt *)scanaddr; idx<(UInt *)ip ;(reverse ? idx-- : idx++)){
- UInt insn = *idx;
+ /* Loop unwinding the stack. */
- if(svc_hack && idx < (UInt*)prologue) {
- break;
- }
- if(0)
- VG_(printf)("Decoding 0x%x, insn: 0x%x\n",(UInt)idx,insn);
- if (insn == 0xe52de004 || (i == 1 && (insn & 0xe52d0004) == 0xe52d0004) ) /* str ??, [sp, #-4]! a.k.a. push {one register} */
- {
- if(tracking_lr) {
- lr_sp_delta+=4;
- }
- if(tracking_fp)
- fp_sp_delta+=4;
-
- if(insn == 0xe52de004) { /* str lr, [sp, #-4]! */
- tracking_lr = True;
- if(debug)
- VG_(printf)("Backtrace: str lr,[sp, #-4]!\n");
- }
- if(insn == 0xe52db004) { /* str fp, [sp, #-4]! */
- tracking_fp = True;
- if(de...
[truncated message content] |
|
From: <sv...@va...> - 2009-11-13 16:55:30
|
Author: sewardj
Date: 2009-11-13 16:55:17 +0000 (Fri, 13 Nov 2009)
New Revision: 1927
Log:
Ensure r11 is up to date at any potential unwind points; apparently
this is needed for correct stack unwinding.
Modified:
branches/ARM/priv/guest_arm_helpers.c
Modified: branches/ARM/priv/guest_arm_helpers.c
===================================================================
--- branches/ARM/priv/guest_arm_helpers.c 2009-11-05 18:22:34 UTC (rev 1926)
+++ branches/ARM/priv/guest_arm_helpers.c 2009-11-13 16:55:17 UTC (rev 1927)
@@ -524,6 +524,17 @@
return True;
}
+ /* We appear to need precise updates of R11 in order to get proper
+ stacktraces from non-optimised code. */
+ Int r11_min = offsetof(VexGuestARMState, guest_R11);
+ Int r11_max = r11_min + 4 - 1;
+
+ if (maxoff < r11_min || minoff > r11_max) {
+ /* no overlap with pc */
+ } else {
+ return True;
+ }
+
return False;
}
|
|
From: Tom H. <to...@co...> - 2009-11-13 11:50:01
|
On 13/11/09 11:43, Bart Van Assche wrote: > This patch looks like an improvement -- e.g. > memcheck/tests/varinfo2.stderr.diff and > memcheck/tests/varinfo4.stderr.diff became smaller thanks to this > patch. But as you can see in e.g. memcheck/tests/varinfo1.stderr.diff, > unfortunately the off-by-one line number problem in the call stacks > reported on PPC still exists. > > Was this the intended effect of this patch ? You know that's what expected - Jakub said as much on the bug and you replied saying that a fix for the off by one thing would be welcome. Tom -- Tom Hughes (to...@co...) http://www.compton.nu/ |
|
From: Bart V. A. <bar...@gm...> - 2009-11-13 11:43:55
|
On Thu, Nov 12, 2009 at 2:19 PM, <sv...@va...> wrote:
> Author: tom
> Date: 2009-11-12 13:19:41 +0000 (Thu, 12 Nov 2009)
> New Revision: 10938
>
> Log:
> Fix stack unwinding on PPC to store the correct frame pointer for
> frames other than the first one found.
>
> This is taken from Jakub Jelinek's second patch on bug #210479.
>
>
> Modified:
> trunk/coregrind/m_stacktrace.c
>
>
> Modified: trunk/coregrind/m_stacktrace.c
> ===================================================================
> --- trunk/coregrind/m_stacktrace.c 2009-11-11 19:22:05 UTC (rev 10937)
> +++ trunk/coregrind/m_stacktrace.c 2009-11-12 13:19:41 UTC (rev 10938)
> @@ -430,9 +430,9 @@
> # endif
>
> if (0 == ip || 1 == ip) break;
> - fp = (((UWord*)fp)[0]);
> if (sps) sps[i] = fp; /* NB. not sp */
> if (fps) fps[i] = fp;
> + fp = (((UWord*)fp)[0]);
> ips[i++] = ip - 1; /* -1: refer to calling insn, not the RA */
> if (debug)
> VG_(printf)(" ipsF[%d]=%#08lx\n", i-1, ips[i-1]);
>
Hello Tom,
This patch looks like an improvement -- e.g.
memcheck/tests/varinfo2.stderr.diff and
memcheck/tests/varinfo4.stderr.diff became smaller thanks to this
patch. But as you can see in e.g. memcheck/tests/varinfo1.stderr.diff,
unfortunately the off-by-one line number problem in the call stacks
reported on PPC still exists.
Was this the intended effect of this patch ?
Bart.
|
|
From: Bart V. A. <bar...@gm...> - 2009-11-13 08:31:28
|
Nightly build on cellbuzz-native ( cellbuzz, ppc64, Fedora 7, native ) Started at 2009-11-13 02:03:16 EST Ended at 2009-11-13 03:31:07 EST 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 == 449 tests, 45 stderr failures, 10 stdout failures, 0 post failures == memcheck/tests/deep_templates (stdout) memcheck/tests/leak-cases-full (stderr) memcheck/tests/leak-cases-summary (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/linux/timerfd-syscall (stdout) memcheck/tests/linux-syscalls-2007 (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/partiallydefinedeq (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/wrap8 (stdout) memcheck/tests/wrap8 (stderr) none/tests/empty-exe (stderr) none/tests/linux/mremap (stderr) 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) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (stderr) none/tests/shell_zerolength (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) drd/tests/tc23_bogus_condwait (stderr) exp-ptrcheck/tests/bad_percentify (stderr) exp-ptrcheck/tests/base (stderr) exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/fp (stderr) exp-ptrcheck/tests/globalerr (stderr) exp-ptrcheck/tests/hackedbz2 (stderr) exp-ptrcheck/tests/hp_bounds (stderr) exp-ptrcheck/tests/hp_dangle (stderr) exp-ptrcheck/tests/hsg (stderr) exp-ptrcheck/tests/justify (stderr) exp-ptrcheck/tests/partial_bad (stderr) exp-ptrcheck/tests/partial_good (stderr) exp-ptrcheck/tests/preen_invars (stderr) exp-ptrcheck/tests/pth_create (stderr) exp-ptrcheck/tests/pth_specific (stderr) exp-ptrcheck/tests/realloc (stderr) exp-ptrcheck/tests/stackerr (stderr) exp-ptrcheck/tests/strcpy (stderr) exp-ptrcheck/tests/supp (stderr) exp-ptrcheck/tests/tricky (stderr) exp-ptrcheck/tests/unaligned (stderr) exp-ptrcheck/tests/zero (stderr) |
|
From: Tom H. <th...@cy...> - 2009-11-13 03:51:05
|
Nightly build on vauxhall ( x86_64, Fedora 11 ) Started at 2009-11-13 03:20:07 GMT Ended at 2009-11-13 03:50:46 GMT 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 == 541 tests, 8 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/pth_spinlock (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc23_bogus_condwait (stderr) drd/tests/qt4_mutex (stderr) exp-ptrcheck/tests/bad_percentify (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 541 tests, 6 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc23_bogus_condwait (stderr) exp-ptrcheck/tests/bad_percentify (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Fri Nov 13 03:35:41 2009 --- new.short Fri Nov 13 03:50:46 2009 *************** *** 8,12 **** ! == 541 tests, 6 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/tc06_two_races_xml (stderr) --- 8,13 ---- ! == 541 tests, 8 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) + helgrind/tests/pth_spinlock (stderr) helgrind/tests/tc06_two_races_xml (stderr) *************** *** 14,15 **** --- 15,17 ---- helgrind/tests/tc23_bogus_condwait (stderr) + drd/tests/qt4_mutex (stderr) exp-ptrcheck/tests/bad_percentify (stderr) |
|
From: Tom H. <th...@cy...> - 2009-11-13 03:49:15
|
Nightly build on lloyd ( x86_64, Fedora 7 ) Started at 2009-11-13 03:05:05 GMT Ended at 2009-11-13 03:48:57 GMT 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 == 531 tests, 1 stderr failure, 0 stdout failures, 0 post failures == helgrind/tests/tc06_two_races_xml (stderr) |
|
From: Tom H. <th...@cy...> - 2009-11-13 03:36:06
|
Nightly build on mg ( x86_64, Fedora 9 ) Started at 2009-11-13 03:10:05 GMT Ended at 2009-11-13 03:35:50 GMT 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 == 538 tests, 1 stderr failure, 0 stdout failures, 0 post failures == helgrind/tests/tc06_two_races_xml (stderr) |
|
From: <sv...@va...> - 2009-11-12 13:28:46
|
Author: tom
Date: 2009-11-12 13:28:34 +0000 (Thu, 12 Nov 2009)
New Revision: 10939
Log:
Various improvements to DWARF handling to cope with changes in recent
versions of gcc as shipped with Fedora 12. Specific changes include:
- Vastly increase the number of opcodes we understand how to
evaluate when processing a location expression.
- Process frame unwind data from the debug_frame ELF section as
well as the eh_frame section.
- Handle version 3 CIEs in frame unwind data.
- Handle the compact form of DW_AT_data_member_location which just
gives a constant offset from the start of it's base type instead
of a full location expression.
Based on patches from Jakub Jelinek on bugs #210479 and #210566.
Modified:
trunk/coregrind/m_debuginfo/d3basics.c
trunk/coregrind/m_debuginfo/debuginfo.c
trunk/coregrind/m_debuginfo/priv_d3basics.h
trunk/coregrind/m_debuginfo/priv_readdwarf.h
trunk/coregrind/m_debuginfo/priv_storage.h
trunk/coregrind/m_debuginfo/priv_tytypes.h
trunk/coregrind/m_debuginfo/readdwarf.c
trunk/coregrind/m_debuginfo/readdwarf3.c
trunk/coregrind/m_debuginfo/readelf.c
trunk/coregrind/m_debuginfo/storage.c
trunk/coregrind/m_debuginfo/tytypes.c
Modified: trunk/coregrind/m_debuginfo/d3basics.c
===================================================================
--- trunk/coregrind/m_debuginfo/d3basics.c 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/d3basics.c 2009-11-12 13:28:34 UTC (rev 10939)
@@ -387,12 +387,8 @@
if (regno == 7/*RSP*/) { *a = regs->sp; return True; }
# elif defined(VGP_ppc32_linux)
if (regno == 1/*SP*/) { *a = regs->sp; return True; }
- if (regno == 31) return False;
- vg_assert(0);
# elif defined(VGP_ppc64_linux)
if (regno == 1/*SP*/) { *a = regs->sp; return True; }
- if (regno == 31) return False;
- vg_assert(0);
# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
vg_assert(0); /* this function should never be called */
# else
@@ -443,7 +439,7 @@
/* Evaluate a standard DWARF3 expression. See detailed description in
- priv_d3basics.h. */
+ priv_d3basics.h. Doesn't handle DW_OP_piece/DW_OP_bit_piece yet. */
GXResult ML_(evaluate_Dwarf3_Expr) ( UChar* expr, UWord exprszB,
GExpr* fbGX, RegSummary* regs,
const DebugInfo* di,
@@ -482,8 +478,8 @@
Addr stack[N_EXPR_STACK]; /* stack of addresses, as per D3 spec */
GXResult fbval, res;
Addr a1;
- Word sw1;
- UWord uw1;
+ Word sw1, sw2;
+ UWord uw1, uw2;
Bool ok;
sp = -1;
@@ -568,12 +564,15 @@
switch (fbval.kind) {
case GXR_Failure:
return fbval; /* propagate failure */
- case GXR_Value:
+ case GXR_Addr:
a1 = fbval.word; break; /* use as-is */
case GXR_RegNo:
ok = get_Dwarf_Reg( &a1, fbval.word, regs );
if (!ok) return fbval; /* propagate failure */
break;
+ case GXR_Value:
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_{implicit,stack}_value "
+ "in DW_AT_frame_base");
default:
vg_assert(0);
}
@@ -599,11 +598,23 @@
a1 += sw1;
PUSH( a1 );
break;
+ case DW_OP_bregx:
+ if (!regs)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_bregx but no reg info");
+ a1 = 0;
+ uw1 = (UWord)read_leb128U( &expr );
+ if (!get_Dwarf_Reg( &a1, uw1, regs ))
+ FAIL("evaluate_Dwarf3_Expr: unhandled DW_OP_bregx reg value");
+ sw1 = (Word)read_leb128S( &expr );
+ a1 += sw1;
+ PUSH( a1 );
+ break;
/* As per comment on DW_OP_breg*, the following denote that
the value in question is in a register, not in memory. So
we simply return failure. (iow, the expression is
malformed). */
case DW_OP_reg0 ... DW_OP_reg31:
+ case DW_OP_regx:
FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* "
"whilst evaluating for a value");
break;
@@ -637,6 +648,238 @@
"address not valid for client");
}
break;
+ case DW_OP_deref_size:
+ POP(uw1);
+ uw2 = *expr++;
+ if (VG_(am_is_valid_for_client)( (Addr)uw1, uw2,
+ VKI_PROT_READ )) {
+ switch (uw2) {
+ case 1: uw1 = *(UChar*)uw1; break;
+ case 2: uw1 = *(UShort*)uw1; break;
+ case 4: uw1 = *(UInt*)uw1; break;
+ case 8: uw1 = *(ULong*)uw1; break;
+ default:
+ FAIL("warning: evaluate_Dwarf3_Expr: unhandled "
+ "DW_OP_deref_size size");
+ }
+ PUSH(uw1);
+ } else {
+ FAIL("warning: evaluate_Dwarf3_Expr: DW_OP_deref_size: "
+ "address not valid for client");
+ }
+ break;
+ case DW_OP_lit0 ... DW_OP_lit31:
+ PUSH(opcode - DW_OP_lit0);
+ break;
+ case DW_OP_const1u:
+ uw1 = *expr++;
+ PUSH(uw1);
+ break;
+ case DW_OP_const2u:
+ uw1 = *(UShort *)expr;
+ expr += 2;
+ PUSH(uw1);
+ break;
+ case DW_OP_const4u:
+ uw1 = *(UInt *)expr;
+ expr += 4;
+ PUSH(uw1);
+ break;
+ case DW_OP_const8u:
+ uw1 = *(ULong *)expr;
+ expr += 8;
+ PUSH(uw1);
+ break;
+ case DW_OP_constu:
+ uw1 = read_leb128U( &expr );
+ PUSH(uw1);
+ break;
+ case DW_OP_const1s:
+ uw1 = *(Char *)expr;
+ expr++;
+ PUSH(uw1);
+ break;
+ case DW_OP_const2s:
+ uw1 = *(Short *)expr;
+ expr += 2;
+ PUSH(uw1);
+ break;
+ case DW_OP_const4s:
+ uw1 = *(Int *)expr;
+ expr += 4;
+ PUSH(uw1);
+ break;
+ case DW_OP_const8s:
+ uw1 = *(Long *)expr;
+ expr += 8;
+ PUSH(uw1);
+ break;
+ case DW_OP_consts:
+ uw1 = read_leb128S( &expr );
+ PUSH(uw1);
+ break;
+ case DW_OP_dup:
+ POP(uw1);
+ PUSH(uw1);
+ PUSH(uw1);
+ break;
+ case DW_OP_drop:
+ POP(uw1);
+ break;
+ case DW_OP_over:
+ uw1 = 1;
+ goto do_pick;
+ case DW_OP_pick:
+ uw1 = *expr++;
+ do_pick:
+ if (sp < (Int)uw1)
+ FAIL("evaluate_Dwarf3_Expr: stack underflow");
+ uw1 = stack[sp - uw1];
+ PUSH(uw1);
+ break;
+ case DW_OP_swap:
+ if (sp < 1)
+ FAIL("evaluate_Dwarf3_Expr: stack underflow");
+ uw1 = stack[sp];
+ stack[sp] = stack[sp - 1];
+ stack[sp - 1] = uw1;
+ break;
+ case DW_OP_rot:
+ if (sp < 2)
+ FAIL("evaluate_Dwarf3_Expr: stack underflow");
+ uw1 = stack[sp];
+ stack[sp] = stack[sp - 1];
+ stack[sp - 1] = stack[sp - 2];
+ stack[sp - 2] = uw1;
+ break;
+ case DW_OP_abs:
+ POP(sw1);
+ if (sw1 < 0)
+ sw1 = -sw1;
+ PUSH(sw1);
+ break;
+ case DW_OP_div:
+ POP(sw2);
+ if (sw2 == 0)
+ FAIL("evaluate_Dwarf3_Expr: division by zero");
+ POP(sw1);
+ sw1 /= sw2;
+ PUSH(sw1);
+ break;
+ case DW_OP_mod:
+ POP(sw2);
+ if (sw2 == 0)
+ FAIL("evaluate_Dwarf3_Expr: division by zero");
+ POP(sw1);
+ sw1 %= sw2;
+ PUSH(sw1);
+ break;
+#define BINARY(name, op, s) \
+ case DW_OP_##name: \
+ POP(s##w2); \
+ POP(s##w1); \
+ s##w1 = s##w1 op s##w2; \
+ PUSH(s##w1); \
+ break
+#define UNARY(name, op, s) \
+ case DW_OP_##name: \
+ POP(s##w1); \
+ s##w1 = op s##w1; \
+ PUSH(s##w1); \
+ break
+ BINARY (and, &, u);
+ BINARY (minus, -, u);
+ BINARY (mul, *, u);
+ UNARY (neg, -, u);
+ UNARY (not, ~, u);
+ BINARY (or, |, u);
+ BINARY (plus, +, u);
+ BINARY (shl, <<, u);
+ BINARY (shr, >>, u);
+ BINARY (shra, >>, s);
+ BINARY (xor, ^, u);
+ BINARY (le, <=, s);
+ BINARY (lt, <, s);
+ BINARY (ge, >=, s);
+ BINARY (gt, >, s);
+ BINARY (ne, !=, u);
+ BINARY (eq, ==, u);
+#undef UNARY
+#undef BINARY
+ case DW_OP_skip:
+ sw1 = *(Short *)expr;
+ expr += 2;
+ if (expr + sw1 < limit - exprszB)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_skip before start of expr");
+ if (expr + sw1 >= limit)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_skip after end of expr");
+ expr += sw1;
+ break;
+ case DW_OP_bra:
+ sw1 = *(Short *)expr;
+ expr += 2;
+ if (expr + sw1 < limit - exprszB)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_bra before start of expr");
+ if (expr + sw1 >= limit)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_bra after end of expr");
+ POP(uw1);
+ if (uw1)
+ expr += sw1;
+ break;
+ case DW_OP_nop:
+ break;
+ case DW_OP_call_frame_cfa:
+ if (!regs)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_call_frame_cfa but no reg info");
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+ /* Valgrind on ppc32/ppc64 currently doesn't use unwind info. */
+ uw1 = *(Addr *)(regs->sp);
+#else
+ uw1 = ML_(get_CFA)(regs->ip, regs->sp, regs->fp, 0, ~(UWord) 0);
+#endif
+ if (!uw1)
+ FAIL("evaluate_Dwarf3_Expr: Could not resolve "
+ "DW_OP_call_frame_cfa");
+ PUSH(uw1);
+ break;
+ case DW_OP_implicit_value:
+ sw1 = (Word)read_leb128S( &expr );
+ uw1 = 0;
+ switch (sw1) {
+ case 1:
+ uw1 = *(UChar *)expr;
+ expr += 1;
+ break;
+ case 2:
+ uw1 = *(UShort *)expr;
+ expr += 2;
+ break;
+ case 4:
+ uw1 = *(UInt *)expr;
+ expr += 4;
+ break;
+ case 8:
+ uw1 = *(ULong *)expr;
+ expr += 8;
+ break;
+ default:
+ FAIL("evaluate_Dwarf3_Expr: Unhandled "
+ "DW_OP_implicit_value size");
+ }
+ if (expr != limit)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_implicit_value "
+ "does not terminate expression");
+ res.word = uw1;
+ res.kind = GXR_Value;
+ return res;
+ case DW_OP_stack_value:
+ POP (uw1);
+ res.word = uw1;
+ res.kind = GXR_Value;
+ if (expr != limit)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_stack_value "
+ "does not terminate expression");
+ break;
default:
if (!VG_(clo_xml))
VG_(message)(Vg_DebugMsg,
@@ -650,7 +893,7 @@
vg_assert(sp >= 0 && sp < N_EXPR_STACK);
res.word = stack[sp];
- res.kind = GXR_Value;
+ res.kind = GXR_Addr;
return res;
# undef POP
@@ -829,12 +1072,15 @@
if (!badness)
badness = "trivial GExpr denotes register (2)";
}
- else {
+ else if (0) {
VG_(printf)(" ML_(evaluate_trivial_GX): unhandled:\n ");
ML_(pp_GX)( gx );
VG_(printf)("\n");
tl_assert(0);
}
+ else
+ if (!badness)
+ badness = "non-trivial GExpr";
VG_(addToXA)( results, &thisResult );
@@ -884,7 +1130,7 @@
/* Well, we have success. All subexpressions evaluated, and
they all agree. Hurrah. */
- res.kind = GXR_Value;
+ res.kind = GXR_Addr;
res.word = (UWord)mul->ul; /* NB: narrowing from ULong */
VG_(deleteXA)( results );
return res;
@@ -896,6 +1142,8 @@
switch (res.kind) {
case GXR_Failure:
VG_(printf)("GXR_Failure(%s)", (HChar*)res.word); break;
+ case GXR_Addr:
+ VG_(printf)("GXR_Addr(0x%lx)", res.word); break;
case GXR_Value:
VG_(printf)("GXR_Value(0x%lx)", res.word); break;
case GXR_RegNo:
Modified: trunk/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- trunk/coregrind/m_debuginfo/debuginfo.c 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/debuginfo.c 2009-11-12 13:28:34 UTC (rev 10939)
@@ -2003,75 +2003,51 @@
}
-/* The main function for DWARF2/3 CFI-based stack unwinding.
- Given an IP/SP/FP triple, produce the IP/SP/FP values for the
- previous frame, if possible. */
-/* Returns True if OK. If not OK, *{ip,sp,fp}P are not changed. */
-/* NOTE: this function may rearrange the order of entries in the
- DebugInfo list. */
-Bool VG_(use_CF_info) ( /*MOD*/Addr* ipP,
- /*MOD*/Addr* spP,
- /*MOD*/Addr* fpP,
- Addr min_accessible,
- Addr max_accessible )
+static CFSICacheEnt* cfsi_cache__find ( Addr ip )
{
- Bool ok;
- DebugInfo* di;
- DiCfSI* cfsi = NULL;
- Addr cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
+ UWord hash = ip % N_CFSI_CACHE;
+ CFSICacheEnt* ce = &cfsi_cache[hash];
+ static UWord n_q = 0, n_m = 0;
- CfiExprEvalContext eec;
-
- static UWord n_q = 0, n_m = 0;
n_q++;
if (0 && 0 == (n_q & 0x1FFFFF))
VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
- { UWord hash = (*ipP) % N_CFSI_CACHE;
- CFSICacheEnt* ce = &cfsi_cache[hash];
-
- if (LIKELY(ce->ip == *ipP) && LIKELY(ce->di != NULL)) {
- /* found an entry in the cache .. */
- } else {
- /* not found in cache. Search and update. */
- n_m++;
- ce->ip = *ipP;
- find_DiCfSI( &ce->di, &ce->ix, *ipP );
- }
-
- if (UNLIKELY(ce->di == (DebugInfo*)1)) {
- /* no DiCfSI for this address */
- cfsi = NULL;
- di = NULL;
- } else {
- /* found a DiCfSI for this address */
- di = ce->di;
- cfsi = &di->cfsi[ ce->ix ];
- }
+ if (LIKELY(ce->ip == ip) && LIKELY(ce->di != NULL)) {
+ /* found an entry in the cache .. */
+ } else {
+ /* not found in cache. Search and update. */
+ n_m++;
+ ce->ip = ip;
+ find_DiCfSI( &ce->di, &ce->ix, ip );
}
- if (UNLIKELY(cfsi == NULL))
- return False; /* no info. Nothing we can do. */
-
- if (0) {
- VG_(printf)("found cfisi: ");
- ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
+ if (UNLIKELY(ce->di == (DebugInfo*)1)) {
+ /* no DiCfSI for this address */
+ return NULL;
+ } else {
+ /* found a DiCfSI for this address */
+ return ce;
}
+}
- ipPrev = spPrev = fpPrev = 0;
- ipHere = *ipP;
- spHere = *spP;
- fpHere = *fpP;
+static Addr compute_cfa ( Addr ip, Addr sp, Addr fp,
+ Addr min_accessible, Addr max_accessible,
+ DebugInfo* di, DiCfSI* cfsi )
+{
+ CfiExprEvalContext eec;
+ Addr cfa;
+ Bool ok;
- /* First compute the CFA. */
+ /* Compute the CFA. */
cfa = 0;
switch (cfsi->cfa_how) {
case CFIC_SPREL:
- cfa = cfsi->cfa_off + spHere;
+ cfa = sp + cfsi->cfa_off;
break;
case CFIC_FPREL:
- cfa = cfsi->cfa_off + fpHere;
+ cfa = fp + cfsi->cfa_off;
break;
case CFIC_EXPR:
if (0) {
@@ -2079,19 +2055,86 @@
ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
VG_(printf)("\n");
}
- eec.ipHere = ipHere;
- eec.spHere = spHere;
- eec.fpHere = fpHere;
+ eec.ipHere = ip;
+ eec.spHere = sp;
+ eec.fpHere = fp;
eec.min_accessible = min_accessible;
eec.max_accessible = max_accessible;
ok = True;
cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
- if (!ok) return False;
+ if (!ok) return 0;
break;
default:
vg_assert(0);
}
+ return cfa;
+}
+
+/* Get the call frame address (CFA) given an IP/SP/FP triple. */
+Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
+ Addr min_accessible, Addr max_accessible )
+{
+ CFSICacheEnt* ce;
+ DebugInfo* di;
+ DiCfSI* cfsi;
+
+ ce = cfsi_cache__find(ip);
+
+ if (UNLIKELY(ce == NULL))
+ return 0; /* no info. Nothing we can do. */
+
+ di = ce->di;
+ cfsi = &di->cfsi[ ce->ix ];
+
+ return compute_cfa(ip, sp, fp, min_accessible, max_accessible, di, cfsi);
+}
+
+
+/* The main function for DWARF2/3 CFI-based stack unwinding.
+ Given an IP/SP/FP triple, produce the IP/SP/FP values for the
+ previous frame, if possible. */
+/* Returns True if OK. If not OK, *{ip,sp,fp}P are not changed. */
+/* NOTE: this function may rearrange the order of entries in the
+ DebugInfo list. */
+Bool VG_(use_CF_info) ( /*MOD*/Addr* ipP,
+ /*MOD*/Addr* spP,
+ /*MOD*/Addr* fpP,
+ Addr min_accessible,
+ Addr max_accessible )
+{
+ Bool ok;
+ DebugInfo* di;
+ DiCfSI* cfsi = NULL;
+ Addr cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
+ CFSICacheEnt* ce;
+ CfiExprEvalContext eec;
+
+ ce = cfsi_cache__find(*ipP);
+
+ if (UNLIKELY(ce == NULL))
+ return False; /* no info. Nothing we can do. */
+
+ di = ce->di;
+ cfsi = &di->cfsi[ ce->ix ];
+
+ if (0) {
+ VG_(printf)("found cfisi: ");
+ ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
+ }
+
+ ipPrev = spPrev = fpPrev = 0;
+
+ ipHere = *ipP;
+ spHere = *spP;
+ fpHere = *fpP;
+
+ /* First compute the CFA. */
+ cfa = compute_cfa(ipHere, spHere, fpHere,
+ min_accessible, max_accessible, di, cfsi);
+ if (UNLIKELY(cfa == 0))
+ return False;
+
/* Now we know the CFA, use it to roll back the registers we're
interested in. */
@@ -2346,7 +2389,7 @@
VG_(printf)("\n");
}
- if (res.kind == GXR_Value
+ if (res.kind == GXR_Addr
&& res.word <= data_addr
&& data_addr < res.word + var_szB) {
*offset = data_addr - res.word;
@@ -3057,7 +3100,7 @@
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) {
+ if (res_sp_6k.kind == GXR_Addr) {
StackBlock block;
GXResult res;
UWord sp_delta = res_sp_7k.word - res_sp_6k.word;
@@ -3074,7 +3117,7 @@
regs.sp = regs.fp = 0;
regs.ip = ip;
res = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, di );
- tl_assert(res.kind == GXR_Value);
+ tl_assert(res.kind == GXR_Addr);
if (debug)
VG_(printf)(" %5ld .. %5ld (sp) %s\n",
res.word, res.word + ((UWord)mul.ul) - 1, var->name);
@@ -3093,7 +3136,7 @@
regs.sp = regs.fp = 0;
regs.ip = ip;
res = ML_(evaluate_GX)( var->gexpr, var->fbGX, ®s, di );
- tl_assert(res.kind == GXR_Value);
+ tl_assert(res.kind == GXR_Addr);
if (debug)
VG_(printf)(" %5ld .. %5ld (FP) %s\n",
res.word, res.word + ((UWord)mul.ul) - 1, var->name);
@@ -3308,7 +3351,7 @@
res = ML_(evaluate_trivial_GX)( var->gexpr, di );
/* Not a constant address => not interesting */
- if (res.kind != GXR_Value) {
+ if (res.kind != GXR_Addr) {
if (0) VG_(printf)("FAIL\n");
continue;
}
Modified: trunk/coregrind/m_debuginfo/priv_d3basics.h
===================================================================
--- trunk/coregrind/m_debuginfo/priv_d3basics.h 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/priv_d3basics.h 2009-11-12 13:28:34 UTC (rev 10939)
@@ -522,6 +522,9 @@
DW_OP_form_tls_address = 0x9b,
DW_OP_call_frame_cfa = 0x9c,
DW_OP_bit_piece = 0x9d,
+ /* DWARF 4 extensions. */
+ DW_OP_implicit_value = 0x9e,
+ DW_OP_stack_value = 0x9f,
/* GNU extensions. */
DW_OP_GNU_push_tls_address = 0xe0,
/* HP extensions. */
@@ -596,12 +599,13 @@
/* This describes the result of evaluating a DWARF3 expression.
GXR_Failure: failed; .word is an asciiz string summarising why
+ GXR_Addr: evaluated to an address of the object, in .word
GXR_Value: evaluated to a value, in .word
GXR_RegNo: evaluated to a DWARF3 register number, in .word
*/
typedef
struct {
- enum { GXR_Failure, GXR_Value, GXR_RegNo } kind;
+ enum { GXR_Failure, GXR_Addr, GXR_Value, GXR_RegNo } kind;
UWord word;
}
GXResult;
@@ -644,6 +648,10 @@
covered by the guard is also ignored. */
GXResult ML_(evaluate_trivial_GX)( GExpr* gx, const DebugInfo* di );
+/* Compute call frame address (CFA) for IP/SP/FP. */
+Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
+ Addr min_accessible, Addr max_accessible );
+
#endif /* ndef __PRIV_D3BASICS_H */
/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/m_debuginfo/priv_readdwarf.h
===================================================================
--- trunk/coregrind/m_debuginfo/priv_readdwarf.h 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/priv_readdwarf.h 2009-11-12 13:28:34 UTC (rev 10939)
@@ -62,7 +62,7 @@
-------------------- */
extern
void ML_(read_callframe_info_dwarf3)
- ( /*OUT*/struct _DebugInfo* di, UChar* ehframe );
+ ( /*OUT*/struct _DebugInfo* di, UChar* frame, SizeT frame_sz, Bool for_eh );
#endif /* ndef __PRIV_READDWARF_H */
Modified: trunk/coregrind/m_debuginfo/priv_storage.h
===================================================================
--- trunk/coregrind/m_debuginfo/priv_storage.h 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/priv_storage.h 2009-11-12 13:28:34 UTC (rev 10939)
@@ -649,6 +649,11 @@
this after finishing adding entries to these tables. */
extern void ML_(canonicaliseTables) ( struct _DebugInfo* di );
+/* Canonicalise the call-frame-info table held by 'di', in preparation
+ for use. This is called by ML_(canonicaliseTables) but can also be
+ called on it's own to sort just this table. */
+extern void ML_(canonicaliseCFI) ( struct _DebugInfo* di );
+
/* ------ Searching ------ */
/* Find a symbol-table index containing the specified pointer, or -1
Modified: trunk/coregrind/m_debuginfo/priv_tytypes.h
===================================================================
--- trunk/coregrind/m_debuginfo/priv_tytypes.h 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/priv_tytypes.h 2009-11-12 13:28:34 UTC (rev 10939)
@@ -78,8 +78,13 @@
struct {
UChar* name; /* in mallocville */
UWord typeR; /* should be Te_TyXXXX */
- UChar* loc; /* location expr, in mallocville */
- UWord nLoc; /* number of bytes in .loc */
+ union {
+ UChar* loc; /* location expr, in mallocville */
+ Word offset; /* or offset from the beginning of containing
+ entity */
+ } pos;
+ Word nLoc; /* number of bytes in .pos.loc if >= 0, or -1
+ if .pos.offset should be used instead */
Bool isStruct;
} Field;
struct {
Modified: trunk/coregrind/m_debuginfo/readdwarf.c
===================================================================
--- trunk/coregrind/m_debuginfo/readdwarf.c 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/readdwarf.c 2009-11-12 13:28:34 UTC (rev 10939)
@@ -37,6 +37,7 @@
#include "pub_core_libcprint.h"
#include "pub_core_options.h"
#include "pub_core_xarray.h"
+#include "pub_core_tooliface.h" /* VG_(needs) */
#include "priv_misc.h" /* dinfo_zalloc/free/strdup */
#include "priv_d3basics.h"
#include "priv_tytypes.h"
@@ -1777,11 +1778,11 @@
#elif defined(VGP_ppc32_linux)
# define FP_REG 1
# define SP_REG 1
-# define RA_REG_DEFAULT 8 // CAB: What's a good default ?
+# define RA_REG_DEFAULT 65
#elif defined(VGP_ppc64_linux)
# define FP_REG 1
# define SP_REG 1
-# define RA_REG_DEFAULT 8 // CAB: What's a good default ?
+# define RA_REG_DEFAULT 65
#elif defined(VGP_x86_darwin)
# define FP_REG 5
# define SP_REG 4
@@ -1795,7 +1796,11 @@
#endif
/* the number of regs we are prepared to unwind */
-#define N_CFI_REGS 20
+#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+# define N_CFI_REGS 72
+#else
+# define N_CFI_REGS 20
+#endif
/* Instructions for the automaton */
enum dwarf_cfa_primary_ops
@@ -3446,23 +3451,33 @@
void ML_(read_callframe_info_dwarf3)
- ( /*OUT*/struct _DebugInfo* di, UChar* ehframe_image )
+ ( /*OUT*/struct _DebugInfo* di, UChar* frame_image, SizeT frame_size,
+ Bool for_eh )
{
Int nbytes;
HChar* how = NULL;
Int n_CIEs = 0;
- UChar* data = ehframe_image;
+ UChar* data = frame_image;
+ UWord ehframe_cfsis = 0;
+ Addr frame_avma = for_eh ? di->ehframe_avma : 0;
# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
- /* These targets don't use CFI-based stack unwinding. */
+ /* These targets don't use CFI-based stack unwinding. */
return;
# endif
+ /* If we are reading .debug_frame after .eh_frame has been read, only
+ add FDEs which weren't covered in .eh_frame. To be able to quickly
+ search the FDEs, the records must be sorted. */
+ if ( ! for_eh && di->ehframe_size && di->cfsi_used ) {
+ ML_(canonicaliseCFI) ( di );
+ ehframe_cfsis = di->cfsi_used;
+ }
+
if (di->trace_cfi) {
VG_(printf)("\n-----------------------------------------------\n");
VG_(printf)("CFI info: szB %ld, _avma %#lx, _image %p\n",
- di->ehframe_size, di->ehframe_avma,
- ehframe_image );
+ frame_size, frame_avma, frame_image );
VG_(printf)("CFI info: name %s\n",
di->filename );
}
@@ -3495,11 +3510,11 @@
Bool dw64;
/* Are we done? */
- if (data == ehframe_image + di->ehframe_size)
+ if (data == frame_image + frame_size)
return;
/* Overshot the end? Means something is wrong */
- if (data > ehframe_image + di->ehframe_size) {
+ if (data > frame_image + frame_size) {
how = "overran the end of .eh_frame";
goto bad;
}
@@ -3509,9 +3524,9 @@
ciefde_start = data;
if (di->trace_cfi)
- VG_(printf)("\ncie/fde.start = %p (ehframe_image + 0x%lx)\n",
+ VG_(printf)("\ncie/fde.start = %p (frame_image + 0x%lx)\n",
ciefde_start,
- ciefde_start - ehframe_image + 0UL);
+ ciefde_start - frame_image + 0UL);
ciefde_len = (ULong) read_UInt(data); data += sizeof(UInt);
if (di->trace_cfi)
@@ -3524,7 +3539,7 @@
if (ciefde_len == 0) {
if (di->ddump_frames)
VG_(printf)("%08lx ZERO terminator\n\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image));
+ ((Addr)ciefde_start) - ((Addr)frame_image));
return;
}
@@ -3550,8 +3565,10 @@
if (di->trace_cfi)
VG_(printf)("cie.pointer = %lld\n", cie_pointer);
- /* If cie_pointer is zero, we've got a CIE; else it's an FDE. */
- if (cie_pointer == 0) {
+ /* If cie_pointer is zero for .eh_frame or all ones for .debug_frame,
+ we've got a CIE; else it's an FDE. */
+ if (cie_pointer == (for_eh ? 0ULL
+ : dw64 ? 0xFFFFFFFFFFFFFFFFULL : 0xFFFFFFFFULL)) {
Int this_CIE;
UChar cie_version;
@@ -3575,11 +3592,11 @@
/* Record its offset. This is how we will find it again
later when looking at an FDE. */
- the_CIEs[this_CIE].offset = (ULong)(ciefde_start - ehframe_image);
+ the_CIEs[this_CIE].offset = (ULong)(ciefde_start - frame_image);
if (di->ddump_frames)
VG_(printf)("%08lx %08lx %08lx CIE\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image),
+ ((Addr)ciefde_start) - ((Addr)frame_image),
(Addr)ciefde_len,
(Addr)(UWord)cie_pointer );
@@ -3623,8 +3640,13 @@
VG_(printf)(" Data alignment factor: %d\n",
(Int)the_CIEs[this_CIE].data_a_f);
- the_CIEs[this_CIE].ra_reg = (Int)read_UChar(data);
- data += sizeof(UChar);
+ if (cie_version == 1) {
+ the_CIEs[this_CIE].ra_reg = (Int)read_UChar(data);
+ data += sizeof(UChar);
+ } else {
+ the_CIEs[this_CIE].ra_reg = read_leb128( data, &nbytes, 0);
+ data += nbytes;
+ }
if (di->trace_cfi)
VG_(printf)("cie.ra_reg = %d\n",
the_CIEs[this_CIE].ra_reg);
@@ -3702,7 +3724,7 @@
}
if (the_CIEs[this_CIE].ilen < 0
- || the_CIEs[this_CIE].ilen > di->ehframe_size) {
+ || the_CIEs[this_CIE].ilen > frame_size) {
how = "implausible # cie initial insns";
goto bad;
}
@@ -3717,8 +3739,8 @@
if (di->trace_cfi || di->ddump_frames) {
AddressDecodingInfo adi;
adi.encoding = the_CIEs[this_CIE].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.ehframe_image = frame_image;
+ adi.ehframe_avma = frame_avma;
adi.text_bias = di->text_debug_bias;
show_CF_instructions( the_CIEs[this_CIE].instrs,
the_CIEs[this_CIE].ilen, &adi,
@@ -3747,9 +3769,12 @@
cie_pointer bytes back from here. */
/* re sizeof(UInt) / sizeof(ULong), matches XXX above. */
- look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt))
- - ehframe_image)
- - cie_pointer;
+ if (for_eh)
+ look_for = (data - (dw64 ? sizeof(ULong) : sizeof(UInt))
+ - frame_image)
+ - cie_pointer;
+ else
+ look_for = cie_pointer;
for (cie = 0; cie < n_CIEs; cie++) {
if (0) VG_(printf)("look for %lld %lld\n",
@@ -3764,8 +3789,8 @@
}
adi.encoding = the_CIEs[cie].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.ehframe_image = frame_image;
+ adi.ehframe_avma = frame_avma;
adi.text_bias = di->text_debug_bias;
fde_initloc = read_encoded_Addr(&nbytes, &adi, data);
data += nbytes;
@@ -3773,8 +3798,8 @@
VG_(printf)("fde.initloc = %#lx\n", fde_initloc);
adi.encoding = the_CIEs[cie].address_encoding & 0xf;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.ehframe_image = frame_image;
+ adi.ehframe_avma = frame_avma;
adi.text_bias = di->text_debug_bias;
/* WAS (incorrectly):
@@ -3800,7 +3825,7 @@
if (di->ddump_frames)
VG_(printf)("%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
- ((Addr)ciefde_start) - ((Addr)ehframe_image),
+ ((Addr)ciefde_start) - ((Addr)frame_image),
(Addr)ciefde_len,
(Addr)(UWord)cie_pointer,
(Addr)look_for,
@@ -3827,16 +3852,43 @@
VG_(printf)("fde.ilen = %d\n", (Int)fde_ilen);
}
- if (fde_ilen < 0 || fde_ilen > di->ehframe_size) {
+ if (fde_ilen < 0 || fde_ilen > frame_size) {
how = "implausible # fde insns";
goto bad;
}
data += fde_ilen;
+ if (ehframe_cfsis) {
+ Addr a_mid_lo, a_mid_hi;
+ Word mid, size,
+ lo = 0,
+ hi = ehframe_cfsis-1;
+ while (True) {
+ /* current unsearched space is from lo to hi, inclusive. */
+ if (lo > hi) break; /* not found */
+ mid = (lo + hi) / 2;
+ a_mid_lo = di->cfsi[mid].base;
+ size = di->cfsi[mid].len;
+ a_mid_hi = a_mid_lo + size - 1;
+ vg_assert(a_mid_hi >= a_mid_lo);
+ if (fde_initloc + fde_arange <= a_mid_lo) {
+ hi = mid-1; continue;
+ }
+ if (fde_initloc > a_mid_hi) { lo = mid+1; continue; }
+ break;
+ }
+
+ /* The range this .debug_frame FDE covers has been already
+ covered in .eh_frame section. Don't add it from .debug_frame
+ section again. */
+ if (lo <= hi)
+ continue;
+ }
+
adi.encoding = the_CIEs[cie].address_encoding;
- adi.ehframe_image = ehframe_image;
- adi.ehframe_avma = di->ehframe_avma;
+ adi.ehframe_image = frame_image;
+ adi.ehframe_avma = frame_avma;
adi.text_bias = di->text_debug_bias;
if (di->trace_cfi)
Modified: trunk/coregrind/m_debuginfo/readdwarf3.c
===================================================================
--- trunk/coregrind/m_debuginfo/readdwarf3.c 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/readdwarf3.c 2009-11-12 13:28:34 UTC (rev 10939)
@@ -2356,9 +2356,16 @@
if (attr == DW_AT_type && ctsSzB > 0) {
fieldE.Te.Field.typeR = (UWord)cts;
}
- if (attr == DW_AT_data_member_location && ctsMemSzB > 0) {
+ /* There are 2 different cases for DW_AT_data_member_location.
+ If it is a constant class attribute, it contains byte offset
+ from the beginning of the containing entity.
+ Otherwise it is a location expression. */
+ if (attr == DW_AT_data_member_location && ctsSzB > 0) {
+ fieldE.Te.Field.nLoc = -1;
+ fieldE.Te.Field.pos.offset = cts;
+ } else if (attr == DW_AT_data_member_location && ctsMemSzB > 0) {
fieldE.Te.Field.nLoc = (UWord)ctsMemSzB;
- fieldE.Te.Field.loc
+ fieldE.Te.Field.pos.loc
= ML_(dinfo_memdup)( "di.readdwarf3.ptD.member.2",
(UChar*)(UWord)cts,
(SizeT)fieldE.Te.Field.nLoc );
@@ -2385,13 +2392,14 @@
vg_assert(fieldE.Te.Field.name);
if (fieldE.Te.Field.typeR == D3_INVALID_CUOFF)
goto bad_DIE;
- if (fieldE.Te.Field.loc) {
+ if (fieldE.Te.Field.nLoc) {
if (!parent_is_struct) {
/* If this is a union type, pretend we haven't seen the data
member location expression, as it is by definition
redundant (it must be zero). */
- ML_(dinfo_free)(fieldE.Te.Field.loc);
- fieldE.Te.Field.loc = NULL;
+ if (fieldE.Te.Field.nLoc > 0)
+ ML_(dinfo_free)(fieldE.Te.Field.pos.loc);
+ fieldE.Te.Field.pos.loc = NULL;
fieldE.Te.Field.nLoc = 0;
}
/* Record this child in the parent */
@@ -2616,10 +2624,10 @@
/* For union members, Expr should be absent */
if (0) VG_(printf)("YYYY Acquire Field\n");
vg_assert(fieldE.tag == Te_Field);
- vg_assert( (fieldE.Te.Field.nLoc > 0 && fieldE.Te.Field.loc != NULL)
- || (fieldE.Te.Field.nLoc == 0 && fieldE.Te.Field.loc == NULL) );
+ vg_assert(fieldE.Te.Field.nLoc <= 0 || fieldE.Te.Field.pos.loc != NULL);
+ vg_assert(fieldE.Te.Field.nLoc != 0 || fieldE.Te.Field.pos.loc == NULL);
if (fieldE.Te.Field.isStruct) {
- vg_assert(fieldE.Te.Field.nLoc > 0);
+ vg_assert(fieldE.Te.Field.nLoc != 0);
} else {
vg_assert(fieldE.Te.Field.nLoc == 0);
}
Modified: trunk/coregrind/m_debuginfo/readelf.c
===================================================================
--- trunk/coregrind/m_debuginfo/readelf.c 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/readelf.c 2009-11-12 13:28:34 UTC (rev 10939)
@@ -1691,6 +1691,7 @@
UChar* debug_str_img = NULL; /* .debug_str (dwarf2) */
UChar* debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
UChar* debug_loc_img = NULL; /* .debug_loc (dwarf2) */
+ UChar* debug_frame_img = NULL; /* .debug_frame (dwarf2) */
UChar* dwarf1d_img = NULL; /* .debug (dwarf1) */
UChar* dwarf1l_img = NULL; /* .line (dwarf1) */
UChar* ehframe_img = NULL; /* .eh_frame (dwarf2) */
@@ -1710,6 +1711,7 @@
SizeT debug_str_sz = 0;
SizeT debug_ranges_sz = 0;
SizeT debug_loc_sz = 0;
+ SizeT debug_frame_sz = 0;
SizeT dwarf1d_sz = 0;
SizeT dwarf1l_sz = 0;
SizeT ehframe_sz = 0;
@@ -1767,6 +1769,7 @@
FIND(".debug_str", debug_str_sz, debug_str_img)
FIND(".debug_ranges", debug_ranges_sz, debug_ranges_img)
FIND(".debug_loc", debug_loc_sz, debug_loc_img)
+ FIND(".debug_frame", debug_frame_sz, debug_frame_img)
FIND(".debug", dwarf1d_sz, dwarf1d_img)
FIND(".line", dwarf1l_sz, dwarf1l_img)
@@ -1959,6 +1962,8 @@
FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz,
debug_ranges_img)
FIND(need_dwarf2, ".debug_loc", debug_loc_sz, debug_loc_img)
+ FIND(need_dwarf2, ".debug_frame", debug_frame_sz,
+ debug_frame_img)
FIND(need_dwarf1, ".debug", dwarf1d_sz, dwarf1d_img)
FIND(need_dwarf1, ".line", dwarf1l_sz, dwarf1l_img)
@@ -1996,11 +2001,15 @@
False, opd_img);
}
- /* Read .eh_frame (call-frame-info) if any */
+ /* Read .eh_frame and .debug_frame (call-frame-info) if any */
if (ehframe_img) {
vg_assert(ehframe_sz == di->ehframe_size);
- ML_(read_callframe_info_dwarf3)( di, ehframe_img );
+ ML_(read_callframe_info_dwarf3)( di, ehframe_img, ehframe_sz, True );
}
+ if (debug_frame_sz) {
+ ML_(read_callframe_info_dwarf3)( di, debug_frame_img,
+ debug_frame_sz, False );
+ }
/* Read the stabs and/or dwarf2 debug information, if any. It
appears reading stabs stuff on amd64-linux doesn't work, so
Modified: trunk/coregrind/m_debuginfo/storage.c
===================================================================
--- trunk/coregrind/m_debuginfo/storage.c 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/storage.c 2009-11-12 13:28:34 UTC (rev 10939)
@@ -1435,7 +1435,7 @@
return 0;
}
-static void canonicaliseCFI ( struct _DebugInfo* di )
+void ML_(canonicaliseCFI) ( struct _DebugInfo* di )
{
Word i, j;
const Addr minAvma = 0;
@@ -1528,7 +1528,7 @@
{
canonicaliseSymtab ( di );
canonicaliseLoctab ( di );
- canonicaliseCFI ( di );
+ ML_(canonicaliseCFI) ( di );
canonicaliseVarInfo ( di );
}
Modified: trunk/coregrind/m_debuginfo/tytypes.c
===================================================================
--- trunk/coregrind/m_debuginfo/tytypes.c 2009-11-12 13:19:41 UTC (rev 10938)
+++ trunk/coregrind/m_debuginfo/tytypes.c 2009-11-12 13:28:34 UTC (rev 10939)
@@ -98,10 +98,15 @@
te->Te.Atom.value, te->Te.Atom.name);
break;
case Te_Field:
- VG_(printf)("Te_Field(ty=0x%05lx,nLoc=%lu,loc=%p,\"%s\")",
- te->Te.Field.typeR, te->Te.Field.nLoc,
- te->Te.Field.loc,
- te->Te.Field.name ? te->Te.Field.name : (UChar*)"");
+ if (te->Te.Field.nLoc == -1)
+ VG_(printf)("Te_Field(ty=0x%05lx,pos.offset=%ld,\"%s\")",
+ te->Te.Field.typeR, te->Te.Field.pos.offset,
+ te->Te.Field.name ? te->Te.Field.name : (UChar*)"");
+ else
+ VG_(printf)("Te_Field(ty=0x%05lx,nLoc=%lu,pos.loc=%p,\"%s\")",
+ te->Te.Field.typeR, te->Te.Field.nLoc,
+ te->Te.Field.pos.loc,
+ te->Te.Field.name ? te->Te.Field.name : (UChar*)"");
break;
case Te_Bound:
VG_(printf)("Te_Bound[");
@@ -476,8 +481,11 @@
if (r != 0) return r;
r = UWord__cmp(te1->Te.Field.nLoc, te2->Te.Field.nLoc);
if (r != 0) return r;
- r = Bytevector__cmp(te1->Te.Field.loc, te2->Te.Field.loc,
- te1->Te.Field.nLoc);
+ if (te1->Te.Field.nLoc == -1)
+ r = Long__cmp(te1->Te.Field.pos.offset, te2->Te.Field.pos.offset);
+ else
+ r = Bytevector__cmp(te1->Te.Field.pos.loc, te2->Te.Field.pos.loc,
+ te1->Te.Field.nLoc);
return r;
case Te_Bound:
r = Bool__cmp(te1->Te.Bound.knownL, te2->Te.Bound.knownL);
@@ -568,7 +576,8 @@
break;
case Te_Field:
if (te->Te.Field.name) ML_(dinfo_free)(te->Te.Field.name);
- if (te->Te.Field.loc) ML_(dinfo_free)(te->Te.Field.loc);
+ if (te->Te.Field.nLoc > 0 && te->Te.Field.pos.loc)
+ ML_(dinfo_free)(te->Te.Field.pos.loc);
break;
case Te_Bound:
break;
@@ -747,26 +756,32 @@
field = ML_(TyEnts__index_by_cuOff)(tyents, NULL, fieldR);
vg_assert(field);
vg_assert(field->tag == Te_Field);
- vg_assert(field->Te.Field.loc);
- vg_assert(field->Te.Field.nLoc > 0);
- /* Re data_bias in this call, we should really send in
- a legitimate value. But the expression is expected
- to be a constant expression, evaluation of which
- will not need to use DW_OP_addr and hence we can
- avoid the trouble of plumbing the data bias through
- to this point (if, indeed, it has any meaning; from
- which DebugInfo would we take the data bias? */
- res = ML_(evaluate_Dwarf3_Expr)(
- field->Te.Field.loc, field->Te.Field.nLoc,
- NULL/*fbGX*/, NULL/*RegSummary*/,
- 0/*data_bias*/,
- True/*push_initial_zero*/);
- if (0) {
- VG_(printf)("QQQ ");
- ML_(pp_GXResult)(res);
- VG_(printf)("\n");
+ vg_assert(field->Te.Field.nLoc < 0
+ || (field->Te.Field.nLoc > 0
+ && field->Te.Field.pos.loc));
+ if (field->Te.Field.nLoc == -1) {
+ res.kind = GXR_Addr;
+ res.word = field->Te.Field.pos.offset;
+ } else {
+ /* Re data_bias in this call, we should really send in
+ a legitimate value. But the expression is expected
+ to be a constant expression, evaluation of which
+ will not need to use DW_OP_addr and hence we can
+ avoid the trouble of plumbing the data bias through
+ to this point (if, indeed, it has any meaning; from
+ which DebugInfo would we take the data bias? */
+ res = ML_(evaluate_Dwarf3_Expr)(
+ field->Te.Field.pos.loc, field->Te.Field.nLoc,
+ NULL/*fbGX*/, NULL/*RegSummary*/,
+ 0/*data_bias*/,
+ True/*push_initial_zero*/);
+ if (0) {
+ VG_(printf)("QQQ ");
+ ML_(pp_GXResult)(res);
+ VG_(printf)("\n");
+ }
}
- if (res.kind != GXR_Value)
+ if (res.kind != GXR_Addr)
continue;
mul = ML_(sizeOfType)( tyents, field->Te.Field.typeR );
if (mul.b != True)
|
|
From: <sv...@va...> - 2009-11-12 13:19:57
|
Author: tom
Date: 2009-11-12 13:19:41 +0000 (Thu, 12 Nov 2009)
New Revision: 10938
Log:
Fix stack unwinding on PPC to store the correct frame pointer for
frames other than the first one found.
This is taken from Jakub Jelinek's second patch on bug #210479.
Modified:
trunk/coregrind/m_stacktrace.c
Modified: trunk/coregrind/m_stacktrace.c
===================================================================
--- trunk/coregrind/m_stacktrace.c 2009-11-11 19:22:05 UTC (rev 10937)
+++ trunk/coregrind/m_stacktrace.c 2009-11-12 13:19:41 UTC (rev 10938)
@@ -430,9 +430,9 @@
# endif
if (0 == ip || 1 == ip) break;
- fp = (((UWord*)fp)[0]);
if (sps) sps[i] = fp; /* NB. not sp */
if (fps) fps[i] = fp;
+ fp = (((UWord*)fp)[0]);
ips[i++] = ip - 1; /* -1: refer to calling insn, not the RA */
if (debug)
VG_(printf)(" ipsF[%d]=%#08lx\n", i-1, ips[i-1]);
|
|
From: Tom H. <th...@cy...> - 2009-11-12 03:50:34
|
Nightly build on vauxhall ( x86_64, Fedora 11 ) Started at 2009-11-12 03:20:06 GMT Ended at 2009-11-12 03:50:09 GMT 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 == 541 tests, 8 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/pth_spinlock (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc23_bogus_condwait (stderr) drd/tests/pth_detached_sem (stdout) drd/tests/qt4_semaphore (stderr) exp-ptrcheck/tests/bad_percentify (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 541 tests, 7 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc23_bogus_condwait (stderr) drd/tests/qt4_semaphore (stderr) exp-ptrcheck/tests/bad_percentify (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Thu Nov 12 03:35:11 2009 --- new.short Thu Nov 12 03:50:09 2009 *************** *** 8,12 **** ! == 541 tests, 7 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/tc06_two_races_xml (stderr) --- 8,13 ---- ! == 541 tests, 8 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) + helgrind/tests/pth_spinlock (stderr) helgrind/tests/tc06_two_races_xml (stderr) *************** *** 14,15 **** --- 15,17 ---- helgrind/tests/tc23_bogus_condwait (stderr) + drd/tests/pth_detached_sem (stdout) drd/tests/qt4_semaphore (stderr) |
|
From: Tom H. <th...@cy...> - 2009-11-12 03:49:03
|
Nightly build on lloyd ( x86_64, Fedora 7 ) Started at 2009-11-12 03:05:06 GMT Ended at 2009-11-12 03:48:47 GMT 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 == 531 tests, 1 stderr failure, 0 stdout failures, 0 post failures == helgrind/tests/tc06_two_races_xml (stderr) |
|
From: Tom H. <th...@cy...> - 2009-11-12 03:36:15
|
Nightly build on mg ( x86_64, Fedora 9 ) Started at 2009-11-12 03:10:06 GMT Ended at 2009-11-12 03:35:56 GMT 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 == 538 tests, 1 stderr failure, 0 stdout failures, 0 post failures == helgrind/tests/tc06_two_races_xml (stderr) |
|
From: <sv...@va...> - 2009-11-11 19:22:15
|
Author: bart Date: 2009-11-11 19:22:05 +0000 (Wed, 11 Nov 2009) New Revision: 10937 Log: Fixed typo. Modified: trunk/configure.in Modified: trunk/configure.in =================================================================== --- trunk/configure.in 2009-11-10 15:11:30 UTC (rev 10936) +++ trunk/configure.in 2009-11-11 19:22:05 UTC (rev 10937) @@ -1757,7 +1757,7 @@ # Test for QAtomicInt, which has been introduced in Qt 4.4. # See also http://doc.trolltech.com/4.4/qatomicint.html. if test x$ac_have_qtcore = xyes; then - AC_MSG_CHECKING([for Qt4 QAtomicInt)]) + AC_MSG_CHECKING([for Qt4 QAtomicInt]) AC_LANG(C++) safe_CXXFLAGS="${CXXFLAGS}" CXXFLAGS="${QTCORE_CFLAGS} $mflag_primary" |
|
From: Bart V. A. <bar...@gm...> - 2009-11-11 08:51:12
|
Nightly build on cellbuzz-native ( cellbuzz, ppc64, Fedora 7, native ) Started at 2009-11-11 02:24:01 EST Ended at 2009-11-11 03:50:48 EST 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 == 449 tests, 45 stderr failures, 10 stdout failures, 0 post failures == memcheck/tests/deep_templates (stdout) memcheck/tests/leak-cases-full (stderr) memcheck/tests/leak-cases-summary (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/linux/timerfd-syscall (stdout) memcheck/tests/linux-syscalls-2007 (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/partiallydefinedeq (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/wrap8 (stdout) memcheck/tests/wrap8 (stderr) none/tests/empty-exe (stderr) none/tests/linux/mremap (stderr) 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) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (stderr) none/tests/shell_zerolength (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) drd/tests/tc23_bogus_condwait (stderr) exp-ptrcheck/tests/bad_percentify (stderr) exp-ptrcheck/tests/base (stderr) exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/fp (stderr) exp-ptrcheck/tests/globalerr (stderr) exp-ptrcheck/tests/hackedbz2 (stderr) exp-ptrcheck/tests/hp_bounds (stderr) exp-ptrcheck/tests/hp_dangle (stderr) exp-ptrcheck/tests/hsg (stderr) exp-ptrcheck/tests/justify (stderr) exp-ptrcheck/tests/partial_bad (stderr) exp-ptrcheck/tests/partial_good (stderr) exp-ptrcheck/tests/preen_invars (stderr) exp-ptrcheck/tests/pth_create (stderr) exp-ptrcheck/tests/pth_specific (stderr) exp-ptrcheck/tests/realloc (stderr) exp-ptrcheck/tests/stackerr (stderr) exp-ptrcheck/tests/strcpy (stderr) exp-ptrcheck/tests/supp (stderr) exp-ptrcheck/tests/tricky (stderr) exp-ptrcheck/tests/unaligned (stderr) exp-ptrcheck/tests/zero (stderr) |
|
From: Julian S. <js...@ac...> - 2009-11-11 07:49:35
|
On Tuesday 10 November 2009, Konstantin Serebryany wrote: > Hi, > > Memcheck reports uninitialized reads (UMRs) only when the reads cause side > effects (e.g. cmp, syscall, etc). Yes. So it's not really reporting reads of uninitialised memory; rather it's reporting dangerous uses of uninitialised values. > This cases the implementation to be complex and slow, especially if we need > to have --track-origins=yes. > > Other tools choose to report UMRs on any first access, including move. > This is much simpler and faster, but leads to numerous false positives > (e.g. when copying structures with padding bytes). > > I wonder if these two approaches where discussed and compared somewhere in > literature. I don't know of any. I too would be interested to read more about it. Personally I don't believe it's possible to have an (essentially) zero false positive rate without using an approach like Memcheck's. But I would love to be proved wrong on this, since I too don't like Memcheck's complexity and overhead. J |
|
From: John R. <jr...@bi...> - 2009-11-11 04:39:41
|
> Other tools choose to report UMRs on any first access, including move. > This is much simpler and faster, but leads to numerous false positives > (e.g. when copying structures with padding bytes). There are programming ecosystems in which that is not a "false positive." It is an actual demerit with a real monetary cost. Some software creators must purchase product liability insurance. Some insurance companies offer a discount if the code passes tests which show that no uninitialized bits ever are fetched from memory. Any hole in a structure is avoided, documented, and/or filled deliberately. "Complain immediately upon fetch" sometimes dramatically shortens the search for the cause of a mysterious UMR. The feature "--track-origins=yes" can be viewed as an intermediate strategy between delayed versus immediate complaints. -- |
|
From: Tom H. <th...@cy...> - 2009-11-11 03:50:43
|
Nightly build on vauxhall ( x86_64, Fedora 11 ) Started at 2009-11-11 03:20:06 GMT Ended at 2009-11-11 03:50:24 GMT 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 == 541 tests, 9 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/pth_spinlock (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc23_bogus_condwait (stderr) drd/tests/qt4_mutex (stderr) drd/tests/qt4_rwlock (stderr) exp-ptrcheck/tests/bad_percentify (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 541 tests, 8 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/tc06_two_races_xml (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc23_bogus_condwait (stderr) drd/tests/qt4_mutex (stderr) drd/tests/qt4_rwlock (stderr) exp-ptrcheck/tests/bad_percentify (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Wed Nov 11 03:35:20 2009 --- new.short Wed Nov 11 03:50:24 2009 *************** *** 8,12 **** ! == 541 tests, 8 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) helgrind/tests/tc06_two_races_xml (stderr) --- 8,13 ---- ! == 541 tests, 9 stderr failures, 0 stdout failures, 0 post failures == memcheck/tests/linux/stack_switch (stderr) memcheck/tests/long_namespace_xml (stderr) + helgrind/tests/pth_spinlock (stderr) helgrind/tests/tc06_two_races_xml (stderr) |
|
From: Tom H. <th...@cy...> - 2009-11-11 03:49:23
|
Nightly build on lloyd ( x86_64, Fedora 7 ) Started at 2009-11-11 03:05:06 GMT Ended at 2009-11-11 03:49:10 GMT 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 == 531 tests, 1 stderr failure, 0 stdout failures, 0 post failures == helgrind/tests/tc06_two_races_xml (stderr) |