The MPE XL Programming Environment [ HP Link Editor/XL Reference Manual ] MPE/iX 5.0 Documentation
HP Link Editor/XL Reference Manual
The MPE XL Programming Environment
The paragraphs which follow in this section cover the aspects of the MPE
XL environment that affect HP Link Editor/XL and how it links programs.
Virtual Memory
A program running under MPE XL has at least two spaces, where a space is
a fixed-length block of virtual memory. One is a code space and the
other is a data space. A virtual address is composed of a space
identifier and a space offset, both of which are 32 bits long. Thus,
virtual memory consists of over 4 billion spaces, each of which can
contain over 4 billion bytes (four gigabytes). (Some implementations of
HP Precision Architecture restrict space identifiers to 16 bits, allowing
only 65,536 spaces.)
Even though a virtual memory address is 64 bits long, most addressing can
be done with 32-bit addresses. There are eight space registers that hold
space identifiers. When loading or storing a word in memory using a
32-bit address, one of the last four space registers is selected
automatically. Its selection is based on the high-order two bits of the
address. This method of addressing allows one gigabyte (or quadrant) of
each space selected by the space registers to be addressed: the first
quadrant of the first space, the second quadrant of the second space, the
third quadrant of the third space, and the fourth quadrant of the fourth
space. Figure 7-1 shows the code and data spaces divided into quadrants:
Figure 7-1. Code and Data Quadrants
The link editor places all code and literals in the first quadrant of the
code space, and all data in the second quadrant of the data space. Thus,
every executable module, whether in a executable program file or in an
executable library, consists of one code space and one data space. When
the program is loaded, a new code space is created for the code in the
executable program file and for each executable library that is loaded to
satisfy external references. Only one data space is created. The data
spaces in each executable module are loaded one after another into a
single data space.
If you run a program that is already loaded (someone else is also running
it), the code spaces already loaded can be reused. Only a data space
must be created for the second program (process). The code and literals
can be shared because they cannot be modified by a process.
External Calls
An external call is a procedure call that transfers control from one
executable module to another. These calls are not resolved during the
link operation for two reasons. First, the link editor builds (using
LINK or ADDXL) one executable module at a time. Therefore, it does not
know where the called procedure is located. Second, since space
identifiers are assigned at run time, there is no way to predict what the
space identifier for either code space will be.
Because the link editor cannot resolve external calls, it builds an
import stub during linking for each procedure that is called but not
defined in the executable module. It also allocates an entry in the
External Reference Table (XRT) for the unresolved procedure. The import
stub contains a short sequence of code that is used at run time to
transfer to the procedure's entry point. The import stub uses the XRT
entry to find both the space identifier and the space offset of the
target procedure. The import stub then saves the current value of space
register 4 (which corresponds to the first quadrant of the code space),
and copies the new space identifier into space register 4. This ensures
that the space register always contains the space identifier of the
current code space. The loader locates each procedure referenced in the
XRT and initializes each XRT entry with the appropriate values.
When a procedure is called externally, it must restore the space
identifier of the calling procedure before returning to it. To do this,
the link editor builds an export stub for every procedure that can be
called externally. The export stub gives an alternate entry point to the
procedure that is executed by an external call. All internal calls (that
is, calls to procedures in the same executable module) use the ordinary
procedure entry point. External calls use the export stub as the entry
point. On LISTPROG and LISTXL symbol listings, export stubs are shown as
entry symbols, while the ordinary entry points are shown as code symbols.
Privilege Levels
The HP Precision Architecture provides four levels of privilege. Level 0
is the most privileged and allows complete access to all system
resources. Level 3 is the least privileged. MPE XL establishes the
following meanings for the privilege levels:
0 Restricted to the MPE/XL kernel.
1 Reserved for future use.
2 Privileged Mode. Programs with PM capability execute at this
level. This privilege level provides access to most operating
system features and security checks are streamlined.
3 User Mode. Most programs run at this level. Programs access
operating system features only through documented intrinsics,
and access is subject to full security checking.
All procedures have two privilege levels: the privilege level at which
it runs, the execution privilege level; and the privilege level at which
callers must be running in order for the call to succeed, the call or
xleast privilege level. When a procedure call occurs, the execution
privilege level of the calling procedure must have the same or a higher
(numerically lower) privilege level than the call privilege level of the
procedure being called. (If not, the calling program is aborted with a
privilege violation.) The execution privilege level of the called
procedure is promoted to the execution privilege level of the calling
procedure, when the calling level is more privileged; otherwise the
called procedure's execution privilege level remains unchanged. The
execution and call privilege levels for procedure entry points are shown
in the symbol listings produced by the link editor commands, LISTOBJ,
LISTPROG, LISTRL, and LISTXL.
Privilege level promotion and security checking are performed by the
operating system during an external procedure call. Internal calls
cannot perform promotion. When internal procedure calls require a
promotion, the link editor builds a promotion stub that turns the
internal call into an external call. A promotion stub is a combination
of an import stub and an export stub.
Long Branch Stubs for Procedure Calls
Compilers generate a single branch-and-link instruction for all procedure
calls. The instruction has a limited addressing range - 256K bytes in
either direction from the call. If the call is external, the link editor
places the import stub within this range. If the call is internal, the
target may be out of range. In this case, the link editor builds a long
branch stub within reach of the call. A long branch stub consists of two
instructions that reach the target anywhere in the code space.
Long branch stubs are also used for millicode calls and interchunk
branching for HP COBOL II programs.
Procedure Labels
The address of a procedure is a data item called a procedure label, or
plabel. A plabel can be passed as a parameter from one procedure to
another, so that an indirect call through the plabel might not be an
internal call. To accommodate this possibility, all indirect procedure
calls are external calls, even if the call happens to be in the same code
space as the procedure being called. A plabel is therefore the address
of an XRT entry, not the address of the procedure itself. The indirect
procedure call obtains the space identifier and offset from the XRT entry
just like an import stub.
If you obtain a plabel through the HPGETPROCPLABEL intrinsic, the
intrinsic creates an XRT entry and returns its address. If you obtain a
plabel by taking the address of a procedure in your source program (for
example, by passing a subprogram or function name by reference in HP
FORTRAN 77) the link editor automatically allocates an XRT entry and
creates a plabel stub that instructs the loader to initialize the XRT
entry appropriately. The code in the plabel stub is identical to an
export stub. Plabel stubs are shown in LISTPROG and LISTXL symbol
listings as plab symbols.
Note that if a routine resides in an executable library, and its address
is taken (as in HP C), it will not necessarily be the same as the address
that is taken from the user's program. The addresses will be the same if
they are being compared in the same program or library.
In other words, if your program compares the addresses of routines within
the program, it will work as you expect. Likewise, comparing the
addresses of two routines which reside in the same executable library
will work as you expect. But, if your program compares the address of a
routine taken from within the program code with the address of a routine
taken from within the library, those addressses will not be the same.
You will be comparing the address of an import stub with the address of
an export stub.
HP Link Editor/XL Environment Files
When you use the LINK and ADDXL commands, the link editor includes two
files, NRT0.LIB.SYS and XL0.LIB.SYS, into the executable modules that are
produced. These files define:
* The standard subspaces that control how the link editor arranges
the code and data spaces.
Since MPE XL compilers group the various parts of a relocatable
object file into separate subspaces, the link editor can combine
like subspaces together within each space. Standard subspaces are
defined for millicode, literals, code, stack unwind descriptors,
Pascal outer block global variables, static initialized data and
static uninitialized data. Compilers also define an additional
subspace for each locality set.
* The standard symbols that are used by the compiler libraries and
system debuggers.
For example, the symbols $UNWIND_START and $UNWIND_END declare the
beginning and end of the region containing stack unwind
descriptors.
Stack Unwinding
Whenever a traceback of procedure calls is made, the process is referred
to as unwinding the stack. The traceback can occur as a result of a
multi-level procedure return in languages that support it (for example,
non-local GOTO or escape in Pascal), or from a program abort or a
debugging request. Regardless of the cause, each stack frame must be
examined to determine the procedure that created it and its size. Given
the size of the current stack frame, the previous stack frame can be
located.
All MPE XL compilers create static tables of unwind descriptors that make
stack unwinding possible. The tables are placed in pre-defined subspaces
so that the link editor can build one combined stack unwind table during
a LINK or ADDXL operation. Each descriptor describes the stack frame for
a procedure, which is identified as a range of addresses in the code
space. Thus, given any code address as a starting point, the appropriate
descriptor can be located. The descriptor, in turn, identifies the size
and type of the current stack frame. From this information, the address
of the caller of that procedure and the address of the caller's stack
frame can be determined, and the unwinding can continue until the bottom
of the stack is reached.
MPE/iX 5.0 Documentation