| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2008 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 # Usage: strip_save_dsym <whatever-arguments-you-would-pass-to-strip> | 7 # Usage: strip_save_dsym <whatever-arguments-you-would-pass-to-strip> |
| 8 # | 8 # |
| 9 # strip_save_dsym is a wrapper around the standard strip utility. Given an | 9 # strip_save_dsym is a wrapper around the standard strip utility. Given an |
| 10 # input Mach-O file, strip_save_dsym will save a copy of the file in a "fake" | 10 # input Mach-O file, strip_save_dsym will save a copy of the file in a "fake" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 import sys | 36 import sys |
| 37 import time | 37 import time |
| 38 | 38 |
| 39 # Returns a list of architectures contained in a Mach-O file. The file can be | 39 # Returns a list of architectures contained in a Mach-O file. The file can be |
| 40 # a universal (fat) file, in which case there will be one list element for | 40 # a universal (fat) file, in which case there will be one list element for |
| 41 # each contained architecture, or it can be a thin single-architecture Mach-O | 41 # each contained architecture, or it can be a thin single-architecture Mach-O |
| 42 # file, in which case the list will contain a single element identifying the | 42 # file, in which case the list will contain a single element identifying the |
| 43 # architecture. On error, returns an empty list. Determines the architecture | 43 # architecture. On error, returns an empty list. Determines the architecture |
| 44 # list by calling file. | 44 # list by calling file. |
| 45 def macho_archs(macho): | 45 def macho_archs(macho): |
| 46 macho_types = ["executable", |
| 47 "dynamically linked shared library", |
| 48 "bundle"] |
| 49 macho_types_re = "Mach-O (?:64-bit )?(?:" + "|".join(macho_types) + ")" |
| 50 |
| 46 file_cmd = subprocess.Popen(["/usr/bin/file", "-b", "--", macho], | 51 file_cmd = subprocess.Popen(["/usr/bin/file", "-b", "--", macho], |
| 47 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 52 stdout=subprocess.PIPE) |
| 48 | 53 |
| 49 archs = [] | 54 archs = [] |
| 50 | 55 |
| 51 type_line = file_cmd.stdout.readline() | 56 type_line = file_cmd.stdout.readline() |
| 52 type_match = re.match("^Mach-O executable (.*)$", type_line) | 57 type_match = re.match("^%s (.*)$" % macho_types_re, type_line) |
| 53 if type_match: | 58 if type_match: |
| 54 archs.append(type_match.group(1)) | 59 archs.append(type_match.group(1)) |
| 55 return [type_match.group(1)] | 60 return [type_match.group(1)] |
| 56 else: | 61 else: |
| 57 type_match = re.match("^Mach-O universal binary with (.*) architectures$", | 62 type_match = re.match("^Mach-O universal binary with (.*) architectures$", |
| 58 type_line) | 63 type_line) |
| 59 if type_match: | 64 if type_match: |
| 60 for i in range(0, int(type_match.group(1))): | 65 for i in range(0, int(type_match.group(1))): |
| 61 arch_line = file_cmd.stdout.readline() | 66 arch_line = file_cmd.stdout.readline() |
| 62 arch_match = re.match( | 67 arch_match = re.match( |
| 63 "^.* \(for architecture (.*)\):\tMach-O executable .*$", | 68 "^.* \(for architecture (.*)\):\t%s .*$" % macho_types_re, |
| 64 arch_line) | 69 arch_line) |
| 65 if arch_match: | 70 if arch_match: |
| 66 archs.append(arch_match.group(1)) | 71 archs.append(arch_match.group(1)) |
| 67 | 72 |
| 68 if file_cmd.wait() != 0: | 73 if file_cmd.wait() != 0: |
| 69 archs = [] | 74 archs = [] |
| 70 | 75 |
| 76 if len(archs) == 0: |
| 77 print >> sys.stderr, "No architectures in %s" % macho |
| 78 |
| 71 return archs | 79 return archs |
| 72 | 80 |
| 73 # Returns a dictionary mapping architectures contained in the file as returned | 81 # Returns a dictionary mapping architectures contained in the file as returned |
| 74 # by macho_archs to the LC_UUID load command for that architecture. | 82 # by macho_archs to the LC_UUID load command for that architecture. |
| 75 # Architectures with no LC_UUID load command are omitted from the dictionary. | 83 # Architectures with no LC_UUID load command are omitted from the dictionary. |
| 76 # Determines the UUID value by calling otool. | 84 # Determines the UUID value by calling otool. |
| 77 def macho_uuids(macho): | 85 def macho_uuids(macho): |
| 86 uuids = {} |
| 87 |
| 78 archs = macho_archs(macho) | 88 archs = macho_archs(macho) |
| 79 | 89 if len(archs) == 0: |
| 80 uuids = {} | 90 return uuids |
| 81 | 91 |
| 82 for arch in archs: | 92 for arch in archs: |
| 83 if arch == "": | 93 if arch == "": |
| 84 continue | 94 continue |
| 85 | 95 |
| 86 otool_cmd = subprocess.Popen(["/usr/bin/otool", "-arch", arch, "-l", "-", | 96 otool_cmd = subprocess.Popen(["/usr/bin/otool", "-arch", arch, "-l", "-", |
| 87 macho], | 97 macho], |
| 88 stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 98 stdout=subprocess.PIPE) |
| 89 # state 0 is when nothing UUID-related has been seen yet. State 1 is | 99 # state 0 is when nothing UUID-related has been seen yet. State 1 is |
| 90 # entered after a load command begins, but it may not be an LC_UUID load | 100 # entered after a load command begins, but it may not be an LC_UUID load |
| 91 # command. States 2, 3, and 4 are intermediate states while reading an | 101 # command. States 2, 3, and 4 are intermediate states while reading an |
| 92 # LC_UUID command. State 5 is the terminal state for a successful LC_UUID | 102 # LC_UUID command. State 5 is the terminal state for a successful LC_UUID |
| 93 # read. State 6 is the error state. | 103 # read. State 6 is the error state. |
| 94 state = 0 | 104 state = 0 |
| 95 uuid = "" | 105 uuid = "" |
| 96 for otool_line in otool_cmd.stdout: | 106 for otool_line in otool_cmd.stdout: |
| 97 if state == 0: | 107 if state == 0: |
| 98 if re.match("^Load command .*$", otool_line): | 108 if re.match("^Load command .*$", otool_line): |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 uuid_match.group(7) + uuid_match.group(8) | 141 uuid_match.group(7) + uuid_match.group(8) |
| 132 else: | 142 else: |
| 133 state = 6 | 143 state = 6 |
| 134 | 144 |
| 135 if otool_cmd.wait() != 0: | 145 if otool_cmd.wait() != 0: |
| 136 state = 6 | 146 state = 6 |
| 137 | 147 |
| 138 if state == 5: | 148 if state == 5: |
| 139 uuids[arch] = uuid.upper() | 149 uuids[arch] = uuid.upper() |
| 140 | 150 |
| 151 if len(uuids) == 0: |
| 152 print >> sys.stderr, "No UUIDs in %s" % macho |
| 153 |
| 141 return uuids | 154 return uuids |
| 142 | 155 |
| 143 # Given a path to a Mach-O file and possible information from the environment, | 156 # Given a path to a Mach-O file and possible information from the environment, |
| 144 # determines the desired path to the .dSYM. | 157 # determines the desired path to the .dSYM. |
| 145 def dsym_path(macho): | 158 def dsym_path(macho): |
| 146 # If building a bundle, the .dSYM should be placed next to the bundle. Use | 159 # If building a bundle, the .dSYM should be placed next to the bundle. Use |
| 147 # WRAPPER_NAME to make this determination. If called from xcodebuild, | 160 # WRAPPER_NAME to make this determination. If called from xcodebuild, |
| 148 # WRAPPER_NAME will be set to the name of the bundle. | 161 # WRAPPER_NAME will be set to the name of the bundle. |
| 149 dsym = "" | 162 dsym = "" |
| 150 if "WRAPPER_NAME" in os.environ: | 163 if "WRAPPER_NAME" in os.environ: |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 | 315 |
| 303 if macho is None: | 316 if macho is None: |
| 304 print >> sys.stderr, "Nothing to strip" | 317 print >> sys.stderr, "Nothing to strip" |
| 305 return 1 | 318 return 1 |
| 306 | 319 |
| 307 if not strip_and_make_fake_dsym(macho): | 320 if not strip_and_make_fake_dsym(macho): |
| 308 return 1 | 321 return 1 |
| 309 | 322 |
| 310 return 0 | 323 return 0 |
| 311 | 324 |
| 312 if __name__ == '__main__': | 325 if __name__ == "__main__": |
| 313 sys.exit(main(sys.argv)) | 326 sys.exit(main(sys.argv)) |
| OLD | NEW |