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

Unified Diff: build/android/pylib/symbols/elf_symbolizer.py

Issue 339853004: binary_size_tool: fix for ambiguous addr2line output (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: updated descriptions, rebased, s/os.path.isabs/posixpath.isabs/ Created 6 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | build/android/pylib/symbols/elf_symbolizer_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/android/pylib/symbols/elf_symbolizer.py
diff --git a/build/android/pylib/symbols/elf_symbolizer.py b/build/android/pylib/symbols/elf_symbolizer.py
index b294654f20b1ee3c7f0cdb5c142789f3bc1b5933..08c02d5a8ac056d8f2cf5d79f6da5e8177f8d09c 100644
--- a/build/android/pylib/symbols/elf_symbolizer.py
+++ b/build/android/pylib/symbols/elf_symbolizer.py
@@ -75,7 +75,8 @@ class ELFSymbolizer(object):
"""
def __init__(self, elf_file_path, addr2line_path, callback, inlines=False,
- max_concurrent_jobs=None, addr2line_timeout=30, max_queue_size=50):
+ max_concurrent_jobs=None, addr2line_timeout=30, max_queue_size=50,
+ source_root_path=None, strip_base_path=None):
"""Args:
elf_file_path: path of the elf file to be symbolized.
addr2line_path: path of the toolchain's addr2line binary.
@@ -91,6 +92,18 @@ class ELFSymbolizer(object):
max_queue_size: Max number of outstanding requests per addr2line instance.
addr2line_timeout: Max time (in seconds) to wait for a addr2line response.
After the timeout, the instance will be considered hung and respawned.
+ source_root_path: In some toolchains only the name of the source file is
+ is output, without any path information; disambiguation searches
+ through the source directory specified by |source_root_path| argument
+ for files whose name matches, adding the full path information to the
+ output. For example, if the toolchain outputs "unicode.cc" and there
+ is a file called "unicode.cc" located under |source_root_path|/foo,
+ the tool will replace "unicode.cc" with
+ "|source_root_path|/foo/unicode.cc". If there are multiple files with
+ the same name, disambiguation will fail because the tool cannot
+ determine which of the files was the source of the symbol.
+ strip_base_path: Rebases the symbols source paths onto |source_root_path|
+ (i.e replace |strip_base_path| with |source_root_path).
"""
assert(os.path.isfile(addr2line_path)), 'Cannot find ' + addr2line_path
self.elf_file_path = elf_file_path
@@ -104,6 +117,14 @@ class ELFSymbolizer(object):
self.requests_counter = 0 # For generating monotonic request IDs.
self._a2l_instances = [] # Up to |max_concurrent_jobs| _Addr2Line inst.
+ # If necessary, create disambiguation lookup table
+ self.disambiguate = source_root_path is not None
+ self.disambiguation_table = {}
+ self.strip_base_path = strip_base_path
+ if(self.disambiguate):
+ self.source_root_path = os.path.abspath(source_root_path)
+ self._CreateDisambiguationTable()
+
# Create one addr2line instance. More instances will be created on demand
# (up to |max_concurrent_jobs|) depending on the rate of the requests.
self._CreateNewA2LInstance()
@@ -161,6 +182,15 @@ class ELFSymbolizer(object):
self._a2l_instances.append(a2l)
return a2l
+ def _CreateDisambiguationTable(self):
+ """ Non-unique file names will result in None entries"""
+ self.disambiguation_table = {}
+
+ for root, _, filenames in os.walk(self.source_root_path):
+ for f in filenames:
+ self.disambiguation_table[f] = os.path.join(root, f) if (f not in
+ self.disambiguation_table) else None
+
class Addr2Line(object):
"""A python wrapper around an addr2line instance.
@@ -312,7 +342,28 @@ class ELFSymbolizer(object):
else:
logging.warning('Got invalid symbol path from addr2line: %s' % line2)
- sym_info = ELFSymbolInfo(name, source_path, source_line)
+ # In case disambiguation is on, and needed
+ was_ambiguous = False
+ disambiguated = False
+ if self._symbolizer.disambiguate:
+ if source_path and not posixpath.isabs(source_path):
+ path = self._symbolizer.disambiguation_table.get(source_path)
+ was_ambiguous = True
+ disambiguated = path is not None
+ source_path = path if disambiguated else source_path
+
+ # Use absolute paths (so that paths are consistent, as disambiguation
+ # uses absolute paths)
+ if source_path and not was_ambiguous:
+ source_path = os.path.abspath(source_path)
+
+ if source_path and self._symbolizer.strip_base_path:
+ # Strip the base path
+ source_path = re.sub('^' + self._symbolizer.strip_base_path,
+ self._symbolizer.source_root_path or '', source_path)
+
+ sym_info = ELFSymbolInfo(name, source_path, source_line, was_ambiguous,
+ disambiguated)
if prev_sym_info:
prev_sym_info.inlined_by = sym_info
if not innermost_sym_info:
@@ -393,7 +444,8 @@ class ELFSymbolizer(object):
class ELFSymbolInfo(object):
"""The result of the symbolization passed as first arg. of each callback."""
- def __init__(self, name, source_path, source_line):
+ def __init__(self, name, source_path, source_line, was_ambiguous=False,
+ disambiguated=False):
"""All the fields here can be None (if addr2line replies with '??')."""
self.name = name
self.source_path = source_path
@@ -401,6 +453,8 @@ class ELFSymbolInfo(object):
# In the case of |inlines|=True, the |inlined_by| points to the outer
# function inlining the current one (and so on, to form a chain).
self.inlined_by = None
+ self.disambiguated = disambiguated
+ self.was_ambiguous = was_ambiguous
def __str__(self):
return '%s [%s:%d]' % (
« no previous file with comments | « no previous file | build/android/pylib/symbols/elf_symbolizer_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698