forked from programa-stic/hexag00n
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tests.py
135 lines (91 loc) · 4.27 KB
/
tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import (ascii, bytes, chr, dict, filter, hex, input,
int, map, next, oct, open, pow, range, round,
str, super, zip)
import cProfile
import pstats
import struct
import time
from hexagondisasm import common
from hexagondisasm.disassembler import HexagonDisassembler
from hexagondisasm.objdump_wrapper import ObjdumpWrapper
from hexagondisasm.common import INST_SIZE
from elftools.elf.elffile import ELFFile
from elftools.elf.constants import P_FLAGS
def test_disasm_against_objdump(objdump_path, binary_path):
# TODO: code repetition from test_disasm_standalone, encapsulate inner functionality.
start_time = time.time()
total_inst = 0
match_inst = 0
print(('Processing file:', binary_path))
elf_file = ELFFile(open(binary_path, 'rb'))
if elf_file.num_segments() == 0:
print('There are no program headers in this file.')
return
objdump = ObjdumpWrapper(objdump_path)
disasm = HexagonDisassembler(objdump_compatible=True)
for segment in elf_file.iter_segments():
if segment['p_flags'] & P_FLAGS.PF_X:
print("Offset: {:x}".format(segment['p_offset']))
print("VirtAddr: {:x}".format(segment['p_vaddr']))
print("FileSiz: {:x}".format(segment['p_filesz']))
segment_data = segment.data()
data_pos = 0
while data_pos + INST_SIZE <= len(segment_data):
addr = segment['p_vaddr'] + data_pos
inst_as_int = struct.unpack('<I', segment_data[data_pos: data_pos + 4])[0]
disasm_output = disasm.disasm_one_inst(inst_as_int, addr).text.strip()
objdump_output = objdump.disasm_packet_raw(
segment_data[data_pos: min(data_pos + 4 * 4, segment_data)],
addr).strip()
if (objdump_output != disasm_output):
print("[{:08x}] {:s}".format(addr, objdump_output))
print("[{:08x}] {:s}".format(addr, disasm_output))
print()
else:
match_inst += 1
data_pos += 4
total_inst += 1
elapsed_time = time.time() - start_time
print("Elapsed time: {0:.2f}".format(elapsed_time))
print('Match: {0:.2f}%'.format(match_inst / total_inst * 100))
def test_disasm_standalone(binary_path, timeout = None):
profile = cProfile.Profile()
profile.enable()
start_time = time.time()
print(('Processing file:', binary_path))
elf_file = ELFFile(open(binary_path, 'rb'))
if elf_file.num_segments() == 0:
print('There are no program headers in this file.')
return
disasm = HexagonDisassembler()
total_inst = 0
for segment in elf_file.iter_segments():
if segment['p_flags'] & P_FLAGS.PF_X:
print("Offset: {:x}".format(segment['p_offset']))
print("VirtAddr: {:x}".format(segment['p_vaddr']))
print("FileSiz: {:x}".format(segment['p_filesz']))
segment_data = segment.data()
data_pos = 0
while data_pos + INST_SIZE <= len(segment_data):
addr = segment['p_vaddr'] + data_pos
inst_as_int = struct.unpack('<I', segment_data[data_pos: data_pos + 4])[0]
dis = disasm.disasm_one_inst(inst_as_int, addr)
print("[{:08x}] {:s}".format(addr, dis.text))
data_pos += 4
total_inst += 1
if timeout and (time.time() - start_time) > timeout:
break
profile.disable()
prof_stats = pstats.Stats(profile)
prof_stats.strip_dirs().sort_stats('cumulative').print_stats(20)
print("Total instructions: " + str(total_inst))
elapsed_time = time.time() - start_time
print("Elapsed time: " + str(elapsed_time))
if __name__ == "__main__":
binary_path = common.FACTORIAL_EXAMPLE_ELF
test_disasm_standalone(binary_path)
# objdump_path = "hexagon-objdump.exe"
#
# test_disasm_against_objdump(objdump_path, binary_path)