Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Mac OS Runtime Architectures /
Chapter 8 - PEF Structure / The Loader Section


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.
Table 8-4 Relocation variables
NameDescription
relocAddressHolds an address within the section where the relocations are to be performed. The initial value is the base address of the section that is to be relocated.
importIndexHolds a symbol index, which is used to access an imported symbol's address.(The address can then be used for relocation.) The initial value is 0.
sectionCHolds the memory address of an instantiated section within the PEF container; this variable is used by relocation instructions that relocate section addresses. The initial value is the memory address of section 0 if that section is present and instantiated. Otherwise the initial sectionC value is 0.

Note that relocation instructions can change the value of SectionC; this affects subsequent relocation instructions that refer to this variable.

The name sectionC is given for convenience only; use of this variable is not restricted to code sections.

sectionDHolds the memory address of an instantiated section within the PEF container; this variable is used by relocation instructions that relocate section addresses. The initial value is the memory address of section 1 if that section is present and instantiated. Otherwise the initial sectionD value is 0.

Note that relocation instructions can change the value of sectionD; this affects subsequent relocation instructions that refer to this variable.

The name sectionD is given for convenience only; use of this variable is not restricted to data sections.

Note
The sectionC and sectionD 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 the defaultAddress field of the section header. However, in almost all cases the default address should be 0, so the simplified definition suffices.
The relocation instructions themselves generally accomplish one of the following functions:

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 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 the relocCount 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 routine moo. At build time, all pointers to moo in the calling fragment are set to 0, since the compiler or linker cannot know the actual runtime address of the routine. Similarly, in the fragment that contains moo, the transition vector for moo 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):

  1. Set relocAddress to point to the data pointer for moo.
  2. Set importIndex to select the imported symbol entry for moo.
  3. 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 at relocAddress.

Figure 8-10 Relocations for the calling fragment

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

  1. Set relocAddress to point to the beginning of the transition vector for moo.
  2. Set sectionC to point to the beginning of the code section containing moo.
  3. Set sectionD to point to the beginning of the called fragment's data section.
  4. Execute a relocation instruction that adds sectionC to the contents of the location pointed to by relocAddress; increments relocAddress (4 bytes); adds sectionD to the contents of the location pointed to by the new relocAddress; and increments relocAddress again.

Figure 8-11 Relocations for the called fragment

After being fixed up, the transition vector for moo now contains the actual address of moo and the base register address for its data world. The routine moo 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 */

};
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.
The following sections describe the individual instructions in more detail.

RelocBySectDWithSkip

The RelocBySectDWithSkip 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 of sectionD 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 with 010 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).
Table 8-5 Subopcodes for the RelocateValue opcode group
ValueInstruction nameDescription
0000RelocBySectCAdd the value in the variable sectionC to the next runLength contiguous 4-byte items (words).
0001RelocBySectDAdd the value in the variable sectionD to the next runLength contiguous 4-byte items (words).
0010RelocTVector12Add values to runLength 12-byte items as follows: add the value in sectionC to the first word and the value in sectionD to the second word. No value is added to the third word.
0011RelocTVector8Add values to runLength 8-byte items as follows: add the value in sectionC to the first word and the value in sectionD to the second word.
0100RelocVTable8Add values to runLength 8-byte items as follows: add the value in sectionD to the first word and do not add any value to the second word.
0101RelocImportRunAdd the addresses of a sequence of imported symbols to the next runLength contiguous 4-byte items (words). The importIndex variable is incremented by 1 after every 4-byte relocation (runLength times total).

The Relocate By Index Group

Instructions in the Relocate By Index group all begin with 011 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.
Table 8-6 Subopcodes for the Relocate By Index opcode group
ValueInstruction nameDescription
0000RelocSmByImportAdd 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, and importIndex is set to index +1.
0001RelocSmSetSectCSet the variable sectionC to the memory address of the instantiated section specified by index.
0010RelocSmSetSectDSet the variable sectionD to the memory address of the instantiated section specified by index.
0011RelocSmBySectionAdd the address of the instantiated section specified by index to the word pointed to by relocAddress. After execution, relocAddress points to just past the modified word.

RelocIncrPosition

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

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

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

The RelocLgByImport 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, and importIndex is set to index +1.

RelocLgRepeat

The RelocLgRepeat 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 the relocSmRepeat (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

The RelocLgSetOrBySection 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.
Table 8-7 Subopcodes for the RelocLgSetOrBySection instruction
SubopcodeAction
0000Add the address of the instantiated section specified by index to the word at relocAddress. After the addition, relocAddress points to just past the modified word. (Same as RelocSmBySection.)
0001Set the variable sectionC to the memory address of the instantiated section specified by index. (Same as RelocSmSetSectC.)
0010Set the variable sectionD to the memory address of the instantiated section specified by index. (Same as RelocSmSetSectD.)


Previous Book Contents Book Index Next

© Apple Computer, Inc.
11 MARCH 1997