LPT26x-HSF-4MB-Hilink_14.2..../build/script/image_analysis/common_utils.py
2025-05-13 22:00:58 +08:00

147 lines
5.1 KiB
Python
Executable File

#!/usr/bin/env python3
# coding=utf-8
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2021-2022. All rights reserved.
from os import listdir
from os.path import isdir, exists
import re
import subprocess
import sys
ELF_SYMBOL_RULE = r'^[0-9a-zA-Z]{8}'
class CommonUtils:
symbol_key_arr = []
symbol_data = {}
@staticmethod
def get_prefix(path):
data = {
'prefix': '',
'environment': ''
}
if not exists(path) or not isdir(path):
print(f'compiler path not find or not a directory: {path}')
raise FileExistsError()
cp_files = listdir(path)
objdump_win_sign = '-objdump.exe'
objdump_linux_sign = '-objdump'
has_compiler = False
for file_name in cp_files:
if file_name.endswith(objdump_win_sign):
data['prefix'] = file_name[0: file_name.rindex(objdump_win_sign)]
data['environment'] = 'windows'
has_compiler = True
break
elif file_name.endswith(objdump_linux_sign):
data['prefix'] = file_name[0: file_name.rindex(objdump_linux_sign)]
data['environment'] = 'linux'
has_compiler = True
break
if not has_compiler:
print(f'Incorrect compiler path: {path}')
raise Exception()
return data
@staticmethod
def check_elf_file(file_path):
with open(file_path, 'rb') as f:
elf_ident = f.read(16)
elf_str = ''
for i in elf_ident:
elf_str += hex(i)[2:]
return elf_str.find('7f454c46') >= 0
@staticmethod
def get_obj_dump_info(obj_dump_path, arg, elf_file_path, is_return_arr=True, is_convert=True):
result = []
if not exists(obj_dump_path):
return result
cmd = [obj_dump_path, arg, elf_file_path]
data = CommonUtils.exec_cmd(cmd, is_convert)
if data:
if is_return_arr:
result = data.strip().split('\n')
else:
result.append(data)
return result
@staticmethod
def exec_cmd(cmd, is_convert=True):
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, _ = p.communicate(timeout=120)
if is_convert:
out = out.decode()
return out
except subprocess.TimeoutExpired as e:
print('cmd timeouot')
raise SystemError() from e
except SystemError as e:
print('cmd error')
raise SystemError() from e
@staticmethod
def get_symbol_data(obj_dump_path='', elf_file_path=''):
if not obj_dump_path or not exists(obj_dump_path):
raise FileExistsError(f'objdump path not find: {obj_dump_path}')
if not elf_file_path or not exists(elf_file_path):
raise FileExistsError(f'elf path not find: {elf_file_path}')
CommonUtils.symbol_data = {}
CommonUtils.symbol_key_arr = []
res = CommonUtils.get_obj_dump_info(obj_dump_path, '-t', elf_file_path)
for item in res:
line = re.sub(r'\s+', ' ', item)
if re.search(ELF_SYMBOL_RULE, line):
data_arr = line.split(' ')
section_name = data_arr[3]
symbol_name = data_arr[-1]
type_name = data_arr[2]
if section_name != symbol_name and type_name == 'F':
CommonUtils.symbol_data[data_arr[0]] = symbol_name
for keys in CommonUtils.symbol_data.keys():
hex_str = '0x' + keys
CommonUtils.symbol_key_arr.append(int(hex_str, 16))
if len(CommonUtils.symbol_key_arr) == 0:
return
CommonUtils.symbol_key_arr.sort(reverse=True)
@staticmethod
def get_function_name(num):
index = 0
d_value = sys.maxsize
if num.find('0x') < 0:
num = '0x' + num
for i, symbol_key_val in enumerate(CommonUtils.symbol_key_arr):
new_value = int(num, 16) - symbol_key_val
if d_value >= new_value >= 0:
if new_value == d_value and symbol_key_val < CommonUtils.symbol_key_arr[index]:
continue
index = i
d_value = new_value
break
if CommonUtils.symbol_key_arr[index]:
addr = hex(CommonUtils.symbol_key_arr[index])
return {
'funcname': CommonUtils.symbol_data['%08x' % int(addr, 16)],
'funcaddr': '0x%08x' % int(addr, 16)
}
return {
'funcname': '',
'funcaddr': ''
}
@staticmethod
def read_uint16_le(data, offset=0):
return int.from_bytes(data[offset:offset + 2][::-1], byteorder='big')
@staticmethod
def read_uint32_le(data, offset=0):
return int.from_bytes(data[offset:offset + 4][::-1], byteorder='big')