/** * This file describes the format of Mach-O object files. * * D header file for `mach-o/loader.h` from the macOS 10.15 SDK. * * Copyright: Copyright Digital Mars 2010-2019. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: Jacob Carlborg * Version: Initial created: Feb 20, 2010-2018 * Source: $(DRUNTIMESRC core/sys/darwin/mach/_loader.d) */ module core.sys.darwin.mach.loader; import core.stdc.config; version (CoreDdoc) { /** * The 32-bit mach header appears at the very beginning of the object file * for 32-bit architectures. */ struct mach_header { /// Mach magic number identifier. uint magic; /// Cpu specifier. int cputype; /// Machine specifier. int cpusubtype; /// Type of file. uint filetype; /// Number of load commands. uint ncmds; /// The size of all the load commands. uint sizeofcmds; /// Flags. uint flags; } /// Constant for the magic field of the mach_header (32-bit architectures) enum { /// The mach magic number MH_MAGIC, /// NXSwapInt(MH_MAGIC) MH_CIGAM } /** * The 64-bit mach header appears at the very beginning of object files for * 64-bit architectures. */ struct mach_header_64 { /// Mach magic number identifier. uint magic; /// Cpu specifier. int cputype; /// Machine specifier. int cpusubtype; /// Type of file. uint filetype; /// Number of load commands. uint ncmds; /// The size of all the load commands. uint sizeofcmds; /// Flags. uint flags; /// Reserved. uint reserved; } /// Constant for the magic field of the mach_header_64 (64-bit architectures) enum { /// The 64-bit mach magic number. MH_MAGIC_64, /// NXSwapInt(MH_MAGIC_64). MH_CIGAM_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 arbitrary legal * Mach-O file. * * Constants for the filetype field of the mach_header */ enum { /// Relocatable object file. MH_OBJECT, /// Demand paged executable file. MH_EXECUTE, /// Fixed VM shared library file. MH_FVMLIB, /// Core file. MH_CORE, /// Preloaded executable file. MH_PRELOAD, /// Dynamically bound shared library. MH_DYLIB, /// Dynamic link editor. MH_DYLINKER, /// Dynamically bound bundle file. MH_BUNDLE, /// Shared library stub for static linking only, no section contents. MH_DYLIB_STUB, /// Companion file with only debug sections. MH_DSYM, /// X86_64 kexts. MH_KEXT_BUNDLE } /// Constants for the flags field of the mach_header enum { /// The object file has no undefined references. MH_NOUNDEFS, /** * The object file is the output of an incremental link against a base * file and can't be link edited again. */ MH_INCRLINK, /** * The object file is input for the dynamic linker and can't be * statically link edited again. */ MH_DYLDLINK, /** * The object file's undefined references are bound by the dynamic * linker when loaded. */ MH_BINDATLOAD, /// The file has its dynamic undefined references prebound. MH_PREBOUND, /// The file has its read-only and read-write segments split. MH_SPLIT_SEGS, /** * The shared library init routine is to be run lazily via catching * memory faults to its writeable segments (obsolete). */ MH_LAZY_INIT, /// The image is using two-level name space bindings. MH_TWOLEVEL, /// The executable is forcing all images to use flat name space bindings. MH_FORCE_FLAT, /** * This umbrella guarantees no multiple definitions of symbols in its * sub-images so the two-level namespace hints can always be used. */ MH_NOMULTIDEFS, /// Do not have dyld notify the prebinding agent about this executable. MH_NOFIXPREBINDING, /** * The binary is not prebound but can have its prebinding redone. only * used when MH_PREBOUND is not set. */ MH_PREBINDABLE, /** * 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_ALLMODSBOUND, /** * Safe to divide up the sections into sub-sections via symbols for dead * code stripping. */ MH_SUBSECTIONS_VIA_SYMBOLS, /// The binary has been canonicalized via the unprebind operation. MH_CANONICAL, /// The final linked image contains external weak symbols. MH_WEAK_DEFINES, /// The final linked image uses weak symbols. MH_BINDS_TO_WEAK, /** * When this bit is set, all stacks in the task will be given stack * execution privilege. Only used in MH_EXECUTE filetypes. */ MH_ALLOW_STACK_EXECUTION, /** * When this bit is set, the binary declares it is safe for use in * processes with uid zero. */ MH_ROOT_SAFE, /** * When this bit is set, the binary declares it is safe for use in * processes when issetugid() is true. */ MH_SETUID_SAFE, /** * 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_NO_REEXPORTED_DYLIBS, /** * When this bit is set, the OS will load the main executable at a * random address. Only used in MH_EXECUTE filetypes. */ MH_PIE, /** * Only for use on dylibs. When linking against a dylib that has this * bit set, the static linker will automatically not create a * LC_LOAD_DYLIB load command to the dylib if no symbols are being * referenced from the dylib.. */ MH_DEAD_STRIPPABLE_DYLIB, /// Contains a section of type S_THREAD_LOCAL_VARIABLES. MH_HAS_TLV_DESCRIPTORS, /** * When this bit is set, the OS will run the main executable with a * non-executable heap even on platforms (e.g. i386) that don't require * it. Only used in MH_EXECUTE filetypes. */ MH_NO_HEAP_EXECUTION, /// The code was linked for use in an application extension.. MH_APP_EXTENSION_SAFE, /** * The external symbols listed in the nlist symbol table do not include * all the symbols listed in the dyld info. */ MH_NLIST_OUTOFSYNC_WITH_DYLDINFO, /** * Allow LC_MIN_VERSION_MACOS and LC_BUILD_VERSION load commands with * the platforms macOS, iOSMac, iOSSimulator, tvOSSimulator and * watchOSSimulator. */ MH_SIM_SUPPORT, /** * Only for use on dylibs. When this bit is set, the dylib is part of * the dyld shared cache, rather than loose in the filesystem. */ MH_DYLIB_IN_CACHE } /** * 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. */ struct load_command { /// Type of load command. uint cmd; /// Total size of command in bytes. uint cmdsize; } /** * 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. */ enum LC_REQ_DYLD; /// Constants for the cmd field of all load commands, the type. enum { /// Segment of this file to be mapped. LC_SEGMENT, /// Link-edit stab symbol table info. LC_SYMTAB, /// Link-edit gdb symbol table info (obsolete). LC_SYMSEG, /// Thread. LC_THREAD, /// Unix thread (includes a stack). LC_UNIXTHREAD, /// Load a specified fixed VM shared library. LC_LOADFVMLIB, /// Fixed VM shared library identification. LC_IDFVMLIB, /// Object identification info (obsolete). LC_IDENT, /// Fixed VM file inclusion (internal use). LC_FVMFILE, /// Prepage command (internal use). LC_PREPAGE, /// Dynamic link-edit symbol table info. LC_DYSYMTAB, /// Load a dynamically linked shared library. LC_LOAD_DYLIB, /// Dynamically linked shared lib ident. LC_ID_DYLIB, /// Load a dynamic linker. LC_LOAD_DYLINKER, /// Dynamic linker identification. LC_ID_DYLINKER, /// Modules prebound for a dynamically linked shared library. LC_PREBOUND_DYLIB, /// Image routines. LC_ROUTINES, /// Sub framework. LC_SUB_FRAMEWORK, /// Sub umbrella. LC_SUB_UMBRELLA, /// Sub client. LC_SUB_CLIENT, /// Sub library. LC_SUB_LIBRARY, /// Two-level namespace lookup hints. LC_TWOLEVEL_HINTS, /// Prebind checksum. LC_PREBIND_CKSUM } /** * Load a dynamically linked shared library that is allowed to be missing * (all symbols are weak imported). */ /// enum LC_LOAD_WEAK_DYLIB; /// enum { /// 64-bit segment of this file to be mapped. LC_SEGMENT_64, /// 64-bit image routines. LC_ROUTINES_64, /// The uuid. LC_UUID, /// Runpath additions. LC_RPATH, /// Local of code signature. LC_CODE_SIGNATURE, /// Local of info to split segments. LC_SEGMENT_SPLIT_INFO, /// Load and re-export dylib. LC_REEXPORT_DYLIB, /// Delay load of dylib until first use. LC_LAZY_LOAD_DYLIB, /// Encrypted segment information. LC_ENCRYPTION_INFO, /// Compressed dyld information. LC_DYLD_INFO, /// Compressed dyld information only. LC_DYLD_INFO_ONLY, /// Load upward dylib. LC_LOAD_UPWARD_DYLIB, /// Build for MacOSX min OS version. LC_VERSION_MIN_MACOSX, /// Build for iPhoneOS min OS version. LC_VERSION_MIN_IPHONEOS, /// Compressed table of function start addresses. LC_FUNCTION_STARTS, /// String for dyld to treat like environment variable. LC_DYLD_ENVIRONMENT, /// Replacement for LC_UNIXTHREAD. LC_MAIN, /// Table of non-instructions in __text. LC_DATA_IN_CODE, /// Source version used to build binary. LC_SOURCE_VERSION, /// Code signing DRs copied from linked dylibs. LC_DYLIB_CODE_SIGN_DRS, /// 64-bit encrypted segment information. LC_ENCRYPTION_INFO_64, /// Linker options in MH_OBJECT files. LC_LINKER_OPTION, /// Optimization hints in MH_OBJECT files. LC_LINKER_OPTIMIZATION_HINT, /// Build for AppleTV min OS version. LC_VERSION_MIN_TVOS, /// Build for Watch min OS version. LC_VERSION_MIN_WATCHOS, /// Arbitrary data included within a Mach-O file. LC_NOTE, /// Build for platform min OS version. LC_BUILD_VERSION, /// Used with linkedit_data_command, payload is trie. LC_DYLD_EXPORTS_TRIE, /// Used with linkedit_data_command. LC_DYLD_CHAINED_FIXUPS } /** * 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. */ union lc_str { /// Offset to the string. uint offset; /// Pointer to the string (only available on non 64 bit platforms). char* ptr; } /** * 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. */ struct segment_command { /// LC_SEGMENT. uint cmd; /// Includes sizeof section structs. uint cmdsize; /// Segment name. char[16] segname; /// Memory address of this segment. uint vmaddr; /// Memory size of this segment. uint vmsize; /// File offset of this segment. uint fileoff; /// Amount to map from the file. uint filesize; /// Maximum VM protection. int maxprot; /// Initial VM protection. int initprot; /// Number of sections in segment. uint nsects; /// Flags. uint flags; } /* * 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. */ struct segment_command_64 { /// LC_SEGMENT_64. uint cmd; /// Includes sizeof section_64 structs. uint cmdsize; /// Segment name. char[16] segname; /// Memory address of this segment. ulong vmaddr; /// Memory size of this segment. ulong vmsize; /// File offset of this segment. ulong fileoff; /// Amount to map from the file. ulong filesize; /// Maximum VM protection. int maxprot; /// Initial VM protection. int initprot; /// Number of sections in segment. uint nsects; /// Flags. uint flags; } /// Constants for the flags field of the segment_command. enum { /** * 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_HIGHVM, /** * This segment is the VM that is allocated by a fixed VM library, * for overlap checking in the link editor. */ SG_FVMLIB, /** * This segment has nothing that was relocated in it and nothing * relocated to it, that is it maybe safely replaced without relocation. */ SG_NORELOC, /** * 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. */ SG_PROTECTED_VERSION_1, /// This segment is made read-only after fixups. SG_READ_ONLY } /** * 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 zeroroed 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 . */ struct section { /// Name of this section. char[16] sectname; /// Segment this section goes in. char[16] segname; /// Memory address of this section. uint addr; /// Size in bytes of this section. uint size; /// File offset of this section. uint offset; /// Section alignment (power of 2). uint align_; /// File offset of relocation entries. uint reloff; /// Number of relocation entries. uint nreloc; /// Flags (section type and attributes). uint flags; /// Reserved (for offset or index). uint reserved1; /// Reserved (for count or sizeof). uint reserved2; } /// struct section_64 { /// Name of this section. char[16] sectname; /// Segment this section goes in. char[16] segname; /// Memory address of this section. ulong addr; /// Size in bytes of this section. ulong size; /// File offset of this section. uint offset; /// Section alignment (power of 2). uint align_; /// File offset of relocation entries. uint reloff; /// Number of relocation entries. uint nreloc; /// Flags (section type and attributes). uint flags; /// Reserved (for offset or index). uint reserved1; /// Reserved (for count or sizeof). uint reserved2; /// Reserved. uint reserved3; } /** * 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). */ enum { /// 256 section types. SECTION_TYPE, /// 24 section attributes. SECTION_ATTRIBUTES } /// Constants for the type of a section. enum { /// Regular section. S_REGULAR, /// Zero fill on demand section. S_ZEROFILL, /// Section with only literal C strings. S_CSTRING_LITERALS, /// Section with only 4 byte literals. S_4BYTE_LITERALS, /// Section with only 8 byte literals. S_8BYTE_LITERALS, /// Section with only pointers to literals. S_LITERAL_POINTERS, /** * Section with only non-lazy symbol pointers. * * 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, /// Section with only lazy symbol pointers. S_LAZY_SYMBOL_POINTERS, /// Section with only symbol stubs, byte size of stub in the reserved2 field. S_SYMBOL_STUBS, /// Section with only function pointers for initialization. S_MOD_INIT_FUNC_POINTERS, /// Section with only function pointers for termination. S_MOD_TERM_FUNC_POINTERS, /// Section contains symbols that are to be coalesced. S_COALESCED, /// Zero fill on demand section (that can be larger than 4 gigabytes). S_GB_ZEROFILL, /// Section with only pairs of function pointers for interposing. S_INTERPOSING, /// Section with only 16 byte literals. S_16BYTE_LITERALS, /// Section contains DTrace Object Format. S_DTRACE_DOF, /// Section with only lazy symbol pointers to lazy loaded dylibs. S_LAZY_DYLIB_SYMBOL_POINTERS, // Section types to support thread local variables. /// Template of initial values for TLVs. S_THREAD_LOCAL_REGULAR, /// Template of initial values for TLVs. S_THREAD_LOCAL_ZEROFILL, /// TLV descriptors. S_THREAD_LOCAL_VARIABLES, /// Pointers to TLV descriptors. S_THREAD_LOCAL_VARIABLE_POINTERS, /// Functions to call to initialize TLV values. S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, /// 32-bit offsets to initializers. S_INIT_FUNC_OFFSETS } /** * Constants for the section attributes part of the flags field of a section * structure. */ enum { /// User setable attributes. SECTION_ATTRIBUTES_USR, /// Section contains only true machine instructions. S_ATTR_PURE_INSTRUCTIONS, /// Section contains coalesced symbols that are not to be in a ranlib table of contents. S_ATTR_NO_TOC, /// Ok to strip static symbols in this section in files with the MH_DYLDLINK flag. S_ATTR_STRIP_STATIC_SYMS, /// No dead stripping. S_ATTR_NO_DEAD_STRIP, /// Blocks are live if they reference live blocks. S_ATTR_LIVE_SUPPORT, /// Used with i386 code stubs written on by dyld. S_ATTR_SELF_MODIFYING_CODE, /** * A debug section. * * 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. */ S_ATTR_DEBUG, /// System setable attributes. SECTION_ATTRIBUTES_SYS, /// Section contains some machine instructions. S_ATTR_SOME_INSTRUCTIONS, /// Section has external relocation entries. S_ATTR_EXT_RELOC, /// Section has local relocation entries. S_ATTR_LOC_RELOC } /** * 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. */ enum { /** * The pagezero segment which has no protections and catches NULL * references for MH_EXECUTE files. */ SEG_PAGEZERO, /// The tradition UNIX text segment. SEG_TEXT, /// The real text part of the text section no headers, and no padding. SECT_TEXT, /// The fvmlib initialization section. SECT_FVMLIB_INIT0, /// The section following the fvmlib initialization section. SECT_FVMLIB_INIT1, /// The tradition UNIX data segment. SEG_DATA, /// The real initialized data section no padding, no bss overlap. SECT_DATA, /// The real uninitialized data section no padding. SECT_BSS, /// The section common symbols are allocated in by the link editor. SECT_COMMON, /// Objective-C runtime segment. SEG_OBJC, /// Symbol table. SECT_OBJC_SYMBOLS, /// Module information. SECT_OBJC_MODULES, /// String table. SECT_OBJC_STRINGS, /// String table. SECT_OBJC_REFS, /// The icon segment. SEG_ICON, /// The icon headers. SECT_ICON_HEADER, /// The icons in tiff format. SECT_ICON_TIFF, /** * The segment containing all structs created and maintained by the link * editor. Created with -seglinkedit option to ld(1) for MH_EXECUTE and * FVMLIB file types only. */ SEG_LINKEDIT, /// The unix stack segment. SEG_UNIXSTACK, /** * The segment for the self (dyld) modifing code stubs that has read, * write and execute permissions. */ SEG_IMPORT } /** * 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). */ struct fvmlib { /// Library's target pathname. lc_str name; /// Library's minor version number. uint minor_version; /// Library's header address. uint header_addr; } /** * 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). */ struct fvmlib_command { /// LC_IDFVMLIB or LC_LOADFVMLIB. uint cmd; /// Includes pathname string. uint cmdsize; /// The library identification. fvmlib fvmlib_; } /** * Dynamically 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. */ struct dylib { /// Library's path name. lc_str name; /// Library's build time stamp. uint timestamp; /// Library's current version number. uint current_version; /// Library's compatibility version number. uint compatibility_version; } /** * 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. */ struct dylib_command { /// LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, LC_REEXPORT_DYLIB. uint cmd; /// Includes pathname string. uint cmdsize; /// The library identification. dylib dylib_; } /** * 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. */ struct sub_framework_command { /// LC_SUB_FRAMEWORK. uint cmd; /// Includes umbrella string. uint cmdsize; /// The umbrella framework name. lc_str umbrella; } /** * 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". */ struct sub_client_command { /// LC_SUB_CLIENT. uint cmd; /// Includes client string. uint cmdsize; /// The client name. lc_str client; } /** * 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 * statically 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. */ struct sub_umbrella_command { /// LC_SUB_UMBRELLA. uint cmd; /// Includes sub_umbrella string. uint cmdsize; /// The sub_umbrella framework name. lc_str sub_umbrella; } /** * 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 "library_name" is the name of the sub_library shared library. When * statically 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". */ struct sub_library_command { /// LC_SUB_LIBRARY. uint cmd; /// Includes sub_library string. uint cmdsize; /// The sub_library name. lc_str sub_library; } /** * 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 */ struct prebound_dylib_command { /// LC_PREBOUND_DYLIB. uint cmd; /// Includes strings. uint cmdsize; /// Library's path name. lc_str name; /// Number of modules in library. uint nmodules; /// Bit vector of linked modules. lc_str linked_modules; } /** * 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. */ struct dylinker_command { /// LC_ID_DYLINKER, LC_LOAD_DYLINKER or LC_DYLD_ENVIRONMENT. uint cmd; /// Includes pathname string. uint cmdsize; /// Dynamic linker's path name. lc_str name; } /** * 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 uint32_t * constant for the flavor of that data structure, an uint32_t that is the * count of uint32_t's 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. */ struct thread_command { /// LC_THREAD or LC_UNIXTHREAD. uint cmd; /// Total size of this command. uint cmdsize; } /** * 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. */ struct routines_command { /// LC_ROUTINES. uint cmd; /// Total size of this command. uint cmdsize; /// Address of initialization routine. uint init_address; /// Index into the module table that. uint init_module; // the init routine is defined in /// uint reserved1; /// uint reserved2; /// uint reserved3; /// uint reserved4; /// uint reserved5; /// uint reserved6; } /// The 64-bit routines command. Same use as above. struct routines_command_64 { /// LC_ROUTINES_64. uint cmd; /// Total size of this command. uint cmdsize; /// Address of initialization routine. ulong init_address; /// Index into the module table that. ulong init_module; /* the init routine is defined in */ /// ulong reserved1; /// ulong reserved2; /// ulong reserved3; /// ulong reserved4; /// ulong reserved5; /// ulong reserved6; } /** * 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 . */ struct symtab_command { /// LC_SYMTAB. uint cmd; /// Sizeof(struct symtab_command). uint cmdsize; /// Symbol table offset. uint symoff; /// Number of symbol table entries. uint nsyms; /// String table offset. uint stroff; /// String table size in bytes. uint strsize; } /** * 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. */ struct dysymtab_command { /// LC_DYSYMTAB. uint cmd; /// sizeof(struct dysymtab_command). uint cmdsize; /** * Index to local symbols. * * 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). */ uint ilocalsym; /// Number of local symbols. uint nlocalsym; /// Index to externally defined symbols. uint iextdefsym; /// Number of externally defined symbols. uint nextdefsym; /// Index to undefined symbols. uint iundefsym; /// Number of undefined symbols. uint nundefsym; /** * File offset to table of contents. * * 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. */ uint tocoff; /// Number of entries in table of contents. uint ntoc; /** * File offset to module table. * * 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. */ uint modtaboff; /// Number of module table entries. uint nmodtab; /** * Offset to referenced symbol table. * * 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. */ uint extrefsymoff; /// Number of referenced symbol table entries. uint nextrefsyms; /** * File offset to the indirect symbol table. * * 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. */ uint indirectsymoff; /// Number of indirect symbol table entries. uint nindirectsyms; /** * Offset to external relocation 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 * offset from thevmaddr 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). */ uint extreloff; /// Number of external relocation entries. uint nextrel; /** * Offset to local 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 statically link edited address). */ uint locreloff; /// Number of local relocation entries. uint nlocrel; } /** * 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. 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. */ enum { /// INDIRECT_SYMBOL_LOCAL, /// INDIRECT_SYMBOL_ABS } /// A table of contents entry. struct dylib_table_of_contents { /// The defined external symbol (index into the symbol table). uint symbol_index; /// Index into the module table this symbol is defined in. uint module_index; } /// A module table entry. struct dylib_module { /// The module name (index into string table). uint module_name; /// Index into externally defined symbols. uint iextdefsym; /// Number of externally defined symbols. uint nextdefsym; /// Index into reference symbol table. uint irefsym; /// Number of reference symbol table entries. uint nrefsym; /// Index into symbols for local symbols. uint ilocalsym; /// Number of local symbols. uint nlocalsym; /// Index into external relocation entries. uint iextrel; /// Number of external relocation entries. uint nextrel; /** * Low 16 bits are the index into the init section, high 16 bits are the * index into the term section. */ uint iinit_iterm; /** * Low 16 bits are the number of init section entries, high 16 bits are * the number of term section entries. */ uint ninit_nterm; /** * The (__OBJC,__module_info) section. * * For this module address of the start of. */ uint objc_module_info_addr; /** * The (__OBJC,__module_info) section. * * For this module size of. */ uint objc_module_info_size; } /// A 64-bit module table entry. struct dylib_module_64 { /// The module name (index into string table). uint module_name; /// Index into externally defined symbols. uint iextdefsym; /// Number of externally defined symbols. uint nextdefsym; /// Index into reference symbol table. uint irefsym; /// Number of reference symbol table entries. uint nrefsym; /// Index into symbols for local symbols. uint ilocalsym; /// Number of local symbols. uint nlocalsym; /// Index into external relocation entries. uint iextrel; /// Number of external relocation entries. uint nextrel; /** * Low 16 bits are the index into the init section, high 16 bits are the * index into the term section. */ uint iinit_iterm; /** * Low 16 bits are the number of init section entries, high 16 bits are * the number of term section entries. */ uint ninit_nterm; /** * The (__OBJC,__module_info) section. * * For this module size of. */ uint objc_module_info_size; /** * The (__OBJC,__module_info) section. * * For this module address of the start of. */ ulong objc_module_info_addr; } /** * 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. */ struct dylib_reference { /// Index into the symbol table. @property uint isym() const pure nothrow @nogc @safe; /// ditto @property void isym(uint v) @safe pure nothrow @nogc; /// Flags to indicate the type of reference. @property uint flags() const pure nothrow @nogc @safe; /// ditto @property void flags(uint v) pure nothrow @nogc @safe; } /** * The twolevel_hints_command contains the offset and number of hints in the * two-level namespace lookup hints table. */ struct twolevel_hints_command { /// LC_TWOLEVEL_HINTS. uint cmd; /// Sizeof(struct twolevel_hints_command). uint cmdsize; /// Offset to the hint table. uint offset; /// Number of hints in the hint table. uint nhints; } /** * 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. */ struct twolevel_hint { /// Index into the sub images. @property uint isub_image() const pure nothrow @nogc @safe; /// ditto @property void isub_image(uint v) pure nothrow @nogc @safe; /// Index into the table of contents. @property uint itoc() const pure nothrow @nogc @safe; /// ditto @property void itoc(uint v) pure nothrow @nogc @safe; } /** * 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. */ struct prebind_cksum_command { /// LC_PREBIND_CKSUM. uint cmd; /// Sizeof(struct prebind_cksum_command). uint cmdsize; /// The check sum or zero. uint cksum; } /** * The uuid load command contains a single 128-bit unique random number that * identifies an object produced by the static link editor. */ struct uuid_command { /// LC_UUID. uint cmd; /// Sizeof(struct uuid_command). uint cmdsize; /// The 128-bit uuid. ubyte[16] uuid; } /** * The rpath_command contains a path which at runtime should be added to * the current run path used to find @rpath prefixed dylibs. */ struct rpath_command { /// LC_RPATH. uint cmd; /// Includes string. uint cmdsize; /// Path to add to run path. lc_str path; } /** * The linkedit_data_command contains the offsets and sizes of a blob * of data in the __LINKEDIT segment. */ struct linkedit_data_command { /** * LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, * LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS, * LC_LINKER_OPTIMIZATION_HINT, LC_DYLD_EXPORTS_TRIE or * LC_DYLD_CHAINED_FIXUPS. */ uint cmd; /// Sizeof(struct linkedit_data_command). uint cmdsize; /// File offset of data in __LINKEDIT segment. uint dataoff; /// File size of data in __LINKEDIT segment. uint datasize; } /** * The encryption_info_command contains the file offset and size of an * of an encrypted segment. */ struct encryption_info_command { /// LC_ENCRYPTION_INFO. uint cmd; /// Sizeof(struct encryption_info_command). uint cmdsize; /// File offset of encrypted range. uint cryptoff; /// File size of encrypted range. uint cryptsize; /// Which encryption system, 0 means not-encrypted yet. uint cryptid; } /** * The encryption_info_command_64 contains the file offset and size of an * of an encrypted segment (for use in x86_64 targets). */ struct encryption_info_command_64 { /// LC_ENCRYPTION_INFO_64. uint cmd; /// Sizeof(struct encryption_info_command_64). uint cmdsize; /// File offset of encrypted range. uint cryptoff; /// File size of encrypted range. uint cryptsize; /// Which encryption system, 0 means not-encrypted yet. uint cryptid; /// Padding to make this struct's size a multiple of 8 bytes. uint pad; } /** * The version_min_command contains the min OS version on which this * binary was built to run. */ struct version_min_command { /** * LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS or * LC_VERSION_MIN_WATCHOS or LC_VERSION_MIN_TVOS. */ uint cmd; /// Sizeof(struct min_version_command). uint cmdsize; /// X.Y.Z is encoded in nibbles xxxx.yy.zz. uint version_; /// X.Y.Z is encoded in nibbles xxxx.yy.zz. uint sdk; } /** * 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. */ struct build_version_command { /// LC_BUILD_VERSION. uint cmd; /** * Sizeof(struct build_version_command) plus ntools * sizeof(struct build_tool_version). */ uint cmdsize; /// Platform. uint platform; /// X.Y.Z is encoded in nibbles xxxx.yy.zz. uint minos; /// X.Y.Z is encoded in nibbles xxxx.yy.zz. uint sdk; /// Number of tool entries following this. uint ntools; } /// struct build_tool_version { /// Enum for the tool. uint tool; /// Version number of the tool. uint version_; } /// Known values for the platform field above. enum { /// PLATFORM_MACOS, /// PLATFORM_IOS, /// PLATFORM_TVOS, /// PLATFORM_WATCHOS, /// PLATFORM_BRIDGEOS, /// PLATFORM_UIKITFORMAC, /// PLATFORM_IOSSIMULATOR, /// PLATFORM_TVOSSIMULATOR, /// PLATFORM_WATCHOSSIMULATOR, /// PLATFORM_DRIVERKIT } /// Known values for the tool field above. enum { /// TOOL_CLANG, /// TOOL_SWIFT, /// TOOL_LD } /** * 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. */ struct dyld_info_command { /// LC_DYLD_INFO or LC_DYLD_INFO_ONLY. uint cmd; /// Sizeof(struct dyld_info_command). uint cmdsize; /** * File offset to rebase info. * * 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: * * 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. */ uint rebase_off; /// Size of rebase info. uint rebase_size; /** * File offset to binding 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: * * 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. */ uint bind_off; /// Size of binding info. uint bind_size; /** * File offset to weak 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. */ uint weak_bind_off; /// Size of weak binding info. uint weak_bind_size; /** * File offset to lazy 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. */ uint lazy_bind_off; /// Size of lazy binding infs. uint lazy_bind_size; /** * File offset to lazy binding info. * * 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. * */ uint export_off; /// Size of lazy binding infs. uint export_size; } /// The following are used to encode rebasing information. enum { /// REBASE_TYPE_POINTER, /// REBASE_TYPE_TEXT_ABSOLUTE32, /// REBASE_TYPE_TEXT_PCREL32, /// REBASE_OPCODE_MASK, /// REBASE_IMMEDIATE_MASK, /// REBASE_OPCODE_DONE, /// REBASE_OPCODE_SET_TYPE_IMM, /// REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, /// REBASE_OPCODE_ADD_ADDR_ULEB, /// REBASE_OPCODE_ADD_ADDR_IMM_SCALED, /// REBASE_OPCODE_DO_REBASE_IMM_TIMES, /// REBASE_OPCODE_DO_REBASE_ULEB_TIMES, /// REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB, /// REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB } /// The following are used to encode binding information. enum { /// BIND_TYPE_POINTER, /// BIND_TYPE_TEXT_ABSOLUTE32, /// BIND_TYPE_TEXT_PCREL32, /// BIND_SPECIAL_DYLIB_SELF, /// BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE, /// BIND_SPECIAL_DYLIB_FLAT_LOOKUP, /// BIND_SPECIAL_DYLIB_WEAK_LOOKUP, /// BIND_SYMBOL_FLAGS_WEAK_IMPORT, /// BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION, /// BIND_OPCODE_MASK, /// BIND_IMMEDIATE_MASK, /// BIND_OPCODE_DONE, /// BIND_OPCODE_SET_DYLIB_ORDINAL_IMM, /// BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, /// BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, /// BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, /// BIND_OPCODE_SET_TYPE_IMM, /// BIND_OPCODE_SET_ADDEND_SLEB, /// BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, /// BIND_OPCODE_ADD_ADDR_ULEB, /// BIND_OPCODE_DO_BIND, /// BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB, /// BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED, /// BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB, /// BIND_OPCODE_THREADED, /// BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB, /// BIND_SUBOPCODE_THREADED_APPLY } /** * The following are used on the flags byte of a terminal node * in the export information. */ enum { /// EXPORT_SYMBOL_FLAGS_KIND_MASK, /// EXPORT_SYMBOL_FLAGS_KIND_REGULAR, /// EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL, /// EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE, /// EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION, /// EXPORT_SYMBOL_FLAGS_REEXPORT, /// EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER, } /* * The linker_option_command contains linker options embedded in object files. */ struct linker_option_command { /// LC_LINKER_OPTION only used in MH_OBJECT filetypes. uint cmd; /// uint cmdsize; /** * Number of strings concatenation of zero terminated UTF8 strings. * Zero filled at end to align. */ uint count; } /** * 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). */ struct symseg_command { /// LC_SYMSEG. uint cmd; /// Sizeof(struct symseg_command). uint cmdsize; /// Symbol segment offset. uint offset; /// Symbol segment size in bytes. uint size; } /** * 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). */ struct ident_command { /// LC_IDENT. uint cmd; /// Strings that follow this command. uint cmdsize; } /** * 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). */ struct fvmfile_command { /// LC_FVMFILE. uint cmd; /// Includes pathname string. uint cmdsize; /// Files pathname. lc_str name; /// Files virtual address. uint header_addr; } /** * 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. */ struct entry_point_command { /// LC_MAIN only used in MH_EXECUTE filetypes. uint cmd; /// 24. uint cmdsize; /// File (__TEXT) offset of main(). ulong entryoff; /// If not zero, initial stack size. ulong stacksize; } /** * The source_version_command is an optional load command containing * the version of the sources used to build the binary. */ struct source_version_command { /// LC_SOURCE_VERSION. uint cmd; /// 16. uint cmdsize; /// A.B.C.D.E packed as a24.b10.c10.d10.e10. ulong version_; } /** * The LC_DATA_IN_CODE load commands uses a linkedit_data_command * to point to an array of data_in_code_entry entries. Each entry * describes a range of data in a code section. */ struct data_in_code_entry { /// From mach_header to start of data range. uint offset; /// Number of bytes in data range. ushort length; /// A DICE_KIND_* value. ushort kind; } /// enum { /// DICE_KIND_DATA, /// DICE_KIND_JUMP_TABLE8, /// DICE_KIND_JUMP_TABLE16, /// DICE_KIND_JUMP_TABLE32, /// DICE_KIND_ABS_JUMP_TABLE32 } /** * Sections of type S_THREAD_LOCAL_VARIABLES contain an array * of tlv_descriptor structures. */ struct tlv_descriptor { /// void* function (tlv_descriptor*) thunk; /// c_ulong key; /// c_ulong offset; } /** * LC_NOTE commands describe a region of arbitrary data included in a Mach-O * file. Its initial use is to record extra data in MH_CORE files. */ struct note_command { /// LC_NOTE. uint cmd; /// Sizeof(struct note_command). uint cmdsize; /// Owner name for this LC_NOTE. char[16] data_owner; /// File offset of this data. ulong offset; /// Length of data region. ulong size; } } else version (OSX) version = Darwin; else version (iOS) version = Darwin; else version (TVOS) version = Darwin; else version (WatchOS) version = Darwin; version (Darwin): extern (C): struct mach_header { uint magic; int cputype; int cpusubtype; uint filetype; uint ncmds; uint sizeofcmds; uint flags; } enum { MH_MAGIC = 0xfeedface, MH_CIGAM = 0xcefaedfe } struct mach_header_64 { uint magic; int cputype; int cpusubtype; uint filetype; uint ncmds; uint sizeofcmds; uint flags; uint reserved; } enum { MH_MAGIC_64 = 0xfeedfacf, MH_CIGAM_64 = 0xcffaedfe } enum { MH_OBJECT = 0x1, MH_EXECUTE = 0x2, MH_FVMLIB = 0x3, MH_CORE = 0x4, MH_PRELOAD = 0x5, MH_DYLIB = 0x6, MH_DYLINKER = 0x7, MH_BUNDLE = 0x8, MH_DYLIB_STUB = 0x9, MH_DSYM = 0xa, MH_KEXT_BUNDLE = 0xb } enum { MH_NOUNDEFS = 0x1, MH_INCRLINK = 0x2, MH_DYLDLINK = 0x4, MH_BINDATLOAD = 0x8, MH_PREBOUND = 0x10, MH_SPLIT_SEGS = 0x20, MH_LAZY_INIT = 0x40, MH_TWOLEVEL = 0x80, MH_FORCE_FLAT = 0x100, MH_NOMULTIDEFS = 0x200, MH_NOFIXPREBINDING = 0x400, MH_PREBINDABLE = 0x800, MH_ALLMODSBOUND = 0x1000, MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000, MH_CANONICAL = 0x4000, MH_WEAK_DEFINES = 0x8000, MH_BINDS_TO_WEAK = 0x10000, MH_ALLOW_STACK_EXECUTION = 0x20000, MH_ROOT_SAFE = 0x40000, MH_SETUID_SAFE = 0x80000, MH_NO_REEXPORTED_DYLIBS = 0x100000, MH_PIE = 0x200000, MH_DEAD_STRIPPABLE_DYLIB = 0x400000, MH_HAS_TLV_DESCRIPTORS = 0x800000, MH_NO_HEAP_EXECUTION = 0x1000000, MH_APP_EXTENSION_SAFE = 0x02000000, MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000, MH_SIM_SUPPORT = 0x08000000, MH_DYLIB_IN_CACHE = 0x80000000 } struct load_command { uint cmd; uint cmdsize; } enum LC_REQ_DYLD = 0x80000000; enum { LC_SEGMENT = 0x1, LC_SYMTAB = 0x2, LC_SYMSEG = 0x3, LC_THREAD = 0x4, LC_UNIXTHREAD = 0x5, LC_LOADFVMLIB = 0x6, LC_IDFVMLIB = 0x7, LC_IDENT = 0x8, LC_FVMFILE = 0x9, LC_PREPAGE = 0xa, LC_DYSYMTAB = 0xb, LC_LOAD_DYLIB = 0xc, LC_ID_DYLIB = 0xd, LC_LOAD_DYLINKER = 0xe, LC_ID_DYLINKER = 0xf, LC_PREBOUND_DYLIB = 0x10, LC_ROUTINES = 0x11, LC_SUB_FRAMEWORK = 0x12, LC_SUB_UMBRELLA = 0x13, LC_SUB_CLIENT = 0x14, LC_SUB_LIBRARY = 0x15, LC_TWOLEVEL_HINTS = 0x16, LC_PREBIND_CKSUM = 0x17 } enum LC_LOAD_WEAK_DYLIB = 0x18 | LC_REQ_DYLD; enum { LC_SEGMENT_64 = 0x19, LC_ROUTINES_64 = 0x1a, LC_UUID = 0x1b, LC_RPATH = 0x1c | LC_REQ_DYLD, LC_CODE_SIGNATURE = 0x1d, LC_SEGMENT_SPLIT_INFO = 0x1e, LC_REEXPORT_DYLIB = 0x1f | LC_REQ_DYLD, LC_LAZY_LOAD_DYLIB = 0x20, LC_ENCRYPTION_INFO = 0x21, LC_DYLD_INFO = 0x22, LC_DYLD_INFO_ONLY = 0x22 | LC_REQ_DYLD, LC_LOAD_UPWARD_DYLIB = 0x23 | LC_REQ_DYLD, LC_VERSION_MIN_MACOSX = 0x24, LC_VERSION_MIN_IPHONEOS = 0x25, LC_FUNCTION_STARTS = 0x26, LC_DYLD_ENVIRONMENT = 0x27, LC_MAIN = 0x28 | LC_REQ_DYLD, LC_DATA_IN_CODE = 0x29, LC_SOURCE_VERSION = 0x2A, LC_DYLIB_CODE_SIGN_DRS = 0x2B, LC_ENCRYPTION_INFO_64 = 0x2C, LC_LINKER_OPTION = 0x2D, LC_LINKER_OPTIMIZATION_HINT = 0x2E, LC_VERSION_MIN_TVOS = 0x2F, LC_VERSION_MIN_WATCHOS = 0x30, LC_NOTE = 0x31, LC_BUILD_VERSION = 0x32, LC_DYLD_EXPORTS_TRIE = 0x33 | LC_REQ_DYLD, LC_DYLD_CHAINED_FIXUPS = 0x34 | LC_REQ_DYLD } union lc_str { uint offset; version (D_LP64) {} else char* ptr; } struct segment_command { uint cmd; uint cmdsize; char[16] segname = 0; uint vmaddr; uint vmsize; uint fileoff; uint filesize; int maxprot; int initprot; uint nsects; uint flags; } struct segment_command_64 { uint cmd; uint cmdsize; char[16] segname = 0; ulong vmaddr; ulong vmsize; ulong fileoff; ulong filesize; int maxprot; int initprot; uint nsects; uint flags; } enum { SG_HIGHVM = 0x1, SG_FVMLIB = 0x2, SG_NORELOC = 0x4, SG_PROTECTED_VERSION_1 = 0x8, SG_READ_ONLY = 0x10 } struct section { char[16] sectname = 0; char[16] segname = 0; uint addr; uint size; uint offset; uint align_; uint reloff; uint nreloc; uint flags; uint reserved1; uint reserved2; } struct section_64 { char[16] sectname = 0; char[16] segname = 0; ulong addr; ulong size; uint offset; uint align_; uint reloff; uint nreloc; uint flags; uint reserved1; uint reserved2; uint reserved3; } enum { SECTION_TYPE = 0x000000ff, SECTION_ATTRIBUTES = 0xffffff00 } enum { S_REGULAR = 0x0, S_ZEROFILL = 0x1, S_CSTRING_LITERALS = 0x2, S_4BYTE_LITERALS = 0x3, S_8BYTE_LITERALS = 0x4, S_LITERAL_POINTERS = 0x5, S_NON_LAZY_SYMBOL_POINTERS = 0x6, S_LAZY_SYMBOL_POINTERS = 0x7, S_SYMBOL_STUBS = 0x8, S_MOD_INIT_FUNC_POINTERS = 0x9, S_MOD_TERM_FUNC_POINTERS = 0xa, S_COALESCED = 0xb, S_GB_ZEROFILL = 0xc, S_INTERPOSING = 0xd, S_16BYTE_LITERALS = 0xe, S_DTRACE_DOF = 0xf, S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10, S_THREAD_LOCAL_REGULAR = 0x11, S_THREAD_LOCAL_ZEROFILL = 0x12, S_THREAD_LOCAL_VARIABLES = 0x13, S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14, S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15, S_INIT_FUNC_OFFSETS = 0x16 } enum { SECTION_ATTRIBUTES_USR = 0xff000000, S_ATTR_PURE_INSTRUCTIONS = 0x80000000, S_ATTR_NO_TOC = 0x40000000, S_ATTR_STRIP_STATIC_SYMS = 0x20000000, S_ATTR_NO_DEAD_STRIP = 0x10000000, S_ATTR_LIVE_SUPPORT = 0x08000000, S_ATTR_SELF_MODIFYING_CODE = 0x04000000, S_ATTR_DEBUG = 0x02000000, SECTION_ATTRIBUTES_SYS = 0x00ffff00, S_ATTR_SOME_INSTRUCTIONS = 0x00000400, S_ATTR_EXT_RELOC = 0x00000200, S_ATTR_LOC_RELOC = 0x00000100 } enum { SEG_PAGEZERO = "__PAGEZERO", SEG_TEXT = "__TEXT", SECT_TEXT = "__text", SECT_FVMLIB_INIT0 = "__fvmlib_init0", SECT_FVMLIB_INIT1 = "__fvmlib_init1", SEG_DATA = "__DATA", SECT_DATA = "__data", SECT_BSS = "__bss", SECT_COMMON = "__common", SEG_OBJC = "__OBJC", SECT_OBJC_SYMBOLS = "__symbol_table", SECT_OBJC_MODULES = "__module_info", SECT_OBJC_STRINGS = "__selector_strs", SECT_OBJC_REFS = "__selector_refs", SEG_ICON = "__ICON", SECT_ICON_HEADER = "__header", SECT_ICON_TIFF = "__tiff", SEG_LINKEDIT = "__LINKEDIT", SEG_UNIXSTACK = "__UNIXSTACK", SEG_IMPORT = "__IMPORT" } struct fvmlib { lc_str name; uint minor_version; uint header_addr; } struct fvmlib_command { uint cmd; uint cmdsize; fvmlib fvmlib_; } struct dylib { lc_str name; uint timestamp; uint current_version; uint compatibility_version; } struct dylib_command { uint cmd; uint cmdsize; dylib dylib_; } struct sub_framework_command { uint cmd; uint cmdsize; lc_str umbrella; } struct sub_client_command { uint cmd; uint cmdsize; lc_str client; } struct sub_umbrella_command { uint cmd; uint cmdsize; lc_str sub_umbrella; } struct sub_library_command { uint cmd; uint cmdsize; lc_str sub_library; } struct prebound_dylib_command { uint cmd; uint cmdsize; lc_str name; uint nmodules; lc_str linked_modules; } struct dylinker_command { uint cmd; uint cmdsize; lc_str name; } struct thread_command { uint cmd; uint cmdsize; } struct routines_command { uint cmd; uint cmdsize; uint init_address; uint init_module; uint reserved1; uint reserved2; uint reserved3; uint reserved4; uint reserved5; uint reserved6; } struct routines_command_64 { uint cmd; uint cmdsize; ulong init_address; ulong init_module; ulong reserved1; ulong reserved2; ulong reserved3; ulong reserved4; ulong reserved5; ulong reserved6; } struct symtab_command { uint cmd; uint cmdsize; uint symoff; uint nsyms; uint stroff; uint strsize; } struct dysymtab_command { uint cmd; uint cmdsize; uint ilocalsym; uint nlocalsym; uint iextdefsym; uint nextdefsym; uint iundefsym; uint nundefsym; uint tocoff; uint ntoc; uint modtaboff; uint nmodtab; uint extrefsymoff; uint nextrefsyms; uint indirectsymoff; uint nindirectsyms; uint extreloff; uint nextrel; uint locreloff; uint nlocrel; } enum { INDIRECT_SYMBOL_LOCAL = 0x80000000, INDIRECT_SYMBOL_ABS = 0x40000000 } struct dylib_table_of_contents { uint symbol_index; uint module_index; } struct dylib_module { uint module_name; uint iextdefsym; uint nextdefsym; uint irefsym; uint nrefsym; uint ilocalsym; uint nlocalsym; uint iextrel; uint nextrel; uint iinit_iterm; uint ninit_nterm; uint objc_module_info_addr; uint objc_module_info_size; } struct dylib_module_64 { uint module_name; uint iextdefsym; uint nextdefsym; uint irefsym; uint nrefsym; uint ilocalsym; uint nlocalsym; uint iextrel; uint nextrel; uint iinit_iterm; uint ninit_nterm; uint objc_module_info_size; ulong objc_module_info_addr; } struct dylib_reference { private uint storage; @property uint isym()() const pure nothrow @nogc @safe { return cast(uint) ((storage & 16777215U) >> 0U); } @property void isym()(uint v) @safe pure nothrow @nogc in { assert(v >= 0U, "Value is smaller than the minimum value of bitfield 'isym'"); assert(v <= 16777215U, "Value is greater than the maximum value of bitfield 'isym'"); } body { storage = cast(uint) ((storage & (-1 - cast(uint) 16777215U)) | ((cast(uint) v << 0U) & 16777215U)); } @property uint flags()() const pure nothrow @nogc @safe { return cast(uint) ((storage & 4278190080U) >> 24U); } @property void flags()(uint v) pure nothrow @nogc @safe in { assert(v >= 0U, "Value is smaller than the minimum value of bitfield 'flags'"); assert(v <= 255U, "Value is greater than the maximum value of bitfield 'flags'"); } body { storage = cast(uint) ((storage & (-1 - cast(uint) 4278190080U)) | ((cast(uint) v << 24U) & 4278190080U)); } } struct twolevel_hints_command { uint cmd; uint cmdsize; uint offset; uint nhints; } struct twolevel_hint { private uint storage; @property uint isub_image()() const pure nothrow @nogc @safe { return cast(uint) ((storage & 255U) >>0U); } @property void isub_image()(uint v) pure nothrow @nogc @safe in { assert(v >= 0U, "Value is smaller than the minimum value of bitfield 'isub_image'"); assert(v <= 255U, "Value is greater than the maximum value of bitfield 'isub_image'"); } body { storage = cast(uint) ((storage & (-1-cast(uint)255U)) | ((cast(uint) v << 0U) & 255U)); } @property uint itoc()() const pure nothrow @nogc @safe { return cast(uint) ((storage & 4294967040U) >>8U); } @property void itoc()(uint v) pure nothrow @nogc @safe in { assert(v >= 0U, "Value is smaller than the minimum value of bitfield 'itoc'"); assert(v <= 16777215U, "Value is greater than the maximum value of bitfield 'itoc'"); } body { storage = cast(uint) ((storage & (-1-cast(uint)4294967040U)) | ((cast(uint) v << 8U) & 4294967040U)); } } struct prebind_cksum_command { uint cmd; uint cmdsize; uint cksum; } struct uuid_command { uint cmd; uint cmdsize; ubyte[16] uuid; } struct rpath_command { uint cmd; uint cmdsize; lc_str path; } struct linkedit_data_command { uint cmd; uint cmdsize; uint dataoff; uint datasize; } struct encryption_info_command { uint cmd; uint cmdsize; uint cryptoff; uint cryptsize; uint cryptid; } struct encryption_info_command_64 { uint cmd; uint cmdsize; uint cryptoff; uint cryptsize; uint cryptid; uint pad; } struct version_min_command { uint cmd; uint cmdsize; uint version_; uint sdk; } struct build_version_command { uint cmd; uint cmdsize; uint platform; uint minos; uint sdk; uint ntools; } struct build_tool_version { uint tool; uint version_; } enum { PLATFORM_MACOS = 1, PLATFORM_IOS = 2, PLATFORM_TVOS = 3, PLATFORM_WATCHOS = 4, PLATFORM_BRIDGEOS = 5, PLATFORM_UIKITFORMAC = 6, PLATFORM_IOSSIMULATOR = 7, PLATFORM_TVOSSIMULATOR = 8, PLATFORM_WATCHOSSIMULATOR = 9, PLATFORM_DRIVERKIT = 10 } enum { TOOL_CLANG = 1, TOOL_SWIFT = 2, TOOL_LD = 3 } struct dyld_info_command { uint cmd; uint cmdsize; uint rebase_off; uint rebase_size; uint bind_off; uint bind_size; uint weak_bind_off; uint weak_bind_size; uint lazy_bind_off; uint lazy_bind_size; uint export_off; uint export_size; } enum { REBASE_TYPE_POINTER = 1, REBASE_TYPE_TEXT_ABSOLUTE32 = 2, REBASE_TYPE_TEXT_PCREL32 = 3, REBASE_OPCODE_MASK = 0xF0, REBASE_IMMEDIATE_MASK = 0x0F, REBASE_OPCODE_DONE = 0x00, REBASE_OPCODE_SET_TYPE_IMM = 0x10, REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x20, REBASE_OPCODE_ADD_ADDR_ULEB = 0x30, REBASE_OPCODE_ADD_ADDR_IMM_SCALED = 0x40, REBASE_OPCODE_DO_REBASE_IMM_TIMES = 0x50, REBASE_OPCODE_DO_REBASE_ULEB_TIMES = 0x60, REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB = 0x70, REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80 } enum { BIND_TYPE_POINTER = 1, BIND_TYPE_TEXT_ABSOLUTE32 = 2, BIND_TYPE_TEXT_PCREL32 = 3, BIND_SPECIAL_DYLIB_SELF = 0, BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1, BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2, BIND_SPECIAL_DYLIB_WEAK_LOOKUP = -3, BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1, BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8, BIND_OPCODE_MASK = 0xF0, BIND_IMMEDIATE_MASK = 0x0F, BIND_OPCODE_DONE = 0x00, BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10, BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20, BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30, BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40, BIND_OPCODE_SET_TYPE_IMM = 0x50, BIND_OPCODE_SET_ADDEND_SLEB = 0x60, BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70, BIND_OPCODE_ADD_ADDR_ULEB = 0x80, BIND_OPCODE_DO_BIND = 0x90, BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0, BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0, BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0, BIND_OPCODE_THREADED = 0xD0, BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB = 0x00, BIND_SUBOPCODE_THREADED_APPLY = 0x01 } enum { EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03, EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00, EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01, EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE = 0x02, EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04, EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08, EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10 } struct linker_option_command { uint cmd; uint cmdsize; uint count; } struct symseg_command { uint cmd; uint cmdsize; uint offset; uint size; } struct ident_command { uint cmd; uint cmdsize; } struct fvmfile_command { uint cmd; uint cmdsize; lc_str name; uint header_addr; } struct entry_point_command { uint cmd; uint cmdsize; ulong entryoff; ulong stacksize; } struct source_version_command { uint cmd; uint cmdsize; ulong version_; } struct data_in_code_entry { uint offset; ushort length; ushort kind; } enum { DICE_KIND_DATA = 0x0001, DICE_KIND_JUMP_TABLE8 = 0x0002, DICE_KIND_JUMP_TABLE16 = 0x0003, DICE_KIND_JUMP_TABLE32 = 0x0004, DICE_KIND_ABS_JUMP_TABLE32 = 0x0005, } struct tlv_descriptor { void* function(tlv_descriptor*) thunk; c_ulong key; c_ulong offset; } struct note_command { uint cmd; uint cmdsize; char[16] data_owner = 0; ulong offset; ulong size; }