diff --git a/cctools/libstuff/llvm.c b/cctools/libstuff/llvm.c index 447140d..26b0a66 100644 --- a/cctools/libstuff/llvm.c +++ b/cctools/libstuff/llvm.c @@ -14,7 +14,11 @@ * plan to include it (along with the current libLTO APIs) in a generic * libLLVM.dylib. */ +#ifdef __APPLE__ +#define LIB_LLVM "libLTO.dylib" +#else #define LIB_LLVM "libLTO.so" +#endif /* __APPLE__ */ static int tried_to_load_llvm = 0; static void *llvm_handle = NULL; @@ -62,12 +66,20 @@ static void load_llvm(void) p[1] = '\0'; llvm_path = makestr(prefix, "../lib/" LIB_LLVM, NULL); +#ifdef __APPLE__ llvm_handle = dlopen(llvm_path, RTLD_NOW); if(llvm_handle == NULL){ free(llvm_path); llvm_path = NULL; - llvm_handle = dlopen("/usr/lib/llvm/" LIB_LLVM, RTLD_NOW); + llvm_handle = dlopen("/Applications/Xcode.app/Contents/" + "Developer/Toolchains/XcodeDefault." + "xctoolchain/usr/lib/" LIB_LLVM, + RTLD_NOW); } +#else + llvm_handle = dlopen(LIB_LLVM, RTLD_NOW); +#endif /* __APPLE__ */ + if(llvm_handle == NULL) return; @@ -80,6 +92,13 @@ static void load_llvm(void) createCPU = dlsym(llvm_handle, "LLVMCreateDisasmCPU"); version = dlsym(llvm_handle, "lto_get_version"); +#ifndef __APPLE__ + if(create == NULL){ + fprintf(stderr, "Your " LIB_LLVM " lacks required symbols.\n"); + fprintf(stderr, "Please run: tools/fix_liblto.sh (or http://git.io/AyZP) to fix libLTO.\n"); + } +#endif /* __APPLE__ */ + if(create == NULL || dispose == NULL || disasm == NULL){ diff --git a/tools/fix_liblto.sh b/tools/fix_liblto.sh new file mode 100755 index 0000000..2ef49d6 --- /dev/null +++ b/tools/fix_liblto.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +## http://llvm.org/PR22677 + +pushd "${0%/*}" &>/dev/null + +if [ $(uname -s) == "Darwin" ]; then + echo "Darwin works out of the box." + exit 1 +fi + +if [ -z "$LLVM_CONFIG" ]; then + LLVM_CONFIG=llvm-config +fi + +which $LLVM_CONFIG &>/dev/null + +if [ $? -ne 0 ]; then + echo -n "Cannot find $LLVM_CONFIG, you may want to try " 1>&2 + echo "LLVM_CONFIG=llvm-config $0" 1>&2 + exit 1 +fi + +LIBDIR=$($LLVM_CONFIG --libdir) +INCDIR=$($LLVM_CONFIG --includedir) + +V="$(readelf -Ws $LIBDIR/libLTO.so 2>/dev/null | grep LLVMCreateDisasm)" + +if [ -n "$V" ]; then + echo "No fix needed." + exit 1 +fi + +VERSION=$($LLVM_CONFIG --version | awk -F \. {'print $1$2'} | sed 's/svn//g') + +if [ $VERSION -lt 34 ]; then + echo "This tool requires LLVM 3.4 or later." 1>&2 + exit 1 +fi + +LIBS=$($LLVM_CONFIG --libs all) +SYSLIBS=$($LLVM_CONFIG --system-libs 2>/dev/null || echo "-ldl -lz -ltinfo -pthread") +CXXFLAGS=$($LLVM_CONFIG --cxxflags) + +if [ $VERSION -ge 35 ]; then + SYSLIBS+=" -ledit" +fi + +set -e +TMP=$(mktemp -d) +set +e + +pushd $TMP &>/dev/null +wget https://raw.githubusercontent.com/llvm-mirror/llvm/release_$VERSION/tools/lto/lto.cpp +wget https://raw.githubusercontent.com/llvm-mirror/llvm/release_$VERSION/tools/lto/LTODisassembler.cpp +wget https://raw.githubusercontent.com/llvm-mirror/llvm/release_$VERSION/tools/lto/lto.exports + +echo "{" > lto.ls +echo " global:" >> lto.ls +while read p; do + echo " $p;" >> lto.ls +done < lto.exports +echo " LLVM*;" >> lto.ls +echo " local: *;" >> lto.ls +echo "};" >> lto.ls +popd &>/dev/null + +set -x + +clang++ -shared \ + -L$LIBDIR -I$INCDIR -Wl,--whole-archive $LIBS -Wl,--no-whole-archive $SYSLIBS \ + $CXXFLAGS $TMP/lto.cpp $TMP/LTODisassembler.cpp -Wl,-Map,$TMP/lto.exports \ + -Wl,-no-undefined -fno-rtti -fPIC -o libLTO.so + +rm -r $TMP + +mv -f libLTO.so $LIBDIR || { + set +x + echo "Try again as root." + echo "Or run the following command by hand: mv $PWD/libLTO.so $LIBDIR" + exit 1 +}