summaryrefslogtreecommitdiffstats
path: root/tools/adbs
diff options
context:
space:
mode:
authorBen Cheng <bccheng@android.com>2009-08-11 11:15:26 -0700
committerBen Cheng <bccheng@android.com>2009-08-11 11:17:52 -0700
commitab007efd2fc18a92330ae0be88561b085167df01 (patch)
treee958f440e0c9ee45c69219fa7a2a0b7d8c534c85 /tools/adbs
parent8510a1e0d7d45179e5fa19bebf26d022ec4c4e91 (diff)
downloadbuild-ab007efd2fc18a92330ae0be88561b085167df01.zip
build-ab007efd2fc18a92330ae0be88561b085167df01.tar.gz
build-ab007efd2fc18a92330ae0be88561b085167df01.tar.bz2
Install the generic version of adbs to build/tools.
Diffstat (limited to 'tools/adbs')
-rwxr-xr-xtools/adbs222
1 files changed, 222 insertions, 0 deletions
diff --git a/tools/adbs b/tools/adbs
new file mode 100755
index 0000000..8b1fac6
--- /dev/null
+++ b/tools/adbs
@@ -0,0 +1,222 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the 'License');
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an 'AS IS' BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import re
+import string
+import sys
+
+###############################################################################
+# match "#00 pc 0003f52e /system/lib/libdvm.so" for example
+###############################################################################
+trace_line = re.compile("(.*)(\#[0-9]+) (..) ([0-9a-f]{8}) ([^\r\n \t]*)")
+
+# returns a list containing the function name and the file/lineno
+def CallAddr2Line(lib, addr):
+ global symbols_dir
+ global addr2line_cmd
+ global cppfilt_cmd
+
+ if lib != "":
+ cmd = addr2line_cmd + \
+ " -f -e " + symbols_dir + lib + " 0x" + addr
+ stream = os.popen(cmd)
+ lines = stream.readlines()
+ list = map(string.strip, lines)
+ else:
+ list = []
+ if list != []:
+ # Name like "move_forward_type<JavaVMOption>" causes troubles
+ mangled_name = re.sub('<', '\<', list[0]);
+ mangled_name = re.sub('>', '\>', mangled_name);
+ cmd = cppfilt_cmd + " " + mangled_name
+ stream = os.popen(cmd)
+ list[0] = stream.readline()
+ stream.close()
+ list = map(string.strip, list)
+ else:
+ list = [ "(unknown)", "(unknown)" ]
+ return list
+
+
+###############################################################################
+# similar to CallAddr2Line, but using objdump to find out the name of the
+# containing function of the specified address
+###############################################################################
+def CallObjdump(lib, addr):
+ global objdump_cmd
+ global symbols_dir
+
+ unknown = "(unknown)"
+ uname = os.uname()[0]
+ if uname == "Darwin":
+ proc = os.uname()[-1]
+ if proc == "i386":
+ uname = "darwin-x86"
+ else:
+ uname = "darwin-ppc"
+ elif uname == "Linux":
+ uname = "linux-x86"
+ if lib != "":
+ next_addr = string.atoi(addr, 16) + 1
+ cmd = objdump_cmd \
+ + " -C -d --start-address=0x" + addr + " --stop-address=" \
+ + str(next_addr) \
+ + " " + symbols_dir + lib
+ stream = os.popen(cmd)
+ lines = stream.readlines()
+ map(string.strip, lines)
+ stream.close()
+ else:
+ return unknown
+
+ # output looks like
+ #
+ # file format elf32-littlearm
+ #
+ # Disassembly of section .text:
+ #
+ # 0000833c <func+0x4>:
+ # 833c: 701a strb r2, [r3, #0]
+ #
+ # we want to extract the "func" part
+ num_lines = len(lines)
+ if num_lines < 2:
+ return unknown
+ func_name = lines[num_lines-2]
+ func_regexp = re.compile("(^.*\<)(.*)(\+.*\>:$)")
+ components = func_regexp.match(func_name)
+ if components is None:
+ return unknown
+ return components.group(2)
+
+###############################################################################
+# determine the symbols directory in the local build
+###############################################################################
+def FindSymbolsDir():
+ global symbols_dir
+
+ try:
+ path = os.environ['ANDROID_PRODUCT_OUT'] + "/symbols"
+ except:
+ cmd = "CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core " \
+ + "SRC_TARGET_DIR=build/target make -f build/core/envsetup.mk " \
+ + "dumpvar-abs-TARGET_OUT_UNSTRIPPED"
+ stream = os.popen(cmd)
+ str = stream.read()
+ stream.close()
+ path = str.strip()
+
+ if (not os.path.exists(path)):
+ print path + " not found!"
+ sys.exit(1)
+
+ symbols_dir = path
+
+###############################################################################
+# determine the path of binutils
+###############################################################################
+def SetupToolsPath():
+ global addr2line_cmd
+ global objdump_cmd
+ global cppfilt_cmd
+ global symbols_dir
+
+ uname = os.uname()[0]
+ if uname == "Darwin":
+ proc = os.uname()[-1]
+ if proc == "i386":
+ uname = "darwin-x86"
+ else:
+ uname = "darwin-ppc"
+ elif uname == "Linux":
+ uname = "linux-x86"
+ prefix = "./prebuilt/" + uname + "/toolchain/arm-eabi-4.4.0/bin/"
+ addr2line_cmd = prefix + "arm-eabi-addr2line"
+
+ if (not os.path.exists(addr2line_cmd)):
+ try:
+ prefix = os.environ['ANDROID_BUILD_TOP'] + "/prebuilt/" + uname + \
+ "/toolchain/arm-eabi-4.4.0/bin/"
+ except:
+ prefix = "";
+
+ addr2line_cmd = prefix + "arm-eabi-addr2line"
+ if (not os.path.exists(addr2line_cmd)):
+ print addr2line_cmd + " not found!"
+ sys.exit(1)
+
+ objdump_cmd = prefix + "arm-eabi-objdump"
+ cppfilt_cmd = prefix + "arm-eabi-c++filt"
+
+###############################################################################
+# look up the function and file/line number for a raw stack trace line
+# groups[0]: log tag
+# groups[1]: stack level
+# groups[2]: "pc"
+# groups[3]: code address
+# groups[4]: library name
+###############################################################################
+def SymbolTranslation(groups):
+ lib_name = groups[4]
+ code_addr = groups[3]
+ caller = CallObjdump(lib_name, code_addr)
+ func_line_pair = CallAddr2Line(lib_name, code_addr)
+
+ # If a callee is inlined to the caller, objdump will see the caller's
+ # address but addr2line will report the callee's address. So the printed
+ # format is desgined to be "caller<-callee file:line"
+ if (func_line_pair[0] != caller):
+ print groups[0] + groups[1] + " " + caller + "<-" + \
+ ' '.join(func_line_pair[:]) + " "
+ else:
+ print groups[0] + groups[1] + " " + ' '.join(func_line_pair[:]) + " "
+
+###############################################################################
+
+if __name__ == '__main__':
+ # pass the options to adb
+ adb_cmd = "adb " + ' '.join(sys.argv[1:])
+
+ # setup addr2line_cmd and objdump_cmd
+ SetupToolsPath()
+
+ # setup the symbols directory
+ FindSymbolsDir()
+
+ # invoke the adb command and filter its output
+ stream = os.popen(adb_cmd)
+ while (True):
+ line = stream.readline()
+
+ # EOF reached
+ if (line == ''):
+ break
+
+ # remove the trailing \n
+ line = line.strip()
+
+ # see if this is a stack trace line
+ match = trace_line.match(line)
+ if (match):
+ groups = match.groups()
+ # translate raw address into symbols
+ SymbolTranslation(groups)
+ else:
+ print line
+
+ # adb itself aborts
+ stream.close()