@@ -12,44 +12,80 @@ Author: Peter Schrammel
12
12
#include " shadow_memory.h"
13
13
14
14
#include < util/bitvector_types.h>
15
+ #include < util/expr_initializer.h>
16
+ #include < util/format_expr.h>
15
17
#include < util/format_type.h>
16
18
#include < util/fresh_symbol.h>
19
+ #include < util/pointer_expr.h>
20
+ #include < util/prefix.h>
21
+ #include < util/string_constant.h>
17
22
18
23
#include < langapi/language_util.h>
24
+ #include < linking/static_lifetime_init.h>
19
25
20
26
#include " goto_symex_state.h"
21
27
#include " shadow_memory_util.h"
22
28
23
29
void shadow_memoryt::initialize_shadow_memory (
24
30
goto_symex_statet &state,
25
- const exprt & expr,
31
+ exprt expr,
26
32
const shadow_memory_field_definitionst::field_definitiont &fields)
27
33
{
28
- // To be implemented
34
+ typet type = ns.follow (expr.type ());
35
+ clean_pointer_expr (expr, type);
36
+ for (const auto &field_pair : fields)
37
+ {
38
+ const symbol_exprt &shadow = add_field (state, expr, field_pair.first , type);
39
+
40
+ if (
41
+ field_pair.second .id () == ID_typecast &&
42
+ to_typecast_expr (field_pair.second ).op ().is_zero ())
43
+ {
44
+ const auto zero_value =
45
+ zero_initializer (type, expr.source_location (), ns);
46
+ CHECK_RETURN (zero_value.has_value ());
47
+
48
+ symex_assign (state, shadow, *zero_value);
49
+ }
50
+ else
51
+ {
52
+ exprt init_expr = field_pair.second ;
53
+ if (init_expr.id () == ID_typecast)
54
+ init_expr = to_typecast_expr (field_pair.second ).op ();
55
+ const auto init_value =
56
+ expr_initializer (type, expr.source_location (), ns, init_expr);
57
+ CHECK_RETURN (init_value.has_value ());
58
+
59
+ symex_assign (state, shadow, *init_value);
60
+ }
61
+
62
+ log.debug () << " Shadow memory: initialize field "
63
+ << id2string (shadow.get_identifier ()) << " for " << format (expr)
64
+ << " with initial value " << format (field_pair.second )
65
+ << messaget::eom;
66
+ }
29
67
}
30
68
31
- symbol_exprt shadow_memoryt::add_field (
69
+ const symbol_exprt & shadow_memoryt::add_field (
32
70
goto_symex_statet &state,
33
71
const exprt &expr,
34
72
const irep_idt &field_name,
35
73
const typet &field_type)
36
74
{
37
- // To be completed
38
-
39
75
const auto &function_symbol = ns.lookup (state.source .function_id );
40
-
41
- symbolt &new_symbol = get_fresh_aux_symbol (
76
+ const symbolt &new_symbol = get_fresh_aux_symbol (
42
77
field_type,
43
78
id2string (state.source .function_id ),
44
79
SHADOW_MEMORY_PREFIX + from_expr (expr) + " __" + id2string (field_name),
45
80
state.source .pc ->source_location (),
46
81
function_symbol.mode ,
47
82
state.symbol_table );
48
83
49
- // Call some function on ns to silence the compiler in the meanwhile.
50
- ns.get_symbol_table ();
84
+ auto &addresses = state.shadow_memory .address_fields [field_name];
85
+ addresses.push_back (
86
+ shadow_memory_statet::shadowed_addresst{expr, new_symbol.symbol_expr ()});
51
87
52
- return new_symbol. symbol_expr () ;
88
+ return addresses. back (). shadow ;
53
89
}
54
90
55
91
void shadow_memoryt::symex_set_field (
@@ -67,34 +103,132 @@ void shadow_memoryt::symex_get_field(
67
103
// To be implemented
68
104
}
69
105
106
+ // TODO: the following 4 functions (`symex_field_static_init`,
107
+ // `symex_field_static_init_string_constant`,
108
+ // `symex_field_local_init`,
109
+ // `symex_field_dynamic_init`) do filtering on
110
+ // the input symbol name and then call `initialize_shadow_memory` accordingly.
111
+ // We want to refactor and improve the way the filtering is done, but given
112
+ // that we don't have an easy mechanism to validate that we haven't changed the
113
+ // behaviour, we want to postpone changing this until the full shadow memory
114
+ // functionalities are integrated and we have good regression/unit testing.
115
+
70
116
void shadow_memoryt::symex_field_static_init (
71
117
goto_symex_statet &state,
72
118
const ssa_exprt &lhs)
73
119
{
74
- // To be implemented
120
+ if (lhs.get_original_expr ().id () != ID_symbol)
121
+ return ;
122
+
123
+ const irep_idt &identifier =
124
+ to_symbol_expr (lhs.get_original_expr ()).get_identifier ();
125
+
126
+ if (state.source .function_id != INITIALIZE_FUNCTION)
127
+ return ;
128
+
129
+ if (
130
+ has_prefix (id2string (identifier), CPROVER_PREFIX) &&
131
+ !has_prefix (id2string (identifier), CPROVER_PREFIX " errno" ))
132
+ {
133
+ return ;
134
+ }
135
+
136
+ const symbolt &symbol = ns.lookup (identifier);
137
+
138
+ if (
139
+ (id2string (symbol.name ).find (" ::return_value" ) == std::string::npos &&
140
+ symbol.is_auxiliary ) ||
141
+ !symbol.is_static_lifetime )
142
+ return ;
143
+ if (id2string (symbol.name ).find (" __cs_" ) != std::string::npos)
144
+ return ;
145
+
146
+ const typet &type = symbol.type ;
147
+ log.debug () << " Shadow memory: global memory " << id2string (identifier)
148
+ << " of type " << from_type (ns, " " , type) << messaget::eom;
149
+
150
+ initialize_shadow_memory (
151
+ state, lhs, state.shadow_memory .fields .global_fields );
75
152
}
76
153
77
154
void shadow_memoryt::symex_field_static_init_string_constant (
78
155
goto_symex_statet &state,
79
156
const ssa_exprt &expr,
80
157
const exprt &rhs)
81
158
{
82
- // To be implemented
159
+ if (
160
+ expr.get_original_expr ().id () == ID_symbol &&
161
+ has_prefix (
162
+ id2string (to_symbol_expr (expr.get_original_expr ()).get_identifier ()),
163
+ CPROVER_PREFIX))
164
+ {
165
+ return ;
166
+ }
167
+ const index_exprt &index_expr =
168
+ to_index_expr (to_address_of_expr (rhs).object ());
169
+
170
+ const typet &type = index_expr.array ().type ();
171
+ log.debug () << " Shadow memory: global memory "
172
+ << id2string (to_string_constant (index_expr.array ()).get_value ())
173
+ << " of type " << from_type (ns, " " , type) << messaget::eom;
174
+
175
+ initialize_shadow_memory (
176
+ state, index_expr.array (), state.shadow_memory .fields .global_fields );
83
177
}
84
178
85
179
void shadow_memoryt::symex_field_local_init (
86
180
goto_symex_statet &state,
87
181
const ssa_exprt &expr)
88
182
{
89
- // To be implemented
183
+ const symbolt &symbol =
184
+ ns.lookup (to_symbol_expr (expr.get_original_expr ()).get_identifier ());
185
+
186
+ const std::string symbol_name = id2string (symbol.name );
187
+ if (
188
+ symbol.is_auxiliary &&
189
+ symbol_name.find (" ::return_value" ) == std::string::npos)
190
+ return ;
191
+ if (
192
+ symbol_name.find (" malloc::" ) != std::string::npos &&
193
+ (symbol_name.find (" malloc_size" ) != std::string::npos ||
194
+ symbol_name.find (" malloc_res" ) != std::string::npos ||
195
+ symbol_name.find (" record_malloc" ) != std::string::npos ||
196
+ symbol_name.find (" record_may_leak" ) != std::string::npos))
197
+ {
198
+ return ;
199
+ }
200
+ if (
201
+ symbol_name.find (" __builtin_alloca::" ) != std::string::npos &&
202
+ (symbol_name.find (" alloca_size" ) != std::string::npos ||
203
+ symbol_name.find (" record_malloc" ) != std::string::npos ||
204
+ symbol_name.find (" record_alloca" ) != std::string::npos ||
205
+ symbol_name.find (" res" ) != std::string::npos))
206
+ {
207
+ return ;
208
+ }
209
+ if (symbol_name.find (" __cs_" ) != std::string::npos)
210
+ return ;
211
+
212
+ const typet &type = expr.type ();
213
+ ssa_exprt expr_l1 = remove_level_2 (expr);
214
+ log.debug () << " Shadow memory: local memory "
215
+ << id2string (expr_l1.get_identifier ()) << " of type "
216
+ << from_type (ns, " " , type) << messaget::eom;
217
+
218
+ initialize_shadow_memory (
219
+ state, expr_l1, state.shadow_memory .fields .local_fields );
90
220
}
91
221
92
222
void shadow_memoryt::symex_field_dynamic_init (
93
223
goto_symex_statet &state,
94
224
const exprt &expr,
95
225
const side_effect_exprt &code)
96
226
{
97
- // To be implemented
227
+ log.debug () << " Shadow memory: dynamic memory of type "
228
+ << from_type (ns, " " , expr.type ()) << messaget::eom;
229
+
230
+ initialize_shadow_memory (
231
+ state, expr, state.shadow_memory .fields .global_fields );
98
232
}
99
233
100
234
shadow_memory_field_definitionst shadow_memoryt::gather_field_declarations (
0 commit comments