89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
#!/usr/bin/python
|
|
import re
|
|
import os
|
|
import hashlib
|
|
import hmac
|
|
import argparse
|
|
import sys
|
|
|
|
argparser = argparse.ArgumentParser(description='Parses obfuscated logging from iBoot release builds')
|
|
argparser.add_argument('--src', required=True, help='iBoot source tree corresponding to log')
|
|
argparser.add_argument('-v', '--verbose', action='store_true', default=False, help='Attempts to load log string from source file instead of simplying printing the source file and line number')
|
|
argparser.add_argument('filename', nargs='?', default=None, help='File to read log from (omit for stdin)')
|
|
|
|
args = argparser.parse_args()
|
|
|
|
id_file_map = {}
|
|
|
|
directory = args.src
|
|
|
|
base_hmac = hmac.new('obfuscation of filename for release build logging', '', hashlib.sha1)
|
|
|
|
for (path, dirnames, filenames) in os.walk(directory):
|
|
# strip the part of the pathname we supplied off the pathname
|
|
shortened_path = path[len(directory)+1:]
|
|
# don't iterate into paths we don't care about
|
|
try:
|
|
dirnames.remove('.svn')
|
|
except ValueError:
|
|
pass
|
|
# only look at .c and .cpp files in the build directory, be more permissive elsewhere
|
|
if shortened_path.startswith('build/'):
|
|
filenames = [x for x in filenames if x.endswith('.c') or x.endswith('.cpp')]
|
|
for filename in filenames:
|
|
full_path = os.path.join(shortened_path, filename)
|
|
|
|
current_hmac = base_hmac.copy()
|
|
current_hmac.update(full_path)
|
|
|
|
file_id = current_hmac.hexdigest()[:16]
|
|
|
|
if file_id in id_file_map and id_file_map[file_id] != full_path:
|
|
print 'Warning: Files "{}" and "{}" both have the same ID {}'.format(full_path, id_file_map[file_id], file_id)
|
|
else:
|
|
id_file_map[file_id] = full_path
|
|
|
|
file_cache = {}
|
|
def get_src_line(filename, line_number):
|
|
|
|
if filename not in file_cache:
|
|
file_path = os.path.join(directory, filename)
|
|
with open(file_path) as f:
|
|
lines = [x.strip() for x in f]
|
|
file_cache[filename] = lines
|
|
|
|
return file_cache[filename][line_number - 1]
|
|
|
|
def parse_src_line(src_line):
|
|
result = re.match(r'dprintf\s*\(\s*[a-zA-Z0-9_]+,\s*"([^"]*)".*', src_line)
|
|
|
|
if result is not None:
|
|
return result.group(1)
|
|
else:
|
|
return src_line
|
|
|
|
def parse_log(f):
|
|
log_re = re.compile(r'^(.*\|)?([0-9a-f]{16}):(\d+)$')
|
|
for line in f:
|
|
line = line.rstrip()
|
|
result = log_re.match(line)
|
|
if result is not None:
|
|
timestamp = result.group(1) or ''
|
|
file_id = result.group(2)
|
|
line_number = int(result.group(3))
|
|
if file_id in id_file_map:
|
|
filename = id_file_map[file_id]
|
|
if args.verbose:
|
|
src_line = get_src_line(filename, line_number)
|
|
print '{}{} [{}:{}]'.format(timestamp, parse_src_line(src_line), filename, line_number)
|
|
else:
|
|
print '{}{}:{}'.format(timestamp, filename, line_number)
|
|
continue
|
|
print line
|
|
|
|
if args.filename is not None:
|
|
with open(args.filename) as f:
|
|
parse_log(f)
|
|
else:
|
|
parse_log(sys.stdin)
|