| Index: tools/find_runtime_symbols/prepare_symbol_info.py
|
| diff --git a/tools/find_runtime_symbols/prepare_symbol_info.py b/tools/find_runtime_symbols/prepare_symbol_info.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..57fcfbc3a83d046641379504c93727c61113b911
|
| --- /dev/null
|
| +++ b/tools/find_runtime_symbols/prepare_symbol_info.py
|
| @@ -0,0 +1,121 @@
|
| +#!/usr/bin/env python
|
| +# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +import json
|
| +import logging
|
| +import os
|
| +import re
|
| +import shutil
|
| +import subprocess
|
| +import sys
|
| +import tempfile
|
| +
|
| +from parse_proc_maps import parse_proc_maps
|
| +from util import executable_condition
|
| +
|
| +
|
| +def prepare_symbol_info(maps_path, output_dir_path=None, loglevel=logging.WARN):
|
| + log = logging.getLogger('prepare_symbol_info')
|
| + log.setLevel(loglevel)
|
| + handler = logging.StreamHandler()
|
| + handler.setLevel(loglevel)
|
| + formatter = logging.Formatter('%(message)s')
|
| + handler.setFormatter(formatter)
|
| + log.addHandler(handler)
|
| +
|
| + if not output_dir_path:
|
| + matched = re.match('^(.*)\.maps$', os.path.basename(maps_path))
|
| + if matched:
|
| + output_dir_path = matched.group(1) + '.pre'
|
| + if not output_dir_path:
|
| + matched = re.match('^/proc/(.*)/maps$', os.path.realpath(maps_path))
|
| + if matched:
|
| + output_dir_path = matched.group(1) + '.pre'
|
| + if not output_dir_path:
|
| + output_dir_prefix = os.path.basename(maps_path) + '.pre'
|
| + # TODO(dmikurube): Find another candidate for output_dir_path.
|
| +
|
| + log.info('Data for profiling will be collected in "%s".' % output_dir_path)
|
| + output_dir_path_exists = False
|
| + if os.path.exists(output_dir_path):
|
| + if os.path.isdir(output_dir_path) and not os.listdir(output_dir_path):
|
| + log.warn('Using an empty directory existing at "%s".' % output_dir_path)
|
| + else:
|
| + log.warn('A file or a directory exists at "%s".' % output_dir_path)
|
| + output_dir_path_exists = True
|
| + else:
|
| + log.info('Creating a new directory at "%s".' % output_dir_path)
|
| + os.mkdir(output_dir_path)
|
| +
|
| + if output_dir_path_exists:
|
| + return 1
|
| +
|
| + shutil.copyfile(maps_path, os.path.join(output_dir_path, 'maps'))
|
| +
|
| + with open(maps_path, mode='r') as f:
|
| + maps = parse_proc_maps(f)
|
| +
|
| + log.debug('Listing up symbols.')
|
| + nm_files = {}
|
| + for entry in maps.iter(executable_condition):
|
| + log.debug(' %016x-%016x +%06x %s' % (
|
| + entry.begin, entry.end, entry.offset, entry.name))
|
| + with tempfile.NamedTemporaryFile(
|
| + prefix=os.path.basename(entry.name) + '.',
|
| + suffix='.nm', delete=False, mode='w', dir=output_dir_path) as f:
|
| + nm_filename = os.path.realpath(f.name)
|
| + nm_succeeded = False
|
| + cppfilt_succeeded = False
|
| + p_nm = subprocess.Popen(
|
| + 'nm -n --format bsd %s' % entry.name, shell=True,
|
| + stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
| + p_cppfilt = subprocess.Popen(
|
| + 'c++filt', shell=True,
|
| + stdin=p_nm.stdout, stdout=f, stderr=subprocess.PIPE)
|
| +
|
| + if p_nm.wait() == 0:
|
| + nm_succeeded = True
|
| + for line in p_nm.stderr:
|
| + log.debug(line.rstrip())
|
| + if p_cppfilt.wait() == 0:
|
| + cppfilt_succeeded = True
|
| + for line in p_cppfilt.stderr:
|
| + log.debug(line.rstrip())
|
| +
|
| + if nm_succeeded and cppfilt_succeeded:
|
| + nm_files[entry.name] = {
|
| + 'file': os.path.basename(nm_filename),
|
| + 'format': 'bsd',
|
| + 'mangled': False}
|
| + else:
|
| + os.remove(nm_filename)
|
| +
|
| + with open(os.path.join(output_dir_path, 'nm.json'), 'w') as f:
|
| + json.dump(nm_files, f, indent=2, sort_keys=True)
|
| +
|
| + log.info('Collected symbol information at "%s".' % output_dir_path)
|
| + return 0
|
| +
|
| +
|
| +def main():
|
| + if not sys.platform.startswith('linux'):
|
| + sys.stderr.write('This script work only on Linux.')
|
| + return 1
|
| +
|
| + if len(sys.argv) < 2:
|
| + sys.stderr.write("""Usage:
|
| +%s /path/to/maps [/path/to/output_data_dir/]
|
| +""" % sys.argv[0])
|
| + return 1
|
| + elif len(sys.argv) == 2:
|
| + sys.exit(prepare_symbol_info(sys.argv[1], loglevel=logging.DEBUG))
|
| + else:
|
| + sys.exit(prepare_symbol_info(sys.argv[1], sys.argv[2],
|
| + loglevel=logging.INFO))
|
| + return 0
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + sys.exit(main())
|
|
|