Parameter Make.Domain
include Domains.Memory_domains.With_focusing.BASE_WITH_TYPES
include Domains.Memory_sig.Base
include Domains.Sig.BASE
include Domains.Sig.Minimal
include Domains.Sig.Minimal_No_Boolean
include Domains.Sig.With_Context
module Context : Domains.Sig.Contextval root_context : unit -> Context.tOpens a new context, corresponding to the initial scope.
val context_pretty : Stdlib.Format.formatter -> Context.t -> unitDumps what is known about the current context: useful for debugging.
Guards
Joining variables together.
include Domains.Sig.With_Nondet with module Context := Context
val typed_nondet2 :
Context.t ->
Context.t ->
'a Context.in_tuple ->
Context.t * 'a Context.out_tupleThis joins two basic blocks and returns a new basic block. The Context.in_tuple and Context.out_tuple corresponds to the phi operations in SSA.
val nondet_same_context :
Context.t ->
'a Context.in_tuple ->
'a Context.out_tupleAdditionally, one may compute a non-deterministic choice between two values in the same basic block
It can be seen as equivalent as calling typed_nondet2 by passing the same context twice, which would return the same context.
Fixpoint computation.
include Domains.Sig.With_Fixpoint_Computation with module Context := Context
Opening a new context can also be seen as opening a new scope: new variables can be introduced, but variables of the parent scope can still be seen.
val typed_fixpoint_step :
iteration:int ->
init:Context.t ->
arg:Context.t ->
body:Context.t ->
(bool * 'a Context.in_tuple) ->
bool * (close:bool -> 'a Context.out_tuple * Context.t)Fixpoint step is a combination of inclusion checking + widening.
Also takes a boolean and a tuple of values which is the result of the evaluation of the body (the end of the loop).
Internally, it stores the arguments of the mu.
val widened_fixpoint_step :
widening_id:Domains.Sig.Widening_Id.t ->
previous:Context.t ->
next:Context.t ->
(bool * 'a Context.in_tuple) ->
Context.t * bool * 'a Context.out_tuplewidened_fixpoint_step ~previous ~next (bool,in_tuple) where:
widening_idis a unique representation of the widening point;previousis the previous domain state;nextis the next domain state obtained after execution of the function body;boolis false if we know that the fixpoint is not reached yet, and true otherwise;in_tupleis the argument of the SSA phi function;
returns a triple (context,bool,out_tuple) where:
contextis the new domain state;boolis true if the fixpoint is reached, and false if not reached or we don't know;out_tupleis the result of the SSA phi function.
The boolean domain should be present everywhere, as we need it or guards.
include Domains.Sig.With_Boolean
with module Context := Context
and type boolean := boolean
module Boolean : Datatype_sig.S with type t = booleanval serialize_boolean :
Context.t ->
boolean ->
Context.t ->
boolean ->
'a Context.in_acc ->
(boolean, 'a) Context.resultEmpty denotes that the concretization has no value (or it is the concrete value representing the absence of value). Note that this does not necessarily imply that some error occured; for instance the offset of an uninitialized pointer can be represented with empty. Emptyness testing is a simple way of communicating between domains.
module Boolean_Forward :
Operator.BOOLEAN_FORWARD
with module Arity := Domains.Sig.Context_Arity_Forward(Context)
and type boolean := booleanval query_boolean : Context.t -> boolean -> Lattices.Quadrivalent.tinclude Domains.Sig.With_Types
with module Context := Context
and type binary := binary
val binary_unknown_typed :
size:Units.In_bits.t ->
Context.t ->
Types.TypedC.typ ->
binaryReturns an unknown value with a given type.
include Domains.Sig.With_Binary
with module Context := Context
and type binary := binary
and type boolean := boolean
module Binary : Datatype_sig.S with type t = binaryval binary_pretty :
size:Units.In_bits.t ->
Context.t ->
Stdlib.Format.formatter ->
binary ->
unitval serialize_binary :
widens:bool ->
size:Units.In_bits.t ->
Context.t ->
binary ->
Context.t ->
binary ->
'a Context.in_acc ->
(binary, 'a) Context.resultval binary_empty : size:Units.In_bits.t -> Context.t -> binaryval binary_unknown : size:Units.In_bits.t -> Context.t -> binaryinclude Domains.Sig.With_Binary_Forward
with module Context := Context
and type binary := binary
and type boolean := boolean
module Binary_Forward :
Operator.BINARY_FORWARD
with module Arity := Domains.Sig.Context_Arity_Forward(Context)
and type boolean := boolean
and type binary := binaryinclude Domains.Sig.With_Enum
with module Context := Context
and type enum := enum
and type boolean := boolean
module Enum : Datatype_sig.S with type t = enumval serialize_enum :
Context.t ->
enum ->
Context.t ->
enum ->
'a Context.in_acc ->
(enum, 'a) Context.resultinclude Domains.Sig.With_Enum_Forward
with module Context := Context
and type enum := enum
and type boolean := boolean
module Enum_Forward :
Operator.ENUM_FORWARD
with module Arity := Domains.Sig.Context_Arity_Forward(Context)
and type boolean := boolean
and type enum := enumval union :
Operator.Condition.t ->
Context.t ->
'a Context.in_tuple ->
'a Context.out_tupleSet operations. Note that we do not distinguish binary from binary sets. Note that union reuses the serialize machinery.
val satisfiable : Context.t -> boolean -> Smtbackend.Smtlib_sig.satCheck if an assertion is satisfiable (i.e. a trace exists that makes it true).
include Domains.Memory_sig.WITH_QUERIES
with module Context := Context
and type binary := binary
and type memory := memory
and type offset := offset
and type address := binary
and type enum := enum
module Query : sig ... endinclude Domains.Memory_sig.WITH_MEMORY_QUERIES
with module Context := Context
and type memory := memory
and type address := binary
and type offset := offset
val should_focus :
size:Units.In_bits.t ->
Context.t ->
memory ->
binary ->
(binary * offset) optionshould_focus ~size ctx mem addr asks the domain whether it is useful to "focus" (or "unfold", i.e. try to represent precisely the memory region pointed to by addr, as long as aliasing info ensures that it is sound) a loaded value. size should be the size of addr. If the answer is yes, then the returned value should contain three things about the region to focus: its base, the offset of the end and the offset of addr in it (in bits).
val may_alias :
ptr_size:Units.In_bits.t ->
Context.t ->
size1:offset ->
size2:offset ->
binary ->
binary ->
boolmay_alias ~ptr_size ~size1 ~size2 ctx addr1 addr2 should return whether the region starting at addr1 of size size1 bytes and the region starting at addr2 of size size2 bytes may have a non-empty intersection. This function is used by focusing abstractions to discard a focused region when writing in a possibly aliased address. ptr_size is the size in bits of both addr1 and addr2.
val is_weak : size:Units.In_bits.t -> Context.t -> binary -> boolis_weak ~size ctx addr asks the domain whether the address addr points to a weak type which indicates that the address will not alias with any other
include Domains.Memory_sig.WITH_BLOCK
with module Context := Context
and type block := block
and type offset := offset
and type boolean := boolean
and type value := binary
val serialize_block :
widens:bool ->
Context.t ->
block ->
Context.t ->
block ->
'a Context.in_acc ->
(block, 'a) Context.resultinclude Domains.Memory_sig.WITH_BLOCK_FORWARD
with module Context := Context
and type boolean := boolean
and type value := binary
and type block := block
and type offset := offset
module Block_Forward :
Operator.BLOCK_FORWARD
with module Arity := Domains.Sig.Context_Arity_Forward(Context)
and type boolean := boolean
and type value := binary
and type block := block
and type offset := offsetinclude Domains.Memory_sig.WITH_MEMORY
with module Context := Context
and type memory := memory
and type address := binary
and type boolean := boolean
and type block := block
and type offset := offset
and type value := binary
val serialize_memory :
widens:bool ->
Context.t ->
memory ->
Context.t ->
memory ->
'a Context.in_acc ->
(memory, 'a) Context.resultinclude Domains.Memory_sig.WITH_MEMORY_FORWARD
with module Context := Context
and type memory := memory
and type address := binary
and type boolean := boolean
and type block := block
and type offset := offset
and type value := binary
module Memory_Forward :
Operator.MEMORY_FORWARD
with module Arity := Domains.Sig.Context_Arity_Forward(Context)
and type boolean := boolean
and type address := binary
and type memory := memory
and type block := block
and type value := binaryval reachable : Context.t -> memory -> Smtbackend.Smtlib_sig.satCheck if the memory is reachable. sat means reachable.
val global_symbol : Context.t -> string -> Units.In_bits.t * binaryRetrieves the value of a global symbol
val add_global_symbol :
size:Units.In_bits.t ->
Context.t ->
string ->
binary ->
unitUpdates the value of a global symbol
val check_type :
size:Units.In_bits.t ->
Context.t ->
Types.TypedC.typ ->
binary ->
binary Types.Type_check_tree.tType check a binary value
val type_of :
size:Units.In_bits.t ->
Context.t ->
binary ->
Types.TypedC.typ optionRetrieves the type of value (this only works if it is a pointer and should only be used when looking at function pointers)
val analyze_summary :
Context.t ->
Domains.Memory_domains.With_focusing.TypedC.typ ->
(Units.In_bits.t * binary) list ->
memory ->
bool * (Units.In_bits.t * binary) option * memoryval serialize_memory_and_cache :
'a. widens:bool ->
Context.t ->
memory ->
Context.t ->
memory ->
(binary * binary) list ->
'a Context.in_acc ->
(memory, 'a) Context.result