From: Jurij Smakov <jurij@wooyd.org>
To: sparclinux@vger.kernel.org
Subject: longjmp question
Date: Fri, 07 Oct 2011 23:22:10 +0000 [thread overview]
Message-ID: <20111007232209.GA11892@wooyd.org> (raw)
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
next reply other threads:[~2011-10-07 23:22 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-07 23:22 Jurij Smakov [this message]
2011-10-07 23:42 ` longjmp question 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20111007232209.GA11892@wooyd.org \
--to=jurij@wooyd.org \
--cc=sparclinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.