12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2026 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)openBasic_types.IntegersopenReaderopenLoader_typesmoduleE_class=structtypet=[`x32|`x64]letof_u8=function|1->`x32|2->`x64|_->invalid_format"Invalid elf class"letppppf=function|`x32->Format.fprintfppf"ELF32"|`x64->Format.fprintfppf"ELF64"endletcheck_magicbuffer=(not(Bigarray.Array1.dimbuffer<4))&&buffer.{0}=0x7f&&buffer.{1}=Char.code'E'&&buffer.{2}=Char.code'L'&&buffer.{3}=Char.code'F'moduleE_ident=structtypet={kind:E_class.t;data:Machine.endianness;version:u8;osabi:u8;abiversion:u8;}letendian=function|1->Machine.LittleEndian|2->Machine.BigEndian|_->invalid_format"Unknown ELF data"letreadbuffer=ifBigarray.Array1.dimbuffer<16theninvalid_format"Identification truncated";letkind=E_class.of_u8buffer.{4}inletdata=endianbuffer.{5}inletversion=Int.unsafe_to_uint8buffer.{6}inletosabi=Int.unsafe_to_uint8buffer.{7}inletabiversion=Int.unsafe_to_uint8buffer.{8}inifnot(buffer.{9}=0&&buffer.{10}=0&&buffer.{11}=0&&buffer.{12}=0&&buffer.{13}=0&&buffer.{14}=0&&buffer.{15}=0)theninvalid_format"Invalid padding after identification";{kind;data;version;osabi;abiversion}letinit_cursorbuffer=ifnot(check_magicbuffer)theninvalid_format"No ELF magic number";letident=readbufferin(of_bigarray~pos:16~endianness:ident.databuffer,ident)endmoduleEhdr=structmoduleET=structtypet=NONE|REL|EXEC|DYN|CORE|OSofint|PROCofintletof_u16=function|0->NONE|1->REL|2->EXEC|3->DYN|4->CORE|twhen0xfe00<=t&&t<0xff00->OSt|twhen0xff00<=t&&t<=0xffff->PROCt|_->raise@@Invalid_argument"Not a valid type"letppvxvformatppf=function|NONE->Format.fprintfppf"NONE"|REL->Format.fprintfppf"REL"|EXEC->Format.fprintfppf"EXEC"|DYN->Format.fprintfppf"DYN"|CORE->Format.fprintfppf"CORE"|OSt->vformatppft|PROCt->Format.fprintfppf"PROC(%04x)"tletpp=ppvx(funppf->Format.fprintfppf"OS(%04x)")end(* Program header *)typet={ident:E_ident.t;kind:ET.t;machine:Machine.t;version:u32;entry:Virtual_address.t;phoff:int;shoff:int;flags:u32;ehsize:u16;phentsize:int;phnum:int;shentsize:int;shnum:int;shstrndx:int;}letarchendianness(mode:[`x64|`x32])entry=function(* | 0x02 -> Machine.SPARC *)|0x03->Machine.x86(* | 0x08 -> Machine.MIPS
* | 0x0a -> Machine.MIPS *)|0x12->Machine.sparcv8(* | 0x14 -> Machine.PowerPC *)|0x15->Machine.ppc64endianness|0x28->Machine.armv7endianness~thumb:(ifVirtual_address.modientry2=0thenFalseelseTrue)(* | 0x2b -> Machine.SPARC
* | 0x32 -> Machine.IA64
* | 0x33 -> Machine.MIPS *)|0x3e->Machine.amd64|0xb7->Machine.armv8endianness(* | 0xcb -> Machine.XCORE *)|0xf3->Machine.riscv(mode:>[`x128|`x64|`x32])|_->Machine.unknownletread_32tident=ensuret36"Program header truncated";letkind=ET.of_u16(Uint16.to_int(Read.u16t))inletmachine=Uint16.to_int(Read.u16t)inletversion=Read.u32tinletentry=Virtual_address.of_uint32(Read.u32t)inletmachine=archident.E_ident.dataident.E_ident.kindentrymachineinletphoff=Uint32.to_int(Read.u32t)inletshoff=Uint32.to_int(Read.u32t)inletflags=Read.u32tinletehsize=Read.u16tinletphentsize=Uint16.to_int(Read.u16t)inletphnum=Uint16.to_int(Read.u16t)inletshentsize=Uint16.to_int(Read.u16t)inletshnum=Uint16.to_int(Read.u16t)inletshstrndx=Uint16.to_int(Read.u16t)in{kind;machine;version;entry;phoff;shoff;flags;ehsize;phentsize;phnum;shentsize;shnum;shstrndx;ident;}letread_64tident=ensuret48"Program header truncated";letkind=ET.of_u16(Uint16.to_int(Read.u16t))inletmachine=Uint16.to_int(Read.u16t)inletversion=Read.u32tinletentry=Virtual_address.of_uint64(Read.u64t)inletmachine=archident.E_ident.dataident.E_ident.kindentrymachineinletphoff=Uint64.to_int(Read.u64t)inletshoff=Uint64.to_int(Read.u64t)inletflags=Read.u32tinletehsize=Read.u16tinletphentsize=Uint16.to_int(Read.u16t)inletphnum=Uint16.to_int(Read.u16t)inletshentsize=Uint16.to_int(Read.u16t)inletshnum=Uint16.to_int(Read.u16t)inletshstrndx=Uint16.to_int(Read.u16t)in{kind;machine;version;entry;phoff;shoff;flags;ehsize;phentsize;phnum;shentsize;shnum;shstrndx;ident;}letreadtident=matchident.E_ident.kindwith|`x32->read_32tident|`x64->read_64tidentletppvx=letcolumns=[|Prettytbl.Column.default;Prettytbl.Column.default|]infunvrowsppfh->lett=Prettytbl.makecolumnsinPrettytbl.appendt[|"Class:";Format.asprintf"%a"E_class.pph.ident.E_ident.kind|];(* 2's complement as long as endianness has successfully been read 1 | 2 *)Prettytbl.appendt[|"Data:";Format.asprintf"2's complement, %a"Machine.Endianness.pph.ident.E_ident.data;|];Prettytbl.appendt[|"Type:";Format.asprintf"%a"ET.pph.kind|];Array.iter(funvrow->Prettytbl.appendtvrow)vrows;Prettytbl.appendt[|"Machine:";Format.asprintf"%a"Machine.ISA.pph.machine|];ifh.kind<>ET.RELthenPrettytbl.appendt[|"Entry point address:";Format.asprintf"%a"Virtual_address.pph.entry;|];Format.fprintfppf"@[<v 2>ELF Header:@\n";Prettytbl.ppppft;Format.pp_close_boxppf()letpp=ppvx[||]endmoduleShdr=structmoduleSHT=structtypet=|NULL|PROGBITS|SYMTAB|STRTAB|RELA|HASH|DYNAMIC|NOTE|NOBITS|REL|SHLIB|DYNSYM|INIT_ARRAY|FINI_ARRAY|PREINIT_ARRAY|GROUP|SYMTAB_SHNDX|RELR|OSofint32|PROCofint32|USERofint32letof_u32=function|0l->NULL|1l->PROGBITS|2l->SYMTAB|3l->STRTAB|4l->RELA|5l->HASH|6l->DYNAMIC|7l->NOTE|8l->NOBITS|9l->REL|10l->SHLIB|11l->DYNSYM|14l->INIT_ARRAY|15l->FINI_ARRAY|16l->PREINIT_ARRAY|17l->GROUP|18l->SYMTAB_SHNDX|19l->RELR|twhen0x60000000l<=t&&t<0x70000000l->OSt|twhen0x70000000l<=t(* < 0x80000000l *)->PROCt|twhent<0l(* 0x80000000l <= t <= 0xffffffffl *)->USERt|_->raise@@Invalid_argument"Not a valid section type"letppvxvformatppf=function|NULL->Format.fprintfppf"NULL"|PROGBITS->Format.fprintfppf"PROGBITS"|SYMTAB->Format.fprintfppf"SYMTAB"|STRTAB->Format.fprintfppf"STRTAB"|RELA->Format.fprintfppf"RELA"|HASH->Format.fprintfppf"HASH"|DYNAMIC->Format.fprintfppf"DYNAMIC"|NOTE->Format.fprintfppf"NOTE"|NOBITS->Format.fprintfppf"NOBITS"|REL->Format.fprintfppf"REL"|SHLIB->Format.fprintfppf"SHLIB"|DYNSYM->Format.fprintfppf"DYNSYM"|INIT_ARRAY->Format.fprintfppf"INIT_ARRAY"|FINI_ARRAY->Format.fprintfppf"FINI_ARRAY"|PREINIT_ARRAY->Format.fprintfppf"PREINIT_ARRAY"|GROUP->Format.fprintfppf"GROUP"|SYMTAB_SHNDX->Format.fprintfppf"SYMTAB_SHNDX"|RELR->Format.fprintfppf"RELR"|OSt->vformatppft|PROCt->Format.fprintfppf"PROC(%08lx)"t|USERt->Format.fprintfppf"USER(%08lx)"tletpp=ppvx(funppf->Format.fprintfppf"OS(%08lx)")endmoduleSHF=structtypet=|WRITE|ALLOC|EXECINSTR|MERGE|STRINGS|INFO_LINK|LINK_ORDER|OS_NONCONFORMING|GROUP|TLS|OS|PROCletisff'=letf=Uint64.to_int64finmatchf'with|WRITE->Int64.logandf0x1L<>0L|ALLOC->Int64.logandf0x2L<>0L|EXECINSTR->Int64.logandf0x4L>0L|MERGE->Int64.logandf0x10L>0L|STRINGS->Int64.logandf0x20L>0L|INFO_LINK->Int64.logandf0x40L>0L|LINK_ORDER->Int64.logandf0x80L>0L|OS_NONCONFORMING->Int64.logandf0x100L>0L|GROUP->Int64.logandf0x200L>0L|TLS->Int64.logandf0x400L>0L|OS->Int64.logandf0x0ff00000L>0L|PROC->Int64.logandf0xf0000000L>0Lletrepr=function|WRITE->'W'|ALLOC->'A'|EXECINSTR->'X'|MERGE->'M'|STRINGS->'S'|INFO_LINK->'I'|LINK_ORDER->'L'|OS_NONCONFORMING->'O'|GROUP->'G'|TLS->'T'|OS->'o'|PROC->'p'letifpptppff=ifisftthenFormat.fprintfppf"%c"@@reprtletppppff=ifppWRITEppff;ifppALLOCppff;ifppEXECINSTRppff;ifppMERGEppff;ifppSTRINGSppff;ifppINFO_LINKppff;ifppLINK_ORDERppff;ifppOS_NONCONFORMINGppff;ifppGROUPppff;ifppTLSppffend(* Section header *)typet={idx:int;name:string;kind:SHT.t;flags:u64;addr:Virtual_address.t;offset:int;size:int;link:int;info:u32;addralign:u64;entsize:int;}letdummy={idx=0;name="";kind=SHT.NULL;flags=Int64.to_uint640L;addr=Virtual_address.zero;offset=0;size=0;link=0;info=Int32.to_uint320l;addralign=Int64.to_uint640L;entsize=0;}letread_32t=ensuret40"Section header truncated";letidx=Uint32.to_int(Read.u32t)inletkind=SHT.of_u32(Uint32.to_int32(Read.u32t))inletflags=Uint32.to_uint64(Read.u32t)inletaddr=Virtual_address.of_uint32(Read.u32t)inletoffset=Uint32.to_int(Read.u32t)inletsize=Uint32.to_int(Read.u32t)inletlink=Uint32.to_int(Read.u32t)inletinfo=Read.u32tinletaddralign=Uint32.to_uint64(Read.u32t)inletentsize=Uint32.to_int(Read.u32t)in{idx;name="";kind;flags;addr;offset;size;link;info;addralign;entsize;}letread_64t=ensuret64"Section header truncated";letidx=Uint32.to_int(Read.u32t)inletkind=SHT.of_u32(Uint32.to_int32(Read.u32t))inletflags=Read.u64tinletaddr=Virtual_address.of_uint64(Read.u64t)inletoffset=Uint64.to_int(Read.u64t)inletsize=Uint64.to_int(Read.u64t)inletlink=Uint32.to_int(Read.u32t)inletinfo=Read.u32tinletaddralign=Read.u64tinletentsize=Uint64.to_int(Read.u64t)in{idx;name="";kind;flags;addr;offset;size;link;info;addralign;entsize;}letreadtheadern=set_postEhdr.(header.shoff+(n*header.shentsize));matchheader.Ehdr.ident.E_ident.kindwith|`x32->read_32t|`x64->read_64tletwith_nametshstrndxshdr=letn=shdr.idxinset_post(shstrndx.offset+n);Read.zero_string"Unterminated section name"t~maxlen:(shstrndx.size-n)()letread_alltheader=ifheader.Ehdr.shnum=0then[||]elseletsections=Array.initheader.Ehdr.shnum(readtheader)inletshstrndx=sections.(header.Ehdr.shstrndx)inArray.iteri(funis->sections.(i)<-{swithidx=i;name=with_nametshstrndxs})sections;sectionsletcontainsaddrsection=(* [Improvement] Maybe there is a better, more generic way to handle the
problem below than checking for the SHF_ALLOC flag. But it fixes the
behavior of the loader/disassembly on .o files. *)SHF.(issection.flagsALLOC)&&addr>=section.addr&&addr<Virtual_address.add_intsection.sizesection.addrletfind_by_namesectionsname=Array_utils.find_opt(funs->s.name=name)sectionsletpretty_formats,pretty_names=([|Prettytbl.(Column.make~max_length:2~left_border:"["~right_border:"]"~align:R());Prettytbl.(Column.make~max_length:16());Prettytbl.(Column.make~max_length:10());Prettytbl.(Column.make~max_length:16());Prettytbl.(Column.make~max_length:6());Prettytbl.(Column.make~max_length:6());Prettytbl.(Column.make~max_length:2());Prettytbl.(Column.make~max_length:3~align:R());Prettytbl.(Column.make~max_length:2~align:R());Prettytbl.(Column.make~max_length:3~align:R());Prettytbl.(Column.make~max_length:2~align:R());|],[|"Nr";"Name";"Type";"Addr";"Off";"Size";"ES";"Flg";"Lk";"Inf";"Al";|])letppvx_all(aformat:E_class.t)vformatppfsections=lett=Prettytbl.makepretty_formatsinPrettytbl.appendtpretty_names;Array.iter(funsection->Prettytbl.appendt[|string_of_intsection.idx;section.name;Format.asprintf"%a"(SHT.ppvxvformat)section.kind;Format.asprintf"%a"(Virtual_address.pp_print(aformat:>[`x16|`x32|`x64]))section.addr;Printf.sprintf"%06x"section.offset;Printf.sprintf"%06x"section.size;Printf.sprintf"%02x"section.entsize;Format.asprintf"%a"SHF.ppsection.flags;string_of_intsection.link;Z.to_string(Uint32.to_bigintsection.info);Z.to_string(Uint64.to_bigintsection.addralign);|])sections;Format.fprintfppf"@[<v 2>Section Headers:@\n";Prettytbl.ppppft;Format.fprintfppf"@]@\n\
@[<hov 2>Key to Flags:@\n\
W (write),@ A (alloc),@ X (execute),@ M (merge),@ S (strings),@ I \
(info),@ L (link order),@ G (group),@ T (TLS),@ O (extra OS processing \
required)@]"moduleSHN=structtypesection=ttypet=UNDEF|SECofsection|PROCofint|OSofint|ABS|COMMON(* | XINDEX *)letof_u16sections=function|0x0000->UNDEF|nwhen0x0000<n&&n<0xff00->SEC(sectionsn)|nwhen0xff00<=n&&n<0xff20->PROCn|nwhen0xff20<=n&&n<0xff40->OSn|0xfff1->ABS|0xfff2->COMMON|_->raise@@Invalid_argument"Not a valid section indexes"letppppf=function|UNDEF->Format.fprintfppf"UND"|SECs->Format.fprintfppf"%s"s.name|PROCn->Format.fprintfppf"PROC(%d)"n|OSn->Format.fprintfppf"OS(%d)"n|ABS->Format.fprintfppf"ABS"|COMMON->Format.fprintfppf"COM"endendmoduleSym=structmoduleSTT=structtypet=|NOTYPE|OBJECT|FUNC|SECTION|FILE|COMMON|TLS|OSofint|PROCofintletof_u8i=matchiland0xfwith|0->NOTYPE|1->OBJECT|2->FUNC|3->SECTION|4->FILE|6->TLS|twhen10<=t&&t<13->OSt|twhen13<=t&&t<=15->PROCt|_->raise@@Invalid_argument"Not a valid symbol type"letppvxvformatppf=function|NOTYPE->Format.fprintfppf"NOTYPE"|OBJECT->Format.fprintfppf"OBJECT"|FUNC->Format.fprintfppf"FUNC"|SECTION->Format.fprintfppf"SECTION"|FILE->Format.fprintfppf"FILE"|COMMON->Format.fprintfppf"COMMON"|TLS->Format.fprintfppf"TLS"|OSt->vformatppft|PROCt->Format.fprintfppf"PROC(%x)"tletpp=ppvx(funppf->Format.fprintfppf"OS(%x)")endmoduleSTB=structtypet=LOCAL|GLOBAL|WEAK|OSofint|PROCofintletof_u8i=matchilsr4with|0->LOCAL|1->GLOBAL|2->WEAK|bwhen10<=b&&b<13->OSb|bwhen13<=b&&b<=15->PROCb|_->raise@@Invalid_argument"Not a valid symbol binding"letppppf=function|LOCAL->Format.fprintfppf"LOCAL"|GLOBAL->Format.fprintfppf"GLOBAL"|WEAK->Format.fprintfppf"WEAK"|OSb->Format.fprintfppf"OS(%x)"b|PROCb->Format.fprintfppf"PROC(%x)"bend(* Symbol header *)typet={name:string;kind:STT.t;bind:STB.t;other:u8;sh:Shdr.SHN.t;value:Virtual_address.t;size:int;}letread_namet(strtab:Shdr.t)idx=set_post(strtab.offset+idx);Read.zero_string"Unterminated symbol name"t~maxlen:(strtab.size-idx)()letread_32tsectionsnames=ensuret16"Symbol header truncated";letidx=Uint32.to_int(Read.u32t)inletvalue=Virtual_address.of_uint32(Read.u32t)inletsize=Uint32.to_int(Read.u32t)inletinfo=Uint8.to_int(Read.u8t)inletkind=STT.of_u8infoinletbind=STB.of_u8infoinletother=Read.u8tinletsh=Shdr.SHN.of_u16sections(Uint16.to_int(Read.u16t))in{name=namesidx;kind;bind;other;sh;value;size}letread_64tsectionsnames=ensuret24"Symbol header truncated";letidx=Uint32.to_int(Read.u32t)inletinfo=Uint8.to_int(Read.u8t)inletkind=STT.of_u8infoinletbind=STB.of_u8infoinletother=Read.u8tinletsh=Shdr.SHN.of_u16sections(Uint16.to_int(Read.u16t))inletvalue=Virtual_address.of_uint64(Read.u64t)inletsize=Uint64.to_int(Read.u64t)in{name=namesidx;kind;bind;other;sh;value;size}letreadtheadersectionssymtabstrtabn=set_postShdr.(symtab.offset+(n*symtab.entsize));matchheader.Ehdr.ident.E_ident.kindwith|`x32->read_32tsectionsstrtab|`x64->read_64tsectionsstrtabletread_alltheadersections=Array.map(funsection->matchsection.Shdr.kindwith|(Shdr.SHT.SYMTAB|Shdr.SHT.DYNSYM)whensection.Shdr.entsize<>0->Array.init(section.Shdr.size/section.Shdr.entsize)(readtheader(Array.getsections)section(read_nametsections.(section.Shdr.link)))|_->[||])sectionsletpretty_formats,pretty_names=([|Prettytbl.(Column.make~max_length:3~right_border:":"~align:R());Prettytbl.(Column.make~max_length:16~align:R());Prettytbl.(Column.make~max_length:10~align:R());Prettytbl.(Column.make~max_length:8());Prettytbl.(Column.make~max_length:8());Prettytbl.(Column.make~max_length:16());Prettytbl.(Column.make~max_length:20());|],[|"Num";"Value";"Size";"Type";"Bind";"Section";"Name"|])letppvx_all(iformat:E_class.t)vformatppfsymbols=lett=Prettytbl.makepretty_formatsinPrettytbl.appendtpretty_names;Array.iteri(funisymbol->Prettytbl.appendt[|string_of_inti;Format.asprintf"%a"(Virtual_address.pp_print(iformat:>[`x16|`x32|`x64]))symbol.value;string_of_intsymbol.size;Format.asprintf"%a"(STT.ppvxvformat)symbol.kind;Format.asprintf"%a"STB.ppsymbol.bind;Format.asprintf"%a"Shdr.SHN.ppsymbol.sh;symbol.name;|])symbols;Prettytbl.ppppft;Format.pp_close_boxppf()endmodulePhdr=structmodulePHT=structtypet=|NULL|LOAD|DYNAMIC|INTERP|NOTE|SHLIB|PHDR|TLS|OSofint32|PROCofint32letof_u32=function|0l->NULL|1l->LOAD|2l->DYNAMIC|3l->INTERP|4l->NOTE|5l->SHLIB|6l->PHDR|7l->TLS|twhen0x60000000l<=t&&t<0x70000000l->OSt|twhen0x70000000l<=t(* < 0x80000000l *)->PROCt|_->raise@@Invalid_argument"Not a valid segment type"letppvxvformatppf=function|NULL->Format.fprintfppf"NULL"|LOAD->Format.fprintfppf"LOAD"|DYNAMIC->Format.fprintfppf"DYNAMIC"|INTERP->Format.fprintfppf"INTERP"|NOTE->Format.fprintfppf"NOTE"|SHLIB->Format.fprintfppf"SHLIB"|PHDR->Format.fprintfppf"PHDR"|TLS->Format.fprintfppf"TLS"|OSt->vformatppft|PROCt->Format.fprintfppf"PROC(%08lx)"tletpp=ppvx(funppf->Format.fprintfppf"OS(%08lx)")endmodulePHF=structtypet=X|W|R|OSofint32|PROCofint32letisff'=letf=Uint32.to_int32finmatchf'with|X->Int32.logandf0x1l<>0l|W->Int32.logandf0x2l<>0l|R->Int32.logandf0x4l>0l|OS_->Int32.logandf0x0ff00000l>0l|PROC_->Int32.logandf0xf0000000l>0lletrepr=function|X->'E'|W->'W'|R->'R'|OS_->'o'|PROC_->'p'letifpptppff=Format.pp_print_charppf(ifisftthenreprtelse' ')letppppff=ifppRppff;ifppWppff;ifppXppffend(* ELF program header *)typet={kind:PHT.t;flags:u32;offset:int;vaddr:Virtual_address.t;paddr:u64;filesz:int;memsz:u64;align:u64;}letdummy={kind=NULL;flags=Int32.to_uint320l;offset=0;vaddr=Virtual_address.zero;paddr=Int64.to_uint640L;filesz=0;memsz=Int64.to_uint640L;align=Int64.to_uint640L;}letread_32t=ensuret32"Program header truncated";letkind=PHT.of_u32(Uint32.to_int32(Read.u32t))inletoffset=Uint32.to_int(Read.u32t)inletvaddr=Virtual_address.of_uint32(Read.u32t)inletpaddr=Uint32.to_uint64(Read.u32t)inletfilesz=Uint32.to_int(Read.u32t)inletmemsz=Uint32.to_uint64(Read.u32t)inletflags=Read.u32tinletalign=Uint32.to_uint64(Read.u32t)in{kind;flags;offset;vaddr;paddr;filesz;memsz;align}letread_64t=ensuret56"Program header truncated";letkind=PHT.of_u32(Uint32.to_int32(Read.u32t))inletflags=Read.u32tinletoffset=Uint64.to_int(Read.u64t)inletvaddr=Virtual_address.of_uint64(Read.u64t)inletpaddr=Read.u64tinletfilesz=Uint64.to_int(Read.u64t)inletmemsz=Read.u64tinletalign=Read.u64tin{kind;flags;offset;vaddr;paddr;filesz;memsz;align}letreadtheadern=set_postEhdr.(header.phoff+(n*header.phentsize));matchheader.Ehdr.ident.E_ident.kindwith|`x32->read_32t|`x64->read_64tletread_alltheader=Array.initheader.Ehdr.phnum(readtheader)letcontainsaddrpheader=addr>=pheader.vaddr&&addr<Virtual_address.add_bigint(Uint64.to_bigintpheader.memsz)pheader.vaddrletpretty_formats32,pretty_formats64,pretty_names=([|Prettytbl.(Column.make~max_length:16());Prettytbl.(Column.make~max_length:8());Prettytbl.(Column.make~max_length:10());Prettytbl.(Column.make~max_length:10());Prettytbl.(Column.make~max_length:8());Prettytbl.(Column.make~max_length:8());Prettytbl.(Column.make~max_length:3~align:R());Prettytbl.(Column.make~max_length:6~align:R());|],[|Prettytbl.(Column.make~max_length:16());Prettytbl.(Column.make~max_length:8());Prettytbl.(Column.make~max_length:18());Prettytbl.(Column.make~max_length:18());Prettytbl.(Column.make~max_length:8());Prettytbl.(Column.make~max_length:8());Prettytbl.(Column.make~max_length:3());Prettytbl.(Column.make~max_length:6());|],[|"Type";"Offset";"VirtAddr";"PhysAddr";"FileSiz";"MemSiz";"Flg";"Align";|])letppvx_all(aformat:E_class.t)vformatppfsegments=lett=Prettytbl.make(matchaformatwith|`x32->pretty_formats32|`x64->pretty_formats64)inPrettytbl.appendtpretty_names;Array.iter(funsegment->Prettytbl.appendt[|Format.asprintf"%a"(PHT.ppvxvformat)segment.kind;Printf.sprintf"%#08x"segment.offset;Format.asprintf"0x%a"(Virtual_address.pp_print(aformat:>[`x16|`x32|`x64]))segment.vaddr;Format.asprintf"0x%a"(Virtual_address.pp_print(aformat:>[`x16|`x32|`x64]))(Virtual_address.of_uint64segment.paddr);Printf.sprintf"%#08x"segment.filesz;Printf.sprintf"%#08Lx"(Uint64.to_int64segment.memsz);Format.asprintf"%a"PHF.ppsegment.flags;Printf.sprintf"%#Lx"(Uint64.to_int64segment.align);|])segments;Format.fprintfppf"@[<v 2>Program Headers:@ ";Prettytbl.ppppft;Format.pp_close_boxppf()endmoduleSection=structtypet=Shdr.ttypeheader=tletnames=s.Shdr.nameletflags=s.Shdr.flagsletposs={raw=s.Shdr.offset;virt=s.Shdr.addr}letsizes=letraw=ifShdr.(s.kind=SHT.NOBITS)then0elses.Shdr.sizein{raw;virt=Z.of_ints.Shdr.size}letheader:t->header=Fun.idlethas_flagfs=letmask=matchfwith|Write->Shdr.SHF.WRITE|Read->Shdr.SHF.ALLOC|Exec->Shdr.SHF.EXECINSTRinShdr.SHF.is(flags)maskendmoduleSymbol=structtypet=Sym.ttypeheader=tletnames=s.Sym.nameletvalues=s.Sym.valueletheaders=sendmoduleNote=structtypet={name:string;kind:int;offset:int;size:int}letreadt=letbase=get_postinletnamesz=Uint32.to_int(Read.u32t)inletsize=Uint32.to_int(Read.u32t)inletkind=Uint32.to_int(Read.u32t)inletname=Read.fixed_stringtnameszinset_post(base+((get_post-base+3)land-4));letoffset=get_postinadvancet((size+3)land-4);{name;kind;offset;size}letrecappend_allnotesboundcursor=ifget_poscursor>=boundthennoteselseappend_all(readcursor::notes)boundcursorendmodulerecVendor:sigtypet=Unknown|GNUofstringincludeSigs.PRINTABLEwithtypet:=tvalpretty_rows:t->stringarrayarraymoduleSection:sigvalppt:t->Format.formatter->int32->unitendmoduleSegment:sigvalppt:t->Format.formatter->int32->unitendmoduleSymbol:sigvalppt:t->Format.formatter->int->unitendvalread:Ehdr.t->Shdr.tarray->Sym.tarrayarray->buffer->Ehdr.t*t*Shdr.tarray*Sym.tarrayarray*bufferend=structtypet=Unknown|GNUofstringletppppf=function|Unknown->Format.fprintfppf"Unknown"|GNU_->Format.fprintfppf"GNU"letpretty_rows=function|Unknown->[||]|GNUkernel->[|[|"OS/ABI:";"Linux - GNU"|];[|"Kernel Version:";kernel|]|]moduleCommon=structletpptppfx=Format.fprintfppf"OS(%x)"xletppt8ppfx=Format.fprintfppf"OS(%08lx)"xendmoduleGNU=structmoduleSection=structletpptppf=function|0x6ffffff6l->Format.fprintfppf"GNU_HASH"|0x6ffffffdl->Format.fprintfppf"VERDEF"|0x6ffffffel->Format.fprintfppf"VERNEED"|0x6fffffffl->Format.fprintfppf"VERSYM"|twhen0x60000000l<=t&&t<0x70000000l->Format.fprintfppf"OS(%08lx)"t|_->raise@@Invalid_argument"Not a vendor specific type"endmoduleSegment=structletpptppf=function|0x6474e550l->Format.fprintfppf"GNU_EH_FRAME"|0x6474e551l->Format.fprintfppf"GNU_STACK"|0x6474e552l->Format.fprintfppf"GNU_RELRO"|0x6474e553l->Format.fprintfppf"GNU_PROPERTY"|twhen0x60000000l<=t&&t<0x70000000l->Format.fprintfppf"OS(%08lx)"t|_->raise@@Invalid_argument"Not a vendor specific type"endmoduleSymbol=structletpptppf=function|10->Format.fprintfppf"IFUNC"|twhen10<=t&&t<13->Common.pptppft|_->raise@@Invalid_argument"Not a vendor specific type"endendmoduleSection=structletppt=functionUnknown->Common.ppt8|GNU_->GNU.Section.pptendmoduleSegment=structletppt=functionUnknown->Common.ppt8|GNU_->GNU.Segment.pptendmoduleSymbol=structletppt=functionUnknown->Common.ppt|GNU_->GNU.Symbol.pptendletreadheadersectionssymbolsbuf=matchShdr.find_by_namesections".note.ABI-tag"with|None->(header,Unknown,sections,symbols,buf)|Somenote->letcursor=of_bigarray~pos:note.Shdr.offset~endianness:header.Ehdr.ident.E_ident.databufinletnamesz=Uint32.to_int(Read.u32cursor)inletdescsz=Uint32.to_int(Read.u32cursor)inletkind=Uint32.to_int(Read.u32cursor)inifkind=1thenletname=Read.zero_string"Inconsistent note format"cursor~maxlen:namesz()inifname="GNU"&&descsz=16then(letpadding=((nameszlxor0b11)+1)land0b11inadvancecursorpadding;ifRead.i32cursor=0lthenletversion=Uint32.to_int(Read.u32cursor)inletmajor=Uint32.to_int(Read.u32cursor)inletminor=Uint32.to_int(Read.u32cursor)inletkernel=Printf.sprintf"%d.%d.%d"versionmajorminorin(header,GNUkernel,sections,symbols,buf)else(header,Unknown,sections,symbols,buf))else(header,Unknown,sections,symbols,buf)else(header,Unknown,sections,symbols,buf)endandImg:sigtypet={header:Ehdr.t;vendor:Vendor.t;sections:Shdr.tarray;mutablelast_section:Shdr.t;symtabs:Sym.tarrayarray;buf:buffer;phdrs:Phdr.tarray;mutablelast_phdr:Phdr.t;notes:Note.tarray;}typeheader=Ehdr.tvalarch:t->Machine.tvalentry:t->Virtual_address.t(* val endian : t -> Machine.endianness *)valsections:t->Section.tarrayvalsymbols:t->Symbol.tarrayvalnotes:t->Note.tarrayvalheader:t->headervalcursor:?at:int->t->intReader.tvalcontent:t->Section.t->buffervalbuffer:t->bufferincludeSigs.PRINTABLEwithtypet:=tend=structtypet={header:Ehdr.t;vendor:Vendor.t;sections:Shdr.tarray;mutablelast_section:Shdr.t;symtabs:Sym.tarrayarray;buf:buffer;phdrs:Phdr.tarray;mutablelast_phdr:Phdr.t;notes:Note.tarray;}typeheader=Ehdr.tletarchi=i.header.Ehdr.machineletentryi=i.header.Ehdr.entry(* let endian i = i.header.Ehdr.ident.E_ident.data *)letsectionsi=Array.copyi.sectionsletsymbolsi=Array.concat@@Array.to_listi.symtabsletnotesi=i.notesletheaderi=i.headerletcursor?ati=of_bigarray?pos:at~endianness:i.header.Ehdr.ident.E_ident.datai.bufletcontenti(s:Shdr.t)=ifs.kind=Shdr.SHT.NOBITSthenBigarray.Array1.subi.buf00elseBigarray.Array1.subi.bufs.Shdr.offsets.sizeletbuffer{buf;_}=bufletppppft=lete_class=t.header.Ehdr.ident.E_ident.kindinletvrows=Vendor.pretty_rowst.vendorinFormat.fprintfppf"@[<v>%a@ @ %a@ @ "(Ehdr.ppvxvrows)t.header(Shdr.ppvx_alle_class(Vendor.Section.pptt.vendor))t.sections;ifArray.lengtht.phdrs<>0then(Phdr.ppvx_alle_class(Vendor.Segment.pptt.vendor)ppft.phdrs;Format.pp_print_spaceppf();Format.pp_print_spaceppf());Array.iteri(funisymbols->ifArray.lengthsymbols<>0then(Format.fprintfppf"@[<v 2>Symbol table '%s' contains %d entries:@\n"t.sections.(i).Shdr.name(Array.lengthsymbols);(Sym.ppvx_alle_class(Vendor.Symbol.pptt.vendor))ppfsymbols;Format.fprintfppf"@]@ @ "))t.symtabs;Format.pp_close_boxppf()endmoduleRel=structtypet={offset:Virtual_address.t;kind:int;symbol:Sym.t;addend:Z.toption;}letread32tsymbols=ensuret8"Relocation entry truncated";letoffset=Virtual_address.of_uint32(Read.u32t)inletinfo=Uint32.to_int(Read.u32t)inletkind=infoland0xffinletsymbol_idx=infolsr8in{offset;kind;symbol=symbolssymbol_idx;addend=None}letread64tsymbols=ensuret16"Relocation entry truncated";letoffset=Virtual_address.of_uint64(Read.u64t)inletinfo=Uint64.to_int64(Read.u64t)inletkind=Int64.to_int(Int64.logandinfo0xffffffffL)inletsymbol_idx=Int64.to_int(Int64.shift_right_logicalinfo32)in{offset;kind;symbol=symbolssymbol_idx;addend=None}letreada32tsymbols=ensuret12"Relocation entry truncated";{(read32tsymbols)withaddend=Some(Int32.to_bigint(Read.i32t))}letreada64tsymbols=ensuret24"Relocation entry truncated";{(read64tsymbols)withaddend=Some(Int64.to_bigint(Read.i64t))}letread(img:Img.t)(section:Shdr.t)=letcursor=of_bigarray~pos:section.offset~endianness:img.header.ident.dataimg.bufinletread=match(img.header.ident.kind,section.kind)with|`x32,REL->read32|`x32,RELA->reada32|`x64,REL->read64|`x64,RELA->reada64|_->invalid_format"Invalid ELF class"inletsymbols=Array.getimg.symtabssection.linkinifArray.lengthsymbols=0then[||]elseArray.init(section.size/section.entsize)(fun_->readcursor(Array.getsymbols))endmoduleDynamic=structmoduleDT=structtypet=|NULL|NEEDED|PLTRELSZ|PLTGOT|HASH|STRTAB|SYMTAB|RELA|RELASZ|RELAENT|STRSZ|SYMENT|INIT|FINI|SONAME|RPATH|SYMBOLIC|REL|RELSZ|RELENT|PLTREL|DEBUG|TEXTREL|JMPREL|BIND_NOW|INIT_ARRAY|FINI_ARRAY|INIT_ARRAYSZ|FINI_ARRAYSZ|RUNPATH|FLAGS|ENCODING|PREINIT_ARRAY|PREINIT_ARRAYSZ|Osofint32|VALRNGLO|CHECKSUM|PLTPADSZ|MOVEENT|MOVESZ|FEATURE_1|POSFLAG_1|SYMINSZ|SYMINENT|GNU_HASH|VALRNGHI|ADDRRNGLO|CONFIG|DEPAUDIT|AUDIT|PLTPAD|MOVETAB|SYMINFO|ADDRRNGHI|VERSYM|RELACOUNT|RELCOUNT|FLAGS_1|VERDEF|VERDEFNUM|VERNEED|VERNEEDNUM|Procofint32|Unknownofint32letof_int32:int32->t=function|0l->NULL|1l->NEEDED|2l->PLTRELSZ|3l->PLTGOT|4l->HASH|5l->STRTAB|6l->SYMTAB|7l->RELA|8l->RELASZ|9l->RELAENT|10l->STRSZ|11l->SYMENT|12l->INIT|13l->FINI|14l->SONAME|15l->RPATH|16l->SYMBOLIC|17l->REL|18l->RELSZ|19l->RELENT|20l->PLTREL|21l->DEBUG|22l->TEXTREL|23l->JMPREL|24l->BIND_NOW|25l->INIT_ARRAY|26l->FINI_ARRAY|27l->INIT_ARRAYSZ|28l->FINI_ARRAYSZ|29l->RUNPATH|30l->FLAGS|32l->PREINIT_ARRAY|33l->PREINIT_ARRAYSZ|xwhen0x6000000dl<=x&&x<0x6ffff000l->Osx|0x6ffffd00l->VALRNGLO|0x6ffffdf8l->CHECKSUM|0x6ffffdf9l->PLTPADSZ|0x6ffffdfal->MOVEENT|0x6ffffdfbl->MOVESZ|0x6ffffdfcl->FEATURE_1|0x6ffffdfdl->POSFLAG_1|0x6ffffdfel->SYMINSZ|0x6ffffdffl->SYMINENT|0x6ffffe00l->ADDRRNGLO|0x6ffffef5l->GNU_HASH|0x6ffffefal->CONFIG|0x6ffffefbl->DEPAUDIT|0x6ffffefcl->AUDIT|0x6ffffefdl->PLTPAD|0x6ffffefel->MOVETAB|0x6ffffeffl->SYMINFO|0x6ffffff0l->VERSYM|0x6ffffff9l->RELACOUNT|0x6ffffffal->RELCOUNT|0x6ffffffbl->FLAGS_1|0x6ffffffcl->VERDEF|0x6ffffffdl->VERDEFNUM|0x6ffffffel->VERNEED|0x6fffffffl->VERNEEDNUM|xwhen0x70000000l<x(* && x < 0x7fffffffl *)->Procx|x->UnknownxmoduleMap=Map.Make(structtypenonrect=tletcompare=compareend)letppppf=function|NULL->Format.pp_print_stringppf"DT_NULL"|NEEDED->Format.pp_print_stringppf"DT_NEEDED"|PLTRELSZ->Format.pp_print_stringppf"DT_PLTRELSZ"|PLTGOT->Format.pp_print_stringppf"DT_PLTGOT"|HASH->Format.pp_print_stringppf"DT_HASH"|STRTAB->Format.pp_print_stringppf"DT_STRTAB"|SYMTAB->Format.pp_print_stringppf"DT_SYMTAB"|RELA->Format.pp_print_stringppf"DT_RELA"|RELASZ->Format.pp_print_stringppf"DT_RELASZ"|RELAENT->Format.pp_print_stringppf"DT_RELAENT"|STRSZ->Format.pp_print_stringppf"DT_STRSZ"|SYMENT->Format.pp_print_stringppf"DT_SYMENT"|INIT->Format.pp_print_stringppf"DT_INIT"|FINI->Format.pp_print_stringppf"DT_FINI"|SONAME->Format.pp_print_stringppf"DT_SONAME"|RPATH->Format.pp_print_stringppf"DT_RPATH"|SYMBOLIC->Format.pp_print_stringppf"DT_SYMBOLIC"|REL->Format.pp_print_stringppf"DT_REL"|RELSZ->Format.pp_print_stringppf"DT_RELSZ"|RELENT->Format.pp_print_stringppf"DT_RELENT"|PLTREL->Format.pp_print_stringppf"DT_PLTREL"|DEBUG->Format.pp_print_stringppf"DT_DEBUG"|TEXTREL->Format.pp_print_stringppf"DT_TEXTREL"|JMPREL->Format.pp_print_stringppf"DT_JMPREL"|BIND_NOW->Format.pp_print_stringppf"DT_BIND_NOW"|INIT_ARRAY->Format.pp_print_stringppf"DT_INIT_ARRAY"|FINI_ARRAY->Format.pp_print_stringppf"DT_FINI_ARRAY"|INIT_ARRAYSZ->Format.pp_print_stringppf"DT_INIT_ARRAYSZ"|FINI_ARRAYSZ->Format.pp_print_stringppf"DT_FINI_ARRAYSZ"|RUNPATH->Format.pp_print_stringppf"DT_RUNPATH"|FLAGS->Format.pp_print_stringppf"DT_FLAGS"|ENCODING->Format.pp_print_stringppf"DT_ENCODING"|PREINIT_ARRAY->Format.pp_print_stringppf"DT_PREINIT_ARRAY"|PREINIT_ARRAYSZ->Format.pp_print_stringppf"DT_PREINIT_ARRAYSZ"|Osx->Format.fprintfppf"DT_OS(%lx)"x|VALRNGLO->Format.pp_print_stringppf"DT_VALRNGLO"|CHECKSUM->Format.pp_print_stringppf"DT_CHECKSUM"|PLTPADSZ->Format.pp_print_stringppf"DT_PLTPADSZ"|MOVEENT->Format.pp_print_stringppf"DT_MOVEENT"|MOVESZ->Format.pp_print_stringppf"DT_MOVESZ"|FEATURE_1->Format.pp_print_stringppf"DT_FEATURE_1"|POSFLAG_1->Format.pp_print_stringppf"DT_POSFLAG_1"|SYMINSZ->Format.pp_print_stringppf"DT_SYMINSZ"|SYMINENT->Format.pp_print_stringppf"DT_SYMINENT"|GNU_HASH->Format.pp_print_stringppf"DT_GNU_HASH"|VALRNGHI->Format.pp_print_stringppf"DT_VALRNGHI"|ADDRRNGLO->Format.pp_print_stringppf"DT_ADDRRNGLO"|CONFIG->Format.pp_print_stringppf"DT_CONFIG"|DEPAUDIT->Format.pp_print_stringppf"DT_DEPAUDIT"|AUDIT->Format.pp_print_stringppf"DT_AUDIT"|PLTPAD->Format.pp_print_stringppf"DT_PLTPAD"|MOVETAB->Format.pp_print_stringppf"DT_MOVETAB"|SYMINFO->Format.pp_print_stringppf"DT_SYMINFO"|ADDRRNGHI->Format.pp_print_stringppf"DT_ADDRRNGHI"|VERSYM->Format.pp_print_stringppf"DT_VERSYM"|RELACOUNT->Format.pp_print_stringppf"DT_RELACOUNT"|RELCOUNT->Format.pp_print_stringppf"DT_RELCOUNT"|FLAGS_1->Format.pp_print_stringppf"DT_FLAGS_1"|VERDEF->Format.pp_print_stringppf"DT_VERDEF"|VERDEFNUM->Format.pp_print_stringppf"DT_VERDEFNUM"|VERNEED->Format.pp_print_stringppf"DT_VERNEED"|VERNEEDNUM->Format.pp_print_stringppf"DT_VERNEEDNUM"|Procx->Format.fprintfppf"DT_PROC(%lx)"x|Unknownx->Format.fprintfppf"Unknown(%lx)"xendtypet=DT.t*uint64letread32t=ensuret8"Dynamic entry truncated";letkind=DT.of_int32(Uint32.to_int32(Read.u32t))inletvalue=Uint32.to_uint64(Read.u32t)in(kind,value)letread64t=ensuret16"Dynamic entry truncated";letkind=DT.of_int32(Uint64.to_int32(Read.u64t))inletvalue=Read.u64tin(kind,value)letread:Img.t->Phdr.t->uint64DT.Map.t=letrecloop:(intReader.t->t)->intReader.t->uint64DT.Map.t->uint64DT.Map.t=funreadcursorentries->matchreadcursorwith|NULL,_->entries|key,value->Loader_logger.debug"(%a, %Lx)"DT.ppkey(Uint64.to_int64value);loopreadcursor(DT.Map.addkeyvalueentries)infunimgsegment->letcursor=of_bigarray~pos:segment.offset~endianness:img.header.ident.dataimg.bufinletread=matchimg.header.ident.kindwith`x32->read32|`x64->read64inloopreadcursorDT.Map.emptyendletloadbuf=lett,e_ident=E_ident.init_cursorbufinletheader=Ehdr.readte_identinletsections=Shdr.read_alltheaderinletlast_section=ifArray.lengthsections=0thenShdr.dummyelseArray.getsections0inletphdrs=Phdr.read_alltheaderinletlast_phdr=ifArray.lengthphdrs=0thenPhdr.dummyelseArray.getphdrs0inletsymtabs=Sym.read_alltheadersectionsinletheader,vendor,sections,symtabs,buf=Vendor.readheadersectionssymtabsbufinletnotes=Array.fold_left(funnotess->ifs.Shdr.kind=Shdr.SHT.NOTEthen(set_posts.Shdr.offset;Note.append_allnotes(s.Shdr.offset+s.Shdr.size)t)elsenotes)[]sectionsinletnotes=Array.of_listnotesinletimg={Img.header;vendor;sections;last_section;symtabs;buf;phdrs;last_phdr;notes;}inimgletload_file_descrfile_descr=letbuffer=Bigarray.(array1_of_genarray(Unix.map_filefile_descrInt8_unsignedC_layoutfalse[|-1|]))inloadbufferletload_filepath=letfile_descr=Unix.openfilepath[Unix.O_RDONLY]0inletimg=load_file_descrfile_descrinUnix.closefile_descr;imgletread_offsetioffset=Int.unsafe_to_uint8i.Img.buf.{offset}letfind_section_by_addr_with_cache(i:Img.t)addr=ifShdr.containsaddri.last_sectiontheni.last_sectionelselets=Array_utils.find(Shdr.containsaddr)i.sectionsini.last_section<-s;sletfind_programme_header_by_addr_with_cache(i:Img.t)addr=ifPhdr.containsaddri.last_phdrtheni.last_phdrelseletp=Array_utils.find(Phdr.containsaddr)i.phdrsini.last_phdr<-p;pletread_addressiaddr=tryifArray.lengthi.Img.phdrs>0thenleth=find_programme_header_by_addr_with_cacheiaddrinletoffset=Virtual_address.diffaddrh.Phdr.vaddrinifoffset>h.Phdr.fileszthenInt.unsafe_to_uint80elseInt.unsafe_to_uint8i.Img.buf.{h.Phdr.offset+offset}elselets=find_section_by_addr_with_cacheiaddrinifs.Shdr.kind=Shdr.SHT.NOBITSthenInt.unsafe_to_uint80elseInt.unsafe_to_uint8i.Img.buf.{Virtual_address.diffaddrs.Shdr.addr+s.Shdr.offset}withNot_found->letmsg=Format.asprintf"Unreachable virtual address %a"Virtual_address.ppaddrininvalid_argmsgletprogram_headersi=i.Img.phdrsletnotes=Img.notestypefmap={addresses:Virtual_address.tInterval.t;offset:int;mutablename:string;}letfmapaddressesoffsetname={addresses;offset;name}letfiles(i:Img.t)=letread=matchi.header.ident.kindwith|`x32->funr->Uint32.to_int(Read.u32r)|`x64->funr->Uint64.to_int(Read.u64r)inArray.fold_left(funresult->function|{Note.name="CORE";kind=0x46494c45;offset=at;_}->letcursor=Img.cursor~atiinletn=readcursorinletps=readcursorinletfiles=Array.initn(fun_->letlo=Virtual_address.create(readcursor)inlethi=Virtual_address.create(readcursor)inletoffset=ps*readcursorin{addresses={Interval.lo;hi};offset;name=""})inArray.iter(funfmap->fmap.name<-Read.zero_string"files"cursor())files;files|_->result)[||]i.notesmoduleUtils=structletis_ifunc(img:Img.t)(sym:Sym.t)=matchimg.vendorwith|GNU_->(matchsym.kindwithOS10->true|_->false)|_->falseletgeneric_map_synthetic_symtab:Rel.tarray->plt:Shdr.t->plt0_size:int->pltn_size:int->(Virtual_address.t*string)list=funrel_plt~plt:{addr=base;_}~plt0_size~pltn_size->Array_utils.fold_righti(funisymtab({symbol={name;_};addend;_}:Rel.t)->ifOption.fold~none:true~some:(Z.equalZ.zero)addendthen(Virtual_address.add_int(plt0_size+(pltn_size*i))base,name)::symtabelsesymtab)[]rel_pltletx86_map_synthetic_symtabimage=matchArray.fold_left(fun((rela_opt,plt_opt)asr)sec->matchSection.headersecwith|{name;_}asheader->(matchnamewith|".rela.plt"->(Someheader,plt_opt)|".plt"whenplt_opt=None->(rela_opt,Someheader)|".plt.sec"->(rela_opt,Someheader)|_->r))(None,None)(Img.sectionsimage)with|None,_|_,None->[]|Somerela_plt,Some({name=".plt.sec";_}asplt)->generic_map_synthetic_symtab(Rel.readimagerela_plt)~plt~plt0_size:0~pltn_size:16|Somerela_plt,Someplt->generic_map_synthetic_symtab(Rel.readimagerela_plt)~plt~plt0_size:16~pltn_size:16letgeneric_map_synthetic_symtabimage~plt0_size~pltn_size=matchArray.fold_left(fun((rel_opt,plt_opt)asr)sec->matchSection.headersecwith|{name;_}asheader->(matchnamewith|".rela.plt"|".rel.plt"->(Someheader,plt_opt)|".plt"whenplt_opt=None->(rel_opt,Someheader)|_->r))(None,None)(Img.sectionsimage)with|None,_|_,None->[]|Somerel_plt,Someplt->generic_map_synthetic_symtab(Rel.readimagerel_plt)~plt~plt0_size~pltn_sizeletsynthetic_symtab:Img.t->(Virtual_address.t*string)list=funimg->matchImg.headerimgwith|{Ehdr.kind=EXEC|DYN;machine;_}->(matchmachinewith|X86_->x86_map_synthetic_symtabimg|ARM{rev=`v8;_}|RISCV_->generic_map_synthetic_symtabimg~plt0_size:32~pltn_size:16|_->[])|_->[]letis_jump_slot:Machine.isa->int->bool=funisakind->match(isa,kind)with|ARM{rev=`v7_;_},22|ARM{rev=`v8;_},1026|PPC_,21|RISCV_,5|SPARC_,21|X86_,7->true|_->falseletjmprel:Img.t->Rel.tlist=letget_entry:Dynamic.DT.t->uint64Dynamic.DT.Map.t->uint64=Dynamic.DT.Map.findinletoffsetaddrint=Virtual_address.add_intintaddrandgetimgaddr=Uint8.to_char(read_addressimgaddr)inletrecloop:('aReader.t->Rel.t)->Virtual_address.tReader.t->Rel.tlist->Rel.tlist=funreadcursorrelocs->ifReader.at_endcursorthenList.revrelocselseloopreadcursor(readcursor::relocs)infunimg->letendianness=matchImg.headerimgwith{ident={data;_};_}->datainletphs=program_headersimginmatchArray.find_opt(function{Phdr.kind=DYNAMIC;_}->true|_->false)phswith|None->[]|Somedynamic->(letentries=Dynamic.readimgdynamicinmatch(get_entryJMPRELentries,get_entryPLTRELentries,get_entryPLTRELSZentries,get_entrySTRTABentries,get_entrySTRSZentries,get_entrySYMTABentries,get_entrySYMENTentries)with|exceptionNot_found->[]|jmprel,pltrel,pltrelsz,strtab,strsz,symtab,syment->(matchmatch(img.header.ident.kind,Dynamic.DT.of_int32(Uint64.to_int32pltrel))with|`x32,REL->Some(Rel.read32,Sym.read_32)|`x32,RELA->Some(Rel.reada32,Sym.read_32)|`x64,REL->Some(Rel.read64,Sym.read_64)|`x64,RELA->Some(Rel.reada64,Sym.read_64)|_|(exceptionInvalid_argument_)->Nonewith|Some(rel_read,sym_read)->letrel_reader=letstart=Virtual_address.of_uint64jmprelinletstop=Virtual_address.addstart(Virtual_address.of_uint64pltrelsz)inReader.create~offset~get~endianness~start~stopimgandsym_reader=Reader.create~offset~get~endianness~start:(Virtual_address.of_uint64symtab)~stop:(Virtual_address.of_uint64(Int64.to_uint640xffffffffffffffffL))imgandstr_reader=letstart=Virtual_address.of_uint64strtabinletstop=Virtual_address.addstart(Virtual_address.of_uint64strsz)inReader.create~offset~get~start~stopimginletsym_nameidx=set_posstr_readeridx;Read.zero_string"Unterminated symbol name"str_reader()inletsyment=Uint64.to_intsymentinletsymidx=set_possym_reader(idx*syment);sym_readsym_reader(Fun.constShdr.dummy)sym_nameinletreadcursor=rel_readcursorsyminloopreadrel_reader[]|None->[]))end