Repository URL to install this package:
Version:
3.0.0 ▾
|
{
File: CarbonCore/PEFBinaryFormat.h
Contains: PEF Types and Macros
The contents of this header file are deprecated.
Copyright: © 1993-2011 by Apple Inc. All rights reserved.
}
{ Pascal Translation Updated: Jonas Maebe, <jonas@freepascal.org>, October 2009 }
{ Pascal Translation Updated: Jonas Maebe, <jonas@freepascal.org>, September 2012 }
{
Modified for use with Free Pascal
Version 308
Please report any bugs to <gpc@microbizz.nl>
}
{$ifc not defined MACOSALLINCLUDE or not MACOSALLINCLUDE}
{$mode macpas}
{$packenum 1}
{$macro on}
{$inline on}
{$calling mwpascal}
unit PEFBinaryFormat;
interface
{$setc UNIVERSAL_INTERFACES_VERSION := $0400}
{$setc GAP_INTERFACES_VERSION := $0308}
{$ifc not defined USE_CFSTR_CONSTANT_MACROS}
{$setc USE_CFSTR_CONSTANT_MACROS := TRUE}
{$endc}
{$ifc defined CPUPOWERPC and defined CPUI386}
{$error Conflicting initial definitions for CPUPOWERPC and CPUI386}
{$endc}
{$ifc defined FPC_BIG_ENDIAN and defined FPC_LITTLE_ENDIAN}
{$error Conflicting initial definitions for FPC_BIG_ENDIAN and FPC_LITTLE_ENDIAN}
{$endc}
{$ifc not defined __ppc__ and defined CPUPOWERPC32}
{$setc __ppc__ := 1}
{$elsec}
{$setc __ppc__ := 0}
{$endc}
{$ifc not defined __ppc64__ and defined CPUPOWERPC64}
{$setc __ppc64__ := 1}
{$elsec}
{$setc __ppc64__ := 0}
{$endc}
{$ifc not defined __i386__ and defined CPUI386}
{$setc __i386__ := 1}
{$elsec}
{$setc __i386__ := 0}
{$endc}
{$ifc not defined __x86_64__ and defined CPUX86_64}
{$setc __x86_64__ := 1}
{$elsec}
{$setc __x86_64__ := 0}
{$endc}
{$ifc not defined __arm__ and defined CPUARM}
{$setc __arm__ := 1}
{$elsec}
{$setc __arm__ := 0}
{$endc}
{$ifc defined cpu64}
{$setc __LP64__ := 1}
{$elsec}
{$setc __LP64__ := 0}
{$endc}
{$ifc defined __ppc__ and __ppc__ and defined __i386__ and __i386__}
{$error Conflicting definitions for __ppc__ and __i386__}
{$endc}
{$ifc defined __ppc__ and __ppc__}
{$setc TARGET_CPU_PPC := TRUE}
{$setc TARGET_CPU_PPC64 := FALSE}
{$setc TARGET_CPU_X86 := FALSE}
{$setc TARGET_CPU_X86_64 := FALSE}
{$setc TARGET_CPU_ARM := FALSE}
{$setc TARGET_OS_MAC := TRUE}
{$setc TARGET_OS_IPHONE := FALSE}
{$setc TARGET_IPHONE_SIMULATOR := FALSE}
{$setc TARGET_OS_EMBEDDED := FALSE}
{$elifc defined __ppc64__ and __ppc64__}
{$setc TARGET_CPU_PPC := FALSE}
{$setc TARGET_CPU_PPC64 := TRUE}
{$setc TARGET_CPU_X86 := FALSE}
{$setc TARGET_CPU_X86_64 := FALSE}
{$setc TARGET_CPU_ARM := FALSE}
{$setc TARGET_OS_MAC := TRUE}
{$setc TARGET_OS_IPHONE := FALSE}
{$setc TARGET_IPHONE_SIMULATOR := FALSE}
{$setc TARGET_OS_EMBEDDED := FALSE}
{$elifc defined __i386__ and __i386__}
{$setc TARGET_CPU_PPC := FALSE}
{$setc TARGET_CPU_PPC64 := FALSE}
{$setc TARGET_CPU_X86 := TRUE}
{$setc TARGET_CPU_X86_64 := FALSE}
{$setc TARGET_CPU_ARM := FALSE}
{$ifc defined(iphonesim)}
{$setc TARGET_OS_MAC := FALSE}
{$setc TARGET_OS_IPHONE := TRUE}
{$setc TARGET_IPHONE_SIMULATOR := TRUE}
{$elsec}
{$setc TARGET_OS_MAC := TRUE}
{$setc TARGET_OS_IPHONE := FALSE}
{$setc TARGET_IPHONE_SIMULATOR := FALSE}
{$endc}
{$setc TARGET_OS_EMBEDDED := FALSE}
{$elifc defined __x86_64__ and __x86_64__}
{$setc TARGET_CPU_PPC := FALSE}
{$setc TARGET_CPU_PPC64 := FALSE}
{$setc TARGET_CPU_X86 := FALSE}
{$setc TARGET_CPU_X86_64 := TRUE}
{$setc TARGET_CPU_ARM := FALSE}
{$setc TARGET_OS_MAC := TRUE}
{$setc TARGET_OS_IPHONE := FALSE}
{$setc TARGET_IPHONE_SIMULATOR := FALSE}
{$setc TARGET_OS_EMBEDDED := FALSE}
{$elifc defined __arm__ and __arm__}
{$setc TARGET_CPU_PPC := FALSE}
{$setc TARGET_CPU_PPC64 := FALSE}
{$setc TARGET_CPU_X86 := FALSE}
{$setc TARGET_CPU_X86_64 := FALSE}
{$setc TARGET_CPU_ARM := TRUE}
{ will require compiler define when/if other Apple devices with ARM cpus ship }
{$setc TARGET_OS_MAC := FALSE}
{$setc TARGET_OS_IPHONE := TRUE}
{$setc TARGET_IPHONE_SIMULATOR := FALSE}
{$setc TARGET_OS_EMBEDDED := TRUE}
{$elsec}
{$error __ppc__ nor __ppc64__ nor __i386__ nor __x86_64__ nor __arm__ is defined.}
{$endc}
{$ifc defined __LP64__ and __LP64__ }
{$setc TARGET_CPU_64 := TRUE}
{$elsec}
{$setc TARGET_CPU_64 := FALSE}
{$endc}
{$ifc defined FPC_BIG_ENDIAN}
{$setc TARGET_RT_BIG_ENDIAN := TRUE}
{$setc TARGET_RT_LITTLE_ENDIAN := FALSE}
{$elifc defined FPC_LITTLE_ENDIAN}
{$setc TARGET_RT_BIG_ENDIAN := FALSE}
{$setc TARGET_RT_LITTLE_ENDIAN := TRUE}
{$elsec}
{$error Neither FPC_BIG_ENDIAN nor FPC_LITTLE_ENDIAN are defined.}
{$endc}
{$setc ACCESSOR_CALLS_ARE_FUNCTIONS := TRUE}
{$setc CALL_NOT_IN_CARBON := FALSE}
{$setc OLDROUTINENAMES := FALSE}
{$setc OPAQUE_TOOLBOX_STRUCTS := TRUE}
{$setc OPAQUE_UPP_TYPES := TRUE}
{$setc OTCARBONAPPLICATION := TRUE}
{$setc OTKERNEL := FALSE}
{$setc PM_USE_SESSION_APIS := TRUE}
{$setc TARGET_API_MAC_CARBON := TRUE}
{$setc TARGET_API_MAC_OS8 := FALSE}
{$setc TARGET_API_MAC_OSX := TRUE}
{$setc TARGET_CARBON := TRUE}
{$setc TARGET_CPU_68K := FALSE}
{$setc TARGET_CPU_MIPS := FALSE}
{$setc TARGET_CPU_SPARC := FALSE}
{$setc TARGET_OS_UNIX := FALSE}
{$setc TARGET_OS_WIN32 := FALSE}
{$setc TARGET_RT_MAC_68881 := FALSE}
{$setc TARGET_RT_MAC_CFM := FALSE}
{$setc TARGET_RT_MAC_MACHO := TRUE}
{$setc TYPED_FUNCTION_POINTERS := TRUE}
{$setc TYPE_BOOL := FALSE}
{$setc TYPE_EXTENDED := FALSE}
{$setc TYPE_LONGLONG := TRUE}
uses MacTypes;
{$endc} {not MACOSALLINCLUDE}
{$ifc TARGET_OS_MAC}
{$ALIGN MAC68K}
{ -------------------------------------------------------------------------------------------- }
{ Almost all types are padded for natural alignment. However the PEFExportedSymbol type is }
{ 10 bytes long, containing two 32 bit fields and one 16 bit field. Arrays of it must be }
{ packed, so it requires "68K" alignment. Setting this globally to 68K should also help }
{ ensure consistent treatment across compilers. }
{ ======================================================================================== }
{ Overall Structure }
{ ================= }
{ -------------------------------------------------------------------------------------------- }
{ This header contains a complete set of types and macros for dealing with the PEF executable }
{ format. While some description is provided, this header is not meant as a primary source }
{ of documentation on PEF. An excellent specification of PEF can be found in the Macintosh }
{ Runtime Architectures book. This header is primarily a physical format description. Thus }
{ it depends on as few other headers as possible and structure fields have obvious sizes. }
{ The physical storage for a PEF executable is known as a "container". This refers to just }
{ the executable itself, not the file etc. E.g. if five DLLs are packaged in a single file's }
{ data fork, that one data fork has five containers within it. }
{ A PEF container consists of an overall header, followed by one or more section headers, }
{ followed by the section name table, followed by the contents for the sections. Some kinds }
{ of sections have specific internal representation. The "loader" section is the most common }
{ of these special sections. It contains information on the exports, imports, and runtime }
{ relocations required to prepare the executable. PEF containers are self contained, all }
{ portions are located via relative offsets. }
{ +-------------------------------+ }
{ | Container Header | 40 bytes }
{ +-------------------------------+ }
{ | Section 0 header | 28 bytes each }
{ |...............................| }
{ | - - - - | }
{ |...............................| }
{ | Section n-1 header | }
{ +-------------------------------+ }
{ | Section Name Table | }
{ +-------------------------------+ }
{ | Section x raw data | }
{ +-------------------------------+ }
{ | - - - - | }
{ +-------------------------------+ }
{ | Section y raw data | }
{ +-------------------------------+ }
{ The sections are implicitly numbered from 0 to n according to the order of their headers. }
{ The headers of the instantiated sections must precede those of the non-instantiated }
{ sections. The ordering of the raw data is independent of the section header ordering. }
{ Each section header contains the offset for that section's raw data. }
{ =========================================================================================== }
{ Container Header }
{ ================ }
type
PEFContainerHeaderPtr = ^PEFContainerHeader;
PEFContainerHeader = record
tag1: OSType; { Must contain 'Joy!'.}
tag2: OSType; { Must contain 'peff'. (Yes, with two 'f's.)}
architecture: OSType; { The ISA for code sections. Constants in CodeFragments.h.}
formatVersion: UInt32; { The physical format version.}
dateTimeStamp: UInt32; { Macintosh format creation/modification stamp.}
oldDefVersion: UInt32; { Old definition version number for the code fragment.}
oldImpVersion: UInt32; { Old implementation version number for the code fragment.}
currentVersion: UInt32; { Current version number for the code fragment.}
sectionCount: UInt16; { Total number of section headers that follow.}
instSectionCount: UInt16; { Number of instantiated sections.}
reservedA: UInt32; { Reserved, must be written as zero.}
end;
const
kPEFTag1 = FourCharCode('Joy!'); { For non-Apple compilers: 0x4A6F7921.}
kPEFTag2 = FourCharCode('peff'); { For non-Apple compilers: 0x70656666.}
kPEFVersion = $00000001;
const
kPEFFirstSectionHeaderOffset = SizeOf(PEFContainerHeader);
(*
#define PEFFirstSectionNameOffset(container) \
( kPEFFirstSectionHeaderOffset + ((container)->sectionCount * sizeof ( PEFSectionHeader )) )
*)
{ =========================================================================================== }
{ Section Headers }
{ =============== }
type
PEFSectionHeaderPtr = ^PEFSectionHeader;
PEFSectionHeader = record
nameOffset: SInt32; { Offset of name within the section name table, -1 => none.}
defaultAddress: UInt32; { Default address, affects relocations.}
totalLength: UInt32; { Fully expanded size in bytes of the section contents.}
unpackedLength: UInt32; { Size in bytes of the "initialized" part of the contents.}
containerLength: UInt32; { Size in bytes of the raw data in the container.}
containerOffset: UInt32; { Offset of section's raw data.}
sectionKind: UInt8; { Kind of section contents/usage.}
shareKind: UInt8; { Sharing level, if a writeable section.}
alignment: UInt8; { Preferred alignment, expressed as log 2.}
reservedA: UInt8; { Reserved, must be zero.}
end;
const
{ Values for the sectionKind field.}
{ Section kind values for instantiated sections.}
kPEFCodeSection = 0; { Code, presumed pure & position independent.}
kPEFUnpackedDataSection = 1; { Unpacked writeable data.}
kPEFPackedDataSection = 2; { Packed writeable data.}
kPEFConstantSection = 3; { Read-only data.}
kPEFExecDataSection = 6; { Intermixed code and writeable data.}
{ Section kind values for non-instantiated sections.}
kPEFLoaderSection = 4; { Loader tables.}
kPEFDebugSection = 5; { Reserved for future use.}
kPEFExceptionSection = 7; { Reserved for future use.}
kPEFTracebackSection = 8; { Reserved for future use.}
const
{ Values for the shareKind field.}
kPEFProcessShare = 1; { Shared within a single process.}
kPEFGlobalShare = 4; { Shared across the entire system.}
kPEFProtectedShare = 5; { Readable across the entire system, writeable only to privileged code.}
{ =========================================================================================== }
{ Packed Data Contents }
{ ==================== }
{ -------------------------------------------------------------------------------------------- }
{ The raw contents of a packed data section are a sequence of byte codes. The basic format }
{ has a 3 bit opcode followed by a 5 bit count. Additional bytes might be used to contain }
{ counts larger than 31, and to contain a second or third count. Further additional bytes }
{ contain actual data values to transfer. }
{ All counts are represented in a variable length manner. A zero in the initial 5 bit count }
{ indicates the actual value follows. In this case, and for the second and third counts, the }
{ count is represented as a variable length sequence of bytes. The bytes are stored in big }
{ endian manner, most significant part first. The high order bit is set in all but the last }
{ byte. The value is accumulated by shifting the current value up 7 bits and adding in the }
{ low order 7 bits of the next byte. }
const
{ The packed data opcodes.}
kPEFPkDataZero = 0; { Zero fill "count" bytes.}
kPEFPkDataBlock = 1; { Block copy "count" bytes.}
kPEFPkDataRepeat = 2; { Repeat "count" bytes "count2"+1 times.}
kPEFPkDataRepeatBlock = 3; { Interleaved repeated and unique data.}
kPEFPkDataRepeatZero = 4; { Interleaved zero and unique data.}
const
kPEFPkDataOpcodeShift = 5;
kPEFPkDataCount5Mask = $1F;
kPEFPkDataMaxCount5 = 31;
kPEFPkDataVCountShift = 7;
kPEFPkDataVCountMask = $7F;
kPEFPkDataVCountEndMask = $80;
(*
#define PEFPkDataOpcode(byte) ( ((UInt8)(byte)) >> kPEFPkDataOpcodeShift )
#define PEFPkDataCount5(byte) ( ((UInt8)(byte)) & kPEFPkDataCount5Mask )
#define PEFPkDataComposeInstr(opcode,count5) \
( (((UInt8)(opcode)) << kPEFPkDataOpcodeShift) | ((UInt8)(count5)) )
*)
{ -------------------------------------------------------------------------------------------- }
{ The following code snippet can be used to input a variable length count. }
{ count = 0; }
{ do ( }
{ byte = *bytePtr++; }
{ count = (count << kPEFPkDataVCountShift) | (byte & kPEFPkDataVCountMask); }
{ ) while ( (byte & kPEFPkDataVCountEndMask) != 0 ); }
{ The following code snippet can be used to output a variable length count to a byte array. }
{ This is more complex than the input code because the chunks are output in big endian order. }
{ Think about handling values like 0 or 0x030000. }
{ count = 1;. }
{ tempValue = value >> kPEFPkDataCountShift; }
{ while ( tempValue != 0 ) ( }
{ count += 1; }
{ tempValue = tempValue >> kPEFPkDataCountShift; }
{ ) }
{ bytePtr += count; }
{ tempPtr = bytePtr - 1; }
{ *tempPtr-- = value; // ! No need to mask, only the low order byte is stored. }
{ for ( count -= 1; count != 0; count -= 1 ) ( }
{ value = value >> kPEFPkDataCountShift; }
{ *tempPtr-- = value | kPEFPkDataCountEndMask; }
{ ) }
{ =========================================================================================== }
{ Loader Section }
{ ============== }
{ -------------------------------------------------------------------------------------------- }
{ The loader section contains information needed to prepare the code fragment for execution. }
{ This includes this fragment's exports, the import libraries and the imported symbols from }
{ each library, and the relocations for the writeable sections. }
{ +-----------------------------------+ <-- containerOffset --------+ }
{ | Loader Info Header | 56 bytes | }
{ |-----------------------------------| | }
{ | Imported Library 0 | 24 bytes each | }
{ |...................................| | }
{ | - - - | | }
{ |...................................| | }
{ | Imported Library l-1 | | }
{ |-----------------------------------| | }
{ | Imported Symbol 0 | 4 bytes each | }
{ |...................................| | }
{ | - - - | | }
{ |...................................| | }
{ | Imported Symbol i-1 | | }
{ |-----------------------------------| | }
{ | Relocation Header 0 | 12 bytes each | }
{ |...................................| | }
{ | - - - | | }
{ |...................................| | }
{ | Relocation Header r-1 | | }
{ |-----------------------------------| <-- + relocInstrOffset -----| }
{ | Relocation Instructions | | }
{ |-----------------------------------| <-- + loaderStringsOffset --| }
{ | Loader String Table | | }
{ |-----------------------------------| <-- + exportHashOffset -----+ }
{ | Export Hash Slot 0 | 4 bytes each }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Export Hash Slot h-1 | }
{ |-----------------------------------| }
{ | Export Symbol Key 0 | 4 bytes each }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Export Symbol Key e-1 | }
{ |-----------------------------------| }
{ | Export Symbol 0 | 10 bytes each }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Export Symbol e-1 | }
{ +-----------------------------------+ }
type
PEFLoaderInfoHeaderPtr = ^PEFLoaderInfoHeader;
PEFLoaderInfoHeader = record
mainSection: SInt32; { Section containing the main symbol, -1 => none.}
mainOffset: UInt32; { Offset of main symbol.}
initSection: SInt32; { Section containing the init routine's TVector, -1 => none.}
initOffset: UInt32; { Offset of the init routine's TVector.}
termSection: SInt32; { Section containing the term routine's TVector, -1 => none.}
termOffset: UInt32; { Offset of the term routine's TVector.}
importedLibraryCount: UInt32; { Number of imported libraries. ('l')}
totalImportedSymbolCount: UInt32; { Total number of imported symbols. ('i')}
relocSectionCount: UInt32; { Number of sections with relocations. ('r')}
relocInstrOffset: UInt32; { Offset of the relocation instructions.}
loaderStringsOffset: UInt32; { Offset of the loader string table.}
exportHashOffset: UInt32; { Offset of the export hash table.}
exportHashTablePower: UInt32; { Export hash table size as log 2. (Log2('h'))}
exportedSymbolCount: UInt32; { Number of exported symbols. ('e')}
end;
{ =========================================================================================== }
{ Imported Libraries }
{ ------------------ }
type
PEFImportedLibraryPtr = ^PEFImportedLibrary;
PEFImportedLibrary = record
nameOffset: UInt32; { Loader string table offset of library's name.}
oldImpVersion: UInt32; { Oldest compatible implementation version.}
currentVersion: UInt32; { Current version at build time.}
importedSymbolCount: UInt32; { Imported symbol count for this library.}
firstImportedSymbol: UInt32; { Index of first imported symbol from this library.}
options: UInt8; { Option bits for this library.}
reservedA: UInt8; { Reserved, must be zero.}
reservedB: UInt16; { Reserved, must be zero.}
end;
const
{ Bits for the PEFImportedLibrary options field.}
kPEFWeakImportLibMask = $40; { The imported library is allowed to be missing.}
kPEFInitLibBeforeMask = $80; { The imported library must be initialized first.}
{ =========================================================================================== }
{ Imported Symbols }
{ ---------------- }
{ -------------------------------------------------------------------------------------------- }
{ The PEFImportedSymbol type has the following bit field layout. }
{ 3 }
{ 0 7 8 1 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ | symbol class | offset of symbol name in loader string table | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<-- 8 bits --->|<-- 24 bits ---------------------------------->| }
type
PEFImportedSymbolPtr = ^PEFImportedSymbol;
PEFImportedSymbol = record
classAndName: UInt32;
end;
const
kPEFImpSymClassShift = 24;
kPEFImpSymNameOffsetMask = $00FFFFFF;
kPEFImpSymMaxNameOffset = $00FFFFFF; { 16,777,215}
const
{ Imported and exported symbol classes.}
kPEFCodeSymbol = $00;
kPEFDataSymbol = $01;
kPEFTVectorSymbol = $02;
kPEFTOCSymbol = $03;
kPEFGlueSymbol = $04;
kPEFUndefinedSymbol = $0F;
kPEFWeakImportSymMask = $80;
{ =========================================================================================== }
{ Exported Symbol Hash Table }
{ -------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ Exported symbols are described in four parts, optimized for speed of lookup. These parts }
{ are the "export hash table", the "export key table", the "export symbol table", and the }
{ "export name table". Overall they contain a flattened representation of a fairly normal }
{ hashed symbol table. }
{ The export hash table is an array of small fixed size elements. The number of elements is }
{ a power of 2. A 32 bit hash word for a symbol is converted into an index into this array. }
{ Each hash slot contains a count of the number of exported symbols that map to this slot and }
{ the index of the first of those symbols in the key and symbol tables. Of course some hash }
{ slots will have a zero count. }
{ The key and symbol tables are also arrays of fixed size elements, one for each exported }
{ symbol. Their entries are grouped by hash slot, those elements mapping to the same hash }
{ slot are contiguous. The key table contains just the full 32 bit hash word for each }
{ exported symbol. The symbol table contains the offset of the symbol's name in the string }
{ table and other information about the exported symbol. }
{ To look up an export you take the hashword and compute the hash slot index. You then scan }
{ the indicated portion of the key table for matching hashwords. If a hashword matches, you }
{ look at the corresponding symbol table entry to find the full symbol name. If the names }
{ match the symbol is found. }
{ -------------------------------------------------------------------------------------------- }
{ The following function may be used to compute the hash table size. Signed values are used }
{ just to avoid potential code generation overhead for unsigned division. }
{ UInt8 PEFComputeHashTableExponent ( SInt32 exportCount ) }
{ ( }
{ SInt32 exponent; }
{ const SInt32 kExponentLimit = 16; // Arbitrary, but must not exceed 30. }
{ const SInt32 kAverageChainLimit = 10; // Arbitrary, for space/time tradeoff. }
{ for ( exponent = 0; exponent < kExponentLimit; exponent += 1 ) ( }
{ if ( (exportCount / (1 << exponent)) < kAverageChainLimit ) break; }
{ ) }
{ return exponent; }
{ ) // PEFComputeHashTableExponent () }
{ -------------------------------------------------------------------------------------------- }
{ The PEFExportedSymbolHashSlot type has the following bit field layout. }
{ 1 1 3 }
{ 0 3 4 1 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ | symbol count | index of first export key | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<-- 14 bits -------------->|<-- 18 bits ---------------------->| }
type
PEFExportedSymbolHashSlotPtr = ^PEFExportedSymbolHashSlot;
PEFExportedSymbolHashSlot = record
countAndStart: UInt32;
end;
const
kPEFHashSlotSymCountShift = 18;
kPEFHashSlotFirstKeyMask = $0003FFFF;
kPEFHashSlotMaxSymbolCount = $00003FFF; { 16,383}
kPEFHashSlotMaxKeyIndex = $0003FFFF; { 262,143}
{ =========================================================================================== }
{ Exported Symbol Hash Key }
{ ------------------------ }
type
PEFSplitHashWordPtr = ^PEFSplitHashWord;
PEFSplitHashWord = record
nameLength: UInt16;
hashValue: UInt16;
end;
type
PEFExportedSymbolKeyPtr = ^PEFExportedSymbolKey;
PEFExportedSymbolKey = record
case SInt16 of
0: (
fullHashWord: UInt32;
);
1: (
splitHashWord: PEFSplitHashWord;
);
end;
const
kPEFHashLengthShift = 16;
kPEFHashValueMask = $0000FFFF;
kPEFHashMaxLength = $0000FFFF; { 65,535}
{ ---------------------------------------------------------------------------------------------------- }
{ The following function computes the full 32 bit hash word. }
{ UInt32 PEFComputeHashWord ( BytePtr nameText, // ! First "letter", not length byte. }
{ UInt32 nameLength ) // ! The text may be zero terminated. }
{ ( }
{ BytePtr charPtr = nameText; }
{ SInt32 hashValue = 0; // ! Signed to match old published algorithm. }
{ UInt32 length = 0; }
{ UInt32 limit; }
{ UInt32 result; }
{ UInt8 currChar; }
{ #define PseudoRotate(x) ( ( (x) << 1 ) - ( (x) >> 16 ) ) }
{ for ( limit = nameLength; limit > 0; limit -= 1 ) ( }
{ currChar = *charPtr++; }
{ if ( currChar == NULL ) break; }
{ length += 1; }
{ hashValue = PseudoRotate ( hashValue ) ^ currChar; }
{ ) }
{ result = (length << kPEFHashLengthShift) | }
{ ((UInt16) ((hashValue ^ (hashValue >> 16)) & kPEFHashValueMask)); }
{ return result; }
{ ) // PEFComputeHashWord () }
{ =========================================================================================== }
{ Exported Symbols }
{ ---------------- }
type
PEFExportedSymbolPtr = ^PEFExportedSymbol;
PEFExportedSymbol = record
{ ! This structure is 10 bytes long and arrays are packed.}
classAndName: UInt32; { A combination of class and name offset.}
symbolValue: UInt32; { Typically the symbol's offset within a section.}
sectionIndex: SInt16; { The index of the section, or pseudo-section, for the symbol.}
end;
{ -------------------------------------------------------------------------------------------- }
{ The classAndName field of the PEFExportedSymbol type has the following bit field layout. }
{ 3 }
{ 0 7 8 1 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ | symbol class | offset of symbol name in loader string table | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<-- 8 bits --->|<-- 24 bits ---------------------------------->| }
const
kPEFExpSymClassShift = 24;
kPEFExpSymNameOffsetMask = $00FFFFFF;
kPEFExpSymMaxNameOffset = $00FFFFFF; { 16,777,215}
(*
#define PEFExportedSymbolClass(classAndName) ((UInt8) ((classAndName) >> kPEFExpSymClassShift))
#define PEFExportedSymbolNameOffset(classAndName) ((classAndName) & kPEFExpSymNameOffsetMask)
#define PEFComposeExportedSymbol(class,nameOffset) \
( ( ((UInt32)(class)) << kPEFExpSymClassShift ) | ( (UInt32)(nameOffset) ) )
*)
const
{ Negative section indices indicate pseudo-sections.}
kPEFAbsoluteExport = -2; { The symbol value is an absolute address.}
kPEFReexportedImport = -3; { The symbol value is the index of a reexported import.}
{ =========================================================================================== }
{ Loader Relocations }
{ ================== }
{ -------------------------------------------------------------------------------------------- }
{ The relocations for a section are defined by a sequence of instructions for an abstract }
{ machine that is specifically geared to performing relocations commonly needed for the "CFM" }
{ code generation model. These instructions occur in 16 bit chunks. Most instructions have }
{ just a single chunk. Instructions that are larger than 16 bits have an opcode and some of }
{ the operands in the first chunk, with other operands in following chunks. }
{ ! Note that the multi-chunk relocations have separate "Compose" macros for each chunk. The }
{ ! macros have the same basic name with a positional suffix of "_1st", "_2nd", etc. }
type
PEFRelocChunk = UInt16;
PEFLoaderRelocationHeaderPtr = ^PEFLoaderRelocationHeader;
PEFLoaderRelocationHeader = record
sectionIndex: UInt16; { Index of the section to be fixed up.}
reservedA: UInt16; { Reserved, must be zero.}
relocCount: UInt32; { Number of 16 bit relocation chunks.}
firstRelocOffset: UInt32; { Offset of first relocation instruction.}
end;
{ -------------------------------------------------------------------------------------------- }
{ ! Note that the relocCount field is the number of 16 bit relocation chunks, i.e. 1/2 the }
{ ! total number of bytes of relocation instructions. While most relocation instructions are }
{ ! 16 bits long, some are longer so the number of complete relocation instructions may be }
{ ! less than the relocCount value. }
{ ------------------------------------------------------------------------------------ }
{ The PEFRelocField macro is a utility for extracting relocation instruction fields. }
(*
#define PEFRFShift(offset,length) (16 - ((offset) + (length)))
#define PEFRFMask(length) ((1 << (length)) - 1)
#define PEFRelocField(chunk,offset,length) \
( ( (chunk) >> (16 - ((offset) + (length))) ) & ((1 << (length)) - 1) )
*)
{ =========================================================================================== }
{ Basic Relocation Opcodes }
{ ------------------------ }
{ -------------------------------------------------------------------------------------------- }
{ The number of opcode bits varies from 2 to 7. The enumeration and switch table given here }
{ are defined in terms of the most significant 7 bits of the first instruction chunk. An }
{ instruction is decoded by using the most significant 7 bits as an index into the opcode }
{ table, which in turn contains appropriately masked forms of the most significant 7 bits. }
{ The macro PEFRelocBasicOpcode assumes a declaration of the form. }
{ UInt8 kPEFRelocBasicOpcodes [kPEFRelocBasicOpcodeRange] = ( PEFMaskedBasicOpcodes ); }
const
kPEFRelocBasicOpcodeRange = 128;
(*
#define PEFRelocBasicOpcode(firstChunk) (kPEFRelocBasicOpcodes[(firstChunk)>>9])
*)
{ -------------------------------------------------------------------------------------------- }
{ The relocation opcodes, clustered by major and minor groups. The instructions within a }
{ cluster all have the same bit field layout. The enumeration values use the high order 7 }
{ bits of the relocation instruction. Unused low order bits are set to zero. }
const
kPEFRelocBySectDWithSkip = $00; { Binary: 00x_xxxx}
kPEFRelocBySectC = $20; { Binary: 010_0000, group is "RelocRun"}
kPEFRelocBySectD = $21; { Binary: 010_0001}
kPEFRelocTVector12 = $22; { Binary: 010_0010}
kPEFRelocTVector8 = $23; { Binary: 010_0011}
kPEFRelocVTable8 = $24; { Binary: 010_0100}
kPEFRelocImportRun = $25; { Binary: 010_0101}
kPEFRelocSmByImport = $30; { Binary: 011_0000, group is "RelocSmIndex"}
kPEFRelocSmSetSectC = $31; { Binary: 011_0001}
kPEFRelocSmSetSectD = $32; { Binary: 011_0010}
kPEFRelocSmBySection = $33; { Binary: 011_0011}
kPEFRelocIncrPosition = $40; { Binary: 100_0xxx}
kPEFRelocSmRepeat = $48; { Binary: 100_1xxx}
kPEFRelocSetPosition = $50; { Binary: 101_000x}
kPEFRelocLgByImport = $52; { Binary: 101_001x}
kPEFRelocLgRepeat = $58; { Binary: 101_100x}
kPEFRelocLgSetOrBySection = $5A; { Binary: 101_101x}
kPEFRelocUndefinedOpcode = $FF; { Used in masking table for all undefined values.}
{ ---------------------------------------------------------------------------- }
{ The RelocLgSetOrBySection instruction has an additional 4 bits of subopcode }
{ beyond the 7 used by the dispatch table. To be precise it has 6 plus 4 but }
{ the dispatch table ignores the 7th bit, so the subdispatch is on all 4 extra }
{ subopcode bits. }
const
kPEFRelocLgBySectionSubopcode = $00; { Binary: 0000}
kPEFRelocLgSetSectCSubopcode = $01; { Binary: 0001}
kPEFRelocLgSetSectDSubopcode = $02; { Binary: 0010}
(*
#define PEFRelocLgSetOrBySubopcode(chunk) (((chunk) >> 6) & 0x0F)
*)
{ -------------------------------------------------------------------------------------------- }
{ The initial values for the opcode "masking" table. This has the enumeration values from }
{ above with appropriate replications for "don't care" bits. It is almost certainly shorter }
{ and faster to look up the masked value in a table than to use a branch tree. }
(*
#define PEFMaskedBasicOpcodes \
\
kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, { 0x00 .. 0x03 } \
kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, { 0x04 .. 0x07 } \
kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, { 0x08 .. 0x0B } \
kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, { 0x0C .. 0x0F } \
\
kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, { 0x10 .. 0x13 } \
kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, { 0x14 .. 0x17 } \
kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, { 0x18 .. 0x1B } \
kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, kPEFRelocBySectDWithSkip, { 0x1C .. 0x1F } \
\
kPEFRelocBySectC, kPEFRelocBySectD, kPEFRelocTVector12, kPEFRelocTVector8, { 0x20 .. 0x23 } \
kPEFRelocVTable8, kPEFRelocImportRun, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x24 .. 0x27 } \
\
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x28 .. 0x2B } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x2C .. 0x2F } \
\
kPEFRelocSmByImport, kPEFRelocSmSetSectC, kPEFRelocSmSetSectD, kPEFRelocSmBySection, { 0x30 .. 0x33 } \
\
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x34 .. 0x37 } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x38 .. 0x3B } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x3C .. 0x3F } \
\
kPEFRelocIncrPosition, kPEFRelocIncrPosition, kPEFRelocIncrPosition, kPEFRelocIncrPosition, { 0x40 .. 0x43 } \
kPEFRelocIncrPosition, kPEFRelocIncrPosition, kPEFRelocIncrPosition, kPEFRelocIncrPosition, { 0x44 .. 0x47 } \
\
kPEFRelocSmRepeat, kPEFRelocSmRepeat, kPEFRelocSmRepeat, kPEFRelocSmRepeat, { 0x48 .. 0x4B } \
kPEFRelocSmRepeat, kPEFRelocSmRepeat, kPEFRelocSmRepeat, kPEFRelocSmRepeat, { 0x4C .. 0x4F } \
\
kPEFRelocSetPosition, kPEFRelocSetPosition, kPEFRelocLgByImport, kPEFRelocLgByImport, { 0x50 .. 0x53 } \
\
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x54 .. 0x57 } \
\
kPEFRelocLgRepeat, kPEFRelocLgRepeat, kPEFRelocLgSetOrBySection, kPEFRelocLgSetOrBySection, { 0x58 .. 0x5B } \
\
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x5C .. 0x5F } \
\
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x60 .. 0x63 } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x64 .. 0x67 } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x68 .. 0x6B } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x6C .. 0x6F } \
\
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x70 .. 0x73 } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x74 .. 0x77 } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, { 0x78 .. 0x7B } \
kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode, kPEFRelocUndefinedOpcode { 0x7C .. 0x7F }
*)
{ =========================================================================================== }
{ RelocBySectDWithSkip Instruction (DDAT) }
{ --------------------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocBySectDWithSkip" (DDAT) instruction has the following bit field layout. }
{ 1 1 }
{ 0 1 2 9 0 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |0 0| skip count | rel count | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ | 2 |<-- 8 bits --->|<-- 6 --->| }
{ ! Note that the stored skip count and reloc count are the actual values! }
const
kPEFRelocWithSkipMaxSkipCount = 255;
kPEFRelocWithSkipMaxRelocCount = 63;
(*
#define PEFRelocWithSkipSkipCount(chunk) PEFRelocField ( (chunk), 2, 8 )
#define PEFRelocWithSkipRelocCount(chunk) PEFRelocField ( (chunk), 10, 6 )
#define PEFRelocComposeWithSkip(skipCount,relocCount) \
( 0x0000 | (((UInt16)(skipCount)) << 6) | ((UInt16)(relocCount)) )
*)
{ =========================================================================================== }
{ RelocRun Group (CODE, DATA, DESC, DSC2, VTBL, SYMR) }
{ --------------------------------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocRun" group includes the "RelocBySectC" (CODE), "RelocBySectD" (DATA), }
{ "RelocTVector12" (DESC), "RelocTVector8" (DSC2), "RelocVTable8" (VTBL), and }
{ "RelocImportRun" (SYMR) instructions. This group has the following bit field layout. }
{ 1 }
{ 0 2 3 6 7 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |0 1 0| subop.| run length | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ | 3 |<- 4 ->|<-- 9 bits ----->| }
{ ! Note that the stored run length is the actual value minus 1, but the macros deal with the }
{ ! actual value! }
const
kPEFRelocRunMaxRunLength = 512;
(*
#define PEFRelocRunSubopcode(chunk) PEFRelocField ( (chunk), 3, 4 )
#define PEFRelocRunRunLength(chunk) (PEFRelocField ( (chunk), 7, 9 ) + 1)
#define PEFRelocComposeRun(subopcode,runLength) \
( 0x4000 | (((UInt16)(subopcode)) << 9) | ((UInt16)((runLength)-1)) )
#define PEFRelocComposeBySectC(runLength) PEFRelocComposeRun ( 0, (runLength) )
#define PEFRelocComposeBySectD(runLength) PEFRelocComposeRun ( 1, (runLength) )
#define PEFRelocComposeTVector12(runLength) PEFRelocComposeRun ( 2, (runLength) )
#define PEFRelocComposeTVector8(runLength) PEFRelocComposeRun ( 3, (runLength) )
#define PEFRelocComposeVTable8(runLength) PEFRelocComposeRun ( 4, (runLength) )
#define PEFRelocComposeImportRun(runLength) PEFRelocComposeRun ( 5, (runLength) )
*)
{ =========================================================================================== }
{ RelocSmIndex Group (SYMB, CDIS, DTIS, SECN) }
{ ------------------------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocSmIndex" group includes the "RelocSmByImport" (SYMB), "RelocSmSetSectC" (CDIS), }
{ "RelocSmSetSectD" (DTIS) and "RelocSmBySection" (SECN) instructions. This group has the }
{ following bit field layout. }
{ 1 }
{ 0 2 3 6 7 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |0 1 1| subop.| index | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ | 3 |<- 4 ->|<-- 9 bits ----->| }
{ ! Note that the stored index is the actual value! }
const
kPEFRelocSmIndexMaxIndex = 511;
(*
#define PEFRelocSmIndexSubopcode(chunk) PEFRelocField ( (chunk), 3, 4 )
#define PEFRelocSmIndexIndex(chunk) PEFRelocField ( (chunk), 7, 9 )
#define PEFRelocComposeSmIndex(subopcode,index) \
( 0x6000 | (((UInt16)(subopcode)) << 9) | ((UInt16)(index)) )
#define PEFRelocComposeSmByImport(index) PEFRelocComposeSmIndex ( 0, (index) )
#define PEFRelocComposeSmSetSectC(index) PEFRelocComposeSmIndex ( 1, (index) )
#define PEFRelocComposeSmSetSectD(index) PEFRelocComposeSmIndex ( 2, (index) )
#define PEFRelocComposeSmBySection(index) PEFRelocComposeSmIndex ( 3, (index) )
*)
{ =========================================================================================== }
{ RelocIncrPosition Instruction (DELT) }
{ ------------------------------------ }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocIncrPosition" (DELT) instruction has the following bit field layout. }
{ 1 }
{ 0 3 4 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |1 0 0 0| offset | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<- 4 ->|<-- 12 bits ---------->| }
{ ! Note that the stored offset is the actual value minus 1, but the macros deal with the }
{ ! actual value! }
const
kPEFRelocIncrPositionMaxOffset = 4096;
(*
#define PEFRelocIncrPositionOffset(chunk) (PEFRelocField ( (chunk), 4, 12 ) + 1)
#define PEFRelocComposeIncrPosition(offset) \
( 0x8000 | ((UInt16)((offset)-1)) )
*)
{ =========================================================================================== }
{ RelocSmRepeat Instruction (RPT) }
{ ------------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocSmRepeat" (RPT) instruction has the following bit field layout. }
{ 1 }
{ 0 3 4 7 8 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |1 0 0 1| chnks | repeat count | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<- 4 ->|<- 4 ->|<-- 8 bits --->| }
{ ! Note that the stored chunk count and repeat count are the actual values minus 1, but the }
{ ! macros deal with the actual values! }
const
kPEFRelocSmRepeatMaxChunkCount = 16;
kPEFRelocSmRepeatMaxRepeatCount = 256;
(*
#define PEFRelocSmRepeatChunkCount(chunk) (PEFRelocField ( (chunk), 4, 4 ) + 1)
#define PEFRelocSmRepeatRepeatCount(chunk) (PEFRelocField ( (chunk), 8, 8 ) + 1)
#define PEFRelocComposeSmRepeat(chunkCount,repeatCount) \
( 0x9000 | ((((UInt16)(chunkCount))-1) << 8) | (((UInt16)(repeatCount))-1) )
*)
{ =========================================================================================== }
{ RelocSetPosition Instruction (LABS) }
{ ----------------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocSetPosition" (LABS) instruction has the following bit field layout. }
{ 1 1 }
{ 0 5 6 5 0 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |1 0 1 0 0 0| offset (high) | | offset (low) | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<-- 6 ---->|<-- 10 bits ------>| |<-- 16 bits ------------------>| }
{ ! Note that the stored offset is the actual value! }
const
kPEFRelocSetPosMaxOffset = $03FFFFFF; { 67,108,863}
(*
#define PEFRelocSetPosOffsetHigh(chunk) PEFRelocField ( (chunk), 6, 10 )
#define PEFRelocSetPosFullOffset(firstChunk,secondChunk) \
( ((((UInt32)(firstChunk)) & 0x03FF) << 16) | ((UInt32)(secondChunk)) )
#define PEFRelocComposeSetPosition_1st(fullOffset) \
( 0xA000 | ((UInt16) (((UInt32)(fullOffset)) >> 16) ) )
#define PEFRelocComposeSetPosition_2nd(fullOffset) \
( (UInt16) ((UInt32)(fullOffset) & 0xFFFF) )
*)
{ =========================================================================================== }
{ RelocLgByImport Instruction (LSYM) }
{ ---------------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocLgByImport" (LSYM) instruction has the following bit field layout. }
{ 1 1 }
{ 0 5 6 5 0 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |1 0 1 0 0 1| index (high) | | index (low) | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<-- 6 ---->|<-- 10 bits ------>| |<-- 16 bits ------------------>| }
{ ! Note that the stored offset is the actual value! }
const
kPEFRelocLgByImportMaxIndex = $03FFFFFF; { 67,108,863}
(*
#define PEFRelocLgByImportIndexHigh(chunk) PEFRelocField ( (chunk), 6, 10 )
#define PEFRelocLgByImportFullIndex(firstChunk,secondChunk) \
( ((((UInt32)(firstChunk)) & 0x03FF) << 16) | ((UInt32)(secondChunk)) )
#define PEFRelocComposeLgByImport_1st(fullIndex) \
( 0xA400 | ((UInt16) (((UInt32)(fullIndex)) >> 16) ) )
#define PEFRelocComposeLgByImport_2nd(fullIndex) \
( (UInt16) ((UInt32)(fullIndex) & 0xFFFF) )
*)
{ =========================================================================================== }
{ RelocLgRepeat Instruction (LRPT) }
{ -------------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocLgRepeat" (LRPT) instruction has the following bit field layout. }
{ 1 1 1 }
{ 0 5 6 9 0 5 0 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |1 0 1 1 0 0| chnks | rpt (high)| | repeat count (low) | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<-- 6 --->|<- 4 ->|<-- 6 --->| |<-- 16 bits ------------------>| }
{ ! Note that the stored chunk count is the actual value minus 1, but the macros deal with }
{ ! the actual value! The stored repeat count is the actual value! }
const
kPEFRelocLgRepeatMaxChunkCount = 16;
kPEFRelocLgRepeatMaxRepeatCount = $003FFFFF; { 4,194,303}
(*
#define PEFRelocLgRepeatChunkCount(chunk) (PEFRelocField ( (chunk), 6, 4 ) + 1)
#define PEFRelocLgRepeatRepeatCountHigh(chunk) PEFRelocField ( (chunk), 10, 6 )
#define PEFRelocLgRepeatFullRepeatCount(firstChunk,secondChunk) \
( ((((UInt32)(firstChunk)) & 0x003F) << 16) | ((UInt32)(secondChunk)) )
#define PEFRelocComposeLgRepeat_1st(chunkCount,fullRepeatCount) \
( 0xB000 | ((((UInt16)(chunkCount))-1) << 6) | ((UInt16) (((UInt32)(fullRepeatCount)) >>16 ) ) )
#define PEFRelocComposeLgRepeat_2nd(chunkCount,fullRepeatCount) \
( (UInt16) ((UInt32)(fullRepeatCount) & 0xFFFF) )
*)
{ =========================================================================================== }
{ RelocLgSetOrBySection Group (LSEC) }
{ ---------------------------------- }
{ -------------------------------------------------------------------------------------------- }
{ The "RelocLgSetOrBySection" (LSEC) instruction is a group including the "RelocLgBySection", }
{ "RelocLgSetSectC" and "RelocLgSetSectD" instructions. This group has the following bit }
{ field layout. }
{ 1 1 1 }
{ 0 5 6 9 0 5 0 5 }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |1 0 1 1 0 1| subop | idx (high)| | index (low) | }
{ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ }
{ |<-- 6 --->|<- 4 ->|<-- 6 --->| |<-- 16 bits ------------------>| }
{ ! Note that the stored index is the actual value! }
const
kPEFRelocLgSetOrBySectionMaxIndex = $003FFFFF; { 4,194,303}
(*
#define PEFRelocLgSetOrBySectionSubopcode(chunk) PEFRelocField ( (chunk), 6, 4 )
#define PEFRelocLgSetOrBySectionIndexHigh(chunk) PEFRelocField ( (chunk), 10, 6 )
#define PEFRelocLgSetOrBySectionFullIndex(firstChunk,secondChunk) \
( ((((UInt32)(firstChunk)) & 0x003F) << 16) | ((UInt32)(secondChunk)) )
#define PEFRelocComposeLgSetOrBySection_1st(subopcode,fullIndex) \
( 0xB400 | (((UInt16)(subopcode)) << 6) | ((UInt16) (((UInt32)(fullIndex)) >> 16) ) )
#define PEFRelocComposeLgSetOrBySection_2nd(subopcode,fullIndex) \
( (UInt16) ((UInt32)(fullIndex) & 0xFFFF) )
#define PEFRelocComposeLgBySection(fullIndex) PEFRelocComposeLgSetOrBySection ( 0x00, (fullIndex) )
#define PEFRelocComposeLgSetSectC(fullIndex) PEFRelocComposeLgSetOrBySection ( 0x01, (fullIndex) )
#define PEFRelocComposeLgSetSectD(fullIndex) PEFRelocComposeLgSetOrBySection ( 0x02, (fullIndex) )
*)
{ ======================================================================================== }
{ ======================================================================================== }
{ ======================================================================================== }
{ Vector Library Declarations }
{ =========================== }
{ -------------------------------------------------------------------------------------------- }
{ Mac OS X has special "vector" and "bridge" libraries to allow CFM managed clients to import }
{ from the dyld managed implementation libraries. The vector libraries are typically embedded }
{ within their respective implementation libraries. Even if standalone, the vector libraries }
{ are themselves normal dyld managed libraries. The vector libraries contain an export symbol }
{ table and pointers to the actual implementations. For functions, these pointers serve as }
{ the PMacCG TVectors. Because the dyld libraries are not part of the CFM search, we need a }
{ separate library for CFM to find that then indicates where the vector library is. These are }
{ the bridge libraries. They are tiny, just the container header and container strings parts. }
{ Since the vector library is embedded in a Mach-O dylib, we use dyld services to obtain the }
{ base address for the main portion and the exported symbol portion. The binding pointers are }
{ found through offsets in the exported symbol records. }
{ +-----------------------------------+ <-- containerOrigin ------------+ }
{ | Container Header | 76 bytes | }
{ |-----------------------------------| <-- + containerStringsOffset ---| }
{ | Container Strings | | }
{ |-----------------------------------| <-- + exportHashOffset ---------+ }
{ | Export Hash Slot 0 | 4 bytes each | }
{ |...................................| | }
{ | - - - | | }
{ |...................................| | }
{ | Export Hash Slot h-1 | | }
{ |-----------------------------------| <-- + exportKeyOffset ----------+ }
{ | Export Symbol Key 0 | 4 bytes each | }
{ |...................................| Order must match the exported symbols | }
{ | - - - | | }
{ |...................................| | }
{ | Export Symbol Key e-1 | | }
{ |-----------------------------------| <-- + exportNamesOffset --------+ }
{ | Export Names | | }
{ |-----------------------------------| | }
{ (Disjoint parts) | }
{ |-----------------------------------| <-- + exportSymbolOffset -------+ }
{ | Export Symbol 0 | 8 bytes each }
{ |...................................| Order must match the export keys }
{ | - - - | }
{ |...................................| }
{ | Export Symbol e-1 | }
{ +-----------------------------------+ }
{ (Disjoint parts) }
{ |-----------------------------------| }
{ | Binding Pointer 0 | 4 bytes each }
{ |-----------------------------------| Possibly disjoint, order does not matter }
{ | - - - | }
{ |-----------------------------------| }
{ | Binding Pointer e-1 | }
{ +-----------------------------------+ }
type
XLibContainerHeaderPtr = ^XLibContainerHeader;
XLibContainerHeader = record
{ Structural description fields:}
tag1: OSType; { Must contain 'ðMac'.}
tag2: OSType; { Must contain 'vLib' or 'bLib'.}
currentFormat: UInt32; { The version of XLib types used to create this container.}
containerStringsOffset: UInt32; { Container offset of the container string table.}
exportHashOffset: UInt32; { Offset of the export hash table.}
exportKeyOffset: UInt32; { Offset of the export key table.}
exportSymbolOffset: UInt32; { Offset of the export symbol table.}
exportNamesOffset: UInt32; { Offset of the export names.}
exportHashTablePower: UInt32; { Export hash table size as log 2. (Log2('h'))}
exportedSymbolCount: UInt32; { Number of exported symbols. ('e')}
{ Fragment description fields:}
fragNameOffset: UInt32; { The offset of the fragment name in the container string table.}
fragNameLength: UInt32; { The length of the fragment name in the container string table.}
dylibPathOffset: UInt32; { The offset of the dyld "install name" in the container string table.}
dylibPathLength: UInt32; { The length of the dyld "install name" in the container string table.}
cpuFamily: OSType; { The ISA for code sections. Constants in CodeFragments.h.}
cpuModel: OSType; { Specific CPU model if applicable.}
dateTimeStamp: UInt32; { Mac format creation stamp.}
currentVersion: UInt32; { Current version number for the code fragment.}
oldDefVersion: UInt32; { Old definition version number for the code fragment.}
oldImpVersion: UInt32; { Old implementation version number for the code fragment.}
end;
const
kXLibTag1 = FourCharCode('ðMac'); { For non-Apple compilers: 0xF04D6163.}
kVLibTag2 = FourCharCode('VLib'); { For non-Apple compilers: 0x564C6962.}
kBLibTag2 = FourCharCode('BLib'); { For non-Apple compilers: 0x424C6962.}
kXLibVersion = $00000001;
type
XLibExportedSymbolHashSlot = PEFExportedSymbolHashSlot;
XLibExportedSymbolKey = PEFExportedSymbolKey;
XLibExportedSymbolPtr = ^XLibExportedSymbol;
XLibExportedSymbol = record
classAndName: UInt32; { A combination of class and name offset.}
bpOffset: UInt32; { Container offset of the export's dyld binding pointer.}
end;
{ =========================================================================================== }
{$ifc not undefined IncludePEF2Declarations and IncludePEF2Declarations}
{ ======================================================================================== }
{ ======================================================================================== }
{ ======================================================================================== }
{ PEF2 Declarations }
{ ================= }
{ -------------------------------------------------------------------------------------------- }
{ PEF2 is a follow-on to the original PEF, incorporating changes that would break backward }
{ compatibility. The primary motivations for PEF2 are to incorporate new features cleanly, to }
{ relax some physical limitations, and to provide a more explicit path for future growth. }
{ PEF2 is very similar to PEF, it is possible for any PEF container to be mechanically }
{ converted to PEF2. The converse is not necessarily true, containers that use new features }
{ of PEF2 might not be convertable to PEF. }
{ One difference from PEF is that PEF2 has no implicit ordering, e.g. the section headers do }
{ not necessarily immediately follow the container header. Explicit offsets and lengths are }
{ provided for all portions of the container so that tools can continue to parse PEF2 as new }
{ versions of it are produced in the future. The following overall layout is suggested for }
{ locality of reference in typical usage with a packed data image: }
{ +-----------------------------------+ }
{ | Container Header | }
{ +-----------------------------------+ }
{ | Section 0 header | }
{ |...................................| }
{ | - - - - | }
{ |...................................| }
{ | Section n-1 header | }
{ +-----------------------------------+ }
{ | Container String Table | }
{ +-----------------------------------+ }
{ | Loader section contents | }
{ +-----------------------------------+ }
{ | Packed data contents | }
{ +-----------------------------------+ }
{ | Code section contents | }
{ +-----------------------------------+ }
{ If unpacked data is used for prebinding with copy-on-write mapping, the unpacked data should }
{ follow the code section. }
{ Note that the rule regarding instantiated sections preceeding noninstantiated sections only }
{ applies to the section headers, not the section contents. Thus it is perfectly fine for the }
{ loader section contents to be first. }
{ The container string table holds the name of the fragment and the names of the sections. }
{ The first 4 bytes of the container string table must be zero and always present. An offset }
{ of zero into the container string table is considered a null name. Actual names are stored }
{ as a PEF-style 32 bit hashword followed by the text of the name. The encoding of the text }
{ is given by the stringEncoding field of the container header. The hashword is computed from }
{ the encoded name as a string of bytes. The length in the hashword is the number of bytes in }
{ the encoded name, not the number of logical characters. }
{ =========================================================================================== }
{ Container Header }
{ ================ }
type
PEF2ContainerHeaderPtr = ^PEF2ContainerHeader;
PEF2ContainerHeader = record
{ Structural fields:}
tag1: OSType; { Must contain 'Joy!'.}
tag2: OSType; { Must contain 'PEF '.}
currentFormat: UInt32; { The version of PEF2 used to create this container.}
oldestFormat: UInt32; { Oldest compatible container handler.}
containerHeaderSize: UInt32; { The size of this header in bytes.}
containerLength: UInt32; { The total length of the container in bytes.}
checksum: UInt32; { A checksum for the entire container.}
sectionHeadersOffset: UInt32; { Container offset of the first section header.}
sectionHeaderSize: UInt32; { The size in bytes of each section header.}
totalSectionCount: UInt32; { Total number of section headers.}
instSectionCount: UInt32; { Number of instantiated sections.}
loaderSectionIndex: UInt32; { Index of the section containing runtime loader tables.}
containerStringsOffset: UInt32; { Container offset of the container string table.}
containerStringsLength: UInt32; { Length in bytes of the container string table.}
options: UInt32; { Array of 32 option bits.}
preferredAddress: UInt32; { Preferred container address, 0xFFFFFFFF indicates no preference.}
alignment: UInt8; { Required container alignment as LOG 2.}
stringEncoding: UInt8; { The encoding for all strings in the container.}
reservedA: UInt16; { Reserved, must be written as zero.}
reservedB: UInt32; { Reserved, must be written as zero.}
reservedC: UInt32; { Reserved, must be written as zero.}
{ Fragment description fields:}
nameOffset: UInt32; { The offset of the name in the container string table.}
architecture: OSType; { The ISA for code sections. Constants in CodeFragments.h.}
dateTimeStamp: UInt32; { Macintosh format creation/modification stamp.}
currentVersion: UInt32; { Current version number for the code fragment.}
oldDefVersion: UInt32; { Old definition version number for the code fragment.}
oldImpVersion: UInt32; { Old implementation version number for the code fragment.}
reservedD: UInt32; { Reserved, must be written as zero.}
reservedE: UInt32; { Reserved, must be written as zero.}
end;
const
kPEF2Tag1 = kPEFTag1;
kPEF2Tag2 = FourCharCode('PEF '); { For non-Apple compilers: 0x50656620.}
kPEF2CurrentFormat = $00000002; { ! There is no version 0 or 1.}
kPEF2OldestHandler = $00000002;
const
{ Values for the options field.}
kPEF2IsReexportLibraryMask = $00000001; { This fragment does nothing but reexport imports.}
kPEF2IsGlueLibraryMask = $00000002; { A special form of import library that provides a glue layer.}
const
{ Values for the stringEncoding field.}
kPEF2StringsAreASCII = 0;
kPEF2StringsAreUnicode = 1;
{ =========================================================================================== }
{ Section Headers }
{ =============== }
type
PEF2SectionHeaderPtr = ^PEF2SectionHeader;
PEF2SectionHeader = record
nameOffset: UInt32; { Offset of the name within the container string table.}
presumedAddress: UInt32; { Presumed address, affects relocations.}
totalLength: UInt32; { Fully expanded size in bytes of the section contents.}
unpackedLength: UInt32; { Size in bytes of the "initialized" part of the contents.}
containerLength: UInt32; { Size in bytes of the raw data in the container.}
containerOffset: UInt32; { Offset of section's raw data within the container.}
options: UInt32; { Array of 32 option bits.}
shareKind: UInt8; { Sharing level, if a writeable section.}
alignment: UInt8; { Required alignment, expressed as log 2.}
reservedA: UInt16; { Reserved, must be written as zero.}
reservedB: UInt32; { Reserved, must be written as zero.}
reservedC: UInt32; { Reserved, must be written as zero.}
end;
const
{ Masks for instantiated section options.}
{ Bits that define the preparation and usage of the section's contents.}
kPEF2SectionHasCodeMask = $00000001; { Affects cache flushing operations.}
kPEF2SectionIsWriteableMask = $00000002; { Affects MMU access.}
kPEF2SectionHasRelocationsMask = $00000004; { The section has runtime relocations.}
kPEF2SectionContentsArePackedMask = $00000100; { The raw data is compressed.}
kPEF2SectionNoZeroFillMask = $00000200; { "Uninit" part is not zero filled.}
kPEF2SectionResidentMask = $00000400; { The section should be RAM resident.}
{ Bits that describe higher level semantics.}
kPEF2SectionFollowsPriorMask = $00010000; { Raw data is related to prior section.}
kPEF2SectionPrecedesNextMask = $00020000; { Raw data is related to next section.}
kPEF2SectionHasLoaderTablesMask = $01000000;
kPEF2SectionHasDebugTablesMask = $02000000;
kPEF2SectionHasExceptionTablesMask = $04000000;
kPEF2SectionHasTracebackTablesMask = $08000000;
const
{ Values for the shareKind field.}
kPEF2PrivateShare = 0; { Shared only within a "private" closure.}
kPEF2ProcessShare = 1; { Shared within a single process.}
kPEF2GlobalShare = 4; { Shared across the entire system.}
kPEF2ProtectedShare = 5; { Readable across the entire system, writeable only to privileged code.}
{ =========================================================================================== }
{ Loader Section }
{ ============== }
{ -------------------------------------------------------------------------------------------- }
{ The PEF2 loader section is very similar to that of PEF. The following overall layout is }
{ not required, but suggested for typical locality of reference. The loader header contains }
{ explicit offsets and sizes for each of the subsections. }
{ +-----------------------------------+ }
{ | Loader Info Header | }
{ |-----------------------------------| }
{ | Imported Library 0 | }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Imported Library l-1 | }
{ |-----------------------------------| }
{ | Imported Symbol 0 | }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Imported Symbol i-1 | }
{ |-----------------------------------| }
{ | Loader Name Table | }
{ |-----------------------------------| }
{ | Export Hash Slot 0 | }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Export Hash Slot h-1 | }
{ |-----------------------------------| }
{ | Exported Symbol Key 0 | }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Exported Symbol Key e-1 | }
{ |-----------------------------------| }
{ | Exported Symbol 0 | }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Exported Symbol e-1 | }
{ |-----------------------------------| }
{ | Relocation Header 0 | }
{ |...................................| }
{ | - - - | }
{ |...................................| }
{ | Relocation Header r-1 | }
{ |-----------------------------------| }
{ | Relocation Instructions | }
{ +-----------------------------------+ }
type
PEF2LoaderInfoHeaderPtr = ^PEF2LoaderInfoHeader;
PEF2LoaderInfoHeader = record
headerSize: UInt32; { Size in bytes of the loader info header.}
options: UInt32; { An array of 32 option bits.}
mainSection: SInt32; { Section containing the main symbol, -1 => none.}
mainOffset: UInt32; { Offset of main symbol.}
initSection: SInt32; { Section containing the init routine's TVector, -1 => none.}
initOffset: UInt32; { Offset of the init routine's TVector.}
termSection: SInt32; { Section containing the term routine's TVector, -1 => none.}
termOffset: UInt32; { Offset of the term routine's TVector.}
notifySection: SInt32; { Section containing the notification routine's TVector, -1 => none.}
notifyOffset: UInt32; { Offset of the notification routine's TVector.}
importedLibrariesOffset: UInt32; { Offset of the imported library table.}
importedLibrarySize: UInt32; { The size in bytes of an imported library entry.}
importedLibraryCount: UInt32; { Number of imported libraries. ('l')}
importedSymbolsOffset: UInt32; { Offset of the imported symbol table.}
importedSymbolSize: UInt32; { The size in bytes of an imported symbol entry.}
totalImportedSymbolCount: UInt32; { Total number of imported symbols. ('s')}
loaderNamesOffset: UInt32; { Offset of the loader name table.}
loaderNamesLength: UInt32; { Total number of bytes in the loader name table.}
exportHashTableOffset: UInt32; { Offset of the export hash slot table.}
exportHashTablePower: UInt8; { Hash slot count as log 2.}
reservedA: UInt8; { Reserved, must be zero.}
reservedB: UInt16; { Reserved, must be zero.}
exportedKeysOffset: UInt32; { Offset of the exported symbol key table.}
exportedSymbolsOffset: UInt32; { Offset of the exported symbol table.}
exportedSymbolSize: UInt32; { The size in bytes of an exported symbol entry.}
exportedSymbolCount: UInt32; { Number of exported symbols. ('e')}
relocHeadersOffset: UInt32; { Offset of the relocation headers.}
relocHeaderCount: UInt32; { Number of sections with relocations.}
relocInstrOffset: UInt32; { Offset of the relocation instructions.}
relocInstrLength: UInt32; { Total number of bytes of relocation instructions.}
reservedC: UInt32; { Reserved, must be zero.}
reservedD: UInt32; { Reserved, must be zero.}
end;
const
{ Masks for the option bits.}
kPEF2LdrInfoLargeImpSymMask = $00000001; { Selects large imported symbol entries.}
kPEF2LdrInfoLargeExpSymMask = $00000002; { Selects large exported symbol entries.}
kPEF2LdrInfoLargeExpHashMask = $00000004; { Selects large export hash table entries.}
{ =========================================================================================== }
{ Imports and Exports }
{ ------------------- }
{ -------------------------------------------------------------------------------------------- }
{ Imports and exports in PEF2 have both small and large representations. The small form is }
{ identical to original PEF. The large form removes count limitations by having full 32 bit }
{ offsets. The import and export name tables have the same representation as the container }
{ string table, four bytes of zero at the start followed by pairs of 32 bit hashwords and }
{ the names in the appropriate encoding. }
type
PEF2ImportedLibraryPtr = ^PEF2ImportedLibrary;
PEF2ImportedLibrary = record
nameOffset: UInt32; { Imported name table offset of library's name.}
oldImpVersion: UInt32; { Oldest compatible implementation version.}
currentVersion: UInt32; { Current version at build time.}
importedSymbolCount: UInt32; { Imported symbol count for this library.}
firstImportedSymbol: UInt32; { Index of first imported symbol from this library.}
options: UInt32; { Option bits for this library.}
reservedA: UInt32; { Reserved, must be zero.}
end;
const
{ Bits for the PEF2ImportedLibrary options field.}
kPEF2WeakImportLibMask = kPEFWeakImportLibMask; { The imported library is allowed to be missing.}
kPEF2InitLibBeforeMask = kPEFInitLibBeforeMask; { The imported library must be initialized first.}
type
PEF2SmImportedSymbol = PEFImportedSymbol;
// PEF2ComposeSmImportedSymbol = PEFComposeImportedSymbol;
type
PEF2LgImportedSymbolPtr = ^PEF2LgImportedSymbol;
PEF2LgImportedSymbol = record
symClass: UInt8;
flags: UInt8;
reservedA: UInt16;
nameOffset: UInt32;
versionPair: UInt32;
reservedB: UInt32;
end;
PEF2SmExportedSymbolHashSlot = PEFExportedSymbolHashSlot;
PEF2ExportedSymbolKey = PEFExportedSymbolKey;
PEF2SmExportedSymbol = PEFExportedSymbol;
// PEF2ComposeSmExportedSymbol = PEFComposeExportedSymbol;
type
PEF2LgExportedSymbolHashSlotPtr = ^PEF2LgExportedSymbolHashSlot;
PEF2LgExportedSymbolHashSlot = record
chainCount: UInt32;
chainOffset: UInt32;
end;
type
PEF2LgExportedSymbolPtr = ^PEF2LgExportedSymbol;
PEF2LgExportedSymbol = record
symClass: UInt8;
flags: UInt8;
reservedA: UInt16;
nameOffset: UInt32;
versionPair: UInt32;
sectionIndex: SInt32;
sectionOffset: UInt32;
reservedB: UInt32;
end;
{ =========================================================================================== }
{ Loader Relocations }
{ ================== }
{ -------------------------------------------------------------------------------------------- }
{ The relocation header differs slightly in PEF2. The relocation instructions identical. }
type
PEF2LoaderRelocationHeaderPtr = ^PEF2LoaderRelocationHeader;
PEF2LoaderRelocationHeader = record
sectionIndex: UInt32; { Index of the section to be fixed up.}
relocLength: UInt32; { Number of bytes of relocation items.}
firstRelocOffset: UInt32; { Byte offset of first relocation instruction.}
reservedA: UInt32; { Reserved, must be zero.}
end;
{ =========================================================================================== }
{$endc} {IncludePEF2Declarations}
{$endc} {TARGET_OS_MAC}
{$ifc not defined MACOSALLINCLUDE or not MACOSALLINCLUDE}
end.
{$endc} {not MACOSALLINCLUDE}