1112 lines
66 KiB
C
1112 lines
66 KiB
C
/*
|
|
File: PEFBinaryFormat.h
|
|
|
|
Contains: PEF Types and Macros
|
|
|
|
Version: QuickTime 7.3
|
|
|
|
Copyright: (c) 2007 (c) 1993-2001 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Bugs?: For bug reports, consult the following page on
|
|
the World Wide Web:
|
|
|
|
http://developer.apple.com/bugreporter/
|
|
|
|
*/
|
|
|
|
|
|
#ifndef __PEFBINARYFORMAT__
|
|
#define __PEFBINARYFORMAT__
|
|
|
|
#ifndef __MACTYPES__
|
|
#include <MacTypes.h>
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if PRAGMA_ONCE
|
|
#pragma once
|
|
#endif
|
|
|
|
#if PRAGMA_IMPORT
|
|
#pragma import on
|
|
#endif
|
|
|
|
#if PRAGMA_STRUCT_ALIGN
|
|
#pragma options align=mac68k
|
|
#elif PRAGMA_STRUCT_PACKPUSH
|
|
#pragma pack(push, 2)
|
|
#elif PRAGMA_STRUCT_PACK
|
|
#pragma pack(2)
|
|
#endif
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------------------------- */
|
|
/* 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 */
|
|
/* ================ */
|
|
|
|
|
|
|
|
struct PEFContainerHeader {
|
|
OSType tag1; /* Must contain 'Joy!'.*/
|
|
OSType tag2; /* Must contain 'peff'. (Yes, with two 'f's.)*/
|
|
OSType architecture; /* The ISA for code sections. Constants in CodeFragments.h.*/
|
|
UInt32 formatVersion; /* The physical format version.*/
|
|
UInt32 dateTimeStamp; /* Macintosh format creation/modification stamp.*/
|
|
UInt32 oldDefVersion; /* Old definition version number for the code fragment.*/
|
|
UInt32 oldImpVersion; /* Old implementation version number for the code fragment.*/
|
|
UInt32 currentVersion; /* Current version number for the code fragment.*/
|
|
UInt16 sectionCount; /* Total number of section headers that follow.*/
|
|
UInt16 instSectionCount; /* Number of instantiated sections.*/
|
|
UInt32 reservedA; /* Reserved, must be written as zero.*/
|
|
};
|
|
typedef struct PEFContainerHeader PEFContainerHeader;
|
|
enum {
|
|
kPEFTag1 = FOUR_CHAR_CODE('Joy!'), /* For non-Apple compilers: 0x4A6F7921.*/
|
|
kPEFTag2 = FOUR_CHAR_CODE('peff'), /* For non-Apple compilers: 0x70656666.*/
|
|
kPEFVersion = 0x00000001
|
|
};
|
|
|
|
|
|
enum {
|
|
kPEFFirstSectionHeaderOffset = sizeof(PEFContainerHeader)
|
|
};
|
|
|
|
#define PEFFirstSectionNameOffset(container) \
|
|
( kPEFFirstSectionHeaderOffset + ((container)->sectionCount * sizeof ( PEFSectionHeader )) )
|
|
|
|
|
|
|
|
/* =========================================================================================== */
|
|
/* Section Headers */
|
|
/* =============== */
|
|
|
|
|
|
|
|
struct PEFSectionHeader {
|
|
SInt32 nameOffset; /* Offset of name within the section name table, -1 => none.*/
|
|
UInt32 defaultAddress; /* Default address, affects relocations.*/
|
|
UInt32 totalLength; /* Fully expanded size in bytes of the section contents.*/
|
|
UInt32 unpackedLength; /* Size in bytes of the "initialized" part of the contents.*/
|
|
UInt32 containerLength; /* Size in bytes of the raw data in the container.*/
|
|
UInt32 containerOffset; /* Offset of section's raw data.*/
|
|
UInt8 sectionKind; /* Kind of section contents/usage.*/
|
|
UInt8 shareKind; /* Sharing level, if a writeable section.*/
|
|
UInt8 alignment; /* Preferred alignment, expressed as log 2.*/
|
|
UInt8 reservedA; /* Reserved, must be zero.*/
|
|
};
|
|
typedef struct PEFSectionHeader PEFSectionHeader;
|
|
enum {
|
|
/* 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.*/
|
|
};
|
|
|
|
|
|
enum {
|
|
/* 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. */
|
|
|
|
|
|
enum {
|
|
/* 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.*/
|
|
};
|
|
|
|
|
|
enum {
|
|
kPEFPkDataOpcodeShift = 5,
|
|
kPEFPkDataCount5Mask = 0x1F,
|
|
kPEFPkDataMaxCount5 = 31,
|
|
kPEFPkDataVCountShift = 7,
|
|
kPEFPkDataVCountMask = 0x7F,
|
|
kPEFPkDataVCountEndMask = 0x80
|
|
};
|
|
|
|
|
|
#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 | */
|
|
/* +-----------------------------------+ */
|
|
|
|
|
|
|
|
struct PEFLoaderInfoHeader {
|
|
SInt32 mainSection; /* Section containing the main symbol, -1 => none.*/
|
|
UInt32 mainOffset; /* Offset of main symbol.*/
|
|
SInt32 initSection; /* Section containing the init routine's TVector, -1 => none.*/
|
|
UInt32 initOffset; /* Offset of the init routine's TVector.*/
|
|
SInt32 termSection; /* Section containing the term routine's TVector, -1 => none.*/
|
|
UInt32 termOffset; /* Offset of the term routine's TVector.*/
|
|
UInt32 importedLibraryCount; /* Number of imported libraries. ('l')*/
|
|
UInt32 totalImportedSymbolCount; /* Total number of imported symbols. ('i')*/
|
|
UInt32 relocSectionCount; /* Number of sections with relocations. ('r')*/
|
|
UInt32 relocInstrOffset; /* Offset of the relocation instructions.*/
|
|
UInt32 loaderStringsOffset; /* Offset of the loader string table.*/
|
|
UInt32 exportHashOffset; /* Offset of the export hash table.*/
|
|
UInt32 exportHashTablePower; /* Export hash table size as log 2. (Log2('h'))*/
|
|
UInt32 exportedSymbolCount; /* Number of exported symbols. ('e')*/
|
|
};
|
|
typedef struct PEFLoaderInfoHeader PEFLoaderInfoHeader;
|
|
|
|
|
|
/* =========================================================================================== */
|
|
/* Imported Libraries */
|
|
/* ------------------ */
|
|
|
|
|
|
struct PEFImportedLibrary {
|
|
UInt32 nameOffset; /* Loader string table offset of library's name.*/
|
|
UInt32 oldImpVersion; /* Oldest compatible implementation version.*/
|
|
UInt32 currentVersion; /* Current version at build time.*/
|
|
UInt32 importedSymbolCount; /* Imported symbol count for this library.*/
|
|
UInt32 firstImportedSymbol; /* Index of first imported symbol from this library.*/
|
|
UInt8 options; /* Option bits for this library.*/
|
|
UInt8 reservedA; /* Reserved, must be zero.*/
|
|
UInt16 reservedB; /* Reserved, must be zero.*/
|
|
};
|
|
typedef struct PEFImportedLibrary PEFImportedLibrary;
|
|
enum {
|
|
/* Bits for the PEFImportedLibrary options field.*/
|
|
kPEFWeakImportLibMask = 0x40, /* The imported library is allowed to be missing.*/
|
|
kPEFInitLibBeforeMask = 0x80 /* 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 ---------------------------------->| */
|
|
|
|
|
|
|
|
struct PEFImportedSymbol {
|
|
UInt32 classAndName;
|
|
};
|
|
typedef struct PEFImportedSymbol PEFImportedSymbol;
|
|
enum {
|
|
kPEFImpSymClassShift = 24,
|
|
kPEFImpSymNameOffsetMask = 0x00FFFFFF,
|
|
kPEFImpSymMaxNameOffset = 0x00FFFFFF /* 16,777,215*/
|
|
};
|
|
|
|
#define PEFImportedSymbolClass(classAndName) ((UInt8) ((classAndName) >> kPEFImpSymClassShift))
|
|
#define PEFImportedSymbolNameOffset(classAndName) ((classAndName) & kPEFImpSymNameOffsetMask)
|
|
|
|
#define PEFComposeImportedSymbol(class,nameOffset) \
|
|
( ( ((UInt32)(class)) << kPEFImpSymClassShift ) | ( (UInt32)(nameOffset) ) )
|
|
|
|
enum {
|
|
/* Imported and exported symbol classes.*/
|
|
kPEFCodeSymbol = 0x00,
|
|
kPEFDataSymbol = 0x01,
|
|
kPEFTVectorSymbol = 0x02,
|
|
kPEFTOCSymbol = 0x03,
|
|
kPEFGlueSymbol = 0x04,
|
|
kPEFUndefinedSymbol = 0x0F,
|
|
kPEFWeakImportSymMask = 0x80
|
|
};
|
|
|
|
|
|
|
|
|
|
/* =========================================================================================== */
|
|
/* 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 ---------------------->| */
|
|
|
|
|
|
|
|
struct PEFExportedSymbolHashSlot {
|
|
UInt32 countAndStart;
|
|
};
|
|
typedef struct PEFExportedSymbolHashSlot PEFExportedSymbolHashSlot;
|
|
enum {
|
|
kPEFHashSlotSymCountShift = 18,
|
|
kPEFHashSlotFirstKeyMask = 0x0003FFFF,
|
|
kPEFHashSlotMaxSymbolCount = 0x00003FFF, /* 16,383*/
|
|
kPEFHashSlotMaxKeyIndex = 0x0003FFFF /* 262,143*/
|
|
};
|
|
|
|
#define PEFHashTableIndex(fullHashWord,hashTablePower) \
|
|
( ( (fullHashWord) ^ ((fullHashWord) >> (hashTablePower)) ) & ((1 << (hashTablePower)) - 1) )
|
|
|
|
#define PEFHashSlotSymbolCount(countAndStart) ((UInt32) ((countAndStart) >> kPEFHashSlotSymCountShift))
|
|
#define PEFHashSlotFirstKey(countAndStart) ((countAndStart) & kPEFHashSlotFirstKeyMask)
|
|
|
|
#define PEFComposeExportedSymbolHashSlot(symbolCount,firstKey) \
|
|
( ( ((UInt32)(symbolCount)) << kPEFHashSlotSymCountShift ) | ( (UInt32)(firstKey) ) )
|
|
|
|
|
|
|
|
/* =========================================================================================== */
|
|
/* Exported Symbol Hash Key */
|
|
/* ------------------------ */
|
|
|
|
|
|
|
|
struct PEFSplitHashWord {
|
|
UInt16 nameLength;
|
|
UInt16 hashValue;
|
|
};
|
|
typedef struct PEFSplitHashWord PEFSplitHashWord;
|
|
struct PEFExportedSymbolKey {
|
|
union {
|
|
UInt32 fullHashWord;
|
|
PEFSplitHashWord splitHashWord;
|
|
} u;
|
|
};
|
|
typedef struct PEFExportedSymbolKey PEFExportedSymbolKey;
|
|
enum {
|
|
kPEFHashLengthShift = 16,
|
|
kPEFHashValueMask = 0x0000FFFF,
|
|
kPEFHashMaxLength = 0x0000FFFF /* 65,535*/
|
|
};
|
|
|
|
#define PEFHashNameLength(fullHashWord) ((UInt32) ((fullHashWord) >> kPEFHashLengthShift))
|
|
#define PEFHashValue(fullHashWord) ((fullHashWord) & kPEFHashValueMask)
|
|
|
|
#define PEFComposeFullHashWord(nameLength,hashValue) \
|
|
( ( ((UInt32)(nameLength)) << kPEFHashLengthShift ) | ( (UInt32)(hashValue) ) )
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
/* 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 */
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
struct PEFExportedSymbol { /* ! This structure is 10 bytes long and arrays are packed.*/
|
|
UInt32 classAndName; /* A combination of class and name offset.*/
|
|
UInt32 symbolValue; /* Typically the symbol's offset within a section.*/
|
|
SInt16 sectionIndex; /* The index of the section, or pseudo-section, for the symbol.*/
|
|
};
|
|
typedef struct PEFExportedSymbol PEFExportedSymbol;
|
|
|
|
/* -------------------------------------------------------------------------------------------- */
|
|
/* 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 ---------------------------------->| */
|
|
|
|
|
|
enum {
|
|
kPEFExpSymClassShift = 24,
|
|
kPEFExpSymNameOffsetMask = 0x00FFFFFF,
|
|
kPEFExpSymMaxNameOffset = 0x00FFFFFF /* 16,777,215*/
|
|
};
|
|
|
|
#define PEFExportedSymbolClass(classAndName) ((UInt8) ((classAndName) >> kPEFExpSymClassShift))
|
|
#define PEFExportedSymbolNameOffset(classAndName) ((classAndName) & kPEFExpSymNameOffsetMask)
|
|
|
|
#define PEFComposeExportedSymbol(class,nameOffset) \
|
|
( ( ((UInt32)(class)) << kPEFExpSymClassShift ) | ( (UInt32)(nameOffset) ) )
|
|
|
|
enum {
|
|
/* 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. */
|
|
|
|
|
|
|
|
|
|
typedef UInt16 PEFRelocChunk;
|
|
struct PEFLoaderRelocationHeader {
|
|
UInt16 sectionIndex; /* Index of the section to be fixed up.*/
|
|
UInt16 reservedA; /* Reserved, must be zero.*/
|
|
UInt32 relocCount; /* Number of 16 bit relocation chunks.*/
|
|
UInt32 firstRelocOffset; /* Offset of first relocation instruction.*/
|
|
};
|
|
typedef struct PEFLoaderRelocationHeader PEFLoaderRelocationHeader;
|
|
|
|
/* -------------------------------------------------------------------------------------------- */
|
|
/* ! 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 }; */
|
|
|
|
|
|
enum {
|
|
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. */
|
|
|
|
enum {
|
|
kPEFRelocBySectDWithSkip = 0x00, /* Binary: 00x_xxxx*/
|
|
kPEFRelocBySectC = 0x20, /* Binary: 010_0000, group is "RelocRun"*/
|
|
kPEFRelocBySectD = 0x21, /* Binary: 010_0001*/
|
|
kPEFRelocTVector12 = 0x22, /* Binary: 010_0010*/
|
|
kPEFRelocTVector8 = 0x23, /* Binary: 010_0011*/
|
|
kPEFRelocVTable8 = 0x24, /* Binary: 010_0100*/
|
|
kPEFRelocImportRun = 0x25, /* Binary: 010_0101*/
|
|
kPEFRelocSmByImport = 0x30, /* Binary: 011_0000, group is "RelocSmIndex"*/
|
|
kPEFRelocSmSetSectC = 0x31, /* Binary: 011_0001*/
|
|
kPEFRelocSmSetSectD = 0x32, /* Binary: 011_0010*/
|
|
kPEFRelocSmBySection = 0x33, /* Binary: 011_0011*/
|
|
kPEFRelocIncrPosition = 0x40, /* Binary: 100_0xxx*/
|
|
kPEFRelocSmRepeat = 0x48, /* Binary: 100_1xxx*/
|
|
kPEFRelocSetPosition = 0x50, /* Binary: 101_000x*/
|
|
kPEFRelocLgByImport = 0x52, /* Binary: 101_001x*/
|
|
kPEFRelocLgRepeat = 0x58, /* Binary: 101_100x*/
|
|
kPEFRelocLgSetOrBySection = 0x5A, /* Binary: 101_101x*/
|
|
kPEFRelocUndefinedOpcode = 0xFF /* 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. */
|
|
|
|
enum {
|
|
kPEFRelocLgBySectionSubopcode = 0x00, /* Binary: 0000*/
|
|
kPEFRelocLgSetSectCSubopcode = 0x01, /* Binary: 0001*/
|
|
kPEFRelocLgSetSectDSubopcode = 0x02 /* 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! */
|
|
|
|
enum {
|
|
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! */
|
|
|
|
enum {
|
|
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! */
|
|
|
|
enum {
|
|
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! */
|
|
|
|
enum {
|
|
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! */
|
|
|
|
enum {
|
|
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! */
|
|
|
|
enum {
|
|
kPEFRelocSetPosMaxOffset = 0x03FFFFFF /* 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! */
|
|
|
|
enum {
|
|
kPEFRelocLgByImportMaxIndex = 0x03FFFFFF /* 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! */
|
|
|
|
enum {
|
|
kPEFRelocLgRepeatMaxChunkCount = 16,
|
|
kPEFRelocLgRepeatMaxRepeatCount = 0x003FFFFF /* 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! */
|
|
|
|
enum {
|
|
kPEFRelocLgSetOrBySectionMaxIndex = 0x003FFFFF /* 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) )
|
|
|
|
|
|
|
|
#if PRAGMA_STRUCT_ALIGN
|
|
#pragma options align=reset
|
|
#elif PRAGMA_STRUCT_PACKPUSH
|
|
#pragma pack(pop)
|
|
#elif PRAGMA_STRUCT_PACK
|
|
#pragma pack()
|
|
#endif
|
|
|
|
#ifdef PRAGMA_IMPORT_OFF
|
|
#pragma import off
|
|
#elif PRAGMA_IMPORT
|
|
#pragma import reset
|
|
#endif
|
|
|
|
|
|
#endif /* __PEFBINARYFORMAT__ */
|
|
|