Skip to content

Commit

Permalink
[Reland] Use llvm symbolizer for stack script.
Browse files Browse the repository at this point in the history
llvm symbolizer is a more efficient symbolizer than addr2line, objdump,
etc.

In this cl, I 1)created a wrapper instance to interact with
llvm symbolizer, 2)made the stack script to use llvm symbolizer instance,
and then 3)added llvm symbolizer into isolated inputs.

Bug: 774267
Change-Id: I43d305b4c0c94be614ee4cad35b40f04b3d3ae20
Reviewed-on: https://chromium-review.googlesource.com/810007
Reviewed-by: John Budorick <jbudorick@chromium.org>
Reviewed-by: agrieve <agrieve@chromium.org>
Reviewed-by: Dirk Pranke <dpranke@chromium.org>
Commit-Queue: Zhiling Huang <hzl@chromium.org>
Cr-Commit-Position: refs/heads/master@{#522520}
  • Loading branch information
Zhiling Huang authored and Commit Bot committed Dec 7, 2017
1 parent c98d97d commit b2754af
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 399 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,5 @@ group("stack_py") {
sources = _py_files
data = sources

data += [
"${android_tool_prefix}addr2line",
"${android_tool_prefix}objdump",
"${android_tool_prefix}c++filt",
]
data += [ "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer" ]
}
4 changes: 4 additions & 0 deletions third_party/android_platform/README.chromium
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ Added code to capture java stderr for better handling of native->java crashes.
Fixed invalid using decl in logging header debug.h
Only attempt to symbolize with ELF libraries.

Changed the stack script to use llvm symbolizer instead of addr2line,
objdump, etc, since llvm symbolizer is more efficient in finding
function names, line numbers etc.

Android relocation packing tool details:
Copy sources from AOSP bionic/tools/relocation_packer
Remove scripts that regenerate golden test data (not relevant here)
Expand Down
15 changes: 11 additions & 4 deletions third_party/android_platform/development/scripts/stack
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, os.pardir, os.pardir,
'build', 'android'))

from pylib import constants

sys.path.insert(0, os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, os.pardir, os.pardir,
'tools', 'python'))
import llvm_symbolizer

DEFAULT_SYMROOT='/tmp/symbols'
# From: https://source.android.com/source/build-numbers.html
Expand Down Expand Up @@ -225,10 +230,12 @@ def main(argv):
print ("Reading Android symbols from: "
+ os.path.normpath(symbol.SYMBOLS_DIR))
chrome_search_path = symbol.GetLibrarySearchPaths()
print ("Searching for Chrome symbols from within: "
+ ':'.join((os.path.normpath(d) for d in chrome_search_path)))
stack_core.ConvertTrace(lines, load_vaddrs, more_info, fallback_monochrome,
arch_defined)

with llvm_symbolizer.LLVMSymbolizer() as symbolizer:
print ("Searching for Chrome symbols from within: "
+ ':'.join((os.path.normpath(d) for d in chrome_search_path)))
stack_core.ConvertTrace(lines, load_vaddrs, more_info, fallback_monochrome,
arch_defined, symbolizer)

if rootdir:
# be a good citizen and clean up...os.rmdir and os.removedirs() don't work
Expand Down
66 changes: 15 additions & 51 deletions third_party/android_platform/development/scripts/stack_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def PrintDivider():
print
print '-----------------------------------------------------\n'

def ConvertTrace(lines, load_vaddrs, more_info, fallback_monochrome, arch_defined):
def ConvertTrace(lines, load_vaddrs, more_info, fallback_monochrome, arch_defined, llvm_symbolizer):
"""Convert strings containing native crash to a stack."""
InitWidthRelatedLineMatchers()

Expand Down Expand Up @@ -189,7 +189,7 @@ def ConvertTrace(lines, load_vaddrs, more_info, fallback_monochrome, arch_define
print ('Find ABI:' + arch)
symbol.ARCH = arch

ResolveCrashSymbol(list(useful_log), more_info)
ResolveCrashSymbol(list(useful_log), more_info, llvm_symbolizer)
end = time.time()
logging.debug('Finished resolving symbols. Elapsed time: %.4fs',
(end - start))
Expand Down Expand Up @@ -304,7 +304,7 @@ def __call__(self, lines):
useful_log.append(line)
return useful_log, self._so_dirs

def ResolveCrashSymbol(lines, more_info):
def ResolveCrashSymbol(lines, more_info, llvm_symbolizer):
"""Convert unicode strings which contains native crash to a stack
"""

Expand All @@ -313,39 +313,15 @@ def ResolveCrashSymbol(lines, more_info):
last_frame = -1
pid = -1

# It is faster to get symbol information with a single call rather than with
# separate calls for each line. Since symbol.SymbolInformation caches results,
# we can extract all the addresses that we will want symbol information for
# from the log and call symbol.SymbolInformation so that the results are
# cached in the following lookups.
code_addresses = {}

# Collects all java exception lines, keyed by pid for later output during
# native crash handling.
java_stderr_by_pid = {}
for line in lines:
lib, address = None, None

match = _TRACE_LINE.match(line) or _DEBUG_TRACE_LINE.match(line)
if match:
address, lib = match.group('address', 'lib')

match = _VALUE_LINE.match(line)
if match and not _CODE_LINE.match(line):
(_0, _1, address, lib, _2, _3) = match.groups()

if lib:
code_addresses.setdefault(lib, set()).add(address)

java_stderr_match = _JAVA_STDERR_LINE.search(line)
if java_stderr_match:
pid, msg = java_stderr_match.groups()
java_stderr_by_pid.setdefault(pid, []).append(msg)

for lib in code_addresses:
symbol.SymbolInformationForSet(
symbol.TranslateLibPath(lib), code_addresses[lib], more_info)

for line in lines:
# AndroidFeedback adds zero width spaces into its crash reports. These
# should be removed or the regular expresssions will fail to match.
Expand Down Expand Up @@ -410,46 +386,34 @@ def ResolveCrashSymbol(lines, more_info):
logging.debug('Identified lib: %s' % area)
# If a calls b which further calls c and c is inlined to b, we want to
# display "a -> b -> c" in the stack trace instead of just "a -> c"
info = symbol.SymbolInformation(area, code_addr, more_info)
# To use llvm symbolizer, the hexadecimal address has to start with 0x.
info = llvm_symbolizer.GetSymbolInformation(
os.path.join(symbol.SYMBOLS_DIR, symbol.TranslateLibPath(area)),
'0x' + code_addr)
logging.debug('symbol information: %s' % info)
nest_count = len(info) - 1
for (source_symbol, source_location, object_symbol_with_offset) in info:
if not source_symbol:
if symbol_present:
source_symbol = symbol.CallCppFilt(symbol_name)
else:
source_symbol = UNKNOWN
if not source_location:
source_location = area
for source_symbol, source_location in info:
if nest_count > 0:
nest_count = nest_count - 1
trace_lines.append(('v------>', source_symbol, source_location))
else:
if not object_symbol_with_offset:
object_symbol_with_offset = source_symbol
trace_lines.append((code_addr,
object_symbol_with_offset,
source_symbol,
source_location))
match = _VALUE_LINE.match(line)
if match:
(unused_, addr, value, area, symbol_present, symbol_name) = match.groups()
if area == UNKNOWN or area == HEAP or area == STACK or not area:
value_lines.append((addr, value, '', area))
else:
info = symbol.SymbolInformation(area, value, more_info)
(source_symbol, source_location, object_symbol_with_offset) = info.pop()
if not source_symbol:
if symbol_present:
source_symbol = symbol.CallCppFilt(symbol_name)
else:
source_symbol = UNKNOWN
if not source_location:
source_location = area
if not object_symbol_with_offset:
object_symbol_with_offset = source_symbol
info = llvm_symbolizer.GetSymbolInformation(
os.path.join(symbol.SYMBOLS_DIR, symbol.TranslateLibPath(area)),
'0x' + code_addr)
source_symbol, source_location = info.pop()

value_lines.append((addr,
value,
object_symbol_with_offset,
source_symbol,
source_location))

java_lines = []
Expand Down
Loading

0 comments on commit b2754af

Please sign in to comment.