OLD | NEW |
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: | 9 # About linker maps: |
10 # * "Discarded input sections" include symbols merged with other symbols | 10 # * "Discarded input sections" include symbols merged with other symbols |
(...skipping 17 matching lines...) Expand all Loading... |
28 def Parse(self, lines): | 28 def Parse(self, lines): |
29 """Parses a linker map file. | 29 """Parses a linker map file. |
30 | 30 |
31 Args: | 31 Args: |
32 lines: Iterable of lines. | 32 lines: Iterable of lines. |
33 | 33 |
34 Returns: | 34 Returns: |
35 A tuple of (section_sizes, symbols). | 35 A tuple of (section_sizes, symbols). |
36 """ | 36 """ |
37 self._lines = iter(lines) | 37 self._lines = iter(lines) |
38 logging.info('Parsing common symbols') | 38 logging.debug('Scanning for Header') |
39 self._common_symbols = self._ParseCommonSymbols() | 39 |
40 logging.debug('.bss common entries: %d', len(self._common_symbols)) | 40 while True: |
41 logging.info('Parsing section symbols') | 41 line = self._SkipToLineWithPrefix('Common symbol', 'Memory map') |
42 self._ParseSections() | 42 if line.startswith('Common symbol'): |
| 43 self._common_symbols = self._ParseCommonSymbols() |
| 44 logging.debug('.bss common entries: %d', len(self._common_symbols)) |
| 45 continue |
| 46 elif line.startswith('Memory map'): |
| 47 self._ParseSections() |
| 48 break |
43 return self._section_sizes, self._symbols | 49 return self._section_sizes, self._symbols |
44 | 50 |
45 def _SkipToLineWithPrefix(self, prefix): | 51 def _SkipToLineWithPrefix(self, prefix, prefix2=None): |
46 for l in self._lines: | 52 for l in self._lines: |
47 if l.startswith(prefix): | 53 if l.startswith(prefix) or (prefix2 and l.startswith(prefix2)): |
48 return l | 54 return l |
49 | 55 |
50 def _ParsePossiblyWrappedParts(self, line, count): | 56 def _ParsePossiblyWrappedParts(self, line, count): |
51 parts = line.split(None, count - 1) | 57 parts = line.split(None, count - 1) |
52 if not parts: | 58 if not parts: |
53 return None | 59 return None |
54 if len(parts) != count: | 60 if len(parts) != count: |
55 line = next(self._lines) | 61 line = next(self._lines) |
56 parts.extend(line.split(None, count - len(parts) - 1)) | 62 parts.extend(line.split(None, count - len(parts) - 1)) |
57 assert len(parts) == count, 'parts: ' + ' '.join(parts) | 63 assert len(parts) == count, 'parts: ' + ' '.join(parts) |
58 parts[-1] = parts[-1].rstrip() | 64 parts[-1] = parts[-1].rstrip() |
59 return parts | 65 return parts |
60 | 66 |
61 def _ParseCommonSymbols(self): | 67 def _ParseCommonSymbols(self): |
62 # Common symbol size file | 68 # Common symbol size file |
63 # | 69 # |
64 # ff_cos_131072 0x40000 obj/third_party/<snip> | 70 # ff_cos_131072 0x40000 obj/third_party/<snip> |
65 # ff_cos_131072_fixed | 71 # ff_cos_131072_fixed |
66 # 0x20000 obj/third_party/<snip> | 72 # 0x20000 obj/third_party/<snip> |
67 ret = [] | 73 ret = [] |
68 self._SkipToLineWithPrefix('Common symbol') | |
69 next(self._lines) # Skip past blank line | 74 next(self._lines) # Skip past blank line |
70 | 75 |
71 name, size_str, path = None, None, None | 76 name, size_str, path = None, None, None |
72 for l in self._lines: | 77 for l in self._lines: |
73 parts = self._ParsePossiblyWrappedParts(l, 3) | 78 parts = self._ParsePossiblyWrappedParts(l, 3) |
74 if not parts: | 79 if not parts: |
75 break | 80 break |
76 name, size_str, path = parts | 81 name, size_str, path = parts |
77 sym = models.Symbol('.bss', int(size_str[2:], 16), name=name, | 82 sym = models.Symbol('.bss', int(size_str[2:], 16), name=name, |
78 object_path=path) | 83 object_path=path) |
(...skipping 19 matching lines...) Expand all Loading... |
98 # 0x02d4b294 guard variable for void GrProcessor::initClassID | 103 # 0x02d4b294 guard variable for void GrProcessor::initClassID |
99 # .data 0x0028c600 0x22d3468 | 104 # .data 0x0028c600 0x22d3468 |
100 # .data.rel.ro._ZTVN3gvr7android19ScopedJavaGlobalRefIP12_jfloatArrayEE | 105 # .data.rel.ro._ZTVN3gvr7android19ScopedJavaGlobalRefIP12_jfloatArrayEE |
101 # 0x02d1e668 0x10 ../../third_party/.../libfoo.a(bar.o) | 106 # 0x02d1e668 0x10 ../../third_party/.../libfoo.a(bar.o) |
102 # 0x02d1e668 vtable for gvr::android::GlobalRef<_jfloatArray*> | 107 # 0x02d1e668 vtable for gvr::android::GlobalRef<_jfloatArray*> |
103 # ** merge strings | 108 # ** merge strings |
104 # 0x0255fb00 0x1f2424 | 109 # 0x0255fb00 0x1f2424 |
105 # ** merge constants | 110 # ** merge constants |
106 # 0x0255fb00 0x8 | 111 # 0x0255fb00 0x8 |
107 # ** common 0x02db5700 0x13ab48 | 112 # ** common 0x02db5700 0x13ab48 |
108 self._SkipToLineWithPrefix('Memory map') | |
109 syms = self._symbols | 113 syms = self._symbols |
110 symbol_gap_count = 0 | 114 symbol_gap_count = 0 |
111 while True: | 115 while True: |
112 line = self._SkipToLineWithPrefix('.') | 116 line = self._SkipToLineWithPrefix('.') |
113 if not line: | 117 if not line: |
114 break | 118 break |
115 section_name = None | 119 section_name = None |
116 try: | 120 try: |
117 # Parse section name and size. | 121 # Parse section name and size. |
118 parts = self._ParsePossiblyWrappedParts(line, 3) | 122 parts = self._ParsePossiblyWrappedParts(line, 3) |
119 if not parts: | 123 if not parts: |
120 break | 124 break |
121 section_name, address, size_str = parts | 125 section_name, section_address_str, section_size_str = parts |
122 self._section_sizes[section_name] = int(size_str[2:], 16) | 126 section_address = int(section_address_str[2:], 16) |
| 127 section_size = int(section_size_str[2:], 16) |
| 128 self._section_sizes[section_name] = section_size |
123 if (section_name in ('.bss', '.rodata', '.text') or | 129 if (section_name in ('.bss', '.rodata', '.text') or |
124 section_name.startswith('.data')): | 130 section_name.startswith('.data')): |
125 logging.info('Parsing %s', section_name) | 131 logging.info('Parsing %s', section_name) |
126 if section_name == '.bss': | 132 if section_name == '.bss': |
| 133 # Common symbols have no address. |
127 syms.extend(self._common_symbols) | 134 syms.extend(self._common_symbols) |
128 prefix_len = len(section_name) + 1 # + 1 for the trailing . | 135 prefix_len = len(section_name) + 1 # + 1 for the trailing . |
129 merge_symbol_start_address = 0 | 136 merge_symbol_start_address = section_address |
130 sym_count_at_start = len(syms) | 137 sym_count_at_start = len(syms) |
131 line = next(self._lines) | 138 line = next(self._lines) |
132 # Parse section symbols. | 139 # Parse section symbols. |
133 while True: | 140 while True: |
134 if not line or line.isspace(): | 141 if not line or line.isspace(): |
135 break | 142 break |
136 if line.startswith(' **'): | 143 if line.startswith(' **'): |
137 zero_index = line.find('0') | 144 zero_index = line.find('0') |
138 if zero_index == -1: | 145 if zero_index == -1: |
139 # Line wraps. | 146 # Line wraps. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 else: | 202 else: |
196 logging.warning('First symbol of section had address -1') | 203 logging.warning('First symbol of section had address -1') |
197 address = 0 | 204 address = 0 |
198 | 205 |
199 merge_symbol_start_address = address + size | 206 merge_symbol_start_address = address + size |
200 else: | 207 else: |
201 address = int(address_str[2:], 16) | 208 address = int(address_str[2:], 16) |
202 # Finish off active address gap / merge section. | 209 # Finish off active address gap / merge section. |
203 if merge_symbol_start_address: | 210 if merge_symbol_start_address: |
204 merge_size = address - merge_symbol_start_address | 211 merge_size = address - merge_symbol_start_address |
205 logging.debug('Merge symbol of size %d found at:\n %r', | |
206 merge_size, syms[-1]) | |
207 # Set size=0 so that it will show up as padding. | |
208 sym = models.Symbol( | |
209 section_name, 0, | |
210 address=address, | |
211 name='** symbol gap %d' % symbol_gap_count, | |
212 object_path=path) | |
213 symbol_gap_count += 1 | |
214 syms.append(sym) | |
215 merge_symbol_start_address = 0 | 212 merge_symbol_start_address = 0 |
| 213 if merge_size > 0: |
| 214 # merge_size == 0 for the initial symbol generally. |
| 215 logging.debug('Merge symbol of size %d found at:\n %r', |
| 216 merge_size, syms[-1]) |
| 217 # Set size=0 so that it will show up as padding. |
| 218 sym = models.Symbol( |
| 219 section_name, 0, |
| 220 address=address, |
| 221 name='** symbol gap %d' % symbol_gap_count, |
| 222 object_path=path) |
| 223 symbol_gap_count += 1 |
| 224 syms.append(sym) |
216 | 225 |
217 sym = models.Symbol(section_name, size, address=address, | 226 sym = models.Symbol(section_name, size, address=address, |
218 name=name or mangled_name, object_path=path) | 227 name=name or mangled_name, object_path=path) |
219 syms.append(sym) | 228 syms.append(sym) |
| 229 section_end_address = section_address + section_size |
| 230 if section_name != '.bss' and ( |
| 231 syms[-1].end_address < section_end_address): |
| 232 # Set size=0 so that it will show up as padding. |
| 233 sym = models.Symbol( |
| 234 section_name, 0, |
| 235 address=section_end_address, |
| 236 name='** symbol gap %d (end of section)' % symbol_gap_count) |
| 237 syms.append(sym) |
220 logging.debug('Symbol count for %s: %d', section_name, | 238 logging.debug('Symbol count for %s: %d', section_name, |
221 len(syms) - sym_count_at_start) | 239 len(syms) - sym_count_at_start) |
222 except: | 240 except: |
223 logging.error('Problem line: %r', line) | 241 logging.error('Problem line: %r', line) |
224 logging.error('In section: %r', section_name) | 242 logging.error('In section: %r', section_name) |
225 raise | 243 raise |
OLD | NEW |