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 = []
|
value_lines = []
|
||||||
last_frame = -1
|
last_frame = -1
|
||||||
width = "{8}"
|
width = "{8}"
|
||||||
|
spacing = ""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.UpdateAbiRegexes()
|
self.UpdateAbiRegexes()
|
||||||
@@ -59,8 +60,10 @@ class TraceConverter:
|
|||||||
def UpdateAbiRegexes(self):
|
def UpdateAbiRegexes(self):
|
||||||
if symbol.ARCH == "arm64" or symbol.ARCH == "mips64" or symbol.ARCH == "x86_64":
|
if symbol.ARCH == "arm64" or symbol.ARCH == "mips64" or symbol.ARCH == "x86_64":
|
||||||
self.width = "{16}"
|
self.width = "{16}"
|
||||||
|
self.spacing = " "
|
||||||
else:
|
else:
|
||||||
self.width = "{8}"
|
self.width = "{8}"
|
||||||
|
self.spacing = ""
|
||||||
|
|
||||||
self.register_line = re.compile("(([ ]*\\b(" + self.register_names[symbol.ARCH] + ")\\b +[0-9a-f]" + self.width + "){2,5})")
|
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):
|
def PrintTraceLines(self, trace_lines):
|
||||||
"""Print back trace."""
|
"""Print back trace."""
|
||||||
maxlen = max(map(lambda tl: len(tl[1]), trace_lines))
|
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
|
||||||
print "Stack Trace:"
|
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:
|
for tl in self.trace_lines:
|
||||||
(addr, symbol_with_offset, location) = tl
|
(addr, symbol_with_offset, location) = tl
|
||||||
print " %8s %s %s" % (addr, symbol_with_offset.ljust(maxlen), location)
|
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))
|
maxlen = max(map(lambda tl: len(tl[2]), self.value_lines))
|
||||||
print
|
print
|
||||||
print "Stack Data:"
|
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:
|
for vl in self.value_lines:
|
||||||
(addr, value, symbol_with_offset, location) = vl
|
(addr, value, symbol_with_offset, location) = vl
|
||||||
print " %8s %8s %s %s" % (addr, value, symbol_with_offset.ljust(maxlen), location)
|
print " %8s %8s %s %s" % (addr, value, symbol_with_offset.ljust(maxlen), location)
|
||||||
@@ -256,12 +256,12 @@ class TraceConverter:
|
|||||||
class RegisterPatternTests(unittest.TestCase):
|
class RegisterPatternTests(unittest.TestCase):
|
||||||
def assert_register_matches(self, abi, example_crash, stupid_pattern):
|
def assert_register_matches(self, abi, example_crash, stupid_pattern):
|
||||||
tc = TraceConverter()
|
tc = TraceConverter()
|
||||||
symbol.ARCH = abi
|
|
||||||
tc.UpdateAbiRegexes()
|
|
||||||
for line in example_crash.split('\n'):
|
for line in example_crash.split('\n'):
|
||||||
|
tc.ProcessLine(line)
|
||||||
is_register = (re.search(stupid_pattern, line) is not None)
|
is_register = (re.search(stupid_pattern, line) is not None)
|
||||||
matched = (tc.register_line.search(line) is not None)
|
matched = (tc.register_line.search(line) is not None)
|
||||||
self.assertEquals(matched, is_register, line)
|
self.assertEquals(matched, is_register, line)
|
||||||
|
tc.PrintOutput(tc.trace_lines, tc.value_lines)
|
||||||
|
|
||||||
def test_arm_registers(self):
|
def test_arm_registers(self):
|
||||||
self.assert_register_matches("arm", example_crashes.arm, '\\b(r0|r4|r8|ip)\\b')
|
self.assert_register_matches("arm", example_crashes.arm, '\\b(r0|r4|r8|ip)\\b')
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import glob
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import unittest
|
||||||
|
|
||||||
ANDROID_BUILD_TOP = os.environ["ANDROID_BUILD_TOP"]
|
ANDROID_BUILD_TOP = os.environ["ANDROID_BUILD_TOP"]
|
||||||
if not ANDROID_BUILD_TOP:
|
if not ANDROID_BUILD_TOP:
|
||||||
@@ -44,7 +45,11 @@ SYMBOLS_DIR = FindSymbolsDir()
|
|||||||
|
|
||||||
ARCH = "arm"
|
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):
|
def ToolPath(tool, toolchain=None):
|
||||||
"""Return a fully-qualified path to the specified tool"""
|
"""Return a fully-qualified path to the specified tool"""
|
||||||
@@ -52,42 +57,38 @@ def ToolPath(tool, toolchain=None):
|
|||||||
toolchain = FindToolchain()
|
toolchain = FindToolchain()
|
||||||
return glob.glob(os.path.join(toolchain, "*-" + tool))[0]
|
return glob.glob(os.path.join(toolchain, "*-" + tool))[0]
|
||||||
|
|
||||||
|
|
||||||
def FindToolchain():
|
def FindToolchain():
|
||||||
"""Returns the toolchain matching ARCH. Assumes that you're lunched
|
"""Returns the toolchain matching ARCH."""
|
||||||
such that the necessary toolchain is either your primary or secondary.
|
global _CACHED_TOOLCHAIN, _CACHED_TOOLCHAIN_ARCH
|
||||||
TODO: we could make this 'just work' for most users by just globbing the
|
if _CACHED_TOOLCHAIN is not None and _CACHED_TOOLCHAIN_ARCH == ARCH:
|
||||||
newest toolchains for every architecture out of prebuilts/, but other
|
return _CACHED_TOOLCHAIN
|
||||||
parts of this tool assume you're lunched correctly anyway."""
|
|
||||||
global TOOLCHAIN
|
|
||||||
if TOOLCHAIN is not None:
|
|
||||||
return TOOLCHAIN
|
|
||||||
|
|
||||||
# We use slightly different names from GCC, and there's only one toolchain
|
# We use slightly different names from GCC, and there's only one toolchain
|
||||||
# for x86/x86_64.
|
# for x86/x86_64. Note that these are the names of the top-level directory
|
||||||
gcc_arch = ARCH
|
# rather than the _different_ names used lower down the directory hierarchy!
|
||||||
if gcc_arch == "arm64":
|
gcc_dir = ARCH
|
||||||
gcc_arch = "aarch64"
|
if gcc_dir == "arm64":
|
||||||
elif gcc_arch == "mips":
|
gcc_dir = "aarch64"
|
||||||
gcc_arch = "mipsel"
|
elif gcc_dir == "mips64":
|
||||||
elif gcc_arch == "x86":
|
gcc_dir = "mips"
|
||||||
gcc_arch = "x86_64"
|
elif gcc_dir == "x86_64":
|
||||||
|
gcc_dir = "x86"
|
||||||
|
|
||||||
tc1 = os.environ["ANDROID_TOOLCHAIN"]
|
available_toolchains = glob.glob("%s/prebuilts/gcc/linux-x86/%s/*-linux-*/bin/" % (ANDROID_BUILD_TOP, gcc_dir))
|
||||||
tc2 = os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"]
|
if len(available_toolchains) == 0:
|
||||||
|
raise Exception("Could not find tool chain for %s" % (ARCH))
|
||||||
|
|
||||||
if ("/" + gcc_arch + "-linux-") in tc1:
|
toolchain = sorted(available_toolchains)[-1]
|
||||||
toolchain = tc1
|
|
||||||
elif ("/" + gcc_arch + "-linux-") in tc2:
|
|
||||||
toolchain = tc2
|
|
||||||
else:
|
|
||||||
raise Exception("Could not find tool chain for %s" % (gcc_arch))
|
|
||||||
|
|
||||||
if not os.path.exists(ToolPath("addr2line", toolchain)):
|
if not os.path.exists(ToolPath("addr2line", toolchain)):
|
||||||
raise Exception("No addr2line for %s" % (toolchain))
|
raise Exception("No addr2line for %s" % (toolchain))
|
||||||
|
|
||||||
TOOLCHAIN = toolchain
|
_CACHED_TOOLCHAIN = toolchain
|
||||||
print "Using toolchain from: %s" % TOOLCHAIN
|
_CACHED_TOOLCHAIN_ARCH = ARCH
|
||||||
return TOOLCHAIN
|
print "Using %s toolchain from: %s" % (_CACHED_TOOLCHAIN_ARCH, _CACHED_TOOLCHAIN)
|
||||||
|
return _CACHED_TOOLCHAIN
|
||||||
|
|
||||||
|
|
||||||
def SymbolInformation(lib, addr):
|
def SymbolInformation(lib, addr):
|
||||||
"""Look up symbol information about an address.
|
"""Look up symbol information about an address.
|
||||||
@@ -179,7 +180,6 @@ def CallAddr2LineForSet(lib, unique_addrs):
|
|||||||
if not lib:
|
if not lib:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
symbols = SYMBOLS_DIR + lib
|
symbols = SYMBOLS_DIR + lib
|
||||||
if not os.path.exists(symbols):
|
if not os.path.exists(symbols):
|
||||||
return None
|
return None
|
||||||
@@ -227,11 +227,11 @@ def StripPC(addr):
|
|||||||
The stripped program counter address.
|
The stripped program counter address.
|
||||||
"""
|
"""
|
||||||
global ARCH
|
global ARCH
|
||||||
|
|
||||||
if ARCH == "arm":
|
if ARCH == "arm":
|
||||||
return addr & ~1
|
return addr & ~1
|
||||||
return addr
|
return addr
|
||||||
|
|
||||||
|
|
||||||
def CallObjdumpForSet(lib, unique_addrs):
|
def CallObjdumpForSet(lib, unique_addrs):
|
||||||
"""Use objdump to find out the names of the containing functions.
|
"""Use objdump to find out the names of the containing functions.
|
||||||
|
|
||||||
@@ -326,7 +326,27 @@ def CallCppFilt(mangled_symbol):
|
|||||||
process.stdout.close()
|
process.stdout.close()
|
||||||
return demangled_symbol
|
return demangled_symbol
|
||||||
|
|
||||||
|
|
||||||
def FormatSymbolWithOffset(symbol, offset):
|
def FormatSymbolWithOffset(symbol, offset):
|
||||||
if offset == 0:
|
if offset == 0:
|
||||||
return symbol
|
return symbol
|
||||||
return "%s+%d" % (symbol, offset)
|
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