2
File: PEFBinaryFormat.p
4
Contains: PEF Types and Macros
6
Version: Technology: Master Interfaces
7
Release: Universal Interfaces 3.4.2
9
Copyright: � 1993-2002 by Apple Computer, Inc., all rights reserved.
11
Bugs?: For bug reports, consult the following page on
14
http://www.freepascal.org/bugs.html
20
Modified for use with Free Pascal
22
Please report any bugs to <gpc@microbizz.nl>
33
{$setc UNIVERSAL_INTERFACES_VERSION := $0342}
34
{$setc GAP_INTERFACES_VERSION := $0200}
36
{$ifc not defined USE_CFSTR_CONSTANT_MACROS}
37
{$setc USE_CFSTR_CONSTANT_MACROS := TRUE}
40
{$ifc defined CPUPOWERPC and defined CPUI386}
41
{$error Conflicting initial definitions for CPUPOWERPC and CPUI386}
43
{$ifc defined FPC_BIG_ENDIAN and defined FPC_LITTLE_ENDIAN}
44
{$error Conflicting initial definitions for FPC_BIG_ENDIAN and FPC_LITTLE_ENDIAN}
47
{$ifc not defined __ppc__ and defined CPUPOWERPC}
52
{$ifc not defined __i386__ and defined CPUI386}
58
{$ifc defined __ppc__ and __ppc__ and defined __i386__ and __i386__}
59
{$error Conflicting definitions for __ppc__ and __i386__}
62
{$ifc defined __ppc__ and __ppc__}
63
{$setc TARGET_CPU_PPC := TRUE}
64
{$setc TARGET_CPU_X86 := FALSE}
65
{$elifc defined __i386__ and __i386__}
66
{$setc TARGET_CPU_PPC := FALSE}
67
{$setc TARGET_CPU_X86 := TRUE}
69
{$error Neither __ppc__ nor __i386__ is defined.}
71
{$setc TARGET_CPU_PPC_64 := FALSE}
73
{$ifc defined FPC_BIG_ENDIAN}
74
{$setc TARGET_RT_BIG_ENDIAN := TRUE}
75
{$setc TARGET_RT_LITTLE_ENDIAN := FALSE}
76
{$elifc defined FPC_LITTLE_ENDIAN}
77
{$setc TARGET_RT_BIG_ENDIAN := FALSE}
78
{$setc TARGET_RT_LITTLE_ENDIAN := TRUE}
80
{$error Neither FPC_BIG_ENDIAN nor FPC_LITTLE_ENDIAN are defined.}
82
{$setc ACCESSOR_CALLS_ARE_FUNCTIONS := TRUE}
83
{$setc CALL_NOT_IN_CARBON := FALSE}
84
{$setc OLDROUTINENAMES := FALSE}
85
{$setc OPAQUE_TOOLBOX_STRUCTS := TRUE}
86
{$setc OPAQUE_UPP_TYPES := TRUE}
87
{$setc OTCARBONAPPLICATION := TRUE}
88
{$setc OTKERNEL := FALSE}
89
{$setc PM_USE_SESSION_APIS := TRUE}
90
{$setc TARGET_API_MAC_CARBON := TRUE}
91
{$setc TARGET_API_MAC_OS8 := FALSE}
92
{$setc TARGET_API_MAC_OSX := TRUE}
93
{$setc TARGET_CARBON := TRUE}
94
{$setc TARGET_CPU_68K := FALSE}
95
{$setc TARGET_CPU_MIPS := FALSE}
96
{$setc TARGET_CPU_SPARC := FALSE}
97
{$setc TARGET_OS_MAC := TRUE}
98
{$setc TARGET_OS_UNIX := FALSE}
99
{$setc TARGET_OS_WIN32 := FALSE}
100
{$setc TARGET_RT_MAC_68881 := FALSE}
101
{$setc TARGET_RT_MAC_CFM := FALSE}
102
{$setc TARGET_RT_MAC_MACHO := TRUE}
103
{$setc TYPED_FUNCTION_POINTERS := TRUE}
104
{$setc TYPE_BOOL := FALSE}
105
{$setc TYPE_EXTENDED := FALSE}
106
{$setc TYPE_LONGLONG := TRUE}
113
{ -------------------------------------------------------------------------------------------- }
114
{ Almost all types are padded for natural alignment. However the PEFExportedSymbol type is }
115
{ 10 bytes long, containing two 32 bit fields and one 16 bit field. Arrays of it must be }
116
{ packed, so it requires "68K" alignment. Setting this globally to 68K should also help }
117
{ ensure consistent treatment across compilers. }
119
{ ======================================================================================== }
120
{ Overall Structure }
121
{ ================= }
123
{ -------------------------------------------------------------------------------------------- }
124
{ This header contains a complete set of types and macros for dealing with the PEF executable }
125
{ format. While some description is provided, this header is not meant as a primary source }
126
{ of documentation on PEF. An excellent specification of PEF can be found in the Macintosh }
127
{ Runtime Architectures book. This header is primarily a physical format description. Thus }
128
{ it depends on as few other headers as possible and structure fields have obvious sizes. }
130
{ The physical storage for a PEF executable is known as a "container". This refers to just }
131
{ the executable itself, not the file etc. E.g. if five DLLs are packaged in a single file's }
132
{ data fork, that one data fork has five containers within it. }
134
{ A PEF container consists of an overall header, followed by one or more section headers, }
135
{ followed by the section name table, followed by the contents for the sections. Some kinds }
136
{ of sections have specific internal representation. The "loader" section is the most common }
137
{ of these special sections. It contains information on the exports, imports, and runtime }
138
{ relocations required to prepare the executable. PEF containers are self contained, all }
139
{ portions are located via relative offsets. }
142
{ +-------------------------------+ }
143
{ | Container Header | 40 bytes }
144
{ +-------------------------------+ }
145
{ | Section 0 header | 28 bytes each }
146
{ |...............................| }
148
{ |...............................| }
149
{ | Section n-1 header | }
150
{ +-------------------------------+ }
151
{ | Section Name Table | }
152
{ +-------------------------------+ }
153
{ | Section x raw data | }
154
{ +-------------------------------+ }
156
{ +-------------------------------+ }
157
{ | Section y raw data | }
158
{ +-------------------------------+ }
161
{ The sections are implicitly numbered from 0 to n according to the order of their headers. }
162
{ The headers of the instantiated sections must precede those of the non-instantiated }
163
{ sections. The ordering of the raw data is independent of the section header ordering. }
164
{ Each section header contains the offset for that section's raw data. }
166
{ =========================================================================================== }
172
PEFContainerHeaderPtr = ^PEFContainerHeader;
173
PEFContainerHeader = record
174
tag1: OSType; { Must contain 'Joy!'. }
175
tag2: OSType; { Must contain 'peff'. (Yes, with two 'f's.) }
176
architecture: OSType; { The ISA for code sections. Constants in CodeFragments.h. }
177
formatVersion: UInt32; { The physical format version. }
178
dateTimeStamp: UInt32; { Macintosh format creation/modification stamp. }
179
oldDefVersion: UInt32; { Old definition version number for the code fragment. }
180
oldImpVersion: UInt32; { Old implementation version number for the code fragment. }
181
currentVersion: UInt32; { Current version number for the code fragment. }
182
sectionCount: UInt16; { Total number of section headers that follow. }
183
instSectionCount: UInt16; { Number of instantiated sections. }
184
reservedA: UInt32; { Reserved, must be written as zero. }
189
kPEFTag1 = $4A6F7921 (* 'Joy!' *); { For non-Apple compilers: 0x4A6F7921. }
190
kPEFTag2 = $70656666 (* 'peff' *); { For non-Apple compilers: 0x70656666. }
191
kPEFVersion = $00000001;
194
kPEFFirstSectionHeaderOffset = 40;
197
{ =========================================================================================== }
203
PEFSectionHeaderPtr = ^PEFSectionHeader;
204
PEFSectionHeader = record
205
nameOffset: SInt32; { Offset of name within the section name table, -1 => none. }
206
defaultAddress: UInt32; { Default address, affects relocations. }
207
totalLength: UInt32; { Fully expanded size in bytes of the section contents. }
208
unpackedLength: UInt32; { Size in bytes of the "initialized" part of the contents. }
209
containerLength: UInt32; { Size in bytes of the raw data in the container. }
210
containerOffset: UInt32; { Offset of section's raw data. }
211
sectionKind: SInt8; { Kind of section contents/usage. }
212
shareKind: SInt8; { Sharing level, if a writeable section. }
213
alignment: SInt8; { Preferred alignment, expressed as log 2. }
214
reservedA: SInt8; { Reserved, must be zero. }
219
{ Values for the sectionKind field. }
220
{ Section kind values for instantiated sections. }
221
kPEFCodeSection = 0; { Code, presumed pure & position independent. }
222
kPEFUnpackedDataSection = 1; { Unpacked writeable data. }
223
kPEFPackedDataSection = 2; { Packed writeable data. }
224
kPEFConstantSection = 3; { Read-only data. }
225
kPEFExecDataSection = 6; { Intermixed code and writeable data. }
226
{ Section kind values for non-instantiated sections. }
227
kPEFLoaderSection = 4; { Loader tables. }
228
kPEFDebugSection = 5; { Reserved for future use. }
229
kPEFExceptionSection = 7; { Reserved for future use. }
230
kPEFTracebackSection = 8; { Reserved for future use. }
233
{ Values for the shareKind field. }
234
kPEFProcessShare = 1; { Shared within a single process. }
235
kPEFGlobalShare = 4; { Shared across the entire system. }
236
kPEFProtectedShare = 5; { Readable across the entire system, writeable only to privileged code. }
239
{ =========================================================================================== }
240
{ Packed Data Contents }
241
{ ==================== }
243
{ -------------------------------------------------------------------------------------------- }
244
{ The raw contents of a packed data section are a sequence of byte codes. The basic format }
245
{ has a 3 bit opcode followed by a 5 bit count. Additional bytes might be used to contain }
246
{ counts larger than 31, and to contain a second or third count. Further additional bytes }
247
{ contain actual data values to transfer. }
249
{ All counts are represented in a variable length manner. A zero in the initial 5 bit count }
250
{ indicates the actual value follows. In this case, and for the second and third counts, the }
251
{ count is represented as a variable length sequence of bytes. The bytes are stored in big }
252
{ endian manner, most significant part first. The high order bit is set in all but the last }
253
{ byte. The value is accumulated by shifting the current value up 7 bits and adding in the }
254
{ low order 7 bits of the next byte. }
256
{ The packed data opcodes. }
257
kPEFPkDataZero = 0; { Zero fill "count" bytes. }
258
kPEFPkDataBlock = 1; { Block copy "count" bytes. }
259
kPEFPkDataRepeat = 2; { Repeat "count" bytes "count2"+1 times. }
260
kPEFPkDataRepeatBlock = 3; { Interleaved repeated and unique data. }
261
kPEFPkDataRepeatZero = 4; { Interleaved zero and unique data. }
264
kPEFPkDataOpcodeShift = 5;
265
kPEFPkDataCount5Mask = $1F;
266
kPEFPkDataMaxCount5 = 31;
267
kPEFPkDataVCountShift = 7;
268
kPEFPkDataVCountMask = $7F;
269
kPEFPkDataVCountEndMask = $80;
272
{ -------------------------------------------------------------------------------------------- }
273
{ The following code snippet can be used to input a variable length count. }
277
{ byte = *bytePtr++; }
278
{ count = (count << kPEFPkDataVCountShift) | (byte & kPEFPkDataVCountMask); }
279
{ ) while ( (byte & kPEFPkDataVCountEndMask) != 0 ); }
281
{ The following code snippet can be used to output a variable length count to a byte array. }
282
{ This is more complex than the input code because the chunks are output in big endian order. }
283
{ Think about handling values like 0 or 0x030000. }
286
{ tempValue = value >> kPEFPkDataCountShift; }
287
{ while ( tempValue != 0 ) ( }
289
{ tempValue = tempValue >> kPEFPkDataCountShift; }
292
{ bytePtr += count; }
293
{ tempPtr = bytePtr - 1; }
294
{ *tempPtr-- = value; // ! No need to mask, only the low order byte is stored. }
295
{ for ( count -= 1; count != 0; count -= 1 ) ( }
296
{ value = value >> kPEFPkDataCountShift; }
297
{ *tempPtr-- = value | kPEFPkDataCountEndMask; }
300
{ =========================================================================================== }
304
{ -------------------------------------------------------------------------------------------- }
305
{ The loader section contains information needed to prepare the code fragment for execution. }
306
{ This includes this fragment's exports, the import libraries and the imported symbols from }
307
{ each library, and the relocations for the writeable sections. }
309
{ +-----------------------------------+ <-- containerOffset --------+ }
310
{ | Loader Info Header | 56 bytes | }
311
{ |-----------------------------------| | }
312
{ | Imported Library 0 | 24 bytes each | }
313
{ |...................................| | }
315
{ |...................................| | }
316
{ | Imported Library l-1 | | }
317
{ |-----------------------------------| | }
318
{ | Imported Symbol 0 | 4 bytes each | }
319
{ |...................................| | }
321
{ |...................................| | }
322
{ | Imported Symbol i-1 | | }
323
{ |-----------------------------------| | }
324
{ | Relocation Header 0 | 12 bytes each | }
325
{ |...................................| | }
327
{ |...................................| | }
328
{ | Relocation Header r-1 | | }
329
{ |-----------------------------------| <-- + relocInstrOffset -----| }
330
{ | Relocation Instructions | | }
331
{ |-----------------------------------| <-- + loaderStringsOffset --| }
332
{ | Loader String Table | | }
333
{ |-----------------------------------| <-- + exportHashOffset -----+ }
334
{ | Export Hash Slot 0 | 4 bytes each }
335
{ |...................................| }
337
{ |...................................| }
338
{ | Export Hash Slot h-1 | }
339
{ |-----------------------------------| }
340
{ | Export Symbol Key 0 | 4 bytes each }
341
{ |...................................| }
343
{ |...................................| }
344
{ | Export Symbol Key e-1 | }
345
{ |-----------------------------------| }
346
{ | Export Symbol 0 | 10 bytes each }
347
{ |...................................| }
349
{ |...................................| }
350
{ | Export Symbol e-1 | }
351
{ +-----------------------------------+ }
355
PEFLoaderInfoHeaderPtr = ^PEFLoaderInfoHeader;
356
PEFLoaderInfoHeader = record
357
mainSection: SInt32; { Section containing the main symbol, -1 => none. }
358
mainOffset: UInt32; { Offset of main symbol. }
359
initSection: SInt32; { Section containing the init routine's TVector, -1 => none. }
360
initOffset: UInt32; { Offset of the init routine's TVector. }
361
termSection: SInt32; { Section containing the term routine's TVector, -1 => none. }
362
termOffset: UInt32; { Offset of the term routine's TVector. }
363
importedLibraryCount: UInt32; { Number of imported libraries. ('l') }
364
totalImportedSymbolCount: UInt32; { Total number of imported symbols. ('i') }
365
relocSectionCount: UInt32; { Number of sections with relocations. ('r') }
366
relocInstrOffset: UInt32; { Offset of the relocation instructions. }
367
loaderStringsOffset: UInt32; { Offset of the loader string table. }
368
exportHashOffset: UInt32; { Offset of the export hash table. }
369
exportHashTablePower: UInt32; { Export hash table size as log 2. (Log2('h')) }
370
exportedSymbolCount: UInt32; { Number of exported symbols. ('e') }
373
{ =========================================================================================== }
374
{ Imported Libraries }
375
{ ------------------ }
376
PEFImportedLibraryPtr = ^PEFImportedLibrary;
377
PEFImportedLibrary = record
378
nameOffset: UInt32; { Loader string table offset of library's name. }
379
oldImpVersion: UInt32; { Oldest compatible implementation version. }
380
currentVersion: UInt32; { Current version at build time. }
381
importedSymbolCount: UInt32; { Imported symbol count for this library. }
382
firstImportedSymbol: UInt32; { Index of first imported symbol from this library. }
383
options: SInt8; { Option bits for this library. }
384
reservedA: SInt8; { Reserved, must be zero. }
385
reservedB: UInt16; { Reserved, must be zero. }
390
{ Bits for the PEFImportedLibrary options field. }
391
kPEFWeakImportLibMask = $40; { The imported library is allowed to be missing. }
392
kPEFInitLibBeforeMask = $80; { The imported library must be initialized first. }
395
{ =========================================================================================== }
399
{ -------------------------------------------------------------------------------------------- }
400
{ The PEFImportedSymbol type has the following bit field layout. }
404
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
405
{ | symbol class | offset of symbol name in loader string table | }
406
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
407
{ |<-- 8 bits --->|<-- 24 bits ---------------------------------->| }
411
PEFImportedSymbolPtr = ^PEFImportedSymbol;
412
PEFImportedSymbol = record
413
classAndName: UInt32;
418
kPEFImpSymClassShift = 24;
419
kPEFImpSymNameOffsetMask = $00FFFFFF;
420
kPEFImpSymMaxNameOffset = $00FFFFFF; { 16,777,215 }
423
{ Imported and exported symbol classes. }
424
kPEFCodeSymbol = $00;
425
kPEFDataSymbol = $01;
426
kPEFTVectorSymbol = $02;
428
kPEFGlueSymbol = $04;
429
kPEFUndefinedSymbol = $0F;
430
kPEFWeakImportSymMask = $80;
433
{ =========================================================================================== }
434
{ Exported Symbol Hash Table }
435
{ -------------------------- }
437
{ -------------------------------------------------------------------------------------------- }
438
{ Exported symbols are described in four parts, optimized for speed of lookup. These parts }
439
{ are the "export hash table", the "export key table", the "export symbol table", and the }
440
{ "export name table". Overall they contain a flattened representation of a fairly normal }
441
{ hashed symbol table. }
443
{ The export hash table is an array of small fixed size elements. The number of elements is }
444
{ a power of 2. A 32 bit hash word for a symbol is converted into an index into this array. }
445
{ Each hash slot contains a count of the number of exported symbols that map to this slot and }
446
{ the index of the first of those symbols in the key and symbol tables. Of course some hash }
447
{ slots will have a zero count. }
449
{ The key and symbol tables are also arrays of fixed size elements, one for each exported }
450
{ symbol. Their entries are grouped by hash slot, those elements mapping to the same hash }
451
{ slot are contiguous. The key table contains just the full 32 bit hash word for each }
452
{ exported symbol. The symbol table contains the offset of the symbol's name in the string }
453
{ table and other information about the exported symbol. }
455
{ To look up an export you take the hashword and compute the hash slot index. You then scan }
456
{ the indicated portion of the key table for matching hashwords. If a hashword matches, you }
457
{ look at the corresponding symbol table entry to find the full symbol name. If the names }
458
{ match the symbol is found. }
460
{ -------------------------------------------------------------------------------------------- }
461
{ The following function may be used to compute the hash table size. Signed values are used }
462
{ just to avoid potential code generation overhead for unsigned division. }
464
{ UInt8 PEFComputeHashTableExponent ( SInt32 exportCount ) }
468
{ const SInt32 kExponentLimit = 16; // Arbitrary, but must not exceed 30. }
469
{ const SInt32 kAverageChainLimit = 10; // Arbitrary, for space/time tradeoff. }
471
{ for ( exponent = 0; exponent < kExponentLimit; exponent += 1 ) ( }
472
{ if ( (exportCount / (1 << exponent)) < kAverageChainLimit ) break; }
477
{ ) // PEFComputeHashTableExponent () }
479
{ -------------------------------------------------------------------------------------------- }
480
{ The PEFExportedSymbolHashSlot type has the following bit field layout. }
484
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
485
{ | symbol count | index of first export key | }
486
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
487
{ |<-- 14 bits -------------->|<-- 18 bits ---------------------->| }
491
PEFExportedSymbolHashSlotPtr = ^PEFExportedSymbolHashSlot;
492
PEFExportedSymbolHashSlot = record
493
countAndStart: UInt32;
498
kPEFHashSlotSymCountShift = 18;
499
kPEFHashSlotFirstKeyMask = $0003FFFF;
500
kPEFHashSlotMaxSymbolCount = $00003FFF; { 16,383 }
501
kPEFHashSlotMaxKeyIndex = $0003FFFF; { 262,143 }
504
{ =========================================================================================== }
505
{ Exported Symbol Hash Key }
506
{ ------------------------ }
510
PEFSplitHashWordPtr = ^PEFSplitHashWord;
511
PEFSplitHashWord = record
516
PEFExportedSymbolKeyPtr = ^PEFExportedSymbolKey;
517
PEFExportedSymbolKey = record
520
fullHashWord: UInt32;
523
splitHashWord: PEFSplitHashWord;
529
kPEFHashLengthShift = 16;
530
kPEFHashValueMask = $0000FFFF;
531
kPEFHashMaxLength = $0000FFFF; { 65,535 }
534
{ ---------------------------------------------------------------------------------------------------- }
535
{ The following function computes the full 32 bit hash word. }
537
{ UInt32 PEFComputeHashWord ( BytePtr nameText, // ! First "letter", not length byte. }
538
{ UInt32 nameLength ) // ! The text may be zero terminated. }
540
{ BytePtr charPtr = nameText; }
541
{ SInt32 hashValue = 0; // ! Signed to match old published algorithm. }
542
{ UInt32 length = 0; }
547
{ #define PseudoRotate(x) ( ( (x) << 1 ) - ( (x) >> 16 ) ) }
549
{ for ( limit = nameLength; limit > 0; limit -= 1 ) ( }
550
{ currChar = *charPtr++; }
551
{ if ( currChar == NULL ) break; }
553
{ hashValue = PseudoRotate ( hashValue ) ^ currChar; }
556
{ result = (length << kPEFHashLengthShift) | }
557
{ ((UInt16) ((hashValue ^ (hashValue >> 16)) & kPEFHashValueMask)); }
561
{ ) // PEFComputeHashWord () }
563
{ =========================================================================================== }
569
PEFExportedSymbolPtr = ^PEFExportedSymbol;
570
PEFExportedSymbol = record
571
{ ! This structure is 10 bytes long and arrays are packed. }
572
classAndName: UInt32; { A combination of class and name offset. }
573
symbolValue: UInt32; { Typically the symbol's offset within a section. }
574
sectionIndex: SInt16; { The index of the section, or pseudo-section, for the symbol. }
577
{ -------------------------------------------------------------------------------------------- }
578
{ The classAndName field of the PEFExportedSymbol type has the following bit field layout. }
582
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
583
{ | symbol class | offset of symbol name in loader string table | }
584
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
585
{ |<-- 8 bits --->|<-- 24 bits ---------------------------------->| }
589
kPEFExpSymClassShift = 24;
590
kPEFExpSymNameOffsetMask = $00FFFFFF;
591
kPEFExpSymMaxNameOffset = $00FFFFFF; { 16,777,215 }
594
{ Negative section indices indicate pseudo-sections. }
595
kPEFAbsoluteExport = -2; { The symbol value is an absolute address. }
596
kPEFReexportedImport = -3; { The symbol value is the index of a reexported import. }
599
{ =========================================================================================== }
600
{ Loader Relocations }
601
{ ================== }
603
{ -------------------------------------------------------------------------------------------- }
604
{ The relocations for a section are defined by a sequence of instructions for an abstract }
605
{ machine that is specifically geared to performing relocations commonly needed for the "CFM" }
606
{ code generation model. These instructions occur in 16 bit chunks. Most instructions have }
607
{ just a single chunk. Instructions that are larger than 16 bits have an opcode and some of }
608
{ the operands in the first chunk, with other operands in following chunks. }
610
{ ! Note that the multi-chunk relocations have separate "Compose" macros for each chunk. The }
611
{ ! macros have the same basic name with a positional suffix of "_1st", "_2nd", etc. }
615
PEFRelocChunk = UInt16;
616
PEFLoaderRelocationHeaderPtr = ^PEFLoaderRelocationHeader;
617
PEFLoaderRelocationHeader = record
618
sectionIndex: UInt16; { Index of the section to be fixed up. }
619
reservedA: UInt16; { Reserved, must be zero. }
620
relocCount: UInt32; { Number of 16 bit relocation chunks. }
621
firstRelocOffset: UInt32; { Offset of first relocation instruction. }
624
{ -------------------------------------------------------------------------------------------- }
625
{ ! Note that the relocCount field is the number of 16 bit relocation chunks, i.e. 1/2 the }
626
{ ! total number of bytes of relocation instructions. While most relocation instructions are }
627
{ ! 16 bits long, some are longer so the number of complete relocation instructions may be }
628
{ ! less than the relocCount value. }
630
{ ------------------------------------------------------------------------------------ }
631
{ The PEFRelocField macro is a utility for extracting relocation instruction fields. }
633
{ =========================================================================================== }
634
{ Basic Relocation Opcodes }
635
{ ------------------------ }
636
{ -------------------------------------------------------------------------------------------- }
637
{ The number of opcode bits varies from 2 to 7. The enumeration and switch table given here }
638
{ are defined in terms of the most significant 7 bits of the first instruction chunk. An }
639
{ instruction is decoded by using the most significant 7 bits as an index into the opcode }
640
{ table, which in turn contains appropriately masked forms of the most significant 7 bits. }
641
{ The macro PEFRelocBasicOpcode assumes a declaration of the form. }
643
{ UInt8 kPEFRelocBasicOpcodes [kPEFRelocBasicOpcodeRange] = ( PEFMaskedBasicOpcodes ); }
647
kPEFRelocBasicOpcodeRange = 128;
650
{ -------------------------------------------------------------------------------------------- }
651
{ The relocation opcodes, clustered by major and minor groups. The instructions within a }
652
{ cluster all have the same bit field layout. The enumeration values use the high order 7 }
653
{ bits of the relocation instruction. Unused low order bits are set to zero. }
654
kPEFRelocBySectDWithSkip = $00; { Binary: 00x_xxxx }
655
kPEFRelocBySectC = $20; { Binary: 010_0000, group is "RelocRun" }
656
kPEFRelocBySectD = $21; { Binary: 010_0001 }
657
kPEFRelocTVector12 = $22; { Binary: 010_0010 }
658
kPEFRelocTVector8 = $23; { Binary: 010_0011 }
659
kPEFRelocVTable8 = $24; { Binary: 010_0100 }
660
kPEFRelocImportRun = $25; { Binary: 010_0101 }
661
kPEFRelocSmByImport = $30; { Binary: 011_0000, group is "RelocSmIndex" }
662
kPEFRelocSmSetSectC = $31; { Binary: 011_0001 }
663
kPEFRelocSmSetSectD = $32; { Binary: 011_0010 }
664
kPEFRelocSmBySection = $33; { Binary: 011_0011 }
665
kPEFRelocIncrPosition = $40; { Binary: 100_0xxx }
666
kPEFRelocSmRepeat = $48; { Binary: 100_1xxx }
667
kPEFRelocSetPosition = $50; { Binary: 101_000x }
668
kPEFRelocLgByImport = $52; { Binary: 101_001x }
669
kPEFRelocLgRepeat = $58; { Binary: 101_100x }
670
kPEFRelocLgSetOrBySection = $5A; { Binary: 101_101x }
671
kPEFRelocUndefinedOpcode = $FF; { Used in masking table for all undefined values. }
674
{ ---------------------------------------------------------------------------- }
675
{ The RelocLgSetOrBySection instruction has an additional 4 bits of subopcode }
676
{ beyond the 7 used by the dispatch table. To be precise it has 6 plus 4 but }
677
{ the dispatch table ignores the 7th bit, so the subdispatch is on all 4 extra }
679
kPEFRelocLgBySectionSubopcode = $00; { Binary: 0000 }
680
kPEFRelocLgSetSectCSubopcode = $01; { Binary: 0001 }
681
kPEFRelocLgSetSectDSubopcode = $02; { Binary: 0010 }
684
{ -------------------------------------------------------------------------------------------- }
685
{ The initial values for the opcode "masking" table. This has the enumeration values from }
686
{ above with appropriate replications for "don't care" bits. It is almost certainly shorter }
687
{ and faster to look up the masked value in a table than to use a branch tree. }
689
{ =========================================================================================== }
690
{ RelocBySectDWithSkip Instruction (DDAT) }
691
{ --------------------------------------- }
693
{ -------------------------------------------------------------------------------------------- }
694
{ The "RelocBySectDWithSkip" (DDAT) instruction has the following bit field layout. }
698
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
699
{ |0 0| skip count | rel count | }
700
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
701
{ | 2 |<-- 8 bits --->|<-- 6 --->| }
703
{ ! Note that the stored skip count and reloc count are the actual values! }
704
kPEFRelocWithSkipMaxSkipCount = 255;
705
kPEFRelocWithSkipMaxRelocCount = 63;
708
{ =========================================================================================== }
709
{ RelocRun Group (CODE, DATA, DESC, DSC2, VTBL, SYMR) }
710
{ --------------------------------------------------- }
712
{ -------------------------------------------------------------------------------------------- }
713
{ The "RelocRun" group includes the "RelocBySectC" (CODE), "RelocBySectD" (DATA), }
714
{ "RelocTVector12" (DESC), "RelocTVector8" (DSC2), "RelocVTable8" (VTBL), and }
715
{ "RelocImportRun" (SYMR) instructions. This group has the following bit field layout. }
719
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
720
{ |0 1 0| subop.| run length | }
721
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
722
{ | 3 |<- 4 ->|<-- 9 bits ----->| }
724
{ ! Note that the stored run length is the actual value minus 1, but the macros deal with the }
726
kPEFRelocRunMaxRunLength = 512;
729
{ =========================================================================================== }
730
{ RelocSmIndex Group (SYMB, CDIS, DTIS, SECN) }
731
{ ------------------------------------------- }
733
{ -------------------------------------------------------------------------------------------- }
734
{ The "RelocSmIndex" group includes the "RelocSmByImport" (SYMB), "RelocSmSetSectC" (CDIS), }
735
{ "RelocSmSetSectD" (DTIS) and "RelocSmBySection" (SECN) instructions. This group has the }
736
{ following bit field layout. }
740
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
741
{ |0 1 1| subop.| index | }
742
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
743
{ | 3 |<- 4 ->|<-- 9 bits ----->| }
745
{ ! Note that the stored index is the actual value! }
746
kPEFRelocSmIndexMaxIndex = 511;
749
{ =========================================================================================== }
750
{ RelocIncrPosition Instruction (DELT) }
751
{ ------------------------------------ }
753
{ -------------------------------------------------------------------------------------------- }
754
{ The "RelocIncrPosition" (DELT) instruction has the following bit field layout. }
758
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
759
{ |1 0 0 0| offset | }
760
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
761
{ |<- 4 ->|<-- 12 bits ---------->| }
763
{ ! Note that the stored offset is the actual value minus 1, but the macros deal with the }
765
kPEFRelocIncrPositionMaxOffset = 4096;
768
{ =========================================================================================== }
769
{ RelocSmRepeat Instruction (RPT) }
770
{ ------------------------------- }
772
{ -------------------------------------------------------------------------------------------- }
773
{ The "RelocSmRepeat" (RPT) instruction has the following bit field layout. }
777
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
778
{ |1 0 0 1| chnks | repeat count | }
779
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
780
{ |<- 4 ->|<- 4 ->|<-- 8 bits --->| }
782
{ ! Note that the stored chunk count and repeat count are the actual values minus 1, but the }
783
{ ! macros deal with the actual values! }
784
kPEFRelocSmRepeatMaxChunkCount = 16;
785
kPEFRelocSmRepeatMaxRepeatCount = 256;
788
{ =========================================================================================== }
789
{ RelocSetPosition Instruction (LABS) }
790
{ ----------------------------------- }
792
{ -------------------------------------------------------------------------------------------- }
793
{ The "RelocSetPosition" (LABS) instruction has the following bit field layout. }
797
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
798
{ |1 0 1 0 0 0| offset (high) | | offset (low) | }
799
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
800
{ |<-- 6 ---->|<-- 10 bits ------>| |<-- 16 bits ------------------>| }
802
{ ! Note that the stored offset is the actual value! }
803
kPEFRelocSetPosMaxOffset = $03FFFFFF; { 67,108,863 }
806
{ =========================================================================================== }
807
{ RelocLgByImport Instruction (LSYM) }
808
{ ---------------------------------- }
810
{ -------------------------------------------------------------------------------------------- }
811
{ The "RelocLgByImport" (LSYM) instruction has the following bit field layout. }
815
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
816
{ |1 0 1 0 0 1| index (high) | | index (low) | }
817
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
818
{ |<-- 6 ---->|<-- 10 bits ------>| |<-- 16 bits ------------------>| }
820
{ ! Note that the stored offset is the actual value! }
821
kPEFRelocLgByImportMaxIndex = $03FFFFFF; { 67,108,863 }
824
{ =========================================================================================== }
825
{ RelocLgRepeat Instruction (LRPT) }
826
{ -------------------------------- }
828
{ -------------------------------------------------------------------------------------------- }
829
{ The "RelocLgRepeat" (LRPT) instruction has the following bit field layout. }
833
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
834
{ |1 0 1 1 0 0| chnks | rpt (high)| | repeat count (low) | }
835
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
836
{ |<-- 6 --->|<- 4 ->|<-- 6 --->| |<-- 16 bits ------------------>| }
838
{ ! Note that the stored chunk count is the actual value minus 1, but the macros deal with }
839
{ ! the actual value! The stored repeat count is the actual value! }
840
kPEFRelocLgRepeatMaxChunkCount = 16;
841
kPEFRelocLgRepeatMaxRepeatCount = $003FFFFF; { 4,194,303 }
844
{ =========================================================================================== }
845
{ RelocLgSetOrBySection Group (LSEC) }
846
{ ---------------------------------- }
848
{ -------------------------------------------------------------------------------------------- }
849
{ The "RelocLgSetOrBySection" (LSEC) instruction is a group including the "RelocLgBySection", }
850
{ "RelocLgSetSectC" and "RelocLgSetSectD" instructions. This group has the following bit }
855
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
856
{ |1 0 1 1 0 1| subop | idx (high)| | index (low) | }
857
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
858
{ |<-- 6 --->|<- 4 ->|<-- 6 --->| |<-- 16 bits ------------------>| }
860
{ ! Note that the stored index is the actual value! }
861
kPEFRelocLgSetOrBySectionMaxIndex = $003FFFFF; { 4,194,303 }