Skip to content

Commit 7258f15

Browse files
author
Daniel Kroening
committed
added show_on_source for abstract domains
The abstract states are shown in a different color on the source code text of the program, as opposed to the goto-program dump. Indentation of the output of the abstract is made to match the indentation of the source code.
1 parent 2df5dec commit 7258f15

File tree

4 files changed

+190
-3
lines changed

4 files changed

+190
-3
lines changed

src/goto-analyzer/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ SRC = goto_analyzer_main.cpp \
33
taint_analysis.cpp \
44
taint_parser.cpp \
55
unreachable_instructions.cpp \
6+
show_on_source.cpp \
67
static_show_domain.cpp \
78
static_simplifier.cpp \
89
static_verifier.cpp \

src/goto-analyzer/goto_analyzer_parse_options.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,12 @@ Author: Daniel Kroening, [email protected]
5757
#include <util/unicode.h>
5858
#include <util/version.h>
5959

60-
#include "taint_analysis.h"
61-
#include "unreachable_instructions.h"
60+
#include "show_on_source.h"
6261
#include "static_show_domain.h"
6362
#include "static_simplifier.h"
6463
#include "static_verifier.h"
64+
#include "taint_analysis.h"
65+
#include "unreachable_instructions.h"
6566

6667
goto_analyzer_parse_optionst::goto_analyzer_parse_optionst(
6768
int argc,
@@ -626,7 +627,18 @@ int goto_analyzer_parse_optionst::perform_analysis(const optionst &options)
626627

627628
if(options.get_bool_option("show"))
628629
{
629-
static_show_domain(goto_model, *analyzer, options, out);
630+
if(
631+
options.get_bool_option("json") || options.get_bool_option("xml") ||
632+
options.get_bool_option("dot") ||
633+
options.get_bool_option("dependence-graph"))
634+
{
635+
static_show_domain(goto_model, *analyzer, options, out);
636+
}
637+
else
638+
{
639+
show_on_source(goto_model, *analyzer, get_message_handler());
640+
}
641+
630642
return CPROVER_EXIT_SUCCESS;
631643
}
632644
else if(options.get_bool_option("verify"))

src/goto-analyzer/show_on_source.cpp

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*******************************************************************\
2+
3+
Module: goto-analyzer
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "show_on_source.h"
10+
11+
#include <util/file_util.h>
12+
#include <util/message.h>
13+
#include <util/unicode.h>
14+
15+
#include <analyses/ai.h>
16+
17+
#include <fstream>
18+
19+
/// get a path to the file in given source location
20+
static std::string file(const source_locationt &l)
21+
{
22+
if(l.get_file().empty())
23+
return std::string();
24+
25+
const auto file = id2string(l.get_file());
26+
27+
if(source_locationt::is_built_in(file))
28+
return std::string();
29+
30+
return concat_dir_file(id2string(l.get_working_directory()), file);
31+
}
32+
33+
/// get the source files with non-top abstract states
34+
static std::set<std::string>
35+
get_source_files(const goto_modelt &goto_model, const ai_baset &ai)
36+
{
37+
std::set<std::string> files;
38+
39+
for(const auto &f : goto_model.goto_functions.function_map)
40+
{
41+
forall_goto_program_instructions(i_it, f.second.body)
42+
{
43+
const auto abstract_state = ai.abstract_state_before(i_it);
44+
if(abstract_state->is_top())
45+
continue; // ignore
46+
47+
if(i_it->source_location.get_line().empty())
48+
continue; // ignore
49+
50+
auto f = file(i_it->source_location);
51+
52+
if(!f.empty())
53+
files.insert(f);
54+
}
55+
}
56+
57+
return files;
58+
}
59+
60+
/// print a string with indent to match given sample line
61+
static void print_with_indent(
62+
const std::string &src,
63+
const std::string &indent_line,
64+
std::ostream &out)
65+
{
66+
const std::size_t p = indent_line.find_first_not_of(" \t");
67+
const std::string indent =
68+
p == std::string::npos ? std::string("") : std::string(indent_line, 0, p);
69+
std::istringstream in(src);
70+
std::string src_line;
71+
while(std::getline(in, src_line))
72+
out << indent << src_line << '\n';
73+
}
74+
75+
/// output source code annotated with abstract states for given file
76+
void show_on_source(
77+
const std::string &source_file,
78+
const goto_modelt &goto_model,
79+
const ai_baset &ai,
80+
message_handlert &message_handler)
81+
{
82+
#ifdef _MSC_VER
83+
std::ifstream in(widen(source_file));
84+
#else
85+
std::ifstream in(source_file);
86+
#endif
87+
88+
if(!in)
89+
return; // we fail silently
90+
91+
std::map<unsigned, ai_baset::locationt> line_map;
92+
93+
// Collect line numbers with non-top abstract states.
94+
// We pick the _first_ state for each line.
95+
for(const auto &f : goto_model.goto_functions.function_map)
96+
{
97+
forall_goto_program_instructions(i_it, f.second.body)
98+
{
99+
auto abstract_state = ai.abstract_state_before(i_it);
100+
if(abstract_state->is_top())
101+
continue; // ignore
102+
103+
const auto line = i_it->source_location.get_line();
104+
105+
if(line.empty())
106+
continue; // ignore
107+
108+
if(file(i_it->source_location) == source_file)
109+
{
110+
const unsigned line_no = stoul(id2string(line));
111+
if(line_map.find(line_no) == line_map.end())
112+
line_map[line_no] = i_it;
113+
}
114+
}
115+
}
116+
117+
// now print file to message handler
118+
messaget message(message_handler);
119+
const namespacet ns(goto_model.symbol_table);
120+
121+
unsigned line_no = 0;
122+
std::string line;
123+
while(std::getline(in, line))
124+
{
125+
line_no++;
126+
const auto map_it = line_map.find(line_no);
127+
if(map_it != line_map.end())
128+
{
129+
auto abstract_state = ai.abstract_state_before(map_it->second);
130+
std::ostringstream state_str;
131+
abstract_state->output(state_str, ai, ns);
132+
if(!state_str.str().empty())
133+
{
134+
message.result() << messaget::blue;
135+
print_with_indent(state_str.str(), line, message.result());
136+
message.result() << messaget::reset;
137+
}
138+
}
139+
140+
message.result() << line << messaget::eom;
141+
}
142+
}
143+
144+
/// output source code annotated with abstract states
145+
void show_on_source(
146+
const goto_modelt &goto_model,
147+
const ai_baset &ai,
148+
message_handlert &message_handler)
149+
{
150+
// first gather the source files that have something to show
151+
const auto source_files = get_source_files(goto_model, ai);
152+
153+
// now show file-by-file
154+
for(const auto &source_file : source_files)
155+
show_on_source(source_file, goto_model, ai, message_handler);
156+
}

src/goto-analyzer/show_on_source.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*******************************************************************\
2+
3+
Module: goto-analyzer
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_GOTO_ANALYZER_SHOW_ON_SOURCE_H
10+
#define CPROVER_GOTO_ANALYZER_SHOW_ON_SOURCE_H
11+
12+
class ai_baset;
13+
class goto_modelt;
14+
class message_handlert;
15+
16+
void show_on_source(const goto_modelt &, const ai_baset &, message_handlert &);
17+
18+
#endif // CPROVER_GOTO_ANALYZER_SHOW_ON_SOURCE_H

0 commit comments

Comments
 (0)