Home | History | Annotate | Download | only in cygprofile
      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