Remove upstream files and directories from vendor/compiler-rt/dist that

we do not use.  This saves on repository space, and reduces the number
of tree conflicts when merging.
This commit is contained in:
Dimitry Andric 2019-08-20 18:00:15 +00:00
parent 0646903fc1
commit 63714eb580
2292 changed files with 0 additions and 313172 deletions

View File

@ -1,4 +0,0 @@
{
"repository.callsign" : "CRT",
"conduit_uri" : "https://reviews.llvm.org/"
}

6
.gitignore vendored
View File

@ -1,6 +0,0 @@
*~
darwin_fat
clang_darwin
multi_arch
*.sw?
*.pyc

View File

@ -1,474 +0,0 @@
# CMake build for CompilerRT.
#
# An important constraint of the build is that it only produces libraries
# based on the ability of the host toolchain to target various platforms.
cmake_minimum_required(VERSION 3.4.3)
# Check if compiler-rt is built as a standalone project.
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR COMPILER_RT_STANDALONE_BUILD)
project(CompilerRT C CXX ASM)
set(COMPILER_RT_STANDALONE_BUILD TRUE)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
endif()
# Add path for custom compiler-rt modules.
list(INSERT CMAKE_MODULE_PATH 0
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
)
if(CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CFG_RESOLVED_INTDIR "${CMAKE_CFG_INTDIR}/")
else()
set(CMAKE_CFG_RESOLVED_INTDIR "")
endif()
include(base-config-ix)
include(CompilerRTUtils)
option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON)
mark_as_advanced(COMPILER_RT_BUILD_BUILTINS)
option(COMPILER_RT_BUILD_SANITIZERS "Build sanitizers" ON)
mark_as_advanced(COMPILER_RT_BUILD_SANITIZERS)
option(COMPILER_RT_BUILD_XRAY "Build xray" ON)
mark_as_advanced(COMPILER_RT_BUILD_XRAY)
option(COMPILER_RT_BUILD_LIBFUZZER "Build libFuzzer" ON)
mark_as_advanced(COMPILER_RT_BUILD_LIBFUZZER)
option(COMPILER_RT_BUILD_PROFILE "Build profile runtime" ON)
mark_as_advanced(COMPILER_RT_BUILD_PROFILE)
option(COMPILER_RT_BUILD_XRAY_NO_PREINIT "Build xray with no preinit patching" OFF)
mark_as_advanced(COMPILER_RT_BUILD_XRAY_NO_PREINIT)
set(COMPILER_RT_ASAN_SHADOW_SCALE ""
CACHE STRING "Override the shadow scale to be used in ASan runtime")
if (NOT COMPILER_RT_ASAN_SHADOW_SCALE STREQUAL "")
# Check that the shadow scale value is valid.
if (NOT (COMPILER_RT_ASAN_SHADOW_SCALE GREATER -1 AND
COMPILER_RT_ASAN_SHADOW_SCALE LESS 8))
message(FATAL_ERROR "
Invalid ASan Shadow Scale '${COMPILER_RT_ASAN_SHADOW_SCALE}'.")
endif()
set(COMPILER_RT_ASAN_SHADOW_SCALE_LLVM_FLAG
-mllvm -asan-mapping-scale=${COMPILER_RT_ASAN_SHADOW_SCALE})
set(COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION
ASAN_SHADOW_SCALE=${COMPILER_RT_ASAN_SHADOW_SCALE})
set(COMPILER_RT_ASAN_SHADOW_SCALE_FLAG
-D${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION})
endif()
set(COMPILER_RT_HWASAN_WITH_INTERCEPTORS ON CACHE BOOLEAN
"Enable libc interceptors in HWASan (testing mode)")
set(COMPILER_RT_BAREMETAL_BUILD OFF CACHE BOOLEAN
"Build for a bare-metal target.")
if (COMPILER_RT_STANDALONE_BUILD)
load_llvm_config()
if (TARGET intrinsics_gen)
# Loading the llvm config causes this target to be imported so place it
# under the appropriate folder in an IDE.
set_target_properties(intrinsics_gen PROPERTIES FOLDER "Compiler-RT Misc")
endif()
# Find Python interpreter.
set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5)
include(FindPythonInterp)
if(NOT PYTHONINTERP_FOUND)
message(FATAL_ERROR "
Unable to find Python interpreter required testing. Please install Python
or specify the PYTHON_EXECUTABLE CMake variable.")
endif()
# Ensure that fat libraries are built correctly on Darwin
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
if(NOT CMAKE_LIBTOOL)
find_program(CMAKE_XCRUN
NAMES
xcrun)
if(CMAKE_XCRUN)
execute_process(COMMAND
${CMAKE_XCRUN} -find libtool
OUTPUT_VARIABLE
CMAKE_LIBTOOL
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if(NOT CMAKE_LIBTOOL OR NOT EXISTS CMAKE_LIBTOOL)
find_program(CMAKE_LIBTOOL
NAMES
libtool)
endif()
endif()
get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
if(CMAKE_LIBTOOL)
set(CMAKE_LIBTOOL ${CMAKE_LIBTOOL} CACHE PATH "libtool executable")
message(STATUS "Found libtool - ${CMAKE_LIBTOOL}")
execute_process(COMMAND
${CMAKE_LIBTOOL} -V
OUTPUT_VARIABLE
LIBTOOL_V_OUTPUT
OUTPUT_STRIP_TRAILING_WHITESPACE)
if("${LIBTOOL_V_OUTPUT}" MATCHES ".*cctools-([0-9]+).*")
string(REGEX REPLACE ".*cctools-([0-9]+).*" "\\1" LIBTOOL_VERSION ${LIBTOOL_V_OUTPUT})
if(NOT LIBTOOL_VERSION VERSION_LESS "862")
set(LIBTOOL_NO_WARNING_FLAG "-no_warning_for_no_symbols")
endif()
endif()
foreach(lang ${languages})
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "\"${CMAKE_LIBTOOL}\" -static ${LIBTOOL_NO_WARNING_FLAG} -o <TARGET> <LINK_FLAGS> <OBJECTS>")
endforeach()
endif()
# Workaround SIP :-(
if(DYLD_LIBRARY_PATH)
set(dyld_envar "DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}")
foreach(lang ${languages})
foreach(cmd ${CMAKE_${lang}_CREATE_STATIC_LIBRARY})
list(APPEND CMAKE_${lang}_CREATE_STATIC_LIBRARY_NEW "${dyld_envar} ${cmd}")
endforeach()
endforeach()
endif()
endif()
# Define default arguments to lit.
set(LIT_ARGS_DEFAULT "-sv")
if (MSVC OR XCODE)
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
endif()
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
set(LLVM_LIT_OUTPUT_DIR "${COMPILER_RT_EXEC_OUTPUT_DIR}")
endif()
construct_compiler_rt_default_triple()
if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*hf$")
if (${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "^arm")
set(COMPILER_RT_DEFAULT_TARGET_ARCH "armhf")
endif()
endif()
if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*")
set(ANDROID 1)
endif()
pythonize_bool(ANDROID)
set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
pythonize_bool(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
# We support running instrumented tests when we're not cross compiling
# and target a UNIX-like system or Windows.
# We can run tests on Android even when we are cross-compiling.
if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR WIN32)) OR ANDROID
OR COMPILER_RT_EMULATOR)
option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON)
else()
option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF)
endif()
option(COMPILER_RT_DEBUG "Build runtimes with full debug info" OFF)
option(COMPILER_RT_EXTERNALIZE_DEBUGINFO
"Generate dSYM files and strip executables and libraries (Darwin Only)" OFF)
# COMPILER_RT_DEBUG_PYBOOL is used by lit.common.configured.in.
pythonize_bool(COMPILER_RT_DEBUG)
if(APPLE AND SANITIZER_MIN_OSX_VERSION AND SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.9")
# Mac OS X prior to 10.9 had problems with exporting symbols from
# libc++/libc++abi.
set(cxxabi_supported OFF)
else()
set(cxxabi_supported ON)
endif()
option(SANITIZER_ALLOW_CXXABI "Allow use of C++ ABI details in ubsan" ON)
set(SANITIZE_CAN_USE_CXXABI OFF)
if (cxxabi_supported AND SANITIZER_ALLOW_CXXABI)
set(SANITIZER_CAN_USE_CXXABI ON)
endif()
pythonize_bool(SANITIZER_CAN_USE_CXXABI)
set(SANITIZER_CXX_ABI "default" CACHE STRING
"Specify C++ ABI library to use.")
set(CXXABIS none default libstdc++ libc++)
set_property(CACHE SANITIZER_CXX_ABI PROPERTY STRINGS ;${CXXABIS})
if (SANITIZER_CXX_ABI STREQUAL "default")
if (APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(SANITIZER_CXX_ABI_LIBNAME "libc++")
set(SANITIZER_CXX_ABI_SYSTEM 1)
elseif (FUCHSIA)
set(SANITIZER_CXX_ABI_LIBNAME "libc++")
set(SANITIZER_CXX_ABI_INTREE 1)
else()
set(SANITIZER_CXX_ABI_LIBNAME "libstdc++")
set(SANITIZER_CXX_ABI_SYSTEM 1)
endif()
else()
set(SANITIZER_CXX_ABI_LIBNAME "${SANITIZER_CXX_ABI}")
set(SANITIZER_CXX_ABI_SYSTEM 1)
endif()
set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY OFF)
if (FUCHSIA)
set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY ON)
endif()
option(COMPILER_RT_USE_BUILTINS_LIBRARY
"Use compiler-rt builtins instead of libgcc" ${DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY})
include(config-ix)
#================================
# Setup Compiler Flags
#================================
if(MSVC)
# Override any existing /W flags with /W4. This is what LLVM does. Failing to
# remove other /W[0-4] flags will result in a warning about overriding a
# previous flag.
if (COMPILER_RT_HAS_W4_FLAG)
string(REGEX REPLACE " /W[0-4]" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REGEX REPLACE " /W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
append_string_if(COMPILER_RT_HAS_W4_FLAG /W4 CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
endif()
else()
append_string_if(COMPILER_RT_HAS_WALL_FLAG -Wall CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
endif()
if(COMPILER_RT_ENABLE_WERROR)
append_string_if(COMPILER_RT_HAS_WERROR_FLAG -Werror CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
append_string_if(COMPILER_RT_HAS_WX_FLAG /WX CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
endif()
append_string_if(COMPILER_RT_HAS_STD_CXX11_FLAG -std=c++11 CMAKE_CXX_FLAGS)
# Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP.
if(NOT COMPILER_RT_HAS_FUNC_SYMBOL)
add_definitions(-D__func__=__FUNCTION__)
endif()
# Provide some common commmandline flags for Sanitizer runtimes.
if(NOT WIN32)
append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC SANITIZER_COMMON_CFLAGS)
endif()
append_list_if(COMPILER_RT_HAS_FNO_BUILTIN_FLAG -fno-builtin SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG -fno-exceptions SANITIZER_COMMON_CFLAGS)
if(NOT COMPILER_RT_DEBUG AND NOT APPLE)
append_list_if(COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG -fomit-frame-pointer SANITIZER_COMMON_CFLAGS)
endif()
append_list_if(COMPILER_RT_HAS_FUNWIND_TABLES_FLAG -funwind-tables SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG -fno-sanitize=safe-stack SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS)
if(NOT COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG)
append_list_if(COMPILER_RT_HAS_FVISIBILITY_INLINES_HIDDEN_FLAG -fvisibility-inlines-hidden SANITIZER_COMMON_CFLAGS)
endif()
append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)
# The following is a workaround for powerpc64le. This is the only architecture
# that requires -fno-function-sections to work properly. If lacking, the ASan
# Linux test function-sections-are-bad.cc fails with the following error:
# 'undefined symbol: __sanitizer_unaligned_load32'.
if(DEFINED TARGET_powerpc64le_CFLAGS)
append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections TARGET_powerpc64le_CFLAGS)
endif()
if(MSVC)
# Replace the /M[DT][d] flags with /MT, and strip any definitions of _DEBUG,
# which cause definition mismatches at link time.
# FIXME: In fact, sanitizers should support both /MT and /MD, see PR20214.
if(COMPILER_RT_HAS_MT_FLAG)
foreach(flag_var
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
string(REGEX REPLACE "/M[DT]d" "/MT" ${flag_var} "${${flag_var}}")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
string(REGEX REPLACE "/D_DEBUG" "" ${flag_var} "${${flag_var}}")
endforeach()
endif()
append_list_if(COMPILER_RT_HAS_Oy_FLAG /Oy- SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_GS_FLAG /GS- SANITIZER_COMMON_CFLAGS)
# VS 2015 (version 1900) added support for thread safe static initialization.
# However, ASan interceptors run before CRT initialization, which causes the
# new thread safe code to crash. Disable this feature for now.
if (MSVC_VERSION GREATER 1899 OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
list(APPEND SANITIZER_COMMON_CFLAGS /Zc:threadSafeInit-)
endif()
endif()
append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 SANITIZER_COMMON_CFLAGS)
# If we're using MSVC,
# always respect the optimization flags set by CMAKE_BUILD_TYPE instead.
if (NOT MSVC)
# Build with optimization, unless we're in debug mode.
if(COMPILER_RT_DEBUG)
list(APPEND SANITIZER_COMMON_CFLAGS -O0)
else()
list(APPEND SANITIZER_COMMON_CFLAGS -O3)
endif()
endif()
# Determine if we should restrict stack frame sizes.
# Stack frames on PowerPC and Mips and in debug biuld can be much larger than
# anticipated.
# FIXME: Fix all sanitizers and add -Wframe-larger-than to
# SANITIZER_COMMON_FLAGS
if(COMPILER_RT_HAS_WFRAME_LARGER_THAN_FLAG AND NOT COMPILER_RT_DEBUG
AND NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "powerpc|mips")
set(SANITIZER_LIMIT_FRAME_SIZE TRUE)
else()
set(SANITIZER_LIMIT_FRAME_SIZE FALSE)
endif()
if(FUCHSIA OR UNIX)
set(SANITIZER_USE_SYMBOLS TRUE)
else()
set(SANITIZER_USE_SYMBOLS FALSE)
endif()
# Build sanitizer runtimes with debug info.
if(MSVC)
# Use /Z7 instead of /Zi for the asan runtime. This avoids the LNK4099
# warning from the MS linker complaining that it can't find the 'vc140.pdb'
# file used by our object library compilations.
list(APPEND SANITIZER_COMMON_CFLAGS /Z7)
llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/Z[i7I]" "/Z7")
llvm_replace_compiler_option(CMAKE_CXX_FLAGS_DEBUG "/Z[i7I]" "/Z7")
llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/Z[i7I]" "/Z7")
elseif(COMPILER_RT_HAS_GLINE_TABLES_ONLY_FLAG AND NOT COMPILER_RT_DEBUG)
list(APPEND SANITIZER_COMMON_CFLAGS -gline-tables-only)
elseif(COMPILER_RT_HAS_G_FLAG)
list(APPEND SANITIZER_COMMON_CFLAGS -g)
endif()
if(LLVM_ENABLE_MODULES)
# Sanitizers cannot be built with -fmodules. The interceptors intentionally
# don't include system headers, which is incompatible with modules.
list(APPEND SANITIZER_COMMON_CFLAGS -fno-modules)
endif()
# Turn off several warnings.
append_list_if(COMPILER_RT_HAS_WGNU_FLAG -Wno-gnu SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG -Wno-c99-extensions SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_WNON_VIRTUAL_DTOR_FLAG -Wno-non-virtual-dtor SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_WD4146_FLAG /wd4146 SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_WD4291_FLAG /wd4291 SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_WD4391_FLAG /wd4391 SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_WD4722_FLAG /wd4722 SANITIZER_COMMON_CFLAGS)
append_list_if(COMPILER_RT_HAS_WD4800_FLAG /wd4800 SANITIZER_COMMON_CFLAGS)
append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS)
# Set common link flags.
append_list_if(COMPILER_RT_HAS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS)
if (COMPILER_RT_USE_BUILTINS_LIBRARY)
list(APPEND SANITIZER_COMMON_LINK_LIBS ${COMPILER_RT_BUILTINS_LIBRARY})
string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
else()
if (ANDROID)
append_list_if(COMPILER_RT_HAS_GCC_LIB gcc SANITIZER_COMMON_LINK_LIBS)
else()
append_list_if(COMPILER_RT_HAS_GCC_S_LIB gcc_s SANITIZER_COMMON_LINK_LIBS)
endif()
endif()
append_list_if(COMPILER_RT_HAS_LIBC c SANITIZER_COMMON_LINK_LIBS)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
list(APPEND SANITIZER_COMMON_LINK_FLAGS -Wl,-z,defs,-z,now,-z,relro)
list(APPEND SANITIZER_COMMON_LINK_LIBS zircon)
endif()
if (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libc++")
if (SANITIZER_CXX_ABI_INTREE)
if (NOT LIBCXXABI_ENABLE_STATIC_UNWINDER AND (TARGET unwind_shared OR HAVE_LIBUNWIND))
list(APPEND SANITIZER_CXX_ABI_LIBRARY unwind_shared)
elseif (LIBCXXABI_ENABLE_STATIC_UNWINDER AND (TARGET unwind_static OR HAVE_LIBUNWIND))
list(APPEND SANITIZER_CXX_ABI_LIBRARY unwind_static)
endif()
if (NOT LIBCXX_ENABLE_STATIC_ABI_LIBRARY AND (TARGET cxxabi_shared OR HAVE_LIBCXXABI))
list(APPEND SANITIZER_CXX_ABI_LIBRARY cxxabi_shared)
elseif (LIBCXX_ENABLE_STATIC_ABI_LIBRARY AND (TARGET cxxabi_static OR HAVE_LIBCXXABI))
list(APPEND SANITIZER_CXX_ABI_LIBRARY cxxabi_static)
endif()
else()
append_list_if(COMPILER_RT_HAS_LIBCXX c++ SANITIZER_CXX_ABI_LIBRARY)
endif()
elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libcxxabi")
list(APPEND SANITIZER_CXX_ABI_LIBRARY "c++abi")
elseif (SANITIZER_CXX_ABI_LIBNAME STREQUAL "libstdc++")
append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ SANITIZER_CXX_ABI_LIBRARY)
endif()
# Warnings to turn off for all libraries, not just sanitizers.
append_string_if(COMPILER_RT_HAS_WUNUSED_PARAMETER_FLAG -Wno-unused-parameter CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
if (CMAKE_LINKER MATCHES "link.exe$")
# Silence MSVC linker warnings caused by empty object files. The
# sanitizer libraries intentionally use ifdefs that result in empty
# files, rather than skipping these files in the build system.
# Ideally, we would pass this flag only for the libraries that need
# it, but CMake doesn't seem to have a way to set linker flags for
# individual static libraries, so we enable the suppression flag for
# the whole compiler-rt project.
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221")
endif()
add_subdirectory(include)
option(COMPILER_RT_USE_LIBCXX
"Enable compiler-rt to use libc++ from the source tree" ON)
if(COMPILER_RT_USE_LIBCXX)
foreach(path IN ITEMS ${LLVM_MAIN_SRC_DIR}/projects/libcxx
${LLVM_MAIN_SRC_DIR}/runtimes/libcxx
${LLVM_MAIN_SRC_DIR}/../libcxx
${LLVM_EXTERNAL_LIBCXX_SOURCE_DIR})
if(IS_DIRECTORY ${path})
set(COMPILER_RT_LIBCXX_PATH ${path})
break()
endif()
endforeach()
endif()
set(COMPILER_RT_LLD_PATH ${LLVM_MAIN_SRC_DIR}/tools/lld)
if(EXISTS ${COMPILER_RT_LLD_PATH}/ AND LLVM_TOOL_LLD_BUILD)
set(COMPILER_RT_HAS_LLD TRUE)
else()
set(COMPILER_RT_LLD_PATH ${LLVM_MAIN_SRC_DIR}/../lld)
if(EXISTS ${COMPILER_RT_LLD_PATH}/ AND LLVM_TOOL_LLD_BUILD)
set(COMPILER_RT_HAS_LLD TRUE)
else()
set(COMPILER_RT_HAS_LLD FALSE)
endif()
endif()
pythonize_bool(COMPILER_RT_HAS_LLD)
add_subdirectory(lib)
if(COMPILER_RT_INCLUDE_TESTS)
add_subdirectory(unittests)
add_subdirectory(test)
if (COMPILER_RT_STANDALONE_BUILD)
# If we have a valid source tree, generate llvm-lit into the bin directory.
# The user can still choose to have the check targets *use* a different lit
# by specifying -DLLVM_EXTERNAL_LIT, but we generate it regardless.
if (EXISTS ${LLVM_MAIN_SRC_DIR}/utils/llvm-lit)
add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/llvm-lit ${CMAKE_CURRENT_BINARY_DIR}/llvm-lit)
elseif(NOT EXISTS ${LLVM_EXTERNAL_LIT})
message(WARNING "Could not find LLVM source directory and LLVM_EXTERNAL_LIT does not"
"point to a valid file. You will not be able to run tests.")
endif()
endif()
endif()

View File

@ -1,53 +0,0 @@
This file is a list of the people responsible for ensuring that patches for a
particular part of compiler-rt are reviewed, either by themself or by
someone else. They are also the gatekeepers for their part of compiler-rt, with
the final word on what goes in or not.
The list is sorted by surname and formatted to allow easy grepping and
beautification by scripts. The fields are: name (N), email (E), web-address
(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
(S).
N: Peter Collingbourne
E: peter@pcc.me.uk
D: DataFlowSanitizer
N: Daniel Dunbar
E: daniel@zuster.org
D: Makefile build
N: Timur Iskhodzhanov
E: timurrrr@google.com
D: AddressSanitizer for Windows
N: Howard Hinnant
E: howard.hinnant@gmail.com
D: builtins library
N: Alexander Potapenko
E: glider@google.com
D: MacOS/iOS port of sanitizers
N: Alexey Samsonov
E: samsonov@google.com
D: CMake build, test suite
N: Kostya Serebryany
E: kcc@google.com
D: AddressSanitizer, sanitizer_common, porting sanitizers to another platforms, LeakSanitizer
N: Richard Smith
E: richard-llvm@metafoo.co.uk
D: UndefinedBehaviorSanitizer
N: Evgeniy Stepanov
E: eugenis@google.com
D: MemorySanitizer, Android port of sanitizers
N: Dmitry Vyukov
E: dvyukov@google.com
D: ThreadSanitizer
N: Bill Wendling
E: isanbard@gmail.com
D: Profile runtime library

View File

@ -1,670 +0,0 @@
include(ExternalProject)
include(CompilerRTUtils)
function(set_target_output_directories target output_dir)
# For RUNTIME_OUTPUT_DIRECTORY variable, Multi-configuration generators
# append a per-configuration subdirectory to the specified directory.
# To avoid the appended folder, the configuration specific variable must be
# set 'RUNTIME_OUTPUT_DIRECTORY_${CONF}':
# RUNTIME_OUTPUT_DIRECTORY_DEBUG, RUNTIME_OUTPUT_DIRECTORY_RELEASE, ...
if(CMAKE_CONFIGURATION_TYPES)
foreach(build_mode ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER "${build_mode}" CONFIG_SUFFIX)
set_target_properties("${target}" PROPERTIES
"ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir}
"LIBRARY_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir}
"RUNTIME_OUTPUT_DIRECTORY_${CONFIG_SUFFIX}" ${output_dir})
endforeach()
else()
set_target_properties("${target}" PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${output_dir}
LIBRARY_OUTPUT_DIRECTORY ${output_dir}
RUNTIME_OUTPUT_DIRECTORY ${output_dir})
endif()
endfunction()
# Tries to add an "object library" target for a given list of OSs and/or
# architectures with name "<name>.<arch>" for non-Darwin platforms if
# architecture can be targeted, and "<name>.<os>" for Darwin platforms.
# add_compiler_rt_object_libraries(<name>
# OS <os names>
# ARCHS <architectures>
# SOURCES <source files>
# CFLAGS <compile flags>
# DEFS <compile definitions>
# DEPS <dependencies>
# ADDITIONAL_HEADERS <header files>)
function(add_compiler_rt_object_libraries name)
cmake_parse_arguments(LIB "" "" "OS;ARCHS;SOURCES;CFLAGS;DEFS;DEPS;ADDITIONAL_HEADERS"
${ARGN})
set(libnames)
if(APPLE)
foreach(os ${LIB_OS})
set(libname "${name}.${os}")
set(libnames ${libnames} ${libname})
set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS})
list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS)
endforeach()
else()
foreach(arch ${LIB_ARCHS})
set(libname "${name}.${arch}")
set(libnames ${libnames} ${libname})
set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS})
if(NOT CAN_TARGET_${arch})
message(FATAL_ERROR "Architecture ${arch} can't be targeted")
return()
endif()
endforeach()
endif()
# Add headers to LIB_SOURCES for IDEs
compiler_rt_process_sources(LIB_SOURCES
${LIB_SOURCES}
ADDITIONAL_HEADERS
${LIB_ADDITIONAL_HEADERS}
)
foreach(libname ${libnames})
add_library(${libname} OBJECT ${LIB_SOURCES})
if(LIB_DEPS)
add_dependencies(${libname} ${LIB_DEPS})
endif()
# Strip out -msse3 if this isn't macOS.
set(target_flags ${LIB_CFLAGS})
if(APPLE AND NOT "${libname}" MATCHES ".*\.osx.*")
list(REMOVE_ITEM target_flags "-msse3")
endif()
set_target_compile_flags(${libname}
${extra_cflags_${libname}} ${target_flags})
set_property(TARGET ${libname} APPEND PROPERTY
COMPILE_DEFINITIONS ${LIB_DEFS})
set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Libraries")
if(APPLE)
set_target_properties(${libname} PROPERTIES
OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}")
endif()
endforeach()
endfunction()
# Takes a list of object library targets, and a suffix and appends the proper
# TARGET_OBJECTS string to the output variable.
# format_object_libs(<output> <suffix> ...)
macro(format_object_libs output suffix)
foreach(lib ${ARGN})
list(APPEND ${output} $<TARGET_OBJECTS:${lib}.${suffix}>)
endforeach()
endmacro()
function(add_compiler_rt_component name)
add_custom_target(${name})
set_target_properties(${name} PROPERTIES FOLDER "Compiler-RT Misc")
if(COMMAND runtime_register_component)
runtime_register_component(${name})
endif()
add_dependencies(compiler-rt ${name})
endfunction()
function(add_asm_sources output)
set(${output} ${ARGN} PARENT_SCOPE)
# Xcode will try to compile asm files as C ('clang -x c'), and that will fail.
if (${CMAKE_GENERATOR} STREQUAL "Xcode")
enable_language(ASM)
else()
# Pass ASM file directly to the C++ compiler.
set_source_files_properties(${ARGN} PROPERTIES LANGUAGE C)
endif()
endfunction()
macro(set_output_name output name arch)
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
set(${output} ${name})
else()
if(ANDROID AND ${arch} STREQUAL "i386")
set(${output} "${name}-i686${COMPILER_RT_OS_SUFFIX}")
else()
set(${output} "${name}-${arch}${COMPILER_RT_OS_SUFFIX}")
endif()
endif()
endmacro()
# Adds static or shared runtime for a list of architectures and operating
# systems and puts it in the proper directory in the build and install trees.
# add_compiler_rt_runtime(<name>
# {STATIC|SHARED}
# ARCHS <architectures>
# OS <os list>
# SOURCES <source files>
# CFLAGS <compile flags>
# LINK_FLAGS <linker flags>
# DEFS <compile definitions>
# LINK_LIBS <linked libraries> (only for shared library)
# OBJECT_LIBS <object libraries to use as sources>
# PARENT_TARGET <convenience parent target>
# ADDITIONAL_HEADERS <header files>)
function(add_compiler_rt_runtime name type)
if(NOT type MATCHES "^(STATIC|SHARED)$")
message(FATAL_ERROR "type argument must be STATIC or SHARED")
return()
endif()
cmake_parse_arguments(LIB
""
"PARENT_TARGET"
"OS;ARCHS;SOURCES;CFLAGS;LINK_FLAGS;DEFS;LINK_LIBS;OBJECT_LIBS;ADDITIONAL_HEADERS"
${ARGN})
set(libnames)
# Until we support this some other way, build compiler-rt runtime without LTO
# to allow non-LTO projects to link with it.
if(COMPILER_RT_HAS_FNO_LTO_FLAG)
set(NO_LTO_FLAGS "-fno-lto")
else()
set(NO_LTO_FLAGS "")
endif()
list(LENGTH LIB_SOURCES LIB_SOURCES_LENGTH)
if (${LIB_SOURCES_LENGTH} GREATER 0)
# Add headers to LIB_SOURCES for IDEs. It doesn't make sense to
# do this for a runtime library that only consists of OBJECT
# libraries, so only add the headers when source files are present.
compiler_rt_process_sources(LIB_SOURCES
${LIB_SOURCES}
ADDITIONAL_HEADERS
${LIB_ADDITIONAL_HEADERS}
)
endif()
if(APPLE)
foreach(os ${LIB_OS})
# Strip out -msse3 if this isn't macOS.
list(LENGTH LIB_CFLAGS HAS_EXTRA_CFLAGS)
if(HAS_EXTRA_CFLAGS AND NOT "${os}" MATCHES "^(osx)$")
list(REMOVE_ITEM LIB_CFLAGS "-msse3")
endif()
if(type STREQUAL "STATIC")
set(libname "${name}_${os}")
else()
set(libname "${name}_${os}_dynamic")
set(extra_link_flags_${libname} ${DARWIN_${os}_LINK_FLAGS} ${LIB_LINK_FLAGS})
endif()
list_intersect(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS)
if(LIB_ARCHS_${libname})
list(APPEND libnames ${libname})
set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS} ${NO_LTO_FLAGS} ${LIB_CFLAGS})
set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX})
set(sources_${libname} ${LIB_SOURCES})
format_object_libs(sources_${libname} ${os} ${LIB_OBJECT_LIBS})
get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir_${libname})
get_compiler_rt_install_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} install_dir_${libname})
endif()
endforeach()
else()
foreach(arch ${LIB_ARCHS})
if(NOT CAN_TARGET_${arch})
message(FATAL_ERROR "Architecture ${arch} can't be targeted")
return()
endif()
if(type STREQUAL "STATIC")
set(libname "${name}-${arch}")
set_output_name(output_name_${libname} ${name} ${arch})
else()
set(libname "${name}-dynamic-${arch}")
set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS})
set(extra_link_flags_${libname} ${TARGET_${arch}_LINK_FLAGS} ${LIB_LINK_FLAGS})
if(WIN32)
set_output_name(output_name_${libname} ${name}_dynamic ${arch})
else()
set_output_name(output_name_${libname} ${name} ${arch})
endif()
endif()
set(sources_${libname} ${LIB_SOURCES})
format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS})
set(libnames ${libnames} ${libname})
set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${NO_LTO_FLAGS} ${LIB_CFLAGS})
get_compiler_rt_output_dir(${arch} output_dir_${libname})
get_compiler_rt_install_dir(${arch} install_dir_${libname})
endforeach()
endif()
if(NOT libnames)
return()
endif()
if(LIB_PARENT_TARGET)
# If the parent targets aren't created we should create them
if(NOT TARGET ${LIB_PARENT_TARGET})
add_custom_target(${LIB_PARENT_TARGET})
set_target_properties(${LIB_PARENT_TARGET} PROPERTIES
FOLDER "Compiler-RT Misc")
endif()
if(NOT TARGET install-${LIB_PARENT_TARGET})
# The parent install target specifies the parent component to scrape up
# anything not installed by the individual install targets, and to handle
# installation when running the multi-configuration generators.
add_custom_target(install-${LIB_PARENT_TARGET}
DEPENDS ${LIB_PARENT_TARGET}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=${LIB_PARENT_TARGET}
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
add_custom_target(install-${LIB_PARENT_TARGET}-stripped
DEPENDS ${LIB_PARENT_TARGET}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=${LIB_PARENT_TARGET}
-DCMAKE_INSTALL_DO_STRIP=1
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
set_target_properties(install-${LIB_PARENT_TARGET} PROPERTIES
FOLDER "Compiler-RT Misc")
set_target_properties(install-${LIB_PARENT_TARGET}-stripped PROPERTIES
FOLDER "Compiler-RT Misc")
add_dependencies(install-compiler-rt install-${LIB_PARENT_TARGET})
add_dependencies(install-compiler-rt-stripped install-${LIB_PARENT_TARGET}-stripped)
endif()
endif()
foreach(libname ${libnames})
# If you are using a multi-configuration generator we don't generate
# per-library install rules, so we fall back to the parent target COMPONENT
if(CMAKE_CONFIGURATION_TYPES AND LIB_PARENT_TARGET)
set(COMPONENT_OPTION COMPONENT ${LIB_PARENT_TARGET})
else()
set(COMPONENT_OPTION COMPONENT ${libname})
endif()
add_library(${libname} ${type} ${sources_${libname}})
set_target_compile_flags(${libname} ${extra_cflags_${libname}})
set_target_link_flags(${libname} ${extra_link_flags_${libname}})
set_property(TARGET ${libname} APPEND PROPERTY
COMPILE_DEFINITIONS ${LIB_DEFS})
set_target_output_directories(${libname} ${output_dir_${libname}})
set_target_properties(${libname} PROPERTIES
OUTPUT_NAME ${output_name_${libname}})
set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Runtime")
if(LIB_LINK_LIBS)
target_link_libraries(${libname} ${LIB_LINK_LIBS})
endif()
if(${type} STREQUAL "SHARED")
if(COMMAND llvm_setup_rpath)
llvm_setup_rpath(${libname})
endif()
if(WIN32 AND NOT CYGWIN AND NOT MINGW)
set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "")
set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib")
endif()
if(APPLE)
# Ad-hoc sign the dylibs
add_custom_command(TARGET ${libname}
POST_BUILD
COMMAND codesign --sign - $<TARGET_FILE:${libname}>
WORKING_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
)
endif()
endif()
install(TARGETS ${libname}
ARCHIVE DESTINATION ${install_dir_${libname}}
${COMPONENT_OPTION}
LIBRARY DESTINATION ${install_dir_${libname}}
${COMPONENT_OPTION}
RUNTIME DESTINATION ${install_dir_${libname}}
${COMPONENT_OPTION})
# We only want to generate per-library install targets if you aren't using
# an IDE because the extra targets get cluttered in IDEs.
if(NOT CMAKE_CONFIGURATION_TYPES)
add_custom_target(install-${libname}
DEPENDS ${libname}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=${libname}
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
add_custom_target(install-${libname}-stripped
DEPENDS ${libname}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=${libname}
-DCMAKE_INSTALL_DO_STRIP=1
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
# If you have a parent target specified, we bind the new install target
# to the parent install target.
if(LIB_PARENT_TARGET)
add_dependencies(install-${LIB_PARENT_TARGET} install-${libname})
add_dependencies(install-${LIB_PARENT_TARGET}-stripped install-${libname}-stripped)
endif()
endif()
if(APPLE)
set_target_properties(${libname} PROPERTIES
OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}")
endif()
if(type STREQUAL "SHARED")
rt_externalize_debuginfo(${libname})
endif()
endforeach()
if(LIB_PARENT_TARGET)
add_dependencies(${LIB_PARENT_TARGET} ${libnames})
endif()
endfunction()
# when cross compiling, COMPILER_RT_TEST_COMPILER_CFLAGS help
# in compilation and linking of unittests.
string(REPLACE " " ";" COMPILER_RT_UNITTEST_CFLAGS "${COMPILER_RT_TEST_COMPILER_CFLAGS}")
set(COMPILER_RT_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_CFLAGS})
# Unittests support.
set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest)
set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc)
set(COMPILER_RT_GTEST_CFLAGS
-DGTEST_NO_LLVM_RAW_OSTREAM=1
-DGTEST_HAS_RTTI=0
-I${COMPILER_RT_GTEST_PATH}/include
-I${COMPILER_RT_GTEST_PATH}
)
# Mocking support.
set(COMPILER_RT_GMOCK_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock)
set(COMPILER_RT_GMOCK_SOURCE ${COMPILER_RT_GMOCK_PATH}/src/gmock-all.cc)
set(COMPILER_RT_GMOCK_CFLAGS
-DGTEST_NO_LLVM_RAW_OSTREAM=1
-DGTEST_HAS_RTTI=0
-I${COMPILER_RT_GMOCK_PATH}/include
-I${COMPILER_RT_GMOCK_PATH}
)
append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 COMPILER_RT_UNITTEST_CFLAGS)
append_list_if(COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG -Wno-covered-switch-default COMPILER_RT_UNITTEST_CFLAGS)
if(MSVC)
# gtest use a lot of stuff marked as deprecated on Windows.
list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations)
endif()
# Compile and register compiler-rt tests.
# generate_compiler_rt_tests(<output object files> <test_suite> <test_name>
# <test architecture>
# KIND <custom prefix>
# SUBDIR <subdirectory for testing binary>
# SOURCES <sources to compile>
# RUNTIME <tests runtime to link in>
# CFLAGS <compile-time flags>
# COMPILE_DEPS <compile-time dependencies>
# DEPS <dependencies>
# LINK_FLAGS <flags to use during linking>
# )
function(generate_compiler_rt_tests test_objects test_suite testname arch)
cmake_parse_arguments(TEST "" "KIND;RUNTIME;SUBDIR"
"SOURCES;COMPILE_DEPS;DEPS;CFLAGS;LINK_FLAGS" ${ARGN})
foreach(source ${TEST_SOURCES})
sanitizer_test_compile(
"${test_objects}" "${source}" "${arch}"
KIND ${TEST_KIND}
COMPILE_DEPS ${TEST_COMPILE_DEPS}
DEPS ${TEST_DEPS}
CFLAGS ${TEST_CFLAGS}
)
endforeach()
set(TEST_DEPS ${${test_objects}})
if(NOT "${TEST_RUNTIME}" STREQUAL "")
list(APPEND TEST_DEPS ${TEST_RUNTIME})
list(APPEND "${test_objects}" $<TARGET_FILE:${TEST_RUNTIME}>)
endif()
add_compiler_rt_test(${test_suite} "${testname}" "${arch}"
SUBDIR ${TEST_SUBDIR}
OBJECTS ${${test_objects}}
DEPS ${TEST_DEPS}
LINK_FLAGS ${TEST_LINK_FLAGS}
)
set("${test_objects}" "${${test_objects}}" PARENT_SCOPE)
endfunction()
# Link objects into a single executable with COMPILER_RT_TEST_COMPILER,
# using specified link flags. Make executable a part of provided
# test_suite.
# add_compiler_rt_test(<test_suite> <test_name> <arch>
# SUBDIR <subdirectory for binary>
# OBJECTS <object files>
# DEPS <deps (e.g. runtime libs)>
# LINK_FLAGS <link flags>)
function(add_compiler_rt_test test_suite test_name arch)
cmake_parse_arguments(TEST "" "SUBDIR" "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN})
set(output_dir ${CMAKE_CURRENT_BINARY_DIR})
if(TEST_SUBDIR)
set(output_dir "${output_dir}/${TEST_SUBDIR}")
endif()
set(output_dir "${output_dir}/${CMAKE_CFG_INTDIR}")
file(MAKE_DIRECTORY "${output_dir}")
set(output_bin "${output_dir}/${test_name}")
if(MSVC)
set(output_bin "${output_bin}.exe")
endif()
# Use host compiler in a standalone build, and just-built Clang otherwise.
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND TEST_DEPS clang)
endif()
get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)
list(APPEND TEST_LINK_FLAGS ${TARGET_LINK_FLAGS})
# If we're not on MSVC, include the linker flags from CMAKE but override them
# with the provided link flags. This ensures that flags which are required to
# link programs at all are included, but the changes needed for the test
# trump. With MSVC we can't do that because CMake is set up to run link.exe
# when linking, not the compiler. Here, we hack it to use the compiler
# because we want to use -fsanitize flags.
if(NOT MSVC)
set(TEST_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TEST_LINK_FLAGS}")
separate_arguments(TEST_LINK_FLAGS)
endif()
add_custom_command(
OUTPUT "${output_bin}"
COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS} -o "${output_bin}"
${TEST_LINK_FLAGS}
DEPENDS ${TEST_DEPS}
)
add_custom_target(T${test_name} DEPENDS "${output_bin}")
set_target_properties(T${test_name} PROPERTIES FOLDER "Compiler-RT Tests")
# Make the test suite depend on the binary.
add_dependencies(${test_suite} T${test_name})
endfunction()
macro(add_compiler_rt_resource_file target_name file_name component)
set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}")
set(dst_file "${COMPILER_RT_OUTPUT_DIR}/share/${file_name}")
add_custom_command(OUTPUT ${dst_file}
DEPENDS ${src_file}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file}
COMMENT "Copying ${file_name}...")
add_custom_target(${target_name} DEPENDS ${dst_file})
# Install in Clang resource directory.
install(FILES ${file_name}
DESTINATION ${COMPILER_RT_INSTALL_PATH}/share
COMPONENT ${component})
add_dependencies(${component} ${target_name})
set_target_properties(${target_name} PROPERTIES FOLDER "Compiler-RT Misc")
endmacro()
macro(add_compiler_rt_script name)
set(dst ${COMPILER_RT_EXEC_OUTPUT_DIR}/${name})
set(src ${CMAKE_CURRENT_SOURCE_DIR}/${name})
add_custom_command(OUTPUT ${dst}
DEPENDS ${src}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
COMMENT "Copying ${name}...")
add_custom_target(${name} DEPENDS ${dst})
install(FILES ${dst}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
DESTINATION ${COMPILER_RT_INSTALL_PATH}/bin)
endmacro(add_compiler_rt_script src name)
# Builds custom version of libc++ and installs it in <prefix>.
# Can be used to build sanitized versions of libc++ for running unit tests.
# add_custom_libcxx(<name> <prefix>
# DEPS <list of build deps>
# CFLAGS <list of compile flags>
# USE_TOOLCHAIN)
macro(add_custom_libcxx name prefix)
if(NOT COMPILER_RT_LIBCXX_PATH)
message(FATAL_ERROR "libcxx not found!")
endif()
cmake_parse_arguments(LIBCXX "USE_TOOLCHAIN" "" "DEPS;CFLAGS;CMAKE_ARGS" ${ARGN})
if(LIBCXX_USE_TOOLCHAIN)
set(compiler_args -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER}
-DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_CXX_COMPILER})
if(NOT COMPILER_RT_STANDALONE_BUILD)
set(toolchain_deps $<TARGET_FILE:clang>)
set(force_deps DEPENDS $<TARGET_FILE:clang>)
endif()
else()
set(compiler_args -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER})
endif()
set(STAMP_DIR ${prefix}-stamps/)
set(BINARY_DIR ${prefix}-bins/)
add_custom_target(${name}-clear
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
COMMENT "Clobbering ${name} build and stamp directories"
USES_TERMINAL
)
set_target_properties(${name}-clear PROPERTIES FOLDER "Compiler-RT Misc")
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
DEPENDS ${LIBCXX_DEPS} ${toolchain_deps}
COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
COMMENT "Clobbering bootstrap build and stamp directories"
)
add_custom_target(${name}-clobber
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
set_target_properties(${name}-clobber PROPERTIES FOLDER "Compiler-RT Misc")
set(PASSTHROUGH_VARIABLES
CMAKE_C_COMPILER_TARGET
CMAKE_CXX_COMPILER_TARGET
CMAKE_SHARED_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_EXE_LINKER_FLAGS
CMAKE_INSTALL_PREFIX
CMAKE_MAKE_PROGRAM
CMAKE_LINKER
CMAKE_AR
CMAKE_RANLIB
CMAKE_NM
CMAKE_OBJCOPY
CMAKE_OBJDUMP
CMAKE_STRIP
CMAKE_SYSROOT
CMAKE_SYSTEM_NAME)
foreach(variable ${PASSTHROUGH_VARIABLES})
get_property(is_value_set CACHE ${variable} PROPERTY VALUE SET)
if(${is_value_set})
get_property(value CACHE ${variable} PROPERTY VALUE)
list(APPEND CMAKE_PASSTHROUGH_VARIABLES -D${variable}=${value})
endif()
endforeach()
string(REPLACE ";" " " LIBCXX_C_FLAGS "${LIBCXX_CFLAGS}")
get_property(C_FLAGS CACHE CMAKE_C_FLAGS PROPERTY VALUE)
set(LIBCXX_C_FLAGS "${LIBCXX_C_FLAGS} ${C_FLAGS}")
string(REPLACE ";" " " LIBCXX_CXX_FLAGS "${LIBCXX_CFLAGS}")
get_property(CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE)
set(LIBCXX_CXX_FLAGS "${LIBCXX_CXX_FLAGS} ${CXX_FLAGS}")
ExternalProject_Add(${name}
DEPENDS ${name}-clobber ${LIBCXX_DEPS}
PREFIX ${prefix}
SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH}
STAMP_DIR ${STAMP_DIR}
BINARY_DIR ${BINARY_DIR}
CMAKE_ARGS ${CMAKE_PASSTHROUGH_VARIABLES}
${compiler_args}
-DCMAKE_C_FLAGS=${LIBCXX_C_FLAGS}
-DCMAKE_CXX_FLAGS=${LIBCXX_CXX_FLAGS}
-DCMAKE_BUILD_TYPE=Release
-DLLVM_PATH=${LLVM_MAIN_SRC_DIR}
-DLLVM_BINARY_DIR=${prefix}
-DLLVM_LIBRARY_OUTPUT_INTDIR=${prefix}/lib
-DLIBCXX_STANDALONE_BUILD=ON
${LIBCXX_CMAKE_ARGS}
INSTALL_COMMAND ""
STEP_TARGETS configure build
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
EXCLUDE_FROM_ALL TRUE
)
if (CMAKE_GENERATOR MATCHES "Make")
set(run_clean "$(MAKE)" "-C" "${BINARY_DIR}" "clean")
else()
set(run_clean ${CMAKE_COMMAND} --build ${BINARY_DIR} --target clean
--config "$<CONFIGURATION>")
endif()
ExternalProject_Add_Step(${name} clean
COMMAND ${run_clean}
COMMENT "Cleaning ${name}..."
DEPENDEES configure
${force_deps}
WORKING_DIRECTORY ${BINARY_DIR}
EXCLUDE_FROM_MAIN 1
USES_TERMINAL 1
)
ExternalProject_Add_StepTargets(${name} clean)
if(LIBCXX_USE_TOOLCHAIN)
add_dependencies(${name}-clean ${name}-clobber)
set_target_properties(${name}-clean PROPERTIES
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
endif()
endmacro()
function(rt_externalize_debuginfo name)
if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO)
return()
endif()
if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO_SKIP_STRIP)
set(strip_command COMMAND xcrun strip -Sl $<TARGET_FILE:${name}>)
endif()
if(APPLE)
if(CMAKE_CXX_FLAGS MATCHES "-flto"
OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto")
set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o)
set_property(TARGET ${name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}")
endif()
add_custom_command(TARGET ${name} POST_BUILD
COMMAND xcrun dsymutil $<TARGET_FILE:${name}>
${strip_command})
else()
message(FATAL_ERROR "COMPILER_RT_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!")
endif()
endfunction()
# Configure lit configuration files, including compiler-rt specific variables.
function(configure_compiler_rt_lit_site_cfg input output)
set_llvm_build_mode()
get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir)
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER})
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR ${output_dir})
configure_lit_site_cfg(${input} ${output})
endfunction()

View File

@ -1,98 +0,0 @@
include(CMakeCheckCompilerFlagCommonPatterns)
# This function takes an OS and a list of architectures and identifies the
# subset of the architectures list that the installed toolchain can target.
function(try_compile_only output)
cmake_parse_arguments(ARG "" "" "SOURCE;FLAGS" ${ARGN})
if(NOT ARG_SOURCE)
set(ARG_SOURCE "int foo(int x, int y) { return x + y; }\n")
endif()
set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c)
file(WRITE ${SIMPLE_C} "${ARG_SOURCE}\n")
string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions
${CMAKE_C_COMPILE_OBJECT})
set(TRY_COMPILE_FLAGS "${ARG_FLAGS}")
if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET)
list(APPEND TRY_COMPILE_FLAGS "-target ${CMAKE_C_COMPILER_TARGET}")
endif()
string(REPLACE ";" " " extra_flags "${TRY_COMPILE_FLAGS}")
set(test_compile_command "${CMAKE_C_COMPILE_OBJECT}")
foreach(substitution ${substitutions})
if(substitution STREQUAL "<CMAKE_C_COMPILER>")
string(REPLACE "<CMAKE_C_COMPILER>"
"${CMAKE_C_COMPILER}" test_compile_command ${test_compile_command})
elseif(substitution STREQUAL "<OBJECT>")
string(REPLACE "<OBJECT>"
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/test.o"
test_compile_command ${test_compile_command})
elseif(substitution STREQUAL "<SOURCE>")
string(REPLACE "<SOURCE>" "${SIMPLE_C}" test_compile_command
${test_compile_command})
elseif(substitution STREQUAL "<FLAGS>")
string(REPLACE "<FLAGS>" "${CMAKE_C_FLAGS} ${extra_flags}"
test_compile_command ${test_compile_command})
else()
string(REPLACE "${substitution}" "" test_compile_command
${test_compile_command})
endif()
endforeach()
string(REPLACE " " ";" test_compile_command "${test_compile_command}")
execute_process(
COMMAND ${test_compile_command}
RESULT_VARIABLE result
OUTPUT_VARIABLE TEST_OUTPUT
ERROR_VARIABLE TEST_ERROR
)
CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckCCompilerFlag_COMMON_PATTERNS)
set(ERRORS_FOUND OFF)
foreach(var ${_CheckCCompilerFlag_COMMON_PATTERNS})
if("${var}" STREQUAL "FAIL_REGEX")
continue()
endif()
if("${TEST_ERROR}" MATCHES "${var}" OR "${TEST_OUTPUT}" MATCHES "${var}")
set(ERRORS_FOUND ON)
endif()
endforeach()
if(result EQUAL 0 AND NOT ERRORS_FOUND)
set(${output} True PARENT_SCOPE)
else()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Testing compiler for supporting " ${ARGN} ":\n"
"Command: ${test_compile_command}\n"
"${TEST_OUTPUT}\n${TEST_ERROR}\n${result}\n")
set(${output} False PARENT_SCOPE)
endif()
endfunction()
function(builtin_check_c_compiler_flag flag output)
if(NOT DEFINED ${output})
message(STATUS "Performing Test ${output}")
try_compile_only(result FLAGS ${flag})
set(${output} ${result} CACHE INTERNAL "Compiler supports ${flag}")
if(${result})
message(STATUS "Performing Test ${output} - Success")
else()
message(STATUS "Performing Test ${output} - Failed")
endif()
endif()
endfunction()
function(builtin_check_c_compiler_source output source)
if(NOT DEFINED ${output})
message(STATUS "Performing Test ${output}")
try_compile_only(result SOURCE ${source})
set(${output} ${result} CACHE INTERNAL "Compiler supports ${flag}")
if(${result})
message(STATUS "Performing Test ${output} - Success")
else()
message(STATUS "Performing Test ${output} - Failed")
endif()
endif()
endfunction()

View File

@ -1,143 +0,0 @@
# On Windows, CMAKE_*_FLAGS are built for MSVC but we use the GCC clang.exe,
# which uses completely different flags. Translate some common flag types, and
# drop the rest.
function(translate_msvc_cflags out_flags msvc_flags)
# Insert an empty string in the list to simplify processing.
set(msvc_flags ";${msvc_flags}")
# Canonicalize /flag to -flag.
string(REPLACE ";/" ";-" msvc_flags "${msvc_flags}")
# Make space separated -D and -U flags into joined flags.
string(REGEX REPLACE ";-\([DU]\);" ";-\\1" msvc_flags "${msvc_flags}")
set(clang_flags "")
foreach(flag ${msvc_flags})
if ("${flag}" MATCHES "^-[DU]")
# Pass through basic command line macro definitions (-DNDEBUG).
list(APPEND clang_flags "${flag}")
elseif ("${flag}" MATCHES "^-O[2x]")
# Canonicalize normal optimization flags to -O2.
list(APPEND clang_flags "-O2")
endif()
endforeach()
set(${out_flags} "${clang_flags}" PARENT_SCOPE)
endfunction()
# Compile a sanitizer test with a freshly built clang
# for a given architecture, adding the result to the object list.
# - obj_list: output list of objects, populated by path
# of a generated object file.
# - source: source file of a test.
# - arch: architecture to compile for.
# sanitizer_test_compile(<obj_list> <source> <arch>
# KIND <custom namespace>
# COMPILE_DEPS <list of compile-time dependencies>
# DEPS <list of dependencies>
# CFLAGS <list of flags>
# )
function(sanitizer_test_compile obj_list source arch)
cmake_parse_arguments(TEST
"" "" "KIND;COMPILE_DEPS;DEPS;CFLAGS" ${ARGN})
get_filename_component(basename ${source} NAME)
set(output_obj
"${CMAKE_CFG_RESOLVED_INTDIR}${obj_list}.${basename}.${arch}${TEST_KIND}.o")
# Write out architecture-specific flags into TARGET_CFLAGS variable.
get_target_flags_for_arch(${arch} TARGET_CFLAGS)
set(COMPILE_DEPS ${TEST_COMPILE_DEPS})
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND COMPILE_DEPS ${TEST_DEPS})
endif()
clang_compile(${output_obj} ${source}
CFLAGS ${TEST_CFLAGS} ${TARGET_CFLAGS}
DEPS ${COMPILE_DEPS})
list(APPEND ${obj_list} ${output_obj})
set("${obj_list}" "${${obj_list}}" PARENT_SCOPE)
endfunction()
# Compile a source into an object file with COMPILER_RT_TEST_COMPILER using
# a provided compile flags and dependenices.
# clang_compile(<object> <source>
# CFLAGS <list of compile flags>
# DEPS <list of dependencies>)
function(clang_compile object_file source)
cmake_parse_arguments(SOURCE "" "" "CFLAGS;DEPS" ${ARGN})
get_filename_component(source_rpath ${source} REALPATH)
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND SOURCE_DEPS clang compiler-rt-headers)
endif()
if (TARGET CompilerRTUnitTestCheckCxx)
list(APPEND SOURCE_DEPS CompilerRTUnitTestCheckCxx)
endif()
string(REGEX MATCH "[.](cc|cpp)$" is_cxx ${source_rpath})
string(REGEX MATCH "[.](m|mm)$" is_objc ${source_rpath})
if(is_cxx)
string(REPLACE " " ";" global_flags "${CMAKE_CXX_FLAGS}")
else()
string(REPLACE " " ";" global_flags "${CMAKE_C_FLAGS}")
endif()
if (MSVC)
translate_msvc_cflags(global_flags "${global_flags}")
endif()
if (APPLE)
set(global_flags ${OSX_SYSROOT_FLAG} ${global_flags})
endif()
if (is_objc)
list(APPEND global_flags -ObjC)
endif()
# Ignore unknown warnings. CMAKE_CXX_FLAGS may contain GCC-specific options
# which are not supported by Clang.
list(APPEND global_flags -Wno-unknown-warning-option)
set(compile_flags ${global_flags} ${SOURCE_CFLAGS})
add_custom_command(
OUTPUT ${object_file}
COMMAND ${COMPILER_RT_TEST_COMPILER} ${compile_flags} -c
-o "${object_file}"
${source_rpath}
MAIN_DEPENDENCY ${source}
DEPENDS ${SOURCE_DEPS})
endfunction()
# On Darwin, there are no system-wide C++ headers and the just-built clang is
# therefore not able to compile C++ files unless they are copied/symlinked into
# ${LLVM_BINARY_DIR}/include/c++
# The just-built clang is used to build compiler-rt unit tests. Let's detect
# this before we try to build the tests and print out a suggestion how to fix
# it.
# On other platforms, this is currently not an issue.
macro(clang_compiler_add_cxx_check)
if (APPLE)
set(CMD
"echo '#include <iostream>' | ${COMPILER_RT_TEST_COMPILER} ${OSX_SYSROOT_FLAG} -E -x c++ - > /dev/null"
"if [ $? != 0 ] "
" then echo"
" echo 'Your just-built clang cannot find C++ headers, which are needed to build and run compiler-rt tests.'"
" echo 'You should copy or symlink your system C++ headers into ${LLVM_BINARY_DIR}/include/c++'"
" if [ -d $(dirname $(dirname $(xcrun -f clang)))/include/c++ ]"
" then echo 'e.g. with:'"
" echo ' cp -r' $(dirname $(dirname $(xcrun -f clang)))/include/c++ '${LLVM_BINARY_DIR}/include/'"
" elif [ -d $(dirname $(dirname $(xcrun -f clang)))/lib/c++ ]"
" then echo 'e.g. with:'"
" echo ' cp -r' $(dirname $(dirname $(xcrun -f clang)))/lib/c++ '${LLVM_BINARY_DIR}/include/'"
" fi"
" echo 'This can also be fixed by checking out the libcxx project from llvm.org and installing the headers'"
" echo 'into your build directory:'"
" echo ' cd ${LLVM_MAIN_SRC_DIR}/projects && svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx'"
" echo ' cd ${LLVM_BINARY_DIR} && make -C ${LLVM_MAIN_SRC_DIR}/projects/libcxx installheaders HEADER_DIR=${LLVM_BINARY_DIR}/include'"
" echo"
" false"
"fi"
)
add_custom_target(CompilerRTUnitTestCheckCxx
COMMAND bash -c "${CMD}"
COMMENT "Checking that just-built clang can find C++ headers..."
VERBATIM)
if (NOT COMPILER_RT_STANDALONE_BUILD)
ADD_DEPENDENCIES(CompilerRTUnitTestCheckCxx clang)
endif()
endif()
endmacro()

View File

@ -1,440 +0,0 @@
include(CMakeParseArguments)
# On OS X SDKs can be installed anywhere on the base system and xcode-select can
# set the default Xcode to use. This function finds the SDKs that are present in
# the current Xcode.
function(find_darwin_sdk_dir var sdk_name)
set(DARWIN_${sdk_name}_CACHED_SYSROOT "" CACHE STRING "Darwin SDK path for SDK ${sdk_name}.")
set(DARWIN_PREFER_PUBLIC_SDK OFF CACHE BOOL "Prefer Darwin public SDK, even when an internal SDK is present.")
if(DARWIN_${sdk_name}_CACHED_SYSROOT)
set(${var} ${DARWIN_${sdk_name}_CACHED_SYSROOT} PARENT_SCOPE)
return()
endif()
if(NOT DARWIN_PREFER_PUBLIC_SDK)
# Let's first try the internal SDK, otherwise use the public SDK.
execute_process(
COMMAND xcodebuild -version -sdk ${sdk_name}.internal Path
RESULT_VARIABLE result_process
OUTPUT_VARIABLE var_internal
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_FILE /dev/null
)
endif()
if((NOT result_process EQUAL 0) OR "" STREQUAL "${var_internal}")
execute_process(
COMMAND xcodebuild -version -sdk ${sdk_name} Path
RESULT_VARIABLE result_process
OUTPUT_VARIABLE var_internal
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_FILE /dev/null
)
else()
set(${var}_INTERNAL ${var_internal} PARENT_SCOPE)
endif()
if(result_process EQUAL 0)
set(${var} ${var_internal} PARENT_SCOPE)
endif()
set(DARWIN_${sdk_name}_CACHED_SYSROOT ${var_internal} CACHE STRING "Darwin SDK path for SDK ${sdk_name}." FORCE)
endfunction()
# There isn't a clear mapping of what architectures are supported with a given
# target platform, but ld's version output does list the architectures it can
# link for.
function(darwin_get_toolchain_supported_archs output_var)
execute_process(
COMMAND "${CMAKE_LINKER}" -v
ERROR_VARIABLE LINKER_VERSION)
string(REGEX MATCH "configured to support archs: ([^\n]+)"
ARCHES_MATCHED "${LINKER_VERSION}")
if(ARCHES_MATCHED)
set(ARCHES "${CMAKE_MATCH_1}")
message(STATUS "Got ld supported ARCHES: ${ARCHES}")
string(REPLACE " " ";" ARCHES ${ARCHES})
else()
# If auto-detecting fails, fall back to a default set
message(WARNING "Detecting supported architectures from 'ld -v' failed. Returning default set.")
set(ARCHES "i386;x86_64;armv7;armv7s;arm64")
endif()
set(${output_var} ${ARCHES} PARENT_SCOPE)
endfunction()
# This function takes an OS and a list of architectures and identifies the
# subset of the architectures list that the installed toolchain can target.
function(darwin_test_archs os valid_archs)
if(${valid_archs})
message(STATUS "Using cached valid architectures for ${os}.")
return()
endif()
set(archs ${ARGN})
if(NOT TEST_COMPILE_ONLY)
message(STATUS "Finding valid architectures for ${os}...")
set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c)
file(WRITE ${SIMPLE_C} "#include <stdio.h>\nint main() { printf(__FILE__); return 0; }\n")
set(os_linker_flags)
foreach(flag ${DARWIN_${os}_LINK_FLAGS})
set(os_linker_flags "${os_linker_flags} ${flag}")
endforeach()
endif()
# The simple program will build for x86_64h on the simulator because it is
# compatible with x86_64 libraries (mostly), but since x86_64h isn't actually
# a valid or useful architecture for the iOS simulator we should drop it.
if(${os} MATCHES "^(iossim|tvossim|watchossim)$")
list(REMOVE_ITEM archs "x86_64h")
endif()
set(working_archs)
foreach(arch ${archs})
set(arch_linker_flags "-arch ${arch} ${os_linker_flags}")
if(TEST_COMPILE_ONLY)
try_compile_only(CAN_TARGET_${os}_${arch} -v -arch ${arch} ${DARWIN_${os}_CFLAGS})
else()
set(SAVED_CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${arch_linker_flags}")
try_compile(CAN_TARGET_${os}_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_C}
COMPILE_DEFINITIONS "-v -arch ${arch}" ${DARWIN_${os}_CFLAGS}
OUTPUT_VARIABLE TEST_OUTPUT)
set(CMAKE_EXE_LINKER_FLAGS ${SAVED_CMAKE_EXE_LINKER_FLAGS})
endif()
if(${CAN_TARGET_${os}_${arch}})
list(APPEND working_archs ${arch})
else()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Testing compiler for supporting ${os}-${arch}:\n"
"${TEST_OUTPUT}\n")
endif()
endforeach()
set(${valid_archs} ${working_archs}
CACHE STRING "List of valid architectures for platform ${os}.")
endfunction()
# This function checks the host cpusubtype to see if it is post-haswell. Haswell
# and later machines can run x86_64h binaries. Haswell is cpusubtype 8.
function(darwin_filter_host_archs input output)
list_intersect(tmp_var DARWIN_osx_ARCHS ${input})
execute_process(
COMMAND sysctl hw.cpusubtype
OUTPUT_VARIABLE SUBTYPE)
string(REGEX MATCH "hw.cpusubtype: ([0-9]*)"
SUBTYPE_MATCHED "${SUBTYPE}")
set(HASWELL_SUPPORTED Off)
if(SUBTYPE_MATCHED)
if(${CMAKE_MATCH_1} GREATER 7)
set(HASWELL_SUPPORTED On)
endif()
endif()
if(NOT HASWELL_SUPPORTED)
list(REMOVE_ITEM tmp_var x86_64h)
endif()
set(${output} ${tmp_var} PARENT_SCOPE)
endfunction()
# Read and process the exclude file into a list of symbols
function(darwin_read_list_from_file output_var file)
if(EXISTS ${file})
file(READ ${file} EXCLUDES)
string(REPLACE "\n" ";" EXCLUDES ${EXCLUDES})
set(${output_var} ${EXCLUDES} PARENT_SCOPE)
endif()
endfunction()
# this function takes an OS, architecture and minimum version and provides a
# list of builtin functions to exclude
function(darwin_find_excluded_builtins_list output_var)
cmake_parse_arguments(LIB
""
"OS;ARCH;MIN_VERSION"
""
${ARGN})
if(NOT LIB_OS OR NOT LIB_ARCH)
message(FATAL_ERROR "Must specify OS and ARCH to darwin_find_excluded_builtins_list!")
endif()
darwin_read_list_from_file(${LIB_OS}_BUILTINS
${DARWIN_EXCLUDE_DIR}/${LIB_OS}.txt)
darwin_read_list_from_file(${LIB_OS}_${LIB_ARCH}_BASE_BUILTINS
${DARWIN_EXCLUDE_DIR}/${LIB_OS}-${LIB_ARCH}.txt)
if(LIB_MIN_VERSION)
file(GLOB builtin_lists ${DARWIN_EXCLUDE_DIR}/${LIB_OS}*-${LIB_ARCH}.txt)
foreach(builtin_list ${builtin_lists})
string(REGEX MATCH "${LIB_OS}([0-9\\.]*)-${LIB_ARCH}.txt" VERSION_MATCHED "${builtin_list}")
if (VERSION_MATCHED AND NOT CMAKE_MATCH_1 VERSION_LESS LIB_MIN_VERSION)
if(NOT smallest_version)
set(smallest_version ${CMAKE_MATCH_1})
elseif(CMAKE_MATCH_1 VERSION_LESS smallest_version)
set(smallest_version ${CMAKE_MATCH_1})
endif()
endif()
endforeach()
if(smallest_version)
darwin_read_list_from_file(${LIB_ARCH}_${LIB_OS}_BUILTINS
${DARWIN_EXCLUDE_DIR}/${LIB_OS}${smallest_version}-${LIB_ARCH}.txt)
endif()
endif()
set(${output_var}
${${LIB_ARCH}_${LIB_OS}_BUILTINS}
${${LIB_OS}_${LIB_ARCH}_BASE_BUILTINS}
${${LIB_OS}_BUILTINS} PARENT_SCOPE)
endfunction()
# adds a single builtin library for a single OS & ARCH
macro(darwin_add_builtin_library name suffix)
cmake_parse_arguments(LIB
""
"PARENT_TARGET;OS;ARCH"
"SOURCES;CFLAGS;DEFS"
${ARGN})
set(libname "${name}.${suffix}_${LIB_ARCH}_${LIB_OS}")
add_library(${libname} STATIC ${LIB_SOURCES})
if(DARWIN_${LIB_OS}_SYSROOT)
set(sysroot_flag -isysroot ${DARWIN_${LIB_OS}_SYSROOT})
endif()
# Make a copy of the compilation flags.
set(builtin_cflags ${LIB_CFLAGS})
# Strip out any inappropriate flags for the target.
if("${LIB_ARCH}" MATCHES "^(armv7|armv7k|armv7s)$")
set(builtin_cflags "")
foreach(cflag "${LIB_CFLAGS}")
string(REPLACE "-fomit-frame-pointer" "" cflag "${cflag}")
list(APPEND builtin_cflags ${cflag})
endforeach(cflag)
endif()
set_target_compile_flags(${libname}
${sysroot_flag}
${DARWIN_${LIB_OS}_BUILTIN_MIN_VER_FLAG}
${builtin_cflags})
set_property(TARGET ${libname} APPEND PROPERTY
COMPILE_DEFINITIONS ${LIB_DEFS})
set_target_properties(${libname} PROPERTIES
OUTPUT_NAME ${libname}${COMPILER_RT_OS_SUFFIX})
set_target_properties(${libname} PROPERTIES
OSX_ARCHITECTURES ${LIB_ARCH})
if(LIB_PARENT_TARGET)
add_dependencies(${LIB_PARENT_TARGET} ${libname})
endif()
list(APPEND ${LIB_OS}_${suffix}_libs ${libname})
list(APPEND ${LIB_OS}_${suffix}_lipo_flags -arch ${arch} $<TARGET_FILE:${libname}>)
set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Libraries")
endmacro()
function(darwin_lipo_libs name)
cmake_parse_arguments(LIB
""
"PARENT_TARGET;OUTPUT_DIR;INSTALL_DIR"
"LIPO_FLAGS;DEPENDS"
${ARGN})
if(LIB_DEPENDS AND LIB_LIPO_FLAGS)
add_custom_command(OUTPUT ${LIB_OUTPUT_DIR}/lib${name}.a
COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_OUTPUT_DIR}
COMMAND lipo -output
${LIB_OUTPUT_DIR}/lib${name}.a
-create ${LIB_LIPO_FLAGS}
DEPENDS ${LIB_DEPENDS}
)
add_custom_target(${name}
DEPENDS ${LIB_OUTPUT_DIR}/lib${name}.a)
add_dependencies(${LIB_PARENT_TARGET} ${name})
install(FILES ${LIB_OUTPUT_DIR}/lib${name}.a
DESTINATION ${LIB_INSTALL_DIR})
set_target_properties(${name} PROPERTIES FOLDER "Compiler-RT Misc")
else()
message(WARNING "Not generating lipo target for ${name} because no input libraries exist.")
endif()
endfunction()
# Generates builtin libraries for all operating systems specified in ARGN. Each
# OS library is constructed by lipo-ing together single-architecture libraries.
macro(darwin_add_builtin_libraries)
set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes)
set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer")
set(CMAKE_C_FLAGS "")
set(CMAKE_CXX_FLAGS "")
set(CMAKE_ASM_FLAGS "")
set(PROFILE_SOURCES ../profile/InstrProfiling
../profile/InstrProfilingBuffer
../profile/InstrProfilingPlatformDarwin
../profile/InstrProfilingWriter)
foreach (os ${ARGN})
list_intersect(DARWIN_BUILTIN_ARCHS DARWIN_${os}_ARCHS BUILTIN_SUPPORTED_ARCH)
foreach (arch ${DARWIN_BUILTIN_ARCHS})
darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS
OS ${os}
ARCH ${arch}
MIN_VERSION ${DARWIN_${os}_BUILTIN_MIN_VER})
filter_builtin_sources(filtered_sources
EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS
${${arch}_SOURCES})
darwin_add_builtin_library(clang_rt builtins
OS ${os}
ARCH ${arch}
SOURCES ${filtered_sources}
CFLAGS ${CFLAGS} -arch ${arch}
PARENT_TARGET builtins)
endforeach()
# Don't build cc_kext libraries for simulator platforms
if(NOT DARWIN_${os}_SKIP_CC_KEXT)
foreach (arch ${DARWIN_BUILTIN_ARCHS})
# By not specifying MIN_VERSION this only reads the OS and OS-arch lists.
# We don't want to filter out the builtins that are present in libSystem
# because kexts can't link libSystem.
darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS
OS ${os}
ARCH ${arch})
filter_builtin_sources(filtered_sources
EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS
${${arch}_SOURCES})
# In addition to the builtins cc_kext includes some profile sources
darwin_add_builtin_library(clang_rt cc_kext
OS ${os}
ARCH ${arch}
SOURCES ${filtered_sources} ${PROFILE_SOURCES}
CFLAGS ${CFLAGS} -arch ${arch} -mkernel
DEFS KERNEL_USE
PARENT_TARGET builtins)
endforeach()
set(archive_name clang_rt.cc_kext_${os})
if(${os} STREQUAL "osx")
set(archive_name clang_rt.cc_kext)
endif()
darwin_lipo_libs(${archive_name}
PARENT_TARGET builtins
LIPO_FLAGS ${${os}_cc_kext_lipo_flags}
DEPENDS ${${os}_cc_kext_libs}
OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR})
endif()
endforeach()
# We put the x86 sim slices into the archives for their base OS
foreach (os ${ARGN})
if(NOT ${os} MATCHES ".*sim$")
darwin_lipo_libs(clang_rt.${os}
PARENT_TARGET builtins
LIPO_FLAGS ${${os}_builtins_lipo_flags} ${${os}sim_builtins_lipo_flags}
DEPENDS ${${os}_builtins_libs} ${${os}sim_builtins_libs}
OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR})
endif()
endforeach()
darwin_add_embedded_builtin_libraries()
endmacro()
macro(darwin_add_embedded_builtin_libraries)
# this is a hacky opt-out. If you can't target both intel and arm
# architectures we bail here.
set(DARWIN_SOFT_FLOAT_ARCHS armv6m armv7m armv7em armv7)
set(DARWIN_HARD_FLOAT_ARCHS armv7em armv7)
if(COMPILER_RT_SUPPORTED_ARCH MATCHES ".*armv.*")
list(FIND COMPILER_RT_SUPPORTED_ARCH i386 i386_idx)
if(i386_idx GREATER -1)
list(APPEND DARWIN_HARD_FLOAT_ARCHS i386)
endif()
list(FIND COMPILER_RT_SUPPORTED_ARCH x86_64 x86_64_idx)
if(x86_64_idx GREATER -1)
list(APPEND DARWIN_HARD_FLOAT_ARCHS x86_64)
endif()
set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded)
set(CFLAGS "-Oz -Wall -fomit-frame-pointer -ffreestanding")
set(CMAKE_C_FLAGS "")
set(CMAKE_CXX_FLAGS "")
set(CMAKE_ASM_FLAGS "")
set(SOFT_FLOAT_FLAG -mfloat-abi=soft)
set(HARD_FLOAT_FLAG -mfloat-abi=hard)
set(ENABLE_PIC Off)
set(PIC_FLAG -fPIC)
set(STATIC_FLAG -static)
set(DARWIN_macho_embedded_ARCHS armv6m armv7m armv7em armv7 i386 x86_64)
set(DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR
${COMPILER_RT_OUTPUT_DIR}/lib/macho_embedded)
set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR
${COMPILER_RT_INSTALL_PATH}/lib/macho_embedded)
set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi")
set(CFLAGS_i386 "-march=pentium")
darwin_read_list_from_file(common_FUNCTIONS ${MACHO_SYM_DIR}/common.txt)
darwin_read_list_from_file(thumb2_FUNCTIONS ${MACHO_SYM_DIR}/thumb2.txt)
darwin_read_list_from_file(thumb2_64_FUNCTIONS ${MACHO_SYM_DIR}/thumb2-64.txt)
darwin_read_list_from_file(arm_FUNCTIONS ${MACHO_SYM_DIR}/arm.txt)
darwin_read_list_from_file(i386_FUNCTIONS ${MACHO_SYM_DIR}/i386.txt)
set(armv6m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS})
set(armv7m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS})
set(armv7em_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS})
set(armv7_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS} ${thumb2_64_FUNCTIONS})
set(i386_FUNCTIONS ${common_FUNCTIONS} ${i386_FUNCTIONS})
set(x86_64_FUNCTIONS ${common_FUNCTIONS})
foreach(arch ${DARWIN_macho_embedded_ARCHS})
filter_builtin_sources(${arch}_filtered_sources
INCLUDE ${arch}_FUNCTIONS
${${arch}_SOURCES})
if(NOT ${arch}_filtered_sources)
message("${arch}_SOURCES: ${${arch}_SOURCES}")
message("${arch}_FUNCTIONS: ${${arch}_FUNCTIONS}")
message(FATAL_ERROR "Empty filtered sources!")
endif()
endforeach()
foreach(float_type SOFT HARD)
foreach(type PIC STATIC)
string(TOLOWER "${float_type}_${type}" lib_suffix)
foreach(arch ${DARWIN_${float_type}_FLOAT_ARCHS})
set(DARWIN_macho_embedded_SYSROOT ${DARWIN_osx_SYSROOT})
set(float_flag)
if(${arch} MATCHES "^arm")
# x86 targets are hard float by default, but the complain about the
# float ABI flag, so don't pass it unless we're targeting arm.
set(float_flag ${${float_type}_FLOAT_FLAG})
endif()
darwin_add_builtin_library(clang_rt ${lib_suffix}
OS macho_embedded
ARCH ${arch}
SOURCES ${${arch}_filtered_sources}
CFLAGS ${CFLAGS} -arch ${arch} ${${type}_FLAG} ${float_flag} ${CFLAGS_${arch}}
PARENT_TARGET builtins)
endforeach()
foreach(lib ${macho_embedded_${lib_suffix}_libs})
set_target_properties(${lib} PROPERTIES LINKER_LANGUAGE C)
endforeach()
darwin_lipo_libs(clang_rt.${lib_suffix}
PARENT_TARGET builtins
LIPO_FLAGS ${macho_embedded_${lib_suffix}_lipo_flags}
DEPENDS ${macho_embedded_${lib_suffix}_libs}
OUTPUT_DIR ${DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR}
INSTALL_DIR ${DARWIN_macho_embedded_LIBRARY_INSTALL_DIR})
endforeach()
endforeach()
endif()
endmacro()

View File

@ -1,16 +0,0 @@
# Link a shared library with COMPILER_RT_TEST_COMPILER.
# clang_link_shared(<output.so>
# OBJECTS <list of input objects>
# LINK_FLAGS <list of link flags>
# DEPS <list of dependencies>)
macro(clang_link_shared so_file)
cmake_parse_arguments(SOURCE "" "" "OBJECTS;LINK_FLAGS;DEPS" ${ARGN})
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND SOURCE_DEPS clang)
endif()
add_custom_command(
OUTPUT ${so_file}
COMMAND ${COMPILER_RT_TEST_COMPILER} -o "${so_file}" -shared
${SOURCE_LINK_FLAGS} ${SOURCE_OBJECTS}
DEPENDS ${SOURCE_DEPS})
endmacro()

View File

@ -1,415 +0,0 @@
include(CMakePushCheckState)
include(CheckSymbolExists)
# Because compiler-rt spends a lot of time setting up custom compile flags,
# define a handy helper function for it. The compile flags setting in CMake
# has serious issues that make its syntax challenging at best.
function(set_target_compile_flags target)
set(argstring "")
foreach(arg ${ARGN})
set(argstring "${argstring} ${arg}")
endforeach()
set_property(TARGET ${target} PROPERTY COMPILE_FLAGS "${argstring}")
endfunction()
function(set_target_link_flags target)
set(argstring "")
foreach(arg ${ARGN})
set(argstring "${argstring} ${arg}")
endforeach()
set_property(TARGET ${target} PROPERTY LINK_FLAGS "${argstring}")
endfunction()
# Set the variable var_PYBOOL to True if var holds a true-ish string,
# otherwise set it to False.
macro(pythonize_bool var)
if (${var})
set(${var}_PYBOOL True)
else()
set(${var}_PYBOOL False)
endif()
endmacro()
# Appends value to all lists in ARGN, if the condition is true.
macro(append_list_if condition value)
if(${condition})
foreach(list ${ARGN})
list(APPEND ${list} ${value})
endforeach()
endif()
endmacro()
# Appends value to all strings in ARGN, if the condition is true.
macro(append_string_if condition value)
if(${condition})
foreach(str ${ARGN})
set(${str} "${${str}} ${value}")
endforeach()
endif()
endmacro()
macro(append_rtti_flag polarity list)
if(${polarity})
append_list_if(COMPILER_RT_HAS_FRTTI_FLAG -frtti ${list})
append_list_if(COMPILER_RT_HAS_GR_FLAG /GR ${list})
else()
append_list_if(COMPILER_RT_HAS_FNO_RTTI_FLAG -fno-rtti ${list})
append_list_if(COMPILER_RT_HAS_GR_FLAG /GR- ${list})
endif()
endmacro()
macro(list_intersect output input1 input2)
set(${output})
foreach(it ${${input1}})
list(FIND ${input2} ${it} index)
if( NOT (index EQUAL -1))
list(APPEND ${output} ${it})
endif()
endforeach()
endmacro()
function(list_replace input_list old new)
set(replaced_list)
foreach(item ${${input_list}})
if(${item} STREQUAL ${old})
list(APPEND replaced_list ${new})
else()
list(APPEND replaced_list ${item})
endif()
endforeach()
set(${input_list} "${replaced_list}" PARENT_SCOPE)
endfunction()
# Takes ${ARGN} and puts only supported architectures in @out_var list.
function(filter_available_targets out_var)
set(archs ${${out_var}})
foreach(arch ${ARGN})
list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX)
if(NOT (ARCH_INDEX EQUAL -1) AND CAN_TARGET_${arch})
list(APPEND archs ${arch})
endif()
endforeach()
set(${out_var} ${archs} PARENT_SCOPE)
endfunction()
# Add $arch as supported with no additional flags.
macro(add_default_target_arch arch)
set(TARGET_${arch}_CFLAGS "")
set(CAN_TARGET_${arch} 1)
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
endmacro()
function(check_compile_definition def argstring out_var)
if("${def}" STREQUAL "")
set(${out_var} TRUE PARENT_SCOPE)
return()
endif()
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${argstring}")
check_symbol_exists(${def} "" ${out_var})
cmake_pop_check_state()
endfunction()
# test_target_arch(<arch> <def> <target flags...>)
# Checks if architecture is supported: runs host compiler with provided
# flags to verify that:
# 1) <def> is defined (if non-empty)
# 2) simple file can be successfully built.
# If successful, saves target flags for this architecture.
macro(test_target_arch arch def)
set(TARGET_${arch}_CFLAGS ${ARGN})
set(TARGET_${arch}_LINK_FLAGS ${ARGN})
set(argstring "")
foreach(arg ${ARGN})
set(argstring "${argstring} ${arg}")
endforeach()
check_compile_definition("${def}" "${argstring}" HAS_${arch}_DEF)
if(NOT DEFINED CAN_TARGET_${arch})
if(NOT HAS_${arch}_DEF)
set(CAN_TARGET_${arch} FALSE)
elseif(TEST_COMPILE_ONLY)
try_compile_only(CAN_TARGET_${arch} ${TARGET_${arch}_CFLAGS})
else()
set(FLAG_NO_EXCEPTIONS "")
if(COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG)
set(FLAG_NO_EXCEPTIONS " -fno-exceptions ")
endif()
set(SAVED_CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${argstring}")
try_compile(CAN_TARGET_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_SOURCE}
COMPILE_DEFINITIONS "${TARGET_${arch}_CFLAGS} ${FLAG_NO_EXCEPTIONS}"
OUTPUT_VARIABLE TARGET_${arch}_OUTPUT)
set(CMAKE_EXE_LINKER_FLAGS ${SAVED_CMAKE_EXE_LINKER_FLAGS})
endif()
endif()
if(${CAN_TARGET_${arch}})
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" STREQUAL "${arch}" AND
COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE)
# Bail out if we cannot target the architecture we plan to test.
message(FATAL_ERROR "Cannot compile for ${arch}:\n${TARGET_${arch}_OUTPUT}")
endif()
endmacro()
macro(detect_target_arch)
check_symbol_exists(__arm__ "" __ARM)
check_symbol_exists(__aarch64__ "" __AARCH64)
check_symbol_exists(__x86_64__ "" __X86_64)
check_symbol_exists(__i386__ "" __I386)
check_symbol_exists(__mips__ "" __MIPS)
check_symbol_exists(__mips64__ "" __MIPS64)
check_symbol_exists(__powerpc64__ "" __PPC64)
check_symbol_exists(__powerpc64le__ "" __PPC64LE)
check_symbol_exists(__riscv "" __RISCV)
check_symbol_exists(__s390x__ "" __S390X)
check_symbol_exists(__wasm32__ "" __WEBASSEMBLY32)
check_symbol_exists(__wasm64__ "" __WEBASSEMBLY64)
if(__ARM)
add_default_target_arch(arm)
elseif(__AARCH64)
add_default_target_arch(aarch64)
elseif(__X86_64)
add_default_target_arch(x86_64)
elseif(__I386)
add_default_target_arch(i386)
elseif(__MIPS64) # must be checked before __MIPS
add_default_target_arch(mips64)
elseif(__MIPS)
add_default_target_arch(mips)
elseif(__PPC64)
add_default_target_arch(powerpc64)
elseif(__PPC64LE)
add_default_target_arch(powerpc64le)
elseif(__RISCV)
if(CMAKE_SIZEOF_VOID_P EQUAL "4")
add_default_target_arch(riscv32)
elseif(CMAKE_SIZEOF_VOID_P EQUAL "8")
add_default_target_arch(riscv64)
else()
message(FATAL_ERROR "Unsupport XLEN for RISC-V")
endif()
elseif(__S390X)
add_default_target_arch(s390x)
elseif(__WEBASSEMBLY32)
add_default_target_arch(wasm32)
elseif(__WEBASSEMBLY64)
add_default_target_arch(wasm64)
endif()
endmacro()
macro(load_llvm_config)
if (NOT LLVM_CONFIG_PATH)
find_program(LLVM_CONFIG_PATH "llvm-config"
DOC "Path to llvm-config binary")
if (NOT LLVM_CONFIG_PATH)
message(WARNING "UNSUPPORTED COMPILER-RT CONFIGURATION DETECTED: "
"llvm-config not found.\n"
"Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config.")
endif()
endif()
if (LLVM_CONFIG_PATH)
execute_process(
COMMAND ${LLVM_CONFIG_PATH} "--obj-root" "--bindir" "--libdir" "--src-root" "--includedir"
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE CONFIG_OUTPUT)
if (HAD_ERROR)
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
endif()
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT})
list(GET CONFIG_OUTPUT 0 BINARY_DIR)
list(GET CONFIG_OUTPUT 1 TOOLS_BINARY_DIR)
list(GET CONFIG_OUTPUT 2 LIBRARY_DIR)
list(GET CONFIG_OUTPUT 3 MAIN_SRC_DIR)
list(GET CONFIG_OUTPUT 4 INCLUDE_DIR)
set(LLVM_BINARY_DIR ${BINARY_DIR} CACHE PATH "Path to LLVM build tree")
set(LLVM_LIBRARY_DIR ${LIBRARY_DIR} CACHE PATH "Path to llvm/lib")
set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
set(LLVM_TOOLS_BINARY_DIR ${TOOLS_BINARY_DIR} CACHE PATH "Path to llvm/bin")
set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Paths to LLVM headers")
# Detect if we have the LLVMXRay and TestingSupport library installed and
# available from llvm-config.
execute_process(
COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "xray"
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE CONFIG_OUTPUT)
if (HAD_ERROR)
message(WARNING "llvm-config finding xray failed with status ${HAD_ERROR}")
set(COMPILER_RT_HAS_LLVMXRAY FALSE)
else()
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT})
list(GET CONFIG_OUTPUT 0 LDFLAGS)
list(GET CONFIG_OUTPUT 1 LIBLIST)
set(LLVM_XRAY_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMXRay library")
set(LLVM_XRAY_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMXRay")
set(COMPILER_RT_HAS_LLVMXRAY TRUE)
endif()
set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT FALSE)
execute_process(
COMMAND ${LLVM_CONFIG_PATH} "--ldflags" "--libs" "testingsupport"
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE CONFIG_OUTPUT)
if (HAD_ERROR)
message(WARNING "llvm-config finding testingsupport failed with status ${HAD_ERROR}")
else()
string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT})
list(GET CONFIG_OUTPUT 0 LDFLAGS)
list(GET CONFIG_OUTPUT 1 LIBLIST)
if (LIBLIST STREQUAL "")
message(WARNING "testingsupport library not installed, some tests will be skipped")
else()
set(LLVM_TESTINGSUPPORT_LDFLAGS ${LDFLAGS} CACHE STRING "Linker flags for LLVMTestingSupport library")
set(LLVM_TESTINGSUPPORT_LIBLIST ${LIBLIST} CACHE STRING "Library list for LLVMTestingSupport")
set(COMPILER_RT_HAS_LLVMTESTINGSUPPORT TRUE)
endif()
endif()
# Make use of LLVM CMake modules.
# --cmakedir is supported since llvm r291218 (4.0 release)
execute_process(
COMMAND ${LLVM_CONFIG_PATH} --cmakedir
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE CONFIG_OUTPUT)
if(NOT HAD_ERROR)
string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG)
file(TO_CMAKE_PATH ${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG} LLVM_CMAKE_PATH)
else()
file(TO_CMAKE_PATH ${LLVM_BINARY_DIR} LLVM_BINARY_DIR_CMAKE_STYLE)
set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
endif()
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
# Get some LLVM variables from LLVMConfig.
include("${LLVM_CMAKE_PATH}/LLVMConfig.cmake")
set(LLVM_LIBRARY_OUTPUT_INTDIR
${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})
endif()
endmacro()
macro(construct_compiler_rt_default_triple)
if(COMPILER_RT_DEFAULT_TARGET_ONLY)
if(DEFINED COMPILER_RT_DEFAULT_TARGET_TRIPLE)
message(FATAL_ERROR "COMPILER_RT_DEFAULT_TARGET_TRIPLE isn't supported when building for default target only")
endif()
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${CMAKE_C_COMPILER_TARGET})
else()
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${TARGET_TRIPLE} CACHE STRING
"Default triple for which compiler-rt runtimes will be built.")
endif()
if(DEFINED COMPILER_RT_TEST_TARGET_TRIPLE)
# Backwards compatibility: this variable used to be called
# COMPILER_RT_TEST_TARGET_TRIPLE.
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${COMPILER_RT_TEST_TARGET_TRIPLE})
endif()
string(REPLACE "-" ";" TARGET_TRIPLE_LIST ${COMPILER_RT_DEFAULT_TARGET_TRIPLE})
list(GET TARGET_TRIPLE_LIST 0 COMPILER_RT_DEFAULT_TARGET_ARCH)
# Determine if test target triple is specified explicitly, and doesn't match the
# default.
if(NOT COMPILER_RT_DEFAULT_TARGET_TRIPLE STREQUAL TARGET_TRIPLE)
set(COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE TRUE)
else()
set(COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE FALSE)
endif()
endmacro()
# 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.
function(filter_builtin_sources output_var exclude_or_include excluded_list)
if(exclude_or_include STREQUAL "EXCLUDE")
set(filter_action GREATER)
set(filter_value -1)
elseif(exclude_or_include STREQUAL "INCLUDE")
set(filter_action LESS)
set(filter_value 0)
else()
message(FATAL_ERROR "filter_builtin_sources called without EXCLUDE|INCLUDE")
endif()
set(intermediate ${ARGN})
foreach (_file ${intermediate})
get_filename_component(_name_we ${_file} NAME_WE)
list(FIND ${excluded_list} ${_name_we} _found)
if(_found ${filter_action} ${filter_value})
list(REMOVE_ITEM intermediate ${_file})
elseif(${_file} MATCHES ".*/.*\\.S" OR ${_file} MATCHES ".*/.*\\.c")
get_filename_component(_name ${_file} NAME)
string(REPLACE ".S" ".c" _cname "${_name}")
list(REMOVE_ITEM intermediate ${_cname})
endif ()
endforeach ()
set(${output_var} ${intermediate} PARENT_SCOPE)
endfunction()
function(get_compiler_rt_target arch variable)
string(FIND ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} "-" dash_index)
string(SUBSTRING ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} ${dash_index} -1 triple_suffix)
if(COMPILER_RT_DEFAULT_TARGET_ONLY)
# Use exact spelling when building only for the target specified to CMake.
set(target "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}")
elseif(ANDROID AND ${arch} STREQUAL "i386")
set(target "i686${COMPILER_RT_OS_SUFFIX}${triple_suffix}")
else()
set(target "${arch}${triple_suffix}")
endif()
set(${variable} ${target} PARENT_SCOPE)
endfunction()
function(get_compiler_rt_install_dir arch install_dir)
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
get_compiler_rt_target(${arch} target)
set(${install_dir} ${COMPILER_RT_INSTALL_PATH}/${target}/lib PARENT_SCOPE)
else()
set(${install_dir} ${COMPILER_RT_LIBRARY_INSTALL_DIR} PARENT_SCOPE)
endif()
endfunction()
function(get_compiler_rt_output_dir arch output_dir)
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
get_compiler_rt_target(${arch} target)
set(${output_dir} ${COMPILER_RT_OUTPUT_DIR}/${target}/lib PARENT_SCOPE)
else()
set(${output_dir} ${COMPILER_RT_LIBRARY_OUTPUT_DIR} PARENT_SCOPE)
endif()
endfunction()
# compiler_rt_process_sources(
# <OUTPUT_VAR>
# <SOURCE_FILE> ...
# [ADDITIONAL_HEADERS <header> ...]
# )
#
# Process the provided sources and write the list of new sources
# into `<OUTPUT_VAR>`.
#
# ADDITIONAL_HEADERS - Adds the supplied header to list of sources for IDEs.
#
# This function is very similar to `llvm_process_sources()` but exists here
# because we need to support standalone builds of compiler-rt.
function(compiler_rt_process_sources OUTPUT_VAR)
cmake_parse_arguments(
ARG
""
""
"ADDITIONAL_HEADERS"
${ARGN}
)
set(sources ${ARG_UNPARSED_ARGUMENTS})
set(headers "")
if (XCODE OR MSVC_IDE OR CMAKE_EXTRA_GENERATOR)
# For IDEs we need to tell CMake about header files.
# Otherwise they won't show up in UI.
set(headers ${ARG_ADDITIONAL_HEADERS})
list(LENGTH headers headers_length)
if (${headers_length} GREATER 0)
set_source_files_properties(${headers}
PROPERTIES HEADER_FILE_ONLY ON)
endif()
endif()
set("${OUTPUT_VAR}" ${sources} ${headers} PARENT_SCOPE)
endfunction()

View File

@ -1,24 +0,0 @@
function(find_compiler_rt_library name variable)
set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${SANITIZER_COMMON_CFLAGS}
"--rtlib=compiler-rt" "--print-libgcc-file-name")
if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_CXX_COMPILER_TARGET)
list(APPEND CLANG_COMMAND "--target=${CMAKE_CXX_COMPILER_TARGET}")
endif()
get_property(SANITIZER_CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE)
string(REPLACE " " ";" SANITIZER_CXX_FLAGS "${SANITIZER_CXX_FLAGS}")
list(APPEND CLANG_COMMAND ${SANITIZER_CXX_FLAGS})
execute_process(
COMMAND ${CLANG_COMMAND}
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE LIBRARY_FILE
)
string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE)
file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE)
string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}")
if (NOT HAD_ERROR AND EXISTS "${LIBRARY_FILE}")
message(STATUS "Found compiler-rt ${name} library: ${LIBRARY_FILE}")
set(${variable} "${LIBRARY_FILE}" PARENT_SCOPE)
else()
message(STATUS "Failed to find compiler-rt ${name} library")
endif()
endfunction()

View File

@ -1,108 +0,0 @@
include(CompilerRTUtils)
set(SANITIZER_GEN_DYNAMIC_LIST
${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/scripts/gen_dynamic_list.py)
set(SANITIZER_LINT_SCRIPT
${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/scripts/check_lint.sh)
# Create a target "<name>-<arch>-symbols" that would generate the list of
# symbols that need to be exported from sanitizer runtime "<name>". Function
# interceptors are exported automatically, user can also provide files with
# symbol names that should be exported as well.
# add_sanitizer_rt_symbols(<name>
# ARCHS <architectures>
# PARENT_TARGET <convenience parent target>
# EXTRA <files with extra symbols to export>)
macro(add_sanitizer_rt_symbols name)
cmake_parse_arguments(ARG
""
"PARENT_TARGET"
"ARCHS;EXTRA"
${ARGN})
foreach(arch ${ARG_ARCHS})
set(target_name ${name}-${arch})
set(stamp ${CMAKE_CURRENT_BINARY_DIR}/${target_name}.syms-stamp)
set(extra_args)
foreach(arg ${ARG_EXTRA})
list(APPEND extra_args "--extra" ${arg})
endforeach()
add_custom_command(OUTPUT ${stamp}
COMMAND ${PYTHON_EXECUTABLE}
${SANITIZER_GEN_DYNAMIC_LIST} ${extra_args} $<TARGET_FILE:${target_name}>
-o $<TARGET_FILE:${target_name}>.syms
COMMAND ${CMAKE_COMMAND} -E touch ${stamp}
DEPENDS ${target_name} ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating exported symbols for ${target_name}"
VERBATIM)
add_custom_target(${target_name}-symbols ALL
DEPENDS ${stamp}
SOURCES ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA})
get_compiler_rt_install_dir(${arch} install_dir)
install(FILES $<TARGET_FILE:${target_name}>.syms
DESTINATION ${install_dir})
if(ARG_PARENT_TARGET)
add_dependencies(${ARG_PARENT_TARGET} ${target_name}-symbols)
endif()
endforeach()
endmacro()
# This function is only used on Darwin, where undefined symbols must be specified
# in the linker invocation.
function(add_weak_symbols libname link_flags)
set(weak_symbols_file "${COMPILER_RT_SOURCE_DIR}/lib/${libname}/weak_symbols.txt")
file(STRINGS "${weak_symbols_file}" WEAK_SYMBOLS)
# Add this file as a configure-time dependency so that changes to this
# file trigger a re-configure. This is necessary so that `${link_flags}`
# is changed when appropriate.
set_property(
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND
PROPERTY CMAKE_CONFIGURE_DEPENDS "${weak_symbols_file}")
set(local_link_flags ${${link_flags}})
foreach(SYMBOL ${WEAK_SYMBOLS})
set(local_link_flags ${local_link_flags} -Wl,-U,${SYMBOL})
endforeach()
set(${link_flags} ${local_link_flags} PARENT_SCOPE)
endfunction()
macro(add_sanitizer_rt_version_list name)
set(vers ${CMAKE_CURRENT_BINARY_DIR}/${name}.vers)
cmake_parse_arguments(ARG "" "" "LIBS;EXTRA" ${ARGN})
set(args)
foreach(arg ${ARG_EXTRA})
list(APPEND args "--extra" ${arg})
endforeach()
foreach(arg ${ARG_LIBS})
list(APPEND args "$<TARGET_FILE:${arg}>")
endforeach()
add_custom_command(OUTPUT ${vers}
COMMAND ${PYTHON_EXECUTABLE}
${SANITIZER_GEN_DYNAMIC_LIST} --version-list ${args}
-o ${vers}
DEPENDS ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA} ${ARG_LIBS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating version list for ${name}"
VERBATIM)
add_custom_target(${name}-version-list ALL
DEPENDS ${vers})
endmacro()
# Add target to check code style for sanitizer runtimes.
if(CMAKE_HOST_UNIX AND NOT OS_NAME MATCHES "OpenBSD")
add_custom_target(SanitizerLintCheck
COMMAND env LLVM_CHECKOUT=${LLVM_MAIN_SRC_DIR} SILENT=1 TMPDIR=
PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
COMPILER_RT=${COMPILER_RT_SOURCE_DIR}
${SANITIZER_LINT_SCRIPT}
DEPENDS ${SANITIZER_LINT_SCRIPT}
COMMENT "Running lint check for sanitizer sources..."
VERBATIM)
else()
add_custom_target(SanitizerLintCheck
COMMAND echo "No lint check")
endif()
set_target_properties(SanitizerLintCheck
PROPERTIES FOLDER "Compiler-RT Misc")

View File

@ -1,226 +0,0 @@
# The CompilerRT build system requires CMake version 2.8.8 or higher in order
# to use its support for building convenience "libraries" as a collection of
# .o files. This is particularly useful in producing larger, more complex
# runtime libraries.
include(CheckIncludeFile)
include(CheckCXXSourceCompiles)
check_include_file(unwind.h HAVE_UNWIND_H)
# Used by sanitizer_common and tests.
check_include_file(rpc/xdr.h HAVE_RPC_XDR_H)
if (NOT HAVE_RPC_XDR_H)
set(HAVE_RPC_XDR_H 0)
endif()
# Top level target used to build all compiler-rt libraries.
add_custom_target(compiler-rt ALL)
add_custom_target(install-compiler-rt)
add_custom_target(install-compiler-rt-stripped)
set_property(
TARGET
compiler-rt
install-compiler-rt
install-compiler-rt-stripped
PROPERTY
FOLDER "Compiler-RT Misc"
)
# Setting these variables from an LLVM build is sufficient that compiler-rt can
# construct the output paths, so it can behave as if it were in-tree here.
if (LLVM_LIBRARY_OUTPUT_INTDIR AND LLVM_RUNTIME_OUTPUT_INTDIR AND PACKAGE_VERSION)
set(LLVM_TREE_AVAILABLE On)
endif()
if (LLVM_TREE_AVAILABLE)
# Compute the Clang version from the LLVM version.
# FIXME: We should be able to reuse CLANG_VERSION variable calculated
# in Clang cmake files, instead of copying the rules here.
string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
${PACKAGE_VERSION})
# Setup the paths where compiler-rt runtimes and headers should be stored.
set(COMPILER_RT_OUTPUT_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION})
set(COMPILER_RT_EXEC_OUTPUT_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
set(COMPILER_RT_INSTALL_PATH lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION})
option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests."
${LLVM_INCLUDE_TESTS})
option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered"
${LLVM_ENABLE_WERROR})
# Use just-built Clang to compile/link tests on all platforms, except for
# Windows where we need to use clang-cl instead.
if(NOT MSVC)
set(COMPILER_RT_TEST_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)
set(COMPILER_RT_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++)
else()
set(COMPILER_RT_TEST_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang.exe)
set(COMPILER_RT_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++.exe)
endif()
else()
# Take output dir and install path from the user.
set(COMPILER_RT_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH
"Path where built compiler-rt libraries should be stored.")
set(COMPILER_RT_EXEC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin CACHE PATH
"Path where built compiler-rt executables should be stored.")
set(COMPILER_RT_INSTALL_PATH ${CMAKE_INSTALL_PREFIX} CACHE PATH
"Path where built compiler-rt libraries should be installed.")
option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests." OFF)
option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered" OFF)
# Use a host compiler to compile/link tests.
set(COMPILER_RT_TEST_COMPILER ${CMAKE_C_COMPILER} CACHE PATH "Compiler to use for testing")
set(COMPILER_RT_TEST_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE PATH "C++ Compiler to use for testing")
endif()
if("${COMPILER_RT_TEST_COMPILER}" MATCHES "clang[+]*$")
set(COMPILER_RT_TEST_COMPILER_ID Clang)
elseif("${COMPILER_RT_TEST_COMPILER}" MATCHES "clang.*.exe$")
set(COMPILER_RT_TEST_COMPILER_ID Clang)
else()
set(COMPILER_RT_TEST_COMPILER_ID GNU)
endif()
if(NOT DEFINED COMPILER_RT_OS_DIR)
string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR)
endif()
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
set(COMPILER_RT_LIBRARY_OUTPUT_DIR
${COMPILER_RT_OUTPUT_DIR})
set(COMPILER_RT_LIBRARY_INSTALL_DIR
${COMPILER_RT_INSTALL_PATH})
else(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
set(COMPILER_RT_LIBRARY_OUTPUT_DIR
${COMPILER_RT_OUTPUT_DIR}/lib/${COMPILER_RT_OS_DIR})
set(COMPILER_RT_LIBRARY_INSTALL_DIR
${COMPILER_RT_INSTALL_PATH}/lib/${COMPILER_RT_OS_DIR})
endif()
if(APPLE)
# On Darwin if /usr/include doesn't exist, the user probably has Xcode but not
# the command line tools. If this is the case, we need to find the OS X
# sysroot to pass to clang.
if(NOT EXISTS /usr/include)
execute_process(COMMAND xcodebuild -version -sdk macosx Path
OUTPUT_VARIABLE OSX_SYSROOT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(OSX_SYSROOT_FLAG "-isysroot${OSX_SYSROOT}")
endif()
option(COMPILER_RT_ENABLE_IOS "Enable building for iOS" On)
option(COMPILER_RT_ENABLE_WATCHOS "Enable building for watchOS - Experimental" Off)
option(COMPILER_RT_ENABLE_TVOS "Enable building for tvOS - Experimental" Off)
else()
option(COMPILER_RT_DEFAULT_TARGET_ONLY "Build builtins only for the default target" Off)
endif()
if(WIN32 AND NOT MINGW AND NOT CYGWIN)
set(CMAKE_SHARED_LIBRARY_PREFIX_C "")
set(CMAKE_SHARED_LIBRARY_PREFIX_CXX "")
set(CMAKE_STATIC_LIBRARY_PREFIX_C "")
set(CMAKE_STATIC_LIBRARY_PREFIX_CXX "")
set(CMAKE_STATIC_LIBRARY_SUFFIX_C ".lib")
set(CMAKE_STATIC_LIBRARY_SUFFIX_CXX ".lib")
endif()
macro(test_targets)
# Find and run MSVC (not clang-cl) and get its version. This will tell clang-cl
# what version of MSVC to pretend to be so that the STL works.
set(MSVC_VERSION_FLAG "")
if (MSVC)
execute_process(COMMAND "$ENV{VSINSTALLDIR}/VC/bin/cl.exe"
OUTPUT_QUIET
ERROR_VARIABLE MSVC_COMPAT_VERSION
)
string(REGEX REPLACE "^.*Compiler Version ([0-9.]+) for .*$" "\\1"
MSVC_COMPAT_VERSION "${MSVC_COMPAT_VERSION}")
if (MSVC_COMPAT_VERSION MATCHES "^[0-9].+$")
set(MSVC_VERSION_FLAG "-fms-compatibility-version=${MSVC_COMPAT_VERSION}")
# Add this flag into the host build if this is clang-cl.
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
append("${MSVC_VERSION_FLAG}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
elseif (COMPILER_RT_TEST_COMPILER_ID MATCHES "Clang")
# Add this flag to test compiles to suppress clang's auto-detection
# logic.
append("${MSVC_VERSION_FLAG}" COMPILER_RT_TEST_COMPILER_CFLAGS)
endif()
endif()
endif()
# Generate the COMPILER_RT_SUPPORTED_ARCH list.
if(ANDROID)
# Examine compiler output to determine target architecture.
detect_target_arch()
set(COMPILER_RT_OS_SUFFIX "-android")
elseif(NOT APPLE) # Supported archs for Apple platforms are generated later
if(COMPILER_RT_DEFAULT_TARGET_ONLY)
add_default_target_arch(${COMPILER_RT_DEFAULT_TARGET_ARCH})
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "i[2-6]86|x86|amd64")
if(NOT MSVC)
if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
test_target_arch(i386 __i386__ "-m32")
else()
test_target_arch(x86_64 "" "-m64")
endif()
else()
test_target_arch(x86_64 "" "-m64")
test_target_arch(i386 __i386__ "-m32")
endif()
else()
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
test_target_arch(i386 "" "")
else()
test_target_arch(x86_64 "" "")
endif()
endif()
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc")
# Strip out -nodefaultlibs when calling TEST_BIG_ENDIAN. Configuration
# will fail with this option when building with a sanitizer.
cmake_push_check_state()
string(REPLACE "-nodefaultlibs" "" CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
TEST_BIG_ENDIAN(HOST_IS_BIG_ENDIAN)
cmake_pop_check_state()
if(HOST_IS_BIG_ENDIAN)
test_target_arch(powerpc64 "" "-m64")
else()
test_target_arch(powerpc64le "" "-m64")
endif()
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "s390x")
test_target_arch(s390x "" "")
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mipsel|mips64el")
# Gcc doesn't accept -m32/-m64 so we do the next best thing and use
# -mips32r2/-mips64r2. We don't use -mips1/-mips3 because we want to match
# clang's default CPU's. In the 64-bit case, we must also specify the ABI
# since the default ABI differs between gcc and clang.
# FIXME: Ideally, we would build the N32 library too.
test_target_arch(mipsel "" "-mips32r2" "-mabi=32")
test_target_arch(mips64el "" "-mips64r2" "-mabi=64")
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mips")
test_target_arch(mips "" "-mips32r2" "-mabi=32")
test_target_arch(mips64 "" "-mips64r2" "-mabi=64")
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "arm")
if(WIN32)
test_target_arch(arm "" "" "")
else()
test_target_arch(arm "" "-march=armv7-a" "-mfloat-abi=soft")
test_target_arch(armhf "" "-march=armv7-a" "-mfloat-abi=hard")
test_target_arch(armv6m "" "-march=armv6m" "-mfloat-abi=soft")
endif()
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch32")
test_target_arch(aarch32 "" "-march=armv8-a")
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch64")
test_target_arch(aarch64 "" "-march=armv8-a")
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "riscv32")
test_target_arch(riscv32 "" "")
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "riscv64")
test_target_arch(riscv64 "" "")
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "wasm32")
test_target_arch(wasm32 "" "--target=wasm32-unknown-unknown")
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "wasm64")
test_target_arch(wasm64 "" "--target=wasm64-unknown-unknown")
endif()
set(COMPILER_RT_OS_SUFFIX "")
endif()
endmacro()

View File

@ -1,167 +0,0 @@
include(BuiltinTests)
include(CheckCSourceCompiles)
# Make all the tests only check the compiler
set(TEST_COMPILE_ONLY On)
# Check host compiler support for certain flags
builtin_check_c_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG)
builtin_check_c_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG)
builtin_check_c_compiler_flag(-fno-builtin COMPILER_RT_HAS_FNO_BUILTIN_FLAG)
builtin_check_c_compiler_flag(-std=c11 COMPILER_RT_HAS_STD_C11_FLAG)
builtin_check_c_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG)
builtin_check_c_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG)
builtin_check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FREESTANDING_FLAG)
builtin_check_c_compiler_flag(-fxray-instrument COMPILER_RT_HAS_XRAY_COMPILER_FLAG)
builtin_check_c_compiler_source(COMPILER_RT_HAS_ATOMIC_KEYWORD
"
int foo(int x, int y) {
_Atomic int result = x * y;
return result;
}
")
set(ARM64 aarch64)
set(ARM32 arm armhf armv6m armv7m armv7em armv7 armv7s armv7k)
set(HEXAGON hexagon)
set(X86 i386)
set(X86_64 x86_64)
set(MIPS32 mips mipsel)
set(MIPS64 mips64 mips64el)
set(PPC64 powerpc64 powerpc64le)
set(RISCV32 riscv32)
set(RISCV64 riscv64)
set(WASM32 wasm32)
set(WASM64 wasm64)
if(APPLE)
set(ARM64 arm64)
set(ARM32 armv7 armv7k armv7s)
set(X86_64 x86_64 x86_64h)
endif()
set(ALL_BUILTIN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
${HEXAGON} ${MIPS32} ${MIPS64} ${PPC64} ${RISCV32} ${RISCV64} ${WASM32} ${WASM64})
include(CompilerRTUtils)
include(CompilerRTDarwinUtils)
if(APPLE)
find_darwin_sdk_dir(DARWIN_osx_SYSROOT macosx)
find_darwin_sdk_dir(DARWIN_iossim_SYSROOT iphonesimulator)
find_darwin_sdk_dir(DARWIN_ios_SYSROOT iphoneos)
find_darwin_sdk_dir(DARWIN_watchossim_SYSROOT watchsimulator)
find_darwin_sdk_dir(DARWIN_watchos_SYSROOT watchos)
find_darwin_sdk_dir(DARWIN_tvossim_SYSROOT appletvsimulator)
find_darwin_sdk_dir(DARWIN_tvos_SYSROOT appletvos)
set(DARWIN_EMBEDDED_PLATFORMS)
set(DARWIN_osx_BUILTIN_MIN_VER 10.5)
set(DARWIN_osx_BUILTIN_MIN_VER_FLAG
-mmacosx-version-min=${DARWIN_osx_BUILTIN_MIN_VER})
if(COMPILER_RT_ENABLE_IOS)
list(APPEND DARWIN_EMBEDDED_PLATFORMS ios)
set(DARWIN_ios_MIN_VER_FLAG -miphoneos-version-min)
set(DARWIN_ios_BUILTIN_MIN_VER 6.0)
set(DARWIN_ios_BUILTIN_MIN_VER_FLAG
${DARWIN_ios_MIN_VER_FLAG}=${DARWIN_ios_BUILTIN_MIN_VER})
endif()
if(COMPILER_RT_ENABLE_WATCHOS)
list(APPEND DARWIN_EMBEDDED_PLATFORMS watchos)
set(DARWIN_watchos_MIN_VER_FLAG -mwatchos-version-min)
set(DARWIN_watchos_BUILTIN_MIN_VER 2.0)
set(DARWIN_watchos_BUILTIN_MIN_VER_FLAG
${DARWIN_watchos_MIN_VER_FLAG}=${DARWIN_watchos_BUILTIN_MIN_VER})
endif()
if(COMPILER_RT_ENABLE_TVOS)
list(APPEND DARWIN_EMBEDDED_PLATFORMS tvos)
set(DARWIN_tvos_MIN_VER_FLAG -mtvos-version-min)
set(DARWIN_tvos_BUILTIN_MIN_VER 9.0)
set(DARWIN_tvos_BUILTIN_MIN_VER_FLAG
${DARWIN_tvos_MIN_VER_FLAG}=${DARWIN_tvos_BUILTIN_MIN_VER})
endif()
set(BUILTIN_SUPPORTED_OS osx)
# We're setting the flag manually for each target OS
set(CMAKE_OSX_DEPLOYMENT_TARGET "")
if(NOT DARWIN_osx_ARCHS)
set(DARWIN_osx_ARCHS i386 x86_64 x86_64h)
endif()
set(DARWIN_sim_ARCHS i386 x86_64)
set(DARWIN_device_ARCHS armv7 armv7s armv7k arm64)
message(STATUS "OSX supported arches: ${DARWIN_osx_ARCHS}")
foreach(arch ${DARWIN_osx_ARCHS})
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
set(CAN_TARGET_${arch} 1)
endforeach()
foreach(platform ${DARWIN_EMBEDDED_PLATFORMS})
if(DARWIN_${platform}sim_SYSROOT)
set(DARWIN_${platform}sim_BUILTIN_MIN_VER
${DARWIN_${platform}_BUILTIN_MIN_VER})
set(DARWIN_${platform}sim_BUILTIN_MIN_VER_FLAG
${DARWIN_${platform}_BUILTIN_MIN_VER_FLAG})
set(DARWIN_${platform}sim_SKIP_CC_KEXT On)
set(test_arches ${DARWIN_sim_ARCHS})
if(DARWIN_${platform}sim_ARCHS)
set(test_arches DARWIN_${platform}sim_ARCHS)
endif()
darwin_test_archs(${platform}sim
DARWIN_${platform}sim_ARCHS
${test_arches})
message(STATUS "${platform} Simulator supported builtin arches: ${DARWIN_${platform}sim_ARCHS}")
if(DARWIN_${platform}sim_ARCHS)
list(APPEND BUILTIN_SUPPORTED_OS ${platform}sim)
endif()
foreach(arch ${DARWIN_${platform}sim_ARCHS})
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
set(CAN_TARGET_${arch} 1)
endforeach()
endif()
if(DARWIN_${platform}_SYSROOT)
set(test_arches ${DARWIN_device_ARCHS})
if(DARWIN_${platform}_ARCHS)
set(test_arches DARWIN_${platform}_ARCHS)
endif()
darwin_test_archs(${platform}
DARWIN_${platform}_ARCHS
${test_arches})
message(STATUS "${platform} supported builtin arches: ${DARWIN_${platform}_ARCHS}")
if(DARWIN_${platform}_ARCHS)
list(APPEND BUILTIN_SUPPORTED_OS ${platform})
endif()
foreach(arch ${DARWIN_${platform}_ARCHS})
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
set(CAN_TARGET_${arch} 1)
endforeach()
endif()
endforeach()
list_intersect(BUILTIN_SUPPORTED_ARCH ALL_BUILTIN_SUPPORTED_ARCH COMPILER_RT_SUPPORTED_ARCH)
else()
# If we're not building the builtins standalone, just rely on the tests in
# config-ix.cmake to tell us what to build. Otherwise we need to do some leg
# work here...
if(COMPILER_RT_BUILTINS_STANDALONE_BUILD)
test_targets()
endif()
# Architectures supported by compiler-rt libraries.
filter_available_targets(BUILTIN_SUPPORTED_ARCH
${ALL_BUILTIN_SUPPORTED_ARCH})
endif()
message(STATUS "Builtin supported architectures: ${BUILTIN_SUPPORTED_ARCH}")

View File

@ -1,15 +0,0 @@
# This file sets up a CMakeCache for Apple-style builds of compiler-rt.
# This configuration matches Apple uses when shipping Xcode releases.
set(COMPILER_RT_INCLUDE_TESTS OFF CACHE BOOL "")
set(COMPILER_RT_HAS_SAFESTACK OFF CACHE BOOL "")
set(COMPILER_RT_EXTERNALIZE_DEBUGINFO ON CACHE BOOL "")
set(CMAKE_MACOSX_RPATH ON CACHE BOOL "")
set(CMAKE_C_FLAGS_RELEASE "-O3" CACHE STRING "")
set(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE STRING "")
set(CMAKE_ASM_FLAGS_RELEASE "-O3" CACHE STRING "")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
set(CMAKE_ASM_FLAGS_RELWITHDEBINFO "-O3 -gline-tables-only -DNDEBUG" CACHE STRING "")
set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "")

View File

@ -1,665 +0,0 @@
include(CMakePushCheckState)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
include(CheckLibraryExists)
include(CheckSymbolExists)
include(TestBigEndian)
function(check_linker_flag flag out_var)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}")
check_cxx_compiler_flag("" ${out_var})
cmake_pop_check_state()
endfunction()
check_library_exists(c fopen "" COMPILER_RT_HAS_LIBC)
if (COMPILER_RT_USE_BUILTINS_LIBRARY)
include(HandleCompilerRT)
find_compiler_rt_library(builtins COMPILER_RT_BUILTINS_LIBRARY)
else()
if (ANDROID)
check_library_exists(gcc __gcc_personality_v0 "" COMPILER_RT_HAS_GCC_LIB)
else()
check_library_exists(gcc_s __gcc_personality_v0 "" COMPILER_RT_HAS_GCC_S_LIB)
endif()
endif()
check_c_compiler_flag(-nodefaultlibs COMPILER_RT_HAS_NODEFAULTLIBS_FLAG)
if (COMPILER_RT_HAS_NODEFAULTLIBS_FLAG)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
if (COMPILER_RT_HAS_LIBC)
list(APPEND CMAKE_REQUIRED_LIBRARIES c)
endif ()
if (COMPILER_RT_USE_BUILTINS_LIBRARY)
list(APPEND CMAKE_REQUIRED_LIBRARIES "${COMPILER_RT_BUILTINS_LIBRARY}")
elseif (COMPILER_RT_HAS_GCC_S_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s)
elseif (COMPILER_RT_HAS_GCC_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES gcc)
endif ()
if (MINGW)
# Mingw64 requires quite a few "C" runtime libraries in order for basic
# programs to link successfully with -nodefaultlibs.
if (COMPILER_RT_USE_BUILTINS_LIBRARY)
set(MINGW_RUNTIME ${COMPILER_RT_BUILTINS_LIBRARY})
else ()
set(MINGW_RUNTIME gcc_s gcc)
endif()
set(MINGW_LIBRARIES mingw32 ${MINGW_RUNTIME} moldname mingwex msvcrt advapi32
shell32 user32 kernel32 mingw32 ${MINGW_RUNTIME}
moldname mingwex msvcrt)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES})
endif()
endif ()
# CodeGen options.
check_c_compiler_flag(-ffreestanding COMPILER_RT_HAS_FFREESTANDING_FLAG)
check_cxx_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG)
check_cxx_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG)
check_cxx_compiler_flag(-fno-builtin COMPILER_RT_HAS_FNO_BUILTIN_FLAG)
check_cxx_compiler_flag(-fno-exceptions COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG)
check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)
check_cxx_compiler_flag(-funwind-tables COMPILER_RT_HAS_FUNWIND_TABLES_FLAG)
check_cxx_compiler_flag(-fno-stack-protector COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG)
check_cxx_compiler_flag(-fno-sanitize=safe-stack COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG)
check_cxx_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG)
check_cxx_compiler_flag(-frtti COMPILER_RT_HAS_FRTTI_FLAG)
check_cxx_compiler_flag(-fno-rtti COMPILER_RT_HAS_FNO_RTTI_FLAG)
check_cxx_compiler_flag("-Werror -fno-function-sections" COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG)
check_cxx_compiler_flag(-std=c++11 COMPILER_RT_HAS_STD_CXX11_FLAG)
check_cxx_compiler_flag(-ftls-model=initial-exec COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC)
check_cxx_compiler_flag(-fno-lto COMPILER_RT_HAS_FNO_LTO_FLAG)
check_cxx_compiler_flag("-Werror -msse3" COMPILER_RT_HAS_MSSE3_FLAG)
check_cxx_compiler_flag("-Werror -msse4.2" COMPILER_RT_HAS_MSSE4_2_FLAG)
check_cxx_compiler_flag(--sysroot=. COMPILER_RT_HAS_SYSROOT_FLAG)
check_cxx_compiler_flag("-Werror -mcrc" COMPILER_RT_HAS_MCRC_FLAG)
if(NOT WIN32 AND NOT CYGWIN)
# MinGW warns if -fvisibility-inlines-hidden is used.
check_cxx_compiler_flag("-fvisibility-inlines-hidden" COMPILER_RT_HAS_FVISIBILITY_INLINES_HIDDEN_FLAG)
endif()
check_cxx_compiler_flag(/GR COMPILER_RT_HAS_GR_FLAG)
check_cxx_compiler_flag(/GS COMPILER_RT_HAS_GS_FLAG)
check_cxx_compiler_flag(/MT COMPILER_RT_HAS_MT_FLAG)
check_cxx_compiler_flag(/Oy COMPILER_RT_HAS_Oy_FLAG)
# Debug info flags.
check_cxx_compiler_flag(-gline-tables-only COMPILER_RT_HAS_GLINE_TABLES_ONLY_FLAG)
check_cxx_compiler_flag(-g COMPILER_RT_HAS_G_FLAG)
check_cxx_compiler_flag(/Zi COMPILER_RT_HAS_Zi_FLAG)
# Warnings.
check_cxx_compiler_flag(-Wall COMPILER_RT_HAS_WALL_FLAG)
check_cxx_compiler_flag(-Werror COMPILER_RT_HAS_WERROR_FLAG)
check_cxx_compiler_flag("-Werror -Wframe-larger-than=512" COMPILER_RT_HAS_WFRAME_LARGER_THAN_FLAG)
check_cxx_compiler_flag("-Werror -Wglobal-constructors" COMPILER_RT_HAS_WGLOBAL_CONSTRUCTORS_FLAG)
check_cxx_compiler_flag("-Werror -Wc99-extensions" COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG)
check_cxx_compiler_flag("-Werror -Wgnu" COMPILER_RT_HAS_WGNU_FLAG)
check_cxx_compiler_flag("-Werror -Wnon-virtual-dtor" COMPILER_RT_HAS_WNON_VIRTUAL_DTOR_FLAG)
check_cxx_compiler_flag("-Werror -Wvariadic-macros" COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG)
check_cxx_compiler_flag("-Werror -Wunused-parameter" COMPILER_RT_HAS_WUNUSED_PARAMETER_FLAG)
check_cxx_compiler_flag("-Werror -Wcovered-switch-default" COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG)
check_cxx_compiler_flag(/W4 COMPILER_RT_HAS_W4_FLAG)
check_cxx_compiler_flag(/WX COMPILER_RT_HAS_WX_FLAG)
check_cxx_compiler_flag(/wd4146 COMPILER_RT_HAS_WD4146_FLAG)
check_cxx_compiler_flag(/wd4291 COMPILER_RT_HAS_WD4291_FLAG)
check_cxx_compiler_flag(/wd4221 COMPILER_RT_HAS_WD4221_FLAG)
check_cxx_compiler_flag(/wd4391 COMPILER_RT_HAS_WD4391_FLAG)
check_cxx_compiler_flag(/wd4722 COMPILER_RT_HAS_WD4722_FLAG)
check_cxx_compiler_flag(/wd4800 COMPILER_RT_HAS_WD4800_FLAG)
# Symbols.
check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL)
# Libraries.
check_library_exists(dl dlopen "" COMPILER_RT_HAS_LIBDL)
check_library_exists(rt shm_open "" COMPILER_RT_HAS_LIBRT)
check_library_exists(m pow "" COMPILER_RT_HAS_LIBM)
check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD)
# Look for terminfo library, used in unittests that depend on LLVMSupport.
if(LLVM_ENABLE_TERMINFO)
foreach(library terminfo tinfo curses ncurses ncursesw)
string(TOUPPER ${library} library_suffix)
check_library_exists(
${library} setupterm "" COMPILER_RT_HAS_TERMINFO_${library_suffix})
if(COMPILER_RT_HAS_TERMINFO_${library_suffix})
set(COMPILER_RT_HAS_TERMINFO TRUE)
set(COMPILER_RT_TERMINFO_LIB "${library}")
break()
endif()
endforeach()
endif()
if (ANDROID AND COMPILER_RT_HAS_LIBDL)
# Android's libstdc++ has a dependency on libdl.
list(APPEND CMAKE_REQUIRED_LIBRARIES dl)
endif()
check_library_exists(c++ __cxa_throw "" COMPILER_RT_HAS_LIBCXX)
check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX)
# Linker flags.
if(ANDROID)
check_linker_flag("-Wl,-z,global" COMPILER_RT_HAS_Z_GLOBAL)
check_library_exists(log __android_log_write "" COMPILER_RT_HAS_LIBLOG)
endif()
# Architectures.
# List of all architectures we can target.
set(COMPILER_RT_SUPPORTED_ARCH)
# Try to compile a very simple source file to ensure we can target the given
# platform. We use the results of these tests to build only the various target
# runtime libraries supported by our current compilers cross-compiling
# abilities.
set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc)
file(WRITE ${SIMPLE_SOURCE} "#include <stdlib.h>\n#include <stdio.h>\nint main() { printf(\"hello, world\"); }\n")
# Detect whether the current target platform is 32-bit or 64-bit, and setup
# the correct commandline flags needed to attempt to target 32-bit and 64-bit.
if (NOT CMAKE_SIZEOF_VOID_P EQUAL 4 AND
NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message(FATAL_ERROR "Please use architecture with 4 or 8 byte pointers.")
endif()
test_targets()
# Returns a list of architecture specific target cflags in @out_var list.
function(get_target_flags_for_arch arch out_var)
list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX)
if(ARCH_INDEX EQUAL -1)
message(FATAL_ERROR "Unsupported architecture: ${arch}")
else()
if (NOT APPLE)
set(${out_var} ${TARGET_${arch}_CFLAGS} PARENT_SCOPE)
else()
# This is only called in constructing cflags for tests executing on the
# host. This will need to all be cleaned up to support building tests
# for cross-targeted hardware (i.e. iOS).
set(${out_var} -arch ${arch} PARENT_SCOPE)
endif()
endif()
endfunction()
# Returns a compiler and CFLAGS that should be used to run tests for the
# specific architecture. When cross-compiling, this is controled via
# COMPILER_RT_TEST_COMPILER and COMPILER_RT_TEST_COMPILER_CFLAGS.
macro(get_test_cc_for_arch arch cc_out cflags_out)
if(ANDROID OR ${arch} MATCHES "arm|aarch64")
# This is only true if we are cross-compiling.
# Build all tests with host compiler and use host tools.
set(${cc_out} ${COMPILER_RT_TEST_COMPILER})
set(${cflags_out} ${COMPILER_RT_TEST_COMPILER_CFLAGS})
else()
get_target_flags_for_arch(${arch} ${cflags_out})
if(APPLE)
list(APPEND ${cflags_out} ${DARWIN_osx_CFLAGS})
endif()
string(REPLACE ";" " " ${cflags_out} "${${cflags_out}}")
endif()
endmacro()
set(ARM64 aarch64)
set(ARM32 arm armhf)
set(HEXAGON hexagon)
set(X86 i386)
set(X86_64 x86_64)
set(MIPS32 mips mipsel)
set(MIPS64 mips64 mips64el)
set(PPC64 powerpc64 powerpc64le)
set(RISCV32 riscv32)
set(RISCV64 riscv64)
set(S390X s390x)
set(WASM32 wasm32)
set(WASM64 wasm64)
if(APPLE)
set(ARM64 arm64)
set(ARM32 armv7 armv7s armv7k)
set(X86_64 x86_64 x86_64h)
endif()
set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64}
${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X})
set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
${MIPS32} ${MIPS64} ${PPC64} ${S390X})
set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64})
if(APPLE)
set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64})
else()
set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64})
endif()
set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64})
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC64}
${MIPS32} ${MIPS64} ${S390X})
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
${MIPS32} ${MIPS64} ${PPC64} ${S390X})
set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64})
set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64})
set(ALL_ESAN_SUPPORTED_ARCH ${X86_64} ${MIPS64})
set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64})
if(APPLE)
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
else()
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le)
endif()
set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${X86_64} ${ARM64})
if(APPLE)
include(CompilerRTDarwinUtils)
find_darwin_sdk_dir(DARWIN_osx_SYSROOT macosx)
find_darwin_sdk_dir(DARWIN_iossim_SYSROOT iphonesimulator)
find_darwin_sdk_dir(DARWIN_ios_SYSROOT iphoneos)
find_darwin_sdk_dir(DARWIN_watchossim_SYSROOT watchsimulator)
find_darwin_sdk_dir(DARWIN_watchos_SYSROOT watchos)
find_darwin_sdk_dir(DARWIN_tvossim_SYSROOT appletvsimulator)
find_darwin_sdk_dir(DARWIN_tvos_SYSROOT appletvos)
if(NOT DARWIN_osx_SYSROOT)
if(EXISTS /usr/include)
set(DARWIN_osx_SYSROOT /)
else()
message(ERROR "Could not detect OS X Sysroot. Either install Xcode or the Apple Command Line Tools")
endif()
endif()
if(COMPILER_RT_ENABLE_IOS)
list(APPEND DARWIN_EMBEDDED_PLATFORMS ios)
set(DARWIN_ios_MIN_VER_FLAG -miphoneos-version-min)
set(DARWIN_ios_SANITIZER_MIN_VER_FLAG
${DARWIN_ios_MIN_VER_FLAG}=8.0)
endif()
if(COMPILER_RT_ENABLE_WATCHOS)
list(APPEND DARWIN_EMBEDDED_PLATFORMS watchos)
set(DARWIN_watchos_MIN_VER_FLAG -mwatchos-version-min)
set(DARWIN_watchos_SANITIZER_MIN_VER_FLAG
${DARWIN_watchos_MIN_VER_FLAG}=2.0)
endif()
if(COMPILER_RT_ENABLE_TVOS)
list(APPEND DARWIN_EMBEDDED_PLATFORMS tvos)
set(DARWIN_tvos_MIN_VER_FLAG -mtvos-version-min)
set(DARWIN_tvos_SANITIZER_MIN_VER_FLAG
${DARWIN_tvos_MIN_VER_FLAG}=9.0)
endif()
# Note: In order to target x86_64h on OS X the minimum deployment target must
# be 10.8 or higher.
set(SANITIZER_COMMON_SUPPORTED_OS osx)
set(PROFILE_SUPPORTED_OS osx)
set(TSAN_SUPPORTED_OS osx)
set(XRAY_SUPPORTED_OS osx)
if(NOT SANITIZER_MIN_OSX_VERSION)
string(REGEX MATCH "-mmacosx-version-min=([.0-9]+)"
MACOSX_VERSION_MIN_FLAG "${CMAKE_CXX_FLAGS}")
if(MACOSX_VERSION_MIN_FLAG)
set(SANITIZER_MIN_OSX_VERSION "${CMAKE_MATCH_1}")
elseif(CMAKE_OSX_DEPLOYMENT_TARGET)
set(SANITIZER_MIN_OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET})
else()
set(SANITIZER_MIN_OSX_VERSION 10.9)
endif()
if(SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.7")
message(FATAL_ERROR "macOS deployment target '${SANITIZER_MIN_OSX_VERSION}' is too old.")
endif()
if(SANITIZER_MIN_OSX_VERSION VERSION_GREATER "10.9")
message(WARNING "macOS deployment target '${SANITIZER_MIN_OSX_VERSION}' is too new, setting to '10.9' instead.")
set(SANITIZER_MIN_OSX_VERSION 10.9)
endif()
endif()
# We're setting the flag manually for each target OS
set(CMAKE_OSX_DEPLOYMENT_TARGET "")
set(DARWIN_COMMON_CFLAGS -stdlib=libc++)
set(DARWIN_COMMON_LINK_FLAGS
-stdlib=libc++
-lc++
-lc++abi)
check_linker_flag("-fapplication-extension" COMPILER_RT_HAS_APP_EXTENSION)
if(COMPILER_RT_HAS_APP_EXTENSION)
list(APPEND DARWIN_COMMON_LINK_FLAGS "-fapplication-extension")
endif()
set(DARWIN_osx_CFLAGS
${DARWIN_COMMON_CFLAGS}
-mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION})
set(DARWIN_osx_LINK_FLAGS
${DARWIN_COMMON_LINK_FLAGS}
-mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION})
if(DARWIN_osx_SYSROOT)
list(APPEND DARWIN_osx_CFLAGS -isysroot ${DARWIN_osx_SYSROOT})
list(APPEND DARWIN_osx_LINK_FLAGS -isysroot ${DARWIN_osx_SYSROOT})
endif()
# Figure out which arches to use for each OS
darwin_get_toolchain_supported_archs(toolchain_arches)
message(STATUS "Toolchain supported arches: ${toolchain_arches}")
if(NOT MACOSX_VERSION_MIN_FLAG)
darwin_test_archs(osx
DARWIN_osx_ARCHS
${toolchain_arches})
message(STATUS "OSX supported arches: ${DARWIN_osx_ARCHS}")
foreach(arch ${DARWIN_osx_ARCHS})
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
set(CAN_TARGET_${arch} 1)
endforeach()
foreach(platform ${DARWIN_EMBEDDED_PLATFORMS})
if(DARWIN_${platform}sim_SYSROOT)
set(DARWIN_${platform}sim_CFLAGS
${DARWIN_COMMON_CFLAGS}
${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG}
-isysroot ${DARWIN_${platform}sim_SYSROOT})
set(DARWIN_${platform}sim_LINK_FLAGS
${DARWIN_COMMON_LINK_FLAGS}
${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG}
-isysroot ${DARWIN_${platform}sim_SYSROOT})
set(DARWIN_${platform}sim_SKIP_CC_KEXT On)
darwin_test_archs(${platform}sim
DARWIN_${platform}sim_ARCHS
${toolchain_arches})
message(STATUS "${platform} Simulator supported arches: ${DARWIN_${platform}sim_ARCHS}")
if(DARWIN_${platform}sim_ARCHS)
list(APPEND SANITIZER_COMMON_SUPPORTED_OS ${platform}sim)
list(APPEND PROFILE_SUPPORTED_OS ${platform}sim)
list(APPEND TSAN_SUPPORTED_OS ${platform}sim)
endif()
foreach(arch ${DARWIN_${platform}sim_ARCHS})
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
set(CAN_TARGET_${arch} 1)
endforeach()
endif()
if(DARWIN_${platform}_SYSROOT)
set(DARWIN_${platform}_CFLAGS
${DARWIN_COMMON_CFLAGS}
${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG}
-isysroot ${DARWIN_${platform}_SYSROOT})
set(DARWIN_${platform}_LINK_FLAGS
${DARWIN_COMMON_LINK_FLAGS}
${DARWIN_${platform}_SANITIZER_MIN_VER_FLAG}
-isysroot ${DARWIN_${platform}_SYSROOT})
darwin_test_archs(${platform}
DARWIN_${platform}_ARCHS
${toolchain_arches})
message(STATUS "${platform} supported arches: ${DARWIN_${platform}_ARCHS}")
if(DARWIN_${platform}_ARCHS)
list(APPEND SANITIZER_COMMON_SUPPORTED_OS ${platform})
list(APPEND PROFILE_SUPPORTED_OS ${platform})
list_intersect(DARWIN_${platform}_TSAN_ARCHS DARWIN_${platform}_ARCHS ALL_TSAN_SUPPORTED_ARCH)
if(DARWIN_${platform}_TSAN_ARCHS)
list(APPEND TSAN_SUPPORTED_OS ${platform})
endif()
endif()
foreach(arch ${DARWIN_${platform}_ARCHS})
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
set(CAN_TARGET_${arch} 1)
endforeach()
endif()
endforeach()
endif()
# for list_intersect
include(CompilerRTUtils)
list_intersect(SANITIZER_COMMON_SUPPORTED_ARCH
ALL_SANITIZER_COMMON_SUPPORTED_ARCH
COMPILER_RT_SUPPORTED_ARCH
)
set(LSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH})
set(UBSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH})
list_intersect(ASAN_SUPPORTED_ARCH
ALL_ASAN_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(DFSAN_SUPPORTED_ARCH
ALL_DFSAN_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(LSAN_SUPPORTED_ARCH
ALL_LSAN_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(MSAN_SUPPORTED_ARCH
ALL_MSAN_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(HWASAN_SUPPORTED_ARCH
ALL_HWASAN_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(PROFILE_SUPPORTED_ARCH
ALL_PROFILE_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(TSAN_SUPPORTED_ARCH
ALL_TSAN_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(UBSAN_SUPPORTED_ARCH
ALL_UBSAN_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(SAFESTACK_SUPPORTED_ARCH
ALL_SAFESTACK_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(CFI_SUPPORTED_ARCH
ALL_CFI_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(ESAN_SUPPORTED_ARCH
ALL_ESAN_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(SCUDO_SUPPORTED_ARCH
ALL_SCUDO_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(FUZZER_SUPPORTED_ARCH
ALL_FUZZER_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(XRAY_SUPPORTED_ARCH
ALL_XRAY_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
list_intersect(SHADOWCALLSTACK_SUPPORTED_ARCH
ALL_SHADOWCALLSTACK_SUPPORTED_ARCH
SANITIZER_COMMON_SUPPORTED_ARCH)
else()
# Architectures supported by compiler-rt libraries.
filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
${ALL_SANITIZER_COMMON_SUPPORTED_ARCH})
# LSan and UBSan common files should be available on all architectures
# supported by other sanitizers (even if they build into dummy object files).
filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH
${SANITIZER_COMMON_SUPPORTED_ARCH})
filter_available_targets(UBSAN_COMMON_SUPPORTED_ARCH
${SANITIZER_COMMON_SUPPORTED_ARCH})
filter_available_targets(ASAN_SUPPORTED_ARCH ${ALL_ASAN_SUPPORTED_ARCH})
filter_available_targets(FUZZER_SUPPORTED_ARCH ${ALL_FUZZER_SUPPORTED_ARCH})
filter_available_targets(DFSAN_SUPPORTED_ARCH ${ALL_DFSAN_SUPPORTED_ARCH})
filter_available_targets(LSAN_SUPPORTED_ARCH ${ALL_LSAN_SUPPORTED_ARCH})
filter_available_targets(MSAN_SUPPORTED_ARCH ${ALL_MSAN_SUPPORTED_ARCH})
filter_available_targets(HWASAN_SUPPORTED_ARCH ${ALL_HWASAN_SUPPORTED_ARCH})
filter_available_targets(PROFILE_SUPPORTED_ARCH ${ALL_PROFILE_SUPPORTED_ARCH})
filter_available_targets(TSAN_SUPPORTED_ARCH ${ALL_TSAN_SUPPORTED_ARCH})
filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH})
filter_available_targets(SAFESTACK_SUPPORTED_ARCH
${ALL_SAFESTACK_SUPPORTED_ARCH})
filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH})
filter_available_targets(ESAN_SUPPORTED_ARCH ${ALL_ESAN_SUPPORTED_ARCH})
filter_available_targets(SCUDO_SUPPORTED_ARCH ${ALL_SCUDO_SUPPORTED_ARCH})
filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH})
filter_available_targets(SHADOWCALLSTACK_SUPPORTED_ARCH
${ALL_SHADOWCALLSTACK_SUPPORTED_ARCH})
endif()
if (MSVC)
# See if the DIA SDK is available and usable.
set(MSVC_DIA_SDK_DIR "$ENV{VSINSTALLDIR}DIA SDK")
if (IS_DIRECTORY ${MSVC_DIA_SDK_DIR})
set(CAN_SYMBOLIZE 1)
else()
set(CAN_SYMBOLIZE 0)
endif()
else()
set(CAN_SYMBOLIZE 1)
endif()
find_program(GOLD_EXECUTABLE NAMES ${LLVM_DEFAULT_TARGET_TRIPLE}-ld.gold ld.gold ${LLVM_DEFAULT_TARGET_TRIPLE}-ld ld DOC "The gold linker")
if(COMPILER_RT_SUPPORTED_ARCH)
list(REMOVE_DUPLICATES COMPILER_RT_SUPPORTED_ARCH)
endif()
message(STATUS "Compiler-RT supported architectures: ${COMPILER_RT_SUPPORTED_ARCH}")
if(ANDROID)
set(OS_NAME "Android")
else()
set(OS_NAME "${CMAKE_SYSTEM_NAME}")
endif()
set(ALL_SANITIZERS asan;dfsan;msan;hwasan;tsan;safestack;cfi;esan;scudo;ubsan_minimal)
set(COMPILER_RT_SANITIZERS_TO_BUILD all CACHE STRING
"sanitizers to build if supported on the target (all;${ALL_SANITIZERS})")
list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}")
if (SANITIZER_COMMON_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
(OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|OpenBSD|Fuchsia|SunOS" OR
(OS_NAME MATCHES "Windows" AND NOT CYGWIN AND
(NOT MINGW OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"))))
set(COMPILER_RT_HAS_SANITIZER_COMMON TRUE)
else()
set(COMPILER_RT_HAS_SANITIZER_COMMON FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON)
set(COMPILER_RT_HAS_INTERCEPTION TRUE)
else()
set(COMPILER_RT_HAS_INTERCEPTION FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND ASAN_SUPPORTED_ARCH AND
NOT OS_NAME MATCHES "OpenBSD")
set(COMPILER_RT_HAS_ASAN TRUE)
else()
set(COMPILER_RT_HAS_ASAN FALSE)
endif()
if (OS_NAME MATCHES "Linux|FreeBSD|Windows|NetBSD|SunOS")
set(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME TRUE)
else()
set(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME FALSE)
endif()
# TODO: Add builtins support.
if (COMPILER_RT_HAS_SANITIZER_COMMON AND DFSAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux")
set(COMPILER_RT_HAS_DFSAN TRUE)
else()
set(COMPILER_RT_HAS_DFSAN FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND LSAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD")
set(COMPILER_RT_HAS_LSAN TRUE)
else()
set(COMPILER_RT_HAS_LSAN FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND MSAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux|FreeBSD|NetBSD")
set(COMPILER_RT_HAS_MSAN TRUE)
else()
set(COMPILER_RT_HAS_MSAN FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND HWASAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux|Android")
set(COMPILER_RT_HAS_HWASAN TRUE)
else()
set(COMPILER_RT_HAS_HWASAN FALSE)
endif()
if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD")
set(COMPILER_RT_HAS_PROFILE TRUE)
else()
set(COMPILER_RT_HAS_PROFILE FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android|NetBSD")
set(COMPILER_RT_HAS_TSAN TRUE)
else()
set(COMPILER_RT_HAS_TSAN FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|OpenBSD|Windows|Android|Fuchsia|SunOS")
set(COMPILER_RT_HAS_UBSAN TRUE)
else()
set(COMPILER_RT_HAS_UBSAN FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux|FreeBSD|NetBSD|OpenBSD|Android|Darwin")
set(COMPILER_RT_HAS_UBSAN_MINIMAL TRUE)
else()
set(COMPILER_RT_HAS_UBSAN_MINIMAL FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND SAFESTACK_SUPPORTED_ARCH AND
OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD")
set(COMPILER_RT_HAS_SAFESTACK TRUE)
else()
set(COMPILER_RT_HAS_SAFESTACK FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND CFI_SUPPORTED_ARCH)
set(COMPILER_RT_HAS_CFI TRUE)
else()
set(COMPILER_RT_HAS_CFI FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND ESAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux|FreeBSD")
set(COMPILER_RT_HAS_ESAN TRUE)
else()
set(COMPILER_RT_HAS_ESAN FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND SCUDO_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux|Android|Fuchsia")
set(COMPILER_RT_HAS_SCUDO TRUE)
else()
set(COMPILER_RT_HAS_SCUDO FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND XRAY_SUPPORTED_ARCH AND
OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|OpenBSD|Fuchsia")
set(COMPILER_RT_HAS_XRAY TRUE)
else()
set(COMPILER_RT_HAS_XRAY FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND FUZZER_SUPPORTED_ARCH AND
OS_NAME MATCHES "Android|Darwin|Linux|NetBSD|FreeBSD|OpenBSD|Fuchsia|Windows" AND
# TODO: Support builds with MSVC.
NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" AND
NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
set(COMPILER_RT_HAS_FUZZER TRUE)
else()
set(COMPILER_RT_HAS_FUZZER FALSE)
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND SHADOWCALLSTACK_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux|Android")
set(COMPILER_RT_HAS_SHADOWCALLSTACK TRUE)
else()
set(COMPILER_RT_HAS_SHADOWCALLSTACK FALSE)
endif()

View File

@ -1,66 +0,0 @@
========================================
Compiler-rt Testing Infrastructure Guide
========================================
.. contents::
:local:
Overview
========
This document is the reference manual for the compiler-rt modifications to the
testing infrastructure. Documentation for the infrastructure itself can be found at
:ref:`llvm_testing_guide`.
LLVM testing infrastructure organization
========================================
The compiler-rt testing infrastructure contains regression tests which are run
as part of the usual ``make check-all`` and are expected to always pass -- they
should be run before every commit.
Quick start
===========
The regressions tests are in the "compiler-rt" module and are normally checked
out in the directory ``llvm/projects/compiler-rt/test``. Use ``make check-all``
to run the regression tests after building compiler-rt.
REQUIRES, XFAIL, etc.
---------------------
Sometimes it is necessary to restrict a test to a specific target or mark it as
an "expected fail" or XFAIL. This is normally achieved using ``REQUIRES:`` or
``XFAIL:`` with a substring of LLVM's default target triple. Unfortunately, the
behaviour of this is somewhat quirky in compiler-rt. There are two main
pitfalls to avoid.
The first pitfall is that these directives perform a substring match on the
triple and as such ``XFAIL: mips`` affects more triples than expected. For
example, ``mips-linux-gnu``, ``mipsel-linux-gnu``, ``mips64-linux-gnu``, and
``mips64el-linux-gnu`` will all match a ``XFAIL: mips`` directive. Including a
trailing ``-`` such as in ``XFAIL: mips-`` can help to mitigate this quirk but
even that has issues as described below.
The second pitfall is that the default target triple is often inappropriate for
compiler-rt tests since compiler-rt tests may be compiled for multiple targets.
For example, a typical build on an ``x86_64-linux-gnu`` host will often run the
tests for both x86_64 and i386. In this situation ``XFAIL: x86_64`` will mark
both the x86_64 and i386 tests as an expected failure while ``XFAIL: i386``
will have no effect at all.
To remedy both pitfalls, compiler-rt tests provide a feature string which can
be used to specify a single target. This string is of the form
``target-is-${arch}`` where ``${arch}}`` is one of the values from the
following lines of the CMake output::
-- Compiler-RT supported architectures: x86_64;i386
-- Builtin supported architectures: i386;x86_64
So for example ``XFAIL: target-is-x86_64`` will mark a test as expected to fail
on x86_64 without also affecting the i386 test and ``XFAIL: target-is-i386``
will mark a test as expected to fail on i386 even if the default target triple
is ``x86_64-linux-gnu``. Directives that use these ``target-is-${arch}`` string
require exact matches so ``XFAIL: target-is-mips``,
``XFAIL: target-is-mipsel``, ``XFAIL: target-is-mips64``, and
``XFAIL: target-is-mips64el`` all refer to different MIPS targets.

View File

@ -1,72 +0,0 @@
if (COMPILER_RT_BUILD_SANITIZERS)
set(SANITIZER_HEADERS
sanitizer/allocator_interface.h
sanitizer/asan_interface.h
sanitizer/common_interface_defs.h
sanitizer/coverage_interface.h
sanitizer/dfsan_interface.h
sanitizer/esan_interface.h
sanitizer/hwasan_interface.h
sanitizer/linux_syscall_hooks.h
sanitizer/lsan_interface.h
sanitizer/msan_interface.h
sanitizer/netbsd_syscall_hooks.h
sanitizer/scudo_interface.h
sanitizer/tsan_interface.h
sanitizer/tsan_interface_atomic.h)
endif(COMPILER_RT_BUILD_SANITIZERS)
if (COMPILER_RT_BUILD_XRAY)
set(XRAY_HEADERS
xray/xray_interface.h
xray/xray_log_interface.h)
endif(COMPILER_RT_BUILD_XRAY)
set(COMPILER_RT_HEADERS
${SANITIZER_HEADERS}
${XRAY_HEADERS})
set(output_dir ${COMPILER_RT_OUTPUT_DIR}/include)
# Copy compiler-rt headers to the build tree.
set(out_files)
foreach( f ${COMPILER_RT_HEADERS} )
set( src ${CMAKE_CURRENT_SOURCE_DIR}/${f} )
set( dst ${output_dir}/${f} )
add_custom_command(OUTPUT ${dst}
DEPENDS ${src}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
COMMENT "Copying compiler-rt's ${f}...")
list(APPEND out_files ${dst})
endforeach( f )
add_custom_target(compiler-rt-headers ALL DEPENDS ${out_files})
add_dependencies(compiler-rt compiler-rt-headers)
set_target_properties(compiler-rt-headers PROPERTIES FOLDER "Compiler-RT Misc")
# Install sanitizer headers.
install(FILES ${SANITIZER_HEADERS}
COMPONENT compiler-rt-headers
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/sanitizer)
# Install xray headers.
install(FILES ${XRAY_HEADERS}
COMPONENT compiler-rt-headers
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/xray)
if (NOT CMAKE_CONFIGURATION_TYPES) # don't add this for IDEs.
add_custom_target(install-compiler-rt-headers
DEPENDS compiler-rt-headers
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT="compiler-rt-headers"
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
USES_TERMINAL)
add_custom_target(install-compiler-rt-headers-stripped
DEPENDS compiler-rt-headers
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT="compiler-rt-headers"
-DCMAKE_INSTALL_DO_STRIP=1
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
USES_TERMINAL)
endif()

View File

@ -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()

View File

@ -1,2 +0,0 @@
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false

View File

@ -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()

View File

@ -1,4 +0,0 @@
if(ANDROID)
add_compiler_rt_script(asan_device_setup)
add_dependencies(asan asan_device_setup)
endif()

View File

@ -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"

View File

@ -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()

View File

@ -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()

View File

@ -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__)

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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

View File

@ -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];
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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().
}

View File

@ -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();
}

View File

@ -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];
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
# blacklisted functions for instrumented ASan unit test
fun:*IgnoreTest*
fun:*SomeOtherFunc*

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
apple_versioning

View File

@ -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

View File

@ -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

View File

@ -1,16 +0,0 @@
clzti2
divti3
fixdfti
fixsfti
fixunsdfti
floattidf
floattisf
floatuntidf
floatuntisf
gcc_personality_v0
modti3
powidf2
powisf2
udivmodti4
udivti3
umodti3

View File

@ -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

View File

@ -1,12 +0,0 @@
addtf3
divtf3
multf3
powitf2
subtf3
trampoline_setup
addtf3
divtf3
multf3
powitf2
subtf3
trampoline_setup

View File

@ -1 +0,0 @@
apple_versioning

View File

@ -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

View File

@ -1,7 +0,0 @@
apple_versioning
addtf3
divtf3
multf3
powitf2
subtf3
trampoline_setup

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -1,2 +0,0 @@
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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);
}

View File

@ -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

View File

@ -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"

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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()

View File

@ -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();
}

View File

@ -1,2 +0,0 @@
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false

View File

@ -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()

View File

@ -1,2 +0,0 @@
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -1,2 +0,0 @@
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false

View File

@ -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()

View File

@ -1,2 +0,0 @@
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false

View File

@ -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()

View File

@ -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()

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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();
}

View File

@ -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()

View File

@ -1,2 +0,0 @@
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false

Some files were not shown because too many files have changed in this diff Show More