1*810390e3Srobert#!/usr/bin/env bash 23cab2bb3Spatrick# 33cab2bb3Spatrick# Run as: CLANG=bin/clang ZLIB_SRC=src/zlib \ 43cab2bb3Spatrick# build_symbolizer.sh runtime_build/lib/clang/4.0.0/lib/linux/ 53cab2bb3Spatrick# zlib can be downloaded from http://www.zlib.net. 63cab2bb3Spatrick# 73cab2bb3Spatrick# Script compiles self-contained object file with symbolization code and injects 83cab2bb3Spatrick# it into the given set of runtime libraries. Script updates only libraries 93cab2bb3Spatrick# which has unresolved __sanitizer_symbolize_* symbols and matches architecture. 103cab2bb3Spatrick# Object file is be compiled from LLVM sources with dependencies like libc++ and 113cab2bb3Spatrick# zlib. Then it internalizes symbols in the file, so that it can be linked 123cab2bb3Spatrick# into arbitrary programs, avoiding conflicts with the program own symbols and 133cab2bb3Spatrick# avoiding dependencies on any program symbols. The only acceptable dependencies 143cab2bb3Spatrick# are libc and __sanitizer::internal_* from sanitizer runtime. 153cab2bb3Spatrick# 163cab2bb3Spatrick# Symbols exported by the object file will be used by Sanitizer runtime 173cab2bb3Spatrick# libraries to symbolize code/data in-process. 183cab2bb3Spatrick# 193cab2bb3Spatrick# The script will modify the output directory which is given as the first 203cab2bb3Spatrick# argument to the script. 213cab2bb3Spatrick# 223cab2bb3Spatrick# FIXME: We should really be using a simpler approach to building this object 233cab2bb3Spatrick# file, and it should be available as a regular cmake rule. Conceptually, we 243cab2bb3Spatrick# want to be doing "ld -r" followed by "objcopy -G" to create a relocatable 253cab2bb3Spatrick# object file with only our entry points exposed. However, this does not work at 263cab2bb3Spatrick# present, see PR30750. 273cab2bb3Spatrick 283cab2bb3Spatrickset -x 293cab2bb3Spatrickset -e 303cab2bb3Spatrickset -u 313cab2bb3Spatrick 323cab2bb3SpatrickSCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) 333cab2bb3SpatrickSRC_DIR=$(readlink -f $SCRIPT_DIR/..) 343cab2bb3SpatrickTARGE_DIR=$(readlink -f $1) 353cab2bb3SpatrickCOMPILER_RT_SRC=$(readlink -f ${SCRIPT_DIR}/../../../..) 363cab2bb3SpatrickLLVM_SRC=${LLVM_SRC:-${COMPILER_RT_SRC}/../llvm} 373cab2bb3SpatrickLLVM_SRC=$(readlink -f $LLVM_SRC) 383cab2bb3Spatrick 393cab2bb3Spatrickif [[ "$ZLIB_SRC" == "" || 403cab2bb3Spatrick ! -x "${ZLIB_SRC}/configure" || 413cab2bb3Spatrick ! -f "${ZLIB_SRC}/zlib.h" ]]; then 423cab2bb3Spatrick echo "Missing or incomplete ZLIB_SRC" 433cab2bb3Spatrick exit 1 443cab2bb3Spatrickfi 453cab2bb3SpatrickZLIB_SRC=$(readlink -f $ZLIB_SRC) 463cab2bb3Spatrick 473cab2bb3SpatrickCLANG="${CLANG:-`which clang`}" 483cab2bb3SpatrickCLANG_DIR=$(readlink -f $(dirname "$CLANG")) 493cab2bb3Spatrick 503cab2bb3SpatrickBUILD_DIR=$(readlink -f ./symbolizer) 513cab2bb3Spatrickmkdir -p $BUILD_DIR 523cab2bb3Spatrickcd $BUILD_DIR 533cab2bb3Spatrick 543cab2bb3SpatrickCC=$CLANG_DIR/clang 553cab2bb3SpatrickCXX=$CLANG_DIR/clang++ 563cab2bb3SpatrickTBLGEN=$CLANG_DIR/llvm-tblgen 573cab2bb3SpatrickOPT=$CLANG_DIR/opt 58*810390e3SrobertAR=$CLANG_DIR/llvm-ar 59*810390e3SrobertLINK=$CLANG_DIR/llvm-link 603cab2bb3Spatrick 613cab2bb3Spatrickfor F in $CC $CXX $TBLGEN $LINK $OPT $AR; do 623cab2bb3Spatrick if [[ ! -x "$F" ]]; then 633cab2bb3Spatrick echo "Missing $F" 643cab2bb3Spatrick exit 1 653cab2bb3Spatrick fi 663cab2bb3Spatrickdone 673cab2bb3Spatrick 683cab2bb3SpatrickZLIB_BUILD=${BUILD_DIR}/zlib 693cab2bb3SpatrickLIBCXX_BUILD=${BUILD_DIR}/libcxx 703cab2bb3SpatrickLLVM_BUILD=${BUILD_DIR}/llvm 713cab2bb3SpatrickSYMBOLIZER_BUILD=${BUILD_DIR}/symbolizer 723cab2bb3Spatrick 733cab2bb3SpatrickFLAGS=${FLAGS:-} 74*810390e3SrobertTARGET_TRIPLE=$($CC -print-target-triple $FLAGS) 75*810390e3Srobertif [[ "$FLAGS" =~ "-m32" ]] ; then 76*810390e3Srobert # Avoid new wrappers. 77*810390e3Srobert FLAGS+=" -U_FILE_OFFSET_BITS" 78*810390e3Srobertfi 79*810390e3SrobertFLAGS+=" -fPIC -flto -Oz -g0 -DNDEBUG -target $TARGET_TRIPLE -Wno-unused-command-line-argument" 80*810390e3SrobertLINKFLAGS="-fuse-ld=lld -target $TARGET_TRIPLE" 813cab2bb3Spatrick 823cab2bb3Spatrick# Build zlib. 833cab2bb3Spatrickmkdir -p ${ZLIB_BUILD} 843cab2bb3Spatrickcd ${ZLIB_BUILD} 853cab2bb3Spatrickcp -r ${ZLIB_SRC}/* . 86*810390e3SrobertAR="${AR}" CC="${CC}" CFLAGS="$FLAGS -Wno-deprecated-non-prototype" RANLIB=/bin/true ./configure --static 87*810390e3Srobertmake -j libz.a 883cab2bb3Spatrick 893cab2bb3Spatrick# Build and install libcxxabi and libcxx. 903cab2bb3Spatrickif [[ ! -d ${LIBCXX_BUILD} ]]; then 913cab2bb3Spatrick mkdir -p ${LIBCXX_BUILD} 923cab2bb3Spatrick cd ${LIBCXX_BUILD} 93d89ec533Spatrick LIBCXX_FLAGS="${FLAGS} -Wno-macro-redefined" 943cab2bb3Spatrick cmake -GNinja \ 95*810390e3Srobert -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ 963cab2bb3Spatrick -DCMAKE_BUILD_TYPE=Release \ 973cab2bb3Spatrick -DCMAKE_C_COMPILER=$CC \ 983cab2bb3Spatrick -DCMAKE_CXX_COMPILER=$CXX \ 993cab2bb3Spatrick -DCMAKE_C_FLAGS_RELEASE="${LIBCXX_FLAGS}" \ 1003cab2bb3Spatrick -DCMAKE_CXX_FLAGS_RELEASE="${LIBCXX_FLAGS}" \ 1013cab2bb3Spatrick -DLIBCXXABI_ENABLE_ASSERTIONS=OFF \ 1023cab2bb3Spatrick -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF \ 1033cab2bb3Spatrick -DLIBCXX_ENABLE_ASSERTIONS=OFF \ 1043cab2bb3Spatrick -DLIBCXX_ENABLE_EXCEPTIONS=OFF \ 1053cab2bb3Spatrick -DLIBCXX_ENABLE_RTTI=OFF \ 106*810390e3Srobert -DCMAKE_SHARED_LINKER_FLAGS="$LINKFLAGS" \ 107*810390e3Srobert $LLVM_SRC/../runtimes 1083cab2bb3Spatrickfi 1093cab2bb3Spatrickcd ${LIBCXX_BUILD} 1103cab2bb3Spatrickninja cxx cxxabi 1113cab2bb3Spatrick 1123cab2bb3SpatrickFLAGS="${FLAGS} -fno-rtti -fno-exceptions" 113*810390e3SrobertLLVM_CFLAGS="${FLAGS} -Wno-global-constructors" 114*810390e3SrobertLLVM_CXXFLAGS="${LLVM_CFLAGS} -nostdinc++ -I${ZLIB_BUILD} -isystem ${LIBCXX_BUILD}/include -isystem ${LIBCXX_BUILD}/include/c++/v1" 1153cab2bb3Spatrick 1163cab2bb3Spatrick# Build LLVM. 1173cab2bb3Spatrickif [[ ! -d ${LLVM_BUILD} ]]; then 1183cab2bb3Spatrick mkdir -p ${LLVM_BUILD} 1193cab2bb3Spatrick cd ${LLVM_BUILD} 1203cab2bb3Spatrick cmake -GNinja \ 1213cab2bb3Spatrick -DCMAKE_BUILD_TYPE=Release \ 1223cab2bb3Spatrick -DCMAKE_C_COMPILER=$CC \ 1233cab2bb3Spatrick -DCMAKE_CXX_COMPILER=$CXX \ 124*810390e3Srobert -DCMAKE_C_FLAGS="${LLVM_CFLAGS}" \ 125*810390e3Srobert -DCMAKE_CXX_FLAGS="${LLVM_CXXFLAGS}" \ 126*810390e3Srobert -DCMAKE_EXE_LINKER_FLAGS="$LINKFLAGS -stdlib=libc++ -L${LIBCXX_BUILD}/lib" \ 1273cab2bb3Spatrick -DLLVM_TABLEGEN=$TBLGEN \ 1283cab2bb3Spatrick -DLLVM_ENABLE_ZLIB=ON \ 1293cab2bb3Spatrick -DLLVM_ENABLE_TERMINFO=OFF \ 1303cab2bb3Spatrick -DLLVM_ENABLE_THREADS=OFF \ 1313cab2bb3Spatrick $LLVM_SRC 1323cab2bb3Spatrickfi 1333cab2bb3Spatrickcd ${LLVM_BUILD} 134*810390e3Srobertninja LLVMSymbolize LLVMObject LLVMBinaryFormat LLVMDebugInfoDWARF LLVMSupport LLVMDebugInfoPDB LLVMDebuginfod LLVMMC LLVMDemangle LLVMTextAPI LLVMTargetParser 1353cab2bb3Spatrick 1363cab2bb3Spatrickcd ${BUILD_DIR} 1373cab2bb3Spatrickrm -rf ${SYMBOLIZER_BUILD} 1383cab2bb3Spatrickmkdir ${SYMBOLIZER_BUILD} 1393cab2bb3Spatrickcd ${SYMBOLIZER_BUILD} 1403cab2bb3Spatrick 1413cab2bb3Spatrickecho "Compiling..." 142*810390e3SrobertSYMBOLIZER_FLAGS="$LLVM_CXXFLAGS -I${LLVM_SRC}/include -I${LLVM_BUILD}/include -std=c++17" 1433cab2bb3Spatrick$CXX $SYMBOLIZER_FLAGS ${SRC_DIR}/sanitizer_symbolize.cpp ${SRC_DIR}/sanitizer_wrappers.cpp -c 1443cab2bb3Spatrick$AR rc symbolizer.a sanitizer_symbolize.o sanitizer_wrappers.o 1453cab2bb3Spatrick 146*810390e3SrobertSYMBOLIZER_API_LIST=__sanitizer_symbolize_code 147*810390e3SrobertSYMBOLIZER_API_LIST+=,__sanitizer_symbolize_data 148*810390e3SrobertSYMBOLIZER_API_LIST+=,__sanitizer_symbolize_flush 149*810390e3SrobertSYMBOLIZER_API_LIST+=,__sanitizer_symbolize_demangle 150*810390e3SrobertSYMBOLIZER_API_LIST+=,__sanitizer_symbolize_set_demangle 151*810390e3SrobertSYMBOLIZER_API_LIST+=,__sanitizer_symbolize_set_inline_frames 152*810390e3Srobert 153*810390e3SrobertLIBCXX_ARCHIVE_DIR=$(dirname $(find $LIBCXX_BUILD -name libc++.a | head -n1)) 1543cab2bb3Spatrick 1553cab2bb3Spatrick# Merge all the object files together and copy the resulting library back. 156*810390e3Srobert$LINK $LIBCXX_ARCHIVE_DIR/libc++.a \ 157*810390e3Srobert $LIBCXX_ARCHIVE_DIR/libc++abi.a \ 1583cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMSymbolize.a \ 1593cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMObject.a \ 1603cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMBinaryFormat.a \ 1613cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMDebugInfoDWARF.a \ 1623cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMSupport.a \ 1633cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMDebugInfoPDB.a \ 1641f9cb04fSpatrick $LLVM_BUILD/lib/libLLVMDebugInfoMSF.a \ 1651f9cb04fSpatrick $LLVM_BUILD/lib/libLLVMDebugInfoCodeView.a \ 166*810390e3Srobert $LLVM_BUILD/lib/libLLVMDebuginfod.a \ 1673cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMDemangle.a \ 1683cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMMC.a \ 1693cab2bb3Spatrick $LLVM_BUILD/lib/libLLVMTextAPI.a \ 170*810390e3Srobert $LLVM_BUILD/lib/libLLVMTargetParser.a \ 1713cab2bb3Spatrick $ZLIB_BUILD/libz.a \ 1723cab2bb3Spatrick symbolizer.a \ 173*810390e3Srobert -ignore-non-bitcode -o all.bc 1743cab2bb3Spatrick 1753cab2bb3Spatrickecho "Optimizing..." 176*810390e3Srobert$OPT -passes=internalize -internalize-public-api-list=${SYMBOLIZER_API_LIST} all.bc -o opt.bc 1773cab2bb3Spatrick$CC $FLAGS -fno-lto -c opt.bc -o symbolizer.o 1783cab2bb3Spatrick 1793cab2bb3Spatrickecho "Checking undefined symbols..." 1803cab2bb3Spatricknm -f posix -g symbolizer.o | cut -f 1,2 -d \ | LC_COLLATE=C sort -u > undefined.new 1813cab2bb3Spatrick(diff -u $SCRIPT_DIR/global_symbols.txt undefined.new | grep -E "^\+[^+]") && \ 1823cab2bb3Spatrick (echo "Failed: unexpected symbols"; exit 1) 1833cab2bb3Spatrick 1843cab2bb3Spatrickarch() { 1853cab2bb3Spatrick objdump -f $1 | grep -m1 -Po "(?<=file format ).*$" 1863cab2bb3Spatrick} 1873cab2bb3Spatrick 1883cab2bb3SpatrickSYMBOLIZER_FORMAT=$(arch symbolizer.o) 1893cab2bb3Spatrickecho "Injecting $SYMBOLIZER_FORMAT symbolizer..." 1903cab2bb3Spatrickfor A in $TARGE_DIR/libclang_rt.*san*.a; do 1913cab2bb3Spatrick A_FORMAT=$(arch $A) 1923cab2bb3Spatrick if [[ "$A_FORMAT" != "$SYMBOLIZER_FORMAT" ]] ; then 1933cab2bb3Spatrick continue 1943cab2bb3Spatrick fi 1953cab2bb3Spatrick (nm -u $A 2>/dev/null | grep -E "__sanitizer_symbolize_code" >/dev/null) || continue 1963cab2bb3Spatrick echo "$A" 1973cab2bb3Spatrick $AR rcs $A symbolizer.o 1983cab2bb3Spatrickdone 1993cab2bb3Spatrick 2003cab2bb3Spatrickecho "Success!" 201