Bug 1051190 - Copy and package ASan dylib on OSX. r=ted
authorChristian Holler <choller@mozilla.com>
Mon, 01 Sep 2014 14:34:23 +0200
changeset 202815 3fcf08e891faafb3dfd28253d1e47ba32dc611ae
parent 202814 5ca3c0880050470ad429d980ce46a8d644a59c5b
child 202816 5fa26de0a04fcf3f6e44de54f143fbb9cda38004
push id48500
push usercholler@mozilla.com
push dateMon, 01 Sep 2014 20:10:41 +0000
treeherdermozilla-inbound@3fcf08e891fa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1051190
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1051190 - Copy and package ASan dylib on OSX. r=ted
build/unix/rewrite_asan_dylib.py
toolkit/mozapps/installer/packager.mk
new file mode 100644
--- /dev/null
+++ b/build/unix/rewrite_asan_dylib.py
@@ -0,0 +1,59 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import sys
+import os
+import subprocess
+import shutil
+
+'''
+Scans the given directories for binaries referencing the AddressSanitizer
+runtime library, copies it to the main directory and rewrites binaries to not
+reference it with absolute paths but with @executable_path instead.
+'''
+
+# This is the dylib we're looking for
+DYLIB_NAME='libclang_rt.asan_osx_dynamic.dylib'
+
+def scan_directory(path):
+    dylibCopied = False
+
+    for root, subdirs, files in os.walk(path):
+        for filename in files:
+            filename = os.path.join(root, filename)
+
+            # Skip all files that aren't either dylibs or executable
+            if not (filename.endswith('.dylib') or os.access(filename, os.X_OK)):
+                continue
+
+            try:
+                otoolOut = subprocess.check_output(['otool', '-L', filename])
+            except:
+                # Errors are expected on non-mach executables, ignore them and continue
+                continue
+
+            for line in otoolOut.splitlines():
+                if line.find(DYLIB_NAME) != -1:
+                    absDylibPath = line.split()[0]
+
+                    # Don't try to rewrite binaries twice
+                    if absDylibPath.find('@executable_path/') == 0:
+                        continue
+
+                    if not dylibCopied:
+                        # Copy the runtime once to the main directory, which is passed
+                        # as the argument to this function.
+                        shutil.copy(absDylibPath, path)
+
+                        # Now rewrite the library itself
+                        subprocess.check_call(['install_name_tool', '-id', '@executable_path/' + DYLIB_NAME, os.path.join(path, DYLIB_NAME)])
+                        dylibCopied = True
+
+                    # Now use install_name_tool to rewrite the path in our binary
+                    subprocess.check_call(['install_name_tool', '-change', absDylibPath, '@executable_path/' + DYLIB_NAME, filename])
+                    break
+
+if __name__ == '__main__':
+    for d in sys.argv[1:]:
+        scan_directory(d)
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -744,16 +744,22 @@ endif # MOZ_PACKAGE_JSSHELL
 endif # LIBXUL_SDK
 ifdef MOZ_CODE_COVERAGE
 	# Package code coverage gcno tree
 	@echo 'Packaging code coverage data...'
 	$(RM) $(CODE_COVERAGE_ARCHIVE_BASENAME).zip
 	$(PYTHON) -mmozbuild.codecoverage.packager \
 		--output-file='$(DIST)/$(PKG_PATH)$(CODE_COVERAGE_ARCHIVE_BASENAME).zip'
 endif
+ifeq (Darwin, $(OS_ARCH))
+ifdef MOZ_ASAN
+	@echo "Rewriting ASan runtime dylib paths for all binaries in $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) ..."
+	$(PYTHON) $(MOZILLA_DIR)/build/unix/rewrite_asan_dylib.py $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)
+endif # MOZ_ASAN
+endif # Darwin
 
 prepare-package: stage-package
 
 make-package-internal: prepare-package make-sourcestamp-file make-buildinfo-file
 	@echo 'Compressing...'
 	cd $(DIST) && $(MAKE_PACKAGE)
 
 make-package: FORCE