def evaluate_lines(instr, lines, in_str): # Run the emulation of the basic bloc machine = mapper() def print_machine(machine): return sorted(str(machine).split("\n")) # Emulation with amoco is too slow # For 'movsd' tests depending of 'df' are not simplified, therefore there # are too many nested tests # For 'cmovXX' tests are not simplified either perf_count = {'movsd': 0, 'cmov': 0} for line in lines: # rip is kept symbolic if line.opname in ('call', 'jmp'): machine[env.rip] = env.rip else: machine[env.rip] = env.rip - line.bytelen if line.opname == 'movsd': perf_count['movsd'] += 1 if perf_count['movsd'] >= 3: return (('Emulated too slow (movsd)', line, print_machine(machine)), [None]) if line.opname.startswith('cmov'): perf_count['cmov'] += 1 if perf_count['cmov'] >= 3: return (('Emulated too slow (cmov)', line, print_machine(machine)), [None]) try: log.debug("EVAL %-20r %s", line.amoco.bytes, line) line.amoco(machine) except NotImplementedError: return (('Not implemented', line, print_machine(machine)), [None]) except NameError: return (('Cannot be emulated (name)', line, print_machine(machine)), [None]) except amoco.arch.core.InstructionError: return (('Cannot be emulated', line, print_machine(machine)), [None]) except TypeError: return (('Not callable', line, print_machine(machine)), [None]) if line.opname == 'call': # amoco emulation pushes rip+i.length # we prefer to push the label of the next basic bloc label = instr.symbols.find_symbol(section=line.section, address=line.offset + line.amoco.length) machine[env.mem(env.rsp, cpu_addrsize)] = expressions.lab(label, size=cpu_addrsize) retval = machine[env.rip] msg, val = evaluate(retval, machine, instr.symbols.find_symbols, instr, in_str) if val is None: return ((str(retval.__class__), retval, print_machine(machine)), [None]) elif val == [None]: return ((msg, retval, print_machine(machine)), [None]) else: return (msg, val)
def test_mapper_001(): # create three instructions # movq %rax, (%rip) # movl %eax, (%rip) # movq -16(%rbp), %rcx i0 = cpu.disassemble(b"\x48\x89\x05\x00\x00\x00\x00") i1 = cpu.disassemble(b"\x89\x05\x00\x00\x00\x00") i2 = cpu.disassemble(b"\x48\x8b\x4d\xf0") # modify the first two instructions to insert a label # movq %rax, foo(%rip) i0.operands[0].a.disp = expressions.lab('foo', size=64) # movb %eax, bar(%rip) i1.operands[0].a.disp = expressions.lab('bar', size=64) # evaluate those three instructions m = mapper() i0(m) i1(m) i2(m) assert str(m[rcx]) == 'M64(rbp-16)'
def test_mapper_000(): # create two instructions # movq %rcx, (%rip) # movq (%rip), %rcx i0 = cpu.disassemble(b"\x48\x89\x0d\x00\x00\x00\x00") i1 = cpu.disassemble(b"\x48\x8b\x0d\x00\x00\x00\x00") # modify the first instruction to insert a label, e.g. because # there is a relocation # movq %rcx, foo(%rip) i0.operands[0].a.disp = expressions.lab('foo', size=64) # evaluate those two instructions m = mapper() i0(m) i1(m) assert str(m[rcx]) == 'M64(rip+14)'
def action_term(toks): if isinstance(toks[0], str): return expressions.lab(toks[0],size=att_syntax.cpu_addrsize)