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