pdsc.h - Defines structures describing procedures conforming
to the Calling Standard for Alpha Systems .
#include <pdsc.h>
The pdsc.h header file defines two basic data structures:
the code range descriptor (crd) and the run-time procedure
descriptor (rpd).
Code range descriptors associate a contiguous sequence of
addresses with a run-time procedure descriptor. This mapping
can be many-to-one. Code range descriptors support
optimizations (for example, reducing cache collisions)
where all of the code for a procedure might not be contiguous.
Run-time procedure descriptors provide unwind
and exception handler information about a procedure or
part of a procedure. Several run-time procedure descriptors
might be needed if a procedure has multiple entry
points (as in FORTRAN).
Currently, one code range descriptor exists for each runtime
procedure descriptor. The assembler creates both the
crds and rpds. Crds are stored alone in address order in
the .pdata section of an object file. Rpds are stored
along with language generated exception information in the
.xdata section of an object file.
The assembler supports an .edata 0 directive to allow the
language or user to enter information into the .xdata section.
The .end assembler directive, which denotes the end of a
procedure, tells the assembler to generate the crd and rpd
for the ended procedure.
The .xdata and .pdata sections are coalesced in order from
multiple relocatable objects and non-shared libraries by
the linker into one large .xdata and one large .pdata section
for each executable or shared object. The linker
adds an extra element to the code range descriptors, whose
address is one address beyond the end of the text segment.
For a diagram of a code range descriptor, see the pdsc.h
file.
The begin_address field is shifted left 2 bits. Its position
is relative to the beginning of the whole code range
descriptor table. This shift enables a binary search of
these addresses. (If they were self relative like
rpd_offset, you have to calculate the actual address
before being able to do the compare.) This field definition
restricts the code range to be within 32 bits of the
code range descriptor table. This field is the first
address of a code range. The begin_address of the next crd
is one address beyond the bounds the code range from the
top. As stated above, the linker adds a last element.
The rpd_offset is a self-relative field that points to the
run-time procedure descriptor entry for this code range.
This field definition restricts the run-time procedure
descriptor to be within 32 bits of the code range descriptor
table. The rpd_offset field might equal zero if the
procedure is a null frame whose entry_ra is $26 and contains
no handler and PDSC_FLAGS_REGISTER_FRAME is set.
This condition implies no separate procedure descriptor.
The prologue bit is set if the code range does not contain
a prologue. This information is important in determining
which register to restore during an unwind operation.
All the structure definitions have simple typedefs to
define the fields in case they need to have idfefs processed
to differentiate the code on the basis of the hardware
architecture. See the pdsc.h header file for their
specific definitions.
The pdsc.h header file provides a union that allows for
accessing the two main fields as 32 bit items. The header
file also provides macros to help use those 32 bit items.
The union definition for code range descriptors follows:
/*
* Runtime Code Range Descriptor
*/ typedef union pdsc_crd {
struct {
pdsc_offset begin_address;
/* offst to 1st address in
range */
pdsc_offset rpd_offset;
/* offst to rpd including bits
*/
} words;
struct {
pdsc_mask context_t:1;
/* flags to be used with
no_prolog */
pdsc_mask context_s:1;
/* to determine actual meaning
*/
pdsc_offset shifted_begin_address:30; /* shifted
left 2 */
pdsc_mask no_prolog:1; /* flag */
pdsc_mask memory_speculation:1; /* flag */
pdsc_offset shifted_rpd_offset:30; /* shifted
left 2 */
} fields;
} pdsc_crd;
Run-time procedure descriptors come in a number of variations.
The Tru64 UNIX operating system supports a short
form and a long form and each may or may not have handler
information. Tru64 UNIX supports a short form (and the no
procedure descriptor form mentioned in the code range
descriptors discussion) to minimize the space required for
exception and unwind information. Tru64 UNIX supports a
long form for procedures whose information overflows the
fields in the short form.
Tru64 UNIX also supports register frames that do not manifest
a stack frame and may use temporary registers to save
the ra. Manual collusion between a caller and callee is
required to support the use of temporary registers for
intrinsic and library functions to save the cost of stores
and restores to and from memory.
See the pdsc.h header file for diagrams of the short and
long forms of the descriptors.
The pdsc.h header file provides a union that embodies the
different options discussed above. The union definition
for run-time procedure descriptors is: typedef union
pdsc_rpd {
struct pdsc_short_stack_rpd {
pdsc_uchar_mask flags:8;
/* information about frame */
pdsc_uchar_offset rsa_offset;
/* savregs offst in quadwords
*/
pdsc_uchar_mask fmask:8;
/* floating point reg mask */
pdsc_uchar_mask imask:8;
/* integer register mask */
pdsc_count frame_size:16;
/* frame size in 64 bit words
*/
pdsc_offset sp_set:8;
/* instofset to inst which sets
sp */
pdsc_count entry_length:8;
/* # of insts in prologue */
} short_stack_rpd;
struct pdsc_short_reg_rpd {
pdsc_uchar_mask flags:8;
/* information about frame */
pdsc_space reserved1:3; /* must be zero */
pdsc_register entry_ra:5;
/* what contains ra on entry */
pdsc_register save_ra:5;
/* entry_ra here after the prologue
*/
pdsc_space reserved2:11; /* must be zero */
pdsc_count frame_size:16;
/* frame size in 64 bit words
*/
pdsc_offset sp_set:8;
/* instofset to inst which sets
sp */
pdsc_count entry_length:8;
/* # of insts in prologue */
} short_reg_rpd;
struct pdsc_long_stack_rpd {
pdsc_mask flags:11;
/* information about frame */
pdsc_register entry_ra:5;
/* where ret pc is on entry */
pdsc_ushort_offset rsa_offset;
/* saveregs offst in quadwords
*/
pdsc_count sp_set:16;
/* instofset to inst which sets
sp */
pdsc_count entry_length:16;
/* # of insts in prologue */
pdsc_count frame_size;
/* frame size in quadwords */
pdsc_mask reserved:2; /* must be zero
*/
pdsc_offset return_address:30;
/* offset from base to return
for
inserted code */
pdsc_mask imask;
/* integer register mask */
pdsc_mask fmask;
/* floating point register mask
*/
} long_stack_rpd;
struct pdsc_long_reg_rpd {
pdsc_mask flags:11;
/* information about frame */
pdsc_register entry_ra:5;
/* where ret pc is on entry */
pdsc_register save_ra:5;
/* we moved entry_ra in the
prologue */
pdsc_space reserved1:11; /* must be zero */
pdsc_count sp_set:16;
/* instofset to inst which sets
sp */
pdsc_count entry_length:16;
/* # of insts in prologue */
pdsc_count frame_size;
/* frame size in quadwords */
pdsc_mask reserved:2; /* must be zero
*/
pdsc_offset return_address:30;
/* offset from base to return
for
inserted code */
pdsc_mask imask;
/* integer register mask */
pdsc_mask fmask;
/* floating point register mask
*/
} long_reg_rpd;
struct pdsc_short_with_handler {
union {
struct pdsc_short_stack_rpd short_stack_rpd;
/* base stack rpd */
struct pdsc_short_reg_rpd short_reg_rpd;
/* base stack rpd */
} stack_or_reg;
pdsc_address handler;
/* optional handler address */
pdsc_address handler_data;
/* optional handler data */
} short_with_handler;
struct pdsc_long_with_handler {
union {
struct pdsc_long_stack_rpd long_stack_rpd;
/* base stack rpd */
struct pdsc_long_reg_rpd long_reg_rpd;
/* base stack rpd */
} stack_or_reg;
pdsc_address handler;
/* optional handler address */
pdsc_address handler_data;
/* optional handler data */
} long_with_handler;
} pdsc_rpd; /* runtime procedure descriptor
*/
As noted in the preceding code fragment, the flags field
is a different length depending on whether a long or short
descriptor is used. Consequently, the most used flags are
grouped together so that they fit in the short frame.
Use the PDSC_FLAGS_EXCEPTION_FRAME flag to trace back over
signal frames.
The PDSC_FLAGS_EXTENDER flag is not yet implemented and is
reserved
The header file defines a set of macros that easily enable
users to access fields. Some macros provide support so
users do not have to know whether they are using a short
or long descriptor or even a stack frame as opposed to a
register frame. The header file will also normalize the
fields between descriptor types (for example, the register
mask will be expanded to 32 bits).
A null value for the rpd argument can cause some of the
macros to provide the default values. This provision of
default values supports the case where the pdsc_crd does
not point at any rpd and is denoted by No rpd.
In the following table, each macro carries a PDSC_ prefix,
which is omitted in the table to conserve space. Where
there is no default value (such as for a handler), a zero
(0) is returned when the value is not present. In the
second column, Support, N means no rpd, S means support
for stack, R means support for register, H means support
for short, and L means support for long.
------------------------------------------------------------------------------
PDSC_ Macro Support Arg Comments
------------------------------------------------------------------------------
SHORT_RPD_SIZE None Size of a short without
handler information.
LONG_RPD_SIZE None Size of a long without
handler information.
DEFAULT_ENTRY_RA None $26, the default return
address register.
RPD_SHORT SRHL &rpd 1 if it is a short rpd;
otherwise 0.
RPD_REGISTER SRHL &rpd 1 if it is a register frame;
otherwise 0.
RPD_HAS_HANDLER SRHL &rpd 1 if there is handler
information; otherwise 0.
RPD_FLAGS SRHL &rpd Flags field.
RPD_RSA_OFFSET_FIELD NSRHL &rpd rsa_offset field value.
RPD_RSA_OFFSET NSRHL &rpd rsa_offset in bytes.
RPD_SAVE_RA NSRHL &rpd save ra register.
RPD_ENTRY_RA NSRHL &rpd entry ra register.
RPD_SIZE_FIELD NSRHL &rpd frame_size field value.
RPD_SIZE NSRHL &rpd Frame size in bytes.
RPD_SP_SET_FIELD NSRHL &rpd sp_set field value.
RPD_SP_SET NSHRL &rpd sp_set offset in bytes.
RPD_ENTRY_LENGTH_FIELD NSHRL &rpd entry_length
field value.
RPD_ENTRY_LENGTH NSHRL &rpd Prologue size in bytes.
RPD_IMASK NSHRL &rpd 32 bit saved int
register mask.
RPD_FMASK NSHRL &rpd 32 bit saved fp
register mask.
RPD_HANDLER NSHRL &rpd Handler address.
RPD_HANDLER_DATA NSHRL &rpd Handler data address.
RPD_RETURN_ADDRESS_FIELD SRL &rpd Return address field value.
RPD_RETURN_ADDRESS SRL &.pdata The return address for an
&rpd inserted code range.
CRD_OFFSET_MASK none Masks off the lsb two bits.
CRD_NO_PROLOG_MASK none Masks all but the lsb bit.
CRD_PRPD &crd Pointer to the rpd for
this crd.
CRD_CONTAINS_PROLOG &crd 1 if it does;
0 if not.
CRD_BEGIN_ADRESS_FIELD &crd Begin address field value.
CRD_BEGIN_ADDRESS &.pdata ptr to the first address
in the code range.
&crd
CRD_TYPE_STANDARD &crd 1 if this is a standard type
code range descriptor; 0 if
not.
CRD_TYPE_CONTEXT &crd 1 if this is a context type
code range descriptor that
does not contain the procedure
prolog; 0 if not.
CRD_TYPE_DATA &crd 1 if the code range descriptor
describes data that
resides within the text
area; 0 if not.
CRD_TYPE_NON_CONTEXT &crd 1 if the code range is not
in a routine context, and it
does not contain a stack
allocation that needs to be
deallocated; 0 if not.
CRD_TYPE_NON_CONTEXT_STACK &crd 1 if the code range is a
non-context region for
exception handling, and it
contains a stack allocation;
0 if not.
INST_OFFSET_SHIFT Amounts to << insts to
a get # of bytes.
FRAME_SIZE_SHIFT Amounts to << frame siz
to a get # of bytes
SHORT_RPD_IMASK_SHIFT Amounts to << short imsk
to the position bits.
SHORT_RPD_FMASK_SHIFT Amounts to << short fmsk
to the position bits.
------------------------------------------------------------------------------
exception_intro(3) delim off
pdsc(4)
[ Back ] |