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:
parent
1db450fe70
commit
5c86f0191f
@ -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)
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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()
|
||||
|
@ -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}")
|
||||
|
@ -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}"
|
||||
|
@ -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 "" "" "")
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -82,7 +82,6 @@ extern "C" {
|
||||
Currently available with ASan only.
|
||||
*/
|
||||
void __sanitizer_purge_allocator(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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 "
|
||||
|
@ -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>.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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) \
|
||||
|
@ -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 ||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>.
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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, "ient, "ientLo);
|
||||
|
||||
|
||||
// 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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
106
lib/builtins/ppc/fixunstfti.c
Normal file
106
lib/builtins/ppc/fixunstfti.c
Normal 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;
|
||||
}
|
48
lib/builtins/ppc/floattitf.c
Normal file
48
lib/builtins/ppc/floattitf.c
Normal 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);
|
||||
}
|
@ -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(..)
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
35
lib/esan/esan_sideline_bsd.cpp
Normal file
35
lib/esan/esan_sideline_bsd.cpp
Normal 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
|
@ -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)
|
||||
|
36
lib/fuzzer/FuzzerBuiltins.h
Normal file
36
lib/fuzzer/FuzzerBuiltins.h
Normal 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
|
59
lib/fuzzer/FuzzerBuiltinsMsvc.h
Normal file
59
lib/fuzzer/FuzzerBuiltinsMsvc.h
Normal 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
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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"
|
||||
|
||||
|
@ -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
|
83
lib/fuzzer/FuzzerExtFunctionsWindows.cpp
Normal file
83
lib/fuzzer/FuzzerExtFunctionsWindows.cpp
Normal 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
|
@ -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")
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user