20
20
21
21
from __future__ import print_function
22
22
from os import path
23
- import re , bisect
23
+ import re
24
+ import bisect
24
25
from subprocess import check_output
25
26
import sys
26
27
27
28
#arm-none-eabi-nm -nl <elf file>
28
- NM_EXEC = "arm-none-eabi-nm"
29
- OPT = "-nlC"
30
- ptn = re .compile ("([0-9a-f]*) ([Tt]) ([^\t \n ]*)(?:\t (.*):([0-9]*))?" )
31
- fnt = None
32
- fnt = ""
29
+ _NM_EXEC = "arm-none-eabi-nm"
30
+ _OPT = "-nlC"
31
+ _PTN = re .compile ("([0-9a-f]*) ([Tt]) ([^\t \n ]*)(?:\t (.*):([0-9]*))?" )
33
32
34
33
class ElfHelper (object ):
35
- def __init__ (self , p ,m ):
36
- if path .isfile (p ):
37
- elf_path = p
38
- if path .isfile (m ):
39
- map_path = m
40
-
41
- op = check_output ([NM_EXEC , OPT , elf_path ])
42
- map_file = open (map_path )
34
+ def __init__ (self , elf_file ,map_file ):
35
+
36
+ op = check_output ([_NM_EXEC , _OPT , elf_file .name ])
43
37
self .maplines = map_file .readlines ()
44
- self .matches = ptn .findall (op )
38
+ self .matches = _PTN .findall (op )
45
39
self .addrs = [int (x [0 ],16 ) for x in self .matches ]
46
40
47
41
def function_addrs (self ):
@@ -52,19 +46,7 @@ def function_name_for_addr(self, addr):
52
46
funcname = self .matches [i - 1 ][2 ]
53
47
return funcname
54
48
55
- def file_name_for_function_name (self , funcname ):
56
- for eachline in self .maplines :
57
- result = eachline .find (funcname )
58
- if (result != - 1 ):
59
- break
60
- toks = eachline .split ()
61
- if (len (toks ) <= 0 ):
62
- print ("WARN: Unable to find %s in map file" % (str (funcname )))
63
- return ("%s [FUNCTION]" % (str (funcname )))
64
- else :
65
- return toks [- 1 ]
66
-
67
- def parseHFSR (hfsr ):
49
+ def print_HFSR_info (hfsr ):
68
50
if (hfsr != 0 ):
69
51
if ( int (hfsr ,16 ) & 0x80000000 ):
70
52
print ("\t \t Debug Event Occured" )
@@ -73,7 +55,7 @@ def parseHFSR(hfsr):
73
55
if ( int (hfsr ,16 ) & 0x2 ):
74
56
print ("\t \t Vector table read fault has occurred" )
75
57
76
- def parseMMFSR (mmfsr ,mmfar ):
58
+ def print_MMFSR_info (mmfsr ,mmfar ):
77
59
if (mmfsr != 0 ):
78
60
if ( int (mmfsr ,16 ) & 0x20 ):
79
61
print ("\t \t A MemManage fault occurred during FP lazy state preservation" )
@@ -89,7 +71,7 @@ def parseMMFSR(mmfsr,mmfar):
89
71
if ( int (mmfsr ,16 ) & 0x1 ):
90
72
print ("\t \t MPU or Execute Never (XN) default memory map access violation on an instruction fetch has occurred" )
91
73
92
- def parseBFSR (bfsr ,bfar ):
74
+ def print_BFSR_info (bfsr ,bfar ):
93
75
if (bfsr != 0 ):
94
76
if ( int (bfsr ,16 ) & 0x20 ):
95
77
print ("\t \t A bus fault occurred during FP lazy state preservation" )
@@ -107,7 +89,7 @@ def parseBFSR(bfsr,bfar):
107
89
if ( int (bfsr ,16 ) & 0x1 ):
108
90
print ("\t \t A bus fault on an instruction prefetch has occurred" )
109
91
110
- def parseUFSR (ufsr ):
92
+ def print_UFSR_info (ufsr ):
111
93
if (ufsr != 0 ):
112
94
if ( int (ufsr ,16 ) & 0x200 ):
113
95
print ("\t \t Divide by zero error has occurred" )
@@ -122,156 +104,117 @@ def parseUFSR(ufsr):
122
104
if ( int (ufsr ,16 ) & 0x1 ):
123
105
print ("\t \t The processor has attempted to execute an undefined instruction" )
124
106
125
- def parseCPUID (cpuid ):
107
+ def print_CPUID_info (cpuid ):
126
108
if ( ( ( int (cpuid ,16 ) & 0xF0000 ) >> 16 ) == 0xC ):
127
109
print ("\t \t Processor Arch: ARM-V6M" )
128
110
else :
129
111
print ("\t \t Processor Arch: ARM-V7M or above" )
130
112
131
113
print ("\t \t Processor Variant: %X" % (( ( int (cpuid ,16 ) & 0xFFF0 ) >> 4 )))
132
-
133
114
134
- def main (input ):
135
- global fnt , pc_val , pc_name , lr_val , lr_name , sp_val , hfsr_val , mmfsr_val , ufsr_val , bfsr_val , cpuid_val , mmfar_val , bfar_val
136
- start_parsing = False
115
+ def parse_line_for_register (line ):
116
+ line = re .findall (r"[\w']+" , line )
117
+ line = [x .strip () for x in line if x != '' ]
118
+ tag , register_val = line
119
+ return register_val
120
+
121
+ def main (crash_log ,elfhelper ):
122
+ global pc_val , pc_name , lr_val , lr_name , sp_val , hfsr_val , mmfsr_val , ufsr_val , bfsr_val , cpuid_val , mmfar_val , bfar_val
137
123
mmfar_val = 0
138
124
bfar_val = 0
139
- crash_file = open ( input )
140
- lines = crash_file .readlines ()
125
+
126
+ lines = crash_log .readlines ()
141
127
142
128
cnt = 0
143
129
for eachline in lines :
144
- idx = eachline .find ("MbedOS Fault Handler" )
145
- if (- 1 != idx ):
130
+ if "++ MbedOS Fault Handler ++" in eachline :
146
131
break
147
- cnt = cnt + 1
148
-
149
- if (idx == - 1 ):
132
+ else :
150
133
print ("ERROR: Unable to find \" MbedOS Fault Handler\" header" )
151
134
return
152
135
153
-
154
- print ("\n \n Parsed Crash Info:" )
155
- for i in range (cnt ,len (lines )):
156
- eachline = lines [i ]
157
- if (- 1 != eachline .find ("--- MbedOS Fault Handler ---" )):
136
+ for eachline in lines :
137
+ if ("-- MbedOS Fault Handler --" in eachline ):
158
138
break
159
139
160
- if (eachline .startswith ("PC" )):
161
- l = re .findall (r"[\w']+" , eachline )
162
- l = [x .strip () for x in l if x != '' ]
163
- tag , pc_val = l
164
- pc_name = fnt .function_name_for_addr (int (pc_val ,16 ))
140
+ elif (eachline .startswith ("PC" )):
141
+ pc_val = parse_line_for_register (eachline )
142
+ pc_name = elfhelper .function_name_for_addr (int (pc_val ,16 ))
165
143
166
- if (eachline .startswith ("LR" )):
167
- l = re .findall (r"[\w']+" , eachline )
168
- l = [x .strip () for x in l if x != '' ]
169
- tag , lr_val = l
170
- lr_name = fnt .function_name_for_addr (int (lr_val ,16 ))
144
+ elif (eachline .startswith ("LR" )):
145
+ lr_val = parse_line_for_register (eachline )
146
+ lr_name = elfhelper .function_name_for_addr (int (lr_val ,16 ))
171
147
172
- if (eachline .startswith ("SP" )):
173
- l = re .findall (r"[\w']+" , eachline )
174
- l = [x .strip () for x in l if x != '' ]
175
- tag , sp_val = l
148
+ elif (eachline .startswith ("SP" )):
149
+ sp_val = parse_line_for_register (eachline )
176
150
177
- if (eachline .startswith ("HFSR" )):
178
- l = re .findall (r"[\w']+" , eachline )
179
- l = [x .strip () for x in l if x != '' ]
180
- tag , hfsr_val = l
151
+ elif (eachline .startswith ("HFSR" )):
152
+ hfsr_val = parse_line_for_register (eachline )
181
153
182
- if (eachline .startswith ("MMFSR" )):
183
- l = re .findall (r"[\w']+" , eachline )
184
- l = [x .strip () for x in l if x != '' ]
185
- tag , mmfsr_val = l
154
+ elif (eachline .startswith ("MMFSR" )):
155
+ mmfsr_val = parse_line_for_register (eachline )
186
156
187
- if (eachline .startswith ("BFSR" )):
188
- l = re .findall (r"[\w']+" , eachline )
189
- l = [x .strip () for x in l if x != '' ]
190
- tag , bfsr_val = l
157
+ elif (eachline .startswith ("BFSR" )):
158
+ bfsr_val = parse_line_for_register (eachline )
191
159
192
- if (eachline .startswith ("UFSR" )):
193
- l = re .findall (r"[\w']+" , eachline )
194
- l = [x .strip () for x in l if x != '' ]
195
- tag , ufsr_val = l
160
+ elif (eachline .startswith ("UFSR" )):
161
+ ufsr_val = parse_line_for_register (eachline )
196
162
197
- if (eachline .startswith ("CPUID" )):
198
- l = re .findall (r"[\w']+" , eachline )
199
- l = [x .strip () for x in l if x != '' ]
200
- tag , cpuid_val = l
163
+ elif (eachline .startswith ("CPUID" )):
164
+ cpuid_val = parse_line_for_register (eachline )
201
165
202
- if (eachline .startswith ("MMFAR" )):
203
- l = re .findall (r"[\w']+" , eachline )
204
- l = [x .strip () for x in l if x != '' ]
205
- tag , mmfar_val = l
166
+ elif (eachline .startswith ("MMFAR" )):
167
+ mmfar_val = parse_line_for_register (eachline )
206
168
207
- if (eachline .startswith ("BFAR" )):
208
- l = re .findall (r"[\w']+" , eachline )
209
- l = [x .strip () for x in l if x != '' ]
210
- tag , bfar_val = l
211
-
169
+ elif (eachline .startswith ("BFAR" )):
170
+ bfar_val = parse_line_for_register (eachline )
171
+
172
+ print ("\n \n Crash Info:" )
212
173
print ("\t Crash location = %s [%s] (based on PC value)" % (pc_name .strip (),str (pc_val )))
213
174
print ("\t Caller location = %s [%s] (based on LR value)" % (lr_name .strip (),str (lr_val )))
214
175
print ("\t Stack Pointer at the time of crash = [%s]" % (str (sp_val )))
215
176
216
- print ("\t Target/Fault Info:" )
217
- parseCPUID (cpuid_val )
218
- parseHFSR (hfsr_val )
219
- parseMMFSR (mmfsr_val ,mmfar_val )
220
- parseBFSR (bfsr_val ,bfar_val )
221
- parseUFSR (ufsr_val )
222
-
223
- print ("\n Done parsing..." )
177
+ print ("\t Target and Fault Info:" )
178
+ print_CPUID_info (cpuid_val )
179
+ print_HFSR_info (hfsr_val )
180
+ print_MMFSR_info (mmfsr_val ,mmfar_val )
181
+ print_BFSR_info (bfsr_val ,bfar_val )
182
+ print_UFSR_info (ufsr_val )
224
183
225
184
226
185
if __name__ == '__main__' :
227
186
import argparse
228
187
229
- parser = argparse .ArgumentParser (
230
- description = 'Analyse mbed-os crash log' )
231
-
188
+ parser = argparse .ArgumentParser (description = 'Analyse mbed-os crash log. This tool requires arm-gcc binary utilities to be available in current path as it uses \' nm\' command' )
232
189
# specify arguments
233
- parser .add_argument ('-i' ,'--input' , metavar = '<path to input file with crash log output>' , type = str ,
190
+ parser .add_argument ('-i' ,'--input' , metavar = '<path to input file with crash log output>' , type = argparse . FileType ( 'rb' , 0 ), required = True ,
234
191
help = 'path to input file' )
235
- parser .add_argument ('-e' ,'--elfpath' , metavar = '<module or elf file path>' , type = str ,
192
+ parser .add_argument ('-e' ,'--elfpath' , metavar = '<module or elf file path>' , type = argparse . FileType ( 'rb' , 0 ), required = True ,
236
193
help = 'path to elf file' )
237
- parser .add_argument ('-m' ,'--mappath' , metavar = '<map file path>' , type = str ,
194
+ parser .add_argument ('-m' ,'--mappath' , metavar = '<map file path>' , type = argparse . FileType ( 'rb' , 0 ), required = True ,
238
195
help = 'path to map file' )
239
196
240
197
# get and validate arguments
241
198
args = parser .parse_args ()
242
199
243
- p = args .elfpath
244
- m = args .mappath
245
- i = args .input
246
- if (p == None or m == None or i == None ):
247
- print ("Invalid arguments, exiting" )
248
- parser .print_usage ()
249
- sys .exit (1 )
250
-
251
- if not path .exists (p ):
252
- print ("Elf path %s does not exist" % (str (p )))
253
- parser .print_usage ()
254
- sys .exit (1 )
255
-
256
- if not path .exists (m ):
257
- print ("Map path %s does not exist" % (str (m )))
258
- parser .print_usage ()
259
- sys .exit (1 )
260
-
261
- if not path .exists (i ):
262
- print ("Input crash log path %s does not exist" % (str (i )))
263
- parser .print_usage ()
264
- sys .exit (1 )
200
+ elf_file = args .elfpath
201
+ map_file = args .mappath
202
+ input_crash_log = args .input
265
203
266
204
print ("Inputs:" )
267
- print ("\t Crash Log: %s" % (i ))
268
- print ("\t Elf Path: %s" % (p ))
269
- print ("\t Map Path: %s" % (m ))
205
+ print ("\t Crash Log: %s" % (input_crash_log . name ))
206
+ print ("\t Elf Path: %s" % (elf_file . name ))
207
+ print ("\t Map Path: %s" % (map_file . name ))
270
208
271
- fnt = ElfHelper (p , m )
209
+ elfhelper = ElfHelper (elf_file , map_file )
272
210
273
211
# parse input and write to output
274
- main (i )
212
+ main (input_crash_log ,elfhelper )
213
+
214
+ #close all files
215
+ elf_file .close ()
216
+ map_file .close ()
217
+ input_crash_log .close ()
275
218
276
219
277
220
0 commit comments