1*4882a593Smuzhiyun#!/usr/bin/env python3 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# Copyright 2004 Matt Mackall <mpm@selenic.com> 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# This software may be used and distributed according to the terms 8*4882a593Smuzhiyun# of the GNU General Public License, incorporated herein by reference. 9*4882a593Smuzhiyun 10*4882a593Smuzhiyunimport sys, os, re 11*4882a593Smuzhiyunfrom signal import signal, SIGPIPE, SIG_DFL 12*4882a593Smuzhiyun 13*4882a593Smuzhiyunsignal(SIGPIPE, SIG_DFL) 14*4882a593Smuzhiyun 15*4882a593Smuzhiyunif len(sys.argv) < 3: 16*4882a593Smuzhiyun sys.stderr.write("usage: %s [option] file1 file2\n" % sys.argv[0]) 17*4882a593Smuzhiyun sys.stderr.write("The options are:\n") 18*4882a593Smuzhiyun sys.stderr.write("-c categorize output based on symbol type\n") 19*4882a593Smuzhiyun sys.stderr.write("-d Show delta of Data Section\n") 20*4882a593Smuzhiyun sys.stderr.write("-t Show delta of text Section\n") 21*4882a593Smuzhiyun sys.exit(-1) 22*4882a593Smuzhiyun 23*4882a593Smuzhiyunre_NUMBER = re.compile(r'\.[0-9]+') 24*4882a593Smuzhiyun 25*4882a593Smuzhiyundef getsizes(file, format): 26*4882a593Smuzhiyun sym = {} 27*4882a593Smuzhiyun with os.popen("nm --size-sort " + file) as f: 28*4882a593Smuzhiyun for line in f: 29*4882a593Smuzhiyun if line.startswith("\n") or ":" in line: 30*4882a593Smuzhiyun continue 31*4882a593Smuzhiyun size, type, name = line.split() 32*4882a593Smuzhiyun if type in format: 33*4882a593Smuzhiyun # strip generated symbols 34*4882a593Smuzhiyun if name.startswith("__mod_"): continue 35*4882a593Smuzhiyun if name.startswith("__se_sys"): continue 36*4882a593Smuzhiyun if name.startswith("__se_compat_sys"): continue 37*4882a593Smuzhiyun if name.startswith("__addressable_"): continue 38*4882a593Smuzhiyun if name == "linux_banner": continue 39*4882a593Smuzhiyun # statics and some other optimizations adds random .NUMBER 40*4882a593Smuzhiyun name = re_NUMBER.sub('', name) 41*4882a593Smuzhiyun sym[name] = sym.get(name, 0) + int(size, 16) 42*4882a593Smuzhiyun return sym 43*4882a593Smuzhiyun 44*4882a593Smuzhiyundef calc(oldfile, newfile, format): 45*4882a593Smuzhiyun old = getsizes(oldfile, format) 46*4882a593Smuzhiyun new = getsizes(newfile, format) 47*4882a593Smuzhiyun grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0 48*4882a593Smuzhiyun delta, common = [], {} 49*4882a593Smuzhiyun otot, ntot = 0, 0 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun for a in old: 52*4882a593Smuzhiyun if a in new: 53*4882a593Smuzhiyun common[a] = 1 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun for name in old: 56*4882a593Smuzhiyun otot += old[name] 57*4882a593Smuzhiyun if name not in common: 58*4882a593Smuzhiyun remove += 1 59*4882a593Smuzhiyun down += old[name] 60*4882a593Smuzhiyun delta.append((-old[name], name)) 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun for name in new: 63*4882a593Smuzhiyun ntot += new[name] 64*4882a593Smuzhiyun if name not in common: 65*4882a593Smuzhiyun add += 1 66*4882a593Smuzhiyun up += new[name] 67*4882a593Smuzhiyun delta.append((new[name], name)) 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun for name in common: 70*4882a593Smuzhiyun d = new.get(name, 0) - old.get(name, 0) 71*4882a593Smuzhiyun if d>0: grow, up = grow+1, up+d 72*4882a593Smuzhiyun if d<0: shrink, down = shrink+1, down-d 73*4882a593Smuzhiyun delta.append((d, name)) 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun delta.sort() 76*4882a593Smuzhiyun delta.reverse() 77*4882a593Smuzhiyun return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot 78*4882a593Smuzhiyun 79*4882a593Smuzhiyundef print_result(symboltype, symbolformat, argc): 80*4882a593Smuzhiyun grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \ 81*4882a593Smuzhiyun calc(sys.argv[argc - 1], sys.argv[argc], symbolformat) 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \ 84*4882a593Smuzhiyun (add, remove, grow, shrink, up, -down, up-down)) 85*4882a593Smuzhiyun print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta")) 86*4882a593Smuzhiyun for d, n in delta: 87*4882a593Smuzhiyun if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)) 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun if otot: 90*4882a593Smuzhiyun percent = (ntot - otot) * 100.0 / otot 91*4882a593Smuzhiyun else: 92*4882a593Smuzhiyun percent = 0 93*4882a593Smuzhiyun print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent)) 94*4882a593Smuzhiyun 95*4882a593Smuzhiyunif sys.argv[1] == "-c": 96*4882a593Smuzhiyun print_result("Function", "tT", 3) 97*4882a593Smuzhiyun print_result("Data", "dDbB", 3) 98*4882a593Smuzhiyun print_result("RO Data", "rR", 3) 99*4882a593Smuzhiyunelif sys.argv[1] == "-d": 100*4882a593Smuzhiyun print_result("Data", "dDbBrR", 3) 101*4882a593Smuzhiyunelif sys.argv[1] == "-t": 102*4882a593Smuzhiyun print_result("Function", "tT", 3) 103*4882a593Smuzhiyunelse: 104*4882a593Smuzhiyun print_result("Function", "tTdDbBrR", 2) 105