-
Notifications
You must be signed in to change notification settings - Fork 274
Create harness to initialize memory from snapshot #4150
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
Create harness to initialize memory from snapshot #4150
Conversation
@@ -529,6 +529,23 @@ class goto_programt | |||
return t; | |||
} | |||
|
|||
optionalt<const_targett> get_target(const unsigned location_number) const |
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.
We have elsewhere erased the const
qualifier from POD parameters, so it's probably better to drop it here.
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.
IMHO this is good to keep on definitions, as it still meaningful "I'm not going to modify this value in this body". I'd only remove it from declarations, where it is meaningless.
src/goto-programs/goto_program.h
Outdated
} | ||
|
||
return std::next( | ||
instructions.begin(), location_number - start_location_number); |
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.
I'm not sure we provide a guarantee that location numbers are contiguous. You might want to add a CHECK_RETURN
to make sure what you are about to return has the expected location_number
.
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.
Check added.
throw invalid_command_line_argument_exceptiont( | ||
"no instruction with location number " + | ||
std::to_string(*location_number) + " in function " + function); | ||
} |
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.
I think this check should be done as part of the options parsing very early on.
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.
At present goto-harness
loads the goto binary only after the options checking. We could move the loading of the goto binary to before the options checking, and then give a reference to the goto model to the constructor of every harness generator. Then we could move some of the checks out of generate()
and into handle_option()
. Does that sound reasonable?
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.
Although that's a non-trivial change it would seem like a good idea to me. The earlier we know about a problem the better?
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.
Done.
split_string(initial_location, ':', start, true); | ||
|
||
if( | ||
start.size() == 0 || (start.size() >= 1 && start.front().empty()) || |
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.
- Use
start.empy()
instead ofsize() == 0
start.size() >= 1
is trivially true here
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.
Done.
if(function.empty()) | ||
{ | ||
INVARIANT( | ||
location_number.has_value(), |
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.
Should be negated (if no function is provided, then location_number
must not be set.
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.
Done.
|
||
code_function_callt function_call( | ||
called_function_symbol.symbol_expr(), arguments); | ||
code.add(function_call); |
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.
Use std::move
or inline the constructor call.
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.
Done.
} | ||
|
||
code_function_callt function_call( | ||
called_function_symbol.symbol_expr(), arguments); |
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.
std::move(arguments)
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.
Done.
CHECK_RETURN(r.second); | ||
|
||
auto f_it = goto_model.goto_functions.function_map.insert( | ||
std::make_pair(function.name, goto_functiont())); |
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.
I'd use emplace(function.name, goto_functiont())
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.
Done.
"` already in " | ||
"the symbol table", | ||
"--" GOTO_HARNESS_GENERATOR_HARNESS_FUNCTION_NAME_OPT); | ||
} |
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.
I'd do that check as early as possible, no need to waste time doing add_init_section
or the likes.
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.
Done.
|
||
code_blockt harness_function_body; | ||
|
||
add_assignments_to_globals(snapshot, harness_function_body); |
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.
Make that function return a code_blockt
rather than passing it by reference.
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.
Done.
goto_program.insert_before(std::prev(goto_program.instructions.end())); | ||
|
||
init_it->make_assignment(code_assignt(var, false_exprt())); | ||
} |
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.
Now that since #4001 you can say
goto_program.insert_before(..., goto_programt::make_assignment(...));
The instructiont::make_assignment(...)
will eventually go away.
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.
Done.
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.
LGTM. Just one comment.
|
||
void insert_function(goto_modelt &goto_model, const symbolt &function) const; | ||
|
||
std::string memory_snapshot; |
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: I would change this name to memory_snapshot_file
or something else, because its naming is slightly confusing: When I first saw it in generate()
, I thought it had a complex data structure behind it, but it appears it's just a string indicating the file to read the json_symbol_table from.
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.
Done.
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.
Mostly nitpicks / questions, otherwise looks good to me
const symbol_exprt &var = symbol.symbol_expr(); | ||
|
||
// initialise var in __CPROVER_initialize if it is present | ||
const auto f_it = |
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.
Can you give this is a more meaningful name, such as cprover_init_it
or something along those lines?
Also, can you elaborate why you need to change __CPROVER_initialize
to make this work? (ideally as a comment in the code as well)
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.
Done.
|
||
goto_programt &goto_program = goto_function.body; | ||
|
||
const symbolt &symbol = get_fresh_aux_symbol( |
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.
Can you give symbol
a more meaningful name, such as func_init_done
or func_init_done_symbol
if you want to keep its symbol-ness part of the name?
Also, can you add a comment here about what func_init_done
means?
function_symbol.mode, | ||
symbol_table); | ||
|
||
const symbol_exprt &var = symbol.symbol_expr(); |
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.
Can you give this a more meaningful name, like func_init_done_variable
?
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.
Better names added.
code.add(function_call); | ||
} | ||
|
||
void memory_snapshot_harness_generatort::insert_function( |
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.
If this is supposed to insert the harness function specifically rather than just any function, can you rename this to insert_harness_function_into_goto_model
or something like this? (I know these names are getting rather lengthy, this is just an example)
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.
Renamed.
"--memory-snapshot <file> initialise memory from JSON memory snapshot\n"\ | ||
"--initial-location <func[:<n>]>\n" \ | ||
" use given function and location number as " \ | ||
"entry\n point\n" \ |
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.
⛏️ Looks like the formatting here got messed up a bit
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.
Actually looks ok on the command line.
@@ -23,5 +23,7 @@ if [ -e "${name}-mod.gb" ] ; then | |||
rm -f "${name}-mod.gb" | |||
fi | |||
|
|||
$goto_harness "${name}.gb" "${name}-mod.gb" --harness-function-name $entry_point ${args} | |||
$cbmc --show-goto-functions "${name}.gb" |
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.
Do you need this information for the tests or is this just intended to make debugging a bit easier?
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.
Not need, so I guess debugging.
ad416e2
to
6869881
Compare
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.
✔️
Passed Diffblue compatibility checks (cbmc commit: 6869881).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/100488819
|
||
// initialise var in __CPROVER_initialize if it is present | ||
const auto f_it = | ||
goto_functions.function_map.find(CPROVER_PREFIX "initialize"); |
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.
I'm not sure why you need this at all, shouldn't the generated harness function be enough for whatever you were going to to with initialize
?
This may need modification after diffblue#4150 is merged.
This may need modification after diffblue#4150 is merged.
This may need modification after diffblue#4150 is merged.
This may need modification after diffblue#4150 is merged.
This adds const iterators to iterate over the internal_symbols map of the symbol table. So far, only non-const iterators existed.
This adds several regression tests for the feature of creating a harness that initialises the memory from a memory snapshot.
Adds two invocations of cbmc --show-goto-functions to regression/goto-harness/chain.sh to output the goto program before and after the harness generation.
This adds a harness generator to goto-harness that takes a goto program and a memory snapshot in JSON format (via the option --memory-snapshot), and then builds a harness that initialises the global variables from the snapshot. In addition the harness generator provides the option --initial-location to specify the starting point of the execution. The harness thus behaves as if the original program would start execution at the given program location.
In case we get an array (and not an object) we first find the right object and then pass it to be converted.
1a3d4f4
to
7bc616a
Compare
This PR replaces PR #3755.