Skip to content

Commit 639b9e9

Browse files
authored
Merge pull request #5475 from natasha-jeppu/pointer-alias
CBMC additional profiling info: Pointer dereference, points-to set metric
2 parents c907b2b + f179946 commit 639b9e9

File tree

13 files changed

+151
-19
lines changed

13 files changed

+151
-19
lines changed

regression/cbmc/points-to-sets/main.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
int main()
2+
{
3+
unsigned int value;
4+
int *p = (int *)value;
5+
6+
*p = *p + 1;
7+
assert(1);
8+
return 0;
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--show-points-to-sets
4+
^EXIT=1$
5+
^SIGNAL=0$
6+
--
7+
--
8+
To test output for --show-points-to-sets option that displays the size and contents of points-to sets in json format.
9+
xml-ui and plain output not supported.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--show-points-to-sets --json-ui
4+
activate-multi-line-match
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
\{\n\s*"Pointer": "main::1::p!0@1",\n\s*"PointsToSet": \[ "object_descriptor\(integer_address, unknown\)" \],\n\s*"PointsToSetSize": 1,\n\s*"RetainedValuesSet": \[ "object_descriptor\(integer_address, unknown\)" \],\n\s*"RetainedValuesSetSize": 1,\n\s*"Value": "byte_extract_little_endian\(__CPROVER_memory, pointer_offset\(main::1::p!0@1\), signedbv\[32\]\)"\n\s*\},\n\s*\{\n\s*"Pointer": "main::1::p!0@1",\n\s*"PointsToSet": \[ "object_descriptor\(integer_address, unknown\)" \],\n\s*"PointsToSetSize": 1,\n\s*"RetainedValuesSet": \[ "object_descriptor\(integer_address, unknown\)" \],\n\s*"RetainedValuesSetSize": 1,\n\s*"Value": "byte_extract_little_endian\(__CPROVER_memory, pointer_offset\(main::1::p!0@1\), signedbv\[32\]\)"\n\s*\}
8+
--
9+
--
10+
To test output for --show-points-to-sets option that displays the size and contents of points-to sets in json format.
11+
xml-ui and plain output not supported.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--show-points-to-sets --xml-ui
4+
^EXIT=1$
5+
^SIGNAL=0$
6+
--
7+
--
8+
To test output for --show-points-to-sets option that displays the size and contents of points-to sets in json format.
9+
xml-ui and plain output not supported.

src/cbmc/cbmc_parse_options.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ void cbmc_parse_optionst::set_default_options(optionst &options)
122122
options.set_option("simplify", true);
123123
options.set_option("simplify-if", true);
124124
options.set_option("show-goto-symex-steps", false);
125+
options.set_option("show-points-to-sets", false);
125126

126127
// Other default
127128
options.set_option("arrays-uf", "auto");
@@ -520,6 +521,9 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
520521
if(cmdline.isset("show-goto-symex-steps"))
521522
options.set_option("show-goto-symex-steps", true);
522523

524+
if(cmdline.isset("show-points-to-sets"))
525+
options.set_option("show-points-to-sets", true);
526+
523527
PARSE_OPTIONS_GOTO_TRACE(cmdline, options);
524528
}
525529

@@ -562,6 +566,17 @@ int cbmc_parse_optionst::doit()
562566
return CPROVER_EXIT_USAGE_ERROR;
563567
}
564568

569+
if(cmdline.isset("show-points-to-sets"))
570+
{
571+
if(!cmdline.isset("json-ui") || cmdline.isset("xml-ui"))
572+
{
573+
log.error() << "--show-points-to-sets supports only"
574+
" json output. Use --json-ui."
575+
<< messaget::eom;
576+
return CPROVER_EXIT_USAGE_ERROR;
577+
}
578+
}
579+
565580
register_languages();
566581

567582
// configure gcc, if required

src/goto-checker/bmc_util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ void run_property_decider(
177177
"(show-loops)" \
178178
"(show-vcc)" \
179179
"(show-goto-symex-steps)" \
180+
"(show-points-to-sets)" \
180181
"(slice-formula)" \
181182
"(unwinding-assertions)" \
182183
"(no-unwinding-assertions)" \
@@ -203,6 +204,8 @@ void run_property_decider(
203204
" --show-symex-strategies list strategies for use with --paths\n" \
204205
" --show-goto-symex-steps show which steps symex travels, includes " \
205206
" diagnostic information\n" \
207+
" --show-points-to-sets show points-to sets for\n" \
208+
" pointer dereference. Requires --json-ui.\n" \
206209
" --program-only only show program expression\n" \
207210
" --show-byte-ops show all byte extracts and updates\n" \
208211
" --show-loops show the loops in the program\n" \

src/goto-symex/symex_clean_expr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ void goto_symext::process_array_expr(statet &state, exprt &expr)
134134
symex_dereference_statet symex_dereference_state(state, ns);
135135

136136
value_set_dereferencet dereference(
137-
ns, state.symbol_table, symex_dereference_state, language_mode, false);
137+
ns, state.symbol_table, symex_dereference_state, language_mode, false, log);
138138

139-
expr = dereference.dereference(expr);
139+
expr = dereference.dereference(expr, symex_config.show_points_to_sets);
140140
lift_lets(state, expr);
141141

142142
::process_array_expr(expr, symex_config.simplify_opt, ns);

src/goto-symex/symex_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct symex_configt final
4646
/// \brief Prints out the path that symex is actively taking during execution,
4747
/// includes diagnostic information about call stack and guard size.
4848
bool show_symex_steps;
49+
bool show_points_to_sets;
4950

5051
/// Maximum sizes for which field sensitivity will be applied to array cells
5152
std::size_t max_field_sensitivity_array_size;

src/goto-symex/symex_dereference.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,12 @@ void goto_symext::dereference_rec(exprt &expr, statet &state, bool write)
264264
state.symbol_table,
265265
symex_dereference_state,
266266
language_mode,
267-
expr_is_not_null);
267+
expr_is_not_null,
268+
log);
268269

269270
// std::cout << "**** " << format(tmp1) << '\n';
270-
exprt tmp2 = dereference.dereference(tmp1);
271+
exprt tmp2 =
272+
dereference.dereference(tmp1, symex_config.show_points_to_sets);
271273
// std::cout << "**** " << format(tmp2) << '\n';
272274

273275
expr.swap(tmp2);

src/goto-symex/symex_main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ symex_configt::symex_configt(const optionst &options)
4747
debug_level(unsafe_string2int(options.get_option("debug-level"))),
4848
run_validation_checks(options.get_bool_option("validate-ssa-equation")),
4949
show_symex_steps(options.get_bool_option("show-goto-symex-steps")),
50+
show_points_to_sets(options.get_bool_option("show-points-to-sets")),
5051
max_field_sensitivity_array_size(
5152
options.is_set("no-array-field-sensitivity")
5253
? 0

src/pointer-analysis/goto_program_dereference.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,24 @@ class goto_program_dereferencet:protected dereference_callbackt
2828
// for the final argument to value_set_dereferencet.
2929
// This means that language-inappropriate values such as
3030
// (struct A*)some_integer_value in Java, may be returned.
31+
// Note: value_set_dereferencet requires a messaget instance
32+
// as on of its arguments to display the points-to set
33+
// during symex. Display is not done during goto-program
34+
// conversion. To ensure this the display_points_to_sets
35+
// parameter in value_set_dereferencet::dereference()
36+
// is set to false by default and is not changed by the
37+
// goto program conversion modules. Similarly, here we set
38+
// _log to be a default messaget instance.
3139
goto_program_dereferencet(
3240
const namespacet &_ns,
3341
symbol_tablet &_new_symbol_table,
3442
const optionst &_options,
35-
value_setst &_value_sets)
43+
value_setst &_value_sets,
44+
const messaget &_log = messaget())
3645
: options(_options),
3746
ns(_ns),
3847
value_sets(_value_sets),
39-
dereference(_ns, _new_symbol_table, *this, ID_nil, false)
48+
dereference(_ns, _new_symbol_table, *this, ID_nil, false, _log)
4049
{
4150
}
4251

src/pointer-analysis/value_set_dereference.cpp

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ Author: Daniel Kroening, [email protected]
1313

1414
#ifdef DEBUG
1515
#include <iostream>
16-
#include <util/format_expr.h>
1716
#endif
1817

1918
#include <util/arith_tools.h>
@@ -24,8 +23,10 @@ Author: Daniel Kroening, [email protected]
2423
#include <util/cprover_prefix.h>
2524
#include <util/expr_iterator.h>
2625
#include <util/expr_util.h>
26+
#include <util/format_expr.h>
2727
#include <util/format_type.h>
2828
#include <util/fresh_symbol.h>
29+
#include <util/json_irep.h>
2930
#include <util/options.h>
3031
#include <util/pointer_offset_size.h>
3132
#include <util/pointer_predicates.h>
@@ -60,7 +61,9 @@ static bool should_use_local_definition_for(const exprt &expr)
6061
return false;
6162
}
6263

63-
exprt value_set_dereferencet::dereference(const exprt &pointer)
64+
exprt value_set_dereferencet::dereference(
65+
const exprt &pointer,
66+
bool display_points_to_sets)
6467
{
6568
if(pointer.type().id()!=ID_pointer)
6669
throw "dereference expected pointer type, but got "+
@@ -70,8 +73,9 @@ exprt value_set_dereferencet::dereference(const exprt &pointer)
7073
if(pointer.id()==ID_if)
7174
{
7275
const if_exprt &if_expr=to_if_expr(pointer);
73-
exprt true_case = dereference(if_expr.true_case());
74-
exprt false_case = dereference(if_expr.false_case());
76+
exprt true_case = dereference(if_expr.true_case(), display_points_to_sets);
77+
exprt false_case =
78+
dereference(if_expr.false_case(), display_points_to_sets);
7579
return if_exprt(if_expr.cond(), true_case, false_case);
7680
}
7781
else if(pointer.id() == ID_typecast)
@@ -90,14 +94,26 @@ exprt value_set_dereferencet::dereference(const exprt &pointer)
9094
const auto &if_expr = to_if_expr(*underlying);
9195
return if_exprt(
9296
if_expr.cond(),
93-
dereference(typecast_exprt(if_expr.true_case(), pointer.type())),
94-
dereference(typecast_exprt(if_expr.false_case(), pointer.type())));
97+
dereference(
98+
typecast_exprt(if_expr.true_case(), pointer.type()),
99+
display_points_to_sets),
100+
dereference(
101+
typecast_exprt(if_expr.false_case(), pointer.type()),
102+
display_points_to_sets));
95103
}
96104
}
97105

98106
// type of the object
99107
const typet &type=pointer.type().subtype();
100108

109+
json_objectt json_result;
110+
if(display_points_to_sets)
111+
{
112+
std::stringstream ss;
113+
ss << format(pointer);
114+
json_result["Pointer"] = json_stringt(ss.str());
115+
}
116+
101117
#ifdef DEBUG
102118
std::cout << "value_set_dereferencet::dereference pointer=" << format(pointer)
103119
<< '\n';
@@ -107,6 +123,22 @@ exprt value_set_dereferencet::dereference(const exprt &pointer)
107123
const std::vector<exprt> points_to_set =
108124
dereference_callback.get_value_set(pointer);
109125

126+
if(display_points_to_sets)
127+
{
128+
json_result["PointsToSetSize"] =
129+
json_numbert(std::to_string(points_to_set.size()));
130+
131+
json_arrayt points_to_set_json;
132+
for(auto p : points_to_set)
133+
{
134+
std::stringstream ss;
135+
ss << format(p);
136+
points_to_set_json.push_back(json_stringt(ss.str()));
137+
}
138+
139+
json_result["PointsToSet"] = points_to_set_json;
140+
}
141+
110142
#ifdef DEBUG
111143
std::cout << "value_set_dereferencet::dereference points_to_set={";
112144
for(auto p : points_to_set)
@@ -135,6 +167,22 @@ exprt value_set_dereferencet::dereference(const exprt &pointer)
135167
compare_against_pointer = fresh_binder.symbol_expr();
136168
}
137169

170+
if(display_points_to_sets)
171+
{
172+
json_result["RetainedValuesSetSize"] =
173+
json_numbert(std::to_string(points_to_set.size()));
174+
175+
json_arrayt retained_values_set_json;
176+
for(auto &value : retained_values)
177+
{
178+
std::stringstream ss;
179+
ss << format(value);
180+
retained_values_set_json.push_back(json_stringt(ss.str()));
181+
}
182+
183+
json_result["RetainedValuesSet"] = retained_values_set_json;
184+
}
185+
138186
#ifdef DEBUG
139187
std::cout << "value_set_dereferencet::dereference retained_values={";
140188
for(const auto &value : retained_values)
@@ -224,6 +272,15 @@ exprt value_set_dereferencet::dereference(const exprt &pointer)
224272
if(compare_against_pointer != pointer)
225273
value = let_exprt(to_symbol_expr(compare_against_pointer), pointer, value);
226274

275+
if(display_points_to_sets)
276+
{
277+
std::stringstream ss;
278+
ss << format(value);
279+
json_result["Value"] = json_stringt(ss.str());
280+
281+
log.status() << json_result;
282+
}
283+
227284
#ifdef DEBUG
228285
std::cout << "value_set_derefencet::dereference value=" << format(value)
229286
<< '\n'

src/pointer-analysis/value_set_dereference.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include <unordered_set>
1616

17+
#include <util/message.h>
1718
#include <util/std_expr.h>
1819

1920
#include "dereference_callback.h"
@@ -34,25 +35,29 @@ class value_set_dereferencet final
3435
/// dereference failure
3536
/// \param _exclude_null_derefs: Ignore value-set entries that indicate a
3637
// given dereference may follow a null pointer
38+
/// \param _log: Messaget object for displaying points-to set
3739
value_set_dereferencet(
3840
const namespacet &_ns,
3941
symbol_tablet &_new_symbol_table,
4042
dereference_callbackt &_dereference_callback,
4143
const irep_idt _language_mode,
42-
bool _exclude_null_derefs):
43-
ns(_ns),
44-
new_symbol_table(_new_symbol_table),
45-
dereference_callback(_dereference_callback),
46-
language_mode(_language_mode),
47-
exclude_null_derefs(_exclude_null_derefs)
44+
bool _exclude_null_derefs,
45+
const messaget &_log)
46+
: ns(_ns),
47+
new_symbol_table(_new_symbol_table),
48+
dereference_callback(_dereference_callback),
49+
language_mode(_language_mode),
50+
exclude_null_derefs(_exclude_null_derefs),
51+
log(_log)
4852
{ }
4953

5054
virtual ~value_set_dereferencet() { }
5155

5256
/// Dereference the given pointer-expression. Any errors are
5357
/// reported to the callback method given in the constructor.
5458
/// \param pointer: A pointer-typed expression, to be dereferenced.
55-
exprt dereference(const exprt &pointer);
59+
/// \param display_points_to_sets: Display size and contents of points to sets
60+
exprt dereference(const exprt &pointer, bool display_points_to_sets = false);
5661

5762
/// Return value for `build_reference_to`; see that method for documentation.
5863
class valuet
@@ -105,6 +110,7 @@ class value_set_dereferencet final
105110
/// Flag indicating whether `value_set_dereferencet::dereference` should
106111
/// disregard an apparent attempt to dereference NULL
107112
const bool exclude_null_derefs;
113+
const messaget &log;
108114
};
109115

110116
#endif // CPROVER_POINTER_ANALYSIS_VALUE_SET_DEREFERENCE_H

0 commit comments

Comments
 (0)