#! /usr/bin/env python

# objgraph
#
# Read "nm -o" input (on IRIX: "nm -Bo") of a set of libraries or modules
# and print various interesting listings, such as:
#
# - which names are used but not defined in the set (and used where),
# - which names are defined in the set (and where),
# - which modules use which other modules,
# - which modules are used by which other modules.
#
# Usage: objgraph [-cdu] [file] ...
# -c: print callers per objectfile
# -d: print callees per objectfile
# -u: print usage of undefined symbols
# If none of -cdu is specified, all are assumed.
# Use "nm -o" to generate the input (on IRIX: "nm -Bo"),
# e.g.: nm -o /lib/libc.a | objgraph


import sys
import string
import os
import getopt
import regex

# Types of symbols.
#
definitions = 'TRGDSBAEC'
externals = 'UV'
ignore = 'Nntrgdsbavuc'

# Regular expression to parse "nm -o" output.
#
matcher = regex.compile('\(.*\):\t?........ \(.\) \(.*\)$')

# Store "item" in "dict" under "key".
# The dictionary maps keys to lists of items.
# If there is no list for the key yet, it is created.
#
def store(dict, key, item):
    if dict.has_key(key):
        dict[key].append(item)
    else:
        dict[key] = [item]

# Return a flattened version of a list of strings: the concatenation
# of its elements with intervening spaces.
#
def flat(list):
    s = ''
    for item in list:
        s = s + ' ' + item
    return s[1:]

# Global variables mapping defined/undefined names to files and back.
#
file2undef = {}
def2file = {}
file2def = {}
undef2file = {}

# Read one input file and merge the data into the tables.
# Argument is an open file.
#
def readinput(file):
    while 1:
        s = file.readline()
        if not s:
            break
        # If you get any output from this line,
        # it is probably caused by an unexpected input line:
        if matcher.search(s) < 0: s; continue # Shouldn't happen
        (ra, rb), (r1a, r1b), (r2a, r2b), (r3a, r3b) = matcher.regs[:4]
        fn, name, type = s[r1a:r1b], s[r3a:r3b], s[r2a:r2b]
        if type in definitions:
            store(def2file, name, fn)
            store(file2def, fn, name)
        elif type in externals:
            store(file2undef, fn, name)
            store(undef2file, name, fn)
        elif not type in ignore:
            print fn + ':' + name + ': unknown type ' + type

# Print all names that were undefined in some module and where they are
# defined.
#
def printcallee():
    flist = file2undef.keys()
    flist.sort()
    for file in flist:
        print file + ':'
        elist = file2undef[file]
        elist.sort()
        for ext in elist:
            if len(ext) >= 8:
                tabs = '\t'
            else:
                tabs = '\t\t'
            if not def2file.has_key(ext):
                print '\t' + ext + tabs + ' *undefined'
            else:
                print '\t' + ext + tabs + flat(def2file[ext])

# Print for each module the names of the other modules that use it.
#
def printcaller():
    files = file2def.keys()
    files.sort()
    for file in files:
        callers = []
        for label in file2def[file]:
            if undef2file.has_key(label):
                callers = callers + undef2file[label]
        if callers:
            callers.sort()
            print file + ':'
            lastfn = ''
            for fn in callers:
                if fn <> lastfn:
                    print '\t' + fn
                lastfn = fn
        else:
            print file + ': unused'

# Print undefine names and where they are used.
#
def printundef():
    undefs = {}
    for file in file2undef.keys():
        for ext in file2undef[file]:
            if not def2file.has_key(ext):
                store(undefs, ext, file)
    elist = undefs.keys()
    elist.sort()
    for ext in elist:
        print ext + ':'
        flist = undefs[ext]
        flist.sort()
        for file in flist:
            print '\t' + file

# Print warning messages about names defined in more than one file.
#
def warndups():
    savestdout = sys.stdout
    sys.stdout = sys.stderr
    names = def2file.keys()
    names.sort()
    for name in names:
        if len(def2file[name]) > 1:
            print 'warning:', name, 'multiply defined:',
            print flat(def2file[name])
    sys.stdout = savestdout

# Main program
#
def main():
    try:
        optlist, args = getopt.getopt(sys.argv[1:], 'cdu')
    except getopt.error:
        sys.stdout = sys.stderr
        print 'Usage:', os.path.basename(sys.argv[0]),
        print           '[-cdu] [file] ...'
        print '-c: print callers per objectfile'
        print '-d: print callees per objectfile'
        print '-u: print usage of undefined symbols'
        print 'If none of -cdu is specified, all are assumed.'
        print 'Use "nm -o" to generate the input (on IRIX: "nm -Bo"),'
        print 'e.g.: nm -o /lib/libc.a | objgraph'
        return 1
    optu = optc = optd = 0
    for opt, void in optlist:
        if opt == '-u':
            optu = 1
        elif opt == '-c':
            optc = 1
        elif opt == '-d':
            optd = 1
    if optu == optc == optd == 0:
        optu = optc = optd = 1
    if not args:
        args = ['-']
    for file in args:
        if file == '-':
            readinput(sys.stdin)
        else:
            readinput(open(file, 'r'))
    #
    warndups()
    #
    more = (optu + optc + optd > 1)
    if optd:
        if more:
            print '---------------All callees------------------'
        printcallee()
    if optu:
        if more:
            print '---------------Undefined callees------------'
        printundef()
    if optc:
        if more:
            print '---------------All Callers------------------'
        printcaller()
    return 0

# Call the main program.
# Use its return value as exit status.
# Catch interrupts to avoid stack trace.
#
try:
    sys.exit(main())
except KeyboardInterrupt:
    sys.exit(1)
