18c2ecf20Sopenharmony_ci#!/usr/bin/env python3
28c2ecf20Sopenharmony_ci#
38c2ecf20Sopenharmony_ci# Copyright 2004 Matt Mackall <mpm@selenic.com>
48c2ecf20Sopenharmony_ci#
58c2ecf20Sopenharmony_ci# inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen
68c2ecf20Sopenharmony_ci#
78c2ecf20Sopenharmony_ci# This software may be used and distributed according to the terms
88c2ecf20Sopenharmony_ci# of the GNU General Public License, incorporated herein by reference.
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ciimport sys, os, re
118c2ecf20Sopenharmony_cifrom signal import signal, SIGPIPE, SIG_DFL
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cisignal(SIGPIPE, SIG_DFL)
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ciif len(sys.argv) < 3:
168c2ecf20Sopenharmony_ci    sys.stderr.write("usage: %s [option] file1 file2\n" % sys.argv[0])
178c2ecf20Sopenharmony_ci    sys.stderr.write("The options are:\n")
188c2ecf20Sopenharmony_ci    sys.stderr.write("-c	categorize output based on symbol type\n")
198c2ecf20Sopenharmony_ci    sys.stderr.write("-d	Show delta of Data Section\n")
208c2ecf20Sopenharmony_ci    sys.stderr.write("-t	Show delta of text Section\n")
218c2ecf20Sopenharmony_ci    sys.exit(-1)
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cire_NUMBER = re.compile(r'\.[0-9]+')
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cidef getsizes(file, format):
268c2ecf20Sopenharmony_ci    sym = {}
278c2ecf20Sopenharmony_ci    with os.popen("nm --size-sort " + file) as f:
288c2ecf20Sopenharmony_ci        for line in f:
298c2ecf20Sopenharmony_ci            if line.startswith("\n") or ":" in line:
308c2ecf20Sopenharmony_ci                continue
318c2ecf20Sopenharmony_ci            size, type, name = line.split()
328c2ecf20Sopenharmony_ci            if type in format:
338c2ecf20Sopenharmony_ci                # strip generated symbols
348c2ecf20Sopenharmony_ci                if name.startswith("__mod_"): continue
358c2ecf20Sopenharmony_ci                if name.startswith("__se_sys"): continue
368c2ecf20Sopenharmony_ci                if name.startswith("__se_compat_sys"): continue
378c2ecf20Sopenharmony_ci                if name.startswith("__addressable_"): continue
388c2ecf20Sopenharmony_ci                if name == "linux_banner": continue
398c2ecf20Sopenharmony_ci                # statics and some other optimizations adds random .NUMBER
408c2ecf20Sopenharmony_ci                name = re_NUMBER.sub('', name)
418c2ecf20Sopenharmony_ci                sym[name] = sym.get(name, 0) + int(size, 16)
428c2ecf20Sopenharmony_ci    return sym
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cidef calc(oldfile, newfile, format):
458c2ecf20Sopenharmony_ci    old = getsizes(oldfile, format)
468c2ecf20Sopenharmony_ci    new = getsizes(newfile, format)
478c2ecf20Sopenharmony_ci    grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
488c2ecf20Sopenharmony_ci    delta, common = [], {}
498c2ecf20Sopenharmony_ci    otot, ntot = 0, 0
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci    for a in old:
528c2ecf20Sopenharmony_ci        if a in new:
538c2ecf20Sopenharmony_ci            common[a] = 1
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci    for name in old:
568c2ecf20Sopenharmony_ci        otot += old[name]
578c2ecf20Sopenharmony_ci        if name not in common:
588c2ecf20Sopenharmony_ci            remove += 1
598c2ecf20Sopenharmony_ci            down += old[name]
608c2ecf20Sopenharmony_ci            delta.append((-old[name], name))
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci    for name in new:
638c2ecf20Sopenharmony_ci        ntot += new[name]
648c2ecf20Sopenharmony_ci        if name not in common:
658c2ecf20Sopenharmony_ci            add += 1
668c2ecf20Sopenharmony_ci            up += new[name]
678c2ecf20Sopenharmony_ci            delta.append((new[name], name))
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci    for name in common:
708c2ecf20Sopenharmony_ci        d = new.get(name, 0) - old.get(name, 0)
718c2ecf20Sopenharmony_ci        if d>0: grow, up = grow+1, up+d
728c2ecf20Sopenharmony_ci        if d<0: shrink, down = shrink+1, down-d
738c2ecf20Sopenharmony_ci        delta.append((d, name))
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci    delta.sort()
768c2ecf20Sopenharmony_ci    delta.reverse()
778c2ecf20Sopenharmony_ci    return grow, shrink, add, remove, up, down, delta, old, new, otot, ntot
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cidef print_result(symboltype, symbolformat, argc):
808c2ecf20Sopenharmony_ci    grow, shrink, add, remove, up, down, delta, old, new, otot, ntot = \
818c2ecf20Sopenharmony_ci    calc(sys.argv[argc - 1], sys.argv[argc], symbolformat)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci    print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
848c2ecf20Sopenharmony_ci          (add, remove, grow, shrink, up, -down, up-down))
858c2ecf20Sopenharmony_ci    print("%-40s %7s %7s %+7s" % (symboltype, "old", "new", "delta"))
868c2ecf20Sopenharmony_ci    for d, n in delta:
878c2ecf20Sopenharmony_ci        if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci    if otot:
908c2ecf20Sopenharmony_ci        percent = (ntot - otot) * 100.0 / otot
918c2ecf20Sopenharmony_ci    else:
928c2ecf20Sopenharmony_ci        percent = 0
938c2ecf20Sopenharmony_ci    print("Total: Before=%d, After=%d, chg %+.2f%%" % (otot, ntot, percent))
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ciif sys.argv[1] == "-c":
968c2ecf20Sopenharmony_ci    print_result("Function", "tT", 3)
978c2ecf20Sopenharmony_ci    print_result("Data", "dDbB", 3)
988c2ecf20Sopenharmony_ci    print_result("RO Data", "rR", 3)
998c2ecf20Sopenharmony_cielif sys.argv[1] == "-d":
1008c2ecf20Sopenharmony_ci    print_result("Data", "dDbBrR", 3)
1018c2ecf20Sopenharmony_cielif sys.argv[1] == "-t":
1028c2ecf20Sopenharmony_ci    print_result("Function", "tT", 3)
1038c2ecf20Sopenharmony_cielse:
1048c2ecf20Sopenharmony_ci    print_result("Function", "tTdDbBrR", 2)
105