Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers crash_log_parser.py Source File

crash_log_parser.py

00001 #!/usr/bin/env python
00002 """
00003 mbed SDK
00004 Copyright (c) 2017-2019 ARM Limited
00005 
00006 Licensed under the Apache License, Version 2.0 (the "License");
00007 you may not use this file except in compliance with the License.
00008 You may obtain a copy of the License at
00009 
00010     http://www.apache.org/licenses/LICENSE-2.0
00011 
00012 Unless required by applicable law or agreed to in writing, software
00013 distributed under the License is distributed on an "AS IS" BASIS,
00014 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 See the License for the specific language governing permissions and
00016 limitations under the License.
00017 
00018 LIBRARIES BUILD
00019 """
00020 
00021 from __future__ import print_function
00022 from os import path
00023 import re
00024 import bisect
00025 from subprocess import check_output
00026 import sys
00027 
00028 #arm-none-eabi-nm -nl <elf file>
00029 _NM_EXEC = "arm-none-eabi-nm"
00030 _OPT = "-nlC"
00031 _PTN = re.compile("([0-9a-f]*) ([Tt]) ([^\t\n]*)(?:\t(.*):([0-9]*))?")
00032 
00033 class ElfHelper(object):
00034     def __init__(self, elf_file, map_file):
00035     
00036         op = check_output([_NM_EXEC, _OPT, elf_file.name])
00037         self.maplines = map_file.readlines()
00038         self.matches = _PTN.findall(op)
00039         self.addrs = [int(x[0], 16) for x in self.matches]
00040                 
00041     def function_addrs(self):
00042         return self.addrs
00043     
00044     def function_name_for_addr(self, addr):
00045         i = bisect.bisect_right(self.addrs, addr)
00046         funcname = self.matches[i-1][2]
00047         return funcname
00048 
00049 def print_HFSR_info(hfsr):
00050     if int(hfsr, 16) & 0x80000000:
00051         print("\t\tDebug Event Occurred")
00052     if int(hfsr, 16) & 0x40000000:
00053         print("\t\tForced exception, a fault with configurable priority has been escalated to HardFault")    
00054     if int(hfsr, 16) & 0x2:
00055         print("\t\tVector table read fault has occurred")        
00056 
00057 def print_MMFSR_info(mmfsr, mmfar):            
00058     if int(mmfsr, 16) & 0x20:
00059         print("\t\tA MemManage fault occurred during FP lazy state preservation")
00060     if int(mmfsr, 16) & 0x10:
00061         print("\t\tA derived MemManage fault occurred on exception entry")            
00062     if int(mmfsr, 16) & 0x8:
00063         print("\t\tA derived MemManage fault occurred on exception return")                
00064     if int(mmfsr, 16) & 0x2:
00065         if int(mmfsr, 16) & 0x80:
00066             print("\t\tData access violation. Faulting address: %s"%(str(mmfar)))                    
00067         else:     
00068             print("\t\tData access violation. WARNING: Fault address in MMFAR is NOT valid")                    
00069     if int(mmfsr, 16) & 0x1:
00070         print("\t\tMPU or Execute Never (XN) default memory map access violation on an instruction fetch has occurred")                        
00071     
00072 def print_BFSR_info(bfsr, bfar):
00073     if int(bfsr, 16) & 0x20:
00074         print("\t\tA bus fault occurred during FP lazy state preservation")
00075     if int(bfsr, 16) & 0x10:
00076         print("\t\tA derived bus fault has occurred on exception entry")  
00077     if int(bfsr, 16) & 0x8:
00078         print("\t\tA derived bus fault has occurred on exception return") 
00079     if int(bfsr, 16) & 0x4:
00080         print("\t\tImprecise data access error has occurred")               
00081     if int(bfsr, 16) & 0x2:
00082         if int(bfsr,16) & 0x80:
00083             print("\t\tA precise data access error has occurred. Faulting address: %s"%(str(bfar)))                    
00084         else:     
00085             print("\t\tA precise data access error has occurred. WARNING: Fault address in BFAR is NOT valid")             
00086     if int(bfsr, 16) & 0x1:
00087         print("\t\tA bus fault on an instruction prefetch has occurred")                           
00088 
00089 def print_UFSR_info(ufsr):            
00090     if int(ufsr, 16) & 0x200:
00091         print("\t\tDivide by zero error has occurred")
00092     if int(ufsr, 16) & 0x100:
00093         print("\t\tUnaligned access error has occurred")
00094     if int(ufsr, 16) & 0x8:
00095         print("\t\tA coprocessor access error has occurred. This shows that the coprocessor is disabled or not present")
00096     if int(ufsr, 16) & 0x4:
00097         print("\t\tAn integrity check error has occurred on EXC_RETURN")
00098     if int(ufsr, 16) & 0x2:
00099         print("\t\tInstruction executed with invalid EPSR.T or EPSR.IT field( This may be caused by Thumb bit not being set in branching instruction )")    
00100     if int(ufsr, 16) & 0x1:
00101         print("\t\tThe processor has attempted to execute an undefined instruction")        
00102     
00103 def print_CPUID_info(cpuid):            
00104     if (int(cpuid, 16) & 0xF0000) == 0xC0000:
00105         print("\t\tProcessor Arch: ARM-V6M")
00106     else:        
00107         print("\t\tProcessor Arch: ARM-V7M or above")
00108     
00109     print("\t\tProcessor Variant: %X" % ((int(cpuid,16) & 0xFFF0 ) >> 4))    
00110 
00111 def parse_line_for_register(line):
00112     _, register_val = line.split(":")
00113     return register_val.strip()    
00114 
00115 def main(crash_log, elfhelper):
00116     mmfar_val = 0
00117     bfar_val = 0
00118     lines = iter(crash_log.readlines())
00119     
00120     for eachline in lines:
00121         if "++ MbedOS Fault Handler ++" in eachline:
00122             break
00123     else:
00124         print("ERROR: Unable to find \"MbedOS Fault Handler\" header")
00125         return
00126     
00127     for eachline in lines:
00128         if "-- MbedOS Fault Handler --" in eachline:
00129             break
00130         
00131         elif eachline.startswith("PC"):
00132             pc_val = parse_line_for_register(eachline)
00133             pc_name = elfhelper.function_name_for_addr(int(pc_val, 16))
00134                         
00135         elif eachline.startswith("LR"):
00136             lr_val = parse_line_for_register(eachline)
00137             lr_name = elfhelper.function_name_for_addr(int(lr_val, 16))
00138             
00139         elif eachline.startswith("SP"):
00140             sp_val = parse_line_for_register(eachline)
00141                         
00142         elif eachline.startswith("HFSR"):
00143             hfsr_val = parse_line_for_register(eachline)
00144             
00145         elif eachline.startswith("MMFSR"):
00146             mmfsr_val = parse_line_for_register(eachline)
00147             
00148         elif eachline.startswith("BFSR"):
00149             bfsr_val = parse_line_for_register(eachline)
00150             
00151         elif eachline.startswith("UFSR"):
00152             ufsr_val = parse_line_for_register(eachline)
00153             
00154         elif eachline.startswith("CPUID"):
00155             cpuid_val = parse_line_for_register(eachline)
00156             
00157         elif eachline.startswith("MMFAR"):
00158             mmfar_val = parse_line_for_register(eachline)
00159             
00160         elif eachline.startswith("BFAR"):
00161             bfar_val = parse_line_for_register(eachline)    
00162     
00163     print("\nCrash Info:")        
00164     print("\tCrash location = %s [0x%s] (based on PC value)" % (pc_name.strip(), str(pc_val)))
00165     print("\tCaller location = %s [0x%s] (based on LR value)" % (lr_name.strip(), str(lr_val)))        
00166     print("\tStack Pointer at the time of crash = [%s]" % (str(sp_val)))
00167     
00168     print("\tTarget and Fault Info:")
00169     print_CPUID_info(cpuid_val)
00170     print_HFSR_info(hfsr_val)
00171     print_MMFSR_info(mmfsr_val, mmfar_val)
00172     print_BFSR_info(bfsr_val, bfar_val)
00173     print_UFSR_info(ufsr_val)
00174         
00175                             
00176 if __name__ == '__main__':
00177     import argparse
00178     
00179     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')
00180     # specify arguments
00181     parser.add_argument(metavar='CRASH LOG', type=argparse.FileType('rb', 0),
00182                         dest='crashlog',help='path to crash log file')      
00183     parser.add_argument(metavar='ELF FILE', type=argparse.FileType('rb', 0),
00184                         dest='elffile',help='path to elf file')             
00185     parser.add_argument(metavar='MAP FILE', type=argparse.FileType('rb', 0),
00186                         dest='mapfile',help='path to map file')                                    
00187 
00188     # get and validate arguments
00189     args = parser.parse_args()
00190     
00191     elfhelper = ElfHelper(args.elffile, args.mapfile)
00192     
00193     # parse input and write to output
00194     main(args.crashlog, elfhelper)
00195     
00196     #close all files
00197     args.elffile.close()
00198     args.mapfile.close()
00199     args.crashlog.close()
00200