2013-11-26 13:23:50 +00:00
|
|
|
#!/usr/bin/env python
|
2014-10-31 18:17:05 +00:00
|
|
|
# Copyright (c) 2013 GitHub, Inc.
|
2013-11-26 13:23:50 +00:00
|
|
|
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
|
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
|
|
# found in the LICENSE file.
|
|
|
|
|
|
|
|
"""Convert pdb to sym for given directories"""
|
|
|
|
|
|
|
|
import errno
|
|
|
|
import glob
|
|
|
|
import optparse
|
|
|
|
import os
|
|
|
|
import Queue
|
|
|
|
import re
|
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
import threading
|
|
|
|
|
2018-10-08 20:19:40 +00:00
|
|
|
SRC_DIR = os.path.abspath(os.path.join(__file__, '..', '..', '..', '..'))
|
2018-09-28 05:56:33 +00:00
|
|
|
|
|
|
|
# Duplicated as this script lives in tools not script
|
|
|
|
def get_out_dir():
|
|
|
|
out_dir = 'Debug'
|
|
|
|
override = os.environ.get('ELECTRON_OUT_DIR')
|
|
|
|
if override is not None:
|
|
|
|
out_dir = override
|
2018-10-08 20:19:40 +00:00
|
|
|
return os.path.join(SRC_DIR, 'out', out_dir)
|
2018-09-28 05:56:33 +00:00
|
|
|
|
2013-11-26 13:23:50 +00:00
|
|
|
|
|
|
|
CONCURRENT_TASKS=4
|
2018-09-28 05:56:33 +00:00
|
|
|
OUT_DIR=get_out_dir()
|
|
|
|
DUMP_SYMS=os.path.join(OUT_DIR, 'dump_syms.exe')
|
2013-11-26 13:23:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
def GetCommandOutput(command):
|
|
|
|
"""Runs the command list, returning its output.
|
|
|
|
|
|
|
|
Prints the given command (which should be a list of one or more strings),
|
|
|
|
then runs it and returns its output (stdout) as a string.
|
|
|
|
|
|
|
|
From chromium_utils.
|
|
|
|
"""
|
|
|
|
devnull = open(os.devnull, 'w')
|
|
|
|
proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=devnull,
|
|
|
|
bufsize=1)
|
|
|
|
output = proc.communicate()[0]
|
|
|
|
return output
|
|
|
|
|
|
|
|
|
|
|
|
def mkdir_p(path):
|
|
|
|
"""Simulates mkdir -p."""
|
|
|
|
try:
|
|
|
|
os.makedirs(path)
|
|
|
|
except OSError as e:
|
|
|
|
if e.errno == errno.EEXIST and os.path.isdir(path):
|
|
|
|
pass
|
|
|
|
else: raise
|
|
|
|
|
|
|
|
|
|
|
|
def GenerateSymbols(options, binaries):
|
|
|
|
"""Dumps the symbols of binary and places them in the given directory."""
|
|
|
|
|
|
|
|
queue = Queue.Queue()
|
|
|
|
print_lock = threading.Lock()
|
|
|
|
|
|
|
|
def _Worker():
|
|
|
|
while True:
|
|
|
|
binary = queue.get()
|
|
|
|
|
|
|
|
if options.verbose:
|
|
|
|
with print_lock:
|
|
|
|
print "Generating symbols for %s" % binary
|
|
|
|
|
|
|
|
syms = GetCommandOutput([DUMP_SYMS, binary])
|
2014-07-25 10:00:05 +00:00
|
|
|
module_line = re.match("MODULE [^ ]+ [^ ]+ ([0-9A-Fa-f]+) (.*)\r\n", syms)
|
2013-11-26 13:23:50 +00:00
|
|
|
if module_line == None:
|
|
|
|
with print_lock:
|
|
|
|
print "Failed to get symbols for %s" % binary
|
|
|
|
queue.task_done()
|
|
|
|
continue
|
|
|
|
|
|
|
|
output_path = os.path.join(options.symbols_dir, module_line.group(2),
|
|
|
|
module_line.group(1))
|
|
|
|
mkdir_p(output_path)
|
2013-11-28 12:53:07 +00:00
|
|
|
symbol_file = "%s.sym" % module_line.group(2)[:-4] # strip .pdb
|
2013-11-26 13:23:50 +00:00
|
|
|
f = open(os.path.join(output_path, symbol_file), 'w')
|
|
|
|
f.write(syms)
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
queue.task_done()
|
|
|
|
|
|
|
|
for binary in binaries:
|
|
|
|
queue.put(binary)
|
|
|
|
|
|
|
|
for _ in range(options.jobs):
|
|
|
|
t = threading.Thread(target=_Worker)
|
|
|
|
t.daemon = True
|
|
|
|
t.start()
|
|
|
|
|
|
|
|
queue.join()
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
parser = optparse.OptionParser()
|
|
|
|
parser.add_option('', '--symbols-dir', default='',
|
|
|
|
help='The directory where to write the symbols file.')
|
|
|
|
parser.add_option('', '--clear', default=False, action='store_true',
|
|
|
|
help='Clear the symbols directory before writing new '
|
|
|
|
'symbols.')
|
|
|
|
parser.add_option('-j', '--jobs', default=CONCURRENT_TASKS, action='store',
|
|
|
|
type='int', help='Number of parallel tasks to run.')
|
|
|
|
parser.add_option('-v', '--verbose', action='store_true',
|
|
|
|
help='Print verbose status output.')
|
|
|
|
|
|
|
|
(options, directories) = parser.parse_args()
|
|
|
|
|
|
|
|
if not options.symbols_dir:
|
|
|
|
print "Required option --symbols-dir missing."
|
|
|
|
return 1
|
|
|
|
|
|
|
|
if options.clear:
|
|
|
|
try:
|
|
|
|
shutil.rmtree(options.symbols_dir)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
pdbs = []
|
|
|
|
for directory in directories:
|
2013-11-28 12:53:07 +00:00
|
|
|
pdbs += glob.glob(os.path.join(directory, '*.exe.pdb'))
|
|
|
|
pdbs += glob.glob(os.path.join(directory, '*.dll.pdb'))
|
2013-11-26 13:23:50 +00:00
|
|
|
|
|
|
|
GenerateSymbols(options, pdbs)
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
if '__main__' == __name__:
|
|
|
|
sys.exit(main())
|