-
Notifications
You must be signed in to change notification settings - Fork 274
Gather shadow memory fields #7535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2cd10e5
d84ee18
f3543c4
addef03
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
void bad_declaration1() | ||
{ | ||
__CPROVER_field_decl_local("field1", (int)0); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
void bad_declaration2() | ||
{ | ||
struct STRUCT | ||
{ | ||
char x; | ||
} s; | ||
__CPROVER_field_decl_global("field2", s); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
void good_declarations() | ||
{ | ||
__CPROVER_field_decl_local("field1", (_Bool)0); | ||
__CPROVER_field_decl_global("field2", (unsigned __CPROVER_bitvector[6])0); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CORE | ||
bad1.c | ||
--function bad_declaration1 --verbosity 10 | ||
^EXIT=6$ | ||
^SIGNAL=0$ | ||
^A shadow memory field must not be larger than 8 bits. | ||
-- | ||
-- | ||
Test that a shadow memory declaration of a too large type is rejected. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CORE | ||
bad2.c | ||
--function bad_declaration2 --verbosity 10 | ||
^EXIT=6$ | ||
^SIGNAL=0$ | ||
^A shadow memory field must be of a bitvector type. | ||
-- | ||
-- | ||
Test that a shadow memory declaration of a non-bitvector type is rejected. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
CORE | ||
good.c | ||
--function good_declarations --verbosity 10 | ||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^VERIFICATION SUCCESSFUL$ | ||
^Shadow memory: declare local field field1 of type c_bool\[8\] | ||
^Shadow memory: declare global field field2 of type unsignedbv\[6\] | ||
-- | ||
^A shadow memory field must | ||
-- | ||
Test that shadow memory declarations are correctly gathered. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,11 +11,14 @@ Author: Peter Schrammel | |
|
||
#include "shadow_memory.h" | ||
|
||
#include <util/bitvector_types.h> | ||
#include <util/format_type.h> | ||
#include <util/fresh_symbol.h> | ||
|
||
#include <langapi/language_util.h> | ||
|
||
#include "goto_symex_state.h" | ||
#include "shadow_memory_util.h" | ||
|
||
void shadow_memoryt::initialize_shadow_memory( | ||
goto_symex_statet &state, | ||
|
@@ -95,17 +98,83 @@ void shadow_memoryt::symex_field_dynamic_init( | |
} | ||
|
||
shadow_memory_field_definitionst shadow_memoryt::gather_field_declarations( | ||
abstract_goto_modelt &goto_model, | ||
const abstract_goto_modelt &goto_model, | ||
message_handlert &message_handler) | ||
{ | ||
// To be implemented | ||
|
||
return shadow_memory_field_definitionst(); | ||
shadow_memory_field_definitionst field_definitions; | ||
|
||
// Gather shadow memory declarations from goto model | ||
for(const auto &goto_function : goto_model.get_goto_functions().function_map) | ||
{ | ||
const auto &goto_program = goto_function.second.body; | ||
forall_goto_program_instructions(target, goto_program) | ||
{ | ||
if(!target->is_function_call()) | ||
continue; | ||
|
||
const auto &code_function_call = to_code_function_call(target->code()); | ||
const exprt &function = code_function_call.function(); | ||
|
||
if(function.id() != ID_symbol) | ||
continue; | ||
|
||
const irep_idt &identifier = to_symbol_expr(function).get_identifier(); | ||
|
||
if( | ||
identifier == | ||
CPROVER_PREFIX SHADOW_MEMORY_FIELD_DECL SHADOW_MEMORY_GLOBAL_SCOPE) | ||
{ | ||
convert_field_declaration( | ||
code_function_call, | ||
field_definitions.global_fields, | ||
true, | ||
message_handler); | ||
} | ||
else if( | ||
identifier == | ||
CPROVER_PREFIX SHADOW_MEMORY_FIELD_DECL SHADOW_MEMORY_LOCAL_SCOPE) | ||
{ | ||
convert_field_declaration( | ||
code_function_call, | ||
field_definitions.local_fields, | ||
false, | ||
message_handler); | ||
} | ||
} | ||
} | ||
return field_definitions; | ||
} | ||
|
||
void shadow_memoryt::convert_field_declaration( | ||
const code_function_callt &code_function_call, | ||
shadow_memory_field_definitionst::field_definitiont &fields) | ||
shadow_memory_field_definitionst::field_definitiont &fields, | ||
bool is_global, | ||
message_handlert &message_handler) | ||
{ | ||
// To be implemented | ||
INVARIANT( | ||
code_function_call.arguments().size() == 2, | ||
std::string(CPROVER_PREFIX) + SHADOW_MEMORY_FIELD_DECL + | ||
(is_global ? SHADOW_MEMORY_GLOBAL_SCOPE : SHADOW_MEMORY_LOCAL_SCOPE) + | ||
" requires 2 arguments"); | ||
irep_idt field_name = extract_field_name(code_function_call.arguments()[0]); | ||
|
||
exprt expr = code_function_call.arguments()[1]; | ||
|
||
messaget log(message_handler); | ||
log.debug() << "Shadow memory: declare " << (is_global ? "global " : "local ") | ||
<< "field " << id2string(field_name) << " of type " | ||
<< format(expr.type()) << messaget::eom; | ||
if(!can_cast_type<bitvector_typet>(expr.type())) | ||
{ | ||
throw unsupported_operation_exceptiont( | ||
"A shadow memory field must be of a bitvector type."); | ||
} | ||
if(to_bitvector_type(expr.type()).get_width() > 8) | ||
{ | ||
throw unsupported_operation_exceptiont( | ||
"A shadow memory field must not be larger than 8 bits."); | ||
} | ||
Comment on lines
+167
to
+176
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we please catch this in the front-end and just have a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be doable, but it would mean splitting up the logic over multiple modules, i.e. there will be shadow memory-specific logic in the front end - I tried to avoid that by postponing these checks, but I can of course change this if preferred. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be more user-friendly to catch problems early. If the front-end can tell the user that something will necessarily fail then IMHO it should do so. |
||
|
||
// record the field's initial value (and type) | ||
fields[field_name] = expr; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably a matter of style, but I'd prefer this method to return a pair (field_name, expr) and have the caller put this in place (the caller might choose insert or firmly replace). |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/*******************************************************************\ | ||
|
||
Module: Symex Shadow Memory Instrumentation | ||
|
||
Author: Peter Schrammel | ||
|
||
\*******************************************************************/ | ||
|
||
/// \file | ||
/// Symex Shadow Memory Instrumentation Utilities | ||
|
||
#include "shadow_memory_util.h" | ||
|
||
#include <util/invariant.h> | ||
#include <util/pointer_expr.h> | ||
#include <util/std_expr.h> | ||
|
||
irep_idt extract_field_name(const exprt &string_expr) | ||
{ | ||
if(string_expr.id() == ID_typecast) | ||
return extract_field_name(to_typecast_expr(string_expr).op()); | ||
else if(string_expr.id() == ID_address_of) | ||
return extract_field_name(to_address_of_expr(string_expr).object()); | ||
else if(string_expr.id() == ID_index) | ||
return extract_field_name(to_index_expr(string_expr).array()); | ||
else if(string_expr.id() == ID_string_constant) | ||
{ | ||
return string_expr.get(ID_value); | ||
} | ||
Comment on lines
+26
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit pick: is there a reason for using braces (just!) here? |
||
else | ||
UNREACHABLE; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/*******************************************************************\ | ||
|
||
Module: Symex Shadow Memory Instrumentation | ||
|
||
Author: Peter Schrammel | ||
|
||
\*******************************************************************/ | ||
|
||
/// \file | ||
/// Symex Shadow Memory Instrumentation Utilities | ||
|
||
#ifndef CPROVER_GOTO_SYMEX_SHADOW_MEMORY_UTIL_H | ||
#define CPROVER_GOTO_SYMEX_SHADOW_MEMORY_UTIL_H | ||
|
||
#include <util/irep.h> | ||
|
||
class exprt; | ||
|
||
/// Extracts the field name identifier from a string expression, | ||
/// e.g. as passed as argument to a __CPROVER_field_decl_local call. | ||
/// \param string_expr The string argument expression | ||
/// \return The identifier denoted by the string argument expression | ||
irep_idt extract_field_name(const exprt &string_expr); | ||
|
||
#endif // CPROVER_GOTO_SYMEX_SHADOW_MEMORY_STATE_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pick: no need for
id2string
here.