PEFBinaryFormat.pas 53 KB

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