diff options
Diffstat (limited to 'build/unix/rewrite_asan_dylib.py')
-rw-r--r-- | build/unix/rewrite_asan_dylib.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/build/unix/rewrite_asan_dylib.py b/build/unix/rewrite_asan_dylib.py new file mode 100644 index 000000000..6e30374b7 --- /dev/null +++ b/build/unix/rewrite_asan_dylib.py @@ -0,0 +1,60 @@ +# 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 +from buildconfig import substs + +''' +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([substs['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) |