1#!/usr/bin/env python
2
3import logging, os, re, subprocess, sys
4import os.path
5import pdb, pprint
6
7if len(sys.argv) < 4:
8    print("Usage:")
9    print("\tgen_sym_files.py <path to breakpad's dump_syms> <path to owncloud.app> <symbol output dir>")
10    print("")
11    print("Symbols will be created in './symbols'")
12    sys.exit(1)
13
14dump_symsPath = sys.argv[1]
15bundlePath = sys.argv[2]
16outPath = sys.argv[3]
17macOsDir = os.path.join(bundlePath, 'Contents', 'MacOS')
18pluginsDir = os.path.join(bundlePath, 'Contents', 'PlugIns')
19
20def resolvePath(input):
21    resolved = re.sub(r'@\w+', macOsDir, input)
22    return os.path.normpath(resolved)
23
24def extractDeps(macho):
25    deps = [macho]
26    otool = subprocess.Popen(['otool', '-L', macho], stdout=subprocess.PIPE)
27    for l in otool.communicate()[0].splitlines():
28        if 'is not an object file' in l:
29            return []
30        m = re.search(r'@[^\s]+', l)
31        if m:
32            path = resolvePath(m.group(0))
33            if not os.path.exists(path):
34                logging.warning("Non-existant file found in dependencies, ignoring: [%s]", path)
35                continue
36            deps.append(path)
37    return deps
38
39def findDeps():
40    deps = []
41    for f in os.listdir(macOsDir):
42        path = os.path.join(macOsDir, f)
43        if not os.path.islink(path):
44            deps += extractDeps(path)
45    for root, dirs, files in os.walk(pluginsDir):
46        for f in files:
47            path = os.path.join(root, f)
48            deps += extractDeps(path)
49    return sorted(set(deps))
50
51def dumpSyms(deps):
52    for dep in deps:
53        print("Generating symbols for [%s]" % dep)
54        with open('temp.sym', 'w') as temp:
55            subprocess.check_call([dump_symsPath, dep], stdout=temp)
56        with open('temp.sym', 'r') as temp:
57            header = temp.readline()
58            fields = header.split()
59            key, name = fields[3:5]
60        destDir = '%s/%s/%s/' % (outPath, name, key)
61        destPath = destDir + name + '.sym'
62        if os.path.exists(destPath):
63            logging.warning("Symbols already exist: [%s]", destPath)
64            continue
65        if not os.path.exists(destDir):
66            os.makedirs(destDir)
67        os.rename('temp.sym', destPath)
68
69def strip(deps):
70    for dep in deps:
71        print("Stripping symbols off [%s]" % dep)
72        subprocess.check_call(['strip', '-S', dep])
73
74print('=== Generating symbols for [%s] in [%s]' % (bundlePath, outPath))
75deps = findDeps()
76dumpSyms(deps)
77strip(deps)
78