//------------------------------------------------
//--- 010 Editor v10.0 Binary Template
//
//      File: Dyld.bt
//   Authors: blacktop
//   Version: 1.0
//   Purpose:
//  Category: Executable
// File Mask: dyld_shared_cache*
//  ID Bytes: 64 79 6C 64
//   History:
//------------------------------------------------

#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
#define MH_MAGIC 0xfeedface    /* the mach magic number */
#define MH_CIGAM 0xcefaedfe    /* NXSwapInt(MH_MAGIC) */

typedef ubyte Uuid[16]<read = readUUID, format = hex>;

typedef struct
{
    union
    {
        char n_name[4]; /* for use when in-core */
        uint32 n_strx;  /* index into the string table */
    } n_un;
    uchar n_type;   /* type flag, see below */
    uchar n_sect;   /* section number or NO_SECT */
    int16 n_desc;   /* see <mach-o/stab.h> */
    uint32 n_value; /* value of this symbol (or stab offset) */
} nlist;

/*
 * This is the symbol table entry structure for 64-bit architectures.
 */
typedef struct
{
    union
    {
        uint32 n_strx; /* index into the string table */
    } n_un;
    uchar n_type;   /* type flag, see below */
    uchar n_sect;   /* section number or NO_SECT */
    uint16 n_desc;  /* see <mach-o/stab.h> */
    uint64 n_value; /* value of this symbol (or stab offset) */
} nlist_64;

typedef enum<uint>
{
    unknown = 0,
    macOS = 1,             // PLATFORM_MACOS
    iOS = 2,               // PLATFORM_IOS
    tvOS = 3,              // PLATFORM_TVOS
    watchOS = 4,           // PLATFORM_WATCHOS
    bridgeOS = 5,          // PLATFORM_BRIDGEOS
    iOSMac = 6,            // PLATFORM_MACCATALYST
    iOS_simulator = 7,     // PLATFORM_IOSSIMULATOR
    tvOS_simulator = 8,    // PLATFORM_TVOSSIMULATOR
    watchOS_simulator = 9, // PLATFORM_WATCHOSSIMULATOR
    driverKit = 10,        // PLATFORM_DRIVERKIT
} Platform<format = hex>;

typedef enum<uint>
{
    kDyldSharedCacheTypeDevelopment = 0,
    kDyldSharedCacheTypeProduction = 1,
    kDyldSharedCacheTypeUniversal = 2,
} CacheType<format = decimal>;

typedef struct
{
    uint32 version;
} Version<read = VersionRead>;

string VersionRead(Version &version)
{
    local string version_string;
    if (version.version & 0xFF == 0)
    {
        SPrintf(version_string, "%u.%u", version.version >> 16, (version.version >> 8) & 0xFF);
    }
    else
    {

        SPrintf(version_string, "%u.%u.%u", version.version >> 16, (version.version >> 8) & 0xFF, version.version & 0xFF);
    }
    return version_string;
}

typedef struct
{
    char magic[16]<bgcolor = cLtBlue>;    // e.g. "dyld_v0    i386"
    uint mappingOffset;                   // file offset to first dyld_cache_mapping_info
    uint mappingCount;                    // number of dyld_cache_mapping_info entries
    uint32 imagesOffsetOld;               // UNUSED: moved to imagesOffset to prevent older dsc_extarctors from crashing
    uint32 imagesCountOld;                // UNUSED: moved to imagesCount to prevent older dsc_extarctors from crashing
    uint64 dyldBaseAddress;               // base address of dyld when cache was built
    uint64 codeSignatureOffset;           // file offset of code signature blob
    uint64 codeSignatureSize;             // size of code signature blob (zero means to end of file)
    uint64 slideInfoOffset;               // file offset of kernel slid info
    uint64 slideInfoSize;                 // size of kernel slid info
    uint64 localSymbolsOffset;            // file offset of where local symbols are stored
    uint64 localSymbolsSize;              // size of local symbols information
    Uuid uuid;                            // unique value for each shared cache file
    uint64 cacheType;                     // 0 for development, 1 for production, 2 for multi-cache
    uint branchPoolsOffset;               // file offset to table of uint64 pool addresses
    uint branchPoolsCount;                // number of uint64 entries
    uint64 dyldInCacheMH;                 // (unslid) address of mach_header of dyld in cache
    uint64 dyldInCacheEntry;              // (unslid) address of entry point (_dyld_start) of dyld in cache
    uint64 imagesTextOffset;              // file offset to first dyld_cache_image_text_info
    uint64 imagesTextCount;               // number of dyld_cache_image_text_info entries
    uint64 patchInfoAddr;                 // (unslid) address of dyld_cache_patch_info
    uint64 patchInfoSize;                 // Size of all of the patch information pointed to via the dyld_cache_patch_info
    uint64 otherImageGroupAddrUnused;     // unused
    uint64 otherImageGroupSizeUnused;     // unused
    uint64 progClosuresAddr;              // (unslid) address of list of program launch closures
    uint64 progClosuresSize;              // size of list of program launch closures
    uint64 progClosuresTrieAddr;          // (unslid) address of trie of indexes into program launch closures
    uint64 progClosuresTrieSize;          // size of trie of indexes into program launch closures
    uint platform;                        // platform number (macOS=1, etc)
    uint formatVersion : 8;               // dyld3::closure::kFormatVersion
    uint dylibsExpectedOnDisk : 1;        // dyld should expect the dylib exists on disk and to compare inode/mtime to see if cache is valid
    uint simulator : 1;                   // for simulator of specified platform
    uint locallyBuiltCache : 1;           // 0 for B&I built cache, 1 for locally built cache
    uint builtFromChainedFixups : 1;      // some dylib in cache was built using chained fixups, so patch tables must be used for overrides
    uint newFormatTLVs          : 1;      // TLVs have been set by cache builder as new format (not needing runtime side table)
    uint padding : 19;                    // TBD
    uint64 sharedRegionStart;             // base load address of cache if not slid
    uint64 sharedRegionSize;              // overall size of region cache can be mapped into
    uint64 maxSlide<format = hex>;        // runtime slide of cache can be between zero and this value
    uint64 dylibsImageArrayAddr;          // (unslid) address of ImageArray for dylibs in this cache
    uint64 dylibsImageArraySize;          // size of ImageArray for dylibs in this cache
    uint64 dylibsTrieAddr;                // (unslid) address of trie of indexes of all cached dylibs
    uint64 dylibsTrieSize;                // size of trie of cached dylib paths
    uint64 otherImageArrayAddr;           // (unslid) address of ImageArray for dylibs and bundles with dlopen closures
    uint64 otherImageArraySize;           // size of ImageArray for dylibs and bundles with dlopen closures
    uint64 otherTrieAddr;                 // (unslid) address of trie of indexes of all dylibs and bundles with dlopen closures
    uint64 otherTrieSize;                 // size of trie of dylibs and bundles with dlopen closures
    uint32 mappingWithSlideOffset;        // file offset to first dyld_cache_mapping_and_slide_info
    uint32 mappingWithSlideCount;         // number of dyld_cache_mapping_and_slide_info entries
    uint64 dylibsPBLStateArrayAddrUnused; // unused
    uint64 dylibsPBLSetAddr;              // (unslid) address of PrebuiltLoaderSet of all cached dylibs
    uint64 programsPBLSetPoolAddr;        // (unslid) address of pool of PrebuiltLoaderSet for each program
    uint64 programsPBLSetPoolSize;        // size of pool of PrebuiltLoaderSet for each program
    uint64 programTrieAddr;               // (unslid) address of trie mapping program path to PrebuiltLoaderSet
    uint32 programTrieSize;
    Version osVersion;           // OS Version of dylibs in this cache for the main platform
    Platform altPlatform;        // e.g. iOSMac on macOS
    Version altOsVersion;        // e.g. 14.0 for iOSMac
    uint64 swiftOptsOffset;      // file offset to Swift optimizations header
    uint64 swiftOptsSize;        // size of Swift optimizations header
    uint32 subCacheArrayOffset;  // file offset to first dyld_subcache_entry
    uint32 subCacheArrayCount;   // number of subCache entries
    Uuid symbolFileUUID;         // unique value for the shared cache file containing unmapped local symbols
    uint64 rosettaReadOnlyAddr;  // (unslid) address of the start of where Rosetta can add read-only/executable data
    uint64 rosettaReadOnlySize;  // maximum size of the Rosetta read-only/executable region
    uint64 rosettaReadWriteAddr; // (unslid) address of the start of where Rosetta can add read-write data
    uint64 rosettaReadWriteSize; // maximum size of the Rosetta read-write region
    uint32 imagesOffset;         // file offset to first dyld_cache_image_info
    uint32 imagesCount;          // number of dyld_cache_image_info entries
    uint32 cacheSubType;         // 0 for development, 1 for production, when cacheType is multi-cache(2)
    uint32 padding;
    uint64 objcOptsOffset;       // VM offset from cache_header* to ObjC optimizations header
    uint64 objcOptsSize;         // size of ObjC optimizations header
    uint64 cacheAtlasOffset;     // VM offset from cache_header* to embedded cache atlas for process introspection
    uint64 cacheAtlasSize;       // size of embedded cache atlas
    uint64 dynamicDataOffset;    // VM offset from cache_header* to the location of dyld_cache_dynamic_data_header
    uint64 dynamicDataMaxSize;   // maximum size of space reserved from dynamic dataz
    uint32 tProMappingOffset;    // file offset to first dyld_cache_tpro_mapping_info
    uint32 tProMappingCount;     // number of dyld_cache_tpro_mapping_info entries
    uint64    functionVariantInfoAddr;// (unslid) address of dyld_cache_function_variant_info
    uint64    functionVariantInfoSize;// Size of all of the variant information pointed to via the dyld_cache_function_variant_info
    uint64    prewarmingDataOffset;   // file offset to dyld_prewarming_header
    uint64    prewarmingDataSize;     // byte size of prewarming data
    /* NEW fields (macOS/iOS/etc 27.x beta 1) NOTE: not yet in Apple's published dyld_cache_format.h */
    uint32    cacheCPUType;           // Mach-O CPU type of the cache
    uint32    cacheCPUSubtype;        // Mach-O CPU subtype of the cache (may include capability bits)
    uint64    cacheCPUReserved;       // reserved; observed zero (Apple's field name unknown)
} dyld_cache_header;

typedef struct
{
    uint64 address;
    uint64 size;
    uint64 fileOffset;
    uint32 maxProt;
    uint32 initProt;
} dyld_cache_mapping_info<bgcolor = cBlue>;

typedef struct
{
    uint64 address;
    uint64 size;
    uint64 fileOffset;
    uint64 slideInfoFileOffset;
    uint64 slideInfoFileSize;
    uint64 flags;
    uint32 maxProt;
    uint32 initProt;
} dyld_cache_mapping_and_slide_info<bgcolor = cBlue>;

typedef struct
{
    uint64 address;
    uint64 modTime;
    uint64 inode;
    uint32 pathFileOffset;
    uint32 pad;
} dyld_cache_image_info<read = readimagename, bgcolor = cLtGreen>;

string readimagename(dyld_cache_image_info &info)
{
    return ReadString(info.pathFileOffset);
}

typedef struct
{
    uint64 exportsTrieAddr; // address of trie in unslid cache
    uint64 weakBindingsAddr;
    uint32 exportsTrieSize;
    uint32 weakBindingsSize;
    uint32 dependentsStartArrayIndex;
    uint32 reExportsStartArrayIndex;
} dyld_cache_image_info_extra;

typedef struct
{
    uint32 version;            // currently 1
    uint32 imageExtrasCount;   // does not include aliases
    uint32 imagesExtrasOffset; // offset into this chunk of first dyld_cache_image_info_extra
    uint32 bottomUpListOffset; // offset into this chunk to start of 16-bit array of sorted image indexes
    uint32 dylibTrieOffset;    // offset into this chunk to start of trie containing all dylib paths
    uint32 dylibTrieSize;      // size of trie containing all dylib paths
    uint32 initializersOffset; // offset into this chunk to start of initializers list
    uint32 initializersCount;  // size of initializers list
    uint32 dofSectionsOffset;  // offset into this chunk to start of DOF sections list
    uint32 dofSectionsCount;   // size of initializers list
    uint32 reExportListOffset; // offset into this chunk to start of 16-bit array of re-exports
    uint32 reExportCount;      // size of re-exports
    uint32 depListOffset;      // offset into this chunk to start of 16-bit array of dependencies (0x8000 bit set if upward)
    uint32 depListCount;       // size of dependencies
    uint32 rangeTableOffset;   // offset into this chunk to start of ss
    uint32 rangeTableCount;    // size of dependencies
    uint64 dyldSectionAddr;    // address of libdyld's __dyld section in unslid cache
} dyld_cache_accelerator_info;

typedef struct
{
    uint32 functionOffset; // address offset from start of cache mapping
    uint32 imageIndex;
} dyld_cache_accelerator_initializer;

typedef struct
{
    uint64 startAddress; // unslid address of start of region
    uint32 size;
    uint32 imageIndex;
} dyld_cache_range_entry;

typedef struct
{
    uint64 sectionAddress; // unslid address of start of region
    uint32 sectionSize;
    uint32 imageIndex;
} dyld_cache_accelerator_dof;

typedef struct
{
    Uuid uuid;
    uint64 loadAddress; // unslid address of start of __TEXT
    uint32 textSegmentSize;
    uint32 pathOffset; // offset from start of cache file
} dyld_cache_image_text_info<read = readimagetextname, bgcolor = cGreen>;

string readimagetextname(dyld_cache_image_text_info &tinfo)
{
    return ReadString(tinfo.pathOffset);
}

// typedef struct
// {
//     local uint64 base = FTell();
//     uint32 version; // currently 1
//     uint32 toc_offset<format = hex>;
//     uint32 toc_count;
//     uint32 entries_offset<format = hex>;
//     uint32 entries_count;
//     uint32 entries_size; // currently 128
//     FSeek(base + toc_offset);
//     uint16 toc[toc_count];
//     FSeek(base + entries_offset);
//     uchar entries[entries_count * entries_size];
// } dyld_cache_slide_info;

// void get_dyld_cache_slide_info(uint64 totalsize)
// {
//     dyld_cache_slide_info slideinfo;
// }

char[] showstring64(nlist_64 &list)
{
    return ReadString(strtableoff + list.n_un.n_strx);
}

char[] showstring(nlist &list)
{
    return ReadString(strtableoff + list.n_un.n_strx);
}

void readliststring()
{
    if (isbit64)
    {
        nlist_64 nlists<read = showstring64>;
    }
    else
    {
        nlist nlists<read = showstring>;
    }
}

typedef struct
{
    uint32 dylibOffset;     // offset in cache file of start of dylib
    uint32 nlistStartIndex; // start index of locals for this dylib
    uint32 nlistCount;      // number of local symbols for this dylib
} dyld_cache_local_symbols_entry;

typedef struct
{
    uint64 dylibOffset;     // offset in cache file of start of dylib
    uint32 nlistStartIndex; // start index of locals for this dylib
    uint32 nlistCount;      // number of local symbols for this dylib
} dyld4_cache_local_symbols_entry;

typedef struct(uint count)
{
    for (i = 0; i < count; i++)
    {
        readliststring();
    }
}
allnlist;

struct dyld_cache_slide_info2
{
    uint32 version;   // currently 2
    uint32 page_size; // currently 4096 (may also be 16384)
    uint32 page_starts_offset;
    uint32 page_starts_count;
    uint32 page_extras_offset;
    uint32 page_extras_count;
    uint64 delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location
    uint64 value_add;
    uint16 page_starts[page_starts_count];
    uint16 page_extras[page_extras_count];
};
#define DYLD_CACHE_SLIDE_PAGE_ATTRS 0xC000          // high bits of uint16_t are flags
#define DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA 0x8000     // index is into extras array (not starts array)
#define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE 0x4000 // page has no rebasing
#define DYLD_CACHE_SLIDE_PAGE_ATTR_END 0x8000       // last chain entry for page

typedef struct
{
    local uint64 base = FTell();
    local uint i;
    uint32 nlistOffset;   // offset into this chunk of nlist entries
    uint32 nlistCount;    // count of nlist entries
    uint32 stringsOffset; // offset into this chunk of string pool
    uint32 stringsSize;   // byte count of string pool
    uint32 entriesOffset; // offset into this chunk of array of dyld_cache_local_symbols_entry
    uint32 entriesCount;  // number of elements in dyld_cache_local_symbols_entry array
    FSeek(base + nlistOffset);
    strtableoff = base + stringsOffset;
    // allnlist lists(nlistCount);
    FSeek(base + entriesOffset);
    if (header.imagesOffsetOld > 0)
    {
        dyld_cache_local_symbols_entry nlistentry[entriesCount];
    }
    else
    {
        dyld4_cache_local_symbols_entry nlistentry[entriesCount];
    }
} dyld_cache_local_symbols_info;

typedef struct
{
    uint32 version;
    uint32 padding;
    uint64 typeConformanceHashTableCacheOffset;
    uint64 metadataConformanceHashTableCacheOffset;
    uint64 foreignTypeConformanceHashTableCacheOffset;
} SwiftOptimizationHeader<bgcolor = cPurple>;

typedef struct
{
    uint32 capacity;
    uint32 occupied;
    uint32 shift;
    uint32 mask;
    uint32 sentinelTarget;
    uint32 roundedTabSize;
    uint64 salt;

    uint32 scramble[256];
    uchar tab0; /* tab[mask+1] (always power-of-2). Rounded up to roundedTabSize */
} SwiftHashTable<bgcolor = cLtPurple>;

void get_dyld_cache_local_symbols_info(uint64 totalsize)
{
    dyld_cache_local_symbols_info symbolinfo;
}

void get_dyld_cache_local_symbols_entry(uint64 totalsize)
{
}

LittleEndian();

local int isbit64 = 0;
local uint32 i;
local uint32 sig;
local uint64 strtableoff;
dyld_cache_header header;
FSeek(header.mappingOffset);
dyld_cache_mapping_info mapinfo[header.mappingCount];
FSeek(header.mappingWithSlideOffset);
dyld_cache_mapping_and_slide_info mapWithSlideInfo[header.mappingWithSlideCount];

for (i = 0; i < header.mappingCount; i++)
{
    sig = ReadUInt(mapinfo[i].fileOffset);
    if (sig == MH_MAGIC_64 || sig == MH_CIGAM_64)
    {
        isbit64 = 1;
    }
}

if (header.imagesOffsetOld > 0)
{
    FSeek(header.imagesOffsetOld);
    dyld_cache_image_info imageinfo[header.imagesCountOld];
}
else if (header.imagesOffset > 0)
{
    FSeek(header.imagesOffset);
    dyld_cache_image_info imageinfo[header.imagesCount];
}

// FSeek(header.imagesTextOffset);
// dyld_cache_image_text_info imagetext[header.imagesTextCount];

// FIXME: this is wrong for iOS16 caches
// if (header.imagesOffsetOld == 0 && header.swiftOptsOffset > 0)
// {
//     FSeek(header.swiftOptsOffset);
//     SwiftOptimizationHeader swiftOpt;

//     FSeek(swiftOpt.typeConformanceHashTableCacheOffset);
//     SwiftHashTable typeConformance;
//     FSeek(swiftOpt.metadataConformanceHashTableCacheOffset);
//     SwiftHashTable metadataConformance;
//     FSeek(swiftOpt.foreignTypeConformanceHashTableCacheOffset);
//     SwiftHashTable foreignTypeConformance;
// }

typedef struct
{
    Uuid uuid;                          // UUID of subcache
    uint64 cacheVMOffset<format = hex>; // The offset of this subcache from the main cache base address
} dyld_subcache_entry<bgcolor = cLtPurple>;

typedef struct
{
    Uuid uuid;                          // UUID of subcache
    uint64 cacheVMOffset<format = hex>; // The offset of this subcache from the main cache base address
    char extension[32];
} dyld_subcache_entry_pagein_link<bgcolor = cLtPurple>;

if (header.subCacheArrayOffset > 0 && header.subCacheArrayCount > 0)
{
    if (header.mappingOffset >= 0x200)
    {
        FSeek(header.subCacheArrayOffset);
        dyld_subcache_entry_pagein_link info[header.subCacheArrayCount];
    }
    else
    {
        FSeek(header.subCacheArrayOffset);
        dyld_subcache_entry info[header.subCacheArrayCount];
    }
}

typedef struct
{
    uint64 address;
    uint64 size;
} tpro_mapping<bgcolor = cLtBlue>;

if (header.mappingOffset >= 0x208)
{
    FSeek(header.tProMappingOffset);
    tpro_mapping tproMappings[header.tProMappingCount];
}
// FSeek(header.codeSignatureOffset);
// if (header.codeSignatureSize > 0)
// {
//     uchar sign[header.codeSignatureSize];
// }
// if (header.slideInfoOffset > 0)
// {
//     FSeek(header.slideInfoOffset);
//     get_dyld_cache_slide_info(header.slideInfoSize);
// }

if (header.localSymbolsOffset > 0)
{
    FSeek(header.localSymbolsOffset);
    get_dyld_cache_local_symbols_info(header.localSymbolsSize);
}

//  ----------------------------------    macho header  ---------------------------------------
// Mach-o's should be Little Endian only -- except for the fat_header/fat_arch
LittleEndian();

typedef enum<uint>
{
    MACHO_32 = 0xFEEDFACE,  // 32-bit mach object file
    MACHO_64 = 0xFEEDFACF,  // 64-bit mach object file
    MACHO_FAT = 0xCAFEBABE, // Universal object file / FAT_MAGIC
    MACHO_FAT_CIGAM = 0xBEBAFECA
} Magic<format = hex>;

#define CPU_ARCH_MASK 0xff000000
#define CPU_ARCH_ABI64 0x01000000

// Changed to enum, more info and handles constant | macro fine //
//
typedef enum<uint>
{
    CPU_TYPE_X86 = 0x07,
    CPU_TYPE_X64 = 0x07 | CPU_ARCH_ABI64,
    CPU_TYPE_ARM = 0x0C,
    CPU_TYPE_ARM64 = 0x0C | CPU_ARCH_ABI64,
    CPU_TYPE_PPC = 0x12,
    CPU_TYPE_PPC64 = 0x12 | CPU_ARCH_ABI64,

    CPU_TYPE_I386 = CPU_TYPE_X86,
    CPU_TYPE_X86_64 = CPU_TYPE_X64,
    CPU_TYPE_POWERPC = CPU_TYPE_PPC,
    CPU_TYPE_POWERPC64 = CPU_TYPE_PPC64,
} CpuType<format = hex>;

typedef enum<uint>
{
    MACH_OBJECT = 0x1,
    MACH_EXECUTE = 0x2,
    MACH_FVMLIB = 0x3,
    MACH_CORE = 0x4,
    MACH_PRELOAD = 0x5,
    MACH_DYLIB = 0x6,
    MACH_DYLINKER = 0x7,
    MACH_BUNDLE = 0x8,
    MACH_DYLIB_STUB = 0x9,
    MACH_DSYM = 0xA,
    MACH_KEXT_BUNDLE = 0xB,
} FileType;

typedef enum<uint>
{
    i386_THREAD_STATE = 0x1,
    i386_FLOAT_STATE = 0x2,
    i386_EXCEPTION_STATE = 0x3
} i386ThreadFlavor<format = hex>;

typedef struct
{
    uint32 eax<format = hex>;
    uint32 ebx<format = hex>;
    uint32 ecx<format = hex>;
    uint32 edx<format = hex>;
    uint32 edi<format = hex>;
    uint32 esi<format = hex>;
    uint32 ebp<format = hex>;
    uint32 esp<format = hex>;
    uint32 ss<format = hex>;
    uint32 eflags<format = hex>;
    uint32 eip<format = hex>;
    uint32 cs<format = hex>;
    uint32 ds<format = hex>;
    uint32 es<format = hex>;
    uint32 fs<format = hex>;
    uint32 gs<format = hex>;
} i386ThreadState;

typedef enum<uint>
{
    x86_THREAD_STATE32 = 0x1,
    x86_FLOAT_STATE32 = 0x2,
    x86_EXCEPTION_STATE32 = 0x3,
    x86_THREAD_STATE64 = 0x4,
    x86_FLOAT_STATE64 = 0x5,
    x86_EXCEPTION_STATE64 = 0x6,
    x86_THREAD_STATE = 0x7,
    x86_FLOAT_STATE = 0x8,
    x86_EXCEPTION_STATE = 0x9,
    x86_DEBUG_STATE32 = 0xA,
    x86_DEBUG_STATE64 = 0xB,
    x86_DEBUG_STATE = 0xC,
    THREAD_STATE_NONE = 0xD
} x86ThreadFlavor<format = hex>;

typedef struct
{
    uint64 rax<format = hex>;
    uint64 rbx<format = hex>;
    uint64 rcx<format = hex>;
    uint64 rdx<format = hex>;
    uint64 rdi<format = hex>;
    uint64 rsi<format = hex>;
    uint64 rbp<format = hex>;
    uint64 rsp<format = hex>;
    uint64 r8<format = hex>;
    uint64 r9<format = hex>;
    uint64 r10<format = hex>;
    uint64 r11<format = hex>;
    uint64 r12<format = hex>;
    uint64 r13<format = hex>;
    uint64 r14<format = hex>;
    uint64 r15<format = hex>;
    uint64 rip<format = hex>;
    uint64 rflags<format = hex>;
    uint64 cs<format = hex>;
    uint64 fs<format = hex>;
    uint64 gs<format = hex>;
} x86ThreadState;

typedef enum<uint>
{
    PPC_THREAD_STATE = 0x1,
    PPC_FLOAT_STATE = 0x2,
    PPC_EXCEPTION_STATE = 0x3,
    PPC_VECTOR_STATE = 0x4,
    PPC_THREAD_STATE64 = 0x5,
    PPC_EXCEPTION_STATE64 = 0x6
} PPCThreadFlavor<format = hex>;

typedef struct
{
    uint32 r0<format = hex>;
    uint32 r1<format = hex>;
    uint32 r2<format = hex>;
    uint32 r3<format = hex>;
    uint32 r4<format = hex>;
    uint32 r5<format = hex>;
    uint32 r6<format = hex>;
    uint32 r7<format = hex>;
    uint32 r8<format = hex>;
    uint32 r9<format = hex>;
    uint32 r10<format = hex>;
    uint32 r11<format = hex>;
    uint32 r12<format = hex>;
    uint32 r13<format = hex>;
    uint32 r14<format = hex>;
    uint32 r15<format = hex>;
    uint32 r16<format = hex>;
} ARMThreadState;

typedef struct
{
    uint32 __srr0<comment = "Instruction address register (PC)">;
    uint32 __srr1<comment = "Machine state register (supervisor)">;
    uint32 __r0;
    uint32 __r1;
    uint32 __r2;
    uint32 __r3;
    uint32 __r4;
    uint32 __r5;
    uint32 __r6;
    uint32 __r7;
    uint32 __r8;
    uint32 __r9;
    uint32 __r10;
    uint32 __r11;
    uint32 __r12;
    uint32 __r13;
    uint32 __r14;
    uint32 __r15;
    uint32 __r16;
    uint32 __r17;
    uint32 __r18;
    uint32 __r19;
    uint32 __r20;
    uint32 __r21;
    uint32 __r22;
    uint32 __r23;
    uint32 __r24;
    uint32 __r25;
    uint32 __r26;
    uint32 __r27;
    uint32 __r28;
    uint32 __r29;
    uint32 __r30;
    uint32 __r31;

    uint32 __cr<comment = "Condition register">;
    uint32 __xer<comment = "User's integer exception register">;
    uint32 __lr<comment = "Link register">;
    uint32 __ctr<comment = "Count register">;
    uint32 __mq<comment = "MQ Register (601 only)">;

    uint32 __vrsave<comment = "Vector save register">;
} PPCThreadState;

typedef enum<uint>
{
    MACH_NOUNDEFS = 0x1,
    MACH_INCRLINK = 0x2,
    MACH_DYLDLINK = 0x4,
    MACH_BINDATLOAD = 0x8,
    MACH_PREBOUND = 0x10,
    MACH_SPLIT_SEGS = 0x20,
    MACH_LAZY_INIT = 0x40,
    MACH_TWOLEVEL = 0x80,
    MACH_FORCE_FLAT = 0x100,
    MACH_NOMULTIDEFS = 0x200,
    MACH_NOFIXPREBINDING = 0x400,
    MACH_PREBINDABLE = 0x800,
    MACH_ALLMODSBOUND = 0x1000,
    MACH_SUBSECTIONS_VIA_SYMBOLS = 0x2000,
    MACH_CANONICAL = 0x4000,
    MACH_WEAK_DEFINES = 0x8000,
    MACH_BINDS_TO_WEAK = 0x10000,
    MACH_ALLOW_STACK_EXECUTION = 0x20000,
    MACH_ROOT_SAFE = 0x40000,
    MACH_SETUID_SAFE = 0x80000,
    MACH_NO_REEXPORTED_DYLIBS = 0x100000,
    MACH_PIE = 0x200000,
    MACH_DEAD_STRIPPABLE_DYLIB = 0x400000,
    MACH_HAS_TLV_DESCRIPTORS = 0x800000,
    MACH_NO_HEAP_EXECUTION = 0x1000000
} Flags;

typedef struct
{

    // TODO : Extract out capabilities here
    CpuType cpu_type<comment = "CPU specifier", format = hex>;
    uint32 cpu_sub_type<comment = "Machine specifier", format = hex>;
    uint32 file_offset<comment = "Offset of header in file">;
    uint32 size<comment = "Size of object file">;
    uint32 align<comment = "alignment as a power of two">;
} Fat_Arch;

typedef struct
{
    Magic magic<comment = "Magic bytes for the file">;

    if (magic == MACHO_FAT || magic == MACHO_FAT_CIGAM)
    {
        // Need to switch to BigEndian!
        BigEndian();
        uint32 fat_arch_size<comment = "Number of fat_arch structs">;
        Fat_Arch fat_arch[fat_arch_size];
        // Switch back to LittleEndian for rest of parsing
        LittleEndian();
    }
    else
    {
        CpuType cpu_type<comment = "CPU specifier", format = hex>;
        uint32 cpu_sub_type<comment = "Machine specifier", format = hex>;
        FileType file_type;
        uint32 num_load_commands;
        uint32 size_of_load_commands;
        Flags flags;
    }
    if (magic == MACHO_64)
    {
        uint32 reserved;
    }
} Header<read = HeaderRead>;

string HeaderRead(Header &header)
{
    local string header_string;
    switch (header.magic)
    {
    case MACHO_FAT:
    case MACHO_FAT_CIGAM:
        header_string = "FAT header";
        break;
    case MACHO_32:
        header_string = "32bit Mach-O header";
        break;
    case MACHO_64:
        header_string = "64bit Mach-O header";
        break;
    default:
        header_string = "Unknown header!";
    }
    return header_string;
}

#define REQ_DYLD (0x80000000)

typedef enum<uint>
{
    SEGMENT = 0x1,
    SYM_TAB = 0x2,
    SYM_SEG = 0x3,
    THREAD = 0x4,
    UNIX_THREAD = 0x5,
    LOAD_FVM_LIB = 0x6,
    ID_FVM_LIB = 0x7,
    IDENT = 0x8,
    FVM_FILE = 0x9,
    PREPAGE = 0xA,
    DY_SYM_TAB = 0xB,
    LOAD_DYLIB = 0xC,
    ID_DYLIB = 0xD,
    LOAD_DYLINKER = 0xE,
    ID_DYLINKER = 0xF,
    PREBOUND_DYLIB = 0x10,
    ROUTINES = 0x11,
    SUB_FRAMEWORK = 0x12,
    SUB_UMBRELLA = 0x13,
    SUB_CLIENT = 0x14,
    SUB_LIBRARY = 0x15,
    TWOLEVEL_HINTS = 0x16,
    PREBIND_CKSUM = 0x17,
    LOAD_WEAK_DYLIB = 0x18 | REQ_DYLD,
    SEGMENT_64 = 0x19,
    ROUTINES_64 = 0x1A,
    UUID = 0x1B,
    RPATH = 0x1C | REQ_DYLD,
    CODE_SIGNATURE = 0x1D,
    SEGMENT_SPLIT_INFO = 0x1E,
    REEXPORT_DYLIB = 0x1F | REQ_DYLD,
    LAZY_LOAD_DYLIB = 0x20,
    ENCRYPTION_INFO = 0x21,
    DYLD_INFO = 0x22,
    DYLD_INFO_ONLY = 0x22 | REQ_DYLD,
    LOAD_UPWARD_DYLIB = 0x23 | REQ_DYLD,
    VERSION_MIN_MAC_OSX = 0x24,
    VERSION_MIN_IPHONE_OS = 0x25,
    FUNCTION_STARTS = 0x26,
    DYLD_ENVIRONMENT = 0x27,
    MAIN = 0x28,
    MAIN_DYLIB = 0x28 | REQ_DYLD, // Idk, ios app in arm64 uses
    DATA_IN_CODE = 0x29,
    SOURCE_VERSION = 0x2A,
    DYLIB_CODE_SIGN_DRS = 0x2B,
    ENCRYPTION_INFO_64 = 0x2c,
    LC_BUILD_VERSION = 0x32,
} LoadCommandType<read = LoadCommandTypeRead>;

string LoadCommandTypeRead(LoadCommandType &loadCommandType)
{
    switch (loadCommandType)
    {
    case SEGMENT:
        return "SEGMENT";
    case SYM_TAB:
        return "SYM_TAB";
    case SYM_SEG:
        return "SYM_SEG";
    case THREAD:
        return "THREAD";
    case UNIX_THREAD:
        return "UNIX_THREAD";
    case LOAD_FVM_LIB:
        return "LOAD_FVM_LIB";
    case ID_FVM_LIB:
        return "ID_FVM_LIB";
    case IDENT:
        return "IDENT";
    case FVM_FILE:
        return "FVM_FILE";
    case PREPAGE:
        return "PREPAGE";
    case DY_SYM_TAB:
        return "DY_SYM_TAB";
    case LOAD_DYLIB:
        return "LOAD_DYLIB";
    case ID_DYLIB:
        return "ID_DYLIB";
    case LOAD_DYLINKER:
        return "LOAD_DYLINKER";
    case ID_DYLINKER:
        return "ID_DYLINKER";
    case PREBOUND_DYLIB:
        return "PREBOUND_DYLIB";
    case ROUTINES:
        return "ROUTINES";
    case SUB_FRAMEWORK:
        return "SUB_FRAMEWORK";
    case SUB_UMBRELLA:
        return "SUB_UMBRELLA";
    case SUB_CLIENT:
        return "SUB_CLIENT";
    case SUB_LIBRARY:
        return "SUB_LIBRARY";
    case TWOLEVEL_HINTS:
        return "TWOLEVEL_HINTS";
    case PREBIND_CKSUM:
        return "PREBIND_CKSUM";
    case LOAD_WEAK_DYLIB:
        return "LOAD_WEAK_DYLIB";
    case SEGMENT_64:
        return "SEGMENT_64";
    case ROUTINES_64:
        return "ROUTINES_64";
    case UUID:
        return "UUID";
    case RPATH:
        return "RPATH";
    case CODE_SIGNATURE:
        return "CODE_SIGNATURE";
    case SEGMENT_SPLIT_INFO:
        return "SEGMENT_SPLIT_INFO";
    case REEXPORT_DYLIB:
        return "REEXPORT_DYLIB";
    case LAZY_LOAD_DYLIB:
        return "LAZY_LOAD_DYLIB";
    case ENCRYPTION_INFO:
        return "ENCRYPTION_INFO";
    case DYLD_INFO:
        return "DYLD_INFO";
    case DYLD_INFO_ONLY:
        return "DYLD_INFO_ONLY";
    case LOAD_UPWARD_DYLIB:
        return "LOAD_UPWARD_DYLIB";
    case VERSION_MIN_MAC_OSX:
        return "VERSION_MIN_MAC_OSX";
    case VERSION_MIN_IPHONE_OS:
        return "VERSION_MIN_IPHONE_OS";
    case FUNCTION_STARTS:
        return "FUNCTION_STARTS";
    case DYLD_ENVIRONMENT:
        return "DYLD_ENVIRONMENT";
    case MAIN:
        return "MAIN";
    case MAIN_DYLIB:
        return "MAIN_DYLIB";
    case DATA_IN_CODE:
        return "DATA_IN_CODE";
    case SOURCE_VERSION:
        return "SOURCE_VERSION";
    case DYLIB_CODE_SIGN_DRS:
        return "DYLIB_CODE_SIGN_DRS";
    case ENCRYPTION_INFO_64:
        return "ENCRYPTION_INFO_64";
    case LC_BUILD_VERSION:
        return "LC_BUILD_VERSION";
    default:
        return "Error";
    }
}

typedef struct
{
    char section_name[16];
    char segment_name[16];
    uint32 address<format = hex>;
    uint32 size<format = hex>;
    uint32 offset;
    uint32 section_alignment;
    uint32 relocation_entry_offset;
    uint32 number_of_relocation_entries;
    uint32 flags<format = hex>;
    uint32 reserved1;
    uint32 reserved2;
} Section<optimize = false>;

typedef struct
{
    char section_name[16];
    char segment_name[16];
    uint64 address<format = hex>;
    uint64 size<format = hex>;
    uint32 offset;
    uint32 section_alignment;
    uint32 relocation_entry_offset;
    uint32 number_of_relocation_entries;
    uint32 flags<format = hex>;
    uint32 reserved1;
    uint32 reserved2;
    uint32 reserved3;
} Section64<optimize = false>;

typedef uint vm_proc;

typedef enum<uint>
{
    HIGH_VM = 0x1,
    FVM_LIB = 0x2,
    NO_RELOC = 0x4,
    PROTECTION_VERSION_1 = 0x8
} SegmentFlags<format = hex>;

typedef struct
{
    uint32 load_command_string_offset<comment = "Offset in respect to the start of load command to string data">;

    local int64 pos = FTell();
    // We need to goto beginning of LoadCommand, then goto the offset
    FSeek(FTell() - (sizeof(uint32) * 3) + load_command_string_offset);

    string string_data<comment = "Load command string">;

    FSeek(pos);
} LoadCommandString<read = LoadCommandStringRead>;

string LoadCommandStringRead(LoadCommandString &loadCommandString)
{
    return loadCommandString.string_data;
};

typedef ubyte Uuid[16]<read = readUUID, format = hex>;

// TODO : Clean this ugly thing up
string readUUID(Uuid uuid)
{
    local string ret, tmp;
    local int i;

    for (i = 0; i < 4; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i]);
        ret += tmp;
    }
    ret += "-";

    for (i = 0; i < 2; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i + 4]);
        ret += tmp;
    }
    ret += "-";

    for (i = 0; i < 2; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i + 6]);
        ret += tmp;
    }
    ret += "-";

    for (i = 0; i < 2; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i + 8]);
        ret += tmp;
    }
    ret += "-";

    for (i = 0; i < 6; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i + 10]);
        ret += tmp;
    }
    return ret;
}

string readUUID2(ubyte uuid[16])
{
    local string ret, tmp;
    local int i;

    for (i = 0; i < 4; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i]);
        ret += tmp;
    }
    ret += "-";

    for (i = 0; i < 2; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i + 4]);
        ret += tmp;
    }
    ret += "-";

    for (i = 0; i < 2; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i + 6]);
        ret += tmp;
    }
    ret += "-";

    for (i = 0; i < 2; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i + 8]);
        ret += tmp;
    }
    ret += "-";

    for (i = 0; i < 6; i++)
    {
        SPrintf(tmp, "%.2X", uuid[i + 10]);
        ret += tmp;
    }
    return ret;
}

typedef struct
{
    uint32 tool;     // enum for the tool
    Version version; // version of the tool
} build_tool_version;

typedef struct
{
    local uint64 o_pos = FTell();

    // LoadCommandHead loadCommandHead <comment="Load command type and size">;
    LoadCommandType command;
    uint command_size;

    // Process rest of load command based on command type
    switch (command)
    {
    case ID_DYLIB:
    case LOAD_DYLIB:
    case LOAD_WEAK_DYLIB:
    case REEXPORT_DYLIB:
        LoadCommandString name;
        // TODO : Pretty print this
        uint32 timestamp;
        // TODO : Pretty print this
        uint32 current_version;
        // TODO : Pretty print this
        uint32 compatibility_version;
        break;
    case SYM_TAB:
        uint32 symbol_table_offset<format = hex, comment = "Symbol table offsett address">;
        uint32 number_of_symbol_table_entries<comment = "Number of symbol table entries">;
        uint32 string_table_offset<format = hex, comment = "String table offset">;
        uint32 string_table_size<comment = "String table size in bytes">;
        break;
    case DYLD_INFO:
    case DYLD_INFO_ONLY:
        uint32 rebase_offset;
        uint32 rebase_size;
        uint32 bind_offset;
        uint32 bind_size;
        uint32 weak_bind_offset;
        uint32 weak_bind_size;
        uint32 lazy_bind_offset;
        uint32 lazy_bind_size;
        uint32 export_offset;
        uint32 export_size;
        break;
    case DY_SYM_TAB:
        uint32 index_local_symbols;
        uint32 local_symbols_size;
        uint32 index_externally_defined_symbols;
        uint32 externally_defined_symbols_size;
        uint32 index_undefined_symbols;
        uint32 undefined_symbols_size;
        uint32 table_contents_offset;
        uint32 enteries_toc_size;
        uint32 file_offset_module_table;
        uint32 module_table_entries_size;
        uint32 external_references_symbol_table_offset;
        uint32 external_references_symbol_table_size;
        uint32 indirect_symbol_table_offset;
        uint32 indirect_symbol_table_size;
        uint32 external_relocation_entries_offset;
        uint32 external_relocation_entries_size;
        uint32 local_relocation_entries_offset;
        uint32 local_relocation_entries_size;
        break;
    case UUID:
        Uuid uuid;
        break;
    case VERSION_MIN_MAC_OSX:
    case VERSION_MIN_IPHONE_OS:
        // TODO : Pretty print this
        Version version;
        uint32 reserved<comment = "Should be zero">;
        break;
    case FUNCTION_STARTS:
    case CODE_SIGNATURE:
    case SEGMENT_SPLIT_INFO:
    case DATA_IN_CODE:
        uint32 data_offset;
        uint32 data_size;
        break;
    case UNIX_THREAD:
    case THREAD:
        switch (cpu_typer)
        {
        case CPU_TYPE_X86:
        case CPU_TYPE_I386:
            i386ThreadFlavor flavor;
            // TODO : Pretty print this
            uint32 count;
            switch (flavor)
            {
            case i386_THREAD_STATE:
                i386ThreadState threadState;
            // TODO : Flesh these guys out
            case i386_FLOAT_STATE:
            case i386_EXCEPTION_STATE:
            }
            break;
        case CPU_TYPE_X86_64:
            x86ThreadFlavor flavor;
            // TODO : Pretty print this
            uint32 count;
            switch (flavor)
            {
            case x86_THREAD_STATE64:
                x86ThreadState threadState;
                break;
            // TODO : Flesh these guys out
            case x86_FLOAT_STATE64:
            case x86_EXCEPTION_STATE64:
            case x86_DEBUG_STATE64:
            }
            break;
        case CPU_TYPE_POWERPC:
        case CPU_TYPE_POWERPC64:
            PPCThreadFlavor flavor;
            // TODO : Pretty print this
            uint32 count;
            switch (flavor)
            {
            case PPC_THREAD_STATE:
                PPCThreadState threadState;
                break;
            // TODO : Flesh these guys out
            case PPC_FLOAT_STATE:
            case PPC_EXCEPTION_STATE:
            case PPC_VECTOR_STATE:
            case PPC_THREAD_STATE64:
            case PPC_EXCEPTION_STATE64:
            }
            break;
        case CPU_TYPE_ARM:
            // TODO: Unsure if this is correct ?
            //                uint32 flavor;
            //                uint32 count;
            ARMThreadState threadState;
            break;
        }
        break;
    case FVM_LIB:
    case ID_FVM_LIB:
        LoadCommandString name<comment = "Fixed virtual memory library's target path name">;
        uint32 minor_version<comment = "Library's minor version number">;
        uint32 header_address<comment = "Library's header address">;
        break;
    case SUB_FRAMEWORK:
        LoadCommandString umbrella<comment = "Umbrella framework name">;
        break;
    case SUB_CLIENT:
        LoadCommandString client<comment = "Client name">;
        break;
    case SUB_UMBRELLA:
        LoadCommandString sub_umbrella<comment = "Sub umbrella framework name">;
        break;
    case SUB_LIBRARY:
        LoadCommandString sub_library<comment = "Sub library name">;
        break;
    case PREBOUND_DYLIB:
        LoadCommandString name<comment = "Library's path name">;
        uint32 modules_size<comment = "Number of modules inside library">;
        LoadCommandString linked_modules<comment = "Bit vector of linked modules">;
        break;
    case ID_DYLINKER:
    case LOAD_DYLINKER:
        LoadCommandString name<comment = "Dynamic linker's path name">;
        break;
    case ROUTINES_64:
        uint64 init_address<comment = "Address of initialization routine">;
        uint64 init_module<comment = "Index into module table that init routine is defined">;
        uint32 reversed_1;
        uint32 reversed_2;
        uint32 reversed_3;
        uint32 reversed_4;
        uint32 reversed_5;
        uint32 reversed_6;
        break;
    case ROUTINES:
        uint32 init_address<comment = "Address of initialization routine">;
        uint32 init_module<comment = "Index into module table that init routine is defined">;
        uint32 reversed_1;
        uint32 reversed_2;
        uint32 reversed_3;
        uint32 reversed_4;
        uint32 reversed_5;
        uint32 reversed_6;
        break;
    case TWOLEVEL_HINTS:
        uint32 offset<comment = "Offset into the hint table">;
        uint32 hints_size<comment = "Number of hints inside the hints table">;
        break;
    case PREBIND_CKSUM:
        uint32 cksum<comment = "Checksum or zero">;
        break;
    case RPATH:
        LoadCommandString path<comment = "Path to add to run path">;
        break;
    case ENCRYPTION_INFO:
        uint32 crypt_offset<comment = "File offset of encrypted range">;
        uint32 crypt_size<comment = "File size of the encrypted range">;
        uint32 crypt_id<comment = "Which encryption system, 0 means not-encrypted yet">;
        break;
    case IDENT:
        break;
    case FVM_FILE:
        LoadCommandString name<comment = "File's pathname">;
        uint32 header_address<comment = "File's virtual address">;
        break;
    case SEGMENT_64:
        char segment_name[16];

        uint64 vm_address<format = hex>;
        uint64 vm_size<format = hex>;
        uint64 file_off;
        uint64 file_size;

        vm_proc maximum_protection<format = hex>;
        vm_proc initial_protection<format = hex>;
        uint32 number_of_sections;
        // TODO : Fix this enum
        SegmentFlags flags;

        // Having this if statement will prevent warnings in 010Editor
        if (number_of_sections > 0)
        {
            Section64 section[number_of_sections];
        }
        break;
    case SEGMENT:
        char segment_name[16];

        uint32 vm_address<format = hex>;
        uint32 vm_size<format = hex>;
        uint32 file_off;
        uint32 file_size;

        vm_proc maximum_protection<format = hex>;
        vm_proc initial_protection<format = hex>;
        uint32 number_of_sections;
        // TODO : Fix this enum
        SegmentFlags flags;

        // Having this if statement will prevent warnings in 010Editor
        if (number_of_sections > 0)
        {
            Section section[number_of_sections];
        }
        break;
    case SOURCE_VERSION:
        uint32 unka;
        uint32 unkb;
        break;
    case ENCRYPTION_INFO_64:
        uint32 cryptoff<format = hex>;  /* file offset of encrypted range */
        uint32 cryptsize<format = hex>; /* file size of encrypted range */
        uint32 cryptid;                 /* which enryption system, 0 means not-encrypted yet */
        uint32 pad;                     /* padding to make this struct's size a multiple of 8 */
        break;
    case LC_BUILD_VERSION:
        Platform platform; // platform
        Version minos;     // X.Y.Z is encoded in nibbles xxxx.yy.zz
        Version sdk;       // X.Y.Z is encoded in nibbles xxxx.yy.zz
        uint32 ntools;
        if (ntools > 0)
        {
            build_tool_version tools[ntools];
        }
        break;
    case MAIN:
    case MAIN_DYLIB:
        uint64 entryoff<format = hex>;
        uint64 stacksize<format = hex>;
        break;

    default:
        Warning("Hit an unknown or unsupported load command : [%d]", command);
        break; // Exit(-1);
    }

    FSeek(o_pos + command_size); // AIO solution, fixes default case, need for unk/pad, and all of the LoadCommandString + Seeks all over //

} LoadCommand<read = LoadCommandReader, optimize = false>;

string LoadCommandReader(LoadCommand &loadCommand)
{
    return "load_command[" + LoadCommandTypeRead(loadCommand.command) + "]";
}

// parse each macho
typedef struct(uint64 offset)
{
    local uint64 endpos = FTell();
    FSeek(offset);
    Header header<comment = "Mach-o header information">;
    local uint32 cpu_typer;
    if (header.magic == MACHO_32 || header.magic == MACHO_64)
    {
        cpu_typer = header.cpu_type;
        // If we didn't find a FAT header, then just process the load commands
        LoadCommand loadCommand[header.num_load_commands];
    }
    else
    {
        // Otherwise we need to grab the new headers again
        local int i;
        for (i = 0; i < header.fat_arch_size; i++)
        {
            FSeek(header.fat_arch[i].file_offset);
            Header machHeader;
            cpu_typer = machHeader.cpu_type;
            LoadCommand loadCommand[machHeader.num_load_commands];
        }
    }
    FSeek(endpos);
}
machoParser;

if (header.localSymbolsOffset > 0)
{
    for (i = 0; i < symbolinfo.entriesCount; i++)
    {
        machoParser parser(symbolinfo.nlistentry[i].dylibOffset);
    }
}