#!/usr/bin/env python

import sys
import re
import itertools

def readInput(filename):
    infile = open(filename)

    fdes = []
    inFde = False
    cur = False

    for line in infile:
        line = line.rstrip()

        m = re.match("^ \[[ 0-9a-f]+\] FDE length=[0-9a-z]+ cie=\[[ 0-9a-f]+\]$", line)
        if m:
            if inFde:
                fdes.append(cur)

            inFde = True
            cur = Fde()
            continue

        m = re.match("^     (\S.+)$", line)
        if m and inFde:
            cur.instr.append(m.group(1))
            continue

        m = re.match("^ \[[ 0-9a-f]+\] CIE length=[0-9a-z]+$", line)
        if m:
            if inFde:
                fdes.append(cur)

            inFde = False
            #print line
            continue

    fdes.append(cur)
    return FdeList(fdes)

class Fde(object):
    def __init__(self):
        self.instr = []
        pass

    def __cmp__(self, other):
        return cmp(self.instr, other.instr)

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        if len(self.instr) == 0:
            return "[empty]"

        ret = ""
        for i in self.instr:
            ret += i
            ret += "\n"

        return ret[:-1]

class FdeList(list):
    def apply_filter(self, fun):
        for i in xrange(len(self)):
            fun(self[i].instr)

    def freq(self):
        res = {}
        counts = []
        l = list(self)
        l.sort()

        for _, g in itertools.groupby(l):
            counts.append(len(list(g)))

        counts.sort()

        for k, g in itertools.groupby(counts):
            res[k] = len(list(g))

        return res

def uniq(seq):
    res = []
    for k, _ in itertools.groupby(sorted(seq)):
        res.append(k)

    return res

def f_nops(instr):
    for _ in xrange(instr.count("nop")):
        instr.remove("nop")

def f_toaddr(instr):
    for i in xrange(len(instr)):
        instr[i] = re.sub(" to 0x[0-9a-z]+$", "", instr[i])



#### #### #### #### #### ####

if __name__ != "__main__":
    sys.exit(1)

if len(sys.argv) < 2:
    print "Usage: %s <file1> [<file2> ...]" % sys.argv[0]
    print "Input files have to be produced by 'eu-readelf -e' command"
    sys.exit(1)

files = []
for infile in sys.argv[1:]:

    fdes = readInput(infile)
    fdes.apply_filter(f_nops)
    fdes.apply_filter(f_toaddr)

    print "File:\t\t%s" % infile
    print "FDEs:\t\t%d" % len(fdes)
    print "Distinct:\t%d" % len(uniq(fdes))
    print "Group sizes:"

    freqs = fdes.freq()
    for i in sorted(freqs.iterkeys()):
        print "%6d:\t%d" % (i, freqs[i])

    print ""
    files.append(fdes)

if len(sys.argv) >= 3:
    fdes1 = uniq(files[0])
    fdes2 = uniq(files[1])

    match = 0
    for f in fdes1:
        try:
            fdes2.remove(f)
            match += 1
        except:
            pass

    print "There were %d matches between distinct FDEs from %s and %s\n" % (match, sys.argv[1], sys.argv[2])



