All of lore.kernel.org
 help / color / mirror / Atom feed
* longjmp question
@ 2011-10-07 23:22 Jurij Smakov
  2011-10-07 23:42 ` David Miller
                   ` (23 more replies)
  0 siblings, 24 replies; 25+ messages in thread
From: Jurij Smakov @ 2011-10-07 23:22 UTC (permalink / raw)
  To: sparclinux

Hello,

Over the last few days I had some quality time trying to track down 
the segfault in one of Ruby tests, involving continuations (which are 
implemented on top of setjmp/longjmp):

http://redmine.ruby-lang.org/issues/5244

After lots of experiments I came to a conclusion that something is 
wrong with libc (eglibc in this case) implementation of longjmp. In 
particular, this code from sysdeps/sparc/sparc32/__longjmp.S is used 
to perform the longjmp in the Ruby test:

[...]
#define RW_FP [%fp + 0x48]

ENTRY(__longjmp)
        /* Store our arguments in global registers so we can still
           use them while unwinding frames and their register windows.  */

        ld ENV(o0,JB_FP), %g3   /* Cache target FP in register %g3.  */
#ifdef PTR_DEMANGLE
        PTR_DEMANGLE (%g3, %g3, %g4)
#endif
[...]
LOC(thread):
        /*
         * Do a "flush register windows trap".  The trap handler in the
         * kernel writes all the register windows to their stack slots, and
         * marks them all as invalid (needing to be sucked up from the
         * stack when used).  This ensures that all information needed to
         * unwind to these callers is in memory, not in the register
         * windows.
         */
        ta      ST_FLUSH_WINDOWS
#ifdef PTR_DEMANGLE
        ld      ENV(g1,JB_PC), %g5 /* Set return PC. */
        ld      ENV(g1,JB_SP), %g1 /* Set saved SP on restore below. */
        PTR_DEMANGLE2 (%o7, %g5, %g4)
        PTR_DEMANGLE2 (%fp, %g1, %g4)
#else
        ld      ENV(g1,JB_PC), %o7 /* Set return PC. */
        ld      ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */
#endif
        sub     %fp, 64, %sp    /* Allocate a register frame. */
        st      %g3, RW_FP      /* Set saved FP on restore below. */
        retl
         restore %g2, 0, %o0    /* Restore values from above register frame. */

At the end of the procedure %g3 contains the target (post-jump) frame 
pointer address, which we would like to end up in %fp as a result of 
restore instruction in the retl delay slot. To that end we write it to 
a location determined by RW_FP, which is [%fp + 0x48]. However, 
according to http://www.sics.se/~psm/sparcstack.html, which nicely 
describes the layout of registers in memory and the effect of 
save/restore operations, the post-restore frame pointer value should 
be located at [%fp + 0x38], as we are only saving 16 word-sized 
registers, and %fp is 15-th out of them (see Figure 4), so offset 
should be 14 * 4 = 56 = 0x38. I'm not sure whether if that's just an 
off-by-0x10, or I don't understand how this things work - anyone has 
any ideas?
 
There are a lot of things here I don't understand. For example, Ruby 
test only fails if the code is compiled with -O2, but works with -O0,
and with -O0 we get the correct value of target frame pointer at
[%fp + 0x38], so it does not matter whether we write another one at
the "wrong" location. With -O2 though the memory layout is different, 
and we end up with broken value at [%fp + 0x38], and this is what gets 
restored into %fp, eventually causing a segfault. Also, it's probably 
not the whole story, because after changing the offset to 0x38 I still 
get a test failure, but it now segfaults in a different place. I could 
not, however, explain the 0x48 vs 0x38 discrepancy, so taking things 
one step at a time here :-).

Best regards,
-- 
Jurij Smakov                                           jurij@wooyd.org
Key: http://www.wooyd.org/pgpkey/                      KeyID: C99E03CC

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2011-10-23 20:35 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-07 23:22 longjmp question Jurij Smakov
2011-10-07 23:42 ` David Miller
2011-10-08  6:43 ` David Miller
2011-10-08 12:55 ` Jurij Smakov
2011-10-08 19:22 ` David Miller
2011-10-12 21:22 ` Jurij Smakov
2011-10-12 22:09 ` David Miller
2011-10-12 22:17 ` David Miller
2011-10-12 23:06 ` David Miller
2011-10-12 23:21 ` Jurij Smakov
2011-10-12 23:42 ` David Miller
2011-10-13 22:06 ` Jurij Smakov
2011-10-13 22:35 ` David Miller
2011-10-14 23:06 ` Jurij Smakov
2011-10-14 23:26 ` David Miller
2011-10-16 17:07 ` Jurij Smakov
2011-10-17  0:56 ` David Miller
2011-10-18 20:46 ` Jurij Smakov
2011-10-18 20:53 ` David Miller
2011-10-22  9:00 ` Jurij Smakov
2011-10-22  9:05 ` David Miller
2011-10-22  9:43 ` Jurij Smakov
2011-10-22 22:54 ` David Miller
2011-10-23 13:47 ` Jurij Smakov
2011-10-23 20:35 ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.