feat: 新增ROM/RAM分析工具
Signed-off-by: denny <denny.shenwei@huawei.com>
This commit is contained in:
parent
02beb6b04d
commit
ee3403deaf
|
@ -0,0 +1,353 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 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
|
||||
out_fd = open("./static_symbol_out.txt", "w+")
|
||||
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")
|
||||
|
||||
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' + str(i) + '_addr'
|
||||
c = ws.cell(row, column + 1)
|
||||
c.value = addr_name
|
||||
symbol_name = 'LR' + str(i) + '_symbol'
|
||||
c = ws.cell(row, column + 2)
|
||||
c.value = symbol_name
|
||||
object_name = 'LR' + str(i) + '_object'
|
||||
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
|
||||
out_fd = open("./dynamic_memory_out.txt", "w+")
|
||||
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' + str(i) + '_addr'
|
||||
symbol_name = 'LR' + str(i) + '_symbol'
|
||||
object_name = 'LR' + str(i) + '_object'
|
||||
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')))
|
||||
|
||||
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())
|
Loading…
Reference in New Issue