1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4# 5# Written by Christian Holler <decoder at mozilla dot com> 6 7import json 8import os 9import sys 10import subprocess 11 12if len(sys.argv) != 2: 13 print("Usage: %s binfile" % os.path.basename(sys.argv[0])) 14 sys.exit(1) 15 16binfile = sys.argv[1] 17 18addr2len = {} 19addrs = [] 20 21output = subprocess.check_output(["objdump", "-t", binfile]).decode("utf-8") 22for line in output.splitlines(): 23 line = line.replace("\t", " ") 24 components = [x for x in line.split(" ") if x] 25 if not components: 26 continue 27 try: 28 start_addr = int(components[0], 16) 29 except ValueError: 30 continue 31 32 # Length has variable position in objdump output 33 length = None 34 for comp in components[1:]: 35 if len(comp) == 16: 36 try: 37 length = int(comp, 16) 38 break 39 except: 40 continue 41 42 if length is None: 43 print("ERROR: Couldn't determine function section length: %s" % line) 44 45 func = components[-1] 46 47 addrs.append(start_addr) 48 addr2len[str(hex(start_addr))] = str(length) 49 50# The search implementation in the AFL runtime expects everything sorted. 51addrs.sort() 52addrs = [str(hex(addr)) for addr in addrs] 53 54# We symbolize in one go to speed things up with large binaries. 55output = subprocess.check_output([ 56 "llvm-addr2line", 57 "--output-style=JSON", 58 "-f", "-C", "-a", "-e", 59 binfile], 60 input="\n".join(addrs).encode("utf-8")).decode("utf-8") 61 62output = output.strip().splitlines() 63for line in output: 64 output = json.loads(line) 65 if "Symbol" in output and output["Address"] in addr2len: 66 final_output = [ 67 output["Address"], 68 addr2len[output["Address"]], 69 os.path.basename(output["ModuleName"]), 70 output["Symbol"][0]["FileName"], 71 output["Symbol"][0]["FunctionName"] 72 ] 73 print("\t".join(final_output)) 74