diff options
author | dmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-03 06:32:40 +0000 |
---|---|---|
committer | dmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-03 06:32:40 +0000 |
commit | c6400ce9269d39d5b413c9b17a55f8ff1840456a (patch) | |
tree | f6620ef5dcc36d4be9cd84468545b0fe43df9f92 | |
parent | d42144308fc22012382756ff5c4295ab78b3f0fe (diff) | |
download | chromium_src-c6400ce9269d39d5b413c9b17a55f8ff1840456a.zip chromium_src-c6400ce9269d39d5b413c9b17a55f8ff1840456a.tar.gz chromium_src-c6400ce9269d39d5b413c9b17a55f8ff1840456a.tar.bz2 |
Add hints to find source file names from runtime virtual addresses.
prepare_symbol_info.py collected symbol and elf mapping information
from binaries. This patch adds another set of hints to find source
file names from DWARF .debug_line information with readelf.
reduce_debugline.py picks up only address ranges from the original
readelf output since the original output is too large. See
the test how it works.
BUG=225343
NOTRY=true
Review URL: https://chromiumcodereview.appspot.com/13261014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192004 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-x | tools/find_runtime_symbols/prepare_symbol_info.py | 8 | ||||
-rwxr-xr-x | tools/find_runtime_symbols/reduce_debugline.py | 85 | ||||
-rwxr-xr-x | tools/find_runtime_symbols/tests/reduce_debugline_test.py | 137 |
3 files changed, 230 insertions, 0 deletions
diff --git a/tools/find_runtime_symbols/prepare_symbol_info.py b/tools/find_runtime_symbols/prepare_symbol_info.py index 9b16225..5289cb8 100755 --- a/tools/find_runtime_symbols/prepare_symbol_info.py +++ b/tools/find_runtime_symbols/prepare_symbol_info.py @@ -15,6 +15,8 @@ import tempfile from proc_maps import ProcMaps +BASE_PATH = os.path.dirname(os.path.abspath(__file__)) +REDUCE_DEBUGLINE_PATH = os.path.join(BASE_PATH, 'reduce_debugline.py') LOGGER = logging.getLogger('prepare_symbol_info') @@ -142,6 +144,9 @@ def prepare_symbol_info(maps_path, output_dir_path=None, use_tempdir=False): output_dir_path, os.path.basename(entry.name), '.readelf-e') if not readelf_e_filename: continue + readelf_reduced_debugline_filename = _dump_command_result( + 'readelf -wLW %s | %s' % (entry.name, REDUCE_DEBUGLINE_PATH), + output_dir_path, os.path.basename(entry.name), '.readelf-debugline') files[entry.name] = {} files[entry.name]['nm'] = { @@ -150,6 +155,9 @@ def prepare_symbol_info(maps_path, output_dir_path=None, use_tempdir=False): 'mangled': False} files[entry.name]['readelf-e'] = { 'file': os.path.basename(readelf_e_filename)} + if readelf_reduced_debugline_filename: + files[entry.name]['readelf-reduced-debugline'] = { + 'file': os.path.basename(readelf_reduced_debugline_filename)} with open(os.path.join(output_dir_path, 'files.json'), 'w') as f: json.dump(files, f, indent=2, sort_keys=True) diff --git a/tools/find_runtime_symbols/reduce_debugline.py b/tools/find_runtime_symbols/reduce_debugline.py new file mode 100755 index 0000000..1a4efaa --- /dev/null +++ b/tools/find_runtime_symbols/reduce_debugline.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# Copyright (c) 2013 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. +"""Reduces result of 'readelf -wL' to just a set of address ranges per file. + +For example: + +CU: ../../chrome_main.cc: +File name Line number Starting address +chrome_main.cc 30 0xa3be90 +(an empty line) +chrome_main.cc 31 0xa3bea3 +chrome_main.cc 32 0xa3beaf +chrome_main.cc 34 0xa3bec9 +chrome_main.cc 32 0xa3bed1 +(an empty line) + +The example above is reduced into: +{'../../chrome_main.cc', [(0xa3be90, 0xa3be90), (0xa3bea3, 0xa3bed1)]} +where (0xa3bea3, 0xa3bed1) means an address range from 0xa3bea3 to 0xa3bed1. + +This script assumes that the result of 'readelf -wL' ends with an empty line. + +Note: the option '-wL' has the same meaning with '--debug-dump=decodedline'. +""" + +import re +import sys + + +_FILENAME_PATTERN = re.compile('(CU: |)(.+)\:') + + +def reduce_decoded_debugline(input_file): + filename = '' + ranges_dict = {} + starting = None + ending = None + + for line in input_file: + line = line.strip() + + if line.endswith(':'): + matched = _FILENAME_PATTERN.match(line) + if matched: + filename = matched.group(2) + continue + + unpacked = line.split(None, 2) + if len(unpacked) != 3 or not unpacked[2].startswith('0x'): + if starting: + ranges_dict.setdefault(filename, []).append((starting, ending)) + starting = None + ending = None + continue + + ending = int(unpacked[2], 16) + if not starting: + starting = ending + + if starting or ending: + raise ValueError('No new line at last.') + + return ranges_dict + + +def main(): + if len(sys.argv) != 1: + print >> sys.stderr, 'Unsupported arguments' + return 1 + + ranges_dict = reduce_decoded_debugline(sys.stdin) + for filename, ranges in ranges_dict.iteritems(): + print filename + ':' + prev = (0, 0) + for address_range in sorted(ranges): + if address_range == prev: + continue + print ' %x-%x' % (address_range[0], address_range[1]) + prev = address_range + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/find_runtime_symbols/tests/reduce_debugline_test.py b/tools/find_runtime_symbols/tests/reduce_debugline_test.py new file mode 100755 index 0000000..04488a5 --- /dev/null +++ b/tools/find_runtime_symbols/tests/reduce_debugline_test.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python +# Copyright (c) 2013 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 cStringIO +import logging +import os +import sys +import textwrap +import unittest + +ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, ROOT_DIR) + +import reduce_debugline + + +class ReduceDebuglineTest(unittest.TestCase): + _DECODED_DEBUGLINE = textwrap.dedent("""\ + Decoded dump of debug contents of section .debug_line: + + CU: ../../chrome/app/chrome_exe_main_gtk.cc: + File name Line number Starting address + chrome_exe_main_gtk.cc 33 0xa3be50 + + chrome_exe_main_gtk.cc 34 0xa3be66 + chrome_exe_main_gtk.cc 39 0xa3be75 + chrome_exe_main_gtk.cc 42 0xa3be7a + + CU: ../../chrome/app/chrome_main.cc: + File name Line number Starting address + chrome_main.cc 30 0xa3be90 + + chrome_main.cc 31 0xa3bea3 + chrome_main.cc 32 0xa3beaf + chrome_main.cc 34 0xa3bec9 + chrome_main.cc 32 0xa3bed1 + + CU: ../../chrome/app/chrome_main_delegate.cc: + File name Line number Starting address + chrome_main_delegate.cc 320 0xa3bee0 + + chrome_main_delegate.cc 320 0xa3bef0 + chrome_main_delegate.cc 321 0xa3bf43 + chrome_main_delegate.cc 322 0xa3bf48 + chrome_main_delegate.cc 324 0xa3bf50 + chrome_main_delegate.cc 324 0xa3bf60 + + chrome_main_delegate.cc 612 0xa3cd54 + chrome_main_delegate.cc 617 0xa3cd6b + chrome_main_delegate.cc 299 0xa3d5fd + chrome_main_delegate.cc 300 0xa3d605 + + ../../content/public/app/content_main_delegate.h: + content_main_delegate.h 22 0xa3d620 + + content_main_delegate.h 22 0xa3d637 + + ../../chrome/common/chrome_content_client.h: + chrome_content_client.h 16 0xa3d640 + + chrome_content_client.h 16 0xa3d650 + + ../../base/memory/scoped_ptr.h: + scoped_ptr.h 323 0xa3d680 + + scoped_ptr.h 323 0xa3d690 + + ../../base/memory/scoped_ptr.h: + scoped_ptr.h 323 0xa3d660 + + scoped_ptr.h 323 0xa3d670 + + ../../base/memory/scoped_ptr.h: + scoped_ptr.h 428 0xa3d6a0 + + scoped_ptr.h 428 0xa3d6b0 + + CU: ../../something.c: + File name Line number Starting address + something.c 57 0x76e2cc0 + + something.c 62 0x76e2cd3 + something.c 64 0x76e2cda + something.c 65 0x76e2ce9 + something.c 66 0x76e2cf8 + + """) + + _EXPECTED_REDUCED_DEBUGLINE = { + '../../chrome/app/chrome_exe_main_gtk.cc': [ + (0xa3be50, 0xa3be50), + (0xa3be66, 0xa3be7a), + ], + '../../chrome/app/chrome_main.cc': [ + (0xa3be90, 0xa3be90), + (0xa3bea3, 0xa3bed1), + ], + '../../chrome/app/chrome_main_delegate.cc': [ + (0xa3bee0, 0xa3bee0), + (0xa3bef0, 0xa3bf60), + (0xa3cd54, 0xa3d605), + ], + '../../content/public/app/content_main_delegate.h': [ + (0xa3d620, 0xa3d620), + (0xa3d637, 0xa3d637), + ], + '../../chrome/common/chrome_content_client.h': [ + (0xa3d640, 0xa3d640), + (0xa3d650, 0xa3d650), + ], + '../../base/memory/scoped_ptr.h': [ + (0xa3d680, 0xa3d680), + (0xa3d690, 0xa3d690), + (0xa3d660, 0xa3d660), + (0xa3d670, 0xa3d670), + (0xa3d6a0, 0xa3d6a0), + (0xa3d6b0, 0xa3d6b0), + ], + '../../something.c': [ + (0x76e2cc0, 0x76e2cc0), + (0x76e2cd3, 0x76e2cf8), + ], + } + + def test(self): + ranges_dict = reduce_debugline.reduce_decoded_debugline( + cStringIO.StringIO(self._DECODED_DEBUGLINE)) + self.assertEqual(self._EXPECTED_REDUCED_DEBUGLINE, ranges_dict) + + +if __name__ == '__main__': + logging.basicConfig( + level=logging.DEBUG if '-v' in sys.argv else logging.ERROR, + format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') + unittest.main() |