mirror of
https://github.com/isledecomp/isle.git
synced 2025-10-23 00:14:22 +00:00
generate progress SVGs
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
from capstone import *
|
||||
import difflib
|
||||
import struct
|
||||
@@ -15,9 +16,12 @@ parser.add_argument('original', metavar='original-binary', help='The original bi
|
||||
parser.add_argument('recompiled', metavar='recompiled-binary', help='The recompiled binary')
|
||||
parser.add_argument('pdb', metavar='recompiled-pdb', help='The PDB of the recompiled binary')
|
||||
parser.add_argument('decomp_dir', metavar='decomp-dir', help='The decompiled source tree')
|
||||
parser.add_argument('--total', '-T', metavar='total-func-count', help='Total number of expected functions (improves total accuracy statistic)')
|
||||
parser.add_argument('--verbose', '-v', metavar='offset', help='Print assembly diff for specific function (original file\'s offset)')
|
||||
parser.add_argument('--html', '-H', metavar='output-file', help='Generate searchable HTML summary of status and diffs')
|
||||
parser.add_argument('--no-color', '-n', action='store_true', help='Do not color the output')
|
||||
parser.add_argument('--svg', '-S', metavar='output-svg', help='Generate SVG graphic of progress')
|
||||
parser.add_argument('--svg-icon', metavar='svg-icon', help='Icon to use in SVG (PNG)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -50,6 +54,8 @@ source = args.decomp_dir
|
||||
if not os.path.isdir(source):
|
||||
parser.error('Source directory does not exist')
|
||||
|
||||
svg = args.svg
|
||||
|
||||
# Declare a class that can automatically convert virtual executable addresses
|
||||
# to file addresses
|
||||
class Bin:
|
||||
@@ -365,7 +371,8 @@ for subdir, dirs, files in os.walk(source):
|
||||
|
||||
# If html, record the diffs to an HTML file
|
||||
if html:
|
||||
htmlinsert.append('{address: "%s", name: "%s", matching: %s, diff: "%s"}' % (hex(addr), recinfo.name, str(ratio), '\\n'.join(udiff).replace('"', '\\"').replace('\n', '\\n')))
|
||||
escaped = '\\n'.join(udiff).replace('"', '\\"').replace('\n', '\\n').replace('<', '<').replace('>', '>')
|
||||
htmlinsert.append('{address: "%s", name: "%s", matching: %s, diff: "%s"}' % (hex(addr), recinfo.name, str(ratio), escape))
|
||||
|
||||
except UnicodeDecodeError:
|
||||
break
|
||||
@@ -389,6 +396,49 @@ def gen_html(html, data):
|
||||
htmlfile.write(templatedata)
|
||||
htmlfile.close()
|
||||
|
||||
def gen_svg(svg, name, icon, implemented_funcs, total_funcs, raw_accuracy):
|
||||
templatefile = open(get_file_in_script_dir('template.svg'), 'r')
|
||||
if not templatefile:
|
||||
print('Failed to find SVG template file, can\'t generate SVG summary')
|
||||
return
|
||||
|
||||
templatedata = templatefile.read()
|
||||
templatefile.close()
|
||||
|
||||
# Replace icon
|
||||
if args.svg_icon:
|
||||
iconfile = open(args.svg_icon, 'rb')
|
||||
templatedata = templatedata.replace('{icon}', base64.b64encode(iconfile.read()).decode('utf-8'), 1)
|
||||
iconfile.close()
|
||||
|
||||
# Replace name
|
||||
templatedata = templatedata.replace('{name}', name, 1)
|
||||
|
||||
# Replace implemented statistic
|
||||
templatedata = templatedata.replace('{implemented}', '%.2f%% (%i/%i)' % (implemented_funcs / total_funcs * 100, implemented_funcs, total_funcs), 1)
|
||||
|
||||
# Replace accuracy statistic
|
||||
templatedata = templatedata.replace('{accuracy}', '%.2f%%' % (raw_accuracy / implemented_funcs * 100), 1)
|
||||
|
||||
# Generate progress bar width
|
||||
total_statistic = raw_accuracy / total_funcs
|
||||
percenttemplate = '{progbar'
|
||||
percentstart = templatedata.index(percenttemplate)
|
||||
percentend = templatedata.index('}', percentstart)
|
||||
progwidth = float(templatedata[percentstart + len(percenttemplate) + 1:percentend]) * total_statistic
|
||||
templatedata = templatedata[0:percentstart] + str(progwidth) + templatedata[percentend + 1:]
|
||||
|
||||
# Replace percentage statistic
|
||||
templatedata = templatedata.replace('{percent}', '%.2f%%' % (total_statistic * 100), 1)
|
||||
|
||||
svgfile = open(svg, 'w')
|
||||
if not svgfile:
|
||||
print('Failed to write to SVG file %s' % svg)
|
||||
return
|
||||
|
||||
svgfile.write(templatedata)
|
||||
svgfile.close()
|
||||
|
||||
if html:
|
||||
gen_html(html, htmlinsert)
|
||||
|
||||
@@ -396,5 +446,13 @@ if verbose:
|
||||
if not found_verbose_target:
|
||||
print('Failed to find the function with address %s' % hex(verbose))
|
||||
else:
|
||||
implemented_funcs = function_count
|
||||
|
||||
if args.total:
|
||||
function_count = int(args.total)
|
||||
|
||||
if function_count > 0:
|
||||
print('\nTotal accuracy %.2f%% across %i functions' % (total_accuracy / function_count * 100, function_count))
|
||||
|
||||
if svg:
|
||||
gen_svg(svg, os.path.basename(original), args.svg_icon, implemented_funcs, function_count, total_accuracy)
|
||||
|
Reference in New Issue
Block a user