Re: [PATCH] S/390 DWARF-2 CFI frame support

Ulrich Weigand
2003-12-05T17:54:10Z

Andrew Cagney wrote:

> What does the CFI output look like here? (I'm mainly curious but it
> always helps to have concrete examples).

First some information on our platform: we have a 'Program Status Word'
that contains amongst some other data the instruction address (PC).
We also have 16 general purpose registers %r0 .. %r15. The ABI
reserves register %r15 as stack pointer and register %r14 as function
call return address.

A function call (on 64-bit; 31-bit is similiar but a bit more tedious)
looks basically like this:

brasl %r14, func

The BRANCH RELATIVE LONG AND SAVE (brasl) instruction saves the current
instruction address from the PSW into the specified register, in this
case %r14, and then loads the specified target address, in this case
the address of func, into the instruction address field of the PSW.
(The target address is actually encoded relative to the current PC,
but that doesn't matter here.)

The called function now typically looks like that:

stmg %r6,%r15,48(%r15) (STORE MULTIPLE)
aghi %r15,-160 (ADD IMMEDIATE)

...

lmg %r6,%r15,208(%r15) (LOAD IMMEDIATE)
br %r14 (BRANCH REGISTER)

The prolog stores all call-saved registers, including the return address
%r14 and the old stack pointer %r15 into a register save area on the
stack (allocated but unused by the caller), and subsequently decrements
%r15 to allocate its own stack frame.

The function epilog restores all call-clobbered registers, including
the return register %r14 and the stack pointer %r15 (note that this
-as a side effect- pops the stack frame), and finally branches back
to the return address, which now again resides in register %r14.

The CFI looks about like this:

00000000 00000014 00000000 CIE
Version: 1
Augmentation: "zR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 14
Augmentation data: 1b

DW_CFA_def_cfa: r15 ofs 160
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop

00000018 0000001c 0000001c FDE cie=00000000 pc=000208c0..0002090e
DW_CFA_advance_loc: 6 to 000208c6
DW_CFA_offset: r15 at cfa-40
DW_CFA_offset: r14 at cfa-48
DW_CFA_offset: r13 at cfa-56
DW_CFA_offset: r12 at cfa-64
DW_CFA_offset: r11 at cfa-72
DW_CFA_advance_loc: 8 to 000208ce
DW_CFA_def_cfa_offset: 320

Note that we start out (at function entry) with a CFA of %r15 + 160,
i.e. the CFA points to the top of the save area that our caller has
allocated for us. The CFI describes where the registers, including
%r14 and %r15 are saved. After the AGHI, the CFA is now at %r15 +
320.

To properly unwind this stack frame, we needs to restore all registers
that are described by DW_CFA_offset records. Note that this includes
the stack pointer itself, and %r14. To unwind the PC, however, we
need to copy the value in %r14 *after that was already unwound* into
the PC register (PSW address). This is why we set the return address
column to 14 (which denotes %r14 according to the DWARF-2 register
numbering), which should have just that effect.

Now, in the case of a leaf function with no stack frame, things look
a bit different:

...

br %r14

There is no prologue at all, and the epilogue consists simply of a
branch to register %r14. Such a function would have an empty CFI
record. To unwind that, it is to be interpreted as follows: assume
all call-clobbered registers (*including* both return address (%r14)
and stack pointer (%r15)) as having the same value, and then move
the unwound (i.e. unchanged) value of %r14 into the PC register.

(There are other combinations possible: there might be saved registers
even in a leaf function, and these might include %r14. Then, %r14
would need to be restored from the stack, while %r15 would still need
to be left unchanged.)

I hope this clarifies the sitation on our platform.

Bye,
Ulrich

--
Dr. Ulrich Weigand
weigand@informatik.uni-erlangen.de