Skip to content

Instantly share code, notes, and snippets.

@luser
Created March 6, 2015 21:04
Show Gist options
  • Save luser/015626821a00e819e5f9 to your computer and use it in GitHub Desktop.
Save luser/015626821a00e819e5f9 to your computer and use it in GitHub Desktop.
Fetch and convert PDB files from Microsoft's symbol server to Breakpad .sym format
#!/usr/bin/env python
import distutils.spawn
import os
import requests
import shutil
import subprocess
import sys
import tempfile
import urlparse
URL = 'http://msdl.microsoft.com/download/symbols/'
USER_AGENT = 'Microsoft-Symbol-Server/6.3.0.0'
dump_syms_command = ['wine64', 'dump_syms.exe']
def fetch_symbol(debug_id, debug_file):
'''
Attempt to fetch a PDB file from Microsoft's symbol server.
'''
url = urlparse.urljoin(URL, os.path.join(debug_file,
debug_id,
debug_file[:-1] + '_'))
r = requests.get(url,
headers={'User-Agent': USER_AGENT})
if r.status_code == 200:
return r.content
return None
def fetch_and_dump_symbols(tmpdir, debug_id, debug_file):
pdb_bytes = fetch_symbol(debug_id, debug_file)
if not pdb_bytes or not pdb_bytes.startswith(b'MSCF'):
return False
pdb_path = os.path.join(tmpdir, debug_file[:-1] + '_')
with open(pdb_path, 'wb') as f:
f.write(pdb_bytes)
try:
# Decompress it
subprocess.check_call(['cabextract', '-d', tmpdir, pdb_path])
pdb_path = os.path.join(tmpdir, debug_file)
# Dump it
return subprocess.check_output(dump_syms_command + [pdb_path])
except subprocess.CalledProcessError:
return None
def main():
cabextract = distutils.spawn.find_executable('cabextract')
if not cabextract:
# error
pass
files = [
('69DDFBCBBC14421D8CB974F8EDC414102', 'wntdll.pdb'),
('0FCE9CC301ED4567A819705B2718E1D62', 'wuser32.pdb')
]
tmpdir = tempfile.mkdtemp(prefix='symbols')
try:
for debug_id, debug_file in files:
symbols = fetch_and_dump_symbols(tmpdir, debug_id, debug_file)
if not symbols:
continue
dirs = os.path.join(tmpdir, 'symbols', debug_file, debug_id)
os.makedirs(dirs)
with open(os.path.join(dirs, debug_file[:-4] + '.sym'), 'w') as f:
f.write(symbols)
finally:
pass
#shutil.rmtree(tmpdir)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment