[debug] add --procedures-cfg

Summary:
New option for `infer debug` to dump individual procedures' CFG after
the fact:

```
$ infer -o infer-out -- clang -c examples/hello.c
$ infer debug --procedures --procedures-cfg
test
  source_file: examples/hello.c
  attribute_kind: <defined>
  control-flow graph: '/home/jul/infer/infer-out/captured/hello.c.f19e4797ddf4b23fd1ce68a7e60f3b03/test.098f6bcd4621d373cade4e832627b4f6.dot'
```

Reviewed By: da319

Differential Revision: D22790593

fbshipit-source-id: 2fa2a6371
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent 221d0b62ab
commit 0aeb33947a

@ -46,6 +46,11 @@ DEBUG PROCEDURES
Activates: Print the attributes of each procedure in the output of
--procedures (Conversely: --no-procedures-attributes)
--procedures-cfg
Activates: Output a dotty file in
infer-out/captured/<file_name>/<proc_name>.dot for each procedure
in the output of --procedures (Conversely: --no-procedures-cfg)
--no-procedures-definedness
Deactivates: Include procedures definedness in the output of
--procedures, i.e. whether the procedure definition was found, or

@ -824,6 +824,12 @@ OPTIONS
--procedures (Conversely: --no-procedures-attributes)
See also infer-debug(1).
--procedures-cfg
Activates: Output a dotty file in
infer-out/captured/<file_name>/<proc_name>.dot for each procedure
in the output of --procedures (Conversely: --no-procedures-cfg)
See also infer-debug(1).
--no-procedures-definedness
Deactivates: Include procedures definedness in the output of
--procedures, i.e. whether the procedure definition was found, or

@ -824,6 +824,12 @@ OPTIONS
--procedures (Conversely: --no-procedures-attributes)
See also infer-debug(1).
--procedures-cfg
Activates: Output a dotty file in
infer-out/captured/<file_name>/<proc_name>.dot for each procedure
in the output of --procedures (Conversely: --no-procedures-cfg)
See also infer-debug(1).
--no-procedures-definedness
Deactivates: Include procedures definedness in the output of
--procedures, i.e. whether the procedure definition was found, or

@ -141,4 +141,5 @@ let emit_proc_desc source proc_desc =
in
DB.filename_to_string db_name ^ ".dot"
in
with_dot_file filename ~pp:(fun fmt -> print_pdesc source fmt proc_desc)
with_dot_file filename ~pp:(fun fmt -> print_pdesc source fmt proc_desc) ;
filename

@ -11,5 +11,6 @@ open! IStd
val emit_frontend_cfg : SourceFile.t -> Cfg.t -> unit
(** emit the given {!Cfg.t} in the "dot" format to a file determined by {!Config} values *)
val emit_proc_desc : SourceFile.t -> Procdesc.t -> unit
(** emit the given {!Procdesc.t} in the "dot" format to a file in infer-out/captured/ *)
val emit_proc_desc : SourceFile.t -> Procdesc.t -> string
(** emit the given {!Procdesc.t} in the "dot" format to a file in infer-out/captured/ and return the
path to that file *)

@ -52,7 +52,7 @@ let select_proc_names_interactive ~filter =
let pp_all ~filter ~proc_name:proc_name_cond ~attr_kind ~source_file:source_file_cond
~proc_attributes fmt () =
~proc_attributes ~proc_cfg fmt () =
let db = ResultsDatabase.get_database () in
let pp_if ?(new_line = false) condition title pp fmt x =
if condition then (
@ -66,7 +66,15 @@ let pp_all ~filter ~proc_name:proc_name_cond ~attr_kind ~source_file:source_file
in
let pp_row stmt fmt source_file proc_name =
let[@warning "-8"] (Sqlite3.Data.TEXT proc_name_hum) = Sqlite3.column stmt 1 in
Format.fprintf fmt "@[<v2>%s@,%a%a%a%a@]@\n" proc_name_hum
let dump_cfg fmt cfg_opt =
match cfg_opt with
| None ->
F.pp_print_string fmt "not found"
| Some cfg ->
let path = DotCfg.emit_proc_desc source_file cfg in
F.fprintf fmt "'%s'" path
in
Format.fprintf fmt "@[<v2>%s@,%a%a%a%a%a@]@\n" proc_name_hum
(pp_if source_file_cond "source_file" SourceFile.pp)
source_file
(pp_if proc_name_cond "proc_name" Procname.pp)
@ -77,11 +85,14 @@ let pp_all ~filter ~proc_name:proc_name_cond ~attr_kind ~source_file:source_file
(pp_column_if stmt ~new_line:true proc_attributes "attributes"
ProcAttributes.SQLite.deserialize ProcAttributes.pp)
4
(pp_column_if stmt ~new_line:false proc_cfg "control-flow graph" Procdesc.SQLite.deserialize
dump_cfg)
5
in
(* we could also register this statement but it's typically used only once per run so just prepare
it inside the function *)
Sqlite3.prepare db
"SELECT proc_name, proc_name_hum, attr_kind, source_file, proc_attributes FROM procedures"
"SELECT proc_name, proc_name_hum, attr_kind, source_file, proc_attributes, cfg FROM procedures"
|> Container.iter ~fold:(SqliteUtils.result_fold_rows db ~log:"print all procedures")
~f:(fun stmt ->
let proc_name = Sqlite3.column stmt 0 |> Procname.SQLite.deserialize in

@ -15,6 +15,7 @@ val pp_all :
-> attr_kind:bool
-> source_file:bool
-> proc_attributes:bool
-> proc_cfg:bool
-> Format.formatter
-> unit
-> unit

@ -177,7 +177,8 @@ let run_proc_analysis ~caller_pdesc callee_pdesc =
incr nesting ;
Preanal.do_preanalysis (Option.value_exn !exe_env_ref) callee_pdesc ;
if Config.debug_mode then
DotCfg.emit_proc_desc (Procdesc.get_attributes callee_pdesc).translation_unit callee_pdesc ;
DotCfg.emit_proc_desc (Procdesc.get_attributes callee_pdesc).translation_unit callee_pdesc
|> ignore ;
let initial_callee_summary = Summary.OnDisk.reset callee_pdesc in
add_active callee_pname ;
initial_callee_summary

@ -1724,6 +1724,15 @@ and procedures_attributes =
"Print the attributes of each procedure in the output of $(b,--procedures)"
and procedures_cfg =
CLOpt.mk_bool ~long:"procedures-cfg"
~in_help:InferCommand.[(Debug, manual_debug_procedures)]
(Printf.sprintf
"Output a dotty file in %s/<file_name>/<proc_name>.dot for each procedure in the output of \
$(b,--procedures)"
(ResultsDirEntryName.get_path ~results_dir:"infer-out" Debug))
and procedures_definedness =
CLOpt.mk_bool ~long:"procedures-definedness" ~default:true
~in_help:InferCommand.[(Debug, manual_debug_procedures)]
@ -2924,6 +2933,8 @@ and procedures = !procedures
and procedures_attributes = !procedures_attributes
and procedures_cfg = !procedures_cfg
and procedures_definedness = !procedures_definedness
and procedures_filter = !procedures_filter

@ -425,6 +425,8 @@ val procedures : bool
val procedures_attributes : bool
val procedures_cfg : bool
val procedures_definedness : bool
val procedures_filter : string option

@ -237,7 +237,8 @@ let () =
L.result "%a"
Config.(
Procedures.pp_all ~filter ~proc_name:procedures_name ~attr_kind:procedures_definedness
~source_file:procedures_source_file ~proc_attributes:procedures_attributes)
~source_file:procedures_source_file ~proc_attributes:procedures_attributes
~proc_cfg:procedures_cfg)
() ) ;
if Config.source_files then (
let filter = Lazy.force Filtering.source_files_filter in

Loading…
Cancel
Save