forked from zeldaret/tmc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
progress.py
122 lines (99 loc) · 3.69 KB
/
progress.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
import argparse
import git
import os
import re
def collect_non_matching_funcs():
result = []
for root, dirs, files in os.walk('src'):
for file in files:
if file.endswith('.c'):
with open(os.path.join(root, file), 'r') as f:
data = f.read()
# Find all NONMATCH and ASM_FUNC macros
for match in re.findall(r'(NONMATCH|ASM_FUNC)\(".*",\W*\w*\W*(\w*).*\)', data):
result.append(match)
return result
def parse_map(non_matching_funcs):
src = 0
asm = 0
src_data = 0
data = 0
non_matching = 0
with open('tmc.map', 'r') as map:
# Skip to the linker script section
line = map.readline()
while not line.startswith('Linker script and memory map'):
line = map.readline()
while not line.startswith('rom'):
line = map.readline()
prev_symbol = None
prev_addr = 0
for line in map:
if line.startswith(' .'):
arr = line.split()
section = arr[0]
size = int(arr[2], 16)
filepath = arr[3]
dir = filepath.split('/')[0]
if section == '.text':
if dir == 'src':
src += size
elif dir == 'asm':
asm += size
elif dir == 'data':
# scripts
data += size
elif dir == '..':
# libc
src += size
elif section == '.rodata':
if dir == 'src':
src_data += size
elif dir == 'data':
data += size
elif line.startswith(' '):
arr = line.split()
if len(arr) == 2 and arr[1] != '': # It is actually a symbol
if prev_symbol in non_matching_funcs:
# Calculate the length for non matching function
non_matching += int(arr[0], 16) - prev_addr
prev_symbol = arr[1]
prev_addr = int(arr[0], 16)
elif line.strip() == '':
# End of linker script section
break
src -= non_matching
asm += non_matching
return (src, asm, src_data, data)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--matching', dest='matching', action='store_true',
help='Output matching progress instead of decompilation progress')
args = parser.parse_args()
matching = args.matching
non_matching_funcs = []
funcs = collect_non_matching_funcs()
if matching:
# Remove all non matching funcs from count
non_matching_funcs = [x[1] for x in funcs]
else:
# Only remove ASM_FUNC functions from count
for func in funcs:
if func[0] == 'ASM_FUNC':
non_matching_funcs.append(func[1])
(src, asm, src_data, data) = parse_map(non_matching_funcs)
total = src + asm
data_total = src_data + data
src_pct = '%.4f' % (100 * src / total)
asm_pct = '%.4f' % (100 * asm / total)
src_data_pct = '%.4f' % (100 * src_data / data_total)
data_pct = '%.4f' % (100 * data / data_total)
version = 1
git_object = git.Repo().head.object
timestamp = str(git_object.committed_date)
git_hash = git_object.hexsha
csv_list = [str(version), timestamp, git_hash, str(src_pct),
str(asm_pct), str(src_data_pct), str(data_pct)]
print(','.join(csv_list))
if __name__ == '__main__':
main()