Skip to content

Commit 9f57894

Browse files
authored
Revamp Python regression tests suite (#2022)
* Fix Python regression test suite (partial) * Fix Python regression test suite * Add a test for mapping at high addresses * Add ctl tests
1 parent 78580ca commit 9f57894

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1944
-1496
lines changed

tests/regress/arm_bx_unmapped.py

+95-77
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,111 @@
1-
from __future__ import print_function
1+
2+
import regress
3+
24
from unicorn import *
35
from unicorn.arm_const import *
4-
import regress
56

6-
# code to be emulated
7-
'''
8-
ins = {
9-
0x00008cd4: """
10-
push {r11}
11-
add r11, sp, #0
12-
mov r3, pc
13-
mov r0, r3
14-
sub sp, r11, #0
15-
pop {r11}
16-
bx lr
17-
""",
18-
0x00008cf0: """
19-
push {r11}
20-
add r11, sp, #0
21-
push {r6}
22-
add r6, pc, $1
23-
bx r6
24-
.code 16
25-
mov r3, pc
26-
add r3, $0x4
27-
push {r3}
28-
pop {pc}
29-
.code 32
30-
pop {r6}
31-
mov r0, r3
32-
sub sp, r11, #0
33-
pop {r11}
34-
bx lr
35-
""",
36-
0x00008d20: """
37-
push {r11}
38-
add r11, sp, #0
39-
mov r3, lr
40-
mov r0, r3
41-
sub sp, r11, #0
42-
pop {r11}
43-
bx lr
44-
""",
45-
0x00008d68: "bl 0x8cd4\n"
46-
"mov r4, r0\n"
47-
"bl 0x8cf0\n"
48-
"mov r3, r0\n"
49-
"add r4, r4, r3\n"
50-
"bl 0x8d20\n"
51-
"mov r3, r0\n"
52-
"add r2, r4, r3",
53-
}
54-
'''
7+
8+
MAIN_ADDRESS = 0x8d68
9+
ADDRESS = MAIN_ADDRESS & ~(0x1000 - 1)
10+
STACK_ADDR = ADDRESS + 0x1000
11+
5512

5613
class BxTwiceTest(regress.RegressTest):
5714
def runTest(self):
58-
ADDRESS = 0x8000
59-
MAIN_ADDRESS = 0x8d68
60-
STACK_ADDR = ADDRESS + 0x1000
61-
15+
# code to be emulated
6216
code = {
63-
0x8cf0: '\x04\xb0-\xe5\x00\xb0\x8d\xe2\x04`-\xe5\x01`\x8f\xe2\x16\xff/\xe1{F\x03\xf1\x04\x03\x08\xb4\x00\xbd\x00\x00\x04`\x9d\xe4\x03\x00\xa0\xe1\x00\xd0K\xe2\x04\xb0\x9d\xe4\x1e\xff/\xe1',
64-
0x8d20: '\x04\xb0-\xe5\x00\xb0\x8d\xe2\x0e0\xa0\xe1\x03\x00\xa0\xe1\x00\xd0K\xe2\x04\xb0\x9d\xe4\x1e\xff/\xe1',
65-
0x8cd4: '\x04\xb0-\xe5\x00\xb0\x8d\xe2\x0f0\xa0\xe1\x03\x00\xa0\xe1\x00\xd0K\xe2\x04\xb0\x9d\xe4\x1e\xff/\xe1',
66-
0x8d68: '\xd9\xff\xff\xeb\x00@\xa0\xe1\xde\xff\xff\xeb\x000\xa0\xe1\x03@\x84\xe0\xe7\xff\xff\xeb\x000\xa0\xe1\x03 \x84\xe0'
17+
0x8cd4: (
18+
b'\x04\xb0\x2d\xe5' # 8cd4 push {r11}
19+
b'\x00\xb0\x8d\xe2' # 8cd8 add r11, sp, #0
20+
b'\x0f\x30\xa0\xe1' # 8cdc mov r3, pc
21+
b'\x03\x00\xa0\xe1' # 8ce0 mov r0, r3
22+
b'\x00\xd0\x4b\xe2' # 8ce4 sub sp, r11, #0
23+
b'\x04\xb0\x9d\xe4' # 8ce8 pop {r11}
24+
b'\x1e\xff\x2f\xe1' # 8cec bx lr
25+
),
26+
0x8cf0: (
27+
b'\x04\xb0\x2d\xe5' # 8cf0 push {r11}
28+
b'\x00\xb0\x8d\xe2' # 8cf4 add r11, sp, #0
29+
b'\x04\x60\x2d\xe5' # 8cf8 push {r6}
30+
b'\x01\x60\x8f\xe2' # 8cfc add r6, pc, $1
31+
b'\x16\xff\x2f\xe1' # 8d00 bx r6
32+
# .thumb
33+
b'\x7b\x46' # 8d04 mov r3, pc
34+
b'\x03\xf1\x08\x03' # 8d06 add r3, $0x8 # elicn: used to be $0x4 but it kept failing
35+
b'\x08\xb4' # 8d0a push {r3}
36+
b'\x00\xbd' # 8d0c pop {pc}
37+
b'\x00\x00' # 8d0e (alignment)
38+
# .arm
39+
b'\x04\x60\x9d\xe4' # 8d10 pop {r6}
40+
b'\x03\x00\xa0\xe1' # 8d14 mov r0, r3
41+
b'\x00\xd0\x4b\xe2' # 8d18 sub sp, r11, #0
42+
b'\x04\xb0\x9d\xe4' # 8d1c pop {r11}
43+
b'\x1e\xff\x2f\xe1' # 8d20 bx lr
44+
),
45+
0x8d24: ( # elicn: used to be 0x8d20 but it caused this block to overlap with the previous one
46+
b'\x04\xb0\x2d\xe5' # 8d24 push {r11}
47+
b'\x00\xb0\x8d\xe2' # 8d28 add r11, sp, #0
48+
b'\x0e\x30\xa0\xe1' # 8d2c mov r3, lr
49+
b'\x03\x00\xa0\xe1' # 8d20 mov r0, r3
50+
b'\x00\xd0\x4b\xe2' # 8d34 sub sp, r11, #0
51+
b'\x04\xb0\x9d\xe4' # 8d38 pop {r11}
52+
b'\x1e\xff\x2f\xe1' # 8d3c bx lr
53+
),
54+
0x8d68: (
55+
b'\xd9\xff\xff\xeb' # 8d68 bl 0x8cd4 <-- MAIN_ADDRESS
56+
b'\x00\x40\xa0\xe1' # 8d6c mov r4, r0
57+
b'\xde\xff\xff\xeb' # 8d70 bl 0x8cf0
58+
b'\x00\x30\xa0\xe1' # 8d74 mov r3, r0
59+
b'\x03\x40\x84\xe0' # 8d78 add r4, r4, r3
60+
b'\xe8\xff\xff\xeb' # 8d7c bl 0x8d24
61+
b'\x00\x30\xa0\xe1' # 8d80 mov r3, r0
62+
b'\x03\x20\x84\xe0' # 8d84 add r2, r4, r3
63+
)
6764
}
6865

69-
try:
70-
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
71-
# map 2MB memory for this emulation
72-
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
66+
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
67+
68+
mu.mem_map(ADDRESS, 0x1000)
69+
70+
# write machine code to be emulated to memory
71+
for addr, c in code.items():
72+
regress.logger.debug("Writing %d bytes to %#x", len(c), addr)
73+
mu.mem_write(addr, c)
74+
75+
# initialize machine registers
76+
mu.reg_write(UC_ARM_REG_PC, MAIN_ADDRESS)
77+
mu.reg_write(UC_ARM_REG_SP, STACK_ADDR)
78+
79+
regress.logger.debug("Starting emulation")
80+
81+
# trace code only if we are debugging it
82+
if regress.logger.isEnabledFor(regress.logging.DEBUG):
83+
def __hook_code(uc, addr, size, _):
84+
cpsr, r0, r3, r4, r6 = uc.reg_read_batch((
85+
UC_ARM_REG_CPSR,
86+
UC_ARM_REG_R0,
87+
UC_ARM_REG_R3,
88+
UC_ARM_REG_R4,
89+
UC_ARM_REG_R6
90+
))
91+
92+
is_thumb = (cpsr >> 5) & 0b1
93+
94+
opcode = uc.mem_read(addr, size).hex()
7395

74-
# write machine code to be emulated to memory
75-
for addr, c in code.items():
76-
print("Writing chunk to 0x{:x}".format(addr))
77-
mu.mem_write(addr, c)
96+
regress.logger.debug(
97+
"%-2s PC = %#06x | opcode = %-8s [R0 = %#06x, R3 = %#06x, R4 = %#07x, R6 = %#06x]",
98+
"T" if is_thumb else "", addr, opcode, r0, r3, r4, r6
99+
)
78100

79-
# initialize machine registers
80-
mu.reg_write(UC_ARM_REG_SP, STACK_ADDR)
101+
mu.hook_add(UC_HOOK_CODE, __hook_code)
81102

82-
print("Starting emulation")
103+
mu.emu_start(MAIN_ADDRESS, MAIN_ADDRESS + len(code[MAIN_ADDRESS]))
83104

84-
# emulate code in infinite time & unlimited instructions
85-
mu.emu_start(MAIN_ADDRESS, MAIN_ADDRESS + len(code[MAIN_ADDRESS]))
105+
regress.logger.debug("Emulation done")
86106

87-
print("Emulation done")
107+
self.assertEqual(0x8ce4 + 0x8d10 + 0x8d80, mu.reg_read(UC_ARM_REG_R2))
88108

89-
r2 = mu.reg_read(UC_ARM_REG_R2)
90-
print(">>> r2: 0x{:08x}".format(r2))
91109

92-
except UcError as e:
93-
self.fail("ERROR: %s" % e)
110+
if __name__ == '__main__':
111+
regress.main()

tests/regress/arm_bxeq_hang.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
11
#!/usr/bin/python
22

3+
import regress
4+
35
from unicorn import *
46
from unicorn.arm_const import *
57

6-
import regress
78

89
class BxHang(regress.RegressTest):
9-
1010
def runTest(self):
1111
uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)
1212
uc.mem_map(0x1000, 0x1000)
13-
uc.mem_write(0x1000, '1eff2f010000a0e1'.decode('hex')) # bxeq lr; mov r0, r0
13+
uc.mem_write(0x1000, b'\x1e\xff\x2f\x01\x00\x00\xa0\xe1') # bxeq lr; mov r0, r0
1414
uc.count = 0
1515

1616
def hook_block(uc, addr, *args):
17-
print 'enter block 0x%04x' % addr
17+
regress.logger.debug('enter block %#06x', addr)
1818
uc.count += 1
1919

2020
uc.reg_write(UC_ARM_REG_LR, 0x1004)
2121
uc.hook_add(UC_HOOK_BLOCK, hook_block)
22-
print 'block should only run once'
22+
23+
regress.logger.debug('block should only run once')
2324
uc.emu_start(0x1000, 0x1004)
2425

2526
self.assertEqual(uc.count, 1)
2627

28+
2729
if __name__ == '__main__':
2830
regress.main()

tests/regress/arm_fp_vfp_disabled.py

+23-26
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,41 @@
11
#!/usr/bin/python
2-
# coding=utf8
32

43
# Added by Peter Mackay, relating to issue 571
54
# "ARM NEON/VFP support seems to exist but is disabled by default"
65
# https://github.com/unicorn-engine/unicorn/issues/571
76

7+
import regress
8+
89
from unicorn import *
910
from unicorn.arm_const import *
1011

11-
import regress
12+
13+
CODE = (
14+
b'\x11\xEE\x50\x1F' # MRC p15, #0, r1, c1, c0, #2
15+
b'\x41\xF4\x70\x01' # ORR r1, r1, #(0xf << 20)
16+
b'\x01\xEE\x50\x1F' # MCR p15, #0, r1, c1, c0, #2
17+
b'\x4F\xF0\x00\x01' # MOV r1, #0
18+
b'\x07\xEE\x95\x1F' # MCR p15, #0, r1, c7, c5, #4
19+
b'\x4F\xF0\x80\x40' # MOV r0,#0x40000000
20+
b'\xE8\xEE\x10\x0A' # FMXR FPEXC, r0
21+
b'\x2d\xed\x02\x8b' # vpush {d8}
22+
)
23+
24+
BASE = 0x1000
1225

1326
class FpVfpDisabled(regress.RegressTest):
1427

1528
def runTest(self):
16-
# MRC p15, #0, r1, c1, c0, #2
17-
# ORR r1, r1, #(0xf << 20)
18-
# MCR p15, #0, r1, c1, c0, #2
19-
# MOV r1, #0
20-
# MCR p15, #0, r1, c7, c5, #4
21-
# MOV r0,#0x40000000
22-
# FMXR FPEXC, r0
23-
code = '11EE501F'
24-
code += '41F47001'
25-
code += '01EE501F'
26-
code += '4FF00001'
27-
code += '07EE951F'
28-
code += '4FF08040'
29-
code += 'E8EE100A'
30-
# vpush {d8}
31-
code += '2ded028b'
32-
33-
address = 0x1000
3429
mem_size = 0x1000
35-
code_bytes = code.decode('hex')
36-
30+
3731
uc = Uc(UC_ARCH_ARM, UC_MODE_THUMB)
38-
uc.mem_map(address, mem_size)
39-
uc.mem_write(address, code_bytes)
40-
uc.reg_write(UC_ARM_REG_SP, address + mem_size)
41-
uc.emu_start(address + 1, address + len(code_bytes))
32+
33+
uc.mem_map(BASE, mem_size)
34+
uc.mem_write(BASE, CODE)
35+
uc.reg_write(UC_ARM_REG_SP, BASE + mem_size - 4)
36+
37+
uc.emu_start(BASE + 1, BASE + len(CODE))
38+
4239

4340
if __name__ == '__main__':
4441
regress.main()

tests/regress/arm_init_input_crash.py

+26-30
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,44 @@
33
# Python sample ported by Loi Anh Tuan <[email protected]>
44
#
55

6+
import regress
67

7-
from __future__ import print_function
88
from unicorn import *
99
from unicorn.arm_const import *
1010

1111

1212
# code to be emulated
13-
ARM_CODE = "\x37\x00\xa0\xe3\x03\x10\x42\xe0" # mov r0, #0x37; sub r1, r2, r3
14-
THUMB_CODE = "\x83\xb0" # sub sp, #0xc
13+
ARM_CODE = (
14+
b"\x37\x00\xa0\xe3" # mov r0, #0x37
15+
b"\x03\x10\x42\xe0" # sub r1, r2, r3
16+
)
17+
18+
THUMB_CODE = b"\x83\xb0" # sub sp, #0xc
19+
1520
# memory address where emulation starts
16-
ADDRESS = 0xF0000000
21+
ADDRESS = 0xF0000000
1722

1823

1924
# callback for tracing basic blocks
2025
def hook_block(uc, address, size, user_data):
21-
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
26+
regress.logger.debug(">>> Tracing basic block at %#x, block size = %#x", address, size)
2227

2328

2429
# callback for tracing instructions
2530
def hook_code(uc, address, size, user_data):
26-
print(">>> Tracing instruction at 0x%x, instruction size = %u" %(address, size))
31+
regress.logger.debug(">>> Tracing instruction at %#x, instruction size = %u", address, size)
2732

2833

29-
# Test ARM
30-
def test_arm():
31-
print("Emulate ARM code")
32-
try:
34+
class TestInitInputCrash(regress.RegressTest):
35+
def test_arm(self):
36+
regress.logger.debug("Emulate ARM code")
37+
3338
# Initialize emulator in ARM mode
3439
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
35-
40+
3641
mem_size = 2 * (1024 * 1024)
3742
mu.mem_map(ADDRESS, mem_size)
38-
43+
3944
stack_address = ADDRESS + mem_size
4045
stack_size = stack_address # >>> here huge memory size
4146
mu.mem_map(stack_address, stack_size)
@@ -58,20 +63,16 @@ def test_arm():
5863
mu.emu_start(ADDRESS, ADDRESS + len(ARM_CODE))
5964

6065
# now print out some registers
61-
print(">>> Emulation done. Below is the CPU context")
66+
regress.logger.debug(">>> Emulation done. Below is the CPU context")
6267

6368
r0 = mu.reg_read(UC_ARM_REG_R0)
6469
r1 = mu.reg_read(UC_ARM_REG_R1)
65-
print(">>> R0 = 0x%x" %r0)
66-
print(">>> R1 = 0x%x" %r1)
67-
68-
except UcError as e:
69-
print("ERROR: %s" % e)
70+
regress.logger.debug(">>> R0 = %#x", r0)
71+
regress.logger.debug(">>> R1 = %#x", r1)
7072

73+
def test_thumb(self):
74+
regress.logger.debug("Emulate THUMB code")
7175

72-
def test_thumb():
73-
print("Emulate THUMB code")
74-
try:
7576
# Initialize emulator in thumb mode
7677
mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB)
7778

@@ -91,19 +92,14 @@ def test_thumb():
9192
mu.hook_add(UC_HOOK_CODE, hook_code)
9293

9394
# emulate machine code in infinite time
94-
mu.emu_start(ADDRESS, ADDRESS + len(THUMB_CODE))
95+
mu.emu_start(ADDRESS | 0b1, ADDRESS + len(THUMB_CODE))
9596

9697
# now print out some registers
97-
print(">>> Emulation done. Below is the CPU context")
98+
regress.logger.debug(">>> Emulation done. Below is the CPU context")
9899

99100
sp = mu.reg_read(UC_ARM_REG_SP)
100-
print(">>> SP = 0x%x" %sp)
101-
102-
except UcError as e:
103-
print("ERROR: %s" % e)
101+
regress.logger.debug(">>> SP = %#x", sp)
104102

105103

106104
if __name__ == '__main__':
107-
test_arm()
108-
print("=" * 20)
109-
test_thumb()
105+
regress.main()

0 commit comments

Comments
 (0)