mirror of https://github.com/ARMmbed/mbed-os.git
Fix code style issues and update documentation
parent
8967b52bfb
commit
3340a020ed
|
@ -4,7 +4,9 @@ This post-processing tool can be used to parse crash log generated by Mbed-OS wh
|
|||
## Capturing crash log
|
||||
When an exception happens Mbed-OS will print out the crash information to STDOUT.
|
||||
The crash information contains register context at the time exception and current threads in the system.
|
||||
The information printed out to STDOUT will be similar to below.
|
||||
The information printed out to STDOUT will be similar to below. Registers captured depends on specific
|
||||
Cortex-M core you are using. For example, if your target is using Cortex-M0, some registers like
|
||||
MMFSR, BFSR, UFSR may not be available and will not appear in the crash log.
|
||||
|
||||
++ MbedOS Fault Handler ++
|
||||
|
||||
|
@ -57,9 +59,9 @@ To generate more information copy and save this crash information to a text file
|
|||
NOTE: Make sure you copy the section with text "MbedOS Fault Handler" as the this tool looks for that header.
|
||||
|
||||
## Running the Crash Log Parser
|
||||
crash_log_parser.py -i <Path to Crash log> -e <Path to Elf/Axf file of the build> -m <Path to Map file of the build>
|
||||
crash_log_parser.py <Path to Crash log> <Path to Elf/Axf file of the build> <Path to Map file of the build>
|
||||
For example:
|
||||
crashlogparse.py -i crash.log -e C:\MyProject\BUILD\k64f\arm\mbed-os-hf-handler.elf -m C:\MyProject\BUILD\k64f\arm\mbed-os-hf-handler.map
|
||||
crashlogparse.py crash.log C:\MyProject\BUILD\k64f\arm\mbed-os-hf-handler.elf C:\MyProject\BUILD\k64f\arm\mbed-os-hf-handler.map
|
||||
|
||||
An example output from running crash_log_parser is shown below.
|
||||
|
||||
|
|
|
@ -31,12 +31,12 @@ _OPT = "-nlC"
|
|||
_PTN = re.compile("([0-9a-f]*) ([Tt]) ([^\t\n]*)(?:\t(.*):([0-9]*))?")
|
||||
|
||||
class ElfHelper(object):
|
||||
def __init__(self, elf_file,map_file):
|
||||
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.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):
|
||||
return self.addrs
|
||||
|
@ -47,85 +47,76 @@ class ElfHelper(object):
|
|||
return funcname
|
||||
|
||||
def print_HFSR_info(hfsr):
|
||||
if(hfsr != 0):
|
||||
if( int(hfsr,16) & 0x80000000 ):
|
||||
print("\t\tDebug Event Occured")
|
||||
if( int(hfsr,16) & 0x40000000 ):
|
||||
print("\t\tForced exception, a fault with configurable priority has been escalated to HardFault")
|
||||
if( int(hfsr,16) & 0x2 ):
|
||||
print("\t\tVector table read fault has occurred")
|
||||
if int(hfsr, 16) & 0x80000000:
|
||||
print("\t\tDebug Event Occured")
|
||||
if int(hfsr, 16) & 0x40000000:
|
||||
print("\t\tForced exception, a fault with configurable priority has been escalated to HardFault")
|
||||
if int(hfsr, 16) & 0x2:
|
||||
print("\t\tVector table read fault has occurred")
|
||||
|
||||
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")
|
||||
if( int(mmfsr,16) & 0x10 ):
|
||||
print("\t\tA derived MemManage fault occurred on exception entry")
|
||||
if( int(mmfsr,16) & 0x8 ):
|
||||
print("\t\tA derived MemManage fault occurred on exception return")
|
||||
if( int(mmfsr,16) & 0x2 ):
|
||||
if( int(mmfsr,16) & 0x80 ):
|
||||
print("\t\tData access violation. Faulting address: %s"%(str(mmfar)))
|
||||
else:
|
||||
print("\t\tData access violation. WARNING: Fault address in MMFAR is NOT valid")
|
||||
if( int(mmfsr,16) & 0x1 ):
|
||||
print("\t\tMPU or Execute Never (XN) default memory map access violation on an instruction fetch has occurred")
|
||||
def print_MMFSR_info(mmfsr, mmfar):
|
||||
if int(mmfsr, 16) & 0x20:
|
||||
print("\t\tA MemManage fault occurred during FP lazy state preservation")
|
||||
if int(mmfsr, 16) & 0x10:
|
||||
print("\t\tA derived MemManage fault occurred on exception entry")
|
||||
if int(mmfsr, 16) & 0x8:
|
||||
print("\t\tA derived MemManage fault occurred on exception return")
|
||||
if int(mmfsr, 16) & 0x2:
|
||||
if int(mmfsr, 16) & 0x80:
|
||||
print("\t\tData access violation. Faulting address: %s"%(str(mmfar)))
|
||||
else:
|
||||
print("\t\tData access violation. WARNING: Fault address in MMFAR is NOT valid")
|
||||
if int(mmfsr, 16) & 0x1:
|
||||
print("\t\tMPU or Execute Never (XN) default memory map access violation on an instruction fetch has occurred")
|
||||
|
||||
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")
|
||||
if( int(bfsr,16) & 0x10 ):
|
||||
print("\t\tA derived bus fault has occurred on exception entry")
|
||||
if( int(bfsr,16) & 0x8 ):
|
||||
print("\t\tA derived bus fault has occurred on exception return")
|
||||
if( int(bfsr,16) & 0x4 ):
|
||||
print("\t\tImprecise data access error has occurred")
|
||||
if( int(bfsr,16) & 0x2 ):
|
||||
if( int(bfsr,16) & 0x80 ):
|
||||
print("\t\tA precise data access error has occurred. Faulting address: %s"%(str(bfar)))
|
||||
else:
|
||||
print("\t\tA precise data access error has occurred. WARNING: Fault address in BFAR is NOT valid")
|
||||
if( int(bfsr,16) & 0x1 ):
|
||||
print("\t\tA bus fault on an instruction prefetch has occurred")
|
||||
def print_BFSR_info(bfsr, bfar):
|
||||
if int(bfsr, 16) & 0x20:
|
||||
print("\t\tA bus fault occurred during FP lazy state preservation")
|
||||
if int(bfsr, 16) & 0x10:
|
||||
print("\t\tA derived bus fault has occurred on exception entry")
|
||||
if int(bfsr, 16) & 0x8:
|
||||
print("\t\tA derived bus fault has occurred on exception return")
|
||||
if int(bfsr, 16) & 0x4:
|
||||
print("\t\tImprecise data access error has occurred")
|
||||
if int(bfsr, 16) & 0x2:
|
||||
if int(bfsr,16) & 0x80:
|
||||
print("\t\tA precise data access error has occurred. Faulting address: %s"%(str(bfar)))
|
||||
else:
|
||||
print("\t\tA precise data access error has occurred. WARNING: Fault address in BFAR is NOT valid")
|
||||
if int(bfsr, 16) & 0x1:
|
||||
print("\t\tA bus fault on an instruction prefetch has occurred")
|
||||
|
||||
def print_UFSR_info(ufsr):
|
||||
if(ufsr != 0):
|
||||
if( int(ufsr,16) & 0x200 ):
|
||||
print("\t\tDivide by zero error has occurred")
|
||||
if( int(ufsr,16) & 0x100 ):
|
||||
print("\t\tUnaligned access error has occurred")
|
||||
if( int(ufsr,16) & 0x8 ):
|
||||
print("\t\tA coprocessor access error has occurred. This shows that the coprocessor is disabled or not present")
|
||||
if( int(ufsr,16) & 0x4 ):
|
||||
print("\t\tAn integrity check error has occurred on EXC_RETURN")
|
||||
if( int(ufsr,16) & 0x2 ):
|
||||
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 )")
|
||||
if( int(ufsr,16) & 0x1 ):
|
||||
print("\t\tThe processor has attempted to execute an undefined instruction")
|
||||
if int(ufsr, 16) & 0x200:
|
||||
print("\t\tDivide by zero error has occurred")
|
||||
if int(ufsr, 16) & 0x100:
|
||||
print("\t\tUnaligned access error has occurred")
|
||||
if int(ufsr, 16) & 0x8:
|
||||
print("\t\tA coprocessor access error has occurred. This shows that the coprocessor is disabled or not present")
|
||||
if int(ufsr, 16) & 0x4:
|
||||
print("\t\tAn integrity check error has occurred on EXC_RETURN")
|
||||
if int(ufsr, 16) & 0x2:
|
||||
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 )")
|
||||
if int(ufsr, 16) & 0x1:
|
||||
print("\t\tThe processor has attempted to execute an undefined instruction")
|
||||
|
||||
def print_CPUID_info(cpuid):
|
||||
if( ( ( int(cpuid,16) & 0xF0000 ) >> 16 ) == 0xC ):
|
||||
if (int(cpuid, 16) & 0xF0000) == 0xC0000:
|
||||
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 )))
|
||||
print("\t\tProcessor Variant: %X" % ((int(cpuid,16) & 0xFFF0 ) >> 4))
|
||||
|
||||
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
|
||||
_, register_val = line.split(":")
|
||||
return register_val.strip()
|
||||
|
||||
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
|
||||
def main(crash_log, elfhelper):
|
||||
mmfar_val = 0
|
||||
bfar_val = 0
|
||||
lines = iter(crash_log.readlines())
|
||||
|
||||
lines = crash_log.readlines()
|
||||
|
||||
cnt = 0
|
||||
for eachline in lines:
|
||||
if "++ MbedOS Fault Handler ++" in eachline:
|
||||
break
|
||||
|
@ -134,51 +125,51 @@ def main(crash_log,elfhelper):
|
|||
return
|
||||
|
||||
for eachline in lines:
|
||||
if("-- MbedOS Fault Handler --" in eachline):
|
||||
if "-- MbedOS Fault Handler --" in eachline:
|
||||
break
|
||||
|
||||
elif(eachline.startswith("PC")):
|
||||
elif eachline.startswith("PC"):
|
||||
pc_val = parse_line_for_register(eachline)
|
||||
pc_name = elfhelper.function_name_for_addr(int(pc_val,16))
|
||||
pc_name = elfhelper.function_name_for_addr(int(pc_val, 16))
|
||||
|
||||
elif(eachline.startswith("LR")):
|
||||
elif eachline.startswith("LR"):
|
||||
lr_val = parse_line_for_register(eachline)
|
||||
lr_name = elfhelper.function_name_for_addr(int(lr_val,16))
|
||||
lr_name = elfhelper.function_name_for_addr(int(lr_val, 16))
|
||||
|
||||
elif(eachline.startswith("SP")):
|
||||
elif eachline.startswith("SP"):
|
||||
sp_val = parse_line_for_register(eachline)
|
||||
|
||||
elif(eachline.startswith("HFSR")):
|
||||
elif eachline.startswith("HFSR"):
|
||||
hfsr_val = parse_line_for_register(eachline)
|
||||
|
||||
elif(eachline.startswith("MMFSR")):
|
||||
elif eachline.startswith("MMFSR"):
|
||||
mmfsr_val = parse_line_for_register(eachline)
|
||||
|
||||
elif(eachline.startswith("BFSR")):
|
||||
elif eachline.startswith("BFSR"):
|
||||
bfsr_val = parse_line_for_register(eachline)
|
||||
|
||||
elif(eachline.startswith("UFSR")):
|
||||
elif eachline.startswith("UFSR"):
|
||||
ufsr_val = parse_line_for_register(eachline)
|
||||
|
||||
elif(eachline.startswith("CPUID")):
|
||||
elif eachline.startswith("CPUID"):
|
||||
cpuid_val = parse_line_for_register(eachline)
|
||||
|
||||
elif(eachline.startswith("MMFAR")):
|
||||
elif eachline.startswith("MMFAR"):
|
||||
mmfar_val = parse_line_for_register(eachline)
|
||||
|
||||
elif(eachline.startswith("BFAR")):
|
||||
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("\nCrash Info:")
|
||||
print("\tCrash location = %s [0x%s] (based on PC value)" % (pc_name.strip(), str(pc_val)))
|
||||
print("\tCaller location = %s [0x%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 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_MMFSR_info(mmfsr_val, mmfar_val)
|
||||
print_BFSR_info(bfsr_val, bfar_val)
|
||||
print_UFSR_info(ufsr_val)
|
||||
|
||||
|
||||
|
@ -187,35 +178,23 @@ if __name__ == '__main__':
|
|||
|
||||
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='<path to input file with crash log output>', type=argparse.FileType('rb', 0), required=True,
|
||||
help='path to input file')
|
||||
parser.add_argument('-e','--elfpath', metavar='<module or elf file path>', type=argparse.FileType('rb', 0), required=True,
|
||||
help='path to elf file')
|
||||
parser.add_argument('-m','--mappath', metavar='<map file path>', type=argparse.FileType('rb', 0), required=True,
|
||||
help='path to map file')
|
||||
parser.add_argument(metavar='CRASH LOG', type=argparse.FileType('rb', 0),
|
||||
dest='crashlog',help='path to crash log file')
|
||||
parser.add_argument(metavar='ELF FILE', type=argparse.FileType('rb', 0),
|
||||
dest='elffile',help='path to elf file')
|
||||
parser.add_argument(metavar='MAP FILE', type=argparse.FileType('rb', 0),
|
||||
dest='mapfile',help='path to map file')
|
||||
|
||||
# get and validate arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
elf_file = args.elfpath
|
||||
map_file = args.mappath
|
||||
input_crash_log = args.input
|
||||
|
||||
print("Inputs:")
|
||||
print("\tCrash Log: %s"%(input_crash_log.name))
|
||||
print("\tElf Path: %s"%(elf_file.name))
|
||||
print("\tMap Path: %s"%(map_file.name))
|
||||
|
||||
elfhelper = ElfHelper(elf_file,map_file)
|
||||
elfhelper = ElfHelper(args.elffile, args.mapfile)
|
||||
|
||||
# parse input and write to output
|
||||
main(input_crash_log,elfhelper)
|
||||
main(args.crashlog, elfhelper)
|
||||
|
||||
#close all files
|
||||
elf_file.close()
|
||||
map_file.close()
|
||||
input_crash_log.close()
|
||||
|
||||
|
||||
|
||||
args.elffile.close()
|
||||
args.mapfile.close()
|
||||
args.crashlog.close()
|
||||
|
||||
|
|
Loading…
Reference in New Issue