| Index: tools/find_runtime_symbols/static_symbols.py
|
| diff --git a/tools/find_runtime_symbols/procedure_boundaries.py b/tools/find_runtime_symbols/static_symbols.py
|
| similarity index 59%
|
| rename from tools/find_runtime_symbols/procedure_boundaries.py
|
| rename to tools/find_runtime_symbols/static_symbols.py
|
| index be1d76cc3345ba983f6860f60218532a299c27a1..0141202153738491d655c359e13e50a65d69f3da 100644
|
| --- a/tools/find_runtime_symbols/procedure_boundaries.py
|
| +++ b/tools/find_runtime_symbols/static_symbols.py
|
| @@ -3,10 +3,14 @@
|
| # found in the LICENSE file.
|
|
|
| import bisect
|
| +import json
|
| import os
|
| import re
|
| import sys
|
|
|
| +from parse_proc_maps import parse_proc_maps
|
| +from util import executable_condition
|
| +
|
|
|
| _ARGUMENT_TYPE_PATTERN = re.compile('\([^()]*\)(\s*const)?')
|
| _TEMPLATE_ARGUMENT_PATTERN = re.compile('<[^<>]*>')
|
| @@ -18,6 +22,63 @@ class ParsingException(Exception):
|
| return repr(self.args[0])
|
|
|
|
|
| +class StaticSymbols(object):
|
| + """Represents static symbol information."""
|
| +
|
| + def __init__(self, maps, procedure_boundaries):
|
| + self.maps = maps
|
| + self.procedure_boundaries = procedure_boundaries
|
| +
|
| + # TODO(dmikurube): It will be deprecated.
|
| + @staticmethod
|
| + def _load_nm(prepared_data_dir, maps_filename, nm_json_filename):
|
| + with open(os.path.join(prepared_data_dir, maps_filename), mode='r') as f:
|
| + maps = parse_proc_maps(f)
|
| + with open(os.path.join(prepared_data_dir, nm_json_filename), mode='r') as f:
|
| + nm_files = json.load(f)
|
| +
|
| + symbol_tables = {}
|
| + for entry in maps.iter(executable_condition):
|
| + if nm_files.has_key(entry.name):
|
| + if nm_files[entry.name]['format'] == 'bsd':
|
| + with open(os.path.join(prepared_data_dir,
|
| + nm_files[entry.name]['file']), mode='r') as f:
|
| + symbol_tables[entry.name] = _get_static_symbols_from_nm_bsd(
|
| + f, nm_files[entry.name]['mangled'])
|
| +
|
| + return StaticSymbols(maps, symbol_tables)
|
| +
|
| + @staticmethod
|
| + def _load_files(prepared_data_dir, maps_filename, files_filename):
|
| + with open(os.path.join(prepared_data_dir, maps_filename), mode='r') as f:
|
| + maps = parse_proc_maps(f)
|
| + with open(os.path.join(prepared_data_dir, files_filename), mode='r') as f:
|
| + files = json.load(f)
|
| +
|
| + symbol_tables = {}
|
| + for entry in maps.iter(executable_condition):
|
| + if entry.name in files:
|
| + if 'nm' in files[entry.name]:
|
| + nm_entry = files[entry.name]['nm']
|
| + if nm_entry['format'] == 'bsd':
|
| + with open(os.path.join(prepared_data_dir, nm_entry['file']),
|
| + mode='r') as f:
|
| + symbol_tables[entry.name] = _get_static_symbols_from_nm_bsd(
|
| + f, nm_entry['mangled'])
|
| + if 'readelf-e' in files:
|
| + readelf_entry = files[entry.name]['readelf-e']
|
| + # TODO(dmikurube) Implement it.
|
| +
|
| + return StaticSymbols(maps, symbol_tables)
|
| +
|
| + @staticmethod
|
| + def load(prepared_data_dir):
|
| + if os.path.exists(os.path.join(prepared_data_dir, 'nm.json')):
|
| + return StaticSymbols._load_nm(prepared_data_dir, 'maps', 'nm.json')
|
| + else:
|
| + return StaticSymbols._load_files(prepared_data_dir, 'maps', 'files.json')
|
| +
|
| +
|
| class ProcedureBoundary(object):
|
| """A class for a procedure symbol and an address range for the symbol."""
|
|
|
| @@ -65,7 +126,15 @@ def _get_short_function_name(function):
|
| return _LEADING_TYPE_PATTERN.sub('\g<1>', function)
|
|
|
|
|
| -def get_procedure_boundaries_from_nm_bsd(f, mangled=False):
|
| +def _parse_nm_bsd_line(line):
|
| + if line[8] == ' ':
|
| + return line[0:8], line[9], line[11:]
|
| + elif line[16] == ' ':
|
| + return line[0:16], line[17], line[19:]
|
| + raise ParsingException('Invalid nm output.')
|
| +
|
| +
|
| +def _get_static_symbols_from_nm_bsd(f, mangled=False):
|
| """Gets procedure boundaries from a result of nm -n --format bsd.
|
|
|
| Args:
|
| @@ -81,27 +150,9 @@ def get_procedure_boundaries_from_nm_bsd(f, mangled=False):
|
| routine = ''
|
|
|
| for line in f:
|
| - symbol_info = line.rstrip().split(None, 2)
|
| - if len(symbol_info) == 3:
|
| - if len(symbol_info[0]) == 1:
|
| - symbol_info = line.split(None, 1)
|
| - (sym_type, this_routine) = symbol_info
|
| - sym_value = ''
|
| - else:
|
| - (sym_value, sym_type, this_routine) = symbol_info
|
| - elif len(symbol_info) == 2:
|
| - if len(symbol_info[0]) == 1:
|
| - (sym_type, this_routine) = symbol_info
|
| - sym_value = ''
|
| - elif len(symbol_info[0]) == 8 or len(symbol_info[0]) == 16:
|
| - (sym_value, this_routine) = symbol_info
|
| - sym_type = ' '
|
| - else:
|
| - raise ParsingException('Invalid output 1 from (eu-)nm.')
|
| - else:
|
| - raise ParsingException('Invalid output 2 from (eu-)nm.')
|
| + sym_value, sym_type, sym_name = _parse_nm_bsd_line(line)
|
|
|
| - if sym_value == '':
|
| + if sym_value[0] == ' ':
|
| continue
|
|
|
| start_val = int(sym_value, 16)
|
| @@ -123,7 +174,7 @@ def get_procedure_boundaries_from_nm_bsd(f, mangled=False):
|
| # got touched in the queue), and ignore the others.
|
| if start_val == last_start and (sym_type == 't' or sym_type == 'T'):
|
| # We are the 'T' symbol at this address, replace previous symbol.
|
| - routine = this_routine
|
| + routine = sym_name
|
| continue
|
| elif start_val == last_start:
|
| # We're not the 'T' symbol at this address, so ignore us.
|
| @@ -133,14 +184,14 @@ def get_procedure_boundaries_from_nm_bsd(f, mangled=False):
|
| # has multiple occurrences of this routine. We use a syntax
|
| # that resembles template paramters that are automatically
|
| # stripped out by ShortFunctionName()
|
| - this_routine += "<%016x>" % start_val
|
| + sym_name += "<%016x>" % start_val
|
|
|
| if not mangled:
|
| routine = _get_short_function_name(routine)
|
| symbol_table.append(ProcedureBoundary(last_start, start_val, routine))
|
|
|
| last_start = start_val
|
| - routine = this_routine
|
| + routine = sym_name
|
|
|
| if not mangled:
|
| routine = _get_short_function_name(routine)
|
|
|