|
From: <sv...@va...> - 2008-02-25 00:11:02
|
Author: sewardj
Date: 2008-02-25 00:11:05 +0000 (Mon, 25 Feb 2008)
New Revision: 7453
Log:
Fix off-by-one problem in IP values obtained from stack unwinding,
that caused non-identification of variables on stacks in some cases.
Modified:
branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
branches/DATASYMS/coregrind/m_stacktrace.c
Modified: branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-24 19:51:51 UTC (rev 7452)
+++ branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-25 00:11:05 UTC (rev 7453)
@@ -1815,7 +1815,7 @@
static UInt n_search = 0;
static UInt n_steps = 0;
n_search++;
-
+ if (0) VG_(printf)("QQQQ: cvif: ip,sp,fp %p,%p,%p\n", ip,sp,fp);
/* first, find the DebugInfo that pertains to 'ip'. */
for (di = debugInfo_list; di; di = di->next) {
n_steps++;
@@ -1867,6 +1867,7 @@
DiAddrRange* arange;
OSet* this_scope
= *(OSet**)VG_(indexXA)( di->varinfo, i );
+ if (0) VG_(printf)("QQQQ: considering scope %ld\n", (Word)i);
if (!this_scope)
continue;
/* Find the set of variables in this scope that
@@ -1935,7 +1936,7 @@
vg_assert(n_dname > 1);
dname1[n_dname-1] = dname2[n_dname-1] = 0;
- if (0) VG_(printf)("GDD: dataaddr %p\n", data_addr);
+ if (0) VG_(printf)("get_data_description: dataaddr %p\n", data_addr);
/* First, see if data_addr is (or is part of) a global variable.
Loop over the DebugInfos we have. Check data_addr against the
@@ -2033,14 +2034,29 @@
/* We conclude data_addr is in thread tid's stack. Unwind the
stack to get a bunch of (ip,sp,fp) triples describing the
frames, and for each frame, consider the local variables. */
-
n_frames = VG_(get_StackTrace)( tid, ips, N_FRAMES,
sps, fps, 0/*first_ip_delta*/ );
+ /* Re ip_delta in the next loop: There's a subtlety in the meaning
+ of the IP values in a stack obtained from VG_(get_StackTrace).
+ The innermost value really is simply the thread's program
+ counter at the time the snapshot was taken. However, all the
+ other values are actually return addresses, and so point just
+ after the call instructions. Hence they notionally reflect not
+ what the program counters were at the time those calls were
+ made, but what they will be when those calls return. This can
+ be of significance should an address range happen to end at the
+ end of a call instruction -- we may ignore the range when in
+ fact it should be considered. Hence, back up the IPs by 1 for
+ all non-innermost IPs. Note that VG_(get_StackTrace_wrk) itself
+ has to use the same trick in order to use CFI data to unwind the
+ stack (as documented therein in comments). */
vg_assert(n_frames >= 0 && n_frames <= N_FRAMES);
for (j = 0; j < n_frames; j++) {
+ Word ip_delta = j == 0 ? 0 : 1;
if (consider_vars_in_frame( dname1, dname2, n_dname,
data_addr,
- ips[j], sps[j], fps[j], tid, j )) {
+ ips[j] - ip_delta,
+ sps[j], fps[j], tid, j )) {
dname1[n_dname-1] = dname2[n_dname-1] = 0;
return True;
}
Modified: branches/DATASYMS/coregrind/m_stacktrace.c
===================================================================
--- branches/DATASYMS/coregrind/m_stacktrace.c 2008-02-24 19:51:51 UTC (rev 7452)
+++ branches/DATASYMS/coregrind/m_stacktrace.c 2008-02-25 00:11:05 UTC (rev 7453)
@@ -136,6 +136,11 @@
* This most frequently happens at the end of a function when
* a tail call occurs and we wind up using the CFI info for the
* next function which is completely wrong.
+ *
+ * Note that VG_(get_data_description) (in m_debuginfo) has to take
+ * this same problem into account when unwinding the stack to
+ * examine local variable descriptions (as documented therein in
+ * comments).
*/
while (True) {
@@ -208,6 +213,11 @@
* This most frequently happens at the end of a function when
* a tail call occurs and we wind up using the CFI info for the
* next function which is completely wrong.
+ *
+ * Note that VG_(get_data_description) (in m_debuginfo) has to take
+ * this same problem into account when unwinding the stack to
+ * examine local variable descriptions (as documented therein in
+ * comments).
*/
while (True) {
|