1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240openOwee_bufletrecdecode_flagsnacc=function|[]->acc|(index,flag)::flagswhennland(1lslindex)<>0->decode_flagsn(flag::acc)flags|_::flags->decode_flagsnaccflagsletread_lc_stringbuft=letoffset=Read.u32tinmatchRead.zero_string(cursorbuf~at:offset)()with|None->invalid_format"invalid lc_string"|Somes->stypemagic=|MAGIC32|MAGIC64|CIGAM32|CIGAM64letmagic=function|0xFEEDFACE->MAGIC32|0xFEEDFACF->MAGIC64|0xCEFAEDFE->CIGAM32|0xCFFAEDFE->CIGAM64|_->invalid_format"magic"letstring_of_magic=function|MAGIC32->"MAGIC32"|MAGIC64->"MAGIC64"|CIGAM32->"CIGAM32"|CIGAM64->"CIGAM64"typeunknown=[`Unknownofint]typecpu_type=[|`X86|`X86_64|`ARM|`POWERPC|`POWERPC64|unknown]letcpu_type=function|0x00000007->`X86|0x01000007->`X86_64|0x0000000c->`ARM|0x00000012->`POWERPC|0x01000012->`POWERPC64|n->`Unknownntypecpu_subtype=[|`Intel|`I386_ALL|`I386|`I486|`I486SX|`PENT|`PENTPRO|`PENTII_M3|`PENTII_M5|`CELERON|`CELERON_MOBILE|`PENTIUM_3|`PENTIUM_3_M|`PENTIUM_3_XEON|`PENTIUM_M|`PENTIUM_4|`PENTIUM_4_M|`ITANIUM|`ITANIUM_2|`XEON|`XEON_MP|`INTEL_FAMILY|`INTEL_FAMILY_MAX|`INTEL_MODEL|`INTEL_MODEL_ALL|`X86_ALL|`X86_64_ALL|`X86_ARCH1|`POWERPC_ALL|`POWERPC_601|`POWERPC_602|`POWERPC_603|`POWERPC_603e|`POWERPC_603ev|`POWERPC_604|`POWERPC_604e|`POWERPC_620|`POWERPC_750|`POWERPC_7400|`POWERPC_7450|`POWERPC_970|`ARM_ALL|`ARM_V4T|`ARM_V6|unknown]letcpu_subtypetytag=matchty,tagwith|`X86,132->`I486SX|`X86,5->`PENT|`X86,22->`PENTPRO|`X86,54->`PENTII_M3|`X86,86->`PENTII_M5|`X86,103->`CELERON|`X86,119->`CELERON_MOBILE|`X86,8->`PENTIUM_3|`X86,24->`PENTIUM_3_M|`X86,40->`PENTIUM_3_XEON|`X86,9->`PENTIUM_M|`X86,10->`PENTIUM_4|`X86,26->`PENTIUM_4_M|`X86,11->`ITANIUM|`X86,27->`ITANIUM_2|`X86,12->`XEON|`X86,28->`XEON_MP|`X86,3->`X86_ALL|`X86,4->`X86_ARCH1|`X86_64,3->`X86_64_ALL|`POWERPC,0->`POWERPC_ALL|`POWERPC,1->`POWERPC_601|`POWERPC,2->`POWERPC_602|`POWERPC,3->`POWERPC_603|`POWERPC,4->`POWERPC_603e|`POWERPC,5->`POWERPC_603ev|`POWERPC,6->`POWERPC_604|`POWERPC,7->`POWERPC_604e|`POWERPC,8->`POWERPC_620|`POWERPC,9->`POWERPC_750|`POWERPC,10->`POWERPC_7400|`POWERPC,11->`POWERPC_7450|`POWERPC,100->`POWERPC_970|`POWERPC64,0->`POWERPC_ALL|`POWERPC64,1->`POWERPC_601|`POWERPC64,2->`POWERPC_602|`POWERPC64,3->`POWERPC_603|`POWERPC64,4->`POWERPC_603e|`POWERPC64,5->`POWERPC_603ev|`POWERPC64,6->`POWERPC_604|`POWERPC64,7->`POWERPC_604e|`POWERPC64,8->`POWERPC_620|`POWERPC64,9->`POWERPC_750|`POWERPC64,10->`POWERPC_7400|`POWERPC64,11->`POWERPC_7450|`POWERPC64,100->`POWERPC_970|`ARM,0->`ARM_ALL|`ARM,5->`ARM_V4T|`ARM,6->`ARM_V6|_,n->`Unknownntypefile_type=[|`OBJECT|`EXECUTE|`CORE|`PRELOAD|`DYLIB|`DYLINKER|`BUNDLE|`DYLIB_STUB|`DSYM|unknown]letfile_type=function|0x1->`OBJECT|0x2->`EXECUTE|0x4->`CORE|0x5->`PRELOAD|0x6->`DYLIB|0x7->`DYLINKER|0x8->`BUNDLE|0x9->`DYLIB_STUB|0xA->`DSYM|n->`Unknownntypeheader_flag=[(* the object file has no undefined references *)|`NOUNDEFS(* the object file is the output of an incremental link against a base file and can't be link edited again *)|`INCRLINK(* the object file is input for the dynamic linker and can't be staticly link edited again *)|`DYLDLINK(* the object file's undefined references are bound by the dynamic linker when loaded. *)|`BINDATLOAD(* the file has its dynamic undefined references prebound. *)|`PREBOUND(* the file has its read-only and read-write segments split *)|`SPLIT_SEGS(* the image is using two-level name space bindings *)|`TWOLEVEL(* the executable is forcing all images to use flat name space bindings *)|`FORCE_FLAT(* this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used. *)|`NOMULTIDEFS(* do not have dyld notify the prebinding agent about this executable *)|`NOFIXPREBINDING(* the binary is not prebound but can have its prebinding redone. only used when `PREBOUND is not set. *)|`PREBINDABLE(* indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when `PREBINDABLE and `TWOLEVEL are both set. *)|`ALLMODSBOUND(* safe to divide up the sections into sub-sections via symbols for dead code stripping *)|`SUBSECTIONS_VIA_SYMBOLS(* the binary has been canonicalized via the unprebind operation *)|`CANONICAL(* the final linked image contains external weak symbols *)|`WEAK_DEFINES(* the final linked image uses weak symbols *)|`BINDS_TO_WEAK(* When this bit is set, all stacks in the task will be given stack execution privilege. Only used in `EXECUTE filetypes. *)|`ALLOW_STACK_EXECUTION(* When this bit is set, the binary declares it is safe for use in processes with uid zero *)|`ROOT_SAFE(* When this bit is set, the binary declares it is safe for use in processes when issetugid() is true *)|`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 *)|`NO_REEXPORTED_DYLIBS(* When this bit is set, the OS will load the main executable at a random address. Only used in `EXECUTE filetypes. *)|`PIE]typeheader={magic:magic;cpu_type:cpu_type;cpu_subtype:cpu_subtype;file_type:file_type;flags:header_flaglist;}letis64bitheader=matchheader.magicwith|MAGIC32|CIGAM32->false|MAGIC64|CIGAM64->trueletheader_flags=[00,`NOUNDEFS;01,`INCRLINK;02,`DYLDLINK;03,`BINDATLOAD;04,`PREBOUND;05,`SPLIT_SEGS;07,`TWOLEVEL;08,`FORCE_FLAT;09,`NOMULTIDEFS;10,`NOFIXPREBINDING;11,`PREBINDABLE;12,`ALLMODSBOUND;13,`SUBSECTIONS_VIA_SYMBOLS;14,`CANONICAL;15,`WEAK_DEFINES;16,`BINDS_TO_WEAK;17,`ALLOW_STACK_EXECUTION;18,`ROOT_SAFE;19,`SETUID_SAFE;20,`NO_REEXPORTED_DYLIBS;21,`PIE;]letread_headerbuf=letstart=buf.positioninletmagic=magic(Read.u32buf)inletcpu_type=cpu_type(Read.u32buf)inletcpu_subtype=cpu_subtypecpu_type(Read.u32buf)inletfile_type=file_type(Read.u32buf)inlet_nb_cmds=Read.u32bufinletsize_of_cmds=Read.u32bufinletflags=decode_flags(Read.u32buf)[]header_flagsinlet_reserved=matchmagicwith|MAGIC64|CIGAM64->Read.u32buf|_->0inlet_header_size=buf.position-startinsize_of_cmds,{magic;cpu_type;cpu_subtype;file_type;flags}(* Platform-specific relocation types. *)typereloc_type=[|`GENERIC_RELOC_VANILLA|`GENERIC_RELOC_PAIR|`GENERIC_RELOC_SECTDIFF|`GENERIC_RELOC_LOCAL_SECTDIFF|`GENERIC_RELOC_PB_LA_PTR|`X86_64_RELOC_BRANCH|`X86_64_RELOC_GOT_LOAD|`X86_64_RELOC_GOT|`X86_64_RELOC_SIGNED|`X86_64_RELOC_UNSIGNED|`X86_64_RELOC_SUBTRACTOR|`X86_64_RELOC_SIGNED_1|`X86_64_RELOC_SIGNED_2|`X86_64_RELOC_SIGNED_4|`PPC_RELOC_VANILLA|`PPC_RELOC_PAIR|`PPC_RELOC_BR14|`PPC_RELOC_BR24|`PPC_RELOC_HI16|`PPC_RELOC_LO16|`PPC_RELOC_HA16|`PPC_RELOC_LO14|`PPC_RELOC_SECTDIFF|`PPC_RELOC_LOCAL_SECTDIFF|`PPC_RELOC_PB_LA_PTR|`PPC_RELOC_HI16_SECTDIFF|`PPC_RELOC_LO16_SECTDIFF|`PPC_RELOC_HA16_SECTDIFF|`PPC_RELOC_JBSR|`PPC_RELOC_LO14_SECTDIFF|unknown]letreloc_typecpu_typen=matchcpu_type,nwith|`X86,00->`GENERIC_RELOC_VANILLA|`X86,01->`GENERIC_RELOC_PAIR|`X86,02->`GENERIC_RELOC_SECTDIFF|`X86,03->`GENERIC_RELOC_LOCAL_SECTDIFF|`X86,04->`GENERIC_RELOC_PB_LA_PTR|`X86_64,00->`X86_64_RELOC_UNSIGNED|`X86_64,01->`X86_64_RELOC_SIGNED|`X86_64,02->`X86_64_RELOC_BRANCH|`X86_64,03->`X86_64_RELOC_GOT_LOAD|`X86_64,04->`X86_64_RELOC_GOT|`X86_64,05->`X86_64_RELOC_SUBTRACTOR|`X86_64,06->`X86_64_RELOC_SIGNED_1|`X86_64,07->`X86_64_RELOC_SIGNED_2|`X86_64,08->`X86_64_RELOC_SIGNED_4|`POWERPC,00->`PPC_RELOC_VANILLA|`POWERPC,01->`PPC_RELOC_PAIR|`POWERPC,02->`PPC_RELOC_BR14|`POWERPC,03->`PPC_RELOC_BR24|`POWERPC,04->`PPC_RELOC_HI16|`POWERPC,05->`PPC_RELOC_LO16|`POWERPC,06->`PPC_RELOC_HA16|`POWERPC,07->`PPC_RELOC_LO14|`POWERPC,08->`PPC_RELOC_SECTDIFF|`POWERPC,09->`PPC_RELOC_PB_LA_PTR|`POWERPC,10->`PPC_RELOC_HI16_SECTDIFF|`POWERPC,11->`PPC_RELOC_LO16_SECTDIFF|`POWERPC,12->`PPC_RELOC_HA16_SECTDIFF|`POWERPC,13->`PPC_RELOC_JBSR|`POWERPC,14->`PPC_RELOC_LO14_SECTDIFF|`POWERPC,15->`PPC_RELOC_LOCAL_SECTDIFF|`POWERPC64,00->`PPC_RELOC_VANILLA|`POWERPC64,01->`PPC_RELOC_PAIR|`POWERPC64,02->`PPC_RELOC_BR14|`POWERPC64,03->`PPC_RELOC_BR24|`POWERPC64,04->`PPC_RELOC_HI16|`POWERPC64,05->`PPC_RELOC_LO16|`POWERPC64,06->`PPC_RELOC_HA16|`POWERPC64,07->`PPC_RELOC_LO14|`POWERPC64,08->`PPC_RELOC_SECTDIFF|`POWERPC64,09->`PPC_RELOC_PB_LA_PTR|`POWERPC64,10->`PPC_RELOC_HI16_SECTDIFF|`POWERPC64,11->`PPC_RELOC_LO16_SECTDIFF|`POWERPC64,12->`PPC_RELOC_HA16_SECTDIFF|`POWERPC64,13->`PPC_RELOC_JBSR|`POWERPC64,14->`PPC_RELOC_LO14_SECTDIFF|`POWERPC64,15->`PPC_RELOC_LOCAL_SECTDIFF|_,n->`Unknownntyperelocation_info={(* offset from start of section to place to be relocated *)ri_address:int;(* index into symbol or section table *)ri_symbolnum:u32;(* indicates if the item to be relocated is part of an instruction containing PC-relative addressing *)ri_pcrel:bool;(* length of item containing address to be relocated (literal form (4) instead of power of two (2)) *)ri_length:u32;(* indicates whether symbolnum is an index into the symbol table (True) or section table (False) *)ri_extern:bool;(* relocation type *)ri_type:reloc_type;}letbitsofsszn=(nlsl(32-ofs-sz))lsr(32-sz)letread_relocation_info_theaderri_addressvalue={ri_address;ri_symbolnum=bits024value;ri_pcrel=bits241value=1;ri_length=1lsl(bits252value);ri_extern=bits271value=1;ri_type=reloc_typeheader.cpu_type(bits284value);}typescattered_relocation_info={rs_pcrel:bool;(* indicates if the item to be relocated is part of an instruction containing PC-relative addressing *)rs_length:u32;(* length of item containing address to be relocated (literal form (4) instead of power of two (2)) *)rs_type:reloc_type;(* relocation type *)rs_address:u32;(* offset from start of section to place to be relocated *)rs_value:s32;(* address of the relocatable expression for the item in the file that needs to be updated if the address is changed *)}letread_scattered_relocation_info_theaderaddressvalue={rs_pcrel=bits11address=1;rs_length=1lsl(bits22address);rs_type=reloc_typeheader.cpu_type(bits44address);rs_address=bits824address;rs_value=value;}typerelocation=[|`Relocation_infoofrelocation_info|`Scattered_relocation_infoofscattered_relocation_info]letread_relocationheadert=letaddress=Read.u32tinletvalue=Read.u32tinif(addressland0x80000000)=0then`Relocation_info(read_relocation_infotheaderaddressvalue)else`Scattered_relocation_info(read_scattered_relocation_infotheaderaddressvalue)typesec_type=[(* 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 *)|`S_NON_LAZY_SYMBOL_POINTERS(* section with only lazy symbol pointers *)|`S_LAZY_SYMBOL_POINTERS(* section with only symbol stubs, bte 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|unknown]letsec_typeflags=matchflagsland0x000000ffwith|0x00->`S_REGULAR|0x01->`S_ZEROFILL|0x02->`S_CSTRING_LITERALS|0x03->`S_4BYTE_LITERALS|0x04->`S_8BYTE_LITERALS|0x05->`S_LITERAL_POINTERS|0x06->`S_NON_LAZY_SYMBOL_POINTERS|0x07->`S_LAZY_SYMBOL_POINTERS|0x08->`S_SYMBOL_STUBS|0x09->`S_MOD_INIT_FUNC_POINTERS|0x0a->`S_MOD_TERM_FUNC_POINTERS|0x0b->`S_COALESCED|0x0c->`S_GB_ZEROFILL|0x0d->`S_INTERPOSING|0x0e->`S_16BYTE_LITERALS|0x0f->`S_DTRACE_DOF|0x10->`S_LAZY_DYLIB_SYMBOL_POINTERS|n->`Unknownntypesec_user_attr=[(* section contains only true machine instructions *)|`PURE_INSTRUCTIONS(* section contains coalesced symbols that are not to be in a ranlib table of contents *)|`NO_TOC(* ok to strip static symbols in this section in files with the MH_DYLDLINK flag *)|`STRIP_STATIC_SYMS(* no dead stripping *)|`NO_DEAD_STRIP(* blocks are live if they reference live blocks *)|`LIVE_SUPPORT(* used with i386 code stubs written on by dyld *)|`SELF_MODIFYING_CODE(* a debug section *)|`DEBUG]letsec_user_attrn=decode_flagsn[][30,`PURE_INSTRUCTIONS;29,`NO_TOC;28,`STRIP_STATIC_SYMS;27,`NO_DEAD_STRIP;26,`LIVE_SUPPORT;25,`SELF_MODIFYING_CODE]typesec_sys_attr=[(* section contains soem machine instructions *)|`SOME_INSTRUCTIONS(* section has external relocation entries *)|`EXT_RELOC(* section has local relocation entries *)|`LOC_RELOC]letsec_sys_attrn=decode_flagsn[][7,`LOC_RELOC;8,`EXT_RELOC;9,`SOME_INSTRUCTIONS]typesection={(* name of section *)sec_sectname:string;(* name of segment that should own this section *)sec_segname:string;(* virtual memoy address for section *)sec_addr:u64;(* size of section *)sec_size:u64;(* alignment required by section (literal form, not power of two, e.g. 8 not 3) *)sec_align:int;(* relocations for this section *)sec_relocs:relocationarray;(* type of section *)sec_type:sec_type;(* user attributes of section *)sec_user_attrs:sec_user_attrlist;(* system attibutes of section *)sec_sys_attrs:sec_sys_attrlist;}typevm_prot=[`READ|`WRITE|`EXECUTE]letread_vm_prott=decode_flags(Read.u32t)[][0,`READ;1,`WRITE;2,`EXECUTE]typeseg_flag=[|`HIGHVM(* 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). *)|`NORELOC(* This segment has nothing that was relocated in it and nothing relocated to it, that is it may be safely replaced without relocation. *)]letread_seg_flagt=decode_flags(Read.u32t)[][0,`HIGHVM;2,`NORELOC]typesegment={(* segment name *)seg_segname:string;(* virtual address where the segment is loaded *)seg_vmaddr:u64;(* size of segment at runtime *)seg_vmsize:u64;(* file offset of the segment *)seg_fileoff:u64;(* size of segment in file *)seg_filesize:u64;(* maximum virtual memory protection *)seg_maxprot:vm_protlist;(* initial virtual memory protection *)seg_initprot:vm_protlist;(* segment flags *)seg_flags:seg_flaglist;(* sections owned by this segment *)seg_sections:sectionarray;}typesym_type=[(* undefined symbol, n_sect is 0 *)|`UNDF(* absolute symbol, does not need relocation, n_sect is 0 *)|`ABS(* symbol is defined in section n_sect *)|`SECT(* symbol is undefined and the image is using a prebound value for the symbol, n_sect is 0 *)|`PBUD(* symbol is defined to be the same as another symbol. n_value is a string table offset indicating the name of that symbol *)|`INDR(* stab global symbol: name,,0,type,0 *)|`GSYM(* stab procedure name (f77 kludge): name,,0,0,0 *)|`FNAME(* stab procedure: name,,n_sect,linenumber,address *)|`FUN(* stab static symbol: name,,n_sect,type,address *)|`STSYM(* stab .lcomm symbol: name,,n_sect,type,address *)|`LCSYM(* stab begin nsect sym: 0,,n_sect,0,address *)|`BNSYM(* stab emitted with gcc2_compiled and in gcc source *)|`OPT(* stab register sym: name,,0,type,register *)|`RSYM(* stab src line: 0,,n_sect,linenumber,address *)|`SLINE(* stab end nsect sym: 0,,n_sect,0,address *)|`ENSYM(* stab structure elt: name,,0,type,struct_offset *)|`SSYM(* stab source file name: name,,n_sect,0,address *)|`SO(* stab object file name: name,,0,0,st_mtime *)|`OSO(* stab local sym: name,,0,type,offset *)|`LSYM(* stab include file beginning: name,,0,0,sum *)|`BINCL(* stab #included file name: name,,n_sect,0,address *)|`SOL(* stab compiler parameters: name,,0,0,0 *)|`PARAMS(* stab compiler version: name,,0,0,0 *)|`VERSION(* stab compiler -O level: name,,0,0,0 *)|`OLEVEL(* stab parameter: name,,0,type,offset *)|`PSYM(* stab include file end: name,,0,0,0 *)|`EINCL(* stab alternate entry: name,,n_sect,linenumber,address *)|`ENTRY(* stab left bracket: 0,,0,nesting level,address *)|`LBRAC(* stab deleted include file: name,,0,0,sum *)|`EXCL(* stab right bracket: 0,,0,nesting level,address *)|`RBRAC(* stab begin common: name,,0,0,0 *)|`BCOMM(* stab end common: name,,n_sect,0,0 *)|`ECOMM(* stab end common (local name): 0,,n_sect,0,address *)|`ECOML(* stab second stab entry with length information *)|`LENG(* stab global pascal symbol: name,,0,subtype,line *)|`PC|unknown]letsym_type=function|0x00->`UNDF|0x01->`ABS|0x07->`SECT|0x06->`PBUD|0x05->`INDR|0x20->`GSYM|0x22->`FNAME|0x24->`FUN|0x26->`STSYM|0x28->`LCSYM|0x2e->`BNSYM|0x3c->`OPT|0x40->`RSYM|0x44->`SLINE|0x4e->`ENSYM|0x60->`SSYM|0x64->`SO|0x66->`OSO|0x80->`LSYM|0x82->`BINCL|0x84->`SOL|0x86->`PARAMS|0x88->`VERSION|0x8A->`OLEVEL|0xa0->`PSYM|0xa2->`EINCL|0xa4->`ENTRY|0xc0->`LBRAC|0xc2->`EXCL|0xe0->`RBRAC|0xe2->`BCOMM|0xe4->`ECOMM|0xe8->`ECOML|0xfe->`LENG|0x30->`PC|n->`Unknownntypereference_flag=[(* reference to an external non-lazy symbol *)|`UNDEFINED_NON_LAZY(* reference to an external lazy symbol *)|`UNDEFINED_LAZY(* symbol is defined in this module *)|`DEFINED(* symbol is defined in this module and visible only to modules within this shared library *)|`PRIVATE_DEFINED(* reference to an external non-lazy symbol and visible only to modules within this shared library *)|`PRIVATE_UNDEFINED_NON_LAZY(* reference to an external lazy symbol and visible only to modules within this shared library *)|`PRIVATE_UNDEFINED_LAZY(* set for all symbols referenced by dynamic loader APIs *)|`REFERENCED_DYNAMICALLY(* indicates the symbol is a weak reference, set to 0 if definition cannot be found *)|`SYM_WEAK_REF(* indicates the symbol is a weak definition, will be overridden by a strong definition at link-time *)|`SYM_WEAK_DEF(* for two-level mach-o objects, specifies the index of the library in which this symbol is defined. zero specifies current image. *)|`LIBRARY_ORDINALofu16|unknown]letreference_flag_lo16=function|0->`UNDEFINED_NON_LAZY|1->`UNDEFINED_LAZY|2->`DEFINED|3->`PRIVATE_DEFINED|4->`PRIVATE_UNDEFINED_NON_LAZY|5->`PRIVATE_UNDEFINED_LAZY|n->`Unknownnletreference_flag_hi16n=decode_flagsn[][0,`REFERENCED_DYNAMICALLY;2,`SYM_WEAK_REF;3,`SYM_WEAK_DEF]letreference_flagsheaderv=ifList.mem`TWOLEVELheader.flagsthen(* Something fishy here, check spec FIXME *)[reference_flag_lo16(vland0xF);`LIBRARY_ORDINAL(vland0xf0)]elsereference_flag_lo16(vland0xF)::reference_flag_hi16vletsym_typesn=ifnland0xe0=0thenletnpext=nland0x10<>0inletntype=sym_type((nland0x0e)lsr1)inletnext=nland0x01<>0in(false,npext,ntype,next)else(true,false,sym_typen,false)typesymbol={(* symbol name *)sym_name:string;(* symbol type *)sym_type:sym_type;(* true if limited global scope *)sym_pext:bool;(* true if external symbol *)sym_ext:bool;(* section index where the symbol can be found *)sym_sect:u8;(* for stab entries, Left Word16 is the uninterpreted flags field, otherwise Right [REFERENCE_FLAG] are the symbol flags *)sym_flags:[`Uninterpretedofu16|`Flagsofreference_flaglist];(* symbol value, 32-bit symbol values are promoted to 64-bit for simpliciy *)sym_value:u64;}letread_symbol_nametbuf=letoffset=Read.u32tinmatchRead.zero_string(cursorbuf~at:offset)()with|None->invalid_format"invalid symbol name"|Somes->stypedylib_module={(* module name string table offset *)dylib_module_name_offset:u32;(* (initial, count) pair of symbol table indices for externally defined symbols *)dylib_ext_def_sym:u32*u32;(* (initial, count) pair of symbol table indices for referenced symbols *)dylib_ref_sym:u32*u32;(* (initial, count) pair of symbol table indices for local symbols *)dylib_local_sym:u32*u32;(* (initial, count) pair of symbol table indices for externally referenced symbols *)dylib_ext_rel:u32*u32;(* (initial, count) pair of symbol table indices for the index of the module init section and the number of init pointers *)dylib_init:u32*u32;(* (initial, count) pair of symbol table indices for the index of the module term section and the number of term pointers *)dylib_term:u32*u32;(* statically linked address of the start of the data for this module in the __module_info section in the __OBJC segment *)dylib_objc_module_info_addr:u32;(* number of bytes of data for this module that are used in the __module_info section in the __OBJC segment *)dylib_objc_module_info_size:u64;}typetoc_entry={symbol_index:u32;module_index:u32;}letread_toct=letsymbol_index=Read.u32tinletmodule_index=Read.u32tin{symbol_index;module_index}letread_n_timesftn=Array.initn(fun_->ft)typedynamic_symbol_table={(* symbol table index and count for local symbols *)localSyms:u32*u32;(* symbol table index and count for externally defined symbols *)extDefSyms:u32*u32;(* symbol table index and count for undefined symbols *)undefSyms:u32*u32;(* list of symbol index and module index pairs *)toc_entries:toc_entryarray;(* modules *)modules:dylib_modulearray;(* list of external reference symbol indices *)extRefSyms:u32array;(* list of indirect symbol indices *)indirectSyms:u32array;(* external locations *)extRels:relocationarray;(* local relocations *)locRels:relocationarray;}typedylib={dylib_name:string;dylib_timestamp:u32;dylib_current_version:u32;dylib_compatibility_version:u32;}letread_dylib_commandtlc=letdylib_name=read_lc_stringlctinletdylib_timestamp=Read.u32tinletdylib_current_version=Read.u32tinletdylib_compatibility_version=Read.u32tin{dylib_name;dylib_timestamp;dylib_current_version;dylib_compatibility_version}typecommand=(* segment of this file to be mapped *)|LC_SEGMENT_32ofsegmentlazy_t(* static link-edit symbol table and stab info *)|LC_SYMTABof(symbolarray*Owee_buf.t)lazy_t(* thread state information (list of (flavor, [long]) pairs) *)|LC_THREADof(u32*u32array)listlazy_t(* unix thread state information (includes a stack) (list of (flavor, [long] pairs) *)|LC_UNIXTHREADof(u32*u32array)listlazy_t(* dynamic link-edit symbol table info *)|LC_DYSYMTABofdynamic_symbol_tablelazy_t(* load a dynamically linked shared library (name, timestamp, current version, compatibility version) *)|LC_LOAD_DYLIBofdyliblazy_t(* dynamically linked shared lib ident (name, timestamp, current version, compatibility version) *)|LC_ID_DYLIBofdyliblazy_t(* load a dynamic linker (name of dynamic linker) *)|LC_LOAD_DYLINKERofstring(* dynamic linker identification (name of dynamic linker) *)|LC_ID_DYLINKERofstring(* modules prebound for a dynamically linked shared library (name, list of module indices) *)|LC_PREBOUND_DYLIBof(string*u8array)lazy_t(* image routines (virtual address of initialization routine, module index where it resides) *)|LC_ROUTINES_32ofu32*u32(* sub framework (name) *)|LC_SUB_FRAMEWORKofstring(* sub umbrella (name) *)|LC_SUB_UMBRELLAofstring(* sub client (name) *)|LC_SUB_CLIENTofstring(* sub library (name) *)|LC_SUB_LIBRARYofstring(* two-level namespace lookup hints (list of (subimage index, symbol table index) pairs *)|LC_TWOLEVEL_HINTSof((u32*u32)array)lazy_t(* prebind checksum (checksum) *)|LC_PREBIND_CKSUMofu32(* load a dynamically linked shared library that is allowed to be missing (symbols are weak imported) (name, timestamp, current version, compatibility version) *)|LC_LOAD_WEAK_DYLIBofdyliblazy_t(* 64-bit segment of this file to mapped *)|LC_SEGMENT_64ofsegmentlazy_t(* 64-bit image routines (virtual address of initialization routine, module index where it resides) *)|LC_ROUTINES_64ofu64*u64(* the uuid for an image or its corresponding dsym file (8 element list of bytes) *)|LC_UUIDofstring(* runpath additions (path) *)|LC_RPATHofstring(* local of code signature *)|LC_CODE_SIGNATUREofu32*u32(* local of info to split segments *)|LC_SEGMENT_SPLIT_INFOofu32*u32|LC_UNHANDLEDofint*Owee_buf.tletread_twolevelhintt=letword=Read.u32tinletisub_image=bits08wordanditoc=bits824wordin(isub_image,itoc)letread_twolevelhintsbuft=letoffset=Read.u32tinletnhints=Read.u32tinread_n_timesread_twolevelhint(cursorbuf~at:offset)nhintsletrecread_threadt=ifat_endtthen[]elseletflavor=Read.u32tinletcount=Read.u32tinletstate=read_n_timesRead.u32tcountin(flavor,state)::read_threadtletread_module_32t=letmodule_name=Read.u32tinletiextdefsym=Read.u32tinletnextdefsym=Read.u32tinletirefsym=Read.u32tinletnrefsym=Read.u32tinletilocalsym=Read.u32tinletnlocalsym=Read.u32tinletiextrel=Read.u32tinletnextrel=Read.u32tinletiinit_iterm=Read.u32tinletiinit=(iinit_itermland0x0000ffff)inletiterm=(iinit_itermland0xffff0000)lsr16inletninit_nterm=Read.u32tinletninit=(ninit_ntermland0x0000ffff)inletnterm=(ninit_ntermland0xffff0000)lsr16inletobjc_module_info_addr=Read.u32tinletobjc_module_info_size=Read.u32tin{dylib_module_name_offset=module_name;dylib_ext_def_sym=(iextdefsym,nextdefsym);dylib_ref_sym=(irefsym,nrefsym);dylib_local_sym=(ilocalsym,nlocalsym);dylib_ext_rel=(iextrel,nextrel);dylib_init=(iinit,ninit);dylib_term=(iterm,nterm);dylib_objc_module_info_addr=objc_module_info_addr;dylib_objc_module_info_size=Int64.of_intobjc_module_info_size;}letread_module_64t=letmodule_name=Read.u32tinletiextdefsym=Read.u32tinletnextdefsym=Read.u32tinletirefsym=Read.u32tinletnrefsym=Read.u32tinletilocalsym=Read.u32tinletnlocalsym=Read.u32tinletiextrel=Read.u32tinletnextrel=Read.u32tinletiinit_iterm=Read.u32tinletiinit=(iinit_itermland0x0000ffff)inletiterm=(iinit_itermland0xffff0000)lsr16inletninit_nterm=Read.u32tinletninit=(ninit_ntermland0x0000ffff)inletnterm=(ninit_ntermland0xffff0000)lsr16inletobjc_module_info_addr=Read.u32tinletobjc_module_info_size=Read.u64tin{dylib_module_name_offset=module_name;dylib_ext_def_sym=(iextdefsym,nextdefsym);dylib_ref_sym=(irefsym,nrefsym);dylib_local_sym=(ilocalsym,nlocalsym);dylib_ext_rel=(iextrel,nextrel);dylib_init=(iinit,ninit);dylib_term=(iterm,nterm);dylib_objc_module_info_addr=objc_module_info_addr;dylib_objc_module_info_size=objc_module_info_size;}letread_dynamic_symbol_tableheadertbuf=letilocalsym=Read.u32tinletnlocalsym=Read.u32tinletiextdefsym=Read.u32tinletnextdefsym=Read.u32tinletiundefsym=Read.u32tinletnundefsym=Read.u32tinlettocoff=Read.u32tinletntoc=Read.u32tinlettoc=read_n_timesread_toc(cursorbuf~at:tocoff)ntocinletmodtaboff=Read.u32tinletnmodtab=Read.u32tinletmodtab=read_n_times(ifis64bitheaderthenread_module_64elseread_module_32)(cursorbuf~at:modtaboff)nmodtabinletextrefsymoff=Read.u32tinletnextrefsyms=Read.u32tinletextrefsyms=read_n_timesRead.u32(cursorbuf~at:extrefsymoff)nextrefsymsinletindirectsymoff=Read.u32tinletnindirectsyms=Read.u32tinletindirectsyms=read_n_timesRead.u32(cursorbuf~at:indirectsymoff)nindirectsymsinletextreloff=Read.u32tinletnextrel=Read.u32tinletextrels=read_n_times(read_relocationheader)(cursorbuf~at:extreloff)nextrelinletlocreloff=Read.u32tinletnlocrel=Read.u32tinletlocrels=read_n_times(read_relocationheader)(cursorbuf~at:locreloff)nlocrelin{localSyms=(ilocalsym,nlocalsym);extDefSyms=(iextdefsym,nextdefsym);undefSyms=(iundefsym,nundefsym);toc_entries=toc;modules=modtab;extRefSyms=extrefsyms;indirectSyms=indirectsyms;extRels=extrels;locRels=locrels;}letfixed_0_stringtn=letresult=Read.fixed_stringtnintryString.subresult0(String.indexresult'\000')withNot_found->resultletread_section_32headerbuft=letsectname=fixed_0_stringt16inletsegname=fixed_0_stringt16inletaddr=Read.u32tinletsize=Read.u32tinlet_offset=Read.u32tinletalign=1lslRead.u32tinletreloff=Read.u32tinletnreloc=Read.u32tinletrelocs=read_n_times(read_relocationheader)(cursorbuf~at:reloff)nrelocinletflags=Read.u32tinlet_reserved=Read.u32tinlet_reserved=Read.u32tinletsec_type=sec_typeflagsinletuser_attrs=sec_user_attrflagsinletsys_attrs=sec_sys_attrflagsin{sec_sectname=sectname;sec_segname=segname;sec_addr=Int64.of_intaddr;sec_size=Int64.of_intsize;sec_align=align;sec_relocs=relocs;sec_type=sec_type;sec_user_attrs=user_attrs;sec_sys_attrs=sys_attrs;}letread_segment_32headerbuft=letsegname=fixed_0_stringt16inletvmaddr=Read.u32tinletvmsize=Read.u32tinletfileoff=Read.u32tinletfilesize=Read.u32tinletmaxprot=read_vm_prottinletinitprot=read_vm_prottinletnsects=Read.u32tinletflags=read_seg_flagtinletsects=read_n_times(read_section_32headerbuf)tnsectsin{seg_segname=segname;seg_vmaddr=Int64.of_intvmaddr;seg_vmsize=Int64.of_intvmsize;seg_fileoff=Int64.of_intfileoff;seg_filesize=Int64.of_intfilesize;seg_maxprot=maxprot;seg_initprot=initprot;seg_flags=flags;seg_sections=sects;}letread_section_64headerbuft=letsectname=fixed_0_stringt16inletsegname=fixed_0_stringt16inletaddr=Read.u64tinletsize=Read.u64tinlet_offset=Read.u32tinletalign=1lslRead.u32tinletreloff=Read.u32tinletnreloc=Read.u32tinletrelocs=read_n_times(read_relocationheader)(cursorbuf~at:reloff)nrelocinletflags=Read.u32tinlet_reserved=Read.u32tinlet_reserved=Read.u32tinlet_reserved=Read.u32tinletsec_type=sec_typeflagsinletuser_attrs=sec_user_attrflagsinletsys_attrs=sec_sys_attrflagsin{sec_sectname=sectname;sec_segname=segname;sec_addr=addr;sec_size=size;sec_align=align;sec_relocs=relocs;sec_type=sec_type;sec_user_attrs=user_attrs;sec_sys_attrs=sys_attrs;}letread_segment_64headerbuft=letsegname=fixed_0_stringt16inletvmaddr=Read.u64tinletvmsize=Read.u64tinletfileoff=Read.u64tinletfilesize=Read.u64tinletmaxprot=read_vm_prottinletinitprot=read_vm_prottinletnsects=Read.u32tinletflags=read_seg_flagtinletsects=read_n_times(read_section_64headerbuf)tnsectsin{seg_segname=segname;seg_vmaddr=vmaddr;seg_vmsize=vmsize;seg_fileoff=fileoff;seg_filesize=filesize;seg_maxprot=maxprot;seg_initprot=initprot;seg_flags=flags;seg_sections=sects;}letread_routines_command_32t=letinit_address=Read.u32tinletinit_module=Read.u32tinlet_reserved1=Read.u32tinlet_reserved2=Read.u32tinlet_reserved3=Read.u32tinlet_reserved4=Read.u32tinlet_reserved5=Read.u32tinlet_reserved6=Read.u32tinLC_ROUTINES_32(init_address,init_module)letread_routines_command_64t=letinit_address=Read.u64tinletinit_module=Read.u64tinlet_reserved1=Read.u64tinlet_reserved2=Read.u64tinlet_reserved3=Read.u64tinlet_reserved4=Read.u64tinlet_reserved5=Read.u64tinlet_reserved6=Read.u64tinLC_ROUTINES_64(init_address,init_module)letread_uuid_commandt=LC_UUID(Read.fixed_stringt8)letread_rpath_commandbuft=letoffset=Read.u32tinmatchRead.zero_string(cursorbuf~at:offset)()with|None->invalid_format"invalid rpath"|Somes->LC_RPATHsletread_link_edittk=letdataoff=Read.u32tinletdatasize=Read.u32tinkdataoffdatasizeletread_prebound_dylibbuft=letname=read_lc_stringbuftinletnmodules=Read.u32tinletmodulesoff=Read.u32tinletmodules=read_n_timesRead.u8(cursor~at:modulesoffbuf)(nmodules/8+nmodulesmod8)in(name,modules)letread_symbolread_valueheaderbuft=letsym_name=read_symbol_nametbufinletsym_type=Read.u8tinletstabs,sym_pext,sym_type,sym_ext=sym_typessym_typeinletsym_sect=Read.u8tinletsym_flags=Read.u16tinletsym_flags=ifstabsthen`Uninterpretedsym_flagselse`Flags(reference_flagsheadersym_flags)inletsym_value=read_valuetin{sym_name;sym_type;sym_pext;sym_ext;sym_sect;sym_flags;sym_value;}letread_symbol_tableheaderbuft=letsymoff=Read.u32tinletnsyms=Read.u32tinletstroff=Read.u32tinletstrsize=Read.u32tinPrintf.eprintf"symoff: %d, nsyms: %d, stroff: %d, strsize: %d\n"symoffnsymsstroffstrsize;Printf.eprintf"buffer size: %d\n%!"(Bigarray.Array1.dimbuf);letstrsect=sub(cursorbuf~at:stroff)strsizeinletf=ifis64bitheaderthenRead.u64else(funx->Int64.of_int(Read.u32x))inletread_symbol=read_symbolfinletsymcursor=cursorbuf~at:symoffinletsymbols=read_n_times(read_symbolheaderstrsect.buffer)symcursornsymsin(symbols,strsect.buffer)letread_load_commandheaderbuft=letcmd=Read.u32tinletcmdsize=Read.u32tinlett=subt(cmdsize-8)inmatchcmdwith|0x00000001->LC_SEGMENT_32(lazy(read_segment_32headerbuft))|0x00000002->LC_SYMTAB(lazy(read_symbol_tableheaderbuft))|0x00000004->LC_THREAD(lazy(read_threadt))|0x00000005->LC_UNIXTHREAD(lazy(read_threadt))|0x0000000b->LC_DYSYMTAB(lazy(read_dynamic_symbol_tableheadertbuf))|0x0000000e->LC_LOAD_DYLINKER(read_lc_stringt.buffert)|0x0000000f->LC_ID_DYLINKER(read_lc_stringt.buffert)|0x00000010->LC_PREBOUND_DYLIB(lazy(read_prebound_dylibt.buffert))|0x00000011->read_routines_command_32t|0x00000012->LC_SUB_FRAMEWORK(read_lc_stringt.buffert)|0x00000013->LC_SUB_UMBRELLA(read_lc_stringt.buffert)|0x00000014->LC_SUB_CLIENT(read_lc_stringt.buffert)|0x00000015->LC_SUB_LIBRARY(read_lc_stringt.buffert)|0x00000016->LC_TWOLEVEL_HINTS(lazy(read_twolevelhintst.buffert))|0x00000017->LC_PREBIND_CKSUM(Read.u32t)|0x00000019->LC_SEGMENT_64(lazy(read_segment_64headerbuft))|0x0000001a->read_routines_command_64t|0x0000001b->read_uuid_commandt|0x0000001d->read_link_editt(funab->LC_CODE_SIGNATURE(a,b))|0x0000001e->read_link_editt(funab->LC_SEGMENT_SPLIT_INFO(a,b))|0x0000000c->LC_LOAD_DYLIB(lazy(read_dylib_commandtt.buffer))|0x0000000d->LC_ID_DYLIB(lazy(read_dylib_commandtt.buffer))|0x80000018->LC_LOAD_WEAK_DYLIB(lazy(read_dylib_commandtt.buffer))|0x8000001c->read_rpath_commandbuft|n->LC_UNHANDLED(n,t.buffer)letrecread_load_commandsheaderbuft=ifat_endtthen[]elseletlc=read_load_commandheaderbuftinlc::read_load_commandsheaderbuftletreadbuf=lett=cursorbufinletsize_of_commands,header=read_headertinlett=subtsize_of_commandsinletcommands=read_load_commandsheaderbuftin(header,commands)letsection_bodybuffersegsec=letaddr=Int64.addseg.seg_fileoffsec.sec_addrinBigarray.Array1.subbuffer(Int64.to_intaddr)(Int64.to_intsec.sec_size)