12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118(*Generated by Lem from elf_dynamic.lem.*)(** [elf_dynamic] module exports types and definitions relating to the dynamic
* section and dynamic linking functionality of an ELF file.
*)openLem_basic_classesopenLem_boolopenLem_listopenLem_numopenLem_stringopenByte_sequenceopenEndiannessopenErroropenShowopenString_tableopenElf_fileopenElf_headeropenElf_relocationopenElf_section_header_tableopenElf_program_header_tableopenElf_types_native_uint(** Validity checks *)(** [is_elf32_valid_program_header_table_for_dynamic_linking pht] checks whether
* a program header table [pht] is a valid program header table for an ELF file
* that will be potentially dynamically linked. Returns true if there is exactly
* one segment header of type [elf_pt_interp], i.e. contains a string pointing
* to the requested dynamic interpreter.
*)(*val is_elf32_valid_program_header_table_for_dynamic_linking : elf32_program_header_table ->
bool*)letis_elf32_valid_program_header_table_for_dynamic_linkingpht:bool=(List.length(List.filter(funx->Nat_big_num.equal(Uint32_wrapper.to_bigintx.elf32_p_type)elf_pt_interp)pht)=1)(** [is_elf64_valid_program_header_table_for_dynamic_linking pht] checks whether
* a program header table [pht] is a valid program header table for an ELF file
* that will be potentially dynamically linked. Returns true if there is exactly
* one segment header of type [elf_pt_interp], i.e. contains a string pointing
* to the requested dynamic interpreter.
*)(*val is_elf64_valid_program_header_table_for_dynamic_linking : elf64_program_header_table ->
bool*)letis_elf64_valid_program_header_table_for_dynamic_linkingpht:bool=(List.length(List.filter(funx->Nat_big_num.equal(Uint32_wrapper.to_bigintx.elf64_p_type)elf_pt_interp)pht)=1)(** Dynamic section entry *)(** [dyn_union] represents the C-union type used in the definition of [elf32_dyn]
* and [elf64_dyn] types below. Some section tags correspond to entries where
* the fields are either unspecified or ignored, hence the presence of the
* [D_Ignored] constructor.
*)type('a,'b)dyn_union=D_Valof'a|D_Ptrof'b|D_Ignoredofbyte_sequence0(** [elf32_dyn] captures the notion of an ELF32 dynamic section entry.
* Specialises the [dyn_union] type above to using [elf32_word] values and
* [elf32_addr] pointers.
*)typeelf32_dyn={elf32_dyn_tag:Int32.t(** The type of the entry. *);elf32_dyn_d_un:(Uint32_wrapper.uint32,Uint32_wrapper.uint32)dyn_union(** The value of the entry, stored as a union. *)}(** [elf64_dyn] captures the notion of an ELF32 dynamic section entry.
* Specialises the [dyn_union] type above to using [elf64_xword] values and
* [elf64_addr] pointers.
*)typeelf64_dyn={elf64_dyn_tag:Int64.t(** The type of the entry. *);elf64_dyn_d_un:(Uint64_wrapper.uint64,Uint64_wrapper.uint64)dyn_union(** The value of the entry, stored as a union. *)}(** Dynamic section tags *)(** [dt_null] marks the end of the dynamic array *)letdt_null:Nat_big_num.num=((Nat_big_num.of_int0))(** [dt_needed] holds the string table offset of a string containing the name of
* a needed library.
*)letdt_needed:Nat_big_num.num=((Nat_big_num.of_int1))(** [dt_pltrelsz] holds the size in bytes of relocation entries associated with
* the PLT.
*)letdt_pltrelsz:Nat_big_num.num=((Nat_big_num.of_int2))(** [dt_pltgot] holds an address associated with the PLT or GOT. *)letdt_pltgot:Nat_big_num.num=((Nat_big_num.of_int3))(** [dt_hash] holds the address of a symbol-table hash. *)letdt_hash:Nat_big_num.num=((Nat_big_num.of_int4))(** [dt_strtab] holds the address of the string table. *)letdt_strtab:Nat_big_num.num=((Nat_big_num.of_int5))(** [dt_symtab] holds the address of a symbol table. *)letdt_symtab:Nat_big_num.num=((Nat_big_num.of_int6))(** [dt_rela] holds the address of a relocation table. *)letdt_rela:Nat_big_num.num=((Nat_big_num.of_int7))(** [dt_relasz] holds the size in bytes of the relocation table. *)letdt_relasz:Nat_big_num.num=((Nat_big_num.of_int8))(** [dt_relaent] holds the size in bytes of a relocation table entry. *)letdt_relaent:Nat_big_num.num=((Nat_big_num.of_int9))(** [dt_strsz] holds the size in bytes of the string table. *)letdt_strsz:Nat_big_num.num=((Nat_big_num.of_int10))(** [dt_syment] holds the size in bytes of a symbol table entry. *)letdt_syment:Nat_big_num.num=((Nat_big_num.of_int11))(** [dt_init] holds the address of the initialisation function. *)letdt_init:Nat_big_num.num=((Nat_big_num.of_int12))(** [dt_fini] holds the address of the finalisation function. *)letdt_fini:Nat_big_num.num=((Nat_big_num.of_int13))(** [dt_soname] holds the string table offset of a string containing the shared-
* object name.
*)letdt_soname:Nat_big_num.num=((Nat_big_num.of_int14))(** [dt_rpath] holds the string table offset of a string containing the library
* search path.
*)letdt_rpath:Nat_big_num.num=((Nat_big_num.of_int15))(** [dt_symbolic] alters the linker's symbol resolution algorithm so that names
* are resolved first from the shared object file itself, rather than the
* executable file.
*)letdt_symbolic:Nat_big_num.num=((Nat_big_num.of_int16))(** [dt_rel] is similar to [dt_rela] except its table has implicit addends. *)letdt_rel:Nat_big_num.num=((Nat_big_num.of_int17))(** [dt_relsz] holds the size in bytes of the [dt_rel] relocation table. *)letdt_relsz:Nat_big_num.num=((Nat_big_num.of_int18))(** [dt_relent] holds the size in bytes of a [dt_rel] relocation entry. *)letdt_relent:Nat_big_num.num=((Nat_big_num.of_int19))(** [dt_pltrel] specifies the type of relocation entry to which the PLT refers. *)letdt_pltrel:Nat_big_num.num=((Nat_big_num.of_int20))(** [dt_debug] is used for debugging and its purpose is not specified in the ABI.
* Programs using this entry are not ABI-conformant.
*)letdt_debug:Nat_big_num.num=((Nat_big_num.of_int21))(** [dt_textrel] absence of this entry indicates that no relocation entry should
* cause a modification to a non-writable segment. Otherwise, if present, one
* or more relocation entries may request modifications to a non-writable
* segment.
*)letdt_textrel:Nat_big_num.num=((Nat_big_num.of_int22))(** [dt_jmprel]'s member holds the address of relocation entries associated with
* the PLT.
*)letdt_jmprel:Nat_big_num.num=((Nat_big_num.of_int23))(** [dt_bindnow] instructs the linker to process all relocations for the object
* containing the entry before transferring control to the program.
*)letdt_bindnow:Nat_big_num.num=((Nat_big_num.of_int24))(** [dt_init_array] holds the address to the array of pointers to initialisation
* functions.
*)letdt_init_array:Nat_big_num.num=((Nat_big_num.of_int25))(** [dt_fini_array] holds the address to the array of pointers to finalisation
* functions.
*)letdt_fini_array:Nat_big_num.num=((Nat_big_num.of_int26))(** [dt_init_arraysz] holds the size in bytes of the array of pointers to
* initialisation functions.
*)letdt_init_arraysz:Nat_big_num.num=((Nat_big_num.of_int27))(** [dt_fini_arraysz] holds the size in bytes of the array of pointers to
* finalisation functions.
*)letdt_fini_arraysz:Nat_big_num.num=((Nat_big_num.of_int28))(** [dt_runpath] holds an offset into the string table holding a string containing
* the library search path.
*)letdt_runpath:Nat_big_num.num=((Nat_big_num.of_int29))(** [dt_flags] holds flag values specific to the object being loaded. *)letdt_flags:Nat_big_num.num=((Nat_big_num.of_int30))letdt_encoding:Nat_big_num.num=((Nat_big_num.of_int32))(** [dt_preinit_array] holds the address to the array of pointers of pre-
* initialisation functions.
*)letdt_preinit_array:Nat_big_num.num=((Nat_big_num.of_int32))(** [dt_preinit_arraysz] holds the size in bytes of the array of pointers of
* pre-initialisation functions.
*)letdt_preinit_arraysz:Nat_big_num.num=((Nat_big_num.of_int33))(** [dt_loos] and [dt_hios]: this inclusive range is reserved for OS-specific
* semantics.
*)letdt_loos:Nat_big_num.num=(Nat_big_num.add(Nat_big_num.mul((Nat_big_num.of_int2))((Nat_big_num.of_int805306374)))((Nat_big_num.of_int1)))(* 0x6000000D *)letdt_hios:Nat_big_num.num=(Nat_big_num.mul((Nat_big_num.of_int2))((Nat_big_num.of_int939522048)))(* 0x6ffff000 *)(** [dt_loproc] and [dt_hiproc]: this inclusive range is reserved for processor
* specific semantics.
*)letdt_loproc:Nat_big_num.num=(Nat_big_num.mul((Nat_big_num.of_int2))((Nat_big_num.of_int939524096)))(* 0x70000000 *)letdt_hiproc:Nat_big_num.num=(Nat_big_num.add(Nat_big_num.mul((Nat_big_num.of_int2))((Nat_big_num.of_int1073741823)))((Nat_big_num.of_int1)))(* 0x7fffffff *)(** [string_of_dynamic_tag so t os proc] produces a string-based representation of
* dynamic section tag [t]. For tag values between LO_OS and HI_OS [os] is
* used to produce the resulting value. For tag values between LO_PROC and
* HI_PROC [proc] is used to produce the resulting value. Boolean flag [so]
* indicates whether the flag in question is derived from a shared object file,
* which alters the printing of ENCODING and PRE_INITARRAY flags.
*)(*val string_of_dynamic_tag : bool -> natural -> (natural -> bool) -> (natural -> string) -> (natural -> string)
-> string*)letstring_of_dynamic_tagshared_objecttagos_additional_rangesosproc:string=(ifNat_big_num.equaltagdt_nullthen"NULL"elseifNat_big_num.equaltagdt_neededthen"NEEDED"elseifNat_big_num.equaltagdt_pltrelszthen"PLTRELSZ"elseifNat_big_num.equaltagdt_pltgotthen"PLTGOT"elseifNat_big_num.equaltagdt_hashthen"HASH"elseifNat_big_num.equaltagdt_strtabthen"STRTAB"elseifNat_big_num.equaltagdt_symtabthen"SYMTAB"elseifNat_big_num.equaltagdt_relathen"RELA"elseifNat_big_num.equaltagdt_relaszthen"RELASZ"elseifNat_big_num.equaltagdt_relaentthen"RELAENT"elseifNat_big_num.equaltagdt_strszthen"STRSZ"elseifNat_big_num.equaltagdt_symentthen"SYMENT"elseifNat_big_num.equaltagdt_initthen"INIT"elseifNat_big_num.equaltagdt_finithen"FINI"elseifNat_big_num.equaltagdt_sonamethen"SONAME"elseifNat_big_num.equaltagdt_rpaththen"RPATH"elseifNat_big_num.equaltagdt_symbolicthen"SYMBOLIC"elseifNat_big_num.equaltagdt_relthen"REL"elseifNat_big_num.equaltagdt_relszthen"RELSZ"elseifNat_big_num.equaltagdt_relentthen"RELENT"elseifNat_big_num.equaltagdt_pltrelthen"PLTREL"elseifNat_big_num.equaltagdt_debugthen"DEBUG"elseifNat_big_num.equaltagdt_textrelthen"TEXTREL"elseifNat_big_num.equaltagdt_jmprelthen"JMPREL"elseifNat_big_num.equaltagdt_bindnowthen"BIND_NOW"elseifNat_big_num.equaltagdt_init_arraythen"INIT_ARRAY"elseifNat_big_num.equaltagdt_fini_arraythen"FINI_ARRAY"elseifNat_big_num.equaltagdt_init_arrayszthen"INIT_ARRAYSZ"elseifNat_big_num.equaltagdt_fini_arrayszthen"FINI_ARRAYSZ"elseifNat_big_num.equaltagdt_runpaththen"RUNPATH"elseifNat_big_num.equaltagdt_flagsthen"FLAGS"elseifNat_big_num.equaltagdt_encodingthenifnotshared_objectthen"ENCODING"else"PREINIT_ARRAY"elseifNat_big_num.equaltagdt_preinit_arrayszthen"PREINIT_ARRAYSZ"elseifNat_big_num.greater_equaltagdt_loproc&&Nat_big_num.less_equaltagdt_hiprocthenproctagelseifNat_big_num.greater_equaltagdt_loos&&Nat_big_num.less_equaltagdt_hiosthenostagelseifos_additional_rangestagthenostagelse"Invalid dynamic section tag")(** [tag_correspondence] is a type used to emulate the functionality of a C-union
* in Lem. The type records whether the union should be interpreted as a value,
* a pointer, or a "do not care" value. An accompanying function will map a
* dynamic section tag to a [tag_correspondence], so that transcription functions
* know how to properly use the [dyn_union] value in a dynamic section entry.
*)typetag_correspondence=C_Val(** [dyn_union] should be interpreted as a value. *)|C_Ptr(** [dyn_union] should be interpreted as a pointer. *)|C_Ignored(** [dyn_union] is irrelevant, so we do not care. *)(** [tag_correspondence_of_tag tag os_additional_ranges os proc] produces a
* [tag_correspondence] value for a given dynamic tag, [tag]. Some tag values
* are reserved for interpretation by the OS or processor supplement (i.e. the
* ABI). We therefore also take in a predicate, [os_additional_ranges], that
* recognises when a tag is "special" for a given ABI, and a means of interpreting
* that tag, using [os] and [proc] functions.
*)(*val tag_correspondence_of_tag : bool -> natural -> (natural -> bool) -> (natural -> error tag_correspondence) ->
(natural -> error tag_correspondence) -> error tag_correspondence*)lettag_correspondence_of_tagshared_objecttagos_additional_rangesosproc:(tag_correspondence)error=(ifNat_big_num.equaltagdt_nullthenreturnC_IgnoredelseifNat_big_num.equaltagdt_neededthenreturnC_ValelseifNat_big_num.equaltagdt_pltrelszthenreturnC_ValelseifNat_big_num.equaltagdt_pltgotthenreturnC_PtrelseifNat_big_num.equaltagdt_hashthenreturnC_PtrelseifNat_big_num.equaltagdt_strtabthenreturnC_PtrelseifNat_big_num.equaltagdt_symtabthenreturnC_PtrelseifNat_big_num.equaltagdt_relathenreturnC_PtrelseifNat_big_num.equaltagdt_relaszthenreturnC_ValelseifNat_big_num.equaltagdt_relaentthenreturnC_ValelseifNat_big_num.equaltagdt_strszthenreturnC_ValelseifNat_big_num.equaltagdt_symentthenreturnC_ValelseifNat_big_num.equaltagdt_initthenreturnC_PtrelseifNat_big_num.equaltagdt_finithenreturnC_PtrelseifNat_big_num.equaltagdt_sonamethenreturnC_ValelseifNat_big_num.equaltagdt_rpaththenreturnC_ValelseifNat_big_num.equaltagdt_symbolicthenreturnC_IgnoredelseifNat_big_num.equaltagdt_relthenreturnC_PtrelseifNat_big_num.equaltagdt_relszthenreturnC_ValelseifNat_big_num.equaltagdt_relentthenreturnC_ValelseifNat_big_num.equaltagdt_pltrelthenreturnC_ValelseifNat_big_num.equaltagdt_debugthenreturnC_PtrelseifNat_big_num.equaltagdt_textrelthenreturnC_IgnoredelseifNat_big_num.equaltagdt_jmprelthenreturnC_PtrelseifNat_big_num.equaltagdt_bindnowthenreturnC_IgnoredelseifNat_big_num.equaltagdt_init_arraythenreturnC_PtrelseifNat_big_num.equaltagdt_fini_arraythenreturnC_PtrelseifNat_big_num.equaltagdt_init_arrayszthenreturnC_ValelseifNat_big_num.equaltagdt_fini_arrayszthenreturnC_ValelseifNat_big_num.equaltagdt_runpaththenreturnC_ValelseifNat_big_num.equaltagdt_flagsthenreturnC_ValelseifNat_big_num.equaltagdt_encodingthenifnotshared_objectthenreturnC_IgnoredelsereturnC_PtrelseifNat_big_num.equaltagdt_preinit_arrayszthenreturnC_ValelseifNat_big_num.greater_equaltagdt_loproc&&Nat_big_num.less_equaltagdt_hiprocthenproctagelseifNat_big_num.greater_equaltagdt_loos&&Nat_big_num.less_equaltagdt_hiosthenostagelseifos_additional_rangestagthenostagelsefail("tag_correspondence_of_tag: invalid dynamic section tag"))(** [read_elf32_dyn endian bs0 so os_additional_ranges os proc] reads an [elf32_dyn]
* record from byte sequence [bs0], assuming endianness [endian]. As mentioned
* above some ABIs reserve additional tag values for their own purposes. These
* are recognised by the predicate [os_additional_ranges] and interpreted by
* the functions [os] and [proc]. Fails if the transcription of the record from
* [bs0] fails, or if [os] or [proc] fail.
*)(*val read_elf32_dyn : endianness -> byte_sequence -> bool -> (natural -> bool) -> (natural -> error tag_correspondence) ->
(natural -> error tag_correspondence) -> error (elf32_dyn * byte_sequence)*)letread_elf32_dynendianbs0shared_objectos_additional_rangesosproc:(elf32_dyn*Byte_sequence_wrapper.byte_sequence)error=(bind(read_elf32_swordendianbs0)(fun(tag0,bs1)->lettag=(Nat_big_num.abs(Nat_big_num.of_int32tag0))inbind(tag_correspondence_of_tagshared_objecttagos_additional_rangesosproc)(funcorr->(matchcorrwith|C_Ptr->bind(read_elf32_addrendianbs1)(fun(ptr,bs2)->return({elf32_dyn_tag=tag0;elf32_dyn_d_un=(D_Ptrptr)},bs2))|C_Val->bind(read_elf32_wordendianbs1)(fun(vl,bs2)->return({elf32_dyn_tag=tag0;elf32_dyn_d_un=(D_Valvl)},bs2))|C_Ignored->(matchendianwith|Big->bind(read_4_bytes_bebs1)(fun((b1,b2,b3,b4),bs2)->letcut=(Byte_sequence.from_byte_lists[[b1;b2;b3;b4]])inreturn({elf32_dyn_tag=tag0;elf32_dyn_d_un=(D_Ignoredcut)},bs2))|Little->bind(read_4_bytes_lebs1)(fun((b1,b2,b3,b4),bs2)->letcut=(Byte_sequence.from_byte_lists[[b1;b2;b3;b4]])inreturn({elf32_dyn_tag=tag0;elf32_dyn_d_un=(D_Ignoredcut)},bs2)))))))(** [read_elf64_dyn endian bs0 os_additional_ranges os proc] reads an [elf64_dyn]
* record from byte sequence [bs0], assuming endianness [endian]. As mentioned
* above some ABIs reserve additional tag values for their own purposes. These
* are recognised by the predicate [os_additional_ranges] and interpreted by
* the functions [os] and [proc]. Fails if the transcription of the record from
* [bs0] fails, or if [os] or [proc] fail.
*)(*val read_elf64_dyn : endianness -> byte_sequence -> bool -> (natural -> bool) ->
(natural -> error tag_correspondence) -> (natural -> error tag_correspondence) ->
error (elf64_dyn * byte_sequence)*)letread_elf64_dynendianbs0shared_objectos_additional_rangesosproc:(elf64_dyn*Byte_sequence_wrapper.byte_sequence)error=(bind(read_elf64_sxwordendianbs0)(fun(tag0,bs1)->lettag=(Nat_big_num.abs(Nat_big_num.of_int64tag0))inbind(tag_correspondence_of_tagshared_objecttagos_additional_rangesosproc)(funcorr->(matchcorrwith|C_Ptr->bind(read_elf64_addrendianbs1)(fun(ptr,bs2)->return({elf64_dyn_tag=tag0;elf64_dyn_d_un=(D_Ptrptr)},bs2))|C_Val->bind(read_elf64_xwordendianbs1)(fun(vl,bs2)->return({elf64_dyn_tag=tag0;elf64_dyn_d_un=(D_Valvl)},bs2))|C_Ignored->(matchendianwith|Big->bind(read_8_bytes_bebs1)(fun((b1,b2,b3,b4,b5,b6,b7,b8),bs2)->letcut=(Byte_sequence.from_byte_lists[[b1;b2;b3;b4;b5;b6;b7;b8]])inreturn({elf64_dyn_tag=tag0;elf64_dyn_d_un=(D_Ignoredcut)},bs2))|Little->bind(read_8_bytes_lebs1)(fun((b1,b2,b3,b4,b5,b6,b7,b8),bs2)->letcut=(Byte_sequence.from_byte_lists[[b1;b2;b3;b4;b5;b6;b7;b8]])inreturn({elf64_dyn_tag=tag0;elf64_dyn_d_un=(D_Ignoredcut)},bs2)))))))(** [obtain_elf32_dynamic_section_contents' endian bs0 os_additional_ranges os
* proc] exhaustively reads in [elf32_dyn] values from byte sequence [bs0],
* interpreting ABI-specific dynamic tags with [os_additional_ranges], [os], and
* [proc] as mentioned above. Fails if [bs0]'s length modulo the size of an
* [elf32_dyn] entry is not 0.
*)(*val obtain_elf32_dynamic_section_contents' : endianness -> byte_sequence ->
bool -> (natural -> bool) -> (natural -> error tag_correspondence) ->
(natural -> error tag_correspondence) -> error (list elf32_dyn)*)letrecobtain_elf32_dynamic_section_contents'endianbs0shared_objectos_additional_rangesosproc:((elf32_dyn)list)error=(ifNat_big_num.equal(Byte_sequence.length0bs0)((Nat_big_num.of_int0))thenreturn[]elsebind(read_elf32_dynendianbs0shared_objectos_additional_rangesosproc)(fun(head,bs0)->ifNat_big_num.equal(Nat_big_num.of_int32head.elf32_dyn_tag)(dt_null)then(* DT_NULL marks end of array *)return[head]elsebind(obtain_elf32_dynamic_section_contents'endianbs0shared_objectos_additional_rangesosproc)(funtail->return(head::tail))))(** [obtain_elf64_dynamic_section_contents' endian bs0 os_additional_ranges os
* proc] exhaustively reads in [elf64_dyn] values from byte sequence [bs0],
* interpreting ABI-specific dynamic tags with [os_additional_ranges], [os], and
* [proc] as mentioned above. Fails if [bs0]'s length modulo the size of an
* [elf64_dyn] entry is not 0.
*)(*val obtain_elf64_dynamic_section_contents' : endianness -> byte_sequence ->
bool -> (natural -> bool) -> (natural -> error tag_correspondence) ->
(natural -> error tag_correspondence) -> error (list elf64_dyn)*)letrecobtain_elf64_dynamic_section_contents'endianbs0shared_objectos_additional_rangesosproc:((elf64_dyn)list)error=(ifNat_big_num.equal(Byte_sequence.length0bs0)((Nat_big_num.of_int0))thenreturn[]elsebind(read_elf64_dynendianbs0shared_objectos_additional_rangesosproc)(fun(head,bs0)->ifNat_big_num.equal(Nat_big_num.of_int64head.elf64_dyn_tag)(dt_null)then(* DT_NULL marks end of array *)return[head]elsebind(obtain_elf64_dynamic_section_contents'endianbs0shared_objectos_additional_rangesosproc)(funtail->return(head::tail))))(** [obtain_elf32_dynamic_section_contents' f1 os_additional_ranges os
* proc bs0] exhaustively reads in [elf32_dyn] values from byte sequence [bs0],
* obtaining endianness and the section header table from [elf32_file] f1,
* interpreting ABI-specific dynamic tags with [os_additional_ranges], [os], and
* [proc] as mentioned above. Fails if [bs0]'s length modulo the size of an
* [elf32_dyn] entry is not 0.
*)(*val obtain_elf32_dynamic_section_contents : elf32_file ->
(natural -> bool) -> (natural -> error tag_correspondence) ->
(natural -> error tag_correspondence) -> byte_sequence -> error (list elf32_dyn)*)letobtain_elf32_dynamic_section_contentsf1os_additional_rangesosprocbs0:((elf32_dyn)list)error=(letendian=(get_elf32_header_endiannessf1.elf32_file_header)inletsht=(f1.elf32_file_section_header_table)inletshared_object=(is_elf32_shared_object_filef1.elf32_file_header)in(matchList.filter(funent->Nat_big_num.equal(Uint32_wrapper.to_bigintent.elf32_sh_type)sht_dynamic)shtwith|[]->fail"obtain_elf32_dynamic_section_contents: no SHT_DYNAMIC section header entries"|[dyn]->letoff=(Uint32_wrapper.to_bigintdyn.elf32_sh_offset)inletsiz=(Uint32_wrapper.to_bigintdyn.elf32_sh_size)inbind(Byte_sequence.offset_and_cutoffsizbs0)(funrel->obtain_elf32_dynamic_section_contents'endianrelshared_objectos_additional_rangesosproc)|_->fail"obtain_elf32_dynamic_section_contents: multiple SHT_DYNAMIC section header entries"))(** [obtain_elf64_dynamic_section_contents' f1 os_additional_ranges os
* proc bs0] exhaustively reads in [elf64_dyn] values from byte sequence [bs0],
* obtaining endianness and the section header table from [elf64_file] f1,
* interpreting ABI-specific dynamic tags with [os_additional_ranges], [os], and
* [proc] as mentioned above. Fails if [bs0]'s length modulo the size of an
* [elf64_dyn] entry is not 0.
*)(*val obtain_elf64_dynamic_section_contents : elf64_file ->
(natural -> bool) -> (natural -> error tag_correspondence) ->
(natural -> error tag_correspondence) -> byte_sequence -> error (list elf64_dyn)*)letobtain_elf64_dynamic_section_contentsf1os_additional_rangesosprocbs0:((elf64_dyn)list)error=(letendian=(get_elf64_header_endiannessf1.elf64_file_header)inletsht=(f1.elf64_file_section_header_table)inletshared_object=(is_elf64_shared_object_filef1.elf64_file_header)in(matchList.filter(funent->Nat_big_num.equal(Uint32_wrapper.to_bigintent.elf64_sh_type)sht_dynamic)shtwith|[]->fail"obtain_elf64_dynamic_section_contents: no SHT_DYNAMIC section header entries"|[dyn]->letoff=(Uint64_wrapper.to_bigintdyn.elf64_sh_offset)inletsiz=(Ml_bindings.nat_big_num_of_uint64dyn.elf64_sh_size)inbind(Byte_sequence.offset_and_cutoffsizbs0)(funrel->obtain_elf64_dynamic_section_contents'endianrelshared_objectos_additional_rangesosproc)|_->fail"obtain_elf64_dynamic_section_contents: multiple SHT_DYNAMIC section header entries"))(** DT Flags values *)(** [df_origin] specific that the object being loaded may make reference to the
* $(ORIGIN) substitution string.
*)letdf_origin:Nat_big_num.num=((Nat_big_num.of_int1))(* 0x1 *)(** [df_symbolic] changes the linker's symbol resolution algorithm, resolving
* symbols first from the shared object file rather than the executable file.
*)letdf_symbolic:Nat_big_num.num=((Nat_big_num.of_int2))(* 0x2 *)(** [df_textrel] if this flag is not set then no relocation entry should cause
* modification to a non-writable segment.
*)letdf_textrel:Nat_big_num.num=((Nat_big_num.of_int4))(* 0x4 *)(** [df_bindnow] if set this instructs the linker to process all relocation entries
* of the containing object before transferring control to the program.
*)letdf_bindnow:Nat_big_num.num=((Nat_big_num.of_int8))(* 0x8 *)(** [df_static_tls] if set instructs the linker to reject all attempts to load
* the containing file dynamically.
*)letdf_static_tls:Nat_big_num.num=((Nat_big_num.of_int16))(* 0x10 *)(** [check_flag] is a utility function for testing whether a flag is set.
* TODO: so simple it is probably unneccessary now.
*)(*val check_flag : natural -> natural -> bool*)letcheck_flagmpos:bool=(Nat_big_num.equalmpos)(** [string_of_dt_flag f] produces a string-based representation of dynamic
* section flag [f].
*)(*val string_of_dt_flag : natural -> string*)letstring_of_dt_flagflag:string=(ifcheck_flagflag((Nat_big_num.of_int0))then"None"elseifcheck_flagflagdf_originthen"ORIGIN"elseifcheck_flagflagdf_bindnowthen"BIND_NOW"elseifcheck_flagflagdf_symbolicthen"SYMBOLIC"elseifcheck_flagflagdf_textrelthen"TEXTREL"elseifcheck_flagflagdf_static_tlsthen"STATIC_TLS"elseifcheck_flagflag(Nat_big_num.adddf_bindnowdf_static_tls)then"BIND_NOW STATIC_TLS"elseifcheck_flagflag(Nat_big_num.adddf_static_tlsdf_symbolic)then"SYMBOLIC STATIC_TLS"else(* XXX: add more as needed *)"Invalid dynamic section flag")(** [rel_type] represents the two types of relocation records potentially present
* in an ELF file: relocation, and relocation with addends.
*)typerel_type=Rel(** Plain relocation type. *)|RelA(** Relocation with addends type. *)(** [string_of_rel_type r] produces a string-based representation of [rel_type],
* [r].
*)(*val string_of_rel_type : rel_type -> string*)letstring_of_rel_typer:string=((matchrwith|Rel->"REL"|RelA->"RELA"))(** Type [dyn_value] represents the value of an ELF dynamic section entry. Values
* can represent various different types of objects (e.g. paths to libraries, or
* flags, or sizes of other entries in a file), and this type collates them all.
* Parameterised over two type variables so the type can be shared between ELF32
* and ELF64.
*)type('addr,'size)dyn_value=Addressof'addr(** An address. *)|Sizeof'size(** A size (in bytes). *)|FNameofstring(** A filename. *)|SONameofstring(** A shared object name. *)|Pathofstring(** A path to some directory. *)|RPathofstring(** A "run path". *)|RunPathofstring(** A "run path". *)|Libraryofstring(** A library path. *)|Flags1ofNat_big_num.num(** Flags. *)|FlagsofNat_big_num.num(** Flags. *)|NumericofNat_big_num.num(** An uninterpreted numeric value. *)|ChecksumofNat_big_num.num(** A checksum value *)|RelTypeofrel_type(** A relocation entry type. *)|TimestampofNat_big_num.num(** A timestamp value. *)|Null(** A null (0) value. *)|Ignored(** An ignored value. *)(** [elf32_dyn_value] and [elf64_dyn_value] are specialisations of [dyn_value]
* fixing the correct types for the ['addr] and ['size] type variables.
*)typeelf32_dyn_value=(Uint32_wrapper.uint32,Uint32_wrapper.uint32)dyn_valuetypeelf64_dyn_value=(Uint64_wrapper.uint64,Uint64_wrapper.uint64)dyn_value(** [get_string_table_of_elf32_dyn_section endian dyns sht bs0] searches through
* dynamic section entries [dyns] looking for one pointing to a string table, looks
* up the corresponding section header [sht] pointed to by that dynamic
* section entry, finds the section in [bs0] and decodes a string table from that
* section assuming endianness [endian]. May fail.
*)(*val get_string_table_of_elf32_dyn_section : endianness -> list elf32_dyn ->
elf32_section_header_table -> byte_sequence -> error string_table*)letget_string_table_of_elf32_dyn_sectionendiandynsshtbs0:(string_table)error=(letstrtabs=(List.filter(funx->Nat_big_num.equal(Nat_big_num.of_int32x.elf32_dyn_tag)(dt_strtab))dyns)in(matchstrtabswith|[strtab]->(matchstrtab.elf32_dyn_d_unwith|D_Valv->fail"get_string_table_of_elf32_dyn_section: STRTAB must be a PTR"|D_Ptrp->letsect=(List.filter(funs->(s.elf32_sh_addr=p)&&(s.elf32_sh_type=Uint32_wrapper.of_bigintsht_strtab))sht)in(matchsectwith|[]->fail"get_string_table_of_elf32_dyn_section: no section entry with same address as STRTAB"|[s]->letoff=(Uint32_wrapper.to_bigints.elf32_sh_offset)inletsiz=(Uint32_wrapper.to_bigints.elf32_sh_size)inbind(Byte_sequence.offset_and_cutoffsizbs0)(funrel->letstrings=(Byte_sequence.string_of_byte_sequencerel)inreturn(String_table.mk_string_tablestrings(Missing_pervasives.null_char)))|_->fail"get_string_table_of_elf32_dyn_section: multiple section entries with same address as STRTAB")|D_Ignoredi->fail"get_string_table_of_elf32_dyn_section: STRTAB must be a PTR")|[]->fail"get_string_table_of_elf32_dyn_section: no string table entry"|_->fail"get_string_table_of_elf32_dyn_section: multiple string table entries"))(** [get_string_table_of_elf64_dyn_section endian dyns sht bs0] searches through
* dynamic section entries [dyns] looking for one pointing to a string table, looks
* up the corresponding section header [sht] pointed to by that dynamic
* section entry, finds the section in [bs0] and decodes a string table from that
* section assuming endianness [endian]. May fail.
*)(*val get_string_table_of_elf64_dyn_section : endianness -> list elf64_dyn ->
elf64_section_header_table -> byte_sequence -> error string_table*)letget_string_table_of_elf64_dyn_sectionendiandynsshtbs0:(string_table)error=(letstrtabs=(List.filter(funx->Nat_big_num.equal(Nat_big_num.of_int64x.elf64_dyn_tag)(dt_strtab))dyns)in(matchstrtabswith|[strtab]->(matchstrtab.elf64_dyn_d_unwith|D_Valv->fail"get_string_table_of_elf64_dyn_section: STRTAB must be a PTR"|D_Ptrp->letsect=(List.filter(funs->(s.elf64_sh_addr=p)&&(s.elf64_sh_type=Uint32_wrapper.of_bigintsht_strtab))sht)in(matchsectwith|[]->fail"get_string_table_of_elf64_dyn_section: no section entry with same address as STRTAB"|[s]->letoff=(Uint64_wrapper.to_bigints.elf64_sh_offset)inletsiz=(Ml_bindings.nat_big_num_of_uint64s.elf64_sh_size)inbind(Byte_sequence.offset_and_cutoffsizbs0)(funrel->letstrings=(Byte_sequence.string_of_byte_sequencerel)inreturn(String_table.mk_string_tablestringsMissing_pervasives.null_char))|_->fail"get_string_table_of_elf64_dyn_section: multiple section entries with same address as STRTAB")|D_Ignoredi->fail"get_string_table_of_elf64_dyn_section: STRTAB must be a PTR")|[]->fail"get_string_table_of_elf64_dyn_section: no string table entry"|_->fail"get_string_table_of_elf64_dyn_section: multiple string table entries"))(** [get_value_of_elf32_dyn so dyn os_additional_ranges os proc stab] returns the value
* stored in a dynamic section entry [dyn], using [os_additional_ranges] and
* [os] to decode ABI-reserved tags. String table [stab] is used to correctly
* decode library and run paths, etc.
* May fail.
*)(*val get_value_of_elf32_dyn : bool -> elf32_dyn -> (natural -> bool) ->
(elf32_dyn -> string_table -> error elf32_dyn_value) ->
(elf32_dyn -> string_table -> error elf32_dyn_value) ->
string_table -> error elf32_dyn_value*)letget_value_of_elf32_dynshared_objectdynos_additional_rangesosprocstab:(((Uint32_wrapper.uint32),(Uint32_wrapper.uint32))dyn_value)error=(lettag=(Nat_big_num.abs(Nat_big_num.of_int32dyn.elf32_dyn_tag))inifNat_big_num.equaltagdt_nullthenreturnNullelseifNat_big_num.equaltagdt_neededthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: NEEDED must be a Val"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: NEEDED must be a Val")(funoff->letoff=(Uint32_wrapper.to_bigintoff)inbind(String_table.get_string_atoffstab)(funstr->return(Librarystr)))elseifNat_big_num.equaltagdt_pltrelszthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: PLTRELSZ must be a Val"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: PLTRELSZ must be a Val")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_pltgotthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: PLTGOT must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: PLTGOT must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_hashthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: HASH must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: HASH must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_strtabthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: STRTAB must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: STRTAB must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_symtabthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: SYMTAB must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: SYMTAB must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_relathenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: RELA must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: RELA must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_relaszthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: RELASZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: RELASZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_relaentthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: RELAENT must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: RELAENT must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_strszthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: STRSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: STRSZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_symentthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: SYMENT must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: SYMENT must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_initthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: INIT must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: INIT must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_finithenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: FINI must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: FINI must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_sonamethenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: SONAME must be a Val"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: SONAME must be a Val")(funoff->letoff=(Uint32_wrapper.to_bigintoff)inbind(String_table.get_string_atoffstab)(funstr->return(SONamestr)))elseifNat_big_num.equaltagdt_rpaththenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: RPATH must be a Val"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: RPATH must be a Val")(funoff->letoff=(Uint32_wrapper.to_bigintoff)inbind(String_table.get_string_atoffstab)(funstr->return(RPathstr)))elseifNat_big_num.equaltagdt_symbolicthenreturnNullelseifNat_big_num.equaltagdt_relthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: REL must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: REL must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_relszthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: RELSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: RELSZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_relentthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: RELENT must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: RELENT must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_pltrelthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: PLTREL must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: PLTREL must be a VAL")(funr->ifNat_big_num.equal(Uint32_wrapper.to_bigintr)dt_relthenreturn(RelTypeRel)elseifNat_big_num.equal(Uint32_wrapper.to_bigintr)dt_relathenreturn(RelTypeRelA)elsefail"get_value_of_elf32_dyn_entry: PLTREL neither REL nor RELA")elseifNat_big_num.equaltagdt_debugthenreturnNullelseifNat_big_num.equaltagdt_textrelthenreturnNullelseifNat_big_num.equaltagdt_jmprelthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: JMPREL must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: JMPREL must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_bindnowthenreturnIgnoredelseifNat_big_num.equaltagdt_init_arraythenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: INIT_ARRAY must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: INIT_ARRAY must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_fini_arraythenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: FINI_ARRAY must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: FINI_ARRAY must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_init_arrayszthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: INIT_ARRAYSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: INIT_ARRAYSZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_fini_arrayszthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: FINI_ARRAYSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: FINI_ARRAYSZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_runpaththenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: RUNPATH must be a Val"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: RUNPATH must be a Val")(funoff->letoff=(Uint32_wrapper.to_bigintoff)inbind(String_table.get_string_atoffstab)(funstr->return(RunPathstr)))elseifNat_big_num.equaltagdt_flagsthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: FLAGS must be a Val"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: FLAGS must be a Val")(funflags->return(Flags(Uint32_wrapper.to_bigintflags)))elseifNat_big_num.equaltagdt_encodingthenifnotshared_objectthenreturnIgnoredelsebind(matchdyn.elf32_dyn_d_unwith|D_Valv->fail"get_value_of_elf32_dyn_entry: PREINIT_ARRAY must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: PREINIT_ARRAY must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_preinit_arrayszthenbind(matchdyn.elf32_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf32_dyn_entry: PREINIT_ARRAYSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf32_dyn_entry: PREINIT_ARRAYSZ must be a VAL")(funsz->return(Checksum(Uint32_wrapper.to_bigintsz)))(** XXX: bug in readelf does not print this as a size! *)elseifNat_big_num.greater_equaltagdt_loproc&&Nat_big_num.less_equaltagdt_hiprocthenprocdynstabelseifNat_big_num.greater_equaltagdt_loos&&Nat_big_num.less_equaltagdt_hiosthenosdynstabelseifos_additional_rangestagthenosdynstabelsefail"get_value_of_elf32_dyn: unrecognised tag type")(** [get_value_of_elf64_dyn dyn os_additional_ranges os proc stab] returns the value
* stored in a dynamic section entry [dyn], using [os_additional_ranges] and
* [os] to decode ABI-reserved tags. String table [stab] is used to correctly
* decode library and run paths, etc.
* May fail.
*)(*val get_value_of_elf64_dyn : bool -> elf64_dyn -> (natural -> bool) ->
(elf64_dyn -> string_table -> error elf64_dyn_value) ->
(elf64_dyn -> string_table -> error elf64_dyn_value) ->
string_table -> error elf64_dyn_value*)letget_value_of_elf64_dynshared_objectdynos_additional_rangesos_dynproc_dynstab:(((Uint64_wrapper.uint64),(Uint64_wrapper.uint64))dyn_value)error=(lettag=(Nat_big_num.abs(Nat_big_num.of_int64dyn.elf64_dyn_tag))inifNat_big_num.equaltagdt_nullthenreturnNullelseifNat_big_num.equaltagdt_neededthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: NEEDED must be a Val"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: NEEDED must be a Val")(funoff->letoff=(Ml_bindings.nat_big_num_of_uint64off)inbind(String_table.get_string_atoffstab)(funstr->return(Librarystr)))elseifNat_big_num.equaltagdt_pltrelszthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: PLTRELSZ must be a Val"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: PLTRELSZ must be a Val")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_pltgotthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: PLTGOT must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: PLTGOT must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_hashthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: HASH must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: HASH must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_strtabthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: STRTAB must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: STRTAB must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_symtabthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: SYMTAB must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: SYMTAB must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_relathenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: RELA must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: RELA must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_relaszthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: RELASZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: RELASZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_relaentthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: RELAENT must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: RELAENT must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_strszthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: STRSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: STRSZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_symentthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: SYMENT must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: SYMENT must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_initthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: INIT must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: INIT must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_finithenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: FINI must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: FINI must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_sonamethenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: SONAME must be a Val"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: SONAME must be a Val")(funoff->letoff=(Ml_bindings.nat_big_num_of_uint64off)inbind(String_table.get_string_atoffstab)(funstr->return(SONamestr)))elseifNat_big_num.equaltagdt_rpaththenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: RPATH must be a Val"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: RPATH must be a Val")(funoff->letoff=(Ml_bindings.nat_big_num_of_uint64off)inbind(String_table.get_string_atoffstab)(funstr->return(RPathstr)))elseifNat_big_num.equaltagdt_symbolicthenreturnNullelseifNat_big_num.equaltagdt_relthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: REL must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: REL must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_relszthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: RELSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: RELSZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_relentthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: RELENT must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: RELENT must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_pltrelthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: PLTREL must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: PLTREL must be a VAL")(funr->ifNat_big_num.equal(Ml_bindings.nat_big_num_of_uint64r)dt_relthenreturn(RelTypeRel)elseifNat_big_num.equal(Ml_bindings.nat_big_num_of_uint64r)dt_relathenreturn(RelTypeRelA)elsefail"get_value_of_elf64_dyn_entry: PLTREL neither REL nor RELA")elseifNat_big_num.equaltagdt_debugthenreturnNullelseifNat_big_num.equaltagdt_textrelthenreturnNullelseifNat_big_num.equaltagdt_jmprelthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: JMPREL must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: JMPREL must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_bindnowthenreturnIgnoredelseifNat_big_num.equaltagdt_init_arraythenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: INIT_ARRAY must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: INIT_ARRAY must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_fini_arraythenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: FINI_ARRAY must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: FINI_ARRAY must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_init_arrayszthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: INIT_ARRAYSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: INIT_ARRAYSZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_fini_arrayszthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: FINI_ARRAYSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: FINI_ARRAYSZ must be a VAL")(funsz->return(Sizesz))elseifNat_big_num.equaltagdt_runpaththenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: RUNPATH must be a Val"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: RUNPATH must be a Val")(funoff->letoff=(Ml_bindings.nat_big_num_of_uint64off)inbind(String_table.get_string_atoffstab)(funstr->return(RunPathstr)))elseifNat_big_num.equaltagdt_flagsthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: FLAGS must be a Val"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: FLAGS must be a Val")(funflags->return(Flags(Ml_bindings.nat_big_num_of_uint64flags)))elseifNat_big_num.equaltagdt_encodingthenifnotshared_objectthenreturnIgnoredelsebind(matchdyn.elf64_dyn_d_unwith|D_Valv->fail"get_value_of_elf64_dyn_entry: PREINIT_ARRAY must be a PTR"|D_Ptrp->returnp|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: PREINIT_ARRAY must be a PTR")(funptr->return(Addressptr))elseifNat_big_num.equaltagdt_preinit_arrayszthenbind(matchdyn.elf64_dyn_d_unwith|D_Valv->returnv|D_Ptrp->fail"get_value_of_elf64_dyn_entry: PREINIT_ARRAYSZ must be a VAL"|D_Ignoredi->fail"get_value_of_elf64_dyn_entry: PREINIT_ARRAYSZ must be a VAL")(funsz->return(Checksum(Ml_bindings.nat_big_num_of_uint64sz)))(** XXX: bug in readelf does not print this as a size! *)elseifNat_big_num.greater_equaltagdt_loproc&&Nat_big_num.less_equaltagdt_hiprocthenproc_dyndynstabelseifNat_big_num.greater_equaltagdt_loos&&Nat_big_num.less_equaltagdt_hiosthenos_dyndynstabelseifos_additional_rangestagthenos_dyndynstabelsefail"get_value_of_elf64_dyn: unrecognised tag type")