#!/usr/bin/python # vim: tabstop=8 softtabstop=4 shiftwidth=4 nocindent smartindent import os, sys import sqlite3 def setup_database(): """Create a database to hold the data""" global conn global curs if os.path.exists("xref.sqlite"): os.remove("xref.sqlite") conn = sqlite3.connect("xref.sqlite") curs = conn.cursor() curs.execute("CREATE TABLE libtab (name TEXT)") curs.execute("CREATE TABLE objtab (name TEXT, lib_id INTEGER)") curs.execute("CREATE INDEX objidx ON objtab ( name )") curs.execute("CREATE TABLE symtab (name TEXT, usage CHAR, obj_id INTEGER)") curs.execute("CREATE INDEX symidx ON symtab ( name )") curs.execute("CREATE VIEW defs AS SELECT DISTINCT s.name sym, s.obj_id mod FROM symtab s WHERE s.usage != 'U'"); curs.execute("CREATE VIEW refs AS SELECT DISTINCT s.name sym, s.obj_id mod FROM symtab s WHERE s.usage = 'U'"); def get_one_object(arg): line = arg.strip() line = os.path.realpath(os.path.abspath(line)) if line.endswith(".a"): head, tail = os.path.split(line) if libraries.has_key(tail): if head in libraries[tail]: print "Skipping duplicate library:", line else: libraries[tail].append(head) else: libraries[tail] = [head] elif line.endswith(".o"): head, tail = os.path.split(line) if objects.has_key(tail): if head in objects[tail]: print "Skipping duplicate object:", line else: objects[tail].append(head) else: objects[tail] = [head] else: print "Unknown file type:", line def get_objects(arg): """Get all .a and .o files into libraries and objects""" global libraries global objects if os.path.isfile(arg): get_one_object(arg) return if os.path.isdir(arg): lines = os.popen("find -H " + arg + " -name *.a -o -name *.o") for line in lines: get_one_object(line) else: print "Unrecognised argument:", arg def report_duplicates(): """report all duplicate libraries and objects""" global libraries global objects for lib in libraries.keys(): if len(libraries[lib]) > 1: print "Duplicate Library:", str(len(libraries[lib])), lib, libraries[lib] for obj in objects.keys(): if len(objects[obj]) > 1: print "Duplicate Object:", str(len(objects[obj])), obj, objects[obj] def process_library(path, lib): global dict_fm global dict_sm global dict_sf arg = os.path.join(path, lib) print 'lib -> ', arg curs.execute("insert into libtab values (:1)", (arg,)) lib_id = curs.lastrowid conn.commit() for line in os.popen('nm ' + arg): while len(line) > 0 and (line[-1] in (' ', '\n', '\r')): line = line[0:-1] if len(line) > 0: if line[-1] == ':': file = line[0:-1] file_path = os.path.join(path, file) curs.execute("insert into objtab values (:1, :2)", (file_path, lib_id)) obj_id = curs.lastrowid dict_fm[os.path.split(file)[1]] = os.path.split(arg)[1] remove_object(path, file) elif len(line) > 10: value = line[0:8] tag = line[9:10] name = line[11:] if tag in ("B", "D", "G", "R", "S", "T", "U"): curs.execute("insert into symtab values (:1, :2, :3)", (name, tag, obj_id)) if not tag == 'U': dict_sf[name] = os.path.split(file)[1] dict_sm[name] = os.path.split(arg)[1] conn.commit() def process_libraries(): for lib in libraries.keys(): for path in libraries[lib]: process_library(path, lib) def process_object(path, obj): global dict_sf arg = os.path.join(path, obj) print 'obj -> ', arg file = arg curs.execute("insert into objtab values (:1, :2)", (file, 0)) obj_id = curs.lastrowid conn.commit() for line in os.popen('nm ' + arg): while len(line) > 0 and (line[-1] in (' ', '\n', '\r')): line = line[0:-1] if len(line) > 10: value = line[0:8] tag = line[9:10] name = line[11:] if tag in ("B", "D", "G", "R", "S", "T", "U"): curs.execute("insert into symtab values (:1, :2, :3)", (name, tag, obj_id)) if not tag == 'U': dict_sf[name] = os.path.split(file)[1] conn.commit() def remove_object(path, file): if objects.has_key(file): del objects[file] # if len(objects[file]) == 1 and objects[file][0] == path: # del objects[file] # elif path in objects[file]: # del objects[file][objects[file].index(path)] def process_objects(): for obj in objects.keys(): for path in objects[obj]: process_object(path, obj) args = sys.argv progname = args[0] del args[0] print 'prog ->', progname print 'args ->', args setup_database() libraries = {} objects = {} dict_sf = {} dict_sm = {} dict_fm = {} for arg in args: get_objects(arg) report_duplicates() print "Libraries:", libraries process_libraries() print "Objects:", objects process_objects() conn.commit() #graph = {} #build_graph() #plot_modules() #print "dict_sf = ", dict_sf #print "dict_sm = ", dict_sm #print "dict_fm = ", dict_fm if dict_sf.has_key("main"): print "main is in file", dict_sf["main"] if dict_sm.has_key("main"): print "main is in library", dict_sm["main"] curs.execute("""CREATE VIEW v AS SELECT distinct a.name from_name, b.name to_name FROM defs, refs, objtab a, objtab b WHERE refs.mod = a.rowid and refs.sym = defs.sym and defs.mod = b.rowid and refs.mod != defs.mod """) curs.execute("""CREATE VIEW vnum AS SELECT distinct a.name from_name, b.name to_name, defs.sym sym FROM defs, refs, objtab a, objtab b WHERE refs.mod = a.rowid and refs.sym = defs.sym and defs.mod = b.rowid and refs.mod != defs.mod """) curs.execute("""CREATE VIEW level_1 AS SELECT DISTINCT to_name name FROM v WHERE to_name NOT IN (SELECT DISTINCT from_name FROM v) """) curs.execute("CREATE TABLE associations AS SELECT * from v") curs.execute("CREATE TABLE linkages AS SELECT * from vnum")