Chromium Code Reviews| Index: tools/find_runtime_symbols/find_runtime_symbols.py |
| diff --git a/tools/find_runtime_symbols/find_runtime_symbols.py b/tools/find_runtime_symbols/find_runtime_symbols.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..c6c6a63a914ec70c3f53d9d549546f6d2e0feb9e |
| --- /dev/null |
| +++ b/tools/find_runtime_symbols/find_runtime_symbols.py |
| @@ -0,0 +1,133 @@ |
| +#!/usr/bin/env python |
| + |
|
M-A Ruel
2012/07/19 15:21:15
Copyright in all files
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
Done.
|
| +import json |
| +import logging |
| +import os |
| +import re |
| +import sys |
| + |
| +from parse_proc_maps import parse_proc_maps |
| +from procedure_boundaries import get_procedure_boundaries_from_nm_bsd |
| + |
| + |
| +def _executable_condition(entry): |
| + return (entry.executable == 'x' and re.match( |
|
M-A Ruel
2012/07/19 15:21:15
You know about os.path.splitext(entry.name)[1] ?
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
I didn't know. But, it should match foo.dll, libf
|
| + '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?', |
| + entry.name)) |
| + |
| + |
| +def _determine_symbol_name(address, symbol): |
| + if symbol: |
| + return symbol.name |
| + else: |
| + return '0x%016x' % address |
| + |
| + |
| +class _ListOutput(object): |
| + def __init__(self, result): |
| + self.result = result |
| + |
| + def output(self, address, symbol=None): |
| + self.result.append(_determine_symbol_name(address, symbol)) |
| + |
| + |
| +class _DictOutput(object): |
| + def __init__(self, result): |
| + self.result = result |
| + |
| + def output(self, address, symbol=None): |
| + self.result[address] = _determine_symbol_name(address, symbol) |
| + |
| + |
| +class _FileOutput(object): |
| + def __init__(self, result, with_address): |
| + self.result = result |
| + self.with_address = with_address |
| + |
| + def output(self, address, symbol=None): |
| + symbol_name = _determine_symbol_name(address, symbol) |
| + if self.with_address: |
| + self.result.write('%016x %s\n' % (address, symbol_name)) |
| + else: |
| + self.result.write('%s\n' % symbol_name) |
| + |
| + |
| +def _find_runtime_symbols( |
| + prepared_data_dir, addresses, outputter, loglevel=logging.WARN): |
| + log = logging.getLogger('find_runtime_symbols') |
| + log.setLevel(loglevel) |
|
M-A Ruel
2012/07/19 15:21:15
Usually we make it module wide, but I don't mind.
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
I wanted to set loglevel in _find_runtime_symbols
|
| + handler = logging.StreamHandler() |
| + handler.setLevel(loglevel) |
| + formatter = logging.Formatter('%(message)s') |
| + handler.setFormatter(formatter) |
| + log.addHandler(handler) |
| + |
| + if not os.path.exists(prepared_data_dir): |
| + log.warn("Nothing found: %s" % prepared_data_dir) |
| + return 1 |
| + if not os.path.isdir(prepared_data_dir): |
| + log.warn("Not a directory: %s" % prepared_data_dir) |
| + return 1 |
| + |
| + with open(os.path.join(prepared_data_dir, 'maps'), mode='r') as FILE: |
|
M-A Ruel
2012/07/19 15:21:15
ALL CAPS are for constants. In other files too.
U
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
Done.
|
| + maps = parse_proc_maps(FILE) |
| + |
| + with open(os.path.join(prepared_data_dir, 'nm.json'), mode='r') as FILE: |
| + nm_files = json.load(FILE) |
| + |
| + symbol_table = {} |
| + 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 FILE: |
| + symbol_table[entry.name] = get_procedure_boundaries_from_nm_bsd( |
| + FILE, nm_files[entry.name]['mangled']) |
| + |
| + for address in addresses: |
| + if isinstance(address, str): |
| + address = int(address, 16) |
| + is_found = False |
| + for entry in maps.iter(_executable_condition): |
| + if (entry.begin <= address and address < entry.end): |
|
M-A Ruel
2012/07/19 15:21:15
if entry.begin <= address < entry.end:
is valid py
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
Done.
|
| + if symbol_table.has_key(entry.name): |
|
M-A Ruel
2012/07/19 15:21:15
if entry.name in symbol_table:
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
Done.
|
| + found = symbol_table[entry.name].find_procedure( |
| + address - (entry.begin - entry.offset)) |
| + outputter.output(address, found) |
| + is_found = True |
| + else: |
| + outputter.output(address) |
| + is_found = True |
|
M-A Ruel
2012/07/19 15:21:15
move this assignment out of the condition.
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
Done.
|
| + break |
| + if not is_found: |
| + outputter.output(address) |
| + |
| + return 0 |
|
M-A Ruel
2012/07/19 15:21:15
Why not return a list and have it output after? E.
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
It's to allow a file object for outputter (_FileOu
|
| + |
| + |
| +def find_runtime_symbols_list(prepared_data_dir, addresses): |
| + result = [] |
| + _find_runtime_symbols(prepared_data_dir, addresses, _ListOutput(result)) |
| + return result |
| + |
| + |
| +def find_runtime_symbols_dict(prepared_data_dir, addresses): |
| + result = {} |
| + _find_runtime_symbols(prepared_data_dir, addresses, _DictOutput(result)) |
| + return result |
| + |
| + |
| +def find_runtime_symbols_file(prepared_data_dir, addresses, FILE): |
| + _find_runtime_symbols( |
| + prepared_data_dir, addresses, _FileOutput(sys.stdout, False)) |
| + |
| + |
| +if __name__ == '__main__': |
| + # FIX: Accept only .pre data |
|
M-A Ruel
2012/07/19 15:21:15
Use a main() in every file where the code is not t
Dai Mikurube (NOT FULLTIME)
2012/07/20 04:32:39
I was misunderstanding about Python modules. I wa
|
| + if len(sys.argv) < 2: |
| + sys.stderr.write("""Usage: |
| +%s /path/to/prepared_data_dir/ < addresses.txt |
| +""" % sys.argv[0]) |
| + sys.exit(1) |
| + |
| + sys.exit(find_runtime_symbols_file(sys.argv[1], sys.stdin, sys.stdout)) |