#!/usr/bin/env python
#
# Copyright 2004 Matt Mackall <mpm@selenic.com>
#
# 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

def usage():
    sys.stderr.write("usage: %s [-t] file1 file2\n" % sys.argv[0])
    sys.exit(-1)

f1, f2 = (None, None)
flag_timing, dashes = (False, False)

for f in sys.argv[1:]:
    if f.startswith("-"):
        if f == "--": # sym_args
            dashes = True
            break
        if f == "-t": # timings
            flag_timing = True
    else:
        if not os.path.exists(f):
            sys.stderr.write("Error: file '%s' does not exist\n" % f)
            usage()
        if f1 is None:
            f1 = f
        elif f2 is None:
            f2 = f
if flag_timing:
    import time
if f1 is None or f2 is None:
    usage()

sym_args = " ".join(sys.argv[3 + flag_timing + dashes:])
def getsizes(file):
    sym, alias, lut = {}, {}, {}
    #dynsym_filter = re.compile("^\d+:\s+[\dA-Fa-f]+\s+\d+\s+\w+\s+\w+\s+\w+\s+\w+\s+\w+$")
    for l in os.popen("readelf -W -s %s %s" % (sym_args, file)).readlines():
        if True:
            l = l.strip()
            if not (len(l) and l[0].isdigit() and len(l.split()) == 8):
                continue
            num, value, size, typ, bind, vis, ndx, name = l.split()
            if ndx == "UND": continue # skip undefined
            if typ in ["SECTION", "FILES"]: continue # skip sections and files
        #else:
        #    l = l.strip()
        #    match = dynsym_filter.match(l)
        #    if not match: continue
        #    x, value, size, typ, bind, x, ndx, name = l.split()
        #    if ndx == "UND": continue # skip undefined
        #    if typ in ["SECTION", "FILES"]: continue # skip sections and files
        if "." in name: name = "static." + name.split(".")[0]
        value = int(value, 16)
        size = int(size)
        if vis != "DEFAULT" and bind != "GLOBAL": # see if it is an alias
            alias[(value, size)] = {"name" : name}
        else:
            sym[name] = {"addr" : value, "size":  size}
            lut[(value, size)] = 0
    for addr, sz in iter(alias.keys()):
        # If the non-GLOBAL sym has an implementation elsewhere then
        # it's an alias, disregard it.
        if not (addr, sz) in lut:
            # If this non-GLOBAL sym does not have an implementation at
            # another address, then treat it as a normal symbol.
            sym[alias[(addr, sz)]["name"]] = {"addr" : addr, "size": sz}
    for l in os.popen("readelf -W -S " + file).readlines():
        x = l.split()
        if len(x)<6: continue
        # Should take these into account too!
        #if x[1] not in [".text", ".rodata", ".symtab", ".strtab"]: continue
        if x[1] not in [".rodata"]: continue
        sym[x[1]] = {"addr" : int(x[3], 16), "size" : int(x[5], 16)}
    return sym

if flag_timing:
    start_t1 = int(time.time() * 1e9)
old = getsizes(f1)
if flag_timing:
    end_t1 = int(time.time() * 1e9)
    start_t2 = int(time.time() * 1e9)
new = getsizes(f2)
if flag_timing:
    end_t2 = int(time.time() * 1e9)
    start_t3 = int(time.time() * 1e9)
grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
delta, common = [], {}

for name in iter(old.keys()):
    if name in new:
        common[name] = 1

for name in old:
    if name not in common:
        remove += 1
        sz = old[name]["size"]
        down += sz
        delta.append((-sz, name))

for name in new:
    if name not in common:
        add += 1
        sz = new[name]["size"]
        up += sz
        delta.append((sz, name))

for name in common:
        d = new[name].get("size", 0) - old[name].get("size", 0)
        if d>0: grow, up = grow+1, up+d
        elif d<0: shrink, down = shrink+1, down-d
        else:
            continue
        delta.append((d, name))

delta.sort()
delta.reverse()
if flag_timing:
    end_t3 = int(time.time() * 1e9)

print("%-48s %7s %7s %+7s" % ("function", "old", "new", "delta"))
for d, n in delta:
    if d:
        old_sz = old.get(n, {}).get("size", "-")
        new_sz = new.get(n, {}).get("size", "-")
        print("%-48s %7s %7s %+7d" % (n, old_sz, new_sz, d))
print("-"*78)
total="(add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s)%%sTotal: %s bytes"\
    % (add, remove, grow, shrink, up, -down, up-down)
print(total % (" "*(80-len(total))))
if flag_timing:
    print("\n%d/%d; %d Parse origin/new; processing nsecs" %
        (end_t1-start_t1, end_t2-start_t2, end_t3-start_t3))
    print("total nsecs: %d" % (end_t3-start_t1))
