diff options
| author | Kathy Gray | 2014-09-29 12:36:14 +0100 |
|---|---|---|
| committer | Kathy Gray | 2014-09-29 12:36:14 +0100 |
| commit | c205e3e77e35cf07fdf616c133d9a70a96986394 (patch) | |
| tree | a827d3d436fb69c4a73df9b9fb066c98fbceab84 /src/elf_model/elf_program_header_table.lem | |
| parent | 80eabf2fca417f5dc245e5212e0f33f6c23bb58b (diff) | |
Add in elf model from Dominic/Stephen. Make run_power build again. Does not effectively use elf model yet
Diffstat (limited to 'src/elf_model/elf_program_header_table.lem')
| -rw-r--r-- | src/elf_model/elf_program_header_table.lem | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/src/elf_model/elf_program_header_table.lem b/src/elf_model/elf_program_header_table.lem new file mode 100644 index 00000000..ad97d566 --- /dev/null +++ b/src/elf_model/elf_program_header_table.lem @@ -0,0 +1,306 @@ +open import Basic_classes +open import Bool +open import Function +open import List +open import Maybe +open import Num +open import String + +open import Elf_types +open import Endianness + +open import Bitstring +open import Error +open import Missing_pervasives +open import Show + +(** Segment types + * + * 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. + *) + +(** Unused array element. All other members of the structure are undefined. *) +let elf_pt_null : nat = 0 +(** A loadable segment. *) +let elf_pt_load : nat = 1 +(** Dynamic linking information. *) +let elf_pt_dynamic : nat = 2 +(** Specifies the location and size of a null-terminated path name to be used to + * invoke an interpreter. + *) +let elf_pt_interp : nat = 3 +(** Specifies location and size of auxiliary information. *) +let elf_pt_note : nat = 4 +(** 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. + *) +let elf_pt_shlib : nat = 5 +(** Specifies the location and size of the program header table. *) +let elf_pt_phdr : nat = 6 +(** Specifies the thread local storage (TLS) template. Need not be supported. *) +let elf_pt_tls : nat = 7 +(** Start of reserved indices for operating system specific semantics. *) +let elf_pt_loos : nat = 128 * 128 * 128 * 256 * 3 (* 1610612736 (* 0x60000000 *) *) +(** End of reserved indices for operating system specific semantics. *) +let elf_pt_hios : nat = (469762047 * 4) + 3 (* 1879048191 (* 0x6fffffff *) *) +(** Start of reserved indices for processor specific semantics. *) +let elf_pt_loproc : nat = (469762048 * 4) (* 1879048192 (* 0x70000000 *) *) +(** End of reserved indices for processor specific semantics. *) +let elf_pt_hiproc : nat = (536870911 * 4) + 3 (* 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. + *) +val string_of_elf_segment_type : (nat -> string) -> (nat -> string) -> nat -> string +let string_of_elf_segment_type os proc pt = + if pt = elf_pt_null then + "PT_NULL" + else if pt = elf_pt_load then + "PT_LOAD" + else if pt = elf_pt_dynamic then + "PT_DYNAMIC" + else if pt = elf_pt_interp then + "PT_INTERP" + else if pt = elf_pt_note then + "PT_NOTE" + else if pt = elf_pt_shlib then + "PT_SHLIB" + else if pt = elf_pt_phdr then + "PT_PHDR" + else if pt = elf_pt_tls then + "PT_TLS" + else if pt >= elf_pt_loos && pt <= elf_pt_hios then + os pt + else if pt >= elf_pt_loproc && pt <= elf_pt_hiproc then + proc pt + else + "Undefined or invalid segment type" + +(** 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. + *) +type elf32_program_header_table_entry = + <| elf32_p_type : elf32_word (** Type of the segment *) + ; elf32_p_offset : elf32_off (** Offset from beginning of file for segment *) + ; elf32_p_vaddr : elf32_addr (** Virtual address for segment in memory *) + ; elf32_p_paddr : elf32_addr (** Physical address for segment *) + ; elf32_p_filesz : elf32_word (** Size of segment in file, in bytes *) + ; elf32_p_memsz : elf32_word (** Size of segment in memory image, in bytes *) + ; elf32_p_flags : elf32_word (** Segment flags *) + ; elf32_p_align : elf32_word (** Segment alignment memory for memory and file *) + |> + +(** 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. + *) +type elf64_program_header_table_entry = + <| elf64_p_type : elf64_word (** Type of the segment *) + ; elf64_p_flags : elf64_word (** Segment flags *) + ; elf64_p_offset : elf64_off (** Offset from beginning of file for segment *) + ; elf64_p_vaddr : elf64_addr (** Virtual address for segment in memory *) + ; elf64_p_paddr : elf64_addr (** Physical address for segment *) + ; elf64_p_filesz : elf64_xword (** Size of segment in file, in bytes *) + ; elf64_p_memsz : elf64_xword (** Size of segment in memory image, in bytes *) + ; elf64_p_align : elf64_xword (** Segment alignment memory for memory and file *) + |> + +(** [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 : (nat -> string) -> (nat -> string) -> elf32_program_header_table_entry -> string +let string_of_elf32_program_header_table_entry os proc entry = + unlines [ + "\t" ^ "Segment type: " ^ string_of_elf_segment_type os proc (nat_of_elf32_word entry.elf32_p_type) + ; "\t" ^ "Offset: " ^ show entry.elf32_p_offset + ; "\t" ^ "Virtual address: " ^ show entry.elf32_p_vaddr + ; "\t" ^ "Physical address: " ^ show entry.elf32_p_paddr + ; "\t" ^ "Segment size (bytes): " ^ show entry.elf32_p_filesz + ; "\t" ^ "Segment size in memory image (bytes): " ^ show entry.elf32_p_memsz + ; "\t" ^ "Flags: " ^ show entry.elf32_p_flags + ; "\t" ^ "Alignment: " ^ show entry.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 : (nat -> string) -> (nat -> string) -> elf64_program_header_table_entry -> string +let string_of_elf64_program_header_table_entry os proc entry = + unlines [ + "\t" ^ "Segment type: " ^ string_of_elf_segment_type os proc (nat_of_elf64_word entry.elf64_p_type) + ; "\t" ^ "Offset: " ^ show entry.elf64_p_offset + ; "\t" ^ "Virtual address: " ^ show entry.elf64_p_vaddr + ; "\t" ^ "Physical address: " ^ show entry.elf64_p_paddr + ; "\t" ^ "Segment size (bytes): " ^ show entry.elf64_p_filesz + ; "\t" ^ "Segment size in memory image (bytes): " ^ show entry.elf64_p_memsz + ; "\t" ^ "Flags: " ^ show entry.elf64_p_flags + ; "\t" ^ "Alignment: " ^ show entry.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 +let string_of_elf32_program_header_table_entry_default = + string_of_elf32_program_header_table_entry + (const "*Default OS specific print*") + (const "*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 +let string_of_elf64_program_header_table_entry_default = + string_of_elf64_program_header_table_entry + (const "*Default OS specific print*") + (const "*Default processor specific print*") + +instance (Show elf32_program_header_table_entry) + let show = string_of_elf32_program_header_table_entry_default +end + +instance (Show elf64_program_header_table_entry) + let show = string_of_elf64_program_header_table_entry_default +end + +(** [read_elf32_program_header_table_entry endian bs0] reads an ELF32 program header table + * entry from bitstring [bs0] assuming endianness [endian]. If [bs0] is larger + * than necessary, the excess is returned from the function, too. + *) +val read_elf32_program_header_table_entry : endianness -> bitstring -> error (elf32_program_header_table_entry * bitstring) +let read_elf32_program_header_table_entry endian bs = + read_elf32_word endian bs >>= fun (typ, bs) -> + read_elf32_off endian bs >>= fun (offset, bs) -> + read_elf32_addr endian bs >>= fun (vaddr, bs) -> + read_elf32_addr endian bs >>= fun (paddr, bs) -> + read_elf32_word endian bs >>= fun (filesz, bs) -> + read_elf32_word endian bs >>= fun (memsz, bs) -> + read_elf32_word endian bs >>= fun (flags, bs) -> + read_elf32_word endian bs >>= 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) + +val read_elf64_program_header_table_entry : endianness -> bitstring -> error (elf64_program_header_table_entry * bitstring) +let read_elf64_program_header_table_entry endian bs = + read_elf64_word endian bs >>= fun (typ, bs) -> + read_elf64_word endian bs >>= fun (flags, bs) -> + read_elf64_off endian bs >>= fun (offset, bs) -> + read_elf64_addr endian bs >>= fun (vaddr, bs) -> + read_elf64_addr endian bs >>= fun (paddr, bs) -> + read_elf64_xword endian bs >>= fun (filesz, bs) -> + read_elf64_xword endian bs >>= fun (memsz, bs) -> + read_elf64_xword endian bs >>= 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. + *) +type elf32_program_header_table = + list elf32_program_header_table_entry + +class (HasElf32ProgramHeaderTable 'a) + val get_elf32_program_header_table : 'a -> maybe elf32_program_header_table +end + +(** 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. + *) +type elf64_program_header_table = + list elf64_program_header_table_entry + +class (HasElf64ProgramHeaderTable 'a) + val get_elf64_program_header_table : 'a -> maybe elf64_program_header_table +end + +(** [read_elf32_program_header_table' endian bs0] reads an ELF32 program header table from + * bitstring [bs0] assuming endianness [endian]. The bitstring [bs0] is assumed + * to have exactly the correct size for the table. For internal use, only. Use + * [read_elf32_program_header_table] below instead. + *) +let rec read_elf32_program_header_table' endian bs0 = + if length bs0 = 0 then + return [] + else + read_elf32_program_header_table_entry endian bs0 >>= fun (entry, bs1) -> + read_elf32_program_header_table' endian bs1 >>= fun tail -> + return (entry::tail) + +(** [read_elf64_program_header_table' endian bs0] reads an ELF64 program header table from + * bitstring [bs0] assuming endianness [endian]. The bitstring [bs0] is assumed + * to have exactly the correct size for the table. For internal use, only. Use + * [read_elf32_program_header_table] below instead. + *) +let rec read_elf64_program_header_table' endian bs0 = + if length bs0 = 0 then + return [] + else + read_elf64_program_header_table_entry endian bs0 >>= fun (entry, bs1) -> + read_elf64_program_header_table' endian bs1 >>= fun tail -> + return (entry::tail) + +(** [read_elf32_program_header_table table_size endian bs0] reads an ELF32 program header + * table from bitstring [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 : nat -> endianness -> bitstring -> error (elf32_program_header_table * bitstring) +let read_elf32_program_header_table table_size endian bs0 = + let (eat, rest) = partition table_size bs0 in + read_elf32_program_header_table' endian eat >>= fun table -> + return (table, rest) + +(** [read_elf64_program_header_table table_size endian bs0] reads an ELF64 program header + * table from bitstring [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 : nat -> endianness -> bitstring -> error (elf64_program_header_table * bitstring) +let read_elf64_program_header_table table_size endian bs0 = + let (eat, rest) = partition table_size bs0 in + read_elf64_program_header_table' endian eat >>= fun table -> + 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. + *) +type pht_print_bundle = (nat -> string) * (nat -> 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 +let string_of_elf32_program_header_table (os, proc) tbl = + unlines (List.map (string_of_elf32_program_header_table_entry os proc) 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 +let string_of_elf64_program_header_table (os, proc) tbl = + unlines (List.map (string_of_elf64_program_header_table_entry os proc) tbl) |
