4   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 three distinct representations:

The first two forms of relocation information are discussed in this chapter. Note that the discussion of the second form is limited to Section 4.4. The third form is covered in Chapter 6. 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 Relocations Features

Version 3.13 of the object file format does not introduce any new relocations features.


4.2   Structures, Fields, and Values for Relocations


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.
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.
There are exceptions to this interpretation:
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

Table 4-2 Relocation Types

Symbol

Value

Description

R_ABS

0x0

Relocation already performed.

R_REFLONG

0x1

Identifies a 32-bit reference to symbol's virtual address.

R_REFQUAD

0x2

Identifies a 64-bit reference to symbol's virtual address.

R_GPREL32

0x3

Identifies a 32-bit displacement from the global pointer to a symbol's virtual address.

R_LITERAL

0x4

Identifies a reference to a literal in the literal address pool as an offset from the global pointer.

R_LITUSE1

0x5

Identifies an instance of a literal address previously loaded into a register.

R_GPDISP

0x6

Identifies an lda/ldah instruction pair that is used to initialize a procedure's global-pointer register.

R_BRADDR

0x7

Identifies a 21-bit branch reference to the symbol's virtual address.

R_HINT

0x8

Identifies a 14-bit jsr hint reference to symbol's virtual address.

R_SREL16

0x9

Identifies a 16-bit self-relative reference to symbol's virtual address.

R_SREL32

0xa

Identifies a 32-bit self-relative reference to symbol's virtual address.

R_SREL64

0xb

Identifies a 64-bit self-relative reference to symbol's virtual address.

R_OP_PUSH

0xc

Identifies a 64-bit virtual address to push on the relocation expression stack.

R_OP_STORE

0xd

Identifies an address to store the value popped from the relocation expression stack.

R_OP_PSUB

0xe

Identifies a symbol's virtual address to subtract from value at the top of the relocation expression stack.

R_OP_PRSHIFT

0xf

Identifies the number of bit positions to shift the value at the top of the relocation expression stack.

R_GPVALUE

0x10

Specifies a new gp value to be used for the address range starting with the address specified by the r_vaddr field.

R_GPRELHIGH

0x11

Identifies the most significant 16 bits of a 32-bit from the global pointer to a symbol's virtual address.

R_GPRELLOW

0x12

Identifies the least significant 16 bits of a 32-bit from the global pointer to a symbol's virtual address.

R_IMMED2

0x13

Indicates an instruction sequence that calculates an address.

R_TLS_LITERAL

0x14

Identifies the instruction that loads the TLS key.

R_TLS_HIGH

0x15

Identifies the most significant 16 bits of a 32-bit from the TLS region pointer to a symbol's virtual address

R_TLS_LOW

0x16

Identifies the least significant 16 bits of a 32-bit 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


4.2.2   Compact Relocation Subsection (of .comment section)

Compact relocation records are written into the free-form data area of the comment section. They are identified by a tag type of CM_COMPACT_RLC in the comment header. The public versions of compact relocation interfaces for producers and consumers are located in the header file cmplrs/cmrlc.h. See Section 4.4 and Chapter 7 for more information.


4.2.3   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_nrelocs. If that field overflows, the section header flag S_NRELOCS_OVFL is set and the first relocation entry's r_symndx 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   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 drivers, which are object files that are dynamically added to a running kernel. Information is available in the System Administration Guide.

Relocatable objects can also be used by the bootlinker, 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 4.4.


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 whenever necessary to prevent it from becoming outdated. 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 symbols 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_GP_VALUE 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_32 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 an item 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 correponding 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_GP16 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. Optimization cannot be done for external symbols that are weak symbols in a dynamic executable, hidden symbols in a shared library, or unresolved.

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

Unused.

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.

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

An example that will result in production of this type of relocation is a procedure call of a static function:

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, withone 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. See Section 3.2.1. This value is calculated by subtracting two addresses and storing the least significant 32 bits. A series of three 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 foo's code range descriptor:

          Vaddr         Symndx   Type  Off Size Extern  Name

.pdata:

    0x0000000000000030       1    PUSH          local   .text
    0x0000000000000000       3    PSUB          extern   _fpdata
    0x0000000000000078      11   STORE  0   32  local    .pdata

The following series of relocation entries will effectively perform the calculation:

(.pdata+0x78)  =  (long)(((.text+0x30)-&_fpdata) & 0xffffffff)

 


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. It should be noted that bits are numbered differently depending on the endian-ness of the object.

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 is not currently used by the system compiler. A potential use of this relocation type would be 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    R_SN_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_GP16.

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 __tls_offset 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   Compact Relocations

Compact relocations are a highly compressed form of relocation records designed for the use of profiling tools and object restructuring tools. By default, they are generated by the linker for all fully linked executable objects and recorded in the object's .comment section. The linker produces this information using libmld.a APIs, which implement the reading and writing of compact relocations. Compact relocations are not produced for images linked with the following linker options: -r, -om, or -ncr. See Chapter 7 for the format of the .comment section.

Compact relocations must provide crucial relocation information in much less space than the space required for actual relocation entries. This goal is accomplished by employing a heuristic function to predict relocations. For some sections, this heuristic is highly accurate. Detailing many records in the object file becomes unnecessary because the algorithm can be used instead to recreate many of the actual relocation entries.

The current implementation contains only enough relocation information to drive tools that restructure an executable's .text, .init, and .fini sections. It is sufficient for compact relocations to handle text segment relocations only because the current consumers (Atom-based tools) change only these sections. There is currently no algorithm to predict data relocations.

The interfaces for compact relocations continue to evolve. These interfaces are defined and described in the header file cmplrs/cmrlc.h. This section describes the on-disk file format of compact relocations and the producer and consumer algorithms.


4.4.1   Overview

The procedure for creation of compact relocations is as follows:

  1. Generate a list of predicted relocations using heuristics.
  2. Compare the predicted relocations to the actual relocation entries (which are input data to the compact relocations producer).
  3. Wherever a "miss" occurs (that is, the predicted and actual entries do not match) output a compact relocation record.

The procedure for the use of compact relocation records follows:

  1. Generate the list of predicted relocations using the same heuristics as the compact relocations producer.
  2. Compare the expanded compact relocations data with predicted relocations to reconstruct the actual relocation entries.

See Section 4.4.3 for more details.


4.4.2   File Format

Compact relocations are stored in a subsection of the .comment section. The linker and other tools do not need to be aware of the details of the internal structure of the compact relocation subsection. This knowledge is encapsulated in the cmrlc_* routines found in libmld.a.

The on-disk format of the compact relocations data consists of the following components, in order:

Code may only assume that the version and the file header are contiguous. To access other structures, it is necessary to rely on the location information in the file header.


4.4.2.1   Compact Relocations Version

The compact relocation section begins with a version identifier, which has the following structure:

struct {
        unsigned int   version_major;
        unsigned int   version_minor;
};

SIZE - 8 bytes, ALIGNMENT - 4 bytes

The version identifier allows the format of the compact relocations to change from one release to another while providing a mechanism for tools to work on binaries with either the old or new formats. The version identifiers are separate from the header because the format of the header itself may change from release to release.

The major version identifier is incremented whenever a change in the compact relocation algorithms affects the external interface. For example, adding support for data-related relocation information would require the major version identifier to be incremented. Simple bug fixes that correct problems with the external interface should not cause the major version identifier to be incremented.

The minor version identifier is incremented whenever the compact relocation algorithms change without affecting the external interface. For example, changing the heuristic to further compact the stored relocation information would require the minor version identifier to be incremented. If the consumer routines see that an object has an old minor version number, they can call a matching version of the heuristic to correctly reconstruct the relocation information.


4.4.2.2   Compact Relocations File Header

The version identifier is followed by a high-level header structure that stores the sizes and locations of the other tables with compact relocations information:

struct cmrlc_file_header {
        /*
         * Total number of elements in each sub-table.
         */
        unsigned long	scn_num;    /* section header table */
        unsigned long	rlc_num;    /* compact relocation table */
        unsigned long	expr_num;   /* expression relocation table */
        unsigned long	gpval_num;  /* GP value table */

        /*
         * Relative file offset from start of compact relocation data
         * to each sub-table.
         */
        unsigned long	scn_off;
        unsigned long	rlc_off;
        unsigned long	expr_off;
        unsigned long	gpval_off;
};

SIZE - 64 bytes, ALIGNMENT - 8 bytes

Each of the *_num fields indicates the number of entries in the corresponding tables. Each of the *_off fields contains a relative file offset from the start of the compact relocations .comment subsection to the start of the corresponding table. If any of the tables are not present for a particular program, the *_num and *_off fields should be set to zero.


4.4.2.3   Compact Relocations Section Header

One or more compact relocations section headers follow the compact relocations file header. Each section header has the following structure:

struct cmrlc_file_scnhdr {
        char           name[8];    /* section name */

        /*
         * Number of elements for this section in each sub-table.
         */
        unsigned long  rlc_snum;
        unsigned long  expr_snum;
        unsigned long  gpval_snum;

        /*
         * Index from start of table to this section's elements.
         * (This is an element index, not a byte offset.)
         */
        unsigned long  rlc_indx;
        unsigned long  expr_indx;
        unsigned long  gpval_indx;

        /*
         * Flag: True if compact relocation table is sorted by
         * increasing virtual address.
         */
         unsigned long  rlc_sorted:1;
         unsigned long  :63;
};

SIZE - 64 bytes, ALIGNMENT - 8 bytes

One compact relocation section header is created for each eCOFF object file section for which compact relocation data is stored. This section header is unrelated to the eCOFF section header structure except for the name field, which connects the two.

Each of the *_num fields indicates the number of entries in the corresponding table for this object file section. If the *_num field is non-zero, the corresponding *_indx field contains the index of the start of that section's entries within the table.

The rlc_sorted field indicates whether the compact relocation table entries for this section are sorted by virtual address.

If an object file section does not have entries in one of the tables for a particular program, the corresponding fields should be set to zero.


4.4.2.4   Compact Relocations Table

Compact relocation tables follow the compact relocation section headers. Each compact relocation table consists of an array of structures:

struct cmrlc_file_rlc {
    unsigned	v_offset;
    union {
	unsigned 	word;
	struct {
	    unsigned	type:5;
	    unsigned	:27;
	} common;
	struct {		/* GPDISP */
	    unsigned	type:5;
	    unsigned	lda_offset:27;
	} gpdisp;
	struct {		/* EXPRESSION */
	    unsigned	type:5;
	    unsigned	index:27;
	} expr;
	struct {		/* REF*, SREL*, GPREL32 */
	    unsigned	type:5;
	    unsigned	rel_scn:5;
	    unsigned	count:12;
	    unsigned	:10;
	} addrtype;
	struct {         	/* IMMED: GP_HI32, SCN_HI32, BR_HI32 */
	    unsigned 	type:5;
	    unsigned 	subop:6;
	    unsigned	br_offset:21;
	} immedhi;
	struct {        	/* IMMED: all other sub-opcodes */
	    unsigned 	type:5;
	    unsigned 	subop:6;
	    unsigned 	rel_scn:5;
	    unsigned	:16;
	} immedlo;
	struct {		/* VADJUST */
	    unsigned	type:5;
	    signed	adjust:27;
	} vadjust;
	struct {		/* BRADDR, HINT */
	    unsigned 	type:5;
	    unsigned	rel_scn:5;
	    unsigned	:22;
	} other;
    } info;
};

SIZE - 8 bytes, ALIGNMENT - 4 bytes

/*
 * Values for 'type' field.
 */
enum cmrlc_rlctypes {
    CMRLC_REFLONG=1,       /* unpredicted R_REFLONG */
    CMRLC_REFQUAD=2,       /* unpredicted R_REFQUAD */
    CMRLC_GPREL32=3,       /* unpredicted R_GPREL32 */
    CMRLC_GPDISP=4,        /* unpredicted R_GPDISP */
    CMRLC_BRADDR=5,        /* unpredicted R_BRADDR */
    CMRLC_HINT=6,          /* unpredicted R_HINT */
    CMRLC_SREL16=7,        /* unpredicted R_SREL16 */
    CMRLC_SREL32=8,        /* unpredicted R_SREL32 */
    CMRLC_SREL64=9,        /* unpredicted R_SREL64 */
    CMRLC_EXPRESSION=10,   /* unpredicted R_OP_* expression */
    CMRLC_IMMEDHI=11,      /* unpredicted R_IMMED for high part */
    CMRLC_IMMEDLO=12,      /* unpredicted R_IMMED for low part */
    CMRLC_NO_RELOC=13,     /* correct mispredicted relocation */
    CMRLC_VADJUST=14,      /* adjust base for succeeding 'v_offset's */
    CMRLC_TLS_HIGH=15,     /* unpredicted R_TLS_HIGH */
    CMRLC_TLS_LOW=16       /* unpredicted R_TLS_LOW */
};

/*
 * Maximum value for 'count' field in 'addrtype' relocations.
 */
#define CMRLC_COUNT_MAX 	((1<<12) - 1)

The number of elements in the array is determined by the corresponding *_num field in the section header.

The v_offset field specifies the virtual address of each relocation entry as a byte offset from a base address. Initially, the base is the starting virtual address of the current section. If relocations are required at addresses that cannot be expressed as a 32-bit offset from the section's start address, CMRLC_VADJUST relocation entries are used to extend the addressing range. However, this feature is not fully supported.

The value of the type field determines how to interpret the remainder of a compact relocation structure.

The lda_offset field specifies an instruction offset (byte offset divided by 4) from the relocation entrys virtual address to the lda instruction in an R_GPDISP entry's ldah/lda pair. This design does not support ldah/lda pairs that are separated by more than 2^29 bytes.

The rel_scn field indicates the ID of the section to which this relocation is relative. It uses the R_SN_* values from the header file reloc.h.

The count field is used to specify consecutive relocation entries that are identical. The count field can be used in this manner for R_REFLONG, R_REFQUAD, R_SREL16, R_SREL32, R_SREL64, and R_GPREL32 entries. Two relocation entries are identical if they have the same type and relative section. Two relocation entries are consecutive if the difference in their virtual addresses is equal to the natural size for the relocation type (16 bits for R_SREL16; 32 bits for R_REFLONG, R_SREL32, and R_GPREL32; and 64 bits for R_REFQUAD and R_SREL64). A count value of zero is not allowed. The count field reduces the impact of mispredicting the relocations for jump tables.


4.4.2.5   Stack Relocation Table

Expression stack relocation information is stored separately. Each stack relocation table entry has the following structure:

struct cmrlc_file_expr {
        unsigned long  vaddr;
        unsigned       type:5;
        unsigned       rel_scn:5;
        unsigned       offset:6;  /* CMRLC_EXPR_STORE only */
        unsigned       size:6;    /* CMRLC_EXPR_STORE only */
        unsigned       last:1;    /* true for last reloc in expr */
        unsigned       :9;
        unsigned       reserved;
};

SIZE - 16 bytes, ALIGNMENT - 8 bytes

/*
 * Values for 'type' field.
 */
enum cmrlc_exprtypes {
        CMRLC_EXPR_PUSH=1,     /* R_OP_PUSH */
        CMRLC_EXPR_PSUB=2,     /* R_OP_PSUB */
        CMRLC_EXPR_PRSHIFT=3,  /* R_OP_PRSHIFT */
        CMRLC_EXPR_STORE=4     /* R_OP_STORE */
};

Expression stack compact relocation records are stored in a separate table because each record requires more space than other types of compact relocation records. Entries in this table are grouped into sequences of relocation entries that form a single expression. The first entry in each table starts a sequence. The last entry in each sequence has its last field set to one. A new sequence starts immediately after the end of the previous sequence.

The start of each sequence is referenced by a CMRLC_EXPRESSION entry in the section's compact relocation table. The index field of that entry points to the first entry in a stack relocation sequence. All sequences in the stack relocation table should have a corresponding CMRLC_EXPRESSION entry in the compact relocation table.


4.4.2.6   GP Value Tables

Additional tables called GP value tables are used to store GP range information. GP values are kept in tables separate from other compact relocations to reduce the processing required to map a virtual address to the corresponding active GP value.

Each GP value table consists of an array of these structures:

struct {
        unsigned long     vaddr
        unsigned          gp_offset
        unsigned          reserved
};

SIZE - 16 bytes, ALIGNMENT - 8 bytes

Each additional GP range after the first range has an entry in the table. (The first range is described by the GP value in the file's a.out header.) Therefore, a single-GOT program will have no entries in its GP value tables.

If an executable's sections have different numbers of GP ranges, gpval_num should be set to describe the section with the largest number of ranges. eCOFF sections with fewer GP ranges must still have GP value tables with gpval_num entries. Sections with short GP value tables can duplicate their last GP value table entry until the table is the proper length.

The vaddr field contains the virtual address where the new range starts. vaddr must point within the section to which this GP value table corresponds. The new GP value is computed by adding gp_offset to the GP value in the file's a.out header.


4.4.3   Detailed Algorithm for Compact Relocations Production

In order to produce compact relocations, a tool must have a set of actual relocation entries and the raw data to which those relocation entries apply. It should then apply the following algorithm to create a set of matching compact relocations:

  1. Remove any actual relocation entries not needed to describe the .text, .init, or .fini sections.
  2. Convert the remaining external relocation entries to local relocation entries.
  3. Run the prediction heuristic function to construct a set of predicted relocation entries from the raw data.
  4. Compare the predicted relocation entries to the remaining actual relocation entries and create a compact relocation record for any mismatches.
  5. Compress any sequences of consecutive, identical R_REF*, R_SREL*,or R_GPREL32 entries.
  6. Set the rlc_sorted field if the compact relocation entries are stored in a sorted order.

The tool should first remove any actual relocation entries that are not needed to describe the .text, .init, or .fini sections. Compact relocation entries describe only these sections, so any others should be removed to save space. In general, any relocation entry relative to one of these sections must be saved. Also, any self-relative relocation entry that points inside one of these sections must be saved. Because R_GPDISP entries point to instructions that are implicitly relative to text addresses, any R_GPDISP entries within the .text, .init, or .fini sections must also be preserved. Finally, any R_REFLONG, R_REFQUAD, and R_GPREL32 entries in the .text, .init, or .fini sections must be saved because these relocation entries would indicate the presence of address constants in these sections. Note that R_LITERAL and R_LITUSE entries describe addresses in the .lita or .got section, so they do not need to be saved.

A tool must take special care when analyzing expression stack (R_OP_*), R_IMMED, and R_GPRELHIGH/R_GPRELLOW entries. It is not possible to determine if one of these entries needs to be saved without analyzing it in the context of its other related relocation entries. For instance, an expression stack relocation must be saved if any relocation in its expression is relative to the .text, .init, or .fini sections. The same is true for sequences of R_IMMED entries or sequences of R_GPRELHIGH/R_GPRELLOW entries.

Any R_GPVALUE entries must also be handled specially. These relocation entries must be added to their section's GP value table. They should then be removed from the list of actual relocation entries used to create compact relocations.

The second step in the algorithm is to convert any remaining actual relocation entries from external to local. The compact relocations only exist in fully linked executables with no undefined symbols. Thus, external relocation entries are not needed. An external relocation entry is converted to a local relocation entry by setting its r_extern field to zero and changing its r_symndx field to the appropriate R_SN_* constant.

The third step is to run the prediction heuristic function over the raw data for which these actual relocation entries apply. This produces a set of predicted relocation entries.

Then compare the predicted relocation entries to the actual relocation entries as follows:

  1. If a match exists between a predicted relocation entry and an actual relocation entry at the same virtual address, do nothing.
  2. If a predicted relocation entry and an actual relocation entry at the same virtual address do not match, write a compact form of the actual relocation entry to the compact relocation data file.
  3. If only a predicted relocation entry exists for a particular virtual address, write a compact CMRLC_NO_RELOC record to the data file at this virtual address.
  4. If only an actual relocation entry exists for a particular virtual address, write a compact form of the actual relocation entry to the compact relocation data file.

Creating a compact relocation entry from an actual relocation entry is fairly straightforward except in the case of an expression stack relocation sequence. First, create entries in the stack relocation table for each relocation entry in the sequence. Normally, this sequence starts with an R_OP_PUSH entry and ends with an R_OP_STORE entry. The last entry should have the last field set to one. Then create an EXPRESSION compact relocation entry whose index field points to the first entry in the stack relocation table for this expression. (This can only be done for a sequence that describes a complete expression.)

The fifth step is to compress any sequences of R_REF*, R_SREL*, or R_GPREL32 entries that are consecutive and identical . Such a sequence exists if all relocation entries in the sequence have the same relocation type, are relative to the same rel_scn value (R_SN_* constant), and have v_offset fields that increase by the natural size of the relocation type (for example, 8 bytes for REFQUAD, 2 bytes for SREL16). Such sequences can be replaced with a single compact relocation entry that has the sequence's type and rel_scn value. The v_offset field should be that of the first relocation entry in the sequence, and the count field should be set to the number of relocation entries in the sequence.

The final step is to set the rlc_sorted field in the compact relocation section header. If the compact relocations are stored in order of increasing v_offset values, this field should be set to one. Otherwise, it should be set to zero.


4.4.4   Detailed Algorithm for Compact Relocations Consumption

A consumer tool can read back the compact relocation entries if it has the compact relocation information and the raw data that they describe. The consumer tool can use this information to regenerate the actual relocation entries by following this algorithm:

  1. Expand any R_REF*, R_SREL*, or R_GPREL32 compact relocation entries whose count field is greater than one.
  2. Run the prediction heuristic function to construct a set of predicted relocation entries from the raw data.
  3. Compare the predicted relocation entries to the compact relocation entries and reconstruct the actual relocation entries.

The first step in this algorithm just undoes the compression step (step five) in the production algorithm.

The second step runs the same prediction heuristic that was used in the production algorithm. To guarantee that the generated predicted relocation entries are the same as when the compact relocation entries were produced, it is critical that the heuristic function is the same. It is also critical that the raw data is the same as when the compact relocation entries were produced.

The final step compares the predicted relocation entries with the stored compact relocation entries as follows:

  1. If only a predicted relocation entry exists for a particular virtual address, report the predicted relocation entry.
  2. If a CMRLC_NO_RELOC entry exists at the same virtual address as a predicted relocation entry, do not report a relocation entry at this virtual address.
  3. If a compact relocation entry other than CMRLC_NO_RELOC exists at the same virtual address as a predicted relocation entry, report the compact relocation entry.
  4. If only a compact relocation entry exists for a particular virtual address, report the compact relocation entry.
The basic strategy for compact relocations consumption is to step through both the predicted relocation entries and the stored compact relocation mismatch data for a given section in order to reconstruct the actual relocation entries for that section.


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