unit macho; { * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ } { converted by Dmitry Boyarintsev 2009 } {$i fpcdefs.inc} {$H+} interface {$IFDEF FPC} {$PACKRECORDS C} {$PACKENUM 4} {$ENDIF} // mach/$arch/machine.h // $arch can be: i386, x86_64, ppc, arm // currently used is i386 type integer_t = Integer; uint8_t = Byte; int16_t = SmallInt; uint16_t = Word; uint32_t = LongWord; int32_t = Integer; uint64_t = QWord; // mach/thread_status.h {$ifdef i386} {$endif i386} // mach/machine.h type cpu_type_t = integer_t; cpu_subtype_t = integer_t; cpu_threadtype_t = integer_t; const CPU_STATE_MAX = 4; CPU_STATE_USER = 0; CPU_STATE_SYSTEM = 1; CPU_STATE_IDLE = 2; CPU_STATE_NICE = 3; {* Capability bits used in the definition of cpu_type. } CPU_ARCH_MASK = $ff000000; { mask for architecture bits } CPU_ARCH_ABI64 = $01000000; { 64 bit ABI } { Machine types known by all. } CPU_TYPE_ANY = -1; CPU_TYPE_VAX = 1; CPU_TYPE_MC680x0 = 6; CPU_TYPE_X86 = 7; CPU_TYPE_I386 = CPU_TYPE_X86; { compatibility } CPU_TYPE_X86_64 = CPU_TYPE_X86 or CPU_ARCH_ABI64; // skip CPU_TYPE_MIPS = 8; CPU_TYPE_MC98000 = 10; CPU_TYPE_HPPA = 11; CPU_TYPE_ARM = 12; CPU_TYPE_ARM64 = CPU_TYPE_ARM or CPU_ARCH_ABI64; CPU_TYPE_MC88000 = 13; CPU_TYPE_SPARC = 14; CPU_TYPE_I860 = 15; // skip CPU_TYPE_ALPHA = 16; */ CPU_TYPE_POWERPC = 18; CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC or CPU_ARCH_ABI64; {* * Machine subtypes (these are defined here, instead of in a machine * dependent directory, so that any program can get all definitions * regardless of where is it compiled). *} {* * Capability bits used in the definition of cpu_subtype. *} CPU_SUBTYPE_MASK = $ff000000; { mask for feature flags } CPU_SUBTYPE_LIB64 = $80000000; { 64 bit libraries } {* * Object files that are hand-crafted to run on any * implementation of an architecture are tagged with * CPU_SUBTYPE_MULTIPLE. This functions essentially the same as * the "ALL" subtype of an architecture except that it allows us * to easily find object files that may need to be modified * whenever a new implementation of an architecture comes out. * * It is the responsibility of the implementor to make sure the * software handles unsupported implementations elegantly. *} CPU_SUBTYPE_MULTIPLE = -1; CPU_SUBTYPE_LITTLE_ENDIAN = 0; CPU_SUBTYPE_BIG_ENDIAN = 1; {* * Machine threadtypes. * This is none - not defined - for most machine types/subtypes. *} CPU_THREADTYPE_NONE = 0; {* * VAX subtypes (these do *not* necessary conform to the actual cpu * ID assigned by DEC available via the SID register). *} CPU_SUBTYPE_VAX_ALL = 0; CPU_SUBTYPE_VAX780 = 1; CPU_SUBTYPE_VAX785 = 2; CPU_SUBTYPE_VAX750 = 3; CPU_SUBTYPE_VAX730 = 4; CPU_SUBTYPE_UVAXI = 5; CPU_SUBTYPE_UVAXII = 6; CPU_SUBTYPE_VAX8200 = 7; CPU_SUBTYPE_VAX8500 = 8; CPU_SUBTYPE_VAX8600 = 9; CPU_SUBTYPE_VAX8650 = 10; CPU_SUBTYPE_VAX8800 = 11; CPU_SUBTYPE_UVAXIII = 12; {* * 680x0 subtypes * * The subtype definitions here are unusual for historical reasons. * NeXT used to consider 68030 code as generic 68000 code. For * backwards compatability: * * CPU_SUBTYPE_MC68030 symbol has been preserved for source code * compatability. * * CPU_SUBTYPE_MC680x0_ALL has been defined to be the same * subtype as CPU_SUBTYPE_MC68030 for binary comatability. * * CPU_SUBTYPE_MC68030_ONLY has been added to allow new object * files to be tagged as containing 68030-specific instructions. *} CPU_SUBTYPE_MC680x0_ALL = 1; CPU_SUBTYPE_MC68030 = 1; { compat } CPU_SUBTYPE_MC68040 = 2; CPU_SUBTYPE_MC68030_ONLY = 3; {* I386 subtypes *} CPU_SUBTYPE_I386_ALL = 3 + (0 shl 4); CPU_SUBTYPE_386 = 3 + (0 shl 4); CPU_SUBTYPE_486 = 4 + (0 shl 4); CPU_SUBTYPE_486SX = 4 + (8 shl 4); // 8 << 4 = 128 CPU_SUBTYPE_586 = 5 + (0 shl 4); CPU_SUBTYPE_PENT = 5 + (0 shl 4); CPU_SUBTYPE_PENTPRO = 6 + (1 shl 4); CPU_SUBTYPE_PENTII_M3 = 6 + (3 shl 4); CPU_SUBTYPE_PENTII_M5 = 6 + (5 shl 4); CPU_SUBTYPE_CELERON = 7 + (6 shl 4); CPU_SUBTYPE_CELERON_MOBILE = 7 + (7 shl 4); CPU_SUBTYPE_PENTIUM_3 = 8 + (0 shl 4); CPU_SUBTYPE_PENTIUM_3_M = 8 + (1 shl 4); CPU_SUBTYPE_PENTIUM_3_XEON = 8 + (2 shl 4); CPU_SUBTYPE_PENTIUM_M = 9 + (0 shl 4); CPU_SUBTYPE_PENTIUM_4 = 10 + (0 shl 4); CPU_SUBTYPE_PENTIUM_4_M = 10 + (1 shl 4); CPU_SUBTYPE_ITANIUM = 11 + (0 shl 4); CPU_SUBTYPE_ITANIUM_2 = 11 + (1 shl 4); CPU_SUBTYPE_XEON = 12 + (0 shl 4); CPU_SUBTYPE_XEON_MP = 12 + (1 shl 4); CPU_SUBTYPE_INTEL_FAMILY_MAX = 15; CPU_SUBTYPE_INTEL_MODEL_ALL = 0; {* X86 subtypes. *} CPU_SUBTYPE_X86_ALL = 3; CPU_SUBTYPE_X86_64_ALL = 3; CPU_SUBTYPE_X86_ARCH1 = 4; CPU_THREADTYPE_INTEL_HTT = 1; {* Mips subtypes. *} CPU_SUBTYPE_MIPS_ALL = 0; CPU_SUBTYPE_MIPS_R2300 = 1; CPU_SUBTYPE_MIPS_R2600 = 2; CPU_SUBTYPE_MIPS_R2800 = 3; CPU_SUBTYPE_MIPS_R2000a = 4; {* pmax *} CPU_SUBTYPE_MIPS_R2000 = 5; CPU_SUBTYPE_MIPS_R3000a = 6; { 3max *} CPU_SUBTYPE_MIPS_R3000 = 7; {* MC98000 (PowerPC) subtypes *} CPU_SUBTYPE_MC98000_ALL = 0; CPU_SUBTYPE_MC98601 = 1; {* * HPPA subtypes for Hewlett-Packard HP-PA family of * risc processors. Port by NeXT to 700 series. *} CPU_SUBTYPE_HPPA_ALL = 0; CPU_SUBTYPE_HPPA_7100 = 0; {* compat *} CPU_SUBTYPE_HPPA_7100LC = 1; {* MC88000 subtypes. *} CPU_SUBTYPE_MC88000_ALL = 0; CPU_SUBTYPE_MC88100 = 1; CPU_SUBTYPE_MC88110 = 2; {* SPARC subtypes *} CPU_SUBTYPE_SPARC_ALL = 0; {* I860 subtypes *} CPU_SUBTYPE_I860_ALL = 0; CPU_SUBTYPE_I860_860 = 1; {* PowerPC subtypes *} CPU_SUBTYPE_POWERPC_ALL = 0; CPU_SUBTYPE_POWERPC_601 = 1; CPU_SUBTYPE_POWERPC_602 = 2; CPU_SUBTYPE_POWERPC_603 = 3; CPU_SUBTYPE_POWERPC_603e = 4; CPU_SUBTYPE_POWERPC_603ev = 5; CPU_SUBTYPE_POWERPC_604 = 6; CPU_SUBTYPE_POWERPC_604e = 7; CPU_SUBTYPE_POWERPC_620 = 8; CPU_SUBTYPE_POWERPC_750 = 9; CPU_SUBTYPE_POWERPC_7400 = 10; CPU_SUBTYPE_POWERPC_7450 = 11; CPU_SUBTYPE_POWERPC_970 = 100; {* ARM subtypes *} CPU_SUBTYPE_ARM_ALL = 0; CPU_SUBTYPE_ARM_V4T = 5; CPU_SUBTYPE_ARM_V6 = 6; CPU_SUBTYPE_ARM_V5TEJ = 7; CPU_SUBTYPE_ARM_XSCALE = 8; {* * CPU families (sysctl hw.cpufamily) * * These are meant to identify the CPU's marketing name - an * application can map these to (possibly) localized strings. * NB: the encodings of the CPU families are intentionally arbitrary. * There is no ordering, and you should never try to deduce whether * or not some feature is available based on the family. * Use feature flags (eg, hw.optional.altivec) to test for optional * functionality. *} CPUFAMILY_UNKNOWN = 0; CPUFAMILY_POWERPC_G3 = $cee41549; CPUFAMILY_POWERPC_G4 = $77c184ae; CPUFAMILY_POWERPC_G5 = $ed76d8aa; CPUFAMILY_INTEL_6_13 = $aa33392b; CPUFAMILY_INTEL_6_14 = $73d67300; { "Intel Core Solo" and "Intel Core Duo" (32-bit Pentium-M with SSE3) } CPUFAMILY_INTEL_6_15 = $426f69ef; { "Intel Core 2 Duo" } CPUFAMILY_INTEL_6_23 = $78ea4fbc; { Penryn } CPUFAMILY_INTEL_6_26 = $6b5a4cd2; { Nehalem } CPUFAMILY_ARM_9 = $e73283ae; CPUFAMILY_ARM_11 = $8ff620d8; CPUFAMILY_ARM_XSCALE = $53b005f5; CPUFAMILY_INTEL_YONAH = CPUFAMILY_INTEL_6_14; CPUFAMILY_INTEL_MEROM = CPUFAMILY_INTEL_6_15; CPUFAMILY_INTEL_PENRYN = CPUFAMILY_INTEL_6_23; CPUFAMILY_INTEL_NEHALEM = CPUFAMILY_INTEL_6_26; CPUFAMILY_INTEL_CORE = CPUFAMILY_INTEL_6_14; CPUFAMILY_INTEL_CORE2 = CPUFAMILY_INTEL_6_15; // mach/vm_prot.h type vm_prot_t = Integer; const VM_PROT_NONE = $00; VM_PROT_READ = $01; {* read permission *} VM_PROT_WRITE = $02; {* write permission *} VM_PROT_EXECUTE = $04; {* execute permission *} {* * The default protection for newly-created virtual memory *} VM_PROT_DEFAULT = VM_PROT_READ or VM_PROT_WRITE; {* * The maximum privileges possible, for parameter checking. *} VM_PROT_ALL = VM_PROT_READ or VM_PROT_WRITE or VM_PROT_EXECUTE; {* * An invalid protection value. * Used only by memory_object_lock_request to indicate no change * to page locks. Using -1 here is a bad idea because it * looks like VM_PROT_ALL and then some. *} VM_PROT_NO_CHANGE = $08; {* * When a caller finds that he cannot obtain write permission on a * mapped entry, the following flag can be used. The entry will * be made "needs copy" effectively copying the object (using COW), * and write permission will be added to the maximum protections * for the associated entry. *} VM_PROT_COPY = $10; {* * Another invalid protection value. * Used only by memory_object_data_request upon an object * which has specified a copy_call copy strategy. It is used * when the kernel wants a page belonging to a copy of the * object, and is only asking the object as a result of * following a shadow chain. This solves the race between pages * being pushed up by the memory manager and the kernel * walking down the shadow chain. *} VM_PROT_WANTS_COPY = $10; { Constant for the magic field of the mach_header (32-bit architectures) the mach magic number } const MH_MAGIC = $feedface; MH_CIGAM = $cefaedfe; { NXSwapInt(MH_MAGIC) } type { * The 32-bit mach header appears at the very beginning of the object file for 32-bit architectures. } mach_header = record magic : uint32_t; { mach magic number identifier } cputype : cpu_type_t; { cpu specifier } cpusubtype : cpu_subtype_t; { machine specifier } filetype : uint32_t; { type of file } ncmds : uint32_t; { number of load commands } sizeofcmds : uint32_t; { the size of all the load commands } flags : uint32_t; { flags } end; pmach_header = ^mach_header; type {* The 64-bit mach header appears at the very beginning of object files for * 64-bit architectures. } mach_header_64 = record magic : uint32_t; { mach magic number identifier } cputype : cpu_type_t; { cpu specifier } cpusubtype : cpu_subtype_t; { machine specifier } filetype : uint32_t; { type of file } ncmds : uint32_t; { number of load commands } sizeofcmds : uint32_t; { the size of all the load commands } flags : uint32_t; { flags } reserved : uint32_t; { reserved } end; pmach_header_64 = ^mach_header_64; { Constant for the magic field of the mach_header_64 (64-bit architectures) } { the 64-bit mach magic number } const MH_MAGIC_64 = $feedfacf; MH_CIGAM_64 = $cffaedfe; { NXSwapInt(MH_MAGIC_64) } {* 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 } const MH_OBJECT = $1; { relocatable object file } MH_EXECUTE = $2; { demand paged executable file } MH_FVMLIB = $3; { fixed VM shared library file } MH_CORE = $4; { core file } MH_PRELOAD = $5; { preloaded executable file } MH_DYLIB = $6; { dynamically bound shared library } MH_DYLINKER = $7; { dynamic link editor } MH_BUNDLE = $8; { dynamically bound bundle file } MH_DYLIB_STUB = $9; { shared library stub for static } MH_DSYM = $a; { linking only, no section contents } { companion file with only debug sections } const { Constants for the flags field of the mach_header } MH_NOUNDEFS = $1; { the object file has no undefined references } MH_INCRLINK = $2; { the object file is the output of an incremental link against a base file and can't be link edited again } MH_DYLDLINK = $4; { the object file is input for the dynamic linker and can't be staticly link edited again } MH_BINDATLOAD = $8; { the object file's undefined references are bound by the dynamic linker when loaded. } MH_PREBOUND = $10; { the file has its dynamic undefined references prebound. } MH_SPLIT_SEGS = $20; { the file has its read-only and read-write segments split } MH_LAZY_INIT = $40; { the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) } MH_TWOLEVEL = $80; { the image is using two-level name space bindings } MH_FORCE_FLAT = $100; { the executable is forcing all images to use flat name space bindings } MH_NOMULTIDEFS = $200; { this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used. } MH_NOFIXPREBINDING = $400; { do not have dyld notify the prebinding agent about this executable } MH_PREBINDABLE = $800; { the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set. } MH_ALLMODSBOUND = $1000; { indicates that this binary binds to all two-level namespace modules of } { its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set. } MH_SUBSECTIONS_VIA_SYMBOLS = $2000; { safe to divide up the sections into sub-sections via symbols for dead code stripping } MH_CANONICAL = $4000; { the binary has been canonicalized via the unprebind operation } MH_WEAK_DEFINES = $8000; { the final linked image contains external weak symbols } MH_BINDS_TO_WEAK = $10000; { the final linked image uses weak symbols } MH_ALLOW_STACK_EXECUTION = $20000; { When this bit is set, all stacks in the task will be given stack } { execution privilege. Only used in MH_EXECUTE filetypes. } MH_ROOT_SAFE = $40000; { When this bit is set, the binary declares it is safe for use in processes with uid zero } MH_SETUID_SAFE = $80000; { When this bit is set, the binary declares it is safe for use in processes when issetugid() is true } MH_NO_REEXPORTED_DYLIBS = $100000; { When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported } MH_PIE = $200000; { When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes. } { * The load commands directly follow the mach_header. The total size of all * of the commands is given by the sizeofcmds field in the mach_header. All * load commands must have as their first two fields cmd and cmdsize. The cmd * field is filled in with a constant for that command type. Each command type * has a structure specifically for it. The cmdsize field is the size in bytes * of the particular load command structure plus anything that follows it that * is a part of the load command (i.e. section structures, strings, etc.). To * advance to the next load command the cmdsize can be added to the offset or * pointer of the current load command. The cmdsize for 32-bit architectures * MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple * of 8 bytes (these are forever the maximum alignment of any load commands). * The padded bytes must be zero. All tables in the object file must also * follow these rules so the file can be memory mapped. Otherwise the pointers * to these tables will not work well or at all on some machines. With all * padding zeroed like objects will compare byte for byte. } type load_command = record cmd : uint32_t; { type of load command } cmdsize : uint32_t; { total size of command in bytes } end; pload_command = ^load_command; { * 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 * LC_REQ_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. } const LC_REQ_DYLD = $80000000; { Constants for the cmd field of all load commands, the type } const LC_SEGMENT = $1; { segment of this file to be mapped } LC_SYMTAB = $2; { link-edit stab symbol table info } LC_SYMSEG = $3; { link-edit gdb symbol table info (obsolete) } LC_THREAD = $4; { thread } LC_UNIXTHREAD = $5; { unix thread (includes a stack) } LC_LOADFVMLIB = $6; { load a specified fixed VM shared library } LC_IDFVMLIB = $7; { fixed VM shared library identification } LC_IDENT = $8; { object identification info (obsolete) } LC_FVMFILE = $9; { fixed VM file inclusion (internal use) } LC_PREPAGE = $a; { prepage command (internal use) } LC_DYSYMTAB = $b; { dynamic link-edit symbol table info } LC_LOAD_DYLIB = $c; { load a dynamically linked shared library } LC_ID_DYLIB = $d; { dynamically linked shared lib ident } LC_LOAD_DYLINKER = $e; { load a dynamic linker } LC_ID_DYLINKER = $f; { dynamic linker identification } LC_PREBOUND_DYLIB = $10; { modules prebound for a dynamically linked shared library } LC_ROUTINES = $11; { image routines } LC_SUB_FRAMEWORK = $12; { sub framework } LC_SUB_UMBRELLA = $13; { sub umbrella } LC_SUB_CLIENT = $14; { sub client } LC_SUB_LIBRARY = $15; { sub library } LC_TWOLEVEL_HINTS = $16; { two-level namespace lookup hints } LC_PREBIND_CKSUM = $17; { prebind checksum } LC_LOAD_WEAK_DYLIB = $18 or LC_REQ_DYLD; { load a dynamically linked shared library that is allowed to be missing (all symbols are weak imported). } LC_SEGMENT_64 = $19; { 64-bit segment of this file to be mapped } LC_ROUTINES_64 = $1a; { 64-bit image routines } LC_UUID = $1b; { the uuid } LC_RPATH = $1c or LC_REQ_DYLD; { runpath additions } LC_CODE_SIGNATURE = $1d; { local of code signature } LC_SEGMENT_SPLIT_INFO = $1e; { local of info to split segments } LC_REEXPORT_DYLIB = $1f or LC_REQ_DYLD; { load and re-export dylib } LC_LAZY_LOAD_DYLIB = $20; { delay load of dylib until first use } LC_ENCRYPTION_INFO = $21; { encrypted segment information } { * 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. } { offset to the string } {$ifndef __LP64__} { pointer to the string } {$endif} type lc_str = record case longint of 0 : ( offset : uint32_t ); 1 : ( ptr : ^char ); end; { * The segment load command indicates that a part of this file is to be * mapped into the task's address space. 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 specified * 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 } segment_command = record cmd : uint32_t; { LC_SEGMENT } cmdsize : uint32_t; { includes sizeof section structs } segname : array[0..15] of char; { segment name } vmaddr : uint32_t; { memory address of this segment } vmsize : uint32_t; { memory size of this segment } fileoff : uint32_t; { file offset of this segment } filesize : uint32_t; { amount to map from the file } maxprot : vm_prot_t; { maximum VM protection } initprot : vm_prot_t; { initial VM protection } nsects : uint32_t; { number of sections in segment } flags : uint32_t; { flags } end; psegment_command = ^segment_command; { * The 64-bit segment load command indicates that a part of this file is to be * mapped into a 64-bit task's address space. 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 } segment_command_64 = record cmd : uint32_t; { LC_SEGMENT_64 } cmdsize : uint32_t; { includes sizeof section_64 structs } segname : array[0..15] of char; { segment name } vmaddr : uint64_t; { memory address of this segment } vmsize : uint64_t; { memory size of this segment } fileoff : uint64_t; { file offset of this segment } filesize : uint64_t; { amount to map from the file } maxprot : vm_prot_t; { maximum VM protection } initprot : vm_prot_t; { initial VM protection } nsects : uint32_t; { number of sections in segment } flags : uint32_t; { flags } end; psegment_command_64 = ^segment_command_64; { Constants for the flags field of the segment_command } const SG_HIGHVM = $1; { 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) } SG_FVMLIB = $2; { this segment is the VM that is allocated by } { a fixed VM library, for overlap checking in } { the link editor } SG_NORELOC = $4; { this segment has nothing that was relocated } { in it and nothing relocated to it, that is } { it maybe safely replaced without relocation } SG_PROTECTED_VERSION_1 = $8; { 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. } {* A segment is made up of zero or more sections. Non-MH_OBJECT files have * all of their segments with the proper sections in each, and padded to the * specified segment alignment when produced by the link editor. The first * segment of a MH_EXECUTE and MH_FVMLIB 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 S_GB_ZEROFILL, can only be in a segment with sections of this type. * These segments are then placed after all other segments. * * The MH_OBJECT format has all of its sections in one segment for * compactness. There is no padding to a specified segment boundary and the * mach_header and load commands are not part of the segment. * * Sections with the same section name, sectname, going into the same segment, * segname, 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 specified 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 . } type { for 32-bit architectures } section = record sectname : array[0..15] of char; { name of this section } segname : array[0..15] of char; { segment this section goes in } addr : uint32_t; { memory address of this section } size : uint32_t; { size in bytes of this section } offset : uint32_t; { file offset of this section } align : uint32_t; { section alignment (power of 2) } reloff : uint32_t; { file offset of relocation entries } nreloc : uint32_t; { number of relocation entries } flags : uint32_t; { flags (section type and attributes) } reserved1 : uint32_t; { reserved (for offset or index) } reserved2 : uint32_t; { reserved (for count or sizeof) } end; psection = ^section; { for 64-bit architectures } section_64 = record sectname : array[0..15] of char; { name of this section } segname : array[0..15] of char; { segment this section goes in } addr : uint64_t; { memory address of this section } size : uint64_t; { size in bytes of this section } offset : uint32_t; { file offset of this section } align : uint32_t; { section alignment (power of 2) } reloff : uint32_t; { file offset of relocation entries } nreloc : uint32_t; { number of relocation entries } flags : uint32_t; { flags (section type and attributes) } reserved1 : uint32_t; { reserved (for offset or index) } reserved2 : uint32_t; { reserved (for count or sizeof) } reserved3 : uint32_t; { reserved } end; psection_64 = ^section_64; {* 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). } { 256 section types } const SECTION_TYPE = $000000ff; { Constants for the type of a section } SECTION_ATTRIBUTES = $ffffff00; { 24 section attributes } S_REGULAR = $0; { regular section } S_ZEROFILL = $1; { zero fill on demand section } S_CSTRING_LITERALS = $2; { section with only literal C strings } S_4BYTE_LITERALS = $3; { section with only 4 byte literals } S_8BYTE_LITERALS = $4; { section with only 8 byte literals } S_LITERAL_POINTERS = $5; { section with only pointers to literals } {* 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. } S_NON_LAZY_SYMBOL_POINTERS = $6; { section with only non-lazy symbol pointers } S_LAZY_SYMBOL_POINTERS = $7; { section with only lazy symbol pointers } S_SYMBOL_STUBS = $8; { section with only symbol stubs, byte size of stub in the reserved2 field } S_MOD_INIT_FUNC_POINTERS = $9; { section with only function pointers for initialization } S_MOD_TERM_FUNC_POINTERS = $a; { section with only function pointers for termination } S_COALESCED = $b; { section contains symbols that are to be coalesced } S_GB_ZEROFILL = $c; { zero fill on demand section (that can be larger than 4 gigabytes) } S_INTERPOSING = $d; { section with only pairs of function pointers for interposing } S_16BYTE_LITERALS = $e; { section with only 16 byte literals } S_DTRACE_DOF = $f; { section contains DTrace Object Format } S_LAZY_DYLIB_SYMBOL_POINTERS = $10; { section with only lazy symbol pointers to lazy loaded dylibs } {* Constants for the section attributes part of the flags field of a section structure. } SECTION_ATTRIBUTES_USR = $ff000000; { User setable attributes } S_ATTR_PURE_INSTRUCTIONS = $80000000; { section contains only true machine instructions } S_ATTR_NO_TOC = $40000000; { section contains coalesced symbols } { that are not to be in a ranlib table of contents } S_ATTR_STRIP_STATIC_SYMS = $20000000; { ok to strip static symbols this section } { in files with the MH_DYLDLINK flag } S_ATTR_NO_DEAD_STRIP = $10000000; { no dead stripping } S_ATTR_LIVE_SUPPORT = $08000000; { blocks are live if they reference live blocks } S_ATTR_SELF_MODIFYING_CODE = $04000000; { Used with i386 code stubs written on by dyld } { * If a segment contains any sections marked with S_ATTR_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. } { a debug section } S_ATTR_DEBUG = $02000000; { system setable attributes } SECTION_ATTRIBUTES_SYS = $00ffff00; { section contains some machine instructions } S_ATTR_SOME_INSTRUCTIONS = $00000400; { section has external relocation entries } S_ATTR_EXT_RELOC = $00000200; { section has local relocation entries } S_ATTR_LOC_RELOC = $00000100; { * The names of segments and sections in them are mostly meaningless to the * link-editor. But there are few things to support traditional UNIX * executables that require the link-editor and assembler to use some names * agreed upon by convention. * * The initial protection of the "__TEXT" segment has write protection turned * off (not writeable). * * The link-editor will allocate common symbols at the end of the "__common" * section in the "__DATA" segment. It will create the section and segment * if needed. } { The currently known segment names and the section names in those segments } SEG_PAGEZERO = '__PAGEZERO'; { the pagezero segment which has no } { protections and catches NULL references for MH_EXECUTE files } SEG_TEXT = '__TEXT'; { the tradition UNIX text segment } SECT_TEXT = '__text'; { the real text part of the text } SECT_FVMLIB_INIT0 = '__fvmlib_init0'; { the fvmlib initialization section } SECT_FVMLIB_INIT1 = '__fvmlib_init1'; { the section following the fvmlib initialization section } SEG_DATA = '__DATA'; { the tradition UNIX data segment } SECT_DATA = '__data'; { the real initialized data section no padding, no bss overlap } SECT_BSS = '__bss'; { the real uninitialized data section no padding } SECT_COMMON = '__common'; { the section common symbols are allocated in by the link editor } SEG_OBJC = '__OBJC'; { objective-C runtime segment } SECT_OBJC_SYMBOLS = '__symbol_table'; { symbol table } SECT_OBJC_MODULES = '__module_info'; { module information } SECT_OBJC_STRINGS = '__selector_strs'; { string table } SECT_OBJC_REFS = '__selector_refs'; { string table } SEG_ICON = '__ICON'; { the icon segment } SECT_ICON_HEADER = '__header'; { the icon headers } SECT_ICON_TIFF = '__tiff'; { the icons in tiff format } SEG_LINKEDIT = '__LINKEDIT'; { the segment containing all structs } { created and maintained by the linkeditor. } { Created with -seglinkedit option to ld(1) for MH_EXECUTE and FVMLIB file types only } SEG_UNIXSTACK = '__UNIXSTACK'; { the unix stack segment } SEG_IMPORT = '__IMPORT'; { the segment for the self (dyld) } { modifing code stubs that has read, write and execute permissions } {* 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). } type fvmlib = record name : lc_str; { library's target pathname } minor_version : uint32_t; { library's minor version number } header_addr : uint32_t; { library's header address } end; {* 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). } fvmlib_command = record cmd : uint32_t; { LC_IDFVMLIB or LC_LOADFVMLIB } cmdsize : uint32_t; { includes pathname string } fvmlib : fvmlib; { the library identification } end; pfvmlib_command = ^fvmlib_command; {* 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. } dylib = record name : lc_str; { library's path name } timestamp : uint32_t; { library's build time stamp } current_version : uint32_t; { library's current version number } compatibility_version : uint32_t; { library's compatibility vers number } end; {* 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. } dylib_command = record cmd : uint32_t; { LC_ID_DYLIB, LC_LOAD_DYLIB,WEAK_DYLIB, LC_REEXPORT_DYLIB } cmdsize : uint32_t; { includes pathname string } dylib : dylib; { the library identification } end; pdylib_command = ^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. } sub_framework_command = record cmd : uint32_t; { LC_SUB_FRAMEWORK } cmdsize : uint32_t; { includes umbrella string } umbrella : lc_str; { the umbrella framework name } end; psub_framework_command = ^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". } sub_client_command = record cmd : uint32_t; { LC_SUB_CLIENT } cmdsize : uint32_t; { includes client string } client : lc_str; { the client name } end; psub_client_command = ^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 * 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. } sub_umbrella_command = record cmd : uint32_t; { LC_SUB_UMBRELLA } cmdsize : uint32_t; { includes sub_umbrella string } sub_umbrella : lc_str; { the sub_umbrella framework name } end; {* 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".} sub_library_command = record cmd : uint32_t; { LC_SUB_LIBRARY } cmdsize : uint32_t; { includes sub_library string } sub_library : lc_str; { the sub_library name } end; psub_library_command = ^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 } prebound_dylib_command = record cmd : uint32_t; { LC_PREBOUND_DYLIB } cmdsize : uint32_t; { includes strings } name : lc_str; { library's path name } nmodules : uint32_t; { number of modules in library } linked_modules : lc_str; { bit vector of linked modules } end; pprebound_dylib_command = ^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.} dylinker_command = record cmd : uint32_t; { LC_ID_DYLINKER or LC_LOAD_DYLINKER } cmdsize : uint32_t; { includes pathname string } name : lc_str; { dynamic linker's path name } end; pdylinker_command = ^dylinker_command; { * 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_t * 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 . * 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. } thread_command = record cmd : uint32_t; { LC_THREAD or LC_UNIXTHREAD } cmdsize : uint32_t; { total size of this command } flavor : uint32_t; { uint32_t flavor flavor of thread state } count : uint32_t; { uint32_t count count of longs in thread state } { struct XXX_thread_state state thread state for this flavor } { ... } end; pthread_command = ^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 } routines_command = record cmd : uint32_t; { LC_ROUTINES } cmdsize : uint32_t; { total size of this command } init_address : uint32_t; { address of initialization routine } init_module : uint32_t; { index into the module table that the init routine is defined in } reserved1 : uint32_t; reserved2 : uint32_t; reserved3 : uint32_t; reserved4 : uint32_t; reserved5 : uint32_t; reserved6 : uint32_t; end; proutines_command = ^routines_command; { * The 64-bit routines command. Same use as above. } { for 64-bit architectures } routines_command_64 = record cmd : uint32_t; { LC_ROUTINES_64 } cmdsize : uint32_t; { total size of this command } init_address : uint64_t; { address of initialization routine } init_module : uint64_t; { index into the module table that } { the init routine is defined in } reserved1 : uint64_t; reserved2 : uint64_t; reserved3 : uint64_t; reserved4 : uint64_t; reserved5 : uint64_t; reserved6 : uint64_t; end; proutines_command_64 = ^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 * and . } symtab_command = record cmd : uint32_t; { LC_SYMTAB } cmdsize : uint32_t; { sizeof(struct symtab_command) } symoff : uint32_t; { symbol table offset } nsyms : uint32_t; { number of symbol table entries } stroff : uint32_t; { string table offset } strsize : uint32_t; { string table size in bytes } end; psymtab_command = ^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. } dysymtab_command = record cmd : uint32_t; { LC_DYSYMTAB } cmdsize : uint32_t; { sizeof(struct dysymtab_command) } { * 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). } ilocalsym : uint32_t; { index to local symbols } nlocalsym : uint32_t; { number of local symbols } iextdefsym : uint32_t; { index to externally defined symbols } nextdefsym : uint32_t; { number of externally defined symbols } iundefsym : uint32_t; { index to undefined symbols } nundefsym : uint32_t; { 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. } tocoff : uint32_t; { file offset to table of contents } ntoc : uint32_t; { number of entries in table of contents } { * 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. } modtaboff : uint32_t; { file offset to module table } nmodtab : uint32_t; { 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. } extrefsymoff : uint32_t; { offset to referenced symbol table } nextrefsyms : uint32_t; { number of referenced symbol table entries } { * 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. } indirectsymoff : uint32_t; { file offset to the indirect symbol table } nindirectsyms : uint32_t; { number of indirect symbol table entries } { * 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). } extreloff : uint32_t; { offset to external relocation entries } nextrel : uint32_t; { number of external relocation entries } { * 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). } locreloff : uint32_t; { offset to local relocation entries } nlocrel : uint32_t; { number of local relocation entries } end; { * 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. } const INDIRECT_SYMBOL_LOCAL = $80000000; INDIRECT_SYMBOL_ABS = $40000000; type dylib_table_of_contents = record { a table of contents entry } symbol_index : uint32_t; { the defined external symbol (index into the symbol table) } module_index : uint32_t; { index into the module table this symbol is defined in } end; dylib_module = record { a module table entry } module_name : uint32_t; { the module name (index into string table) } iextdefsym : uint32_t; { index into externally defined symbols } nextdefsym : uint32_t; { number of externally defined symbols } irefsym : uint32_t; { index into reference symbol table } nrefsym : uint32_t; { number of reference symbol table entries } ilocalsym : uint32_t; { index into symbols for local symbols } nlocalsym : uint32_t; { number of local symbols } iextrel : uint32_t; { index into external relocation entries } nextrel : uint32_t; { number of external relocation entries } iinit_iterm : uint32_t; { low 16 bits are the index into the init section, high 16 bits are the index into the term section } ninit_nterm : uint32_t; { low 16 bits are the number of init section entries, high 16 bits are the number of term section entries } objc_module_info_addr : uint32_t; { for this module address of the start of the (__OBJC,__module_info) section } objc_module_info_size : uint32_t; { for this module size of the (__OBJC,__module_info) section } end; dylib_module_64 = record { a 64-bit module table entry } module_name : uint32_t; { the module name (index into string table) } iextdefsym : uint32_t; { index into externally defined symbols } nextdefsym : uint32_t; { number of externally defined symbols } irefsym : uint32_t; { index into reference symbol table } nrefsym : uint32_t; { number of reference symbol table entries } ilocalsym : uint32_t; { index into symbols for local symbols } nlocalsym : uint32_t; { number of local symbols } iextrel : uint32_t; { index into external relocation entries } nextrel : uint32_t; { number of external relocation entries } iinit_iterm : uint32_t; { low 16 bits are the index into the init section, high 16 bits are the index into the term section } ninit_nterm : uint32_t; { low 16 bits are the number of init section entries, high 16 bits are the number of term section entries } objc_module_info_size : uint32_t; { for this module size of the (__OBJC,__module_info) section } objc_module_info_addr : uint64_t; { for this module address of the start of the (__OBJC,__module_info) section } end; { * The entries in the reference symbol table are used when loading the module * (both by the static and dynamic link editors) and if the module is unloaded * or replaced. Therefore all external symbols (defined and undefined) are * listed in the module's reference table. The flags describe the type of * reference that is being made. The constants for the flags are defined in * as they are also used for symbol table entries. } { index into the symbol table } { flags to indicate the type of reference } dylib_reference = record flag0 : longint; end; { const bm_dylib_reference_isym = $FFFFFF; bp_dylib_reference_isym = 0; bm_dylib_reference_flags = $FF000000; bp_dylib_reference_flags = 24; function isym(var a : dylib_reference) : uint32_t; procedure set_isym(var a : dylib_reference; __isym : uint32_t); function flags(var a : dylib_reference) : uint32_t; procedure set_flags(var a : dylib_reference; __flags : uint32_t);} {* The twolevel_hints_command contains the offset and number of hints in the * two-level namespace lookup hints table.} type twolevel_hints_command = record cmd : uint32_t; { LC_TWOLEVEL_HINTS } cmdsize : uint32_t; { sizeof(struct twolevel_hints_command) } offset : uint32_t; { offset to the hint table } nhints : uint32_t; { number of hints in the hint table } end; { * 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. } { index into the sub images } { index into the table of contents } twolevel_hint = record flag0 : longint; end; { const bm_twolevel_hint_isub_image = $FF; bp_twolevel_hint_isub_image = 0; bm_twolevel_hint_itoc = $FFFFFF00; bp_twolevel_hint_itoc = 8; function isub_image(var a : twolevel_hint) : uint32_t; procedure set_isub_image(var a : twolevel_hint; __isub_image : uint32_t); function itoc(var a : twolevel_hint) : uint32_t; procedure set_itoc(var a : twolevel_hint; __itoc : uint32_t); } type {* 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. } prebind_cksum_command = record cmd : uint32_t; { LC_PREBIND_CKSUM } cmdsize : uint32_t; { sizeof(struct prebind_cksum_command) } cksum : uint32_t; { the check sum or zero } end; pprebind_cksum_command = ^prebind_cksum_command; {* The uuid load command contains a single 128-bit unique random number that * identifies an object produced by the static link editor. } uuid_command = record cmd : uint32_t; { LC_UUID } cmdsize : uint32_t; { sizeof(struct uuid_command) } uuid : array[0..15] of uint8_t; { the 128-bit uuid } end; puuid_command = ^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.} rpath_command = record cmd : uint32_t; { LC_RPATH } cmdsize : uint32_t; { includes string } path : lc_str; { path to add to run path } end; prpath_command = ^rpath_command; {* The linkedit_data_command contains the offsets and sizes of a blob * of data in the __LINKEDIT segment.} linkedit_data_command = record cmd : uint32_t; { LC_CODE_SIGNATURE or LC_SEGMENT_SPLIT_INFO } cmdsize : uint32_t; { sizeof(struct linkedit_data_command) } dataoff : uint32_t; { file offset of data in __LINKEDIT segment } datasize : uint32_t; { file size of data in __LINKEDIT segment } end; plinkedit_data_command = ^linkedit_data_command; {* The encryption_info_command contains the file offset and size of an * of an encrypted segment.} encryption_info_command = record cmd : uint32_t; { LC_ENCRYPTION_INFO } cmdsize : uint32_t; { sizeof(struct encryption_info_command) } cryptoff : uint32_t; { file offset of encrypted range } cryptsize : uint32_t; { file size of encrypted range } cryptid : uint32_t; { which enryption system, 0 means not-encrypted yet } end; pencryption_info_command = ^encryption_info_command; {* The symseg_command contains the offset and size of the GNU style * symbol table information as described in the header file . * 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). } symseg_command = record cmd : uint32_t; { LC_SYMSEG } cmdsize : uint32_t; { sizeof(struct symseg_command) } offset : uint32_t; { symbol segment offset } size : uint32_t; { symbol segment size in bytes } end; psymseg_command = ^symseg_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).} ident_command = record cmd : uint32_t; { LC_IDENT } cmdsize : uint32_t; { strings that follow this command } end; pident_command = ^ident_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). } fvmfile_command = record cmd : uint32_t; { LC_FVMFILE } cmdsize : uint32_t; { includes pathname string } name : lc_str; { files pathname } header_addr : uint32_t; { files virtual address } end; pfvmfile_command = ^fvmfile_command; {* This header file describes the structures of the file format for "fat" * architecture specific file (wrapper design). At the begining of the file * there is one fat_header structure followed by a number of fat_arch * structures. For each architecture in the file, specified by a pair of * cputype and cpusubtype, the fat_header describes the file offset, file * size and alignment in the file of the architecture specific member. * The padded bytes in the file to place each member on it's specific alignment * are defined to be read as zeros and can be left as "holes" if the file system * can support them as long as they read as zeros. * * All structures defined here are always written and read to/from disk * in big-endian order.} {* is needed here for the cpu_type_t and cpu_subtype_t types * and contains the constants for the possible values of these types.} const FAT_MAGIC = $cafebabe; FAT_CIGAM = $bebafeca; type fat_header = record magic : uint32_t; { FAT_MAGIC } nfat_arch : uint32_t; { number of structs that follow } end; fat_arch = record cputype : cpu_type_t; { cpu specifier (int) } cpusubtype : cpu_subtype_t; { machine specifier (int) } offset : uint32_t; { file offset to this object file } size : uint32_t; { size of this object file } align : uint32_t; { alignment as a power of 2 } end; { * 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. } type nlist = record n_un : record case longint of {$ifndef __LP64__} 0 : ( n_name : Pchar ); { for use when in-core } {$endif} 1 : ( n_strx : int32_t ); { index into the string table } end; n_type : uint8_t; { type flag, see below } n_sect : uint8_t; { section number or NO_SECT } n_desc : int16_t; { see } n_value : uint32_t; { value of this symbol (or stab offset) } end; pnlist = ^nlist; {* This is the symbol table entry structure for 64-bit architectures.} nlist_64 = record n_un : record case longint of 0 : ( n_strx : uint32_t ); { index into the string table } end; n_type : uint8_t; { type flag, see below } n_sect : uint8_t; { section number or NO_SECT } n_desc : uint16_t; { see } n_value : uint64_t; { value of this symbol (or stab offset) } end; pnlist_64 = ^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.} const N_STAB = $e0; { if any of these bits set, a symbolic debugging entry } N_PEXT = $10; { private external symbol bit } N_TYPE = $0e; { mask for the type bits } N_EXT = $01; { 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 } {* Values for N_TYPE bits of the n_type field. } N_UNDF = $0; { undefined, n_sect == NO_SECT } N_ABS = $2; { absolute, n_sect == NO_SECT } N_SECT = $e; { defined in section number n_sect } N_PBUD = $c; { prebound undefined (defined in a dylib) } N_INDR = $a; { 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.} NO_SECT = 0; { symbol is not in any section } MAX_SECT = 255; { 1 thru 255 inclusive } {* Common symbols are represented by undefined (N_UNDF) external (N_EXT) types * who's values (n_value) are non-zero. In which case the value of the n_value * field is the size (in bytes) of the common symbol. The n_sect field is set * to NO_SECT. The alignment of a common symbol may be set as a power of 2 * between 2^1 and 2^15 as part of the n_desc field using the macros below. If * the alignment is not set (a value of zero) then natural alignment based on * the size is used.} { ----- Process manually ----- #define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f) #define SET_COMM_ALIGN(n_desc,align) \ (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8)) } {* To support the lazy binding of undefined symbols in the dynamic link-editor, * the undefined symbols in the symbol table (the nlist structures) are marked * with the indication if the undefined reference is a lazy reference or * non-lazy reference. If both a non-lazy reference and a lazy reference is * made to the same symbol the non-lazy reference takes precedence. A reference * is lazy only when all references to that symbol are made through a symbol * pointer in a lazy symbol pointer section. * * The implementation of marking nlist structures in the symbol table for * undefined symbols will be to use some of the bits of the n_desc field as a * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field * of an nlist structure for an undefined symbol to determine the type of * undefined reference (lazy or non-lazy). * * The constants for the REFERENCE FLAGS are propagated to the reference table * in a shared library file. In that case the constant for a defined symbol, * REFERENCE_FLAG_DEFINED, is also used.} { Reference type bits of the n_desc field of undefined symbols } REFERENCE_TYPE = $7; { types of references } REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0; REFERENCE_FLAG_UNDEFINED_LAZY = 1; REFERENCE_FLAG_DEFINED = 2; REFERENCE_FLAG_PRIVATE_DEFINED = 3; REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4; REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5; {* To simplify stripping of objects that use are used with the dynamic link * editor, the static link editor marks the symbols defined an object that are * referenced by a dynamicly bound object (dynamic shared libraries, bundles). * With this marking strip knows not to strip these symbols.} REFERENCED_DYNAMICALLY = $0010; {* For images created by the static link editor with the -twolevel_namespace * option in effect the flags field of the mach header is marked with * MH_TWOLEVEL. And the binding of the undefined references of the image are * determined by the static link editor. Which library an undefined symbol is * bound to is recorded by the static linker in the high 8 bits of the n_desc * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded * references the libraries listed in the Mach-O's LC_LOAD_DYLIB load commands * in the order they appear in the headers. The library ordinals start from 1. * For a dynamic library that is built as a two-level namespace image the * undefined references from module defined in another use the same nlist struct * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For * defined symbols in all images they also must have the library ordinal set to * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable * image for references from plugins that refer to the executable that loads * them. * * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace * image that are looked up by the dynamic linker with flat namespace semantics. * This ordinal was added as a feature in Mac OS X 10.3 by reducing the * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries * or binaries built with older tools to have 0xfe (254) dynamic libraries. In * this case the ordinal value 0xfe (254) must be treated as a library ordinal * for compatibility.} { was #define dname(params) para_def_expr } { argument types are unknown } { return type might be wrong } // function GET_LIBRARY_ORDINAL(n_desc : longint) : longint; { -- Process Manually --- #define SET_LIBRARY_ORDINAL(n_desc,ordinal) \ (n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)) } const SELF_LIBRARY_ORDINAL = $0; MAX_LIBRARY_ORDINAL = $fd; DYNAMIC_LOOKUP_ORDINAL = $fe; EXECUTABLE_ORDINAL = $ff; {* 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.} N_NO_DEAD_STRIP = $0020; { 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. } N_DESC_DISCARDED = $0020; { symbol is discarded } {* 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. } N_WEAK_REF = $0040; { symbol is weak referenced } {* 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. } N_WEAK_DEF = $0080; { coalesed symbol is a weak definition } {* 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. } N_REF_TO_WEAK = $0080; { reference to a weak symbol } {* The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is * a defintion of a Thumb function. } N_ARM_THUMB_DEF = $0008; { symbol is a Thumb function (ARM) } {* There are two known orders of table of contents for archives. The first is * the order ranlib(1) originally produced and still produces without any * options. This table of contents has the archive member name "__.SYMDEF" * This order has the ranlib structures in the order the objects appear in the * archive and the symbol names of those objects in the order of symbol table. * The second know order is sorted by symbol name and is produced with the -s * option to ranlib(1). This table of contents has the archive member name * "__.SYMDEF SORTED" and many programs (notably the 1.0 version of ld(1) can't * tell the difference between names because of the imbedded blank in the name * and works with either table of contents). This second order is used by the * post 1.0 link editor to produce faster linking. The original 1.0 version of * ranlib(1) gets confused when it is run on a archive with the second type of * table of contents because it and ar(1) which it uses use different ways to * determined the member name (ar(1) treats all blanks in the name as * significant and ranlib(1) only checks for the first one).} const SYMDEF = '__.SYMDEF'; SYMDEF_SORTED = '__.SYMDEF SORTED'; { * Structure of the __.SYMDEF table of contents for an archive. * __.SYMDEF begins with a long giving the size in bytes of the ranlib * structures which immediately follow, and then continues with a string * table consisting of a long giving the number of bytes of strings which * follow and then the strings themselves. The ran_strx fields index the * string table whose first byte is numbered 0. } type ranlib = record ran_un : record case longint of 0 : ( ran_strx : uint32_t ); 1 : ( ran_name : ^char ); end; ran_off : uint32_t; end; type {* 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. } relocation_info = record r_address : int32_t; { offset in the section to what is being relocated } r_info : longint; // r_symbolnum:24, {* symbol index if r_extern == 1 or section ordinal if r_extern == 0 *} // r_pcrel:1; {* was relocated pc relative already *} // r_length:2; {* 0=byte, 1=word, 2=long, 3=quad *} // r_extern:1; {* does not include value of sym referenced *} // r_type:4; {* if not 0, machine specific relocation type *} end; { absolute relocation type for Mach-O files } const R_ABS = 0; R_SCATTERED = $80000000; { 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 } { * 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 about the r_address feild * 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 R_ABS 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. } { * 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. } { * 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). } type scattered_relocation_info = record {$ifdef ENDIAN_BIG} r_info : longint; { r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */ r_pcrel:1, /* was relocated pc relative already */ r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */ r_type:4, /* if not 0, machine specific relocation type */ r_address:24; /* offset in the section to what is being relocated */} r_value : int32_t; {* the value the item to be relocated is refering to (without any offset added) *} {$else} r_value : int32_t; r_info : longint; {* r_address:24, /* offset in the section to what is being relocated */ r_type:4, /* if not 0, machine specific relocation type */ r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */ r_pcrel:1, /* was relocated pc relative already */ r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */ *} {$endif} end; { * 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. } const GENERIC_RELOC_VANILLA = 0; { generic relocation as discribed above } GENERIC_RELOC_PAIR = 1; { Only follows a GENERIC_RELOC_SECTDIFF } GENERIC_RELOC_SECTDIFF = 2; GENERIC_RELOC_PB_LA_PTR = 3; { prebound lazy pointer } GENERIC_RELOC_LOCAL_SECTDIFF = 4; {* * 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, has an address of 0x00000056 in .o * // file, and there is no previous non-local label * * .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). * *} const X86_64_RELOC_UNSIGNED = 0; // for absolute addresses X86_64_RELOC_SIGNED = 1; // for signed 32-bit displacement X86_64_RELOC_BRANCH = 2; // a CALL/JMP instruction with 32-bit displacement X86_64_RELOC_GOT_LOAD = 3; // a MOVQ load of a GOT entry X86_64_RELOC_GOT = 4; // other GOT references X86_64_RELOC_SUBTRACTOR = 5; // must be followed by a X86_64_RELOC_UNSIGNED X86_64_RELOC_SIGNED_1 = 6; // for signed 32-bit displacement with a -1 addend X86_64_RELOC_SIGNED_2 = 7; // for signed 32-bit displacement with a -2 addend X86_64_RELOC_SIGNED_4 = 8; // for signed 32-bit displacement with a -4 addend {* Relocation types used in the ppc implementation. Relocation entries for * things other than instructions use the same generic relocation as discribed * above and their r_type is RELOC_VANILLA. The rest of the relocation types * are for instructions. Since they are for instructions the r_address field * indicates the 32 bit instruction that the relocation is to be preformed on. * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types * except for PPC_RELOC_BR14. * * For PPC_RELOC_BR14 if the r_length is the unused value 3, then the branch was * statically predicted setting or clearing the Y-bit based on the sign of the * displacement or the opcode. If this is the case the static linker must flip * the value of the Y-bit if the sign of the displacement changes for non-branch * always conditions. } const PPC_RELOC_VANILLA = 0; { generic relocation as discribed above } PPC_RELOC_PAIR = 1; { the second relocation entry of a pair } PPC_RELOC_BR14 = 2; { 14 bit branch displacement (to a word address) } PPC_RELOC_BR24 = 3; { 24 bit branch displacement (to a word address) } PPC_RELOC_HI16 = 4; { a PAIR follows with the low half } PPC_RELOC_LO16 = 5; { a PAIR follows with the high half } PPC_RELOC_HA16 = 6; { Same as the RELOC_HI16 except the low 16 bits and the } { * high 16 bits are added together with the low 16 bits } { * sign extened first. This means if bit 15 of the low } { * 16 bits is set the high 16 bits stored in the } { * instruction will be adjusted. } PPC_RELOC_LO14 = 7; { Same as the LO16 except that the low 2 bits are not } { * stored in the instruction and are always zero. This } { * is used in double word load/store instructions. } PPC_RELOC_SECTDIFF = 8; { a PAIR follows with subtract symbol value } PPC_RELOC_PB_LA_PTR = 9; { prebound lazy pointer } PPC_RELOC_HI16_SECTDIFF = 10; { section difference forms of above. a PAIR } PPC_RELOC_LO16_SECTDIFF = 11; { follows these with subtract symbol value } PPC_RELOC_HA16_SECTDIFF = 12; PPC_RELOC_JBSR = 13; PPC_RELOC_LO14_SECTDIFF = 14; PPC_RELOC_LOCAL_SECTDIFF = 15; { like PPC_RELOC_SECTDIFF, but the symbol referenced was local. } { * 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. } const N_GSYM = $20; { global symbol: name,,NO_SECT,type,0 } N_FNAME = $22; { procedure name (f77 kludge): name,,NO_SECT,0,0 } N_FUN = $24; { procedure: name,,n_sect,linenumber,address } N_STSYM = $26; { static symbol: name,,n_sect,type,address } N_LCSYM = $28; { .lcomm symbol: name,,n_sect,type,address } N_BNSYM = $2e; { begin nsect sym: 0,,n_sect,0,address } N_OPT = $3c; { emitted with gcc2_compiled and in gcc source } N_RSYM = $40; { register sym: name,,NO_SECT,type,register } N_SLINE = $44; { src line: 0,,n_sect,linenumber,address } N_ENSYM = $4e; { end nsect sym: 0,,n_sect,0,address } N_SSYM = $60; { structure elt: name,,NO_SECT,type,struct_offset } N_SO = $64; { source file name: name,,n_sect,0,address } N_OSO = $66; { object file name: name,,0,0,st_mtime } N_LSYM = $80; { local sym: name,,NO_SECT,type,offset } N_BINCL = $82; { include file beginning: name,,NO_SECT,0,sum } N_SOL = $84; { #included file name: name,,n_sect,0,address } N_PARAMS = $86; { compiler parameters: name,,NO_SECT,0,0 } N_VERSION = $88; { compiler version: name,,NO_SECT,0,0 } N_OLEVEL = $8A; { compiler -O level: name,,NO_SECT,0,0 } N_PSYM = $a0; { parameter: name,,NO_SECT,type,offset } N_EINCL = $a2; { include file end: name,,NO_SECT,0,0 } N_ENTRY = $a4; { alternate entry: name,,n_sect,linenumber,address } N_LBRAC = $c0; { left bracket: 0,,NO_SECT,nesting level,address } N_EXCL = $c2; { deleted include file: name,,NO_SECT,0,sum } N_RBRAC = $e0; { right bracket: 0,,NO_SECT,nesting level,address } N_BCOMM = $e2; { begin common: name,,NO_SECT,0,0 } N_ECOMM = $e4; { end common: name,,n_sect,0,0 } N_ECOML = $e8; { end common (local name): 0,,n_sect,0,address } N_LENG = $fe; { second stab entry with length information } { * for the berkeley pascal compiler, pc(1): } N_PC = $30; { global pascal symbol: name,,NO_SECT,subtype,line } implementation end.