OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 """Reduces result of 'readelf -wL' to just a set of address ranges per file. | 5 """Reduces result of 'readelf -wL' to just a list of starting addresses. |
6 | 6 |
7 For example: | 7 It lists up all addresses where the corresponding source files change. The |
8 | 8 list is sorted in ascending order. See tests/reduce_debugline_test.py for |
9 CU: ../../chrome_main.cc: | 9 examples. |
10 File name Line number Starting address | |
11 chrome_main.cc 30 0xa3be90 | |
12 (an empty line) | |
13 chrome_main.cc 31 0xa3bea3 | |
14 chrome_main.cc 32 0xa3beaf | |
15 chrome_main.cc 34 0xa3bec9 | |
16 chrome_main.cc 32 0xa3bed1 | |
17 (an empty line) | |
18 | |
19 The example above is reduced into: | |
20 {'../../chrome_main.cc', [(0xa3be90, 0xa3be90), (0xa3bea3, 0xa3bed1)]} | |
21 where (0xa3bea3, 0xa3bed1) means an address range from 0xa3bea3 to 0xa3bed1. | |
22 | 10 |
23 This script assumes that the result of 'readelf -wL' ends with an empty line. | 11 This script assumes that the result of 'readelf -wL' ends with an empty line. |
24 | 12 |
25 Note: the option '-wL' has the same meaning with '--debug-dump=decodedline'. | 13 Note: the option '-wL' has the same meaning with '--debug-dump=decodedline'. |
26 """ | 14 """ |
27 | 15 |
28 import re | 16 import re |
29 import sys | 17 import sys |
30 | 18 |
31 | 19 |
32 _FILENAME_PATTERN = re.compile('(CU: |)(.+)\:') | 20 _FILENAME_PATTERN = re.compile('(CU: |)(.+)\:') |
33 | 21 |
34 | 22 |
35 def reduce_decoded_debugline(input_file): | 23 def reduce_decoded_debugline(input_file): |
36 filename = '' | 24 filename = '' |
37 ranges_dict = {} | 25 starting_dict = {} |
38 starting = None | 26 started = False |
39 ending = None | |
40 | 27 |
41 for line in input_file: | 28 for line in input_file: |
42 line = line.strip() | 29 line = line.strip() |
| 30 unpacked = line.split(None, 2) |
43 | 31 |
44 if line.endswith(':'): | 32 if len(unpacked) == 3 and unpacked[2].startswith('0x'): |
45 matched = _FILENAME_PATTERN.match(line) | 33 if not started and filename: |
46 if matched: | 34 started = True |
47 filename = matched.group(2) | 35 starting_dict[int(unpacked[2], 16)] = filename |
48 continue | 36 else: |
| 37 started = False |
| 38 if line.endswith(':'): |
| 39 matched = _FILENAME_PATTERN.match(line) |
| 40 if matched: |
| 41 filename = matched.group(2) |
49 | 42 |
50 unpacked = line.split(None, 2) | 43 starting_list = [] |
51 if len(unpacked) != 3 or not unpacked[2].startswith('0x'): | 44 prev_filename = '' |
52 if starting: | 45 for address in sorted(starting_dict): |
53 ranges_dict.setdefault(filename, []).append((starting, ending)) | 46 curr_filename = starting_dict[address] |
54 starting = None | 47 if prev_filename != curr_filename: |
55 ending = None | 48 starting_list.append((address, starting_dict[address])) |
56 continue | 49 prev_filename = curr_filename |
57 | 50 return starting_list |
58 ending = int(unpacked[2], 16) | |
59 if not starting: | |
60 starting = ending | |
61 | |
62 if starting or ending: | |
63 raise ValueError('No new line at last.') | |
64 | |
65 return ranges_dict | |
66 | 51 |
67 | 52 |
68 def main(): | 53 def main(): |
69 if len(sys.argv) != 1: | 54 if len(sys.argv) != 1: |
70 print >> sys.stderr, 'Unsupported arguments' | 55 print >> sys.stderr, 'Unsupported arguments' |
71 return 1 | 56 return 1 |
72 | 57 |
73 ranges_dict = reduce_decoded_debugline(sys.stdin) | 58 starting_list = reduce_decoded_debugline(sys.stdin) |
74 for filename, ranges in ranges_dict.iteritems(): | 59 bits64 = starting_list[-1][0] > 0xffffffff |
75 print filename + ':' | 60 for address, filename in starting_list: |
76 prev = (0, 0) | 61 if bits64: |
77 for address_range in sorted(ranges): | 62 print '%016x %s' % (address, filename) |
78 if address_range == prev: | 63 else: |
79 continue | 64 print '%08x %s' % (address, filename) |
80 print ' %x-%x' % (address_range[0], address_range[1]) | |
81 prev = address_range | |
82 | 65 |
83 | 66 |
84 if __name__ == '__main__': | 67 if __name__ == '__main__': |
85 sys.exit(main()) | 68 sys.exit(main()) |
OLD | NEW |