mirror of https://github.com/zeldaret/tmc.git
123 lines
3.7 KiB
Python
123 lines
3.7 KiB
Python
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()
|