123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588(*Generated by Lem from elf_program_header_table.lem.*)(** [elf_program_header_table] contains type, functions and other definitions
* for working with program header tables and their entries and ELF segments.
* Related files are [elf_interpreted_segments] which extracts information
* derived from PHTs presented in this file and converts it into a more usable
* format for processing.
*
* FIXME:
* Bug in Lem as Lem codebase uses [int] type throughout where [BigInt.t]
* is really needed, hence chokes on huge constants below, which is why they are
* written in the way that they are.
*)openLem_assert_extraopenLem_basic_classesopenLem_boolopenLem_functionopenLem_listopenLem_maybeopenLem_numopenLem_string(*import Set*)openElf_types_native_uintopenEndiannessopenByte_sequenceopenErroropenMissing_pervasivesopenShow(** Segment types *)(** Unused array element. All other members of the structure are undefined. *)letelf_pt_null:Nat_big_num.num=((Nat_big_num.of_int0))(** A loadable segment. *)letelf_pt_load:Nat_big_num.num=((Nat_big_num.of_int1))(** Dynamic linking information. *)letelf_pt_dynamic:Nat_big_num.num=((Nat_big_num.of_int2))(** Specifies the location and size of a null-terminated path name to be used to
* invoke an interpreter.
*)letelf_pt_interp:Nat_big_num.num=((Nat_big_num.of_int3))(** Specifies location and size of auxiliary information. *)letelf_pt_note:Nat_big_num.num=((Nat_big_num.of_int4))(** Reserved but with unspecified semantics. If the file contains a segment of
* this type then it is to be regarded as non-conformant with the ABI.
*)letelf_pt_shlib:Nat_big_num.num=((Nat_big_num.of_int5))(** Specifies the location and size of the program header table. *)letelf_pt_phdr:Nat_big_num.num=((Nat_big_num.of_int6))(** Specifies the thread local storage (TLS) template. Need not be supported. *)letelf_pt_tls:Nat_big_num.num=((Nat_big_num.of_int7))(** Start of reserved indices for operating system specific semantics. *)letelf_pt_loos:Nat_big_num.num=(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int128))((Nat_big_num.of_int128)))((Nat_big_num.of_int128)))((Nat_big_num.of_int256)))((Nat_big_num.of_int3)))(* 1610612736 (* 0x60000000 *) *)(** End of reserved indices for operating system specific semantics. *)letelf_pt_hios:Nat_big_num.num=(Nat_big_num.add(Nat_big_num.mul((Nat_big_num.of_int469762047))((Nat_big_num.of_int4)))((Nat_big_num.of_int3)))(* 1879048191 (* 0x6fffffff *) *)(** Start of reserved indices for processor specific semantics. *)letelf_pt_loproc:Nat_big_num.num=(Nat_big_num.mul((Nat_big_num.of_int469762048))((Nat_big_num.of_int4)))(* 1879048192 (* 0x70000000 *) *)(** End of reserved indices for processor specific semantics. *)letelf_pt_hiproc:Nat_big_num.num=(Nat_big_num.add(Nat_big_num.mul((Nat_big_num.of_int536870911))((Nat_big_num.of_int4)))((Nat_big_num.of_int3)))(* 2147483647 (* 0x7fffffff *) *)(** [string_of_elf_segment_type os proc st] produces a string representation of
* the coding of an ELF segment type [st] using [os] and [proc] to render OS-
* and processor-specific codings.
*)(* XXX: is GNU stuff supposed to be hardcoded here? *)(*val string_of_segment_type : (natural -> string) -> (natural -> string) -> natural -> string*)letstring_of_segment_typeosprocpt:string=(ifNat_big_num.equalptelf_pt_nullthen"NULL"elseifNat_big_num.equalptelf_pt_loadthen"LOAD"elseifNat_big_num.equalptelf_pt_dynamicthen"DYNAMIC"elseifNat_big_num.equalptelf_pt_interpthen"INTERP"elseifNat_big_num.equalptelf_pt_notethen"NOTE"elseifNat_big_num.equalptelf_pt_shlibthen"SHLIB"elseifNat_big_num.equalptelf_pt_phdrthen"PHDR"elseifNat_big_num.equalptelf_pt_tlsthen"TLS"elseifNat_big_num.greater_equalptelf_pt_loos&&Nat_big_num.less_equalptelf_pt_hiosthenosptelseifNat_big_num.greater_equalptelf_pt_loproc&&Nat_big_num.less_equalptelf_pt_hiprocthenprocptelse"Undefined or invalid segment type")(** Segments permission flags *)(** Execute bit *)letelf_pf_x:Nat_big_num.num=((Nat_big_num.of_int1))(** Write bit *)letelf_pf_w:Nat_big_num.num=((Nat_big_num.of_int2))(** Read bit *)letelf_pf_r:Nat_big_num.num=((Nat_big_num.of_int4))(** The following two bit ranges are reserved for OS- and processor-specific
* flags respectively.
*)letelf_pf_maskos:Nat_big_num.num=((Nat_big_num.of_int267386880))(* 0x0ff00000 *)letelf_pf_maskproc:Nat_big_num.num=(Nat_big_num.mul((Nat_big_num.of_int4))((Nat_big_num.of_int1006632960)))(* 0xf0000000 *)(** [exact_permission_of_permission m]: ELF has two interpretations of a RWX-style
* permission bit [m], an exact permission and an allowable permission. These
* permissions allow us to interpret a flag as an upper bound for behaviour and
* an ABI-compliant implementation can choose to interpret the flag [m] as either.
*
* In the exact interpretation, the upper bound is exactly the natural interpretation
* of the flag. This is encoded in [exact_permission_of_permission], which is
* a glorified identity function, though included for completeness.
*)(*val exact_permissions_of_permission : natural -> error natural*)letexact_permissions_of_permissionm:(Nat_big_num.num)error=(ifNat_big_num.equalm((Nat_big_num.of_int0))thenreturn((Nat_big_num.of_int0))elseifNat_big_num.equalmelf_pf_xthenreturn((Nat_big_num.of_int1))elseifNat_big_num.equalmelf_pf_wthenreturn((Nat_big_num.of_int2))elseifNat_big_num.equalmelf_pf_rthenreturn((Nat_big_num.of_int4))elseifNat_big_num.equalm(Nat_big_num.addelf_pf_xelf_pf_w)thenreturn((Nat_big_num.of_int3))elseifNat_big_num.equalm(Nat_big_num.addelf_pf_xelf_pf_r)thenreturn((Nat_big_num.of_int5))elseifNat_big_num.equalm(Nat_big_num.addelf_pf_welf_pf_r)thenreturn((Nat_big_num.of_int6))elseifNat_big_num.equalm(Nat_big_num.add(Nat_big_num.addelf_pf_xelf_pf_r)elf_pf_w)thenreturn((Nat_big_num.of_int7))elsefail"exact_permission_of_permission: invalid permission flag")(** [allowable_permission_of_permission m]: ELF has two interpretations of a RWX-style
* permission bit [m], an exact permission and an allowable permission. These
* permissions allow us to interpret a flag as an upper bound for behaviour and
* an ABI-compliant implementation can choose to interpret the flag [m] as either.
*
* In the allowable interpretation, the upper bound is more lax than the natural
* interpretation of the flag.
*)(*val allowable_permissions_of_permission : natural -> error natural*)letallowable_permissions_of_permissionm:(Nat_big_num.num)error=(ifNat_big_num.equalm((Nat_big_num.of_int0))thenreturn((Nat_big_num.of_int0))elseifNat_big_num.equalmelf_pf_xthenreturn((Nat_big_num.of_int5))elseifNat_big_num.equalmelf_pf_wthenreturn((Nat_big_num.of_int7))elseifNat_big_num.equalmelf_pf_rthenreturn((Nat_big_num.of_int5))elseifNat_big_num.equalm(Nat_big_num.addelf_pf_xelf_pf_w)thenreturn((Nat_big_num.of_int7))elseifNat_big_num.equalm(Nat_big_num.addelf_pf_xelf_pf_r)thenreturn((Nat_big_num.of_int5))elseifNat_big_num.equalm(Nat_big_num.addelf_pf_welf_pf_r)thenreturn((Nat_big_num.of_int7))elseifNat_big_num.equalm(Nat_big_num.add(Nat_big_num.addelf_pf_xelf_pf_r)elf_pf_w)thenreturn((Nat_big_num.of_int7))elsefail"exact_permission_of_permission: invalid permission flag")(** [elf64_interpreted_program_header_flags w] extracts a boolean triple of flags
* from the flags field of an interpreted segment.
*)(*val parse_elf_segment_permissions : natural -> (bool * bool * bool)*)letparse_elf_segment_permissionsm:bool*bool*bool=(ifNat_big_num.equalm((Nat_big_num.of_int0))then(false,false,false)elseifNat_big_num.equalmelf_pf_xthen(false,false,true)elseifNat_big_num.equalmelf_pf_wthen(false,true,false)elseifNat_big_num.equalmelf_pf_rthen(true,false,false)elseifNat_big_num.equalm(Nat_big_num.addelf_pf_xelf_pf_w)then(false,true,true)elseifNat_big_num.equalm(Nat_big_num.addelf_pf_xelf_pf_r)then(true,false,true)elseifNat_big_num.equalm(Nat_big_num.addelf_pf_welf_pf_r)then(true,true,false)elseifNat_big_num.equalm(Nat_big_num.add(Nat_big_num.addelf_pf_xelf_pf_r)elf_pf_w)then(true,true,true)elsefailwith"Invalid permisssion flag")(** [string_of_elf_segment_permissions m] produces a string-based representation
* of an ELF segment's permission field.
* TODO: expand this as is needed by the validation tests.
*)(*val string_of_elf_segment_permissions : natural -> string*)letstring_of_elf_segment_permissionsm:string=(let(r,w,x)=(parse_elf_segment_permissionsm)in(ifrthen"R"else" ")^((ifwthen"W"else" ")^(ifxthen"X"else" ")))(** Program header table entry type *)(** Type [elf32_program_header_table_entry] encodes a program header table entry
* for 32-bit platforms. Each entry describes a segment in an executable or
* shared object file.
*)typeelf32_program_header_table_entry={elf32_p_type:Uint32_wrapper.uint32(** Type of the segment *);elf32_p_offset:Uint32_wrapper.uint32(** Offset from beginning of file for segment *);elf32_p_vaddr:Uint32_wrapper.uint32(** Virtual address for segment in memory *);elf32_p_paddr:Uint32_wrapper.uint32(** Physical address for segment *);elf32_p_filesz:Uint32_wrapper.uint32(** Size of segment in file, in bytes *);elf32_p_memsz:Uint32_wrapper.uint32(** Size of segment in memory image, in bytes *);elf32_p_flags:Uint32_wrapper.uint32(** Segment flags *);elf32_p_align:Uint32_wrapper.uint32(** Segment alignment memory for memory and file *)}(** [compare_elf32_program_header_table_entry ent1 ent2] is an ordering-comparison
* function on program header table entries suitable for constructing sets,
* finite maps, and other ordered data types with.
*)(*val compare_elf32_program_header_table_entry : elf32_program_header_table_entry ->
elf32_program_header_table_entry -> ordering*)letcompare_elf32_program_header_table_entryh1h2:int=(lexicographic_compareNat_big_num.compare[Uint32_wrapper.to_biginth1.elf32_p_type;Uint32_wrapper.to_biginth1.elf32_p_offset;Uint32_wrapper.to_biginth1.elf32_p_vaddr;Uint32_wrapper.to_biginth1.elf32_p_paddr;Uint32_wrapper.to_biginth1.elf32_p_filesz;Uint32_wrapper.to_biginth1.elf32_p_memsz;Uint32_wrapper.to_biginth1.elf32_p_flags;Uint32_wrapper.to_biginth1.elf32_p_align][Uint32_wrapper.to_biginth2.elf32_p_type;Uint32_wrapper.to_biginth2.elf32_p_offset;Uint32_wrapper.to_biginth2.elf32_p_vaddr;Uint32_wrapper.to_biginth2.elf32_p_paddr;Uint32_wrapper.to_biginth2.elf32_p_filesz;Uint32_wrapper.to_biginth2.elf32_p_memsz;Uint32_wrapper.to_biginth2.elf32_p_flags;Uint32_wrapper.to_biginth2.elf32_p_align])letinstance_Basic_classes_Ord_Elf_program_header_table_elf32_program_header_table_entry_dict:(elf32_program_header_table_entry)ord_class=({compare_method=compare_elf32_program_header_table_entry;isLess_method=(funf1->(funf2->(Lem.orderingEqual(compare_elf32_program_header_table_entryf1f2)(-1))));isLessEqual_method=(funf1->(funf2->Pset.mem(compare_elf32_program_header_table_entryf1f2)(Pset.from_listcompare[(-1);0])));isGreater_method=(funf1->(funf2->(Lem.orderingEqual(compare_elf32_program_header_table_entryf1f2)1)));isGreaterEqual_method=(funf1->(funf2->Pset.mem(compare_elf32_program_header_table_entryf1f2)(Pset.from_listcompare[1;0])))})(** Type [elf64_program_header_table_entry] encodes a program header table entry
* for 64-bit platforms. Each entry describes a segment in an executable or
* shared object file.
*)typeelf64_program_header_table_entry={elf64_p_type:Uint32_wrapper.uint32(** Type of the segment *);elf64_p_flags:Uint32_wrapper.uint32(** Segment flags *);elf64_p_offset:Uint64_wrapper.uint64(** Offset from beginning of file for segment *);elf64_p_vaddr:Uint64_wrapper.uint64(** Virtual address for segment in memory *);elf64_p_paddr:Uint64_wrapper.uint64(** Physical address for segment *);elf64_p_filesz:Uint64_wrapper.uint64(** Size of segment in file, in bytes *);elf64_p_memsz:Uint64_wrapper.uint64(** Size of segment in memory image, in bytes *);elf64_p_align:Uint64_wrapper.uint64(** Segment alignment memory for memory and file *)}(** [compare_elf64_program_header_table_entry ent1 ent2] is an ordering-comparison
* function on program header table entries suitable for constructing sets,
* finite maps, and other ordered data types with.
*)(*val compare_elf64_program_header_table_entry : elf64_program_header_table_entry ->
elf64_program_header_table_entry -> ordering*)letcompare_elf64_program_header_table_entryh1h2:int=(lexicographic_compareNat_big_num.compare[Uint32_wrapper.to_biginth1.elf64_p_type;Uint64_wrapper.to_biginth1.elf64_p_offset;Ml_bindings.nat_big_num_of_uint64h1.elf64_p_vaddr;Ml_bindings.nat_big_num_of_uint64h1.elf64_p_paddr;Ml_bindings.nat_big_num_of_uint64h1.elf64_p_filesz;Ml_bindings.nat_big_num_of_uint64h1.elf64_p_memsz;Uint32_wrapper.to_biginth1.elf64_p_flags;Ml_bindings.nat_big_num_of_uint64h1.elf64_p_align][Uint32_wrapper.to_biginth2.elf64_p_type;Uint64_wrapper.to_biginth2.elf64_p_offset;Ml_bindings.nat_big_num_of_uint64h2.elf64_p_vaddr;Ml_bindings.nat_big_num_of_uint64h2.elf64_p_paddr;Ml_bindings.nat_big_num_of_uint64h2.elf64_p_filesz;Ml_bindings.nat_big_num_of_uint64h2.elf64_p_memsz;Uint32_wrapper.to_biginth2.elf64_p_flags;Ml_bindings.nat_big_num_of_uint64h2.elf64_p_align])letinstance_Basic_classes_Ord_Elf_program_header_table_elf64_program_header_table_entry_dict:(elf64_program_header_table_entry)ord_class=({compare_method=compare_elf64_program_header_table_entry;isLess_method=(funf1->(funf2->(Lem.orderingEqual(compare_elf64_program_header_table_entryf1f2)(-1))));isLessEqual_method=(funf1->(funf2->Pset.mem(compare_elf64_program_header_table_entryf1f2)(Pset.from_listcompare[(-1);0])));isGreater_method=(funf1->(funf2->(Lem.orderingEqual(compare_elf64_program_header_table_entryf1f2)1)));isGreaterEqual_method=(funf1->(funf2->Pset.mem(compare_elf64_program_header_table_entryf1f2)(Pset.from_listcompare[1;0])))})(** [string_of_elf32_program_header_table_entry os proc et] produces a string
* representation of a 32-bit program header table entry using [os] and [proc]
* to render OS- and processor-specific entries.
*)(*val string_of_elf32_program_header_table_entry : (natural -> string) -> (natural -> string) -> elf32_program_header_table_entry -> string*)letstring_of_elf32_program_header_table_entryosprocentry:string=(unlines[("\t"^("Segment type: "^string_of_segment_typeosproc(Uint32_wrapper.to_bigintentry.elf32_p_type)));("\t"^("Offset: "^Uint32_wrapper.to_stringentry.elf32_p_offset));("\t"^("Virtual address: "^Uint32_wrapper.to_stringentry.elf32_p_vaddr));("\t"^("Physical address: "^Uint32_wrapper.to_stringentry.elf32_p_paddr));("\t"^("Segment size (bytes): "^Uint32_wrapper.to_stringentry.elf32_p_filesz));("\t"^("Segment size in memory image (bytes): "^Uint32_wrapper.to_stringentry.elf32_p_memsz));("\t"^("Flags: "^Uint32_wrapper.to_stringentry.elf32_p_flags));("\t"^("Alignment: "^Uint32_wrapper.to_stringentry.elf32_p_align))])(** [string_of_elf64_program_header_table_entry os proc et] produces a string
* representation of a 64-bit program header table entry using [os] and [proc]
* to render OS- and processor-specific entries.
*)(*val string_of_elf64_program_header_table_entry : (natural -> string) -> (natural -> string) -> elf64_program_header_table_entry -> string*)letstring_of_elf64_program_header_table_entryosprocentry:string=(unlines[("\t"^("Segment type: "^string_of_segment_typeosproc(Uint32_wrapper.to_bigintentry.elf64_p_type)));("\t"^("Offset: "^Uint64_wrapper.to_stringentry.elf64_p_offset));("\t"^("Virtual address: "^Uint64_wrapper.to_stringentry.elf64_p_vaddr));("\t"^("Physical address: "^Uint64_wrapper.to_stringentry.elf64_p_paddr));("\t"^("Segment size (bytes): "^Uint64_wrapper.to_stringentry.elf64_p_filesz));("\t"^("Segment size in memory image (bytes): "^Uint64_wrapper.to_stringentry.elf64_p_memsz));("\t"^("Flags: "^Uint32_wrapper.to_stringentry.elf64_p_flags));("\t"^("Alignment: "^Uint64_wrapper.to_stringentry.elf64_p_align))])(** [string_of_elf32_program_header_table_entry_default et] produces a string representation
* of table entry [et] where OS- and processor-specific entries are replaced with
* default strings.
*)(*val string_of_elf32_program_header_table_entry_default : elf32_program_header_table_entry -> string*)letstring_of_elf32_program_header_table_entry_default:elf32_program_header_table_entry->string=(string_of_elf32_program_header_table_entry((funy->"*Default OS specific print*"))((funy->"*Default processor specific print*")))(** [string_of_elf64_program_header_table_entry_default et] produces a string representation
* of table entry [et] where OS- and processor-specific entries are replaced with
* default strings.
*)(*val string_of_elf64_program_header_table_entry_default : elf64_program_header_table_entry -> string*)letstring_of_elf64_program_header_table_entry_default:elf64_program_header_table_entry->string=(string_of_elf64_program_header_table_entry((funy->"*Default OS specific print*"))((funy->"*Default processor specific print*")))letinstance_Show_Show_Elf_program_header_table_elf32_program_header_table_entry_dict:(elf32_program_header_table_entry)show_class=({show_method=string_of_elf32_program_header_table_entry_default})letinstance_Show_Show_Elf_program_header_table_elf64_program_header_table_entry_dict:(elf64_program_header_table_entry)show_class=({show_method=string_of_elf64_program_header_table_entry_default})(** Parsing and blitting *)(** [bytes_of_elf32_program_header_table_entry ed ent] blits a 32-bit program
* header table entry [ent] into a byte sequence assuming endianness [ed].
*)(*val bytes_of_elf32_program_header_table_entry : endianness -> elf32_program_header_table_entry -> byte_sequence*)letbytes_of_elf32_program_header_table_entryendianentry:Byte_sequence_wrapper.byte_sequence=(Byte_sequence.from_byte_lists[bytes_of_elf32_wordendianentry.elf32_p_type;bytes_of_elf32_offendianentry.elf32_p_offset;bytes_of_elf32_addrendianentry.elf32_p_vaddr;bytes_of_elf32_addrendianentry.elf32_p_paddr;bytes_of_elf32_wordendianentry.elf32_p_filesz;bytes_of_elf32_wordendianentry.elf32_p_memsz;bytes_of_elf32_wordendianentry.elf32_p_flags;bytes_of_elf32_wordendianentry.elf32_p_align])(** [bytes_of_elf64_program_header_table_entry ed ent] blits a 64-bit program
* header table entry [ent] into a byte sequence assuming endianness [ed].
*)(*val bytes_of_elf64_program_header_table_entry : endianness -> elf64_program_header_table_entry -> byte_sequence*)letbytes_of_elf64_program_header_table_entryendianentry:Byte_sequence_wrapper.byte_sequence=(Byte_sequence.from_byte_lists[bytes_of_elf64_wordendianentry.elf64_p_type;bytes_of_elf64_wordendianentry.elf64_p_flags;bytes_of_elf64_offendianentry.elf64_p_offset;bytes_of_elf64_addrendianentry.elf64_p_vaddr;bytes_of_elf64_addrendianentry.elf64_p_paddr;bytes_of_elf64_xwordendianentry.elf64_p_filesz;bytes_of_elf64_xwordendianentry.elf64_p_memsz;bytes_of_elf64_xwordendianentry.elf64_p_align])(** [read_elf32_program_header_table_entry endian bs0] reads an ELF32 program header table
* entry from byte sequence [bs0] assuming endianness [endian]. If [bs0] is larger
* than necessary, the excess is returned from the function, too.
* Fails if the entry cannot be read.
*)(*val read_elf32_program_header_table_entry : endianness -> byte_sequence ->
error (elf32_program_header_table_entry * byte_sequence)*)letread_elf32_program_header_table_entryendianbs:(elf32_program_header_table_entry*Byte_sequence_wrapper.byte_sequence)error=(bind(read_elf32_wordendianbs)(fun(typ,bs)->bind(read_elf32_offendianbs)(fun(offset,bs)->bind(read_elf32_addrendianbs)(fun(vaddr,bs)->bind(read_elf32_addrendianbs)(fun(paddr,bs)->bind(read_elf32_wordendianbs)(fun(filesz,bs)->bind(read_elf32_wordendianbs)(fun(memsz,bs)->bind(read_elf32_wordendianbs)(fun(flags,bs)->bind(read_elf32_wordendianbs)(fun(align,bs)->return({elf32_p_type=typ;elf32_p_offset=offset;elf32_p_vaddr=vaddr;elf32_p_paddr=paddr;elf32_p_filesz=filesz;elf32_p_memsz=memsz;elf32_p_flags=flags;elf32_p_align=align},bs))))))))))(** [read_elf64_program_header_table_entry endian bs0] reads an ELF64 program header table
* entry from byte sequence [bs0] assuming endianness [endian]. If [bs0] is larger
* than necessary, the excess is returned from the function, too.
* Fails if the entry cannot be read.
*)(*val read_elf64_program_header_table_entry : endianness -> byte_sequence ->
error (elf64_program_header_table_entry * byte_sequence)*)letread_elf64_program_header_table_entryendianbs:(elf64_program_header_table_entry*Byte_sequence_wrapper.byte_sequence)error=(bind(read_elf64_wordendianbs)(fun(typ,bs)->bind(read_elf64_wordendianbs)(fun(flags,bs)->bind(read_elf64_offendianbs)(fun(offset,bs)->bind(read_elf64_addrendianbs)(fun(vaddr,bs)->bind(read_elf64_addrendianbs)(fun(paddr,bs)->bind(read_elf64_xwordendianbs)(fun(filesz,bs)->bind(read_elf64_xwordendianbs)(fun(memsz,bs)->bind(read_elf64_xwordendianbs)(fun(align,bs)->return({elf64_p_type=typ;elf64_p_offset=offset;elf64_p_vaddr=vaddr;elf64_p_paddr=paddr;elf64_p_filesz=filesz;elf64_p_memsz=memsz;elf64_p_flags=flags;elf64_p_align=align},bs))))))))))(** Program header table type *)(** Type [elf32_program_header_table] represents a program header table for 32-bit
* ELF files. A program header table is an array (implemented as a list, here)
* of program header table entries.
*)typeelf32_program_header_table=elf32_program_header_table_entrylist(** Type [elf64_program_header_table] represents a program header table for 64-bit
* ELF files. A program header table is an array (implemented as a list, here)
* of program header table entries.
*)typeelf64_program_header_table=elf64_program_header_table_entrylist(** [bytes_of_elf32_program_header_table ed tbl] blits an ELF32 program header
* table into a byte sequence assuming endianness [ed].
*)letbytes_of_elf32_program_header_tableendiantbl:Byte_sequence_wrapper.byte_sequence=(Byte_sequence.concat(Lem_list.map(bytes_of_elf32_program_header_table_entryendian)tbl))(** [bytes_of_elf64_program_header_table ed tbl] blits an ELF64 program header
* table into a byte sequence assuming endianness [ed].
*)letbytes_of_elf64_program_header_tableendiantbl:Byte_sequence_wrapper.byte_sequence=(Byte_sequence.concat(Lem_list.map(bytes_of_elf64_program_header_table_entryendian)tbl))(** [read_elf32_program_header_table' endian bs0] reads an ELF32 program header table from
* byte_sequence [bs0] assuming endianness [endian]. The byte_sequence [bs0] is assumed
* to have exactly the correct size for the table. For internal use, only. Use
* [read_elf32_program_header_table] below instead.
*)letrecread_elf32_program_header_table'endianbs0:((elf32_program_header_table_entry)list)error=(ifNat_big_num.equal(Byte_sequence.length0bs0)((Nat_big_num.of_int0))thenreturn[]elsebind(read_elf32_program_header_table_entryendianbs0)(fun(entry,bs1)->bind(read_elf32_program_header_table'endianbs1)(funtail->return(entry::tail))))(** [read_elf64_program_header_table' endian bs0] reads an ELF64 program header table from
* byte_sequence [bs0] assuming endianness [endian]. The byte_sequence [bs0] is assumed
* to have exactly the correct size for the table. For internal use, only. Use
* [read_elf32_program_header_table] below instead.
*)letrecread_elf64_program_header_table'endianbs0:((elf64_program_header_table_entry)list)error=(ifNat_big_num.equal(Byte_sequence.length0bs0)((Nat_big_num.of_int0))thenreturn[]elsebind(read_elf64_program_header_table_entryendianbs0)(fun(entry,bs1)->bind(read_elf64_program_header_table'endianbs1)(funtail->return(entry::tail))))(** [read_elf32_program_header_table table_size endian bs0] reads an ELF32 program header
* table from byte_sequence [bs0] assuming endianness [endian] based on the size (in bytes) passed in via [table_size].
* This [table_size] argument should be equal to the number of entries in the
* table multiplied by the fixed entry size. Bitstring [bs0] may be larger than
* necessary, in which case the excess is returned.
*)(*val read_elf32_program_header_table : natural -> endianness -> byte_sequence ->
error (elf32_program_header_table * byte_sequence)*)letread_elf32_program_header_tabletable_sizeendianbs0:((elf32_program_header_table_entry)list*Byte_sequence_wrapper.byte_sequence)error=(bind(partition0table_sizebs0)(fun(eat,rest)->bind(read_elf32_program_header_table'endianeat)(funtable->return(table,rest))))(** [read_elf64_program_header_table table_size endian bs0] reads an ELF64 program header
* table from byte_sequence [bs0] assuming endianness [endian] based on the size (in bytes) passed in via [table_size].
* This [table_size] argument should be equal to the number of entries in the
* table multiplied by the fixed entry size. Bitstring [bs0] may be larger than
* necessary, in which case the excess is returned.
*)(*val read_elf64_program_header_table : natural -> endianness -> byte_sequence ->
error (elf64_program_header_table * byte_sequence)*)letread_elf64_program_header_tabletable_sizeendianbs0:((elf64_program_header_table_entry)list*Byte_sequence_wrapper.byte_sequence)error=(bind(partition0table_sizebs0)(fun(eat,rest)->bind(read_elf64_program_header_table'endianeat)(funtable->return(table,rest))))(** The [pht_print_bundle] type is used to tidy up other type signatures. Some of the
* top-level string_of_ functions require six or more functions passed to them,
* which quickly gets out of hand. This type is used to reduce that complexity.
* The first component of the type is an OS specific print function, the second is
* a processor specific print function.
*)typepht_print_bundle=(Nat_big_num.num->string)*(Nat_big_num.num->string)(** [string_of_elf32_program_header_table os proc tbl] produces a string representation
* of program header table [tbl] using [os] and [proc] to render OS- and processor-
* specific entries.
*)(*val string_of_elf32_program_header_table : pht_print_bundle -> elf32_program_header_table -> string*)letstring_of_elf32_program_header_table(os,proc)tbl:string=(unlines(Lem_list.map(string_of_elf32_program_header_table_entryosproc)tbl))(** [string_of_elf64_program_header_table os proc tbl] produces a string representation
* of program header table [tbl] using [os] and [proc] to render OS- and processor-
* specific entries.
*)(*val string_of_elf64_program_header_table : pht_print_bundle -> elf64_program_header_table -> string*)letstring_of_elf64_program_header_table(os,proc)tbl:string=(unlines(Lem_list.map(string_of_elf64_program_header_table_entryosproc)tbl))(** Static/dynamic linkage *)(** [get_elf32_dynamic_linked pht] tests whether an ELF32 file is a dynamically
* linked object by traversing the program header table and attempting to find
* a header describing a segment with the name of an associated interpreter.
* Returns [true] if any such header is found, [false] --- indicating static
* linkage --- otherwise.
*)(*val get_elf32_dynamic_linked : elf32_program_header_table -> bool*)letget_elf32_dynamic_linkedpht:bool=(List.exists(funp->Nat_big_num.equal(Uint32_wrapper.to_bigintp.elf32_p_type)elf_pt_interp)pht)(** [get_elf64_dynamic_linked pht] tests whether an ELF64 file is a dynamically
* linked object by traversing the program header table and attempting to find
* a header describing a segment with the name of an associated interpreter.
* Returns [true] if any such header is found, [false] --- indicating static
* linkage --- otherwise.
*)(*val get_elf64_dynamic_linked : elf64_program_header_table -> bool*)letget_elf64_dynamic_linkedpht:bool=(List.exists(funp->Nat_big_num.equal(Uint32_wrapper.to_bigintp.elf64_p_type)elf_pt_interp)pht)(** [get_elf32_static_linked] is a utility function defined as the inverse
* of [get_elf32_dynamic_linked].
*)(*val get_elf32_static_linked : elf32_program_header_table -> bool*)letget_elf32_static_linkedpht:bool=(not(get_elf32_dynamic_linkedpht))(** [get_elf64_static_linked] is a utility function defined as the inverse
* of [get_elf64_dynamic_linked].
*)(*val get_elf64_static_linked : elf64_program_header_table -> bool*)letget_elf64_static_linkedpht:bool=(not(get_elf64_dynamic_linkedpht))(** [get_elf32_requested_interpreter ent bs0] extracts the requested interpreter
* of a dynamically linkable ELF file from that file's program header table
* entry of type PT_INTERP, [ent]. Interpreter string is extracted from byte
* sequence [bs0].
* Fails if [ent] is not of type PT_INTERP, or if transcription otherwise fails.
*)(*val get_elf32_requested_interpreter : elf32_program_header_table_entry ->
byte_sequence -> error string*)letget_elf32_requested_interpreterpentbs0:(string)error=(ifNat_big_num.equal(Uint32_wrapper.to_bigintpent.elf32_p_type)elf_pt_interpthenletoff=(Uint32_wrapper.to_bigintpent.elf32_p_offset)inletsiz=(Uint32_wrapper.to_bigintpent.elf32_p_filesz)inbind(Byte_sequence.offset_and_cutoff(Nat_big_num.sub_natsiz((Nat_big_num.of_int1)))bs0)(funcut->return(Byte_sequence.string_of_byte_sequencecut))elsefail"get_elf32_requested_interpreter: not an INTERP segment header")(** [get_elf64_requested_interpreter ent bs0] extracts the requested interpreter
* of a dynamically linkable ELF file from that file's program header table
* entry of type PT_INTERP, [ent]. Interpreter string is extracted from byte
* sequence [bs0].
* Fails if [ent] is not of type PT_INTERP, or if transcription otherwise fails.
*)(*val get_elf64_requested_interpreter : elf64_program_header_table_entry ->
byte_sequence -> error string*)letget_elf64_requested_interpreterpentbs0:(string)error=(ifNat_big_num.equal(Uint32_wrapper.to_bigintpent.elf64_p_type)elf_pt_interpthenletoff=(Uint64_wrapper.to_bigintpent.elf64_p_offset)inletsiz=(Ml_bindings.nat_big_num_of_uint64pent.elf64_p_filesz)inbind(Byte_sequence.offset_and_cutoff(Nat_big_num.sub_natsiz((Nat_big_num.of_int1)))bs0)(funcut->return(Byte_sequence.string_of_byte_sequencecut))elsefail"get_elf64_requested_interpreter: not an INTERP segment header")