| Index: tools/binary_size/linker_map_parser.py
|
| diff --git a/tools/binary_size/linker_map_parser.py b/tools/binary_size/linker_map_parser.py
|
| deleted file mode 100644
|
| index 5c6eca40740c49c91c3196cbabcea0f191da0659..0000000000000000000000000000000000000000
|
| --- a/tools/binary_size/linker_map_parser.py
|
| +++ /dev/null
|
| @@ -1,213 +0,0 @@
|
| -# Copyright 2017 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 logging
|
| -
|
| -import models
|
| -
|
| -
|
| -class MapFileParser(object):
|
| - """Parses a linker map file (tested only on files from gold linker)."""
|
| - # Map file writer for gold linker:
|
| - # https://github.com/gittup/binutils/blob/HEAD/gold/mapfile.cc
|
| -
|
| - def __init__(self):
|
| - self._symbols = []
|
| - self._section_sizes = {}
|
| - self._lines = None
|
| -
|
| - def Parse(self, lines):
|
| - """Parses a linker map file.
|
| -
|
| - Args:
|
| - lines: Iterable of lines.
|
| -
|
| - Returns:
|
| - A tuple of (section_sizes, symbols).
|
| - """
|
| - self._lines = iter(lines)
|
| - logging.info('Parsing common symbols')
|
| - self._ParseCommonSymbols()
|
| - logging.debug('.bss common entries: %d', len(self._symbols))
|
| - logging.info('Parsing section symbols')
|
| - self._ParseSections()
|
| - return self._section_sizes, self._symbols
|
| -
|
| - def _SkipToLineWithPrefix(self, prefix):
|
| - for l in self._lines:
|
| - if l.startswith(prefix):
|
| - return l
|
| -
|
| - def _ParsePossiblyWrappedParts(self, line, count):
|
| - parts = line.split(None, count - 1)
|
| - if not parts:
|
| - return None
|
| - if len(parts) != count:
|
| - line = next(self._lines)
|
| - parts.extend(line.split(None, count - len(parts) - 1))
|
| - assert len(parts) == count, 'parts: ' + ' '.join(parts)
|
| - parts[-1] = parts[-1].rstrip()
|
| - return parts
|
| -
|
| - def _ParseCommonSymbols(self):
|
| -# Common symbol size file
|
| -#
|
| -# ff_cos_131072 0x40000 obj/third_party/<snip>
|
| -# ff_cos_131072_fixed
|
| -# 0x20000 obj/third_party/<snip>
|
| - self._SkipToLineWithPrefix('Common symbol')
|
| - next(self._lines) # Skip past blank line
|
| -
|
| - name, size_str, path = None, None, None
|
| - for l in self._lines:
|
| - parts = self._ParsePossiblyWrappedParts(l, 3)
|
| - if not parts:
|
| - break
|
| - name, size_str, path = parts
|
| - self._symbols.append(
|
| - models.Symbol('.bss', int(size_str[2:], 16), name=name,
|
| - object_path=path))
|
| -
|
| - def _ParseSections(self):
|
| -# .text 0x0028c600 0x22d3468
|
| -# .text.startup._GLOBAL__sub_I_bbr_sender.cc
|
| -# 0x0028c600 0x38 obj/net/net/bbr_sender.o
|
| -# .text._reset 0x00339d00 0xf0 obj/third_party/icu/icuuc/ucnv.o
|
| -# ** fill 0x0255fb00 0x02
|
| -# .text._ZN4base8AutoLockD2Ev
|
| -# 0x00290710 0xe obj/net/net/file_name.o
|
| -# 0x00290711 base::AutoLock::~AutoLock()
|
| -# 0x00290711 base::AutoLock::~AutoLock()
|
| -# .text._ZNK5blink15LayoutBlockFlow31mustSeparateMarginAfterForChildERK...
|
| -# 0xffffffffffffffff 0x46 obj/...
|
| -# 0x006808e1 blink::LayoutBlockFlow::...
|
| -# .bss
|
| -# .bss._ZGVZN11GrProcessor11initClassIDI10LightingFPEEvvE8kClassID
|
| -# 0x02d4b294 0x4 obj/skia/skia/SkLightingShader.o
|
| -# 0x02d4b294 guard variable for void GrProcessor::initClassID
|
| -# .data 0x0028c600 0x22d3468
|
| -# .data.rel.ro._ZTVN3gvr7android19ScopedJavaGlobalRefIP12_jfloatArrayEE
|
| -# 0x02d1e668 0x10 ../../third_party/.../libfoo.a(bar.o)
|
| -# 0x02d1e668 vtable for gvr::android::GlobalRef<_jfloatArray*>
|
| -# ** merge strings
|
| -# 0x0255fb00 0x1f2424
|
| -# ** merge constants
|
| -# 0x0255fb00 0x8
|
| -# ** common 0x02db5700 0x13ab48
|
| - self._SkipToLineWithPrefix('Memory map')
|
| - syms = self._symbols
|
| - symbol_gap_count = 0
|
| - while True:
|
| - line = self._SkipToLineWithPrefix('.')
|
| - if not line:
|
| - break
|
| - section_name = None
|
| - try:
|
| - # Parse section name and size.
|
| - parts = self._ParsePossiblyWrappedParts(line, 3)
|
| - if not parts:
|
| - break
|
| - section_name, address, size_str = parts
|
| - self._section_sizes[section_name] = int(size_str[2:], 16)
|
| - if (section_name in ('.bss', '.rodata', '.text') or
|
| - section_name.startswith('.data')):
|
| - logging.info('Parsing %s', section_name)
|
| - prefix_len = len(section_name) + 1 # + 1 for the trailing .
|
| - merge_symbol_start_address = 0
|
| - sym_count_at_start = len(syms)
|
| - line = next(self._lines)
|
| - # Parse section symbols.
|
| - while True:
|
| - if not line or line.isspace():
|
| - break
|
| - if line.startswith(' **'):
|
| - zero_index = line.find('0')
|
| - if zero_index == -1:
|
| - # Line wraps.
|
| - name = line.strip()
|
| - line = next(self._lines)
|
| - else:
|
| - # Line does not wrap.
|
| - name = line[:zero_index].strip()
|
| - line = line[zero_index:]
|
| - address_str, size_str = self._ParsePossiblyWrappedParts(line, 2)
|
| - line = next(self._lines)
|
| - # These bytes are already accounted for.
|
| - if name == '** common':
|
| - continue
|
| - address = int(address_str[2:], 16)
|
| - size = int(size_str[2:], 16)
|
| - path = None
|
| - syms.append(
|
| - models.Symbol(section_name, size, address=address, name=name,
|
| - object_path=path))
|
| - else:
|
| - # A normal symbol entry.
|
| - subsection_name, address_str, size_str, path = (
|
| - self._ParsePossiblyWrappedParts(line, 4))
|
| - size = int(size_str[2:], 16)
|
| - assert subsection_name.startswith(section_name), (
|
| - 'subsection name was: ' + subsection_name)
|
| - mangled_name = subsection_name[prefix_len:]
|
| - name = None
|
| - address_str2 = None
|
| - while True:
|
| - line = next(self._lines).rstrip()
|
| - if not line or line.startswith(' .'):
|
| - break
|
| - # clang includes ** fill, but gcc does not.
|
| - if line.startswith(' ** fill'):
|
| - # Alignment explicitly recorded in map file. Rather than
|
| - # record padding based on these entries, we calculate it
|
| - # using addresses. We do this because fill lines are not
|
| - # present when compiling with gcc (only for clang).
|
| - continue
|
| - elif line.startswith(' **'):
|
| - break
|
| - elif name is None:
|
| - address_str2, name = self._ParsePossiblyWrappedParts(line, 2)
|
| -
|
| - if address_str == '0xffffffffffffffff':
|
| - # The section needs special handling (e.g., a merge section)
|
| - # It also generally has a large offset after it, so don't
|
| - # penalize the subsequent symbol for this gap (e.g. a 50kb gap).
|
| - # There seems to be no corelation between where these gaps occur
|
| - # and the symbols they come in-between.
|
| - # TODO(agrieve): Learn more about why this happens.
|
| - if address_str2:
|
| - address = int(address_str2[2:], 16) - 1
|
| - elif syms and syms[-1].address > 0:
|
| - # Merge sym with no second line showing real address.
|
| - address = syms[-1].end_address
|
| - else:
|
| - logging.warning('First symbol of section had address -1')
|
| - address = 0
|
| -
|
| - merge_symbol_start_address = address + size
|
| - else:
|
| - address = int(address_str[2:], 16)
|
| - # Finish off active address gap / merge section.
|
| - if merge_symbol_start_address:
|
| - merge_size = address - merge_symbol_start_address
|
| - logging.debug('Merge symbol of size %d found at:\n %r',
|
| - merge_size, syms[-1])
|
| - # Set size=0 so that it will show up as padding.
|
| - sym = models.Symbol(
|
| - section_name, 0,
|
| - address=address,
|
| - name='** symbol gap %d' % symbol_gap_count,
|
| - object_path=path)
|
| - symbol_gap_count += 1
|
| - syms.append(sym)
|
| - merge_symbol_start_address = 0
|
| -
|
| - syms.append(models.Symbol(section_name, size, address=address,
|
| - name=name or mangled_name,
|
| - object_path=path))
|
| - logging.debug('Symbol count for %s: %d', section_name,
|
| - len(syms) - sym_count_at_start)
|
| - except:
|
| - logging.error('Problem line: %r', line)
|
| - logging.error('In section: %r', section_name)
|
| - raise
|
|
|