1 #!/usr/bin/python 2 # Copyright 2013 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 import commands 7 import os 8 import sys 9 10 orderfile = sys.argv[1] 11 uninstrumented_shlib = sys.argv[2] 12 13 nmlines_uninstrumented = commands.getoutput ('nm -S -n ' + 14 uninstrumented_shlib + ' | egrep "( t )|( W )|( T )"').split('\n') 15 16 nmlines = [] 17 for nmline in nmlines_uninstrumented: 18 if (len(nmline.split()) == 4): 19 nmlines.append(nmline) 20 21 # Map addresses to list of functions at that address. There are multiple 22 # functions at an address because of aliasing. 23 nm_index = 0 24 uniqueAddrs = [] 25 addressMap = {} 26 while nm_index < len(nmlines): 27 if (len(nmlines[nm_index].split()) == 4): 28 nm_int = int (nmlines[nm_index].split()[0], 16) 29 size = int (nmlines[nm_index].split()[1], 16) 30 fnames = [nmlines[nm_index].split()[3]] 31 nm_index = nm_index + 1 32 while nm_index < len(nmlines) and nm_int == int ( 33 nmlines[nm_index].split()[0], 16): 34 fnames.append(nmlines[nm_index].split()[3]) 35 nm_index = nm_index + 1 36 addressMap[nm_int] = fnames 37 uniqueAddrs.append((nm_int, size)) 38 else: 39 nm_index = nm_index + 1 40 41 def binary_search (addr, start, end): 42 if start >= end or start == end - 1: 43 (nm_addr, size) = uniqueAddrs[start] 44 if not (addr >= nm_addr and addr < nm_addr + size): 45 sys.stderr.write ("ERROR: did not find function in binary: addr: " + 46 hex(addr) + " nm_addr: " + str(nm_addr) + " start: " + str(start) + 47 " end: " + str(end) + "\n") 48 raise Error("error") 49 return (addressMap[nm_addr], size) 50 else: 51 halfway = start + ((end - start) / 2) 52 (nm_addr, size) = uniqueAddrs[halfway] 53 if (addr >= nm_addr and addr < nm_addr + size): 54 return (addressMap[nm_addr], size) 55 elif (addr < nm_addr): 56 return binary_search (addr, start, halfway) 57 elif (addr >= nm_addr + size): 58 return binary_search (addr, halfway, end) 59 else: 60 raise "ERROR: did not expect this case" 61 62 f = open (orderfile) 63 lines = f.readlines() 64 profiled_list = [] 65 for line in lines: 66 if (line.strip() == ''): 67 continue 68 functionName = line.replace('.text.', '').split('.clone.')[0].strip() 69 profiled_list.append (functionName) 70 71 # Symbol names are not unique. Since the order file uses symbol names, the 72 # patched order file pulls in all symbols with the same name. Multiple function 73 # addresses for the same function name may also be due to ".clone" symbols, 74 # since the substring is stripped. 75 functions = [] 76 functionAddressMap = {} 77 for line in nmlines: 78 try: 79 functionName = line.split()[3] 80 except: 81 functionName = line.split()[2] 82 functionName = functionName.split('.clone.')[0] 83 functionAddress = int (line.split()[0].strip(), 16) 84 try: 85 functionAddressMap[functionName].append(functionAddress) 86 except: 87 functionAddressMap[functionName] = [functionAddress] 88 functions.append(functionName) 89 90 sys.stderr.write ("profiled list size: " + str(len(profiled_list)) + "\n") 91 addresses = [] 92 symbols_found = 0 93 for function in profiled_list: 94 try: 95 addrs = functionAddressMap[function] 96 symbols_found = symbols_found + 1 97 except: 98 addrs = [] 99 # sys.stderr.write ("WARNING: could not find symbol " + function + "\n") 100 for addr in addrs: 101 if not (addr in addresses): 102 addresses.append(addr) 103 sys.stderr.write ("symbols found: " + str(symbols_found) + "\n") 104 105 sys.stderr.write ("number of addresses: " + str(len(addresses)) + "\n") 106 total_size = 0 107 for addr in addresses: 108 (functions, size) = binary_search (addr, 0, len(uniqueAddrs)) 109 total_size = total_size + size 110 prefixes = ['.text.', '.text.startup.', '.text.hot.', '.text.unlikely.'] 111 for function in functions: 112 for prefix in prefixes: 113 print prefix + function 114 115 # The following is needed otherwise Gold only applies a partial sort. 116 print '.text.*' 117 sys.stderr.write ("total_size: " + str(total_size) + "\n") 118