|
From: <sv...@va...> - 2007-11-09 23:02:26
|
Author: sewardj
Date: 2007-11-09 23:02:28 +0000 (Fri, 09 Nov 2007)
New Revision: 7118
Log:
Merge (from branches/THRCHECK) the following amd64-linux stack unwind
kludges^H^H^H^H^H^H^Henhancements:
r6802: For VG_(record_ExeContext) et al, add a new parameter
(first_ip_delta) which is added to the initial IP value before the
stack is unwound. A safe value to pass is zero, which causes the
existing behaviour to be unchanged. This is a kludge needed to work
around the incomplete amd64 stack unwind info in glibc-2.5's clone()
routine.
r7059: Add a last-ditch heuristic-hack to the amd64-linux stack
unwinder, which is used when all other methods fail. Seems like GDB
has something similar.
Modified:
trunk/coregrind/m_execontext.c
trunk/coregrind/m_stacktrace.c
trunk/exp-omega/o_main.c
trunk/include/pub_tool_execontext.h
trunk/massif/ms_main.c
trunk/memcheck/mc_main.c
trunk/memcheck/mc_malloc_wrappers.c
Modified: trunk/coregrind/m_execontext.c
===================================================================
--- trunk/coregrind/m_execontext.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/coregrind/m_execontext.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -277,7 +277,7 @@
ec_htab_size_idx++;
}
-ExeContext* VG_(record_ExeContext) ( ThreadId tid )
+ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta )
{
Int i;
Addr ips[VG_DEEPEST_BACKTRACE];
@@ -297,7 +297,8 @@
vg_assert(VG_(clo_backtrace_size) >= 1 &&
VG_(clo_backtrace_size) <= VG_DEEPEST_BACKTRACE);
- n_ips = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size) );
+ n_ips = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size),
+ first_ip_delta );
tl_assert(n_ips >= 1 && n_ips <= VG_(clo_backtrace_size));
/* Now figure out if we've seen this one before. First hash it so
Modified: trunk/coregrind/m_stacktrace.c
===================================================================
--- trunk/coregrind/m_stacktrace.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/coregrind/m_stacktrace.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -240,7 +240,29 @@
continue;
}
- /* No luck there. We have to give up. */
+ /* Last-ditch hack (evidently GDB does something similar). We
+ are in the middle of nowhere and we have a nonsense value for
+ the frame pointer. If the stack pointer is still valid,
+ assume that what it points at is a return address. Yes,
+ desperate measures. Could do better here:
+ - check that the supposed return address is in
+ an executable page
+ - check that the supposed return address is just after a call insn
+ - given those two checks, don't just consider *sp as the return
+ address; instead scan a likely section of stack (eg sp .. sp+256)
+ and use suitable values found there.
+ */
+ if (fp_min <= sp && sp < fp_max) {
+ ip = ((UWord*)sp)[0];
+ ips[i++] = ip;
+ if (debug)
+ VG_(printf)(" ipsH[%d]=%08p\n", i-1, ips[i-1]);
+ ip = ip - 1;
+ sp += 8;
+ continue;
+ }
+
+ /* No luck at all. We have to give up. */
break;
}
@@ -369,7 +391,8 @@
return n_found;
}
-UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips )
+UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips,
+ Word first_ip_delta )
{
/* thread in thread table */
Addr ip = VG_(get_IP)(tid);
@@ -405,6 +428,10 @@
}
# endif
+ /* Take into account the first_ip_delta. */
+ vg_assert( sizeof(Addr) == sizeof(Word) );
+ ip += first_ip_delta;
+
if (0)
VG_(printf)("tid %d: stack_highest=0x%08lx ip=0x%08lx sp=0x%08lx fp=0x%08lx\n",
tid, stack_highest_word, ip, sp, fp);
@@ -446,7 +473,8 @@
void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt n_ips )
{
Addr ips[n_ips];
- UInt n_ips_obtained = VG_(get_StackTrace)(tid, ips, n_ips);
+ UInt n_ips_obtained = VG_(get_StackTrace)(tid, ips, n_ips,
+ 0/*first_ip_delta*/);
VG_(pp_StackTrace)(ips, n_ips_obtained);
}
Modified: trunk/exp-omega/o_main.c
===================================================================
--- trunk/exp-omega/o_main.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/exp-omega/o_main.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -15,7 +15,7 @@
providing moral support.)
Partly based upon other Valgrind tools
- Copyright (C) 2000-2006 Julian Seward, Nicholas Nethercote et al.
+ Copyright (C) 2000-2007 Julian Seward, Nicholas Nethercote et al.
js...@ac...
nj...@va...
@@ -1582,7 +1582,8 @@
{
O_MDEBUG("creating new context maybeLast=0");
// Get the current stacktrace
- mb->leaked = VG_(record_ExeContext)(VG_(get_running_tid)());
+ mb->leaked = VG_(record_ExeContext)(VG_(get_running_tid)(),
+ 0/*first_ip_delta*/);
}
doReport = o_addLeakedBlock(mb->where, mb->leaked, mb->length);
@@ -1945,7 +1946,7 @@
*/
mb->hdr.key = start;
mb->length = size;
- mb->where = VG_(record_ExeContext)(tid);
+ mb->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
/*
O_DEBUG("Creating new MemBlock (%p) key = %p, length %d",
@@ -2036,7 +2037,8 @@
if(!tp->memBlock->maybeLast)
{
tp->memBlock->maybeLast = tp;
- tp->memBlock->funcEnd = VG_(record_ExeContext)(VG_(get_running_tid)());
+ tp->memBlock->funcEnd = VG_(record_ExeContext)(VG_(get_running_tid)(),
+ 0/*first_ip_delta*/);
O_MDEBUG("setting maybeLast to %p in block at %p",
FROM_TRACKED_KEY(tp->hdr.key), tp->block);
}
Modified: trunk/include/pub_tool_execontext.h
===================================================================
--- trunk/include/pub_tool_execontext.h 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/include/pub_tool_execontext.h 2007-11-09 23:02:28 UTC (rev 7118)
@@ -51,8 +51,11 @@
//
// If called from generated code, use VG_(get_running_tid)() to get the
// current ThreadId. If called from non-generated code, the current
-// ThreadId should be passed in by the core.
-extern ExeContext* VG_(record_ExeContext) ( ThreadId tid );
+// ThreadId should be passed in by the core. The initial IP value to
+// use is adjusted by first_ip_delta before the stack is unwound.
+// A safe value to pass is zero.
+extern
+ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta );
// Apply a function to every element in the ExeContext. The parameter 'n'
// gives the index of the passed ip. Doesn't go below main() unless
Modified: trunk/massif/ms_main.c
===================================================================
--- trunk/massif/ms_main.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/massif/ms_main.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -875,7 +875,8 @@
VG_(tool_panic)("get_IPs: ips[] too small, inc. MAX_OVERESTIMATE?");
// Ask for more IPs than clo_depth suggests we need.
- n_ips = VG_(get_StackTrace)( tid, ips, clo_depth + overestimate );
+ n_ips = VG_(get_StackTrace)( tid, ips, clo_depth + overestimate,
+ 0/*first_ip_delta*/ );
tl_assert(n_ips > 0);
// If the original stack trace is smaller than asked-for, redo=False.
Modified: trunk/memcheck/mc_main.c
===================================================================
--- trunk/memcheck/mc_main.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/memcheck/mc_main.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -4659,7 +4659,7 @@
cgbs[i].start = arg[1];
cgbs[i].size = arg[2];
cgbs[i].desc = VG_(strdup)((Char *)arg[3]);
- cgbs[i].where = VG_(record_ExeContext) ( tid );
+ cgbs[i].where = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
*ret = i;
} else
@@ -4975,6 +4975,7 @@
VG_(needs_core_errors) ();
VG_(needs_tool_errors) (mc_eq_Error,
mc_pp_Error,
+ True,/*show TIDs for errors*/
mc_update_extra,
mc_recognised_suppression,
mc_read_extra_suppression_info,
Modified: trunk/memcheck/mc_malloc_wrappers.c
===================================================================
--- trunk/memcheck/mc_malloc_wrappers.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/memcheck/mc_malloc_wrappers.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -131,7 +131,7 @@
mc->data = p;
mc->szB = szB;
mc->allockind = kind;
- mc->where = VG_(record_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
/* Paranoia ... ensure the MC_Chunk is off-limits to the client, so
the mc->data field isn't visible to the leak checker. If memory
@@ -271,7 +271,7 @@
/* Put it out of harm's way for a while, if not from a client request */
if (MC_AllocCustom != mc->allockind) {
/* Record where freed */
- mc->where = VG_(record_ExeContext) ( tid );
+ mc->where = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
add_to_freed_queue ( mc );
} else {
VG_(free) ( mc );
@@ -349,14 +349,14 @@
if (old_szB == new_szB) {
/* size unchanged */
- mc->where = VG_(record_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
p_new = p_old;
} else if (old_szB > new_szB) {
/* new size is smaller */
MC_(make_mem_noaccess)( mc->data+new_szB, mc->szB-new_szB );
mc->szB = new_szB;
- mc->where = VG_(record_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
p_new = p_old;
} else {
|