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