Blame SOURCES/valgrind-3.11.0-x86_unwind.patch

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;