Skip to content

Commit 31daa8a

Browse files
committed
Arm: add parallel instructions
1 parent f54b2e4 commit 31daa8a

File tree

6 files changed

+720
-1
lines changed

6 files changed

+720
-1
lines changed

miasm/arch/arm/arch.py

+24
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,30 @@ def armtop(name, fields, args=None, alias=False):
17091709
armop("isb", [bs8(0xF5), bs8(0x7F), bs8(0xF0), bs8(0x6F)])
17101710
armop("nop", [bs8(0xE3), bs8(0x20), bs8(0xF0), bs8(0)])
17111711

1712+
1713+
parallel_arith_name = {
1714+
'Q': 0b01100010,
1715+
'S': 0b01100001,
1716+
'SH': 0b01100011,
1717+
'U': 0b01100101,
1718+
'UH': 0b01100111,
1719+
'UQ': 0b01100110,
1720+
}
1721+
bs_parallel_arith = bs_name(l=8, name=parallel_arith_name)
1722+
1723+
parallel_modarith_name = {
1724+
0b0001 : 'ADD16',
1725+
0b0011 : 'ADDSUBX',
1726+
0b0101 : 'SUBADDX',
1727+
0b0111 : 'SUB16',
1728+
0b1001 : 'ADD8',
1729+
0b1111 : 'SUB8',
1730+
}
1731+
bs_parallel_modarith = bs_mod_name(l=4, mn_mod=parallel_modarith_name)
1732+
1733+
armop("arith", [bs_parallel_arith, rn, rd, bs('1111'), bs_parallel_modarith, rm], [rd, rn, rm])
1734+
1735+
17121736
class arm_widthm1(arm_imm, m_arg):
17131737
def decode(self, v):
17141738
self.expr = ExprInt(v+1, 32)

miasm/arch/arm/sem.py

+163
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,160 @@ def uadd8(ir, instr, a, b, c):
12851285
return e, []
12861286

12871287

1288+
def uadd16(ir, instr, a, b, c):
1289+
e = []
1290+
sums = []
1291+
ges = []
1292+
for i in range(0, 32, 16):
1293+
sums.append(b[i:i+16] + c[i:i+16])
1294+
ges.append((b[i:i+16].zeroExtend(17) + c[i:i+16].zeroExtend(17))[16:17])
1295+
1296+
e.append(ExprAssign(a, ExprCompose(*sums)))
1297+
1298+
for i, value in enumerate(ges):
1299+
e.append(ExprAssign(ge_regs[2 * i], value))
1300+
e.append(ExprAssign(ge_regs[2 * i + 1], value))
1301+
return e, []
1302+
1303+
1304+
def uaddsubx(ir, instr, a, b, c):
1305+
e = []
1306+
sums = []
1307+
ges = []
1308+
1309+
1310+
part1, part2 = b[16:32], c[0:16]
1311+
sums.append(part1 + part2)
1312+
ges.append((part1.zeroExtend(17) + part2.zeroExtend(17))[16:17])
1313+
1314+
part1, part2 = b[0:16], c[16:32]
1315+
sums.append(part1 - part2)
1316+
ges.append(ExprOp("FLAG_SIGN_SUB", part1, part2))
1317+
1318+
e.append(ExprAssign(a, ExprCompose(*sums[::-1])))
1319+
1320+
for i, value in enumerate(ges[::-1]):
1321+
e.append(ExprAssign(ge_regs[2 * i], value))
1322+
e.append(ExprAssign(ge_regs[2 * i + 1], value))
1323+
return e, []
1324+
1325+
1326+
def sadd8(ir, instr, a, b, c):
1327+
e = []
1328+
sums = []
1329+
ges = []
1330+
for i in range(0, 32, 8):
1331+
sums.append(b[i:i+8] + c[i:i+8])
1332+
ges.append(ExprOp("FLAG_SIGN_SUB", ExprInt(0, 9), b[i:i+8].signExtend(9) + c[i:i+8].signExtend(9)))
1333+
1334+
e.append(ExprAssign(a, ExprCompose(*sums)))
1335+
1336+
for i, value in enumerate(ges):
1337+
e.append(ExprAssign(ge_regs[i], value))
1338+
return e, []
1339+
1340+
1341+
def sadd16(ir, instr, a, b, c):
1342+
e = []
1343+
sums = []
1344+
ges = []
1345+
for i in range(0, 32, 16):
1346+
sums.append(b[i:i+16] + c[i:i+16])
1347+
ges.append(ExprOp("FLAG_SIGN_SUB", ExprInt(0, 17), b[i:i+16].signExtend(17) + c[i:i+16].signExtend(17)))
1348+
1349+
e.append(ExprAssign(a, ExprCompose(*sums)))
1350+
1351+
for i, value in enumerate(ges):
1352+
e.append(ExprAssign(ge_regs[2 * i], value))
1353+
e.append(ExprAssign(ge_regs[2 * i + 1], value))
1354+
return e, []
1355+
1356+
1357+
def saddsubx(ir, instr, a, b, c):
1358+
e = []
1359+
sums = []
1360+
ges = []
1361+
1362+
1363+
part1, part2 = b[16:32], c[0:16]
1364+
sums.append(part1 + part2)
1365+
ges.append(ExprOp("FLAG_SIGN_SUB", ExprInt(0, 17), part1.signExtend(17) + part2.signExtend(17)))
1366+
1367+
part1, part2 = b[0:16], c[16:32]
1368+
sums.append(part1 - part2)
1369+
ges.append(~ExprOp("FLAG_SIGN_SUB", part1, part2))
1370+
1371+
e.append(ExprAssign(a, ExprCompose(*sums[::-1])))
1372+
1373+
for i, value in enumerate(ges[::-1]):
1374+
e.append(ExprAssign(ge_regs[2 * i], value))
1375+
e.append(ExprAssign(ge_regs[2 * i + 1], value))
1376+
return e, []
1377+
1378+
1379+
1380+
def q_tpl(ir, instr, is_sub, dst_size, a, b, c):
1381+
e = []
1382+
sums = []
1383+
1384+
median = 1 << (dst_size - 1)
1385+
1386+
min_int = ExprInt(- median, dst_size)
1387+
max_int = ExprInt(median - 1, dst_size)
1388+
1389+
test_min_int = min_int.signExtend(dst_size + 1)
1390+
test_max_int = max_int.signExtend(dst_size + 1)
1391+
1392+
for i in range(0, a.size, dst_size):
1393+
src1 = b[i:i+dst_size].signExtend(dst_size + 1)
1394+
src2 = c[i:i+dst_size].signExtend(dst_size + 1)
1395+
if is_sub:
1396+
src2 = -src2
1397+
res = src1 + src2
1398+
value = res[:dst_size]
1399+
res_sat = ExprCond(
1400+
ExprOp(
1401+
TOK_INF_EQUAL_SIGNED,
1402+
res,
1403+
test_min_int
1404+
),
1405+
min_int,
1406+
ExprCond(
1407+
ExprOp(
1408+
TOK_INF_SIGNED,
1409+
res,
1410+
test_max_int
1411+
),
1412+
value,
1413+
max_int
1414+
)
1415+
)
1416+
sums.append(res_sat)
1417+
1418+
e.append(ExprAssign(a, ExprCompose(*sums)))
1419+
return e, []
1420+
1421+
1422+
def qadd8(ir, instr, a, b, c):
1423+
e, blocks = q_tpl(ir, instr, False, 8, a, b, c)
1424+
return e, blocks
1425+
1426+
1427+
def qadd16(ir, instr, a, b, c):
1428+
e, blocks = q_tpl(ir, instr, False, 16, a, b, c)
1429+
return e, blocks
1430+
1431+
1432+
def qsub8(ir, instr, a, b, c):
1433+
e, blocks = q_tpl(ir, instr, True, 8, a, b, c)
1434+
return e, blocks
1435+
1436+
1437+
def qsub16(ir, instr, a, b, c):
1438+
e, blocks = q_tpl(ir, instr, True, 16, a, b, c)
1439+
return e, blocks
1440+
1441+
12881442
def sel(ir, instr, a, b, c):
12891443
e = []
12901444
cond = nf ^ of ^ ExprInt(1, 1)
@@ -1641,6 +1795,15 @@ def add_condition_expr(ir, instr, cond, instr_ir, extra_ir):
16411795
'smlatb': smlatb,
16421796
'smlatt': smlatt,
16431797
'uadd8': uadd8,
1798+
'uadd16': uadd16,
1799+
'uaddsubx': uaddsubx,
1800+
'sadd8': sadd8,
1801+
'sadd16': sadd16,
1802+
'saddsubx': saddsubx,
1803+
'qadd8': qadd8,
1804+
'qadd16': qadd16,
1805+
'qsub8': qsub8,
1806+
'qsub16': qsub16,
16441807
'sel': sel,
16451808
}
16461809

test/arch/arm/arch.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,8 @@ def u16swap(i):
222222

223223
('XXXXXXXX UXTAB R5, R2, R8 ROR 0x8',
224224
'7854e2e6'),
225-
225+
('XXXXXXXX UADD8 R1, R2, R3',
226+
'931f52e6'),
226227

227228
('XXXXXXXX PKHBT R1, R2, R3 LSL 0x8',
228229
'131482e6'),

test/arch/arm/unit/asm_test.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from builtins import str
2+
from builtins import object
3+
import sys
4+
import os
5+
6+
from future.utils import viewitems
7+
8+
from miasm.arch.arm.arch import mn_arm, base_expr, variable
9+
from miasm.core import parse_asm
10+
from miasm.expression.expression import *
11+
from miasm.core import asmblock
12+
from miasm.loader.strpatchwork import StrPatchwork
13+
from miasm.analysis.machine import Machine
14+
from miasm.jitter.csts import *
15+
16+
reg_and_id = dict(mn_arm.regs.all_regs_ids_byname)
17+
18+
class Asm_Test(object):
19+
run_addr = 0x0
20+
21+
def __init__(self, jitter_engine):
22+
self.myjit = Machine(self.arch_name).jitter(jitter_engine)
23+
self.myjit.init_stack()
24+
25+
def test_init(self):
26+
pass
27+
28+
def prepare(self):
29+
pass
30+
31+
def __call__(self):
32+
self.prepare()
33+
self.asm()
34+
self.init_machine()
35+
self.test_init()
36+
self.run()
37+
self.check()
38+
39+
def run(self):
40+
41+
self.myjit.init_run(self.run_addr)
42+
self.myjit.continue_run()
43+
44+
assert(self.myjit.pc == self.ret_addr)
45+
46+
def asm(self):
47+
blocks, loc_db = parse_asm.parse_txt(
48+
mn_arm, self.arch_attrib, self.TXT,
49+
loc_db = self.myjit.ir_arch.loc_db
50+
)
51+
# fix shellcode addr
52+
loc_db.set_location_offset(loc_db.get_name_location("main"), 0x0)
53+
s = StrPatchwork()
54+
patches = asmblock.asm_resolve_final(mn_arm, blocks, loc_db)
55+
for offset, raw in viewitems(patches):
56+
s[offset] = raw
57+
58+
s = bytes(s)
59+
self.assembly = s
60+
61+
def check(self):
62+
raise NotImplementedError('abstract method')
63+
64+
65+
class Asm_Test(Asm_Test):
66+
arch_name = "arml"
67+
arch_attrib = "l"
68+
ret_addr = 0x1330
69+
70+
def init_machine(self):
71+
self.myjit.vm.add_memory_page(self.run_addr, PAGE_READ | PAGE_WRITE, self.assembly)
72+
self.myjit.push_uint32_t(self.ret_addr)
73+
self.myjit.add_breakpoint(self.ret_addr, lambda x:False)
74+

0 commit comments

Comments
 (0)