CloverBootloader/Include/IndustryStandard/AppleMachoImage.h

2496 lines
97 KiB
C
Raw Normal View History

/** @file
Copyright (c) 2016 - 2018, Download-Fritz. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef APPLE_MACHO_IMAGE_H
#define APPLE_MACHO_IMAGE_H
#define MACH_CPU_ARCH_ABI64 BIT24
#define MACH_CPU_ARCH_ABI64_32 BIT25
//
// Capability bits used in the definition of MACH_CPU_SUBTYPE.
//
#define MACH_CPU_SUBTYPE_MASK 0xFF000000U ///< mask for feature flags
#define MACH_CPU_SUBTYPE_LIB64 BIT17 ///< 64 bit libraries
#define MACH_CPU_SUBTYPE_INTEL_MODEL_SHIFT 4U
#define MACH_CPU_SUBTYPE_INTEL_FAMILY_MAX 0x0FU
#define MACH_CPU_SUBTYPE_INTEL_MODEL_ALL 0U
#define MACH_CPU_SUBTYPE_INTEL(f, Model) \
((f) + ((Model) << MACH_CPU_SUBTYPE_INTEL_MODEL_SHIFT))
#define MACH_CPU_SUBTYPE_INTEL_FAMILY(Identifier) \
((Identifier) & MACH_CPU_SUBTYPE_INTEL_FAMILY_MAX)
#define MACH_CPU_SUBTYPE_INTEL_MODEL(Identifier) \
((Identifier) >> MACH_CPU_SUBTYPE_INTEL_MODEL_SHIFT)
#define FORMALIZE_CPU_SUBTYPE(CpuSubtype) ((CpuSubtype) & ~CPU_SUBTYPE_MASK)
#define MACH_CPU_TYPE_64(CpuType) ((CpuType) | MACH_CPU_ARCH_ABI64)
#define MACH_CPU_TYPE_64_32(CpuType) ((CpuType) | MACH_CPU_ARCH_ABI64_32)
///
/// There is no standard way to detect endianness in EDK2 (yet).
/// Provide MACH_LITTLE_ENDIAN on IA32 and X64 platforms by default,
/// as they are strictly little endian.
///
#if !defined(MACH_LITTLE_ENDIAN) && !defined(MACH_BIG_ENDIAN)
#if defined (MDE_CPU_IA32) || defined(MDE_CPU_X64)
#define MACH_LITTLE_ENDIAN
#endif //< defined (MDE_CPU_IA32) || defined(MDE_CPU_X64)
#endif //< !defined(MACH_LITTLE_ENDIAN) && !defined(MACH_BIG_ENDIAN)
///
/// CPU Type definitions
///
enum {
MachCpuTypeAny = -1,
MachCpuTypeVax = 1,
MachCpuTypeMc680x0 = 6,
MachCpuTypeX86 = 7,
MachCpuTypeI386 = MachCpuTypeX86,
MachCpuTypeX8664 = MACH_CPU_TYPE_64 (MachCpuTypeX86),
MachCpuTypeMc98000 = 10,
MachCpuTypeHppa = 11,
MachCpuTypeArm = 12,
MachCpuTypeArm64 = MACH_CPU_TYPE_64 (MachCpuTypeArm),
MachCpuTypeArm6432 = MACH_CPU_TYPE_64_32 (MachCpuTypeArm),
MachCpuTypeMc88000 = 13,
MachCpuTypeSparc = 14,
MachCpuTypeI860 = 15,
MachCpuTypePowerPc = 18,
MachCpuTypePowerPc64 = MACH_CPU_TYPE_64 (MachCpuTypePowerPc),
MachCpuTypeVeo = 255
};
typedef INT32 MACH_CPU_TYPE;
enum {
MachCpuSubtypeInvalid = -1,
//
// Any
//
MachCpuSubtypeMultiple = -1,
MachCpuSubtypeLittleEndian = 0,
MachCpuSubtypeBigEndian = 1,
//
// VAX Subtypes
//
MachCpuSubtypeVaxAll = 0,
MachCpuSubtypeVax780 = 1,
MachCpuSubtypeVax785 = 2,
MachCpuSubtypeVax750 = 3,
MachCpuSubtypeVax730 = 4,
MachCpuSubtypeUVax1 = 5,
MachCpuSubtypeUVax2 = 6,
MachCpuSubtypeVax8200 = 7,
MachCpuSubtypeVax8500 = 8,
MachCpuSubtypeVax8600 = 9,
MachCpuSubtypeVax8650 = 10,
MachCpuSubtypeVax8800 = 11,
MachCpuSubtypeUVax3 = 12,
//
// MC680 Subtypes
//
MachCpuSubtypeMc680All = 1,
MachCpuSubtypeMc68030 = MachCpuSubtypeMc680All,
MachCpuSubtypeMc68040 = 2,
MachCpuSubtypeMc68030Only = 3,
//
// x86 Subtypes
//
MachCpuSubtypeX86All = MACH_CPU_SUBTYPE_INTEL (3, 0),
MachCpuSubtypeX86Arch1 = MACH_CPU_SUBTYPE_INTEL (4, 0),
//
// x86_64 Subtypes
//
MachCpuSubtypeX8664All = MachCpuSubtypeX86All,
MachCpuSubtypeX8664H = MACH_CPU_SUBTYPE_INTEL (8, 0),
//
// i386 Subytpes
//
MachCpuSubtypeI386All = MachCpuSubtypeX86All,
MachCpuSubtype386 = MachCpuSubtypeI386All,
MachCpuSubtype486 = MachCpuSubtypeX86Arch1,
MachCpuSubtype486Sx = MACH_CPU_SUBTYPE_INTEL (4, 8),
MachCpuSubtype586 = MACH_CPU_SUBTYPE_INTEL (5, 0),
MachCpuSubtypePentium = MachCpuSubtype586,
MachCpuSubtypePentiumPro = MACH_CPU_SUBTYPE_INTEL (6, 1),
MachCpuSubtypePentium3M3 = MACH_CPU_SUBTYPE_INTEL (6, 3),
MachCpuSubtypePentium3M5 = MACH_CPU_SUBTYPE_INTEL (6, 5),
MachCpuSubtypeCeleron = MACH_CPU_SUBTYPE_INTEL (7, 6),
MachCpuSubtypeCeleronMobile = MACH_CPU_SUBTYPE_INTEL (7, 7),
MachCpuSubtypePentium3 = MACH_CPU_SUBTYPE_INTEL (8, 0),
MachCpuSubtypePentium3M = MACH_CPU_SUBTYPE_INTEL (8, 1),
MachCpuSubtypePentium3Xeon = MACH_CPU_SUBTYPE_INTEL (8, 2),
MachCpuSubtypePentiumM = MACH_CPU_SUBTYPE_INTEL (9, 0),
MachCpuSubtypePentium4 = MACH_CPU_SUBTYPE_INTEL (10, 0),
MachCpuSubtypePentium4M = MACH_CPU_SUBTYPE_INTEL (10, 1),
MachCpuSubtypeItanium = MACH_CPU_SUBTYPE_INTEL (11, 0),
MachCpuSubtypeItanium2 = MACH_CPU_SUBTYPE_INTEL (11, 1),
MachCpuSubtypeXeon = MACH_CPU_SUBTYPE_INTEL (12, 0),
MachCpuSubtypeXeonMp = MACH_CPU_SUBTYPE_INTEL (12, 1),
//
// Mips subtypes
//
MachCpuSubtypeMipsAll = 0,
MachCpuSubtypeMipsR2300 = 1,
MachCpuSubtypeMipsR2600 = 2,
MachCpuSubtypeMipsR2800 = 3,
MachCpuSubtypeMipsR2000a = 4,
MachCpuSubtypeMipsR2000 = 5,
MachCpuSubtypeMipsR3000a = 6,
MachCpuSubtypeMipsR3000 = 7,
//
// MC98000 Subtypes
//
MachCpuSubtypeMc98000All = 0,
MachCpuSubtypeMc98601 = 1,
//
// HPPA Subtypes
//
MachCpuSubtypeHppaAll = 0,
MachCpuSubtypeHppa7100 = MachCpuSubtypeHppaAll,
MachCpuSubtypeHppa7100Lc = 1,
//
// ARM Subtypes
//
MachCpuSubtypeArmAll = 0,
MachCpuSubtypeArmV4T = 5,
MachCpuSubtypeArmV6 = 6,
MachCpuSubtypeArmV5Tej = 7,
MachCpuSubtypeArmXscale = 8,
MachCpuSubtypeArmV7 = 9,
MachCpuSubtypeArmV7F = 10,
MachCpuSubtypeArmV7S = 11,
MachCpuSubtypeArmV7K = 12,
MachCpuSubtypeArmV8 = 13,
MachCpuSubtypeArmV6M = 14,
MachCpuSubtypeArmV7M = 15,
MachCpuSubtypeArmV7Em = 16,
//
// ARM64 Subytypes
//
MachCpuSubtypeArm64All = 0,
MachCpuSubtypeArm64V8 = 1,
//
// ARM64_32 Subtypes
//
MachCpuSubtypeArm6432All = 0,
MachCpuSubtypeArm6432V8 = 1,
//
// MC88000 Subytpes
//
MachCpuSubtypeMc88000All = 0,
MachCpuSubtypeMc88100 = 1,
MachCpuSubtypeMc88110 = 2,
//
// SPARC Subtypes
//
MachCpuSubtypeSparcAll = 0,
//
// i860 Subtypes
//
MachCpuSubtypeI860All = 0,
MachCpuSubtypeI860860 = 1,
//
// PowerPC Subtypes
//
MachCpuSubtypePowerPcAll = 0,
MachCpuSubtypePowerPc601 = 1,
MachCpuSubtypePowerPc602 = 2,
MachCpuSubtypePowerPc603 = 3,
MachCpuSubtypePowerPc603e = 4,
MachCpuSubtypePowerPc603ev = 5,
MachCpuSubtypePowerPc604 = 6,
MachCpuSubtypePowerPc604e = 7,
MachCpuSubtypePowerPc620 = 8,
MachCpuSubtypePowerPc750 = 9,
MachCpuSubtypePowerPc7400 = 10,
MachCpuSubtypePowerPc7450 = 11,
MachCpuSubtypePowerPc970 = 100,
//
// VEO Subtypes
//
MachCpuSubtypeVeo1 = 1,
MachCpuSubtypeVeo2 = 2,
MachCpuSubtypeVeo3 = 3,
MachCpuSubtypeVeo4 = 4,
MachCpuSubtypeVeoAll = MachCpuSubtypeVeo2
};
typedef INT32 MACH_CPU_SUBTYPE;
///
/// CPU Family definitions
///
enum {
MachCpuFamilyUnknown = 0,
//
// PowerPC Family
//
MachCpuFamilyPowerPcG3 = 0xCEE41549,
MachCpuFamilyPowerPcG4 = 0x77C184AE,
MachCpuFamilyPowerPcG5 = 0xED76D8AA,
//
// Intel Family
//
MachCpuFamilyIntel613 = 0xAA33392B,
MachCpuFamilyIntelYonah = 0x73D67300,
MachCpuFamilyIntelMerom = 0x426F69EF,
MachCpuFamilyIntelPenryn = 0x78EA4FBC,
MachCpuFamilyIntelNehalem = 0x6B5A4CD2,
MachCpuFamilyIntelWestmere = 0x573B5EEC,
MachCpuFamilyIntelSandyBridge = 0x5490B78C,
MachCpuFamilyIntelIvyBridge = 0x1F65E835,
MachCpuFamilyIntelHaswell = 0x10B282DC,
MachCpuFamilyIntelBroadwell = 0x582ED09C,
MachCpuFamilyIntelSkylake = 0x37FC219F,
MachCpuFamilyIntelKabyLake = 0x0F817246,
MachCpuFamilyIntelCoffeeLake = MachCpuFamilyIntelKabyLake,
//
// The following synonyms are deprecated:
//
MachCpuFamilyIntel614 = MachCpuFamilyIntelYonah,
MachCpuFamilyIntel615 = MachCpuFamilyIntelMerom,
MachCpuFamilyIntel623 = MachCpuFamilyIntelPenryn,
MachCpuFamilyIntel626 = MachCpuFamilyIntelNehalem,
MachCpuFamilyIntelCore = MachCpuFamilyIntelYonah,
MachCpuFamilyIntelCore2 = MachCpuFamilyIntelMerom,
//
// ARM Family
//
MachCpuFamilyArm9 = 0xE73283AE,
MachCpuFamilyArm11 = 0x8FF620D8,
MachCpuFamilyArmXscale = 0x53B005F5,
MachCpuFamilyArm12 = 0xBD1B0AE9,
MachCpuFamilyArm13 = 0x0CC90E64,
MachCpuFamilyArm14 = 0x96077EF1,
MachCpuFamilyArm15 = 0xA8511BCA,
MachCpuFamilyArmSwift = 0x1E2D6381,
MachCpuFamilyArmCyclone = 0x37A09642,
MachCpuFamilyArmTyphoon = 0x2C91A47E,
MachCpuFamilyArmTwister = 0x92FB37C8,
MachCpuFamilyArmHurricane = 0x67CEEE93,
MachCpuFamilyArmMonsoonMistral = 0xE81E7EF6,
};
typedef UINT32 MACH_CPU_FAMILY;
typedef INT32 MACH_CPU_THREADTYPE;
typedef INT32 MACH_VM_PROTECTION;
///
/// A variable length string in a load command is represented by an lc_str
/// union. The strings are stored just after the load command structure and
/// the offset is from the start of the load command structure. The size of
/// the string is reflected in the cmdsize field of the load command. Once
/// again any padded bytes to bring the cmdsize field to a multiple of 4 bytes
/// must be zero.
///
typedef union {
UINT32 Offset; ///< offset to the string
UINT32 Address32; ///< pointer to the string
} MACH_LOAD_COMMAND_STRING;
///
/// Fixed virtual memory shared libraries are identified by two things. The
/// target pathname (the name of the library as found for execution), and the
/// minor version number. The address of where the headers are loaded is in
/// header_addr. (THIS IS OBSOLETE and no longer supported).
///
typedef struct {
MACH_LOAD_COMMAND_STRING Name; ///< library's target pathname
UINT32 MinorVersion; ///< library's minor version number
UINT32 HeaderAddress; ///< library's header address
} MACH_FIXED_VM_LIB;
///
/// Dynamicly linked shared libraries are identified by two things. The
/// pathname (the name of the library as found for execution), and the
/// compatibility version number. The pathname must match and the
/// compatibility number in the user of the library must be greater than or
/// equal to the library being used. The time stamp is used to record the time
/// a library was built and copied into user so it can be use to determined if
/// the library used at runtime is exactly the same as used to built the
/// program.
///
typedef struct {
///
/// library's path name
///
MACH_LOAD_COMMAND_STRING Name;
///
/// library's build time stamp
///
UINT32 Timestamp;
///
/// library's current version number
///
UINT32 CurrentVersion;
///
/// library's compatibility vers number
///
UINT32 CompatibilityVersion;
} MACH_DYLIB;
//
// Mach Load Commands
//
///
/// After MacOS X 10.1 when a new load command is added that is required to be
/// understood by the dynamic linker for the image to execute properly the
/// MACH_LC_REQUIRE_DYLD bit will be or 'ed into the load
/// command constant. If the dynamic linker sees such a load command it it
/// does not understand will issue a "unknown load command required for
/// execution" error and refuse to use the image. Other load commands without
/// this bit that are not understood will simply be ignored.
///
#define MACH_LC_REQUIRE_DYLD BIT31
///
/// segment of this file to be mapped
///
#define MACH_LOAD_COMMAND_SEGMENT 1U
///
/// link-edit stab symbol table info
///
#define MACH_LOAD_COMMAND_SYMTAB 2U
///
/// link-edit gdb symbol table info (obsolete)
///
#define MACH_LOAD_COMMAND_SYMSEG 3U
///
/// thread
///
#define MACH_LOAD_COMMAND_THREAD 4U
///
/// unix thread (includes a stack)
///
#define MACH_LOAD_COMMAND_UNIX_THREAD 5U
///
/// load a specified fixed VM shared library
///
#define MACH_LOAD_COMMAND_LOAD_FIXED_VM_LIB 6U
///
/// fixed VM shared library identification
///
#define MACH_LOAD_COMMAND_IDENTIFICATION_VM_LIB 7U
///
/// object identification info (obsolete)
///
#define MACH_LOAD_COMMAND_IDENTIFICATION 8U
///
/// fixed VM file inclusion (internal use)
///
#define MACH_LOAD_COMMAND_FIXED_VM_FILE 9U
///
/// prepage command (internal use)
///
#define MACH_LOAD_COMMAND_PRE_PAGE 10U
///
/// dynamic link-edit symbol table info
///
#define MACH_LOAD_COMMAND_DYSYMTAB 11U
///
/// load a dynamically linked shared library
///
#define MACH_LOAD_COMMAND_LOAD_DYLIB 12U
///
/// dynamically linked shared lib ident
///
#define MACH_LOAD_COMMAND_IDENTITY_DYLIB 13U
///
/// load a dynamic linker
///
#define MACH_LOAD_COMMAND_LOAD_DYLD 14U
///
/// dynamic linker identification
///
#define MACH_LOAD_COMMAND_IDENTIFICATION_DYLD 15U
///
/// modules prebound for a dynamically
///
#define MACH_LOAD_COMMAND_PREBOUNT_SYLIB 16U
///
/// image routines
///
#define MACH_LOAD_COMMAND_ROUTINES 17U
///
/// sub framework
///
#define MACH_LOAD_COMMAND_SUB_FRAMEWORK 18U
///
/// sub umbrella
///
#define MACH_LOAD_COMMAND_SUB_UMBRELLA 19U
///
/// sub clien
///
#define MACH_LOAD_COMMAND_SUB_CLIENT 20U
///
/// sub library
///
#define MACH_LOAD_COMMAND_SUB_LIBRARY 21U
///
/// two-level namespace lookup hints
///
#define MACH_LOAD_COMMAND_TWO_LEVEL_HINTS 22U
///
/// prebind checksum
///
#define MACH_LOAD_COMMAND_PREBIND_CHECKSUM 23U
///
/// load a dynamically linked shared library that is allowed to be missing
/// (all symbols are weak imported).
///
#define MACH_LOAD_COMMAND_LLOAD_WEAK_DYLIB (24U | MACH_LC_REQUIRE_DYLD)
///
/// 64-bit segment of this file to be mapped
///
#define MACH_LOAD_COMMAND_SEGMENT_64 25U
///
/// 64-bit image routines
///
#define MACH_LOAD_COMMAND_ROUTINES_64 26U
///
/// the uuid
///
#define MACH_LOAD_COMMAND_UUID 27U
///
/// runpath additions
///
#define MACH_LOAD_COMMAND_RUN_PATH (28U | MACH_LC_REQUIRE_DYLD)
///
/// local of code signature
///
#define MACH_LOAD_COMMAND_CODE_SIGNATURE 29U
///
/// local of info to split segments
///
#define MACH_LOAD_COMMAND_SEGMENT_SPLIT_INFO 30U
///
/// load and re-export dylib
///
#define MACH_LOAD_COMMAND_REEXPORT_DYLIB (31U | MACH_LC_REQUIRE_DYLD)
///
/// delay load of dylib until first use
///
#define MACH_LOAD_COMMAND_LAZY_LOAD_DYLIB 32U
///
/// encrypted segment information
///
#define MACH_LOAD_COMMAND_ENCRYPTION_INFO 33U
///
/// compressed dyld information
///
#define MACH_LOAD_COMMAND_DYLD_INFO 34U
///
/// compressed dyld information only
///
#define MACH_LOAD_COMMAND_DYLD_INFO_ONLY (34U | MACH_LC_REQUIRE_DYLD)
///
/// load upward dylib
///
#define MACH_LOAD_COMMAND_LOAD_UPWARD_DYLIB (35U | MACH_LC_REQUIRE_DYLD)
///
/// build for MacOSX min OS version
///
#define MACH_LOAD_COMMAND_VERSION_MIN_MAC_OS_X 36U
///
/// build for iPhoneOS min OS version
///
#define MACH_LOAD_COMMAND_VERSION_MIN_IPHONE_OS 37U
///
/// compressed table of function start addresses
///
#define MACH_LOAD_COMMAND_FUNCTION_STARTS 38U
///
/// string for dyld to treat like environment variable
///
#define MACH_LOAD_COMMAND_DYLD_ENVIRONMENT 39U
///
/// replacement for MachLoadCommandUnixThread
///
#define MACH_LOAD_COMMAND_MAIN (40U | MACH_LC_REQUIRE_DYLD)
///
/// table of non-in structions in __text
///
#define MACH_LOAD_COMMAND_DATA_IN_CODE 41U
///
/// source version used to build binary
///
#define MACH_LOAD_COMMAND_SOURCE_VERSION 42U
///
/// Code signing DRs copied from linked dylibs
///
#define MACH_LOAD_COMMAND_DYLIB_CODE_SIGN_DRS 43U
///
/// 64-bit encrypted segment information
///
#define MACH_LOAD_COMMAND_ENCRYPTION_INFO_64 44U
///
/// linker options in MH_OBJECT files
///
#define MACH_LOAD_COMMAND_LINKER_OPTION 45U
///
/// optimization hints in MH_OBJECT files
///
#define MACH_LOAD_COMMAND_LINKER_OPTIMIZATION_HINT 46U
///
/// build for AppleTV min OS version
///
#define MACH_LOAD_COMMAND_VERSION_MIN_TV_OS 47U
///
/// build for Watch min OS version
///
#define MACH_LOAD_COMMAND_VERSION_MIN_WATCH_OS 48U
///
/// arbitrary data included within a Mach-O file
///
#define MACH_LOAD_COMMAND_NOTE 49U
///
/// build for platform min OS version
///
#define MACH_LOAD_COMMAND_BUILD_VERSION 50U
///
/// used with linkedit_data_command, payload is trie
///
#define MACH_LOAD_COMMAND_DYLD_EXPORTS_TRIE (51U | MACH_LC_REQUIRE_DYLD)
///
/// used with linkedit_data_command
///
#define MACH_LOAD_COMMAND_DYLD_CHAINED_FIXUPS (52U | MACH_LC_REQUIRE_DYLD)
///
/// used with fileset_entry_command
///
#define MACH_LOAD_COMMAND_FILESET_ENTRY (53U | MACH_LC_REQUIRE_DYLD)
typedef UINT32 MACH_LOAD_COMMAND_TYPE;
#define MACH_LOAD_COMMAND_HDR_ \
MACH_LOAD_COMMAND_TYPE CommandType; /* type of load command */ \
UINT32 CommandSize; /* total size of command in bytes
(includes sizeof section structs) */
#define NEXT_MACH_LOAD_COMMAND(Command) \
((MACH_LOAD_COMMAND *)((UINTN)(Command) + (Command)->CommandSize))
typedef struct {
MACH_LOAD_COMMAND_HDR_
} MACH_LOAD_COMMAND;
//
// Constants for the Flags field of the MACH_SEGMENT_COMMAND struct
//
///
/// the file contents for this segment is for the high part of the VM space,
/// the low part is zero filled (for stacks in core files)
///
#define MACH_SEGMENT_FLAG_HIGH_VIRTUAL_MEMORY BIT0
///
/// this segment is the VM that is allocated by a fixed VM library, for overlap
/// checking in the link editor
///
#define MACH_SEGMENT_FLAG_FIXED_VM_LIB BIT1
///
/// this segment has nothing that was relocated in it and nothing relocated to
/// it, that is it maybe safely replaced without relocation
///
#define MACH_SEGMENT_FLAG_NO_RELOCATION BIT2
///
/// This segment is protected. If the segment starts at file offset 0, the
/// first page of the segment is not protected. All other pages of the
/// segment are protected.
///
#define MACH_SEGMENT_FLAG_PROTECTED_VERSION_1 BIT3
#define MACH_SEGMENT_VM_PROT_NONE 0U
#define MACH_SEGMENT_VM_PROT_READ BIT0
#define MACH_SEGMENT_VM_PROT_WRITE BIT1
#define MACH_SEGMENT_VM_PROT_EXECUTE BIT2
typedef UINT32 MACH_SEGMENT_FLAGS;
///
/// Constants for the type of a section
///
enum {
///
/// regular section
///
MachSectionTypeRegular = 0,
///
/// zero fill on demand section
///
MachSectionTypeZeroFill = 1,
///
/// section with only literal C strings
///
MachSectionTypeCStringLiterals = 2,
///
/// section with only 4 byte literals
///
MachSectionType4ByteLiterals = 3,
///
/// section with only 8 byte literals
///
MachSectionType8ByteLiterals = 4,
///
/// section with only pointers to literals
///
MachSectionTypeLiteralPointers = 5,
//
// For the two types of symbol pointers sections and the symbol stubs section
// they have indirect symbol table entries. For each of the entries in the
// section the indirect symbol table entries, in corresponding order in the
// indirect symbol table, start at the index stored in the reserved1 field
// of the section structure. Since the indirect symbol table entries
// correspond to the entries in the section the number of indirect symbol
// table entries is inferred from the size of the section divided by the size
// of the entries in the section. For symbol pointers sections the size of
// the entries in the section is 4 bytes and for symbol stubs sections the
// byte size of the stubs is stored in the reserved2 field of the section
// structure.
//
///
/// section with only non-lazy symbol pointers
///
MachSectionTypeNonLazySymbolPointers = 6,
///
/// section with only lazy symbol pointers
///
MachSectionTypeLazySymbolPointers = 7,
///
/// section with only symbol stubs, byte size of stub in the reserved2 field
///
MachSectionTypeSymbolStubs = 8,
///
/// section with only function pointers for initialization
///
MachSectionTypeModInitalizeFunctionPointers = 9,
///
/// section with only function pointers for termination
///
MachSectionTypeModTerminateFunctionPointers = 10,
///
/// section contains symbols that are to be coalesced
///
MachSectionTypeCoalesced = 11,
///
/// zero fill on demand section (that can be larger than 4 gigabytes)
///
MachSectionTypeGigabyteZeroFill = 12,
///
/// section with only pairs of function pointers for interposing
///
MachSectionTypeInterposing = 13,
///
/// section with only 16 byte literals
///
MachSectionType16ByteLiterals = 14,
///
/// section contains DTrace Object Format
///
MachSectionTypeDtraceObjectFormat = 15,
///
/// section with only lazy symbol pointers to lazy loaded dylibs
///
MachSectionTypeLazyDylibSymbolPointers = 16,
//
// Section types to support thread local variables
//
///
/// template of initial values for TLVs
///
MachSectionTypeThreadLocalRegular = 17,
///
/// template of initial values for TLVs
///
MachSectionTypeThreadLocalZeroFill = 18,
///
/// TLV descriptors
///
MachSectionTypeThreadLocalVariables = 19,
///
/// pointers to TLV descriptors
///
MachSectionTypeThreadVariablePointers = 20,
///
/// functions to call to initialize TLV values
///
MachSectionTypeThreadLocalInitializeFunctionPointers = 21,
///
/// 32-bit offsets to initializers
///
MachSectionTypeThreadLocalInitializeFunctionOffsets = 22
};
//
// Constants for the section attributes part of the Flags field of a section
// structure.
//
///
/// system setable attributes
///
#define MACH_SECTION_ATTRIBUTES_SYSYTEM 0x00FFFF00U
///
/// User setable attributes
///
#define MACH_SECTION_ATTRIBUTES_USER 0xFF000000U
///
/// section has local relocation entries
///
#define MACH_SECTION_ATTRIBUTE_LOCAL_RELOCATION BIT8
///
/// section has external relocation entries
///
#define MACH_SECTION_ATTRIBUTE_EXTERNAL_RELOCATION BIT9
///
/// section contains some machine instructions
///
#define MACH_SECTION_ATTRIBUTE_SOME_INSTRUCTIONS BIT10
//
// The flags field of a section structure is separated into two parts a section
// type and section attributes.The section types are mutually exclusive (it
// can only have one type) but the section attributes are not (it may have more
// than one attribute).
//
#define MACH_SECTION_TYPE_MASK 0x000000FFU ///< 256 section types
#define MACH_SECTION_ATTRIBUTES_MASK 0xFFFFFF00U ///< 24 section attributes
///
/// If a segment contains any sections marked with
/// MACH_SECTION_ATTRIBUTE_DEBUG then all sections in that segment must have
/// this attribute. No section other than a section marked with this attribute
/// may reference the contents of this section. A section with this attribute
/// may contain no symbols and must have a section type S_REGULAR. The static
/// linker will not copy section contents from sections with this attribute
/// into its output file. These sections generally contain DWARF debugging
/// info.
///
#define MACH_SECTION_ATTRIBUTE_DEBUG BIT25
///
/// Used with i386 code stubs written on by dyld
///
#define MACH_SECTION_ATTRIBUTE_SELF_MODIFYING_CODE BIT26
///
/// blocks are live if they reference live blocks
///
#define MACH_SECTION_ATTRIBUTE_LIVE_SUPPORT BIT27
///
/// no dead stripping
///
#define MACH_SECTION_ATTRIBUTE_NO_DEAD_STRIP BIT28
///
/// ok to strip static symbols in this section in files with the
/// MACH_HEADER_FLAG_DYNAMIC_LINKER_LINK flag
///
#define MACH_SECTION_ATTRIBUTE_STRIP_STATIC_SYMBOLS BIT29
///
/// section contains coalesced symbols that are not to be in a ranlib table of
/// contents
///
#define MACH_SECTION_ATTRIBUTE_NO_TOC BIT30
///
/// section contains only true machine instructions
///
#define MACH_SECTION_ATTRIBUTE_PURE_INSTRUCTIONS BIT31
///
/// A segment is made up of zero or more sections.
/// Non-MachHeaderFileTypeObject files have all of their segments with the
/// proper sections in each, and padded to the Sectionecified segment alignment
/// when produced by the link editor. The first segment of a
/// MachHeaderFileTypeExecute and MachHeaderFileTypeFixedVmLib format file
/// contains the MACH_HEADER and load commands of the object file before its
/// first section. The zero fill sections are always last in their segment (in
/// all formats). This allows the zeroed segment padding to be mapped into
/// memory where zero fill sections might be. The gigabyte zero fill sections,
/// those with the section type MachSectionTypeGigabyteZeroFill, can only be
/// in a segment with sections of this type. These segments are then placed
/// after all other segments.
///
/// The MachHeaderFileTypeObject format has all of its sections in one segment
/// for compactness. There is no padding to a Sectionecified segment boundary
/// and the MACH_HEADER and load commands are not part of the segment.
///
/// Sections with the same section Name, SectionName, going into the same
/// segment, SegmentName, are combined by the link editor. The resulting
/// section is aligned to the maximum alignment of the combined sections and is
/// the new section's alignment. The combined sections are aligned to their
/// original alignment in the combined section. Any padded bytes to get the
/// Sectionecified alignment are zeroed.
///
/// The format of the relocation entries referenced by the reloff and nreloc
/// fields of the section structure for mach object files is described in the
/// header file <reloc.h>.
///
/// for 32-bit architectures
///
typedef struct {
CHAR8 SectionName[16]; ///< Name of this section
CHAR8 SegmentName[16]; ///< segment this section goes in
UINT32 Address; ///< memory address of this section
UINT32 Size; ///< size in bytes of this section
UINT32 Offset; ///< file offset of this section
UINT32 Alignment; ///< section alignment (power of 2)
UINT32 RelocationEntriesOffset; ///< file offset of relocation entries
UINT32 NumRelocationEntries; ///< number of relocation entries
UINT32 Flags; ///< flags (section type and attributes)
UINT32 Reserved1; ///< reserved (for offset or index)
UINT32 Reserved2; ///< reserved (for count or sizeof)
} MACH_SECTION;
///
/// for 64-bit architectures
///
typedef struct {
CHAR8 SectionName[16]; ///< Name of this section
CHAR8 SegmentName[16]; ///< segment this section goes in
UINT64 Address; ///< memory address of this section
UINT64 Size; ///< size in bytes of this section
UINT32 Offset; ///< file offset of this section
UINT32 Alignment; ///< section alignment (power of 2)
UINT32 RelocationsOffset; ///< file offset of relocation entries
UINT32 NumRelocations; ///< number of relocation entries
UINT32 Flags; ///< flags (section type and attributes)
UINT32 Reserved1; ///< reserved (for offset or index)
UINT32 Reserved2; ///< reserved (for count or sizeof)
UINT32 Reserved3; ///< reserved
} MACH_SECTION_64;
#define NEXT_MACH_SEGMENT(Segment) \
(MACH_SEGMENT_COMMAND *)((UINTN)(Segment) + (Segment)->Command.Size)
///
/// The segment load command indicates that a part of this file is to be
/// mapped into the task's address Sectionace. The size of this segment in
/// memory, vmsize, maybe equal to or larger than the amount to map from this
/// file, filesize. The file is mapped starting at fileoff to the beginning of
/// the segment in memory, vmaddr. The rest of the memory of the segment,
/// if any, is allocated zero fill on demand. The segment's maximum virtual
/// memory protection and initial virtual memory protection are Sectionecified
/// by the maxprot and initprot fields. If the segment has sections then the
/// section structures directly follow the segment command and their size is
/// reflected in cmdsize.
///
/// for 32 - bit architectures
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
CHAR8 SegmentName[16]; ///< segment Name
UINT32 VirtualAddress; ///< memory address of this segment
UINT32 Size; ///< memory size of this segment
UINT32 FileOffset; ///< file offset of this segment
UINT32 FileSize; ///< amount to map from the file
MACH_VM_PROTECTION MaximumProtection; ///< maximum VM protection
MACH_VM_PROTECTION InitialProtection; ///< initial VM protection
UINT32 NumSections; ///< number of sections in segment
MACH_SEGMENT_FLAGS Flags; ///< flags
MACH_SECTION Sections[];
} MACH_SEGMENT_COMMAND;
#define NEXT_MACH_SEGMENT_64(Segment) \
(MACH_SEGMENT_COMMAND_64 *)((UINTN)(Segment) + (Segment)->Hdr.Size)
///
/// The 64-bit segment load command indicates that a part of this file is to be
/// mapped into a 64-bit task's address Sectionace. If the 64-bit segment has
/// sections then section_64 structures directly follow the 64-bit segment
/// command and their size is reflected in cmdsize.
///
/// for 64-bit architectures
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
CHAR8 SegmentName[16]; ///< segment Name
UINT64 VirtualAddress; ///< memory address of this segment
UINT64 Size; ///< memory size of this segment
UINT64 FileOffset; ///< file offset of this segment
UINT64 FileSize; ///< amount to map from the file
MACH_VM_PROTECTION MaximumProtection; ///< maximum VM protection
MACH_VM_PROTECTION InitialProtection; ///< initial VM protection
UINT32 NumSections; ///< number of sections in segment
MACH_SEGMENT_FLAGS Flags; ///< flags
MACH_SECTION_64 Sections[];
} MACH_SEGMENT_COMMAND_64;
///
/// A fixed virtual shared library (filetype == MH_FVMLIB in the mach header)
/// contains a fvmlib_command (cmd == LC_IDFVMLIB) to identify the library.
/// An object that uses a fixed virtual shared library also contains a
/// fvmlib_command (cmd == LC_LOADFVMLIB) for each library it uses.
/// (THIS IS OBSOLETE and no longer supported).
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_FIXED_VM_LIB FixedVmLib; ///< the library identification
} MACH_FIXED_VM_LIB_COMMAND;
///
/// A dynamically linked shared library (filetype == MH_DYLIB in the mach
/// header) contains a dylib_command (cmd == LC_ID_DYLIB) to identify the
/// library. An object that uses a dynamically linked shared library also
/// contains a dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or
/// LC_REEXPORT_DYLIB) for each library it uses.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_DYLIB Dylib; ///< the library identification
} MACH_DYLIB_COMMAND;
///
/// A dynamically linked shared library may be a subframework of an umbrella
/// framework. If so it will be linked with "-umbrella umbrella_name" where
/// Where "umbrella_name" is the name of the umbrella framework. A subframework
/// can only be linked against by its umbrella framework or other subframeworks
/// that are part of the same umbrella framework. Otherwise the static link
/// editor produces an error and states to link against the umbrella framework.
/// The name of the umbrella framework for subframeworks is recorded in the
/// following structure.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_LOAD_COMMAND_STRING Umbrella; ///< the umbrella framework name
} MACH_SUB_FRAMEWORK_COMMAND;
///
/// For dynamically linked shared libraries that are subframework of an
/// umbrella framework they can allow clients other than the umbrella
/// framework or other subframeworks in the same umbrella framework. To do
/// this the subframework is built with "-allowable_client client_name" and an
/// LC_SUB_CLIENT load command is created for each -allowable_client flag.
/// The client_name is usually a framework name. It can also be a name used
/// for bundles clients where the bundle is built with
/// "-client_name client_name".
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_LOAD_COMMAND_STRING Client; ///< the client name
} MACH_SUB_CLIENT_COMMAND;
///
/// A dynamically linked shared library may be a sub_umbrella of an umbrella
/// framework. If so it will be linked with "-sub_umbrella umbrella_name"
/// where "umbrella_name" is the name of the sub_umbrella framework. When
/// staticly linking when -twolevel_namespace is in effect a twolevel namespace
/// umbrella framework will only cause its subframeworks and those frameworks
/// listed as sub_umbrella frameworks to be implicited linked in. Any other
/// dependent dynamic libraries will not be linked it when -twolevel_namespace
/// is in effect. The primary library recorded by the static linker when
/// resolving a symbol in these libraries will be the umbrella framework.
/// Zero or more sub_umbrella frameworks may be use by an umbrella framework.
/// The name of a sub_umbrella framework is recorded in the following structure.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_LOAD_COMMAND_STRING SubUmbrella; ///< the sub_umbrella framework name
} MACH_SUB_UMBRELLA_COMMAND;
///
/// A dynamically linked shared library may be a sub_library of another shared
/// library. If so it will be linked with "-sub_library library_name" where
/// Where "library_name" is the name of the sub_library shared library. When
/// staticly linking when -twolevel_namespace is in effect a twolevel namespace
/// shared library will only cause its subframeworks and those frameworks
/// listed as sub_umbrella frameworks and libraries listed as sub_libraries to
/// be implicited linked in. Any other dependent dynamic libraries will not be
/// linked it when -twolevel_namespace is in effect. The primary library
/// recorded by the static linker when resolving a symbol in these libraries
/// will be the umbrella framework (or dynamic library). Zero or more
/// sub_library shared libraries may be use by an umbrella framework or (or
/// dynamic library). The name of a sub_library framework is recorded in the
/// following structure. For example /usr/lib/libobjc_profile.A.dylib would be
/// recorded as "libobjc".
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_LOAD_COMMAND_STRING SubLibrary; ///< the sub_library name
} MACH_SUB_LIBRARY_COMMAND;
///
/// A program (filetype == MH_EXECUTE) that is
/// prebound to its dynamic libraries has one of these for each library that
/// the static linker used in prebinding. It contains a bit vector for the
/// modules in the library. The bits indicate which modules are bound (1) and
/// which are not (0) from the library. The bit for module 0 is the low bit
/// of the first byte. So the bit for the Nth module is:
/// (linked_modules[N/8] >> N%8) & 1
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_LOAD_COMMAND_STRING Name; ///< library's path name
UINT32 NumModules; ///< number of modules in library
MACH_LOAD_COMMAND_STRING LinkedModules[]; ///< bit vector of linked modules
} MACH_PREBOUND_DYLIB_COMMAND;
///
/// A program that uses a dynamic linker contains a dylinker_command to
/// identify the name of the dynamic linker (LC_LOAD_DYLINKER). And a dynamic
/// linker contains a dylinker_command to identify the dynamic linker
/// (LC_ID_DYLINKER). A file can have at most one of these.
/// This struct is also used for the LC_DYLD_ENVIRONMENT load command and
/// contains string for dyld to treat like environment variable.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_LOAD_COMMAND_STRING Name; ///< dynamic linker's path name
} MACH_DYLINKER_COMMAND;
enum {
MachX86ThreadState32 = 1,
MachX86FloatState32 = 2,
MachX86ExceptionState32 = 3,
MachX86ThreadState64 = 4,
MachX86FloatState64 = 5,
MachX86ExceptionState64 = 6,
MachX86ThreadState = 7,
MachX86FloatState = 8,
MachX86ExceptionState = 9,
MachX86DebugState32 = 10,
MachX86DebugState64 = 11,
MachX86DebugState = 12,
MachThreadStateNone = 13,
//
// 14 and 15 are used for the internal x86SavedState flavours.
//
MachX86AvxState32 = 16,
MachX86AvxState64 = 17,
MachX86AvxState = 18,
MachX86Avx512State32 = 19,
MachX86Avx512State64 = 20,
MachX86Avx512State = 21,
};
///
/// Size of maximum exported thread state in words
///
#define MACH_X86_THREAD_STATE_MAX 614
typedef struct {
UINT32 eax;
UINT32 ebx;
UINT32 ecx;
UINT32 edx;
UINT32 edi;
UINT32 esi;
UINT32 ebp;
UINT32 esp;
UINT32 ss;
UINT32 eflags;
UINT32 eip;
UINT32 cs;
UINT32 ds;
UINT32 es;
UINT32 fs;
UINT32 gs;
} MACH_X86_THREAD_STATE32;
typedef struct {
UINT64 rax;
UINT64 rbx;
UINT64 rcx;
UINT64 rdx;
UINT64 rdi;
UINT64 rsi;
UINT64 rbp;
UINT64 rsp;
UINT64 r8;
UINT64 r9;
UINT64 r10;
UINT64 r11;
UINT64 r12;
UINT64 r13;
UINT64 r14;
UINT64 r15;
UINT64 rip;
UINT64 rflags;
UINT64 cs;
UINT64 fs;
UINT64 gs;
} MACH_X86_THREAD_STATE64;
typedef union {
MACH_X86_THREAD_STATE32 State32;
MACH_X86_THREAD_STATE64 State64;
} MACH_X86_THREAD_STATE;
///
/// MACH_VALID_THREAD_STATE_FLAVOR is a platform specific macro that when
/// passed an exception flavor will return if that is a defined flavor for that
/// platform. The macro must be manually updated to include all of the valid
/// exception flavors as defined above.
///
#define MACH_VALID_THREAD_STATE_FLAVOR(Flavor) \
(((Flavor) == MachX86ThreadState32) \
|| ((Flavor) == MachX86FloatState32) \
|| ((Flavor) == MachX86ExceptionState32) \
|| ((Flavor) == MachX86DebugState32) \
|| ((Flavor) == MachX86ThreadState64) \
|| ((Flavor) == MachX86FloatState64) \
|| ((Flavor) == MachX86ExceptionState64) \
|| ((Flavor) == MachX86DebugState64) \
|| ((Flavor) == MachX86ThreadState) \
|| ((Flavor) == MachX86FloatState) \
|| ((Flavor) == MachX86ExceptionState) \
|| ((Flavor) == MachX86DebugState) \
|| ((Flavor) == MachX86AvxState32) \
|| ((Flavor) == MachX86AvxState64) \
|| ((Flavor) == MachX86AvxState) \
|| ((Flavor) == MachX86Avx512State32) \
|| ((Flavor) == MachX86Avx512State64) \
|| ((Flavor) == MachX86Avx512State) \
|| ((Flavor) == MachThreadStateNone))
///
/// Thread commands contain machine-specific data structures suitable for
/// use in the thread state primitives. The machine specific data structures
/// follow the struct thread_command as follows.
/// Each flavor of machine specific data structure is preceded by an unsigned
/// long constant for the flavor of that data structure, an UINT32
/// that is the count of longs of the size of the state data structure and
/// then the state data structure follows. This triple may be repeated for
/// many flavors. The constants for the flavors, counts and state data
/// structure definitions are expected to be in the header file
/// <machine/thread_status.h>.
/// These machine specific data structures sizes must be multiples of
/// 4 bytes The cmdsize reflects the total size of the thread_command
/// and all of the sizes of the constants for the flavors, counts and state
/// data structures.
///
/// For executable objects that are unix processes there will be one
/// thread_command (cmd == LC_UNIXTHREAD) created for it by the link-editor.
/// This is the same as a LC_THREAD, except that a stack is automatically
/// created (based on the shell's limit for the stack size). Command arguments
/// and environment variables are copied onto that stack.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 Flavor; ///< flavor of thread state
UINT32 NumThreadStates; ///< count of UINT32s in thread state
UINT32 ThreadState[];
} MACH_THREAD_COMMAND;
///
/// The routines command contains the address of the dynamic shared library
/// initialization routine and an index into the module table for the module
/// that defines the routine. Before any modules are used from the library the
/// dynamic linker fully binds the module that defines the initialization routine
/// and then calls it. This gets called before any module initialization
/// routines (used for C++ static constructors) in the library.
/// For 32-bit architectures.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
///
/// address of initialization routine
///
UINT32 InitRoutineAddress;
///
/// index into the module table that the init routine is defined in
///
UINT32 InitModuleIndex;
UINT32 Reserved1;
UINT32 Reserved2;
UINT32 Reserved3;
UINT32 Reserved4;
UINT32 Reserved5;
UINT32 Reserved6;
} MACH_ROUTINES_COMMAND;
///
/// The 64-bit routines command. Same use as above. For 64-bit architectures.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
///
/// address of initialization routine
///
UINT64 InitiRoutineAddress;
///
/// index into the module table that the init routine is defined in
///
UINT64 InitModuleIndex;
UINT64 Reserved1;
UINT64 Reserved2;
UINT64 Reserved3;
UINT64 Reserved4;
UINT64 Reserved5;
UINT64 Reserved6;
} MACH_ROUTINES_COMMAND_64;
///
/// The symtab_command contains the offsets and sizes of the link-edit 4.3BSD
/// "stab" style symbol table information as described in the header files
/// <nlist.h> and <stab.h>.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 SymbolsOffset; ///< symbol table offset
UINT32 NumSymbols; ///< number of symbol table entries
UINT32 StringsOffset; ///< string table offset
UINT32 StringsSize; ///< string table size in bytes
} MACH_SYMTAB_COMMAND;
///
/// This is the second set of the symbolic information which is used to support
/// the data structures for the dynamically link editor.
///
/// The original set of symbolic information in the symtab_command which
/// contains the symbol and string tables must also be present when this load
/// command is present. When this load command is present the symbol table is
/// organized into three groups of symbols:
/// local symbols (static and debugging symbols) - grouped by module
/// defined external symbols - grouped by module (sorted by name if not lib)
/// undefined external symbols (sorted by name if MH_BINDATLOAD is not set,
/// and in order the were seen by the static
/// linker if MH_BINDATLOAD is set)
/// In this load command there are offsets and counts to each of the three
/// groups of symbols.
///
/// This load command contains a the offsets and sizes of the following new
/// symbolic information tables:
/// table of contents
/// module table
/// reference symbol table
/// indirect symbol table
/// The first three tables above (the table of contents, module table and
/// reference symbol table) are only present if the file is a dynamically
/// linked shared library. For executable and object modules, which are files
/// containing only one module, the information that would be in these three
/// tables is determined as follows:
/// table of contents - the defined external symbols are sorted by name
/// module table - the file contains only one module so everything in the
/// file is part of the module.
/// reference symbol table - is the defined and undefined external symbols
///
/// For dynamically linked shared library files this load command also contains
/// offsets and sizes to the pool of relocation entries for all sections
/// separated into two groups:
/// external relocation entries
/// local relocation entries
/// For executable and object modules the relocation entries continue to hang
/// off the section structures.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
//
// The symbols indicated by symoff and nsyms of the LC_SYMTAB load command
// are grouped into the following three groups:
// local symbols (further grouped by the module they are from)
// defined external symbols (further grouped by the module they are from)
// undefined symbols
//
// The local symbols are used only for debugging. The dynamic binding
// process may have to use them to indicate to the debugger the local
// symbols for a module that is being bound.
//
// The last two groups are used by the dynamic binding process to do the
// binding (indirectly through the module table and the reference symbol
// table when this is a dynamically linked shared library file).
//
UINT32 LocalSymbolsIndex; ///< index to local symbols
UINT32 NumLocalSymbols; ///< number of local symbols
UINT32 ExternalSymbolsIndex; ///< index to externally defined symbols
UINT32 NumExternalSymbols; ///< number of externally defined symbols
UINT32 UndefinedSymbolsIndex; ///< index to undefined symbols
UINT32 NumUndefinedSymbols; ///< number of undefined symbols
//
// For the for the dynamic binding process to find which module a symbol
// is defined in the table of contents is used (analogous to the ranlib
// structure in an archive) which maps defined external symbols to modules
// they are defined in. This exists only in a dynamically linked shared
// library file. For executable and object modules the defined external
// symbols are sorted by name and is use as the table of contents.
//
///
/// file offset to table of contents
///
UINT32 TableOfContentsFileOffset;
///
/// number of entries in table of contents
///
UINT32 TableOfContentsNumEntries;
//
// To support dynamic binding of "modules" (whole object files) the symbol
// table must reflect the modules that the file was created from. This is
// done by having a module table that has indexes and counts into the merged
// tables for each module. The module structure that these two entries
// refer to is described below. This exists only in a dynamically linked
// shared library file. For executable and object modules the file only
// contains one module so everything in the file belongs to the module.
//
UINT32 ModuleTableFileOffset; ///< file offset to module table
UINT32 ModuleTableNumEntries; ///< number of module table entries
//
// To support dynamic module binding the module structure for each module
// indicates the external references (defined and undefined) each module
// makes. For each module there is an offset and a count into the
// reference symbol table for the symbols that the module references.
// This exists only in a dynamically linked shared library file. For
// executable and object modules the defined external symbols and the
// undefined external symbols indicates the external references.
//
///
/// offset to referenced symbol table
///
UINT32 ReferencedSymbolTableFileOffset;
///
/// number of referenced symbol table entries
///
UINT32 ReferencedSymbolTableNumEntries;
//
// The sections that contain "symbol pointers" and "routine stubs" have
// indexes and (implied counts based on the size of the section and fixed
// size of the entry) into the "indirect symbol" table for each pointer
// and stub. For every section of these two types the index into the
// indirect symbol table is stored in the section header in the field
// reserved1. An indirect symbol table entry is simply a 32bit index into
// the symbol table to the symbol that the pointer or stub is referring to.
// The indirect symbol table is ordered to match the entries in the section.
//
///
/// file offset to the indirect symbol table
///
UINT32 IndirectSymbolsOffset;
///
/// number of indirect symbol table entries
///
UINT32 NumIndirectSymbols;
//
// To support relocating an individual module in a library file quickly the
// external relocation entries for each module in the library need to be
// accessed efficiently. Since the relocation entries can't be accessed
// through the section headers for a library file they are separated into
// groups of local and external entries further grouped by module. In this
// case the presents of this load command who's extreloff, nextrel,
// locreloff and nlocrel fields are non-zero indicates that the relocation
// entries of non-merged sections are not referenced through the section
// structures (and the reloff and nreloc fields in the section headers are
// set to zero).
//
// Since the relocation entries are not accessed through the section headers
// this requires the r_address field to be something other than a section
// offset to identify the item to be relocated. In this case r_address is
// set to the offset from the vmaddr of the first LC_SEGMENT command.
// For MH_SPLIT_SEGS images r_address is set to the the offset from the
// vmaddr of the first read-write LC_SEGMENT command.
//
// The relocation entries are grouped by module and the module table
// entries have indexes and counts into them for the group of external
// relocation entries for that the module.
//
// For sections that are merged across modules there must not be any
// remaining external relocation entries for them (for merged sections
// remaining relocation entries must be local).
//
///
/// offset to external relocation entries
///
UINT32 ExternalRelocationsOffset;
///
/// number of external relocation entries
///
UINT32 NumExternalRelocations;
//
// All the local relocation entries are grouped together (they are not
// grouped by their module since they are only used if the object is moved
// from it staticly link edited address).
//
UINT32 LocalRelocationsOffset; ///< offset to local relocation entries
UINT32 NumOfLocalRelocations; ///< number of local relocation entries
} MACH_DYSYMTAB_COMMAND;
//
// An indirect symbol table entry is simply a 32bit index into the symbol table
// to the symbol that the pointer or stub is refering to. Unless it is for a
// non-lazy symbol pointer section for a defined symbol which strip(1) as
// removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the
// symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that.
//
#define MACH_INDIRECT_SYMBOL_LOCAL 0x80000000U
#define MACH_INDIRECT_SYMBOL_ABS 0x40000000U
///
/// The entries in the two-level namespace lookup hints table are twolevel_hint
/// structs. These provide hints to the dynamic link editor where to start
/// looking for an undefined symbol in a two-level namespace image. The
/// isub_image field is an index into the sub-images (sub-frameworks and
/// sub-umbrellas list) that made up the two-level image that the undefined
/// symbol was found in when it was built by the static link editor. If
/// isub-image is 0 the the symbol is expected to be defined in library and not
/// in the sub-images. If isub-image is non-zero it is an index into the array
/// of sub-images for the umbrella with the first index in the sub-images being
/// 1. The array of sub-images is the ordered list of sub-images of the
/// umbrella that would be searched for a symbol that has the umbrella recorded
/// as its primary library. The table of contents index is an index into the
/// library's table of contents. This is used as the starting point of the
/// binary search or a directed linear search.
///
typedef struct {
UINT32 SubImagesIndex : 8; ///< index into the sub images
UINT32 TableOfContentsIndex : 24; ///< index into the table of contents
} TWOLEVEL_HINT;
///
/// The twolevel_hints_command contains the offset and number of hints in the
/// two-level namespace lookup hints table.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 Offset; ///< offset to the hint table
UINT32 NumHints; ///< number of hints in the hint table
TWOLEVEL_HINT Hints[];
} MACH_TWO_LEVEL_HINTS_COMMAND;
///
/// The prebind_cksum_command contains the value of the original check sum for
/// prebound files or zero. When a prebound file is first created or modified
/// for other than updating its prebinding information the value of the check
/// sum is set to zero. When the file has it prebinding re-done and if the
/// value of the check sum is zero the original check sum is calculated and
/// stored in cksum field of this load command in the output file. If when the
/// prebinding is re-done and the cksum field is non-zero it is left unchanged
/// from the input file.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 Checksum; ///< the check sum or zero
} MACH_PREBIND_CHECKSUM_COMMAND;
///
/// The uuid load command contains a single 128-bit unique random number that
/// identifies an object produced by the static link editor.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT8 Uuid[16]; ///< the 128-bit uuid
} MACH_UUID_COMMAND;
///
/// The rpath_command contains a path which at runtime should be added to
/// the current run path used to find @rpath prefixed dylibs.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_LOAD_COMMAND_STRING Path; ///< path to add to run path
} MACH_RUN_PATH_COMMAND;
///
/// The linkedit_data_command contains the offsets and sizes of a blob
/// of data in the __LINKEDIT segment.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 DataOffset; ///< file offset of data in __LINKEDIT segment
UINT32 DataSize; ///< file size of data in __LINKEDIT segment
} MACH_LINKEDIT_DATA_COMMAND;
///
/// The encryption_info_command contains the file offset and size of an
/// of an encrypted segment.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
///
/// file offset of encrypted range
///
UINT32 CryptOffset;
///
/// file size of encrypted range
///
UINT32 CryptSize;
///
/// which enryption system, 0 means not-encrypted yet
///
UINT32 CryptId;
} MACH_ENCRYPTION_INFO_COMMAND;
///
/// The encryption_info_command_64 contains the file offset and size of an
/// of an encrypted segment (for use in x86_64 targets).
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
///
/// file offset of encrypted range
///
UINT32 CryptOffset;
///
/// file size of encrypted range
///
UINT32 CryptSize;
///
/// which enryption system, 0 means not-encrypted yet
///
UINT32 CryptId;
///
/// padding to make this struct's size a multiple of 8 bytes
///
UINT32 Pad;
} MACH_ENCRYPTION_INFO_COMMAND_64;
///
/// The version_min_command contains the min OS version on which this
/// binary was built to run.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 Version; ///< X.Y.Z is encoded in nibbles xxxx.yy.zz
UINT32 SdkVersion; ///< X.Y.Z is encoded in nibbles xxxx.yy.zz
} MACH_VERSION_MIN_COMMAND;
///
/// Encoded tools
///
typedef struct {
UINT32 Tool; ///< enum for the tool
UINT32 Version; ///< version number of the tool
} MACH_BUILD_VERSION_TOOL;
///
/// The build_version_command contains the min OS version on which this
/// binary was built to run for its platform. The list of known platforms and
/// tool values following it.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 Platform; ///< platform
UINT32 MinOs; ///< X.Y.Z is encoded in nibbles xxxx.yy.zz
UINT32 SdkVersion; ///< X.Y.Z is encoded in nibbles xxxx.yy.zz
UINT32 NumTools; ///< number of tool entries following this
MACH_BUILD_VERSION_TOOL Tools[];
} MACH_BUILD_VERSION_COMMAND;
///
/// Known values for the platform field above.
///
#define MACH_PLATFORM_MACOS 1U
#define MACH_PLATFORM_IOS 2U
#define MACH_PLATFORM_TVOS 3U
#define MACH_PLATFORM_WATCHOS 4U
#define MACH_PLATFORM_BRIDGEOS 5U
#define MACH_PLATFORM_IOSMAC 6U
#define MACH_PLATFORM_IOSSIMULATOR 7U
#define MACH_PLATFORM_TVOSSIMULATOR 8U
#define MACH_PLATFORM_WATCHOSSIMULATOR 9U
#define MACH_PLATFORM_DRIVERKIT 10U
///
/// Known values for the tool field above.
///
#define MACH_TOOL_CLANG 1U
#define MACH_TOOL_SWIFT 2U
#define MACH_TOOL_LD 3U
///
/// The dyld_info_command contains the file offsets and sizes of
/// the new compressed form of the information dyld needs to
/// load the image. This information is used by dyld on Mac OS X
/// 10.6 and later. All information pointed to by this command
/// is encoded using byte streams, so no endian swapping is needed
/// to interpret it.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
//
// Dyld rebases an image whenever dyld loads it at an address different
// from its preferred address. The rebase information is a stream
// of byte sized opcodes whose symbolic names start with REBASE_OPCODE_.
// Conceptually the rebase information is a table of tuples:
// <seg-index, seg-offset, type>
// The opcodes are a compressed way to encode the table by only
// encoding when a column changes. In addition simple patterns
// like "every n'th offset for m times" can be encoded in a few
// bytes.
//
UINT32 RebaseOffset; ///< file offset to rebase info
UINT32 RebaseSize; ///< size of rebase info
//
// Dyld binds an image during the loading process, if the image
// requires any pointers to be initialized to symbols in other images.
// The bind information is a stream of byte sized
// opcodes whose symbolic names start with BIND_OPCODE_.
// Conceptually the bind information is a table of tuples:
// <seg-index, seg-offset, type, symbol-library-ordinal, symbol-name,
// addend>
// The opcodes are a compressed way to encode the table by only
// encoding when a column changes. In addition simple patterns
// like for runs of pointers initialzed to the same value can be
// encoded in a few bytes.
//
UINT32 BindingInfoOffset; ///< file offset to binding info
UINT32 BindingInfoSize; ///< size of binding info
//
// Some C++ programs require dyld to unique symbols so that all
// images in the process use the same copy of some code/data.
// This step is done after binding. The content of the weak_bind
// info is an opcode stream like the bind_info. But it is sorted
// alphabetically by symbol name. This enable dyld to walk
// all images with weak binding information in order and look
// for collisions. If there are no collisions, dyld does
// no updating. That means that some fixups are also encoded
// in the bind_info. For instance, all calls to "operator new"
// are first bound to libstdc++.dylib using the information
// in bind_info. Then if some image overrides operator new
// that is detected when the weak_bind information is processed
// and the call to operator new is then rebound.
//
UINT32 WeakBindingInfoOffset; ///< file offset to weak binding info
UINT32 WeakBindingInfoSize; ///< size of weak binding info
//
// Some uses of external symbols do not need to be bound immediately.
// Instead they can be lazily bound on first use. The lazy_bind
// are contains a stream of BIND opcodes to bind all lazy symbols.
// Normal use is that dyld ignores the lazy_bind section when
// loading an image. Instead the static linker arranged for the
// lazy pointer to initially point to a helper function which
// pushes the offset into the lazy_bind area for the symbol
// needing to be bound, then jumps to dyld which simply adds
// the offset to lazy_bind_off to get the information on what
// to bind.
//
UINT32 LazyBindingInfoOffset; ///< file offset to lazy binding info
UINT32 LazyBindingInfoSize; ///< size of lazy binding infs
//
// The symbols exported by a dylib are encoded in a trie. This
// is a compact representation that factors out common prefixes.
// It also reduces LINKEDIT pages in RAM because it encodes all
// information (name, address, flags) in one small, contiguous range.
// The export area is a stream of nodes. The first node sequentially
// is the start node for the trie.
//
// Nodes for a symbol start with a uleb128 that is the length of
// the exported symbol information for the string so far.
// If there is no exported symbol, the node starts with a zero byte.
// If there is exported info, it follows the length.
//
// First is a uleb128 containing flags. Normally, it is followed by
// a uleb128 encoded offset which is location of the content named
// by the symbol from the mach_header for the image. If the flags
// is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is
// a uleb128 encoded library ordinal, then a zero terminated
// UTF8 string. If the string is zero length, then the symbol
// is re-export from the specified dylib with the same name.
// If the flags is EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, then following
// the flags is two uleb128s: the stub offset and the resolver offset.
// The stub is used by non-lazy pointers. The resolver is used
// by lazy pointers and must be called to get the actual address to use.
//
// After the optional exported symbol information is a byte of
// how many edges (0-255) that this node has leaving it,
// followed by each edge.
// Each edge is a zero terminated UTF8 of the addition chars
// in the symbol, followed by a uleb128 offset for the node that
// edge points to.
//
UINT32 ExportSymbolsOffset; ///< file offset to lazy binding info
UINT32 ExportSymbolsSize; ///< size of lazy binding infs
} MACH_DYLD_INFO_COMMAND;
///
/// The linker_option_command contains linker options embedded in object files.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 NumStrings; ///< number of strings
///
/// concatenation of zero terminated UTF8 strings. Zero filled at end to
/// align.
///
CHAR8 Strings[];
} MACH_LINKER_OPTION_COMMAND;
///
/// The symseg_command contains the offset and size of the GNU style
/// symbol table information as described in the header file <symseg.h>.
/// The symbol roots of the symbol segments must also be aligned properly
/// in the file. So the requirement of keeping the offsets aligned to a
/// multiple of a 4 bytes translates to the length field of the symbol
/// roots also being a multiple of a long. Also the padding must again be
/// zeroed. (THIS IS OBSOLETE and no longer supported).
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT32 Offset; ///< symbol segment offset
UINT32 Size; ///< symbol segment size in bytes
} MACH_SYMBOL_SEGMENT_COMMAND;
///
/// The ident_command contains a free format string table following the
/// ident_command structure. The strings are null terminated and the size of
/// the command is padded out with zero bytes to a multiple of 4 bytes/
/// (THIS IS OBSOLETE and no longer supported).
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
CHAR8 Strings[];
} MACH_IDENTIFICATION_COMMAND;
///
/// The fvmfile_command contains a reference to a file to be loaded at the
/// specified virtual address. (Presently, this command is reserved for
/// internal use. The kernel ignores this command when loading a program into
/// memory).
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
MACH_LOAD_COMMAND_STRING Name; ///< files pathname
UINT32 HeaderAddress; ///< files virtual address
} MACH_FIXED_VM_FILE_COMMAND;
///
/// The entry_point_command is a replacement for thread_command.
/// It is used for main executables to specify the location (file offset)
/// of main(). If -stack_size was used at link time, the stacksize
/// field will contain the stack size need for the main thread.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT64 EntryOffset; ///< file (__TEXT) offset of main()
UINT64 StackSize; ///< if not zero, initial stack size
} MACH_ENTRY_POINT_COMMAND;
#define MACH_SOURCE_VERSION_A_MASK 0xFFFFFF0000000000U
#define MACH_SOURCE_VERSION_B_MASK 0x000000FFC0000000U
#define MACH_SOURCE_VERSION_V_MASK 0x000000003FF00000U
#define MACH_SOURCE_VERSION_D_MASK 0x00000000000FFC00U
#define MACH_SOURCE_VERSION_E_MASK 0x00000000000003FFU
#define MACH_SOURCE_VERSION_A(Version) (((Version) & MACH_SOURCE_VERSION_A_MASK) >> 40U)
#define MACH_SOURCE_VERSION_B(Version) (((Version) & MACH_SOURCE_VERSION_B_MASK) >> 30U)
#define MACH_SOURCE_VERSION_C(Version) (((Version) & MACH_SOURCE_VERSION_V_MASK) >> 20U)
#define MACH_SOURCE_VERSION_D(Version) (((Version) & MACH_SOURCE_VERSION_D_MASK) >> 10U)
#define MACH_SOURCE_VERSION_E(Version) ((Version) & MACH_SOURCE_VERSION_E_MASK)
///
/// The source_version_command is an optional load command containing
/// the version of the sources used to build the binary.
///
typedef struct {
MACH_LOAD_COMMAND_HDR_
UINT64 Version; ///< A.B.C.D.E as a24.b10.c10.d10.e10
} MACH_SOURCE_VERSION_COMMAND;
typedef union {
CONST MACH_LOAD_COMMAND *Hdr;
CONST MACH_SEGMENT_COMMAND *Segment;
CONST MACH_SEGMENT_COMMAND_64 *Segment64;
CONST MACH_FIXED_VM_LIB_COMMAND *VmLib;
CONST MACH_DYLIB_COMMAND *Dylib;
CONST MACH_SUB_FRAMEWORK_COMMAND *SubFramework;
CONST MACH_SUB_CLIENT_COMMAND *SubClient;
CONST MACH_SUB_UMBRELLA_COMMAND *SubUmbrella;
CONST MACH_SUB_LIBRARY_COMMAND *SubLibrary;
CONST MACH_PREBOUND_DYLIB_COMMAND *PreboundDyLib;
CONST MACH_DYLINKER_COMMAND *Dylinker;
CONST MACH_THREAD_COMMAND *Thread;
CONST MACH_ROUTINES_COMMAND *Routines;
CONST MACH_ROUTINES_COMMAND_64 *Routines64;
CONST MACH_SYMTAB_COMMAND *Symtab;
CONST MACH_DYSYMTAB_COMMAND *Dysymtab;
CONST MACH_TWO_LEVEL_HINTS_COMMAND *TwoLevelHints;
CONST MACH_PREBIND_CHECKSUM_COMMAND *PrebindChecksum;
CONST MACH_UUID_COMMAND *Uuid;
CONST MACH_RUN_PATH_COMMAND *RunPath;
CONST MACH_LINKEDIT_DATA_COMMAND *LinkeditData;
CONST MACH_ENCRYPTION_INFO_COMMAND *EncryptionInfo;
CONST MACH_ENCRYPTION_INFO_COMMAND_64 *EncryptionInfo64;
CONST MACH_VERSION_MIN_COMMAND *VersionMin;
CONST MACH_BUILD_VERSION_COMMAND *BuildVersion;
CONST MACH_DYLD_INFO_COMMAND *DyldInfo;
CONST MACH_LINKER_OPTION_COMMAND *LinkerOption;
CONST MACH_SYMBOL_SEGMENT_COMMAND *SymbolSegment;
CONST MACH_IDENTIFICATION_COMMAND *Identification;
CONST MACH_FIXED_VM_FILE_COMMAND *FixedVmFile;
CONST VOID *Pointer;
UINTN Address;
} MACH_LOAD_COMMAND_PTR;
#undef MACH_LOAD_COMMAND_HDR_
///
/// The layout of the file depends on the filetype. For all but the MH_OBJECT
/// file type the segments are padded out and aligned on a segment alignment
/// boundary for efficient demand pageing. The MH_EXECUTE, MH_FVMLIB,
/// MH_DYLIB, MH_DYLINKER and MH_BUNDLE file types also have the headers
/// included as part of their first segment.
///
/// The file type MH_OBJECT is a compact format intended as output of the
/// assembler and input (and possibly output) of the link editor (the .o
/// format). All sections are in one unnamed segment with no segment padding.
/// This format is used as an executable format when the file is so small the
/// segment padding greatly increases its size.
///
/// The file type MH_PRELOAD is an executable format intended for things that
/// are not executed under the kernel (proms, stand alones, kernels, etc). The
/// format can be executed under the kernel but may demand paged it and not
/// preload it before execution.
///
/// A core file is in MH_CORE format and can be any in an arbritray legal
/// Mach-O file.
///
/// Constants for the filetype field of the mach_header
///
enum {
MachHeaderFileTypeObject = 1,
MachHeaderFileTypeExecute = 2,
MachHeaderFileTypeFixedVmLib = 3,
MachHeaderFileTypeCore = 4,
MachHeaderFileTypePreload = 5,
MachHeaderFileTypeDylib = 6,
MachHeaderFileTypeDynamicLinker = 7,
MachHeaderFileTypeBundle = 8,
MachHeaderFileTypeDynamicLinkerStub = 9,
MachHeaderFileTypeDsym = 10,
MachHeaderFileTypeKextBundle = 11,
MachHeaderFileTypeFileSet = 12,
};
typedef UINT32 MACH_HEADER_FILE_TYPE;
//
// Constants for the Flags field of the MACH_HEADER struct
//
#define MACH_HEADER_FLAG_NO_UNDEFINED_REFERENCES BIT0
#define MACH_HEADER_FLAG_INCREMENTAL_LINK BIT1
#define MACH_HEADER_FLAG_DYNAMIC_LINKER_LINK BIT2
#define MACH_HEADER_FLAG_BINARY_DATA_LOAD BIT3
#define MACH_HEADER_FLAG_PREBOUND BIT4
#define MACH_HEADER_FLAG_SPLIT_SEGMENTS BIT5
#define MACH_HEADER_FLAG_LAZY_INITIALIZATION BIT6
#define MACH_HEADER_FLAG_TWO_LEVEL BIT7
#define MACH_HEADER_FLAG_FORCE_FLAT BIT8
#define MACH_HEADER_FLAG_NO_MULTIPLE_DEFINITIONS BIT9
#define MACH_HEADER_FLAG_NO_FIX_PREBINDING BIT10
#define MACH_HEADER_FLAG_PREBINDABLE BIT11
#define MACH_HEADER_FLAG_ALL_MODULES_BOUND BIT12
#define MACH_HEADER_FLAG_SUBSECTIONS_VIA_SYNBOLS BIT13
#define MACH_HEADER_FLAG_CANONICAL BIT14
#define MACH_HEADER_FLAG_WEAK_DEFINES BIT15
#define MACH_HEADER_FLAG_BINDS_TO_WEAK BIT16
#define MACH_HEADER_FLAG_ALLOW_STACK_EXECUTION BIT17
#define MACH_HEADER_FLAG_ROOT_SAFE BIT18
#define MACH_HEADER_FLAG_SET_UID_SAFE BIT19
#define MACH_HEADER_FLAG_NO_REEXPORTED_DYLIBS BIT20
#define MACH_HEADER_FLAG_POSITION_INDEPENDENT_EXECUTABLE BIT21
#define MACH_HEADER_FLAG_DEAD_STRIPPABLE_DYLIB BIT22
#define MACH_HEADER_FLAG_HAS_TLV_DESCRIPTORS BIT23
#define MACH_HEADER_FLAG_NO_HEAP_EXECUTION BIT24
#define MACH_HEADER_FLAG_APP_EXTENSION_SAFE BIT25
#define MACH_HEADER_FLAG_NLIST_OUTOFSYNC_WITH_DYLDINFO BIT26
#define MACH_HEADER_FLAG_SIM_SUPPORT BIT27
typedef UINT32 MACH_HEADER_FLAGS;
//
// Constant for the magic field of the MACH_HEADER (32-bit architectures)
//
#define MACH_HEADER_SIGNATURE 0xFEEDFACE ///< the mach magic number
#define MACH_HEADER_INVERT_SIGNATURE 0xCEFAEDFE ///< the mach magic number (byte swapped)
///
/// The 32-bit mach header appears at the very beginning of the object file for
/// 32-bit architectures.
///
typedef struct {
UINT32 Signature; ///< mach magic number identifier
MACH_CPU_TYPE CpuType; ///< cpu Sectionecifier
MACH_CPU_SUBTYPE CpuSubtype; ///< machine Sectionecifier
MACH_HEADER_FILE_TYPE FileType; ///< type of file
UINT32 NumCommands; ///< number of load commands
UINT32 CommandsSize; ///< the size of all load commands
MACH_HEADER_FLAGS Flags; ///< flags
MACH_LOAD_COMMAND Commands[];
} MACH_HEADER;
//
// Constant for the magic field of the MACH_HEADER_64 (64-bit architectures)
//
#define MACH_HEADER_64_SIGNATURE 0xFEEDFACF ///< the 64-bit mach magic number
#define MACH_HEADER_64_INVERT_SIGNATURE 0xCFFAEDFE ///< the 64-bit mach magic number (byte swapped)
///
/// The 64-bit mach header appears at the very beginning of object files for
/// 64-bit architectures.
///
typedef struct {
UINT32 Signature; ///< mach magic number identifier
MACH_CPU_TYPE CpuType; ///< cpu Sectionecifier
MACH_CPU_SUBTYPE CpuSubtype; ///< machine Sectionecifier
MACH_HEADER_FILE_TYPE FileType; ///< type of file
UINT32 NumCommands; ///< number of load commands
UINT32 CommandsSize; ///< the size of all load commands
MACH_HEADER_FLAGS Flags; ///< flags
UINT32 Reserved; ///< reserved
MACH_LOAD_COMMAND Commands[];
} MACH_HEADER_64;
///
/// Allow selecting a correct header based on magic
///
typedef union {
UINT32 Signature;
MACH_HEADER Header32;
MACH_HEADER_64 Header64;
} MACH_HEADER_ANY;
//
// Symbols
//
///
/// Format of a symbol table entry of a Mach-O file for 32-bit architectures.
/// Modified from the BSD format. The modifications from the original format
/// were changing n_other (an unused field) to n_sect and the addition of the
/// N_SECT type. These modifications are required to support symbols in a
/// larger number of sections not just the three sections (text, data and bss)
/// in a BSD file.
///
typedef struct {
union {
UINT32 Address32; ///< for use when in-core
UINT32 StringIndex; ///< index into the string table
} UnifiedName;
UINT8 Type; ///< type flag, see below
UINT8 Section; ///< section number or NO_SECT
INT16 Descriptor; ///< see <mach-o/stab.h>
UINT32 Value; ///< value of this symbol (or stab offset)
} MACH_NLIST;
///
/// This is the symbol table entry structure for 64-bit architectures.
///
typedef struct {
union {
UINT32 StringIndex; ///< index into the string table
} UnifiedName;
UINT8 Type; ///< type flag, see below
UINT8 Section; ///< section number or NO_SECT
UINT16 Descriptor; ///< see <mach-o/stab.h>
UINT64 Value; ///< value of this symbol (or stab offset)
} MACH_NLIST_64;
//
// Symbols with a index into the string table of zero (n_un.n_strx == 0) are
// defined to have a null, "", name. Therefore all string indexes to non null
// names must not have a zero string index. This is bit historical information
// that has never been well documented.
//
//
// The n_type field really contains four fields:
// unsigned char N_STAB:3,
// N_PEXT:1,
// N_TYPE:3,
// N_EXT:1;
// which are used via the following masks.
//
#define MACH_N_TYPE_STAB 0xE0U ///< if any of these bits set, a symbolic
///< debugging entry
#define MACH_N_TYPE_PEXT 0x10U ///< private external symbol bit
#define MACH_N_TYPE_TYPE 0x0EU ///< mask for the type bit
#define MACH_N_TYPE_EXT 0x01U ///< external symbol bit, set for external
///< symbols
//
// Only symbolic debugging entries have some of the N_STAB bits set and if any
// of these bits are set then it is a symbolic debugging entry (a stab). In
// which case then the values of the n_type field (the entire field) are given
// in <mach-o/stab.h>
//
//
// Values for N_TYPE bits of the n_type field.
//
#define MACH_N_TYPE_UNDF 0x0U ///< undefined, n_sect == NO_SECT
#define MACH_N_TYPE_ABS 0x2U ///< absolute, n_sect == NO_SECT
#define MACH_N_TYPE_SECT 0xEU ///< defined in section number n_sect
#define MACH_N_TYPE_PBUD 0xCU ///< prebound undefined (defined in a dylib)
#define MACH_N_TYPE_INDR 0xAU ///< indirect
//
// If the type is N_INDR then the symbol is defined to be the same as another
// symbol. In this case the n_value field is an index into the string table
// of the other symbol's name. When the other symbol is defined then they both
// take on the defined type and value.
//
//
// If the type is N_SECT then the n_sect field contains an ordinal of the
// section the symbol is defined in. The sections are numbered from 1 and
// refer to sections in order they appear in the load commands for the file
// they are in. This means the same ordinal may very well refer to different
// sections in different files.
//
// The n_value field for all symbol table entries (including N_STAB's) gets
// updated by the link editor based on the value of it's n_sect field and where
// the section n_sect references gets relocated. If the value of the n_sect
// field is NO_SECT then it's n_value field is not changed by the link editor.
//
#define NO_SECT 0 ///< symbol is not in any section
#define MAX_SECT 255 ///< 1 thru 255 inclusive
//
// STAB
//
//
// Symbolic debugger symbols. The comments give the conventional use for
//
// .stabs "n_name", n_type, n_sect, n_desc, n_value
//
// where n_type is the defined constant and not listed in the comment. Other
// fields not listed are zero. n_sect is the section ordinal the entry is
// refering to.
//
#define MACH_N_GSYM 0x20U ///< global symbol: name,,NO_SECT,type,0
#define MACH_N_FNAME 0x22U ///< procedure name (f77 kludge): name,,NO_SECT,0,0
#define MACH_N_FUN 0x24U ///< procedure: name,,n_sect,linenumber,address
#define MACH_N_STSYM 0x26U ///< static symbol: name,,n_sect,type,address
#define MACH_N_LCSYM 0x28U ///< .lcomm symbol: name,,n_sect,type,address
#define MACH_N_BNSYM 0x2EU ///< begin nsect sym: 0,,n_sect,0,address
#define MACH_N_AST 0x32U ///< AST file path: name,,NO_SECT,0,0
#define MACH_N_OPT 0x3CU ///< emitted with gcc2_compiled and in gcc source
#define MACH_N_RSYM 0x40U ///< register sym: name,,NO_SECT,type,register
#define MACH_N_SLINE 0x44U ///< src line: 0,,n_sect,linenumber,address
#define MACH_N_ENSYM 0x4EU ///< end nsect sym: 0,,n_sect,0,address
#define MACH_N_SSYM 0x60U ///< structure elt: name,,NO_SECT,type,struct_offset
#define MACH_N_SO 0x64U ///< source file name: name,,n_sect,0,address
#define MACH_N_OSO 0x66U ///< object file name: name,,0,0,st_mtime
#define MACH_N_LSYM 0x80U ///< local sym: name,,NO_SECT,type,offset
#define MACH_N_BINCL 0x82U ///< include file beginning: name,,NO_SECT,0,sum
#define MACH_N_SOL 0x84U ///< #included file name: name,,n_sect,0,address
#define MACH_N_PARAMS 0x86U ///< compiler parameters: name,,NO_SECT,0,0
#define MACH_N_VERSION 0x88U ///< compiler version: name,,NO_SECT,0,0
#define MACH_N_OLEVEL 0x8AU ///< compiler -O level: name,,NO_SECT,0,0
#define MACH_N_PSYM 0xA0U ///< parameter: name,,NO_SECT,type,offset
#define MACH_N_EINCL 0xA2U ///< include file end: name,,NO_SECT,0,0
#define MACH_N_ENTRY 0xA4U ///< alternate entry: name,,n_sect,linenumber,address
#define MACH_N_LBRAC 0xC0U ///< left bracket: 0,,NO_SECT,nesting level,address
#define MACH_N_EXCL 0xC2U ///< deleted include file: name,,NO_SECT,0,sum
#define MACH_N_RBRAC 0xE0U ///< right bracket: 0,,NO_SECT,nesting level,address
#define MACH_N_BCOMM 0xE2U ///< begin common: name,,NO_SECT,0,0
#define MACH_N_ECOMM 0xE4U ///< end common: name,,n_sect,0,0
#define MACH_N_ECOML 0xE8U ///< end common (local name): 0,,n_sect,0,address
#define MACH_N_LENG 0xFEU ///< second stab entry with length information
//
// The bit 0x0020 of the n_desc field is used for two non-overlapping purposes
// and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED.
//
///
/// The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a
/// relocatable .o file (MH_OBJECT filetype). And is used to indicate to the
/// static link editor it is never to dead strip the symbol.
///
#define MACH_N_NO_DEAD_STRIP 0x0020U ///< symbol is not to be dead stripped
///
/// The N_DESC_DISCARDED bit of the n_desc field never appears in linked image.
/// But is used in very rare cases by the dynamic link editor to mark an in
/// memory symbol as discared and longer used for linking.
///
#define MACH_N_DESC_DISCARDED 0x0020U
///
/// The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that
/// the undefined symbol is allowed to be missing and is to have the address of
/// zero when missing.
///
#define MACH_N_WEAK_REF 0x0040U
///
/// The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic
/// linkers that the symbol definition is weak, allowing a non-weak symbol to
/// also be used which causes the weak definition to be discared. Currently
/// this is only supported for symbols in coalesed sections.
///
#define MACH_N_WEAK_DEF 0x0080U
///
/// The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker
/// that the undefined symbol should be resolved using flat namespace
/// searching.
///
#define MACH_N_REF_TO_WEAK 0x0080U
///
/// The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is
/// a defintion of a Thumb function.
///
#define MACH_N_ARM_THUMB_DEF 0x0008U
///
/// The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
/// that the function is actually a resolver function and should
/// be called to get the address of the real function to use.
/// This bit is only available in .o files (MH_OBJECT filetype)
///
#define MACH_N_SYMBOL_RESOLVER 0x0100U
///
/// The N_ALT_ENTRY bit of the n_desc field indicates that the
/// symbol is pinned to the previous content.
///
#define MACH_N_ALT_ENTRY 0x0200U
///
/// for the berkeley pascal compiler, pc(1):
/// global pascal symbol: name,,NO_SECT,subtype,line
///
#define MACH_N_PC 0x30U
//
// Relocations
//
///
/// Format of a relocation entry of a Mach-O file. Modified from the 4.3BSD
/// format. The modifications from the original format were changing the value
/// of the r_symbolnum field for "local" (r_extern == 0) relocation entries.
/// This modification is required to support symbols in an arbitrary number of
/// sections not just the three sections (text, data and bss) in a 4.3BSD file.
/// Also the last 4 bits have had the r_type tag added to them.
///
typedef struct {
INT32 Address; ///< offset in the section to what is being
///< relocated
UINT32 SymbolNumber : 24; ///< symbol index if r_extern == 1 or section
///< ordinal if r_extern == 0
UINT32 PcRelative : 1; ///< was relocated pc relative already
UINT32 Size : 2; ///< 0=byte, 1=word, 2=long, 3=quad
UINT32 Extern : 1; ///< does not include value of sym referenced
UINT32 Type : 4; ///< if not 0, machine specific relocation type
} MACH_RELOCATION_INFO;
#define MACH_RELOC_ABSOLUTE 0U ///< absolute relocation type for Mach-O files
//
// The r_address is not really the address as it's name indicates but an
// offset. In 4.3BSD a.out objects this offset is from the start of the
// "segment" for which relocation entry is for (text or data). For Mach-O
// object files it is also an offset but from the start of the "section" for
// which the relocation entry is for. See comments in <mach-o/loader.h> about
// the r_address field in images for used with the dynamic linker.
//
// In 4.3BSD a.out objects if r_extern is zero then r_symbolnum is an ordinal
// for the segment the symbol being relocated is in. These ordinals are the
// symbol types N_TEXT, N_DATA, N_BSS or N_ABS. In Mach-O object files these
// ordinals refer to the sections in the object file in the order their section
// structures appear in the headers of the object file they are in. The first
// section has the ordinal 1, the second 2, and so on. This means that the
// same ordinal in two different object files could refer to two different
// sections. And further could have still different ordinals when combined
// by the link-editor. The value MACH_RELOC_ABSOLUTE is used for relocation entries for
// absolute symbols which need no further relocation.
//
//
// For RISC machines some of the references are split across two instructions
// and the instruction does not contain the complete value of the reference.
// In these cases a second, or paired relocation entry, follows each of these
// relocation entries, using a PAIR r_type, which contains the other part of
// the reference not contained in the instruction. This other part is stored
// in the pair's r_address field. The exact number of bits of the other part
// of the reference store in the r_address field is dependent on the particular
// relocation type for the particular architecture.
//
///
/// mask to be applied to the r_address field of a relocation_info structure
/// to tell that is is really a scattered_relocation_info stucture
///
/// To make scattered loading by the link editor work correctly "local"
/// relocation entries can't be used when the item to be relocated is the value
/// of a symbol plus an offset (where the resulting expresion is outside the
/// block the link editor is moving, a blocks are divided at symbol addresses).
/// In this case. where the item is a symbol value plus offset, the link editor
/// needs to know more than just the section the symbol was defined. What is
/// needed is the actual value of the symbol without the offset so it can do
/// the relocation correctly based on where the value of the symbol got
/// relocated to not the value of the expression (with the offset added to the
/// symbol value). So for the NeXT 2.0 release no "local" relocation entries
/// are ever used when there is a non-zero offset added to a symbol.
/// The "external" and "local" relocation entries remain unchanged.
///
/// The implemention is quite messy given the compatibility with the existing
/// relocation entry format. The ASSUMPTION is that a section will never be
/// bigger than 2**24 - 1 (0x00ffffff or 16,777,215) bytes. This assumption
/// allows the r_address (which is really an offset) to fit in 24 bits and high
/// bit of the r_address field in the relocation_info structure to indicate
/// it is really a scattered_relocation_info structure. Since these are only
/// used in places where "local" relocation entries are used and not where
/// "external" relocation entries are used the r_extern field has been removed.
///
/// For scattered loading to work on a RISC machine where some of the
/// references are split across two instructions the link editor needs to be
/// assured that each reference has a unique 32 bit reference (that more than
/// one reference is NOT sharing the same high 16 bits for example) so it move
/// each referenced item independent of each other. Some compilers guarantees
/// this but the compilers don't so scattered loading can be done on those that
/// do guarantee this.
///
#define MACH_RELOC_SCATTERED 0x80000000U
typedef struct {
#if defined(MACH_LITTLE_ENDIAN)
UINT32 Address : 24; ///< offset in the section to what is being
///< relocated
UINT32 Type : 4; ///< if not 0, machine specific relocation type
UINT32 Size : 2; ///< 0=byte, 1=word, 2=long, 3=quad
UINT32 PcRelative : 1; ///< was relocated pc relative already
UINT32 Scattered : 1; ///< 1=scattered, 0=non-scattered (see above)
INT32 Value; ///< the value the item to be relocated is refering
///< to (without any offset added)
#elif defined(MACH_BIG_ENDIAN)
UINT32 Scattered : 1; ///< 1=scattered, 0=non-scattered (see above)
UINT32 PcRelative : 1; ///< was relocated pc relative already
UINT32 Size : 2; ///< 0=byte, 1=word, 2=long, 3=quad
UINT32 Type : 4; ///< if not 0, machine specific relocation type
UINT32 Address : 24; ///< offset in the section to what is being
///< relocated
INT32 Value; ///< the value the item to be relocated is refering
///< to (without any offset added)
#else
///
/// The reason for the ifdef's of __BIG_ENDIAN__ and __LITTLE_ENDIAN__ are that
/// when stattered relocation entries were added the mistake of using a mask
/// against a structure that is made up of bit fields was used. To make this
/// design work this structure must be laid out in memory the same way so the
/// mask can be applied can check the same bit each time (r_scattered).
///
#error "No endianness information was provided!"
#endif
} MACH_SCATTERED_RELOCATION_INFO;
///
/// Relocation types used in a generic implementation. Relocation entries for
/// normal things use the generic relocation as discribed above and their
/// r_type is GENERIC_RELOC_VANILLA (a value of zero).
///
/// Another type of generic relocation, GENERIC_RELOC_SECTDIFF, is to support
/// the difference of two symbols defined in different sections. That is the
/// expression "symbol1 - symbol2 + constant" is a relocatable expression when
/// both symbols are defined in some section. For this type of relocation the
/// both relocations entries are scattered relocation entries. The value of
/// symbol1 is stored in the first relocation entry's r_value field and the
/// value of symbol2 is stored in the pair's r_value field.
///
/// A special case for a prebound lazy pointer is needed to beable to set the
/// value of the lazy pointer back to its non-prebound state. This is done
/// using the GENERIC_RELOC_PB_LA_PTR r_type. This is a scattered relocation
/// entry where the r_value feild is the value of the lazy pointer not
/// prebound.
///
enum {
MachGenericRelocVanilla, ///< generic relocation as discribed
///< above
MachGenericRelocPair, ///< Only follows a
///< MachGenericRelocLocalSectDiff
MachGenericRelocSectDiff,
MachGenericRelocPreboundLazyPointer, ///< prebound lazy pointer
MachGenericRelocLocalSectDiff,
MachGenericRelocThreadLocalVariables ///< thread local variables
};
///
/// Relocations for x86_64 are a bit different than for other architectures in
/// Mach-O: Scattered relocations are not used. Almost all relocations
/// produced by the compiler are external relocations. An external relocation
/// has the r_extern bit set to 1 and the r_symbolnum field contains the symbol
/// table index of the target label.
///
/// When the assembler is generating relocations, if the target label is a
/// local label (begins with 'L'), then the previous non-local label in the
/// same section is used as the target of the external relocation. An addend
/// is used with the distance from that non-local label to the target label.
/// Only when there is no previous non-local label in the section is an
/// internal relocation used.
///
/// The addend (i.e. the 4 in _foo+4) is encoded in the instruction (Mach-O
/// does not have RELA relocations). For PC-relative relocations, the addend
/// is stored directly in the instruction. This is different from other Mach-O
/// architectures, which encode the addend minus the current section offset.
///
/// The relocation types are:
///
/// X86_64_RELOC_UNSIGNED // for absolute addresses
/// X86_64_RELOC_SIGNED // for signed 32-bit displacement
/// X86_64_RELOC_BRANCH // a CALL/JMP instruction with 32-bit displacement
/// X86_64_RELOC_GOT_LOAD // a MOVQ load of a GOT entry
/// X86_64_RELOC_GOT // other GOT references
/// X86_64_RELOC_SUBTRACTOR // must be followed by a X86_64_RELOC_UNSIGNED
///
/// The following are sample assembly instructions, followed by the relocation
/// and section content they generate in an object file:
///
/// call _foo
/// r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
/// E8 00 00 00 00
///
/// call _foo+4
/// r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
/// E8 04 00 00 00
///
/// movq _foo@GOTPCREL(%rip), %rax
/// r_type=X86_64_RELOC_GOT_LOAD, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
/// 48 8B 05 00 00 00 00
///
/// pushq _foo@GOTPCREL(%rip)
/// r_type=X86_64_RELOC_GOT, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
/// FF 35 00 00 00 00
///
/// movl _foo(%rip), %eax
/// r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
/// 8B 05 00 00 00 00
///
/// movl _foo+4(%rip), %eax
/// r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
/// 8B 05 04 00 00 00
///
/// movb $0x12, _foo(%rip)
/// r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
/// C6 05 FF FF FF FF 12
///
/// movl $0x12345678, _foo(%rip)
/// r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
/// C7 05 FC FF FF FF 78 56 34 12
///
/// .quad _foo
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
/// 00 00 00 00 00 00 00 00
///
/// .quad _foo+4
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
/// 04 00 00 00 00 00 00 00
///
/// .quad _foo - _bar
/// r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
/// 00 00 00 00 00 00 00 00
///
/// .quad _foo - _bar + 4
/// r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
/// 04 00 00 00 00 00 00 00
///
/// .long _foo - _bar
/// r_type=X86_64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar
/// r_type=X86_64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
/// 00 00 00 00
///
/// lea L1(%rip), %rax
/// r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_prev
/// 48 8d 05 12 00 00 00
/// // assumes _prev is the first non-local label 0x12 bytes before L1
///
/// lea L0(%rip), %rax
/// r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3
/// 48 8d 05 56 00 00 00
/// // assumes L0 is in third section and there is no previous non-local label.
/// // The rip-relative-offset of 0x00000056 is L0-address_of_next_instruction.
/// // address_of_next_instruction is the address of the relocation + 4.
///
/// add $6,L0(%rip)
/// r_type=X86_64_RELOC_SIGNED_1, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3
/// 83 05 18 00 00 00 06
/// // assumes L0 is in third section and there is no previous non-local label.
/// // The rip-relative-offset of 0x00000018 is L0-address_of_next_instruction.
/// // address_of_next_instruction is the address of the relocation + 4 + 1.
/// // The +1 comes from SIGNED_1. This is used because the relocation is not
/// // at the end of the instruction.
///
/// .quad L1
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
/// 12 00 00 00 00 00 00 00
/// // assumes _prev is the first non-local label 0x12 bytes before L1
///
/// .quad L0
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=0, r_pcrel=0, r_symbolnum=3
/// 56 00 00 00 00 00 00 00
/// // assumes L0 is in third section, has an address of 0x00000056 in .o
/// // file, and there is no previous non-local label
///
/// .quad _foo - .
/// r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
/// EE FF FF FF FF FF FF FF
/// // assumes _prev is the first non-local label 0x12 bytes before this
/// // .quad
///
/// .quad _foo - L1
/// r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
/// EE FF FF FF FF FF FF FF
/// // assumes _prev is the first non-local label 0x12 bytes before L1
///
/// .quad L1 - _prev
/// // No relocations. This is an assembly time constant.
/// 12 00 00 00 00 00 00 00
/// // assumes _prev is the first non-local label 0x12 bytes before L1
///
///
///
/// In final linked images, there are only two valid relocation kinds:
///
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=1, r_symbolnum=sym_index
/// This tells dyld to add the address of a symbol to a pointer sized (8-byte)
/// piece of data (i.e on disk the 8-byte piece of data contains the addend). The
/// r_symbolnum contains the index into the symbol table of the target symbol.
///
/// r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=0, r_symbolnum=0
/// This tells dyld to adjust the pointer sized (8-byte) piece of data by the amount
/// the containing image was loaded from its base address (e.g. slide).
///
enum {
MachX8664RelocUnsigned, ///< for absolute addresses
MachX8664RelocSigned, ///< for signed 32-bit displacement
MachX8664RelocBranch, ///< a CALL/JMP instruction with 32-bit
///< displacement
MachX8664RelocGotLoad, ///< a MOVQ load of a GOT entry
MachX8664RelocGot, ///< other GOT references
MachX8664RelocSubtractor, ///< must be followed by a
///< MachX8664RelocUnsigned
MachX8664RelocSigned1, ///< for signed 32-bit displacement with
///< a -1 addend
MachX8664RelocSigned2, ///< for signed 32-bit displacement with
///< a -2 addend
MachX8664RelocSigned4, ///< for signed 32-bit displacement with
///< a -4 addend
MachX8664RelocThreadLocalVariable ///< for thread local variables
};
#endif // APPLE_MACHO_IMAGE_H