diff options
Diffstat (limited to 'lib')
178 files changed, 0 insertions, 34901 deletions
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt deleted file mode 100644 index b3731f653a01a..0000000000000 --- a/lib/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -# First, add the subdirectories which contain feature-based runtime libraries -# and several convenience helper libraries. - -include(AddCompilerRT) -include(SanitizerUtils) - -# Hoist the building of sanitizer_common on whether we're building either the -# sanitizers or xray (or both). -# -#TODO: Refactor sanitizer_common into smaller pieces (e.g. flag parsing, utils). -if (COMPILER_RT_HAS_SANITIZER_COMMON AND - (COMPILER_RT_BUILD_SANITIZERS OR COMPILER_RT_BUILD_XRAY)) - add_subdirectory(sanitizer_common) -endif() - -if(COMPILER_RT_BUILD_BUILTINS) - add_subdirectory(builtins) -endif() - -function(compiler_rt_build_runtime runtime) - string(TOUPPER ${runtime} runtime_uppercase) - if(COMPILER_RT_HAS_${runtime_uppercase}) - add_subdirectory(${runtime}) - if(${runtime} STREQUAL tsan) - add_subdirectory(tsan/dd) - endif() - endif() -endfunction() - -if(COMPILER_RT_BUILD_SANITIZERS) - compiler_rt_build_runtime(interception) - - if(COMPILER_RT_HAS_SANITIZER_COMMON) - add_subdirectory(stats) - add_subdirectory(lsan) - add_subdirectory(ubsan) - endif() - - foreach(sanitizer ${COMPILER_RT_SANITIZERS_TO_BUILD}) - compiler_rt_build_runtime(${sanitizer}) - endforeach() -endif() - -if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) - compiler_rt_build_runtime(profile) -endif() - -if(COMPILER_RT_BUILD_XRAY) - compiler_rt_build_runtime(xray) -endif() - -if(COMPILER_RT_BUILD_LIBFUZZER) - compiler_rt_build_runtime(fuzzer) -endif() diff --git a/lib/asan/.clang-format b/lib/asan/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/asan/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt deleted file mode 100644 index 726da27d052f1..0000000000000 --- a/lib/asan/CMakeLists.txt +++ /dev/null @@ -1,338 +0,0 @@ -# Build for the AddressSanitizer runtime support library. - -set(ASAN_SOURCES - asan_allocator.cc - asan_activation.cc - asan_debugging.cc - asan_descriptions.cc - asan_errors.cc - asan_fake_stack.cc - asan_flags.cc - asan_fuchsia.cc - asan_globals.cc - asan_globals_win.cc - asan_interceptors.cc - asan_interceptors_memintrinsics.cc - asan_linux.cc - asan_mac.cc - asan_malloc_linux.cc - asan_malloc_mac.cc - asan_malloc_win.cc - asan_memory_profile.cc - asan_poisoning.cc - asan_posix.cc - asan_premap_shadow.cc - asan_report.cc - asan_rtems.cc - asan_rtl.cc - asan_shadow_setup.cc - asan_stack.cc - asan_stats.cc - asan_suppressions.cc - asan_thread.cc - asan_win.cc) - -set(ASAN_CXX_SOURCES - asan_new_delete.cc) - -set(ASAN_PREINIT_SOURCES - asan_preinit.cc) - -SET(ASAN_HEADERS - asan_activation.h - asan_activation_flags.inc - asan_allocator.h - asan_descriptions.h - asan_errors.h - asan_fake_stack.h - asan_flags.h - asan_flags.inc - asan_init_version.h - asan_interceptors.h - asan_interceptors_memintrinsics.h - asan_interface.inc - asan_interface_internal.h - asan_internal.h - asan_lock.h - asan_malloc_local.h - asan_mapping.h - asan_mapping_myriad.h - asan_poisoning.h - asan_premap_shadow.h - asan_report.h - asan_scariness_score.h - asan_stack.h - asan_stats.h - asan_suppressions.h - asan_thread.h) - -include_directories(..) - -set(ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -set(ASAN_COMMON_DEFINITIONS ${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION}) - -append_rtti_flag(OFF ASAN_CFLAGS) - -set(ASAN_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) - -if(ANDROID) -# Put most Sanitizer shared libraries in the global group. For more details, see -# android-changes-for-ndk-developers.md#changes-to-library-search-order - if (COMPILER_RT_HAS_Z_GLOBAL) - list(APPEND ASAN_DYNAMIC_LINK_FLAGS -Wl,-z,global) - endif() -endif() - -set(ASAN_DYNAMIC_DEFINITIONS - ${ASAN_COMMON_DEFINITIONS} ASAN_DYNAMIC=1) -append_list_if(WIN32 INTERCEPTION_DYNAMIC_CRT ASAN_DYNAMIC_DEFINITIONS) - -set(ASAN_DYNAMIC_CFLAGS ${ASAN_CFLAGS}) -append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC - -ftls-model=initial-exec ASAN_DYNAMIC_CFLAGS) -append_list_if(MSVC /DEBUG ASAN_DYNAMIC_LINK_FLAGS) - -set(ASAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARY} ${SANITIZER_COMMON_LINK_LIBS}) - -append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBRT rt ASAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBM m ASAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread ASAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBLOG log ASAN_DYNAMIC_LIBS) -append_list_if(MINGW "${MINGW_LIBRARIES}" ASAN_DYNAMIC_LIBS) - -if (TARGET cxx-headers OR HAVE_LIBCXX) - set(ASAN_DEPS cxx-headers) -endif() - -# Compile ASan sources into an object library. - -add_compiler_rt_object_libraries(RTAsan_dynamic - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${ASAN_SUPPORTED_ARCH} - SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES} - ADDITIONAL_HEADERS ${ASAN_HEADERS} - CFLAGS ${ASAN_DYNAMIC_CFLAGS} - DEFS ${ASAN_DYNAMIC_DEFINITIONS} - DEPS ${ASAN_DEPS}) - -if(NOT APPLE) - add_compiler_rt_object_libraries(RTAsan - ARCHS ${ASAN_SUPPORTED_ARCH} - SOURCES ${ASAN_SOURCES} - ADDITIONAL_HEADERS ${ASAN_HEADERS} - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - DEPS ${ASAN_DEPS}) - add_compiler_rt_object_libraries(RTAsan_cxx - ARCHS ${ASAN_SUPPORTED_ARCH} - SOURCES ${ASAN_CXX_SOURCES} - ADDITIONAL_HEADERS ${ASAN_HEADERS} - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - DEPS ${ASAN_DEPS}) - add_compiler_rt_object_libraries(RTAsan_preinit - ARCHS ${ASAN_SUPPORTED_ARCH} - SOURCES ${ASAN_PREINIT_SOURCES} - ADDITIONAL_HEADERS ${ASAN_HEADERS} - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - DEPS ${ASAN_DEPS}) - - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc "") - add_compiler_rt_object_libraries(RTAsan_dynamic_version_script_dummy - ARCHS ${ASAN_SUPPORTED_ARCH} - SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc - CFLAGS ${ASAN_DYNAMIC_CFLAGS} - DEFS ${ASAN_DYNAMIC_DEFINITIONS} - DEPS ${ASAN_DEPS}) -endif() - -# Build ASan runtimes shipped with Clang. -add_compiler_rt_component(asan) - -if(APPLE) - add_weak_symbols("asan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("lsan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("ubsan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("xray" WEAK_SYMBOL_LINK_FLAGS) - - add_compiler_rt_runtime(clang_rt.asan - SHARED - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${ASAN_SUPPORTED_ARCH} - OBJECT_LIBS RTAsan_dynamic - RTInterception - RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTLSanCommon - RTUbsan - CFLAGS ${ASAN_DYNAMIC_CFLAGS} - LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS} - DEFS ${ASAN_DYNAMIC_DEFINITIONS} - PARENT_TARGET asan) -else() - # Build separate libraries for each target. - - set(ASAN_COMMON_RUNTIME_OBJECT_LIBS - RTInterception - RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTLSanCommon - RTUbsan) - - add_compiler_rt_runtime(clang_rt.asan - STATIC - ARCHS ${ASAN_SUPPORTED_ARCH} - OBJECT_LIBS RTAsan_preinit - RTAsan - ${ASAN_COMMON_RUNTIME_OBJECT_LIBS} - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - PARENT_TARGET asan) - - add_compiler_rt_runtime(clang_rt.asan_cxx - STATIC - ARCHS ${ASAN_SUPPORTED_ARCH} - OBJECT_LIBS RTAsan_cxx - RTUbsan_cxx - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - PARENT_TARGET asan) - - add_compiler_rt_runtime(clang_rt.asan-preinit - STATIC - ARCHS ${ASAN_SUPPORTED_ARCH} - OBJECT_LIBS RTAsan_preinit - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - PARENT_TARGET asan) - - foreach(arch ${ASAN_SUPPORTED_ARCH}) - if (UNIX) - add_sanitizer_rt_version_list(clang_rt.asan-dynamic-${arch} - LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch} - EXTRA asan.syms.extra) - set(VERSION_SCRIPT_FLAG - -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers) - # The Solaris 11.4 linker supports a subset of GNU ld version scripts, - # but requires a special option to enable it. - if (OS_NAME MATCHES "SunOS") - list(APPEND VERSION_SCRIPT_FLAG -Wl,-z,gnu-version-script-compat) - endif() - set_property(SOURCE - ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc - APPEND PROPERTY - OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers) - else() - set(VERSION_SCRIPT_FLAG) - endif() - - set(ASAN_DYNAMIC_WEAK_INTERCEPTION) - if (WIN32) - add_compiler_rt_object_libraries(AsanWeakInterception - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${arch} - SOURCES asan_win_weak_interception.cc - CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DYNAMIC - DEFS ${ASAN_COMMON_DEFINITIONS} - DEPS ${ASAN_DEPS}) - set(ASAN_DYNAMIC_WEAK_INTERCEPTION - AsanWeakInterception - UbsanWeakInterception - SancovWeakInterception - SanitizerCommonWeakInterception) - endif() - - add_compiler_rt_runtime(clang_rt.asan - SHARED - ARCHS ${arch} - OBJECT_LIBS ${ASAN_COMMON_RUNTIME_OBJECT_LIBS} - RTAsan_dynamic - # The only purpose of RTAsan_dynamic_version_script_dummy is to - # carry a dependency of the shared runtime on the version script. - # Replacing it with a straightforward - # add_dependencies(clang_rt.asan-dynamic-${arch} clang_rt.asan-dynamic-${arch}-version-list) - # generates an order-only dependency in ninja. - RTAsan_dynamic_version_script_dummy - RTUbsan_cxx - ${ASAN_DYNAMIC_WEAK_INTERCEPTION} - CFLAGS ${ASAN_DYNAMIC_CFLAGS} - LINK_FLAGS ${ASAN_DYNAMIC_LINK_FLAGS} - ${VERSION_SCRIPT_FLAG} - LINK_LIBS ${ASAN_DYNAMIC_LIBS} - DEFS ${ASAN_DYNAMIC_DEFINITIONS} - PARENT_TARGET asan) - - if (SANITIZER_USE_SYMBOLS AND NOT ${arch} STREQUAL "i386") - add_sanitizer_rt_symbols(clang_rt.asan_cxx - ARCHS ${arch}) - add_dependencies(asan clang_rt.asan_cxx-${arch}-symbols) - add_sanitizer_rt_symbols(clang_rt.asan - ARCHS ${arch} - EXTRA asan.syms.extra) - add_dependencies(asan clang_rt.asan-${arch}-symbols) - endif() - - if (WIN32) - add_compiler_rt_object_libraries(AsanDllThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${arch} - SOURCES asan_globals_win.cc - asan_win_dll_thunk.cc - CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DLL_THUNK - DEFS ${ASAN_COMMON_DEFINITIONS} - DEPS ${ASAN_DEPS}) - - add_compiler_rt_runtime(clang_rt.asan_dll_thunk - STATIC - ARCHS ${arch} - OBJECT_LIBS AsanDllThunk - UbsanDllThunk - SancovDllThunk - SanitizerCommonDllThunk - SOURCES $<TARGET_OBJECTS:RTInterception.${arch}> - PARENT_TARGET asan) - - set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK") - if(MSVC) - list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl") - elseif(CMAKE_C_COMPILER_ID MATCHES Clang) - list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs") - endif() - - add_compiler_rt_object_libraries(AsanDynamicRuntimeThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${arch} - SOURCES asan_globals_win.cc - asan_win_dynamic_runtime_thunk.cc - CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - DEPS ${ASAN_DEPS}) - - add_compiler_rt_runtime(clang_rt.asan_dynamic_runtime_thunk - STATIC - ARCHS ${arch} - OBJECT_LIBS AsanDynamicRuntimeThunk - UbsanDynamicRuntimeThunk - SancovDynamicRuntimeThunk - SanitizerCommonDynamicRuntimeThunk - CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - PARENT_TARGET asan) - endif() - endforeach() -endif() - -add_compiler_rt_resource_file(asan_blacklist asan_blacklist.txt asan) - -add_subdirectory(scripts) - -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/lib/asan/scripts/CMakeLists.txt b/lib/asan/scripts/CMakeLists.txt deleted file mode 100644 index e5ab8ebed0242..0000000000000 --- a/lib/asan/scripts/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -if(ANDROID) - add_compiler_rt_script(asan_device_setup) - add_dependencies(asan asan_device_setup) -endif() diff --git a/lib/asan/scripts/asan_device_setup b/lib/asan/scripts/asan_device_setup deleted file mode 100755 index 5e679e366514a..0000000000000 --- a/lib/asan/scripts/asan_device_setup +++ /dev/null @@ -1,467 +0,0 @@ -#!/bin/bash -#===- lib/asan/scripts/asan_device_setup -----------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -# Prepare Android device to run ASan applications. -# -#===------------------------------------------------------------------------===# - -set -e - -HERE="$(cd "$(dirname "$0")" && pwd)" - -revert=no -extra_options= -device= -lib= -use_su=0 - -function usage { - echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-options options]" - echo " --revert: Uninstall ASan from the device." - echo " --lib: Path to ASan runtime library." - echo " --extra-options: Extra ASAN_OPTIONS." - echo " --device: Install to the given device. Use 'adb devices' to find" - echo " device-id." - echo " --use-su: Use 'su -c' prefix for every adb command instead of using" - echo " 'adb root' once." - echo - exit 1 -} - -function adb_push { - if [ $use_su -eq 0 ]; then - $ADB push "$1" "$2" - else - local FILENAME=$(basename $1) - $ADB push "$1" "/data/local/tmp/$FILENAME" - $ADB shell su -c "rm \\\"$2/$FILENAME\\\"" >&/dev/null - $ADB shell su -c "cat \\\"/data/local/tmp/$FILENAME\\\" > \\\"$2/$FILENAME\\\"" - $ADB shell su -c "rm \\\"/data/local/tmp/$FILENAME\\\"" - fi -} - -function adb_remount { - if [ $use_su -eq 0 ]; then - $ADB remount - else - local STORAGE=`$ADB shell mount | grep /system | cut -d ' ' -f1` - if [ "$STORAGE" != "" ]; then - echo Remounting $STORAGE at /system - $ADB shell su -c "mount -o rw,remount $STORAGE /system" - else - echo Failed to get storage device name for "/system" mount point - fi - fi -} - -function adb_shell { - if [ $use_su -eq 0 ]; then - $ADB shell $@ - else - $ADB shell su -c "$*" - fi -} - -function adb_root { - if [ $use_su -eq 0 ]; then - $ADB root - fi -} - -function adb_wait_for_device { - $ADB wait-for-device -} - -function adb_pull { - if [ $use_su -eq 0 ]; then - $ADB pull "$1" "$2" - else - local FILENAME=$(basename $1) - $ADB shell rm "/data/local/tmp/$FILENAME" >&/dev/null - $ADB shell su -c "[ -f \\\"$1\\\" ] && cat \\\"$1\\\" > \\\"/data/local/tmp/$FILENAME\\\" && chown root.shell \\\"/data/local/tmp/$FILENAME\\\" && chmod 755 \\\"/data/local/tmp/$FILENAME\\\"" && - $ADB pull "/data/local/tmp/$FILENAME" "$2" >&/dev/null && $ADB shell "rm \"/data/local/tmp/$FILENAME\"" - fi -} - -function get_device_arch { # OUT OUT64 - local _outvar=$1 - local _outvar64=$2 - local _ABI=$(adb_shell getprop ro.product.cpu.abi) - local _ARCH= - local _ARCH64= - if [[ $_ABI == x86* ]]; then - _ARCH=i386 - elif [[ $_ABI == armeabi* ]]; then - _ARCH=arm - elif [[ $_ABI == arm64-v8a* ]]; then - _ARCH=arm - _ARCH64=aarch64 - else - echo "Unrecognized device ABI: $_ABI" - exit 1 - fi - eval $_outvar=\$_ARCH - eval $_outvar64=\$_ARCH64 -} - -while [[ $# > 0 ]]; do - case $1 in - --revert) - revert=yes - ;; - --extra-options) - shift - if [[ $# == 0 ]]; then - echo "--extra-options requires an argument." - exit 1 - fi - extra_options="$1" - ;; - --lib) - shift - if [[ $# == 0 ]]; then - echo "--lib requires an argument." - exit 1 - fi - lib="$1" - ;; - --device) - shift - if [[ $# == 0 ]]; then - echo "--device requires an argument." - exit 1 - fi - device="$1" - ;; - --use-su) - use_su=1 - ;; - *) - usage - ;; - esac - shift -done - -ADB=${ADB:-adb} -if [[ x$device != x ]]; then - ADB="$ADB -s $device" -fi - -if [ $use_su -eq 1 ]; then - # Test if 'su' is present on the device - SU_TEST_OUT=`$ADB shell su -c "echo foo" 2>&1 | sed 's/\r$//'` - if [ $? != 0 -o "$SU_TEST_OUT" != "foo" ]; then - echo "ERROR: Cannot use 'su -c':" - echo "$ adb shell su -c \"echo foo\"" - echo $SU_TEST_OUT - echo "Check that 'su' binary is correctly installed on the device or omit" - echo " --use-su flag" - exit 1 - fi -fi - -echo '>> Remounting /system rw' -adb_wait_for_device -adb_root -adb_wait_for_device -adb_remount -adb_wait_for_device - -get_device_arch ARCH ARCH64 -echo "Target architecture: $ARCH" -ASAN_RT="libclang_rt.asan-$ARCH-android.so" -if [[ -n $ARCH64 ]]; then - echo "Target architecture: $ARCH64" - ASAN_RT64="libclang_rt.asan-$ARCH64-android.so" -fi - -RELEASE=$(adb_shell getprop ro.build.version.release) -PRE_L=0 -if echo "$RELEASE" | grep '^4\.' >&/dev/null; then - PRE_L=1 -fi -ANDROID_O=0 -if echo "$RELEASE" | grep '^8\.0\.' >&/dev/null; then - # 8.0.x is for Android O - ANDROID_O=1 -fi - -if [[ x$revert == xyes ]]; then - echo '>> Uninstalling ASan' - - if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then - echo '>> Pre-L device detected.' - adb_shell mv /system/bin/app_process.real /system/bin/app_process - adb_shell rm /system/bin/asanwrapper - elif ! adb_shell ls -l /system/bin/app_process64.real | grep -o 'No such file or directory' >&/dev/null; then - # 64-bit installation. - adb_shell mv /system/bin/app_process32.real /system/bin/app_process32 - adb_shell mv /system/bin/app_process64.real /system/bin/app_process64 - adb_shell rm /system/bin/asanwrapper - adb_shell rm /system/bin/asanwrapper64 - else - # 32-bit installation. - adb_shell rm /system/bin/app_process.wrap - adb_shell rm /system/bin/asanwrapper - adb_shell rm /system/bin/app_process - adb_shell ln -s /system/bin/app_process32 /system/bin/app_process - fi - - if [[ ANDROID_O -eq 1 ]]; then - adb_shell mv /system/etc/ld.config.txt.saved /system/etc/ld.config.txt - fi - - echo '>> Restarting shell' - adb_shell stop - adb_shell start - - # Remove the library on the last step to give a chance to the 'su' binary to - # be executed without problem. - adb_shell rm /system/lib/$ASAN_RT - - echo '>> Done' - exit 0 -fi - -if [[ -d "$lib" ]]; then - ASAN_RT_PATH="$lib" -elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then - ASAN_RT_PATH=$(dirname "$lib") -elif [[ -f "$HERE/$ASAN_RT" ]]; then - ASAN_RT_PATH="$HERE" -elif [[ $(basename "$HERE") == "bin" ]]; then - # We could be in the toolchain's base directory. - # Consider ../lib, ../lib/asan, ../lib/linux, - # ../lib/clang/$VERSION/lib/linux, and ../lib64/clang/$VERSION/lib/linux. - P=$(ls "$HERE"/../lib/"$ASAN_RT" \ - "$HERE"/../lib/asan/"$ASAN_RT" \ - "$HERE"/../lib/linux/"$ASAN_RT" \ - "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" \ - "$HERE"/../lib64/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1) - if [[ -n "$P" ]]; then - ASAN_RT_PATH="$(dirname "$P")" - fi -fi - -if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then - echo ">> ASan runtime library not found" - exit 1 -fi - -if [[ -n "$ASAN_RT64" ]]; then - if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT64" ]]; then - echo ">> ASan runtime library not found" - exit 1 - fi -fi - -TMPDIRBASE=$(mktemp -d) -TMPDIROLD="$TMPDIRBASE/old" -TMPDIR="$TMPDIRBASE/new" -mkdir "$TMPDIROLD" - -if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then - - if adb_pull /system/bin/app_process.real /dev/null >&/dev/null; then - echo '>> Old-style ASan installation detected. Reverting.' - adb_shell mv /system/bin/app_process.real /system/bin/app_process - fi - - echo '>> Pre-L device detected. Setting up app_process symlink.' - adb_shell mv /system/bin/app_process /system/bin/app_process32 - adb_shell ln -s /system/bin/app_process32 /system/bin/app_process -fi - -echo '>> Copying files from the device' -if [[ -n "$ASAN_RT64" ]]; then - adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true - adb_pull /system/lib64/"$ASAN_RT64" "$TMPDIROLD" || true - adb_pull /system/bin/app_process32 "$TMPDIROLD" || true - adb_pull /system/bin/app_process32.real "$TMPDIROLD" || true - adb_pull /system/bin/app_process64 "$TMPDIROLD" || true - adb_pull /system/bin/app_process64.real "$TMPDIROLD" || true - adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true - adb_pull /system/bin/asanwrapper64 "$TMPDIROLD" || true -else - adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true - adb_pull /system/bin/app_process32 "$TMPDIROLD" || true - adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true - adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true -fi -cp -r "$TMPDIROLD" "$TMPDIR" - -if [[ -f "$TMPDIR/app_process.wrap" || -f "$TMPDIR/app_process64.real" ]]; then - echo ">> Previous installation detected" -else - echo ">> New installation" -fi - -echo '>> Generating wrappers' - -cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/" -if [[ -n "$ASAN_RT64" ]]; then - cp "$ASAN_RT_PATH/$ASAN_RT64" "$TMPDIR/" -fi - -ASAN_OPTIONS=start_deactivated=1 - -# The name of a symlink to libclang_rt.asan-$ARCH-android.so used in LD_PRELOAD. -# The idea is to have the same name in lib and lib64 to keep it from falling -# apart when a 64-bit process spawns a 32-bit one, inheriting the environment. -ASAN_RT_SYMLINK=symlink-to-libclang_rt.asan - -function generate_zygote_wrapper { # from, to - local _from=$1 - local _to=$2 - if [[ PRE_L -eq 0 ]]; then - # LD_PRELOAD parsing is broken in N if it starts with ":". Luckily, it is - # unset in the system environment since L. - local _ld_preload=$ASAN_RT_SYMLINK - else - local _ld_preload=\$LD_PRELOAD:$ASAN_RT_SYMLINK - fi - cat <<EOF >"$TMPDIR/$_from" -#!/system/bin/sh-from-zygote -ASAN_OPTIONS=$ASAN_OPTIONS \\ -ASAN_ACTIVATION_OPTIONS=include_if_exists=/data/local/tmp/asan.options.%b \\ -LD_PRELOAD=$_ld_preload \\ -exec $_to \$@ - -EOF -} - -# On Android-L not allowing user segv handler breaks some applications. -# Since ~May 2017 this is the default setting; included for compatibility with -# older library versions. -if [[ PRE_L -eq 0 ]]; then - ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1" -fi - -if [[ x$extra_options != x ]] ; then - ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options" -fi - -# Zygote wrapper. -if [[ -f "$TMPDIR/app_process64" ]]; then - # A 64-bit device. - if [[ ! -f "$TMPDIR/app_process64.real" ]]; then - # New installation. - mv "$TMPDIR/app_process32" "$TMPDIR/app_process32.real" - mv "$TMPDIR/app_process64" "$TMPDIR/app_process64.real" - fi - generate_zygote_wrapper "app_process32" "/system/bin/app_process32.real" - generate_zygote_wrapper "app_process64" "/system/bin/app_process64.real" -else - # A 32-bit device. - generate_zygote_wrapper "app_process.wrap" "/system/bin/app_process32" -fi - -# General command-line tool wrapper (use for anything that's not started as -# zygote). -cat <<EOF >"$TMPDIR/asanwrapper" -#!/system/bin/sh -LD_PRELOAD=$ASAN_RT_SYMLINK \\ -exec \$@ - -EOF - -if [[ -n "$ASAN_RT64" ]]; then - cat <<EOF >"$TMPDIR/asanwrapper64" -#!/system/bin/sh -LD_PRELOAD=$ASAN_RT_SYMLINK \\ -exec \$@ - -EOF -fi - -function install { # from, to, chmod, chcon - local _from=$1 - local _to=$2 - local _mode=$3 - local _context=$4 - local _basename="$(basename "$_from")" - echo "Installing $_to/$_basename $_mode $_context" - adb_push "$_from" "$_to/$_basename" - adb_shell chown root.shell "$_to/$_basename" - if [[ -n "$_mode" ]]; then - adb_shell chmod "$_mode" "$_to/$_basename" - fi - if [[ -n "$_context" ]]; then - adb_shell chcon "$_context" "$_to/$_basename" - fi -} - -if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then - # Make SELinux happy by keeping app_process wrapper and the shell - # it runs on in zygote domain. - ENFORCING=0 - if adb_shell getenforce | grep Enforcing >/dev/null; then - # Sometimes shell is not allowed to change file contexts. - # Temporarily switch to permissive. - ENFORCING=1 - adb_shell setenforce 0 - fi - - if [[ PRE_L -eq 1 ]]; then - CTX=u:object_r:system_file:s0 - else - CTX=u:object_r:zygote_exec:s0 - fi - - echo '>> Pushing files to the device' - - if [[ -n "$ASAN_RT64" ]]; then - install "$TMPDIR/$ASAN_RT" /system/lib 644 - install "$TMPDIR/$ASAN_RT64" /system/lib64 644 - install "$TMPDIR/app_process32" /system/bin 755 $CTX - install "$TMPDIR/app_process32.real" /system/bin 755 $CTX - install "$TMPDIR/app_process64" /system/bin 755 $CTX - install "$TMPDIR/app_process64.real" /system/bin 755 $CTX - install "$TMPDIR/asanwrapper" /system/bin 755 - install "$TMPDIR/asanwrapper64" /system/bin 755 - - adb_shell rm -f /system/lib/$ASAN_RT_SYMLINK - adb_shell ln -s $ASAN_RT /system/lib/$ASAN_RT_SYMLINK - adb_shell rm -f /system/lib64/$ASAN_RT_SYMLINK - adb_shell ln -s $ASAN_RT64 /system/lib64/$ASAN_RT_SYMLINK - else - install "$TMPDIR/$ASAN_RT" /system/lib 644 - install "$TMPDIR/app_process32" /system/bin 755 $CTX - install "$TMPDIR/app_process.wrap" /system/bin 755 $CTX - install "$TMPDIR/asanwrapper" /system/bin 755 $CTX - - adb_shell rm -f /system/lib/$ASAN_RT_SYMLINK - adb_shell ln -s $ASAN_RT /system/lib/$ASAN_RT_SYMLINK - - adb_shell rm /system/bin/app_process - adb_shell ln -s /system/bin/app_process.wrap /system/bin/app_process - fi - - adb_shell cp /system/bin/sh /system/bin/sh-from-zygote - adb_shell chcon $CTX /system/bin/sh-from-zygote - - if [[ ANDROID_O -eq 1 ]]; then - # For Android O, the linker namespace is temporarily disabled. - adb_shell mv /system/etc/ld.config.txt /system/etc/ld.config.txt.saved - fi - - if [ $ENFORCING == 1 ]; then - adb_shell setenforce 1 - fi - - echo '>> Restarting shell (asynchronous)' - adb_shell stop - adb_shell start - - echo '>> Please wait until the device restarts' -else - echo '>> Device is up to date' -fi - -rm -r "$TMPDIRBASE" diff --git a/lib/asan/scripts/asan_symbolize.py b/lib/asan/scripts/asan_symbolize.py deleted file mode 100755 index 2dbb05283c1e7..0000000000000 --- a/lib/asan/scripts/asan_symbolize.py +++ /dev/null @@ -1,523 +0,0 @@ -#!/usr/bin/env python -#===- lib/asan/scripts/asan_symbolize.py -----------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -import argparse -import bisect -import getopt -import os -import re -import subprocess -import sys - -symbolizers = {} -DEBUG = False -demangle = False -binutils_prefix = None -sysroot_path = None -binary_name_filter = None -fix_filename_patterns = None -logfile = sys.stdin -allow_system_symbolizer = True -force_system_symbolizer = False - -# FIXME: merge the code that calls fix_filename(). -def fix_filename(file_name): - if fix_filename_patterns: - for path_to_cut in fix_filename_patterns: - file_name = re.sub('.*' + path_to_cut, '', file_name) - file_name = re.sub('.*asan_[a-z_]*.cc:[0-9]*', '_asan_rtl_', file_name) - file_name = re.sub('.*crtstuff.c:0', '???:0', file_name) - return file_name - -def sysroot_path_filter(binary_name): - return sysroot_path + binary_name - -def is_valid_arch(s): - return s in ["i386", "x86_64", "x86_64h", "arm", "armv6", "armv7", "armv7s", - "armv7k", "arm64", "powerpc64", "powerpc64le", "s390x", "s390"] - -def guess_arch(addr): - # Guess which arch we're running. 10 = len('0x') + 8 hex digits. - if len(addr) > 10: - return 'x86_64' - else: - return 'i386' - -class Symbolizer(object): - def __init__(self): - pass - - def symbolize(self, addr, binary, offset): - """Symbolize the given address (pair of binary and offset). - - Overriden in subclasses. - Args: - addr: virtual address of an instruction. - binary: path to executable/shared object containing this instruction. - offset: instruction offset in the @binary. - Returns: - list of strings (one string for each inlined frame) describing - the code locations for this instruction (that is, function name, file - name, line and column numbers). - """ - return None - - -class LLVMSymbolizer(Symbolizer): - def __init__(self, symbolizer_path, default_arch, system, dsym_hints=[]): - super(LLVMSymbolizer, self).__init__() - self.symbolizer_path = symbolizer_path - self.default_arch = default_arch - self.system = system - self.dsym_hints = dsym_hints - self.pipe = self.open_llvm_symbolizer() - - def open_llvm_symbolizer(self): - cmd = [self.symbolizer_path, - '--use-symbol-table=true', - '--demangle=%s' % demangle, - '--functions=linkage', - '--inlining=true', - '--default-arch=%s' % self.default_arch] - if self.system == 'Darwin': - for hint in self.dsym_hints: - cmd.append('--dsym-hint=%s' % hint) - if DEBUG: - print(' '.join(cmd)) - try: - result = subprocess.Popen(cmd, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - bufsize=0, - universal_newlines=True) - except OSError: - result = None - return result - - def symbolize(self, addr, binary, offset): - """Overrides Symbolizer.symbolize.""" - if not self.pipe: - return None - result = [] - try: - symbolizer_input = '"%s" %s' % (binary, offset) - if DEBUG: - print(symbolizer_input) - self.pipe.stdin.write("%s\n" % symbolizer_input) - while True: - function_name = self.pipe.stdout.readline().rstrip() - if not function_name: - break - file_name = self.pipe.stdout.readline().rstrip() - file_name = fix_filename(file_name) - if (not function_name.startswith('??') or - not file_name.startswith('??')): - # Append only non-trivial frames. - result.append('%s in %s %s' % (addr, function_name, - file_name)) - except Exception: - result = [] - if not result: - result = None - return result - - -def LLVMSymbolizerFactory(system, default_arch, dsym_hints=[]): - symbolizer_path = os.getenv('LLVM_SYMBOLIZER_PATH') - if not symbolizer_path: - symbolizer_path = os.getenv('ASAN_SYMBOLIZER_PATH') - if not symbolizer_path: - # Assume llvm-symbolizer is in PATH. - symbolizer_path = 'llvm-symbolizer' - return LLVMSymbolizer(symbolizer_path, default_arch, system, dsym_hints) - - -class Addr2LineSymbolizer(Symbolizer): - def __init__(self, binary): - super(Addr2LineSymbolizer, self).__init__() - self.binary = binary - self.pipe = self.open_addr2line() - self.output_terminator = -1 - - def open_addr2line(self): - addr2line_tool = 'addr2line' - if binutils_prefix: - addr2line_tool = binutils_prefix + addr2line_tool - cmd = [addr2line_tool, '-fi'] - if demangle: - cmd += ['--demangle'] - cmd += ['-e', self.binary] - if DEBUG: - print(' '.join(cmd)) - return subprocess.Popen(cmd, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, - bufsize=0, - universal_newlines=True) - - def symbolize(self, addr, binary, offset): - """Overrides Symbolizer.symbolize.""" - if self.binary != binary: - return None - lines = [] - try: - self.pipe.stdin.write("%s\n" % offset) - self.pipe.stdin.write("%s\n" % self.output_terminator) - is_first_frame = True - while True: - function_name = self.pipe.stdout.readline().rstrip() - file_name = self.pipe.stdout.readline().rstrip() - if is_first_frame: - is_first_frame = False - elif function_name in ['', '??']: - assert file_name == function_name - break - lines.append((function_name, file_name)); - except Exception: - lines.append(('??', '??:0')) - return ['%s in %s %s' % (addr, function, fix_filename(file)) for (function, file) in lines] - -class UnbufferedLineConverter(object): - """ - Wrap a child process that responds to each line of input with one line of - output. Uses pty to trick the child into providing unbuffered output. - """ - def __init__(self, args, close_stderr=False): - # Local imports so that the script can start on Windows. - import pty - import termios - pid, fd = pty.fork() - if pid == 0: - # We're the child. Transfer control to command. - if close_stderr: - dev_null = os.open('/dev/null', 0) - os.dup2(dev_null, 2) - os.execvp(args[0], args) - else: - # Disable echoing. - attr = termios.tcgetattr(fd) - attr[3] = attr[3] & ~termios.ECHO - termios.tcsetattr(fd, termios.TCSANOW, attr) - # Set up a file()-like interface to the child process - self.r = os.fdopen(fd, "r", 1) - self.w = os.fdopen(os.dup(fd), "w", 1) - - def convert(self, line): - self.w.write(line + "\n") - return self.readline() - - def readline(self): - return self.r.readline().rstrip() - - -class DarwinSymbolizer(Symbolizer): - def __init__(self, addr, binary, arch): - super(DarwinSymbolizer, self).__init__() - self.binary = binary - self.arch = arch - self.open_atos() - - def open_atos(self): - if DEBUG: - print('atos -o %s -arch %s' % (self.binary, self.arch)) - cmdline = ['atos', '-o', self.binary, '-arch', self.arch] - self.atos = UnbufferedLineConverter(cmdline, close_stderr=True) - - def symbolize(self, addr, binary, offset): - """Overrides Symbolizer.symbolize.""" - if self.binary != binary: - return None - if not os.path.exists(binary): - # If the binary doesn't exist atos will exit which will lead to IOError - # exceptions being raised later on so just don't try to symbolize. - return ['{} ({}:{}+{})'.format(addr, binary, self.arch, offset)] - atos_line = self.atos.convert('0x%x' % int(offset, 16)) - while "got symbolicator for" in atos_line: - atos_line = self.atos.readline() - # A well-formed atos response looks like this: - # foo(type1, type2) (in object.name) (filename.cc:80) - match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line) - if DEBUG: - print('atos_line: ', atos_line) - if match: - function_name = match.group(1) - function_name = re.sub('\(.*?\)', '', function_name) - file_name = fix_filename(match.group(3)) - return ['%s in %s %s' % (addr, function_name, file_name)] - else: - return ['%s in %s' % (addr, atos_line)] - - -# Chain several symbolizers so that if one symbolizer fails, we fall back -# to the next symbolizer in chain. -class ChainSymbolizer(Symbolizer): - def __init__(self, symbolizer_list): - super(ChainSymbolizer, self).__init__() - self.symbolizer_list = symbolizer_list - - def symbolize(self, addr, binary, offset): - """Overrides Symbolizer.symbolize.""" - for symbolizer in self.symbolizer_list: - if symbolizer: - result = symbolizer.symbolize(addr, binary, offset) - if result: - return result - return None - - def append_symbolizer(self, symbolizer): - self.symbolizer_list.append(symbolizer) - - -def BreakpadSymbolizerFactory(binary): - suffix = os.getenv('BREAKPAD_SUFFIX') - if suffix: - filename = binary + suffix - if os.access(filename, os.F_OK): - return BreakpadSymbolizer(filename) - return None - - -def SystemSymbolizerFactory(system, addr, binary, arch): - if system == 'Darwin': - return DarwinSymbolizer(addr, binary, arch) - elif system in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']: - return Addr2LineSymbolizer(binary) - - -class BreakpadSymbolizer(Symbolizer): - def __init__(self, filename): - super(BreakpadSymbolizer, self).__init__() - self.filename = filename - lines = file(filename).readlines() - self.files = [] - self.symbols = {} - self.address_list = [] - self.addresses = {} - # MODULE mac x86_64 A7001116478B33F18FF9BEDE9F615F190 t - fragments = lines[0].rstrip().split() - self.arch = fragments[2] - self.debug_id = fragments[3] - self.binary = ' '.join(fragments[4:]) - self.parse_lines(lines[1:]) - - def parse_lines(self, lines): - cur_function_addr = '' - for line in lines: - fragments = line.split() - if fragments[0] == 'FILE': - assert int(fragments[1]) == len(self.files) - self.files.append(' '.join(fragments[2:])) - elif fragments[0] == 'PUBLIC': - self.symbols[int(fragments[1], 16)] = ' '.join(fragments[3:]) - elif fragments[0] in ['CFI', 'STACK']: - pass - elif fragments[0] == 'FUNC': - cur_function_addr = int(fragments[1], 16) - if not cur_function_addr in self.symbols.keys(): - self.symbols[cur_function_addr] = ' '.join(fragments[4:]) - else: - # Line starting with an address. - addr = int(fragments[0], 16) - self.address_list.append(addr) - # Tuple of symbol address, size, line, file number. - self.addresses[addr] = (cur_function_addr, - int(fragments[1], 16), - int(fragments[2]), - int(fragments[3])) - self.address_list.sort() - - def get_sym_file_line(self, addr): - key = None - if addr in self.addresses.keys(): - key = addr - else: - index = bisect.bisect_left(self.address_list, addr) - if index == 0: - return None - else: - key = self.address_list[index - 1] - sym_id, size, line_no, file_no = self.addresses[key] - symbol = self.symbols[sym_id] - filename = self.files[file_no] - if addr < key + size: - return symbol, filename, line_no - else: - return None - - def symbolize(self, addr, binary, offset): - if self.binary != binary: - return None - res = self.get_sym_file_line(int(offset, 16)) - if res: - function_name, file_name, line_no = res - result = ['%s in %s %s:%d' % ( - addr, function_name, file_name, line_no)] - print(result) - return result - else: - return None - - -class SymbolizationLoop(object): - def __init__(self, binary_name_filter=None, dsym_hint_producer=None): - if sys.platform == 'win32': - # ASan on Windows uses dbghelp.dll to symbolize in-process, which works - # even in sandboxed processes. Nothing needs to be done here. - self.process_line = self.process_line_echo - else: - # Used by clients who may want to supply a different binary name. - # E.g. in Chrome several binaries may share a single .dSYM. - self.binary_name_filter = binary_name_filter - self.dsym_hint_producer = dsym_hint_producer - self.system = os.uname()[0] - if self.system not in ['Linux', 'Darwin', 'FreeBSD', 'NetBSD','SunOS']: - raise Exception('Unknown system') - self.llvm_symbolizers = {} - self.last_llvm_symbolizer = None - self.dsym_hints = set([]) - self.frame_no = 0 - self.process_line = self.process_line_posix - - def symbolize_address(self, addr, binary, offset, arch): - # On non-Darwin (i.e. on platforms without .dSYM debug info) always use - # a single symbolizer binary. - # On Darwin, if the dsym hint producer is present: - # 1. check whether we've seen this binary already; if so, - # use |llvm_symbolizers[binary]|, which has already loaded the debug - # info for this binary (might not be the case for - # |last_llvm_symbolizer|); - # 2. otherwise check if we've seen all the hints for this binary already; - # if so, reuse |last_llvm_symbolizer| which has the full set of hints; - # 3. otherwise create a new symbolizer and pass all currently known - # .dSYM hints to it. - result = None - if not force_system_symbolizer: - if not binary in self.llvm_symbolizers: - use_new_symbolizer = True - if self.system == 'Darwin' and self.dsym_hint_producer: - dsym_hints_for_binary = set(self.dsym_hint_producer(binary)) - use_new_symbolizer = bool(dsym_hints_for_binary - self.dsym_hints) - self.dsym_hints |= dsym_hints_for_binary - if self.last_llvm_symbolizer and not use_new_symbolizer: - self.llvm_symbolizers[binary] = self.last_llvm_symbolizer - else: - self.last_llvm_symbolizer = LLVMSymbolizerFactory( - self.system, arch, self.dsym_hints) - self.llvm_symbolizers[binary] = self.last_llvm_symbolizer - # Use the chain of symbolizers: - # Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos - # (fall back to next symbolizer if the previous one fails). - if not binary in symbolizers: - symbolizers[binary] = ChainSymbolizer( - [BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]]) - result = symbolizers[binary].symbolize(addr, binary, offset) - else: - symbolizers[binary] = ChainSymbolizer([]) - if result is None: - if not allow_system_symbolizer: - raise Exception('Failed to launch or use llvm-symbolizer.') - # Initialize system symbolizer only if other symbolizers failed. - symbolizers[binary].append_symbolizer( - SystemSymbolizerFactory(self.system, addr, binary, arch)) - result = symbolizers[binary].symbolize(addr, binary, offset) - # The system symbolizer must produce some result. - assert result - return result - - def get_symbolized_lines(self, symbolized_lines): - if not symbolized_lines: - return [self.current_line] - else: - result = [] - for symbolized_frame in symbolized_lines: - result.append(' #%s %s' % (str(self.frame_no), symbolized_frame.rstrip())) - self.frame_no += 1 - return result - - def process_logfile(self): - self.frame_no = 0 - for line in logfile: - processed = self.process_line(line) - print('\n'.join(processed)) - - def process_line_echo(self, line): - return [line.rstrip()] - - def process_line_posix(self, line): - self.current_line = line.rstrip() - #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45) - stack_trace_line_format = ( - '^( *#([0-9]+) *)(0x[0-9a-f]+) *\((.*)\+(0x[0-9a-f]+)\)') - match = re.match(stack_trace_line_format, line) - if not match: - return [self.current_line] - if DEBUG: - print(line) - _, frameno_str, addr, binary, offset = match.groups() - arch = "" - # Arch can be embedded in the filename, e.g.: "libabc.dylib:x86_64h" - colon_pos = binary.rfind(":") - if colon_pos != -1: - maybe_arch = binary[colon_pos+1:] - if is_valid_arch(maybe_arch): - arch = maybe_arch - binary = binary[0:colon_pos] - if arch == "": - arch = guess_arch(addr) - if frameno_str == '0': - # Assume that frame #0 is the first frame of new stack trace. - self.frame_no = 0 - original_binary = binary - if self.binary_name_filter: - binary = self.binary_name_filter(binary) - symbolized_line = self.symbolize_address(addr, binary, offset, arch) - if not symbolized_line: - if original_binary != binary: - symbolized_line = self.symbolize_address(addr, original_binary, offset, arch) - return self.get_symbolized_lines(symbolized_line) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description='ASan symbolization script', - epilog='Example of use:\n' - 'asan_symbolize.py -c "$HOME/opt/cross/bin/arm-linux-gnueabi-" ' - '-s "$HOME/SymbolFiles" < asan.log') - parser.add_argument('path_to_cut', nargs='*', - help='pattern to be cut from the result file path ') - parser.add_argument('-d','--demangle', action='store_true', - help='demangle function names') - parser.add_argument('-s', metavar='SYSROOT', - help='set path to sysroot for sanitized binaries') - parser.add_argument('-c', metavar='CROSS_COMPILE', - help='set prefix for binutils') - parser.add_argument('-l','--logfile', default=sys.stdin, - type=argparse.FileType('r'), - help='set log file name to parse, default is stdin') - parser.add_argument('--force-system-symbolizer', action='store_true', - help='don\'t use llvm-symbolizer') - args = parser.parse_args() - if args.path_to_cut: - fix_filename_patterns = args.path_to_cut - if args.demangle: - demangle = True - if args.s: - binary_name_filter = sysroot_path_filter - sysroot_path = args.s - if args.c: - binutils_prefix = args.c - if args.logfile: - logfile = args.logfile - else: - logfile = sys.stdin - if args.force_system_symbolizer: - force_system_symbolizer = True - if force_system_symbolizer: - assert(allow_system_symbolizer) - loop = SymbolizationLoop(binary_name_filter) - loop.process_logfile() diff --git a/lib/asan/tests/CMakeLists.txt b/lib/asan/tests/CMakeLists.txt deleted file mode 100644 index 9e640d1d8b012..0000000000000 --- a/lib/asan/tests/CMakeLists.txt +++ /dev/null @@ -1,309 +0,0 @@ -# Testing rules for AddressSanitizer. -# -# These are broken into two buckets. One set of tests directly interacts with -# the runtime library and checks its functionality. These are the -# no-instrumentation tests. -# -# Another group of tests relies upon the ability to compile the test with -# address sanitizer instrumentation pass. These tests form "integration" tests -# and have some elements of version skew -- they test the *host* compiler's -# instrumentation against the just-built runtime library. - -include(CheckCXXCompilerFlag) -include(CompilerRTCompile) - -include_directories(..) -include_directories(../..) - -set(ASAN_UNITTEST_HEADERS - asan_mac_test.h - asan_test_config.h - asan_test_utils.h) - -set(ASAN_UNITTEST_COMMON_CFLAGS - ${COMPILER_RT_UNITTEST_CFLAGS} - ${COMPILER_RT_GTEST_CFLAGS} - ${COMPILER_RT_ASAN_SHADOW_SCALE_LLVM_FLAG} - -I${COMPILER_RT_SOURCE_DIR}/include - -I${COMPILER_RT_SOURCE_DIR}/lib - -I${COMPILER_RT_SOURCE_DIR}/lib/asan - -I${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/tests - -fno-rtti - -O2 - -Wno-format - -Werror=sign-compare - -Wno-non-virtual-dtor) -append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros ASAN_UNITTEST_COMMON_CFLAGS) - -# This will ensure the target linker is used -# during cross compilation -set(ASAN_UNITTEST_COMMON_LINK_FLAGS - ${COMPILER_RT_UNITTEST_LINK_FLAGS}) - -# -gline-tables-only must be enough for ASan, so use it if possible. -if(COMPILER_RT_TEST_COMPILER_ID MATCHES "Clang") - list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -gline-tables-only) -else() - list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -g) -endif() -if(MSVC) - list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -gcodeview) -endif() -list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS -g) - -# Use -D instead of definitions to please custom compile command. -list(APPEND ASAN_UNITTEST_COMMON_CFLAGS - ${COMPILER_RT_ASAN_SHADOW_SCALE_FLAG} - -DASAN_HAS_BLACKLIST=1 - -DASAN_HAS_EXCEPTIONS=1 - -DASAN_UAR=0) - -if(APPLE) - list(APPEND ASAN_UNITTEST_COMMON_CFLAGS ${DARWIN_osx_CFLAGS}) - list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS ${DARWIN_osx_LINK_FLAGS}) - - add_weak_symbols("asan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("ubsan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) - list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS}) -endif() - -set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore") -set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS - ${ASAN_UNITTEST_COMMON_CFLAGS} - -fsanitize=address - "-fsanitize-blacklist=${ASAN_BLACKLIST_FILE}" -) -if(CAN_TARGET_x86_64 OR CAN_TARGET_i386) - list(APPEND ASAN_UNITTEST_INSTRUMENTED_CFLAGS -mllvm -asan-instrument-assembly) -endif() - -if(NOT MSVC) - list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS --driver-mode=g++) -endif() - -# x86_64 FreeBSD 9.2 additionally requires libc++ to build the tests. -if(CMAKE_SYSTEM MATCHES "FreeBSD-9.2-RELEASE") - list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS "-lc++") -endif() - -# Unit tests on Mac depend on Foundation. -if(APPLE) - list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS -framework Foundation) -endif() -if(ANDROID) - list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS -pie) -endif() - -set(ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS - ${ASAN_UNITTEST_COMMON_LINK_FLAGS}) -list(APPEND ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS -fsanitize=address) - -set(ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS - ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS} - -shared-libasan) - -set(ASAN_UNITTEST_INSTRUMENTED_LIBS) -# NDK r10 requires -latomic almost always. -append_list_if(ANDROID atomic ASAN_UNITTEST_INSTRUMENTED_LIBS) - -set(ASAN_UNITTEST_NOINST_LINK_FLAGS ${ASAN_UNITTEST_COMMON_LINK_FLAGS}) -if(NOT APPLE) - append_list_if(COMPILER_RT_HAS_LIBM -lm ASAN_UNITTEST_NOINST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LIBDL -ldl ASAN_UNITTEST_NOINST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LIBRT -lrt ASAN_UNITTEST_NOINST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread ASAN_UNITTEST_NOINST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS) -endif() - -# TODO(eugenis): move all -l flags above to _LIBS? -set(ASAN_UNITTEST_NOINST_LIBS) -append_list_if(COMPILER_RT_HAS_LIBLOG log ASAN_UNITTEST_NOINST_LIBS) -# NDK r10 requires -latomic almost always. -append_list_if(ANDROID atomic ASAN_UNITTEST_NOINST_LIBS) - -# Main AddressSanitizer unit tests. -add_custom_target(AsanUnitTests) -set_target_properties(AsanUnitTests PROPERTIES FOLDER "Compiler-RT Tests") - -# AddressSanitizer unit tests with dynamic runtime (on platforms where it's -# not the default). -add_custom_target(AsanDynamicUnitTests) -set_target_properties(AsanDynamicUnitTests PROPERTIES FOLDER "Compiler-RT Tests") -# ASan benchmarks (not actively used now). -add_custom_target(AsanBenchmarks) -set_target_properties(AsanBenchmarks PROPERTIES FOLDER "Compiler-RT Tests") - -set(ASAN_NOINST_TEST_SOURCES - ${COMPILER_RT_GTEST_SOURCE} - asan_fake_stack_test.cc - asan_noinst_test.cc - asan_test_main.cc) - -set(ASAN_INST_TEST_SOURCES - ${COMPILER_RT_GTEST_SOURCE} - asan_asm_test.cc - asan_globals_test.cc - asan_interface_test.cc - asan_internal_interface_test.cc - asan_test.cc - asan_oob_test.cc - asan_mem_test.cc - asan_str_test.cc - asan_test_main.cc) -if(APPLE) - list(APPEND ASAN_INST_TEST_SOURCES asan_mac_test.cc asan_mac_test_helpers.mm) -endif() - -set(ASAN_BENCHMARKS_SOURCES - ${COMPILER_RT_GTEST_SOURCE} - asan_benchmarks_test.cc) - -function(add_asan_tests arch test_runtime) - cmake_parse_arguments(TEST "" "KIND" "CFLAGS" ${ARGN}) - - # Closure to keep the values. - function(generate_asan_tests test_objects test_suite testname) - generate_compiler_rt_tests(${test_objects} ${test_suite} ${testname} ${arch} - COMPILE_DEPS ${ASAN_UNITTEST_HEADERS} ${ASAN_BLACKLIST_FILE} - DEPS gtest asan - KIND ${TEST_KIND} - ${ARGN} - ) - set("${test_objects}" "${${test_objects}}" PARENT_SCOPE) - endfunction() - - set(ASAN_INST_TEST_OBJECTS) - generate_asan_tests(ASAN_INST_TEST_OBJECTS AsanUnitTests - "Asan-${arch}${TEST_KIND}-Test" - SUBDIR "default" - LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS} - SOURCES ${ASAN_INST_TEST_SOURCES} - CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} ${TEST_CFLAGS}) - - if(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME) - set(dynamic_test_name "Asan-${arch}${TEST_KIND}-Dynamic-Test") - if(MSVC) - - # With the MSVC CRT, the choice between static and dynamic CRT is made at - # compile time with a macro. Simulate the effect of passing /MD to clang-cl. - set(ASAN_DYNAMIC_TEST_OBJECTS) - generate_asan_tests(ASAN_DYNAMIC_TEST_OBJECTS - AsanDynamicUnitTests "${dynamic_test_name}" - SUBDIR "dynamic" - CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -D_MT -D_DLL - SOURCES ${ASAN_INST_TEST_SOURCES} - LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS} - -Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames - ) - else() - - # Otherwise, reuse ASAN_INST_TEST_OBJECTS. - add_compiler_rt_test(AsanDynamicUnitTests "${dynamic_test_name}" "${arch}" - SUBDIR "dynamic" - OBJECTS ${ASAN_INST_TEST_OBJECTS} - DEPS asan ${ASAN_INST_TEST_OBJECTS} - LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS} - ) - endif() - endif() - - # Uninstrumented tests. - set(ASAN_NOINST_TEST_OBJECTS) - generate_asan_tests(ASAN_NOINST_TEST_OBJECTS - AsanUnitTests "Asan-${arch}${TEST_KIND}-Noinst-Test" - SUBDIR "default" - CFLAGS ${ASAN_UNITTEST_COMMON_CFLAGS} - LINK_FLAGS ${ASAN_UNITTEST_NOINST_LINK_FLAGS} - SOURCES ${ASAN_NOINST_TEST_SOURCES} - RUNTIME ${test_runtime}) - - set(ASAN_BENCHMARK_OBJECTS) - generate_asan_tests(ASAN_BENCHMARK_OBJECTS - AsanBenchmarks "Asan-${arch}${TEST_KIND}-Benchmark" - SUBDIR "default" - CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} - SOURCES ${ASAN_BENCHMARKS_SOURCES} - LINK_FLAGS ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS}) -endfunction() - -if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID) - set(ASAN_TEST_ARCH ${ASAN_SUPPORTED_ARCH}) - if(APPLE) - darwin_filter_host_archs(ASAN_SUPPORTED_ARCH ASAN_TEST_ARCH) - endif() - if(OS_NAME MATCHES "SunOS") - list(REMOVE_ITEM ASAN_TEST_ARCH x86_64) - endif() - - foreach(arch ${ASAN_TEST_ARCH}) - - # Add static ASan runtime that will be linked with uninstrumented tests. - set(ASAN_TEST_RUNTIME RTAsanTest.${arch}) - if(APPLE) - set(ASAN_TEST_RUNTIME_OBJECTS - $<TARGET_OBJECTS:RTAsan_dynamic.osx> - $<TARGET_OBJECTS:RTInterception.osx> - $<TARGET_OBJECTS:RTSanitizerCommon.osx> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.osx> - $<TARGET_OBJECTS:RTSanitizerCommonCoverage.osx> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.osx> - $<TARGET_OBJECTS:RTLSanCommon.osx> - $<TARGET_OBJECTS:RTUbsan.osx>) - else() - set(ASAN_TEST_RUNTIME_OBJECTS - $<TARGET_OBJECTS:RTAsan.${arch}> - $<TARGET_OBJECTS:RTAsan_cxx.${arch}> - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> - $<TARGET_OBJECTS:RTLSanCommon.${arch}> - $<TARGET_OBJECTS:RTUbsan.${arch}> - $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>) - endif() - add_library(${ASAN_TEST_RUNTIME} STATIC ${ASAN_TEST_RUNTIME_OBJECTS}) - set_target_properties(${ASAN_TEST_RUNTIME} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - FOLDER "Compiler-RT Runtime tests") - - add_asan_tests(${arch} ${ASAN_TEST_RUNTIME} KIND "-inline") - add_asan_tests(${arch} ${ASAN_TEST_RUNTIME} KIND "-calls" - CFLAGS -mllvm -asan-instrumentation-with-call-threshold=0) - endforeach() -endif() - -if(ANDROID) - foreach(arch ${ASAN_SUPPORTED_ARCH}) - # Test w/o ASan instrumentation. Link it with ASan statically. - add_executable(AsanNoinstTest # FIXME: .arch? - $<TARGET_OBJECTS:RTAsan.${arch}> - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> - $<TARGET_OBJECTS:RTUbsan.${arch}> - $<TARGET_OBJECTS:RTUbsan_cxx.${arch}> - ${COMPILER_RT_GTEST_SOURCE} - ${ASAN_NOINST_TEST_SOURCES}) - set_target_compile_flags(AsanNoinstTest ${ASAN_UNITTEST_COMMON_CFLAGS}) - set_target_link_flags(AsanNoinstTest ${ASAN_UNITTEST_NOINST_LINK_FLAGS}) - target_link_libraries(AsanNoinstTest ${ASAN_UNITTEST_NOINST_LIBS}) - - # Test with ASan instrumentation. Link with ASan dynamic runtime. - add_executable(AsanTest - ${COMPILER_RT_GTEST_SOURCE} - ${ASAN_INST_TEST_SOURCES}) - set_target_compile_flags(AsanTest ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS}) - set_target_link_flags(AsanTest ${ASAN_UNITTEST_INSTRUMENTED_LINK_FLAGS}) - target_link_libraries(AsanTest ${ASAN_UNITTEST_INSTRUMENTED_LIBS}) - - # Setup correct output directory and link flags. - set_target_properties(AsanNoinstTest AsanTest PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - # Add unit tests to the test suite. - add_dependencies(AsanUnitTests AsanNoinstTest AsanTest) - endforeach() -endif() diff --git a/lib/asan/tests/asan_asm_test.cc b/lib/asan/tests/asan_asm_test.cc deleted file mode 100644 index 91f8aacd6eeb1..0000000000000 --- a/lib/asan/tests/asan_asm_test.cc +++ /dev/null @@ -1,274 +0,0 @@ -//===-- asan_asm_test.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -#if defined(__linux__) && \ - (!defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3) - -// Assembly instrumentation is broken on x86 Android (x86 + PIC + shared runtime -// library). See https://github.com/google/sanitizers/issues/353 -#if defined(__x86_64__) || \ - (defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__)) - -#include <emmintrin.h> - -namespace { - -template<typename T> void asm_write(T *ptr, T val); -template<typename T> T asm_read(T *ptr); -template<typename T> void asm_rep_movs(T *dst, T *src, size_t n); - -} // End of anonymous namespace - -#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#if defined(__x86_64__) - -namespace { - -#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg) \ -template<> void asm_write<Type>(Type *ptr, Type val) { \ - __asm__( \ - Mov " %[val], (%[ptr]) \n\t" \ - : \ - : [ptr] "r" (ptr), [val] Reg (val) \ - : "memory" \ - ); \ -} - -#define DECLARE_ASM_READ(Type, Size, Mov, Reg) \ -template<> Type asm_read<Type>(Type *ptr) { \ - Type res; \ - __asm__( \ - Mov " (%[ptr]), %[res] \n\t" \ - : [res] Reg (res) \ - : [ptr] "r" (ptr) \ - : "memory" \ - ); \ - return res; \ -} - -#define DECLARE_ASM_REP_MOVS(Type, Movs) \ - template <> \ - void asm_rep_movs<Type>(Type * dst, Type * src, size_t size) { \ - __asm__("rep " Movs " \n\t" \ - : "+D"(dst), "+S"(src), "+c"(size) \ - : \ - : "memory"); \ - } - -DECLARE_ASM_WRITE(U8, "8", "movq", "r"); -DECLARE_ASM_READ(U8, "8", "movq", "=r"); -DECLARE_ASM_REP_MOVS(U8, "movsq"); - -} // End of anonymous namespace - -#endif // defined(__x86_64__) - -#if defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__) - -namespace { - -#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg) \ -template<> void asm_write<Type>(Type *ptr, Type val) { \ - __asm__( \ - Mov " %[val], (%[ptr]) \n\t" \ - : \ - : [ptr] "r" (ptr), [val] Reg (val) \ - : "memory" \ - ); \ -} - -#define DECLARE_ASM_READ(Type, Size, Mov, Reg) \ -template<> Type asm_read<Type>(Type *ptr) { \ - Type res; \ - __asm__( \ - Mov " (%[ptr]), %[res] \n\t" \ - : [res] Reg (res) \ - : [ptr] "r" (ptr) \ - : "memory" \ - ); \ - return res; \ -} - -#define DECLARE_ASM_REP_MOVS(Type, Movs) \ - template <> \ - void asm_rep_movs<Type>(Type * dst, Type * src, size_t size) { \ - __asm__("rep " Movs " \n\t" \ - : "+D"(dst), "+S"(src), "+c"(size) \ - : \ - : "memory"); \ - } - -} // End of anonymous namespace - -#endif // defined(__i386__) && defined(__SSE2__) - -#if defined(__x86_64__) || \ - (defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__)) - -namespace { - -DECLARE_ASM_WRITE(U1, "1", "movb", "r"); -DECLARE_ASM_WRITE(U2, "2", "movw", "r"); -DECLARE_ASM_WRITE(U4, "4", "movl", "r"); -DECLARE_ASM_WRITE(__m128i, "16", "movaps", "x"); - -DECLARE_ASM_READ(U1, "1", "movb", "=r"); -DECLARE_ASM_READ(U2, "2", "movw", "=r"); -DECLARE_ASM_READ(U4, "4", "movl", "=r"); -DECLARE_ASM_READ(__m128i, "16", "movaps", "=x"); - -DECLARE_ASM_REP_MOVS(U1, "movsb"); -DECLARE_ASM_REP_MOVS(U2, "movsw"); -DECLARE_ASM_REP_MOVS(U4, "movsl"); - -template<typename T> void TestAsmWrite(const char *DeathPattern) { - T *buf = new T; - EXPECT_DEATH(asm_write(&buf[1], static_cast<T>(0)), DeathPattern); - T var = 0x12; - asm_write(&var, static_cast<T>(0x21)); - ASSERT_EQ(static_cast<T>(0x21), var); - delete buf; -} - -template<> void TestAsmWrite<__m128i>(const char *DeathPattern) { - char *buf = new char[16]; - char *p = buf + 16; - if (((uintptr_t) p % 16) != 0) - p = buf + 8; - assert(((uintptr_t) p % 16) == 0); - __m128i val = _mm_set1_epi16(0x1234); - EXPECT_DEATH(asm_write<__m128i>((__m128i*) p, val), DeathPattern); - __m128i var = _mm_set1_epi16(0x4321); - asm_write(&var, val); - ASSERT_EQ(0x1234, _mm_extract_epi16(var, 0)); - delete [] buf; -} - -template<typename T> void TestAsmRead(const char *DeathPattern) { - T *buf = new T; - EXPECT_DEATH(asm_read(&buf[1]), DeathPattern); - T var = 0x12; - ASSERT_EQ(static_cast<T>(0x12), asm_read(&var)); - delete buf; -} - -template<> void TestAsmRead<__m128i>(const char *DeathPattern) { - char *buf = new char[16]; - char *p = buf + 16; - if (((uintptr_t) p % 16) != 0) - p = buf + 8; - assert(((uintptr_t) p % 16) == 0); - EXPECT_DEATH(asm_read<__m128i>((__m128i*) p), DeathPattern); - __m128i val = _mm_set1_epi16(0x1234); - ASSERT_EQ(0x1234, _mm_extract_epi16(asm_read(&val), 0)); - delete [] buf; -} - -U4 AsmLoad(U4 *a) { - U4 r; - __asm__("movl (%[a]), %[r] \n\t" : [r] "=r" (r) : [a] "r" (a) : "memory"); - return r; -} - -void AsmStore(U4 r, U4 *a) { - __asm__("movl %[r], (%[a]) \n\t" : : [a] "r" (a), [r] "r" (r) : "memory"); -} - -template <typename T> -void TestAsmRepMovs(const char *DeathPatternRead, - const char *DeathPatternWrite) { - T src_good[4] = { 0x0, 0x1, 0x2, 0x3 }; - T dst_good[4] = {}; - asm_rep_movs(dst_good, src_good, 4); - ASSERT_EQ(static_cast<T>(0x0), dst_good[0]); - ASSERT_EQ(static_cast<T>(0x1), dst_good[1]); - ASSERT_EQ(static_cast<T>(0x2), dst_good[2]); - ASSERT_EQ(static_cast<T>(0x3), dst_good[3]); - - T dst_bad[3]; - EXPECT_DEATH(asm_rep_movs(dst_bad, src_good, 4), DeathPatternWrite); - - T src_bad[3] = { 0x0, 0x1, 0x2 }; - EXPECT_DEATH(asm_rep_movs(dst_good, src_bad, 4), DeathPatternRead); - - T* dp = dst_bad + 4; - T* sp = src_bad + 4; - asm_rep_movs(dp, sp, 0); -} - -} // End of anonymous namespace - -TEST(AddressSanitizer, asm_load_store) { - U4* buf = new U4[2]; - EXPECT_DEATH(AsmLoad(&buf[3]), "READ of size 4"); - EXPECT_DEATH(AsmStore(0x1234, &buf[3]), "WRITE of size 4"); - delete [] buf; -} - -TEST(AddressSanitizer, asm_rw) { - TestAsmWrite<U1>("WRITE of size 1"); - TestAsmWrite<U2>("WRITE of size 2"); - TestAsmWrite<U4>("WRITE of size 4"); -#if defined(__x86_64__) - TestAsmWrite<U8>("WRITE of size 8"); -#endif // defined(__x86_64__) - TestAsmWrite<__m128i>("WRITE of size 16"); - - TestAsmRead<U1>("READ of size 1"); - TestAsmRead<U2>("READ of size 2"); - TestAsmRead<U4>("READ of size 4"); -#if defined(__x86_64__) - TestAsmRead<U8>("READ of size 8"); -#endif // defined(__x86_64__) - TestAsmRead<__m128i>("READ of size 16"); -} - -TEST(AddressSanitizer, asm_flags) { - long magic = 0x1234; - long r = 0x0; - -#if defined(__x86_64__) && !defined(__ILP32__) - __asm__("xorq %%rax, %%rax \n\t" - "movq (%[p]), %%rax \n\t" - "sete %%al \n\t" - "movzbq %%al, %[r] \n\t" - : [r] "=r"(r) - : [p] "r"(&magic) - : "rax", "memory"); -#else - __asm__("xorl %%eax, %%eax \n\t" - "movl (%[p]), %%eax \n\t" - "sete %%al \n\t" - "movzbl %%al, %[r] \n\t" - : [r] "=r"(r) - : [p] "r"(&magic) - : "eax", "memory"); -#endif // defined(__x86_64__) && !defined(__ILP32__) - - ASSERT_EQ(0x1, r); -} - -TEST(AddressSanitizer, asm_rep_movs) { - TestAsmRepMovs<U1>("READ of size 1", "WRITE of size 1"); - TestAsmRepMovs<U2>("READ of size 2", "WRITE of size 2"); - TestAsmRepMovs<U4>("READ of size 4", "WRITE of size 4"); -#if defined(__x86_64__) - TestAsmRepMovs<U8>("READ of size 8", "WRITE of size 8"); -#endif // defined(__x86_64__) -} - -#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#endif // defined(__linux__) diff --git a/lib/asan/tests/asan_benchmarks_test.cc b/lib/asan/tests/asan_benchmarks_test.cc deleted file mode 100644 index fc522de475faa..0000000000000 --- a/lib/asan/tests/asan_benchmarks_test.cc +++ /dev/null @@ -1,85 +0,0 @@ -//===-- asan_benchmarks_test.cc ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// Some benchmarks for the instrumented code. -//===----------------------------------------------------------------------===// - -#include "asan_test_utils.h" - -template<class T> -__attribute__((noinline)) -static void ManyAccessFunc(T *x, size_t n_elements, size_t n_iter) { - for (size_t iter = 0; iter < n_iter; iter++) { - break_optimization(0); - // hand unroll the loop to stress the reg alloc. - for (size_t i = 0; i <= n_elements - 16; i += 16) { - x[i + 0] = i; - x[i + 1] = i; - x[i + 2] = i; - x[i + 3] = i; - x[i + 4] = i; - x[i + 5] = i; - x[i + 6] = i; - x[i + 7] = i; - x[i + 8] = i; - x[i + 9] = i; - x[i + 10] = i; - x[i + 11] = i; - x[i + 12] = i; - x[i + 13] = i; - x[i + 14] = i; - x[i + 15] = i; - } - } -} - -TEST(AddressSanitizer, ManyAccessBenchmark) { - size_t kLen = 1024; - int *int_array = new int[kLen]; - ManyAccessFunc(int_array, kLen, 1 << 24); - delete [] int_array; -} - -// access 7 char elements in a 7 byte array (i.e. on the border). -__attribute__((noinline)) -static void BorderAccessFunc(char *x, size_t n_iter) { - for (size_t iter = 0; iter < n_iter; iter++) { - break_optimization(x); - x[0] = 0; - x[1] = 0; - x[2] = 0; - x[3] = 0; - x[4] = 0; - x[5] = 0; - x[6] = 0; - } -} - -TEST(AddressSanitizer, BorderAccessBenchmark) { - char *char_7_array = new char[7]; - BorderAccessFunc(char_7_array, 1 << 30); - delete [] char_7_array; -} - -static void FunctionWithLargeStack() { - int stack[1000]; - Ident(stack); -} - -TEST(AddressSanitizer, FakeStackBenchmark) { - for (int i = 0; i < 10000000; i++) - Ident(&FunctionWithLargeStack)(); -} - -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/lib/asan/tests/asan_exceptions_test.cc b/lib/asan/tests/asan_exceptions_test.cc deleted file mode 100644 index ecd406de7561f..0000000000000 --- a/lib/asan/tests/asan_exceptions_test.cc +++ /dev/null @@ -1,27 +0,0 @@ -// See http://llvm.org/bugs/show_bug.cgi?id=11468 -#include <stdio.h> -#include <string> - -class Action { - public: - Action() {} - void PrintString(const std::string& msg) const { - fprintf(stderr, "%s\n", msg.c_str()); - } - void Throw(const char& arg) const { - PrintString("PrintString called!"); // this line is important - throw arg; - } -}; - -int main() { - const Action a; - fprintf(stderr, "&a before = %p\n", &a); - try { - a.Throw('c'); - } catch(const char&) { - fprintf(stderr, "&a in catch = %p\n", &a); - } - fprintf(stderr, "&a final = %p\n", &a); - return 0; -} diff --git a/lib/asan/tests/asan_fake_stack_test.cc b/lib/asan/tests/asan_fake_stack_test.cc deleted file mode 100644 index 516142f0c3b73..0000000000000 --- a/lib/asan/tests/asan_fake_stack_test.cc +++ /dev/null @@ -1,152 +0,0 @@ -//===-- asan_fake_stack_test.cc -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// Tests for FakeStack. -// This test file should be compiled w/o asan instrumentation. -//===----------------------------------------------------------------------===// - -#include "asan_fake_stack.h" -#include "asan_test_utils.h" -#include "sanitizer_common/sanitizer_common.h" - -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> - -#include <map> - -namespace __asan { - -TEST(FakeStack, FlagsSize) { - EXPECT_EQ(FakeStack::SizeRequiredForFlags(10), 1U << 5); - EXPECT_EQ(FakeStack::SizeRequiredForFlags(11), 1U << 6); - EXPECT_EQ(FakeStack::SizeRequiredForFlags(20), 1U << 15); -} - -TEST(FakeStack, RequiredSize) { - // for (int i = 15; i < 20; i++) { - // uptr alloc_size = FakeStack::RequiredSize(i); - // printf("%zdK ==> %zd\n", 1 << (i - 10), alloc_size); - // } - EXPECT_EQ(FakeStack::RequiredSize(15), 365568U); - EXPECT_EQ(FakeStack::RequiredSize(16), 727040U); - EXPECT_EQ(FakeStack::RequiredSize(17), 1449984U); - EXPECT_EQ(FakeStack::RequiredSize(18), 2895872U); - EXPECT_EQ(FakeStack::RequiredSize(19), 5787648U); -} - -TEST(FakeStack, FlagsOffset) { - for (uptr stack_size_log = 15; stack_size_log <= 20; stack_size_log++) { - uptr stack_size = 1UL << stack_size_log; - uptr offset = 0; - for (uptr class_id = 0; class_id < FakeStack::kNumberOfSizeClasses; - class_id++) { - uptr frame_size = FakeStack::BytesInSizeClass(class_id); - uptr num_flags = stack_size / frame_size; - EXPECT_EQ(offset, FakeStack::FlagsOffset(stack_size_log, class_id)); - // printf("%zd: %zd => %zd %zd\n", stack_size_log, class_id, offset, - // FakeStack::FlagsOffset(stack_size_log, class_id)); - offset += num_flags; - } - } -} - -#if !defined(_WIN32) // FIXME: Fails due to OOM on Windows. -TEST(FakeStack, CreateDestroy) { - for (int i = 0; i < 1000; i++) { - for (uptr stack_size_log = 20; stack_size_log <= 22; stack_size_log++) { - FakeStack *fake_stack = FakeStack::Create(stack_size_log); - fake_stack->Destroy(0); - } - } -} -#endif - -TEST(FakeStack, ModuloNumberOfFrames) { - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, 0), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<15)), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<10)), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<9)), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<8)), 1U<<8); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 0, (1<<15) + 1), 1U); - - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 0), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<9), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<8), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 1, 1<<7), 1U<<7); - - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 0), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 1), 1U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 15), 15U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 16), 0U); - EXPECT_EQ(FakeStack::ModuloNumberOfFrames(15, 5, 17), 1U); -} - -TEST(FakeStack, GetFrame) { - const uptr stack_size_log = 20; - const uptr stack_size = 1 << stack_size_log; - FakeStack *fs = FakeStack::Create(stack_size_log); - u8 *base = fs->GetFrame(stack_size_log, 0, 0); - EXPECT_EQ(base, reinterpret_cast<u8 *>(fs) + - fs->SizeRequiredForFlags(stack_size_log) + 4096); - EXPECT_EQ(base + 0*stack_size + 64 * 7, fs->GetFrame(stack_size_log, 0, 7U)); - EXPECT_EQ(base + 1*stack_size + 128 * 3, fs->GetFrame(stack_size_log, 1, 3U)); - EXPECT_EQ(base + 2*stack_size + 256 * 5, fs->GetFrame(stack_size_log, 2, 5U)); - fs->Destroy(0); -} - -TEST(FakeStack, Allocate) { - const uptr stack_size_log = 19; - FakeStack *fs = FakeStack::Create(stack_size_log); - std::map<FakeFrame *, uptr> s; - for (int iter = 0; iter < 2; iter++) { - s.clear(); - for (uptr cid = 0; cid < FakeStack::kNumberOfSizeClasses; cid++) { - uptr n = FakeStack::NumberOfFrames(stack_size_log, cid); - uptr bytes_in_class = FakeStack::BytesInSizeClass(cid); - for (uptr j = 0; j < n; j++) { - FakeFrame *ff = fs->Allocate(stack_size_log, cid, 0); - uptr x = reinterpret_cast<uptr>(ff); - EXPECT_TRUE(s.insert(std::make_pair(ff, cid)).second); - EXPECT_EQ(x, fs->AddrIsInFakeStack(x)); - EXPECT_EQ(x, fs->AddrIsInFakeStack(x + 1)); - EXPECT_EQ(x, fs->AddrIsInFakeStack(x + bytes_in_class - 1)); - EXPECT_NE(x, fs->AddrIsInFakeStack(x + bytes_in_class)); - } - // We are out of fake stack, so Allocate should return 0. - EXPECT_EQ(0UL, fs->Allocate(stack_size_log, cid, 0)); - } - for (std::map<FakeFrame *, uptr>::iterator it = s.begin(); it != s.end(); - ++it) { - fs->Deallocate(reinterpret_cast<uptr>(it->first), it->second); - } - } - fs->Destroy(0); -} - -static void RecursiveFunction(FakeStack *fs, int depth) { - uptr class_id = depth / 3; - FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, 0); - if (depth) { - RecursiveFunction(fs, depth - 1); - RecursiveFunction(fs, depth - 1); - } - fs->Deallocate(reinterpret_cast<uptr>(ff), class_id); -} - -TEST(FakeStack, RecursiveStressTest) { - const uptr stack_size_log = 16; - FakeStack *fs = FakeStack::Create(stack_size_log); - RecursiveFunction(fs, 22); // with 26 runs for 2-3 seconds. - fs->Destroy(0); -} - -} // namespace __asan diff --git a/lib/asan/tests/asan_globals_test.cc b/lib/asan/tests/asan_globals_test.cc deleted file mode 100644 index 5042ef07378d3..0000000000000 --- a/lib/asan/tests/asan_globals_test.cc +++ /dev/null @@ -1,45 +0,0 @@ -//===-- asan_globals_test.cc ----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// Some globals in a separate file. -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -char glob1[1]; -char glob2[2]; -char glob3[3]; -char glob4[4]; -char glob5[5]; -char glob6[6]; -char glob7[7]; -char glob8[8]; -char glob9[9]; -char glob10[10]; -char glob11[11]; -char glob12[12]; -char glob13[13]; -char glob14[14]; -char glob15[15]; -char glob16[16]; -char glob17[17]; -char glob1000[1000]; -char glob10000[10000]; -char glob100000[100000]; - -static char static10[10]; - -int GlobalsTest(int zero) { - static char func_static15[15]; - glob5[zero] = 0; - static10[zero] = 0; - func_static15[zero] = 0; - return glob5[1] + func_static15[2]; -} diff --git a/lib/asan/tests/asan_interface_test.cc b/lib/asan/tests/asan_interface_test.cc deleted file mode 100644 index b5c8303cb84b4..0000000000000 --- a/lib/asan/tests/asan_interface_test.cc +++ /dev/null @@ -1,422 +0,0 @@ -//===-- asan_interface_test.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" -#include "sanitizer_common/sanitizer_internal_defs.h" -#include <sanitizer/allocator_interface.h> -#include <sanitizer/asan_interface.h> -#include <vector> - -TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) { - EXPECT_EQ(0U, __sanitizer_get_estimated_allocated_size(0)); - const size_t sizes[] = { 1, 30, 1<<30 }; - for (size_t i = 0; i < 3; i++) { - EXPECT_EQ(sizes[i], __sanitizer_get_estimated_allocated_size(sizes[i])); - } -} - -static const char* kGetAllocatedSizeErrorMsg = - "attempting to call __sanitizer_get_allocated_size"; - -TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) { - const size_t kArraySize = 100; - char *array = Ident((char*)malloc(kArraySize)); - int *int_ptr = Ident(new int); - - // Allocated memory is owned by allocator. Allocated size should be - // equal to requested size. - EXPECT_EQ(true, __sanitizer_get_ownership(array)); - EXPECT_EQ(kArraySize, __sanitizer_get_allocated_size(array)); - EXPECT_EQ(true, __sanitizer_get_ownership(int_ptr)); - EXPECT_EQ(sizeof(int), __sanitizer_get_allocated_size(int_ptr)); - - // We cannot call GetAllocatedSize from the memory we didn't map, - // and from the interior pointers (not returned by previous malloc). - void *wild_addr = (void*)0x1; - EXPECT_FALSE(__sanitizer_get_ownership(wild_addr)); - EXPECT_DEATH(__sanitizer_get_allocated_size(wild_addr), - kGetAllocatedSizeErrorMsg); - EXPECT_FALSE(__sanitizer_get_ownership(array + kArraySize / 2)); - EXPECT_DEATH(__sanitizer_get_allocated_size(array + kArraySize / 2), - kGetAllocatedSizeErrorMsg); - - // NULL is not owned, but is a valid argument for - // __sanitizer_get_allocated_size(). - EXPECT_FALSE(__sanitizer_get_ownership(NULL)); - EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL)); - - // When memory is freed, it's not owned, and call to GetAllocatedSize - // is forbidden. - free(array); - EXPECT_FALSE(__sanitizer_get_ownership(array)); - EXPECT_DEATH(__sanitizer_get_allocated_size(array), - kGetAllocatedSizeErrorMsg); - delete int_ptr; - - void *zero_alloc = Ident(malloc(0)); - if (zero_alloc != 0) { - // If malloc(0) is not null, this pointer is owned and should have valid - // allocated size. - EXPECT_TRUE(__sanitizer_get_ownership(zero_alloc)); - // Allocated size is 0 or 1 depending on the allocator used. - EXPECT_LT(__sanitizer_get_allocated_size(zero_alloc), 2U); - } - free(zero_alloc); -} - -TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) { - size_t before_malloc, after_malloc, after_free; - char *array; - const size_t kMallocSize = 100; - before_malloc = __sanitizer_get_current_allocated_bytes(); - - array = Ident((char*)malloc(kMallocSize)); - after_malloc = __sanitizer_get_current_allocated_bytes(); - EXPECT_EQ(before_malloc + kMallocSize, after_malloc); - - free(array); - after_free = __sanitizer_get_current_allocated_bytes(); - EXPECT_EQ(before_malloc, after_free); -} - -TEST(AddressSanitizerInterface, GetHeapSizeTest) { - // ASan allocator does not keep huge chunks in free list, but unmaps them. - // The chunk should be greater than the quarantine size, - // otherwise it will be stuck in quarantine instead of being unmaped. - static const size_t kLargeMallocSize = (1 << 28) + 1; // 256M - free(Ident(malloc(kLargeMallocSize))); // Drain quarantine. - size_t old_heap_size = __sanitizer_get_heap_size(); - for (int i = 0; i < 3; i++) { - // fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize); - free(Ident(malloc(kLargeMallocSize))); - EXPECT_EQ(old_heap_size, __sanitizer_get_heap_size()); - } -} - -#if !defined(__NetBSD__) -static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357}; -static const size_t kManyThreadsIterations = 250; -static const size_t kManyThreadsNumThreads = - (SANITIZER_WORDSIZE == 32) ? 40 : 200; - -static void *ManyThreadsWithStatsWorker(void *arg) { - (void)arg; - for (size_t iter = 0; iter < kManyThreadsIterations; iter++) { - for (size_t size_index = 0; size_index < 4; size_index++) { - free(Ident(malloc(kManyThreadsMallocSizes[size_index]))); - } - } - // Just one large allocation. - free(Ident(malloc(1 << 20))); - return 0; -} - -TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) { - size_t before_test, after_test, i; - pthread_t threads[kManyThreadsNumThreads]; - before_test = __sanitizer_get_current_allocated_bytes(); - for (i = 0; i < kManyThreadsNumThreads; i++) { - PTHREAD_CREATE(&threads[i], 0, - (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i); - } - for (i = 0; i < kManyThreadsNumThreads; i++) { - PTHREAD_JOIN(threads[i], 0); - } - after_test = __sanitizer_get_current_allocated_bytes(); - // ASan stats also reflect memory usage of internal ASan RTL structs, - // so we can't check for equality here. - EXPECT_LT(after_test, before_test + (1UL<<20)); -} -#endif - -static void DoDoubleFree() { - int *x = Ident(new int); - delete Ident(x); - delete Ident(x); -} - -static void MyDeathCallback() { - fprintf(stderr, "MyDeathCallback\n"); - fflush(0); // On Windows, stderr doesn't flush on crash. -} - -TEST(AddressSanitizerInterface, DeathCallbackTest) { - __asan_set_death_callback(MyDeathCallback); - EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback"); - __asan_set_death_callback(NULL); -} - -#define GOOD_ACCESS(ptr, offset) \ - EXPECT_FALSE(__asan_address_is_poisoned(ptr + offset)) - -#define BAD_ACCESS(ptr, offset) \ - EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset)) - -#if !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3 -static const char* kUseAfterPoisonErrorMessage = "use-after-poison"; - -TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) { - char *array = Ident((char*)malloc(120)); - // poison array[40..80) - __asan_poison_memory_region(array + 40, 40); - GOOD_ACCESS(array, 39); - GOOD_ACCESS(array, 80); - BAD_ACCESS(array, 40); - BAD_ACCESS(array, 60); - BAD_ACCESS(array, 79); - char value; - EXPECT_DEATH(value = Ident(array[40]), kUseAfterPoisonErrorMessage); - __asan_unpoison_memory_region(array + 40, 40); - // access previously poisoned memory. - GOOD_ACCESS(array, 40); - GOOD_ACCESS(array, 79); - free(array); -} - -TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) { - char *array = Ident((char*)malloc(120)); - // Poison [0..40) and [80..120) - __asan_poison_memory_region(array, 40); - __asan_poison_memory_region(array + 80, 40); - BAD_ACCESS(array, 20); - GOOD_ACCESS(array, 60); - BAD_ACCESS(array, 100); - // Poison whole array - [0..120) - __asan_poison_memory_region(array, 120); - BAD_ACCESS(array, 60); - // Unpoison [24..96) - __asan_unpoison_memory_region(array + 24, 72); - BAD_ACCESS(array, 23); - GOOD_ACCESS(array, 24); - GOOD_ACCESS(array, 60); - GOOD_ACCESS(array, 95); - BAD_ACCESS(array, 96); - free(array); -} -#endif // !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3 - -TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) { - // Vector of capacity 20 - char *vec = Ident((char*)malloc(20)); - __asan_poison_memory_region(vec, 20); - for (size_t i = 0; i < 7; i++) { - // Simulate push_back. - __asan_unpoison_memory_region(vec + i, 1); - GOOD_ACCESS(vec, i); - BAD_ACCESS(vec, i + 1); - } - for (size_t i = 7; i > 0; i--) { - // Simulate pop_back. - __asan_poison_memory_region(vec + i - 1, 1); - BAD_ACCESS(vec, i - 1); - if (i > 1) GOOD_ACCESS(vec, i - 2); - } - free(vec); -} - -#if !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3 -// Make sure that each aligned block of size "2^granularity" doesn't have -// "true" value before "false" value. -static void MakeShadowValid(bool *shadow, int length, int granularity) { - bool can_be_poisoned = true; - for (int i = length - 1; i >= 0; i--) { - if (!shadow[i]) - can_be_poisoned = false; - if (!can_be_poisoned) - shadow[i] = false; - if (i % (1 << granularity) == 0) { - can_be_poisoned = true; - } - } -} - -TEST(AddressSanitizerInterface, PoisoningStressTest) { - const size_t kSize = 24; - bool expected[kSize]; - char *arr = Ident((char*)malloc(kSize)); - for (size_t l1 = 0; l1 < kSize; l1++) { - for (size_t s1 = 1; l1 + s1 <= kSize; s1++) { - for (size_t l2 = 0; l2 < kSize; l2++) { - for (size_t s2 = 1; l2 + s2 <= kSize; s2++) { - // Poison [l1, l1+s1), [l2, l2+s2) and check result. - __asan_unpoison_memory_region(arr, kSize); - __asan_poison_memory_region(arr + l1, s1); - __asan_poison_memory_region(arr + l2, s2); - memset(expected, false, kSize); - memset(expected + l1, true, s1); - MakeShadowValid(expected, kSize, /*granularity*/ 3); - memset(expected + l2, true, s2); - MakeShadowValid(expected, kSize, /*granularity*/ 3); - for (size_t i = 0; i < kSize; i++) { - ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i)); - } - // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result. - __asan_poison_memory_region(arr, kSize); - __asan_unpoison_memory_region(arr + l1, s1); - __asan_unpoison_memory_region(arr + l2, s2); - memset(expected, true, kSize); - memset(expected + l1, false, s1); - MakeShadowValid(expected, kSize, /*granularity*/ 3); - memset(expected + l2, false, s2); - MakeShadowValid(expected, kSize, /*granularity*/ 3); - for (size_t i = 0; i < kSize; i++) { - ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i)); - } - } - } - } - } - free(arr); -} -#endif // !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3 - -TEST(AddressSanitizerInterface, GlobalRedzones) { - GOOD_ACCESS(glob1, 1 - 1); - GOOD_ACCESS(glob2, 2 - 1); - GOOD_ACCESS(glob3, 3 - 1); - GOOD_ACCESS(glob4, 4 - 1); - GOOD_ACCESS(glob5, 5 - 1); - GOOD_ACCESS(glob6, 6 - 1); - GOOD_ACCESS(glob7, 7 - 1); - GOOD_ACCESS(glob8, 8 - 1); - GOOD_ACCESS(glob9, 9 - 1); - GOOD_ACCESS(glob10, 10 - 1); - GOOD_ACCESS(glob11, 11 - 1); - GOOD_ACCESS(glob12, 12 - 1); - GOOD_ACCESS(glob13, 13 - 1); - GOOD_ACCESS(glob14, 14 - 1); - GOOD_ACCESS(glob15, 15 - 1); - GOOD_ACCESS(glob16, 16 - 1); - GOOD_ACCESS(glob17, 17 - 1); - GOOD_ACCESS(glob1000, 1000 - 1); - GOOD_ACCESS(glob10000, 10000 - 1); - GOOD_ACCESS(glob100000, 100000 - 1); - - BAD_ACCESS(glob1, 1); - BAD_ACCESS(glob2, 2); - BAD_ACCESS(glob3, 3); - BAD_ACCESS(glob4, 4); - BAD_ACCESS(glob5, 5); - BAD_ACCESS(glob6, 6); - BAD_ACCESS(glob7, 7); - BAD_ACCESS(glob8, 8); - BAD_ACCESS(glob9, 9); - BAD_ACCESS(glob10, 10); - BAD_ACCESS(glob11, 11); - BAD_ACCESS(glob12, 12); - BAD_ACCESS(glob13, 13); - BAD_ACCESS(glob14, 14); - BAD_ACCESS(glob15, 15); - BAD_ACCESS(glob16, 16); - BAD_ACCESS(glob17, 17); - BAD_ACCESS(glob1000, 1000); - BAD_ACCESS(glob1000, 1100); // Redzone is at least 101 bytes. - BAD_ACCESS(glob10000, 10000); - BAD_ACCESS(glob10000, 11000); // Redzone is at least 1001 bytes. - BAD_ACCESS(glob100000, 100000); - BAD_ACCESS(glob100000, 110000); // Redzone is at least 10001 bytes. -} - -TEST(AddressSanitizerInterface, PoisonedRegion) { - size_t rz = 16; - for (size_t size = 1; size <= 64; size++) { - char *p = new char[size]; - for (size_t beg = 0; beg < size + rz; beg++) { - for (size_t end = beg; end < size + rz; end++) { - void *first_poisoned = __asan_region_is_poisoned(p + beg, end - beg); - if (beg == end) { - EXPECT_FALSE(first_poisoned); - } else if (beg < size && end <= size) { - EXPECT_FALSE(first_poisoned); - } else if (beg >= size) { - EXPECT_EQ(p + beg, first_poisoned); - } else { - EXPECT_GT(end, size); - EXPECT_EQ(p + size, first_poisoned); - } - } - } - delete [] p; - } -} - -// This is a performance benchmark for manual runs. -// asan's memset interceptor calls mem_is_zero for the entire shadow region. -// the profile should look like this: -// 89.10% [.] __memset_sse2 -// 10.50% [.] __sanitizer::mem_is_zero -// I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles -// than memset itself. -TEST(AddressSanitizerInterface, DISABLED_StressLargeMemset) { - size_t size = 1 << 20; - char *x = new char[size]; - for (int i = 0; i < 100000; i++) - Ident(memset)(x, 0, size); - delete [] x; -} - -// Same here, but we run memset with small sizes. -TEST(AddressSanitizerInterface, DISABLED_StressSmallMemset) { - size_t size = 32; - char *x = new char[size]; - for (int i = 0; i < 100000000; i++) - Ident(memset)(x, 0, size); - delete [] x; -} -static const char *kInvalidPoisonMessage = "invalid-poison-memory-range"; -static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range"; - -TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) { - char *array = Ident((char*)malloc(120)); - __asan_unpoison_memory_region(array, 120); - // Try to unpoison not owned memory - EXPECT_DEATH(__asan_unpoison_memory_region(array, 121), - kInvalidUnpoisonMessage); - EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120), - kInvalidUnpoisonMessage); - - __asan_poison_memory_region(array, 120); - // Try to poison not owned memory. - EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage); - EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120), - kInvalidPoisonMessage); - free(array); -} - -TEST(AddressSanitizerInterface, GetOwnershipStressTest) { - std::vector<char *> pointers; - std::vector<size_t> sizes; - const size_t kNumMallocs = 1 << 9; - for (size_t i = 0; i < kNumMallocs; i++) { - size_t size = i * 100 + 1; - pointers.push_back((char*)malloc(size)); - sizes.push_back(size); - } - for (size_t i = 0; i < 4000000; i++) { - EXPECT_FALSE(__sanitizer_get_ownership(&pointers)); - EXPECT_FALSE(__sanitizer_get_ownership((void*)0x1234)); - size_t idx = i % kNumMallocs; - EXPECT_TRUE(__sanitizer_get_ownership(pointers[idx])); - EXPECT_EQ(sizes[idx], __sanitizer_get_allocated_size(pointers[idx])); - } - for (size_t i = 0, n = pointers.size(); i < n; i++) - free(pointers[i]); -} - -TEST(AddressSanitizerInterface, HandleNoReturnTest) { - char array[40]; - __asan_poison_memory_region(array, sizeof(array)); - BAD_ACCESS(array, 20); - __asan_handle_no_return(); - // It unpoisons the whole thread stack. - GOOD_ACCESS(array, 20); -} diff --git a/lib/asan/tests/asan_internal_interface_test.cc b/lib/asan/tests/asan_internal_interface_test.cc deleted file mode 100644 index e247bb4299faf..0000000000000 --- a/lib/asan/tests/asan_internal_interface_test.cc +++ /dev/null @@ -1,37 +0,0 @@ -//===-- asan_internal_interface_test.cc -----------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_interface_internal.h" -#include "asan_test_utils.h" -#include <vector> - -TEST(AddressSanitizerInternalInterface, SetShadow) { - std::vector<char> buffer(17, 0xff); - - __asan_set_shadow_00((uptr)buffer.data(), buffer.size()); - EXPECT_EQ(std::vector<char>(buffer.size(), 0x00), buffer); - - __asan_set_shadow_f1((uptr)buffer.data(), buffer.size()); - EXPECT_EQ(std::vector<char>(buffer.size(), 0xf1), buffer); - - __asan_set_shadow_f2((uptr)buffer.data(), buffer.size()); - EXPECT_EQ(std::vector<char>(buffer.size(), 0xf2), buffer); - - __asan_set_shadow_f3((uptr)buffer.data(), buffer.size()); - EXPECT_EQ(std::vector<char>(buffer.size(), 0xf3), buffer); - - __asan_set_shadow_f5((uptr)buffer.data(), buffer.size()); - EXPECT_EQ(std::vector<char>(buffer.size(), 0xf5), buffer); - - __asan_set_shadow_f8((uptr)buffer.data(), buffer.size()); - EXPECT_EQ(std::vector<char>(buffer.size(), 0xf8), buffer); -} diff --git a/lib/asan/tests/asan_mac_test.cc b/lib/asan/tests/asan_mac_test.cc deleted file mode 100644 index dfa6d7596d742..0000000000000 --- a/lib/asan/tests/asan_mac_test.cc +++ /dev/null @@ -1,236 +0,0 @@ -//===-- asan_test_mac.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// - -#include "asan_test_utils.h" - -#include "asan_mac_test.h" - -#include <malloc/malloc.h> -#include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_* -#include <CoreFoundation/CFString.h> - -TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree) { - EXPECT_DEATH( - CFAllocatorDefaultDoubleFree(NULL), - "attempting double-free"); -} - -void CFAllocator_DoubleFreeOnPthread() { - pthread_t child; - PTHREAD_CREATE(&child, NULL, CFAllocatorDefaultDoubleFree, NULL); - PTHREAD_JOIN(child, NULL); // Shouldn't be reached. -} - -TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree_ChildPhread) { - EXPECT_DEATH(CFAllocator_DoubleFreeOnPthread(), "attempting double-free"); -} - -namespace { - -void *GLOB; - -void *CFAllocatorAllocateToGlob(void *unused) { - GLOB = CFAllocatorAllocate(NULL, 100, /*hint*/0); - return NULL; -} - -void *CFAllocatorDeallocateFromGlob(void *unused) { - char *p = (char*)GLOB; - p[100] = 'A'; // ASan should report an error here. - CFAllocatorDeallocate(NULL, GLOB); - return NULL; -} - -void CFAllocator_PassMemoryToAnotherThread() { - pthread_t th1, th2; - PTHREAD_CREATE(&th1, NULL, CFAllocatorAllocateToGlob, NULL); - PTHREAD_JOIN(th1, NULL); - PTHREAD_CREATE(&th2, NULL, CFAllocatorDeallocateFromGlob, NULL); - PTHREAD_JOIN(th2, NULL); -} - -TEST(AddressSanitizerMac, CFAllocator_PassMemoryToAnotherThread) { - EXPECT_DEATH(CFAllocator_PassMemoryToAnotherThread(), - "heap-buffer-overflow"); -} - -} // namespace - -// TODO(glider): figure out whether we still need these tests. Is it correct -// to intercept the non-default CFAllocators? -TEST(AddressSanitizerMac, DISABLED_CFAllocatorSystemDefaultDoubleFree) { - EXPECT_DEATH( - CFAllocatorSystemDefaultDoubleFree(), - "attempting double-free"); -} - -// We're intercepting malloc, so kCFAllocatorMalloc is routed to ASan. -TEST(AddressSanitizerMac, CFAllocatorMallocDoubleFree) { - EXPECT_DEATH(CFAllocatorMallocDoubleFree(), "attempting double-free"); -} - -TEST(AddressSanitizerMac, DISABLED_CFAllocatorMallocZoneDoubleFree) { - EXPECT_DEATH(CFAllocatorMallocZoneDoubleFree(), "attempting double-free"); -} - -// For libdispatch tests below we check that ASan got to the shadow byte -// legend, i.e. managed to print the thread stacks (this almost certainly -// means that the libdispatch task creation has been intercepted correctly). -TEST(AddressSanitizerMac, GCDDispatchAsync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDDispatchAsync(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDDispatchSync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDDispatchSync(), "Shadow byte legend"); -} - - -TEST(AddressSanitizerMac, GCDReuseWqthreadsAsync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDReuseWqthreadsAsync(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDReuseWqthreadsSync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDReuseWqthreadsSync(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDDispatchAfter) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDDispatchAfter(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDSourceEvent) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDSourceEvent(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDSourceCancel) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDSourceCancel(), "Shadow byte legend"); -} - -TEST(AddressSanitizerMac, GCDGroupAsync) { - // Make sure the whole ASan report is printed, i.e. that we don't die - // on a CHECK. - EXPECT_DEATH(TestGCDGroupAsync(), "Shadow byte legend"); -} - -void *MallocIntrospectionLockWorker(void *_) { - const int kNumPointers = 100; - int i; - void *pointers[kNumPointers]; - for (i = 0; i < kNumPointers; i++) { - pointers[i] = malloc(i + 1); - } - for (i = 0; i < kNumPointers; i++) { - free(pointers[i]); - } - - return NULL; -} - -void *MallocIntrospectionLockForker(void *_) { - pid_t result = fork(); - if (result == -1) { - perror("fork"); - } - assert(result != -1); - if (result == 0) { - // Call malloc in the child process to make sure we won't deadlock. - void *ptr = malloc(42); - free(ptr); - exit(0); - } else { - // Return in the parent process. - return NULL; - } -} - -TEST(AddressSanitizerMac, MallocIntrospectionLock) { - // Incorrect implementation of force_lock and force_unlock in our malloc zone - // will cause forked processes to deadlock. - // TODO(glider): need to detect that none of the child processes deadlocked. - const int kNumWorkers = 5, kNumIterations = 100; - int i, iter; - for (iter = 0; iter < kNumIterations; iter++) { - pthread_t workers[kNumWorkers], forker; - for (i = 0; i < kNumWorkers; i++) { - PTHREAD_CREATE(&workers[i], 0, MallocIntrospectionLockWorker, 0); - } - PTHREAD_CREATE(&forker, 0, MallocIntrospectionLockForker, 0); - for (i = 0; i < kNumWorkers; i++) { - PTHREAD_JOIN(workers[i], 0); - } - PTHREAD_JOIN(forker, 0); - } -} - -void *TSDAllocWorker(void *test_key) { - if (test_key) { - void *mem = malloc(10); - pthread_setspecific(*(pthread_key_t*)test_key, mem); - } - return NULL; -} - -TEST(AddressSanitizerMac, DISABLED_TSDWorkqueueTest) { - pthread_t th; - pthread_key_t test_key; - pthread_key_create(&test_key, CallFreeOnWorkqueue); - PTHREAD_CREATE(&th, NULL, TSDAllocWorker, &test_key); - PTHREAD_JOIN(th, NULL); - pthread_key_delete(test_key); -} - -// Test that CFStringCreateCopy does not copy constant strings. -TEST(AddressSanitizerMac, CFStringCreateCopy) { - CFStringRef str = CFSTR("Hello world!\n"); - CFStringRef str2 = CFStringCreateCopy(0, str); - EXPECT_EQ(str, str2); -} - -TEST(AddressSanitizerMac, NSObjectOOB) { - // Make sure that our allocators are used for NSObjects. - EXPECT_DEATH(TestOOBNSObjects(), "heap-buffer-overflow"); -} - -// Make sure that correct pointer is passed to free() when deallocating a -// NSURL object. -// See https://github.com/google/sanitizers/issues/70. -TEST(AddressSanitizerMac, NSURLDeallocation) { - TestNSURLDeallocation(); -} - -// See https://github.com/google/sanitizers/issues/109. -TEST(AddressSanitizerMac, Mstats) { - malloc_statistics_t stats1, stats2; - malloc_zone_statistics(/*all zones*/NULL, &stats1); - const size_t kMallocSize = 100000; - void *alloc = Ident(malloc(kMallocSize)); - malloc_zone_statistics(/*all zones*/NULL, &stats2); - EXPECT_GT(stats2.blocks_in_use, stats1.blocks_in_use); - EXPECT_GE(stats2.size_in_use - stats1.size_in_use, kMallocSize); - free(alloc); - // Even the default OSX allocator may not change the stats after free(). -} - diff --git a/lib/asan/tests/asan_mac_test.h b/lib/asan/tests/asan_mac_test.h deleted file mode 100644 index 441547a5a3dcb..0000000000000 --- a/lib/asan/tests/asan_mac_test.h +++ /dev/null @@ -1,19 +0,0 @@ -extern "C" { - void *CFAllocatorDefaultDoubleFree(void *unused); - void CFAllocatorSystemDefaultDoubleFree(); - void CFAllocatorMallocDoubleFree(); - void CFAllocatorMallocZoneDoubleFree(); - void CallFreeOnWorkqueue(void *mem); - void TestGCDDispatchAsync(); - void TestGCDDispatchSync(); - void TestGCDReuseWqthreadsAsync(); - void TestGCDReuseWqthreadsSync(); - void TestGCDDispatchAfter(); - void TestGCDInTSDDestructor(); - void TestGCDSourceEvent(); - void TestGCDSourceCancel(); - void TestGCDGroupAsync(); - void TestOOBNSObjects(); - void TestNSURLDeallocation(); - void TestPassCFMemoryToAnotherThread(); -} diff --git a/lib/asan/tests/asan_mac_test_helpers.mm b/lib/asan/tests/asan_mac_test_helpers.mm deleted file mode 100644 index 3f8fa26d95b8d..0000000000000 --- a/lib/asan/tests/asan_mac_test_helpers.mm +++ /dev/null @@ -1,241 +0,0 @@ -// Mac OS X 10.6 or higher only. -#include <dispatch/dispatch.h> -#include <pthread.h> // for pthread_yield_np() -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#import <CoreFoundation/CFBase.h> -#import <Foundation/NSObject.h> -#import <Foundation/NSURL.h> - -// This is a (void*)(void*) function so it can be passed to pthread_create. -void *CFAllocatorDefaultDoubleFree(void *unused) { - void *mem = CFAllocatorAllocate(kCFAllocatorDefault, 5, 0); - CFAllocatorDeallocate(kCFAllocatorDefault, mem); - CFAllocatorDeallocate(kCFAllocatorDefault, mem); - return 0; -} - -void CFAllocatorSystemDefaultDoubleFree() { - void *mem = CFAllocatorAllocate(kCFAllocatorSystemDefault, 5, 0); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, mem); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, mem); -} - -void CFAllocatorMallocDoubleFree() { - void *mem = CFAllocatorAllocate(kCFAllocatorMalloc, 5, 0); - CFAllocatorDeallocate(kCFAllocatorMalloc, mem); - CFAllocatorDeallocate(kCFAllocatorMalloc, mem); -} - -void CFAllocatorMallocZoneDoubleFree() { - void *mem = CFAllocatorAllocate(kCFAllocatorMallocZone, 5, 0); - CFAllocatorDeallocate(kCFAllocatorMallocZone, mem); - CFAllocatorDeallocate(kCFAllocatorMallocZone, mem); -} - -__attribute__((noinline)) -void access_memory(char *a) { - *a = 0; -} - -// Test the +load instrumentation. -// Because the +load methods are invoked before anything else is initialized, -// it makes little sense to wrap the code below into a gTest test case. -// If AddressSanitizer doesn't instrument the +load method below correctly, -// everything will just crash. - -char kStartupStr[] = - "If your test didn't crash, AddressSanitizer is instrumenting " - "the +load methods correctly."; - -@interface LoadSomething : NSObject { -} -@end - -@implementation LoadSomething - -+(void) load { - for (size_t i = 0; i < strlen(kStartupStr); i++) { - access_memory(&kStartupStr[i]); // make sure no optimizations occur. - } - // Don't print anything here not to interfere with the death tests. -} - -@end - -void worker_do_alloc(int size) { - char * volatile mem = (char * volatile)malloc(size); - mem[0] = 0; // Ok - free(mem); -} - -void worker_do_crash(int size) { - char * volatile mem = (char * volatile)malloc(size); - access_memory(&mem[size]); // BOOM - free(mem); -} - -// Used by the GCD tests to avoid a race between the worker thread reporting a -// memory error and the main thread which may exit with exit code 0 before -// that. -void wait_forever() { - volatile bool infinite = true; - while (infinite) pthread_yield_np(); -} - -// Tests for the Grand Central Dispatch. See -// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html -// for the reference. -void TestGCDDispatchAsync() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_block_t block = ^{ worker_do_crash(1024); }; - // dispatch_async() runs the task on a worker thread that does not go through - // pthread_create(). We need to verify that AddressSanitizer notices that the - // thread has started. - dispatch_async(queue, block); - wait_forever(); -} - -void TestGCDDispatchSync() { - dispatch_queue_t queue = dispatch_get_global_queue(2, 0); - dispatch_block_t block = ^{ worker_do_crash(1024); }; - // dispatch_sync() runs the task on a worker thread that does not go through - // pthread_create(). We need to verify that AddressSanitizer notices that the - // thread has started. - dispatch_sync(queue, block); - wait_forever(); -} - -// libdispatch spawns a rather small number of threads and reuses them. We need -// to make sure AddressSanitizer handles the reusing correctly. -void TestGCDReuseWqthreadsAsync() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_block_t block_alloc = ^{ worker_do_alloc(1024); }; - dispatch_block_t block_crash = ^{ worker_do_crash(1024); }; - for (int i = 0; i < 100; i++) { - dispatch_async(queue, block_alloc); - } - dispatch_async(queue, block_crash); - wait_forever(); -} - -// Try to trigger abnormal behaviour of dispatch_sync() being unhandled by us. -void TestGCDReuseWqthreadsSync() { - dispatch_queue_t queue[4]; - queue[0] = dispatch_get_global_queue(2, 0); - queue[1] = dispatch_get_global_queue(0, 0); - queue[2] = dispatch_get_global_queue(-2, 0); - queue[3] = dispatch_queue_create("my_queue", NULL); - dispatch_block_t block_alloc = ^{ worker_do_alloc(1024); }; - dispatch_block_t block_crash = ^{ worker_do_crash(1024); }; - for (int i = 0; i < 1000; i++) { - dispatch_sync(queue[i % 4], block_alloc); - } - dispatch_sync(queue[3], block_crash); - wait_forever(); -} - -void TestGCDDispatchAfter() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_block_t block_crash = ^{ worker_do_crash(1024); }; - // Schedule the event one second from the current time. - dispatch_time_t milestone = - dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC); - dispatch_after(milestone, queue, block_crash); - wait_forever(); -} - -void worker_do_deallocate(void *ptr) { - free(ptr); -} - -void CallFreeOnWorkqueue(void *tsd) { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_block_t block_dealloc = ^{ worker_do_deallocate(tsd); }; - dispatch_async(queue, block_dealloc); - // Do not wait for the worker to free the memory -- nobody is going to touch - // it. -} - -void TestGCDSourceEvent() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_source_t timer = - dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); - // Schedule the timer one second from the current time. - dispatch_time_t milestone = - dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC); - - dispatch_source_set_timer(timer, milestone, DISPATCH_TIME_FOREVER, 0); - char * volatile mem = (char * volatile)malloc(10); - dispatch_source_set_event_handler(timer, ^{ - access_memory(&mem[10]); - }); - dispatch_resume(timer); - wait_forever(); -} - -void TestGCDSourceCancel() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_source_t timer = - dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); - // Schedule the timer one second from the current time. - dispatch_time_t milestone = - dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC); - - dispatch_source_set_timer(timer, milestone, DISPATCH_TIME_FOREVER, 0); - char * volatile mem = (char * volatile)malloc(10); - // Both dispatch_source_set_cancel_handler() and - // dispatch_source_set_event_handler() use dispatch_barrier_async_f(). - // It's tricky to test dispatch_source_set_cancel_handler() separately, - // so we test both here. - dispatch_source_set_event_handler(timer, ^{ - dispatch_source_cancel(timer); - }); - dispatch_source_set_cancel_handler(timer, ^{ - access_memory(&mem[10]); - }); - dispatch_resume(timer); - wait_forever(); -} - -void TestGCDGroupAsync() { - dispatch_queue_t queue = dispatch_get_global_queue(0, 0); - dispatch_group_t group = dispatch_group_create(); - char * volatile mem = (char * volatile)malloc(10); - dispatch_group_async(group, queue, ^{ - access_memory(&mem[10]); - }); - dispatch_group_wait(group, DISPATCH_TIME_FOREVER); - wait_forever(); -} - -@interface FixedArray : NSObject { - int items[10]; -} -@end - -@implementation FixedArray --(int) access: (int)index { - return items[index]; -} -@end - -void TestOOBNSObjects() { - id anObject = [FixedArray new]; - [anObject access:1]; - [anObject access:11]; - [anObject release]; -} - -void TestNSURLDeallocation() { - NSURL *base = - [[NSURL alloc] initWithString:@"file://localhost/Users/glider/Library/"]; - volatile NSURL *u = - [[NSURL alloc] initWithString:@"Saved Application State" - relativeToURL:base]; - [u release]; - [base release]; -} diff --git a/lib/asan/tests/asan_mem_test.cc b/lib/asan/tests/asan_mem_test.cc deleted file mode 100644 index c3208868464e1..0000000000000 --- a/lib/asan/tests/asan_mem_test.cc +++ /dev/null @@ -1,242 +0,0 @@ -//===-- asan_mem_test.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" -#include <vector> - -template<typename T> -void MemSetOOBTestTemplate(size_t length) { - if (length == 0) return; - size_t size = Ident(sizeof(T) * length); - T *array = Ident((T*)malloc(size)); - int element = Ident(42); - int zero = Ident(0); - void *(*MEMSET)(void *s, int c, size_t n) = Ident(memset); - // memset interval inside array - MEMSET(array, element, size); - MEMSET(array, element, size - 1); - MEMSET(array + length - 1, element, sizeof(T)); - MEMSET(array, element, 1); - - // memset 0 bytes - MEMSET(array - 10, element, zero); - MEMSET(array - 1, element, zero); - MEMSET(array, element, zero); - MEMSET(array + length, 0, zero); - MEMSET(array + length + 1, 0, zero); - - // try to memset bytes to the right of array - EXPECT_DEATH(MEMSET(array, 0, size + 1), - RightOOBWriteMessage(0)); - EXPECT_DEATH(MEMSET((char*)(array + length) - 1, element, 6), - RightOOBWriteMessage(0)); - EXPECT_DEATH(MEMSET(array + 1, element, size + sizeof(T)), - RightOOBWriteMessage(0)); - // whole interval is to the right - EXPECT_DEATH(MEMSET(array + length + 1, 0, 10), - RightOOBWriteMessage(sizeof(T))); - - // try to memset bytes to the left of array - EXPECT_DEATH(MEMSET((char*)array - 1, element, size), - LeftOOBWriteMessage(1)); - EXPECT_DEATH(MEMSET((char*)array - 5, 0, 6), - LeftOOBWriteMessage(5)); - if (length >= 100) { - // Large OOB, we find it only if the redzone is large enough. - EXPECT_DEATH(memset(array - 5, element, size + 5 * sizeof(T)), - LeftOOBWriteMessage(5 * sizeof(T))); - } - // whole interval is to the left - EXPECT_DEATH(MEMSET(array - 2, 0, sizeof(T)), - LeftOOBWriteMessage(2 * sizeof(T))); - - // try to memset bytes both to the left & to the right - EXPECT_DEATH(MEMSET((char*)array - 2, element, size + 4), - LeftOOBWriteMessage(2)); - - free(array); -} - -TEST(AddressSanitizer, MemSetOOBTest) { - MemSetOOBTestTemplate<char>(100); - MemSetOOBTestTemplate<int>(5); - MemSetOOBTestTemplate<double>(256); - // We can test arrays of structres/classes here, but what for? -} - -// Try to allocate two arrays of 'size' bytes that are near each other. -// Strictly speaking we are not guaranteed to find such two pointers, -// but given the structure of asan's allocator we will. -static bool AllocateTwoAdjacentArrays(char **x1, char **x2, size_t size) { - std::vector<uintptr_t> v; - bool res = false; - for (size_t i = 0; i < 1000U && !res; i++) { - v.push_back(reinterpret_cast<uintptr_t>(new char[size])); - if (i == 0) continue; - sort(v.begin(), v.end()); - for (size_t j = 1; j < v.size(); j++) { - assert(v[j] > v[j-1]); - if ((size_t)(v[j] - v[j-1]) < size * 2) { - *x2 = reinterpret_cast<char*>(v[j]); - *x1 = reinterpret_cast<char*>(v[j-1]); - res = true; - break; - } - } - } - - for (size_t i = 0; i < v.size(); i++) { - char *p = reinterpret_cast<char *>(v[i]); - if (res && p == *x1) continue; - if (res && p == *x2) continue; - delete [] p; - } - return res; -} - -TEST(AddressSanitizer, LargeOOBInMemset) { - for (size_t size = 200; size < 100000; size += size / 2) { - char *x1, *x2; - if (!Ident(AllocateTwoAdjacentArrays)(&x1, &x2, size)) - continue; - // fprintf(stderr, " large oob memset: %p %p %zd\n", x1, x2, size); - // Do a memset on x1 with huge out-of-bound access that will end up in x2. - EXPECT_DEATH(Ident(memset)(x1, 0, size * 2), - "is located 0 bytes to the right"); - delete [] x1; - delete [] x2; - return; - } - assert(0 && "Did not find two adjacent malloc-ed pointers"); -} - -// Same test for memcpy and memmove functions -template <typename T, class M> -void MemTransferOOBTestTemplate(size_t length) { - if (length == 0) return; - size_t size = Ident(sizeof(T) * length); - T *src = Ident((T*)malloc(size)); - T *dest = Ident((T*)malloc(size)); - int zero = Ident(0); - - // valid transfer of bytes between arrays - M::transfer(dest, src, size); - M::transfer(dest + 1, src, size - sizeof(T)); - M::transfer(dest, src + length - 1, sizeof(T)); - M::transfer(dest, src, 1); - - // transfer zero bytes - M::transfer(dest - 1, src, 0); - M::transfer(dest + length, src, zero); - M::transfer(dest, src - 1, zero); - M::transfer(dest, src, zero); - - // try to change mem to the right of dest - EXPECT_DEATH(M::transfer(dest + 1, src, size), - RightOOBWriteMessage(0)); - EXPECT_DEATH(M::transfer((char*)(dest + length) - 1, src, 5), - RightOOBWriteMessage(0)); - - // try to change mem to the left of dest - EXPECT_DEATH(M::transfer(dest - 2, src, size), - LeftOOBWriteMessage(2 * sizeof(T))); - EXPECT_DEATH(M::transfer((char*)dest - 3, src, 4), - LeftOOBWriteMessage(3)); - - // try to access mem to the right of src - EXPECT_DEATH(M::transfer(dest, src + 2, size), - RightOOBReadMessage(0)); - EXPECT_DEATH(M::transfer(dest, (char*)(src + length) - 3, 6), - RightOOBReadMessage(0)); - - // try to access mem to the left of src - EXPECT_DEATH(M::transfer(dest, src - 1, size), - LeftOOBReadMessage(sizeof(T))); - EXPECT_DEATH(M::transfer(dest, (char*)src - 6, 7), - LeftOOBReadMessage(6)); - - // Generally we don't need to test cases where both accessing src and writing - // to dest address to poisoned memory. - - T *big_src = Ident((T*)malloc(size * 2)); - T *big_dest = Ident((T*)malloc(size * 2)); - // try to change mem to both sides of dest - EXPECT_DEATH(M::transfer(dest - 1, big_src, size * 2), - LeftOOBWriteMessage(sizeof(T))); - // try to access mem to both sides of src - EXPECT_DEATH(M::transfer(big_dest, src - 2, size * 2), - LeftOOBReadMessage(2 * sizeof(T))); - - free(src); - free(dest); - free(big_src); - free(big_dest); -} - -class MemCpyWrapper { - public: - static void* transfer(void *to, const void *from, size_t size) { - return Ident(memcpy)(to, from, size); - } -}; - -TEST(AddressSanitizer, MemCpyOOBTest) { - MemTransferOOBTestTemplate<char, MemCpyWrapper>(100); - MemTransferOOBTestTemplate<int, MemCpyWrapper>(1024); -} - -class MemMoveWrapper { - public: - static void* transfer(void *to, const void *from, size_t size) { - return Ident(memmove)(to, from, size); - } -}; - -TEST(AddressSanitizer, MemMoveOOBTest) { - MemTransferOOBTestTemplate<char, MemMoveWrapper>(100); - MemTransferOOBTestTemplate<int, MemMoveWrapper>(1024); -} - - -TEST(AddressSanitizer, MemCmpOOBTest) { - size_t size = Ident(100); - char *s1 = MallocAndMemsetString(size); - char *s2 = MallocAndMemsetString(size); - // Normal memcmp calls. - Ident(memcmp(s1, s2, size)); - Ident(memcmp(s1 + size - 1, s2 + size - 1, 1)); - Ident(memcmp(s1 - 1, s2 - 1, 0)); - // One of arguments points to not allocated memory. - EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBReadMessage(0)); - // Hit unallocated memory and die. - EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0)); - // Zero bytes are not terminators and don't prevent from OOB. - s1[size - 1] = '\0'; - s2[size - 1] = '\0'; - EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0)); - - // Even if the buffers differ in the first byte, we still assume that - // memcmp may access the whole buffer and thus reporting the overflow here: - s1[0] = 1; - s2[0] = 123; - EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0)); - - free(s1); - free(s2); -} - - - diff --git a/lib/asan/tests/asan_noinst_test.cc b/lib/asan/tests/asan_noinst_test.cc deleted file mode 100644 index 3e366842c65ff..0000000000000 --- a/lib/asan/tests/asan_noinst_test.cc +++ /dev/null @@ -1,273 +0,0 @@ -//===-- asan_noinst_test.cc -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// This test file should be compiled w/o asan instrumentation. -//===----------------------------------------------------------------------===// - -#include "asan_allocator.h" -#include "asan_internal.h" -#include "asan_mapping.h" -#include "asan_test_utils.h" -#include <sanitizer/allocator_interface.h> - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> // for memset() -#include <algorithm> -#include <vector> -#include <limits> - -using namespace __sanitizer; - -// ATTENTION! -// Please don't call intercepted functions (including malloc() and friends) -// in this test. The static runtime library is linked explicitly (without -// -fsanitize=address), thus the interceptors do not work correctly on OS X. - -// Make sure __asan_init is called before any test case is run. -struct AsanInitCaller { - AsanInitCaller() { - __asan_init(); - } -}; -static AsanInitCaller asan_init_caller; - -TEST(AddressSanitizer, InternalSimpleDeathTest) { - EXPECT_DEATH(exit(1), ""); -} - -static void MallocStress(size_t n) { - u32 seed = my_rand(); - BufferedStackTrace stack1; - stack1.trace_buffer[0] = 0xa123; - stack1.trace_buffer[1] = 0xa456; - stack1.size = 2; - - BufferedStackTrace stack2; - stack2.trace_buffer[0] = 0xb123; - stack2.trace_buffer[1] = 0xb456; - stack2.size = 2; - - BufferedStackTrace stack3; - stack3.trace_buffer[0] = 0xc123; - stack3.trace_buffer[1] = 0xc456; - stack3.size = 2; - - std::vector<void *> vec; - for (size_t i = 0; i < n; i++) { - if ((i % 3) == 0) { - if (vec.empty()) continue; - size_t idx = my_rand_r(&seed) % vec.size(); - void *ptr = vec[idx]; - vec[idx] = vec.back(); - vec.pop_back(); - __asan::asan_free(ptr, &stack1, __asan::FROM_MALLOC); - } else { - size_t size = my_rand_r(&seed) % 1000 + 1; - switch ((my_rand_r(&seed) % 128)) { - case 0: size += 1024; break; - case 1: size += 2048; break; - case 2: size += 4096; break; - } - size_t alignment = 1 << (my_rand_r(&seed) % 10 + 1); - char *ptr = (char*)__asan::asan_memalign(alignment, size, - &stack2, __asan::FROM_MALLOC); - EXPECT_EQ(size, __asan::asan_malloc_usable_size(ptr, 0, 0)); - vec.push_back(ptr); - ptr[0] = 0; - ptr[size-1] = 0; - ptr[size/2] = 0; - } - } - for (size_t i = 0; i < vec.size(); i++) - __asan::asan_free(vec[i], &stack3, __asan::FROM_MALLOC); -} - - -TEST(AddressSanitizer, NoInstMallocTest) { - MallocStress(ASAN_LOW_MEMORY ? 300000 : 1000000); -} - -TEST(AddressSanitizer, ThreadedMallocStressTest) { - const int kNumThreads = 4; - const int kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000; - pthread_t t[kNumThreads]; - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, (void* (*)(void *x))MallocStress, - (void*)kNumIterations); - } - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} - -static void PrintShadow(const char *tag, uptr ptr, size_t size) { - fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size); - uptr prev_shadow = 0; - for (sptr i = -32; i < (sptr)size + 32; i++) { - uptr shadow = __asan::MemToShadow(ptr + i); - if (i == 0 || i == (sptr)size) - fprintf(stderr, "."); - if (shadow != prev_shadow) { - prev_shadow = shadow; - fprintf(stderr, "%02x", (int)*(u8*)shadow); - } - } - fprintf(stderr, "\n"); -} - -TEST(AddressSanitizer, DISABLED_InternalPrintShadow) { - for (size_t size = 1; size <= 513; size++) { - char *ptr = new char[size]; - PrintShadow("m", (uptr)ptr, size); - delete [] ptr; - PrintShadow("f", (uptr)ptr, size); - } -} - -TEST(AddressSanitizer, QuarantineTest) { - BufferedStackTrace stack; - stack.trace_buffer[0] = 0x890; - stack.size = 1; - - const int size = 1024; - void *p = __asan::asan_malloc(size, &stack); - __asan::asan_free(p, &stack, __asan::FROM_MALLOC); - size_t i; - size_t max_i = 1 << 30; - for (i = 0; i < max_i; i++) { - void *p1 = __asan::asan_malloc(size, &stack); - __asan::asan_free(p1, &stack, __asan::FROM_MALLOC); - if (p1 == p) break; - } - EXPECT_GE(i, 10000U); - EXPECT_LT(i, max_i); -} - -#if !defined(__NetBSD__) -void *ThreadedQuarantineTestWorker(void *unused) { - (void)unused; - u32 seed = my_rand(); - BufferedStackTrace stack; - stack.trace_buffer[0] = 0x890; - stack.size = 1; - - for (size_t i = 0; i < 1000; i++) { - void *p = __asan::asan_malloc(1 + (my_rand_r(&seed) % 4000), &stack); - __asan::asan_free(p, &stack, __asan::FROM_MALLOC); - } - return NULL; -} - -// Check that the thread local allocators are flushed when threads are -// destroyed. -TEST(AddressSanitizer, ThreadedQuarantineTest) { - // Run the routine once to warm up ASAN internal structures to get more - // predictable incremental memory changes. - pthread_t t; - PTHREAD_CREATE(&t, NULL, ThreadedQuarantineTestWorker, 0); - PTHREAD_JOIN(t, 0); - - const int n_threads = 3000; - size_t mmaped1 = __sanitizer_get_heap_size(); - for (int i = 0; i < n_threads; i++) { - pthread_t t; - PTHREAD_CREATE(&t, NULL, ThreadedQuarantineTestWorker, 0); - PTHREAD_JOIN(t, 0); - size_t mmaped2 = __sanitizer_get_heap_size(); - // Figure out why this much memory is required. - EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20)); - } -} -#endif - -void *ThreadedOneSizeMallocStress(void *unused) { - (void)unused; - BufferedStackTrace stack; - stack.trace_buffer[0] = 0x890; - stack.size = 1; - const size_t kNumMallocs = 1000; - for (int iter = 0; iter < 1000; iter++) { - void *p[kNumMallocs]; - for (size_t i = 0; i < kNumMallocs; i++) { - p[i] = __asan::asan_malloc(32, &stack); - } - for (size_t i = 0; i < kNumMallocs; i++) { - __asan::asan_free(p[i], &stack, __asan::FROM_MALLOC); - } - } - return NULL; -} - -TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) { - const int kNumThreads = 4; - pthread_t t[kNumThreads]; - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, ThreadedOneSizeMallocStress, 0); - } - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} - -TEST(AddressSanitizer, ShadowRegionIsPoisonedTest) { - using __asan::kHighMemEnd; - // Check that __asan_region_is_poisoned works for shadow regions. - uptr ptr = kLowShadowBeg + 200; - EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); - ptr = kShadowGapBeg + 200; - EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); - ptr = kHighShadowBeg + 200; - EXPECT_EQ(ptr, __asan_region_is_poisoned(ptr, 100)); -} - -// Test __asan_load1 & friends. -TEST(AddressSanitizer, LoadStoreCallbacks) { - typedef void (*CB)(uptr p); - CB cb[2][5] = { - { - __asan_load1, __asan_load2, __asan_load4, __asan_load8, __asan_load16, - }, { - __asan_store1, __asan_store2, __asan_store4, __asan_store8, - __asan_store16, - } - }; - - uptr buggy_ptr; - - __asan_test_only_reported_buggy_pointer = &buggy_ptr; - BufferedStackTrace stack; - stack.trace_buffer[0] = 0x890; - stack.size = 1; - - for (uptr len = 16; len <= 32; len++) { - char *ptr = (char*) __asan::asan_malloc(len, &stack); - uptr p = reinterpret_cast<uptr>(ptr); - for (uptr is_write = 0; is_write <= 1; is_write++) { - for (uptr size_log = 0; size_log <= 4; size_log++) { - uptr size = 1 << size_log; - CB call = cb[is_write][size_log]; - // Iterate only size-aligned offsets. - for (uptr offset = 0; offset <= len; offset += size) { - buggy_ptr = 0; - call(p + offset); - if (offset + size <= len) - EXPECT_EQ(buggy_ptr, 0U); - else - EXPECT_EQ(buggy_ptr, p + offset); - } - } - } - __asan::asan_free(ptr, &stack, __asan::FROM_MALLOC); - } - __asan_test_only_reported_buggy_pointer = 0; -} diff --git a/lib/asan/tests/asan_oob_test.cc b/lib/asan/tests/asan_oob_test.cc deleted file mode 100644 index 0c6bea2858649..0000000000000 --- a/lib/asan/tests/asan_oob_test.cc +++ /dev/null @@ -1,128 +0,0 @@ -//===-- asan_oob_test.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -NOINLINE void asan_write_sized_aligned(uint8_t *p, size_t size) { - EXPECT_EQ(0U, ((uintptr_t)p % size)); - if (size == 1) asan_write((uint8_t*)p); - else if (size == 2) asan_write((uint16_t*)p); - else if (size == 4) asan_write((uint32_t*)p); - else if (size == 8) asan_write((uint64_t*)p); -} - -template<typename T> -NOINLINE void oob_test(int size, int off) { - char *p = (char*)malloc_aaa(size); - // fprintf(stderr, "writing %d byte(s) into [%p,%p) with offset %d\n", - // sizeof(T), p, p + size, off); - asan_write((T*)(p + off)); - free_aaa(p); -} - -template<typename T> -void OOBTest() { - char expected_str[100]; - for (int size = sizeof(T); size < 20; size += 5) { - for (int i = -5; i < 0; i++) { - const char *str = - "is located.*%d byte.*to the left"; - sprintf(expected_str, str, abs(i)); - EXPECT_DEATH(oob_test<T>(size, i), expected_str); - } - - for (int i = 0; i < (int)(size - sizeof(T) + 1); i++) - oob_test<T>(size, i); - - for (int i = size - sizeof(T) + 1; i <= (int)(size + 2 * sizeof(T)); i++) { - const char *str = - "is located.*%d byte.*to the right"; - int off = i >= size ? (i - size) : 0; - // we don't catch unaligned partially OOB accesses. - if (i % sizeof(T)) continue; - sprintf(expected_str, str, off); - EXPECT_DEATH(oob_test<T>(size, i), expected_str); - } - } - - EXPECT_DEATH(oob_test<T>(kLargeMalloc, -1), - "is located.*1 byte.*to the left"); - EXPECT_DEATH(oob_test<T>(kLargeMalloc, kLargeMalloc), - "is located.*0 byte.*to the right"); -} - -// TODO(glider): the following tests are EXTREMELY slow on Darwin: -// AddressSanitizer.OOB_char (125503 ms) -// AddressSanitizer.OOB_int (126890 ms) -// AddressSanitizer.OOBRightTest (315605 ms) -// AddressSanitizer.SimpleStackTest (366559 ms) - -TEST(AddressSanitizer, OOB_char) { - OOBTest<U1>(); -} - -TEST(AddressSanitizer, OOB_int) { - OOBTest<U4>(); -} - -TEST(AddressSanitizer, OOBRightTest) { - size_t max_access_size = SANITIZER_WORDSIZE == 64 ? 8 : 4; - for (size_t access_size = 1; access_size <= max_access_size; - access_size *= 2) { - for (size_t alloc_size = 1; alloc_size <= 8; alloc_size++) { - for (size_t offset = 0; offset <= 8; offset += access_size) { - void *p = malloc(alloc_size); - // allocated: [p, p + alloc_size) - // accessed: [p + offset, p + offset + access_size) - uint8_t *addr = (uint8_t*)p + offset; - if (offset + access_size <= alloc_size) { - asan_write_sized_aligned(addr, access_size); - } else { - int outside_bytes = offset > alloc_size ? (offset - alloc_size) : 0; - const char *str = - "is located.%d *byte.*to the right"; - char expected_str[100]; - sprintf(expected_str, str, outside_bytes); - EXPECT_DEATH(asan_write_sized_aligned(addr, access_size), - expected_str); - } - free(p); - } - } - } -} - -TEST(AddressSanitizer, LargeOOBRightTest) { - size_t large_power_of_two = 1 << 19; - for (size_t i = 16; i <= 256; i *= 2) { - size_t size = large_power_of_two - i; - char *p = Ident(new char[size]); - EXPECT_DEATH(p[size] = 0, "is located 0 bytes to the right"); - delete [] p; - } -} - -TEST(AddressSanitizer, DISABLED_DemoOOBLeftLow) { - oob_test<U1>(10, -1); -} - -TEST(AddressSanitizer, DISABLED_DemoOOBLeftHigh) { - oob_test<U1>(kLargeMalloc, -1); -} - -TEST(AddressSanitizer, DISABLED_DemoOOBRightLow) { - oob_test<U1>(10, 10); -} - -TEST(AddressSanitizer, DISABLED_DemoOOBRightHigh) { - oob_test<U1>(kLargeMalloc, kLargeMalloc); -} diff --git a/lib/asan/tests/asan_racy_double_free_test.cc b/lib/asan/tests/asan_racy_double_free_test.cc deleted file mode 100644 index 23240e714d561..0000000000000 --- a/lib/asan/tests/asan_racy_double_free_test.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include <pthread.h> -#include <stdlib.h> -#include <stdio.h> - -const int N = 1000; -void *x[N]; - -void *Thread1(void *unused) { - for (int i = 0; i < N; i++) { - fprintf(stderr, "%s %d\n", __func__, i); - free(x[i]); - } - return NULL; -} - -void *Thread2(void *unused) { - for (int i = 0; i < N; i++) { - fprintf(stderr, "%s %d\n", __func__, i); - free(x[i]); - } - return NULL; -} - -int main() { - for (int i = 0; i < N; i++) - x[i] = malloc(128); - pthread_t t[2]; - pthread_create(&t[0], 0, Thread1, 0); - pthread_create(&t[1], 0, Thread2, 0); - pthread_join(t[0], 0); - pthread_join(t[1], 0); -} diff --git a/lib/asan/tests/asan_str_test.cc b/lib/asan/tests/asan_str_test.cc deleted file mode 100644 index 5cf4e05c81c82..0000000000000 --- a/lib/asan/tests/asan_str_test.cc +++ /dev/null @@ -1,635 +0,0 @@ -//=-- asan_str_test.cc ----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -#if defined(__APPLE__) -#include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_* -#endif - -// Used for string functions tests -static char global_string[] = "global"; -static size_t global_string_length = 6; - -const char kStackReadUnderflow[] = -#if !GTEST_USES_SIMPLE_RE - ASAN_PCRE_DOTALL - "READ.*" -#endif - "underflows this variable"; -const char kStackReadOverflow[] = -#if !GTEST_USES_SIMPLE_RE - ASAN_PCRE_DOTALL - "READ.*" -#endif - "overflows this variable"; - -namespace { -enum class OOBKind { - Heap, - Stack, - Global, -}; - -string LeftOOBReadMessage(OOBKind oob_kind, int oob_distance) { - return oob_kind == OOBKind::Stack ? kStackReadUnderflow - : ::LeftOOBReadMessage(oob_distance); -} - -string RightOOBReadMessage(OOBKind oob_kind, int oob_distance) { - return oob_kind == OOBKind::Stack ? kStackReadOverflow - : ::RightOOBReadMessage(oob_distance); -} -} // namespace - -// Input to a test is a zero-terminated string str with given length -// Accesses to the bytes to the left and to the right of str -// are presumed to produce OOB errors -void StrLenOOBTestTemplate(char *str, size_t length, OOBKind oob_kind) { - // Normal strlen calls - EXPECT_EQ(strlen(str), length); - if (length > 0) { - EXPECT_EQ(length - 1, strlen(str + 1)); - EXPECT_EQ(0U, strlen(str + length)); - } - // Arg of strlen is not malloced, OOB access - if (oob_kind != OOBKind::Global) { - // We don't insert RedZones to the left of global variables - EXPECT_DEATH(Ident(strlen(str - 1)), LeftOOBReadMessage(oob_kind, 1)); - EXPECT_DEATH(Ident(strlen(str - 5)), LeftOOBReadMessage(oob_kind, 5)); - } - EXPECT_DEATH(Ident(strlen(str + length + 1)), - RightOOBReadMessage(oob_kind, 0)); - // Overwrite terminator - str[length] = 'a'; - // String is not zero-terminated, strlen will lead to OOB access - EXPECT_DEATH(Ident(strlen(str)), RightOOBReadMessage(oob_kind, 0)); - EXPECT_DEATH(Ident(strlen(str + length)), RightOOBReadMessage(oob_kind, 0)); - // Restore terminator - str[length] = 0; -} -TEST(AddressSanitizer, StrLenOOBTest) { - // Check heap-allocated string - size_t length = Ident(10); - char *heap_string = Ident((char*)malloc(length + 1)); - char stack_string[10 + 1]; - break_optimization(&stack_string); - for (size_t i = 0; i < length; i++) { - heap_string[i] = 'a'; - stack_string[i] = 'b'; - } - heap_string[length] = 0; - stack_string[length] = 0; - StrLenOOBTestTemplate(heap_string, length, OOBKind::Heap); - StrLenOOBTestTemplate(stack_string, length, OOBKind::Stack); - StrLenOOBTestTemplate(global_string, global_string_length, OOBKind::Global); - free(heap_string); -} - -// 32-bit android libc++-based NDK toolchain links wcslen statically, disabling -// the interceptor. -#if !defined(__ANDROID__) || defined(__LP64__) -TEST(AddressSanitizer, WcsLenTest) { - EXPECT_EQ(0U, wcslen(Ident(L""))); - size_t hello_len = 13; - size_t hello_size = (hello_len + 1) * sizeof(wchar_t); - EXPECT_EQ(hello_len, wcslen(Ident(L"Hello, World!"))); - wchar_t *heap_string = Ident((wchar_t*)malloc(hello_size)); - memcpy(heap_string, L"Hello, World!", hello_size); - EXPECT_EQ(hello_len, Ident(wcslen(heap_string))); - EXPECT_DEATH(Ident(wcslen(heap_string + 14)), RightOOBReadMessage(0)); - free(heap_string); -} -#endif - -#if SANITIZER_TEST_HAS_STRNLEN -TEST(AddressSanitizer, StrNLenOOBTest) { - size_t size = Ident(123); - char *str = MallocAndMemsetString(size); - // Normal strnlen calls. - Ident(strnlen(str - 1, 0)); - Ident(strnlen(str, size)); - Ident(strnlen(str + size - 1, 1)); - str[size - 1] = '\0'; - Ident(strnlen(str, 2 * size)); - // Argument points to not allocated memory. - EXPECT_DEATH(Ident(strnlen(str - 1, 1)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strnlen(str + size, 1)), RightOOBReadMessage(0)); - // Overwrite the terminating '\0' and hit unallocated memory. - str[size - 1] = 'z'; - EXPECT_DEATH(Ident(strnlen(str, size + 1)), RightOOBReadMessage(0)); - free(str); -} -#endif // SANITIZER_TEST_HAS_STRNLEN - -// This test fails with the WinASan dynamic runtime because we fail to intercept -// strdup. -#if defined(_MSC_VER) && defined(_DLL) -#define MAYBE_StrDupOOBTest DISABLED_StrDupOOBTest -#else -#define MAYBE_StrDupOOBTest StrDupOOBTest -#endif - -TEST(AddressSanitizer, MAYBE_StrDupOOBTest) { - size_t size = Ident(42); - char *str = MallocAndMemsetString(size); - char *new_str; - // Normal strdup calls. - str[size - 1] = '\0'; - new_str = strdup(str); - free(new_str); - new_str = strdup(str + size - 1); - free(new_str); - // Argument points to not allocated memory. - EXPECT_DEATH(Ident(strdup(str - 1)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strdup(str + size)), RightOOBReadMessage(0)); - // Overwrite the terminating '\0' and hit unallocated memory. - str[size - 1] = 'z'; - EXPECT_DEATH(Ident(strdup(str)), RightOOBReadMessage(0)); - free(str); -} - -#if SANITIZER_TEST_HAS_STRNDUP -TEST(AddressSanitizer, MAYBE_StrNDupOOBTest) { - size_t size = Ident(42); - char *str = MallocAndMemsetString(size); - char *new_str; - // Normal strndup calls. - str[size - 1] = '\0'; - new_str = strndup(str, size - 13); - free(new_str); - new_str = strndup(str + size - 1, 13); - free(new_str); - // Argument points to not allocated memory. - EXPECT_DEATH(Ident(strndup(str - 1, 13)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strndup(str + size, 13)), RightOOBReadMessage(0)); - // Overwrite the terminating '\0' and hit unallocated memory. - str[size - 1] = 'z'; - EXPECT_DEATH(Ident(strndup(str, size + 13)), RightOOBReadMessage(0)); - // Check handling of non 0 terminated strings. - Ident(new_str = strndup(str + size - 1, 0)); - free(new_str); - Ident(new_str = strndup(str + size - 1, 1)); - free(new_str); - EXPECT_DEATH(Ident(strndup(str + size - 1, 2)), RightOOBReadMessage(0)); - free(str); -} -#endif // SANITIZER_TEST_HAS_STRNDUP - -TEST(AddressSanitizer, StrCpyOOBTest) { - size_t to_size = Ident(30); - size_t from_size = Ident(6); // less than to_size - char *to = Ident((char*)malloc(to_size)); - char *from = Ident((char*)malloc(from_size)); - // Normal strcpy calls. - strcpy(from, "hello"); - strcpy(to, from); - strcpy(to + to_size - from_size, from); - // Length of "from" is too small. - EXPECT_DEATH(Ident(strcpy(from, "hello2")), RightOOBWriteMessage(0)); - // "to" or "from" points to not allocated memory. - EXPECT_DEATH(Ident(strcpy(to - 1, from)), LeftOOBWriteMessage(1)); - EXPECT_DEATH(Ident(strcpy(to, from - 1)), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strcpy(to, from + from_size)), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(strcpy(to + to_size, from)), RightOOBWriteMessage(0)); - // Overwrite the terminating '\0' character and hit unallocated memory. - from[from_size - 1] = '!'; - EXPECT_DEATH(Ident(strcpy(to, from)), RightOOBReadMessage(0)); - free(to); - free(from); -} - -TEST(AddressSanitizer, StrNCpyOOBTest) { - size_t to_size = Ident(20); - size_t from_size = Ident(6); // less than to_size - char *to = Ident((char*)malloc(to_size)); - // From is a zero-terminated string "hello\0" of length 6 - char *from = Ident((char*)malloc(from_size)); - strcpy(from, "hello"); - // copy 0 bytes - strncpy(to, from, 0); - strncpy(to - 1, from - 1, 0); - // normal strncpy calls - strncpy(to, from, from_size); - strncpy(to, from, to_size); - strncpy(to, from + from_size - 1, to_size); - strncpy(to + to_size - 1, from, 1); - // One of {to, from} points to not allocated memory - EXPECT_DEATH(Ident(strncpy(to, from - 1, from_size)), - LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(strncpy(to - 1, from, from_size)), - LeftOOBWriteMessage(1)); - EXPECT_DEATH(Ident(strncpy(to, from + from_size, 1)), - RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(strncpy(to + to_size, from, 1)), - RightOOBWriteMessage(0)); - // Length of "to" is too small - EXPECT_DEATH(Ident(strncpy(to + to_size - from_size + 1, from, from_size)), - RightOOBWriteMessage(0)); - EXPECT_DEATH(Ident(strncpy(to + 1, from, to_size)), - RightOOBWriteMessage(0)); - // Overwrite terminator in from - from[from_size - 1] = '!'; - // normal strncpy call - strncpy(to, from, from_size); - // Length of "from" is too small - EXPECT_DEATH(Ident(strncpy(to, from, to_size)), - RightOOBReadMessage(0)); - free(to); - free(from); -} - -// Users may have different definitions of "strchr" and "index", so provide -// function pointer typedefs and overload RunStrChrTest implementation. -// We can't use macro for RunStrChrTest body here, as this macro would -// confuse EXPECT_DEATH gtest macro. -typedef char*(*PointerToStrChr1)(const char*, int); -typedef char*(*PointerToStrChr2)(char*, int); - -template<typename StrChrFn> -static void RunStrChrTestImpl(StrChrFn *StrChr) { - size_t size = Ident(100); - char *str = MallocAndMemsetString(size); - str[10] = 'q'; - str[11] = '\0'; - EXPECT_EQ(str, StrChr(str, 'z')); - EXPECT_EQ(str + 10, StrChr(str, 'q')); - EXPECT_EQ(NULL, StrChr(str, 'a')); - // StrChr argument points to not allocated memory. - EXPECT_DEATH(Ident(StrChr(str - 1, 'z')), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrChr(str + size, 'z')), RightOOBReadMessage(0)); - // Overwrite the terminator and hit not allocated memory. - str[11] = 'z'; - EXPECT_DEATH(Ident(StrChr(str, 'a')), RightOOBReadMessage(0)); - free(str); -} - -// Prefer to use the standard signature if both are available. -UNUSED static void RunStrChrTest(PointerToStrChr1 StrChr, ...) { - RunStrChrTestImpl(StrChr); -} -UNUSED static void RunStrChrTest(PointerToStrChr2 StrChr, int) { - RunStrChrTestImpl(StrChr); -} - -TEST(AddressSanitizer, StrChrAndIndexOOBTest) { - RunStrChrTest(&strchr, 0); -// No index() on Windows and on Android L. -#if !defined(_WIN32) && !defined(__ANDROID__) - RunStrChrTest(&index, 0); -#endif -} - -TEST(AddressSanitizer, StrCmpAndFriendsLogicTest) { - // strcmp - EXPECT_EQ(0, strcmp("", "")); - EXPECT_EQ(0, strcmp("abcd", "abcd")); - EXPECT_GT(0, strcmp("ab", "ac")); - EXPECT_GT(0, strcmp("abc", "abcd")); - EXPECT_LT(0, strcmp("acc", "abc")); - EXPECT_LT(0, strcmp("abcd", "abc")); - - // strncmp - EXPECT_EQ(0, strncmp("a", "b", 0)); - EXPECT_EQ(0, strncmp("abcd", "abcd", 10)); - EXPECT_EQ(0, strncmp("abcd", "abcef", 3)); - EXPECT_GT(0, strncmp("abcde", "abcfa", 4)); - EXPECT_GT(0, strncmp("a", "b", 5)); - EXPECT_GT(0, strncmp("bc", "bcde", 4)); - EXPECT_LT(0, strncmp("xyz", "xyy", 10)); - EXPECT_LT(0, strncmp("baa", "aaa", 1)); - EXPECT_LT(0, strncmp("zyx", "", 2)); - -#if !defined(_WIN32) // no str[n]casecmp on Windows. - // strcasecmp - EXPECT_EQ(0, strcasecmp("", "")); - EXPECT_EQ(0, strcasecmp("zzz", "zzz")); - EXPECT_EQ(0, strcasecmp("abCD", "ABcd")); - EXPECT_GT(0, strcasecmp("aB", "Ac")); - EXPECT_GT(0, strcasecmp("ABC", "ABCd")); - EXPECT_LT(0, strcasecmp("acc", "abc")); - EXPECT_LT(0, strcasecmp("ABCd", "abc")); - - // strncasecmp - EXPECT_EQ(0, strncasecmp("a", "b", 0)); - EXPECT_EQ(0, strncasecmp("abCD", "ABcd", 10)); - EXPECT_EQ(0, strncasecmp("abCd", "ABcef", 3)); - EXPECT_GT(0, strncasecmp("abcde", "ABCfa", 4)); - EXPECT_GT(0, strncasecmp("a", "B", 5)); - EXPECT_GT(0, strncasecmp("bc", "BCde", 4)); - EXPECT_LT(0, strncasecmp("xyz", "xyy", 10)); - EXPECT_LT(0, strncasecmp("Baa", "aaa", 1)); - EXPECT_LT(0, strncasecmp("zyx", "", 2)); -#endif - - // memcmp - EXPECT_EQ(0, memcmp("a", "b", 0)); - EXPECT_EQ(0, memcmp("ab\0c", "ab\0c", 4)); - EXPECT_GT(0, memcmp("\0ab", "\0ac", 3)); - EXPECT_GT(0, memcmp("abb\0", "abba", 4)); - EXPECT_LT(0, memcmp("ab\0cd", "ab\0c\0", 5)); - EXPECT_LT(0, memcmp("zza", "zyx", 3)); -} - -typedef int(*PointerToStrCmp)(const char*, const char*); -void RunStrCmpTest(PointerToStrCmp StrCmp) { - size_t size = Ident(100); - int fill = 'o'; - char *s1 = MallocAndMemsetString(size, fill); - char *s2 = MallocAndMemsetString(size, fill); - s1[size - 1] = '\0'; - s2[size - 1] = '\0'; - // Normal StrCmp calls - Ident(StrCmp(s1, s2)); - Ident(StrCmp(s1, s2 + size - 1)); - Ident(StrCmp(s1 + size - 1, s2 + size - 1)); - // One of arguments points to not allocated memory. - EXPECT_DEATH(Ident(StrCmp)(s1 - 1, s2), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrCmp)(s1, s2 - 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrCmp)(s1 + size, s2), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(StrCmp)(s1, s2 + size), RightOOBReadMessage(0)); - // Hit unallocated memory and die. - s1[size - 1] = fill; - EXPECT_DEATH(Ident(StrCmp)(s1, s1), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(StrCmp)(s1 + size - 1, s2), RightOOBReadMessage(0)); - free(s1); - free(s2); -} - -TEST(AddressSanitizer, StrCmpOOBTest) { - RunStrCmpTest(&strcmp); -} - -#if !defined(_WIN32) // no str[n]casecmp on Windows. -TEST(AddressSanitizer, StrCaseCmpOOBTest) { - RunStrCmpTest(&strcasecmp); -} -#endif - -typedef int(*PointerToStrNCmp)(const char*, const char*, size_t); -void RunStrNCmpTest(PointerToStrNCmp StrNCmp) { - size_t size = Ident(100); - char *s1 = MallocAndMemsetString(size); - char *s2 = MallocAndMemsetString(size); - s1[size - 1] = '\0'; - s2[size - 1] = '\0'; - // Normal StrNCmp calls - Ident(StrNCmp(s1, s2, size + 2)); - s1[size - 1] = 'z'; - s2[size - 1] = 'x'; - Ident(StrNCmp(s1 + size - 2, s2 + size - 2, size)); - s2[size - 1] = 'z'; - Ident(StrNCmp(s1 - 1, s2 - 1, 0)); - Ident(StrNCmp(s1 + size - 1, s2 + size - 1, 1)); - // One of arguments points to not allocated memory. - EXPECT_DEATH(Ident(StrNCmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrNCmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(StrNCmp)(s1 + size, s2, 1), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(StrNCmp)(s1, s2 + size, 1), RightOOBReadMessage(0)); - // Hit unallocated memory and die. - EXPECT_DEATH(Ident(StrNCmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(StrNCmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0)); - free(s1); - free(s2); -} - -TEST(AddressSanitizer, StrNCmpOOBTest) { - RunStrNCmpTest(&strncmp); -} - -#if !defined(_WIN32) // no str[n]casecmp on Windows. -TEST(AddressSanitizer, StrNCaseCmpOOBTest) { - RunStrNCmpTest(&strncasecmp); -} -#endif - -TEST(AddressSanitizer, StrCatOOBTest) { - // strcat() reads strlen(to) bytes from |to| before concatenating. - size_t to_size = Ident(100); - char *to = MallocAndMemsetString(to_size); - to[0] = '\0'; - size_t from_size = Ident(20); - char *from = MallocAndMemsetString(from_size); - from[from_size - 1] = '\0'; - // Normal strcat calls. - strcat(to, from); - strcat(to, from); - strcat(to + from_size, from + from_size - 2); - // Passing an invalid pointer is an error even when concatenating an empty - // string. - EXPECT_DEATH(strcat(to - 1, from + from_size - 1), LeftOOBAccessMessage(1)); - // One of arguments points to not allocated memory. - EXPECT_DEATH(strcat(to - 1, from), LeftOOBAccessMessage(1)); - EXPECT_DEATH(strcat(to, from - 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(strcat(to, from + from_size), RightOOBReadMessage(0)); - - // "from" is not zero-terminated. - from[from_size - 1] = 'z'; - EXPECT_DEATH(strcat(to, from), RightOOBReadMessage(0)); - from[from_size - 1] = '\0'; - // "to" is too short to fit "from". - memset(to, 'z', to_size); - to[to_size - from_size + 1] = '\0'; - EXPECT_DEATH(strcat(to, from), RightOOBWriteMessage(0)); - // length of "to" is just enough. - strcat(to, from + 1); - - free(to); - free(from); -} - -TEST(AddressSanitizer, StrNCatOOBTest) { - // strncat() reads strlen(to) bytes from |to| before concatenating. - size_t to_size = Ident(100); - char *to = MallocAndMemsetString(to_size); - to[0] = '\0'; - size_t from_size = Ident(20); - char *from = MallocAndMemsetString(from_size); - // Normal strncat calls. - strncat(to, from, 0); - strncat(to, from, from_size); - from[from_size - 1] = '\0'; - strncat(to, from, 2 * from_size); - // Catenating empty string with an invalid string is still an error. - EXPECT_DEATH(strncat(to - 1, from, 0), LeftOOBAccessMessage(1)); - strncat(to, from + from_size - 1, 10); - // One of arguments points to not allocated memory. - EXPECT_DEATH(strncat(to - 1, from, 2), LeftOOBAccessMessage(1)); - EXPECT_DEATH(strncat(to, from - 1, 2), LeftOOBReadMessage(1)); - EXPECT_DEATH(strncat(to, from + from_size, 2), RightOOBReadMessage(0)); - - memset(from, 'z', from_size); - memset(to, 'z', to_size); - to[0] = '\0'; - // "from" is too short. - EXPECT_DEATH(strncat(to, from, from_size + 1), RightOOBReadMessage(0)); - // "to" is too short to fit "from". - to[0] = 'z'; - to[to_size - from_size + 1] = '\0'; - EXPECT_DEATH(strncat(to, from, from_size - 1), RightOOBWriteMessage(0)); - // "to" is just enough. - strncat(to, from, from_size - 2); - - free(to); - free(from); -} - -static string OverlapErrorMessage(const string &func) { - return func + "-param-overlap"; -} - -TEST(AddressSanitizer, StrArgsOverlapTest) { - size_t size = Ident(100); - char *str = Ident((char*)malloc(size)); - -// Do not check memcpy() on OS X 10.7 and later, where it actually aliases -// memmove(). -#if !defined(__APPLE__) || !defined(MAC_OS_X_VERSION_10_7) || \ - (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7) - // Check "memcpy". Use Ident() to avoid inlining. -#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE - memset(str, 'z', size); - Ident(memcpy)(str + 1, str + 11, 10); - Ident(memcpy)(str, str, 0); - EXPECT_DEATH(Ident(memcpy)(str, str + 14, 15), OverlapErrorMessage("memcpy")); - EXPECT_DEATH(Ident(memcpy)(str + 14, str, 15), OverlapErrorMessage("memcpy")); -#endif -#endif - - // We do not treat memcpy with to==from as a bug. - // See http://llvm.org/bugs/show_bug.cgi?id=11763. - // EXPECT_DEATH(Ident(memcpy)(str + 20, str + 20, 1), - // OverlapErrorMessage("memcpy")); - - // Check "strcpy". - memset(str, 'z', size); - str[9] = '\0'; - strcpy(str + 10, str); - EXPECT_DEATH(strcpy(str + 9, str), OverlapErrorMessage("strcpy")); - EXPECT_DEATH(strcpy(str, str + 4), OverlapErrorMessage("strcpy")); - strcpy(str, str + 5); - - // Check "strncpy". - memset(str, 'z', size); - strncpy(str, str + 10, 10); - EXPECT_DEATH(strncpy(str, str + 9, 10), OverlapErrorMessage("strncpy")); - EXPECT_DEATH(strncpy(str + 9, str, 10), OverlapErrorMessage("strncpy")); - str[10] = '\0'; - strncpy(str + 11, str, 20); - EXPECT_DEATH(strncpy(str + 10, str, 20), OverlapErrorMessage("strncpy")); - - // Check "strcat". - memset(str, 'z', size); - str[10] = '\0'; - str[20] = '\0'; - strcat(str, str + 10); - EXPECT_DEATH(strcat(str, str + 11), OverlapErrorMessage("strcat")); - str[10] = '\0'; - strcat(str + 11, str); - EXPECT_DEATH(strcat(str, str + 9), OverlapErrorMessage("strcat")); - EXPECT_DEATH(strcat(str + 9, str), OverlapErrorMessage("strcat")); - EXPECT_DEATH(strcat(str + 10, str), OverlapErrorMessage("strcat")); - - // Check "strncat". - memset(str, 'z', size); - str[10] = '\0'; - strncat(str, str + 10, 10); // from is empty - EXPECT_DEATH(strncat(str, str + 11, 10), OverlapErrorMessage("strncat")); - str[10] = '\0'; - str[20] = '\0'; - strncat(str + 5, str, 5); - str[10] = '\0'; - EXPECT_DEATH(strncat(str + 5, str, 6), OverlapErrorMessage("strncat")); - EXPECT_DEATH(strncat(str, str + 9, 10), OverlapErrorMessage("strncat")); - - free(str); -} - -typedef void(*PointerToCallAtoi)(const char*); - -void RunAtoiOOBTest(PointerToCallAtoi Atoi) { - char *array = MallocAndMemsetString(10, '1'); - // Invalid pointer to the string. - EXPECT_DEATH(Atoi(array + 11), RightOOBReadMessage(1)); - EXPECT_DEATH(Atoi(array - 1), LeftOOBReadMessage(1)); - // Die if a buffer doesn't have terminating NULL. - EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0)); - // Make last symbol a terminating NULL - array[9] = '\0'; - Atoi(array); - // Sometimes we need to detect overflow if no digits are found. - memset(array, ' ', 10); - EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0)); - array[9] = '-'; - EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0)); - EXPECT_DEATH(Atoi(array + 9), RightOOBReadMessage(0)); - free(array); -} - -#if !defined(_WIN32) // FIXME: Fix and enable on Windows. -void CallAtoi(const char *nptr) { - Ident(atoi(nptr)); -} -void CallAtol(const char *nptr) { - Ident(atol(nptr)); -} -void CallAtoll(const char *nptr) { - Ident(atoll(nptr)); -} -TEST(AddressSanitizer, AtoiAndFriendsOOBTest) { - RunAtoiOOBTest(&CallAtoi); - RunAtoiOOBTest(&CallAtol); - RunAtoiOOBTest(&CallAtoll); -} -#endif - -typedef void(*PointerToCallStrtol)(const char*, char**, int); - -void RunStrtolOOBTest(PointerToCallStrtol Strtol) { - char *array = MallocAndMemsetString(3); - array[0] = '1'; - array[1] = '2'; - array[2] = '3'; - // Invalid pointer to the string. - EXPECT_DEATH(Strtol(array + 3, NULL, 0), RightOOBReadMessage(0)); - EXPECT_DEATH(Strtol(array - 1, NULL, 0), LeftOOBReadMessage(1)); - // Buffer overflow if there is no terminating null (depends on base). - EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); - array[2] = 'z'; - EXPECT_DEATH(Strtol(array, NULL, 36), RightOOBReadMessage(0)); - // Add terminating zero to get rid of overflow. - array[2] = '\0'; - Strtol(array, NULL, 36); - // Sometimes we need to detect overflow if no digits are found. - array[0] = array[1] = array[2] = ' '; - EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); - array[2] = '+'; - EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); - array[2] = '-'; - EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0)); - free(array); -} - -#if !defined(_WIN32) // FIXME: Fix and enable on Windows. -void CallStrtol(const char *nptr, char **endptr, int base) { - Ident(strtol(nptr, endptr, base)); -} -void CallStrtoll(const char *nptr, char **endptr, int base) { - Ident(strtoll(nptr, endptr, base)); -} -TEST(AddressSanitizer, StrtollOOBTest) { - RunStrtolOOBTest(&CallStrtoll); -} -TEST(AddressSanitizer, StrtolOOBTest) { - RunStrtolOOBTest(&CallStrtol); -} -#endif diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc deleted file mode 100644 index 464e99f614d5b..0000000000000 --- a/lib/asan/tests/asan_test.cc +++ /dev/null @@ -1,1363 +0,0 @@ -//===-- asan_test.cc ------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -#include <errno.h> -#include <stdarg.h> - -#ifdef _LIBCPP_GET_C_LOCALE -#define SANITIZER_GET_C_LOCALE _LIBCPP_GET_C_LOCALE -#else -#if defined(__FreeBSD__) -#define SANITIZER_GET_C_LOCALE 0 -#elif defined(__NetBSD__) -#define SANITIZER_GET_C_LOCALE LC_C_LOCALE -#endif -#endif - -#if defined(__sun__) && defined(__svr4__) -using std::_setjmp; -using std::_longjmp; -#endif - -NOINLINE void *malloc_fff(size_t size) { - void *res = malloc/**/(size); break_optimization(0); return res;} -NOINLINE void *malloc_eee(size_t size) { - void *res = malloc_fff(size); break_optimization(0); return res;} -NOINLINE void *malloc_ddd(size_t size) { - void *res = malloc_eee(size); break_optimization(0); return res;} -NOINLINE void *malloc_ccc(size_t size) { - void *res = malloc_ddd(size); break_optimization(0); return res;} -NOINLINE void *malloc_bbb(size_t size) { - void *res = malloc_ccc(size); break_optimization(0); return res;} -NOINLINE void *malloc_aaa(size_t size) { - void *res = malloc_bbb(size); break_optimization(0); return res;} - -NOINLINE void free_ccc(void *p) { free(p); break_optimization(0);} -NOINLINE void free_bbb(void *p) { free_ccc(p); break_optimization(0);} -NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);} - -template<typename T> -NOINLINE void uaf_test(int size, int off) { - void *p = malloc_aaa(size); - free_aaa(p); - for (int i = 1; i < 100; i++) - free_aaa(malloc_aaa(i)); - fprintf(stderr, "writing %ld byte(s) at %p with offset %d\n", - (long)sizeof(T), p, off); - asan_write((T *)((char *)p + off)); -} - -TEST(AddressSanitizer, HasFeatureAddressSanitizerTest) { -#if defined(__has_feature) && __has_feature(address_sanitizer) - bool asan = 1; -#elif defined(__SANITIZE_ADDRESS__) - bool asan = 1; -#else - bool asan = 0; -#endif - EXPECT_EQ(true, asan); -} - -TEST(AddressSanitizer, SimpleDeathTest) { - EXPECT_DEATH(exit(1), ""); -} - -TEST(AddressSanitizer, VariousMallocsTest) { - int *a = (int*)malloc(100 * sizeof(int)); - a[50] = 0; - free(a); - - int *r = (int*)malloc(10); - r = (int*)realloc(r, 2000 * sizeof(int)); - r[1000] = 0; - free(r); - - int *b = new int[100]; - b[50] = 0; - delete [] b; - - int *c = new int; - *c = 0; - delete c; - -#if SANITIZER_TEST_HAS_POSIX_MEMALIGN - void *pm = 0; - // Valid allocation. - int pm_res = posix_memalign(&pm, kPageSize, kPageSize); - EXPECT_EQ(0, pm_res); - EXPECT_NE(nullptr, pm); - free(pm); -#endif // SANITIZER_TEST_HAS_POSIX_MEMALIGN - -#if SANITIZER_TEST_HAS_MEMALIGN - int *ma = (int*)memalign(kPageSize, kPageSize); - EXPECT_EQ(0U, (uintptr_t)ma % kPageSize); - ma[123] = 0; - free(ma); -#endif // SANITIZER_TEST_HAS_MEMALIGN -} - -TEST(AddressSanitizer, CallocTest) { - int *a = (int*)calloc(100, sizeof(int)); - EXPECT_EQ(0, a[10]); - free(a); -} - -TEST(AddressSanitizer, CallocReturnsZeroMem) { - size_t sizes[] = {16, 1000, 10000, 100000, 2100000}; - for (size_t s = 0; s < sizeof(sizes)/sizeof(sizes[0]); s++) { - size_t size = sizes[s]; - for (size_t iter = 0; iter < 5; iter++) { - char *x = Ident((char*)calloc(1, size)); - EXPECT_EQ(x[0], 0); - EXPECT_EQ(x[size - 1], 0); - EXPECT_EQ(x[size / 2], 0); - EXPECT_EQ(x[size / 3], 0); - EXPECT_EQ(x[size / 4], 0); - memset(x, 0x42, size); - free(Ident(x)); -#if !defined(_WIN32) - // FIXME: OOM on Windows. We should just make this a lit test - // with quarantine size set to 1. - free(Ident(malloc(Ident(1 << 27)))); // Try to drain the quarantine. -#endif - } - } -} - -// No valloc on Windows or Android. -#if !defined(_WIN32) && !defined(__ANDROID__) -TEST(AddressSanitizer, VallocTest) { - void *a = valloc(100); - EXPECT_EQ(0U, (uintptr_t)a % kPageSize); - free(a); -} -#endif - -#if SANITIZER_TEST_HAS_PVALLOC -TEST(AddressSanitizer, PvallocTest) { - char *a = (char*)pvalloc(kPageSize + 100); - EXPECT_EQ(0U, (uintptr_t)a % kPageSize); - a[kPageSize + 101] = 1; // we should not report an error here. - free(a); - - a = (char*)pvalloc(0); // pvalloc(0) should allocate at least one page. - EXPECT_EQ(0U, (uintptr_t)a % kPageSize); - a[101] = 1; // we should not report an error here. - free(a); -} -#endif // SANITIZER_TEST_HAS_PVALLOC - -#if !defined(_WIN32) -// FIXME: Use an equivalent of pthread_setspecific on Windows. -void *TSDWorker(void *test_key) { - if (test_key) { - pthread_setspecific(*(pthread_key_t*)test_key, (void*)0xfeedface); - } - return NULL; -} - -void TSDDestructor(void *tsd) { - // Spawning a thread will check that the current thread id is not -1. - pthread_t th; - PTHREAD_CREATE(&th, NULL, TSDWorker, NULL); - PTHREAD_JOIN(th, NULL); -} - -// This tests triggers the thread-specific data destruction fiasco which occurs -// if we don't manage the TSD destructors ourselves. We create a new pthread -// key with a non-NULL destructor which is likely to be put after the destructor -// of AsanThread in the list of destructors. -// In this case the TSD for AsanThread will be destroyed before TSDDestructor -// is called for the child thread, and a CHECK will fail when we call -// pthread_create() to spawn the grandchild. -TEST(AddressSanitizer, DISABLED_TSDTest) { - pthread_t th; - pthread_key_t test_key; - pthread_key_create(&test_key, TSDDestructor); - PTHREAD_CREATE(&th, NULL, TSDWorker, &test_key); - PTHREAD_JOIN(th, NULL); - pthread_key_delete(test_key); -} -#endif - -TEST(AddressSanitizer, UAF_char) { - const char *uaf_string = "AddressSanitizer:.*heap-use-after-free"; - EXPECT_DEATH(uaf_test<U1>(1, 0), uaf_string); - EXPECT_DEATH(uaf_test<U1>(10, 0), uaf_string); - EXPECT_DEATH(uaf_test<U1>(10, 10), uaf_string); - EXPECT_DEATH(uaf_test<U1>(kLargeMalloc, 0), uaf_string); - EXPECT_DEATH(uaf_test<U1>(kLargeMalloc, kLargeMalloc / 2), uaf_string); -} - -TEST(AddressSanitizer, UAF_long_double) { - if (sizeof(long double) == sizeof(double)) return; - long double *p = Ident(new long double[10]); - EXPECT_DEATH(Ident(p)[12] = 0, "WRITE of size 1[026]"); - EXPECT_DEATH(Ident(p)[0] = Ident(p)[12], "READ of size 1[026]"); - delete [] Ident(p); -} - -#if !defined(_WIN32) -struct Packed5 { - int x; - char c; -} __attribute__((packed)); -#else -# pragma pack(push, 1) -struct Packed5 { - int x; - char c; -}; -# pragma pack(pop) -#endif - -TEST(AddressSanitizer, UAF_Packed5) { - static_assert(sizeof(Packed5) == 5, "Please check the keywords used"); - Packed5 *p = Ident(new Packed5[2]); - EXPECT_DEATH(p[0] = p[3], "READ of size 5"); - EXPECT_DEATH(p[3] = p[0], "WRITE of size 5"); - delete [] Ident(p); -} - -#if ASAN_HAS_BLACKLIST -TEST(AddressSanitizer, IgnoreTest) { - int *x = Ident(new int); - delete Ident(x); - *x = 0; -} -#endif // ASAN_HAS_BLACKLIST - -struct StructWithBitField { - int bf1:1; - int bf2:1; - int bf3:1; - int bf4:29; -}; - -TEST(AddressSanitizer, BitFieldPositiveTest) { - StructWithBitField *x = new StructWithBitField; - delete Ident(x); - EXPECT_DEATH(x->bf1 = 0, "use-after-free"); - EXPECT_DEATH(x->bf2 = 0, "use-after-free"); - EXPECT_DEATH(x->bf3 = 0, "use-after-free"); - EXPECT_DEATH(x->bf4 = 0, "use-after-free"); -} - -struct StructWithBitFields_8_24 { - int a:8; - int b:24; -}; - -TEST(AddressSanitizer, BitFieldNegativeTest) { - StructWithBitFields_8_24 *x = Ident(new StructWithBitFields_8_24); - x->a = 0; - x->b = 0; - delete Ident(x); -} - -#if ASAN_NEEDS_SEGV -namespace { - -const char kSEGVCrash[] = "AddressSanitizer: SEGV on unknown address"; -const char kOverriddenSigactionHandler[] = "Test sigaction handler\n"; -const char kOverriddenSignalHandler[] = "Test signal handler\n"; - -TEST(AddressSanitizer, WildAddressTest) { - char *c = (char*)0x123; - EXPECT_DEATH(*c = 0, kSEGVCrash); -} - -void my_sigaction_sighandler(int, siginfo_t*, void*) { - fprintf(stderr, kOverriddenSigactionHandler); - exit(1); -} - -void my_signal_sighandler(int signum) { - fprintf(stderr, kOverriddenSignalHandler); - exit(1); -} - -TEST(AddressSanitizer, SignalTest) { - struct sigaction sigact; - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_sigaction = my_sigaction_sighandler; - sigact.sa_flags = SA_SIGINFO; - char *c = (char *)0x123; - - EXPECT_DEATH(*c = 0, kSEGVCrash); - - // ASan should allow to set sigaction()... - EXPECT_EQ(0, sigaction(SIGSEGV, &sigact, 0)); -#ifdef __APPLE__ - EXPECT_EQ(0, sigaction(SIGBUS, &sigact, 0)); -#endif - EXPECT_DEATH(*c = 0, kOverriddenSigactionHandler); - - // ... and signal(). - EXPECT_NE(SIG_ERR, signal(SIGSEGV, my_signal_sighandler)); - EXPECT_DEATH(*c = 0, kOverriddenSignalHandler); -} -} // namespace -#endif - -static void TestLargeMalloc(size_t size) { - char buff[1024]; - sprintf(buff, "is located 1 bytes to the left of %lu-byte", (long)size); - EXPECT_DEATH(Ident((char*)malloc(size))[-1] = 0, buff); -} - -TEST(AddressSanitizer, LargeMallocTest) { - const int max_size = (SANITIZER_WORDSIZE == 32) ? 1 << 26 : 1 << 28; - for (int i = 113; i < max_size; i = i * 2 + 13) { - TestLargeMalloc(i); - } -} - -#if !GTEST_USES_SIMPLE_RE -TEST(AddressSanitizer, HugeMallocTest) { - if (SANITIZER_WORDSIZE != 64 || ASAN_AVOID_EXPENSIVE_TESTS) return; - size_t n_megs = 4100; - EXPECT_DEATH(Ident((char*)malloc(n_megs << 20))[-1] = 0, - "is located 1 bytes to the left|" - "AddressSanitizer failed to allocate"); -} -#endif - -#if SANITIZER_TEST_HAS_MEMALIGN -void MemalignRun(size_t align, size_t size, int idx) { - char *p = (char *)memalign(align, size); - Ident(p)[idx] = 0; - free(p); -} - -TEST(AddressSanitizer, memalign) { - for (int align = 16; align <= (1 << 23); align *= 2) { - size_t size = align * 5; - EXPECT_DEATH(MemalignRun(align, size, -1), - "is located 1 bytes to the left"); - EXPECT_DEATH(MemalignRun(align, size, size + 1), - "is located 1 bytes to the right"); - } -} -#endif // SANITIZER_TEST_HAS_MEMALIGN - -void *ManyThreadsWorker(void *a) { - for (int iter = 0; iter < 100; iter++) { - for (size_t size = 100; size < 2000; size *= 2) { - free(Ident(malloc(size))); - } - } - return 0; -} - -#if !defined(__aarch64__) && !defined(__powerpc64__) -// FIXME: Infinite loop in AArch64 (PR24389). -// FIXME: Also occasional hang on powerpc. Maybe same problem as on AArch64? -TEST(AddressSanitizer, ManyThreadsTest) { - const size_t kNumThreads = - (SANITIZER_WORDSIZE == 32 || ASAN_AVOID_EXPENSIVE_TESTS) ? 30 : 1000; - pthread_t t[kNumThreads]; - for (size_t i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, ManyThreadsWorker, (void*)i); - } - for (size_t i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} -#endif - -TEST(AddressSanitizer, ReallocTest) { - const int kMinElem = 5; - int *ptr = (int*)malloc(sizeof(int) * kMinElem); - ptr[3] = 3; - for (int i = 0; i < 10000; i++) { - ptr = (int*)realloc(ptr, - (my_rand() % 1000 + kMinElem) * sizeof(int)); - EXPECT_EQ(3, ptr[3]); - } - free(ptr); - // Realloc pointer returned by malloc(0). - int *ptr2 = Ident((int*)malloc(0)); - ptr2 = Ident((int*)realloc(ptr2, sizeof(*ptr2))); - *ptr2 = 42; - EXPECT_EQ(42, *ptr2); - free(ptr2); -} - -TEST(AddressSanitizer, ReallocFreedPointerTest) { - void *ptr = Ident(malloc(42)); - ASSERT_TRUE(NULL != ptr); - free(ptr); - EXPECT_DEATH(ptr = realloc(ptr, 77), "attempting double-free"); -} - -TEST(AddressSanitizer, ReallocInvalidPointerTest) { - void *ptr = Ident(malloc(42)); - EXPECT_DEATH(ptr = realloc((int*)ptr + 1, 77), "attempting free.*not malloc"); - free(ptr); -} - -TEST(AddressSanitizer, ZeroSizeMallocTest) { - // Test that malloc(0) and similar functions don't return NULL. - void *ptr = Ident(malloc(0)); - EXPECT_TRUE(NULL != ptr); - free(ptr); -#if SANITIZER_TEST_HAS_POSIX_MEMALIGN - int pm_res = posix_memalign(&ptr, 1<<20, 0); - EXPECT_EQ(0, pm_res); - EXPECT_TRUE(NULL != ptr); - free(ptr); -#endif // SANITIZER_TEST_HAS_POSIX_MEMALIGN - int *int_ptr = new int[0]; - int *int_ptr2 = new int[0]; - EXPECT_TRUE(NULL != int_ptr); - EXPECT_TRUE(NULL != int_ptr2); - EXPECT_NE(int_ptr, int_ptr2); - delete[] int_ptr; - delete[] int_ptr2; -} - -#if SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE -static const char *kMallocUsableSizeErrorMsg = - "AddressSanitizer: attempting to call malloc_usable_size()"; - -TEST(AddressSanitizer, MallocUsableSizeTest) { - const size_t kArraySize = 100; - char *array = Ident((char*)malloc(kArraySize)); - int *int_ptr = Ident(new int); - EXPECT_EQ(0U, malloc_usable_size(NULL)); - EXPECT_EQ(kArraySize, malloc_usable_size(array)); - EXPECT_EQ(sizeof(int), malloc_usable_size(int_ptr)); - EXPECT_DEATH(malloc_usable_size((void*)0x123), kMallocUsableSizeErrorMsg); - EXPECT_DEATH(malloc_usable_size(array + kArraySize / 2), - kMallocUsableSizeErrorMsg); - free(array); - EXPECT_DEATH(malloc_usable_size(array), kMallocUsableSizeErrorMsg); - delete int_ptr; -} -#endif // SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE - -void WrongFree() { - int *x = (int*)malloc(100 * sizeof(int)); - // Use the allocated memory, otherwise Clang will optimize it out. - Ident(x); - free(x + 1); -} - -#if !defined(_WIN32) // FIXME: This should be a lit test. -TEST(AddressSanitizer, WrongFreeTest) { - EXPECT_DEATH(WrongFree(), ASAN_PCRE_DOTALL - "ERROR: AddressSanitizer: attempting free.*not malloc" - ".*is located 4 bytes inside of 400-byte region" - ".*allocated by thread"); -} -#endif - -void DoubleFree() { - int *x = (int*)malloc(100 * sizeof(int)); - fprintf(stderr, "DoubleFree: x=%p\n", (void *)x); - free(x); - free(x); - fprintf(stderr, "should have failed in the second free(%p)\n", (void *)x); - abort(); -} - -#if !defined(_WIN32) // FIXME: This should be a lit test. -TEST(AddressSanitizer, DoubleFreeTest) { - EXPECT_DEATH(DoubleFree(), ASAN_PCRE_DOTALL - "ERROR: AddressSanitizer: attempting double-free" - ".*is located 0 bytes inside of 400-byte region" - ".*freed by thread T0 here" - ".*previously allocated by thread T0 here"); -} -#endif - -template<int kSize> -NOINLINE void SizedStackTest() { - char a[kSize]; - char *A = Ident((char*)&a); - const char *expected_death = "AddressSanitizer: stack-buffer-"; - for (size_t i = 0; i < kSize; i++) - A[i] = i; - EXPECT_DEATH(A[-1] = 0, expected_death); - EXPECT_DEATH(A[-5] = 0, expected_death); - EXPECT_DEATH(A[kSize] = 0, expected_death); - EXPECT_DEATH(A[kSize + 1] = 0, expected_death); - EXPECT_DEATH(A[kSize + 5] = 0, expected_death); - if (kSize > 16) - EXPECT_DEATH(A[kSize + 31] = 0, expected_death); -} - -TEST(AddressSanitizer, SimpleStackTest) { - SizedStackTest<1>(); - SizedStackTest<2>(); - SizedStackTest<3>(); - SizedStackTest<4>(); - SizedStackTest<5>(); - SizedStackTest<6>(); - SizedStackTest<7>(); - SizedStackTest<16>(); - SizedStackTest<25>(); - SizedStackTest<34>(); - SizedStackTest<43>(); - SizedStackTest<51>(); - SizedStackTest<62>(); - SizedStackTest<64>(); - SizedStackTest<128>(); -} - -#if !defined(_WIN32) -// FIXME: It's a bit hard to write multi-line death test expectations -// in a portable way. Anyways, this should just be turned into a lit test. -TEST(AddressSanitizer, ManyStackObjectsTest) { - char XXX[10]; - char YYY[20]; - char ZZZ[30]; - Ident(XXX); - Ident(YYY); - EXPECT_DEATH(Ident(ZZZ)[-1] = 0, ASAN_PCRE_DOTALL "XXX.*YYY.*ZZZ"); -} -#endif - -#if 0 // This test requires online symbolizer. -// Moved to lit_tests/stack-oob-frames.cc. -// Reenable here once we have online symbolizer by default. -NOINLINE static void Frame0(int frame, char *a, char *b, char *c) { - char d[4] = {0}; - char *D = Ident(d); - switch (frame) { - case 3: a[5]++; break; - case 2: b[5]++; break; - case 1: c[5]++; break; - case 0: D[5]++; break; - } -} -NOINLINE static void Frame1(int frame, char *a, char *b) { - char c[4] = {0}; Frame0(frame, a, b, c); - break_optimization(0); -} -NOINLINE static void Frame2(int frame, char *a) { - char b[4] = {0}; Frame1(frame, a, b); - break_optimization(0); -} -NOINLINE static void Frame3(int frame) { - char a[4] = {0}; Frame2(frame, a); - break_optimization(0); -} - -TEST(AddressSanitizer, GuiltyStackFrame0Test) { - EXPECT_DEATH(Frame3(0), "located .*in frame <.*Frame0"); -} -TEST(AddressSanitizer, GuiltyStackFrame1Test) { - EXPECT_DEATH(Frame3(1), "located .*in frame <.*Frame1"); -} -TEST(AddressSanitizer, GuiltyStackFrame2Test) { - EXPECT_DEATH(Frame3(2), "located .*in frame <.*Frame2"); -} -TEST(AddressSanitizer, GuiltyStackFrame3Test) { - EXPECT_DEATH(Frame3(3), "located .*in frame <.*Frame3"); -} -#endif - -NOINLINE void LongJmpFunc1(jmp_buf buf) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - longjmp(buf, 1); -} - -NOINLINE void TouchStackFunc() { - int a[100]; // long array will intersect with redzones from LongJmpFunc1. - int *A = Ident(a); - for (int i = 0; i < 100; i++) - A[i] = i*i; -} - -// Test that we handle longjmp and do not report false positives on stack. -TEST(AddressSanitizer, LongJmpTest) { - static jmp_buf buf; - if (!setjmp(buf)) { - LongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} - -#if !defined(_WIN32) // Only basic longjmp is available on Windows. -NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - _longjmp(buf, 1); -} - -NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - siglongjmp(buf, 1); -} - -#if !defined(__ANDROID__) && !defined(__arm__) && \ - !defined(__aarch64__) && !defined(__mips__) && \ - !defined(__mips64) && !defined(__s390__) -NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - __builtin_longjmp((void**)buf, 1); -} - -// Does not work on ARM: -// https://github.com/google/sanitizers/issues/185 -TEST(AddressSanitizer, BuiltinLongJmpTest) { - static jmp_buf buf; - if (!__builtin_setjmp((void**)buf)) { - BuiltinLongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} -#endif // !defined(__ANDROID__) && !defined(__arm__) && - // !defined(__aarch64__) && !defined(__mips__) - // !defined(__mips64) && !defined(__s390__) - -TEST(AddressSanitizer, UnderscopeLongJmpTest) { - static jmp_buf buf; - if (!_setjmp(buf)) { - UnderscopeLongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} - -TEST(AddressSanitizer, SigLongJmpTest) { - static sigjmp_buf buf; - if (!sigsetjmp(buf, 1)) { - SigLongJmpFunc1(buf); - } else { - TouchStackFunc(); - } -} -#endif - -// FIXME: Why does clang-cl define __EXCEPTIONS? -#if defined(__EXCEPTIONS) && !defined(_WIN32) -NOINLINE void ThrowFunc() { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - ASAN_THROW(1); -} - -TEST(AddressSanitizer, CxxExceptionTest) { - if (ASAN_UAR) return; - // TODO(kcc): this test crashes on 32-bit for some reason... - if (SANITIZER_WORDSIZE == 32) return; - try { - ThrowFunc(); - } catch(...) {} - TouchStackFunc(); -} -#endif - -void *ThreadStackReuseFunc1(void *unused) { - // create three red zones for these two stack objects. - int a; - int b; - - int *A = Ident(&a); - int *B = Ident(&b); - *A = *B; - pthread_exit(0); - return 0; -} - -void *ThreadStackReuseFunc2(void *unused) { - TouchStackFunc(); - return 0; -} - -#if !defined(__thumb__) -TEST(AddressSanitizer, ThreadStackReuseTest) { - pthread_t t; - PTHREAD_CREATE(&t, 0, ThreadStackReuseFunc1, 0); - PTHREAD_JOIN(t, 0); - PTHREAD_CREATE(&t, 0, ThreadStackReuseFunc2, 0); - PTHREAD_JOIN(t, 0); -} -#endif - -#if defined(__SSE2__) -#include <emmintrin.h> -TEST(AddressSanitizer, Store128Test) { - char *a = Ident((char*)malloc(Ident(12))); - char *p = a; - if (((uintptr_t)a % 16) != 0) - p = a + 8; - assert(((uintptr_t)p % 16) == 0); - __m128i value_wide = _mm_set1_epi16(0x1234); - EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide), - "AddressSanitizer: heap-buffer-overflow"); - EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide), - "WRITE of size 16"); - EXPECT_DEATH(_mm_store_si128((__m128i*)p, value_wide), - "located 0 bytes to the right of 12-byte"); - free(a); -} -#endif - -// FIXME: All tests that use this function should be turned into lit tests. -string RightOOBErrorMessage(int oob_distance, bool is_write) { - assert(oob_distance >= 0); - char expected_str[100]; - sprintf(expected_str, ASAN_PCRE_DOTALL -#if !GTEST_USES_SIMPLE_RE - "buffer-overflow.*%s.*" -#endif - "located %d bytes to the right", -#if !GTEST_USES_SIMPLE_RE - is_write ? "WRITE" : "READ", -#endif - oob_distance); - return string(expected_str); -} - -string RightOOBWriteMessage(int oob_distance) { - return RightOOBErrorMessage(oob_distance, /*is_write*/true); -} - -string RightOOBReadMessage(int oob_distance) { - return RightOOBErrorMessage(oob_distance, /*is_write*/false); -} - -// FIXME: All tests that use this function should be turned into lit tests. -string LeftOOBErrorMessage(int oob_distance, bool is_write) { - assert(oob_distance > 0); - char expected_str[100]; - sprintf(expected_str, -#if !GTEST_USES_SIMPLE_RE - ASAN_PCRE_DOTALL "%s.*" -#endif - "located %d bytes to the left", -#if !GTEST_USES_SIMPLE_RE - is_write ? "WRITE" : "READ", -#endif - oob_distance); - return string(expected_str); -} - -string LeftOOBWriteMessage(int oob_distance) { - return LeftOOBErrorMessage(oob_distance, /*is_write*/true); -} - -string LeftOOBReadMessage(int oob_distance) { - return LeftOOBErrorMessage(oob_distance, /*is_write*/false); -} - -string LeftOOBAccessMessage(int oob_distance) { - assert(oob_distance > 0); - char expected_str[100]; - sprintf(expected_str, "located %d bytes to the left", oob_distance); - return string(expected_str); -} - -char* MallocAndMemsetString(size_t size, char ch) { - char *s = Ident((char*)malloc(size)); - memset(s, ch, size); - return s; -} - -char* MallocAndMemsetString(size_t size) { - return MallocAndMemsetString(size, 'z'); -} - -#if defined(__linux__) && !defined(__ANDROID__) -#define READ_TEST(READ_N_BYTES) \ - char *x = new char[10]; \ - int fd = open("/proc/self/stat", O_RDONLY); \ - ASSERT_GT(fd, 0); \ - EXPECT_DEATH(READ_N_BYTES, \ - ASAN_PCRE_DOTALL \ - "AddressSanitizer: heap-buffer-overflow" \ - ".* is located 0 bytes to the right of 10-byte region"); \ - close(fd); \ - delete [] x; \ - -TEST(AddressSanitizer, pread) { - READ_TEST(pread(fd, x, 15, 0)); -} - -TEST(AddressSanitizer, pread64) { - READ_TEST(pread64(fd, x, 15, 0)); -} - -TEST(AddressSanitizer, read) { - READ_TEST(read(fd, x, 15)); -} -#endif // defined(__linux__) && !defined(__ANDROID__) - -// This test case fails -// Clang optimizes memcpy/memset calls which lead to unaligned access -TEST(AddressSanitizer, DISABLED_MemIntrinsicUnalignedAccessTest) { - int size = Ident(4096); - char *s = Ident((char*)malloc(size)); - EXPECT_DEATH(memset(s + size - 1, 0, 2), RightOOBWriteMessage(0)); - free(s); -} - -NOINLINE static int LargeFunction(bool do_bad_access) { - int *x = new int[100]; - x[0]++; - x[1]++; - x[2]++; - x[3]++; - x[4]++; - x[5]++; - x[6]++; - x[7]++; - x[8]++; - x[9]++; - - x[do_bad_access ? 100 : 0]++; int res = __LINE__; - - x[10]++; - x[11]++; - x[12]++; - x[13]++; - x[14]++; - x[15]++; - x[16]++; - x[17]++; - x[18]++; - x[19]++; - - delete[] x; - return res; -} - -// Test the we have correct debug info for the failing instruction. -// This test requires the in-process symbolizer to be enabled by default. -TEST(AddressSanitizer, DISABLED_LargeFunctionSymbolizeTest) { - int failing_line = LargeFunction(false); - char expected_warning[128]; - sprintf(expected_warning, "LargeFunction.*asan_test.*:%d", failing_line); - EXPECT_DEATH(LargeFunction(true), expected_warning); -} - -// Check that we unwind and symbolize correctly. -TEST(AddressSanitizer, DISABLED_MallocFreeUnwindAndSymbolizeTest) { - int *a = (int*)malloc_aaa(sizeof(int)); - *a = 1; - free_aaa(a); - EXPECT_DEATH(*a = 1, "free_ccc.*free_bbb.*free_aaa.*" - "malloc_fff.*malloc_eee.*malloc_ddd"); -} - -static bool TryToSetThreadName(const char *name) { -#if defined(__linux__) && defined(PR_SET_NAME) - return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); -#else - return false; -#endif -} - -void *ThreadedTestAlloc(void *a) { - EXPECT_EQ(true, TryToSetThreadName("AllocThr")); - int **p = (int**)a; - *p = new int; - return 0; -} - -void *ThreadedTestFree(void *a) { - EXPECT_EQ(true, TryToSetThreadName("FreeThr")); - int **p = (int**)a; - delete *p; - return 0; -} - -void *ThreadedTestUse(void *a) { - EXPECT_EQ(true, TryToSetThreadName("UseThr")); - int **p = (int**)a; - **p = 1; - return 0; -} - -void ThreadedTestSpawn() { - pthread_t t; - int *x; - PTHREAD_CREATE(&t, 0, ThreadedTestAlloc, &x); - PTHREAD_JOIN(t, 0); - PTHREAD_CREATE(&t, 0, ThreadedTestFree, &x); - PTHREAD_JOIN(t, 0); - PTHREAD_CREATE(&t, 0, ThreadedTestUse, &x); - PTHREAD_JOIN(t, 0); -} - -#if !defined(_WIN32) // FIXME: This should be a lit test. -TEST(AddressSanitizer, ThreadedTest) { - EXPECT_DEATH(ThreadedTestSpawn(), - ASAN_PCRE_DOTALL - "Thread T.*created" - ".*Thread T.*created" - ".*Thread T.*created"); -} -#endif - -void *ThreadedTestFunc(void *unused) { - // Check if prctl(PR_SET_NAME) is supported. Return if not. - if (!TryToSetThreadName("TestFunc")) - return 0; - EXPECT_DEATH(ThreadedTestSpawn(), - ASAN_PCRE_DOTALL - "WRITE .*thread T. .UseThr." - ".*freed by thread T. .FreeThr. here:" - ".*previously allocated by thread T. .AllocThr. here:" - ".*Thread T. .UseThr. created by T.*TestFunc" - ".*Thread T. .FreeThr. created by T" - ".*Thread T. .AllocThr. created by T" - ""); - return 0; -} - -TEST(AddressSanitizer, ThreadNamesTest) { - // Run ThreadedTestFunc in a separate thread because it tries to set a - // thread name and we don't want to change the main thread's name. - pthread_t t; - PTHREAD_CREATE(&t, 0, ThreadedTestFunc, 0); - PTHREAD_JOIN(t, 0); -} - -#if ASAN_NEEDS_SEGV -TEST(AddressSanitizer, ShadowGapTest) { -#if SANITIZER_WORDSIZE == 32 - char *addr = (char*)0x23000000; -#else -# if defined(__powerpc64__) - char *addr = (char*)0x024000800000; -# elif defined(__s390x__) - char *addr = (char*)0x11000000000000; -# else - char *addr = (char*)0x0000100000080000; -# endif -#endif - EXPECT_DEATH(*addr = 1, "AddressSanitizer: (SEGV|BUS) on unknown"); -} -#endif // ASAN_NEEDS_SEGV - -extern "C" { -NOINLINE static void UseThenFreeThenUse() { - char *x = Ident((char*)malloc(8)); - *x = 1; - free_aaa(x); - *x = 2; -} -} - -TEST(AddressSanitizer, UseThenFreeThenUseTest) { - EXPECT_DEATH(UseThenFreeThenUse(), "freed by thread"); -} - -TEST(AddressSanitizer, StrDupTest) { - free(strdup(Ident("123"))); -} - -// Currently we create and poison redzone at right of global variables. -static char static110[110]; -const char ConstGlob[7] = {1, 2, 3, 4, 5, 6, 7}; -static const char StaticConstGlob[3] = {9, 8, 7}; - -TEST(AddressSanitizer, GlobalTest) { - static char func_static15[15]; - - static char fs1[10]; - static char fs2[10]; - static char fs3[10]; - - glob5[Ident(0)] = 0; - glob5[Ident(1)] = 0; - glob5[Ident(2)] = 0; - glob5[Ident(3)] = 0; - glob5[Ident(4)] = 0; - - EXPECT_DEATH(glob5[Ident(5)] = 0, - "0 bytes to the right of global variable.*glob5.* size 5"); - EXPECT_DEATH(glob5[Ident(5+6)] = 0, - "6 bytes to the right of global variable.*glob5.* size 5"); - Ident(static110); // avoid optimizations - static110[Ident(0)] = 0; - static110[Ident(109)] = 0; - EXPECT_DEATH(static110[Ident(110)] = 0, - "0 bytes to the right of global variable"); - EXPECT_DEATH(static110[Ident(110+7)] = 0, - "7 bytes to the right of global variable"); - - Ident(func_static15); // avoid optimizations - func_static15[Ident(0)] = 0; - EXPECT_DEATH(func_static15[Ident(15)] = 0, - "0 bytes to the right of global variable"); - EXPECT_DEATH(func_static15[Ident(15 + 9)] = 0, - "9 bytes to the right of global variable"); - - Ident(fs1); - Ident(fs2); - Ident(fs3); - - // We don't create left redzones, so this is not 100% guaranteed to fail. - // But most likely will. - EXPECT_DEATH(fs2[Ident(-1)] = 0, "is located.*of global variable"); - - EXPECT_DEATH(Ident(Ident(ConstGlob)[8]), - "is located 1 bytes to the right of .*ConstGlob"); - EXPECT_DEATH(Ident(Ident(StaticConstGlob)[5]), - "is located 2 bytes to the right of .*StaticConstGlob"); - - // call stuff from another file. - GlobalsTest(0); -} - -TEST(AddressSanitizer, GlobalStringConstTest) { - static const char *zoo = "FOOBAR123"; - const char *p = Ident(zoo); - EXPECT_DEATH(Ident(p[15]), "is ascii string 'FOOBAR123'"); -} - -TEST(AddressSanitizer, FileNameInGlobalReportTest) { - static char zoo[10]; - const char *p = Ident(zoo); - // The file name should be present in the report. - EXPECT_DEATH(Ident(p[15]), "zoo.*asan_test."); -} - -int *ReturnsPointerToALocalObject() { - int a = 0; - return Ident(&a); -} - -#if ASAN_UAR == 1 -TEST(AddressSanitizer, LocalReferenceReturnTest) { - int *(*f)() = Ident(ReturnsPointerToALocalObject); - int *p = f(); - // Call 'f' a few more times, 'p' should still be poisoned. - for (int i = 0; i < 32; i++) - f(); - EXPECT_DEATH(*p = 1, "AddressSanitizer: stack-use-after-return"); - EXPECT_DEATH(*p = 1, "is located.*in frame .*ReturnsPointerToALocal"); -} -#endif - -template <int kSize> -NOINLINE static void FuncWithStack() { - char x[kSize]; - Ident(x)[0] = 0; - Ident(x)[kSize-1] = 0; -} - -static void LotsOfStackReuse() { - int LargeStack[10000]; - Ident(LargeStack)[0] = 0; - for (int i = 0; i < 10000; i++) { - FuncWithStack<128 * 1>(); - FuncWithStack<128 * 2>(); - FuncWithStack<128 * 4>(); - FuncWithStack<128 * 8>(); - FuncWithStack<128 * 16>(); - FuncWithStack<128 * 32>(); - FuncWithStack<128 * 64>(); - FuncWithStack<128 * 128>(); - FuncWithStack<128 * 256>(); - FuncWithStack<128 * 512>(); - Ident(LargeStack)[0] = 0; - } -} - -TEST(AddressSanitizer, StressStackReuseTest) { - LotsOfStackReuse(); -} - -TEST(AddressSanitizer, ThreadedStressStackReuseTest) { - const int kNumThreads = 20; - pthread_t t[kNumThreads]; - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, (void* (*)(void *x))LotsOfStackReuse, 0); - } - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } -} - -// pthread_exit tries to perform unwinding stuff that leads to dlopen'ing -// libgcc_s.so. dlopen in its turn calls malloc to store "libgcc_s.so" string -// that confuses LSan on Thumb because it fails to understand that this -// allocation happens in dynamic linker and should be ignored. -#if !defined(__thumb__) -static void *PthreadExit(void *a) { - pthread_exit(0); - return 0; -} - -TEST(AddressSanitizer, PthreadExitTest) { - pthread_t t; - for (int i = 0; i < 1000; i++) { - PTHREAD_CREATE(&t, 0, PthreadExit, 0); - PTHREAD_JOIN(t, 0); - } -} -#endif - -// FIXME: Why does clang-cl define __EXCEPTIONS? -#if defined(__EXCEPTIONS) && !defined(_WIN32) -NOINLINE static void StackReuseAndException() { - int large_stack[1000]; - Ident(large_stack); - ASAN_THROW(1); -} - -// TODO(kcc): support exceptions with use-after-return. -TEST(AddressSanitizer, DISABLED_StressStackReuseAndExceptionsTest) { - for (int i = 0; i < 10000; i++) { - try { - StackReuseAndException(); - } catch(...) { - } - } -} -#endif - -#if !defined(_WIN32) -TEST(AddressSanitizer, MlockTest) { - EXPECT_EQ(0, mlockall(MCL_CURRENT)); - EXPECT_EQ(0, mlock((void*)0x12345, 0x5678)); - EXPECT_EQ(0, munlockall()); - EXPECT_EQ(0, munlock((void*)0x987, 0x654)); -} -#endif - -struct LargeStruct { - int foo[100]; -}; - -// Test for bug http://llvm.org/bugs/show_bug.cgi?id=11763. -// Struct copy should not cause asan warning even if lhs == rhs. -TEST(AddressSanitizer, LargeStructCopyTest) { - LargeStruct a; - *Ident(&a) = *Ident(&a); -} - -ATTRIBUTE_NO_SANITIZE_ADDRESS -static void NoSanitizeAddress() { - char *foo = new char[10]; - Ident(foo)[10] = 0; - delete [] foo; -} - -TEST(AddressSanitizer, AttributeNoSanitizeAddressTest) { - Ident(NoSanitizeAddress)(); -} - -// The new/delete/etc mismatch checks don't work on Android, -// as calls to new/delete go through malloc/free. -// OS X support is tracked here: -// https://github.com/google/sanitizers/issues/131 -// Windows support is tracked here: -// https://github.com/google/sanitizers/issues/309 -#if !defined(__ANDROID__) && \ - !defined(__APPLE__) && \ - !defined(_WIN32) -static string MismatchStr(const string &str) { - return string("AddressSanitizer: alloc-dealloc-mismatch \\(") + str; -} - -static string MismatchOrNewDeleteTypeStr(const string &mismatch_str) { - return "(" + MismatchStr(mismatch_str) + - ")|(AddressSanitizer: new-delete-type-mismatch)"; -} - -TEST(AddressSanitizer, AllocDeallocMismatch) { - EXPECT_DEATH(free(Ident(new int)), - MismatchStr("operator new vs free")); - EXPECT_DEATH(free(Ident(new int[2])), - MismatchStr("operator new \\[\\] vs free")); - EXPECT_DEATH( - delete (Ident(new int[2])), - MismatchOrNewDeleteTypeStr("operator new \\[\\] vs operator delete")); - EXPECT_DEATH(delete (Ident((int *)malloc(2 * sizeof(int)))), - MismatchOrNewDeleteTypeStr("malloc vs operator delete")); - EXPECT_DEATH(delete [] (Ident(new int)), - MismatchStr("operator new vs operator delete \\[\\]")); - EXPECT_DEATH(delete [] (Ident((int*)malloc(2 * sizeof(int)))), - MismatchStr("malloc vs operator delete \\[\\]")); -} -#endif - -// ------------------ demo tests; run each one-by-one ------------- -// e.g. --gtest_filter=*DemoOOBLeftHigh --gtest_also_run_disabled_tests -TEST(AddressSanitizer, DISABLED_DemoThreadedTest) { - ThreadedTestSpawn(); -} - -void *SimpleBugOnSTack(void *x = 0) { - char a[20]; - Ident(a)[20] = 0; - return 0; -} - -TEST(AddressSanitizer, DISABLED_DemoStackTest) { - SimpleBugOnSTack(); -} - -TEST(AddressSanitizer, DISABLED_DemoThreadStackTest) { - pthread_t t; - PTHREAD_CREATE(&t, 0, SimpleBugOnSTack, 0); - PTHREAD_JOIN(t, 0); -} - -TEST(AddressSanitizer, DISABLED_DemoUAFLowIn) { - uaf_test<U1>(10, 0); -} -TEST(AddressSanitizer, DISABLED_DemoUAFLowLeft) { - uaf_test<U1>(10, -2); -} -TEST(AddressSanitizer, DISABLED_DemoUAFLowRight) { - uaf_test<U1>(10, 10); -} - -TEST(AddressSanitizer, DISABLED_DemoUAFHigh) { - uaf_test<U1>(kLargeMalloc, 0); -} - -TEST(AddressSanitizer, DISABLED_DemoOOM) { - size_t size = SANITIZER_WORDSIZE == 64 ? (size_t)(1ULL << 40) : (0xf0000000); - printf("%p\n", malloc(size)); -} - -TEST(AddressSanitizer, DISABLED_DemoDoubleFreeTest) { - DoubleFree(); -} - -TEST(AddressSanitizer, DISABLED_DemoNullDerefTest) { - int *a = 0; - Ident(a)[10] = 0; -} - -TEST(AddressSanitizer, DISABLED_DemoFunctionStaticTest) { - static char a[100]; - static char b[100]; - static char c[100]; - Ident(a); - Ident(b); - Ident(c); - Ident(a)[5] = 0; - Ident(b)[105] = 0; - Ident(a)[5] = 0; -} - -TEST(AddressSanitizer, DISABLED_DemoTooMuchMemoryTest) { - const size_t kAllocSize = (1 << 28) - 1024; - size_t total_size = 0; - while (true) { - void *x = malloc(kAllocSize); - memset(x, 0, kAllocSize); - total_size += kAllocSize; - fprintf(stderr, "total: %ldM %p\n", (long)total_size >> 20, x); - } -} - -#if !defined(__NetBSD__) && !defined(__i386__) -// https://github.com/google/sanitizers/issues/66 -TEST(AddressSanitizer, BufferOverflowAfterManyFrees) { - for (int i = 0; i < 1000000; i++) { - delete [] (Ident(new char [8644])); - } - char *x = new char[8192]; - EXPECT_DEATH(x[Ident(8192)] = 0, "AddressSanitizer: heap-buffer-overflow"); - delete [] Ident(x); -} -#endif - - -// Test that instrumentation of stack allocations takes into account -// AllocSize of a type, and not its StoreSize (16 vs 10 bytes for long double). -// See http://llvm.org/bugs/show_bug.cgi?id=12047 for more details. -TEST(AddressSanitizer, LongDoubleNegativeTest) { - long double a, b; - static long double c; - memcpy(Ident(&a), Ident(&b), sizeof(long double)); - memcpy(Ident(&c), Ident(&b), sizeof(long double)); -} - -#if !defined(_WIN32) -TEST(AddressSanitizer, pthread_getschedparam) { - int policy; - struct sched_param param; - EXPECT_DEATH( - pthread_getschedparam(pthread_self(), &policy, Ident(¶m) + 2), - "AddressSanitizer: stack-buffer-.*flow"); - EXPECT_DEATH( - pthread_getschedparam(pthread_self(), Ident(&policy) - 1, ¶m), - "AddressSanitizer: stack-buffer-.*flow"); - int res = pthread_getschedparam(pthread_self(), &policy, ¶m); - ASSERT_EQ(0, res); -} -#endif - -#if SANITIZER_TEST_HAS_PRINTF_L -static int vsnprintf_l_wrapper(char *s, size_t n, - locale_t l, const char *format, ...) { - va_list va; - va_start(va, format); - int res = vsnprintf_l(s, n , l, format, va); - va_end(va); - return res; -} - -TEST(AddressSanitizer, snprintf_l) { - char buff[5]; - // Check that snprintf_l() works fine with Asan. - int res = snprintf_l(buff, 5, SANITIZER_GET_C_LOCALE, "%s", "snprintf_l()"); - EXPECT_EQ(12, res); - // Check that vsnprintf_l() works fine with Asan. - res = vsnprintf_l_wrapper(buff, 5, SANITIZER_GET_C_LOCALE, "%s", - "vsnprintf_l()"); - EXPECT_EQ(13, res); - - EXPECT_DEATH( - snprintf_l(buff, 10, SANITIZER_GET_C_LOCALE, "%s", "snprintf_l()"), - "AddressSanitizer: stack-buffer-overflow"); - EXPECT_DEATH(vsnprintf_l_wrapper(buff, 10, SANITIZER_GET_C_LOCALE, "%s", - "vsnprintf_l()"), - "AddressSanitizer: stack-buffer-overflow"); -} -#endif diff --git a/lib/asan/tests/asan_test.ignore b/lib/asan/tests/asan_test.ignore deleted file mode 100644 index ea5c26099e75c..0000000000000 --- a/lib/asan/tests/asan_test.ignore +++ /dev/null @@ -1,3 +0,0 @@ -# blacklisted functions for instrumented ASan unit test -fun:*IgnoreTest* -fun:*SomeOtherFunc* diff --git a/lib/asan/tests/asan_test_config.h b/lib/asan/tests/asan_test_config.h deleted file mode 100644 index 8493f41ef4dcc..0000000000000 --- a/lib/asan/tests/asan_test_config.h +++ /dev/null @@ -1,50 +0,0 @@ -//===-- asan_test_config.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#if !defined(INCLUDED_FROM_ASAN_TEST_UTILS_H) -# error "This file should be included into asan_test_utils.h only" -#endif - -#ifndef ASAN_TEST_CONFIG_H -#define ASAN_TEST_CONFIG_H - -#include <string> - -using std::string; - -#ifndef ASAN_UAR -# error "please define ASAN_UAR" -#endif - -#ifndef ASAN_HAS_EXCEPTIONS -# error "please define ASAN_HAS_EXCEPTIONS" -#endif - -#ifndef ASAN_HAS_BLACKLIST -# error "please define ASAN_HAS_BLACKLIST" -#endif - -#ifndef ASAN_NEEDS_SEGV -# if defined(_WIN32) -# define ASAN_NEEDS_SEGV 0 -# else -# define ASAN_NEEDS_SEGV 1 -# endif -#endif - -#ifndef ASAN_AVOID_EXPENSIVE_TESTS -# define ASAN_AVOID_EXPENSIVE_TESTS 0 -#endif - -#define ASAN_PCRE_DOTALL "" - -#endif // ASAN_TEST_CONFIG_H diff --git a/lib/asan/tests/asan_test_main.cc b/lib/asan/tests/asan_test_main.cc deleted file mode 100644 index 0c1b93c7fda7d..0000000000000 --- a/lib/asan/tests/asan_test_main.cc +++ /dev/null @@ -1,56 +0,0 @@ -//===-- asan_test_main.cc -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" -#include "sanitizer_common/sanitizer_platform.h" - -// Default ASAN_OPTIONS for the unit tests. -extern "C" const char* __asan_default_options() { -#if SANITIZER_MAC - // On Darwin, we default to `abort_on_error=1`, which would make tests run - // much slower. Let's override this and run lit tests with 'abort_on_error=0' - // and make sure we do not overwhelm the syslog while testing. Also, let's - // turn symbolization off to speed up testing, especially when not running - // with llvm-symbolizer but with atos. - return "symbolize=false:abort_on_error=0:log_to_syslog=0"; -#elif SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT - // On PowerPC and ARM Thumb, a couple tests involving pthread_exit fail due to - // leaks detected by LSan. Symbolized leak report is required to apply a - // suppression for this known problem. - return ""; -#else - // Let's turn symbolization off to speed up testing (more than 3 times speedup - // observed). - return "symbolize=false"; -#endif -} - -namespace __sanitizer { -bool ReexecDisabled() { -#if __has_feature(address_sanitizer) && SANITIZER_MAC - // Allow re-exec in instrumented unit tests on Darwin. Technically, we only - // need this for 10.10 and below, where re-exec is required for the - // interceptors to work, but to avoid duplicating the version detection logic, - // let's just allow re-exec for all Darwin versions. On newer OS versions, - // returning 'false' doesn't do anything anyway, because we don't re-exec. - return false; -#else - return true; -#endif -} -} // namespace __sanitizer - -int main(int argc, char **argv) { - testing::GTEST_FLAG(death_test_style) = "threadsafe"; - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/lib/asan/tests/asan_test_utils.h b/lib/asan/tests/asan_test_utils.h deleted file mode 100644 index d7b6f82e29783..0000000000000 --- a/lib/asan/tests/asan_test_utils.h +++ /dev/null @@ -1,109 +0,0 @@ -//===-- asan_test_utils.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// - -#ifndef ASAN_TEST_UTILS_H -#define ASAN_TEST_UTILS_H - -#if !defined(SANITIZER_EXTERNAL_TEST_CONFIG) -# define INCLUDED_FROM_ASAN_TEST_UTILS_H -# include "asan_test_config.h" -# undef INCLUDED_FROM_ASAN_TEST_UTILS_H -#endif - -#include "sanitizer_test_utils.h" -#include "sanitizer_pthread_wrappers.h" - -#include <stdio.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <assert.h> -#include <algorithm> -#include <setjmp.h> - -#if !defined(_WIN32) -# include <strings.h> -# include <sys/mman.h> -#endif - -#ifdef __linux__ -# include <sys/prctl.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <fcntl.h> -#include <unistd.h> -#endif - -#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) -#include <malloc.h> -#endif - -#if ASAN_HAS_EXCEPTIONS -# define ASAN_THROW(x) throw (x) -#else -# define ASAN_THROW(x) -#endif - -typedef uint8_t U1; -typedef uint16_t U2; -typedef uint32_t U4; -typedef uint64_t U8; - -static const int kPageSize = 4096; - -// Big enough to be handled by secondary allocator and small enough to fit into -// quarantine for all configurations. -const size_t kLargeMalloc = 1 << 22; - -extern void free_aaa(void *p); -extern void *malloc_aaa(size_t size); - -template<typename T> -NOINLINE void asan_write(T *a) { - *a = 0; -} - -string RightOOBErrorMessage(int oob_distance, bool is_write); -string RightOOBWriteMessage(int oob_distance); -string RightOOBReadMessage(int oob_distance); -string LeftOOBErrorMessage(int oob_distance, bool is_write); -string LeftOOBWriteMessage(int oob_distance); -string LeftOOBReadMessage(int oob_distance); -string LeftOOBAccessMessage(int oob_distance); -char* MallocAndMemsetString(size_t size, char ch); -char* MallocAndMemsetString(size_t size); - -extern char glob1[1]; -extern char glob2[2]; -extern char glob3[3]; -extern char glob4[4]; -extern char glob5[5]; -extern char glob6[6]; -extern char glob7[7]; -extern char glob8[8]; -extern char glob9[9]; -extern char glob10[10]; -extern char glob11[11]; -extern char glob12[12]; -extern char glob13[13]; -extern char glob14[14]; -extern char glob15[15]; -extern char glob16[16]; -extern char glob17[17]; -extern char glob1000[1000]; -extern char glob10000[10000]; -extern char glob100000[100000]; -extern int GlobalsTest(int x); - -#endif // ASAN_TEST_UTILS_H diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt deleted file mode 100644 index 77947417bfed8..0000000000000 --- a/lib/builtins/CMakeLists.txt +++ /dev/null @@ -1,615 +0,0 @@ -# This directory contains a large amount of C code which provides -# generic implementations of the core runtime library along with optimized -# architecture-specific code in various subdirectories. - -if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) - cmake_minimum_required(VERSION 3.4.3) - - project(CompilerRTBuiltins C ASM) - set(COMPILER_RT_STANDALONE_BUILD TRUE) - set(COMPILER_RT_BUILTINS_STANDALONE_BUILD TRUE) - list(INSERT CMAKE_MODULE_PATH 0 - "${CMAKE_SOURCE_DIR}/../../cmake" - "${CMAKE_SOURCE_DIR}/../../cmake/Modules") - include(base-config-ix) - include(CompilerRTUtils) - - load_llvm_config() - construct_compiler_rt_default_triple() - - if(APPLE) - include(CompilerRTDarwinUtils) - endif() - include(AddCompilerRT) -endif() - -include(builtin-config-ix) - -# TODO: Need to add a mechanism for logging errors when builtin source files are -# added to a sub-directory and not this CMakeLists file. -set(GENERIC_SOURCES - absvdi2.c - absvsi2.c - absvti2.c - adddf3.c - addsf3.c - addtf3.c - addvdi3.c - addvsi3.c - addvti3.c - apple_versioning.c - ashldi3.c - ashlti3.c - ashrdi3.c - ashrti3.c - bswapdi2.c - bswapsi2.c - clzdi2.c - clzsi2.c - clzti2.c - cmpdi2.c - cmpti2.c - comparedf2.c - comparesf2.c - ctzdi2.c - ctzsi2.c - ctzti2.c - divdc3.c - divdf3.c - divdi3.c - divmoddi4.c - divmodsi4.c - divsc3.c - divsf3.c - divsi3.c - divtc3.c - divti3.c - divtf3.c - extendsfdf2.c - extendhfsf2.c - ffsdi2.c - ffssi2.c - ffsti2.c - fixdfdi.c - fixdfsi.c - fixdfti.c - fixsfdi.c - fixsfsi.c - fixsfti.c - fixunsdfdi.c - fixunsdfsi.c - fixunsdfti.c - fixunssfdi.c - fixunssfsi.c - fixunssfti.c - floatdidf.c - floatdisf.c - floatsidf.c - floatsisf.c - floattidf.c - floattisf.c - floatundidf.c - floatundisf.c - floatunsidf.c - floatunsisf.c - floatuntidf.c - floatuntisf.c - int_util.c - lshrdi3.c - lshrti3.c - moddi3.c - modsi3.c - modti3.c - muldc3.c - muldf3.c - muldi3.c - mulodi4.c - mulosi4.c - muloti4.c - mulsc3.c - mulsf3.c - multi3.c - multf3.c - mulvdi3.c - mulvsi3.c - mulvti3.c - negdf2.c - negdi2.c - negsf2.c - negti2.c - negvdi2.c - negvsi2.c - negvti2.c - os_version_check.c - paritydi2.c - paritysi2.c - parityti2.c - popcountdi2.c - popcountsi2.c - popcountti2.c - powidf2.c - powisf2.c - powitf2.c - subdf3.c - subsf3.c - subvdi3.c - subvsi3.c - subvti3.c - subtf3.c - trampoline_setup.c - truncdfhf2.c - truncdfsf2.c - truncsfhf2.c - ucmpdi2.c - ucmpti2.c - udivdi3.c - udivmoddi4.c - udivmodsi4.c - udivmodti4.c - udivsi3.c - udivti3.c - umoddi3.c - umodsi3.c - umodti3.c) - -set(GENERIC_TF_SOURCES - comparetf2.c - extenddftf2.c - extendsftf2.c - fixtfdi.c - fixtfsi.c - fixtfti.c - fixunstfdi.c - fixunstfsi.c - fixunstfti.c - floatditf.c - floatsitf.c - floattitf.c - floatunditf.c - floatunsitf.c - floatuntitf.c - multc3.c - trunctfdf2.c - trunctfsf2.c) - -option(COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN - "Skip the atomic builtin (these should normally be provided by a shared library)" - On) - -if(NOT FUCHSIA AND NOT COMPILER_RT_BAREMETAL_BUILD) - set(GENERIC_SOURCES - ${GENERIC_SOURCES} - emutls.c - enable_execute_stack.c - eprintf.c) -endif() - -if(COMPILER_RT_HAS_ATOMIC_KEYWORD AND NOT COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN) - set(GENERIC_SOURCES - ${GENERIC_SOURCES} - atomic.c) -endif() - -if(APPLE) - set(GENERIC_SOURCES - ${GENERIC_SOURCES} - atomic_flag_clear.c - atomic_flag_clear_explicit.c - atomic_flag_test_and_set.c - atomic_flag_test_and_set_explicit.c - atomic_signal_fence.c - atomic_thread_fence.c) -endif() - -if (HAVE_UNWIND_H) - set(GENERIC_SOURCES - ${GENERIC_SOURCES} - gcc_personality_v0.c) -endif () - -if (NOT FUCHSIA) - set(GENERIC_SOURCES - ${GENERIC_SOURCES} - clear_cache.c) -endif() - -# These sources work on all x86 variants, but only x86 variants. -set(x86_ARCH_SOURCES - cpu_model.c - divxc3.c - fixxfdi.c - fixxfti.c - fixunsxfdi.c - fixunsxfsi.c - fixunsxfti.c - floatdixf.c - floattixf.c - floatundixf.c - floatuntixf.c - mulxc3.c - powixf2.c -) - -if (NOT MSVC) - set(x86_64_SOURCES - x86_64/floatdidf.c - x86_64/floatdisf.c - x86_64/floatdixf.c - x86_64/floatundidf.S - x86_64/floatundisf.S - x86_64/floatundixf.S) - filter_builtin_sources(x86_64_SOURCES EXCLUDE x86_64_SOURCES "${x86_64_SOURCES};${GENERIC_SOURCES}") - set(x86_64h_SOURCES ${x86_64_SOURCES}) - - if (WIN32) - set(x86_64_SOURCES - ${x86_64_SOURCES} - x86_64/chkstk.S - x86_64/chkstk2.S) - endif() - - set(i386_SOURCES - i386/ashldi3.S - i386/ashrdi3.S - i386/divdi3.S - i386/floatdidf.S - i386/floatdisf.S - i386/floatdixf.S - i386/floatundidf.S - i386/floatundisf.S - i386/floatundixf.S - i386/lshrdi3.S - i386/moddi3.S - i386/muldi3.S - i386/udivdi3.S - i386/umoddi3.S) - filter_builtin_sources(i386_SOURCES EXCLUDE i386_SOURCES "${i386_SOURCES};${GENERIC_SOURCES}") - - if (WIN32) - set(i386_SOURCES - ${i386_SOURCES} - i386/chkstk.S - i386/chkstk2.S) - endif() -else () # MSVC - # Use C versions of functions when building on MSVC - # MSVC's assembler takes Intel syntax, not AT&T syntax. - # Also use only MSVC compilable builtin implementations. - set(x86_64_SOURCES - x86_64/floatdidf.c - x86_64/floatdisf.c - x86_64/floatdixf.c - ${GENERIC_SOURCES}) - set(x86_64h_SOURCES ${x86_64_SOURCES}) - set(i386_SOURCES ${GENERIC_SOURCES}) -endif () # if (NOT MSVC) - -set(x86_64h_SOURCES ${x86_64h_SOURCES} ${x86_ARCH_SOURCES}) -set(x86_64_SOURCES ${x86_64_SOURCES} ${x86_ARCH_SOURCES}) -set(i386_SOURCES ${i386_SOURCES} ${x86_ARCH_SOURCES}) -set(i686_SOURCES ${i686_SOURCES} ${x86_ARCH_SOURCES}) - -set(arm_SOURCES - arm/bswapdi2.S - arm/bswapsi2.S - arm/clzdi2.S - arm/clzsi2.S - arm/comparesf2.S - arm/divmodsi4.S - arm/divsi3.S - arm/modsi3.S - arm/sync_fetch_and_add_4.S - arm/sync_fetch_and_add_8.S - arm/sync_fetch_and_and_4.S - arm/sync_fetch_and_and_8.S - arm/sync_fetch_and_max_4.S - arm/sync_fetch_and_max_8.S - arm/sync_fetch_and_min_4.S - arm/sync_fetch_and_min_8.S - arm/sync_fetch_and_nand_4.S - arm/sync_fetch_and_nand_8.S - arm/sync_fetch_and_or_4.S - arm/sync_fetch_and_or_8.S - arm/sync_fetch_and_sub_4.S - arm/sync_fetch_and_sub_8.S - arm/sync_fetch_and_umax_4.S - arm/sync_fetch_and_umax_8.S - arm/sync_fetch_and_umin_4.S - arm/sync_fetch_and_umin_8.S - arm/sync_fetch_and_xor_4.S - arm/sync_fetch_and_xor_8.S - arm/udivmodsi4.S - arm/udivsi3.S - arm/umodsi3.S) -filter_builtin_sources(arm_SOURCES EXCLUDE arm_SOURCES "${arm_SOURCES};${GENERIC_SOURCES}") - -set(thumb1_SOURCES - arm/divsi3.S - arm/udivsi3.S - arm/comparesf2.S - arm/addsf3.S - ${GENERIC_SOURCES}) - -set(arm_EABI_SOURCES - arm/aeabi_cdcmp.S - arm/aeabi_cdcmpeq_check_nan.c - arm/aeabi_cfcmp.S - arm/aeabi_cfcmpeq_check_nan.c - arm/aeabi_dcmp.S - arm/aeabi_div0.c - arm/aeabi_drsub.c - arm/aeabi_fcmp.S - arm/aeabi_frsub.c - arm/aeabi_idivmod.S - arm/aeabi_ldivmod.S - arm/aeabi_memcmp.S - arm/aeabi_memcpy.S - arm/aeabi_memmove.S - arm/aeabi_memset.S - arm/aeabi_uidivmod.S - arm/aeabi_uldivmod.S) - -set(arm_Thumb1_JT_SOURCES - arm/switch16.S - arm/switch32.S - arm/switch8.S - arm/switchu8.S) -set(arm_Thumb1_SjLj_EH_SOURCES - arm/restore_vfp_d8_d15_regs.S - arm/save_vfp_d8_d15_regs.S) -set(arm_Thumb1_VFPv2_SOURCES - arm/adddf3vfp.S - arm/addsf3vfp.S - arm/divdf3vfp.S - arm/divsf3vfp.S - arm/eqdf2vfp.S - arm/eqsf2vfp.S - arm/extendsfdf2vfp.S - arm/fixdfsivfp.S - arm/fixsfsivfp.S - arm/fixunsdfsivfp.S - arm/fixunssfsivfp.S - arm/floatsidfvfp.S - arm/floatsisfvfp.S - arm/floatunssidfvfp.S - arm/floatunssisfvfp.S - arm/gedf2vfp.S - arm/gesf2vfp.S - arm/gtdf2vfp.S - arm/gtsf2vfp.S - arm/ledf2vfp.S - arm/lesf2vfp.S - arm/ltdf2vfp.S - arm/ltsf2vfp.S - arm/muldf3vfp.S - arm/mulsf3vfp.S - arm/nedf2vfp.S - arm/negdf2vfp.S - arm/negsf2vfp.S - arm/nesf2vfp.S - arm/subdf3vfp.S - arm/subsf3vfp.S - arm/truncdfsf2vfp.S - arm/unorddf2vfp.S - arm/unordsf2vfp.S) -set(arm_Thumb1_icache_SOURCES - arm/sync_synchronize.S) -set(arm_Thumb1_SOURCES - ${arm_Thumb1_JT_SOURCES} - ${arm_Thumb1_SjLj_EH_SOURCES} - ${arm_Thumb1_VFPv2_SOURCES} - ${arm_Thumb1_icache_SOURCES}) - -if(MINGW) - set(arm_SOURCES - arm/aeabi_idivmod.S - arm/aeabi_ldivmod.S - arm/aeabi_uidivmod.S - arm/aeabi_uldivmod.S - arm/chkstk.S - divmoddi4.c - divmodsi4.c - divdi3.c - divsi3.c - fixdfdi.c - fixsfdi.c - fixunsdfdi.c - fixunssfdi.c - floatdidf.c - floatdisf.c - floatundidf.c - floatundisf.c - mingw_fixfloat.c - moddi3.c - udivmoddi4.c - udivmodsi4.c - udivsi3.c - umoddi3.c - emutls.c) - filter_builtin_sources(arm_SOURCES EXCLUDE arm_SOURCES "${arm_SOURCES};${GENERIC_SOURCES}") -elseif(NOT WIN32) - # TODO the EABI sources should only be added to EABI targets - set(arm_SOURCES - ${arm_SOURCES} - ${arm_EABI_SOURCES} - ${arm_Thumb1_SOURCES}) - - set(thumb1_SOURCES - ${thumb1_SOURCES} - ${arm_EABI_SOURCES}) -endif() - -set(aarch64_SOURCES - ${GENERIC_TF_SOURCES} - ${GENERIC_SOURCES}) - -if (MINGW) - set(aarch64_SOURCES - ${aarch64_SOURCES} - aarch64/chkstk.S) -endif() - -set(armhf_SOURCES ${arm_SOURCES}) -set(armv7_SOURCES ${arm_SOURCES}) -set(armv7s_SOURCES ${arm_SOURCES}) -set(armv7k_SOURCES ${arm_SOURCES}) -set(arm64_SOURCES ${aarch64_SOURCES}) - -# macho_embedded archs -set(armv6m_SOURCES ${thumb1_SOURCES}) -set(armv7m_SOURCES ${arm_SOURCES}) -set(armv7em_SOURCES ${arm_SOURCES}) - -# hexagon arch -set(hexagon_SOURCES ${GENERIC_SOURCES} ${GENERIC_TF_SOURCES}) -set(hexagon_SOURCES - hexagon/common_entry_exit_abi1.S - hexagon/common_entry_exit_abi2.S - hexagon/common_entry_exit_legacy.S - hexagon/dfaddsub.S - hexagon/dfdiv.S - hexagon/dffma.S - hexagon/dfminmax.S - hexagon/dfmul.S - hexagon/dfsqrt.S - hexagon/divdi3.S - hexagon/divsi3.S - hexagon/fabs_opt.S - hexagon/fastmath2_dlib_asm.S - hexagon/fastmath2_ldlib_asm.S - hexagon/fastmath_dlib_asm.S - hexagon/fma_opt.S - hexagon/fmax_opt.S - hexagon/fmin_opt.S - hexagon/memcpy_forward_vp4cp4n2.S - hexagon/memcpy_likely_aligned.S - hexagon/moddi3.S - hexagon/modsi3.S - hexagon/sfdiv_opt.S - hexagon/sfsqrt_opt.S - hexagon/udivdi3.S - hexagon/udivmoddi4.S - hexagon/udivmodsi4.S - hexagon/udivsi3.S - hexagon/umoddi3.S - hexagon/umodsi3.S) - - -set(mips_SOURCES ${GENERIC_SOURCES}) -set(mipsel_SOURCES ${mips_SOURCES}) -set(mips64_SOURCES ${GENERIC_TF_SOURCES} - ${mips_SOURCES}) -set(mips64el_SOURCES ${GENERIC_TF_SOURCES} - ${mips_SOURCES}) - -set(powerpc64_SOURCES - ppc/divtc3.c - ppc/fixtfdi.c - ppc/fixunstfti.c - ppc/fixunstfdi.c - ppc/floattitf.c - ppc/floatditf.c - ppc/floatunditf.c - ppc/gcc_qadd.c - ppc/gcc_qdiv.c - ppc/gcc_qmul.c - ppc/gcc_qsub.c - ppc/multc3.c - ${GENERIC_SOURCES}) -set(powerpc64le_SOURCES ${powerpc64_SOURCES}) - -set(riscv_SOURCES ${GENERIC_SOURCES} ${GENERIC_TF_SOURCES}) -set(riscv32_SOURCES - riscv/mulsi3.S - ${riscv_SOURCES}) -set(riscv64_SOURCES ${riscv_SOURCES}) - -set(wasm32_SOURCES - ${GENERIC_TF_SOURCES} - ${GENERIC_SOURCES}) -set(wasm64_SOURCES - ${GENERIC_TF_SOURCES} - ${GENERIC_SOURCES}) - -add_custom_target(builtins) -set_target_properties(builtins PROPERTIES FOLDER "Compiler-RT Misc") - -if (APPLE) - add_subdirectory(Darwin-excludes) - add_subdirectory(macho_embedded) - darwin_add_builtin_libraries(${BUILTIN_SUPPORTED_OS}) -else () - set(BUILTIN_CFLAGS "") - - append_list_if(COMPILER_RT_HAS_STD_C11_FLAG -std=c11 BUILTIN_CFLAGS) - - # These flags would normally be added to CMAKE_C_FLAGS by the llvm - # cmake step. Add them manually if this is a standalone build. - if(COMPILER_RT_STANDALONE_BUILD) - append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC BUILTIN_CFLAGS) - append_list_if(COMPILER_RT_HAS_FNO_BUILTIN_FLAG -fno-builtin BUILTIN_CFLAGS) - append_list_if(COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG -fvisibility=hidden BUILTIN_CFLAGS) - if(NOT COMPILER_RT_DEBUG) - append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fomit-frame-pointer BUILTIN_CFLAGS) - endif() - endif() - - set(BUILTIN_DEFS "") - - append_list_if(COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG VISIBILITY_HIDDEN BUILTIN_DEFS) - - foreach (arch ${BUILTIN_SUPPORTED_ARCH}) - if (CAN_TARGET_${arch}) - # NOTE: some architectures (e.g. i386) have multiple names. Ensure that - # we catch them all. - set(_arch ${arch}) - if("${arch}" STREQUAL "armv6m") - set(_arch "arm|armv6m") - elseif("${arch}" MATCHES "^(armhf|armv7|armv7s|armv7k|armv7m|armv7em)$") - set(_arch "arm") - endif() - - # For ARM archs, exclude any VFP builtins if VFP is not supported - if (${arch} MATCHES "^(arm|armhf|armv7|armv7s|armv7k|armv7m|armv7em)$") - string(REPLACE ";" " " _TARGET_${arch}_CFLAGS "${TARGET_${arch}_CFLAGS}") - check_compile_definition(__VFP_FP__ "${CMAKE_C_FLAGS} ${_TARGET_${arch}_CFLAGS}" COMPILER_RT_HAS_${arch}_VFP) - if(NOT COMPILER_RT_HAS_${arch}_VFP) - list(REMOVE_ITEM ${arch}_SOURCES ${arm_Thumb1_VFPv2_SOURCES} ${arm_Thumb1_SjLj_EH_SOURCES}) - endif() - endif() - - # Filter out generic versions of routines that are re-implemented in - # architecture specific manner. This prevents multiple definitions of the - # same symbols, making the symbol selection non-deterministic. - foreach (_file ${${arch}_SOURCES}) - if (${_file} MATCHES ${_arch}/*) - get_filename_component(_name ${_file} NAME) - string(REPLACE ".S" ".c" _cname "${_name}") - list(REMOVE_ITEM ${arch}_SOURCES ${_cname}) - endif () - endforeach () - - # Needed for clear_cache on debug mode, due to r7's usage in inline asm. - # Release mode already sets it via -O2/3, Debug mode doesn't. - if (${arch} STREQUAL "armhf") - list(APPEND BUILTIN_CFLAGS -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET) - endif() - - # For RISCV32, we must force enable int128 for compiling long - # double routines. - if("${arch}" STREQUAL "riscv32") - list(APPEND BUILTIN_CFLAGS -fforce-enable-int128) - endif() - - add_compiler_rt_runtime(clang_rt.builtins - STATIC - ARCHS ${arch} - SOURCES ${${arch}_SOURCES} - DEFS ${BUILTIN_DEFS} - CFLAGS ${BUILTIN_CFLAGS} - PARENT_TARGET builtins) - endif () - endforeach () -endif () - -add_dependencies(compiler-rt builtins) diff --git a/lib/builtins/Darwin-excludes/CMakeLists.txt b/lib/builtins/Darwin-excludes/CMakeLists.txt deleted file mode 100644 index 266e422152436..0000000000000 --- a/lib/builtins/Darwin-excludes/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -file(GLOB filter_files ${CMAKE_CURRENT_SOURCE_DIR}/*.txt) -foreach(filter_file ${filter_files}) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${filter_file}) -endforeach() diff --git a/lib/builtins/Darwin-excludes/README.TXT b/lib/builtins/Darwin-excludes/README.TXT deleted file mode 100644 index 173eccca6decd..0000000000000 --- a/lib/builtins/Darwin-excludes/README.TXT +++ /dev/null @@ -1,11 +0,0 @@ -This folder contains list of symbols that should be excluded from the builtin -libraries for Darwin. There are two reasons symbols are excluded: - -(1) They aren't supported on Darwin -(2) They are contained within the OS on the minimum supported target - -The builtin libraries must contain all symbols not provided by the lowest -supported target OS. Meaning if minimum deployment target is iOS 6, all builtins -not included in the ios6-<arch>.txt files need to be included. The one catch is -that this is per-architecture. Since iOS 6 doesn't support arm64, when supporting -iOS 6, the minimum deployment target for arm64 binaries is iOS 7. diff --git a/lib/builtins/Darwin-excludes/ios-armv7.txt b/lib/builtins/Darwin-excludes/ios-armv7.txt deleted file mode 100644 index 6aa542f7fe4ad..0000000000000 --- a/lib/builtins/Darwin-excludes/ios-armv7.txt +++ /dev/null @@ -1,57 +0,0 @@ -absvti2 -addtf3 -addvti3 -aeabi_cdcmp -aeabi_cdcmpeq_check_nan -aeabi_cfcmp -aeabi_cfcmpeq_check_nan -aeabi_dcmp -aeabi_div0 -aeabi_drsub -aeabi_fcmp -aeabi_frsub -aeabi_idivmod -aeabi_ldivmod -aeabi_memcmp -aeabi_memcpy -aeabi_memmove -aeabi_memset -aeabi_uidivmod -aeabi_uldivmod -ashlti3 -ashrti3 -clzti2 -cmpti2 -ctzti2 -divtf3 -divti3 -ffsti2 -fixdfti -fixsfti -fixunsdfti -fixunssfti -fixunsxfti -fixxfti -floattidf -floattisf -floattixf -floatuntidf -floatuntisf -floatuntixf -lshrti3 -modti3 -multf3 -multi3 -mulvti3 -negti2 -negvti2 -parityti2 -popcountti2 -powitf2 -subtf3 -subvti3 -trampoline_setup -ucmpti2 -udivmodti4 -udivti3 -umodti3 diff --git a/lib/builtins/Darwin-excludes/ios-armv7s.txt b/lib/builtins/Darwin-excludes/ios-armv7s.txt deleted file mode 100644 index 28167aa4c5db7..0000000000000 --- a/lib/builtins/Darwin-excludes/ios-armv7s.txt +++ /dev/null @@ -1,57 +0,0 @@ -absvti2 -addtf3 -addvti3 -aeabi_cdcmp -aeabi_cdcmpeq_check_nan -aeabi_cfcmp -aeabi_cfcmpeq_check_nan -aeabi_dcmp -aeabi_div0 -aeabi_drsub -aeabi_fcmp -aeabi_frsub -aeabi_idivmod -aeabi_ldivmod -aeabi_memcmp -aeabi_memcpy -aeabi_memmove -aeabi_memset -aeabi_uidivmod -aeabi_uldivmod -ashlti3 -ashrti3 -clzti2 -cmpti2 -ctzti2 -divtf3 -divti3 -ffsti2 -fixdfti -fixsfti -fixunsdfti -fixunssfti -fixunsxfti -fixxfti -floattidf -floattisf -floattixf -floatuntidf -floatuntisf -floatuntixf -lshrti3 -modti3 -multf -multi3 -mulvti3 -negti2 -negvti2 -parityti2 -popcountti2 -powitf2 -subtf3 -subvti3 -trampoline_setup -ucmpti2 -udivmodti4 -udivti3 -umodti3 diff --git a/lib/builtins/Darwin-excludes/ios.txt b/lib/builtins/Darwin-excludes/ios.txt deleted file mode 100644 index 5db24000a1740..0000000000000 --- a/lib/builtins/Darwin-excludes/ios.txt +++ /dev/null @@ -1 +0,0 @@ -apple_versioning diff --git a/lib/builtins/Darwin-excludes/ios6-armv7.txt b/lib/builtins/Darwin-excludes/ios6-armv7.txt deleted file mode 100644 index b01fa711a357b..0000000000000 --- a/lib/builtins/Darwin-excludes/ios6-armv7.txt +++ /dev/null @@ -1,120 +0,0 @@ -absvdi2 -absvsi2 -adddf3 -adddf3vfp -addsf3 -addsf3vfp -addvdi3 -addvsi3 -ashldi3 -ashrdi3 -bswapdi2 -bswapsi2 -clzdi2 -clzsi2 -cmpdi2 -ctzdi2 -ctzsi2 -divdc3 -divdf3 -divdf3vfp -divdi3 -divmodsi4 -divsc3 -divsf3 -divsf3vfp -divsi3 -eqdf2 -eqdf2vfp -eqsf2 -eqsf2vfp -extendsfdf2 -extendsfdf2vfp -ffsdi2 -fixdfdi -fixdfsi -fixdfsivfp -fixsfdi -fixsfsi -fixsfsivfp -fixunsdfdi -fixunsdfsi -fixunsdfsivfp -fixunssfdi -fixunssfsi -fixunssfsivfp -floatdidf -floatdisf -floatsidf -floatsidfvfp -floatsisf -floatsisfvfp -floatundidf -floatundisf -floatunsidf -floatunsisf -floatunssidfvfp -floatunssisfvfp -gcc_personality_sj0 -gedf2 -gedf2vfp -gesf2 -gesf2vfp -gtdf2 -gtdf2vfp -gtsf2 -gtsf2vfp -ledf2 -ledf2vfp -lesf2 -lesf2vfp -lshrdi3 -ltdf2 -ltdf2vfp -ltsf2 -ltsf2vfp -moddi3 -modsi3 -muldc3 -muldf3 -muldf3vfp -muldi3 -mulodi4 -mulosi4 -mulsc3 -mulsf3 -mulsf3vfp -mulvdi3 -mulvsi3 -nedf2 -nedf2vfp -negdi2 -negvdi2 -negvsi2 -nesf2 -nesf2vfp -paritydi2 -paritysi2 -popcountdi2 -popcountsi2 -powidf2 -powisf2 -subdf3 -subdf3vfp -subsf3 -subsf3vfp -subvdi3 -subvsi3 -truncdfsf2 -truncdfsf2vfp -ucmpdi2 -udivdi3 -udivmoddi4 -udivmodsi4 -udivsi3 -umoddi3 -umodsi3 -unorddf2 -unorddf2vfp -unordsf2 -unordsf2vfp diff --git a/lib/builtins/Darwin-excludes/ios6-armv7s.txt b/lib/builtins/Darwin-excludes/ios6-armv7s.txt deleted file mode 100644 index b01fa711a357b..0000000000000 --- a/lib/builtins/Darwin-excludes/ios6-armv7s.txt +++ /dev/null @@ -1,120 +0,0 @@ -absvdi2 -absvsi2 -adddf3 -adddf3vfp -addsf3 -addsf3vfp -addvdi3 -addvsi3 -ashldi3 -ashrdi3 -bswapdi2 -bswapsi2 -clzdi2 -clzsi2 -cmpdi2 -ctzdi2 -ctzsi2 -divdc3 -divdf3 -divdf3vfp -divdi3 -divmodsi4 -divsc3 -divsf3 -divsf3vfp -divsi3 -eqdf2 -eqdf2vfp -eqsf2 -eqsf2vfp -extendsfdf2 -extendsfdf2vfp -ffsdi2 -fixdfdi -fixdfsi -fixdfsivfp -fixsfdi -fixsfsi -fixsfsivfp -fixunsdfdi -fixunsdfsi -fixunsdfsivfp -fixunssfdi -fixunssfsi -fixunssfsivfp -floatdidf -floatdisf -floatsidf -floatsidfvfp -floatsisf -floatsisfvfp -floatundidf -floatundisf -floatunsidf -floatunsisf -floatunssidfvfp -floatunssisfvfp -gcc_personality_sj0 -gedf2 -gedf2vfp -gesf2 -gesf2vfp -gtdf2 -gtdf2vfp -gtsf2 -gtsf2vfp -ledf2 -ledf2vfp -lesf2 -lesf2vfp -lshrdi3 -ltdf2 -ltdf2vfp -ltsf2 -ltsf2vfp -moddi3 -modsi3 -muldc3 -muldf3 -muldf3vfp -muldi3 -mulodi4 -mulosi4 -mulsc3 -mulsf3 -mulsf3vfp -mulvdi3 -mulvsi3 -nedf2 -nedf2vfp -negdi2 -negvdi2 -negvsi2 -nesf2 -nesf2vfp -paritydi2 -paritysi2 -popcountdi2 -popcountsi2 -powidf2 -powisf2 -subdf3 -subdf3vfp -subsf3 -subsf3vfp -subvdi3 -subvsi3 -truncdfsf2 -truncdfsf2vfp -ucmpdi2 -udivdi3 -udivmoddi4 -udivmodsi4 -udivsi3 -umoddi3 -umodsi3 -unorddf2 -unorddf2vfp -unordsf2 -unordsf2vfp diff --git a/lib/builtins/Darwin-excludes/ios7-arm64.txt b/lib/builtins/Darwin-excludes/ios7-arm64.txt deleted file mode 100644 index 5e4caf9e9fb73..0000000000000 --- a/lib/builtins/Darwin-excludes/ios7-arm64.txt +++ /dev/null @@ -1,16 +0,0 @@ -clzti2 -divti3 -fixdfti -fixsfti -fixunsdfti -floattidf -floattisf -floatuntidf -floatuntisf -gcc_personality_v0 -modti3 -powidf2 -powisf2 -udivmodti4 -udivti3 -umodti3 diff --git a/lib/builtins/Darwin-excludes/iossim-i386.txt b/lib/builtins/Darwin-excludes/iossim-i386.txt deleted file mode 100644 index 60c0e2d650565..0000000000000 --- a/lib/builtins/Darwin-excludes/iossim-i386.txt +++ /dev/null @@ -1,82 +0,0 @@ -absvti2 -addtf3 -addvti3 -ashlti3 -ashrti3 -clzti2 -cmpti2 -ctzti2 -divti3 -divtf3 -ffsti2 -fixdfti -fixsfti -fixunsdfti -fixunssfti -fixunsxfti -fixxfti -floattidf -floattisf -floattixf -floatuntidf -floatuntisf -floatuntixf -lshrti3 -modti3 -muloti4 -multi3 -multf3 -mulvti3 -negti2 -negvti2 -parityti2 -popcountti2 -powitf2 -subvti3 -subtf3 -trampoline_setup -ucmpti2 -udivmodti4 -udivti3 -umodti3 -absvti2 -addtf3 -addvti3 -ashlti3 -ashrti3 -clzti2 -cmpti2 -ctzti2 -divti3 -divtf3 -ffsti2 -fixdfti -fixsfti -fixunsdfti -fixunssfti -fixunsxfti -fixxfti -floattidf -floattisf -floattixf -floatuntidf -floatuntisf -floatuntixf -lshrti3 -modti3 -muloti4 -multi3 -multf3 -mulvti3 -negti2 -negvti2 -parityti2 -popcountti2 -powitf2 -subvti3 -subtf3 -trampoline_setup -ucmpti2 -udivmodti4 -udivti3 -umodti3 diff --git a/lib/builtins/Darwin-excludes/iossim-x86_64.txt b/lib/builtins/Darwin-excludes/iossim-x86_64.txt deleted file mode 100644 index de1574e6ce3d9..0000000000000 --- a/lib/builtins/Darwin-excludes/iossim-x86_64.txt +++ /dev/null @@ -1,12 +0,0 @@ -addtf3 -divtf3 -multf3 -powitf2 -subtf3 -trampoline_setup -addtf3 -divtf3 -multf3 -powitf2 -subtf3 -trampoline_setup diff --git a/lib/builtins/Darwin-excludes/iossim.txt b/lib/builtins/Darwin-excludes/iossim.txt deleted file mode 100644 index 5db24000a1740..0000000000000 --- a/lib/builtins/Darwin-excludes/iossim.txt +++ /dev/null @@ -1 +0,0 @@ -apple_versioning diff --git a/lib/builtins/Darwin-excludes/osx-i386.txt b/lib/builtins/Darwin-excludes/osx-i386.txt deleted file mode 100644 index f2ee7fef0c631..0000000000000 --- a/lib/builtins/Darwin-excludes/osx-i386.txt +++ /dev/null @@ -1,35 +0,0 @@ -absvti2 -addvti3 -ashlti3 -ashrti3 -clzti2 -cmpti2 -ctzti2 -divti3 -ffsti2 -fixdfti -fixsfti -fixunsdfti -fixunssfti -fixunsxfti -fixxfti -floattidf -floattisf -floattixf -floatuntidf -floatuntisf -floatuntixf -lshrti3 -modti3 -muloti4 -multi3 -mulvti3 -negti2 -negvti2 -parityti2 -popcountti2 -subvti3 -ucmpti2 -udivmodti4 -udivti3 -umodti3 diff --git a/lib/builtins/Darwin-excludes/osx.txt b/lib/builtins/Darwin-excludes/osx.txt deleted file mode 100644 index 6f9d0a7b245d3..0000000000000 --- a/lib/builtins/Darwin-excludes/osx.txt +++ /dev/null @@ -1,7 +0,0 @@ -apple_versioning -addtf3 -divtf3 -multf3 -powitf2 -subtf3 -trampoline_setup diff --git a/lib/builtins/macho_embedded/CMakeLists.txt b/lib/builtins/macho_embedded/CMakeLists.txt deleted file mode 100644 index 266e422152436..0000000000000 --- a/lib/builtins/macho_embedded/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -file(GLOB filter_files ${CMAKE_CURRENT_SOURCE_DIR}/*.txt) -foreach(filter_file ${filter_files}) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${filter_file}) -endforeach() diff --git a/lib/builtins/macho_embedded/arm.txt b/lib/builtins/macho_embedded/arm.txt deleted file mode 100644 index 4b1683a6baef8..0000000000000 --- a/lib/builtins/macho_embedded/arm.txt +++ /dev/null @@ -1,16 +0,0 @@ -aeabi_cdcmpeq -aeabi_cdrcmple -aeabi_cfcmpeq -aeabi_cfrcmple -aeabi_dcmpeq -aeabi_dcmpge -aeabi_dcmpgt -aeabi_dcmple -aeabi_dcmplt -aeabi_drsub -aeabi_fcmpeq -aeabi_fcmpge -aeabi_fcmpgt -aeabi_fcmple -aeabi_fcmplt -aeabi_frsub diff --git a/lib/builtins/macho_embedded/common.txt b/lib/builtins/macho_embedded/common.txt deleted file mode 100644 index 6ac85a771fcbe..0000000000000 --- a/lib/builtins/macho_embedded/common.txt +++ /dev/null @@ -1,92 +0,0 @@ -absvdi2 -absvsi2 -addvdi3 -addvsi3 -ashldi3 -ashrdi3 -clzdi2 -clzsi2 -cmpdi2 -ctzdi2 -ctzsi2 -divdc3 -divdi3 -divsc3 -divmodsi4 -udivmodsi4 -do_global_dtors -ffsdi2 -fixdfdi -fixsfdi -fixunsdfdi -fixunsdfsi -fixunssfdi -fixunssfsi -floatdidf -floatdisf -floatundidf -floatundisf -gcc_bcmp -lshrdi3 -moddi3 -muldc3 -muldi3 -mulsc3 -mulvdi3 -mulvsi3 -negdi2 -negvdi2 -negvsi2 -paritydi2 -paritysi2 -popcountdi2 -popcountsi2 -powidf2 -powisf2 -subvdi3 -subvsi3 -ucmpdi2 -udiv_w_sdiv -udivdi3 -udivmoddi4 -umoddi3 -adddf3 -addsf3 -cmpdf2 -cmpsf2 -div0 -divdf3 -divsf3 -divsi3 -extendsfdf2 -extendhfsf2 -ffssi2 -fixdfsi -fixsfsi -floatsidf -floatsisf -floatunsidf -floatunsisf -comparedf2 -comparesf2 -modsi3 -muldf3 -mulsf3 -negdf2 -negsf2 -subdf3 -subsf3 -truncdfhf2 -truncdfsf2 -truncsfhf2 -udivsi3 -umodsi3 -unorddf2 -unordsf2 -atomic_flag_clear -atomic_flag_clear_explicit -atomic_flag_test_and_set -atomic_flag_test_and_set_explicit -atomic_signal_fence -atomic_thread_fence -int_util diff --git a/lib/builtins/macho_embedded/i386.txt b/lib/builtins/macho_embedded/i386.txt deleted file mode 100644 index b92e44bb35ae3..0000000000000 --- a/lib/builtins/macho_embedded/i386.txt +++ /dev/null @@ -1,7 +0,0 @@ -i686.get_pc_thunk.eax -i686.get_pc_thunk.ebp -i686.get_pc_thunk.ebx -i686.get_pc_thunk.ecx -i686.get_pc_thunk.edi -i686.get_pc_thunk.edx -i686.get_pc_thunk.esi diff --git a/lib/builtins/macho_embedded/thumb2-64.txt b/lib/builtins/macho_embedded/thumb2-64.txt deleted file mode 100644 index 1c72fb1c3c64e..0000000000000 --- a/lib/builtins/macho_embedded/thumb2-64.txt +++ /dev/null @@ -1,10 +0,0 @@ -sync_fetch_and_add_8 -sync_fetch_and_sub_8 -sync_fetch_and_and_8 -sync_fetch_and_or_8 -sync_fetch_and_xor_8 -sync_fetch_and_nand_8 -sync_fetch_and_max_8 -sync_fetch_and_umax_8 -sync_fetch_and_min_8 -sync_fetch_and_umin_8 diff --git a/lib/builtins/macho_embedded/thumb2.txt b/lib/builtins/macho_embedded/thumb2.txt deleted file mode 100644 index 6add5ecd2dc71..0000000000000 --- a/lib/builtins/macho_embedded/thumb2.txt +++ /dev/null @@ -1,14 +0,0 @@ -switch16 -switch32 -switch8 -switchu8 -sync_fetch_and_add_4 -sync_fetch_and_sub_4 -sync_fetch_and_and_4 -sync_fetch_and_or_4 -sync_fetch_and_xor_4 -sync_fetch_and_nand_4 -sync_fetch_and_max_4 -sync_fetch_and_umax_4 -sync_fetch_and_min_4 -sync_fetch_and_umin_4 diff --git a/lib/cfi/CMakeLists.txt b/lib/cfi/CMakeLists.txt deleted file mode 100644 index 463a1fd599153..0000000000000 --- a/lib/cfi/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -add_compiler_rt_component(cfi) - -if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetBSD") - set(CFI_SOURCES cfi.cc) - - include_directories(..) - - set(CFI_CFLAGS - ${SANITIZER_COMMON_CFLAGS} - ) - - set(CFI_DIAG_CFLAGS - -DCFI_ENABLE_DIAG=1 - ) - - foreach(arch ${CFI_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.cfi - STATIC - ARCHS ${arch} - SOURCES ${CFI_SOURCES} - OBJECT_LIBS RTInterception - RTSanitizerCommon - RTSanitizerCommonLibc - CFLAGS ${CFI_CFLAGS} - PARENT_TARGET cfi) - add_compiler_rt_runtime(clang_rt.cfi_diag - STATIC - ARCHS ${arch} - SOURCES ${CFI_SOURCES} - OBJECT_LIBS RTInterception - RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTUbsan - CFLAGS ${CFI_CFLAGS} ${CFI_DIAG_CFLAGS} - PARENT_TARGET cfi) - endforeach() -endif() - -add_compiler_rt_resource_file(cfi_blacklist cfi_blacklist.txt cfi) diff --git a/lib/dfsan/.clang-format b/lib/dfsan/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/dfsan/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/dfsan/CMakeLists.txt b/lib/dfsan/CMakeLists.txt deleted file mode 100644 index b3ae713cf02c5..0000000000000 --- a/lib/dfsan/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -include_directories(..) - -# Runtime library sources and build flags. -set(DFSAN_RTL_SOURCES - dfsan.cc - dfsan_custom.cc - dfsan_interceptors.cc) - -set(DFSAN_RTL_HEADERS - dfsan.h - dfsan_flags.inc - dfsan_platform.h) - -set(DFSAN_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF DFSAN_COMMON_CFLAGS) -# Prevent clang from generating libc calls. -append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding DFSAN_COMMON_CFLAGS) - -# Static runtime library. -add_compiler_rt_component(dfsan) - -foreach(arch ${DFSAN_SUPPORTED_ARCH}) - set(DFSAN_CFLAGS ${DFSAN_COMMON_CFLAGS}) - append_list_if(COMPILER_RT_HAS_FPIE_FLAG -fPIE DFSAN_CFLAGS) - add_compiler_rt_runtime(clang_rt.dfsan - STATIC - ARCHS ${arch} - SOURCES ${DFSAN_RTL_SOURCES} - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - ADDITIONAL_HEADERS ${DFSAN_RTL_HEADERS} - CFLAGS ${DFSAN_CFLAGS} - PARENT_TARGET dfsan) - add_sanitizer_rt_symbols(clang_rt.dfsan - ARCHS ${arch} - EXTRA dfsan.syms.extra) - add_dependencies(dfsan - clang_rt.dfsan-${arch}-symbols) -endforeach() - -set(dfsan_abilist_dir ${COMPILER_RT_OUTPUT_DIR}/share) -set(dfsan_abilist_filename ${dfsan_abilist_dir}/dfsan_abilist.txt) -add_custom_target(dfsan_abilist ALL - DEPENDS ${dfsan_abilist_filename}) -add_custom_command(OUTPUT ${dfsan_abilist_filename} - VERBATIM - COMMAND - ${CMAKE_COMMAND} -E make_directory ${dfsan_abilist_dir} - COMMAND - cat ${CMAKE_CURRENT_SOURCE_DIR}/done_abilist.txt - ${CMAKE_CURRENT_SOURCE_DIR}/libc_ubuntu1404_abilist.txt - > ${dfsan_abilist_filename} - DEPENDS done_abilist.txt libc_ubuntu1404_abilist.txt) -add_dependencies(dfsan dfsan_abilist) -install(FILES ${dfsan_abilist_filename} - DESTINATION ${COMPILER_RT_INSTALL_PATH}/share) diff --git a/lib/dfsan/scripts/build-libc-list.py b/lib/dfsan/scripts/build-libc-list.py deleted file mode 100755 index eddb6c07e99d8..0000000000000 --- a/lib/dfsan/scripts/build-libc-list.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python -#===- lib/dfsan/scripts/build-libc-list.py ---------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# The purpose of this script is to identify every function symbol in a set of -# libraries (in this case, libc and libgcc) so that they can be marked as -# uninstrumented, thus allowing the instrumentation pass to treat calls to those -# functions correctly. - -import os -import subprocess -import sys -from optparse import OptionParser - -def defined_function_list(object): - functions = [] - readelf_proc = subprocess.Popen(['readelf', '-s', '-W', object], - stdout=subprocess.PIPE) - readelf = readelf_proc.communicate()[0].split('\n') - if readelf_proc.returncode != 0: - raise subprocess.CalledProcessError(readelf_proc.returncode, 'readelf') - for line in readelf: - if (line[31:35] == 'FUNC' or line[31:36] == 'IFUNC') and \ - line[39:44] != 'LOCAL' and \ - line[55:58] != 'UND': - function_name = line[59:].split('@')[0] - functions.append(function_name) - return functions - -p = OptionParser() - -p.add_option('--libc-dso-path', metavar='PATH', - help='path to libc DSO directory', - default='/lib/x86_64-linux-gnu') -p.add_option('--libc-archive-path', metavar='PATH', - help='path to libc archive directory', - default='/usr/lib/x86_64-linux-gnu') - -p.add_option('--libgcc-dso-path', metavar='PATH', - help='path to libgcc DSO directory', - default='/lib/x86_64-linux-gnu') -p.add_option('--libgcc-archive-path', metavar='PATH', - help='path to libgcc archive directory', - default='/usr/lib/gcc/x86_64-linux-gnu/4.6') - -p.add_option('--with-libstdcxx', action='store_true', - dest='with_libstdcxx', - help='include libstdc++ in the list (inadvisable)') -p.add_option('--libstdcxx-dso-path', metavar='PATH', - help='path to libstdc++ DSO directory', - default='/usr/lib/x86_64-linux-gnu') - -(options, args) = p.parse_args() - -libs = [os.path.join(options.libc_dso_path, name) for name in - ['ld-linux-x86-64.so.2', - 'libanl.so.1', - 'libBrokenLocale.so.1', - 'libcidn.so.1', - 'libcrypt.so.1', - 'libc.so.6', - 'libdl.so.2', - 'libm.so.6', - 'libnsl.so.1', - 'libpthread.so.0', - 'libresolv.so.2', - 'librt.so.1', - 'libthread_db.so.1', - 'libutil.so.1']] -libs += [os.path.join(options.libc_archive_path, name) for name in - ['libc_nonshared.a', - 'libpthread_nonshared.a']] - -libs.append(os.path.join(options.libgcc_dso_path, 'libgcc_s.so.1')) -libs.append(os.path.join(options.libgcc_archive_path, 'libgcc.a')) - -if options.with_libstdcxx: - libs.append(os.path.join(options.libstdcxx_dso_path, 'libstdc++.so.6')) - -functions = [] -for l in libs: - if os.path.exists(l): - functions += defined_function_list(l) - else: - print >> sys.stderr, 'warning: library %s not found' % l - -functions = list(set(functions)) -functions.sort() - -for f in functions: - print 'fun:%s=uninstrumented' % f diff --git a/lib/dfsan/scripts/check_custom_wrappers.sh b/lib/dfsan/scripts/check_custom_wrappers.sh deleted file mode 100755 index 9a80cb9c6ffd6..0000000000000 --- a/lib/dfsan/scripts/check_custom_wrappers.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh - -DFSAN_DIR=$(dirname "$0")/../ -DFSAN_CUSTOM_TESTS=${DFSAN_DIR}/../../test/dfsan/custom.cc -DFSAN_CUSTOM_WRAPPERS=${DFSAN_DIR}/dfsan_custom.cc -DFSAN_ABI_LIST=${DFSAN_DIR}/done_abilist.txt - -DIFFOUT=$(mktemp -q /tmp/tmp.XXXXXXXXXX) -ERRORLOG=$(mktemp -q /tmp/tmp.XXXXXXXXXX) -DIFF_A=$(mktemp -q /tmp/tmp.XXXXXXXXXX) -DIFF_B=$(mktemp -q /tmp/tmp.XXXXXXXXXX) - -on_exit() { - rm -f ${DIFFOUT} 2> /dev/null - rm -f ${ERRORLOG} 2> /dev/null - rm -f ${DIFF_A} 2> /dev/null - rm -f ${DIFF_B} 2> /dev/null -} - -# Ignore __sanitizer_cov_trace* because they are implemented elsewhere. -trap on_exit EXIT -grep -E "^fun:.*=custom" ${DFSAN_ABI_LIST} \ - | grep -v "dfsan_get_label\|__sanitizer_cov_trace" \ - | sed "s/^fun:\(.*\)=custom.*/\1/" | sort > $DIFF_A -grep -E "__dfsw.*\(" ${DFSAN_CUSTOM_WRAPPERS} \ - | grep -v "__sanitizer_cov_trace" \ - | sed "s/.*__dfsw_\(.*\)(.*/\1/" | sort > $DIFF_B -diff -u $DIFF_A $DIFF_B > ${DIFFOUT} -if [ $? -ne 0 ] -then - echo -n "The following differences between the ABI list and ">> ${ERRORLOG} - echo "the implemented custom wrappers have been found:" >> ${ERRORLOG} - cat ${DIFFOUT} >> ${ERRORLOG} -fi - -grep -E __dfsw_ ${DFSAN_CUSTOM_WRAPPERS} \ - | grep -v "__sanitizer_cov_trace" \ - | sed "s/.*__dfsw_\([^(]*\).*/\1/" | sort > $DIFF_A -grep -E "^[[:space:]]*test_.*\(\);" ${DFSAN_CUSTOM_TESTS} \ - | sed "s/.*test_\(.*\)();/\1/" | sort > $DIFF_B -diff -u $DIFF_A $DIFF_B > ${DIFFOUT} -if [ $? -ne 0 ] -then - echo -n "The following differences between the implemented " >> ${ERRORLOG} - echo "custom wrappers and the tests have been found:" >> ${ERRORLOG} - cat ${DIFFOUT} >> ${ERRORLOG} -fi - -if [ -s ${ERRORLOG} ] -then - cat ${ERRORLOG} - exit 1 -fi - diff --git a/lib/esan/CMakeLists.txt b/lib/esan/CMakeLists.txt deleted file mode 100644 index c880971e3dd97..0000000000000 --- a/lib/esan/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -# Build for the EfficiencySanitizer runtime support library. - -add_compiler_rt_component(esan) - -set(ESAN_RTL_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF ESAN_RTL_CFLAGS) - -include_directories(..) - -set(ESAN_SOURCES - esan.cpp - esan_flags.cpp - esan_interface.cpp - esan_interceptors.cpp - esan_linux.cpp - esan_sideline_linux.cpp - esan_sideline_bsd.cpp - cache_frag.cpp - working_set.cpp - working_set_posix.cpp) - -set(ESAN_HEADERS - cache_frag.h - esan.h - esan_circular_buffer.h - esan_flags.h - esan_flags.inc - esan_hashtable.h - esan_interface_internal.h - esan_shadow.h - esan_sideline.h - working_set.h) - -foreach (arch ${ESAN_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.esan - STATIC - ARCHS ${arch} - SOURCES ${ESAN_SOURCES} - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> - ADDITIONAL_HEADERS ${ESAN_HEADERS} - CFLAGS ${ESAN_RTL_CFLAGS}) - add_sanitizer_rt_symbols(clang_rt.esan - ARCHS ${arch} - EXTRA esan.syms.extra) - add_dependencies(esan - clang_rt.esan-${arch} - clang_rt.esan-${arch}-symbols) -endforeach() - -if (COMPILER_RT_INCLUDE_TESTS) - # TODO(bruening): add tests via add_subdirectory(tests) -endif() diff --git a/lib/fuzzer/CMakeLists.txt b/lib/fuzzer/CMakeLists.txt deleted file mode 100644 index caea9734fe532..0000000000000 --- a/lib/fuzzer/CMakeLists.txt +++ /dev/null @@ -1,147 +0,0 @@ -set(LIBFUZZER_SOURCES - FuzzerCrossOver.cpp - FuzzerDataFlowTrace.cpp - FuzzerDriver.cpp - FuzzerExtFunctionsDlsym.cpp - FuzzerExtFunctionsWeak.cpp - FuzzerExtFunctionsWindows.cpp - FuzzerExtraCounters.cpp - FuzzerIO.cpp - FuzzerIOPosix.cpp - FuzzerIOWindows.cpp - FuzzerLoop.cpp - FuzzerMerge.cpp - FuzzerMutate.cpp - FuzzerSHA1.cpp - FuzzerShmemFuchsia.cpp - FuzzerShmemPosix.cpp - FuzzerShmemWindows.cpp - FuzzerTracePC.cpp - FuzzerUtil.cpp - FuzzerUtilDarwin.cpp - FuzzerUtilFuchsia.cpp - FuzzerUtilLinux.cpp - FuzzerUtilPosix.cpp - FuzzerUtilWindows.cpp) - -set(LIBFUZZER_HEADERS - FuzzerBuiltins.h - FuzzerBuiltinsMsvc.h - FuzzerCommand.h - FuzzerCorpus.h - FuzzerDataFlowTrace.h - FuzzerDefs.h - FuzzerDictionary.h - FuzzerExtFunctions.def - FuzzerExtFunctions.h - FuzzerFlags.def - FuzzerIO.h - FuzzerInterface.h - FuzzerInternal.h - FuzzerMerge.h - FuzzerMutate.h - FuzzerOptions.h - FuzzerRandom.h - FuzzerSHA1.h - FuzzerShmem.h - FuzzerTracePC.h - FuzzerUtil.h - FuzzerValueBitMap.h) - -CHECK_CXX_SOURCE_COMPILES(" - static thread_local int blah; - int main() { - return 0; - } - " HAS_THREAD_LOCAL) - -set(LIBFUZZER_CFLAGS ${SANITIZER_COMMON_CFLAGS}) - -if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH) - list(APPEND LIBFUZZER_CFLAGS -nostdinc++ -D_LIBCPP_ABI_VERSION=Fuzzer) - # Remove -stdlib= which is unused when passing -nostdinc++. - string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) -elseif(TARGET cxx-headers OR HAVE_LIBCXX) - set(LIBFUZZER_DEPS cxx-headers) -endif() - -append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer LIBFUZZER_CFLAGS) - -if (CMAKE_CXX_FLAGS MATCHES "fsanitize-coverage") - list(APPEND LIBFUZZER_CFLAGS -fno-sanitize-coverage=trace-pc-guard,edge,trace-cmp,indirect-calls,8bit-counters) -endif() - -if(NOT HAS_THREAD_LOCAL) - list(APPEND LIBFUZZER_CFLAGS -Dthread_local=__thread) -endif() - -set(FUZZER_SUPPORTED_OS ${SANITIZER_COMMON_SUPPORTED_OS}) - -add_compiler_rt_object_libraries(RTfuzzer - OS ${FUZZER_SUPPORTED_OS} - ARCHS ${FUZZER_SUPPORTED_ARCH} - SOURCES ${LIBFUZZER_SOURCES} - ADDITIONAL_HEADERS ${LIBFUZZER_HEADERS} - CFLAGS ${LIBFUZZER_CFLAGS} - DEPS ${LIBFUZZER_DEPS}) - -add_compiler_rt_object_libraries(RTfuzzer_main - OS ${FUZZER_SUPPORTED_OS} - ARCHS ${FUZZER_SUPPORTED_ARCH} - SOURCES FuzzerMain.cpp - CFLAGS ${LIBFUZZER_CFLAGS} - DEPS ${LIBFUZZER_DEPS}) - -add_compiler_rt_runtime(clang_rt.fuzzer - STATIC - OS ${FUZZER_SUPPORTED_OS} - ARCHS ${FUZZER_SUPPORTED_ARCH} - OBJECT_LIBS RTfuzzer RTfuzzer_main - CFLAGS ${LIBFUZZER_CFLAGS} - PARENT_TARGET fuzzer) - -add_compiler_rt_runtime(clang_rt.fuzzer_no_main - STATIC - OS ${FUZZER_SUPPORTED_OS} - ARCHS ${FUZZER_SUPPORTED_ARCH} - OBJECT_LIBS RTfuzzer - CFLAGS ${LIBFUZZER_CFLAGS} - PARENT_TARGET fuzzer) - -if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH) - macro(partially_link_libcxx name dir arch) - set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") - file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) - add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD - COMMAND ${CMAKE_LINKER} --whole-archive "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o - COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o - COMMAND ${CMAKE_COMMAND} -E remove "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" - COMMAND ${CMAKE_AR} qcs "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" ${name}.o - WORKING_DIRECTORY ${cxx_${arch}_merge_dir} - ) - endmacro() - - foreach(arch ${FUZZER_SUPPORTED_ARCH}) - get_target_flags_for_arch(${arch} TARGET_CFLAGS) - set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch}) - add_custom_libcxx(libcxx_fuzzer_${arch} ${LIBCXX_${arch}_PREFIX} - CFLAGS ${TARGET_CFLAGS} - -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS=1 - -fvisibility=hidden - CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON - -DLIBCXX_ENABLE_EXCEPTIONS=OFF - -DLIBCXX_ENABLE_SHARED=OFF - -DLIBCXX_ABI_NAMESPACE=Fuzzer - -DLIBCXX_CXX_ABI=none) - target_compile_options(RTfuzzer.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) - add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-build) - target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) - add_dependencies(RTfuzzer_main.${arch} libcxx_fuzzer_${arch}-build) - partially_link_libcxx(fuzzer_no_main ${LIBCXX_${arch}_PREFIX} ${arch}) - partially_link_libcxx(fuzzer ${LIBCXX_${arch}_PREFIX} ${arch}) - endforeach() -endif() - -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/lib/fuzzer/afl/afl_driver.cpp b/lib/fuzzer/afl/afl_driver.cpp deleted file mode 100644 index 5a10c0d27f3ac..0000000000000 --- a/lib/fuzzer/afl/afl_driver.cpp +++ /dev/null @@ -1,378 +0,0 @@ -//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===// - -/* This file allows to fuzz libFuzzer-style target functions - (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode. - -Usage: -################################################################################ -cat << EOF > test_fuzzer.cc -#include <stddef.h> -#include <stdint.h> -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (size > 0 && data[0] == 'H') - if (size > 1 && data[1] == 'I') - if (size > 2 && data[2] == '!') - __builtin_trap(); - return 0; -} -EOF -# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. -clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c -# Build afl-llvm-rt.o.c from the AFL distribution. -clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c -# Build this file, link it with afl-llvm-rt.o.o and the target code. -clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o -# Run AFL: -rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; -$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out -################################################################################ -Environment Variables: -There are a few environment variables that can be set to use features that -afl-fuzz doesn't have. - -AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file -specified. If the file does not exist, it is created. This is useful for getting -stack traces (when using ASAN for example) or original error messages on hard to -reproduce bugs. - -AFL_DRIVER_EXTRA_STATS_FILENAME: Setting this causes afl_driver to write extra -statistics to the file specified. Currently these are peak_rss_mb -(the peak amount of virtual memory used in MB) and slowest_unit_time_secs. If -the file does not exist it is created. If the file does exist then -afl_driver assumes it was restarted by afl-fuzz and will try to read old -statistics from the file. If that fails then the process will quit. - -*/ -#include <assert.h> -#include <errno.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/resource.h> -#include <sys/time.h> -#include <unistd.h> - -#include <fstream> -#include <iostream> -#include <vector> - -// Platform detection. Copied from FuzzerInternal.h -#ifdef __linux__ -#define LIBFUZZER_LINUX 1 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __APPLE__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 1 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __NetBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 1 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __FreeBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 1 -#define LIBFUZZER_OPENBSD 0 -#elif __OpenBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 1 -#else -#error "Support for your platform has not been implemented" -#endif - -// Used to avoid repeating error checking boilerplate. If cond is false, a -// fatal error has occurred in the program. In this event print error_message -// to stderr and abort(). Otherwise do nothing. Note that setting -// AFL_DRIVER_STDERR_DUPLICATE_FILENAME may cause error_message to be appended -// to the file as well, if the error occurs after the duplication is performed. -#define CHECK_ERROR(cond, error_message) \ - if (!(cond)) { \ - fprintf(stderr, "%s\n", (error_message)); \ - abort(); \ - } - -// libFuzzer interface is thin, so we don't include any libFuzzer headers. -extern "C" { -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); -__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); -} - -// Notify AFL about persistent mode. -static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; -extern "C" int __afl_persistent_loop(unsigned int); -static volatile char suppress_warning2 = AFL_PERSISTENT[0]; - -// Notify AFL about deferred forkserver. -static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; -extern "C" void __afl_manual_init(); -static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0]; - -// Input buffer. -static const size_t kMaxAflInputSize = 1 << 20; -static uint8_t AflInputBuf[kMaxAflInputSize]; - -// Variables we need for writing to the extra stats file. -static FILE *extra_stats_file = NULL; -static uint32_t previous_peak_rss = 0; -static time_t slowest_unit_time_secs = 0; -static const int kNumExtraStats = 2; -static const char *kExtraStatsFormatString = "peak_rss_mb : %u\n" - "slowest_unit_time_sec : %u\n"; - -// Experimental feature to use afl_driver without AFL's deferred mode. -// Needs to run before __afl_auto_init. -__attribute__((constructor(0))) void __decide_deferred_forkserver(void) { - if (getenv("AFL_DRIVER_DONT_DEFER")) { - if (unsetenv("__AFL_DEFER_FORKSRV")) { - perror("Failed to unset __AFL_DEFER_FORKSRV"); - abort(); - } - } -} - -// Copied from FuzzerUtil.cpp. -size_t GetPeakRSSMb() { - struct rusage usage; - if (getrusage(RUSAGE_SELF, &usage)) - return 0; - if (LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || - LIBFUZZER_OPENBSD) { - // ru_maxrss is in KiB - return usage.ru_maxrss >> 10; - } else if (LIBFUZZER_APPLE) { - // ru_maxrss is in bytes - return usage.ru_maxrss >> 20; - } - assert(0 && "GetPeakRSSMb() is not implemented for your platform"); - return 0; -} - -// Based on SetSigaction in FuzzerUtil.cpp -static void SetSigaction(int signum, - void (*callback)(int, siginfo_t *, void *)) { - struct sigaction sigact; - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_sigaction = callback; - if (sigaction(signum, &sigact, 0)) { - fprintf(stderr, "libFuzzer: sigaction failed with %d\n", errno); - exit(1); - } -} - -// Write extra stats to the file specified by the user. If none is specified -// this function will never be called. -static void write_extra_stats() { - uint32_t peak_rss = GetPeakRSSMb(); - - if (peak_rss < previous_peak_rss) - peak_rss = previous_peak_rss; - - int chars_printed = fprintf(extra_stats_file, kExtraStatsFormatString, - peak_rss, slowest_unit_time_secs); - - CHECK_ERROR(chars_printed != 0, "Failed to write extra_stats_file"); - - CHECK_ERROR(fclose(extra_stats_file) == 0, - "Failed to close extra_stats_file"); -} - -// Call write_extra_stats before we exit. -static void crash_handler(int, siginfo_t *, void *) { - // Make sure we don't try calling write_extra_stats again if we crashed while - // trying to call it. - static bool first_crash = true; - CHECK_ERROR(first_crash, - "Crashed in crash signal handler. This is a bug in the fuzzer."); - - first_crash = false; - write_extra_stats(); -} - -// If the user has specified an extra_stats_file through the environment -// variable AFL_DRIVER_EXTRA_STATS_FILENAME, then perform necessary set up -// to write stats to it on exit. If no file is specified, do nothing. Otherwise -// install signal and exit handlers to write to the file when the process exits. -// Then if the file doesn't exist create it and set extra stats to 0. But if it -// does exist then read the initial values of the extra stats from the file -// and check that the file is writable. -static void maybe_initialize_extra_stats() { - // If AFL_DRIVER_EXTRA_STATS_FILENAME isn't set then we have nothing to do. - char *extra_stats_filename = getenv("AFL_DRIVER_EXTRA_STATS_FILENAME"); - if (!extra_stats_filename) - return; - - // Open the file and find the previous peak_rss_mb value. - // This is necessary because the fuzzing process is restarted after N - // iterations are completed. So we may need to get this value from a previous - // process to be accurate. - extra_stats_file = fopen(extra_stats_filename, "r"); - - // If extra_stats_file already exists: read old stats from it. - if (extra_stats_file) { - int matches = fscanf(extra_stats_file, kExtraStatsFormatString, - &previous_peak_rss, &slowest_unit_time_secs); - - // Make sure we have read a real extra stats file and that we have used it - // to set slowest_unit_time_secs and previous_peak_rss. - CHECK_ERROR(matches == kNumExtraStats, "Extra stats file is corrupt"); - - CHECK_ERROR(fclose(extra_stats_file) == 0, "Failed to close file"); - - // Now open the file for writing. - extra_stats_file = fopen(extra_stats_filename, "w"); - CHECK_ERROR(extra_stats_file, - "Failed to open extra stats file for writing"); - } else { - // Looks like this is the first time in a fuzzing job this is being called. - extra_stats_file = fopen(extra_stats_filename, "w+"); - CHECK_ERROR(extra_stats_file, "failed to create extra stats file"); - } - - // Make sure that crash_handler gets called on any kind of fatal error. - int crash_signals[] = {SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGFPE, SIGINT, - SIGTERM}; - - const size_t num_signals = sizeof(crash_signals) / sizeof(crash_signals[0]); - - for (size_t idx = 0; idx < num_signals; idx++) - SetSigaction(crash_signals[idx], crash_handler); - - // Make sure it gets called on other kinds of exits. - atexit(write_extra_stats); -} - -// If the user asks us to duplicate stderr, then do it. -static void maybe_duplicate_stderr() { - char* stderr_duplicate_filename = - getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - - if (!stderr_duplicate_filename) - return; - - FILE* stderr_duplicate_stream = - freopen(stderr_duplicate_filename, "a+", stderr); - - if (!stderr_duplicate_stream) { - fprintf( - stderr, - "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - abort(); - } -} - -// Define LLVMFuzzerMutate to avoid link failures for targets that use it -// with libFuzzer's LLVMFuzzerCustomMutator. -extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); - return 0; -} - -// Execute any files provided as parameters. -int ExecuteFilesOnyByOne(int argc, char **argv) { - for (int i = 1; i < argc; i++) { - std::ifstream in(argv[i], std::ios::binary); - in.seekg(0, in.end); - size_t length = in.tellg(); - in.seekg (0, in.beg); - std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl; - // Allocate exactly length bytes so that we reliably catch buffer overflows. - std::vector<char> bytes(length); - in.read(bytes.data(), bytes.size()); - assert(in); - LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t *>(bytes.data()), - bytes.size()); - std::cout << "Execution successful" << std::endl; - } - return 0; -} - -int main(int argc, char **argv) { - fprintf(stderr, - "======================= INFO =========================\n" - "This binary is built for AFL-fuzz.\n" - "To run the target function on individual input(s) execute this:\n" - " %s < INPUT_FILE\n" - "or\n" - " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n" - "To fuzz with afl-fuzz execute this:\n" - " afl-fuzz [afl-flags] %s [-N]\n" - "afl-fuzz will run N iterations before " - "re-spawning the process (default: 1000)\n" - "======================================================\n", - argv[0], argv[0], argv[0]); - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); - // Do any other expensive one-time initialization here. - - maybe_duplicate_stderr(); - maybe_initialize_extra_stats(); - - if (!getenv("AFL_DRIVER_DONT_DEFER")) - __afl_manual_init(); - - int N = 1000; - if (argc == 2 && argv[1][0] == '-') - N = atoi(argv[1] + 1); - else if(argc == 2 && (N = atoi(argv[1])) > 0) - fprintf(stderr, "WARNING: using the deprecated call style `%s %d`\n", - argv[0], N); - else if (argc > 1) - return ExecuteFilesOnyByOne(argc, argv); - - assert(N > 0); - - // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization - // on the first execution of LLVMFuzzerTestOneInput is ignored. - uint8_t dummy_input[1] = {0}; - LLVMFuzzerTestOneInput(dummy_input, 1); - - time_t unit_time_secs; - int num_runs = 0; - while (__afl_persistent_loop(N)) { - ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize); - if (n_read > 0) { - // Copy AflInputBuf into a separate buffer to let asan find buffer - // overflows. Don't use unique_ptr/etc to avoid extra dependencies. - uint8_t *copy = new uint8_t[n_read]; - memcpy(copy, AflInputBuf, n_read); - - struct timeval unit_start_time; - CHECK_ERROR(gettimeofday(&unit_start_time, NULL) == 0, - "Calling gettimeofday failed"); - - num_runs++; - LLVMFuzzerTestOneInput(copy, n_read); - - struct timeval unit_stop_time; - CHECK_ERROR(gettimeofday(&unit_stop_time, NULL) == 0, - "Calling gettimeofday failed"); - - // Update slowest_unit_time_secs if we see a new max. - unit_time_secs = unit_stop_time.tv_sec - unit_start_time.tv_sec; - if (slowest_unit_time_secs < unit_time_secs) - slowest_unit_time_secs = unit_time_secs; - - delete[] copy; - } - } - fprintf(stderr, "%s: successfully executed %d input(s)\n", argv[0], num_runs); -} diff --git a/lib/fuzzer/build.sh b/lib/fuzzer/build.sh deleted file mode 100755 index 504e54e3a819e..0000000000000 --- a/lib/fuzzer/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -LIBFUZZER_SRC_DIR=$(dirname $0) -CXX="${CXX:-clang}" -for f in $LIBFUZZER_SRC_DIR/*.cpp; do - $CXX -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c & -done -wait -rm -f libFuzzer.a -ar ru libFuzzer.a Fuzzer*.o -rm -f Fuzzer*.o - diff --git a/lib/fuzzer/dataflow/DataFlow.cpp b/lib/fuzzer/dataflow/DataFlow.cpp deleted file mode 100644 index a79c796ac456c..0000000000000 --- a/lib/fuzzer/dataflow/DataFlow.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/*===- DataFlow.cpp - a standalone DataFlow tracer -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// An experimental data-flow tracer for fuzz targets. -// It is based on DFSan and SanitizerCoverage. -// https://clang.llvm.org/docs/DataFlowSanitizer.html -// https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow -// -// It executes the fuzz target on the given input while monitoring the -// data flow for every instrumented comparison instruction. -// -// The output shows which functions depend on which bytes of the input. -// -// Build: -// 1. Compile this file with -fsanitize=dataflow -// 2. Build the fuzz target with -g -fsanitize=dataflow -// -fsanitize-coverage=trace-pc-guard,pc-table,func,trace-cmp -// 3. Link those together with -fsanitize=dataflow -// -// -fsanitize-coverage=trace-cmp inserts callbacks around every comparison -// instruction, DFSan modifies the calls to pass the data flow labels. -// The callbacks update the data flow label for the current function. -// See e.g. __dfsw___sanitizer_cov_trace_cmp1 below. -// -// -fsanitize-coverage=trace-pc-guard,pc-table,func instruments function -// entries so that the comparison callback knows that current function. -// -// -// Run: -// # Collect data flow for INPUT_FILE, write to OUTPUT_FILE (default: stdout) -// ./a.out INPUT_FILE [OUTPUT_FILE] -// -// # Print all instrumented functions. llvm-symbolizer must be present in PATH -// ./a.out -// -// Example output: -// =============== -// F0 11111111111111 -// F1 10000000000000 -// =============== -// "FN xxxxxxxxxx": tells what bytes of the input does the function N depend on. -// The byte string is LEN+1 bytes. The last byte is set if the function -// depends on the input length. -//===----------------------------------------------------------------------===*/ - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> - -#include <execinfo.h> // backtrace_symbols_fd - -#include <sanitizer/dfsan_interface.h> - -extern "C" { -extern int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size); -__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); -} // extern "C" - -static size_t InputLen; -static size_t NumFuncs; -static const uintptr_t *FuncsBeg; -static __thread size_t CurrentFunc; -static dfsan_label *FuncLabels; // Array of NumFuncs elements. -static char *PrintableStringForLabel; // InputLen + 2 bytes. -static bool LabelSeen[1 << 8 * sizeof(dfsan_label)]; - -// Prints all instrumented functions. -static int PrintFunctions() { - // We don't have the symbolizer integrated with dfsan yet. - // So use backtrace_symbols_fd and pipe it through llvm-symbolizer. - // TODO(kcc): this is pretty ugly and may break in lots of ways. - // We'll need to make a proper in-process symbolizer work with DFSan. - FILE *Pipe = popen("sed 's/(+/ /g; s/).*//g' " - "| llvm-symbolizer " - "| grep 'dfs\\$' " - "| sed 's/dfs\\$//g'", "w"); - for (size_t I = 0; I < NumFuncs; I++) { - uintptr_t PC = FuncsBeg[I * 2]; - void *const Buf[1] = {(void*)PC}; - backtrace_symbols_fd(Buf, 1, fileno(Pipe)); - } - pclose(Pipe); - return 0; -} - -extern "C" -void SetBytesForLabel(dfsan_label L, char *Bytes) { - if (LabelSeen[L]) - return; - LabelSeen[L] = true; - assert(L); - if (L <= InputLen + 1) { - Bytes[L - 1] = '1'; - } else { - auto *DLI = dfsan_get_label_info(L); - SetBytesForLabel(DLI->l1, Bytes); - SetBytesForLabel(DLI->l2, Bytes); - } -} - -static char *GetPrintableStringForLabel(dfsan_label L) { - memset(PrintableStringForLabel, '0', InputLen + 1); - PrintableStringForLabel[InputLen + 1] = 0; - memset(LabelSeen, 0, sizeof(LabelSeen)); - SetBytesForLabel(L, PrintableStringForLabel); - return PrintableStringForLabel; -} - -static void PrintDataFlow(FILE *Out) { - for (size_t I = 0; I < NumFuncs; I++) - if (FuncLabels[I]) - fprintf(Out, "F%zd %s\n", I, GetPrintableStringForLabel(FuncLabels[I])); -} - -int main(int argc, char **argv) { - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); - if (argc == 1) - return PrintFunctions(); - assert(argc == 4 || argc == 5); - size_t Beg = atoi(argv[1]); - size_t End = atoi(argv[2]); - assert(Beg < End); - - const char *Input = argv[3]; - fprintf(stderr, "INFO: reading '%s'\n", Input); - FILE *In = fopen(Input, "r"); - assert(In); - fseek(In, 0, SEEK_END); - InputLen = ftell(In); - fseek(In, 0, SEEK_SET); - unsigned char *Buf = (unsigned char*)malloc(InputLen); - size_t NumBytesRead = fread(Buf, 1, InputLen, In); - assert(NumBytesRead == InputLen); - PrintableStringForLabel = (char*)malloc(InputLen + 2); - fclose(In); - - fprintf(stderr, "INFO: running '%s'\n", Input); - for (size_t I = 1; I <= InputLen; I++) { - dfsan_label L = dfsan_create_label("", nullptr); - assert(L == I); - size_t Idx = I - 1; - if (Idx >= Beg && Idx < End) - dfsan_set_label(L, Buf + Idx, 1); - } - dfsan_label SizeL = dfsan_create_label("", nullptr); - assert(SizeL == InputLen + 1); - dfsan_set_label(SizeL, &InputLen, sizeof(InputLen)); - - LLVMFuzzerTestOneInput(Buf, InputLen); - free(Buf); - - bool OutIsStdout = argc == 4; - fprintf(stderr, "INFO: writing dataflow to %s\n", - OutIsStdout ? "<stdout>" : argv[4]); - FILE *Out = OutIsStdout ? stdout : fopen(argv[4], "w"); - PrintDataFlow(Out); - if (!OutIsStdout) fclose(Out); -} - -extern "C" { - -void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, - uint32_t *stop) { - assert(NumFuncs == 0 && "This tool does not support DSOs"); - assert(start < stop && "The code is not instrumented for coverage"); - if (start == stop || *start) return; // Initialize only once. - for (uint32_t *x = start; x < stop; x++) - *x = ++NumFuncs; // The first index is 1. - FuncLabels = (dfsan_label*)calloc(NumFuncs, sizeof(dfsan_label)); - fprintf(stderr, "INFO: %zd instrumented function(s) observed\n", NumFuncs); -} - -void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, - const uintptr_t *pcs_end) { - assert(NumFuncs == (pcs_end - pcs_beg) / 2); - FuncsBeg = pcs_beg; -} - -void __sanitizer_cov_trace_pc_indir(uint64_t x){} // unused. - -void __sanitizer_cov_trace_pc_guard(uint32_t *guard){ - uint32_t FuncNum = *guard - 1; // Guards start from 1. - assert(FuncNum < NumFuncs); - CurrentFunc = FuncNum; -} - -void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases, - dfsan_label L1, dfsan_label UnusedL) { - assert(CurrentFunc < NumFuncs); - FuncLabels[CurrentFunc] = dfsan_union(FuncLabels[CurrentFunc], L1); -} - -#define HOOK(Name, Type) \ - void Name(Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) { \ - assert(CurrentFunc < NumFuncs); \ - FuncLabels[CurrentFunc] = \ - dfsan_union(FuncLabels[CurrentFunc], dfsan_union(L1, L2)); \ - } - -HOOK(__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t) -HOOK(__dfsw___sanitizer_cov_trace_const_cmp2, uint16_t) -HOOK(__dfsw___sanitizer_cov_trace_const_cmp4, uint32_t) -HOOK(__dfsw___sanitizer_cov_trace_const_cmp8, uint64_t) -HOOK(__dfsw___sanitizer_cov_trace_cmp1, uint8_t) -HOOK(__dfsw___sanitizer_cov_trace_cmp2, uint16_t) -HOOK(__dfsw___sanitizer_cov_trace_cmp4, uint32_t) -HOOK(__dfsw___sanitizer_cov_trace_cmp8, uint64_t) - -} // extern "C" diff --git a/lib/fuzzer/scripts/collect_data_flow.py b/lib/fuzzer/scripts/collect_data_flow.py deleted file mode 100755 index 3edff66bb9d16..0000000000000 --- a/lib/fuzzer/scripts/collect_data_flow.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -#===- lib/fuzzer/scripts/collect_data_flow.py ------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# Runs the data-flow tracer several times on the same input in order to collect -# the complete trace for all input bytes (running it on all bytes at once -# may fail if DFSan runs out of labels). -# Usage: -# -# # Collect dataflow for one input, store it in OUTPUT (default is stdout) -# collect_data_flow.py BINARY INPUT [OUTPUT] -# -# # Collect dataflow for all inputs in CORPUS_DIR, store them in OUTPUT_DIR -# collect_data_flow.py BINARY CORPUS_DIR OUTPUT_DIR -#===------------------------------------------------------------------------===# -import atexit -import hashlib -import sys -import os -import subprocess -import tempfile -import shutil - -tmpdir = "" - -def cleanup(d): - print("removing: %s" % d) - shutil.rmtree(d) - -def collect_dataflow_for_corpus(self, exe, corpus_dir, output_dir): - print("Collecting dataflow for corpus: %s output_dir: %s" % (corpus_dir, - output_dir)) - assert not os.path.exists(output_dir) - os.mkdir(output_dir) - for root, dirs, files in os.walk(corpus_dir): - for f in files: - path = os.path.join(root, f) - sha1 = hashlib.sha1(open(path).read()).hexdigest() - output = os.path.join(output_dir, sha1) - subprocess.call([self, exe, path, output]) - functions_txt = open(os.path.join(output_dir, "functions.txt"), "w") - subprocess.call([exe], stdout=functions_txt) - - -def main(argv): - exe = argv[1] - inp = argv[2] - if os.path.isdir(inp): - return collect_dataflow_for_corpus(argv[0], exe, inp, argv[3]) - size = os.path.getsize(inp) - q = [[0, size]] - tmpdir = tempfile.mkdtemp(prefix="libfuzzer-tmp-") - atexit.register(cleanup, tmpdir) - print "tmpdir: ", tmpdir - outputs = [] - while len(q): - r = q.pop() - print "******* Trying: ", r - tmpfile = os.path.join(tmpdir, str(r[0]) + "-" + str(r[1])) - ret = subprocess.call([exe, str(r[0]), str(r[1]), inp, tmpfile]) - if ret and r[1] - r[0] >= 2: - q.append([r[0], (r[1] + r[0]) / 2]) - q.append([(r[1] + r[0]) / 2, r[1]]) - else: - outputs.append(tmpfile) - print "******* Success: ", r - f = sys.stdout - if len(argv) >= 4: - f = open(argv[3], "w") - merge = os.path.join(os.path.dirname(argv[0]), "merge_data_flow.py") - subprocess.call([merge] + outputs, stdout=f) - -if __name__ == '__main__': - main(sys.argv) diff --git a/lib/fuzzer/scripts/merge_data_flow.py b/lib/fuzzer/scripts/merge_data_flow.py deleted file mode 100755 index d2f5081e7b8cc..0000000000000 --- a/lib/fuzzer/scripts/merge_data_flow.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -#===- lib/fuzzer/scripts/merge_data_flow.py ------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# Merge several data flow traces into one. -# Usage: -# merge_data_flow.py trace1 trace2 ... > result -#===------------------------------------------------------------------------===# -import sys -import fileinput -from array import array - -def Merge(a, b): - res = array('b') - for i in range(0, len(a)): - res.append(ord('1' if a[i] == '1' or b[i] == '1' else '0')) - return res.tostring() - -def main(argv): - D = {} - for line in fileinput.input(): - [F,BV] = line.strip().split(' ') - if F in D: - D[F] = Merge(D[F], BV) - else: - D[F] = BV; - for F in D.keys(): - print("%s %s" % (F, D[F])) - -if __name__ == '__main__': - main(sys.argv) diff --git a/lib/fuzzer/scripts/unbalanced_allocs.py b/lib/fuzzer/scripts/unbalanced_allocs.py deleted file mode 100755 index 74478ad55af0c..0000000000000 --- a/lib/fuzzer/scripts/unbalanced_allocs.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -#===- lib/fuzzer/scripts/unbalanced_allocs.py ------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# -# Post-process -trace_malloc=2 output and printout only allocations and frees -# unbalanced inside of fuzzer runs. -# Usage: -# my_fuzzer -trace_malloc=2 -runs=10 2>&1 | unbalanced_allocs.py -skip=5 -# -#===------------------------------------------------------------------------===# - -import argparse -import sys - -_skip = 0 - -def PrintStack(line, stack): - global _skip - if _skip > 0: - return - print('Unbalanced ' + line.rstrip()); - for l in stack: - print(l.rstrip()) - -def ProcessStack(line, f): - stack = [] - while line and line.startswith(' #'): - stack += [line] - line = f.readline() - return line, stack - -def ProcessFree(line, f, allocs): - if not line.startswith('FREE['): - return f.readline() - - addr = int(line.split()[1], 16) - next_line, stack = ProcessStack(f.readline(), f) - if addr in allocs: - del allocs[addr] - else: - PrintStack(line, stack) - return next_line - -def ProcessMalloc(line, f, allocs): - if not line.startswith('MALLOC['): - return ProcessFree(line, f, allocs) - - addr = int(line.split()[1], 16) - assert not addr in allocs - - next_line, stack = ProcessStack(f.readline(), f) - allocs[addr] = (line, stack) - return next_line - -def ProcessRun(line, f): - if not line.startswith('MallocFreeTracer: START'): - return ProcessMalloc(line, f, {}) - - allocs = {} - print(line.rstrip()) - line = f.readline() - while line: - if line.startswith('MallocFreeTracer: STOP'): - global _skip - _skip = _skip - 1 - for _, (l, s) in allocs.items(): - PrintStack(l, s) - print(line.rstrip()) - return f.readline() - line = ProcessMalloc(line, f, allocs) - return line - -def ProcessFile(f): - line = f.readline() - while line: - line = ProcessRun(line, f); - -def main(argv): - parser = argparse.ArgumentParser() - parser.add_argument('--skip', default=0, help='number of runs to ignore') - args = parser.parse_args() - global _skip - _skip = int(args.skip) + 1 - ProcessFile(sys.stdin) - -if __name__ == '__main__': - main(sys.argv) diff --git a/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c b/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c deleted file mode 100644 index 0d76ea49e7964..0000000000000 --- a/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c +++ /dev/null @@ -1,41 +0,0 @@ -/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// This main() function can be linked to a fuzz target (i.e. a library -// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize()) -// instead of libFuzzer. This main() function will not perform any fuzzing -// but will simply feed all input files one by one to the fuzz target. -// -// Use this file to provide reproducers for bugs when linking against libFuzzer -// or other fuzzing engine is undesirable. -//===----------------------------------------------------------------------===*/ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> - -extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); -__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); -int main(int argc, char **argv) { - fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); - for (int i = 1; i < argc; i++) { - fprintf(stderr, "Running: %s\n", argv[i]); - FILE *f = fopen(argv[i], "r"); - assert(f); - fseek(f, 0, SEEK_END); - size_t len = ftell(f); - fseek(f, 0, SEEK_SET); - unsigned char *buf = (unsigned char*)malloc(len); - size_t n_read = fread(buf, 1, len, f); - assert(n_read == len); - LLVMFuzzerTestOneInput(buf, len); - free(buf); - fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); - } -} diff --git a/lib/fuzzer/tests/CMakeLists.txt b/lib/fuzzer/tests/CMakeLists.txt deleted file mode 100644 index 6abb72def3e19..0000000000000 --- a/lib/fuzzer/tests/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -include(CompilerRTCompile) - -set(LIBFUZZER_UNITTEST_CFLAGS - ${COMPILER_RT_UNITTEST_CFLAGS} - ${COMPILER_RT_GTEST_CFLAGS} - -I${COMPILER_RT_SOURCE_DIR}/lib/fuzzer - -fno-rtti - -O2) - -if (APPLE) - set(FUZZER_SUPPORTED_OS osx) -endif() - -add_custom_target(FuzzerUnitTests) -set_target_properties(FuzzerUnitTests PROPERTIES FOLDER "Compiler-RT Tests") - -set(LIBFUZZER_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_LINK_FLAGS}) -list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS --driver-mode=g++) - -if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") - list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -lc++ -lpthread) -elseif(NOT WIN32) - list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -lstdc++ -lpthread) -endif() - -if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND COMPILER_RT_LIBCXX_PATH) - list(APPEND LIBFUZZER_UNITTEST_CFLAGS -nostdinc++) -endif() - -if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) - # libFuzzer unit tests are only run on the host machine. - set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH}) - - set(LIBFUZZER_TEST_RUNTIME RTFuzzerTest.${arch}) - if(APPLE) - set(LIBFUZZER_TEST_RUNTIME_OBJECTS - $<TARGET_OBJECTS:RTfuzzer.osx>) - else() - set(LIBFUZZER_TEST_RUNTIME_OBJECTS - $<TARGET_OBJECTS:RTfuzzer.${arch}>) - endif() - add_library(${LIBFUZZER_TEST_RUNTIME} STATIC - ${LIBFUZZER_TEST_RUNTIME_OBJECTS}) - set_target_properties(${LIBFUZZER_TEST_RUNTIME} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - FOLDER "Compiler-RT Runtime tests") - - if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND COMPILER_RT_LIBCXX_PATH) - set(LIBFUZZER_TEST_RUNTIME_DEPS libcxx_fuzzer_${arch}-build) - set(LIBFUZZER_TEST_RUNTIME_CFLAGS -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) - set(LIBFUZZER_TEST_RUNTIME_LINK_FLAGS ${LIBCXX_${arch}_PREFIX}/lib/libc++.a) - endif() - - set(FuzzerTestObjects) - generate_compiler_rt_tests(FuzzerTestObjects - FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch} - SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} - RUNTIME ${LIBFUZZER_TEST_RUNTIME} - DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} - CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} - LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) - set_target_properties(FuzzerUnitTests PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -endif() diff --git a/lib/fuzzer/tests/FuzzerUnittest.cpp b/lib/fuzzer/tests/FuzzerUnittest.cpp deleted file mode 100644 index 7cdd44582329e..0000000000000 --- a/lib/fuzzer/tests/FuzzerUnittest.cpp +++ /dev/null @@ -1,964 +0,0 @@ -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. - -// Avoid ODR violations (LibFuzzer is built without ASan and this test is built -// with ASan) involving C++ standard library types when using libcxx. -#define _LIBCPP_HAS_NO_ASAN - -// Do not attempt to use LLVM ostream from gtest. -#define GTEST_NO_LLVM_RAW_OSTREAM 1 - -#include "FuzzerCorpus.h" -#include "FuzzerDictionary.h" -#include "FuzzerInternal.h" -#include "FuzzerMerge.h" -#include "FuzzerMutate.h" -#include "FuzzerRandom.h" -#include "FuzzerTracePC.h" -#include "gtest/gtest.h" -#include <memory> -#include <set> -#include <sstream> - -using namespace fuzzer; - -// For now, have LLVMFuzzerTestOneInput just to make it link. -// Later we may want to make unittests that actually call LLVMFuzzerTestOneInput. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - abort(); -} - -TEST(Fuzzer, Basename) { - EXPECT_EQ(Basename("foo/bar"), "bar"); - EXPECT_EQ(Basename("bar"), "bar"); - EXPECT_EQ(Basename("/bar"), "bar"); - EXPECT_EQ(Basename("foo/x"), "x"); - EXPECT_EQ(Basename("foo/"), ""); -#if LIBFUZZER_WINDOWS - EXPECT_EQ(Basename("foo\\bar"), "bar"); - EXPECT_EQ(Basename("foo\\bar/baz"), "baz"); - EXPECT_EQ(Basename("\\bar"), "bar"); - EXPECT_EQ(Basename("foo\\x"), "x"); - EXPECT_EQ(Basename("foo\\"), ""); -#endif -} - -TEST(Fuzzer, CrossOver) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - Unit A({0, 1, 2}), B({5, 6, 7}); - Unit C; - Unit Expected[] = { - { 0 }, - { 0, 1 }, - { 0, 5 }, - { 0, 1, 2 }, - { 0, 1, 5 }, - { 0, 5, 1 }, - { 0, 5, 6 }, - { 0, 1, 2, 5 }, - { 0, 1, 5, 2 }, - { 0, 1, 5, 6 }, - { 0, 5, 1, 2 }, - { 0, 5, 1, 6 }, - { 0, 5, 6, 1 }, - { 0, 5, 6, 7 }, - { 0, 1, 2, 5, 6 }, - { 0, 1, 5, 2, 6 }, - { 0, 1, 5, 6, 2 }, - { 0, 1, 5, 6, 7 }, - { 0, 5, 1, 2, 6 }, - { 0, 5, 1, 6, 2 }, - { 0, 5, 1, 6, 7 }, - { 0, 5, 6, 1, 2 }, - { 0, 5, 6, 1, 7 }, - { 0, 5, 6, 7, 1 }, - { 0, 1, 2, 5, 6, 7 }, - { 0, 1, 5, 2, 6, 7 }, - { 0, 1, 5, 6, 2, 7 }, - { 0, 1, 5, 6, 7, 2 }, - { 0, 5, 1, 2, 6, 7 }, - { 0, 5, 1, 6, 2, 7 }, - { 0, 5, 1, 6, 7, 2 }, - { 0, 5, 6, 1, 2, 7 }, - { 0, 5, 6, 1, 7, 2 }, - { 0, 5, 6, 7, 1, 2 } - }; - for (size_t Len = 1; Len < 8; Len++) { - Set<Unit> FoundUnits, ExpectedUnitsWitThisLength; - for (int Iter = 0; Iter < 3000; Iter++) { - C.resize(Len); - size_t NewSize = MD->CrossOver(A.data(), A.size(), B.data(), B.size(), - C.data(), C.size()); - C.resize(NewSize); - FoundUnits.insert(C); - } - for (const Unit &U : Expected) - if (U.size() <= Len) - ExpectedUnitsWitThisLength.insert(U); - EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits); - } -} - -TEST(Fuzzer, Hash) { - uint8_t A[] = {'a', 'b', 'c'}; - fuzzer::Unit U(A, A + sizeof(A)); - EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d", fuzzer::Hash(U)); - U.push_back('d'); - EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U)); -} - -typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size, - size_t MaxSize); - -void TestEraseBytes(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77}; - uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77}; - uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77}; - uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77}; - uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; - uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77}; - - uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44}; - uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77}; - - - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - int FoundMask = 0; - for (int i = 0; i < NumIter; i++) { - uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - size_t NewSize = (*MD.*M)(T, sizeof(T), sizeof(T)); - if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0; - if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1; - if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2; - if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3; - if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4; - if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5; - if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6; - if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7; - - if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8; - if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9; - if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10; - - if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11; - if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12; - if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13; - } - EXPECT_EQ(FoundMask, (1 << 14) - 1); -} - -TEST(FuzzerMutate, EraseBytes1) { - TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200); -} -TEST(FuzzerMutate, EraseBytes2) { - TestEraseBytes(&MutationDispatcher::Mutate, 2000); -} - -void TestInsertByte(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - int FoundMask = 0; - uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66}; - uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66}; - uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66}; - uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66}; - uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66}; - uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8}; - for (int i = 0; i < NumIter; i++) { - uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - size_t NewSize = (*MD.*M)(T, 7, 8); - if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0; - if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1; - if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2; - if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3; - if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4; - if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5; - if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6; - if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7; - } - EXPECT_EQ(FoundMask, 255); -} - -TEST(FuzzerMutate, InsertByte1) { - TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15); -} -TEST(FuzzerMutate, InsertByte2) { - TestInsertByte(&MutationDispatcher::Mutate, 1 << 17); -} - -void TestInsertRepeatedBytes(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - int FoundMask = 0; - uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'}; - uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33}; - uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33}; - uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33}; - uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33}; - - uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'}; - uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33}; - uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33}; - uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33}; - uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33}; - - for (int i = 0; i < NumIter; i++) { - uint8_t T[8] = {0x00, 0x11, 0x22, 0x33}; - size_t NewSize = (*MD.*M)(T, 4, 8); - if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0; - if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1; - if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2; - if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3; - if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4; - - if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5; - if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6; - if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7; - if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8; - if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9; - - } - EXPECT_EQ(FoundMask, (1 << 10) - 1); -} - -TEST(FuzzerMutate, InsertRepeatedBytes1) { - TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000); -} -TEST(FuzzerMutate, InsertRepeatedBytes2) { - TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000); -} - -void TestChangeByte(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - int FoundMask = 0; - uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77}; - uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77}; - uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77}; - uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; - for (int i = 0; i < NumIter; i++) { - uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - size_t NewSize = (*MD.*M)(T, 8, 9); - if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; - if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; - if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; - if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; - if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; - if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; - if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; - if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; - } - EXPECT_EQ(FoundMask, 255); -} - -TEST(FuzzerMutate, ChangeByte1) { - TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15); -} -TEST(FuzzerMutate, ChangeByte2) { - TestChangeByte(&MutationDispatcher::Mutate, 1 << 17); -} - -void TestChangeBit(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - int FoundMask = 0; - uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77}; - uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77}; - uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77}; - uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7}; - for (int i = 0; i < NumIter; i++) { - uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - size_t NewSize = (*MD.*M)(T, 8, 9); - if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; - if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; - if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; - if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; - if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; - if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; - if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; - if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; - } - EXPECT_EQ(FoundMask, 255); -} - -TEST(FuzzerMutate, ChangeBit1) { - TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16); -} -TEST(FuzzerMutate, ChangeBit2) { - TestChangeBit(&MutationDispatcher::Mutate, 1 << 18); -} - -void TestShuffleBytes(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - int FoundMask = 0; - uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66}; - uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66}; - uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66}; - uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33}; - uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66}; - for (int i = 0; i < NumIter; i++) { - uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - size_t NewSize = (*MD.*M)(T, 7, 7); - if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; - if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; - if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; - if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; - if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4; - } - EXPECT_EQ(FoundMask, 31); -} - -TEST(FuzzerMutate, ShuffleBytes1) { - TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 17); -} -TEST(FuzzerMutate, ShuffleBytes2) { - TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20); -} - -void TestCopyPart(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - int FoundMask = 0; - uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11}; - uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66}; - uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66}; - uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66}; - uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66}; - - for (int i = 0; i < NumIter; i++) { - uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - size_t NewSize = (*MD.*M)(T, 7, 7); - if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; - if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; - if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; - if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; - if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4; - } - - uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22}; - uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44}; - uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44}; - uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44}; - uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44}; - - for (int i = 0; i < NumIter; i++) { - uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - size_t NewSize = (*MD.*M)(T, 5, 8); - if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; - if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; - if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; - if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8; - if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9; - } - - EXPECT_EQ(FoundMask, 1023); -} - -TEST(FuzzerMutate, CopyPart1) { - TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10); -} -TEST(FuzzerMutate, CopyPart2) { - TestCopyPart(&MutationDispatcher::Mutate, 1 << 13); -} -TEST(FuzzerMutate, CopyPartNoInsertAtMaxSize) { - // This (non exhaustively) tests if `Mutate_CopyPart` tries to perform an - // insert on an input of size `MaxSize`. Performing an insert in this case - // will lead to the mutation failing. - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - uint8_t Data[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22}; - size_t MaxSize = sizeof(Data); - for (int count = 0; count < (1 << 18); ++count) { - size_t NewSize = MD->Mutate_CopyPart(Data, MaxSize, MaxSize); - ASSERT_EQ(NewSize, MaxSize); - } -} - -void TestAddWordFromDictionary(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD}; - uint8_t Word2[3] = {0xFF, 0xEE, 0xEF}; - MD->AddWordToManualDictionary(Word(Word1, sizeof(Word1))); - MD->AddWordToManualDictionary(Word(Word2, sizeof(Word2))); - int FoundMask = 0; - uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD}; - uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22}; - uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22}; - uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22}; - uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF}; - uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22}; - uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22}; - uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22}; - for (int i = 0; i < NumIter; i++) { - uint8_t T[7] = {0x00, 0x11, 0x22}; - size_t NewSize = (*MD.*M)(T, 3, 7); - if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0; - if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1; - if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2; - if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3; - if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4; - if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5; - if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6; - if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7; - } - EXPECT_EQ(FoundMask, 255); -} - -TEST(FuzzerMutate, AddWordFromDictionary1) { - TestAddWordFromDictionary( - &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15); -} - -TEST(FuzzerMutate, AddWordFromDictionary2) { - TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15); -} - -void TestChangeASCIIInteger(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - - uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'}; - uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'}; - uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'}; - uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'}; - int FoundMask = 0; - for (int i = 0; i < NumIter; i++) { - uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'}; - size_t NewSize = (*MD.*M)(T, 8, 8); - /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; - else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; - else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; - else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; - else if (NewSize == 8) FoundMask |= 1 << 4; - } - EXPECT_EQ(FoundMask, 31); -} - -TEST(FuzzerMutate, ChangeASCIIInteger1) { - TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger, - 1 << 15); -} - -TEST(FuzzerMutate, ChangeASCIIInteger2) { - TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15); -} - -void TestChangeBinaryInteger(Mutator M, int NumIter) { - std::unique_ptr<ExternalFunctions> t(new ExternalFunctions()); - fuzzer::EF = t.get(); - Random Rand(0); - std::unique_ptr<MutationDispatcher> MD(new MutationDispatcher(Rand, {})); - - uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79}; - uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77}; - uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77}; - uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88}; - uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size - uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size) - - int FoundMask = 0; - for (int i = 0; i < NumIter; i++) { - uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - size_t NewSize = (*MD.*M)(T, 8, 8); - /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0; - else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1; - else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2; - else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3; - else if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4; - else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5; - else if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6; - else if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7; - } - EXPECT_EQ(FoundMask, 255); -} - -TEST(FuzzerMutate, ChangeBinaryInteger1) { - TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger, - 1 << 12); -} - -TEST(FuzzerMutate, ChangeBinaryInteger2) { - TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15); -} - - -TEST(FuzzerDictionary, ParseOneDictionaryEntry) { - Unit U; - EXPECT_FALSE(ParseOneDictionaryEntry("", &U)); - EXPECT_FALSE(ParseOneDictionaryEntry(" ", &U)); - EXPECT_FALSE(ParseOneDictionaryEntry("\t ", &U)); - EXPECT_FALSE(ParseOneDictionaryEntry(" \" ", &U)); - EXPECT_FALSE(ParseOneDictionaryEntry(" zz\" ", &U)); - EXPECT_FALSE(ParseOneDictionaryEntry(" \"zz ", &U)); - EXPECT_FALSE(ParseOneDictionaryEntry(" \"\" ", &U)); - EXPECT_TRUE(ParseOneDictionaryEntry("\"a\"", &U)); - EXPECT_EQ(U, Unit({'a'})); - EXPECT_TRUE(ParseOneDictionaryEntry("\"abc\"", &U)); - EXPECT_EQ(U, Unit({'a', 'b', 'c'})); - EXPECT_TRUE(ParseOneDictionaryEntry("abc=\"abc\"", &U)); - EXPECT_EQ(U, Unit({'a', 'b', 'c'})); - EXPECT_FALSE(ParseOneDictionaryEntry("\"\\\"", &U)); - EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\\\"", &U)); - EXPECT_EQ(U, Unit({'\\'})); - EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xAB\"", &U)); - EXPECT_EQ(U, Unit({0xAB})); - EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xABz\\xDE\"", &U)); - EXPECT_EQ(U, Unit({0xAB, 'z', 0xDE})); - EXPECT_TRUE(ParseOneDictionaryEntry("\"#\"", &U)); - EXPECT_EQ(U, Unit({'#'})); - EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\"\"", &U)); - EXPECT_EQ(U, Unit({'"'})); -} - -TEST(FuzzerDictionary, ParseDictionaryFile) { - Vector<Unit> Units; - EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units)); - EXPECT_FALSE(ParseDictionaryFile("", &Units)); - EXPECT_TRUE(ParseDictionaryFile("\n", &Units)); - EXPECT_EQ(Units.size(), 0U); - EXPECT_TRUE(ParseDictionaryFile("#zzzz a b c d\n", &Units)); - EXPECT_EQ(Units.size(), 0U); - EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); - EXPECT_EQ(Units.size(), 0U); - EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units)); - EXPECT_EQ(Units.size(), 0U); - EXPECT_TRUE(ParseDictionaryFile(" #zzzz\naaa=\"aa\"", &Units)); - EXPECT_EQ(Units, Vector<Unit>({Unit({'a', 'a'})})); - EXPECT_TRUE( - ParseDictionaryFile(" #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units)); - EXPECT_EQ(Units, - Vector<Unit>({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})})); -} - -TEST(FuzzerUtil, Base64) { - EXPECT_EQ("", Base64({})); - EXPECT_EQ("YQ==", Base64({'a'})); - EXPECT_EQ("eA==", Base64({'x'})); - EXPECT_EQ("YWI=", Base64({'a', 'b'})); - EXPECT_EQ("eHk=", Base64({'x', 'y'})); - EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'})); - EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'})); - EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'})); - EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'})); - EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'})); -} - -TEST(Corpus, Distribution) { - DataFlowTrace DFT; - Random Rand(0); - std::unique_ptr<InputCorpus> C(new InputCorpus("")); - size_t N = 10; - size_t TriesPerUnit = 1<<16; - for (size_t i = 0; i < N; i++) - C->AddToCorpus(Unit{static_cast<uint8_t>(i)}, 1, false, false, {}, DFT, - nullptr); - - Vector<size_t> Hist(N); - for (size_t i = 0; i < N * TriesPerUnit; i++) { - Hist[C->ChooseUnitIdxToMutate(Rand)]++; - } - for (size_t i = 0; i < N; i++) { - // A weak sanity check that every unit gets invoked. - EXPECT_GT(Hist[i], TriesPerUnit / N / 3); - } -} - -TEST(Merge, Bad) { - const char *kInvalidInputs[] = { - "", - "x", - "3\nx", - "2\n3", - "2\n2", - "2\n2\nA\n", - "2\n2\nA\nB\nC\n", - "0\n0\n", - "1\n1\nA\nDONE 0", - "1\n1\nA\nSTARTED 1", - }; - Merger M; - for (auto S : kInvalidInputs) { - // fprintf(stderr, "TESTING:\n%s\n", S); - EXPECT_FALSE(M.Parse(S, false)); - } -} - -void EQ(const Vector<uint32_t> &A, const Vector<uint32_t> &B) { - EXPECT_EQ(A, B); -} - -void EQ(const Vector<std::string> &A, const Vector<std::string> &B) { - Set<std::string> a(A.begin(), A.end()); - Set<std::string> b(B.begin(), B.end()); - EXPECT_EQ(a, b); -} - -static void Merge(const std::string &Input, - const Vector<std::string> Result, - size_t NumNewFeatures) { - Merger M; - Vector<std::string> NewFiles; - EXPECT_TRUE(M.Parse(Input, true)); - std::stringstream SS; - M.PrintSummary(SS); - EXPECT_EQ(NumNewFeatures, M.Merge(&NewFiles)); - EXPECT_EQ(M.AllFeatures(), M.ParseSummary(SS)); - EQ(NewFiles, Result); -} - -TEST(Merge, Good) { - Merger M; - - EXPECT_TRUE(M.Parse("1\n0\nAA\n", false)); - EXPECT_EQ(M.Files.size(), 1U); - EXPECT_EQ(M.NumFilesInFirstCorpus, 0U); - EXPECT_EQ(M.Files[0].Name, "AA"); - EXPECT_TRUE(M.LastFailure.empty()); - EXPECT_EQ(M.FirstNotProcessedFile, 0U); - - EXPECT_TRUE(M.Parse("2\n1\nAA\nBB\nSTARTED 0 42\n", false)); - EXPECT_EQ(M.Files.size(), 2U); - EXPECT_EQ(M.NumFilesInFirstCorpus, 1U); - EXPECT_EQ(M.Files[0].Name, "AA"); - EXPECT_EQ(M.Files[1].Name, "BB"); - EXPECT_EQ(M.LastFailure, "AA"); - EXPECT_EQ(M.FirstNotProcessedFile, 1U); - - EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n" - "STARTED 0 1000\n" - "DONE 0 1 2 3\n" - "STARTED 1 1001\n" - "DONE 1 4 5 6 \n" - "STARTED 2 1002\n" - "", true)); - EXPECT_EQ(M.Files.size(), 3U); - EXPECT_EQ(M.NumFilesInFirstCorpus, 1U); - EXPECT_EQ(M.Files[0].Name, "AA"); - EXPECT_EQ(M.Files[0].Size, 1000U); - EXPECT_EQ(M.Files[1].Name, "BB"); - EXPECT_EQ(M.Files[1].Size, 1001U); - EXPECT_EQ(M.Files[2].Name, "C"); - EXPECT_EQ(M.Files[2].Size, 1002U); - EXPECT_EQ(M.LastFailure, "C"); - EXPECT_EQ(M.FirstNotProcessedFile, 3U); - EQ(M.Files[0].Features, {1, 2, 3}); - EQ(M.Files[1].Features, {4, 5, 6}); - - - Vector<std::string> NewFiles; - - EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n" - "STARTED 0 1000\nDONE 0 1 2 3\n" - "STARTED 1 1001\nDONE 1 4 5 6 \n" - "STARTED 2 1002\nDONE 2 6 1 3 \n" - "", true)); - EXPECT_EQ(M.Files.size(), 3U); - EXPECT_EQ(M.NumFilesInFirstCorpus, 2U); - EXPECT_TRUE(M.LastFailure.empty()); - EXPECT_EQ(M.FirstNotProcessedFile, 3U); - EQ(M.Files[0].Features, {1, 2, 3}); - EQ(M.Files[1].Features, {4, 5, 6}); - EQ(M.Files[2].Features, {1, 3, 6}); - EXPECT_EQ(0U, M.Merge(&NewFiles)); - EQ(NewFiles, {}); - - EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n" - "STARTED 0 1000\nDONE 0 1 2 3\n" - "STARTED 1 1001\nDONE 1 4 5 6 \n" - "STARTED 2 1002\nDONE 2 6 1 3\n" - "", true)); - EQ(M.Files[0].Features, {1, 2, 3}); - EQ(M.Files[1].Features, {4, 5, 6}); - EQ(M.Files[2].Features, {1, 3, 6}); - EXPECT_EQ(3U, M.Merge(&NewFiles)); - EQ(NewFiles, {"B"}); - - // Same as the above, but with InitialFeatures. - EXPECT_TRUE(M.Parse("2\n0\nB\nC\n" - "STARTED 0 1001\nDONE 0 4 5 6 \n" - "STARTED 1 1002\nDONE 1 6 1 3\n" - "", true)); - EQ(M.Files[0].Features, {4, 5, 6}); - EQ(M.Files[1].Features, {1, 3, 6}); - Set<uint32_t> InitialFeatures; - InitialFeatures.insert(1); - InitialFeatures.insert(2); - InitialFeatures.insert(3); - EXPECT_EQ(3U, M.Merge(InitialFeatures, &NewFiles)); - EQ(NewFiles, {"B"}); -} - -TEST(Merge, Merge) { - - Merge("3\n1\nA\nB\nC\n" - "STARTED 0 1000\nDONE 0 1 2 3\n" - "STARTED 1 1001\nDONE 1 4 5 6 \n" - "STARTED 2 1002\nDONE 2 6 1 3 \n", - {"B"}, 3); - - Merge("3\n0\nA\nB\nC\n" - "STARTED 0 2000\nDONE 0 1 2 3\n" - "STARTED 1 1001\nDONE 1 4 5 6 \n" - "STARTED 2 1002\nDONE 2 6 1 3 \n", - {"A", "B", "C"}, 6); - - Merge("4\n0\nA\nB\nC\nD\n" - "STARTED 0 2000\nDONE 0 1 2 3\n" - "STARTED 1 1101\nDONE 1 4 5 6 \n" - "STARTED 2 1102\nDONE 2 6 1 3 100 \n" - "STARTED 3 1000\nDONE 3 1 \n", - {"A", "B", "C", "D"}, 7); - - Merge("4\n1\nA\nB\nC\nD\n" - "STARTED 0 2000\nDONE 0 4 5 6 7 8\n" - "STARTED 1 1100\nDONE 1 1 2 3 \n" - "STARTED 2 1100\nDONE 2 2 3 \n" - "STARTED 3 1000\nDONE 3 1 \n", - {"B", "D"}, 3); -} - -TEST(Fuzzer, ForEachNonZeroByte) { - const size_t N = 64; - alignas(64) uint8_t Ar[N + 8] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 5, 0, 6, 0, 0, - 0, 0, 0, 0, 0, 0, 7, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 8, - 9, 9, 9, 9, 9, 9, 9, 9, - }; - typedef Vector<std::pair<size_t, uint8_t> > Vec; - Vec Res, Expected; - auto CB = [&](size_t FirstFeature, size_t Idx, uint8_t V) { - Res.push_back({FirstFeature + Idx, V}); - }; - ForEachNonZeroByte(Ar, Ar + N, 100, CB); - Expected = {{108, 1}, {109, 2}, {118, 3}, {120, 4}, - {135, 5}, {137, 6}, {146, 7}, {163, 8}}; - EXPECT_EQ(Res, Expected); - - Res.clear(); - ForEachNonZeroByte(Ar + 9, Ar + N, 109, CB); - Expected = { {109, 2}, {118, 3}, {120, 4}, - {135, 5}, {137, 6}, {146, 7}, {163, 8}}; - EXPECT_EQ(Res, Expected); - - Res.clear(); - ForEachNonZeroByte(Ar + 9, Ar + N - 9, 109, CB); - Expected = { {109, 2}, {118, 3}, {120, 4}, - {135, 5}, {137, 6}, {146, 7}}; - EXPECT_EQ(Res, Expected); -} - -// FuzzerCommand unit tests. The arguments in the two helper methods below must -// match. -static void makeCommandArgs(Vector<std::string> *ArgsToAdd) { - assert(ArgsToAdd); - ArgsToAdd->clear(); - ArgsToAdd->push_back("foo"); - ArgsToAdd->push_back("-bar=baz"); - ArgsToAdd->push_back("qux"); - ArgsToAdd->push_back(Command::ignoreRemainingArgs()); - ArgsToAdd->push_back("quux"); - ArgsToAdd->push_back("-grault=garply"); -} - -static std::string makeCmdLine(const char *separator, const char *suffix) { - std::string CmdLine("foo -bar=baz qux "); - if (strlen(separator) != 0) { - CmdLine += separator; - CmdLine += " "; - } - CmdLine += Command::ignoreRemainingArgs(); - CmdLine += " quux -grault=garply"; - if (strlen(suffix) != 0) { - CmdLine += " "; - CmdLine += suffix; - } - return CmdLine; -} - -TEST(FuzzerCommand, Create) { - std::string CmdLine; - - // Default constructor - Command DefaultCmd; - - CmdLine = DefaultCmd.toString(); - EXPECT_EQ(CmdLine, ""); - - // Explicit constructor - Vector<std::string> ArgsToAdd; - makeCommandArgs(&ArgsToAdd); - Command InitializedCmd(ArgsToAdd); - - CmdLine = InitializedCmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", "")); - - // Compare each argument - auto InitializedArgs = InitializedCmd.getArguments(); - auto i = ArgsToAdd.begin(); - auto j = InitializedArgs.begin(); - while (i != ArgsToAdd.end() && j != InitializedArgs.end()) { - EXPECT_EQ(*i++, *j++); - } - EXPECT_EQ(i, ArgsToAdd.end()); - EXPECT_EQ(j, InitializedArgs.end()); - - // Copy constructor - Command CopiedCmd(InitializedCmd); - - CmdLine = CopiedCmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", "")); - - // Assignment operator - Command AssignedCmd; - AssignedCmd = CopiedCmd; - - CmdLine = AssignedCmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", "")); -} - -TEST(FuzzerCommand, ModifyArguments) { - Vector<std::string> ArgsToAdd; - makeCommandArgs(&ArgsToAdd); - Command Cmd; - std::string CmdLine; - - Cmd.addArguments(ArgsToAdd); - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", "")); - - Cmd.addArgument("waldo"); - EXPECT_TRUE(Cmd.hasArgument("waldo")); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("waldo", "")); - - Cmd.removeArgument("waldo"); - EXPECT_FALSE(Cmd.hasArgument("waldo")); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", "")); -} - -TEST(FuzzerCommand, ModifyFlags) { - Vector<std::string> ArgsToAdd; - makeCommandArgs(&ArgsToAdd); - Command Cmd(ArgsToAdd); - std::string Value, CmdLine; - ASSERT_FALSE(Cmd.hasFlag("fred")); - - Value = Cmd.getFlagValue("fred"); - EXPECT_EQ(Value, ""); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", "")); - - Cmd.addFlag("fred", "plugh"); - EXPECT_TRUE(Cmd.hasFlag("fred")); - - Value = Cmd.getFlagValue("fred"); - EXPECT_EQ(Value, "plugh"); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("-fred=plugh", "")); - - Cmd.removeFlag("fred"); - EXPECT_FALSE(Cmd.hasFlag("fred")); - - Value = Cmd.getFlagValue("fred"); - EXPECT_EQ(Value, ""); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", "")); -} - -TEST(FuzzerCommand, SetOutput) { - Vector<std::string> ArgsToAdd; - makeCommandArgs(&ArgsToAdd); - Command Cmd(ArgsToAdd); - std::string CmdLine; - ASSERT_FALSE(Cmd.hasOutputFile()); - ASSERT_FALSE(Cmd.isOutAndErrCombined()); - - Cmd.combineOutAndErr(true); - EXPECT_TRUE(Cmd.isOutAndErrCombined()); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", "2>&1")); - - Cmd.combineOutAndErr(false); - EXPECT_FALSE(Cmd.isOutAndErrCombined()); - - Cmd.setOutputFile("xyzzy"); - EXPECT_TRUE(Cmd.hasOutputFile()); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", ">xyzzy")); - - Cmd.setOutputFile("thud"); - EXPECT_TRUE(Cmd.hasOutputFile()); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", ">thud")); - - Cmd.combineOutAndErr(); - EXPECT_TRUE(Cmd.isOutAndErrCombined()); - - CmdLine = Cmd.toString(); - EXPECT_EQ(CmdLine, makeCmdLine("", ">thud 2>&1")); -} - -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/lib/hwasan/.clang-format b/lib/hwasan/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/hwasan/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/hwasan/CMakeLists.txt b/lib/hwasan/CMakeLists.txt deleted file mode 100644 index 20ab94dc04467..0000000000000 --- a/lib/hwasan/CMakeLists.txt +++ /dev/null @@ -1,179 +0,0 @@ -include_directories(..) - -# Runtime library sources and build flags. -set(HWASAN_RTL_SOURCES - hwasan.cc - hwasan_allocator.cc - hwasan_dynamic_shadow.cc - hwasan_interceptors.cc - hwasan_linux.cc - hwasan_memintrinsics.cc - hwasan_poisoning.cc - hwasan_report.cc - hwasan_thread.cc - hwasan_thread_list.cc - ) - -set(HWASAN_RTL_CXX_SOURCES - hwasan_new_delete.cc) - -set(HWASAN_RTL_HEADERS - hwasan.h - hwasan_allocator.h - hwasan_dynamic_shadow.h - hwasan_flags.h - hwasan_flags.inc - hwasan_interface_internal.h - hwasan_mapping.h - hwasan_poisoning.h - hwasan_report.h - hwasan_thread.h - hwasan_thread_list.h - ) - -set(HWASAN_DEFINITIONS) -append_list_if(COMPILER_RT_HWASAN_WITH_INTERCEPTORS HWASAN_WITH_INTERCEPTORS=1 HWASAN_DEFINITIONS) - -set(HWASAN_RTL_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF HWASAN_RTL_CFLAGS) -append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC HWASAN_RTL_CFLAGS) -# Prevent clang from generating libc calls. -append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding HWASAN_RTL_CFLAGS) - -set(HWASAN_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) - -if(ANDROID) -# Put most Sanitizer shared libraries in the global group. For more details, see -# android-changes-for-ndk-developers.md#changes-to-library-search-order - if (COMPILER_RT_HAS_Z_GLOBAL) - list(APPEND HWASAN_DYNAMIC_LINK_FLAGS -Wl,-z,global) - endif() -endif() - -set(HWASAN_DYNAMIC_CFLAGS ${HWASAN_RTL_CFLAGS}) -append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC - -ftls-model=initial-exec HWASAN_DYNAMIC_CFLAGS) -append_list_if(MSVC /DEBUG HWASAN_DYNAMIC_LINK_FLAGS) - -set(HWASAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARY} ${SANITIZER_COMMON_LINK_LIBS}) - -append_list_if(COMPILER_RT_HAS_LIBDL dl HWASAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBRT rt HWASAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBM m HWASAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread HWASAN_DYNAMIC_LIBS) - -if (TARGET cxx-headers OR HAVE_LIBCXX) - set(HWASAN_DEPS cxx-headers) -endif() - -# Static runtime library. -add_compiler_rt_component(hwasan) - -add_compiler_rt_object_libraries(RTHwasan - ARCHS ${HWASAN_SUPPORTED_ARCH} - SOURCES ${HWASAN_RTL_SOURCES} - ADDITIONAL_HEADERS ${HWASAN_RTL_HEADERS} - CFLAGS ${HWASAN_RTL_CFLAGS} - DEFS ${HWASAN_DEFINITIONS} - DEPS ${HWASAN_DEPS}) -add_compiler_rt_object_libraries(RTHwasan_cxx - ARCHS ${HWASAN_SUPPORTED_ARCH} - SOURCES ${HWASAN_RTL_CXX_SOURCES} - ADDITIONAL_HEADERS ${HWASAN_RTL_HEADERS} - CFLAGS ${HWASAN_RTL_CFLAGS} - DEFS ${HWASAN_DEFINITIONS} - DEPS ${HWASAN_DEPS}) -add_compiler_rt_object_libraries(RTHwasan_dynamic - ARCHS ${HWASAN_SUPPORTED_ARCH} - SOURCES ${HWASAN_RTL_SOURCES} ${HWASAN_RTL_CXX_SOURCES} - ADDITIONAL_HEADERS ${HWASAN_RTL_HEADERS} - CFLAGS ${HWASAN_DYNAMIC_CFLAGS} - DEFS ${HWASAN_DEFINITIONS} - DEPS ${HWASAN_DEPS}) - -file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc "") -add_compiler_rt_object_libraries(RTHwasan_dynamic_version_script_dummy - ARCHS ${HWASAN_SUPPORTED_ARCH} - SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc - CFLAGS ${HWASAN_DYNAMIC_CFLAGS} - DEFS ${HWASAN_DEFINITIONS} - DEPS ${HWASAN_DEPS}) - -foreach(arch ${HWASAN_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.hwasan - STATIC - ARCHS ${arch} - OBJECT_LIBS RTHwasan - RTInterception - RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTUbsan - CFLAGS ${HWASAN_RTL_CFLAGS} - PARENT_TARGET hwasan) - add_compiler_rt_runtime(clang_rt.hwasan_cxx - STATIC - ARCHS ${arch} - OBJECT_LIBS RTHwasan_cxx - RTUbsan_cxx - CFLAGS ${HWASAN_RTL_CFLAGS} - PARENT_TARGET hwasan) - - if (UNIX) - add_sanitizer_rt_version_list(clang_rt.hwasan-dynamic-${arch} - LIBS clang_rt.hwasan-${arch} clang_rt.hwasan_cxx-${arch} - EXTRA hwasan.syms.extra) - set(VERSION_SCRIPT_FLAG - -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.hwasan-dynamic-${arch}.vers) - set_property(SOURCE - ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc - APPEND PROPERTY - OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang_rt.hwasan-dynamic-${arch}.vers) - else() - set(VERSION_SCRIPT_FLAG) - endif() - - - add_compiler_rt_runtime(clang_rt.hwasan - SHARED - ARCHS ${arch} - OBJECT_LIBS - RTHwasan_dynamic - RTInterception - RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTUbsan - RTUbsan_cxx - # The only purpose of RTHWAsan_dynamic_version_script_dummy is to - # carry a dependency of the shared runtime on the version script. - # Replacing it with a straightforward - # add_dependencies(clang_rt.asan-dynamic-${arch} clang_rt.asan-dynamic-${arch}-version-list) - # generates an order-only dependency in ninja. - RTHwasan_dynamic_version_script_dummy - CFLAGS ${HWASAN_DYNAMIC_CFLAGS} - LINK_FLAGS ${HWASAN_DYNAMIC_LINK_FLAGS} - ${VERSION_SCRIPT_FLAG} - LINK_LIBS ${HWASAN_DYNAMIC_LIBS} - DEFS ${ASAN_DYNAMIC_DEFINITIONS} - PARENT_TARGET hwasan) - - if(SANITIZER_USE_SYMBOLS) - add_sanitizer_rt_symbols(clang_rt.hwasan - ARCHS ${arch} - EXTRA hwasan.syms.extra) - add_sanitizer_rt_symbols(clang_rt.hwasan_cxx - ARCHS ${arch} - EXTRA hwasan.syms.extra) - add_dependencies(hwasan clang_rt.hwasan-${arch}-symbols - clang_rt.hwasan_cxx-${arch}-symbols) - endif() -endforeach() - -add_compiler_rt_resource_file(hwasan_blacklist hwasan_blacklist.txt hwasan) - -# if(COMPILER_RT_INCLUDE_TESTS) -# add_subdirectory(tests) -# endif() diff --git a/lib/interception/.clang-format b/lib/interception/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/interception/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/interception/CMakeLists.txt b/lib/interception/CMakeLists.txt deleted file mode 100644 index c0ac974d726ae..0000000000000 --- a/lib/interception/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# Build for the runtime interception helper library. - -set(INTERCEPTION_SOURCES - interception_linux.cc - interception_mac.cc - interception_win.cc - interception_type_test.cc) - -set(INTERCEPTION_HEADERS - interception.h - interception_linux.h - interception_mac.h - interception_win.h) - -include_directories(..) - -set(INTERCEPTION_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF INTERCEPTION_CFLAGS) - -add_compiler_rt_object_libraries(RTInterception - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${INTERCEPTION_SOURCES} - ADDITIONAL_HEADERS ${INTERCEPTION_HEADERS} - CFLAGS ${INTERCEPTION_CFLAGS}) - -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/lib/interception/tests/CMakeLists.txt b/lib/interception/tests/CMakeLists.txt deleted file mode 100644 index 1da0a455bf331..0000000000000 --- a/lib/interception/tests/CMakeLists.txt +++ /dev/null @@ -1,113 +0,0 @@ -include(CompilerRTCompile) - -filter_available_targets(INTERCEPTION_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el) - -set(INTERCEPTION_UNITTESTS - interception_linux_test.cc - interception_test_main.cc - interception_win_test.cc -) - -set(INTERCEPTION_TEST_HEADERS) - -set(INTERCEPTION_TEST_CFLAGS_COMMON - ${COMPILER_RT_UNITTEST_CFLAGS} - ${COMPILER_RT_GTEST_CFLAGS} - -I${COMPILER_RT_SOURCE_DIR}/include - -I${COMPILER_RT_SOURCE_DIR}/lib - -I${COMPILER_RT_SOURCE_DIR}/lib/interception - -fno-rtti - -O2 - -Werror=sign-compare - -Wno-non-virtual-dtor) - -# -gline-tables-only must be enough for these tests, so use it if possible. -if(COMPILER_RT_TEST_COMPILER_ID MATCHES "Clang") - list(APPEND INTERCEPTION_TEST_CFLAGS_COMMON -gline-tables-only) -else() - list(APPEND INTERCEPTION_TEST_CFLAGS_COMMON -g) -endif() -if(MSVC) - list(APPEND INTERCEPTION_TEST_CFLAGS_COMMON -gcodeview) - list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON -Wl,-largeaddressaware) -endif() -list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON -g) - -if(NOT MSVC) - list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON --driver-mode=g++) -endif() - -if(ANDROID) - list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON -pie) -endif() - -set(INTERCEPTION_TEST_LINK_LIBS) -append_list_if(COMPILER_RT_HAS_LIBLOG log INTERCEPTION_TEST_LINK_LIBS) -# NDK r10 requires -latomic almost always. -append_list_if(ANDROID atomic INTERCEPTION_TEST_LINK_LIBS) - -append_list_if(COMPILER_RT_HAS_LIBDL -ldl INTERCEPTION_TEST_LINK_FLAGS_COMMON) -append_list_if(COMPILER_RT_HAS_LIBRT -lrt INTERCEPTION_TEST_LINK_FLAGS_COMMON) -append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread INTERCEPTION_TEST_LINK_FLAGS_COMMON) -# x86_64 FreeBSD 9.2 additionally requires libc++ to build the tests. Also, -# 'libm' shall be specified explicitly to build i386 tests. -if(CMAKE_SYSTEM MATCHES "FreeBSD-9.2-RELEASE") - list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON "-lc++ -lm") -endif() - -include_directories(..) -include_directories(../..) - -# Adds static library which contains interception object file -# (universal binary on Mac and arch-specific object files on Linux). -macro(add_interceptor_lib library) - add_library(${library} STATIC ${ARGN}) - set_target_properties(${library} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - FOLDER "Compiler-RT Runtime tests") -endmacro() - -function(get_interception_lib_for_arch arch lib) - if(APPLE) - set(tgt_name "RTInterception.test.osx") - else() - set(tgt_name "RTInterception.test.${arch}") - endif() - set(${lib} "${tgt_name}" PARENT_SCOPE) -endfunction() - -# Interception unit tests testsuite. -add_custom_target(InterceptionUnitTests) -set_target_properties(InterceptionUnitTests PROPERTIES - FOLDER "Compiler-RT Tests") - -# Adds interception tests for architecture. -macro(add_interception_tests_for_arch arch) - set(INTERCEPTION_TEST_OBJECTS) - get_interception_lib_for_arch(${arch} INTERCEPTION_COMMON_LIB) - generate_compiler_rt_tests(INTERCEPTION_TEST_OBJECTS - InterceptionUnitTests "Interception-${arch}-Test" ${arch} - RUNTIME ${INTERCEPTION_COMMON_LIB} - SOURCES ${INTERCEPTION_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} - COMPILE_DEPS ${INTERCEPTION_TEST_HEADERS} - DEPS gtest - CFLAGS ${INTERCEPTION_TEST_CFLAGS_COMMON} - LINK_FLAGS ${INTERCEPTION_TEST_LINK_FLAGS_COMMON}) -endmacro() - -if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID AND NOT APPLE) - # We use just-built clang to build interception unittests, so we must - # be sure that produced binaries would work. - if(APPLE) - add_interceptor_lib("RTInterception.test.osx" - $<TARGET_OBJECTS:RTInterception.osx>) - else() - foreach(arch ${INTERCEPTION_UNITTEST_SUPPORTED_ARCH}) - add_interceptor_lib("RTInterception.test.${arch}" - $<TARGET_OBJECTS:RTInterception.${arch}>) - endforeach() - endif() - foreach(arch ${INTERCEPTION_UNITTEST_SUPPORTED_ARCH}) - add_interception_tests_for_arch(${arch}) - endforeach() -endif() diff --git a/lib/interception/tests/interception_linux_test.cc b/lib/interception/tests/interception_linux_test.cc deleted file mode 100644 index cc09aa09df3a4..0000000000000 --- a/lib/interception/tests/interception_linux_test.cc +++ /dev/null @@ -1,68 +0,0 @@ -//===-- interception_linux_test.cc ----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// Tests for interception_linux.h. -// -//===----------------------------------------------------------------------===// - -// Do not declare isdigit in ctype.h. -#define __NO_CTYPE - -#include "interception/interception.h" - -#include "gtest/gtest.h" - -// Too slow for debug build -#if !SANITIZER_DEBUG -#if SANITIZER_LINUX - -static int InterceptorFunctionCalled; - -DECLARE_REAL(int, isdigit, int); - -INTERCEPTOR(int, isdigit, int d) { - ++InterceptorFunctionCalled; - return d >= '0' && d <= '9'; -} - -namespace __interception { - -TEST(Interception, GetRealFunctionAddress) { - uptr malloc_address = 0; - EXPECT_TRUE(GetRealFunctionAddress("malloc", &malloc_address, 0, 0)); - EXPECT_NE(0U, malloc_address); - - uptr dummy_address = 0; - EXPECT_TRUE( - GetRealFunctionAddress("dummy_doesnt_exist__", &dummy_address, 0, 0)); - EXPECT_EQ(0U, dummy_address); -} - -TEST(Interception, Basic) { - ASSERT_TRUE(INTERCEPT_FUNCTION(isdigit)); - - // After interception, the counter should be incremented. - InterceptorFunctionCalled = 0; - EXPECT_NE(0, isdigit('1')); - EXPECT_EQ(1, InterceptorFunctionCalled); - EXPECT_EQ(0, isdigit('a')); - EXPECT_EQ(2, InterceptorFunctionCalled); - - // Calling the REAL function should not affect the counter. - InterceptorFunctionCalled = 0; - EXPECT_NE(0, REAL(isdigit)('1')); - EXPECT_EQ(0, REAL(isdigit)('a')); - EXPECT_EQ(0, InterceptorFunctionCalled); -} - -} // namespace __interception - -#endif // SANITIZER_LINUX -#endif // #if !SANITIZER_DEBUG diff --git a/lib/interception/tests/interception_test_main.cc b/lib/interception/tests/interception_test_main.cc deleted file mode 100644 index 311da51ecfcec..0000000000000 --- a/lib/interception/tests/interception_test_main.cc +++ /dev/null @@ -1,22 +0,0 @@ -//===-- interception_test_main.cc------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// Testing the machinery for providing replacements/wrappers for system -// functions. -//===----------------------------------------------------------------------===// - -#include "gtest/gtest.h" - -int main(int argc, char **argv) { - testing::GTEST_FLAG(death_test_style) = "threadsafe"; - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/lib/interception/tests/interception_win_test.cc b/lib/interception/tests/interception_win_test.cc deleted file mode 100644 index 37ef994f83da1..0000000000000 --- a/lib/interception/tests/interception_win_test.cc +++ /dev/null @@ -1,637 +0,0 @@ -//===-- interception_win_test.cc ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// Tests for interception_win.h. -// -//===----------------------------------------------------------------------===// -#include "interception/interception.h" - -#include "gtest/gtest.h" - -// Too slow for debug build -#if !SANITIZER_DEBUG -#if SANITIZER_WINDOWS - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - -namespace __interception { -namespace { - -enum FunctionPrefixKind { - FunctionPrefixNone, - FunctionPrefixPadding, - FunctionPrefixHotPatch, - FunctionPrefixDetour, -}; - -typedef bool (*TestOverrideFunction)(uptr, uptr, uptr*); -typedef int (*IdentityFunction)(int); - -#if SANITIZER_WINDOWS64 - -const u8 kIdentityCodeWithPrologue[] = { - 0x55, // push rbp - 0x48, 0x89, 0xE5, // mov rbp,rsp - 0x8B, 0xC1, // mov eax,ecx - 0x5D, // pop rbp - 0xC3, // ret -}; - -const u8 kIdentityCodeWithPushPop[] = { - 0x55, // push rbp - 0x48, 0x89, 0xE5, // mov rbp,rsp - 0x53, // push rbx - 0x50, // push rax - 0x58, // pop rax - 0x8B, 0xC1, // mov rax,rcx - 0x5B, // pop rbx - 0x5D, // pop rbp - 0xC3, // ret -}; - -const u8 kIdentityTwiceOffset = 16; -const u8 kIdentityTwice[] = { - 0x55, // push rbp - 0x48, 0x89, 0xE5, // mov rbp,rsp - 0x8B, 0xC1, // mov eax,ecx - 0x5D, // pop rbp - 0xC3, // ret - 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, - 0x55, // push rbp - 0x48, 0x89, 0xE5, // mov rbp,rsp - 0x8B, 0xC1, // mov eax,ecx - 0x5D, // pop rbp - 0xC3, // ret -}; - -const u8 kIdentityCodeWithMov[] = { - 0x89, 0xC8, // mov eax, ecx - 0xC3, // ret -}; - -const u8 kIdentityCodeWithJump[] = { - 0xE9, 0x04, 0x00, 0x00, - 0x00, // jmp + 4 - 0xCC, 0xCC, 0xCC, 0xCC, - 0x89, 0xC8, // mov eax, ecx - 0xC3, // ret -}; - -#else - -const u8 kIdentityCodeWithPrologue[] = { - 0x55, // push ebp - 0x8B, 0xEC, // mov ebp,esp - 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] - 0x5D, // pop ebp - 0xC3, // ret -}; - -const u8 kIdentityCodeWithPushPop[] = { - 0x55, // push ebp - 0x8B, 0xEC, // mov ebp,esp - 0x53, // push ebx - 0x50, // push eax - 0x58, // pop eax - 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] - 0x5B, // pop ebx - 0x5D, // pop ebp - 0xC3, // ret -}; - -const u8 kIdentityTwiceOffset = 8; -const u8 kIdentityTwice[] = { - 0x55, // push ebp - 0x8B, 0xEC, // mov ebp,esp - 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] - 0x5D, // pop ebp - 0xC3, // ret - 0x55, // push ebp - 0x8B, 0xEC, // mov ebp,esp - 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp + 8] - 0x5D, // pop ebp - 0xC3, // ret -}; - -const u8 kIdentityCodeWithMov[] = { - 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4] - 0xC3, // ret -}; - -const u8 kIdentityCodeWithJump[] = { - 0xE9, 0x04, 0x00, 0x00, - 0x00, // jmp + 4 - 0xCC, 0xCC, 0xCC, 0xCC, - 0x8B, 0x44, 0x24, 0x04, // mov eax,dword ptr [esp + 4] - 0xC3, // ret -}; - -#endif - -const u8 kPatchableCode1[] = { - 0xB8, 0x4B, 0x00, 0x00, 0x00, // mov eax,4B - 0x33, 0xC9, // xor ecx,ecx - 0xC3, // ret -}; - -const u8 kPatchableCode2[] = { - 0x55, // push ebp - 0x8B, 0xEC, // mov ebp,esp - 0x33, 0xC0, // xor eax,eax - 0x5D, // pop ebp - 0xC3, // ret -}; - -const u8 kPatchableCode3[] = { - 0x55, // push ebp - 0x8B, 0xEC, // mov ebp,esp - 0x6A, 0x00, // push 0 - 0xE8, 0x3D, 0xFF, 0xFF, 0xFF, // call <func> -}; - -const u8 kPatchableCode4[] = { - 0xE9, 0xCC, 0xCC, 0xCC, 0xCC, // jmp <label> - 0x90, 0x90, 0x90, 0x90, -}; - -const u8 kPatchableCode5[] = { - 0x55, // push ebp - 0x8b, 0xec, // mov ebp,esp - 0x8d, 0xa4, 0x24, 0x30, 0xfd, 0xff, 0xff, // lea esp,[esp-2D0h] - 0x54, // push esp -}; - -#if SANITIZER_WINDOWS64 -u8 kLoadGlobalCode[] = { - 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov eax [rip + global] - 0xC3, // ret -}; -#endif - -const u8 kUnpatchableCode1[] = { - 0xC3, // ret -}; - -const u8 kUnpatchableCode2[] = { - 0x33, 0xC9, // xor ecx,ecx - 0xC3, // ret -}; - -const u8 kUnpatchableCode3[] = { - 0x75, 0xCC, // jne <label> - 0x33, 0xC9, // xor ecx,ecx - 0xC3, // ret -}; - -const u8 kUnpatchableCode4[] = { - 0x74, 0xCC, // jne <label> - 0x33, 0xC9, // xor ecx,ecx - 0xC3, // ret -}; - -const u8 kUnpatchableCode5[] = { - 0xEB, 0x02, // jmp <label> - 0x33, 0xC9, // xor ecx,ecx - 0xC3, // ret -}; - -const u8 kUnpatchableCode6[] = { - 0xE8, 0xCC, 0xCC, 0xCC, 0xCC, // call <func> - 0x90, 0x90, 0x90, 0x90, -}; - -// A buffer holding the dynamically generated code under test. -u8* ActiveCode; -const size_t ActiveCodeLength = 4096; - -int InterceptorFunction(int x); - -/// Allocate code memory more than 2GB away from Base. -u8 *AllocateCode2GBAway(u8 *Base) { - // Find a 64K aligned location after Base plus 2GB. - size_t TwoGB = 0x80000000; - size_t AllocGranularity = 0x10000; - Base = (u8 *)((((uptr)Base + TwoGB + AllocGranularity)) & ~(AllocGranularity - 1)); - - // Check if that location is free, and if not, loop over regions until we find - // one that is. - MEMORY_BASIC_INFORMATION mbi = {}; - while (sizeof(mbi) == VirtualQuery(Base, &mbi, sizeof(mbi))) { - if (mbi.State & MEM_FREE) break; - Base += mbi.RegionSize; - } - - // Allocate one RWX page at the free location. - return (u8 *)::VirtualAlloc(Base, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); -} - -template<class T> -static void LoadActiveCode( - const T &code, - uptr *entry_point, - FunctionPrefixKind prefix_kind = FunctionPrefixNone) { - if (ActiveCode == nullptr) { - ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction); - ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away"; - } - - size_t position = 0; - - // Add padding to avoid memory violation when scanning the prefix. - for (int i = 0; i < 16; ++i) - ActiveCode[position++] = 0xC3; // Instruction 'ret'. - - // Add function padding. - size_t padding = 0; - if (prefix_kind == FunctionPrefixPadding) - padding = 16; - else if (prefix_kind == FunctionPrefixDetour || - prefix_kind == FunctionPrefixHotPatch) - padding = FIRST_32_SECOND_64(5, 6); - // Insert |padding| instructions 'nop'. - for (size_t i = 0; i < padding; ++i) - ActiveCode[position++] = 0x90; - - // Keep track of the entry point. - *entry_point = (uptr)&ActiveCode[position]; - - // Add the detour instruction (i.e. mov edi, edi) - if (prefix_kind == FunctionPrefixDetour) { -#if SANITIZER_WINDOWS64 - // Note that "mov edi,edi" is NOP in 32-bit only, in 64-bit it clears - // higher bits of RDI. - // Use 66,90H as NOP for Windows64. - ActiveCode[position++] = 0x66; - ActiveCode[position++] = 0x90; -#else - // mov edi,edi. - ActiveCode[position++] = 0x8B; - ActiveCode[position++] = 0xFF; -#endif - - } - - // Copy the function body. - for (size_t i = 0; i < sizeof(T); ++i) - ActiveCode[position++] = code[i]; -} - -int InterceptorFunctionCalled; -IdentityFunction InterceptedRealFunction; - -int InterceptorFunction(int x) { - ++InterceptorFunctionCalled; - return InterceptedRealFunction(x); -} - -} // namespace - -// Tests for interception_win.h -TEST(Interception, InternalGetProcAddress) { - HMODULE ntdll_handle = ::GetModuleHandle("ntdll"); - ASSERT_NE(nullptr, ntdll_handle); - uptr DbgPrint_expected = (uptr)::GetProcAddress(ntdll_handle, "DbgPrint"); - uptr isdigit_expected = (uptr)::GetProcAddress(ntdll_handle, "isdigit"); - uptr DbgPrint_adddress = InternalGetProcAddress(ntdll_handle, "DbgPrint"); - uptr isdigit_address = InternalGetProcAddress(ntdll_handle, "isdigit"); - - EXPECT_EQ(DbgPrint_expected, DbgPrint_adddress); - EXPECT_EQ(isdigit_expected, isdigit_address); - EXPECT_NE(DbgPrint_adddress, isdigit_address); -} - -template<class T> -static void TestIdentityFunctionPatching( - const T &code, - TestOverrideFunction override, - FunctionPrefixKind prefix_kind = FunctionPrefixNone) { - uptr identity_address; - LoadActiveCode(code, &identity_address, prefix_kind); - IdentityFunction identity = (IdentityFunction)identity_address; - - // Validate behavior before dynamic patching. - InterceptorFunctionCalled = 0; - EXPECT_EQ(0, identity(0)); - EXPECT_EQ(42, identity(42)); - EXPECT_EQ(0, InterceptorFunctionCalled); - - // Patch the function. - uptr real_identity_address = 0; - bool success = override(identity_address, - (uptr)&InterceptorFunction, - &real_identity_address); - EXPECT_TRUE(success); - EXPECT_NE(0U, real_identity_address); - IdentityFunction real_identity = (IdentityFunction)real_identity_address; - InterceptedRealFunction = real_identity; - - // Don't run tests if hooking failed or the real function is not valid. - if (!success || !real_identity_address) - return; - - // Calling the redirected function. - InterceptorFunctionCalled = 0; - EXPECT_EQ(0, identity(0)); - EXPECT_EQ(42, identity(42)); - EXPECT_EQ(2, InterceptorFunctionCalled); - - // Calling the real function. - InterceptorFunctionCalled = 0; - EXPECT_EQ(0, real_identity(0)); - EXPECT_EQ(42, real_identity(42)); - EXPECT_EQ(0, InterceptorFunctionCalled); - - TestOnlyReleaseTrampolineRegions(); -} - -#if !SANITIZER_WINDOWS64 -TEST(Interception, OverrideFunctionWithDetour) { - TestOverrideFunction override = OverrideFunctionWithDetour; - FunctionPrefixKind prefix = FunctionPrefixDetour; - TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); -} -#endif // !SANITIZER_WINDOWS64 - -TEST(Interception, OverrideFunctionWithRedirectJump) { - TestOverrideFunction override = OverrideFunctionWithRedirectJump; - TestIdentityFunctionPatching(kIdentityCodeWithJump, override); -} - -TEST(Interception, OverrideFunctionWithHotPatch) { - TestOverrideFunction override = OverrideFunctionWithHotPatch; - FunctionPrefixKind prefix = FunctionPrefixHotPatch; - TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); -} - -TEST(Interception, OverrideFunctionWithTrampoline) { - TestOverrideFunction override = OverrideFunctionWithTrampoline; - FunctionPrefixKind prefix = FunctionPrefixNone; - TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); - - prefix = FunctionPrefixPadding; - TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); -} - -TEST(Interception, OverrideFunction) { - TestOverrideFunction override = OverrideFunction; - FunctionPrefixKind prefix = FunctionPrefixNone; - TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); - - prefix = FunctionPrefixPadding; - TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); - - prefix = FunctionPrefixHotPatch; - TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); - - prefix = FunctionPrefixDetour; - TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); - TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix); -} - -template<class T> -static void TestIdentityFunctionMultiplePatching( - const T &code, - TestOverrideFunction override, - FunctionPrefixKind prefix_kind = FunctionPrefixNone) { - uptr identity_address; - LoadActiveCode(code, &identity_address, prefix_kind); - - // Patch the function. - uptr real_identity_address = 0; - bool success = override(identity_address, - (uptr)&InterceptorFunction, - &real_identity_address); - EXPECT_TRUE(success); - EXPECT_NE(0U, real_identity_address); - - // Re-patching the function should not work. - success = override(identity_address, - (uptr)&InterceptorFunction, - &real_identity_address); - EXPECT_FALSE(success); - - TestOnlyReleaseTrampolineRegions(); -} - -TEST(Interception, OverrideFunctionMultiplePatchingIsFailing) { -#if !SANITIZER_WINDOWS64 - TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue, - OverrideFunctionWithDetour, - FunctionPrefixDetour); -#endif - - TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov, - OverrideFunctionWithHotPatch, - FunctionPrefixHotPatch); - - TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop, - OverrideFunctionWithTrampoline, - FunctionPrefixPadding); -} - -TEST(Interception, OverrideFunctionTwice) { - uptr identity_address1; - LoadActiveCode(kIdentityTwice, &identity_address1); - uptr identity_address2 = identity_address1 + kIdentityTwiceOffset; - IdentityFunction identity1 = (IdentityFunction)identity_address1; - IdentityFunction identity2 = (IdentityFunction)identity_address2; - - // Patch the two functions. - uptr real_identity_address = 0; - EXPECT_TRUE(OverrideFunction(identity_address1, - (uptr)&InterceptorFunction, - &real_identity_address)); - EXPECT_TRUE(OverrideFunction(identity_address2, - (uptr)&InterceptorFunction, - &real_identity_address)); - IdentityFunction real_identity = (IdentityFunction)real_identity_address; - InterceptedRealFunction = real_identity; - - // Calling the redirected function. - InterceptorFunctionCalled = 0; - EXPECT_EQ(42, identity1(42)); - EXPECT_EQ(42, identity2(42)); - EXPECT_EQ(2, InterceptorFunctionCalled); - - TestOnlyReleaseTrampolineRegions(); -} - -template<class T> -static bool TestFunctionPatching( - const T &code, - TestOverrideFunction override, - FunctionPrefixKind prefix_kind = FunctionPrefixNone) { - uptr address; - LoadActiveCode(code, &address, prefix_kind); - uptr unused_real_address = 0; - bool result = override( - address, (uptr)&InterceptorFunction, &unused_real_address); - - TestOnlyReleaseTrampolineRegions(); - return result; -} - -TEST(Interception, PatchableFunction) { - TestOverrideFunction override = OverrideFunction; - // Test without function padding. - EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override)); -#if SANITIZER_WINDOWS64 - EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); -#else - EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override)); -#endif - EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override)); - -#if SANITIZER_WINDOWS64 - EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override)); -#endif - - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); -} - -#if !SANITIZER_WINDOWS64 -TEST(Interception, PatchableFunctionWithDetour) { - TestOverrideFunction override = OverrideFunctionWithDetour; - // Without the prefix, no function can be detoured. - EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override)); - EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override)); - EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); - EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); - - // With the prefix, all functions can be detoured. - FunctionPrefixKind prefix = FunctionPrefixDetour; - EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); -} -#endif // !SANITIZER_WINDOWS64 - -TEST(Interception, PatchableFunctionWithRedirectJump) { - TestOverrideFunction override = OverrideFunctionWithRedirectJump; - EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override)); - EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override)); - EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override)); -} - -TEST(Interception, PatchableFunctionWithHotPatch) { - TestOverrideFunction override = OverrideFunctionWithHotPatch; - FunctionPrefixKind prefix = FunctionPrefixHotPatch; - - EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix)); - - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); -} - -TEST(Interception, PatchableFunctionWithTrampoline) { - TestOverrideFunction override = OverrideFunctionWithTrampoline; - FunctionPrefixKind prefix = FunctionPrefixPadding; - - EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); -#if SANITIZER_WINDOWS64 - EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); -#else - EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); -#endif - EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix)); - - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); -} - -TEST(Interception, PatchableFunctionPadding) { - TestOverrideFunction override = OverrideFunction; - FunctionPrefixKind prefix = FunctionPrefixPadding; - - EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix)); -#if SANITIZER_WINDOWS64 - EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); -#else - EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix)); -#endif - EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix)); - - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); - EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix)); - EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); -} - -TEST(Interception, EmptyExportTable) { - // We try to get a pointer to a function from an executable that doesn't - // export any symbol (empty export table). - uptr FunPtr = InternalGetProcAddress((void *)GetModuleHandleA(0), "example"); - EXPECT_EQ(0U, FunPtr); -} - -} // namespace __interception - -#endif // SANITIZER_WINDOWS -#endif // #if !SANITIZER_DEBUG diff --git a/lib/lsan/.clang-format b/lib/lsan/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/lsan/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/lsan/CMakeLists.txt b/lib/lsan/CMakeLists.txt deleted file mode 100644 index 34f686135ac47..0000000000000 --- a/lib/lsan/CMakeLists.txt +++ /dev/null @@ -1,78 +0,0 @@ -include_directories(..) - -set(LSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF LSAN_CFLAGS) - -set(LSAN_COMMON_SOURCES - lsan_common.cc - lsan_common_linux.cc - lsan_common_mac.cc) - -set(LSAN_SOURCES - lsan.cc - lsan_allocator.cc - lsan_linux.cc - lsan_interceptors.cc - lsan_mac.cc - lsan_malloc_mac.cc - lsan_preinit.cc - lsan_thread.cc) - -set(LSAN_HEADERS - lsan.h - lsan_allocator.h - lsan_common.h - lsan_flags.inc - lsan_thread.h) - -set(LSAN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - -add_compiler_rt_object_libraries(RTLSanCommon - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${LSAN_COMMON_SUPPORTED_ARCH} - SOURCES ${LSAN_COMMON_SOURCES} - ADDITIONAL_HEADERS ${LSAN_HEADERS} - CFLAGS ${LSAN_CFLAGS}) - -if(COMPILER_RT_HAS_LSAN) - add_compiler_rt_component(lsan) - if(APPLE) - set(LSAN_LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS}) - - add_weak_symbols("lsan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) - - add_compiler_rt_runtime(clang_rt.lsan - SHARED - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${LSAN_SUPPORTED_ARCH} - SOURCES ${LSAN_SOURCES} - ADDITIONAL_HEADERS ${LSAN_HEADERS} - OBJECT_LIBS RTLSanCommon - RTInterception - RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - CFLAGS ${LSAN_CFLAGS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} - LINK_LIBS ${LSAN_LINK_LIBS} - PARENT_TARGET lsan) - else() - foreach(arch ${LSAN_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.lsan - STATIC - ARCHS ${arch} - SOURCES ${LSAN_SOURCES} - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> - $<TARGET_OBJECTS:RTLSanCommon.${arch}> - ADDITIONAL_HEADERS ${LSAN_HEADERS} - CFLAGS ${LSAN_CFLAGS} - PARENT_TARGET lsan) - endforeach() - endif() -endif() diff --git a/lib/msan/.clang-format b/lib/msan/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/msan/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/msan/CMakeLists.txt b/lib/msan/CMakeLists.txt deleted file mode 100644 index 15cc513c20e94..0000000000000 --- a/lib/msan/CMakeLists.txt +++ /dev/null @@ -1,86 +0,0 @@ -include_directories(..) - -# Runtime library sources and build flags. -set(MSAN_RTL_SOURCES - msan.cc - msan_allocator.cc - msan_chained_origin_depot.cc - msan_interceptors.cc - msan_linux.cc - msan_report.cc - msan_thread.cc - msan_poisoning.cc - ) - -set(MSAN_RTL_CXX_SOURCES - msan_new_delete.cc) - -set(MSAN_RTL_HEADERS - msan.h - msan_allocator.h - msan_chained_origin_depot.h - msan_flags.h - msan_flags.inc - msan_interface_internal.h - msan_origin.h - msan_poisoning.h - msan_report.h - msan_thread.h) - -set(MSAN_RTL_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC -ftls-model=initial-exec MSAN_RTL_CFLAGS) -endif() -append_rtti_flag(OFF MSAN_RTL_CFLAGS) -if(NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - append_list_if(COMPILER_RT_HAS_FPIE_FLAG -fPIE MSAN_RTL_CFLAGS) -endif() -# Prevent clang from generating libc calls. -append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding MSAN_RTL_CFLAGS) - -set(MSAN_RUNTIME_LIBRARIES) - -# Static runtime library. -add_compiler_rt_component(msan) - -foreach(arch ${MSAN_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.msan - STATIC - ARCHS ${arch} - SOURCES ${MSAN_RTL_SOURCES} - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> - $<TARGET_OBJECTS:RTUbsan.${arch}> - ADDITIONAL_HEADERS ${MSAN_RTL_HEADERS} - CFLAGS ${MSAN_RTL_CFLAGS} - PARENT_TARGET msan) - add_compiler_rt_runtime(clang_rt.msan_cxx - STATIC - ARCHS ${arch} - SOURCES ${MSAN_RTL_CXX_SOURCES} - $<TARGET_OBJECTS:RTUbsan_cxx.${arch}> - ADDITIONAL_HEADERS ${MSAN_RTL_HEADERS} - CFLAGS ${MSAN_RTL_CFLAGS} - PARENT_TARGET msan) - list(APPEND MSAN_RUNTIME_LIBRARIES clang_rt.msan-${arch} - clang_rt.msan_cxx-${arch}) - if(SANITIZER_USE_SYMBOLS) - add_sanitizer_rt_symbols(clang_rt.msan - ARCHS ${arch} - EXTRA msan.syms.extra) - add_sanitizer_rt_symbols(clang_rt.msan_cxx - ARCHS ${arch} - EXTRA msan.syms.extra) - add_dependencies(msan clang_rt.msan-${arch}-symbols - clang_rt.msan_cxx-${arch}-symbols) - endif() -endforeach() - -add_compiler_rt_resource_file(msan_blacklist msan_blacklist.txt msan) - -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/lib/msan/tests/CMakeLists.txt b/lib/msan/tests/CMakeLists.txt deleted file mode 100644 index e9f4e34bfe617..0000000000000 --- a/lib/msan/tests/CMakeLists.txt +++ /dev/null @@ -1,142 +0,0 @@ -include(CheckCXXCompilerFlag) -include(CompilerRTCompile) -include(CompilerRTLink) - -include_directories(..) -include_directories(../..) - -set(MSAN_LIBCXX_CFLAGS - -fsanitize=memory - -fsanitize-memory-track-origins - -Wno-pedantic) - -# Unittest sources and build flags. -set(MSAN_UNITTEST_SOURCES msan_test.cc msan_test_main.cc) -set(MSAN_LOADABLE_SOURCE msan_loadable.cc) -set(MSAN_UNITTEST_HEADERS - msan_test_config.h - ../../../include/sanitizer/msan_interface.h -) -set(MSAN_UNITTEST_COMMON_CFLAGS - -nostdinc++ - -isystem ${COMPILER_RT_LIBCXX_PATH}/include - ${COMPILER_RT_UNITTEST_CFLAGS} - ${COMPILER_RT_GTEST_CFLAGS} - -I${COMPILER_RT_SOURCE_DIR}/include - -I${COMPILER_RT_SOURCE_DIR}/lib - -I${COMPILER_RT_SOURCE_DIR}/lib/msan - -g - -O2 - -fno-exceptions - -fno-omit-frame-pointer - -mno-omit-leaf-frame-pointer - -Wno-deprecated-declarations - -Wno-unused-variable - -Wno-zero-length-array - -Wno-uninitialized - -Werror=sign-compare - -Wno-gnu-zero-variadic-macro-arguments -) -# Remove -stdlib= which is unused when passing -nostdinc++. -string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - -set(MSAN_UNITTEST_INSTRUMENTED_CFLAGS - ${MSAN_UNITTEST_COMMON_CFLAGS} - -fsanitize=memory - -fsanitize-memory-track-origins - -mllvm -msan-keep-going=1 -) -set(MSAN_UNITTEST_LINK_FLAGS - -fsanitize=memory - # Don't need -stdlib=libc++ because we explicitly list libc++.so in the linker - # inputs. - # FIXME: we build libcxx without cxxabi and need libstdc++ to provide it. - -lstdc++ -) - -append_list_if(COMPILER_RT_HAS_LIBDL -ldl MSAN_UNITTEST_LINK_FLAGS) - -macro(msan_compile obj_list source arch kind cflags) - sanitizer_test_compile( - ${obj_list} ${source} ${arch} - KIND ${kind} - COMPILE_DEPS ${MSAN_UNITTEST_HEADERS} - DEPS gtest msan - CFLAGS ${MSAN_UNITTEST_INSTRUMENTED_CFLAGS} ${cflags} - ) -endmacro() - -macro(msan_link_shared so_list so_name arch kind) - cmake_parse_arguments(SOURCE "" "" "OBJECTS;LINK_FLAGS;DEPS" ${ARGN}) - set(output_so "${CMAKE_CURRENT_BINARY_DIR}/${so_name}.${arch}${kind}.so") - get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS) - if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND SOURCE_DEPS msan) - endif() - clang_link_shared(${output_so} - OBJECTS ${SOURCE_OBJECTS} - LINK_FLAGS ${TARGET_LINK_FLAGS} ${SOURCE_LINK_FLAGS} - DEPS ${SOURCE_DEPS}) - list(APPEND ${so_list} ${output_so}) -endmacro() - -# Main MemorySanitizer unit tests. -add_custom_target(MsanUnitTests) -set_target_properties(MsanUnitTests PROPERTIES FOLDER "MSan unit tests") - -# Adds MSan unit tests and benchmarks for architecture. -macro(add_msan_tests_for_arch arch kind cflags) - # Build gtest instrumented with MSan. - set(MSAN_INST_GTEST) - msan_compile(MSAN_INST_GTEST ${COMPILER_RT_GTEST_SOURCE} ${arch} "${kind}" - "${cflags}") - - # Instrumented tests. - set(MSAN_INST_TEST_OBJECTS) - foreach (SOURCE ${MSAN_UNITTEST_SOURCES}) - msan_compile(MSAN_INST_TEST_OBJECTS ${SOURCE} ${arch} "${kind}" "${cflags}") - endforeach(SOURCE) - - # Instrumented loadable module objects. - set(MSAN_INST_LOADABLE_OBJECTS) - msan_compile(MSAN_INST_LOADABLE_OBJECTS ${MSAN_LOADABLE_SOURCE} ${arch} "${kind}" - "-fPIC;${cflags}") - - # Instrumented loadable library tests. - set(MSAN_LOADABLE_SO) - msan_link_shared(MSAN_LOADABLE_SO "libmsan_loadable" ${arch} "${kind}" - OBJECTS ${MSAN_INST_LOADABLE_OBJECTS} - DEPS ${MSAN_INST_LOADABLE_OBJECTS}) - - set(MSAN_TEST_OBJECTS ${MSAN_INST_TEST_OBJECTS} ${MSAN_INST_GTEST}) - set(MSAN_TEST_DEPS ${MSAN_TEST_OBJECTS} libcxx_msan_${arch}-build - ${MSAN_LOADABLE_SO}) - if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND MSAN_TEST_DEPS msan) - endif() - get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS) - add_compiler_rt_test(MsanUnitTests "Msan-${arch}${kind}-Test" ${arch} - OBJECTS ${MSAN_TEST_OBJECTS} ${MSAN_LIBCXX_SO} - DEPS ${MSAN_TEST_DEPS} - LINK_FLAGS ${MSAN_UNITTEST_LINK_FLAGS} - ${TARGET_LINK_FLAGS} - "-Wl,-rpath=${CMAKE_CURRENT_BINARY_DIR}" - "-Wl,-rpath=${LIBCXX_PREFIX}/lib") -endmacro() - -# We should only build MSan unit tests if we can build instrumented libcxx. -if(COMPILER_RT_CAN_EXECUTE_TESTS AND COMPILER_RT_LIBCXX_PATH) - foreach(arch ${MSAN_SUPPORTED_ARCH}) - get_target_flags_for_arch(${arch} TARGET_CFLAGS) - set(LIBCXX_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/../libcxx_msan_${arch}) - add_custom_libcxx(libcxx_msan_${arch} ${LIBCXX_PREFIX} - DEPS ${MSAN_RUNTIME_LIBRARIES} - CFLAGS ${MSAN_LIBCXX_CFLAGS} ${TARGET_CFLAGS} - USE_TOOLCHAIN) - set(MSAN_LIBCXX_SO ${LIBCXX_PREFIX}/lib/libc++.so) - - add_msan_tests_for_arch(${arch} "" "") - add_msan_tests_for_arch(${arch} "-with-call" - "-mllvm;-msan-instrumentation-with-call-threshold=0") - endforeach() -endif() diff --git a/lib/msan/tests/msan_loadable.cc b/lib/msan/tests/msan_loadable.cc deleted file mode 100644 index 06e880f90dee1..0000000000000 --- a/lib/msan/tests/msan_loadable.cc +++ /dev/null @@ -1,27 +0,0 @@ -//===-- msan_loadable.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of MemorySanitizer. -// -// MemorySanitizer unit tests. -//===----------------------------------------------------------------------===// - -#include "msan/msan_interface_internal.h" -#include <stdlib.h> - -static void *dso_global; - -// No name mangling. -extern "C" { - -void **get_dso_global() { - return &dso_global; -} - -} diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc deleted file mode 100644 index 19f46abdc5740..0000000000000 --- a/lib/msan/tests/msan_test.cc +++ /dev/null @@ -1,4639 +0,0 @@ -//===-- msan_test.cc ------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of MemorySanitizer. -// -// MemorySanitizer unit tests. -//===----------------------------------------------------------------------===// - -#ifndef MSAN_EXTERNAL_TEST_CONFIG -#include "msan_test_config.h" -#endif // MSAN_EXTERNAL_TEST_CONFIG - -#include "sanitizer_common/tests/sanitizer_test_utils.h" - -#include "sanitizer/allocator_interface.h" -#include "sanitizer/msan_interface.h" - -#if defined(__FreeBSD__) -# define _KERNEL // To declare 'shminfo' structure. -# include <sys/shm.h> -# undef _KERNEL -extern "C" { -// <sys/shm.h> doesn't declare these functions in _KERNEL mode. -void *shmat(int, const void *, int); -int shmget(key_t, size_t, int); -int shmctl(int, int, struct shmid_ds *); -int shmdt(const void *); -} -#endif - -#include <inttypes.h> -#include <stdlib.h> -#include <stdarg.h> -#include <stdio.h> -#include <wchar.h> -#include <math.h> - -#include <arpa/inet.h> -#include <dlfcn.h> -#include <grp.h> -#include <unistd.h> -#include <link.h> -#include <limits.h> -#include <sys/time.h> -#include <poll.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/resource.h> -#include <sys/ioctl.h> -#include <sys/statvfs.h> -#include <sys/utsname.h> -#include <sys/mman.h> -#include <dirent.h> -#include <pwd.h> -#include <sys/socket.h> -#include <netdb.h> -#include <wordexp.h> -#include <sys/ipc.h> -#include <sys/shm.h> - -#if defined(__NetBSD__) -# include <signal.h> -# include <netinet/in.h> -# include <sys/uio.h> -# include <sys/mount.h> -# include <sys/sysctl.h> -# include <net/if.h> -# include <net/if_ether.h> -#elif defined(__FreeBSD__) -# include <signal.h> -# include <netinet/in.h> -# include <pthread_np.h> -# include <sys/uio.h> -# include <sys/mount.h> -# include <sys/sysctl.h> -# include <net/ethernet.h> -# define f_namelen f_namemax // FreeBSD names this statfs field so. -# define cpu_set_t cpuset_t -extern "C" { -// FreeBSD's <ssp/string.h> defines mempcpy() to be a macro expanding into -// a __builtin___mempcpy_chk() call, but since Msan RTL defines it as an -// ordinary function, we can declare it here to complete the tests. -void *mempcpy(void *dest, const void *src, size_t n); -} -#else -# include <malloc.h> -# include <sys/sysinfo.h> -# include <sys/vfs.h> -# include <mntent.h> -# include <netinet/ether.h> -# if defined(__linux__) -# include <sys/uio.h> -# endif -#endif - -#if defined(__i386__) || defined(__x86_64__) -# include <emmintrin.h> -# define MSAN_HAS_M128 1 -#else -# define MSAN_HAS_M128 0 -#endif - -#ifdef __AVX2__ -# include <immintrin.h> -#endif - -#if defined(__FreeBSD__) || defined(__NetBSD__) -# define FILE_TO_READ "/bin/cat" -# define DIR_TO_READ "/bin" -# define SUBFILE_TO_READ "cat" -# define SYMLINK_TO_READ "/usr/bin/tar" -# define SUPERUSER_GROUP "wheel" -#else -# define FILE_TO_READ "/proc/self/stat" -# define DIR_TO_READ "/proc/self" -# define SUBFILE_TO_READ "stat" -# define SYMLINK_TO_READ "/proc/self/exe" -# define SUPERUSER_GROUP "root" -#endif - -static uintptr_t GetPageSize() { - return sysconf(_SC_PAGESIZE); -} - -const size_t kMaxPathLength = 4096; - -typedef unsigned char U1; -typedef unsigned short U2; // NOLINT -typedef unsigned int U4; -typedef unsigned long long U8; // NOLINT -typedef signed char S1; -typedef signed short S2; // NOLINT -typedef signed int S4; -typedef signed long long S8; // NOLINT -#define NOINLINE __attribute__((noinline)) -#define INLINE __attribute__((always_inline)) - -static bool TrackingOrigins() { - S8 x; - __msan_set_origin(&x, sizeof(x), 0x1234); - U4 origin = __msan_get_origin(&x); - __msan_set_origin(&x, sizeof(x), 0); - return __msan_origin_is_descendant_or_same(origin, 0x1234); -} - -#define EXPECT_ORIGIN(expected, origin) \ - EXPECT_TRUE(__msan_origin_is_descendant_or_same((origin), (expected))) - -#define EXPECT_UMR(action) \ - do { \ - __msan_set_expect_umr(1); \ - action; \ - __msan_set_expect_umr(0); \ - } while (0) - -#define EXPECT_UMR_O(action, origin) \ - do { \ - __msan_set_expect_umr(1); \ - action; \ - __msan_set_expect_umr(0); \ - if (TrackingOrigins()) EXPECT_ORIGIN(origin, __msan_get_umr_origin()); \ - } while (0) - -#define EXPECT_POISONED(x) ExpectPoisoned(x) - -template<typename T> -void ExpectPoisoned(const T& t) { - EXPECT_NE(-1, __msan_test_shadow((void*)&t, sizeof(t))); -} - -#define EXPECT_POISONED_O(x, origin) \ - ExpectPoisonedWithOrigin(x, origin) - -template<typename T> -void ExpectPoisonedWithOrigin(const T& t, unsigned origin) { - EXPECT_NE(-1, __msan_test_shadow((void*)&t, sizeof(t))); - if (TrackingOrigins()) EXPECT_ORIGIN(origin, __msan_get_origin((void *)&t)); -} - -#define EXPECT_NOT_POISONED(x) EXPECT_EQ(true, TestForNotPoisoned((x))) -#define EXPECT_NOT_POISONED2(data, size) \ - EXPECT_EQ(true, TestForNotPoisoned((data), (size))) - -bool TestForNotPoisoned(const void *data, size_t size) { - return __msan_test_shadow(data, size) == -1; -} - -template<typename T> -bool TestForNotPoisoned(const T& t) { - return TestForNotPoisoned((void *)&t, sizeof(t)); -} - -static U8 poisoned_array[100]; -template<class T> -T *GetPoisoned(int i = 0, T val = 0) { - T *res = (T*)&poisoned_array[i]; - *res = val; - __msan_poison(&poisoned_array[i], sizeof(T)); - return res; -} - -template<class T> -T *GetPoisonedO(int i, U4 origin, T val = 0) { - T *res = (T*)&poisoned_array[i]; - *res = val; - __msan_poison(&poisoned_array[i], sizeof(T)); - __msan_set_origin(&poisoned_array[i], sizeof(T), origin); - return res; -} - -template<typename T> -T Poisoned(T v = 0, T s = (T)(-1)) { - __msan_partial_poison(&v, &s, sizeof(T)); - return v; -} - -template<class T> NOINLINE T ReturnPoisoned() { return *GetPoisoned<T>(); } - -static volatile int g_one = 1; -static volatile int g_zero = 0; -static volatile int g_0 = 0; -static volatile int g_1 = 1; - -S4 a_s4[100]; -S8 a_s8[100]; - -// Check that malloc poisons memory. -// A lot of tests below depend on this. -TEST(MemorySanitizerSanity, PoisonInMalloc) { - int *x = (int*)malloc(sizeof(int)); - EXPECT_POISONED(*x); - free(x); -} - -TEST(MemorySanitizer, NegativeTest1) { - S4 *x = GetPoisoned<S4>(); - if (g_one) - *x = 0; - EXPECT_NOT_POISONED(*x); -} - -TEST(MemorySanitizer, PositiveTest1) { - // Load to store. - EXPECT_POISONED(*GetPoisoned<S1>()); - EXPECT_POISONED(*GetPoisoned<S2>()); - EXPECT_POISONED(*GetPoisoned<S4>()); - EXPECT_POISONED(*GetPoisoned<S8>()); - - // S->S conversions. - EXPECT_POISONED(*GetPoisoned<S1>()); - EXPECT_POISONED(*GetPoisoned<S1>()); - EXPECT_POISONED(*GetPoisoned<S1>()); - - EXPECT_POISONED(*GetPoisoned<S2>()); - EXPECT_POISONED(*GetPoisoned<S2>()); - EXPECT_POISONED(*GetPoisoned<S2>()); - - EXPECT_POISONED(*GetPoisoned<S4>()); - EXPECT_POISONED(*GetPoisoned<S4>()); - EXPECT_POISONED(*GetPoisoned<S4>()); - - EXPECT_POISONED(*GetPoisoned<S8>()); - EXPECT_POISONED(*GetPoisoned<S8>()); - EXPECT_POISONED(*GetPoisoned<S8>()); - - // ZExt - EXPECT_POISONED(*GetPoisoned<U1>()); - EXPECT_POISONED(*GetPoisoned<U1>()); - EXPECT_POISONED(*GetPoisoned<U1>()); - EXPECT_POISONED(*GetPoisoned<U2>()); - EXPECT_POISONED(*GetPoisoned<U2>()); - EXPECT_POISONED(*GetPoisoned<U4>()); - - // Unary ops. - EXPECT_POISONED(- *GetPoisoned<S4>()); - - EXPECT_UMR(a_s4[g_zero] = 100 / *GetPoisoned<S4>(0, 1)); - - - a_s4[g_zero] = 1 - *GetPoisoned<S4>(); - a_s4[g_zero] = 1 + *GetPoisoned<S4>(); -} - -TEST(MemorySanitizer, Phi1) { - S4 c; - if (g_one) { - c = *GetPoisoned<S4>(); - } else { - break_optimization(0); - c = 0; - } - EXPECT_POISONED(c); -} - -TEST(MemorySanitizer, Phi2) { - S4 i = *GetPoisoned<S4>(); - S4 n = g_one; - EXPECT_UMR(for (; i < g_one; i++);); - EXPECT_POISONED(i); -} - -NOINLINE void Arg1ExpectUMR(S4 a1) { EXPECT_POISONED(a1); } -NOINLINE void Arg2ExpectUMR(S4 a1, S4 a2) { EXPECT_POISONED(a2); } -NOINLINE void Arg3ExpectUMR(S1 a1, S4 a2, S8 a3) { EXPECT_POISONED(a3); } - -TEST(MemorySanitizer, ArgTest) { - Arg1ExpectUMR(*GetPoisoned<S4>()); - Arg2ExpectUMR(0, *GetPoisoned<S4>()); - Arg3ExpectUMR(0, 1, *GetPoisoned<S8>()); -} - - -TEST(MemorySanitizer, CallAndRet) { - ReturnPoisoned<S1>(); - ReturnPoisoned<S2>(); - ReturnPoisoned<S4>(); - ReturnPoisoned<S8>(); - - EXPECT_POISONED(ReturnPoisoned<S1>()); - EXPECT_POISONED(ReturnPoisoned<S2>()); - EXPECT_POISONED(ReturnPoisoned<S4>()); - EXPECT_POISONED(ReturnPoisoned<S8>()); -} - -// malloc() in the following test may be optimized to produce a compile-time -// undef value. Check that we trap on the volatile assignment anyway. -TEST(MemorySanitizer, DISABLED_MallocNoIdent) { - S4 *x = (int*)malloc(sizeof(S4)); - EXPECT_POISONED(*x); - free(x); -} - -TEST(MemorySanitizer, Malloc) { - S4 *x = (int*)Ident(malloc(sizeof(S4))); - EXPECT_POISONED(*x); - free(x); -} - -TEST(MemorySanitizer, Realloc) { - S4 *x = (int*)Ident(realloc(0, sizeof(S4))); - EXPECT_POISONED(x[0]); - x[0] = 1; - x = (int*)Ident(realloc(x, 2 * sizeof(S4))); - EXPECT_NOT_POISONED(x[0]); // Ok, was inited before. - EXPECT_POISONED(x[1]); - x = (int*)Ident(realloc(x, 3 * sizeof(S4))); - EXPECT_NOT_POISONED(x[0]); // Ok, was inited before. - EXPECT_POISONED(x[2]); - EXPECT_POISONED(x[1]); - x[2] = 1; // Init this here. Check that after realloc it is poisoned again. - x = (int*)Ident(realloc(x, 2 * sizeof(S4))); - EXPECT_NOT_POISONED(x[0]); // Ok, was inited before. - EXPECT_POISONED(x[1]); - x = (int*)Ident(realloc(x, 3 * sizeof(S4))); - EXPECT_POISONED(x[1]); - EXPECT_POISONED(x[2]); - free(x); -} - -TEST(MemorySanitizer, Calloc) { - S4 *x = (int*)Ident(calloc(1, sizeof(S4))); - EXPECT_NOT_POISONED(*x); // Should not be poisoned. - EXPECT_EQ(0, *x); - free(x); -} - -TEST(MemorySanitizer, CallocReturnsZeroMem) { - size_t sizes[] = {16, 1000, 10000, 100000, 2100000}; - for (size_t s = 0; s < sizeof(sizes)/sizeof(sizes[0]); s++) { - size_t size = sizes[s]; - for (size_t iter = 0; iter < 5; iter++) { - char *x = Ident((char*)calloc(1, size)); - EXPECT_EQ(x[0], 0); - EXPECT_EQ(x[size - 1], 0); - EXPECT_EQ(x[size / 2], 0); - EXPECT_EQ(x[size / 3], 0); - EXPECT_EQ(x[size / 4], 0); - memset(x, 0x42, size); - free(Ident(x)); - } - } -} - -TEST(MemorySanitizer, AndOr) { - U4 *p = GetPoisoned<U4>(); - // We poison two bytes in the midle of a 4-byte word to make the test - // correct regardless of endianness. - ((U1*)p)[1] = 0; - ((U1*)p)[2] = 0xff; - EXPECT_NOT_POISONED(*p & 0x00ffff00); - EXPECT_NOT_POISONED(*p & 0x00ff0000); - EXPECT_NOT_POISONED(*p & 0x0000ff00); - EXPECT_POISONED(*p & 0xff000000); - EXPECT_POISONED(*p & 0x000000ff); - EXPECT_POISONED(*p & 0x0000ffff); - EXPECT_POISONED(*p & 0xffff0000); - - EXPECT_NOT_POISONED(*p | 0xff0000ff); - EXPECT_NOT_POISONED(*p | 0xff00ffff); - EXPECT_NOT_POISONED(*p | 0xffff00ff); - EXPECT_POISONED(*p | 0xff000000); - EXPECT_POISONED(*p | 0x000000ff); - EXPECT_POISONED(*p | 0x0000ffff); - EXPECT_POISONED(*p | 0xffff0000); - - EXPECT_POISONED(*GetPoisoned<bool>() & *GetPoisoned<bool>()); -} - -template<class T> -static bool applyNot(T value, T shadow) { - __msan_partial_poison(&value, &shadow, sizeof(T)); - return !value; -} - -TEST(MemorySanitizer, Not) { - EXPECT_NOT_POISONED(applyNot<U4>(0x0, 0x0)); - EXPECT_NOT_POISONED(applyNot<U4>(0xFFFFFFFF, 0x0)); - EXPECT_POISONED(applyNot<U4>(0xFFFFFFFF, 0xFFFFFFFF)); - EXPECT_NOT_POISONED(applyNot<U4>(0xFF000000, 0x0FFFFFFF)); - EXPECT_NOT_POISONED(applyNot<U4>(0xFF000000, 0x00FFFFFF)); - EXPECT_NOT_POISONED(applyNot<U4>(0xFF000000, 0x0000FFFF)); - EXPECT_NOT_POISONED(applyNot<U4>(0xFF000000, 0x00000000)); - EXPECT_POISONED(applyNot<U4>(0xFF000000, 0xFF000000)); - EXPECT_NOT_POISONED(applyNot<U4>(0xFF800000, 0xFF000000)); - EXPECT_POISONED(applyNot<U4>(0x00008000, 0x00008000)); - - EXPECT_NOT_POISONED(applyNot<U1>(0x0, 0x0)); - EXPECT_NOT_POISONED(applyNot<U1>(0xFF, 0xFE)); - EXPECT_NOT_POISONED(applyNot<U1>(0xFF, 0x0)); - EXPECT_POISONED(applyNot<U1>(0xFF, 0xFF)); - - EXPECT_POISONED(applyNot<void*>((void*)0xFFFFFF, (void*)(-1))); - EXPECT_NOT_POISONED(applyNot<void*>((void*)0xFFFFFF, (void*)(-2))); -} - -TEST(MemorySanitizer, Shift) { - U4 *up = GetPoisoned<U4>(); - ((U1*)up)[0] = 0; - ((U1*)up)[3] = 0xff; - EXPECT_NOT_POISONED(*up >> 30); - EXPECT_NOT_POISONED(*up >> 24); - EXPECT_POISONED(*up >> 23); - EXPECT_POISONED(*up >> 10); - - EXPECT_NOT_POISONED(*up << 30); - EXPECT_NOT_POISONED(*up << 24); - EXPECT_POISONED(*up << 23); - EXPECT_POISONED(*up << 10); - - S4 *sp = (S4*)up; - EXPECT_NOT_POISONED(*sp >> 30); - EXPECT_NOT_POISONED(*sp >> 24); - EXPECT_POISONED(*sp >> 23); - EXPECT_POISONED(*sp >> 10); - - sp = GetPoisoned<S4>(); - ((S1*)sp)[1] = 0; - ((S1*)sp)[2] = 0; - EXPECT_POISONED(*sp >> 31); - - EXPECT_POISONED(100 >> *GetPoisoned<S4>()); - EXPECT_POISONED(100U >> *GetPoisoned<S4>()); -} - -NOINLINE static int GetPoisonedZero() { - int *zero = new int; - *zero = 0; - __msan_poison(zero, sizeof(*zero)); - int res = *zero; - delete zero; - return res; -} - -TEST(MemorySanitizer, LoadFromDirtyAddress) { - int *a = new int; - *a = 0; - EXPECT_UMR(break_optimization((void*)(U8)a[GetPoisonedZero()])); - delete a; -} - -TEST(MemorySanitizer, StoreToDirtyAddress) { - int *a = new int; - EXPECT_UMR(a[GetPoisonedZero()] = 0); - break_optimization(a); - delete a; -} - - -NOINLINE void StackTestFunc() { - S4 p4; - S4 ok4 = 1; - S2 p2; - S2 ok2 = 1; - S1 p1; - S1 ok1 = 1; - break_optimization(&p4); - break_optimization(&ok4); - break_optimization(&p2); - break_optimization(&ok2); - break_optimization(&p1); - break_optimization(&ok1); - - EXPECT_POISONED(p4); - EXPECT_POISONED(p2); - EXPECT_POISONED(p1); - EXPECT_NOT_POISONED(ok1); - EXPECT_NOT_POISONED(ok2); - EXPECT_NOT_POISONED(ok4); -} - -TEST(MemorySanitizer, StackTest) { - StackTestFunc(); -} - -NOINLINE void StackStressFunc() { - int foo[10000]; - break_optimization(foo); -} - -TEST(MemorySanitizer, DISABLED_StackStressTest) { - for (int i = 0; i < 1000000; i++) - StackStressFunc(); -} - -template<class T> -void TestFloatingPoint() { - static volatile T v; - static T g[100]; - break_optimization(&g); - T *x = GetPoisoned<T>(); - T *y = GetPoisoned<T>(1); - EXPECT_POISONED(*x); - EXPECT_POISONED((long long)*x); - EXPECT_POISONED((int)*x); - g[0] = *x; - g[1] = *x + *y; - g[2] = *x - *y; - g[3] = *x * *y; -} - -TEST(MemorySanitizer, FloatingPointTest) { - TestFloatingPoint<float>(); - TestFloatingPoint<double>(); -} - -TEST(MemorySanitizer, DynMem) { - S4 x = 0; - S4 *y = GetPoisoned<S4>(); - memcpy(y, &x, g_one * sizeof(S4)); - EXPECT_NOT_POISONED(*y); -} - -static char *DynRetTestStr; - -TEST(MemorySanitizer, DynRet) { - ReturnPoisoned<S8>(); - EXPECT_NOT_POISONED(atoi("0")); -} - -TEST(MemorySanitizer, DynRet1) { - ReturnPoisoned<S8>(); -} - -struct LargeStruct { - S4 x[10]; -}; - -NOINLINE -LargeStruct LargeRetTest() { - LargeStruct res; - res.x[0] = *GetPoisoned<S4>(); - res.x[1] = *GetPoisoned<S4>(); - res.x[2] = *GetPoisoned<S4>(); - res.x[3] = *GetPoisoned<S4>(); - res.x[4] = *GetPoisoned<S4>(); - res.x[5] = *GetPoisoned<S4>(); - res.x[6] = *GetPoisoned<S4>(); - res.x[7] = *GetPoisoned<S4>(); - res.x[8] = *GetPoisoned<S4>(); - res.x[9] = *GetPoisoned<S4>(); - return res; -} - -TEST(MemorySanitizer, strcmp) { - char s1[10]; - char s2[10]; - strncpy(s1, "foo", 10); - s2[0] = 'f'; - s2[1] = 'n'; - EXPECT_GT(strcmp(s1, s2), 0); - s2[1] = 'o'; - int res; - EXPECT_UMR(res = strcmp(s1, s2)); - EXPECT_NOT_POISONED(res); - EXPECT_EQ(strncmp(s1, s2, 1), 0); -} - -TEST(MemorySanitizer, LargeRet) { - LargeStruct a = LargeRetTest(); - EXPECT_POISONED(a.x[0]); - EXPECT_POISONED(a.x[9]); -} - -TEST(MemorySanitizer, strerror) { - char *buf = strerror(EINVAL); - EXPECT_NOT_POISONED(strlen(buf)); - buf = strerror(123456); - EXPECT_NOT_POISONED(strlen(buf)); -} - -TEST(MemorySanitizer, strerror_r) { - errno = 0; - char buf[1000]; - char *res = (char*) (size_t) strerror_r(EINVAL, buf, sizeof(buf)); - ASSERT_EQ(0, errno); - if (!res) res = buf; // POSIX version success. - EXPECT_NOT_POISONED(strlen(res)); -} - -TEST(MemorySanitizer, fread) { - char *x = new char[32]; - FILE *f = fopen(FILE_TO_READ, "r"); - ASSERT_TRUE(f != NULL); - fread(x, 1, 32, f); - EXPECT_NOT_POISONED(x[0]); - EXPECT_NOT_POISONED(x[16]); - EXPECT_NOT_POISONED(x[31]); - fclose(f); - delete[] x; -} - -TEST(MemorySanitizer, read) { - char *x = new char[32]; - int fd = open(FILE_TO_READ, O_RDONLY); - ASSERT_GT(fd, 0); - int sz = read(fd, x, 32); - ASSERT_EQ(sz, 32); - EXPECT_NOT_POISONED(x[0]); - EXPECT_NOT_POISONED(x[16]); - EXPECT_NOT_POISONED(x[31]); - close(fd); - delete[] x; -} - -TEST(MemorySanitizer, pread) { - char *x = new char[32]; - int fd = open(FILE_TO_READ, O_RDONLY); - ASSERT_GT(fd, 0); - int sz = pread(fd, x, 32, 0); - ASSERT_EQ(sz, 32); - EXPECT_NOT_POISONED(x[0]); - EXPECT_NOT_POISONED(x[16]); - EXPECT_NOT_POISONED(x[31]); - close(fd); - delete[] x; -} - -TEST(MemorySanitizer, readv) { - char buf[2011]; - struct iovec iov[2]; - iov[0].iov_base = buf + 1; - iov[0].iov_len = 5; - iov[1].iov_base = buf + 10; - iov[1].iov_len = 2000; - int fd = open(FILE_TO_READ, O_RDONLY); - ASSERT_GT(fd, 0); - int sz = readv(fd, iov, 2); - ASSERT_GE(sz, 0); - ASSERT_LE(sz, 5 + 2000); - ASSERT_GT((size_t)sz, iov[0].iov_len); - EXPECT_POISONED(buf[0]); - EXPECT_NOT_POISONED(buf[1]); - EXPECT_NOT_POISONED(buf[5]); - EXPECT_POISONED(buf[6]); - EXPECT_POISONED(buf[9]); - EXPECT_NOT_POISONED(buf[10]); - EXPECT_NOT_POISONED(buf[10 + (sz - 1) - 5]); - EXPECT_POISONED(buf[11 + (sz - 1) - 5]); - close(fd); -} - -TEST(MemorySanitizer, preadv) { - char buf[2011]; - struct iovec iov[2]; - iov[0].iov_base = buf + 1; - iov[0].iov_len = 5; - iov[1].iov_base = buf + 10; - iov[1].iov_len = 2000; - int fd = open(FILE_TO_READ, O_RDONLY); - ASSERT_GT(fd, 0); - int sz = preadv(fd, iov, 2, 3); - ASSERT_GE(sz, 0); - ASSERT_LE(sz, 5 + 2000); - ASSERT_GT((size_t)sz, iov[0].iov_len); - EXPECT_POISONED(buf[0]); - EXPECT_NOT_POISONED(buf[1]); - EXPECT_NOT_POISONED(buf[5]); - EXPECT_POISONED(buf[6]); - EXPECT_POISONED(buf[9]); - EXPECT_NOT_POISONED(buf[10]); - EXPECT_NOT_POISONED(buf[10 + (sz - 1) - 5]); - EXPECT_POISONED(buf[11 + (sz - 1) - 5]); - close(fd); -} - -// FIXME: fails now. -TEST(MemorySanitizer, DISABLED_ioctl) { - struct winsize ws; - EXPECT_EQ(ioctl(2, TIOCGWINSZ, &ws), 0); - EXPECT_NOT_POISONED(ws.ws_col); -} - -TEST(MemorySanitizer, readlink) { - char *x = new char[1000]; - readlink(SYMLINK_TO_READ, x, 1000); - EXPECT_NOT_POISONED(x[0]); - delete [] x; -} - -TEST(MemorySanitizer, readlinkat) { - char *x = new char[1000]; - readlinkat(AT_FDCWD, SYMLINK_TO_READ, x, 1000); - EXPECT_NOT_POISONED(x[0]); - delete[] x; -} - -TEST(MemorySanitizer, stat) { - struct stat* st = new struct stat; - int res = stat(FILE_TO_READ, st); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(st->st_dev); - EXPECT_NOT_POISONED(st->st_mode); - EXPECT_NOT_POISONED(st->st_size); -} - -TEST(MemorySanitizer, fstatat) { - struct stat* st = new struct stat; - int dirfd = open(DIR_TO_READ, O_RDONLY); - ASSERT_GT(dirfd, 0); - int res = fstatat(dirfd, SUBFILE_TO_READ, st, 0); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(st->st_dev); - EXPECT_NOT_POISONED(st->st_mode); - EXPECT_NOT_POISONED(st->st_size); - close(dirfd); -} - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, statfs) { - struct statfs st; - int res = statfs("/", &st); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(st.f_type); - EXPECT_NOT_POISONED(st.f_bfree); - EXPECT_NOT_POISONED(st.f_namelen); -} -#endif - -TEST(MemorySanitizer, statvfs) { - struct statvfs st; - int res = statvfs("/", &st); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(st.f_bsize); - EXPECT_NOT_POISONED(st.f_blocks); - EXPECT_NOT_POISONED(st.f_bfree); - EXPECT_NOT_POISONED(st.f_namemax); -} - -TEST(MemorySanitizer, fstatvfs) { - struct statvfs st; - int fd = open("/", O_RDONLY | O_DIRECTORY); - int res = fstatvfs(fd, &st); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(st.f_bsize); - EXPECT_NOT_POISONED(st.f_blocks); - EXPECT_NOT_POISONED(st.f_bfree); - EXPECT_NOT_POISONED(st.f_namemax); - close(fd); -} - -TEST(MemorySanitizer, pipe) { - int* pipefd = new int[2]; - int res = pipe(pipefd); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(pipefd[0]); - EXPECT_NOT_POISONED(pipefd[1]); - close(pipefd[0]); - close(pipefd[1]); -} - -TEST(MemorySanitizer, pipe2) { - int* pipefd = new int[2]; - int res = pipe2(pipefd, O_NONBLOCK); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(pipefd[0]); - EXPECT_NOT_POISONED(pipefd[1]); - close(pipefd[0]); - close(pipefd[1]); -} - -TEST(MemorySanitizer, socketpair) { - int sv[2]; - int res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(sv[0]); - EXPECT_NOT_POISONED(sv[1]); - close(sv[0]); - close(sv[1]); -} - -TEST(MemorySanitizer, poll) { - int* pipefd = new int[2]; - int res = pipe(pipefd); - ASSERT_EQ(0, res); - - char data = 42; - res = write(pipefd[1], &data, 1); - ASSERT_EQ(1, res); - - pollfd fds[2]; - fds[0].fd = pipefd[0]; - fds[0].events = POLLIN; - fds[1].fd = pipefd[1]; - fds[1].events = POLLIN; - res = poll(fds, 2, 500); - ASSERT_EQ(1, res); - EXPECT_NOT_POISONED(fds[0].revents); - EXPECT_NOT_POISONED(fds[1].revents); - - close(pipefd[0]); - close(pipefd[1]); -} - -#if !defined (__FreeBSD__) && !defined (__NetBSD__) -TEST(MemorySanitizer, ppoll) { - int* pipefd = new int[2]; - int res = pipe(pipefd); - ASSERT_EQ(0, res); - - char data = 42; - res = write(pipefd[1], &data, 1); - ASSERT_EQ(1, res); - - pollfd fds[2]; - fds[0].fd = pipefd[0]; - fds[0].events = POLLIN; - fds[1].fd = pipefd[1]; - fds[1].events = POLLIN; - sigset_t ss; - sigemptyset(&ss); - res = ppoll(fds, 2, NULL, &ss); - ASSERT_EQ(1, res); - EXPECT_NOT_POISONED(fds[0].revents); - EXPECT_NOT_POISONED(fds[1].revents); - - close(pipefd[0]); - close(pipefd[1]); -} -#endif - -TEST(MemorySanitizer, poll_positive) { - int* pipefd = new int[2]; - int res = pipe(pipefd); - ASSERT_EQ(0, res); - - pollfd fds[2]; - fds[0].fd = pipefd[0]; - fds[0].events = POLLIN; - // fds[1].fd uninitialized - fds[1].events = POLLIN; - EXPECT_UMR(poll(fds, 2, 0)); - - close(pipefd[0]); - close(pipefd[1]); -} - -TEST(MemorySanitizer, bind_getsockname) { - int sock = socket(AF_UNIX, SOCK_STREAM, 0); - - struct sockaddr_in sai; - memset(&sai, 0, sizeof(sai)); - sai.sin_family = AF_UNIX; - int res = bind(sock, (struct sockaddr *)&sai, sizeof(sai)); - - ASSERT_EQ(0, res); - char buf[200]; - socklen_t addrlen; - EXPECT_UMR(getsockname(sock, (struct sockaddr *)&buf, &addrlen)); - - addrlen = sizeof(buf); - res = getsockname(sock, (struct sockaddr *)&buf, &addrlen); - EXPECT_NOT_POISONED(addrlen); - EXPECT_NOT_POISONED(buf[0]); - EXPECT_NOT_POISONED(buf[addrlen - 1]); - EXPECT_POISONED(buf[addrlen]); - close(sock); -} - -class SocketAddr { - public: - virtual ~SocketAddr() = default; - virtual struct sockaddr *ptr() = 0; - virtual size_t size() const = 0; - - template <class... Args> - static std::unique_ptr<SocketAddr> Create(int family, Args... args); -}; - -class SocketAddr4 : public SocketAddr { - public: - SocketAddr4() { EXPECT_POISONED(sai_); } - explicit SocketAddr4(uint16_t port) { - memset(&sai_, 0, sizeof(sai_)); - sai_.sin_family = AF_INET; - sai_.sin_port = port; - sai_.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } - - sockaddr *ptr() override { return reinterpret_cast<sockaddr *>(&sai_); } - - size_t size() const override { return sizeof(sai_); } - - private: - sockaddr_in sai_; -}; - -class SocketAddr6 : public SocketAddr { - public: - SocketAddr6() { EXPECT_POISONED(sai_); } - explicit SocketAddr6(uint16_t port) { - memset(&sai_, 0, sizeof(sai_)); - sai_.sin6_family = AF_INET6; - sai_.sin6_port = port; - sai_.sin6_addr = in6addr_loopback; - } - - sockaddr *ptr() override { return reinterpret_cast<sockaddr *>(&sai_); } - - size_t size() const override { return sizeof(sai_); } - - private: - sockaddr_in6 sai_; -}; - -template <class... Args> -std::unique_ptr<SocketAddr> SocketAddr::Create(int family, Args... args) { - if (family == AF_INET) - return std::unique_ptr<SocketAddr>(new SocketAddr4(args...)); - return std::unique_ptr<SocketAddr>(new SocketAddr6(args...)); -} - -class MemorySanitizerIpTest : public ::testing::TestWithParam<int> { - public: - void SetUp() override { - ASSERT_TRUE(GetParam() == AF_INET || GetParam() == AF_INET6); - } - - template <class... Args> - std::unique_ptr<SocketAddr> CreateSockAddr(Args... args) const { - return SocketAddr::Create(GetParam(), args...); - } - - int CreateSocket(int socket_type) const { - return socket(GetParam(), socket_type, 0); - } -}; - -std::vector<int> GetAvailableIpSocketFamilies() { - std::vector<int> result; - - for (int i : {AF_INET, AF_INET6}) { - int s = socket(i, SOCK_STREAM, 0); - if (s > 0) { - auto sai = SocketAddr::Create(i, 0); - if (bind(s, sai->ptr(), sai->size()) == 0) result.push_back(i); - close(s); - } - } - - return result; -} - -INSTANTIATE_TEST_CASE_P(IpTests, MemorySanitizerIpTest, - ::testing::ValuesIn(GetAvailableIpSocketFamilies())); - -TEST_P(MemorySanitizerIpTest, accept) { - int listen_socket = CreateSocket(SOCK_STREAM); - ASSERT_LT(0, listen_socket); - - auto sai = CreateSockAddr(0); - int res = bind(listen_socket, sai->ptr(), sai->size()); - ASSERT_EQ(0, res); - - res = listen(listen_socket, 1); - ASSERT_EQ(0, res); - - socklen_t sz = sai->size(); - res = getsockname(listen_socket, sai->ptr(), &sz); - ASSERT_EQ(0, res); - ASSERT_EQ(sai->size(), sz); - - int connect_socket = CreateSocket(SOCK_STREAM); - ASSERT_LT(0, connect_socket); - res = fcntl(connect_socket, F_SETFL, O_NONBLOCK); - ASSERT_EQ(0, res); - res = connect(connect_socket, sai->ptr(), sai->size()); - // On FreeBSD this connection completes immediately. - if (res != 0) { - ASSERT_EQ(-1, res); - ASSERT_EQ(EINPROGRESS, errno); - } - - __msan_poison(sai->ptr(), sai->size()); - int new_sock = accept(listen_socket, sai->ptr(), &sz); - ASSERT_LT(0, new_sock); - ASSERT_EQ(sai->size(), sz); - EXPECT_NOT_POISONED2(sai->ptr(), sai->size()); - - __msan_poison(sai->ptr(), sai->size()); - res = getpeername(new_sock, sai->ptr(), &sz); - ASSERT_EQ(0, res); - ASSERT_EQ(sai->size(), sz); - EXPECT_NOT_POISONED2(sai->ptr(), sai->size()); - - close(new_sock); - close(connect_socket); - close(listen_socket); -} - -TEST_P(MemorySanitizerIpTest, recvmsg) { - int server_socket = CreateSocket(SOCK_DGRAM); - ASSERT_LT(0, server_socket); - - auto sai = CreateSockAddr(0); - int res = bind(server_socket, sai->ptr(), sai->size()); - ASSERT_EQ(0, res); - - socklen_t sz = sai->size(); - res = getsockname(server_socket, sai->ptr(), &sz); - ASSERT_EQ(0, res); - ASSERT_EQ(sai->size(), sz); - - int client_socket = CreateSocket(SOCK_DGRAM); - ASSERT_LT(0, client_socket); - - auto client_sai = CreateSockAddr(0); - res = bind(client_socket, client_sai->ptr(), client_sai->size()); - ASSERT_EQ(0, res); - - sz = client_sai->size(); - res = getsockname(client_socket, client_sai->ptr(), &sz); - ASSERT_EQ(0, res); - ASSERT_EQ(client_sai->size(), sz); - - const char *s = "message text"; - struct iovec iov; - iov.iov_base = (void *)s; - iov.iov_len = strlen(s) + 1; - struct msghdr msg; - memset(&msg, 0, sizeof(msg)); - msg.msg_name = sai->ptr(); - msg.msg_namelen = sai->size(); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - res = sendmsg(client_socket, &msg, 0); - ASSERT_LT(0, res); - - char buf[1000]; - struct iovec recv_iov; - recv_iov.iov_base = (void *)&buf; - recv_iov.iov_len = sizeof(buf); - auto recv_sai = CreateSockAddr(); - struct msghdr recv_msg; - memset(&recv_msg, 0, sizeof(recv_msg)); - recv_msg.msg_name = recv_sai->ptr(); - recv_msg.msg_namelen = recv_sai->size(); - recv_msg.msg_iov = &recv_iov; - recv_msg.msg_iovlen = 1; - res = recvmsg(server_socket, &recv_msg, 0); - ASSERT_LT(0, res); - - ASSERT_EQ(recv_sai->size(), recv_msg.msg_namelen); - EXPECT_NOT_POISONED2(recv_sai->ptr(), recv_sai->size()); - EXPECT_STREQ(s, buf); - - close(server_socket); - close(client_socket); -} - -#define EXPECT_HOSTENT_NOT_POISONED(he) \ - do { \ - EXPECT_NOT_POISONED(*(he)); \ - ASSERT_NE((void *)0, (he)->h_name); \ - ASSERT_NE((void *)0, (he)->h_aliases); \ - ASSERT_NE((void *)0, (he)->h_addr_list); \ - EXPECT_NOT_POISONED(strlen((he)->h_name)); \ - char **p = (he)->h_aliases; \ - while (*p) { \ - EXPECT_NOT_POISONED(strlen(*p)); \ - ++p; \ - } \ - char **q = (he)->h_addr_list; \ - while (*q) { \ - EXPECT_NOT_POISONED(*q[0]); \ - ++q; \ - } \ - EXPECT_NOT_POISONED(*q); \ - } while (0) - -TEST(MemorySanitizer, gethostent) { - struct hostent *he = gethostent(); - ASSERT_NE((void *)NULL, he); - EXPECT_HOSTENT_NOT_POISONED(he); -} - -#ifndef MSAN_TEST_DISABLE_GETHOSTBYNAME - -TEST(MemorySanitizer, gethostbyname) { - struct hostent *he = gethostbyname("localhost"); - ASSERT_NE((void *)NULL, he); - EXPECT_HOSTENT_NOT_POISONED(he); -} - -#endif // MSAN_TEST_DISABLE_GETHOSTBYNAME - -TEST(MemorySanitizer, getaddrinfo) { - struct addrinfo *ai; - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - int res = getaddrinfo("localhost", NULL, &hints, &ai); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(*ai); - ASSERT_EQ(sizeof(sockaddr_in), ai->ai_addrlen); - EXPECT_NOT_POISONED(*(sockaddr_in *)ai->ai_addr); -} - -TEST(MemorySanitizer, getnameinfo) { - struct sockaddr_in sai; - memset(&sai, 0, sizeof(sai)); - sai.sin_family = AF_INET; - sai.sin_port = 80; - sai.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - char host[500]; - char serv[500]; - int res = getnameinfo((struct sockaddr *)&sai, sizeof(sai), host, - sizeof(host), serv, sizeof(serv), 0); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(host[0]); - EXPECT_POISONED(host[sizeof(host) - 1]); - - ASSERT_NE(0U, strlen(host)); - EXPECT_NOT_POISONED(serv[0]); - EXPECT_POISONED(serv[sizeof(serv) - 1]); - ASSERT_NE(0U, strlen(serv)); -} - -TEST(MemorySanitizer, gethostbyname2) { - struct hostent *he = gethostbyname2("localhost", AF_INET); - ASSERT_NE((void *)NULL, he); - EXPECT_HOSTENT_NOT_POISONED(he); -} - -TEST(MemorySanitizer, gethostbyaddr) { - in_addr_t addr = inet_addr("127.0.0.1"); - EXPECT_NOT_POISONED(addr); - struct hostent *he = gethostbyaddr(&addr, sizeof(addr), AF_INET); - ASSERT_NE((void *)NULL, he); - EXPECT_HOSTENT_NOT_POISONED(he); -} - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, gethostent_r) { - char buf[2000]; - struct hostent he; - struct hostent *result; - int err; - int res = gethostent_r(&he, buf, sizeof(buf), &result, &err); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(result); - ASSERT_NE((void *)NULL, result); - EXPECT_HOSTENT_NOT_POISONED(result); - EXPECT_NOT_POISONED(err); -} -#endif - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, gethostbyname_r) { - char buf[2000]; - struct hostent he; - struct hostent *result; - int err; - int res = gethostbyname_r("localhost", &he, buf, sizeof(buf), &result, &err); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(result); - ASSERT_NE((void *)NULL, result); - EXPECT_HOSTENT_NOT_POISONED(result); - EXPECT_NOT_POISONED(err); -} -#endif - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, gethostbyname_r_bad_host_name) { - char buf[2000]; - struct hostent he; - struct hostent *result; - int err; - int res = gethostbyname_r("bad-host-name", &he, buf, sizeof(buf), &result, &err); - ASSERT_EQ((struct hostent *)0, result); - EXPECT_NOT_POISONED(err); -} -#endif - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, gethostbyname_r_erange) { - char buf[5]; - struct hostent he; - struct hostent *result; - int err; - gethostbyname_r("localhost", &he, buf, sizeof(buf), &result, &err); - ASSERT_EQ(ERANGE, errno); - EXPECT_NOT_POISONED(err); -} -#endif - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, gethostbyname2_r) { - char buf[2000]; - struct hostent he; - struct hostent *result; - int err; - int res = gethostbyname2_r("localhost", AF_INET, &he, buf, sizeof(buf), - &result, &err); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(result); - ASSERT_NE((void *)NULL, result); - EXPECT_HOSTENT_NOT_POISONED(result); - EXPECT_NOT_POISONED(err); -} -#endif - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, gethostbyaddr_r) { - char buf[2000]; - struct hostent he; - struct hostent *result; - int err; - in_addr_t addr = inet_addr("127.0.0.1"); - EXPECT_NOT_POISONED(addr); - int res = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &he, buf, sizeof(buf), - &result, &err); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(result); - ASSERT_NE((void *)NULL, result); - EXPECT_HOSTENT_NOT_POISONED(result); - EXPECT_NOT_POISONED(err); -} -#endif - -TEST(MemorySanitizer, getsockopt) { - int sock = socket(AF_UNIX, SOCK_STREAM, 0); - struct linger l[2]; - socklen_t sz = sizeof(l[0]); - int res = getsockopt(sock, SOL_SOCKET, SO_LINGER, &l[0], &sz); - ASSERT_EQ(0, res); - ASSERT_EQ(sizeof(l[0]), sz); - EXPECT_NOT_POISONED(l[0]); - EXPECT_POISONED(*(char *)(l + 1)); -} - -TEST(MemorySanitizer, getcwd) { - char path[PATH_MAX + 1]; - char* res = getcwd(path, sizeof(path)); - ASSERT_TRUE(res != NULL); - EXPECT_NOT_POISONED(path[0]); -} - -TEST(MemorySanitizer, getcwd_gnu) { - char* res = getcwd(NULL, 0); - ASSERT_TRUE(res != NULL); - EXPECT_NOT_POISONED(res[0]); - free(res); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, get_current_dir_name) { - char* res = get_current_dir_name(); - ASSERT_TRUE(res != NULL); - EXPECT_NOT_POISONED(res[0]); - free(res); -} -#endif - -TEST(MemorySanitizer, shmctl) { - int id = shmget(IPC_PRIVATE, 4096, 0644 | IPC_CREAT); - ASSERT_GT(id, -1); - - struct shmid_ds ds; - int res = shmctl(id, IPC_STAT, &ds); - ASSERT_GT(res, -1); - EXPECT_NOT_POISONED(ds); - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) - struct shminfo si; - res = shmctl(id, IPC_INFO, (struct shmid_ds *)&si); - ASSERT_GT(res, -1); - EXPECT_NOT_POISONED(si); - - struct shm_info s_i; - res = shmctl(id, SHM_INFO, (struct shmid_ds *)&s_i); - ASSERT_GT(res, -1); - EXPECT_NOT_POISONED(s_i); -#endif - - res = shmctl(id, IPC_RMID, 0); - ASSERT_GT(res, -1); -} - -TEST(MemorySanitizer, shmat) { - const int kShmSize = 4096; - void *mapping_start = mmap(NULL, kShmSize + SHMLBA, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ASSERT_NE(MAP_FAILED, mapping_start); - - void *p = (void *)(((unsigned long)mapping_start + SHMLBA - 1) / SHMLBA * SHMLBA); - // p is now SHMLBA-aligned; - - ((char *)p)[10] = *GetPoisoned<U1>(); - ((char *)p)[kShmSize - 1] = *GetPoisoned<U1>(); - - int res = munmap(mapping_start, kShmSize + SHMLBA); - ASSERT_EQ(0, res); - - int id = shmget(IPC_PRIVATE, kShmSize, 0644 | IPC_CREAT); - ASSERT_GT(id, -1); - - void *q = shmat(id, p, 0); - ASSERT_EQ(p, q); - - EXPECT_NOT_POISONED(((char *)q)[0]); - EXPECT_NOT_POISONED(((char *)q)[10]); - EXPECT_NOT_POISONED(((char *)q)[kShmSize - 1]); - - res = shmdt(q); - ASSERT_EQ(0, res); - - res = shmctl(id, IPC_RMID, 0); - ASSERT_GT(res, -1); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, random_r) { - int32_t x; - char z[64]; - memset(z, 0, sizeof(z)); - - struct random_data buf; - memset(&buf, 0, sizeof(buf)); - - int res = initstate_r(0, z, sizeof(z), &buf); - ASSERT_EQ(0, res); - - res = random_r(&buf, &x); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(x); -} -#endif - -TEST(MemorySanitizer, confstr) { - char buf[3]; - size_t res = confstr(_CS_PATH, buf, sizeof(buf)); - ASSERT_GT(res, sizeof(buf)); - EXPECT_NOT_POISONED(buf[0]); - EXPECT_NOT_POISONED(buf[sizeof(buf) - 1]); - - char buf2[1000]; - res = confstr(_CS_PATH, buf2, sizeof(buf2)); - ASSERT_LT(res, sizeof(buf2)); - EXPECT_NOT_POISONED(buf2[0]); - EXPECT_NOT_POISONED(buf2[res - 1]); - EXPECT_POISONED(buf2[res]); - ASSERT_EQ(res, strlen(buf2) + 1); -} - -TEST(MemorySanitizer, opendir) { - DIR *dir = opendir("."); - closedir(dir); - - char name[10] = "."; - __msan_poison(name, sizeof(name)); - EXPECT_UMR(dir = opendir(name)); - closedir(dir); -} - -TEST(MemorySanitizer, readdir) { - DIR *dir = opendir("."); - struct dirent *d = readdir(dir); - ASSERT_TRUE(d != NULL); - EXPECT_NOT_POISONED(d->d_name[0]); - closedir(dir); -} - -TEST(MemorySanitizer, readdir_r) { - DIR *dir = opendir("."); - struct dirent d; - struct dirent *pd; - int res = readdir_r(dir, &d, &pd); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(pd); - EXPECT_NOT_POISONED(d.d_name[0]); - closedir(dir); -} - -TEST(MemorySanitizer, realpath) { - const char* relpath = "."; - char path[PATH_MAX + 1]; - char* res = realpath(relpath, path); - ASSERT_TRUE(res != NULL); - EXPECT_NOT_POISONED(path[0]); -} - -TEST(MemorySanitizer, realpath_null) { - const char* relpath = "."; - char* res = realpath(relpath, NULL); - printf("%d, %s\n", errno, strerror(errno)); - ASSERT_TRUE(res != NULL); - EXPECT_NOT_POISONED(res[0]); - free(res); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, canonicalize_file_name) { - const char* relpath = "."; - char* res = canonicalize_file_name(relpath); - ASSERT_TRUE(res != NULL); - EXPECT_NOT_POISONED(res[0]); - free(res); -} -#endif - -extern char **environ; - -TEST(MemorySanitizer, setenv) { - setenv("AAA", "BBB", 1); - for (char **envp = environ; *envp; ++envp) { - EXPECT_NOT_POISONED(*envp); - EXPECT_NOT_POISONED(*envp[0]); - } -} - -TEST(MemorySanitizer, putenv) { - char s[] = "AAA=BBB"; - putenv(s); - for (char **envp = environ; *envp; ++envp) { - EXPECT_NOT_POISONED(*envp); - EXPECT_NOT_POISONED(*envp[0]); - } -} - -TEST(MemorySanitizer, memcpy) { - char* x = new char[2]; - char* y = new char[2]; - x[0] = 1; - x[1] = *GetPoisoned<char>(); - memcpy(y, x, 2); - EXPECT_NOT_POISONED(y[0]); - EXPECT_POISONED(y[1]); -} - -void TestUnalignedMemcpy(unsigned left, unsigned right, bool src_is_aligned, - bool src_is_poisoned, bool dst_is_poisoned) { - fprintf(stderr, "%s(%d, %d, %d, %d, %d)\n", __func__, left, right, - src_is_aligned, src_is_poisoned, dst_is_poisoned); - - const unsigned sz = 20; - U4 dst_origin, src_origin; - char *dst = (char *)malloc(sz); - if (dst_is_poisoned) - dst_origin = __msan_get_origin(dst); - else - memset(dst, 0, sz); - - char *src = (char *)malloc(sz); - if (src_is_poisoned) - src_origin = __msan_get_origin(src); - else - memset(src, 0, sz); - - memcpy(dst + left, src_is_aligned ? src + left : src, sz - left - right); - - for (unsigned i = 0; i < (left & (~3U)); ++i) - if (dst_is_poisoned) - EXPECT_POISONED_O(dst[i], dst_origin); - else - EXPECT_NOT_POISONED(dst[i]); - - for (unsigned i = 0; i < (right & (~3U)); ++i) - if (dst_is_poisoned) - EXPECT_POISONED_O(dst[sz - i - 1], dst_origin); - else - EXPECT_NOT_POISONED(dst[sz - i - 1]); - - for (unsigned i = left; i < sz - right; ++i) - if (src_is_poisoned) - EXPECT_POISONED_O(dst[i], src_origin); - else - EXPECT_NOT_POISONED(dst[i]); - - free(dst); - free(src); -} - -TEST(MemorySanitizer, memcpy_unaligned) { - for (int i = 0; i < 10; ++i) - for (int j = 0; j < 10; ++j) - for (int aligned = 0; aligned < 2; ++aligned) - for (int srcp = 0; srcp < 2; ++srcp) - for (int dstp = 0; dstp < 2; ++dstp) - TestUnalignedMemcpy(i, j, aligned, srcp, dstp); -} - -TEST(MemorySanitizer, memmove) { - char* x = new char[2]; - char* y = new char[2]; - x[0] = 1; - x[1] = *GetPoisoned<char>(); - memmove(y, x, 2); - EXPECT_NOT_POISONED(y[0]); - EXPECT_POISONED(y[1]); -} - -TEST(MemorySanitizer, memccpy_nomatch) { - char* x = new char[5]; - char* y = new char[5]; - strcpy(x, "abc"); - memccpy(y, x, 'd', 4); - EXPECT_NOT_POISONED(y[0]); - EXPECT_NOT_POISONED(y[1]); - EXPECT_NOT_POISONED(y[2]); - EXPECT_NOT_POISONED(y[3]); - EXPECT_POISONED(y[4]); - delete[] x; - delete[] y; -} - -TEST(MemorySanitizer, memccpy_match) { - char* x = new char[5]; - char* y = new char[5]; - strcpy(x, "abc"); - memccpy(y, x, 'b', 4); - EXPECT_NOT_POISONED(y[0]); - EXPECT_NOT_POISONED(y[1]); - EXPECT_POISONED(y[2]); - EXPECT_POISONED(y[3]); - EXPECT_POISONED(y[4]); - delete[] x; - delete[] y; -} - -TEST(MemorySanitizer, memccpy_nomatch_positive) { - char* x = new char[5]; - char* y = new char[5]; - strcpy(x, "abc"); - EXPECT_UMR(memccpy(y, x, 'd', 5)); - delete[] x; - delete[] y; -} - -TEST(MemorySanitizer, memccpy_match_positive) { - char* x = new char[5]; - char* y = new char[5]; - x[0] = 'a'; - x[2] = 'b'; - EXPECT_UMR(memccpy(y, x, 'b', 5)); - delete[] x; - delete[] y; -} - -TEST(MemorySanitizer, bcopy) { - char* x = new char[2]; - char* y = new char[2]; - x[0] = 1; - x[1] = *GetPoisoned<char>(); - bcopy(x, y, 2); - EXPECT_NOT_POISONED(y[0]); - EXPECT_POISONED(y[1]); -} - -TEST(MemorySanitizer, strdup) { - char buf[4] = "abc"; - __msan_poison(buf + 2, sizeof(*buf)); - char *x = strdup(buf); - EXPECT_NOT_POISONED(x[0]); - EXPECT_NOT_POISONED(x[1]); - EXPECT_POISONED(x[2]); - EXPECT_NOT_POISONED(x[3]); - free(x); -} - -TEST(MemorySanitizer, strndup) { - char buf[4] = "abc"; - __msan_poison(buf + 2, sizeof(*buf)); - char *x; - EXPECT_UMR(x = strndup(buf, 3)); - EXPECT_NOT_POISONED(x[0]); - EXPECT_NOT_POISONED(x[1]); - EXPECT_POISONED(x[2]); - EXPECT_NOT_POISONED(x[3]); - free(x); - // Check handling of non 0 terminated strings. - buf[3] = 'z'; - __msan_poison(buf + 3, sizeof(*buf)); - EXPECT_UMR(x = strndup(buf + 3, 1)); - EXPECT_POISONED(x[0]); - EXPECT_NOT_POISONED(x[1]); - free(x); -} - -TEST(MemorySanitizer, strndup_short) { - char buf[4] = "abc"; - __msan_poison(buf + 1, sizeof(*buf)); - __msan_poison(buf + 2, sizeof(*buf)); - char *x; - EXPECT_UMR(x = strndup(buf, 2)); - EXPECT_NOT_POISONED(x[0]); - EXPECT_POISONED(x[1]); - EXPECT_NOT_POISONED(x[2]); - free(x); -} - - -template<class T, int size> -void TestOverlapMemmove() { - T *x = new T[size]; - ASSERT_GE(size, 3); - x[2] = 0; - memmove(x, x + 1, (size - 1) * sizeof(T)); - EXPECT_NOT_POISONED(x[1]); - EXPECT_POISONED(x[0]); - EXPECT_POISONED(x[2]); - delete [] x; -} - -TEST(MemorySanitizer, overlap_memmove) { - TestOverlapMemmove<U1, 10>(); - TestOverlapMemmove<U1, 1000>(); - TestOverlapMemmove<U8, 4>(); - TestOverlapMemmove<U8, 1000>(); -} - -TEST(MemorySanitizer, strcpy) { // NOLINT - char* x = new char[3]; - char* y = new char[3]; - x[0] = 'a'; - x[1] = *GetPoisoned<char>(1, 1); - x[2] = 0; - strcpy(y, x); // NOLINT - EXPECT_NOT_POISONED(y[0]); - EXPECT_POISONED(y[1]); - EXPECT_NOT_POISONED(y[2]); -} - -TEST(MemorySanitizer, strncpy) { // NOLINT - char* x = new char[3]; - char* y = new char[5]; - x[0] = 'a'; - x[1] = *GetPoisoned<char>(1, 1); - x[2] = '\0'; - strncpy(y, x, 4); // NOLINT - EXPECT_NOT_POISONED(y[0]); - EXPECT_POISONED(y[1]); - EXPECT_NOT_POISONED(y[2]); - EXPECT_NOT_POISONED(y[3]); - EXPECT_POISONED(y[4]); -} - -TEST(MemorySanitizer, stpcpy) { // NOLINT - char* x = new char[3]; - char* y = new char[3]; - x[0] = 'a'; - x[1] = *GetPoisoned<char>(1, 1); - x[2] = 0; - char *res = stpcpy(y, x); // NOLINT - ASSERT_EQ(res, y + 2); - EXPECT_NOT_POISONED(y[0]); - EXPECT_POISONED(y[1]); - EXPECT_NOT_POISONED(y[2]); -} - -TEST(MemorySanitizer, strcat) { // NOLINT - char a[10]; - char b[] = "def"; - strcpy(a, "abc"); - __msan_poison(b + 1, 1); - strcat(a, b); - EXPECT_NOT_POISONED(a[3]); - EXPECT_POISONED(a[4]); - EXPECT_NOT_POISONED(a[5]); - EXPECT_NOT_POISONED(a[6]); - EXPECT_POISONED(a[7]); -} - -TEST(MemorySanitizer, strncat) { // NOLINT - char a[10]; - char b[] = "def"; - strcpy(a, "abc"); - __msan_poison(b + 1, 1); - strncat(a, b, 5); - EXPECT_NOT_POISONED(a[3]); - EXPECT_POISONED(a[4]); - EXPECT_NOT_POISONED(a[5]); - EXPECT_NOT_POISONED(a[6]); - EXPECT_POISONED(a[7]); -} - -TEST(MemorySanitizer, strncat_overflow) { // NOLINT - char a[10]; - char b[] = "def"; - strcpy(a, "abc"); - __msan_poison(b + 1, 1); - strncat(a, b, 2); - EXPECT_NOT_POISONED(a[3]); - EXPECT_POISONED(a[4]); - EXPECT_NOT_POISONED(a[5]); - EXPECT_POISONED(a[6]); - EXPECT_POISONED(a[7]); -} - -TEST(MemorySanitizer, wcscat) { - wchar_t a[10]; - wchar_t b[] = L"def"; - wcscpy(a, L"abc"); - - wcscat(a, b); - EXPECT_EQ(6U, wcslen(a)); - EXPECT_POISONED(a[7]); - - a[3] = 0; - __msan_poison(b + 1, sizeof(wchar_t)); - EXPECT_UMR(wcscat(a, b)); - - __msan_unpoison(b + 1, sizeof(wchar_t)); - __msan_poison(a + 2, sizeof(wchar_t)); - EXPECT_UMR(wcscat(a, b)); -} - -TEST(MemorySanitizer, wcsncat) { - wchar_t a[10]; - wchar_t b[] = L"def"; - wcscpy(a, L"abc"); - - wcsncat(a, b, 5); - EXPECT_EQ(6U, wcslen(a)); - EXPECT_POISONED(a[7]); - - a[3] = 0; - __msan_poison(a + 4, sizeof(wchar_t) * 6); - wcsncat(a, b, 2); - EXPECT_EQ(5U, wcslen(a)); - EXPECT_POISONED(a[6]); - - a[3] = 0; - __msan_poison(b + 1, sizeof(wchar_t)); - EXPECT_UMR(wcsncat(a, b, 2)); - - __msan_unpoison(b + 1, sizeof(wchar_t)); - __msan_poison(a + 2, sizeof(wchar_t)); - EXPECT_UMR(wcsncat(a, b, 2)); -} - -#define TEST_STRTO_INT(func_name, char_type, str_prefix) \ - TEST(MemorySanitizer, func_name) { \ - char_type *e; \ - EXPECT_EQ(1U, func_name(str_prefix##"1", &e, 10)); \ - EXPECT_NOT_POISONED((S8)e); \ - } - -#define TEST_STRTO_FLOAT(func_name, char_type, str_prefix) \ - TEST(MemorySanitizer, func_name) { \ - char_type *e; \ - EXPECT_NE(0, func_name(str_prefix##"1.5", &e)); \ - EXPECT_NOT_POISONED((S8)e); \ - } - -#define TEST_STRTO_FLOAT_LOC(func_name, char_type, str_prefix) \ - TEST(MemorySanitizer, func_name) { \ - locale_t loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); \ - char_type *e; \ - EXPECT_NE(0, func_name(str_prefix##"1.5", &e, loc)); \ - EXPECT_NOT_POISONED((S8)e); \ - freelocale(loc); \ - } - -#define TEST_STRTO_INT_LOC(func_name, char_type, str_prefix) \ - TEST(MemorySanitizer, func_name) { \ - locale_t loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); \ - char_type *e; \ - ASSERT_EQ(1U, func_name(str_prefix##"1", &e, 10, loc)); \ - EXPECT_NOT_POISONED((S8)e); \ - freelocale(loc); \ - } - -TEST_STRTO_INT(strtol, char, ) -TEST_STRTO_INT(strtoll, char, ) -TEST_STRTO_INT(strtoul, char, ) -TEST_STRTO_INT(strtoull, char, ) -TEST_STRTO_INT(strtouq, char, ) - -TEST_STRTO_FLOAT(strtof, char, ) -TEST_STRTO_FLOAT(strtod, char, ) -TEST_STRTO_FLOAT(strtold, char, ) - -TEST_STRTO_FLOAT_LOC(strtof_l, char, ) -TEST_STRTO_FLOAT_LOC(strtod_l, char, ) -TEST_STRTO_FLOAT_LOC(strtold_l, char, ) - -TEST_STRTO_INT_LOC(strtol_l, char, ) -TEST_STRTO_INT_LOC(strtoll_l, char, ) -TEST_STRTO_INT_LOC(strtoul_l, char, ) -TEST_STRTO_INT_LOC(strtoull_l, char, ) - -TEST_STRTO_INT(wcstol, wchar_t, L) -TEST_STRTO_INT(wcstoll, wchar_t, L) -TEST_STRTO_INT(wcstoul, wchar_t, L) -TEST_STRTO_INT(wcstoull, wchar_t, L) - -TEST_STRTO_FLOAT(wcstof, wchar_t, L) -TEST_STRTO_FLOAT(wcstod, wchar_t, L) -TEST_STRTO_FLOAT(wcstold, wchar_t, L) - -TEST_STRTO_FLOAT_LOC(wcstof_l, wchar_t, L) -TEST_STRTO_FLOAT_LOC(wcstod_l, wchar_t, L) -TEST_STRTO_FLOAT_LOC(wcstold_l, wchar_t, L) - -TEST_STRTO_INT_LOC(wcstol_l, wchar_t, L) -TEST_STRTO_INT_LOC(wcstoll_l, wchar_t, L) -TEST_STRTO_INT_LOC(wcstoul_l, wchar_t, L) -TEST_STRTO_INT_LOC(wcstoull_l, wchar_t, L) - - -TEST(MemorySanitizer, strtoimax) { - char *e; - ASSERT_EQ(1, strtoimax("1", &e, 10)); - EXPECT_NOT_POISONED((S8) e); -} - -TEST(MemorySanitizer, strtoumax) { - char *e; - ASSERT_EQ(1U, strtoumax("1", &e, 10)); - EXPECT_NOT_POISONED((S8) e); -} - -#ifdef __GLIBC__ -extern "C" float __strtof_l(const char *nptr, char **endptr, locale_t loc); -TEST_STRTO_FLOAT_LOC(__strtof_l, char, ) -extern "C" double __strtod_l(const char *nptr, char **endptr, locale_t loc); -TEST_STRTO_FLOAT_LOC(__strtod_l, char, ) -extern "C" long double __strtold_l(const char *nptr, char **endptr, - locale_t loc); -TEST_STRTO_FLOAT_LOC(__strtold_l, char, ) - -extern "C" float __wcstof_l(const wchar_t *nptr, wchar_t **endptr, locale_t loc); -TEST_STRTO_FLOAT_LOC(__wcstof_l, wchar_t, L) -extern "C" double __wcstod_l(const wchar_t *nptr, wchar_t **endptr, locale_t loc); -TEST_STRTO_FLOAT_LOC(__wcstod_l, wchar_t, L) -extern "C" long double __wcstold_l(const wchar_t *nptr, wchar_t **endptr, - locale_t loc); -TEST_STRTO_FLOAT_LOC(__wcstold_l, wchar_t, L) -#endif // __GLIBC__ - -TEST(MemorySanitizer, modf) { - double x, y; - x = modf(2.1, &y); - EXPECT_NOT_POISONED(y); -} - -TEST(MemorySanitizer, modff) { - float x, y; - x = modff(2.1, &y); - EXPECT_NOT_POISONED(y); -} - -TEST(MemorySanitizer, modfl) { - long double x, y; - x = modfl(2.1, &y); - EXPECT_NOT_POISONED(y); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, sincos) { - double s, c; - sincos(0.2, &s, &c); - EXPECT_NOT_POISONED(s); - EXPECT_NOT_POISONED(c); -} -#endif - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, sincosf) { - float s, c; - sincosf(0.2, &s, &c); - EXPECT_NOT_POISONED(s); - EXPECT_NOT_POISONED(c); -} -#endif - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, sincosl) { - long double s, c; - sincosl(0.2, &s, &c); - EXPECT_NOT_POISONED(s); - EXPECT_NOT_POISONED(c); -} -#endif - -TEST(MemorySanitizer, remquo) { - int quo; - double res = remquo(29.0, 3.0, &quo); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(quo); -} - -TEST(MemorySanitizer, remquof) { - int quo; - float res = remquof(29.0, 3.0, &quo); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(quo); -} - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, remquol) { - int quo; - long double res = remquof(29.0, 3.0, &quo); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(quo); -} -#endif - -TEST(MemorySanitizer, lgamma) { - double res = lgamma(1.1); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(signgam); -} - -TEST(MemorySanitizer, lgammaf) { - float res = lgammaf(1.1); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(signgam); -} - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, lgammal) { - long double res = lgammal(1.1); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(signgam); -} -#endif - -TEST(MemorySanitizer, lgamma_r) { - int sgn; - double res = lgamma_r(1.1, &sgn); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(sgn); -} - -TEST(MemorySanitizer, lgammaf_r) { - int sgn; - float res = lgammaf_r(1.1, &sgn); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(sgn); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, lgammal_r) { - int sgn; - long double res = lgammal_r(1.1, &sgn); - ASSERT_NE(0.0, res); - EXPECT_NOT_POISONED(sgn); -} -#endif - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, drand48_r) { - struct drand48_data buf; - srand48_r(0, &buf); - double d; - drand48_r(&buf, &d); - EXPECT_NOT_POISONED(d); -} -#endif - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, lrand48_r) { - struct drand48_data buf; - srand48_r(0, &buf); - long d; - lrand48_r(&buf, &d); - EXPECT_NOT_POISONED(d); -} -#endif - -TEST(MemorySanitizer, sprintf) { // NOLINT - char buff[10]; - break_optimization(buff); - EXPECT_POISONED(buff[0]); - int res = sprintf(buff, "%d", 1234567); // NOLINT - ASSERT_EQ(res, 7); - ASSERT_EQ(buff[0], '1'); - ASSERT_EQ(buff[1], '2'); - ASSERT_EQ(buff[2], '3'); - ASSERT_EQ(buff[6], '7'); - ASSERT_EQ(buff[7], 0); - EXPECT_POISONED(buff[8]); -} - -TEST(MemorySanitizer, snprintf) { - char buff[10]; - break_optimization(buff); - EXPECT_POISONED(buff[0]); - int res = snprintf(buff, sizeof(buff), "%d", 1234567); - ASSERT_EQ(res, 7); - ASSERT_EQ(buff[0], '1'); - ASSERT_EQ(buff[1], '2'); - ASSERT_EQ(buff[2], '3'); - ASSERT_EQ(buff[6], '7'); - ASSERT_EQ(buff[7], 0); - EXPECT_POISONED(buff[8]); -} - -TEST(MemorySanitizer, swprintf) { - wchar_t buff[10]; - ASSERT_EQ(4U, sizeof(wchar_t)); - break_optimization(buff); - EXPECT_POISONED(buff[0]); - int res = swprintf(buff, 9, L"%d", 1234567); - ASSERT_EQ(res, 7); - ASSERT_EQ(buff[0], '1'); - ASSERT_EQ(buff[1], '2'); - ASSERT_EQ(buff[2], '3'); - ASSERT_EQ(buff[6], '7'); - ASSERT_EQ(buff[7], L'\0'); - EXPECT_POISONED(buff[8]); -} - -TEST(MemorySanitizer, asprintf) { // NOLINT - char *pbuf; - EXPECT_POISONED(pbuf); - int res = asprintf(&pbuf, "%d", 1234567); // NOLINT - ASSERT_EQ(res, 7); - EXPECT_NOT_POISONED(pbuf); - ASSERT_EQ(pbuf[0], '1'); - ASSERT_EQ(pbuf[1], '2'); - ASSERT_EQ(pbuf[2], '3'); - ASSERT_EQ(pbuf[6], '7'); - ASSERT_EQ(pbuf[7], 0); - free(pbuf); -} - -TEST(MemorySanitizer, mbstowcs) { - const char *x = "abc"; - wchar_t buff[10]; - int res = mbstowcs(buff, x, 2); - EXPECT_EQ(2, res); - EXPECT_EQ(L'a', buff[0]); - EXPECT_EQ(L'b', buff[1]); - EXPECT_POISONED(buff[2]); - res = mbstowcs(buff, x, 10); - EXPECT_EQ(3, res); - EXPECT_NOT_POISONED(buff[3]); -} - -TEST(MemorySanitizer, wcstombs) { - const wchar_t *x = L"abc"; - char buff[10]; - int res = wcstombs(buff, x, 4); - EXPECT_EQ(res, 3); - EXPECT_EQ(buff[0], 'a'); - EXPECT_EQ(buff[1], 'b'); - EXPECT_EQ(buff[2], 'c'); -} - -TEST(MemorySanitizer, wcsrtombs) { - const wchar_t *x = L"abc"; - const wchar_t *p = x; - char buff[10]; - mbstate_t mbs; - memset(&mbs, 0, sizeof(mbs)); - int res = wcsrtombs(buff, &p, 4, &mbs); - EXPECT_EQ(res, 3); - EXPECT_EQ(buff[0], 'a'); - EXPECT_EQ(buff[1], 'b'); - EXPECT_EQ(buff[2], 'c'); - EXPECT_EQ(buff[3], '\0'); - EXPECT_POISONED(buff[4]); -} - -TEST(MemorySanitizer, wcsnrtombs) { - const wchar_t *x = L"abc"; - const wchar_t *p = x; - char buff[10]; - mbstate_t mbs; - memset(&mbs, 0, sizeof(mbs)); - int res = wcsnrtombs(buff, &p, 2, 4, &mbs); - EXPECT_EQ(res, 2); - EXPECT_EQ(buff[0], 'a'); - EXPECT_EQ(buff[1], 'b'); - EXPECT_POISONED(buff[2]); -} - -TEST(MemorySanitizer, wcrtomb) { - wchar_t x = L'a'; - char buff[10]; - mbstate_t mbs; - memset(&mbs, 0, sizeof(mbs)); - size_t res = wcrtomb(buff, x, &mbs); - EXPECT_EQ(res, (size_t)1); - EXPECT_EQ(buff[0], 'a'); -} - -TEST(MemorySanitizer, wmemset) { - wchar_t x[25]; - break_optimization(x); - EXPECT_POISONED(x[0]); - wmemset(x, L'A', 10); - EXPECT_EQ(x[0], L'A'); - EXPECT_EQ(x[9], L'A'); - EXPECT_POISONED(x[10]); -} - -TEST(MemorySanitizer, mbtowc) { - const char *x = "abc"; - wchar_t wx; - int res = mbtowc(&wx, x, 3); - EXPECT_GT(res, 0); - EXPECT_NOT_POISONED(wx); -} - -TEST(MemorySanitizer, mbrtowc) { - mbstate_t mbs = {}; - - wchar_t wc; - size_t res = mbrtowc(&wc, "\377", 1, &mbs); - EXPECT_EQ(res, -1ULL); - - res = mbrtowc(&wc, "abc", 3, &mbs); - EXPECT_GT(res, 0ULL); - EXPECT_NOT_POISONED(wc); -} - -TEST(MemorySanitizer, wcsftime) { - wchar_t x[100]; - time_t t = time(NULL); - struct tm tms; - struct tm *tmres = localtime_r(&t, &tms); - ASSERT_NE((void *)0, tmres); - size_t res = wcsftime(x, sizeof(x) / sizeof(x[0]), L"%Y-%m-%d", tmres); - EXPECT_GT(res, 0UL); - EXPECT_EQ(res, wcslen(x)); -} - -TEST(MemorySanitizer, gettimeofday) { - struct timeval tv; - struct timezone tz; - break_optimization(&tv); - break_optimization(&tz); - ASSERT_EQ(16U, sizeof(tv)); - ASSERT_EQ(8U, sizeof(tz)); - EXPECT_POISONED(tv.tv_sec); - EXPECT_POISONED(tv.tv_usec); - EXPECT_POISONED(tz.tz_minuteswest); - EXPECT_POISONED(tz.tz_dsttime); - ASSERT_EQ(0, gettimeofday(&tv, &tz)); - EXPECT_NOT_POISONED(tv.tv_sec); - EXPECT_NOT_POISONED(tv.tv_usec); - EXPECT_NOT_POISONED(tz.tz_minuteswest); - EXPECT_NOT_POISONED(tz.tz_dsttime); -} - -TEST(MemorySanitizer, clock_gettime) { - struct timespec tp; - EXPECT_POISONED(tp.tv_sec); - EXPECT_POISONED(tp.tv_nsec); - ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp)); - EXPECT_NOT_POISONED(tp.tv_sec); - EXPECT_NOT_POISONED(tp.tv_nsec); -} - -TEST(MemorySanitizer, clock_getres) { - struct timespec tp; - EXPECT_POISONED(tp.tv_sec); - EXPECT_POISONED(tp.tv_nsec); - ASSERT_EQ(0, clock_getres(CLOCK_REALTIME, 0)); - EXPECT_POISONED(tp.tv_sec); - EXPECT_POISONED(tp.tv_nsec); - ASSERT_EQ(0, clock_getres(CLOCK_REALTIME, &tp)); - EXPECT_NOT_POISONED(tp.tv_sec); - EXPECT_NOT_POISONED(tp.tv_nsec); -} - -TEST(MemorySanitizer, getitimer) { - struct itimerval it1, it2; - int res; - EXPECT_POISONED(it1.it_interval.tv_sec); - EXPECT_POISONED(it1.it_interval.tv_usec); - EXPECT_POISONED(it1.it_value.tv_sec); - EXPECT_POISONED(it1.it_value.tv_usec); - res = getitimer(ITIMER_VIRTUAL, &it1); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(it1.it_interval.tv_sec); - EXPECT_NOT_POISONED(it1.it_interval.tv_usec); - EXPECT_NOT_POISONED(it1.it_value.tv_sec); - EXPECT_NOT_POISONED(it1.it_value.tv_usec); - - it1.it_interval.tv_sec = it1.it_value.tv_sec = 10000; - it1.it_interval.tv_usec = it1.it_value.tv_usec = 0; - - res = setitimer(ITIMER_VIRTUAL, &it1, &it2); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(it2.it_interval.tv_sec); - EXPECT_NOT_POISONED(it2.it_interval.tv_usec); - EXPECT_NOT_POISONED(it2.it_value.tv_sec); - EXPECT_NOT_POISONED(it2.it_value.tv_usec); - - // Check that old_value can be 0, and disable the timer. - memset(&it1, 0, sizeof(it1)); - res = setitimer(ITIMER_VIRTUAL, &it1, 0); - ASSERT_EQ(0, res); -} - -TEST(MemorySanitizer, setitimer_null) { - setitimer(ITIMER_VIRTUAL, 0, 0); - // Not testing the return value, since it the behaviour seems to differ - // between libc implementations and POSIX. - // Should never crash, though. -} - -TEST(MemorySanitizer, time) { - time_t t; - EXPECT_POISONED(t); - time_t t2 = time(&t); - ASSERT_NE(t2, (time_t)-1); - EXPECT_NOT_POISONED(t); -} - -TEST(MemorySanitizer, strptime) { - struct tm time; - char *p = strptime("11/1/2013-05:39", "%m/%d/%Y-%H:%M", &time); - ASSERT_TRUE(p != NULL); - EXPECT_NOT_POISONED(time.tm_sec); - EXPECT_NOT_POISONED(time.tm_hour); - EXPECT_NOT_POISONED(time.tm_year); -} - -TEST(MemorySanitizer, localtime) { - time_t t = 123; - struct tm *time = localtime(&t); - ASSERT_TRUE(time != NULL); - EXPECT_NOT_POISONED(time->tm_sec); - EXPECT_NOT_POISONED(time->tm_hour); - EXPECT_NOT_POISONED(time->tm_year); - EXPECT_NOT_POISONED(time->tm_isdst); - EXPECT_NE(0U, strlen(time->tm_zone)); -} - -TEST(MemorySanitizer, localtime_r) { - time_t t = 123; - struct tm time; - struct tm *res = localtime_r(&t, &time); - ASSERT_TRUE(res != NULL); - EXPECT_NOT_POISONED(time.tm_sec); - EXPECT_NOT_POISONED(time.tm_hour); - EXPECT_NOT_POISONED(time.tm_year); - EXPECT_NOT_POISONED(time.tm_isdst); - EXPECT_NE(0U, strlen(time.tm_zone)); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -/* Creates a temporary file with contents similar to /etc/fstab to be used - with getmntent{_r}. */ -class TempFstabFile { - public: - TempFstabFile() : fd (-1) { } - ~TempFstabFile() { - if (fd >= 0) - close (fd); - } - - bool Create(void) { - snprintf(tmpfile, sizeof(tmpfile), "/tmp/msan.getmntent.tmp.XXXXXX"); - - fd = mkstemp(tmpfile); - if (fd == -1) - return false; - - const char entry[] = "/dev/root / ext4 errors=remount-ro 0 1"; - size_t entrylen = sizeof(entry); - - size_t bytesWritten = write(fd, entry, entrylen); - if (entrylen != bytesWritten) - return false; - - return true; - } - - const char* FileName(void) { - return tmpfile; - } - - private: - char tmpfile[128]; - int fd; -}; -#endif - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, getmntent) { - TempFstabFile fstabtmp; - ASSERT_TRUE(fstabtmp.Create()); - FILE *fp = setmntent(fstabtmp.FileName(), "r"); - - struct mntent *mnt = getmntent(fp); - ASSERT_TRUE(mnt != NULL); - ASSERT_NE(0U, strlen(mnt->mnt_fsname)); - ASSERT_NE(0U, strlen(mnt->mnt_dir)); - ASSERT_NE(0U, strlen(mnt->mnt_type)); - ASSERT_NE(0U, strlen(mnt->mnt_opts)); - EXPECT_NOT_POISONED(mnt->mnt_freq); - EXPECT_NOT_POISONED(mnt->mnt_passno); - fclose(fp); -} -#endif - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, getmntent_r) { - TempFstabFile fstabtmp; - ASSERT_TRUE(fstabtmp.Create()); - FILE *fp = setmntent(fstabtmp.FileName(), "r"); - - struct mntent mntbuf; - char buf[1000]; - struct mntent *mnt = getmntent_r(fp, &mntbuf, buf, sizeof(buf)); - ASSERT_TRUE(mnt != NULL); - ASSERT_NE(0U, strlen(mnt->mnt_fsname)); - ASSERT_NE(0U, strlen(mnt->mnt_dir)); - ASSERT_NE(0U, strlen(mnt->mnt_type)); - ASSERT_NE(0U, strlen(mnt->mnt_opts)); - EXPECT_NOT_POISONED(mnt->mnt_freq); - EXPECT_NOT_POISONED(mnt->mnt_passno); - fclose(fp); -} -#endif - -#if !defined(__NetBSD__) -TEST(MemorySanitizer, ether) { - const char *asc = "11:22:33:44:55:66"; - struct ether_addr *paddr = ether_aton(asc); - EXPECT_NOT_POISONED(*paddr); - - struct ether_addr addr; - paddr = ether_aton_r(asc, &addr); - ASSERT_EQ(paddr, &addr); - EXPECT_NOT_POISONED(addr); - - char *s = ether_ntoa(&addr); - ASSERT_NE(0U, strlen(s)); - - char buf[100]; - s = ether_ntoa_r(&addr, buf); - ASSERT_EQ(s, buf); - ASSERT_NE(0U, strlen(buf)); -} -#endif - -TEST(MemorySanitizer, mmap) { - const int size = 4096; - void *p1, *p2; - p1 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); - __msan_poison(p1, size); - munmap(p1, size); - for (int i = 0; i < 1000; i++) { - p2 = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); - if (p2 == p1) - break; - else - munmap(p2, size); - } - if (p1 == p2) { - EXPECT_NOT_POISONED(*(char*)p2); - munmap(p2, size); - } -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -// FIXME: enable and add ecvt. -// FIXME: check why msandr does nt handle fcvt. -TEST(MemorySanitizer, fcvt) { - int a, b; - break_optimization(&a); - break_optimization(&b); - EXPECT_POISONED(a); - EXPECT_POISONED(b); - char *str = fcvt(12345.6789, 10, &a, &b); - EXPECT_NOT_POISONED(a); - EXPECT_NOT_POISONED(b); - ASSERT_NE(nullptr, str); - EXPECT_NOT_POISONED(str[0]); - ASSERT_NE(0U, strlen(str)); -} -#endif - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, fcvt_long) { - int a, b; - break_optimization(&a); - break_optimization(&b); - EXPECT_POISONED(a); - EXPECT_POISONED(b); - char *str = fcvt(111111112345.6789, 10, &a, &b); - EXPECT_NOT_POISONED(a); - EXPECT_NOT_POISONED(b); - ASSERT_NE(nullptr, str); - EXPECT_NOT_POISONED(str[0]); - ASSERT_NE(0U, strlen(str)); -} -#endif - -TEST(MemorySanitizer, memchr) { - char x[10]; - break_optimization(x); - EXPECT_POISONED(x[0]); - x[2] = '2'; - void *res; - EXPECT_UMR(res = memchr(x, '2', 10)); - EXPECT_NOT_POISONED(res); - x[0] = '0'; - x[1] = '1'; - res = memchr(x, '2', 10); - EXPECT_EQ(&x[2], res); - EXPECT_UMR(res = memchr(x, '3', 10)); - EXPECT_NOT_POISONED(res); -} - -TEST(MemorySanitizer, memrchr) { - char x[10]; - break_optimization(x); - EXPECT_POISONED(x[0]); - x[9] = '9'; - void *res; - EXPECT_UMR(res = memrchr(x, '9', 10)); - EXPECT_NOT_POISONED(res); - x[0] = '0'; - x[1] = '1'; - res = memrchr(x, '0', 2); - EXPECT_EQ(&x[0], res); - EXPECT_UMR(res = memrchr(x, '7', 10)); - EXPECT_NOT_POISONED(res); -} - -TEST(MemorySanitizer, frexp) { - int x; - x = *GetPoisoned<int>(); - double r = frexp(1.1, &x); - EXPECT_NOT_POISONED(r); - EXPECT_NOT_POISONED(x); - - x = *GetPoisoned<int>(); - float rf = frexpf(1.1, &x); - EXPECT_NOT_POISONED(rf); - EXPECT_NOT_POISONED(x); - - x = *GetPoisoned<int>(); - double rl = frexpl(1.1, &x); - EXPECT_NOT_POISONED(rl); - EXPECT_NOT_POISONED(x); -} - -namespace { - -static int cnt; - -void SigactionHandler(int signo, siginfo_t* si, void* uc) { - ASSERT_EQ(signo, SIGPROF); - ASSERT_TRUE(si != NULL); - EXPECT_NOT_POISONED(si->si_errno); - EXPECT_NOT_POISONED(si->si_pid); -#ifdef _UC_MACHINE_PC - EXPECT_NOT_POISONED(_UC_MACHINE_PC((ucontext_t*)uc)); -#else -# if __linux__ -# if defined(__x86_64__) - EXPECT_NOT_POISONED(((ucontext_t*)uc)->uc_mcontext.gregs[REG_RIP]); -# elif defined(__i386__) - EXPECT_NOT_POISONED(((ucontext_t*)uc)->uc_mcontext.gregs[REG_EIP]); -# endif -# endif -#endif - ++cnt; -} - -TEST(MemorySanitizer, sigaction) { - struct sigaction act = {}; - struct sigaction oldact = {}; - struct sigaction origact = {}; - - sigaction(SIGPROF, 0, &origact); - - act.sa_flags |= SA_SIGINFO; - act.sa_sigaction = &SigactionHandler; - sigaction(SIGPROF, &act, 0); - - kill(getpid(), SIGPROF); - - act.sa_flags &= ~SA_SIGINFO; - act.sa_handler = SIG_DFL; - sigaction(SIGPROF, &act, 0); - - act.sa_flags &= ~SA_SIGINFO; - act.sa_handler = SIG_IGN; - sigaction(SIGPROF, &act, &oldact); - EXPECT_FALSE(oldact.sa_flags & SA_SIGINFO); - EXPECT_EQ(SIG_DFL, oldact.sa_handler); - kill(getpid(), SIGPROF); - - act.sa_flags |= SA_SIGINFO; - act.sa_sigaction = &SigactionHandler; - sigaction(SIGPROF, &act, &oldact); - EXPECT_FALSE(oldact.sa_flags & SA_SIGINFO); - EXPECT_EQ(SIG_IGN, oldact.sa_handler); - kill(getpid(), SIGPROF); - - act.sa_flags &= ~SA_SIGINFO; - act.sa_handler = SIG_DFL; - sigaction(SIGPROF, &act, &oldact); - EXPECT_TRUE(oldact.sa_flags & SA_SIGINFO); - EXPECT_EQ(&SigactionHandler, oldact.sa_sigaction); - EXPECT_EQ(2, cnt); - - sigaction(SIGPROF, &origact, 0); -} - -} // namespace - - -TEST(MemorySanitizer, sigemptyset) { - sigset_t s; - EXPECT_POISONED(s); - int res = sigemptyset(&s); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(s); -} - -TEST(MemorySanitizer, sigfillset) { - sigset_t s; - EXPECT_POISONED(s); - int res = sigfillset(&s); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(s); -} - -TEST(MemorySanitizer, sigpending) { - sigset_t s; - EXPECT_POISONED(s); - int res = sigpending(&s); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(s); -} - -TEST(MemorySanitizer, sigprocmask) { - sigset_t s; - EXPECT_POISONED(s); - int res = sigprocmask(SIG_BLOCK, 0, &s); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(s); -} - -struct StructWithDtor { - ~StructWithDtor(); -}; - -NOINLINE StructWithDtor::~StructWithDtor() { - break_optimization(0); -} - -TEST(MemorySanitizer, Invoke) { - StructWithDtor s; // Will cause the calls to become invokes. - EXPECT_NOT_POISONED(0); - EXPECT_POISONED(*GetPoisoned<int>()); - EXPECT_NOT_POISONED(0); - EXPECT_POISONED(*GetPoisoned<int>()); - EXPECT_POISONED(ReturnPoisoned<S4>()); -} - -TEST(MemorySanitizer, ptrtoint) { - // Test that shadow is propagated through pointer-to-integer conversion. - unsigned char c = 0; - __msan_poison(&c, 1); - uintptr_t u = (uintptr_t)c << 8; - EXPECT_NOT_POISONED(u & 0xFF00FF); - EXPECT_POISONED(u & 0xFF00); - - break_optimization(&u); - void* p = (void*)u; - - break_optimization(&p); - EXPECT_POISONED(p); - EXPECT_NOT_POISONED(((uintptr_t)p) & 0xFF00FF); - EXPECT_POISONED(((uintptr_t)p) & 0xFF00); -} - -static void vaargsfn2(int guard, ...) { - va_list vl; - va_start(vl, guard); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, double)); - va_end(vl); -} - -static void vaargsfn(int guard, ...) { - va_list vl; - va_start(vl, guard); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); - // The following call will overwrite __msan_param_tls. - // Checks after it test that arg shadow was somehow saved across the call. - vaargsfn2(1, 2, 3, 4, *GetPoisoned<double>()); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); - va_end(vl); -} - -TEST(MemorySanitizer, VAArgTest) { - int* x = GetPoisoned<int>(); - int* y = GetPoisoned<int>(4); - vaargsfn(1, 13, *x, 42, *y); -} - -static void vaargsfn_many(int guard, ...) { - va_list vl; - va_start(vl, guard); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); - va_end(vl); -} - -TEST(MemorySanitizer, VAArgManyTest) { - int* x = GetPoisoned<int>(); - int* y = GetPoisoned<int>(4); - vaargsfn_many(1, 2, *x, 3, 4, 5, 6, 7, 8, 9, *y); -} - -static void vaargsfn_manyfix(int g1, int g2, int g3, int g4, int g5, int g6, int g7, int g8, int g9, ...) { - va_list vl; - va_start(vl, g9); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); - va_end(vl); -} - -TEST(MemorySanitizer, VAArgManyFixTest) { - int* x = GetPoisoned<int>(); - int* y = GetPoisoned<int>(); - vaargsfn_manyfix(1, *x, 3, 4, 5, 6, 7, 8, 9, 10, *y); -} - -static void vaargsfn_pass2(va_list vl) { - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); -} - -static void vaargsfn_pass(int guard, ...) { - va_list vl; - va_start(vl, guard); - EXPECT_POISONED(va_arg(vl, int)); - vaargsfn_pass2(vl); - va_end(vl); -} - -TEST(MemorySanitizer, VAArgPass) { - int* x = GetPoisoned<int>(); - int* y = GetPoisoned<int>(4); - vaargsfn_pass(1, *x, 2, 3, *y); -} - -static void vaargsfn_copy2(va_list vl) { - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); -} - -static void vaargsfn_copy(int guard, ...) { - va_list vl; - va_start(vl, guard); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); - va_list vl2; - va_copy(vl2, vl); - vaargsfn_copy2(vl2); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); - va_end(vl); -} - -TEST(MemorySanitizer, VAArgCopy) { - int* x = GetPoisoned<int>(); - int* y = GetPoisoned<int>(4); - vaargsfn_copy(1, 2, *x, 3, *y); -} - -static void vaargsfn_ptr(int guard, ...) { - va_list vl; - va_start(vl, guard); - EXPECT_NOT_POISONED(va_arg(vl, int*)); - EXPECT_POISONED(va_arg(vl, int*)); - EXPECT_NOT_POISONED(va_arg(vl, int*)); - EXPECT_POISONED(va_arg(vl, double*)); - va_end(vl); -} - -TEST(MemorySanitizer, VAArgPtr) { - int** x = GetPoisoned<int*>(); - double** y = GetPoisoned<double*>(8); - int z; - vaargsfn_ptr(1, &z, *x, &z, *y); -} - -static void vaargsfn_overflow(int guard, ...) { - va_list vl; - va_start(vl, guard); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, int)); - - EXPECT_NOT_POISONED(va_arg(vl, double)); - EXPECT_NOT_POISONED(va_arg(vl, double)); - EXPECT_NOT_POISONED(va_arg(vl, double)); - EXPECT_POISONED(va_arg(vl, double)); - EXPECT_NOT_POISONED(va_arg(vl, double)); - EXPECT_POISONED(va_arg(vl, int*)); - EXPECT_NOT_POISONED(va_arg(vl, double)); - EXPECT_NOT_POISONED(va_arg(vl, double)); - - EXPECT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, double)); - EXPECT_POISONED(va_arg(vl, int*)); - - EXPECT_NOT_POISONED(va_arg(vl, int)); - EXPECT_NOT_POISONED(va_arg(vl, double)); - EXPECT_NOT_POISONED(va_arg(vl, int*)); - - EXPECT_POISONED(va_arg(vl, int)); - EXPECT_POISONED(va_arg(vl, double)); - EXPECT_POISONED(va_arg(vl, int*)); - - va_end(vl); -} - -TEST(MemorySanitizer, VAArgOverflow) { - int* x = GetPoisoned<int>(); - double* y = GetPoisoned<double>(8); - int** p = GetPoisoned<int*>(16); - int z; - vaargsfn_overflow(1, - 1, 2, *x, 4, 5, 6, - 1.1, 2.2, 3.3, *y, 5.5, *p, 7.7, 8.8, - // the following args will overflow for sure - *x, *y, *p, - 7, 9.9, &z, - *x, *y, *p); -} - -static void vaargsfn_tlsoverwrite2(int guard, ...) { - va_list vl; - va_start(vl, guard); - for (int i = 0; i < 20; ++i) - EXPECT_NOT_POISONED(va_arg(vl, int)); - va_end(vl); -} - -static void vaargsfn_tlsoverwrite(int guard, ...) { - // This call will overwrite TLS contents unless it's backed up somewhere. - vaargsfn_tlsoverwrite2(2, - 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42); // 20x - va_list vl; - va_start(vl, guard); - for (int i = 0; i < 20; ++i) - EXPECT_POISONED(va_arg(vl, int)); - va_end(vl); -} - -TEST(MemorySanitizer, VAArgTLSOverwrite) { - int* x = GetPoisoned<int>(); - vaargsfn_tlsoverwrite(1, - *x, *x, *x, *x, *x, - *x, *x, *x, *x, *x, - *x, *x, *x, *x, *x, - *x, *x, *x, *x, *x); // 20x - -} - -struct StructByVal { - int a, b, c, d, e, f; -}; - -static void vaargsfn_structbyval(int guard, ...) { - va_list vl; - va_start(vl, guard); - { - StructByVal s = va_arg(vl, StructByVal); - EXPECT_NOT_POISONED(s.a); - EXPECT_POISONED(s.b); - EXPECT_NOT_POISONED(s.c); - EXPECT_POISONED(s.d); - EXPECT_NOT_POISONED(s.e); - EXPECT_POISONED(s.f); - } - { - StructByVal s = va_arg(vl, StructByVal); - EXPECT_NOT_POISONED(s.a); - EXPECT_POISONED(s.b); - EXPECT_NOT_POISONED(s.c); - EXPECT_POISONED(s.d); - EXPECT_NOT_POISONED(s.e); - EXPECT_POISONED(s.f); - } - va_end(vl); -} - -TEST(MemorySanitizer, VAArgStructByVal) { - StructByVal s; - s.a = 1; - s.b = *GetPoisoned<int>(); - s.c = 2; - s.d = *GetPoisoned<int>(); - s.e = 3; - s.f = *GetPoisoned<int>(); - vaargsfn_structbyval(0, s, s); -} - -NOINLINE void StructByValTestFunc(struct StructByVal s) { - EXPECT_NOT_POISONED(s.a); - EXPECT_POISONED(s.b); - EXPECT_NOT_POISONED(s.c); - EXPECT_POISONED(s.d); - EXPECT_NOT_POISONED(s.e); - EXPECT_POISONED(s.f); -} - -NOINLINE void StructByValTestFunc1(struct StructByVal s) { - StructByValTestFunc(s); -} - -NOINLINE void StructByValTestFunc2(int z, struct StructByVal s) { - StructByValTestFunc(s); -} - -TEST(MemorySanitizer, StructByVal) { - // Large aggregates are passed as "byval" pointer argument in LLVM. - struct StructByVal s; - s.a = 1; - s.b = *GetPoisoned<int>(); - s.c = 2; - s.d = *GetPoisoned<int>(); - s.e = 3; - s.f = *GetPoisoned<int>(); - StructByValTestFunc(s); - StructByValTestFunc1(s); - StructByValTestFunc2(0, s); -} - - -#if MSAN_HAS_M128 -NOINLINE __m128i m128Eq(__m128i *a, __m128i *b) { return _mm_cmpeq_epi16(*a, *b); } -NOINLINE __m128i m128Lt(__m128i *a, __m128i *b) { return _mm_cmplt_epi16(*a, *b); } -TEST(MemorySanitizer, m128) { - __m128i a = _mm_set1_epi16(0x1234); - __m128i b = _mm_set1_epi16(0x7890); - EXPECT_NOT_POISONED(m128Eq(&a, &b)); - EXPECT_NOT_POISONED(m128Lt(&a, &b)); -} -// FIXME: add more tests for __m128i. -#endif // MSAN_HAS_M128 - -// We should not complain when copying this poisoned hole. -struct StructWithHole { - U4 a; - // 4-byte hole. - U8 b; -}; - -NOINLINE StructWithHole ReturnStructWithHole() { - StructWithHole res; - __msan_poison(&res, sizeof(res)); - res.a = 1; - res.b = 2; - return res; -} - -TEST(MemorySanitizer, StructWithHole) { - StructWithHole a = ReturnStructWithHole(); - break_optimization(&a); -} - -template <class T> -NOINLINE T ReturnStruct() { - T res; - __msan_poison(&res, sizeof(res)); - res.a = 1; - return res; -} - -template <class T> -NOINLINE void TestReturnStruct() { - T s1 = ReturnStruct<T>(); - EXPECT_NOT_POISONED(s1.a); - EXPECT_POISONED(s1.b); -} - -struct SSS1 { - int a, b, c; -}; -struct SSS2 { - int b, a, c; -}; -struct SSS3 { - int b, c, a; -}; -struct SSS4 { - int c, b, a; -}; - -struct SSS5 { - int a; - float b; -}; -struct SSS6 { - int a; - double b; -}; -struct SSS7 { - S8 b; - int a; -}; -struct SSS8 { - S2 b; - S8 a; -}; - -TEST(MemorySanitizer, IntStruct3) { - TestReturnStruct<SSS1>(); - TestReturnStruct<SSS2>(); - TestReturnStruct<SSS3>(); - TestReturnStruct<SSS4>(); - TestReturnStruct<SSS5>(); - TestReturnStruct<SSS6>(); - TestReturnStruct<SSS7>(); - TestReturnStruct<SSS8>(); -} - -struct LongStruct { - U1 a1, b1; - U2 a2, b2; - U4 a4, b4; - U8 a8, b8; -}; - -NOINLINE LongStruct ReturnLongStruct1() { - LongStruct res; - __msan_poison(&res, sizeof(res)); - res.a1 = res.a2 = res.a4 = res.a8 = 111; - // leaves b1, .., b8 poisoned. - return res; -} - -NOINLINE LongStruct ReturnLongStruct2() { - LongStruct res; - __msan_poison(&res, sizeof(res)); - res.b1 = res.b2 = res.b4 = res.b8 = 111; - // leaves a1, .., a8 poisoned. - return res; -} - -TEST(MemorySanitizer, LongStruct) { - LongStruct s1 = ReturnLongStruct1(); - __msan_print_shadow(&s1, sizeof(s1)); - EXPECT_NOT_POISONED(s1.a1); - EXPECT_NOT_POISONED(s1.a2); - EXPECT_NOT_POISONED(s1.a4); - EXPECT_NOT_POISONED(s1.a8); - - EXPECT_POISONED(s1.b1); - EXPECT_POISONED(s1.b2); - EXPECT_POISONED(s1.b4); - EXPECT_POISONED(s1.b8); - - LongStruct s2 = ReturnLongStruct2(); - __msan_print_shadow(&s2, sizeof(s2)); - EXPECT_NOT_POISONED(s2.b1); - EXPECT_NOT_POISONED(s2.b2); - EXPECT_NOT_POISONED(s2.b4); - EXPECT_NOT_POISONED(s2.b8); - - EXPECT_POISONED(s2.a1); - EXPECT_POISONED(s2.a2); - EXPECT_POISONED(s2.a4); - EXPECT_POISONED(s2.a8); -} - -#if defined(__FreeBSD__) || defined(__NetBSD__) -#define MSAN_TEST_PRLIMIT 0 -#elif defined(__GLIBC__) -#define MSAN_TEST_PRLIMIT __GLIBC_PREREQ(2, 13) -#else -#define MSAN_TEST_PRLIMIT 1 -#endif - -TEST(MemorySanitizer, getrlimit) { - struct rlimit limit; - __msan_poison(&limit, sizeof(limit)); - int result = getrlimit(RLIMIT_DATA, &limit); - ASSERT_EQ(result, 0); - EXPECT_NOT_POISONED(limit.rlim_cur); - EXPECT_NOT_POISONED(limit.rlim_max); - -#if MSAN_TEST_PRLIMIT - struct rlimit limit2; - __msan_poison(&limit2, sizeof(limit2)); - result = prlimit(getpid(), RLIMIT_DATA, &limit, &limit2); - ASSERT_EQ(result, 0); - EXPECT_NOT_POISONED(limit2.rlim_cur); - EXPECT_NOT_POISONED(limit2.rlim_max); - - __msan_poison(&limit, sizeof(limit)); - result = prlimit(getpid(), RLIMIT_DATA, nullptr, &limit); - ASSERT_EQ(result, 0); - EXPECT_NOT_POISONED(limit.rlim_cur); - EXPECT_NOT_POISONED(limit.rlim_max); - - result = prlimit(getpid(), RLIMIT_DATA, &limit, nullptr); - ASSERT_EQ(result, 0); -#endif -} - -TEST(MemorySanitizer, getrusage) { - struct rusage usage; - __msan_poison(&usage, sizeof(usage)); - int result = getrusage(RUSAGE_SELF, &usage); - ASSERT_EQ(result, 0); - EXPECT_NOT_POISONED(usage.ru_utime.tv_sec); - EXPECT_NOT_POISONED(usage.ru_utime.tv_usec); - EXPECT_NOT_POISONED(usage.ru_stime.tv_sec); - EXPECT_NOT_POISONED(usage.ru_stime.tv_usec); - EXPECT_NOT_POISONED(usage.ru_maxrss); - EXPECT_NOT_POISONED(usage.ru_minflt); - EXPECT_NOT_POISONED(usage.ru_majflt); - EXPECT_NOT_POISONED(usage.ru_inblock); - EXPECT_NOT_POISONED(usage.ru_oublock); - EXPECT_NOT_POISONED(usage.ru_nvcsw); - EXPECT_NOT_POISONED(usage.ru_nivcsw); -} - -#if defined(__FreeBSD__) || defined(__NetBSD__) -static void GetProgramPath(char *buf, size_t sz) { -#if defined(__FreeBSD__) - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; -#elif defined(__NetBSD__) - int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME}; -#endif - int res = sysctl(mib, 4, buf, &sz, NULL, 0); - ASSERT_EQ(0, res); -} -#elif defined(__GLIBC__) -static void GetProgramPath(char *buf, size_t sz) { - extern char *program_invocation_name; - int res = snprintf(buf, sz, "%s", program_invocation_name); - ASSERT_GE(res, 0); - ASSERT_LT((size_t)res, sz); -} -#else -# error "TODO: port this" -#endif - -static void dladdr_testfn() {} - -TEST(MemorySanitizer, dladdr) { - Dl_info info; - __msan_poison(&info, sizeof(info)); - int result = dladdr((const void*)dladdr_testfn, &info); - ASSERT_NE(result, 0); - EXPECT_NOT_POISONED((unsigned long)info.dli_fname); - if (info.dli_fname) - EXPECT_NOT_POISONED(strlen(info.dli_fname)); - EXPECT_NOT_POISONED((unsigned long)info.dli_fbase); - EXPECT_NOT_POISONED((unsigned long)info.dli_sname); - if (info.dli_sname) - EXPECT_NOT_POISONED(strlen(info.dli_sname)); - EXPECT_NOT_POISONED((unsigned long)info.dli_saddr); -} - -#ifndef MSAN_TEST_DISABLE_DLOPEN - -static int dl_phdr_callback(struct dl_phdr_info *info, size_t size, void *data) { - (*(int *)data)++; - EXPECT_NOT_POISONED(info->dlpi_addr); - EXPECT_NOT_POISONED(strlen(info->dlpi_name)); - EXPECT_NOT_POISONED(info->dlpi_phnum); - for (int i = 0; i < info->dlpi_phnum; ++i) - EXPECT_NOT_POISONED(info->dlpi_phdr[i]); - return 0; -} - -// Compute the path to our loadable DSO. We assume it's in the same -// directory. Only use string routines that we intercept so far to do this. -static void GetPathToLoadable(char *buf, size_t sz) { - char program_path[kMaxPathLength]; - GetProgramPath(program_path, sizeof(program_path)); - - const char *last_slash = strrchr(program_path, '/'); - ASSERT_NE(nullptr, last_slash); - size_t dir_len = (size_t)(last_slash - program_path); -#if defined(__x86_64__) - static const char basename[] = "libmsan_loadable.x86_64.so"; -#elif defined(__MIPSEB__) || defined(MIPSEB) - static const char basename[] = "libmsan_loadable.mips64.so"; -#elif defined(__mips64) - static const char basename[] = "libmsan_loadable.mips64el.so"; -#elif defined(__aarch64__) - static const char basename[] = "libmsan_loadable.aarch64.so"; -#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - static const char basename[] = "libmsan_loadable.powerpc64.so"; -#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - static const char basename[] = "libmsan_loadable.powerpc64le.so"; -#endif - int res = snprintf(buf, sz, "%.*s/%s", - (int)dir_len, program_path, basename); - ASSERT_GE(res, 0); - ASSERT_LT((size_t)res, sz); -} - -TEST(MemorySanitizer, dl_iterate_phdr) { - char path[kMaxPathLength]; - GetPathToLoadable(path, sizeof(path)); - - // Having at least one dlopen'ed library in the process makes this more - // entertaining. - void *lib = dlopen(path, RTLD_LAZY); - ASSERT_NE((void*)0, lib); - - int count = 0; - int result = dl_iterate_phdr(dl_phdr_callback, &count); - ASSERT_GT(count, 0); - - dlclose(lib); -} - -TEST(MemorySanitizer, dlopen) { - char path[kMaxPathLength]; - GetPathToLoadable(path, sizeof(path)); - - // We need to clear shadow for globals when doing dlopen. In order to test - // this, we have to poison the shadow for the DSO before we load it. In - // general this is difficult, but the loader tends to reload things in the - // same place, so we open, close, and then reopen. The global should always - // start out clean after dlopen. - for (int i = 0; i < 2; i++) { - void *lib = dlopen(path, RTLD_LAZY); - if (lib == NULL) { - printf("dlerror: %s\n", dlerror()); - ASSERT_TRUE(lib != NULL); - } - void **(*get_dso_global)() = (void **(*)())dlsym(lib, "get_dso_global"); - ASSERT_TRUE(get_dso_global != NULL); - void **dso_global = get_dso_global(); - EXPECT_NOT_POISONED(*dso_global); - __msan_poison(dso_global, sizeof(*dso_global)); - EXPECT_POISONED(*dso_global); - dlclose(lib); - } -} - -// Regression test for a crash in dlopen() interceptor. -TEST(MemorySanitizer, dlopenFailed) { - const char *path = "/libmsan_loadable_does_not_exist.so"; - void *lib = dlopen(path, RTLD_LAZY); - ASSERT_TRUE(lib == NULL); -} - -#endif // MSAN_TEST_DISABLE_DLOPEN - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, sched_getaffinity) { - cpu_set_t mask; - int res = sched_getaffinity(getpid(), sizeof(mask), &mask); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(mask); -} -#endif - -TEST(MemorySanitizer, scanf) { - const char *input = "42 hello"; - int* d = new int; - char* s = new char[7]; - int res = sscanf(input, "%d %5s", d, s); - printf("res %d\n", res); - ASSERT_EQ(res, 2); - EXPECT_NOT_POISONED(*d); - EXPECT_NOT_POISONED(s[0]); - EXPECT_NOT_POISONED(s[1]); - EXPECT_NOT_POISONED(s[2]); - EXPECT_NOT_POISONED(s[3]); - EXPECT_NOT_POISONED(s[4]); - EXPECT_NOT_POISONED(s[5]); - EXPECT_POISONED(s[6]); - delete[] s; - delete d; -} - -static void *SimpleThread_threadfn(void* data) { - return new int; -} - -TEST(MemorySanitizer, SimpleThread) { - pthread_t t; - void *p; - int res = pthread_create(&t, NULL, SimpleThread_threadfn, NULL); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(t); - res = pthread_join(t, &p); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(p); - delete (int*)p; -} - -static void *SmallStackThread_threadfn(void* data) { - return 0; -} - -#ifdef PTHREAD_STACK_MIN -# define SMALLSTACKSIZE PTHREAD_STACK_MIN -# define SMALLPRESTACKSIZE PTHREAD_STACK_MIN -#else -# define SMALLSTACKSIZE 64 * 1024 -# define SMALLPRESTACKSIZE 16 * 1024 -#endif - -TEST(MemorySanitizer, SmallStackThread) { - pthread_attr_t attr; - pthread_t t; - void *p; - int res; - res = pthread_attr_init(&attr); - ASSERT_EQ(0, res); - res = pthread_attr_setstacksize(&attr, SMALLSTACKSIZE); - ASSERT_EQ(0, res); - res = pthread_create(&t, &attr, SmallStackThread_threadfn, NULL); - ASSERT_EQ(0, res); - res = pthread_join(t, &p); - ASSERT_EQ(0, res); - res = pthread_attr_destroy(&attr); - ASSERT_EQ(0, res); -} - -TEST(MemorySanitizer, SmallPreAllocatedStackThread) { - pthread_attr_t attr; - pthread_t t; - int res; - res = pthread_attr_init(&attr); - ASSERT_EQ(0, res); - void *stack; - const size_t kStackSize = SMALLPRESTACKSIZE; - res = posix_memalign(&stack, 4096, kStackSize); - ASSERT_EQ(0, res); - res = pthread_attr_setstack(&attr, stack, kStackSize); - ASSERT_EQ(0, res); - res = pthread_create(&t, &attr, SmallStackThread_threadfn, NULL); - EXPECT_EQ(0, res); - res = pthread_join(t, NULL); - ASSERT_EQ(0, res); - res = pthread_attr_destroy(&attr); - ASSERT_EQ(0, res); -} - -TEST(MemorySanitizer, pthread_attr_get) { - pthread_attr_t attr; - int res; - res = pthread_attr_init(&attr); - ASSERT_EQ(0, res); - { - int v; - res = pthread_attr_getdetachstate(&attr, &v); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - } - { - size_t v; - res = pthread_attr_getguardsize(&attr, &v); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - } - { - struct sched_param v; - res = pthread_attr_getschedparam(&attr, &v); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - } - { - int v; - res = pthread_attr_getschedpolicy(&attr, &v); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - } - { - int v; - res = pthread_attr_getinheritsched(&attr, &v); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - } - { - int v; - res = pthread_attr_getscope(&attr, &v); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - } - { - size_t v; - res = pthread_attr_getstacksize(&attr, &v); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - } - { - void *v; - size_t w; - res = pthread_attr_getstack(&attr, &v, &w); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - EXPECT_NOT_POISONED(w); - } -#if !defined(__NetBSD__) - { - cpu_set_t v; - res = pthread_attr_getaffinity_np(&attr, sizeof(v), &v); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(v); - } -#endif - res = pthread_attr_destroy(&attr); - ASSERT_EQ(0, res); -} - -TEST(MemorySanitizer, pthread_getschedparam) { - int policy; - struct sched_param param; - int res = pthread_getschedparam(pthread_self(), &policy, ¶m); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(policy); - EXPECT_NOT_POISONED(param.sched_priority); -} - -TEST(MemorySanitizer, pthread_key_create) { - pthread_key_t key; - int res = pthread_key_create(&key, NULL); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(key); - res = pthread_key_delete(key); - ASSERT_EQ(0, res); -} - -namespace { -struct SignalCondArg { - pthread_cond_t* cond; - pthread_mutex_t* mu; - bool broadcast; -}; - -void *SignalCond(void *param) { - SignalCondArg *arg = reinterpret_cast<SignalCondArg *>(param); - pthread_mutex_lock(arg->mu); - if (arg->broadcast) - pthread_cond_broadcast(arg->cond); - else - pthread_cond_signal(arg->cond); - pthread_mutex_unlock(arg->mu); - return 0; -} -} // namespace - -TEST(MemorySanitizer, pthread_cond_wait) { - pthread_cond_t cond; - pthread_mutex_t mu; - SignalCondArg args = {&cond, &mu, false}; - pthread_cond_init(&cond, 0); - pthread_mutex_init(&mu, 0); - pthread_mutex_lock(&mu); - - // signal - pthread_t thr; - pthread_create(&thr, 0, SignalCond, &args); - int res = pthread_cond_wait(&cond, &mu); - ASSERT_EQ(0, res); - pthread_join(thr, 0); - - // broadcast - args.broadcast = true; - pthread_create(&thr, 0, SignalCond, &args); - res = pthread_cond_wait(&cond, &mu); - ASSERT_EQ(0, res); - pthread_join(thr, 0); - - pthread_mutex_unlock(&mu); - pthread_mutex_destroy(&mu); - pthread_cond_destroy(&cond); -} - -TEST(MemorySanitizer, tmpnam) { - char s[L_tmpnam]; - char *res = tmpnam(s); - ASSERT_EQ(s, res); - EXPECT_NOT_POISONED(strlen(res)); -} - -TEST(MemorySanitizer, tempnam) { - char *res = tempnam(NULL, "zzz"); - EXPECT_NOT_POISONED(strlen(res)); - free(res); -} - -TEST(MemorySanitizer, posix_memalign) { - void *p; - EXPECT_POISONED(p); - int res = posix_memalign(&p, 4096, 13); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(p); - EXPECT_EQ(0U, (uintptr_t)p % 4096); - free(p); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, memalign) { - void *p = memalign(4096, 13); - EXPECT_EQ(0U, (uintptr_t)p % 4096); - free(p); -} -#endif - -TEST(MemorySanitizer, valloc) { - void *a = valloc(100); - uintptr_t PageSize = GetPageSize(); - EXPECT_EQ(0U, (uintptr_t)a % PageSize); - free(a); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, pvalloc) { - uintptr_t PageSize = GetPageSize(); - void *p = pvalloc(PageSize + 100); - EXPECT_EQ(0U, (uintptr_t)p % PageSize); - EXPECT_EQ(2 * PageSize, __sanitizer_get_allocated_size(p)); - free(p); - - p = pvalloc(0); // pvalloc(0) should allocate at least one page. - EXPECT_EQ(0U, (uintptr_t)p % PageSize); - EXPECT_EQ(PageSize, __sanitizer_get_allocated_size(p)); - free(p); -} -#endif - -TEST(MemorySanitizer, inet_pton) { - const char *s = "1:0:0:0:0:0:0:8"; - unsigned char buf[sizeof(struct in6_addr)]; - int res = inet_pton(AF_INET6, s, buf); - ASSERT_EQ(1, res); - EXPECT_NOT_POISONED(buf[0]); - EXPECT_NOT_POISONED(buf[sizeof(struct in6_addr) - 1]); - - char s_out[INET6_ADDRSTRLEN]; - EXPECT_POISONED(s_out[3]); - const char *q = inet_ntop(AF_INET6, buf, s_out, INET6_ADDRSTRLEN); - ASSERT_NE((void*)0, q); - EXPECT_NOT_POISONED(s_out[3]); -} - -TEST(MemorySanitizer, inet_aton) { - const char *s = "127.0.0.1"; - struct in_addr in[2]; - int res = inet_aton(s, in); - ASSERT_NE(0, res); - EXPECT_NOT_POISONED(in[0]); - EXPECT_POISONED(*(char *)(in + 1)); -} - -TEST(MemorySanitizer, uname) { - struct utsname u; - int res = uname(&u); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(strlen(u.sysname)); - EXPECT_NOT_POISONED(strlen(u.nodename)); - EXPECT_NOT_POISONED(strlen(u.release)); - EXPECT_NOT_POISONED(strlen(u.version)); - EXPECT_NOT_POISONED(strlen(u.machine)); -} - -TEST(MemorySanitizer, gethostname) { - char buf[100]; - int res = gethostname(buf, 100); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(strlen(buf)); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, sysinfo) { - struct sysinfo info; - int res = sysinfo(&info); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(info); -} -#endif - -TEST(MemorySanitizer, getpwuid) { - struct passwd *p = getpwuid(0); // root - ASSERT_TRUE(p != NULL); - EXPECT_NOT_POISONED(p->pw_name); - ASSERT_TRUE(p->pw_name != NULL); - EXPECT_NOT_POISONED(p->pw_name[0]); - EXPECT_NOT_POISONED(p->pw_uid); - ASSERT_EQ(0U, p->pw_uid); -} - -TEST(MemorySanitizer, getpwuid_r) { - struct passwd pwd; - struct passwd *pwdres; - char buf[10000]; - int res = getpwuid_r(0, &pwd, buf, sizeof(buf), &pwdres); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(pwd.pw_name); - ASSERT_TRUE(pwd.pw_name != NULL); - EXPECT_NOT_POISONED(pwd.pw_name[0]); - EXPECT_NOT_POISONED(pwd.pw_uid); - ASSERT_EQ(0U, pwd.pw_uid); - EXPECT_NOT_POISONED(pwdres); -} - -TEST(MemorySanitizer, getpwnam_r) { - struct passwd pwd; - struct passwd *pwdres; - char buf[10000]; - int res = getpwnam_r("root", &pwd, buf, sizeof(buf), &pwdres); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(pwd.pw_name); - ASSERT_TRUE(pwd.pw_name != NULL); - EXPECT_NOT_POISONED(pwd.pw_name[0]); - EXPECT_NOT_POISONED(pwd.pw_uid); - ASSERT_EQ(0U, pwd.pw_uid); - EXPECT_NOT_POISONED(pwdres); -} - -TEST(MemorySanitizer, getpwnam_r_positive) { - struct passwd pwd; - struct passwd *pwdres; - char s[5]; - strncpy(s, "abcd", 5); - __msan_poison(s, 5); - char buf[10000]; - int res; - EXPECT_UMR(res = getpwnam_r(s, &pwd, buf, sizeof(buf), &pwdres)); -} - -TEST(MemorySanitizer, getgrnam_r) { - struct group grp; - struct group *grpres; - char buf[10000]; - int res = getgrnam_r(SUPERUSER_GROUP, &grp, buf, sizeof(buf), &grpres); - ASSERT_EQ(0, res); - // Note that getgrnam_r() returns 0 if the matching group is not found. - ASSERT_NE(nullptr, grpres); - EXPECT_NOT_POISONED(grp.gr_name); - ASSERT_TRUE(grp.gr_name != NULL); - EXPECT_NOT_POISONED(grp.gr_name[0]); - EXPECT_NOT_POISONED(grp.gr_gid); - EXPECT_NOT_POISONED(grpres); -} - -TEST(MemorySanitizer, getpwent) { - setpwent(); - struct passwd *p = getpwent(); - ASSERT_TRUE(p != NULL); - EXPECT_NOT_POISONED(p->pw_name); - ASSERT_TRUE(p->pw_name != NULL); - EXPECT_NOT_POISONED(p->pw_name[0]); - EXPECT_NOT_POISONED(p->pw_uid); -} - -TEST(MemorySanitizer, getpwent_r) { - struct passwd pwd; - struct passwd *pwdres; - char buf[10000]; - setpwent(); - int res = getpwent_r(&pwd, buf, sizeof(buf), &pwdres); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(pwd.pw_name); - ASSERT_TRUE(pwd.pw_name != NULL); - EXPECT_NOT_POISONED(pwd.pw_name[0]); - EXPECT_NOT_POISONED(pwd.pw_uid); - EXPECT_NOT_POISONED(pwdres); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, fgetpwent) { - FILE *fp = fopen("/etc/passwd", "r"); - struct passwd *p = fgetpwent(fp); - ASSERT_TRUE(p != NULL); - EXPECT_NOT_POISONED(p->pw_name); - ASSERT_TRUE(p->pw_name != NULL); - EXPECT_NOT_POISONED(p->pw_name[0]); - EXPECT_NOT_POISONED(p->pw_uid); - fclose(fp); -} -#endif - -TEST(MemorySanitizer, getgrent) { - setgrent(); - struct group *p = getgrent(); - ASSERT_TRUE(p != NULL); - EXPECT_NOT_POISONED(p->gr_name); - ASSERT_TRUE(p->gr_name != NULL); - EXPECT_NOT_POISONED(p->gr_name[0]); - EXPECT_NOT_POISONED(p->gr_gid); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, fgetgrent) { - FILE *fp = fopen("/etc/group", "r"); - struct group *grp = fgetgrent(fp); - ASSERT_TRUE(grp != NULL); - EXPECT_NOT_POISONED(grp->gr_name); - ASSERT_TRUE(grp->gr_name != NULL); - EXPECT_NOT_POISONED(grp->gr_name[0]); - EXPECT_NOT_POISONED(grp->gr_gid); - for (char **p = grp->gr_mem; *p; ++p) { - EXPECT_NOT_POISONED((*p)[0]); - EXPECT_TRUE(strlen(*p) > 0); - } - fclose(fp); -} -#endif - -TEST(MemorySanitizer, getgrent_r) { - struct group grp; - struct group *grpres; - char buf[10000]; - setgrent(); - int res = getgrent_r(&grp, buf, sizeof(buf), &grpres); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(grp.gr_name); - ASSERT_TRUE(grp.gr_name != NULL); - EXPECT_NOT_POISONED(grp.gr_name[0]); - EXPECT_NOT_POISONED(grp.gr_gid); - EXPECT_NOT_POISONED(grpres); -} - -#if !defined(__FreeBSD__) && !defined(__NetBSD__) -TEST(MemorySanitizer, fgetgrent_r) { - FILE *fp = fopen("/etc/group", "r"); - struct group grp; - struct group *grpres; - char buf[10000]; - setgrent(); - int res = fgetgrent_r(fp, &grp, buf, sizeof(buf), &grpres); - ASSERT_EQ(0, res); - EXPECT_NOT_POISONED(grp.gr_name); - ASSERT_TRUE(grp.gr_name != NULL); - EXPECT_NOT_POISONED(grp.gr_name[0]); - EXPECT_NOT_POISONED(grp.gr_gid); - EXPECT_NOT_POISONED(grpres); - fclose(fp); -} -#endif - -TEST(MemorySanitizer, getgroups) { - int n = getgroups(0, 0); - gid_t *gids = new gid_t[n]; - int res = getgroups(n, gids); - ASSERT_EQ(n, res); - for (int i = 0; i < n; ++i) - EXPECT_NOT_POISONED(gids[i]); -} - -TEST(MemorySanitizer, getgroups_zero) { - gid_t group; - int n = getgroups(0, &group); - ASSERT_GE(n, 0); -} - -TEST(MemorySanitizer, getgroups_negative) { - gid_t group; - int n = getgroups(-1, 0); - ASSERT_EQ(-1, n); - - n = getgroups(-1, 0); - ASSERT_EQ(-1, n); -} - -TEST(MemorySanitizer, wordexp) { - wordexp_t w; - int res = wordexp("a b c", &w, 0); - ASSERT_EQ(0, res); - ASSERT_EQ(3U, w.we_wordc); - ASSERT_STREQ("a", w.we_wordv[0]); - ASSERT_STREQ("b", w.we_wordv[1]); - ASSERT_STREQ("c", w.we_wordv[2]); -} - -template<class T> -static bool applySlt(T value, T shadow) { - __msan_partial_poison(&value, &shadow, sizeof(T)); - volatile bool zzz = true; - // This "|| zzz" trick somehow makes LLVM emit "icmp slt" instead of - // a shift-and-trunc to get at the highest bit. - volatile bool v = value < 0 || zzz; - return v; -} - -TEST(MemorySanitizer, SignedCompareWithZero) { - EXPECT_NOT_POISONED(applySlt<S4>(0xF, 0xF)); - EXPECT_NOT_POISONED(applySlt<S4>(0xF, 0xFF)); - EXPECT_NOT_POISONED(applySlt<S4>(0xF, 0xFFFFFF)); - EXPECT_NOT_POISONED(applySlt<S4>(0xF, 0x7FFFFFF)); - EXPECT_UMR(applySlt<S4>(0xF, 0x80FFFFFF)); - EXPECT_UMR(applySlt<S4>(0xF, 0xFFFFFFFF)); -} - -template <class T, class S> -static T poisoned(T Va, S Sa) { - char SIZE_CHECK1[(ssize_t)sizeof(T) - (ssize_t)sizeof(S)]; - char SIZE_CHECK2[(ssize_t)sizeof(S) - (ssize_t)sizeof(T)]; - T a; - a = Va; - __msan_partial_poison(&a, &Sa, sizeof(T)); - return a; -} - -TEST(MemorySanitizer, ICmpRelational) { - EXPECT_NOT_POISONED(poisoned(0, 0) < poisoned(0, 0)); - EXPECT_NOT_POISONED(poisoned(0U, 0) < poisoned(0U, 0)); - EXPECT_NOT_POISONED(poisoned(0LL, 0LLU) < poisoned(0LL, 0LLU)); - EXPECT_NOT_POISONED(poisoned(0LLU, 0LLU) < poisoned(0LLU, 0LLU)); - EXPECT_POISONED(poisoned(0xFF, 0xFF) < poisoned(0xFF, 0xFF)); - EXPECT_POISONED(poisoned(0xFFFFFFFFU, 0xFFFFFFFFU) < - poisoned(0xFFFFFFFFU, 0xFFFFFFFFU)); - EXPECT_POISONED(poisoned(-1, 0xFFFFFFFFU) < - poisoned(-1, 0xFFFFFFFFU)); - - EXPECT_NOT_POISONED(poisoned(0, 0) <= poisoned(0, 0)); - EXPECT_NOT_POISONED(poisoned(0U, 0) <= poisoned(0U, 0)); - EXPECT_NOT_POISONED(poisoned(0LL, 0LLU) <= poisoned(0LL, 0LLU)); - EXPECT_NOT_POISONED(poisoned(0LLU, 0LLU) <= poisoned(0LLU, 0LLU)); - EXPECT_POISONED(poisoned(0xFF, 0xFF) <= poisoned(0xFF, 0xFF)); - EXPECT_POISONED(poisoned(0xFFFFFFFFU, 0xFFFFFFFFU) <= - poisoned(0xFFFFFFFFU, 0xFFFFFFFFU)); - EXPECT_POISONED(poisoned(-1, 0xFFFFFFFFU) <= - poisoned(-1, 0xFFFFFFFFU)); - - EXPECT_NOT_POISONED(poisoned(0, 0) > poisoned(0, 0)); - EXPECT_NOT_POISONED(poisoned(0U, 0) > poisoned(0U, 0)); - EXPECT_NOT_POISONED(poisoned(0LL, 0LLU) > poisoned(0LL, 0LLU)); - EXPECT_NOT_POISONED(poisoned(0LLU, 0LLU) > poisoned(0LLU, 0LLU)); - EXPECT_POISONED(poisoned(0xFF, 0xFF) > poisoned(0xFF, 0xFF)); - EXPECT_POISONED(poisoned(0xFFFFFFFFU, 0xFFFFFFFFU) > - poisoned(0xFFFFFFFFU, 0xFFFFFFFFU)); - EXPECT_POISONED(poisoned(-1, 0xFFFFFFFFU) > - poisoned(-1, 0xFFFFFFFFU)); - - EXPECT_NOT_POISONED(poisoned(0, 0) >= poisoned(0, 0)); - EXPECT_NOT_POISONED(poisoned(0U, 0) >= poisoned(0U, 0)); - EXPECT_NOT_POISONED(poisoned(0LL, 0LLU) >= poisoned(0LL, 0LLU)); - EXPECT_NOT_POISONED(poisoned(0LLU, 0LLU) >= poisoned(0LLU, 0LLU)); - EXPECT_POISONED(poisoned(0xFF, 0xFF) >= poisoned(0xFF, 0xFF)); - EXPECT_POISONED(poisoned(0xFFFFFFFFU, 0xFFFFFFFFU) >= - poisoned(0xFFFFFFFFU, 0xFFFFFFFFU)); - EXPECT_POISONED(poisoned(-1, 0xFFFFFFFFU) >= - poisoned(-1, 0xFFFFFFFFU)); - - EXPECT_POISONED(poisoned(6, 0xF) > poisoned(7, 0)); - EXPECT_POISONED(poisoned(0xF, 0xF) > poisoned(7, 0)); - // Note that "icmp op X, Y" is approximated with "or shadow(X), shadow(Y)" - // and therefore may generate false positives in some cases, e.g. the - // following one: - // EXPECT_NOT_POISONED(poisoned(-1, 0x80000000U) >= poisoned(-1, 0U)); -} - -#if MSAN_HAS_M128 -TEST(MemorySanitizer, ICmpVectorRelational) { - EXPECT_NOT_POISONED( - _mm_cmplt_epi16(poisoned(_mm_set1_epi16(0), _mm_set1_epi16(0)), - poisoned(_mm_set1_epi16(0), _mm_set1_epi16(0)))); - EXPECT_NOT_POISONED( - _mm_cmplt_epi16(poisoned(_mm_set1_epi32(0), _mm_set1_epi32(0)), - poisoned(_mm_set1_epi32(0), _mm_set1_epi32(0)))); - EXPECT_POISONED( - _mm_cmplt_epi16(poisoned(_mm_set1_epi16(0), _mm_set1_epi16(0xFFFF)), - poisoned(_mm_set1_epi16(0), _mm_set1_epi16(0xFFFF)))); - EXPECT_POISONED(_mm_cmpgt_epi16(poisoned(_mm_set1_epi16(6), _mm_set1_epi16(0xF)), - poisoned(_mm_set1_epi16(7), _mm_set1_epi16(0)))); -} - -TEST(MemorySanitizer, stmxcsr_ldmxcsr) { - U4 x = _mm_getcsr(); - EXPECT_NOT_POISONED(x); - - _mm_setcsr(x); - - __msan_poison(&x, sizeof(x)); - U4 origin = __LINE__; - __msan_set_origin(&x, sizeof(x), origin); - EXPECT_UMR_O(_mm_setcsr(x), origin); -} -#endif - -// Volatile bitfield store is implemented as load-mask-store -// Test that we don't warn on the store of (uninitialized) padding. -struct VolatileBitfieldStruct { - volatile unsigned x : 1; - unsigned y : 1; -}; - -TEST(MemorySanitizer, VolatileBitfield) { - VolatileBitfieldStruct *S = new VolatileBitfieldStruct; - S->x = 1; - EXPECT_NOT_POISONED((unsigned)S->x); - EXPECT_POISONED((unsigned)S->y); -} - -TEST(MemorySanitizer, UnalignedLoad) { - char x[32] __attribute__((aligned(8))); - U4 origin = __LINE__; - for (unsigned i = 0; i < sizeof(x) / 4; ++i) - __msan_set_origin(x + 4 * i, 4, origin + i); - - memset(x + 8, 0, 16); - EXPECT_POISONED_O(__sanitizer_unaligned_load16(x + 6), origin + 1); - EXPECT_POISONED_O(__sanitizer_unaligned_load16(x + 7), origin + 1); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x + 8)); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x + 9)); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load16(x + 22)); - EXPECT_POISONED_O(__sanitizer_unaligned_load16(x + 23), origin + 6); - EXPECT_POISONED_O(__sanitizer_unaligned_load16(x + 24), origin + 6); - - EXPECT_POISONED_O(__sanitizer_unaligned_load32(x + 4), origin + 1); - EXPECT_POISONED_O(__sanitizer_unaligned_load32(x + 7), origin + 1); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x + 8)); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x + 9)); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load32(x + 20)); - EXPECT_POISONED_O(__sanitizer_unaligned_load32(x + 21), origin + 6); - EXPECT_POISONED_O(__sanitizer_unaligned_load32(x + 24), origin + 6); - - EXPECT_POISONED_O(__sanitizer_unaligned_load64(x), origin); - EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 1), origin); - EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 7), origin + 1); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x + 8)); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x + 9)); - EXPECT_NOT_POISONED(__sanitizer_unaligned_load64(x + 16)); - EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 17), origin + 6); - EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 21), origin + 6); - EXPECT_POISONED_O(__sanitizer_unaligned_load64(x + 24), origin + 6); -} - -TEST(MemorySanitizer, UnalignedStore16) { - char x[5] __attribute__((aligned(4))); - U2 y2 = 0; - U4 origin = __LINE__; - __msan_poison(&y2, 1); - __msan_set_origin(&y2, 1, origin); - - __sanitizer_unaligned_store16(x + 1, y2); - EXPECT_POISONED_O(x[0], origin); - EXPECT_POISONED_O(x[1], origin); - EXPECT_NOT_POISONED(x[2]); - EXPECT_POISONED_O(x[3], origin); -} - -TEST(MemorySanitizer, UnalignedStore32) { - char x[8] __attribute__((aligned(4))); - U4 y4 = 0; - U4 origin = __LINE__; - __msan_poison(&y4, 2); - __msan_set_origin(&y4, 2, origin); - - __sanitizer_unaligned_store32(x + 3, y4); - EXPECT_POISONED_O(x[0], origin); - EXPECT_POISONED_O(x[1], origin); - EXPECT_POISONED_O(x[2], origin); - EXPECT_POISONED_O(x[3], origin); - EXPECT_POISONED_O(x[4], origin); - EXPECT_NOT_POISONED(x[5]); - EXPECT_NOT_POISONED(x[6]); - EXPECT_POISONED_O(x[7], origin); -} - -TEST(MemorySanitizer, UnalignedStore64) { - char x[16] __attribute__((aligned(8))); - U8 y8 = 0; - U4 origin = __LINE__; - __msan_poison(&y8, 3); - __msan_poison(((char *)&y8) + sizeof(y8) - 2, 1); - __msan_set_origin(&y8, 8, origin); - - __sanitizer_unaligned_store64(x + 3, y8); - EXPECT_POISONED_O(x[0], origin); - EXPECT_POISONED_O(x[1], origin); - EXPECT_POISONED_O(x[2], origin); - EXPECT_POISONED_O(x[3], origin); - EXPECT_POISONED_O(x[4], origin); - EXPECT_POISONED_O(x[5], origin); - EXPECT_NOT_POISONED(x[6]); - EXPECT_NOT_POISONED(x[7]); - EXPECT_NOT_POISONED(x[8]); - EXPECT_POISONED_O(x[9], origin); - EXPECT_NOT_POISONED(x[10]); - EXPECT_POISONED_O(x[11], origin); -} - -TEST(MemorySanitizer, UnalignedStore16_precise) { - char x[8] __attribute__((aligned(4))); - U2 y = 0; - U4 originx1 = __LINE__; - U4 originx2 = __LINE__; - U4 originy = __LINE__; - __msan_poison(x, sizeof(x)); - __msan_set_origin(x, 4, originx1); - __msan_set_origin(x + 4, 4, originx2); - __msan_poison(((char *)&y) + 1, 1); - __msan_set_origin(&y, sizeof(y), originy); - - __sanitizer_unaligned_store16(x + 3, y); - EXPECT_POISONED_O(x[0], originx1); - EXPECT_POISONED_O(x[1], originx1); - EXPECT_POISONED_O(x[2], originx1); - EXPECT_NOT_POISONED(x[3]); - EXPECT_POISONED_O(x[4], originy); - EXPECT_POISONED_O(x[5], originy); - EXPECT_POISONED_O(x[6], originy); - EXPECT_POISONED_O(x[7], originy); -} - -TEST(MemorySanitizer, UnalignedStore16_precise2) { - char x[8] __attribute__((aligned(4))); - U2 y = 0; - U4 originx1 = __LINE__; - U4 originx2 = __LINE__; - U4 originy = __LINE__; - __msan_poison(x, sizeof(x)); - __msan_set_origin(x, 4, originx1); - __msan_set_origin(x + 4, 4, originx2); - __msan_poison(((char *)&y), 1); - __msan_set_origin(&y, sizeof(y), originy); - - __sanitizer_unaligned_store16(x + 3, y); - EXPECT_POISONED_O(x[0], originy); - EXPECT_POISONED_O(x[1], originy); - EXPECT_POISONED_O(x[2], originy); - EXPECT_POISONED_O(x[3], originy); - EXPECT_NOT_POISONED(x[4]); - EXPECT_POISONED_O(x[5], originx2); - EXPECT_POISONED_O(x[6], originx2); - EXPECT_POISONED_O(x[7], originx2); -} - -TEST(MemorySanitizer, UnalignedStore64_precise) { - char x[12] __attribute__((aligned(8))); - U8 y = 0; - U4 originx1 = __LINE__; - U4 originx2 = __LINE__; - U4 originx3 = __LINE__; - U4 originy = __LINE__; - __msan_poison(x, sizeof(x)); - __msan_set_origin(x, 4, originx1); - __msan_set_origin(x + 4, 4, originx2); - __msan_set_origin(x + 8, 4, originx3); - __msan_poison(((char *)&y) + 1, 1); - __msan_poison(((char *)&y) + 7, 1); - __msan_set_origin(&y, sizeof(y), originy); - - __sanitizer_unaligned_store64(x + 2, y); - EXPECT_POISONED_O(x[0], originy); - EXPECT_POISONED_O(x[1], originy); - EXPECT_NOT_POISONED(x[2]); - EXPECT_POISONED_O(x[3], originy); - - EXPECT_NOT_POISONED(x[4]); - EXPECT_NOT_POISONED(x[5]); - EXPECT_NOT_POISONED(x[6]); - EXPECT_NOT_POISONED(x[7]); - - EXPECT_NOT_POISONED(x[8]); - EXPECT_POISONED_O(x[9], originy); - EXPECT_POISONED_O(x[10], originy); - EXPECT_POISONED_O(x[11], originy); -} - -TEST(MemorySanitizer, UnalignedStore64_precise2) { - char x[12] __attribute__((aligned(8))); - U8 y = 0; - U4 originx1 = __LINE__; - U4 originx2 = __LINE__; - U4 originx3 = __LINE__; - U4 originy = __LINE__; - __msan_poison(x, sizeof(x)); - __msan_set_origin(x, 4, originx1); - __msan_set_origin(x + 4, 4, originx2); - __msan_set_origin(x + 8, 4, originx3); - __msan_poison(((char *)&y) + 3, 3); - __msan_set_origin(&y, sizeof(y), originy); - - __sanitizer_unaligned_store64(x + 2, y); - EXPECT_POISONED_O(x[0], originx1); - EXPECT_POISONED_O(x[1], originx1); - EXPECT_NOT_POISONED(x[2]); - EXPECT_NOT_POISONED(x[3]); - - EXPECT_NOT_POISONED(x[4]); - EXPECT_POISONED_O(x[5], originy); - EXPECT_POISONED_O(x[6], originy); - EXPECT_POISONED_O(x[7], originy); - - EXPECT_NOT_POISONED(x[8]); - EXPECT_NOT_POISONED(x[9]); - EXPECT_POISONED_O(x[10], originx3); - EXPECT_POISONED_O(x[11], originx3); -} - -#if (defined(__x86_64__) && defined(__clang__)) -namespace { -typedef U1 V16x8 __attribute__((__vector_size__(16))); -typedef U2 V8x16 __attribute__((__vector_size__(16))); -typedef U4 V4x32 __attribute__((__vector_size__(16))); -typedef U8 V2x64 __attribute__((__vector_size__(16))); -typedef U4 V8x32 __attribute__((__vector_size__(32))); -typedef U8 V4x64 __attribute__((__vector_size__(32))); -typedef U4 V2x32 __attribute__((__vector_size__(8))); -typedef U2 V4x16 __attribute__((__vector_size__(8))); -typedef U1 V8x8 __attribute__((__vector_size__(8))); - -V8x16 shift_sse2_left_scalar(V8x16 x, U4 y) { - return _mm_slli_epi16(x, y); -} - -V8x16 shift_sse2_left(V8x16 x, V8x16 y) { - return _mm_sll_epi16(x, y); -} - -TEST(VectorShiftTest, sse2_left_scalar) { - V8x16 v = {Poisoned<U2>(0, 3), Poisoned<U2>(0, 7), 2, 3, 4, 5, 6, 7}; - V8x16 u = shift_sse2_left_scalar(v, 2); - EXPECT_POISONED(u[0]); - EXPECT_POISONED(u[1]); - EXPECT_NOT_POISONED(u[0] | (3U << 2)); - EXPECT_NOT_POISONED(u[1] | (7U << 2)); - u[0] = u[1] = 0; - EXPECT_NOT_POISONED(u); -} - -TEST(VectorShiftTest, sse2_left_scalar_by_uninit) { - V8x16 v = {0, 1, 2, 3, 4, 5, 6, 7}; - V8x16 u = shift_sse2_left_scalar(v, Poisoned<U4>()); - EXPECT_POISONED(u[0]); - EXPECT_POISONED(u[1]); - EXPECT_POISONED(u[2]); - EXPECT_POISONED(u[3]); - EXPECT_POISONED(u[4]); - EXPECT_POISONED(u[5]); - EXPECT_POISONED(u[6]); - EXPECT_POISONED(u[7]); -} - -TEST(VectorShiftTest, sse2_left) { - V8x16 v = {Poisoned<U2>(0, 3), Poisoned<U2>(0, 7), 2, 3, 4, 5, 6, 7}; - // Top 64 bits of shift count don't affect the result. - V2x64 s = {2, Poisoned<U8>()}; - V8x16 u = shift_sse2_left(v, s); - EXPECT_POISONED(u[0]); - EXPECT_POISONED(u[1]); - EXPECT_NOT_POISONED(u[0] | (3U << 2)); - EXPECT_NOT_POISONED(u[1] | (7U << 2)); - u[0] = u[1] = 0; - EXPECT_NOT_POISONED(u); -} - -TEST(VectorShiftTest, sse2_left_by_uninit) { - V8x16 v = {Poisoned<U2>(0, 3), Poisoned<U2>(0, 7), 2, 3, 4, 5, 6, 7}; - V2x64 s = {Poisoned<U8>(), Poisoned<U8>()}; - V8x16 u = shift_sse2_left(v, s); - EXPECT_POISONED(u[0]); - EXPECT_POISONED(u[1]); - EXPECT_POISONED(u[2]); - EXPECT_POISONED(u[3]); - EXPECT_POISONED(u[4]); - EXPECT_POISONED(u[5]); - EXPECT_POISONED(u[6]); - EXPECT_POISONED(u[7]); -} - -#ifdef __AVX2__ -V4x32 shift_avx2_left(V4x32 x, V4x32 y) { - return _mm_sllv_epi32(x, y); -} -// This is variable vector shift that's only available starting with AVX2. -// V4x32 shift_avx2_left(V4x32 x, V4x32 y) { -TEST(VectorShiftTest, avx2_left) { - V4x32 v = {Poisoned<U2>(0, 3), Poisoned<U2>(0, 7), 2, 3}; - V4x32 s = {2, Poisoned<U4>(), 3, Poisoned<U4>()}; - V4x32 u = shift_avx2_left(v, s); - EXPECT_POISONED(u[0]); - EXPECT_NOT_POISONED(u[0] | (~7U)); - EXPECT_POISONED(u[1]); - EXPECT_POISONED(u[1] | (~31U)); - EXPECT_NOT_POISONED(u[2]); - EXPECT_POISONED(u[3]); - EXPECT_POISONED(u[3] | (~31U)); -} -#endif // __AVX2__ -} // namespace - -TEST(VectorPackTest, sse2_packssdw_128) { - const unsigned S2_max = (1 << 15) - 1; - V4x32 a = {Poisoned<U4>(0, 0xFF0000), Poisoned<U4>(0, 0xFFFF0000), - S2_max + 100, 4}; - V4x32 b = {Poisoned<U4>(0, 0xFF), S2_max + 10000, Poisoned<U4>(0, 0xFF00), - S2_max}; - - V8x16 c = _mm_packs_epi32(a, b); - - EXPECT_POISONED(c[0]); - EXPECT_POISONED(c[1]); - EXPECT_NOT_POISONED(c[2]); - EXPECT_NOT_POISONED(c[3]); - EXPECT_POISONED(c[4]); - EXPECT_NOT_POISONED(c[5]); - EXPECT_POISONED(c[6]); - EXPECT_NOT_POISONED(c[7]); - - EXPECT_EQ(c[2], S2_max); - EXPECT_EQ(c[3], 4); - EXPECT_EQ(c[5], S2_max); - EXPECT_EQ(c[7], S2_max); -} - -TEST(VectorPackTest, mmx_packuswb) { - const unsigned U1_max = (1 << 8) - 1; - V4x16 a = {Poisoned<U2>(0, 0xFF00), Poisoned<U2>(0, 0xF000U), U1_max + 100, - 4}; - V4x16 b = {Poisoned<U2>(0, 0xFF), U1_max - 1, Poisoned<U2>(0, 0xF), U1_max}; - V8x8 c = _mm_packs_pu16(a, b); - - EXPECT_POISONED(c[0]); - EXPECT_POISONED(c[1]); - EXPECT_NOT_POISONED(c[2]); - EXPECT_NOT_POISONED(c[3]); - EXPECT_POISONED(c[4]); - EXPECT_NOT_POISONED(c[5]); - EXPECT_POISONED(c[6]); - EXPECT_NOT_POISONED(c[7]); - - EXPECT_EQ(c[2], U1_max); - EXPECT_EQ(c[3], 4); - EXPECT_EQ(c[5], U1_max - 1); - EXPECT_EQ(c[7], U1_max); -} - -TEST(VectorSadTest, sse2_psad_bw) { - V16x8 a = {Poisoned<U1>(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - V16x8 b = {100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115}; - V2x64 c = _mm_sad_epu8(a, b); - - EXPECT_POISONED(c[0]); - EXPECT_NOT_POISONED(c[1]); - - EXPECT_EQ(800U, c[1]); -} - -TEST(VectorMaddTest, mmx_pmadd_wd) { - V4x16 a = {Poisoned<U2>(), 1, 2, 3}; - V4x16 b = {100, 101, 102, 103}; - V2x32 c = _mm_madd_pi16(a, b); - - EXPECT_POISONED(c[0]); - EXPECT_NOT_POISONED(c[1]); - - EXPECT_EQ((unsigned)(2 * 102 + 3 * 103), c[1]); -} - -TEST(VectorCmpTest, mm_cmpneq_ps) { - V4x32 c; - c = _mm_cmpneq_ps(V4x32{Poisoned<U4>(), 1, 2, 3}, V4x32{4, 5, Poisoned<U4>(), 6}); - EXPECT_POISONED(c[0]); - EXPECT_NOT_POISONED(c[1]); - EXPECT_POISONED(c[2]); - EXPECT_NOT_POISONED(c[3]); - - c = _mm_cmpneq_ps(V4x32{0, 1, 2, 3}, V4x32{4, 5, 6, 7}); - EXPECT_NOT_POISONED(c); -} - -TEST(VectorCmpTest, mm_cmpneq_sd) { - V2x64 c; - c = _mm_cmpneq_sd(V2x64{Poisoned<U8>(), 1}, V2x64{2, 3}); - EXPECT_POISONED(c[0]); - c = _mm_cmpneq_sd(V2x64{1, 2}, V2x64{Poisoned<U8>(), 3}); - EXPECT_POISONED(c[0]); - c = _mm_cmpneq_sd(V2x64{1, 2}, V2x64{3, 4}); - EXPECT_NOT_POISONED(c[0]); - c = _mm_cmpneq_sd(V2x64{1, Poisoned<U8>()}, V2x64{2, Poisoned<U8>()}); - EXPECT_NOT_POISONED(c[0]); - c = _mm_cmpneq_sd(V2x64{1, Poisoned<U8>()}, V2x64{1, Poisoned<U8>()}); - EXPECT_NOT_POISONED(c[0]); -} - -TEST(VectorCmpTest, builtin_ia32_ucomisdlt) { - U4 c; - c = __builtin_ia32_ucomisdlt(V2x64{Poisoned<U8>(), 1}, V2x64{2, 3}); - EXPECT_POISONED(c); - c = __builtin_ia32_ucomisdlt(V2x64{1, 2}, V2x64{Poisoned<U8>(), 3}); - EXPECT_POISONED(c); - c = __builtin_ia32_ucomisdlt(V2x64{1, 2}, V2x64{3, 4}); - EXPECT_NOT_POISONED(c); - c = __builtin_ia32_ucomisdlt(V2x64{1, Poisoned<U8>()}, V2x64{2, Poisoned<U8>()}); - EXPECT_NOT_POISONED(c); - c = __builtin_ia32_ucomisdlt(V2x64{1, Poisoned<U8>()}, V2x64{1, Poisoned<U8>()}); - EXPECT_NOT_POISONED(c); -} - -#endif // defined(__x86_64__) && defined(__clang__) - -TEST(MemorySanitizerOrigins, SetGet) { - EXPECT_EQ(TrackingOrigins(), !!__msan_get_track_origins()); - if (!TrackingOrigins()) return; - int x; - __msan_set_origin(&x, sizeof(x), 1234); - EXPECT_ORIGIN(1234U, __msan_get_origin(&x)); - __msan_set_origin(&x, sizeof(x), 5678); - EXPECT_ORIGIN(5678U, __msan_get_origin(&x)); - __msan_set_origin(&x, sizeof(x), 0); - EXPECT_ORIGIN(0U, __msan_get_origin(&x)); -} - -namespace { -struct S { - U4 dummy; - U2 a; - U2 b; -}; - -TEST(MemorySanitizerOrigins, InitializedStoreDoesNotChangeOrigin) { - if (!TrackingOrigins()) return; - - S s; - U4 origin = rand(); // NOLINT - s.a = *GetPoisonedO<U2>(0, origin); - EXPECT_ORIGIN(origin, __msan_get_origin(&s.a)); - EXPECT_ORIGIN(origin, __msan_get_origin(&s.b)); - - s.b = 42; - EXPECT_ORIGIN(origin, __msan_get_origin(&s.a)); - EXPECT_ORIGIN(origin, __msan_get_origin(&s.b)); -} -} // namespace - -template<class T, class BinaryOp> -INLINE -void BinaryOpOriginTest(BinaryOp op) { - U4 ox = rand(); //NOLINT - U4 oy = rand(); //NOLINT - T *x = GetPoisonedO<T>(0, ox, 0); - T *y = GetPoisonedO<T>(1, oy, 0); - T *z = GetPoisonedO<T>(2, 0, 0); - - *z = op(*x, *y); - U4 origin = __msan_get_origin(z); - EXPECT_POISONED_O(*z, origin); - EXPECT_EQ(true, __msan_origin_is_descendant_or_same(origin, ox) || - __msan_origin_is_descendant_or_same(origin, oy)); - - // y is poisoned, x is not. - *x = 10101; - *y = *GetPoisonedO<T>(1, oy); - break_optimization(x); - __msan_set_origin(z, sizeof(*z), 0); - *z = op(*x, *y); - EXPECT_POISONED_O(*z, oy); - EXPECT_ORIGIN(oy, __msan_get_origin(z)); - - // x is poisoned, y is not. - *x = *GetPoisonedO<T>(0, ox); - *y = 10101010; - break_optimization(y); - __msan_set_origin(z, sizeof(*z), 0); - *z = op(*x, *y); - EXPECT_POISONED_O(*z, ox); - EXPECT_ORIGIN(ox, __msan_get_origin(z)); -} - -template<class T> INLINE T XOR(const T &a, const T&b) { return a ^ b; } -template<class T> INLINE T ADD(const T &a, const T&b) { return a + b; } -template<class T> INLINE T SUB(const T &a, const T&b) { return a - b; } -template<class T> INLINE T MUL(const T &a, const T&b) { return a * b; } -template<class T> INLINE T AND(const T &a, const T&b) { return a & b; } -template<class T> INLINE T OR (const T &a, const T&b) { return a | b; } - -TEST(MemorySanitizerOrigins, BinaryOp) { - if (!TrackingOrigins()) return; - BinaryOpOriginTest<S8>(XOR<S8>); - BinaryOpOriginTest<U8>(ADD<U8>); - BinaryOpOriginTest<S4>(SUB<S4>); - BinaryOpOriginTest<S4>(MUL<S4>); - BinaryOpOriginTest<U4>(OR<U4>); - BinaryOpOriginTest<U4>(AND<U4>); - BinaryOpOriginTest<double>(ADD<U4>); - BinaryOpOriginTest<float>(ADD<S4>); - BinaryOpOriginTest<double>(ADD<double>); - BinaryOpOriginTest<float>(ADD<double>); -} - -TEST(MemorySanitizerOrigins, Unary) { - if (!TrackingOrigins()) return; - EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__), __LINE__); - - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - - EXPECT_POISONED_O(*GetPoisonedO<U4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<U4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<U4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<U4>(0, __LINE__), __LINE__); - - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - - EXPECT_POISONED_O((void*)*GetPoisonedO<S8>(0, __LINE__), __LINE__); - EXPECT_POISONED_O((U8)*GetPoisonedO<void*>(0, __LINE__), __LINE__); -} - -TEST(MemorySanitizerOrigins, EQ) { - if (!TrackingOrigins()) return; - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__) <= 11, __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__) == 11, __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<float>(0, __LINE__) == 1.1, __LINE__); -} - -TEST(MemorySanitizerOrigins, DIV) { - if (!TrackingOrigins()) return; - EXPECT_POISONED_O(*GetPoisonedO<U8>(0, __LINE__) / 100, __LINE__); - unsigned o = __LINE__; - EXPECT_UMR_O(volatile unsigned y = 100 / *GetPoisonedO<S4>(0, o, 1), o); -} - -TEST(MemorySanitizerOrigins, SHIFT) { - if (!TrackingOrigins()) return; - EXPECT_POISONED_O(*GetPoisonedO<U8>(0, __LINE__) >> 10, __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__) >> 10, __LINE__); - EXPECT_POISONED_O(*GetPoisonedO<S8>(0, __LINE__) << 10, __LINE__); - EXPECT_POISONED_O(10U << *GetPoisonedO<U8>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(-10 >> *GetPoisonedO<S8>(0, __LINE__), __LINE__); - EXPECT_POISONED_O(-10 << *GetPoisonedO<S8>(0, __LINE__), __LINE__); -} - -template<class T, int N> -void MemCpyTest() { - int ox = __LINE__; - T *x = new T[N]; - T *y = new T[N]; - T *z = new T[N]; - T *q = new T[N]; - __msan_poison(x, N * sizeof(T)); - __msan_set_origin(x, N * sizeof(T), ox); - __msan_set_origin(y, N * sizeof(T), 777777); - __msan_set_origin(z, N * sizeof(T), 888888); - EXPECT_NOT_POISONED(x); - memcpy(y, x, N * sizeof(T)); - EXPECT_POISONED_O(y[0], ox); - EXPECT_POISONED_O(y[N/2], ox); - EXPECT_POISONED_O(y[N-1], ox); - EXPECT_NOT_POISONED(x); -#if !defined(__NetBSD__) - void *res = mempcpy(q, x, N * sizeof(T)); - ASSERT_EQ(q + N, res); - EXPECT_POISONED_O(q[0], ox); - EXPECT_POISONED_O(q[N/2], ox); - EXPECT_POISONED_O(q[N-1], ox); - EXPECT_NOT_POISONED(x); -#endif - memmove(z, x, N * sizeof(T)); - EXPECT_POISONED_O(z[0], ox); - EXPECT_POISONED_O(z[N/2], ox); - EXPECT_POISONED_O(z[N-1], ox); -} - -TEST(MemorySanitizerOrigins, LargeMemCpy) { - if (!TrackingOrigins()) return; - MemCpyTest<U1, 10000>(); - MemCpyTest<U8, 10000>(); -} - -TEST(MemorySanitizerOrigins, SmallMemCpy) { - if (!TrackingOrigins()) return; - MemCpyTest<U8, 1>(); - MemCpyTest<U8, 2>(); - MemCpyTest<U8, 3>(); -} - -TEST(MemorySanitizerOrigins, Select) { - if (!TrackingOrigins()) return; - EXPECT_NOT_POISONED(g_one ? 1 : *GetPoisonedO<S4>(0, __LINE__)); - EXPECT_POISONED_O(*GetPoisonedO<S4>(0, __LINE__), __LINE__); - S4 x; - break_optimization(&x); - x = g_1 ? *GetPoisonedO<S4>(0, __LINE__) : 0; - - EXPECT_POISONED_O(g_1 ? *GetPoisonedO<S4>(0, __LINE__) : 1, __LINE__); - EXPECT_POISONED_O(g_0 ? 1 : *GetPoisonedO<S4>(0, __LINE__), __LINE__); -} - -NOINLINE int RetvalOriginTest(U4 origin) { - int *a = new int; - break_optimization(a); - __msan_set_origin(a, sizeof(*a), origin); - int res = *a; - delete a; - return res; -} - -TEST(MemorySanitizerOrigins, Retval) { - if (!TrackingOrigins()) return; - EXPECT_POISONED_O(RetvalOriginTest(__LINE__), __LINE__); -} - -NOINLINE void ParamOriginTest(int param, U4 origin) { - EXPECT_POISONED_O(param, origin); -} - -TEST(MemorySanitizerOrigins, Param) { - if (!TrackingOrigins()) return; - int *a = new int; - U4 origin = __LINE__; - break_optimization(a); - __msan_set_origin(a, sizeof(*a), origin); - ParamOriginTest(*a, origin); - delete a; -} - -TEST(MemorySanitizerOrigins, Invoke) { - if (!TrackingOrigins()) return; - StructWithDtor s; // Will cause the calls to become invokes. - EXPECT_POISONED_O(RetvalOriginTest(__LINE__), __LINE__); -} - -TEST(MemorySanitizerOrigins, strlen) { - S8 alignment; - break_optimization(&alignment); - char x[4] = {'a', 'b', 0, 0}; - __msan_poison(&x[2], 1); - U4 origin = __LINE__; - __msan_set_origin(x, sizeof(x), origin); - EXPECT_UMR_O(volatile unsigned y = strlen(x), origin); -} - -TEST(MemorySanitizerOrigins, wcslen) { - wchar_t w[3] = {'a', 'b', 0}; - U4 origin = __LINE__; - __msan_set_origin(w, sizeof(w), origin); - __msan_poison(&w[2], sizeof(wchar_t)); - EXPECT_UMR_O(volatile unsigned y = wcslen(w), origin); -} - -#if MSAN_HAS_M128 -TEST(MemorySanitizerOrigins, StoreIntrinsic) { - __m128 x, y; - U4 origin = __LINE__; - __msan_set_origin(&x, sizeof(x), origin); - __msan_poison(&x, sizeof(x)); - _mm_storeu_ps((float*)&y, x); - EXPECT_POISONED_O(y, origin); -} -#endif - -NOINLINE void RecursiveMalloc(int depth) { - static int count; - count++; - if ((count % (1024 * 1024)) == 0) - printf("RecursiveMalloc: %d\n", count); - int *x1 = new int; - int *x2 = new int; - break_optimization(x1); - break_optimization(x2); - if (depth > 0) { - RecursiveMalloc(depth-1); - RecursiveMalloc(depth-1); - } - delete x1; - delete x2; -} - -TEST(MemorySanitizer, Select) { - int x; - int volatile* p = &x; - int z = *p ? 1 : 0; - EXPECT_POISONED(z); -} - -TEST(MemorySanitizer, SelectPartial) { - // Precise instrumentation of select. - // Some bits of the result do not depend on select condition, and must stay - // initialized even if select condition is not. These are the bits that are - // equal and initialized in both left and right select arguments. - U4 x = 0xFFFFABCDU; - U4 x_s = 0xFFFF0000U; - __msan_partial_poison(&x, &x_s, sizeof(x)); - U4 y = 0xAB00U; - U1 cond = true; - __msan_poison(&cond, sizeof(cond)); - U4 z = cond ? x : y; - __msan_print_shadow(&z, sizeof(z)); - EXPECT_POISONED(z & 0xFFU); - EXPECT_NOT_POISONED(z & 0xFF00U); - EXPECT_POISONED(z & 0xFF0000U); - EXPECT_POISONED(z & 0xFF000000U); - EXPECT_EQ(0xAB00U, z & 0xFF00U); -} - -TEST(MemorySanitizerStress, DISABLED_MallocStackTrace) { - RecursiveMalloc(22); -} - -TEST(MemorySanitizerAllocator, get_estimated_allocated_size) { - size_t sizes[] = {0, 20, 5000, 1<<20}; - for (size_t i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i) { - size_t alloc_size = __sanitizer_get_estimated_allocated_size(sizes[i]); - EXPECT_EQ(alloc_size, sizes[i]); - } -} - -TEST(MemorySanitizerAllocator, get_allocated_size_and_ownership) { - char *array = reinterpret_cast<char*>(malloc(100)); - int *int_ptr = new int; - - EXPECT_TRUE(__sanitizer_get_ownership(array)); - EXPECT_EQ(100U, __sanitizer_get_allocated_size(array)); - - EXPECT_TRUE(__sanitizer_get_ownership(int_ptr)); - EXPECT_EQ(sizeof(*int_ptr), __sanitizer_get_allocated_size(int_ptr)); - - void *wild_addr = reinterpret_cast<void*>(0x1); - EXPECT_FALSE(__sanitizer_get_ownership(wild_addr)); - EXPECT_EQ(0U, __sanitizer_get_allocated_size(wild_addr)); - - EXPECT_FALSE(__sanitizer_get_ownership(array + 50)); - EXPECT_EQ(0U, __sanitizer_get_allocated_size(array + 50)); - - // NULL is a valid argument for GetAllocatedSize but is not owned. - EXPECT_FALSE(__sanitizer_get_ownership(NULL)); - EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL)); - - free(array); - EXPECT_FALSE(__sanitizer_get_ownership(array)); - EXPECT_EQ(0U, __sanitizer_get_allocated_size(array)); - - delete int_ptr; -} - -TEST(MemorySanitizer, MlockTest) { - EXPECT_EQ(0, mlockall(MCL_CURRENT)); - EXPECT_EQ(0, mlock((void*)0x12345, 0x5678)); - EXPECT_EQ(0, munlockall()); - EXPECT_EQ(0, munlock((void*)0x987, 0x654)); -} - -// Test that LargeAllocator unpoisons memory before releasing it to the OS. -TEST(MemorySanitizer, LargeAllocatorUnpoisonsOnFree) { - void *p = malloc(1024 * 1024); - free(p); - - typedef void *(*mmap_fn)(void *, size_t, int, int, int, off_t); - mmap_fn real_mmap = (mmap_fn)dlsym(RTLD_NEXT, "mmap"); - - // Allocate the page that was released to the OS in free() with the real mmap, - // bypassing the interceptor. - char *q = (char *)real_mmap(p, 4096, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ASSERT_NE((char *)0, q); - - ASSERT_TRUE(q <= p); - ASSERT_TRUE(q + 4096 > p); - - EXPECT_NOT_POISONED(q[0]); - EXPECT_NOT_POISONED(q[10]); - EXPECT_NOT_POISONED(q[100]); - - munmap(q, 4096); -} - -#if SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE -TEST(MemorySanitizer, MallocUsableSizeTest) { - const size_t kArraySize = 100; - char *array = Ident((char*)malloc(kArraySize)); - int *int_ptr = Ident(new int); - EXPECT_EQ(0U, malloc_usable_size(NULL)); - EXPECT_EQ(kArraySize, malloc_usable_size(array)); - EXPECT_EQ(sizeof(int), malloc_usable_size(int_ptr)); - free(array); - delete int_ptr; -} -#endif // SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE diff --git a/lib/msan/tests/msan_test_config.h b/lib/msan/tests/msan_test_config.h deleted file mode 100644 index 5404c434d09f3..0000000000000 --- a/lib/msan/tests/msan_test_config.h +++ /dev/null @@ -1,20 +0,0 @@ -//===-- msan_test_config.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of MemorySanitizer. -// -// MemorySanitizer unit tests. -//===----------------------------------------------------------------------===// - -#ifndef MSAN_TEST_CONFIG_H -#define MSAN_TEST_CONFIG_H - -#include "gtest/gtest.h" - -#endif // MSAN_TEST_CONFIG_H diff --git a/lib/msan/tests/msan_test_main.cc b/lib/msan/tests/msan_test_main.cc deleted file mode 100644 index c8c5fefb19f5d..0000000000000 --- a/lib/msan/tests/msan_test_main.cc +++ /dev/null @@ -1,21 +0,0 @@ -//===-- msan_test_main.cc -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of MemorySanitizer. -// -//===----------------------------------------------------------------------===// -#ifndef MSAN_EXTERNAL_TEST_CONFIG -#include "msan_test_config.h" -#endif // MSAN_EXTERNAL_TEST_CONFIG - -int main(int argc, char **argv) { - testing::GTEST_FLAG(death_test_style) = "threadsafe"; - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/lib/profile/CMakeLists.txt b/lib/profile/CMakeLists.txt deleted file mode 100644 index 488673dd2c227..0000000000000 --- a/lib/profile/CMakeLists.txt +++ /dev/null @@ -1,126 +0,0 @@ - -CHECK_CXX_SOURCE_COMPILES(" -#ifdef _MSC_VER -#include <Intrin.h> /* Workaround for PR19898. */ -#include <windows.h> -#endif -int main() { -#ifdef _MSC_VER - volatile LONG val = 1; - MemoryBarrier(); - InterlockedCompareExchange(&val, 0, 1); - InterlockedIncrement(&val); - InterlockedDecrement(&val); -#else - volatile unsigned long val = 1; - __sync_synchronize(); - __sync_val_compare_and_swap(&val, 1, 0); - __sync_add_and_fetch(&val, 1); - __sync_sub_and_fetch(&val, 1); -#endif - return 0; - } -" COMPILER_RT_TARGET_HAS_ATOMICS) - -CHECK_CXX_SOURCE_COMPILES(" -#if defined(__linux__) -#include <unistd.h> -#endif -#include <fcntl.h> -int fd; -int main() { - struct flock s_flock; - - s_flock.l_type = F_WRLCK; - fcntl(fd, F_SETLKW, &s_flock); - return 0; -} - -" COMPILER_RT_TARGET_HAS_FCNTL_LCK) - -CHECK_CXX_SOURCE_COMPILES(" -#include <sys/utsname.h> -int main() { - return 0; -} - -" COMPILER_RT_TARGET_HAS_UNAME) - -add_compiler_rt_component(profile) - -set(PROFILE_SOURCES - GCDAProfiling.c - InstrProfiling.c - InstrProfilingValue.c - InstrProfilingBuffer.c - InstrProfilingFile.c - InstrProfilingMerge.c - InstrProfilingMergeFile.c - InstrProfilingNameVar.c - InstrProfilingWriter.c - InstrProfilingPlatformDarwin.c - InstrProfilingPlatformFuchsia.c - InstrProfilingPlatformLinux.c - InstrProfilingPlatformOther.c - InstrProfilingRuntime.cc - InstrProfilingUtil.c) - -set(PROFILE_HEADERS - InstrProfData.inc - InstrProfiling.h - InstrProfilingInternal.h - InstrProfilingPort.h - InstrProfilingUtil.h - WindowsMMap.h) - -if(WIN32) - list(APPEND PROFILE_SOURCES WindowsMMap.c) -endif() - -if(FUCHSIA OR UNIX) - set(EXTRA_FLAGS - -fPIC - -Wno-pedantic) -endif() - -if(COMPILER_RT_TARGET_HAS_ATOMICS) - set(EXTRA_FLAGS - ${EXTRA_FLAGS} - -DCOMPILER_RT_HAS_ATOMICS=1) -endif() - -if(COMPILER_RT_TARGET_HAS_FCNTL_LCK) - set(EXTRA_FLAGS - ${EXTRA_FLAGS} - -DCOMPILER_RT_HAS_FCNTL_LCK=1) -endif() - -if(COMPILER_RT_TARGET_HAS_UNAME) - set(EXTRA_FLAGS - ${EXTRA_FLAGS} - -DCOMPILER_RT_HAS_UNAME=1) -endif() - -# This appears to be a C-only warning banning the use of locals in aggregate -# initializers. All other compilers accept this, though. -# nonstandard extension used : 'identifier' : cannot be initialized using address of automatic variable -append_list_if(COMPILER_RT_HAS_WD4221_FLAG /wd4221 EXTRA_FLAGS) - -if(APPLE) - add_compiler_rt_runtime(clang_rt.profile - STATIC - OS ${PROFILE_SUPPORTED_OS} - ARCHS ${PROFILE_SUPPORTED_ARCH} - CFLAGS ${EXTRA_FLAGS} - SOURCES ${PROFILE_SOURCES} - ADDITIONAL_HEADERS ${PROFILE_HEADERS} - PARENT_TARGET profile) -else() - add_compiler_rt_runtime(clang_rt.profile - STATIC - ARCHS ${PROFILE_SUPPORTED_ARCH} - CFLAGS ${EXTRA_FLAGS} - SOURCES ${PROFILE_SOURCES} - ADDITIONAL_HEADERS ${PROFILE_HEADERS} - PARENT_TARGET profile) -endif() diff --git a/lib/safestack/.clang-format b/lib/safestack/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/safestack/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/safestack/CMakeLists.txt b/lib/safestack/CMakeLists.txt deleted file mode 100644 index cc874a3fe8f18..0000000000000 --- a/lib/safestack/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -add_compiler_rt_component(safestack) - -set(SAFESTACK_SOURCES safestack.cc) - -include_directories(..) - -set(SAFESTACK_CFLAGS ${SANITIZER_COMMON_CFLAGS}) - -foreach(arch ${SAFESTACK_SUPPORTED_ARCH}) - add_compiler_rt_runtime(clang_rt.safestack - STATIC - ARCHS ${arch} - SOURCES ${SAFESTACK_SOURCES} - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonNoLibc.${arch}> - CFLAGS ${SAFESTACK_CFLAGS} - PARENT_TARGET safestack) -endforeach() diff --git a/lib/sanitizer_common/.clang-format b/lib/sanitizer_common/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/sanitizer_common/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/sanitizer_common/.clang-tidy b/lib/sanitizer_common/.clang-tidy deleted file mode 100644 index 6c71abff0d382..0000000000000 --- a/lib/sanitizer_common/.clang-tidy +++ /dev/null @@ -1,16 +0,0 @@ -Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,readability-identifier-naming' -CheckOptions: - - key: readability-identifier-naming.ClassCase - value: CamelCase - - key: readability-identifier-naming.EnumCase - value: CamelCase - - key: readability-identifier-naming.FunctionCase - value: CamelCase - - key: readability-identifier-naming.UnionCase - value: CamelCase - - key: readability-identifier-naming.GlobalConstantCase - value: CamelCase - - key: readability-identifier-naming.GlobalConstantPrefix - value: "k" - - key: readability-identifier-naming.VariableCase - value: lower_case diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt deleted file mode 100644 index f7bf4b009720e..0000000000000 --- a/lib/sanitizer_common/CMakeLists.txt +++ /dev/null @@ -1,374 +0,0 @@ -# Build system for the common Sanitizer runtime support library components. -# These components are shared between AddressSanitizer and ThreadSanitizer. - -set(SANITIZER_SOURCES_NOTERMINATION - sanitizer_allocator.cc - sanitizer_common.cc - sanitizer_deadlock_detector1.cc - sanitizer_deadlock_detector2.cc - sanitizer_errno.cc - sanitizer_file.cc - sanitizer_flags.cc - sanitizer_flag_parser.cc - sanitizer_fuchsia.cc - sanitizer_libc.cc - sanitizer_libignore.cc - sanitizer_linux.cc - sanitizer_linux_s390.cc - sanitizer_mac.cc - sanitizer_netbsd.cc - sanitizer_openbsd.cc - sanitizer_persistent_allocator.cc - sanitizer_platform_limits_freebsd.cc - sanitizer_platform_limits_linux.cc - sanitizer_platform_limits_netbsd.cc - sanitizer_platform_limits_openbsd.cc - sanitizer_platform_limits_posix.cc - sanitizer_platform_limits_solaris.cc - sanitizer_posix.cc - sanitizer_printf.cc - sanitizer_procmaps_common.cc - sanitizer_procmaps_bsd.cc - sanitizer_procmaps_linux.cc - sanitizer_procmaps_mac.cc - sanitizer_procmaps_solaris.cc - sanitizer_rtems.cc - sanitizer_solaris.cc - sanitizer_stoptheworld_mac.cc - sanitizer_suppressions.cc - sanitizer_tls_get_addr.cc - sanitizer_thread_registry.cc - sanitizer_type_traits.cc - sanitizer_win.cc) - -if(UNIX AND NOT APPLE AND NOT OS_NAME MATCHES "SunOS") - list(APPEND SANITIZER_SOURCES_NOTERMINATION - sanitizer_linux_x86_64.S) - list(APPEND SANITIZER_SOURCES_NOTERMINATION - sanitizer_linux_mips64.S) -endif() - -set(SANITIZER_SOURCES - ${SANITIZER_SOURCES_NOTERMINATION} sanitizer_termination.cc) - -# Libc functions stubs. These sources should be linked instead of -# SANITIZER_LIBCDEP_SOURCES when sanitizer_common library must not depend on -# libc. -set(SANITIZER_NOLIBC_SOURCES - sanitizer_common_nolibc.cc) - -set(SANITIZER_LIBCDEP_SOURCES - sanitizer_common_libcdep.cc - sanitizer_allocator_checks.cc - sanitizer_linux_libcdep.cc - sanitizer_mac_libcdep.cc - sanitizer_posix_libcdep.cc - sanitizer_stoptheworld_linux_libcdep.cc) - -set(SANITIZER_COVERAGE_SOURCES - sancov_flags.cc - sanitizer_coverage_fuchsia.cc - sanitizer_coverage_libcdep_new.cc - sanitizer_coverage_win_sections.cc) - -set(SANITIZER_SYMBOLIZER_SOURCES - sanitizer_allocator_report.cc - sanitizer_stackdepot.cc - sanitizer_stacktrace.cc - sanitizer_stacktrace_libcdep.cc - sanitizer_stacktrace_printer.cc - sanitizer_stacktrace_sparc.cc - sanitizer_symbolizer.cc - sanitizer_symbolizer_libbacktrace.cc - sanitizer_symbolizer_libcdep.cc - sanitizer_symbolizer_mac.cc - sanitizer_symbolizer_markup.cc - sanitizer_symbolizer_posix_libcdep.cc - sanitizer_symbolizer_report.cc - sanitizer_symbolizer_win.cc - sanitizer_unwind_linux_libcdep.cc - sanitizer_unwind_win.cc) - -# Explicitly list all sanitizer_common headers. Not all of these are -# included in sanitizer_common source files, but we need to depend on -# headers when building our custom unit tests. -set(SANITIZER_IMPL_HEADERS - sancov_flags.h - sancov_flags.inc - sanitizer_addrhashmap.h - sanitizer_allocator.h - sanitizer_allocator_bytemap.h - sanitizer_allocator_checks.h - sanitizer_allocator_combined.h - sanitizer_allocator_interface.h - sanitizer_allocator_internal.h - sanitizer_allocator_local_cache.h - sanitizer_allocator_primary32.h - sanitizer_allocator_primary64.h - sanitizer_allocator_report.h - sanitizer_allocator_secondary.h - sanitizer_allocator_size_class_map.h - sanitizer_allocator_stats.h - sanitizer_asm.h - sanitizer_atomic.h - sanitizer_atomic_clang.h - sanitizer_atomic_clang_mips.h - sanitizer_atomic_clang_other.h - sanitizer_atomic_clang_x86.h - sanitizer_atomic_msvc.h - sanitizer_bitvector.h - sanitizer_bvgraph.h - sanitizer_common.h - sanitizer_common_interceptors.inc - sanitizer_common_interceptors_format.inc - sanitizer_common_interceptors_ioctl.inc - sanitizer_common_interface.inc - sanitizer_common_interface_posix.inc - sanitizer_common_syscalls.inc - sanitizer_coverage_interface.inc - sanitizer_dbghelp.h - sanitizer_deadlock_detector.h - sanitizer_deadlock_detector_interface.h - sanitizer_errno.h - sanitizer_errno_codes.h - sanitizer_file.h - sanitizer_flag_parser.h - sanitizer_flags.h - sanitizer_flags.inc - sanitizer_freebsd.h - sanitizer_fuchsia.h - sanitizer_getauxval.h - sanitizer_interceptors_ioctl_netbsd.inc - sanitizer_interface_internal.h - sanitizer_internal_defs.h - sanitizer_lfstack.h - sanitizer_libc.h - sanitizer_libignore.h - sanitizer_linux.h - sanitizer_list.h - sanitizer_local_address_space_view.h - sanitizer_mac.h - sanitizer_malloc_mac.inc - sanitizer_mutex.h - sanitizer_persistent_allocator.h - sanitizer_placement_new.h - sanitizer_platform.h - sanitizer_platform_interceptors.h - sanitizer_platform_limits_netbsd.h - sanitizer_platform_limits_openbsd.h - sanitizer_platform_limits_posix.h - sanitizer_platform_limits_solaris.h - sanitizer_posix.h - sanitizer_procmaps.h - sanitizer_quarantine.h - sanitizer_report_decorator.h - sanitizer_ring_buffer.h - sanitizer_rtems.h - sanitizer_signal_interceptors.inc - sanitizer_stackdepot.h - sanitizer_stackdepotbase.h - sanitizer_stacktrace.h - sanitizer_stacktrace_printer.h - sanitizer_stoptheworld.h - sanitizer_suppressions.h - sanitizer_symbolizer.h - sanitizer_symbolizer_fuchsia.h - sanitizer_symbolizer_internal.h - sanitizer_symbolizer_libbacktrace.h - sanitizer_symbolizer_mac.h - sanitizer_symbolizer_rtems.h - sanitizer_syscall_generic.inc - sanitizer_syscall_linux_aarch64.inc - sanitizer_syscall_linux_arm.inc - sanitizer_syscall_linux_x86_64.inc - sanitizer_syscalls_netbsd.inc - sanitizer_thread_registry.h - sanitizer_tls_get_addr.h - sanitizer_vector.h - sanitizer_win.h - sanitizer_win_defs.h - sanitizer_win_dll_thunk.h - sanitizer_win_weak_interception.h) - -include_directories(..) - -set(SANITIZER_COMMON_DEFINITIONS - HAVE_RPC_XDR_H=${HAVE_RPC_XDR_H}) - -set(SANITIZER_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF SANITIZER_CFLAGS) - -append_list_if(SANITIZER_LIMIT_FRAME_SIZE -Wframe-larger-than=570 - SANITIZER_CFLAGS) -append_list_if(COMPILER_RT_HAS_WGLOBAL_CONSTRUCTORS_FLAG -Wglobal-constructors - SANITIZER_CFLAGS) - -if (LLVM_ENABLE_PEDANTIC AND UNIX AND NOT APPLE) - # With -pedantic, our .S files raise warnings about empty macro arguments - # from __USER_LABEL_PREFIX__ being an empty arg to GLUE(). Unfortunately, - # there is no simple way to test for an empty define, nor to disable just - # that warning or to disable -pedantic. There is also no simple way to - # remove -pedantic from just this file (we'd have to remove from - # CMAKE_C*_FLAGS and re-add as a source property to all the non-.S files). - set_source_files_properties(sanitizer_linux_x86_64.S - PROPERTIES COMPILE_FLAGS "-w") - set_source_files_properties(sanitizer_linux_mips64.S - PROPERTIES COMPILE_FLAGS "-w") -endif () - -if(APPLE) - set(OS_OPTION OS ${SANITIZER_COMMON_SUPPORTED_OS}) -endif() - -add_compiler_rt_object_libraries(RTSanitizerCommon - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_SOURCES} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -add_compiler_rt_object_libraries(RTSanitizerCommonNoTermination - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_SOURCES_NOTERMINATION} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -add_compiler_rt_object_libraries(RTSanitizerCommonNoLibc - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_NOLIBC_SOURCES} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -add_compiler_rt_object_libraries(RTSanitizerCommonLibc - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_LIBCDEP_SOURCES} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -add_compiler_rt_object_libraries(RTSanitizerCommonCoverage - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_COVERAGE_SOURCES} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -add_compiler_rt_object_libraries(RTSanitizerCommonSymbolizer - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_SYMBOLIZER_SOURCES} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - -set(SANITIZER_NO_WEAK_HOOKS_CFLAGS ${SANITIZER_CFLAGS}) -list(APPEND SANITIZER_NO_WEAK_HOOKS_CFLAGS "-DSANITIZER_SUPPORTS_WEAK_HOOKS=0") -add_compiler_rt_object_libraries(RTSanitizerCommonNoHooks - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_SOURCES} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_NO_WEAK_HOOKS_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -add_compiler_rt_object_libraries(RTSanitizerCommonLibcNoHooks - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_LIBCDEP_SOURCES} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_NO_WEAK_HOOKS_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -add_compiler_rt_object_libraries(RTSanitizerCommonSymbolizerNoHooks - ${OS_OPTION} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES ${SANITIZER_SYMBOLIZER_SOURCES} - ADDITIONAL_HEADERS ${SANITIZER_IMPL_HEADERS} - CFLAGS ${SANITIZER_NO_WEAK_HOOKS_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - -if(OS_NAME MATCHES "SunOS") - # Solaris ld doesn't support the non-standard GNU ld extension of adding - # __start_SECNAME and __stop_SECNAME labels to sections whose names are - # valid C identifiers. Instead we add our own definitions for the - # __sancov_guards section. - add_compiler_rt_object_libraries(SancovBegin - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES sancov_begin.S - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - - add_compiler_rt_runtime(clang_rt.sancov_begin - STATIC - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - OBJECT_LIBS SancovBegin - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - - add_compiler_rt_object_libraries(SancovEnd - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES sancov_end.S - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - - add_compiler_rt_runtime(clang_rt.sancov_end - STATIC - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - OBJECT_LIBS SancovEnd - CFLAGS ${SANITIZER_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -endif() - -if(WIN32) - add_compiler_rt_object_libraries(SanitizerCommonWeakInterception - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES sanitizer_win_weak_interception.cc - CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DYNAMIC - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - add_compiler_rt_object_libraries(SancovWeakInterception - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES sanitizer_coverage_win_weak_interception.cc - CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DYNAMIC - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - - add_compiler_rt_object_libraries(SanitizerCommonDllThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES sanitizer_win_dll_thunk.cc - CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DLL_THUNK - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - add_compiler_rt_object_libraries(SancovDllThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES sanitizer_coverage_win_dll_thunk.cc - sanitizer_coverage_win_sections.cc - CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DLL_THUNK - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - - set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK") - if(MSVC) - list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl") - elseif(CMAKE_C_COMPILER_ID MATCHES Clang) - list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs") - endif() - add_compiler_rt_object_libraries(SanitizerCommonDynamicRuntimeThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES sanitizer_win_dynamic_runtime_thunk.cc - CFLAGS ${SANITIZER_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) - add_compiler_rt_object_libraries(SancovDynamicRuntimeThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - SOURCES sanitizer_coverage_win_dynamic_runtime_thunk.cc - sanitizer_coverage_win_sections.cc - CFLAGS ${SANITIZER_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} - DEFS ${SANITIZER_COMMON_DEFINITIONS}) -endif() - -# Unit tests for common sanitizer runtime. -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/lib/sanitizer_common/scripts/check_lint.sh b/lib/sanitizer_common/scripts/check_lint.sh deleted file mode 100755 index ec07138cac1c5..0000000000000 --- a/lib/sanitizer_common/scripts/check_lint.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/sh - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" - -# Guess path to LLVM_CHECKOUT if not provided -if [ "${LLVM_CHECKOUT}" = "" ]; then - LLVM_CHECKOUT="${SCRIPT_DIR}/../../../../../" -fi - -# python tools setup -CPPLINT=${SCRIPT_DIR}/cpplint.py -LITLINT=${SCRIPT_DIR}/litlint.py -if [ "${PYTHON_EXECUTABLE}" != "" ]; then - CPPLINT="${PYTHON_EXECUTABLE} ${CPPLINT}" - LITLINT="${PYTHON_EXECUTABLE} ${LITLINT}" -fi - -# Filters -# TODO: remove some of these filters -COMMON_LINT_FILTER=-build/include,-build/header_guard,-legal/copyright,-whitespace/comments,-readability/casting,\ --build/namespaces,-readability/braces -ASAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int -ASAN_TEST_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/sizeof,-runtime/int,-runtime/printf,-runtime/threadsafe_fn -ASAN_LIT_TEST_LINT_FILTER=${ASAN_TEST_LINT_FILTER},-whitespace/line_length -TSAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER} -TSAN_TEST_LINT_FILTER=${TSAN_RTL_LINT_FILTER},-runtime/threadsafe_fn,-runtime/int -TSAN_LIT_TEST_LINT_FILTER=${TSAN_TEST_LINT_FILTER},-whitespace/line_length -MSAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER} -LSAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER} -LSAN_LIT_TEST_LINT_FILTER=${LSAN_RTL_LINT_FILTER},-whitespace/line_length -DFSAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int,-runtime/printf,-runtime/references,-readability/function -SCUDO_RTL_LINT_FILTER=${COMMON_LINT_FILTER} -COMMON_RTL_INC_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int,-runtime/sizeof,-runtime/printf,-readability/fn_size -SANITIZER_INCLUDES_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int - -MKTEMP_DIR=$(mktemp -qd /tmp/check_lint.XXXXXXXXXX) -MKTEMP="mktemp -q ${MKTEMP_DIR}/tmp.XXXXXXXXXX" -cleanup() { - rm -rf $MKTEMP_DIR -} -trap cleanup EXIT - -cd ${LLVM_CHECKOUT} - -EXITSTATUS=0 -ERROR_LOG=$(${MKTEMP}) - -run_lint() { - FILTER=$1 - shift - TASK_LOG=$(${MKTEMP}) - ${CPPLINT} --filter=${FILTER} "$@" 2>$TASK_LOG - if [ "$?" != "0" ]; then - cat $TASK_LOG | grep -v "Done processing" | grep -v "Total errors found" \ - | grep -v "Skipping input" >> $ERROR_LOG - fi - if [ "${SILENT}" != "1" ]; then - cat $TASK_LOG - fi - ${LITLINT} "$@" 2>>$ERROR_LOG -} - -if [ "${COMPILER_RT}" = "" ]; then - COMPILER_RT=projects/compiler-rt -fi -LIT_TESTS=${COMPILER_RT}/test -# Headers -SANITIZER_INCLUDES=${COMPILER_RT}/include/sanitizer -run_lint ${SANITIZER_INCLUDES_LINT_FILTER} ${SANITIZER_INCLUDES}/*.h & - -# Sanitizer_common -COMMON_RTL=${COMPILER_RT}/lib/sanitizer_common -run_lint ${COMMON_RTL_INC_LINT_FILTER} ${COMMON_RTL}/*.cc \ - ${COMMON_RTL}/*.h \ - ${COMMON_RTL}/tests/*.cc & - -# Interception -INTERCEPTION=${COMPILER_RT}/lib/interception -run_lint ${ASAN_RTL_LINT_FILTER} ${INTERCEPTION}/*.cc \ - ${INTERCEPTION}/*.h & - -# ASan -ASAN_RTL=${COMPILER_RT}/lib/asan -run_lint ${ASAN_RTL_LINT_FILTER} ${ASAN_RTL}/*.cc \ - ${ASAN_RTL}/*.h & -run_lint ${ASAN_TEST_LINT_FILTER} ${ASAN_RTL}/tests/*.cc \ - ${ASAN_RTL}/tests/*.h & -run_lint ${ASAN_LIT_TEST_LINT_FILTER} ${LIT_TESTS}/asan/*/*.cc & - -# TSan -TSAN_RTL=${COMPILER_RT}/lib/tsan -run_lint ${TSAN_RTL_LINT_FILTER} ${TSAN_RTL}/rtl/*.cc \ - ${TSAN_RTL}/rtl/*.h & -run_lint ${TSAN_TEST_LINT_FILTER} ${TSAN_RTL}/tests/rtl/*.cc \ - ${TSAN_RTL}/tests/rtl/*.h \ - ${TSAN_RTL}/tests/unit/*.cc & -run_lint ${TSAN_LIT_TEST_LINT_FILTER} ${LIT_TESTS}/tsan/*.cc & - -# MSan -MSAN_RTL=${COMPILER_RT}/lib/msan -run_lint ${MSAN_RTL_LINT_FILTER} ${MSAN_RTL}/*.cc \ - ${MSAN_RTL}/*.h & - -# LSan -LSAN_RTL=${COMPILER_RT}/lib/lsan -run_lint ${LSAN_RTL_LINT_FILTER} ${LSAN_RTL}/*.cc \ - ${LSAN_RTL}/*.h & -run_lint ${LSAN_LIT_TEST_LINT_FILTER} ${LIT_TESTS}/lsan/*/*.cc & - -# DFSan -DFSAN_RTL=${COMPILER_RT}/lib/dfsan -run_lint ${DFSAN_RTL_LINT_FILTER} ${DFSAN_RTL}/*.cc \ - ${DFSAN_RTL}/*.h & -${DFSAN_RTL}/scripts/check_custom_wrappers.sh >> $ERROR_LOG - -# Scudo -SCUDO_RTL=${COMPILER_RT}/lib/scudo -run_lint ${SCUDO_RTL_LINT_FILTER} ${SCUDO_RTL}/*.cpp \ - ${SCUDO_RTL}/*.h & - -# Misc files -FILES=${COMMON_RTL}/*.inc -TMPFILES="" -for FILE in $FILES; do - TMPFILE="$(${MKTEMP}).$(basename ${FILE}).cc" - cp -f $FILE $TMPFILE - run_lint ${COMMON_RTL_INC_LINT_FILTER} $TMPFILE & - TMPFILES="$TMPFILES $TMPFILE" -done - -wait - -for temp in $TMPFILES; do - rm -f $temp -done - -if [ -s $ERROR_LOG ]; then - cat $ERROR_LOG - exit 1 -fi - -exit 0 diff --git a/lib/sanitizer_common/scripts/cpplint.py b/lib/sanitizer_common/scripts/cpplint.py deleted file mode 100755 index d45c47f7ed0cd..0000000000000 --- a/lib/sanitizer_common/scripts/cpplint.py +++ /dev/null @@ -1,4024 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2009 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Here are some issues that I've had people identify in my code during reviews, -# that I think are possible to flag automatically in a lint tool. If these were -# caught by lint, it would save time both for myself and that of my reviewers. -# Most likely, some of these are beyond the scope of the current lint framework, -# but I think it is valuable to retain these wish-list items even if they cannot -# be immediately implemented. -# -# Suggestions -# ----------- -# - Check for no 'explicit' for multi-arg ctor -# - Check for boolean assign RHS in parens -# - Check for ctor initializer-list colon position and spacing -# - Check that if there's a ctor, there should be a dtor -# - Check accessors that return non-pointer member variables are -# declared const -# - Check accessors that return non-const pointer member vars are -# *not* declared const -# - Check for using public includes for testing -# - Check for spaces between brackets in one-line inline method -# - Check for no assert() -# - Check for spaces surrounding operators -# - Check for 0 in pointer context (should be NULL) -# - Check for 0 in char context (should be '\0') -# - Check for camel-case method name conventions for methods -# that are not simple inline getters and setters -# - Do not indent namespace contents -# - Avoid inlining non-trivial constructors in header files -# - Check for old-school (void) cast for call-sites of functions -# ignored return value -# - Check gUnit usage of anonymous namespace -# - Check for class declaration order (typedefs, consts, enums, -# ctor(s?), dtor, friend declarations, methods, member vars) -# - -"""Does google-lint on c++ files. - -The goal of this script is to identify places in the code that *may* -be in non-compliance with google style. It does not attempt to fix -up these problems -- the point is to educate. It does also not -attempt to find all problems, or to ensure that everything it does -find is legitimately a problem. - -In particular, we can get very confused by /* and // inside strings! -We do a small hack, which is to ignore //'s with "'s after them on the -same line, but it is far from perfect (in either direction). -""" - -import codecs -import copy -import getopt -import math # for log -import os -import re -import sre_compile -import string -import sys -import unicodedata - - -_USAGE = """ -Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] - [--counting=total|toplevel|detailed] - <file> [file] ... - - The style guidelines this tries to follow are those in - http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml - - Every problem is given a confidence score from 1-5, with 5 meaning we are - certain of the problem, and 1 meaning it could be a legitimate construct. - This will miss some errors, and is not a substitute for a code review. - - To suppress false-positive errors of a certain category, add a - 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) - suppresses errors of all categories on that line. - - The files passed in will be linted; at least one file must be provided. - Linted extensions are .cc, .cpp, and .h. Other file types will be ignored. - - Flags: - - output=vs7 - By default, the output is formatted to ease emacs parsing. Visual Studio - compatible output (vs7) may also be used. Other formats are unsupported. - - verbose=# - Specify a number 0-5 to restrict errors to certain verbosity levels. - - filter=-x,+y,... - Specify a comma-separated list of category-filters to apply: only - error messages whose category names pass the filters will be printed. - (Category names are printed with the message and look like - "[whitespace/indent]".) Filters are evaluated left to right. - "-FOO" and "FOO" means "do not print categories that start with FOO". - "+FOO" means "do print categories that start with FOO". - - Examples: --filter=-whitespace,+whitespace/braces - --filter=whitespace,runtime/printf,+runtime/printf_format - --filter=-,+build/include_what_you_use - - To see a list of all the categories used in cpplint, pass no arg: - --filter= - - counting=total|toplevel|detailed - The total number of errors found is always printed. If - 'toplevel' is provided, then the count of errors in each of - the top-level categories like 'build' and 'whitespace' will - also be printed. If 'detailed' is provided, then a count - is provided for each category like 'build/class'. - - root=subdir - The root directory used for deriving header guard CPP variable. - By default, the header guard CPP variable is calculated as the relative - path to the directory that contains .git, .hg, or .svn. When this flag - is specified, the relative path is calculated from the specified - directory. If the specified directory does not exist, this flag is - ignored. - - Examples: - Assuing that src/.git exists, the header guard CPP variables for - src/chrome/browser/ui/browser.h are: - - No flag => CHROME_BROWSER_UI_BROWSER_H_ - --root=chrome => BROWSER_UI_BROWSER_H_ - --root=chrome/browser => UI_BROWSER_H_ -""" - -# We categorize each error message we print. Here are the categories. -# We want an explicit list so we can list them all in cpplint --filter=. -# If you add a new error message with a new category, add it to the list -# here! cpplint_unittest.py should tell you if you forget to do this. -# \ used for clearer layout -- pylint: disable-msg=C6013 -_ERROR_CATEGORIES = [ - 'build/class', - 'build/deprecated', - 'build/endif_comment', - 'build/explicit_make_pair', - 'build/forward_decl', - 'build/header_guard', - 'build/include', - 'build/include_alpha', - 'build/include_order', - 'build/include_what_you_use', - 'build/namespaces', - 'build/printf_format', - 'build/storage_class', - 'legal/copyright', - 'readability/alt_tokens', - 'readability/braces', - 'readability/casting', - 'readability/check', - 'readability/constructors', - 'readability/fn_size', - 'readability/function', - 'readability/multiline_comment', - 'readability/multiline_string', - 'readability/namespace', - 'readability/nolint', - 'readability/streams', - 'readability/todo', - 'readability/utf8', - 'runtime/arrays', - 'runtime/casting', - 'runtime/explicit', - 'runtime/int', - 'runtime/init', - 'runtime/invalid_increment', - 'runtime/member_string_references', - 'runtime/memset', - 'runtime/operator', - 'runtime/printf', - 'runtime/printf_format', - 'runtime/references', - 'runtime/rtti', - 'runtime/sizeof', - 'runtime/string', - 'runtime/threadsafe_fn', - 'whitespace/blank_line', - 'whitespace/braces', - 'whitespace/comma', - 'whitespace/comments', - 'whitespace/empty_loop_body', - 'whitespace/end_of_line', - 'whitespace/ending_newline', - 'whitespace/forcolon', - 'whitespace/indent', - 'whitespace/labels', - 'whitespace/line_length', - 'whitespace/newline', - 'whitespace/operators', - 'whitespace/parens', - 'whitespace/semicolon', - 'whitespace/tab', - 'whitespace/todo' - ] - -# The default state of the category filter. This is overrided by the --filter= -# flag. By default all errors are on, so only add here categories that should be -# off by default (i.e., categories that must be enabled by the --filter= flags). -# All entries here should start with a '-' or '+', as in the --filter= flag. -_DEFAULT_FILTERS = ['-build/include_alpha'] - -# We used to check for high-bit characters, but after much discussion we -# decided those were OK, as long as they were in UTF-8 and didn't represent -# hard-coded international strings, which belong in a separate i18n file. - -# Headers that we consider STL headers. -_STL_HEADERS = frozenset([ - 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', - 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', - 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new', - 'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', - 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', - 'utility', 'vector', 'vector.h', - ]) - - -# Non-STL C++ system headers. -_CPP_HEADERS = frozenset([ - 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', - 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', - 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', - 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', - 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', - 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', - 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream', - 'istream.h', 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', - 'numeric', 'ostream', 'ostream.h', 'parsestream.h', 'pfstream.h', - 'PlotFile.h', 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', - 'ropeimpl.h', 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', - 'stdiostream.h', 'streambuf', 'streambuf.h', 'stream.h', 'strfile.h', - 'string', 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', - 'valarray', - ]) - - -# Assertion macros. These are defined in base/logging.h and -# testing/base/gunit.h. Note that the _M versions need to come first -# for substring matching to work. -_CHECK_MACROS = [ - 'DCHECK', 'CHECK', - 'EXPECT_TRUE_M', 'EXPECT_TRUE', - 'ASSERT_TRUE_M', 'ASSERT_TRUE', - 'EXPECT_FALSE_M', 'EXPECT_FALSE', - 'ASSERT_FALSE_M', 'ASSERT_FALSE', - ] - -# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE -_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) - -for op, replacement in [('==', 'EQ'), ('!=', 'NE'), - ('>=', 'GE'), ('>', 'GT'), - ('<=', 'LE'), ('<', 'LT')]: - _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement - _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement - _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement - _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement - _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement - _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement - -for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), - ('>=', 'LT'), ('>', 'LE'), - ('<=', 'GT'), ('<', 'GE')]: - _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement - _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement - _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement - _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement - -# Alternative tokens and their replacements. For full list, see section 2.5 -# Alternative tokens [lex.digraph] in the C++ standard. -# -# Digraphs (such as '%:') are not included here since it's a mess to -# match those on a word boundary. -_ALT_TOKEN_REPLACEMENT = { - 'and': '&&', - 'bitor': '|', - 'or': '||', - 'xor': '^', - 'compl': '~', - 'bitand': '&', - 'and_eq': '&=', - 'or_eq': '|=', - 'xor_eq': '^=', - 'not': '!', - 'not_eq': '!=' - } - -# Compile regular expression that matches all the above keywords. The "[ =()]" -# bit is meant to avoid matching these keywords outside of boolean expressions. -# -# False positives include C-style multi-line comments (http://go/nsiut ) -# and multi-line strings (http://go/beujw ), but those have always been -# troublesome for cpplint. -_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile( - r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)') - - -# These constants define types of headers for use with -# _IncludeState.CheckNextIncludeOrder(). -_C_SYS_HEADER = 1 -_CPP_SYS_HEADER = 2 -_LIKELY_MY_HEADER = 3 -_POSSIBLE_MY_HEADER = 4 -_OTHER_HEADER = 5 - -# These constants define the current inline assembly state -_NO_ASM = 0 # Outside of inline assembly block -_INSIDE_ASM = 1 # Inside inline assembly block -_END_ASM = 2 # Last line of inline assembly block -_BLOCK_ASM = 3 # The whole block is an inline assembly block - -# Match start of assembly blocks -_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)' - r'(?:\s+(volatile|__volatile__))?' - r'\s*[{(]') - - -_regexp_compile_cache = {} - -# Finds occurrences of NOLINT or NOLINT(...). -_RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?') - -# {str, set(int)}: a map from error categories to sets of linenumbers -# on which those errors are expected and should be suppressed. -_error_suppressions = {} - -# The root directory used for deriving header guard CPP variable. -# This is set by --root flag. -_root = None - -def ParseNolintSuppressions(filename, raw_line, linenum, error): - """Updates the global list of error-suppressions. - - Parses any NOLINT comments on the current line, updating the global - error_suppressions store. Reports an error if the NOLINT comment - was malformed. - - Args: - filename: str, the name of the input file. - raw_line: str, the line of input text, with comments. - linenum: int, the number of the current line. - error: function, an error handler. - """ - # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*). - matched = _RE_SUPPRESSION.search(raw_line) - if matched: - category = matched.group(1) - if category in (None, '(*)'): # => "suppress all" - _error_suppressions.setdefault(None, set()).add(linenum) - else: - if category.startswith('(') and category.endswith(')'): - category = category[1:-1] - if category in _ERROR_CATEGORIES: - _error_suppressions.setdefault(category, set()).add(linenum) - else: - error(filename, linenum, 'readability/nolint', 5, - 'Unknown NOLINT error category: %s' % category) - - -def ResetNolintSuppressions(): - "Resets the set of NOLINT suppressions to empty." - _error_suppressions.clear() - - -def IsErrorSuppressedByNolint(category, linenum): - """Returns true if the specified error category is suppressed on this line. - - Consults the global error_suppressions map populated by - ParseNolintSuppressions/ResetNolintSuppressions. - - Args: - category: str, the category of the error. - linenum: int, the current line number. - Returns: - bool, True iff the error should be suppressed due to a NOLINT comment. - """ - return (linenum in _error_suppressions.get(category, set()) or - linenum in _error_suppressions.get(None, set())) - -def Match(pattern, s): - """Matches the string with the pattern, caching the compiled regexp.""" - # The regexp compilation caching is inlined in both Match and Search for - # performance reasons; factoring it out into a separate function turns out - # to be noticeably expensive. - if not pattern in _regexp_compile_cache: - _regexp_compile_cache[pattern] = sre_compile.compile(pattern) - return _regexp_compile_cache[pattern].match(s) - - -def Search(pattern, s): - """Searches the string for the pattern, caching the compiled regexp.""" - if not pattern in _regexp_compile_cache: - _regexp_compile_cache[pattern] = sre_compile.compile(pattern) - return _regexp_compile_cache[pattern].search(s) - - -class _IncludeState(dict): - """Tracks line numbers for includes, and the order in which includes appear. - - As a dict, an _IncludeState object serves as a mapping between include - filename and line number on which that file was included. - - Call CheckNextIncludeOrder() once for each header in the file, passing - in the type constants defined above. Calls in an illegal order will - raise an _IncludeError with an appropriate error message. - - """ - # self._section will move monotonically through this set. If it ever - # needs to move backwards, CheckNextIncludeOrder will raise an error. - _INITIAL_SECTION = 0 - _MY_H_SECTION = 1 - _C_SECTION = 2 - _CPP_SECTION = 3 - _OTHER_H_SECTION = 4 - - _TYPE_NAMES = { - _C_SYS_HEADER: 'C system header', - _CPP_SYS_HEADER: 'C++ system header', - _LIKELY_MY_HEADER: 'header this file implements', - _POSSIBLE_MY_HEADER: 'header this file may implement', - _OTHER_HEADER: 'other header', - } - _SECTION_NAMES = { - _INITIAL_SECTION: "... nothing. (This can't be an error.)", - _MY_H_SECTION: 'a header this file implements', - _C_SECTION: 'C system header', - _CPP_SECTION: 'C++ system header', - _OTHER_H_SECTION: 'other header', - } - - def __init__(self): - dict.__init__(self) - # The name of the current section. - self._section = self._INITIAL_SECTION - # The path of last found header. - self._last_header = '' - - def CanonicalizeAlphabeticalOrder(self, header_path): - """Returns a path canonicalized for alphabetical comparison. - - - replaces "-" with "_" so they both cmp the same. - - removes '-inl' since we don't require them to be after the main header. - - lowercase everything, just in case. - - Args: - header_path: Path to be canonicalized. - - Returns: - Canonicalized path. - """ - return header_path.replace('-inl.h', '.h').replace('-', '_').lower() - - def IsInAlphabeticalOrder(self, header_path): - """Check if a header is in alphabetical order with the previous header. - - Args: - header_path: Header to be checked. - - Returns: - Returns true if the header is in alphabetical order. - """ - canonical_header = self.CanonicalizeAlphabeticalOrder(header_path) - if self._last_header > canonical_header: - return False - self._last_header = canonical_header - return True - - def CheckNextIncludeOrder(self, header_type): - """Returns a non-empty error message if the next header is out of order. - - This function also updates the internal state to be ready to check - the next include. - - Args: - header_type: One of the _XXX_HEADER constants defined above. - - Returns: - The empty string if the header is in the right order, or an - error message describing what's wrong. - - """ - error_message = ('Found %s after %s' % - (self._TYPE_NAMES[header_type], - self._SECTION_NAMES[self._section])) - - last_section = self._section - - if header_type == _C_SYS_HEADER: - if self._section <= self._C_SECTION: - self._section = self._C_SECTION - else: - self._last_header = '' - return error_message - elif header_type == _CPP_SYS_HEADER: - if self._section <= self._CPP_SECTION: - self._section = self._CPP_SECTION - else: - self._last_header = '' - return error_message - elif header_type == _LIKELY_MY_HEADER: - if self._section <= self._MY_H_SECTION: - self._section = self._MY_H_SECTION - else: - self._section = self._OTHER_H_SECTION - elif header_type == _POSSIBLE_MY_HEADER: - if self._section <= self._MY_H_SECTION: - self._section = self._MY_H_SECTION - else: - # This will always be the fallback because we're not sure - # enough that the header is associated with this file. - self._section = self._OTHER_H_SECTION - else: - assert header_type == _OTHER_HEADER - self._section = self._OTHER_H_SECTION - - if last_section != self._section: - self._last_header = '' - - return '' - - -class _CppLintState(object): - """Maintains module-wide state..""" - - def __init__(self): - self.verbose_level = 1 # global setting. - self.error_count = 0 # global count of reported errors - # filters to apply when emitting error messages - self.filters = _DEFAULT_FILTERS[:] - self.counting = 'total' # In what way are we counting errors? - self.errors_by_category = {} # string to int dict storing error counts - - # output format: - # "emacs" - format that emacs can parse (default) - # "vs7" - format that Microsoft Visual Studio 7 can parse - self.output_format = 'emacs' - - def SetOutputFormat(self, output_format): - """Sets the output format for errors.""" - self.output_format = output_format - - def SetVerboseLevel(self, level): - """Sets the module's verbosity, and returns the previous setting.""" - last_verbose_level = self.verbose_level - self.verbose_level = level - return last_verbose_level - - def SetCountingStyle(self, counting_style): - """Sets the module's counting options.""" - self.counting = counting_style - - def SetFilters(self, filters): - """Sets the error-message filters. - - These filters are applied when deciding whether to emit a given - error message. - - Args: - filters: A string of comma-separated filters (eg "+whitespace/indent"). - Each filter should start with + or -; else we die. - - Raises: - ValueError: The comma-separated filters did not all start with '+' or '-'. - E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" - """ - # Default filters always have less priority than the flag ones. - self.filters = _DEFAULT_FILTERS[:] - for filt in filters.split(','): - clean_filt = filt.strip() - if clean_filt: - self.filters.append(clean_filt) - for filt in self.filters: - if not (filt.startswith('+') or filt.startswith('-')): - raise ValueError('Every filter in --filters must start with + or -' - ' (%s does not)' % filt) - - def ResetErrorCounts(self): - """Sets the module's error statistic back to zero.""" - self.error_count = 0 - self.errors_by_category = {} - - def IncrementErrorCount(self, category): - """Bumps the module's error statistic.""" - self.error_count += 1 - if self.counting in ('toplevel', 'detailed'): - if self.counting != 'detailed': - category = category.split('/')[0] - if category not in self.errors_by_category: - self.errors_by_category[category] = 0 - self.errors_by_category[category] += 1 - - def PrintErrorCounts(self): - """Print a summary of errors by category, and the total.""" - for category, count in self.errors_by_category.iteritems(): - sys.stderr.write('Category \'%s\' errors found: %d\n' % - (category, count)) - sys.stderr.write('Total errors found: %d\n' % self.error_count) - -_cpplint_state = _CppLintState() - - -def _OutputFormat(): - """Gets the module's output format.""" - return _cpplint_state.output_format - - -def _SetOutputFormat(output_format): - """Sets the module's output format.""" - _cpplint_state.SetOutputFormat(output_format) - - -def _VerboseLevel(): - """Returns the module's verbosity setting.""" - return _cpplint_state.verbose_level - - -def _SetVerboseLevel(level): - """Sets the module's verbosity, and returns the previous setting.""" - return _cpplint_state.SetVerboseLevel(level) - - -def _SetCountingStyle(level): - """Sets the module's counting options.""" - _cpplint_state.SetCountingStyle(level) - - -def _Filters(): - """Returns the module's list of output filters, as a list.""" - return _cpplint_state.filters - - -def _SetFilters(filters): - """Sets the module's error-message filters. - - These filters are applied when deciding whether to emit a given - error message. - - Args: - filters: A string of comma-separated filters (eg "whitespace/indent"). - Each filter should start with + or -; else we die. - """ - _cpplint_state.SetFilters(filters) - - -class _FunctionState(object): - """Tracks current function name and the number of lines in its body.""" - - _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. - _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. - - def __init__(self): - self.in_a_function = False - self.lines_in_function = 0 - self.current_function = '' - - def Begin(self, function_name): - """Start analyzing function body. - - Args: - function_name: The name of the function being tracked. - """ - self.in_a_function = True - self.lines_in_function = 0 - self.current_function = function_name - - def Count(self): - """Count line in current function body.""" - if self.in_a_function: - self.lines_in_function += 1 - - def Check(self, error, filename, linenum): - """Report if too many lines in function body. - - Args: - error: The function to call with any errors found. - filename: The name of the current file. - linenum: The number of the line to check. - """ - if Match(r'T(EST|est)', self.current_function): - base_trigger = self._TEST_TRIGGER - else: - base_trigger = self._NORMAL_TRIGGER - trigger = base_trigger * 2**_VerboseLevel() - - if self.lines_in_function > trigger: - error_level = int(math.log(self.lines_in_function / base_trigger, 2)) - # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... - if error_level > 5: - error_level = 5 - error(filename, linenum, 'readability/fn_size', error_level, - 'Small and focused functions are preferred:' - ' %s has %d non-comment lines' - ' (error triggered by exceeding %d lines).' % ( - self.current_function, self.lines_in_function, trigger)) - - def End(self): - """Stop analyzing function body.""" - self.in_a_function = False - - -class _IncludeError(Exception): - """Indicates a problem with the include order in a file.""" - pass - - -class FileInfo: - """Provides utility functions for filenames. - - FileInfo provides easy access to the components of a file's path - relative to the project root. - """ - - def __init__(self, filename): - self._filename = filename - - def FullName(self): - """Make Windows paths like Unix.""" - return os.path.abspath(self._filename).replace('\\', '/') - - def RepositoryName(self): - """FullName after removing the local path to the repository. - - If we have a real absolute path name here we can try to do something smart: - detecting the root of the checkout and truncating /path/to/checkout from - the name so that we get header guards that don't include things like - "C:\Documents and Settings\..." or "/home/username/..." in them and thus - people on different computers who have checked the source out to different - locations won't see bogus errors. - """ - fullname = self.FullName() - - if os.path.exists(fullname): - project_dir = os.path.dirname(fullname) - - if os.path.exists(os.path.join(project_dir, ".svn")): - # If there's a .svn file in the current directory, we recursively look - # up the directory tree for the top of the SVN checkout - root_dir = project_dir - one_up_dir = os.path.dirname(root_dir) - while os.path.exists(os.path.join(one_up_dir, ".svn")): - root_dir = os.path.dirname(root_dir) - one_up_dir = os.path.dirname(one_up_dir) - - prefix = os.path.commonprefix([root_dir, project_dir]) - return fullname[len(prefix) + 1:] - - # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by - # searching up from the current path. - root_dir = os.path.dirname(fullname) - while (root_dir != os.path.dirname(root_dir) and - not os.path.exists(os.path.join(root_dir, ".git")) and - not os.path.exists(os.path.join(root_dir, ".hg")) and - not os.path.exists(os.path.join(root_dir, ".svn"))): - root_dir = os.path.dirname(root_dir) - - if (os.path.exists(os.path.join(root_dir, ".git")) or - os.path.exists(os.path.join(root_dir, ".hg")) or - os.path.exists(os.path.join(root_dir, ".svn"))): - prefix = os.path.commonprefix([root_dir, project_dir]) - return fullname[len(prefix) + 1:] - - # Don't know what to do; header guard warnings may be wrong... - return fullname - - def Split(self): - """Splits the file into the directory, basename, and extension. - - For 'chrome/browser/browser.cc', Split() would - return ('chrome/browser', 'browser', '.cc') - - Returns: - A tuple of (directory, basename, extension). - """ - - googlename = self.RepositoryName() - project, rest = os.path.split(googlename) - return (project,) + os.path.splitext(rest) - - def BaseName(self): - """File base name - text after the final slash, before the final period.""" - return self.Split()[1] - - def Extension(self): - """File extension - text following the final period.""" - return self.Split()[2] - - def NoExtension(self): - """File has no source file extension.""" - return '/'.join(self.Split()[0:2]) - - def IsSource(self): - """File has a source file extension.""" - return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') - - -def _ShouldPrintError(category, confidence, linenum): - """If confidence >= verbose, category passes filter and is not suppressed.""" - - # There are three ways we might decide not to print an error message: - # a "NOLINT(category)" comment appears in the source, - # the verbosity level isn't high enough, or the filters filter it out. - if IsErrorSuppressedByNolint(category, linenum): - return False - if confidence < _cpplint_state.verbose_level: - return False - - is_filtered = False - for one_filter in _Filters(): - if one_filter.startswith('-'): - if category.startswith(one_filter[1:]): - is_filtered = True - elif one_filter.startswith('+'): - if category.startswith(one_filter[1:]): - is_filtered = False - else: - assert False # should have been checked for in SetFilter. - if is_filtered: - return False - - return True - - -def Error(filename, linenum, category, confidence, message): - """Logs the fact we've found a lint error. - - We log where the error was found, and also our confidence in the error, - that is, how certain we are this is a legitimate style regression, and - not a misidentification or a use that's sometimes justified. - - False positives can be suppressed by the use of - "cpplint(category)" comments on the offending line. These are - parsed into _error_suppressions. - - Args: - filename: The name of the file containing the error. - linenum: The number of the line containing the error. - category: A string used to describe the "category" this bug - falls under: "whitespace", say, or "runtime". Categories - may have a hierarchy separated by slashes: "whitespace/indent". - confidence: A number from 1-5 representing a confidence score for - the error, with 5 meaning that we are certain of the problem, - and 1 meaning that it could be a legitimate construct. - message: The error message. - """ - if _ShouldPrintError(category, confidence, linenum): - _cpplint_state.IncrementErrorCount(category) - if _cpplint_state.output_format == 'vs7': - sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( - filename, linenum, message, category, confidence)) - elif _cpplint_state.output_format == 'eclipse': - sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( - filename, linenum, message, category, confidence)) - else: - sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( - filename, linenum, message, category, confidence)) - - -# Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard. -_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( - r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') -# Matches strings. Escape codes should already be removed by ESCAPES. -_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') -# Matches characters. Escape codes should already be removed by ESCAPES. -_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") -# Matches multi-line C++ comments. -# This RE is a little bit more complicated than one might expect, because we -# have to take care of space removals tools so we can handle comments inside -# statements better. -# The current rule is: We only clear spaces from both sides when we're at the -# end of the line. Otherwise, we try to remove spaces from the right side, -# if this doesn't work we try on left side but only if there's a non-character -# on the right. -_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( - r"""(\s*/\*.*\*/\s*$| - /\*.*\*/\s+| - \s+/\*.*\*/(?=\W)| - /\*.*\*/)""", re.VERBOSE) - - -def IsCppString(line): - """Does line terminate so, that the next symbol is in string constant. - - This function does not consider single-line nor multi-line comments. - - Args: - line: is a partial line of code starting from the 0..n. - - Returns: - True, if next character appended to 'line' is inside a - string constant. - """ - - line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" - return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 - - -def FindNextMultiLineCommentStart(lines, lineix): - """Find the beginning marker for a multiline comment.""" - while lineix < len(lines): - if lines[lineix].strip().startswith('/*'): - # Only return this marker if the comment goes beyond this line - if lines[lineix].strip().find('*/', 2) < 0: - return lineix - lineix += 1 - return len(lines) - - -def FindNextMultiLineCommentEnd(lines, lineix): - """We are inside a comment, find the end marker.""" - while lineix < len(lines): - if lines[lineix].strip().endswith('*/'): - return lineix - lineix += 1 - return len(lines) - - -def RemoveMultiLineCommentsFromRange(lines, begin, end): - """Clears a range of lines for multi-line comments.""" - # Having // dummy comments makes the lines non-empty, so we will not get - # unnecessary blank line warnings later in the code. - for i in range(begin, end): - lines[i] = '// dummy' - - -def RemoveMultiLineComments(filename, lines, error): - """Removes multiline (c-style) comments from lines.""" - lineix = 0 - while lineix < len(lines): - lineix_begin = FindNextMultiLineCommentStart(lines, lineix) - if lineix_begin >= len(lines): - return - lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin) - if lineix_end >= len(lines): - error(filename, lineix_begin + 1, 'readability/multiline_comment', 5, - 'Could not find end of multi-line comment') - return - RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1) - lineix = lineix_end + 1 - - -def CleanseComments(line): - """Removes //-comments and single-line C-style /* */ comments. - - Args: - line: A line of C++ source. - - Returns: - The line with single-line comments removed. - """ - commentpos = line.find('//') - if commentpos != -1 and not IsCppString(line[:commentpos]): - line = line[:commentpos].rstrip() - # get rid of /* ... */ - return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) - - -class CleansedLines(object): - """Holds 3 copies of all lines with different preprocessing applied to them. - - 1) elided member contains lines without strings and comments, - 2) lines member contains lines without comments, and - 3) raw_lines member contains all the lines without processing. - All these three members are of <type 'list'>, and of the same length. - """ - - def __init__(self, lines): - self.elided = [] - self.lines = [] - self.raw_lines = lines - self.num_lines = len(lines) - for linenum in range(len(lines)): - self.lines.append(CleanseComments(lines[linenum])) - elided = self._CollapseStrings(lines[linenum]) - self.elided.append(CleanseComments(elided)) - - def NumLines(self): - """Returns the number of lines represented.""" - return self.num_lines - - @staticmethod - def _CollapseStrings(elided): - """Collapses strings and chars on a line to simple "" or '' blocks. - - We nix strings first so we're not fooled by text like '"http://"' - - Args: - elided: The line being processed. - - Returns: - The line with collapsed strings. - """ - if not _RE_PATTERN_INCLUDE.match(elided): - # Remove escaped characters first to make quote/single quote collapsing - # basic. Things that look like escaped characters shouldn't occur - # outside of strings and chars. - elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) - elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) - elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) - return elided - - -def FindEndOfExpressionInLine(line, startpos, depth, startchar, endchar): - """Find the position just after the matching endchar. - - Args: - line: a CleansedLines line. - startpos: start searching at this position. - depth: nesting level at startpos. - startchar: expression opening character. - endchar: expression closing character. - - Returns: - Index just after endchar. - """ - for i in xrange(startpos, len(line)): - if line[i] == startchar: - depth += 1 - elif line[i] == endchar: - depth -= 1 - if depth == 0: - return i + 1 - return -1 - - -def CloseExpression(clean_lines, linenum, pos): - """If input points to ( or { or [, finds the position that closes it. - - If lines[linenum][pos] points to a '(' or '{' or '[', finds the - linenum/pos that correspond to the closing of the expression. - - Args: - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - pos: A position on the line. - - Returns: - A tuple (line, linenum, pos) pointer *past* the closing brace, or - (line, len(lines), -1) if we never find a close. Note we ignore - strings and comments when matching; and the line we return is the - 'cleansed' line at linenum. - """ - - line = clean_lines.elided[linenum] - startchar = line[pos] - if startchar not in '({[': - return (line, clean_lines.NumLines(), -1) - if startchar == '(': endchar = ')' - if startchar == '[': endchar = ']' - if startchar == '{': endchar = '}' - - # Check first line - end_pos = FindEndOfExpressionInLine(line, pos, 0, startchar, endchar) - if end_pos > -1: - return (line, linenum, end_pos) - tail = line[pos:] - num_open = tail.count(startchar) - tail.count(endchar) - while linenum < clean_lines.NumLines() - 1: - linenum += 1 - line = clean_lines.elided[linenum] - delta = line.count(startchar) - line.count(endchar) - if num_open + delta <= 0: - return (line, linenum, - FindEndOfExpressionInLine(line, 0, num_open, startchar, endchar)) - num_open += delta - - # Did not find endchar before end of file, give up - return (line, clean_lines.NumLines(), -1) - -def CheckForCopyright(filename, lines, error): - """Logs an error if no Copyright message appears at the top of the file.""" - - # We'll say it should occur by line 10. Don't forget there's a - # dummy line at the front. - for line in xrange(1, min(len(lines), 11)): - if re.search(r'Copyright', lines[line], re.I): break - else: # means no copyright line was found - error(filename, 0, 'legal/copyright', 5, - 'No copyright message found. ' - 'You should have a line: "Copyright [year] <Copyright Owner>"') - - -def GetHeaderGuardCPPVariable(filename): - """Returns the CPP variable that should be used as a header guard. - - Args: - filename: The name of a C++ header file. - - Returns: - The CPP variable that should be used as a header guard in the - named file. - - """ - - # Restores original filename in case that cpplint is invoked from Emacs's - # flymake. - filename = re.sub(r'_flymake\.h$', '.h', filename) - filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename) - - fileinfo = FileInfo(filename) - file_path_from_root = fileinfo.RepositoryName() - if _root: - file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root) - return re.sub(r'[-./\s]', '_', file_path_from_root).upper() + '_' - - -def CheckForHeaderGuard(filename, lines, error): - """Checks that the file contains a header guard. - - Logs an error if no #ifndef header guard is present. For other - headers, checks that the full pathname is used. - - Args: - filename: The name of the C++ header file. - lines: An array of strings, each representing a line of the file. - error: The function to call with any errors found. - """ - - cppvar = GetHeaderGuardCPPVariable(filename) - - ifndef = None - ifndef_linenum = 0 - define = None - endif = None - endif_linenum = 0 - for linenum, line in enumerate(lines): - linesplit = line.split() - if len(linesplit) >= 2: - # find the first occurrence of #ifndef and #define, save arg - if not ifndef and linesplit[0] == '#ifndef': - # set ifndef to the header guard presented on the #ifndef line. - ifndef = linesplit[1] - ifndef_linenum = linenum - if not define and linesplit[0] == '#define': - define = linesplit[1] - # find the last occurrence of #endif, save entire line - if line.startswith('#endif'): - endif = line - endif_linenum = linenum - - if not ifndef: - error(filename, 0, 'build/header_guard', 5, - 'No #ifndef header guard found, suggested CPP variable is: %s' % - cppvar) - return - - if not define: - error(filename, 0, 'build/header_guard', 5, - 'No #define header guard found, suggested CPP variable is: %s' % - cppvar) - return - - # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__ - # for backward compatibility. - if ifndef != cppvar: - error_level = 0 - if ifndef != cppvar + '_': - error_level = 5 - - ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum, - error) - error(filename, ifndef_linenum, 'build/header_guard', error_level, - '#ifndef header guard has wrong style, please use: %s' % cppvar) - - if define != ifndef: - error(filename, 0, 'build/header_guard', 5, - '#ifndef and #define don\'t match, suggested CPP variable is: %s' % - cppvar) - return - - if endif != ('#endif // %s' % cppvar): - error_level = 0 - if endif != ('#endif // %s' % (cppvar + '_')): - error_level = 5 - - ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum, - error) - error(filename, endif_linenum, 'build/header_guard', error_level, - '#endif line should be "#endif // %s"' % cppvar) - - -def CheckForUnicodeReplacementCharacters(filename, lines, error): - """Logs an error for each line containing Unicode replacement characters. - - These indicate that either the file contained invalid UTF-8 (likely) - or Unicode replacement characters (which it shouldn't). Note that - it's possible for this to throw off line numbering if the invalid - UTF-8 occurred adjacent to a newline. - - Args: - filename: The name of the current file. - lines: An array of strings, each representing a line of the file. - error: The function to call with any errors found. - """ - for linenum, line in enumerate(lines): - if u'\ufffd' in line: - error(filename, linenum, 'readability/utf8', 5, - 'Line contains invalid UTF-8 (or Unicode replacement character).') - - -def CheckForNewlineAtEOF(filename, lines, error): - """Logs an error if there is no newline char at the end of the file. - - Args: - filename: The name of the current file. - lines: An array of strings, each representing a line of the file. - error: The function to call with any errors found. - """ - - # The array lines() was created by adding two newlines to the - # original file (go figure), then splitting on \n. - # To verify that the file ends in \n, we just have to make sure the - # last-but-two element of lines() exists and is empty. - if len(lines) < 3 or lines[-2]: - error(filename, len(lines) - 2, 'whitespace/ending_newline', 5, - 'Could not find a newline character at the end of the file.') - - -def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error): - """Logs an error if we see /* ... */ or "..." that extend past one line. - - /* ... */ comments are legit inside macros, for one line. - Otherwise, we prefer // comments, so it's ok to warn about the - other. Likewise, it's ok for strings to extend across multiple - lines, as long as a line continuation character (backslash) - terminates each line. Although not currently prohibited by the C++ - style guide, it's ugly and unnecessary. We don't do well with either - in this lint program, so we warn about both. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] - - # Remove all \\ (escaped backslashes) from the line. They are OK, and the - # second (escaped) slash may trigger later \" detection erroneously. - line = line.replace('\\\\', '') - - if line.count('/*') > line.count('*/'): - error(filename, linenum, 'readability/multiline_comment', 5, - 'Complex multi-line /*...*/-style comment found. ' - 'Lint may give bogus warnings. ' - 'Consider replacing these with //-style comments, ' - 'with #if 0...#endif, ' - 'or with more clearly structured multi-line comments.') - - if (line.count('"') - line.count('\\"')) % 2: - error(filename, linenum, 'readability/multiline_string', 5, - 'Multi-line string ("...") found. This lint script doesn\'t ' - 'do well with such strings, and may give bogus warnings. They\'re ' - 'ugly and unnecessary, and you should use concatenation instead".') - - -threading_list = ( - ('asctime(', 'asctime_r('), - ('ctime(', 'ctime_r('), - ('getgrgid(', 'getgrgid_r('), - ('getgrnam(', 'getgrnam_r('), - ('getlogin(', 'getlogin_r('), - ('getpwnam(', 'getpwnam_r('), - ('getpwuid(', 'getpwuid_r('), - ('gmtime(', 'gmtime_r('), - ('localtime(', 'localtime_r('), - ('rand(', 'rand_r('), - ('readdir(', 'readdir_r('), - ('strtok(', 'strtok_r('), - ('ttyname(', 'ttyname_r('), - ) - - -def CheckPosixThreading(filename, clean_lines, linenum, error): - """Checks for calls to thread-unsafe functions. - - Much code has been originally written without consideration of - multi-threading. Also, engineers are relying on their old experience; - they have learned posix before threading extensions were added. These - tests guide the engineers to use thread-safe functions (when using - posix directly). - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] - for single_thread_function, multithread_safe_function in threading_list: - ix = line.find(single_thread_function) - # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 - if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and - line[ix - 1] not in ('_', '.', '>'))): - error(filename, linenum, 'runtime/threadsafe_fn', 2, - 'Consider using ' + multithread_safe_function + - '...) instead of ' + single_thread_function + - '...) for improved thread safety.') - - -# Matches invalid increment: *count++, which moves pointer instead of -# incrementing a value. -_RE_PATTERN_INVALID_INCREMENT = re.compile( - r'^\s*\*\w+(\+\+|--);') - - -def CheckInvalidIncrement(filename, clean_lines, linenum, error): - """Checks for invalid increment *count++. - - For example following function: - void increment_counter(int* count) { - *count++; - } - is invalid, because it effectively does count++, moving pointer, and should - be replaced with ++*count, (*count)++ or *count += 1. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] - if _RE_PATTERN_INVALID_INCREMENT.match(line): - error(filename, linenum, 'runtime/invalid_increment', 5, - 'Changing pointer instead of value (or unused value of operator*).') - - -class _BlockInfo(object): - """Stores information about a generic block of code.""" - - def __init__(self, seen_open_brace): - self.seen_open_brace = seen_open_brace - self.open_parentheses = 0 - self.inline_asm = _NO_ASM - - def CheckBegin(self, filename, clean_lines, linenum, error): - """Run checks that applies to text up to the opening brace. - - This is mostly for checking the text after the class identifier - and the "{", usually where the base class is specified. For other - blocks, there isn't much to check, so we always pass. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - pass - - def CheckEnd(self, filename, clean_lines, linenum, error): - """Run checks that applies to text after the closing brace. - - This is mostly used for checking end of namespace comments. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - pass - - -class _ClassInfo(_BlockInfo): - """Stores information about a class.""" - - def __init__(self, name, class_or_struct, clean_lines, linenum): - _BlockInfo.__init__(self, False) - self.name = name - self.starting_linenum = linenum - self.is_derived = False - if class_or_struct == 'struct': - self.access = 'public' - else: - self.access = 'private' - - # Try to find the end of the class. This will be confused by things like: - # class A { - # } *x = { ... - # - # But it's still good enough for CheckSectionSpacing. - self.last_line = 0 - depth = 0 - for i in range(linenum, clean_lines.NumLines()): - line = clean_lines.elided[i] - depth += line.count('{') - line.count('}') - if not depth: - self.last_line = i - break - - def CheckBegin(self, filename, clean_lines, linenum, error): - # Look for a bare ':' - if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]): - self.is_derived = True - - -class _NamespaceInfo(_BlockInfo): - """Stores information about a namespace.""" - - def __init__(self, name, linenum): - _BlockInfo.__init__(self, False) - self.name = name or '' - self.starting_linenum = linenum - - def CheckEnd(self, filename, clean_lines, linenum, error): - """Check end of namespace comments.""" - line = clean_lines.raw_lines[linenum] - - # Check how many lines is enclosed in this namespace. Don't issue - # warning for missing namespace comments if there aren't enough - # lines. However, do apply checks if there is already an end of - # namespace comment and it's incorrect. - # - # TODO(unknown): We always want to check end of namespace comments - # if a namespace is large, but sometimes we also want to apply the - # check if a short namespace contained nontrivial things (something - # other than forward declarations). There is currently no logic on - # deciding what these nontrivial things are, so this check is - # triggered by namespace size only, which works most of the time. - if (linenum - self.starting_linenum < 10 - and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)): - return - - # Look for matching comment at end of namespace. - # - # Note that we accept C style "/* */" comments for terminating - # namespaces, so that code that terminate namespaces inside - # preprocessor macros can be cpplint clean. Example: http://go/nxpiz - # - # We also accept stuff like "// end of namespace <name>." with the - # period at the end. - # - # Besides these, we don't accept anything else, otherwise we might - # get false negatives when existing comment is a substring of the - # expected namespace. Example: http://go/ldkdc, http://cl/23548205 - if self.name: - # Named namespace - if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + - r'[\*/\.\\\s]*$'), - line): - error(filename, linenum, 'readability/namespace', 5, - 'Namespace should be terminated with "// namespace %s"' % - self.name) - else: - # Anonymous namespace - if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): - error(filename, linenum, 'readability/namespace', 5, - 'Namespace should be terminated with "// namespace"') - - -class _PreprocessorInfo(object): - """Stores checkpoints of nesting stacks when #if/#else is seen.""" - - def __init__(self, stack_before_if): - # The entire nesting stack before #if - self.stack_before_if = stack_before_if - - # The entire nesting stack up to #else - self.stack_before_else = [] - - # Whether we have already seen #else or #elif - self.seen_else = False - - -class _NestingState(object): - """Holds states related to parsing braces.""" - - def __init__(self): - # Stack for tracking all braces. An object is pushed whenever we - # see a "{", and popped when we see a "}". Only 3 types of - # objects are possible: - # - _ClassInfo: a class or struct. - # - _NamespaceInfo: a namespace. - # - _BlockInfo: some other type of block. - self.stack = [] - - # Stack of _PreprocessorInfo objects. - self.pp_stack = [] - - def SeenOpenBrace(self): - """Check if we have seen the opening brace for the innermost block. - - Returns: - True if we have seen the opening brace, False if the innermost - block is still expecting an opening brace. - """ - return (not self.stack) or self.stack[-1].seen_open_brace - - def InNamespaceBody(self): - """Check if we are currently one level inside a namespace body. - - Returns: - True if top of the stack is a namespace block, False otherwise. - """ - return self.stack and isinstance(self.stack[-1], _NamespaceInfo) - - def UpdatePreprocessor(self, line): - """Update preprocessor stack. - - We need to handle preprocessors due to classes like this: - #ifdef SWIG - struct ResultDetailsPageElementExtensionPoint { - #else - struct ResultDetailsPageElementExtensionPoint : public Extension { - #endif - (see http://go/qwddn for original example) - - We make the following assumptions (good enough for most files): - - Preprocessor condition evaluates to true from #if up to first - #else/#elif/#endif. - - - Preprocessor condition evaluates to false from #else/#elif up - to #endif. We still perform lint checks on these lines, but - these do not affect nesting stack. - - Args: - line: current line to check. - """ - if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line): - # Beginning of #if block, save the nesting stack here. The saved - # stack will allow us to restore the parsing state in the #else case. - self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack))) - elif Match(r'^\s*#\s*(else|elif)\b', line): - # Beginning of #else block - if self.pp_stack: - if not self.pp_stack[-1].seen_else: - # This is the first #else or #elif block. Remember the - # whole nesting stack up to this point. This is what we - # keep after the #endif. - self.pp_stack[-1].seen_else = True - self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack) - - # Restore the stack to how it was before the #if - self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if) - else: - # TODO(unknown): unexpected #else, issue warning? - pass - elif Match(r'^\s*#\s*endif\b', line): - # End of #if or #else blocks. - if self.pp_stack: - # If we saw an #else, we will need to restore the nesting - # stack to its former state before the #else, otherwise we - # will just continue from where we left off. - if self.pp_stack[-1].seen_else: - # Here we can just use a shallow copy since we are the last - # reference to it. - self.stack = self.pp_stack[-1].stack_before_else - # Drop the corresponding #if - self.pp_stack.pop() - else: - # TODO(unknown): unexpected #endif, issue warning? - pass - - def Update(self, filename, clean_lines, linenum, error): - """Update nesting state with current line. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] - - # Update pp_stack first - self.UpdatePreprocessor(line) - - # Count parentheses. This is to avoid adding struct arguments to - # the nesting stack. - if self.stack: - inner_block = self.stack[-1] - depth_change = line.count('(') - line.count(')') - inner_block.open_parentheses += depth_change - - # Also check if we are starting or ending an inline assembly block. - if inner_block.inline_asm in (_NO_ASM, _END_ASM): - if (depth_change != 0 and - inner_block.open_parentheses == 1 and - _MATCH_ASM.match(line)): - # Enter assembly block - inner_block.inline_asm = _INSIDE_ASM - else: - # Not entering assembly block. If previous line was _END_ASM, - # we will now shift to _NO_ASM state. - inner_block.inline_asm = _NO_ASM - elif (inner_block.inline_asm == _INSIDE_ASM and - inner_block.open_parentheses == 0): - # Exit assembly block - inner_block.inline_asm = _END_ASM - - # Consume namespace declaration at the beginning of the line. Do - # this in a loop so that we catch same line declarations like this: - # namespace proto2 { namespace bridge { class MessageSet; } } - while True: - # Match start of namespace. The "\b\s*" below catches namespace - # declarations even if it weren't followed by a whitespace, this - # is so that we don't confuse our namespace checker. The - # missing spaces will be flagged by CheckSpacing. - namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line) - if not namespace_decl_match: - break - - new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum) - self.stack.append(new_namespace) - - line = namespace_decl_match.group(2) - if line.find('{') != -1: - new_namespace.seen_open_brace = True - line = line[line.find('{') + 1:] - - # Look for a class declaration in whatever is left of the line - # after parsing namespaces. The regexp accounts for decorated classes - # such as in: - # class LOCKABLE API Object { - # }; - # - # Templates with class arguments may confuse the parser, for example: - # template <class T - # class Comparator = less<T>, - # class Vector = vector<T> > - # class HeapQueue { - # - # Because this parser has no nesting state about templates, by the - # time it saw "class Comparator", it may think that it's a new class. - # Nested templates have a similar problem: - # template < - # typename ExportedType, - # typename TupleType, - # template <typename, typename> class ImplTemplate> - # - # To avoid these cases, we ignore classes that are followed by '=' or '>' - class_decl_match = Match( - r'\s*(template\s*<[\w\s<>,:]*>\s*)?' - '(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)' - '(([^=>]|<[^<>]*>)*)$', line) - if (class_decl_match and - (not self.stack or self.stack[-1].open_parentheses == 0)): - self.stack.append(_ClassInfo( - class_decl_match.group(4), class_decl_match.group(2), - clean_lines, linenum)) - line = class_decl_match.group(5) - - # If we have not yet seen the opening brace for the innermost block, - # run checks here. - if not self.SeenOpenBrace(): - self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) - - # Update access control if we are inside a class/struct - if self.stack and isinstance(self.stack[-1], _ClassInfo): - access_match = Match(r'\s*(public|private|protected)\s*:', line) - if access_match: - self.stack[-1].access = access_match.group(1) - - # Consume braces or semicolons from what's left of the line - while True: - # Match first brace, semicolon, or closed parenthesis. - matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line) - if not matched: - break - - token = matched.group(1) - if token == '{': - # If namespace or class hasn't seen a opening brace yet, mark - # namespace/class head as complete. Push a new block onto the - # stack otherwise. - if not self.SeenOpenBrace(): - self.stack[-1].seen_open_brace = True - else: - self.stack.append(_BlockInfo(True)) - if _MATCH_ASM.match(line): - self.stack[-1].inline_asm = _BLOCK_ASM - elif token == ';' or token == ')': - # If we haven't seen an opening brace yet, but we already saw - # a semicolon, this is probably a forward declaration. Pop - # the stack for these. - # - # Similarly, if we haven't seen an opening brace yet, but we - # already saw a closing parenthesis, then these are probably - # function arguments with extra "class" or "struct" keywords. - # Also pop these stack for these. - if not self.SeenOpenBrace(): - self.stack.pop() - else: # token == '}' - # Perform end of block checks and pop the stack. - if self.stack: - self.stack[-1].CheckEnd(filename, clean_lines, linenum, error) - self.stack.pop() - line = matched.group(2) - - def InnermostClass(self): - """Get class info on the top of the stack. - - Returns: - A _ClassInfo object if we are inside a class, or None otherwise. - """ - for i in range(len(self.stack), 0, -1): - classinfo = self.stack[i - 1] - if isinstance(classinfo, _ClassInfo): - return classinfo - return None - - def CheckClassFinished(self, filename, error): - """Checks that all classes have been completely parsed. - - Call this when all lines in a file have been processed. - Args: - filename: The name of the current file. - error: The function to call with any errors found. - """ - # Note: This test can result in false positives if #ifdef constructs - # get in the way of brace matching. See the testBuildClass test in - # cpplint_unittest.py for an example of this. - for obj in self.stack: - if isinstance(obj, _ClassInfo): - error(filename, obj.starting_linenum, 'build/class', 5, - 'Failed to find complete declaration of class %s' % - obj.name) - - -def CheckForNonStandardConstructs(filename, clean_lines, linenum, - nesting_state, error): - """Logs an error if we see certain non-ANSI constructs ignored by gcc-2. - - Complain about several constructs which gcc-2 accepts, but which are - not standard C++. Warning about these in lint is one way to ease the - transition to new compilers. - - put storage class first (e.g. "static const" instead of "const static"). - - "%lld" instead of %qd" in printf-type functions. - - "%1$d" is non-standard in printf-type functions. - - "\%" is an undefined character escape sequence. - - text after #endif is not allowed. - - invalid inner-style forward declaration. - - >? and <? operators, and their >?= and <?= cousins. - - Additionally, check for constructor/destructor style violations and reference - members, as it is very convenient to do so while checking for - gcc-2 compliance. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - nesting_state: A _NestingState instance which maintains information about - the current stack of nested blocks being parsed. - error: A callable to which errors are reported, which takes 4 arguments: - filename, line number, error level, and message - """ - - # Remove comments from the line, but leave in strings for now. - line = clean_lines.lines[linenum] - - if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line): - error(filename, linenum, 'runtime/printf_format', 3, - '%q in format strings is deprecated. Use %ll instead.') - - if Search(r'printf\s*\(.*".*%\d+\$', line): - error(filename, linenum, 'runtime/printf_format', 2, - '%N$ formats are unconventional. Try rewriting to avoid them.') - - # Remove escaped backslashes before looking for undefined escapes. - line = line.replace('\\\\', '') - - if Search(r'("|\').*\\(%|\[|\(|{)', line): - error(filename, linenum, 'build/printf_format', 3, - '%, [, (, and { are undefined character escapes. Unescape them.') - - # For the rest, work with both comments and strings removed. - line = clean_lines.elided[linenum] - - if Search(r'\b(const|volatile|void|char|short|int|long' - r'|float|double|signed|unsigned' - r'|schar|u?int8|u?int16|u?int32|u?int64)' - r'\s+(register|static|extern|typedef)\b', - line): - error(filename, linenum, 'build/storage_class', 5, - 'Storage class (static, extern, typedef, etc) should be first.') - - if Match(r'\s*#\s*endif\s*[^/\s]+', line): - error(filename, linenum, 'build/endif_comment', 5, - 'Uncommented text after #endif is non-standard. Use a comment.') - - if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line): - error(filename, linenum, 'build/forward_decl', 5, - 'Inner-style forward declarations are invalid. Remove this line.') - - if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', - line): - error(filename, linenum, 'build/deprecated', 3, - '>? and <? (max and min) operators are non-standard and deprecated.') - - if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line): - # TODO(unknown): Could it be expanded safely to arbitrary references, - # without triggering too many false positives? The first - # attempt triggered 5 warnings for mostly benign code in the regtest, hence - # the restriction. - # Here's the original regexp, for the reference: - # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?' - # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;' - error(filename, linenum, 'runtime/member_string_references', 2, - 'const string& members are dangerous. It is much better to use ' - 'alternatives, such as pointers or simple constants.') - - # Everything else in this function operates on class declarations. - # Return early if the top of the nesting stack is not a class, or if - # the class head is not completed yet. - classinfo = nesting_state.InnermostClass() - if not classinfo or not classinfo.seen_open_brace: - return - - # The class may have been declared with namespace or classname qualifiers. - # The constructor and destructor will not have those qualifiers. - base_classname = classinfo.name.split('::')[-1] - - # Look for single-argument constructors that aren't marked explicit. - # Technically a valid construct, but against style. - args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' - % re.escape(base_classname), - line) - if (args and - args.group(1) != 'void' and - not Match(r'(const\s+)?%s\s*(?:<\w+>\s*)?&' % re.escape(base_classname), - args.group(1).strip())): - error(filename, linenum, 'runtime/explicit', 5, - 'Single-argument constructors should be marked explicit.') - - -def CheckSpacingForFunctionCall(filename, line, linenum, error): - """Checks for the correctness of various spacing around function calls. - - Args: - filename: The name of the current file. - line: The text of the line to check. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - - # Since function calls often occur inside if/for/while/switch - # expressions - which have their own, more liberal conventions - we - # first see if we should be looking inside such an expression for a - # function call, to which we can apply more strict standards. - fncall = line # if there's no control flow construct, look at whole line - for pattern in (r'\bif\s*\((.*)\)\s*{', - r'\bfor\s*\((.*)\)\s*{', - r'\bwhile\s*\((.*)\)\s*[{;]', - r'\bswitch\s*\((.*)\)\s*{'): - match = Search(pattern, line) - if match: - fncall = match.group(1) # look inside the parens for function calls - break - - # Except in if/for/while/switch, there should never be space - # immediately inside parens (eg "f( 3, 4 )"). We make an exception - # for nested parens ( (a+b) + c ). Likewise, there should never be - # a space before a ( when it's a function argument. I assume it's a - # function argument when the char before the whitespace is legal in - # a function name (alnum + _) and we're not starting a macro. Also ignore - # pointers and references to arrays and functions coz they're too tricky: - # we use a very simple way to recognize these: - # " (something)(maybe-something)" or - # " (something)(maybe-something," or - # " (something)[something]" - # Note that we assume the contents of [] to be short enough that - # they'll never need to wrap. - if ( # Ignore control structures. - not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and - # Ignore pointers/references to functions. - not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and - # Ignore pointers/references to arrays. - not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): - if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call - error(filename, linenum, 'whitespace/parens', 4, - 'Extra space after ( in function call') - elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): - error(filename, linenum, 'whitespace/parens', 2, - 'Extra space after (') - if (Search(r'\w\s+\(', fncall) and - not Search(r'#\s*define|typedef', fncall) and - not Search(r'\w\s+\((\w+::)?\*\w+\)\(', fncall)): - error(filename, linenum, 'whitespace/parens', 4, - 'Extra space before ( in function call') - # If the ) is followed only by a newline or a { + newline, assume it's - # part of a control statement (if/while/etc), and don't complain - if Search(r'[^)]\s+\)\s*[^{\s]', fncall): - # If the closing parenthesis is preceded by only whitespaces, - # try to give a more descriptive error message. - if Search(r'^\s+\)', fncall): - error(filename, linenum, 'whitespace/parens', 2, - 'Closing ) should be moved to the previous line') - else: - error(filename, linenum, 'whitespace/parens', 2, - 'Extra space before )') - - -def IsBlankLine(line): - """Returns true if the given line is blank. - - We consider a line to be blank if the line is empty or consists of - only white spaces. - - Args: - line: A line of a string. - - Returns: - True, if the given line is blank. - """ - return not line or line.isspace() - - -def CheckForFunctionLengths(filename, clean_lines, linenum, - function_state, error): - """Reports for long function bodies. - - For an overview why this is done, see: - http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions - - Uses a simplistic algorithm assuming other style guidelines - (especially spacing) are followed. - Only checks unindented functions, so class members are unchecked. - Trivial bodies are unchecked, so constructors with huge initializer lists - may be missed. - Blank/comment lines are not counted so as to avoid encouraging the removal - of vertical space and comments just to get through a lint check. - NOLINT *on the last line of a function* disables this check. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - function_state: Current function name and lines in body so far. - error: The function to call with any errors found. - """ - lines = clean_lines.lines - line = lines[linenum] - raw = clean_lines.raw_lines - raw_line = raw[linenum] - joined_line = '' - - starting_func = False - regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... - match_result = Match(regexp, line) - if match_result: - # If the name is all caps and underscores, figure it's a macro and - # ignore it, unless it's TEST or TEST_F. - function_name = match_result.group(1).split()[-1] - if function_name == 'TEST' or function_name == 'TEST_F' or ( - not Match(r'[A-Z_]+$', function_name)): - starting_func = True - - if starting_func: - body_found = False - for start_linenum in xrange(linenum, clean_lines.NumLines()): - start_line = lines[start_linenum] - joined_line += ' ' + start_line.lstrip() - if Search(r'(;|})', start_line): # Declarations and trivial functions - body_found = True - break # ... ignore - elif Search(r'{', start_line): - body_found = True - function = Search(r'((\w|:)*)\(', line).group(1) - if Match(r'TEST', function): # Handle TEST... macros - parameter_regexp = Search(r'(\(.*\))', joined_line) - if parameter_regexp: # Ignore bad syntax - function += parameter_regexp.group(1) - else: - function += '()' - function_state.Begin(function) - break - if not body_found: - # No body for the function (or evidence of a non-function) was found. - error(filename, linenum, 'readability/fn_size', 5, - 'Lint failed to find start of function body.') - elif Match(r'^\}\s*$', line): # function end - function_state.Check(error, filename, linenum) - function_state.End() - elif not Match(r'^\s*$', line): - function_state.Count() # Count non-blank/non-comment lines. - - -_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') - - -def CheckComment(comment, filename, linenum, error): - """Checks for common mistakes in TODO comments. - - Args: - comment: The text of the comment from the line in question. - filename: The name of the current file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - match = _RE_PATTERN_TODO.match(comment) - if match: - # One whitespace is correct; zero whitespace is handled elsewhere. - leading_whitespace = match.group(1) - if len(leading_whitespace) > 1: - error(filename, linenum, 'whitespace/todo', 2, - 'Too many spaces before TODO') - - username = match.group(2) - if not username: - error(filename, linenum, 'readability/todo', 2, - 'Missing username in TODO; it should look like ' - '"// TODO(my_username): Stuff."') - - middle_whitespace = match.group(3) - # Comparisons made explicit for correctness -- pylint: disable-msg=C6403 - if middle_whitespace != ' ' and middle_whitespace != '': - error(filename, linenum, 'whitespace/todo', 2, - 'TODO(my_username) should be followed by a space') - -def CheckAccess(filename, clean_lines, linenum, nesting_state, error): - """Checks for improper use of DISALLOW* macros. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - nesting_state: A _NestingState instance which maintains information about - the current stack of nested blocks being parsed. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] # get rid of comments and strings - - matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|' - r'DISALLOW_EVIL_CONSTRUCTORS|' - r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line) - if not matched: - return - if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo): - if nesting_state.stack[-1].access != 'private': - error(filename, linenum, 'readability/constructors', 3, - '%s must be in the private: section' % matched.group(1)) - - else: - # Found DISALLOW* macro outside a class declaration, or perhaps it - # was used inside a function when it should have been part of the - # class declaration. We could issue a warning here, but it - # probably resulted in a compiler error already. - pass - - -def FindNextMatchingAngleBracket(clean_lines, linenum, init_suffix): - """Find the corresponding > to close a template. - - Args: - clean_lines: A CleansedLines instance containing the file. - linenum: Current line number. - init_suffix: Remainder of the current line after the initial <. - - Returns: - True if a matching bracket exists. - """ - line = init_suffix - nesting_stack = ['<'] - while True: - # Find the next operator that can tell us whether < is used as an - # opening bracket or as a less-than operator. We only want to - # warn on the latter case. - # - # We could also check all other operators and terminate the search - # early, e.g. if we got something like this "a<b+c", the "<" is - # most likely a less-than operator, but then we will get false - # positives for default arguments (e.g. http://go/prccd) and - # other template expressions (e.g. http://go/oxcjq). - match = Search(r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line) - if match: - # Found an operator, update nesting stack - operator = match.group(1) - line = match.group(2) - - if nesting_stack[-1] == '<': - # Expecting closing angle bracket - if operator in ('<', '(', '['): - nesting_stack.append(operator) - elif operator == '>': - nesting_stack.pop() - if not nesting_stack: - # Found matching angle bracket - return True - elif operator == ',': - # Got a comma after a bracket, this is most likely a template - # argument. We have not seen a closing angle bracket yet, but - # it's probably a few lines later if we look for it, so just - # return early here. - return True - else: - # Got some other operator. - return False - - else: - # Expecting closing parenthesis or closing bracket - if operator in ('<', '(', '['): - nesting_stack.append(operator) - elif operator in (')', ']'): - # We don't bother checking for matching () or []. If we got - # something like (] or [), it would have been a syntax error. - nesting_stack.pop() - - else: - # Scan the next line - linenum += 1 - if linenum >= len(clean_lines.elided): - break - line = clean_lines.elided[linenum] - - # Exhausted all remaining lines and still no matching angle bracket. - # Most likely the input was incomplete, otherwise we should have - # seen a semicolon and returned early. - return True - - -def FindPreviousMatchingAngleBracket(clean_lines, linenum, init_prefix): - """Find the corresponding < that started a template. - - Args: - clean_lines: A CleansedLines instance containing the file. - linenum: Current line number. - init_prefix: Part of the current line before the initial >. - - Returns: - True if a matching bracket exists. - """ - line = init_prefix - nesting_stack = ['>'] - while True: - # Find the previous operator - match = Search(r'^(.*)([<>(),;\[\]])[^<>(),;\[\]]*$', line) - if match: - # Found an operator, update nesting stack - operator = match.group(2) - line = match.group(1) - - if nesting_stack[-1] == '>': - # Expecting opening angle bracket - if operator in ('>', ')', ']'): - nesting_stack.append(operator) - elif operator == '<': - nesting_stack.pop() - if not nesting_stack: - # Found matching angle bracket - return True - elif operator == ',': - # Got a comma before a bracket, this is most likely a - # template argument. The opening angle bracket is probably - # there if we look for it, so just return early here. - return True - else: - # Got some other operator. - return False - - else: - # Expecting opening parenthesis or opening bracket - if operator in ('>', ')', ']'): - nesting_stack.append(operator) - elif operator in ('(', '['): - nesting_stack.pop() - - else: - # Scan the previous line - linenum -= 1 - if linenum < 0: - break - line = clean_lines.elided[linenum] - - # Exhausted all earlier lines and still no matching angle bracket. - return False - - -def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): - """Checks for the correctness of various spacing issues in the code. - - Things we check for: spaces around operators, spaces after - if/for/while/switch, no spaces around parens in function calls, two - spaces between code and comment, don't start a block with a blank - line, don't end a function with a blank line, don't add a blank line - after public/protected/private, don't have too many blank lines in a row. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - nesting_state: A _NestingState instance which maintains information about - the current stack of nested blocks being parsed. - error: The function to call with any errors found. - """ - - raw = clean_lines.raw_lines - line = raw[linenum] - - # Before nixing comments, check if the line is blank for no good - # reason. This includes the first line after a block is opened, and - # blank lines at the end of a function (ie, right before a line like '}' - # - # Skip all the blank line checks if we are immediately inside a - # namespace body. In other words, don't issue blank line warnings - # for this block: - # namespace { - # - # } - # - # A warning about missing end of namespace comments will be issued instead. - if IsBlankLine(line) and not nesting_state.InNamespaceBody(): - elided = clean_lines.elided - prev_line = elided[linenum - 1] - prevbrace = prev_line.rfind('{') - # TODO(unknown): Don't complain if line before blank line, and line after, - # both start with alnums and are indented the same amount. - # This ignores whitespace at the start of a namespace block - # because those are not usually indented. - if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1: - # OK, we have a blank line at the start of a code block. Before we - # complain, we check if it is an exception to the rule: The previous - # non-empty line has the parameters of a function header that are indented - # 4 spaces (because they did not fit in a 80 column line when placed on - # the same line as the function name). We also check for the case where - # the previous line is indented 6 spaces, which may happen when the - # initializers of a constructor do not fit into a 80 column line. - exception = False - if Match(r' {6}\w', prev_line): # Initializer list? - # We are looking for the opening column of initializer list, which - # should be indented 4 spaces to cause 6 space indentation afterwards. - search_position = linenum-2 - while (search_position >= 0 - and Match(r' {6}\w', elided[search_position])): - search_position -= 1 - exception = (search_position >= 0 - and elided[search_position][:5] == ' :') - else: - # Search for the function arguments or an initializer list. We use a - # simple heuristic here: If the line is indented 4 spaces; and we have a - # closing paren, without the opening paren, followed by an opening brace - # or colon (for initializer lists) we assume that it is the last line of - # a function header. If we have a colon indented 4 spaces, it is an - # initializer list. - exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', - prev_line) - or Match(r' {4}:', prev_line)) - - if not exception: - error(filename, linenum, 'whitespace/blank_line', 2, - 'Blank line at the start of a code block. Is this needed?') - # Ignore blank lines at the end of a block in a long if-else - # chain, like this: - # if (condition1) { - # // Something followed by a blank line - # - # } else if (condition2) { - # // Something else - # } - if linenum + 1 < clean_lines.NumLines(): - next_line = raw[linenum + 1] - if (next_line - and Match(r'\s*}', next_line) - and next_line.find('} else ') == -1): - error(filename, linenum, 'whitespace/blank_line', 3, - 'Blank line at the end of a code block. Is this needed?') - - matched = Match(r'\s*(public|protected|private):', prev_line) - if matched: - error(filename, linenum, 'whitespace/blank_line', 3, - 'Do not leave a blank line after "%s:"' % matched.group(1)) - - # Next, we complain if there's a comment too near the text - commentpos = line.find('//') - if commentpos != -1: - # Check if the // may be in quotes. If so, ignore it - # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 - if (line.count('"', 0, commentpos) - - line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes - # Allow one space for new scopes, two spaces otherwise: - if (not Match(r'^\s*{ //', line) and - ((commentpos >= 1 and - line[commentpos-1] not in string.whitespace) or - (commentpos >= 2 and - line[commentpos-2] not in string.whitespace))): - error(filename, linenum, 'whitespace/comments', 2, - 'At least two spaces is best between code and comments') - # There should always be a space between the // and the comment - commentend = commentpos + 2 - if commentend < len(line) and not line[commentend] == ' ': - # but some lines are exceptions -- e.g. if they're big - # comment delimiters like: - # //---------------------------------------------------------- - # or are an empty C++ style Doxygen comment, like: - # /// - # or they begin with multiple slashes followed by a space: - # //////// Header comment - match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or - Search(r'^/$', line[commentend:]) or - Search(r'^/+ ', line[commentend:])) - if not match: - error(filename, linenum, 'whitespace/comments', 4, - 'Should have a space between // and comment') - CheckComment(line[commentpos:], filename, linenum, error) - - line = clean_lines.elided[linenum] # get rid of comments and strings - - # Don't try to do spacing checks for operator methods - line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) - - # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". - # Otherwise not. Note we only check for non-spaces on *both* sides; - # sometimes people put non-spaces on one side when aligning ='s among - # many lines (not that this is behavior that I approve of...) - if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line): - error(filename, linenum, 'whitespace/operators', 4, - 'Missing spaces around =') - - # It's ok not to have spaces around binary operators like + - * /, but if - # there's too little whitespace, we get concerned. It's hard to tell, - # though, so we punt on this one for now. TODO. - - # You should always have whitespace around binary operators. - # - # Check <= and >= first to avoid false positives with < and >, then - # check non-include lines for spacing around < and >. - match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line) - if match: - error(filename, linenum, 'whitespace/operators', 3, - 'Missing spaces around %s' % match.group(1)) - # We allow no-spaces around << when used like this: 10<<20, but - # not otherwise (particularly, not when used as streams) - match = Search(r'(\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line) - if match and not (match.group(1).isdigit() and match.group(2).isdigit()): - error(filename, linenum, 'whitespace/operators', 3, - 'Missing spaces around <<') - elif not Match(r'#.*include', line): - # Avoid false positives on -> - reduced_line = line.replace('->', '') - - # Look for < that is not surrounded by spaces. This is only - # triggered if both sides are missing spaces, even though - # technically should should flag if at least one side is missing a - # space. This is done to avoid some false positives with shifts. - match = Search(r'[^\s<]<([^\s=<].*)', reduced_line) - if (match and - not FindNextMatchingAngleBracket(clean_lines, linenum, match.group(1))): - error(filename, linenum, 'whitespace/operators', 3, - 'Missing spaces around <') - - # Look for > that is not surrounded by spaces. Similar to the - # above, we only trigger if both sides are missing spaces to avoid - # false positives with shifts. - match = Search(r'^(.*[^\s>])>[^\s=>]', reduced_line) - if (match and - not FindPreviousMatchingAngleBracket(clean_lines, linenum, - match.group(1))): - error(filename, linenum, 'whitespace/operators', 3, - 'Missing spaces around >') - - # We allow no-spaces around >> for almost anything. This is because - # C++11 allows ">>" to close nested templates, which accounts for - # most cases when ">>" is not followed by a space. - # - # We still warn on ">>" followed by alpha character, because that is - # likely due to ">>" being used for right shifts, e.g.: - # value >> alpha - # - # When ">>" is used to close templates, the alphanumeric letter that - # follows would be part of an identifier, and there should still be - # a space separating the template type and the identifier. - # type<type<type>> alpha - match = Search(r'>>[a-zA-Z_]', line) - if match: - error(filename, linenum, 'whitespace/operators', 3, - 'Missing spaces around >>') - - # There shouldn't be space around unary operators - match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) - if match: - error(filename, linenum, 'whitespace/operators', 4, - 'Extra space for operator %s' % match.group(1)) - - # A pet peeve of mine: no spaces after an if, while, switch, or for - match = Search(r' (if\(|for\(|while\(|switch\()', line) - if match: - error(filename, linenum, 'whitespace/parens', 5, - 'Missing space before ( in %s' % match.group(1)) - - # For if/for/while/switch, the left and right parens should be - # consistent about how many spaces are inside the parens, and - # there should either be zero or one spaces inside the parens. - # We don't want: "if ( foo)" or "if ( foo )". - # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. - match = Search(r'\b(if|for|while|switch)\s*' - r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', - line) - if match: - if len(match.group(2)) != len(match.group(4)): - if not (match.group(3) == ';' and - len(match.group(2)) == 1 + len(match.group(4)) or - not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): - error(filename, linenum, 'whitespace/parens', 5, - 'Mismatching spaces inside () in %s' % match.group(1)) - if not len(match.group(2)) in [0, 1]: - error(filename, linenum, 'whitespace/parens', 5, - 'Should have zero or one spaces inside ( and ) in %s' % - match.group(1)) - - # You should always have a space after a comma (either as fn arg or operator) - if Search(r',[^\s]', line): - error(filename, linenum, 'whitespace/comma', 3, - 'Missing space after ,') - - # You should always have a space after a semicolon - # except for few corner cases - # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more - # space after ; - if Search(r';[^\s};\\)/]', line): - error(filename, linenum, 'whitespace/semicolon', 3, - 'Missing space after ;') - - # Next we will look for issues with function calls. - CheckSpacingForFunctionCall(filename, line, linenum, error) - - # Except after an opening paren, or after another opening brace (in case of - # an initializer list, for instance), you should have spaces before your - # braces. And since you should never have braces at the beginning of a line, - # this is an easy test. - if Search(r'[^ ({]{', line): - error(filename, linenum, 'whitespace/braces', 5, - 'Missing space before {') - - # Make sure '} else {' has spaces. - if Search(r'}else', line): - error(filename, linenum, 'whitespace/braces', 5, - 'Missing space before else') - - # You shouldn't have spaces before your brackets, except maybe after - # 'delete []' or 'new char * []'. - if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line): - error(filename, linenum, 'whitespace/braces', 5, - 'Extra space before [') - - # You shouldn't have a space before a semicolon at the end of the line. - # There's a special case for "for" since the style guide allows space before - # the semicolon there. - if Search(r':\s*;\s*$', line): - error(filename, linenum, 'whitespace/semicolon', 5, - 'Semicolon defining empty statement. Use {} instead.') - elif Search(r'^\s*;\s*$', line): - error(filename, linenum, 'whitespace/semicolon', 5, - 'Line contains only semicolon. If this should be an empty statement, ' - 'use {} instead.') - elif (Search(r'\s+;\s*$', line) and - not Search(r'\bfor\b', line)): - error(filename, linenum, 'whitespace/semicolon', 5, - 'Extra space before last semicolon. If this should be an empty ' - 'statement, use {} instead.') - - # In range-based for, we wanted spaces before and after the colon, but - # not around "::" tokens that might appear. - if (Search('for *\(.*[^:]:[^: ]', line) or - Search('for *\(.*[^: ]:[^:]', line)): - error(filename, linenum, 'whitespace/forcolon', 2, - 'Missing space around colon in range-based for loop') - - -def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): - """Checks for additional blank line issues related to sections. - - Currently the only thing checked here is blank line before protected/private. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - class_info: A _ClassInfo objects. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - # Skip checks if the class is small, where small means 25 lines or less. - # 25 lines seems like a good cutoff since that's the usual height of - # terminals, and any class that can't fit in one screen can't really - # be considered "small". - # - # Also skip checks if we are on the first line. This accounts for - # classes that look like - # class Foo { public: ... }; - # - # If we didn't find the end of the class, last_line would be zero, - # and the check will be skipped by the first condition. - if (class_info.last_line - class_info.starting_linenum <= 24 or - linenum <= class_info.starting_linenum): - return - - matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum]) - if matched: - # Issue warning if the line before public/protected/private was - # not a blank line, but don't do this if the previous line contains - # "class" or "struct". This can happen two ways: - # - We are at the beginning of the class. - # - We are forward-declaring an inner class that is semantically - # private, but needed to be public for implementation reasons. - # Also ignores cases where the previous line ends with a backslash as can be - # common when defining classes in C macros. - prev_line = clean_lines.lines[linenum - 1] - if (not IsBlankLine(prev_line) and - not Search(r'\b(class|struct)\b', prev_line) and - not Search(r'\\$', prev_line)): - # Try a bit harder to find the beginning of the class. This is to - # account for multi-line base-specifier lists, e.g.: - # class Derived - # : public Base { - end_class_head = class_info.starting_linenum - for i in range(class_info.starting_linenum, linenum): - if Search(r'\{\s*$', clean_lines.lines[i]): - end_class_head = i - break - if end_class_head < linenum - 1: - error(filename, linenum, 'whitespace/blank_line', 3, - '"%s:" should be preceded by a blank line' % matched.group(1)) - - -def GetPreviousNonBlankLine(clean_lines, linenum): - """Return the most recent non-blank line and its line number. - - Args: - clean_lines: A CleansedLines instance containing the file contents. - linenum: The number of the line to check. - - Returns: - A tuple with two elements. The first element is the contents of the last - non-blank line before the current line, or the empty string if this is the - first non-blank line. The second is the line number of that line, or -1 - if this is the first non-blank line. - """ - - prevlinenum = linenum - 1 - while prevlinenum >= 0: - prevline = clean_lines.elided[prevlinenum] - if not IsBlankLine(prevline): # if not a blank line... - return (prevline, prevlinenum) - prevlinenum -= 1 - return ('', -1) - - -def CheckBraces(filename, clean_lines, linenum, error): - """Looks for misplaced braces (e.g. at the end of line). - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - - line = clean_lines.elided[linenum] # get rid of comments and strings - - if Match(r'\s*{\s*$', line): - # We allow an open brace to start a line in the case where someone - # is using braces in a block to explicitly create a new scope, - # which is commonly used to control the lifetime of - # stack-allocated variables. We don't detect this perfectly: we - # just don't complain if the last non-whitespace character on the - # previous non-blank line is ';', ':', '{', or '}', or if the previous - # line starts a preprocessor block. - prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] - if (not Search(r'[;:}{]\s*$', prevline) and - not Match(r'\s*#', prevline)): - error(filename, linenum, 'whitespace/braces', 4, - '{ should almost always be at the end of the previous line') - - # An else clause should be on the same line as the preceding closing brace. - if Match(r'\s*else\s*', line): - prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] - if Match(r'\s*}\s*$', prevline): - error(filename, linenum, 'whitespace/newline', 4, - 'An else should appear on the same line as the preceding }') - - # If braces come on one side of an else, they should be on both. - # However, we have to worry about "else if" that spans multiple lines! - if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): - if Search(r'}\s*else if([^{]*)$', line): # could be multi-line if - # find the ( after the if - pos = line.find('else if') - pos = line.find('(', pos) - if pos > 0: - (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) - if endline[endpos:].find('{') == -1: # must be brace after if - error(filename, linenum, 'readability/braces', 5, - 'If an else has a brace on one side, it should have it on both') - else: # common case: else not followed by a multi-line if - error(filename, linenum, 'readability/braces', 5, - 'If an else has a brace on one side, it should have it on both') - - # Likewise, an else should never have the else clause on the same line - if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): - error(filename, linenum, 'whitespace/newline', 4, - 'Else clause should never be on same line as else (use 2 lines)') - - # In the same way, a do/while should never be on one line - if Match(r'\s*do [^\s{]', line): - error(filename, linenum, 'whitespace/newline', 4, - 'do/while clauses should not be on a single line') - - # Braces shouldn't be followed by a ; unless they're defining a struct - # or initializing an array. - # We can't tell in general, but we can for some common cases. - prevlinenum = linenum - while True: - (prevline, prevlinenum) = GetPreviousNonBlankLine(clean_lines, prevlinenum) - if Match(r'\s+{.*}\s*;', line) and not prevline.count(';'): - line = prevline + line - else: - break - if (Search(r'{.*}\s*;', line) and - line.count('{') == line.count('}') and - not Search(r'struct|class|enum|\s*=\s*{', line)): - error(filename, linenum, 'readability/braces', 4, - "You don't need a ; after a }") - - -def CheckEmptyLoopBody(filename, clean_lines, linenum, error): - """Loop for empty loop body with only a single semicolon. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - - # Search for loop keywords at the beginning of the line. Because only - # whitespaces are allowed before the keywords, this will also ignore most - # do-while-loops, since those lines should start with closing brace. - line = clean_lines.elided[linenum] - if Match(r'\s*(for|while)\s*\(', line): - # Find the end of the conditional expression - (end_line, end_linenum, end_pos) = CloseExpression( - clean_lines, linenum, line.find('(')) - - # Output warning if what follows the condition expression is a semicolon. - # No warning for all other cases, including whitespace or newline, since we - # have a separate check for semicolons preceded by whitespace. - if end_pos >= 0 and Match(r';', end_line[end_pos:]): - error(filename, end_linenum, 'whitespace/empty_loop_body', 5, - 'Empty loop bodies should use {} or continue') - - -def ReplaceableCheck(operator, macro, line): - """Determine whether a basic CHECK can be replaced with a more specific one. - - For example suggest using CHECK_EQ instead of CHECK(a == b) and - similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE. - - Args: - operator: The C++ operator used in the CHECK. - macro: The CHECK or EXPECT macro being called. - line: The current source line. - - Returns: - True if the CHECK can be replaced with a more specific one. - """ - - # This matches decimal and hex integers, strings, and chars (in that order). - match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')' - - # Expression to match two sides of the operator with something that - # looks like a literal, since CHECK(x == iterator) won't compile. - # This means we can't catch all the cases where a more specific - # CHECK is possible, but it's less annoying than dealing with - # extraneous warnings. - match_this = (r'\s*' + macro + r'\((\s*' + - match_constant + r'\s*' + operator + r'[^<>].*|' - r'.*[^<>]' + operator + r'\s*' + match_constant + - r'\s*\))') - - # Don't complain about CHECK(x == NULL) or similar because - # CHECK_EQ(x, NULL) won't compile (requires a cast). - # Also, don't complain about more complex boolean expressions - # involving && or || such as CHECK(a == b || c == d). - return Match(match_this, line) and not Search(r'NULL|&&|\|\|', line) - - -def CheckCheck(filename, clean_lines, linenum, error): - """Checks the use of CHECK and EXPECT macros. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - - # Decide the set of replacement macros that should be suggested - raw_lines = clean_lines.raw_lines - current_macro = '' - for macro in _CHECK_MACROS: - if raw_lines[linenum].find(macro) >= 0: - current_macro = macro - break - if not current_macro: - # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' - return - - line = clean_lines.elided[linenum] # get rid of comments and strings - - # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc. - for operator in ['==', '!=', '>=', '>', '<=', '<']: - if ReplaceableCheck(operator, current_macro, line): - error(filename, linenum, 'readability/check', 2, - 'Consider using %s instead of %s(a %s b)' % ( - _CHECK_REPLACEMENT[current_macro][operator], - current_macro, operator)) - break - - -def CheckAltTokens(filename, clean_lines, linenum, error): - """Check alternative keywords being used in boolean expressions. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - line = clean_lines.elided[linenum] - - # Avoid preprocessor lines - if Match(r'^\s*#', line): - return - - # Last ditch effort to avoid multi-line comments. This will not help - # if the comment started before the current line or ended after the - # current line, but it catches most of the false positives. At least, - # it provides a way to workaround this warning for people who use - # multi-line comments in preprocessor macros. - # - # TODO(unknown): remove this once cpplint has better support for - # multi-line comments. - if line.find('/*') >= 0 or line.find('*/') >= 0: - return - - for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line): - error(filename, linenum, 'readability/alt_tokens', 2, - 'Use operator %s instead of %s' % ( - _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1))) - - -def GetLineWidth(line): - """Determines the width of the line in column positions. - - Args: - line: A string, which may be a Unicode string. - - Returns: - The width of the line in column positions, accounting for Unicode - combining characters and wide characters. - """ - if isinstance(line, unicode): - width = 0 - for uc in unicodedata.normalize('NFC', line): - if unicodedata.east_asian_width(uc) in ('W', 'F'): - width += 2 - elif not unicodedata.combining(uc): - width += 1 - return width - else: - return len(line) - - -def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, - error): - """Checks rules from the 'C++ style rules' section of cppguide.html. - - Most of these rules are hard to test (naming, comment style), but we - do what we can. In particular we check for 2-space indents, line lengths, - tab usage, spaces inside code, etc. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - file_extension: The extension (without the dot) of the filename. - nesting_state: A _NestingState instance which maintains information about - the current stack of nested blocks being parsed. - error: The function to call with any errors found. - """ - - raw_lines = clean_lines.raw_lines - line = raw_lines[linenum] - - if line.find('\t') != -1: - error(filename, linenum, 'whitespace/tab', 1, - 'Tab found; better to use spaces') - - # One or three blank spaces at the beginning of the line is weird; it's - # hard to reconcile that with 2-space indents. - # NOTE: here are the conditions rob pike used for his tests. Mine aren't - # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces - # if(RLENGTH > 20) complain = 0; - # if(match($0, " +(error|private|public|protected):")) complain = 0; - # if(match(prev, "&& *$")) complain = 0; - # if(match(prev, "\\|\\| *$")) complain = 0; - # if(match(prev, "[\",=><] *$")) complain = 0; - # if(match($0, " <<")) complain = 0; - # if(match(prev, " +for \\(")) complain = 0; - # if(prevodd && match(prevprev, " +for \\(")) complain = 0; - initial_spaces = 0 - cleansed_line = clean_lines.elided[linenum] - while initial_spaces < len(line) and line[initial_spaces] == ' ': - initial_spaces += 1 - if line and line[-1].isspace(): - error(filename, linenum, 'whitespace/end_of_line', 4, - 'Line ends in whitespace. Consider deleting these extra spaces.') - # There are certain situations we allow one space, notably for labels - elif ((initial_spaces == 1 or initial_spaces == 3) and - not Match(r'\s*\w+\s*:\s*$', cleansed_line)): - error(filename, linenum, 'whitespace/indent', 3, - 'Weird number of spaces at line-start. ' - 'Are you using a 2-space indent?') - # Labels should always be indented at least one space. - elif not initial_spaces and line[:2] != '//' and Search(r'[^:]:\s*$', - line): - error(filename, linenum, 'whitespace/labels', 4, - 'Labels should always be indented at least one space. ' - 'If this is a member-initializer list in a constructor or ' - 'the base class list in a class definition, the colon should ' - 'be on the following line.') - - - # Check if the line is a header guard. - is_header_guard = False - if file_extension == 'h': - cppvar = GetHeaderGuardCPPVariable(filename) - if (line.startswith('#ifndef %s' % cppvar) or - line.startswith('#define %s' % cppvar) or - line.startswith('#endif // %s' % cppvar)): - is_header_guard = True - # #include lines and header guards can be long, since there's no clean way to - # split them. - # - # URLs can be long too. It's possible to split these, but it makes them - # harder to cut&paste. - # - # The "$Id:...$" comment may also get very long without it being the - # developers fault. - if (not line.startswith('#include') and not is_header_guard and - not Match(r'^\s*//.*http(s?)://\S*$', line) and - not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): - line_width = GetLineWidth(line) - if line_width > 100: - error(filename, linenum, 'whitespace/line_length', 4, - 'Lines should very rarely be longer than 100 characters') - elif line_width > 80: - error(filename, linenum, 'whitespace/line_length', 2, - 'Lines should be <= 80 characters long') - - if (cleansed_line.count(';') > 1 and - # for loops are allowed two ;'s (and may run over two lines). - cleansed_line.find('for') == -1 and - (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or - GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and - # It's ok to have many commands in a switch case that fits in 1 line - not ((cleansed_line.find('case ') != -1 or - cleansed_line.find('default:') != -1) and - cleansed_line.find('break;') != -1)): - error(filename, linenum, 'whitespace/newline', 0, - 'More than one command on the same line') - - # Some more style checks - CheckBraces(filename, clean_lines, linenum, error) - CheckEmptyLoopBody(filename, clean_lines, linenum, error) - CheckAccess(filename, clean_lines, linenum, nesting_state, error) - CheckSpacing(filename, clean_lines, linenum, nesting_state, error) - CheckCheck(filename, clean_lines, linenum, error) - CheckAltTokens(filename, clean_lines, linenum, error) - classinfo = nesting_state.InnermostClass() - if classinfo: - CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) - - -_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') -_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') -# Matches the first component of a filename delimited by -s and _s. That is: -# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' -# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' -# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo' -# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo' -_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') - - -def _DropCommonSuffixes(filename): - """Drops common suffixes like _test.cc or -inl.h from filename. - - For example: - >>> _DropCommonSuffixes('foo/foo-inl.h') - 'foo/foo' - >>> _DropCommonSuffixes('foo/bar/foo.cc') - 'foo/bar/foo' - >>> _DropCommonSuffixes('foo/foo_internal.h') - 'foo/foo' - >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') - 'foo/foo_unusualinternal' - - Args: - filename: The input filename. - - Returns: - The filename with the common suffix removed. - """ - for suffix in ('test.cc', 'regtest.cc', 'unittest.cc', - 'inl.h', 'impl.h', 'internal.h'): - if (filename.endswith(suffix) and len(filename) > len(suffix) and - filename[-len(suffix) - 1] in ('-', '_')): - return filename[:-len(suffix) - 1] - return os.path.splitext(filename)[0] - - -def _IsTestFilename(filename): - """Determines if the given filename has a suffix that identifies it as a test. - - Args: - filename: The input filename. - - Returns: - True if 'filename' looks like a test, False otherwise. - """ - if (filename.endswith('_test.cc') or - filename.endswith('_unittest.cc') or - filename.endswith('_regtest.cc')): - return True - else: - return False - - -def _ClassifyInclude(fileinfo, include, is_system): - """Figures out what kind of header 'include' is. - - Args: - fileinfo: The current file cpplint is running over. A FileInfo instance. - include: The path to a #included file. - is_system: True if the #include used <> rather than "". - - Returns: - One of the _XXX_HEADER constants. - - For example: - >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) - _C_SYS_HEADER - >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) - _CPP_SYS_HEADER - >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) - _LIKELY_MY_HEADER - >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), - ... 'bar/foo_other_ext.h', False) - _POSSIBLE_MY_HEADER - >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) - _OTHER_HEADER - """ - # This is a list of all standard c++ header files, except - # those already checked for above. - is_stl_h = include in _STL_HEADERS - is_cpp_h = is_stl_h or include in _CPP_HEADERS - - if is_system: - if is_cpp_h: - return _CPP_SYS_HEADER - else: - return _C_SYS_HEADER - - # If the target file and the include we're checking share a - # basename when we drop common extensions, and the include - # lives in . , then it's likely to be owned by the target file. - target_dir, target_base = ( - os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName()))) - include_dir, include_base = os.path.split(_DropCommonSuffixes(include)) - if target_base == include_base and ( - include_dir == target_dir or - include_dir == os.path.normpath(target_dir + '/../public')): - return _LIKELY_MY_HEADER - - # If the target and include share some initial basename - # component, it's possible the target is implementing the - # include, so it's allowed to be first, but we'll never - # complain if it's not there. - target_first_component = _RE_FIRST_COMPONENT.match(target_base) - include_first_component = _RE_FIRST_COMPONENT.match(include_base) - if (target_first_component and include_first_component and - target_first_component.group(0) == - include_first_component.group(0)): - return _POSSIBLE_MY_HEADER - - return _OTHER_HEADER - - - -def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): - """Check rules that are applicable to #include lines. - - Strings on #include lines are NOT removed from elided line, to make - certain tasks easier. However, to prevent false positives, checks - applicable to #include lines in CheckLanguage must be put here. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - include_state: An _IncludeState instance in which the headers are inserted. - error: The function to call with any errors found. - """ - fileinfo = FileInfo(filename) - - line = clean_lines.lines[linenum] - - # "include" should use the new style "foo/bar.h" instead of just "bar.h" - if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line): - error(filename, linenum, 'build/include', 4, - 'Include the directory when naming .h files') - - # we shouldn't include a file more than once. actually, there are a - # handful of instances where doing so is okay, but in general it's - # not. - match = _RE_PATTERN_INCLUDE.search(line) - if match: - include = match.group(2) - is_system = (match.group(1) == '<') - if include in include_state: - error(filename, linenum, 'build/include', 4, - '"%s" already included at %s:%s' % - (include, filename, include_state[include])) - else: - include_state[include] = linenum - - # We want to ensure that headers appear in the right order: - # 1) for foo.cc, foo.h (preferred location) - # 2) c system files - # 3) cpp system files - # 4) for foo.cc, foo.h (deprecated location) - # 5) other google headers - # - # We classify each include statement as one of those 5 types - # using a number of techniques. The include_state object keeps - # track of the highest type seen, and complains if we see a - # lower type after that. - error_message = include_state.CheckNextIncludeOrder( - _ClassifyInclude(fileinfo, include, is_system)) - if error_message: - error(filename, linenum, 'build/include_order', 4, - '%s. Should be: %s.h, c system, c++ system, other.' % - (error_message, fileinfo.BaseName())) - if not include_state.IsInAlphabeticalOrder(include): - error(filename, linenum, 'build/include_alpha', 4, - 'Include "%s" not in alphabetical order' % include) - - # Look for any of the stream classes that are part of standard C++. - match = _RE_PATTERN_INCLUDE.match(line) - if match: - include = match.group(2) - if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): - # Many unit tests use cout, so we exempt them. - if not _IsTestFilename(filename): - error(filename, linenum, 'readability/streams', 3, - 'Streams are highly discouraged.') - - -def _GetTextInside(text, start_pattern): - """Retrieves all the text between matching open and close parentheses. - - Given a string of lines and a regular expression string, retrieve all the text - following the expression and between opening punctuation symbols like - (, [, or {, and the matching close-punctuation symbol. This properly nested - occurrences of the punctuations, so for the text like - printf(a(), b(c())); - a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. - start_pattern must match string having an open punctuation symbol at the end. - - Args: - text: The lines to extract text. Its comments and strings must be elided. - It can be single line and can span multiple lines. - start_pattern: The regexp string indicating where to start extracting - the text. - Returns: - The extracted text. - None if either the opening string or ending punctuation could not be found. - """ - # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably - # rewritten to use _GetTextInside (and use inferior regexp matching today). - - # Give opening punctuations to get the matching close-punctuations. - matching_punctuation = {'(': ')', '{': '}', '[': ']'} - closing_punctuation = set(matching_punctuation.itervalues()) - - # Find the position to start extracting text. - match = re.search(start_pattern, text, re.M) - if not match: # start_pattern not found in text. - return None - start_position = match.end(0) - - assert start_position > 0, ( - 'start_pattern must ends with an opening punctuation.') - assert text[start_position - 1] in matching_punctuation, ( - 'start_pattern must ends with an opening punctuation.') - # Stack of closing punctuations we expect to have in text after position. - punctuation_stack = [matching_punctuation[text[start_position - 1]]] - position = start_position - while punctuation_stack and position < len(text): - if text[position] == punctuation_stack[-1]: - punctuation_stack.pop() - elif text[position] in closing_punctuation: - # A closing punctuation without matching opening punctuations. - return None - elif text[position] in matching_punctuation: - punctuation_stack.append(matching_punctuation[text[position]]) - position += 1 - if punctuation_stack: - # Opening punctuations left without matching close-punctuations. - return None - # punctuations match. - return text[start_position:position - 1] - - -def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, - error): - """Checks rules from the 'C++ language rules' section of cppguide.html. - - Some of these rules are hard to test (function overloading, using - uint32 inappropriately), but we do the best we can. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - file_extension: The extension (without the dot) of the filename. - include_state: An _IncludeState instance in which the headers are inserted. - error: The function to call with any errors found. - """ - # If the line is empty or consists of entirely a comment, no need to - # check it. - line = clean_lines.elided[linenum] - if not line: - return - - match = _RE_PATTERN_INCLUDE.search(line) - if match: - CheckIncludeLine(filename, clean_lines, linenum, include_state, error) - return - - # Create an extended_line, which is the concatenation of the current and - # next lines, for more effective checking of code that may span more than one - # line. - if linenum + 1 < clean_lines.NumLines(): - extended_line = line + clean_lines.elided[linenum + 1] - else: - extended_line = line - - # Make Windows paths like Unix. - fullname = os.path.abspath(filename).replace('\\', '/') - - # TODO(unknown): figure out if they're using default arguments in fn proto. - - # Check for non-const references in functions. This is tricky because & - # is also used to take the address of something. We allow <> for templates, - # (ignoring whatever is between the braces) and : for classes. - # These are complicated re's. They try to capture the following: - # paren (for fn-prototype start), typename, &, varname. For the const - # version, we're willing for const to be before typename or after - # Don't check the implementation on same line. - fnline = line.split('{', 1)[0] - if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) > - len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?' - r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) + - len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+', - fnline))): - - # We allow non-const references in a few standard places, like functions - # called "swap()" or iostream operators like "<<" or ">>". We also filter - # out for loops, which lint otherwise mistakenly thinks are functions. - if not Search( - r'(for|swap|Swap|operator[<>][<>])\s*\(\s*' - r'(?:(?:typename\s*)?[\w:]|<.*>)+\s*&', - fnline): - error(filename, linenum, 'runtime/references', 2, - 'Is this a non-const reference? ' - 'If so, make const or use a pointer.') - - # Check to see if they're using an conversion function cast. - # I just try to capture the most common basic types, though there are more. - # Parameterless conversion functions, such as bool(), are allowed as they are - # probably a member operator declaration or default constructor. - match = Search( - r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there - r'(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line) - if match: - # gMock methods are defined using some variant of MOCK_METHODx(name, type) - # where type may be float(), int(string), etc. Without context they are - # virtually indistinguishable from int(x) casts. Likewise, gMock's - # MockCallback takes a template parameter of the form return_type(arg_type), - # which looks much like the cast we're trying to detect. - if (match.group(1) is None and # If new operator, then this isn't a cast - not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or - Match(r'^\s*MockCallback<.*>', line))): - # Try a bit harder to catch gmock lines: the only place where - # something looks like an old-style cast is where we declare the - # return type of the mocked method, and the only time when we - # are missing context is if MOCK_METHOD was split across - # multiple lines (for example http://go/hrfhr ), so we only need - # to check the previous line for MOCK_METHOD. - if (linenum == 0 or - not Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(\S+,\s*$', - clean_lines.elided[linenum - 1])): - error(filename, linenum, 'readability/casting', 4, - 'Using deprecated casting style. ' - 'Use static_cast<%s>(...) instead' % - match.group(2)) - - CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], - 'static_cast', - r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) - - # This doesn't catch all cases. Consider (const char * const)"hello". - # - # (char *) "foo" should always be a const_cast (reinterpret_cast won't - # compile). - if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], - 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): - pass - else: - # Check pointer casts for other than string constants - CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], - 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) - - # In addition, we look for people taking the address of a cast. This - # is dangerous -- casts can assign to temporaries, so the pointer doesn't - # point where you think. - if Search( - r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line): - error(filename, linenum, 'runtime/casting', 4, - ('Are you taking an address of a cast? ' - 'This is dangerous: could be a temp var. ' - 'Take the address before doing the cast, rather than after')) - - # Check for people declaring static/global STL strings at the top level. - # This is dangerous because the C++ language does not guarantee that - # globals with constructors are initialized before the first access. - match = Match( - r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', - line) - # Make sure it's not a function. - # Function template specialization looks like: "string foo<Type>(...". - # Class template definitions look like: "string Foo<Type>::Method(...". - if match and not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', - match.group(3)): - error(filename, linenum, 'runtime/string', 4, - 'For a static/global string constant, use a C style string instead: ' - '"%schar %s[]".' % - (match.group(1), match.group(2))) - - # Check that we're not using RTTI outside of testing code. - if Search(r'\bdynamic_cast<', line) and not _IsTestFilename(filename): - error(filename, linenum, 'runtime/rtti', 5, - 'Do not use dynamic_cast<>. If you need to cast within a class ' - "hierarchy, use static_cast<> to upcast. Google doesn't support " - 'RTTI.') - - if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): - error(filename, linenum, 'runtime/init', 4, - 'You seem to be initializing a member variable with itself.') - - if file_extension == 'h': - # TODO(unknown): check that 1-arg constructors are explicit. - # How to tell it's a constructor? - # (handled in CheckForNonStandardConstructs for now) - # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS - # (level 1 error) - pass - - # Check if people are using the verboten C basic types. The only exception - # we regularly allow is "unsigned short port" for port. - if Search(r'\bshort port\b', line): - if not Search(r'\bunsigned short port\b', line): - error(filename, linenum, 'runtime/int', 4, - 'Use "unsigned short" for ports, not "short"') - else: - match = Search(r'\b(short|long(?! +double)|long long)\b', line) - if match: - error(filename, linenum, 'runtime/int', 4, - 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) - - # When snprintf is used, the second argument shouldn't be a literal. - match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) - if match and match.group(2) != '0': - # If 2nd arg is zero, snprintf is used to calculate size. - error(filename, linenum, 'runtime/printf', 3, - 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' - 'to snprintf.' % (match.group(1), match.group(2))) - - # Check if some verboten C functions are being used. - if Search(r'\bsprintf\b', line): - error(filename, linenum, 'runtime/printf', 5, - 'Never use sprintf. Use snprintf instead.') - match = Search(r'\b(strcpy|strcat)\b', line) - if match: - error(filename, linenum, 'runtime/printf', 4, - 'Almost always, snprintf is better than %s' % match.group(1)) - - if Search(r'\bsscanf\b', line): - error(filename, linenum, 'runtime/printf', 1, - 'sscanf can be ok, but is slow and can overflow buffers.') - - # Check if some verboten operator overloading is going on - # TODO(unknown): catch out-of-line unary operator&: - # class X {}; - # int operator&(const X& x) { return 42; } // unary operator& - # The trick is it's hard to tell apart from binary operator&: - # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& - if Search(r'\boperator\s*&\s*\(\s*\)', line): - error(filename, linenum, 'runtime/operator', 4, - 'Unary operator& is dangerous. Do not use it.') - - # Check for suspicious usage of "if" like - # } if (a == b) { - if Search(r'\}\s*if\s*\(', line): - error(filename, linenum, 'readability/braces', 4, - 'Did you mean "else if"? If not, start a new line for "if".') - - # Check for potential format string bugs like printf(foo). - # We constrain the pattern not to pick things like DocidForPrintf(foo). - # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) - # TODO(sugawarayu): Catch the following case. Need to change the calling - # convention of the whole function to process multiple line to handle it. - # printf( - # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); - printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') - if printf_args: - match = Match(r'([\w.\->()]+)$', printf_args) - if match and match.group(1) != '__VA_ARGS__': - function_name = re.search(r'\b((?:string)?printf)\s*\(', - line, re.I).group(1) - error(filename, linenum, 'runtime/printf', 4, - 'Potential format string bug. Do %s("%%s", %s) instead.' - % (function_name, match.group(1))) - - # Check for potential memset bugs like memset(buf, sizeof(buf), 0). - match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) - if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): - error(filename, linenum, 'runtime/memset', 4, - 'Did you mean "memset(%s, 0, %s)"?' - % (match.group(1), match.group(2))) - - if Search(r'\busing namespace\b', line): - error(filename, linenum, 'build/namespaces', 5, - 'Do not use namespace using-directives. ' - 'Use using-declarations instead.') - - # Detect variable-length arrays. - match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) - if (match and match.group(2) != 'return' and match.group(2) != 'delete' and - match.group(3).find(']') == -1): - # Split the size using space and arithmetic operators as delimiters. - # If any of the resulting tokens are not compile time constants then - # report the error. - tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3)) - is_const = True - skip_next = False - for tok in tokens: - if skip_next: - skip_next = False - continue - - if Search(r'sizeof\(.+\)', tok): continue - if Search(r'arraysize\(\w+\)', tok): continue - - tok = tok.lstrip('(') - tok = tok.rstrip(')') - if not tok: continue - if Match(r'\d+', tok): continue - if Match(r'0[xX][0-9a-fA-F]+', tok): continue - if Match(r'k[A-Z0-9]\w*', tok): continue - if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue - if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue - # A catch all for tricky sizeof cases, including 'sizeof expression', - # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' - # requires skipping the next token because we split on ' ' and '*'. - if tok.startswith('sizeof'): - skip_next = True - continue - is_const = False - break - if not is_const: - error(filename, linenum, 'runtime/arrays', 1, - 'Do not use variable-length arrays. Use an appropriately named ' - "('k' followed by CamelCase) compile-time constant for the size.") - - # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or - # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing - # in the class declaration. - match = Match( - (r'\s*' - r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))' - r'\(.*\);$'), - line) - if match and linenum + 1 < clean_lines.NumLines(): - next_line = clean_lines.elided[linenum + 1] - # We allow some, but not all, declarations of variables to be present - # in the statement that defines the class. The [\w\*,\s]* fragment of - # the regular expression below allows users to declare instances of - # the class or pointers to instances, but not less common types such - # as function pointers or arrays. It's a tradeoff between allowing - # reasonable code and avoiding trying to parse more C++ using regexps. - if not Search(r'^\s*}[\w\*,\s]*;', next_line): - error(filename, linenum, 'readability/constructors', 3, - match.group(1) + ' should be the last thing in the class') - - # Check for use of unnamed namespaces in header files. Registration - # macros are typically OK, so we allow use of "namespace {" on lines - # that end with backslashes. - if (file_extension == 'h' - and Search(r'\bnamespace\s*{', line) - and line[-1] != '\\'): - error(filename, linenum, 'build/namespaces', 4, - 'Do not use unnamed namespaces in header files. See ' - 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' - ' for more information.') - - -def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, - error): - """Checks for a C-style cast by looking for the pattern. - - This also handles sizeof(type) warnings, due to similarity of content. - - Args: - filename: The name of the current file. - linenum: The number of the line to check. - line: The line of code to check. - raw_line: The raw line of code to check, with comments. - cast_type: The string for the C++ cast to recommend. This is either - reinterpret_cast, static_cast, or const_cast, depending. - pattern: The regular expression used to find C-style casts. - error: The function to call with any errors found. - - Returns: - True if an error was emitted. - False otherwise. - """ - match = Search(pattern, line) - if not match: - return False - - # e.g., sizeof(int) - sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) - if sizeof_match: - error(filename, linenum, 'runtime/sizeof', 1, - 'Using sizeof(type). Use sizeof(varname) instead if possible') - return True - - # operator++(int) and operator--(int) - if (line[0:match.start(1) - 1].endswith(' operator++') or - line[0:match.start(1) - 1].endswith(' operator--')): - return False - - remainder = line[match.end(0):] - - # The close paren is for function pointers as arguments to a function. - # eg, void foo(void (*bar)(int)); - # The semicolon check is a more basic function check; also possibly a - # function pointer typedef. - # eg, void foo(int); or void foo(int) const; - # The equals check is for function pointer assignment. - # eg, void *(*foo)(int) = ... - # The > is for MockCallback<...> ... - # - # Right now, this will only catch cases where there's a single argument, and - # it's unnamed. It should probably be expanded to check for multiple - # arguments with some unnamed. - function_match = Match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)|>))', remainder) - if function_match: - if (not function_match.group(3) or - function_match.group(3) == ';' or - ('MockCallback<' not in raw_line and - '/*' not in raw_line)): - error(filename, linenum, 'readability/function', 3, - 'All parameters should be named in a function') - return True - - # At this point, all that should be left is actual casts. - error(filename, linenum, 'readability/casting', 4, - 'Using C-style cast. Use %s<%s>(...) instead' % - (cast_type, match.group(1))) - - return True - - -_HEADERS_CONTAINING_TEMPLATES = ( - ('<deque>', ('deque',)), - ('<functional>', ('unary_function', 'binary_function', - 'plus', 'minus', 'multiplies', 'divides', 'modulus', - 'negate', - 'equal_to', 'not_equal_to', 'greater', 'less', - 'greater_equal', 'less_equal', - 'logical_and', 'logical_or', 'logical_not', - 'unary_negate', 'not1', 'binary_negate', 'not2', - 'bind1st', 'bind2nd', - 'pointer_to_unary_function', - 'pointer_to_binary_function', - 'ptr_fun', - 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', - 'mem_fun_ref_t', - 'const_mem_fun_t', 'const_mem_fun1_t', - 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', - 'mem_fun_ref', - )), - ('<limits>', ('numeric_limits',)), - ('<list>', ('list',)), - ('<map>', ('map', 'multimap',)), - ('<memory>', ('allocator',)), - ('<queue>', ('queue', 'priority_queue',)), - ('<set>', ('set', 'multiset',)), - ('<stack>', ('stack',)), - ('<string>', ('char_traits', 'basic_string',)), - ('<utility>', ('pair',)), - ('<vector>', ('vector',)), - - # gcc extensions. - # Note: std::hash is their hash, ::hash is our hash - ('<hash_map>', ('hash_map', 'hash_multimap',)), - ('<hash_set>', ('hash_set', 'hash_multiset',)), - ('<slist>', ('slist',)), - ) - -_RE_PATTERN_STRING = re.compile(r'\bstring\b') - -_re_pattern_algorithm_header = [] -for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', - 'transform'): - # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or - # type::max(). - _re_pattern_algorithm_header.append( - (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), - _template, - '<algorithm>')) - -_re_pattern_templates = [] -for _header, _templates in _HEADERS_CONTAINING_TEMPLATES: - for _template in _templates: - _re_pattern_templates.append( - (re.compile(r'(\<|\b)' + _template + r'\s*\<'), - _template + '<>', - _header)) - - -def FilesBelongToSameModule(filename_cc, filename_h): - """Check if these two filenames belong to the same module. - - The concept of a 'module' here is a as follows: - foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the - same 'module' if they are in the same directory. - some/path/public/xyzzy and some/path/internal/xyzzy are also considered - to belong to the same module here. - - If the filename_cc contains a longer path than the filename_h, for example, - '/absolute/path/to/base/sysinfo.cc', and this file would include - 'base/sysinfo.h', this function also produces the prefix needed to open the - header. This is used by the caller of this function to more robustly open the - header file. We don't have access to the real include paths in this context, - so we need this guesswork here. - - Known bugs: tools/base/bar.cc and base/bar.h belong to the same module - according to this implementation. Because of this, this function gives - some false positives. This should be sufficiently rare in practice. - - Args: - filename_cc: is the path for the .cc file - filename_h: is the path for the header path - - Returns: - Tuple with a bool and a string: - bool: True if filename_cc and filename_h belong to the same module. - string: the additional prefix needed to open the header file. - """ - - if not filename_cc.endswith('.cc'): - return (False, '') - filename_cc = filename_cc[:-len('.cc')] - if filename_cc.endswith('_unittest'): - filename_cc = filename_cc[:-len('_unittest')] - elif filename_cc.endswith('_test'): - filename_cc = filename_cc[:-len('_test')] - filename_cc = filename_cc.replace('/public/', '/') - filename_cc = filename_cc.replace('/internal/', '/') - - if not filename_h.endswith('.h'): - return (False, '') - filename_h = filename_h[:-len('.h')] - if filename_h.endswith('-inl'): - filename_h = filename_h[:-len('-inl')] - filename_h = filename_h.replace('/public/', '/') - filename_h = filename_h.replace('/internal/', '/') - - files_belong_to_same_module = filename_cc.endswith(filename_h) - common_path = '' - if files_belong_to_same_module: - common_path = filename_cc[:-len(filename_h)] - return files_belong_to_same_module, common_path - - -def UpdateIncludeState(filename, include_state, io=codecs): - """Fill up the include_state with new includes found from the file. - - Args: - filename: the name of the header to read. - include_state: an _IncludeState instance in which the headers are inserted. - io: The io factory to use to read the file. Provided for testability. - - Returns: - True if a header was successfully added. False otherwise. - """ - headerfile = None - try: - headerfile = io.open(filename, 'r', 'utf8', 'replace') - except IOError: - return False - linenum = 0 - for line in headerfile: - linenum += 1 - clean_line = CleanseComments(line) - match = _RE_PATTERN_INCLUDE.search(clean_line) - if match: - include = match.group(2) - # The value formatting is cute, but not really used right now. - # What matters here is that the key is in include_state. - include_state.setdefault(include, '%s:%d' % (filename, linenum)) - return True - - -def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, - io=codecs): - """Reports for missing stl includes. - - This function will output warnings to make sure you are including the headers - necessary for the stl containers and functions that you use. We only give one - reason to include a header. For example, if you use both equal_to<> and - less<> in a .h file, only one (the latter in the file) of these will be - reported as a reason to include the <functional>. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - include_state: An _IncludeState instance. - error: The function to call with any errors found. - io: The IO factory to use to read the header file. Provided for unittest - injection. - """ - required = {} # A map of header name to linenumber and the template entity. - # Example of required: { '<functional>': (1219, 'less<>') } - - for linenum in xrange(clean_lines.NumLines()): - line = clean_lines.elided[linenum] - if not line or line[0] == '#': - continue - - # String is special -- it is a non-templatized type in STL. - matched = _RE_PATTERN_STRING.search(line) - if matched: - # Don't warn about strings in non-STL namespaces: - # (We check only the first match per line; good enough.) - prefix = line[:matched.start()] - if prefix.endswith('std::') or not prefix.endswith('::'): - required['<string>'] = (linenum, 'string') - - for pattern, template, header in _re_pattern_algorithm_header: - if pattern.search(line): - required[header] = (linenum, template) - - # The following function is just a speed up, no semantics are changed. - if not '<' in line: # Reduces the cpu time usage by skipping lines. - continue - - for pattern, template, header in _re_pattern_templates: - if pattern.search(line): - required[header] = (linenum, template) - - # The policy is that if you #include something in foo.h you don't need to - # include it again in foo.cc. Here, we will look at possible includes. - # Let's copy the include_state so it is only messed up within this function. - include_state = include_state.copy() - - # Did we find the header for this file (if any) and successfully load it? - header_found = False - - # Use the absolute path so that matching works properly. - abs_filename = FileInfo(filename).FullName() - - # For Emacs's flymake. - # If cpplint is invoked from Emacs's flymake, a temporary file is generated - # by flymake and that file name might end with '_flymake.cc'. In that case, - # restore original file name here so that the corresponding header file can be - # found. - # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h' - # instead of 'foo_flymake.h' - abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename) - - # include_state is modified during iteration, so we iterate over a copy of - # the keys. - header_keys = include_state.keys() - for header in header_keys: - (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) - fullpath = common_path + header - if same_module and UpdateIncludeState(fullpath, include_state, io): - header_found = True - - # If we can't find the header file for a .cc, assume it's because we don't - # know where to look. In that case we'll give up as we're not sure they - # didn't include it in the .h file. - # TODO(unknown): Do a better job of finding .h files so we are confident that - # not having the .h file means there isn't one. - if filename.endswith('.cc') and not header_found: - return - - # All the lines have been processed, report the errors found. - for required_header_unstripped in required: - template = required[required_header_unstripped][1] - if required_header_unstripped.strip('<>"') not in include_state: - error(filename, required[required_header_unstripped][0], - 'build/include_what_you_use', 4, - 'Add #include ' + required_header_unstripped + ' for ' + template) - - -_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') - - -def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): - """Check that make_pair's template arguments are deduced. - - G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are - specified explicitly, and such use isn't intended in any case. - - Args: - filename: The name of the current file. - clean_lines: A CleansedLines instance containing the file. - linenum: The number of the line to check. - error: The function to call with any errors found. - """ - raw = clean_lines.raw_lines - line = raw[linenum] - match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) - if match: - error(filename, linenum, 'build/explicit_make_pair', - 4, # 4 = high confidence - 'For C++11-compatibility, omit template arguments from make_pair' - ' OR use pair directly OR if appropriate, construct a pair directly') - - -def ProcessLine(filename, file_extension, clean_lines, line, - include_state, function_state, nesting_state, error, - extra_check_functions=[]): - """Processes a single line in the file. - - Args: - filename: Filename of the file that is being processed. - file_extension: The extension (dot not included) of the file. - clean_lines: An array of strings, each representing a line of the file, - with comments stripped. - line: Number of line being processed. - include_state: An _IncludeState instance in which the headers are inserted. - function_state: A _FunctionState instance which counts function lines, etc. - nesting_state: A _NestingState instance which maintains information about - the current stack of nested blocks being parsed. - error: A callable to which errors are reported, which takes 4 arguments: - filename, line number, error level, and message - extra_check_functions: An array of additional check functions that will be - run on each source line. Each function takes 4 - arguments: filename, clean_lines, line, error - """ - raw_lines = clean_lines.raw_lines - ParseNolintSuppressions(filename, raw_lines[line], line, error) - nesting_state.Update(filename, clean_lines, line, error) - if nesting_state.stack and nesting_state.stack[-1].inline_asm != _NO_ASM: - return - CheckForFunctionLengths(filename, clean_lines, line, function_state, error) - CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) - CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) - CheckLanguage(filename, clean_lines, line, file_extension, include_state, - error) - CheckForNonStandardConstructs(filename, clean_lines, line, - nesting_state, error) - CheckPosixThreading(filename, clean_lines, line, error) - CheckInvalidIncrement(filename, clean_lines, line, error) - CheckMakePairUsesDeduction(filename, clean_lines, line, error) - for check_fn in extra_check_functions: - check_fn(filename, clean_lines, line, error) - -def ProcessFileData(filename, file_extension, lines, error, - extra_check_functions=[]): - """Performs lint checks and reports any errors to the given error function. - - Args: - filename: Filename of the file that is being processed. - file_extension: The extension (dot not included) of the file. - lines: An array of strings, each representing a line of the file, with the - last element being empty if the file is terminated with a newline. - error: A callable to which errors are reported, which takes 4 arguments: - filename, line number, error level, and message - extra_check_functions: An array of additional check functions that will be - run on each source line. Each function takes 4 - arguments: filename, clean_lines, line, error - """ - lines = (['// marker so line numbers and indices both start at 1'] + lines + - ['// marker so line numbers end in a known way']) - - include_state = _IncludeState() - function_state = _FunctionState() - nesting_state = _NestingState() - - ResetNolintSuppressions() - - CheckForCopyright(filename, lines, error) - - if file_extension == 'h': - CheckForHeaderGuard(filename, lines, error) - - RemoveMultiLineComments(filename, lines, error) - clean_lines = CleansedLines(lines) - for line in xrange(clean_lines.NumLines()): - ProcessLine(filename, file_extension, clean_lines, line, - include_state, function_state, nesting_state, error, - extra_check_functions) - nesting_state.CheckClassFinished(filename, error) - - CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) - - # We check here rather than inside ProcessLine so that we see raw - # lines rather than "cleaned" lines. - CheckForUnicodeReplacementCharacters(filename, lines, error) - - CheckForNewlineAtEOF(filename, lines, error) - -def ProcessFile(filename, vlevel, extra_check_functions=[]): - """Does google-lint on a single file. - - Args: - filename: The name of the file to parse. - - vlevel: The level of errors to report. Every error of confidence - >= verbose_level will be reported. 0 is a good default. - - extra_check_functions: An array of additional check functions that will be - run on each source line. Each function takes 4 - arguments: filename, clean_lines, line, error - """ - - _SetVerboseLevel(vlevel) - - try: - # Support the UNIX convention of using "-" for stdin. Note that - # we are not opening the file with universal newline support - # (which codecs doesn't support anyway), so the resulting lines do - # contain trailing '\r' characters if we are reading a file that - # has CRLF endings. - # If after the split a trailing '\r' is present, it is removed - # below. If it is not expected to be present (i.e. os.linesep != - # '\r\n' as in Windows), a warning is issued below if this file - # is processed. - - if filename == '-': - lines = codecs.StreamReaderWriter(sys.stdin, - codecs.getreader('utf8'), - codecs.getwriter('utf8'), - 'replace').read().split('\n') - else: - lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n') - - carriage_return_found = False - # Remove trailing '\r'. - for linenum in range(len(lines)): - if lines[linenum].endswith('\r'): - lines[linenum] = lines[linenum].rstrip('\r') - carriage_return_found = True - - except IOError: - sys.stderr.write( - "Skipping input '%s': Can't open for reading\n" % filename) - return - - # Note, if no dot is found, this will give the entire filename as the ext. - file_extension = filename[filename.rfind('.') + 1:] - - # When reading from stdin, the extension is unknown, so no cpplint tests - # should rely on the extension. - if (filename != '-' and file_extension != 'cc' and file_extension != 'h' - and file_extension != 'cpp'): - sys.stderr.write('Ignoring %s; not a .cc or .h file\n' % filename) - else: - ProcessFileData(filename, file_extension, lines, Error, - extra_check_functions) - if carriage_return_found and os.linesep != '\r\n': - # Use 0 for linenum since outputting only one error for potentially - # several lines. - Error(filename, 0, 'whitespace/newline', 1, - 'One or more unexpected \\r (^M) found;' - 'better to use only a \\n') - - sys.stderr.write('Done processing %s\n' % filename) - - -def PrintUsage(message): - """Prints a brief usage string and exits, optionally with an error message. - - Args: - message: The optional error message. - """ - sys.stderr.write(_USAGE) - if message: - sys.exit('\nFATAL ERROR: ' + message) - else: - sys.exit(1) - - -def PrintCategories(): - """Prints a list of all the error-categories used by error messages. - - These are the categories used to filter messages via --filter. - """ - sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES)) - sys.exit(0) - - -def ParseArguments(args): - """Parses the command line arguments. - - This may set the output format and verbosity level as side-effects. - - Args: - args: The command line arguments: - - Returns: - The list of filenames to lint. - """ - try: - (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', - 'counting=', - 'filter=', - 'root=']) - except getopt.GetoptError: - PrintUsage('Invalid arguments.') - - verbosity = _VerboseLevel() - output_format = _OutputFormat() - filters = '' - counting_style = '' - - for (opt, val) in opts: - if opt == '--help': - PrintUsage(None) - elif opt == '--output': - if not val in ('emacs', 'vs7', 'eclipse'): - PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.') - output_format = val - elif opt == '--verbose': - verbosity = int(val) - elif opt == '--filter': - filters = val - if not filters: - PrintCategories() - elif opt == '--counting': - if val not in ('total', 'toplevel', 'detailed'): - PrintUsage('Valid counting options are total, toplevel, and detailed') - counting_style = val - elif opt == '--root': - global _root - _root = val - - if not filenames: - PrintUsage('No files were specified.') - - _SetOutputFormat(output_format) - _SetVerboseLevel(verbosity) - _SetFilters(filters) - _SetCountingStyle(counting_style) - - return filenames - - -def main(): - filenames = ParseArguments(sys.argv[1:]) - - # Change stderr to write with replacement characters so we don't die - # if we try to print something containing non-ASCII characters. - sys.stderr = codecs.StreamReaderWriter(sys.stderr, - codecs.getreader('utf8'), - codecs.getwriter('utf8'), - 'replace') - - _cpplint_state.ResetErrorCounts() - for filename in filenames: - ProcessFile(filename, _cpplint_state.verbose_level) - _cpplint_state.PrintErrorCounts() - - sys.exit(_cpplint_state.error_count > 0) - - -if __name__ == '__main__': - main() diff --git a/lib/sanitizer_common/scripts/gen_dynamic_list.py b/lib/sanitizer_common/scripts/gen_dynamic_list.py deleted file mode 100755 index 4a9c7af955480..0000000000000 --- a/lib/sanitizer_common/scripts/gen_dynamic_list.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -#===- lib/sanitizer_common/scripts/gen_dynamic_list.py ---------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# -# Generates the list of functions that should be exported from sanitizer -# runtimes. The output format is recognized by --dynamic-list linker option. -# Usage: -# gen_dynamic_list.py libclang_rt.*san*.a [ files ... ] -# -#===------------------------------------------------------------------------===# -from __future__ import print_function -import argparse -import os -import re -import subprocess -import sys -import platform - -new_delete = set([ - '_Znam', '_ZnamRKSt9nothrow_t', # operator new[](unsigned long) - '_Znwm', '_ZnwmRKSt9nothrow_t', # operator new(unsigned long) - '_Znaj', '_ZnajRKSt9nothrow_t', # operator new[](unsigned int) - '_Znwj', '_ZnwjRKSt9nothrow_t', # operator new(unsigned int) - # operator new(unsigned long, std::align_val_t) - '_ZnwmSt11align_val_t', '_ZnwmSt11align_val_tRKSt9nothrow_t', - # operator new(unsigned int, std::align_val_t) - '_ZnwjSt11align_val_t', '_ZnwjSt11align_val_tRKSt9nothrow_t', - # operator new[](unsigned long, std::align_val_t) - '_ZnamSt11align_val_t', '_ZnamSt11align_val_tRKSt9nothrow_t', - # operator new[](unsigned int, std::align_val_t) - '_ZnajSt11align_val_t', '_ZnajSt11align_val_tRKSt9nothrow_t', - '_ZdaPv', '_ZdaPvRKSt9nothrow_t', # operator delete[](void *) - '_ZdlPv', '_ZdlPvRKSt9nothrow_t', # operator delete(void *) - '_ZdaPvm', # operator delete[](void*, unsigned long) - '_ZdlPvm', # operator delete(void*, unsigned long) - '_ZdaPvj', # operator delete[](void*, unsigned int) - '_ZdlPvj', # operator delete(void*, unsigned int) - # operator delete(void*, std::align_val_t) - '_ZdlPvSt11align_val_t', '_ZdlPvSt11align_val_tRKSt9nothrow_t', - # operator delete[](void*, std::align_val_t) - '_ZdaPvSt11align_val_t', '_ZdaPvSt11align_val_tRKSt9nothrow_t', - # operator delete(void*, unsigned long, std::align_val_t) - '_ZdlPvmSt11align_val_t', - # operator delete[](void*, unsigned long, std::align_val_t) - '_ZdaPvmSt11align_val_t', - # operator delete(void*, unsigned int, std::align_val_t) - '_ZdlPvjSt11align_val_t', - # operator delete[](void*, unsigned int, std::align_val_t) - '_ZdaPvjSt11align_val_t', - ]) - -versioned_functions = set(['memcpy', 'pthread_attr_getaffinity_np', - 'pthread_cond_broadcast', - 'pthread_cond_destroy', 'pthread_cond_init', - 'pthread_cond_signal', 'pthread_cond_timedwait', - 'pthread_cond_wait', 'realpath', - 'sched_getaffinity']) - -def get_global_functions(library): - functions = [] - nm = os.environ.get('NM', 'nm') - nm_proc = subprocess.Popen([nm, library], stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - nm_out = nm_proc.communicate()[0].decode().split('\n') - if nm_proc.returncode != 0: - raise subprocess.CalledProcessError(nm_proc.returncode, nm) - func_symbols = ['T', 'W'] - # On PowerPC, nm prints function descriptors from .data section. - if platform.uname()[4] in ["powerpc", "ppc64"]: - func_symbols += ['D'] - for line in nm_out: - cols = line.split(' ') - if len(cols) == 3 and cols[1] in func_symbols : - functions.append(cols[2]) - return functions - -def main(argv): - parser = argparse.ArgumentParser() - parser.add_argument('--version-list', action='store_true') - parser.add_argument('--extra', default=[], action='append') - parser.add_argument('libraries', default=[], nargs='+') - parser.add_argument('-o', '--output', required=True) - args = parser.parse_args() - - result = [] - - all_functions = [] - for library in args.libraries: - all_functions.extend(get_global_functions(library)) - function_set = set(all_functions) - for func in all_functions: - # Export new/delete operators. - if func in new_delete: - result.append(func) - continue - # Export interceptors. - match = re.match('__interceptor_(.*)', func) - if match: - result.append(func) - # We have to avoid exporting the interceptors for versioned library - # functions due to gold internal error. - orig_name = match.group(1) - if orig_name in function_set and (args.version_list or orig_name not in versioned_functions): - result.append(orig_name) - continue - # Export sanitizer interface functions. - if re.match('__sanitizer_(.*)', func): - result.append(func) - - # Additional exported functions from files. - for fname in args.extra: - f = open(fname, 'r') - for line in f: - result.append(line.rstrip()) - # Print the resulting list in the format recognized by ld. - with open(args.output, 'w') as f: - print('{', file=f) - if args.version_list: - print('global:', file=f) - result.sort() - for sym in result: - print(u' %s;' % sym, file=f) - if args.version_list: - print('local:', file=f) - print(' *;', file=f) - print('};', file=f) - -if __name__ == '__main__': - main(sys.argv) diff --git a/lib/sanitizer_common/scripts/litlint.py b/lib/sanitizer_common/scripts/litlint.py deleted file mode 100755 index 81b89c2144381..0000000000000 --- a/lib/sanitizer_common/scripts/litlint.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# -# litlint -# -# Ensure RUN commands in lit tests are free of common errors. -# -# If any errors are detected, litlint returns a nonzero exit code. -# - -import optparse -import re -import sys - -# Compile regex once for all files -runRegex = re.compile(r'(?<!-o)(?<!%run) %t\s') - -def LintLine(s): - """ Validate a line - - Args: - s: str, the line to validate - - Returns: - Returns an error message and a 1-based column number if an error was - detected, otherwise (None, None). - """ - - # Check that RUN command can be executed with an emulator - m = runRegex.search(s) - if m: - start, end = m.span() - return ('missing %run before %t', start + 2) - - # No errors - return (None, None) - - -def LintFile(p): - """ Check that each RUN command can be executed with an emulator - - Args: - p: str, valid path to a file - - Returns: - The number of errors detected. - """ - errs = 0 - with open(p, 'r') as f: - for i, s in enumerate(f.readlines(), start=1): - msg, col = LintLine(s) - if msg != None: - errs += 1 - errorMsg = 'litlint: {}:{}:{}: error: {}.\n{}{}\n' - arrow = (col-1) * ' ' + '^' - sys.stderr.write(errorMsg.format(p, i, col, msg, s, arrow)) - return errs - - -if __name__ == "__main__": - # Parse args - parser = optparse.OptionParser() - parser.add_option('--filter') # ignored - (options, filenames) = parser.parse_args() - - # Lint each file - errs = 0 - for p in filenames: - errs += LintFile(p) - - # If errors, return nonzero - if errs > 0: - sys.exit(1) diff --git a/lib/sanitizer_common/scripts/litlint_test.py b/lib/sanitizer_common/scripts/litlint_test.py deleted file mode 100755 index 3ce482d704442..0000000000000 --- a/lib/sanitizer_common/scripts/litlint_test.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/python - -# Tests for litlint.py -# -# Usage: python litlint_test.py -# -# Returns nonzero if any test fails - -import litlint -import unittest - -class TestLintLine(unittest.TestCase): - def test_missing_run(self): - f = litlint.LintLine - self.assertEqual(f(' %t '), ('missing %run before %t', 2)) - self.assertEqual(f(' %t\n'), ('missing %run before %t', 2)) - self.assertEqual(f(' %t.so '), (None, None)) - self.assertEqual(f(' %t.o '), (None, None)) - self.assertEqual(f('%run %t '), (None, None)) - self.assertEqual(f('-o %t '), (None, None)) - -if __name__ == '__main__': - unittest.main() diff --git a/lib/sanitizer_common/scripts/sancov.py b/lib/sanitizer_common/scripts/sancov.py deleted file mode 100755 index 35606396b78e6..0000000000000 --- a/lib/sanitizer_common/scripts/sancov.py +++ /dev/null @@ -1,251 +0,0 @@ -#!/usr/bin/env python -# Merge or print the coverage data collected by asan's coverage. -# Input files are sequences of 4-byte integers. -# We need to merge these integers into a set and then -# either print them (as hex) or dump them into another file. -import array -import bisect -import glob -import os.path -import struct -import subprocess -import sys - -prog_name = "" - -def Usage(): - sys.stderr.write( - "Usage: \n" + \ - " " + prog_name + " merge FILE [FILE...] > OUTPUT\n" \ - " " + prog_name + " print FILE [FILE...]\n" \ - " " + prog_name + " unpack FILE [FILE...]\n" \ - " " + prog_name + " rawunpack FILE [FILE ...]\n" \ - " " + prog_name + " missing BINARY < LIST_OF_PCS\n" \ - "\n") - exit(1) - -def CheckBits(bits): - if bits != 32 and bits != 64: - raise Exception("Wrong bitness: %d" % bits) - -def TypeCodeForBits(bits): - CheckBits(bits) - return 'L' if bits == 64 else 'I' - -def TypeCodeForStruct(bits): - CheckBits(bits) - return 'Q' if bits == 64 else 'I' - -kMagic32SecondHalf = 0xFFFFFF32; -kMagic64SecondHalf = 0xFFFFFF64; -kMagicFirstHalf = 0xC0BFFFFF; - -def MagicForBits(bits): - CheckBits(bits) - if sys.byteorder == 'little': - return [kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf, kMagicFirstHalf] - else: - return [kMagicFirstHalf, kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf] - -def ReadMagicAndReturnBitness(f, path): - magic_bytes = f.read(8) - magic_words = struct.unpack('II', magic_bytes); - bits = 0 - idx = 1 if sys.byteorder == 'little' else 0 - if magic_words[idx] == kMagicFirstHalf: - if magic_words[1-idx] == kMagic64SecondHalf: - bits = 64 - elif magic_words[1-idx] == kMagic32SecondHalf: - bits = 32 - if bits == 0: - raise Exception('Bad magic word in %s' % path) - return bits - -def ReadOneFile(path): - with open(path, mode="rb") as f: - f.seek(0, 2) - size = f.tell() - f.seek(0, 0) - if size < 8: - raise Exception('File %s is short (< 8 bytes)' % path) - bits = ReadMagicAndReturnBitness(f, path) - size -= 8 - w = size * 8 // bits - s = struct.unpack_from(TypeCodeForStruct(bits) * (w), f.read(size)) - sys.stderr.write( - "%s: read %d %d-bit PCs from %s\n" % (prog_name, w, bits, path)) - return s - -def Merge(files): - s = set() - for f in files: - s = s.union(set(ReadOneFile(f))) - sys.stderr.write( - "%s: %d files merged; %d PCs total\n" % (prog_name, len(files), len(s)) - ) - return sorted(s) - -def PrintFiles(files): - if len(files) > 1: - s = Merge(files) - else: # If there is just on file, print the PCs in order. - s = ReadOneFile(files[0]) - sys.stderr.write("%s: 1 file merged; %d PCs total\n" % (prog_name, len(s))) - for i in s: - print("0x%x" % i) - -def MergeAndPrint(files): - if sys.stdout.isatty(): - Usage() - s = Merge(files) - bits = 32 - if max(s) > 0xFFFFFFFF: - bits = 64 - stdout_buf = getattr(sys.stdout, 'buffer', sys.stdout) - array.array('I', MagicForBits(bits)).tofile(stdout_buf) - a = struct.pack(TypeCodeForStruct(bits) * len(s), *s) - stdout_buf.write(a) - - -def UnpackOneFile(path): - with open(path, mode="rb") as f: - sys.stderr.write("%s: unpacking %s\n" % (prog_name, path)) - while True: - header = f.read(12) - if not header: return - if len(header) < 12: - break - pid, module_length, blob_size = struct.unpack('iII', header) - module = f.read(module_length).decode('utf-8') - blob = f.read(blob_size) - assert(len(module) == module_length) - assert(len(blob) == blob_size) - extracted_file = "%s.%d.sancov" % (module, pid) - sys.stderr.write("%s: extracting %s\n" % (prog_name, extracted_file)) - # The packed file may contain multiple blobs for the same pid/module - # pair. Append to the end of the file instead of overwriting. - with open(extracted_file, 'ab') as f2: - f2.write(blob) - # fail - raise Exception('Error reading file %s' % path) - - -def Unpack(files): - for f in files: - UnpackOneFile(f) - -def UnpackOneRawFile(path, map_path): - mem_map = [] - with open(map_path, mode="rt") as f_map: - sys.stderr.write("%s: reading map %s\n" % (prog_name, map_path)) - bits = int(f_map.readline()) - if bits != 32 and bits != 64: - raise Exception('Wrong bits size in the map') - for line in f_map: - parts = line.rstrip().split() - mem_map.append((int(parts[0], 16), - int(parts[1], 16), - int(parts[2], 16), - ' '.join(parts[3:]))) - mem_map.sort(key=lambda m : m[0]) - mem_map_keys = [m[0] for m in mem_map] - - with open(path, mode="rb") as f: - sys.stderr.write("%s: unpacking %s\n" % (prog_name, path)) - - f.seek(0, 2) - size = f.tell() - f.seek(0, 0) - pcs = struct.unpack_from(TypeCodeForStruct(bits) * (size * 8 // bits), f.read(size)) - mem_map_pcs = [[] for i in range(0, len(mem_map))] - - for pc in pcs: - if pc == 0: continue - map_idx = bisect.bisect(mem_map_keys, pc) - 1 - (start, end, base, module_path) = mem_map[map_idx] - assert pc >= start - if pc >= end: - sys.stderr.write("warning: %s: pc %x outside of any known mapping\n" % (prog_name, pc)) - continue - mem_map_pcs[map_idx].append(pc - base) - - for ((start, end, base, module_path), pc_list) in zip(mem_map, mem_map_pcs): - if len(pc_list) == 0: continue - assert path.endswith('.sancov.raw') - dst_path = module_path + '.' + os.path.basename(path)[:-4] - sys.stderr.write("%s: writing %d PCs to %s\n" % (prog_name, len(pc_list), dst_path)) - sorted_pc_list = sorted(pc_list) - pc_buffer = struct.pack(TypeCodeForStruct(bits) * len(pc_list), *sorted_pc_list) - with open(dst_path, 'ab+') as f2: - array.array('I', MagicForBits(bits)).tofile(f2) - f2.seek(0, 2) - f2.write(pc_buffer) - -def RawUnpack(files): - for f in files: - if not f.endswith('.sancov.raw'): - raise Exception('Unexpected raw file name %s' % f) - f_map = f[:-3] + 'map' - UnpackOneRawFile(f, f_map) - -def GetInstrumentedPCs(binary): - # This looks scary, but all it does is extract all offsets where we call: - # - __sanitizer_cov() or __sanitizer_cov_with_check(), - # - with call or callq, - # - directly or via PLT. - cmd = "objdump -d %s | " \ - "grep '^\s\+[0-9a-f]\+:.*\scall\(q\|\)\s\+[0-9a-f]\+ <__sanitizer_cov\(_with_check\|\|_trace_pc_guard\)\(@plt\|\)>' | " \ - "grep '^\s\+[0-9a-f]\+' -o" % binary - proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - shell=True) - proc.stdin.close() - # The PCs we get from objdump are off by 4 bytes, as they point to the - # beginning of the callq instruction. Empirically this is true on x86 and - # x86_64. - return set(int(line.strip(), 16) + 4 for line in proc.stdout) - -def PrintMissing(binary): - if not os.path.isfile(binary): - raise Exception('File not found: %s' % binary) - instrumented = GetInstrumentedPCs(binary) - sys.stderr.write("%s: found %d instrumented PCs in %s\n" % (prog_name, - len(instrumented), - binary)) - covered = set(int(line, 16) for line in sys.stdin) - sys.stderr.write("%s: read %d PCs from stdin\n" % (prog_name, len(covered))) - missing = instrumented - covered - sys.stderr.write("%s: %d PCs missing from coverage\n" % (prog_name, len(missing))) - if (len(missing) > len(instrumented) - len(covered)): - sys.stderr.write( - "%s: WARNING: stdin contains PCs not found in binary\n" % prog_name - ) - for pc in sorted(missing): - print("0x%x" % pc) - -if __name__ == '__main__': - prog_name = sys.argv[0] - if len(sys.argv) <= 2: - Usage(); - - if sys.argv[1] == "missing": - if len(sys.argv) != 3: - Usage() - PrintMissing(sys.argv[2]) - exit(0) - - file_list = [] - for f in sys.argv[2:]: - file_list += glob.glob(f) - if not file_list: - Usage() - - if sys.argv[1] == "print": - PrintFiles(file_list) - elif sys.argv[1] == "merge": - MergeAndPrint(file_list) - elif sys.argv[1] == "unpack": - Unpack(file_list) - elif sys.argv[1] == "rawunpack": - RawUnpack(file_list) - else: - Usage() diff --git a/lib/sanitizer_common/tests/CMakeLists.txt b/lib/sanitizer_common/tests/CMakeLists.txt deleted file mode 100644 index 21ffe2528c25e..0000000000000 --- a/lib/sanitizer_common/tests/CMakeLists.txt +++ /dev/null @@ -1,218 +0,0 @@ -include(CompilerRTCompile) - -clang_compiler_add_cxx_check() - -# FIXME: use SANITIZER_COMMON_SUPPORTED_ARCH here -filter_available_targets(SANITIZER_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el) -if(APPLE) - darwin_filter_host_archs(SANITIZER_UNITTEST_SUPPORTED_ARCH SANITIZER_UNITTEST_SUPPORTED_ARCH) -endif() - -set(SANITIZER_UNITTESTS - sanitizer_allocator_test.cc - sanitizer_atomic_test.cc - sanitizer_bitvector_test.cc - sanitizer_bvgraph_test.cc - sanitizer_common_test.cc - sanitizer_deadlock_detector_test.cc - sanitizer_flags_test.cc - sanitizer_format_interceptor_test.cc - sanitizer_ioctl_test.cc - sanitizer_libc_test.cc - sanitizer_linux_test.cc - sanitizer_list_test.cc - sanitizer_mutex_test.cc - sanitizer_nolibc_test.cc - sanitizer_posix_test.cc - sanitizer_printf_test.cc - sanitizer_procmaps_test.cc - sanitizer_ring_buffer_test.cc - sanitizer_quarantine_test.cc - sanitizer_stackdepot_test.cc - sanitizer_stacktrace_printer_test.cc - sanitizer_stacktrace_test.cc - sanitizer_stoptheworld_test.cc - sanitizer_suppressions_test.cc - sanitizer_symbolizer_test.cc - sanitizer_test_main.cc - sanitizer_thread_registry_test.cc - sanitizer_type_traits_test.cc - sanitizer_vector_test.cc) - -set(SANITIZER_TEST_HEADERS - sanitizer_pthread_wrappers.h - sanitizer_test_config.h - sanitizer_test_utils.h) -foreach(header ${SANITIZER_IMPL_HEADERS}) - list(APPEND SANITIZER_TEST_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../${header}) -endforeach() - -set(SANITIZER_TEST_CFLAGS_COMMON - ${COMPILER_RT_UNITTEST_CFLAGS} - ${COMPILER_RT_GTEST_CFLAGS} - -I${COMPILER_RT_SOURCE_DIR}/include - -I${COMPILER_RT_SOURCE_DIR}/lib - -I${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common - -fno-rtti - -O2 - -Werror=sign-compare - -Wno-non-virtual-dtor - -Wno-gnu-zero-variadic-macro-arguments) - -# -gline-tables-only must be enough for these tests, so use it if possible. -if(COMPILER_RT_TEST_COMPILER_ID MATCHES "Clang") - list(APPEND SANITIZER_TEST_CFLAGS_COMMON -gline-tables-only) -else() - list(APPEND SANITIZER_TEST_CFLAGS_COMMON -g) -endif() -if(MSVC) - list(APPEND SANITIZER_TEST_CFLAGS_COMMON -gcodeview) -endif() -list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON -g) - -if(NOT MSVC) - list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON --driver-mode=g++) -endif() - -if(ANDROID) - list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON -pie) -endif() - -if(APPLE) - list(APPEND SANITIZER_TEST_CFLAGS_COMMON ${DARWIN_osx_CFLAGS}) - list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON ${DARWIN_osx_LINK_FLAGS}) - - add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) - list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON ${WEAK_SYMBOL_LINK_FLAGS}) -endif() - -# MSVC linker is allocating 1M for the stack by default, which is not -# enough for the unittests. Some unittests require more than 2M. -# The default stack size for clang is 8M. -if(MSVC) - list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON -Wl,/STACK:0xC00000) -endif() - -set(SANITIZER_TEST_LINK_LIBS) -append_list_if(COMPILER_RT_HAS_LIBLOG log SANITIZER_TEST_LINK_LIBS) -# NDK r10 requires -latomic almost always. -append_list_if(ANDROID atomic SANITIZER_TEST_LINK_LIBS) - -append_list_if(COMPILER_RT_HAS_LIBDL -ldl SANITIZER_TEST_LINK_FLAGS_COMMON) -append_list_if(COMPILER_RT_HAS_LIBRT -lrt SANITIZER_TEST_LINK_FLAGS_COMMON) -append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread SANITIZER_TEST_LINK_FLAGS_COMMON) -# x86_64 FreeBSD 9.2 additionally requires libc++ to build the tests. Also, -# 'libm' shall be specified explicitly to build i386 tests. -if(CMAKE_SYSTEM MATCHES "FreeBSD-9.2-RELEASE") - list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON "-lc++ -lm") -endif() - -include_directories(..) -include_directories(../..) - -# Adds static library which contains sanitizer_common object file -# (universal binary on Mac and arch-specific object files on Linux). -macro(add_sanitizer_common_lib library) - add_library(${library} STATIC ${ARGN}) - set_target_properties(${library} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - FOLDER "Compiler-RT Runtime tests") -endmacro() - -function(get_sanitizer_common_lib_for_arch arch lib) - if(APPLE) - set(tgt_name "RTSanitizerCommon.test.osx") - else() - set(tgt_name "RTSanitizerCommon.test.${arch}") - endif() - set(${lib} "${tgt_name}" PARENT_SCOPE) -endfunction() - -# Sanitizer_common unit tests testsuite. -add_custom_target(SanitizerUnitTests) -set_target_properties(SanitizerUnitTests PROPERTIES FOLDER "Compiler-RT Tests") - -# Adds sanitizer tests for architecture. -macro(add_sanitizer_tests_for_arch arch) - set(extra_flags) - if( CMAKE_SIZEOF_VOID_P EQUAL 4 ) - list(APPEND extra_flags "-D_LARGEFILE_SOURCE") - list(APPEND extra_flags "-D_FILE_OFFSET_BITS=64") - endif() - get_sanitizer_common_lib_for_arch(${arch} SANITIZER_COMMON_LIB) - - set(SANITIZER_TEST_OBJECTS) - generate_compiler_rt_tests(SANITIZER_TEST_OBJECTS SanitizerUnitTests - "Sanitizer-${arch}-Test" ${arch} - RUNTIME "${SANITIZER_COMMON_LIB}" - SOURCES ${SANITIZER_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} - COMPILE_DEPS ${SANITIZER_TEST_HEADERS} - DEPS gtest - CFLAGS ${SANITIZER_TEST_CFLAGS_COMMON} ${extra_flags} - LINK_FLAGS ${SANITIZER_TEST_LINK_FLAGS_COMMON} ${extra_flags}) - - if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND "${arch}" STREQUAL "x86_64") - # Test that the libc-independent part of sanitizer_common is indeed - # independent of libc, by linking this binary without libc (here) and - # executing it (unit test in sanitizer_nolibc_test.cc). - clang_compile(sanitizer_nolibc_test_main.${arch}.o - sanitizer_nolibc_test_main.cc - CFLAGS ${SANITIZER_TEST_CFLAGS_COMMON} ${TARGET_FLAGS} - DEPS ${SANITIZER_TEST_COMPILE_DEPS}) - add_compiler_rt_test(SanitizerUnitTests "Sanitizer-${arch}-Test-Nolibc" ${arch} - OBJECTS sanitizer_nolibc_test_main.${arch}.o - -Wl,-whole-archive - libRTSanitizerCommon.test.nolibc.${arch}.a - -Wl,-no-whole-archive - DEPS sanitizer_nolibc_test_main.${arch}.o - RTSanitizerCommon.test.nolibc.${arch} - LINK_FLAGS -nostdlib ${TARGET_FLAGS}) - endif() -endmacro() - -if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID) - # We use just-built clang to build sanitizer_common unittests, so we must - # be sure that produced binaries would work. - if(APPLE) - add_sanitizer_common_lib("RTSanitizerCommon.test.osx" - $<TARGET_OBJECTS:RTSanitizerCommon.osx> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.osx> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.osx>) - else() - if(CAN_TARGET_x86_64) - add_sanitizer_common_lib("RTSanitizerCommon.test.nolibc.x86_64" - $<TARGET_OBJECTS:RTSanitizerCommon.x86_64> - $<TARGET_OBJECTS:RTSanitizerCommonNoLibc.x86_64>) - endif() - foreach(arch ${SANITIZER_UNITTEST_SUPPORTED_ARCH}) - add_sanitizer_common_lib("RTSanitizerCommon.test.${arch}" - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>) - endforeach() - endif() - foreach(arch ${SANITIZER_UNITTEST_SUPPORTED_ARCH}) - add_sanitizer_tests_for_arch(${arch}) - endforeach() -endif() - -if(ANDROID) - foreach(arch ${SANITIZER_COMMON_SUPPORTED_ARCH}) - add_executable(SanitizerTest - ${SANITIZER_UNITTESTS} - ${COMPILER_RT_GTEST_SOURCE} - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>) - set_target_compile_flags(SanitizerTest - ${SANITIZER_COMMON_CFLAGS} - ${SANITIZER_TEST_CFLAGS_COMMON}) - # Setup correct output directory and link flags. - set_target_properties(SanitizerTest PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_target_link_flags(SanitizerTest ${SANITIZER_TEST_LINK_FLAGS_COMMON}) - target_link_libraries(SanitizerTest ${SANITIZER_TEST_LINK_LIBS}) - # Add unit test to test suite. - add_dependencies(SanitizerUnitTests SanitizerTest) - endforeach() -endif() diff --git a/lib/sanitizer_common/tests/malloc_stress_transfer_test.cc b/lib/sanitizer_common/tests/malloc_stress_transfer_test.cc deleted file mode 100644 index 3e03c4bddfd75..0000000000000 --- a/lib/sanitizer_common/tests/malloc_stress_transfer_test.cc +++ /dev/null @@ -1,37 +0,0 @@ -#include <thread> -#include <iostream> - -const size_t kAllocSize = 16; -const size_t kInitialNumAllocs = 1 << 10; -const size_t kPeriodicNumAllocs = 1 << 10; -const size_t kNumIterations = 1 << 7; -const size_t kNumThreads = 16; - -void Thread() { - // int sp; - // std::cerr << "Thread starting, sp = " << &sp << std::endl; - char *InitialAllocations[kInitialNumAllocs]; - char *PeriodicaAllocations[kPeriodicNumAllocs]; - for (auto &p : InitialAllocations) p = new char[kAllocSize]; - for (size_t i = 0; i < kNumIterations; i++) { - for (size_t j = 0; j < kPeriodicNumAllocs; j++) { - for (auto &p : PeriodicaAllocations) { - p = new char[kAllocSize]; - *p = 0; - } - for (auto p : PeriodicaAllocations) delete [] p; - } - } - for (auto p : InitialAllocations) delete [] p; -} - -int main() { -// Thread(); -// return 0; - std::thread *Threads[kNumThreads]; - for (auto &T : Threads) T = new std::thread(&Thread); - for (auto T : Threads) { - T->join(); - delete T; - } -} diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc deleted file mode 100644 index 3123a1d5abf44..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc +++ /dev/null @@ -1,1430 +0,0 @@ -//===-- sanitizer_allocator_test.cc ---------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// Tests for sanitizer_allocator.h. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_allocator.h" -#include "sanitizer_common/sanitizer_allocator_internal.h" -#include "sanitizer_common/sanitizer_common.h" - -#include "sanitizer_test_utils.h" -#include "sanitizer_pthread_wrappers.h" - -#include "gtest/gtest.h" - -#include <stdio.h> -#include <stdlib.h> -#include <algorithm> -#include <vector> -#include <random> -#include <set> - -using namespace __sanitizer; - -// Too slow for debug build -#if !SANITIZER_DEBUG - -#if SANITIZER_CAN_USE_ALLOCATOR64 -#if SANITIZER_WINDOWS -// On Windows 64-bit there is no easy way to find a large enough fixed address -// space that is always available. Thus, a dynamically allocated address space -// is used instead (i.e. ~(uptr)0). -static const uptr kAllocatorSpace = ~(uptr)0; -static const uptr kAllocatorSize = 0x8000000000ULL; // 500G -static const u64 kAddressSpaceSize = 1ULL << 47; -typedef DefaultSizeClassMap SizeClassMap; -#elif SANITIZER_ANDROID && defined(__aarch64__) -static const uptr kAllocatorSpace = 0x3000000000ULL; -static const uptr kAllocatorSize = 0x2000000000ULL; -static const u64 kAddressSpaceSize = 1ULL << 39; -typedef VeryCompactSizeClassMap SizeClassMap; -#else -static const uptr kAllocatorSpace = 0x700000000000ULL; -static const uptr kAllocatorSize = 0x010000000000ULL; // 1T. -static const u64 kAddressSpaceSize = 1ULL << 47; -typedef DefaultSizeClassMap SizeClassMap; -#endif - -template <typename AddressSpaceViewTy> -struct AP64 { // Allocator Params. Short name for shorter demangled names.. - static const uptr kSpaceBeg = kAllocatorSpace; - static const uptr kSpaceSize = kAllocatorSize; - static const uptr kMetadataSize = 16; - typedef ::SizeClassMap SizeClassMap; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - using AddressSpaceView = AddressSpaceViewTy; -}; - -template <typename AddressSpaceViewTy> -struct AP64Dyn { - static const uptr kSpaceBeg = ~(uptr)0; - static const uptr kSpaceSize = kAllocatorSize; - static const uptr kMetadataSize = 16; - typedef ::SizeClassMap SizeClassMap; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - using AddressSpaceView = AddressSpaceViewTy; -}; - -template <typename AddressSpaceViewTy> -struct AP64Compact { - static const uptr kSpaceBeg = ~(uptr)0; - static const uptr kSpaceSize = kAllocatorSize; - static const uptr kMetadataSize = 16; - typedef CompactSizeClassMap SizeClassMap; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - using AddressSpaceView = AddressSpaceViewTy; -}; - -template <typename AddressSpaceViewTy> -struct AP64VeryCompact { - static const uptr kSpaceBeg = ~(uptr)0; - static const uptr kSpaceSize = 1ULL << 37; - static const uptr kMetadataSize = 16; - typedef VeryCompactSizeClassMap SizeClassMap; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - using AddressSpaceView = AddressSpaceViewTy; -}; - -template <typename AddressSpaceViewTy> -struct AP64Dense { - static const uptr kSpaceBeg = kAllocatorSpace; - static const uptr kSpaceSize = kAllocatorSize; - static const uptr kMetadataSize = 16; - typedef DenseSizeClassMap SizeClassMap; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - using AddressSpaceView = AddressSpaceViewTy; -}; - -template <typename AddressSpaceView> -using Allocator64ASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; -using Allocator64 = Allocator64ASVT<LocalAddressSpaceView>; - -template <typename AddressSpaceView> -using Allocator64DynamicASVT = SizeClassAllocator64<AP64Dyn<AddressSpaceView>>; -using Allocator64Dynamic = Allocator64DynamicASVT<LocalAddressSpaceView>; - -template <typename AddressSpaceView> -using Allocator64CompactASVT = - SizeClassAllocator64<AP64Compact<AddressSpaceView>>; -using Allocator64Compact = Allocator64CompactASVT<LocalAddressSpaceView>; - -template <typename AddressSpaceView> -using Allocator64VeryCompactASVT = - SizeClassAllocator64<AP64VeryCompact<AddressSpaceView>>; -using Allocator64VeryCompact = - Allocator64VeryCompactASVT<LocalAddressSpaceView>; - -template <typename AddressSpaceView> -using Allocator64DenseASVT = SizeClassAllocator64<AP64Dense<AddressSpaceView>>; -using Allocator64Dense = Allocator64DenseASVT<LocalAddressSpaceView>; - -#elif defined(__mips64) -static const u64 kAddressSpaceSize = 1ULL << 40; -#elif defined(__aarch64__) -static const u64 kAddressSpaceSize = 1ULL << 39; -#elif defined(__s390x__) -static const u64 kAddressSpaceSize = 1ULL << 53; -#elif defined(__s390__) -static const u64 kAddressSpaceSize = 1ULL << 31; -#else -static const u64 kAddressSpaceSize = 1ULL << 32; -#endif - -static const uptr kRegionSizeLog = FIRST_32_SECOND_64(20, 24); -static const uptr kFlatByteMapSize = kAddressSpaceSize >> kRegionSizeLog; - -template <typename AddressSpaceViewTy> -struct AP32Compact { - static const uptr kSpaceBeg = 0; - static const u64 kSpaceSize = kAddressSpaceSize; - static const uptr kMetadataSize = 16; - typedef CompactSizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = ::kRegionSizeLog; - using AddressSpaceView = AddressSpaceViewTy; - using ByteMap = FlatByteMap<kFlatByteMapSize, AddressSpaceView>; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; -}; -template <typename AddressSpaceView> -using Allocator32CompactASVT = - SizeClassAllocator32<AP32Compact<AddressSpaceView>>; -using Allocator32Compact = Allocator32CompactASVT<LocalAddressSpaceView>; - -template <class SizeClassMap> -void TestSizeClassMap() { - typedef SizeClassMap SCMap; - SCMap::Print(); - SCMap::Validate(); -} - -TEST(SanitizerCommon, DefaultSizeClassMap) { - TestSizeClassMap<DefaultSizeClassMap>(); -} - -TEST(SanitizerCommon, CompactSizeClassMap) { - TestSizeClassMap<CompactSizeClassMap>(); -} - -TEST(SanitizerCommon, VeryCompactSizeClassMap) { - TestSizeClassMap<VeryCompactSizeClassMap>(); -} - -TEST(SanitizerCommon, InternalSizeClassMap) { - TestSizeClassMap<InternalSizeClassMap>(); -} - -TEST(SanitizerCommon, DenseSizeClassMap) { - TestSizeClassMap<VeryCompactSizeClassMap>(); -} - -template <class Allocator> -void TestSizeClassAllocator() { - Allocator *a = new Allocator; - a->Init(kReleaseToOSIntervalNever); - SizeClassAllocatorLocalCache<Allocator> cache; - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - - static const uptr sizes[] = { - 1, 16, 30, 40, 100, 1000, 10000, - 50000, 60000, 100000, 120000, 300000, 500000, 1000000, 2000000 - }; - - std::vector<void *> allocated; - - uptr last_total_allocated = 0; - for (int i = 0; i < 3; i++) { - // Allocate a bunch of chunks. - for (uptr s = 0; s < ARRAY_SIZE(sizes); s++) { - uptr size = sizes[s]; - if (!a->CanAllocate(size, 1)) continue; - // printf("s = %ld\n", size); - uptr n_iter = std::max((uptr)6, 4000000 / size); - // fprintf(stderr, "size: %ld iter: %ld\n", size, n_iter); - for (uptr i = 0; i < n_iter; i++) { - uptr class_id0 = Allocator::SizeClassMapT::ClassID(size); - char *x = (char*)cache.Allocate(a, class_id0); - x[0] = 0; - x[size - 1] = 0; - x[size / 2] = 0; - allocated.push_back(x); - CHECK_EQ(x, a->GetBlockBegin(x)); - CHECK_EQ(x, a->GetBlockBegin(x + size - 1)); - CHECK(a->PointerIsMine(x)); - CHECK(a->PointerIsMine(x + size - 1)); - CHECK(a->PointerIsMine(x + size / 2)); - CHECK_GE(a->GetActuallyAllocatedSize(x), size); - uptr class_id = a->GetSizeClass(x); - CHECK_EQ(class_id, Allocator::SizeClassMapT::ClassID(size)); - uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x)); - metadata[0] = reinterpret_cast<uptr>(x) + 1; - metadata[1] = 0xABCD; - } - } - // Deallocate all. - for (uptr i = 0; i < allocated.size(); i++) { - void *x = allocated[i]; - uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x)); - CHECK_EQ(metadata[0], reinterpret_cast<uptr>(x) + 1); - CHECK_EQ(metadata[1], 0xABCD); - cache.Deallocate(a, a->GetSizeClass(x), x); - } - allocated.clear(); - uptr total_allocated = a->TotalMemoryUsed(); - if (last_total_allocated == 0) - last_total_allocated = total_allocated; - CHECK_EQ(last_total_allocated, total_allocated); - } - - // Check that GetBlockBegin never crashes. - for (uptr x = 0, step = kAddressSpaceSize / 100000; - x < kAddressSpaceSize - step; x += step) - if (a->PointerIsMine(reinterpret_cast<void *>(x))) - Ident(a->GetBlockBegin(reinterpret_cast<void *>(x))); - - a->TestOnlyUnmap(); - delete a; -} - -#if SANITIZER_CAN_USE_ALLOCATOR64 -// These tests can fail on Windows if memory is somewhat full and lit happens -// to run them all at the same time. FIXME: Make them not flaky and reenable. -#if !SANITIZER_WINDOWS -TEST(SanitizerCommon, SizeClassAllocator64) { - TestSizeClassAllocator<Allocator64>(); -} - -TEST(SanitizerCommon, SizeClassAllocator64Dynamic) { - TestSizeClassAllocator<Allocator64Dynamic>(); -} - -#if !SANITIZER_ANDROID -//FIXME(kostyak): find values so that those work on Android as well. -TEST(SanitizerCommon, SizeClassAllocator64Compact) { - TestSizeClassAllocator<Allocator64Compact>(); -} - -TEST(SanitizerCommon, SizeClassAllocator64Dense) { - TestSizeClassAllocator<Allocator64Dense>(); -} -#endif - -TEST(SanitizerCommon, SizeClassAllocator64VeryCompact) { - TestSizeClassAllocator<Allocator64VeryCompact>(); -} -#endif -#endif - -TEST(SanitizerCommon, SizeClassAllocator32Compact) { - TestSizeClassAllocator<Allocator32Compact>(); -} - -template <typename AddressSpaceViewTy> -struct AP32SeparateBatches { - static const uptr kSpaceBeg = 0; - static const u64 kSpaceSize = kAddressSpaceSize; - static const uptr kMetadataSize = 16; - typedef DefaultSizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = ::kRegionSizeLog; - using AddressSpaceView = AddressSpaceViewTy; - using ByteMap = FlatByteMap<kFlatByteMapSize, AddressSpaceView>; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = - SizeClassAllocator32FlagMasks::kUseSeparateSizeClassForBatch; -}; -template <typename AddressSpaceView> -using Allocator32SeparateBatchesASVT = - SizeClassAllocator32<AP32SeparateBatches<AddressSpaceView>>; -using Allocator32SeparateBatches = - Allocator32SeparateBatchesASVT<LocalAddressSpaceView>; - -TEST(SanitizerCommon, SizeClassAllocator32SeparateBatches) { - TestSizeClassAllocator<Allocator32SeparateBatches>(); -} - -template <class Allocator> -void SizeClassAllocatorMetadataStress() { - Allocator *a = new Allocator; - a->Init(kReleaseToOSIntervalNever); - SizeClassAllocatorLocalCache<Allocator> cache; - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - - const uptr kNumAllocs = 1 << 13; - void *allocated[kNumAllocs]; - void *meta[kNumAllocs]; - for (uptr i = 0; i < kNumAllocs; i++) { - void *x = cache.Allocate(a, 1 + i % (Allocator::kNumClasses - 1)); - allocated[i] = x; - meta[i] = a->GetMetaData(x); - } - // Get Metadata kNumAllocs^2 times. - for (uptr i = 0; i < kNumAllocs * kNumAllocs; i++) { - uptr idx = i % kNumAllocs; - void *m = a->GetMetaData(allocated[idx]); - EXPECT_EQ(m, meta[idx]); - } - for (uptr i = 0; i < kNumAllocs; i++) { - cache.Deallocate(a, 1 + i % (Allocator::kNumClasses - 1), allocated[i]); - } - - a->TestOnlyUnmap(); - delete a; -} - -#if SANITIZER_CAN_USE_ALLOCATOR64 -// These tests can fail on Windows if memory is somewhat full and lit happens -// to run them all at the same time. FIXME: Make them not flaky and reenable. -#if !SANITIZER_WINDOWS -TEST(SanitizerCommon, SizeClassAllocator64MetadataStress) { - SizeClassAllocatorMetadataStress<Allocator64>(); -} - -TEST(SanitizerCommon, SizeClassAllocator64DynamicMetadataStress) { - SizeClassAllocatorMetadataStress<Allocator64Dynamic>(); -} - -#if !SANITIZER_ANDROID -TEST(SanitizerCommon, SizeClassAllocator64CompactMetadataStress) { - SizeClassAllocatorMetadataStress<Allocator64Compact>(); -} -#endif - -#endif -#endif // SANITIZER_CAN_USE_ALLOCATOR64 -TEST(SanitizerCommon, SizeClassAllocator32CompactMetadataStress) { - SizeClassAllocatorMetadataStress<Allocator32Compact>(); -} - -template <class Allocator> -void SizeClassAllocatorGetBlockBeginStress(u64 TotalSize) { - Allocator *a = new Allocator; - a->Init(kReleaseToOSIntervalNever); - SizeClassAllocatorLocalCache<Allocator> cache; - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - - uptr max_size_class = Allocator::SizeClassMapT::kLargestClassID; - uptr size = Allocator::SizeClassMapT::Size(max_size_class); - // Make sure we correctly compute GetBlockBegin() w/o overflow. - for (size_t i = 0; i <= TotalSize / size; i++) { - void *x = cache.Allocate(a, max_size_class); - void *beg = a->GetBlockBegin(x); - // if ((i & (i - 1)) == 0) - // fprintf(stderr, "[%zd] %p %p\n", i, x, beg); - EXPECT_EQ(x, beg); - } - - a->TestOnlyUnmap(); - delete a; -} - -#if SANITIZER_CAN_USE_ALLOCATOR64 -// These tests can fail on Windows if memory is somewhat full and lit happens -// to run them all at the same time. FIXME: Make them not flaky and reenable. -#if !SANITIZER_WINDOWS -TEST(SanitizerCommon, SizeClassAllocator64GetBlockBegin) { - SizeClassAllocatorGetBlockBeginStress<Allocator64>( - 1ULL << (SANITIZER_ANDROID ? 31 : 33)); -} -TEST(SanitizerCommon, SizeClassAllocator64DynamicGetBlockBegin) { - SizeClassAllocatorGetBlockBeginStress<Allocator64Dynamic>( - 1ULL << (SANITIZER_ANDROID ? 31 : 33)); -} -#if !SANITIZER_ANDROID -TEST(SanitizerCommon, SizeClassAllocator64CompactGetBlockBegin) { - SizeClassAllocatorGetBlockBeginStress<Allocator64Compact>(1ULL << 33); -} -#endif -TEST(SanitizerCommon, SizeClassAllocator64VeryCompactGetBlockBegin) { - // Does not have > 4Gb for each class. - SizeClassAllocatorGetBlockBeginStress<Allocator64VeryCompact>(1ULL << 31); -} -TEST(SanitizerCommon, SizeClassAllocator32CompactGetBlockBegin) { - SizeClassAllocatorGetBlockBeginStress<Allocator32Compact>(1ULL << 33); -} -#endif -#endif // SANITIZER_CAN_USE_ALLOCATOR64 - -struct TestMapUnmapCallback { - static int map_count, unmap_count; - void OnMap(uptr p, uptr size) const { map_count++; } - void OnUnmap(uptr p, uptr size) const { unmap_count++; } -}; -int TestMapUnmapCallback::map_count; -int TestMapUnmapCallback::unmap_count; - -#if SANITIZER_CAN_USE_ALLOCATOR64 -// These tests can fail on Windows if memory is somewhat full and lit happens -// to run them all at the same time. FIXME: Make them not flaky and reenable. -#if !SANITIZER_WINDOWS - -template <typename AddressSpaceViewTy = LocalAddressSpaceView> -struct AP64WithCallback { - static const uptr kSpaceBeg = kAllocatorSpace; - static const uptr kSpaceSize = kAllocatorSize; - static const uptr kMetadataSize = 16; - typedef ::SizeClassMap SizeClassMap; - typedef TestMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - using AddressSpaceView = AddressSpaceViewTy; -}; - -TEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) { - TestMapUnmapCallback::map_count = 0; - TestMapUnmapCallback::unmap_count = 0; - typedef SizeClassAllocator64<AP64WithCallback<>> Allocator64WithCallBack; - Allocator64WithCallBack *a = new Allocator64WithCallBack; - a->Init(kReleaseToOSIntervalNever); - EXPECT_EQ(TestMapUnmapCallback::map_count, 1); // Allocator state. - SizeClassAllocatorLocalCache<Allocator64WithCallBack> cache; - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - AllocatorStats stats; - stats.Init(); - const size_t kNumChunks = 128; - uint32_t chunks[kNumChunks]; - a->GetFromAllocator(&stats, 30, chunks, kNumChunks); - // State + alloc + metadata + freearray. - EXPECT_EQ(TestMapUnmapCallback::map_count, 4); - a->TestOnlyUnmap(); - EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1); // The whole thing. - delete a; -} -#endif -#endif - -template <typename AddressSpaceViewTy = LocalAddressSpaceView> -struct AP32WithCallback { - static const uptr kSpaceBeg = 0; - static const u64 kSpaceSize = kAddressSpaceSize; - static const uptr kMetadataSize = 16; - typedef CompactSizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = ::kRegionSizeLog; - using AddressSpaceView = AddressSpaceViewTy; - using ByteMap = FlatByteMap<kFlatByteMapSize, AddressSpaceView>; - typedef TestMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; -}; - -TEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) { - TestMapUnmapCallback::map_count = 0; - TestMapUnmapCallback::unmap_count = 0; - typedef SizeClassAllocator32<AP32WithCallback<>> Allocator32WithCallBack; - Allocator32WithCallBack *a = new Allocator32WithCallBack; - a->Init(kReleaseToOSIntervalNever); - EXPECT_EQ(TestMapUnmapCallback::map_count, 0); - SizeClassAllocatorLocalCache<Allocator32WithCallBack> cache; - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - AllocatorStats stats; - stats.Init(); - a->AllocateBatch(&stats, &cache, 32); - EXPECT_EQ(TestMapUnmapCallback::map_count, 1); - a->TestOnlyUnmap(); - EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1); - delete a; - // fprintf(stderr, "Map: %d Unmap: %d\n", - // TestMapUnmapCallback::map_count, - // TestMapUnmapCallback::unmap_count); -} - -TEST(SanitizerCommon, LargeMmapAllocatorMapUnmapCallback) { - TestMapUnmapCallback::map_count = 0; - TestMapUnmapCallback::unmap_count = 0; - LargeMmapAllocator<TestMapUnmapCallback> a; - a.Init(); - AllocatorStats stats; - stats.Init(); - void *x = a.Allocate(&stats, 1 << 20, 1); - EXPECT_EQ(TestMapUnmapCallback::map_count, 1); - a.Deallocate(&stats, x); - EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1); -} - -// Don't test OOM conditions on Win64 because it causes other tests on the same -// machine to OOM. -#if SANITIZER_CAN_USE_ALLOCATOR64 && !SANITIZER_WINDOWS64 && !SANITIZER_ANDROID -TEST(SanitizerCommon, SizeClassAllocator64Overflow) { - Allocator64 a; - a.Init(kReleaseToOSIntervalNever); - SizeClassAllocatorLocalCache<Allocator64> cache; - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - AllocatorStats stats; - stats.Init(); - - const size_t kNumChunks = 128; - uint32_t chunks[kNumChunks]; - bool allocation_failed = false; - for (int i = 0; i < 1000000; i++) { - if (!a.GetFromAllocator(&stats, 52, chunks, kNumChunks)) { - allocation_failed = true; - break; - } - } - EXPECT_EQ(allocation_failed, true); - - a.TestOnlyUnmap(); -} -#endif - -TEST(SanitizerCommon, LargeMmapAllocator) { - LargeMmapAllocator<NoOpMapUnmapCallback> a; - a.Init(); - AllocatorStats stats; - stats.Init(); - - static const int kNumAllocs = 1000; - char *allocated[kNumAllocs]; - static const uptr size = 4000; - // Allocate some. - for (int i = 0; i < kNumAllocs; i++) { - allocated[i] = (char *)a.Allocate(&stats, size, 1); - CHECK(a.PointerIsMine(allocated[i])); - } - // Deallocate all. - CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs); - for (int i = 0; i < kNumAllocs; i++) { - char *p = allocated[i]; - CHECK(a.PointerIsMine(p)); - a.Deallocate(&stats, p); - } - // Check that non left. - CHECK_EQ(a.TotalMemoryUsed(), 0); - - // Allocate some more, also add metadata. - for (int i = 0; i < kNumAllocs; i++) { - char *x = (char *)a.Allocate(&stats, size, 1); - CHECK_GE(a.GetActuallyAllocatedSize(x), size); - uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(x)); - *meta = i; - allocated[i] = x; - } - for (int i = 0; i < kNumAllocs * kNumAllocs; i++) { - char *p = allocated[i % kNumAllocs]; - CHECK(a.PointerIsMine(p)); - CHECK(a.PointerIsMine(p + 2000)); - } - CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs); - // Deallocate all in reverse order. - for (int i = 0; i < kNumAllocs; i++) { - int idx = kNumAllocs - i - 1; - char *p = allocated[idx]; - uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(p)); - CHECK_EQ(*meta, idx); - CHECK(a.PointerIsMine(p)); - a.Deallocate(&stats, p); - } - CHECK_EQ(a.TotalMemoryUsed(), 0); - - // Test alignments. Test with 512MB alignment on x64 non-Windows machines. - // Windows doesn't overcommit, and many machines do not have 51.2GB of swap. - uptr max_alignment = - (SANITIZER_WORDSIZE == 64 && !SANITIZER_WINDOWS) ? (1 << 28) : (1 << 24); - for (uptr alignment = 8; alignment <= max_alignment; alignment *= 2) { - const uptr kNumAlignedAllocs = 100; - for (uptr i = 0; i < kNumAlignedAllocs; i++) { - uptr size = ((i % 10) + 1) * 4096; - char *p = allocated[i] = (char *)a.Allocate(&stats, size, alignment); - CHECK_EQ(p, a.GetBlockBegin(p)); - CHECK_EQ(p, a.GetBlockBegin(p + size - 1)); - CHECK_EQ(p, a.GetBlockBegin(p + size / 2)); - CHECK_EQ(0, (uptr)allocated[i] % alignment); - p[0] = p[size - 1] = 0; - } - for (uptr i = 0; i < kNumAlignedAllocs; i++) { - a.Deallocate(&stats, allocated[i]); - } - } - - // Regression test for boundary condition in GetBlockBegin(). - uptr page_size = GetPageSizeCached(); - char *p = (char *)a.Allocate(&stats, page_size, 1); - CHECK_EQ(p, a.GetBlockBegin(p)); - CHECK_EQ(p, (char *)a.GetBlockBegin(p + page_size - 1)); - CHECK_NE(p, (char *)a.GetBlockBegin(p + page_size)); - a.Deallocate(&stats, p); -} - -template -<class PrimaryAllocator, class SecondaryAllocator, class AllocatorCache> -void TestCombinedAllocator() { - typedef - CombinedAllocator<PrimaryAllocator, AllocatorCache, SecondaryAllocator> - Allocator; - Allocator *a = new Allocator; - a->Init(kReleaseToOSIntervalNever); - std::mt19937 r; - - AllocatorCache cache; - memset(&cache, 0, sizeof(cache)); - a->InitCache(&cache); - - EXPECT_EQ(a->Allocate(&cache, -1, 1), (void*)0); - EXPECT_EQ(a->Allocate(&cache, -1, 1024), (void*)0); - EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1), (void*)0); - EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1024), (void*)0); - EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1023, 1024), (void*)0); - EXPECT_EQ(a->Allocate(&cache, -1, 1), (void*)0); - - const uptr kNumAllocs = 100000; - const uptr kNumIter = 10; - for (uptr iter = 0; iter < kNumIter; iter++) { - std::vector<void*> allocated; - for (uptr i = 0; i < kNumAllocs; i++) { - uptr size = (i % (1 << 14)) + 1; - if ((i % 1024) == 0) - size = 1 << (10 + (i % 14)); - void *x = a->Allocate(&cache, size, 1); - uptr *meta = reinterpret_cast<uptr*>(a->GetMetaData(x)); - CHECK_EQ(*meta, 0); - *meta = size; - allocated.push_back(x); - } - - std::shuffle(allocated.begin(), allocated.end(), r); - - // Test ForEachChunk(...) - { - std::set<void *> reported_chunks; - auto cb = [](uptr chunk, void *arg) { - auto reported_chunks_ptr = reinterpret_cast<std::set<void *> *>(arg); - auto pair = - reported_chunks_ptr->insert(reinterpret_cast<void *>(chunk)); - // Check chunk is never reported more than once. - ASSERT_TRUE(pair.second); - }; - a->ForEachChunk(cb, reinterpret_cast<void *>(&reported_chunks)); - for (const auto &allocated_ptr : allocated) { - ASSERT_NE(reported_chunks.find(allocated_ptr), reported_chunks.end()); - } - } - - for (uptr i = 0; i < kNumAllocs; i++) { - void *x = allocated[i]; - uptr *meta = reinterpret_cast<uptr*>(a->GetMetaData(x)); - CHECK_NE(*meta, 0); - CHECK(a->PointerIsMine(x)); - *meta = 0; - a->Deallocate(&cache, x); - } - allocated.clear(); - a->SwallowCache(&cache); - } - a->DestroyCache(&cache); - a->TestOnlyUnmap(); -} - -#if SANITIZER_CAN_USE_ALLOCATOR64 -TEST(SanitizerCommon, CombinedAllocator64) { - TestCombinedAllocator<Allocator64, - LargeMmapAllocator<>, - SizeClassAllocatorLocalCache<Allocator64> > (); -} - -TEST(SanitizerCommon, CombinedAllocator64Dynamic) { - TestCombinedAllocator<Allocator64Dynamic, - LargeMmapAllocator<>, - SizeClassAllocatorLocalCache<Allocator64Dynamic> > (); -} - -#if !SANITIZER_ANDROID -TEST(SanitizerCommon, CombinedAllocator64Compact) { - TestCombinedAllocator<Allocator64Compact, - LargeMmapAllocator<>, - SizeClassAllocatorLocalCache<Allocator64Compact> > (); -} -#endif - -TEST(SanitizerCommon, CombinedAllocator64VeryCompact) { - TestCombinedAllocator<Allocator64VeryCompact, - LargeMmapAllocator<>, - SizeClassAllocatorLocalCache<Allocator64VeryCompact> > (); -} -#endif - -TEST(SanitizerCommon, CombinedAllocator32Compact) { - TestCombinedAllocator<Allocator32Compact, - LargeMmapAllocator<>, - SizeClassAllocatorLocalCache<Allocator32Compact> > (); -} - -template <class AllocatorCache> -void TestSizeClassAllocatorLocalCache() { - AllocatorCache cache; - typedef typename AllocatorCache::Allocator Allocator; - Allocator *a = new Allocator(); - - a->Init(kReleaseToOSIntervalNever); - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - - const uptr kNumAllocs = 10000; - const int kNumIter = 100; - uptr saved_total = 0; - for (int class_id = 1; class_id <= 5; class_id++) { - for (int it = 0; it < kNumIter; it++) { - void *allocated[kNumAllocs]; - for (uptr i = 0; i < kNumAllocs; i++) { - allocated[i] = cache.Allocate(a, class_id); - } - for (uptr i = 0; i < kNumAllocs; i++) { - cache.Deallocate(a, class_id, allocated[i]); - } - cache.Drain(a); - uptr total_allocated = a->TotalMemoryUsed(); - if (it) - CHECK_EQ(saved_total, total_allocated); - saved_total = total_allocated; - } - } - - a->TestOnlyUnmap(); - delete a; -} - -#if SANITIZER_CAN_USE_ALLOCATOR64 -// These tests can fail on Windows if memory is somewhat full and lit happens -// to run them all at the same time. FIXME: Make them not flaky and reenable. -#if !SANITIZER_WINDOWS -TEST(SanitizerCommon, SizeClassAllocator64LocalCache) { - TestSizeClassAllocatorLocalCache< - SizeClassAllocatorLocalCache<Allocator64> >(); -} - -TEST(SanitizerCommon, SizeClassAllocator64DynamicLocalCache) { - TestSizeClassAllocatorLocalCache< - SizeClassAllocatorLocalCache<Allocator64Dynamic> >(); -} - -#if !SANITIZER_ANDROID -TEST(SanitizerCommon, SizeClassAllocator64CompactLocalCache) { - TestSizeClassAllocatorLocalCache< - SizeClassAllocatorLocalCache<Allocator64Compact> >(); -} -#endif -TEST(SanitizerCommon, SizeClassAllocator64VeryCompactLocalCache) { - TestSizeClassAllocatorLocalCache< - SizeClassAllocatorLocalCache<Allocator64VeryCompact> >(); -} -#endif -#endif - -TEST(SanitizerCommon, SizeClassAllocator32CompactLocalCache) { - TestSizeClassAllocatorLocalCache< - SizeClassAllocatorLocalCache<Allocator32Compact> >(); -} - -#if SANITIZER_CAN_USE_ALLOCATOR64 -typedef SizeClassAllocatorLocalCache<Allocator64> AllocatorCache; -static AllocatorCache static_allocator_cache; - -void *AllocatorLeakTestWorker(void *arg) { - typedef AllocatorCache::Allocator Allocator; - Allocator *a = (Allocator*)(arg); - static_allocator_cache.Allocate(a, 10); - static_allocator_cache.Drain(a); - return 0; -} - -TEST(SanitizerCommon, AllocatorLeakTest) { - typedef AllocatorCache::Allocator Allocator; - Allocator a; - a.Init(kReleaseToOSIntervalNever); - uptr total_used_memory = 0; - for (int i = 0; i < 100; i++) { - pthread_t t; - PTHREAD_CREATE(&t, 0, AllocatorLeakTestWorker, &a); - PTHREAD_JOIN(t, 0); - if (i == 0) - total_used_memory = a.TotalMemoryUsed(); - EXPECT_EQ(a.TotalMemoryUsed(), total_used_memory); - } - - a.TestOnlyUnmap(); -} - -// Struct which is allocated to pass info to new threads. The new thread frees -// it. -struct NewThreadParams { - AllocatorCache *thread_cache; - AllocatorCache::Allocator *allocator; - uptr class_id; -}; - -// Called in a new thread. Just frees its argument. -static void *DeallocNewThreadWorker(void *arg) { - NewThreadParams *params = reinterpret_cast<NewThreadParams*>(arg); - params->thread_cache->Deallocate(params->allocator, params->class_id, params); - return NULL; -} - -// The allocator cache is supposed to be POD and zero initialized. We should be -// able to call Deallocate on a zeroed cache, and it will self-initialize. -TEST(Allocator, AllocatorCacheDeallocNewThread) { - AllocatorCache::Allocator allocator; - allocator.Init(kReleaseToOSIntervalNever); - AllocatorCache main_cache; - AllocatorCache child_cache; - memset(&main_cache, 0, sizeof(main_cache)); - memset(&child_cache, 0, sizeof(child_cache)); - - uptr class_id = DefaultSizeClassMap::ClassID(sizeof(NewThreadParams)); - NewThreadParams *params = reinterpret_cast<NewThreadParams*>( - main_cache.Allocate(&allocator, class_id)); - params->thread_cache = &child_cache; - params->allocator = &allocator; - params->class_id = class_id; - pthread_t t; - PTHREAD_CREATE(&t, 0, DeallocNewThreadWorker, params); - PTHREAD_JOIN(t, 0); - - allocator.TestOnlyUnmap(); -} -#endif - -TEST(Allocator, Basic) { - char *p = (char*)InternalAlloc(10); - EXPECT_NE(p, (char*)0); - char *p2 = (char*)InternalAlloc(20); - EXPECT_NE(p2, (char*)0); - EXPECT_NE(p2, p); - InternalFree(p); - InternalFree(p2); -} - -TEST(Allocator, Stress) { - const int kCount = 1000; - char *ptrs[kCount]; - unsigned rnd = 42; - for (int i = 0; i < kCount; i++) { - uptr sz = my_rand_r(&rnd) % 1000; - char *p = (char*)InternalAlloc(sz); - EXPECT_NE(p, (char*)0); - ptrs[i] = p; - } - for (int i = 0; i < kCount; i++) { - InternalFree(ptrs[i]); - } -} - -TEST(Allocator, LargeAlloc) { - void *p = InternalAlloc(10 << 20); - InternalFree(p); -} - -TEST(Allocator, ScopedBuffer) { - const int kSize = 512; - { - InternalMmapVector<int> int_buf(kSize); - EXPECT_EQ((uptr)kSize, int_buf.size()); // NOLINT - } - InternalMmapVector<char> char_buf(kSize); - EXPECT_EQ((uptr)kSize, char_buf.size()); // NOLINT - internal_memset(char_buf.data(), 'c', kSize); - for (int i = 0; i < kSize; i++) { - EXPECT_EQ('c', char_buf[i]); - } -} - -void IterationTestCallback(uptr chunk, void *arg) { - reinterpret_cast<std::set<uptr> *>(arg)->insert(chunk); -} - -template <class Allocator> -void TestSizeClassAllocatorIteration() { - Allocator *a = new Allocator; - a->Init(kReleaseToOSIntervalNever); - SizeClassAllocatorLocalCache<Allocator> cache; - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - - static const uptr sizes[] = {1, 16, 30, 40, 100, 1000, 10000, - 50000, 60000, 100000, 120000, 300000, 500000, 1000000, 2000000}; - - std::vector<void *> allocated; - - // Allocate a bunch of chunks. - for (uptr s = 0; s < ARRAY_SIZE(sizes); s++) { - uptr size = sizes[s]; - if (!a->CanAllocate(size, 1)) continue; - // printf("s = %ld\n", size); - uptr n_iter = std::max((uptr)6, 80000 / size); - // fprintf(stderr, "size: %ld iter: %ld\n", size, n_iter); - for (uptr j = 0; j < n_iter; j++) { - uptr class_id0 = Allocator::SizeClassMapT::ClassID(size); - void *x = cache.Allocate(a, class_id0); - allocated.push_back(x); - } - } - - std::set<uptr> reported_chunks; - a->ForceLock(); - a->ForEachChunk(IterationTestCallback, &reported_chunks); - a->ForceUnlock(); - - for (uptr i = 0; i < allocated.size(); i++) { - // Don't use EXPECT_NE. Reporting the first mismatch is enough. - ASSERT_NE(reported_chunks.find(reinterpret_cast<uptr>(allocated[i])), - reported_chunks.end()); - } - - a->TestOnlyUnmap(); - delete a; -} - -#if SANITIZER_CAN_USE_ALLOCATOR64 -// These tests can fail on Windows if memory is somewhat full and lit happens -// to run them all at the same time. FIXME: Make them not flaky and reenable. -#if !SANITIZER_WINDOWS -TEST(SanitizerCommon, SizeClassAllocator64Iteration) { - TestSizeClassAllocatorIteration<Allocator64>(); -} -TEST(SanitizerCommon, SizeClassAllocator64DynamicIteration) { - TestSizeClassAllocatorIteration<Allocator64Dynamic>(); -} -#endif -#endif - -TEST(SanitizerCommon, SizeClassAllocator32Iteration) { - TestSizeClassAllocatorIteration<Allocator32Compact>(); -} - -TEST(SanitizerCommon, LargeMmapAllocatorIteration) { - LargeMmapAllocator<NoOpMapUnmapCallback> a; - a.Init(); - AllocatorStats stats; - stats.Init(); - - static const uptr kNumAllocs = 1000; - char *allocated[kNumAllocs]; - static const uptr size = 40; - // Allocate some. - for (uptr i = 0; i < kNumAllocs; i++) - allocated[i] = (char *)a.Allocate(&stats, size, 1); - - std::set<uptr> reported_chunks; - a.ForceLock(); - a.ForEachChunk(IterationTestCallback, &reported_chunks); - a.ForceUnlock(); - - for (uptr i = 0; i < kNumAllocs; i++) { - // Don't use EXPECT_NE. Reporting the first mismatch is enough. - ASSERT_NE(reported_chunks.find(reinterpret_cast<uptr>(allocated[i])), - reported_chunks.end()); - } - for (uptr i = 0; i < kNumAllocs; i++) - a.Deallocate(&stats, allocated[i]); -} - -TEST(SanitizerCommon, LargeMmapAllocatorBlockBegin) { - LargeMmapAllocator<NoOpMapUnmapCallback> a; - a.Init(); - AllocatorStats stats; - stats.Init(); - - static const uptr kNumAllocs = 1024; - static const uptr kNumExpectedFalseLookups = 10000000; - char *allocated[kNumAllocs]; - static const uptr size = 4096; - // Allocate some. - for (uptr i = 0; i < kNumAllocs; i++) { - allocated[i] = (char *)a.Allocate(&stats, size, 1); - } - - a.ForceLock(); - for (uptr i = 0; i < kNumAllocs * kNumAllocs; i++) { - // if ((i & (i - 1)) == 0) fprintf(stderr, "[%zd]\n", i); - char *p1 = allocated[i % kNumAllocs]; - EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1)); - EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 + size / 2)); - EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 + size - 1)); - EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 - 100)); - } - - for (uptr i = 0; i < kNumExpectedFalseLookups; i++) { - void *p = reinterpret_cast<void *>(i % 1024); - EXPECT_EQ((void *)0, a.GetBlockBeginFastLocked(p)); - p = reinterpret_cast<void *>(~0L - (i % 1024)); - EXPECT_EQ((void *)0, a.GetBlockBeginFastLocked(p)); - } - a.ForceUnlock(); - - for (uptr i = 0; i < kNumAllocs; i++) - a.Deallocate(&stats, allocated[i]); -} - - -// Don't test OOM conditions on Win64 because it causes other tests on the same -// machine to OOM. -#if SANITIZER_CAN_USE_ALLOCATOR64 && !SANITIZER_WINDOWS64 && !SANITIZER_ANDROID -typedef SizeClassMap<3, 4, 8, 63, 128, 16> SpecialSizeClassMap; -template <typename AddressSpaceViewTy = LocalAddressSpaceView> -struct AP64_SpecialSizeClassMap { - static const uptr kSpaceBeg = kAllocatorSpace; - static const uptr kSpaceSize = kAllocatorSize; - static const uptr kMetadataSize = 0; - typedef SpecialSizeClassMap SizeClassMap; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = 0; - using AddressSpaceView = AddressSpaceViewTy; -}; - -// Regression test for out-of-memory condition in PopulateFreeList(). -TEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) { - // In a world where regions are small and chunks are huge... - typedef SizeClassAllocator64<AP64_SpecialSizeClassMap<>> SpecialAllocator64; - const uptr kRegionSize = - kAllocatorSize / SpecialSizeClassMap::kNumClassesRounded; - SpecialAllocator64 *a = new SpecialAllocator64; - a->Init(kReleaseToOSIntervalNever); - SizeClassAllocatorLocalCache<SpecialAllocator64> cache; - memset(&cache, 0, sizeof(cache)); - cache.Init(0); - - // ...one man is on a mission to overflow a region with a series of - // successive allocations. - - const uptr kClassID = 107; - const uptr kAllocationSize = SpecialSizeClassMap::Size(kClassID); - ASSERT_LT(2 * kAllocationSize, kRegionSize); - ASSERT_GT(3 * kAllocationSize, kRegionSize); - EXPECT_NE(cache.Allocate(a, kClassID), nullptr); - EXPECT_NE(cache.Allocate(a, kClassID), nullptr); - EXPECT_EQ(cache.Allocate(a, kClassID), nullptr); - - const uptr Class2 = 100; - const uptr Size2 = SpecialSizeClassMap::Size(Class2); - ASSERT_EQ(Size2 * 8, kRegionSize); - char *p[7]; - for (int i = 0; i < 7; i++) { - p[i] = (char*)cache.Allocate(a, Class2); - EXPECT_NE(p[i], nullptr); - fprintf(stderr, "p[%d] %p s = %lx\n", i, (void*)p[i], Size2); - p[i][Size2 - 1] = 42; - if (i) ASSERT_LT(p[i - 1], p[i]); - } - EXPECT_EQ(cache.Allocate(a, Class2), nullptr); - cache.Deallocate(a, Class2, p[0]); - cache.Drain(a); - ASSERT_EQ(p[6][Size2 - 1], 42); - a->TestOnlyUnmap(); - delete a; -} - -#endif - -#if SANITIZER_CAN_USE_ALLOCATOR64 - -class NoMemoryMapper { - public: - uptr last_request_buffer_size; - - NoMemoryMapper() : last_request_buffer_size(0) {} - - uptr MapPackedCounterArrayBuffer(uptr buffer_size) { - last_request_buffer_size = buffer_size; - return 0; - } - void UnmapPackedCounterArrayBuffer(uptr buffer, uptr buffer_size) {} -}; - -class RedZoneMemoryMapper { - public: - RedZoneMemoryMapper() { - const auto page_size = GetPageSize(); - buffer = MmapOrDie(3ULL * page_size, ""); - MprotectNoAccess(reinterpret_cast<uptr>(buffer), page_size); - MprotectNoAccess(reinterpret_cast<uptr>(buffer) + page_size * 2, page_size); - } - ~RedZoneMemoryMapper() { - UnmapOrDie(buffer, 3 * GetPageSize()); - } - - uptr MapPackedCounterArrayBuffer(uptr buffer_size) { - const auto page_size = GetPageSize(); - CHECK_EQ(buffer_size, page_size); - memset(reinterpret_cast<void*>(reinterpret_cast<uptr>(buffer) + page_size), - 0, page_size); - return reinterpret_cast<uptr>(buffer) + page_size; - } - void UnmapPackedCounterArrayBuffer(uptr buffer, uptr buffer_size) {} - - private: - void *buffer; -}; - -TEST(SanitizerCommon, SizeClassAllocator64PackedCounterArray) { - NoMemoryMapper no_memory_mapper; - typedef Allocator64::PackedCounterArray<NoMemoryMapper> - NoMemoryPackedCounterArray; - - for (int i = 0; i < 64; i++) { - // Various valid counter's max values packed into one word. - NoMemoryPackedCounterArray counters_2n(1, 1ULL << i, &no_memory_mapper); - EXPECT_EQ(8ULL, no_memory_mapper.last_request_buffer_size); - - // Check the "all bit set" values too. - NoMemoryPackedCounterArray counters_2n1_1(1, ~0ULL >> i, &no_memory_mapper); - EXPECT_EQ(8ULL, no_memory_mapper.last_request_buffer_size); - - // Verify the packing ratio, the counter is expected to be packed into the - // closest power of 2 bits. - NoMemoryPackedCounterArray counters(64, 1ULL << i, &no_memory_mapper); - EXPECT_EQ(8ULL * RoundUpToPowerOfTwo(i + 1), - no_memory_mapper.last_request_buffer_size); - } - - RedZoneMemoryMapper memory_mapper; - typedef Allocator64::PackedCounterArray<RedZoneMemoryMapper> - RedZonePackedCounterArray; - // Go through 1, 2, 4, 8, .. 64 bits per counter. - for (int i = 0; i < 7; i++) { - // Make sure counters request one memory page for the buffer. - const u64 kNumCounters = (GetPageSize() / 8) * (64 >> i); - RedZonePackedCounterArray counters(kNumCounters, - 1ULL << ((1 << i) - 1), - &memory_mapper); - counters.Inc(0); - for (u64 c = 1; c < kNumCounters - 1; c++) { - ASSERT_EQ(0ULL, counters.Get(c)); - counters.Inc(c); - ASSERT_EQ(1ULL, counters.Get(c - 1)); - } - ASSERT_EQ(0ULL, counters.Get(kNumCounters - 1)); - counters.Inc(kNumCounters - 1); - - if (i > 0) { - counters.IncRange(0, kNumCounters - 1); - for (u64 c = 0; c < kNumCounters; c++) - ASSERT_EQ(2ULL, counters.Get(c)); - } - } -} - -class RangeRecorder { - public: - std::string reported_pages; - - RangeRecorder() - : page_size_scaled_log( - Log2(GetPageSizeCached() >> Allocator64::kCompactPtrScale)), - last_page_reported(0) {} - - void ReleasePageRangeToOS(u32 from, u32 to) { - from >>= page_size_scaled_log; - to >>= page_size_scaled_log; - ASSERT_LT(from, to); - if (!reported_pages.empty()) - ASSERT_LT(last_page_reported, from); - reported_pages.append(from - last_page_reported, '.'); - reported_pages.append(to - from, 'x'); - last_page_reported = to; - } - private: - const uptr page_size_scaled_log; - u32 last_page_reported; -}; - -TEST(SanitizerCommon, SizeClassAllocator64FreePagesRangeTracker) { - typedef Allocator64::FreePagesRangeTracker<RangeRecorder> RangeTracker; - - // 'x' denotes a page to be released, '.' denotes a page to be kept around. - const char* test_cases[] = { - "", - ".", - "x", - "........", - "xxxxxxxxxxx", - "..............xxxxx", - "xxxxxxxxxxxxxxxxxx.....", - "......xxxxxxxx........", - "xxx..........xxxxxxxxxxxxxxx", - "......xxxx....xxxx........", - "xxx..........xxxxxxxx....xxxxxxx", - "x.x.x.x.x.x.x.x.x.x.x.x.", - ".x.x.x.x.x.x.x.x.x.x.x.x", - ".x.x.x.x.x.x.x.x.x.x.x.x.", - "x.x.x.x.x.x.x.x.x.x.x.x.x", - }; - - for (auto test_case : test_cases) { - RangeRecorder range_recorder; - RangeTracker tracker(&range_recorder); - for (int i = 0; test_case[i] != 0; i++) - tracker.NextPage(test_case[i] == 'x'); - tracker.Done(); - // Strip trailing '.'-pages before comparing the results as they are not - // going to be reported to range_recorder anyway. - const char* last_x = strrchr(test_case, 'x'); - std::string expected( - test_case, - last_x == nullptr ? 0 : (last_x - test_case + 1)); - EXPECT_STREQ(expected.c_str(), range_recorder.reported_pages.c_str()); - } -} - -class ReleasedPagesTrackingMemoryMapper { - public: - std::set<u32> reported_pages; - - uptr MapPackedCounterArrayBuffer(uptr buffer_size) { - reported_pages.clear(); - return reinterpret_cast<uptr>(calloc(1, buffer_size)); - } - void UnmapPackedCounterArrayBuffer(uptr buffer, uptr buffer_size) { - free(reinterpret_cast<void*>(buffer)); - } - - void ReleasePageRangeToOS(u32 from, u32 to) { - uptr page_size_scaled = - GetPageSizeCached() >> Allocator64::kCompactPtrScale; - for (u32 i = from; i < to; i += page_size_scaled) - reported_pages.insert(i); - } -}; - -template <class Allocator> -void TestReleaseFreeMemoryToOS() { - ReleasedPagesTrackingMemoryMapper memory_mapper; - const uptr kAllocatedPagesCount = 1024; - const uptr page_size = GetPageSizeCached(); - const uptr page_size_scaled = page_size >> Allocator::kCompactPtrScale; - std::mt19937 r; - uint32_t rnd_state = 42; - - for (uptr class_id = 1; class_id <= Allocator::SizeClassMapT::kLargestClassID; - class_id++) { - const uptr chunk_size = Allocator::SizeClassMapT::Size(class_id); - const uptr chunk_size_scaled = chunk_size >> Allocator::kCompactPtrScale; - const uptr max_chunks = - kAllocatedPagesCount * GetPageSizeCached() / chunk_size; - - // Generate the random free list. - std::vector<u32> free_array; - bool in_free_range = false; - uptr current_range_end = 0; - for (uptr i = 0; i < max_chunks; i++) { - if (i == current_range_end) { - in_free_range = (my_rand_r(&rnd_state) & 1U) == 1; - current_range_end += my_rand_r(&rnd_state) % 100 + 1; - } - if (in_free_range) - free_array.push_back(i * chunk_size_scaled); - } - if (free_array.empty()) - continue; - // Shuffle free_list to verify that ReleaseFreeMemoryToOS does not depend on - // the list ordering. - std::shuffle(free_array.begin(), free_array.end(), r); - - Allocator::ReleaseFreeMemoryToOS(&free_array[0], free_array.size(), - chunk_size, kAllocatedPagesCount, - &memory_mapper); - - // Verify that there are no released pages touched by used chunks and all - // ranges of free chunks big enough to contain the entire memory pages had - // these pages released. - uptr verified_released_pages = 0; - std::set<u32> free_chunks(free_array.begin(), free_array.end()); - - u32 current_chunk = 0; - in_free_range = false; - u32 current_free_range_start = 0; - for (uptr i = 0; i <= max_chunks; i++) { - bool is_free_chunk = free_chunks.find(current_chunk) != free_chunks.end(); - - if (is_free_chunk) { - if (!in_free_range) { - in_free_range = true; - current_free_range_start = current_chunk; - } - } else { - // Verify that this used chunk does not touch any released page. - for (uptr i_page = current_chunk / page_size_scaled; - i_page <= (current_chunk + chunk_size_scaled - 1) / - page_size_scaled; - i_page++) { - bool page_released = - memory_mapper.reported_pages.find(i_page * page_size_scaled) != - memory_mapper.reported_pages.end(); - ASSERT_EQ(false, page_released); - } - - if (in_free_range) { - in_free_range = false; - // Verify that all entire memory pages covered by this range of free - // chunks were released. - u32 page = RoundUpTo(current_free_range_start, page_size_scaled); - while (page + page_size_scaled <= current_chunk) { - bool page_released = - memory_mapper.reported_pages.find(page) != - memory_mapper.reported_pages.end(); - ASSERT_EQ(true, page_released); - verified_released_pages++; - page += page_size_scaled; - } - } - } - - current_chunk += chunk_size_scaled; - } - - ASSERT_EQ(memory_mapper.reported_pages.size(), verified_released_pages); - } -} - -TEST(SanitizerCommon, SizeClassAllocator64ReleaseFreeMemoryToOS) { - TestReleaseFreeMemoryToOS<Allocator64>(); -} - -#if !SANITIZER_ANDROID -TEST(SanitizerCommon, SizeClassAllocator64CompactReleaseFreeMemoryToOS) { - TestReleaseFreeMemoryToOS<Allocator64Compact>(); -} - -TEST(SanitizerCommon, SizeClassAllocator64VeryCompactReleaseFreeMemoryToOS) { - TestReleaseFreeMemoryToOS<Allocator64VeryCompact>(); -} -#endif // !SANITIZER_ANDROID - -#endif // SANITIZER_CAN_USE_ALLOCATOR64 - -TEST(SanitizerCommon, TwoLevelByteMap) { - const u64 kSize1 = 1 << 6, kSize2 = 1 << 12; - const u64 n = kSize1 * kSize2; - TwoLevelByteMap<kSize1, kSize2> m; - m.Init(); - for (u64 i = 0; i < n; i += 7) { - m.set(i, (i % 100) + 1); - } - for (u64 j = 0; j < n; j++) { - if (j % 7) - EXPECT_EQ(m[j], 0); - else - EXPECT_EQ(m[j], (j % 100) + 1); - } - - m.TestOnlyUnmap(); -} - -template <typename AddressSpaceView> -using TestByteMapASVT = - TwoLevelByteMap<1 << 12, 1 << 13, AddressSpaceView, TestMapUnmapCallback>; -using TestByteMap = TestByteMapASVT<LocalAddressSpaceView>; - -struct TestByteMapParam { - TestByteMap *m; - size_t shard; - size_t num_shards; -}; - -void *TwoLevelByteMapUserThread(void *param) { - TestByteMapParam *p = (TestByteMapParam*)param; - for (size_t i = p->shard; i < p->m->size(); i += p->num_shards) { - size_t val = (i % 100) + 1; - p->m->set(i, val); - EXPECT_EQ((*p->m)[i], val); - } - return 0; -} - -TEST(SanitizerCommon, ThreadedTwoLevelByteMap) { - TestByteMap m; - m.Init(); - TestMapUnmapCallback::map_count = 0; - TestMapUnmapCallback::unmap_count = 0; - static const int kNumThreads = 4; - pthread_t t[kNumThreads]; - TestByteMapParam p[kNumThreads]; - for (int i = 0; i < kNumThreads; i++) { - p[i].m = &m; - p[i].shard = i; - p[i].num_shards = kNumThreads; - PTHREAD_CREATE(&t[i], 0, TwoLevelByteMapUserThread, &p[i]); - } - for (int i = 0; i < kNumThreads; i++) { - PTHREAD_JOIN(t[i], 0); - } - EXPECT_EQ((uptr)TestMapUnmapCallback::map_count, m.size1()); - EXPECT_EQ((uptr)TestMapUnmapCallback::unmap_count, 0UL); - m.TestOnlyUnmap(); - EXPECT_EQ((uptr)TestMapUnmapCallback::map_count, m.size1()); - EXPECT_EQ((uptr)TestMapUnmapCallback::unmap_count, m.size1()); -} - -#endif // #if !SANITIZER_DEBUG diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc b/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc deleted file mode 100644 index d2920d8f7f67c..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_allocator_testlib.cc +++ /dev/null @@ -1,203 +0,0 @@ -//===-- sanitizer_allocator_testlib.cc ------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Malloc replacement library based on CombinedAllocator. -// The primary purpose of this file is an end-to-end integration test -// for CombinedAllocator. -//===----------------------------------------------------------------------===// -/* Usage: -clang++ -std=c++11 -fno-exceptions -g -fPIC -I. -I../include -Isanitizer \ - sanitizer_common/tests/sanitizer_allocator_testlib.cc \ - $(\ls sanitizer_common/sanitizer_*.cc | grep -v sanitizer_common_nolibc.cc) \ - sanitizer_common/sanitizer_linux_x86_64.S \ - -shared -lpthread -o testmalloc.so -LD_PRELOAD=`pwd`/testmalloc.so /your/app -*/ -#include "sanitizer_common/sanitizer_allocator.h" -#include "sanitizer_common/sanitizer_common.h" -#include <stddef.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <pthread.h> - -#ifndef SANITIZER_MALLOC_HOOK -# define SANITIZER_MALLOC_HOOK(p, s) -#endif - -#ifndef SANITIZER_FREE_HOOK -# define SANITIZER_FREE_HOOK(p) -#endif - -static const uptr kAllocatorSpace = 0x600000000000ULL; -static const uptr kAllocatorSize = 0x10000000000ULL; // 1T. - -struct __AP64 { - static const uptr kSpaceBeg = ~(uptr)0; - static const uptr kSpaceSize = kAllocatorSize; - static const uptr kMetadataSize = 0; - typedef CompactSizeClassMap SizeClassMap; - typedef NoOpMapUnmapCallback MapUnmapCallback; - static const uptr kFlags = - SizeClassAllocator64FlagMasks::kRandomShuffleChunks; -}; - -namespace { - -typedef SizeClassAllocator64<__AP64> PrimaryAllocator; -typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; -typedef LargeMmapAllocator<> SecondaryAllocator; -typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, - SecondaryAllocator> Allocator; - -static Allocator allocator; -static bool global_inited; -static THREADLOCAL AllocatorCache cache; -static THREADLOCAL bool thread_inited; -static pthread_key_t pkey; - -static void thread_dtor(void *v) { - if ((uptr)v != 3) { - pthread_setspecific(pkey, (void*)((uptr)v + 1)); - return; - } - allocator.SwallowCache(&cache); -} - -static size_t GetRss() { - if (FILE *f = fopen("/proc/self/statm", "r")) { - size_t size = 0, rss = 0; - fscanf(f, "%zd %zd", &size, &rss); - fclose(f); - return rss << 12; // rss is in pages. - } - return 0; -} - -struct AtExit { - ~AtExit() { - allocator.PrintStats(); - Printf("RSS: %zdM\n", GetRss() >> 20); - } -}; - -static AtExit at_exit; - -static void NOINLINE thread_init() { - if (!global_inited) { - global_inited = true; - allocator.Init(false /*may_return_null*/); - pthread_key_create(&pkey, thread_dtor); - } - thread_inited = true; - pthread_setspecific(pkey, (void*)1); - cache.Init(nullptr); -} -} // namespace - -extern "C" { -void *malloc(size_t size) { - if (UNLIKELY(!thread_inited)) - thread_init(); - void *p = allocator.Allocate(&cache, size, 8); - SANITIZER_MALLOC_HOOK(p, size); - return p; -} - -void free(void *p) { - if (UNLIKELY(!thread_inited)) - thread_init(); - SANITIZER_FREE_HOOK(p); - allocator.Deallocate(&cache, p); -} - -void *calloc(size_t nmemb, size_t size) { - if (UNLIKELY(!thread_inited)) - thread_init(); - size *= nmemb; - void *p = allocator.Allocate(&cache, size, 8, false); - memset(p, 0, size); - SANITIZER_MALLOC_HOOK(p, size); - return p; -} - -void *realloc(void *p, size_t size) { - if (UNLIKELY(!thread_inited)) - thread_init(); - if (p) { - SANITIZER_FREE_HOOK(p); - } - p = allocator.Reallocate(&cache, p, size, 8); - if (p) { - SANITIZER_MALLOC_HOOK(p, size); - } - return p; -} - -#if SANITIZER_INTERCEPT_MEMALIGN -void *memalign(size_t alignment, size_t size) { - if (UNLIKELY(!thread_inited)) - thread_init(); - void *p = allocator.Allocate(&cache, size, alignment); - SANITIZER_MALLOC_HOOK(p, size); - return p; -} -#endif // SANITIZER_INTERCEPT_MEMALIGN - -int posix_memalign(void **memptr, size_t alignment, size_t size) { - if (UNLIKELY(!thread_inited)) - thread_init(); - *memptr = allocator.Allocate(&cache, size, alignment); - SANITIZER_MALLOC_HOOK(*memptr, size); - return 0; -} - -void *valloc(size_t size) { - if (UNLIKELY(!thread_inited)) - thread_init(); - if (size == 0) - size = GetPageSizeCached(); - void *p = allocator.Allocate(&cache, size, GetPageSizeCached()); - SANITIZER_MALLOC_HOOK(p, size); - return p; -} - -#if SANITIZER_INTERCEPT_CFREE -void cfree(void *p) ALIAS("free"); -#endif // SANITIZER_INTERCEPT_CFREE -#if SANITIZER_INTERCEPT_PVALLOC -void *pvalloc(size_t size) ALIAS("valloc"); -#endif // SANITIZER_INTERCEPT_PVALLOC -#if SANITIZER_INTERCEPT_MEMALIGN -void *__libc_memalign(size_t alignment, size_t size) ALIAS("memalign"); -#endif // SANITIZER_INTERCEPT_MEMALIGN - -void malloc_usable_size() { -} - -#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO -void mallinfo() { -} - -void mallopt() { -} -#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO -} // extern "C" - -namespace std { - struct nothrow_t; -} - -void *operator new(size_t size) ALIAS("malloc"); -void *operator new[](size_t size) ALIAS("malloc"); -void *operator new(size_t size, std::nothrow_t const&) ALIAS("malloc"); -void *operator new[](size_t size, std::nothrow_t const&) ALIAS("malloc"); -void operator delete(void *ptr) throw() ALIAS("free"); -void operator delete[](void *ptr) throw() ALIAS("free"); -void operator delete(void *ptr, std::nothrow_t const&) ALIAS("free"); -void operator delete[](void *ptr, std::nothrow_t const&) ALIAS("free"); diff --git a/lib/sanitizer_common/tests/sanitizer_atomic_test.cc b/lib/sanitizer_common/tests/sanitizer_atomic_test.cc deleted file mode 100644 index 56bcd35c826c1..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_atomic_test.cc +++ /dev/null @@ -1,128 +0,0 @@ -//===-- sanitizer_atomic_test.cc ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_atomic.h" -#include "gtest/gtest.h" - -namespace __sanitizer { - -template<typename T> -struct ValAndMagic { - typename T::Type magic0; - T a; - typename T::Type magic1; - - static ValAndMagic<T> *sink; -}; - -template<typename T> -ValAndMagic<T> *ValAndMagic<T>::sink; - -template<typename T, memory_order load_mo, memory_order store_mo> -void CheckStoreLoad() { - typedef typename T::Type Type; - ValAndMagic<T> val; - // Prevent the compiler from scalarizing the struct. - ValAndMagic<T>::sink = &val; - // Ensure that surrounding memory is not overwritten. - val.magic0 = val.magic1 = (Type)-3; - for (u64 i = 0; i < 100; i++) { - // Generate a value that occupies all bytes of the variable. - u64 v = i; - v |= v << 8; - v |= v << 16; - v |= v << 32; - val.a.val_dont_use = (Type)v; - EXPECT_EQ(atomic_load(&val.a, load_mo), (Type)v); - val.a.val_dont_use = (Type)-1; - atomic_store(&val.a, (Type)v, store_mo); - EXPECT_EQ(val.a.val_dont_use, (Type)v); - } - EXPECT_EQ(val.magic0, (Type)-3); - EXPECT_EQ(val.magic1, (Type)-3); -} - -TEST(SanitizerCommon, AtomicStoreLoad) { - CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint8_t, memory_order_consume, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint8_t, memory_order_acquire, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_release>(); - CheckStoreLoad<atomic_uint8_t, memory_order_seq_cst, memory_order_seq_cst>(); - - CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint16_t, memory_order_consume, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint16_t, memory_order_acquire, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_release>(); - CheckStoreLoad<atomic_uint16_t, memory_order_seq_cst, memory_order_seq_cst>(); - - CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint32_t, memory_order_consume, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint32_t, memory_order_acquire, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_release>(); - CheckStoreLoad<atomic_uint32_t, memory_order_seq_cst, memory_order_seq_cst>(); - - CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint64_t, memory_order_consume, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint64_t, memory_order_acquire, memory_order_relaxed>(); - CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_release>(); - CheckStoreLoad<atomic_uint64_t, memory_order_seq_cst, memory_order_seq_cst>(); - - CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_relaxed> - (); - CheckStoreLoad<atomic_uintptr_t, memory_order_consume, memory_order_relaxed> - (); - CheckStoreLoad<atomic_uintptr_t, memory_order_acquire, memory_order_relaxed> - (); - CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_release> - (); - CheckStoreLoad<atomic_uintptr_t, memory_order_seq_cst, memory_order_seq_cst> - (); -} - -// Clang crashes while compiling this test for Android: -// http://llvm.org/bugs/show_bug.cgi?id=15587 -#if !SANITIZER_ANDROID -template<typename T> -void CheckAtomicCompareExchange() { - typedef typename T::Type Type; - { - Type old_val = 42; - Type new_val = 24; - Type var = old_val; - EXPECT_TRUE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val, - memory_order_relaxed)); - EXPECT_FALSE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val, - memory_order_relaxed)); - EXPECT_EQ(new_val, old_val); - } - { - Type old_val = 42; - Type new_val = 24; - Type var = old_val; - EXPECT_TRUE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val, - memory_order_relaxed)); - EXPECT_FALSE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val, - memory_order_relaxed)); - EXPECT_EQ(new_val, old_val); - } -} - -TEST(SanitizerCommon, AtomicCompareExchangeTest) { - CheckAtomicCompareExchange<atomic_uint8_t>(); - CheckAtomicCompareExchange<atomic_uint16_t>(); - CheckAtomicCompareExchange<atomic_uint32_t>(); - CheckAtomicCompareExchange<atomic_uint64_t>(); - CheckAtomicCompareExchange<atomic_uintptr_t>(); -} -#endif //!SANITIZER_ANDROID - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc b/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc deleted file mode 100644 index 669365b80ecbf..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_bitvector_test.cc +++ /dev/null @@ -1,178 +0,0 @@ -//===-- sanitizer_bitvector_test.cc ---------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of Sanitizer runtime. -// Tests for sanitizer_bitvector.h. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_bitvector.h" - -#include "sanitizer_test_utils.h" - -#include "gtest/gtest.h" - -#include <algorithm> -#include <vector> -#include <random> -#include <set> - -using namespace __sanitizer; -using namespace std; - - -// Check the 'bv' == 's' and that the indexes go in increasing order. -// Also check the BV::Iterator -template <class BV> -static void CheckBV(const BV &bv, const set<uptr> &s) { - BV t; - t.copyFrom(bv); - set<uptr> t_s(s); - uptr last_idx = bv.size(); - uptr count = 0; - for (typename BV::Iterator it(bv); it.hasNext();) { - uptr idx = it.next(); - count++; - if (last_idx != bv.size()) - EXPECT_LT(last_idx, idx); - last_idx = idx; - EXPECT_TRUE(s.count(idx)); - } - EXPECT_EQ(count, s.size()); - - last_idx = bv.size(); - while (!t.empty()) { - uptr idx = t.getAndClearFirstOne(); - if (last_idx != bv.size()) - EXPECT_LT(last_idx, idx); - last_idx = idx; - EXPECT_TRUE(t_s.erase(idx)); - } - EXPECT_TRUE(t_s.empty()); -} - -template <class BV> -void Print(const BV &bv) { - BV t; - t.copyFrom(bv); - while (!t.empty()) { - uptr idx = t.getAndClearFirstOne(); - fprintf(stderr, "%lu ", idx); - } - fprintf(stderr, "\n"); -} - -void Print(const set<uptr> &s) { - for (set<uptr>::iterator it = s.begin(); it != s.end(); ++it) { - fprintf(stderr, "%lu ", *it); - } - fprintf(stderr, "\n"); -} - -template <class BV> -void TestBitVector(uptr expected_size) { - std::mt19937 r; - BV bv, bv1, t_bv; - EXPECT_EQ(expected_size, BV::kSize); - bv.clear(); - EXPECT_TRUE(bv.empty()); - bv.setBit(5); - EXPECT_FALSE(bv.empty()); - EXPECT_FALSE(bv.getBit(4)); - EXPECT_FALSE(bv.getBit(6)); - EXPECT_TRUE(bv.getBit(5)); - bv.clearBit(5); - EXPECT_FALSE(bv.getBit(5)); - - // test random bits - bv.clear(); - set<uptr> s; - for (uptr it = 0; it < 1000; it++) { - uptr bit = ((uptr)my_rand() % bv.size()); - EXPECT_EQ(bv.getBit(bit), s.count(bit) == 1); - switch (my_rand() % 2) { - case 0: - EXPECT_EQ(bv.setBit(bit), s.insert(bit).second); - break; - case 1: - size_t old_size = s.size(); - s.erase(bit); - EXPECT_EQ(bv.clearBit(bit), old_size > s.size()); - break; - } - EXPECT_EQ(bv.getBit(bit), s.count(bit) == 1); - } - - vector<uptr>bits(bv.size()); - // Test setUnion, setIntersection, setDifference, - // intersectsWith, and getAndClearFirstOne. - for (uptr it = 0; it < 30; it++) { - // iota - for (size_t j = 0; j < bits.size(); j++) bits[j] = j; - std::shuffle(bits.begin(), bits.end(), r); - set<uptr> s, s1, t_s; - bv.clear(); - bv1.clear(); - uptr n_bits = ((uptr)my_rand() % bv.size()) + 1; - uptr n_bits1 = (uptr)my_rand() % (bv.size() / 2); - EXPECT_TRUE(n_bits > 0 && n_bits <= bv.size()); - EXPECT_TRUE(n_bits1 < bv.size() / 2); - for (uptr i = 0; i < n_bits; i++) { - bv.setBit(bits[i]); - s.insert(bits[i]); - } - CheckBV(bv, s); - for (uptr i = 0; i < n_bits1; i++) { - bv1.setBit(bits[bv.size() / 2 + i]); - s1.insert(bits[bv.size() / 2 + i]); - } - CheckBV(bv1, s1); - - vector<uptr> vec; - set_intersection(s.begin(), s.end(), s1.begin(), s1.end(), - back_insert_iterator<vector<uptr> >(vec)); - EXPECT_EQ(bv.intersectsWith(bv1), !vec.empty()); - - // setUnion - t_s = s; - t_bv.copyFrom(bv); - t_s.insert(s1.begin(), s1.end()); - EXPECT_EQ(t_bv.setUnion(bv1), s.size() != t_s.size()); - CheckBV(t_bv, t_s); - - // setIntersection - t_s = set<uptr>(vec.begin(), vec.end()); - t_bv.copyFrom(bv); - EXPECT_EQ(t_bv.setIntersection(bv1), s.size() != t_s.size()); - CheckBV(t_bv, t_s); - - // setDifference - vec.clear(); - set_difference(s.begin(), s.end(), s1.begin(), s1.end(), - back_insert_iterator<vector<uptr> >(vec)); - t_s = set<uptr>(vec.begin(), vec.end()); - t_bv.copyFrom(bv); - EXPECT_EQ(t_bv.setDifference(bv1), s.size() != t_s.size()); - CheckBV(t_bv, t_s); - } -} - -TEST(SanitizerCommon, BasicBitVector) { - TestBitVector<BasicBitVector<u8> >(8); - TestBitVector<BasicBitVector<u16> >(16); - TestBitVector<BasicBitVector<> >(SANITIZER_WORDSIZE); -} - -TEST(SanitizerCommon, TwoLevelBitVector) { - uptr ws = SANITIZER_WORDSIZE; - TestBitVector<TwoLevelBitVector<1, BasicBitVector<u8> > >(8 * 8); - TestBitVector<TwoLevelBitVector<> >(ws * ws); - TestBitVector<TwoLevelBitVector<2> >(ws * ws * 2); - TestBitVector<TwoLevelBitVector<3> >(ws * ws * 3); - TestBitVector<TwoLevelBitVector<3, BasicBitVector<u16> > >(16 * 16 * 3); -} diff --git a/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc b/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc deleted file mode 100644 index 3b39f8dd734aa..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_bvgraph_test.cc +++ /dev/null @@ -1,339 +0,0 @@ -//===-- sanitizer_bvgraph_test.cc -----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of Sanitizer runtime. -// Tests for sanitizer_bvgraph.h. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_bvgraph.h" - -#include "sanitizer_test_utils.h" - -#include "gtest/gtest.h" - -#include <algorithm> -#include <vector> -#include <set> - -using namespace __sanitizer; -using namespace std; - -typedef BasicBitVector<u8> BV1; -typedef BasicBitVector<> BV2; -typedef TwoLevelBitVector<> BV3; -typedef TwoLevelBitVector<3, BasicBitVector<u8> > BV4; - -template<class G> -void PrintGraph(const G &g) { - for (uptr i = 0; i < g.size(); i++) { - for (uptr j = 0; j < g.size(); j++) { - fprintf(stderr, "%d", g.hasEdge(i, j)); - } - fprintf(stderr, "\n"); - } -} - - -class SimpleGraph { - public: - void clear() { s_.clear(); } - bool addEdge(uptr from, uptr to) { - return s_.insert(idx(from, to)).second; - } - bool removeEdge(uptr from, uptr to) { - return s_.erase(idx(from, to)); - } - template <class G> - void checkSameAs(G *g) { - for (set<uptr>::iterator it = s_.begin(); it != s_.end(); ++it) { - uptr from = *it >> 16; - uptr to = *it & ((1 << 16) - 1); - EXPECT_TRUE(g->removeEdge(from, to)); - } - EXPECT_TRUE(g->empty()); - } - private: - uptr idx(uptr from, uptr to) { - CHECK_LE(from|to, 1 << 16); - return (from << 16) + to; - } - set<uptr> s_; -}; - -template <class BV> -void BasicTest() { - BVGraph<BV> g; - g.clear(); - BV target; - SimpleGraph s_g; - set<uptr> s; - set<uptr> s_target; - int num_reachable = 0; - for (int it = 0; it < 1000; it++) { - target.clear(); - s_target.clear(); - for (int t = 0; t < 4; t++) { - uptr idx = (uptr)my_rand() % g.size(); - EXPECT_EQ(target.setBit(idx), s_target.insert(idx).second); - } - uptr from = my_rand() % g.size(); - uptr to = my_rand() % g.size(); - EXPECT_EQ(g.addEdge(from, to), s_g.addEdge(from, to)); - EXPECT_TRUE(g.hasEdge(from, to)); - for (int i = 0; i < 10; i++) { - from = my_rand() % g.size(); - bool is_reachable = g.isReachable(from, target); - if (is_reachable) { - uptr path[BV::kSize]; - uptr len; - for (len = 1; len < BV::kSize; len++) { - if (g.findPath(from, target, path, len) == len) - break; - } - EXPECT_LT(len, BV::kSize); - EXPECT_TRUE(target.getBit(path[len - 1])); - // fprintf(stderr, "reachable: %zd; path %zd {%zd %zd %zd}\n", - // from, len, path[0], path[1], path[2]); - num_reachable++; - } - } - } - EXPECT_GT(num_reachable, 0); -} - -TEST(BVGraph, BasicTest) { - BasicTest<BV1>(); - BasicTest<BV2>(); - BasicTest<BV3>(); - BasicTest<BV4>(); -} - -template <class BV> -void RemoveEdges() { - SimpleGraph s_g; - BVGraph<BV> g; - g.clear(); - BV bv; - set<uptr> s; - for (int it = 0; it < 100; it++) { - s.clear(); - bv.clear(); - s_g.clear(); - g.clear(); - for (uptr j = 0; j < g.size() * 2; j++) { - uptr from = my_rand() % g.size(); - uptr to = my_rand() % g.size(); - EXPECT_EQ(g.addEdge(from, to), s_g.addEdge(from, to)); - } - for (uptr j = 0; j < 5; j++) { - uptr idx = my_rand() % g.size(); - s.insert(idx); - bv.setBit(idx); - } - - if (it % 2) { - g.removeEdgesFrom(bv); - for (set<uptr>::iterator from = s.begin(); from != s.end(); ++from) { - for (uptr to = 0; to < g.size(); to++) - s_g.removeEdge(*from, to); - } - } else { - g.removeEdgesTo(bv); - for (set<uptr>::iterator to = s.begin(); to != s.end(); ++to) { - for (uptr from = 0; from < g.size(); from++) - s_g.removeEdge(from, *to); - } - } - s_g.checkSameAs(&g); - } -} - -TEST(BVGraph, RemoveEdges) { - RemoveEdges<BV1>(); - RemoveEdges<BV2>(); - RemoveEdges<BV3>(); - RemoveEdges<BV4>(); -} - -template <class BV> -void Test_isReachable() { - uptr path[5]; - BVGraph<BV> g; - g.clear(); - BV target; - target.clear(); - uptr t0 = 0; - uptr t1 = g.size() - 1; - target.setBit(t0); - target.setBit(t1); - - uptr f0 = 1; - uptr f1 = 2; - uptr f2 = g.size() / 2; - uptr f3 = g.size() - 2; - - EXPECT_FALSE(g.isReachable(f0, target)); - EXPECT_FALSE(g.isReachable(f1, target)); - EXPECT_FALSE(g.isReachable(f2, target)); - EXPECT_FALSE(g.isReachable(f3, target)); - - g.addEdge(f0, f1); - g.addEdge(f1, f2); - g.addEdge(f2, f3); - EXPECT_FALSE(g.isReachable(f0, target)); - EXPECT_FALSE(g.isReachable(f1, target)); - EXPECT_FALSE(g.isReachable(f2, target)); - EXPECT_FALSE(g.isReachable(f3, target)); - - g.addEdge(f1, t0); - EXPECT_TRUE(g.isReachable(f0, target)); - EXPECT_TRUE(g.isReachable(f1, target)); - EXPECT_FALSE(g.isReachable(f2, target)); - EXPECT_FALSE(g.isReachable(f3, target)); - EXPECT_EQ(g.findPath(f0, target, path, ARRAY_SIZE(path)), 3U); - EXPECT_EQ(path[0], f0); - EXPECT_EQ(path[1], f1); - EXPECT_EQ(path[2], t0); - EXPECT_EQ(g.findPath(f1, target, path, ARRAY_SIZE(path)), 2U); - EXPECT_EQ(path[0], f1); - EXPECT_EQ(path[1], t0); - - g.addEdge(f3, t1); - EXPECT_TRUE(g.isReachable(f0, target)); - EXPECT_TRUE(g.isReachable(f1, target)); - EXPECT_TRUE(g.isReachable(f2, target)); - EXPECT_TRUE(g.isReachable(f3, target)); -} - -TEST(BVGraph, isReachable) { - Test_isReachable<BV1>(); - Test_isReachable<BV2>(); - Test_isReachable<BV3>(); - Test_isReachable<BV4>(); -} - -template <class BV> -void LongCycle() { - BVGraph<BV> g; - g.clear(); - vector<uptr> path_vec(g.size()); - uptr *path = path_vec.data(); - uptr start = 5; - for (uptr i = start; i < g.size() - 1; i++) { - g.addEdge(i, i + 1); - for (uptr j = 0; j < start; j++) - g.addEdge(i, j); - } - // Bad graph that looks like this: - // 00000000000000 - // 00000000000000 - // 00000000000000 - // 00000000000000 - // 00000000000000 - // 11111010000000 - // 11111001000000 - // 11111000100000 - // 11111000010000 - // 11111000001000 - // 11111000000100 - // 11111000000010 - // 11111000000001 - // if (g.size() <= 64) PrintGraph(g); - BV target; - for (uptr i = start + 1; i < g.size(); i += 11) { - // if ((i & (i - 1)) == 0) fprintf(stderr, "Path: : %zd\n", i); - target.clear(); - target.setBit(i); - EXPECT_TRUE(g.isReachable(start, target)); - EXPECT_EQ(g.findPath(start, target, path, g.size()), i - start + 1); - } -} - -TEST(BVGraph, LongCycle) { - LongCycle<BV1>(); - LongCycle<BV2>(); - LongCycle<BV3>(); - LongCycle<BV4>(); -} - -template <class BV> -void ShortestPath() { - uptr path[8]; - BVGraph<BV> g; - g.clear(); - BV t7; - t7.clear(); - t7.setBit(7); - // 1=>2=>3=>4=>5=>6=>7 - // 1=>7 - g.addEdge(1, 2); - g.addEdge(2, 3); - g.addEdge(3, 4); - g.addEdge(4, 5); - g.addEdge(5, 6); - g.addEdge(6, 7); - g.addEdge(1, 7); - EXPECT_TRUE(g.isReachable(1, t7)); - // No path of length 1. - EXPECT_EQ(0U, g.findPath(1, t7, path, 1)); - // Trying to find a path of len 2..6 gives path of len 2. - EXPECT_EQ(2U, g.findPath(1, t7, path, 2)); - EXPECT_EQ(2U, g.findPath(1, t7, path, 3)); - EXPECT_EQ(2U, g.findPath(1, t7, path, 4)); - EXPECT_EQ(2U, g.findPath(1, t7, path, 5)); - EXPECT_EQ(2U, g.findPath(1, t7, path, 6)); - // Trying to find a path of len 7 gives path of len 7, because this is DFS. - EXPECT_EQ(7U, g.findPath(1, t7, path, 7)); - // But findShortestPath will find the shortest path. - EXPECT_EQ(2U, g.findShortestPath(1, t7, path, 2)); - EXPECT_EQ(2U, g.findShortestPath(1, t7, path, 7)); -} - -TEST(BVGraph, ShortestPath) { - ShortestPath<BV1>(); - ShortestPath<BV2>(); - ShortestPath<BV3>(); - ShortestPath<BV4>(); -} - -template <class BV> -void RunAddEdgesTest() { - BVGraph<BV> g; - BV from; - const int kMaxEdges = 10; - uptr added_edges[kMaxEdges]; - g.clear(); - from.clear(); - EXPECT_EQ(0U, g.addEdges(from, 0, added_edges, kMaxEdges)); - EXPECT_EQ(0U, g.addEdges(from, 1, added_edges, kMaxEdges)); - from.setBit(0); - EXPECT_EQ(1U, g.addEdges(from, 1, added_edges, kMaxEdges)); - EXPECT_EQ(0U, added_edges[0]); - EXPECT_EQ(0U, g.addEdges(from, 1, added_edges, kMaxEdges)); - - from.clear(); - from.setBit(1); - EXPECT_EQ(1U, g.addEdges(from, 4, added_edges, kMaxEdges)); - EXPECT_TRUE(g.hasEdge(1, 4)); - EXPECT_FALSE(g.hasEdge(1, 5)); - EXPECT_EQ(1U, added_edges[0]); - from.setBit(2); - from.setBit(3); - EXPECT_EQ(2U, g.addEdges(from, 4, added_edges, kMaxEdges)); - EXPECT_TRUE(g.hasEdge(2, 4)); - EXPECT_FALSE(g.hasEdge(2, 5)); - EXPECT_TRUE(g.hasEdge(3, 4)); - EXPECT_FALSE(g.hasEdge(3, 5)); - EXPECT_EQ(2U, added_edges[0]); - EXPECT_EQ(3U, added_edges[1]); -} - -TEST(BVGraph, AddEdgesTest) { - RunAddEdgesTest<BV2>(); -} diff --git a/lib/sanitizer_common/tests/sanitizer_common_test.cc b/lib/sanitizer_common/tests/sanitizer_common_test.cc deleted file mode 100644 index 6b091de60d6d9..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_common_test.cc +++ /dev/null @@ -1,442 +0,0 @@ -//===-- sanitizer_common_test.cc ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include <algorithm> - -#include "sanitizer_common/sanitizer_allocator_internal.h" -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_file.h" -#include "sanitizer_common/sanitizer_flags.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "sanitizer_common/sanitizer_platform.h" - -#include "sanitizer_pthread_wrappers.h" - -#include "gtest/gtest.h" - -namespace __sanitizer { - -static bool IsSorted(const uptr *array, uptr n) { - for (uptr i = 1; i < n; i++) { - if (array[i] < array[i - 1]) return false; - } - return true; -} - -TEST(SanitizerCommon, SortTest) { - uptr array[100]; - uptr n = 100; - // Already sorted. - for (uptr i = 0; i < n; i++) { - array[i] = i; - } - Sort(array, n); - EXPECT_TRUE(IsSorted(array, n)); - // Reverse order. - for (uptr i = 0; i < n; i++) { - array[i] = n - 1 - i; - } - Sort(array, n); - EXPECT_TRUE(IsSorted(array, n)); - // Mixed order. - for (uptr i = 0; i < n; i++) { - array[i] = (i % 2 == 0) ? i : n - 1 - i; - } - Sort(array, n); - EXPECT_TRUE(IsSorted(array, n)); - // All equal. - for (uptr i = 0; i < n; i++) { - array[i] = 42; - } - Sort(array, n); - EXPECT_TRUE(IsSorted(array, n)); - // All but one sorted. - for (uptr i = 0; i < n - 1; i++) { - array[i] = i; - } - array[n - 1] = 42; - Sort(array, n); - EXPECT_TRUE(IsSorted(array, n)); - // Minimal case - sort three elements. - array[0] = 1; - array[1] = 0; - Sort(array, 2); - EXPECT_TRUE(IsSorted(array, 2)); -} - -TEST(SanitizerCommon, MmapAlignedOrDieOnFatalError) { - uptr PageSize = GetPageSizeCached(); - for (uptr size = 1; size <= 32; size *= 2) { - for (uptr alignment = 1; alignment <= 32; alignment *= 2) { - for (int iter = 0; iter < 100; iter++) { - uptr res = (uptr)MmapAlignedOrDieOnFatalError( - size * PageSize, alignment * PageSize, "MmapAlignedOrDieTest"); - EXPECT_EQ(0U, res % (alignment * PageSize)); - internal_memset((void*)res, 1, size * PageSize); - UnmapOrDie((void*)res, size * PageSize); - } - } - } -} - -TEST(SanitizerCommon, InternalMmapVectorRoundUpCapacity) { - InternalMmapVector<uptr> v; - v.reserve(1); - CHECK_EQ(v.capacity(), GetPageSizeCached() / sizeof(uptr)); -} - -TEST(SanitizerCommon, InternalMmapVectorReize) { - InternalMmapVector<uptr> v; - CHECK_EQ(0U, v.size()); - CHECK_GE(v.capacity(), v.size()); - - v.reserve(1000); - CHECK_EQ(0U, v.size()); - CHECK_GE(v.capacity(), 1000U); - - v.resize(10000); - CHECK_EQ(10000U, v.size()); - CHECK_GE(v.capacity(), v.size()); - uptr cap = v.capacity(); - - v.resize(100); - CHECK_EQ(100U, v.size()); - CHECK_EQ(v.capacity(), cap); - - v.reserve(10); - CHECK_EQ(100U, v.size()); - CHECK_EQ(v.capacity(), cap); -} - -TEST(SanitizerCommon, InternalMmapVector) { - InternalMmapVector<uptr> vector; - for (uptr i = 0; i < 100; i++) { - EXPECT_EQ(i, vector.size()); - vector.push_back(i); - } - for (uptr i = 0; i < 100; i++) { - EXPECT_EQ(i, vector[i]); - } - for (int i = 99; i >= 0; i--) { - EXPECT_EQ((uptr)i, vector.back()); - vector.pop_back(); - EXPECT_EQ((uptr)i, vector.size()); - } - InternalMmapVector<uptr> empty_vector; - CHECK_GT(empty_vector.capacity(), 0U); - CHECK_EQ(0U, empty_vector.size()); -} - -TEST(SanitizerCommon, InternalMmapVectorEq) { - InternalMmapVector<uptr> vector1; - InternalMmapVector<uptr> vector2; - for (uptr i = 0; i < 100; i++) { - vector1.push_back(i); - vector2.push_back(i); - } - EXPECT_TRUE(vector1 == vector2); - EXPECT_FALSE(vector1 != vector2); - - vector1.push_back(1); - EXPECT_FALSE(vector1 == vector2); - EXPECT_TRUE(vector1 != vector2); - - vector2.push_back(1); - EXPECT_TRUE(vector1 == vector2); - EXPECT_FALSE(vector1 != vector2); - - vector1[55] = 1; - EXPECT_FALSE(vector1 == vector2); - EXPECT_TRUE(vector1 != vector2); -} - -TEST(SanitizerCommon, InternalMmapVectorSwap) { - InternalMmapVector<uptr> vector1; - InternalMmapVector<uptr> vector2; - InternalMmapVector<uptr> vector3; - InternalMmapVector<uptr> vector4; - for (uptr i = 0; i < 100; i++) { - vector1.push_back(i); - vector2.push_back(i); - vector3.push_back(-i); - vector4.push_back(-i); - } - EXPECT_NE(vector2, vector3); - EXPECT_NE(vector1, vector4); - vector1.swap(vector3); - EXPECT_EQ(vector2, vector3); - EXPECT_EQ(vector1, vector4); -} - -void TestThreadInfo(bool main) { - uptr stk_addr = 0; - uptr stk_size = 0; - uptr tls_addr = 0; - uptr tls_size = 0; - GetThreadStackAndTls(main, &stk_addr, &stk_size, &tls_addr, &tls_size); - - int stack_var; - EXPECT_NE(stk_addr, (uptr)0); - EXPECT_NE(stk_size, (uptr)0); - EXPECT_GT((uptr)&stack_var, stk_addr); - EXPECT_LT((uptr)&stack_var, stk_addr + stk_size); - -#if SANITIZER_LINUX && defined(__x86_64__) - static __thread int thread_var; - EXPECT_NE(tls_addr, (uptr)0); - EXPECT_NE(tls_size, (uptr)0); - EXPECT_GT((uptr)&thread_var, tls_addr); - EXPECT_LT((uptr)&thread_var, tls_addr + tls_size); - - // Ensure that tls and stack do not intersect. - uptr tls_end = tls_addr + tls_size; - EXPECT_TRUE(tls_addr < stk_addr || tls_addr >= stk_addr + stk_size); - EXPECT_TRUE(tls_end < stk_addr || tls_end >= stk_addr + stk_size); - EXPECT_TRUE((tls_addr < stk_addr) == (tls_end < stk_addr)); -#endif -} - -static void *WorkerThread(void *arg) { - TestThreadInfo(false); - return 0; -} - -TEST(SanitizerCommon, ThreadStackTlsMain) { - InitTlsSize(); - TestThreadInfo(true); -} - -TEST(SanitizerCommon, ThreadStackTlsWorker) { - InitTlsSize(); - pthread_t t; - PTHREAD_CREATE(&t, 0, WorkerThread, 0); - PTHREAD_JOIN(t, 0); -} - -bool UptrLess(uptr a, uptr b) { - return a < b; -} - -TEST(SanitizerCommon, InternalLowerBound) { - static const uptr kSize = 5; - int arr[kSize]; - arr[0] = 1; - arr[1] = 3; - arr[2] = 5; - arr[3] = 7; - arr[4] = 11; - - EXPECT_EQ(0u, InternalLowerBound(arr, 0, kSize, 0, UptrLess)); - EXPECT_EQ(0u, InternalLowerBound(arr, 0, kSize, 1, UptrLess)); - EXPECT_EQ(1u, InternalLowerBound(arr, 0, kSize, 2, UptrLess)); - EXPECT_EQ(1u, InternalLowerBound(arr, 0, kSize, 3, UptrLess)); - EXPECT_EQ(2u, InternalLowerBound(arr, 0, kSize, 4, UptrLess)); - EXPECT_EQ(2u, InternalLowerBound(arr, 0, kSize, 5, UptrLess)); - EXPECT_EQ(3u, InternalLowerBound(arr, 0, kSize, 6, UptrLess)); - EXPECT_EQ(3u, InternalLowerBound(arr, 0, kSize, 7, UptrLess)); - EXPECT_EQ(4u, InternalLowerBound(arr, 0, kSize, 8, UptrLess)); - EXPECT_EQ(4u, InternalLowerBound(arr, 0, kSize, 9, UptrLess)); - EXPECT_EQ(4u, InternalLowerBound(arr, 0, kSize, 10, UptrLess)); - EXPECT_EQ(4u, InternalLowerBound(arr, 0, kSize, 11, UptrLess)); - EXPECT_EQ(5u, InternalLowerBound(arr, 0, kSize, 12, UptrLess)); -} - -TEST(SanitizerCommon, InternalLowerBoundVsStdLowerBound) { - std::vector<int> data; - auto create_item = [] (size_t i, size_t j) { - auto v = i * 10000 + j; - return ((v << 6) + (v >> 6) + 0x9e3779b9) % 100; - }; - for (size_t i = 0; i < 1000; ++i) { - data.resize(i); - for (size_t j = 0; j < i; ++j) { - data[j] = create_item(i, j); - } - - std::sort(data.begin(), data.end()); - - for (size_t j = 0; j < i; ++j) { - int val = create_item(i, j); - for (auto to_find : {val - 1, val, val + 1}) { - uptr expected = - std::lower_bound(data.begin(), data.end(), to_find) - data.begin(); - EXPECT_EQ(expected, InternalLowerBound(data.data(), 0, data.size(), - to_find, std::less<int>())); - } - } - } -} - -#if SANITIZER_LINUX && !SANITIZER_ANDROID -TEST(SanitizerCommon, FindPathToBinary) { - char *true_path = FindPathToBinary("true"); - EXPECT_NE((char*)0, internal_strstr(true_path, "/bin/true")); - InternalFree(true_path); - EXPECT_EQ(0, FindPathToBinary("unexisting_binary.ergjeorj")); -} -#elif SANITIZER_WINDOWS -TEST(SanitizerCommon, FindPathToBinary) { - // ntdll.dll should be on PATH in all supported test environments on all - // supported Windows versions. - char *ntdll_path = FindPathToBinary("ntdll.dll"); - EXPECT_NE((char*)0, internal_strstr(ntdll_path, "ntdll.dll")); - InternalFree(ntdll_path); - EXPECT_EQ(0, FindPathToBinary("unexisting_binary.ergjeorj")); -} -#endif - -TEST(SanitizerCommon, StripPathPrefix) { - EXPECT_EQ(0, StripPathPrefix(0, "prefix")); - EXPECT_STREQ("foo", StripPathPrefix("foo", 0)); - EXPECT_STREQ("dir/file.cc", - StripPathPrefix("/usr/lib/dir/file.cc", "/usr/lib/")); - EXPECT_STREQ("/file.cc", StripPathPrefix("/usr/myroot/file.cc", "/myroot")); - EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/")); -} - -TEST(SanitizerCommon, RemoveANSIEscapeSequencesFromString) { - RemoveANSIEscapeSequencesFromString(nullptr); - const char *buffs[22] = { - "Default", "Default", - "\033[95mLight magenta", "Light magenta", - "\033[30mBlack\033[32mGreen\033[90mGray", "BlackGreenGray", - "\033[106mLight cyan \033[107mWhite ", "Light cyan White ", - "\033[31mHello\033[0m World", "Hello World", - "\033[38;5;82mHello \033[38;5;198mWorld", "Hello World", - "123[653456789012", "123[653456789012", - "Normal \033[5mBlink \033[25mNormal", "Normal Blink Normal", - "\033[106m\033[107m", "", - "", "", - " ", " ", - }; - - for (size_t i = 0; i < ARRAY_SIZE(buffs); i+=2) { - char *buffer_copy = internal_strdup(buffs[i]); - RemoveANSIEscapeSequencesFromString(buffer_copy); - EXPECT_STREQ(buffer_copy, buffs[i+1]); - InternalFree(buffer_copy); - } -} - -TEST(SanitizerCommon, InternalScopedString) { - InternalScopedString str(10); - EXPECT_EQ(0U, str.length()); - EXPECT_STREQ("", str.data()); - - str.append("foo"); - EXPECT_EQ(3U, str.length()); - EXPECT_STREQ("foo", str.data()); - - int x = 1234; - str.append("%d", x); - EXPECT_EQ(7U, str.length()); - EXPECT_STREQ("foo1234", str.data()); - - str.append("%d", x); - EXPECT_EQ(9U, str.length()); - EXPECT_STREQ("foo123412", str.data()); - - str.clear(); - EXPECT_EQ(0U, str.length()); - EXPECT_STREQ("", str.data()); - - str.append("0123456789"); - EXPECT_EQ(9U, str.length()); - EXPECT_STREQ("012345678", str.data()); -} - -#if SANITIZER_LINUX || SANITIZER_FREEBSD || \ - SANITIZER_OPENBSD || SANITIZER_MAC || SANITIZER_IOS -TEST(SanitizerCommon, GetRandom) { - u8 buffer_1[32], buffer_2[32]; - for (bool blocking : { false, true }) { - EXPECT_FALSE(GetRandom(nullptr, 32, blocking)); - EXPECT_FALSE(GetRandom(buffer_1, 0, blocking)); - EXPECT_FALSE(GetRandom(buffer_1, 512, blocking)); - EXPECT_EQ(ARRAY_SIZE(buffer_1), ARRAY_SIZE(buffer_2)); - for (uptr size = 4; size <= ARRAY_SIZE(buffer_1); size += 4) { - for (uptr i = 0; i < 100; i++) { - EXPECT_TRUE(GetRandom(buffer_1, size, blocking)); - EXPECT_TRUE(GetRandom(buffer_2, size, blocking)); - EXPECT_NE(internal_memcmp(buffer_1, buffer_2, size), 0); - } - } - } -} -#endif - -TEST(SanitizerCommon, ReservedAddressRangeInit) { - uptr init_size = 0xffff; - ReservedAddressRange address_range; - uptr res = address_range.Init(init_size); - CHECK_NE(res, (void*)-1); - UnmapOrDie((void*)res, init_size); - // Should be able to map into the same space now. - ReservedAddressRange address_range2; - uptr res2 = address_range2.Init(init_size, nullptr, res); - CHECK_EQ(res, res2); - - // TODO(flowerhack): Once this is switched to the "real" implementation - // (rather than passing through to MmapNoAccess*), enforce and test "no - // double initializations allowed" -} - -TEST(SanitizerCommon, ReservedAddressRangeMap) { - constexpr uptr init_size = 0xffff; - ReservedAddressRange address_range; - uptr res = address_range.Init(init_size); - CHECK_NE(res, (void*) -1); - - // Valid mappings should succeed. - CHECK_EQ(res, address_range.Map(res, init_size)); - - // Valid mappings should be readable. - unsigned char buffer[init_size]; - memcpy(buffer, reinterpret_cast<void *>(res), init_size); - - // TODO(flowerhack): Once this is switched to the "real" implementation, make - // sure you can only mmap into offsets in the Init range. -} - -TEST(SanitizerCommon, ReservedAddressRangeUnmap) { - uptr PageSize = GetPageSizeCached(); - uptr init_size = PageSize * 8; - ReservedAddressRange address_range; - uptr base_addr = address_range.Init(init_size); - CHECK_NE(base_addr, (void*)-1); - CHECK_EQ(base_addr, address_range.Map(base_addr, init_size)); - - // Unmapping the entire range should succeed. - address_range.Unmap(base_addr, init_size); - - // Map a new range. - base_addr = address_range.Init(init_size); - CHECK_EQ(base_addr, address_range.Map(base_addr, init_size)); - - // Windows doesn't allow partial unmappings. - #if !SANITIZER_WINDOWS - - // Unmapping at the beginning should succeed. - address_range.Unmap(base_addr, PageSize); - - // Unmapping at the end should succeed. - uptr new_start = reinterpret_cast<uptr>(address_range.base()) + - address_range.size() - PageSize; - address_range.Unmap(new_start, PageSize); - - #endif - - // Unmapping in the middle of the ReservedAddressRange should fail. - EXPECT_DEATH(address_range.Unmap(base_addr + (PageSize * 2), PageSize), ".*"); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc b/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc deleted file mode 100644 index 7835eef76d063..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_deadlock_detector_test.cc +++ /dev/null @@ -1,496 +0,0 @@ -//===-- sanitizer_deadlock_detector_test.cc -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of Sanitizer runtime. -// Tests for sanitizer_deadlock_detector.h -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_deadlock_detector.h" - -#include "sanitizer_test_utils.h" - -#include "gtest/gtest.h" - -#include <algorithm> -#include <vector> -#include <set> - -using namespace __sanitizer; -using namespace std; - -typedef BasicBitVector<u8> BV1; -typedef BasicBitVector<> BV2; -typedef TwoLevelBitVector<> BV3; -typedef TwoLevelBitVector<3, BasicBitVector<u8> > BV4; - -// Poor man's unique_ptr. -template<class BV> -struct ScopedDD { - ScopedDD() { - dp = new DeadlockDetector<BV>; - dp->clear(); - dtls.clear(); - } - ~ScopedDD() { delete dp; } - DeadlockDetector<BV> *dp; - DeadlockDetectorTLS<BV> dtls; -}; - -template <class BV> -void RunBasicTest() { - uptr path[10]; - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - set<uptr> s; - for (size_t i = 0; i < d.size() * 3; i++) { - uptr node = d.newNode(0); - EXPECT_TRUE(s.insert(node).second); - } - - d.clear(); - s.clear(); - // Add size() nodes. - for (size_t i = 0; i < d.size(); i++) { - uptr node = d.newNode(0); - EXPECT_TRUE(s.insert(node).second); - } - // Remove all nodes. - for (set<uptr>::iterator it = s.begin(); it != s.end(); ++it) - d.removeNode(*it); - // The nodes should be reused. - for (size_t i = 0; i < d.size(); i++) { - uptr node = d.newNode(0); - EXPECT_FALSE(s.insert(node).second); - } - - // Cycle: n1->n2->n1 - { - d.clear(); - dtls.clear(); - uptr n1 = d.newNode(1); - uptr n2 = d.newNode(2); - EXPECT_FALSE(d.onLock(&dtls, n1)); - EXPECT_FALSE(d.onLock(&dtls, n2)); - d.onUnlock(&dtls, n2); - d.onUnlock(&dtls, n1); - - EXPECT_FALSE(d.onLock(&dtls, n2)); - EXPECT_EQ(0U, d.findPathToLock(&dtls, n1, path, 1)); - EXPECT_EQ(2U, d.findPathToLock(&dtls, n1, path, 10)); - EXPECT_EQ(2U, d.findPathToLock(&dtls, n1, path, 2)); - EXPECT_TRUE(d.onLock(&dtls, n1)); - EXPECT_EQ(path[0], n1); - EXPECT_EQ(path[1], n2); - EXPECT_EQ(d.getData(n1), 1U); - EXPECT_EQ(d.getData(n2), 2U); - d.onUnlock(&dtls, n1); - d.onUnlock(&dtls, n2); - } - - // Cycle: n1->n2->n3->n1 - { - d.clear(); - dtls.clear(); - uptr n1 = d.newNode(1); - uptr n2 = d.newNode(2); - uptr n3 = d.newNode(3); - - EXPECT_FALSE(d.onLock(&dtls, n1)); - EXPECT_FALSE(d.onLock(&dtls, n2)); - d.onUnlock(&dtls, n2); - d.onUnlock(&dtls, n1); - - EXPECT_FALSE(d.onLock(&dtls, n2)); - EXPECT_FALSE(d.onLock(&dtls, n3)); - d.onUnlock(&dtls, n3); - d.onUnlock(&dtls, n2); - - EXPECT_FALSE(d.onLock(&dtls, n3)); - EXPECT_EQ(0U, d.findPathToLock(&dtls, n1, path, 2)); - EXPECT_EQ(3U, d.findPathToLock(&dtls, n1, path, 10)); - EXPECT_TRUE(d.onLock(&dtls, n1)); - EXPECT_EQ(path[0], n1); - EXPECT_EQ(path[1], n2); - EXPECT_EQ(path[2], n3); - EXPECT_EQ(d.getData(n1), 1U); - EXPECT_EQ(d.getData(n2), 2U); - EXPECT_EQ(d.getData(n3), 3U); - d.onUnlock(&dtls, n1); - d.onUnlock(&dtls, n3); - } -} - -TEST(DeadlockDetector, BasicTest) { - RunBasicTest<BV1>(); - RunBasicTest<BV2>(); - RunBasicTest<BV3>(); - RunBasicTest<BV4>(); -} - -template <class BV> -void RunRemoveNodeTest() { - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - - uptr l0 = d.newNode(0); - uptr l1 = d.newNode(1); - uptr l2 = d.newNode(2); - uptr l3 = d.newNode(3); - uptr l4 = d.newNode(4); - uptr l5 = d.newNode(5); - - // l0=>l1=>l2 - d.onLock(&dtls, l0); - d.onLock(&dtls, l1); - d.onLock(&dtls, l2); - d.onUnlock(&dtls, l1); - d.onUnlock(&dtls, l0); - d.onUnlock(&dtls, l2); - // l3=>l4=>l5 - d.onLock(&dtls, l3); - d.onLock(&dtls, l4); - d.onLock(&dtls, l5); - d.onUnlock(&dtls, l4); - d.onUnlock(&dtls, l3); - d.onUnlock(&dtls, l5); - - set<uptr> locks; - locks.insert(l0); - locks.insert(l1); - locks.insert(l2); - locks.insert(l3); - locks.insert(l4); - locks.insert(l5); - for (uptr i = 6; i < d.size(); i++) { - uptr lt = d.newNode(i); - locks.insert(lt); - d.onLock(&dtls, lt); - d.onUnlock(&dtls, lt); - d.removeNode(lt); - } - EXPECT_EQ(locks.size(), d.size()); - // l2=>l0 - EXPECT_FALSE(d.onLock(&dtls, l2)); - EXPECT_TRUE(d.onLock(&dtls, l0)); - d.onUnlock(&dtls, l2); - d.onUnlock(&dtls, l0); - // l4=>l3 - EXPECT_FALSE(d.onLock(&dtls, l4)); - EXPECT_TRUE(d.onLock(&dtls, l3)); - d.onUnlock(&dtls, l4); - d.onUnlock(&dtls, l3); - - EXPECT_EQ(d.size(), d.testOnlyGetEpoch()); - - d.removeNode(l2); - d.removeNode(l3); - locks.clear(); - // make sure no edges from or to l0,l1,l4,l5 left. - for (uptr i = 4; i < d.size(); i++) { - uptr lt = d.newNode(i); - locks.insert(lt); - uptr a, b; - // l0 => lt? - a = l0; b = lt; - EXPECT_FALSE(d.onLock(&dtls, a)); - EXPECT_FALSE(d.onLock(&dtls, b)); - d.onUnlock(&dtls, a); - d.onUnlock(&dtls, b); - // l1 => lt? - a = l1; b = lt; - EXPECT_FALSE(d.onLock(&dtls, a)); - EXPECT_FALSE(d.onLock(&dtls, b)); - d.onUnlock(&dtls, a); - d.onUnlock(&dtls, b); - // lt => l4? - a = lt; b = l4; - EXPECT_FALSE(d.onLock(&dtls, a)); - EXPECT_FALSE(d.onLock(&dtls, b)); - d.onUnlock(&dtls, a); - d.onUnlock(&dtls, b); - // lt => l5? - a = lt; b = l5; - EXPECT_FALSE(d.onLock(&dtls, a)); - EXPECT_FALSE(d.onLock(&dtls, b)); - d.onUnlock(&dtls, a); - d.onUnlock(&dtls, b); - - d.removeNode(lt); - } - // Still the same epoch. - EXPECT_EQ(d.size(), d.testOnlyGetEpoch()); - EXPECT_EQ(locks.size(), d.size() - 4); - // l2 and l3 should have ben reused. - EXPECT_EQ(locks.count(l2), 1U); - EXPECT_EQ(locks.count(l3), 1U); -} - -TEST(DeadlockDetector, RemoveNodeTest) { - RunRemoveNodeTest<BV1>(); - RunRemoveNodeTest<BV2>(); - RunRemoveNodeTest<BV3>(); - RunRemoveNodeTest<BV4>(); -} - -template <class BV> -void RunMultipleEpochsTest() { - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - - set<uptr> locks; - for (uptr i = 0; i < d.size(); i++) { - EXPECT_TRUE(locks.insert(d.newNode(i)).second); - } - EXPECT_EQ(d.testOnlyGetEpoch(), d.size()); - for (uptr i = 0; i < d.size(); i++) { - EXPECT_TRUE(locks.insert(d.newNode(i)).second); - EXPECT_EQ(d.testOnlyGetEpoch(), d.size() * 2); - } - locks.clear(); - - uptr l0 = d.newNode(0); - uptr l1 = d.newNode(0); - d.onLock(&dtls, l0); - d.onLock(&dtls, l1); - d.onUnlock(&dtls, l0); - EXPECT_EQ(d.testOnlyGetEpoch(), 3 * d.size()); - for (uptr i = 0; i < d.size(); i++) { - EXPECT_TRUE(locks.insert(d.newNode(i)).second); - } - EXPECT_EQ(d.testOnlyGetEpoch(), 4 * d.size()); - -#if !SANITIZER_DEBUG - // EXPECT_DEATH clones a thread with 4K stack, - // which is overflown by tsan memory accesses functions in debug mode. - - // Can not handle the locks from the previous epoch. - // The caller should update the lock id. - EXPECT_DEATH(d.onLock(&dtls, l0), "CHECK failed.*current_epoch_"); -#endif -} - -TEST(DeadlockDetector, MultipleEpochsTest) { - RunMultipleEpochsTest<BV1>(); - RunMultipleEpochsTest<BV2>(); - RunMultipleEpochsTest<BV3>(); - RunMultipleEpochsTest<BV4>(); -} - -template <class BV> -void RunCorrectEpochFlush() { - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - vector<uptr> locks1; - for (uptr i = 0; i < d.size(); i++) - locks1.push_back(d.newNode(i)); - EXPECT_EQ(d.testOnlyGetEpoch(), d.size()); - d.onLock(&dtls, locks1[3]); - d.onLock(&dtls, locks1[4]); - d.onLock(&dtls, locks1[5]); - - // We have a new epoch, old locks in dtls will have to be forgotten. - uptr l0 = d.newNode(0); - EXPECT_EQ(d.testOnlyGetEpoch(), d.size() * 2); - uptr l1 = d.newNode(0); - EXPECT_EQ(d.testOnlyGetEpoch(), d.size() * 2); - d.onLock(&dtls, l0); - d.onLock(&dtls, l1); - EXPECT_TRUE(d.testOnlyHasEdgeRaw(0, 1)); - EXPECT_FALSE(d.testOnlyHasEdgeRaw(1, 0)); - EXPECT_FALSE(d.testOnlyHasEdgeRaw(3, 0)); - EXPECT_FALSE(d.testOnlyHasEdgeRaw(4, 0)); - EXPECT_FALSE(d.testOnlyHasEdgeRaw(5, 0)); -} - -TEST(DeadlockDetector, CorrectEpochFlush) { - RunCorrectEpochFlush<BV1>(); - RunCorrectEpochFlush<BV2>(); -} - -template <class BV> -void RunTryLockTest() { - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - - uptr l0 = d.newNode(0); - uptr l1 = d.newNode(0); - uptr l2 = d.newNode(0); - EXPECT_FALSE(d.onLock(&dtls, l0)); - EXPECT_FALSE(d.onTryLock(&dtls, l1)); - EXPECT_FALSE(d.onLock(&dtls, l2)); - EXPECT_TRUE(d.isHeld(&dtls, l0)); - EXPECT_TRUE(d.isHeld(&dtls, l1)); - EXPECT_TRUE(d.isHeld(&dtls, l2)); - EXPECT_FALSE(d.testOnlyHasEdge(l0, l1)); - EXPECT_TRUE(d.testOnlyHasEdge(l1, l2)); - d.onUnlock(&dtls, l0); - d.onUnlock(&dtls, l1); - d.onUnlock(&dtls, l2); -} - -TEST(DeadlockDetector, TryLockTest) { - RunTryLockTest<BV1>(); - RunTryLockTest<BV2>(); -} - -template <class BV> -void RunOnFirstLockTest() { - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - - uptr l0 = d.newNode(0); - uptr l1 = d.newNode(0); - EXPECT_FALSE(d.onFirstLock(&dtls, l0)); // dtls has old epoch. - d.onLock(&dtls, l0); - d.onUnlock(&dtls, l0); - - EXPECT_TRUE(d.onFirstLock(&dtls, l0)); // Ok, same ecpoch, first lock. - EXPECT_FALSE(d.onFirstLock(&dtls, l1)); // Second lock. - d.onLock(&dtls, l1); - d.onUnlock(&dtls, l1); - d.onUnlock(&dtls, l0); - - EXPECT_TRUE(d.onFirstLock(&dtls, l0)); // Ok - d.onUnlock(&dtls, l0); - - vector<uptr> locks1; - for (uptr i = 0; i < d.size(); i++) - locks1.push_back(d.newNode(i)); - - EXPECT_TRUE(d.onFirstLock(&dtls, l0)); // Epoch has changed, but not in dtls. - - uptr l3 = d.newNode(0); - d.onLock(&dtls, l3); - d.onUnlock(&dtls, l3); - - EXPECT_FALSE(d.onFirstLock(&dtls, l0)); // Epoch has changed in dtls. -} - -TEST(DeadlockDetector, onFirstLockTest) { - RunOnFirstLockTest<BV2>(); -} - -template <class BV> -void RunRecusriveLockTest() { - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - - uptr l0 = d.newNode(0); - uptr l1 = d.newNode(0); - uptr l2 = d.newNode(0); - uptr l3 = d.newNode(0); - - EXPECT_FALSE(d.onLock(&dtls, l0)); - EXPECT_FALSE(d.onLock(&dtls, l1)); - EXPECT_FALSE(d.onLock(&dtls, l0)); // Recurisve. - EXPECT_FALSE(d.onLock(&dtls, l2)); - d.onUnlock(&dtls, l0); - EXPECT_FALSE(d.onLock(&dtls, l3)); - d.onUnlock(&dtls, l0); - d.onUnlock(&dtls, l1); - d.onUnlock(&dtls, l2); - d.onUnlock(&dtls, l3); - EXPECT_TRUE(d.testOnlyHasEdge(l0, l1)); - EXPECT_TRUE(d.testOnlyHasEdge(l0, l2)); - EXPECT_TRUE(d.testOnlyHasEdge(l0, l3)); -} - -TEST(DeadlockDetector, RecusriveLockTest) { - RunRecusriveLockTest<BV2>(); -} - -template <class BV> -void RunLockContextTest() { - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - - uptr l0 = d.newNode(0); - uptr l1 = d.newNode(0); - uptr l2 = d.newNode(0); - uptr l3 = d.newNode(0); - uptr l4 = d.newNode(0); - EXPECT_FALSE(d.onLock(&dtls, l0, 10)); - EXPECT_FALSE(d.onLock(&dtls, l1, 11)); - EXPECT_FALSE(d.onLock(&dtls, l2, 12)); - EXPECT_FALSE(d.onLock(&dtls, l3, 13)); - EXPECT_EQ(10U, d.findLockContext(&dtls, l0)); - EXPECT_EQ(11U, d.findLockContext(&dtls, l1)); - EXPECT_EQ(12U, d.findLockContext(&dtls, l2)); - EXPECT_EQ(13U, d.findLockContext(&dtls, l3)); - d.onUnlock(&dtls, l0); - EXPECT_EQ(0U, d.findLockContext(&dtls, l0)); - EXPECT_EQ(11U, d.findLockContext(&dtls, l1)); - EXPECT_EQ(12U, d.findLockContext(&dtls, l2)); - EXPECT_EQ(13U, d.findLockContext(&dtls, l3)); - d.onUnlock(&dtls, l2); - EXPECT_EQ(0U, d.findLockContext(&dtls, l0)); - EXPECT_EQ(11U, d.findLockContext(&dtls, l1)); - EXPECT_EQ(0U, d.findLockContext(&dtls, l2)); - EXPECT_EQ(13U, d.findLockContext(&dtls, l3)); - - EXPECT_FALSE(d.onLock(&dtls, l4, 14)); - EXPECT_EQ(14U, d.findLockContext(&dtls, l4)); -} - -TEST(DeadlockDetector, LockContextTest) { - RunLockContextTest<BV2>(); -} - -template <class BV> -void RunRemoveEdgesTest() { - ScopedDD<BV> sdd; - DeadlockDetector<BV> &d = *sdd.dp; - DeadlockDetectorTLS<BV> &dtls = sdd.dtls; - vector<uptr> node(BV::kSize); - u32 stk_from = 0, stk_to = 0; - int unique_tid = 0; - for (size_t i = 0; i < BV::kSize; i++) - node[i] = d.newNode(0); - - for (size_t i = 0; i < BV::kSize; i++) - EXPECT_FALSE(d.onLock(&dtls, node[i], i + 1)); - for (size_t i = 0; i < BV::kSize; i++) { - for (uptr j = i + 1; j < BV::kSize; j++) { - EXPECT_TRUE( - d.findEdge(node[i], node[j], &stk_from, &stk_to, &unique_tid)); - EXPECT_EQ(stk_from, i + 1); - EXPECT_EQ(stk_to, j + 1); - } - } - EXPECT_EQ(d.testOnlyGetEpoch(), d.size()); - // Remove and re-create half of the nodes. - for (uptr i = 1; i < BV::kSize; i += 2) - d.removeNode(node[i]); - for (uptr i = 1; i < BV::kSize; i += 2) - node[i] = d.newNode(0); - EXPECT_EQ(d.testOnlyGetEpoch(), d.size()); - // The edges from or to the removed nodes should be gone. - for (size_t i = 0; i < BV::kSize; i++) { - for (uptr j = i + 1; j < BV::kSize; j++) { - if ((i % 2) || (j % 2)) - EXPECT_FALSE( - d.findEdge(node[i], node[j], &stk_from, &stk_to, &unique_tid)); - else - EXPECT_TRUE( - d.findEdge(node[i], node[j], &stk_from, &stk_to, &unique_tid)); - } - } -} - -TEST(DeadlockDetector, RemoveEdgesTest) { - RunRemoveEdgesTest<BV1>(); -} diff --git a/lib/sanitizer_common/tests/sanitizer_flags_test.cc b/lib/sanitizer_common/tests/sanitizer_flags_test.cc deleted file mode 100644 index f3fe139e6ee87..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_flags_test.cc +++ /dev/null @@ -1,180 +0,0 @@ -//===-- sanitizer_flags_test.cc -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_flags.h" -#include "sanitizer_common/sanitizer_flag_parser.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "sanitizer_common/sanitizer_allocator_internal.h" -#include "gtest/gtest.h" - -#include <string.h> - -namespace __sanitizer { - -static const char kFlagName[] = "flag_name"; -static const char kFlagDesc[] = "flag description"; - -template <typename T> -static void TestFlag(T start_value, const char *env, T final_value) { - T flag = start_value; - - FlagParser parser; - RegisterFlag(&parser, kFlagName, kFlagDesc, &flag); - - parser.ParseString(env); - - EXPECT_EQ(final_value, flag); -} - -template <> -void TestFlag(const char *start_value, const char *env, - const char *final_value) { - const char *flag = start_value; - - FlagParser parser; - RegisterFlag(&parser, kFlagName, kFlagDesc, &flag); - - parser.ParseString(env); - - EXPECT_EQ(0, internal_strcmp(final_value, flag)); - - // Reporting unrecognized flags is needed to reset them. - ReportUnrecognizedFlags(); -} - -TEST(SanitizerCommon, BooleanFlags) { - TestFlag(false, "flag_name=1", true); - TestFlag(false, "flag_name=yes", true); - TestFlag(false, "flag_name=true", true); - TestFlag(true, "flag_name=0", false); - TestFlag(true, "flag_name=no", false); - TestFlag(true, "flag_name=false", false); - - EXPECT_DEATH(TestFlag(false, "flag_name", true), "expected '='"); - EXPECT_DEATH(TestFlag(false, "flag_name=", true), - "Invalid value for bool option: ''"); - EXPECT_DEATH(TestFlag(false, "flag_name=2", true), - "Invalid value for bool option: '2'"); - EXPECT_DEATH(TestFlag(false, "flag_name=-1", true), - "Invalid value for bool option: '-1'"); - EXPECT_DEATH(TestFlag(false, "flag_name=on", true), - "Invalid value for bool option: 'on'"); -} - -TEST(SanitizerCommon, HandleSignalMode) { - TestFlag(kHandleSignalNo, "flag_name=1", kHandleSignalYes); - TestFlag(kHandleSignalNo, "flag_name=yes", kHandleSignalYes); - TestFlag(kHandleSignalNo, "flag_name=true", kHandleSignalYes); - TestFlag(kHandleSignalYes, "flag_name=0", kHandleSignalNo); - TestFlag(kHandleSignalYes, "flag_name=no", kHandleSignalNo); - TestFlag(kHandleSignalYes, "flag_name=false", kHandleSignalNo); - TestFlag(kHandleSignalNo, "flag_name=2", kHandleSignalExclusive); - TestFlag(kHandleSignalYes, "flag_name=exclusive", kHandleSignalExclusive); - - EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name", kHandleSignalNo), - "expected '='"); - EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=", kHandleSignalNo), - "Invalid value for signal handler option: ''"); - EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=3", kHandleSignalNo), - "Invalid value for signal handler option: '3'"); - EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=-1", kHandleSignalNo), - "Invalid value for signal handler option: '-1'"); - EXPECT_DEATH(TestFlag(kHandleSignalNo, "flag_name=on", kHandleSignalNo), - "Invalid value for signal handler option: 'on'"); -} - -TEST(SanitizerCommon, IntFlags) { - TestFlag(-11, 0, -11); - TestFlag(-11, "flag_name=0", 0); - TestFlag(-11, "flag_name=42", 42); - TestFlag(-11, "flag_name=-42", -42); - - // Unrecognized flags are ignored. - TestFlag(-11, "--flag_name=42", -11); - TestFlag(-11, "zzzzzzz=42", -11); - - EXPECT_DEATH(TestFlag(-11, "flag_name", 0), "expected '='"); - EXPECT_DEATH(TestFlag(-11, "flag_name=42U", 0), - "Invalid value for int option"); -} - -TEST(SanitizerCommon, StrFlags) { - TestFlag("zzz", 0, "zzz"); - TestFlag("zzz", "flag_name=", ""); - TestFlag("zzz", "flag_name=abc", "abc"); - TestFlag("", "flag_name=abc", "abc"); - TestFlag("", "flag_name='abc zxc'", "abc zxc"); - // TestStrFlag("", "flag_name=\"abc qwe\" asd", "abc qwe"); -} - -static void TestTwoFlags(const char *env, bool expected_flag1, - const char *expected_flag2, - const char *name1 = "flag1", - const char *name2 = "flag2") { - bool flag1 = !expected_flag1; - const char *flag2 = ""; - - FlagParser parser; - RegisterFlag(&parser, name1, kFlagDesc, &flag1); - RegisterFlag(&parser, name2, kFlagDesc, &flag2); - - parser.ParseString(env); - - EXPECT_EQ(expected_flag1, flag1); - EXPECT_EQ(0, internal_strcmp(flag2, expected_flag2)); - - // Reporting unrecognized flags is needed to reset them. - ReportUnrecognizedFlags(); -} - -TEST(SanitizerCommon, MultipleFlags) { - TestTwoFlags("flag1=1 flag2='zzz'", true, "zzz"); - TestTwoFlags("flag2='qxx' flag1=0", false, "qxx"); - TestTwoFlags("flag1=false:flag2='zzz'", false, "zzz"); - TestTwoFlags("flag2=qxx:flag1=yes", true, "qxx"); - TestTwoFlags("flag2=qxx\nflag1=yes", true, "qxx"); - TestTwoFlags("flag2=qxx\r\nflag1=yes", true, "qxx"); - TestTwoFlags("flag2=qxx\tflag1=yes", true, "qxx"); -} - -TEST(SanitizerCommon, CommonSuffixFlags) { - TestTwoFlags("flag=1 other_flag='zzz'", true, "zzz", "flag", "other_flag"); - TestTwoFlags("other_flag='zzz' flag=1", true, "zzz", "flag", "other_flag"); - TestTwoFlags("other_flag=' flag=0 ' flag=1", true, " flag=0 ", "flag", - "other_flag"); - TestTwoFlags("flag=1 other_flag=' flag=0 '", true, " flag=0 ", "flag", - "other_flag"); -} - -TEST(SanitizerCommon, CommonFlags) { - CommonFlags cf; - FlagParser parser; - RegisterCommonFlags(&parser, &cf); - - cf.SetDefaults(); - EXPECT_TRUE(cf.symbolize); - EXPECT_STREQ(".", cf.coverage_dir); - - cf.symbolize = false; - cf.coverage = true; - cf.heap_profile = true; - cf.log_path = "path/one"; - - parser.ParseString("symbolize=1:heap_profile=false log_path='path/two'"); - EXPECT_TRUE(cf.symbolize); - EXPECT_TRUE(cf.coverage); - EXPECT_FALSE(cf.heap_profile); - EXPECT_STREQ("path/two", cf.log_path); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc b/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc deleted file mode 100644 index 2f0494f82b0af..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_format_interceptor_test.cc +++ /dev/null @@ -1,263 +0,0 @@ -//===-- sanitizer_format_interceptor_test.cc ------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tests for *scanf interceptors implementation in sanitizer_common. -// -//===----------------------------------------------------------------------===// -#include <algorithm> -#include <vector> - -#include "interception/interception.h" -#include "sanitizer_test_utils.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "sanitizer_common/sanitizer_common.h" -#include "gtest/gtest.h" - -using namespace __sanitizer; - -#define COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size) \ - do { \ - ((std::vector<unsigned> *)ctx)->push_back(size); \ - ptr = ptr; \ - } while (0) - -#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ - COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size) - -#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ - COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size) - -#define SANITIZER_INTERCEPT_PRINTF 1 -#include "sanitizer_common/sanitizer_common_interceptors_format.inc" - -static const unsigned I = sizeof(int); -static const unsigned L = sizeof(long); -static const unsigned LL = sizeof(long long); -static const unsigned S = sizeof(short); -static const unsigned C = sizeof(char); -static const unsigned LC = sizeof(wchar_t); -static const unsigned D = sizeof(double); -static const unsigned LD = sizeof(long double); -static const unsigned F = sizeof(float); -static const unsigned P = sizeof(char *); - -static void verifyFormatResults(const char *format, unsigned n, - const std::vector<unsigned> &computed_sizes, - va_list expected_sizes) { - // "+ 1" because of format string - ASSERT_EQ(n + 1, - computed_sizes.size()) << "Unexpected number of format arguments: '" - << format << "'"; - for (unsigned i = 0; i < n; ++i) - EXPECT_EQ(va_arg(expected_sizes, unsigned), computed_sizes[i + 1]) - << "Unexpect write size for argument " << i << ", format string '" - << format << "'"; -} - -static const char test_buf[] = "Test string."; -static const size_t test_buf_size = sizeof(test_buf); - -static const unsigned SCANF_ARGS_MAX = 16; - -static void testScanf3(void *ctx, int result, bool allowGnuMalloc, - const char *format, ...) { - va_list ap; - va_start(ap, format); - scanf_common(ctx, result, allowGnuMalloc, format, ap); - va_end(ap); -} - -static void testScanf2(const char *format, int scanf_result, - bool allowGnuMalloc, unsigned n, - va_list expected_sizes) { - std::vector<unsigned> scanf_sizes; - // 16 args should be enough. - testScanf3((void *)&scanf_sizes, scanf_result, allowGnuMalloc, format, - test_buf, test_buf, test_buf, test_buf, test_buf, test_buf, - test_buf, test_buf, test_buf, test_buf, test_buf, test_buf, - test_buf, test_buf, test_buf, test_buf); - verifyFormatResults(format, n, scanf_sizes, expected_sizes); -} - -static void testScanf(const char *format, unsigned n, ...) { - va_list ap; - va_start(ap, n); - testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ true, n, ap); - va_end(ap); -} - -static void testScanfPartial(const char *format, int scanf_result, unsigned n, - ...) { - va_list ap; - va_start(ap, n); - testScanf2(format, scanf_result, /* allowGnuMalloc */ true, n, ap); - va_end(ap); -} - -static void testScanfNoGnuMalloc(const char *format, unsigned n, ...) { - va_list ap; - va_start(ap, n); - testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ false, n, ap); - va_end(ap); -} - -TEST(SanitizerCommonInterceptors, Scanf) { - testScanf("%d", 1, I); - testScanf("%d%d%d", 3, I, I, I); - testScanf("ab%u%dc", 2, I, I); - testScanf("%ld", 1, L); - testScanf("%llu", 1, LL); - testScanf("%qd", 1, LL); - testScanf("a %hd%hhx", 2, S, C); - testScanf("%c", 1, C); - testScanf("%lc", 1, LC); - - testScanf("%%", 0); - testScanf("a%%", 0); - testScanf("a%%b", 0); - testScanf("a%%%%b", 0); - testScanf("a%%b%%", 0); - testScanf("a%%%%%%b", 0); - testScanf("a%%%%%b", 0); - testScanf("a%%%%%f", 1, F); - testScanf("a%%%lxb", 1, L); - testScanf("a%lf%%%lxb", 2, D, L); - testScanf("%nf", 1, I); - - testScanf("%10s", 1, 11); - testScanf("%10c", 1, 10); - testScanf("%10ls", 1, 11 * LC); - testScanf("%10lc", 1, 10 * LC); - testScanf("%%10s", 0); - testScanf("%*10s", 0); - testScanf("%*d", 0); - - testScanf("%4d%8f%c", 3, I, F, C); - testScanf("%s%d", 2, test_buf_size, I); - testScanf("%[abc]", 1, test_buf_size); - testScanf("%4[bcdef]", 1, 5); - testScanf("%[]]", 1, test_buf_size); - testScanf("%8[^]%d0-9-]%c", 2, 9, C); - - testScanf("%*[^:]%n:%d:%1[ ]%n", 4, I, I, 2, I); - - testScanf("%*d%u", 1, I); - - testScanf("%c%d", 2, C, I); - testScanf("%A%lf", 2, F, D); - - testScanf("%ms %Lf", 2, P, LD); - testScanf("s%Las", 1, LD); - testScanf("%ar", 1, F); - - // In the cases with std::min below the format spec can be interpreted as - // either floating-something, or (GNU extension) callee-allocated string. - // Our conservative implementation reports one of the two possibilities with - // the least store range. - testScanf("%a[", 0); - testScanf("%a[]", 0); - testScanf("%a[]]", 1, std::min(F, P)); - testScanf("%a[abc]", 1, std::min(F, P)); - testScanf("%a[^abc]", 1, std::min(F, P)); - testScanf("%a[ab%c] %d", 0); - testScanf("%a[^ab%c] %d", 0); - testScanf("%as", 1, std::min(F, P)); - testScanf("%aS", 1, std::min(F, P)); - testScanf("%a13S", 1, std::min(F, P)); - testScanf("%alS", 1, std::min(F, P)); - - testScanfNoGnuMalloc("s%Las", 1, LD); - testScanfNoGnuMalloc("%ar", 1, F); - testScanfNoGnuMalloc("%a[", 1, F); - testScanfNoGnuMalloc("%a[]", 1, F); - testScanfNoGnuMalloc("%a[]]", 1, F); - testScanfNoGnuMalloc("%a[abc]", 1, F); - testScanfNoGnuMalloc("%a[^abc]", 1, F); - testScanfNoGnuMalloc("%a[ab%c] %d", 3, F, C, I); - testScanfNoGnuMalloc("%a[^ab%c] %d", 3, F, C, I); - testScanfNoGnuMalloc("%as", 1, F); - testScanfNoGnuMalloc("%aS", 1, F); - testScanfNoGnuMalloc("%a13S", 1, F); - testScanfNoGnuMalloc("%alS", 1, F); - - testScanf("%5$d", 0); - testScanf("%md", 0); - testScanf("%m10s", 0); - - testScanfPartial("%d%d%d%d //1\n", 1, 1, I); - testScanfPartial("%d%d%d%d //2\n", 2, 2, I, I); - testScanfPartial("%d%d%d%d //3\n", 3, 3, I, I, I); - testScanfPartial("%d%d%d%d //4\n", 4, 4, I, I, I, I); - - testScanfPartial("%d%n%n%d //1\n", 1, 3, I, I, I); - testScanfPartial("%d%n%n%d //2\n", 2, 4, I, I, I, I); - - testScanfPartial("%d%n%n%d %s %s", 3, 5, I, I, I, I, test_buf_size); - testScanfPartial("%d%n%n%d %s %s", 4, 6, I, I, I, I, test_buf_size, - test_buf_size); -} - -static void testPrintf3(void *ctx, const char *format, ...) { - va_list ap; - va_start(ap, format); - printf_common(ctx, format, ap); - va_end(ap); -} - -static void testPrintf2(const char *format, unsigned n, - va_list expected_sizes) { - std::vector<unsigned> printf_sizes; - // 16 args should be enough. - testPrintf3((void *)&printf_sizes, format, - test_buf, test_buf, test_buf, test_buf, test_buf, test_buf, - test_buf, test_buf, test_buf, test_buf, test_buf, test_buf, - test_buf, test_buf, test_buf, test_buf); - verifyFormatResults(format, n, printf_sizes, expected_sizes); -} - -static void testPrintf(const char *format, unsigned n, ...) { - va_list ap; - va_start(ap, n); - testPrintf2(format, n, ap); - va_end(ap); -} - -TEST(SanitizerCommonInterceptors, Printf) { - // Only test functionality which differs from scanf - - // Indexed arguments - testPrintf("%5$d", 0); - testPrintf("%.*5$d", 0); - - // errno - testPrintf("%0-m", 0); - - // Dynamic width - testPrintf("%*n", 1, I); - testPrintf("%*.10n", 1, I); - - // Precision - testPrintf("%10.10n", 1, I); - testPrintf("%.3s", 1, 3); - testPrintf("%.20s", 1, test_buf_size); - - // Dynamic precision - testPrintf("%.*n", 1, I); - testPrintf("%10.*n", 1, I); - - // Dynamic precision for strings is not implemented yet. - testPrintf("%.*s", 1, 0); - - // Checks for wide-character strings are not implemented yet. - testPrintf("%ls", 1, 0); - - testPrintf("%m", 0); - testPrintf("%m%s", 1, test_buf_size); - testPrintf("%s%m%s", 2, test_buf_size, test_buf_size); -} diff --git a/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc b/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc deleted file mode 100644 index 6e2a20b85d6ab..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc +++ /dev/null @@ -1,105 +0,0 @@ -//===-- sanitizer_ioctl_test.cc -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tests for ioctl interceptor implementation in sanitizer_common. -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_LINUX - -#include <linux/input.h> -#include <vector> - -#include "interception/interception.h" -#include "sanitizer_test_utils.h" -#include "sanitizer_common/sanitizer_platform_limits_posix.h" -#include "sanitizer_common/sanitizer_common.h" -#include "gtest/gtest.h" - - -using namespace __sanitizer; - -#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, sz) \ - do { \ - (void) ctx; \ - (void) ptr; \ - (void) sz; \ - } while (0) -#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sz) \ - do { \ - (void) ctx; \ - (void) ptr; \ - (void) sz; \ - } while (0) - -#include "sanitizer_common/sanitizer_common_interceptors_ioctl.inc" - -static struct IoctlInit { - IoctlInit() { - ioctl_init(); - // Avoid unused function warnings. - (void)&ioctl_common_pre; - (void)&ioctl_common_post; - (void)&ioctl_decode; - } -} ioctl_static_initializer; - -TEST(SanitizerIoctl, Fixup) { - EXPECT_EQ((unsigned)FIONBIO, ioctl_request_fixup(FIONBIO)); - - EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(0, 16))); - EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(1, 16))); - EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(1, 17))); - EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(31, 16))); - EXPECT_NE(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(32, 16))); - - EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(0))); - EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(5))); - EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(63))); - EXPECT_NE(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(64))); - - EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(0))); - EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(5))); - EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(63))); - EXPECT_NE(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(64))); - - const ioctl_desc *desc = ioctl_lookup(EVIOCGKEY(16)); - EXPECT_NE((void *)0, desc); - EXPECT_EQ(EVIOCGKEY(0), desc->req); -} - -// Test decoding KVM ioctl numbers. -TEST(SanitizerIoctl, KVM_GET_MP_STATE) { - ioctl_desc desc; - unsigned int desc_value = SANITIZER_MIPS ? 0x4004ae98U : 0x8004ae98U; - bool res = ioctl_decode(desc_value, &desc); - EXPECT_TRUE(res); - EXPECT_EQ(ioctl_desc::WRITE, desc.type); - EXPECT_EQ(4U, desc.size); -} - -TEST(SanitizerIoctl, KVM_GET_LAPIC) { - ioctl_desc desc; - unsigned int desc_value = SANITIZER_MIPS ? 0x4400ae8eU : 0x8400ae8eU; - bool res = ioctl_decode(desc_value, &desc); - EXPECT_TRUE(res); - EXPECT_EQ(ioctl_desc::WRITE, desc.type); - EXPECT_EQ(1024U, desc.size); -} - -TEST(SanitizerIoctl, KVM_GET_MSR_INDEX_LIST) { - ioctl_desc desc; - bool res = ioctl_decode(0xc004ae02U, &desc); - EXPECT_TRUE(res); - EXPECT_EQ(ioctl_desc::READWRITE, desc.type); - EXPECT_EQ(4U, desc.size); -} - -#endif // SANITIZER_LINUX diff --git a/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/lib/sanitizer_common/tests/sanitizer_libc_test.cc deleted file mode 100644 index 2f61601cdff95..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_libc_test.cc +++ /dev/null @@ -1,315 +0,0 @@ -//===-- sanitizer_libc_test.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Tests for sanitizer_libc.h. -//===----------------------------------------------------------------------===// -#include <algorithm> -#include <fstream> - -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_file.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "sanitizer_common/sanitizer_platform.h" -#include "gtest/gtest.h" - -#if SANITIZER_WINDOWS -#define NOMINMAX -#include <windows.h> -#undef NOMINMAX -#endif -#if SANITIZER_POSIX -# include <sys/stat.h> -# include "sanitizer_common/sanitizer_posix.h" -#endif - -using namespace __sanitizer; - -// A regression test for internal_memmove() implementation. -TEST(SanitizerCommon, InternalMemmoveRegression) { - char src[] = "Hello World"; - char *dest = src + 6; - __sanitizer::internal_memmove(dest, src, 5); - EXPECT_EQ(dest[0], src[0]); - EXPECT_EQ(dest[4], src[4]); -} - -TEST(SanitizerCommon, mem_is_zero) { - size_t size = 128; - char *x = new char[size]; - memset(x, 0, size); - for (size_t pos = 0; pos < size; pos++) { - x[pos] = 1; - for (size_t beg = 0; beg < size; beg++) { - for (size_t end = beg; end < size; end++) { - // fprintf(stderr, "pos %zd beg %zd end %zd \n", pos, beg, end); - if (beg <= pos && pos < end) - EXPECT_FALSE(__sanitizer::mem_is_zero(x + beg, end - beg)); - else - EXPECT_TRUE(__sanitizer::mem_is_zero(x + beg, end - beg)); - } - } - x[pos] = 0; - } - delete [] x; -} - -struct stat_and_more { - struct stat st; - unsigned char z; -}; - -static void temp_file_name(char *buf, size_t bufsize, const char *prefix) { -#if SANITIZER_WINDOWS - buf[0] = '\0'; - char tmp_dir[MAX_PATH]; - if (!::GetTempPathA(MAX_PATH, tmp_dir)) - return; - // GetTempFileNameA needs a MAX_PATH buffer. - char tmp_path[MAX_PATH]; - if (!::GetTempFileNameA(tmp_dir, prefix, 0, tmp_path)) - return; - internal_strncpy(buf, tmp_path, bufsize); -#else - const char *tmpdir = "/tmp"; -#if SANITIZER_ANDROID - // I don't know a way to query temp directory location on Android without - // going through Java interfaces. The code below is not ideal, but should - // work. May require "adb root", but it is needed for almost any use of ASan - // on Android already. - tmpdir = GetEnv("EXTERNAL_STORAGE"); -#endif - internal_snprintf(buf, bufsize, "%s/%sXXXXXX", tmpdir, prefix); - ASSERT_TRUE(mkstemp(buf)); -#endif -} - -static void Unlink(const char *path) { -#if SANITIZER_WINDOWS - // No sanitizer needs to delete a file on Windows yet. If we ever do, we can - // add a portable wrapper and test it from here. - ::DeleteFileA(&path[0]); -#else - internal_unlink(path); -#endif -} - -TEST(SanitizerCommon, FileOps) { - const char *str1 = "qwerty"; - uptr len1 = internal_strlen(str1); - const char *str2 = "zxcv"; - uptr len2 = internal_strlen(str2); - - char tmpfile[128]; - temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp."); - fd_t fd = OpenFile(tmpfile, WrOnly); - ASSERT_NE(fd, kInvalidFd); - ASSERT_TRUE(WriteToFile(fd, "A", 1)); - CloseFile(fd); - - fd = OpenFile(tmpfile, WrOnly); - ASSERT_NE(fd, kInvalidFd); -#if SANITIZER_POSIX && !SANITIZER_MAC - EXPECT_EQ(internal_lseek(fd, 0, SEEK_END), 0u); -#endif - uptr bytes_written = 0; - EXPECT_TRUE(WriteToFile(fd, str1, len1, &bytes_written)); - EXPECT_EQ(len1, bytes_written); - EXPECT_TRUE(WriteToFile(fd, str2, len2, &bytes_written)); - EXPECT_EQ(len2, bytes_written); - CloseFile(fd); - - EXPECT_TRUE(FileExists(tmpfile)); - - fd = OpenFile(tmpfile, RdOnly); - ASSERT_NE(fd, kInvalidFd); - -#if SANITIZER_POSIX - // The stat wrappers are posix-only. - uptr fsize = internal_filesize(fd); - EXPECT_EQ(len1 + len2, fsize); - - struct stat st1, st2, st3; - EXPECT_EQ(0u, internal_stat(tmpfile, &st1)); - EXPECT_EQ(0u, internal_lstat(tmpfile, &st2)); - EXPECT_EQ(0u, internal_fstat(fd, &st3)); - EXPECT_EQ(fsize, (uptr)st3.st_size); - - // Verify that internal_fstat does not write beyond the end of the supplied - // buffer. - struct stat_and_more sam; - memset(&sam, 0xAB, sizeof(sam)); - EXPECT_EQ(0u, internal_fstat(fd, &sam.st)); - EXPECT_EQ(0xAB, sam.z); - EXPECT_NE(0xAB, sam.st.st_size); - EXPECT_NE(0, sam.st.st_size); -#endif - - char buf[64] = {}; - uptr bytes_read = 0; - EXPECT_TRUE(ReadFromFile(fd, buf, len1, &bytes_read)); - EXPECT_EQ(len1, bytes_read); - EXPECT_EQ(0, internal_memcmp(buf, str1, len1)); - EXPECT_EQ((char)0, buf[len1 + 1]); - internal_memset(buf, 0, len1); - EXPECT_TRUE(ReadFromFile(fd, buf, len2, &bytes_read)); - EXPECT_EQ(len2, bytes_read); - EXPECT_EQ(0, internal_memcmp(buf, str2, len2)); - CloseFile(fd); - - Unlink(tmpfile); -} - -class SanitizerCommonFileTest : public ::testing::TestWithParam<uptr> { - void SetUp() override { - data_.resize(GetParam()); - std::generate(data_.begin(), data_.end(), [] { - return rand() % 256; // NOLINT - }); - - temp_file_name(file_name_, sizeof(file_name_), - "sanitizer_common.ReadFile.tmp."); - - std::ofstream f(file_name_, std::ios::out | std::ios::binary); - if (!data_.empty()) - f.write(data_.data(), data_.size()); - } - - void TearDown() override { Unlink(file_name_); } - - protected: - char file_name_[256]; - std::vector<char> data_; -}; - -TEST_P(SanitizerCommonFileTest, ReadFileToBuffer) { - char *buff; - uptr size; - uptr len; - EXPECT_TRUE(ReadFileToBuffer(file_name_, &buff, &len, &size)); - EXPECT_EQ(data_, std::vector<char>(buff, buff + size)); - UnmapOrDie(buff, len); -} - -TEST_P(SanitizerCommonFileTest, ReadFileToBufferHalf) { - char *buff; - uptr size; - uptr len; - data_.resize(data_.size() / 2); - EXPECT_TRUE(ReadFileToBuffer(file_name_, &buff, &len, &size, data_.size())); - EXPECT_EQ(data_, std::vector<char>(buff, buff + size)); - UnmapOrDie(buff, len); -} - -TEST_P(SanitizerCommonFileTest, ReadFileToVector) { - InternalMmapVector<char> buff; - EXPECT_TRUE(ReadFileToVector(file_name_, &buff)); - EXPECT_EQ(data_, std::vector<char>(buff.begin(), buff.end())); -} - -TEST_P(SanitizerCommonFileTest, ReadFileToVectorHalf) { - InternalMmapVector<char> buff; - data_.resize(data_.size() / 2); - EXPECT_TRUE(ReadFileToVector(file_name_, &buff, data_.size())); - EXPECT_EQ(data_, std::vector<char>(buff.begin(), buff.end())); -} - -INSTANTIATE_TEST_CASE_P(FileSizes, SanitizerCommonFileTest, - ::testing::Values(0, 1, 7, 13, 32, 4096, 4097, 1048575, - 1048576, 1048577)); - -static const size_t kStrlcpyBufSize = 8; -void test_internal_strlcpy(char *dbuf, const char *sbuf) { - uptr retval = 0; - retval = internal_strlcpy(dbuf, sbuf, kStrlcpyBufSize); - EXPECT_EQ(internal_strncmp(dbuf, sbuf, kStrlcpyBufSize - 1), 0); - EXPECT_EQ(internal_strlen(dbuf), - std::min(internal_strlen(sbuf), (uptr)(kStrlcpyBufSize - 1))); - EXPECT_EQ(retval, internal_strlen(sbuf)); - - // Test with shorter maxlen. - uptr maxlen = 2; - if (internal_strlen(sbuf) > maxlen) { - retval = internal_strlcpy(dbuf, sbuf, maxlen); - EXPECT_EQ(internal_strncmp(dbuf, sbuf, maxlen - 1), 0); - EXPECT_EQ(internal_strlen(dbuf), maxlen - 1); - } -} - -TEST(SanitizerCommon, InternalStrFunctions) { - const char *haystack = "haystack"; - EXPECT_EQ(haystack + 2, internal_strchr(haystack, 'y')); - EXPECT_EQ(haystack + 2, internal_strchrnul(haystack, 'y')); - EXPECT_EQ(0, internal_strchr(haystack, 'z')); - EXPECT_EQ(haystack + 8, internal_strchrnul(haystack, 'z')); - - char dbuf[kStrlcpyBufSize] = {}; - const char *samesizestr = "1234567"; - const char *shortstr = "123"; - const char *longerstr = "123456789"; - - // Test internal_strlcpy. - internal_strlcpy(dbuf, shortstr, 0); - EXPECT_EQ(dbuf[0], 0); - EXPECT_EQ(dbuf[0], 0); - test_internal_strlcpy(dbuf, samesizestr); - test_internal_strlcpy(dbuf, shortstr); - test_internal_strlcpy(dbuf, longerstr); - - // Test internal_strlcat. - char dcatbuf[kStrlcpyBufSize] = {}; - uptr retval = 0; - retval = internal_strlcat(dcatbuf, "aaa", 0); - EXPECT_EQ(internal_strlen(dcatbuf), (uptr)0); - EXPECT_EQ(retval, (uptr)3); - - retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize); - EXPECT_EQ(internal_strcmp(dcatbuf, "123"), 0); - EXPECT_EQ(internal_strlen(dcatbuf), (uptr)3); - EXPECT_EQ(retval, (uptr)3); - - retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize); - EXPECT_EQ(internal_strcmp(dcatbuf, "123123"), 0); - EXPECT_EQ(internal_strlen(dcatbuf), (uptr)6); - EXPECT_EQ(retval, (uptr)6); - - retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize); - EXPECT_EQ(internal_strcmp(dcatbuf, "1231231"), 0); - EXPECT_EQ(internal_strlen(dcatbuf), (uptr)7); - EXPECT_EQ(retval, (uptr)9); -} - -// FIXME: File manipulations are not yet supported on Windows -#if SANITIZER_POSIX && !SANITIZER_MAC -TEST(SanitizerCommon, InternalMmapWithOffset) { - char tmpfile[128]; - temp_file_name(tmpfile, sizeof(tmpfile), - "sanitizer_common.internalmmapwithoffset.tmp."); - fd_t fd = OpenFile(tmpfile, RdWr); - ASSERT_NE(fd, kInvalidFd); - - uptr page_size = GetPageSizeCached(); - uptr res = internal_ftruncate(fd, page_size * 2); - ASSERT_FALSE(internal_iserror(res)); - - res = internal_lseek(fd, page_size, SEEK_SET); - ASSERT_FALSE(internal_iserror(res)); - - res = internal_write(fd, "AB", 2); - ASSERT_FALSE(internal_iserror(res)); - - char *p = (char *)MapWritableFileToMemory(nullptr, page_size, fd, page_size); - ASSERT_NE(nullptr, p); - - ASSERT_EQ('A', p[0]); - ASSERT_EQ('B', p[1]); - - CloseFile(fd); - UnmapOrDie(p, page_size); - internal_unlink(tmpfile); -} -#endif diff --git a/lib/sanitizer_common/tests/sanitizer_linux_test.cc b/lib/sanitizer_common/tests/sanitizer_linux_test.cc deleted file mode 100644 index fbac9cc1438e8..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_linux_test.cc +++ /dev/null @@ -1,296 +0,0 @@ -//===-- sanitizer_linux_test.cc -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tests for sanitizer_linux.h -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_LINUX - -#include "sanitizer_common/sanitizer_linux.h" - -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_file.h" -#include "gtest/gtest.h" - -#include <pthread.h> -#include <sched.h> -#include <stdlib.h> - -#include <algorithm> -#include <vector> - -namespace __sanitizer { - -struct TidReporterArgument { - TidReporterArgument() { - pthread_mutex_init(&terminate_thread_mutex, NULL); - pthread_mutex_init(&tid_reported_mutex, NULL); - pthread_cond_init(&terminate_thread_cond, NULL); - pthread_cond_init(&tid_reported_cond, NULL); - terminate_thread = false; - } - - ~TidReporterArgument() { - pthread_mutex_destroy(&terminate_thread_mutex); - pthread_mutex_destroy(&tid_reported_mutex); - pthread_cond_destroy(&terminate_thread_cond); - pthread_cond_destroy(&tid_reported_cond); - } - - tid_t reported_tid; - // For signaling to spawned threads that they should terminate. - pthread_cond_t terminate_thread_cond; - pthread_mutex_t terminate_thread_mutex; - bool terminate_thread; - // For signaling to main thread that a child thread has reported its tid. - pthread_cond_t tid_reported_cond; - pthread_mutex_t tid_reported_mutex; - - private: - // Disallow evil constructors - TidReporterArgument(const TidReporterArgument &); - void operator=(const TidReporterArgument &); -}; - -class ThreadListerTest : public ::testing::Test { - protected: - virtual void SetUp() { - pthread_t pthread_id; - tid_t tid; - for (uptr i = 0; i < kThreadCount; i++) { - SpawnTidReporter(&pthread_id, &tid); - pthread_ids_.push_back(pthread_id); - tids_.push_back(tid); - } - } - - virtual void TearDown() { - pthread_mutex_lock(&thread_arg.terminate_thread_mutex); - thread_arg.terminate_thread = true; - pthread_cond_broadcast(&thread_arg.terminate_thread_cond); - pthread_mutex_unlock(&thread_arg.terminate_thread_mutex); - for (uptr i = 0; i < pthread_ids_.size(); i++) - pthread_join(pthread_ids_[i], NULL); - } - - void SpawnTidReporter(pthread_t *pthread_id, tid_t *tid); - - static const uptr kThreadCount = 20; - - std::vector<pthread_t> pthread_ids_; - std::vector<tid_t> tids_; - - TidReporterArgument thread_arg; -}; - -// Writes its TID once to reported_tid and waits until signaled to terminate. -void *TidReporterThread(void *argument) { - TidReporterArgument *arg = reinterpret_cast<TidReporterArgument *>(argument); - pthread_mutex_lock(&arg->tid_reported_mutex); - arg->reported_tid = GetTid(); - pthread_cond_broadcast(&arg->tid_reported_cond); - pthread_mutex_unlock(&arg->tid_reported_mutex); - - pthread_mutex_lock(&arg->terminate_thread_mutex); - while (!arg->terminate_thread) - pthread_cond_wait(&arg->terminate_thread_cond, - &arg->terminate_thread_mutex); - pthread_mutex_unlock(&arg->terminate_thread_mutex); - return NULL; -} - -void ThreadListerTest::SpawnTidReporter(pthread_t *pthread_id, tid_t *tid) { - pthread_mutex_lock(&thread_arg.tid_reported_mutex); - thread_arg.reported_tid = -1; - ASSERT_EQ(0, pthread_create(pthread_id, NULL, - TidReporterThread, - &thread_arg)); - while (thread_arg.reported_tid == (tid_t)(-1)) - pthread_cond_wait(&thread_arg.tid_reported_cond, - &thread_arg.tid_reported_mutex); - pthread_mutex_unlock(&thread_arg.tid_reported_mutex); - *tid = thread_arg.reported_tid; -} - -static std::vector<tid_t> ReadTidsToVector(ThreadLister *thread_lister) { - std::vector<tid_t> listed_tids; - InternalMmapVector<tid_t> threads(128); - EXPECT_TRUE(thread_lister->ListThreads(&threads)); - return std::vector<tid_t>(threads.begin(), threads.end()); -} - -static bool Includes(std::vector<tid_t> first, std::vector<tid_t> second) { - std::sort(first.begin(), first.end()); - std::sort(second.begin(), second.end()); - return std::includes(first.begin(), first.end(), - second.begin(), second.end()); -} - -static bool HasElement(const std::vector<tid_t> &vector, tid_t element) { - return std::find(vector.begin(), vector.end(), element) != vector.end(); -} - -// ThreadLister's output should include the current thread's TID and the TID of -// every thread we spawned. -TEST_F(ThreadListerTest, ThreadListerSeesAllSpawnedThreads) { - tid_t self_tid = GetTid(); - ThreadLister thread_lister(getpid()); - std::vector<tid_t> listed_tids = ReadTidsToVector(&thread_lister); - ASSERT_TRUE(HasElement(listed_tids, self_tid)); - ASSERT_TRUE(Includes(listed_tids, tids_)); -} - -TEST_F(ThreadListerTest, DoNotForgetThreads) { - ThreadLister thread_lister(getpid()); - - // Run the loop body twice, because ThreadLister might behave differently if - // called on a freshly created object. - for (uptr i = 0; i < 2; i++) { - std::vector<tid_t> listed_tids = ReadTidsToVector(&thread_lister); - ASSERT_TRUE(Includes(listed_tids, tids_)); - } -} - -// If new threads have spawned during ThreadLister object's lifetime, calling -// relisting should cause ThreadLister to recognize their existence. -TEST_F(ThreadListerTest, NewThreads) { - ThreadLister thread_lister(getpid()); - std::vector<tid_t> threads_before_extra = ReadTidsToVector(&thread_lister); - - pthread_t extra_pthread_id; - tid_t extra_tid; - SpawnTidReporter(&extra_pthread_id, &extra_tid); - // Register the new thread so it gets terminated in TearDown(). - pthread_ids_.push_back(extra_pthread_id); - - // It would be very bizarre if the new TID had been listed before we even - // spawned that thread, but it would also cause a false success in this test, - // so better check for that. - ASSERT_FALSE(HasElement(threads_before_extra, extra_tid)); - - std::vector<tid_t> threads_after_extra = ReadTidsToVector(&thread_lister); - ASSERT_TRUE(HasElement(threads_after_extra, extra_tid)); -} - -TEST(SanitizerCommon, SetEnvTest) { - const char kEnvName[] = "ENV_FOO"; - SetEnv(kEnvName, "value"); - EXPECT_STREQ("value", getenv(kEnvName)); - unsetenv(kEnvName); - EXPECT_EQ(0, getenv(kEnvName)); -} - -#if (defined(__x86_64__) || defined(__i386__)) && !SANITIZER_ANDROID -void *thread_self_offset_test_func(void *arg) { - bool result = - *(uptr *)((char *)ThreadSelf() + ThreadSelfOffset()) == ThreadSelf(); - return (void *)result; -} - -TEST(SanitizerLinux, ThreadSelfOffset) { - EXPECT_TRUE((bool)thread_self_offset_test_func(0)); - pthread_t tid; - void *result; - ASSERT_EQ(0, pthread_create(&tid, 0, thread_self_offset_test_func, 0)); - ASSERT_EQ(0, pthread_join(tid, &result)); - EXPECT_TRUE((bool)result); -} - -// libpthread puts the thread descriptor at the end of stack space. -void *thread_descriptor_size_test_func(void *arg) { - uptr descr_addr = ThreadSelf(); - pthread_attr_t attr; - pthread_getattr_np(pthread_self(), &attr); - void *stackaddr; - size_t stacksize; - pthread_attr_getstack(&attr, &stackaddr, &stacksize); - return (void *)((uptr)stackaddr + stacksize - descr_addr); -} - -TEST(SanitizerLinux, ThreadDescriptorSize) { - pthread_t tid; - void *result; - ASSERT_EQ(0, pthread_create(&tid, 0, thread_descriptor_size_test_func, 0)); - ASSERT_EQ(0, pthread_join(tid, &result)); - EXPECT_EQ((uptr)result, ThreadDescriptorSize()); -} -#endif - -TEST(SanitizerCommon, LibraryNameIs) { - EXPECT_FALSE(LibraryNameIs("", "")); - - char full_name[256]; - const char *paths[] = { "", "/", "/path/to/" }; - const char *suffixes[] = { "", "-linux", ".1.2", "-linux.1.2" }; - const char *base_names[] = { "lib", "lib.0", "lib-i386" }; - const char *wrong_names[] = { "", "lib.9", "lib-x86_64" }; - for (uptr i = 0; i < ARRAY_SIZE(paths); i++) - for (uptr j = 0; j < ARRAY_SIZE(suffixes); j++) { - for (uptr k = 0; k < ARRAY_SIZE(base_names); k++) { - internal_snprintf(full_name, ARRAY_SIZE(full_name), "%s%s%s.so", - paths[i], base_names[k], suffixes[j]); - EXPECT_TRUE(LibraryNameIs(full_name, base_names[k])) - << "Full name " << full_name - << " doesn't match base name " << base_names[k]; - for (uptr m = 0; m < ARRAY_SIZE(wrong_names); m++) - EXPECT_FALSE(LibraryNameIs(full_name, wrong_names[m])) - << "Full name " << full_name - << " matches base name " << wrong_names[m]; - } - } -} - -#if defined(__mips64) -// Effectively, this is a test for ThreadDescriptorSize() which is used to -// compute ThreadSelf(). -TEST(SanitizerLinux, ThreadSelfTest) { - ASSERT_EQ(pthread_self(), ThreadSelf()); -} -#endif - -TEST(SanitizerCommon, StartSubprocessTest) { - int pipe_fds[2]; - ASSERT_EQ(0, pipe(pipe_fds)); -#if SANITIZER_ANDROID - const char *shell = "/system/bin/sh"; -#else - const char *shell = "/bin/sh"; -#endif - const char *argv[] = {shell, "-c", "echo -n 'hello'", (char *)NULL}; - int pid = StartSubprocess(shell, argv, - /* stdin */ kInvalidFd, /* stdout */ pipe_fds[1]); - ASSERT_GT(pid, 0); - - // wait for process to finish. - while (IsProcessRunning(pid)) { - } - ASSERT_FALSE(IsProcessRunning(pid)); - - char buffer[256]; - { - char *ptr = buffer; - uptr bytes_read; - while (ReadFromFile(pipe_fds[0], ptr, 256, &bytes_read)) { - if (!bytes_read) { - break; - } - ptr += bytes_read; - } - ASSERT_EQ(5, ptr - buffer); - *ptr = 0; - } - ASSERT_EQ(0, strcmp(buffer, "hello")) << "Buffer: " << buffer; - internal_close(pipe_fds[0]); -} - -} // namespace __sanitizer - -#endif // SANITIZER_LINUX diff --git a/lib/sanitizer_common/tests/sanitizer_list_test.cc b/lib/sanitizer_common/tests/sanitizer_list_test.cc deleted file mode 100644 index ede9771cb2496..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_list_test.cc +++ /dev/null @@ -1,189 +0,0 @@ -//===-- sanitizer_list_test.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_list.h" -#include "gtest/gtest.h" - -namespace __sanitizer { - -struct ListItem { - ListItem *next; -}; - -typedef IntrusiveList<ListItem> List; - -static List static_list; - -static void SetList(List *l, ListItem *x = 0, - ListItem *y = 0, ListItem *z = 0) { - l->clear(); - if (x) l->push_back(x); - if (y) l->push_back(y); - if (z) l->push_back(z); -} - -static void CheckList(List *l, ListItem *i1, ListItem *i2 = 0, ListItem *i3 = 0, - ListItem *i4 = 0, ListItem *i5 = 0, ListItem *i6 = 0) { - if (i1) { - CHECK_EQ(l->front(), i1); - l->pop_front(); - } - if (i2) { - CHECK_EQ(l->front(), i2); - l->pop_front(); - } - if (i3) { - CHECK_EQ(l->front(), i3); - l->pop_front(); - } - if (i4) { - CHECK_EQ(l->front(), i4); - l->pop_front(); - } - if (i5) { - CHECK_EQ(l->front(), i5); - l->pop_front(); - } - if (i6) { - CHECK_EQ(l->front(), i6); - l->pop_front(); - } - CHECK(l->empty()); -} - -TEST(SanitizerCommon, IntrusiveList) { - ListItem items[6]; - CHECK_EQ(static_list.size(), 0); - - List l; - l.clear(); - - ListItem *x = &items[0]; - ListItem *y = &items[1]; - ListItem *z = &items[2]; - ListItem *a = &items[3]; - ListItem *b = &items[4]; - ListItem *c = &items[5]; - - CHECK_EQ(l.size(), 0); - l.push_back(x); - CHECK_EQ(l.size(), 1); - CHECK_EQ(l.back(), x); - CHECK_EQ(l.front(), x); - l.pop_front(); - CHECK(l.empty()); - l.CheckConsistency(); - - l.push_front(x); - CHECK_EQ(l.size(), 1); - CHECK_EQ(l.back(), x); - CHECK_EQ(l.front(), x); - l.pop_front(); - CHECK(l.empty()); - l.CheckConsistency(); - - l.push_front(x); - l.push_front(y); - l.push_front(z); - CHECK_EQ(l.size(), 3); - CHECK_EQ(l.front(), z); - CHECK_EQ(l.back(), x); - l.CheckConsistency(); - - l.pop_front(); - CHECK_EQ(l.size(), 2); - CHECK_EQ(l.front(), y); - CHECK_EQ(l.back(), x); - l.pop_front(); - l.pop_front(); - CHECK(l.empty()); - l.CheckConsistency(); - - l.push_back(x); - l.push_back(y); - l.push_back(z); - CHECK_EQ(l.size(), 3); - CHECK_EQ(l.front(), x); - CHECK_EQ(l.back(), z); - l.CheckConsistency(); - - l.pop_front(); - CHECK_EQ(l.size(), 2); - CHECK_EQ(l.front(), y); - CHECK_EQ(l.back(), z); - l.pop_front(); - l.pop_front(); - CHECK(l.empty()); - l.CheckConsistency(); - - l.push_back(x); - l.push_back(y); - l.push_back(z); - l.extract(x, y); - CHECK_EQ(l.size(), 2); - CHECK_EQ(l.front(), x); - CHECK_EQ(l.back(), z); - l.CheckConsistency(); - l.extract(x, z); - CHECK_EQ(l.size(), 1); - CHECK_EQ(l.front(), x); - CHECK_EQ(l.back(), x); - l.CheckConsistency(); - l.pop_front(); - CHECK(l.empty()); - - List l1, l2; - l1.clear(); - l2.clear(); - - l1.append_front(&l2); - CHECK(l1.empty()); - CHECK(l2.empty()); - - l1.append_back(&l2); - CHECK(l1.empty()); - CHECK(l2.empty()); - - SetList(&l1, x); - CheckList(&l1, x); - - SetList(&l1, x, y, z); - SetList(&l2, a, b, c); - l1.append_back(&l2); - CheckList(&l1, x, y, z, a, b, c); - CHECK(l2.empty()); - - SetList(&l1, x, y); - SetList(&l2); - l1.append_front(&l2); - CheckList(&l1, x, y); - CHECK(l2.empty()); -} - -TEST(SanitizerCommon, IntrusiveListAppendEmpty) { - ListItem i; - List l; - l.clear(); - l.push_back(&i); - List l2; - l2.clear(); - l.append_back(&l2); - CHECK_EQ(l.back(), &i); - CHECK_EQ(l.front(), &i); - CHECK_EQ(l.size(), 1); - l.append_front(&l2); - CHECK_EQ(l.back(), &i); - CHECK_EQ(l.front(), &i); - CHECK_EQ(l.size(), 1); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_mutex_test.cc b/lib/sanitizer_common/tests/sanitizer_mutex_test.cc deleted file mode 100644 index d14e7c2fba217..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_mutex_test.cc +++ /dev/null @@ -1,137 +0,0 @@ -//===-- sanitizer_mutex_test.cc -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_mutex.h" -#include "sanitizer_common/sanitizer_common.h" - -#include "sanitizer_pthread_wrappers.h" - -#include "gtest/gtest.h" - -#include <string.h> - -namespace __sanitizer { - -template<typename MutexType> -class TestData { - public: - explicit TestData(MutexType *mtx) - : mtx_(mtx) { - for (int i = 0; i < kSize; i++) - data_[i] = 0; - } - - void Write() { - Lock l(mtx_); - T v0 = data_[0]; - for (int i = 0; i < kSize; i++) { - CHECK_EQ(data_[i], v0); - data_[i]++; - } - } - - void TryWrite() { - if (!mtx_->TryLock()) - return; - T v0 = data_[0]; - for (int i = 0; i < kSize; i++) { - CHECK_EQ(data_[i], v0); - data_[i]++; - } - mtx_->Unlock(); - } - - void Backoff() { - volatile T data[kSize] = {}; - for (int i = 0; i < kSize; i++) { - data[i]++; - CHECK_EQ(data[i], 1); - } - } - - private: - typedef GenericScopedLock<MutexType> Lock; - static const int kSize = 64; - typedef u64 T; - MutexType *mtx_; - char pad_[kCacheLineSize]; - T data_[kSize]; -}; - -const int kThreads = 8; -#if SANITIZER_DEBUG -const int kIters = 16*1024; -#else -const int kIters = 64*1024; -#endif - -template<typename MutexType> -static void *lock_thread(void *param) { - TestData<MutexType> *data = (TestData<MutexType>*)param; - for (int i = 0; i < kIters; i++) { - data->Write(); - data->Backoff(); - } - return 0; -} - -template<typename MutexType> -static void *try_thread(void *param) { - TestData<MutexType> *data = (TestData<MutexType>*)param; - for (int i = 0; i < kIters; i++) { - data->TryWrite(); - data->Backoff(); - } - return 0; -} - -template<typename MutexType> -static void check_locked(MutexType *mtx) { - GenericScopedLock<MutexType> l(mtx); - mtx->CheckLocked(); -} - -TEST(SanitizerCommon, SpinMutex) { - SpinMutex mtx; - mtx.Init(); - TestData<SpinMutex> data(&mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - PTHREAD_CREATE(&threads[i], 0, lock_thread<SpinMutex>, &data); - for (int i = 0; i < kThreads; i++) - PTHREAD_JOIN(threads[i], 0); -} - -TEST(SanitizerCommon, SpinMutexTry) { - SpinMutex mtx; - mtx.Init(); - TestData<SpinMutex> data(&mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - PTHREAD_CREATE(&threads[i], 0, try_thread<SpinMutex>, &data); - for (int i = 0; i < kThreads; i++) - PTHREAD_JOIN(threads[i], 0); -} - -TEST(SanitizerCommon, BlockingMutex) { - u64 mtxmem[1024] = {}; - BlockingMutex *mtx = new(mtxmem) BlockingMutex(LINKER_INITIALIZED); - TestData<BlockingMutex> data(mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - PTHREAD_CREATE(&threads[i], 0, lock_thread<BlockingMutex>, &data); - for (int i = 0; i < kThreads; i++) - PTHREAD_JOIN(threads[i], 0); - check_locked(mtx); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc b/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc deleted file mode 100644 index d0d5a5e138985..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc +++ /dev/null @@ -1,31 +0,0 @@ -//===-- sanitizer_nolibc_test.cc ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// Tests for libc independence of sanitizer_common. -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_platform.h" - -#include "gtest/gtest.h" - -#include <stdlib.h> - -extern const char *argv0; - -#if SANITIZER_LINUX && defined(__x86_64__) -TEST(SanitizerCommon, NolibcMain) { - std::string NolibcTestPath = argv0; - NolibcTestPath += "-Nolibc"; - int status = system(NolibcTestPath.c_str()); - EXPECT_EQ(true, WIFEXITED(status)); - EXPECT_EQ(0, WEXITSTATUS(status)); -} -#endif diff --git a/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc b/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc deleted file mode 100644 index e761f00c56fc0..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc +++ /dev/null @@ -1,19 +0,0 @@ -//===-- sanitizer_nolibc_test_main.cc -------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// Tests for libc independence of sanitizer_common. -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_libc.h" - -extern "C" void _start() { - __sanitizer::internal__exit(0); -} diff --git a/lib/sanitizer_common/tests/sanitizer_posix_test.cc b/lib/sanitizer_common/tests/sanitizer_posix_test.cc deleted file mode 100644 index b7cca83622aa7..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_posix_test.cc +++ /dev/null @@ -1,81 +0,0 @@ -//===-- sanitizer_posix_test.cc -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tests for POSIX-specific code. -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_POSIX - -#include "sanitizer_common/sanitizer_common.h" -#include "gtest/gtest.h" - -#include <pthread.h> -#include <sys/mman.h> - -namespace __sanitizer { - -static pthread_key_t key; -static bool destructor_executed; - -extern "C" -void destructor(void *arg) { - uptr iter = reinterpret_cast<uptr>(arg); - if (iter > 1) { - ASSERT_EQ(0, pthread_setspecific(key, reinterpret_cast<void *>(iter - 1))); - return; - } - destructor_executed = true; -} - -extern "C" -void *thread_func(void *arg) { - return reinterpret_cast<void*>(pthread_setspecific(key, arg)); -} - -static void SpawnThread(uptr iteration) { - destructor_executed = false; - pthread_t tid; - ASSERT_EQ(0, pthread_create(&tid, 0, &thread_func, - reinterpret_cast<void *>(iteration))); - void *retval; - ASSERT_EQ(0, pthread_join(tid, &retval)); - ASSERT_EQ(0, retval); -} - -TEST(SanitizerCommon, PthreadDestructorIterations) { - ASSERT_EQ(0, pthread_key_create(&key, &destructor)); - SpawnThread(GetPthreadDestructorIterations()); - EXPECT_TRUE(destructor_executed); - SpawnThread(GetPthreadDestructorIterations() + 1); - EXPECT_FALSE(destructor_executed); - ASSERT_EQ(0, pthread_key_delete(key)); -} - -TEST(SanitizerCommon, IsAccessibleMemoryRange) { - const int page_size = GetPageSize(); - uptr mem = (uptr)mmap(0, 3 * page_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); - // Protect the middle page. - mprotect((void *)(mem + page_size), page_size, PROT_NONE); - EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size - 1)); - EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size)); - EXPECT_FALSE(IsAccessibleMemoryRange(mem, page_size + 1)); - EXPECT_TRUE(IsAccessibleMemoryRange(mem + page_size - 1, 1)); - EXPECT_FALSE(IsAccessibleMemoryRange(mem + page_size - 1, 2)); - EXPECT_FALSE(IsAccessibleMemoryRange(mem + 2 * page_size - 1, 1)); - EXPECT_TRUE(IsAccessibleMemoryRange(mem + 2 * page_size, page_size)); - EXPECT_FALSE(IsAccessibleMemoryRange(mem, 3 * page_size)); - EXPECT_FALSE(IsAccessibleMemoryRange(0x0, 2)); -} - -} // namespace __sanitizer - -#endif // SANITIZER_POSIX diff --git a/lib/sanitizer_common/tests/sanitizer_printf_test.cc b/lib/sanitizer_common/tests/sanitizer_printf_test.cc deleted file mode 100644 index 75fe6667864f8..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_printf_test.cc +++ /dev/null @@ -1,161 +0,0 @@ -//===-- sanitizer_printf_test.cc ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tests for sanitizer_printf.cc -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "gtest/gtest.h" - -#include <string.h> -#include <limits.h> - -namespace __sanitizer { - -TEST(Printf, Basic) { - char buf[1024]; - uptr len = internal_snprintf(buf, sizeof(buf), - "a%db%zdc%ue%zuf%xh%zxq%pe%sr", - (int)-1, (uptr)-2, // NOLINT - (unsigned)-4, (uptr)5, // NOLINT - (unsigned)10, (uptr)11, // NOLINT - (void*)0x123, "_string_"); - EXPECT_EQ(len, strlen(buf)); - - std::string expectedString = "a-1b-2c4294967292e5fahbq0x"; - expectedString += std::string(SANITIZER_POINTER_FORMAT_LENGTH - 3, '0'); - expectedString += "123e_string_r"; - EXPECT_STREQ(expectedString.c_str(), buf); -} - -TEST(Printf, OverflowStr) { - char buf[] = "123456789"; - uptr len = internal_snprintf(buf, 4, "%s", "abcdef"); // NOLINT - EXPECT_EQ(len, (uptr)6); - EXPECT_STREQ("abc", buf); - EXPECT_EQ(buf[3], 0); - EXPECT_EQ(buf[4], '5'); - EXPECT_EQ(buf[5], '6'); - EXPECT_EQ(buf[6], '7'); - EXPECT_EQ(buf[7], '8'); - EXPECT_EQ(buf[8], '9'); - EXPECT_EQ(buf[9], 0); -} - -TEST(Printf, OverflowInt) { - char buf[] = "123456789"; - internal_snprintf(buf, 4, "%d", -123456789); // NOLINT - EXPECT_STREQ("-12", buf); - EXPECT_EQ(buf[3], 0); - EXPECT_EQ(buf[4], '5'); - EXPECT_EQ(buf[5], '6'); - EXPECT_EQ(buf[6], '7'); - EXPECT_EQ(buf[7], '8'); - EXPECT_EQ(buf[8], '9'); - EXPECT_EQ(buf[9], 0); -} - -TEST(Printf, OverflowUint) { - char buf[] = "123456789"; - uptr val; - if (sizeof(val) == 4) { - val = (uptr)0x12345678; - } else { - val = (uptr)0x123456789ULL; - } - internal_snprintf(buf, 4, "a%zx", val); // NOLINT - EXPECT_STREQ("a12", buf); - EXPECT_EQ(buf[3], 0); - EXPECT_EQ(buf[4], '5'); - EXPECT_EQ(buf[5], '6'); - EXPECT_EQ(buf[6], '7'); - EXPECT_EQ(buf[7], '8'); - EXPECT_EQ(buf[8], '9'); - EXPECT_EQ(buf[9], 0); -} - -TEST(Printf, OverflowPtr) { - char buf[] = "123456789"; - void *p; - if (sizeof(p) == 4) { - p = (void*)0x1234567; - } else { - p = (void*)0x123456789ULL; - } - internal_snprintf(buf, 4, "%p", p); // NOLINT - EXPECT_STREQ("0x0", buf); - EXPECT_EQ(buf[3], 0); - EXPECT_EQ(buf[4], '5'); - EXPECT_EQ(buf[5], '6'); - EXPECT_EQ(buf[6], '7'); - EXPECT_EQ(buf[7], '8'); - EXPECT_EQ(buf[8], '9'); - EXPECT_EQ(buf[9], 0); -} - -#if defined(_WIN32) -// Oh well, MSVS headers don't define snprintf. -# define snprintf _snprintf -#endif - -template<typename T> -static void TestAgainstLibc(const char *fmt, T arg1, T arg2) { - char buf[1024]; - uptr len = internal_snprintf(buf, sizeof(buf), fmt, arg1, arg2); - char buf2[1024]; - snprintf(buf2, sizeof(buf2), fmt, arg1, arg2); - EXPECT_EQ(len, strlen(buf)); - EXPECT_STREQ(buf2, buf); -} - -TEST(Printf, MinMax) { - TestAgainstLibc<int>("%d-%d", INT_MIN, INT_MAX); // NOLINT - TestAgainstLibc<unsigned>("%u-%u", 0, UINT_MAX); // NOLINT - TestAgainstLibc<unsigned>("%x-%x", 0, UINT_MAX); // NOLINT -#if !defined(_WIN32) - // %z* format doesn't seem to be supported by MSVS. - TestAgainstLibc<long>("%zd-%zd", LONG_MIN, LONG_MAX); // NOLINT - TestAgainstLibc<unsigned long>("%zu-%zu", 0, ULONG_MAX); // NOLINT - TestAgainstLibc<unsigned long>("%zx-%zx", 0, ULONG_MAX); // NOLINT -#endif -} - -TEST(Printf, Padding) { - TestAgainstLibc<int>("%3d - %3d", 1, 0); - TestAgainstLibc<int>("%3d - %3d", -1, 123); - TestAgainstLibc<int>("%3d - %3d", -1, -123); - TestAgainstLibc<int>("%3d - %3d", 12, 1234); - TestAgainstLibc<int>("%3d - %3d", -12, -1234); - TestAgainstLibc<int>("%03d - %03d", 1, 0); - TestAgainstLibc<int>("%03d - %03d", -1, 123); - TestAgainstLibc<int>("%03d - %03d", -1, -123); - TestAgainstLibc<int>("%03d - %03d", 12, 1234); - TestAgainstLibc<int>("%03d - %03d", -12, -1234); -} - -TEST(Printf, Precision) { - char buf[1024]; - uptr len = internal_snprintf(buf, sizeof(buf), "%.*s", 3, "12345"); - EXPECT_EQ(3U, len); - EXPECT_STREQ("123", buf); - len = internal_snprintf(buf, sizeof(buf), "%.*s", 6, "12345"); - EXPECT_EQ(5U, len); - EXPECT_STREQ("12345", buf); - len = internal_snprintf(buf, sizeof(buf), "%-6s", "12345"); - EXPECT_EQ(6U, len); - EXPECT_STREQ("12345 ", buf); - // Check that width does not overflow the smaller buffer, although - // 10 chars is requested, it stops at the buffer size, 8. - len = internal_snprintf(buf, 8, "%-10s", "12345"); - EXPECT_EQ(10U, len); // The required size reported. - EXPECT_STREQ("12345 ", buf); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc b/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc deleted file mode 100644 index 22052d9a4f592..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc +++ /dev/null @@ -1,79 +0,0 @@ -//===-- sanitizer_procmaps_test.cc ----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#if !defined(_WIN32) // There are no /proc/maps on Windows. - -#include "sanitizer_common/sanitizer_procmaps.h" -#include "gtest/gtest.h" - -#include <stdlib.h> - -static void noop() {} -extern const char *argv0; - -namespace __sanitizer { - -#if SANITIZER_LINUX && !SANITIZER_ANDROID -TEST(MemoryMappingLayout, CodeRange) { - uptr start, end; - bool res = GetCodeRangeForFile("[vdso]", &start, &end); - EXPECT_EQ(res, true); - EXPECT_GT(start, 0U); - EXPECT_LT(start, end); -} -#endif - -TEST(MemoryMappingLayout, DumpListOfModules) { - const char *last_slash = strrchr(argv0, '/'); - const char *binary_name = last_slash ? last_slash + 1 : argv0; - MemoryMappingLayout memory_mapping(false); - const uptr kMaxModules = 100; - InternalMmapVector<LoadedModule> modules; - modules.reserve(kMaxModules); - memory_mapping.DumpListOfModules(&modules); - EXPECT_GT(modules.size(), 0U); - bool found = false; - for (uptr i = 0; i < modules.size(); ++i) { - if (modules[i].containsAddress((uptr)&noop)) { - // Verify that the module name is sane. - if (strstr(modules[i].full_name(), binary_name) != 0) - found = true; - } - modules[i].clear(); - } - EXPECT_TRUE(found); -} - -TEST(MemoryMapping, LoadedModuleArchAndUUID) { - if (SANITIZER_MAC) { - MemoryMappingLayout memory_mapping(false); - const uptr kMaxModules = 100; - InternalMmapVector<LoadedModule> modules; - modules.reserve(kMaxModules); - memory_mapping.DumpListOfModules(&modules); - for (uptr i = 0; i < modules.size(); ++i) { - ModuleArch arch = modules[i].arch(); - // Darwin unit tests are only run on i386/x86_64/x86_64h. - if (SANITIZER_WORDSIZE == 32) { - EXPECT_EQ(arch, kModuleArchI386); - } else if (SANITIZER_WORDSIZE == 64) { - EXPECT_TRUE(arch == kModuleArchX86_64 || arch == kModuleArchX86_64H); - } - const u8 *uuid = modules[i].uuid(); - u8 null_uuid[kModuleUUIDSize] = {0}; - EXPECT_NE(memcmp(null_uuid, uuid, kModuleUUIDSize), 0); - } - } -} - -} // namespace __sanitizer -#endif // !defined(_WIN32) diff --git a/lib/sanitizer_common/tests/sanitizer_pthread_wrappers.h b/lib/sanitizer_common/tests/sanitizer_pthread_wrappers.h deleted file mode 100644 index b7d784c2566df..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_pthread_wrappers.h +++ /dev/null @@ -1,68 +0,0 @@ -//===-- sanitizer_pthread_wrappers.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of *Sanitizer runtime. -// It provides handy wrappers for thread manipulation, that: -// a) assert on any failure rather than returning an error code -// b) defines pthread-like interface on platforms where where <pthread.h> -// is not supplied by default. -// -//===----------------------------------------------------------------------===// - -#ifndef SANITIZER_PTHREAD_WRAPPERS_H -#define SANITIZER_PTHREAD_WRAPPERS_H - -#include "sanitizer_test_utils.h" - -#if !defined(_WIN32) -# include <pthread.h> -// Simply forward the arguments and check that the pthread functions succeed. -# define PTHREAD_CREATE(a, b, c, d) ASSERT_EQ(0, pthread_create(a, b, c, d)) -# define PTHREAD_JOIN(a, b) ASSERT_EQ(0, pthread_join(a, b)) -#else -typedef HANDLE pthread_t; - -struct PthreadHelperCreateThreadInfo { - void *(*start_routine)(void *); - void *arg; -}; - -inline DWORD WINAPI PthreadHelperThreadProc(void *arg) { - PthreadHelperCreateThreadInfo *start_data = - reinterpret_cast<PthreadHelperCreateThreadInfo*>(arg); - void *ret = (start_data->start_routine)(start_data->arg); - delete start_data; - return (DWORD)ret; -} - -inline void PTHREAD_CREATE(pthread_t *thread, void *attr, - void *(*start_routine)(void *), void *arg) { - ASSERT_EQ(0, attr) << "Thread attributes are not supported yet."; - PthreadHelperCreateThreadInfo *data = new PthreadHelperCreateThreadInfo; - data->start_routine = start_routine; - data->arg = arg; - *thread = CreateThread(0, 0, PthreadHelperThreadProc, data, 0, 0); - DWORD err = GetLastError(); - ASSERT_NE(nullptr, *thread) << "Failed to create a thread, got error 0x" - << std::hex << err; -} - -inline void PTHREAD_JOIN(pthread_t thread, void **value_ptr) { - ASSERT_EQ(0, value_ptr) << "Nonzero value_ptr is not supported yet."; - ASSERT_EQ(WAIT_OBJECT_0, WaitForSingleObject(thread, INFINITE)); - ASSERT_NE(0, CloseHandle(thread)); -} - -inline void pthread_exit(void *retval) { - ASSERT_EQ(0, retval) << "Nonzero retval is not supported yet."; - ExitThread((DWORD)retval); -} -#endif // _WIN32 - -#endif // SANITIZER_PTHREAD_WRAPPERS_H diff --git a/lib/sanitizer_common/tests/sanitizer_quarantine_test.cc b/lib/sanitizer_common/tests/sanitizer_quarantine_test.cc deleted file mode 100644 index 23ed5f97ae27f..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_quarantine_test.cc +++ /dev/null @@ -1,180 +0,0 @@ -//===-- sanitizer_quarantine_test.cc --------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_quarantine.h" -#include "gtest/gtest.h" - -#include <stdlib.h> - -namespace __sanitizer { - -struct QuarantineCallback { - void Recycle(void *m) {} - void *Allocate(uptr size) { - return malloc(size); - } - void Deallocate(void *p) { - free(p); - } -}; - -typedef QuarantineCache<QuarantineCallback> Cache; - -static void* kFakePtr = reinterpret_cast<void*>(0xFA83FA83); -static const size_t kBlockSize = 8; - -static QuarantineCallback cb; - -static void DeallocateCache(Cache *cache) { - while (QuarantineBatch *batch = cache->DequeueBatch()) - cb.Deallocate(batch); -} - -TEST(SanitizerCommon, QuarantineBatchMerge) { - // Verify the trivial case. - QuarantineBatch into; - into.init(kFakePtr, 4UL); - QuarantineBatch from; - from.init(kFakePtr, 8UL); - - into.merge(&from); - - ASSERT_EQ(into.count, 2UL); - ASSERT_EQ(into.batch[0], kFakePtr); - ASSERT_EQ(into.batch[1], kFakePtr); - ASSERT_EQ(into.size, 12UL + sizeof(QuarantineBatch)); - ASSERT_EQ(into.quarantined_size(), 12UL); - - ASSERT_EQ(from.count, 0UL); - ASSERT_EQ(from.size, sizeof(QuarantineBatch)); - ASSERT_EQ(from.quarantined_size(), 0UL); - - // Merge the batch to the limit. - for (uptr i = 2; i < QuarantineBatch::kSize; ++i) - from.push_back(kFakePtr, 8UL); - ASSERT_TRUE(into.count + from.count == QuarantineBatch::kSize); - ASSERT_TRUE(into.can_merge(&from)); - - into.merge(&from); - ASSERT_TRUE(into.count == QuarantineBatch::kSize); - - // No more space, not even for one element. - from.init(kFakePtr, 8UL); - - ASSERT_FALSE(into.can_merge(&from)); -} - -TEST(SanitizerCommon, QuarantineCacheMergeBatchesEmpty) { - Cache cache; - Cache to_deallocate; - cache.MergeBatches(&to_deallocate); - - ASSERT_EQ(to_deallocate.Size(), 0UL); - ASSERT_EQ(to_deallocate.DequeueBatch(), nullptr); -} - -TEST(SanitizerCommon, QuarantineCacheMergeBatchesOneBatch) { - Cache cache; - cache.Enqueue(cb, kFakePtr, kBlockSize); - ASSERT_EQ(kBlockSize + sizeof(QuarantineBatch), cache.Size()); - - Cache to_deallocate; - cache.MergeBatches(&to_deallocate); - - // Nothing to merge, nothing to deallocate. - ASSERT_EQ(kBlockSize + sizeof(QuarantineBatch), cache.Size()); - - ASSERT_EQ(to_deallocate.Size(), 0UL); - ASSERT_EQ(to_deallocate.DequeueBatch(), nullptr); - - DeallocateCache(&cache); -} - -TEST(SanitizerCommon, QuarantineCacheMergeBatchesSmallBatches) { - // Make a cache with two batches small enough to merge. - Cache from; - from.Enqueue(cb, kFakePtr, kBlockSize); - Cache cache; - cache.Enqueue(cb, kFakePtr, kBlockSize); - - cache.Transfer(&from); - ASSERT_EQ(kBlockSize * 2 + sizeof(QuarantineBatch) * 2, cache.Size()); - - Cache to_deallocate; - cache.MergeBatches(&to_deallocate); - - // Batches merged, one batch to deallocate. - ASSERT_EQ(kBlockSize * 2 + sizeof(QuarantineBatch), cache.Size()); - ASSERT_EQ(to_deallocate.Size(), sizeof(QuarantineBatch)); - - DeallocateCache(&cache); - DeallocateCache(&to_deallocate); -} - -TEST(SanitizerCommon, QuarantineCacheMergeBatchesTooBigToMerge) { - const uptr kNumBlocks = QuarantineBatch::kSize - 1; - - // Make a cache with two batches small enough to merge. - Cache from; - Cache cache; - for (uptr i = 0; i < kNumBlocks; ++i) { - from.Enqueue(cb, kFakePtr, kBlockSize); - cache.Enqueue(cb, kFakePtr, kBlockSize); - } - cache.Transfer(&from); - ASSERT_EQ(kBlockSize * kNumBlocks * 2 + - sizeof(QuarantineBatch) * 2, cache.Size()); - - Cache to_deallocate; - cache.MergeBatches(&to_deallocate); - - // Batches cannot be merged. - ASSERT_EQ(kBlockSize * kNumBlocks * 2 + - sizeof(QuarantineBatch) * 2, cache.Size()); - ASSERT_EQ(to_deallocate.Size(), 0UL); - - DeallocateCache(&cache); -} - -TEST(SanitizerCommon, QuarantineCacheMergeBatchesALotOfBatches) { - const uptr kNumBatchesAfterMerge = 3; - const uptr kNumBlocks = QuarantineBatch::kSize * kNumBatchesAfterMerge; - const uptr kNumBatchesBeforeMerge = kNumBlocks; - - // Make a cache with many small batches. - Cache cache; - for (uptr i = 0; i < kNumBlocks; ++i) { - Cache from; - from.Enqueue(cb, kFakePtr, kBlockSize); - cache.Transfer(&from); - } - - ASSERT_EQ(kBlockSize * kNumBlocks + - sizeof(QuarantineBatch) * kNumBatchesBeforeMerge, cache.Size()); - - Cache to_deallocate; - cache.MergeBatches(&to_deallocate); - - // All blocks should fit into 3 batches. - ASSERT_EQ(kBlockSize * kNumBlocks + - sizeof(QuarantineBatch) * kNumBatchesAfterMerge, cache.Size()); - - ASSERT_EQ(to_deallocate.Size(), - sizeof(QuarantineBatch) * - (kNumBatchesBeforeMerge - kNumBatchesAfterMerge)); - - DeallocateCache(&cache); - DeallocateCache(&to_deallocate); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cc b/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cc deleted file mode 100644 index 80aa57c5290eb..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cc +++ /dev/null @@ -1,99 +0,0 @@ -//===-- sanitizer_vector_test.cc ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of *Sanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_ring_buffer.h" -#include "gtest/gtest.h" - -namespace __sanitizer { - -struct LargeStruct { - int64_t v; - int64_t extra[3]; - - explicit LargeStruct(int64_t v) : v(v) {} - operator int64_t() { return v; } -}; - -struct Struct10Bytes { - short t[3]; -}; - -TEST(RingBuffer, Construct) { - RingBuffer<int64_t> *RBlong = RingBuffer<int64_t>::New(20); - EXPECT_EQ(RBlong->size(), 20U); - RBlong->Delete(); -} - -template <class T> void TestRB() { - RingBuffer<T> *RB; - const size_t Sizes[] = {1, 2, 3, 5, 8, 16, 20, 40, 10000}; - for (size_t Size : Sizes) { - RB = RingBuffer<T>::New(Size); - EXPECT_EQ(RB->size(), Size); - RB->Delete(); - } - - RB = RingBuffer<T>::New(4); - EXPECT_EQ(RB->size(), 4U); -#define EXPECT_RING_BUFFER(a0, a1, a2, a3) \ - EXPECT_EQ((int64_t)(*RB)[0], (int64_t)a0); \ - EXPECT_EQ((int64_t)(*RB)[1], (int64_t)a1); \ - EXPECT_EQ((int64_t)(*RB)[2], (int64_t)a2); \ - EXPECT_EQ((int64_t)(*RB)[3], (int64_t)a3); - - RB->push(T(1)); EXPECT_RING_BUFFER(1, 0, 0, 0); - RB->push(T(2)); EXPECT_RING_BUFFER(2, 1, 0, 0); - RB->push(T(3)); EXPECT_RING_BUFFER(3, 2, 1, 0); - RB->push(T(4)); EXPECT_RING_BUFFER(4, 3, 2, 1); - RB->push(T(5)); EXPECT_RING_BUFFER(5, 4, 3, 2); - RB->push(T(6)); EXPECT_RING_BUFFER(6, 5, 4, 3); - RB->push(T(7)); EXPECT_RING_BUFFER(7, 6, 5, 4); - RB->push(T(8)); EXPECT_RING_BUFFER(8, 7, 6, 5); - RB->push(T(9)); EXPECT_RING_BUFFER(9, 8, 7, 6); - RB->push(T(10)); EXPECT_RING_BUFFER(10, 9, 8, 7); - RB->push(T(11)); EXPECT_RING_BUFFER(11, 10, 9, 8); - RB->push(T(12)); EXPECT_RING_BUFFER(12, 11, 10, 9); - -#undef EXPECT_RING_BUFFER -} - -#if SANITIZER_WORDSIZE == 64 -TEST(RingBuffer, int64) { - TestRB<int64_t>(); -} - -TEST(RingBuffer, LargeStruct) { - TestRB<LargeStruct>(); -} - -template<typename T> -CompactRingBuffer<T> *AllocCompactRingBuffer(size_t count) { - size_t sz = sizeof(T) * count; - EXPECT_EQ(0ULL, sz % 4096); - void *p = MmapAlignedOrDieOnFatalError(sz, sz * 2, "CompactRingBuffer"); - return new CompactRingBuffer<T>(p, sz); -} - -TEST(CompactRingBuffer, int64) { - const size_t page_sizes[] = {1, 2, 4, 128}; - - for (size_t pages : page_sizes) { - size_t count = 4096 * pages / sizeof(int64_t); - auto R = AllocCompactRingBuffer<int64_t>(count); - int64_t top = count * 3 + 13; - for (int64_t i = 0; i < top; ++i) R->push(i); - for (int64_t i = 0; i < (int64_t)count; ++i) - EXPECT_EQ(top - i - 1, (*R)[i]); - } -} -#endif -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc b/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc deleted file mode 100644 index 513432fac214a..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc +++ /dev/null @@ -1,93 +0,0 @@ -//===-- sanitizer_stackdepot_test.cc --------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_stackdepot.h" -#include "sanitizer_common/sanitizer_internal_defs.h" -#include "sanitizer_common/sanitizer_libc.h" -#include "gtest/gtest.h" - -namespace __sanitizer { - -TEST(SanitizerCommon, StackDepotBasic) { - uptr array[] = {1, 2, 3, 4, 5}; - StackTrace s1(array, ARRAY_SIZE(array)); - u32 i1 = StackDepotPut(s1); - StackTrace stack = StackDepotGet(i1); - EXPECT_NE(stack.trace, (uptr*)0); - EXPECT_EQ(ARRAY_SIZE(array), stack.size); - EXPECT_EQ(0, internal_memcmp(stack.trace, array, sizeof(array))); -} - -TEST(SanitizerCommon, StackDepotAbsent) { - StackTrace stack = StackDepotGet((1 << 30) - 1); - EXPECT_EQ((uptr*)0, stack.trace); -} - -TEST(SanitizerCommon, StackDepotEmptyStack) { - u32 i1 = StackDepotPut(StackTrace()); - StackTrace stack = StackDepotGet(i1); - EXPECT_EQ((uptr*)0, stack.trace); -} - -TEST(SanitizerCommon, StackDepotZeroId) { - StackTrace stack = StackDepotGet(0); - EXPECT_EQ((uptr*)0, stack.trace); -} - -TEST(SanitizerCommon, StackDepotSame) { - uptr array[] = {1, 2, 3, 4, 6}; - StackTrace s1(array, ARRAY_SIZE(array)); - u32 i1 = StackDepotPut(s1); - u32 i2 = StackDepotPut(s1); - EXPECT_EQ(i1, i2); - StackTrace stack = StackDepotGet(i1); - EXPECT_NE(stack.trace, (uptr*)0); - EXPECT_EQ(ARRAY_SIZE(array), stack.size); - EXPECT_EQ(0, internal_memcmp(stack.trace, array, sizeof(array))); -} - -TEST(SanitizerCommon, StackDepotSeveral) { - uptr array1[] = {1, 2, 3, 4, 7}; - StackTrace s1(array1, ARRAY_SIZE(array1)); - u32 i1 = StackDepotPut(s1); - uptr array2[] = {1, 2, 3, 4, 8, 9}; - StackTrace s2(array2, ARRAY_SIZE(array2)); - u32 i2 = StackDepotPut(s2); - EXPECT_NE(i1, i2); -} - -TEST(SanitizerCommon, StackDepotReverseMap) { - uptr array1[] = {1, 2, 3, 4, 5}; - uptr array2[] = {7, 1, 3, 0}; - uptr array3[] = {10, 2, 5, 3}; - uptr array4[] = {1, 3, 2, 5}; - u32 ids[4] = {0}; - StackTrace s1(array1, ARRAY_SIZE(array1)); - StackTrace s2(array2, ARRAY_SIZE(array2)); - StackTrace s3(array3, ARRAY_SIZE(array3)); - StackTrace s4(array4, ARRAY_SIZE(array4)); - ids[0] = StackDepotPut(s1); - ids[1] = StackDepotPut(s2); - ids[2] = StackDepotPut(s3); - ids[3] = StackDepotPut(s4); - - StackDepotReverseMap map; - - for (uptr i = 0; i < 4; i++) { - StackTrace stack = StackDepotGet(ids[i]); - StackTrace from_map = map.Get(ids[i]); - EXPECT_EQ(stack.size, from_map.size); - EXPECT_EQ(stack.trace, from_map.trace); - } -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc b/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc deleted file mode 100644 index 405f8d86ea3c1..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc +++ /dev/null @@ -1,157 +0,0 @@ -//===-- sanitizer_common_printer_test.cc ----------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of sanitizer_common test suite. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_stacktrace_printer.h" - -#include "gtest/gtest.h" - -namespace __sanitizer { - -TEST(SanitizerStacktracePrinter, RenderSourceLocation) { - InternalScopedString str(128); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, false, ""); - EXPECT_STREQ("/dir/file.cc:10:5", str.data()); - - str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 11, 0, false, ""); - EXPECT_STREQ("/dir/file.cc:11", str.data()); - - str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 0, 0, false, ""); - EXPECT_STREQ("/dir/file.cc", str.data()); - - str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, false, "/dir/"); - EXPECT_STREQ("file.cc:10:5", str.data()); - - str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, true, ""); - EXPECT_STREQ("/dir/file.cc(10,5)", str.data()); - - str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 11, 0, true, ""); - EXPECT_STREQ("/dir/file.cc(11)", str.data()); - - str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 0, 0, true, ""); - EXPECT_STREQ("/dir/file.cc", str.data()); - - str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, true, "/dir/"); - EXPECT_STREQ("file.cc(10,5)", str.data()); -} - -TEST(SanitizerStacktracePrinter, RenderModuleLocation) { - InternalScopedString str(128); - RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchUnknown, ""); - EXPECT_STREQ("(/dir/exe+0x123)", str.data()); - - // Check that we strip file prefix if necessary. - str.clear(); - RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchUnknown, "/dir/"); - EXPECT_STREQ("(exe+0x123)", str.data()); - - // Check that we render the arch. - str.clear(); - RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchX86_64H, "/dir/"); - EXPECT_STREQ("(exe:x86_64h+0x123)", str.data()); -} - -TEST(SanitizerStacktracePrinter, RenderFrame) { - int frame_no = 42; - AddressInfo info; - info.address = 0x400000; - info.module = internal_strdup("/path/to/my/module"); - info.module_offset = 0x200; - info.function = internal_strdup("function_foo"); - info.function_offset = 0x100; - info.file = internal_strdup("/path/to/my/source"); - info.line = 10; - info.column = 5; - InternalScopedString str(256); - - // Dump all the AddressInfo fields. - RenderFrame(&str, "%% Frame:%n PC:%p Module:%m ModuleOffset:%o " - "Function:%f FunctionOffset:%q Source:%s Line:%l " - "Column:%c", - frame_no, info, false, "/path/to/", "function_"); - EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 " - "Function:foo FunctionOffset:0x100 Source:my/source Line:10 " - "Column:5", - str.data()); - info.Clear(); - str.clear(); - - // Test special format specifiers. - info.address = 0x400000; - RenderFrame(&str, "%M", frame_no, info, false); - EXPECT_NE(nullptr, internal_strstr(str.data(), "400000")); - str.clear(); - - RenderFrame(&str, "%L", frame_no, info, false); - EXPECT_STREQ("(<unknown module>)", str.data()); - str.clear(); - - info.module = internal_strdup("/path/to/module"); - info.module_offset = 0x200; - RenderFrame(&str, "%M", frame_no, info, false); - EXPECT_NE(nullptr, internal_strstr(str.data(), "(module+0x")); - EXPECT_NE(nullptr, internal_strstr(str.data(), "200")); - str.clear(); - - RenderFrame(&str, "%L", frame_no, info, false); - EXPECT_STREQ("(/path/to/module+0x200)", str.data()); - str.clear(); - - info.function = internal_strdup("my_function"); - RenderFrame(&str, "%F", frame_no, info, false); - EXPECT_STREQ("in my_function", str.data()); - str.clear(); - - info.function_offset = 0x100; - RenderFrame(&str, "%F %S", frame_no, info, false); - EXPECT_STREQ("in my_function+0x100 <null>", str.data()); - str.clear(); - - info.file = internal_strdup("my_file"); - RenderFrame(&str, "%F %S", frame_no, info, false); - EXPECT_STREQ("in my_function my_file", str.data()); - str.clear(); - - info.line = 10; - RenderFrame(&str, "%F %S", frame_no, info, false); - EXPECT_STREQ("in my_function my_file:10", str.data()); - str.clear(); - - info.column = 5; - RenderFrame(&str, "%S %L", frame_no, info, false); - EXPECT_STREQ("my_file:10:5 my_file:10:5", str.data()); - str.clear(); - - RenderFrame(&str, "%S %L", frame_no, info, true); - EXPECT_STREQ("my_file(10,5) my_file(10,5)", str.data()); - str.clear(); - - info.column = 0; - RenderFrame(&str, "%F %S", frame_no, info, true); - EXPECT_STREQ("in my_function my_file(10)", str.data()); - str.clear(); - - info.line = 0; - RenderFrame(&str, "%F %S", frame_no, info, true); - EXPECT_STREQ("in my_function my_file", str.data()); - str.clear(); - - info.Clear(); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc deleted file mode 100644 index ba9f4fd693265..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc +++ /dev/null @@ -1,167 +0,0 @@ -//===-- sanitizer_stacktrace_test.cc --------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_stacktrace.h" -#include "gtest/gtest.h" - -namespace __sanitizer { - -class FastUnwindTest : public ::testing::Test { - protected: - virtual void SetUp(); - virtual void TearDown(); - bool TryFastUnwind(uptr max_depth) { - if (!StackTrace::WillUseFastUnwind(true)) - return false; - trace.Unwind(max_depth, start_pc, (uptr)&fake_stack[0], 0, fake_top, - fake_bottom, true); - return true; - } - - void *mapping; - uhwptr *fake_stack; - const uptr fake_stack_size = 10; - uhwptr start_pc; - uhwptr fake_top; - uhwptr fake_bottom; - BufferedStackTrace trace; -}; - -static uptr PC(uptr idx) { - return (1<<20) + idx; -} - -void FastUnwindTest::SetUp() { - size_t ps = GetPageSize(); - mapping = MmapOrDie(2 * ps, "FastUnwindTest"); - MprotectNoAccess((uptr)mapping, ps); - - // Unwinder may peek 1 word down from the starting FP. - fake_stack = (uhwptr *)((uptr)mapping + ps + sizeof(uhwptr)); - - // Fill an array of pointers with fake fp+retaddr pairs. Frame pointers have - // even indices. - for (uptr i = 0; i + 1 < fake_stack_size; i += 2) { - fake_stack[i] = (uptr)&fake_stack[i+2]; // fp - fake_stack[i+1] = PC(i + 1); // retaddr - } - // Mark the last fp point back up to terminate the stack trace. - fake_stack[RoundDownTo(fake_stack_size - 1, 2)] = (uhwptr)&fake_stack[0]; - - // Top is two slots past the end because FastUnwindStack subtracts two. - fake_top = (uhwptr)&fake_stack[fake_stack_size + 2]; - // Bottom is one slot before the start because FastUnwindStack uses >. - fake_bottom = (uhwptr)mapping; - start_pc = PC(0); -} - -void FastUnwindTest::TearDown() { - size_t ps = GetPageSize(); - UnmapOrDie(mapping, 2 * ps); -} - -TEST_F(FastUnwindTest, Basic) { - if (!TryFastUnwind(kStackTraceMax)) - return; - // Should get all on-stack retaddrs and start_pc. - EXPECT_EQ(6U, trace.size); - EXPECT_EQ(start_pc, trace.trace[0]); - for (uptr i = 1; i <= 5; i++) { - EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); - } -} - -// From: https://github.com/google/sanitizers/issues/162 -TEST_F(FastUnwindTest, FramePointerLoop) { - // Make one fp point to itself. - fake_stack[4] = (uhwptr)&fake_stack[4]; - if (!TryFastUnwind(kStackTraceMax)) - return; - // Should get all on-stack retaddrs up to the 4th slot and start_pc. - EXPECT_EQ(4U, trace.size); - EXPECT_EQ(start_pc, trace.trace[0]); - for (uptr i = 1; i <= 3; i++) { - EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); - } -} - -TEST_F(FastUnwindTest, MisalignedFramePointer) { - // Make one fp misaligned. - fake_stack[4] += 3; - if (!TryFastUnwind(kStackTraceMax)) - return; - // Should get all on-stack retaddrs up to the 4th slot and start_pc. - EXPECT_EQ(4U, trace.size); - EXPECT_EQ(start_pc, trace.trace[0]); - for (uptr i = 1; i < 4U; i++) { - EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); - } -} - -TEST_F(FastUnwindTest, OneFrameStackTrace) { - if (!TryFastUnwind(1)) - return; - EXPECT_EQ(1U, trace.size); - EXPECT_EQ(start_pc, trace.trace[0]); - EXPECT_EQ((uhwptr)&fake_stack[0], trace.top_frame_bp); -} - -TEST_F(FastUnwindTest, ZeroFramesStackTrace) { - if (!TryFastUnwind(0)) - return; - EXPECT_EQ(0U, trace.size); - EXPECT_EQ(0U, trace.top_frame_bp); -} - -TEST_F(FastUnwindTest, FPBelowPrevFP) { - // The next FP points to unreadable memory inside the stack limits, but below - // current FP. - fake_stack[0] = (uhwptr)&fake_stack[-50]; - fake_stack[1] = PC(1); - if (!TryFastUnwind(3)) - return; - EXPECT_EQ(2U, trace.size); - EXPECT_EQ(PC(0), trace.trace[0]); - EXPECT_EQ(PC(1), trace.trace[1]); -} - -TEST_F(FastUnwindTest, CloseToZeroFrame) { - // Make one pc a NULL pointer. - fake_stack[5] = 0x0; - if (!TryFastUnwind(kStackTraceMax)) - return; - // The stack should be truncated at the NULL pointer (and not include it). - EXPECT_EQ(3U, trace.size); - EXPECT_EQ(start_pc, trace.trace[0]); - for (uptr i = 1; i < 3U; i++) { - EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); - } -} - -TEST(SlowUnwindTest, ShortStackTrace) { - if (StackTrace::WillUseFastUnwind(false)) - return; - BufferedStackTrace stack; - uptr pc = StackTrace::GetCurrentPc(); - uptr bp = GET_CURRENT_FRAME(); - stack.Unwind(0, pc, bp, 0, 0, 0, false); - EXPECT_EQ(0U, stack.size); - EXPECT_EQ(0U, stack.top_frame_bp); - stack.Unwind(1, pc, bp, 0, 0, 0, false); - EXPECT_EQ(1U, stack.size); - EXPECT_EQ(pc, stack.trace[0]); - EXPECT_EQ(bp, stack.top_frame_bp); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc b/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc deleted file mode 100644 index 802af392c6096..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc +++ /dev/null @@ -1,204 +0,0 @@ -//===-- sanitizer_stoptheworld_test.cc ------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tests for sanitizer_stoptheworld.h -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_LINUX && defined(__x86_64__) - -#include "sanitizer_common/sanitizer_stoptheworld.h" -#include "gtest/gtest.h" - -#include "sanitizer_common/sanitizer_libc.h" -#include "sanitizer_common/sanitizer_common.h" - -#include <pthread.h> -#include <sched.h> - -namespace __sanitizer { - -static pthread_mutex_t incrementer_thread_exit_mutex; - -struct CallbackArgument { - volatile int counter; - volatile bool threads_stopped; - volatile bool callback_executed; - CallbackArgument() - : counter(0), - threads_stopped(false), - callback_executed(false) {} -}; - -void *IncrementerThread(void *argument) { - CallbackArgument *callback_argument = (CallbackArgument *)argument; - while (true) { - __sync_fetch_and_add(&callback_argument->counter, 1); - if (pthread_mutex_trylock(&incrementer_thread_exit_mutex) == 0) { - pthread_mutex_unlock(&incrementer_thread_exit_mutex); - return NULL; - } else { - sched_yield(); - } - } -} - -// This callback checks that IncrementerThread is suspended at the time of its -// execution. -void Callback(const SuspendedThreadsList &suspended_threads_list, - void *argument) { - CallbackArgument *callback_argument = (CallbackArgument *)argument; - callback_argument->callback_executed = true; - int counter_at_init = __sync_fetch_and_add(&callback_argument->counter, 0); - for (uptr i = 0; i < 1000; i++) { - sched_yield(); - if (__sync_fetch_and_add(&callback_argument->counter, 0) != - counter_at_init) { - callback_argument->threads_stopped = false; - return; - } - } - callback_argument->threads_stopped = true; -} - -TEST(StopTheWorld, SuspendThreadsSimple) { - pthread_mutex_init(&incrementer_thread_exit_mutex, NULL); - CallbackArgument argument; - pthread_t thread_id; - int pthread_create_result; - pthread_mutex_lock(&incrementer_thread_exit_mutex); - pthread_create_result = pthread_create(&thread_id, NULL, IncrementerThread, - &argument); - ASSERT_EQ(0, pthread_create_result); - StopTheWorld(&Callback, &argument); - pthread_mutex_unlock(&incrementer_thread_exit_mutex); - EXPECT_TRUE(argument.callback_executed); - EXPECT_TRUE(argument.threads_stopped); - // argument is on stack, so we have to wait for the incrementer thread to - // terminate before we can return from this function. - ASSERT_EQ(0, pthread_join(thread_id, NULL)); - pthread_mutex_destroy(&incrementer_thread_exit_mutex); -} - -// A more comprehensive test where we spawn a bunch of threads while executing -// StopTheWorld in parallel. -static const uptr kThreadCount = 50; -static const uptr kStopWorldAfter = 10; // let this many threads spawn first - -static pthread_mutex_t advanced_incrementer_thread_exit_mutex; - -struct AdvancedCallbackArgument { - volatile uptr thread_index; - volatile int counters[kThreadCount]; - pthread_t thread_ids[kThreadCount]; - volatile bool threads_stopped; - volatile bool callback_executed; - volatile bool fatal_error; - AdvancedCallbackArgument() - : thread_index(0), - threads_stopped(false), - callback_executed(false), - fatal_error(false) {} -}; - -void *AdvancedIncrementerThread(void *argument) { - AdvancedCallbackArgument *callback_argument = - (AdvancedCallbackArgument *)argument; - uptr this_thread_index = __sync_fetch_and_add( - &callback_argument->thread_index, 1); - // Spawn the next thread. - int pthread_create_result; - if (this_thread_index + 1 < kThreadCount) { - pthread_create_result = - pthread_create(&callback_argument->thread_ids[this_thread_index + 1], - NULL, AdvancedIncrementerThread, argument); - // Cannot use ASSERT_EQ in non-void-returning functions. If there's a - // problem, defer failing to the main thread. - if (pthread_create_result != 0) { - callback_argument->fatal_error = true; - __sync_fetch_and_add(&callback_argument->thread_index, - kThreadCount - callback_argument->thread_index); - } - } - // Do the actual work. - while (true) { - __sync_fetch_and_add(&callback_argument->counters[this_thread_index], 1); - if (pthread_mutex_trylock(&advanced_incrementer_thread_exit_mutex) == 0) { - pthread_mutex_unlock(&advanced_incrementer_thread_exit_mutex); - return NULL; - } else { - sched_yield(); - } - } -} - -void AdvancedCallback(const SuspendedThreadsList &suspended_threads_list, - void *argument) { - AdvancedCallbackArgument *callback_argument = - (AdvancedCallbackArgument *)argument; - callback_argument->callback_executed = true; - - int counters_at_init[kThreadCount]; - for (uptr j = 0; j < kThreadCount; j++) - counters_at_init[j] = __sync_fetch_and_add(&callback_argument->counters[j], - 0); - for (uptr i = 0; i < 10; i++) { - sched_yield(); - for (uptr j = 0; j < kThreadCount; j++) - if (__sync_fetch_and_add(&callback_argument->counters[j], 0) != - counters_at_init[j]) { - callback_argument->threads_stopped = false; - return; - } - } - callback_argument->threads_stopped = true; -} - -TEST(StopTheWorld, SuspendThreadsAdvanced) { - pthread_mutex_init(&advanced_incrementer_thread_exit_mutex, NULL); - AdvancedCallbackArgument argument; - - pthread_mutex_lock(&advanced_incrementer_thread_exit_mutex); - int pthread_create_result; - pthread_create_result = pthread_create(&argument.thread_ids[0], NULL, - AdvancedIncrementerThread, - &argument); - ASSERT_EQ(0, pthread_create_result); - // Wait for several threads to spawn before proceeding. - while (__sync_fetch_and_add(&argument.thread_index, 0) < kStopWorldAfter) - sched_yield(); - StopTheWorld(&AdvancedCallback, &argument); - EXPECT_TRUE(argument.callback_executed); - EXPECT_TRUE(argument.threads_stopped); - - // Wait for all threads to spawn before we start terminating them. - while (__sync_fetch_and_add(&argument.thread_index, 0) < kThreadCount) - sched_yield(); - ASSERT_FALSE(argument.fatal_error); // a pthread_create has failed - // Signal the threads to terminate. - pthread_mutex_unlock(&advanced_incrementer_thread_exit_mutex); - for (uptr i = 0; i < kThreadCount; i++) - ASSERT_EQ(0, pthread_join(argument.thread_ids[i], NULL)); - pthread_mutex_destroy(&advanced_incrementer_thread_exit_mutex); -} - -static void SegvCallback(const SuspendedThreadsList &suspended_threads_list, - void *argument) { - *(volatile int*)0x1234 = 0; -} - -TEST(StopTheWorld, SegvInCallback) { - // Test that tracer thread catches SIGSEGV. - StopTheWorld(&SegvCallback, NULL); -} - -} // namespace __sanitizer - -#endif // SANITIZER_LINUX && defined(__x86_64__) diff --git a/lib/sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc b/lib/sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc deleted file mode 100644 index d8be2afb19e9c..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc +++ /dev/null @@ -1,53 +0,0 @@ -//===-- sanitizer_stoptheworld_testlib.cc ---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Dynamic library to test StopTheWorld functionality. -// When loaded with LD_PRELOAD, it will periodically suspend all threads. -//===----------------------------------------------------------------------===// -/* Usage: -clang++ -fno-exceptions -g -fPIC -I. \ - sanitizer_common/tests/sanitizer_stoptheworld_testlib.cc \ - sanitizer_common/sanitizer_*.cc -shared -lpthread -o teststoptheworld.so -LD_PRELOAD=`pwd`/teststoptheworld.so /your/app -*/ - -#include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_LINUX - -#include <dlfcn.h> -#include <stddef.h> -#include <stdio.h> -#include <pthread.h> -#include <unistd.h> - -#include "sanitizer_common/sanitizer_stoptheworld.h" - -namespace { -const uptr kSuspendDuration = 3; -const uptr kRunDuration = 3; - -void Callback(const SuspendedThreadsList &suspended_threads_list, - void *argument) { - sleep(kSuspendDuration); -} - -void *SuspenderThread(void *argument) { - while (true) { - sleep(kRunDuration); - StopTheWorld(Callback, NULL); - } - return NULL; -} - -__attribute__((constructor)) void StopTheWorldTestLibConstructor(void) { - pthread_t thread_id; - pthread_create(&thread_id, NULL, SuspenderThread, NULL); -} -} // namespace - -#endif // SANITIZER_LINUX diff --git a/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc b/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc deleted file mode 100644 index 224ab05383774..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc +++ /dev/null @@ -1,135 +0,0 @@ -//===-- sanitizer_suppressions_test.cc ------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_suppressions.h" -#include "gtest/gtest.h" - -#include <string.h> - -namespace __sanitizer { - -static bool MyMatch(const char *templ, const char *func) { - char tmp[1024]; - strcpy(tmp, templ); // NOLINT - return TemplateMatch(tmp, func); -} - -TEST(Suppressions, Match) { - EXPECT_TRUE(MyMatch("foobar$", "foobar")); - - EXPECT_TRUE(MyMatch("foobar", "foobar")); - EXPECT_TRUE(MyMatch("*foobar*", "foobar")); - EXPECT_TRUE(MyMatch("foobar", "prefix_foobar_postfix")); - EXPECT_TRUE(MyMatch("*foobar*", "prefix_foobar_postfix")); - EXPECT_TRUE(MyMatch("foo*bar", "foo_middle_bar")); - EXPECT_TRUE(MyMatch("foo*bar", "foobar")); - EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_bar_another_baz")); - EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_barbaz")); - EXPECT_TRUE(MyMatch("^foobar", "foobar")); - EXPECT_TRUE(MyMatch("^foobar", "foobar_postfix")); - EXPECT_TRUE(MyMatch("^*foobar", "foobar")); - EXPECT_TRUE(MyMatch("^*foobar", "prefix_foobar")); - EXPECT_TRUE(MyMatch("foobar$", "foobar")); - EXPECT_TRUE(MyMatch("foobar$", "prefix_foobar")); - EXPECT_TRUE(MyMatch("*foobar*$", "foobar")); - EXPECT_TRUE(MyMatch("*foobar*$", "foobar_postfix")); - EXPECT_TRUE(MyMatch("^foobar$", "foobar")); - - EXPECT_FALSE(MyMatch("foo", "baz")); - EXPECT_FALSE(MyMatch("foobarbaz", "foobar")); - EXPECT_FALSE(MyMatch("foobarbaz", "barbaz")); - EXPECT_FALSE(MyMatch("foo*bar", "foobaz")); - EXPECT_FALSE(MyMatch("foo*bar", "foo_baz")); - EXPECT_FALSE(MyMatch("^foobar", "prefix_foobar")); - EXPECT_FALSE(MyMatch("foobar$", "foobar_postfix")); - EXPECT_FALSE(MyMatch("^foobar$", "prefix_foobar")); - EXPECT_FALSE(MyMatch("^foobar$", "foobar_postfix")); - EXPECT_FALSE(MyMatch("foo^bar", "foobar")); - EXPECT_FALSE(MyMatch("foo$bar", "foobar")); - EXPECT_FALSE(MyMatch("foo$^bar", "foobar")); -} - -static const char *kTestSuppressionTypes[] = {"race", "thread", "mutex", - "signal"}; - -class SuppressionContextTest : public ::testing::Test { - public: - SuppressionContextTest() - : ctx_(kTestSuppressionTypes, ARRAY_SIZE(kTestSuppressionTypes)) {} - - protected: - SuppressionContext ctx_; - - void CheckSuppressions(unsigned count, std::vector<const char *> types, - std::vector<const char *> templs) const { - EXPECT_EQ(count, ctx_.SuppressionCount()); - for (unsigned i = 0; i < count; i++) { - const Suppression *s = ctx_.SuppressionAt(i); - EXPECT_STREQ(types[i], s->type); - EXPECT_STREQ(templs[i], s->templ); - } - } -}; - -TEST_F(SuppressionContextTest, Parse) { - ctx_.Parse("race:foo\n" - " race:bar\n" // NOLINT - "race:baz \n" // NOLINT - "# a comment\n" - "race:quz\n"); // NOLINT - CheckSuppressions(4, {"race", "race", "race", "race"}, - {"foo", "bar", "baz", "quz"}); -} - -TEST_F(SuppressionContextTest, Parse2) { - ctx_.Parse( - " # first line comment\n" // NOLINT - " race:bar \n" // NOLINT - "race:baz* *baz\n" - "# a comment\n" - "# last line comment\n" - ); // NOLINT - CheckSuppressions(2, {"race", "race"}, {"bar", "baz* *baz"}); -} - -TEST_F(SuppressionContextTest, Parse3) { - ctx_.Parse( - "# last suppression w/o line-feed\n" - "race:foo\n" - "race:bar\r\n" - "race:baz" - ); // NOLINT - CheckSuppressions(3, {"race", "race", "race"}, {"foo", "bar", "baz"}); -} - -TEST_F(SuppressionContextTest, ParseType) { - ctx_.Parse( - "race:foo\n" - "thread:bar\n" - "mutex:baz\n" - "signal:quz\n" - ); // NOLINT - CheckSuppressions(4, {"race", "thread", "mutex", "signal"}, - {"foo", "bar", "baz", "quz"}); -} - -TEST_F(SuppressionContextTest, HasSuppressionType) { - ctx_.Parse( - "race:foo\n" - "thread:bar\n"); - EXPECT_TRUE(ctx_.HasSuppressionType("race")); - EXPECT_TRUE(ctx_.HasSuppressionType("thread")); - EXPECT_FALSE(ctx_.HasSuppressionType("mutex")); - EXPECT_FALSE(ctx_.HasSuppressionType("signal")); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc b/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc deleted file mode 100644 index 4c4d2a8c3fb20..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_symbolizer_test.cc +++ /dev/null @@ -1,72 +0,0 @@ -//===-- sanitizer_symbolizer_test.cc --------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tests for sanitizer_symbolizer.h and sanitizer_symbolizer_internal.h -// -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_allocator_internal.h" -#include "sanitizer_common/sanitizer_symbolizer_internal.h" -#include "gtest/gtest.h" - -namespace __sanitizer { - -TEST(Symbolizer, ExtractToken) { - char *token; - const char *rest; - - rest = ExtractToken("a;b;c", ";", &token); - EXPECT_STREQ("a", token); - EXPECT_STREQ("b;c", rest); - InternalFree(token); - - rest = ExtractToken("aaa-bbb.ccc", ";.-*", &token); - EXPECT_STREQ("aaa", token); - EXPECT_STREQ("bbb.ccc", rest); - InternalFree(token); -} - -TEST(Symbolizer, ExtractInt) { - int token; - const char *rest = ExtractInt("123,456;789", ";,", &token); - EXPECT_EQ(123, token); - EXPECT_STREQ("456;789", rest); -} - -TEST(Symbolizer, ExtractUptr) { - uptr token; - const char *rest = ExtractUptr("123,456;789", ";,", &token); - EXPECT_EQ(123U, token); - EXPECT_STREQ("456;789", rest); -} - -TEST(Symbolizer, ExtractTokenUpToDelimiter) { - char *token; - const char *rest = - ExtractTokenUpToDelimiter("aaa-+-bbb-+-ccc", "-+-", &token); - EXPECT_STREQ("aaa", token); - EXPECT_STREQ("bbb-+-ccc", rest); - InternalFree(token); -} - -#if !SANITIZER_WINDOWS -TEST(Symbolizer, DemangleSwiftAndCXX) { - // Swift names are not demangled in default llvm build because Swift - // runtime is not linked in. - EXPECT_STREQ("_TtSd", DemangleSwiftAndCXX("_TtSd")); - // Check that the rest demangles properly. - EXPECT_STREQ("f1(char*, int)", DemangleSwiftAndCXX("_Z2f1Pci")); -#if !SANITIZER_FREEBSD // QoI issue with libcxxrt on FreeBSD - EXPECT_STREQ("foo", DemangleSwiftAndCXX("foo")); -#endif - EXPECT_STREQ("", DemangleSwiftAndCXX("")); -} -#endif - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_test_config.h b/lib/sanitizer_common/tests/sanitizer_test_config.h deleted file mode 100644 index bdf614606d6aa..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_test_config.h +++ /dev/null @@ -1,30 +0,0 @@ -//===-- sanitizer_test_config.h ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of *Sanitizer runtime. -// -//===----------------------------------------------------------------------===// -#if !defined(INCLUDED_FROM_SANITIZER_TEST_UTILS_H) -# error "This file should be included into sanitizer_test_utils.h only" -#endif - -#ifndef SANITIZER_TEST_CONFIG_H -#define SANITIZER_TEST_CONFIG_H - -#include <vector> -#include <string> -#include <map> - -#if SANITIZER_USE_DEJAGNU_GTEST -# include "dejagnu-gtest.h" -#else -# include "gtest/gtest.h" -#endif - -#endif // SANITIZER_TEST_CONFIG_H diff --git a/lib/sanitizer_common/tests/sanitizer_test_main.cc b/lib/sanitizer_common/tests/sanitizer_test_main.cc deleted file mode 100644 index 0da886120c31a..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_test_main.cc +++ /dev/null @@ -1,24 +0,0 @@ -//===-- sanitizer_test_main.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "gtest/gtest.h" -#include "sanitizer_common/sanitizer_flags.h" - -const char *argv0; - -int main(int argc, char **argv) { - argv0 = argv[0]; - testing::GTEST_FLAG(death_test_style) = "threadsafe"; - testing::InitGoogleTest(&argc, argv); - __sanitizer::SetCommonFlagsDefaults(); - return RUN_ALL_TESTS(); -} diff --git a/lib/sanitizer_common/tests/sanitizer_test_utils.h b/lib/sanitizer_common/tests/sanitizer_test_utils.h deleted file mode 100644 index 5c1f8ad488647..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_test_utils.h +++ /dev/null @@ -1,139 +0,0 @@ -//===-- sanitizer_test_utils.h ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of *Sanitizer runtime. -// Common unit tests utilities. -// -//===----------------------------------------------------------------------===// - -#ifndef SANITIZER_TEST_UTILS_H -#define SANITIZER_TEST_UTILS_H - -#if defined(_WIN32) -// <windows.h> should always be the first include on Windows. -# include <windows.h> -// MSVS headers define max/min as macros, so std::max/min gets crazy. -# undef max -# undef min -#endif - -#if !defined(SANITIZER_EXTERNAL_TEST_CONFIG) -# define INCLUDED_FROM_SANITIZER_TEST_UTILS_H -# include "sanitizer_test_config.h" -# undef INCLUDED_FROM_SANITIZER_TEST_UTILS_H -#endif - -#include <stdint.h> - -#if defined(_MSC_VER) -# define NOINLINE __declspec(noinline) -#else // defined(_MSC_VER) -# define NOINLINE __attribute__((noinline)) -#endif // defined(_MSC_VER) - -#if !defined(_MSC_VER) || defined(__clang__) -# define UNUSED __attribute__((unused)) -# define USED __attribute__((used)) -#else -# define UNUSED -# define USED -#endif - -#if !defined(__has_feature) -#define __has_feature(x) 0 -#endif - -#ifndef ATTRIBUTE_NO_SANITIZE_ADDRESS -# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) -# define ATTRIBUTE_NO_SANITIZE_ADDRESS \ - __attribute__((no_sanitize_address)) -# else -# define ATTRIBUTE_NO_SANITIZE_ADDRESS -# endif -#endif // ATTRIBUTE_NO_SANITIZE_ADDRESS - -#if __LP64__ || defined(_WIN64) -# define SANITIZER_WORDSIZE 64 -#else -# define SANITIZER_WORDSIZE 32 -#endif - -// Make the compiler thinks that something is going on there. -inline void break_optimization(void *arg) { -#if !defined(_WIN32) || defined(__clang__) - __asm__ __volatile__("" : : "r" (arg) : "memory"); -#endif -} - -// This function returns its parameter but in such a way that compiler -// can not prove it. -template<class T> -NOINLINE -static T Ident(T t) { - T ret = t; - break_optimization(&ret); - return ret; -} - -// Simple stand-alone pseudorandom number generator. -// Current algorithm is ANSI C linear congruential PRNG. -static inline uint32_t my_rand_r(uint32_t* state) { - return (*state = *state * 1103515245 + 12345) >> 16; -} - -static uint32_t global_seed = 0; - -static inline uint32_t my_rand() { - return my_rand_r(&global_seed); -} - -// Set availability of platform-specific functions. - -#if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) -# define SANITIZER_TEST_HAS_POSIX_MEMALIGN 1 -#else -# define SANITIZER_TEST_HAS_POSIX_MEMALIGN 0 -#endif - -#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__ANDROID__) && \ - !defined(__NetBSD__) && !defined(_WIN32) -# define SANITIZER_TEST_HAS_MEMALIGN 1 -#else -# define SANITIZER_TEST_HAS_MEMALIGN 0 -#endif - -#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__ANDROID__) && \ - !defined(__NetBSD__) && !defined(_WIN32) && \ - !(defined(__sun__) && defined(__svr4__)) -# define SANITIZER_TEST_HAS_PVALLOC 1 -# define SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE 1 -#else -# define SANITIZER_TEST_HAS_PVALLOC 0 -# define SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE 0 -#endif - -#if !defined(__APPLE__) -# define SANITIZER_TEST_HAS_STRNLEN 1 -#else -# define SANITIZER_TEST_HAS_STRNLEN 0 -#endif - -#if defined(__FreeBSD__) || defined(__NetBSD__) -# define SANITIZER_TEST_HAS_PRINTF_L 1 -#else -# define SANITIZER_TEST_HAS_PRINTF_L 0 -#endif - -#if !defined(_MSC_VER) -# define SANITIZER_TEST_HAS_STRNDUP 1 -#else -# define SANITIZER_TEST_HAS_STRNDUP 0 -#endif - -#endif // SANITIZER_TEST_UTILS_H diff --git a/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc b/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc deleted file mode 100644 index f8b8c12d4ac34..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc +++ /dev/null @@ -1,236 +0,0 @@ -//===-- sanitizer_thread_registry_test.cc ---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of shared sanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_thread_registry.h" - -#include "sanitizer_pthread_wrappers.h" - -#include "gtest/gtest.h" - -#include <vector> - -namespace __sanitizer { - -static BlockingMutex tctx_allocator_lock(LINKER_INITIALIZED); -static LowLevelAllocator tctx_allocator; - -template<typename TCTX> -static ThreadContextBase *GetThreadContext(u32 tid) { - BlockingMutexLock l(&tctx_allocator_lock); - return new(tctx_allocator) TCTX(tid); -} - -static const u32 kMaxRegistryThreads = 1000; -static const u32 kRegistryQuarantine = 2; - -static void CheckThreadQuantity(ThreadRegistry *registry, uptr exp_total, - uptr exp_running, uptr exp_alive) { - uptr total, running, alive; - registry->GetNumberOfThreads(&total, &running, &alive); - EXPECT_EQ(exp_total, total); - EXPECT_EQ(exp_running, running); - EXPECT_EQ(exp_alive, alive); -} - -static bool is_detached(u32 tid) { - return (tid % 2 == 0); -} - -static uptr get_uid(u32 tid) { - return tid * 2; -} - -static bool HasName(ThreadContextBase *tctx, void *arg) { - char *name = (char*)arg; - return (0 == internal_strcmp(tctx->name, name)); -} - -static bool HasUid(ThreadContextBase *tctx, void *arg) { - uptr uid = (uptr)arg; - return (tctx->user_id == uid); -} - -static void MarkUidAsPresent(ThreadContextBase *tctx, void *arg) { - bool *arr = (bool*)arg; - arr[tctx->tid] = true; -} - -static void TestRegistry(ThreadRegistry *registry, bool has_quarantine) { - // Create and start a main thread. - EXPECT_EQ(0U, registry->CreateThread(get_uid(0), true, -1, 0)); - registry->StartThread(0, 0, false, 0); - // Create a bunch of threads. - for (u32 i = 1; i <= 10; i++) { - EXPECT_EQ(i, registry->CreateThread(get_uid(i), is_detached(i), 0, 0)); - } - CheckThreadQuantity(registry, 11, 1, 11); - // Start some of them. - for (u32 i = 1; i <= 5; i++) { - registry->StartThread(i, 0, false, 0); - } - CheckThreadQuantity(registry, 11, 6, 11); - // Finish, create and start more threads. - for (u32 i = 1; i <= 5; i++) { - registry->FinishThread(i); - if (!is_detached(i)) - registry->JoinThread(i, 0); - } - for (u32 i = 6; i <= 10; i++) { - registry->StartThread(i, 0, false, 0); - } - std::vector<u32> new_tids; - for (u32 i = 11; i <= 15; i++) { - new_tids.push_back( - registry->CreateThread(get_uid(i), is_detached(i), 0, 0)); - } - ASSERT_LE(kRegistryQuarantine, 5U); - u32 exp_total = 16 - (has_quarantine ? 5 - kRegistryQuarantine : 0); - CheckThreadQuantity(registry, exp_total, 6, 11); - // Test SetThreadName and FindThread. - registry->SetThreadName(6, "six"); - registry->SetThreadName(7, "seven"); - EXPECT_EQ(7U, registry->FindThread(HasName, (void*)"seven")); - EXPECT_EQ(ThreadRegistry::kUnknownTid, - registry->FindThread(HasName, (void*)"none")); - EXPECT_EQ(0U, registry->FindThread(HasUid, (void*)get_uid(0))); - EXPECT_EQ(10U, registry->FindThread(HasUid, (void*)get_uid(10))); - EXPECT_EQ(ThreadRegistry::kUnknownTid, - registry->FindThread(HasUid, (void*)0x1234)); - // Detach and finish and join remaining threads. - for (u32 i = 6; i <= 10; i++) { - registry->DetachThread(i, 0); - registry->FinishThread(i); - } - for (u32 i = 0; i < new_tids.size(); i++) { - u32 tid = new_tids[i]; - registry->StartThread(tid, 0, false, 0); - registry->DetachThread(tid, 0); - registry->FinishThread(tid); - } - CheckThreadQuantity(registry, exp_total, 1, 1); - // Test methods that require the caller to hold a ThreadRegistryLock. - bool has_tid[16]; - internal_memset(&has_tid[0], 0, sizeof(has_tid)); - { - ThreadRegistryLock l(registry); - registry->RunCallbackForEachThreadLocked(MarkUidAsPresent, &has_tid[0]); - } - for (u32 i = 0; i < exp_total; i++) { - EXPECT_TRUE(has_tid[i]); - } - { - ThreadRegistryLock l(registry); - registry->CheckLocked(); - ThreadContextBase *main_thread = registry->GetThreadLocked(0); - EXPECT_EQ(main_thread, registry->FindThreadContextLocked( - HasUid, (void*)get_uid(0))); - } - EXPECT_EQ(11U, registry->GetMaxAliveThreads()); -} - -TEST(SanitizerCommon, ThreadRegistryTest) { - ThreadRegistry quarantine_registry(GetThreadContext<ThreadContextBase>, - kMaxRegistryThreads, - kRegistryQuarantine); - TestRegistry(&quarantine_registry, true); - - ThreadRegistry no_quarantine_registry(GetThreadContext<ThreadContextBase>, - kMaxRegistryThreads, - kMaxRegistryThreads); - TestRegistry(&no_quarantine_registry, false); -} - -static const int kThreadsPerShard = 20; -static const int kNumShards = 25; - -static int num_created[kNumShards + 1]; -static int num_started[kNumShards + 1]; -static int num_joined[kNumShards + 1]; - -namespace { - -struct RunThreadArgs { - ThreadRegistry *registry; - uptr shard; // started from 1. -}; - -class TestThreadContext : public ThreadContextBase { - public: - explicit TestThreadContext(int tid) : ThreadContextBase(tid) {} - void OnJoined(void *arg) { - uptr shard = (uptr)arg; - num_joined[shard]++; - } - void OnStarted(void *arg) { - uptr shard = (uptr)arg; - num_started[shard]++; - } - void OnCreated(void *arg) { - uptr shard = (uptr)arg; - num_created[shard]++; - } -}; - -} // namespace - -void *RunThread(void *arg) { - RunThreadArgs *args = static_cast<RunThreadArgs*>(arg); - std::vector<int> tids; - for (int i = 0; i < kThreadsPerShard; i++) - tids.push_back( - args->registry->CreateThread(0, false, 0, (void*)args->shard)); - for (int i = 0; i < kThreadsPerShard; i++) - args->registry->StartThread(tids[i], 0, false, (void*)args->shard); - for (int i = 0; i < kThreadsPerShard; i++) - args->registry->FinishThread(tids[i]); - for (int i = 0; i < kThreadsPerShard; i++) - args->registry->JoinThread(tids[i], (void*)args->shard); - return 0; -} - -static void ThreadedTestRegistry(ThreadRegistry *registry) { - // Create and start a main thread. - EXPECT_EQ(0U, registry->CreateThread(0, true, -1, 0)); - registry->StartThread(0, 0, false, 0); - pthread_t threads[kNumShards]; - RunThreadArgs args[kNumShards]; - for (int i = 0; i < kNumShards; i++) { - args[i].registry = registry; - args[i].shard = i + 1; - PTHREAD_CREATE(&threads[i], 0, RunThread, &args[i]); - } - for (int i = 0; i < kNumShards; i++) { - PTHREAD_JOIN(threads[i], 0); - } - // Check that each thread created/started/joined correct amount - // of "threads" in thread_registry. - EXPECT_EQ(1, num_created[0]); - EXPECT_EQ(1, num_started[0]); - EXPECT_EQ(0, num_joined[0]); - for (int i = 1; i <= kNumShards; i++) { - EXPECT_EQ(kThreadsPerShard, num_created[i]); - EXPECT_EQ(kThreadsPerShard, num_started[i]); - EXPECT_EQ(kThreadsPerShard, num_joined[i]); - } -} - -TEST(SanitizerCommon, ThreadRegistryThreadedTest) { - memset(&num_created, 0, sizeof(num_created)); - memset(&num_started, 0, sizeof(num_created)); - memset(&num_joined, 0, sizeof(num_created)); - - ThreadRegistry registry(GetThreadContext<TestThreadContext>, - kThreadsPerShard * kNumShards + 1, 10); - ThreadedTestRegistry(®istry); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_type_traits_test.cc b/lib/sanitizer_common/tests/sanitizer_type_traits_test.cc deleted file mode 100644 index 0dce02fac1700..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_type_traits_test.cc +++ /dev/null @@ -1,28 +0,0 @@ -//===-- sanitizer_type_traits_test.cc -------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer/AddressSanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_type_traits.h" -#include "gtest/gtest.h" -#include "sanitizer_common/sanitizer_internal_defs.h" - -using namespace __sanitizer; - -TEST(SanitizerCommon, IsSame) { - ASSERT_TRUE((is_same<unsigned, unsigned>::value)); - ASSERT_TRUE((is_same<uptr, uptr>::value)); - ASSERT_TRUE((is_same<sptr, sptr>::value)); - ASSERT_TRUE((is_same<const uptr, const uptr>::value)); - - ASSERT_FALSE((is_same<unsigned, signed>::value)); - ASSERT_FALSE((is_same<uptr, sptr>::value)); - ASSERT_FALSE((is_same<uptr, const uptr>::value)); -} diff --git a/lib/sanitizer_common/tests/sanitizer_vector_test.cc b/lib/sanitizer_common/tests/sanitizer_vector_test.cc deleted file mode 100644 index 59fbf39685bdf..0000000000000 --- a/lib/sanitizer_common/tests/sanitizer_vector_test.cc +++ /dev/null @@ -1,51 +0,0 @@ -//===-- sanitizer_vector_test.cc ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of *Sanitizer runtime. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_vector.h" -#include "gtest/gtest.h" - -namespace __sanitizer { - -TEST(Vector, Basic) { - Vector<int> v; - EXPECT_EQ(v.Size(), 0u); - v.PushBack(42); - EXPECT_EQ(v.Size(), 1u); - EXPECT_EQ(v[0], 42); - v.PushBack(43); - EXPECT_EQ(v.Size(), 2u); - EXPECT_EQ(v[0], 42); - EXPECT_EQ(v[1], 43); -} - -TEST(Vector, Stride) { - Vector<int> v; - for (int i = 0; i < 1000; i++) { - v.PushBack(i); - EXPECT_EQ(v.Size(), i + 1u); - EXPECT_EQ(v[i], i); - } - for (int i = 0; i < 1000; i++) { - EXPECT_EQ(v[i], i); - } -} - -TEST(Vector, ResizeReduction) { - Vector<int> v; - v.PushBack(0); - v.PushBack(0); - EXPECT_EQ(v.Size(), 2u); - v.Resize(1); - EXPECT_EQ(v.Size(), 1u); -} - -} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/standalone_malloc_test.cc b/lib/sanitizer_common/tests/standalone_malloc_test.cc deleted file mode 100644 index 9e6f7c93b04b2..0000000000000 --- a/lib/sanitizer_common/tests/standalone_malloc_test.cc +++ /dev/null @@ -1,87 +0,0 @@ -#include <stdio.h> -#include <vector> -#include <pthread.h> -#include <malloc.h> -#include <algorithm> - -using namespace std; - -const size_t kNumThreds = 16; -const size_t kNumIters = 1 << 23; - -inline void break_optimization(void *arg) { - __asm__ __volatile__("" : : "r" (arg) : "memory"); -} - -__attribute__((noinline)) -static void *MallocThread(void *t) { - size_t total_malloced = 0, total_freed = 0; - size_t max_in_use = 0; - size_t tid = reinterpret_cast<size_t>(t); - vector<pair<char *, size_t> > allocated; - allocated.reserve(kNumIters); - for (size_t i = 1; i < kNumIters; i++) { - if ((i % (kNumIters / 4)) == 0 && tid == 0) - fprintf(stderr, " T[%ld] iter %ld\n", tid, i); - bool allocate = (i % 5) <= 2; // 60% malloc, 40% free - if (i > kNumIters / 4) - allocate = i % 2; // then switch to 50% malloc, 50% free - if (allocate) { - size_t size = 1 + (i % 200); - if ((i % 10001) == 0) - size *= 4096; - total_malloced += size; - char *x = new char[size]; - x[0] = x[size - 1] = x[size / 2] = 0; - allocated.push_back(make_pair(x, size)); - max_in_use = max(max_in_use, total_malloced - total_freed); - } else { - if (allocated.empty()) continue; - size_t slot = i % allocated.size(); - char *p = allocated[slot].first; - p[0] = 0; // emulate last user touch of the block - size_t size = allocated[slot].second; - total_freed += size; - swap(allocated[slot], allocated.back()); - allocated.pop_back(); - delete [] p; - } - } - if (tid == 0) - fprintf(stderr, " T[%ld] total_malloced: %ldM in use %ldM max %ldM\n", - tid, total_malloced >> 20, (total_malloced - total_freed) >> 20, - max_in_use >> 20); - for (size_t i = 0; i < allocated.size(); i++) - delete [] allocated[i].first; - return 0; -} - -template <int depth> -struct DeepStack { - __attribute__((noinline)) - static void *run(void *t) { - break_optimization(0); - DeepStack<depth - 1>::run(t); - break_optimization(0); - return 0; - } -}; - -template<> -struct DeepStack<0> { - static void *run(void *t) { - MallocThread(t); - return 0; - } -}; - -// Build with -Dstandalone_malloc_test=main to make it a separate program. -int standalone_malloc_test() { - pthread_t t[kNumThreds]; - for (size_t i = 0; i < kNumThreds; i++) - pthread_create(&t[i], 0, DeepStack<200>::run, reinterpret_cast<void *>(i)); - for (size_t i = 0; i < kNumThreds; i++) - pthread_join(t[i], 0); - malloc_stats(); - return 0; -} diff --git a/lib/scudo/CMakeLists.txt b/lib/scudo/CMakeLists.txt deleted file mode 100644 index 79f69e934f223..0000000000000 --- a/lib/scudo/CMakeLists.txt +++ /dev/null @@ -1,142 +0,0 @@ -add_compiler_rt_component(scudo) - -include_directories(..) - -set(SCUDO_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -# SANITIZER_COMMON_CFLAGS include -fno-builtin, but we actually want builtins! -list(APPEND SCUDO_CFLAGS -fbuiltin) -append_rtti_flag(OFF SCUDO_CFLAGS) - -set(SCUDO_MINIMAL_DYNAMIC_LIBS ${SANITIZER_COMMON_LINK_LIBS}) -append_list_if(COMPILER_RT_HAS_LIBDL dl SCUDO_MINIMAL_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBRT rt SCUDO_MINIMAL_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread SCUDO_MINIMAL_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBLOG log SCUDO_MINIMAL_DYNAMIC_LIBS) - -set(SCUDO_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) -# Use gc-sections by default to avoid unused code being pulled in. -list(APPEND SCUDO_DYNAMIC_LINK_FLAGS -Wl,--gc-sections) - -if(ANDROID) -# Put most Sanitizer shared libraries in the global group. For more details, see -# android-changes-for-ndk-developers.md#changes-to-library-search-order - if (COMPILER_RT_HAS_Z_GLOBAL) - list(APPEND SCUDO_DYNAMIC_LINK_FLAGS -Wl,-z,global) - endif() -endif() - -# The minimal Scudo runtime does not inlude the UBSan runtime. -set(SCUDO_MINIMAL_OBJECT_LIBS - RTSanitizerCommonNoTermination - RTSanitizerCommonLibc - RTInterception) -set(SCUDO_OBJECT_LIBS ${SCUDO_MINIMAL_OBJECT_LIBS}) -set(SCUDO_DYNAMIC_LIBS ${SCUDO_MINIMAL_DYNAMIC_LIBS}) - -if (FUCHSIA) - list(APPEND SCUDO_CFLAGS -nostdinc++) - list(APPEND SCUDO_DYNAMIC_LINK_FLAGS -nostdlib++) -else() - list(APPEND SCUDO_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARY}) - list(APPEND SCUDO_OBJECT_LIBS - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTUbsan) -endif() - -set(SCUDO_SOURCES - scudo_allocator.cpp - scudo_crc32.cpp - scudo_errors.cpp - scudo_flags.cpp - scudo_malloc.cpp - scudo_termination.cpp - scudo_tsd_exclusive.cpp - scudo_tsd_shared.cpp - scudo_utils.cpp) - -set(SCUDO_CXX_SOURCES - scudo_new_delete.cpp) - -set(SCUDO_HEADERS - scudo_allocator.h - scudo_allocator_combined.h - scudo_allocator_secondary.h - scudo_crc32.h - scudo_errors.h - scudo_flags.h - scudo_flags.inc - scudo_interface_internal.h - scudo_platform.h - scudo_tsd.h - scudo_tsd_exclusive.inc - scudo_tsd_shared.inc - scudo_utils.h) - -# Enable the SSE 4.2 instruction set for scudo_crc32.cpp, if available. -if (COMPILER_RT_HAS_MSSE4_2_FLAG) - set_source_files_properties(scudo_crc32.cpp PROPERTIES COMPILE_FLAGS -msse4.2) -endif() - -# Enable the AArch64 CRC32 feature for scudo_crc32.cpp, if available. -# Note that it is enabled by default starting with armv8.1-a. -if (COMPILER_RT_HAS_MCRC_FLAG) - set_source_files_properties(scudo_crc32.cpp PROPERTIES COMPILE_FLAGS -mcrc) -endif() - -if(COMPILER_RT_HAS_SCUDO) - add_compiler_rt_runtime(clang_rt.scudo_minimal - STATIC - ARCHS ${SCUDO_SUPPORTED_ARCH} - SOURCES ${SCUDO_SOURCES} - ADDITIONAL_HEADERS ${SCUDO_HEADERS} - OBJECT_LIBS ${SCUDO_MINIMAL_OBJECT_LIBS} - CFLAGS ${SCUDO_CFLAGS} - PARENT_TARGET scudo) - add_compiler_rt_runtime(clang_rt.scudo_cxx_minimal - STATIC - ARCHS ${SCUDO_SUPPORTED_ARCH} - SOURCES ${SCUDO_CXX_SOURCES} - ADDITIONAL_HEADERS ${SCUDO_HEADERS} - CFLAGS ${SCUDO_CFLAGS} - PARENT_TARGET scudo) - - add_compiler_rt_runtime(clang_rt.scudo - STATIC - ARCHS ${SCUDO_SUPPORTED_ARCH} - SOURCES ${SCUDO_SOURCES} - ADDITIONAL_HEADERS ${SCUDO_HEADERS} - OBJECT_LIBS ${SCUDO_OBJECT_LIBS} - CFLAGS ${SCUDO_CFLAGS} - PARENT_TARGET scudo) - add_compiler_rt_runtime(clang_rt.scudo_cxx - STATIC - ARCHS ${SCUDO_SUPPORTED_ARCH} - SOURCES ${SCUDO_CXX_SOURCES} - ADDITIONAL_HEADERS ${SCUDO_HEADERS} - OBJECT_LIBS RTUbsan_cxx - CFLAGS ${SCUDO_CFLAGS} - PARENT_TARGET scudo) - - add_compiler_rt_runtime(clang_rt.scudo_minimal - SHARED - ARCHS ${SCUDO_SUPPORTED_ARCH} - SOURCES ${SCUDO_SOURCES} ${SCUDO_CXX_SOURCES} - ADDITIONAL_HEADERS ${SCUDO_HEADERS} - OBJECT_LIBS ${SCUDO_MINIMAL_OBJECT_LIBS} - CFLAGS ${SCUDO_CFLAGS} - LINK_FLAGS ${SCUDO_DYNAMIC_LINK_FLAGS} - LINK_LIBS ${SCUDO_MINIMAL_DYNAMIC_LIBS} - PARENT_TARGET scudo) - - add_compiler_rt_runtime(clang_rt.scudo - SHARED - ARCHS ${SCUDO_SUPPORTED_ARCH} - SOURCES ${SCUDO_SOURCES} ${SCUDO_CXX_SOURCES} - ADDITIONAL_HEADERS ${SCUDO_HEADERS} - OBJECT_LIBS ${SCUDO_OBJECT_LIBS} - CFLAGS ${SCUDO_CFLAGS} - LINK_FLAGS ${SCUDO_DYNAMIC_LINK_FLAGS} - LINK_LIBS ${SCUDO_DYNAMIC_LIBS} - PARENT_TARGET scudo) -endif() diff --git a/lib/stats/CMakeLists.txt b/lib/stats/CMakeLists.txt deleted file mode 100644 index 23c80843195d2..0000000000000 --- a/lib/stats/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -set(STATS_HEADERS - stats.h) - -include_directories(..) - -add_custom_target(stats) -set_target_properties(stats PROPERTIES FOLDER "Compiler-RT Misc") - -if(APPLE) - set(STATS_LIB_FLAVOR SHARED) - - set(STATS_LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS}) - - add_weak_symbols("asan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("ubsan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) -else() - set(STATS_LIB_FLAVOR STATIC) - - set(WEAK_SYMBOL_LINK_FLAGS) -endif() - -add_compiler_rt_runtime(clang_rt.stats - ${STATS_LIB_FLAVOR} - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - OS ${SANITIZER_COMMON_SUPPORTED_OS} - SOURCES stats.cc - ADDITIONAL_HEADERS ${STATS_HEADERS} - OBJECT_LIBS RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonSymbolizer - CFLAGS ${SANITIZER_COMMON_CFLAGS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} - LINK_LIBS ${STATS_LINK_LIBS} - PARENT_TARGET stats) - -add_compiler_rt_runtime(clang_rt.stats_client - STATIC - ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} - OS ${SANITIZER_COMMON_SUPPORTED_OS} - SOURCES stats_client.cc - ADDITIONAL_HEADERS ${STATS_HEADERS} - CFLAGS ${SANITIZER_COMMON_CFLAGS} - LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS} - PARENT_TARGET stats) diff --git a/lib/tsan/.clang-format b/lib/tsan/.clang-format deleted file mode 100644 index 560308c91deec..0000000000000 --- a/lib/tsan/.clang-format +++ /dev/null @@ -1,2 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: false diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt deleted file mode 100644 index e1da319ccc872..0000000000000 --- a/lib/tsan/CMakeLists.txt +++ /dev/null @@ -1,258 +0,0 @@ -# Build for the ThreadSanitizer runtime support library. - -include_directories(..) - -set(TSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -# SANITIZER_COMMON_CFLAGS contains -fPIC, but it's performance-critical for -# TSan runtime to be built with -fPIE to reduce the number of register spills. -# On FreeBSD however it provokes linkage issue thus we disable it. -if(NOT CMAKE_SYSTEM MATCHES "FreeBSD") - append_list_if(COMPILER_RT_HAS_FPIE_FLAG -fPIE TSAN_CFLAGS) -endif() -append_rtti_flag(OFF TSAN_CFLAGS) - -if(COMPILER_RT_TSAN_DEBUG_OUTPUT) - # Add extra debug information to TSan runtime. This configuration is rarely - # used, but we need to support it so that debug output will not bitrot. - list(APPEND TSAN_CFLAGS -DTSAN_COLLECT_STATS=1 - -DTSAN_DEBUG_OUTPUT=2) -endif() - -set(TSAN_RTL_CFLAGS ${TSAN_CFLAGS}) -append_list_if(COMPILER_RT_HAS_MSSE3_FLAG -msse3 TSAN_RTL_CFLAGS) -append_list_if(SANITIZER_LIMIT_FRAME_SIZE -Wframe-larger-than=530 - TSAN_RTL_CFLAGS) -append_list_if(COMPILER_RT_HAS_WGLOBAL_CONSTRUCTORS_FLAG -Wglobal-constructors - TSAN_RTL_CFLAGS) - -set(TSAN_SOURCES - rtl/tsan_clock.cc - rtl/tsan_debugging.cc - rtl/tsan_external.cc - rtl/tsan_fd.cc - rtl/tsan_flags.cc - rtl/tsan_ignoreset.cc - rtl/tsan_interceptors.cc - rtl/tsan_interface.cc - rtl/tsan_interface_ann.cc - rtl/tsan_interface_atomic.cc - rtl/tsan_interface_java.cc - rtl/tsan_malloc_mac.cc - rtl/tsan_md5.cc - rtl/tsan_mman.cc - rtl/tsan_mutex.cc - rtl/tsan_mutexset.cc - rtl/tsan_preinit.cc - rtl/tsan_report.cc - rtl/tsan_rtl.cc - rtl/tsan_rtl_mutex.cc - rtl/tsan_rtl_proc.cc - rtl/tsan_rtl_report.cc - rtl/tsan_rtl_thread.cc - rtl/tsan_stack_trace.cc - rtl/tsan_stat.cc - rtl/tsan_suppressions.cc - rtl/tsan_symbolize.cc - rtl/tsan_sync.cc) - -set(TSAN_CXX_SOURCES - rtl/tsan_new_delete.cc) - -if(APPLE) - list(APPEND TSAN_SOURCES - rtl/tsan_interceptors_mac.cc - rtl/tsan_libdispatch_mac.cc - rtl/tsan_platform_mac.cc - rtl/tsan_platform_posix.cc) -elseif(UNIX) - # Assume Linux - list(APPEND TSAN_SOURCES - rtl/tsan_platform_linux.cc - rtl/tsan_platform_posix.cc) -endif() - -set(TSAN_HEADERS - rtl/tsan_clock.h - rtl/tsan_defs.h - rtl/tsan_dense_alloc.h - rtl/tsan_fd.h - rtl/tsan_flags.h - rtl/tsan_flags.inc - rtl/tsan_ignoreset.h - rtl/tsan_interceptors.h - rtl/tsan_interface.h - rtl/tsan_interface_ann.h - rtl/tsan_interface_inl.h - rtl/tsan_interface_java.h - rtl/tsan_mman.h - rtl/tsan_mutex.h - rtl/tsan_mutexset.h - rtl/tsan_platform.h - rtl/tsan_ppc_regs.h - rtl/tsan_report.h - rtl/tsan_rtl.h - rtl/tsan_stack_trace.h - rtl/tsan_stat.h - rtl/tsan_suppressions.h - rtl/tsan_symbolize.h - rtl/tsan_sync.h - rtl/tsan_trace.h - rtl/tsan_update_shadow_word_inl.h) - -set(TSAN_RUNTIME_LIBRARIES) -add_compiler_rt_component(tsan) - -if(APPLE) - add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S rtl/tsan_rtl_aarch64.S) - - set(TSAN_LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS}) - - add_weak_symbols("ubsan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) - - add_compiler_rt_runtime(clang_rt.tsan - SHARED - OS ${TSAN_SUPPORTED_OS} - ARCHS ${TSAN_SUPPORTED_ARCH} - SOURCES ${TSAN_SOURCES} ${TSAN_CXX_SOURCES} ${TSAN_ASM_SOURCES} - ADDITIONAL_HEADERS ${TSAN_HEADERS} - OBJECT_LIBS RTInterception - RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTUbsan - CFLAGS ${TSAN_RTL_CFLAGS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} - LINK_LIBS ${TSAN_LINK_LIBS} objc - PARENT_TARGET tsan) - add_compiler_rt_object_libraries(RTTsan_dynamic - OS ${TSAN_SUPPORTED_OS} - ARCHS ${TSAN_SUPPORTED_ARCH} - SOURCES ${TSAN_SOURCES} ${TSAN_CXX_SOURCES} ${TSAN_ASM_SOURCES} - ADDITIONAL_HEADERS ${TSAN_HEADERS} - CFLAGS ${TSAN_RTL_CFLAGS}) - - # Build and check Go runtime. - set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) - add_custom_target(GotsanRuntimeCheck - COMMAND env "CC=${CMAKE_C_COMPILER} ${OSX_SYSROOT_FLAG}" - IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} - DEPENDS tsan ${BUILDGO_SCRIPT} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go - COMMENT "Checking TSan Go runtime..." - VERBATIM) - set_target_properties(GotsanRuntimeCheck PROPERTIES FOLDER "Compiler-RT Misc") -else() - foreach(arch ${TSAN_SUPPORTED_ARCH}) - if(arch STREQUAL "x86_64") - add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S) - # Sanity check for Go runtime. - set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) - add_custom_target(GotsanRuntimeCheck - COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" - IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} - DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go - COMMENT "Checking TSan Go runtime..." - VERBATIM) - elseif(arch STREQUAL "aarch64") - add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_aarch64.S) - # Sanity check for Go runtime. - set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) - add_custom_target(GotsanRuntimeCheck - COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" - IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} - DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go - COMMENT "Checking TSan Go runtime..." - VERBATIM) - elseif(arch MATCHES "powerpc64|powerpc64le") - add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_ppc64.S) - # Sanity check for Go runtime. - set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) - add_custom_target(GotsanRuntimeCheck - COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" - IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} - DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go - COMMENT "Checking TSan Go runtime..." - VERBATIM) - elseif(arch MATCHES "mips64|mips64le") - add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_mips64.S) - else() - set(TSAN_ASM_SOURCES) - endif() - add_compiler_rt_runtime(clang_rt.tsan - STATIC - ARCHS ${arch} - SOURCES ${TSAN_SOURCES} ${TSAN_ASM_SOURCES} - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> - $<TARGET_OBJECTS:RTUbsan.${arch}> - ADDITIONAL_HEADERS ${TSAN_HEADERS} - CFLAGS ${TSAN_RTL_CFLAGS} - PARENT_TARGET tsan) - add_compiler_rt_runtime(clang_rt.tsan_cxx - STATIC - ARCHS ${arch} - SOURCES ${TSAN_CXX_SOURCES} - $<TARGET_OBJECTS:RTUbsan_cxx.${arch}> - ADDITIONAL_HEADERS ${TSAN_HEADERS} - CFLAGS ${TSAN_RTL_CFLAGS} - PARENT_TARGET tsan) - list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch} - clang_rt.tsan_cxx-${arch}) - add_sanitizer_rt_symbols(clang_rt.tsan - ARCHS ${arch} - EXTRA rtl/tsan.syms.extra) - add_sanitizer_rt_symbols(clang_rt.tsan_cxx - ARCHS ${arch} - EXTRA rtl/tsan.syms.extra) - add_dependencies(tsan clang_rt.tsan-${arch} - clang_rt.tsan_cxx-${arch} - clang_rt.tsan-${arch}-symbols - clang_rt.tsan_cxx-${arch}-symbols) - endforeach() -endif() - -# Make sure that non-platform-specific files don't include any system headers. -# FreeBSD/NetBSD do not install a number of Clang-provided headers for the -# compiler in the base system due to incompatibilities between FreeBSD/NetBSD's -# and Clang's versions. As a workaround do not use --sysroot=. on FreeBSD/NetBSD -# until this is addressed. -if(COMPILER_RT_HAS_SYSROOT_FLAG AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD" - AND NOT CMAKE_SYSTEM_NAME MATCHES "NetBSD") - file(GLOB _tsan_generic_sources rtl/tsan*) - file(GLOB _tsan_platform_sources rtl/tsan*posix* rtl/tsan*mac* - rtl/tsan*linux*) - list(REMOVE_ITEM _tsan_generic_sources ${_tsan_platform_sources}) - set_source_files_properties(${_tsan_generic_sources} - PROPERTIES COMPILE_FLAGS "--sysroot=.") -endif() - -# Build libcxx instrumented with TSan. -if(COMPILER_RT_LIBCXX_PATH AND - COMPILER_RT_TEST_COMPILER_ID STREQUAL "Clang" AND - NOT ANDROID) - set(libcxx_tsan_deps) - foreach(arch ${TSAN_SUPPORTED_ARCH}) - get_target_flags_for_arch(${arch} TARGET_CFLAGS) - set(LIBCXX_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_tsan_${arch}) - add_custom_libcxx(libcxx_tsan_${arch} ${LIBCXX_PREFIX} - DEPS ${TSAN_RUNTIME_LIBRARIES} - CFLAGS ${TARGET_CFLAGS} -fsanitize=thread - USE_TOOLCHAIN) - list(APPEND libcxx_tsan_deps libcxx_tsan_${arch}-build) - endforeach() - - add_custom_target(libcxx_tsan DEPENDS ${libcxx_tsan_deps}) - set_target_properties(libcxx_tsan PROPERTIES FOLDER "Compiler-RT Misc") -endif() - -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/lib/tsan/analyze_libtsan.sh b/lib/tsan/analyze_libtsan.sh deleted file mode 100755 index ae29f1b5b05a1..0000000000000 --- a/lib/tsan/analyze_libtsan.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# -# Script that prints information about generated code in TSan runtime. - -set -e -set -u - -if [[ "$#" != 1 ]]; then - echo "Usage: $0 /path/to/binary/built/with/tsan" - exit 1 -fi - -get_asm() { - grep __tsan_$1.: -A 10000 ${OBJDUMP_CONTENTS} | \ - awk "/[^:]$/ {print;} />:/ {c++; if (c == 2) {exit}}" -} - -list="write1 \ - write2 \ - write4 \ - write8 \ - read1 \ - read2 \ - read4 \ - read8 \ - func_entry \ - func_exit" - -BIN=$1 -OUTPUT_DIR=$(mktemp -t -d analyze_libtsan_out.XXXXXXXX) -OBJDUMP_CONTENTS=${OUTPUT_DIR}/libtsan_objdump -NM_CONTENTS=${OUTPUT_DIR}/libtsan_nm - -objdump -d $BIN > ${OBJDUMP_CONTENTS} -nm -S $BIN | grep "__tsan_" > ${NM_CONTENTS} - -for f in $list; do - file=${OUTPUT_DIR}/asm_$f.s - get_asm $f > $file - tot=$(wc -l < $file) - size=$(grep __tsan_$f$ ${NM_CONTENTS} | awk --non-decimal-data '{print ("0x"$2)+0}') - rsp=$(grep '(%rsp)' $file | wc -l) - push=$(grep 'push' $file | wc -l) - pop=$(grep 'pop' $file | wc -l) - call=$(grep 'call' $file | wc -l) - load=$(egrep 'mov .*\,.*\(.*\)|cmp .*\,.*\(.*\)' $file | wc -l) - store=$(egrep 'mov .*\(.*\),' $file | wc -l) - mov=$(grep 'mov' $file | wc -l) - lea=$(grep 'lea' $file | wc -l) - sh=$(grep 'shr\|shl' $file | wc -l) - cmp=$(grep 'cmp\|test' $file | wc -l) - printf "%10s tot %3d; size %4d; rsp %d; push %d; pop %d; call %d; load %2d; store %2d; sh %3d; mov %3d; lea %3d; cmp %3d\n" \ - $f $tot $size $rsp $push $pop $call $load $store $sh $mov $lea $cmp; -done diff --git a/lib/tsan/check_analyze.sh b/lib/tsan/check_analyze.sh deleted file mode 100755 index 65c34d466da3f..0000000000000 --- a/lib/tsan/check_analyze.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -# -# Script that checks that critical functions in TSan runtime have correct number -# of push/pop/rsp instructions to verify that runtime is efficient enough. -# -# This test can fail when backend code generation changes the output for various -# tsan interceptors. When such a change happens, you can ensure that the -# performance has not regressed by running the following benchmarks before and -# after the breaking change to verify that the values in this file are safe to -# update: -# ./projects/compiler-rt/lib/tsan/tests/rtl/TsanRtlTest-x86_64-Test -# --gtest_also_run_disabled_tests --gtest_filter=DISABLED_BENCH.Mop* - -set -u - -if [[ "$#" != 1 ]]; then - echo "Usage: $0 /path/to/binary/built/with/tsan" - exit 1 -fi - -SCRIPTDIR=$(dirname $0) -RES=$(${SCRIPTDIR}/analyze_libtsan.sh $1) -PrintRes() { - printf "%s\n" "$RES" -} - -PrintRes - -check() { - res=$(PrintRes | egrep "$1 .* $2 $3; ") - if [ "$res" == "" ]; then - echo FAILED $1 must contain $2 $3 - exit 1 - fi -} - -for f in write1 write2 write4 write8 read2 read4; do - check $f rsp 1 - check $f push 1 - check $f pop 6 -done - -for f in read1 read8; do - check $f rsp 1 - check $f push 2 - check $f pop 12 -done - -for f in func_entry func_exit; do - check $f rsp 0 - check $f push 0 - check $f pop 0 - check $f call 1 # TraceSwitch() -done - -echo LGTM diff --git a/lib/tsan/check_cmake.sh b/lib/tsan/check_cmake.sh deleted file mode 100755 index 7668c5b49e1a7..0000000000000 --- a/lib/tsan/check_cmake.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -set -u -set -e - -ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if [ -d "$ROOT/llvm-build" ]; then - cd $ROOT/llvm-build -else - mkdir -p $ROOT/llvm-build - cd $ROOT/llvm-build - CC=clang CXX=clang++ cmake -G Ninja -DLLVM_ENABLE_WERROR=ON -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON $ROOT/../../../.. -fi -ninja -ninja check-sanitizer -ninja check-tsan -ninja check-asan -ninja check-msan -ninja check-lsan diff --git a/lib/tsan/dd/CMakeLists.txt b/lib/tsan/dd/CMakeLists.txt deleted file mode 100644 index f2b8a6d173a42..0000000000000 --- a/lib/tsan/dd/CMakeLists.txt +++ /dev/null @@ -1,52 +0,0 @@ -# Build for the experimental deadlock detector runtime library. - -include_directories(../..) - -set(DD_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF DD_CFLAGS) - -set(DD_SOURCES - dd_rtl.cc - dd_interceptors.cc -) - -set(DD_LINKLIBS ${SANITIZER_CXX_ABI_LIBRARY} ${SANITIZER_COMMON_LINK_LIBS}) - -append_list_if(COMPILER_RT_HAS_LIBDL dl DD_LINKLIBS) -append_list_if(COMPILER_RT_HAS_LIBRT rt DD_LINKLIBS) -append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread DD_LINKLIBS) - -add_custom_target(dd) -set_target_properties(dd PROPERTIES FOLDER "Compiler-RT Misc") - -# Deadlock detector is currently supported on 64-bit Linux only. -if(CAN_TARGET_x86_64 AND UNIX AND NOT APPLE AND NOT ANDROID) - set(arch "x86_64") - add_compiler_rt_runtime(clang_rt.dd - STATIC - ARCHS ${arch} - SOURCES ${DD_SOURCES} - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - CFLAGS ${DD_CFLAGS} - PARENT_TARGET dd) - - add_compiler_rt_object_libraries(RTDD - ARCHS ${arch} - SOURCES ${DD_SOURCES} CFLAGS ${DD_CFLAGS}) - - add_compiler_rt_runtime(clang_rt.dyndd - SHARED - ARCHS ${arch} - SOURCES $<TARGET_OBJECTS:RTDD.${arch}> - $<TARGET_OBJECTS:RTInterception.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}> - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} - LINK_LIBS ${DD_LINKLIBS} - PARENT_TARGET dd) -endif() - -add_dependencies(compiler-rt dd) diff --git a/lib/tsan/go/build.bat b/lib/tsan/go/build.bat deleted file mode 100644 index 3a64a2413b979..0000000000000 --- a/lib/tsan/go/build.bat +++ /dev/null @@ -1,4 +0,0 @@ -type tsan_go.cc ..\rtl\tsan_interface_atomic.cc ..\rtl\tsan_clock.cc ..\rtl\tsan_flags.cc ..\rtl\tsan_md5.cc ..\rtl\tsan_mutex.cc ..\rtl\tsan_report.cc ..\rtl\tsan_rtl.cc ..\rtl\tsan_rtl_mutex.cc ..\rtl\tsan_rtl_report.cc ..\rtl\tsan_rtl_thread.cc ..\rtl\tsan_rtl_proc.cc ..\rtl\tsan_stat.cc ..\rtl\tsan_suppressions.cc ..\rtl\tsan_sync.cc ..\rtl\tsan_stack_trace.cc ..\..\sanitizer_common\sanitizer_allocator.cc ..\..\sanitizer_common\sanitizer_common.cc ..\..\sanitizer_common\sanitizer_flags.cc ..\..\sanitizer_common\sanitizer_stacktrace.cc ..\..\sanitizer_common\sanitizer_libc.cc ..\..\sanitizer_common\sanitizer_printf.cc ..\..\sanitizer_common\sanitizer_suppressions.cc ..\..\sanitizer_common\sanitizer_thread_registry.cc ..\rtl\tsan_platform_windows.cc ..\..\sanitizer_common\sanitizer_win.cc ..\..\sanitizer_common\sanitizer_deadlock_detector1.cc ..\..\sanitizer_common\sanitizer_stackdepot.cc ..\..\sanitizer_common\sanitizer_persistent_allocator.cc ..\..\sanitizer_common\sanitizer_flag_parser.cc ..\..\sanitizer_common\sanitizer_symbolizer.cc ..\..\sanitizer_common\sanitizer_termination.cc > gotsan.cc - -gcc -c -o race_windows_amd64.syso gotsan.cc -I..\rtl -I..\.. -I..\..\sanitizer_common -I..\..\..\include -m64 -Wall -fno-exceptions -fno-rtti -DSANITIZER_GO=1 -Wno-error=attributes -Wno-attributes -Wno-format -Wno-maybe-uninitialized -DSANITIZER_DEBUG=0 -O3 -fomit-frame-pointer -std=c++11 - diff --git a/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh deleted file mode 100755 index eec4cf15e5aac..0000000000000 --- a/lib/tsan/go/buildgo.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/sh - -set -e - -SRCS=" - tsan_go.cc - ../rtl/tsan_clock.cc - ../rtl/tsan_external.cc - ../rtl/tsan_flags.cc - ../rtl/tsan_interface_atomic.cc - ../rtl/tsan_md5.cc - ../rtl/tsan_mutex.cc - ../rtl/tsan_report.cc - ../rtl/tsan_rtl.cc - ../rtl/tsan_rtl_mutex.cc - ../rtl/tsan_rtl_report.cc - ../rtl/tsan_rtl_thread.cc - ../rtl/tsan_rtl_proc.cc - ../rtl/tsan_stack_trace.cc - ../rtl/tsan_stat.cc - ../rtl/tsan_suppressions.cc - ../rtl/tsan_sync.cc - ../../sanitizer_common/sanitizer_allocator.cc - ../../sanitizer_common/sanitizer_common.cc - ../../sanitizer_common/sanitizer_common_libcdep.cc - ../../sanitizer_common/sanitizer_deadlock_detector2.cc - ../../sanitizer_common/sanitizer_file.cc - ../../sanitizer_common/sanitizer_flag_parser.cc - ../../sanitizer_common/sanitizer_flags.cc - ../../sanitizer_common/sanitizer_libc.cc - ../../sanitizer_common/sanitizer_persistent_allocator.cc - ../../sanitizer_common/sanitizer_printf.cc - ../../sanitizer_common/sanitizer_suppressions.cc - ../../sanitizer_common/sanitizer_thread_registry.cc - ../../sanitizer_common/sanitizer_stackdepot.cc - ../../sanitizer_common/sanitizer_stacktrace.cc - ../../sanitizer_common/sanitizer_symbolizer.cc - ../../sanitizer_common/sanitizer_symbolizer_report.cc - ../../sanitizer_common/sanitizer_termination.cc -" - -if [ "`uname -a | grep Linux`" != "" ]; then - OSCFLAGS="-fPIC -Wno-maybe-uninitialized" - OSLDFLAGS="-lpthread -fPIC -fpie" - SRCS=" - $SRCS - ../rtl/tsan_platform_linux.cc - ../../sanitizer_common/sanitizer_posix.cc - ../../sanitizer_common/sanitizer_posix_libcdep.cc - ../../sanitizer_common/sanitizer_procmaps_common.cc - ../../sanitizer_common/sanitizer_procmaps_linux.cc - ../../sanitizer_common/sanitizer_linux.cc - ../../sanitizer_common/sanitizer_linux_libcdep.cc - ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc - " - if [ "`uname -a | grep ppc64le`" != "" ]; then - SUFFIX="linux_ppc64le" - ARCHCFLAGS="-m64" - elif [ "`uname -a | grep x86_64`" != "" ]; then - SUFFIX="linux_amd64" - ARCHCFLAGS="-m64" - OSCFLAGS="$OSCFLAGS -ffreestanding -Wno-unused-const-variable -Werror -Wno-unknown-warning-option" - elif [ "`uname -a | grep aarch64`" != "" ]; then - SUFFIX="linux_arm64" - ARCHCFLAGS="" - fi -elif [ "`uname -a | grep FreeBSD`" != "" ]; then - SUFFIX="freebsd_amd64" - OSCFLAGS="-fno-strict-aliasing -fPIC -Werror" - ARCHCFLAGS="-m64" - OSLDFLAGS="-lpthread -fPIC -fpie" - SRCS=" - $SRCS - ../rtl/tsan_platform_linux.cc - ../../sanitizer_common/sanitizer_posix.cc - ../../sanitizer_common/sanitizer_posix_libcdep.cc - ../../sanitizer_common/sanitizer_procmaps_bsd.cc - ../../sanitizer_common/sanitizer_procmaps_common.cc - ../../sanitizer_common/sanitizer_linux.cc - ../../sanitizer_common/sanitizer_linux_libcdep.cc - ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc - " -elif [ "`uname -a | grep NetBSD`" != "" ]; then - SUFFIX="netbsd_amd64" - OSCFLAGS="-fno-strict-aliasing -fPIC -Werror" - ARCHCFLAGS="-m64" - OSLDFLAGS="-lpthread -fPIC -fpie" - SRCS=" - $SRCS - ../rtl/tsan_platform_linux.cc - ../../sanitizer_common/sanitizer_posix.cc - ../../sanitizer_common/sanitizer_posix_libcdep.cc - ../../sanitizer_common/sanitizer_procmaps_bsd.cc - ../../sanitizer_common/sanitizer_procmaps_common.cc - ../../sanitizer_common/sanitizer_linux.cc - ../../sanitizer_common/sanitizer_linux_libcdep.cc - ../../sanitizer_common/sanitizer_netbsd.cc - ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc - " -elif [ "`uname -a | grep Darwin`" != "" ]; then - SUFFIX="darwin_amd64" - OSCFLAGS="-fPIC -Wno-unused-const-variable -Wno-unknown-warning-option -mmacosx-version-min=10.7" - ARCHCFLAGS="-m64" - OSLDFLAGS="-lpthread -fPIC -fpie -mmacosx-version-min=10.7" - SRCS=" - $SRCS - ../rtl/tsan_platform_mac.cc - ../../sanitizer_common/sanitizer_mac.cc - ../../sanitizer_common/sanitizer_posix.cc - ../../sanitizer_common/sanitizer_posix_libcdep.cc - ../../sanitizer_common/sanitizer_procmaps_mac.cc - " -elif [ "`uname -a | grep MINGW`" != "" ]; then - SUFFIX="windows_amd64" - OSCFLAGS="-Wno-error=attributes -Wno-attributes -Wno-unused-const-variable -Wno-unknown-warning-option" - ARCHCFLAGS="-m64" - OSLDFLAGS="" - SRCS=" - $SRCS - ../rtl/tsan_platform_windows.cc - ../../sanitizer_common/sanitizer_win.cc - " -else - echo Unknown platform - exit 1 -fi - -CC=${CC:-gcc} -IN_TMPDIR=${IN_TMPDIR:-0} -SILENT=${SILENT:-0} - -if [ $IN_TMPDIR != "0" ]; then - DIR=$(mktemp -qd /tmp/gotsan.XXXXXXXXXX) - cleanup() { - rm -rf $DIR - } - trap cleanup EXIT -else - DIR=. -fi - -SRCS="$SRCS $ADD_SRCS" - -rm -f $DIR/gotsan.cc -for F in $SRCS; do - cat $F >> $DIR/gotsan.cc -done - -FLAGS=" -I../rtl -I../.. -I../../sanitizer_common -I../../../include -std=c++11 -Wall -fno-exceptions -fno-rtti -DSANITIZER_GO=1 -DSANITIZER_DEADLOCK_DETECTOR_VERSION=2 $OSCFLAGS $ARCHCFLAGS" -if [ "$DEBUG" = "" ]; then - FLAGS="$FLAGS -DSANITIZER_DEBUG=0 -O3 -fomit-frame-pointer" - if [ "$SUFFIX" = "linux_ppc64le" ]; then - FLAGS="$FLAGS -mcpu=power8 -fno-function-sections" - elif [ "$SUFFIX" = "linux_amd64" ]; then - FLAGS="$FLAGS -msse3" - fi -else - FLAGS="$FLAGS -DSANITIZER_DEBUG=1 -g" -fi - -if [ "$SILENT" != "1" ]; then - echo $CC gotsan.cc -c -o $DIR/race_$SUFFIX.syso $FLAGS $CFLAGS -fi -$CC $DIR/gotsan.cc -c -o $DIR/race_$SUFFIX.syso $FLAGS $CFLAGS - -$CC $OSCFLAGS $ARCHCFLAGS test.c $DIR/race_$SUFFIX.syso -g -o $DIR/test $OSLDFLAGS $LDFLAGS - -export GORACE="exitcode=0 atexit_sleep_ms=0" -if [ "$SILENT" != "1" ]; then - $DIR/test -else - $DIR/test 2>/dev/null -fi diff --git a/lib/tsan/tests/CMakeLists.txt b/lib/tsan/tests/CMakeLists.txt deleted file mode 100644 index 352319f101092..0000000000000 --- a/lib/tsan/tests/CMakeLists.txt +++ /dev/null @@ -1,72 +0,0 @@ -include_directories(../rtl) - -add_custom_target(TsanUnitTests) -set_target_properties(TsanUnitTests PROPERTIES - FOLDER "Compiler-RT Tests") - -set(TSAN_UNITTEST_CFLAGS - ${TSAN_CFLAGS} - ${COMPILER_RT_UNITTEST_CFLAGS} - ${COMPILER_RT_GTEST_CFLAGS} - -I${COMPILER_RT_SOURCE_DIR}/include - -I${COMPILER_RT_SOURCE_DIR}/lib - -I${COMPILER_RT_SOURCE_DIR}/lib/tsan/rtl - -DGTEST_HAS_RTTI=0) - -set(TSAN_TEST_ARCH ${TSAN_SUPPORTED_ARCH}) -if(APPLE) - - # Create a static library for test dependencies. - set(TSAN_TEST_RUNTIME_OBJECTS - $<TARGET_OBJECTS:RTTsan_dynamic.osx> - $<TARGET_OBJECTS:RTInterception.osx> - $<TARGET_OBJECTS:RTSanitizerCommon.osx> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.osx> - $<TARGET_OBJECTS:RTSanitizerCommonCoverage.osx> - $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.osx> - $<TARGET_OBJECTS:RTUbsan.osx>) - set(TSAN_TEST_RUNTIME RTTsanTest) - add_library(${TSAN_TEST_RUNTIME} STATIC ${TSAN_TEST_RUNTIME_OBJECTS}) - set_target_properties(${TSAN_TEST_RUNTIME} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - - darwin_filter_host_archs(TSAN_SUPPORTED_ARCH TSAN_TEST_ARCH) - list(APPEND TSAN_UNITTEST_CFLAGS ${DARWIN_osx_CFLAGS}) - - set(LINK_FLAGS "-lc++") - list(APPEND LINK_FLAGS ${DARWIN_osx_LINK_FLAGS}) - add_weak_symbols("ubsan" LINK_FLAGS) - add_weak_symbols("sanitizer_common" LINK_FLAGS) -else() - set(LINK_FLAGS "-fsanitize=thread;-lstdc++;-lm") -endif() - -set(TSAN_RTL_HEADERS) -foreach (header ${TSAN_HEADERS}) - list(APPEND TSAN_RTL_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../${header}) -endforeach() - -# add_tsan_unittest(<name> -# SOURCES <sources list> -# HEADERS <extra headers list>) -macro(add_tsan_unittest testname) - cmake_parse_arguments(TEST "" "" "SOURCES;HEADERS" ${ARGN}) - if(UNIX) - foreach(arch ${TSAN_TEST_ARCH}) - set(TsanUnitTestsObjects) - generate_compiler_rt_tests(TsanUnitTestsObjects TsanUnitTests - "${testname}-${arch}-Test" ${arch} - SOURCES ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE} - RUNTIME ${TSAN_TEST_RUNTIME} - COMPILE_DEPS ${TEST_HEADERS} ${TSAN_RTL_HEADERS} - DEPS gtest tsan - CFLAGS ${TSAN_UNITTEST_CFLAGS} - LINK_FLAGS ${LINK_FLAGS}) - endforeach() - endif() -endmacro() - -if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID) - add_subdirectory(rtl) - add_subdirectory(unit) -endif() diff --git a/lib/tsan/tests/rtl/CMakeLists.txt b/lib/tsan/tests/rtl/CMakeLists.txt deleted file mode 100644 index a34f08ea965b8..0000000000000 --- a/lib/tsan/tests/rtl/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -set(TSAN_RTL_TEST_SOURCES - tsan_bench.cc - tsan_mop.cc - tsan_mutex.cc - tsan_posix.cc - tsan_string.cc - tsan_test.cc - tsan_thread.cc) - -if(UNIX) - list(APPEND TSAN_RTL_TEST_SOURCES tsan_test_util_posix.cc) -endif() - -set(TSAN_RTL_TEST_HEADERS - tsan_test_util.h) - -add_tsan_unittest(TsanRtlTest - SOURCES ${TSAN_RTL_TEST_SOURCES} - HEADERS ${TSAN_RTL_TEST_HEADERS}) diff --git a/lib/tsan/tests/rtl/tsan_bench.cc b/lib/tsan/tests/rtl/tsan_bench.cc deleted file mode 100644 index a3cf22f2c6262..0000000000000 --- a/lib/tsan/tests/rtl/tsan_bench.cc +++ /dev/null @@ -1,105 +0,0 @@ -//===-- tsan_bench.cc -----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_test_util.h" -#include "tsan_interface.h" -#include "tsan_defs.h" -#include "gtest/gtest.h" -#include <stdint.h> - -const int kSize = 128; -const int kRepeat = 2*1024*1024; - -void noinstr(void *p) {} - -template<typename T, void(*__tsan_mop)(void *p)> -static void Benchmark() { - volatile T data[kSize]; - for (int i = 0; i < kRepeat; i++) { - for (int j = 0; j < kSize; j++) { - __tsan_mop((void*)&data[j]); - data[j]++; - } - } -} - -TEST(DISABLED_BENCH, Mop1) { - Benchmark<uint8_t, noinstr>(); -} - -TEST(DISABLED_BENCH, Mop1Read) { - Benchmark<uint8_t, __tsan_read1>(); -} - -TEST(DISABLED_BENCH, Mop1Write) { - Benchmark<uint8_t, __tsan_write1>(); -} - -TEST(DISABLED_BENCH, Mop2) { - Benchmark<uint16_t, noinstr>(); -} - -TEST(DISABLED_BENCH, Mop2Read) { - Benchmark<uint16_t, __tsan_read2>(); -} - -TEST(DISABLED_BENCH, Mop2Write) { - Benchmark<uint16_t, __tsan_write2>(); -} - -TEST(DISABLED_BENCH, Mop4) { - Benchmark<uint32_t, noinstr>(); -} - -TEST(DISABLED_BENCH, Mop4Read) { - Benchmark<uint32_t, __tsan_read4>(); -} - -TEST(DISABLED_BENCH, Mop4Write) { - Benchmark<uint32_t, __tsan_write4>(); -} - -TEST(DISABLED_BENCH, Mop8) { - Benchmark<uint8_t, noinstr>(); -} - -TEST(DISABLED_BENCH, Mop8Read) { - Benchmark<uint64_t, __tsan_read8>(); -} - -TEST(DISABLED_BENCH, Mop8Write) { - Benchmark<uint64_t, __tsan_write8>(); -} - -TEST(DISABLED_BENCH, FuncCall) { - for (int i = 0; i < kRepeat; i++) { - for (int j = 0; j < kSize; j++) - __tsan_func_entry((void*)(uintptr_t)j); - for (int j = 0; j < kSize; j++) - __tsan_func_exit(); - } -} - -TEST(DISABLED_BENCH, MutexLocal) { - Mutex m; - ScopedThread().Create(m); - for (int i = 0; i < 50; i++) { - ScopedThread t; - t.Lock(m); - t.Unlock(m); - } - for (int i = 0; i < 16*1024*1024; i++) { - m.Lock(); - m.Unlock(); - } - ScopedThread().Destroy(m); -} diff --git a/lib/tsan/tests/rtl/tsan_mop.cc b/lib/tsan/tests/rtl/tsan_mop.cc deleted file mode 100644 index f217428250509..0000000000000 --- a/lib/tsan/tests/rtl/tsan_mop.cc +++ /dev/null @@ -1,233 +0,0 @@ -//===-- tsan_mop.cc -------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_interface.h" -#include "tsan_test_util.h" -#include "gtest/gtest.h" -#include <stddef.h> -#include <stdint.h> - -TEST(ThreadSanitizer, SimpleWrite) { - ScopedThread t; - MemLoc l; - t.Write1(l); -} - -TEST(ThreadSanitizer, SimpleWriteWrite) { - ScopedThread t1, t2; - MemLoc l1, l2; - t1.Write1(l1); - t2.Write1(l2); -} - -TEST(ThreadSanitizer, WriteWriteRace) { - ScopedThread t1, t2; - MemLoc l; - t1.Write1(l); - t2.Write1(l, true); -} - -TEST(ThreadSanitizer, ReadWriteRace) { - ScopedThread t1, t2; - MemLoc l; - t1.Read1(l); - t2.Write1(l, true); -} - -TEST(ThreadSanitizer, WriteReadRace) { - ScopedThread t1, t2; - MemLoc l; - t1.Write1(l); - t2.Read1(l, true); -} - -TEST(ThreadSanitizer, ReadReadNoRace) { - ScopedThread t1, t2; - MemLoc l; - t1.Read1(l); - t2.Read1(l); -} - -TEST(ThreadSanitizer, WriteThenRead) { - MemLoc l; - ScopedThread t1, t2; - t1.Write1(l); - t1.Read1(l); - t2.Read1(l, true); -} - -TEST(ThreadSanitizer, WriteThenLockedRead) { - Mutex m(Mutex::RW); - MainThread t0; - t0.Create(m); - MemLoc l; - { - ScopedThread t1, t2; - - t1.Write8(l); - - t1.Lock(m); - t1.Read8(l); - t1.Unlock(m); - - t2.Read8(l, true); - } - t0.Destroy(m); -} - -TEST(ThreadSanitizer, LockedWriteThenRead) { - Mutex m(Mutex::RW); - MainThread t0; - t0.Create(m); - MemLoc l; - { - ScopedThread t1, t2; - - t1.Lock(m); - t1.Write8(l); - t1.Unlock(m); - - t1.Read8(l); - - t2.Read8(l, true); - } - t0.Destroy(m); -} - - -TEST(ThreadSanitizer, RaceWithOffset) { - ScopedThread t1, t2; - { - MemLoc l; - t1.Access(l.loc(), true, 8, false); - t2.Access((char*)l.loc() + 4, true, 4, true); - } - { - MemLoc l; - t1.Access(l.loc(), true, 8, false); - t2.Access((char*)l.loc() + 7, true, 1, true); - } - { - MemLoc l; - t1.Access((char*)l.loc() + 4, true, 4, false); - t2.Access((char*)l.loc() + 4, true, 2, true); - } - { - MemLoc l; - t1.Access((char*)l.loc() + 4, true, 4, false); - t2.Access((char*)l.loc() + 6, true, 2, true); - } - { - MemLoc l; - t1.Access((char*)l.loc() + 3, true, 2, false); - t2.Access((char*)l.loc() + 4, true, 1, true); - } - { - MemLoc l; - t1.Access((char*)l.loc() + 1, true, 8, false); - t2.Access((char*)l.loc() + 3, true, 1, true); - } -} - -TEST(ThreadSanitizer, RaceWithOffset2) { - ScopedThread t1, t2; - { - MemLoc l; - t1.Access((char*)l.loc(), true, 4, false); - t2.Access((char*)l.loc() + 2, true, 1, true); - } - { - MemLoc l; - t1.Access((char*)l.loc() + 2, true, 1, false); - t2.Access((char*)l.loc(), true, 4, true); - } -} - -TEST(ThreadSanitizer, NoRaceWithOffset) { - ScopedThread t1, t2; - { - MemLoc l; - t1.Access(l.loc(), true, 4, false); - t2.Access((char*)l.loc() + 4, true, 4, false); - } - { - MemLoc l; - t1.Access((char*)l.loc() + 3, true, 2, false); - t2.Access((char*)l.loc() + 1, true, 2, false); - t2.Access((char*)l.loc() + 5, true, 2, false); - } -} - -TEST(ThreadSanitizer, RaceWithDeadThread) { - MemLoc l; - ScopedThread t; - ScopedThread().Write1(l); - t.Write1(l, true); -} - -TEST(ThreadSanitizer, BenignRaceOnVptr) { - void *vptr_storage; - MemLoc vptr(&vptr_storage), val; - vptr_storage = val.loc(); - ScopedThread t1, t2; - t1.VptrUpdate(vptr, val); - t2.Read8(vptr); -} - -TEST(ThreadSanitizer, HarmfulRaceOnVptr) { - void *vptr_storage; - MemLoc vptr(&vptr_storage), val1, val2; - vptr_storage = val1.loc(); - ScopedThread t1, t2; - t1.VptrUpdate(vptr, val2); - t2.Read8(vptr, true); -} - -static void foo() { - volatile int x = 42; - int x2 = x; - (void)x2; -} - -static void bar() { - volatile int x = 43; - int x2 = x; - (void)x2; -} - -TEST(ThreadSanitizer, ReportDeadThread) { - MemLoc l; - ScopedThread t1; - { - ScopedThread t2; - t2.Call(&foo); - t2.Call(&bar); - t2.Write1(l); - } - t1.Write1(l, true); -} - -struct ClassWithStatic { - static int Data[4]; -}; - -int ClassWithStatic::Data[4]; - -static void foobarbaz() {} - -TEST(ThreadSanitizer, ReportRace) { - ScopedThread t1; - MainThread().Access(&ClassWithStatic::Data, true, 4, false); - t1.Call(&foobarbaz); - t1.Access(&ClassWithStatic::Data, true, 2, true); - t1.Return(); -} diff --git a/lib/tsan/tests/rtl/tsan_mutex.cc b/lib/tsan/tests/rtl/tsan_mutex.cc deleted file mode 100644 index 4d9c779618187..0000000000000 --- a/lib/tsan/tests/rtl/tsan_mutex.cc +++ /dev/null @@ -1,221 +0,0 @@ -//===-- tsan_mutex.cc -----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_atomic.h" -#include "tsan_interface.h" -#include "tsan_interface_ann.h" -#include "tsan_test_util.h" -#include "gtest/gtest.h" -#include <stdint.h> - -namespace __tsan { - -TEST(ThreadSanitizer, BasicMutex) { - ScopedThread t; - Mutex m; - t.Create(m); - - t.Lock(m); - t.Unlock(m); - - CHECK(t.TryLock(m)); - t.Unlock(m); - - t.Lock(m); - CHECK(!t.TryLock(m)); - t.Unlock(m); - - t.Destroy(m); -} - -TEST(ThreadSanitizer, BasicSpinMutex) { - ScopedThread t; - Mutex m(Mutex::Spin); - t.Create(m); - - t.Lock(m); - t.Unlock(m); - - CHECK(t.TryLock(m)); - t.Unlock(m); - - t.Lock(m); - CHECK(!t.TryLock(m)); - t.Unlock(m); - - t.Destroy(m); -} - -TEST(ThreadSanitizer, BasicRwMutex) { - ScopedThread t; - Mutex m(Mutex::RW); - t.Create(m); - - t.Lock(m); - t.Unlock(m); - - CHECK(t.TryLock(m)); - t.Unlock(m); - - t.Lock(m); - CHECK(!t.TryLock(m)); - t.Unlock(m); - - t.ReadLock(m); - t.ReadUnlock(m); - - CHECK(t.TryReadLock(m)); - t.ReadUnlock(m); - - t.Lock(m); - CHECK(!t.TryReadLock(m)); - t.Unlock(m); - - t.ReadLock(m); - CHECK(!t.TryLock(m)); - t.ReadUnlock(m); - - t.ReadLock(m); - CHECK(t.TryReadLock(m)); - t.ReadUnlock(m); - t.ReadUnlock(m); - - t.Destroy(m); -} - -TEST(ThreadSanitizer, Mutex) { - Mutex m; - MainThread t0; - t0.Create(m); - - ScopedThread t1, t2; - MemLoc l; - t1.Lock(m); - t1.Write1(l); - t1.Unlock(m); - t2.Lock(m); - t2.Write1(l); - t2.Unlock(m); - t2.Destroy(m); -} - -TEST(ThreadSanitizer, SpinMutex) { - Mutex m(Mutex::Spin); - MainThread t0; - t0.Create(m); - - ScopedThread t1, t2; - MemLoc l; - t1.Lock(m); - t1.Write1(l); - t1.Unlock(m); - t2.Lock(m); - t2.Write1(l); - t2.Unlock(m); - t2.Destroy(m); -} - -TEST(ThreadSanitizer, RwMutex) { - Mutex m(Mutex::RW); - MainThread t0; - t0.Create(m); - - ScopedThread t1, t2, t3; - MemLoc l; - t1.Lock(m); - t1.Write1(l); - t1.Unlock(m); - t2.Lock(m); - t2.Write1(l); - t2.Unlock(m); - t1.ReadLock(m); - t3.ReadLock(m); - t1.Read1(l); - t3.Read1(l); - t1.ReadUnlock(m); - t3.ReadUnlock(m); - t2.Lock(m); - t2.Write1(l); - t2.Unlock(m); - t2.Destroy(m); -} - -TEST(ThreadSanitizer, StaticMutex) { - // Emulates statically initialized mutex. - Mutex m; - m.StaticInit(); - { - ScopedThread t1, t2; - t1.Lock(m); - t1.Unlock(m); - t2.Lock(m); - t2.Unlock(m); - } - MainThread().Destroy(m); -} - -static void *singleton_thread(void *param) { - atomic_uintptr_t *singleton = (atomic_uintptr_t *)param; - for (int i = 0; i < 4*1024*1024; i++) { - int *val = (int *)atomic_load(singleton, memory_order_acquire); - __tsan_acquire(singleton); - __tsan_read4(val); - CHECK_EQ(*val, 42); - } - return 0; -} - -TEST(DISABLED_BENCH_ThreadSanitizer, Singleton) { - const int kClockSize = 100; - const int kThreadCount = 8; - - // Puff off thread's clock. - for (int i = 0; i < kClockSize; i++) { - ScopedThread t1; - (void)t1; - } - // Create the singleton. - int val = 42; - __tsan_write4(&val); - atomic_uintptr_t singleton; - __tsan_release(&singleton); - atomic_store(&singleton, (uintptr_t)&val, memory_order_release); - // Create reader threads. - pthread_t threads[kThreadCount]; - for (int t = 0; t < kThreadCount; t++) - pthread_create(&threads[t], 0, singleton_thread, &singleton); - for (int t = 0; t < kThreadCount; t++) - pthread_join(threads[t], 0); -} - -TEST(DISABLED_BENCH_ThreadSanitizer, StopFlag) { - const int kClockSize = 100; - const int kIters = 16*1024*1024; - - // Puff off thread's clock. - for (int i = 0; i < kClockSize; i++) { - ScopedThread t1; - (void)t1; - } - // Create the stop flag. - atomic_uintptr_t flag; - __tsan_release(&flag); - atomic_store(&flag, 0, memory_order_release); - // Read it a lot. - for (int i = 0; i < kIters; i++) { - uptr v = atomic_load(&flag, memory_order_acquire); - __tsan_acquire(&flag); - CHECK_EQ(v, 0); - } -} - -} // namespace __tsan diff --git a/lib/tsan/tests/rtl/tsan_posix.cc b/lib/tsan/tests/rtl/tsan_posix.cc deleted file mode 100644 index e66dab609c620..0000000000000 --- a/lib/tsan/tests/rtl/tsan_posix.cc +++ /dev/null @@ -1,155 +0,0 @@ -//===-- tsan_posix.cc -----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_interface.h" -#include "tsan_posix_util.h" -#include "tsan_test_util.h" -#include "gtest/gtest.h" -#include <pthread.h> - -struct thread_key { - pthread_key_t key; - pthread_mutex_t *mtx; - int val; - int *cnt; - thread_key(pthread_key_t key, pthread_mutex_t *mtx, int val, int *cnt) - : key(key) - , mtx(mtx) - , val(val) - , cnt(cnt) { - } -}; - -static void thread_secific_dtor(void *v) { - thread_key *k = (thread_key *)v; - EXPECT_EQ(__interceptor_pthread_mutex_lock(k->mtx), 0); - (*k->cnt)++; - __tsan_write4(&k->cnt); - EXPECT_EQ(__interceptor_pthread_mutex_unlock(k->mtx), 0); - if (k->val == 42) { - // Okay. - } else if (k->val == 43 || k->val == 44) { - k->val--; - EXPECT_EQ(pthread_setspecific(k->key, k), 0); - } else { - ASSERT_TRUE(false); - } -} - -static void *dtors_thread(void *p) { - thread_key *k = (thread_key *)p; - EXPECT_EQ(pthread_setspecific(k->key, k), 0); - return 0; -} - -TEST(Posix, ThreadSpecificDtors) { - int cnt = 0; - pthread_key_t key; - EXPECT_EQ(pthread_key_create(&key, thread_secific_dtor), 0); - pthread_mutex_t mtx; - EXPECT_EQ(__interceptor_pthread_mutex_init(&mtx, 0), 0); - pthread_t th[3]; - thread_key k1 = thread_key(key, &mtx, 42, &cnt); - thread_key k2 = thread_key(key, &mtx, 43, &cnt); - thread_key k3 = thread_key(key, &mtx, 44, &cnt); - EXPECT_EQ(__interceptor_pthread_create(&th[0], 0, dtors_thread, &k1), 0); - EXPECT_EQ(__interceptor_pthread_create(&th[1], 0, dtors_thread, &k2), 0); - EXPECT_EQ(__interceptor_pthread_join(th[0], 0), 0); - EXPECT_EQ(__interceptor_pthread_create(&th[2], 0, dtors_thread, &k3), 0); - EXPECT_EQ(__interceptor_pthread_join(th[1], 0), 0); - EXPECT_EQ(__interceptor_pthread_join(th[2], 0), 0); - EXPECT_EQ(pthread_key_delete(key), 0); - EXPECT_EQ(6, cnt); -} - -#if !defined(__aarch64__) && !defined(__APPLE__) -static __thread int local_var; - -static void *local_thread(void *p) { - __tsan_write1(&local_var); - __tsan_write1(&p); - if (p == 0) - return 0; - const int kThreads = 4; - pthread_t th[kThreads]; - for (int i = 0; i < kThreads; i++) - EXPECT_EQ(__interceptor_pthread_create(&th[i], 0, local_thread, - (void*)((long)p - 1)), 0); // NOLINT - for (int i = 0; i < kThreads; i++) - EXPECT_EQ(__interceptor_pthread_join(th[i], 0), 0); - return 0; -} -#endif - -TEST(Posix, ThreadLocalAccesses) { -// The test is failing with high thread count for aarch64. -// FIXME: track down the issue and re-enable the test. -// On Darwin, we're running unit tests without interceptors and __thread is -// using malloc and free, which causes false data race reports. On rare -// occasions on powerpc64le this test also fails. -#if !defined(__aarch64__) && !defined(__APPLE__) && !defined(powerpc64le) - local_thread((void*)2); -#endif -} - -struct CondContext { - pthread_mutex_t m; - pthread_cond_t c; - int data; -}; - -static void *cond_thread(void *p) { - CondContext &ctx = *static_cast<CondContext*>(p); - - EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); - EXPECT_EQ(ctx.data, 0); - ctx.data = 1; - EXPECT_EQ(__interceptor_pthread_cond_signal(&ctx.c), 0); - EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); - - EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); - while (ctx.data != 2) - EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); - EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); - - EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); - ctx.data = 3; - EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0); - EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); - - return 0; -} - -TEST(Posix, CondBasic) { - CondContext ctx; - EXPECT_EQ(__interceptor_pthread_mutex_init(&ctx.m, 0), 0); - EXPECT_EQ(__interceptor_pthread_cond_init(&ctx.c, 0), 0); - ctx.data = 0; - pthread_t th; - EXPECT_EQ(__interceptor_pthread_create(&th, 0, cond_thread, &ctx), 0); - - EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); - while (ctx.data != 1) - EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); - ctx.data = 2; - EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); - EXPECT_EQ(pthread_cond_broadcast(&ctx.c), 0); - - EXPECT_EQ(__interceptor_pthread_mutex_lock(&ctx.m), 0); - while (ctx.data != 3) - EXPECT_EQ(__interceptor_pthread_cond_wait(&ctx.c, &ctx.m), 0); - EXPECT_EQ(__interceptor_pthread_mutex_unlock(&ctx.m), 0); - - EXPECT_EQ(__interceptor_pthread_join(th, 0), 0); - EXPECT_EQ(__interceptor_pthread_cond_destroy(&ctx.c), 0); - EXPECT_EQ(__interceptor_pthread_mutex_destroy(&ctx.m), 0); -} diff --git a/lib/tsan/tests/rtl/tsan_posix_util.h b/lib/tsan/tests/rtl/tsan_posix_util.h deleted file mode 100644 index 340693ebb8a09..0000000000000 --- a/lib/tsan/tests/rtl/tsan_posix_util.h +++ /dev/null @@ -1,77 +0,0 @@ -//===-- tsan_posix_util.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -// Test POSIX utils. -//===----------------------------------------------------------------------===// -#ifndef TSAN_POSIX_UTIL_H -#define TSAN_POSIX_UTIL_H - -#include <pthread.h> - -#ifdef __APPLE__ -#define __interceptor_memcpy wrap_memcpy -#define __interceptor_memset wrap_memset -#define __interceptor_pthread_create wrap_pthread_create -#define __interceptor_pthread_join wrap_pthread_join -#define __interceptor_pthread_detach wrap_pthread_detach -#define __interceptor_pthread_mutex_init wrap_pthread_mutex_init -#define __interceptor_pthread_mutex_lock wrap_pthread_mutex_lock -#define __interceptor_pthread_mutex_unlock wrap_pthread_mutex_unlock -#define __interceptor_pthread_mutex_destroy wrap_pthread_mutex_destroy -#define __interceptor_pthread_mutex_trylock wrap_pthread_mutex_trylock -#define __interceptor_pthread_rwlock_init wrap_pthread_rwlock_init -#define __interceptor_pthread_rwlock_destroy wrap_pthread_rwlock_destroy -#define __interceptor_pthread_rwlock_trywrlock wrap_pthread_rwlock_trywrlock -#define __interceptor_pthread_rwlock_wrlock wrap_pthread_rwlock_wrlock -#define __interceptor_pthread_rwlock_unlock wrap_pthread_rwlock_unlock -#define __interceptor_pthread_rwlock_rdlock wrap_pthread_rwlock_rdlock -#define __interceptor_pthread_rwlock_tryrdlock wrap_pthread_rwlock_tryrdlock -#define __interceptor_pthread_cond_init wrap_pthread_cond_init -#define __interceptor_pthread_cond_signal wrap_pthread_cond_signal -#define __interceptor_pthread_cond_broadcast wrap_pthread_cond_broadcast -#define __interceptor_pthread_cond_wait wrap_pthread_cond_wait -#define __interceptor_pthread_cond_destroy wrap_pthread_cond_destroy -#endif - -extern "C" void *__interceptor_memcpy(void *, const void *, uptr); -extern "C" void *__interceptor_memset(void *, int, uptr); -extern "C" int __interceptor_pthread_create(pthread_t *thread, - const pthread_attr_t *attr, - void *(*start_routine)(void *), - void *arg); -extern "C" int __interceptor_pthread_join(pthread_t thread, void **value_ptr); -extern "C" int __interceptor_pthread_detach(pthread_t thread); - -extern "C" int __interceptor_pthread_mutex_init( - pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); -extern "C" int __interceptor_pthread_mutex_lock(pthread_mutex_t *mutex); -extern "C" int __interceptor_pthread_mutex_unlock(pthread_mutex_t *mutex); -extern "C" int __interceptor_pthread_mutex_destroy(pthread_mutex_t *mutex); -extern "C" int __interceptor_pthread_mutex_trylock(pthread_mutex_t *mutex); - -extern "C" int __interceptor_pthread_rwlock_init( - pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); -extern "C" int __interceptor_pthread_rwlock_destroy(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_unlock(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); -extern "C" int __interceptor_pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); - -extern "C" int __interceptor_pthread_cond_init(pthread_cond_t *cond, - const pthread_condattr_t *attr); -extern "C" int __interceptor_pthread_cond_signal(pthread_cond_t *cond); -extern "C" int __interceptor_pthread_cond_broadcast(pthread_cond_t *cond); -extern "C" int __interceptor_pthread_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex); -extern "C" int __interceptor_pthread_cond_destroy(pthread_cond_t *cond); - -#endif // #ifndef TSAN_POSIX_UTIL_H diff --git a/lib/tsan/tests/rtl/tsan_string.cc b/lib/tsan/tests/rtl/tsan_string.cc deleted file mode 100644 index 75adc6c85ee9c..0000000000000 --- a/lib/tsan/tests/rtl/tsan_string.cc +++ /dev/null @@ -1,82 +0,0 @@ -//===-- tsan_string.cc ----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_test_util.h" -#include "gtest/gtest.h" -#include <string.h> - -namespace __tsan { - -TEST(ThreadSanitizer, Memcpy) { - char data0[7] = {1, 2, 3, 4, 5, 6, 7}; - char data[7] = {42, 42, 42, 42, 42, 42, 42}; - MainThread().Memcpy(data+1, data0+1, 5); - EXPECT_EQ(data[0], 42); - EXPECT_EQ(data[1], 2); - EXPECT_EQ(data[2], 3); - EXPECT_EQ(data[3], 4); - EXPECT_EQ(data[4], 5); - EXPECT_EQ(data[5], 6); - EXPECT_EQ(data[6], 42); - MainThread().Memset(data+1, 13, 5); - EXPECT_EQ(data[0], 42); - EXPECT_EQ(data[1], 13); - EXPECT_EQ(data[2], 13); - EXPECT_EQ(data[3], 13); - EXPECT_EQ(data[4], 13); - EXPECT_EQ(data[5], 13); - EXPECT_EQ(data[6], 42); -} - -TEST(ThreadSanitizer, MemcpyRace1) { - char *data = new char[10]; - char *data1 = new char[10]; - char *data2 = new char[10]; - ScopedThread t1, t2; - t1.Memcpy(data, data1, 10); - t2.Memcpy(data, data2, 10, true); -} - -TEST(ThreadSanitizer, MemcpyRace2) { - char *data = new char[10]; - char *data1 = new char[10]; - char *data2 = new char[10]; - ScopedThread t1, t2; - t1.Memcpy(data+5, data1, 1); - t2.Memcpy(data+3, data2, 4, true); -} - -TEST(ThreadSanitizer, MemcpyRace3) { - char *data = new char[10]; - char *data1 = new char[10]; - char *data2 = new char[10]; - ScopedThread t1, t2; - t1.Memcpy(data, data1, 10); - t2.Memcpy(data1, data2, 10, true); -} - -TEST(ThreadSanitizer, MemcpyStack) { - char *data = new char[10]; - char *data1 = new char[10]; - ScopedThread t1, t2; - t1.Memcpy(data, data1, 10); - t2.Memcpy(data, data1, 10, true); -} - -TEST(ThreadSanitizer, MemsetRace1) { - char *data = new char[10]; - ScopedThread t1, t2; - t1.Memset(data, 1, 10); - t2.Memset(data, 2, 10, true); -} - -} // namespace __tsan diff --git a/lib/tsan/tests/rtl/tsan_test.cc b/lib/tsan/tests/rtl/tsan_test.cc deleted file mode 100644 index 842b417500d83..0000000000000 --- a/lib/tsan/tests/rtl/tsan_test.cc +++ /dev/null @@ -1,66 +0,0 @@ -//===-- tsan_test.cc ------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_interface.h" -#include "tsan_test_util.h" -#include "gtest/gtest.h" - -static void foo() {} -static void bar() {} - -TEST(ThreadSanitizer, FuncCall) { - ScopedThread t1, t2; - MemLoc l; - t1.Write1(l); - t2.Call(foo); - t2.Call(bar); - t2.Write1(l, true); - t2.Return(); - t2.Return(); -} - -// We use this function instead of main, as ISO C++ forbids taking the address -// of main, which we need to pass inside __tsan_func_entry. -int run_tests(int argc, char **argv) { - TestMutexBeforeInit(); // Mutexes must be usable before __tsan_init(); - __tsan_init(); - __tsan_func_entry(__builtin_return_address(0)); - __tsan_func_entry((void*)((intptr_t)&run_tests + 1)); - - testing::GTEST_FLAG(death_test_style) = "threadsafe"; - testing::InitGoogleTest(&argc, argv); - int res = RUN_ALL_TESTS(); - - __tsan_func_exit(); - __tsan_func_exit(); - return res; -} - -const char *argv0; - -#ifdef __APPLE__ -// On Darwin, turns off symbolication and crash logs to make tests faster. -extern "C" const char* __tsan_default_options() { - return "symbolize=false:abort_on_error=0"; -} -#endif - -namespace __sanitizer { -bool ReexecDisabled() { - return true; -} -} - -int main(int argc, char **argv) { - argv0 = argv[0]; - return run_tests(argc, argv); -} diff --git a/lib/tsan/tests/rtl/tsan_test_util.h b/lib/tsan/tests/rtl/tsan_test_util.h deleted file mode 100644 index 31b1b188f6247..0000000000000 --- a/lib/tsan/tests/rtl/tsan_test_util.h +++ /dev/null @@ -1,130 +0,0 @@ -//===-- tsan_test_util.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -// Test utils. -//===----------------------------------------------------------------------===// -#ifndef TSAN_TEST_UTIL_H -#define TSAN_TEST_UTIL_H - -void TestMutexBeforeInit(); - -// A location of memory on which a race may be detected. -class MemLoc { - public: - explicit MemLoc(int offset_from_aligned = 0); - explicit MemLoc(void *const real_addr) : loc_(real_addr) { } - ~MemLoc(); - void *loc() const { return loc_; } - private: - void *const loc_; - MemLoc(const MemLoc&); - void operator = (const MemLoc&); -}; - -class Mutex { - public: - enum Type { - Normal, - RW, -#ifndef __APPLE__ - Spin -#else - Spin = Normal -#endif - }; - - explicit Mutex(Type type = Normal); - ~Mutex(); - - void Init(); - void StaticInit(); // Emulates static initialization (tsan invisible). - void Destroy(); - void Lock(); - bool TryLock(); - void Unlock(); - void ReadLock(); - bool TryReadLock(); - void ReadUnlock(); - - private: - // Placeholder for pthread_mutex_t, CRITICAL_SECTION or whatever. - void *mtx_[128]; - bool alive_; - const Type type_; - - Mutex(const Mutex&); - void operator = (const Mutex&); -}; - -// A thread is started in CTOR and joined in DTOR. -class ScopedThread { - public: - explicit ScopedThread(bool detached = false, bool main = false); - ~ScopedThread(); - void Detach(); - - void Access(void *addr, bool is_write, int size, bool expect_race); - void Read(const MemLoc &ml, int size, bool expect_race = false) { - Access(ml.loc(), false, size, expect_race); - } - void Write(const MemLoc &ml, int size, bool expect_race = false) { - Access(ml.loc(), true, size, expect_race); - } - void Read1(const MemLoc &ml, bool expect_race = false) { - Read(ml, 1, expect_race); } - void Read2(const MemLoc &ml, bool expect_race = false) { - Read(ml, 2, expect_race); } - void Read4(const MemLoc &ml, bool expect_race = false) { - Read(ml, 4, expect_race); } - void Read8(const MemLoc &ml, bool expect_race = false) { - Read(ml, 8, expect_race); } - void Write1(const MemLoc &ml, bool expect_race = false) { - Write(ml, 1, expect_race); } - void Write2(const MemLoc &ml, bool expect_race = false) { - Write(ml, 2, expect_race); } - void Write4(const MemLoc &ml, bool expect_race = false) { - Write(ml, 4, expect_race); } - void Write8(const MemLoc &ml, bool expect_race = false) { - Write(ml, 8, expect_race); } - - void VptrUpdate(const MemLoc &vptr, const MemLoc &new_val, - bool expect_race = false); - - void Call(void(*pc)()); - void Return(); - - void Create(const Mutex &m); - void Destroy(const Mutex &m); - void Lock(const Mutex &m); - bool TryLock(const Mutex &m); - void Unlock(const Mutex &m); - void ReadLock(const Mutex &m); - bool TryReadLock(const Mutex &m); - void ReadUnlock(const Mutex &m); - - void Memcpy(void *dst, const void *src, int size, bool expect_race = false); - void Memset(void *dst, int val, int size, bool expect_race = false); - - private: - struct Impl; - Impl *impl_; - ScopedThread(const ScopedThread&); // Not implemented. - void operator = (const ScopedThread&); // Not implemented. -}; - -class MainThread : public ScopedThread { - public: - MainThread() - : ScopedThread(false, true) { - } -}; - -#endif // #ifndef TSAN_TEST_UTIL_H diff --git a/lib/tsan/tests/rtl/tsan_test_util_posix.cc b/lib/tsan/tests/rtl/tsan_test_util_posix.cc deleted file mode 100644 index d00e26dd5ca6b..0000000000000 --- a/lib/tsan/tests/rtl/tsan_test_util_posix.cc +++ /dev/null @@ -1,478 +0,0 @@ -//===-- tsan_test_util_posix.cc -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -// Test utils, Linux, FreeBSD, NetBSD and Darwin implementation. -//===----------------------------------------------------------------------===// - -#include "sanitizer_common/sanitizer_atomic.h" -#include "tsan_interface.h" -#include "tsan_posix_util.h" -#include "tsan_test_util.h" -#include "tsan_report.h" - -#include "gtest/gtest.h" - -#include <assert.h> -#include <pthread.h> -#include <stdio.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -using namespace __tsan; // NOLINT - -static __thread bool expect_report; -static __thread bool expect_report_reported; -static __thread ReportType expect_report_type; - -static void *BeforeInitThread(void *param) { - (void)param; - return 0; -} - -static void AtExit() { -} - -void TestMutexBeforeInit() { - // Mutexes must be usable before __tsan_init(); - pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; - __interceptor_pthread_mutex_lock(&mtx); - __interceptor_pthread_mutex_unlock(&mtx); - __interceptor_pthread_mutex_destroy(&mtx); - pthread_t thr; - __interceptor_pthread_create(&thr, 0, BeforeInitThread, 0); - __interceptor_pthread_join(thr, 0); - atexit(AtExit); -} - -namespace __tsan { -bool OnReport(const ReportDesc *rep, bool suppressed) { - if (expect_report) { - if (rep->typ != expect_report_type) { - printf("Expected report of type %d, got type %d\n", - (int)expect_report_type, (int)rep->typ); - EXPECT_TRUE(false) << "Wrong report type"; - return false; - } - } else { - EXPECT_TRUE(false) << "Unexpected report"; - return false; - } - expect_report_reported = true; - return true; -} -} // namespace __tsan - -static void* allocate_addr(int size, int offset_from_aligned = 0) { - static uintptr_t foo; - static atomic_uintptr_t uniq = {(uintptr_t)&foo}; // Some real address. - const int kAlign = 16; - CHECK(offset_from_aligned < kAlign); - size = (size + 2 * kAlign) & ~(kAlign - 1); - uintptr_t addr = atomic_fetch_add(&uniq, size, memory_order_relaxed); - return (void*)(addr + offset_from_aligned); -} - -MemLoc::MemLoc(int offset_from_aligned) - : loc_(allocate_addr(16, offset_from_aligned)) { -} - -MemLoc::~MemLoc() { -} - -Mutex::Mutex(Type type) - : alive_() - , type_(type) { -} - -Mutex::~Mutex() { - CHECK(!alive_); -} - -void Mutex::Init() { - CHECK(!alive_); - alive_ = true; - if (type_ == Normal) - CHECK_EQ(__interceptor_pthread_mutex_init((pthread_mutex_t*)mtx_, 0), 0); -#ifndef __APPLE__ - else if (type_ == Spin) - CHECK_EQ(pthread_spin_init((pthread_spinlock_t*)mtx_, 0), 0); -#endif - else if (type_ == RW) - CHECK_EQ(__interceptor_pthread_rwlock_init((pthread_rwlock_t*)mtx_, 0), 0); - else - CHECK(0); -} - -void Mutex::StaticInit() { - CHECK(!alive_); - CHECK(type_ == Normal); - alive_ = true; - pthread_mutex_t tmp = PTHREAD_MUTEX_INITIALIZER; - memcpy(mtx_, &tmp, sizeof(tmp)); -} - -void Mutex::Destroy() { - CHECK(alive_); - alive_ = false; - if (type_ == Normal) - CHECK_EQ(__interceptor_pthread_mutex_destroy((pthread_mutex_t*)mtx_), 0); -#ifndef __APPLE__ - else if (type_ == Spin) - CHECK_EQ(pthread_spin_destroy((pthread_spinlock_t*)mtx_), 0); -#endif - else if (type_ == RW) - CHECK_EQ(__interceptor_pthread_rwlock_destroy((pthread_rwlock_t*)mtx_), 0); -} - -void Mutex::Lock() { - CHECK(alive_); - if (type_ == Normal) - CHECK_EQ(__interceptor_pthread_mutex_lock((pthread_mutex_t*)mtx_), 0); -#ifndef __APPLE__ - else if (type_ == Spin) - CHECK_EQ(pthread_spin_lock((pthread_spinlock_t*)mtx_), 0); -#endif - else if (type_ == RW) - CHECK_EQ(__interceptor_pthread_rwlock_wrlock((pthread_rwlock_t*)mtx_), 0); -} - -bool Mutex::TryLock() { - CHECK(alive_); - if (type_ == Normal) - return __interceptor_pthread_mutex_trylock((pthread_mutex_t*)mtx_) == 0; -#ifndef __APPLE__ - else if (type_ == Spin) - return pthread_spin_trylock((pthread_spinlock_t*)mtx_) == 0; -#endif - else if (type_ == RW) - return __interceptor_pthread_rwlock_trywrlock((pthread_rwlock_t*)mtx_) == 0; - return false; -} - -void Mutex::Unlock() { - CHECK(alive_); - if (type_ == Normal) - CHECK_EQ(__interceptor_pthread_mutex_unlock((pthread_mutex_t*)mtx_), 0); -#ifndef __APPLE__ - else if (type_ == Spin) - CHECK_EQ(pthread_spin_unlock((pthread_spinlock_t*)mtx_), 0); -#endif - else if (type_ == RW) - CHECK_EQ(__interceptor_pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0); -} - -void Mutex::ReadLock() { - CHECK(alive_); - CHECK(type_ == RW); - CHECK_EQ(__interceptor_pthread_rwlock_rdlock((pthread_rwlock_t*)mtx_), 0); -} - -bool Mutex::TryReadLock() { - CHECK(alive_); - CHECK(type_ == RW); - return __interceptor_pthread_rwlock_tryrdlock((pthread_rwlock_t*)mtx_) == 0; -} - -void Mutex::ReadUnlock() { - CHECK(alive_); - CHECK(type_ == RW); - CHECK_EQ(__interceptor_pthread_rwlock_unlock((pthread_rwlock_t*)mtx_), 0); -} - -struct Event { - enum Type { - SHUTDOWN, - READ, - WRITE, - VPTR_UPDATE, - CALL, - RETURN, - MUTEX_CREATE, - MUTEX_DESTROY, - MUTEX_LOCK, - MUTEX_TRYLOCK, - MUTEX_UNLOCK, - MUTEX_READLOCK, - MUTEX_TRYREADLOCK, - MUTEX_READUNLOCK, - MEMCPY, - MEMSET - }; - Type type; - void *ptr; - uptr arg; - uptr arg2; - bool res; - bool expect_report; - ReportType report_type; - - Event(Type type, const void *ptr = 0, uptr arg = 0, uptr arg2 = 0) - : type(type) - , ptr(const_cast<void*>(ptr)) - , arg(arg) - , arg2(arg2) - , res() - , expect_report() - , report_type() { - } - - void ExpectReport(ReportType type) { - expect_report = true; - report_type = type; - } -}; - -struct ScopedThread::Impl { - pthread_t thread; - bool main; - bool detached; - atomic_uintptr_t event; // Event* - - static void *ScopedThreadCallback(void *arg); - void send(Event *ev); - void HandleEvent(Event *ev); -}; - -void ScopedThread::Impl::HandleEvent(Event *ev) { - CHECK_EQ(expect_report, false); - expect_report = ev->expect_report; - expect_report_reported = false; - expect_report_type = ev->report_type; - switch (ev->type) { - case Event::READ: - case Event::WRITE: { - void (*tsan_mop)(void *addr) = 0; - if (ev->type == Event::READ) { - switch (ev->arg /*size*/) { - case 1: tsan_mop = __tsan_read1; break; - case 2: tsan_mop = __tsan_read2; break; - case 4: tsan_mop = __tsan_read4; break; - case 8: tsan_mop = __tsan_read8; break; - case 16: tsan_mop = __tsan_read16; break; - } - } else { - switch (ev->arg /*size*/) { - case 1: tsan_mop = __tsan_write1; break; - case 2: tsan_mop = __tsan_write2; break; - case 4: tsan_mop = __tsan_write4; break; - case 8: tsan_mop = __tsan_write8; break; - case 16: tsan_mop = __tsan_write16; break; - } - } - CHECK_NE(tsan_mop, 0); -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__) - const int ErrCode = ESOCKTNOSUPPORT; -#else - const int ErrCode = ECHRNG; -#endif - errno = ErrCode; - tsan_mop(ev->ptr); - CHECK_EQ(ErrCode, errno); // In no case must errno be changed. - break; - } - case Event::VPTR_UPDATE: - __tsan_vptr_update((void**)ev->ptr, (void*)ev->arg); - break; - case Event::CALL: - __tsan_func_entry((void*)((uptr)ev->ptr)); - break; - case Event::RETURN: - __tsan_func_exit(); - break; - case Event::MUTEX_CREATE: - static_cast<Mutex*>(ev->ptr)->Init(); - break; - case Event::MUTEX_DESTROY: - static_cast<Mutex*>(ev->ptr)->Destroy(); - break; - case Event::MUTEX_LOCK: - static_cast<Mutex*>(ev->ptr)->Lock(); - break; - case Event::MUTEX_TRYLOCK: - ev->res = static_cast<Mutex*>(ev->ptr)->TryLock(); - break; - case Event::MUTEX_UNLOCK: - static_cast<Mutex*>(ev->ptr)->Unlock(); - break; - case Event::MUTEX_READLOCK: - static_cast<Mutex*>(ev->ptr)->ReadLock(); - break; - case Event::MUTEX_TRYREADLOCK: - ev->res = static_cast<Mutex*>(ev->ptr)->TryReadLock(); - break; - case Event::MUTEX_READUNLOCK: - static_cast<Mutex*>(ev->ptr)->ReadUnlock(); - break; - case Event::MEMCPY: - __interceptor_memcpy(ev->ptr, (void*)ev->arg, ev->arg2); - break; - case Event::MEMSET: - __interceptor_memset(ev->ptr, ev->arg, ev->arg2); - break; - default: CHECK(0); - } - if (expect_report && !expect_report_reported) { - printf("Missed expected report of type %d\n", (int)ev->report_type); - EXPECT_TRUE(false) << "Missed expected race"; - } - expect_report = false; -} - -void *ScopedThread::Impl::ScopedThreadCallback(void *arg) { - __tsan_func_entry(__builtin_return_address(0)); - Impl *impl = (Impl*)arg; - for (;;) { - Event* ev = (Event*)atomic_load(&impl->event, memory_order_acquire); - if (ev == 0) { - sched_yield(); - continue; - } - if (ev->type == Event::SHUTDOWN) { - atomic_store(&impl->event, 0, memory_order_release); - break; - } - impl->HandleEvent(ev); - atomic_store(&impl->event, 0, memory_order_release); - } - __tsan_func_exit(); - return 0; -} - -void ScopedThread::Impl::send(Event *e) { - if (main) { - HandleEvent(e); - } else { - CHECK_EQ(atomic_load(&event, memory_order_relaxed), 0); - atomic_store(&event, (uintptr_t)e, memory_order_release); - while (atomic_load(&event, memory_order_acquire) != 0) - sched_yield(); - } -} - -ScopedThread::ScopedThread(bool detached, bool main) { - impl_ = new Impl; - impl_->main = main; - impl_->detached = detached; - atomic_store(&impl_->event, 0, memory_order_relaxed); - if (!main) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate( - &attr, detached ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); - pthread_attr_setstacksize(&attr, 64*1024); - __interceptor_pthread_create(&impl_->thread, &attr, - ScopedThread::Impl::ScopedThreadCallback, impl_); - } -} - -ScopedThread::~ScopedThread() { - if (!impl_->main) { - Event event(Event::SHUTDOWN); - impl_->send(&event); - if (!impl_->detached) - __interceptor_pthread_join(impl_->thread, 0); - } - delete impl_; -} - -void ScopedThread::Detach() { - CHECK(!impl_->main); - CHECK(!impl_->detached); - impl_->detached = true; - __interceptor_pthread_detach(impl_->thread); -} - -void ScopedThread::Access(void *addr, bool is_write, - int size, bool expect_race) { - Event event(is_write ? Event::WRITE : Event::READ, addr, size); - if (expect_race) - event.ExpectReport(ReportTypeRace); - impl_->send(&event); -} - -void ScopedThread::VptrUpdate(const MemLoc &vptr, - const MemLoc &new_val, - bool expect_race) { - Event event(Event::VPTR_UPDATE, vptr.loc(), (uptr)new_val.loc()); - if (expect_race) - event.ExpectReport(ReportTypeRace); - impl_->send(&event); -} - -void ScopedThread::Call(void(*pc)()) { - Event event(Event::CALL, (void*)((uintptr_t)pc)); - impl_->send(&event); -} - -void ScopedThread::Return() { - Event event(Event::RETURN); - impl_->send(&event); -} - -void ScopedThread::Create(const Mutex &m) { - Event event(Event::MUTEX_CREATE, &m); - impl_->send(&event); -} - -void ScopedThread::Destroy(const Mutex &m) { - Event event(Event::MUTEX_DESTROY, &m); - impl_->send(&event); -} - -void ScopedThread::Lock(const Mutex &m) { - Event event(Event::MUTEX_LOCK, &m); - impl_->send(&event); -} - -bool ScopedThread::TryLock(const Mutex &m) { - Event event(Event::MUTEX_TRYLOCK, &m); - impl_->send(&event); - return event.res; -} - -void ScopedThread::Unlock(const Mutex &m) { - Event event(Event::MUTEX_UNLOCK, &m); - impl_->send(&event); -} - -void ScopedThread::ReadLock(const Mutex &m) { - Event event(Event::MUTEX_READLOCK, &m); - impl_->send(&event); -} - -bool ScopedThread::TryReadLock(const Mutex &m) { - Event event(Event::MUTEX_TRYREADLOCK, &m); - impl_->send(&event); - return event.res; -} - -void ScopedThread::ReadUnlock(const Mutex &m) { - Event event(Event::MUTEX_READUNLOCK, &m); - impl_->send(&event); -} - -void ScopedThread::Memcpy(void *dst, const void *src, int size, - bool expect_race) { - Event event(Event::MEMCPY, dst, (uptr)src, size); - if (expect_race) - event.ExpectReport(ReportTypeRace); - impl_->send(&event); -} - -void ScopedThread::Memset(void *dst, int val, int size, - bool expect_race) { - Event event(Event::MEMSET, dst, val, size); - if (expect_race) - event.ExpectReport(ReportTypeRace); - impl_->send(&event); -} diff --git a/lib/tsan/tests/rtl/tsan_thread.cc b/lib/tsan/tests/rtl/tsan_thread.cc deleted file mode 100644 index 5646415a79b87..0000000000000 --- a/lib/tsan/tests/rtl/tsan_thread.cc +++ /dev/null @@ -1,59 +0,0 @@ -//===-- tsan_thread.cc ----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_test_util.h" -#include "gtest/gtest.h" - -TEST(ThreadSanitizer, ThreadSync) { - MainThread t0; - MemLoc l; - t0.Write1(l); - { - ScopedThread t1; - t1.Write1(l); - } - t0.Write1(l); -} - -TEST(ThreadSanitizer, ThreadDetach1) { - ScopedThread t1(true); - MemLoc l; - t1.Write1(l); -} - -TEST(ThreadSanitizer, ThreadDetach2) { - ScopedThread t1; - MemLoc l; - t1.Write1(l); - t1.Detach(); -} - -static void *thread_alot_func(void *arg) { - (void)arg; - int usleep(unsigned); - usleep(50); - return 0; -} - -TEST(DISABLED_SLOW_ThreadSanitizer, ThreadALot) { - const int kThreads = 70000; - const int kAlive = 1000; - pthread_t threads[kAlive] = {}; - for (int i = 0; i < kThreads; i++) { - if (threads[i % kAlive]) - pthread_join(threads[i % kAlive], 0); - pthread_create(&threads[i % kAlive], 0, thread_alot_func, 0); - } - for (int i = 0; i < kAlive; i++) { - pthread_join(threads[i], 0); - } -} diff --git a/lib/tsan/tests/unit/CMakeLists.txt b/lib/tsan/tests/unit/CMakeLists.txt deleted file mode 100644 index c08508d507917..0000000000000 --- a/lib/tsan/tests/unit/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -set(TSAN_UNIT_TEST_SOURCES - tsan_clock_test.cc - tsan_flags_test.cc - tsan_mman_test.cc - tsan_mutex_test.cc - tsan_shadow_test.cc - tsan_stack_test.cc - tsan_sync_test.cc - tsan_unit_test_main.cc) - -add_tsan_unittest(TsanUnitTest - SOURCES ${TSAN_UNIT_TEST_SOURCES}) diff --git a/lib/tsan/tests/unit/tsan_clock_test.cc b/lib/tsan/tests/unit/tsan_clock_test.cc deleted file mode 100644 index f6230e1be5656..0000000000000 --- a/lib/tsan/tests/unit/tsan_clock_test.cc +++ /dev/null @@ -1,494 +0,0 @@ -//===-- tsan_clock_test.cc ------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_clock.h" -#include "tsan_rtl.h" -#include "gtest/gtest.h" -#include <sys/time.h> -#include <time.h> - -namespace __tsan { - -ClockCache cache; - -TEST(Clock, VectorBasic) { - ThreadClock clk(0); - ASSERT_EQ(clk.size(), 1U); - clk.tick(); - ASSERT_EQ(clk.size(), 1U); - ASSERT_EQ(clk.get(0), 1U); - clk.set(&cache, 3, clk.get(3) + 1); - ASSERT_EQ(clk.size(), 4U); - ASSERT_EQ(clk.get(0), 1U); - ASSERT_EQ(clk.get(1), 0U); - ASSERT_EQ(clk.get(2), 0U); - ASSERT_EQ(clk.get(3), 1U); - clk.set(&cache, 3, clk.get(3) + 1); - ASSERT_EQ(clk.get(3), 2U); -} - -TEST(Clock, ChunkedBasic) { - ThreadClock vector(0); - SyncClock chunked; - ASSERT_EQ(vector.size(), 1U); - ASSERT_EQ(chunked.size(), 0U); - vector.acquire(&cache, &chunked); - ASSERT_EQ(vector.size(), 1U); - ASSERT_EQ(chunked.size(), 0U); - vector.release(&cache, &chunked); - ASSERT_EQ(vector.size(), 1U); - ASSERT_EQ(chunked.size(), 1U); - vector.acq_rel(&cache, &chunked); - ASSERT_EQ(vector.size(), 1U); - ASSERT_EQ(chunked.size(), 1U); - chunked.Reset(&cache); -} - -static const uptr interesting_sizes[] = {0, 1, 2, 30, 61, 62, 63, 64, 65, 66, - 100, 124, 125, 126, 127, 128, 129, 130, 188, 189, 190, 191, 192, 193, 254, - 255}; - -TEST(Clock, Iter) { - const uptr n = ARRAY_SIZE(interesting_sizes); - for (uptr fi = 0; fi < n; fi++) { - const uptr size = interesting_sizes[fi]; - SyncClock sync; - ThreadClock vector(0); - for (uptr i = 0; i < size; i++) - vector.set(&cache, i, i + 1); - if (size != 0) - vector.release(&cache, &sync); - uptr i = 0; - for (ClockElem &ce : sync) { - ASSERT_LT(i, size); - ASSERT_EQ(sync.get_clean(i), ce.epoch); - i++; - } - ASSERT_EQ(i, size); - sync.Reset(&cache); - } -} - -TEST(Clock, AcquireRelease) { - ThreadClock vector1(100); - vector1.tick(); - SyncClock chunked; - vector1.release(&cache, &chunked); - ASSERT_EQ(chunked.size(), 101U); - ThreadClock vector2(0); - vector2.acquire(&cache, &chunked); - ASSERT_EQ(vector2.size(), 101U); - ASSERT_EQ(vector2.get(0), 0U); - ASSERT_EQ(vector2.get(1), 0U); - ASSERT_EQ(vector2.get(99), 0U); - ASSERT_EQ(vector2.get(100), 1U); - chunked.Reset(&cache); -} - -TEST(Clock, RepeatedAcquire) { - ThreadClock thr1(1); - thr1.tick(); - ThreadClock thr2(2); - thr2.tick(); - - SyncClock sync; - thr1.ReleaseStore(&cache, &sync); - - thr2.acquire(&cache, &sync); - thr2.acquire(&cache, &sync); - - sync.Reset(&cache); -} - -TEST(Clock, ManyThreads) { - SyncClock chunked; - for (unsigned i = 0; i < 200; i++) { - ThreadClock vector(0); - vector.tick(); - vector.set(&cache, i, i + 1); - vector.release(&cache, &chunked); - ASSERT_EQ(i + 1, chunked.size()); - vector.acquire(&cache, &chunked); - ASSERT_EQ(i + 1, vector.size()); - } - - for (unsigned i = 0; i < 200; i++) { - printf("i=%d\n", i); - ASSERT_EQ(i + 1, chunked.get(i)); - } - - ThreadClock vector(1); - vector.acquire(&cache, &chunked); - ASSERT_EQ(200U, vector.size()); - for (unsigned i = 0; i < 200; i++) - ASSERT_EQ(i + 1, vector.get(i)); - - chunked.Reset(&cache); -} - -TEST(Clock, DifferentSizes) { - { - ThreadClock vector1(10); - vector1.tick(); - ThreadClock vector2(20); - vector2.tick(); - { - SyncClock chunked; - vector1.release(&cache, &chunked); - ASSERT_EQ(chunked.size(), 11U); - vector2.release(&cache, &chunked); - ASSERT_EQ(chunked.size(), 21U); - chunked.Reset(&cache); - } - { - SyncClock chunked; - vector2.release(&cache, &chunked); - ASSERT_EQ(chunked.size(), 21U); - vector1.release(&cache, &chunked); - ASSERT_EQ(chunked.size(), 21U); - chunked.Reset(&cache); - } - { - SyncClock chunked; - vector1.release(&cache, &chunked); - vector2.acquire(&cache, &chunked); - ASSERT_EQ(vector2.size(), 21U); - chunked.Reset(&cache); - } - { - SyncClock chunked; - vector2.release(&cache, &chunked); - vector1.acquire(&cache, &chunked); - ASSERT_EQ(vector1.size(), 21U); - chunked.Reset(&cache); - } - } -} - -TEST(Clock, Growth) { - { - ThreadClock vector(10); - vector.tick(); - vector.set(&cache, 5, 42); - SyncClock sync; - vector.release(&cache, &sync); - ASSERT_EQ(sync.size(), 11U); - ASSERT_EQ(sync.get(0), 0ULL); - ASSERT_EQ(sync.get(1), 0ULL); - ASSERT_EQ(sync.get(5), 42ULL); - ASSERT_EQ(sync.get(9), 0ULL); - ASSERT_EQ(sync.get(10), 1ULL); - sync.Reset(&cache); - } - { - ThreadClock vector1(10); - vector1.tick(); - ThreadClock vector2(20); - vector2.tick(); - SyncClock sync; - vector1.release(&cache, &sync); - vector2.release(&cache, &sync); - ASSERT_EQ(sync.size(), 21U); - ASSERT_EQ(sync.get(0), 0ULL); - ASSERT_EQ(sync.get(10), 1ULL); - ASSERT_EQ(sync.get(19), 0ULL); - ASSERT_EQ(sync.get(20), 1ULL); - sync.Reset(&cache); - } - { - ThreadClock vector(100); - vector.tick(); - vector.set(&cache, 5, 42); - vector.set(&cache, 90, 84); - SyncClock sync; - vector.release(&cache, &sync); - ASSERT_EQ(sync.size(), 101U); - ASSERT_EQ(sync.get(0), 0ULL); - ASSERT_EQ(sync.get(1), 0ULL); - ASSERT_EQ(sync.get(5), 42ULL); - ASSERT_EQ(sync.get(60), 0ULL); - ASSERT_EQ(sync.get(70), 0ULL); - ASSERT_EQ(sync.get(90), 84ULL); - ASSERT_EQ(sync.get(99), 0ULL); - ASSERT_EQ(sync.get(100), 1ULL); - sync.Reset(&cache); - } - { - ThreadClock vector1(10); - vector1.tick(); - ThreadClock vector2(100); - vector2.tick(); - SyncClock sync; - vector1.release(&cache, &sync); - vector2.release(&cache, &sync); - ASSERT_EQ(sync.size(), 101U); - ASSERT_EQ(sync.get(0), 0ULL); - ASSERT_EQ(sync.get(10), 1ULL); - ASSERT_EQ(sync.get(99), 0ULL); - ASSERT_EQ(sync.get(100), 1ULL); - sync.Reset(&cache); - } -} - -TEST(Clock, Growth2) { - // Test clock growth for every pair of sizes: - const uptr n = ARRAY_SIZE(interesting_sizes); - for (uptr fi = 0; fi < n; fi++) { - for (uptr ti = fi + 1; ti < n; ti++) { - const uptr from = interesting_sizes[fi]; - const uptr to = interesting_sizes[ti]; - SyncClock sync; - ThreadClock vector(0); - for (uptr i = 0; i < from; i++) - vector.set(&cache, i, i + 1); - if (from != 0) - vector.release(&cache, &sync); - ASSERT_EQ(sync.size(), from); - for (uptr i = 0; i < from; i++) - ASSERT_EQ(sync.get(i), i + 1); - for (uptr i = 0; i < to; i++) - vector.set(&cache, i, i + 1); - vector.release(&cache, &sync); - ASSERT_EQ(sync.size(), to); - for (uptr i = 0; i < to; i++) - ASSERT_EQ(sync.get(i), i + 1); - vector.set(&cache, to + 1, to + 1); - vector.release(&cache, &sync); - ASSERT_EQ(sync.size(), to + 2); - for (uptr i = 0; i < to; i++) - ASSERT_EQ(sync.get(i), i + 1); - ASSERT_EQ(sync.get(to), 0U); - ASSERT_EQ(sync.get(to + 1), to + 1); - sync.Reset(&cache); - } - } -} - -const uptr kThreads = 4; -const uptr kClocks = 4; - -// SimpleSyncClock and SimpleThreadClock implement the same thing as -// SyncClock and ThreadClock, but in a very simple way. -struct SimpleSyncClock { - u64 clock[kThreads]; - uptr size; - - SimpleSyncClock() { - Reset(); - } - - void Reset() { - size = 0; - for (uptr i = 0; i < kThreads; i++) - clock[i] = 0; - } - - bool verify(const SyncClock *other) const { - for (uptr i = 0; i < min(size, other->size()); i++) { - if (clock[i] != other->get(i)) - return false; - } - for (uptr i = min(size, other->size()); i < max(size, other->size()); i++) { - if (i < size && clock[i] != 0) - return false; - if (i < other->size() && other->get(i) != 0) - return false; - } - return true; - } -}; - -struct SimpleThreadClock { - u64 clock[kThreads]; - uptr size; - unsigned tid; - - explicit SimpleThreadClock(unsigned tid) { - this->tid = tid; - size = tid + 1; - for (uptr i = 0; i < kThreads; i++) - clock[i] = 0; - } - - void tick() { - clock[tid]++; - } - - void acquire(const SimpleSyncClock *src) { - if (size < src->size) - size = src->size; - for (uptr i = 0; i < kThreads; i++) - clock[i] = max(clock[i], src->clock[i]); - } - - void release(SimpleSyncClock *dst) const { - if (dst->size < size) - dst->size = size; - for (uptr i = 0; i < kThreads; i++) - dst->clock[i] = max(dst->clock[i], clock[i]); - } - - void acq_rel(SimpleSyncClock *dst) { - acquire(dst); - release(dst); - } - - void ReleaseStore(SimpleSyncClock *dst) const { - if (dst->size < size) - dst->size = size; - for (uptr i = 0; i < kThreads; i++) - dst->clock[i] = clock[i]; - } - - bool verify(const ThreadClock *other) const { - for (uptr i = 0; i < min(size, other->size()); i++) { - if (clock[i] != other->get(i)) - return false; - } - for (uptr i = min(size, other->size()); i < max(size, other->size()); i++) { - if (i < size && clock[i] != 0) - return false; - if (i < other->size() && other->get(i) != 0) - return false; - } - return true; - } -}; - -static bool ClockFuzzer(bool printing) { - // Create kThreads thread clocks. - SimpleThreadClock *thr0[kThreads]; - ThreadClock *thr1[kThreads]; - unsigned reused[kThreads]; - for (unsigned i = 0; i < kThreads; i++) { - reused[i] = 0; - thr0[i] = new SimpleThreadClock(i); - thr1[i] = new ThreadClock(i, reused[i]); - } - - // Create kClocks sync clocks. - SimpleSyncClock *sync0[kClocks]; - SyncClock *sync1[kClocks]; - for (unsigned i = 0; i < kClocks; i++) { - sync0[i] = new SimpleSyncClock(); - sync1[i] = new SyncClock(); - } - - // Do N random operations (acquire, release, etc) and compare results - // for SimpleThread/SyncClock and real Thread/SyncClock. - for (int i = 0; i < 10000; i++) { - unsigned tid = rand() % kThreads; - unsigned cid = rand() % kClocks; - thr0[tid]->tick(); - thr1[tid]->tick(); - - switch (rand() % 6) { - case 0: - if (printing) - printf("acquire thr%d <- clk%d\n", tid, cid); - thr0[tid]->acquire(sync0[cid]); - thr1[tid]->acquire(&cache, sync1[cid]); - break; - case 1: - if (printing) - printf("release thr%d -> clk%d\n", tid, cid); - thr0[tid]->release(sync0[cid]); - thr1[tid]->release(&cache, sync1[cid]); - break; - case 2: - if (printing) - printf("acq_rel thr%d <> clk%d\n", tid, cid); - thr0[tid]->acq_rel(sync0[cid]); - thr1[tid]->acq_rel(&cache, sync1[cid]); - break; - case 3: - if (printing) - printf("rel_str thr%d >> clk%d\n", tid, cid); - thr0[tid]->ReleaseStore(sync0[cid]); - thr1[tid]->ReleaseStore(&cache, sync1[cid]); - break; - case 4: - if (printing) - printf("reset clk%d\n", cid); - sync0[cid]->Reset(); - sync1[cid]->Reset(&cache); - break; - case 5: - if (printing) - printf("reset thr%d\n", tid); - u64 epoch = thr0[tid]->clock[tid] + 1; - reused[tid]++; - delete thr0[tid]; - thr0[tid] = new SimpleThreadClock(tid); - thr0[tid]->clock[tid] = epoch; - delete thr1[tid]; - thr1[tid] = new ThreadClock(tid, reused[tid]); - thr1[tid]->set(epoch); - break; - } - - if (printing) { - for (unsigned i = 0; i < kThreads; i++) { - printf("thr%d: ", i); - thr1[i]->DebugDump(printf); - printf("\n"); - } - for (unsigned i = 0; i < kClocks; i++) { - printf("clk%d: ", i); - sync1[i]->DebugDump(printf); - printf("\n"); - } - - printf("\n"); - } - - if (!thr0[tid]->verify(thr1[tid]) || !sync0[cid]->verify(sync1[cid])) { - if (!printing) - return false; - printf("differs with model:\n"); - for (unsigned i = 0; i < kThreads; i++) { - printf("thr%d: clock=[", i); - for (uptr j = 0; j < thr0[i]->size; j++) - printf("%s%llu", j == 0 ? "" : ",", thr0[i]->clock[j]); - printf("]\n"); - } - for (unsigned i = 0; i < kClocks; i++) { - printf("clk%d: clock=[", i); - for (uptr j = 0; j < sync0[i]->size; j++) - printf("%s%llu", j == 0 ? "" : ",", sync0[i]->clock[j]); - printf("]\n"); - } - return false; - } - } - - for (unsigned i = 0; i < kClocks; i++) { - sync1[i]->Reset(&cache); - } - return true; -} - -TEST(Clock, Fuzzer) { - struct timeval tv; - gettimeofday(&tv, NULL); - int seed = tv.tv_sec + tv.tv_usec; - printf("seed=%d\n", seed); - srand(seed); - if (!ClockFuzzer(false)) { - // Redo the test with the same seed, but logging operations. - srand(seed); - ClockFuzzer(true); - ASSERT_TRUE(false); - } -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_dense_alloc_test.cc b/lib/tsan/tests/unit/tsan_dense_alloc_test.cc deleted file mode 100644 index e848e48c6641d..0000000000000 --- a/lib/tsan/tests/unit/tsan_dense_alloc_test.cc +++ /dev/null @@ -1,55 +0,0 @@ -//===-- tsan_dense_alloc_test.cc ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_dense_alloc.h" -#include "tsan_rtl.h" -#include "tsan_mman.h" -#include "gtest/gtest.h" - -#include <stdlib.h> -#include <stdint.h> -#include <map> - -namespace __tsan { - -TEST(DenseSlabAlloc, Basic) { - typedef DenseSlabAlloc<int, 128, 128> Alloc; - typedef Alloc::Cache Cache; - typedef Alloc::IndexT IndexT; - const int N = 1000; - - Alloc alloc; - Cache cache; - alloc.InitCache(&cache); - - IndexT blocks[N]; - for (int ntry = 0; ntry < 3; ntry++) { - for (int i = 0; i < N; i++) { - IndexT idx = alloc.Alloc(&cache); - blocks[i] = idx; - EXPECT_NE(idx, 0U); - int *v = alloc.Map(idx); - *v = i; - } - - for (int i = 0; i < N; i++) { - IndexT idx = blocks[i]; - int *v = alloc.Map(idx); - EXPECT_EQ(*v, i); - alloc.Free(&cache, idx); - } - - alloc.FlushCache(&cache); - } -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_flags_test.cc b/lib/tsan/tests/unit/tsan_flags_test.cc deleted file mode 100644 index aa8a024f9dc5e..0000000000000 --- a/lib/tsan/tests/unit/tsan_flags_test.cc +++ /dev/null @@ -1,174 +0,0 @@ -//===-- tsan_flags_test.cc ------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_flags.h" -#include "tsan_rtl.h" -#include "gtest/gtest.h" -#include <string> - -namespace __tsan { - -TEST(Flags, Basic) { - // At least should not crash. - Flags f; - InitializeFlags(&f, 0); - InitializeFlags(&f, ""); -} - -TEST(Flags, DefaultValues) { - Flags f; - - f.enable_annotations = false; - InitializeFlags(&f, ""); - EXPECT_EQ(true, f.enable_annotations); -} - -static const char *options1 = - " enable_annotations=0" - " suppress_equal_stacks=0" - " suppress_equal_addresses=0" - " report_bugs=0" - " report_thread_leaks=0" - " report_destroy_locked=0" - " report_mutex_bugs=0" - " report_signal_unsafe=0" - " report_atomic_races=0" - " force_seq_cst_atomics=0" - " print_benign=0" - " halt_on_error=0" - " atexit_sleep_ms=222" - " profile_memory=qqq" - " flush_memory_ms=444" - " flush_symbolizer_ms=555" - " memory_limit_mb=666" - " stop_on_start=0" - " running_on_valgrind=0" - " history_size=5" - " io_sync=1" - " die_after_fork=true" - ""; - -static const char *options2 = - " enable_annotations=true" - " suppress_equal_stacks=true" - " suppress_equal_addresses=true" - " report_bugs=true" - " report_thread_leaks=true" - " report_destroy_locked=true" - " report_mutex_bugs=true" - " report_signal_unsafe=true" - " report_atomic_races=true" - " force_seq_cst_atomics=true" - " print_benign=true" - " halt_on_error=true" - " atexit_sleep_ms=123" - " profile_memory=bbbbb" - " flush_memory_ms=234" - " flush_symbolizer_ms=345" - " memory_limit_mb=456" - " stop_on_start=true" - " running_on_valgrind=true" - " history_size=6" - " io_sync=2" - " die_after_fork=false" - ""; - -void VerifyOptions1(Flags *f) { - EXPECT_EQ(f->enable_annotations, 0); - EXPECT_EQ(f->suppress_equal_stacks, 0); - EXPECT_EQ(f->suppress_equal_addresses, 0); - EXPECT_EQ(f->report_bugs, 0); - EXPECT_EQ(f->report_thread_leaks, 0); - EXPECT_EQ(f->report_destroy_locked, 0); - EXPECT_EQ(f->report_mutex_bugs, 0); - EXPECT_EQ(f->report_signal_unsafe, 0); - EXPECT_EQ(f->report_atomic_races, 0); - EXPECT_EQ(f->force_seq_cst_atomics, 0); - EXPECT_EQ(f->print_benign, 0); - EXPECT_EQ(f->halt_on_error, 0); - EXPECT_EQ(f->atexit_sleep_ms, 222); - EXPECT_EQ(f->profile_memory, std::string("qqq")); - EXPECT_EQ(f->flush_memory_ms, 444); - EXPECT_EQ(f->flush_symbolizer_ms, 555); - EXPECT_EQ(f->memory_limit_mb, 666); - EXPECT_EQ(f->stop_on_start, 0); - EXPECT_EQ(f->running_on_valgrind, 0); - EXPECT_EQ(f->history_size, 5); - EXPECT_EQ(f->io_sync, 1); - EXPECT_EQ(f->die_after_fork, true); -} - -void VerifyOptions2(Flags *f) { - EXPECT_EQ(f->enable_annotations, true); - EXPECT_EQ(f->suppress_equal_stacks, true); - EXPECT_EQ(f->suppress_equal_addresses, true); - EXPECT_EQ(f->report_bugs, true); - EXPECT_EQ(f->report_thread_leaks, true); - EXPECT_EQ(f->report_destroy_locked, true); - EXPECT_EQ(f->report_mutex_bugs, true); - EXPECT_EQ(f->report_signal_unsafe, true); - EXPECT_EQ(f->report_atomic_races, true); - EXPECT_EQ(f->force_seq_cst_atomics, true); - EXPECT_EQ(f->print_benign, true); - EXPECT_EQ(f->halt_on_error, true); - EXPECT_EQ(f->atexit_sleep_ms, 123); - EXPECT_EQ(f->profile_memory, std::string("bbbbb")); - EXPECT_EQ(f->flush_memory_ms, 234); - EXPECT_EQ(f->flush_symbolizer_ms, 345); - EXPECT_EQ(f->memory_limit_mb, 456); - EXPECT_EQ(f->stop_on_start, true); - EXPECT_EQ(f->running_on_valgrind, true); - EXPECT_EQ(f->history_size, 6); - EXPECT_EQ(f->io_sync, 2); - EXPECT_EQ(f->die_after_fork, false); -} - -static const char *test_default_options; -extern "C" const char *__tsan_default_options() { - return test_default_options; -} - -TEST(Flags, ParseDefaultOptions) { - Flags f; - - test_default_options = options1; - InitializeFlags(&f, ""); - VerifyOptions1(&f); - - test_default_options = options2; - InitializeFlags(&f, ""); - VerifyOptions2(&f); -} - -TEST(Flags, ParseEnvOptions) { - Flags f; - - InitializeFlags(&f, options1); - VerifyOptions1(&f); - - InitializeFlags(&f, options2); - VerifyOptions2(&f); -} - -TEST(Flags, ParsePriority) { - Flags f; - - test_default_options = options2; - InitializeFlags(&f, options1); - VerifyOptions1(&f); - - test_default_options = options1; - InitializeFlags(&f, options2); - VerifyOptions2(&f); -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_mman_test.cc b/lib/tsan/tests/unit/tsan_mman_test.cc deleted file mode 100644 index 26e13a55ce1c3..0000000000000 --- a/lib/tsan/tests/unit/tsan_mman_test.cc +++ /dev/null @@ -1,197 +0,0 @@ -//===-- tsan_mman_test.cc -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include <limits> -#include <sanitizer/allocator_interface.h> -#include "tsan_mman.h" -#include "tsan_rtl.h" -#include "gtest/gtest.h" - -namespace __tsan { - -TEST(Mman, Internal) { - char *p = (char*)internal_alloc(MBlockScopedBuf, 10); - EXPECT_NE(p, (char*)0); - char *p2 = (char*)internal_alloc(MBlockScopedBuf, 20); - EXPECT_NE(p2, (char*)0); - EXPECT_NE(p2, p); - for (int i = 0; i < 10; i++) { - p[i] = 42; - } - for (int i = 0; i < 20; i++) { - ((char*)p2)[i] = 42; - } - internal_free(p); - internal_free(p2); -} - -TEST(Mman, User) { - ThreadState *thr = cur_thread(); - uptr pc = 0; - char *p = (char*)user_alloc(thr, pc, 10); - EXPECT_NE(p, (char*)0); - char *p2 = (char*)user_alloc(thr, pc, 20); - EXPECT_NE(p2, (char*)0); - EXPECT_NE(p2, p); - EXPECT_EQ(10U, user_alloc_usable_size(p)); - EXPECT_EQ(20U, user_alloc_usable_size(p2)); - user_free(thr, pc, p); - user_free(thr, pc, p2); -} - -TEST(Mman, UserRealloc) { - ThreadState *thr = cur_thread(); - uptr pc = 0; - { - void *p = user_realloc(thr, pc, 0, 0); - // Realloc(NULL, N) is equivalent to malloc(N), thus must return - // non-NULL pointer. - EXPECT_NE(p, (void*)0); - user_free(thr, pc, p); - } - { - void *p = user_realloc(thr, pc, 0, 100); - EXPECT_NE(p, (void*)0); - memset(p, 0xde, 100); - user_free(thr, pc, p); - } - { - void *p = user_alloc(thr, pc, 100); - EXPECT_NE(p, (void*)0); - memset(p, 0xde, 100); - // Realloc(P, 0) is equivalent to free(P) and returns NULL. - void *p2 = user_realloc(thr, pc, p, 0); - EXPECT_EQ(p2, (void*)0); - } - { - void *p = user_realloc(thr, pc, 0, 100); - EXPECT_NE(p, (void*)0); - memset(p, 0xde, 100); - void *p2 = user_realloc(thr, pc, p, 10000); - EXPECT_NE(p2, (void*)0); - for (int i = 0; i < 100; i++) - EXPECT_EQ(((char*)p2)[i], (char)0xde); - memset(p2, 0xde, 10000); - user_free(thr, pc, p2); - } - { - void *p = user_realloc(thr, pc, 0, 10000); - EXPECT_NE(p, (void*)0); - memset(p, 0xde, 10000); - void *p2 = user_realloc(thr, pc, p, 10); - EXPECT_NE(p2, (void*)0); - for (int i = 0; i < 10; i++) - EXPECT_EQ(((char*)p2)[i], (char)0xde); - user_free(thr, pc, p2); - } -} - -TEST(Mman, UsableSize) { - ThreadState *thr = cur_thread(); - uptr pc = 0; - char *p = (char*)user_alloc(thr, pc, 10); - char *p2 = (char*)user_alloc(thr, pc, 20); - EXPECT_EQ(0U, user_alloc_usable_size(NULL)); - EXPECT_EQ(10U, user_alloc_usable_size(p)); - EXPECT_EQ(20U, user_alloc_usable_size(p2)); - user_free(thr, pc, p); - user_free(thr, pc, p2); - EXPECT_EQ(0U, user_alloc_usable_size((void*)0x4123)); -} - -TEST(Mman, Stats) { - ThreadState *thr = cur_thread(); - - uptr alloc0 = __sanitizer_get_current_allocated_bytes(); - uptr heap0 = __sanitizer_get_heap_size(); - uptr free0 = __sanitizer_get_free_bytes(); - uptr unmapped0 = __sanitizer_get_unmapped_bytes(); - - EXPECT_EQ(10U, __sanitizer_get_estimated_allocated_size(10)); - EXPECT_EQ(20U, __sanitizer_get_estimated_allocated_size(20)); - EXPECT_EQ(100U, __sanitizer_get_estimated_allocated_size(100)); - - char *p = (char*)user_alloc(thr, 0, 10); - EXPECT_TRUE(__sanitizer_get_ownership(p)); - EXPECT_EQ(10U, __sanitizer_get_allocated_size(p)); - - EXPECT_EQ(alloc0 + 16, __sanitizer_get_current_allocated_bytes()); - EXPECT_GE(__sanitizer_get_heap_size(), heap0); - EXPECT_EQ(free0, __sanitizer_get_free_bytes()); - EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes()); - - user_free(thr, 0, p); - - EXPECT_EQ(alloc0, __sanitizer_get_current_allocated_bytes()); - EXPECT_GE(__sanitizer_get_heap_size(), heap0); - EXPECT_EQ(free0, __sanitizer_get_free_bytes()); - EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes()); -} - -TEST(Mman, Valloc) { - ThreadState *thr = cur_thread(); - uptr page_size = GetPageSizeCached(); - - void *p = user_valloc(thr, 0, 100); - EXPECT_NE(p, (void*)0); - user_free(thr, 0, p); - - p = user_pvalloc(thr, 0, 100); - EXPECT_NE(p, (void*)0); - user_free(thr, 0, p); - - p = user_pvalloc(thr, 0, 0); - EXPECT_NE(p, (void*)0); - EXPECT_EQ(page_size, __sanitizer_get_allocated_size(p)); - user_free(thr, 0, p); -} - -#if !SANITIZER_DEBUG -// EXPECT_DEATH clones a thread with 4K stack, -// which is overflown by tsan memory accesses functions in debug mode. - -TEST(Mman, Memalign) { - ThreadState *thr = cur_thread(); - - void *p = user_memalign(thr, 0, 8, 100); - EXPECT_NE(p, (void*)0); - user_free(thr, 0, p); - - // TODO(alekseyshl): Remove this death test when memalign is verified by - // tests in sanitizer_common. - p = NULL; - EXPECT_DEATH(p = user_memalign(thr, 0, 7, 100), - "invalid-allocation-alignment"); - EXPECT_EQ(0L, p); -} - -#endif - -TEST(Mman, PosixMemalign) { - ThreadState *thr = cur_thread(); - - void *p = NULL; - int res = user_posix_memalign(thr, 0, &p, 8, 100); - EXPECT_NE(p, (void*)0); - EXPECT_EQ(res, 0); - user_free(thr, 0, p); -} - -TEST(Mman, AlignedAlloc) { - ThreadState *thr = cur_thread(); - - void *p = user_aligned_alloc(thr, 0, 8, 64); - EXPECT_NE(p, (void*)0); - user_free(thr, 0, p); -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_mutex_test.cc b/lib/tsan/tests/unit/tsan_mutex_test.cc deleted file mode 100644 index cce7f073b92fc..0000000000000 --- a/lib/tsan/tests/unit/tsan_mutex_test.cc +++ /dev/null @@ -1,126 +0,0 @@ -//===-- tsan_mutex_test.cc ------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "sanitizer_common/sanitizer_internal_defs.h" -#include "sanitizer_common/sanitizer_atomic.h" -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_mutex.h" -#include "tsan_mutex.h" -#include "gtest/gtest.h" - -namespace __tsan { - -template<typename MutexType> -class TestData { - public: - explicit TestData(MutexType *mtx) - : mtx_(mtx) { - for (int i = 0; i < kSize; i++) - data_[i] = 0; - } - - void Write() { - Lock l(mtx_); - T v0 = data_[0]; - for (int i = 0; i < kSize; i++) { - CHECK_EQ(data_[i], v0); - data_[i]++; - } - } - - void Read() { - ReadLock l(mtx_); - T v0 = data_[0]; - for (int i = 0; i < kSize; i++) { - CHECK_EQ(data_[i], v0); - } - } - - void Backoff() { - volatile T data[kSize] = {}; - for (int i = 0; i < kSize; i++) { - data[i]++; - CHECK_EQ(data[i], 1); - } - } - - private: - typedef GenericScopedLock<MutexType> Lock; - static const int kSize = 64; - typedef u64 T; - MutexType *mtx_; - char pad_[kCacheLineSize]; - T data_[kSize]; -}; - -const int kThreads = 8; -const int kWriteRate = 1024; -#if SANITIZER_DEBUG -const int kIters = 16*1024; -#else -const int kIters = 64*1024; -#endif - -template<typename MutexType> -static void *write_mutex_thread(void *param) { - TestData<MutexType> *data = (TestData<MutexType>*)param; - for (int i = 0; i < kIters; i++) { - data->Write(); - data->Backoff(); - } - return 0; -} - -template<typename MutexType> -static void *read_mutex_thread(void *param) { - TestData<MutexType> *data = (TestData<MutexType>*)param; - for (int i = 0; i < kIters; i++) { - if ((i % kWriteRate) == 0) - data->Write(); - else - data->Read(); - data->Backoff(); - } - return 0; -} - -TEST(Mutex, Write) { - Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); - TestData<Mutex> data(&mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - pthread_create(&threads[i], 0, write_mutex_thread<Mutex>, &data); - for (int i = 0; i < kThreads; i++) - pthread_join(threads[i], 0); -} - -TEST(Mutex, ReadWrite) { - Mutex mtx(MutexTypeAnnotations, StatMtxAnnotations); - TestData<Mutex> data(&mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - pthread_create(&threads[i], 0, read_mutex_thread<Mutex>, &data); - for (int i = 0; i < kThreads; i++) - pthread_join(threads[i], 0); -} - -TEST(Mutex, SpinWrite) { - SpinMutex mtx; - TestData<SpinMutex> data(&mtx); - pthread_t threads[kThreads]; - for (int i = 0; i < kThreads; i++) - pthread_create(&threads[i], 0, write_mutex_thread<SpinMutex>, &data); - for (int i = 0; i < kThreads; i++) - pthread_join(threads[i], 0); -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_mutexset_test.cc b/lib/tsan/tests/unit/tsan_mutexset_test.cc deleted file mode 100644 index 335a7748cc1a9..0000000000000 --- a/lib/tsan/tests/unit/tsan_mutexset_test.cc +++ /dev/null @@ -1,127 +0,0 @@ -//===-- tsan_mutexset_test.cc ---------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_mutexset.h" -#include "gtest/gtest.h" - -namespace __tsan { - -static void Expect(const MutexSet &mset, uptr i, u64 id, bool write, u64 epoch, - int count) { - MutexSet::Desc d = mset.Get(i); - EXPECT_EQ(id, d.id); - EXPECT_EQ(write, d.write); - EXPECT_EQ(epoch, d.epoch); - EXPECT_EQ(count, d.count); -} - -TEST(MutexSet, Basic) { - MutexSet mset; - EXPECT_EQ(mset.Size(), (uptr)0); - - mset.Add(1, true, 2); - EXPECT_EQ(mset.Size(), (uptr)1); - Expect(mset, 0, 1, true, 2, 1); - mset.Del(1, true); - EXPECT_EQ(mset.Size(), (uptr)0); - - mset.Add(3, true, 4); - mset.Add(5, false, 6); - EXPECT_EQ(mset.Size(), (uptr)2); - Expect(mset, 0, 3, true, 4, 1); - Expect(mset, 1, 5, false, 6, 1); - mset.Del(3, true); - EXPECT_EQ(mset.Size(), (uptr)1); - mset.Del(5, false); - EXPECT_EQ(mset.Size(), (uptr)0); -} - -TEST(MutexSet, DoubleAdd) { - MutexSet mset; - mset.Add(1, true, 2); - EXPECT_EQ(mset.Size(), (uptr)1); - Expect(mset, 0, 1, true, 2, 1); - - mset.Add(1, true, 2); - EXPECT_EQ(mset.Size(), (uptr)1); - Expect(mset, 0, 1, true, 2, 2); - - mset.Del(1, true); - EXPECT_EQ(mset.Size(), (uptr)1); - Expect(mset, 0, 1, true, 2, 1); - - mset.Del(1, true); - EXPECT_EQ(mset.Size(), (uptr)0); -} - -TEST(MutexSet, DoubleDel) { - MutexSet mset; - mset.Add(1, true, 2); - EXPECT_EQ(mset.Size(), (uptr)1); - mset.Del(1, true); - EXPECT_EQ(mset.Size(), (uptr)0); - mset.Del(1, true); - EXPECT_EQ(mset.Size(), (uptr)0); -} - -TEST(MutexSet, Remove) { - MutexSet mset; - mset.Add(1, true, 2); - mset.Add(1, true, 2); - mset.Add(3, true, 4); - mset.Add(3, true, 4); - EXPECT_EQ(mset.Size(), (uptr)2); - - mset.Remove(1); - EXPECT_EQ(mset.Size(), (uptr)1); - Expect(mset, 0, 3, true, 4, 2); -} - -TEST(MutexSet, Full) { - MutexSet mset; - for (uptr i = 0; i < MutexSet::kMaxSize; i++) { - mset.Add(i, true, i + 1); - } - EXPECT_EQ(mset.Size(), MutexSet::kMaxSize); - for (uptr i = 0; i < MutexSet::kMaxSize; i++) { - Expect(mset, i, i, true, i + 1, 1); - } - - for (uptr i = 0; i < MutexSet::kMaxSize; i++) { - mset.Add(i, true, i + 1); - } - EXPECT_EQ(mset.Size(), MutexSet::kMaxSize); - for (uptr i = 0; i < MutexSet::kMaxSize; i++) { - Expect(mset, i, i, true, i + 1, 2); - } -} - -TEST(MutexSet, Overflow) { - MutexSet mset; - for (uptr i = 0; i < MutexSet::kMaxSize; i++) { - mset.Add(i, true, i + 1); - mset.Add(i, true, i + 1); - } - mset.Add(100, true, 200); - EXPECT_EQ(mset.Size(), MutexSet::kMaxSize); - for (uptr i = 0; i < MutexSet::kMaxSize; i++) { - if (i == 0) - Expect(mset, i, MutexSet::kMaxSize - 1, - true, MutexSet::kMaxSize, 2); - else if (i == MutexSet::kMaxSize - 1) - Expect(mset, i, 100, true, 200, 1); - else - Expect(mset, i, i, true, i + 1, 2); - } -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_shadow_test.cc b/lib/tsan/tests/unit/tsan_shadow_test.cc deleted file mode 100644 index 17b17977bf86b..0000000000000 --- a/lib/tsan/tests/unit/tsan_shadow_test.cc +++ /dev/null @@ -1,78 +0,0 @@ -//===-- tsan_shadow_test.cc -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_platform.h" -#include "tsan_rtl.h" -#include "gtest/gtest.h" - -namespace __tsan { - -TEST(Shadow, FastState) { - Shadow s(FastState(11, 22)); - EXPECT_EQ(s.tid(), (u64)11); - EXPECT_EQ(s.epoch(), (u64)22); - EXPECT_EQ(s.GetIgnoreBit(), false); - EXPECT_EQ(s.GetFreedAndReset(), false); - EXPECT_EQ(s.GetHistorySize(), 0); - EXPECT_EQ(s.addr0(), (u64)0); - EXPECT_EQ(s.size(), (u64)1); - EXPECT_EQ(s.IsWrite(), true); - - s.IncrementEpoch(); - EXPECT_EQ(s.epoch(), (u64)23); - s.IncrementEpoch(); - EXPECT_EQ(s.epoch(), (u64)24); - - s.SetIgnoreBit(); - EXPECT_EQ(s.GetIgnoreBit(), true); - s.ClearIgnoreBit(); - EXPECT_EQ(s.GetIgnoreBit(), false); - - for (int i = 0; i < 8; i++) { - s.SetHistorySize(i); - EXPECT_EQ(s.GetHistorySize(), i); - } - s.SetHistorySize(2); - s.ClearHistorySize(); - EXPECT_EQ(s.GetHistorySize(), 0); -} - -TEST(Shadow, Mapping) { - static int global; - int stack; - void *heap = malloc(0); - free(heap); - - CHECK(IsAppMem((uptr)&global)); - CHECK(IsAppMem((uptr)&stack)); - CHECK(IsAppMem((uptr)heap)); - - CHECK(IsShadowMem(MemToShadow((uptr)&global))); - CHECK(IsShadowMem(MemToShadow((uptr)&stack))); - CHECK(IsShadowMem(MemToShadow((uptr)heap))); -} - -TEST(Shadow, Celling) { - u64 aligned_data[4]; - char *data = (char*)aligned_data; - CHECK_EQ((uptr)data % kShadowSize, 0); - uptr s0 = MemToShadow((uptr)&data[0]); - CHECK_EQ(s0 % kShadowSize, 0); - for (unsigned i = 1; i < kShadowCell; i++) - CHECK_EQ(s0, MemToShadow((uptr)&data[i])); - for (unsigned i = kShadowCell; i < 2*kShadowCell; i++) - CHECK_EQ(s0 + kShadowSize*kShadowCnt, MemToShadow((uptr)&data[i])); - for (unsigned i = 2*kShadowCell; i < 3*kShadowCell; i++) - CHECK_EQ(s0 + 2*kShadowSize*kShadowCnt, MemToShadow((uptr)&data[i])); -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_stack_test.cc b/lib/tsan/tests/unit/tsan_stack_test.cc deleted file mode 100644 index 92e035d8d0004..0000000000000 --- a/lib/tsan/tests/unit/tsan_stack_test.cc +++ /dev/null @@ -1,95 +0,0 @@ -//===-- tsan_stack_test.cc ------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_sync.h" -#include "tsan_rtl.h" -#include "gtest/gtest.h" -#include <string.h> - -namespace __tsan { - -template <typename StackTraceTy> -static void TestStackTrace(StackTraceTy *trace) { - ThreadState thr(0, 0, 0, 0, 0, 0, 0, 0, 0); - uptr stack[128]; - thr.shadow_stack = &stack[0]; - thr.shadow_stack_pos = &stack[0]; - thr.shadow_stack_end = &stack[128]; - - ObtainCurrentStack(&thr, 0, trace); - EXPECT_EQ(0U, trace->size); - - ObtainCurrentStack(&thr, 42, trace); - EXPECT_EQ(1U, trace->size); - EXPECT_EQ(42U, trace->trace[0]); - - *thr.shadow_stack_pos++ = 100; - *thr.shadow_stack_pos++ = 101; - ObtainCurrentStack(&thr, 0, trace); - EXPECT_EQ(2U, trace->size); - EXPECT_EQ(100U, trace->trace[0]); - EXPECT_EQ(101U, trace->trace[1]); - - ObtainCurrentStack(&thr, 42, trace); - EXPECT_EQ(3U, trace->size); - EXPECT_EQ(100U, trace->trace[0]); - EXPECT_EQ(101U, trace->trace[1]); - EXPECT_EQ(42U, trace->trace[2]); -} - -template<typename StackTraceTy> -static void TestTrim(StackTraceTy *trace) { - ThreadState thr(0, 0, 0, 0, 0, 0, 0, 0, 0); - const uptr kShadowStackSize = 2 * kStackTraceMax; - uptr stack[kShadowStackSize]; - thr.shadow_stack = &stack[0]; - thr.shadow_stack_pos = &stack[0]; - thr.shadow_stack_end = &stack[kShadowStackSize]; - - for (uptr i = 0; i < kShadowStackSize; ++i) - *thr.shadow_stack_pos++ = 100 + i; - - ObtainCurrentStack(&thr, 0, trace); - EXPECT_EQ(kStackTraceMax, trace->size); - for (uptr i = 0; i < kStackTraceMax; i++) { - EXPECT_EQ(100 + kStackTraceMax + i, trace->trace[i]); - } - - ObtainCurrentStack(&thr, 42, trace); - EXPECT_EQ(kStackTraceMax, trace->size); - for (uptr i = 0; i < kStackTraceMax - 1; i++) { - EXPECT_EQ(101 + kStackTraceMax + i, trace->trace[i]); - } - EXPECT_EQ(42U, trace->trace[kStackTraceMax - 1]); -} - -TEST(StackTrace, BasicVarSize) { - VarSizeStackTrace trace; - TestStackTrace(&trace); -} - -TEST(StackTrace, BasicBuffered) { - BufferedStackTrace trace; - TestStackTrace(&trace); -} - -TEST(StackTrace, TrimVarSize) { - VarSizeStackTrace trace; - TestTrim(&trace); -} - -TEST(StackTrace, TrimBuffered) { - BufferedStackTrace trace; - TestTrim(&trace); -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_sync_test.cc b/lib/tsan/tests/unit/tsan_sync_test.cc deleted file mode 100644 index 8016654787870..0000000000000 --- a/lib/tsan/tests/unit/tsan_sync_test.cc +++ /dev/null @@ -1,123 +0,0 @@ -//===-- tsan_sync_test.cc -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "tsan_sync.h" -#include "tsan_rtl.h" -#include "gtest/gtest.h" - -namespace __tsan { - -TEST(MetaMap, Basic) { - ThreadState *thr = cur_thread(); - MetaMap *m = &ctx->metamap; - u64 block[1] = {}; // fake malloc block - m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64)); - MBlock *mb = m->GetBlock((uptr)&block[0]); - EXPECT_NE(mb, (MBlock*)0); - EXPECT_EQ(mb->siz, 1 * sizeof(u64)); - EXPECT_EQ(mb->tid, thr->tid); - uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0]); - EXPECT_EQ(sz, 1 * sizeof(u64)); - mb = m->GetBlock((uptr)&block[0]); - EXPECT_EQ(mb, (MBlock*)0); -} - -TEST(MetaMap, FreeRange) { - ThreadState *thr = cur_thread(); - MetaMap *m = &ctx->metamap; - u64 block[4] = {}; // fake malloc block - m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64)); - m->AllocBlock(thr, 0, (uptr)&block[1], 3 * sizeof(u64)); - MBlock *mb1 = m->GetBlock((uptr)&block[0]); - EXPECT_EQ(mb1->siz, 1 * sizeof(u64)); - MBlock *mb2 = m->GetBlock((uptr)&block[1]); - EXPECT_EQ(mb2->siz, 3 * sizeof(u64)); - m->FreeRange(thr->proc(), (uptr)&block[0], 4 * sizeof(u64)); - mb1 = m->GetBlock((uptr)&block[0]); - EXPECT_EQ(mb1, (MBlock*)0); - mb2 = m->GetBlock((uptr)&block[1]); - EXPECT_EQ(mb2, (MBlock*)0); -} - -TEST(MetaMap, Sync) { - ThreadState *thr = cur_thread(); - MetaMap *m = &ctx->metamap; - u64 block[4] = {}; // fake malloc block - m->AllocBlock(thr, 0, (uptr)&block[0], 4 * sizeof(u64)); - SyncVar *s1 = m->GetIfExistsAndLock((uptr)&block[0], true); - EXPECT_EQ(s1, (SyncVar*)0); - s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true); - EXPECT_NE(s1, (SyncVar*)0); - EXPECT_EQ(s1->addr, (uptr)&block[0]); - s1->mtx.Unlock(); - SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block[1], false); - EXPECT_NE(s2, (SyncVar*)0); - EXPECT_EQ(s2->addr, (uptr)&block[1]); - s2->mtx.ReadUnlock(); - m->FreeBlock(thr->proc(), (uptr)&block[0]); - s1 = m->GetIfExistsAndLock((uptr)&block[0], true); - EXPECT_EQ(s1, (SyncVar*)0); - s2 = m->GetIfExistsAndLock((uptr)&block[1], true); - EXPECT_EQ(s2, (SyncVar*)0); - m->OnProcIdle(thr->proc()); -} - -TEST(MetaMap, MoveMemory) { - ThreadState *thr = cur_thread(); - MetaMap *m = &ctx->metamap; - u64 block1[4] = {}; // fake malloc block - u64 block2[4] = {}; // fake malloc block - m->AllocBlock(thr, 0, (uptr)&block1[0], 3 * sizeof(u64)); - m->AllocBlock(thr, 0, (uptr)&block1[3], 1 * sizeof(u64)); - SyncVar *s1 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[0], true); - s1->mtx.Unlock(); - SyncVar *s2 = m->GetOrCreateAndLock(thr, 0, (uptr)&block1[1], true); - s2->mtx.Unlock(); - m->MoveMemory((uptr)&block1[0], (uptr)&block2[0], 4 * sizeof(u64)); - MBlock *mb1 = m->GetBlock((uptr)&block1[0]); - EXPECT_EQ(mb1, (MBlock*)0); - MBlock *mb2 = m->GetBlock((uptr)&block1[3]); - EXPECT_EQ(mb2, (MBlock*)0); - mb1 = m->GetBlock((uptr)&block2[0]); - EXPECT_NE(mb1, (MBlock*)0); - EXPECT_EQ(mb1->siz, 3 * sizeof(u64)); - mb2 = m->GetBlock((uptr)&block2[3]); - EXPECT_NE(mb2, (MBlock*)0); - EXPECT_EQ(mb2->siz, 1 * sizeof(u64)); - s1 = m->GetIfExistsAndLock((uptr)&block1[0], true); - EXPECT_EQ(s1, (SyncVar*)0); - s2 = m->GetIfExistsAndLock((uptr)&block1[1], true); - EXPECT_EQ(s2, (SyncVar*)0); - s1 = m->GetIfExistsAndLock((uptr)&block2[0], true); - EXPECT_NE(s1, (SyncVar*)0); - EXPECT_EQ(s1->addr, (uptr)&block2[0]); - s1->mtx.Unlock(); - s2 = m->GetIfExistsAndLock((uptr)&block2[1], true); - EXPECT_NE(s2, (SyncVar*)0); - EXPECT_EQ(s2->addr, (uptr)&block2[1]); - s2->mtx.Unlock(); - m->FreeRange(thr->proc(), (uptr)&block2[0], 4 * sizeof(u64)); -} - -TEST(MetaMap, ResetSync) { - ThreadState *thr = cur_thread(); - MetaMap *m = &ctx->metamap; - u64 block[1] = {}; // fake malloc block - m->AllocBlock(thr, 0, (uptr)&block[0], 1 * sizeof(u64)); - SyncVar *s = m->GetOrCreateAndLock(thr, 0, (uptr)&block[0], true); - s->Reset(thr->proc()); - s->mtx.Unlock(); - uptr sz = m->FreeBlock(thr->proc(), (uptr)&block[0]); - EXPECT_EQ(sz, 1 * sizeof(u64)); -} - -} // namespace __tsan diff --git a/lib/tsan/tests/unit/tsan_unit_test_main.cc b/lib/tsan/tests/unit/tsan_unit_test_main.cc deleted file mode 100644 index 2d55747a0257f..0000000000000 --- a/lib/tsan/tests/unit/tsan_unit_test_main.cc +++ /dev/null @@ -1,25 +0,0 @@ -//===-- tsan_unit_test_main.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of ThreadSanitizer (TSan), a race detector. -// -//===----------------------------------------------------------------------===// -#include "gtest/gtest.h" - -namespace __sanitizer { -bool ReexecDisabled() { - return true; -} -} - -int main(int argc, char **argv) { - testing::GTEST_FLAG(death_test_style) = "threadsafe"; - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/lib/ubsan/CMakeLists.txt b/lib/ubsan/CMakeLists.txt deleted file mode 100644 index ab118ae4a5216..0000000000000 --- a/lib/ubsan/CMakeLists.txt +++ /dev/null @@ -1,227 +0,0 @@ -# Build for the undefined behavior sanitizer runtime support library. - -set(UBSAN_SOURCES - ubsan_diag.cc - ubsan_init.cc - ubsan_flags.cc - ubsan_handlers.cc - ubsan_monitor.cc - ubsan_value.cc) - -set(UBSAN_STANDALONE_SOURCES - ubsan_diag_standalone.cc - ubsan_init_standalone.cc - ubsan_signals_standalone.cc) - -set(UBSAN_CXXABI_SOURCES - ubsan_handlers_cxx.cc - ubsan_type_hash.cc - ubsan_type_hash_itanium.cc - ubsan_type_hash_win.cc) - -set(UBSAN_HEADERS - ubsan_checks.inc - ubsan_diag.h - ubsan_flags.h - ubsan_flags.inc - ubsan_handlers.h - ubsan_handlers_cxx.h - ubsan_init.h - ubsan_interface.inc - ubsan_monitor.h - ubsan_platform.h - ubsan_signals_standalone.h - ubsan_type_hash.h - ubsan_value.h -) - -include_directories(..) - -set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF UBSAN_CFLAGS) -append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CFLAGS) - -set(UBSAN_STANDALONE_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF UBSAN_STANDALONE_CFLAGS) -append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_STANDALONE_CFLAGS) - -set(UBSAN_CXXFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(ON UBSAN_CXXFLAGS) -append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CXXFLAGS) - -set(UBSAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARY} ${SANITIZER_COMMON_LINK_LIBS}) - -append_list_if(COMPILER_RT_HAS_LIBDL dl UBSAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBLOG log UBSAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBRT rt UBSAN_DYNAMIC_LIBS) -append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread UBSAN_DYNAMIC_LIBS) - -add_compiler_rt_component(ubsan) - -if(APPLE) - set(UBSAN_COMMON_SOURCES ${UBSAN_SOURCES}) - if(SANITIZER_CAN_USE_CXXABI) - list(APPEND UBSAN_COMMON_SOURCES ${UBSAN_CXXABI_SOURCES}) - endif() - - # Common parts of UBSan runtime. - add_compiler_rt_object_libraries(RTUbsan - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_COMMON_SUPPORTED_ARCH} - SOURCES ${UBSAN_COMMON_SOURCES} - ADDITIONAL_HEADERS ${UBSAN_HEADERS} - CFLAGS ${UBSAN_CXXFLAGS}) - - if(COMPILER_RT_HAS_UBSAN) - # Initializer of standalone UBSan runtime. - add_compiler_rt_object_libraries(RTUbsan_standalone - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_SUPPORTED_ARCH} - SOURCES ${UBSAN_STANDALONE_SOURCES} - ADDITIONAL_HEADERS ${UBSAN_HEADERS} - CFLAGS ${UBSAN_STANDALONE_CFLAGS}) - - add_weak_symbols("ubsan" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) - - add_compiler_rt_runtime(clang_rt.ubsan - SHARED - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_SUPPORTED_ARCH} - OBJECT_LIBS RTUbsan - RTUbsan_standalone - RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTInterception - LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS} - PARENT_TARGET ubsan) - - add_compiler_rt_runtime(clang_rt.ubsan - STATIC - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_SUPPORTED_ARCH} - OBJECT_LIBS RTUbsan - RTUbsan_standalone - RTSanitizerCommonNoHooks - RTSanitizerCommonLibcNoHooks - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizerNoHooks - RTInterception - LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS} - PARENT_TARGET ubsan) - endif() - -else() - # Common parts of UBSan runtime. - add_compiler_rt_object_libraries(RTUbsan - ARCHS ${UBSAN_COMMON_SUPPORTED_ARCH} - SOURCES ${UBSAN_SOURCES} - ADDITIONAL_HEADERS ${UBSAN_HEADERS} - CFLAGS ${UBSAN_CFLAGS}) - - if(SANITIZER_CAN_USE_CXXABI) - # C++-specific parts of UBSan runtime. Requires a C++ ABI library. - set(UBSAN_CXX_SOURCES ${UBSAN_CXXABI_SOURCES}) - else() - # Dummy target if we don't have C++ ABI library. - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cxx_dummy.cc "") - set(UBSAN_CXX_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/cxx_dummy.cc) - endif() - - add_compiler_rt_object_libraries(RTUbsan_cxx - ARCHS ${UBSAN_COMMON_SUPPORTED_ARCH} - SOURCES ${UBSAN_CXX_SOURCES} - ADDITIONAL_HEADERS ${UBSAN_HEADERS} - CFLAGS ${UBSAN_CXXFLAGS}) - - if (WIN32) - add_compiler_rt_object_libraries(UbsanWeakInterception - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_SUPPORTED_ARCH} - SOURCES ubsan_win_weak_interception.cc - CFLAGS ${UBSAN_CFLAGS} -DSANITIZER_DYNAMIC - DEFS ${UBSAN_COMMON_DEFINITIONS}) - - add_compiler_rt_object_libraries(UbsanDllThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_SUPPORTED_ARCH} - SOURCES ubsan_win_dll_thunk.cc - CFLAGS ${UBSAN_CFLAGS} -DSANITIZER_DLL_THUNK - DEFS ${UBSAN_COMMON_DEFINITIONS}) - - set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK") - if(MSVC) - list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl") - elseif(CMAKE_C_COMPILER_ID MATCHES Clang) - list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs") - endif() - add_compiler_rt_object_libraries(UbsanDynamicRuntimeThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_SUPPORTED_ARCH} - SOURCES ubsan_win_dynamic_runtime_thunk.cc - CFLAGS ${UBSAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} - DEFS ${UBSAN_COMMON_DEFINITIONS}) - endif() - - if(COMPILER_RT_HAS_UBSAN) - add_compiler_rt_object_libraries(RTUbsan_standalone - ARCHS ${UBSAN_SUPPORTED_ARCH} - SOURCES ${UBSAN_STANDALONE_SOURCES} - ADDITIONAL_HEADERS ${UBSAN_HEADERS} - CFLAGS ${UBSAN_STANDALONE_CFLAGS}) - - # Standalone UBSan runtimes. - add_compiler_rt_runtime(clang_rt.ubsan_standalone - STATIC - ARCHS ${UBSAN_SUPPORTED_ARCH} - SOURCES ubsan_init_standalone_preinit.cc - ADDITIONAL_HEADERS ${UBSAN_HEADERS} - OBJECT_LIBS RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTUbsan - RTUbsan_standalone - RTInterception - CFLAGS ${UBSAN_CFLAGS} - PARENT_TARGET ubsan) - - add_compiler_rt_runtime(clang_rt.ubsan_standalone_cxx - STATIC - ARCHS ${UBSAN_SUPPORTED_ARCH} - OBJECT_LIBS RTUbsan_cxx - CFLAGS ${UBSAN_CXXFLAGS} - PARENT_TARGET ubsan) - - if (FUCHSIA OR UNIX) - add_compiler_rt_runtime(clang_rt.ubsan_standalone - SHARED - ARCHS ${UBSAN_SUPPORTED_ARCH} - OBJECT_LIBS RTSanitizerCommon - RTSanitizerCommonLibc - RTSanitizerCommonCoverage - RTSanitizerCommonSymbolizer - RTUbsan - RTUbsan_cxx - RTUbsan_standalone - RTInterception - CFLAGS ${UBSAN_CFLAGS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} - LINK_LIBS ${UBSAN_DYNAMIC_LIBS} - PARENT_TARGET ubsan) - - set(ARCHS_FOR_SYMBOLS ${UBSAN_SUPPORTED_ARCH}) - list(REMOVE_ITEM ARCHS_FOR_SYMBOLS i386) - add_sanitizer_rt_symbols(clang_rt.ubsan_standalone - ARCHS ${ARCHS_FOR_SYMBOLS} - PARENT_TARGET ubsan - EXTRA ubsan.syms.extra) - add_sanitizer_rt_symbols(clang_rt.ubsan_standalone_cxx - ARCHS ${ARCHS_FOR_SYMBOLS} - PARENT_TARGET ubsan - EXTRA ubsan.syms.extra) - endif() - endif() -endif() diff --git a/lib/ubsan_minimal/CMakeLists.txt b/lib/ubsan_minimal/CMakeLists.txt deleted file mode 100644 index e0910e80f97e3..0000000000000 --- a/lib/ubsan_minimal/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ -# Build for the minimal undefined behavior sanitizer runtime support library. - -set(UBSAN_MINIMAL_SOURCES - ubsan_minimal_handlers.cc - ) - -include_directories(..) - -set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_rtti_flag(OFF UBSAN_CFLAGS) - -set(UBSAN_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) - -set(UBSAN_DYNAMIC_LIBS ${SANITIZER_COMMON_LINK_LIBS}) - -add_compiler_rt_component(ubsan-minimal) - -# Common parts of minimal UBSan runtime. -add_compiler_rt_object_libraries(RTUbsan_minimal - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_COMMON_SUPPORTED_ARCH} - SOURCES ${UBSAN_MINIMAL_SOURCES} CFLAGS ${UBSAN_CFLAGS}) - - -if(COMPILER_RT_HAS_UBSAN_MINIMAL) - # Standalone minimal UBSan runtimes. - add_compiler_rt_runtime(clang_rt.ubsan_minimal - STATIC - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_SUPPORTED_ARCH} - OBJECT_LIBS RTUbsan_minimal - CFLAGS ${UBSAN_CFLAGS} - PARENT_TARGET ubsan-minimal) - - add_compiler_rt_runtime(clang_rt.ubsan_minimal - SHARED - OS ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${UBSAN_SUPPORTED_ARCH} - OBJECT_LIBS RTUbsan_minimal - CFLAGS ${UBSAN_CFLAGS} - LINK_FLAGS ${UBSAN_LINK_FLAGS} - LINK_LIBS ${UBSAN_DYNAMIC_LIBS} - PARENT_TARGET ubsan-minimal) - - if (SANITIZER_USE_SYMBOLS AND NOT APPLE) - set(ARCHS_FOR_SYMBOLS ${UBSAN_SUPPORTED_ARCH}) - list(REMOVE_ITEM ARCHS_FOR_SYMBOLS i386 i686) - add_sanitizer_rt_symbols(clang_rt.ubsan_minimal - ARCHS ${ARCHS_FOR_SYMBOLS} - PARENT_TARGET ubsan-minimal - EXTRA ubsan.syms.extra) - endif() -endif() diff --git a/lib/xray/CMakeLists.txt b/lib/xray/CMakeLists.txt deleted file mode 100644 index 0a86c52e62089..0000000000000 --- a/lib/xray/CMakeLists.txt +++ /dev/null @@ -1,296 +0,0 @@ -# Build for all components of the XRay runtime support library. - -# XRay runtime library implementation files. -set(XRAY_SOURCES - xray_buffer_queue.cc - xray_init.cc - xray_flags.cc - xray_interface.cc - xray_log_interface.cc - xray_utils.cc) - -# Implementation files for all XRay modes. -set(XRAY_FDR_MODE_SOURCES - xray_fdr_flags.cc - xray_fdr_logging.cc) - -set(XRAY_BASIC_MODE_SOURCES - xray_basic_flags.cc - xray_basic_logging.cc) - -set(XRAY_PROFILING_MODE_SOURCES - xray_profile_collector.cc - xray_profiling.cc - xray_profiling_flags.cc) - -# Implementation files for all XRay architectures. -set(x86_64_SOURCES - xray_x86_64.cc - xray_trampoline_x86_64.S) - -set(arm_SOURCES - xray_arm.cc - xray_trampoline_arm.S) - -set(armhf_SOURCES - ${arm_SOURCES}) - -set(aarch64_SOURCES - xray_AArch64.cc - xray_trampoline_AArch64.S) - -set(mips_SOURCES - xray_mips.cc - xray_trampoline_mips.S) - -set(mipsel_SOURCES - xray_mips.cc - xray_trampoline_mips.S) - -set(mips64_SOURCES - xray_mips64.cc - xray_trampoline_mips64.S) - -set(mips64el_SOURCES - xray_mips64.cc - xray_trampoline_mips64.S) - -set(powerpc64le_SOURCES - xray_powerpc64.cc - xray_trampoline_powerpc64.cc - xray_trampoline_powerpc64_asm.S) - -set(XRAY_IMPL_HEADERS - xray_allocator.h - xray_basic_flags.h - xray_basic_flags.inc - xray_basic_logging.h - xray_buffer_queue.h - xray_defs.h - xray_fdr_controller.h - xray_fdr_flags.h - xray_fdr_flags.inc - xray_fdr_log_records.h - xray_fdr_log_writer.h - xray_fdr_logging.h - xray_flags.h - xray_flags.inc - xray_function_call_trie.h - xray_interface_internal.h - xray_powerpc64.inc - xray_profile_collector.h - xray_profiling_flags.h - xray_profiling_flags.inc - xray_recursion_guard.h - xray_segmented_array.h - xray_tsc.h - xray_utils.h - xray_x86_64.inc) - -# Create list of all source files for -# consumption by tests. -set(XRAY_ALL_SOURCE_FILES - ${XRAY_SOURCES} - ${XRAY_FDR_MODE_SOURCES} - ${XRAY_BASIC_MODE_SOURCES} - ${XRAY_PROFILING_MODE_SOURCES} - ${x86_64_SOURCES} - ${arm_SOURCES} - ${armhf_SOURCES} - ${mips_SOURCES} - ${mipsel_SOURCES} - ${mips64_SOURCES} - ${mips64el_SOURCES} - ${powerpc64le_SOURCES} - ${XRAY_IMPL_HEADERS} -) -list(REMOVE_DUPLICATES XRAY_ALL_SOURCE_FILES) -# Make list that uses absolute paths -set(XRAY_ALL_SOURCE_FILES_ABS_PATHS "") -foreach (src_file ${XRAY_ALL_SOURCE_FILES}) - list(APPEND - XRAY_ALL_SOURCE_FILES_ABS_PATHS - "${CMAKE_CURRENT_SOURCE_DIR}/${src_file}") -endforeach() - - -# Now put it all together... -include_directories(..) -include_directories(../../include) - -set(XRAY_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -set(XRAY_COMMON_DEFINITIONS XRAY_HAS_EXCEPTIONS=1) - -# We don't need RTTI in XRay, so turn that off. -append_rtti_flag(OFF XRAY_CFLAGS) - -append_list_if( - COMPILER_RT_HAS_XRAY_COMPILER_FLAG XRAY_SUPPORTED=1 XRAY_COMMON_DEFINITIONS) -append_list_if( - COMPILER_RT_BUILD_XRAY_NO_PREINIT XRAY_NO_PREINIT XRAY_COMMON_DEFINITIONS) - -add_compiler_rt_component(xray) - -set(XRAY_COMMON_RUNTIME_OBJECT_LIBS - RTSanitizerCommon - RTSanitizerCommonLibc) - -if (TARGET cxx-headers OR HAVE_LIBCXX) - set(XRAY_DEPS cxx-headers) -endif() - -if (APPLE) - set(XRAY_LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS}) - add_asm_sources(XRAY_ASM_SOURCES xray_trampoline_x86_64.S) - - add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) - add_weak_symbols("xray" WEAK_SYMBOL_LINK_FLAGS) - - add_compiler_rt_object_libraries(RTXray - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_SUPPORTED_ARCH} - SOURCES ${XRAY_SOURCES} ${x86_64_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - DEPS ${XRAY_DEPS}) - add_compiler_rt_object_libraries(RTXrayFDR - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_SUPPORTED_ARCH} - SOURCES ${XRAY_FDR_MODE_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - DEPS ${XRAY_DEPS}) - add_compiler_rt_object_libraries(RTXrayBASIC - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_SUPPORTED_ARCH} - SOURCES ${XRAY_BASIC_MODE_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - DEPS ${XRAY_DEPS}) - add_compiler_rt_object_libraries(RTXrayPROFILING - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_SUPPORTED_ARCH} - SOURCES ${XRAY_PROFILING_MODE_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - DEPS ${XRAY_DEPS}) - - # We only support running on osx for now. - add_compiler_rt_runtime(clang_rt.xray - STATIC - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_SUPPORTED_ARCH} - OBJECT_LIBS RTXray - RTSanitizerCommon - RTSanitizerCommonLibc - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} - LINK_LIBS ${XRAY_LINK_LIBS} - PARENT_TARGET xray) - add_compiler_rt_runtime(clang_rt.xray-fdr - STATIC - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_SUPPORTED_ARCH} - OBJECT_LIBS RTXrayFDR - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} - LINK_LIBS ${XRAY_LINK_LIBS} - PARENT_TARGET xray) - add_compiler_rt_runtime(clang_rt.xray-basic - STATIC - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_SUPPORTED_ARCH} - OBJECT_LIBS RTXrayBASIC - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} - LINK_LIBS ${XRAY_LINK_LIBS} - PARENT_TARGET xray) - add_compiler_rt_runtime(clang_rt.xray-profiling - STATIC - OS ${XRAY_SUPPORTED_OS} - ARCHS ${XRAY_SUPPORTED_ARCH} - OBJECT_LIBS RTXrayPROFILING - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} - LINK_LIBS ${XRAY_LINK_LIBS} - PARENT_TARGET xray) -else() # not Apple - foreach(arch ${XRAY_SUPPORTED_ARCH}) - if(NOT CAN_TARGET_${arch}) - continue() - endif() - add_compiler_rt_object_libraries(RTXray - ARCHS ${arch} - SOURCES ${XRAY_SOURCES} ${${arch}_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - DEPS ${XRAY_DEPS}) - add_compiler_rt_object_libraries(RTXrayFDR - ARCHS ${arch} - SOURCES ${XRAY_FDR_MODE_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - DEPS ${XRAY_DEPS}) - add_compiler_rt_object_libraries(RTXrayBASIC - ARCHS ${arch} - SOURCES ${XRAY_BASIC_MODE_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - DEPS ${XRAY_DEPS}) - add_compiler_rt_object_libraries(RTXrayPROFILING - ARCHS ${arch} - SOURCES ${XRAY_PROFILING_MODE_SOURCES} - ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - DEPS ${XRAY_DEPS}) - - # Common XRay archive for instrumented binaries. - add_compiler_rt_runtime(clang_rt.xray - STATIC - ARCHS ${arch} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - OBJECT_LIBS ${XRAY_COMMON_RUNTIME_OBJECT_LIBS} RTXray - PARENT_TARGET xray) - # FDR mode runtime archive (addon for clang_rt.xray) - add_compiler_rt_runtime(clang_rt.xray-fdr - STATIC - ARCHS ${arch} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - OBJECT_LIBS RTXrayFDR - PARENT_TARGET xray) - # Basic mode runtime archive (addon for clang_rt.xray) - add_compiler_rt_runtime(clang_rt.xray-basic - STATIC - ARCHS ${arch} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - OBJECT_LIBS RTXrayBASIC - PARENT_TARGET xray) - # Profiler Mode runtime - add_compiler_rt_runtime(clang_rt.xray-profiling - STATIC - ARCHS ${arch} - CFLAGS ${XRAY_CFLAGS} - DEFS ${XRAY_COMMON_DEFINITIONS} - OBJECT_LIBS RTXrayPROFILING - PARENT_TARGET xray) - endforeach() -endif() # not Apple - -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/lib/xray/tests/CMakeLists.txt b/lib/xray/tests/CMakeLists.txt deleted file mode 100644 index 89a2b3b01ed8a..0000000000000 --- a/lib/xray/tests/CMakeLists.txt +++ /dev/null @@ -1,132 +0,0 @@ -include_directories(..) - -add_custom_target(XRayUnitTests) -set_target_properties(XRayUnitTests PROPERTIES FOLDER "XRay unittests") - -# Sanity check XRAY_ALL_SOURCE_FILES_ABS_PATHS -list(LENGTH XRAY_ALL_SOURCE_FILES_ABS_PATHS XASFAP_LENGTH) -if (${XASFAP_LENGTH} EQUAL 0) - message(FATAL_ERROR "XRAY_ALL_SOURCE_FILES_ABS_PATHS cannot be empty") -endif() -unset(XASFAP_LENGTH) -foreach (src_file ${XRAY_ALL_SOURCE_FILES_ABS_PATHS}) - if (NOT EXISTS "${src_file}") - message(FATAL_ERROR "Source file \"${src_file}\" does not exist") - endif() -endforeach() - -set(XRAY_UNITTEST_CFLAGS - ${XRAY_CFLAGS} - ${COMPILER_RT_UNITTEST_CFLAGS} - ${COMPILER_RT_GTEST_CFLAGS} - ${COMPILER_RT_GMOCK_CFLAGS} - -I${COMPILER_RT_SOURCE_DIR}/include - -I${COMPILER_RT_SOURCE_DIR}/lib/xray - -I${COMPILER_RT_SOURCE_DIR}/lib - ) - -# We add the include directories one at a time in our CFLAGS. -foreach (DIR ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR}) - list(APPEND XRAY_UNITTEST_CFLAGS -I${DIR}) -endforeach() - -function(add_xray_lib library) - add_library(${library} STATIC ${ARGN}) - set_target_properties(${library} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - FOLDER "Compiler-RT Runtime tests") -endfunction() - -function(get_xray_lib_for_arch arch lib) - if(APPLE) - set(tgt_name "RTXRay.test.osx") - else() - set(tgt_name "RTXRay.test.${arch}") - endif() - set(${lib} "${tgt_name}" PARENT_SCOPE) -endfunction() - -set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH}) -set(XRAY_UNITTEST_LINK_FLAGS - ${CMAKE_THREAD_LIBS_INIT} - -l${SANITIZER_CXX_ABI_LIBRARY}) - -if (NOT APPLE) - # Needed by LLVMSupport. - append_list_if( - COMPILER_RT_HAS_TERMINFO - -l${COMPILER_RT_TERMINFO_LIB} XRAY_UNITTEST_LINK_FLAGS) - - if (COMPILER_RT_STANDALONE_BUILD) - append_list_if(COMPILER_RT_HAS_LLVMXRAY ${LLVM_XRAY_LDFLAGS} XRAY_UNITTEST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LLVMXRAY ${LLVM_XRAY_LIBLIST} XRAY_UNITTEST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LLVMTESTINGSUPPORT - ${LLVM_TESTINGSUPPORT_LDFLAGS} XRAY_UNITTEST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LLVMTESTINGSUPPORT - ${LLVM_TESTINGSUPPORT_LIBLIST} XRAY_UNITTEST_LINK_FLAGS) - else() - # We add the library directories one at a time in our CFLAGS. - foreach (DIR ${LLVM_LIBRARY_DIR}) - list(APPEND XRAY_UNITTEST_LINK_FLAGS -L${DIR}) - endforeach() - - # We also add the actual libraries to link as dependencies. - list(APPEND XRAY_UNITTEST_LINK_FLAGS -lLLVMXRay -lLLVMSupport -lLLVMTestingSupport) - endif() - - append_list_if(COMPILER_RT_HAS_LIBM -lm XRAY_UNITTEST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LIBRT -lrt XRAY_UNITTEST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LIBDL -ldl XRAY_UNITTEST_LINK_FLAGS) - append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread XRAY_UNITTEST_LINK_FLAGS) -endif() - -macro(add_xray_unittest testname) - cmake_parse_arguments(TEST "" "" "SOURCES;HEADERS" ${ARGN}) - if(UNIX AND NOT APPLE) - set(CMAKE_DL_LIBS_INIT "") - foreach(arch ${XRAY_TEST_ARCH}) - set(TEST_OBJECTS) - get_xray_lib_for_arch(${arch} XRAY_RUNTIME_LIBS) - generate_compiler_rt_tests(TEST_OBJECTS - XRayUnitTests "${testname}-${arch}-Test" "${arch}" - SOURCES ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE} - ${COMPILER_RT_GMOCK_SOURCE} - - # Note that any change in the implementations will cause all the unit - # tests to be re-built. This is by design, but may be cumbersome during - # the build/test cycle. - COMPILE_DEPS ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE} - ${XRAY_HEADERS} ${XRAY_ALL_SOURCE_FILES_ABS_PATHS} - "test_helpers.h" - RUNTIME "${XRAY_RUNTIME_LIBS}" - DEPS gtest xray llvm-xray LLVMXRay LLVMTestingSupport - CFLAGS ${XRAY_UNITTEST_CFLAGS} - LINK_FLAGS ${TARGET_LINK_FLAGS} ${XRAY_UNITTEST_LINK_FLAGS} - ) - set_target_properties(XRayUnitTests - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - endforeach() - endif() -endmacro() - -if(COMPILER_RT_CAN_EXECUTE_TESTS) - if (APPLE) - add_xray_lib("RTXRay.test.osx" - $<TARGET_OBJECTS:RTXray.osx> - $<TARGET_OBJECTS:RTXrayFDR.osx> - $<TARGET_OBJECTS:RTXrayPROFILING.osx> - $<TARGET_OBJECTS:RTSanitizerCommon.osx> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.osx>) - else() - foreach(arch ${XRAY_SUPPORTED_ARCH}) - add_xray_lib("RTXRay.test.${arch}" - $<TARGET_OBJECTS:RTXray.${arch}> - $<TARGET_OBJECTS:RTXrayFDR.${arch}> - $<TARGET_OBJECTS:RTXrayPROFILING.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommon.${arch}> - $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>) - endforeach() - endif() - add_subdirectory(unit) -endif() diff --git a/lib/xray/tests/unit/CMakeLists.txt b/lib/xray/tests/unit/CMakeLists.txt deleted file mode 100644 index d10524b8d030a..0000000000000 --- a/lib/xray/tests/unit/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(TEST_SOURCES - allocator_test.cc - buffer_queue_test.cc - function_call_trie_test.cc - profile_collector_test.cc - segmented_array_test.cc - test_helpers.cc - xray_unit_test_main.cc) - -if (NOT COMPILER_RT_STANDALONE_BUILD OR COMPILER_RT_HAS_LLVMTESTINGSUPPORT) - list(APPEND TEST_SOURCES - fdr_controller_test.cc - fdr_log_writer_test.cc) -endif() - -add_xray_unittest(XRayTest SOURCES ${TEST_SOURCES}) diff --git a/lib/xray/tests/unit/allocator_test.cc b/lib/xray/tests/unit/allocator_test.cc deleted file mode 100644 index 1170741623cbe..0000000000000 --- a/lib/xray/tests/unit/allocator_test.cc +++ /dev/null @@ -1,82 +0,0 @@ -//===-- allocator_test.cc -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// - -#include "xray_allocator.h" -#include "xray_buffer_queue.h" -#include "gtest/gtest.h" - -namespace __xray { -namespace { - -struct TestData { - s64 First; - s64 Second; -}; - -TEST(AllocatorTest, Construction) { Allocator<sizeof(TestData)> A(2 << 11); } - -TEST(AllocatorTest, Allocate) { - Allocator<sizeof(TestData)> A(2 << 11); - auto B = A.Allocate(); - ASSERT_NE(B.Data, nullptr); -} - -TEST(AllocatorTest, OverAllocate) { - Allocator<sizeof(TestData)> A(sizeof(TestData)); - auto B1 = A.Allocate(); - ASSERT_NE(B1.Data, nullptr); - auto B2 = A.Allocate(); - ASSERT_EQ(B2.Data, nullptr); -} - -struct OddSizedData { - s64 A; - s32 B; -}; - -TEST(AllocatorTest, AllocateBoundaries) { - Allocator<sizeof(OddSizedData)> A(GetPageSizeCached()); - - // Keep allocating until we hit a nullptr block. - unsigned C = 0; - auto Expected = - GetPageSizeCached() / RoundUpTo(sizeof(OddSizedData), kCacheLineSize); - for (auto B = A.Allocate(); B.Data != nullptr; B = A.Allocate(), ++C) - ; - - ASSERT_EQ(C, Expected); -} - -TEST(AllocatorTest, AllocateFromNonOwned) { - bool Success = false; - BufferQueue BQ(GetPageSizeCached(), 10, Success); - ASSERT_TRUE(Success); - BufferQueue::Buffer B; - ASSERT_EQ(BQ.getBuffer(B), BufferQueue::ErrorCode::Ok); - { - Allocator<sizeof(OddSizedData)> A(B.Data, B.Size); - - // Keep allocating until we hit a nullptr block. - unsigned C = 0; - auto Expected = - GetPageSizeCached() / RoundUpTo(sizeof(OddSizedData), kCacheLineSize); - for (auto B = A.Allocate(); B.Data != nullptr; B = A.Allocate(), ++C) - ; - - ASSERT_EQ(C, Expected); - } - ASSERT_EQ(BQ.releaseBuffer(B), BufferQueue::ErrorCode::Ok); -} - -} // namespace -} // namespace __xray diff --git a/lib/xray/tests/unit/buffer_queue_test.cc b/lib/xray/tests/unit/buffer_queue_test.cc deleted file mode 100644 index a30343e188f28..0000000000000 --- a/lib/xray/tests/unit/buffer_queue_test.cc +++ /dev/null @@ -1,235 +0,0 @@ -//===-- buffer_queue_test.cc ----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// -#include "xray_buffer_queue.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -#include <atomic> -#include <future> -#include <thread> -#include <unistd.h> - -namespace __xray { -namespace { - -static constexpr size_t kSize = 4096; - -using ::testing::Eq; - -TEST(BufferQueueTest, API) { - bool Success = false; - BufferQueue Buffers(kSize, 1, Success); - ASSERT_TRUE(Success); -} - -TEST(BufferQueueTest, GetAndRelease) { - bool Success = false; - BufferQueue Buffers(kSize, 1, Success); - ASSERT_TRUE(Success); - BufferQueue::Buffer Buf; - ASSERT_EQ(Buffers.getBuffer(Buf), BufferQueue::ErrorCode::Ok); - ASSERT_NE(nullptr, Buf.Data); - ASSERT_EQ(Buffers.releaseBuffer(Buf), BufferQueue::ErrorCode::Ok); - ASSERT_EQ(nullptr, Buf.Data); -} - -TEST(BufferQueueTest, GetUntilFailed) { - bool Success = false; - BufferQueue Buffers(kSize, 1, Success); - ASSERT_TRUE(Success); - BufferQueue::Buffer Buf0; - EXPECT_EQ(Buffers.getBuffer(Buf0), BufferQueue::ErrorCode::Ok); - BufferQueue::Buffer Buf1; - EXPECT_EQ(BufferQueue::ErrorCode::NotEnoughMemory, Buffers.getBuffer(Buf1)); - EXPECT_EQ(Buffers.releaseBuffer(Buf0), BufferQueue::ErrorCode::Ok); -} - -TEST(BufferQueueTest, ReleaseUnknown) { - bool Success = false; - BufferQueue Buffers(kSize, 1, Success); - ASSERT_TRUE(Success); - BufferQueue::Buffer Buf; - Buf.Data = reinterpret_cast<void *>(0xdeadbeef); - Buf.Size = kSize; - Buf.Generation = Buffers.generation(); - - BufferQueue::Buffer Known; - EXPECT_THAT(Buffers.getBuffer(Known), Eq(BufferQueue::ErrorCode::Ok)); - EXPECT_THAT(Buffers.releaseBuffer(Buf), - Eq(BufferQueue::ErrorCode::UnrecognizedBuffer)); - EXPECT_THAT(Buffers.releaseBuffer(Known), Eq(BufferQueue::ErrorCode::Ok)); -} - -TEST(BufferQueueTest, ErrorsWhenFinalising) { - bool Success = false; - BufferQueue Buffers(kSize, 2, Success); - ASSERT_TRUE(Success); - BufferQueue::Buffer Buf; - ASSERT_EQ(Buffers.getBuffer(Buf), BufferQueue::ErrorCode::Ok); - ASSERT_NE(nullptr, Buf.Data); - ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok); - BufferQueue::Buffer OtherBuf; - ASSERT_EQ(BufferQueue::ErrorCode::QueueFinalizing, - Buffers.getBuffer(OtherBuf)); - ASSERT_EQ(BufferQueue::ErrorCode::QueueFinalizing, Buffers.finalize()); - ASSERT_EQ(Buffers.releaseBuffer(Buf), BufferQueue::ErrorCode::Ok); -} - -TEST(BufferQueueTest, MultiThreaded) { - bool Success = false; - BufferQueue Buffers(kSize, 100, Success); - ASSERT_TRUE(Success); - auto F = [&] { - BufferQueue::Buffer B; - while (true) { - auto EC = Buffers.getBuffer(B); - if (EC != BufferQueue::ErrorCode::Ok) - return; - Buffers.releaseBuffer(B); - } - }; - auto T0 = std::async(std::launch::async, F); - auto T1 = std::async(std::launch::async, F); - auto T2 = std::async(std::launch::async, [&] { - while (Buffers.finalize() != BufferQueue::ErrorCode::Ok) - ; - }); - F(); -} - -TEST(BufferQueueTest, Apply) { - bool Success = false; - BufferQueue Buffers(kSize, 10, Success); - ASSERT_TRUE(Success); - auto Count = 0; - BufferQueue::Buffer B; - for (int I = 0; I < 10; ++I) { - ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok); - ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok); - } - Buffers.apply([&](const BufferQueue::Buffer &B) { ++Count; }); - ASSERT_EQ(Count, 10); -} - -TEST(BufferQueueTest, GenerationalSupport) { - bool Success = false; - BufferQueue Buffers(kSize, 10, Success); - ASSERT_TRUE(Success); - BufferQueue::Buffer B0; - ASSERT_EQ(Buffers.getBuffer(B0), BufferQueue::ErrorCode::Ok); - ASSERT_EQ(Buffers.finalize(), - BufferQueue::ErrorCode::Ok); // No more new buffers. - - // Re-initialise the queue. - ASSERT_EQ(Buffers.init(kSize, 10), BufferQueue::ErrorCode::Ok); - - BufferQueue::Buffer B1; - ASSERT_EQ(Buffers.getBuffer(B1), BufferQueue::ErrorCode::Ok); - - // Validate that the buffers come from different generations. - ASSERT_NE(B0.Generation, B1.Generation); - - // We stash the current generation, for use later. - auto PrevGen = B1.Generation; - - // At this point, we want to ensure that we can return the buffer from the - // first "generation" would still be accepted in the new generation... - EXPECT_EQ(Buffers.releaseBuffer(B0), BufferQueue::ErrorCode::Ok); - - // ... and that the new buffer is also accepted. - EXPECT_EQ(Buffers.releaseBuffer(B1), BufferQueue::ErrorCode::Ok); - - // A next round will do the same, ensure that we are able to do multiple - // rounds in this case. - ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok); - ASSERT_EQ(Buffers.init(kSize, 10), BufferQueue::ErrorCode::Ok); - EXPECT_EQ(Buffers.getBuffer(B0), BufferQueue::ErrorCode::Ok); - EXPECT_EQ(Buffers.getBuffer(B1), BufferQueue::ErrorCode::Ok); - - // Here we ensure that the generation is different from the previous - // generation. - EXPECT_NE(B0.Generation, PrevGen); - EXPECT_EQ(B1.Generation, B1.Generation); - ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok); - EXPECT_EQ(Buffers.releaseBuffer(B0), BufferQueue::ErrorCode::Ok); - EXPECT_EQ(Buffers.releaseBuffer(B1), BufferQueue::ErrorCode::Ok); -} - -TEST(BufferQueueTest, GenerationalSupportAcrossThreads) { - bool Success = false; - BufferQueue Buffers(kSize, 10, Success); - ASSERT_TRUE(Success); - - std::atomic<int> Counter{0}; - - // This function allows us to use thread-local storage to isolate the - // instances of the buffers to be used. It also allows us signal the threads - // of a new generation, and allow those to get new buffers. This is - // representative of how we expect the buffer queue to be used by the XRay - // runtime. - auto Process = [&] { - thread_local BufferQueue::Buffer B; - ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok); - auto FirstGen = B.Generation; - - // Signal that we've gotten a buffer in the thread. - Counter.fetch_add(1, std::memory_order_acq_rel); - while (!Buffers.finalizing()) { - Buffers.releaseBuffer(B); - Buffers.getBuffer(B); - } - - // Signal that we've exited the get/release buffer loop. - Counter.fetch_sub(1, std::memory_order_acq_rel); - if (B.Data != nullptr) - Buffers.releaseBuffer(B); - - // Spin until we find that the Buffer Queue is no longer finalizing. - while (Buffers.getBuffer(B) != BufferQueue::ErrorCode::Ok) - ; - - // Signal that we've successfully gotten a buffer in the thread. - Counter.fetch_add(1, std::memory_order_acq_rel); - - EXPECT_NE(FirstGen, B.Generation); - EXPECT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok); - - // Signal that we've successfully exited. - Counter.fetch_sub(1, std::memory_order_acq_rel); - }; - - // Spawn two threads running Process. - std::thread T0(Process), T1(Process); - - // Spin until we find the counter is up to 2. - while (Counter.load(std::memory_order_acquire) != 2) - ; - - // Then we finalize, then re-initialize immediately. - Buffers.finalize(); - - // Spin until we find the counter is down to 0. - while (Counter.load(std::memory_order_acquire) != 0) - ; - - // Then we re-initialize. - EXPECT_EQ(Buffers.init(kSize, 10), BufferQueue::ErrorCode::Ok); - - T0.join(); - T1.join(); - - ASSERT_EQ(Counter.load(std::memory_order_acquire), 0); -} - -} // namespace -} // namespace __xray diff --git a/lib/xray/tests/unit/fdr_controller_test.cc b/lib/xray/tests/unit/fdr_controller_test.cc deleted file mode 100644 index 8967c4919ae67..0000000000000 --- a/lib/xray/tests/unit/fdr_controller_test.cc +++ /dev/null @@ -1,424 +0,0 @@ -//===-- fdr_controller_test.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// -#include <algorithm> -#include <memory> -#include <time.h> - -#include "test_helpers.h" -#include "xray/xray_records.h" -#include "xray_buffer_queue.h" -#include "xray_fdr_controller.h" -#include "xray_fdr_log_writer.h" -#include "llvm/Support/DataExtractor.h" -#include "llvm/Testing/Support/Error.h" -#include "llvm/XRay/Trace.h" -#include "llvm/XRay/XRayRecord.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace __xray { -namespace { - -using ::llvm::HasValue; -using ::llvm::xray::testing::FuncId; -using ::llvm::xray::testing::HasArg; -using ::llvm::xray::testing::RecordType; -using ::llvm::xray::testing::TSCIs; -using ::testing::AllOf; -using ::testing::ElementsAre; -using ::testing::Eq; -using ::testing::Field; -using ::testing::Gt; -using ::testing::IsEmpty; -using ::testing::SizeIs; - -class FunctionSequenceTest : public ::testing::Test { -protected: - BufferQueue::Buffer B{}; - std::unique_ptr<BufferQueue> BQ; - std::unique_ptr<FDRLogWriter> W; - std::unique_ptr<FDRController<>> C; - -public: - void SetUp() override { - bool Success; - BQ = llvm::make_unique<BufferQueue>(4096, 1, Success); - ASSERT_TRUE(Success); - ASSERT_EQ(BQ->getBuffer(B), BufferQueue::ErrorCode::Ok); - W = llvm::make_unique<FDRLogWriter>(B); - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 0); - } -}; - -TEST_F(FunctionSequenceTest, DefaultInitFinalizeFlush) { - ASSERT_TRUE(C->functionEnter(1, 2, 3)); - ASSERT_TRUE(C->functionExit(1, 2, 3)); - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize the buffers then test to see we find the expected records. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, - HasValue(ElementsAre( - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER)), - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT))))); -} - -TEST_F(FunctionSequenceTest, BoundaryFuncIdEncoding) { - // We ensure that we can write function id's that are at the boundary of the - // acceptable function ids. - int32_t FId = (1 << 28) - 1; - uint64_t TSC = 2; - uint16_t CPU = 1; - ASSERT_TRUE(C->functionEnter(FId, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(FId, TSC++, CPU)); - ASSERT_TRUE(C->functionEnterArg(FId, TSC++, CPU, 1)); - ASSERT_TRUE(C->functionTailExit(FId, TSC++, CPU)); - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize the buffers then test to see we find the expected records. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, - HasValue(ElementsAre( - AllOf(FuncId(FId), RecordType(llvm::xray::RecordTypes::ENTER)), - AllOf(FuncId(FId), RecordType(llvm::xray::RecordTypes::EXIT)), - AllOf(FuncId(FId), RecordType(llvm::xray::RecordTypes::ENTER_ARG)), - AllOf(FuncId(FId), RecordType(llvm::xray::RecordTypes::TAIL_EXIT))))); -} - -TEST_F(FunctionSequenceTest, ThresholdsAreEnforced) { - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000); - ASSERT_TRUE(C->functionEnter(1, 2, 3)); - ASSERT_TRUE(C->functionExit(1, 2, 3)); - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize the buffers then test to see we find the *no* records, because - // the function entry-exit comes under the cycle threshold. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty())); -} - -TEST_F(FunctionSequenceTest, ArgsAreHandledAndKept) { - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000); - ASSERT_TRUE(C->functionEnterArg(1, 2, 3, 4)); - ASSERT_TRUE(C->functionExit(1, 2, 3)); - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize the buffers then test to see we find the function enter arg - // record with the specified argument. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, - HasValue(ElementsAre( - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER_ARG), - HasArg(4)), - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT))))); -} - -TEST_F(FunctionSequenceTest, PreservedCallsHaveCorrectTSC) { - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000); - uint64_t TSC = 1; - uint16_t CPU = 0; - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(2, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(2, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(1, TSC += 1000, CPU)); - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize the buffers then test to see if we find the remaining records, - // because the function entry-exit comes under the cycle threshold. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, - HasValue(ElementsAre( - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER), - TSCIs(Eq(1uL))), - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT), - TSCIs(Gt(1000uL)))))); -} - -TEST_F(FunctionSequenceTest, PreservedCallsSupportLargeDeltas) { - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000); - uint64_t TSC = 1; - uint16_t CPU = 0; - const auto LargeDelta = uint64_t{std::numeric_limits<int32_t>::max()}; - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(1, TSC += LargeDelta, CPU)); - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize the buffer then test to see if we find the right TSC with a large - // delta. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, - HasValue(ElementsAre( - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER), - TSCIs(Eq(1uL))), - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT), - TSCIs(Gt(LargeDelta)))))); -} - -TEST_F(FunctionSequenceTest, RewindingMultipleCalls) { - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000); - - // First we construct an arbitrarily deep function enter/call stack. - // We also ensure that we are in the same CPU. - uint64_t TSC = 1; - uint16_t CPU = 1; - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(2, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(3, TSC++, CPU)); - - // Then we exit them one at a time, in reverse order of entry. - ASSERT_TRUE(C->functionExit(3, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(2, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(1, TSC++, CPU)); - - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize the buffers then test to see we find that all the calls have been - // unwound because all of them are under the cycle counter threshold. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty())); -} - -TEST_F(FunctionSequenceTest, RewindingIntermediaryTailExits) { - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000); - - // First we construct an arbitrarily deep function enter/call stack. - // We also ensure that we are in the same CPU. - uint64_t TSC = 1; - uint16_t CPU = 1; - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(2, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(3, TSC++, CPU)); - - // Next we tail-exit into a new function multiple times. - ASSERT_TRUE(C->functionTailExit(3, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(4, TSC++, CPU)); - ASSERT_TRUE(C->functionTailExit(4, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(5, TSC++, CPU)); - ASSERT_TRUE(C->functionTailExit(5, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(6, TSC++, CPU)); - - // Then we exit them one at a time, in reverse order of entry. - ASSERT_TRUE(C->functionExit(6, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(2, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(1, TSC++, CPU)); - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize the buffers then test to see we find that all the calls have been - // unwound because all of them are under the cycle counter threshold. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty())); -} - -TEST_F(FunctionSequenceTest, RewindingAfterMigration) { - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 1000); - - // First we construct an arbitrarily deep function enter/call stack. - // We also ensure that we are in the same CPU. - uint64_t TSC = 1; - uint16_t CPU = 1; - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(2, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(3, TSC++, CPU)); - - // Next we tail-exit into a new function multiple times. - ASSERT_TRUE(C->functionTailExit(3, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(4, TSC++, CPU)); - ASSERT_TRUE(C->functionTailExit(4, TSC++, CPU)); - - // But before we enter the next function, we migrate to a different CPU. - CPU = 2; - ASSERT_TRUE(C->functionEnter(5, TSC++, CPU)); - ASSERT_TRUE(C->functionTailExit(5, TSC++, CPU)); - ASSERT_TRUE(C->functionEnter(6, TSC++, CPU)); - - // Then we exit them one at a time, in reverse order of entry. - ASSERT_TRUE(C->functionExit(6, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(2, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(1, TSC++, CPU)); - - ASSERT_TRUE(C->flush()); - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // Serialize buffers then test that we can find all the events that span the - // CPU migration. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, - HasValue(ElementsAre( - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER)), - AllOf(FuncId(2), RecordType(llvm::xray::RecordTypes::ENTER)), - AllOf(FuncId(2), RecordType(llvm::xray::RecordTypes::EXIT)), - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT))))); -} - -class BufferManagementTest : public ::testing::Test { -protected: - BufferQueue::Buffer B{}; - std::unique_ptr<BufferQueue> BQ; - std::unique_ptr<FDRLogWriter> W; - std::unique_ptr<FDRController<>> C; - - static constexpr size_t kBuffers = 10; - -public: - void SetUp() override { - bool Success; - BQ = llvm::make_unique<BufferQueue>(sizeof(MetadataRecord) * 5 + - sizeof(FunctionRecord) * 2, - kBuffers, Success); - ASSERT_TRUE(Success); - ASSERT_EQ(BQ->getBuffer(B), BufferQueue::ErrorCode::Ok); - W = llvm::make_unique<FDRLogWriter>(B); - C = llvm::make_unique<FDRController<>>(BQ.get(), B, *W, clock_gettime, 0); - } -}; - -constexpr size_t BufferManagementTest::kBuffers; - -TEST_F(BufferManagementTest, HandlesOverflow) { - uint64_t TSC = 1; - uint16_t CPU = 1; - for (size_t I = 0; I < kBuffers + 1; ++I) { - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(1, TSC++, CPU)); - } - ASSERT_TRUE(C->flush()); - ASSERT_THAT(BQ->finalize(), Eq(BufferQueue::ErrorCode::Ok)); - - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(SizeIs(kBuffers * 2))); -} - -TEST_F(BufferManagementTest, HandlesOverflowWithArgs) { - uint64_t TSC = 1; - uint16_t CPU = 1; - uint64_t ARG = 1; - for (size_t I = 0; I < kBuffers + 1; ++I) { - ASSERT_TRUE(C->functionEnterArg(1, TSC++, CPU, ARG++)); - ASSERT_TRUE(C->functionExit(1, TSC++, CPU)); - } - ASSERT_TRUE(C->flush()); - ASSERT_THAT(BQ->finalize(), Eq(BufferQueue::ErrorCode::Ok)); - - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(SizeIs(kBuffers))); -} - -TEST_F(BufferManagementTest, HandlesOverflowWithCustomEvents) { - uint64_t TSC = 1; - uint16_t CPU = 1; - int32_t D = 0x9009; - for (size_t I = 0; I < kBuffers; ++I) { - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - ASSERT_TRUE(C->functionExit(1, TSC++, CPU)); - ASSERT_TRUE(C->customEvent(TSC++, CPU, &D, sizeof(D))); - } - ASSERT_TRUE(C->flush()); - ASSERT_THAT(BQ->finalize(), Eq(BufferQueue::ErrorCode::Ok)); - - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - - // We expect to also now count the kBuffers/2 custom event records showing up - // in the Trace. - EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(SizeIs(kBuffers + (kBuffers / 2)))); -} - -TEST_F(BufferManagementTest, HandlesFinalizedBufferQueue) { - uint64_t TSC = 1; - uint16_t CPU = 1; - - // First write one function entry. - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - - // Then we finalize the buffer queue, simulating the case where the logging - // has been finalized. - ASSERT_EQ(BQ->finalize(), BufferQueue::ErrorCode::Ok); - - // At this point further calls to the controller must fail. - ASSERT_FALSE(C->functionExit(1, TSC++, CPU)); - - // But flushing should succeed. - ASSERT_TRUE(C->flush()); - - // We expect that we'll only be able to find the function enter event, but not - // the function exit event. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, HasValue(ElementsAre(AllOf( - FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER))))); -} - -TEST_F(BufferManagementTest, HandlesGenerationalBufferQueue) { - uint64_t TSC = 1; - uint16_t CPU = 1; - - ASSERT_TRUE(C->functionEnter(1, TSC++, CPU)); - ASSERT_THAT(BQ->finalize(), Eq(BufferQueue::ErrorCode::Ok)); - ASSERT_THAT(BQ->init(sizeof(MetadataRecord) * 4 + sizeof(FunctionRecord) * 2, - kBuffers), - Eq(BufferQueue::ErrorCode::Ok)); - EXPECT_TRUE(C->functionExit(1, TSC++, CPU)); - ASSERT_TRUE(C->flush()); - - // We expect that we will only be able to find the function exit event, but - // not the function enter event, since we only have information about the new - // generation of the buffers. - std::string Serialized = serialize(*BQ, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, HasValue(ElementsAre(AllOf( - FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT))))); -} - -} // namespace -} // namespace __xray diff --git a/lib/xray/tests/unit/fdr_log_writer_test.cc b/lib/xray/tests/unit/fdr_log_writer_test.cc deleted file mode 100644 index f2e7a5cba5d15..0000000000000 --- a/lib/xray/tests/unit/fdr_log_writer_test.cc +++ /dev/null @@ -1,162 +0,0 @@ -//===-- fdr_log_writer_test.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// -#include <time.h> - -#include "test_helpers.h" -#include "xray/xray_records.h" -#include "xray_fdr_log_writer.h" -#include "llvm/Support/DataExtractor.h" -#include "llvm/Testing/Support/Error.h" -#include "llvm/XRay/Trace.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace __xray { -namespace { - -static constexpr size_t kSize = 4096; - -using ::llvm::HasValue; -using ::llvm::xray::testing::FuncId; -using ::llvm::xray::testing::RecordType; -using ::testing::AllOf; -using ::testing::ElementsAre; -using ::testing::Eq; -using ::testing::IsEmpty; -using ::testing::IsNull; - -// Exercise the common code path where we initialize a buffer and are able to -// write some records successfully. -TEST(FdrLogWriterTest, WriteSomeRecords) { - bool Success = false; - BufferQueue Buffers(kSize, 1, Success); - BufferQueue::Buffer B; - ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok); - - FDRLogWriter Writer(B); - MetadataRecord Preamble[] = { - createMetadataRecord<MetadataRecord::RecordKinds::NewBuffer>(int32_t{1}), - createMetadataRecord<MetadataRecord::RecordKinds::WalltimeMarker>( - int64_t{1}, int32_t{2}), - createMetadataRecord<MetadataRecord::RecordKinds::Pid>(int32_t{1}), - }; - ASSERT_THAT(Writer.writeMetadataRecords(Preamble), - Eq(sizeof(MetadataRecord) * 3)); - ASSERT_TRUE(Writer.writeMetadata<MetadataRecord::RecordKinds::NewCPUId>(1)); - ASSERT_TRUE( - Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Enter, 1, 1)); - ASSERT_TRUE( - Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Exit, 1, 1)); - ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok); - ASSERT_EQ(B.Data, nullptr); - ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok); - - // We then need to go through each element of the Buffers, and re-create a - // flat buffer that we would see if they were laid out in a file. This also - // means we need to write out the header manually. - std::string Serialized = serialize(Buffers, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, - HasValue(ElementsAre( - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER)), - AllOf(FuncId(1), RecordType(llvm::xray::RecordTypes::EXIT))))); -} - -// Ensure that we can handle buffer re-use. -TEST(FdrLogWriterTest, ReuseBuffers) { - bool Success = false; - BufferQueue Buffers(kSize, 1, Success); - BufferQueue::Buffer B; - ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok); - - FDRLogWriter Writer(B); - MetadataRecord Preamble[] = { - createMetadataRecord<MetadataRecord::RecordKinds::NewBuffer>(int32_t{1}), - createMetadataRecord<MetadataRecord::RecordKinds::WalltimeMarker>( - int64_t{1}, int32_t{2}), - createMetadataRecord<MetadataRecord::RecordKinds::Pid>(int32_t{1}), - }; - - // First we write the first set of records into the single buffer in the - // queue which includes one enter and one exit record. - ASSERT_THAT(Writer.writeMetadataRecords(Preamble), - Eq(sizeof(MetadataRecord) * 3)); - ASSERT_TRUE(Writer.writeMetadata<MetadataRecord::RecordKinds::NewCPUId>( - uint16_t{1}, uint64_t{1})); - uint64_t TSC = 1; - ASSERT_TRUE( - Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Enter, 1, TSC++)); - ASSERT_TRUE( - Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Exit, 1, TSC++)); - ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok); - ASSERT_THAT(B.Data, IsNull()); - - // Then we re-use the buffer, but only write one record. - ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok); - Writer.resetRecord(); - ASSERT_THAT(Writer.writeMetadataRecords(Preamble), - Eq(sizeof(MetadataRecord) * 3)); - ASSERT_TRUE(Writer.writeMetadata<MetadataRecord::RecordKinds::NewCPUId>( - uint16_t{1}, uint64_t{1})); - ASSERT_TRUE( - Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Enter, 1, TSC++)); - ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok); - ASSERT_THAT(B.Data, IsNull()); - ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok); - - // Then we validate that we only see the single enter record. - std::string Serialized = serialize(Buffers, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED( - TraceOrErr, HasValue(ElementsAre(AllOf( - FuncId(1), RecordType(llvm::xray::RecordTypes::ENTER))))); -} - -TEST(FdrLogWriterTest, UnwriteRecords) { - bool Success = false; - BufferQueue Buffers(kSize, 1, Success); - BufferQueue::Buffer B; - ASSERT_EQ(Buffers.getBuffer(B), BufferQueue::ErrorCode::Ok); - - FDRLogWriter Writer(B); - MetadataRecord Preamble[] = { - createMetadataRecord<MetadataRecord::RecordKinds::NewBuffer>(int32_t{1}), - createMetadataRecord<MetadataRecord::RecordKinds::WalltimeMarker>( - int64_t{1}, int32_t{2}), - createMetadataRecord<MetadataRecord::RecordKinds::Pid>(int32_t{1}), - }; - ASSERT_THAT(Writer.writeMetadataRecords(Preamble), - Eq(sizeof(MetadataRecord) * 3)); - ASSERT_TRUE(Writer.writeMetadata<MetadataRecord::RecordKinds::NewCPUId>(1)); - ASSERT_TRUE( - Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Enter, 1, 1)); - ASSERT_TRUE( - Writer.writeFunction(FDRLogWriter::FunctionRecordKind::Exit, 1, 1)); - Writer.undoWrites(sizeof(FunctionRecord) * 2); - ASSERT_EQ(Buffers.releaseBuffer(B), BufferQueue::ErrorCode::Ok); - ASSERT_EQ(B.Data, nullptr); - ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok); - - // We've un-done the two function records we've written, and now we expect - // that we don't have any function records in the trace. - std::string Serialized = serialize(Buffers, 3); - llvm::DataExtractor DE(Serialized, true, 8); - auto TraceOrErr = llvm::xray::loadTrace(DE); - EXPECT_THAT_EXPECTED(TraceOrErr, HasValue(IsEmpty())); -} - -} // namespace -} // namespace __xray diff --git a/lib/xray/tests/unit/function_call_trie_test.cc b/lib/xray/tests/unit/function_call_trie_test.cc deleted file mode 100644 index 01be691228f2b..0000000000000 --- a/lib/xray/tests/unit/function_call_trie_test.cc +++ /dev/null @@ -1,344 +0,0 @@ -//===-- function_call_trie_test.cc ----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// -#include "xray_function_call_trie.h" -#include "gtest/gtest.h" -#include <cstdint> - -namespace __xray { - -namespace { - -TEST(FunctionCallTrieTest, ConstructWithTLSAllocators) { - profilingFlags()->setDefaults(); - FunctionCallTrie::Allocators Allocators = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(Allocators); -} - -TEST(FunctionCallTrieTest, EnterAndExitFunction) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - - uint64_t TSC = 1; - uint16_t CPU = 0; - Trie.enterFunction(1, TSC++, CPU++); - Trie.exitFunction(1, TSC++, CPU++); - const auto &R = Trie.getRoots(); - - ASSERT_EQ(R.size(), 1u); - ASSERT_EQ(R.front()->FId, 1); - ASSERT_EQ(R.front()->CallCount, 1u); - ASSERT_EQ(R.front()->CumulativeLocalTime, 1u); -} - -TEST(FunctionCallTrieTest, HandleTSCOverflow) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - - Trie.enterFunction(1, std::numeric_limits<uint64_t>::max(), 0); - Trie.exitFunction(1, 1, 0); - const auto &R = Trie.getRoots(); - - ASSERT_EQ(R.size(), 1u); - ASSERT_EQ(R.front()->FId, 1); - ASSERT_EQ(R.front()->CallCount, 1u); - ASSERT_EQ(R.front()->CumulativeLocalTime, 1u); -} - -TEST(FunctionCallTrieTest, MaximalCumulativeTime) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - - Trie.enterFunction(1, 1, 0); - Trie.exitFunction(1, 0, 0); - const auto &R = Trie.getRoots(); - - ASSERT_EQ(R.size(), 1u); - ASSERT_EQ(R.front()->FId, 1); - ASSERT_EQ(R.front()->CallCount, 1u); - ASSERT_EQ(R.front()->CumulativeLocalTime, - std::numeric_limits<uint64_t>::max() - 1); -} - -TEST(FunctionCallTrieTest, MissingFunctionEntry) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - Trie.exitFunction(1, 1, 0); - const auto &R = Trie.getRoots(); - - ASSERT_TRUE(R.empty()); -} - -TEST(FunctionCallTrieTest, NoMatchingEntersForExit) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - Trie.enterFunction(2, 1, 0); - Trie.enterFunction(3, 3, 0); - Trie.exitFunction(1, 5, 0); - const auto &R = Trie.getRoots(); - - ASSERT_FALSE(R.empty()); - EXPECT_EQ(R.size(), size_t{1}); -} - -TEST(FunctionCallTrieTest, MissingFunctionExit) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - Trie.enterFunction(1, 1, 0); - const auto &R = Trie.getRoots(); - - ASSERT_FALSE(R.empty()); - EXPECT_EQ(R.size(), size_t{1}); -} - -TEST(FunctionCallTrieTest, MultipleRoots) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - - // Enter and exit FId = 1. - Trie.enterFunction(1, 1, 0); - Trie.exitFunction(1, 2, 0); - - // Enter and exit FId = 2. - Trie.enterFunction(2, 3, 0); - Trie.exitFunction(2, 4, 0); - - const auto &R = Trie.getRoots(); - ASSERT_FALSE(R.empty()); - ASSERT_EQ(R.size(), 2u); - - // Make sure the roots have different IDs. - const auto R0 = R[0]; - const auto R1 = R[1]; - ASSERT_NE(R0->FId, R1->FId); - - // Inspect the roots that they have the right data. - ASSERT_NE(R0, nullptr); - EXPECT_EQ(R0->CallCount, 1u); - EXPECT_EQ(R0->CumulativeLocalTime, 1u); - - ASSERT_NE(R1, nullptr); - EXPECT_EQ(R1->CallCount, 1u); - EXPECT_EQ(R1->CumulativeLocalTime, 1u); -} - -// While missing an intermediary entry may be rare in practice, we still enforce -// that we can handle the case where we've missed the entry event somehow, in -// between call entry/exits. To illustrate, imagine the following shadow call -// stack: -// -// f0@t0 -> f1@t1 -> f2@t2 -// -// If for whatever reason we see an exit for `f2` @ t3, followed by an exit for -// `f0` @ t4 (i.e. no `f1` exit in between) then we need to handle the case of -// accounting local time to `f2` from d = (t3 - t2), then local time to `f1` -// as d' = (t3 - t1) - d, and then local time to `f0` as d'' = (t3 - t0) - d'. -TEST(FunctionCallTrieTest, MissingIntermediaryExit) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - - Trie.enterFunction(1, 0, 0); - Trie.enterFunction(2, 100, 0); - Trie.enterFunction(3, 200, 0); - Trie.exitFunction(3, 300, 0); - Trie.exitFunction(1, 400, 0); - - // What we should see at this point is all the functions in the trie in a - // specific order (1 -> 2 -> 3) with the appropriate count(s) and local - // latencies. - const auto &R = Trie.getRoots(); - ASSERT_FALSE(R.empty()); - ASSERT_EQ(R.size(), 1u); - - const auto &F1 = *R[0]; - ASSERT_EQ(F1.FId, 1); - ASSERT_FALSE(F1.Callees.empty()); - - const auto &F2 = *F1.Callees[0].NodePtr; - ASSERT_EQ(F2.FId, 2); - ASSERT_FALSE(F2.Callees.empty()); - - const auto &F3 = *F2.Callees[0].NodePtr; - ASSERT_EQ(F3.FId, 3); - ASSERT_TRUE(F3.Callees.empty()); - - // Now that we've established the preconditions, we check for specific aspects - // of the nodes. - EXPECT_EQ(F3.CallCount, 1u); - EXPECT_EQ(F2.CallCount, 1u); - EXPECT_EQ(F1.CallCount, 1u); - EXPECT_EQ(F3.CumulativeLocalTime, 100u); - EXPECT_EQ(F2.CumulativeLocalTime, 300u); - EXPECT_EQ(F1.CumulativeLocalTime, 100u); -} - -TEST(FunctionCallTrieTest, DeepCallStack) { - // Simulate a relatively deep call stack (32 levels) and ensure that we can - // properly pop all the way up the stack. - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - for (int i = 0; i < 32; ++i) - Trie.enterFunction(i + 1, i, 0); - Trie.exitFunction(1, 33, 0); - - // Here, validate that we have a 32-level deep function call path from the - // root (1) down to the leaf (33). - const auto &R = Trie.getRoots(); - ASSERT_EQ(R.size(), 1u); - auto F = R[0]; - for (int i = 0; i < 32; ++i) { - EXPECT_EQ(F->FId, i + 1); - EXPECT_EQ(F->CallCount, 1u); - if (F->Callees.empty() && i != 31) - FAIL() << "Empty callees for FId " << F->FId; - if (i != 31) - F = F->Callees[0].NodePtr; - } -} - -// TODO: Test that we can handle cross-CPU migrations, where TSCs are not -// guaranteed to be synchronised. -TEST(FunctionCallTrieTest, DeepCopy) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Trie(A); - - Trie.enterFunction(1, 0, 0); - Trie.enterFunction(2, 1, 0); - Trie.exitFunction(2, 2, 0); - Trie.enterFunction(3, 3, 0); - Trie.exitFunction(3, 4, 0); - Trie.exitFunction(1, 5, 0); - - // We want to make a deep copy and compare notes. - auto B = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Copy(B); - Trie.deepCopyInto(Copy); - - ASSERT_NE(Trie.getRoots().size(), 0u); - ASSERT_EQ(Trie.getRoots().size(), Copy.getRoots().size()); - const auto &R0Orig = *Trie.getRoots()[0]; - const auto &R0Copy = *Copy.getRoots()[0]; - EXPECT_EQ(R0Orig.FId, 1); - EXPECT_EQ(R0Orig.FId, R0Copy.FId); - - ASSERT_EQ(R0Orig.Callees.size(), 2u); - ASSERT_EQ(R0Copy.Callees.size(), 2u); - - const auto &F1Orig = - *R0Orig.Callees - .find_element( - [](const FunctionCallTrie::NodeIdPair &R) { return R.FId == 2; }) - ->NodePtr; - const auto &F1Copy = - *R0Copy.Callees - .find_element( - [](const FunctionCallTrie::NodeIdPair &R) { return R.FId == 2; }) - ->NodePtr; - EXPECT_EQ(&R0Orig, F1Orig.Parent); - EXPECT_EQ(&R0Copy, F1Copy.Parent); -} - -TEST(FunctionCallTrieTest, MergeInto) { - profilingFlags()->setDefaults(); - auto A = FunctionCallTrie::InitAllocators(); - FunctionCallTrie T0(A); - FunctionCallTrie T1(A); - - // 1 -> 2 -> 3 - T0.enterFunction(1, 0, 0); - T0.enterFunction(2, 1, 0); - T0.enterFunction(3, 2, 0); - T0.exitFunction(3, 3, 0); - T0.exitFunction(2, 4, 0); - T0.exitFunction(1, 5, 0); - - // 1 -> 2 -> 3 - T1.enterFunction(1, 0, 0); - T1.enterFunction(2, 1, 0); - T1.enterFunction(3, 2, 0); - T1.exitFunction(3, 3, 0); - T1.exitFunction(2, 4, 0); - T1.exitFunction(1, 5, 0); - - // We use a different allocator here to make sure that we're able to transfer - // data into a FunctionCallTrie which uses a different allocator. This - // reflects the inteded usage scenario for when we're collecting profiles that - // aggregate across threads. - auto B = FunctionCallTrie::InitAllocators(); - FunctionCallTrie Merged(B); - - T0.mergeInto(Merged); - T1.mergeInto(Merged); - - ASSERT_EQ(Merged.getRoots().size(), 1u); - const auto &R0 = *Merged.getRoots()[0]; - EXPECT_EQ(R0.FId, 1); - EXPECT_EQ(R0.CallCount, 2u); - EXPECT_EQ(R0.CumulativeLocalTime, 10u); - EXPECT_EQ(R0.Callees.size(), 1u); - - const auto &F1 = *R0.Callees[0].NodePtr; - EXPECT_EQ(F1.FId, 2); - EXPECT_EQ(F1.CallCount, 2u); - EXPECT_EQ(F1.CumulativeLocalTime, 6u); - EXPECT_EQ(F1.Callees.size(), 1u); - - const auto &F2 = *F1.Callees[0].NodePtr; - EXPECT_EQ(F2.FId, 3); - EXPECT_EQ(F2.CallCount, 2u); - EXPECT_EQ(F2.CumulativeLocalTime, 2u); - EXPECT_EQ(F2.Callees.size(), 0u); -} - -TEST(FunctionCallTrieTest, PlacementNewOnAlignedStorage) { - profilingFlags()->setDefaults(); - typename std::aligned_storage<sizeof(FunctionCallTrie::Allocators), - alignof(FunctionCallTrie::Allocators)>::type - AllocatorsStorage; - new (&AllocatorsStorage) - FunctionCallTrie::Allocators(FunctionCallTrie::InitAllocators()); - auto *A = - reinterpret_cast<FunctionCallTrie::Allocators *>(&AllocatorsStorage); - - typename std::aligned_storage<sizeof(FunctionCallTrie), - alignof(FunctionCallTrie)>::type FCTStorage; - new (&FCTStorage) FunctionCallTrie(*A); - auto *T = reinterpret_cast<FunctionCallTrie *>(&FCTStorage); - - // Put some data into it. - T->enterFunction(1, 0, 0); - T->exitFunction(1, 1, 0); - - // Re-initialize the objects in storage. - T->~FunctionCallTrie(); - A->~Allocators(); - new (A) FunctionCallTrie::Allocators(FunctionCallTrie::InitAllocators()); - new (T) FunctionCallTrie(*A); - - // Then put some data into it again. - T->enterFunction(1, 0, 0); - T->exitFunction(1, 1, 0); -} - -} // namespace - -} // namespace __xray diff --git a/lib/xray/tests/unit/profile_collector_test.cc b/lib/xray/tests/unit/profile_collector_test.cc deleted file mode 100644 index df786d46b9d46..0000000000000 --- a/lib/xray/tests/unit/profile_collector_test.cc +++ /dev/null @@ -1,236 +0,0 @@ -//===-- profile_collector_test.cc -----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// -#include "gtest/gtest.h" - -#include "xray_profile_collector.h" -#include "xray_profiling_flags.h" -#include <cstdint> -#include <cstring> -#include <memory> -#include <thread> -#include <utility> -#include <vector> - -namespace __xray { -namespace { - -static constexpr auto kHeaderSize = 16u; - -constexpr uptr ExpectedProfilingVersion = 0x20180424; - -struct ExpectedProfilingFileHeader { - const u64 MagicBytes = 0x7872617970726f66; // Identifier for XRay profiling - // files 'xrayprof' in hex. - const u64 Version = ExpectedProfilingVersion; - u64 Timestamp = 0; - u64 PID = 0; -}; - -void ValidateFileHeaderBlock(XRayBuffer B) { - ASSERT_NE(static_cast<const void *>(B.Data), nullptr); - ASSERT_EQ(B.Size, sizeof(ExpectedProfilingFileHeader)); - typename std::aligned_storage<sizeof(ExpectedProfilingFileHeader)>::type - FileHeaderStorage; - ExpectedProfilingFileHeader ExpectedHeader; - std::memcpy(&FileHeaderStorage, B.Data, B.Size); - auto &FileHeader = - *reinterpret_cast<ExpectedProfilingFileHeader *>(&FileHeaderStorage); - ASSERT_EQ(ExpectedHeader.MagicBytes, FileHeader.MagicBytes); - ASSERT_EQ(ExpectedHeader.Version, FileHeader.Version); -} - -void ValidateBlock(XRayBuffer B) { - profilingFlags()->setDefaults(); - ASSERT_NE(static_cast<const void *>(B.Data), nullptr); - ASSERT_NE(B.Size, 0u); - ASSERT_GE(B.Size, kHeaderSize); - // We look at the block size, the block number, and the thread ID to ensure - // that none of them are zero (or that the header data is laid out as we - // expect). - char LocalBuffer[kHeaderSize] = {}; - internal_memcpy(LocalBuffer, B.Data, kHeaderSize); - u32 BlockSize = 0; - u32 BlockNumber = 0; - u64 ThreadId = 0; - internal_memcpy(&BlockSize, LocalBuffer, sizeof(u32)); - internal_memcpy(&BlockNumber, LocalBuffer + sizeof(u32), sizeof(u32)); - internal_memcpy(&ThreadId, LocalBuffer + (2 * sizeof(u32)), sizeof(u64)); - ASSERT_NE(BlockSize, 0u); - ASSERT_GE(BlockNumber, 0u); - ASSERT_NE(ThreadId, 0u); -} - -std::tuple<u32, u32, u64> ParseBlockHeader(XRayBuffer B) { - char LocalBuffer[kHeaderSize] = {}; - internal_memcpy(LocalBuffer, B.Data, kHeaderSize); - u32 BlockSize = 0; - u32 BlockNumber = 0; - u64 ThreadId = 0; - internal_memcpy(&BlockSize, LocalBuffer, sizeof(u32)); - internal_memcpy(&BlockNumber, LocalBuffer + sizeof(u32), sizeof(u32)); - internal_memcpy(&ThreadId, LocalBuffer + (2 * sizeof(u32)), sizeof(u64)); - return std::make_tuple(BlockSize, BlockNumber, ThreadId); -} - -struct Profile { - int64_t CallCount; - int64_t CumulativeLocalTime; - std::vector<int32_t> Path; -}; - -std::tuple<Profile, const char *> ParseProfile(const char *P) { - Profile Result; - // Read the path first, until we find a sentinel 0. - int32_t F; - do { - internal_memcpy(&F, P, sizeof(int32_t)); - P += sizeof(int32_t); - Result.Path.push_back(F); - } while (F != 0); - - // Then read the CallCount. - internal_memcpy(&Result.CallCount, P, sizeof(int64_t)); - P += sizeof(int64_t); - - // Then read the CumulativeLocalTime. - internal_memcpy(&Result.CumulativeLocalTime, P, sizeof(int64_t)); - P += sizeof(int64_t); - return std::make_tuple(std::move(Result), P); -} - -TEST(profileCollectorServiceTest, PostSerializeCollect) { - profilingFlags()->setDefaults(); - bool Success = false; - BufferQueue BQ(profilingFlags()->per_thread_allocator_max, - profilingFlags()->buffers_max, Success); - ASSERT_EQ(Success, true); - FunctionCallTrie::Allocators::Buffers Buffers; - ASSERT_EQ(BQ.getBuffer(Buffers.NodeBuffer), BufferQueue::ErrorCode::Ok); - ASSERT_EQ(BQ.getBuffer(Buffers.RootsBuffer), BufferQueue::ErrorCode::Ok); - ASSERT_EQ(BQ.getBuffer(Buffers.ShadowStackBuffer), - BufferQueue::ErrorCode::Ok); - ASSERT_EQ(BQ.getBuffer(Buffers.NodeIdPairBuffer), BufferQueue::ErrorCode::Ok); - auto Allocators = FunctionCallTrie::InitAllocatorsFromBuffers(Buffers); - FunctionCallTrie T(Allocators); - - // Populate the trie with some data. - T.enterFunction(1, 1, 0); - T.enterFunction(2, 2, 0); - T.exitFunction(2, 3, 0); - T.exitFunction(1, 4, 0); - - // Reset the collector data structures. - profileCollectorService::reset(); - - // Then we post the data to the global profile collector service. - profileCollectorService::post(&BQ, std::move(T), std::move(Allocators), - std::move(Buffers), 1); - - // Then we serialize the data. - profileCollectorService::serialize(); - - // Then we go through two buffers to see whether we're getting the data we - // expect. The first block must always be as large as a file header, which - // will have a fixed size. - auto B = profileCollectorService::nextBuffer({nullptr, 0}); - ValidateFileHeaderBlock(B); - - B = profileCollectorService::nextBuffer(B); - ValidateBlock(B); - u32 BlockSize; - u32 BlockNum; - u64 ThreadId; - std::tie(BlockSize, BlockNum, ThreadId) = ParseBlockHeader(B); - - // We look at the serialized buffer to see whether the Trie we're expecting - // to see is there. - auto DStart = static_cast<const char *>(B.Data) + kHeaderSize; - std::vector<char> D(DStart, DStart + BlockSize); - B = profileCollectorService::nextBuffer(B); - ASSERT_EQ(B.Data, nullptr); - ASSERT_EQ(B.Size, 0u); - - Profile Profile1, Profile2; - auto P = static_cast<const char *>(D.data()); - std::tie(Profile1, P) = ParseProfile(P); - std::tie(Profile2, P) = ParseProfile(P); - - ASSERT_NE(Profile1.Path.size(), Profile2.Path.size()); - auto &P1 = Profile1.Path.size() < Profile2.Path.size() ? Profile2 : Profile1; - auto &P2 = Profile1.Path.size() < Profile2.Path.size() ? Profile1 : Profile2; - std::vector<int32_t> P1Expected = {2, 1, 0}; - std::vector<int32_t> P2Expected = {1, 0}; - ASSERT_EQ(P1.Path.size(), P1Expected.size()); - ASSERT_EQ(P2.Path.size(), P2Expected.size()); - ASSERT_EQ(P1.Path, P1Expected); - ASSERT_EQ(P2.Path, P2Expected); -} - -// We break out a function that will be run in multiple threads, one that will -// use a thread local allocator, and will post the FunctionCallTrie to the -// profileCollectorService. This simulates what the threads being profiled would -// be doing anyway, but through the XRay logging implementation. -void threadProcessing() { - static bool Success = false; - static BufferQueue BQ(profilingFlags()->per_thread_allocator_max, - profilingFlags()->buffers_max, Success); - thread_local FunctionCallTrie::Allocators::Buffers Buffers = [] { - FunctionCallTrie::Allocators::Buffers B; - BQ.getBuffer(B.NodeBuffer); - BQ.getBuffer(B.RootsBuffer); - BQ.getBuffer(B.ShadowStackBuffer); - BQ.getBuffer(B.NodeIdPairBuffer); - return B; - }(); - - thread_local auto Allocators = - FunctionCallTrie::InitAllocatorsFromBuffers(Buffers); - - FunctionCallTrie T(Allocators); - - T.enterFunction(1, 1, 0); - T.enterFunction(2, 2, 0); - T.exitFunction(2, 3, 0); - T.exitFunction(1, 4, 0); - - profileCollectorService::post(&BQ, std::move(T), std::move(Allocators), - std::move(Buffers), GetTid()); -} - -TEST(profileCollectorServiceTest, PostSerializeCollectMultipleThread) { - profilingFlags()->setDefaults(); - - profileCollectorService::reset(); - - std::thread t1(threadProcessing); - std::thread t2(threadProcessing); - - t1.join(); - t2.join(); - - // At this point, t1 and t2 are already done with what they were doing. - profileCollectorService::serialize(); - - // Ensure that we see two buffers. - auto B = profileCollectorService::nextBuffer({nullptr, 0}); - ValidateFileHeaderBlock(B); - - B = profileCollectorService::nextBuffer(B); - ValidateBlock(B); - - B = profileCollectorService::nextBuffer(B); - ValidateBlock(B); -} - -} // namespace -} // namespace __xray diff --git a/lib/xray/tests/unit/segmented_array_test.cc b/lib/xray/tests/unit/segmented_array_test.cc deleted file mode 100644 index 46aeb88f71b4c..0000000000000 --- a/lib/xray/tests/unit/segmented_array_test.cc +++ /dev/null @@ -1,349 +0,0 @@ -#include "test_helpers.h" -#include "xray_segmented_array.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include <algorithm> -#include <numeric> -#include <vector> - -namespace __xray { -namespace { - -using ::testing::SizeIs; - -struct TestData { - s64 First; - s64 Second; - - // Need a constructor for emplace operations. - TestData(s64 F, s64 S) : First(F), Second(S) {} -}; - -void PrintTo(const TestData &D, std::ostream *OS) { - *OS << "{ " << D.First << ", " << D.Second << " }"; -} - -TEST(SegmentedArrayTest, ConstructWithAllocators) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 4); - Array<TestData> Data(A); - (void)Data; -} - -TEST(SegmentedArrayTest, ConstructAndPopulate) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 4); - Array<TestData> data(A); - ASSERT_NE(data.Append(TestData{0, 0}), nullptr); - ASSERT_NE(data.Append(TestData{1, 1}), nullptr); - ASSERT_EQ(data.size(), 2u); -} - -TEST(SegmentedArrayTest, ConstructPopulateAndLookup) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 4); - Array<TestData> data(A); - ASSERT_NE(data.Append(TestData{0, 1}), nullptr); - ASSERT_EQ(data.size(), 1u); - ASSERT_EQ(data[0].First, 0); - ASSERT_EQ(data[0].Second, 1); -} - -TEST(SegmentedArrayTest, PopulateWithMoreElements) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 24); - Array<TestData> data(A); - static const auto kMaxElements = 100u; - for (auto I = 0u; I < kMaxElements; ++I) { - ASSERT_NE(data.Append(TestData{I, I + 1}), nullptr); - } - ASSERT_EQ(data.size(), kMaxElements); - for (auto I = 0u; I < kMaxElements; ++I) { - ASSERT_EQ(data[I].First, I); - ASSERT_EQ(data[I].Second, I + 1); - } -} - -TEST(SegmentedArrayTest, AppendEmplace) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 4); - Array<TestData> data(A); - ASSERT_NE(data.AppendEmplace(1, 1), nullptr); - ASSERT_EQ(data[0].First, 1); - ASSERT_EQ(data[0].Second, 1); -} - -TEST(SegmentedArrayTest, AppendAndTrim) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 4); - Array<TestData> data(A); - ASSERT_NE(data.AppendEmplace(1, 1), nullptr); - ASSERT_EQ(data.size(), 1u); - data.trim(1); - ASSERT_EQ(data.size(), 0u); - ASSERT_TRUE(data.empty()); -} - -TEST(SegmentedArrayTest, IteratorAdvance) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 4); - Array<TestData> data(A); - ASSERT_TRUE(data.empty()); - ASSERT_EQ(data.begin(), data.end()); - auto I0 = data.begin(); - ASSERT_EQ(I0++, data.begin()); - ASSERT_NE(I0, data.begin()); - for (const auto &D : data) { - (void)D; - FAIL(); - } - ASSERT_NE(data.AppendEmplace(1, 1), nullptr); - ASSERT_EQ(data.size(), 1u); - ASSERT_NE(data.begin(), data.end()); - auto &D0 = *data.begin(); - ASSERT_EQ(D0.First, 1); - ASSERT_EQ(D0.Second, 1); -} - -TEST(SegmentedArrayTest, IteratorRetreat) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 4); - Array<TestData> data(A); - ASSERT_TRUE(data.empty()); - ASSERT_EQ(data.begin(), data.end()); - ASSERT_NE(data.AppendEmplace(1, 1), nullptr); - ASSERT_EQ(data.size(), 1u); - ASSERT_NE(data.begin(), data.end()); - auto &D0 = *data.begin(); - ASSERT_EQ(D0.First, 1); - ASSERT_EQ(D0.Second, 1); - - auto I0 = data.end(); - ASSERT_EQ(I0--, data.end()); - ASSERT_NE(I0, data.end()); - ASSERT_EQ(I0, data.begin()); - ASSERT_EQ(I0->First, 1); - ASSERT_EQ(I0->Second, 1); -} - -TEST(SegmentedArrayTest, IteratorTrimBehaviour) { - using AllocatorType = typename Array<TestData>::AllocatorType; - AllocatorType A(1 << 20); - Array<TestData> Data(A); - ASSERT_TRUE(Data.empty()); - auto I0Begin = Data.begin(), I0End = Data.end(); - // Add enough elements in Data to have more than one chunk. - constexpr auto Segment = Array<TestData>::SegmentSize; - constexpr auto SegmentX2 = Segment * 2; - for (auto i = SegmentX2; i > 0u; --i) { - Data.AppendEmplace(static_cast<s64>(i), static_cast<s64>(i)); - } - ASSERT_EQ(Data.size(), SegmentX2); - { - auto &Back = Data.back(); - ASSERT_EQ(Back.First, 1); - ASSERT_EQ(Back.Second, 1); - } - - // Trim one chunk's elements worth. - Data.trim(Segment); - ASSERT_EQ(Data.size(), Segment); - - // Check that we are still able to access 'back' properly. - { - auto &Back = Data.back(); - ASSERT_EQ(Back.First, static_cast<s64>(Segment + 1)); - ASSERT_EQ(Back.Second, static_cast<s64>(Segment + 1)); - } - - // Then trim until it's empty. - Data.trim(Segment); - ASSERT_TRUE(Data.empty()); - - // Here our iterators should be the same. - auto I1Begin = Data.begin(), I1End = Data.end(); - EXPECT_EQ(I0Begin, I1Begin); - EXPECT_EQ(I0End, I1End); - - // Then we ensure that adding elements back works just fine. - for (auto i = SegmentX2; i > 0u; --i) { - Data.AppendEmplace(static_cast<s64>(i), static_cast<s64>(i)); - } - EXPECT_EQ(Data.size(), SegmentX2); -} - -TEST(SegmentedArrayTest, HandleExhaustedAllocator) { - using AllocatorType = typename Array<TestData>::AllocatorType; - constexpr auto Segment = Array<TestData>::SegmentSize; - constexpr auto MaxElements = Array<TestData>::ElementsPerSegment; - AllocatorType A(Segment); - Array<TestData> Data(A); - for (auto i = MaxElements; i > 0u; --i) - EXPECT_NE(Data.AppendEmplace(static_cast<s64>(i), static_cast<s64>(i)), - nullptr); - EXPECT_EQ(Data.AppendEmplace(0, 0), nullptr); - EXPECT_THAT(Data, SizeIs(MaxElements)); - - // Trimming more elements than there are in the container should be fine. - Data.trim(MaxElements + 1); - EXPECT_THAT(Data, SizeIs(0u)); -} - -struct ShadowStackEntry { - uint64_t EntryTSC = 0; - uint64_t *NodePtr = nullptr; - ShadowStackEntry(uint64_t T, uint64_t *N) : EntryTSC(T), NodePtr(N) {} -}; - -TEST(SegmentedArrayTest, SimulateStackBehaviour) { - using AllocatorType = typename Array<ShadowStackEntry>::AllocatorType; - AllocatorType A(1 << 10); - Array<ShadowStackEntry> Data(A); - static uint64_t Dummy = 0; - constexpr uint64_t Max = 9; - - for (uint64_t i = 0; i < Max; ++i) { - auto P = Data.Append({i, &Dummy}); - ASSERT_NE(P, nullptr); - ASSERT_EQ(P->NodePtr, &Dummy); - auto &Back = Data.back(); - ASSERT_EQ(Back.NodePtr, &Dummy); - ASSERT_EQ(Back.EntryTSC, i); - } - - // Simulate a stack by checking the data from the end as we're trimming. - auto Counter = Max; - ASSERT_EQ(Data.size(), size_t(Max)); - while (!Data.empty()) { - const auto &Top = Data.back(); - uint64_t *TopNode = Top.NodePtr; - EXPECT_EQ(TopNode, &Dummy) << "Counter = " << Counter; - Data.trim(1); - --Counter; - ASSERT_EQ(Data.size(), size_t(Counter)); - } -} - -TEST(SegmentedArrayTest, PlacementNewOnAlignedStorage) { - using AllocatorType = typename Array<ShadowStackEntry>::AllocatorType; - typename std::aligned_storage<sizeof(AllocatorType), - alignof(AllocatorType)>::type AllocatorStorage; - new (&AllocatorStorage) AllocatorType(1 << 10); - auto *A = reinterpret_cast<AllocatorType *>(&AllocatorStorage); - typename std::aligned_storage<sizeof(Array<ShadowStackEntry>), - alignof(Array<ShadowStackEntry>)>::type - ArrayStorage; - new (&ArrayStorage) Array<ShadowStackEntry>(*A); - auto *Data = reinterpret_cast<Array<ShadowStackEntry> *>(&ArrayStorage); - - static uint64_t Dummy = 0; - constexpr uint64_t Max = 9; - - for (uint64_t i = 0; i < Max; ++i) { - auto P = Data->Append({i, &Dummy}); - ASSERT_NE(P, nullptr); - ASSERT_EQ(P->NodePtr, &Dummy); - auto &Back = Data->back(); - ASSERT_EQ(Back.NodePtr, &Dummy); - ASSERT_EQ(Back.EntryTSC, i); - } - - // Simulate a stack by checking the data from the end as we're trimming. - auto Counter = Max; - ASSERT_EQ(Data->size(), size_t(Max)); - while (!Data->empty()) { - const auto &Top = Data->back(); - uint64_t *TopNode = Top.NodePtr; - EXPECT_EQ(TopNode, &Dummy) << "Counter = " << Counter; - Data->trim(1); - --Counter; - ASSERT_EQ(Data->size(), size_t(Counter)); - } - - // Once the stack is exhausted, we re-use the storage. - for (uint64_t i = 0; i < Max; ++i) { - auto P = Data->Append({i, &Dummy}); - ASSERT_NE(P, nullptr); - ASSERT_EQ(P->NodePtr, &Dummy); - auto &Back = Data->back(); - ASSERT_EQ(Back.NodePtr, &Dummy); - ASSERT_EQ(Back.EntryTSC, i); - } - - // We re-initialize the storage, by calling the destructor and - // placement-new'ing again. - Data->~Array(); - A->~AllocatorType(); - new (A) AllocatorType(1 << 10); - new (Data) Array<ShadowStackEntry>(*A); - - // Then re-do the test. - for (uint64_t i = 0; i < Max; ++i) { - auto P = Data->Append({i, &Dummy}); - ASSERT_NE(P, nullptr); - ASSERT_EQ(P->NodePtr, &Dummy); - auto &Back = Data->back(); - ASSERT_EQ(Back.NodePtr, &Dummy); - ASSERT_EQ(Back.EntryTSC, i); - } - - // Simulate a stack by checking the data from the end as we're trimming. - Counter = Max; - ASSERT_EQ(Data->size(), size_t(Max)); - while (!Data->empty()) { - const auto &Top = Data->back(); - uint64_t *TopNode = Top.NodePtr; - EXPECT_EQ(TopNode, &Dummy) << "Counter = " << Counter; - Data->trim(1); - --Counter; - ASSERT_EQ(Data->size(), size_t(Counter)); - } - - // Once the stack is exhausted, we re-use the storage. - for (uint64_t i = 0; i < Max; ++i) { - auto P = Data->Append({i, &Dummy}); - ASSERT_NE(P, nullptr); - ASSERT_EQ(P->NodePtr, &Dummy); - auto &Back = Data->back(); - ASSERT_EQ(Back.NodePtr, &Dummy); - ASSERT_EQ(Back.EntryTSC, i); - } -} - -TEST(SegmentedArrayTest, ArrayOfPointersIteratorAccess) { - using PtrArray = Array<int *>; - PtrArray::AllocatorType Alloc(16384); - Array<int *> A(Alloc); - static constexpr size_t Count = 100; - std::vector<int> Integers(Count); - std::iota(Integers.begin(), Integers.end(), 0); - for (auto &I : Integers) - ASSERT_NE(A.Append(&I), nullptr); - int V = 0; - ASSERT_EQ(A.size(), Count); - for (auto P : A) { - ASSERT_NE(P, nullptr); - ASSERT_EQ(*P, V++); - } -} - -TEST(SegmentedArrayTest, ArrayOfPointersIteratorAccessExhaustion) { - using PtrArray = Array<int *>; - PtrArray::AllocatorType Alloc(4096); - Array<int *> A(Alloc); - static constexpr size_t Count = 1000; - std::vector<int> Integers(Count); - std::iota(Integers.begin(), Integers.end(), 0); - for (auto &I : Integers) - if (A.Append(&I) == nullptr) - break; - int V = 0; - ASSERT_LT(A.size(), Count); - for (auto P : A) { - ASSERT_NE(P, nullptr); - ASSERT_EQ(*P, V++); - } -} - -} // namespace -} // namespace __xray diff --git a/lib/xray/tests/unit/test_helpers.cc b/lib/xray/tests/unit/test_helpers.cc deleted file mode 100644 index 284492d1050b4..0000000000000 --- a/lib/xray/tests/unit/test_helpers.cc +++ /dev/null @@ -1,95 +0,0 @@ -//===-- test_helpers.cc ---------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// -#include "test_helpers.h" -#include "xray/xray_records.h" -#include "xray_buffer_queue.h" -#include "xray_fdr_log_writer.h" -#include <type_traits> - -// TODO: Move these to llvm/include/Testing/XRay/... -namespace llvm { -namespace xray { - -std::string RecordTypeAsString(RecordTypes T) { - switch (T) { - case RecordTypes::ENTER: - return "llvm::xray::RecordTypes::ENTER"; - case RecordTypes::EXIT: - return "llvm::xray::RecordTypes::EXIT"; - case RecordTypes::TAIL_EXIT: - return "llvm::xray::RecordTypes::TAIL_EXIT"; - case RecordTypes::ENTER_ARG: - return "llvm::xray::RecordTypes::ENTER_ARG"; - case RecordTypes::CUSTOM_EVENT: - return "llvm::xray::RecordTypes::CUSTOM_EVENT"; - case RecordTypes::TYPED_EVENT: - return "llvm::xray::RecordTypes::TYPED_EVENT"; - } - return "<UNKNOWN>"; -} - -void PrintTo(RecordTypes T, std::ostream *OS) { - *OS << RecordTypeAsString(T); -} - -void PrintTo(const XRayRecord &R, std::ostream *OS) { - *OS << "XRayRecord { CPU = " << R.CPU - << "; Type = " << RecordTypeAsString(R.Type) << "; FuncId = " << R.FuncId - << "; TSC = " << R.TSC << "; TId = " << R.TId << "; PId = " << R.PId - << " Args = " << ::testing::PrintToString(R.CallArgs) << " }"; -} - -void PrintTo(const Trace &T, std::ostream *OS) { - const auto &H = T.getFileHeader(); - *OS << "XRay Trace:\nHeader: { Version = " << H.Version - << "; Type = " << H.Type - << "; ConstantTSC = " << ::testing::PrintToString(H.ConstantTSC) - << "; NonstopTSC = " << ::testing::PrintToString(H.NonstopTSC) - << "; CycleFrequency = " << H.CycleFrequency << "; FreeFormData = '" - << ::testing::PrintToString(H.FreeFormData) << "' }\n"; - for (const auto &R : T) { - PrintTo(R, OS); - *OS << "\n"; - } -} - -} // namespace xray -} // namespace llvm - -namespace __xray { - -std::string serialize(BufferQueue &Buffers, int32_t Version) { - std::string Serialized; - std::aligned_storage<sizeof(XRayFileHeader), alignof(XRayFileHeader)>::type - HeaderStorage; - auto *Header = reinterpret_cast<XRayFileHeader *>(&HeaderStorage); - new (Header) XRayFileHeader(); - Header->Version = Version; - Header->Type = FileTypes::FDR_LOG; - Header->CycleFrequency = 3e9; - Header->ConstantTSC = 1; - Header->NonstopTSC = 1; - Serialized.append(reinterpret_cast<const char *>(&HeaderStorage), - sizeof(XRayFileHeader)); - Buffers.apply([&](const BufferQueue::Buffer &B) { - auto Size = atomic_load_relaxed(B.Extents); - auto Extents = - createMetadataRecord<MetadataRecord::RecordKinds::BufferExtents>(Size); - Serialized.append(reinterpret_cast<const char *>(&Extents), - sizeof(Extents)); - Serialized.append(reinterpret_cast<const char *>(B.Data), Size); - }); - return Serialized; -} - -} // namespace __xray diff --git a/lib/xray/tests/unit/test_helpers.h b/lib/xray/tests/unit/test_helpers.h deleted file mode 100644 index ff0311e9bd30f..0000000000000 --- a/lib/xray/tests/unit/test_helpers.h +++ /dev/null @@ -1,78 +0,0 @@ -//===-- test_helpers.h ----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// -#ifndef COMPILER_RT_LIB_XRAY_TESTS_TEST_HELPERS_H_ -#define COMPILER_RT_LIB_XRAY_TESTS_TEST_HELPERS_H_ - -#include "xray_buffer_queue.h" -#include "xray_segmented_array.h" -#include "llvm/XRay/Trace.h" -#include "llvm/XRay/XRayRecord.h" -#include "gmock/gmock.h" - -// TODO: Move these to llvm/include/Testing/XRay/... -namespace llvm { -namespace xray { - -std::string RecordTypeAsString(RecordTypes T); -void PrintTo(RecordTypes T, std::ostream *OS); -void PrintTo(const XRayRecord &R, std::ostream *OS); -void PrintTo(const Trace &T, std::ostream *OS); - -namespace testing { - -MATCHER_P(FuncId, F, "") { - *result_listener << "where the function id is " << F; - return arg.FuncId == F; -} - -MATCHER_P(RecordType, T, "") { - *result_listener << "where the record type is " << RecordTypeAsString(T); - return arg.Type == T; -} - -MATCHER_P(HasArg, A, "") { - *result_listener << "where args contains " << A; - return !arg.CallArgs.empty() && - std::any_of(arg.CallArgs.begin(), arg.CallArgs.end(), - [this](decltype(A) V) { return V == A; }); -} - -MATCHER_P(TSCIs, M, std::string("TSC is ") + ::testing::PrintToString(M)) { - return ::testing::Matcher<decltype(arg.TSC)>(M).MatchAndExplain( - arg.TSC, result_listener); -} - -} // namespace testing -} // namespace xray -} // namespace llvm - -namespace __xray { - -std::string serialize(BufferQueue &Buffers, int32_t Version); - -template <class T> void PrintTo(const Array<T> &A, std::ostream *OS) { - *OS << "["; - bool first = true; - for (const auto &E : A) { - if (!first) { - *OS << ", "; - } - PrintTo(E, OS); - first = false; - } - *OS << "]"; -} - -} // namespace __xray - -#endif // COMPILER_RT_LIB_XRAY_TESTS_TEST_HELPERS_H_ diff --git a/lib/xray/tests/unit/xray_unit_test_main.cc b/lib/xray/tests/unit/xray_unit_test_main.cc deleted file mode 100644 index 27d17527dd5bc..0000000000000 --- a/lib/xray/tests/unit/xray_unit_test_main.cc +++ /dev/null @@ -1,18 +0,0 @@ -//===-- xray_unit_test_main.cc --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of XRay, a function call tracing system. -// -//===----------------------------------------------------------------------===// -#include "gtest/gtest.h" - -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} |