On Mon, Nov 14, 2011 at 5:02 PM, Paul Pluzhnikov <[email protected]> wrote:

> P.S. test-setjmp is failing for me (before or after the patch).
> When I enable assertions (to confirm my new assertions are correct), I see:
>
>  lt-test-setjmp: ../../src/dwarf/Gparser.c:754: apply_reg_state: \
>    Assertion `rs->reg[17].where == DWARF_WHERE_EXPR' failed.
>
> which likely explains that failure.

The problem is actually two-fold:

First, the loops in {sig,}longjmp.c are "do { ... } while (unw_step() >= 0);"

But unw_step() returns 0 on reaching the end of the chain (_start),
and the loop should stop there.

The second problem is that with this commit:
  
http://repo.or.cz/w/glibc.git/commitdiff/c67da0b50e3d20f89d7bb352cd67dcf66d808e50
glibc obfuscates value of SP in jmp_buf, so we might as well just give up.

Patch attached.

Thanks,
-- 
Paul Pluzhnikov
diff --git a/src/setjmp/longjmp.c b/src/setjmp/longjmp.c
index d056b1f..c9fb17b 100644
--- a/src/setjmp/longjmp.c
+++ b/src/setjmp/longjmp.c
@@ -35,6 +35,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.  */
 #include "jmpbuf.h"
 #include "setjmp_i.h"
 
+#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 4)
+
+/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the
+   register values in jmp_buf by XORing them with a "random"
+   canary value.
+
+   This makes it impossible to implement longjmp, as we
+   can never match wp[JB_SP], unless we decode the canary first.
+
+   Doing so is possible, but doesn't appear to be worth the trouble,
+   so we simply defer to glibc longjmp here.  */
+
+#else
+
 void
 _longjmp (jmp_buf env, int val)
 {
@@ -75,7 +89,7 @@ _longjmp (jmp_buf env, int val)
 
       abort ();
     }
-  while (unw_step (&c) >= 0);
+  while (unw_step (&c) > 0);
 
   abort ();
 }
@@ -90,4 +104,6 @@ longjmp (jmp_buf env, int val)
   _longjmp (env, val);
 }
 
+#endif  /* __GLIBC__  */
+
 #endif
diff --git a/src/setjmp/siglongjmp.c b/src/setjmp/siglongjmp.c
index da757e3..028c224 100644
--- a/src/setjmp/siglongjmp.c
+++ b/src/setjmp/siglongjmp.c
@@ -35,6 +35,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.  */
 # define _NSIG (_SIG_MAXSIG - 1)
 #endif
 
+#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 4)
+
+/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the
+   register values in jmp_buf by XORing them with a "random"
+   canary value.
+
+   This makes it impossible to implement longjmp, as we
+   can never match wp[JB_SP], unless we decode the canary first.
+
+   Doing so is possible, but doesn't appear to be worth the trouble,
+   so we simply defer to glibc siglongjmp here.  */
+
+#else
+
 void
 siglongjmp (sigjmp_buf env, int val)
 {
@@ -96,7 +110,9 @@ siglongjmp (sigjmp_buf env, int val)
 
       abort ();
     }
-  while (unw_step (&c) >= 0);
+  while (unw_step (&c) > 0);
 
   abort ();
 }
+
+#endif  /* __GLIBC__ */
_______________________________________________
Libunwind-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/libunwind-devel

Reply via email to