#!/usr/bin/python
#
# Copyright 2004 Matt Mackall <[email protected]>
#
# inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
##
#本程序实现比较两个不同时期的二进制文件,统计增加了哪些符号,删除了哪些符号,
#以及符号占用的内存大小的变化。
##
import sys, os, re
if len(sys.argv) != 3:
sys.stderr.write("usage: %s file1 file2/n" % sys.argv[0])
sys.exit(-1)
#
#nm命令介绍:
#nm命令还是比较简单而且强大的。它用来列出一个目标文件中的各种符号。符号的种类很多,以下是一些常见的符号类型
#nm输出字符 含义
#R Read only symbol. 比如在代码中有一个const MAXDATA = 3095; 则MAXDATA就是一个Read only symbol
#N 这是一个调试符号
#D 这是一个已经初始化的变量的符号。比如代码中int i = 1和char #str = "Hello"则i和str都是这种类型的符号
#T Text段的符号。子程序都是这种符号,比如文件中实现了一个函数function,则function就是这种符号
#U 未定义的符号。如果文件中引用了不存在的函数,则这些未定义的函数符号就是这种类型
#S 未初始化的符号,比如全局变量int s;则s的符号就是此类型
#
#[root@localhost Music]# nm --size-sort bin2c
#00000001 b completed.5645
#00000004 R _IO_stdin_used
#00000004 R _fp_hw
#00000004 b dtor_idx.5647
#00000005 T __libc_csu_fini
#00000069 T __libc_csu_init
#000000eb T main
#该函数返回一个字典类型的数据,{ name:size, ... }
#
#、
def getsizes(file):
sym = {}
for l in os.popen("nm --size-sort " + file).readlines():
size, type, name = l[:-1].split()
if type in "tTdDbB":
# function names begin with '.' on 64-bit powerpc
if "." in name[1:]: name = "static." + name.split(".")[0]##如果符号名中含有'.'
sym[name] = sym.get(name, 0) + int(size, 16)##对于相同的符号,累计大小
return sym
old = getsizes(sys.argv[1])##获得旧文件的符号:大小信息
new = getsizes(sys.argv[2])##获得新文件的符号:大小信息
##
#grow:符号占用内存增加的个数
#shrink:符号占用内存减少的个数
#add:增加的符号个数
#remove:减少的符号个数
#up:总共由于新符号引入而增加的占用内存的大小
#down:总共由于旧符号删除而减少的占用内存的大小。
##
grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
##
#delta:新旧文件中不同的部分
#common:新旧文件中相同的部分
##
delta, common = [], {}
##记录新旧文件中相同的符号
for a in old:
if a in new:
common[a] = 1
##记录出现在旧文件而不在新文件中的符号
for name in old:
if name not in common:
remove += 1##统计减少的符号个数
down += old[name]##统计占用的内存空间减少的数目
delta.append((-old[name], name))##负数表示占用空间减小
##记录出现在新文件而不在旧文件中的符号
for name in new:
if name not in common:
add += 1##统计增加的符号个数
up += new[name]##统计占用的内在空间增加的数目
delta.append((new[name], name))##正数表示占用空间增加
##统计新旧相同的符号中,占用的大小是否发生改变
for name in common:
d = new.get(name, 0) - old.get(name, 0)
if d>0: grow, up = grow+1, up+d##统计符号占用内存大小增加的个数以及增加的总量
if d<0: shrink, down = shrink+1, down-d##统计符号占用内存减少的个数以及减小的总量
delta.append((d, name))
delta.sort()
delta.reverse()
print "add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % /
(add, remove, grow, shrink, up, -down, up-down)
print "%-40s %7s %7s %+7s" % ("function", "old", "new", "delta")
for d, n in delta:
if d: print "%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)
##
#运行例子:
#[root@localhost Music]# python ./bloat-o-meter bin2c1 bin2c
#add/remove: 1/1 grow/shrink: 0/0 up/down: 20/-20 (0)
#function old new delta
#func3 - 20 +20
#func 20 - -20
#