Skip to content

Commit 1db7abe

Browse files
committed
Modular analysis: Fix collect_graph algorithm.
1 parent 4d8d57e commit 1db7abe

File tree

5 files changed

+63
-27
lines changed

5 files changed

+63
-27
lines changed

src/analyses/accessAnalysis.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ struct
117117
in
118118
let read_addresses = f_ask.f Queries.Read in
119119
let get_reachable e = ctx.ask (Queries.ReachableAddressesFrom e) in
120-
let used_globals = UsedGlobals.get_callee_globals f_ask in
120+
let used_globals = UsedGlobals.get_used_globals_exps f_ask in
121121
let effective_args = args @ used_globals in
122122
let reachable =
123123
List.fold_left (fun acc arg -> AD.join acc (get_reachable arg) ) (AD.bot ()) effective_args

src/analyses/base.ml

+41-19
Original file line numberDiff line numberDiff line change
@@ -1292,17 +1292,21 @@ struct
12921292
| Some m1, Some m2 -> Option.is_some (Addr.Mval.prefix m1 m2)
12931293
| _ -> false
12941294

1295+
module Graph = ValueDomain.ADGraph
1296+
12951297
(* Given a set of addresses, collect graph
12961298
that contains all paths with which these addresses are reachable with a depth-first search *)
12971299
let collect_graph (local: CPA.t) (start: AD.t) (goal: AD.t) =
1298-
if AD.is_empty start || AD.is_empty goal then
1300+
if M.tracing then M.tracel "collect_graph" "local: %a\n start: %a\n" CPA.pretty local AD.pretty start;
1301+
let r = if AD.is_empty start || AD.is_empty goal then
12991302
ValueDomain.ADGraph.bot ()
13001303
else
13011304
let ask: Queries.ask = { Queries.f = (fun (type a) (q: a Queries.t) -> Queries.Result.top q)} in
13021305
let state = D.top () in
13031306
let local = {state with cpa = local} in
13041307
let rec dfs node (visited, graph) : bool * ValueDomain.ADGraph.t =
13051308
let node = node in
1309+
if M.tracing then M.tracel "collect_graph" "visited-set: %a + %a\n" AD.pretty visited Addr.pretty node;
13061310
let visited = AD.join visited (AD.singleton node) in
13071311
let glob_fun = fun _ -> failwith "Should not lookup globals." in
13081312
let reachable_from_node = reachable_from_address_offset ask glob_fun local (AD.singleton node) in
@@ -1318,10 +1322,11 @@ struct
13181322
else
13191323
begin
13201324
let found, graph = dfs n (visited, graph) in
1321-
if goal_reached || found then
1325+
if goal_reached || found then begin
1326+
if M.tracing then M.tracel "collect_graph" "Adding edge from %a via %a to %a graph.\n" Addr.pretty node Offset.Unit.pretty o Addr.pretty n;
13221327
let graph = ValueDomain.ADGraph.add node (ADOffsetMap.singleton o (AD.singleton n)) graph in
13231328
(true, graph)
1324-
else
1329+
end else
13251330
(found, graph)
13261331
end
13271332
in
@@ -1330,16 +1335,17 @@ struct
13301335
let f, g = dfs_add_edge o a g in
13311336
f, g) n g
13321337
in
1333-
ADOffsetMap.fold dfs_add_edge reachable_from_node (false, ValueDomain.ADGraph.bot ())
1338+
ADOffsetMap.fold dfs_add_edge reachable_from_node (false, graph)
13341339
in
13351340
let dfs_combine node (_, graph) =
1336-
let graph = dfs node (AD.empty (), graph) in
1337-
graph
1341+
dfs node (AD.empty (), graph)
13381342
in
13391343
let empty_graph = ValueDomain.ADGraph.empty () in
13401344
let _, result = AD.fold dfs_combine start (false, empty_graph) in
1341-
if M.tracing then M.tracel "collect_graph" "From %a to %a, in graph %a\n" AD.pretty start AD.pretty goal ValueDomain.ADGraph.pretty result;
13421345
result
1346+
in
1347+
if M.tracing then M.tracel "collect_graph" "Result: %a\n" Graph.pretty r;
1348+
r
13431349

13441350
let query ctx (type a) (q: a Q.t): a Q.result =
13451351
match q with
@@ -2940,19 +2946,23 @@ struct
29402946
module AddrPair = Lattice.Prod (Addr) (Addr)
29412947
module AddrPairSet = Set.Make (AddrPair)
29422948

2943-
module Graph = ValueDomain.ADGraph
2944-
29452949
(** In the given local state, from the start state, find the addresses that correspond to the goals *)
29462950
let collect_targets_with_graph ctx (graph: Graph.t) (args: exp list) (params: varinfo list) (goal: AD.t) =
29472951
let ask = Analyses.ask_of_ctx ctx in
29482952
let start = List.map (Addr.of_var ~is_modular:true) params in
2949-
let queue = List.combine start start in
2950-
let queue : (Addr.t * Addr.t) Queue.t = queue |> Seq.of_list |> Queue.of_seq in (* mutable! *)
2953+
(* let queue = List.combine args start in *)
2954+
(* let queue : (Addr.t * Addr.t) Queue.t = queue |> Seq.of_list |> Queue.of_seq in mutable! *)
2955+
let queue = Queue.of_seq Seq.empty in
29512956
let visited = ref AddrPairSet.empty in
29522957

29532958

29542959
let dir_reachable_conc = collect_funargs_immediate_offset ask ctx.global ctx.local args in
2955-
let dir_reachable_abs = List.map (fun a -> Graph.find a graph) start in
2960+
let dir_reachable_abs = List.map (fun a ->
2961+
let r = Graph.find a graph in
2962+
if M.tracing then M.tracel "modular_combine" "For %a found %a in graph.\n" Addr.pretty a ADOffsetMap.pretty r;
2963+
r)
2964+
start
2965+
in
29562966
let combined = try
29572967
List.combine dir_reachable_conc dir_reachable_abs
29582968
with Invalid_argument e -> (
@@ -2975,6 +2985,10 @@ struct
29752985
) dir_reachable_abs;
29762986
) combined;
29772987

2988+
M.tracel "modular_combine" "Initalized conc: %a\n" (d_list ", " ADOffsetMap.pretty) (List.map Tuple2.first combined);
2989+
M.tracel "modular_combine" "Initalized abs: %a\n" (d_list ", " ADOffsetMap.pretty) (List.map Tuple2.second combined);
2990+
M.tracel "modular_combine" "graph: %a\n" Graph.pretty graph;
2991+
29782992
while not (Queue.is_empty queue) do
29792993
let c, a = Queue.pop queue in
29802994
let dir_reachable_conc = reachable_from_address_offset ask ctx.global ctx.local (AD.singleton c) in
@@ -2998,8 +3012,13 @@ struct
29983012
let combine_env_modular ctx lval fexp f args fc au (f_ask: Queries.ask) =
29993013
let ask = Analyses.ask_of_ctx ctx in
30003014
let glob_fun = modular_glob_fun ctx in
3001-
let callee_globals = UsedGlobals.get_callee_globals f_ask in
3015+
let callee_globals_exp = UsedGlobals.get_used_globals f_ask in
3016+
let callee_globals = UsedGlobals.get_used_globals_exps f_ask in
3017+
3018+
let effective_params = f.sformals @ callee_globals_exp in
30023019
let effective_args = args @ callee_globals in
3020+
3021+
M.tracel "modular_combine" "effective_params: %a\n effective_args: %a\n" (d_list ", " CilType.Varinfo.pretty) effective_params (d_list ", " CilType.Exp.pretty) effective_args;
30033022
(* TODO: Use information from Read and Written graphs to determine subset of reachable that is reachable via arguments like provided in the graph. *)
30043023
(*
30053024
let reachable = collect_funargs ask ~warn:false glob_fun ctx.local effective_args in
@@ -3014,8 +3033,9 @@ struct
30143033
let write_graph = ask.f (WriteGraph f) in
30153034

30163035
(* TODO: pass goal, use goal in collect_targets_with_graph function*)
3017-
let reachable = collect_targets_with_graph ctx write_graph args f.sformals (AD.bot ()) in
3036+
let reachable = collect_targets_with_graph ctx write_graph effective_args effective_params (AD.bot ()) in
30183037

3038+
M.tracel "modular_combine" "reachable: %a\n" AD.pretty reachable;
30193039
let vars_to_writes : value_map VarMap.t =
30203040
let update_entry (address: address) (value: value) (acc: value_map VarMap.t) =
30213041
let lvals = AD.to_mval address in
@@ -3070,12 +3090,14 @@ struct
30703090
else
30713091
combine_env_regular ctx lval fexp f args fc au f_ask
30723092

3073-
let translate_callee_value_back ctx f (args: exp list) (value: VD.t): VD.t =
3093+
let translate_callee_value_back ctx f f_ask (args: exp list) (value: VD.t): VD.t =
30743094
let glob_fun = modular_glob_fun ctx in
30753095
let ask = Analyses.ask_of_ctx ctx in
30763096
let write_graph = ask.f (WriteGraph f) in
30773097
(* TODO: pass goal, use goal in collect_targets_with_graph function*)
3078-
let reachable = collect_targets_with_graph ctx write_graph args f.sformals (AD.bot ()) in
3098+
let callee_globals = UsedGlobals.get_used_globals f_ask in
3099+
let effective_params = f.sformals @ callee_globals in
3100+
let reachable = collect_targets_with_graph ctx write_graph args effective_params (AD.bot ()) in
30793101
let value = ModularUtil.ValueDomainExtension.map_back value ~reachable in
30803102
value
30813103

@@ -3088,10 +3110,10 @@ struct
30883110
else VD.top ()
30893111
in
30903112
let return_val = if is_callee_modular ~ask:(Analyses.ask_of_ctx ctx) ~callee:f then
3091-
let callee_globals = UsedGlobals.get_callee_globals f_ask in
3113+
let callee_globals = UsedGlobals.get_used_globals_exps f_ask in
30923114
(* let effective_args = args @ callee_globals in *)
3093-
let effective_args = args in
3094-
translate_callee_value_back ctx f effective_args return_val
3115+
let effective_args = args @ callee_globals in
3116+
translate_callee_value_back ctx f f_ask effective_args return_val
30953117
else
30963118
return_val
30973119
in

src/analyses/readAnalysis.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ struct
9090

9191
let get_reachable ctx args f_ask =
9292
let ask = Analyses.ask_of_ctx ctx in
93-
let used_globals = UsedGlobals.get_callee_globals f_ask in
93+
let used_globals = UsedGlobals.get_used_globals_exps f_ask in
9494
let get_reachable_exp (exp: exp) =
9595
ask.f (Q.ReachableAddressesFrom exp)
9696
in

src/analyses/usedGlobals.ml

+11-3
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@ open Batteries
44
open GoblintCil
55
open Analyses
66

7+
let accessed_globals_top_warning = "Accessed globals returned `Top!"
8+
9+
let get_used_globals (ask: Queries.ask) =
10+
match ask.f Queries.AccessedGlobals with
11+
| `Top -> failwith accessed_globals_top_warning
12+
| `Lifted globals ->
13+
ModularUtil.VS.to_list globals
14+
715
(** Get list of pointers to globals for all potentially used globals by function. *)
8-
let get_callee_globals (callee_ask: Queries.ask) =
9-
match callee_ask.f Queries.AccessedGlobals with
16+
let get_used_globals_exps (ask: Queries.ask) =
17+
match ask.f Queries.AccessedGlobals with
1018
| `Top ->
11-
failwith @@ "Accessed globals returned `Top!"
19+
failwith accessed_globals_top_warning
1220
| `Lifted globals ->
1321
ModularUtil.VS.fold (fun v acc -> mkAddrOf (Cil.var v) :: acc) globals []
1422

src/analyses/written.ml

+9-3
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,14 @@ struct
5151
let start_state = ask.f (Queries.StartCPA f) in
5252
let written = List.map Tuple2.first (D.bindings ctx.local) in
5353
let written = join_address_list written in
54-
let params = f.sformals in
55-
let params = List.map (AD.of_var ~is_modular:true) params in
54+
55+
(* TODO: Collect used globals in global invariant, as this may omit globals accessed in the return *)
56+
let callee_globals = match ask.f Queries.AccessedGlobals with
57+
| `Top -> []
58+
| `Lifted globals -> ModularUtil.VS.to_list globals
59+
in
60+
let effective_params = f.sformals @ callee_globals in
61+
let params = List.map (AD.of_var ~is_modular:true) effective_params in
5662
let params = join_address_list params in
5763
let graph = ask.f (CollectGraph (start_state, params, written)) in (* TODO: Adapt start and end sets *)
5864
M.tracel "startstate" "Looking for path from %a to %a in state %a\n" AD.pretty params AD.pretty written BaseDomain.CPA.pretty start_state;
@@ -66,7 +72,7 @@ struct
6672

6773
let get_reachable ctx args f_ask =
6874
let ask = Analyses.ask_of_ctx ctx in
69-
let used_globals = UsedGlobals.get_callee_globals f_ask in
75+
let used_globals = UsedGlobals.get_used_globals_exps f_ask in
7076
let get_reachable_exp (exp: exp) =
7177
ask.f (Q.ReachableAddressesFrom exp)
7278
in

0 commit comments

Comments
 (0)