#!/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())