Base.MainFunctor
module Priv : BasePriv.S
module RVEval : BaseDomain.ExpEvaluator with type t = BaseComponents(Priv.D).t
include module type of struct include Analyses.DefaultSpec end
Relatively safe default implementations of some boring Spec functions.
module P = Analyses.UnitP
val asm : ('a, 'b, 'c, 'd) Analyses.ctx -> 'e
val skip : ('a, 'b, 'c, 'd) Analyses.ctx -> 'e
val paths_as_set : ('a, 'b, 'c, 'd) Analyses.ctx -> 'e list
module A = Analyses.UnitA
module Dom : sig ... end
type t = Dom.t
module D = Dom
module V : sig ... end
module G : sig ... end
type extra = (GoblintCil.varinfo * Offs.t * bool) list
type store = D.t
type value = VD.t
type address = AD.t
val startstate : 'a -> store
val exitstate : 'a -> store
module VarH : sig ... end
module VarMap : sig ... end
val add_to_array_map :
GoblintCil.fundec ->
(GoblintCil.varinfo * VD.t) list ->
unit
val attributes_varinfo :
VarMap.key ->
GoblintCil.fundec ->
(GoblintCil.attributes * GoblintCil.attribute list) option
val project_val :
ValueDomain.VDQ.t ->
(GoblintCil.attributes * GoblintCil.attributes) option ->
PrecisionUtil.int_precision option ->
VD.t ->
bool ->
VD.t
val project :
ValueDomain.VDQ.t ->
PrecisionUtil.int_precision option ->
CPA.t ->
GoblintCil.fundec ->
CPA.t
val heap_var : bool -> ('a, 'b, 'c, 'd) Analyses.ctx -> Basetype.Variables.t
val evalbinop_base :
ctx:('a, 'b, 'c, 'd) Analyses.ctx ->
GoblintCil.binop ->
GoblintCil.typ ->
value ->
GoblintCil.typ ->
value ->
GoblintCil.typ ->
value
val add_offset_varinfo : Addr.Offs.t -> Addr.t -> Addr.t
val sync' :
[ `Init
| `Join
| `JoinCall of CilType.Fundec.t
| `Normal
| `Return
| `Thread ] ->
(BaseDomain.BaseComponents(Priv.D).t,
[> `Bot | `Lifted1 of Priv.G.t ],
'a,
[> `Left of Priv.V.t ])
Analyses.ctx ->
D.t
val sync :
(BaseDomain.BaseComponents(Priv.D).t,
[> `Bot | `Lifted1 of Priv.G.t ],
'a,
[> `Left of Priv.V.t ])
Analyses.ctx ->
[< `Init
| `Join
| `JoinCall of CilType.Fundec.t
| `Normal
| `Return
| `Thread ] ->
D.t
val publish_all :
(BaseDomain.BaseComponents(Priv.D).t,
[> `Bot | `Lifted1 of Priv.G.t ],
'a,
[> `Left of Priv.V.t ])
Analyses.ctx ->
[ `Init
| `Join
| `JoinCall of CilType.Fundec.t
| `Normal
| `Return
| `Thread ] ->
unit
val get_var :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.varinfo ->
value
val get :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
?top:VD.t ->
?full:bool ->
store ->
address ->
GoblintCil.exp option ->
value
get st addr
returns the value corresponding to addr
in st
* adding proper dependencies. * For the exp argument it is always ok to put None. This means not using precise information about * which part of an array is involved.
val reachable_from_value :
Queries.ask ->
value ->
GoblintCil.typ ->
string ->
AD.t
val reachable_top_pointers_types :
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
AD.t ->
Queries.TS.t
val eval_rv_ask_evalint :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
VD.t
Evaluate expression using EvalInt query. Base itself also answers EvalInt, so recursion goes indirectly through queries. This allows every subexpression to also meet more precise value from other analyses. Non-integer expression just delegate to next eval_rv function.
val eval_rv_no_ask_evalint :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
value
Evaluate expression without EvalInt query on outermost expression. This is used by base responding to EvalInt to immediately directly avoid EvalInt query cycle, which would return top. Recursive eval_rv
calls on subexpressions still go through eval_rv_ask_evalint
.
val eval_rv_back_up :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
value
val eval_rv_base :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
value
Evaluate expression structurally by base. This handles constants directly and variables using CPA. Subexpressions delegate to eval_rv
, which may use queries on them.
val eval_rv_base_lval :
eval_lv:
(ctx:
('a,
[> `Bot | `Lifted1 of Priv.G.t ] as 'b,
'c,
[> `Left of Priv.V.t ] as 'd)
Analyses.ctx ->
store ->
GoblintCil.lval ->
AD.t) ->
ctx:('a, 'b, 'c, 'd) Analyses.ctx ->
store ->
GoblintCil.exp ->
GoblintCil.lval ->
value
val evalbinop :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.binop ->
e1:GoblintCil.exp ->
?t1:GoblintCil.typ ->
e2:GoblintCil.exp ->
?t2:GoblintCil.typ ->
GoblintCil.typ ->
value
val evalbinop_mustbeequal :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.binop ->
e1:GoblintCil.exp ->
?t1:GoblintCil.typ ->
e2:GoblintCil.exp ->
?t2:GoblintCil.typ ->
GoblintCil.typ ->
value
Evaluate BinOp using MustBeEqual query as fallback.
val eval_fv :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
AD.t
val eval_tv :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
AD.t
val eval_int :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
ValueDomain.ID.t
val convert_offset :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.offset ->
VD.offs
val eval_lv :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.lval ->
AD.t
val eval_rv_keep_bot :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
value
val eval_rv :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
value
val query_evalint :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
[> `Bot | `Lifted of ValueDomain.ID.t | `Top ]
val eval_exp : store -> GoblintCil.exp -> ValueDomain.ID.int_t option
val eval_funvar :
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
GoblintCil.exp ->
ValueDomain.AD.t
val eval_rv_address :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
store ->
GoblintCil.exp ->
VD.t
Evaluate expression as address. Avoids expensive Apron EvalInt if the Int result would be useless to us anyway.
val is_not_alloc_var :
('a, 'b, 'c, 'd) Analyses.ctx ->
GoblintCil.varinfo ->
bool
val is_not_heap_alloc_var :
('a, 'b, 'c, 'd) Analyses.ctx ->
GoblintCil.varinfo ->
bool
val query_invariant :
(Priv.D.t BaseDomain.basecomponents_t,
[> `Bot | `Lifted1 of Priv.G.t ],
'a,
[> `Left of Priv.V.t ])
Analyses.ctx ->
Invariant.context ->
Invariant.t
val query_invariant_global :
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
[< `Left of Priv.V.t | `Right of 'c ] ->
Invariant.t
val exp_may_signed_overflow :
('a, 'b, 'c, 'd) Analyses.ctx ->
GoblintCil.exp ->
BoolDomain.MayBool.t
This query returns false if the expression exp
will definitely not result in an overflow.
Each subexpression is analyzed to see if an overflow happened. For each operator in the expression, we use the query EvalInt to approximate the bounds of each operand and we compute if in the worst case there could be an overflow.
For now we return true if the expression contains a shift left.
val lval_may_signed_overflow :
('a, 'b, 'c, 'd) Analyses.ctx ->
GoblintCil.lval ->
BoolDomain.MayBool.t
Add dependencies between a value and the expression it (or any of its contents) are partitioned by
val set :
ctx:
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
?invariant:bool ->
?blob_destructive:bool ->
?lval_raw:GoblintCil.lval ->
?rval_raw:GoblintCil.exp ->
?t_override:GoblintCil.Cil.typ ->
store ->
AD.t ->
GoblintCil.Cil.typ ->
value ->
store
set st addr val
returns a state where addr
is set to val
* it is always ok to put None for lval_raw and rval_raw, this amounts to not using/maintaining * precise information about arrays.
val rem_many_partitioning :
ValueDomain.VDQ.t ->
store ->
GoblintCil.varinfo list ->
store
val is_some_bot : value -> bool
module InvariantEval : sig ... end
module Invariant : sig ... end
val invariant :
(InvariantEval.D.t, InvariantEval.G.t, 'a, InvariantEval.V.t) Analyses.ctx ->
InvariantEval.D.t ->
GoblintCil.exp ->
bool ->
InvariantEval.D.t
val assign :
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
GoblintCil.lval ->
GoblintCil.exp ->
store
val branch :
(store, InvariantEval.G.t, 'a, InvariantEval.V.t) Analyses.ctx ->
GoblintCil.exp ->
bool ->
store
val body :
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
GoblintCil.fundec ->
store
val return :
(store,
[> `Bot | `Lifted1 of Priv.G.t | `Lifted2 of VD.t ],
'a,
[> `Left of Priv.V.t | `Right of ThreadIdDomain.Thread.t ])
Analyses.ctx ->
GoblintCil.exp option ->
GoblintCil.fundec ->
store
val vdecl :
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
GoblintCil.varinfo ->
store
val collect_funargs :
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
?warn:bool ->
store ->
GoblintCil.exp list ->
address list
From a list of expressions, collect a list of addresses that they might point to, or contain pointers to.
val collect_invalidate :
deep:bool ->
ctx:
('a, [> `Bot | `Lifted1 of Priv.G.t ], 'b, [> `Left of Priv.V.t ])
Analyses.ctx ->
?warn:bool ->
store ->
GoblintCil.exp list ->
address list
val forkfun :
(D.t, G.t, C.t, V.t) Analyses.ctx ->
GoblintCil.lval option ->
GoblintCil.varinfo ->
GoblintCil.exp list ->
(GoblintCil.lval option * GoblintCil.varinfo * GoblintCil.exp list * bool)
list
val assert_fn :
(InvariantEval.D.t, InvariantEval.G.t, 'a, InvariantEval.V.t) Analyses.ctx ->
GoblintCil.exp ->
bool ->
InvariantEval.D.t
val special_unknown_invalidate :
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
CilType.Varinfo.t ->
LibraryDesc.Cil.Cil.exp list ->
store
val check_invalid_mem_dealloc :
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
GoblintCil.varinfo ->
GoblintCil.exp ->
unit
val points_to_heap_only :
('a, 'b, 'c, 'd) Analyses.ctx ->
GoblintCil.exp ->
bool
val get_size_of_ptr_target :
('a, 'b, 'c, 'd) Analyses.ctx ->
GoblintCil.exp ->
ValueDomainQueries.ID.t Queries.result
val combine_env :
(store, [> `Bot | `Lifted1 of Priv.G.t ], 'a, [> `Left of Priv.V.t ])
Analyses.ctx ->
'b ->
'c ->
GoblintCil.fundec ->
'd ->
'e ->
D.t ->
Queries.ask ->
Priv.D.t Goblint_lib__BaseDomain.basecomponents_t
val threadspawn :
(BaseDomain.BaseComponents(Priv.D).t,
[> `Bot | `Lifted1 of Priv.G.t ],
'a,
[> `Left of Priv.V.t ])
Analyses.ctx ->
multiple:'b ->
GoblintCil.lval option ->
GoblintCil.varinfo ->
GoblintCil.exp list ->
('c, 'd, 'e, 'f) Analyses.ctx ->
D.t
val unassume :
(D.t,
[ `Bot | `Lifted1 of Priv.G.t | `Lifted2 of VD.t | `Top ],
'a,
[ `Left of Priv.V.t | `Right of ThreadIdDomain.thread ])
Analyses.ctx ->
GoblintCil.exp ->
WideningTokens.TS.elt list ->
D.t
val event :
(store, InvariantEval.G.t, 'a, InvariantEval.V.t) Analyses.ctx ->
Events.t ->
'b ->
BaseDomain.BaseComponents(Priv.D).t