#! /usr/bin/env python2 #-*- coding:utf-8 -*- import unittest import logging from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.arch.arm.arch import mn_arm as mn from miasm2.arch.arm.sem import ir_arml as ir_arch from miasm2.arch.arm.regs import * from miasm2.expression.expression import * from miasm2.core.locationdb import LocationDB from pdb import pm logging.getLogger('cpuhelper').setLevel(logging.ERROR) EXCLUDE_REGS = set([ir_arch().IRDst]) def M(addr): return ExprMem(ExprInt(addr, 16), 16) def compute(asm, inputstate={}, debug=False): loc_db = LocationDB() sympool = dict(regs_init) sympool.update({k: ExprInt(v, k.size) for k, v in inputstate.iteritems()}) ir_tmp = ir_arch(loc_db) ircfg = ir_tmp.new_ircfg() symexec = SymbolicExecutionEngine(ir_tmp, sympool) instr = mn.fromstring(asm, loc_db, "l") code = mn.asm(instr)[0] instr = mn.dis(code, "l") instr.offset = inputstate.get(PC, 0) lbl = ir_tmp.add_instr_to_ircfg(instr, ircfg) symexec.run_at(ircfg, lbl) if debug: for k, v in symexec.symbols.items(): if regs_init.get(k, None) != v: print k, v out = {} for k, v in symexec.symbols.items(): if k in EXCLUDE_REGS: continue elif regs_init.get(k, None) == v: continue elif isinstance(v, ExprInt): out[k] = long(v) else: out[k] = v return out class TestARMSemantic(unittest.TestCase): # def test_condition(self): # §A8.3: Conditional execution # pass def test_shift(self): # §A8.4: Shifts applied to a register self.assertEqual( compute('MOV R4, R4 ', {R4: 0xDEADBEEFL, }), {R4: 0xDEADBEEFL, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 LSL 0') self.assertEqual( compute('MOV R4, R4 LSL 1', {R4: 0xDEADBEEFL, }), {R4: 0xBD5B7DDEL, }) self.assertEqual( compute('MOV R4, R4 LSL 16', {R4: 0xDEADBEEFL, }), {R4: 0xBEEF0000L, }) self.assertEqual( compute('MOV R4, R4 LSL 31', {R4: 0xDEADBEEFL, }), {R4: 0x80000000L, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 LSL 32') self.assertEqual( compute('MOV R4, R4 LSL R5', {R4: 0xDEADBEEFL, R5: 0xBADBAD01L, }), {R4: 0xBD5B7DDEL, R5: 0xBADBAD01L, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 LSR 0') self.assertEqual( compute('MOV R4, R4 LSR 1', {R4: 0xDEADBEEFL, }), {R4: 0x6F56DF77L, }) self.assertEqual( compute('MOV R4, R4 LSR 16', {R4: 0xDEADBEEFL, }), {R4: 0x0000DEADL, }) self.assertEqual( compute('MOV R4, R4 LSR 31', {R4: 0xDEADBEEFL, }), {R4: 0x00000001L, }) self.assertEqual( compute('MOV R4, R4 LSR 32', {R4: 0xDEADBEEFL, }), {R4: 0xDEADBEEFL, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 LSR 33') self.assertEqual( compute('MOV R4, R4 LSR R5', {R4: 0xDEADBEEFL, R5: 0xBADBAD01L, }), {R4: 0x6F56DF77L, R5: 0xBADBAD01L, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 ASR 0') self.assertEqual( compute('MOV R4, R4 ASR 1', {R4: 0xDEADBEEFL, }), {R4: 0xEF56DF77L, }) self.assertEqual( compute('MOV R4, R4 ASR 16', {R4: 0xDEADBEEFL, }), {R4: 0xFFFFDEADL, }) self.assertEqual( compute('MOV R4, R4 ASR 31', {R4: 0xDEADBEEFL, }), {R4: 0xFFFFFFFFL, }) self.assertEqual( compute('MOV R4, R4 ASR 32', {R4: 0xDEADBEEFL, }), {R4: 0xDEADBEEFL, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 ASR 33') self.assertEqual( compute('MOV R4, R4 ASR R5', {R4: 0xDEADBEEFL, R5: 0xBADBAD01L, }), {R4: 0xEF56DF77L, R5: 0xBADBAD01L, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 ROR 0') self.assertEqual( compute('MOV R4, R4 ROR 1', {R4: 0xDEADBEEFL, }), {R4: 0xEF56DF77L, }) self.assertEqual( compute('MOV R4, R4 ROR 16', {R4: 0xDEADBEEFL, }), {R4: 0xBEEFDEADL, }) self.assertEqual( compute('MOV R4, R4 ROR 31', {R4: 0xDEADBEEFL, }), {R4: 0xBD5B7DDFL, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 ROR 32') self.assertEqual( compute('MOV R4, R4 ROR R5', {R4: 0xDEADBEEFL, R5: 0xBADBAD01L, }), {R4: 0xEF56DF77L, R5: 0xBADBAD01L, }) self.assertEqual(compute('MOV R4, R4 RRX ', {cf: 0L, R4: 0xDEADBEEFL, }), { cf: 0L, R4: 0x6F56DF77L, }) self.assertEqual(compute('MOV R4, R4 RRX ', {cf: 1L, R4: 0xDEADBEEFL, }), { cf: 1L, R4: 0xEF56DF77L, }) def test_ADC(self): # §A8.8.1: ADC{S}{}{} {,} , # self.assertRaises( ValueError, compute, 'ADC R4, 0x00000001 ') self.assertEqual(compute('ADC R4, R4, 0x00000001 ', { cf: 0L, R4: 0x00000000L, }), {cf: 0L, R4: 0x00000001L, }) self.assertEqual(compute('ADC R4, R4, 0x00000000 ', { cf: 1L, R4: 0x00000000L, }), {cf: 1L, R4: 0x00000001L, }) self.assertEqual(compute('ADC PC, R4, 0x00000001 ', { cf: 0L, R4: 0xFFFFFFFFL, PC: 0x55555555L, }), {cf: 0L, R4: 0xFFFFFFFFL, PC: 0x00000000L, }) self.assertEqual(compute('ADC PC, R4, 0x00000000 ', { cf: 1L, R4: 0xFFFFFFFFL, PC: 0x55555555L, }), {cf: 1L, R4: 0xFFFFFFFFL, PC: 0x00000000L, }) self.assertEqual(compute('ADCS R4, R4, 0x80000000 ', {cf: 0L, R4: 0x80000000L, }), { nf: 0L, zf: 1L, cf: 1L, of: 1L, R4: 0x00000000L, }) self.assertEqual(compute('ADCS R4, R4, 0xFF000000 ', {cf: 1L, R4: 0x00FFFFFEL, }), { nf: 1L, zf: 0L, cf: 0L, of: 0L, R4: 0xFFFFFFFFL, }) self.assertEqual(compute('ADCS PC, R4, 0x00000000 ', { cf: 0L, R4: 0x00000000L, PC: 0x55555555L, }), {cf: 0L, R4: 0x00000000L, PC: 0x00000000L, }) self.assertEqual(compute('ADCS PC, R4, 0xFF000000 ', { cf: 1L, R4: 0x01000000L, PC: 0x55555555L, }), {cf: 1L, R4: 0x01000000L, PC: 0x00000001L, }) # §A8.8.2: ADC{S}{}{} {,} , {,} self.assertRaises( ValueError, compute, 'ADC R4, R5 ') self.assertEqual(compute('ADC R4, R4, R5 ', { cf: 1L, R4: 0xFFFFFFFFL, R5: 0x00000000L, }), {cf: 1L, R4: 0x00000000L, R5: 0x00000000L, }) self.assertEqual(compute('ADC R4, R4, R5 LSL 1 ', { cf: 0L, R4: 0x00000001L, R5: 0x00000008L, }), {cf: 0L, R4: 0x00000011L, R5: 0x00000008L, }) self.assertEqual(compute('ADC R4, R4, R5 LSR 2 ', { cf: 1L, R4: 0x00000000L, R5: 0x80000041L, }), {cf: 1L, R4: 0x20000011L, R5: 0x80000041L, }) self.assertEqual(compute('ADC R4, R4, R5 ASR 3 ', { cf: 0L, R4: 0x00000001L, R5: 0x80000081L, }), {cf: 0L, R4: 0xF0000011L, R5: 0x80000081L, }) self.assertEqual(compute('ADC R4, R4, R5 ROR 4 ', { cf: 1L, R4: 0xFFFFFFFFL, R5: 0x0000010FL, }), {cf: 1L, R4: 0xF0000010L, R5: 0x0000010FL, }) self.assertEqual(compute('ADC R4, R4, R5 RRX ', { cf: 1L, R4: 0xFFFFFFFFL, R5: 0x00000101L, }), {cf: 1L, R4: 0x80000080L, R5: 0x00000101L, }) self.assertEqual(compute('ADCS R4, R4, R5 ', {cf: 1L, R4: 0xFFFFFFFFL, R5: 0x00000000L, }), { nf: 0L, zf: 1L, cf: 1L, of: 0L, R4: 0x00000000L, R5: 0x00000000L, }) self.assertEqual(compute('ADCS R4, R4, R5 LSL 1 ', {cf: 0L, R4: 0x00000001L, R5: 0x00000008L, }), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R4: 0x00000011L, R5: 0x00000008L, }) self.assertEqual(compute('ADCS R4, R4, R5 LSR 2 ', {cf: 1L, R4: 0x00000000L, R5: 0x80000041L, }), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R4: 0x20000011L, R5: 0x80000041L, }) self.assertEqual(compute('ADCS R4, R4, R5 ASR 3 ', {cf: 0L, R4: 0x00000001L, R5: 0x80000081L, }), { nf: 1L, zf: 0L, cf: 0L, of: 0L, R4: 0xF0000011L, R5: 0x80000081L, }) self.assertEqual(compute('ADCS R4, R4, R5 ROR 4 ', {cf: 1L, R4: 0xFFFFFFFFL, R5: 0x0000010FL, }), { nf: 1L, zf: 0L, cf: 1L, of: 0L, R4: 0xF0000010L, R5: 0x0000010FL, }) self.assertEqual(compute('ADCS R4, R4, R5 RRX ', {cf: 1L, R4: 0xFFFFFFFFL, R5: 0x00000101L, }), { nf: 1L, zf: 0L, cf: 1L, of: 0L, R4: 0x80000080L, R5: 0x00000101L, }) # §A8.8.3: ADC{S}{}{} {,} , , self.assertEqual(compute('ADC R4, R6, R4 LSL R5', { cf: 0L, R4: 0x00000001L, R5: 0x00000004L, R6: 0L, }), {cf: 0L, R4: 0x00000010L, R5: 0x00000004L, R6: 0L, }) self.assertEqual(compute('ADC R4, R6, R4 LSR R5', { cf: 1L, R4: 0x00000110L, R5: 0x80000004L, R6: 0L, }), {cf: 1L, R4: 0x00000012L, R5: 0x80000004L, R6: 0L, }) self.assertEqual(compute('ADC R4, R6, R4 ASR R5', { cf: 0L, R4: 0x80000010L, R5: 0xF0000001L, R6: 0L, }), {cf: 0L, R4: 0xC0000008L, R5: 0xF0000001L, R6: 0L, }) self.assertEqual(compute('ADC R4, R6, R4 ROR R5', { cf: 1L, R4: 0x000000FFL, R5: 0x00000F04L, R6: 0L, }), {cf: 1L, R4: 0xF0000010L, R5: 0x00000F04L, R6: 0L, }) self.assertEqual(compute('ADCS R4, R6, R4 LSL R5', {cf: 0L, R4: 0x00000001L, R5: 0x00000004L, R6: 0L, }), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R4: 0x00000010L, R5: 0x00000004L, R6: 0L, }) self.assertEqual(compute('ADCS R4, R6, R4 LSR R5', {cf: 1L, R4: 0x00000110L, R5: 0x80000004L, R6: 0L, }), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R4: 0x00000012L, R5: 0x80000004L, R6: 0L, }) self.assertEqual(compute('ADCS R4, R6, R4 ASR R5', {cf: 0L, R4: 0x80000010L, R5: 0xF0000001L, R6: 0L, }), { nf: 1L, zf: 0L, cf: 0L, of: 0L, R4: 0xC0000008L, R5: 0xF0000001L, R6: 0L, }) self.assertEqual(compute('ADCS R4, R6, R4 ROR R5', {cf: 1L, R4: 0x000000FFL, R5: 0x00000F04L, R6: 0L, }), { nf: 1L, zf: 0L, cf: 0L, of: 0L, R4: 0xF0000010L, R5: 0x00000F04L, R6: 0L, }) def test_ADD(self): # §A8.8.{5,9}: ADD{S}{}{} {,} , # self.assertRaises( ValueError, compute, 'ADD R4, 0x00000001L ') self.assertEqual(compute('ADD R4, R4, 0x00000001 ', { R4: 0x00000000L, }), {R4: 0x00000001L, }) self.assertEqual(compute('ADD R4, R4, 0x00000000 ', { R4: 0x00000000L, }), {R4: 0x00000000L, }) self.assertEqual(compute('ADD PC, R4, 0x00000001 ', { R4: 0xFFFFFFFFL, PC: 0x55555555L, }), {R4: 0xFFFFFFFFL, PC: 0x00000000L, }) self.assertEqual(compute('ADD PC, R4, 0x00000000 ', { R4: 0xFFFFFFFFL, PC: 0x55555555L, }), {R4: 0xFFFFFFFFL, PC: 0xFFFFFFFFL, }) self.assertEqual(compute('ADDS R4, R4, 0x80000000 ', {R4: 0x80000000L, }), { nf: 0L, zf: 1L, cf: 1L, of: 1L, R4: 0x00000000L, }) self.assertEqual(compute('ADDS R4, R4, 0xFF000000 ', {R4: 0x00FFFFFEL, }), { nf: 1L, zf: 0L, cf: 0L, of: 0L, R4: 0xFFFFFFFEL, }) self.assertEqual(compute('ADDS PC, R4, 0x00000000 ', { R4: 0x00000000L, PC: 0x55555555L, }), {R4: 0x00000000L, PC: 0x00000000L, }) self.assertEqual(compute('ADDS PC, R4, 0xFF000000 ', { R4: 0x01000000L, PC: 0x55555555L, }), {R4: 0x01000000L, PC: 0x00000000L, }) # SP special part self.assertEqual(compute('ADD R4, SP, 0x00000001 ', { R4: 0x00000000L, SP: 0x00000000L, }), {R4: 0x00000001L, SP: 0x00000000L, }) # §A8.8.{7,11}: ADD{S}{}{} {,} , {,} self.assertRaises( ValueError, compute, 'ADD R4, R5 ') self.assertEqual(compute('ADD R4, R4, R5 ', { R4: 0xFFFFFFFFL, R5: 0x00000001L, }), {R4: 0x00000000L, R5: 0x00000001L, }) self.assertEqual(compute('ADD R4, R4, R5 LSL 1 ', { R4: 0x00000001L, R5: 0x00000008L, }), {R4: 0x00000011L, R5: 0x00000008L, }) self.assertEqual(compute('ADD R4, R4, R5 LSR 2 ', { R4: 0x00000000L, R5: 0x80000041L, }), {R4: 0x20000010L, R5: 0x80000041L, }) self.assertEqual(compute('ADD R4, R4, R5 ASR 3 ', { R4: 0x00000001L, R5: 0x80000081L, }), {R4: 0xF0000011L, R5: 0x80000081L, }) self.assertEqual(compute('ADD R4, R4, R5 ROR 4 ', { R4: 0xFFFFFFFFL, R5: 0x0000010FL, }), {R4: 0xF000000FL, R5: 0x0000010FL, }) self.assertEqual(compute('ADD R4, R4, R5 RRX ', { cf: 1L, R4: 0xFFFFFFFFL, R5: 0x00000101L, }), {cf: 1L, R4: 0x8000007FL, R5: 0x00000101L, }) self.assertEqual(compute('ADDS R4, R4, R5 ', {R4: 0xFFFFFFFFL, R5: 0x00000001L, }), { nf: 0L, zf: 1L, cf: 1L, of: 0L, R4: 0x00000000L, R5: 0x00000001L, }) self.assertEqual(compute('ADDS R4, R4, R5 LSL 1 ', {R4: 0x00000001L, R5: 0x00000008L, }), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R4: 0x00000011L, R5: 0x00000008L, }) self.assertEqual(compute('ADDS R4, R4, R5 LSR 2 ', {R4: 0x00000000L, R5: 0x80000041L, }), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R4: 0x20000010L, R5: 0x80000041L, }) self.assertEqual(compute('ADDS R4, R4, R5 ASR 3 ', {R4: 0x00000001L, R5: 0x80000081L, }), { nf: 1L, zf: 0L, cf: 0L, of: 0L, R4: 0xF0000011L, R5: 0x80000081L, }) self.assertEqual(compute('ADDS R4, R4, R5 ROR 4 ', {R4: 0xFFFFFFFFL, R5: 0x0000010FL, }), { nf: 1L, zf: 0L, cf: 1L, of: 0L, R4: 0xF000000FL, R5: 0x0000010FL, }) self.assertEqual(compute('ADDS R4, R4, R5 RRX ', {cf: 1L, R4: 0xFFFFFFFFL, R5: 0x00000101L, }), { nf: 1L, zf: 0L, cf: 1L, of: 0L, R4: 0x8000007FL, R5: 0x00000101L, }) # SP special part self.assertEqual(compute('ADD R4, SP, R4 LSR 1 ', { R4: 0x00000002L, SP: 0x00000000L, }), {R4: 0x00000001L, SP: 0x00000000L, }) # §A8.8.8: ADD{S}{}{} {,} , , self.assertEqual(compute('ADD R4, R6, R4 LSL R5', { R4: 0x00000001L, R5: 0x00000004L, R6: 0L, }), {R4: 0x00000010L, R5: 0x00000004L, R6: 0L, }) self.assertEqual(compute('ADD R4, R6, R4 LSR R5', { R4: 0x00000110L, R5: 0x80000004L, R6: 0L, }), {R4: 0x00000011L, R5: 0x80000004L, R6: 0L, }) self.assertEqual(compute('ADD R4, R6, R4 ASR R5', { R4: 0x80000010L, R5: 0xF0000001L, R6: 0L, }), {R4: 0xC0000008L, R5: 0xF0000001L, R6: 0L, }) self.assertEqual(compute('ADD R4, R6, R4 ROR R5', { R4: 0x000000FFL, R5: 0x00000F04L, R6: 0L, }), {R4: 0xF000000FL, R5: 0x00000F04L, R6: 0L, }) self.assertEqual(compute('ADDS R4, R6, R4 LSL R5', {R4: 0x00000001L, R5: 0x00000004L, R6: 0L, }), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R4: 0x00000010L, R5: 0x00000004L, R6: 0L, }) self.assertEqual(compute('ADDS R4, R6, R4 LSR R5', {R4: 0x00000110L, R5: 0x80000004L, R6: 0L, }), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R4: 0x00000011L, R5: 0x80000004L, R6: 0L, }) self.assertEqual(compute('ADDS R4, R6, R4 ASR R5', {R4: 0x80000010L, R5: 0xF0000001L, R6: 0L, }), { nf: 1L, zf: 0L, cf: 0L, of: 0L, R4: 0xC0000008L, R5: 0xF0000001L, R6: 0L, }) self.assertEqual(compute('ADDS R4, R6, R4 ROR R5', {R4: 0x000000FFL, R5: 0x00000F04L, R6: 0L, }), { nf: 1L, zf: 0L, cf: 0L, of: 0L, R4: 0xF000000FL, R5: 0x00000F04L, R6: 0L, }) # Test against qemu self.assertEqual(compute('ADDS R3, R2, R3 ', {R2: 0x1L, R3: 0x1L}), { nf: 0L, zf: 0L, cf: 0L, of: 0L, R2: 0x00000001L, R3: 0x00000002L}) self.assertEqual(compute('ADDS R3, R2, R3 ', {R2: 0x1L, R3: 0x7FFFFFFFL}), { nf: 1L, zf: 0L, cf: 0L, of: 1L, R2: 0x00000001L, R3: 0x80000000L}) self.assertEqual(compute('ADDS R3, R2, R3 ', {R2: 0x80000000L, R3: 0x80000000L}), { nf: 0L, zf: 1L, cf: 1L, of: 1L, R2: 0x80000000L, R3: 0x00000000L}) self.assertEqual(compute('ADDS R3, R2, R3 ', {R2: 0x7FFFFFFFL, R3:0x7FFFFFFFL}), { nf: 1L, zf: 0L, cf: 0L, of: 1L, R2: 0x7FFFFFFFL, R3:0xFFFFFFFEL}) self.assertEqual(compute('ADDS R3, R2, R3 ', {R2: 0L, R3:0}), { nf: 0L, zf: 1L, cf: 0L, of: 0L, R2: 0L, R3:0}) self.assertEqual(compute('ADDS R3, R2, R3 ', {R2: 0xFFFFFFFFL, R3:0xFFFFFFFFL}), { nf: 1L, zf: 0L, cf: 1L, of: 0L, R2: 0xFFFFFFFFL, R3:0xFFFFFFFEL}) def test_ADR(self): # §A8.8.12: ADR{}{} ,