193 lines
6.1 KiB
Python
Executable File
193 lines
6.1 KiB
Python
Executable File
#!/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"]
|
|
|