The purpose of relocation is to identify and update storage locations that need to be adjusted when an executable image is created from input object files at link time. Relocation information enables the linker to patch addresses where necessary by providing the location of those addresses and indicating the type of adjustments to be performed. Relocation entries in the section relocation information are created by the assembler, compiler, or other object producer, and the address adjustments are performed by the linker.
The linker performs relocation fixups after determining the linked object's memory layout and selecting starting addresses for its segments. During partial links, relocation information is updated and preserved for subsequent links. Relocation updates for partial links include converting external relocation entries to local relocation entries and retargeting relocation entries to new section addresses. See Section 4.3.2.1 for details.
Relocation information contained in an object file can have four distinct representations:
Relocation entries identified in section headers. These are the relocation entries referred to in this document as "normal" or "actual".
Compact relocation records, produced by the linker and consumed
by
om,
spike, and profiling tools.
Compact
relocations are stored in the
.comment
section.
Linkerdef entries which are produced by the linker to identify
all uses of linker-defined symbols.
Linkerdef entries are stored in the
.comment
section.
Version Note Linkerdef entries are supported in Tru64 UNIX V5.1 and greater for object format V3.13 and greater.
Dynamic relocations, which are present only in shared objects. Dynamic relocation may be performed for shared objects at load time.
The first form of relocation information is discussed in this chapter. The second and third forms are used by post-link object modification tools. They are discussed in Chapter 5. The fourth form is covered in Chapter 14. Figure 4-1 summarizes which kinds of objects contain which kinds of relocation information.
Figure 4-1: Kinds of Relocations
Actual relocation entries are organized by raw data section. Not all object file sections necessarily have relocation entries associated with them. For example, bss sections do not have relocation entries because they do not have raw data to relocate. Section headers for sections with relocation entries contain pointers to the appropriate section relocation information, as shown in Figure 4-2.
Figure 4-2: Section Relocation Information in an Object File
Note that the ordering of section headers does not necessarily correspond
to the ordering of raw data and section relocation information.
Consumers
should rely on the section header to access this information.
4.1 New or Changed Object Relocation Features
Tru64 UNIX V5.1B introduces the following new or changed features:
Use of R_GPDISP_GP_TAILCALL
flag to disable a linker optimization.
See
Section 4.3.4.8.
4.2 Structures, Fields, and Values for Object Relocation
4.2.1 Relocation Entry (
reloc.h)
struct reloc {
coff_addr r_vaddr;
coff_uint r_symndx;
coff_uint r_type : 8;
coff_uint r_extern: 1;
coff_uint r_offset:6;
coff_uint r_reserved:11;
coff_uint r_size:6;
};
SIZE - 16 bytes, ALIGNMENT - 8 bytes
Relocation Entry Fields
r_vaddrVirtual address of an item to be relocated.
If the
s_nreloc
field in the section header
overflows, this field contains the number of relocation entries for the section.
This possibility applies only to the first entry in a section's relocation
information.
See
Section 4.2.2
for more information.
r_symndx
For
an external relocation entry,
r_symndx
is an index
into external symbols.
For a local relocation entry,
r_symndx
is the number of the section containing the symbol.
Table 4-1
lists the section numbering.
For entries of type
R_LITUSE,
this field contains a subtype.
See
Table 4-3.
r_typeRelocation type code. Table 4-2 lists all possible values.
r_externSet to 1 for an external relocation entry. Set to 0 for a local relocation entry.
r_offsetFor an entry
of type
R_OP_STORE,
r_offset
is the bit offset of a field within a quadword.
For
other relocation types, the field is unused and must be zero.
r_reservedMust be zero.
r_sizeFor an entry
of type
R_OP_STORE,
r_size
is the bit size of a field.
For
R_IMMED_*
entries, it is a subtype.
See
Table 4-4.
For other relocation types, the field is unused and must be zero.
Table 4-1: Section Numbers for Local Relocation Entries
| Symbol | Value | Description |
R_SN_NULL |
0 | no section |
R_SN_TEXT |
1 | .text
section |
R_SN_RDATA |
2 | .rdata
section |
R_SN_DATA |
3 | .data
section |
R_SN_SDATA |
4 | .sdata
section |
R_SN_SBSS |
5 | .sbss
section |
R_SN_BSS |
6 | .bss
section |
R_SN_INIT |
7 | .init
section |
R_SN_LIT8 |
8 | .lit8
section |
R_SN_LIT4 |
9 | .lit4
section |
R_SN_XDATA |
10 | .xdata
section |
R_SN_PDATA |
11 | .pdata
section |
R_SN_FINI |
12 | .fini
section |
R_SN_LITA |
13 | .lita
section |
R_SN_ABS |
14 | for
R_OP_xxxx
constants |
R_SN_RCONST |
15 | .rconst
section |
R_SN_TLSDATA |
16 | .tlsdata
section |
R_SN_TLSBSS |
17 | .tlsbss
section |
R_SN_TLSINIT |
18 | .tlsinit
section |
R_SN_GOT |
20 | (V5.1 - ).got
section |
| Symbol | Value | Description |
R_ABS |
0x0 | Relocation already performed |
R_REFLONG |
0x1 | A 32-bit reference to symbol's virtual address |
R_REFQUAD |
0x2 | A 64-bit reference to symbol's virtual address |
R_GPREL32 |
0x3 | A 32-bit displacement from the global pointer to a symbol's virtual address |
R_LITERAL |
0x4 | A reference to a literal in the literal address pool as an offset from the global pointer |
R_LITUSE1 |
0x5 | An instance of a literal address previously loaded into a register |
R_GPDISP |
0x6 | An
lda/ldah
instruction pair that
is used to initialize a procedure's global-pointer register |
R_BRADDR |
0x7 | A 21-bit branch reference to the symbol's virtual address |
R_HINT |
0x8 | A 14-bit
jsr
hint reference to symbol's
virtual address |
R_SREL16 |
0x9 | A 16-bit self-relative reference to symbol's virtual address |
R_SREL32 |
0xa | A 32-bit self-relative reference to symbol's virtual address |
R_SREL64 |
0xb | A 64-bit self-relative reference to symbol's virtual address |
R_OP_PUSH |
0xc | A 64-bit virtual address to push on the relocation expression stack |
R_OP_STORE |
0xd | An address to store the value popped from the relocation expression stack |
R_OP_PSUB |
0xe | A symbol's virtual address to subtract from value at the top of the relocation expression stack |
R_OP_PRSHIFT |
0xf | The number of bit positions to shift the value at the top of the relocation expression stack |
R_GPVALUE |
0x10 | A new GP value to be used for the address range starting
with the address specified by the
r_vaddr
field |
R_GPRELHIGH |
0x11 | The most significant 16 bits of a 32-bit displacement from the global pointer to a symbol's virtual address |
R_GPRELLOW |
0x12 | The least significant 16 bits of a 32-bit displacement from the global pointer to a symbol's virtual address |
R_IMMED2 |
0x13 | An instruction sequence that calculates an address |
R_TLS_LITERAL |
0x14 | The instruction that loads the TLS key |
R_TLS_HIGH |
0x15 | The most significant 16 bits of a 32-bit displacement from the TLS region pointer to a symbol's virtual address |
R_TLS_LOW |
0x16 | The least significant 16 bits of a 32-bit displacement from the TLS region pointer to a symbol's virtual address |
Table Notes
The
r_symndx
field for the relocation
type
R_LITUSE
is a subtype.
The
valid entries for this field and their meanings are summarized in
Table 4-3.
The
r_size
field for the relocation
type
R_IMMED
is a subtype.
The valid entries for this field
and their meanings are summarized in
Table 4-4.
Table 4-3: Literal Usage Types
| Symbol | Value | Description |
R_LU_BASE |
1 | The base register of a memory format instruction (except
ldah) contains a literal address |
R_LU_BYTOFF |
2 | Should not be used |
R_LU_JSR |
3 | The target register of a
jsr
instruction
contains a literal address |
Table 4-4: Immediate Relocation Types
| Symbol | Value | Description |
R_IMMED_GP_16 |
1 | 16-bit displacement from GP value |
R_IMMED_GP_HI32 |
2 | Most significant 16 bits of 32-bit displacement from GP value |
R_IMMED_SCN_HI32 |
3 | Most significant 16 bits of 32-bit displacement from section start |
R_IMMED_BR_HI32 |
4 | Most significant 16 bits of 32-bit displacement from instruction following branch |
R_IMMED_LO32 |
5 | Least significant 16 bits of 32-bit displacement specified
by last
R_IMMED_*_HI32 |
| Symbol | Value | Description |
R_GPDISP_NONE |
0 | (V5.1B - )No flag set |
R_GPDISP_GP_TAILCALL |
0x1 | (V5.1B - )Target
of relocation is an ldgp instruction following a call to a procedure with
its
gp_tailcall
flag set. |
The section header contains a file pointer to the section's relocation
information and the number of entries.
(See
Section 2.2.3
for the
declaration.) The number of relocation entries for a section is contained
in the section header field
s_nreloc.
If that field
overflows, the section header flag
S_NRELOCS_OVFL
is set and the first relocation entry's
r_vaddr
field stores the actual number of relocation entries for the
section.
That relocation entry has a type of
R_ABS
and all other fields are zero, causing it to be ignored
during relocation.
4.3 Object Relocations Usage
4.3.1 Relocatable Objects
An object is relocatable if it contains enough relocation information for the linker to successfully relocate it. Relocatable objects can be produced by compiling without linking or by partial linking.
Compilers and assemblers
always produce relocatable objects.
By default, the relocatable object files
produced are passed to the linker to produce a non-relocatable executable
object.
Most compilers recognize a
-c
option.
The
-c
option suppresses the link operation and writes the object file
in its relocatable form.
For example, the following command produces a non-executable
OMAGIC
file named
pgm.o.
$ cc -c pgm.c
By means of partial linking, the linker can also
produce a relocatable object.
By default, the linker attempts to produce an
executable
ZMAGIC
file for which
all relocation entries have been processed and removed.
To preserve relocation
information, the linker's
-r
switch should be selected.
For
example, the following command produces a non-executable
OMAGIC
file named
a.out.
$ ld -r pgm.o
Selection of the -r switch has other effects: common storage class symbol allocation is deferred until final link and undefined symbol error messages are suppressed.
Relocatable objects
have various uses.
The most obvious is as input to a subsequent partial or
final link operation.
All objects input to the linker are relocatable objects,
regardless of how they are produced.
Multiple relocatable objects can be combined
during a final link to produce an executable object.
The typical example of
this process is when several separately compiled modules are created at different
times and later linked together to produce the final executable program.
For
example, the following steps produce an executable
ZMAGIC
file named
a.out.
$ cc -c part1.c $ cc -c part2.c $ cc -c part3.c $ cc part1.o part2.o part3.o
Relocatable objects
are also used for archives.
Although files of any type may be archived, one
important use of archives is for user or system libraries.
An example is the
system library
libc.a, which is linked with many C programs.
Objects in archive libraries must be relocatable to be linked with other object
files to make executable programs.
Relocatable objects may be used as loadable device drivers, which are object files that are dynamically added to a running kernel. See Reference Pages, Section 9r, Device Drivers (Volume 1) and Reference Pages, Section 9s, 9u, and 9v, Device Drivers (Volume 2) for more information.
Relocatable objects can also be used by the boot linker, which builds the kernel from object files at boot time. Information is available in the System Administration guide.
Some profiling tools
require relocatable objects as input because they rebuild the object and require
the capability of rearranging raw data.
However, on Tru64 UNIX, these tools
rely on compact relocations, which are an alternate form of relocation information.
Compact relocations are described in
Section 5.3.1.
4.3.2 Relocation Processing
This section describes the generic process of relocating object files from a high-level viewpoint. It does not include details of address calculations, nor does it take into account the substantial variations in the contents of a relocation entry's fields. For specifics, see Section 4.3.4.
Relocation involves tracking and updating references as the referenced
items move in memory.
At a minimum, one relocation entry is required for each
reference made to an item whose address may potentially change.
This address,
pointed to by the
reloc
structure field
r_vaddr, is the target address of the relocation.
This address
is adjusted when relocation records are preserved at link time.
The target
address is located in one of the raw data sections of the object file.
The target address points to another item in the raw data. This item can be a data item, procedure, or any program element that will potentially be mapped to a new memory location when the linker builds the executable object.
Note that a many-to-one relationship may exist between relocation entries and target items. A target item may be addressed multiple times in an object file's raw data, and a single target address reference may be described by multiple relocation entries.
Taken together, the
r_symndx
field and
r_extern
bit track the position of the target item.
If it is
moved to a new location, the target address is updated accordingly.
The value of the relocation is the distance that the tracked item will
move in memory.
4.3.2.1 Local and External Entries
Relocation entries are used for several purposes:
Address references to unresolved symbols that will be imported from other objects.
References to addresses within an object that may change when the object is linked at a different base address or linked with other object files.
Identification of address references that may be optimized at link time.
Relocation entries may be local or external. Local relocation entries are used for references to addresses within an object. External relocation entries are used for references to any external symbols. In particular, unresolved symbol references can only be represented by external relocation entries.
The
r_extern
flag is set in external relocation
entries.
This flag determines the interpretation of the
r_symndx
field.
For external entries, this field provides the external
symbol table index of the referenced symbol.
Figure 4-4 shows a sample external relocation entry.
Figure 4-4: External Relocation Entry
For an external entry, the value for relocation is the run-time address of the referenced external symbol. In cases where the symbol is undefined in an input object, it must first be resolved. Figure 4-5 depicts this process.
Figure 4-5: Processing an External Relocation Entry
A local relocation entry has its
r_extern
flag cleared and tracks references by section.
Figure 4-6 shows a sample local entry.
Figure 4-6: Local Relocation Entry
For a local entry, the value for relocation is the difference between
a section's address in the input object and the address of that section's
data after linking.
The section is identified by a relocation section type
in
r_symndx.
Figure 4-7
depicts this
situation.
Figure 4-7: Processing a Local Relocation Entry
To complete relocation for all entries, the base address for the final
process image is required.
The linker can then use that address to patch all
relocatable entries.
4.3.2.2 Relocation Entry Ordering
The ordering of relocation entries is sometimes significant. The diagram below shows the optional relocation entry count and grouping of relocation entries according to GP range.
Figure 4-8: Relocation Entry Ordering Requirements
If a section requires an optional relocation entry overflow count, it must be in the first relocation entry.
Relocation processing tools require GP-relative relocations to be grouped
by GP range.
R_GPVALUE
entries will
effectively separate the groups of GP-relative relocation entries for each
GP range.
For a list of GP-relative relocation types, see
Section 4.3.3.2.
Some relocation types can only be used when paired with other relocation types. These relocation groupings are:
R_GPRELHIGH,
R_GPRELLOW
R_TLSHIGH,
R_TLSLOW
R_LITERAL,
R_LITUSE
R_OP_PUSH,
R_OP_PSUB,
R_OP_PRSHIFT,
R_OP_STORE
An
R_GPRELHIGH
entry must
be followed by one or more
R_GPRELLOW
entries.
An
R_TLSHIGH
entry must be followed by one or more
R_TLSLOW
entries.
An
R_LITERAL
entry may be
followed by zero or more
R_LITUSE
entries.
An
R_OP_PUSH
entry must be
followed by exactly one
R_OP_STORE
entry.
Zero or more
R_OP_PSUB
and
R_OP_PRSHIFT
entries may be located between
the
R_OP_PUSH
and
R_OP_STORE
entries.
4.3.2.3 Shared Object Transformation
Part of the linker's preparation of loading information for shared objects is to create dynamic relocation entries from some of the actual relocation entries.
The linker must determine which relocation entries need to be converted
to dynamic relocation entries.
Data references (
R_REFQUAD
and
R_REFLONG
relocation types) must be represented in the
.rel.dyn
section
if they are not in the
.lita
section.
The
.lita
section is an exception because its contents are mapped directly
into the GOT.
All other
R_REFQUAD
or
R_REFLONG
entries have an associated
dynamic relocation entry in the shared object file.
Dynamic relocation entries are not permitted for text addresses.
The
text segment is not mapped with write permission, so text relocation fixups
cannot be performed by the dynamic loader.
4.3.3 Kinds of Relocations
Relocations types can be grouped into the following categories:
Direct Relocations
GP-relative Relocations
Self-relative Relocations
Literal Relocations
Relocations Stack Expressions
Immediate Relocations
TLS Relocations
The categories often overlap.
4.3.3.1 Direct Relocations
Direct relocations are independent entries; all of the information necessary
to process them is self-contained.
The relocation target contains either the
address of a relocatable symbol or an offset from that address.
They are used
for simple address adjustments; addresses in the literal address pool (.lita
section), for example, will have associated direct relocation
entries.
R_REFQUAD
and
R_REFLONG
are direct relocation types.
R_REFQUAD
indicates a 64-bit address and thus
is normally used on Alpha systems.
R_REFLONG
indicates a 32-bit address and most often occurs when the xtaso
environment is in effect.
These types of relocations are processed in the
manner described in
Section 4.3.2.
The following special requirements exist for direct relocation entries
for the
.lita
section:
Only entries of type
R_REFQUAD
or
R_REFLONG
are permitted.
R_REFLONG
entries
pertain to the bottom 4 bytes of a
.lita
entry.
The size
of the entry is unchanged, but an error is generated if the result overflows
4 bytes.
All external entries must correspond to symbols whose value is zero prior to relocation.
4.3.3.2 GP-Relative Relocations
This class of relocations requires use of the GP value as a factor in the calculation. Note that the literal relocations in Section 4.3.3.4 and Section 4.3.3.7 also fit this category.
The
R_GPREL32,
R_GPRELHIGH,
R_GPRELLOW, and
R_GPDISP
relocation
types are GP-relative.
They typically point to instructions that calculate
or load addresses using a GP value.
The
R_GPRELHIGH
and
R_GPRELLOW
relocation
types must be used together.
The
R_GPDISP
relocation type is used for instruction pairs that load the GP value.
A special-purpose
GP-relative relocation entry specifies that a new GP range is in effect.
The
relocation type for this entry is
R_GPVALUE.
The linker inserts
R_GPVALUE
entries
at object module boundaries during a partial link (ld
-r) when the
.lita
section it is building would
otherwise overflow.
Entries of this type appear in the
.text
section or the
.rdata
section.
These entries are local
entries because they are not tied to any symbol.
4.3.3.3 Self-Relative (PC-Relative) Relocations
This class of relocations require adjustments based on the current position in the text or data. Self-relative relocations are also referred to as PC-relative relocations.
The
R_SREL16,
R_SREL32, and
R_SREL64
relocation types apply to 16, 32, and 64 bit target
addresses, respectively.
Two more self-relative relocation types are
R_BRADDR
and
R_HINT.
R_BRADDR
is used to identify branching instructions
whose targets are known at link time.
R_HINT
is used to adjust the branch-prediction hint bits in jump instructions.
4.3.3.4 Literal Relocations
This category of relocations encompasses both literal relocations
(type
R_LITERAL) and literal-usage
relocations (type
R_LITUSE), which
work together to describe text references.
A literal relocation (type
R_LITERAL)
occurs on a load of an address from the
.lita
section.
Any associated
R_LITUSE
entries
always directly follow the
R_LITERAL
entry.
The literal-usage entries are used for linker optimizations. Processing for these relocation entries is optional. The linker and other tools may ignore these relocation entries with no risk of producing an improperly relocated object file.
The advantage of
literal-usage entries is that they enable link-time memory-access optimizations.
These relocation entries identify instructions which use a previously loaded
literal.
With this knowledge, the linker is able to determine that certain
instructions are unnecessary or can be altered to improve performance.
Optimization
is performed only during final link and with an optimization level setting
of at least
-O1.
4.3.3.5 Relocation Stack Expressions
Relocation stack expressions constitute a sequence of relocation entries that must be evaluated as a group. The purpose of stack expressions is to provide a way to represent complex relationships between relocatable addresses and store results with bit field granularity. They are currently used only for exception-handling sections.
An additional advantage of stack expressions is that they provide the
capability to describe a new relocation type without requiring tool support
or code modification to recognize and execute a new
r_type.
However, the greater flexibility of relocations expressions is offset by the
fact that multiple entries are necessary to describe a single fix-up.
Special relocation types are used to build relocation expressions. The types are:
R_OP_PUSH
R_OP_STORE
R_OP_PSUB
R_OP_PRSHIFT
An
R_OP_PUSH
entry marks the
beginning of a sequence of relocation stack expressions and an
R_OP_STORE
marks the end.
The types of any intervening
relocation entries should be either
R_OP_PRSHIFT
to shift the top of stack value right or
R_OP_PSUB
to subtract an address from the top of stack value.
An
R_OP_STORE
entry pops the
value from the top of the expression stack and stores selected bits into a
field in a word in memory.
The
r_offset
and
r_size
fields of a relocation entry are used to specify the
target bit field.
It is an error to cause stack underflow or to have values left on the stack when section relocation is complete.
Currently, these relocation types are used exclusively for relocating
the exception-handling data in
.xdata
and
.pdata.
The reason this relocation is performed using the stack expression
types is the need to shift the address by two bits.
Bit field granularity
cannot be specified with other relocation types unless it is implicit in the
relocation type.
4.3.3.6 Immediate Relocations
Immediate relocations are used to describe the linker's optimization
of literal pool references.
If optimization options are in effect, the linker
will replace
R_LITERAL
and
R_LITUSE
entries with
R_IMMED
entries wherever possible.
This information is then used to generate compact
relocations that sufficiently describe all relocatable storage locations.
Immediate relocations can describe instruction sequences that calculate
addresses by adding either a 16-bit or 32-bit immediate displacement to a
base address.
R_IMMED
entries always point to memory-access
instructions.
The displacement is obtained from the instruction.
There are five types of immediate relocations.
Subcodes in the
r_size
field identify them.
The types are:
R_IMMED_GP_16
R_IMMED_GP_HI32
R_IMMED_SCN_HI32
R_IMMED_BR_HI32
R_IMMED_LO32
R_IMMED_GP_16
and
R_IMMED_GP_HI32
entries identify address calculations
performed by adding an offset to the global pointer.
An
R_IMMED_SCN_HI32
entry is paired with an
R_IMMED_LO32
entry to identify a pair of instructions which add
a 32 bit displacement to the starting address of a section.
An
R_IMMED_BR_HI32
entry is paired with an
R_IMMED_LO32
entry to identify a pair of instructions
which add a 32 bit displacement to the address of an instruction following
a branch.
4.3.3.7 TLS Relocations
The types
R_TLS_LITERAL,
R_TLS_LOW, and
R_TLS_HIGH
are TLS-specific relocation types.
R_TLS_LITERAL
is very similar
to
R_LITERAL, except it relates
to a literal in the TLS data storage area, the TSD array.
R_TLS_LOW
and
R_TLS_HIGH
entries are used as a pair to identify instructions which load a TLS data
address by adding a 32 bit offset to the TLS region pointer.
These relocation
types are identical to the
R_GPRELHIGH
and
R_GPRELLOW
relocation types
except for the fact that the target instructions for the TLS relocation entries
calculate addresses using the TLS region pointer instead of the GP value.
4.3.4 Relocation Entry Types
The type of a relocation entry (stored in the
r_type
field) describes the action the linker must perform.
This section discusses
the purposes of the different types and provides examples of their use.
Relocation entry fields are interpreted differently based on relocation type. There also may be constraints on fields' contents depending on the type. Some relocation entries are context sensitive and must be preceded or followed by a particular entry. Some are size specific and the computed address must fall within a specified range. Moreover, some types are constrained to be local entries only or are associated with particular object file sections.
To describe the calculations performed by the linker, the following notation is used in the detailed descriptions for each relocation type:
*_dispThe displacement field of whatever instruction is indicated.
GPCurrent GP value; begins
as the contents of
AOUTHDR.gp_value
for the final object.
new_scn_addrThe address of the tracked section of a local relocation entry, as calculated by the linker.
old_GPGP value in the input
object; begins as
AOUTHDR.gp_value
for the input object.
old_scn_addrThe contents of
s_vaddr
in the section header of the input object file for the
tracked section of a local relocation entry.
[r_vaddr]The contents at the
address
r_vaddr; to be distinguished from the address
itself.
SEXTThe constant immediately following is sign-extended.
stackThe relocation expression stack.
this_new_addrWhere
r_vaddr
will be after relocation .
this_new_scn_addrWhere the
section containing
r_vaddr
will be after relocation,
as calculated by the linker.
this_old_scn_addrThe contents
of
s_vaddr
in the section header of the input object
file for the section containing
r_vaddr.
tosTop of relocation expression stack.
resultThe result of the relocation,
which is written back into the relocated
r_vaddr
in the object file that the linker is producing.
r_vaddr
Number of relocation entries if
s_nreloc
section
header field has overflowed.
This number includes itself in the count.
Otherwise,
unused.
r_symndxUnused.
r_externUnused.
r_offsetUnused.
r_sizeUnused.
Operation
N/A
Restrictions
N/A
Description
This relocation entry is used to indicate a relocation has already been performed or should not be performed. No calculation is associated with such an entry.
The first entry in a relocation section is of type
R_ABS
if it contains the number of relocation entries in that
section (which is the case when the section header field
s_nreloc
overflows).
This type can also be used to pad relocation data
or to delete relocation entries in place.
In-place deletions of relocation
entries are likely to be performed during a partial link.
Example
An object file produced during a partial link has 99993 relocations
associated with its
.text
section.
A listing of the entries
begins with an
R_ABS
because the
total number overflows
s_nreloc:
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000018699 0 ABS local <null>
r_vaddrPoints to target address.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
result = (new_scn_addr - old_scn_addr) + (int)[r_vaddr]
else
result = EXTR.asym.value + (int)[r_vaddr]
Restrictions
Result after relocation must not overflow 32 bits.
Description
A relocation entry of
this type describes a simple address adjustment to the 32-bit value pointed
to by
r_vaddr.
R_REFLONG
entries are most likely to occur when the compilation option
-xtaso_short
is specified.
The relocated value may be unaligned.
Example 1
C code fragment:
extern int i; void *p = (void *)(&i + 1);
Compile as follows:
$ cc -c -xtaso_short pgmname.c
Produces the following
R_REFLONG
entry:
***RELOCATION INFORMATION***
Vaddr Symndx Type Off Size Extern Name
.sdata:
0x0000000000000000 0 REFLONG extern I
This relocation entry is necessary because the value of the pointer
p
depends on the address of the global (common storage class) symbol
i, whose address is yet to be determined.
At the location indicated
by
s_vaddr, the value 4 is stored, which will be
added to the resolved address of
i.
The "4" represents the
4 bytes to the next integer storage location in memory after
i's.
Example 2
From assembly code, the following declaration produces the same relocation entry as the previous example.
.long I
r_vaddrPoints to target address.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
result = (new_scn_addr - old_scn_addr) + (long)[r_vaddr]
else
result = EXTR.asym.value + (long)[r_vaddr]
Restrictions
None.
Description
A relocation
entry of this type describes a simple address adjustment to the 64-bit value
pointed to by
r_vaddr.
R_REFQUAD
entries are most likely to occur in data sections and
almost always are used for relocation of the
.lita
section.
The relocated value may be unaligned.
Example 1
Small program:
#include <stdio.h>
main(){
printf("printing!\n");
}
Relocation entries produced for its
.lita
section:
***RELOCATION INFORMATION***
Vaddr Symndx Type Off Size Extern Name
.lita:
0x0000000000000070 1 REFQUAD extern printf
0x0000000000000078 3 REFQUAD local .data
The
.lita
section consists of two entries, and each
is relocated.
One entry is external, tracking the routine name
printf(), and one local, tracking the address of the string literal
in the
.data
section.
Example 2
A
R_REFQUAD
entry can also
be produced by an assembly language statement such as:
.globl y
.data
b: .quad y
Relocation entry produced:
***RELOCATION INFORMATION***
Vaddr Symndx Type Off Size Extern Name
.data:
0x0000000000000000 0 REFQUAD extern y
The variable
b
is allocated at
s_vaddr
in the
.data
section and will be updated
by adding the address of
y
when the symbol
y
is resolved.
4.3.4.4
R_GPREL32Fields
r_vaddrPoints to a 32-bit GP-relative value.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
result = (new_scn_addr - old_scn_addr) + old_GP - GP +
SEXT((int)[r_vaddr]
else
result = EXTR.asym.value - GP + SEXT((int)[r_vaddr]
Restrictions
Signed result after relocation must not overflow 32 bits.
Description
A relocation entry
of this type indicates a 32-bit GP-relative value that must be updated.
If
it is a local entry, this value must be biased by the GP value for the input
object file.
In both cases, the current GP value is subtracted to produce
a result that is an offset from the GP.
Example 1
Local
R_GPREL32
entries are
produced for a many-case switch statement.
For example, consider the following
C program:
main(){
int i;
scanf("%d",&i);
switch(i) {
case 0:i++; break;
case 1:i--; break;
case 2:i+=2; break;
case 3:i-=2; break;
case 4:i+=3; break;
case 5:i-=3; break;
case 6:i++; break;
default: i=0;
}
}
A compiler may implement a switch statement with a "jump table", that is a code sequence containing labels for each case and a jump statement selecting between them. For each case label, a relocation entry is produced:
Vaddr Symndx Type Off Size Extern Name
.rconst:
0x00000000000000d0 1 GPREL32 local .text
0x00000000000000d4 1 GPREL32 local .text
0x00000000000000d8 1 GPREL32 local .text
0x00000000000000dc 1 GPREL32 local .text
0x00000000000000e0 1 GPREL32 local .text
0x00000000000000e4 1 GPREL32 local .text
0x00000000000000e8 1 GPREL32 local .text
Example 2
The following assembly code sequence also produces a
R_GPREL32
entry:
.globl z
.data
a: .gprel32 z
Relocation entry produced:
***RELOCATION INFORMATION***
Vaddr Symndx Type Off Size Extern Name
gprel32.o:
.data:
0x0000000000000000 0 GPREL32 extern z
r_vaddrPoints to a
load instruction in the text segment.
The value to be relocated is the memory
displacement from the
$gp
in the instruction.
r_symndx
R_SN_LITA
r_externMust be zero;
all
R_LITERAL
entries are local.
r_offsetUnused.
r_sizeUnused.
Operation
result = (new_scn_addr - old_scn_addr) + (SEXT((short)[r_vaddr]) +
old_GP) - GP
Restrictions
The result after relocation for an
R_LITERAL
entry must not overflow 16 bits.
.
R_LITERAL
entries must be
local and relative to the
.lita
section.
Description
A relocation entry of this type is produced when an instruction attempts
to reference values in the literal-address pool (.lita
section).
The instruction containing the reference accesses a
.lita
entry using the GP value in effect and a signed 16-bit constant.
The original address of the item has to be reconstructed and then adjusted
for the new location of the address table.
The new address then has to be
reconverted into a GP displacement using the new GP value.
An
R_LITERAL
entry may or
may not be followed by corresponding
R_LITUSE
entries.
The
R_LITERAL
entry is required but the
R_LITUSE
entries are not.
Example
R_LITERAL
entries are used
when an address is loaded from the literal address pool:
ldq t12, -32664(gp)
Relocation entry produced:
***RELOCATION INFORMATION***
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000000038 13 LITERAL local .lita
4.3.4.6
R_LITUSE: R_LU_BASEFields
r_vaddrPoints to memory-format instruction.
r_symndx
R_LU_BASE
r_externMust be zero;
all
R_LITUSE
entries are local.
r_offsetUnused.
r_sizeUnused.
Operation
Check if displacement is within 16 or 32 bits. The displacement is calculated:
new_lit = [relocated literal belonging to corresponding R_LITERAL] disp = new_lit + lituse_disp - GP
Restrictions
A relocation entry of this type must follow either an
R_LITERAL
or another
R_LITUSE
entry with no other types intervening.
r_vaddr
must be aligned on a byte boundary.
Ignored if optimization level is not at least -O1.
Cannot remove the first load instruction unless this is the only corresponding
R_LITUSE
entry.
Description
This relocation entry is informational and indicates that the base register
of the indicated instruction holds a literal address.
Note that a
R_LITERAL
entry, corresponding to an
ldq
instruction, precedes this entry.
Possible optimizations depend on the distance of the memory displacement from the GP value. If the displacement is less than 16 bits from the GP, a single instruction suffices to describe the location. The code sequence can be changed as shown:
ldq rx, disp(gp) R_LITERAL
ldq/stq ry, disp2(rx) R_LITUSE(R_LU_BASE)
--
ldq/stq ry, disp3(gp)
The linker converts the
R_LITUSE
entry to an
R_IMMED_GP_16
for the
transformed instructions.
If the displacement is within 32 bits of the GP, one memory access can
be saved by replacing the first load instruction with the faster
ldah
instruction.
ldq rx, disp(gp) R_LITERAL
ldq/stq ry, disp2(rx) R_LITUSE(R_LU_BASE)
--
ldah rx, disp3(gp)
ldq/stq ry, disp4(rx)
The linker will convert the
R_LITERAL
and the
R_LITUSE, respectively,
to entries of type
R_IMMED_GP_HI32
and
R_IMMED_GPLOW32.
This can currently only be done if exactly one
R_LITUSE
exists for the
R_LITERAL.
Example 1
The following instructions represent a single use of an address literal:
0x100: ldq a1, -32656(gp) // R_LITERAL 0x104: lda a1, 32(a1) // R_LU_BASE
Relocation entries produced:
***RELOCATION INFORMATION***
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000000100 13 LITERAL local .lita
0x0000000000000104 1 LITUSE local R_LU_BASE
The potential optimization indicated by this
R_LU_BASE
is that the two instructions could possibly be replaced
by a single
ldq
instruction of the form:
ldq a1, <disp>(gp)
Example 2
The following instructions illustrate multiple
R_LITUSE
entries following an
R_LITERAL
entry:
0x130: ldq t0, -32736(gp) // R_LITERAL 0x134: ldq t1, 0(t0) // R_LU_BASE 0x138: zap t1, 0x2, t1 0x13c: insbl v0, 0x1, v0 0x140: bis t1, v0, t1 0x144: stq t1, 0(t0) // R_LU_BASE
Relocation entries produced are:
***RELOCATION INFORMATION***
Vaddr Symndx Type Off Size Extern Name
0x0000000000000130 13 LITERAL local .lita
0x0000000000000134 1 LITUSE local R_LU_BASE
0x0000000000000144 1 LITUSE local R_LU_BASE
4.3.4.7
R_LITUSE: R_LU_JSRFields
r_vaddrPoints to jump instruction (in text segment).
r_symndx
R_LU_JSR
r_externMust be zero;
all
R_LITUSE
entries are local.
r_offsetUnused.
r_sizeUnused.
Operation
new_lit = [relocated literal belonging to correponding R_LITERAL] this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr branch_disp = prologue_size + new_lit - this_new_addr + 4 result = branch_disp / 4
Restrictions
Must follow either an
R_LITERAL
or another
R_LITUSE
entry with no
other types intervening.
Result after relocation must not overflow 21 bits (size of branch displacement
field in the branch instruction format).
Description
A relocation entry of this type is informational only.
It informs the
linker that the indicated jump instruction is jumping to an address previously
loaded out of the literal address pool.
The load instruction had an associated
R_LITERAL
entry that precedes this relocation
entry.
Under the right circumstances, the linker can optimize this sequence in several ways:
The procedure prologue can be skipped if it is not needed to load a GP value for the procedure.
The branch can be calculated and the instruction changed to a branch instruction.
The preceding
ldq
can be removed.
The first two actions may be performed but not the last if other
R_LITUSE
entries correspond to the same
R_LITERAL.
These optimization are performed
by the linker for optimization level 1 and greater.
In order to preserve
preemptibility of symbol references, this optimization can only be done for
non-weak global symbols in a static and dynamic executable.
References to
static or hidden symbols can be optimized in executables or shared libraries.
Example
The following instructions illustrate the use of a literal as the target of a jump instruction:
0x8: ldq t12, -32736(gp) // R_LITERAL 0xc: lda sp, -16(sp) 0x10: stq ra, 0(sp) 0x14: jsr ra, (t12) // R_LU_JSR
Relocation entries produced:
***RELOCATION INFORMATION***
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000000008 13 LITERAL local .lita
0x0000000000000014 3 LITUSE local R_LU_JSR
The instructions identified by the
R_LITERAL
and
R_LU_JSR
entries
in this example can be optimized.
The
ldq
instruction can
be replaced with a
NOP
instruction and the
jsr
can be replaced with a
bsr
yielding:
0x1200011a8: ldq_u zero, 0(sp) // NOP 0x1200011ac: lda sp, -16(sp) 0x120001110: stq ra, 0(sp) 0x120001114: bsr ra, 0x1200011d8
r_vaddrPoints to the
first of a pair of instructions:
lda
and
ldah.
Either instruction may occur first.
r_symndxContains the
unsigned byte offset from the instruction indicated in
r_vaddr
to the other instruction used to load the GP value.
r_externMust be zero;
all
R_GPDISP
entries are local.
r_offsetUnused.
r_size
R_GPDISP_NONE
or
R_GPDISP_GP_TAILCALL
(see
Table 4-5)
Operation
result = (old_GP - GP) + (this_old_scn_addr - this_new_scn_addr)
+ (65536 * high_disp) + low_disp
The result after relocation is written back into the instruction pair.
lda_disp = result ldah_disp = (result + 32768) / 65536
Restrictions
Must be a local relocation.
Must describe an
lda/ldah
instruction pair.
Result after relocation must not overflow 32 bits.
Description
A relocation entry of this type corresponds to two instructions
in the code.
The field
r_vaddr
points to one instruction
and the address of the other is computed by adding the value of
r_symndx
to
r_vaddr.
This relocation
entry occurs for each instruction sequence that loads the GP value.
For instance,
procedure entry points typically include instructions which load their effective
GP value.
They are normally the first instructions in a procedure's prologue.
Version Note The
R_GPDISP_GP_TAILCALLflag is supported on Tru64 UNIX V5.1B and greater.
Under certain conditions, the linker can optimize the code by replacing
ldgp instructions with
NOP
instructions.
If this relocation's
r_size
field is set to
R_GPDISP_GP_TAILCALL, the linker will not remove the relocation's targetted ldgp
instruction.
The
R_GPDISP_GP_TAILCALL
flag indicates that the ldgp instruction follows a call to a procedure with
it
gp_tailcall
flag set.
The linker cannot rely
on the state of the GP following the procedure call, so the ldgp instruction
must be retained to insure the GP is properly restored.
Example
A simple example of an occurrence of the
R_GPDISP
entry is the program entry point:
main() {
}
Instructions generated:
0x0: ldah gp, 1(t12) // R_GPDISP (r_vaddr) 0x4: lda gp, -32704(gp) // R_GPDISP (r_vaddr + r_symndx)
Relocation entry produced:
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000000000 4 GPDISP local
There are situations where a procedure is called but the
R_GPDISP
entry is not required.
In this case,
the
gp_used
field of the procedure's descriptor
will be zero, and an
R_LU_JSR
optimization
may cause the prologue to be skipped.
See the
Calling Standard for Alpha Systems
for details
on when a procedure requires calculation of a GP value.
4.3.4.9
R_BRADDRFields
r_vaddrPoints to a branch instruction.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = ((new_scn_addr - old_scn_addr) +
(branch_displacement * 4)
+ r_vaddr + 4 - this_new_addr) / 4
else
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = (EXTR.asym.value + (branch_displacement * 4)
- this_new_addr) / 4
Restrictions
After relocation the result should be aligned on a 4-byte boundary.
The signed result must not overflow the 21-bit branch displacement field.
Description
A relocation entry of this type identifies a branch instruction in the code. The branch displacement is treated as a longword (32-bit, or one instruction) offset. The branch target's virtual address is computed:
va <- PC + (4 * branch_displacement)
The branch displacement must be relocated.
The
R_BRADDR
relocation can only be used for local
or static references because the displacement is fixed at link time.
Updating
it at run time would require writing to the text segment, which is not permitted.
Without the ability to update at run time, symbol preemption for shared objects
will not function.
Example
A relocation of this type is used for a call of a static procedure:
static bar(){
int q =1;
printf ("the value of q is %d\n", q);
}
main (){
bar();
}
Instruction generated:
0x4c: bsr ra, 0x8(zero) // R_BRADDR
Relocation entry produced:
Vaddr Symndx Type Off Size Extern Name
.text:
0x000000000000004c 1 BRADDR local .text
r_vaddrPoints to jump-format instruction.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = ((new_scn_addr - old_scn_addr) + (jump_disp * 4) +
r_vaddr + 4 - this_new_addr) / 4
else
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = (EXTR.asym.value + (jump_displacement * 4) -
this_new_addr) / 4
Restrictions
Result after relocation should be aligned on a 4-byte (instruction-size)
boundary.
Description
Jump instructions are memory-format instructions where the 14 bits of the displacement field serve as a hint for determining the jump target. The hint is PC-relative and must be relocated to remain relevant. Note that the use of hints is for optimization purposes only and takes advantage of branch-prediction logic built into the architecture. If the hint values were not relocated, a correct executable program would still be produced but potential performance improvements would be lost.
A characteristic of
R_HINT
entry processing is that instead of checking for overflow of the 14-bit result
after relocation, the linker truncates the result and writes it back without
issuing an error or warning.
Example
Subroutine calls often cause
R_HINT
entries.
main() {
printf("hello\n");
}
Instructions generated:
0x14: ldq t12, -32752(gp) // R_LITERAL 0x18: jsr ra, (t12), printf // R_HINT
Relocation entries produced:
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000000018 3 LITUSE local R_LU_JSR
0x0000000000000018 0 HINT extern printf
Note that the same source line and corresponding instruction produce
a second relocation entry of type
R_LITUSE_JSR.
This second entry is also informational only.
It indicates
that the target register of the jump instruction contains a previously loaded
literal address.
4.3.4.11
R_SREL16Fields
r_vaddrPoints to a 16-bit self-relative value.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = (new_scn_addr - old_scn_addr) +
SEXT((short)[r_vaddr]) + r_vaddr - this_new_addr
else
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = EXTR.asym.value - this_new_addr
Restrictions
The result after relocation must not overflow 16 bits.
Description
A relocation entry of this type is identical to an
R_SREL32
entry except for the size of the value being adjusted.
Example
This type is currently not used by the compilation system.
4.3.4.12
R_SREL32Fields
r_vaddrPoints to a 32-bit self-relative value.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = (new_scn_addr - old_scn_addr)
+ SEXT((int)[r_vaddr]) + r_vaddr - this_new_addr
else
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = EXTR.asym.value - this_new_addr
Restrictions
The result after relocation must not overflow 32 bits.
Description
A relocation entry of this type indicates a value that describes a reference
as an offset to its own location.
In other words, the target address is computed
by adding the contents of the relocation address ([r_vaddr])
to the address of the relocation (r_vaddr).
To
perform this relocation, the new location of
r_vaddr
must be computed and subtracted from the new target address to provide the
correctly adjusted self-relative, offset which is then written back into the
raw data.
Example
The code range
descriptors that are generated for each object contain a 32-bit self-relative
offset in the
rpd_offset
field.
See
Section 3.2.1.
The
rpd_offset
field contains an offset to the
associated run-time procedure descriptor in the
.xdata
section.
The
R_SREL32
entry identifies
this value.
main(){
printf("Printing\n");
}
Relocation entry produced:
Vaddr Symndx Type Off Size Extern Name
.pdata:
0x0000000000000054 10 SREL32 local .xdata
Note that this relationship between the
.xdata
and
.pdata
sections imposes a restriction on the distance between the
text and data segments.
The run-time procedures in the .xdata section must
be within reach of a 32-bit signed offset from the code range descriptors
in .pdata.
4.3.4.13
R_SREL64Fields
r_vaddrPoints to a 64-bit self-relative value.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = (new_scn_addr - old_scn_addr) + (long)[r_vaddr]
+ r_vaddr - this_new_addr
else
this_new_addr = r_vaddr - this_old_scn_addr + this_new_scn_addr
result = EXTR.asym.value - this_new_addr
Restrictions
None.
Description
A relocation entry of this type is identical to an
R_SREL32
entry except for the size of the value being adjusted.
Example
This type is currently not used by the compilation system.
4.3.4.14
R_OP_PUSHFields
r_vaddr0 if
r_extern
is 1; an unsigned offset within a section if
r_extern
is 0.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
stack[++tos] = (new_scn_addr - old_scn_addr) + r_vaddr
else
stack[++tos] = EXTR.asym.value
Restrictions
This relocation entry must be followed by an
R_OP_STORE
entry, with one or more
R_OP_PSUB
or
R_OP_PRSHIFT
entries in between.
Stack can hold a maximum of 20 entries.
Description
A relocation
entry of this type causes a value to be pushed onto the relocation stack.
The value is generally the target address of the relocation, which will be
adjusted using subsequent
R_OP_PSUB
and
R_OP_PRSHIFT
relocation calculations.
Example
A code range descriptor in the
.pdata
section contains
a 32-bit field,
begin_address, which is the offset
of the associated code range address from the beginning of the code range
descriptor table.
The two low-order bits of this value are used as flags.
See
Section 3.2.1.
This value is calculated by subtracting two addresses,
shifting the result two bits to the right and storing the result in the most
significant 30 bits of the
begin_address
field.
A series of four stack relocation entries is used to represent this offset
calculation.
main(){
foo();
}
foo(){
printf("Printing\n");
}
Relocation entries produced for use in calculating the
begin_address
in the code range descriptor for
foo():
Vaddr Symndx Type Off Size Extern Name
.pdata:
0x0000000000000030 1 PUSH local .text
0x0000000000000000 3 PSUB extern _fpdata
0x0000000000000002 14 PRSHIFT local .abs
0x0000000000000078 11 STORE 2 30 local .pdata
The following series of relocation entries will effectively perform the calculation:
value = (long)(((.text+0x30)-&_fpdata) & 0xffffffff) >> 2; (.pdata+0x78) = ((.pdata+0x78) & 0x3) + (value << 2)
r_vaddrLocation to store calculated bit field.
r_symndxSection index of containing section.
r_externMust be 0.
r_offsetBit offset
from
r_vaddr.
(Bit 0 is the least significant
bit in little-endian objects and the most significant bit in big-endian objects.
See
Section 1.7.)
r_sizeNumber of bits to store.
Operation
if (little_endian)
rshift = r_offset
else
rshift = 64 - (r_offset + r_size)
bitfield = ((long)[r_vaddr] >> r_offset) & ((1 << r_size) - 1)
bitfield <- stack[tos--]
Restrictions
Stack cannot be empty.
Description
A relocation entry of this type causes the value currently on the top
of the relocation stack to be written into a bit field specified by the entry.
The bit field is described using a bit position and size in bits.
Note that
bit numbering is reversed in a big-endian representation.
Example
An example of the
R_OP_STORE
entry is given in
Section 4.3.4.14.
4.3.4.16
R_OP_PSUBFields
r_vaddr0 if
r_extern
is 1; an unsigned offset within a section if
r_extern
is 0.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
result = (new_scn_addr - old_scn_addr) + r_vaddr
stack[tos] = stack[tos] - result
else
result = EXTR.asym.value
stack[tos] = stack[tos] - result
Restrictions
The relocation stack cannot be empty.
This entry must fall somewhere
between an
R_OP_PUSH
entry and an
R_OP_STORE
entry.
Description
A relocation entry of this type causes the value at the top of the relocation
expression stack to be popped, adjusted by subtracting the address described
by
r_extern
and
r_symndx,
and pushed back on the stack.
Example
An example of the
R_OP_STORE
entry is given in
Section 4.3.4.14.
4.3.4.17
R_OP_PRSHIFTFields
r_vaddr0 if
r_extern
is 1; an unsigned offset within a section if
r_extern
is 0.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
if (r_extern == 0)
result = (new_scn_addr - old_scn_addr) + r_vaddr
stack[tos] = stack[tos] >> result
else
result = EXTR.asym.value
stack[tos] = stack[tos] >> result
Restrictions
The stack cannot be empty.
So this entry must fall somewhere between
an
R_OP_PUSH
and an
R_OP_STORE.
Description
A relocation entry of this type causes the value at the top of the relocation
expression stack to be popped, adjusted by right shifting the value by the
number of bits described by
r_extern
and
r_symndx, and pushed back on the stack.
Example
This relocation type can be used to convert a byte offset into an instruction offset. Right shifting a byte offset by two bits will produce an instruction offset because Alpha instructions are 4 bytes wide.
The following assembly code will result in an
R_HINT
entry for the 14-bit instruction offset contained in the
hint field of a
jsr
instruction.
See
Section 4.3.4.10
for a description of the
R_HINT
entry.
0x3c ldq t12, -32752(gp) /* &printf */ 0x40 jsr ra, (t12)
The
R_HINT
entry for the instruction
at
0x40
could also be accomplished with a series of stack
relocation options:
.text:
0x0000000000000000 2 PUSH extern printf
0x0000000000000044 1 PSUB local .text
0x0000000000000002 14 PRSHIFT local .abs
0x0000000000000040 1 STORE 0 14 local .text
r_vaddrStarting virtual address for new GP value.
r_symndxConstant that
is added to the GP value in the
a.out
header to obtain
the new GP value.
r_externMust be zero;
all
R_GPVALUE
entries are local.
r_offsetUnused.
r_sizeUnused.
Operation
new GP = AOUTHDR.gp_value + r_symndx
Restrictions
This type of relocation entry cannot be external.
Description
A relocation
entry of this type identifies the position in the code where a new GP value
takes effect.
R_GPVALUE
entries
are inserted by the linker during partial links.
Example
A linked program that references 20,000
external symbols will have at least 3 GOT entries with 3 corresponding GP
values.
See
Section 2.3.4.
If the program has GP-relative relocation
entries in both
.text
and
.rdata
sections,
two
R_GPVALUE
entries would be reported
for each of these sections.
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000010084cf0 64000 GPVALUE local
0x00000000100cb190 111984 GPVALUE local
.rdata:
0x000000001000fa00 64000 GPVALUE local
0x000000001001b570 111984 GPVALUE local
r_vaddrPoints to a
memory format instruction (ldah).
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
See
R_GPRELLOW
relocation
type.
Restrictions
Must be followed by at least one
R_GPRELLOW.
Relocated result must not overflow unsigned 32-bit range.
Description
A relocation entry of this type is invalid unless it is followed by
at least one
R_GPRELLOW
entry.
When
an
R_GPRELHIGH
entry is encountered,
no calculation is performed.
The relocation calculation is deferred until
the
R_GPRELLOW
entry is processed.
See the
R_GPRELLOW
description for
more information.
Example
See
R_GPRELLOW.
4.3.4.20
R_GPRELLOWFields
r_vaddrPoints to memory
format instruction (ld*
or
st*).
r_symndxMust match
R_GPRELHIGH.
r_externMust match
R_GPRELHIGH.
r_offsetUnused.
r_sizeUnused.
Operation
low_disp = [r_vaddr].displacement
high_disp = [R_GPRELHIGH->r_vaddr].displacement
displacement = high_disp * 65536 + low_disp
if (r_extern = 0)
result = displacement + (new_scn_addr - old_scn_addr) +
(old_GP - GP)
else
result = displacement + EXTR.asym.value + (old_GP - GP)
[R_GPRELHIGH->r_vaddr].displacement = (result+32768) >> 16
[r_vaddr].displacement = result & 0xFFFF
Restrictions
The
R_GPRELHIGH/
R_GPRELLOW
relocations must be used as a pair
or set.
At least one
R_GPRELLOW
entry follows each
R_GPRELHIGH
entry.
After relocation, the result must not overflow 32 bits.
The memory displacement for all
R_GPRELLOW
entries corresponding to the same
R_GPRELHIGH
must match.
Description
The
R_GPRELHIGH/
R_GPRELLOW
entry pair is used to describe GP-relative
memory accesses.
The
R_GPRELHIGH
entry indicates an
ldah
instruction.
The
R_GPRELLOW
entry (or entries) indicates a load or store instruction.
If multiple
R_GPRELLOW
entries are
associated with an
R_GPRELHIGH,
they must all describe the same memory location.
A relocatable address can
be formed with the following computation:
addr = 65536 * high_disp + SEXT (low_disp)
To relocate this code sequence, the memory displacement fields in each instruction must be adjusted to reflect changes in the target address they compute and in the GP value.
The reason these entries are treated as a pair is that sign extension of the low instruction's displacement field can result in an off-by-one error that must be fixed by adding one to the high instruction's displacement. This situation can only be detected if the instructions are considered together.
These relocation entries describe instructions
that are primarily used for computing addresses in kernel code..
The kernel
is built without a
.lita
section, and kernel performance
is enhanced by code that calculates addresses directly instead of loading
addresses from a
.lita
memory location.
The code size,
on average, is unaffected by the kernel's use of this addressing method.
Example
Use the kernel build option -Wb,-static to compile the following sample code.
static int a;
foo(){
a++;
}
Code generated for loading the address of
"a":
0x0: ldah t0, 0(gp) 0x4: lda t0, 16(t0)
Relocation entries produced are:
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000000000 5 GPHIGH local .sbss
0x0000000000000004 5 GPLOW local .sbss
r_vaddrPoints to memory-format instruction.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_size
R_IMMED_GP_16.
Operation
N/A
Restrictions
N/A
Description
A relocation entry of this type identifies an instruction that adds
a 16-bit displacement to the GP value, obtaining an address.
The
r_extern
and
r_symndx
fields specify
the external symbol or section to which the calculated address is relative.
This relocation entry
is created by the linker to indicate that an optimization has taken place
because the displacement is within 16-bits of the GP value.
Example
N/A
4.3.4.22
R_IMMED: GP_HI32Fields
r_vaddrPoints to memory-format instruction.
r_symndxUnused.
r_externUnused.
r_offsetUnused.
r_size
R_IMMED_GP_HI32.
Operation
N/A
Restrictions
N/A
Description
A relocation entry of this type identifies an instruction that is part
of a pair of instructions that add a 32-bit displacement to the GP value.
This instruction adds the high portion of the 32-bit displacement.
The next
R_IMMED_LO32
entry identifies the instruction
containing the low portion of the displacement.
More than one subsequent
R_IMMED_LO32
entry can share the same
R_IMMED_GP_HI32
entry.
Example
N/A
4.3.4.23
R_IMMED: SCN_HI32Fields
r_vaddrPoints to memory-format instruction.
r_symndxUnused.
r_externUnused.
r_offsetUnused.
r_size
R_IMMED_SCNHI32.
Operation
N/A
Restrictions
N/A
Description
A relocation entry of this type identifies an instruction that is part
of a pair of instructions that add a 32-bit displacement to the starting address
of the current section.
This instruction adds the high portion of the displacement.
The next
R_IMMED_LO32
entry identifies
the instruction with the low portion.
Example
N/A
4.3.4.24
R_IMMED: BR_HI32Fields
r_vaddrPoints to a
memory-format instruction following a branch (br,
bsr,
jsr, or
jmp) instruction.
r_symndxSpecifies
a byte offset from
r_vaddr
to the branch instruction.
r_externUnused.
r_offsetUnused.
r_size
R_IMMED_BRHI32.
Operation
N/A
Restrictions
N/A
Description
A relocation entry of this type identifies an instruction that is part
of a pair of instructions that add a 32-bit displacement to the address of
the instruction following a branch (br,
bsr,
jsr, or
jmp).
The branch must precede this instruction.
The
r_symndx
field specifies a byte offset from
r_vaddr
to the branch instruction.
The instruction identified
by this relocation entry adds the high portion of the displacement.
The next
R_IMMED_LO32
entry identifies the instruction
with the low portion of the displacement.
Example
N/A
4.3.4.25
R_IMMED: LO32Fields
r_vaddrPoints to a memory-format instruction.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_size
R_IMMED_LO32.
Operation
N/A
Restrictions
N/A
Description
A relocation entry of this type identifies an instruction that is part
of a pair of instructions that add a 32-bit displacement to a base address.
This instruction adds the low portion of the displacement.
This relocation
entry is combined with the previous
R_IMMED_GP_HI32,
R_IMMED_SCN_HI32,
or
R_IMMED_BR_HI32
entry.
The
r_extern
and
r_symndx
fields specify
the external symbol or section to which the calculated address is relative.
Example
N/A
4.3.4.26
R_TLS_LITERALFields
r_vaddrPoints to an instruction that loads the TSD key for initiating a thread local storage reference actually, not the key itself but key * 8, which gives the offset of the TLS pointer in the TSD array.
r_symndx
R_SN_LITA
r_externMust be zero;
all
R_TLS_LITERAL
entries are local.
r_offsetUnused.
r_sizeUnused.
Operation
result = (new_scn_addr - old_scn_addr) +
(SEXT((short)[r_vaddr]) +old_GP) - GP
Restrictions
The result after relocation for an
R_TLS_LITERAL
entry must not overflow 16 bits.
R_TLS_LITERAL
entries must
be local and relative to the
.lita
section.
Description
A relocation entry of this type is very similar to an
R_LITERAL
entry.
An
R_TLS_LITERAL
entry identifies an instruction that uses a GP displacement
to load an the address of the symbol
__tlsoffset
from the
.lita
section.
The value of the
__tlsoffset
symbol is fixed at run
time to be the TSD array offset of the TLS pointer.
The symbol can occur anywhere
in the GOT or .lita section.
The linker-defined symbol
__tlskey
points to one of the instances of the
__tlsoffset
symbol.
The linker processes the
R_TLS_LITERAL
relocation by adjusting the GP offset in the displacement of
the target instruction.
Example
Routines that reference TLS addresses will have at least one
R_TLS_LITERAL
entry for the load of the
__tlsoffset
value.
__declspec(thread) long foo;
main(){
foo = 2;
}
Code generated will include the instruction:
0x14: ldq at, -32752(gp)
Relocation entry produced:
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000000014 13 TLSLITE local .lita
r_vaddrPoints to memory-format instruction.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
See
R_TLS_LOW
description.
Restrictions
Must be followed by
R_TLS_LOW
entry.
Description
See
R_TLS_LOW.
Example
See
R_TLS_LOW.
4.3.4.28
R_TLS_LOWFields
r_vaddrPoints to memory-format instruction.
r_symndxExternal symbol
index if
r_extern
is 1; section number if
r_extern
is 0.
r_externEither 0 or 1.
r_offsetUnused.
r_sizeUnused.
Operation
low_disp = [r_vaddr].displacement
high_disp = [R_TLS_HIGH->r_vaddr].displacement
displacement = high_disp * 65536 + low_disp
if (r_extern = 0)
result = displacement + (new_scn_addr - old_scn_addr)
else
result = displacement + EXTR.asym.value
[R_TLS_HIGH->r_vaddr].displacement = (result+32768) >> 16
[r_vaddr].displacement = result & 0xFFFF
Restrictions
External relocation entries of this type are limited to TLS symbols.
Local relocation entries of this type are restricted to the TLS sections
.tlsdata
and
.tlsbss.
The relocated result must not exceed 32 bits.
Description
The linker must handle
R_TLS_HIGH
and
R_TLS_LOW
entries as a pair.
The pairs of relocation entries must be in sequence starting with
R_TLS_HIGH.
The order and location of the instructions
associated with these relocation entries are not restricted.
Example
The load of a TLS symbol's address requires an
R_TLS_HIGH/
R_TLS_LOW
entry pair.
__declspec(thread) long foo;
main(){
foo = 2;
}
Code generated:
0x0c: call_pal rduniq 0x10: ldq v0, 96(v0) 0x14: ldq at, -32752(gp) 0x18: addq v0, at, v0 0x1c: ldq v0, 0(v0) 0x20: ldah v0, 0(v0) 0x24: stq t0, 0(v0)
Relocation entries produced:
Vaddr Symndx Type Off Size Extern Name
.text:
0x0000000000000020 0 TLSHIGH extern foo
0x0000000000000024 0 TLSLOW extern foo
4.4 Language-Specific Relocations Features
Relocation entries may be generated for language-specific compiler-generated
external symbols.
For example, they are often generated in Fortran programs
for the procedure
for_set_reentrancy()
and in C++ programs
for exception-handling labels.