From ab007efd2fc18a92330ae0be88561b085167df01 Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Tue, 11 Aug 2009 11:15:26 -0700 Subject: [PATCH] Install the generic version of adbs to build/tools. --- tools/adbs | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100755 tools/adbs diff --git a/tools/adbs b/tools/adbs new file mode 100755 index 000000000..8b1fac60f --- /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" 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 : + # 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() -- 2.11.0