Commit 85ddfa5c authored by Samuel Huang's avatar Samuel Huang Committed by Commit Bot

[SuperSize] linker_map_parser.py: Add main() for interactive debugging.

This CL adds main() to linker_map_parser.py, so it can be used to
parse a linker map file directly. The results are then made available
to an interactive Python console for further analysis.

Also fix LLD .map file parsing to ignore 'PROVIDE_HIDDEN' lines that
appear at the end of .map files and get confused with actual sections.

Change-Id: Ice5a3b52495ed4eecd5deab7d890344bf740a20f
Reviewed-on: https://chromium-review.googlesource.com/c/1334275Reviewed-by: default avatarSamuel Huang <huangs@chromium.org>
Reviewed-by: default avatarEric Stevenson <estevenson@chromium.org>
Commit-Queue: Samuel Huang <huangs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607789}
parent 85403e29
#!/usr/bin/env python
# Copyright 2017 The Chromium Authors. All rights reserved. # Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import demangle """Parser for linker map files."""
from __future__ import print_function
import argparse
import code
import logging import logging
import os import os
import re import re
import readline
import demangle
import models import models
# About linker maps: # About linker maps:
...@@ -362,6 +370,7 @@ class MapFileParserLld(object): ...@@ -362,6 +370,7 @@ class MapFileParserLld(object):
if indent_size == 0: if indent_size == 0:
sym_maker.Flush() sym_maker.Flush()
if not tok.startswith('PROVIDE_HIDDEN'):
self._section_sizes[tok] = size self._section_sizes[tok] = size
cur_section = tok cur_section = tok
# E.g., Want to convert "(.text._name)" -> "_name" later. # E.g., Want to convert "(.text._name)" -> "_name" later.
...@@ -454,7 +463,15 @@ def _DetectLto(lines): ...@@ -454,7 +463,15 @@ def _DetectLto(lines):
def DetectLinkerNameFromMapFile(lines): def DetectLinkerNameFromMapFile(lines):
"""Scans linker map file, and returns a coded linker name.""" """Heuristic linker detection from partial scan of the linker map.
Args:
lines: Iterable of lines from the linker map.
Returns:
A coded linker name: 'gold', 'lld_v#' (# is a number), or 'lld-lto_v#'.
"""
first_line = next(lines) first_line = next(lines)
if first_line.startswith('Address'): if first_line.startswith('Address'):
...@@ -470,12 +487,13 @@ def DetectLinkerNameFromMapFile(lines): ...@@ -470,12 +487,13 @@ def DetectLinkerNameFromMapFile(lines):
class MapFileParser(object): class MapFileParser(object):
"""Parses a linker map file, with heuristic linker detection.""" """Parses a linker map file generated from a specified linker."""
def Parse(self, linker_name, lines): def Parse(self, linker_name, lines):
"""Parses a linker map file. """Parses a linker map file.
Args: Args:
lines: Iterable of lines. linker_name: Coded linker name to specify a linker.
lines: Iterable of lines from the linker map.
Returns: Returns:
A tuple of (section_sizes, symbols). A tuple of (section_sizes, symbols).
...@@ -495,3 +513,42 @@ class MapFileParser(object): ...@@ -495,3 +513,42 @@ class MapFileParser(object):
# Thin archives' paths will get fixed in |ar.CreateThinObjectPath|. # Thin archives' paths will get fixed in |ar.CreateThinObjectPath|.
sym.object_path = os.path.normpath(sym.object_path) sym.object_path = os.path.normpath(sym.object_path)
return (section_sizes, syms) return (section_sizes, syms)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('linker_file', type=os.path.realpath)
parser.add_argument(
'-v',
'--verbose',
default=0,
action='count',
help='Verbose level (multiple times for more)')
args = parser.parse_args()
logging.basicConfig(
level=logging.WARNING - args.verbose * 10,
format='%(levelname).1s %(relativeCreated)6d %(message)s')
with open(args.linker_file, 'r') as map_file:
linker_name = DetectLinkerNameFromMapFile(map_file)
print('Linker type: %s' % linker_name)
with open(args.linker_file, 'r') as map_file:
section_sizes, syms = MapFileParser().Parse(linker_name, map_file)
# Enter interactive shell.
readline.parse_and_bind('tab: complete')
variables = {'section_sizes': section_sizes, 'syms': syms}
banner_lines = [
'*' * 80,
'Variables:',
' section_sizes: Map from section to sizes.',
' syms: Raw symbols parsed from the linker map file.',
'*' * 80,
]
code.InteractiveConsole(variables).interact('\n'.join(banner_lines))
if __name__ == '__main__':
main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment