Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file abi_utilities.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222(*Generated by Lem from abis/abi_utilities.lem.*)(** [abi_utilities], generic utilities shared between all ABIs.
*)openLem_mapopenLem_maybeopenLem_numopenLem_basic_classesopenLem_maybeopenLem_stringopenErroropenLem_assert_extraopenAbi_classesopenMissing_pervasivesopenElf_types_native_uintopenElf_symbol_tableopenElf_relocationopenMemory_imageopenMemory_image_orderingsopenError(** [integer_bit_width] records various bit widths for integral types, as used
* in relocation calculations. The names are taken directly from the processor
* supplements to keep the calculations as close as possible
* to the specification of relocations.
*)typeinteger_bit_width=I8(** Signed 8 bit *)|I12|U12(** Unsigned 12 bit *)|Low14|U15(** Unsigned 15 bit *)|I15|I16(** Signed 16 bit *)|Half16ds|I20(** Signed 20 bit *)|Low24|I27|Word30|I32(** Signed 32 bit *)|I48(** Signed 48 bit *)|I64(** Signed 64 bit *)|I64X2(** Signed 128 bit *)|U16(** Unsigned 16 bit *)|U24(** Unsigned 24 bit *)|U32(** Unsigned 32 bit *)|U48(** Unsigned 48 bit *)|U64(** Unsigned 64 bit *)(** [natural_of_integer_bit_width i] computes the bit width of integer bit width
* [i].
*)(*val natural_of_integer_bit_width : integer_bit_width -> natural*)letnatural_of_integer_bit_widthi:Nat_big_num.num=((matchiwith|I8->(Nat_big_num.of_int8)|I12->(Nat_big_num.of_int12)|U12->(Nat_big_num.of_int12)|Low14->(Nat_big_num.of_int14)|I15->(Nat_big_num.of_int15)|U15->(Nat_big_num.of_int15)|I16->(Nat_big_num.of_int16)|Half16ds->(Nat_big_num.of_int16)|U16->(Nat_big_num.of_int16)|I20->(Nat_big_num.of_int20)|Low24->(Nat_big_num.of_int24)|U24->(Nat_big_num.of_int24)|I27->(Nat_big_num.of_int27)|Word30->(Nat_big_num.of_int30)|I32->(Nat_big_num.of_int32)|U32->(Nat_big_num.of_int32)|I48->(Nat_big_num.of_int48)|U48->(Nat_big_num.of_int48)|I64->(Nat_big_num.of_int64)|U64->(Nat_big_num.of_int64)|I64X2->(Nat_big_num.of_int128)))(** [relocation_operator] records the operators used to calculate relocations by
* the various ABIs. Each ABI will only use a subset of these, and they should
* be interpreted on a per-ABI basis. As more ABIs are added, more operators
* will be needed, and therefore more constructors in this type will need to
* be added. These are unary operators, operating on a single integral type.
*)typerelocation_operator=TPRel|LTOff|DTPMod|DTPRel|Page|GDat|G|GLDM|GTPRel|GTLSDesc|Delta|LDM|TLSDesc|Indirect|Lo|Hi|Ha|Higher|HigherA|Highest|HighestA(** [relocation_operator2] is a binary relocation operator, as detailed above.
*)typerelocation_operator2=|GTLSIdx(** Generalising and abstracting over relocation calculations and their return
* types
*)type('k,'v)val_map=('k,'v)Pmap.map(*val lookupM : forall 'k 'v. MapKeyType 'k => 'k -> val_map 'k 'v -> error 'v*)letlookupMdict_Map_MapKeyType_kkeyval_map1:'verror=((matchPmap.lookupkeyval_map1with|None->fail"lookupM: key not found in val_map"|Somej->returnj))(** Some relocations may fail, for example:
* Page 58, Power ABI: relocation types whose Field column is marked with an
* asterisk are subject to failure is the value computed does not fit in the
* allocated bits. [can_fail] type passes this information back to the caller
* of the relocation application function.
*)type'acan_fail=CanFail(** [CanFail] signals a potential failing relocation calculation when width constraints are invalidated *)|CanFailOnTestof('a->bool)(** [CanFailOnTest p] signals a potentially failing relocation calculation when predicate [p] on the result of the calculation returns [false] *)|CannotFail(** [CannotFail] states the relocation calculation cannot fail and bit-width constraints should be ignored *)(** [relocation_operator_expression] is an AST of expressions describing a relocation
* calculation. An AST is used as it allows us to unify the treatment of relocation
* calculation: rather than passing in dozens of functions to the calculation function
* that perform the actual relocation, we can simply return a description (in the form
* of the AST below) of the calculation to be carried out and have it interpreted
* separately from the function that produces it. The type parameter 'a is the
* type of base integral type. This AST suffices for the relocation calculations we
* currently have implemented, but adding more ABIs may require that this type is
* expanded.
*)type'arelocation_operator_expression=Liftof'a(** Lift a base type into an AST *)|Applyof(relocation_operator*'arelocation_operator_expression)(** Apply a unary operator to an expression *)|Apply2of(relocation_operator2*'arelocation_operator_expression*'arelocation_operator_expression)(** Apply a binary operator to two expressions *)|Plusof('arelocation_operator_expression*'arelocation_operator_expression)(** Add two expressions. *)|Minusof('arelocation_operator_expression*'arelocation_operator_expression)(** Subtract two expressions. *)|RShiftof('arelocation_operator_expression*Nat_big_num.num)(** Right shift the result of an expression [m] places. *)type('addr,'res)relocation_frame=|Copy|NoCopyof(('addr,('resrelocation_operator_expression*integer_bit_width*'rescan_fail))Pmap.map)(*val size_of_def : symbol_reference_and_reloc_site -> natural*)letsize_of_defrr:Nat_big_num.num=(letrf=(rr.ref)inletsm=(rf.ref_syment)inMl_bindings.nat_big_num_of_uint64sm.elf64_st_size)(*val size_of_copy_reloc : forall 'abifeature. annotated_memory_image 'abifeature -> symbol_reference_and_reloc_site -> natural*)letsize_of_copy_relocimg2rr:Nat_big_num.num=((* it's the minimum of the two definition symbol sizes. FIXME: for now, just use the rr *)size_of_defrr)(*val reloc_site_address : forall 'abifeature. Ord 'abifeature, AbiFeatureTagEquiv 'abifeature =>
annotated_memory_image 'abifeature -> symbol_reference_and_reloc_site -> natural*)letreloc_site_addressdict_Basic_classes_Ord_abifeaturedict_Abi_classes_AbiFeatureTagEquiv_abifeatureimg2rr:Nat_big_num.num=((* find the element range that's tagged with this reloc site *)letfound_kvs=(Multimap.lookupBy0(instance_Basic_classes_Ord_Memory_image_range_tag_dictdict_Basic_classes_Ord_abifeature)(instance_Basic_classes_Ord_Maybe_maybe_dict(instance_Basic_classes_Ord_tup2_dictLem_string_extra.instance_Basic_classes_Ord_string_dict(instance_Basic_classes_Ord_tup2_dictinstance_Basic_classes_Ord_Num_natural_dictinstance_Basic_classes_Ord_Num_natural_dict)))instance_Basic_classes_SetType_var_dict(instance_Basic_classes_SetType_Maybe_maybe_dict(instance_Basic_classes_SetType_tup2_dictinstance_Basic_classes_SetType_var_dict(instance_Basic_classes_SetType_tup2_dictinstance_Basic_classes_SetType_Num_natural_dictinstance_Basic_classes_SetType_Num_natural_dict)))(=)(SymbolRef(rr))img2.by_tag)in(matchfound_kvswith[]->failwith"impossible: reloc site not marked in memory image"|[(_,maybe_range)]->(matchmaybe_rangewithNone->failwith"impossible: reloc site has no element range"|Some(el_name,el_range)->letelement_addr=((matchPmap.lookupel_nameimg2.elementswithNone->failwith"impossible: non-existent element"|Someel->(matchel.startposwithNone->failwith"error: resolving relocation site address before address has been assigned"|Someaddr->addr)))inletsite_offset=(* match rr.maybe_reloc with
Just reloc -> natural_of_elf64_addr reloc.ref_relent.elf64_ra_offset
| Nothing -> failwith "symbol reference with range but no reloc site"
end*)(let(start,_)=el_rangeinstart)inNat_big_num.addelement_addrsite_offset)|_->failwith"error: more than one address with identical relocation record"))(** Extracting useful information from relocs *)(*val parse_elf64_relocation_info : elf64_xword -> (natural (* type *) * natural (* symbol *))*)letparse_elf64_relocation_infow:Nat_big_num.num*Nat_big_num.num=(letmask=(Uint64_wrapper.of_bigint(natural_of_hex"0xffffffff"))inlettyp=(Ml_bindings.nat_big_num_of_uint64(Uint64_wrapper.logandwmask))inletsym1=(Ml_bindings.nat_big_num_of_uint64(Uint64_wrapper.shift_rightw32))in(typ,sym1))