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

Side by Side Diff: tools/binary_size/libsupersize/linker_map_parser.py

Issue 2851473003: supersize: Track symbol aliases and shared symbols (Closed)
Patch Set: fix regression in calculate padding introduced in ps3 Created 3 years, 7 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 unified diff | Download patch
OLDNEW
1 # Copyright 2017 The Chromium Authors. All rights reserved. 1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import logging 5 import logging
6 6
7 import models 7 import models
8 8
9 # About linker maps:
10 # * "Discarded input sections" include symbols merged with other symbols
11 # (aliases), so the information there is not actually a list of unused things.
12 # * Linker maps include symbols that do not have names (with object path),
13 # whereas "nm" skips over these (they don't account for much though).
14 # * The parse time for compressed linker maps is dominated by ungzipping.
15
9 16
10 class MapFileParser(object): 17 class MapFileParser(object):
11 """Parses a linker map file (tested only on files from gold linker).""" 18 """Parses a linker map file (tested only on files from gold linker)."""
12 # Map file writer for gold linker: 19 # Map file writer for gold linker:
13 # https://github.com/gittup/binutils/blob/HEAD/gold/mapfile.cc 20 # https://github.com/gittup/binutils/blob/HEAD/gold/mapfile.cc
14 21
15 def __init__(self): 22 def __init__(self):
23 self._common_symbols = []
16 self._symbols = [] 24 self._symbols = []
17 self._section_sizes = {} 25 self._section_sizes = {}
18 self._lines = None 26 self._lines = None
19 27
20 def Parse(self, lines): 28 def Parse(self, lines):
21 """Parses a linker map file. 29 """Parses a linker map file.
22 30
23 Args: 31 Args:
24 lines: Iterable of lines. 32 lines: Iterable of lines.
25 33
26 Returns: 34 Returns:
27 A tuple of (section_sizes, symbols). 35 A tuple of (section_sizes, symbols).
28 """ 36 """
29 self._lines = iter(lines) 37 self._lines = iter(lines)
30 logging.info('Parsing common symbols') 38 logging.info('Parsing common symbols')
31 self._ParseCommonSymbols() 39 self._common_symbols = self._ParseCommonSymbols()
32 logging.debug('.bss common entries: %d', len(self._symbols)) 40 logging.debug('.bss common entries: %d', len(self._common_symbols))
33 logging.info('Parsing section symbols') 41 logging.info('Parsing section symbols')
34 self._ParseSections() 42 self._ParseSections()
35 return self._section_sizes, self._symbols 43 return self._section_sizes, self._symbols
36 44
37 def _SkipToLineWithPrefix(self, prefix): 45 def _SkipToLineWithPrefix(self, prefix):
38 for l in self._lines: 46 for l in self._lines:
39 if l.startswith(prefix): 47 if l.startswith(prefix):
40 return l 48 return l
41 49
42 def _ParsePossiblyWrappedParts(self, line, count): 50 def _ParsePossiblyWrappedParts(self, line, count):
43 parts = line.split(None, count - 1) 51 parts = line.split(None, count - 1)
44 if not parts: 52 if not parts:
45 return None 53 return None
46 if len(parts) != count: 54 if len(parts) != count:
47 line = next(self._lines) 55 line = next(self._lines)
48 parts.extend(line.split(None, count - len(parts) - 1)) 56 parts.extend(line.split(None, count - len(parts) - 1))
49 assert len(parts) == count, 'parts: ' + ' '.join(parts) 57 assert len(parts) == count, 'parts: ' + ' '.join(parts)
50 parts[-1] = parts[-1].rstrip() 58 parts[-1] = parts[-1].rstrip()
51 return parts 59 return parts
52 60
53 def _ParseCommonSymbols(self): 61 def _ParseCommonSymbols(self):
54 # Common symbol size file 62 # Common symbol size file
55 # 63 #
56 # ff_cos_131072 0x40000 obj/third_party/<snip> 64 # ff_cos_131072 0x40000 obj/third_party/<snip>
57 # ff_cos_131072_fixed 65 # ff_cos_131072_fixed
58 # 0x20000 obj/third_party/<snip> 66 # 0x20000 obj/third_party/<snip>
67 ret = []
59 self._SkipToLineWithPrefix('Common symbol') 68 self._SkipToLineWithPrefix('Common symbol')
60 next(self._lines) # Skip past blank line 69 next(self._lines) # Skip past blank line
61 70
62 name, size_str, path = None, None, None 71 name, size_str, path = None, None, None
63 for l in self._lines: 72 for l in self._lines:
64 parts = self._ParsePossiblyWrappedParts(l, 3) 73 parts = self._ParsePossiblyWrappedParts(l, 3)
65 if not parts: 74 if not parts:
66 break 75 break
67 name, size_str, path = parts 76 name, size_str, path = parts
68 self._symbols.append( 77 sym = models.Symbol('.bss', int(size_str[2:], 16), name=name,
69 models.Symbol('.bss', int(size_str[2:], 16), name=name, 78 object_path=path)
70 object_path=path)) 79 ret.append(sym)
80 return ret
71 81
72 def _ParseSections(self): 82 def _ParseSections(self):
73 # .text 0x0028c600 0x22d3468 83 # .text 0x0028c600 0x22d3468
74 # .text.startup._GLOBAL__sub_I_bbr_sender.cc 84 # .text.startup._GLOBAL__sub_I_bbr_sender.cc
75 # 0x0028c600 0x38 obj/net/net/bbr_sender.o 85 # 0x0028c600 0x38 obj/net/net/bbr_sender.o
76 # .text._reset 0x00339d00 0xf0 obj/third_party/icu/icuuc/ucnv.o 86 # .text._reset 0x00339d00 0xf0 obj/third_party/icu/icuuc/ucnv.o
77 # ** fill 0x0255fb00 0x02 87 # ** fill 0x0255fb00 0x02
78 # .text._ZN4base8AutoLockD2Ev 88 # .text._ZN4base8AutoLockD2Ev
79 # 0x00290710 0xe obj/net/net/file_name.o 89 # 0x00290710 0xe obj/net/net/file_name.o
80 # 0x00290711 base::AutoLock::~AutoLock() 90 # 0x00290711 base::AutoLock::~AutoLock()
(...skipping 25 matching lines...) Expand all
106 try: 116 try:
107 # Parse section name and size. 117 # Parse section name and size.
108 parts = self._ParsePossiblyWrappedParts(line, 3) 118 parts = self._ParsePossiblyWrappedParts(line, 3)
109 if not parts: 119 if not parts:
110 break 120 break
111 section_name, address, size_str = parts 121 section_name, address, size_str = parts
112 self._section_sizes[section_name] = int(size_str[2:], 16) 122 self._section_sizes[section_name] = int(size_str[2:], 16)
113 if (section_name in ('.bss', '.rodata', '.text') or 123 if (section_name in ('.bss', '.rodata', '.text') or
114 section_name.startswith('.data')): 124 section_name.startswith('.data')):
115 logging.info('Parsing %s', section_name) 125 logging.info('Parsing %s', section_name)
126 if section_name == '.bss':
127 syms.extend(self._common_symbols)
116 prefix_len = len(section_name) + 1 # + 1 for the trailing . 128 prefix_len = len(section_name) + 1 # + 1 for the trailing .
117 merge_symbol_start_address = 0 129 merge_symbol_start_address = 0
118 sym_count_at_start = len(syms) 130 sym_count_at_start = len(syms)
119 line = next(self._lines) 131 line = next(self._lines)
120 # Parse section symbols. 132 # Parse section symbols.
121 while True: 133 while True:
122 if not line or line.isspace(): 134 if not line or line.isspace():
123 break 135 break
124 if line.startswith(' **'): 136 if line.startswith(' **'):
125 zero_index = line.find('0') 137 zero_index = line.find('0')
126 if zero_index == -1: 138 if zero_index == -1:
127 # Line wraps. 139 # Line wraps.
128 name = line.strip() 140 name = line.strip()
129 line = next(self._lines) 141 line = next(self._lines)
130 else: 142 else:
131 # Line does not wrap. 143 # Line does not wrap.
132 name = line[:zero_index].strip() 144 name = line[:zero_index].strip()
133 line = line[zero_index:] 145 line = line[zero_index:]
134 address_str, size_str = self._ParsePossiblyWrappedParts(line, 2) 146 address_str, size_str = self._ParsePossiblyWrappedParts(line, 2)
135 line = next(self._lines) 147 line = next(self._lines)
136 # These bytes are already accounted for. 148 # These bytes are already accounted for.
137 if name == '** common': 149 if name == '** common':
138 continue 150 continue
139 address = int(address_str[2:], 16) 151 address = int(address_str[2:], 16)
140 size = int(size_str[2:], 16) 152 size = int(size_str[2:], 16)
141 path = None 153 path = None
142 syms.append( 154 sym = models.Symbol(section_name, size, address=address,
143 models.Symbol(section_name, size, address=address, name=name, 155 name=name, object_path=path)
144 object_path=path)) 156 syms.append(sym)
145 else: 157 else:
146 # A normal symbol entry. 158 # A normal symbol entry.
147 subsection_name, address_str, size_str, path = ( 159 subsection_name, address_str, size_str, path = (
148 self._ParsePossiblyWrappedParts(line, 4)) 160 self._ParsePossiblyWrappedParts(line, 4))
149 size = int(size_str[2:], 16) 161 size = int(size_str[2:], 16)
150 assert subsection_name.startswith(section_name), ( 162 assert subsection_name.startswith(section_name), (
151 'subsection name was: ' + subsection_name) 163 'subsection name was: ' + subsection_name)
152 mangled_name = subsection_name[prefix_len:] 164 mangled_name = subsection_name[prefix_len:]
153 name = None 165 name = None
154 address_str2 = None 166 address_str2 = None
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 # Set size=0 so that it will show up as padding. 207 # Set size=0 so that it will show up as padding.
196 sym = models.Symbol( 208 sym = models.Symbol(
197 section_name, 0, 209 section_name, 0,
198 address=address, 210 address=address,
199 name='** symbol gap %d' % symbol_gap_count, 211 name='** symbol gap %d' % symbol_gap_count,
200 object_path=path) 212 object_path=path)
201 symbol_gap_count += 1 213 symbol_gap_count += 1
202 syms.append(sym) 214 syms.append(sym)
203 merge_symbol_start_address = 0 215 merge_symbol_start_address = 0
204 216
205 syms.append(models.Symbol(section_name, size, address=address, 217 sym = models.Symbol(section_name, size, address=address,
206 name=name or mangled_name, 218 name=name or mangled_name, object_path=path)
207 object_path=path)) 219 syms.append(sym)
208 logging.debug('Symbol count for %s: %d', section_name, 220 logging.debug('Symbol count for %s: %d', section_name,
209 len(syms) - sym_count_at_start) 221 len(syms) - sym_count_at_start)
210 except: 222 except:
211 logging.error('Problem line: %r', line) 223 logging.error('Problem line: %r', line)
212 logging.error('In section: %r', section_name) 224 logging.error('In section: %r', section_name)
213 raise 225 raise
OLDNEW
« no previous file with comments | « tools/binary_size/libsupersize/integration_test.py ('k') | tools/binary_size/libsupersize/main.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698