10d163575Sopenharmony_ci#!/usr/bin/env python
20d163575Sopenharmony_ci# -*- coding: utf-8 -*-
30d163575Sopenharmony_ci
40d163575Sopenharmony_ci# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
50d163575Sopenharmony_ci# Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
60d163575Sopenharmony_ci#
70d163575Sopenharmony_ci# Redistribution and use in source and binary forms, with or without modification,
80d163575Sopenharmony_ci# are permitted provided that the following conditions are met:
90d163575Sopenharmony_ci#
100d163575Sopenharmony_ci# 1. Redistributions of source code must retain the above copyright notice, this list of
110d163575Sopenharmony_ci#    conditions and the following disclaimer.
120d163575Sopenharmony_ci#
130d163575Sopenharmony_ci# 2. Redistributions in binary form must reproduce the above copyright notice, this list
140d163575Sopenharmony_ci#    of conditions and the following disclaimer in the documentation and/or other materials
150d163575Sopenharmony_ci#    provided with the distribution.
160d163575Sopenharmony_ci#
170d163575Sopenharmony_ci# 3. Neither the name of the copyright holder nor the names of its contributors may be used
180d163575Sopenharmony_ci#    to endorse or promote products derived from this software without specific prior written
190d163575Sopenharmony_ci#    permission.
200d163575Sopenharmony_ci#
210d163575Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
220d163575Sopenharmony_ci# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
230d163575Sopenharmony_ci# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
240d163575Sopenharmony_ci# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
250d163575Sopenharmony_ci# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
260d163575Sopenharmony_ci# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
270d163575Sopenharmony_ci# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
280d163575Sopenharmony_ci# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
290d163575Sopenharmony_ci# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
300d163575Sopenharmony_ci# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
310d163575Sopenharmony_ci# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
320d163575Sopenharmony_ci
330d163575Sopenharmony_ciimport sys
340d163575Sopenharmony_ciimport os
350d163575Sopenharmony_ciimport argparse
360d163575Sopenharmony_ciimport io
370d163575Sopenharmony_ciimport commands
380d163575Sopenharmony_ci
390d163575Sopenharmony_cidef find_string(excinfo_file, string):
400d163575Sopenharmony_ci    res = ''
410d163575Sopenharmony_ci    with open(excinfo_file, 'r+') as f:
420d163575Sopenharmony_ci        for lines in f:
430d163575Sopenharmony_ci            if string in lines:
440d163575Sopenharmony_ci                res = lines
450d163575Sopenharmony_ci                break
460d163575Sopenharmony_ci    return res
470d163575Sopenharmony_ci
480d163575Sopenharmony_cidef is_kernel_exc(excinfo_file):
490d163575Sopenharmony_ci    res = find_string(excinfo_file, 'excFrom: kernel')
500d163575Sopenharmony_ci    print(res)
510d163575Sopenharmony_ci    return res != ''
520d163575Sopenharmony_ci
530d163575Sopenharmony_cidef is_user_exc(excinfo_file):
540d163575Sopenharmony_ci    res = find_string(excinfo_file, 'excFrom: User')
550d163575Sopenharmony_ci    print(res)
560d163575Sopenharmony_ci    return res != ''
570d163575Sopenharmony_ci
580d163575Sopenharmony_cidef parse_string_line(excinfo_file, string):
590d163575Sopenharmony_ci    line = find_string(excinfo_file, string)
600d163575Sopenharmony_ci    if line == '':
610d163575Sopenharmony_ci        print("%s is not in %s\n" %(string, excinfo_file))
620d163575Sopenharmony_ci        return ''
630d163575Sopenharmony_ci    line = line.replace('\n', '')
640d163575Sopenharmony_ci    strlist = line.split(' ')
650d163575Sopenharmony_ci    return strlist
660d163575Sopenharmony_ci
670d163575Sopenharmony_cidef parse_kernel_pc_klr(excinfo_file, ohos_image_file, string, addr2line_cmd, objdump_cmd):
680d163575Sopenharmony_ci    #parse pc
690d163575Sopenharmony_ci    with open(excinfo_file, 'r+') as f:
700d163575Sopenharmony_ci        start = 0
710d163575Sopenharmony_ci        for lines in f.readlines():
720d163575Sopenharmony_ci            if 'excFrom: kernel' in lines:
730d163575Sopenharmony_ci                if start == 1:
740d163575Sopenharmony_ci                    break
750d163575Sopenharmony_ci                start = 1
760d163575Sopenharmony_ci            if start and string in lines:
770d163575Sopenharmony_ci                lines = lines[lines.find(string):]
780d163575Sopenharmony_ci                strlist = lines.split()
790d163575Sopenharmony_ci                cmd = "%s%s | grep %s: -B 10 -A 5 -w" % (objdump_cmd, ohos_image_file, strlist[2][2:])
800d163575Sopenharmony_ci                ret = commands.getoutput(cmd)
810d163575Sopenharmony_ci                print(ret)
820d163575Sopenharmony_ci                cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2])
830d163575Sopenharmony_ci                ret = commands.getoutput(cmd)
840d163575Sopenharmony_ci                ret = ret.split('\n')
850d163575Sopenharmony_ci                print("<%s>%s<%s>\n") % (string, ret[0], strlist[2])
860d163575Sopenharmony_ci                return 0
870d163575Sopenharmony_ci    return -1
880d163575Sopenharmony_ci
890d163575Sopenharmony_cidef parse_kernel_lr(excinfo_file, ohos_image_file, addr2line_cmd):
900d163575Sopenharmony_ci    with open(excinfo_file, 'r+') as f:
910d163575Sopenharmony_ci        start = 0
920d163575Sopenharmony_ci        index = 1
930d163575Sopenharmony_ci        for lines in f.readlines():
940d163575Sopenharmony_ci            if 'excFrom: kernel' in lines:
950d163575Sopenharmony_ci                if start == 1:
960d163575Sopenharmony_ci                    break
970d163575Sopenharmony_ci                start = 1
980d163575Sopenharmony_ci            if start and 'lr =' in lines:
990d163575Sopenharmony_ci                lines = lines[lines.find('lr ='):]
1000d163575Sopenharmony_ci                strlist = lines.split()
1010d163575Sopenharmony_ci                cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2])
1020d163575Sopenharmony_ci                ret = commands.getoutput(cmd)
1030d163575Sopenharmony_ci                ret = ret.split('\n')
1040d163575Sopenharmony_ci                print("<%.2d>%s<%s>" % (index, ret[0], strlist[2]))
1050d163575Sopenharmony_ci                index = index + 1
1060d163575Sopenharmony_ci
1070d163575Sopenharmony_cidef parse_kernel_exc(excinfo_file, ohos_image_file, addr2line_cmd, objdump_cmd):
1080d163575Sopenharmony_ci    #parse pc, klr
1090d163575Sopenharmony_ci    ret1 = parse_kernel_pc_klr(excinfo_file, ohos_image_file, 'pc', addr2line_cmd, objdump_cmd)
1100d163575Sopenharmony_ci    ret2 = parse_kernel_pc_klr(excinfo_file, ohos_image_file, 'klr', addr2line_cmd, objdump_cmd)
1110d163575Sopenharmony_ci    #parse lr
1120d163575Sopenharmony_ci    parse_kernel_lr(excinfo_file, ohos_image_file, addr2line_cmd)
1130d163575Sopenharmony_ci    return ret1 and ret2
1140d163575Sopenharmony_ci
1150d163575Sopenharmony_cidef parse_user_pc_ulr(excinfo_file, rootfs_dir, string, addr2line_cmd, objdump_cmd):
1160d163575Sopenharmony_ci    #parse pc
1170d163575Sopenharmony_ci    with open(excinfo_file, 'r+') as f:
1180d163575Sopenharmony_ci        start = 0
1190d163575Sopenharmony_ci        for lines in f.readlines():
1200d163575Sopenharmony_ci            if 'excFrom: User' in lines:
1210d163575Sopenharmony_ci                if start == 1:
1220d163575Sopenharmony_ci                    break
1230d163575Sopenharmony_ci                start = 1
1240d163575Sopenharmony_ci            if start and string in lines:
1250d163575Sopenharmony_ci                lines = lines[lines.find(string):]
1260d163575Sopenharmony_ci                strlist = lines.split()
1270d163575Sopenharmony_ci                if len(strlist) < 7:
1280d163575Sopenharmony_ci                    print('%s is error'%string)
1290d163575Sopenharmony_ci                    return 0
1300d163575Sopenharmony_ci                cmd = "%s%s%s | grep %s: -B 10 -A 5 -w" % (objdump_cmd, rootfs_dir, strlist[4], strlist[6][2:])
1310d163575Sopenharmony_ci                ret = commands.getoutput(cmd)
1320d163575Sopenharmony_ci                print(ret)
1330d163575Sopenharmony_ci                cmd = "%s%s%s %s" % (addr2line_cmd, rootfs_dir, strlist[4], strlist[6])
1340d163575Sopenharmony_ci                ret = commands.getoutput(cmd)
1350d163575Sopenharmony_ci                ret = ret.split('\n')
1360d163575Sopenharmony_ci                print("<%s>%s<%s><%s>\n" % (string, ret[0], strlist[6], strlist[4]))
1370d163575Sopenharmony_ci                return 0
1380d163575Sopenharmony_ci    return -1
1390d163575Sopenharmony_ci
1400d163575Sopenharmony_cidef parse_user_lr(excinfo_file, rootfs_dir, addr2line_cmd):
1410d163575Sopenharmony_ci    with open(excinfo_file, 'r+') as f:
1420d163575Sopenharmony_ci        start = 0
1430d163575Sopenharmony_ci        index = 1
1440d163575Sopenharmony_ci        for lines in f.readlines():
1450d163575Sopenharmony_ci            if 'excFrom: User' in lines:
1460d163575Sopenharmony_ci                if start == 1:
1470d163575Sopenharmony_ci                    break
1480d163575Sopenharmony_ci                start = 1
1490d163575Sopenharmony_ci            if start and 'lr =' in lines:
1500d163575Sopenharmony_ci                lines = lines[lines.find('lr ='):]
1510d163575Sopenharmony_ci                strlist = lines.split()
1520d163575Sopenharmony_ci                if len(strlist) < 11:
1530d163575Sopenharmony_ci                    print('%s is error' % strlist)
1540d163575Sopenharmony_ci                    return
1550d163575Sopenharmony_ci                cmd = "%s%s%s %s" % (addr2line_cmd, rootfs_dir, strlist[8], strlist[10])
1560d163575Sopenharmony_ci                res = commands.getoutput(cmd)
1570d163575Sopenharmony_ci                res = res.split('\n')
1580d163575Sopenharmony_ci                print("<%.2d>%s<%s><%s>" % (index, res[0], strlist[10], strlist[8]))
1590d163575Sopenharmony_ci                index = index + 1
1600d163575Sopenharmony_ci
1610d163575Sopenharmony_cidef parse_user_exc(excinfo_file, rootfs_dir, addr2line_cmd, objdump_cmd):
1620d163575Sopenharmony_ci    #parse pc ulr
1630d163575Sopenharmony_ci    ret1 = parse_user_pc_ulr(excinfo_file, rootfs_dir, 'pc', addr2line_cmd, objdump_cmd)
1640d163575Sopenharmony_ci    ret2 = parse_user_pc_ulr(excinfo_file, rootfs_dir, 'ulr', addr2line_cmd, objdump_cmd)
1650d163575Sopenharmony_ci    #parse lr
1660d163575Sopenharmony_ci    parse_user_lr(excinfo_file, rootfs_dir, addr2line_cmd)
1670d163575Sopenharmony_ci    return ret1 and ret2
1680d163575Sopenharmony_ci
1690d163575Sopenharmony_cidef parse_backtrace(backtrace_file, ohos_image_file, addr2line_cmd):
1700d163575Sopenharmony_ci    with open(backtrace_file, 'r+') as f:
1710d163575Sopenharmony_ci        find = -1
1720d163575Sopenharmony_ci        start = 0
1730d163575Sopenharmony_ci        index = 1
1740d163575Sopenharmony_ci        for lines in f.readlines():
1750d163575Sopenharmony_ci            if 'backtrace begin' in lines:
1760d163575Sopenharmony_ci                if start == 1:
1770d163575Sopenharmony_ci                    break
1780d163575Sopenharmony_ci                start = 1
1790d163575Sopenharmony_ci            if start and 'lr =' in lines:
1800d163575Sopenharmony_ci                lines = lines[lines.find('lr ='):]
1810d163575Sopenharmony_ci                strlist = lines.split()
1820d163575Sopenharmony_ci                cmd = "%s%s %s" % (addr2line_cmd, ohos_image_file, strlist[2])
1830d163575Sopenharmony_ci                ret = commands.getoutput(cmd)
1840d163575Sopenharmony_ci                ret = ret.split('\n')
1850d163575Sopenharmony_ci                print("\n<%.2d>%s<%s>" % (index, ret[0], strlist[2]))
1860d163575Sopenharmony_ci                index = index + 1
1870d163575Sopenharmony_ci                find = 0
1880d163575Sopenharmony_ci
1890d163575Sopenharmony_ci    return find
1900d163575Sopenharmony_ci
1910d163575Sopenharmony_cidef parse_excinfo(excinfo_file, ohos_image_file, rootfs_dir, addr2line_cmd, objdump_cmd):
1920d163575Sopenharmony_ci    cmd = "dos2unix %s" % (excinfo_file)
1930d163575Sopenharmony_ci    commands.getoutput(cmd)
1940d163575Sopenharmony_ci    kernel_exc = is_kernel_exc(excinfo_file)
1950d163575Sopenharmony_ci    user_exc = is_user_exc(excinfo_file)
1960d163575Sopenharmony_ci
1970d163575Sopenharmony_ci    if kernel_exc == False and user_exc == False:
1980d163575Sopenharmony_ci        if parse_backtrace(excinfo_file, ohos_image_file, addr2line_cmd) != 0:
1990d163575Sopenharmony_ci            print("%s is not a excinfo or backtrace file\n"%excinfo_file)
2000d163575Sopenharmony_ci            return -1
2010d163575Sopenharmony_ci        else:
2020d163575Sopenharmony_ci            return 0
2030d163575Sopenharmony_ci    if user_exc:
2040d163575Sopenharmony_ci        if rootfs_dir != None:
2050d163575Sopenharmony_ci            return parse_user_exc(excinfo_file, rootfs_dir, addr2line_cmd, objdump_cmd)
2060d163575Sopenharmony_ci        else:
2070d163575Sopenharmony_ci            print('error: rootfs_dir is none')
2080d163575Sopenharmony_ci            return -1
2090d163575Sopenharmony_ci    return parse_kernel_exc(excinfo_file, ohos_image_file, addr2line_cmd, objdump_cmd)
2100d163575Sopenharmony_ci
2110d163575Sopenharmony_cidef parse_compiler(compiler):
2120d163575Sopenharmony_ci    addr2line = ''
2130d163575Sopenharmony_ci    addr2line_cmd = ''
2140d163575Sopenharmony_ci    objdump = ''
2150d163575Sopenharmony_ci    objdump_cmd = ''
2160d163575Sopenharmony_ci    cmd = "which %s" % (compiler)
2170d163575Sopenharmony_ci    ret = commands.getoutput(cmd)
2180d163575Sopenharmony_ci    if ret == '':
2190d163575Sopenharmony_ci        print('%s is not exist'%compiler)
2200d163575Sopenharmony_ci        return None
2210d163575Sopenharmony_ci    index1 = ret.rfind('gcc')
2220d163575Sopenharmony_ci    index2 = ret.rfind('clang')
2230d163575Sopenharmony_ci    if index1 != -1:
2240d163575Sopenharmony_ci        addr2line = ret[0:index1] + 'addr2line'
2250d163575Sopenharmony_ci        objdump = ret[0:index1] + 'objdump'
2260d163575Sopenharmony_ci    elif index2 != -1:
2270d163575Sopenharmony_ci        index3 = ret.rfind('/')
2280d163575Sopenharmony_ci        addr2line = ret[0:index3 + 1] + 'llvm-addr2line'
2290d163575Sopenharmony_ci        objdump = ret[0:index3 + 1] + 'llvm-objdump'
2300d163575Sopenharmony_ci    else:
2310d163575Sopenharmony_ci        print('%s is not arm-xxx-xxx-gcc or clang'%compiler)
2320d163575Sopenharmony_ci        return None
2330d163575Sopenharmony_ci    addr2line_cmd = addr2line + ' -C -f -e '
2340d163575Sopenharmony_ci    objdump_cmd = objdump + ' -d '
2350d163575Sopenharmony_ci    return [addr2line_cmd, objdump_cmd]
2360d163575Sopenharmony_ci
2370d163575Sopenharmony_cidef main():
2380d163575Sopenharmony_ci    parser = argparse.ArgumentParser()
2390d163575Sopenharmony_ci    parser.add_argument('--f', help = 'excinfo file or backtrace file')
2400d163575Sopenharmony_ci    parser.add_argument('--e', help = 'elf system image file')
2410d163575Sopenharmony_ci    parser.add_argument('--r', help = 'the path of rootfs')
2420d163575Sopenharmony_ci    parser.add_argument('--c', help = 'compiler [arm-xxx-xxx-gcc/clang]')
2430d163575Sopenharmony_ci    args = parser.parse_args()
2440d163575Sopenharmony_ci
2450d163575Sopenharmony_ci    if args.f == None or args.e == None:
2460d163575Sopenharmony_ci        print("input error\n")
2470d163575Sopenharmony_ci        parser.print_help()
2480d163575Sopenharmony_ci        return -1
2490d163575Sopenharmony_ci
2500d163575Sopenharmony_ci    excinfo_file = args.f
2510d163575Sopenharmony_ci    ohos_image_file = args.e
2520d163575Sopenharmony_ci    rootfs_dir = args.r
2530d163575Sopenharmony_ci
2540d163575Sopenharmony_ci    addr2line_cmd = 'llvm-addr2line -C -f -e '
2550d163575Sopenharmony_ci    objdump_cmd = 'llvm-objdump -d '
2560d163575Sopenharmony_ci    if args.c != None:
2570d163575Sopenharmony_ci        cmd = parse_compiler(args.c)
2580d163575Sopenharmony_ci        if cmd == None:
2590d163575Sopenharmony_ci            return -1
2600d163575Sopenharmony_ci        addr2line_cmd = cmd[0]
2610d163575Sopenharmony_ci        objdump_cmd = cmd[1]
2620d163575Sopenharmony_ci    return parse_excinfo(excinfo_file, ohos_image_file, rootfs_dir, addr2line_cmd, objdump_cmd)
2630d163575Sopenharmony_ci
2640d163575Sopenharmony_ciif __name__ == "__main__":
2650d163575Sopenharmony_ci    sys.exit(main())
266