Important: The information in this document is obsolete and should not be used for new development.
Relocations
Relocations (sometimes called fix-ups) are part of a process by which the Code Fragment Manager replaces references to code and data with actual addresses at runtime. The loader section contains information on how to perform these relocations. These relocations apply to any symbols accessed via pointers, such as imported code and data, or a fragment's own pointer-based function calls.By the very nature of pointer-based references, you cannot know the actual address that a pointer refers to at build time. Instead, the compiler includes placeholders than can be fixed up by the Code Fragment Manager at preparation time.
For example, a reference to an imported routine points to a transition vector. Before preparation, the pointer in the calling fragment that points to the transition vector has the value
0
. After instantiating the called fragment at preparation time, the actual address of the transition vector becomes known. The Code Fragment Manager then executes a relocation instruction that adds the address of the transition vector to the pointer that references it. The pointer then points to the transition vector in the called fragment's data section.Relocation information is stored in PEF containers using a number of specialized instructions and variables, which act much like machine-language instructions for a pseudo-microprocessor. These elements reduce the number of bytes required to store the relocation information and reduce the time required to perform the relocations.
The pseudo-microprocessor maintains state information in pseudo-registers. For the state to be correct for each instruction, relocation instructions must be executed in order from start to finish for each section.
The relocation instructions make use of the variables shown in Table 8-4. The initial values are set by the Code Fragment Manager prior to executing the relocations for each section.
The relocation instructions themselves generally accomplish one of the following functions:
- Note
- The
sectionC
andsectionD
variables actually contain the memory address of an instantiated section minus the default address for that section. The default address for a section is contained in thedefaultAddress
field of the section header. However, in almost all cases the default address should be0
, so the simplified definition suffices.
- assign a value to one of the relocation variables
- add an imported symbol's address to the current location (pointed to by
relocAddress
), then incrementimportIndex
andrelocAddress
- add the
sectionC
value to the current location, then incrementrelocAddress
- add the
sectionD
value to the current location, then incrementrelocAddress
- add the
sectionC
value to the current location and incrementrelocAddress
, then add thesectionD
value to the new current location, and incrementrelocAddress
again
The Relocation Headers Table
If an instantiated section requires one or more relocations, it has an entry in the relocation headers table. A header entry data structure is of fixed size (12 bytes) and has the form shown in Listing 8-5.Listing 8-5 Relocation header entry data structure
struct PEFLoaderRelocationHeader { UInt16sectionIndex; UInt16reservedA; UInt32relocCount; UInt32firstRelocOffset; };The header fields are as follows:
Note that the
- The
sectionIndex
field (2 bytes) designates the section number to which this relocation header refers.- The
reservedA
field (2 bytes) is currently reserved and must be set to0
.- The
relocCount
field (4 bytes) indicates the number of 16-bit relocation blocks for this section.- The
firstRelocOffset
field (4 bytes) indicates the byte offset from the start of the relocations area to the first relocation instruction for this section.
relocCount
field is the number of 16-bit relocation blocks (that is, one half the total number of bytes of relocation instructions). Although most relocation instructions are 16 bits long, some are longer, so the number of complete relocation instructions may be less than therelocCount
value.The Relocation Area
The relocation area consists of a sequence of relocation instructions that describe how to fix up pointers to the fragment's own code and data and to imported symbols during the preparation process. These instructions are grouped by section number, and they are accessed through the relocation headers described earlier. See "Relocation Instruction Set" (page 8-27) for a detailed description of the relocation instructions.A Relocation Example
This section gives an example of how various relocation instructions are used. In this example, a fragment calls the imported routinemoo
. At build time, all pointers tomoo
in the calling fragment are set to0
, since the compiler or linker cannot know the actual runtime address of the routine. Similarly, in the fragment that containsmoo
, the transition vector formoo
contains only offset values for the location of its code and its data world. Figure 8-9 shows the unprepared state for the two fragments.Figure 8-9 Unprepared fragments
After instantiating both fragments, the Code Fragment Manager fixes up the calling fragment's pointer by executing instructions as follows (see Figure 8-10):
Figure 8-10 Relocations for the calling fragment
- Set
relocAddress
to point to the data pointer formoo
.- Set
importIndex
to select the imported symbol entry formoo
.- Execute a relocation instruction that adds the address of the imported symbol
moo
(that is, the address of its transition vector) to the 4 bytes atrelocAddress
.
After being fixed up, the calling fragment's pointer now points to the transition vector for
moo
.The pointers for the called fragment are fixed up as follows (see Figure 8-11):
Figure 8-11 Relocations for the called fragment
- Set
relocAddress
to point to the beginning of the transition vector formoo
.- Set
sectionC
to point to the beginning of the code section containingmoo
.- Set
sectionD
to point to the beginning of the called fragment's data section.- Execute a relocation instruction that adds
sectionC
to the contents of the location pointed to byrelocAddress
; incrementsrelocAddress
(4 bytes); addssectionD
to the contents of the location pointed to by the newrelocAddress
; and incrementsrelocAddress
again.
After being fixed up, the transition vector for
moo
now contains the actual address ofmoo
and the base register address for its data world. The routinemoo
is now prepared for execution.Relocation Instruction Set
Relocation instructions are stored in 2-byte relocation blocks. Most instructions take up one block that combines an opcode and related arguments. Instructions that are larger than 2 bytes have an opcode and some of the operands in the first 2-byte block, with other operands in the following 2-byte blocks. The opcode occupies the upper (higher-order) bits of the block that contains it. Relocation instructions can be decoded from the high-order 7 bits of their first block. Listing 8-6 shows the high-order 7 bits for the currently defined relocation opcode values. Binary values indicated by "x
" are "don't care" operands. For example, any combination of the high-order 7 bits that starts with two zero bits (00
) indicates the RelocBySectDWithSkip instruction.All currently defined relocation instructions relocate locations as words (that is, 4-byte values).
Listing 8-6 Relocation opcode values
enum { kPEFRelocBySectDWithSkip= 0x00,/* binary: 00xxxxx */ kPEFRelocBySectC = 0x20, /* binary: 0100000 */ kPEFRelocBySectD = 0x21, /* binary: 0100001 */ kPEFRelocTVector12 = 0x22, /* binary: 0100010 */ kPEFRelocTVector8 = 0x23, /* binary: 0100011 */ kPEFRelocVTable8 = 0x24, /* binary: 0100100 */ kPEFRelocImportRun = 0x25, /* binary: 0100101 */ kPEFRelocSmByImport = 0x30, /* binary: 0110000 */ kPEFRelocSmSetSectC = 0x31, /* binary: 0110001 */ kPEFRelocSmSetSectD = 0x32, /* binary: 0110010 */ kPEFRelocSmBySection = 0x33, /* binary: 0110011 */ kPEFRelocIncrPosition= 0x40, /* binary: 1000xxx */ kPEFRelocSmRepeat = 0x48, /* binary: 1001xxx */ kPEFRelocSetPosition = 0x50, /* binary: 101000x */ kPEFRelocLgByImport = 0x52, /* binary: 101001x */ kPEFRelocLgRepeat = 0x58, /* binary: 101100x */ kPEFRelocLgSetOrBySection= 0x5A,/* binary: 101101x */ };The following sections describe the individual instructions in more detail.
- IMPORTANT
- If you wish to create your own relocation instructions, the 3 highest order bits must be set (
111xxxx
) to indicate a third-party opcode. All other undocumented opcode values are reserved.RelocBySectDWithSkip
TheRelocBySectDWithSkip
instruction (opcode 00) has the structure shown in Figure 8-12.Figure 8-12 Structure of the
RelocBySectDWithSkip
instruction
This instruction first increments
relocAddress
by skipCount * 4 bytes. It then adds the value ofsectionD
to the next relocCount contiguous words. After the instruction is executed,relocAddress
points just past the last modified word.The Relocate Value Group
Instructions in the Relocate Value group of opcodes all begin with010
and have the structure shown in Figure 8-13.Figure 8-13 Structure of the Relocate Value opcode group
Instructions in this group add a value to the next runLength items starting at address
relocAddress
. The subopcode indicates the type and size of the items to be added as shown in Table 8-5. After execution,relocAddress
points to just past the last modified item.
- IMPORTANT
- The value stored in this instruction is one less than the actual run length (runLength-1).
The Relocate By Index Group
Instructions in the Relocate By Index group all begin with011
and have the structure shown in Figure 8-14.Figure 8-14 Structure of the Relocate By Index opcode group
Instructions in this group fix up values according to the subopcode values shown in Table 8-6.
RelocIncrPosition
TheRelocIncrPosition
instruction (opcode 1000) has the structure shown in Figure 8-15.Figure 8-15 Structure of the
RelocIncrPosition
instruction
This instruction increments
relocAddress
by offset bytes. The value of offset is treated as an unsigned value.
- IMPORTANT
- The value stored in this instruction is one less than the actual offset (offset-1).
RelocSmRepeat
TheRelocSmRepeat
instruction (opcode 1001) has the structure shown in Figure 8-16.Figure 8-16 Structure of the
RelocSmRepeat
instruction
This instruction repeats the preceding blockCount relocation blocks repeatCount number of times. Note that you cannot nest this instruction within itself or within the
RelocLgRepeat
instruction.
- IMPORTANT
- The values of blockCount and repeatCount stored in this instruction are one less than the actual values.
RelocSetPosition
TheRelocSetPosition
instruction (opcode 101000) takes two relocation blocks (4 bytes) rather than the usual one; the extra bytes allow you to specify an unsigned offset parameter of up to 26 bits.The
RelocSetPosition
instruction has the structure shown in Figure 8-17.Figure 8-17 Structure of the
RelocSetPosition
instruction
This instruction sets
relocAddress
to the address of the section offset offset.RelocLgByImport
TheRelocLgByImport
instruction (opcode 101001) takes two relocation blocks (4 bytes); the extra bytes allow you to specify an unsigned index parameter of up to 26 bits.The
RelocLgByImport
instruction has the structure shown in Figure 8-18.Figure 8-18 Structure of the
RelocLgByImport
instruction
This instruction adds the address of the imported symbol whose index is held in index to the word pointed to by
relocAddress
. After the addition,relocAddress
points to just past the modified word, andimportIndex
is set to index +1.RelocLgRepeat
TheRelocLgRepeat
instruction (opcode 101100) takes two relocation blocks and has the structure shown in Figure 8-19.Figure 8-19 Structure of the
RelocLgRepeat
instruction
This instruction repeats the preceding blockCount relocation blocks repeatCount number of times. The
RelocLgRepeat
instruction is very similar to therelocSmRepeat
(opcode 1001) instruction, but it allows for larger repeat counts.You cannot nest this instruction, either within itself or within the
relocSmRepeat
instruction.
- IMPORTANT
- Note that the repeat value stored in this instruction is the actual value (repeatCount), while for the
relocSmRepeat
instruction the value stored is repeatCount-1. The block count value stored is blockCount-1 for both repeat instructions.RelocLgSetOrBySection
TheRelocLgSetOrBySection
instruction (opcode 101101) takes two relocation blocks and has the form shown in Figure 8-20.Figure 8-20 Structure of the
RelocLgSetOrBySection
instruction
This instruction performs instructions identical to those shown in "The Relocate By Index Group" (page 8-31), but with a larger (up to 22-bit, unsigned) section number. The action specified depends on the value of subopcode as shown in Table 8-7.