Vendor import of compiler-rt trunk r351319 (just before the release_80

branch point):
https://llvm.org/svn/llvm-project/compiler-rt/trunk@351319
This commit is contained in:
dim 2019-01-19 10:05:08 +00:00
parent 1db450fe70
commit 5c86f0191f
713 changed files with 23364 additions and 5711 deletions

View File

@ -59,6 +59,9 @@ if (NOT COMPILER_RT_ASAN_SHADOW_SCALE STREQUAL "")
-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.")
@ -79,6 +82,61 @@ if (COMPILER_RT_STANDALONE_BUILD)
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)
@ -89,12 +147,12 @@ if (COMPILER_RT_STANDALONE_BUILD)
endif()
construct_compiler_rt_default_triple()
if ("${COMPILER_RT_DEFAULT_TARGET_ABI}" MATCHES "hf$")
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_ABI}" MATCHES "^android")
if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*")
set(ANDROID 1)
endif()
pythonize_bool(ANDROID)
@ -142,7 +200,7 @@ set(CXXABIS none default libstdc++ libc++)
set_property(CACHE SANITIZER_CXX_ABI PROPERTY STRINGS ;${CXXABIS})
if (SANITIZER_CXX_ABI STREQUAL "default")
if (APPLE)
if (APPLE OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(SANITIZER_CXX_ABI_LIBNAME "libc++")
set(SANITIZER_CXX_ABI_SYSTEM 1)
elseif (FUCHSIA)
@ -310,11 +368,14 @@ 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)
@ -325,14 +386,6 @@ endif()
append_list_if(COMPILER_RT_HAS_LIBC c SANITIZER_COMMON_LINK_LIBS)
if(ANDROID)
# Put the 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 SANITIZER_COMMON_LINK_FLAGS -Wl,-z,global)
endif()
endif()
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)
@ -375,15 +428,19 @@ endif()
add_subdirectory(include)
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()
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)

View File

@ -14,7 +14,7 @@ Full text of the relevant licenses is included below.
University of Illinois/NCSA
Open Source License
Copyright (c) 2009-2018 by the contributors listed in CREDITS.TXT
Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
All rights reserved.

View File

@ -77,7 +77,7 @@ function(add_compiler_rt_object_libraries name)
endif()
set_target_compile_flags(${libname}
${CMAKE_CXX_FLAGS} ${extra_cflags_${libname}} ${target_flags})
${extra_cflags_${libname}} ${target_flags})
set_property(TARGET ${libname} APPEND PROPERTY
COMPILE_DEFINITIONS ${LIB_DEFS})
set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Libraries")
@ -357,19 +357,20 @@ set(COMPILER_RT_GTEST_CFLAGS
-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)
# clang doesn't support exceptions on Windows yet.
list(APPEND COMPILER_RT_UNITTEST_CFLAGS -D_HAS_EXCEPTIONS=0)
# We should teach clang to understand "#pragma intrinsic", see PR19898.
list(APPEND COMPILER_RT_UNITTEST_CFLAGS -Wno-undefined-inline)
# Clang doesn't support SEH on Windows yet.
list(APPEND COMPILER_RT_GTEST_CFLAGS -DGTEST_HAS_SEH=0)
# gtest use a lot of stuff marked as deprecated on Windows.
list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations)
endif()
@ -550,6 +551,9 @@ macro(add_custom_libcxx name prefix)
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
@ -562,14 +566,20 @@ macro(add_custom_libcxx name prefix)
CMAKE_SYSROOT
CMAKE_SYSTEM_NAME)
foreach(variable ${PASSTHROUGH_VARIABLES})
if(${variable})
list(APPEND CMAKE_PASSTHROUGH_VARIABLES -D${variable}=${${variable}})
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 ";" " " FLAGS_STRING "${LIBCXX_CFLAGS}")
set(LIBCXX_C_FLAGS "${FLAGS_STRING}")
set(LIBCXX_CXX_FLAGS "${FLAGS_STRING}")
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}

View File

@ -58,14 +58,6 @@ macro(append_rtti_flag polarity list)
endif()
endmacro()
macro(append_have_file_definition filename varname list)
check_include_file("${filename}" "${varname}")
if (NOT ${varname})
set("${varname}" 0)
endif()
list(APPEND ${list} "${varname}=${${varname}}")
endmacro()
macro(list_intersect output input1 input2)
set(${output})
foreach(it ${${input1}})
@ -210,47 +202,91 @@ macro(load_llvm_config)
find_program(LLVM_CONFIG_PATH "llvm-config"
DOC "Path to llvm-config binary")
if (NOT LLVM_CONFIG_PATH)
message(FATAL_ERROR "llvm-config not found: specify 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()
execute_process(
COMMAND ${LLVM_CONFIG_PATH} "--obj-root" "--bindir" "--libdir" "--src-root"
RESULT_VARIABLE HAD_ERROR
OUTPUT_VARIABLE CONFIG_OUTPUT)
if (HAD_ERROR)
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
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()
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)
set(LLVM_BINARY_DIR ${BINARY_DIR} CACHE PATH "Path to LLVM build tree")
set(LLVM_TOOLS_BINARY_DIR ${TOOLS_BINARY_DIR} CACHE PATH "Path to llvm/bin")
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")
# 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})
endmacro()
macro(construct_compiler_rt_default_triple)
@ -272,11 +308,6 @@ macro(construct_compiler_rt_default_triple)
string(REPLACE "-" ";" TARGET_TRIPLE_LIST ${COMPILER_RT_DEFAULT_TARGET_TRIPLE})
list(GET TARGET_TRIPLE_LIST 0 COMPILER_RT_DEFAULT_TARGET_ARCH)
list(GET TARGET_TRIPLE_LIST 1 COMPILER_RT_DEFAULT_TARGET_OS)
list(LENGTH TARGET_TRIPLE_LIST TARGET_TRIPLE_LIST_LENGTH)
if(TARGET_TRIPLE_LIST_LENGTH GREATER 2)
list(GET TARGET_TRIPLE_LIST 2 COMPILER_RT_DEFAULT_TARGET_ABI)
endif()
# Determine if test target triple is specified explicitly, and doesn't match the
# default.
if(NOT COMPILER_RT_DEFAULT_TARGET_TRIPLE STREQUAL TARGET_TRIPLE)
@ -316,13 +347,15 @@ function(filter_builtin_sources output_var exclude_or_include excluded_list)
endfunction()
function(get_compiler_rt_target arch variable)
if(ANDROID AND ${arch} STREQUAL "i386")
set(target "i686${COMPILER_RT_OS_SUFFIX}-${COMPILER_RT_DEFAULT_TARGET_OS}")
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}-${COMPILER_RT_DEFAULT_TARGET_OS}")
endif()
if(COMPILER_RT_DEFAULT_TARGET_ABI)
set(target "${target}-${COMPILER_RT_DEFAULT_TARGET_ABI}")
set(target "${arch}${triple_suffix}")
endif()
set(${variable} ${target} PARENT_SCOPE)
endfunction()

View File

@ -4,12 +4,16 @@ function(find_compiler_rt_library name variable)
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}")

View File

@ -30,7 +30,7 @@ macro(add_sanitizer_rt_symbols name)
add_custom_command(OUTPUT ${stamp}
COMMAND ${PYTHON_EXECUTABLE}
${SANITIZER_GEN_DYNAMIC_LIST} ${extra_args} $<TARGET_FILE:${target_name}>
> $<TARGET_FILE:${target_name}>.syms
-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}
@ -51,7 +51,15 @@ 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)
file(STRINGS "${COMPILER_RT_SOURCE_DIR}/lib/${libname}/weak_symbols.txt" WEAK_SYMBOLS)
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})
@ -72,7 +80,7 @@ macro(add_sanitizer_rt_version_list name)
add_custom_command(OUTPUT ${vers}
COMMAND ${PYTHON_EXECUTABLE}
${SANITIZER_GEN_DYNAMIC_LIST} --version-list ${args}
> ${vers}
-o ${vers}
DEPENDS ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA} ${ARG_LIBS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating version list for ${name}"

View File

@ -8,6 +8,12 @@ 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)
@ -122,8 +128,6 @@ macro(test_targets)
# what version of MSVC to pretend to be so that the STL works.
set(MSVC_VERSION_FLAG "")
if (MSVC)
# 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.
execute_process(COMMAND "$ENV{VSINSTALLDIR}/VC/bin/cl.exe"
OUTPUT_QUIET
ERROR_VARIABLE MSVC_COMPAT_VERSION
@ -191,11 +195,11 @@ macro(test_targets)
# 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" "--target=mipsel-linux-gnu")
test_target_arch(mips64el "" "-mips64r2" "--target=mips64el-linux-gnu" "-mabi=64")
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" "--target=mips-linux-gnu")
test_target_arch(mips64 "" "-mips64r2" "--target=mips64-linux-gnu" "-mabi=64")
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 "" "" "")

View File

@ -103,20 +103,6 @@ if(APPLE)
set(CAN_TARGET_${arch} 1)
endforeach()
# Need to build a 10.4 compatible libclang_rt
set(DARWIN_10.4_SYSROOT ${DARWIN_osx_SYSROOT})
set(DARWIN_10.4_BUILTIN_MIN_VER 10.4)
set(DARWIN_10.4_BUILTIN_MIN_VER_FLAG
-mmacosx-version-min=${DARWIN_10.4_BUILTIN_MIN_VER})
set(DARWIN_10.4_SKIP_CC_KEXT On)
darwin_test_archs(10.4 DARWIN_10.4_ARCHS i386 x86_64)
message(STATUS "OSX 10.4 supported builtin arches: ${DARWIN_10.4_ARCHS}")
if(DARWIN_10.4_ARCHS)
# don't include the Haswell slice in the 10.4 compatibility library
list(REMOVE_ITEM DARWIN_10.4_ARCHS x86_64h)
list(APPEND BUILTIN_SUPPORTED_OS 10.4)
endif()
foreach(platform ${DARWIN_EMBEDDED_PLATFORMS})
if(DARWIN_${platform}sim_SYSROOT)
set(DARWIN_${platform}sim_BUILTIN_MIN_VER

View File

@ -37,9 +37,23 @@ if (COMPILER_RT_HAS_NODEFAULTLIBS_FLAG)
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)
@ -51,7 +65,6 @@ check_cxx_compiler_flag(-fno-sanitize=safe-stack COMPILER_RT_HAS_FNO_SANITIZE_SA
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(-ffreestanding COMPILER_RT_HAS_FFREESTANDING_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)
@ -105,6 +118,21 @@ 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)
@ -501,7 +529,8 @@ 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 MINGW AND NOT CYGWIN))))
(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)
@ -557,7 +586,7 @@ else()
endif()
if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS")
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD")
set(COMPILER_RT_HAS_PROFILE TRUE)
else()
set(COMPILER_RT_HAS_PROFILE FALSE)
@ -598,7 +627,7 @@ else()
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND ESAN_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux")
OS_NAME MATCHES "Linux|FreeBSD")
set(COMPILER_RT_HAS_ESAN TRUE)
else()
set(COMPILER_RT_HAS_ESAN FALSE)
@ -612,14 +641,17 @@ else()
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND XRAY_SUPPORTED_ARCH AND
OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|OpenBSD")
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")
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)

View File

@ -82,7 +82,6 @@ extern "C" {
Currently available with ASan only.
*/
void __sanitizer_purge_allocator(void);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -124,6 +124,12 @@ extern "C" {
// Symbolizes the supplied 'pc' using the format string 'fmt'.
// Outputs at most 'out_buf_size' bytes into 'out_buf'.
// If 'out_buf' is not empty then output is zero or more non empty C strings
// followed by single empty C string. Multiple strings can be returned if PC
// corresponds to inlined function. Inlined frames are printed in the order
// from "most-inlined" to the "least-inlined", so the last frame should be the
// not inlined function.
// Inlined frames can be removed with 'symbolize_inline_frames=0'.
// The format syntax is described in
// lib/sanitizer_common/sanitizer_stacktrace_printer.h.
void __sanitizer_symbolize_pc(void *pc, const char *fmt, char *out_buf,

View File

@ -19,6 +19,12 @@
#ifdef __cplusplus
extern "C" {
#endif
// Initialize shadow but not the rest of the runtime.
// Does not call libc unless there is an error.
// Can be called multiple times, or not at all (in which case shadow will
// be initialized in compiler-inserted __hwasan_init() call).
void __hwasan_shadow_init(void);
// This function may be optionally provided by user and should return
// a string containing HWASan runtime options. See asan_flags.h for details.
const char* __hwasan_default_options(void);
@ -26,6 +32,51 @@ extern "C" {
void __hwasan_enable_allocator_tagging(void);
void __hwasan_disable_allocator_tagging(void);
// Mark region of memory with the given tag. Both address and size need to be
// 16-byte aligned.
void __hwasan_tag_memory(const volatile void *p, unsigned char tag,
size_t size);
/// Set pointer tag. Previous tag is lost.
void *__hwasan_tag_pointer(const volatile void *p, unsigned char tag);
// Set memory tag from the current SP address to the given address to zero.
// This is meant to annotate longjmp and other non-local jumps.
// This function needs to know the (almost) exact destination frame address;
// clearing shadow for the entire thread stack like __asan_handle_no_return
// does would cause false reports.
void __hwasan_handle_longjmp(const void *sp_dst);
// Libc hook for thread creation. Should be called in the child thread before
// any instrumented code.
void __hwasan_thread_enter();
// Libc hook for thread destruction. No instrumented code should run after
// this call.
void __hwasan_thread_exit();
// Print shadow and origin for the memory range to stderr in a human-readable
// format.
void __hwasan_print_shadow(const volatile void *x, size_t size);
// Print one-line report about the memory usage of the current process.
void __hwasan_print_memory_usage();
int __sanitizer_posix_memalign(void **memptr, size_t alignment, size_t size);
void * __sanitizer_memalign(size_t alignment, size_t size);
void * __sanitizer_aligned_alloc(size_t alignment, size_t size);
void * __sanitizer___libc_memalign(size_t alignment, size_t size);
void * __sanitizer_valloc(size_t size);
void * __sanitizer_pvalloc(size_t size);
void __sanitizer_free(void *ptr);
void __sanitizer_cfree(void *ptr);
size_t __sanitizer_malloc_usable_size(const void *ptr);
struct mallinfo __sanitizer_mallinfo();
int __sanitizer_mallopt(int cmd, int value);
void __sanitizer_malloc_stats(void);
void * __sanitizer_calloc(size_t nmemb, size_t size);
void * __sanitizer_realloc(void *ptr, size_t size);
void * __sanitizer_malloc(size_t size);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -21,8 +21,8 @@
// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!
//
// Generated with: generate_netbsd_syscalls.awk
// Generated date: 2018-03-03
// Generated from: syscalls.master,v 1.291 2018/01/06 16:41:23 kamil Exp
// Generated date: 2018-10-30
// Generated from: syscalls.master,v 1.293 2018/07/31 13:00:13 rjs Exp
//
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_NETBSD_SYSCALL_HOOKS_H
@ -986,7 +986,15 @@
#define __sanitizer_syscall_post_fpathconf(res, fd, name) \
__sanitizer_syscall_post_impl_fpathconf(res, (long long)(fd), \
(long long)(name))
/* syscall 193 has been skipped */
#define __sanitizer_syscall_pre_getsockopt2(s, level, name, val, avalsize) \
__sanitizer_syscall_pre_impl_getsockopt2( \
(long long)(s), (long long)(level), (long long)(name), (long long)(val), \
(long long)(avalsize))
#define __sanitizer_syscall_post_getsockopt2(res, s, level, name, val, \
avalsize) \
__sanitizer_syscall_post_impl_getsockopt2( \
res, (long long)(s), (long long)(level), (long long)(name), \
(long long)(val), (long long)(avalsize))
#define __sanitizer_syscall_pre_getrlimit(which, rlp) \
__sanitizer_syscall_pre_impl_getrlimit((long long)(which), (long long)(rlp))
#define __sanitizer_syscall_post_getrlimit(res, which, rlp) \
@ -1752,18 +1760,8 @@
__sanitizer_syscall_post_impl___sigaction_sigtramp( \
res, (long long)(signum), (long long)(nsa), (long long)(osa), \
(long long)(tramp), (long long)(vers))
#define __sanitizer_syscall_pre_pmc_get_info(ctr, op, args) \
__sanitizer_syscall_pre_impl_pmc_get_info((long long)(ctr), (long long)(op), \
(long long)(args))
#define __sanitizer_syscall_post_pmc_get_info(res, ctr, op, args) \
__sanitizer_syscall_post_impl_pmc_get_info( \
res, (long long)(ctr), (long long)(op), (long long)(args))
#define __sanitizer_syscall_pre_pmc_control(ctr, op, args) \
__sanitizer_syscall_pre_impl_pmc_control((long long)(ctr), (long long)(op), \
(long long)(args))
#define __sanitizer_syscall_post_pmc_control(res, ctr, op, args) \
__sanitizer_syscall_post_impl_pmc_control( \
res, (long long)(ctr), (long long)(op), (long long)(args))
/* syscall 341 has been skipped */
/* syscall 342 has been skipped */
#define __sanitizer_syscall_pre_rasctl(addr, len, op) \
__sanitizer_syscall_pre_impl_rasctl((long long)(addr), (long long)(len), \
(long long)(op))
@ -3444,7 +3442,13 @@ void __sanitizer_syscall_post_impl_pathconf(long long res, long long path,
void __sanitizer_syscall_pre_impl_fpathconf(long long fd, long long name);
void __sanitizer_syscall_post_impl_fpathconf(long long res, long long fd,
long long name);
/* syscall 193 has been skipped */
void __sanitizer_syscall_pre_impl_getsockopt2(long long s, long long level,
long long name, long long val,
long long avalsize);
void __sanitizer_syscall_post_impl_getsockopt2(long long res, long long s,
long long level, long long name,
long long val,
long long avalsize);
void __sanitizer_syscall_pre_impl_getrlimit(long long which, long long rlp);
void __sanitizer_syscall_post_impl_getrlimit(long long res, long long which,
long long rlp);
@ -4001,14 +4005,8 @@ void __sanitizer_syscall_pre_impl___sigaction_sigtramp(long long signum,
void __sanitizer_syscall_post_impl___sigaction_sigtramp(
long long res, long long signum, long long nsa, long long osa,
long long tramp, long long vers);
void __sanitizer_syscall_pre_impl_pmc_get_info(long long ctr, long long op,
long long args);
void __sanitizer_syscall_post_impl_pmc_get_info(long long res, long long ctr,
long long op, long long args);
void __sanitizer_syscall_pre_impl_pmc_control(long long ctr, long long op,
long long args);
void __sanitizer_syscall_post_impl_pmc_control(long long res, long long ctr,
long long op, long long args);
/* syscall 341 has been skipped */
/* syscall 342 has been skipped */
void __sanitizer_syscall_pre_impl_rasctl(long long addr, long long len,
long long op);
void __sanitizer_syscall_post_impl_rasctl(long long res, long long addr,

View File

@ -158,8 +158,8 @@ struct XRayLogImpl {
/// The log initialization routine provided by the implementation, always
/// provided with the following parameters:
///
/// - buffer size
/// - maximum number of buffers
/// - buffer size (unused)
/// - maximum number of buffers (unused)
/// - a pointer to an argument struct that the implementation MUST handle
/// - the size of the argument struct
///
@ -355,25 +355,4 @@ XRayLogFlushStatus __xray_log_process_buffers(void (*Processor)(const char *,
} // extern "C"
namespace __xray {
/// DEPRECATED: Use __xray_log_init_mode(...) instead, and provide flag
/// configuration strings to set the options instead.
/// Options used by the LLVM XRay FDR logging implementation.
struct FDRLoggingOptions {
bool ReportErrors = false;
int Fd = -1;
};
/// DEPRECATED: Use __xray_log_init_mode(...) instead, and provide flag
/// configuration strings to set the options instead.
/// Options used by the LLVM XRay Basic (Naive) logging implementation.
struct BasicLoggingOptions {
int DurationFilterMicros = 0;
size_t MaxStackDepth = 0;
size_t ThreadBufferSize = 0;
};
} // namespace __xray
#endif // XRAY_XRAY_LOG_INTERFACE_H

View File

@ -75,6 +75,14 @@ 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)
@ -91,6 +99,11 @@ 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.
@ -100,7 +113,8 @@ add_compiler_rt_object_libraries(RTAsan_dynamic
SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
ADDITIONAL_HEADERS ${ASAN_HEADERS}
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
DEFS ${ASAN_DYNAMIC_DEFINITIONS}
DEPS ${ASAN_DEPS})
if(NOT APPLE)
add_compiler_rt_object_libraries(RTAsan
@ -108,26 +122,30 @@ if(NOT APPLE)
SOURCES ${ASAN_SOURCES}
ADDITIONAL_HEADERS ${ASAN_HEADERS}
CFLAGS ${ASAN_CFLAGS}
DEFS ${ASAN_COMMON_DEFINITIONS})
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})
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})
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})
DEFS ${ASAN_DYNAMIC_DEFINITIONS}
DEPS ${ASAN_DEPS})
endif()
# Build ASan runtimes shipped with Clang.
@ -138,6 +156,7 @@ if(APPLE)
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
@ -215,13 +234,14 @@ else()
endif()
set(ASAN_DYNAMIC_WEAK_INTERCEPTION)
if (MSVC)
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})
DEFS ${ASAN_COMMON_DEFINITIONS}
DEPS ${ASAN_DEPS})
set(ASAN_DYNAMIC_WEAK_INTERCEPTION
AsanWeakInterception
UbsanWeakInterception
@ -266,7 +286,8 @@ else()
SOURCES asan_globals_win.cc
asan_win_dll_thunk.cc
CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DLL_THUNK
DEFS ${ASAN_COMMON_DEFINITIONS})
DEFS ${ASAN_COMMON_DEFINITIONS}
DEPS ${ASAN_DEPS})
add_compiler_rt_runtime(clang_rt.asan_dll_thunk
STATIC
@ -291,7 +312,8 @@ else()
SOURCES asan_globals_win.cc
asan_win_dynamic_runtime_thunk.cc
CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS}
DEFS ${ASAN_COMMON_DEFINITIONS})
DEFS ${ASAN_COMMON_DEFINITIONS}
DEPS ${ASAN_DEPS})
add_compiler_rt_runtime(clang_rt.asan_dynamic_runtime_thunk
STATIC

View File

@ -148,6 +148,7 @@ const uptr kAllocatorSpace = 0x600000000000ULL;
const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
typedef DefaultSizeClassMap SizeClassMap;
# endif
template <typename AddressSpaceViewTy>
struct AP64 { // Allocator64 parameters. Deliberately using a short name.
static const uptr kSpaceBeg = kAllocatorSpace;
static const uptr kSpaceSize = kAllocatorSize;
@ -155,37 +156,57 @@ struct AP64 { // Allocator64 parameters. Deliberately using a short name.
typedef __asan::SizeClassMap SizeClassMap;
typedef AsanMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
using AddressSpaceView = AddressSpaceViewTy;
};
typedef SizeClassAllocator64<AP64> PrimaryAllocator;
template <typename AddressSpaceView>
using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>;
using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
#else // Fallback to SizeClassAllocator32.
static const uptr kRegionSizeLog = 20;
static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
# if SANITIZER_WORDSIZE == 32
typedef FlatByteMap<kNumRegions> ByteMap;
template <typename AddressSpaceView>
using ByteMapASVT = FlatByteMap<kNumRegions, AddressSpaceView>;
# elif SANITIZER_WORDSIZE == 64
typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
template <typename AddressSpaceView>
using ByteMapASVT =
TwoLevelByteMap<(kNumRegions >> 12), 1 << 12, AddressSpaceView>;
# endif
typedef CompactSizeClassMap SizeClassMap;
template <typename AddressSpaceViewTy>
struct AP32 {
static const uptr kSpaceBeg = 0;
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
static const uptr kMetadataSize = 16;
typedef __asan::SizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = __asan::kRegionSizeLog;
typedef __asan::ByteMap ByteMap;
using AddressSpaceView = AddressSpaceViewTy;
using ByteMap = __asan::ByteMapASVT<AddressSpaceView>;
typedef AsanMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
typedef SizeClassAllocator32<AP32> PrimaryAllocator;
template <typename AddressSpaceView>
using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >;
using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
#endif // SANITIZER_CAN_USE_ALLOCATOR64
static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
SecondaryAllocator> AsanAllocator;
template <typename AddressSpaceView>
using AllocatorCacheASVT =
SizeClassAllocatorLocalCache<PrimaryAllocatorASVT<AddressSpaceView>>;
using AllocatorCache = AllocatorCacheASVT<LocalAddressSpaceView>;
template <typename AddressSpaceView>
using SecondaryAllocatorASVT =
LargeMmapAllocator<AsanMapUnmapCallback, DefaultLargeMmapAllocatorPtrArray,
AddressSpaceView>;
template <typename AddressSpaceView>
using AsanAllocatorASVT =
CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>,
AllocatorCacheASVT<AddressSpaceView>,
SecondaryAllocatorASVT<AddressSpaceView>>;
using AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>;
struct AsanThreadLocalMallocStorage {
uptr quarantine_cache[16];

View File

@ -125,9 +125,8 @@ void ErrorAllocTypeMismatch::Print() {
Decorator d;
Printf("%s", d.Error());
Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n",
scariness.GetDescription(),
alloc_names[alloc_type], dealloc_names[dealloc_type],
addr_description.addr);
scariness.GetDescription(), alloc_names[alloc_type],
dealloc_names[dealloc_type], addr_description.Address());
Printf("%s", d.Default());
CHECK_GT(dealloc_stack->size, 0);
scariness.Print();

View File

@ -110,8 +110,8 @@ struct ErrorFreeNotMalloced : ErrorBase {
struct ErrorAllocTypeMismatch : ErrorBase {
const BufferedStackTrace *dealloc_stack;
HeapAddressDescription addr_description;
AllocType alloc_type, dealloc_type;
AddressDescription addr_description;
ErrorAllocTypeMismatch() = default; // (*)
ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
@ -119,9 +119,8 @@ struct ErrorAllocTypeMismatch : ErrorBase {
: ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
dealloc_stack(stack),
alloc_type(alloc_type_),
dealloc_type(dealloc_type_) {
GetHeapAddressInformation(addr, 1, &addr_description);
};
dealloc_type(dealloc_type_),
addr_description(addr, 1, false) {}
void Print();
};

View File

@ -152,8 +152,6 @@ ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
ASAN_FLAG(bool, halt_on_error, true,
"Crash the program after printing the first error report "
"(WARNING: USE AT YOUR OWN RISK!)")
ASAN_FLAG(bool, use_odr_indicator, false,
"Use special ODR indicator symbol for ODR violation detection")
ASAN_FLAG(bool, allocator_frees_and_returns_null_on_realloc_zero, true,
"realloc(p, 0) is equivalent to free(p) by default (Same as the "
"POSIX standard). If set to false, realloc(p, 0) will return a "

View File

@ -190,6 +190,13 @@ static void ThreadExitHook(void *hook, uptr os_id) {
AsanThread::TSDDtor(per_thread);
}
bool HandleDlopenInit() {
// Not supported on this platform.
static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
"Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
return false;
}
} // namespace __asan
// These are declared (in extern "C") by <zircon/sanitizer.h>.

View File

@ -83,9 +83,11 @@ static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {
}
static void ReportGlobal(const Global &g, const char *prefix) {
Report("%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n",
prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name,
g.module_name, g.has_dynamic_init);
Report(
"%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu "
"odr_indicator=%p\n",
prefix, &g, (void *)g.beg, g.size, g.size_with_redzone, g.name,
g.module_name, g.has_dynamic_init, (void *)g.odr_indicator);
if (g.location) {
Report(" location (%p): name=%s[%p], %d %d\n", g.location,
g.location->filename, g.location->filename, g.location->line_no,
@ -133,6 +135,9 @@ enum GlobalSymbolState {
// this method in case compiler instruments global variables through their
// local aliases.
static void CheckODRViolationViaIndicator(const Global *g) {
// Instrumentation requests to skip ODR check.
if (g->odr_indicator == UINTPTR_MAX)
return;
u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator);
if (*odr_indicator == UNREGISTERED) {
*odr_indicator = REGISTERED;
@ -183,9 +188,7 @@ static void CheckODRViolationViaPoisoning(const Global *g) {
// This routine chooses between two different methods of ODR violation
// detection.
static inline bool UseODRIndicator(const Global *g) {
// Use ODR indicator method iff use_odr_indicator flag is set and
// indicator symbol address is not 0.
return flags()->use_odr_indicator && g->odr_indicator > 0;
return g->odr_indicator > 0;
}
// Register a global variable.
@ -248,7 +251,7 @@ static void UnregisterGlobal(const Global *g) {
// implementation. It might not be worth doing anyway.
// Release ODR indicator.
if (UseODRIndicator(g)) {
if (UseODRIndicator(g) && g->odr_indicator != UINTPTR_MAX) {
u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator);
*odr_indicator = UNREGISTERED;
}

View File

@ -29,7 +29,7 @@ static void call_on_globals(void (*hook)(__asan_global *, uptr)) {
__asan_global *end = &__asan_globals_end;
uptr bytediff = (uptr)end - (uptr)start;
if (bytediff % sizeof(__asan_global) != 0) {
#ifdef SANITIZER_DLL_THUNK
#if defined(SANITIZER_DLL_THUNK) || defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)
__debugbreak();
#else
CHECK("corrupt asan global array");

View File

@ -111,6 +111,11 @@ void *AsanDlSymNext(const char *sym);
void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name);
// Returns `true` iff most of ASan init process should be skipped due to the
// ASan library being loaded via `dlopen()`. Platforms may perform any
// `dlopen()` specific initialization inside this function.
bool HandleDlopenInit();
// Add convenient macro for interface functions that may be represented as
// weak hooks.
#define ASAN_MALLOC_HOOK(ptr, size) \

View File

@ -248,6 +248,13 @@ void *AsanDlSymNext(const char *sym) {
return dlsym(RTLD_NEXT, sym);
}
bool HandleDlopenInit() {
// Not supported on this platform.
static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
"Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
return false;
}
} // namespace __asan
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||

View File

@ -209,7 +209,7 @@ INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
}
INTERCEPTOR(int, mallopt, int cmd, int value) {
return -1;
return 0;
}
#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO

View File

@ -61,4 +61,25 @@ using namespace __asan;
#include "sanitizer_common/sanitizer_malloc_mac.inc"
namespace COMMON_MALLOC_NAMESPACE {
bool HandleDlopenInit() {
static_assert(SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
"Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be true");
// We have no reliable way of knowing how we are being loaded
// so make it a requirement on Apple platforms to set this environment
// variable to indicate that we want to perform initialization via
// dlopen().
auto init_str = GetEnv("APPLE_ASAN_INIT_FOR_DLOPEN");
if (!init_str)
return false;
if (internal_strncmp(init_str, "1", 1) != 0)
return false;
// When we are loaded via `dlopen()` path we still initialize the malloc zone
// so Symbolication clients (e.g. `leaks`) that load the ASan allocator can
// find an initialized malloc zone.
InitMallocZoneFields();
return true;
}
} // namespace COMMON_MALLOC_NAMESPACE
#endif

View File

@ -14,8 +14,17 @@
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// Intentionally not including windows.h here, to avoid the risk of
// pulling in conflicting declarations of these functions. (With mingw-w64,
// there's a risk of windows.h pulling in stdint.h.)
typedef int BOOL;
typedef void *HANDLE;
typedef const void *LPCVOID;
typedef void *LPVOID;
#define HEAP_ZERO_MEMORY 0x00000008
#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010
#include "asan_allocator.h"
#include "asan_interceptors.h"
@ -125,12 +134,17 @@ void *_recalloc_base(void *p, size_t n, size_t elem_size) {
}
ALLOCATION_FUNCTION_ATTRIBUTE
size_t _msize(const void *ptr) {
size_t _msize(void *ptr) {
GET_CURRENT_PC_BP_SP;
(void)sp;
return asan_malloc_usable_size(ptr, pc, bp);
}
ALLOCATION_FUNCTION_ATTRIBUTE
size_t _msize_base(void *ptr) {
return _msize(ptr);
}
ALLOCATION_FUNCTION_ATTRIBUTE
void *_expand(void *memblock, size_t size) {
// _expand is used in realloc-like functions to resize the buffer if possible.
@ -226,6 +240,7 @@ void ReplaceSystemMalloc() {
TryToOverrideFunction("_recalloc_base", (uptr)_recalloc);
TryToOverrideFunction("_recalloc_crt", (uptr)_recalloc);
TryToOverrideFunction("_msize", (uptr)_msize);
TryToOverrideFunction("_msize_base", (uptr)_msize);
TryToOverrideFunction("_expand", (uptr)_expand);
TryToOverrideFunction("_expand_base", (uptr)_expand);

View File

@ -26,7 +26,7 @@
// anyway by passing extra -export flags to the linker, which is exactly that
// dllexport would normally do. We need to export them in order to make the
// VS2015 dynamic CRT (MD) work.
#if SANITIZER_WINDOWS
#if SANITIZER_WINDOWS && defined(_MSC_VER)
#define CXX_OPERATOR_ATTRIBUTE
#define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:" sym))
#ifdef _WIN64

View File

@ -40,6 +40,51 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
// ---------------------- TSD ---------------- {{{1
#if SANITIZER_NETBSD || SANITIZER_FREEBSD
// Thread Static Data cannot be used in early init on NetBSD and FreeBSD.
// Reuse the Asan TSD API for compatibility with existing code
// with an alternative implementation.
static void (*tsd_destructor)(void *tsd) = nullptr;
struct tsd_key {
tsd_key() : key(nullptr) {}
~tsd_key() {
CHECK(tsd_destructor);
if (key)
(*tsd_destructor)(key);
}
void *key;
};
static thread_local struct tsd_key key;
void AsanTSDInit(void (*destructor)(void *tsd)) {
CHECK(!tsd_destructor);
tsd_destructor = destructor;
}
void *AsanTSDGet() {
CHECK(tsd_destructor);
return key.key;
}
void AsanTSDSet(void *tsd) {
CHECK(tsd_destructor);
CHECK(tsd);
CHECK(!key.key);
key.key = tsd;
}
void PlatformTSDDtor(void *tsd) {
CHECK(tsd_destructor);
CHECK_EQ(key.key, tsd);
key.key = nullptr;
// Make sure that signal handler can not see a stale current thread pointer.
atomic_signal_fence(memory_order_seq_cst);
AsanThread::TSDDtor(tsd);
}
#else
static pthread_key_t tsd_key;
static bool tsd_key_inited = false;
void AsanTSDInit(void (*destructor)(void *tsd)) {
@ -67,6 +112,7 @@ void PlatformTSDDtor(void *tsd) {
}
AsanThread::TSDDtor(tsd);
}
#endif
} // namespace __asan
#endif // SANITIZER_POSIX

View File

@ -12,6 +12,9 @@
// ASan-private header for error reporting functions.
//===----------------------------------------------------------------------===//
#ifndef ASAN_REPORT_H
#define ASAN_REPORT_H
#include "asan_allocator.h"
#include "asan_internal.h"
#include "asan_thread.h"
@ -92,3 +95,4 @@ void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr,
BufferedStackTrace *stack);
} // namespace __asan
#endif // ASAN_REPORT_H

View File

@ -213,6 +213,12 @@ static void HandleExit() {
}
}
bool HandleDlopenInit() {
// Not supported on this platform.
static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
"Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
return false;
}
} // namespace __asan
// These are declared (in extern "C") by <some_path/sanitizer.h>.

View File

@ -383,6 +383,19 @@ void PrintAddressSpaceLayout() {
kHighShadowBeg > kMidMemEnd);
}
#if defined(__thumb__) && defined(__linux__)
#define START_BACKGROUND_THREAD_IN_ASAN_INTERNAL
#endif
#ifndef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL
static bool UNUSED __local_asan_dyninit = [] {
MaybeStartBackgroudThread();
SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback);
return false;
}();
#endif
static void AsanInitInternal() {
if (LIKELY(asan_inited)) return;
SanitizerToolName = "AddressSanitizer";
@ -396,6 +409,14 @@ static void AsanInitInternal() {
// initialization steps look at flags().
InitializeFlags();
// Stop performing init at this point if we are being loaded via
// dlopen() and the platform supports it.
if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) {
asan_init_is_running = false;
VReport(1, "AddressSanitizer init is being performed for dlopen().\n");
return;
}
AsanCheckIncompatibleRT();
AsanCheckDynamicRTPrereqs();
AvoidCVE_2016_2143();
@ -420,6 +441,8 @@ static void AsanInitInternal() {
__asan_option_detect_stack_use_after_return =
flags()->detect_stack_use_after_return;
__sanitizer::InitializePlatformEarly();
// Re-exec ourselves if we need to set additional env or command line args.
MaybeReexec();
@ -447,8 +470,10 @@ static void AsanInitInternal() {
allocator_options.SetFrom(flags(), common_flags());
InitializeAllocator(allocator_options);
#ifdef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL
MaybeStartBackgroudThread();
SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback);
#endif
// On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
// should be set to 1 prior to initializing the threads.

View File

@ -223,9 +223,11 @@ void AsanThread::Init(const InitOptions *options) {
atomic_store(&stack_switching_, false, memory_order_release);
CHECK_EQ(this->stack_size(), 0U);
SetThreadStackAndTls(options);
CHECK_GT(this->stack_size(), 0U);
CHECK(AddrIsInMem(stack_bottom_));
CHECK(AddrIsInMem(stack_top_ - 1));
if (stack_top_ != stack_bottom_) {
CHECK_GT(this->stack_size(), 0U);
CHECK(AddrIsInMem(stack_bottom_));
CHECK(AddrIsInMem(stack_top_ - 1));
}
ClearShadowForThreadStackAndTLS();
fake_stack_ = nullptr;
if (__asan_option_detect_stack_use_after_return)
@ -289,20 +291,23 @@ void AsanThread::SetThreadStackAndTls(const InitOptions *options) {
DCHECK_EQ(options, nullptr);
uptr tls_size = 0;
uptr stack_size = 0;
GetThreadStackAndTls(tid() == 0, const_cast<uptr *>(&stack_bottom_),
const_cast<uptr *>(&stack_size), &tls_begin_, &tls_size);
GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size, &tls_begin_,
&tls_size);
stack_top_ = stack_bottom_ + stack_size;
tls_end_ = tls_begin_ + tls_size;
dtls_ = DTLS_Get();
int local;
CHECK(AddrIsInStack((uptr)&local));
if (stack_top_ != stack_bottom_) {
int local;
CHECK(AddrIsInStack((uptr)&local));
}
}
#endif // !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
void AsanThread::ClearShadowForThreadStackAndTLS() {
PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
if (stack_top_ != stack_bottom_)
PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
if (tls_begin_ != tls_end_) {
uptr tls_begin_aligned = RoundDownTo(tls_begin_, SHADOW_GRANULARITY);
uptr tls_end_aligned = RoundUpTo(tls_end_, SHADOW_GRANULARITY);
@ -314,6 +319,9 @@ void AsanThread::ClearShadowForThreadStackAndTLS() {
bool AsanThread::GetStackFrameAccessByAddr(uptr addr,
StackFrameAccess *access) {
if (stack_top_ == stack_bottom_)
return false;
uptr bottom = 0;
if (AddrIsInStack(addr)) {
bottom = stack_bottom();

View File

@ -159,6 +159,14 @@ INTERCEPTOR_WINAPI(DWORD, CreateThread,
namespace __asan {
void InitializePlatformInterceptors() {
// The interceptors were not designed to be removable, so we have to keep this
// module alive for the life of the process.
HMODULE pinned;
CHECK(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_PIN,
(LPCWSTR)&InitializePlatformInterceptors,
&pinned));
ASAN_INTERCEPT_FUNC(CreateThread);
ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter);
@ -314,6 +322,13 @@ int __asan_set_seh_filter() {
return 0;
}
bool HandleDlopenInit() {
// Not supported on this platform.
static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
"Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
return false;
}
#if !ASAN_DYNAMIC
// The CRT runs initializers in this order:
// - C initializers, from XIA to XIZ

View File

@ -48,6 +48,7 @@ INTERCEPT_WRAP_W_WWW(_recalloc)
INTERCEPT_WRAP_W_WWW(_recalloc_base)
INTERCEPT_WRAP_W_W(_msize)
INTERCEPT_WRAP_W_W(_msize_base)
INTERCEPT_WRAP_W_W(_expand)
INTERCEPT_WRAP_W_W(_expand_dbg)

View File

@ -231,6 +231,10 @@ class DarwinSymbolizer(Symbolizer):
"""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()
@ -473,7 +477,7 @@ class SymbolizationLoop(object):
symbolized_line = self.symbolize_address(addr, binary, offset, arch)
if not symbolized_line:
if original_binary != binary:
symbolized_line = self.symbolize_address(addr, binary, offset, arch)
symbolized_line = self.symbolize_address(addr, original_binary, offset, arch)
return self.get_symbolized_lines(symbolized_line)

View File

@ -68,11 +68,6 @@ if(APPLE)
list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS})
endif()
if(MSVC)
# Disable exceptions on Windows until they work reliably.
list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -fno-exceptions -DGTEST_HAS_SEH=0)
endif()
set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore")
set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS
${ASAN_UNITTEST_COMMON_CFLAGS}

View File

@ -102,6 +102,7 @@ TEST(AddressSanitizerInterface, GetHeapSizeTest) {
}
}
#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 =
@ -135,6 +136,7 @@ TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
// 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);

View File

@ -153,6 +153,7 @@ TEST(AddressSanitizer, QuarantineTest) {
EXPECT_LT(i, max_i);
}
#if !defined(__NetBSD__)
void *ThreadedQuarantineTestWorker(void *unused) {
(void)unused;
u32 seed = my_rand();
@ -187,6 +188,7 @@ TEST(AddressSanitizer, ThreadedQuarantineTest) {
EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20));
}
}
#endif
void *ThreadedOneSizeMallocStress(void *unused) {
(void)unused;

View File

@ -1295,6 +1295,7 @@ TEST(AddressSanitizer, DISABLED_DemoTooMuchMemoryTest) {
}
}
#if !defined(__NetBSD__) && !defined(__i386__)
// https://github.com/google/sanitizers/issues/66
TEST(AddressSanitizer, BufferOverflowAfterManyFrees) {
for (int i = 0; i < 1000000; i++) {
@ -1304,6 +1305,7 @@ TEST(AddressSanitizer, BufferOverflowAfterManyFrees) {
EXPECT_DEATH(x[Ident(8192)] = 0, "AddressSanitizer: heap-buffer-overflow");
delete [] Ident(x);
}
#endif
// Test that instrumentation of stack allocations takes into account

View File

@ -505,7 +505,9 @@ set(mips64el_SOURCES ${GENERIC_TF_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

View File

@ -1,137 +0,0 @@
absvdi2
absvsi2
absvti2
adddf3
addsf3
addtf3
addvdi3
addvsi3
addvti3
apple_versioning
ashldi3
ashlti3
ashrdi3
ashrti3
atomic_flag_clear
atomic_flag_clear_explicit
atomic_flag_test_and_set
atomic_flag_test_and_set_explicit
atomic_signal_fence
atomic_thread_fence
clear_cache
clzdi2
clzsi2
clzti2
cmpdi2
cmpti2
comparedf2
comparesf2
ctzdi2
ctzsi2
ctzti2
divdc3
divdf3
divdi3
divmoddi4
divmodsi4
divsc3
divsf3
divsi3
divtf3
divti3
divxc3
enable_execute_stack
extendhfsf2
extendsfdf2
ffsdi2
ffsti2
fixdfdi
fixdfsi
fixdfti
fixsfdi
fixsfsi
fixsfti
fixunsdfdi
fixunsdfsi
fixunsdfti
fixunssfdi
fixunssfsi
fixunssfti
fixunsxfdi
fixunsxfsi
fixunsxfti
fixxfdi
fixxfti
floatdidf
floatdisf
floatdixf
floatsidf
floatsisf
floattidf
floattisf
floattixf
floatunsidf
floatunsisf
floatuntidf
floatuntisf
floatuntixf
gcc_personality_v0
gnu_f2h_ieee
gnu_h2f_ieee
lshrdi3
lshrti3
moddi3
modsi3
modti3
muldc3
muldf3
muldi3
mulodi4
mulosi4
muloti4
mulsc3
mulsf3
multf3
multi3
mulvdi3
mulvsi3
mulvti3
mulxc3
negdf2
negdi2
negsf2
negti2
negvdi2
negvsi2
negvti2
paritydi2
paritysi2
parityti2
popcountdi2
popcountsi2
popcountti2
powidf2
powisf2
powitf2
powixf2
subdf3
subsf3
subtf3
subvdi3
subvsi3
subvti3
trampoline_setup
truncdfhf2
truncdfsf2
truncsfhf2
ucmpdi2
ucmpti2
udivdi3
udivmoddi4
udivmodsi4
udivmodti4
udivsi3
udivti3
umoddi3
umodsi3
umodti3

View File

@ -178,7 +178,7 @@ LOCAL_LABEL(do_substraction):
push {r0, r1, r2, r3}
movs r0, r4
bl __clzsi2
bl SYMBOL_NAME(__clzsi2)
movs r5, r0
pop {r0, r1, r2, r3}
// shift = rep_clz(aSignificand) - rep_clz(implicitBit << 3);

View File

@ -55,7 +55,7 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
mov ip, #APSR_C
msr APSR_nzcvq, ip
#else
msr CPSR_f, #APSR_C
msr APSR_nzcvq, #APSR_C
#endif
JMP(lr)
#endif
@ -115,11 +115,7 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple)
movne ip, #(APSR_C)
1:
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
msr APSR_nzcvq, ip
#else
msr CPSR_f, ip
#endif
pop {r0-r3}
POP_PC()
#endif

View File

@ -55,7 +55,7 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
mov ip, #APSR_C
msr APSR_nzcvq, ip
#else
msr CPSR_f, #APSR_C
msr APSR_nzcvq, #APSR_C
#endif
JMP(lr)
#endif
@ -115,11 +115,7 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmple)
movne ip, #(APSR_C)
1:
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
msr APSR_nzcvq, ip
#else
msr CPSR_f, ip
#endif
pop {r0-r3}
POP_PC()
#endif

View File

@ -16,8 +16,13 @@
/* Returns: the number of leading 0-bits */
#if !defined(__clang__) && (defined(__sparc64__) || defined(__mips64) || defined(__riscv__))
/* gcc resolves __builtin_clz -> __clzdi2 leading to infinite recursion */
#if !defined(__clang__) && \
((defined(__sparc__) && defined(__arch64__)) || \
defined(__mips64) || \
(defined(__riscv) && __SIZEOF_POINTER__ >= 8))
/* On 64-bit architectures with neither a native clz instruction nor a native
* ctz instruction, gcc resolves __builtin_clz to __clzdi2 rather than
* __clzsi2, leading to infinite recursion. */
#define __builtin_clz(a) __clzsi2(a)
extern si_int __clzsi2(si_int);
#endif

View File

@ -55,6 +55,9 @@ enum ProcessorTypes {
AMD_BTVER2,
AMDFAM17H,
INTEL_KNM,
INTEL_GOLDMONT,
INTEL_GOLDMONT_PLUS,
INTEL_TREMONT,
CPU_TYPE_MAX
};
@ -76,6 +79,8 @@ enum ProcessorSubtypes {
INTEL_COREI7_SKYLAKE,
INTEL_COREI7_SKYLAKE_AVX512,
INTEL_COREI7_CANNONLAKE,
INTEL_COREI7_ICELAKE_CLIENT,
INTEL_COREI7_ICELAKE_SERVER,
CPU_SUBTYPE_MAX
};
@ -110,7 +115,12 @@ enum ProcessorFeatures {
FEATURE_AVX512IFMA,
FEATURE_AVX5124VNNIW,
FEATURE_AVX5124FMAPS,
FEATURE_AVX512VPOPCNTDQ
FEATURE_AVX512VPOPCNTDQ,
FEATURE_AVX512VBMI2,
FEATURE_GFNI,
FEATURE_VPCLMULQDQ,
FEATURE_AVX512VNNI,
FEATURE_AVX512BITALG
};
// The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
@ -364,6 +374,14 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
case 0x4c: // really airmont
*Type = INTEL_SILVERMONT;
break; // "silvermont"
// Goldmont:
case 0x5c: // Apollo Lake
case 0x5f: // Denverton
*Type = INTEL_GOLDMONT;
break; // "goldmont"
case 0x7a:
*Type = INTEL_GOLDMONT_PLUS;
break;
case 0x57:
*Type = INTEL_KNL; // knl
@ -438,35 +456,45 @@ static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
}
static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
unsigned *FeaturesOut) {
unsigned *FeaturesOut,
unsigned *Features2Out) {
unsigned Features = 0;
unsigned Features2 = 0;
unsigned EAX, EBX;
#define setFeature(F) \
do { \
if (F < 32) \
Features |= 1U << (F & 0x1f); \
else if (F < 64) \
Features2 |= 1U << ((F - 32) & 0x1f); \
} while (0)
if ((EDX >> 15) & 1)
Features |= 1 << FEATURE_CMOV;
setFeature(FEATURE_CMOV);
if ((EDX >> 23) & 1)
Features |= 1 << FEATURE_MMX;
setFeature(FEATURE_MMX);
if ((EDX >> 25) & 1)
Features |= 1 << FEATURE_SSE;
setFeature(FEATURE_SSE);
if ((EDX >> 26) & 1)
Features |= 1 << FEATURE_SSE2;
setFeature(FEATURE_SSE2);
if ((ECX >> 0) & 1)
Features |= 1 << FEATURE_SSE3;
setFeature(FEATURE_SSE3);
if ((ECX >> 1) & 1)
Features |= 1 << FEATURE_PCLMUL;
setFeature(FEATURE_PCLMUL);
if ((ECX >> 9) & 1)
Features |= 1 << FEATURE_SSSE3;
setFeature(FEATURE_SSSE3);
if ((ECX >> 12) & 1)
Features |= 1 << FEATURE_FMA;
setFeature(FEATURE_FMA);
if ((ECX >> 19) & 1)
Features |= 1 << FEATURE_SSE4_1;
setFeature(FEATURE_SSE4_1);
if ((ECX >> 20) & 1)
Features |= 1 << FEATURE_SSE4_2;
setFeature(FEATURE_SSE4_2);
if ((ECX >> 23) & 1)
Features |= 1 << FEATURE_POPCNT;
setFeature(FEATURE_POPCNT);
if ((ECX >> 25) & 1)
Features |= 1 << FEATURE_AES;
setFeature(FEATURE_AES);
// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
// indicates that the AVX registers will be saved and restored on context
@ -477,43 +505,53 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
if (HasAVX)
Features |= 1 << FEATURE_AVX;
setFeature(FEATURE_AVX);
bool HasLeaf7 =
MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
if (HasLeaf7 && ((EBX >> 3) & 1))
Features |= 1 << FEATURE_BMI;
setFeature(FEATURE_BMI);
if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
Features |= 1 << FEATURE_AVX2;
setFeature(FEATURE_AVX2);
if (HasLeaf7 && ((EBX >> 9) & 1))
Features |= 1 << FEATURE_BMI2;
setFeature(FEATURE_BMI2);
if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512F;
setFeature(FEATURE_AVX512F);
if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512DQ;
setFeature(FEATURE_AVX512DQ);
if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512IFMA;
setFeature(FEATURE_AVX512IFMA);
if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512PF;
setFeature(FEATURE_AVX512PF);
if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512ER;
setFeature(FEATURE_AVX512ER);
if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512CD;
setFeature(FEATURE_AVX512CD);
if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512BW;
setFeature(FEATURE_AVX512BW);
if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512VL;
setFeature(FEATURE_AVX512VL);
if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512VBMI;
setFeature(FEATURE_AVX512VBMI);
if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512VBMI2);
if (HasLeaf7 && ((ECX >> 8) & 1))
setFeature(FEATURE_GFNI);
if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
setFeature(FEATURE_VPCLMULQDQ);
if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512VNNI);
if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512BITALG);
if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX512VPOPCNTDQ;
setFeature(FEATURE_AVX512VPOPCNTDQ);
if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX5124VNNIW;
setFeature(FEATURE_AVX5124VNNIW);
if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
Features |= 1 << FEATURE_AVX5124FMAPS;
setFeature(FEATURE_AVX5124FMAPS);
unsigned MaxExtLevel;
getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
@ -521,13 +559,15 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
!getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
if (HasExtLeaf1 && ((ECX >> 6) & 1))
Features |= 1 << FEATURE_SSE4_A;
setFeature(FEATURE_SSE4_A);
if (HasExtLeaf1 && ((ECX >> 11) & 1))
Features |= 1 << FEATURE_XOP;
setFeature(FEATURE_XOP);
if (HasExtLeaf1 && ((ECX >> 16) & 1))
Features |= 1 << FEATURE_FMA4;
setFeature(FEATURE_FMA4);
*FeaturesOut = Features;
*Features2Out = Features2;
#undef setFeature
}
#if defined(HAVE_INIT_PRIORITY)
@ -548,8 +588,9 @@ struct __processor_model {
unsigned int __cpu_subtype;
unsigned int __cpu_features[1];
} __cpu_model = {0, 0, 0, {0}};
unsigned int __cpu_features2;
/* A constructor function that is sets __cpu_model and __cpu_features with
/* A constructor function that is sets __cpu_model and __cpu_features2 with
the right values. This needs to run only once. This constructor is
given the highest priority and it should run before constructors without
the priority set. However, it still runs after ifunc initializers and
@ -562,6 +603,7 @@ __cpu_indicator_init(void) {
unsigned Vendor;
unsigned Model, Family, Brand_id;
unsigned Features = 0;
unsigned Features2 = 0;
/* This function needs to run just once. */
if (__cpu_model.__cpu_vendor)
@ -580,8 +622,9 @@ __cpu_indicator_init(void) {
Brand_id = EBX & 0xff;
/* Find available features. */
getAvailableFeatures(ECX, EDX, MaxLeaf, &Features);
getAvailableFeatures(ECX, EDX, MaxLeaf, &Features, &Features2);
__cpu_model.__cpu_features[0] = Features;
__cpu_features2 = Features2;
if (Vendor == SIG_INTEL) {
/* Get CPU type. */

View File

@ -16,8 +16,13 @@
/* Returns: the number of trailing 0-bits */
#if !defined(__clang__) && (defined(__sparc64__) || defined(__mips64) || defined(__riscv__))
/* gcc resolves __builtin_ctz -> __ctzdi2 leading to infinite recursion */
#if !defined(__clang__) && \
((defined(__sparc__) && defined(__arch64__)) || \
defined(__mips64) || \
(defined(__riscv) && __SIZEOF_POINTER__ >= 8))
/* On 64-bit architectures with neither a native clz instruction nor a native
* ctz instruction, gcc resolves __builtin_ctz to __ctzdi2 rather than
* __ctzsi2, leading to infinite recursion. */
#define __builtin_ctz(a) __ctzsi2(a)
extern si_int __ctzsi2(si_int);
#endif

View File

@ -12,6 +12,8 @@
* ===----------------------------------------------------------------------===
*/
#define DOUBLE_PRECISION
#include "fp_lib.h"
#include "int_lib.h"
#include "int_math.h"
@ -21,7 +23,7 @@ COMPILER_RT_ABI Dcomplex
__divdc3(double __a, double __b, double __c, double __d)
{
int __ilogbw = 0;
double __logbw = crt_logb(crt_fmax(crt_fabs(__c), crt_fabs(__d)));
double __logbw = __compiler_rt_logb(crt_fmax(crt_fabs(__c), crt_fabs(__d)));
if (crt_isfinite(__logbw))
{
__ilogbw = (int)__logbw;

View File

@ -21,36 +21,36 @@
COMPILER_RT_ABI fp_t
__divdf3(fp_t a, fp_t b) {
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
const rep_t quotientSign = (toRep(a) ^ toRep(b)) & signBit;
rep_t aSignificand = toRep(a) & significandMask;
rep_t bSignificand = toRep(b) & significandMask;
int scale = 0;
// Detect if a or b is zero, denormal, infinity, or NaN.
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
const rep_t aAbs = toRep(a) & absMask;
const rep_t bAbs = toRep(b) & absMask;
// NaN / anything = qNaN
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
// anything / NaN = qNaN
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
if (aAbs == infRep) {
// infinity / infinity = NaN
if (bAbs == infRep) return fromRep(qnanRep);
// infinity / anything else = +/- infinity
else return fromRep(aAbs | quotientSign);
}
// anything else / infinity = +/- 0
if (bAbs == infRep) return fromRep(quotientSign);
if (!aAbs) {
// zero / zero = NaN
if (!bAbs) return fromRep(qnanRep);
@ -59,28 +59,28 @@ __divdf3(fp_t a, fp_t b) {
}
// anything else / zero = +/- infinity
if (!bAbs) return fromRep(infRep | quotientSign);
// one or both of a or b is denormal, the other (if applicable) is a
// normal number. Renormalize one or both of a and b, and set scale to
// include the necessary exponent adjustment.
if (aAbs < implicitBit) scale += normalize(&aSignificand);
if (bAbs < implicitBit) scale -= normalize(&bSignificand);
}
// Or in the implicit significand bit. (If we fell through from the
// denormal path it was already set by normalize( ), but setting it twice
// won't hurt anything.)
aSignificand |= implicitBit;
bSignificand |= implicitBit;
int quotientExponent = aExponent - bExponent + scale;
// Align the significand of b as a Q31 fixed-point number in the range
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
// is accurate to about 3.5 binary digits.
const uint32_t q31b = bSignificand >> 21;
uint32_t recip32 = UINT32_C(0x7504f333) - q31b;
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
//
// x1 = x0 * (2 - x0 * b)
@ -95,13 +95,13 @@ __divdf3(fp_t a, fp_t b) {
recip32 = (uint64_t)recip32 * correction32 >> 31;
correction32 = -((uint64_t)recip32 * q31b >> 32);
recip32 = (uint64_t)recip32 * correction32 >> 31;
// recip32 might have overflowed to exactly zero in the preceding
// computation if the high word of b is exactly 1.0. This would sabotage
// the full-width final stage of the computation that follows, so we adjust
// recip32 downward by one bit.
recip32--;
// We need to perform one more iteration to get us to 56 binary digits;
// The last iteration needs to happen with extra precision.
const uint32_t q63blo = bSignificand << 11;
@ -110,14 +110,14 @@ __divdf3(fp_t a, fp_t b) {
uint32_t cHi = correction >> 32;
uint32_t cLo = correction;
reciprocal = (uint64_t)recip32*cHi + ((uint64_t)recip32*cLo >> 32);
// We already adjusted the 32-bit estimate, now we need to adjust the final
// 64-bit reciprocal estimate downward to ensure that it is strictly smaller
// than the infinitely precise exact reciprocal. Because the computation
// of the Newton-Raphson step is truncating at every step, this adjustment
// is small; most of the work is already done.
reciprocal -= 2;
// The numerical reciprocal is accurate to within 2^-56, lies in the
// interval [0.5, 1.0), and is strictly smaller than the true reciprocal
// of b. Multiplying a by this reciprocal thus gives a numerical q = a/b
@ -127,12 +127,12 @@ __divdf3(fp_t a, fp_t b) {
// 2. q is in the interval [0.5, 2.0)
// 3. the error in q is bounded away from 2^-53 (actually, we have a
// couple of bits to spare, but this is all we need).
// We need a 64 x 64 multiply high to compute q, which isn't a basic
// operation in C, so we need to be a little bit fussy.
rep_t quotient, quotientLo;
wideMultiply(aSignificand << 2, reciprocal, &quotient, &quotientLo);
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
// In either case, we are going to compute a residual of the form
//
@ -141,7 +141,7 @@ __divdf3(fp_t a, fp_t b) {
// We know from the construction of q that r satisfies:
//
// 0 <= r < ulp(q)*b
//
//
// if r is greater than 1/2 ulp(q)*b, then q rounds up. Otherwise, we
// already have the correct result. The exact halfway case cannot occur.
// We also take this time to right shift quotient if it falls in the [1,2)
@ -154,20 +154,20 @@ __divdf3(fp_t a, fp_t b) {
quotient >>= 1;
residual = (aSignificand << 52) - quotient * bSignificand;
}
const int writtenExponent = quotientExponent + exponentBias;
if (writtenExponent >= maxExponent) {
// If we have overflowed the exponent, return infinity.
return fromRep(infRep | quotientSign);
}
else if (writtenExponent < 1) {
// Flush denormals to zero. In the future, it would be nice to add
// code to round them correctly.
return fromRep(quotientSign);
}
else {
const bool round = (residual << 1) > bSignificand;
// Clear the implicit bit

View File

@ -12,6 +12,8 @@
*===----------------------------------------------------------------------===
*/
#define SINGLE_PRECISION
#include "fp_lib.h"
#include "int_lib.h"
#include "int_math.h"
@ -21,7 +23,8 @@ COMPILER_RT_ABI Fcomplex
__divsc3(float __a, float __b, float __c, float __d)
{
int __ilogbw = 0;
float __logbw = crt_logbf(crt_fmaxf(crt_fabsf(__c), crt_fabsf(__d)));
float __logbw =
__compiler_rt_logbf(crt_fmaxf(crt_fabsf(__c), crt_fabsf(__d)));
if (crt_isfinite(__logbw))
{
__ilogbw = (int)__logbw;

View File

@ -21,36 +21,36 @@
COMPILER_RT_ABI fp_t
__divsf3(fp_t a, fp_t b) {
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
const rep_t quotientSign = (toRep(a) ^ toRep(b)) & signBit;
rep_t aSignificand = toRep(a) & significandMask;
rep_t bSignificand = toRep(b) & significandMask;
int scale = 0;
// Detect if a or b is zero, denormal, infinity, or NaN.
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
const rep_t aAbs = toRep(a) & absMask;
const rep_t bAbs = toRep(b) & absMask;
// NaN / anything = qNaN
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
// anything / NaN = qNaN
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
if (aAbs == infRep) {
// infinity / infinity = NaN
if (bAbs == infRep) return fromRep(qnanRep);
// infinity / anything else = +/- infinity
else return fromRep(aAbs | quotientSign);
}
// anything else / infinity = +/- 0
if (bAbs == infRep) return fromRep(quotientSign);
if (!aAbs) {
// zero / zero = NaN
if (!bAbs) return fromRep(qnanRep);
@ -59,28 +59,28 @@ __divsf3(fp_t a, fp_t b) {
}
// anything else / zero = +/- infinity
if (!bAbs) return fromRep(infRep | quotientSign);
// one or both of a or b is denormal, the other (if applicable) is a
// normal number. Renormalize one or both of a and b, and set scale to
// include the necessary exponent adjustment.
if (aAbs < implicitBit) scale += normalize(&aSignificand);
if (bAbs < implicitBit) scale -= normalize(&bSignificand);
}
// Or in the implicit significand bit. (If we fell through from the
// denormal path it was already set by normalize( ), but setting it twice
// won't hurt anything.)
aSignificand |= implicitBit;
bSignificand |= implicitBit;
int quotientExponent = aExponent - bExponent + scale;
// Align the significand of b as a Q31 fixed-point number in the range
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
// is accurate to about 3.5 binary digits.
uint32_t q31b = bSignificand << 8;
uint32_t reciprocal = UINT32_C(0x7504f333) - q31b;
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
//
// x1 = x0 * (2 - x0 * b)
@ -95,7 +95,7 @@ __divsf3(fp_t a, fp_t b) {
reciprocal = (uint64_t)reciprocal * correction >> 31;
correction = -((uint64_t)reciprocal * q31b >> 32);
reciprocal = (uint64_t)reciprocal * correction >> 31;
// Exhaustive testing shows that the error in reciprocal after three steps
// is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our
// expectations. We bump the reciprocal by a tiny value to force the error
@ -103,7 +103,7 @@ __divsf3(fp_t a, fp_t b) {
// be specific). This also causes 1/1 to give a sensible approximation
// instead of zero (due to overflow).
reciprocal -= 2;
// The numerical reciprocal is accurate to within 2^-28, lies in the
// interval [0x1.000000eep-1, 0x1.fffffffcp-1], and is strictly smaller
// than the true reciprocal of b. Multiplying a by this reciprocal thus
@ -115,9 +115,9 @@ __divsf3(fp_t a, fp_t b) {
// from the fact that we truncate the product, and the 2^27 term
// is the error in the reciprocal of b scaled by the maximum
// possible value of a. As a consequence of this error bound,
// either q or nextafter(q) is the correctly rounded
// either q or nextafter(q) is the correctly rounded
rep_t quotient = (uint64_t)reciprocal*(aSignificand << 1) >> 32;
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
// In either case, we are going to compute a residual of the form
//
@ -126,7 +126,7 @@ __divsf3(fp_t a, fp_t b) {
// We know from the construction of q that r satisfies:
//
// 0 <= r < ulp(q)*b
//
//
// if r is greater than 1/2 ulp(q)*b, then q rounds up. Otherwise, we
// already have the correct result. The exact halfway case cannot occur.
// We also take this time to right shift quotient if it falls in the [1,2)
@ -141,18 +141,18 @@ __divsf3(fp_t a, fp_t b) {
}
const int writtenExponent = quotientExponent + exponentBias;
if (writtenExponent >= maxExponent) {
// If we have overflowed the exponent, return infinity.
return fromRep(infRep | quotientSign);
}
else if (writtenExponent < 1) {
// Flush denormals to zero. In the future, it would be nice to add
// code to round them correctly.
return fromRep(quotientSign);
}
else {
const bool round = (residual << 1) > bSignificand;
// Clear the implicit bit

View File

@ -12,6 +12,8 @@
*===----------------------------------------------------------------------===
*/
#define QUAD_PRECISION
#include "fp_lib.h"
#include "int_lib.h"
#include "int_math.h"
@ -21,7 +23,8 @@ COMPILER_RT_ABI Lcomplex
__divtc3(long double __a, long double __b, long double __c, long double __d)
{
int __ilogbw = 0;
long double __logbw = crt_logbl(crt_fmaxl(crt_fabsl(__c), crt_fabsl(__d)));
long double __logbw =
__compiler_rt_logbl(crt_fmaxl(crt_fabsl(__c), crt_fabsl(__d)));
if (crt_isfinite(__logbw))
{
__ilogbw = (int)__logbw;

View File

@ -42,6 +42,7 @@ static void emutls_shutdown(emutls_address_array *array);
static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t emutls_pthread_key;
static bool emutls_key_created = false;
typedef unsigned int gcc_word __attribute__((mode(word)));
typedef unsigned int gcc_pointer __attribute__((mode(pointer)));
@ -109,6 +110,7 @@ static void emutls_key_destructor(void* ptr) {
static __inline void emutls_init(void) {
if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0)
abort();
emutls_key_created = true;
}
static __inline void emutls_init_once(void) {
@ -390,3 +392,14 @@ void* __emutls_get_address(__emutls_control* control) {
array->data[index] = emutls_allocate_object(control);
return array->data[index];
}
#ifdef __BIONIC__
/* Called by Bionic on dlclose to delete the emutls pthread key. */
__attribute__((visibility("hidden")))
void __emutls_unregister_key(void) {
if (emutls_key_created) {
pthread_key_delete(emutls_pthread_key);
emutls_key_created = false;
}
}
#endif

View File

@ -25,6 +25,7 @@
#include <stdbool.h>
#include <limits.h>
#include "int_lib.h"
#include "int_math.h"
// x86_64 FreeBSD prior v9.3 define fixed-width types incorrectly in
// 32-bit mode.
@ -265,6 +266,62 @@ static __inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo, unsigned int
*hi = 0;
}
}
// Implements logb methods (logb, logbf, logbl) for IEEE-754. This avoids
// pulling in a libm dependency from compiler-rt, but is not meant to replace
// it (i.e. code calling logb() should get the one from libm, not this), hence
// the __compiler_rt prefix.
static __inline fp_t __compiler_rt_logbX(fp_t x) {
rep_t rep = toRep(x);
int exp = (rep & exponentMask) >> significandBits;
// Abnormal cases:
// 1) +/- inf returns +inf; NaN returns NaN
// 2) 0.0 returns -inf
if (exp == maxExponent) {
if (((rep & signBit) == 0) || (x != x)) {
return x; // NaN or +inf: return x
} else {
return -x; // -inf: return -x
}
} else if (x == 0.0) {
// 0.0: return -inf
return fromRep(infRep | signBit);
}
if (exp != 0) {
// Normal number
return exp - exponentBias; // Unbias exponent
} else {
// Subnormal number; normalize and repeat
rep &= absMask;
const int shift = 1 - normalize(&rep);
exp = (rep & exponentMask) >> significandBits;
return exp - exponentBias - shift; // Unbias exponent
}
}
#endif
#if defined(SINGLE_PRECISION)
static __inline fp_t __compiler_rt_logbf(fp_t x) {
return __compiler_rt_logbX(x);
}
#elif defined(DOUBLE_PRECISION)
static __inline fp_t __compiler_rt_logb(fp_t x) {
return __compiler_rt_logbX(x);
}
#elif defined(QUAD_PRECISION)
#if defined(CRT_LDBL_128BIT)
static __inline fp_t __compiler_rt_logbl(fp_t x) {
return __compiler_rt_logbX(x);
}
#else
// The generic implementation only works for ieee754 floating point. For other
// floating point types, continue to rely on the libm implementation for now.
static __inline long double __compiler_rt_logbl(long double x) {
return crt_logbl(x);
}
#endif
#endif
#endif // FP_LIB_HEADER

View File

@ -206,8 +206,8 @@ __gcc_personality_v0(int version, _Unwind_Action actions,
if ( lsda == (uint8_t*) 0 )
return continueUnwind(exceptionObject, context);
uintptr_t pc = _Unwind_GetIP(context)-1;
uintptr_t funcStart = _Unwind_GetRegionStart(context);
uintptr_t pc = (uintptr_t)_Unwind_GetIP(context)-1;
uintptr_t funcStart = (uintptr_t)_Unwind_GetRegionStart(context);
uintptr_t pcOffset = pc - funcStart;
/* Parse LSDA header. */
@ -249,4 +249,3 @@ __gcc_personality_v0(int version, _Unwind_Action actions,
/* No landing pad found, continue unwinding. */
return continueUnwind(exceptionObject, context);
}

View File

@ -43,7 +43,7 @@
#define AEABI_RTABI __attribute__((__pcs__("aapcs")))
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
#define ALWAYS_INLINE __forceinline
#define NOINLINE __declspec(noinline)
#define NORETURN __declspec(noreturn)

View File

@ -92,12 +92,8 @@
#endif
#if defined(_MSC_VER) && !defined(__clang__)
#define crt_logb(x) logb((x))
#define crt_logbf(x) logbf((x))
#define crt_logbl(x) logbl((x))
#else
#define crt_logb(x) __builtin_logb((x))
#define crt_logbf(x) __builtin_logbf((x))
#define crt_logbl(x) __builtin_logbl((x))
#endif

View File

@ -60,10 +60,19 @@ typedef union
}s;
} udwords;
#if (defined(__LP64__) || defined(__wasm__) || defined(__mips64)) || defined(__riscv)
#if defined(__LP64__) || defined(__wasm__) || defined(__mips64) || \
defined(__riscv) || defined(_WIN64)
#define CRT_HAS_128BIT
#endif
/* MSVC doesn't have a working 128bit integer type. Users should really compile
* compiler-rt with clang, but if they happen to be doing a standalone build for
* asan or something else, disable the 128 bit parts so things sort of work.
*/
#if defined(_MSC_VER) && !defined(__clang__)
#undef CRT_HAS_128BIT
#endif
#ifdef CRT_HAS_128BIT
typedef int ti_int __attribute__ ((mode (TI)));
typedef unsigned tu_int __attribute__ ((mode (TI)));
@ -137,6 +146,18 @@ typedef struct
#endif /* _YUGA_LITTLE_ENDIAN */
} uqwords;
/* Check if the target supports 80 bit extended precision long doubles.
* Notably, on x86 Windows, MSVC only provides a 64-bit long double, but GCC
* still makes it 80 bits. Clang will match whatever compiler it is trying to
* be compatible with.
*/
#if ((defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)) || \
defined(__m68k__) || defined(__ia64__)
#define HAS_80_BIT_LONG_DOUBLE 1
#else
#define HAS_80_BIT_LONG_DOUBLE 0
#endif
typedef union
{
uqwords u;

View File

@ -27,7 +27,7 @@ NORETURN extern void panic(const char *, ...);
#ifndef _WIN32
__attribute__((visibility("hidden")))
#endif
void compilerrt_abort_impl(const char *file, int line, const char *function) {
void __compilerrt_abort_impl(const char *file, int line, const char *function) {
panic("%s:%d: abort in %s", file, line, function);
}
@ -41,7 +41,7 @@ NORETURN extern void __assert_rtn(const char *func, const char *file, int line,
__attribute__((weak))
__attribute__((visibility("hidden")))
#endif
void compilerrt_abort_impl(const char *file, int line, const char *function) {
void __compilerrt_abort_impl(const char *file, int line, const char *function) {
__assert_rtn(function, file, line, "libcompiler_rt abort");
}
@ -51,7 +51,7 @@ void compilerrt_abort_impl(const char *file, int line, const char *function) {
__attribute__((weak))
__attribute__((visibility("hidden")))
#endif
void compilerrt_abort_impl(const char *file, int line, const char *function) {
void __compilerrt_abort_impl(const char *file, int line, const char *function) {
__builtin_trap();
}
@ -64,7 +64,7 @@ void compilerrt_abort_impl(const char *file, int line, const char *function) {
__attribute__((weak))
__attribute__((visibility("hidden")))
#endif
void compilerrt_abort_impl(const char *file, int line, const char *function) {
void __compilerrt_abort_impl(const char *file, int line, const char *function) {
abort();
}

View File

@ -20,10 +20,10 @@
#define INT_UTIL_H
/** \brief Trigger a program abort (or panic for kernel code). */
#define compilerrt_abort() compilerrt_abort_impl(__FILE__, __LINE__, __func__)
#define compilerrt_abort() __compilerrt_abort_impl(__FILE__, __LINE__, __func__)
NORETURN void compilerrt_abort_impl(const char *file, int line,
const char *function);
NORETURN void __compilerrt_abort_impl(const char *file, int line,
const char *function);
#define COMPILE_TIME_ASSERT(expr) COMPILE_TIME_ASSERT1(expr, __COUNTER__)
#define COMPILE_TIME_ASSERT1(expr, cnt) COMPILE_TIME_ASSERT2(expr, cnt)

View File

@ -15,7 +15,6 @@
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#include <TargetConditionals.h>
#include <dispatch/dispatch.h>
#include <dlfcn.h>
@ -28,6 +27,33 @@
static int32_t GlobalMajor, GlobalMinor, GlobalSubminor;
static dispatch_once_t DispatchOnceCounter;
/* We can't include <CoreFoundation/CoreFoundation.h> directly from here, so
* just forward declare everything that we need from it. */
typedef const void *CFDataRef, *CFAllocatorRef, *CFPropertyListRef,
*CFStringRef, *CFDictionaryRef, *CFTypeRef, *CFErrorRef;
#if __LLP64__
typedef unsigned long long CFTypeID;
typedef unsigned long long CFOptionFlags;
typedef signed long long CFIndex;
#else
typedef unsigned long CFTypeID;
typedef unsigned long CFOptionFlags;
typedef signed long CFIndex;
#endif
typedef unsigned char UInt8;
typedef _Bool Boolean;
typedef CFIndex CFPropertyListFormat;
typedef uint32_t CFStringEncoding;
/* kCFStringEncodingASCII analog. */
#define CF_STRING_ENCODING_ASCII 0x0600
/* kCFStringEncodingUTF8 analog. */
#define CF_STRING_ENCODING_UTF8 0x08000100
#define CF_PROPERTY_LIST_IMMUTABLE 0
typedef CFDataRef (*CFDataCreateWithBytesNoCopyFuncTy)(CFAllocatorRef,
const UInt8 *, CFIndex,
CFAllocatorRef);
@ -55,8 +81,7 @@ static void parseSystemVersionPList(void *Unused) {
const void *NullAllocator = dlsym(RTLD_DEFAULT, "kCFAllocatorNull");
if (!NullAllocator)
return;
const CFAllocatorRef kCFAllocatorNull =
*(const CFAllocatorRef *)NullAllocator;
const CFAllocatorRef AllocatorNull = *(const CFAllocatorRef *)NullAllocator;
CFDataCreateWithBytesNoCopyFuncTy CFDataCreateWithBytesNoCopyFunc =
(CFDataCreateWithBytesNoCopyFuncTy)dlsym(RTLD_DEFAULT,
"CFDataCreateWithBytesNoCopy");
@ -140,21 +165,21 @@ static void parseSystemVersionPList(void *Unused) {
/* Get the file buffer into CF's format. We pass in a null allocator here *
* because we free PListBuf ourselves */
FileContentsRef = (*CFDataCreateWithBytesNoCopyFunc)(
NULL, PListBuf, (CFIndex)NumRead, kCFAllocatorNull);
NULL, PListBuf, (CFIndex)NumRead, AllocatorNull);
if (!FileContentsRef)
goto Fail;
if (CFPropertyListCreateWithDataFunc)
PListRef = (*CFPropertyListCreateWithDataFunc)(
NULL, FileContentsRef, kCFPropertyListImmutable, NULL, NULL);
NULL, FileContentsRef, CF_PROPERTY_LIST_IMMUTABLE, NULL, NULL);
else
PListRef = (*CFPropertyListCreateFromXMLDataFunc)(
NULL, FileContentsRef, kCFPropertyListImmutable, NULL);
NULL, FileContentsRef, CF_PROPERTY_LIST_IMMUTABLE, NULL);
if (!PListRef)
goto Fail;
CFStringRef ProductVersion = (*CFStringCreateWithCStringNoCopyFunc)(
NULL, "ProductVersion", kCFStringEncodingASCII, kCFAllocatorNull);
NULL, "ProductVersion", CF_STRING_ENCODING_ASCII, AllocatorNull);
if (!ProductVersion)
goto Fail;
CFTypeRef OpaqueValue = (*CFDictionaryGetValueFunc)(PListRef, ProductVersion);
@ -165,7 +190,7 @@ static void parseSystemVersionPList(void *Unused) {
char VersionStr[32];
if (!(*CFStringGetCStringFunc)((CFStringRef)OpaqueValue, VersionStr,
sizeof(VersionStr), kCFStringEncodingUTF8))
sizeof(VersionStr), CF_STRING_ENCODING_UTF8))
goto Fail;
sscanf(VersionStr, "%d.%d.%d", &GlobalMajor, &GlobalMinor, &GlobalSubminor);

View File

@ -4,6 +4,11 @@
#include "DD.h"
#include "../int_math.h"
// Use DOUBLE_PRECISION because the soft-fp method we use is logb (on the upper
// half of the long doubles), even though this file defines complex division for
// 128-bit floats.
#define DOUBLE_PRECISION
#include "../fp_lib.h"
#if !defined(CRT_INFINITY) && defined(HUGE_VAL)
#define CRT_INFINITY HUGE_VAL
@ -21,9 +26,10 @@ __divtc3(long double a, long double b, long double c, long double d)
DD dDD = { .ld = d };
int ilogbw = 0;
const double logbw = crt_logb(crt_fmax(crt_fabs(cDD.s.hi), crt_fabs(dDD.s.hi) ));
if (crt_isfinite(logbw))
const double logbw = __compiler_rt_logb(
crt_fmax(crt_fabs(cDD.s.hi), crt_fabs(dDD.s.hi)));
if (crt_isfinite(logbw))
{
ilogbw = (int)logbw;

View File

@ -0,0 +1,106 @@
//===-- lib/builtins/ppc/fixunstfti.c - Convert long double->int128 *-C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements converting the 128bit IBM/PowerPC long double (double-
// double) data type to an unsigned 128 bit integer.
//
//===----------------------------------------------------------------------===//
#include "../int_math.h"
#define BIAS 1023
/* Convert long double into an unsigned 128-bit integer. */
__uint128_t __fixunstfti(long double input) {
/* If we are trying to convert a NaN, return the NaN bit pattern. */
if (crt_isnan(input)) {
return ((__uint128_t)0x7FF8000000000000ll) << 64 |
(__uint128_t)0x0000000000000000ll;
}
__uint128_t result, hiResult, loResult;
int hiExponent, loExponent, shift;
/* The long double representation, with the high and low portions of
* the long double, and the corresponding bit patterns of each double. */
union {
long double ld;
double d[2]; /* [0] is the high double, [1] is the low double. */
unsigned long long ull[2]; /* High and low doubles as 64-bit integers. */
} ldUnion;
/* If the long double is less than 1.0 or negative,
* return 0.0. */
if (input < 1.0)
return 0.0;
/* Retrieve the 64-bit patterns of high and low doubles.
* Compute the unbiased exponent of both high and low doubles by
* removing the signs, isolating the exponent, and subtracting
* the bias from it. */
ldUnion.ld = input;
hiExponent = ((ldUnion.ull[0] & 0x7FFFFFFFFFFFFFFFll) >> 52) - BIAS;
loExponent = ((ldUnion.ull[1] & 0x7FFFFFFFFFFFFFFFll) >> 52) - BIAS;
/* Convert each double into int64; they will be added to the int128 result.
* CASE 1: High or low double fits in int64
* - Convert the each double normally into int64.
*
* CASE 2: High or low double does not fit in int64
* - Scale the double to fit within a 64-bit integer
* - Calculate the shift (amount to scale the double by in the int128)
* - Clear all the bits of the exponent (with 0x800FFFFFFFFFFFFF)
* - Add BIAS+53 (0x4350000000000000) to exponent to correct the value
* - Scale (move) the double to the correct place in the int128
* (Move it by 2^53 places)
*
* Note: If the high double is assumed to be positive, an unsigned conversion
* from long double to 64-bit integer is needed. The low double can be either
* positive or negative, so a signed conversion is needed to retain the result
* of the low double and to ensure it does not simply get converted to 0. */
/* CASE 1 - High double fits in int64. */
if (hiExponent < 63) {
hiResult = (unsigned long long)ldUnion.d[0];
} else if (hiExponent < 128) {
/* CASE 2 - High double does not fit in int64, scale and convert it. */
shift = hiExponent - 54;
ldUnion.ull[0] &= 0x800FFFFFFFFFFFFFll;
ldUnion.ull[0] |= 0x4350000000000000ll;
hiResult = (unsigned long long)ldUnion.d[0];
hiResult <<= shift;
} else {
/* Detect cases for overflow. When the exponent of the high
* double is greater than 128 bits and when the long double
* input is positive, return the max 128-bit integer.
* For negative inputs with exponents > 128, return 1, like gcc. */
if (ldUnion.d[0] > 0) {
return ((__uint128_t)0xFFFFFFFFFFFFFFFFll) << 64 |
(__uint128_t)0xFFFFFFFFFFFFFFFFll;
} else {
return ((__uint128_t)0x0000000000000000ll) << 64 |
(__uint128_t)0x0000000000000001ll;
}
}
/* CASE 1 - Low double fits in int64. */
if (loExponent < 63) {
loResult = (long long)ldUnion.d[1];
} else {
/* CASE 2 - Low double does not fit in int64, scale and convert it. */
shift = loExponent - 54;
ldUnion.ull[1] &= 0x800FFFFFFFFFFFFFll;
ldUnion.ull[1] |= 0x4350000000000000ll;
loResult = (long long)ldUnion.d[1];
loResult <<= shift;
}
/* Add the high and low doublewords together to form a 128 bit integer. */
result = loResult + hiResult;
return result;
}

View File

@ -0,0 +1,48 @@
//===-- lib/builtins/ppc/floattitf.c - Convert int128->long double -*-C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements converting a signed 128 bit integer to a 128bit IBM /
// PowerPC long double (double-double) value.
//
//===----------------------------------------------------------------------===//
#include <stdint.h>
/* Conversions from signed and unsigned 64-bit int to long double. */
long double __floatditf(int64_t);
long double __floatunditf(uint64_t);
/* Convert a signed 128-bit integer to long double.
* This uses the following property: Let hi and lo be 64-bits each,
* and let signed_val_k() and unsigned_val_k() be the value of the
* argument interpreted as a signed or unsigned k-bit integer. Then,
*
* signed_val_128(hi,lo) = signed_val_64(hi) * 2^64 + unsigned_val_64(lo)
* = (long double)hi * 2^64 + (long double)lo,
*
* where (long double)hi and (long double)lo are signed and
* unsigned 64-bit integer to long double conversions, respectively.
*/
long double __floattitf(__int128_t arg) {
/* Split the int128 argument into 64-bit high and low int64 parts. */
int64_t ArgHiPart = (int64_t)(arg >> 64);
uint64_t ArgLoPart = (uint64_t)arg;
/* Convert each 64-bit part into long double. The high part
* must be a signed conversion and the low part an unsigned conversion
* to ensure the correct result. */
long double ConvertedHiPart = __floatditf(ArgHiPart);
long double ConvertedLoPart = __floatunditf(ArgLoPart);
/* The low bit of ArgHiPart corresponds to the 2^64 bit in arg.
* Multiply the high part by 2^64 to undo the right shift by 64-bits
* done in the splitting. Then, add to the low part to obtain the
* final result. */
return ((ConvertedHiPart * 0x1.0p64) + ConvertedLoPart);
}

View File

@ -1,6 +1,6 @@
add_compiler_rt_component(cfi)
if(OS_NAME MATCHES "Linux")
if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetBSD")
set(CFI_SOURCES cfi.cc)
include_directories(..)

View File

@ -13,15 +13,33 @@
#include <assert.h>
#include <elf.h>
#include "sanitizer_common/sanitizer_common.h"
#if SANITIZER_FREEBSD
#include <sys/link_elf.h>
#endif
#include <link.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#if SANITIZER_LINUX
typedef ElfW(Phdr) Elf_Phdr;
typedef ElfW(Ehdr) Elf_Ehdr;
typedef ElfW(Addr) Elf_Addr;
typedef ElfW(Sym) Elf_Sym;
typedef ElfW(Dyn) Elf_Dyn;
#elif SANITIZER_FREEBSD
#if SANITIZER_WORDSIZE == 64
#define ElfW64_Dyn Elf_Dyn
#define ElfW64_Sym Elf_Sym
#else
#define ElfW32_Dyn Elf_Dyn
#define ElfW32_Sym Elf_Sym
#endif
#endif
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flag_parser.h"
#include "ubsan/ubsan_init.h"
#include "ubsan/ubsan_flags.h"
@ -154,15 +172,25 @@ void ShadowBuilder::Add(uptr begin, uptr end, uptr cfi_check) {
*s = sv;
}
#if SANITIZER_LINUX
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD
void ShadowBuilder::Install() {
MprotectReadOnly(shadow_, GetShadowSize());
uptr main_shadow = GetShadow();
if (main_shadow) {
// Update.
#if SANITIZER_LINUX
void *res = mremap((void *)shadow_, GetShadowSize(), GetShadowSize(),
MREMAP_MAYMOVE | MREMAP_FIXED, (void *)main_shadow);
CHECK(res != MAP_FAILED);
#elif SANITIZER_NETBSD
void *res = mremap((void *)shadow_, GetShadowSize(), (void *)main_shadow,
GetShadowSize(), MAP_FIXED);
CHECK(res != MAP_FAILED);
#else
void *res = MmapFixedOrDie(shadow_, GetShadowSize());
CHECK(res != MAP_FAILED);
::memcpy(&shadow_, &main_shadow, GetShadowSize());
#endif
} else {
// Initial setup.
CHECK_EQ(kCfiShadowLimitsStorageSize, GetPageSizeCached());
@ -183,17 +211,17 @@ void ShadowBuilder::Install() {
// dlopen(RTLD_NOLOAD | RTLD_LAZY)
// dlsym("__cfi_check").
uptr find_cfi_check_in_dso(dl_phdr_info *info) {
const ElfW(Dyn) *dynamic = nullptr;
const Elf_Dyn *dynamic = nullptr;
for (int i = 0; i < info->dlpi_phnum; ++i) {
if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
dynamic =
(const ElfW(Dyn) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
(const Elf_Dyn *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
break;
}
}
if (!dynamic) return 0;
uptr strtab = 0, symtab = 0, strsz = 0;
for (const ElfW(Dyn) *p = dynamic; p->d_tag != PT_NULL; ++p) {
for (const Elf_Dyn *p = dynamic; p->d_tag != PT_NULL; ++p) {
if (p->d_tag == DT_SYMTAB)
symtab = p->d_un.d_ptr;
else if (p->d_tag == DT_STRTAB)
@ -227,7 +255,7 @@ uptr find_cfi_check_in_dso(dl_phdr_info *info) {
return 0;
}
for (const ElfW(Sym) *p = (const ElfW(Sym) *)symtab; (ElfW(Addr))p < strtab;
for (const Elf_Sym *p = (const Elf_Sym *)symtab; (Elf_Addr)p < strtab;
++p) {
// There is no reliable way to find the end of the symbol table. In
// lld-produces files, there are other sections between symtab and strtab.

View File

@ -1,13 +1,11 @@
[cfi-unrelated-cast]
# The specification of std::get_temporary_buffer mandates a cast to
# uninitialized T* (libstdc++, libc++, MSVC stdlib).
# uninitialized T* (libstdc++, MSVC stdlib).
fun:_ZSt20get_temporary_buffer*
fun:_ZNSt3__120get_temporary_buffer*
fun:*get_temporary_buffer@.*@std@@*
# STL address-of magic (libstdc++, libc++).
# STL address-of magic (libstdc++).
fun:*__addressof*
fun:_ZNSt3__19addressof*
# Windows C++ stdlib headers that contain bad unrelated casts.
src:*xmemory0

View File

@ -423,7 +423,7 @@ static void dfsan_fini() {
static void dfsan_init(int argc, char **argv, char **envp) {
InitializeFlags();
InitializePlatformEarly();
::InitializePlatformEarly();
if (!MmapFixedNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr()))
Die();

View File

@ -14,6 +14,7 @@ set(ESAN_SOURCES
esan_interceptors.cpp
esan_linux.cpp
esan_sideline_linux.cpp
esan_sideline_bsd.cpp
cache_frag.cpp
working_set.cpp
working_set_posix.cpp)

View File

@ -327,7 +327,7 @@ INTERCEPTOR(int, rmdir, char *path) {
// Signal-related interceptors
//===----------------------------------------------------------------------===//
#if SANITIZER_LINUX
#if SANITIZER_LINUX || SANITIZER_FREEBSD
typedef void (*signal_handler_t)(int);
INTERCEPTOR(signal_handler_t, signal, int signum, signal_handler_t handler) {
void *ctx;
@ -344,7 +344,7 @@ INTERCEPTOR(signal_handler_t, signal, int signum, signal_handler_t handler) {
#define ESAN_MAYBE_INTERCEPT_SIGNAL
#endif
#if SANITIZER_LINUX
#if SANITIZER_LINUX || SANITIZER_FREEBSD
DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
struct sigaction *oldact)
INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
@ -363,7 +363,11 @@ int real_sigaction(int signum, const void *act, void *oldact) {
if (REAL(sigaction) == nullptr) {
// With an instrumented allocator, this is called during interceptor init
// and we need a raw syscall solution.
#if SANITIZER_LINUX
return internal_sigaction_syscall(signum, act, oldact);
#else
return internal_sigaction(signum, act, oldact);
#endif
}
return REAL(sigaction)(signum, (const struct sigaction *)act,
(struct sigaction *)oldact);
@ -376,7 +380,7 @@ int real_sigaction(int signum, const void *act, void *oldact) {
#define ESAN_MAYBE_INTERCEPT_SIGACTION
#endif
#if SANITIZER_LINUX
#if SANITIZER_LINUX || SANITIZER_FREEBSD
INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
__sanitizer_sigset_t *oldset) {
void *ctx;

View File

@ -30,7 +30,7 @@ struct ApplicationRegion {
bool ShadowMergedWithPrev;
};
#if SANITIZER_LINUX && defined(__x86_64__)
#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && defined(__x86_64__)
// Linux x86_64
//
// Application memory falls into these 5 regions (ignoring the corner case

View File

@ -17,6 +17,7 @@
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_platform_limits_freebsd.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
namespace __esan {

View File

@ -0,0 +1,35 @@
//===-- esan_sideline_bsd.cpp -----------------------------------*- 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 EfficiencySanitizer, a family of performance tuners.
//
// Support for a separate or "sideline" tool thread on FreeBSD.
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_FREEBSD
#include "esan_sideline.h"
namespace __esan {
static SidelineThread *TheThread;
bool SidelineThread::launchThread(SidelineFunc takeSample, void *Arg,
u32 FreqMilliSec) {
return true;
}
bool SidelineThread::joinThread() {
return true;
}
} // namespace __esan
#endif // SANITIZER_FREEBSD

View File

@ -3,8 +3,8 @@ set(LIBFUZZER_SOURCES
FuzzerDataFlowTrace.cpp
FuzzerDriver.cpp
FuzzerExtFunctionsDlsym.cpp
FuzzerExtFunctionsDlsymWin.cpp
FuzzerExtFunctionsWeak.cpp
FuzzerExtFunctionsWindows.cpp
FuzzerExtraCounters.cpp
FuzzerIO.cpp
FuzzerIOPosix.cpp
@ -25,6 +25,8 @@ set(LIBFUZZER_SOURCES
FuzzerUtilWindows.cpp)
set(LIBFUZZER_HEADERS
FuzzerBuiltins.h
FuzzerBuiltinsMsvc.h
FuzzerCommand.h
FuzzerCorpus.h
FuzzerDataFlowTrace.h
@ -124,12 +126,12 @@ if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH)
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_ABI_VERSION=Fuzzer
-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)

View File

@ -0,0 +1,36 @@
//===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Wrapper functions and marcos around builtin functions.
//===----------------------------------------------------------------------===//
#ifndef LLVM_FUZZER_BUILTINS_H
#define LLVM_FUZZER_BUILTINS_H
#include "FuzzerDefs.h"
#if !LIBFUZZER_MSVC
#include <cstdint>
#define GET_CALLER_PC() __builtin_return_address(0)
namespace fuzzer {
inline uint8_t Bswap(uint8_t x) { return x; }
inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); }
inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); }
inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); }
inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); }
inline uint32_t Clz(unsigned long long X) { return __builtin_clz(X); }
inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); }
} // namespace fuzzer
#endif // !LIBFUZZER_MSVC
#endif // LLVM_FUZZER_BUILTINS_H

View File

@ -0,0 +1,59 @@
//===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Wrapper functions and marcos that use intrinsics instead of builtin functions
// which cannot be compiled by MSVC.
//===----------------------------------------------------------------------===//
#ifndef LLVM_FUZZER_BUILTINS_MSVC_H
#define LLVM_FUZZER_BUILTINS_MSVC_H
#include "FuzzerDefs.h"
#if LIBFUZZER_MSVC
#if !defined(_M_ARM) && !defined(_M_X64)
#error "_BitScanReverse64 unavailable on this platform so MSVC is unsupported."
#endif
#include <intrin.h>
#include <cstdint>
#include <cstdlib>
// __builtin_return_address() cannot be compiled with MSVC. Use the equivalent
// from <intrin.h>
#define GET_CALLER_PC() reinterpret_cast<uintptr_t>(_ReturnAddress())
namespace fuzzer {
inline uint8_t Bswap(uint8_t x) { return x; }
// Use alternatives to __builtin functions from <stdlib.h> and <intrin.h> on
// Windows since the builtins are not supported by MSVC.
inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); }
inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); }
inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); }
// The functions below were mostly copied from
// compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used
// outside of Windows.
inline uint32_t Clzll(uint64_t X) {
unsigned long LeadZeroIdx = 0;
if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx;
return 64;
}
inline uint32_t Clz(uint32_t X) {
unsigned long LeadZeroIdx = 0;
if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx;
return 32;
}
inline int Popcountll(unsigned long long X) { return __popcnt64(X); }
} // namespace fuzzer
#endif // LIBFUZER_MSVC
#endif // LLVM_FUZZER_BUILTINS_MSVC_H

View File

@ -81,7 +81,7 @@ public:
}
// Like hasArgument, but checks for "-[Flag]=...".
bool hasFlag(const std::string &Flag) {
bool hasFlag(const std::string &Flag) const {
std::string Arg("-" + Flag + "=");
auto IsMatch = [&](const std::string &Other) {
return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
@ -92,7 +92,7 @@ public:
// Returns the value of the first instance of a given flag, or an empty string
// if the flag isn't present. Ignores any occurrences after
// "-ignore_remaining_args=1", if present.
std::string getFlagValue(const std::string &Flag) {
std::string getFlagValue(const std::string &Flag) const {
std::string Arg("-" + Flag + "=");
auto IsMatch = [&](const std::string &Other) {
return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;

View File

@ -238,12 +238,6 @@ class InputCorpus {
return false;
}
bool IsFeatureNew(size_t Idx, uint32_t NewSize, bool Shrink) {
assert(NewSize);
uint32_t OldSize = GetFeature(Idx % kFeatureSetSize);
return OldSize == 0 || (Shrink && OldSize > NewSize);
}
size_t NumFeatures() const { return NumAddedFeatures; }
size_t NumFeatureUpdates() const { return NumUpdatedFeatures; }

View File

@ -82,6 +82,13 @@
#error "Support for your platform has not been implemented"
#endif
#if defined(_MSC_VER) && !defined(__clang__)
// MSVC compiler is being used.
#define LIBFUZZER_MSVC 1
#else
#define LIBFUZZER_MSVC 0
#endif
#ifndef __has_attribute
# define __has_attribute(x) 0
#endif
@ -129,8 +136,15 @@
#if LIBFUZZER_WINDOWS
#define ATTRIBUTE_INTERFACE __declspec(dllexport)
// This is used for __sancov_lowest_stack which is needed for
// -fsanitize-coverage=stack-depth. That feature is not yet available on
// Windows, so make the symbol static to avoid linking errors.
#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \
__attribute__((tls_model("initial-exec"))) thread_local static
#else
#define ATTRIBUTE_INTERFACE __attribute__((visibility("default")))
#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \
ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec"))) thread_local
#endif
namespace fuzzer {
@ -176,11 +190,6 @@ typedef int (*UserCallback)(const uint8_t *Data, size_t Size);
int FuzzerDriver(int *argc, char ***argv, UserCallback Callback);
inline uint8_t Bswap(uint8_t x) { return x; }
inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); }
inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); }
inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); }
uint8_t *ExtraCountersBegin();
uint8_t *ExtraCountersEnd();
void ClearExtraCounters();

View File

@ -615,13 +615,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
Options.PrintNewCovPcs = Flags.print_pcs;
Options.PrintNewCovFuncs = Flags.print_funcs;
Options.PrintFinalStats = Flags.print_final_stats;
Options.PrintMutationStats = Flags.print_mutation_stats;
Options.PrintCorpusStats = Flags.print_corpus_stats;
Options.PrintCoverage = Flags.print_coverage;
Options.PrintUnstableStats = Flags.print_unstable_stats;
if (Flags.handle_unstable == TracePC::MinUnstable ||
Flags.handle_unstable == TracePC::ZeroUnstable)
Options.HandleUnstable = Flags.handle_unstable;
Options.DumpCoverage = Flags.dump_coverage;
if (Flags.exit_on_src_pos)
Options.ExitOnSrcPos = Flags.exit_on_src_pos;

View File

@ -1,62 +0,0 @@
//===- FuzzerExtFunctionsDlsymWin.cpp - Interface to external functions ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Implementation using dynamic loading for Windows.
//===----------------------------------------------------------------------===//
#include "FuzzerDefs.h"
#if LIBFUZZER_WINDOWS
#include "FuzzerExtFunctions.h"
#include "FuzzerIO.h"
#include "Windows.h"
// This must be included after Windows.h.
#include "Psapi.h"
namespace fuzzer {
ExternalFunctions::ExternalFunctions() {
HMODULE Modules[1024];
DWORD BytesNeeded;
HANDLE CurrentProcess = GetCurrentProcess();
if (!EnumProcessModules(CurrentProcess, Modules, sizeof(Modules),
&BytesNeeded)) {
Printf("EnumProcessModules failed (error: %d).\n", GetLastError());
exit(1);
}
if (sizeof(Modules) < BytesNeeded) {
Printf("Error: the array is not big enough to hold all loaded modules.\n");
exit(1);
}
for (size_t i = 0; i < (BytesNeeded / sizeof(HMODULE)); i++)
{
FARPROC Fn;
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
if (this->NAME == nullptr) { \
Fn = GetProcAddress(Modules[i], #NAME); \
if (Fn == nullptr) \
Fn = GetProcAddress(Modules[i], #NAME "__dll"); \
this->NAME = (decltype(ExternalFunctions::NAME)) Fn; \
}
#include "FuzzerExtFunctions.def"
#undef EXT_FUNC
}
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
if (this->NAME == nullptr && WARN) \
Printf("WARNING: Failed to find function \"%s\".\n", #NAME);
#include "FuzzerExtFunctions.def"
#undef EXT_FUNC
}
} // namespace fuzzer
#endif // LIBFUZZER_WINDOWS

View File

@ -22,7 +22,7 @@
extern "C" {
// Declare these symbols as weak to allow them to be optionally defined.
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
__attribute__((weak)) RETURN_TYPE NAME FUNC_SIG
__attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG
#include "FuzzerExtFunctions.def"

View File

@ -1,56 +0,0 @@
//===- FuzzerExtFunctionsWeakAlias.cpp - Interface to external functions --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Implementation using weak aliases. Works for Windows.
//===----------------------------------------------------------------------===//
#include "FuzzerDefs.h"
#if LIBFUZZER_WINDOWS
#include "FuzzerExtFunctions.h"
#include "FuzzerIO.h"
using namespace fuzzer;
extern "C" {
// Declare these symbols as weak to allow them to be optionally defined.
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
RETURN_TYPE NAME##Def FUNC_SIG { \
Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \
exit(1); \
} \
RETURN_TYPE NAME FUNC_SIG __attribute__((weak, alias(#NAME "Def")));
#include "FuzzerExtFunctions.def"
#undef EXT_FUNC
}
template <typename T>
static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) {
if (Fun == FunDef) {
if (WarnIfMissing)
Printf("WARNING: Failed to find function \"%s\".\n", FnName);
return nullptr;
}
return Fun;
}
namespace fuzzer {
ExternalFunctions::ExternalFunctions() {
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN);
#include "FuzzerExtFunctions.def"
#undef EXT_FUNC
}
} // namespace fuzzer
#endif // LIBFUZZER_WINDOWS

View File

@ -0,0 +1,83 @@
//=== FuzzerExtWindows.cpp - Interface to external functions --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Implementation of FuzzerExtFunctions for Windows. Uses alternatename when
// compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately
// the method each compiler supports is not supported by the other.
//===----------------------------------------------------------------------===//
#include "FuzzerDefs.h"
#if LIBFUZZER_WINDOWS
#include "FuzzerExtFunctions.h"
#include "FuzzerIO.h"
using namespace fuzzer;
// Intermediate macro to ensure the parameter is expanded before stringified.
#define STRINGIFY_(A) #A
#define STRINGIFY(A) STRINGIFY_(A)
#if LIBFUZZER_MSVC
// Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
#if defined(_M_IX86) || defined(__i386__)
#define WIN_SYM_PREFIX "_"
#else
#define WIN_SYM_PREFIX
#endif
// Declare external functions as having alternativenames, so that we can
// determine if they are not defined.
#define EXTERNAL_FUNC(Name, Default) \
__pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \
Name) "=" WIN_SYM_PREFIX STRINGIFY(Default)))
#else
// Declare external functions as weak to allow them to default to a specified
// function if not defined explicitly. We must use weak symbols because clang's
// support for alternatename is not 100%, see
// https://bugs.llvm.org/show_bug.cgi?id=40218 for more details.
#define EXTERNAL_FUNC(Name, Default) \
__attribute__((weak, alias(STRINGIFY(Default))))
#endif // LIBFUZZER_MSVC
extern "C" {
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
RETURN_TYPE NAME##Def FUNC_SIG { \
Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \
exit(1); \
} \
EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG;
#include "FuzzerExtFunctions.def"
#undef EXT_FUNC
}
template <typename T>
static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) {
if (Fun == FunDef) {
if (WarnIfMissing)
Printf("WARNING: Failed to find function \"%s\".\n", FnName);
return nullptr;
}
return Fun;
}
namespace fuzzer {
ExternalFunctions::ExternalFunctions() {
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN);
#include "FuzzerExtFunctions.def"
#undef EXT_FUNC
}
} // namespace fuzzer
#endif // LIBFUZZER_WINDOWS

View File

@ -17,7 +17,7 @@ FUZZER_FLAG_INT(runs, -1,
FUZZER_FLAG_INT(max_len, 0, "Maximum length of the test input. "
"If 0, libFuzzer tries to guess a good value based on the corpus "
"and reports it. ")
FUZZER_FLAG_INT(len_control, 1000, "Try generating small inputs first, "
FUZZER_FLAG_INT(len_control, 100, "Try generating small inputs first, "
"then try larger inputs over time. Specifies the rate at which the length "
"limit is increased (smaller == faster). If 0, immediately try inputs with "
"size up to max_len.")
@ -110,15 +110,6 @@ FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information as text"
FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated."
" If 1, dump coverage information as a"
" .sancov file at exit.")
FUZZER_FLAG_INT(handle_unstable, 0, "Experimental."
" Executes every input 3 times in total if a unique feature"
" is found during the first execution."
" If 1, we only use the minimum hit count from the 3 runs"
" to determine whether an input is interesting."
" If 2, we disregard edges that are found unstable for"
" feature collection.")
FUZZER_FLAG_INT(print_unstable_stats, 0, "Experimental."
" If 1, print unstable statistics at exit.")
FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGBUS.")
FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.")
@ -162,4 +153,3 @@ FUZZER_DEPRECATED_FLAG(use_equivalence_server)
FUZZER_FLAG_INT(analyze_dict, 0, "Experimental")
FUZZER_DEPRECATED_FLAG(use_clang_coverage)
FUZZER_FLAG_STRING(data_flow_trace, "Experimental: use the data flow trace")
FUZZER_FLAG_INT(print_mutation_stats, 0, "Experimental")

View File

@ -31,7 +31,7 @@ long GetEpoch(const std::string &Path) {
}
Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {
std::ifstream T(Path);
std::ifstream T(Path, std::ios::binary);
if (ExitOnError && !T) {
Printf("No such directory: %s; exiting\n", Path.c_str());
exit(1);
@ -51,7 +51,7 @@ Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {
}
std::string FileToString(const std::string &Path) {
std::ifstream T(Path);
std::ifstream T(Path, std::ios::binary);
return std::string((std::istreambuf_iterator<char>(T)),
std::istreambuf_iterator<char>());
}
@ -100,14 +100,6 @@ std::string DirPlusFile(const std::string &DirPath,
return DirPath + GetSeparator() + FileName;
}
std::string Basename(const std::string &Path, char Separator) {
size_t Pos = Path.rfind(Separator);
if (Pos == std::string::npos)
return Path;
assert(Pos < Path.size());
return Path.substr(Pos + 1);
}
void DupAndCloseStderr() {
int OutputFd = DuplicateFile(2);
if (OutputFd > 0) {

View File

@ -68,7 +68,7 @@ void GetSizedFilesFromDir(const std::string &Dir, Vector<SizedFile> *V);
char GetSeparator();
// Similar to the basename utility: returns the file name w/o the dir prefix.
std::string Basename(const std::string &Path, char Separator = GetSeparator());
std::string Basename(const std::string &Path);
FILE* OpenFile(int Fd, const char *Mode);

View File

@ -46,6 +46,13 @@ size_t FileSize(const std::string &Path) {
return St.st_size;
}
std::string Basename(const std::string &Path) {
size_t Pos = Path.rfind(GetSeparator());
if (Pos == std::string::npos) return Path;
assert(Pos < Path.size());
return Path.substr(Pos + 1);
}
void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
Vector<std::string> *V, bool TopDir) {
auto E = GetEpoch(Dir);

View File

@ -72,6 +72,26 @@ bool IsFile(const std::string &Path) {
return IsFile(Path, Att);
}
std::string Basename(const std::string &Path) {
size_t Pos = Path.find_last_of("/\\");
if (Pos == std::string::npos) return Path;
assert(Pos < Path.size());
return Path.substr(Pos + 1);
}
size_t FileSize(const std::string &Path) {
WIN32_FILE_ATTRIBUTE_DATA attr;
if (!GetFileAttributesExA(Path.c_str(), GetFileExInfoStandard, &attr)) {
Printf("GetFileAttributesExA() failed for \"%s\" (Error code: %lu).\n",
Path.c_str(), GetLastError());
return 0;
}
ULARGE_INTEGER size;
size.HighPart = attr.nFileSizeHigh;
size.LowPart = attr.nFileSizeLow;
return size.QuadPart;
}
void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
Vector<std::string> *V, bool TopDir) {
auto E = GetEpoch(Dir);
@ -91,7 +111,7 @@ void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
return;
Printf("No such directory: %s; exiting\n", Dir.c_str());
Printf("No such file or directory: %s; exiting\n", Dir.c_str());
exit(1);
}

View File

@ -67,7 +67,6 @@ public:
static void StaticGracefulExitCallback();
void ExecuteCallback(const uint8_t *Data, size_t Size);
void CheckForUnstableCounters(const uint8_t *Data, size_t Size);
bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);

View File

@ -275,7 +275,8 @@ NO_SANITIZE_MEMORY
void Fuzzer::AlarmCallback() {
assert(Options.UnitTimeoutSec > 0);
// In Windows Alarm callback is executed by a different thread.
#if !LIBFUZZER_WINDOWS
// NetBSD's current behavior needs this change too.
#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD
if (!InFuzzingThread())
return;
#endif
@ -354,13 +355,10 @@ void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
void Fuzzer::PrintFinalStats() {
if (Options.PrintCoverage)
TPC.PrintCoverage();
if (Options.PrintUnstableStats)
TPC.PrintUnstableStats();
if (Options.DumpCoverage)
TPC.DumpCoverage();
if (Options.PrintCorpusStats)
Corpus.PrintStats();
if (Options.PrintMutationStats) MD.PrintMutationStats();
if (!Options.PrintFinalStats)
return;
size_t ExecPerSec = execPerSec();
@ -449,34 +447,6 @@ void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
}
}
void Fuzzer::CheckForUnstableCounters(const uint8_t *Data, size_t Size) {
auto CBSetupAndRun = [&]() {
ScopedEnableMsanInterceptorChecks S;
UnitStartTime = system_clock::now();
TPC.ResetMaps();
RunningUserCallback = true;
CB(Data, Size);
RunningUserCallback = false;
UnitStopTime = system_clock::now();
};
// Copy original run counters into our unstable counters
TPC.InitializeUnstableCounters();
// First Rerun
CBSetupAndRun();
TPC.UpdateUnstableCounters(Options.HandleUnstable);
// Second Rerun
CBSetupAndRun();
TPC.UpdateUnstableCounters(Options.HandleUnstable);
// Move minimum hit counts back to ModuleInline8bitCounters
if (Options.HandleUnstable == TracePC::MinUnstable ||
Options.HandleUnstable == TracePC::ZeroUnstable)
TPC.ApplyUnstableCounters();
}
bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
InputInfo *II, bool *FoundUniqFeatures) {
if (!Size)
@ -487,17 +457,6 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
UniqFeatureSetTmp.clear();
size_t FoundUniqFeaturesOfII = 0;
size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
bool NewFeaturesUnstable = false;
if (Options.HandleUnstable || Options.PrintUnstableStats) {
TPC.CollectFeatures([&](size_t Feature) {
if (Corpus.IsFeatureNew(Feature, Size, Options.Shrink))
NewFeaturesUnstable = true;
});
if (NewFeaturesUnstable)
CheckForUnstableCounters(Data, Size);
}
TPC.CollectFeatures([&](size_t Feature) {
if (Corpus.AddFeature(Feature, Size, Options.Shrink))
UniqFeatureSetTmp.push_back(Feature);
@ -506,12 +465,10 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
II->UniqFeatureSet.end(), Feature))
FoundUniqFeaturesOfII++;
});
if (FoundUniqFeatures)
*FoundUniqFeatures = FoundUniqFeaturesOfII;
PrintPulseAndReportSlowInput(Data, Size);
size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
if (NumNewFeatures) {
TPC.UpdateObservedPCs();
Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile,

View File

@ -30,36 +30,34 @@ MutationDispatcher::MutationDispatcher(Random &Rand,
DefaultMutators.insert(
DefaultMutators.begin(),
{
{&MutationDispatcher::Mutate_EraseBytes, "EraseBytes", 0, 0},
{&MutationDispatcher::Mutate_InsertByte, "InsertByte", 0, 0},
{&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
{&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
{&MutationDispatcher::Mutate_InsertRepeatedBytes,
"InsertRepeatedBytes", 0, 0},
{&MutationDispatcher::Mutate_ChangeByte, "ChangeByte", 0, 0},
{&MutationDispatcher::Mutate_ChangeBit, "ChangeBit", 0, 0},
{&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes", 0, 0},
{&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt", 0,
0},
{&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt", 0,
0},
{&MutationDispatcher::Mutate_CopyPart, "CopyPart", 0, 0},
{&MutationDispatcher::Mutate_CrossOver, "CrossOver", 0, 0},
"InsertRepeatedBytes"},
{&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
{&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
{&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
{&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
{&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
{&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
{&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
{&MutationDispatcher::Mutate_AddWordFromManualDictionary,
"ManualDict", 0, 0},
"ManualDict"},
{&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
"PersAutoDict", 0, 0},
"PersAutoDict"},
});
if(Options.UseCmp)
DefaultMutators.push_back(
{&MutationDispatcher::Mutate_AddWordFromTORC, "CMP", 0, 0});
{&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
if (EF->LLVMFuzzerCustomMutator)
Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom", 0, 0});
Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
else
Mutators = DefaultMutators;
if (EF->LLVMFuzzerCustomCrossOver)
Mutators.push_back(
{&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver", 0, 0});
{&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
}
static char RandCh(Random &Rand) {
@ -466,7 +464,6 @@ void MutationDispatcher::RecordSuccessfulMutationSequence() {
if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
PersistentAutoDictionary.push_back({DE->GetW(), 1});
}
RecordUsefulMutations();
}
void MutationDispatcher::PrintRecommendedDictionary() {
@ -487,7 +484,8 @@ void MutationDispatcher::PrintRecommendedDictionary() {
void MutationDispatcher::PrintMutationSequence() {
Printf("MS: %zd ", CurrentMutatorSequence.size());
for (auto M : CurrentMutatorSequence) Printf("%s-", M->Name);
for (auto M : CurrentMutatorSequence)
Printf("%s-", M.Name);
if (!CurrentDictionaryEntrySequence.empty()) {
Printf(" DE: ");
for (auto DE : CurrentDictionaryEntrySequence) {
@ -515,13 +513,12 @@ size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
// in which case they will return 0.
// Try several times before returning un-mutated data.
for (int Iter = 0; Iter < 100; Iter++) {
auto M = &Mutators[Rand(Mutators.size())];
size_t NewSize = (this->*(M->Fn))(Data, Size, MaxSize);
auto M = Mutators[Rand(Mutators.size())];
size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
if (NewSize && NewSize <= MaxSize) {
if (Options.OnlyASCII)
ToASCII(Data, NewSize);
CurrentMutatorSequence.push_back(M);
M->TotalCount++;
return NewSize;
}
}
@ -562,21 +559,4 @@ void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
{W, std::numeric_limits<size_t>::max()});
}
void MutationDispatcher::RecordUsefulMutations() {
for (auto M : CurrentMutatorSequence) M->UsefulCount++;
}
void MutationDispatcher::PrintMutationStats() {
Printf("\nstat::mutation_usefulness: ");
for (size_t i = 0; i < Mutators.size(); i++) {
double UsefulPercentage =
Mutators[i].TotalCount
? (100.0 * Mutators[i].UsefulCount) / Mutators[i].TotalCount
: 0;
Printf("%.3f", UsefulPercentage);
if (i < Mutators.size() - 1) Printf(",");
}
Printf("\n");
}
} // namespace fuzzer

View File

@ -93,16 +93,10 @@ public:
Random &GetRand() { return Rand; }
void PrintMutationStats();
void RecordUsefulMutations();
private:
struct Mutator {
size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
const char *Name;
uint64_t UsefulCount;
uint64_t TotalCount;
};
size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
@ -141,7 +135,6 @@ public:
Dictionary PersistentAutoDictionary;
Vector<DictionaryEntry *> CurrentDictionaryEntrySequence;
Vector<Mutator *> CurrentMutatorSequence;
static const size_t kCmpDictionaryEntriesDequeSize = 16;
DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize];
@ -156,6 +149,7 @@ public:
Vector<Mutator> Mutators;
Vector<Mutator> DefaultMutators;
Vector<Mutator> CurrentMutatorSequence;
};
} // namespace fuzzer

View File

@ -52,11 +52,8 @@ struct FuzzingOptions {
bool PrintNewCovPcs = false;
int PrintNewCovFuncs = 0;
bool PrintFinalStats = false;
bool PrintMutationStats = false;
bool PrintCorpusStats = false;
bool PrintCoverage = false;
bool PrintUnstableStats = false;
int HandleUnstable = 0;
bool DumpCoverage = false;
bool DetectLeaks = true;
int PurgeAllocatorIntervalSec = 1;

View File

@ -13,6 +13,8 @@
//===----------------------------------------------------------------------===//
#include "FuzzerTracePC.h"
#include "FuzzerBuiltins.h"
#include "FuzzerBuiltinsMsvc.h"
#include "FuzzerCorpus.h"
#include "FuzzerDefs.h"
#include "FuzzerDictionary.h"
@ -32,8 +34,7 @@ ATTRIBUTE_INTERFACE
uintptr_t __sancov_trace_pc_pcs[fuzzer::TracePC::kNumPCs];
// Used by -fsanitize-coverage=stack-depth to track stack depth
ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec")))
thread_local uintptr_t __sancov_lowest_stack;
ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC uintptr_t __sancov_lowest_stack;
namespace fuzzer {
@ -57,49 +58,6 @@ size_t TracePC::GetTotalPCCoverage() {
return Res;
}
template<class CallBack>
void TracePC::IterateInline8bitCounters(CallBack CB) const {
if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables) {
size_t CounterIdx = 0;
for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
uint8_t *Beg = ModuleCounters[i].Start;
size_t Size = ModuleCounters[i].Stop - Beg;
assert(Size == (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
for (size_t j = 0; j < Size; j++, CounterIdx++)
CB(i, j, CounterIdx);
}
}
}
// Initializes unstable counters by copying Inline8bitCounters to unstable
// counters.
void TracePC::InitializeUnstableCounters() {
IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j];
});
}
// Compares the current counters with counters from previous runs
// and records differences as unstable edges.
void TracePC::UpdateUnstableCounters(int UnstableMode) {
IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) {
UnstableCounters[UnstableIdx].IsUnstable = true;
if (UnstableMode == ZeroUnstable)
UnstableCounters[UnstableIdx].Counter = 0;
else if (UnstableMode == MinUnstable)
UnstableCounters[UnstableIdx].Counter = std::min(
ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter);
}
});
}
// Moves the minimum hit counts to ModuleCounters.
void TracePC::ApplyUnstableCounters() {
IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
ModuleCounters[i].Start[j] = UnstableCounters[UnstableIdx].Counter;
});
}
void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) {
if (Start == Stop) return;
@ -185,11 +143,42 @@ void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
ValueProfileMap.AddValueModPrime(Idx);
}
/// \return the address of the previous instruction.
/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.h`
inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
#if defined(__arm__)
// T32 (Thumb) branch instructions might be 16 or 32 bit long,
// so we return (pc-2) in that case in order to be safe.
// For A32 mode we return (pc-4) because all instructions are 32 bit long.
return (PC - 3) & (~1);
#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
// PCs are always 4 byte aligned.
return PC - 4;
#elif defined(__sparc__) || defined(__mips__)
return PC - 8;
#else
return PC - 1;
#endif
}
/// \return the address of the next instruction.
/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cc`
inline ALWAYS_INLINE uintptr_t GetNextInstructionPc(uintptr_t PC) {
#if defined(__mips__)
return PC + 8;
#elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \
defined(__aarch64__)
return PC + 4;
#else
return PC + 1;
#endif
}
void TracePC::UpdateObservedPCs() {
Vector<uintptr_t> CoveredFuncs;
auto ObservePC = [&](uintptr_t PC) {
if (ObservedPCs.insert(PC).second && DoPrintNewPCs) {
PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", PC + 1);
PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", GetNextInstructionPc(PC));
Printf("\n");
}
};
@ -203,10 +192,15 @@ void TracePC::UpdateObservedPCs() {
if (NumPCsInPCTables) {
if (NumInline8bitCounters == NumPCsInPCTables) {
IterateInline8bitCounters([&](int i, int j, int CounterIdx) {
if (ModuleCounters[i].Start[j])
Observe(ModulePCTable[i].Start[j]);
});
for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
uint8_t *Beg = ModuleCounters[i].Start;
size_t Size = ModuleCounters[i].Stop - Beg;
assert(Size ==
(size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
for (size_t j = 0; j < Size; j++)
if (Beg[j])
Observe(ModulePCTable[i].Start[j]);
}
} else if (NumGuards == NumPCsInPCTables) {
size_t GuardIdx = 1;
for (size_t i = 0; i < NumModules; i++) {
@ -224,22 +218,11 @@ void TracePC::UpdateObservedPCs() {
for (size_t i = 0, N = Min(CoveredFuncs.size(), NumPrintNewFuncs); i < N;
i++) {
Printf("\tNEW_FUNC[%zd/%zd]: ", i + 1, CoveredFuncs.size());
PrintPC("%p %F %L", "%p", CoveredFuncs[i] + 1);
PrintPC("%p %F %L", "%p", GetNextInstructionPc(CoveredFuncs[i]));
Printf("\n");
}
}
inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
// TODO: this implementation is x86 only.
// see sanitizer_common GetPreviousInstructionPc for full implementation.
return PC - 1;
}
inline ALWAYS_INLINE uintptr_t GetNextInstructionPc(uintptr_t PC) {
// TODO: this implementation is x86 only.
// see sanitizer_common GetPreviousInstructionPc for full implementation.
return PC + 1;
}
static std::string GetModuleName(uintptr_t PC) {
char ModulePathRaw[4096] = ""; // What's PATH_MAX in portable C++?
@ -349,15 +332,6 @@ void TracePC::DumpCoverage() {
}
}
void TracePC::PrintUnstableStats() {
size_t count = 0;
for (size_t i = 0; i < NumInline8bitCounters; i++)
if (UnstableCounters[i].IsUnstable)
count++;
Printf("stat::stability_rate: %.2f\n",
100 - static_cast<float>(count * 100) / NumInline8bitCounters);
}
// Value profile.
// We keep track of various values that affect control flow.
// These values are inserted into a bit-set-based hash map.
@ -401,20 +375,14 @@ ATTRIBUTE_TARGET_POPCNT ALWAYS_INLINE
ATTRIBUTE_NO_SANITIZE_ALL
void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) {
uint64_t ArgXor = Arg1 ^ Arg2;
uint64_t ArgDistance = __builtin_popcountll(ArgXor) + 1; // [1,65]
uintptr_t Idx = ((PC & 4095) + 1) * ArgDistance;
if (sizeof(T) == 4)
TORC4.Insert(ArgXor, Arg1, Arg2);
else if (sizeof(T) == 8)
TORC8.Insert(ArgXor, Arg1, Arg2);
// TODO: remove these flags and instead use all metrics at once.
if (UseValueProfileMask & 1)
ValueProfileMap.AddValue(Idx);
if (UseValueProfileMask & 2)
ValueProfileMap.AddValue(
PC * 64 + (Arg1 == Arg2 ? 0 : __builtin_clzll(Arg1 - Arg2) + 1));
if (UseValueProfileMask & 4) // alternative way to use the hamming distance
ValueProfileMap.AddValue(PC * 64 + ArgDistance);
uint64_t HammingDistance = Popcountll(ArgXor); // [0,64]
uint64_t AbsoluteDistance = (Arg1 == Arg2 ? 0 : Clzll(Arg1 - Arg2) + 1);
ValueProfileMap.AddValue(PC * 128 + HammingDistance);
ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance);
}
static size_t InternalStrnlen(const char *S, size_t MaxLen) {
@ -455,7 +423,7 @@ extern "C" {
ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
uint32_t Idx = *Guard;
__sancov_trace_pc_pcs[Idx] = PC;
__sancov_trace_pc_guard_8bit_counters[Idx]++;
@ -466,7 +434,7 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) {
ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
void __sanitizer_cov_trace_pc() {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
uintptr_t Idx = PC & (((uintptr_t)1 << fuzzer::TracePC::kTracePcBits) - 1);
__sancov_trace_pc_pcs[Idx] = PC;
__sancov_trace_pc_guard_8bit_counters[Idx]++;
@ -491,7 +459,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCallerCallee(PC, Callee);
}
@ -499,7 +467,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
}
@ -510,7 +478,7 @@ ATTRIBUTE_TARGET_POPCNT
// the behaviour of __sanitizer_cov_trace_cmp[1248] ones. This, however,
// should be changed later to make full use of instrumentation.
void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
}
@ -518,7 +486,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
}
@ -526,7 +494,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
}
@ -534,7 +502,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
}
@ -542,7 +510,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
}
@ -550,7 +518,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
}
@ -558,7 +526,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
}
@ -572,7 +540,7 @@ void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
// Skip the most common and the most boring case.
if (Vals[N - 1] < 256 && Val < 256)
return;
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
size_t i;
uint64_t Token = 0;
for (i = 0; i < N; i++) {
@ -593,7 +561,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_div4(uint32_t Val) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0);
}
@ -601,7 +569,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_div8(uint64_t Val) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0);
}
@ -609,7 +577,7 @@ ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
ATTRIBUTE_TARGET_POPCNT
void __sanitizer_cov_trace_gep(uintptr_t Idx) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0);
}

View File

@ -74,11 +74,6 @@ class TracePC {
// How many bits of PC are used from __sanitizer_cov_trace_pc.
static const size_t kTracePcBits = 18;
enum HandleUnstableOptions {
MinUnstable = 1,
ZeroUnstable = 2,
};
void HandleInit(uint32_t *Start, uint32_t *Stop);
void HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop);
void HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop);
@ -109,7 +104,6 @@ class TracePC {
void PrintCoverage();
void DumpCoverage();
void PrintUnstableStats();
template<class CallBack>
void IterateCoveredFunctions(CallBack CB);
@ -142,18 +136,7 @@ class TracePC {
void SetFocusFunction(const std::string &FuncName);
bool ObservedFocusFunction();
void InitializeUnstableCounters();
void UpdateUnstableCounters(int UnstableMode);
void ApplyUnstableCounters();
private:
struct UnstableEdge {
uint8_t Counter;
bool IsUnstable;
};
UnstableEdge UnstableCounters[kNumPCs];
bool UseCounters = false;
uint32_t UseValueProfileMask = false;
bool DoPrintNewPCs = false;
@ -185,9 +168,6 @@ private:
Set<uintptr_t> ObservedPCs;
std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs; // PC => Counter.
template <class Callback>
void IterateInline8bitCounters(Callback CB) const;
std::pair<size_t, size_t> FocusFunction = {-1, -1}; // Module and PC IDs.
ValueBitMap ValueProfileMap;

View File

@ -12,8 +12,10 @@
#ifndef LLVM_FUZZER_UTIL_H
#define LLVM_FUZZER_UTIL_H
#include "FuzzerDefs.h"
#include "FuzzerBuiltins.h"
#include "FuzzerBuiltinsMsvc.h"
#include "FuzzerCommand.h"
#include "FuzzerDefs.h"
namespace fuzzer {
@ -84,7 +86,7 @@ std::string SearchRegexCmd(const std::string &Regex);
size_t SimpleFastHash(const uint8_t *Data, size_t Size);
inline uint32_t Log(uint32_t X) { return 32 - __builtin_clz(X) - 1; }
inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; }
} // namespace fuzzer

View File

@ -49,9 +49,6 @@ void CrashTrampolineAsm() __asm__("CrashTrampolineAsm");
namespace {
// TODO(phosek): remove this and replace it with ZX_TIME_INFINITE
#define ZX_TIME_INFINITE_OLD INT64_MAX
// A magic value for the Zircon exception port, chosen to spell 'FUZZING'
// when interpreted as a byte sequence on little-endian platforms.
const uint64_t kFuzzingCrash = 0x474e495a5a5546;
@ -237,7 +234,7 @@ void CrashHandler(zx_handle_t *Event) {
"_zx_object_signal");
zx_port_packet_t Packet;
ExitOnErr(_zx_port_wait(Port.Handle, ZX_TIME_INFINITE_OLD, &Packet),
ExitOnErr(_zx_port_wait(Port.Handle, ZX_TIME_INFINITE, &Packet),
"_zx_port_wait");
// At this point, we want to get the state of the crashing thread, but
@ -315,8 +312,8 @@ void SetSignalHandler(const FuzzingOptions &Options) {
ExitOnErr(_zx_event_create(0, &Event), "_zx_event_create");
std::thread T(CrashHandler, &Event);
zx_status_t Status = _zx_object_wait_one(Event, ZX_USER_SIGNAL_0,
ZX_TIME_INFINITE_OLD, nullptr);
zx_status_t Status =
_zx_object_wait_one(Event, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, nullptr);
_zx_handle_close(Event);
ExitOnErr(Status, "_zx_object_wait_one");
@ -378,19 +375,28 @@ int ExecuteCommand(const Command &Cmd) {
Argv[i] = Args[i].c_str();
Argv[Argc] = nullptr;
// Determine stdout
// Determine output. On Fuchsia, the fuzzer is typically run as a component
// that lacks a mutable working directory. Fortunately, when this is the case
// a mutable output directory must be specified using "-artifact_prefix=...",
// so write the log file(s) there.
int FdOut = STDOUT_FILENO;
if (Cmd.hasOutputFile()) {
auto Filename = Cmd.getOutputFile();
FdOut = open(Filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
std::string Path;
if (Cmd.hasFlag("artifact_prefix"))
Path = Cmd.getFlagValue("artifact_prefix") + "/" + Cmd.getOutputFile();
else
Path = Cmd.getOutputFile();
FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
if (FdOut == -1) {
Printf("libFuzzer: failed to open %s: %s\n", Filename.c_str(),
Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(),
strerror(errno));
return ZX_ERR_IO;
}
}
auto CloseFdOut = at_scope_exit([&]() { close(FdOut); } );
auto CloseFdOut = at_scope_exit([FdOut]() {
if (FdOut != STDOUT_FILENO)
close(FdOut);
});
// Determine stderr
int FdErr = STDERR_FILENO;
@ -440,7 +446,7 @@ int ExecuteCommand(const Command &Cmd) {
// Now join the process and return the exit status.
if ((rc = _zx_object_wait_one(ProcessHandle, ZX_PROCESS_TERMINATED,
ZX_TIME_INFINITE_OLD, nullptr)) != ZX_OK) {
ZX_TIME_INFINITE, nullptr)) != ZX_OK) {
Printf("libFuzzer: failed to join '%s': %s\n", Argv[0],
_zx_status_get_string(rc));
return rc;

View File

@ -24,7 +24,7 @@
#include <windows.h>
// This must be included after windows.h.
#include <Psapi.h>
#include <psapi.h>
namespace fuzzer {
@ -179,7 +179,9 @@ const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
}
std::string DisassembleCmd(const std::string &FileName) {
if (ExecuteCommand("dumpbin /summary > nul") == 0)
Vector<std::string> command_vector;
command_vector.push_back("dumpbin /summary > nul");
if (ExecuteCommand(Command(command_vector)) == 0)
return "dumpbin /disasm " + FileName;
Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n");
exit(1);

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