From 2d9f410c8a0f81e06f5c581f059591f141dcd06d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20P=C3=B6chtrager?= Date: Sat, 27 Jun 2015 19:26:22 +0200 Subject: [PATCH] add compiler-rt build script --- README.COMPILER-RT.md | 111 +++++++++++++++++++++++++++++ build_compiler_rt.sh | 157 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 README.COMPILER-RT.md create mode 100755 build_compiler_rt.sh diff --git a/README.COMPILER-RT.md b/README.COMPILER-RT.md new file mode 100644 index 0000000..893fa6c --- /dev/null +++ b/README.COMPILER-RT.md @@ -0,0 +1,111 @@ +## COMPILER-RT ## + +### WHAT IS COMPILER-RT: ### + +Please see http://compiler-rt.llvm.org/. + +### INSTALLATION: ### + +Ensure you have finished `build.sh`, + +then run: `./build_compiler_rt.sh`. + +You can verify compiler-rt is working by invoking the following command: + + echo "int main(void){return 0;}" | xcrun clang -xc -o/dev/null -v - 2>&1 | \ + grep "libclang_rt" 1>/dev/null && echo "Success" + +If you see "Success", then everything went well. + +### USAGE: ### + +You do not need to do anything, clang's doing the job for you. + +However, `-fsanitize=address` is a bit annoying because the address sanitizer library is linked +dynamically, and thus requires you to copy the ASAN runtime library onto the target system. + +The following example illustrates how to achieve this: + + # Example source code. + $ cat test.c + #include + #include + #include + + int main(void) { + char buf[2]; + strcpy(buf, "Hello World"); /* Buffer overflow. */ + puts(buf); + return 0; + } + + # Compile the source file. + $ o64-clang test.c -fsanitize=address -o test + + # Ensure the ASAN library is linked in. + $ xcrun otool -L test + test: + /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 104.1.0) # ASAN dep. + @rpath/libclang_rt.asan_osx_dynamic.dylib (compatibility version 0.0.0, current version 0.0.0) + /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0) + + # Copy 'test' and 'libclang_rt.asan_osx_dynamic.dylib' onto the target system. + + # You can find the ASAN library path easily with this one-liner: + $ echo "int main(void){return 0;}" | xcrun clang -fsanitize=address -xc -o/dev/null -v - 2>&1 | \ + tr ' ' '\n' | grep libclang_rt.asan_osx_dynamic.dylib + [...]/bin/../lib/clang/3.6.2/lib/darwin/libclang_rt.asan_osx_dynamic.dylib + + # Run ./test on the target system: + $ DYLD_LIBRARY_PATH=. ./test + ================================================================= + ==410==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff58c3ec72 at pc [...] + WRITE of size 12 at 0x7fff58c3ec72 thread T0 + #0 0x1070029ac ([...]/tmp/libclang_rt.asan_osx_dynamic.dylib+0x3a9ac) + #1 0x106fc1d3a ([...]/tmp/./test+0x100000d3a) + #2 0x106fc1bd3 ([...]/tmp/./test+0x100000bd3) + #3 0x0 () + + Address 0x7fff58c3ec72 is located in stack of thread T0 at offset 50 in frame + #0 0x106fc1bef ([...]/tmp/./test+0x100000bef) + + This frame has 2 object(s): + [32, 36) '' + [48, 50) 'buf' <== Memory access at offset 50 overflows this variable + HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext + (longjmp and C++ exceptions *are* supported) + Shadow bytes around the buggy address: + 0x1fffeb187d30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1fffeb187d40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1fffeb187d50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1fffeb187d60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1fffeb187d70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + =>0x1fffeb187d80: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 04 f2[02]f3 + 0x1fffeb187d90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1fffeb187da0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1fffeb187db0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1fffeb187dc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1fffeb187dd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Heap right redzone: fb + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack partial redzone: f4 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb + ==410==ABORTING + diff --git a/build_compiler_rt.sh b/build_compiler_rt.sh new file mode 100755 index 0000000..8fbb115 --- /dev/null +++ b/build_compiler_rt.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env bash + +pushd "${0%/*}" &>/dev/null + +source tools/tools.sh +eval $(tools/osxcross_conf.sh) + +if [ $PLATFORM == "Darwin" ]; then + exit 0 +fi + +require git +require $MAKE + +set +e + +which xcrun &>/dev/null + +# Clang <= 3.4 doesn't like '-arch x86_64h' + +if [ $? -ne 0 ] || + [[ $(xcrun clang -arch x86_64h --version 2>/dev/null) \ + == *Target:\ x86_64-* ]]; +then + echo "Please re-run ./build.sh" 1>&2 + exit 1 +fi + +set -e + +CLANG_VERSION=$(echo "__clang_major__ __clang_minor__ __clang_patchlevel__" | \ + clang -xc -E - | tail -n1 | tr ' ' '.') + +set +e +which llvm-config &>/dev/null && { CLANG_LIB_DIR=$(llvm-config --libdir); } +set -e + +if [ -z "$CLANG_LIB_DIR" ]; then + require $READLINK + CLANG_LIB_DIR="$(dirname $($READLINK -f $(which clang)))/../lib" +fi + +CLANG_LIB_DIR+="/clang" + +if [ ! -d "$CLANG_LIB_DIR" ]; then + echo "$CLANG_LIB_DIR does not exist!" 1>&2 + echo "Installing llvm-dev may help" 1>&2 + exit 1 +fi + +# Drop patch level for <= 3.3. +if [ $(osxcross-cmp $CLANG_VERSION "<=" 3.3) -eq 1 ]; then + CLANG_VERSION=$(echo $CLANG_VERSION | tr '.' ' ' | + awk '{print $1, $2}' | tr ' ' '.') +fi + +CLANG_INCLUDE_DIR="${CLANG_LIB_DIR}/${CLANG_VERSION}/include" +CLANG_DARWIN_LIB_DIR="${CLANG_LIB_DIR}/${CLANG_VERSION}/lib/darwin" + +case $CLANG_VERSION in + 3.2*) BRANCH=release_32 ;; + 3.3*) BRANCH=release_33 ;; + 3.4*) BRANCH=release_34 ;; + 3.5*) BRANCH=release_35 ;; + 3.6*) BRANCH=release_36 ;; + 3.7*) BRANCH=master ;; + * ) echo "Unsupported Clang version, must be >= 3.2 and <= 3.7" 1>&2; exit 1; +esac + +pushd $OSXCROSS_BUILD_DIR &>/dev/null + +if [ ! -e compiler-rt/.clone_complete ]; then + rm -rf compiler-rt + git clone http://llvm.org/git/compiler-rt.git +fi + +pushd compiler-rt &>/dev/null + +git reset --hard + +git checkout $BRANCH +git clean -fdx +touch .clone_complete +git pull + +sed -i "s/Configs += ios//g" make/platform/clang_darwin.mk +sed -i "s/Configs += cc_kext_ios5//g" make/platform/clang_darwin.mk +sed -i "s/Configs += profile_ios//g" make/platform/clang_darwin.mk +sed -i "s/Configs += asan_iossim_dynamic//g" make/platform/clang_darwin.mk + +# Unbreak the -Werror build. +if [ -f lib/asan/asan_mac.h ]; then + sed -i "s/ASAN__MAC_H/ASAN_MAC_H/g" lib/asan/asan_mac.h +fi + +if [ $(osxcross-cmp $CLANG_VERSION ">=" 3.5) -eq 1 ]; then + export MACOSX_DEPLOYMENT_TARGET=10.7 +else + export MACOSX_DEPLOYMENT_TARGET=10.4 +fi + +if [ $(osxcross-cmp $MACOSX_DEPLOYMENT_TARGET ">" \ + $OSXCROSS_SDK_VERSION) -eq 1 ]; +then + echo ">= $MACOSX_DEPLOYMENT_TARGET SDK required" 1>&2 + exit 1 +fi + +EXTRA_MAKE_FLAGS="LIPO=\"xcrun lipo\"" + +if [ $(osxcross-cmp $CLANG_VERSION "<=" 3.3) -eq 1 ]; then + EXTRA_MAKE_FLAGS+=" AR=\"xcrun ar\"" + EXTRA_MAKE_FLAGS+=" RANLIB=\"xcrun ranlib\"" + EXTRA_MAKE_FLAGS+=" CC=\"xcrun clang\"" +fi + +if [ -n "$OCDEBUG" ]; then + EXTRA_MAKE_FLAGS+=" VERBOSE=1" +fi + +# Must eval here because of the spaces in EXTRA_MAKE_FLAGS. + +eval \ + "OSXCROSS_NO_X86_64H_DEPLOYMENT_TARGET_WARNING=1 \ + $MAKE clang_darwin $EXTRA_MAKE_FLAGS -j $JOBS" + +echo "" +echo "" +echo "" +echo "Please run the following commands by hand to install compiler-rt:" +echo "" + +echo "mkdir -p ${CLANG_LIB_DIR}/${CLANG_VERSION}/include" +echo "mkdir -p ${CLANG_LIB_DIR}/${CLANG_VERSION}/lib/darwin" +echo "cp -r $PWD/include/sanitizer ${CLANG_INCLUDE_DIR}" + +pushd "clang_darwin" &>/dev/null + +function print_install_command() { + if [ -f "$1" ]; then + echo "cp $PWD/$1 ${CLANG_DARWIN_LIB_DIR}/$2" + fi +} + +print_install_command "osx/libcompiler_rt.a" "libclang_rt.osx.a" +print_install_command "10.4/libcompiler_rt.a" "libclang_rt.10.4.a" +print_install_command "eprintf/libcompiler_rt.a" "libclang_rt.eprintf.a" +print_install_command "cc_kext/libcompiler_rt.a" "libclang_rt.cc_kext.a" +print_install_command "profile_osx/libcompiler_rt.a" "libclang_rt.profile_osx.a" + +print_install_command "ubsan_osx_dynamic/libcompiler_rt.dylib" \ + "libclang_rt.ubsan_osx_dynamic.dylib" + +print_install_command "asan_osx_dynamic/libcompiler_rt.dylib" \ + "libclang_rt.asan_osx_dynamic.dylib" + +echo ""