把你说的修改进我的代码再把完整代码给我:
import os
import subprocess
import sys
import time
import re
def curFilePath():
"""返回项目根目录 D:\Beta_Interpreter\online_test"""
if hasattr(sys, 'frozen'):
return os.path.dirname(sys.executable)
else:
return os.path.dirname(os.path.dirname(__file__))
def getRelPath(relStr):
return os.path.abspath(os.path.join(curFilePath(), relStr))
g_logLevel = ['INVALID', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']
# g_logLevel 是一个列表,定义了日志的级别。g_logModule 是一个字典,将模块的十六进制编号映射到模块名称
g_logModule = {
0x00 : 'HIVIEW',
0x01 : 'SAMGR',
0x02 : 'UPDATE',
0x03 : 'ACE',
0x04 : 'APP',
0x05 : 'AAFWK',
0x06 : 'GRAPHIC',
0x07 : 'MEDIA',
0x08 : 'DMA',
0x09 : 'SEN',
0x0A : 'SCY',
0x0B : 'XTS',
0x0C : 'SOFTBUS',
0x0D : 'PWM',
0x0E : 'UIKIT',
0x0F : 'GLOBAL',
0x10 : 'DATAMGR',
0x1E : 'HISI',
0x1F : 'COMMU',
0x20 : 'NV',
0x21 : 'BSP',
0x22 : 'DM',
0x23 : 'PM',
0x24 : 'LCD',
0x25 : 'GPS',
0x26 : 'BT',
0x27 : 'NFC',
0x28 : 'SVRAUDIO',
0x29 : 'FTM',
0x2A : 'SVR',
0x2B : 'APPUI',
0x2C : 'AST',
0x2D : 'FIT',
0x2E : 'ALG',
0x2F : 'HRM',
0x30 : 'TLV',
0x31 : 'WIFI',
0x32 : 'INPUT',
0x33 : 'RFID',
0x34 : 'EARSDK',
0x35 : 'SVCOMMU',
0x36 : 'RSMC',
0x37 : 'UWB',
0x38 : 'WATCHEAR',
0x39 : 'PAIR',
0x3A : 'DRVAUDIO',
0x3B : 'BRIGHT',
0x3C : 'FITUI',
0x3D : 'DIALUI',
0x3E : 'FMKUI',
0x3F : 'HRMUI' }
class BIN_INFO():
# 该类用于存储二进制文件的相关信息,包括起始地址、结束地址、二进制内容、文件路径、内容字典和标志。
def __init__(self, flag):
self.start_address = 0
self.end_address = 0
self.bin_content = []
self.bin_path = ""
self.bin_dict = {}
self.flag = flag
class LogProcessThread():
# 该类用于处理日志文件,初始化时接收日志文件和各种二进制文件信息。
def __init__(self, log_file, gpu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info):
self.log_file = log_file
self.gpu_info = gpu_info
self.rom_info = rom_info
self.xip_info = xip_info
self.itcm_info = itcm_info
self.sram_info = sram_info
self.reverse1_info = reverse1_info
self.reverse2_info = reverse2_info
def find_address_by_bin(self, logStr, key_index, num_list, bin_files_dict):
# 该方法用于在二进制文件中查找地址对应的字符串,并替换日志字符串中的 % s占位符。
s_list = []
for i in range(len(logStr)):
if logStr[i] == "%" and i != len(logStr) - 1:
s_list.append(logStr[i: i + 2])
for i in range(len(s_list)):
if s_list[i] == "%s":
for j in key_index:
if num_list[i] > j:
address = num_list[i] - j
new_s = ""
if (bin_files_dict.get(j).bin_dict.__contains__(address) == False):
new_s = str(bin_files_dict.get(j).bin_content[address:-1]).split('\\x00', 1)[0]
new_s = new_s[2: len(new_s)]
if isText(logStr):
new_s = new_s.replace('\r', '')
new_s = new_s.replace('\n', '')
new_s = new_s.replace('{public}', '')
new_s = new_s.replace('{private}', '')
new_s = new_s.replace('%ll', '%')
new_s = new_s.replace('%p', '%x')
bin_files_dict.get(j).bin_dict[address] = new_s
else:
new_s = 'NULL'
else:
new_s = bin_files_dict.get(j).bin_dict[address]
num_list[i] = new_s
break
return num_list
def return_format_str(self, logStr, logContent, logContentIndex, num):
# 该方法用于从日志内容中提取格式化字符串的参数。
num_list = []
index = logStr.find('%', 0, len(logStr))
temp_num = 0
while (index >= 0) or (temp_num < num):
startLogIndex = logContentIndex + 12 + temp_num * 4
endLogIndex = logContentIndex + 12 + (temp_num + 1) * 4
if "%d" in logStr[index:index + 2]:
logArgOne = int.from_bytes(logContent[startLogIndex:endLogIndex], "little", signed=True)
num_list.append(logArgOne)
else:
logArgOne = int.from_bytes(logContent[startLogIndex:endLogIndex], "little", signed=False)
num_list.append(logArgOne)
index = logStr.find('%', index + 1, len(logStr))
temp_num += 1
return num_list
def start_parse_v1r6(self):
# 该方法是核心的日志解析方法,从日志文件中读取内容,检查日志的头部信息、级别、模块和参数数量,提取日志字符串和参数,格式化日志信息并写入结果文件。
with open(self.log_file, 'rb') as logFile:
#logFile = open(self.log_file, 'rb')
logFileSize = os.path.getsize(self.log_file)
logFile.seek(0, 0)
logContent = logFile.read(logFileSize)
list1 = [self.gpu_info, self.rom_info, self.xip_info, self.itcm_info, self.sram_info, self.reverse1_info, self.reverse2_info]
bin_files_dict = {}
for i in list1:
if i.start_address != 4294967295 and i.start_address != 0:
bin_files_dict[i.start_address] = i
key_index = sorted(bin_files_dict.keys(), reverse=True)
logResultFile = open(logFileArg + '_offline.txt', 'w', encoding='utf8', errors='ignore')
logContentIndex = self.find_head_index(logContent, 0)
while logContentIndex <= logFileSize - 12:
if logContent[logContentIndex] == 0xED:
# check the log level is in range or not
logLevel = logContent[logContentIndex + 1]
if (logLevel & 0x7F) >= 0x06:
logContentIndex = self.find_head_index(logContent, logContentIndex + 1)
continue
# check the log module is in range or not
logModule = logContent[logContentIndex + 2]
# if g_logModule.__contains__(logModule) == False:
# logContentIndex = logContentIndex + 1
# continue
# check the log arguments is larger than 6 or not
logArgNum = logContent[logContentIndex + 3]
if logArgNum > 6:
logContentIndex = self.find_head_index(logContent, logContentIndex)
continue
logTime = int.from_bytes(logContent[logContentIndex + 4: logContentIndex + 8], "little")
logAddress = int.from_bytes(logContent[logContentIndex + 8: logContentIndex + 12], "little")
logStr = 'NULL'
if logLevel < 0x06:
for i in key_index:
if logAddress > i:
address = logAddress - i
if (bin_files_dict.get(i).bin_dict.__contains__(address) == False):
logStr = str(bin_files_dict.get(i).bin_content[address:-1]).split('\\x00', 1)[0]
logStr = logStr[2: len(logStr)]
if isText(logStr):
logStr = logStr.replace('\\r', '')
logStr = logStr.replace('\\n', '')
logStr = logStr.replace('{public}', '')
logStr = logStr.replace('{private}', '')
logStr = logStr.replace('%ll', '%')
logStr = logStr.replace('%p', '%x')
bin_files_dict.get(i).bin_dict[address] = logStr
else:
logStr = 'NULL'
else:
logStr = bin_files_dict.get(i).bin_dict[address]
break
if (logArgNum == 1) and (logStr.count('%') >= 1):
num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum)
if logStr.find('%s') != -1:
num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict)
try:
logStr = logStr % (num_list[0])
except:
logStr = "{str},{para1}".format(str=logStr,
para1=num_list[0])
elif (logArgNum == 2) and (logStr.count('%') >= 2):
num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum)
if logStr.find('%s') != -1:
num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict)
try:
logStr = logStr % (num_list[0], num_list[1])
except:
logStr = "{str},{para1},{para2}".format(str=logStr,
para1=num_list[0],
para2=num_list[1])
elif (logArgNum == 3) and (logStr.count('%') >= 3):
num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum)
if logStr.find('%s') != -1:
num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict)
try:
logStr = logStr % (num_list[0], num_list[1], num_list[2])
except:
logStr = "{str},{para1},{para2},{para3}".format(str=logStr,
para1=num_list[0],
para2=num_list[1],
para3=num_list[2])
elif (logArgNum == 4) and (logStr.count('%') >= 4):
num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum)
if logStr.find('%s') != -1:
num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict)
try:
logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3])
except:
logStr = "{str},{para1},{para2},{para3},{para4}".format(str=logStr,
para1=num_list[0],
para2=num_list[1],
para3=num_list[2],
para4=num_list[3])
elif (logArgNum == 5) and (logStr.count('%') >= 5):
num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum)
if logStr.find('%s') != -1:
num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict)
try:
logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3], num_list[4])
except:
logStr = "{str},{para1},{para2},{para3},{para4},{para5}".format(str=logStr,
para1=num_list[0],
para2=num_list[1],
para3=num_list[2],
para4=num_list[3],
para5=num_list[4])
elif (logArgNum == 6) and (logStr.count('%') >= 6):
num_list = self.return_format_str(logStr, logContent, logContentIndex, logArgNum)
if logStr.find('%s') != -1:
num_list = self.find_address_by_bin(logStr, key_index, num_list, bin_files_dict)
try:
logStr = logStr % (num_list[0], num_list[1], num_list[2], num_list[3], num_list[4], num_list[5])
except:
logStr = "{str},{para1},{para2},{para3},{para4},{para5},{para6}".format(str=logStr,
para1=num_list[0],
para2=num_list[1],
para3=num_list[2],
para4=num_list[3],
para5=num_list[4],
para6=num_list[5])
log = "{time},{level},{module},{str}\n".format(
time=time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(logTime)),
level=g_logLevel[logLevel & 0x7F],
module=g_logModule[logModule],
str=logStr.replace(r'\t', '\t').replace(r'\'', "'"))
logResultFile.write(log)
logContentIndex = logContentIndex + 12 + logArgNum * 4
else:
logContentIndex = self.find_head_index(logContent, logContentIndex)
logResultFile.close()
print("success")
def find_head_index(self, logContent, index):
# 该方法用于查找日志头部的起始索引。
firstFlag = logContent[index:].find(0xED) + index
if firstFlag == -1:
return -1
ipos = firstFlag
for i in range(4):
varnum = logContent[ipos + 3]
log_len = 4 * varnum + 12
if log_len < 12 or log_len > 36:
return self.find_head_index(logContent, ipos + 1)
ipos += log_len
if ipos >= len(logContent):
return firstFlag
if log_len == 12 and logContent[ipos] == 0 and logContent[ipos + 1] == 0 and logContent[ipos + 2] == 0 and logContent[ipos + 3] == 0:
ipos += 4
if logContent[ipos] != 0xED:
return self.find_head_index(logContent, ipos + 1)
return firstFlag
def isText(s):
# 该函数用于判断字符串是否为文本。
if len(s) == 0:
return False
if not s:
return False
if (s.count('\\x') >= 1):
return False
return True
def indexOfSubstr(logStr):
# 该函数用于查找日志字符串中 % u的索引。
indexList = []
index = 0
for i in range(len(logStr)):
if logStr[i:i+1] == '%':
index = index + 1
para = logStr[i:i+2]
if para == '%u':
indexList.append(index)
return indexList
def GetBinString(binFile, logDict):
with open(binFile, 'rb') as f:
content = f.read()
# 使用正则找到连续的 8 个 ASCII 字符以上的字符串
matches = re.finditer(rb'[\\x20-\\x7E]{8,}', content)
for match in matches:
address = match.start()
text = match.group().decode('ascii', errors='ignore')
text = text.replace('\r', '').replace('\n', '')
text = text.replace('{public}', '').replace('{private}', '')
text = text.replace('%ll', '%')
text = text.replace('%p', '%x')
# text = text.replace(r'\t', '\t').replace(r'\'', "'") # 在这里无效
stringAddress = f"{address:08X}"
logDict[stringAddress] = f"{stringAddress} {text}"
def GetBinFiles(root):
gpu_log_str_bin = ""
mcu_log_str_bin = ""
bin_files = []
for file in os.listdir(root):
path = os.path.join(root, file)
if not os.path.isfile(path): continue
lower_file = file.lower()
if "gpu_log_str.bin" in lower_file:
gpu_log_str_bin = path
elif "mcu_log_str.bin" in lower_file:
mcu_log_str_bin = path
if file.endswith(".bin"):
bin_files.append(path)
return gpu_log_str_bin, mcu_log_str_bin, bin_files
def CheckBinAddr(bin_infos, bin_files):
# 该函数用于检查二进制文件的地址信息是否正确。
for info in bin_infos:
if info.start_address != 4294967295:
flag = True
for i in bin_files:
if info.flag == "application.bin":
if info.flag in i or "OHOS_Image.bin" in i or "factory.bin" in i:
flag = False
info.bin_path = i
elif info.flag in i:
flag = False
info.bin_path = i
if flag:
if info.flag == "application.bin":
errorLog = "error info: need application.bin or OHOS_Image.bin or factory.bin"
else:
errorLog = "error info: need %s" % info.flag
print("{str}".format(str=errorLog))
sys.exit(-1)
def Addr(log_str_bin):
# 该函数用于从二进制文件中获取地址信息。
with open(log_str_bin, mode="rb") as f:
f.seek(0, 0)
binAddr = f.read(32)
strBinAddr = int.from_bytes(binAddr[4:8], "little")
romBinAddr = int.from_bytes(binAddr[8:12], "little")
xipBinAddr = int.from_bytes(binAddr[12:16], "little")
itcmBinAddr = int.from_bytes(binAddr[16:20], "little")
sramBinAddr = int.from_bytes(binAddr[20:24], "little")
reveser1Addr = int.from_bytes(binAddr[24:28], "little")
reveser2Addr = int.from_bytes(binAddr[28:32], "little")
return strBinAddr, romBinAddr, xipBinAddr, itcmBinAddr, sramBinAddr, reveser1Addr, reveser2Addr
def GetBinFilesString(bin_files):
# 该函数用于获取二进制文件的内容和字符串信息。
for file in bin_files:
if file.start_address != 4294967295:
with open(file.bin_path, 'rb') as f:
binFileSize = os.path.getsize(file.bin_path)
f.seek(0, 0)
file.bin_content = f.read(binFileSize)
file.end_address = file.start_address + binFileSize
GetBinString(file.bin_path, file.bin_dict)
# def main(logFileArg1, root1):
# global logFileArg
#
# logFileArg = logFileArg1
# global root
# root = root1
# print(logFileArg)
# # print(root)
# # print("lex111111")
# # os.system("pause")
#
#
#
# gpu_info = BIN_INFO("gpu_log_str.bin")
# mcu_info = BIN_INFO("mcu_log_str.bin")
# rom_info = BIN_INFO("application.bin")
# xip_info = BIN_INFO("xip_code.bin")
# itcm_info = BIN_INFO("itcm_code.bin")
# sram_info = BIN_INFO("sram_code.bin")
# reverse1_info = BIN_INFO("reserve1.bin")
# reverse2_info = BIN_INFO("reserve2.bin")
# print(xip_info)
#
# gpu_info.bin_path, mcu_info.bin_path, bin_files = GetBinFiles(root)
# if logFileArg.endswith("gpu_debug.log"):
# if gpu_info.bin_path == "":
# errorLog = "error info: need gpu_log_str.bin"
# print("{str}".format(str=errorLog))
# sys.exit(-1)
# else:
# gpu_info.start_address, rom_info.start_address, xip_info.start_address, itcm_info.start_address, sram_info.start_address, \
# reverse1_info.start_address, reverse2_info.start_address = GetBinAddr(gpu_info.bin_path)
# bin_infos = [gpu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info]
# CheckBinAddr(bin_infos, bin_files)
# GetBinFilesString(bin_infos)
# logProcessThread = LogProcessThread(log_file=logFileArg,
# gpu_info=gpu_info,
# rom_info=rom_info,
# xip_info=xip_info,
# itcm_info=itcm_info,
# sram_info=sram_info,
# reverse1_info=reverse1_info,
# reverse2_info=reverse2_info, )
# logProcessThread.start_parse_v1r6()
# elif logFileArg.endswith("mcu_debug.log"):
# if mcu_info.bin_path == "":
# errorLog = "error info: need mcu_log_str.bin"
# print("{str}".format(str=errorLog))
# sys.exit(-1)
# else:
# mcu_info.start_address, rom_info.start_address, xip_info.start_address, itcm_info.start_address, sram_info.start_address, \
# reverse1_info.start_address, reverse2_info.start_address = GetBinAddr(mcu_info.bin_path)
# bin_infos = [mcu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info]
# CheckBinAddr(bin_infos, bin_files)
# GetBinFilesString(bin_infos)
# logProcessThread = LogProcessThread(log_file=logFileArg,
# gpu_info=mcu_info,
# rom_info=rom_info,
# xip_info=xip_info,
# itcm_info=itcm_info,
# sram_info=sram_info,
# reverse1_info=reverse1_info,
# reverse2_info=reverse2_info, )
# logProcessThread.start_parse_v1r6()
def main(logFileArg1=None, root1=None):
"""
解析 GPU 日志主函数
:param logFileArg1: WearableBeta_gpu_debug.log 文件路径(可选)
:param root1: bes2720_m33_user 等 bin 文件所在目录(可选)
"""
global logFileArg, root
# === 自动查找 log 文件 ===
if logFileArg1 is None:
temp_dir = getRelPath("temp_extracted")
print(f" 正在搜索日志文件... 路径: {temp_dir}")
found = False
for root_path, dirs, files in os.walk(temp_dir):
for file in files:
if file.endswith("WearableBeta_gpu_debug.log"): # 只要结尾匹配即可
logFileArg1 = os.path.join(root_path, file)
print(f" 找到日志文件: {logFileArg1}")
found = True
break
if found:
break
if not found:
print("❌ 错误:未找到 WearableBeta_gpu_debug.log,请检查 ZIP 是否解压成功")
return
# === 自动查找 bin 目录 ===
if root1 is None:
version_cache = getRelPath("Version_cache")
print(f"正在扫描 Version_cache: {version_cache}")
found = False
for root_path, dirs, files in os.walk(version_cache):
if "bes2720_m33_user" in dirs:
root1 = os.path.join(root_path, "bes2720_m33_user")
print(f"成功定位 bes2720_m33_user: {root1}")
# 新增:列出内容确认是否有 gpu_log_str.bin
try:
bin_files = os.listdir(root1)
print(f"bes2720_m33_user 内容预览:")
for f in sorted(bin_files):
if f.endswith(".bin"):
print(f" - {f}")
except Exception as e:
print(f"无法读取目录: {e}")
found = True
break
if not found:
print("错误:未找到 bes2720_m33_user 文件夹,请检查固件是否下载成功")
return
# === 设置全局变量(原逻辑保持不变)===
logFileArg = logFileArg1
root = root1
gpu_info = BIN_INFO("gpu_log_str.bin")
mcu_info = BIN_INFO("mcu_log_str.bin")
rom_info = BIN_INFO("application.bin")
xip_info = BIN_INFO("xip_code.bin")
itcm_info = BIN_INFO("itcm_code.bin")
sram_info = BIN_INFO("sram_code.bin")
reverse1_info = BIN_INFO("reserve1.bin")
reverse2_info = BIN_INFO("reserve2.bin")
gpu_info.bin_path, mcu_info.bin_path, bin_files = GetBinFiles(root)
output_file = os.path.join(getRelPath("input"), "gpu_debug.log_offline.txt")
os.makedirs(os.path.dirname(output_file), exist_ok=True)
if "gpu_debug.log" in logFileArg:
if not gpu_info.bin_path:
print("❌ error info: need gpu_log_str.bin")
return
else:
try:
addr_list = GetBinAddr(gpu_info.bin_path)
gpu_info.start_address, rom_info.start_address, xip_info.start_address, \
itcm_info.start_address, sram_info.start_address, reverse1_info.start_address, \
reverse2_info.start_address = addr_list
except Exception as e:
print(f"❌ 解析 Bin 地址失败: {e}")
return
bin_infos = [gpu_info, rom_info, xip_info, itcm_info, sram_info, reverse1_info, reverse2_info]
def CheckBinAddr(bin_infos, bin_files):
"""
检查每个 BIN_INFO 是否能找到对应的 .bin 文件
支持:大小写不敏感、路径包含关键词即可、application.bin 可由 OHOS_Image/factory 替代
跳过:start_address == 4294967295 的项
"""
for info in bin_infos:
# 如果地址无效,说明该段未启用,直接跳过
if info.start_address == 4294967295 or info.start_address == 0:
print(f" 跳过 {info.flag}:起始地址无效 (0x{info.start_address:X})")
continue
matched = False
target_flag = info.flag.lower()
base_names_included = [os.path.basename(f).lower() for f in bin_files]
# 尝试匹配每一个可用的 .bin 文件
for path in bin_files:
filename = os.path.basename(path).lower()
# 特殊处理 application.bin:可用多个名称替代
if target_flag == "application.bin":
if any(kw in filename for kw in ["application", "ohos_image", "factory"]):
info.bin_path = path
print(f" 使用 {filename} 匹配 {info.flag}")
matched = True
break
# 通用规则:文件名包含 flag 关键词(如 xip_code.bin ← xip_code_xxx.bin)
elif target_flag.replace(".bin", "") in filename:
info.bin_path = path
print(f" 使用 {filename} 匹配 {info.flag}")
matched = True
break
# 完全没找到 → 报错退出
if not matched:
print(f" 错误:找不到 {info.flag} 对应的文件")
print(f" 需要一个包含 '{target_flag.replace('.bin', '')}' 的 .bin 文件")
print(f" 当前可用文件: {[os.path.basename(f) for f in bin_files]}")
if info.flag == "application.bin":print(" 提示:请提供 application.bin / OHOS_Image.bin / factory.bin")
sys.exit(-1)
# ========================
# 入口点:允许直接运行或被导入
# ========================
if __name__ == "__main__":
# 如果命令行传参,则使用;否则自动查找
if len(sys.argv) == 3:
main(sys.argv[1], sys.argv[2])
else:
print("📌 未提供参数,进入自动模式...")
main() # 自动查找路径
最新发布