Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(419)

Side by Side Diff: tools/win/linker_verbose_tracking.py

Issue 2564543003: Script for parsing of verbose linker output (Closed)
Patch Set: Comment fixes Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """
6 This script parses the /verbose output from the VC++ linker and uses it to
7 explain why a particular object file is being linked in. It parses records
8 like these:
9
10 Found "public: static void * __cdecl SkTLS::Get(void * (__cdecl*)(void),vo id (__cdecl*)(void *))" (?Get@SkTLS@@SAPAXP6APAXXZP6AXPAX@Z@Z)
11 Referenced in chrome_crash_reporter_client_win.obj
12 Referenced in skia.lib(SkError.obj)
13 Loaded skia.lib(SkTLS.obj)
14
15 and then uses the information to answer questions such as "why is SkTLS.obj
16 being linked in. In this case it was requested by SkError.obj, and the process
17 is then repeated for SkError.obj. It traces the dependency tree back to a file
18 that was specified on the command line. Typically that file is part of a
19 source_set, and if that source_set is causing unnecessary code and data to be
20 pulled in then changing it to a static_library may reduce the binary size. See
21 crrev.com/2556603002 for an example of a ~900 KB savings from such a change.
22
23 In other cases the source_set to static_library fix does not work because some
24 of the symbols are required, while others are pulling in unwanted object files.
25 In these cases it can be necessary to see what symbol is causing one object file
26 to reference another. Removing or moving the problematic symbol can fix the
27 problem. See crrev.com/2559063002 for an example of such a change.
28
29 One complication is that there are sometimes multiple source files with the
30 same name, such as crc.c, which can make analysis more difficult or
31 ambiguous. If this becomes a blocking issue they it may be necessary to
32 temporarily rename the source file.
33
34 Object file name matching is case sensitive.
35
36 Typical output when run on chrome.dll verbose link output is:
37
38 >python linker_verbose_tracking.py chrome_dll_verbose_01.txt chrome_browser_main
39 Database loaded - 11286 xrefs found
40 chrome_browser_main.obj referenced by
41 chrome_browser_main_win.obj for symbol public: virtual __thiscall Chrome BrowserMainParts::~ChromeBrowserMainParts(void)
42
43 chrome_browser_main_win.obj referenced by
44 chrome_content_browser_client.obj for symbol public: __thiscall ChromeBr owserMainPartsWin::ChromeBrowserMainPartsWin(struct content::MainFunctionParams const &)
45
46 chrome_content_browser_client.obj referenced by
47 Command-line obj file: chrome_main_delegate.obj for symbol public: __thi scall ChromeContentBrowserClient::ChromeContentBrowserClient(void)
48 """
49
50 import pdb
51 import re
52 import sys
53
54 def ParseVerbose(input_file):
55 obj_match = re.compile('.*\((.*)\.obj\)')
stanisc 2016/12/10 00:13:11 It would help to see a comment with an example of
brucedawson 2016/12/10 00:59:57 Done.
56
57 cross_refs = {}
58 cross_refed_symbols = {}
59
60 references = None
61 for line in open(input_file):
62 if line.startswith(' Found'):
63 references = []
64 # Grab the symbol name
65 symbol = line[13:line.find('"', 13)]
66 continue
67 if type(references) == type([]):
68 sub_line = line.strip()
69 match = obj_match.match(sub_line)
70 # See if the line is part of the list of places where this symbol was
71 # referenced
72 if sub_line.count('Referenced ') > 0:
73 if match:
74 # This indicates a match that is xxx.lib(yyy.obj), so a referencing
75 # .obj file that was itself
76 reference = match.groups()[0]
77 else:
78 # This indicates a match that is just a pure .obj file name
79 # I think this means that the .obj file was specified on the linker
80 # command line.
81 reference = ('Command-line obj file: ' +
82 sub_line[len('Referenced in '): -len('.obj')])
83 references.append(reference)
84 elif sub_line.count('Loaded ') > 0:
85 if match:
86 loaded = match.groups()[0]
87 cross_refs[loaded] = references
88 cross_refed_symbols[loaded] = symbol
89 references = None
90 if line.startswith('Finished pass 1'):
91 # Stop now because the remaining 90% of the verbose output is
92 # not of interest. Could probably use /VERBOSE:REF to trim out
93 # boring information.
94 break
95 return cross_refs, cross_refed_symbols
96
97
98 def TrackObj(cross_refs, cross_refed_symbols, obj_name):
99 if obj_name.lower().endswith('.obj'):
100 obj_name = obj_name[:-len('.obj')]
101
102 # Keep track of which references we've already followed.
103 tracked = {}
104
105 # Initial set of object files that we are tracking.
106 targets = [obj_name]
107 printed = False
108 for i in range(100):
109 new_targets = {}
110 for target in targets:
111 if not target in tracked:
112 tracked[target] = True
113 if target in cross_refs.keys():
114 printed = True
115 print '%s.obj referenced by' % target
116 for ref in cross_refs[target]:
117 symbol = cross_refed_symbols[target]
stanisc 2016/12/10 00:13:11 Does this need to be inside the inner for loop?
brucedawson 2016/12/10 00:59:57 Good point. And since it is invariant for the targ
118 print '\t%s.obj for symbol %s' % (ref, symbol)
119 new_targets[ref] = True
120 if len(new_targets) == 0:
121 break
122 print
123 targets = new_targets.keys()
124 if not printed:
125 print 'No references to %s.obj found.' % obj_name
126
127
128 def main():
129 if len(sys.argv) < 3:
130 print r'Usage: %s <verbose_output_file> <objfile>' % sys.argv[0]
131 print r'Sample: %s chrome_dll_verbose.txt SkTLS'
stanisc 2016/12/10 00:13:11 It looks like this also needs % sys.argv[0] argume
brucedawson 2016/12/10 00:59:57 Good catch. Done.
132 return 0
133 cross_refs, cross_refed_symbols = ParseVerbose(sys.argv[1])
134 print 'Database loaded - %d xrefs found' % len(cross_refs)
135 TrackObj(cross_refs, cross_refed_symbols, sys.argv[2])
136
137 if __name__ == '__main__':
138 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698