Source file printSlice.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
(** Everything needed to print the result *)
(**/**)
open Cil_types
open Pdg_types
(**/**)
let find_sub_stmts st = match st.skind with
| If(_,bl1,bl2,_) | TryExcept (bl1, _, bl2, _)
| TryFinally (bl1, bl2, _) -> bl1.bstmts@bl2.bstmts
| Block bl | Loop (_,bl, _, _, _) | Switch (_, bl, _, _) -> bl.bstmts
| UnspecifiedSequence seq -> List.map (fun (x,_,_,_,_) -> x) seq
| TryCatch(t,c,_) -> List.fold_left (fun acc (_,b) -> acc @ b.bstmts) t.bstmts c
| Continue _|Break _|Goto (_, _)|Return (_, _)|Instr _|Throw _ -> []
let str_call_sig ff call fmt =
try
let _, ff_marks = ff.SlicingInternals.ff_marks in
let called, sgn = PdgIndex.FctIndex.find_call ff_marks call in
let print_called fmt = match called with
| None
| Some (None) -> Format.fprintf fmt "@[/* undetermined call */@]"
| Some (Some (SlicingInternals.CallSlice ff)) ->
Format.fprintf fmt "@[<hov 2>/* call to %a */@]"
Fct_slice.print_ff_sig ff
| Some (Some(SlicingInternals.CallSrc _)) ->
Format.fprintf fmt "@[/* call to source function */@]"
in
Format.fprintf fmt "@[<v>@[<hov 2>/* sig call:@ %a */@]@ %t@]"
SlicingMarks.pretty_sig sgn print_called
with Not_found ->
Format.fprintf fmt "@[/* invisible call */@]"
class printerClass optional_ff = object(self)
inherit Printer.extensible_printer () as super
val opt_ff = optional_ff
method! vdecl fmt var =
match opt_ff with
| None -> super#vdecl fmt var
| Some ff ->
if var.vglob then
Format.fprintf fmt "@[/**/%a@]" super#vdecl var
else
let str_m =
try
let m = Fct_slice.get_local_var_mark ff var in
SlicingMarks.mark_to_string m
with Not_found -> "[---]"
in
Format.fprintf fmt "@[<hv>/* %s */@ %a@]"
str_m
super#vdecl var
method! stmtkind sattr next fmt kind =
let stmt_info fmt stmt = match opt_ff with
| None -> Format.fprintf fmt "@[/* %d */@]" stmt.Cil_types.sid
| Some ff ->
let str_m = try
let m = Fct_slice.get_stmt_mark ff stmt in
SlicingMarks.mark_to_string m
with Not_found -> "[---]"
in
if (SlicingMacros.is_call_stmt stmt)then
Format.fprintf fmt "@[<hv>%t@ /* %s */@]"
(str_call_sig ff stmt) str_m
else
Format.fprintf fmt "@[/* %s */@]" str_m
in
let s = Option.get self#current_stmt in
try
Format.fprintf fmt "@[<v>%a@ %a@]"
stmt_info s
(fun fmt -> super#stmtkind sattr next fmt) kind
with Not_found ->
let sub_stmts = find_sub_stmts s in
List.iter (self#stmt fmt) sub_stmts
method! label fmt l =
let label_info = match opt_ff with
| None -> "label"
| Some ff ->
let m = Fct_slice.get_label_mark ff (Option.get self#current_stmt) l in
SlicingMarks.mark_to_string m
in
Format.fprintf fmt "@[<hv>/* %s */@ %a@]"
label_info
super#label l
method! private require_braces _ _ = true
end
let print_fct_from_pdg fmt ?ff pdg =
let kf = PdgTypes.Pdg.get_kf pdg in
let fct = Kernel_function.get_definition kf in
let loc = Cil_datatype.Location.unknown in
let glob = Cil_types.GFun (fct, loc) in
let printer = new printerClass ff in
printer#global fmt glob
let print_marked_ff fmt ff =
let pdg = SlicingMacros.get_ff_pdg ff in
Format.fprintf fmt "@[<v>@[<hv>Print slice =@ %a@]@ @ %a@]"
Fct_slice.print_ff_sig ff
(print_fct_from_pdg ~ff) pdg
let print_original_glob fmt glob =
let printer = new printerClass None in
printer#global fmt glob
module PrintProject = struct
type t = string * SlicingInternals.project
type node =
| Src of SlicingInternals.fct_info
| Slice of SlicingInternals.fct_slice
| OptSlicingLevel of SlicingInternals.level_option
| OptSliceCallers of bool
| Action of (int * SlicingInternals.criterion)
module V = struct
type t = node
end
module E = struct
type t = (node * node) * Cil_types.stmt option
let src (e, _) = fst e
let dst (e, _) = snd e
end
type tfi = Undef | PersistSelect | Other
let fi_type fi = match fi.SlicingInternals.fi_def with
| Some _f ->
if SlicingMacros.fi_has_persistent_selection fi
then PersistSelect
else Other
| None -> Undef
let node_slice_callers () =
(OptSliceCallers (SlicingParameters.Mode.Callers.get ()))
let node_slice_calls () =
(OptSlicingLevel (SlicingMacros.get_default_level_option true))
let iter_vertex f (_, proj) =
f (node_slice_calls ()); f (node_slice_callers ());
let rec do_act n rq_list = match rq_list with
| [] -> ()
| rq :: rq_list -> f (Action (n, rq)) ; do_act (n+1) rq_list
in do_act 1 proj.SlicingInternals.actions;
let do_kf kf =
let fi = SlicingMacros.get_kf_fi kf in
let slices = SlicingMacros.fi_slices fi in
List.iter (fun ff -> f (Slice ff)) slices;
f (Src fi)
in
Globals.Functions.iter do_kf
let iter_edges_slices f proj =
let do_edge dest (ff_caller, call) =
f ((Slice ff_caller, dest), Some call) in
let do_f _f_var fi =
List.iter (do_edge (Src fi)) fi.SlicingInternals.f_called_by;
let do_ff ff = List.iter (do_edge (Slice ff)) ff.SlicingInternals.ff_called_by in
List.iter do_ff (SlicingMacros.fi_slices fi)
in
Cil_datatype.Varinfo.Hashtbl.iter do_f proj.SlicingInternals.functions
let iter_edges_actions f proj =
let rec do_act_edge n rq_list = match rq_list with
| [] -> ()
| _ :: [] -> ()
| rq1 :: rq2 :: rq_list ->
f (((Action (n, rq1)), (Action (n+1, rq2))), None);
do_act_edge (n+1) (rq2 :: rq_list)
in do_act_edge 1 proj.SlicingInternals.actions
let iter_edges_src_fun f =
let do_kf_calls kf =
let fi = SlicingMacros.get_kf_fi kf in
let doit kf_caller =
let fi_caller = SlicingMacros.get_kf_fi kf_caller in
f ((Src fi_caller, Src fi), None)
in List.iter doit (Eva.Results.callers kf)
in
Globals.Functions.iter do_kf_calls
let iter_edges_e f (_, proj) =
match proj.SlicingInternals.actions with [] -> ()
| rq :: _ -> f ((node_slice_callers (), (Action (1, rq))), None);
iter_edges_slices f proj;
iter_edges_actions f proj;
iter_edges_src_fun f
let color_soft_green = (0x7FFFD4)
let color_medium_green = (0x00E598)
let _color_soft_blue = (0x7FAAFF)
let color_soft_orange = (0xFFD57F)
let color_medium_orange = (0xFFB57F)
let _color_green_yellow = (0xAAFF7F)
let color_soft_yellow = (0xFFFFC3)
let color_medium_yellow = (0xFFFF5D)
let _color_pale_orange = (0xFFE1C3)
let color_soft_pink = (0xFACDEF)
let color_medium_pink = (0xF070D1)
let color_soft_purple = (0xE2CDFA)
let graph_attributes (name, _) = [`Label name]
let default_vertex_attributes _ = [`Style `Filled]
let vertex_name v = match v with
| Src fi -> SlicingMacros.fi_name fi
| Slice ff -> SlicingMacros.ff_name ff
| Action (n, _) -> ("rq_"^(string_of_int n))
| OptSlicingLevel _ -> "slicing_level"
| OptSliceCallers _ -> "slice_callers"
let vertex_attributes v = match v with
| Src fi ->
let color = match fi_type fi with
| Undef -> (`Fillcolor color_soft_yellow)
| PersistSelect -> (`Fillcolor color_soft_orange)
| Other -> (`Fillcolor color_soft_green)
in color::[`Shape `Plaintext]
| Slice ff ->
let color = match fi_type ff.SlicingInternals.ff_fct with
| Undef -> assert false
| PersistSelect -> (`Fillcolor color_soft_orange)
| Other -> (`Fillcolor color_soft_green)
in color ::[`Shape `Ellipse]
| Action (_, crit) ->
let label = Format.asprintf "%a" SlicingActions.print_crit crit in
let attrib = [] in
let attrib = (`Label label)::attrib in
let attrib = (`Fillcolor color_soft_pink)::attrib in
let attrib = (`Shape `Box)::attrib in
attrib
| OptSlicingLevel mode ->
let label = ("SliceCalls = "^(SlicingMacros.str_level_option mode)) in
let attrib = [] in
let attrib = (`Label label)::attrib in
let attrib = (`Fillcolor color_soft_purple)::attrib in
let attrib = (`Shape `Ellipse)::attrib in
let attrib = (`Fontsize 10)::attrib in
attrib
| OptSliceCallers b ->
let label = ("SliceCallers = "^(if b then "true" else "false")) in
let attrib = [] in
let attrib = (`Label label)::attrib in
let attrib = (`Fillcolor color_soft_purple)::attrib in
let attrib = (`Shape `Ellipse)::attrib in
let attrib = (`Fontsize 10)::attrib in
attrib
let default_edge_attributes _ =
let attrib = [] in
let attrib = (`Fontsize 10)::attrib in
attrib
let edge_attributes (e, call) =
let attrib = match e with
| (Src _, Src _) -> [`Style `Invis]
| (OptSliceCallers _, _) -> [`Style `Invis]
| (_, OptSliceCallers _) -> [`Style `Invis]
| _ -> []
in match call with None -> attrib
| Some call -> (`Label (string_of_int call.sid)):: attrib
let get_subgraph v =
let mk_subgraph name attrib =
let attrib = (`Style `Filled) :: attrib in
Some { Graph.Graphviz.DotAttributes.sg_name= name;
sg_parent = None;
sg_attributes = attrib }
in
let f_subgraph fi =
let name = SlicingMacros.fi_name fi in
let attrib = [`Label ""] in
let color = match fi_type fi with
| Undef -> (`Fillcolor color_medium_yellow)
| PersistSelect -> (`Fillcolor color_medium_orange)
| Other -> (`Fillcolor color_medium_green)
in let attrib = color :: attrib in
mk_subgraph name attrib
in
let rq_subgraph =
let name = "Requests" in
let attrib = [] in
let attrib = (`Fillcolor color_medium_pink) :: attrib in
let attrib = (`Label name) :: attrib in
mk_subgraph name attrib
in match v with
| Src fi -> f_subgraph fi
| Slice ff -> f_subgraph ff.SlicingInternals.ff_fct
| Action _ -> rq_subgraph
| OptSlicingLevel _ | OptSliceCallers _ -> rq_subgraph
end
module PrintProjGraph = Graph.Graphviz.Dot(PrintProject)
let build_dot_project filename title =
let project = SlicingState.get () in
let file = open_out filename in
PrintProjGraph.output_graph file (title, project);
close_out file
let print_fct_stmts fmt kf =
try
let pdg = Pdg.Api.get kf in
print_fct_from_pdg fmt pdg;
Format.pp_print_flush fmt ()
with Not_found -> ()