Skip to content

Commit 9cdd34f

Browse files
author
Enrico Steffinlongo
authored
Merge pull request #7535 from peterschrammel/shadow-memory-basic2
Gather shadow memory fields
2 parents 2c5a2e5 + addef03 commit 9cdd34f

File tree

11 files changed

+187
-9
lines changed

11 files changed

+187
-9
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
void bad_declaration1()
2+
{
3+
__CPROVER_field_decl_local("field1", (int)0);
4+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
void bad_declaration2()
2+
{
3+
struct STRUCT
4+
{
5+
char x;
6+
} s;
7+
__CPROVER_field_decl_global("field2", s);
8+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
void good_declarations()
2+
{
3+
__CPROVER_field_decl_local("field1", (_Bool)0);
4+
__CPROVER_field_decl_global("field2", (unsigned __CPROVER_bitvector[6])0);
5+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
bad1.c
3+
--function bad_declaration1 --verbosity 10
4+
^EXIT=6$
5+
^SIGNAL=0$
6+
^A shadow memory field must not be larger than 8 bits.
7+
--
8+
--
9+
Test that a shadow memory declaration of a too large type is rejected.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
bad2.c
3+
--function bad_declaration2 --verbosity 10
4+
^EXIT=6$
5+
^SIGNAL=0$
6+
^A shadow memory field must be of a bitvector type.
7+
--
8+
--
9+
Test that a shadow memory declaration of a non-bitvector type is rejected.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
good.c
3+
--function good_declarations --verbosity 10
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
^Shadow memory: declare local field field1 of type c_bool\[8\]
8+
^Shadow memory: declare global field field2 of type unsignedbv\[6\]
9+
--
10+
^A shadow memory field must
11+
--
12+
Test that shadow memory declarations are correctly gathered.

src/goto-symex/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ SRC = auto_objects.cpp \
1515
precondition.cpp \
1616
renaming_level.cpp \
1717
shadow_memory.cpp \
18+
shadow_memory_util.cpp \
1819
show_program.cpp \
1920
show_vcc.cpp \
2021
slice.cpp \

src/goto-symex/shadow_memory.cpp

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ Author: Peter Schrammel
1111

1212
#include "shadow_memory.h"
1313

14+
#include <util/bitvector_types.h>
15+
#include <util/format_type.h>
1416
#include <util/fresh_symbol.h>
1517

1618
#include <langapi/language_util.h>
1719

1820
#include "goto_symex_state.h"
21+
#include "shadow_memory_util.h"
1922

2023
void shadow_memoryt::initialize_shadow_memory(
2124
goto_symex_statet &state,
@@ -95,17 +98,83 @@ void shadow_memoryt::symex_field_dynamic_init(
9598
}
9699

97100
shadow_memory_field_definitionst shadow_memoryt::gather_field_declarations(
98-
abstract_goto_modelt &goto_model,
101+
const abstract_goto_modelt &goto_model,
99102
message_handlert &message_handler)
100103
{
101-
// To be implemented
102-
103-
return shadow_memory_field_definitionst();
104+
shadow_memory_field_definitionst field_definitions;
105+
106+
// Gather shadow memory declarations from goto model
107+
for(const auto &goto_function : goto_model.get_goto_functions().function_map)
108+
{
109+
const auto &goto_program = goto_function.second.body;
110+
forall_goto_program_instructions(target, goto_program)
111+
{
112+
if(!target->is_function_call())
113+
continue;
114+
115+
const auto &code_function_call = to_code_function_call(target->code());
116+
const exprt &function = code_function_call.function();
117+
118+
if(function.id() != ID_symbol)
119+
continue;
120+
121+
const irep_idt &identifier = to_symbol_expr(function).get_identifier();
122+
123+
if(
124+
identifier ==
125+
CPROVER_PREFIX SHADOW_MEMORY_FIELD_DECL SHADOW_MEMORY_GLOBAL_SCOPE)
126+
{
127+
convert_field_declaration(
128+
code_function_call,
129+
field_definitions.global_fields,
130+
true,
131+
message_handler);
132+
}
133+
else if(
134+
identifier ==
135+
CPROVER_PREFIX SHADOW_MEMORY_FIELD_DECL SHADOW_MEMORY_LOCAL_SCOPE)
136+
{
137+
convert_field_declaration(
138+
code_function_call,
139+
field_definitions.local_fields,
140+
false,
141+
message_handler);
142+
}
143+
}
144+
}
145+
return field_definitions;
104146
}
105147

106148
void shadow_memoryt::convert_field_declaration(
107149
const code_function_callt &code_function_call,
108-
shadow_memory_field_definitionst::field_definitiont &fields)
150+
shadow_memory_field_definitionst::field_definitiont &fields,
151+
bool is_global,
152+
message_handlert &message_handler)
109153
{
110-
// To be implemented
154+
INVARIANT(
155+
code_function_call.arguments().size() == 2,
156+
std::string(CPROVER_PREFIX) + SHADOW_MEMORY_FIELD_DECL +
157+
(is_global ? SHADOW_MEMORY_GLOBAL_SCOPE : SHADOW_MEMORY_LOCAL_SCOPE) +
158+
" requires 2 arguments");
159+
irep_idt field_name = extract_field_name(code_function_call.arguments()[0]);
160+
161+
exprt expr = code_function_call.arguments()[1];
162+
163+
messaget log(message_handler);
164+
log.debug() << "Shadow memory: declare " << (is_global ? "global " : "local ")
165+
<< "field " << id2string(field_name) << " of type "
166+
<< format(expr.type()) << messaget::eom;
167+
if(!can_cast_type<bitvector_typet>(expr.type()))
168+
{
169+
throw unsupported_operation_exceptiont(
170+
"A shadow memory field must be of a bitvector type.");
171+
}
172+
if(to_bitvector_type(expr.type()).get_width() > 8)
173+
{
174+
throw unsupported_operation_exceptiont(
175+
"A shadow memory field must not be larger than 8 bits.");
176+
}
177+
178+
// record the field's initial value (and type)
179+
fields[field_name] = expr;
111180
}

src/goto-symex/shadow_memory.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class shadow_memoryt
5050
/// \param message_handler For logging
5151
/// \return The field definitions
5252
static shadow_memory_field_definitionst gather_field_declarations(
53-
abstract_goto_modelt &goto_model,
53+
const abstract_goto_modelt &goto_model,
5454
message_handlert &message_handler);
5555

5656
/// Initialize global-scope shadow memory for global/static variables.
@@ -100,9 +100,13 @@ class shadow_memoryt
100100
/// Converts a field declaration
101101
/// \param code_function_call The __CPROVER_field_decl_* call
102102
/// \param fields The field declaration to be extended
103-
void convert_field_declaration(
103+
/// \param is_global True if the declaration is global
104+
/// \param message_handler For logging
105+
static void convert_field_declaration(
104106
const code_function_callt &code_function_call,
105-
shadow_memory_field_definitionst::field_definitiont &fields);
107+
shadow_memory_field_definitionst::field_definitiont &fields,
108+
bool is_global,
109+
message_handlert &message_handler);
106110

107111
/// Allocates and initializes a shadow memory field for the given original
108112
/// memory.

src/goto-symex/shadow_memory_util.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*******************************************************************\
2+
3+
Module: Symex Shadow Memory Instrumentation
4+
5+
Author: Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Symex Shadow Memory Instrumentation Utilities
11+
12+
#include "shadow_memory_util.h"
13+
14+
#include <util/invariant.h>
15+
#include <util/pointer_expr.h>
16+
#include <util/std_expr.h>
17+
18+
irep_idt extract_field_name(const exprt &string_expr)
19+
{
20+
if(string_expr.id() == ID_typecast)
21+
return extract_field_name(to_typecast_expr(string_expr).op());
22+
else if(string_expr.id() == ID_address_of)
23+
return extract_field_name(to_address_of_expr(string_expr).object());
24+
else if(string_expr.id() == ID_index)
25+
return extract_field_name(to_index_expr(string_expr).array());
26+
else if(string_expr.id() == ID_string_constant)
27+
{
28+
return string_expr.get(ID_value);
29+
}
30+
else
31+
UNREACHABLE;
32+
}

0 commit comments

Comments
 (0)