• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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