am 72bd0479: Merge "Make \'stack\' able to find toolchains regardless of lunch."

* commit '72bd04795b38b8dbbbf5d4b6e8c5cac2a4322702':
  Make 'stack' able to find toolchains regardless of lunch.
This commit is contained in:
Elliott Hughes
2014-08-29 22:38:47 +00:00
committed by Android Git Automerger
2 changed files with 57 additions and 37 deletions

View File

@@ -44,6 +44,7 @@ class TraceConverter:
value_lines = []
last_frame = -1
width = "{8}"
spacing = ""
def __init__(self):
self.UpdateAbiRegexes()
@@ -59,8 +60,10 @@ class TraceConverter:
def UpdateAbiRegexes(self):
if symbol.ARCH == "arm64" or symbol.ARCH == "mips64" or symbol.ARCH == "x86_64":
self.width = "{16}"
self.spacing = " "
else:
self.width = "{8}"
self.spacing = ""
self.register_line = re.compile("(([ ]*\\b(" + self.register_names[symbol.ARCH] + ")\\b +[0-9a-f]" + self.width + "){2,5})")
@@ -104,12 +107,9 @@ class TraceConverter:
def PrintTraceLines(self, trace_lines):
"""Print back trace."""
maxlen = max(map(lambda tl: len(tl[1]), trace_lines))
spacing = ""
if symbol.ARCH == "arm64" or symbol.ARCH == "mips64" or symbol.ARCH == "x86_64":
spacing = " "
print
print "Stack Trace:"
print " RELADDR " + spacing + "FUNCTION".ljust(maxlen) + " FILE:LINE"
print " RELADDR " + self.spacing + "FUNCTION".ljust(maxlen) + " FILE:LINE"
for tl in self.trace_lines:
(addr, symbol_with_offset, location) = tl
print " %8s %s %s" % (addr, symbol_with_offset.ljust(maxlen), location)
@@ -120,7 +120,7 @@ class TraceConverter:
maxlen = max(map(lambda tl: len(tl[2]), self.value_lines))
print
print "Stack Data:"
print " ADDR VALUE " + "FUNCTION".ljust(maxlen) + " FILE:LINE"
print " ADDR " + self.spacing + "VALUE " + "FUNCTION".ljust(maxlen) + " FILE:LINE"
for vl in self.value_lines:
(addr, value, symbol_with_offset, location) = vl
print " %8s %8s %s %s" % (addr, value, symbol_with_offset.ljust(maxlen), location)
@@ -256,12 +256,12 @@ class TraceConverter:
class RegisterPatternTests(unittest.TestCase):
def assert_register_matches(self, abi, example_crash, stupid_pattern):
tc = TraceConverter()
symbol.ARCH = abi
tc.UpdateAbiRegexes()
for line in example_crash.split('\n'):
tc.ProcessLine(line)
is_register = (re.search(stupid_pattern, line) is not None)
matched = (tc.register_line.search(line) is not None)
self.assertEquals(matched, is_register, line)
tc.PrintOutput(tc.trace_lines, tc.value_lines)
def test_arm_registers(self):
self.assert_register_matches("arm", example_crashes.arm, '\\b(r0|r4|r8|ip)\\b')

View File

@@ -23,6 +23,7 @@ import glob
import os
import re
import subprocess
import unittest
ANDROID_BUILD_TOP = os.environ["ANDROID_BUILD_TOP"]
if not ANDROID_BUILD_TOP:
@@ -44,7 +45,11 @@ SYMBOLS_DIR = FindSymbolsDir()
ARCH = "arm"
TOOLCHAIN = None
# These are private. Do not access them from other modules.
_CACHED_TOOLCHAIN = None
_CACHED_TOOLCHAIN_ARCH = None
def ToolPath(tool, toolchain=None):
"""Return a fully-qualified path to the specified tool"""
@@ -52,42 +57,38 @@ def ToolPath(tool, toolchain=None):
toolchain = FindToolchain()
return glob.glob(os.path.join(toolchain, "*-" + tool))[0]
def FindToolchain():
"""Returns the toolchain matching ARCH. Assumes that you're lunched
such that the necessary toolchain is either your primary or secondary.
TODO: we could make this 'just work' for most users by just globbing the
newest toolchains for every architecture out of prebuilts/, but other
parts of this tool assume you're lunched correctly anyway."""
global TOOLCHAIN
if TOOLCHAIN is not None:
return TOOLCHAIN
"""Returns the toolchain matching ARCH."""
global _CACHED_TOOLCHAIN, _CACHED_TOOLCHAIN_ARCH
if _CACHED_TOOLCHAIN is not None and _CACHED_TOOLCHAIN_ARCH == ARCH:
return _CACHED_TOOLCHAIN
# We use slightly different names from GCC, and there's only one toolchain
# for x86/x86_64.
gcc_arch = ARCH
if gcc_arch == "arm64":
gcc_arch = "aarch64"
elif gcc_arch == "mips":
gcc_arch = "mipsel"
elif gcc_arch == "x86":
gcc_arch = "x86_64"
# for x86/x86_64. Note that these are the names of the top-level directory
# rather than the _different_ names used lower down the directory hierarchy!
gcc_dir = ARCH
if gcc_dir == "arm64":
gcc_dir = "aarch64"
elif gcc_dir == "mips64":
gcc_dir = "mips"
elif gcc_dir == "x86_64":
gcc_dir = "x86"
tc1 = os.environ["ANDROID_TOOLCHAIN"]
tc2 = os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"]
available_toolchains = glob.glob("%s/prebuilts/gcc/linux-x86/%s/*-linux-*/bin/" % (ANDROID_BUILD_TOP, gcc_dir))
if len(available_toolchains) == 0:
raise Exception("Could not find tool chain for %s" % (ARCH))
if ("/" + gcc_arch + "-linux-") in tc1:
toolchain = tc1
elif ("/" + gcc_arch + "-linux-") in tc2:
toolchain = tc2
else:
raise Exception("Could not find tool chain for %s" % (gcc_arch))
toolchain = sorted(available_toolchains)[-1]
if not os.path.exists(ToolPath("addr2line", toolchain)):
raise Exception("No addr2line for %s" % (toolchain))
TOOLCHAIN = toolchain
print "Using toolchain from: %s" % TOOLCHAIN
return TOOLCHAIN
_CACHED_TOOLCHAIN = toolchain
_CACHED_TOOLCHAIN_ARCH = ARCH
print "Using %s toolchain from: %s" % (_CACHED_TOOLCHAIN_ARCH, _CACHED_TOOLCHAIN)
return _CACHED_TOOLCHAIN
def SymbolInformation(lib, addr):
"""Look up symbol information about an address.
@@ -179,7 +180,6 @@ def CallAddr2LineForSet(lib, unique_addrs):
if not lib:
return None
symbols = SYMBOLS_DIR + lib
if not os.path.exists(symbols):
return None
@@ -227,11 +227,11 @@ def StripPC(addr):
The stripped program counter address.
"""
global ARCH
if ARCH == "arm":
return addr & ~1
return addr
def CallObjdumpForSet(lib, unique_addrs):
"""Use objdump to find out the names of the containing functions.
@@ -326,7 +326,27 @@ def CallCppFilt(mangled_symbol):
process.stdout.close()
return demangled_symbol
def FormatSymbolWithOffset(symbol, offset):
if offset == 0:
return symbol
return "%s+%d" % (symbol, offset)
class FindToolchainTests(unittest.TestCase):
def assert_toolchain_found(self, abi):
global ARCH
ARCH = abi
FindToolchain() # Will throw on failure.
def test_toolchains_found(self):
self.assert_toolchain_found("arm")
self.assert_toolchain_found("arm64")
self.assert_toolchain_found("mips")
self.assert_toolchain_found("x86")
self.assert_toolchain_found("x86_64")
if __name__ == '__main__':
unittest.main()