Merge "ADBS now uses stack_core code to parse traces."
This commit is contained in:
commit
af95db033d
1 changed files with 8 additions and 184 deletions
192
tools/adbs
192
tools/adbs
|
@ -15,206 +15,30 @@
|
|||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
|
||||
###############################################################################
|
||||
# match "#00 pc 0003f52e /system/lib/libdvm.so" for example
|
||||
###############################################################################
|
||||
trace_line = re.compile("(.*)(\#[0-9]+) {1,2}(..) ([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/config.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":
|
||||
uname = "darwin-x86"
|
||||
elif uname == "Linux":
|
||||
uname = "linux-x86"
|
||||
gcc_version = os.environ["TARGET_GCC_VERSION"]
|
||||
prefix = "./prebuilts/gcc/" + uname + "/arm/arm-linux-androideabi-" + \
|
||||
gcc_version + "/bin/"
|
||||
addr2line_cmd = prefix + "arm-linux-androideabi-addr2line"
|
||||
|
||||
if (not os.path.exists(addr2line_cmd)):
|
||||
try:
|
||||
prefix = os.environ['ANDROID_BUILD_TOP'] + "/prebuilts/gcc/" + \
|
||||
uname + "/arm/arm-linux-androideabi-" + gcc_version + "/bin/"
|
||||
except:
|
||||
prefix = "";
|
||||
|
||||
addr2line_cmd = prefix + "arm-linux-androideabi-addr2line"
|
||||
if (not os.path.exists(addr2line_cmd)):
|
||||
print addr2line_cmd + " not found!"
|
||||
sys.exit(1)
|
||||
|
||||
objdump_cmd = prefix + "arm-linux-androideabi-objdump"
|
||||
cppfilt_cmd = prefix + "arm-linux-androideabi-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[:]) + " "
|
||||
|
||||
###############################################################################
|
||||
sys.path.insert(0, os.path.dirname(__file__) + "/../../development/scripts")
|
||||
import stack_core
|
||||
import symbol
|
||||
|
||||
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()
|
||||
# create tracer for line parsing
|
||||
tracer = stack_core.TraceConverter()
|
||||
|
||||
# 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
|
||||
if(tracer.ProcessLine(line) == False):
|
||||
print(line.strip())
|
||||
sys.stdout.flush()
|
||||
|
||||
# adb itself aborts
|
||||
|
|
Loading…
Reference in a new issue