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

Side by Side Diff: tools/symsrc/source_index.py

Issue 155136: Add the symbol and source server scripts. (Closed)
Patch Set: review feedback Created 11 years, 5 months 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 | « tools/symsrc/pefile.py ('k') | 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 #!/usr/bin/env python
2
3 # Copyright (c) 2008 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 """Usage: <win-path-to-pdb.pdb>
8 This tool will take a PDB on the command line, extract the source files that
9 were used in building the PDB, query SVN for which repository and revision
10 these files are at, and then finally write this information back into the PDB
11 in a format that the debugging tools understand. This allows for automatic
12 source debugging, as all of the information is contained in the PDB, and the
13 debugger can go out and fetch the source files via SVN.
14
15 You most likely want to run these immediately after a build, since the source
16 input files need to match the generated PDB, and we want the correct SVN
17 revision information for the exact files that were used for the build.
18
19 The following files from a windbg + source server installation are expected
20 to reside in the same directory as this python script:
21 dbghelp.dll
22 pdbstr.exe
23 srctool.exe
24
25 NOTE: Expected to run under a native win32 python, NOT cygwin. All paths are
26 dealt with as win32 paths, since we have to interact with the Microsoft tools.
27 """
28
29 import sys
30 import os
31 import time
32 import subprocess
33 import tempfile
34
35 # This serves two purposes. First, it acts as a whitelist, and only files
36 # from repositories listed here will be source indexed. Second, it allows us
37 # to map from one SVN URL to another, so we can map to external SVN servers.
38 REPO_MAP = {
39 "svn://chrome-svn/chrome": "http://src.chromium.org/svn",
40 "svn://chrome-svn.corp.google.com/chrome": "http://src.chromium.org/svn",
41 "http://v8.googlecode.com/svn": None,
42 "http://google-breakpad.googlecode.com/svn": None,
43 "http://googletest.googlecode.com/svn": None,
44 "http://open-vcdiff.googlecode.com/svn": None,
45 "http://google-url.googlecode.com/svn": None,
46 }
47
48 def FindFile(filename):
49 """Return the full windows path to a file in the same dir as this code."""
50 thisdir = os.path.dirname(os.path.join(os.path.curdir, __file__))
51 return os.path.abspath(os.path.join(thisdir, filename))
52
53
54 def ExtractSourceFiles(pdb_filename):
55 """Extract a list of local paths of the source files from a PDB."""
56 srctool = subprocess.Popen([FindFile('srctool.exe'), '-r', pdb_filename],
57 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
58 filelist = srctool.stdout.read()
59 res = srctool.wait()
60 if res != 0 or filelist.startswith("srctool: "):
61 raise "srctool failed: " + filelist
62 return [x for x in filelist.split('\r\n') if len(x) != 0]
63
64 def ReadSourceStream(pdb_filename):
65 """Read the contents of the source information stream from a PDB."""
66 srctool = subprocess.Popen([FindFile('pdbstr.exe'),
67 '-r', '-s:srcsrv',
68 '-p:%s' % pdb_filename],
69 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
70 data = srctool.stdout.read()
71 res = srctool.wait()
72
73 if (res != 0 and res != -1) or data.startswith("pdbstr: "):
74 raise "pdbstr failed: " + data
75 return data
76
77 def WriteSourceStream(pdb_filename, data):
78 """Write the contents of the source information stream to a PDB."""
79 # Write out the data to a temporary filename that we can pass to pdbstr.
80 (f, fname) = tempfile.mkstemp()
81 f = os.fdopen(f, "wb")
82 f.write(data)
83 f.close()
84
85 srctool = subprocess.Popen([FindFile('pdbstr.exe'),
86 '-w', '-s:srcsrv',
87 '-i:%s' % fname,
88 '-p:%s' % pdb_filename],
89 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
90 data = srctool.stdout.read()
91 res = srctool.wait()
92
93 if (res != 0 and res != -1) or data.startswith("pdbstr: "):
94 raise "pdbstr failed: " + data
95
96 os.unlink(fname)
97
98 # TODO for performance, we should probably work in directories instead of
99 # files. I'm scared of DEPS and generated files, so for now we query each
100 # individual file, and don't make assumptions that all files in the same
101 # directory are part of the same repository or at the same revision number.
102 def ExtractSvnInfo(local_filename):
103 """Calls svn info to extract the repository, path, and revision."""
104 # We call svn.bat to make sure and get the depot tools SVN and not cygwin.
105 srctool = subprocess.Popen(['svn.bat', 'info', local_filename],
106 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
107 info = srctool.stdout.read()
108 res = srctool.wait()
109 if res != 0:
110 return None
111 # Hack up into a dictionary of the fields printed by svn info.
112 vals = dict((y.split(': ', 2) for y in info.split('\r\n') if y))
113
114 root = vals['Repository Root']
115 if not vals['URL'].startswith(root):
116 raise "URL is not inside of the repository root?!?"
117 path = vals['URL'][len(root):]
118 rev = int(vals['Revision'])
119
120 return [root, path, rev]
121
122 def UpdatePDB(pdb_filename):
123 """Update a pdb file with source information."""
124 dir_blacklist = { }
125 # TODO(deanm) look into "compressing" our output, by making use of vars
126 # and other things, so we don't need to duplicate the repo path and revs.
127 lines = [
128 'SRCSRV: ini ------------------------------------------------',
129 'VERSION=1',
130 'INDEXVERSION=2',
131 'VERCTRL=Subversion',
132 'DATETIME=%s' % time.asctime(),
133 'SRCSRV: variables ------------------------------------------',
134 'SVN_EXTRACT_TARGET=%targ%\%fnbksl%(%var3%)\%var4%\%fnfile%(%var1%)',
135 'SVN_EXTRACT_CMD=cmd /c svn cat "%var2%%var3%@%var4%" --non-interactive > "% svn_extract_target%"',
136 'SRCSRVTRG=%SVN_extract_target%',
137 'SRCSRVCMD=%SVN_extract_cmd%',
138 'SRCSRV: source files ---------------------------------------',
139 ]
140
141 if ReadSourceStream(pdb_filename):
142 raise "PDB already has source indexing information!"
143
144 filelist = ExtractSourceFiles(pdb_filename)
145 for filename in filelist:
146 filedir = os.path.dirname(filename)
147
148 print "Processing: %s" % filename
149 # This directory is blacklisted, either because it's not part of the SVN
150 # repository, or from one we're not interested in indexing.
151 if dir_blacklist.get(filedir, False):
152 print " skipping, directory is blacklisted."
153 continue
154
155 info = ExtractSvnInfo(filename)
156
157 # Skip the file if it's not under an svn repository. To avoid constantly
158 # querying SVN for files outside of SVN control (for example, the CRT
159 # sources), check if the directory is outside of SVN and blacklist it.
160 if not info:
161 if not ExtractSvnInfo(filedir):
162 dir_blacklist[filedir] = True
163 print " skipping, file is not in an SVN repository"
164 continue
165
166 root = info[0]
167 path = info[1]
168 rev = info[2]
169
170 # Check if file was from a svn repository we don't know about, or don't
171 # want to index. Blacklist the entire directory.
172 if not REPO_MAP.has_key(info[0]):
173 print " skipping, file is from an unknown SVN repository %s" % root
174 dir_blacklist[filedir] = True
175 continue
176
177 # We might want to map an internal repository URL to an external repository.
178 if REPO_MAP[root]:
179 root = REPO_MAP[root]
180
181 lines.append('%s*%s*%s*%s' % (filename, root, path, rev))
182 print " indexed file."
183
184 lines.append('SRCSRV: end ------------------------------------------------')
185
186 WriteSourceStream(pdb_filename, '\r\n'.join(lines))
187
188 if __name__ == '__main__':
189 if len(sys.argv) != 2:
190 print "usage: file.pdb"
191 sys.exit(1)
192
193 UpdatePDB(sys.argv[1])
OLDNEW
« no previous file with comments | « tools/symsrc/pefile.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698