Skip to content

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

Merged
merged 7 commits into from
Mar 15, 2019

Conversation

danpoe
Copy link
Contributor

@danpoe danpoe commented Feb 10, 2019

This PR replaces PR #3755.

  • Each commit message has a non-empty body, explaining why the change was made.
  • Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • n/a My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • White-space or formatting changes outside the feature-related changed lines are in commits of their own.

@@ -529,6 +529,23 @@ class goto_programt
return t;
}

optionalt<const_targett> get_target(const unsigned location_number) const
Copy link
Collaborator

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.

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.

}

return std::next(
instructions.begin(), location_number - start_location_number);
Copy link
Collaborator

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.

Copy link
Contributor

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);
}
Copy link
Collaborator

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.

Copy link
Contributor Author

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?

Copy link
Collaborator

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?

Copy link
Contributor

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()) ||
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Use start.empy() instead of size() == 0
  2. start.size() >= 1 is trivially true here

Copy link
Contributor

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(),
Copy link
Collaborator

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.

Copy link
Contributor

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);
Copy link
Collaborator

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.

Copy link
Contributor

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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::move(arguments)

Copy link
Contributor

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()));
Copy link
Collaborator

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())

Copy link
Contributor

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);
}
Copy link
Collaborator

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.

Copy link
Contributor

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);
Copy link
Collaborator

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.

Copy link
Contributor

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()));
}
Copy link
Member

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@NlightNFotis NlightNFotis left a 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;
Copy link
Contributor

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

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 =

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)

Copy link
Contributor

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(

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();

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?

Copy link
Contributor

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(

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)

Copy link
Contributor

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" \

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

Copy link
Contributor

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"

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?

Copy link
Contributor

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.

@danpoe danpoe force-pushed the feature/memory-snapshot-harness branch 3 times, most recently from ad416e2 to 6869881 Compare February 11, 2019 16:06
Copy link
Contributor

@allredj allredj left a 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");

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?

xbauch pushed a commit to xbauch/cbmc that referenced this pull request Mar 8, 2019
xbauch pushed a commit to xbauch/cbmc that referenced this pull request Mar 11, 2019
This may need modification after diffblue#4150 is merged.
xbauch pushed a commit to xbauch/cbmc that referenced this pull request Mar 11, 2019
This may need modification after diffblue#4150 is merged.
xbauch pushed a commit to xbauch/cbmc that referenced this pull request Mar 13, 2019
This may need modification after diffblue#4150 is merged.
@xbauch xbauch mentioned this pull request Mar 13, 2019
7 tasks
xbauch pushed a commit to xbauch/cbmc that referenced this pull request Mar 13, 2019
This may need modification after diffblue#4150 is merged.
@tautschnig
Copy link
Collaborator

@danpoe @xbauch This needs a rebase.

danpoe added 2 commits March 15, 2019 10:49
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.
danpoe and others added 4 commits March 15, 2019 10:49
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.
@danpoe danpoe force-pushed the feature/memory-snapshot-harness branch 2 times, most recently from 1a3d4f4 to 7bc616a Compare March 15, 2019 13:53
@danpoe danpoe merged commit f9f0733 into diffblue:develop Mar 15, 2019
@danpoe danpoe deleted the feature/memory-snapshot-harness branch June 2, 2020 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants