#!/usr/bin/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 alias.iterkeys():
        # 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 old.iterkeys():
    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))
