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) |