266 lines
9.8 KiB
Python
266 lines
9.8 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
|
# Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without modification,
|
|
# are permitted provided that the following conditions are met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
# conditions and the following disclaimer.
|
|
#
|
|
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
# of conditions and the following disclaimer in the documentation and/or other materials
|
|
# provided with the distribution.
|
|
#
|
|
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
|
# to endorse or promote products derived from this software without specific prior written
|
|
# permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
import sys
|
|
import os
|
|
import argparse
|
|
import io
|
|
import commands
|
|
|
|
def find_string(excinfo_file, string):
|
|
res = ''
|
|
with open(excinfo_file, 'r+') as f:
|
|
for lines in f:
|
|
if string in lines:
|
|
res = lines
|
|
break
|
|
return res
|
|
|
|
def is_kernel_exc(excinfo_file):
|
|
res = find_string(excinfo_file, 'excFrom: kernel')
|
|
print(res)
|
|
return res != ''
|
|
|
|
def is_user_exc(excinfo_file):
|
|
res = find_string(excinfo_file, 'excFrom: User')
|
|
print(res)
|
|
return res != ''
|
|
|
|
def parse_string_line(excinfo_file, string):
|
|
line = find_string(excinfo_file, string)
|
|
if line == '':
|
|
print("%s is not in %s\n" %(string, excinfo_file))
|
|
return ''
|
|
line = line.replace('\n', '')
|
|
strlist = line.split(' ')
|
|
return strlist
|
|
|
|
def parse_kernel_pc_klr(excinfo_file, ohos_image_file, string, addr2line_cmd, objdump_cmd):
|
|
#parse pc
|
|
with open(excinfo_file, 'r+') as f:
|
|
start = 0
|
|
for lines in f.readlines():
|
|
if 'excFrom: kernel' in lines:
|
|
if start == 1:
|
|
break
|
|
start = 1
|
|
if start and string in lines:
|
|
lines = lines[lines.find(string):]
|
|
strlist = lines.split()
|
|
cmd = "%s%s | grep %s: -B 10 -A 5 -w" % (objdump_cmd, ohos_image_file, strlist[2][2:])
|
|
ret = commands.getoutput(cmd)
|
|
print(ret)
|
|
cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2])
|
|
ret = commands.getoutput(cmd)
|
|
ret = ret.split('\n')
|
|
print("<%s>%s<%s>\n") % (string, ret[0], strlist[2])
|
|
return 0
|
|
return -1
|
|
|
|
def parse_kernel_lr(excinfo_file, ohos_image_file, addr2line_cmd):
|
|
with open(excinfo_file, 'r+') as f:
|
|
start = 0
|
|
index = 1
|
|
for lines in f.readlines():
|
|
if 'excFrom: kernel' in lines:
|
|
if start == 1:
|
|
break
|
|
start = 1
|
|
if start and 'lr =' in lines:
|
|
lines = lines[lines.find('lr ='):]
|
|
strlist = lines.split()
|
|
cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2])
|
|
ret = commands.getoutput(cmd)
|
|
ret = ret.split('\n')
|
|
print("<%.2d>%s<%s>" % (index, ret[0], strlist[2]))
|
|
index = index + 1
|
|
|
|
def parse_kernel_exc(excinfo_file, ohos_image_file, addr2line_cmd, objdump_cmd):
|
|
#parse pc, klr
|
|
ret1 = parse_kernel_pc_klr(excinfo_file, ohos_image_file, 'pc', addr2line_cmd, objdump_cmd)
|
|
ret2 = parse_kernel_pc_klr(excinfo_file, ohos_image_file, 'klr', addr2line_cmd, objdump_cmd)
|
|
#parse lr
|
|
parse_kernel_lr(excinfo_file, ohos_image_file, addr2line_cmd)
|
|
return ret1 and ret2
|
|
|
|
def parse_user_pc_ulr(excinfo_file, rootfs_dir, string, addr2line_cmd, objdump_cmd):
|
|
#parse pc
|
|
with open(excinfo_file, 'r+') as f:
|
|
start = 0
|
|
for lines in f.readlines():
|
|
if 'excFrom: User' in lines:
|
|
if start == 1:
|
|
break
|
|
start = 1
|
|
if start and string in lines:
|
|
lines = lines[lines.find(string):]
|
|
strlist = lines.split()
|
|
if len(strlist) < 7:
|
|
print('%s is error'%string)
|
|
return 0
|
|
cmd = "%s%s%s | grep %s: -B 10 -A 5 -w" % (objdump_cmd, rootfs_dir, strlist[4], strlist[6][2:])
|
|
ret = commands.getoutput(cmd)
|
|
print(ret)
|
|
cmd = "%s%s%s %s" % (addr2line_cmd, rootfs_dir, strlist[4], strlist[6])
|
|
ret = commands.getoutput(cmd)
|
|
ret = ret.split('\n')
|
|
print("<%s>%s<%s><%s>\n" % (string, ret[0], strlist[6], strlist[4]))
|
|
return 0
|
|
return -1
|
|
|
|
def parse_user_lr(excinfo_file, rootfs_dir, addr2line_cmd):
|
|
with open(excinfo_file, 'r+') as f:
|
|
start = 0
|
|
index = 1
|
|
for lines in f.readlines():
|
|
if 'excFrom: User' in lines:
|
|
if start == 1:
|
|
break
|
|
start = 1
|
|
if start and 'lr =' in lines:
|
|
lines = lines[lines.find('lr ='):]
|
|
strlist = lines.split()
|
|
if len(strlist) < 11:
|
|
print('%s is error' % strlist)
|
|
return
|
|
cmd = "%s%s%s %s" % (addr2line_cmd, rootfs_dir, strlist[8], strlist[10])
|
|
res = commands.getoutput(cmd)
|
|
res = res.split('\n')
|
|
print("<%.2d>%s<%s><%s>" % (index, res[0], strlist[10], strlist[8]))
|
|
index = index + 1
|
|
|
|
def parse_user_exc(excinfo_file, rootfs_dir, addr2line_cmd, objdump_cmd):
|
|
#parse pc ulr
|
|
ret1 = parse_user_pc_ulr(excinfo_file, rootfs_dir, 'pc', addr2line_cmd, objdump_cmd)
|
|
ret2 = parse_user_pc_ulr(excinfo_file, rootfs_dir, 'ulr', addr2line_cmd, objdump_cmd)
|
|
#parse lr
|
|
parse_user_lr(excinfo_file, rootfs_dir, addr2line_cmd)
|
|
return ret1 and ret2
|
|
|
|
def parse_backtrace(backtrace_file, ohos_image_file, addr2line_cmd):
|
|
with open(backtrace_file, 'r+') as f:
|
|
find = -1
|
|
start = 0
|
|
index = 1
|
|
for lines in f.readlines():
|
|
if 'backtrace begin' in lines:
|
|
if start == 1:
|
|
break
|
|
start = 1
|
|
if start and 'lr =' in lines:
|
|
lines = lines[lines.find('lr ='):]
|
|
strlist = lines.split()
|
|
cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2])
|
|
ret = commands.getoutput(cmd)
|
|
ret = ret.split('\n')
|
|
print("\n<%.2d>%s<%s>" % (index, ret[0], strlist[2]))
|
|
index = index + 1
|
|
find = 0
|
|
|
|
return find
|
|
|
|
def parse_excinfo(excinfo_file, ohos_image_file, rootfs_dir, addr2line_cmd, objdump_cmd):
|
|
cmd = "dos2unix %s" % (excinfo_file)
|
|
commands.getoutput(cmd)
|
|
kernel_exc = is_kernel_exc(excinfo_file)
|
|
user_exc = is_user_exc(excinfo_file)
|
|
|
|
if kernel_exc == False and user_exc == False:
|
|
if parse_backtrace(excinfo_file, ohos_image_file, addr2line_cmd) != 0:
|
|
print("%s is not a excinfo or backtrace file\n"%excinfo_file)
|
|
return -1
|
|
else:
|
|
return 0
|
|
if user_exc:
|
|
if rootfs_dir != None:
|
|
return parse_user_exc(excinfo_file, rootfs_dir, addr2line_cmd, objdump_cmd)
|
|
else:
|
|
print('error: rootfs_dir is none')
|
|
return -1
|
|
return parse_kernel_exc(excinfo_file, ohos_image_file, addr2line_cmd, objdump_cmd)
|
|
|
|
def parse_compiler(compiler):
|
|
addr2line = ''
|
|
addr2line_cmd = ''
|
|
objdump = ''
|
|
objdump_cmd = ''
|
|
cmd = "which %s" % (compiler)
|
|
ret = commands.getoutput(cmd)
|
|
if ret == '':
|
|
print('%s is not exist'%compiler)
|
|
return None
|
|
index1 = ret.rfind('gcc')
|
|
index2 = ret.rfind('clang')
|
|
if index1 != -1:
|
|
addr2line = ret[0:index1] + 'addr2line'
|
|
objdump = ret[0:index1] + 'objdump'
|
|
elif index2 != -1:
|
|
index3 = ret.rfind('/')
|
|
addr2line = ret[0:index3 + 1] + 'llvm-addr2line'
|
|
objdump = ret[0:index3 + 1] + 'llvm-objdump'
|
|
else:
|
|
print('%s is not arm-xxx-xxx-gcc or clang'%compiler)
|
|
return None
|
|
addr2line_cmd = addr2line + ' -C -f -e '
|
|
objdump_cmd = objdump + ' -d '
|
|
return [addr2line_cmd, objdump_cmd]
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--f', help = 'excinfo file or backtrace file')
|
|
parser.add_argument('--e', help = 'elf system image file')
|
|
parser.add_argument('--r', help = 'the path of rootfs')
|
|
parser.add_argument('--c', help = 'compiler [arm-xxx-xxx-gcc/clang]')
|
|
args = parser.parse_args()
|
|
|
|
if args.f == None or args.e == None:
|
|
print("input error\n")
|
|
parser.print_help()
|
|
return -1
|
|
|
|
excinfo_file = args.f
|
|
ohos_image_file = args.e
|
|
rootfs_dir = args.r
|
|
|
|
addr2line_cmd = 'llvm-addr2line -C -f -e '
|
|
objdump_cmd = 'llvm-objdump -d '
|
|
if args.c != None:
|
|
cmd = parse_compiler(args.c)
|
|
if cmd == None:
|
|
return -1
|
|
addr2line_cmd = cmd[0]
|
|
objdump_cmd = cmd[1]
|
|
return parse_excinfo(excinfo_file, ohos_image_file, rootfs_dir, addr2line_cmd, objdump_cmd)
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|