1ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng#!/usr/bin/env python 2ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 3ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# Copyright (C) 2009 The Android Open Source Project 4ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# 5ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# Licensed under the Apache License, Version 2.0 (the 'License'); 6ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# you may not use this file except in compliance with the License. 7ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# You may obtain a copy of the License at 8ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# 9ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# http://www.apache.org/licenses/LICENSE-2.0 10ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# 11ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# Unless required by applicable law or agreed to in writing, software 12ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# distributed under the License is distributed on an 'AS IS' BASIS, 13ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# See the License for the specific language governing permissions and 15ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# limitations under the License. 16ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 17ab007efd2fc18a92330ae0be88561b085167df01Ben Chengimport os 18ab007efd2fc18a92330ae0be88561b085167df01Ben Chengimport re 19ab007efd2fc18a92330ae0be88561b085167df01Ben Chengimport string 20ab007efd2fc18a92330ae0be88561b085167df01Ben Chengimport sys 21ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 22ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 23ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# match "#00 pc 0003f52e /system/lib/libdvm.so" for example 24ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 25ab007efd2fc18a92330ae0be88561b085167df01Ben Chengtrace_line = re.compile("(.*)(\#[0-9]+) (..) ([0-9a-f]{8}) ([^\r\n \t]*)") 26ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 27ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# returns a list containing the function name and the file/lineno 28ab007efd2fc18a92330ae0be88561b085167df01Ben Chengdef CallAddr2Line(lib, addr): 29ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global symbols_dir 30ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global addr2line_cmd 31ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global cppfilt_cmd 32ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 33ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if lib != "": 34ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng cmd = addr2line_cmd + \ 35ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng " -f -e " + symbols_dir + lib + " 0x" + addr 36ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream = os.popen(cmd) 37ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng lines = stream.readlines() 38ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng list = map(string.strip, lines) 39ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng else: 40ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng list = [] 41ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if list != []: 42ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # Name like "move_forward_type<JavaVMOption>" causes troubles 43ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng mangled_name = re.sub('<', '\<', list[0]); 44ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng mangled_name = re.sub('>', '\>', mangled_name); 45ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng cmd = cppfilt_cmd + " " + mangled_name 46ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream = os.popen(cmd) 47ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng list[0] = stream.readline() 48ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream.close() 49ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng list = map(string.strip, list) 50ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng else: 51ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng list = [ "(unknown)", "(unknown)" ] 52ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng return list 53ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 54ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 55ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 56ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# similar to CallAddr2Line, but using objdump to find out the name of the 57ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# containing function of the specified address 58ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 59ab007efd2fc18a92330ae0be88561b085167df01Ben Chengdef CallObjdump(lib, addr): 60ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global objdump_cmd 61ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global symbols_dir 62ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 63ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng unknown = "(unknown)" 64ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng uname = os.uname()[0] 65ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if uname == "Darwin": 66ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng proc = os.uname()[-1] 67ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if proc == "i386": 68ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng uname = "darwin-x86" 69ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng else: 70ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng uname = "darwin-ppc" 71ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng elif uname == "Linux": 72ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng uname = "linux-x86" 73ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if lib != "": 74ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng next_addr = string.atoi(addr, 16) + 1 75ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng cmd = objdump_cmd \ 76ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng + " -C -d --start-address=0x" + addr + " --stop-address=" \ 77ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng + str(next_addr) \ 78ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng + " " + symbols_dir + lib 79ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream = os.popen(cmd) 80ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng lines = stream.readlines() 81ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng map(string.strip, lines) 82ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream.close() 83ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng else: 84ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng return unknown 85ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 86ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # output looks like 87ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # 88ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # file format elf32-littlearm 89ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # 90ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # Disassembly of section .text: 91ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # 92ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # 0000833c <func+0x4>: 93ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # 833c: 701a strb r2, [r3, #0] 94ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # 95ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # we want to extract the "func" part 96ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng num_lines = len(lines) 97ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if num_lines < 2: 98ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng return unknown 99ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng func_name = lines[num_lines-2] 100ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng func_regexp = re.compile("(^.*\<)(.*)(\+.*\>:$)") 101ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng components = func_regexp.match(func_name) 102ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if components is None: 103ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng return unknown 104ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng return components.group(2) 105ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 106ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 107ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# determine the symbols directory in the local build 108ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 109ab007efd2fc18a92330ae0be88561b085167df01Ben Chengdef FindSymbolsDir(): 110ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global symbols_dir 111ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 112ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng try: 113ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng path = os.environ['ANDROID_PRODUCT_OUT'] + "/symbols" 114ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng except: 115ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng cmd = "CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core " \ 11677f31fe7280610cd47519616f061953215d28dbfYing Wang + "SRC_TARGET_DIR=build/target make -f build/core/config.mk " \ 117ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng + "dumpvar-abs-TARGET_OUT_UNSTRIPPED" 118ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream = os.popen(cmd) 119ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng str = stream.read() 120ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream.close() 121ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng path = str.strip() 122ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 123ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if (not os.path.exists(path)): 124ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng print path + " not found!" 125ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng sys.exit(1) 126ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 127ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng symbols_dir = path 128ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 129ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 130ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# determine the path of binutils 131ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 132ab007efd2fc18a92330ae0be88561b085167df01Ben Chengdef SetupToolsPath(): 133ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global addr2line_cmd 134ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global objdump_cmd 135ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global cppfilt_cmd 136ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng global symbols_dir 137ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 138ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng uname = os.uname()[0] 139ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if uname == "Darwin": 140aaf01f48ee2c84019edf8c76d0770a69994112b4Romain Guy uname = "darwin-x86" 141ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng elif uname == "Linux": 142ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng uname = "linux-x86" 1431526670628fc1a44cbe553253bdcd23f078c13beBen Cheng gcc_version = os.environ["TARGET_GCC_VERSION"] 1441526670628fc1a44cbe553253bdcd23f078c13beBen Cheng prefix = "./prebuilts/gcc/" + uname + "/arm/arm-linux-androideabi-" + \ 1451526670628fc1a44cbe553253bdcd23f078c13beBen Cheng gcc_version + "/bin/" 1469d396e37ac695916671614ab89797652ed02538cJing Yu addr2line_cmd = prefix + "arm-linux-androideabi-addr2line" 147ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 148ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if (not os.path.exists(addr2line_cmd)): 149ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng try: 150f5172c7564e0d84bf02b9add47809ce10a9cff4fJing Yu prefix = os.environ['ANDROID_BUILD_TOP'] + "/prebuilts/gcc/" + \ 1511526670628fc1a44cbe553253bdcd23f078c13beBen Cheng uname + "/arm/arm-linux-androideabi-" + gcc_version + "/bin/" 152ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng except: 153ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng prefix = ""; 154ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 1559d396e37ac695916671614ab89797652ed02538cJing Yu addr2line_cmd = prefix + "arm-linux-androideabi-addr2line" 156ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if (not os.path.exists(addr2line_cmd)): 157ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng print addr2line_cmd + " not found!" 158ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng sys.exit(1) 159ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 1609d396e37ac695916671614ab89797652ed02538cJing Yu objdump_cmd = prefix + "arm-linux-androideabi-objdump" 1619d396e37ac695916671614ab89797652ed02538cJing Yu cppfilt_cmd = prefix + "arm-linux-androideabi-c++filt" 162ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 163ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 164ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# look up the function and file/line number for a raw stack trace line 165ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# groups[0]: log tag 166ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# groups[1]: stack level 167ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# groups[2]: "pc" 168ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# groups[3]: code address 169ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng# groups[4]: library name 170ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 171ab007efd2fc18a92330ae0be88561b085167df01Ben Chengdef SymbolTranslation(groups): 172ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng lib_name = groups[4] 173ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng code_addr = groups[3] 174ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng caller = CallObjdump(lib_name, code_addr) 175ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng func_line_pair = CallAddr2Line(lib_name, code_addr) 176ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 177ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # If a callee is inlined to the caller, objdump will see the caller's 178ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # address but addr2line will report the callee's address. So the printed 179ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # format is desgined to be "caller<-callee file:line" 180ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if (func_line_pair[0] != caller): 181ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng print groups[0] + groups[1] + " " + caller + "<-" + \ 182ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng ' '.join(func_line_pair[:]) + " " 183ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng else: 184ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng print groups[0] + groups[1] + " " + ' '.join(func_line_pair[:]) + " " 185ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 186ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng############################################################################### 187ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 188ab007efd2fc18a92330ae0be88561b085167df01Ben Chengif __name__ == '__main__': 189ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # pass the options to adb 190ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng adb_cmd = "adb " + ' '.join(sys.argv[1:]) 191ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 192ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # setup addr2line_cmd and objdump_cmd 193ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng SetupToolsPath() 194ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 195ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # setup the symbols directory 196ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng FindSymbolsDir() 197ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 198ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # invoke the adb command and filter its output 199ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream = os.popen(adb_cmd) 200ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng while (True): 201ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng line = stream.readline() 202ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 203ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # EOF reached 204ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if (line == ''): 205ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng break 206ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 207ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # remove the trailing \n 208ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng line = line.strip() 209ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 210ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # see if this is a stack trace line 211ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng match = trace_line.match(line) 212ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng if (match): 213ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng groups = match.groups() 214ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # translate raw address into symbols 215ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng SymbolTranslation(groups) 216ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng else: 217ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng print line 2189611ceb4608f8b64313b1c74a7ec36b64ef2daefAndy McFadden sys.stdout.flush() 219ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng 220ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng # adb itself aborts 221ab007efd2fc18a92330ae0be88561b085167df01Ben Cheng stream.close() 222