summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/stack_core.py56
-rwxr-xr-xscripts/symbol.py87
2 files changed, 79 insertions, 64 deletions
diff --git a/scripts/stack_core.py b/scripts/stack_core.py
index 42285d462..31b68be18 100755
--- a/scripts/stack_core.py
+++ b/scripts/stack_core.py
@@ -23,9 +23,12 @@ import symbol
def PrintTraceLines(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 " + "FUNCTION".ljust(maxlen) + " FILE:LINE"
+ print " RELADDR " + spacing + "FUNCTION".ljust(maxlen) + " FILE:LINE"
for tl in trace_lines:
(addr, symbol_with_offset, location) = tl
print " %8s %s %s" % (addr, symbol_with_offset.ljust(maxlen), location)
@@ -58,14 +61,35 @@ def PrintDivider():
print
print "-----------------------------------------------------\n"
+def CleanLine(ln):
+ # AndroidFeedback adds zero width spaces into its crash reports. These
+ # should be removed or the regular expresssions will fail to match.
+ return unicode(ln, errors='ignore')
+
def ConvertTrace(lines):
"""Convert strings containing native crash to a stack."""
+ lines = map(CleanLine, lines)
+
process_info_line = re.compile("(pid: [0-9]+, tid: [0-9]+.*)")
+ abi_line = re.compile("(ABI: \'(.*)\')")
signal_line = re.compile("(signal [0-9]+ \(.*\).*)")
- register_line = re.compile("(([ ]*[0-9a-z]{2} [0-9a-f]{8}){4})")
+ abort_message_line = re.compile("(Abort message: '.*')")
thread_line = re.compile("(.*)(\-\-\- ){15}\-\-\-")
dalvik_jni_thread_line = re.compile("(\".*\" prio=[0-9]+ tid=[0-9]+ NATIVE.*)")
dalvik_native_thread_line = re.compile("(\".*\" sysTid=[0-9]+ nice=[0-9]+.*)")
+
+ for line in lines:
+ abi_header = abi_line.search(line)
+ if abi_header:
+ symbol.ARCH = abi_header.group(2)
+ break
+
+ width = "{8}"
+ if symbol.ARCH == "arm64" or symbol.ARCH == "mips64" or symbol.ARCH == "x86_64":
+ width = "{16}"
+
+ register_line = re.compile("(([ ]*[0-9a-z]{2} +[0-9a-f]" + width + "){4})")
+
# Note that both trace and value line matching allow for variable amounts of
# whitespace (e.g. \t). This is because the we want to allow for the stack
# tool to operate on AndroidFeedback provided system logs. AndroidFeedback
@@ -77,13 +101,13 @@ def ConvertTrace(lines):
# Or lines from AndroidFeedback crash report system logs like:
# 03-25 00:51:05.520 I/DEBUG ( 65): #00 pc 001cf42e /data/data/com.my.project/lib/libmyproject.so
# Please note the spacing differences.
- trace_line = re.compile("(.*)\#([0-9]+)[ \t]+(..)[ \t]+([0-9a-f]{8})[ \t]+([^\r\n \t]*)( \((.*)\))?") # pylint: disable-msg=C6310
+ trace_line = re.compile("(.*)\#([0-9]+)[ \t]+(..)[ \t]+([0-9a-f]" + width + ")[ \t]+([^\r\n \t]*)( \((.*)\))?") # pylint: disable-msg=C6310
# Examples of matched value lines include:
# bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so
# bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so (symbol)
# 03-25 00:51:05.530 I/DEBUG ( 65): bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so
# Again, note the spacing differences.
- value_line = re.compile("(.*)([0-9a-f]{8})[ \t]+([0-9a-f]{8})[ \t]+([^\r\n \t]*)( \((.*)\))?")
+ value_line = re.compile("(.*)([0-9a-f]" + width + ")[ \t]+([0-9a-f]" + width + ")[ \t]+([^\r\n \t]*)( \((.*)\))?")
# Lines from 'code around' sections of the output will be matched before
# value lines because otheriwse the 'code around' sections will be confused as
# value lines.
@@ -91,24 +115,28 @@ def ConvertTrace(lines):
# Examples include:
# 801cf40c ffffc4cc 00b2f2c5 00b2f1c7 00c1e1a8
# 03-25 00:51:05.530 I/DEBUG ( 65): 801cf40c ffffc4cc 00b2f2c5 00b2f1c7 00c1e1a8
- code_line = re.compile("(.*)[ \t]*[a-f0-9]{8}[ \t]*[a-f0-9]{8}[ \t]*[a-f0-9]{8}[ \t]*[a-f0-9]{8}[ \t]*[a-f0-9]{8}[ \t]*[ \r\n]") # pylint: disable-msg=C6310
+ code_line = re.compile("(.*)[ \t]*[a-f0-9]" + width +
+ "[ \t]*[a-f0-9]" + width +
+ "[ \t]*[a-f0-9]" + width +
+ "[ \t]*[a-f0-9]" + width +
+ "[ \t]*[a-f0-9]" + width +
+ "[ \t]*[ \r\n]") # pylint: disable-msg=C6310
trace_lines = []
value_lines = []
last_frame = -1
- for ln in lines:
- # AndroidFeedback adds zero width spaces into its crash reports. These
- # should be removed or the regular expresssions will fail to match.
- line = unicode(ln, errors='ignore')
+ for line in lines:
process_header = process_info_line.search(line)
signal_header = signal_line.search(line)
- register_header = register_line.search(line)
+ abort_message_header = abort_message_line.search(line)
thread_header = thread_line.search(line)
+ register_header = register_line.search(line)
+ abi_header = abi_line.search(line)
dalvik_jni_thread_header = dalvik_jni_thread_line.search(line)
dalvik_native_thread_header = dalvik_native_thread_line.search(line)
- if process_header or signal_header or register_header or thread_header \
- or dalvik_jni_thread_header or dalvik_native_thread_header:
+ if process_header or signal_header or abort_message_header or thread_header or abi_header or \
+ register_header or dalvik_jni_thread_header or dalvik_native_thread_header:
if trace_lines or value_lines:
PrintOutput(trace_lines, value_lines)
PrintDivider()
@@ -119,6 +147,8 @@ def ConvertTrace(lines):
print process_header.group(1)
if signal_header:
print signal_header.group(1)
+ if abort_message_header:
+ print abort_message_header.group(1)
if register_header:
print register_header.group(1)
if thread_header:
@@ -127,6 +157,8 @@ def ConvertTrace(lines):
print dalvik_jni_thread_header.group(1)
if dalvik_native_thread_header:
print dalvik_native_thread_header.group(1)
+ if abi_header:
+ print abi_header.group(1)
continue
if trace_line.match(line):
match = trace_line.match(line)
diff --git a/scripts/symbol.py b/scripts/symbol.py
index 0f58df64c..a10621a98 100755
--- a/scripts/symbol.py
+++ b/scripts/symbol.py
@@ -19,6 +19,7 @@
The information can include symbol names, offsets, and source locations.
"""
+import glob
import os
import re
import subprocess
@@ -43,62 +44,45 @@ SYMBOLS_DIR = FindSymbolsDir()
ARCH = "arm"
-TOOLCHAIN_INFO = None
-
-def Uname():
- """'uname' for constructing prebuilt/<...> and out/host/<...> paths."""
- uname = os.uname()[0]
- if uname == "Darwin":
- proc = os.uname()[-1]
- if proc == "i386" or proc == "x86_64":
- return "darwin-x86"
- return "darwin-ppc"
- if uname == "Linux":
- return "linux-x86"
- return uname
-
-def ToolPath(tool, toolchain_info=None):
- """Return a full qualified path to the specified tool"""
- if not toolchain_info:
- toolchain_info = FindToolchain()
- (label, platform, target) = toolchain_info
- return os.path.join(ANDROID_BUILD_TOP, "prebuilts/gcc", Uname(), platform, label, "bin",
- target + "-" + tool)
+TOOLCHAIN = None
-def FindToolchain():
- """Look for the latest available toolchain
-
- Args:
- None
-
- Returns:
- A pair of strings containing toolchain label and target prefix.
- """
- global TOOLCHAIN_INFO
- if TOOLCHAIN_INFO is not None:
- return TOOLCHAIN_INFO
+def ToolPath(tool, toolchain=None):
+ """Return a fully-qualified path to the specified tool"""
+ if not toolchain:
+ toolchain = FindToolchain()
+ return glob.glob(os.path.join(toolchain, "*-" + tool))[0]
- ## Known toolchains, newer ones in the front.
- if ARCH == "arm":
- gcc_version = os.environ["TARGET_GCC_VERSION"]
- known_toolchains = [
- ("arm-linux-androideabi-" + gcc_version, "arm", "arm-linux-androideabi"),
- ]
- elif ARCH =="x86":
- known_toolchains = [
- ("i686-android-linux-4.4.3", "x86", "i686-android-linux")
- ]
+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
+
+ # We say "arm64", GCC says "aarch64".
+ gcc_arch = ARCH
+ if gcc_arch == "arm64":
+ gcc_arch = "aarch64"
+
+ tc1 = os.environ["ANDROID_TOOLCHAIN"]
+ tc2 = os.environ["ANDROID_TOOLCHAIN_2ND_ARCH"]
+
+ if (gcc_arch + "/" + gcc_arch + "-") in tc1:
+ toolchain = tc1
+ elif (gcc_arch + "/" + gcc_arch + "-") in tc2:
+ toolchain = tc2
else:
- known_toolchains = []
+ raise Exception("Could not find tool chain for %s" % (gcc_arch))
- # Look for addr2line to check for valid toolchain path.
- for (label, platform, target) in known_toolchains:
- toolchain_info = (label, platform, target);
- if os.path.exists(ToolPath("addr2line", toolchain_info)):
- TOOLCHAIN_INFO = toolchain_info
- return toolchain_info
+ if not os.path.exists(ToolPath("addr2line", toolchain)):
+ raise Exception("No addr2line for %s" % (toolchain))
- raise Exception("Could not find tool chain")
+ TOOLCHAIN = toolchain
+ print "Using toolchain from: %s" % TOOLCHAIN
+ return TOOLCHAIN
def SymbolInformation(lib, addr):
"""Look up symbol information about an address.
@@ -195,7 +179,6 @@ def CallAddr2LineForSet(lib, unique_addrs):
if not os.path.exists(symbols):
return None
- (label, platform, target) = FindToolchain()
cmd = [ToolPath("addr2line"), "--functions", "--inlines",
"--demangle", "--exe=" + symbols]
child = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)