libunwind-devel
[Top][All Lists]
Advanced

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

Re: [libunwind] Alloc and saving the return address


From: David Mosberger
Subject: Re: [libunwind] Alloc and saving the return address
Date: Mon, 8 Dec 2003 10:46:44 -0800

Hi Johan,

Answering the last question first...

>>>>> On Mon, 08 Dec 2003 18:24:54 +0100, Johan Walles <address@hidden> said:

  Johan> Here's the top of a dynamically generated Java method:

  Johan> (gdb) disass 0x2000000062730010 0x2000000062730140
  Johan> Dump of assembler code from 0x2000000062730010 to 0x2000000062730140:
  Johan> 0x2000000062730010:    [MII]       alloc r32=ar.pfs,5,4,0
  Johan> 0x2000000062730011:                mov r33=b0
  Johan> 0x2000000062730012:                adds r12=-16,r12
  Johan> 0x2000000062730020:    [MII]       add r35=r1,r0
  Johan> 0x2000000062730021:                adds r34=40,r13;;
  Johan> 0x2000000062730022:                nop.i 0x0
  Johan> 0x2000000062730030:    [MMI]       ld8 r34=[r34];;
  Johan> 0x2000000062730031:                adds r15=104,r34
  Johan> 0x2000000062730032:                nop.i 0x0;;
  Johan> 0x2000000062730040:    [MMI]       ld8 r15=[r15];;

  Johan> The alloc instruction is first and the saving of the return
  Johan> address comes second.  AFAIU, I should use
  Johan> _U_dyn_op_save_reg() to tell libunwind about the two
  Johan> instructions.

Yes.  You'd also need to describe the fact that the third instruction is
allocating a stack-frame.  So you'd need three directives.  Something
along the lines of these should do:

 _U_dyn_op_save_reg (&region->op[0], _U_QP_TRUE, 0, UNW_IA64_AR_PFS,
                     UNW_IA64_GR + 32);
 _U_dyn_op_save_reg (&region->op[1], _U_QP_TRUE, 1, UNW_IA64_RP,
                     UNW_IA64_GR + 33);
 _U_dyn_op_add (&region->op[2], _U_QP_TRUE, 2, UNW_REG_SP, -16);

First one says: the instruction is not predicated (always enabled,
i.e., _U_QP_TRUE), it's instruction 0 in the region, and it saves
ar.pfs in r32.  Second one says: the instruction is not predicated,
it's instruction 1 in the region, and it saves the return-pointer (rp)
in r33.  Third one says: the instruction is not predicated, it's
instruction 2 in the region, and it adds -16 to the stack-pointer.

You didn't show the epilogue, but obviously you'll have to restore the
stack-pointer before returning to the caller.  That needs to be described
with:

        _U_dyn_op (&region->op[3], _UP_QP_TRUE, N, 1);

This says: the stack-pointer gets restored by instruction N, counting
from the end of the region and undoes the effect of one prologue (the
last parameter would only ever be > 1 if you had multiple nested
regions).  NOTE: you can't just use another _U_dyn_op_add () here,
because restoring the stack-pointer also has the side-effect of
invalidating any saves that may have been done in the stack-frame.

  Johan> However, there is no guarantee that either the alloc or the
  Johan> mov r33=b0 is first in the method.  Currently we don't move
  Johan> any of them, but because of instruction scheduling the save
  Johan> of the return address will start moving around rsn.

As long as you keep track of how the instructions move around, that's
OK.  Just be sure to emit the right instruction number in the
corresponding _U_dyn_ directive.  Note that for the purposes of
unwinding, each bundle is counted as having exactly three
instructions, even for MLX bundles, which have only two instructions
in them.

  Johan> What do I do in this case?  Should I tell libunwind about two
  Johan> regions with one instruction in each?  If so, and assuming
  Johan> either of the two instructions can be some place other than
  Johan> the first slot in a bundle, how do I address them?

A single region is fine.  Just use the "when" parameter to the _U_dyn
directives to indicate when a directive takes effect.  Hopefully, the
above example helps clarify this.

        --david


reply via email to

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