1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 5# Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without modification, 8# are permitted provided that the following conditions are met: 9# 10# 1. Redistributions of source code must retain the above copyright notice, this list of 11# conditions and the following disclaimer. 12# 13# 2. Redistributions in binary form must reproduce the above copyright notice, this list 14# of conditions and the following disclaimer in the documentation and/or other materials 15# provided with the distribution. 16# 17# 3. Neither the name of the copyright holder nor the names of its contributors may be used 18# to endorse or promote products derived from this software without specific prior written 19# permission. 20# 21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 25# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 33import sys 34import os 35import argparse 36import io 37import commands 38 39def find_string(excinfo_file, string): 40 res = '' 41 with open(excinfo_file, 'r+') as f: 42 for lines in f: 43 if string in lines: 44 res = lines 45 break 46 return res 47 48def is_kernel_exc(excinfo_file): 49 res = find_string(excinfo_file, 'excFrom: kernel') 50 print(res) 51 return res != '' 52 53def is_user_exc(excinfo_file): 54 res = find_string(excinfo_file, 'excFrom: User') 55 print(res) 56 return res != '' 57 58def parse_string_line(excinfo_file, string): 59 line = find_string(excinfo_file, string) 60 if line == '': 61 print("%s is not in %s\n" %(string, excinfo_file)) 62 return '' 63 line = line.replace('\n', '') 64 strlist = line.split(' ') 65 return strlist 66 67def parse_kernel_pc_klr(excinfo_file, ohos_image_file, string, addr2line_cmd, objdump_cmd): 68 #parse pc 69 with open(excinfo_file, 'r+') as f: 70 start = 0 71 for lines in f.readlines(): 72 if 'excFrom: kernel' in lines: 73 if start == 1: 74 break 75 start = 1 76 if start and string in lines: 77 lines = lines[lines.find(string):] 78 strlist = lines.split() 79 cmd = "%s%s | grep %s: -B 10 -A 5 -w" % (objdump_cmd, ohos_image_file, strlist[2][2:]) 80 ret = commands.getoutput(cmd) 81 print(ret) 82 cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2]) 83 ret = commands.getoutput(cmd) 84 ret = ret.split('\n') 85 print("<%s>%s<%s>\n") % (string, ret[0], strlist[2]) 86 return 0 87 return -1 88 89def parse_kernel_lr(excinfo_file, ohos_image_file, addr2line_cmd): 90 with open(excinfo_file, 'r+') as f: 91 start = 0 92 index = 1 93 for lines in f.readlines(): 94 if 'excFrom: kernel' in lines: 95 if start == 1: 96 break 97 start = 1 98 if start and 'lr =' in lines: 99 lines = lines[lines.find('lr ='):] 100 strlist = lines.split() 101 cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2]) 102 ret = commands.getoutput(cmd) 103 ret = ret.split('\n') 104 print("<%.2d>%s<%s>" % (index, ret[0], strlist[2])) 105 index = index + 1 106 107def parse_kernel_exc(excinfo_file, ohos_image_file, addr2line_cmd, objdump_cmd): 108 #parse pc, klr 109 ret1 = parse_kernel_pc_klr(excinfo_file, ohos_image_file, 'pc', addr2line_cmd, objdump_cmd) 110 ret2 = parse_kernel_pc_klr(excinfo_file, ohos_image_file, 'klr', addr2line_cmd, objdump_cmd) 111 #parse lr 112 parse_kernel_lr(excinfo_file, ohos_image_file, addr2line_cmd) 113 return ret1 and ret2 114 115def parse_user_pc_ulr(excinfo_file, rootfs_dir, string, addr2line_cmd, objdump_cmd): 116 #parse pc 117 with open(excinfo_file, 'r+') as f: 118 start = 0 119 for lines in f.readlines(): 120 if 'excFrom: User' in lines: 121 if start == 1: 122 break 123 start = 1 124 if start and string in lines: 125 lines = lines[lines.find(string):] 126 strlist = lines.split() 127 if len(strlist) < 7: 128 print('%s is error'%string) 129 return 0 130 cmd = "%s%s%s | grep %s: -B 10 -A 5 -w" % (objdump_cmd, rootfs_dir, strlist[4], strlist[6][2:]) 131 ret = commands.getoutput(cmd) 132 print(ret) 133 cmd = "%s%s%s %s" % (addr2line_cmd, rootfs_dir, strlist[4], strlist[6]) 134 ret = commands.getoutput(cmd) 135 ret = ret.split('\n') 136 print("<%s>%s<%s><%s>\n" % (string, ret[0], strlist[6], strlist[4])) 137 return 0 138 return -1 139 140def parse_user_lr(excinfo_file, rootfs_dir, addr2line_cmd): 141 with open(excinfo_file, 'r+') as f: 142 start = 0 143 index = 1 144 for lines in f.readlines(): 145 if 'excFrom: User' in lines: 146 if start == 1: 147 break 148 start = 1 149 if start and 'lr =' in lines: 150 lines = lines[lines.find('lr ='):] 151 strlist = lines.split() 152 if len(strlist) < 11: 153 print('%s is error' % strlist) 154 return 155 cmd = "%s%s%s %s" % (addr2line_cmd, rootfs_dir, strlist[8], strlist[10]) 156 res = commands.getoutput(cmd) 157 res = res.split('\n') 158 print("<%.2d>%s<%s><%s>" % (index, res[0], strlist[10], strlist[8])) 159 index = index + 1 160 161def parse_user_exc(excinfo_file, rootfs_dir, addr2line_cmd, objdump_cmd): 162 #parse pc ulr 163 ret1 = parse_user_pc_ulr(excinfo_file, rootfs_dir, 'pc', addr2line_cmd, objdump_cmd) 164 ret2 = parse_user_pc_ulr(excinfo_file, rootfs_dir, 'ulr', addr2line_cmd, objdump_cmd) 165 #parse lr 166 parse_user_lr(excinfo_file, rootfs_dir, addr2line_cmd) 167 return ret1 and ret2 168 169def parse_backtrace(backtrace_file, ohos_image_file, addr2line_cmd): 170 with open(backtrace_file, 'r+') as f: 171 find = -1 172 start = 0 173 index = 1 174 for lines in f.readlines(): 175 if 'backtrace begin' in lines: 176 if start == 1: 177 break 178 start = 1 179 if start and 'lr =' in lines: 180 lines = lines[lines.find('lr ='):] 181 strlist = lines.split() 182 cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2]) 183 ret = commands.getoutput(cmd) 184 ret = ret.split('\n') 185 print("\n<%.2d>%s<%s>" % (index, ret[0], strlist[2])) 186 index = index + 1 187 find = 0 188 189 return find 190 191def parse_excinfo(excinfo_file, ohos_image_file, rootfs_dir, addr2line_cmd, objdump_cmd): 192 cmd = "dos2unix %s" % (excinfo_file) 193 commands.getoutput(cmd) 194 kernel_exc = is_kernel_exc(excinfo_file) 195 user_exc = is_user_exc(excinfo_file) 196 197 if kernel_exc == False and user_exc == False: 198 if parse_backtrace(excinfo_file, ohos_image_file, addr2line_cmd) != 0: 199 print("%s is not a excinfo or backtrace file\n"%excinfo_file) 200 return -1 201 else: 202 return 0 203 if user_exc: 204 if rootfs_dir != None: 205 return parse_user_exc(excinfo_file, rootfs_dir, addr2line_cmd, objdump_cmd) 206 else: 207 print('error: rootfs_dir is none') 208 return -1 209 return parse_kernel_exc(excinfo_file, ohos_image_file, addr2line_cmd, objdump_cmd) 210 211def parse_compiler(compiler): 212 addr2line = '' 213 addr2line_cmd = '' 214 objdump = '' 215 objdump_cmd = '' 216 cmd = "which %s" % (compiler) 217 ret = commands.getoutput(cmd) 218 if ret == '': 219 print('%s is not exist'%compiler) 220 return None 221 index1 = ret.rfind('gcc') 222 index2 = ret.rfind('clang') 223 if index1 != -1: 224 addr2line = ret[0:index1] + 'addr2line' 225 objdump = ret[0:index1] + 'objdump' 226 elif index2 != -1: 227 index3 = ret.rfind('/') 228 addr2line = ret[0:index3 + 1] + 'llvm-addr2line' 229 objdump = ret[0:index3 + 1] + 'llvm-objdump' 230 else: 231 print('%s is not arm-xxx-xxx-gcc or clang'%compiler) 232 return None 233 addr2line_cmd = addr2line + ' -C -f -e ' 234 objdump_cmd = objdump + ' -d ' 235 return [addr2line_cmd, objdump_cmd] 236 237def main(): 238 parser = argparse.ArgumentParser() 239 parser.add_argument('--f', help = 'excinfo file or backtrace file') 240 parser.add_argument('--e', help = 'elf system image file') 241 parser.add_argument('--r', help = 'the path of rootfs') 242 parser.add_argument('--c', help = 'compiler [arm-xxx-xxx-gcc/clang]') 243 args = parser.parse_args() 244 245 if args.f == None or args.e == None: 246 print("input error\n") 247 parser.print_help() 248 return -1 249 250 excinfo_file = args.f 251 ohos_image_file = args.e 252 rootfs_dir = args.r 253 254 addr2line_cmd = 'llvm-addr2line -C -f -e ' 255 objdump_cmd = 'llvm-objdump -d ' 256 if args.c != None: 257 cmd = parse_compiler(args.c) 258 if cmd == None: 259 return -1 260 addr2line_cmd = cmd[0] 261 objdump_cmd = cmd[1] 262 return parse_excinfo(excinfo_file, ohos_image_file, rootfs_dir, addr2line_cmd, objdump_cmd) 263 264if __name__ == "__main__": 265 sys.exit(main()) 266