1#!/usr/bin/env python
2
3from __future__ import print_function
4
5import argparse
6import os
7import subprocess
8import sys
9import zipfile
10
11
12class ProcError(Exception):
13    def __init__(self, returncode, stderr):
14        self.returncode = returncode
15        self.stderr = stderr
16
17
18def check_output(command):
19    proc = subprocess.Popen(command,
20                            stdout=subprocess.PIPE,
21                            stderr=subprocess.PIPE)
22    stdout, stderr = proc.communicate()
23    if proc.returncode != 0:
24        raise ProcError(proc.returncode, stderr)
25    return stdout
26
27
28def process_file(dump_syms, path):
29    try:
30        stdout = check_output([dump_syms, path])
31    except ProcError as e:
32        print('Error: running "%s %s": %s' % (dump_syms, path, e.stderr))
33        return None, None, None
34    bits = stdout.splitlines()[0].split(' ', 4)
35    if len(bits) != 5:
36        return None, None, None
37    _, platform, cpu_arch, debug_id, debug_file = bits
38    if debug_file.lower().endswith('.pdb'):
39        sym_file = debug_file[:-4] + '.sym'
40    else:
41        sym_file = debug_file + '.sym'
42    filename = os.path.join(debug_file, debug_id, sym_file)
43    debug_filename = os.path.join(debug_file, debug_id, debug_file)
44    return filename, stdout, debug_filename
45
46
47def main():
48    parser = argparse.ArgumentParser()
49    parser.add_argument('dump_syms', help='Path to dump_syms binary')
50    parser.add_argument('files', nargs='+',
51                        help='Path to files to dump symbols from')
52    parser.add_argument('--symbol-zip', default='symbols.zip',
53                        help='Name of zip file to put dumped symbols in')
54    parser.add_argument('--no-binaries',
55                        action='store_true',
56                        default=False,
57                        help='Don\'t store binaries in zip file')
58    args = parser.parse_args()
59    count = 0
60    with zipfile.ZipFile(args.symbol_zip, 'w', zipfile.ZIP_DEFLATED) as zf:
61        for f in args.files:
62            filename, contents, debug_filename = process_file(args.dump_syms, f)
63            if not (filename and contents):
64                print('Error dumping symbols')
65                sys.exit(1)
66            zf.writestr(filename, contents)
67            count += 1
68            if not args.no_binaries:
69                zf.write(f, debug_filename)
70                count += 1
71    print('Added %d files to %s' % (count, args.symbol_zip))
72
73if __name__ == '__main__':
74    main()
75