| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright (c) 2015 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 | 7 |
| 8 """Identifies address adjustments required for native crash dumps.""" | 8 """Identifies address adjustments required for native crash dumps.""" |
| 9 | 9 |
| 10 import glob | 10 import glob |
| 11 import os.path | 11 import os.path |
| 12 import re |
| 12 import subprocess | 13 import subprocess |
| 13 | 14 |
| 14 | 15 |
| 15 _BASE_APK = 'base.apk' | 16 _BASE_APK = 'base.apk' |
| 16 _LIBCHROME_SO = 'libchrome.so' | 17 _LIBCHROME_SO = 'libchrome.so' |
| 17 | 18 |
| 19 _BUILD_FINGERPRINT_RE = re.compile('.*Build fingerprint: (.*)$') |
| 20 |
| 18 | 21 |
| 19 def GetTargetAndroidVersionNumber(lines): | 22 def GetTargetAndroidVersionNumber(lines): |
| 20 """Return the Android major version number from the build fingerprint. | 23 """Return the Android major version number from the build fingerprint. |
| 21 | 24 |
| 22 Args: | 25 Args: |
| 23 lines: Lines read from the tombstone file, before preprocessing. | 26 lines: Lines read from the tombstone file, before preprocessing. |
| 24 Returns: | 27 Returns: |
| 25 5, 6, etc, or None if not determinable (developer build?) | 28 5, 6, etc, or None if not determinable (developer build?) |
| 26 """ | 29 """ |
| 27 # For example, "Build fingerprint: 'Android/aosp_flo/flo:5.1.1/...'" is 5. | 30 # For example, "Build fingerprint: 'Android/aosp_flo/flo:5.1.1/...'" is 5. |
| 28 for line in lines: | 31 for line in lines: |
| 29 if line.startswith('Build fingerprint: '): | 32 m = _BUILD_FINGERPRINT_RE.match(line) |
| 30 fingerprint = line.split()[2] | 33 if not m: |
| 34 continue |
| 35 fingerprint = m.group(1) |
| 36 try: |
| 31 version = fingerprint.split('/')[2].split(':')[1].split('.')[0] | 37 version = fingerprint.split('/')[2].split(':')[1].split('.')[0] |
| 32 try: | 38 return int(version) |
| 33 return int(version) | 39 except Exception: |
| 34 except ValueError: | 40 pass |
| 35 return None | |
| 36 return None | 41 return None |
| 37 | 42 |
| 38 | 43 |
| 39 def _HasElfHeader(path): | 44 def _HasElfHeader(path): |
| 40 """Return True if the file at the given path has an ELF magic header. | 45 """Return True if the file at the given path has an ELF magic header. |
| 41 | 46 |
| 42 Minimal check only, for 'ELF' in bytes 1 to 3 of the file. Filters out | 47 Minimal check only, for 'ELF' in bytes 1 to 3 of the file. Filters out |
| 43 the zero-byte false-positives such as libchromeview.so returned by glob. | 48 the zero-byte false-positives such as libchromeview.so returned by glob. |
| 44 | 49 |
| 45 Args: | 50 Args: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 # would return 0x1d6000. Ignores all non-LOAD lines. | 88 # would return 0x1d6000. Ignores all non-LOAD lines. |
| 84 for line in _ReadElfProgramHeaders(lib): | 89 for line in _ReadElfProgramHeaders(lib): |
| 85 elements = line.split() | 90 elements = line.split() |
| 86 if elements and elements[0] == 'LOAD': | 91 if elements and elements[0] == 'LOAD': |
| 87 vaddrs.append(int(elements[2], 16)) | 92 vaddrs.append(int(elements[2], 16)) |
| 88 if vaddrs: | 93 if vaddrs: |
| 89 return min(vaddrs) | 94 return min(vaddrs) |
| 90 return 0 | 95 return 0 |
| 91 | 96 |
| 92 | 97 |
| 93 def GetLoadVaddrs(stripped_libs_dir): | 98 def GetLoadVaddrs(stripped_libs=None, stripped_libs_dir=None): |
| 94 """Return a dict of minimum VirtAddr for libraries in the given directory. | 99 """Return a dict of minimum VirtAddr for libraries in the given directory. |
| 95 | 100 |
| 96 The dictionary returned may be passed to stack_core.ConvertTrace(). In | 101 The dictionary returned may be passed to stack_core.ConvertTrace(). In |
| 97 pre-M Android releases the addresses printed by debuggerd into tombstones | 102 pre-M Android releases the addresses printed by debuggerd into tombstones |
| 98 do not take account of non-zero vaddrs. Here we collect this information, | 103 do not take account of non-zero vaddrs. Here we collect this information, |
| 99 so that we can use it later to correct such debuggerd tombstones. | 104 so that we can use it later to correct such debuggerd tombstones. |
| 100 | 105 |
| 101 Args: | 106 Args: |
| 102 stripped_libs_dir: Path to directory containing apk's stripped libraries. | 107 stripped_libs_dir: Path to directory containing apk's stripped libraries. |
| 103 Returns: | 108 Returns: |
| 104 {'libchrome.so': 12345, ...} | 109 {'libchrome.so': 12345, ...} |
| 105 """ | 110 """ |
| 106 libs = glob.glob(os.path.join(stripped_libs_dir, '*.so')) | 111 if not stripped_libs: |
| 107 libs = [l for l in libs if _HasElfHeader(l)] | 112 stripped_libs = [] |
| 113 if stripped_libs_dir: |
| 114 stripped_libs.extend(glob.glob(os.path.join(stripped_libs_dir, '*.so'))) |
| 115 libs = [l for l in stripped_libs if _HasElfHeader(l)] |
| 108 | 116 |
| 109 load_vaddrs = {} | 117 load_vaddrs = {} |
| 110 for lib in libs: | 118 for lib in libs: |
| 111 min_vaddr = _FindMinLoadVaddr(lib) | 119 min_vaddr = _FindMinLoadVaddr(lib) |
| 112 if min_vaddr: | 120 if min_vaddr: |
| 113 # Store with the library basename as the key. This is because once on | 121 # Store with the library basename as the key. This is because once on |
| 114 # the device its path may not fully match its place in the APK staging | 122 # the device its path may not fully match its place in the APK staging |
| 115 # directory | 123 # directory |
| 116 load_vaddrs[os.path.basename(lib)] = min_vaddr | 124 load_vaddrs[os.path.basename(lib)] = min_vaddr |
| 117 | 125 |
| 118 # Direct load from APK causes debuggerd to tag trace lines as if from the | 126 # Direct load from APK causes debuggerd to tag trace lines as if from the |
| 119 # file .../base.apk. So if we encounter a libchrome.so with packed | 127 # file .../base.apk. So if we encounter a libchrome.so with packed |
| 120 # relocations, replicate this as base.apk so that later adjustment code | 128 # relocations, replicate this as base.apk so that later adjustment code |
| 121 # finds the appropriate adjustment. | 129 # finds the appropriate adjustment. |
| 122 if _LIBCHROME_SO in load_vaddrs: | 130 if _LIBCHROME_SO in load_vaddrs: |
| 123 load_vaddrs[_BASE_APK] = load_vaddrs[_LIBCHROME_SO] | 131 load_vaddrs[_BASE_APK] = load_vaddrs[_LIBCHROME_SO] |
| 124 | 132 |
| 125 return load_vaddrs | 133 return load_vaddrs |
| OLD | NEW |