[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [libunwind] Unwinding using the context passed to a signal handler (
From: |
Johan Walles |
Subject: |
Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work) |
Date: |
Thu, 25 Mar 2004 11:04:34 +0100 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 |
David Mosberger wrote:
On Wed, 24 Mar 2004 10:53:12 +0100, Johan Walles <address@hidden> said:
Johan> 1 foo() {
Johan> 2 getcontext();
Johan> 3 }
Johan> 4
Johan> 5 main() {
Johan> 6 foo();
Johan> 7 }
Johan> Inside of foo(), b0 will point to line 7.
Wrong. On _entry_ to foo() b0 will point to line 7. After the call
to getcontext(), b0 will point to line 3.
My point is that "getcontext(&ctxt); ctxt.uc_mcontext.sc_br[0]" gives me the
value 3 that b0 has inside of getcontext(), not the value 7 that b0 has inside
of foo() (aka "the call site").
Johan> case UNW_IA64_IP: addr = &uc->uc_mcontext.sc_br[0]; break;
This says is that the IP of the caller of
getcontext() is stored in sc_br[0]. Could it be stored in sc_ip
instead? Sure. What would it change? Absolutely nothing.
What it would change is that I could then take a signal context that I get from
the Linux kernel, fill in the missing registers, pass the result to
unw_init_local() and get a complete stack trace, including the first stack
frame. If this doesn't matter to you, could you please change it for my sake?
I think the issue here is that we're approaching the whole context handling from
different perspectives.
I guess that from your point of view, libunwind is an abstraction layer on top
of context structs, and that accesses to all fields in the context should go
through libunwind.
From my point of view, libunwind is a secondary way of accessing contexts. For
our primary use (of walking Java stacks and throwing exceptions), we have our
own unwinding code. Thus, we want to be able to access contexts by directly
accessing fields in the struct (be it sigcontext or ucontext_t).
An example of when these views clash is the C program I sent with my last
e-mail. If I set the sc_ip in the context to 0x42, pass it to libunwind and ask
about the IP I get NULL back. From my perspective, I should have gotten 0x42
back. Had I instead first initialized libunwind with an empty context, set the
IP to 0x42 and then asked about it I would have got 0x42 back (as expected),
which I imagine is enough from your perspective.
And if JRockits unwinding was entirely libunwind based, that would have been
enough for me too.
a signal
context is a very different animal from the ucontext_t returned by
unw_getcontext(). The former captures the "asynchronous state"
(mostly scratch register), the latter the "synchronous state" (mostly
preserved registers).
Another difference is that the Linux kernel puts the IP in the sc_ip field of
the sigcontext, but if I understand you correctly the ucontext_t is supposed to
have the IP in the sc_br[0] field. This makes it impossible to walk the stack
starting from a signal context, with or without the rest of the registers filled
in. Libunwind will miss / skip the first frame.
If I re-phrase my question thusly; if I have a signal context, what should I do
with it to be able to pass it to libunwind and have libunwind give me all stack
frames, including the first one? Filling in all the missing registers doesn't
help, as libunwind expects to find the IP in sc_br[0], but the Linux kernel
gives me a context where the IP is stored in sc_ip. How do I convert between a
struct sigcontext and an ucontext_t?
Could you post an example of how my unwind.c could be modified to do that very
conversion correctly?
The attached program has the following output:
"
Here's a stack trace using the signal context with all extra registers filled
in:
printStackTrace(): Got context at 0x60000fffffff95b0
printStackTrace(): Context sc_ip is 0x40000000000022c0
0: 0x4000000000002330: main()
1: 0x200000000008c560: __libc_start_main()
2: 0x4000000000001420: _start()
Here's a stack trace using the raw signal context:
printStackTrace(): Got context at 0x60000fffffffae20
printStackTrace(): Context sc_ip is 0x40000000000022c0
0: 0x4000000000002330: main()
1: 0x200000000008c560: __libc_start_main()
2: 0x4000000000001420: _start()
Here's a stack trace using the raw signal context with the sc_ip moved to
sc_br[0]:
printStackTrace(): Got context at 0x60000fffffffa010
printStackTrace(): Context sc_ip is (nil)
0: 0x40000000000022c0: crash()
unw_step_ptr: Bad register number
Here's a stack trace using an unmodified context from getcontext():
printStackTrace(): Got context at 0x60000fffffff8b50
printStackTrace(): Context sc_ip is (nil)
0: 0x4000000000001b60: crashhandler()
1: 0xa0000000000040d0: Unknown
2: 0x40000000000022c0: crash()
3: 0x4000000000002330: main()
4: 0x200000000008c560: __libc_start_main()
5: 0x4000000000001420: _start()
"
A correct stack trace would have said:
0: 0x40000000000022c0: crash()
1: 0x4000000000002330: main()
2: 0x200000000008c560: __libc_start_main()
3: 0x4000000000001420: _start()
Using the signal context with all extra registers filled in with values I get
from getcontext() doesn't help (which I thought you said it would). If you find
any errors in the code for this, it would be *great* if you could point them out
to me.
Using the raw signal context doesn't help either (which is what we're debating).
Using the raw signal context, but storing the sc_ip I got from the kernel in
sc_br[0] works for the first frame, but then libunwind gets lost.
Using the result of getcontext() works if we skip a few frames.
However, I would *really* want to base the unwinding on the signal context,
possibly transformed in any number of ways. How do I convert between from a
sigcontext to an ucontext_t? I have added all missing registers, now I want to
know *what else* I have to do?
Regards //Johan
PS: I'm subscribed to the mailing list, so you don't need to include me
personally among the recipients.
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), (continued)
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Matthieu Delahaye, 2004/03/22
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Johan Walles, 2004/03/23
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), David Mosberger, 2004/03/23
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Johan Walles, 2004/03/24
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), David Mosberger, 2004/03/24
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work),
Johan Walles <=
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Matthieu Delahaye, 2004/03/25
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Johan Walles, 2004/03/25
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Matthieu Delahaye, 2004/03/25
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Johan Walles, 2004/03/26
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), David Mosberger, 2004/03/25
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), David Mosberger, 2004/03/25
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Johan Walles, 2004/03/26
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Young, Mark, 2004/03/26
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), David Mosberger, 2004/03/26
- Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work), Young, Mark, 2004/03/26