12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244openOwee_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|`ARM64|`ARM64_32|`POWERPC|`POWERPC64|unknown]letcpu_type=function|0x00000007->`X86|0x01000007->`X86_64|0x0000000c->`ARM|0x0100000c->`ARM64(* ABI for 64-bit hardware *)|0x0200000c->`ARM64_32(* ABI for 64-bit hardware with 32-bit types; LP32 *)|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)