Open axt opened 8 years ago
Interesting...
It looks like a brand new plugin is being created while you're copying, either regs
(though then printing rax
should have no effect; just grabbing the regs
plugin would cause the bug) or registers
(when you're accessing regs.rax
, though it's surprising that it doesn't already exist). Could you print out state.plugins.keys()
at every step of the process (before copying, at the beginning of SimStateTest.copy()
, and at the end of SimStateTest.copy()
)? I think that'll let us track it down pretty quickly.
BEFORE ['solver_engine', 'scratch', 'regs', 'registers', 'procedure_data', 'memory', 'test', 'posix'] AFTER ['log', 'solver_engine', 'scratch', 'regs', 'registers', 'procedure_data', 'memory', 'test', 'posix']
With just print regs.ip
in the step
function. The 'log' plugin is missing in the first step.
BEFORE ['solver_engine', 'scratch', 'regs', 'registers', 'procedure_data', 'memory', 'test', 'posix']
<BV32 0x804841d>
AFTER ['solver_engine', 'scratch', 'regs', 'registers', 'procedure_data', 'memory', 'test', 'posix']
BEFORE ['log', 'solver_engine', 'scratch', 'regs', 'registers', 'procedure_data', 'memory', 'test', 'posix']
<BV32 0x804842b>
AFTER ['log', 'solver_engine', 'scratch', 'regs', 'registers', 'procedure_data', 'memory', 'test', 'posix']
BEFORE ['log', 'solver_engine', 'scratch', 'regs', 'registers', 'procedure_data', 'memory', 'test', 'posix']
<BV32 0x804842d>
AFTER ['log', 'solver_engine', 'scratch', 'regs', 'registers', 'procedure_data', 'memory', 'test', 'posix']
[...]
Ah, interesting... Your access of rax
was logging a SimAction
, which, in turn, created the log
plugin. ip
is explicitly filtered out from action logging, IIRC, so in the later case, the log was probably created in the course of processing the actual basic block, rather than during copying.
We have a few potential ways forward:
items
instead of iteritems
in that dict comprehension in SimState.copy
. That's probably the easiest fix, though it feels a tad hackish.angr.SimOS
, but that's also a bandaid because this issue can occur with plugins other than log
, of course.log
.I guess the first option seems best?
With option 1, since we will only copy the plugins which existed before call to the copy
function, will we not loose the state of the on-demand created plugin from the target state?
Regarding the other question: in a long term solution, i think it could be great if you could choose that your access to the registers, etc should be reflected in SimActions or not. Don't know what is the right way to do it, wouldn't be nice to touch the API because of this. Maybe something like:
with SimActions.transparent():
print self.state.regs.eax
I've tried to understand the plugins code more deeper since then. I see now, that probably its not a valid use-case to access the registers in the copy
function. I did it only because I wanted to see how the state propagates. So maybe there is no fix needed at all for this.
We'll lose the state, but since we copy the plugins sequentially anyways, we'd lose the state of the earlier ones if the later ones modify them afterwards.
You're right in that complex operations aren't intended to be done during state copying, but I'm not sure if we want to have it explicitly forbidden. Might be good to do a best-effort support of it, at least using iter
instead of iteritems
(until Python 3 support rolls around).
In terms of the context manager for turning off actions, I think that'd be really cool, state copying aside! We already have state.with_condition()
, and adding some sort of state.with_options()
or state.without_options()
would be really cool as well. We should keep that in mind when there's a free minute to implement it!
I'm trying to add a simuvex plugin the following way:
It works fine. If I remove the
#
in front ofprint regs.eax
in thecopy
function, I get the following error: