4    Object Relocation

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:

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:

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_vaddr

Virtual 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_type

Relocation type code. Table 4-2 lists all possible values.

r_extern

Set to 1 for an external relocation entry. Set to 0 for a local relocation entry.

r_offset

For 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_reserved

Must be zero.

r_size

For 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

Table 4-2:  Relocation Types

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

  1. 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.

  2. 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

Table 4-5:   R_GPDISP Flags

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.

4.2.2    Section Header

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.

Figure 4-3:  Relocation Entry

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:

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:

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:

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:

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:

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 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:

*_disp

The displacement field of whatever instruction is indicated.

GP

Current GP value; begins as the contents of AOUTHDR.gp_value for the final object.

new_scn_addr

The address of the tracked section of a local relocation entry, as calculated by the linker.

old_GP

GP value in the input object; begins as AOUTHDR.gp_value for the input object.

old_scn_addr

The 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.

SEXT

The constant immediately following is sign-extended.

stack

The relocation expression stack.

this_new_addr

Where r_vaddr will be after relocation .

this_new_scn_addr

Where the section containing r_vaddr will be after relocation, as calculated by the linker.

this_old_scn_addr

The contents of s_vaddr in the section header of the input object file for the section containing r_vaddr.

tos

Top of relocation expression stack.

result

The result of the relocation, which is written back into the relocated r_vaddr in the object file that the linker is producing.

4.3.4.1     R_ABS

Fields

r_vaddr

Number of relocation entries if s_nreloc section header field has overflowed. This number includes itself in the count. Otherwise, unused.

r_symndx

Unused.

r_extern

Unused.

r_offset

Unused.

r_size

Unused.

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>

4.3.4.2     R_REFLONG

Fields

r_vaddr

Points to target address.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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

4.3.4.3     R_REFQUAD

Fields

r_vaddr

Points to target address.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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_GPREL32

Fields

r_vaddr

Points to a 32-bit GP-relative value.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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

4.3.4.5     R_LITERAL

Fields

r_vaddr

Points 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_extern

Must be zero; all R_LITERAL entries are local.

r_offset

Unused.

r_size

Unused.

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_BASE

Fields

r_vaddr

Points to memory-format instruction.

r_symndx

R_LU_BASE

r_extern

Must be zero; all R_LITUSE entries are local.

r_offset

Unused.

r_size

Unused.

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_JSR

Fields

r_vaddr

Points to jump instruction (in text segment).

r_symndx

R_LU_JSR

r_extern

Must be zero; all R_LITUSE entries are local.

r_offset

Unused.

r_size

Unused.

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 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

4.3.4.8     R_GPDISP

Fields

r_vaddr

Points to the first of a pair of instructions: lda and ldah. Either instruction may occur first.

r_symndx

Contains the unsigned byte offset from the instruction indicated in r_vaddr to the other instruction used to load the GP value.

r_extern

Must be zero; all R_GPDISP entries are local.

r_offset

Unused.

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_TAILCALL flag 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_BRADDR

Fields

r_vaddr

Points to a branch instruction.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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

4.3.4.10     R_HINT

Fields

r_vaddr

Points to jump-format instruction.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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_SREL16

Fields

>

r_vaddr

Points to a 16-bit self-relative value.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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_SREL32

Fields

r_vaddr

Points to a 32-bit self-relative value.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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_SREL64

Fields

r_vaddr

Points to a 64-bit self-relative value.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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_PUSH

Fields

r_vaddr

0 if r_extern is 1; an unsigned offset within a section if r_extern is 0.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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)

4.3.4.15     R_OP_STORE

Fields

r_vaddr

Location to store calculated bit field.

r_symndx

Section index of containing section.

r_extern

Must be 0.

r_offset

Bit 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_size

Number 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_PSUB

Fields

r_vaddr

0 if r_extern is 1; an unsigned offset within a section if r_extern is 0.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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_PRSHIFT

Fields

r_vaddr

0 if r_extern is 1; an unsigned offset within a section if r_extern is 0.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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

4.3.4.18     R_GPVALUE

Fields

r_vaddr

Starting virtual address for new GP value.

r_symndx

Constant that is added to the GP value in the a.out header to obtain the new GP value.

r_extern

Must be zero; all R_GPVALUE entries are local.

r_offset

Unused.

r_size

Unused.

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

4.3.4.19     R_GPRELHIGH

Fields

r_vaddr

Points to a memory format instruction (ldah).

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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_GPRELLOW

Fields

r_vaddr

Points to memory format instruction (ld* or st*).

r_symndx

Must match R_GPRELHIGH.

r_extern

Must match R_GPRELHIGH.

r_offset

Unused.

r_size

Unused.

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

4.3.4.21     R_IMMED: GP16

Fields

r_vaddr

Points to memory-format instruction.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

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_HI32

Fields

r_vaddr

Points to memory-format instruction.

r_symndx

Unused.

r_extern

Unused.

r_offset

Unused.

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_HI32

Fields

r_vaddr

Points to memory-format instruction.

r_symndx

Unused.

r_extern

Unused.

r_offset

Unused.

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_HI32

Fields

r_vaddr

Points to a memory-format instruction following a branch (br, bsr, jsr, or jmp) instruction.

r_symndx

Specifies a byte offset from r_vaddr to the branch instruction.

r_extern

Unused.

r_offset

Unused.

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: LO32

Fields

r_vaddr

Points to a memory-format instruction.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

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_LITERAL

Fields

r_vaddr

Points 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_extern

Must be zero; all R_TLS_LITERAL entries are local.

r_offset

Unused.

r_size

Unused.

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

4.3.4.27     R_TLS_HIGH

Fields

r_vaddr

Points to memory-format instruction.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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_LOW

Fields

r_vaddr

Points to memory-format instruction.

r_symndx

External symbol index if r_extern is 1; section number if r_extern is 0.

r_extern

Either 0 or 1.

r_offset

Unused.

r_size

Unused.

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.