-
Notifications
You must be signed in to change notification settings - Fork 478
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
[WIP] Opportunistic state merging for Manticore #1351
Closed
+427
−0
Closed
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
fe233dd
Skeleton implementation for state merging in Manticore
vaibhavbsharma f21a8d4
Implementing input, output sockets comparison for states + adding an …
vaibhavbsharma 3abe783
Setting the random seed from the Python script instead of hard-coding…
vaibhavbsharma 317042d
Adding initial implementation of memory comparison for state merging
vaibhavbsharma 1f24e9c
Merge remote-tracking branch 'origin/master' into dev-state-merging
vaibhavbsharma ee29abf
Fixing a few issues to address comments from Yan and Dominik
vaibhavbsharma 9dbdca1
Finishing the `is_merge_possible` predicate's implementation by finis…
vaibhavbsharma 5de9436
Finishing off a basic implementation of opportunistic state merging b…
vaibhavbsharma a1b48c4
Setting the merged constraint in the merged state
vaibhavbsharma bc7af36
Dev state merging loadsave (#1357)
feliam e871f72
Integrating @feliam's changes in so that the basic_statemerging.py ex…
vaibhavbsharma cf5afff
Minor changes to get both Manticore CLI and script-based example via …
vaibhavbsharma c4c5c8a
Avoid unnecessary CPU register merging using the solver + explaining …
vaibhavbsharma 8c01cd8
Merge remote-tracking branch 'origin/master' into dev-state-merging
vaibhavbsharma 13e3ab6
Fixing code climate issues + adding docstrings for a Merger Plugin
vaibhavbsharma fa55715
Updating the description in basic_statemerging.c and .py which is the…
vaibhavbsharma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Integrating @feliam's changes in so that the basic_statemerging.py ex…
…ample is now using the Merge plugin 1. Using Merge plugin and the newly added APIs in Executor to load, delete, replace states 2. Completing the memory objects comparison by comparing both memory object's symbolic writes instead of only comparing the first memory object against the second 3. Adding documentation for all of the newly introduced methods in state_merging.py
commit e871f7296718e8717123be33cae5ef039fa53ab2
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ | |
import logging | ||
import signal | ||
|
||
from .state_merging import merge_constraints, is_merge_possible, merge | ||
from .plugin import Plugin | ||
from ..exceptions import ExecutorError, SolverError | ||
from ..utils.nointerrupt import WithKeyboardInterruptAs | ||
from ..utils.event import Eventful | ||
|
@@ -15,8 +17,6 @@ | |
from multiprocessing.managers import SyncManager | ||
from contextlib import contextmanager | ||
|
||
from core.state_merging import is_merge_possible, merge, merge_constraints | ||
|
||
# This is the single global manager that will handle all shared memory among workers | ||
|
||
consts = config.get_group('executor') | ||
|
@@ -164,29 +164,30 @@ def choice(self, state_ids): | |
else: | ||
return None | ||
|
||
def Merger(Plugin): | ||
|
||
|
||
class Merger(Plugin): | ||
def load_state(self, state_id, delete=False): | ||
return self.manticore._executor._load_state(state_id, delete) | ||
|
||
def delete_state(self, state_id): | ||
return self.manticore._executor._delete_state(state_id) | ||
|
||
def replace_state(self, state_id, state): | ||
return self.manticore._executor._replace_state(state_id, state) | ||
|
||
def did_enqueue_state_callback(self, state, state_id): | ||
# when a new state is addded to the list we save it so we do not have | ||
def did_enqueue_state_callback(self, state_id, state): | ||
# when a new state is addded to the list we save it so we do not have | ||
# to repload all states when try to merges last PC | ||
with self.locked_context('cpu_stateid_dict') as cpu_stateid_dict: | ||
# as we may be riunning in a different process we need to access this | ||
with self.locked_context('cpu_stateid_dict', dict) as cpu_stateid_dict: | ||
# as we may be running in a different process we need to access this | ||
# on a lock and over shared memory like this | ||
l = cpu_stateid_dict.get(state.cpu.PC, list()) | ||
l.append(state_id) | ||
cpu_stateid_dict[state.cpu.PC] = l | ||
|
||
|
||
def will_load_state(self, current_state_id): | ||
# When a state is loaded for exploration lets check if we can find it a | ||
def will_load_state_callback(self, current_state_id): | ||
# When a state is loaded for exploration lets check if we can find it a | ||
# mate for merging | ||
with self.locked_context('cpu_stateid_dict') as cpu_stateid_dict: | ||
# we get the lock and get a copy of the shared context | ||
|
@@ -195,7 +196,7 @@ def will_load_state(self, current_state_id): | |
|
||
# lets remove ourself from the list of waiting states | ||
assert current_state_id in states_at_pc | ||
del states_at_pc[current_state_id] | ||
states_at_pc.remove(current_state_id) | ||
|
||
#Iterate over all remaining states that are waiting for exploration | ||
#at the same PC | ||
|
@@ -204,33 +205,32 @@ def will_load_state(self, current_state_id): | |
new_state = self.load_state(new_state_id) | ||
(exp_merged_state, exp_new_state, merged_constraint) = merge_constraints(merged_state.constraints, new_state.constraints) | ||
is_mergeable, reason = is_merge_possible(merged_state, new_state, merged_constraint) | ||
|
||
if is_mergeable: | ||
#Ok we'll merge it! | ||
merged_state = merge(merged_state, new_state, exp_merged_state, exp_new_state, merged_constraint) | ||
merged_state = merge(merged_state, new_state, exp_merged_state, merged_constraint) | ||
|
||
#lets remove the vestigial links to the old state | ||
self.delete_state(new_state_id) | ||
self._states.remove(new_state_id) # we are locked under locked context | ||
|
||
merged_ids.append(new_state_id) | ||
is_mergeable = "succeeded" | ||
else: | ||
is_mergeable = "failed because of " + reason | ||
debug_string = "at PC = " + hex(current_state.cpu.PC) + \ | ||
debug_string = "at PC = " + hex(merged_state.cpu.PC) + \ | ||
", merge " + is_mergeable + " for state id = " + \ | ||
str(current_state_id) + " and " + str(new_state_id) | ||
print(debug_string) | ||
|
||
for i in merged_ids: | ||
states_at_pc.remove(i) | ||
states_at_pc.remove(i) | ||
|
||
cpu_stateid_dict[current_state.cpu.PC] = states_at_pc | ||
cpu_stateid_dict[merged_state.cpu.PC] = states_at_pc | ||
|
||
#Ok so we have merged current_state_id with {merged_ids} | ||
#And removed all merged_ids from everywhere | ||
|
||
#UGLY we are replacing a state_id. This may be breaking caches in | ||
#UGLY we are replacing a state_id. This may be breaking caches in | ||
#the future | ||
self.replace_state(current_state_id, merged_state) | ||
|
||
|
@@ -414,24 +414,20 @@ def get(self): | |
|
||
@sync | ||
def _load_state(self, state_id, delete=False): | ||
if state_id not in self._states: | ||
raise Exception("State does not exist") | ||
if delete: | ||
del self._states[self._states.index(state_id)] | ||
return self._workspace.load_state(new_state_id, delete=delete) | ||
if state_id in self._states: | ||
del self._states[self._states.index(state_id)] | ||
return self._workspace.load_state(state_id, delete=delete) | ||
|
||
@sync | ||
def _delete_state(self, state_id): | ||
if state_id not in self._states: | ||
raise Exception("State does not exist") | ||
del self._states[self._states.index(state_id)] | ||
return self._workspace.rm(state_id) | ||
if state_id in self._states: | ||
del self._states[self._states.index(state_id)] | ||
return self._workspace.rm_state(state_id) | ||
|
||
@sync | ||
def _replace_state(self, state_id, state): | ||
if state_id not in self._states: | ||
raise Exception("State id does not exist") | ||
self._workspace.rm(state_id) | ||
# self._workspace.rm_state(state_id) | ||
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. Delete comment? |
||
self._workspace.save_state(state, state_id) | ||
|
||
def list(self): | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Loud thinking: do we want users to directly subscribe for events? @feliam