Skip to content

Commit c5b3a4f

Browse files
authored
Merge pull request #1312 from goblint/issue-1192
Small output readability improvements
2 parents f2f5cc1 + f4d5a45 commit c5b3a4f

31 files changed

+560
-106
lines changed

src/analyses/mHPAnalysis.ml

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ struct
1212
include MHP
1313
let name () = "mhp"
1414
let may_race = MHP.may_happen_in_parallel
15-
let should_print _ = true
15+
let should_print {tid; created; must_joined} =
16+
GobConfig.get_bool "dbg.full-output" ||
17+
(not (ConcDomain.ThreadSet.is_empty created) ||
18+
not (ConcDomain.ThreadSet.is_empty must_joined))
1619
end
1720

1821
let access ctx _: MHP.t = MHP.current (Analyses.ask_of_ctx ctx)

src/analyses/wrapperFunctionAnalysis.ml

+13-2
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,19 @@ module MallocWrapper : MCPSpec = struct
131131
CilType.Location.show loc
132132

133133
let name_varinfo (t, node, c) =
134-
Format.asprintf "(alloc@sid:%s@tid:%s(#%s))" (Node.show_id node) (ThreadLifted.show t) (UniqueCount.show c)
135-
134+
let uniq_count =
135+
if not (GobConfig.get_bool "dbg.full-output") && UniqueCount.is_top c then
136+
Format.dprintf ""
137+
else
138+
Format.dprintf "(#%s)" (UniqueCount.show c)
139+
in
140+
let tid =
141+
if not (GobConfig.get_bool "dbg.full-output") && ThreadLifted.is_top t then
142+
Format.dprintf ""
143+
else
144+
Format.dprintf "@tid:%s%t" (ThreadLifted.show t) uniq_count
145+
in
146+
Format.asprintf "(alloc@sid:%s%t)" (Node.show_id node) tid
136147
end
137148

138149
module NodeVarinfoMap = RichVarinfo.BiVarinfoMap.Make(ThreadNode)

src/cdomain/value/cdomains/intDomain.ml

+46-16
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,22 @@ struct
313313
let widen = lift2 I.widen
314314
let narrow = lift2 I.narrow
315315

316-
let show x = I.show x.v (* TODO add ikind to output *)
317-
let pretty () x = I.pretty () x.v (* TODO add ikind to output *)
316+
let show x =
317+
if not (GobConfig.get_bool "dbg.full-output") && I.is_top_of x.ikind x.v then
318+
""
319+
else
320+
I.show x.v (* TODO add ikind to output *)
321+
let pretty () x =
322+
if not (GobConfig.get_bool "dbg.full-output") && I.is_top_of x.ikind x.v then
323+
Pretty.text ""
324+
else
325+
I.pretty () x.v (* TODO add ikind to output *)
318326
let pretty_diff () (x, y) = I.pretty_diff () (x.v, y.v) (* TODO check ikinds, add them to output *)
319-
let printXml o x = I.printXml o x.v (* TODO add ikind to output *)
327+
let printXml o x =
328+
if not (GobConfig.get_bool "dbg.full-output") && I.is_top_of x.ikind x.v then
329+
BatPrintf.fprintf o "<value>\n<data>\n\n</data>\n</value>\n"
330+
else
331+
I.printXml o x.v (* TODO add ikind to output *)
320332
(* This is for debugging *)
321333
let name () = "IntDomLifter(" ^ (I.name ()) ^ ")"
322334
let to_yojson x = I.to_yojson x.v
@@ -3477,9 +3489,27 @@ module IntDomTupleImpl = struct
34773489
in
34783490
mapp2 { fp2 = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.to_incl_list } x |> flat merge
34793491

3492+
let same show x = let xs = to_list_some x in let us = List.unique xs in let n = List.length us in
3493+
if n = 1 then Some (List.hd xs)
3494+
else (
3495+
if n>1 then Messages.info ~category:Unsound "Inconsistent state! %a" (Pretty.docList ~sep:(Pretty.text ",") (Pretty.text % show)) us; (* do not want to abort *)
3496+
None
3497+
)
3498+
let to_int = same Z.to_string % mapp2 { fp2 = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.to_int }
34803499

3481-
let pretty () = (fun xs -> text "(" ++ (try List.reduce (fun a b -> a ++ text "," ++ b) xs with Invalid_argument _ -> nil) ++ text ")") % to_list % mapp { fp = fun (type a) (module I:SOverflow with type t = a) -> (* assert sf==I.short; *) I.pretty () } (* NOTE: the version above does something else. also, we ignore the sf-argument here. *)
3482-
3500+
let pretty () x =
3501+
match to_int x with
3502+
| Some v when not (GobConfig.get_bool "dbg.full-output") -> Pretty.text (Z.to_string v)
3503+
| _ ->
3504+
mapp { fp = fun (type a) (module I:SOverflow with type t = a) -> (* assert sf==I.short; *) I.pretty () } x
3505+
|> to_list
3506+
|> (fun xs ->
3507+
text "(" ++ (
3508+
try
3509+
List.reduce (fun a b -> a ++ text "," ++ b) xs
3510+
with Invalid_argument _ ->
3511+
nil)
3512+
++ text ")") (* NOTE: the version above does something else. also, we ignore the sf-argument here. *)
34833513

34843514
let refine_functions ik : (t -> t) list =
34853515
let maybe reffun ik domtup dom =
@@ -3575,20 +3605,17 @@ module IntDomTupleImpl = struct
35753605
if List.mem `Eq xs then `Eq else
35763606
if List.mem `Neq xs then `Neq else
35773607
`Top
3578-
let same show x =
3579-
let us = List.unique (to_list_some x) in
3580-
match us with
3581-
| [x] -> Some x
3582-
| [] -> None
3583-
| _ ->
3584-
Messages.info ~category:Unsound "Inconsistent state! %a" (Pretty.docList ~sep:(Pretty.text ",") (Pretty.text % show)) us; (* do not want to abort *)
3585-
None
3586-
let to_int = same Z.to_string % mapp2 { fp2 = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.to_int }
3608+
35873609
let to_bool = same string_of_bool % mapp { fp = fun (type a) (module I:SOverflow with type t = a) -> I.to_bool }
35883610
let minimal = flat (List.max ~cmp:Z.compare) % mapp2 { fp2 = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.minimal }
35893611
let maximal = flat (List.min ~cmp:Z.compare) % mapp2 { fp2 = fun (type a) (module I:SOverflow with type t = a and type int_t = int_t) -> I.maximal }
35903612
(* others *)
3591-
let show = String.concat "; " % to_list % mapp { fp = fun (type a) (module I:SOverflow with type t = a) x -> I.name () ^ ":" ^ (I.show x) }
3613+
let show x =
3614+
match to_int x with
3615+
| Some v when not (GobConfig.get_bool "dbg.full-output") -> Z.to_string v
3616+
| _ -> mapp { fp = fun (type a) (module I:SOverflow with type t = a) x -> I.name () ^ ":" ^ (I.show x) } x
3617+
|> to_list
3618+
|> String.concat "; "
35923619
let to_yojson = [%to_yojson: Yojson.Safe.t list] % to_list % mapp { fp = fun (type a) (module I:SOverflow with type t = a) x -> I.to_yojson x }
35933620
let hash = List.fold_left (lxor) 0 % to_list % mapp { fp = fun (type a) (module I:SOverflow with type t = a) -> I.hash }
35943621

@@ -3698,7 +3725,10 @@ module IntDomTupleImpl = struct
36983725

36993726
(* printing boilerplate *)
37003727
let pretty_diff () (x,y) = dprintf "%a instead of %a" pretty x pretty y
3701-
let printXml f x = BatPrintf.fprintf f "<value>\n<data>\n%s\n</data>\n</value>\n" (show x)
3728+
let printXml f x =
3729+
match to_int x with
3730+
| Some v when not (GobConfig.get_bool "dbg.full-output") -> BatPrintf.fprintf f "<value>\n<data>\n%s\n</data>\n</value>\n" (Z.to_string v)
3731+
| _ -> BatPrintf.fprintf f "<value>\n<data>\n%s\n</data>\n</value>\n" (show x)
37023732

37033733
let invariant_ikind e ik x =
37043734
match to_int x with

src/cdomain/value/cdomains/threadIdDomain.ml

+14-10
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,23 @@ struct
5555
(struct let name = "no index" end)))
5656
(struct let name = "no node" end))
5757

58-
let show = function
59-
| (f, Some (n, i)) ->
60-
f.vname
61-
^ "@" ^ (CilType.Location.show (UpdateCil.getLoc n))
62-
^ "#" ^ Option.fold ~none:"top" ~some:string_of_int i
63-
| (f, None) -> f.vname
58+
let show (f, ni_opt) =
59+
let vname = f.vname in
60+
match ni_opt with
61+
| None -> vname
62+
| Some (n, i_opt) ->
63+
let vname_loc = vname ^ "@" ^ CilType.Location.show (UpdateCil.getLoc n) in
64+
match i_opt with
65+
| Some i -> vname_loc ^ "#" ^ string_of_int i
66+
| None when GobConfig.get_bool "dbg.full-output" -> vname_loc ^ "#⊤"
67+
| None -> vname_loc
6468

6569
include Printable.SimpleShow (
6670
struct
6771
type nonrec t = t
6872
let show = show
6973
end
70-
)
74+
)
7175

7276
let threadinit v ~multiple: t = (v, None)
7377

@@ -128,9 +132,9 @@ struct
128132
include S
129133
let name () = "created (once)"
130134
end) (struct
131-
include S
132-
let name () = "created (multiple times)"
133-
end)
135+
include S
136+
let name () = "created (multiple times)"
137+
end)
134138

135139

136140
let is_unique (_, s) =

src/cdomains/mHP.ml

+6-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ let current (ask:Queries.ask) =
2424
}
2525

2626
let pretty () {tid; created; must_joined} =
27-
let tid_doc = Some (Pretty.dprintf "tid=%a" ThreadIdDomain.ThreadLifted.pretty tid) in
27+
let tid_doc =
28+
if GobConfig.get_bool "dbg.full-output" then
29+
Some (Pretty.dprintf "tid=%a" ThreadIdDomain.ThreadLifted.pretty tid)
30+
else
31+
None
32+
in
2833
(* avoid useless empty sets in race output *)
2934
let created_doc =
3035
if ConcDomain.ThreadSet.is_empty created then

src/config/options.schema.json

+6
Original file line numberDiff line numberDiff line change
@@ -2038,6 +2038,12 @@
20382038
"Should the analysis call Check.checkFile after creating the CFG (helpful to verify that transformations respect CIL's invariants.",
20392039
"type": "boolean",
20402040
"default": false
2041+
},
2042+
"full-output": {
2043+
"title": "dbg.full-output",
2044+
"description": "Output abstract values, etc. with full internal details, without readability-oriented simplifications.",
2045+
"type": "boolean",
2046+
"default": false
20412047
}
20422048
},
20432049
"additionalProperties": false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
$ goblint --set ana.activated "['base', 'mallocWrapper']" --set ana.ctx_insens[+] 'base' --set ana.ctx_insens[+] 'mallocWrapper' --set ana.base.privatization none --enable warn.debug 87-casts-dep-on-param.c 2>&1 | sed -r 's/sid:[0-9]+/sid:$SID/' | tee default-output.txt
2+
[Warning] Without thread escape analysis, every local variable whose address is taken is considered escaped, i.e., global!
3+
[Info][Unsound] Unknown address in {&i} has escaped. (87-casts-dep-on-param.c:11:3-11:11)
4+
[Info][Unsound] Unknown value in {?} could be an escaped pointer address! (87-casts-dep-on-param.c:11:3-11:11)
5+
[Debug][Analyzer] Base EvalInt i query answering bot instead of {?, NULL, &(alloc@sid:$SID)} (87-casts-dep-on-param.c:13:7-13:15)
6+
[Debug][Analyzer] Base EvalInt i query answering bot instead of {?, NULL, &(alloc@sid:$SID)} (87-casts-dep-on-param.c:14:3-14:11)
7+
[Info][Unsound] Unknown address in {&p} has escaped. (87-casts-dep-on-param.c:17:7-17:19)
8+
[Info][Unsound] Unknown address in {&i} has escaped. (87-casts-dep-on-param.c:17:7-17:19)
9+
[Info][Unsound] Unknown value in {?} could be an escaped pointer address! (87-casts-dep-on-param.c:17:7-17:19)
10+
[Info][Deadcode] Logical lines of code (LLoC) summary:
11+
live: 15
12+
dead: 0
13+
total lines: 15
14+
15+
$ goblint --set ana.activated "['base', 'mallocWrapper']" --set ana.ctx_insens[+] 'base' --set ana.ctx_insens[+] 'mallocWrapper' --set ana.base.privatization none --enable warn.debug --enable dbg.full-output 87-casts-dep-on-param.c 2>&1 | sed -r 's/sid:[0-9]+/sid:$SID/' > full-output.txt
16+
17+
$ diff default-output.txt full-output.txt
18+
4,5c4,5
19+
< [Debug][Analyzer] Base EvalInt i query answering bot instead of {?, NULL, &(alloc@sid:$SID)} (87-casts-dep-on-param.c:13:7-13:15)
20+
< [Debug][Analyzer] Base EvalInt i query answering bot instead of {?, NULL, &(alloc@sid:$SID)} (87-casts-dep-on-param.c:14:3-14:11)
21+
---
22+
> [Debug][Analyzer] Base EvalInt i query answering bot instead of {?, NULL, &(alloc@sid:$SID@tid:Top Threads(#top))} (87-casts-dep-on-param.c:13:7-13:15)
23+
> [Debug][Analyzer] Base EvalInt i query answering bot instead of {?, NULL, &(alloc@sid:$SID@tid:Top Threads(#top))} (87-casts-dep-on-param.c:14:3-14:11)
24+
[1]

tests/regression/02-base/dune

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
(cram
2+
(deps (glob_files *.c)))
+20-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
$ goblint --enable warn.deterministic 01-simple_rc.c
1+
$ goblint --enable warn.deterministic 01-simple_rc.c 2>&1 | tee default-output.txt
22
[Warning][Race] Memory location myglobal (race with conf. 110): (01-simple_rc.c:4:5-4:13)
3-
write with [mhp:{tid=[main, t_fun@01-simple_rc.c:17:3-17:40#top]}, lock:{mutex1}, thread:[main, t_fun@01-simple_rc.c:17:3-17:40#top]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:10:3-10:22)
4-
write with [mhp:{tid=[main]; created={[main, t_fun@01-simple_rc.c:17:3-17:40#top]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:19:3-19:22)
5-
read with [mhp:{tid=[main, t_fun@01-simple_rc.c:17:3-17:40#top]}, lock:{mutex1}, thread:[main, t_fun@01-simple_rc.c:17:3-17:40#top]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:10:3-10:22)
6-
read with [mhp:{tid=[main]; created={[main, t_fun@01-simple_rc.c:17:3-17:40#top]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:19:3-19:22)
3+
write with [lock:{mutex1}, thread:[main, t_fun@01-simple_rc.c:17:3-17:40]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:10:3-10:22)
4+
write with [mhp:{created={[main, t_fun@01-simple_rc.c:17:3-17:40]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:19:3-19:22)
5+
read with [lock:{mutex1}, thread:[main, t_fun@01-simple_rc.c:17:3-17:40]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:10:3-10:22)
6+
read with [mhp:{created={[main, t_fun@01-simple_rc.c:17:3-17:40]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:19:3-19:22)
77
[Info][Race] Memory locations race summary:
88
safe: 0
99
vulnerable: 0
@@ -13,3 +13,18 @@
1313
live: 12
1414
dead: 0
1515
total lines: 12
16+
17+
$ goblint --enable warn.deterministic --enable dbg.full-output 01-simple_rc.c > full-output.txt 2>&1
18+
19+
$ diff default-output.txt full-output.txt
20+
2,5c2,5
21+
< write with [lock:{mutex1}, thread:[main, t_fun@01-simple_rc.c:17:3-17:40]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:10:3-10:22)
22+
< write with [mhp:{created={[main, t_fun@01-simple_rc.c:17:3-17:40]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:19:3-19:22)
23+
< read with [lock:{mutex1}, thread:[main, t_fun@01-simple_rc.c:17:3-17:40]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:10:3-10:22)
24+
< read with [mhp:{created={[main, t_fun@01-simple_rc.c:17:3-17:40]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:19:3-19:22)
25+
---
26+
> write with [mhp:{tid=[main, t_fun@01-simple_rc.c:17:3-17:40#⊤]}, lock:{mutex1}, thread:[main, t_fun@01-simple_rc.c:17:3-17:40#⊤]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:10:3-10:22)
27+
> write with [mhp:{tid=[main]; created={[main, t_fun@01-simple_rc.c:17:3-17:40#⊤]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:19:3-19:22)
28+
> read with [mhp:{tid=[main, t_fun@01-simple_rc.c:17:3-17:40#⊤]}, lock:{mutex1}, thread:[main, t_fun@01-simple_rc.c:17:3-17:40#⊤]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:10:3-10:22)
29+
> read with [mhp:{tid=[main]; created={[main, t_fun@01-simple_rc.c:17:3-17:40#⊤]}}, lock:{mutex2}, thread:[main]] (conf. 110) (exp: & myglobal) (01-simple_rc.c:19:3-19:22)
30+
[1]

0 commit comments

Comments
 (0)