#! /usr/bin/env python3# objgraph## Read "nm -o" input 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# e.g.: nm -o /lib/libc.a | objgraphimport sysimport osimport getoptimport re# Types of symbols.#definitions = 'TRGDSBAEC'externals = 'UV'ignore = 'Nntrgdsbavuc'# Regular expression to parse "nm -o" output.#matcher = re.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 key in dict: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 + ' ' + itemreturn 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(fp):while 1:s = fp.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 = sorted(file2undef.keys())for filename in flist:print(filename + ':')elist = file2undef[filename]elist.sort()for ext in elist:if len(ext) >= 8:tabs = '\t'else:tabs = '\t\t'if ext not in def2file: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 = sorted(file2def.keys())for filename in files:callers = []for label in file2def[filename]:if label in undef2file:callers = callers + undef2file[label]if callers:callers.sort()print(filename + ':')lastfn = ''for fn in callers:if fn != lastfn:print('\t' + fn)lastfn = fnelse:print(filename + ': unused')# Print undefined names and where they are used.#def printundef():undefs = {}for filename in list(file2undef.keys()):for ext in file2undef[filename]:if ext not in def2file:store(undefs, ext, filename)elist = sorted(undefs.keys())for ext in elist:print(ext + ':')flist = sorted(undefs[ext])for filename in flist:print('\t' + filename)# Print warning messages about names defined in more than one file.#def warndups():savestdout = sys.stdoutsys.stdout = sys.stderrnames = sorted(def2file.keys())for name in names:if len(def2file[name]) > 1:print('warning:', name, 'multiply defined:', end=' ')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.stderrprint('Usage:', os.path.basename(sys.argv[0]), end=' ')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')print('e.g.: nm -o /lib/libc.a | objgraph')return 1optu = optc = optd = 0for opt, void in optlist:if opt == '-u':optu = 1elif opt == '-c':optc = 1elif opt == '-d':optd = 1if optu == optc == optd == 0:optu = optc = optd = 1if not args:args = ['-']for filename in args:if filename == '-':readinput(sys.stdin)else:with open(filename) as f:readinput(f)#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.#if __name__ == '__main__':try:sys.exit(main())except KeyboardInterrupt:sys.exit(1)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。