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: Johan Walles
Subject: Re: [libunwind] Unwinding using the context passed to a signal handler (doesn't work)
Date: Fri, 26 Mar 2004 08:29:51 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624

Matthieu Delahaye wrote:
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.

Quoting the Intel IA-64 Architecture Software Developer's Manual Volume 3: Instruction Set Reference, Revision 1.1, July 2000, page 2-9, describing what different branch instructions do:

"
[br.]call:
[...]
  * A return link value is placed in [the indicated branch register]
"

If you look at the C source on page 2-14, you'll see that the exact value placed in the branch register is IP + 16.

So the branch register is filled in with IP+16 by the call instruction. Before the call instruction is executed, b0 (in our example) still contains 7.

I'm wondering what is the most efficient: unwinding or filling correctly
the registers.

In our case, since walking the C stack happens *very* seldom, fixing up the sigcontext information could take up to something like 50ms per context and still be worth it.

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.

If finding out where the return address was stored was indeed impossible, as you seem to suggest, returning from a signal handler would never work. It does. So it's doable.

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

I hope I haven't been saying that because I don't think it *always* does. It has just happened to do that in all of my examples.

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.

Everything supposed to be on the stack already is. It has been put there by the function that received the signal.

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

I was kind of hoping libunwind would take care of that part for me.

  Regards //Johan



reply via email to

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