Skip to content

Commit

Permalink
Create assemble function and update unittest
Browse files Browse the repository at this point in the history
  • Loading branch information
Pongsakorn Sommalai committed Jan 11, 2021
1 parent 5a576a8 commit 5e41c59
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 104 deletions.
27 changes: 24 additions & 3 deletions hasm.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
from util import *
import json
import os
import shutil

def dump(hbc, path):
assert not os.path.exists(path), f"'{path}' exists."
if os.path.exists(path):
c = input(f"'{path}' exists. Do you want to remove it ? (y/n): ").strip()
if c == "y":
shutil.rmtree(path)
else:
exit(1337)

os.makedirs(path)
# Write all obj to metadata.json
json.dump(hbc.getObj(), open(f"{path}/metadata.json", "w"))
f = open(f"{path}/metadata.json", "w")
json.dump(hbc.getObj(), f)
f.close()

stringCount = hbc.getStringCount()
functionCount = hbc.getFunctionCount()

ss = []
for i in range(stringCount):
val, header = hbc.getString(i)
ss.append({
"id": i,
"value": val
})

f = open(f"{path}/string.json", "w")
json.dump(ss, f, indent=4)
f.close()

f = open(f"{path}/instruction.hasm", "w")
for i in range(functionCount):
functionName, paramCount, registerCount, symbolCount, insts, _ = hbc.getFunction(i)
Expand All @@ -32,7 +53,7 @@ def dump(hbc, path):
f.write(f"{', '.join(o)}\n")
if len(ss) > 0:
for ii, val, s in ss:
f.write(f"\t; Oper[{ii}]: String({val}) {s}\n")
f.write(f"\t; Oper[{ii}]: String({val}) {repr(s)}\n")

f.write("\n")

Expand Down
9 changes: 9 additions & 0 deletions hbc/hbc74/test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from hbc import parseFromFile
from .translator import assemble, disassemble
import unittest
import re
import pathlib
Expand Down Expand Up @@ -59,3 +60,11 @@ def test_get_string(self):

# TODO : Implement this please
# self.assertEqual(val, target_val)

def test_translator(self):
functionCount = self.hbc.getFunctionCount()

for i in range(functionCount):
_, _, _, _, bc, _ = self.hbc.getFunction(i, disasm=False)

self.assertEqual(assemble(disassemble(bc)), bc)
45 changes: 29 additions & 16 deletions hbc/hbc74/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,52 @@
"Reg32": (4, to_uint32, from_uint32),
"UInt8": (1, to_uint8, from_uint8),
"UInt16": (2, to_uint16, from_uint16),
"UInt32": (4, to_uint32, from_uint16),
"UInt32": (4, to_uint32, from_uint32),
"Addr8": (1, to_int8, from_int8),
"Addr32": (4, to_int32, from_int32),
"Reg32": (4, to_uint32, from_uint32),
"Imm32": (4, to_uint32, from_uint32),
"Double": (8, to_double, from_double)
}

def disassemble(inst):
f = open(f"{basepath}/data/opcode.json", "r")
opcode_operand = json.load(f)
f.close()
opcode_mapper = list(opcode_operand.keys())
f = open(f"{basepath}/data/opcode.json", "r")
opcode_operand = json.load(f)
opcode_mapper = list(opcode_operand.keys())
opcode_mapper_inv = {}
for i, v in enumerate(opcode_mapper):
opcode_mapper_inv[v] = i

f.close()

def disassemble(bc):
i = 0
rs = []
while i < len(inst):
opcode = opcode_mapper[inst[i]]
insts = []
while i < len(bc):
opcode = opcode_mapper[bc[i]]
i+=1
r = (opcode, [])
inst = (opcode, [])
operand_ts = opcode_operand[opcode]
for oper_t in operand_ts:
is_str = oper_t.endswith(":S")
if is_str:
oper_t = oper_t[:-2]

size, conv_to, _ = operand_type[oper_t]
val = conv_to(inst[i:i+size])
r[1].append((oper_t, is_str, val))
val = conv_to(bc[i:i+size])
inst[1].append((oper_t, is_str, val))
i+=size

rs.append(r)
insts.append(inst)

return rs
return insts

def assemble(inst):
pass
def assemble(insts):
bc = []
for opcode, operands in insts:
opcode = opcode_mapper_inv[opcode]
bc.append(opcode)
for oper_t, _, val in operands:
_, _, conv_from = operand_type[oper_t]
bc += conv_from(val)

return bc
2 changes: 1 addition & 1 deletion hbctool.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

if __name__ == "__main__":
hbc = parseFromFile(open("hbc/hbc74/example/index.android.bundle", "rb"))
print(hbc.getString(10)[1])
hasm.dump(hbc, "output/test")
95 changes: 95 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,100 @@
import unittest
from util import *
from hbc.hbc74.test import TestHBC74

class ByteIO:
def __init__(self, v=b""):
self.buf = v

def write(self, b):
self.buf += b

def read(self, n=-1):
if n==-1:
o = self.buf
self.buf = b""
return o

o = self.buf[:n]
self.buf = self.buf[n:]
return o

class TestFileUtilization(unittest.TestCase):
def test_bit_writer(self):
io = ByteIO()
fw = BitWriter(io)

offset = 182856
paramCount = 1
bytecodeSizeInBytes = 12342
functionName = 3086

write(fw, offset, ["bit", 25, 1])
write(fw, paramCount, ["bit", 7, 1])
write(fw, bytecodeSizeInBytes, ["bit", 15, 1])
write(fw, functionName, ["bit", 17, 1])

bs = io.read()
self.assertEqual("48ca020236300706", bs.hex())

isUTF16 = 0
offset = 465
length = 3

write(fw, isUTF16, ["bit", 1, 1])
write(fw, offset, ["bit", 23, 1])
write(fw, length, ["bit", 8, 1])

bs = io.read()
self.assertEqual("a2030003", bs.hex())

def test_bit_reader(self):
io = ByteIO()
fr = BitReader(io)

io.write(bytes.fromhex("48ca020236300706"))

offset = read(fr, ["bit", 25, 1])
paramCount = read(fr, ["bit", 7, 1])
bytecodeSizeInBytes = read(fr, ["bit", 15, 1])
functionName = read(fr, ["bit", 17, 1])

self.assertEqual(offset, 182856)
self.assertEqual(paramCount, 1)
self.assertEqual(bytecodeSizeInBytes, 12342)
self.assertEqual(functionName, 3086)

io.write(bytes.fromhex("a2030003"))

isUTF16 = read(fr, ["bit", 1, 1])
offset = read(fr, ["bit", 23, 1])
length = read(fr, ["bit", 8, 1])

self.assertEqual(isUTF16, 0)
self.assertEqual(offset, 465)
self.assertEqual(length, 3)

def test_conversion(self):

io = ByteIO()
fr = BitReader(io)
fw = BitWriter(io)

isUTF16 = 1
offset = 465
length = 3

write(fw, isUTF16, ["bit", 1, 1])
write(fw, offset, ["bit", 23, 1])
write(fw, length, ["bit", 8, 1])

isUTF16 = read(fr, ["bit", 1, 1])
offset = read(fr, ["bit", 23, 1])
length = read(fr, ["bit", 8, 1])

self.assertEqual(isUTF16, 1)
self.assertEqual(offset, 465)
self.assertEqual(length, 3)

if __name__ == "__main__":
unittest.main()
84 changes: 0 additions & 84 deletions util.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,87 +334,3 @@ def memcpy(dest, src, start, length):
for i in range(length):
dest[start + i] = src[i]


class ByteIO:
def __init__(self, v=b""):
self.buf = v

def write(self, b):
self.buf += b

def read(self, n=-1):
if n==-1:
o = self.buf
self.buf = b""
return o

o = self.buf[:n]
self.buf = self.buf[n:]
return o

if __name__ == "__main__":
offset = 182856
paramCount = 1
bytecodeSizeInBytes = 12342
functionName = 3086

io = ByteIO()
fw = BitWriter(io)
fr = BitReader(io)

write(fw, offset, ["bit", 25, 1])
write(fw, paramCount, ["bit", 7, 1])
write(fw, bytecodeSizeInBytes, ["bit", 15, 1])
write(fw, functionName, ["bit", 17, 1])

bs = io.read()
assert "48ca020236300706" == bs.hex()

isUTF16 = 0
offset = 465
length = 3

write(fw, isUTF16, ["bit", 1, 1])
write(fw, offset, ["bit", 23, 1])
write(fw, length, ["bit", 8, 1])

bs = io.read()
assert "a2030003" == bs.hex()

io.write(bytes.fromhex("48ca020236300706"))

offset = read(fr, ["bit", 25, 1])
paramCount = read(fr, ["bit", 7, 1])
bytecodeSizeInBytes = read(fr, ["bit", 15, 1])
functionName = read(fr, ["bit", 17, 1])

assert offset == 182856
assert paramCount == 1
assert bytecodeSizeInBytes == 12342
assert functionName == 3086

io.write(bytes.fromhex("a2030003"))

isUTF16 = read(fr, ["bit", 1, 1])
offset = read(fr, ["bit", 23, 1])
length = read(fr, ["bit", 8, 1])

assert isUTF16 == 0
assert offset == 465
assert length == 3

isUTF16 = 1
offset = 465
length = 3

write(fw, isUTF16, ["bit", 1, 1])
write(fw, offset, ["bit", 23, 1])
write(fw, length, ["bit", 8, 1])

isUTF16 = read(fr, ["bit", 1, 1])
offset = read(fr, ["bit", 23, 1])
length = read(fr, ["bit", 8, 1])

assert isUTF16 == 1
assert offset == 465
assert length == 3

0 comments on commit 5e41c59

Please sign in to comment.