We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Semantics of preconstrainer interface is confusing or wrong
<!--
*Disclaimer:
The angr suite is maintained by a small team of volunteers.
While we cannot guarantee any timeliness for fixes and enhancements, we will do our best.
For more real-time help with angr, from us and the community, join our [Slack.](https://angr.io/invite/)*
-->

**Describe the bug.**
Consider:
```
preconstrainer.preconstrain(value, exp1)
preconstrainer.remove_preconstraints()
preconstrainer.preconstrain(value, exp2)
```

After this sequence of calls, I expect `exp2 == value`, but **not** `exp1 == value`.  Right now, angr constrains both.  If this is intentional, how do I obtain my desired behavior?  If not, that is the bug.

**Describe the solution you would like.**
<!--
A clear and concise description of what you want to happen.
-->
My personal preference would be to adjust the preconstrainer to match my expected behavior.  Also I would like 10 BTC and a unicorn.

**Please include a sample of what *should* work if this feature is implemented.**
<!--
If this is related to a Python user interface/experience feature, please include an example of what this may look like.
If this is related to a certain kind of binary program, please attach one if possible.
-->
See above.

**Describe alternatives you have considered.**
<!--
A clear and concise description of any alternative solutions or features you've considered.
-->
I am going to manually clear `preconstrainer.preconstraints` and `preconstrainer.variable_map` but I shouldn't have to do that as the user.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `angr/state_plugins/preconstrainer.py`
Content:
```
1 import logging
2 import claripy
3 
4 from .plugin import SimStatePlugin
5 from .. import sim_options as o
6 from ..errors import AngrError
7 
8 
9 l = logging.getLogger(name=__name__)
10 
11 
12 class SimStatePreconstrainer(SimStatePlugin):
13     """
14     This state plugin manages the concept of preconstraining - adding constraints which you would like to remove later.
15 
16     :param constrained_addrs : SimActions for memory operations whose addresses should be constrained during crash analysis
17     """
18 
19     def __init__(self, constrained_addrs=None):
20         SimStatePlugin.__init__(self)
21 
22         # map of variable string names to preconstraints, for re-applying constraints.
23         self.variable_map = {}
24         self.preconstraints = []
25         self._constrained_addrs = [] if constrained_addrs is None else constrained_addrs
26         self.address_concretization = []
27 
28     def merge(self, others, merge_conditions, common_ancestor=None): # pylint: disable=unused-argument
29         l.warning("Merging is not implemented for preconstrainer!")
30         return False
31 
32     def widen(self, others): # pylint: disable=unused-argument
33         l.warning("Widening is not implemented for preconstrainer!")
34         return False
35 
36     @SimStatePlugin.memo
37     def copy(self, memo): # pylint: disable=unused-argument
38         c = SimStatePreconstrainer(constrained_addrs=self._constrained_addrs)
39 
40         c.variable_map = dict(self.variable_map)
41         c.preconstraints = list(self.preconstraints)
42         c.address_concretization = list(self.address_concretization)
43 
44         return c
45 
46     def preconstrain(self, value, variable):
47         """
48         Add a preconstraint that ``variable == value`` to the state.
49 
50         :param value:       The concrete value. Can be a bitvector or a bytestring or an integer.
51         :param variable:    The BVS to preconstrain.
52         """
53         if not isinstance(value, claripy.ast.Base):
54             value = self.state.solver.BVV(value, len(variable))
55         elif value.op != 'BVV':
56             raise ValueError("Passed a value to preconstrain that was not a BVV or a string")
57 
58         if variable.op not in claripy.operations.leaf_operations:
59             l.warning("The variable %s to preconstrain is not a leaf AST. This may cause replacement failures in the "
60                       "claripy replacement backend.", variable)
61             l.warning("Please use a leaf AST as the preconstraining variable instead.")
62 
63         constraint = variable == value
64         l.debug("Preconstraint: %s", constraint)
65 
66         # add the constraint for reconstraining later
67         self.variable_map[next(iter(variable.variables))] = constraint
68         self.preconstraints.append(constraint)
69         if o.REPLACEMENT_SOLVER in self.state.options:
70             self.state.solver._solver.add_replacement(variable, value, invalidate_cache=False)
71         else:
72             self.state.add_constraints(*self.preconstraints)
73         if not self.state.satisfiable():
74             l.warning("State went unsat while adding preconstraints")
75 
76     def preconstrain_file(self, content, simfile, set_length=False):
77         """
78         Preconstrain the contents of a file.
79 
80         :param content:     The content to preconstrain the file to. Can be a bytestring or a list thereof.
81         :param simfile:     The actual simfile to preconstrain
82         """
83         repair_entry_state_opts = False
84         if o.TRACK_ACTION_HISTORY in self.state.options:
85             repair_entry_state_opts = True
86             self.state.options -= {o.TRACK_ACTION_HISTORY}
87 
88         if set_length: # disable read bounds
89             simfile.has_end = False
90 
91         pos = 0
92         for write in content:
93             if type(write) is int:
94                 write = bytes([write])
95             data, length, pos = simfile.read(pos, len(write), disable_actions=True, inspect=False, short_reads=False)
96             if not claripy.is_true(length == len(write)):
97                 raise AngrError("Bug in either SimFile or in usage of preconstrainer: couldn't get requested data from file")
98             self.preconstrain(write, data)
99 
100         # if the file is a stream, reset its position
101         if simfile.pos is not None:
102             simfile.pos = 0
103 
104         if set_length: # enable read bounds; size is now maximum size
105             simfile.has_end = True
106 
107         if repair_entry_state_opts:
108             self.state.options |= {o.TRACK_ACTION_HISTORY}
109 
110     def preconstrain_flag_page(self, magic_content):
111         """
112         Preconstrain the data in the flag page.
113 
114         :param magic_content:   The content of the magic page as a bytestring.
115         """
116         for m, v in zip(magic_content, self.state.cgc.flag_bytes):
117             self.preconstrain(m, v)
118 
119     def remove_preconstraints(self, to_composite_solver=True, simplify=True):
120         """
121         Remove the preconstraints from the state.
122 
123         If you are using the zen plugin, this will also use that to filter the constraints.
124 
125         :param to_composite_solver:     Whether to convert the replacement solver to a composite solver. You probably
126                                         want this if you're switching from tracing to symbolic analysis.
127         :param simplify:                Whether to simplify the resulting set of constraints.
128         """
129         if not self.preconstraints:
130             return
131 
132         # cache key set creation
133         precon_cache_keys = set()
134 
135         for con in self.preconstraints:
136             precon_cache_keys.add(con.cache_key)
137 
138         # if we used the replacement solver we didn't add constraints we need to remove so keep all constraints
139         if o.REPLACEMENT_SOLVER in self.state.options:
140             new_constraints = self.state.solver.constraints
141         else:
142             new_constraints = list(filter(lambda x: x.cache_key not in precon_cache_keys, self.state.solver.constraints))
143 
144 
145         if self.state.has_plugin("zen_plugin"):
146             new_constraints = self.state.get_plugin("zen_plugin").filter_constraints(new_constraints)
147 
148         if to_composite_solver:
149             self.state.options.discard(o.REPLACEMENT_SOLVER)
150             self.state.options.add(o.COMPOSITE_SOLVER)
151 
152         # clear the solver's internal memory and replace it with the new solver options and constraints
153         self.state.solver.reload_solver(new_constraints)
154 
155         if simplify:
156             l.debug("simplifying solver...")
157             self.state.solver.simplify()
158             l.debug("...simplification done")
159 
160     def reconstrain(self):
161         """
162         Split the solver. If any of the subsolvers time out after a short timeout (10 seconds), re-add the
163         preconstraints associated with each of its variables. Hopefully these constraints still allow us to do
164         meaningful things to the state.
165         """
166 
167         # test all solver splits
168         subsolvers = self.state.solver._solver.split()
169 
170         for solver in subsolvers:
171             solver.timeout = 1000 * 10  # 10 seconds
172             if not solver.satisfiable():
173                 for var in solver.variables:
174                     if var in self.variable_map:
175                         self.state.add_constraints(self.variable_map[var])
176                     else:
177                         l.warning("var %s not found in self.variable_map", var)
178 
179 
180 from angr.sim_state import SimState
181 SimState.register_default('preconstrainer', SimStatePreconstrainer)
182
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/angr/state_plugins/preconstrainer.py b/angr/state_plugins/preconstrainer.py
--- a/angr/state_plugins/preconstrainer.py
+++ b/angr/state_plugins/preconstrainer.py
@@ -64,12 +64,14 @@
         l.debug("Preconstraint: %s", constraint)
 
         # add the constraint for reconstraining later
+        if next(iter(variable.variables)) in self.variable_map:
+            l.warning("%s is already preconstrained. Are you misusing preconstrainer?", next(iter(variable.variables)))
         self.variable_map[next(iter(variable.variables))] = constraint
         self.preconstraints.append(constraint)
         if o.REPLACEMENT_SOLVER in self.state.options:
             self.state.solver._solver.add_replacement(variable, value, invalidate_cache=False)
         else:
-            self.state.add_constraints(*self.preconstraints)
+            self.state.add_constraints(constraint)
         if not self.state.satisfiable():
             l.warning("State went unsat while adding preconstraints")

{"golden_diff": "diff --git a/angr/state_plugins/preconstrainer.py b/angr/state_plugins/preconstrainer.py\n--- a/angr/state_plugins/preconstrainer.py\n+++ b/angr/state_plugins/preconstrainer.py\n@@ -64,12 +64,14 @@\n         l.debug(\"Preconstraint: %s\", constraint)\n \n         # add the constraint for reconstraining later\n+        if next(iter(variable.variables)) in self.variable_map:\n+            l.warning(\"%s is already preconstrained. Are you misusing preconstrainer?\", next(iter(variable.variables)))\n         self.variable_map[next(iter(variable.variables))] = constraint\n         self.preconstraints.append(constraint)\n         if o.REPLACEMENT_SOLVER in self.state.options:\n             self.state.solver._solver.add_replacement(variable, value, invalidate_cache=False)\n         else:\n-            self.state.add_constraints(*self.preconstraints)\n+            self.state.add_constraints(constraint)\n         if not self.state.satisfiable():\n             l.warning(\"State went unsat while adding preconstraints\")\n", "issue": "Semantics of preconstrainer interface is confusing or wrong\n<!--\r\n*Disclaimer:\r\nThe angr suite is maintained by a small team of volunteers.\r\nWhile we cannot guarantee any timeliness for fixes and enhancements, we will do our best.\r\nFor more real-time help with angr, from us and the community, join our [Slack.](https://angr.io/invite/)*\r\n-->\r\n\r\n**Describe the bug.**\r\nConsider:\r\n```\r\npreconstrainer.preconstrain(value, exp1)\r\npreconstrainer.remove_preconstraints()\r\npreconstrainer.preconstrain(value, exp2)\r\n```\r\n\r\nAfter this sequence of calls, I expect `exp2 == value`, but **not** `exp1 == value`.  Right now, angr constrains both.  If this is intentional, how do I obtain my desired behavior?  If not, that is the bug.\r\n\r\n**Describe the solution you would like.**\r\n<!--\r\nA clear and concise description of what you want to happen.\r\n-->\r\nMy personal preference would be to adjust the preconstrainer to match my expected behavior.  Also I would like 10 BTC and a unicorn.\r\n\r\n**Please include a sample of what *should* work if this feature is implemented.**\r\n<!--\r\nIf this is related to a Python user interface/experience feature, please include an example of what this may look like.\r\nIf this is related to a certain kind of binary program, please attach one if possible.\r\n-->\r\nSee above.\r\n\r\n**Describe alternatives you have considered.**\r\n<!--\r\nA clear and concise description of any alternative solutions or features you've considered.\r\n-->\r\nI am going to manually clear `preconstrainer.preconstraints` and `preconstrainer.variable_map` but I shouldn't have to do that as the user.\r\n\n", "before_files": [{"content": "import logging\nimport claripy\n\nfrom .plugin import SimStatePlugin\nfrom .. import sim_options as o\nfrom ..errors import AngrError\n\n\nl = logging.getLogger(name=__name__)\n\n\nclass SimStatePreconstrainer(SimStatePlugin):\n    \"\"\"\n    This state plugin manages the concept of preconstraining - adding constraints which you would like to remove later.\n\n    :param constrained_addrs : SimActions for memory operations whose addresses should be constrained during crash analysis\n    \"\"\"\n\n    def __init__(self, constrained_addrs=None):\n        SimStatePlugin.__init__(self)\n\n        # map of variable string names to preconstraints, for re-applying constraints.\n        self.variable_map = {}\n        self.preconstraints = []\n        self._constrained_addrs = [] if constrained_addrs is None else constrained_addrs\n        self.address_concretization = []\n\n    def merge(self, others, merge_conditions, common_ancestor=None): # pylint: disable=unused-argument\n        l.warning(\"Merging is not implemented for preconstrainer!\")\n        return False\n\n    def widen(self, others): # pylint: disable=unused-argument\n        l.warning(\"Widening is not implemented for preconstrainer!\")\n        return False\n\n    @SimStatePlugin.memo\n    def copy(self, memo): # pylint: disable=unused-argument\n        c = SimStatePreconstrainer(constrained_addrs=self._constrained_addrs)\n\n        c.variable_map = dict(self.variable_map)\n        c.preconstraints = list(self.preconstraints)\n        c.address_concretization = list(self.address_concretization)\n\n        return c\n\n    def preconstrain(self, value, variable):\n        \"\"\"\n        Add a preconstraint that ``variable == value`` to the state.\n\n        :param value:       The concrete value. Can be a bitvector or a bytestring or an integer.\n        :param variable:    The BVS to preconstrain.\n        \"\"\"\n        if not isinstance(value, claripy.ast.Base):\n            value = self.state.solver.BVV(value, len(variable))\n        elif value.op != 'BVV':\n            raise ValueError(\"Passed a value to preconstrain that was not a BVV or a string\")\n\n        if variable.op not in claripy.operations.leaf_operations:\n            l.warning(\"The variable %s to preconstrain is not a leaf AST. This may cause replacement failures in the \"\n                      \"claripy replacement backend.\", variable)\n            l.warning(\"Please use a leaf AST as the preconstraining variable instead.\")\n\n        constraint = variable == value\n        l.debug(\"Preconstraint: %s\", constraint)\n\n        # add the constraint for reconstraining later\n        self.variable_map[next(iter(variable.variables))] = constraint\n        self.preconstraints.append(constraint)\n        if o.REPLACEMENT_SOLVER in self.state.options:\n            self.state.solver._solver.add_replacement(variable, value, invalidate_cache=False)\n        else:\n            self.state.add_constraints(*self.preconstraints)\n        if not self.state.satisfiable():\n            l.warning(\"State went unsat while adding preconstraints\")\n\n    def preconstrain_file(self, content, simfile, set_length=False):\n        \"\"\"\n        Preconstrain the contents of a file.\n\n        :param content:     The content to preconstrain the file to. Can be a bytestring or a list thereof.\n        :param simfile:     The actual simfile to preconstrain\n        \"\"\"\n        repair_entry_state_opts = False\n        if o.TRACK_ACTION_HISTORY in self.state.options:\n            repair_entry_state_opts = True\n            self.state.options -= {o.TRACK_ACTION_HISTORY}\n\n        if set_length: # disable read bounds\n            simfile.has_end = False\n\n        pos = 0\n        for write in content:\n            if type(write) is int:\n                write = bytes([write])\n            data, length, pos = simfile.read(pos, len(write), disable_actions=True, inspect=False, short_reads=False)\n            if not claripy.is_true(length == len(write)):\n                raise AngrError(\"Bug in either SimFile or in usage of preconstrainer: couldn't get requested data from file\")\n            self.preconstrain(write, data)\n\n        # if the file is a stream, reset its position\n        if simfile.pos is not None:\n            simfile.pos = 0\n\n        if set_length: # enable read bounds; size is now maximum size\n            simfile.has_end = True\n\n        if repair_entry_state_opts:\n            self.state.options |= {o.TRACK_ACTION_HISTORY}\n\n    def preconstrain_flag_page(self, magic_content):\n        \"\"\"\n        Preconstrain the data in the flag page.\n\n        :param magic_content:   The content of the magic page as a bytestring.\n        \"\"\"\n        for m, v in zip(magic_content, self.state.cgc.flag_bytes):\n            self.preconstrain(m, v)\n\n    def remove_preconstraints(self, to_composite_solver=True, simplify=True):\n        \"\"\"\n        Remove the preconstraints from the state.\n\n        If you are using the zen plugin, this will also use that to filter the constraints.\n\n        :param to_composite_solver:     Whether to convert the replacement solver to a composite solver. You probably\n                                        want this if you're switching from tracing to symbolic analysis.\n        :param simplify:                Whether to simplify the resulting set of constraints.\n        \"\"\"\n        if not self.preconstraints:\n            return\n\n        # cache key set creation\n        precon_cache_keys = set()\n\n        for con in self.preconstraints:\n            precon_cache_keys.add(con.cache_key)\n\n        # if we used the replacement solver we didn't add constraints we need to remove so keep all constraints\n        if o.REPLACEMENT_SOLVER in self.state.options:\n            new_constraints = self.state.solver.constraints\n        else:\n            new_constraints = list(filter(lambda x: x.cache_key not in precon_cache_keys, self.state.solver.constraints))\n\n\n        if self.state.has_plugin(\"zen_plugin\"):\n            new_constraints = self.state.get_plugin(\"zen_plugin\").filter_constraints(new_constraints)\n\n        if to_composite_solver:\n            self.state.options.discard(o.REPLACEMENT_SOLVER)\n            self.state.options.add(o.COMPOSITE_SOLVER)\n\n        # clear the solver's internal memory and replace it with the new solver options and constraints\n        self.state.solver.reload_solver(new_constraints)\n\n        if simplify:\n            l.debug(\"simplifying solver...\")\n            self.state.solver.simplify()\n            l.debug(\"...simplification done\")\n\n    def reconstrain(self):\n        \"\"\"\n        Split the solver. If any of the subsolvers time out after a short timeout (10 seconds), re-add the\n        preconstraints associated with each of its variables. Hopefully these constraints still allow us to do\n        meaningful things to the state.\n        \"\"\"\n\n        # test all solver splits\n        subsolvers = self.state.solver._solver.split()\n\n        for solver in subsolvers:\n            solver.timeout = 1000 * 10  # 10 seconds\n            if not solver.satisfiable():\n                for var in solver.variables:\n                    if var in self.variable_map:\n                        self.state.add_constraints(self.variable_map[var])\n                    else:\n                        l.warning(\"var %s not found in self.variable_map\", var)\n\n\nfrom angr.sim_state import SimState\nSimState.register_default('preconstrainer', SimStatePreconstrainer)\n", "path": "angr/state_plugins/preconstrainer.py"}], "after_files": [{"content": "import logging\nimport claripy\n\nfrom .plugin import SimStatePlugin\nfrom .. import sim_options as o\nfrom ..errors import AngrError\n\n\nl = logging.getLogger(name=__name__)\n\n\nclass SimStatePreconstrainer(SimStatePlugin):\n    \"\"\"\n    This state plugin manages the concept of preconstraining - adding constraints which you would like to remove later.\n\n    :param constrained_addrs : SimActions for memory operations whose addresses should be constrained during crash analysis\n    \"\"\"\n\n    def __init__(self, constrained_addrs=None):\n        SimStatePlugin.__init__(self)\n\n        # map of variable string names to preconstraints, for re-applying constraints.\n        self.variable_map = {}\n        self.preconstraints = []\n        self._constrained_addrs = [] if constrained_addrs is None else constrained_addrs\n        self.address_concretization = []\n\n    def merge(self, others, merge_conditions, common_ancestor=None): # pylint: disable=unused-argument\n        l.warning(\"Merging is not implemented for preconstrainer!\")\n        return False\n\n    def widen(self, others): # pylint: disable=unused-argument\n        l.warning(\"Widening is not implemented for preconstrainer!\")\n        return False\n\n    @SimStatePlugin.memo\n    def copy(self, memo): # pylint: disable=unused-argument\n        c = SimStatePreconstrainer(constrained_addrs=self._constrained_addrs)\n\n        c.variable_map = dict(self.variable_map)\n        c.preconstraints = list(self.preconstraints)\n        c.address_concretization = list(self.address_concretization)\n\n        return c\n\n    def preconstrain(self, value, variable):\n        \"\"\"\n        Add a preconstraint that ``variable == value`` to the state.\n\n        :param value:       The concrete value. Can be a bitvector or a bytestring or an integer.\n        :param variable:    The BVS to preconstrain.\n        \"\"\"\n        if not isinstance(value, claripy.ast.Base):\n            value = self.state.solver.BVV(value, len(variable))\n        elif value.op != 'BVV':\n            raise ValueError(\"Passed a value to preconstrain that was not a BVV or a string\")\n\n        if variable.op not in claripy.operations.leaf_operations:\n            l.warning(\"The variable %s to preconstrain is not a leaf AST. This may cause replacement failures in the \"\n                      \"claripy replacement backend.\", variable)\n            l.warning(\"Please use a leaf AST as the preconstraining variable instead.\")\n\n        constraint = variable == value\n        l.debug(\"Preconstraint: %s\", constraint)\n\n        # add the constraint for reconstraining later\n        if next(iter(variable.variables)) in self.variable_map:\n            l.warning(\"%s is already preconstrained. Are you misusing preconstrainer?\", next(iter(variable.variables)))\n        self.variable_map[next(iter(variable.variables))] = constraint\n        self.preconstraints.append(constraint)\n        if o.REPLACEMENT_SOLVER in self.state.options:\n            self.state.solver._solver.add_replacement(variable, value, invalidate_cache=False)\n        else:\n            self.state.add_constraints(constraint)\n        if not self.state.satisfiable():\n            l.warning(\"State went unsat while adding preconstraints\")\n\n    def preconstrain_file(self, content, simfile, set_length=False):\n        \"\"\"\n        Preconstrain the contents of a file.\n\n        :param content:     The content to preconstrain the file to. Can be a bytestring or a list thereof.\n        :param simfile:     The actual simfile to preconstrain\n        \"\"\"\n        repair_entry_state_opts = False\n        if o.TRACK_ACTION_HISTORY in self.state.options:\n            repair_entry_state_opts = True\n            self.state.options -= {o.TRACK_ACTION_HISTORY}\n\n        if set_length: # disable read bounds\n            simfile.has_end = False\n\n        pos = 0\n        for write in content:\n            if type(write) is int:\n                write = bytes([write])\n            data, length, pos = simfile.read(pos, len(write), disable_actions=True, inspect=False, short_reads=False)\n            if not claripy.is_true(length == len(write)):\n                raise AngrError(\"Bug in either SimFile or in usage of preconstrainer: couldn't get requested data from file\")\n            self.preconstrain(write, data)\n\n        # if the file is a stream, reset its position\n        if simfile.pos is not None:\n            simfile.pos = 0\n\n        if set_length: # enable read bounds; size is now maximum size\n            simfile.has_end = True\n\n        if repair_entry_state_opts:\n            self.state.options |= {o.TRACK_ACTION_HISTORY}\n\n    def preconstrain_flag_page(self, magic_content):\n        \"\"\"\n        Preconstrain the data in the flag page.\n\n        :param magic_content:   The content of the magic page as a bytestring.\n        \"\"\"\n        for m, v in zip(magic_content, self.state.cgc.flag_bytes):\n            self.preconstrain(m, v)\n\n    def remove_preconstraints(self, to_composite_solver=True, simplify=True):\n        \"\"\"\n        Remove the preconstraints from the state.\n\n        If you are using the zen plugin, this will also use that to filter the constraints.\n\n        :param to_composite_solver:     Whether to convert the replacement solver to a composite solver. You probably\n                                        want this if you're switching from tracing to symbolic analysis.\n        :param simplify:                Whether to simplify the resulting set of constraints.\n        \"\"\"\n        if not self.preconstraints:\n            return\n\n        # cache key set creation\n        precon_cache_keys = set()\n\n        for con in self.preconstraints:\n            precon_cache_keys.add(con.cache_key)\n\n        # if we used the replacement solver we didn't add constraints we need to remove so keep all constraints\n        if o.REPLACEMENT_SOLVER in self.state.options:\n            new_constraints = self.state.solver.constraints\n        else:\n            new_constraints = list(filter(lambda x: x.cache_key not in precon_cache_keys, self.state.solver.constraints))\n\n\n        if self.state.has_plugin(\"zen_plugin\"):\n            new_constraints = self.state.get_plugin(\"zen_plugin\").filter_constraints(new_constraints)\n\n        if to_composite_solver:\n            self.state.options.discard(o.REPLACEMENT_SOLVER)\n            self.state.options.add(o.COMPOSITE_SOLVER)\n\n        # clear the solver's internal memory and replace it with the new solver options and constraints\n        self.state.solver.reload_solver(new_constraints)\n\n        if simplify:\n            l.debug(\"simplifying solver...\")\n            self.state.solver.simplify()\n            l.debug(\"...simplification done\")\n\n    def reconstrain(self):\n        \"\"\"\n        Split the solver. If any of the subsolvers time out after a short timeout (10 seconds), re-add the\n        preconstraints associated with each of its variables. Hopefully these constraints still allow us to do\n        meaningful things to the state.\n        \"\"\"\n\n        # test all solver splits\n        subsolvers = self.state.solver._solver.split()\n\n        for solver in subsolvers:\n            solver.timeout = 1000 * 10  # 10 seconds\n            if not solver.satisfiable():\n                for var in solver.variables:\n                    if var in self.variable_map:\n                        self.state.add_constraints(self.variable_map[var])\n                    else:\n                        l.warning(\"var %s not found in self.variable_map\", var)\n\n\nfrom angr.sim_state import SimState\nSimState.register_default('preconstrainer', SimStatePreconstrainer)\n", "path": "angr/state_plugins/preconstrainer.py"}]}