#!/usr/bin/env python3 # tools/parsememdump.py # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. The # ASF licenses this file to you 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 argparse import os import re program_description = """ This program will help you analyze memdump log files, analyze the number of occurrences of backtrace, and output stack information memdump log files need this format: pid size seq addr mem """ class dump_line: def __init__(self, line_str): self.mem = [] self.err = 0 self.cnt = 1 tmp = re.search("( \d+ )", line_str) if tmp is None: self.err = 1 return self.pid = int(tmp.group(0)[1:]) tmp = re.search("( \d+ )", line_str[tmp.span()[1] :]) if tmp is None: self.err = 1 return self.size = int(tmp.group(0)[1:]) tmp = re.search("( \d+ )", line_str[tmp.span()[1] :]) if tmp is None: self.err = 1 return self.seq = int(tmp.group(0)[1:]) tmp = re.findall("0x([0-9a-fA-F]+)", line_str[tmp.span()[1] :]) self.addr = tmp[0] for str in tmp[1:]: self.mem.append(str) class log_output: def __init__(self, args): if args.output: self.file = open(args.output, "w") def output(self, str): if hasattr(self, "file"): self.file.write(str) else: print(str, end="") def __del__(self): if hasattr(self, "file"): self.file.close() def compare_dump_line(dump_line_list, str): t = dump_line(str) if t.err: return if dump_line_list.__len__() == 0: dump_line_list.append(t) return find = 0 for tmp in dump_line_list: if tmp.mem is t.mem: find = 1 tmp.cnt += 1 break if find == 0: dump_line_list.append(t) if __name__ == "__main__": parser = argparse.ArgumentParser( description=program_description, formatter_class=argparse.RawTextHelpFormatter ) parser.add_argument("-f", "--file", help="dump file", nargs=1, required=True) parser.add_argument( "-p", "--prefix", help="addr2line program prefix", nargs=1, default="" ) parser.add_argument( "-e", "--elffile", default="", help="elf file,use it can output stack info", nargs=1, ) parser.add_argument("-o", "--output", help="output file,default output shell") args = parser.parse_args() dump_file = open("%s" % args.file[0], "r") list = [] while 1: str = dump_file.readline() if str == "": break compare_dump_line(list, str) dump_file.close() list.sort(key=lambda x: x.cnt, reverse=True) log = log_output(args) total_dir = {} for t in list: if t.pid in total_dir: total_dir[t.pid] += t.size else: total_dir.setdefault(t.pid, t.size) log.output("total memory used for ervey pid\n") log.output("pid total size\n") total_size = 0 for pid, size in sorted(total_dir.items(), key=lambda x: x[1]): log.output("%-3d %-6d\n" % (pid, size)) total_size += size log.output("all used memory %-6d\n" % (total_size)) log.output("cnt size pid addr mem\n") for t in list: memstr = "" log.output("%-4d %-6d %-3d %s " % (t.cnt, t.size, t.pid, t.addr)) if t.mem == []: continue for mem in t.mem: log.output("%s " % mem) memstr += mem + " " log.output("\n") if args.elffile != "": addr2line_file = os.popen( "%saddr2line -Cfe %s %s" % (args.prefix, args.elffile[0], memstr), "r" ) while 1: add2line_str = addr2line_file.readline() if add2line_str == "": break log.output(" " + add2line_str) log.output("\n" + add2line_str) log.__del__()