1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768(**************************************************************************)(* 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:int32;offset:int;size:int}letreadt=letbase=get_postinletnamesz=Uint32.to_int(Read.u32t)inletsize=Uint32.to_int(Read.u32t)inletkind=Uint32.to_int32(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_bigint(Read.u32r)|`x64->funr->Uint64.to_bigint(Read.u64r)inArray.fold_left(funresult->function|{Note.name="CORE";kind=0x46494c45l;offset=at;_}->letcursor=Img.cursor~atiinletn=Z.to_int(readcursor)inletps=Z.to_int(readcursor)inletfiles=Array.initn(fun_->letlo=Virtual_address.of_bigint(readcursor)inlethi=Virtual_address.of_bigint(readcursor)inletoffset=ps*Z.to_int(readcursor)in{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*int*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,pltn_size,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*int*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