|
|
0ab3a1 |
commit f250c4d3241c156f8e65398e2af76e3e2ee1ccb5
|
|
|
0ab3a1 |
Author: philippe <philippe@a5019735-40e9-0310-863c-91ae7b9d1cf9>
|
|
|
0ab3a1 |
Date: Wed Nov 18 20:56:55 2015 +0000
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
Fix incorrect (or infinite loop) unwind on RHEL7 x86 32 bits.
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
On RHEL7 x86 32 bits, Valgrind unwinder cannot properly unwind
|
|
|
0ab3a1 |
the stack just after a thread creation : the unwinder always retrieves
|
|
|
0ab3a1 |
the same pc/sp/bp.
|
|
|
0ab3a1 |
See below for an example.
|
|
|
0ab3a1 |
This has as consequences that some stack traces are bigger than
|
|
|
0ab3a1 |
needed (i.e. they always fill up the ips array). If
|
|
|
0ab3a1 |
--merge-recursive-frames is given, then the unwinder enters in an
|
|
|
0ab3a1 |
infinite loop (as identical frames will be merged, and the ips array
|
|
|
0ab3a1 |
will never be filled in).
|
|
|
0ab3a1 |
Thi patch adds an additional exit condition : after unwinding
|
|
|
0ab3a1 |
a frame, if the previous sp is >= new sp, then unwinding stops.
|
|
|
0ab3a1 |
Patch has been tested on debian 8/x86, RHEL7/x86.
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
0x0417db67 <+55>: mov 0x18(%esp),%ebx
|
|
|
0ab3a1 |
0x0417db6b <+59>: mov 0x28(%esp),%edi
|
|
|
0ab3a1 |
0x0417db6f <+63>: mov $0x78,%eax
|
|
|
0ab3a1 |
0x0417db74 <+68>: mov %ebx,(%ecx)
|
|
|
0ab3a1 |
0x0417db76 <+70>: int $0x80
|
|
|
0ab3a1 |
=> 0x0417db78 <+72>: pop %edi
|
|
|
0ab3a1 |
0x0417db79 <+73>: pop %esi
|
|
|
0ab3a1 |
0x0417db7a <+74>: pop %ebx
|
|
|
0ab3a1 |
0x0417db7b <+75>: test %eax,%eax
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
Valgrind stacktrace gives:
|
|
|
0ab3a1 |
==21261== at 0x417DB78: clone (clone.S:110)
|
|
|
0ab3a1 |
==21261== by 0x424702F: ???
|
|
|
0ab3a1 |
==21261== by 0x424702F: ???
|
|
|
0ab3a1 |
==21261== by 0x424702F: ???
|
|
|
0ab3a1 |
==21261== by 0x424702F: ???
|
|
|
0ab3a1 |
==21261== by 0x424702F: ???
|
|
|
0ab3a1 |
==21261== by 0x424702F: ???
|
|
|
0ab3a1 |
==21261== by 0x424702F: ???
|
|
|
0ab3a1 |
...
|
|
|
0ab3a1 |
(till the array of ips is full)
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
while gdb stacktrace gives:
|
|
|
0ab3a1 |
(gdb) bt
|
|
|
0ab3a1 |
#0 clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:110
|
|
|
0ab3a1 |
#1 0x00000000 in ?? ()
|
|
|
0ab3a1 |
(gdb) p $pc
|
|
|
0ab3a1 |
$2 = (void (*)()) 0x417db78 <clone+72>
|
|
|
0ab3a1 |
(gdb)
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
With the fix, valgrind gives:
|
|
|
0ab3a1 |
==21261== at 0x417DB78: clone (clone.S:110)
|
|
|
0ab3a1 |
==21261== by 0x424702F: ???
|
|
|
0ab3a1 |
which looks more reasonable.
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15729 a5019735-40e9-0310-863c-91ae7b9d1cf9
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
|
|
|
0ab3a1 |
index 8c1e9a4..137e780 100644
|
|
|
0ab3a1 |
--- a/coregrind/m_stacktrace.c
|
|
|
0ab3a1 |
+++ b/coregrind/m_stacktrace.c
|
|
|
0ab3a1 |
@@ -350,6 +350,8 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
|
|
|
0ab3a1 |
uregs.xbp <= fp_max - 1 * sizeof(UWord)/*see comment below*/ &&
|
|
|
0ab3a1 |
VG_IS_4_ALIGNED(uregs.xbp))
|
|
|
0ab3a1 |
{
|
|
|
0ab3a1 |
+ Addr old_xsp;
|
|
|
0ab3a1 |
+
|
|
|
0ab3a1 |
/* fp looks sane, so use it. */
|
|
|
0ab3a1 |
uregs.xip = (((UWord*)uregs.xbp)[1]);
|
|
|
0ab3a1 |
// We stop if we hit a zero (the traditional end-of-stack
|
|
|
0ab3a1 |
@@ -382,6 +384,7 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
|
|
|
0ab3a1 |
}
|
|
|
0ab3a1 |
}
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
+ old_xsp = uregs.xsp;
|
|
|
0ab3a1 |
uregs.xsp = uregs.xbp + sizeof(Addr) /*saved %ebp*/
|
|
|
0ab3a1 |
+ sizeof(Addr) /*ra*/;
|
|
|
0ab3a1 |
uregs.xbp = (((UWord*)uregs.xbp)[0]);
|
|
|
0ab3a1 |
@@ -393,6 +396,12 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
|
|
|
0ab3a1 |
if (debug) VG_(printf)(" cache FPUNWIND >2\n");
|
|
|
0ab3a1 |
if (debug) unwind_case = "FO";
|
|
|
0ab3a1 |
if (do_stats) stats.FO++;
|
|
|
0ab3a1 |
+ if (old_xsp >= uregs.xsp) {
|
|
|
0ab3a1 |
+ if (debug)
|
|
|
0ab3a1 |
+ VG_(printf) (" FO end of stack old_xsp %p >= xsp %p\n",
|
|
|
0ab3a1 |
+ (void*)old_xsp, (void*)uregs.xsp);
|
|
|
0ab3a1 |
+ break;
|
|
|
0ab3a1 |
+ }
|
|
|
0ab3a1 |
} else {
|
|
|
0ab3a1 |
fp_CF_verif_cache [hash] = xip_verified ^ CFUNWIND;
|
|
|
0ab3a1 |
if (debug) VG_(printf)(" cache CFUNWIND >2\n");
|
|
|
0ab3a1 |
@@ -406,6 +415,12 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
|
|
|
0ab3a1 |
} else {
|
|
|
0ab3a1 |
if (debug) unwind_case = "FF";
|
|
|
0ab3a1 |
if (do_stats) stats.FF++;
|
|
|
0ab3a1 |
+ if (old_xsp >= uregs.xsp) {
|
|
|
0ab3a1 |
+ if (debug)
|
|
|
0ab3a1 |
+ VG_(printf) (" FF end of stack old_xsp %p >= xsp %p\n",
|
|
|
0ab3a1 |
+ (void*)old_xsp, (void*)uregs.xsp);
|
|
|
0ab3a1 |
+ break;
|
|
|
0ab3a1 |
+ }
|
|
|
0ab3a1 |
}
|
|
|
0ab3a1 |
goto unwind_done;
|
|
|
0ab3a1 |
} else {
|
|
|
0ab3a1 |
commit 4520d562975820aced0fda6ed503379f337da66e
|
|
|
0ab3a1 |
Author: philippe <philippe@a5019735-40e9-0310-863c-91ae7b9d1cf9>
|
|
|
0ab3a1 |
Date: Wed Feb 17 22:41:14 2016 +0000
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
Fix incorrect (or infinite loop) unwind on RHEL7 amd64 64 bits.
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
Same kind of problems as explained and fixed in revision 15720:
|
|
|
0ab3a1 |
In some cases, unwinding always retrieves the same pc/sp/bp.
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
Fix for 64 bits is similar: stop unwinding if the previous sp is >= new sp
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15794 a5019735-40e9-0310-863c-91ae7b9d1cf9
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
|
|
|
0ab3a1 |
index 137e780..ef4984c 100644
|
|
|
0ab3a1 |
--- a/coregrind/m_stacktrace.c
|
|
|
0ab3a1 |
+++ b/coregrind/m_stacktrace.c
|
|
|
0ab3a1 |
@@ -607,16 +607,25 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
|
|
|
0ab3a1 |
* next function which is completely wrong.
|
|
|
0ab3a1 |
*/
|
|
|
0ab3a1 |
while (True) {
|
|
|
0ab3a1 |
+ Addr old_xsp;
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
if (i >= max_n_ips)
|
|
|
0ab3a1 |
break;
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
+ old_xsp = uregs.xsp;
|
|
|
0ab3a1 |
+
|
|
|
0ab3a1 |
/* Try to derive a new (ip,sp,fp) triple from the current set. */
|
|
|
0ab3a1 |
|
|
|
0ab3a1 |
/* First off, see if there is any CFI info to hand which can
|
|
|
0ab3a1 |
be used. */
|
|
|
0ab3a1 |
if ( VG_(use_CF_info)( &uregs, fp_min, fp_max ) ) {
|
|
|
0ab3a1 |
if (0 == uregs.xip || 1 == uregs.xip) break;
|
|
|
0ab3a1 |
+ if (old_xsp >= uregs.xsp) {
|
|
|
0ab3a1 |
+ if (debug)
|
|
|
0ab3a1 |
+ VG_(printf) (" CF end of stack old_xsp %p >= xsp %p\n",
|
|
|
0ab3a1 |
+ (void*)old_xsp, (void*)uregs.xsp);
|
|
|
0ab3a1 |
+ break;
|
|
|
0ab3a1 |
+ }
|
|
|
0ab3a1 |
if (sps) sps[i] = uregs.xsp;
|
|
|
0ab3a1 |
if (fps) fps[i] = uregs.xbp;
|
|
|
0ab3a1 |
ips[i++] = uregs.xip - 1; /* -1: refer to calling insn, not the RA */
|
|
|
0ab3a1 |
@@ -646,6 +655,12 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
|
|
|
0ab3a1 |
if (0 == uregs.xip || 1 == uregs.xip) break;
|
|
|
0ab3a1 |
uregs.xsp = uregs.xbp + sizeof(Addr) /*saved %rbp*/
|
|
|
0ab3a1 |
+ sizeof(Addr) /*ra*/;
|
|
|
0ab3a1 |
+ if (old_xsp >= uregs.xsp) {
|
|
|
0ab3a1 |
+ if (debug)
|
|
|
0ab3a1 |
+ VG_(printf) (" FF end of stack old_xsp %p >= xsp %p\n",
|
|
|
0ab3a1 |
+ (void*)old_xsp, (void*)uregs.xsp);
|
|
|
0ab3a1 |
+ break;
|
|
|
0ab3a1 |
+ }
|
|
|
0ab3a1 |
uregs.xbp = (((UWord*)uregs.xbp)[0]);
|
|
|
0ab3a1 |
if (sps) sps[i] = uregs.xsp;
|
|
|
0ab3a1 |
if (fps) fps[i] = uregs.xbp;
|