libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [libunwind] Unwinding using the context passed to a signal handler (


From: Matthieu Delahaye
Subject: Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work)
Date: Thu, 25 Mar 2004 17:41:34 +0100
User-agent: Mutt/1.5.4i

On Thu, Mar 25, 2004 at 05:00:52PM +0100, Johan Walles wrote:
> Matthieu Delahaye wrote:
> >On Thu, Mar 25, 2004 at 11:04:34AM +0100, Johan Walles wrote:
> >
> >>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").
> >
> >This is false. At the return of getcontext() b0 is still to 3. AFAIK, b0 
> >should
> >be restored by the callee [It is a scratch register, not a preserved].
> >The only garanty that b0 is to 7 is at the _entry_ of the function, and
> >at the return.
> 
> The value of b0 when getcontext() returns doesn't matter.
> 
> My interpretation of "b0's value at the call site" is "the value of b0 just 
> before the call was made".  Right before getcontext() is called, b0 
> contains 7.
False again. At the call of getcontext, b0 already contains 3 so that
the called function (getcontext) can return correctly to this point.

> 
> >>>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?
> >
> >There is something I don't understand. First you are complaining that the
> >context you get is a machine-state you say is corresponding to a state 
> >inside
> >of getcontext()
> 
> Yes.
> 
> >[And thus after a step you get the one from foo()]
> 
> Yes.
> 
> >, and now
> >you want to use the context sended by the kernel,
> 
> Yes.
> 
> >and add yourself the missing
> >information so that by unwinding, you get foo() inside?
> 
> I don't understand this question.  My problem is only this:
> 
> When my program receives a SIGSEGV, the Linux kernel passes a sigcontext 
> struct to my signal handler.  Passing the contents of that struct to 
> unw_init_local() makes libunwind miss / skip / whatever the function where 
> the signal was received.
Ok.

> 
> I want to know what I have to do to the sigcontext before I pass it to 
> unw_init_local() if I want libunwind to give me a complete stack trace.


> 
> So far, the two suggestion I have gotten has been to fill in the rest of 
> the registers (which either I'm doing wrong or doesn't help), and to use 
> getcontext() and step using libunwind every time a signal is received 
> (which I don't want to for performance reasons).
I'm wondering what is the most efficient: unwinding or filling correctly
the registers.

> There *must* be some sort 
> of relation between the signal context I get from the kernel and the 
> context I'm supposed to pass to libunwind.
> 
> So far, nobody has been able to explain that relation to me.
> 

I'm not really thinking this is possible in fact. To unwind, you need to
know certain values (including the return link). If the return link is
set into b0 at the begining of each function, you have no garantee they
are kept inside of these registers along the function body. 

So you cannot assert "B0 always contains" the return link. And this true for
all others registers. 

That's why unwind tables exist. They say for
example: Inside this IP range, the return link is inside of B0, inside
of this IP range, the return link is into the stack, at SP+8 (this
expression is wrong, it is just an example). 

So if you want to use libunwind for unwinding, you need to ensure that
values are at the correct place, and not necesseraly inside of
registers, but on stack location too, if this is relevant.

Of course, you'll have to read the unwind table too to reconstruct it.

So now think again about performance: what is the fatest? Rebuild
register values and stack content, or use getcontext, and step back
until you detect the signal frame?

Matthieu
>   Regards //Johan
> 
> _______________________________________________
> libunwind mailing list
> address@hidden
> http://www.hpl.hp.com/hosted/linux/mail-archives/libunwind/

-- 
It were not best that we should all think alike; it is difference of opinion
that makes horse-races.
                -- Mark Twain, "Pudd'nhead Wilson's Calendar"


reply via email to

[Prev in Thread] Current Thread [Next in Thread]