sdk-hwV1.3/lichee/melis-v3.0/source/tools/python/backtrace_parser.py

258 lines
8.6 KiB
Python
Raw Normal View History

2024-05-07 10:09:20 +00:00
#!/usr/bin/env python
#coding:utf-8
#Copyright (C) 2015-2018 Alibaba Group Holding Limited
#The file is from Alios-Things, which is licensed under Apache License 2.0
#Modified:
# 2020-06-01 Zeng Zhijin support riscv
import os
import sys
import subprocess
import argparse
import re
import logging
import operator
#--------------------------------------------------------------
# Global defines
#--------------------------------------------------------------
_TOOLCHAIN_NM_OPT_ = "-nlCS"
_TOOLCHAIN_SIZE_OPT_ = "-Axt"
_TOOLCHAIN_OBJDUMP_OPT_ = "-D"
_TOOLCHAIN_ADDR2LINE_OPT_ = "-pfiCe"
_TOOLCHAIN_READELF_OPT_ = "-h"
_TOOLCHAIN_PREFIX_ = ""
_TOOLCHAIN_GCC_ = ""
_TOOLCHAIN_NM_ = ""
_TOOLCHAIN_SIZE_ = ""
_TOOLCHAIN_OBJDUMP_ = ""
_TOOLCHAIN_ADDR2LINE_ = ""
_TOOLCHAIN_READELF_ = ""
_ARM_TOOLCHAIN_PREFIX_ = "arm-melis-eabi-"
_ARM_TOOLCHAIN_GCC_ = "arm-melis-eabi-gcc"
_ARM_TOOLCHAIN_NM_ = "arm-melis-eabi-nm"
_ARM_TOOLCHAIN_SIZE_ = "arm-melis-eabi-size"
_ARM_TOOLCHAIN_OBJDUMP_ = "arm-melis-eabi-objdump"
_ARM_TOOLCHAIN_ADDR2LINE_ = "arm-melis-eabi-addr2line"
_ARM_TOOLCHAIN_READELF_ = "arm-melis-eabi-readelf"
_RISCV_TOOLCHAIN_PREFIX_ = "riscv64-unknown-elf-"
_RISCV_TOOLCHAIN_GCC_ = "riscv64-unknown-elf-gcc"
_RISCV_TOOLCHAIN_NM_ = "riscv64-unknown-elf-nm"
_RISCV_TOOLCHAIN_SIZE_ = "riscv64-unknown-elf-size"
_RISCV_TOOLCHAIN_OBJDUMP_ = "riscv64-unknown-elf-objdump"
_RISCV_TOOLCHAIN_ADDR2LINE_ = "riscv64-unknown-elf-addr2line"
_RISCV_TOOLCHAIN_READELF_ = "riscv64-unknown-elf-readelf"
_HOST_READELF_ = "readelf"
_HOST_READELF_OPT_ = "-h"
_CRASH_LOG_ = "crash_log"
MATCH_ADDR = re.compile(r'0x[0-9a-f]{1,8}', re.IGNORECASE)
_ARCH_TYPE_ARM_ = "ARM"
_ARCH_TYPE_RISCV_ = "RISC-V"
_ARCH_TYPE_RISCV_ID_ = "0xf3"
g_arch = [_ARCH_TYPE_ARM_, _ARCH_TYPE_RISCV_, _ARCH_TYPE_RISCV_ID_]
def get_arch_from_elf(elf_file):
if not elf_file:
return ""
arch_info = subprocess.check_output(
[_HOST_READELF_, _HOST_READELF_OPT_, elf_file])
for line in arch_info.splitlines():
if 'Machine' in line:
temp = line.split()
for arch in g_arch:
if arch in temp:
return arch
for line in arch_info.splitlines():
if "系统架构" in line:
temp = line.split()
for arch in g_arch:
if arch in temp:
return arch
return ""
class Core_Dump(object):
def __init__(self, crash_log, elf_file, toolchain_path):
super(Core_Dump, self).__init__()
self.crash_log = crash_log
self.elf_file = elf_file.name
self.toolchain_path = toolchain_path
self.parse_addr_list = []
self.arch = _ARCH_TYPE_ARM_
self.check_env()
self.global_list = self.get_filelist('./', [])
def get_filelist(self, dir, Filelist):
newDir = dir
if os.path.isfile(dir):
if os.path.splitext(dir)[1] == '.elf':
Filelist.append(dir)
elif os.path.isdir(dir):
for s in os.listdir(dir):
newDir=os.path.join(dir,s)
self.get_filelist(newDir, Filelist)
return Filelist
def getTargetFileName(self, list, pc_addr, try_list):
for e in list:
arch_info = subprocess.check_output(
[_TOOLCHAIN_READELF_, _TOOLCHAIN_READELF_OPT_ , e])
for line in arch_info.splitlines():
if 'Entry' in line:
entry_line=line.split(":", 1)[1]
entry=entry_line.strip()
if cmp(entry.lower()[2:5], pc_addr.lower()[2:5]):
if cmp(entry.lower()[2:4], "40") or cmp(pc_addr.lower()[2:4], "40"):
continue
else:
try_list.append(e)
else:
try_list.append(e)
for line in arch_info.splitlines():
if "入口" in line:
entry_line=line.split("", 1)[1]
entry=entry_line.strip()
if cmp(entry.lower()[2:5], pc_addr.lower()[2:5]):
if cmp(entry.lower()[2:4], "40") or cmp(pc_addr.lower()[2:4], "40"):
continue
else:
try_list.append(e)
else:
try_list.append(e)
list_len=len(list)
trylist_len=len(try_list)
if list_len == 1 and trylist_len == 0:
try_list.append(e)
return try_list
def find_pc_addr(self, pc_addr):
list = self.global_list
elf = self.getTargetFileName(list, pc_addr, [])
i=0
list_len=len(elf)
err_num=0
for e in elf:
try:
pc_trans = subprocess.check_output([_TOOLCHAIN_ADDR2LINE_, _TOOLCHAIN_ADDR2LINE_OPT_, e, pc_addr])
except Exception as err:
logging.exception(err)
else:
if not "?? ??:0" in pc_trans:
if i==0:
print pc_trans.strip()
elif i==list_len:
print(" or "+pc_trans.strip())
else:
print(" or "+pc_trans.strip())
else:
err_num+=1
i+=1
if (err_num == list_len) and (err_num != 0):
print "addr invalid"
print ""
def get_value_form_line(self, line, index):
val_list = re.findall(MATCH_ADDR, line)
if val_list:
if index > len(val_list):
return ""
return val_list[index]
else:
return ""
def parse_addr(self, line, index):
addr = self.get_value_form_line(line, index)
if addr:
self.parse_addr_list.append(addr)
self.find_pc_addr(addr)
def check_env(self):
global _TOOLCHAIN_GCC_
global _TOOLCHAIN_ADDR2LINE_
if sys.version_info.major > 2:
error = """
This parser tools do not support Python Version 3 and above.
Python {py_version} detected.
""".format(py_version=sys.version_info)
print error
sys.exit(1)
def show(self):
log_lines = iter(self.crash_log.read().splitlines())
for line in log_lines:
if "backtrace" in line:
self.parse_addr(line, 0)
else:
pass
def main():
global _TOOLCHAIN_PREFIX_
global _TOOLCHAIN_GCC_
global _TOOLCHAIN_NM_
global _TOOLCHAIN_SIZE_
global _TOOLCHAIN_OBJDUMP_
global _TOOLCHAIN_ADDR2LINE_
global _TOOLCHAIN_READELF_
parser = argparse.ArgumentParser(description='Melis crash log core dump')
# specify arguments
parser.add_argument(metavar='CRASH LOG', type=argparse.FileType('rb', 0),
dest='crash_log', help='path to backtrace log file')
parser.add_argument(metavar='ELF FILE', type=argparse.FileType('rb', 0),
dest='elf_file', help='elf file of application')
parser.add_argument('-p','--path', help="absolute path of toolchain", default='')
args = parser.parse_args()
arch = get_arch_from_elf(args.elf_file.name)
if (arch == _ARCH_TYPE_RISCV_) or (arch == _ARCH_TYPE_RISCV_ID_):
_TOOLCHAIN_PREFIX_ = _RISCV_TOOLCHAIN_PREFIX_
_TOOLCHAIN_GCC_ = _RISCV_TOOLCHAIN_GCC_
_TOOLCHAIN_NM_ = _RISCV_TOOLCHAIN_NM_
_TOOLCHAIN_SIZE_ = _RISCV_TOOLCHAIN_SIZE_
_TOOLCHAIN_OBJDUMP_ = _RISCV_TOOLCHAIN_OBJDUMP_
_TOOLCHAIN_ADDR2LINE_ = _RISCV_TOOLCHAIN_ADDR2LINE_
_TOOLCHAIN_READELF_ = _RISCV_TOOLCHAIN_READELF_
else:
_TOOLCHAIN_PREFIX_ = _ARM_TOOLCHAIN_PREFIX_
_TOOLCHAIN_GCC_ = _ARM_TOOLCHAIN_GCC_
_TOOLCHAIN_NM_ = _ARM_TOOLCHAIN_NM_
_TOOLCHAIN_SIZE_ = _ARM_TOOLCHAIN_SIZE_
_TOOLCHAIN_OBJDUMP_ = _ARM_TOOLCHAIN_OBJDUMP_
_TOOLCHAIN_ADDR2LINE_ = _ARM_TOOLCHAIN_ADDR2LINE_
_TOOLCHAIN_READELF_ = _ARM_TOOLCHAIN_READELF_
core_dump_ins = Core_Dump(args.crash_log, args.elf_file, args.path)
core_dump_ins.show()
if args.crash_log:
args.crash_log.close()
if args.elf_file:
args.elf_file.close()
if __name__ == "__main__":
main()