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:
@@ -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')
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user