From 64d1ed51f2d4f6e64c95461f74d4e083abf0b4e8 Mon Sep 17 00:00:00 2001 From: Yan Date: Thu, 4 May 2017 17:36:39 -0400 Subject: [PATCH] Decode instruction early (#205) * Move PC verification to decode_instruction * Decode instruction in executor * Fix unicorn tests * remove decoded_pc * use issymbolic() --- manticore/core/cpu/abstractcpu.py | 34 +++++++++++++++++++------------ manticore/core/executor.py | 3 +++ tests/test_unicorn.py | 4 ++-- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/manticore/core/cpu/abstractcpu.py b/manticore/core/cpu/abstractcpu.py index 2233d68..607e48a 100644 --- a/manticore/core/cpu/abstractcpu.py +++ b/manticore/core/cpu/abstractcpu.py @@ -360,12 +360,20 @@ class Cpu(object): def decode_instruction(self, pc): ''' - This will decode an instruction from memory pointed by @pc + This will decode an instruction from memory pointed by `pc` and store + it in self.instruction. :param int pc: address of the instruction ''' - #No dynamic code!!! #TODO! - #Check if instruction was already decoded + # No dynamic code!!! #TODO! + + if issymbolic(pc): + raise SymbolicPCException() + + if not self.memory.access_ok(pc,'x'): + raise InvalidPCException(pc) + + #Check if instruction was already decoded self._instruction_cache = {} if pc in self._instruction_cache: logger.debug("Intruction cache hit at %x", pc) @@ -394,16 +402,16 @@ class Cpu(object): #PC points to symbolic memory if instruction.size > len(text): logger.info("Trying to execute instructions from invalid memory") - raise InvalidPCException(self.PC) + raise InvalidPCException(pc) if not self.memory.access_ok(slice(pc, pc+instruction.size), 'x'): logger.info("Trying to execute instructions from non-executable memory") - raise InvalidPCException(self.PC) + raise InvalidPCException(pc) instruction.operands = self._wrap_operands(instruction.operands) self._instruction_cache[pc] = instruction - return instruction + self.instruction = instruction ####################################### @@ -416,15 +424,15 @@ class Cpu(object): pass def execute(self): - ''' Decode, and execute one instruction pointed by register PC''' - if not isinstance(self.PC, (int,long)): - raise SymbolicPCException() + ''' + Decode, and execute one instruction pointed by register PC + ''' - if not self.memory.access_ok(self.PC,'x'): - raise InvalidPCException(self.PC) + # Decode the instruction if it wasn't explicitly decoded + if self.instruction is None or self.instruction.address != self.PC: + self.decode_instruction(self.PC) - instruction = self.decode_instruction(self.PC) - self.instruction = instruction #FIX + instruction = self.instruction name = self.canonicalize_instruction_name(instruction) diff --git a/manticore/core/executor.py b/manticore/core/executor.py index 8688a17..5d97e3b 100644 --- a/manticore/core/executor.py +++ b/manticore/core/executor.py @@ -664,6 +664,9 @@ class Executor(object): # allow us to terminate manticore processes while not self.isShutdown(): + # Make sure current instruction is decoded so that hooks can access it + current_state.cpu.decode_instruction(current_state.cpu.PC) + # Announce that we're about to execute self.will_execute_pc(current_state) diff --git a/tests/test_unicorn.py b/tests/test_unicorn.py index 2ca5b26..c5691e1 100644 --- a/tests/test_unicorn.py +++ b/tests/test_unicorn.py @@ -34,9 +34,9 @@ def assemble(asm): def emulate_next(cpu): 'Read the next instruction and emulate it with Unicorn ' - instruction = cpu.decode_instruction(cpu.PC) + cpu.decode_instruction(cpu.PC) emu = UnicornEmulator(cpu) - emu.emulate(instruction) + emu.emulate(cpu.instruction) def itest(asm):