History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Tools/scripts/objgraph.py (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Tools/scripts/objgraph.py+215−0
@@ -0,0 +1,215 @@
1+#! /usr/bin/env python
2+
3+# objgraph
4+#
5+# Read "nm -o" input (on IRIX: "nm -Bo") of a set of libraries or modules
6+# and print various interesting listings, such as:
7+#
8+# - which names are used but not defined in the set (and used where),
9+# - which names are defined in the set (and where),
10+# - which modules use which other modules,
11+# - which modules are used by which other modules.
12+#
13+# Usage: objgraph [-cdu] [file] ...
14+# -c: print callers per objectfile
15+# -d: print callees per objectfile
16+# -u: print usage of undefined symbols
17+# If none of -cdu is specified, all are assumed.
18+# Use "nm -o" to generate the input (on IRIX: "nm -Bo"),
19+# e.g.: nm -o /lib/libc.a | objgraph
20+
21+
22+import sys
23+import os
24+import getopt
25+import re
26+
27+# Types of symbols.
28+#
29+definitions = 'TRGDSBAEC'
30+externals = 'UV'
31+ignore = 'Nntrgdsbavuc'
32+
33+# Regular expression to parse "nm -o" output.
34+#
35+matcher = re.compile('(.*):\t?........ (.) (.*)$')
36+
37+# Store "item" in "dict" under "key".
38+# The dictionary maps keys to lists of items.
39+# If there is no list for the key yet, it is created.
40+#
41+def store(dict, key, item):
42+ if dict.has_key(key):
43+ dict[key].append(item)
44+ else:
45+ dict[key] = [item]
46+
47+# Return a flattened version of a list of strings: the concatenation
48+# of its elements with intervening spaces.
49+#
50+def flat(list):
51+ s = ''
52+ for item in list:
53+ s = s + ' ' + item
54+ return s[1:]
55+
56+# Global variables mapping defined/undefined names to files and back.
57+#
58+file2undef = {}
59+def2file = {}
60+file2def = {}
61+undef2file = {}
62+
63+# Read one input file and merge the data into the tables.
64+# Argument is an open file.
65+#
66+def readinput(fp):
67+ while 1:
68+ s = fp.readline()
69+ if not s:
70+ break
71+ # If you get any output from this line,
72+ # it is probably caused by an unexpected input line:
73+ if matcher.search(s) < 0: s; continue # Shouldn't happen
74+ (ra, rb), (r1a, r1b), (r2a, r2b), (r3a, r3b) = matcher.regs[:4]
75+ fn, name, type = s[r1a:r1b], s[r3a:r3b], s[r2a:r2b]
76+ if type in definitions:
77+ store(def2file, name, fn)
78+ store(file2def, fn, name)
79+ elif type in externals:
80+ store(file2undef, fn, name)
81+ store(undef2file, name, fn)
82+ elif not type in ignore:
83+ print fn + ':' + name + ': unknown type ' + type
84+
85+# Print all names that were undefined in some module and where they are
86+# defined.
87+#
88+def printcallee():
89+ flist = file2undef.keys()
90+ flist.sort()
91+ for filename in flist:
92+ print filename + ':'
93+ elist = file2undef[filename]
94+ elist.sort()
95+ for ext in elist:
96+ if len(ext) >= 8:
97+ tabs = '\t'
98+ else:
99+ tabs = '\t\t'
100+ if not def2file.has_key(ext):
101+ print '\t' + ext + tabs + ' *undefined'
102+ else:
103+ print '\t' + ext + tabs + flat(def2file[ext])
104+
105+# Print for each module the names of the other modules that use it.
106+#
107+def printcaller():
108+ files = file2def.keys()
109+ files.sort()
110+ for filename in files:
111+ callers = []
112+ for label in file2def[filename]:
113+ if undef2file.has_key(label):
114+ callers = callers + undef2file[label]
115+ if callers:
116+ callers.sort()
117+ print filename + ':'
118+ lastfn = ''
119+ for fn in callers:
120+ if fn <> lastfn:
121+ print '\t' + fn
122+ lastfn = fn
123+ else:
124+ print filename + ': unused'
125+
126+# Print undefined names and where they are used.
127+#
128+def printundef():
129+ undefs = {}
130+ for filename in file2undef.keys():
131+ for ext in file2undef[filename]:
132+ if not def2file.has_key(ext):
133+ store(undefs, ext, filename)
134+ elist = undefs.keys()
135+ elist.sort()
136+ for ext in elist:
137+ print ext + ':'
138+ flist = undefs[ext]
139+ flist.sort()
140+ for filename in flist:
141+ print '\t' + filename
142+
143+# Print warning messages about names defined in more than one file.
144+#
145+def warndups():
146+ savestdout = sys.stdout
147+ sys.stdout = sys.stderr
148+ names = def2file.keys()
149+ names.sort()
150+ for name in names:
151+ if len(def2file[name]) > 1:
152+ print 'warning:', name, 'multiply defined:',
153+ print flat(def2file[name])
154+ sys.stdout = savestdout
155+
156+# Main program
157+#
158+def main():
159+ try:
160+ optlist, args = getopt.getopt(sys.argv[1:], 'cdu')
161+ except getopt.error:
162+ sys.stdout = sys.stderr
163+ print 'Usage:', os.path.basename(sys.argv[0]),
164+ print '[-cdu] [file] ...'
165+ print '-c: print callers per objectfile'
166+ print '-d: print callees per objectfile'
167+ print '-u: print usage of undefined symbols'
168+ print 'If none of -cdu is specified, all are assumed.'
169+ print 'Use "nm -o" to generate the input (on IRIX: "nm -Bo"),'
170+ print 'e.g.: nm -o /lib/libc.a | objgraph'
171+ return 1
172+ optu = optc = optd = 0
173+ for opt, void in optlist:
174+ if opt == '-u':
175+ optu = 1
176+ elif opt == '-c':
177+ optc = 1
178+ elif opt == '-d':
179+ optd = 1
180+ if optu == optc == optd == 0:
181+ optu = optc = optd = 1
182+ if not args:
183+ args = ['-']
184+ for filename in args:
185+ if filename == '-':
186+ readinput(sys.stdin)
187+ else:
188+ readinput(open(filename, 'r'))
189+ #
190+ warndups()
191+ #
192+ more = (optu + optc + optd > 1)
193+ if optd:
194+ if more:
195+ print '---------------All callees------------------'
196+ printcallee()
197+ if optu:
198+ if more:
199+ print '---------------Undefined callees------------'
200+ printundef()
201+ if optc:
202+ if more:
203+ print '---------------All Callers------------------'
204+ printcaller()
205+ return 0
206+
207+# Call the main program.
208+# Use its return value as exit status.
209+# Catch interrupts to avoid stack trace.
210+#
211+if __name__ == '__main__':
212+ try:
213+ sys.exit(main())
214+ except KeyboardInterrupt:
215+ sys.exit(1)