Mac OS 9
PEFBinaryFormat.h
Go to the documentation of this file.
1 
20 #ifndef __PEFBINARYFORMAT__
21 #define __PEFBINARYFORMAT__
22 
23 #ifndef __MACTYPES__
24 #include <MacTypes.h>
25 #endif
26 
27 #if PRAGMA_ONCE
28 #pragma once
29 #endif
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #if PRAGMA_IMPORT
36 #pragma import on
37 #endif
38 
39 #if PRAGMA_STRUCT_ALIGN
40 #pragma options align = mac68k
41 #elif PRAGMA_STRUCT_PACKPUSH
42 #pragma pack(push, 2)
43 #elif PRAGMA_STRUCT_PACK
44 #pragma pack(2)
45 #endif
46 
47 /* --------------------------------------------------------------------------------------------
48  */
49 /* Almost all types are padded for natural alignment. However the
50  * PEFExportedSymbol type is */
51 /* 10 bytes long, containing two 32 bit fields and one 16 bit field. Arrays of
52  * it must be */
53 /* packed, so it requires "68K" alignment. Setting this globally to 68K should
54  * also help */
55 /* ensure consistent treatment across compilers. */
56 
57 /* ========================================================================================
58  */
59 /* Overall Structure */
60 /* ================= */
61 
62 /* --------------------------------------------------------------------------------------------
63  */
64 /* This header contains a complete set of types and macros for dealing with the
65  * PEF executable */
66 /* format. While some description is provided, this header is not meant as a
67  * primary source */
68 /* of documentation on PEF. An excellent specification of PEF can be found in
69  * the Macintosh */
70 /* Runtime Architectures book. This header is primarily a physical format
71  * description. Thus */
72 /* it depends on as few other headers as possible and structure fields have
73  * obvious sizes. */
74 /* */
75 /* The physical storage for a PEF executable is known as a "container". This
76  * refers to just */
77 /* the executable itself, not the file etc. E.g. if five DLLs are packaged in a
78  * single file's */
79 /* data fork, that one data fork has five containers within it. */
80 /* */
81 /* A PEF container consists of an overall header, followed by one or more
82  * section headers, */
83 /* followed by the section name table, followed by the contents for the
84  * sections. Some kinds */
85 /* of sections have specific internal representation. The "loader" section is
86  * the most common */
87 /* of these special sections. It contains information on the exports, imports,
88  * and runtime */
89 /* relocations required to prepare the executable. PEF containers are self
90  * contained, all */
91 /* portions are located via relative offsets. */
92 /* */
93 /* */
94 /* +-------------------------------+ */
95 /* | Container Header | 40 bytes */
96 /* +-------------------------------+ */
97 /* | Section 0 header | 28 bytes each */
98 /* |...............................| */
99 /* | - - - - | */
100 /* |...............................| */
101 /* | Section n-1 header | */
102 /* +-------------------------------+ */
103 /* | Section Name Table | */
104 /* +-------------------------------+ */
105 /* | Section x raw data | */
106 /* +-------------------------------+ */
107 /* | - - - - | */
108 /* +-------------------------------+ */
109 /* | Section y raw data | */
110 /* +-------------------------------+ */
111 /* */
112 /* */
113 /* The sections are implicitly numbered from 0 to n according to the order of
114  * their headers. */
115 /* The headers of the instantiated sections must precede those of the
116  * non-instantiated */
117 /* sections. The ordering of the raw data is independent of the section header
118  * ordering. */
119 /* Each section header contains the offset for that section's raw data. */
120 
121 /* ===========================================================================================
122  */
123 /* Container Header */
124 /* ================ */
125 
127  OSType tag1; /* Must contain 'Joy!'.*/
128  OSType tag2; /* Must contain 'peff'. (Yes, with two 'f's.)*/
129  OSType architecture; /* The ISA for code sections. Constants in
130  CodeFragments.h.*/
131  UInt32 formatVersion; /* The physical format version.*/
132  UInt32 dateTimeStamp; /* Macintosh format creation/modification stamp.*/
133  UInt32
134  oldDefVersion; /* Old definition version number for the code fragment.*/
135  UInt32 oldImpVersion; /* Old implementation version number for the code
136  fragment.*/
137  UInt32 currentVersion; /* Current version number for the code fragment.*/
138  UInt16 sectionCount; /* Total number of section headers that follow.*/
139  UInt16 instSectionCount; /* Number of instantiated sections.*/
140  UInt32 reservedA; /* Reserved, must be written as zero.*/
141 };
143 enum {
144  kPEFTag1 = FOUR_CHAR_CODE('Joy!'), /* For non-Apple compilers: 0x4A6F7921.*/
145  kPEFTag2 = FOUR_CHAR_CODE('peff'), /* For non-Apple compilers: 0x70656666.*/
146  kPEFVersion = 0x00000001
147 };
148 
149 enum { kPEFFirstSectionHeaderOffset = sizeof(PEFContainerHeader) };
150 
151 #define PEFFirstSectionNameOffset(container) \
152  (kPEFFirstSectionHeaderOffset + \
153  ((container)->sectionCount * sizeof(PEFSectionHeader)))
154 
155 /* ===========================================================================================
156  */
157 /* Section Headers */
158 /* =============== */
159 
161  SInt32
162  nameOffset; /* Offset of name within the section name table, -1 => none.*/
163  UInt32 defaultAddress; /* Default address, affects relocations.*/
164  UInt32 totalLength; /* Fully expanded size in bytes of the section contents.*/
165  UInt32 unpackedLength; /* Size in bytes of the "initialized" part of the
166  contents.*/
167  UInt32 containerLength; /* Size in bytes of the raw data in the container.*/
168  UInt32 containerOffset; /* Offset of section's raw data.*/
169  UInt8 sectionKind; /* Kind of section contents/usage.*/
170  UInt8 shareKind; /* Sharing level, if a writeable section.*/
171  UInt8 alignment; /* Preferred alignment, expressed as log 2.*/
172  UInt8 reservedA; /* Reserved, must be zero.*/
173 };
174 typedef struct PEFSectionHeader PEFSectionHeader;
175 enum {
176  /* Values for the sectionKind field.*/
177  /* Section kind values for instantiated sections.*/
178  kPEFCodeSection = 0, /* Code, presumed pure & position independent.*/
179  kPEFUnpackedDataSection = 1, /* Unpacked writeable data.*/
180  kPEFPackedDataSection = 2, /* Packed writeable data.*/
181  kPEFConstantSection = 3, /* Read-only data.*/
182  kPEFExecDataSection = 6, /* Intermixed code and writeable data.*/
183  /* Section kind values for non-instantiated sections.*/
184  kPEFLoaderSection = 4, /* Loader tables.*/
185  kPEFDebugSection = 5, /* Reserved for future use.*/
186  kPEFExceptionSection = 7, /* Reserved for future use.*/
187  kPEFTracebackSection = 8 /* Reserved for future use.*/
188 };
189 
190 enum {
191  /* Values for the shareKind field.*/
192  kPEFProcessShare = 1, /* Shared within a single process.*/
193  kPEFGlobalShare = 4, /* Shared across the entire system.*/
194  kPEFProtectedShare = 5 /* Readable across the entire system, writeable only to
195  privileged code.*/
196 };
197 
198 /* ===========================================================================================
199  */
200 /* Packed Data Contents */
201 /* ==================== */
202 
203 /* --------------------------------------------------------------------------------------------
204  */
205 /* The raw contents of a packed data section are a sequence of byte codes. The
206  * basic format */
207 /* has a 3 bit opcode followed by a 5 bit count. Additional bytes might be used
208  * to contain */
209 /* counts larger than 31, and to contain a second or third count. Further
210  * additional bytes */
211 /* contain actual data values to transfer. */
212 /* */
213 /* All counts are represented in a variable length manner. A zero in the
214  * initial 5 bit count */
215 /* indicates the actual value follows. In this case, and for the second and
216  * third counts, the */
217 /* count is represented as a variable length sequence of bytes. The bytes are
218  * stored in big */
219 /* endian manner, most significant part first. The high order bit is set in all
220  * but the last */
221 /* byte. The value is accumulated by shifting the current value up 7 bits and
222  * adding in the */
223 /* low order 7 bits of the next byte. */
224 
225 enum {
226  /* The packed data opcodes.*/
227  kPEFPkDataZero = 0, /* Zero fill "count" bytes.*/
228  kPEFPkDataBlock = 1, /* Block copy "count" bytes.*/
229  kPEFPkDataRepeat = 2, /* Repeat "count" bytes "count2"+1 times.*/
230  kPEFPkDataRepeatBlock = 3, /* Interleaved repeated and unique data.*/
231  kPEFPkDataRepeatZero = 4 /* Interleaved zero and unique data.*/
232 };
233 
234 enum {
235  kPEFPkDataOpcodeShift = 5,
236  kPEFPkDataCount5Mask = 0x1F,
237  kPEFPkDataMaxCount5 = 31,
238  kPEFPkDataVCountShift = 7,
239  kPEFPkDataVCountMask = 0x7F,
240  kPEFPkDataVCountEndMask = 0x80
241 };
242 
243 #define PEFPkDataOpcode(byte) (((UInt8)(byte)) >> kPEFPkDataOpcodeShift)
244 
245 #define PEFPkDataCount5(byte) (((UInt8)(byte)) & kPEFPkDataCount5Mask)
246 
247 #define PEFPkDataComposeInstr(opcode, count5) \
248  ((((UInt8)(opcode)) << kPEFPkDataOpcodeShift) | ((UInt8)(count5)))
249 
250 /* --------------------------------------------------------------------------------------------
251  */
252 /* The following code snippet can be used to input a variable length count. */
253 /* */
254 /* count = 0; */
255 /* do { */
256 /* byte = *bytePtr++; */
257 /* count = (count << kPEFPkDataVCountShift) | (byte &
258  * kPEFPkDataVCountMask); */
259 /* } while ( (byte & kPEFPkDataVCountEndMask) != 0 ); */
260 /* */
261 /* The following code snippet can be used to output a variable length count to a
262  * byte array. */
263 /* This is more complex than the input code because the chunks are output in big
264  * endian order. */
265 /* Think about handling values like 0 or 0x030000. */
266 /* */
267 /* count = 1;. */
268 /* tempValue = value >> kPEFPkDataCountShift; */
269 /* while ( tempValue != 0 ) { */
270 /* count += 1; */
271 /* tempValue = tempValue >> kPEFPkDataCountShift; */
272 /* } */
273 /* */
274 /* bytePtr += count; */
275 /* tempPtr = bytePtr - 1; */
276 /* *tempPtr-- = value; // ! No need to mask, only the low order byte is
277  * stored. */
278 /* for ( count -= 1; count != 0; count -= 1 ) { */
279 /* value = value >> kPEFPkDataCountShift; */
280 /* *tempPtr-- = value | kPEFPkDataCountEndMask; */
281 /* } */
282 
283 /* ===========================================================================================
284  */
285 /* Loader Section */
286 /* ============== */
287 
288 /* --------------------------------------------------------------------------------------------
289  */
290 /* The loader section contains information needed to prepare the code fragment
291  * for execution. */
292 /* This includes this fragment's exports, the import libraries and the imported
293  * symbols from */
294 /* each library, and the relocations for the writeable sections. */
295 /* */
296 /* +-----------------------------------+ <--
297  * containerOffset --------+ */
298 /* | Loader Info Header | 56 bytes | */
299 /* |-----------------------------------| | */
300 /* | Imported Library 0 | 24 bytes each | */
301 /* |...................................| | */
302 /* | - - - | | */
303 /* |...................................| | */
304 /* | Imported Library l-1 | | */
305 /* |-----------------------------------| | */
306 /* | Imported Symbol 0 | 4 bytes each | */
307 /* |...................................| | */
308 /* | - - - | | */
309 /* |...................................| | */
310 /* | Imported Symbol i-1 | | */
311 /* |-----------------------------------| | */
312 /* | Relocation Header 0 | 12 bytes each | */
313 /* |...................................| | */
314 /* | - - - | | */
315 /* |...................................| | */
316 /* | Relocation Header r-1 | | */
317 /* |-----------------------------------| <-- +
318  * relocInstrOffset -----| */
319 /* | Relocation Instructions | | */
320 /* |-----------------------------------| <-- +
321  * loaderStringsOffset --| */
322 /* | Loader String Table | | */
323 /* |-----------------------------------| <-- +
324  * exportHashOffset -----+ */
325 /* | Export Hash Slot 0 | 4 bytes each */
326 /* |...................................| */
327 /* | - - - | */
328 /* |...................................| */
329 /* | Export Hash Slot h-1 | */
330 /* |-----------------------------------| */
331 /* | Export Symbol Key 0 | 4 bytes each */
332 /* |...................................| */
333 /* | - - - | */
334 /* |...................................| */
335 /* | Export Symbol Key e-1 | */
336 /* |-----------------------------------| */
337 /* | Export Symbol 0 | 10 bytes each */
338 /* |...................................| */
339 /* | - - - | */
340 /* |...................................| */
341 /* | Export Symbol e-1 | */
342 /* +-----------------------------------+ */
343 
345  SInt32 mainSection; /* Section containing the main symbol, -1 => none.*/
346  UInt32 mainOffset; /* Offset of main symbol.*/
347  SInt32 initSection; /* Section containing the init routine's TVector, -1 =>
348  none.*/
349  UInt32 initOffset; /* Offset of the init routine's TVector.*/
350  SInt32 termSection; /* Section containing the term routine's TVector, -1 =>
351  none.*/
352  UInt32 termOffset; /* Offset of the term routine's TVector.*/
353  UInt32 importedLibraryCount; /* Number of imported libraries. ('l')*/
354  UInt32 totalImportedSymbolCount; /* Total number of imported symbols. ('i')*/
355  UInt32 relocSectionCount; /* Number of sections with relocations. ('r')*/
356  UInt32 relocInstrOffset; /* Offset of the relocation instructions.*/
357  UInt32 loaderStringsOffset; /* Offset of the loader string table.*/
358  UInt32 exportHashOffset; /* Offset of the export hash table.*/
359  UInt32 exportHashTablePower; /* Export hash table size as log 2. (Log2('h'))*/
360  UInt32 exportedSymbolCount; /* Number of exported symbols. ('e')*/
361 };
363 
364 /* ===========================================================================================
365  */
366 /* Imported Libraries */
367 /* ------------------ */
368 
370  UInt32 nameOffset; /* Loader string table offset of library's name.*/
371  UInt32 oldImpVersion; /* Oldest compatible implementation version.*/
372  UInt32 currentVersion; /* Current version at build time.*/
373  UInt32 importedSymbolCount; /* Imported symbol count for this library.*/
374  UInt32 firstImportedSymbol; /* Index of first imported symbol from this
375  library.*/
376  UInt8 options; /* Option bits for this library.*/
377  UInt8 reservedA; /* Reserved, must be zero.*/
378  UInt16 reservedB; /* Reserved, must be zero.*/
379 };
381 enum {
382  /* Bits for the PEFImportedLibrary options field.*/
383  kPEFWeakImportLibMask =
384  0x40, /* The imported library is allowed to be missing.*/
385  kPEFInitLibBeforeMask =
386  0x80 /* The imported library must be initialized first.*/
387 };
388 
389 /* ===========================================================================================
390  */
391 /* Imported Symbols */
392 /* ---------------- */
393 
394 /* --------------------------------------------------------------------------------------------
395  */
396 /* The PEFImportedSymbol type has the following bit field layout. */
397 /* */
398 /* 3 */
399 /* 0 7 8 1 */
400 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
401 /* | symbol class | offset of symbol name in loader string table | */
402 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
403 /* |<-- 8 bits --->|<-- 24 bits ---------------------------------->| */
404 
406  UInt32 classAndName;
407 };
408 typedef struct PEFImportedSymbol PEFImportedSymbol;
409 enum {
410  kPEFImpSymClassShift = 24,
411  kPEFImpSymNameOffsetMask = 0x00FFFFFF,
412  kPEFImpSymMaxNameOffset = 0x00FFFFFF /* 16,777,215*/
413 };
414 
415 #define PEFImportedSymbolClass(classAndName) \
416  ((UInt8)((classAndName) >> kPEFImpSymClassShift))
417 #define PEFImportedSymbolNameOffset(classAndName) \
418  ((classAndName) & kPEFImpSymNameOffsetMask)
419 
420 #define PEFComposeImportedSymbol(class, nameOffset) \
421  ((((UInt32)(class)) << kPEFImpSymClassShift) | ((UInt32)(nameOffset)))
422 
423 enum {
424  /* Imported and exported symbol classes.*/
425  kPEFCodeSymbol = 0x00,
426  kPEFDataSymbol = 0x01,
427  kPEFTVectorSymbol = 0x02,
428  kPEFTOCSymbol = 0x03,
429  kPEFGlueSymbol = 0x04,
430  kPEFUndefinedSymbol = 0x0F,
431  kPEFWeakImportSymMask = 0x80
432 };
433 
434 /* ===========================================================================================
435  */
436 /* Exported Symbol Hash Table */
437 /* -------------------------- */
438 
439 /* --------------------------------------------------------------------------------------------
440  */
441 /* Exported symbols are described in four parts, optimized for speed of lookup.
442  * These parts */
443 /* are the "export hash table", the "export key table", the "export symbol
444  * table", and the */
445 /* "export name table". Overall they contain a flattened representation of a
446  * fairly normal */
447 /* hashed symbol table. */
448 /* */
449 /* The export hash table is an array of small fixed size elements. The number
450  * of elements is */
451 /* a power of 2. A 32 bit hash word for a symbol is converted into an index
452  * into this array. */
453 /* Each hash slot contains a count of the number of exported symbols that map to
454  * this slot and */
455 /* the index of the first of those symbols in the key and symbol tables. Of
456  * course some hash */
457 /* slots will have a zero count. */
458 /* */
459 /* The key and symbol tables are also arrays of fixed size elements, one for
460  * each exported */
461 /* symbol. Their entries are grouped by hash slot, those elements mapping to
462  * the same hash */
463 /* slot are contiguous. The key table contains just the full 32 bit hash word
464  * for each */
465 /* exported symbol. The symbol table contains the offset of the symbol's name
466  * in the string */
467 /* table and other information about the exported symbol. */
468 /* */
469 /* To look up an export you take the hashword and compute the hash slot index.
470  * You then scan */
471 /* the indicated portion of the key table for matching hashwords. If a hashword
472  * matches, you */
473 /* look at the corresponding symbol table entry to find the full symbol name. If
474  * the names */
475 /* match the symbol is found. */
476 
477 /* --------------------------------------------------------------------------------------------
478  */
479 /* The following function may be used to compute the hash table size. Signed
480  * values are used */
481 /* just to avoid potential code generation overhead for unsigned division. */
482 /* */
483 /* UInt8 PEFComputeHashTableExponent ( SInt32 exportCount ) */
484 /* { */
485 /* SInt32 exponent; */
486 /* */
487 /* const SInt32 kExponentLimit = 16; // Arbitrary, but must
488  * not exceed 30. */
489 /* const SInt32 kAverageChainLimit = 10; // Arbitrary, for
490  * space/time tradeoff. */
491 /* */
492 /* for ( exponent = 0; exponent < kExponentLimit; exponent += 1 ) { */
493 /* if ( (exportCount / (1 << exponent)) < kAverageChainLimit )
494  * break; */
495 /* } */
496 /* */
497 /* return exponent; */
498 /* */
499 /* } // PEFComputeHashTableExponent () */
500 
501 /* --------------------------------------------------------------------------------------------
502  */
503 /* The PEFExportedSymbolHashSlot type has the following bit field layout. */
504 /* */
505 /* 1 1 3 */
506 /* 0 3 4 1 */
507 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
508 /* | symbol count | index of first export key | */
509 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
510 /* |<-- 14 bits -------------->|<-- 18 bits ---------------------->| */
511 
513  UInt32 countAndStart;
514 };
516 enum {
517  kPEFHashSlotSymCountShift = 18,
518  kPEFHashSlotFirstKeyMask = 0x0003FFFF,
519  kPEFHashSlotMaxSymbolCount = 0x00003FFF, /* 16,383*/
520  kPEFHashSlotMaxKeyIndex = 0x0003FFFF /* 262,143*/
521 };
522 
523 #define PEFHashTableIndex(fullHashWord, hashTablePower) \
524  (((fullHashWord) ^ ((fullHashWord) >> (hashTablePower))) & \
525  ((1 << (hashTablePower)) - 1))
526 
527 #define PEFHashSlotSymbolCount(countAndStart) \
528  ((UInt32)((countAndStart) >> kPEFHashSlotSymCountShift))
529 #define PEFHashSlotFirstKey(countAndStart) \
530  ((countAndStart) & kPEFHashSlotFirstKeyMask)
531 
532 #define PEFComposeExportedSymbolHashSlot(symbolCount, firstKey) \
533  ((((UInt32)(symbolCount)) << kPEFHashSlotSymCountShift) | \
534  ((UInt32)(firstKey)))
535 
536 /* ===========================================================================================
537  */
538 /* Exported Symbol Hash Key */
539 /* ------------------------ */
540 
542  UInt16 nameLength;
543  UInt16 hashValue;
544 };
545 typedef struct PEFSplitHashWord PEFSplitHashWord;
547  union {
548  UInt32 fullHashWord;
549  PEFSplitHashWord splitHashWord;
550  } u;
551 };
553 enum {
554  kPEFHashLengthShift = 16,
555  kPEFHashValueMask = 0x0000FFFF,
556  kPEFHashMaxLength = 0x0000FFFF /* 65,535*/
557 };
558 
559 #define PEFHashNameLength(fullHashWord) \
560  ((UInt32)((fullHashWord) >> kPEFHashLengthShift))
561 #define PEFHashValue(fullHashWord) ((fullHashWord) & kPEFHashValueMask)
562 
563 #define PEFComposeFullHashWord(nameLength, hashValue) \
564  ((((UInt32)(nameLength)) << kPEFHashLengthShift) | ((UInt32)(hashValue)))
565 
566 /* ----------------------------------------------------------------------------------------------------
567  */
568 /* The following function computes the full 32 bit hash word. */
569 /* */
570 /* UInt32 PEFComputeHashWord ( BytePtr nameText, // ! First
571  * "letter", not length byte. */
572 /* UInt32 nameLength ) // ! The text
573  * may be zero terminated. */
574 /* { */
575 /* BytePtr charPtr = nameText; */
576 /* SInt32 hashValue = 0; // ! Signed to match old published
577  * algorithm. */
578 /* UInt32 length = 0; */
579 /* UInt32 limit; */
580 /* UInt32 result; */
581 /* UInt8 currChar; */
582 /* */
583 /* #define PseudoRotate(x) ( ( (x) << 1 ) - ( (x) >> 16 ) ) */
584 /* */
585 /* for ( limit = nameLength; limit > 0; limit -= 1 ) { */
586 /* currChar = *charPtr++; */
587 /* if ( currChar == NULL ) break; */
588 /* length += 1; */
589 /* hashValue = PseudoRotate ( hashValue ) ^ currChar; */
590 /* } */
591 /* */
592 /* result = (length << kPEFHashLengthShift) | */
593 /* ((UInt16) ((hashValue ^ (hashValue >> 16)) &
594  * kPEFHashValueMask)); */
595 /* */
596 /* return result; */
597 /* */
598 /* } // PEFComputeHashWord () */
599 
600 /* ===========================================================================================
601  */
602 /* Exported Symbols */
603 /* ---------------- */
604 
605 struct PEFExportedSymbol { /* ! This structure is 10 bytes long and arrays are
606  packed.*/
607  UInt32 classAndName; /* A combination of class and name offset.*/
608  UInt32 symbolValue; /* Typically the symbol's offset within a section.*/
609  SInt16 sectionIndex; /* The index of the section, or pseudo-section, for the
610  symbol.*/
611 };
612 typedef struct PEFExportedSymbol PEFExportedSymbol;
613 
614 /* --------------------------------------------------------------------------------------------
615  */
616 /* The classAndName field of the PEFExportedSymbol type has the following bit
617  * field layout. */
618 /* */
619 /* 3 */
620 /* 0 7 8 1 */
621 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
622 /* | symbol class | offset of symbol name in loader string table | */
623 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
624 /* |<-- 8 bits --->|<-- 24 bits ---------------------------------->| */
625 
626 enum {
627  kPEFExpSymClassShift = 24,
628  kPEFExpSymNameOffsetMask = 0x00FFFFFF,
629  kPEFExpSymMaxNameOffset = 0x00FFFFFF /* 16,777,215*/
630 };
631 
632 #define PEFExportedSymbolClass(classAndName) \
633  ((UInt8)((classAndName) >> kPEFExpSymClassShift))
634 #define PEFExportedSymbolNameOffset(classAndName) \
635  ((classAndName) & kPEFExpSymNameOffsetMask)
636 
637 #define PEFComposeExportedSymbol(class, nameOffset) \
638  ((((UInt32)(class)) << kPEFExpSymClassShift) | ((UInt32)(nameOffset)))
639 
640 enum {
641  /* Negative section indices indicate pseudo-sections.*/
642  kPEFAbsoluteExport = -2, /* The symbol value is an absolute address.*/
643  kPEFReexportedImport =
644  -3 /* The symbol value is the index of a reexported import.*/
645 };
646 
647 /* ===========================================================================================
648  */
649 /* Loader Relocations */
650 /* ================== */
651 
652 /* --------------------------------------------------------------------------------------------
653  */
654 /* The relocations for a section are defined by a sequence of instructions for
655  * an abstract */
656 /* machine that is specifically geared to performing relocations commonly needed
657  * for the "CFM" */
658 /* code generation model. These instructions occur in 16 bit chunks. Most
659  * instructions have */
660 /* just a single chunk. Instructions that are larger than 16 bits have an
661  * opcode and some of */
662 /* the operands in the first chunk, with other operands in following chunks. */
663 /* */
664 /* ! Note that the multi-chunk relocations have separate "Compose" macros for
665  * each chunk. The */
666 /* ! macros have the same basic name with a positional suffix of "_1st", "_2nd",
667  * etc. */
668 
669 typedef UInt16 PEFRelocChunk;
671  UInt16 sectionIndex; /* Index of the section to be fixed up.*/
672  UInt16 reservedA; /* Reserved, must be zero.*/
673  UInt32 relocCount; /* Number of 16 bit relocation chunks.*/
674  UInt32 firstRelocOffset; /* Offset of first relocation instruction.*/
675 };
677 
678 /* --------------------------------------------------------------------------------------------
679  */
680 /* ! Note that the relocCount field is the number of 16 bit relocation chunks,
681  * i.e. 1/2 the */
682 /* ! total number of bytes of relocation instructions. While most relocation
683  * instructions are */
684 /* ! 16 bits long, some are longer so the number of complete relocation
685  * instructions may be */
686 /* ! less than the relocCount value. */
687 
688 /* ------------------------------------------------------------------------------------
689  */
690 /* The PEFRelocField macro is a utility for extracting relocation instruction
691  * fields. */
692 
693 #define PEFRFShift(offset, length) (16 - ((offset) + (length)))
694 #define PEFRFMask(length) ((1 << (length)) - 1)
695 
696 #define PEFRelocField(chunk, offset, length) \
697  (((chunk) >> (16 - ((offset) + (length)))) & ((1 << (length)) - 1))
698 
699 /* ===========================================================================================
700  */
701 /* Basic Relocation Opcodes */
702 /* ------------------------ */
703 
704 /* --------------------------------------------------------------------------------------------
705  */
706 /* The number of opcode bits varies from 2 to 7. The enumeration and switch
707  * table given here */
708 /* are defined in terms of the most significant 7 bits of the first instruction
709  * chunk. An */
710 /* instruction is decoded by using the most significant 7 bits as an index into
711  * the opcode */
712 /* table, which in turn contains appropriately masked forms of the most
713  * significant 7 bits. */
714 /* The macro PEFRelocBasicOpcode assumes a declaration of the form. */
715 /* */
716 /* UInt8 kPEFRelocBasicOpcodes [kPEFRelocBasicOpcodeRange] = {
717  * PEFMaskedBasicOpcodes }; */
718 
719 enum { kPEFRelocBasicOpcodeRange = 128 };
720 
721 #define PEFRelocBasicOpcode(firstChunk) \
722  (kPEFRelocBasicOpcodes[(firstChunk) >> 9])
723 
724 /* --------------------------------------------------------------------------------------------
725  */
726 /* The relocation opcodes, clustered by major and minor groups. The
727  * instructions within a */
728 /* cluster all have the same bit field layout. The enumeration values use the
729  * high order 7 */
730 /* bits of the relocation instruction. Unused low order bits are set to zero.
731  */
732 
733 enum {
734  kPEFRelocBySectDWithSkip = 0x00, /* Binary: 00x_xxxx*/
735  kPEFRelocBySectC = 0x20, /* Binary: 010_0000, group is "RelocRun"*/
736  kPEFRelocBySectD = 0x21, /* Binary: 010_0001*/
737  kPEFRelocTVector12 = 0x22, /* Binary: 010_0010*/
738  kPEFRelocTVector8 = 0x23, /* Binary: 010_0011*/
739  kPEFRelocVTable8 = 0x24, /* Binary: 010_0100*/
740  kPEFRelocImportRun = 0x25, /* Binary: 010_0101*/
741  kPEFRelocSmByImport = 0x30, /* Binary: 011_0000, group is "RelocSmIndex"*/
742  kPEFRelocSmSetSectC = 0x31, /* Binary: 011_0001*/
743  kPEFRelocSmSetSectD = 0x32, /* Binary: 011_0010*/
744  kPEFRelocSmBySection = 0x33, /* Binary: 011_0011*/
745  kPEFRelocIncrPosition = 0x40, /* Binary: 100_0xxx*/
746  kPEFRelocSmRepeat = 0x48, /* Binary: 100_1xxx*/
747  kPEFRelocSetPosition = 0x50, /* Binary: 101_000x*/
748  kPEFRelocLgByImport = 0x52, /* Binary: 101_001x*/
749  kPEFRelocLgRepeat = 0x58, /* Binary: 101_100x*/
750  kPEFRelocLgSetOrBySection = 0x5A, /* Binary: 101_101x*/
751  kPEFRelocUndefinedOpcode =
752  0xFF /* Used in masking table for all undefined values.*/
753 };
754 
755 /* ----------------------------------------------------------------------------
756  */
757 /* The RelocLgSetOrBySection instruction has an additional 4 bits of subopcode
758  */
759 /* beyond the 7 used by the dispatch table. To be precise it has 6 plus 4 but
760  */
761 /* the dispatch table ignores the 7th bit, so the subdispatch is on all 4 extra
762  */
763 /* subopcode bits. */
764 
765 enum {
766  kPEFRelocLgBySectionSubopcode = 0x00, /* Binary: 0000*/
767  kPEFRelocLgSetSectCSubopcode = 0x01, /* Binary: 0001*/
768  kPEFRelocLgSetSectDSubopcode = 0x02 /* Binary: 0010*/
769 };
770 
771 #define PEFRelocLgSetOrBySubopcode(chunk) (((chunk) >> 6) & 0x0F)
772 
773 /* --------------------------------------------------------------------------------------------
774  */
775 /* The initial values for the opcode "masking" table. This has the enumeration
776  * values from */
777 /* above with appropriate replications for "don't care" bits. It is almost
778  * certainly shorter */
779 /* and faster to look up the masked value in a table than to use a branch tree.
780  */
781 
782 #define PEFMaskedBasicOpcodes \
783  \
784  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, \
785  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, /* 0x00 .. 0x03 */ \
786  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, \
787  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, /* 0x04 .. 0x07 */ \
788  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, \
789  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, /* 0x08 .. 0x0B */ \
790  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, \
791  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, /* 0x0C .. 0x0F */ \
792  \
793  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, \
794  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, /* 0x10 .. 0x13 */ \
795  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, \
796  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, /* 0x14 .. 0x17 */ \
797  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, \
798  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, /* 0x18 .. 0x1B */ \
799  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, \
800  kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, /* 0x1C .. 0x1F */ \
801  \
802  kPEFRelocBySectC, kPEFRelocBySectD, kPEFRelocTVector12, \
803  kPEFRelocTVector8, /* 0x20 .. 0x23 */ \
804  kPEFRelocVTable8, kPEFRelocImportRun, kPEFRelocUndefinedOpcode, \
805  kPEFRelocUndefinedOpcode, /* 0x24 .. 0x27 */ \
806  \
807  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
808  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x28 .. 0x2B */ \
809  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
810  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x2C .. 0x2F */ \
811  \
812  kPEFRelocSmByImport, kPEFRelocSmSetSectC, kPEFRelocSmSetSectD, \
813  kPEFRelocSmBySection, /* 0x30 .. 0x33 */ \
814  \
815  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
816  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x34 .. 0x37 */ \
817  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
818  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x38 .. 0x3B */ \
819  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
820  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x3C .. 0x3F */ \
821  \
822  kPEFRelocIncrPosition, kPEFRelocIncrPosition, kPEFRelocIncrPosition, \
823  kPEFRelocIncrPosition, /* 0x40 .. 0x43 */ \
824  kPEFRelocIncrPosition, kPEFRelocIncrPosition, kPEFRelocIncrPosition, \
825  kPEFRelocIncrPosition, /* 0x44 .. 0x47 */ \
826  \
827  kPEFRelocSmRepeat, kPEFRelocSmRepeat, kPEFRelocSmRepeat, \
828  kPEFRelocSmRepeat, /* 0x48 .. 0x4B */ \
829  kPEFRelocSmRepeat, kPEFRelocSmRepeat, kPEFRelocSmRepeat, \
830  kPEFRelocSmRepeat, /* 0x4C .. 0x4F */ \
831  \
832  kPEFRelocSetPosition, kPEFRelocSetPosition, kPEFRelocLgByImport, \
833  kPEFRelocLgByImport, /* 0x50 .. 0x53 */ \
834  \
835  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
836  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x54 .. 0x57 */ \
837  \
838  kPEFRelocLgRepeat, kPEFRelocLgRepeat, kPEFRelocLgSetOrBySection, \
839  kPEFRelocLgSetOrBySection, /* 0x58 .. 0x5B */ \
840  \
841  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
842  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x5C .. 0x5F */ \
843  \
844  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
845  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x60 .. 0x63 */ \
846  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
847  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x64 .. 0x67 */ \
848  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
849  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x68 .. 0x6B */ \
850  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
851  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x6C .. 0x6F */ \
852  \
853  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
854  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x70 .. 0x73 */ \
855  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
856  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x74 .. 0x77 */ \
857  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
858  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, /* 0x78 .. 0x7B */ \
859  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, \
860  kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode /* 0x7C .. 0x7F */
861 
862 /* ===========================================================================================
863  */
864 /* RelocBySectDWithSkip Instruction (DDAT) */
865 /* --------------------------------------- */
866 
867 /* --------------------------------------------------------------------------------------------
868  */
869 /* The "RelocBySectDWithSkip" (DDAT) instruction has the following bit field
870  * layout. */
871 /* */
872 /* 1 1 */
873 /* 0 1 2 9 0 5 */
874 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
875 /* |0 0| skip count | rel count | */
876 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
877 /* | 2 |<-- 8 bits --->|<-- 6 --->| */
878 /* */
879 /* ! Note that the stored skip count and reloc count are the actual values! */
880 
881 enum {
882  kPEFRelocWithSkipMaxSkipCount = 255,
883  kPEFRelocWithSkipMaxRelocCount = 63
884 };
885 
886 #define PEFRelocWithSkipSkipCount(chunk) PEFRelocField((chunk), 2, 8)
887 #define PEFRelocWithSkipRelocCount(chunk) PEFRelocField((chunk), 10, 6)
888 
889 #define PEFRelocComposeWithSkip(skipCount, relocCount) \
890  (0x0000 | (((UInt16)(skipCount)) << 6) | ((UInt16)(relocCount)))
891 
892 /* ===========================================================================================
893  */
894 /* RelocRun Group (CODE, DATA, DESC, DSC2, VTBL, SYMR) */
895 /* --------------------------------------------------- */
896 
897 /* --------------------------------------------------------------------------------------------
898  */
899 /* The "RelocRun" group includes the "RelocBySectC" (CODE), "RelocBySectD"
900  * (DATA), */
901 /* "RelocTVector12" (DESC), "RelocTVector8" (DSC2), "RelocVTable8" (VTBL), and
902  */
903 /* "RelocImportRun" (SYMR) instructions. This group has the following bit field
904  * layout. */
905 /* */
906 /* 1 */
907 /* 0 2 3 6 7 5 */
908 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
909 /* |0 1 0| subop.| run length | */
910 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
911 /* | 3 |<- 4 ->|<-- 9 bits ----->| */
912 /* */
913 /* ! Note that the stored run length is the actual value minus 1, but the macros
914  * deal with the */
915 /* ! actual value! */
916 
917 enum { kPEFRelocRunMaxRunLength = 512 };
918 
919 #define PEFRelocRunSubopcode(chunk) PEFRelocField((chunk), 3, 4)
920 #define PEFRelocRunRunLength(chunk) (PEFRelocField((chunk), 7, 9) + 1)
921 
922 #define PEFRelocComposeRun(subopcode, runLength) \
923  (0x4000 | (((UInt16)(subopcode)) << 9) | ((UInt16)((runLength)-1)))
924 
925 #define PEFRelocComposeBySectC(runLength) PEFRelocComposeRun(0, (runLength))
926 #define PEFRelocComposeBySectD(runLength) PEFRelocComposeRun(1, (runLength))
927 #define PEFRelocComposeTVector12(runLength) PEFRelocComposeRun(2, (runLength))
928 #define PEFRelocComposeTVector8(runLength) PEFRelocComposeRun(3, (runLength))
929 #define PEFRelocComposeVTable8(runLength) PEFRelocComposeRun(4, (runLength))
930 #define PEFRelocComposeImportRun(runLength) PEFRelocComposeRun(5, (runLength))
931 
932 /* ===========================================================================================
933  */
934 /* RelocSmIndex Group (SYMB, CDIS, DTIS, SECN) */
935 /* ------------------------------------------- */
936 
937 /* --------------------------------------------------------------------------------------------
938  */
939 /* The "RelocSmIndex" group includes the "RelocSmByImport" (SYMB),
940  * "RelocSmSetSectC" (CDIS), */
941 /* "RelocSmSetSectD" (DTIS) and "RelocSmBySection" (SECN) instructions. This
942  * group has the */
943 /* following bit field layout. */
944 /* */
945 /* 1 */
946 /* 0 2 3 6 7 5 */
947 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
948 /* |0 1 1| subop.| index | */
949 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
950 /* | 3 |<- 4 ->|<-- 9 bits ----->| */
951 /* */
952 /* ! Note that the stored index is the actual value! */
953 
954 enum { kPEFRelocSmIndexMaxIndex = 511 };
955 
956 #define PEFRelocSmIndexSubopcode(chunk) PEFRelocField((chunk), 3, 4)
957 #define PEFRelocSmIndexIndex(chunk) PEFRelocField((chunk), 7, 9)
958 
959 #define PEFRelocComposeSmIndex(subopcode, index) \
960  (0x6000 | (((UInt16)(subopcode)) << 9) | ((UInt16)(index)))
961 
962 #define PEFRelocComposeSmByImport(index) PEFRelocComposeSmIndex(0, (index))
963 #define PEFRelocComposeSmSetSectC(index) PEFRelocComposeSmIndex(1, (index))
964 #define PEFRelocComposeSmSetSectD(index) PEFRelocComposeSmIndex(2, (index))
965 #define PEFRelocComposeSmBySection(index) PEFRelocComposeSmIndex(3, (index))
966 
967 /* ===========================================================================================
968  */
969 /* RelocIncrPosition Instruction (DELT) */
970 /* ------------------------------------ */
971 
972 /* --------------------------------------------------------------------------------------------
973  */
974 /* The "RelocIncrPosition" (DELT) instruction has the following bit field
975  * layout. */
976 /* */
977 /* 1 */
978 /* 0 3 4 5 */
979 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
980 /* |1 0 0 0| offset | */
981 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
982 /* |<- 4 ->|<-- 12 bits ---------->| */
983 /* */
984 /* ! Note that the stored offset is the actual value minus 1, but the macros
985  * deal with the */
986 /* ! actual value! */
987 
988 enum { kPEFRelocIncrPositionMaxOffset = 4096 };
989 
990 #define PEFRelocIncrPositionOffset(chunk) (PEFRelocField((chunk), 4, 12) + 1)
991 
992 #define PEFRelocComposeIncrPosition(offset) (0x8000 | ((UInt16)((offset)-1)))
993 
994 /* ===========================================================================================
995  */
996 /* RelocSmRepeat Instruction (RPT) */
997 /* ------------------------------- */
998 
999 /* --------------------------------------------------------------------------------------------
1000  */
1001 /* The "RelocSmRepeat" (RPT) instruction has the following bit field layout. */
1002 /* */
1003 /* 1 */
1004 /* 0 3 4 7 8 5 */
1005 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1006 /* |1 0 0 1| chnks | repeat count | */
1007 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1008 /* |<- 4 ->|<- 4 ->|<-- 8 bits --->| */
1009 /* */
1010 /* ! Note that the stored chunk count and repeat count are the actual values
1011  * minus 1, but the */
1012 /* ! macros deal with the actual values! */
1013 
1014 enum {
1015  kPEFRelocSmRepeatMaxChunkCount = 16,
1016  kPEFRelocSmRepeatMaxRepeatCount = 256
1017 };
1018 
1019 #define PEFRelocSmRepeatChunkCount(chunk) (PEFRelocField((chunk), 4, 4) + 1)
1020 #define PEFRelocSmRepeatRepeatCount(chunk) (PEFRelocField((chunk), 8, 8) + 1)
1021 
1022 #define PEFRelocComposeSmRepeat(chunkCount, repeatCount) \
1023  (0x9000 | ((((UInt16)(chunkCount)) - 1) << 8) | (((UInt16)(repeatCount)) - 1))
1024 
1025 /* ===========================================================================================
1026  */
1027 /* RelocSetPosition Instruction (LABS) */
1028 /* ----------------------------------- */
1029 
1030 /* --------------------------------------------------------------------------------------------
1031  */
1032 /* The "RelocSetPosition" (LABS) instruction has the following bit field layout.
1033  */
1034 /* */
1035 /* 1 1 */
1036 /* 0 5 6 5 0 5 */
1037 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1038 /* |1 0 1 0 0 0| offset (high) | | offset (low) | */
1039 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1040 /* |<-- 6 ---->|<-- 10 bits ------>| |<-- 16 bits ------------------>| */
1041 /* */
1042 /* ! Note that the stored offset is the actual value! */
1043 
1044 enum {
1045  kPEFRelocSetPosMaxOffset = 0x03FFFFFF /* 67,108,863*/
1046 };
1047 
1048 #define PEFRelocSetPosOffsetHigh(chunk) PEFRelocField((chunk), 6, 10)
1049 
1050 #define PEFRelocSetPosFullOffset(firstChunk, secondChunk) \
1051  (((((UInt32)(firstChunk)) & 0x03FF) << 16) | ((UInt32)(secondChunk)))
1052 
1053 #define PEFRelocComposeSetPosition_1st(fullOffset) \
1054  (0xA000 | ((UInt16)(((UInt32)(fullOffset)) >> 16)))
1055 #define PEFRelocComposeSetPosition_2nd(fullOffset) \
1056  ((UInt16)((UInt32)(fullOffset) & 0xFFFF))
1057 
1058 /* ===========================================================================================
1059  */
1060 /* RelocLgByImport Instruction (LSYM) */
1061 /* ---------------------------------- */
1062 
1063 /* --------------------------------------------------------------------------------------------
1064  */
1065 /* The "RelocLgByImport" (LSYM) instruction has the following bit field layout.
1066  */
1067 /* */
1068 /* 1 1 */
1069 /* 0 5 6 5 0 5 */
1070 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1071 /* |1 0 1 0 0 1| index (high) | | index (low) | */
1072 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1073 /* |<-- 6 ---->|<-- 10 bits ------>| |<-- 16 bits ------------------>| */
1074 /* */
1075 /* ! Note that the stored offset is the actual value! */
1076 
1077 enum {
1078  kPEFRelocLgByImportMaxIndex = 0x03FFFFFF /* 67,108,863*/
1079 };
1080 
1081 #define PEFRelocLgByImportIndexHigh(chunk) PEFRelocField((chunk), 6, 10)
1082 
1083 #define PEFRelocLgByImportFullIndex(firstChunk, secondChunk) \
1084  (((((UInt32)(firstChunk)) & 0x03FF) << 16) | ((UInt32)(secondChunk)))
1085 
1086 #define PEFRelocComposeLgByImport_1st(fullIndex) \
1087  (0xA400 | ((UInt16)(((UInt32)(fullIndex)) >> 16)))
1088 #define PEFRelocComposeLgByImport_2nd(fullIndex) \
1089  ((UInt16)((UInt32)(fullIndex) & 0xFFFF))
1090 
1091 /* ===========================================================================================
1092  */
1093 /* RelocLgRepeat Instruction (LRPT) */
1094 /* -------------------------------- */
1095 
1096 /* --------------------------------------------------------------------------------------------
1097  */
1098 /* The "RelocLgRepeat" (LRPT) instruction has the following bit field layout. */
1099 /* */
1100 /* 1 1 1 */
1101 /* 0 5 6 9 0 5 0 5 */
1102 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1103 /* |1 0 1 1 0 0| chnks | rpt (high)| | repeat count (low) | */
1104 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1105 /* |<-- 6 --->|<- 4 ->|<-- 6 --->| |<-- 16 bits ------------------>| */
1106 /* */
1107 /* ! Note that the stored chunk count is the actual value minus 1, but the
1108  * macros deal with */
1109 /* ! the actual value! The stored repeat count is the actual value! */
1110 
1111 enum {
1112  kPEFRelocLgRepeatMaxChunkCount = 16,
1113  kPEFRelocLgRepeatMaxRepeatCount = 0x003FFFFF /* 4,194,303*/
1114 };
1115 
1116 #define PEFRelocLgRepeatChunkCount(chunk) (PEFRelocField((chunk), 6, 4) + 1)
1117 #define PEFRelocLgRepeatRepeatCountHigh(chunk) PEFRelocField((chunk), 10, 6)
1118 
1119 #define PEFRelocLgRepeatFullRepeatCount(firstChunk, secondChunk) \
1120  (((((UInt32)(firstChunk)) & 0x003F) << 16) | ((UInt32)(secondChunk)))
1121 
1122 #define PEFRelocComposeLgRepeat_1st(chunkCount, fullRepeatCount) \
1123  (0xB000 | ((((UInt16)(chunkCount)) - 1) << 6) | \
1124  ((UInt16)(((UInt32)(fullRepeatCount)) >> 16)))
1125 #define PEFRelocComposeLgRepeat_2nd(chunkCount, fullRepeatCount) \
1126  ((UInt16)((UInt32)(fullRepeatCount) & 0xFFFF))
1127 
1128 /* ===========================================================================================
1129  */
1130 /* RelocLgSetOrBySection Group (LSEC) */
1131 /* ---------------------------------- */
1132 
1133 /* --------------------------------------------------------------------------------------------
1134  */
1135 /* The "RelocLgSetOrBySection" (LSEC) instruction is a group including the
1136  * "RelocLgBySection", */
1137 /* "RelocLgSetSectC" and "RelocLgSetSectD" instructions. This group has the
1138  * following bit */
1139 /* field layout. */
1140 /* */
1141 /* 1 1 1 */
1142 /* 0 5 6 9 0 5 0 5 */
1143 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1144 /* |1 0 1 1 0 1| subop | idx (high)| | index (low) | */
1145 /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
1146 /* |<-- 6 --->|<- 4 ->|<-- 6 --->| |<-- 16 bits ------------------>| */
1147 /* */
1148 /* ! Note that the stored index is the actual value! */
1149 
1150 enum {
1151  kPEFRelocLgSetOrBySectionMaxIndex = 0x003FFFFF /* 4,194,303*/
1152 };
1153 
1154 #define PEFRelocLgSetOrBySectionSubopcode(chunk) PEFRelocField((chunk), 6, 4)
1155 #define PEFRelocLgSetOrBySectionIndexHigh(chunk) PEFRelocField((chunk), 10, 6)
1156 
1157 #define PEFRelocLgSetOrBySectionFullIndex(firstChunk, secondChunk) \
1158  (((((UInt32)(firstChunk)) & 0x003F) << 16) | ((UInt32)(secondChunk)))
1159 
1160 #define PEFRelocComposeLgSetOrBySection_1st(subopcode, fullIndex) \
1161  (0xB400 | (((UInt16)(subopcode)) << 6) | \
1162  ((UInt16)(((UInt32)(fullIndex)) >> 16)))
1163 #define PEFRelocComposeLgSetOrBySection_2nd(subopcode, fullIndex) \
1164  ((UInt16)((UInt32)(fullIndex) & 0xFFFF))
1165 
1166 #define PEFRelocComposeLgBySection(fullIndex) \
1167  PEFRelocComposeLgSetOrBySection(0x00, (fullIndex))
1168 #define PEFRelocComposeLgSetSectC(fullIndex) \
1169  PEFRelocComposeLgSetOrBySection(0x01, (fullIndex))
1170 #define PEFRelocComposeLgSetSectD(fullIndex) \
1171  PEFRelocComposeLgSetOrBySection(0x02, (fullIndex))
1172 
1173 #if PRAGMA_STRUCT_ALIGN
1174 #pragma options align = reset
1175 #elif PRAGMA_STRUCT_PACKPUSH
1176 #pragma pack(pop)
1177 #elif PRAGMA_STRUCT_PACK
1178 #pragma pack()
1179 #endif
1180 
1181 #ifdef PRAGMA_IMPORT_OFF
1182 #pragma import off
1183 #elif PRAGMA_IMPORT
1184 #pragma import reset
1185 #endif
1186 
1187 #ifdef __cplusplus
1188 }
1189 #endif
1190 
1191 #endif /* __PEFBINARYFORMAT__ */
Basic Macintosh data types.
Definition: PEFBinaryFormat.h:126
Definition: PEFBinaryFormat.h:512
Definition: PEFBinaryFormat.h:546
Definition: PEFBinaryFormat.h:605
Definition: PEFBinaryFormat.h:369
Definition: PEFBinaryFormat.h:405
Definition: PEFBinaryFormat.h:344
Definition: PEFBinaryFormat.h:670
Definition: PEFBinaryFormat.h:160
Definition: PEFBinaryFormat.h:541