From a356bcdc6b6d4fb9eca4b342585d57bbc7b32293 Mon Sep 17 00:00:00 2001 From: Douglas Clowes Date: Thu, 1 Aug 2013 16:56:22 +1000 Subject: [PATCH] Add xref to populate an sqlite database with a program cross-reference --- .gitignore | 1 + site_ansto/xref.py | 192 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100755 site_ansto/xref.py diff --git a/.gitignore b/.gitignore index 14163b07..47effe16 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ CVSPSI *.o *.d *.out +*.sqlite diff --git a/site_ansto/xref.py b/site_ansto/xref.py new file mode 100755 index 00000000..f8c32c68 --- /dev/null +++ b/site_ansto/xref.py @@ -0,0 +1,192 @@ +#!/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'"); + 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 + """) + +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"] +