diff --git a/tools/debug_tools/crash_log_parser/crash_log_parser.py b/tools/debug_tools/crash_log_parser/crash_log_parser.py index 32bfda0a35..5ab221bf16 100644 --- a/tools/debug_tools/crash_log_parser/crash_log_parser.py +++ b/tools/debug_tools/crash_log_parser/crash_log_parser.py @@ -20,28 +20,22 @@ LIBRARIES BUILD from __future__ import print_function from os import path -import re, bisect +import re +import bisect from subprocess import check_output import sys #arm-none-eabi-nm -nl -NM_EXEC = "arm-none-eabi-nm" -OPT = "-nlC" -ptn = re.compile("([0-9a-f]*) ([Tt]) ([^\t\n]*)(?:\t(.*):([0-9]*))?") -fnt = None -fnt = "" +_NM_EXEC = "arm-none-eabi-nm" +_OPT = "-nlC" +_PTN = re.compile("([0-9a-f]*) ([Tt]) ([^\t\n]*)(?:\t(.*):([0-9]*))?") class ElfHelper(object): - def __init__(self, p,m): - if path.isfile(p): - elf_path = p - if path.isfile(m): - map_path = m - - op = check_output([NM_EXEC, OPT, elf_path]) - map_file = open(map_path) + def __init__(self, elf_file,map_file): + + op = check_output([_NM_EXEC, _OPT, elf_file.name]) self.maplines = map_file.readlines() - self.matches = ptn.findall(op) + self.matches = _PTN.findall(op) self.addrs = [int(x[0],16) for x in self.matches] def function_addrs(self): @@ -52,19 +46,7 @@ class ElfHelper(object): funcname = self.matches[i-1][2] return funcname - def file_name_for_function_name(self, funcname): - for eachline in self.maplines: - result = eachline.find(funcname) - if(result != -1): - break - toks = eachline.split() - if(len(toks) <= 0): - print("WARN: Unable to find %s in map file"%(str(funcname))) - return ("%s [FUNCTION]"%(str(funcname))) - else: - return toks[-1] - -def parseHFSR(hfsr): +def print_HFSR_info(hfsr): if(hfsr != 0): if( int(hfsr,16) & 0x80000000 ): print("\t\tDebug Event Occured") @@ -73,7 +55,7 @@ def parseHFSR(hfsr): if( int(hfsr,16) & 0x2 ): print("\t\tVector table read fault has occurred") -def parseMMFSR(mmfsr,mmfar): +def print_MMFSR_info(mmfsr,mmfar): if(mmfsr != 0): if( int(mmfsr,16) & 0x20 ): print("\t\tA MemManage fault occurred during FP lazy state preservation") @@ -89,7 +71,7 @@ def parseMMFSR(mmfsr,mmfar): if( int(mmfsr,16) & 0x1 ): print("\t\tMPU or Execute Never (XN) default memory map access violation on an instruction fetch has occurred") -def parseBFSR(bfsr,bfar): +def print_BFSR_info(bfsr,bfar): if(bfsr != 0): if( int(bfsr,16) & 0x20 ): print("\t\tA bus fault occurred during FP lazy state preservation") @@ -107,7 +89,7 @@ def parseBFSR(bfsr,bfar): if( int(bfsr,16) & 0x1 ): print("\t\tA bus fault on an instruction prefetch has occurred") -def parseUFSR(ufsr): +def print_UFSR_info(ufsr): if(ufsr != 0): if( int(ufsr,16) & 0x200 ): print("\t\tDivide by zero error has occurred") @@ -122,156 +104,117 @@ def parseUFSR(ufsr): if( int(ufsr,16) & 0x1 ): print("\t\tThe processor has attempted to execute an undefined instruction") -def parseCPUID(cpuid): +def print_CPUID_info(cpuid): if( ( ( int(cpuid,16) & 0xF0000 ) >> 16 ) == 0xC ): print("\t\tProcessor Arch: ARM-V6M") else: print("\t\tProcessor Arch: ARM-V7M or above") print("\t\tProcessor Variant: %X"%(( ( int(cpuid,16) & 0xFFF0 ) >> 4 ))) - -def main(input): - 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 - start_parsing = False +def parse_line_for_register(line): + line = re.findall(r"[\w']+", line) + line = [x.strip() for x in line if x != ''] + tag, register_val = line + return register_val + +def main(crash_log,elfhelper): + 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 mmfar_val = 0 bfar_val = 0 - crash_file = open(input) - lines = crash_file.readlines() + + lines = crash_log.readlines() cnt = 0 for eachline in lines: - idx = eachline.find("MbedOS Fault Handler") - if(-1 != idx): + if "++ MbedOS Fault Handler ++" in eachline: break - cnt=cnt+1 - - if(idx == -1): + else: print("ERROR: Unable to find \"MbedOS Fault Handler\" header") return - - print("\n\nParsed Crash Info:") - for i in range(cnt,len(lines)): - eachline=lines[i] - if(-1 != eachline.find("--- MbedOS Fault Handler ---")): + for eachline in lines: + if("-- MbedOS Fault Handler --" in eachline): break - if(eachline.startswith("PC")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, pc_val = l - pc_name = fnt.function_name_for_addr(int(pc_val,16)) + elif(eachline.startswith("PC")): + pc_val = parse_line_for_register(eachline) + pc_name = elfhelper.function_name_for_addr(int(pc_val,16)) - if(eachline.startswith("LR")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, lr_val = l - lr_name = fnt.function_name_for_addr(int(lr_val,16)) + elif(eachline.startswith("LR")): + lr_val = parse_line_for_register(eachline) + lr_name = elfhelper.function_name_for_addr(int(lr_val,16)) - if(eachline.startswith("SP")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, sp_val = l + elif(eachline.startswith("SP")): + sp_val = parse_line_for_register(eachline) - if(eachline.startswith("HFSR")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, hfsr_val = l + elif(eachline.startswith("HFSR")): + hfsr_val = parse_line_for_register(eachline) - if(eachline.startswith("MMFSR")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, mmfsr_val = l + elif(eachline.startswith("MMFSR")): + mmfsr_val = parse_line_for_register(eachline) - if(eachline.startswith("BFSR")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, bfsr_val = l + elif(eachline.startswith("BFSR")): + bfsr_val = parse_line_for_register(eachline) - if(eachline.startswith("UFSR")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, ufsr_val = l + elif(eachline.startswith("UFSR")): + ufsr_val = parse_line_for_register(eachline) - if(eachline.startswith("CPUID")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, cpuid_val = l + elif(eachline.startswith("CPUID")): + cpuid_val = parse_line_for_register(eachline) - if(eachline.startswith("MMFAR")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, mmfar_val = l + elif(eachline.startswith("MMFAR")): + mmfar_val = parse_line_for_register(eachline) - if(eachline.startswith("BFAR")): - l = re.findall(r"[\w']+", eachline) - l = [x.strip() for x in l if x != ''] - tag, bfar_val = l - + elif(eachline.startswith("BFAR")): + bfar_val = parse_line_for_register(eachline) + + print("\n\nCrash Info:") print("\tCrash location = %s [%s] (based on PC value)"%(pc_name.strip(),str(pc_val))) print("\tCaller location = %s [%s] (based on LR value)"%(lr_name.strip(),str(lr_val))) print("\tStack Pointer at the time of crash = [%s]"%(str(sp_val))) - print("\tTarget/Fault Info:") - parseCPUID(cpuid_val) - parseHFSR(hfsr_val) - parseMMFSR(mmfsr_val,mmfar_val) - parseBFSR(bfsr_val,bfar_val) - parseUFSR(ufsr_val) - - print("\nDone parsing...") + print("\tTarget and Fault Info:") + print_CPUID_info(cpuid_val) + print_HFSR_info(hfsr_val) + print_MMFSR_info(mmfsr_val,mmfar_val) + print_BFSR_info(bfsr_val,bfar_val) + print_UFSR_info(ufsr_val) if __name__ == '__main__': import argparse - parser = argparse.ArgumentParser( - description='Analyse mbed-os crash log') - + 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') # specify arguments - parser.add_argument('-i','--input', metavar='', type=str, + parser.add_argument('-i','--input', metavar='', type=argparse.FileType('rb', 0), required=True, help='path to input file') - parser.add_argument('-e','--elfpath', metavar='', type=str, + parser.add_argument('-e','--elfpath', metavar='', type=argparse.FileType('rb', 0), required=True, help='path to elf file') - parser.add_argument('-m','--mappath', metavar='', type=str, + parser.add_argument('-m','--mappath', metavar='', type=argparse.FileType('rb', 0), required=True, help='path to map file') # get and validate arguments args = parser.parse_args() - p = args.elfpath - m = args.mappath - i = args.input - if(p == None or m == None or i == None): - print("Invalid arguments, exiting") - parser.print_usage() - sys.exit(1) - - if not path.exists(p): - print("Elf path %s does not exist"%(str(p))) - parser.print_usage() - sys.exit(1) - - if not path.exists(m): - print("Map path %s does not exist"%(str(m))) - parser.print_usage() - sys.exit(1) - - if not path.exists(i): - print("Input crash log path %s does not exist"%(str(i))) - parser.print_usage() - sys.exit(1) + elf_file = args.elfpath + map_file = args.mappath + input_crash_log = args.input print("Inputs:") - print("\tCrash Log: %s"%(i)) - print("\tElf Path: %s"%(p)) - print("\tMap Path: %s"%(m)) + print("\tCrash Log: %s"%(input_crash_log.name)) + print("\tElf Path: %s"%(elf_file.name)) + print("\tMap Path: %s"%(map_file.name)) - fnt = ElfHelper(p,m) + elfhelper = ElfHelper(elf_file,map_file) # parse input and write to output - main(i) + main(input_crash_log,elfhelper) + + #close all files + elf_file.close() + map_file.close() + input_crash_log.close()