Change log:95336cb92b..191d55580eFull diff:95336cb92b..191d55580eRoll chromium third_party 4e16929f46..3a8f2a9e1e Change log:4e16929f46..3a8f2a9e1eChanged dependencies: * src/tools:c44a3f5eca..f524a53b81DEPS diff:95336cb92b..191d55580e/DEPS No update to Clang. TBR=titovartem@google.com, BUG=None CQ_INCLUDE_TRYBOTS=master.internal.tryserver.corp.webrtc:linux_internal Change-Id: Ic9c4a62b050383646e9fcf5cc07a5653c14ac06e Reviewed-on: https://webrtc-review.googlesource.com/76120 Reviewed-by: Patrik Höglund <phoglund@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Reviewed-by: Artem Titov <titovartem@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23205}
134 lines
4.1 KiB
Python
Executable File
134 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Copyright (c) 2015 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.
|
|
|
|
|
|
"""Identifies address adjustments required for native crash dumps."""
|
|
|
|
import glob
|
|
import os.path
|
|
import re
|
|
import subprocess
|
|
|
|
|
|
_BASE_APK = 'base.apk'
|
|
_LIBCHROME_SO = 'libchrome.so'
|
|
|
|
_BUILD_FINGERPRINT_RE = re.compile('.*Build fingerprint: (.*)$')
|
|
|
|
|
|
def GetTargetAndroidVersionNumber(lines):
|
|
"""Return the Android major version number from the build fingerprint.
|
|
|
|
Args:
|
|
lines: Lines read from the tombstone file, before preprocessing.
|
|
Returns:
|
|
5, 6, etc, or None if not determinable (developer build?)
|
|
"""
|
|
# For example, "Build fingerprint: 'Android/aosp_flo/flo:5.1.1/...'" is 5.
|
|
for line in lines:
|
|
m = _BUILD_FINGERPRINT_RE.match(line)
|
|
if not m:
|
|
continue
|
|
fingerprint = m.group(1)
|
|
try:
|
|
version = fingerprint.split('/')[2].split(':')[1].split('.')[0]
|
|
return int(version)
|
|
except Exception:
|
|
pass
|
|
return None
|
|
|
|
|
|
def _HasElfHeader(path):
|
|
"""Return True if the file at the given path has an ELF magic header.
|
|
|
|
Minimal check only, for 'ELF' in bytes 1 to 3 of the file. Filters out
|
|
the zero-byte false-positives such as libchromeview.so returned by glob.
|
|
|
|
Args:
|
|
path: Path to file to check.
|
|
Returns:
|
|
True or False
|
|
"""
|
|
with open(path) as stream:
|
|
elf_header = stream.read(4)
|
|
return len(elf_header) == 4 and elf_header[1:4] == 'ELF'
|
|
|
|
|
|
def _ReadElfProgramHeaders(lib):
|
|
"""Return an iterable of program headers, from 'readelf -l ...'.
|
|
|
|
Uses the platform readelf in all cases. This is somewhat lazy, but suffices
|
|
in practice because program headers in ELF files are architecture-agnostic.
|
|
|
|
Args:
|
|
lib: Library file to read.
|
|
Returns:
|
|
[readelf -l output line, ...]
|
|
"""
|
|
string = subprocess.check_output(['readelf', '-l', lib])
|
|
return string.split('\n')
|
|
|
|
|
|
def _FindMinLoadVaddr(lib):
|
|
"""Return the minimum VirtAddr field of all library LOAD segments.
|
|
|
|
Args:
|
|
lib: Library file to read.
|
|
Returns:
|
|
Min VirtAddr field for all LOAD segments, or 0 if none found.
|
|
"""
|
|
vaddrs = []
|
|
# Locate LOAD lines and find the smallest VirtAddr field, eg:
|
|
# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
|
|
# LOAD 0x000000 0x001d6000 0x001d6000 0x20f63fc 0x20f63fc R E 0x1000
|
|
# LOAD 0x20f6970 0x022cd970 0x022cd970 0x182df8 0x1b4490 RW 0x1000
|
|
# would return 0x1d6000. Ignores all non-LOAD lines.
|
|
for line in _ReadElfProgramHeaders(lib):
|
|
elements = line.split()
|
|
if elements and elements[0] == 'LOAD':
|
|
vaddrs.append(int(elements[2], 16))
|
|
if vaddrs:
|
|
return min(vaddrs)
|
|
return 0
|
|
|
|
|
|
def GetLoadVaddrs(stripped_libs=None, stripped_libs_dir=None):
|
|
"""Return a dict of minimum VirtAddr for libraries in the given directory.
|
|
|
|
The dictionary returned may be passed to stack_core.ConvertTrace(). In
|
|
pre-M Android releases the addresses printed by debuggerd into tombstones
|
|
do not take account of non-zero vaddrs. Here we collect this information,
|
|
so that we can use it later to correct such debuggerd tombstones.
|
|
|
|
Args:
|
|
stripped_libs_dir: Path to directory containing apk's stripped libraries.
|
|
Returns:
|
|
{'libchrome.so': 12345, ...}
|
|
"""
|
|
if not stripped_libs:
|
|
stripped_libs = []
|
|
if stripped_libs_dir:
|
|
stripped_libs.extend(glob.glob(os.path.join(stripped_libs_dir, '*.so')))
|
|
libs = [l for l in stripped_libs if _HasElfHeader(l)]
|
|
|
|
load_vaddrs = {}
|
|
for lib in libs:
|
|
min_vaddr = _FindMinLoadVaddr(lib)
|
|
if min_vaddr:
|
|
# Store with the library basename as the key. This is because once on
|
|
# the device its path may not fully match its place in the APK staging
|
|
# directory
|
|
load_vaddrs[os.path.basename(lib)] = min_vaddr
|
|
|
|
# Direct load from APK causes debuggerd to tag trace lines as if from the
|
|
# file .../base.apk. So if we encounter a libchrome.so with packed
|
|
# relocations, replicate this as base.apk so that later adjustment code
|
|
# finds the appropriate adjustment.
|
|
if _LIBCHROME_SO in load_vaddrs:
|
|
load_vaddrs[_BASE_APK] = load_vaddrs[_LIBCHROME_SO]
|
|
|
|
return load_vaddrs
|