Skip to content

Commit 38b0695

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 dd8d1c2 commit 38b0695

File tree

4 files changed

+188
-3
lines changed

4 files changed

+188
-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: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
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+
for(const auto &f : goto_model.goto_functions.function_map)
95+
{
96+
forall_goto_program_instructions(i_it, f.second.body)
97+
{
98+
auto abstract_state = ai.abstract_state_before(i_it);
99+
if(abstract_state->is_top())
100+
continue; // ignore
101+
102+
const auto line = i_it->source_location.get_line();
103+
104+
if(line.empty())
105+
continue; // ignore
106+
107+
if(file(i_it->source_location) == source_file)
108+
{
109+
const unsigned line_no = stoul(id2string(line));
110+
line_map[line_no] = i_it;
111+
}
112+
}
113+
}
114+
115+
// now print file to message handler
116+
messaget message(message_handler);
117+
const namespacet ns(goto_model.symbol_table);
118+
119+
unsigned line_no = 0;
120+
std::string line;
121+
while(std::getline(in, line))
122+
{
123+
line_no++;
124+
const auto map_it = line_map.find(line_no);
125+
if(map_it != line_map.end())
126+
{
127+
auto abstract_state = ai.abstract_state_before(map_it->second);
128+
std::ostringstream state_str;
129+
abstract_state->output(state_str, ai, ns);
130+
if(!state_str.str().empty())
131+
{
132+
message.result() << messaget::blue;
133+
print_with_indent(state_str.str(), line, message.result());
134+
message.result() << messaget::reset;
135+
}
136+
}
137+
138+
message.result() << line << messaget::eom;
139+
}
140+
}
141+
142+
/// output source code annotated with abstract states
143+
void show_on_source(
144+
const goto_modelt &goto_model,
145+
const ai_baset &ai,
146+
message_handlert &message_handler)
147+
{
148+
// first gather the source files that have something to show
149+
const auto source_files = get_source_files(goto_model, ai);
150+
151+
// now show file-by-file
152+
for(const auto &source_file : source_files)
153+
show_on_source(source_file, goto_model, ai, message_handler);
154+
}

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)