crash_log_parser review comment fixes

pull/5847/head
Senthil Ramakrishnan 2018-01-29 14:54:30 -06:00
parent 96d900c99f
commit 8967b52bfb
1 changed files with 75 additions and 132 deletions

View File

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