Add error checks and more comments

This commit is contained in:
Hans-Joerg Schurr 2018-03-03 16:50:46 +01:00
parent 12a911704f
commit d445ab3e27
1 changed files with 47 additions and 0 deletions

View File

@ -1,11 +1,31 @@
#! /usr/bin/env python3 #! /usr/bin/env python3
""" A python script used to decode the addresses in traces generated by
the dotrace instrumentation.
Requires addr2line to be installed. The script works by collecting a
given number of address from the trace file and then calling addr2line
with such a block of addresses.
"""
import os
import subprocess import subprocess
import collections import collections
import sys
from itertools import chain from itertools import chain
import argparse import argparse
def decode(bin, traces): def decode(bin, traces):
"""Decodes a list of address using addr2line.
Args:
bin: The executable used for retrieving the debug symbols.
traces: A list of lists of the form [c, a, b] where a and
b are addresses as string.
Returns:
Generates lists [c, call targed name, call site name,
call site source location]
"""
if len(traces) == 0: if len(traces) == 0:
return [] return []
addrs = chain.from_iterable([x[1:] for x in traces]) addrs = chain.from_iterable([x[1:] for x in traces])
@ -20,6 +40,15 @@ def decode(bin, traces):
yield [line[0],target_name,site_name,site_line] yield [line[0],target_name,site_name,site_line]
def processBlock(args, traces, out_file): def processBlock(args, traces, out_file):
"""Decodes a block of trace lines.
Args:
args: The program arguments.
traces: A list of lists of the form [c, a, b] where a and
b are addresses as string and c is eiter 'e' or 'x'
indicating if the line is a function entry or exit.
out_file: The output file to write into. In binary mode.
"""
decoded = decode(args.binary, traces) decoded = decode(args.binary, traces)
for decoded_line in decoded: for decoded_line in decoded:
if decoded_line[0] == 'e': if decoded_line[0] == 'e':
@ -37,6 +66,7 @@ def processBlock(args, traces, out_file):
out_file.write(decoded_line[1]) out_file.write(decoded_line[1])
out_file.write(b"\n") out_file.write(b"\n")
# Parser configuration
parser = argparse.ArgumentParser(description='Decode a trace file generated by dotrace.') parser = argparse.ArgumentParser(description='Decode a trace file generated by dotrace.')
parser.add_argument('-b', '--binary', help='The binary file.', parser.add_argument('-b', '--binary', help='The binary file.',
required=True, metavar="FILE") required=True, metavar="FILE")
@ -54,12 +84,29 @@ parser.add_argument('-s', '--block-size', type=int, default=10000,
if __name__ == "__main__": if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
# Check if addr2line is installed
DEVNULL = open(os.devnull, 'w')
try:
subprocess.call(["addr2line", "--version"],
stdout=DEVNULL, stderr=subprocess.STDOUT)
except FileNotFoundError as e:
print("Error: addr2line not installed.", file=sys.stderr)
sys.exit(1)
# Check if the files referenced by the options exist
for f in [args.binary, args.trace]:
if not os.path.exists(f):
print("Error: File {} does not exist.".format(f) ,file=sys.stderr)
sys.exit(1)
lines_to_read = args.block_size / 2 lines_to_read = args.block_size / 2
accumulator = [] accumulator = []
i = 0 i = 0
total = 1 total = 1
with open(args.trace, 'r') as trace_file: with open(args.trace, 'r') as trace_file:
with open(args.output, 'bw') as out_file: with open(args.output, 'bw') as out_file:
# read lines_to_read lines from the file, each line constains two
# addresses
for line in trace_file: for line in trace_file:
i = i + 1 i = i + 1
accumulator.append(line.split()) accumulator.append(line.split())