| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 6 | 5 |
| 7 """Usage: <win-path-to-pdb.pdb> | 6 """Usage: <win-path-to-pdb.pdb> |
| 8 This tool will take a PDB on the command line, extract the source files that | 7 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 | 8 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 | 9 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 | 10 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 | 11 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. | 12 debugger can go out and fetch the source files via SVN. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 38 REPO_MAP = { | 37 REPO_MAP = { |
| 39 "svn://chrome-svn/chrome": "http://src.chromium.org/svn", | 38 "svn://chrome-svn/chrome": "http://src.chromium.org/svn", |
| 40 "svn://chrome-svn.corp.google.com/chrome": "http://src.chromium.org/svn", | 39 "svn://chrome-svn.corp.google.com/chrome": "http://src.chromium.org/svn", |
| 41 "http://v8.googlecode.com/svn": None, | 40 "http://v8.googlecode.com/svn": None, |
| 42 "http://google-breakpad.googlecode.com/svn": None, | 41 "http://google-breakpad.googlecode.com/svn": None, |
| 43 "http://googletest.googlecode.com/svn": None, | 42 "http://googletest.googlecode.com/svn": None, |
| 44 "http://open-vcdiff.googlecode.com/svn": None, | 43 "http://open-vcdiff.googlecode.com/svn": None, |
| 45 "http://google-url.googlecode.com/svn": None, | 44 "http://google-url.googlecode.com/svn": None, |
| 46 } | 45 } |
| 47 | 46 |
| 47 |
| 48 def FindFile(filename): | 48 def FindFile(filename): |
| 49 """Return the full windows path to a file in the same dir as this code.""" | 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__)) | 50 thisdir = os.path.dirname(os.path.join(os.path.curdir, __file__)) |
| 51 return os.path.abspath(os.path.join(thisdir, filename)) | 51 return os.path.abspath(os.path.join(thisdir, filename)) |
| 52 | 52 |
| 53 | 53 |
| 54 def ExtractSourceFiles(pdb_filename): | 54 def ExtractSourceFiles(pdb_filename): |
| 55 """Extract a list of local paths of the source files from a PDB.""" | 55 """Extract a list of local paths of the source files from a PDB.""" |
| 56 srctool = subprocess.Popen([FindFile('srctool.exe'), '-r', pdb_filename], | 56 srctool = subprocess.Popen([FindFile('srctool.exe'), '-r', pdb_filename], |
| 57 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 57 stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 58 filelist = srctool.stdout.read() | 58 filelist = srctool.stdout.read() |
| 59 res = srctool.wait() | 59 res = srctool.wait() |
| 60 if res != 0 or filelist.startswith("srctool: "): | 60 if res != 0 or filelist.startswith("srctool: "): |
| 61 raise "srctool failed: " + filelist | 61 raise "srctool failed: " + filelist |
| 62 return [x for x in filelist.split('\r\n') if len(x) != 0] | 62 return [x for x in filelist.split('\r\n') if len(x) != 0] |
| 63 | 63 |
| 64 |
| 64 def ReadSourceStream(pdb_filename): | 65 def ReadSourceStream(pdb_filename): |
| 65 """Read the contents of the source information stream from a PDB.""" | 66 """Read the contents of the source information stream from a PDB.""" |
| 66 srctool = subprocess.Popen([FindFile('pdbstr.exe'), | 67 srctool = subprocess.Popen([FindFile('pdbstr.exe'), |
| 67 '-r', '-s:srcsrv', | 68 '-r', '-s:srcsrv', |
| 68 '-p:%s' % pdb_filename], | 69 '-p:%s' % pdb_filename], |
| 69 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 70 stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 70 data = srctool.stdout.read() | 71 data = srctool.stdout.read() |
| 71 res = srctool.wait() | 72 res = srctool.wait() |
| 72 | 73 |
| 73 if (res != 0 and res != -1) or data.startswith("pdbstr: "): | 74 if (res != 0 and res != -1) or data.startswith("pdbstr: "): |
| 74 raise "pdbstr failed: " + data | 75 raise "pdbstr failed: " + data |
| 75 return data | 76 return data |
| 76 | 77 |
| 78 |
| 77 def WriteSourceStream(pdb_filename, data): | 79 def WriteSourceStream(pdb_filename, data): |
| 78 """Write the contents of the source information stream to a PDB.""" | 80 """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. | 81 # Write out the data to a temporary filename that we can pass to pdbstr. |
| 80 (f, fname) = tempfile.mkstemp() | 82 (f, fname) = tempfile.mkstemp() |
| 81 f = os.fdopen(f, "wb") | 83 f = os.fdopen(f, "wb") |
| 82 f.write(data) | 84 f.write(data) |
| 83 f.close() | 85 f.close() |
| 84 | 86 |
| 85 srctool = subprocess.Popen([FindFile('pdbstr.exe'), | 87 srctool = subprocess.Popen([FindFile('pdbstr.exe'), |
| 86 '-w', '-s:srcsrv', | 88 '-w', '-s:srcsrv', |
| 87 '-i:%s' % fname, | 89 '-i:%s' % fname, |
| 88 '-p:%s' % pdb_filename], | 90 '-p:%s' % pdb_filename], |
| 89 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 91 stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 90 data = srctool.stdout.read() | 92 data = srctool.stdout.read() |
| 91 res = srctool.wait() | 93 res = srctool.wait() |
| 92 | 94 |
| 93 if (res != 0 and res != -1) or data.startswith("pdbstr: "): | 95 if (res != 0 and res != -1) or data.startswith("pdbstr: "): |
| 94 raise "pdbstr failed: " + data | 96 raise "pdbstr failed: " + data |
| 95 | 97 |
| 96 os.unlink(fname) | 98 os.unlink(fname) |
| 97 | 99 |
| 100 |
| 98 # TODO for performance, we should probably work in directories instead of | 101 # 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 | 102 # 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 | 103 # 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. | 104 # directory are part of the same repository or at the same revision number. |
| 102 def ExtractSvnInfo(local_filename): | 105 def ExtractSvnInfo(local_filename): |
| 103 """Calls svn info to extract the repository, path, and revision.""" | 106 """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. | 107 # 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], | 108 srctool = subprocess.Popen(['svn.bat', 'info', local_filename], |
| 106 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 109 stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 107 info = srctool.stdout.read() | 110 info = srctool.stdout.read() |
| 108 res = srctool.wait() | 111 res = srctool.wait() |
| 109 if res != 0: | 112 if res != 0: |
| 110 return None | 113 return None |
| 111 # Hack up into a dictionary of the fields printed by svn info. | 114 # 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)) | 115 vals = dict((y.split(': ', 2) for y in info.split('\r\n') if y)) |
| 113 | 116 |
| 114 root = vals['Repository Root'] | 117 root = vals['Repository Root'] |
| 115 if not vals['URL'].startswith(root): | 118 if not vals['URL'].startswith(root): |
| 116 raise "URL is not inside of the repository root?!?" | 119 raise "URL is not inside of the repository root?!?" |
| 117 path = vals['URL'][len(root):] | 120 path = vals['URL'][len(root):] |
| 118 rev = int(vals['Revision']) | 121 rev = int(vals['Revision']) |
| 119 | 122 |
| 120 return [root, path, rev] | 123 return [root, path, rev] |
| 121 | 124 |
| 125 |
| 122 def UpdatePDB(pdb_filename, verbose=False): | 126 def UpdatePDB(pdb_filename, verbose=False): |
| 123 """Update a pdb file with source information.""" | 127 """Update a pdb file with source information.""" |
| 124 dir_blacklist = { } | 128 dir_blacklist = { } |
| 125 # TODO(deanm) look into "compressing" our output, by making use of vars | 129 # 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. | 130 # and other things, so we don't need to duplicate the repo path and revs. |
| 127 lines = [ | 131 lines = [ |
| 128 'SRCSRV: ini ------------------------------------------------', | 132 'SRCSRV: ini ------------------------------------------------', |
| 129 'VERSION=1', | 133 'VERSION=1', |
| 130 'INDEXVERSION=2', | 134 'INDEXVERSION=2', |
| 131 'VERCTRL=Subversion', | 135 'VERCTRL=Subversion', |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 root = REPO_MAP[root] | 187 root = REPO_MAP[root] |
| 184 | 188 |
| 185 lines.append('%s*%s*%s*%s' % (filename, root, path, rev)) | 189 lines.append('%s*%s*%s*%s' % (filename, root, path, rev)) |
| 186 if verbose: | 190 if verbose: |
| 187 print " indexed file." | 191 print " indexed file." |
| 188 | 192 |
| 189 lines.append('SRCSRV: end ------------------------------------------------') | 193 lines.append('SRCSRV: end ------------------------------------------------') |
| 190 | 194 |
| 191 WriteSourceStream(pdb_filename, '\r\n'.join(lines)) | 195 WriteSourceStream(pdb_filename, '\r\n'.join(lines)) |
| 192 | 196 |
| 193 if __name__ == '__main__': | 197 |
| 198 def main(): |
| 194 if len(sys.argv) < 2 or len(sys.argv) > 3: | 199 if len(sys.argv) < 2 or len(sys.argv) > 3: |
| 195 print "usage: file.pdb [-v]" | 200 print "usage: file.pdb [-v]" |
| 196 sys.exit(1) | 201 return 1 |
| 197 | 202 |
| 198 verbose = False | 203 verbose = False |
| 199 if len(sys.argv) == 3: | 204 if len(sys.argv) == 3: |
| 200 verbose = (sys.argv[2] == '-v') | 205 verbose = (sys.argv[2] == '-v') |
| 201 | 206 |
| 202 UpdatePDB(sys.argv[1], verbose=verbose) | 207 UpdatePDB(sys.argv[1], verbose=verbose) |
| 208 return 0 |
| 209 |
| 210 |
| 211 if __name__ == '__main__': |
| 212 sys.exit(main()) |
| OLD | NEW |