mirror of
https://github.com/bitdefender/bddisasm.git
synced 2024-12-22 22:18:09 +00:00
9ba1e6a2f9
Multiple minor fixes to existing instructions. Moved x86 decoding tests in a separate directory & improved the test script.
142 lines
3.8 KiB
Python
142 lines
3.8 KiB
Python
#
|
|
# Copyright (c) 2020 Bitdefender
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
import os
|
|
import sys
|
|
import glob
|
|
|
|
total_tests = 0
|
|
failed_tests = 0
|
|
|
|
def get_dict(ins):
|
|
d = {}
|
|
prefix = ""
|
|
|
|
# Remove lines that don't contain tokens.
|
|
lines = ins.split("\n")
|
|
|
|
# Main disassembly.
|
|
d["disasm"] = lines[0]
|
|
|
|
for line in lines[1:]:
|
|
tokens = line.split(",")
|
|
for t in tokens:
|
|
val = t.split(":")
|
|
if len(val) != 2:
|
|
continue
|
|
a = val[0].strip(" ")
|
|
b = val[1].strip(" ")
|
|
if a == "Operand":
|
|
prefix = "op%s_" % b
|
|
a = prefix + a
|
|
d[a] = b
|
|
return d
|
|
|
|
def compare_instruction(i1, i2):
|
|
x1 = get_dict(i1)
|
|
x2 = get_dict(i2)
|
|
for t in x1:
|
|
if not t in x2:
|
|
print(" ! ERROR: Token '%s', value '%s' missing from output!" % (t, x1[t]))
|
|
return False
|
|
if x1[t] != x2[t]:
|
|
print(" ! ERROR: Token '%s' value mismatch: expected '%s', got '%s'!" % (t, x1[t], x2[t]))
|
|
return False
|
|
for t in x2:
|
|
if not t in x1:
|
|
print(" ! WARNING: Extra token in result: '%s', value '%s'!" % (t, x2[t]))
|
|
|
|
return True
|
|
|
|
def compare_results(data1, data2):
|
|
ins1 = data1.split("\n\n")
|
|
ins2 = data2.split("\n\n")
|
|
if len(ins1) != len(ins2):
|
|
print(" ! Different number of instructions in output: expected %d, got %d!" % (len(ins1), len(ins2)))
|
|
return False
|
|
for i in range(0, len(ins1)):
|
|
if not compare_instruction(ins1[i], ins2[i]):
|
|
print(" ! ERROR: Instruction mismatch at %d!" % (i))
|
|
return False
|
|
return True
|
|
|
|
def test_dir(dir):
|
|
global total_tests
|
|
global failed_tests
|
|
|
|
for f in glob.glob('%s\\*.test' % dir):
|
|
base, _ = os.path.splitext(f)
|
|
|
|
tst_file = f
|
|
res_file = base + '.result'
|
|
tmp_file = base + '.temp'
|
|
|
|
if 0 < f.find('_16'):
|
|
mod = '-b16'
|
|
elif 0 < f.find('_32'):
|
|
mod = '-b32'
|
|
else:
|
|
mod = '-b64'
|
|
if 0 < f.find('_r0'):
|
|
mod += ' -k'
|
|
|
|
if 0 < f.find('_skip'):
|
|
mod += ' -skip16'
|
|
|
|
print(' * Running test case %s...' % f)
|
|
os.system('disasm -exi %s -f %s >%s' % (mod, tst_file, tmp_file))
|
|
try:
|
|
res = open(res_file).read()
|
|
except:
|
|
print(' ! No result file provided for test %s!' % tst_file)
|
|
|
|
try:
|
|
tmp = open(tmp_file).read()
|
|
except:
|
|
print(' ! No result produced by test %s!' % tst_file)
|
|
|
|
total_tests += 1
|
|
if not compare_results(res, tmp):
|
|
print(' **** FAILED! ****')
|
|
failed_tests += 1
|
|
else:
|
|
print(' * Passed.')
|
|
|
|
# Cleanup.
|
|
os.remove(tmp_file)
|
|
|
|
def regenerate(dir):
|
|
for f in glob.glob('%s\\*.test' % dir):
|
|
base, _ = os.path.splitext(f)
|
|
|
|
tst_file = f
|
|
res_file = base + '.result'
|
|
|
|
if 0 < f.find('_16'):
|
|
mod = '-b16'
|
|
elif 0 < f.find('_32'):
|
|
mod = '-b32'
|
|
else:
|
|
mod = '-b64'
|
|
if 0 < f.find('_r0'):
|
|
mod += ' -k'
|
|
if 0 < f.find('_skip'):
|
|
mod += ' -skip16'
|
|
|
|
print(' * Regenerating test case %s...' % tst_file)
|
|
os.system('disasm -exi %s -f %s >%s' % (mod, tst_file, res_file))
|
|
|
|
if __name__ == "__main__":
|
|
for dn in glob.glob("x86\\*"):
|
|
if not os.path.isdir(dn):
|
|
continue
|
|
if "regenerate" in sys.argv:
|
|
print('Regenerating %s...' % dn)
|
|
regenerate(dn)
|
|
else:
|
|
print('Testing %s...' % dn)
|
|
test_dir(dn)
|
|
|
|
print("Ran %d tests, %d failed" % (total_tests, failed_tests))
|