151839e29SAndy Shevchenko#!/usr/bin/env python3 2d960600dSMatt Mackall# 3d960600dSMatt Mackall# Copyright 2004 Matt Mackall <mpm@selenic.com> 4d960600dSMatt Mackall# 5d960600dSMatt Mackall# inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen 6d960600dSMatt Mackall# 7d960600dSMatt Mackall# This software may be used and distributed according to the terms 8d960600dSMatt Mackall# of the GNU General Public License, incorporated herein by reference. 9d960600dSMatt Mackall 10*b62eb273SNikolay Borisovimport sys, os, re, argparse 11eef06b82SAlexey Dobriyanfrom signal import signal, SIGPIPE, SIG_DFL 12eef06b82SAlexey Dobriyan 13eef06b82SAlexey Dobriyansignal(SIGPIPE, SIG_DFL) 14d960600dSMatt Mackall 15*b62eb273SNikolay Borisovparser = argparse.ArgumentParser(description="Simple script used to compare the symbol sizes of 2 object files") 16*b62eb273SNikolay Borisovgroup = parser.add_mutually_exclusive_group() 17*b62eb273SNikolay Borisovgroup.add_argument('-c', help='categorize output based on symbol type', action='store_true') 18*b62eb273SNikolay Borisovgroup.add_argument('-d', help='Show delta of Data Section', action='store_true') 19*b62eb273SNikolay Borisovgroup.add_argument('-t', help='Show delta of text Section', action='store_true') 20*b62eb273SNikolay Borisovparser.add_argument('file1', help='First file to compare') 21*b62eb273SNikolay Borisovparser.add_argument('file2', help='Second file to compare') 22*b62eb273SNikolay Borisov 23*b62eb273SNikolay Borisovargs = parser.parse_args() 24d960600dSMatt Mackall 250d7bbb43SAlexey Dobriyanre_NUMBER = re.compile(r'\.[0-9]+') 260d7bbb43SAlexey Dobriyan 27192efb7aSManinder Singhdef getsizes(file, format): 28d960600dSMatt Mackall sym = {} 293af06fd9SAlexey Dobriyan with os.popen("nm --size-sort " + file) as f: 303af06fd9SAlexey Dobriyan for line in f: 311d35b605SNikolay Borisov if line.startswith("\n") or ":" in line: 321d35b605SNikolay Borisov continue 333af06fd9SAlexey Dobriyan size, type, name = line.split() 34192efb7aSManinder Singh if type in format: 35c50e3f51SJean Delvare # strip generated symbols 36c2e182faSJosh Triplett if name.startswith("__mod_"): continue 37e145242eSDominik Brodowski if name.startswith("__se_sys"): continue 385ac9efa3SDominik Brodowski if name.startswith("__se_compat_sys"): continue 39e0b2475aSRasmus Villemoes if name.startswith("__addressable_"): continue 405a7b2d27SJosh Triplett if name == "linux_banner": continue 41dec81a53SPaul Gortmaker if name == "vermagic": continue 4221cf6e58SAndi Kleen # statics and some other optimizations adds random .NUMBER 430d7bbb43SAlexey Dobriyan name = re_NUMBER.sub('', name) 4451849738SRob Landley sym[name] = sym.get(name, 0) + int(size, 16) 45d960600dSMatt Mackall return sym 46d960600dSMatt Mackall 47192efb7aSManinder Singhdef calc(oldfile, newfile, format): 48192efb7aSManinder Singh old = getsizes(oldfile, format) 49192efb7aSManinder Singh new = getsizes(newfile, format) 50d960600dSMatt Mackall grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0 51d960600dSMatt Mackall delta, common = [], {} 52b21e91c3SVineet Gupta otot, ntot = 0, 0 53d960600dSMatt Mackall 54d960600dSMatt Mackall for a in old: 55d960600dSMatt Mackall if a in new: 56d960600dSMatt Mackall common[a] = 1 57d960600dSMatt Mackall 58d960600dSMatt Mackall for name in old: 59b21e91c3SVineet Gupta otot += old[name] 60d960600dSMatt Mackall if name not in common: 61d960600dSMatt Mackall remove += 1 62d960600dSMatt Mackall down += old[name] 63d960600dSMatt Mackall delta.append((-old[name], name)) 64d960600dSMatt Mackall 65d960600dSMatt Mackall for name in new: 66b21e91c3SVineet Gupta ntot += new[name] 67d960600dSMatt Mackall if name not in common: 68d960600dSMatt Mackall add += 1 69d960600dSMatt Mackall up += new[name] 70d960600dSMatt Mackall delta.append((new[name], name)) 71d960600dSMatt Mackall 72d960600dSMatt Mackall for name in common: 73d960600dSMatt Mackall d = new.get(name, 0) - old.get(name, 0) 74d960600dSMatt Mackall if d>0: grow, up = grow+1, up+d 75d960600dSMatt Mackall if d<0: shrink, down = shrink+1, down-d 76d960600dSMatt Mackall delta.append((d, name)) 77d960600dSMatt Mackall 78d960600dSMatt Mackall delta.sort() 79d960600dSMatt Mackall delta.reverse() 80192efb7aSManinder Singh return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot 81192efb7aSManinder Singh 82*b62eb273SNikolay Borisovdef print_result(symboltype, symbolformat): 83192efb7aSManinder Singh grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \ 84*b62eb273SNikolay Borisov calc(args.file1, args.file2, symbolformat) 85d960600dSMatt Mackall 8672214a24SSergey Senozhatsky print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \ 8772214a24SSergey Senozhatsky (add, remove, grow, shrink, up, -down, up-down)) 88192efb7aSManinder Singh print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta")) 89d960600dSMatt Mackall for d, n in delta: 9072214a24SSergey Senozhatsky if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)) 91b21e91c3SVineet Gupta 92edbddb83SAndy Shevchenko if otot: 93edbddb83SAndy Shevchenko percent = (ntot - otot) * 100.0 / otot 94edbddb83SAndy Shevchenko else: 95edbddb83SAndy Shevchenko percent = 0 96edbddb83SAndy Shevchenko print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent)) 97192efb7aSManinder Singh 98*b62eb273SNikolay Borisovif args.c: 99*b62eb273SNikolay Borisov print_result("Function", "tT") 100*b62eb273SNikolay Borisov print_result("Data", "dDbB") 101*b62eb273SNikolay Borisov print_result("RO Data", "rR") 102*b62eb273SNikolay Borisovelif args.d: 103*b62eb273SNikolay Borisov print_result("Data", "dDbBrR") 104*b62eb273SNikolay Borisovelif args.t: 105*b62eb273SNikolay Borisov print_result("Function", "tT") 106192efb7aSManinder Singhelse: 107*b62eb273SNikolay Borisov print_result("Function", "tTdDbBrR") 108