Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Unified Diff: tools/find_runtime_symbols/find_runtime_symbols.py

Issue 10795028: A tool for mapping runtime addresses to symbol names. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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))

Powered by Google App Engine
This is Rietveld 408576698