Every procedure, except for null frame procedures, must have an associated procedure descriptor. (Null frame procedures are discussed in Section 3.1.4.)
The term procedure descriptor also appears in the chapter on the symbol table in the Assembly Language Programmer's Guide. The use of the term in that manual refers to a structure defined in the file /usr/include/sym.h and should not be confused with procedure descriptors used for exceptions, as described in this Digital UNIX calling standard. Note
This chapter covers the following procedure-descriptor topics:
Code range descriptors
associate a contiguous
sequence of addresses with a run-time procedure descriptor. This mapping
can be many-to-one.
Run-time procedure descriptors
provide descriptive information
about a procedure or part of a procedure.
Several run-time procedure descriptors might be needed if the procedure
has multiple entry points, as in FORTRAN. In this case, each entry point consists
of the following elements:
Although the prologues might contain different code, they must all achieve
the same effect: the same registers saved at the same offset, the same frame
size, and so on. There is a run-time procedure descriptor for every entry
point, with the last entry point's run-time procedure descriptor covering
all the common code of the procedure.
The creation of procedure descriptors involves
the combined actions
of compilers and assemblers, the linker, and the loader. The sections that
follow focus solely on the result of this composite process and describe the
resulting descriptors as seen by the executing run-time environment. The
figures present the physical representation of the procedure descriptor structures.
The logical fields, which have the prefix PDSC_, present the abstract
means to access the fields of these structures. The physical representation
and the logical fields are defined in the file /usr/include/pdsc.h.
Contains a longword that is the offset from the base of the code range
table to the starting point of the code to which the associated run-time procedure
descriptor applies. The low two bits of this longword are reserved for use
as flags; they must be masked out before the containing longword is used as
an offset.
Contains a longword that is the self-relative offset to the associated
run-time procedure descriptor. The low two bits of this longword are used
as flags; they must be masked out before the containing longword is used as
an offset. An rpd_offset value of zero indicates a null frame procedure
for which an implicit run-time procedure descriptor is assumed with the characteristics
defined in Section 3.1.4.
Indicates that memory traps (SIGSEGV, SIGBUS)
occurring in this procedure should not be delivered.
Specifies a flag set to indicate that the code range does not begin
with an entry point. This argument might be used for an out-of-line code
segment that is not contiguous with the main body of a procedure.
Each figure shows two alternative representations for the first longword.
The first representation applies to stack frame procedures and is shown in
the main part of the figure. The second representation applies to register
frame procedures and is shown as a separate longword at the end of the figure.
The PDSC_FLAGS_REGISTER_FRAME flag, which is one of the flags common
to both forms, determines which representation applies.
Descriptions of the physical fields follow the figures. These descriptions
include the calculations used to obtain the logical field from the physical
field. Most fields are common to both procedure descriptor forms. The long
form has three additional fields shown in Figure 8-2.
Raise no exceptions and create only finite values (no infinities, denormals,
or NaNs). In this mode, the function result or the C language errno must be examined for any error indication. This mode is the default.
Raise exceptions for all error conditions except for underflow, which
yields a zero result.
Raise exceptions for all error conditions (including underflows).
Raise no exceptions (except as controlled by separate IEEE exception
enable bits), and create infinite, denormal, and NaN values according to the
IEEE floating-point standard.
Perform the exception mode behavior specified by this procedure's caller.
PDSC_RPD_RSA_OFFSET = rsa_offset * 8
PDSC_RPD_SP_SET = sp_set * 4
PDSC_RPD_ENTRY_LENGTH = entry_length * 4
PDSC_RPD_FRAME_SIZE = frame_size * 8
The value of SP at entry to this procedure can be calculated by adding PDSC_RPD_FRAME_SIZE to the value SP or FP, as indicated by PDSC_FLAGS_BASE_REG_IS_FP. PDSC_RPD_FRAME_SIZE cannot be 0 for a stack frame procedure
because the stack frame must include space for the register save area.
Note: If a procedure needs a frame size that is too large to be represented
using the frame_size field, a variable-size stack frame should
be used. In this case, the FP register is used to address a fixed size area
that needs to be just large enough to include the preserved state. An arbitrarily
large stack area can then be covered by the SP register.
The short form run-time procedure descriptor differs from the long form
in the following ways:
In the course of running and debugging a program, there are times when
it is necessary to identify which procedure is currently executing. During
normal thread execution, the current procedure
must be determinable any time an exception
arises so that the proper handlers will be invoked. In addition, a debugger
must know which procedure invocation is currently executing so it can obtain
information about the current state of the execution environment.
To determine precisely the current execution context, two pieces of
information are required:
This context of the current procedure and the specific instance of that
procedure invocation are referred to as the current procedure invocation or
simply, current procedure.
At any point in the execution of a thread,
only one procedure is considered to be the current procedure.
In this calling standard, the value in the PC is used to indicate the
current procedure by means of the code range table described in Section 8.1.1.
The following system-supplied routine is used to obtain the address
of the procedure descriptor that corresponds with any given PC value within
the current address space.
8.1 Procedure Descriptor Representation
Procedure descriptors
on Digital UNIX for Alpha systems use two kinds of structures: code range
descriptors and run-time procedure descriptors.8.1.1 Code Range Descriptors
The code-range table
is an array of code-range descriptors, as shown
in Figure 8-1. There are four fields for
each descriptor:
Figure 8-1: Code Range Descriptor
8.1.2 Run-Time Procedure Descriptors
Run-time procedure descriptors
provide information about a procedure needed for exception handling and other
tools. Table 3-1 lists this information. There
are two forms: long and short. Both forms encode the same information. The
short form is used to save space for the most commonly occurring cases. Figure 8-2 shows the long form; Figure 8-3
shows the short form.
Figure 8-2: Long Form Run-Time Procedure Descriptor
Figure 8-3: Short Form Run-Time Procedure Descriptor
If any of these restrictions cannot be satisfied, the long
form run-time procedure descriptor must be used.8.2 Procedure Descriptor Access Routines
A thread can obtain
information from the descriptor of any procedure in the thread's virtual address
space by calling system library functions.
exc_lookup_function_entry (ControlPC)
Arguments:
ControlPC | Specifies a PC value in the current address space for which the procedure value is to be returned. |
PROC_DESC | Specifies the address of the code range descriptor for the procedure containing the requested PC. If the return value is null, the PC is not currently mapped. |
exc_lookup_function_table (ControlPC)
Arguments:
ControlPC | Specifies a PC value in the current address space for which the code range base address is to be returned. |
PROC_CRD | Specifies the address of the base of the code range descriptor array for the procedure descriptor of the procedure containing the requested PC. If the return value is null, the PC is not currently mapped. |
exc_lookup_gp (ControlPC)
Arguments:
ControlPC | Specifies a PC value in the current address space for which the GP value is to be returned. |
GP_VALUE | Specifies a GP value for the procedure containing the requested PC. If the return value is null, the PC is not currently mapped. |
To maintain stack traceability when code generated at run time is executed, procedure descriptors must be provided for that code. Such procedure descriptors must describe correctly the characteristics of the code and the environment within which that code executes.
Before run-time generated code that uses any exception facilities (directly or indirectly) can be executed, system library functions must be called to communicate the code ranges, procedure descriptors, and GP values to the execution environment. This communication is accomplished by calling the following two system-supplied routines:
exc_add_pc_range_table (PROC_DESC_ADDR, LENGTH)
Arguments:
PROC_DESC_ADDR | Specifies the base address of the code range array for the procedure descriptors. |
LENGTH | Specifies the number of code range elements in the array. |
exc_add_gp_range (BEGIN_ADDRESS, LENGTH, GP_VALUE)
BEGIN_ADDRESS | Specifies the first address for which GP_VALUE applies. |
LENGTH | Specifies the number of bytes from BEGIN_ADDRESS for which GP_VALUE applies. |
GP_VALUE | Specifies the GP value to be associated with the addresses in the range BEGIN_ADDRESS .. BEGIN_ADDRESS + LENGTH + 1. |
When procedure information is no longer valid or if the code will not be executed again, two system library routines should be called to remove the procedure mapping information. These system library routines are defined as follows:
exc_remove_pc_range_table (PROC_DESC_ADDR)
Arguments:
PROC_DESC_ADDR | Specifies the base address of the code range array for the procedure descriptors. |
exc_remove_gp_range (BEGIN_ADDRESS)
Arguments:
BEGIN_ADDRESS | Specifies the beginning address for which GP-value information should be removed. |
The following steps show how run-time code
should be constructed
and released: