When the assembler sees procedure directives such as .ENTER or
.LEAVE, it builds fixup requests for the linker. Using the information
in these fixup requests, the linker builds a 4-word unwind descriptor for each
unwind region. These descriptors monitor a particular code address range,
typically an entire procedure. The unwind descriptors provide information about
the stack size, registers usage, and the lengths of the entry and exit
sequences. The linker sorts these entries in the increasing order of code
addresses and places them in a separate subspace.
Here is a C language declaration of the unwind descriptor.
struct unwind_table_entry {
unsigned int region_start; /* Word 1 */
unsigned int region_end; /* Word 2. */
unsigned int Cannot_unwind:1; /* Word 3. */
unsigned int Millicode;1;
unsigned int Millicode_save_sr0:1;
unsigned int Region_description:2;
unsigned int reserved1:1;
unsigned int Entry_SR:1;
unsigned int Entry_FR:4;
unsigned int Entry_GR:5;
unsigned int Args_stored:1;
unsigned int Variable_Frame:1;
unsigned int Separate_Package_Body:1;
unsigned int Frame_Extension_Millicode:1;
unsigned int Stack_Overflov_Check:1;
unsigned int Two_Instruction_SP_Increment:1;
unsigned int Ada_Region:1;
unsigned int reserved2:4;
unsigned int Save_SP:1;
unsigned int Save_RP:1;
unsigned int Save_MRP_in_frame:1;
unsigned int reserved3:1;
unsigned int Cleanup_defined:1;
unsigned int MPE_XL_interrupt_marker:1; /* Word 4 */
unsigned int BP_UX_interrupt~arker:1;
unsigned int Large_frame_r3:1;
unsigned int reserved4:2;
unsigned int Total_frame_size:27;
};
Each of the fields in this structure are used as follows:
Cannot_unwind: One if this region does not follow
unwind conventions and is therefore not unwindable; zero otherwise.
(Creation of non-unwindable assembly code is strongly
discouraged.)
Millicode: One if this region is a millicode
routine; zero otherwise.
Millicode_save_sr0: One if this (millicode) routine
saves sr0 in its frame (at curren_SP - 16); zero otherwise.
Region_description: Describes the code between the
starting and ending offsets of this region:
00: Normal (entry point at start of region, exit point at end;
contains no other entry /exit points)
01: Entry point only (contains no exit point)
10: Exit point only (contains no entry point)
11: Discontinuous (contains no entry or exit point)
Normal context is code that falls between the last entry point and
first exit point of a routine.
Entry point only context is code that makes up an alternate entry
point. It consists of entry code inserted by the assembler or
compiler as well as user code. It does not contain exit code.
Exit point only context is code that makes up an alternate exit
point. It consists of exit code inserted by the assembler or
compiler as well as user code. It does not contain entry code.
Discontinuous context is code within an assembled or compiled routine
that is either not preceded by some entry point or not followed by
some exit point.
One unwind table entry is generated per routine, plus one for each
additional entry point, exit point, and discontinuous region.
Normally, all unwind descriptors are identical except for the
Region_description field. The entry and exit points to any region are
marked using the .ENTRY and .EXIT assembler
directives.
Entry_SR: One if the sole entry-save space register
sr3 is saved/restored by the associated entry/exit code sequence;
zero otherwise.
Entry_FR: The number of entry-save floating-point
registers saved/restored by the associated entry/exit code
sequence.
Entry_GR: The number of entry-save general registers
saved/restored by the associated entry/exit code sequence. Note that
the semantics of this field are different from those of the similarly
named field of the .CALLINFO directive to the assembler. For
example, a value of 5 in this field would mean that gr3 through gr7
(inclusive) have been saved in the entry save code.
Arqs_stored: One if this region's prologue includes
storing any arguments to the routine in memory in the architected
locations; zero otherwise. (Note: this bit may not be correct if the
associated routine was compiled with optimization, as the optimizer
may remove initial stores of arguments, but will never clear this
bit.)
Variable_Frame: Indicates that this region's frame may
be expanded during the region's execution (using the Ada dynamic
frame facility). Such frames require different unwinding
techniques.
Separate_Packaqe_Body: Indicates the associated region
is an Ada separate package body. It has no frame of its own, but uses
space in a parent frame to save RP and spill any entry save
registers.
Frame_Extension_Millicode: Indicates the associated
region is a special millicode routine which implements the Ada frame
extension operation.
Stack_Overflow_Check: Indicates the associated region
has an Ada stack overflow check in its entry sequence(s).
Two_Instruction_SP_Increment: Indicates the associated
(Ada) region had a large frame such that two instructions were
necessary to produce that portion of the frame increment which cannot
be deduced from the frame size field in the unwind descriptor.
Ada_Region: One if the associated region should be
treated as an Ada routine. Currently this bit is intended for use by
the Ada exception handler.
Save_SP: One if the entry value of SP is saved by this
region's entry sequence in the current frame marker (current_SP - 4);
zero otherwise.
Save_RP: For non-millicode, one if the entry value of
RP is saved by the entry sequence in the previous frame (at
previous_SP - 20); zero otherwise. For millicode, one if the entry
values of MRP and sr0 are saved by the entry sequence in the current
frame (at current_SP - 20 and current_SP - 16, respectively); zero
otherwise. If this bit is one, the Save_MRP_in_frame and
Millicode_save_sr0 bits are ignored.
Save_MRP_in_frame: One if the entry value of MRP is
saved by the entry code in the current frame (at current_SP - 20);
zero otherwise. Applies only to millicode.
Cleanup_defined: The interpretation of this field is
dependent upon the language processor which compiled the routine.
MPE_XL_interrup_marker: One if the frame layout
corresponds to that of an MPE XL interrupt marker.
HP_UX_interrup_marker: One if the frame layout
corresponds to that of an HP-UX interrupt marker.
Large_frame_r3: One if gr3 is changed during the entry
sequence to contain the address of the base of the (new) frame.
Total frame size: The amount of space, in 8-byte units,
added to SP by the entry sequence of this region. This space includes
register save and spill areas, as well as padding. This quantity is
needed during unwinding to locate the entry-save register save area.
It is also used to determine the value of previous_SP if it was not
saved in the stack marker.