74 lines
2.5 KiB
Python
74 lines
2.5 KiB
Python
|
#! /usr/bin/env python3
|
||
|
|
||
|
import subprocess
|
||
|
import collections
|
||
|
from itertools import chain
|
||
|
import argparse
|
||
|
|
||
|
def decode(bin, traces):
|
||
|
if len(traces) == 0:
|
||
|
return []
|
||
|
addrs = chain.from_iterable([x[1:] for x in traces])
|
||
|
cmd = ["addr2line", "-f", "-s", "-e", bin] + list(addrs)
|
||
|
decoded = subprocess.run(cmd, stdout=subprocess.PIPE).stdout
|
||
|
decoded = collections.deque(decoded.split(b'\n'))
|
||
|
for line in traces:
|
||
|
target_name = decoded.popleft()
|
||
|
target_line = decoded.popleft()
|
||
|
site_name = decoded.popleft()
|
||
|
site_line = decoded.popleft()
|
||
|
yield [line[0],target_name,site_name,site_line]
|
||
|
|
||
|
def processBlock(args, traces, out_file):
|
||
|
decoded = decode(args.binary, traces)
|
||
|
for decoded_line in decoded:
|
||
|
if decoded_line[0] == 'e':
|
||
|
out_file.write(b"Enter ")
|
||
|
out_file.write(decoded_line[1])
|
||
|
if not args.suppress_callsite:
|
||
|
out_file.write(b" from ")
|
||
|
out_file.write(decoded_line[2])
|
||
|
out_file.write(b" (")
|
||
|
out_file.write(decoded_line[3])
|
||
|
out_file.write(b")")
|
||
|
out_file.write(b"\n")
|
||
|
if decoded_line[0] == 'x' and (not args.suppress_exit):
|
||
|
out_file.write(b"Exit ")
|
||
|
out_file.write(decoded_line[1])
|
||
|
out_file.write(b"\n")
|
||
|
|
||
|
parser = argparse.ArgumentParser(description='Decode a trace file generated by dotrace.')
|
||
|
parser.add_argument('-b', '--binary', help='The binary file.',
|
||
|
required=True, metavar="FILE")
|
||
|
parser.add_argument('-t', '--trace', help="The trace file (default: '%(default)s').",
|
||
|
default="trace.out", metavar="FILE")
|
||
|
parser.add_argument('-o', '--output', help="The output file (default: '%(default)s').",
|
||
|
default="trace.decoded", metavar="FILE")
|
||
|
parser.add_argument('-e', '--suppress-exit',
|
||
|
help='Do not output function exits.', action='store_true')
|
||
|
parser.add_argument('-c', '--suppress-callsite',
|
||
|
help='Do not output callsite of function calls.', action='store_true')
|
||
|
parser.add_argument('-s', '--block-size', type=int, default=10000,
|
||
|
help='The number of addresses forwarded to addr2line (default: %(default)s).')
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
lines_to_read = args.block_size / 2
|
||
|
accumulator = []
|
||
|
i = 0
|
||
|
total = 1
|
||
|
with open(args.trace, 'r') as trace_file:
|
||
|
with open(args.output, 'bw') as out_file:
|
||
|
for line in trace_file:
|
||
|
i = i + 1
|
||
|
accumulator.append(line.split())
|
||
|
if i >= lines_to_read:
|
||
|
print("Processing lines {}-{}.".format(total, total + i - 1))
|
||
|
processBlock(args, accumulator, out_file)
|
||
|
accumulator.clear()
|
||
|
total = total + i
|
||
|
i = 0
|
||
|
print("Processing lines {}-{} [final block].".format(total, total + i - 1))
|
||
|
processBlock(args, accumulator, out_file)
|