find_runtime_symbols.py revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import json 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from static_symbols import StaticSymbolsInFile 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from proc_maps import ProcMaps 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_MAPS_FILENAME = 'maps' 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_FILES_FILENAME = 'files.json' 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class _ListOutput(object): 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, result): 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.result = result 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def output(self, address, symbol): # pylint: disable=W0613 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.result.append(symbol) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class _DictOutput(object): 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, result): 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.result = result 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def output(self, address, symbol): 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.result[address] = symbol 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class _FileOutput(object): 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, result, with_address): 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.result = result 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.with_address = with_address 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def output(self, address, symbol): 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.with_address: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.result.write('%016x %s\n' % (address, symbol)) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.result.write('%s\n' % symbol) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RuntimeSymbolsInProcess(object): 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self): 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._maps = None 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._static_symbols_in_filse = {} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def find_procedure(self, runtime_address): 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for vma in self._maps.iter(ProcMaps.executable): 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if vma.begin <= runtime_address < vma.end: 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_symbols = self._static_symbols_in_filse.get(vma.name) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if static_symbols: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_symbols.find_procedure_by_runtime_address( 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runtime_address, vma) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def find_typeinfo(self, runtime_address): 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for vma in self._maps.iter(ProcMaps.constants): 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if vma.begin <= runtime_address < vma.end: 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_symbols = self._static_symbols_in_filse.get(vma.name) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if static_symbols: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_symbols.find_typeinfo_by_runtime_address( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runtime_address, vma) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @staticmethod 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def load(prepared_data_dir): 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symbols_in_process = RuntimeSymbolsInProcess() 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open(os.path.join(prepared_data_dir, _MAPS_FILENAME), mode='r') as f: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symbols_in_process._maps = ProcMaps.load(f) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open(os.path.join(prepared_data_dir, _FILES_FILENAME), mode='r') as f: 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files = json.load(f) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # pylint: disable=W0212 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for vma in symbols_in_process._maps.iter(ProcMaps.executable_and_constants): 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_entry = files.get(vma.name) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not file_entry: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_symbols = StaticSymbolsInFile(vma.name) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nm_entry = file_entry.get('nm') 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if nm_entry and nm_entry['format'] == 'bsd': 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open(os.path.join(prepared_data_dir, nm_entry['file']), 'r') as f: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_symbols.load_nm_bsd(f, nm_entry['mangled']) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) readelf_entry = file_entry.get('readelf-e') 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if readelf_entry: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open(os.path.join(prepared_data_dir, readelf_entry['file']), 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'r') as f: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_symbols.load_readelf_ew(f) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symbols_in_process._static_symbols_in_filse[vma.name] = static_symbols 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return symbols_in_process 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _find_runtime_symbols(symbols_in_process, addresses, outputter): 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for address in addresses: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if isinstance(address, basestring): 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address = int(address, 16) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = symbols_in_process.find_procedure(address) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if found: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outputter.output(address, found.name) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outputter.output(address, '0x%016x' % address) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _find_runtime_typeinfo_symbols(symbols_in_process, addresses, outputter): 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for address in addresses: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if isinstance(address, basestring): 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address = int(address, 16) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if address == 0: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outputter.output(address, 'no typeinfo') 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = symbols_in_process.find_typeinfo(address) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if found: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if found.startswith('typeinfo for '): 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outputter.output(address, found[13:]) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outputter.output(address, found) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outputter.output(address, '0x%016x' % address) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def find_runtime_typeinfo_symbols_list(symbols_in_process, addresses): 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = [] 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _find_runtime_typeinfo_symbols( 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) symbols_in_process, addresses, _ListOutput(result)) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def find_runtime_typeinfo_symbols_dict(symbols_in_process, addresses): 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = {} 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _find_runtime_typeinfo_symbols( 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) symbols_in_process, addresses, _DictOutput(result)) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def find_runtime_typeinfo_symbols_file(symbols_in_process, addresses, f): 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _find_runtime_typeinfo_symbols( 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) symbols_in_process, addresses, _FileOutput(f, False)) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def find_runtime_symbols_list(symbols_in_process, addresses): 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = [] 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _find_runtime_symbols(symbols_in_process, addresses, _ListOutput(result)) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def find_runtime_symbols_dict(symbols_in_process, addresses): 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = {} 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _find_runtime_symbols(symbols_in_process, addresses, _DictOutput(result)) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def find_runtime_symbols_file(symbols_in_process, addresses, f): 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _find_runtime_symbols( 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) symbols_in_process, addresses, _FileOutput(f, False)) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def main(): 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # FIX: Accept only .pre data 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(sys.argv) < 2: 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.stderr.write("""Usage: 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)%s /path/to/prepared_data_dir/ < addresses.txt 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""" % sys.argv[0]) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log = logging.getLogger('find_runtime_symbols') 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log.setLevel(logging.WARN) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handler = logging.StreamHandler() 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handler.setLevel(logging.WARN) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formatter = logging.Formatter('%(message)s') 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handler.setFormatter(formatter) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log.addHandler(handler) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prepared_data_dir = sys.argv[1] 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.path.exists(prepared_data_dir): 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log.warn("Nothing found: %s" % prepared_data_dir) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.path.isdir(prepared_data_dir): 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log.warn("Not a directory: %s" % prepared_data_dir) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symbols_in_process = RuntimeSymbolsInProcess.load(prepared_data_dir) 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return find_runtime_symbols_file(symbols_in_process, sys.stdin, sys.stdout) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__': 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.exit(main()) 201