summaryrefslogtreecommitdiff
path: root/lib/ocaml_rts/linksem/abis/abis.ml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ocaml_rts/linksem/abis/abis.ml')
-rw-r--r--lib/ocaml_rts/linksem/abis/abis.ml1420
1 files changed, 0 insertions, 1420 deletions
diff --git a/lib/ocaml_rts/linksem/abis/abis.ml b/lib/ocaml_rts/linksem/abis/abis.ml
deleted file mode 100644
index 0cbd92d8..00000000
--- a/lib/ocaml_rts/linksem/abis/abis.ml
+++ /dev/null
@@ -1,1420 +0,0 @@
-(*Generated by Lem from abis/abis.lem.*)
-(** The [abis] module is the top-level module for all ABI related code, including
- * some generic functionality that works across all ABIs, and a primitive attempt
- * at abstracting over ABIs for purposes of linking.
- *)
-
-open Lem_basic_classes
-open Lem_bool
-open Lem_num
-open Lem_maybe
-open Lem_list
-open Lem_set
-(*import Map*)
-open Lem_string
-open Show
-open Lem_assert_extra
-open Error
-open Missing_pervasives
-
-open Elf_file
-open Elf_header
-open Elf_interpreted_section
-open Elf_relocation
-open Elf_symbol_table
-open Elf_program_header_table
-open Elf_section_header_table
-open Memory_image
-
-open Abi_amd64
-open Abi_amd64_relocation
-
-open Abi_aarch64_le
-open Abi_aarch64_relocation
-
-open Abi_power64
-open Abi_power64_relocation
-
-open Gnu_ext_abi
-
-open Abi_classes
-open Abi_utilities
-open Elf_types_native_uint
-
-open Memory_image_orderings
-
-(** Relocation operators and their validity on a given platform *)
-
-(*val is_valid_abi_aarch64_relocation_operator : relocation_operator -> bool*)
-let is_valid_abi_aarch64_relocation_operator op:bool=
- ((match op with
- | Page -> true
- | G -> true
- | GDat -> true
- | GLDM -> true
- | DTPRel -> true
- | GTPRel -> true
- | TPRel -> true
- | GTLSDesc -> true
- | Delta -> true
- | LDM -> true
- | TLSDesc -> true
- | Indirect -> true
- | _ -> false
- ))
-
-(*val is_valid_abi_aarch64_relocation_operator2 : relocation_operator2 -> bool*)
-let is_valid_abi_aarch64_relocation_operator2 op:bool=
- ((match op with
- | GTLSIdx -> true
- ))
-
-(*val is_valid_abi_amd64_relocation_operator : relocation_operator -> bool*)
-let is_valid_abi_amd64_relocation_operator op:bool=
- ((match op with
- | Indirect -> true
- | _ -> false (* XXX: not sure about this? *)
- ))
-
-(*val is_valid_abi_amd64_relocation_operator2 : relocation_operator2 -> bool*)
-let is_valid_abi_amd64_relocation_operator2 op:bool=
- ((match op with
- | _ -> false
- ))
-
-(*val is_valid_abi_power64_relocation_operator : relocation_operator -> bool*)
-let is_valid_abi_power64_relocation_operator op:bool= false (* TODO *)
-
-(*val is_valid_abi_power64_relocation_operator2 : relocation_operator2 -> bool*)
-let is_valid_abi_power64_relocation_operator2 op:bool=
- ((match op with
- | _ -> false
- ))
-
-(** Misc. ABI related stuff *)
-
-type any_abi_feature = Amd64AbiFeature of any_abi_feature amd64_abi_feature
- | Aarch64LeAbiFeature of aarch64_le_abi_feature
-
-(*val anyAbiFeatureCompare : any_abi_feature -> any_abi_feature -> Basic_classes.ordering*)
-let anyAbiFeatureCompare f1 f2:int=
- ((match (f1, f2) with
- (Amd64AbiFeature(af1), Amd64AbiFeature(af2)) -> Abi_amd64.abiFeatureCompare0 af1 af2
- |(Amd64AbiFeature(_), _) -> (-1)
- |(Aarch64LeAbiFeature(af1), Amd64AbiFeature(af2)) -> 1
- |(Aarch64LeAbiFeature(af1), Aarch64LeAbiFeature(af2)) -> abiFeatureCompare af1 af2
- ))
-
-(*val anyAbiFeatureTagEquiv : any_abi_feature -> any_abi_feature -> bool*)
-let anyAbiFeatureTagEquiv f1 f2:bool=
- ((match (f1, f2) with
- (Amd64AbiFeature(af1), Amd64AbiFeature(af2)) -> Abi_amd64.abiFeatureTagEq0 af1 af2
- |(Amd64AbiFeature(_), _) -> false
- |(Aarch64LeAbiFeature(af1), Amd64AbiFeature(af2)) -> false
- |(Aarch64LeAbiFeature(af1), Aarch64LeAbiFeature(af2)) -> abiFeatureTagEq af1 af2
- ))
-
-let instance_Basic_classes_Ord_Abis_any_abi_feature_dict:(any_abi_feature)ord_class= ({
-
- compare_method = anyAbiFeatureCompare;
-
- isLess_method = (fun f1 -> (fun f2 -> ( Lem.orderingEqual(anyAbiFeatureCompare f1 f2) (-1))));
-
- isLessEqual_method = (fun f1 -> (fun f2 -> Pset.mem (anyAbiFeatureCompare f1 f2)(Pset.from_list compare [(-1); 0])));
-
- isGreater_method = (fun f1 -> (fun f2 -> ( Lem.orderingEqual(anyAbiFeatureCompare f1 f2) 1)));
-
- isGreaterEqual_method = (fun f1 -> (fun f2 -> Pset.mem (anyAbiFeatureCompare f1 f2)(Pset.from_list compare [1; 0])))})
-
-let instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict:(any_abi_feature)abiFeatureTagEquiv_class= ({
-
- abiFeatureTagEquiv_method = anyAbiFeatureTagEquiv})
-
-let make_elf64_header data osabi abiv ma t entry shoff phoff phnum shnum shstrndx:elf64_header=
- ({ elf64_ident = ([elf_mn_mag0; elf_mn_mag1; elf_mn_mag2; elf_mn_mag3;
- Uint32.of_string (Nat_big_num.to_string elf_class_64);
- Uint32.of_string (Nat_big_num.to_string data);
- Uint32.of_string (Nat_big_num.to_string elf_ev_current);
- Uint32.of_string (Nat_big_num.to_string osabi);
- Uint32.of_string (Nat_big_num.to_string abiv);
- Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0));
- Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0));
- Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0));
- Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0));
- Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0));
- Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0));
- Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0))])
- ; elf64_type = (Uint32.of_string (Nat_big_num.to_string t))
- ; elf64_machine = (Uint32.of_string (Nat_big_num.to_string ma))
- ; elf64_version = (Uint32.of_string (Nat_big_num.to_string elf_ev_current))
- ; elf64_entry = (Uint64.of_string (Nat_big_num.to_string entry))
- ; elf64_phoff = (Uint64.of_string (Nat_big_num.to_string phoff))
- ; elf64_shoff = (Uint64.of_string (Nat_big_num.to_string shoff))
- ; elf64_flags = (Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0)))
- ; elf64_ehsize = (Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 64)))
- ; elf64_phentsize= (Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 56)))
- ; elf64_phnum = (Uint32.of_string (Nat_big_num.to_string phnum))
- ; elf64_shentsize= (Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 64)))
- ; elf64_shnum = (Uint32.of_string (Nat_big_num.to_string shnum))
- ; elf64_shstrndx = (Uint32.of_string (Nat_big_num.to_string shstrndx))
- })
-
-(*val phdr_flags_from_section_flags : natural -> string -> natural*)
-let phdr_flags_from_section_flags section_flags sec_name:Nat_big_num.num=
- (let flags = (Nat_big_num.bitwise_or elf_pf_r (Nat_big_num.bitwise_or
- (if flag_is_set shf_write section_flags then elf_pf_w else Nat_big_num.of_int 0)
- (if flag_is_set shf_execinstr section_flags then elf_pf_x else Nat_big_num.of_int 0)))
- in
- (*let _ = errln ("Phdr flags of section " ^ sec_name ^ "(ELF section flags 0x " ^
- (hex_string_of_natural section_flags) ^ ") are 0x" ^ (hex_string_of_natural flags))
- in*)
- flags)
-
-(*val phdr_is_writable : natural -> bool*)
-let phdr_is_writable flags:bool= (Nat_big_num.equal
- (Nat_big_num.bitwise_and flags elf_pf_w) elf_pf_w)
-
-type can_combine_flags_fn = Nat_big_num.num Pset.set -> Nat_big_num.num option
-
-(* FIXME: lift this to a personality function of the GNU linker?
- * Not sure really... need to try some other linkers. *)
-(*val load_can_combine_flags : can_combine_flags_fn*)
-let load_can_combine_flags flagsets:(Nat_big_num.num)option=
-(
- (* The GNU linker happily adds a .rodata section to a RX segment,
- * but not to a RW segment. So the only clear rule is: if any is writable,
- * all must be writable. *)let flagslist = (Pset.elements flagsets)
- in
- let union_flags = (List.fold_left Nat_big_num.bitwise_or(Nat_big_num.of_int 0) flagslist)
- in
- if List.exists phdr_is_writable flagslist
- then
- if List.for_all phdr_is_writable flagslist then Some union_flags
- else None
- else
- Some union_flags)
-
-(*val tls_can_combine_flags : can_combine_flags_fn*)
-let tls_can_combine_flags flagsets:(Nat_big_num.num)option= (Some (List.fold_left Nat_big_num.bitwise_or(Nat_big_num.of_int 0) (Pset.elements flagsets)))
-
-let maybe_extend_phdr phdr isec1 can_combine_flags:(elf64_program_header_table_entry)option=
- (let new_p_type = (Nat_big_num.of_string (Uint32.to_string phdr.elf64_p_type))
- in
- let this_section_phdr_flags = (phdr_flags_from_section_flags isec1.elf64_section_flags isec1.elf64_section_name_as_string)
- in
- let maybe_extended_flags = (can_combine_flags(Pset.from_list Nat_big_num.compare [ this_section_phdr_flags; Nat_big_num.of_string (Uint32.to_string phdr.elf64_p_flags) ]))
- in
- if (Lem.option_equal Nat_big_num.equal maybe_extended_flags None) then (*let _ = errln "flag mismatch" in*) None
- else let new_p_flags = ((match maybe_extended_flags with Some flags -> flags | _ -> failwith "impossible" ))
- in
- (* The new filesz is the file end offset of this section,
- * minus the existing file start offset of the phdr.
- * Check that the new section begins after the old offset+filesz. *)
- if Nat_big_num.less isec1.elf64_section_offset (Nat_big_num.add (Nat_big_num.of_string (Uint64.to_string phdr.elf64_p_offset)) (Ml_bindings.nat_big_num_of_uint64 phdr.elf64_p_filesz))
- then (*let _ = errln "offset went backwards" in*) None
- else
- let new_p_filesz = (Nat_big_num.add (Ml_bindings.nat_big_num_of_uint64 phdr.elf64_p_filesz) (if Nat_big_num.equal isec1.elf64_section_type sht_progbits then isec1.elf64_section_size else Nat_big_num.of_int 0))
- in
- (* The new memsz is the virtual address end address of this section,
- * minus the existing start vaddr of the phdr.
- * Check that the new section begins after the old vaddr+memsz. *)
- if Nat_big_num.less isec1.elf64_section_addr (Nat_big_num.add (Ml_bindings.nat_big_num_of_uint64 phdr.elf64_p_vaddr) (Ml_bindings.nat_big_num_of_uint64 phdr.elf64_p_memsz))
- then (*let _ = errln "vaddr went backwards" in*) None
- else
- let new_p_memsz = (Nat_big_num.add (Ml_bindings.nat_big_num_of_uint64 phdr.elf64_p_memsz) isec1.elf64_section_size)
- in
- let (one_if_zero : Nat_big_num.num -> Nat_big_num.num) = (fun n -> if Nat_big_num.equal n(Nat_big_num.of_int 0) then Nat_big_num.of_int 1 else n)
- in
- let new_p_align = (lcm (one_if_zero (Ml_bindings.nat_big_num_of_uint64 phdr.elf64_p_align)) (one_if_zero isec1.elf64_section_align))
- in
- Some
- { elf64_p_type = (Uint32.of_string (Nat_big_num.to_string new_p_type))
- ; elf64_p_flags = (Uint32.of_string (Nat_big_num.to_string new_p_flags))
- ; elf64_p_offset = (phdr.elf64_p_offset)
- ; elf64_p_vaddr = (phdr.elf64_p_vaddr)
- ; elf64_p_paddr = (phdr.elf64_p_paddr)
- ; elf64_p_filesz = (Uint64.of_string (Nat_big_num.to_string new_p_filesz))
- ; elf64_p_memsz = (Uint64.of_string (Nat_big_num.to_string new_p_memsz))
- ; elf64_p_align = (Uint64.of_string (Nat_big_num.to_string new_p_align))
- })
-
-let make_new_phdr isec1 t maxpagesize1 commonpagesize1:elf64_program_header_table_entry=
- (let rounded_down_offset = (fun isec1 -> round_down_to commonpagesize1 isec1.elf64_section_offset)
- in
- let offset_round_down_amount = (fun isec1 -> Nat_big_num.sub_nat isec1.elf64_section_offset (rounded_down_offset isec1))
- in
- let rounded_down_vaddr = (fun isec1 -> round_down_to commonpagesize1 isec1.elf64_section_addr)
- in
- let vaddr_round_down_amount = (fun isec1 -> Nat_big_num.sub_nat isec1.elf64_section_addr (rounded_down_vaddr isec1))
- in
- { elf64_p_type = (Uint32.of_string (Nat_big_num.to_string t)) (** Type of the segment *)
- ; elf64_p_flags = (Uint32.of_string (Nat_big_num.to_string (phdr_flags_from_section_flags isec1.elf64_section_flags isec1.elf64_section_name_as_string))) (** Segment flags *)
- ; elf64_p_offset = (Uint64.of_string (Nat_big_num.to_string (rounded_down_offset isec1))) (** Offset from beginning of file for segment *)
- ; elf64_p_vaddr = (Uint64.of_string (Nat_big_num.to_string (rounded_down_vaddr isec1))) (** Virtual address for segment in memory *)
- ; elf64_p_paddr = (Uint64.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0))) (** Physical address for segment *)
- ; elf64_p_filesz = (Uint64.of_string (Nat_big_num.to_string (if Nat_big_num.equal isec1.elf64_section_type sht_nobits then Nat_big_num.of_int 0 else Nat_big_num.add isec1.elf64_section_size (offset_round_down_amount isec1)))) (** Size of segment in file, in bytes *)
- ; elf64_p_memsz = (Uint64.of_string (Nat_big_num.to_string ( Nat_big_num.add isec1.elf64_section_size (vaddr_round_down_amount isec1)))) (** Size of segment in memory image, in bytes *)
- ; elf64_p_align = (Uint64.of_string (Nat_big_num.to_string (* isec.elf64_section_align *)maxpagesize1)) (** Segment alignment memory for memory and file *)
- })
-
-(*val make_load_phdrs : forall 'abifeature. natural -> natural -> annotated_memory_image 'abifeature -> list elf64_interpreted_section -> list elf64_program_header_table_entry*)
-let make_load_phdrs maxpagesize1 commonpagesize1 img2 section_pairs_bare_sorted_by_address:(elf64_program_header_table_entry)list=
-(
- (* accumulate sections into the phdr *)let rev_list = (List.fold_left (fun accum_phdr_list -> (fun isec1 -> (
- (* Do we have a current phdr? *)
- (match accum_phdr_list with
- [] -> (* no, so make one *)
- (*let _ = errln ("Starting the first LOAD phdr for section " ^ isec.elf64_section_name_as_string)
- in*)
- [make_new_phdr isec1 elf_pt_load maxpagesize1 commonpagesize1]
- | current_phdr :: more ->
- (* can we extend it with the current section? *)
- (match maybe_extend_phdr current_phdr isec1 load_can_combine_flags with
- None ->
- (*let _ = errln ("Starting new LOAD phdr for section " ^ isec.elf64_section_name_as_string)
- in*)
- (make_new_phdr isec1 elf_pt_load maxpagesize1 commonpagesize1) :: (current_phdr :: more)
- | Some phdr -> phdr :: more
- )
- )
- ))) [] (List.filter (fun isec1 -> flag_is_set shf_alloc isec1.elf64_section_flags
- && not (flag_is_set shf_tls isec1.elf64_section_flags)) section_pairs_bare_sorted_by_address))
- in
- (*let _ = errln "Successfully made phdrs"
- in*)
- List.rev rev_list)
-
-(*val tls_extend: forall 'abifeature. abi 'abifeature -> abi 'abifeature*)
-let tls_extend a:'abifeature abi=
- ({ is_valid_elf_header = (a.is_valid_elf_header)
- ; make_elf_header = (a.make_elf_header)
- ; reloc = (a.reloc)
- ; section_is_special = (a.section_is_special)
- ; section_is_large = (a.section_is_large)
- ; maxpagesize = (a.maxpagesize)
- ; minpagesize = (a.minpagesize)
- ; commonpagesize = (a.commonpagesize)
- ; symbol_is_generated_by_linker = (a.symbol_is_generated_by_linker)
- ; make_phdrs = (fun maxpagesize1 -> fun commonpagesize1 -> fun file_type -> fun img2 -> fun section_pairs_bare_sorted_by_address -> (
- let rev_list = (List.fold_left (fun accum_phdr_list -> (fun isec1 -> (
- (match accum_phdr_list with
- [] ->
- (*let _ = errln "Making a new TLS program header" in*)
- [make_new_phdr isec1 elf_pt_tls maxpagesize1 commonpagesize1]
- | current_phdr :: more ->
- (match maybe_extend_phdr current_phdr isec1 tls_can_combine_flags with
- None ->
- (make_new_phdr isec1 elf_pt_tls maxpagesize1 commonpagesize1) :: (current_phdr :: more)
- | Some phdr -> phdr :: more
- )
- )
- ))) [] (List.filter (fun isec1 -> flag_is_set shf_alloc isec1.elf64_section_flags
- && flag_is_set shf_tls isec1.elf64_section_flags) section_pairs_bare_sorted_by_address))
- in
- List.rev_append (List.rev (a.make_phdrs maxpagesize1 commonpagesize1 file_type img2 section_pairs_bare_sorted_by_address)) (List.rev rev_list)
- ))
- ; max_phnum = (Nat_big_num.add(Nat_big_num.of_int 1) a.max_phnum)
- ; guess_entry_point = (a.guess_entry_point)
- ; pad_data = (a.pad_data)
- ; pad_code = (a.pad_code)
- ; generate_support = (a.generate_support)
- ; concretise_support = (a.concretise_support)
- ; get_reloc_symaddr = (a.get_reloc_symaddr)
- })
-
-(* We use these snappily-named functions in relocation calculations. *)
-
-(*val make_default_phdrs : forall 'abifeature. natural -> natural -> natural (* file type *) -> annotated_memory_image 'abifeature -> list elf64_interpreted_section -> list elf64_program_header_table_entry*)
-let make_default_phdrs maxpagesize1 commonpagesize1 t img2 section_pairs_bare_sorted_by_address:(elf64_program_header_table_entry)list=
-(
- (* FIXME: do the shared object and dyn. exec. stuff too *)make_load_phdrs maxpagesize1 commonpagesize1 img2 section_pairs_bare_sorted_by_address)
-
-(*val find_start_symbol_address : forall 'abifeature. Ord 'abifeature, AbiFeatureTagEquiv 'abifeature => annotated_memory_image 'abifeature -> maybe natural*)
-let find_start_symbol_address dict_Basic_classes_Ord_abifeature dict_Abi_classes_AbiFeatureTagEquiv_abifeature img2:(Nat_big_num.num)option=
-(
- (* Do we have a symbol called "_start"? *)let all_defs = (Memory_image_orderings.defined_symbols_and_ranges
- dict_Basic_classes_Ord_abifeature dict_Abi_classes_AbiFeatureTagEquiv_abifeature img2)
- in
- let get_entry_point = (fun (maybe_range, symbol_def) ->
- if symbol_def.def_symname = "_start"
- then Some (maybe_range, symbol_def)
- else None
- )
- in
- let all_entry_points = (Lem_list.mapMaybe get_entry_point all_defs)
- in
- (match all_entry_points with
- [(maybe_range, symbol_def)] ->
- (match maybe_range with
- Some (el_name, (el_off, len)) ->
- (match Pmap.lookup el_name img2.elements with
- None -> failwith ("_start symbol defined in nonexistent element `" ^ (el_name ^ "'"))
- | Some el_rec ->
- (match el_rec.startpos with
- None -> (*let _ = Missing_pervasives.errln "warning: saw `_start' in element with no assigned address" in *)None
- | Some x -> (* success! *) Some ( Nat_big_num.add x el_off)
- )
- )
- | _ -> (*let _ = Missing_pervasives.errln "warning: `_start' symbol with no range" in*) None
- )
- | [] -> (* no _start symbol *) None
- | _ -> (*let _ = Missing_pervasives.errln ("warning: saw multiple `_start' symbols: " ^
- (let (ranges, defs) = unzip all_entry_points in show ranges)) in *)None
- ))
-
-(*val pad_zeroes : natural -> list byte*)
-let pad_zeroes n:(char)list= (replicate0 n (Char.chr (Nat_big_num.to_int (Nat_big_num.of_int 0))))
-
-(*val pad_0x90 : natural -> list byte*)
-let pad_0x90 n:(char)list= (replicate0 n (Char.chr (Nat_big_num.to_int ( Nat_big_num.mul(Nat_big_num.of_int 9)(Nat_big_num.of_int 16)))))
-
-(* null_abi captures ABI details common to all ELF-based, System V-based systems.
- * HACK: for now, specialise to 64-bit ABIs. *)
-(*val null_abi : abi any_abi_feature*)
-let null_abi:(any_abi_feature)abi= ({
- is_valid_elf_header = is_valid_elf64_header
- ; make_elf_header = (make_elf64_header elf_data_2lsb elf_osabi_none(Nat_big_num.of_int 0) elf_ma_none)
- ; reloc = noop_reloc
- ; section_is_special = elf_section_is_special
- ; section_is_large = (fun s -> (fun f -> false))
- ; maxpagesize = (Nat_big_num.mul (Nat_big_num.mul(Nat_big_num.of_int 2)(Nat_big_num.of_int 256))(Nat_big_num.of_int 4096)) (* 2MB; bit of a guess, based on gdb and prelink code *)
- ; minpagesize =(Nat_big_num.of_int 1024) (* bit of a guess again *)
- ; commonpagesize =(Nat_big_num.of_int 4096)
- ; symbol_is_generated_by_linker = (fun symname -> symname = "_GLOBAL_OFFSET_TABLE_")
- ; make_phdrs = make_default_phdrs
- ; max_phnum =(Nat_big_num.of_int 2)
- ; guess_entry_point =
- (find_start_symbol_address
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict)
- ; pad_data = pad_zeroes
- ; pad_code = pad_zeroes
- ; generate_support = ( (* fun _ -> *)fun _ -> get_empty_memory_image ())
- ; concretise_support = (fun img2 -> img2)
- ; get_reloc_symaddr =
- (default_get_reloc_symaddr
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict)
- })
-
-(*val got_entry_ordering : (string * maybe symbol_definition) -> (string * maybe symbol_definition) -> Basic_classes.ordering*)
-let got_entry_ordering (s1, md1) (s2, md2):int= (compare s1 s2) (* FIXME *)
-
-let is_ifunc_def:(symbol_definition)option ->bool= (fun maybe_def ->
-(match maybe_def with
- None -> false
- | Some d -> Nat_big_num.equal (get_elf64_symbol_type d.def_syment) stt_gnu_ifunc
-))
-
-let amd64_reloc_needs_got_slot:'a ->reloc_site ->(symbol_definition)option ->bool= (fun symref -> fun rr -> fun maybe_def ->
- if ( Pset.mem(get_elf64_relocation_a_type rr.ref_relent)(Pset.from_list Nat_big_num.compare [
- r_x86_64_got32; r_x86_64_gotpcrel; r_x86_64_gottpoff; r_x86_64_gotoff64; r_x86_64_gotpc32 (* ; r_x86_64_gotpc32_tlsdesc *)
- ])) then
- true
- else if is_ifunc_def maybe_def
- then
- (* This reference is bound to a STT_GNU_IFUNC definition.
- * What now needs to happen is as follows.
- * - we ensure that a GOT entry is generated for this symbol (we do this here);
- * - we ensure that a PLT entry (specifically .iplt) is generated for the symbol (Below);
- * - on making the GOT, we also generate a .rela.plt relocation record covering the GOT slot;
- * - when applying the relocation, of whatever kind, the address of the PLT slot
- * is the address input to the calculation
- * - the code marked by the STT_GNU_IFUNC symbol definition is not the function
- * to call; it's the function that calculates the address of the function to call!
- * this becomes the addend of the R_X86_64_IRELATIVE Elf64_Rela marking the GOT slot
- * - note that for static linking, the GOT is usually pre-filled (cf. dynamically when it is filled by JUMP_SLOT relocs).
- * ... but our GOT entries *must* have corresponding R_X86_64_IRELATIVEs generated
- *)
- true
- else false)
-
-
-let amd64_reloc_needs_plt_slot (symref : symbol_reference_and_reloc_site) rr maybe_def ref_is_statically_linked:bool=
- (if ( Pset.mem(get_elf64_relocation_a_type rr.ref_relent)(Pset.from_list Nat_big_num.compare [
- r_x86_64_plt32 (* NOTE: when generating shared libs, it starts to matter
- * where the definition is -- anything that is locally interposable
- * or undefined will need a slot. See amd64_get_reloc_symaddr. *)
- ])) then
- not (ref_is_statically_linked rr)
- else if is_ifunc_def maybe_def
- then
- true
- else
- (* not a PLT ref *)
- false)
-
-let amd64_find_got_label_and_element img2:((string*(symbol_definition)option)list*element)option=
- ((match Pmap.lookup ".got" img2.elements with
- None -> (* got no GOT? okay... *) None
- | Some got_el ->
- (* Find the GOT tag. *)
- let tags_and_ranges = (Multimap.lookupBy0
- (instance_Basic_classes_Ord_Memory_image_range_tag_dict
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict) (instance_Basic_classes_Ord_Maybe_maybe_dict
- (instance_Basic_classes_Ord_tup2_dict
- Lem_string_extra.instance_Basic_classes_Ord_string_dict
- (instance_Basic_classes_Ord_tup2_dict
- instance_Basic_classes_Ord_Num_natural_dict
- instance_Basic_classes_Ord_Num_natural_dict))) instance_Basic_classes_SetType_var_dict (instance_Basic_classes_SetType_Maybe_maybe_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_var_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_Num_natural_dict
- instance_Basic_classes_SetType_Num_natural_dict))) (Memory_image_orderings.tagEquiv
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict) (AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0([])))) img2.by_tag)
- in
- (match tags_and_ranges with
- [] -> failwith "error: GOT element but no ABI feature GOT tag"
- | [(AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0(l))), _)] -> Some (l, got_el)
- | _ -> failwith ("multiple GOT elements/tags")
- )
- ))
-
-let amd64_find_plt_label_and_element img2:((string*(symbol_definition)option*(any_abi_feature)plt_entry_content_fn)list*element)option=
- ((match Pmap.lookup ".plt" img2.elements with
- None -> (* got no PLT? okay... *) None
- | Some plt_el ->
- (* Find the PLT tag. *)
- let tags_and_ranges = (Multimap.lookupBy0
- (instance_Basic_classes_Ord_Memory_image_range_tag_dict
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict) (instance_Basic_classes_Ord_Maybe_maybe_dict
- (instance_Basic_classes_Ord_tup2_dict
- Lem_string_extra.instance_Basic_classes_Ord_string_dict
- (instance_Basic_classes_Ord_tup2_dict
- instance_Basic_classes_Ord_Num_natural_dict
- instance_Basic_classes_Ord_Num_natural_dict))) instance_Basic_classes_SetType_var_dict (instance_Basic_classes_SetType_Maybe_maybe_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_var_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_Num_natural_dict
- instance_Basic_classes_SetType_Num_natural_dict))) (Memory_image_orderings.tagEquiv
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict) (AbiFeature(Amd64AbiFeature(Abi_amd64.PLT0([])))) img2.by_tag)
- in
- (match tags_and_ranges with
- [] -> failwith "error: PLT element but no ABI feature PLT tag"
- | [(AbiFeature(Amd64AbiFeature(Abi_amd64.PLT0(l))), _)] -> Some (l, plt_el)
- | _ -> failwith ("multiple PLT elements/tags")
- )
- ))
-
-let got_slot_index_for_symname dict_Basic_classes_Eq_a symname got_label:(int)option=
- (Lem_list.find_index (fun (s, _) ->
- dict_Basic_classes_Eq_a.isEqual_method s symname) got_label)
-
-(*val amd64_get_reloc_symaddr : symbol_definition -> annotated_memory_image any_abi_feature -> maybe reloc_site -> natural*)
-let amd64_get_reloc_symaddr the_input_def output_img maybe_reloc1:Nat_big_num.num=
-(
- (* The default implementation simply looks up a "matching" symbol in the output image
- * and calculates its address.
- *
- * That's normally fine, even for via-GOT references since their calculations don't
- * use the symaddr. For via-PLT references, we need to use the PLT slot address.
- * HMM. Isn't this duplicating the role of functions like amd64_plt_slot_addr?
-
- * Recall that we created this get_reloc_symaddr mechanism to deal with IFUNC symbols.
- * With an IFUNC symbol, we reference it simply using a PC32 relocation, but the address
- * that gets filled in isn't the IFUNC address; it's the corresponding PLT slot.
- * HMM: does this happen for other PC32 references? If so, we'll need this mechanism
- * there. And it certainly does, because relocatable object code never uses PLT32
- * relocs.
- *
- * I had previously tried to handle this issue in mark_fate_of_relocs, using the
- * 1-argument ApplyReloc(_) and MakePIC to encode the "replacement". But at that stage,
- * which is ABI-independent and happens before address assignment?, we can't know enough.
- *)
- (* match bound_def_in_input with
- Nothing -> 0
- | Just the_input_def -> *)if is_ifunc_def (Some(the_input_def))
- then
- (* We need to return the address of the "matching" PLT slot.
- * PLT label entries are (symname, maybe_def, content_fn). *)
- (match amd64_find_plt_label_and_element output_img with
- None -> failwith "error: ifunc but no PLT"
- | Some (l, plt_el) ->
- (match Lem_list.find_index (fun (symname, _, _) -> symname = the_input_def.def_symname) l with
- (* FIXME: using symnames seems wrong *)
- Some idx1 ->
- (match plt_el.startpos with
- Some addr -> Nat_big_num.add addr (Nat_big_num.mul (Nat_big_num.of_int idx1)(Nat_big_num.of_int 16)) (* size of a PLT entry *)
- | None -> failwith "error: PLT has no address assigned"
- )
- | None ->Nat_big_num.of_int 0
- )
- )
- else default_get_reloc_symaddr
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict the_input_def output_img maybe_reloc1)
- (* end *)
-
-(* *)
-(*val amd64_generate_support : (* list (list reloc_site_resolution) -> *) list (string * annotated_memory_image any_abi_feature) -> annotated_memory_image any_abi_feature*)
-let amd64_generate_support (* reloc_resolution_lists *) input_fnames_and_imgs:(any_abi_feature)annotated_memory_image=
-(
- (* We generate a basic GOT. At the moment we can only describe the GOT
- * contents abstractly, not as its binary content, because addresses
- * have not yet been fixed.
- *
- * To do this, we create a set of Abi_amd64.GOTEntry records, one for
- * each distinct symbol that is referenced by one or more GOT-based relocations.
- * To enumerate these, we look at all the symbol refs in the image.
- *)let ref_is_statically_linked = (fun _ -> true)
- in
- let (fnames, input_imgs) = (List.split input_fnames_and_imgs)
- in
- let tags_and_ranges_by_image = (Lem_list.mapi (fun i -> fun (fname1, img2) ->
- (i, fname1, Multimap.lookupBy0
- (instance_Basic_classes_Ord_Memory_image_range_tag_dict
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict) (instance_Basic_classes_Ord_Maybe_maybe_dict
- (instance_Basic_classes_Ord_tup2_dict
- Lem_string_extra.instance_Basic_classes_Ord_string_dict
- (instance_Basic_classes_Ord_tup2_dict
- instance_Basic_classes_Ord_Num_natural_dict
- instance_Basic_classes_Ord_Num_natural_dict))) instance_Basic_classes_SetType_var_dict (instance_Basic_classes_SetType_Maybe_maybe_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_var_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_Num_natural_dict
- instance_Basic_classes_SetType_Num_natural_dict))) (Memory_image_orderings.tagEquiv
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict) (SymbolRef(null_symbol_reference_and_reloc_site)) img2.by_tag)
- ) input_fnames_and_imgs)
- in
- let refs_via_got = (list_concat_map (fun (i, fname1, tags_and_ranges) -> Lem_list.mapMaybe (fun (tag, maybe_range) -> (match tag with
- SymbolRef(symref) ->
- (* Is this ref a relocation we're going to apply, and does it reference the GOT? *)
- (match (symref.maybe_reloc, symref.maybe_def_bound_to) with
- (None, _) -> None
- | (Some rr, Some(ApplyReloc, maybe_def)) ->
- if amd64_reloc_needs_got_slot symref rr maybe_def then
- (*let _ = errln ("Saw a via-GOT symbol reference: to `" ^ symref.ref.ref_symname ^ "' coming from linkable " ^ (show i) ^ " (" ^
- fname ^ "), logically from section " ^ (show rr.ref_src_scn)) in *)
- Some (symref.ref.ref_symname, maybe_def)
- else None
- | (Some rr, Some(makePIC0, maybe_def)) -> failwith "FIXME: PIC support please"
- )
- | _ -> failwith "impossible: reloc site tag is not a SymbolRef"
- )) tags_and_ranges) tags_and_ranges_by_image)
- in
- let (symnames, maybe_defs) = (List.split refs_via_got)
- in
- (*let _ = errln ("GOT includes defs with names: " ^ (show (Set_extra.toList (Set.fromList symnames))))
- in*)
- let got_pairs_set = (Pset.from_list (pairCompare compare (maybeCompare compare)) refs_via_got)
- in
- let got_defs_set = (Pset.from_list (maybeCompare compare) maybe_defs)
- in
- (* This is where we fix the order of the GOT entries. *)
- let got_pairs_list = (Pset.elements got_pairs_set)
- in
- let got_idx_and_maybe_def_by_symname_map = (Lem_map.fromList
- (Lem_map.instance_Map_MapKeyType_var_dict
- instance_Basic_classes_SetType_var_dict) (mapi (fun slot_idx -> fun (symname, maybe_def) -> (symname, (slot_idx, maybe_def))) got_pairs_list))
- in
- let got_ifunc_set = (let x2 =(Pset.from_list (maybeCompare compare)
- []) in Pset.fold
- (fun maybe_d x2 ->
- if is_ifunc_def maybe_d then Pset.add maybe_d x2 else x2) got_defs_set
- x2)
- in
- (* Quirk: what if we have the same def appearing under two different symnames?
- * This shouldn't happen, at present.
- * What if we have the same symname related to two different defs? This also
- * shouldn't happen, because only global symbols go in the GOT, so we don't have
- * to worry about local symbols with the same name as another symbol. But still, it
- * could plausibly happen in some situations with weird symbol visibilities or binding. *)
- (* if Set.size pairs_set <> Set.size defs_set then
- failwith "something quirky going on with GOT symbol defs and their names"
- else *)
-(* let name_def_pairs = List.foldl (fun acc -> fun (idx, symname, (maybe_range, rr)) ->
- Set.insert (
-
- symname, (match rr.maybe_def_bound_to with
- Map.lookup symname acc with
- Nothing -> [item]
- | Just l -> item :: l
- end) acc) {} refs_via_got
- in *)
- let got_nentries = (Nat_big_num.of_int (Pset.cardinal got_pairs_set))
- in
- let got_entrysize =(Nat_big_num.of_int 8)
- in
- (* We also need a PLT... sort of. We need a way to resolve via-PLT relocs.
- * But we might do so without actually creating a (non-zero-length) PLT.
- * Again, this is to accommodate the sorts of optimisations the GNU linker does.
- *
- * Note that every PLT entry has a corresponding GOT entry. Here we are simply
- * enumerating the via-PLT relocs that imply a PLT entry. We look their GOT
- * slots up later, by symbol name. *)
- let refs_via_plt = (list_concat_map (fun (i, fname1, tags_and_ranges) -> Lem_list.mapMaybe (fun (tag, maybe_range) -> (match tag with
- SymbolRef(symref) ->
- (* Is this ref a relocation we're going to apply, and does it reference the GOT? *)
- (match (symref.maybe_reloc, symref.maybe_def_bound_to) with
- (None, _) -> None
- | (Some rr, Some(ApplyReloc, maybe_def)) ->
- if amd64_reloc_needs_plt_slot symref rr maybe_def ref_is_statically_linked
- then
- (*let _ = if is_ifunc_def maybe_def then
- (* we ensure that a PLT entry (specifically .iplt) is generated for the symbol *)
- errln ("Saw a reference to IFUNC symbol `" ^ symref.ref.ref_symname ^ "'; ref is coming from linkable " ^ (show i) ^ " (" ^
- fname ^ "), relent idx " ^ (show rr.ref_rel_idx) ^ " logically from section " ^ (show rr.ref_src_scn) )
- else
- errln ("Saw a via-PLT symbol reference: to `" ^ symref.ref.ref_symname ^ "' coming from linkable " ^ (show i) ^ " (" ^
- fname ^ "), relent idx " ^ (show rr.ref_rel_idx) ^ " logically from section " ^ (show rr.ref_src_scn) ^
- match maybe_def with Just _ -> ", with definition" | Nothing -> ", not bound to anything" end
- )
- in*)
- Some(symref.ref.ref_symname, maybe_def)
- else None
- | (Some rr, Some(makePIC0, maybe_def)) -> failwith "FIXME: PIC support please"
- )
- | _ -> failwith "impossible: reloc site tag is not a SymbolRef"
- )) tags_and_ranges) tags_and_ranges_by_image)
- in
- (*let _ = errln ("Saw " ^ (show (length refs_via_plt)) ^ " relocations of a via-PLT type")
- in*)
- (* account for the optimisations we did on GOT slots *)
- let refs_via_plt_having_got_slot = (Lem_list.mapMaybe (fun (symname, _) ->
- (match Pmap.lookup symname got_idx_and_maybe_def_by_symname_map with
- Some(idx1, maybe_d) -> Some (symname, idx1, maybe_d)
- | None -> None
- )
- ) refs_via_plt)
- in
- (*let _ = errln ("Saw " ^ (show (length refs_via_plt_having_got_slot)) ^ " relocations of a via-PLT type where we instantiated a GOT slot for the symbol")
- in*)
- let (plt_symnames, plt_got_idxs, plt_ref_bound_to_maybe_defs) = (unzip3 refs_via_plt_having_got_slot)
- in
- let plt_symnames_excluding_header = (Pset.elements ((Pset.from_list compare plt_symnames)))
- in
- (*let _ = errln ("PLT symnames: " ^ (show plt_symnames_excluding_header))
- in*)
- let n_iplt_entries = (Pset.cardinal got_ifunc_set)
- (* The content of the IPLT entries depends on the address assignment of GOT slots
- * and the IFUNCs that they reference. We need to reserve space for them here, though. *)
- in
- (*let _ = errln ("We think there should be " ^ (show n_iplt_entries) ^ " PLT entries due to references to IFUNC symbols")
- in*)
- (* let got_entries_referencing_functions = (List.filter (fun (symname, maybe_def) ->
- match def with
- Just d -> d.def_syment
- | Nothing -> false
- end) refs_via_got)
- in *)
- let plt_needs_header_entry = ((List.length plt_symnames_excluding_header) > n_iplt_entries)
- in
- (*let _ = errln ("PLT needs header entry? " ^ (show plt_needs_header_entry))
- in*)
- let total_n_plt_entries = (Nat_big_num.add (if plt_needs_header_entry then Nat_big_num.of_int 1 else Nat_big_num.of_int 0) (Missing_pervasives.length plt_symnames_excluding_header))
- in
- (*let _ = errln ("PLT total entry count: " ^ (show total_n_plt_entries))
- in*)
- let new_by_range =(Pset.from_list (pairCompare (maybeCompare (pairCompare compare (pairCompare Nat_big_num.compare Nat_big_num.compare))) compare) [
- (Some(".plt", (Nat_big_num.of_int 0, Nat_big_num.mul(Nat_big_num.of_int 16) total_n_plt_entries)), AbiFeature(Amd64AbiFeature(Abi_amd64.PLT0(
- (* header content fn *)
- (* the header entry is required only for dynamic linking, which is not supported yet *)
- (* (if plt_needs_header_entry then
- ("", Nothing, (((fun (got_base_addr : natural) -> fun (plt_base_addr : natural) ->
- (0, [byte_of_natural 0; byte_of_natural 0; byte_of_natural 0; byte_of_natural 0;
- byte_of_natural 0; byte_of_natural 0; byte_of_natural 0; byte_of_natural 0;
- byte_of_natural 0; byte_of_natural 0; byte_of_natural 0; byte_of_natural 0;
- byte_of_natural 0; byte_of_natural 0; byte_of_natural 0; byte_of_natural 0]))) : plt_entry_content_fn any_abi_feature))
- else ("", Nothing, (((fun (got_base_addr : natural) -> fun (plt_base_addr : natural) -> (0, []))) : plt_entry_content_fn any_abi_feature))
- )
- ++ *) (
- mapi (fun plt_entry_idx_not_counting_header -> (fun symname ->
- (* We want to label the PLT entry with a function that
- * - accepts the PLT base address, the GOT base address and the GOT slot number;
- * - closure-captures whatever else it needs (whether we're inserting a PLT header);
- * - yields the *full contents of the PLT entry* before relocation.
- * - recall that PLT entries might be "header" (the special one at the start),
- * "normal" (to be relocated with R_X86_64_JUMP_SLOT)
- * or "irelative" (to be relocated with R_X86_64_IRELATIVE).
- * Q. Why are R_X86_64_JUMP_SLOT necessary?
- * The PLT entries are doing relative addressing, and
- * the offset to the GOT entry is known at link time,
- * so the linker should be able to fill them in. In
- * fact, it does. HMM. Understand this better. *)
- (* What is the GOT slot number? *)
- let (got_slot_idx, maybe_def) = ((match Pmap.lookup symname got_idx_and_maybe_def_by_symname_map with
- Some(idx1, maybe_d) -> (Nat_big_num.of_int idx1, maybe_d)
- | None -> failwith ("GOT does not contain symbol `" ^ (symname ^ "' required by PLT entry"))
- ))
- in
- (symname, maybe_def, ((fun (got_base_addr : Nat_big_num.num) -> fun (plt_base_addr : Nat_big_num.num) ->
- (* Okay, now we can generate the entry. NOTE that we're lexically still in generate_support,
- * but we'll be called from concretise_support. The code that generates the header
- * entry is actually in concretise_support.
- *
- * If the entry is a normal entry, it looks like
- *
- 0x0000000000400410 <+0>: ff 25 02 0c 20 00 jmpq *0x200c02(%rip) # 0x601018 <puts@got.plt>
- 0x0000000000400416 <+6>: 68 00 00 00 00 pushq $0x0
- 0x000000000040041b <+11>: e9 e0 ff ff ff jmpq 0x400400
- *
- * If the entry is an irelative entry, it looks like
- *
- 400350: ff 25 02 fd 2b 00 jmpq *0x2bfd02(%rip) # 6c0058 <_GLOBAL_OFFSET_TABLE_+0x58>
- 400356: 68 00 00 00 00 pushq $0x0
- 40035b: e9 00 00 00 00 jmpq 400360 <check_one_fd.part.0>
-
- * ... i.e. basically the same but the pushq and jmpq have literal-zero args (they're not used).
- *)
- let this_plt_slot_base_addr = (Nat_big_num.add plt_base_addr (Nat_big_num.mul(Nat_big_num.of_int 16) (
- Nat_big_num.add(Nat_big_num.of_int plt_entry_idx_not_counting_header) (if plt_needs_header_entry then Nat_big_num.of_int 1 else Nat_big_num.of_int 0))))
- in
- (*let _ = Missing_pervasives.errln ("PLT slot base address for symname `" ^ symname ^ "': 0x" ^
- (hex_string_of_natural this_plt_slot_base_addr))
- in*)
- let got_slot_addr = (Nat_big_num.add got_base_addr (Nat_big_num.mul(Nat_big_num.of_int 8) got_slot_idx))
- in
- (*let _ = Missing_pervasives.errln ("GOT slot address for symname `" ^ symname ^ "' (idx " ^ (show got_slot_idx) ^ "): 0x" ^
- (hex_string_of_natural got_slot_addr))
- in*)
- let maybe_header_entry_address = (if plt_needs_header_entry then Some(plt_base_addr) else None)
- in
- let offset_to_got_slot = (Nat_big_num.sub ( got_slot_addr) (( Nat_big_num.add this_plt_slot_base_addr(Nat_big_num.of_int 6))))
- in
- (*let _ = Missing_pervasives.errln ("PLT's PC-relative index to GOT slot for symname `" ^ symname ^ "' (GOT idx " ^ (show got_slot_idx) ^ ") is (decimal)" ^
- (show offset_to_got_slot))
- in*)
- let content_bytes =
- (List.rev_append (List.rev (List.rev_append (List.rev (List.rev_append (List.rev (List.rev_append (List.rev (List.rev_append (List.rev [Char.chr (Nat_big_num.to_int (Nat_big_num.of_int 255)); Char.chr (Nat_big_num.to_int (Nat_big_num.of_int 37))]) (* offset to the GOT entry, from the *next* instruction start, signed 32-bit LE *)(to_le_signed_bytes(Nat_big_num.of_int 4) offset_to_got_slot))) [Char.chr (Nat_big_num.to_int (Nat_big_num.of_int 104))])) (* plt slot number not including header, 32-bit LE *)(to_le_unsigned_bytes(Nat_big_num.of_int 4) ((Nat_big_num.of_int plt_entry_idx_not_counting_header))))) [Char.chr (Nat_big_num.to_int (Nat_big_num.of_int 233))])) (to_le_signed_bytes(Nat_big_num.of_int 4) (
- if is_ifunc_def maybe_def
- then Nat_big_num.of_int 0
- else (match maybe_header_entry_address with
- None -> failwith "normal PLT entry but no PLT header!"
- | Some header_entry_address -> Nat_big_num.sub ( header_entry_address) (( Nat_big_num.add this_plt_slot_base_addr(Nat_big_num.of_int 16)))
- )
- )))
- in
- (*let _ = errln ("Created a PLT entry consisting of " ^ (show (length content_bytes)) ^ " bytes.")
- in*)
- (this_plt_slot_base_addr, content_bytes)
- (*
- match maybe_def with
- Nothing -> 0
- | Just sd ->
- match Memory_image_orderings.find_defs_matching sd img with
- [] -> failwith ("no matching definitions for PLT entry named " ^ symname)
- | [(Just(def_el_name, (def_start, def_len)), d)] ->
- match element_and_offset_to_address (def_el_name, def_start) img with
- Nothing -> failwith ("PLT: no address for definition offset in element " ^ def_el_name)
- | Just x ->
- let _ = errln ("PLT slot for symbol `" ^ symname ^
- "' calculated at (non-PLT) address 0x" ^ (hex_string_of_natural x) ^
- " (offset 0x" ^ (hex_string_of_natural def_start) ^ " in element " ^ def_el_name ^ ")")
- in
- x
- end
- | _ -> failwith ("multiple matching definitions for PLT entry named " ^ symname)
- end
- end
- *)
-
- ) : any_abi_feature plt_entry_content_fn))
- ))
- plt_symnames)
- )))
- )
- ; (Some(".plt", (Nat_big_num.of_int 0, Nat_big_num.mul(Nat_big_num.of_int 16) total_n_plt_entries)), FileFeature(ElfSection(Nat_big_num.of_int 1,
- { elf64_section_name =(Nat_big_num.of_int 0) (* ignored *)
- ; elf64_section_type = sht_progbits
- ; elf64_section_flags = shf_alloc
- ; elf64_section_addr =(Nat_big_num.of_int 0) (* ignored -- covered by element *)
- ; elf64_section_offset =(Nat_big_num.of_int 0) (* ignored -- will be replaced when file offsets are assigned *)
- ; elf64_section_size = (Nat_big_num.mul(Nat_big_num.of_int 16) total_n_plt_entries) (* ignored? NO, we use it in linker_script to avoid plumbing through the element record *)
- ; elf64_section_link =(Nat_big_num.of_int 0)
- ; elf64_section_info =(Nat_big_num.of_int 0)
- ; elf64_section_align =(Nat_big_num.of_int 16)
- ; elf64_section_entsize =(Nat_big_num.of_int 16)
- ; elf64_section_body = Byte_sequence.empty (* ignored *)
- ; elf64_section_name_as_string = ".plt"
- }
- )))
- (* For each GOT entry that corresponds to a thread-local symbol, we also need to
- * generate a relocation record. HMM. These new relocation records are ones we don't
- * yet have decisions for. That might be a problem.
- *
- * In fact, this approach is not appropriate for static linking. Just put the offsets
- * in there when we concretise the GOT. Something like this will be good for
- * dynamic linking, though. At the moment, creating a SymbolRef at this stage
- * is problematic because it's not in the bindings list. When we generate shared
- * objects, we'll have to revisit that code. *)
- (* (Just(".got", (i * got_entrysize, 8)), SymbolRef( <|
- ref = <| ref_symname = symname
- ; ref_syment = sd.def_syment
- ; ref_sym_scn = 0
- ; ref_sym_idx = 0
- |>
- ; maybe_def_bound_to = Just(ApplyReloc, Just sd)
- ; maybe_reloc = Just(
- <|
- ref_relent =
- <| elf64_ra_offset = elf64_addr_of_natural 0
- ; elf64_ra_info = elf64_xword_of_natural r_x86_64_tpoff64
- ; elf64_ra_addend = elf64_sxword_of_integer 0
- |>
- ; ref_rel_scn = 0
- ; ref_rel_idx = 0
- ; ref_src_scn = 0
- |>
- )
- |>))
- | forall ((i, symname, sd) IN (Set.fromList (mapMaybei (fun i -> fun (symname, maybe_def) ->
- match maybe_def with Nothing -> Nothing | Just sd -> Just(i, symname, sd) end) refs_via_got)))
- | get_elf64_symbol_type sd.def_syment = stt_tls
- *)
- ; (Some(".got", (Nat_big_num.of_int 0, Nat_big_num.mul got_nentries got_entrysize)), AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0(got_pairs_list))))
- ; (Some(".got", (Nat_big_num.of_int 0, Nat_big_num.mul got_nentries got_entrysize)), FileFeature(ElfSection(Nat_big_num.of_int 2,
- { elf64_section_name =(Nat_big_num.of_int 0) (* ignored *)
- ; elf64_section_type = sht_progbits
- ; elf64_section_flags = (Nat_big_num.bitwise_or shf_write shf_alloc)
- ; elf64_section_addr =(Nat_big_num.of_int 0) (* ignored -- covered by element *)
- ; elf64_section_offset =(Nat_big_num.of_int 0) (* ignored -- will be replaced when file offsets are assigned *)
- ; elf64_section_size = (Nat_big_num.mul got_nentries got_entrysize) (* ignored? NO, we use it in linker_script to avoid plumbing through the element record *)
- ; elf64_section_link =(Nat_big_num.of_int 0)
- ; elf64_section_info =(Nat_big_num.of_int 0)
- ; elf64_section_align =(Nat_big_num.of_int 8)
- ; elf64_section_entsize = got_entrysize
- ; elf64_section_body = Byte_sequence.empty (* ignored *)
- ; elf64_section_name_as_string = ".got"
- }
- )))
- ; (* FIXME: I've a feeling _GLOBAL_OFFSET_TABLE_ generally doesn't mark the *start* of the GOT;
- * it's some distance in. What about .got.plt? *)
- (Some(".got", (Nat_big_num.of_int 0, Nat_big_num.mul got_nentries got_entrysize)), SymbolDef({
- def_symname = "_GLOBAL_OFFSET_TABLE_"
- ; def_syment = ({ elf64_st_name = (Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0))) (* ignored *)
- ; elf64_st_info = (Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0))) (* FIXME *)
- ; elf64_st_other = (Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0))) (* FIXME *)
- ; elf64_st_shndx = (Uint32.of_string (Nat_big_num.to_string (Nat_big_num.of_int 1)))
- ; elf64_st_value = (Uint64.of_string (Nat_big_num.to_string (Nat_big_num.of_int 0))) (* ignored *)
- ; elf64_st_size = (Uint64.of_string (Nat_big_num.to_string ( Nat_big_num.mul got_nentries got_entrysize))) (* FIXME: start later, smaller size? zero size? *)
- })
- ; def_sym_scn =(Nat_big_num.of_int 1)
- ; def_sym_idx =(Nat_big_num.of_int 1)
- ; def_linkable_idx =(Nat_big_num.of_int 0)
- }))
- ; (Some(".rela.iplt", (Nat_big_num.of_int 0, (* size of an Elf64_Rela *) Nat_big_num.mul(Nat_big_num.of_int 24) (Nat_big_num.of_int n_iplt_entries))), FileFeature(ElfSection(Nat_big_num.of_int 3,
- { elf64_section_name =(Nat_big_num.of_int 0) (* ignored *)
- ; elf64_section_type = sht_rela
- ; elf64_section_flags = (Nat_big_num.bitwise_or shf_alloc shf_info_link)
- ; elf64_section_addr =(Nat_big_num.of_int 0) (* ignored -- covered by element *)
- ; elf64_section_offset =(Nat_big_num.of_int 0) (* ignored -- will be replaced when file offsets are assigned *)
- ; elf64_section_size = ( (* size of an Elf64_Rela *)Nat_big_num.mul(Nat_big_num.of_int 24) (Nat_big_num.of_int n_iplt_entries)) (* ignored? NO, we use it in linker_script to avoid plumbing through the element record *)
- ; elf64_section_link =(Nat_big_num.of_int 0)
- ; elf64_section_info =(Nat_big_num.of_int (* FIXME: want this to be the PLT section shndx *)0)
- ; elf64_section_align =(Nat_big_num.of_int 8)
- ; elf64_section_entsize =(Nat_big_num.of_int 24)
- ; elf64_section_body = Byte_sequence.empty (* ignored *)
- ; elf64_section_name_as_string = ".rela.iplt"
- }
- )))
- ])
- in
- { elements = (Pmap.add ".got" {
- startpos = None
- ; length1 = (Some ( Nat_big_num.mul got_nentries got_entrysize))
- ; contents = ([])
- } (Pmap.add ".plt" {
- startpos = None
- ; length1 = (let len = (Nat_big_num.mul(Nat_big_num.of_int 16) total_n_plt_entries) in
- (*let _ = errln ("PLT length in element: " ^ (show len) ^ " bytes")
- in *) Some ( Nat_big_num.mul(Nat_big_num.of_int 16) total_n_plt_entries))
- ; contents = ([])
- } (Pmap.add ".rela.iplt" {
- startpos = None
- ; length1 = (Some ( (* size of an Elf64_Rela *) Nat_big_num.mul(Nat_big_num.of_int 24) (Nat_big_num.of_int n_iplt_entries)))
- ; contents = ([])
- } (Pmap.empty compare)
- )))
- ; by_tag = (by_tag_from_by_range
- (instance_Basic_classes_SetType_Maybe_maybe_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_var_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_Num_natural_dict
- instance_Basic_classes_SetType_Num_natural_dict))) instance_Basic_classes_SetType_var_dict new_by_range)
- ; by_range = new_by_range
- })
-
-(*val amd64_concretise_support : annotated_memory_image any_abi_feature -> annotated_memory_image any_abi_feature*)
-let amd64_concretise_support orig_img:(any_abi_feature)annotated_memory_image=
-(
- (*let _ = errln "Concretising amd64 ABI support structures"
- in*)
- (* Fill in the GOT contents. *)(match amd64_find_got_label_and_element orig_img with
- None -> orig_img (* no GOT, but that's okay *)
- | Some (got_l, got_el) ->
- let got_base_addr = ((match got_el.startpos with
- Some a -> a
- | None -> failwith "GOT has no address assigned"
- ))
- in
- let got_entry_bytes_for = (fun img2 -> fun symname -> fun maybe_def -> fun plt_l -> fun maybe_plt_el -> (match maybe_def with
- None -> replicate0(Nat_big_num.of_int 8) (Char.chr (Nat_big_num.to_int (Nat_big_num.of_int 0)))
- | Some sd ->
- (* What should the GOT slot be initialized to point to?
- * If there's a PLT entry, we should point to that + 6,
- * i.e. the second instruction.
- *
- * If there's not, then it might be a thread-local. *)
- (match Lem_list.find_index (fun (plt_symname, _, _) -> symname = plt_symname) plt_l with
- Some plt_slot_idx ->
- (match maybe_plt_el with
- None -> failwith "GOT slot with PLT entry but no PLT element"
- | Some plt_el ->
- (match plt_el.startpos with
- Some addr -> natural_to_le_byte_list_padded_to(Nat_big_num.of_int 8) ( Nat_big_num.add (Nat_big_num.add addr ( Nat_big_num.mul(Nat_big_num.of_int plt_slot_idx)(Nat_big_num.of_int 16)))(Nat_big_num.of_int 6))
- | None -> failwith ("no PLT!")
- )
- )
- | None ->
- (* Just look for a definition. *)
- (match Memory_image_orderings.find_defs_matching
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict sd img2 with
- [] -> failwith ("no matching definitions for GOT entry named " ^ symname)
- | [(Some(def_el_name, (def_start, def_len)), d)] ->
- (match element_and_offset_to_address (def_el_name, def_start) img2 with
- None -> failwith ("no address for definition offset in element " ^ def_el_name)
- | Some x ->
- (* If sd is a TLS symbol, we want its offset from the *end* of the
- * TLS segment. *)
- (* FIXME: factor out this logic so that it lives in the TLS ABI spec. *)
- if Nat_big_num.equal (get_elf64_symbol_type sd.def_syment) stt_tls then
- (* FIXME: the right way to do this is to mark the segments in the image
- * *first*. They can't have ranges, because they span many elements,
- * but they can have vaddr ranges as arguments. *)
- let offs = (i2n_signed( 64) (Nat_big_num.sub(Nat_big_num.of_int 0)(Nat_big_num.of_int 8)))
- in
- (*let _ = errln ("GOT slot for TLS symbol `" ^ symname ^
- "' created containing offset 0x" ^ (hex_string_of_natural offs))
- in*)
- natural_to_le_byte_list offs
- else (*let _ = errln ("GOT slot for symbol `" ^ symname ^
- "' created pointing to address 0x" ^ (hex_string_of_natural x) ^
- " (offset 0x" ^ (hex_string_of_natural def_start) ^ " in element " ^ def_el_name ^ ")")
- in*)
- natural_to_le_byte_list_padded_to(Nat_big_num.of_int 8) x
- )
- | _ -> failwith ("multiple matching definitions for GOT entry named " ^ symname)
- )
- )
- ))
- in
- let concretise_got = (fun img2 -> fun plt_l -> fun maybe_plt_el ->
- let l = got_l
- (* Just(got_el_name, (got_start_off, got_len)))] -> *)
- in
- (*let _ = errln ("Concretising a GOT of " ^ (show (length l)) ^ " entries.")
- in*)
- let got_entry_contents = (Lem_list.map (fun (symname, maybe_def) ->
- Lem_list.map (fun b -> Some b) (got_entry_bytes_for img2 symname maybe_def plt_l maybe_plt_el)) l)
- in
- (* We replace the GOT element's contents with the concrete addresses
- * of the symbols it should contain. We leave the metadata label in there,
- * for the relocation logic to find. If we change the order of entries,
- * change it there too. *)
- let got_content = (List.concat got_entry_contents)
- in
- let new_got_el =
- ({ contents = got_content
- ; startpos = (got_el.startpos)
- ; length1 = (got_el.length1)
- })
- in
- let new_got_tag = (AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0(l))))
- in
- let got_range = (Some(".got", (Nat_big_num.of_int 0, Nat_big_num.mul(Nat_big_num.of_int 8) (length l))))
- in
- let new_by_tag =
- (Pset.(union)( Pset.diff(img2.by_tag : (( any_abi_feature range_tag) * ( element_range option)) Pset.set)(Pset.from_list (pairCompare compare (maybeCompare (pairCompare compare (pairCompare Nat_big_num.compare Nat_big_num.compare)))) [(AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0(l))), got_range)]))(Pset.from_list (pairCompare compare (maybeCompare (pairCompare compare (pairCompare Nat_big_num.compare Nat_big_num.compare)))) [(new_got_tag, got_range)]))
- in
- let new_elements_map = (Pmap.add ".got" new_got_el (
- Pmap.remove ".got" img2.elements
- ))
- in
- { elements = new_elements_map
- ; by_tag = new_by_tag
- ; by_range = (by_range_from_by_tag
- instance_Basic_classes_SetType_var_dict (instance_Basic_classes_SetType_Maybe_maybe_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_var_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_Num_natural_dict
- instance_Basic_classes_SetType_Num_natural_dict))) new_by_tag)
- })
- in
- (match amd64_find_plt_label_and_element orig_img with
- None -> concretise_got orig_img [] None (* no PLT, but possibly a GOT *)
- | Some (plt_l, plt_el) ->
- let plt_base_addr = ((match plt_el.startpos with
- Some a -> a
- | None -> failwith "PLT has no address assigned"
- ))
- in
- let concretise_plt = (fun img2 ->
- let l = plt_l
- in
- (* We replace the PLT element's contents with the concrete entries
- * for each of the symbols in the table. We leave the metadata label in there,
- * for the relocation logic to find. If we change the order of entries,
- * change it there too. *)
- let all_content = (List.concat (Lem_list.map (fun (_, _, plt_content_fn) ->
- let (_, content) = (plt_content_fn got_base_addr plt_base_addr) in
- content
- ) l))
- in
- (*let _ = errln ("Got " ^ (show (length all_content)) ^ " bytes of PLT content")
- in
- let _ = errln ("Generated PLT reserved " ^ (show (match plt_el.length with
- Just n -> n
- | Nothing -> failwith "PLT has no length"
- end)) ^ " bytes of PLT content")
- in*)
- let new_plt_el =
- ({ contents = (Lem_list.map (fun b -> Some b) all_content)
- ; startpos = (plt_el.startpos)
- ; length1 = (Some(length all_content))
- })
- in
- let new_elements_map = (Pmap.add ".plt" new_plt_el (
- Pmap.remove ".plt" img2.elements
- ))
- in
- { elements = new_elements_map
- ; by_tag = (img2.by_tag)
- ; by_range = (img2.by_range)
- })
- in
- let concretise_rela_plt = (fun img2 ->
- let maybe_rela_plt_el = (Pmap.lookup ".rela.plt" img2.elements)
- in
- let maybe_new_rela_plt_el = ((match maybe_rela_plt_el with
- None -> (* got no .rela.plt? okay... *)
- (*let _ = errln "No .rela.plt found"
- in*)
- None
- | Some rela_plt_el ->
- let got_entry_iplt_widget_for = (fun symname -> fun maybe_def -> (match maybe_def with
- None -> None
- | Some sd ->
- if not (Nat_big_num.equal (get_elf64_symbol_type sd.def_syment) stt_gnu_ifunc) then None
- else Some(fun index_in_got ->
- (* This is a 24-byte Elf64_Rela. *)
- let (r_offset : Nat_big_num.num) (* GOT *slot* address! *) =
- ((match got_el.startpos with
- None -> failwith "internal error: GOT has no assigned address"
- | Some addr -> Nat_big_num.add addr ( Nat_big_num.mul(Nat_big_num.of_int 8) index_in_got)
- ))
- in
- let (r_info : Nat_big_num.num) = r_x86_64_irelative in
- ( List.rev_append (List.rev (List.rev_append (List.rev (natural_to_le_byte_list_padded_to(Nat_big_num.of_int 8) r_offset)) (natural_to_le_byte_list_padded_to(Nat_big_num.of_int 8) r_info)))
- (* r_addend -- address of the ifunc definition.
- * NOTE that this is NOT the same as the GOT entry bytes.
- * It's the actual address of the ifunc, whereas
- * the GOT entry is initialized to point back into the PLT entry. *)(match Memory_image_orderings.find_defs_matching
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict sd img2 with
- [] -> failwith ("impossible: IPLT entry widget found matching ifunc definition for " ^ symname)
- | [(Some(def_el_name, (def_start, def_len)), d)] ->
- (match element_and_offset_to_address (def_el_name, def_start) img2 with
- None -> failwith ("no address for ifunc definition offset in element " ^ def_el_name)
- | Some x ->
- (* If sd is a TLS symbol, we want its offset from the *end* of the
- * TLS segment. *)
- (* FIXME: factor out this logic so that it lives in the TLS ABI spec. *)
- if not (Nat_big_num.equal (get_elf64_symbol_type sd.def_syment) stt_gnu_ifunc)
- then failwith "impossible: found ifunc definition that is not an ifunc"
- else
- natural_to_le_byte_list_padded_to(Nat_big_num.of_int 8) x
- )
- | _ -> failwith "impossible: more than one ifunc definition"
- )
- ))
- (* end Just sd *)
- ))
- in
- let rela_iplt_widgets = (Lem_list.map (fun (symname, maybe_def) -> got_entry_iplt_widget_for symname maybe_def) got_l)
- in
- let new_content_bytelists =
- (mapi (fun i -> fun rela_widget ->
- (match rela_widget with
- Some f -> f (Nat_big_num.of_int i)
- | None -> []
- )
- ) rela_iplt_widgets)
- in
- let new_contents = (Lem_list.map (fun b -> Some b) (List.concat new_content_bytelists))
- in
- (*let _ = errln ("Concretised .rela.plt; first 24 bytes: " ^ (show (take 24 new_contents)))
- in*)
- Some(
- { contents = new_contents
- ; startpos = (rela_plt_el.startpos)
- ; length1 = (rela_plt_el.length1)
- }
- )
- ))
- in
- let new_elements_map = ((match maybe_new_rela_plt_el with
- Some new_rela_plt_el -> Pmap.add ".rela.plt" new_rela_plt_el (
- Pmap.remove ".rela.plt" img2.elements
- )
- | None -> img2.elements
- ))
- in
- { elements = new_elements_map
- ; by_tag = (img2.by_tag)
- ; by_range = (img2.by_range)
- })
- in
- concretise_rela_plt (concretise_plt (concretise_got orig_img plt_l (Some plt_el)))
-) ))
-
-(*val amd64_got_slot_idx : annotated_memory_image any_abi_feature -> symbol_reference_and_reloc_site -> natural*)
-let amd64_got_slot_idx img2 rr:Nat_big_num.num=
-(
- (*let _ = errln ("Looking up GOT slot for symbol " ^ rr.ref.ref_symname) in*)(match Pmap.lookup ".got" img2.elements with
- None -> (* got no GOT? okay... *) failwith "got no GOT"
- | Some got_el ->
- (* Find the GOT tag. *)
- let tags_and_ranges = (Multimap.lookupBy0
- (instance_Basic_classes_Ord_Memory_image_range_tag_dict
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict) (instance_Basic_classes_Ord_Maybe_maybe_dict
- (instance_Basic_classes_Ord_tup2_dict
- Lem_string_extra.instance_Basic_classes_Ord_string_dict
- (instance_Basic_classes_Ord_tup2_dict
- instance_Basic_classes_Ord_Num_natural_dict
- instance_Basic_classes_Ord_Num_natural_dict))) instance_Basic_classes_SetType_var_dict (instance_Basic_classes_SetType_Maybe_maybe_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_var_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_Num_natural_dict
- instance_Basic_classes_SetType_Num_natural_dict))) (Memory_image_orderings.tagEquiv
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict) (AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0([])))) img2.by_tag)
- in
- (match tags_and_ranges with
- [] -> failwith "error: GOT element but no ABI feature GOT tag"
- | [(AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0(l))), Some(got_el_name, (got_start_off, got_len)))] ->
- (* Find the slot corresponding to rr, if we have one. *)
- let got_addr = ((match got_el.startpos with Some addr -> addr | None -> failwith "GOT has no addr at reloc time" ))
- in
- (match rr.maybe_def_bound_to with
- Some (_, Some(d)) ->
- (match Lem_list.find_index (fun (symname, maybe_def) -> (Lem.option_equal (=) (Some(d)) maybe_def)) l with
- Some idx1 -> Nat_big_num.of_int idx1
- | None -> failwith ("no GOT slot for reloc against `" ^ (rr.ref.ref_symname ^ "'"))
- )
- | Some(_, None) -> (* HACK: look for the weak symname. Really want more (ref-based) labelling. *)
- (match Lem_list.find_index (fun (symname, _) -> symname = rr.ref.ref_symname) l with
- Some idx1 -> Nat_big_num.of_int idx1
- | None -> failwith ("no GOT slot for reloc against undefined symbol `" ^ (rr.ref.ref_symname ^ "'"))
- )
- | _ -> failwith "GOT: unbound def"
- )
- | _ -> failwith "got bad GOT"
- )
- ))
-
-(*val amd64_got_slot_addr : annotated_memory_image any_abi_feature -> symbol_reference_and_reloc_site -> natural*)
-let amd64_got_slot_addr img2 rr:Nat_big_num.num=
- ((match Pmap.lookup ".got" img2.elements with
- None -> (* got no GOT? okay... *) failwith "got no GOT"
- | Some got_el ->
- (* Find the GOT tag. *)
- let tags_and_ranges = (Multimap.lookupBy0
- (instance_Basic_classes_Ord_Memory_image_range_tag_dict
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict) (instance_Basic_classes_Ord_Maybe_maybe_dict
- (instance_Basic_classes_Ord_tup2_dict
- Lem_string_extra.instance_Basic_classes_Ord_string_dict
- (instance_Basic_classes_Ord_tup2_dict
- instance_Basic_classes_Ord_Num_natural_dict
- instance_Basic_classes_Ord_Num_natural_dict))) instance_Basic_classes_SetType_var_dict (instance_Basic_classes_SetType_Maybe_maybe_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_var_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_Num_natural_dict
- instance_Basic_classes_SetType_Num_natural_dict))) (Memory_image_orderings.tagEquiv
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict) (AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0([])))) img2.by_tag)
- in
- (match tags_and_ranges with
- [] -> failwith "error: GOT element but no ABI feature GOT tag"
- | [(AbiFeature(Amd64AbiFeature(Abi_amd64.GOT0(l))), Some(got_el_name, (got_start_off, got_len)))] ->
- (* Find the slot corresponding to rr, if we have one. *)
- let got_addr = ((match got_el.startpos with Some addr -> addr | None -> failwith "GOT has no addr at reloc time" ))
- in Nat_big_num.add (Nat_big_num.mul(Nat_big_num.of_int 8) (amd64_got_slot_idx img2 rr)) got_addr
- | _ -> failwith "got bad GOT"
- )
- ))
-
-(*val amd64_plt_slot_addr : annotated_memory_image any_abi_feature -> symbol_reference_and_reloc_site -> natural -> natural*)
-let amd64_plt_slot_addr img2 rr raw_addr:Nat_big_num.num=
- ((match Pmap.lookup ".plt" img2.elements with
- None ->
- (* got no PLT? okay... under static linking this can happen.
- We use the actual symbol address of the *)
- (*let _ = errln "Warning: no PLT, so attempting to use actual symbol address as PLT slot address"
- in*)
- (* if raw_addr = 0 then failwith "bailing rather than resolving PLT slot to null address (perhaps conservatively)" else *)
- raw_addr
- | Some plt_el ->
- (* Find the PLT tag. *)
- let tags_and_ranges = (Multimap.lookupBy0
- (instance_Basic_classes_Ord_Memory_image_range_tag_dict
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict) (instance_Basic_classes_Ord_Maybe_maybe_dict
- (instance_Basic_classes_Ord_tup2_dict
- Lem_string_extra.instance_Basic_classes_Ord_string_dict
- (instance_Basic_classes_Ord_tup2_dict
- instance_Basic_classes_Ord_Num_natural_dict
- instance_Basic_classes_Ord_Num_natural_dict))) instance_Basic_classes_SetType_var_dict (instance_Basic_classes_SetType_Maybe_maybe_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_var_dict
- (instance_Basic_classes_SetType_tup2_dict
- instance_Basic_classes_SetType_Num_natural_dict
- instance_Basic_classes_SetType_Num_natural_dict))) (Memory_image_orderings.tagEquiv
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict) (AbiFeature(Amd64AbiFeature(Abi_amd64.PLT0([])))) img2.by_tag)
- in
- (match tags_and_ranges with
- [] -> failwith "error: PLT element but no ABI feature PLT tag"
- | [(AbiFeature(Amd64AbiFeature(Abi_amd64.PLT0(l))), Some(plt_el_name, (plt_start_off, plt_len)))] ->
- let plt_addr = ((match plt_el.startpos with Some addr -> addr | None -> failwith "PLT has no addr at reloc time" ))
- in
- (* Find the slot corresponding to rr, if we have one. *)
- (match rr.maybe_def_bound_to with
- Some (_, Some(d)) ->
- (match Lem_list.mapMaybe (fun (symname, maybe_def, fn) -> if (Lem.option_equal (=) (Some(d)) maybe_def) then Some fn else None) l with
- [fn] ->
- let got_addr =
- ((match Pmap.lookup ".got" img2.elements with
- None -> (* got no GOT? okay... *) failwith "got no GOT (applying PLT calculation)"
- | Some got_el -> (match got_el.startpos with
- Some addr -> addr
- | None -> failwith "concrete GOT has no addr"
- )
- ))
- in
- let (addr, content) = (fn got_addr plt_addr)
- in
- (*let _ = errln ("Calculated PLT slot for `" ^ d.def_symname ^ "', from PLT addr " ^ (hex_string_of_natural plt_addr)
- ^ " and GOT addr " ^ (hex_string_of_natural got_addr) ^ ", as " ^ (hex_string_of_natural addr))
- in*)
- addr
- | [] -> (* failwith ("internal error: no PLT entry for reloc against `" ^ rr.ref.ref_symname ^ "'") *)
- (* If we got no PLT slot, we assume it's because the PLT entry was optimised out.
- * So we just return the address of the symbol itself. *)
- (*let _ = errln ("No PLT entry for reloc against `" ^ rr.ref.ref_symname ^
- "', which we assume was optimised to avoid the GOT")
- in*)
- (match Memory_image_orderings.find_defs_matching
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict d img2 with
- [] ->Nat_big_num.of_int 0 (* HMM -- should be an error? *)
- | [(Some(el_name, (start_off, len)), matching_d)] ->
- (match element_and_offset_to_address (el_name, start_off) img2 with
- Some a -> a
- | None -> failwith ("internal error: could not get address for PLT-short-circuited symbol `" ^ (rr.ref.ref_symname ^ "'"))
- )
- | _ -> failwith ("output image has multiple and/or no-location definitions to which via-PLT ref to `" ^ (rr.ref.ref_symname ^ "' could resolve"))
- )
- | _ -> failwith ("internal error: multiple PLT entries for reloc against `" ^ (rr.ref.ref_symname ^ "'"))
- )
- | Some(_, None) ->Nat_big_num.of_int (* weak, so 0 *)0
- | _ -> failwith "PLT: unbound def"
- )
- | _ -> failwith "got bad PLT"
- )
- ))
-
-(** [amd64_reloc r] yields a function that applies relocations of type [r]. *)
-(*val amd64_reloc : reloc_fn any_abi_feature*)
-let amd64_reloc r:bool*((any_abi_feature)annotated_memory_image ->Nat_big_num.num ->symbol_reference_and_reloc_site ->Nat_big_num.num*(Nat_big_num.num ->Nat_big_num.num ->Nat_big_num.num ->Nat_big_num.num))=
- ((match (string_of_amd64_relocation_type r) with
- | "R_X86_64_NONE" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 0, (fun s -> fun a -> fun e -> e))))))
- | "R_X86_64_64" -> (true, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8, (fun s -> fun a -> fun e -> i2n ( Nat_big_num.add(n2i s) a)))))))
- | "R_X86_64_PC32" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> i2n_signed( 32) ( Nat_big_num.sub( Nat_big_num.add(n2i s) a) (n2i site_addr))))))))
- | "R_X86_64_GOT32" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> i2n_signed( 32) ( Nat_big_num.add(n2i (amd64_got_slot_idx img2 rr)) a)))))))
- | "R_X86_64_PLT32" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> i2n_signed( 32) ( Nat_big_num.sub (Nat_big_num.add(n2i (amd64_plt_slot_addr img2 rr s)) a) (n2i site_addr))) )))) )
- | "R_X86_64_COPY" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (size_of_copy_reloc img2 rr, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_GLOB_DAT" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (size_of_def rr, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_JUMP_SLOT" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_RELATIVE" -> (true, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_GOTPCREL" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> i2n_signed( 32) ( Nat_big_num.sub (Nat_big_num.add(n2i (amd64_got_slot_addr img2 rr)) a) (n2i site_addr))) )))) )
- | "R_X86_64_32" -> (true, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> i2n ( Nat_big_num.add(n2i s) a)))))))
- | "R_X86_64_32S" -> (true, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> i2n_signed( 32) ( Nat_big_num.add(n2i s) a)))))))
- | "R_X86_64_16" -> (true, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 2, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_PC16" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 2, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_8" -> (true, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 1, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_PC8" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 1, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_DTPMOD64" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_DTPOFF64" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_TPOFF64" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8 (* CHECK *), (fun s -> fun a -> fun e -> i2n_signed( 64) (Nat_big_num.sub(Nat_big_num.of_int 0)(Nat_big_num.of_int 8))) (* FIXME *))))))
- | "R_X86_64_TLSGD" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_TLSLD" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_DTPOFF32" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_GOTTPOFF" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> i2n_signed( 32) ( Nat_big_num.sub (Nat_big_num.add(n2i (amd64_got_slot_addr img2 rr)) a) (n2i site_addr))))))))
- | "R_X86_64_TPOFF32" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_PC64" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_GOTOFF64" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_GOTPC32" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_SIZE32" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_SIZE64" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8, (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_GOTPC32_TLSDESC" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_TLSDESC_CALL" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 4 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_TLSDESC" -> (false, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | "R_X86_64_IRELATIVE" -> (true, (fun img2 -> (fun site_addr -> (fun rr -> (Nat_big_num.of_int 8 (* CHECK *), (fun s -> fun a -> fun e -> e) (* FIXME *))))))
- | _ -> failwith "unrecognised relocation"
-))
-
-(*val sysv_amd64_std_abi : abi any_abi_feature*)
-let sysv_amd64_std_abi:(any_abi_feature)abi=
- ({ is_valid_elf_header = header_is_amd64
- ; make_elf_header = (make_elf64_header elf_data_2lsb elf_osabi_none(Nat_big_num.of_int 0) elf_ma_x86_64)
- ; reloc = amd64_reloc
- ; section_is_special = section_is_special0
- ; section_is_large = (fun s -> (fun f -> flag_is_set shf_x86_64_large s.elf64_section_flags))
- ; maxpagesize =(Nat_big_num.of_int 65536)
- ; minpagesize =(Nat_big_num.of_int 4096)
- ; commonpagesize =(Nat_big_num.of_int 4096)
- (* XXX: DPM, changed from explicit reference to null_abi field due to problems in HOL4. *)
- ; symbol_is_generated_by_linker = (fun symname -> symname = "_GLOBAL_OFFSET_TABLE_")
- ; make_phdrs = make_default_phdrs
- ; max_phnum =(Nat_big_num.of_int 2) (* incremented by extensions *)
- ; guess_entry_point =
- (find_start_symbol_address
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict)
- ; pad_data = pad_zeroes
- ; pad_code = pad_0x90
- ; generate_support = amd64_generate_support
- ; concretise_support = amd64_concretise_support
- ; get_reloc_symaddr = amd64_get_reloc_symaddr
- })
-
-(*val sysv_aarch64_le_std_abi : abi any_abi_feature*)
-let sysv_aarch64_le_std_abi:(any_abi_feature)abi=
- ({ is_valid_elf_header = header_is_aarch64_le
- ; make_elf_header = (make_elf64_header elf_data_2lsb elf_osabi_none(Nat_big_num.of_int 0) elf_ma_aarch64)
- ; reloc = aarch64_le_reloc
- ; section_is_special = section_is_special0
- ; section_is_large = (fun _ -> (fun _ -> false))
- ; maxpagesize = (Nat_big_num.mul (Nat_big_num.mul(Nat_big_num.of_int 2)(Nat_big_num.of_int 256))(Nat_big_num.of_int 4096)) (* 2MB; bit of a guess, based on gdb and prelink code *)
- ; minpagesize =(Nat_big_num.of_int 1024) (* bit of a guess again *)
- ; commonpagesize =(Nat_big_num.of_int 4096)
- ; symbol_is_generated_by_linker = (fun symname -> symname = "_GLOBAL_OFFSET_TABLE_")
- ; make_phdrs = make_default_phdrs
- ; max_phnum =(Nat_big_num.of_int 2) (* incremented by extensions *)
- ; guess_entry_point =
- (find_start_symbol_address
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict)
- ; pad_data = pad_zeroes
- ; pad_code = pad_zeroes
- ; generate_support = ( (* fun _ -> *)fun _ -> get_empty_memory_image ())
- ; concretise_support = (fun img2 -> img2)
- ; get_reloc_symaddr =
- (default_get_reloc_symaddr
- instance_Basic_classes_Ord_Abis_any_abi_feature_dict
- instance_Abi_classes_AbiFeatureTagEquiv_Abis_any_abi_feature_dict)
- })
-
-(*val all_abis : list (abi any_abi_feature)*)
-let all_abis:((any_abi_feature)abi)list= ([sysv_amd64_std_abi; sysv_aarch64_le_std_abi; null_abi])
-