353 lines
13 KiB
Python
353 lines
13 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
|
# Copyright (c) 2020-2022 Huawei Device Co., Ltd.
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
import re
|
|
import sys
|
|
import argparse
|
|
import os
|
|
import datetime
|
|
|
|
g_version = 2.5
|
|
g_excel_support = False
|
|
g_row_num = 0
|
|
|
|
try:
|
|
from openpyxl import Workbook
|
|
except:
|
|
print("excel output is not support, need install openpyxl")
|
|
else:
|
|
g_excel_support = True
|
|
|
|
def is_number(num):
|
|
try:
|
|
int(num, 16)
|
|
return True
|
|
except ValueError:
|
|
pass
|
|
return False
|
|
|
|
static_map = {}
|
|
def storage_static_data(offset, section, sizeHex, symbol, lib, obj):
|
|
global g_row_num
|
|
if (0 == g_row_num):
|
|
static_map[g_row_num] = {'offsets' : "offsets", 'section' : "section",\
|
|
'sizeH' : "size(Hex)", 'sizeD' : "size(Dec)",\
|
|
'symbol' : "symbol", 'lib' : "lib", 'obj' : "object"}
|
|
g_row_num = g_row_num + 1
|
|
|
|
size = int(sizeHex, 16)
|
|
static_map[g_row_num] = {'offsets': offset, 'section' : section,\
|
|
'sizeH' : sizeHex, 'sizeD' : size,\
|
|
'symbol' : symbol, 'lib' : lib, 'obj' : obj}
|
|
g_row_num = g_row_num + 1
|
|
|
|
def store_static_excel():
|
|
wb = Workbook()
|
|
ws = wb.active
|
|
for base_address, values in static_map.items():
|
|
c = ws.cell(row=base_address + 1, column=1)
|
|
c.value = values.get('offsets')
|
|
c = ws.cell(row=base_address + 1, column=2)
|
|
c.value = values.get('section')
|
|
c = ws.cell(row=base_address + 1, column=3)
|
|
c.value = values.get('sizeH')
|
|
c = ws.cell(row=base_address + 1, column=4)
|
|
c.value = values.get('sizeD')
|
|
c = ws.cell(row=base_address + 1, column=5)
|
|
c.value = values.get('symbol')
|
|
c = ws.cell(row=base_address + 1, column=6)
|
|
c.value = values.get('lib')
|
|
c = ws.cell(row=base_address + 1, column=7)
|
|
c.value = values.get('obj')
|
|
wb.save('static_symbol-%s.xlsx' % datetime.datetime.now().strftime('%Y-%m-%d %H_%M_%S'))
|
|
return
|
|
|
|
def format_store_static():
|
|
global g_excel_support
|
|
target_list = []
|
|
|
|
for base_address, values in static_map.items():
|
|
target_list.append('{:<10s}'.format(values.get('offsets')))
|
|
target_list.append('{:<30s}'.format(values.get('section')))
|
|
target_list.append('{:<10}'.format(values.get('sizeH')))
|
|
target_list.append('{:<10}'.format(values.get('sizeD')))
|
|
target_list.append('{:<55s}{:<55s}{:<55s}'.format(values.get('symbol'), values.get('lib'), values.get('obj')))
|
|
target_list.append("\r")
|
|
|
|
with open("./static_symbol_out.txt", "w+") as out_fd:
|
|
out_fd.write("".join(target_list))
|
|
if g_excel_support == True:
|
|
store_static_excel()
|
|
return
|
|
|
|
dync_map = {}
|
|
#dync map multiple LR, first dync_map node will record LR size
|
|
def storage_dync_head(size):
|
|
global g_row_num
|
|
dync_map[0] = {'addr' : "Memnode", 'symbol' : "size", 'lib' : size}
|
|
g_row_num = 1
|
|
|
|
#when the analysis of one line LR is finished, need record "\r\n" and the new line info
|
|
def storage_dync_node(node_addr, size):
|
|
global g_row_num
|
|
dync_map[g_row_num] = {'addr' : "\r\n", 'symbol' : node_addr, 'lib' : size}
|
|
g_row_num = g_row_num + 1
|
|
|
|
def storage_dync_data(addr, symbol, lib):
|
|
global g_row_num
|
|
dync_map[g_row_num] = {'addr' : addr, 'symbol' : symbol, 'lib' : lib}
|
|
g_row_num = g_row_num + 1
|
|
|
|
def store_dync_excel():
|
|
wb = Workbook()
|
|
ws = wb.active
|
|
row = 1
|
|
column = 0
|
|
for base_address, values in dync_map.items():
|
|
if (0 == base_address):
|
|
c = ws.cell(row, 1)
|
|
c.value = values.get('addr')
|
|
c = ws.cell(row, 2)
|
|
c.value = values.get('symbol')
|
|
for i in range(values.get('lib')):
|
|
column = i * 3 + 2
|
|
addr_name = "LR%s_addr" % (str(i))
|
|
c = ws.cell(row, column + 1)
|
|
c.value = addr_name
|
|
symbol_name = "LR%s_symbol" % (str(i))
|
|
c = ws.cell(row, column + 2)
|
|
c.value = symbol_name
|
|
object_name = "LR%s_object" % (str(i))
|
|
c = ws.cell(row, column + 3)
|
|
c.value = object_name
|
|
else:
|
|
if("\r\n" == values.get('addr')):
|
|
row = row + 1
|
|
column = 1
|
|
c = ws.cell(row, column)
|
|
c.value = values.get('symbol')
|
|
column = column + 1
|
|
c = ws.cell(row, column)
|
|
c.value = values.get('lib')
|
|
else:
|
|
c = ws.cell(row, column + 1)
|
|
c.value = values.get('addr')
|
|
c = ws.cell(row, column + 2)
|
|
c.value = values.get('symbol')
|
|
c = ws.cell(row, column + 3)
|
|
c.value = values.get('lib')
|
|
column = column + 3
|
|
wb.save('dync_mem-%s.xlsx' % datetime.datetime.now().strftime('%Y-%m-%d %H_%M_%S'))
|
|
return
|
|
|
|
def format_store_dync():
|
|
global g_excel_support
|
|
target_list = []
|
|
|
|
for base_address, values in dync_map.items():
|
|
if (0 == base_address):
|
|
target_list.append('{:<15s}{:<15s}'.format("node", "size"))
|
|
for i in range(values.get('lib')):
|
|
addr_name = "LR%s_addr" % (str(i))
|
|
symbol_name = "LR%s_symbol" % (str(i))
|
|
object_name = "LR%s_object" % (str(i))
|
|
target_list.append('{:<15s}{:<55s}{:<55s}'.format(addr_name, symbol_name, object_name))
|
|
|
|
else:
|
|
if ("\r\n" == values.get('addr')):
|
|
target_list.append("\r")
|
|
target_list.append('{:<15s}{:<15}'.format(values.get('symbol'), values.get('lib')))
|
|
else:
|
|
target_list.append('{:<15s}'.format(values.get('addr')))
|
|
target_list.append('{:<55s}'.format(values.get('symbol')))
|
|
target_list.append('{:<55s}'.format(values.get('lib')))
|
|
|
|
with open("./dynamic_memory_out.txt", "w+") as out_fd:
|
|
out_fd.write("".join(target_list))
|
|
if g_excel_support == True:
|
|
store_dync_excel()
|
|
return
|
|
|
|
address_map = {}
|
|
def get_func_by_name(function_name):
|
|
for base_address, values in address_map.items():
|
|
if values.get('func_name') == function_name:
|
|
return values.get('lib_name'), values.get('obj_name')
|
|
return "none", "none"
|
|
|
|
def get_func_by_address(address):
|
|
if 0 == address:
|
|
return "none", "none"
|
|
|
|
for base_address, values in address_map.items():
|
|
if (base_address <= address) and (base_address + values.get('size') > address):
|
|
return values.get('func_name'), values.get('obj_name')
|
|
return "none", "none"
|
|
|
|
def line_start_check(line):
|
|
if line.startswith(' .text.'):
|
|
function_name = line.split(".text.")[1]
|
|
elif line.startswith(' .rodata.'):
|
|
function_name = line.split(".rodata.")[1]
|
|
elif line.startswith(' .bss.'):
|
|
function_name = line.split(".bss.")[1]
|
|
elif line.startswith(' .sram.text.'):
|
|
function_name = line.split(".sram.text.")[1]
|
|
elif line.startswith(' .data.'):
|
|
function_name = line.split(".data.")[1]
|
|
else:
|
|
return None
|
|
return function_name
|
|
|
|
def parse_map(file_path):
|
|
parse_begin = False
|
|
function_name = ""
|
|
address = None
|
|
size = None
|
|
obj_name = ""
|
|
lib_name = ""
|
|
pl = re.compile(r'[(](.*?)[)]', re.S)
|
|
with open(file_path, "r") as f:
|
|
for line in f.readlines():
|
|
if not parse_begin:
|
|
function_name = line_start_check(line)
|
|
if function_name != None:
|
|
if len(function_name.split()) > 1:
|
|
strs = function_name.split()
|
|
function_name = strs[0]
|
|
function_name = function_name.strip()
|
|
address = int(strs[1], 16)
|
|
size = int(strs[2], 16)
|
|
obj_name = re.findall(pl, strs[3])
|
|
if len(obj_name) > 0:
|
|
obj_name = obj_name[0]
|
|
else:
|
|
obj_name = strs[3]
|
|
char_temp = strs[3].split('(')
|
|
if len(char_temp) > 1:
|
|
lib_name = char_temp[0].split('/')[-1]
|
|
else:
|
|
lib_name = "none"
|
|
address_map[address] = {'size' : size, 'lib_name' : lib_name, \
|
|
'obj_name' : obj_name, 'func_name' : function_name}
|
|
else:
|
|
parse_begin = True
|
|
else:
|
|
continue
|
|
else:
|
|
parse_begin = False
|
|
if len(line.strip().split()) != 3:
|
|
continue
|
|
strs = line.strip().split()
|
|
address = int(strs[0], 16)
|
|
size = int(strs[1], 16)
|
|
obj_name = re.findall(pl, strs[2])
|
|
if len(obj_name) > 0:
|
|
obj_name = obj_name[0]
|
|
else:
|
|
obj_name = strs[2]
|
|
function_name = function_name.strip()
|
|
char_temp = strs[2].split('(')
|
|
if len(char_temp) > 1:
|
|
lib_name = char_temp[0].split('/')[-1]
|
|
else:
|
|
lib_name = "none"
|
|
address_map[address] = {'size' : size, 'lib_name' : lib_name, \
|
|
'obj_name' : obj_name, 'func_name' : function_name}
|
|
|
|
def parse_dump(dump_path):
|
|
with open(dump_path, "r") as symbol_fd:
|
|
symline = symbol_fd.readlines()
|
|
|
|
for index, line in enumerate(symline):
|
|
offset = line[:8]
|
|
|
|
#According to the regular expression of objdump , section start at 17 char
|
|
symbol_list = line[17:].split()
|
|
if len(symbol_list) < 3:
|
|
continue
|
|
|
|
sec = symbol_list[0]
|
|
size = symbol_list[1]
|
|
if (False == is_number(size)) or 0 == int(size, 16):
|
|
continue
|
|
|
|
lib, obj = get_func_by_name(symbol_list[-1])
|
|
storage_static_data(offset, sec, size, symbol_list[-1], lib, obj)
|
|
|
|
def parse_log(log_path):
|
|
with open(log_path, "r") as log_fd:
|
|
logline = log_fd.readlines()
|
|
get_valid_log = False
|
|
for index, line in enumerate(logline):
|
|
char_list = line.split()
|
|
if len(char_list) < 3:
|
|
continue
|
|
if ("node" == char_list[0]) & ("LR[0]" == char_list[2]):
|
|
storage_dync_head(len(char_list) - 2)
|
|
get_valid_log = True
|
|
continue
|
|
|
|
if True == get_valid_log:
|
|
mem_addr = char_list[0].split(':')
|
|
if True == is_number(mem_addr[0]):
|
|
for i in range(len(char_list)):
|
|
if i == 0:
|
|
size = int(char_list[1], 16)
|
|
storage_dync_node(mem_addr[0], size)
|
|
if i > 1:
|
|
symbol, lib = get_func_by_address(int(char_list[i], 16))
|
|
storage_dync_data(char_list[i], symbol, lib)
|
|
else:
|
|
get_valid_log = False
|
|
continue
|
|
|
|
def main():
|
|
print("memory parses tool ver.%2f\r\n" % g_version)
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--m', help='map path.')
|
|
parser.add_argument('--l', help='dynamic mem log path.')
|
|
parser.add_argument('--d', help='objdump path.')
|
|
args = parser.parse_args()
|
|
|
|
print("map path: %s\r\n" % args.m)
|
|
if args.m == None :
|
|
print("arg error, input -h get the help list\r\n")
|
|
return
|
|
|
|
parse_map(args.m)
|
|
|
|
print("dump path: %s" % args.d)
|
|
if args.d != None :
|
|
parse_dump(args.d)
|
|
format_store_static()
|
|
else:
|
|
print("dump path unspecified, will not be static parser")
|
|
print("you can enter the objdump -t command under the linux shell to obtain dump information\r\n")
|
|
|
|
print("log path: %s" % args.l)
|
|
if args.l != None :
|
|
parse_log(args.l)
|
|
format_store_dync()
|
|
else:
|
|
print("log path unspecified, will not be dynamic parser\r\n")
|
|
|
|
return
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main()) |