Vendor import of compiler-rt trunk r256633:
https://llvm.org/svn/llvm-project/compiler-rt/trunk@256633
This commit is contained in:
parent
f31bcc68c7
commit
5c909fa013
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/compiler-rt/dist/; revision=292925 svn path=/vendor/compiler-rt/compiler-rt-trunk-r256633/; revision=292926; tag=vendor/compiler-rt/compiler-rt-trunk-r256633
116
CMakeLists.txt
116
CMakeLists.txt
@ -9,7 +9,7 @@
|
||||
|
||||
# Check if compiler-rt is built as a standalone project.
|
||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
project(CompilerRT C CXX)
|
||||
project(CompilerRT C CXX ASM)
|
||||
set(COMPILER_RT_STANDALONE_BUILD TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_STANDALONE_BUILD FALSE)
|
||||
@ -22,7 +22,7 @@ endif()
|
||||
if (NOT MSVC)
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
else()
|
||||
# Version 2.8.12.1 is required to build with Visual Studion 2013.
|
||||
# Version 2.8.12.1 is required to build with Visual Studio 2013.
|
||||
cmake_minimum_required(VERSION 2.8.12.1)
|
||||
endif()
|
||||
|
||||
@ -43,6 +43,11 @@ endif()
|
||||
# Top level target used to build all compiler-rt libraries.
|
||||
add_custom_target(compiler-rt ALL)
|
||||
|
||||
option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON)
|
||||
mark_as_advanced(COMPILER_RT_BUILD_BUILTINS)
|
||||
option(COMPILER_RT_BUILD_SANITIZERS "Build sanitizers" ON)
|
||||
mark_as_advanced(COMPILER_RT_BUILD_SANITIZERS)
|
||||
|
||||
if (NOT COMPILER_RT_STANDALONE_BUILD)
|
||||
# Compute the Clang version from the LLVM version.
|
||||
# FIXME: We should be able to reuse CLANG_VERSION variable calculated
|
||||
@ -132,22 +137,27 @@ else()
|
||||
set(COMPILER_RT_TEST_COMPILER_ID GNU)
|
||||
endif()
|
||||
|
||||
# Tests using XFAIL use the first value in COMPILER_RT_TEST_TARGET_TRIPLE
|
||||
set(COMPILER_RT_TEST_TARGET_TRIPLE ${TARGET_TRIPLE} CACHE STRING
|
||||
"Default triple for cross-compiled executables")
|
||||
string(REPLACE "-" ";" TARGET_TRIPLE_LIST ${COMPILER_RT_TEST_TARGET_TRIPLE})
|
||||
list(GET TARGET_TRIPLE_LIST 0 COMPILER_RT_TEST_TARGET_ARCH)
|
||||
list(GET TARGET_TRIPLE_LIST 1 COMPILER_RT_TEST_TARGET_OS)
|
||||
list(GET TARGET_TRIPLE_LIST 2 COMPILER_RT_TEST_TARGET_ABI)
|
||||
# Determine if test target triple is specified explicitly, and doesn't match the
|
||||
# default.
|
||||
if(NOT COMPILER_RT_TEST_TARGET_TRIPLE STREQUAL TARGET_TRIPLE)
|
||||
set(COMPILER_RT_HAS_EXPLICIT_TEST_TARGET_TRIPLE TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_EXPLICIT_TEST_TARGET_TRIPLE FALSE)
|
||||
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${TARGET_TRIPLE} CACHE STRING
|
||||
"Default triple for which compiler-rt runtimes will be built.")
|
||||
if(DEFINED COMPILER_RT_TEST_TARGET_TRIPLE)
|
||||
# Backwards compatibility: this variable used to be called
|
||||
# COMPILER_RT_TEST_TARGET_TRIPLE.
|
||||
set(COMPILER_RT_DEFAULT_TARGET_TRIPLE ${COMPILER_RT_TEST_TARGET_TRIPLE})
|
||||
endif()
|
||||
|
||||
if ("${COMPILER_RT_TEST_TARGET_ABI}" STREQUAL "androideabi")
|
||||
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(GET TARGET_TRIPLE_LIST 2 COMPILER_RT_DEFAULT_TARGET_ABI)
|
||||
# Determine if test target triple is specified explicitly, and doesn't match the
|
||||
# default.
|
||||
if(NOT COMPILER_RT_DEFAULT_TARGET_TRIPLE STREQUAL TARGET_TRIPLE)
|
||||
set(COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE FALSE)
|
||||
endif()
|
||||
|
||||
if ("${COMPILER_RT_DEFAULT_TARGET_ABI}" STREQUAL "androideabi")
|
||||
set(ANDROID 1)
|
||||
endif()
|
||||
|
||||
@ -179,6 +189,8 @@ else()
|
||||
endif()
|
||||
|
||||
option(COMPILER_RT_DEBUG "Build runtimes with full debug info" OFF)
|
||||
option(COMPILER_RT_EXTERNALIZE_DEBUGINFO
|
||||
"Generate dSYM files and strip executables and libraries (Darwin Only)" OFF)
|
||||
# COMPILER_RT_DEBUG_PYBOOL is used by lit.common.configured.in.
|
||||
pythonize_bool(COMPILER_RT_DEBUG)
|
||||
|
||||
@ -216,6 +228,7 @@ append_list_if(COMPILER_RT_HAS_FUNWIND_TABLES_FLAG -funwind-tables SANITIZER_COM
|
||||
append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG -fno-sanitize=safe-stack SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FVISIBILITY_INLINES_HIDDEN_FLAG -fvisibility-inlines-hidden SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)
|
||||
|
||||
@ -250,8 +263,7 @@ endif()
|
||||
# FIXME: Fix all sanitizers and add -Wframe-larger-than to
|
||||
# SANITIZER_COMMON_FLAGS
|
||||
if(COMPILER_RT_HAS_WFRAME_LARGER_THAN_FLAG AND NOT COMPILER_RT_DEBUG
|
||||
AND NOT ${LLVM_NATIVE_ARCH} STREQUAL "PowerPC"
|
||||
AND NOT ${LLVM_NATIVE_ARCH} STREQUAL "Mips")
|
||||
AND NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "powerpc|mips")
|
||||
set(SANITIZER_LIMIT_FRAME_SIZE TRUE)
|
||||
else()
|
||||
set(SANITIZER_LIMIT_FRAME_SIZE FALSE)
|
||||
@ -276,64 +288,6 @@ append_list_if(COMPILER_RT_HAS_WD4291_FLAG /wd4291 SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WD4391_FLAG /wd4391 SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WD4722_FLAG /wd4722 SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_WD4800_FLAG /wd4800 SANITIZER_COMMON_CFLAGS)
|
||||
if(APPLE)
|
||||
macro(find_darwin_sdk_dir var sdk_name)
|
||||
# Let's first try the internal SDK, otherwise use the public SDK.
|
||||
execute_process(
|
||||
COMMAND xcodebuild -version -sdk ${sdk_name}.internal Path
|
||||
OUTPUT_VARIABLE ${var}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_FILE /dev/null
|
||||
)
|
||||
if(${var} STREQUAL "")
|
||||
execute_process(
|
||||
COMMAND xcodebuild -version -sdk ${sdk_name} Path
|
||||
OUTPUT_VARIABLE ${var}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_FILE /dev/null
|
||||
)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
find_darwin_sdk_dir(OSX_SDK_DIR macosx)
|
||||
find_darwin_sdk_dir(IOSSIM_SDK_DIR iphonesimulator)
|
||||
|
||||
set(SANITIZER_COMMON_SUPPORTED_OS osx)
|
||||
string(REGEX MATCH "-mmacosx-version-min=([.0-9]+)"
|
||||
MACOSX_VERSION_MIN_FLAG "${CMAKE_CXX_FLAGS}")
|
||||
if(MACOSX_VERSION_MIN_FLAG)
|
||||
set(SANITIZER_MIN_OSX_VERSION "${CMAKE_MATCH_1}")
|
||||
elseif(CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
set(SANITIZER_MIN_OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET})
|
||||
else()
|
||||
set(SANITIZER_MIN_OSX_VERSION 10.9)
|
||||
if(IOSSIM_SDK_DIR)
|
||||
list(APPEND SANITIZER_COMMON_SUPPORTED_OS iossim)
|
||||
endif()
|
||||
endif()
|
||||
if(SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.7")
|
||||
message(FATAL_ERROR "Too old OS X version: ${SANITIZER_MIN_OSX_VERSION}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "") # We evaluate target OS X version above.
|
||||
set(DARWIN_osx_CFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}
|
||||
-stdlib=libc++)
|
||||
set(DARWIN_iossim_CFLAGS
|
||||
-stdlib=libc++
|
||||
-mios-simulator-version-min=7.0 -isysroot ${IOSSIM_SDK_DIR})
|
||||
set(DARWIN_osx_LINKFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}
|
||||
-stdlib=libc++ -lc++ -lc++abi)
|
||||
set(DARWIN_iossim_LINKFLAGS
|
||||
-stdlib=libc++ -lc++ -lc++abi
|
||||
-Wl,-ios_simulator_version_min,7.0.0
|
||||
-mios-simulator-version-min=7.0
|
||||
-isysroot ${IOSSIM_SDK_DIR})
|
||||
|
||||
if(OSX_SDK_DIR)
|
||||
list(APPEND DARWIN_osx_CFLAGS -isysroot ${OSX_SDK_DIR})
|
||||
list(APPEND DARWIN_osx_LINKFLAGS -isysroot ${OSX_SDK_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE AND SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.9")
|
||||
# Mac OS X prior to 10.9 had problems with exporting symbols from
|
||||
@ -353,9 +307,17 @@ else()
|
||||
set(COMPILER_RT_HAS_LIBCXX_SOURCES FALSE)
|
||||
endif()
|
||||
|
||||
set(COMPILER_RT_LLD_PATH ${LLVM_MAIN_SRC_DIR}/tools/lld)
|
||||
if(EXISTS ${COMPILER_RT_LLD_PATH}/)
|
||||
set(COMPILER_RT_HAS_LLD_SOURCES TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_LLD_SOURCES FALSE)
|
||||
endif()
|
||||
pythonize_bool(COMPILER_RT_HAS_LLD_SOURCES)
|
||||
|
||||
add_subdirectory(lib)
|
||||
|
||||
if(COMPILER_RT_INCLUDE_TESTS)
|
||||
add_subdirectory(unittests)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
add_subdirectory(test)
|
||||
|
@ -19,6 +19,7 @@ function(add_compiler_rt_object_libraries name)
|
||||
set(libname "${name}.${os}")
|
||||
set(libnames ${libnames} ${libname})
|
||||
set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS})
|
||||
list_union(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS)
|
||||
endforeach()
|
||||
else()
|
||||
foreach(arch ${LIB_ARCHS})
|
||||
@ -26,7 +27,7 @@ function(add_compiler_rt_object_libraries name)
|
||||
set(libnames ${libnames} ${libname})
|
||||
set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS})
|
||||
if(NOT CAN_TARGET_${arch})
|
||||
message(FATAL_ERROR "Archtecture ${arch} can't be targeted")
|
||||
message(FATAL_ERROR "Architecture ${arch} can't be targeted")
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
@ -39,91 +40,130 @@ function(add_compiler_rt_object_libraries name)
|
||||
set_property(TARGET ${libname} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
if(APPLE)
|
||||
set_target_properties(${libname} PROPERTIES OSX_ARCHITECTURES "${LIB_ARCHS}")
|
||||
set_target_properties(${libname} PROPERTIES
|
||||
OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# Adds static or shared runtime for a given architecture and puts it in the
|
||||
# proper directory in the build and install trees.
|
||||
# add_compiler_rt_runtime(<name> <arch> {STATIC,SHARED}
|
||||
# Takes a list of object library targets, and a suffix and appends the proper
|
||||
# TARGET_OBJECTS string to the output variable.
|
||||
# format_object_libs(<output> <suffix> ...)
|
||||
macro(format_object_libs output suffix)
|
||||
foreach(lib ${ARGN})
|
||||
list(APPEND ${output} $<TARGET_OBJECTS:${lib}.${suffix}>)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Adds static or shared runtime for a list of architectures and operating
|
||||
# systems and puts it in the proper directory in the build and install trees.
|
||||
# add_compiler_rt_runtime(<name>
|
||||
# {STATIC|SHARED}
|
||||
# ARCHS <architectures>
|
||||
# OS <os list>
|
||||
# SOURCES <source files>
|
||||
# CFLAGS <compile flags>
|
||||
# LINKFLAGS <linker flags>
|
||||
# DEFS <compile definitions>
|
||||
# OUTPUT_NAME <output library name>)
|
||||
macro(add_compiler_rt_runtime name arch type)
|
||||
if(CAN_TARGET_${arch})
|
||||
cmake_parse_arguments(LIB "" "OUTPUT_NAME" "SOURCES;CFLAGS;LINKFLAGS;DEFS" ${ARGN})
|
||||
add_library(${name} ${type} ${LIB_SOURCES})
|
||||
# Setup compile flags and definitions.
|
||||
set_target_compile_flags(${name}
|
||||
${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS})
|
||||
set_target_link_flags(${name}
|
||||
${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS} ${LIB_LINKFLAGS})
|
||||
set_property(TARGET ${name} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
# Setup correct output directory in the build tree.
|
||||
set_target_properties(${name} PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
|
||||
LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
|
||||
if ("${LIB_OUTPUT_NAME}" STREQUAL "")
|
||||
set_target_properties(${name} PROPERTIES
|
||||
OUTPUT_NAME ${name}${COMPILER_RT_OS_SUFFIX})
|
||||
else()
|
||||
set_target_properties(${name} PROPERTIES
|
||||
OUTPUT_NAME ${LIB_OUTPUT_NAME})
|
||||
endif()
|
||||
# Add installation command.
|
||||
install(TARGETS ${name}
|
||||
ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}
|
||||
LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}
|
||||
RUNTIME DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
else()
|
||||
message(FATAL_ERROR "Archtecture ${arch} can't be targeted")
|
||||
# LINK_LIBS <linked libraries> (only for shared library)
|
||||
# OBJECT_LIBS <object libraries to use as sources>
|
||||
# PARENT_TARGET <convenience parent target>)
|
||||
function(add_compiler_rt_runtime name type)
|
||||
if(NOT type MATCHES "^(STATIC|SHARED)$")
|
||||
message(FATAL_ERROR "type argument must be STATIC or SHARED")
|
||||
return()
|
||||
endif()
|
||||
cmake_parse_arguments(LIB
|
||||
""
|
||||
"PARENT_TARGET"
|
||||
"OS;ARCHS;SOURCES;CFLAGS;LINKFLAGS;DEFS;LINK_LIBS;OBJECT_LIBS"
|
||||
${ARGN})
|
||||
set(libnames)
|
||||
if(APPLE)
|
||||
foreach(os ${LIB_OS})
|
||||
if(type STREQUAL "STATIC")
|
||||
set(libname "${name}_${os}")
|
||||
else()
|
||||
set(libname "${name}_${os}_dynamic")
|
||||
set(extra_linkflags_${libname} ${DARWIN_${os}_LINKFLAGS} ${LIB_LINKFLAGS})
|
||||
endif()
|
||||
list_union(LIB_ARCHS_${libname} DARWIN_${os}_ARCHS LIB_ARCHS)
|
||||
if(LIB_ARCHS_${libname})
|
||||
list(APPEND libnames ${libname})
|
||||
set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS} ${LIB_CFLAGS})
|
||||
set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX})
|
||||
set(sources_${libname} ${LIB_SOURCES})
|
||||
format_object_libs(sources_${libname} ${os} ${LIB_OBJECT_LIBS})
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
foreach(arch ${LIB_ARCHS})
|
||||
if(NOT CAN_TARGET_${arch})
|
||||
message(FATAL_ERROR "Architecture ${arch} can't be targeted")
|
||||
return()
|
||||
endif()
|
||||
if(type STREQUAL "STATIC")
|
||||
set(libname "${name}-${arch}")
|
||||
set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX})
|
||||
else()
|
||||
set(libname "${name}-dynamic-${arch}")
|
||||
set(extra_linkflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS} ${LIB_LINKFLAGS})
|
||||
if(WIN32)
|
||||
set(output_name_${libname} ${name}_dynamic-${arch}${COMPILER_RT_OS_SUFFIX})
|
||||
else()
|
||||
set(output_name_${libname} ${name}-${arch}${COMPILER_RT_OS_SUFFIX})
|
||||
endif()
|
||||
endif()
|
||||
set(sources_${libname} ${LIB_SOURCES})
|
||||
format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS})
|
||||
set(libnames ${libnames} ${libname})
|
||||
set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS})
|
||||
endforeach()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Same as add_compiler_rt_runtime(... STATIC), but creates a universal library
|
||||
# for several architectures.
|
||||
# add_compiler_rt_osx_static_runtime(<name> ARCHS <architectures>
|
||||
# SOURCES <source files>
|
||||
# CFLAGS <compile flags>
|
||||
# DEFS <compile definitions>)
|
||||
macro(add_compiler_rt_osx_static_runtime name)
|
||||
cmake_parse_arguments(LIB "" "" "ARCHS;SOURCES;CFLAGS;DEFS" ${ARGN})
|
||||
add_library(${name} STATIC ${LIB_SOURCES})
|
||||
set_target_compile_flags(${name} ${LIB_CFLAGS})
|
||||
set_property(TARGET ${name} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
set_target_properties(${name} PROPERTIES
|
||||
OSX_ARCHITECTURES "${LIB_ARCHS}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
|
||||
install(TARGETS ${name}
|
||||
ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
endmacro()
|
||||
if(NOT libnames)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Adds dynamic runtime library on osx/iossim, which supports multiple
|
||||
# architectures.
|
||||
# add_compiler_rt_darwin_dynamic_runtime(<name> <os>
|
||||
# ARCHS <architectures>
|
||||
# SOURCES <source files>
|
||||
# CFLAGS <compile flags>
|
||||
# DEFS <compile definitions>
|
||||
# LINKFLAGS <link flags>)
|
||||
macro(add_compiler_rt_darwin_dynamic_runtime name os)
|
||||
cmake_parse_arguments(LIB "" "" "ARCHS;SOURCES;CFLAGS;DEFS;LINKFLAGS" ${ARGN})
|
||||
add_library(${name} SHARED ${LIB_SOURCES})
|
||||
set_target_compile_flags(${name} ${LIB_CFLAGS} ${DARWIN_${os}_CFLAGS})
|
||||
set_target_link_flags(${name} ${LIB_LINKFLAGS} ${DARWIN_${os}_LINKFLAGS})
|
||||
set_property(TARGET ${name} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
set_target_properties(${name} PROPERTIES
|
||||
OSX_ARCHITECTURES "${LIB_ARCHS}"
|
||||
LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
|
||||
install(TARGETS ${name}
|
||||
LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
endmacro()
|
||||
if(LIB_PARENT_TARGET)
|
||||
set(COMPONENT_OPTION COMPONENT ${LIB_PARENT_TARGET})
|
||||
endif()
|
||||
|
||||
foreach(libname ${libnames})
|
||||
add_library(${libname} ${type} ${sources_${libname}})
|
||||
set_target_compile_flags(${libname} ${extra_cflags_${libname}})
|
||||
set_target_link_flags(${libname} ${extra_linkflags_${libname}})
|
||||
set_property(TARGET ${libname} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
set_target_properties(${libname} PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
|
||||
LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
|
||||
set_target_properties(${libname} PROPERTIES
|
||||
OUTPUT_NAME ${output_name_${libname}})
|
||||
if(LIB_LINK_LIBS AND ${type} STREQUAL "SHARED")
|
||||
target_link_libraries(${libname} ${LIB_LINK_LIBS})
|
||||
endif()
|
||||
install(TARGETS ${libname}
|
||||
ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}
|
||||
${COMPONENT_OPTION}
|
||||
LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}
|
||||
${COMPONENT_OPTION}
|
||||
RUNTIME DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}
|
||||
${COMPONENT_OPTION})
|
||||
if(APPLE)
|
||||
set_target_properties(${libname} PROPERTIES
|
||||
OSX_ARCHITECTURES "${LIB_ARCHS_${libname}}")
|
||||
endif()
|
||||
|
||||
if(type STREQUAL "SHARED")
|
||||
rt_externalize_debuginfo(${libname})
|
||||
endif()
|
||||
endforeach()
|
||||
if(LIB_PARENT_TARGET)
|
||||
add_dependencies(${LIB_PARENT_TARGET} ${libnames})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(COMPILER_RT_TEST_CFLAGS)
|
||||
|
||||
@ -248,7 +288,8 @@ macro(add_custom_libcxx name prefix)
|
||||
ExternalProject_Add(${name}
|
||||
PREFIX ${prefix}
|
||||
SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH}
|
||||
CMAKE_ARGS -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER}
|
||||
CMAKE_ARGS -DCMAKE_MAKE_PROGRAM:STRING=${CMAKE_MAKE_PROGRAM}
|
||||
-DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_COMPILER}
|
||||
-DCMAKE_C_FLAGS=${LIBCXX_CFLAGS}
|
||||
-DCMAKE_CXX_FLAGS=${LIBCXX_CFLAGS}
|
||||
@ -273,3 +314,24 @@ macro(add_custom_libcxx name prefix)
|
||||
DEPENDS ${LIBCXX_DEPS}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
function(rt_externalize_debuginfo name)
|
||||
if(NOT COMPILER_RT_EXTERNALIZE_DEBUGINFO)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
if(CMAKE_CXX_FLAGS MATCHES "-flto"
|
||||
OR CMAKE_CXX_FLAGS_${uppercase_CMAKE_BUILD_TYPE} MATCHES "-flto")
|
||||
|
||||
set(lto_object ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${name}-lto.o)
|
||||
set_property(TARGET ${name} APPEND_STRING PROPERTY
|
||||
LINK_FLAGS " -Wl,-object_path_lto -Wl,${lto_object}")
|
||||
endif()
|
||||
add_custom_command(TARGET ${name} POST_BUILD
|
||||
COMMAND xcrun dsymutil $<TARGET_FILE:${name}>
|
||||
COMMAND xcrun strip -Sl $<TARGET_FILE:${name}>)
|
||||
else()
|
||||
message(FATAL_ERROR "COMPILER_RT_EXTERNALIZE_DEBUGINFO isn't implemented for non-darwin platforms!")
|
||||
endif()
|
||||
endfunction()
|
||||
|
@ -49,6 +49,10 @@ macro(clang_compile object_file source)
|
||||
translate_msvc_cflags(global_flags "${global_flags}")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set(global_flags ${OSX_SYSROOT_FLAG} ${global_flags})
|
||||
endif()
|
||||
|
||||
# Ignore unknown warnings. CMAKE_CXX_FLAGS may contain GCC-specific options
|
||||
# which are not supported by Clang.
|
||||
list(APPEND global_flags -Wno-unknown-warning-option)
|
||||
@ -72,7 +76,7 @@ endmacro()
|
||||
macro(clang_compiler_add_cxx_check)
|
||||
if (APPLE)
|
||||
set(CMD
|
||||
"echo '#include <iostream>' | ${COMPILER_RT_TEST_COMPILER} -E -x c++ - > /dev/null"
|
||||
"echo '#include <iostream>' | ${COMPILER_RT_TEST_COMPILER} ${OSX_SYSROOT_FLAG} -E -x c++ - > /dev/null"
|
||||
"if [ $? != 0 ] "
|
||||
" then echo"
|
||||
" echo 'Your just-built clang cannot find C++ headers, which are needed to build and run compiler-rt tests.'"
|
||||
|
453
cmake/Modules/CompilerRTDarwinUtils.cmake
Normal file
453
cmake/Modules/CompilerRTDarwinUtils.cmake
Normal file
@ -0,0 +1,453 @@
|
||||
# On OS X SDKs can be installed anywhere on the base system and xcode-select can
|
||||
# set the default Xcode to use. This function finds the SDKs that are present in
|
||||
# the current Xcode.
|
||||
function(find_darwin_sdk_dir var sdk_name)
|
||||
# Let's first try the internal SDK, otherwise use the public SDK.
|
||||
execute_process(
|
||||
COMMAND xcodebuild -version -sdk ${sdk_name}.internal Path
|
||||
OUTPUT_VARIABLE var_internal
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_FILE /dev/null
|
||||
)
|
||||
if("" STREQUAL "${var_internal}")
|
||||
execute_process(
|
||||
COMMAND xcodebuild -version -sdk ${sdk_name} Path
|
||||
OUTPUT_VARIABLE var_internal
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_FILE /dev/null
|
||||
)
|
||||
endif()
|
||||
set(${var} ${var_internal} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# There isn't a clear mapping of what architectures are supported with a given
|
||||
# target platform, but ld's version output does list the architectures it can
|
||||
# link for.
|
||||
function(darwin_get_toolchain_supported_archs output_var)
|
||||
execute_process(
|
||||
COMMAND ld -v
|
||||
ERROR_VARIABLE LINKER_VERSION)
|
||||
|
||||
string(REGEX MATCH "configured to support archs: ([^\n]+)"
|
||||
ARCHES_MATCHED "${LINKER_VERSION}")
|
||||
if(ARCHES_MATCHED)
|
||||
set(ARCHES "${CMAKE_MATCH_1}")
|
||||
message(STATUS "Got ld supported ARCHES: ${ARCHES}")
|
||||
string(REPLACE " " ";" ARCHES ${ARCHES})
|
||||
else()
|
||||
# If auto-detecting fails, fall back to a default set
|
||||
message(WARNING "Detecting supported architectures from 'ld -v' failed. Returning default set.")
|
||||
set(ARCHES "i386;x86_64;armv7;armv7s;arm64")
|
||||
endif()
|
||||
|
||||
set(${output_var} ${ARCHES} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# This function takes an OS and a list of architectures and identifies the
|
||||
# subset of the architectures list that the installed toolchain can target.
|
||||
function(darwin_test_archs os valid_archs)
|
||||
if(${valid_archs})
|
||||
message(STATUS "Using cached valid architectures for ${os}.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(archs ${ARGN})
|
||||
message(STATUS "Finding valid architectures for ${os}...")
|
||||
set(SIMPLE_CPP ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.cpp)
|
||||
file(WRITE ${SIMPLE_CPP} "#include <iostream>\nint main() { std::cout << std::endl; return 0; }\n")
|
||||
|
||||
set(os_linker_flags)
|
||||
foreach(flag ${DARWIN_${os}_LINKFLAGS})
|
||||
set(os_linker_flags "${os_linker_flags} ${flag}")
|
||||
endforeach()
|
||||
|
||||
# The simple program will build for x86_64h on the simulator because it is
|
||||
# compatible with x86_64 libraries (mostly), but since x86_64h isn't actually
|
||||
# a valid or useful architecture for the iOS simulator we should drop it.
|
||||
if(${os} STREQUAL "iossim")
|
||||
list(REMOVE_ITEM archs "x86_64h")
|
||||
endif()
|
||||
|
||||
set(working_archs)
|
||||
foreach(arch ${archs})
|
||||
|
||||
set(arch_linker_flags "-arch ${arch} ${os_linker_flags}")
|
||||
try_compile(CAN_TARGET_${os}_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_CPP}
|
||||
COMPILE_DEFINITIONS "-v -arch ${arch}" ${DARWIN_${os}_CFLAGS}
|
||||
CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS=${arch_linker_flags}"
|
||||
OUTPUT_VARIABLE TEST_OUTPUT)
|
||||
if(${CAN_TARGET_${os}_${arch}})
|
||||
list(APPEND working_archs ${arch})
|
||||
else()
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Testing compiler for supporting ${os}-${arch}:\n"
|
||||
"${TEST_OUTPUT}\n")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${valid_archs} ${working_archs}
|
||||
CACHE STRING "List of valid architectures for platform ${os}.")
|
||||
endfunction()
|
||||
|
||||
# This function checks the host cpusubtype to see if it is post-haswell. Haswell
|
||||
# and later machines can run x86_64h binaries. Haswell is cpusubtype 8.
|
||||
function(darwin_filter_host_archs input output)
|
||||
list_union(tmp_var DARWIN_osx_ARCHS ${input})
|
||||
execute_process(
|
||||
COMMAND sysctl hw.cpusubtype
|
||||
OUTPUT_VARIABLE SUBTYPE)
|
||||
|
||||
string(REGEX MATCH "hw.cpusubtype: ([0-9]*)"
|
||||
SUBTYPE_MATCHED "${SUBTYPE}")
|
||||
set(HASWELL_SUPPORTED Off)
|
||||
if(SUBTYPE_MATCHED)
|
||||
if(${CMAKE_MATCH_1} GREATER 7)
|
||||
set(HASWELL_SUPPORTED On)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT HASWELL_SUPPORTED)
|
||||
list(REMOVE_ITEM tmp_var x86_64h)
|
||||
endif()
|
||||
set(${output} ${tmp_var} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Read and process the exclude file into a list of symbols
|
||||
function(darwin_read_list_from_file output_var file)
|
||||
if(EXISTS ${file})
|
||||
file(READ ${file} EXCLUDES)
|
||||
string(REPLACE "\n" ";" EXCLUDES ${EXCLUDES})
|
||||
set(${output_var} ${EXCLUDES} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# this function takes an OS, architecture and minimum version and provides a
|
||||
# list of builtin functions to exclude
|
||||
function(darwin_find_excluded_builtins_list output_var)
|
||||
cmake_parse_arguments(LIB
|
||||
""
|
||||
"OS;ARCH;MIN_VERSION"
|
||||
""
|
||||
${ARGN})
|
||||
|
||||
if(NOT LIB_OS OR NOT LIB_ARCH)
|
||||
message(FATAL_ERROR "Must specify OS and ARCH to darwin_find_excluded_builtins_list!")
|
||||
endif()
|
||||
|
||||
darwin_read_list_from_file(${LIB_OS}_BUILTINS
|
||||
${DARWIN_EXCLUDE_DIR}/${LIB_OS}.txt)
|
||||
darwin_read_list_from_file(${LIB_OS}_${LIB_ARCH}_BASE_BUILTINS
|
||||
${DARWIN_EXCLUDE_DIR}/${LIB_OS}-${LIB_ARCH}.txt)
|
||||
|
||||
if(LIB_MIN_VERSION)
|
||||
file(GLOB builtin_lists ${DARWIN_EXCLUDE_DIR}/${LIB_OS}*-${LIB_ARCH}.txt)
|
||||
foreach(builtin_list ${builtin_lists})
|
||||
string(REGEX MATCH "${LIB_OS}([0-9\\.]*)-${LIB_ARCH}.txt" VERSION_MATCHED "${builtin_list}")
|
||||
if (VERSION_MATCHED AND NOT CMAKE_MATCH_1 VERSION_LESS LIB_MIN_VERSION)
|
||||
if(NOT smallest_version)
|
||||
set(smallest_version ${CMAKE_MATCH_1})
|
||||
elseif(CMAKE_MATCH_1 VERSION_LESS smallest_version)
|
||||
set(smallest_version ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(smallest_version)
|
||||
darwin_read_list_from_file(${LIB_ARCH}_${LIB_OS}_BUILTINS
|
||||
${DARWIN_EXCLUDE_DIR}/${LIB_OS}${smallest_version}-${LIB_ARCH}.txt)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(${output_var}
|
||||
${${LIB_ARCH}_${LIB_OS}_BUILTINS}
|
||||
${${LIB_OS}_${LIB_ARCH}_BASE_BUILTINS}
|
||||
${${LIB_OS}_BUILTINS} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# adds a single builtin library for a single OS & ARCH
|
||||
macro(darwin_add_builtin_library name suffix)
|
||||
cmake_parse_arguments(LIB
|
||||
""
|
||||
"PARENT_TARGET;OS;ARCH"
|
||||
"SOURCES;CFLAGS;DEFS"
|
||||
${ARGN})
|
||||
set(libname "${name}.${suffix}_${LIB_ARCH}_${LIB_OS}")
|
||||
add_library(${libname} STATIC ${LIB_SOURCES})
|
||||
if(DARWIN_${LIB_OS}_SYSROOT)
|
||||
set(sysroot_flag -isysroot ${DARWIN_${LIB_OS}_SYSROOT})
|
||||
endif()
|
||||
set_target_compile_flags(${libname}
|
||||
${sysroot_flag}
|
||||
${DARWIN_${LIB_OS}_BUILTIN_MIN_VER_FLAG}
|
||||
${LIB_CFLAGS})
|
||||
set_property(TARGET ${libname} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
set_target_properties(${libname} PROPERTIES
|
||||
OUTPUT_NAME ${libname}${COMPILER_RT_OS_SUFFIX})
|
||||
set_target_properties(${libname} PROPERTIES
|
||||
OSX_ARCHITECTURES ${LIB_ARCH})
|
||||
|
||||
if(LIB_PARENT_TARGET)
|
||||
add_dependencies(${LIB_PARENT_TARGET} ${libname})
|
||||
endif()
|
||||
|
||||
list(APPEND ${LIB_OS}_${suffix}_libs ${libname})
|
||||
list(APPEND ${LIB_OS}_${suffix}_lipo_flags -arch ${arch} $<TARGET_FILE:${libname}>)
|
||||
endmacro()
|
||||
|
||||
function(darwin_lipo_libs name)
|
||||
cmake_parse_arguments(LIB
|
||||
""
|
||||
"PARENT_TARGET;OUTPUT_DIR;INSTALL_DIR"
|
||||
"LIPO_FLAGS;DEPENDS"
|
||||
${ARGN})
|
||||
if(LIB_DEPENDS AND LIB_LIPO_FLAGS)
|
||||
add_custom_command(OUTPUT ${LIB_OUTPUT_DIR}/lib${name}.a
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_OUTPUT_DIR}
|
||||
COMMAND lipo -output
|
||||
${LIB_OUTPUT_DIR}/lib${name}.a
|
||||
-create ${LIB_LIPO_FLAGS}
|
||||
DEPENDS ${LIB_DEPENDS}
|
||||
)
|
||||
add_custom_target(${name}
|
||||
DEPENDS ${LIB_OUTPUT_DIR}/lib${name}.a)
|
||||
add_dependencies(${LIB_PARENT_TARGET} ${name})
|
||||
install(FILES ${LIB_OUTPUT_DIR}/lib${name}.a
|
||||
DESTINATION ${LIB_INSTALL_DIR})
|
||||
else()
|
||||
message(WARNING "Not generating lipo target for ${name} because no input libraries exist.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Filter out generic versions of routines that are re-implemented in
|
||||
# architecture specific manner. This prevents multiple definitions of the
|
||||
# same symbols, making the symbol selection non-deterministic.
|
||||
function(darwin_filter_builtin_sources output_var exclude_or_include excluded_list)
|
||||
if(exclude_or_include STREQUAL "EXCLUDE")
|
||||
set(filter_action GREATER)
|
||||
set(filter_value -1)
|
||||
elseif(exclude_or_include STREQUAL "INCLUDE")
|
||||
set(filter_action LESS)
|
||||
set(filter_value 0)
|
||||
else()
|
||||
message(FATAL_ERROR "darwin_filter_builtin_sources called without EXCLUDE|INCLUDE")
|
||||
endif()
|
||||
|
||||
set(intermediate ${ARGN})
|
||||
foreach (_file ${intermediate})
|
||||
get_filename_component(_name_we ${_file} NAME_WE)
|
||||
list(FIND ${excluded_list} ${_name_we} _found)
|
||||
if(_found ${filter_action} ${filter_value})
|
||||
list(REMOVE_ITEM intermediate ${_file})
|
||||
elseif(${_file} MATCHES ".*/.*\\.S" OR ${_file} MATCHES ".*/.*\\.c")
|
||||
get_filename_component(_name ${_file} NAME)
|
||||
string(REPLACE ".S" ".c" _cname "${_name}")
|
||||
list(REMOVE_ITEM intermediate ${_cname})
|
||||
endif ()
|
||||
endforeach ()
|
||||
set(${output_var} ${intermediate} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(darwin_add_eprintf_library)
|
||||
cmake_parse_arguments(LIB
|
||||
""
|
||||
""
|
||||
"CFLAGS"
|
||||
${ARGN})
|
||||
|
||||
add_library(clang_rt.eprintf STATIC eprintf.c)
|
||||
set_target_compile_flags(clang_rt.eprintf
|
||||
-isysroot ${DARWIN_osx_SYSROOT}
|
||||
${DARWIN_osx_BUILTIN_MIN_VER_FLAG}
|
||||
-arch i386
|
||||
${LIB_CFLAGS})
|
||||
set_target_properties(clang_rt.eprintf PROPERTIES
|
||||
OUTPUT_NAME clang_rt.eprintf${COMPILER_RT_OS_SUFFIX})
|
||||
set_target_properties(clang_rt.eprintf PROPERTIES
|
||||
OSX_ARCHITECTURES i386)
|
||||
add_dependencies(builtins clang_rt.eprintf)
|
||||
set_target_properties(clang_rt.eprintf PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
|
||||
install(TARGETS clang_rt.eprintf
|
||||
ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
endfunction()
|
||||
|
||||
# Generates builtin libraries for all operating systems specified in ARGN. Each
|
||||
# OS library is constructed by lipo-ing together single-architecture libraries.
|
||||
macro(darwin_add_builtin_libraries)
|
||||
set(DARWIN_EXCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Darwin-excludes)
|
||||
|
||||
set(CFLAGS "-fPIC -O3 -fvisibility=hidden -DVISIBILITY_HIDDEN -Wall -fomit-frame-pointer")
|
||||
set(CMAKE_C_FLAGS "")
|
||||
set(CMAKE_CXX_FLAGS "")
|
||||
set(CMAKE_ASM_FLAGS "")
|
||||
|
||||
set(PROFILE_SOURCES ../profile/InstrProfiling
|
||||
../profile/InstrProfilingBuffer
|
||||
../profile/InstrProfilingPlatformDarwin)
|
||||
foreach (os ${ARGN})
|
||||
list_union(DARWIN_BUILTIN_ARCHS DARWIN_${os}_ARCHS BUILTIN_SUPPORTED_ARCH)
|
||||
foreach (arch ${DARWIN_BUILTIN_ARCHS})
|
||||
darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS
|
||||
OS ${os}
|
||||
ARCH ${arch}
|
||||
MIN_VERSION ${DARWIN_${os}_BUILTIN_MIN_VER})
|
||||
|
||||
darwin_filter_builtin_sources(filtered_sources
|
||||
EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS
|
||||
${${arch}_SOURCES})
|
||||
|
||||
darwin_add_builtin_library(clang_rt builtins
|
||||
OS ${os}
|
||||
ARCH ${arch}
|
||||
SOURCES ${filtered_sources}
|
||||
CFLAGS ${CFLAGS} -arch ${arch}
|
||||
PARENT_TARGET builtins)
|
||||
endforeach()
|
||||
|
||||
# Don't build cc_kext libraries for simulator platforms
|
||||
if(NOT DARWIN_${os}_SKIP_CC_KEXT)
|
||||
foreach (arch ${DARWIN_BUILTIN_ARCHS})
|
||||
# By not specifying MIN_VERSION this only reads the OS and OS-arch lists.
|
||||
# We don't want to filter out the builtins that are present in libSystem
|
||||
# because kexts can't link libSystem.
|
||||
darwin_find_excluded_builtins_list(${arch}_${os}_EXCLUDED_BUILTINS
|
||||
OS ${os}
|
||||
ARCH ${arch})
|
||||
|
||||
darwin_filter_builtin_sources(filtered_sources
|
||||
EXCLUDE ${arch}_${os}_EXCLUDED_BUILTINS
|
||||
${${arch}_SOURCES})
|
||||
|
||||
# In addition to the builtins cc_kext includes some profile sources
|
||||
darwin_add_builtin_library(clang_rt cc_kext
|
||||
OS ${os}
|
||||
ARCH ${arch}
|
||||
SOURCES ${filtered_sources} ${PROFILE_SOURCES}
|
||||
CFLAGS ${CFLAGS} -arch ${arch} -mkernel
|
||||
DEFS KERNEL_USE
|
||||
PARENT_TARGET builtins)
|
||||
endforeach()
|
||||
set(archive_name clang_rt.cc_kext_${os})
|
||||
if(${os} STREQUAL "osx")
|
||||
set(archive_name clang_rt.cc_kext)
|
||||
endif()
|
||||
darwin_lipo_libs(${archive_name}
|
||||
PARENT_TARGET builtins
|
||||
LIPO_FLAGS ${${os}_cc_kext_lipo_flags}
|
||||
DEPENDS ${${os}_cc_kext_libs}
|
||||
OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
|
||||
INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
darwin_add_eprintf_library(CFLAGS ${CFLAGS})
|
||||
|
||||
# We put the x86 sim slices into the archives for their base OS
|
||||
foreach (os ${ARGN})
|
||||
if(NOT ${os} MATCHES ".*sim$")
|
||||
darwin_lipo_libs(clang_rt.${os}
|
||||
PARENT_TARGET builtins
|
||||
LIPO_FLAGS ${${os}_builtins_lipo_flags} ${${os}sim_builtins_lipo_flags}
|
||||
DEPENDS ${${os}_builtins_libs} ${${os}sim_builtins_libs}
|
||||
OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR}
|
||||
INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
endif()
|
||||
endforeach()
|
||||
darwin_add_embedded_builtin_libraries()
|
||||
endmacro()
|
||||
|
||||
macro(darwin_add_embedded_builtin_libraries)
|
||||
# this is a hacky opt-out. If you can't target both intel and arm
|
||||
# architectures we bail here.
|
||||
set(DARWIN_SOFT_FLOAT_ARCHS armv6m armv7m armv7em armv7)
|
||||
set(DARWIN_HARD_FLOAT_ARCHS armv7em armv7)
|
||||
if(COMPILER_RT_SUPPORTED_ARCH MATCHES ".*armv.*")
|
||||
list(FIND COMPILER_RT_SUPPORTED_ARCH i386 i386_idx)
|
||||
if(i386_idx GREATER -1)
|
||||
list(APPEND DARWIN_HARD_FLOAT_ARCHS i386)
|
||||
endif()
|
||||
|
||||
list(FIND COMPILER_RT_SUPPORTED_ARCH x86_64 x86_64_idx)
|
||||
if(x86_64_idx GREATER -1)
|
||||
list(APPEND DARWIN_HARD_FLOAT_ARCHS x86_64)
|
||||
endif()
|
||||
|
||||
set(MACHO_SYM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/macho_embedded)
|
||||
|
||||
set(CFLAGS "-Oz -Wall -fomit-frame-pointer -ffreestanding")
|
||||
set(CMAKE_C_FLAGS "")
|
||||
set(CMAKE_CXX_FLAGS "")
|
||||
set(CMAKE_ASM_FLAGS "")
|
||||
|
||||
set(SOFT_FLOAT_FLAG -mfloat-abi=soft)
|
||||
set(HARD_FLOAT_FLAG -mfloat-abi=hard)
|
||||
|
||||
set(ENABLE_PIC Off)
|
||||
set(PIC_FLAG -fPIC)
|
||||
set(STATIC_FLAG -static)
|
||||
|
||||
set(DARWIN_macho_embedded_ARCHS armv6m armv7m armv7em armv7 i386 x86_64)
|
||||
|
||||
set(DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR
|
||||
${COMPILER_RT_OUTPUT_DIR}/lib/macho_embedded)
|
||||
set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR
|
||||
${COMPILER_RT_INSTALL_PATH}/lib/macho_embedded)
|
||||
|
||||
set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi")
|
||||
set(CFLAGS_i386 "-march=pentium")
|
||||
|
||||
darwin_read_list_from_file(common_FUNCTIONS ${MACHO_SYM_DIR}/common.txt)
|
||||
darwin_read_list_from_file(thumb2_FUNCTIONS ${MACHO_SYM_DIR}/thumb2.txt)
|
||||
darwin_read_list_from_file(thumb2_64_FUNCTIONS ${MACHO_SYM_DIR}/thumb2-64.txt)
|
||||
darwin_read_list_from_file(arm_FUNCTIONS ${MACHO_SYM_DIR}/arm.txt)
|
||||
darwin_read_list_from_file(i386_FUNCTIONS ${MACHO_SYM_DIR}/i386.txt)
|
||||
|
||||
|
||||
set(armv6m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS})
|
||||
set(armv7m_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS})
|
||||
set(armv7em_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS})
|
||||
set(armv7_FUNCTIONS ${common_FUNCTIONS} ${arm_FUNCTIONS} ${thumb2_FUNCTIONS} ${thumb2_64_FUNCTIONS})
|
||||
set(i386_FUNCTIONS ${common_FUNCTIONS} ${i386_FUNCTIONS})
|
||||
set(x86_64_FUNCTIONS ${common_FUNCTIONS})
|
||||
|
||||
foreach(arch ${DARWIN_macho_embedded_ARCHS})
|
||||
darwin_filter_builtin_sources(${arch}_filtered_sources
|
||||
INCLUDE ${arch}_FUNCTIONS
|
||||
${${arch}_SOURCES})
|
||||
if(NOT ${arch}_filtered_sources)
|
||||
message("${arch}_SOURCES: ${${arch}_SOURCES}")
|
||||
message("${arch}_FUNCTIONS: ${${arch}_FUNCTIONS}")
|
||||
message(FATAL_ERROR "Empty filtered sources!")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(float_type SOFT HARD)
|
||||
foreach(type PIC STATIC)
|
||||
string(TOLOWER "${float_type}_${type}" lib_suffix)
|
||||
foreach(arch ${DARWIN_${float_type}_FLOAT_ARCHS})
|
||||
set(DARWIN_macho_embedded_SYSROOT ${DARWIN_osx_SYSROOT})
|
||||
set(float_flag)
|
||||
if(${arch} MATCHES "^arm")
|
||||
# x86 targets are hard float by default, but the complain about the
|
||||
# float ABI flag, so don't pass it unless we're targeting arm.
|
||||
set(float_flag ${${float_type}_FLOAT_FLAG})
|
||||
endif()
|
||||
darwin_add_builtin_library(clang_rt ${lib_suffix}
|
||||
OS macho_embedded
|
||||
ARCH ${arch}
|
||||
SOURCES ${${arch}_filtered_sources}
|
||||
CFLAGS ${CFLAGS} -arch ${arch} ${${type}_FLAG} ${float_flag} ${CFLAGS_${arch}}
|
||||
PARENT_TARGET builtins)
|
||||
endforeach()
|
||||
foreach(lib ${macho_embedded_${lib_suffix}_libs})
|
||||
set_target_properties(${lib} PROPERTIES LINKER_LANGUAGE C)
|
||||
endforeach()
|
||||
darwin_lipo_libs(clang_rt.${lib_suffix}
|
||||
PARENT_TARGET builtins
|
||||
LIPO_FLAGS ${macho_embedded_${lib_suffix}_lipo_flags}
|
||||
DEPENDS ${macho_embedded_${lib_suffix}_libs}
|
||||
OUTPUT_DIR ${DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR}
|
||||
INSTALL_DIR ${DARWIN_macho_embedded_LIBRARY_INSTALL_DIR})
|
||||
endforeach()
|
||||
endforeach()
|
||||
endif()
|
||||
endmacro()
|
@ -57,3 +57,13 @@ macro(append_have_file_definition filename varname list)
|
||||
endif()
|
||||
list(APPEND ${list} "${varname}=${${varname}}")
|
||||
endmacro()
|
||||
|
||||
macro(list_union output input1 input2)
|
||||
set(${output})
|
||||
foreach(it ${${input1}})
|
||||
list(FIND ${input2} ${it} index)
|
||||
if( NOT (index EQUAL -1))
|
||||
list(APPEND ${output} ${it})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
@ -4,46 +4,60 @@ set(SANITIZER_GEN_DYNAMIC_LIST
|
||||
set(SANITIZER_LINT_SCRIPT
|
||||
${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/scripts/check_lint.sh)
|
||||
|
||||
# Create a target "<name>-symbols" that would generate the list of symbols
|
||||
# that need to be exported from sanitizer runtime "<name>". Function
|
||||
# Create a target "<name>-<arch>-symbols" that would generate the list of
|
||||
# symbols that need to be exported from sanitizer runtime "<name>". Function
|
||||
# interceptors are exported automatically, user can also provide files with
|
||||
# symbol names that should be exported as well.
|
||||
# add_sanitizer_rt_symbols(<name> <files with extra symbols to export>)
|
||||
# add_sanitizer_rt_symbols(<name>
|
||||
# ARCHS <architectures>
|
||||
# PARENT_TARGET <convenience parent target>
|
||||
# EXTRA <files with extra symbols to export>)
|
||||
macro(add_sanitizer_rt_symbols name)
|
||||
set(stamp ${CMAKE_CURRENT_BINARY_DIR}/${name}.syms-stamp)
|
||||
set(extra_args)
|
||||
foreach(arg ${ARGN})
|
||||
list(APPEND extra_args "--extra" ${arg})
|
||||
endforeach()
|
||||
add_custom_command(OUTPUT ${stamp}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${SANITIZER_GEN_DYNAMIC_LIST} ${extra_args} $<TARGET_FILE:${name}>
|
||||
> $<TARGET_FILE:${name}>.syms
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${stamp}
|
||||
DEPENDS ${name} ${SANITIZER_GEN_DYNAMIC_LIST} ${ARGN}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating exported symbols for ${name}"
|
||||
VERBATIM)
|
||||
add_custom_target(${name}-symbols ALL
|
||||
DEPENDS ${stamp}
|
||||
SOURCES ${SANITIZER_GEN_DYNAMIC_LIST} ${ARGN})
|
||||
cmake_parse_arguments(ARG
|
||||
""
|
||||
"PARENT_TARGET"
|
||||
"ARCHS;EXTRA"
|
||||
${ARGN})
|
||||
foreach(arch ${ARG_ARCHS})
|
||||
set(target_name ${name}-${arch})
|
||||
set(stamp ${CMAKE_CURRENT_BINARY_DIR}/${target_name}.syms-stamp)
|
||||
set(extra_args)
|
||||
foreach(arg ${ARG_EXTRA})
|
||||
list(APPEND extra_args "--extra" ${arg})
|
||||
endforeach()
|
||||
add_custom_command(OUTPUT ${stamp}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${SANITIZER_GEN_DYNAMIC_LIST} ${extra_args} $<TARGET_FILE:${target_name}>
|
||||
> $<TARGET_FILE:${target_name}>.syms
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${stamp}
|
||||
DEPENDS ${target_name} ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating exported symbols for ${target_name}"
|
||||
VERBATIM)
|
||||
add_custom_target(${target_name}-symbols ALL
|
||||
DEPENDS ${stamp}
|
||||
SOURCES ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA})
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
|
||||
install(FILES $<TARGET_FILE:${name}>.syms
|
||||
DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
else()
|
||||
# Per-config install location.
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
foreach(c ${CMAKE_CONFIGURATION_TYPES})
|
||||
get_target_property(libfile ${name} LOCATION_${c})
|
||||
install(FILES ${libfile}.syms CONFIGURATIONS ${c}
|
||||
DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
endforeach()
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
|
||||
install(FILES $<TARGET_FILE:${target_name}>.syms
|
||||
DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
else()
|
||||
get_target_property(libfile ${name} LOCATION_${CMAKE_BUILD_TYPE})
|
||||
install(FILES ${libfile}.syms DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
# Per-config install location.
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
foreach(c ${CMAKE_CONFIGURATION_TYPES})
|
||||
get_target_property(libfile ${target_name} LOCATION_${c})
|
||||
install(FILES ${libfile}.syms CONFIGURATIONS ${c}
|
||||
DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
endforeach()
|
||||
else()
|
||||
get_target_property(libfile ${target_name} LOCATION_${CMAKE_BUILD_TYPE})
|
||||
install(FILES ${libfile}.syms DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(ARG_PARENT_TARGET)
|
||||
add_dependencies(${ARG_PARENT_TARGET} ${target_name}-symbols)
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(add_sanitizer_rt_version_list name)
|
||||
|
@ -27,7 +27,14 @@ check_cxx_compiler_flag("-Werror -fno-function-sections" COMPILER_RT_HAS_FNO_FUN
|
||||
check_cxx_compiler_flag(-std=c++11 COMPILER_RT_HAS_STD_CXX11_FLAG)
|
||||
check_cxx_compiler_flag(-ftls-model=initial-exec COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC)
|
||||
check_cxx_compiler_flag(-fno-lto COMPILER_RT_HAS_FNO_LTO_FLAG)
|
||||
check_cxx_compiler_flag(-msse3 COMPILER_RT_HAS_MSSE3_FLAG)
|
||||
check_cxx_compiler_flag("-Werror -msse3" COMPILER_RT_HAS_MSSE3_FLAG)
|
||||
check_cxx_compiler_flag(-std=c99 COMPILER_RT_HAS_STD_C99_FLAG)
|
||||
check_cxx_compiler_flag(--sysroot=. COMPILER_RT_HAS_SYSROOT_FLAG)
|
||||
|
||||
if(NOT WIN32 AND NOT CYGWIN)
|
||||
# MinGW warns if -fvisibility-inlines-hidden is used.
|
||||
check_cxx_compiler_flag("-fvisibility-inlines-hidden" COMPILER_RT_HAS_FVISIBILITY_INLINES_HIDDEN_FLAG)
|
||||
endif()
|
||||
|
||||
check_cxx_compiler_flag(/GR COMPILER_RT_HAS_GR_FLAG)
|
||||
check_cxx_compiler_flag(/GS COMPILER_RT_HAS_GS_FLAG)
|
||||
@ -61,7 +68,7 @@ check_cxx_compiler_flag(/wd4800 COMPILER_RT_HAS_WD4800_FLAG)
|
||||
check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL)
|
||||
|
||||
# Libraries.
|
||||
check_library_exists(c printf "" COMPILER_RT_HAS_LIBC)
|
||||
check_library_exists(c fopen "" COMPILER_RT_HAS_LIBC)
|
||||
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)
|
||||
@ -71,6 +78,7 @@ check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX)
|
||||
# Linker flags.
|
||||
if(ANDROID)
|
||||
check_linker_flag("-Wl,-z,global" COMPILER_RT_HAS_Z_GLOBAL)
|
||||
check_library_exists(log __android_log_write "" COMPILER_RT_HAS_LIBLOG)
|
||||
endif()
|
||||
|
||||
# Architectures.
|
||||
@ -120,8 +128,8 @@ macro(test_target_arch arch def)
|
||||
endif()
|
||||
if(${CAN_TARGET_${arch}})
|
||||
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
|
||||
elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "${arch}" AND
|
||||
COMPILER_RT_HAS_EXPLICIT_TEST_TARGET_TRIPLE)
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "${arch}" AND
|
||||
COMPILER_RT_HAS_EXPLICIT_DEFAULT_TARGET_TRIPLE)
|
||||
# Bail out if we cannot target the architecture we plan to test.
|
||||
message(FATAL_ERROR "Cannot compile for ${arch}:\n${TARGET_${arch}_OUTPUT}")
|
||||
endif()
|
||||
@ -168,12 +176,11 @@ endif()
|
||||
|
||||
# Generate the COMPILER_RT_SUPPORTED_ARCH list.
|
||||
if(ANDROID)
|
||||
# Can't rely on LLVM_NATIVE_ARCH in cross-compilation.
|
||||
# Examine compiler output instead.
|
||||
# Examine compiler output to determine target architecture.
|
||||
detect_target_arch()
|
||||
set(COMPILER_RT_OS_SUFFIX "-android")
|
||||
else()
|
||||
if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
|
||||
elseif(NOT APPLE) # Supported archs for Apple platforms are generated later
|
||||
if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "i[2-6]86|x86|amd64")
|
||||
if(NOT MSVC)
|
||||
test_target_arch(x86_64 "" "-m64")
|
||||
# FIXME: We build runtimes for both i686 and i386, as "clang -m32" may
|
||||
@ -188,42 +195,38 @@ else()
|
||||
test_target_arch(x86_64 "" "")
|
||||
endif()
|
||||
endif()
|
||||
elseif("${LLVM_NATIVE_ARCH}" STREQUAL "PowerPC")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc")
|
||||
TEST_BIG_ENDIAN(HOST_IS_BIG_ENDIAN)
|
||||
if(HOST_IS_BIG_ENDIAN)
|
||||
test_target_arch(powerpc64 "" "-m64")
|
||||
else()
|
||||
test_target_arch(powerpc64le "" "-m64")
|
||||
endif()
|
||||
elseif("${LLVM_NATIVE_ARCH}" STREQUAL "Mips")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mipsel|mips64el")
|
||||
# Gcc doesn't accept -m32/-m64 so we do the next best thing and use
|
||||
# -mips32r2/-mips64r2. We don't use -mips1/-mips3 because we want to match
|
||||
# clang's default CPU's. In the 64-bit case, we must also specify the ABI
|
||||
# since the default ABI differs between gcc and clang.
|
||||
# FIXME: Ideally, we would build the N32 library too.
|
||||
if("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "mipsel|mips64el")
|
||||
# regex for mipsel, mips64el
|
||||
test_target_arch(mipsel "" "-mips32r2" "--target=mipsel-linux-gnu")
|
||||
test_target_arch(mips64el "" "-mips64r2" "-mabi=n64")
|
||||
else()
|
||||
test_target_arch(mips "" "-mips32r2" "--target=mips-linux-gnu")
|
||||
test_target_arch(mips64 "" "-mips64r2" "-mabi=n64")
|
||||
endif()
|
||||
elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "arm")
|
||||
test_target_arch(arm "" "-march=armv7-a")
|
||||
elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "aarch32")
|
||||
test_target_arch(mipsel "" "-mips32r2" "--target=mipsel-linux-gnu")
|
||||
test_target_arch(mips64el "" "-mips64r2" "--target=mips64el-linux-gnu" "-mabi=n64")
|
||||
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=n64")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "arm")
|
||||
test_target_arch(arm "" "-march=armv7-a" "-mfloat-abi=soft")
|
||||
test_target_arch(armhf "" "-march=armv7-a" "-mfloat-abi=hard")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch32")
|
||||
test_target_arch(aarch32 "" "-march=armv8-a")
|
||||
elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "aarch64")
|
||||
elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch64")
|
||||
test_target_arch(aarch64 "" "-march=armv8-a")
|
||||
endif()
|
||||
set(COMPILER_RT_OS_SUFFIX "")
|
||||
endif()
|
||||
|
||||
message(STATUS "Compiler-RT supported architectures: ${COMPILER_RT_SUPPORTED_ARCH}")
|
||||
|
||||
# Takes ${ARGN} and puts only supported architectures in @out_var list.
|
||||
function(filter_available_targets out_var)
|
||||
set(archs)
|
||||
set(archs ${${out_var}})
|
||||
foreach(arch ${ARGN})
|
||||
list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX)
|
||||
if(NOT (ARCH_INDEX EQUAL -1) AND CAN_TARGET_${arch})
|
||||
@ -239,30 +242,264 @@ function(get_target_flags_for_arch arch out_var)
|
||||
if(ARCH_INDEX EQUAL -1)
|
||||
message(FATAL_ERROR "Unsupported architecture: ${arch}")
|
||||
else()
|
||||
set(${out_var} ${TARGET_${arch}_CFLAGS} PARENT_SCOPE)
|
||||
if (NOT APPLE)
|
||||
set(${out_var} ${TARGET_${arch}_CFLAGS} PARENT_SCOPE)
|
||||
else()
|
||||
# This is only called in constructing cflags for tests executing on the
|
||||
# host. This will need to all be cleaned up to support building tests
|
||||
# for cross-targeted hardware (i.e. iOS).
|
||||
set(${out_var} -arch ${arch} PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Architectures supported by compiler-rt libraries.
|
||||
filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
|
||||
x86_64 i386 i686 powerpc64 powerpc64le arm aarch64 mips mips64 mipsel mips64el)
|
||||
# LSan and UBSan common files should be available on all architectures supported
|
||||
# by other sanitizers (even if they build into dummy object files).
|
||||
filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH
|
||||
${SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
filter_available_targets(UBSAN_COMMON_SUPPORTED_ARCH
|
||||
${SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
filter_available_targets(ASAN_SUPPORTED_ARCH
|
||||
x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el)
|
||||
filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
|
||||
filter_available_targets(LSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
|
||||
filter_available_targets(MSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
|
||||
filter_available_targets(PROFILE_SUPPORTED_ARCH x86_64 i386 i686 arm mips mips64
|
||||
mipsel mips64el aarch64 powerpc64 powerpc64le)
|
||||
filter_available_targets(TSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
|
||||
filter_available_targets(UBSAN_SUPPORTED_ARCH x86_64 i386 i686 arm aarch64 mips
|
||||
mipsel mips64 mips64el powerpc64 powerpc64le)
|
||||
filter_available_targets(SAFESTACK_SUPPORTED_ARCH x86_64 i386 i686)
|
||||
set(ARM64 aarch64)
|
||||
set(ARM32 arm armhf)
|
||||
set(X86 i386 i686)
|
||||
set(X86_64 x86_64)
|
||||
set(MIPS32 mips mipsel)
|
||||
set(MIPS64 mips64 mips64el)
|
||||
set(PPC64 powerpc64 powerpc64le)
|
||||
|
||||
if(APPLE)
|
||||
set(ARM64 arm64)
|
||||
set(ARM32 armv7 armv7s)
|
||||
set(X86_64 x86_64 x86_64h)
|
||||
endif()
|
||||
|
||||
set(ALL_BUILTIN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
|
||||
${MIPS32} ${MIPS64})
|
||||
set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64}
|
||||
${ARM32} ${ARM64} ${MIPS32} ${MIPS64})
|
||||
set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
|
||||
${MIPS32} ${MIPS64} ${PPC64})
|
||||
set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
|
||||
set(ALL_LSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
|
||||
set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
|
||||
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC64}
|
||||
${MIPS32} ${MIPS64})
|
||||
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
|
||||
set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
|
||||
${MIPS32} ${MIPS64} ${PPC64})
|
||||
set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64})
|
||||
set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64})
|
||||
|
||||
if(APPLE)
|
||||
include(CompilerRTDarwinUtils)
|
||||
|
||||
# On Darwin if /usr/include doesn't exist, the user probably has Xcode but not
|
||||
# the command line tools. If this is the case, we need to find the OS X
|
||||
# sysroot to pass to clang.
|
||||
if(NOT EXISTS /usr/include)
|
||||
execute_process(COMMAND xcodebuild -version -sdk macosx Path
|
||||
OUTPUT_VARIABLE OSX_SYSROOT
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(OSX_SYSROOT_FLAG "-isysroot${OSX_SYSROOT}")
|
||||
endif()
|
||||
|
||||
option(COMPILER_RT_ENABLE_IOS "Enable building for iOS - Experimental" Off)
|
||||
|
||||
find_darwin_sdk_dir(DARWIN_osx_SYSROOT macosx)
|
||||
find_darwin_sdk_dir(DARWIN_iossim_SYSROOT iphonesimulator)
|
||||
find_darwin_sdk_dir(DARWIN_ios_SYSROOT iphoneos)
|
||||
|
||||
# Note: In order to target x86_64h on OS X the minimum deployment target must
|
||||
# be 10.8 or higher.
|
||||
set(SANITIZER_COMMON_SUPPORTED_OS osx)
|
||||
set(BUILTIN_SUPPORTED_OS osx)
|
||||
set(PROFILE_SUPPORTED_OS osx)
|
||||
set(TSAN_SUPPORTED_OS osx)
|
||||
if(NOT SANITIZER_MIN_OSX_VERSION)
|
||||
string(REGEX MATCH "-mmacosx-version-min=([.0-9]+)"
|
||||
MACOSX_VERSION_MIN_FLAG "${CMAKE_CXX_FLAGS}")
|
||||
if(MACOSX_VERSION_MIN_FLAG)
|
||||
set(SANITIZER_MIN_OSX_VERSION "${CMAKE_MATCH_1}")
|
||||
elseif(CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
set(SANITIZER_MIN_OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET})
|
||||
else()
|
||||
set(SANITIZER_MIN_OSX_VERSION 10.9)
|
||||
endif()
|
||||
if(SANITIZER_MIN_OSX_VERSION VERSION_LESS "10.7")
|
||||
message(FATAL_ERROR "Too old OS X version: ${SANITIZER_MIN_OSX_VERSION}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We're setting the flag manually for each target OS
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "")
|
||||
|
||||
set(DARWIN_COMMON_CFLAGS -stdlib=libc++)
|
||||
set(DARWIN_COMMON_LINKFLAGS
|
||||
-stdlib=libc++
|
||||
-lc++
|
||||
-lc++abi)
|
||||
|
||||
set(DARWIN_osx_CFLAGS
|
||||
${DARWIN_COMMON_CFLAGS}
|
||||
-mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION})
|
||||
set(DARWIN_osx_LINKFLAGS
|
||||
${DARWIN_COMMON_LINKFLAGS}
|
||||
-mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION})
|
||||
set(DARWIN_osx_BUILTIN_MIN_VER 10.5)
|
||||
set(DARWIN_osx_BUILTIN_MIN_VER_FLAG
|
||||
-mmacosx-version-min=${DARWIN_osx_BUILTIN_MIN_VER})
|
||||
|
||||
if(DARWIN_osx_SYSROOT)
|
||||
list(APPEND DARWIN_osx_CFLAGS -isysroot ${DARWIN_osx_SYSROOT})
|
||||
list(APPEND DARWIN_osx_LINKFLAGS -isysroot ${DARWIN_osx_SYSROOT})
|
||||
endif()
|
||||
|
||||
# Figure out which arches to use for each OS
|
||||
darwin_get_toolchain_supported_archs(toolchain_arches)
|
||||
message(STATUS "Toolchain supported arches: ${toolchain_arches}")
|
||||
|
||||
if(NOT MACOSX_VERSION_MIN_FLAG)
|
||||
darwin_test_archs(osx
|
||||
DARWIN_osx_ARCHS
|
||||
${toolchain_arches})
|
||||
message(STATUS "OSX supported arches: ${DARWIN_osx_ARCHS}")
|
||||
foreach(arch ${DARWIN_osx_ARCHS})
|
||||
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
|
||||
set(CAN_TARGET_${arch} 1)
|
||||
endforeach()
|
||||
|
||||
# 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
|
||||
${toolchain_arches})
|
||||
message(STATUS "OSX 10.4 supported 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()
|
||||
|
||||
if(DARWIN_iossim_SYSROOT)
|
||||
set(DARWIN_iossim_CFLAGS
|
||||
${DARWIN_COMMON_CFLAGS}
|
||||
-mios-simulator-version-min=7.0
|
||||
-isysroot ${DARWIN_iossim_SYSROOT})
|
||||
set(DARWIN_iossim_LINKFLAGS
|
||||
${DARWIN_COMMON_LINKFLAGS}
|
||||
-mios-simulator-version-min=7.0
|
||||
-isysroot ${DARWIN_iossim_SYSROOT})
|
||||
set(DARWIN_iossim_BUILTIN_MIN_VER 6.0)
|
||||
set(DARWIN_iossim_BUILTIN_MIN_VER_FLAG
|
||||
-mios-simulator-version-min=${DARWIN_iossim_BUILTIN_MIN_VER})
|
||||
|
||||
set(DARWIN_iossim_SKIP_CC_KEXT On)
|
||||
darwin_test_archs(iossim
|
||||
DARWIN_iossim_ARCHS
|
||||
${toolchain_arches})
|
||||
message(STATUS "iOS Simulator supported arches: ${DARWIN_iossim_ARCHS}")
|
||||
if(DARWIN_iossim_ARCHS)
|
||||
list(APPEND SANITIZER_COMMON_SUPPORTED_OS iossim)
|
||||
list(APPEND BUILTIN_SUPPORTED_OS iossim)
|
||||
list(APPEND PROFILE_SUPPORTED_OS iossim)
|
||||
endif()
|
||||
foreach(arch ${DARWIN_iossim_ARCHS})
|
||||
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
|
||||
set(CAN_TARGET_${arch} 1)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(DARWIN_ios_SYSROOT AND COMPILER_RT_ENABLE_IOS)
|
||||
set(DARWIN_ios_CFLAGS
|
||||
${DARWIN_COMMON_CFLAGS}
|
||||
-miphoneos-version-min=7.0
|
||||
-isysroot ${DARWIN_ios_SYSROOT})
|
||||
set(DARWIN_ios_LINKFLAGS
|
||||
${DARWIN_COMMON_LINKFLAGS}
|
||||
-miphoneos-version-min=7.0
|
||||
-isysroot ${DARWIN_ios_SYSROOT})
|
||||
set(DARWIN_ios_BUILTIN_MIN_VER 6.0)
|
||||
set(DARWIN_ios_BUILTIN_MIN_VER_FLAG
|
||||
-miphoneos-version-min=${DARWIN_ios_BUILTIN_MIN_VER})
|
||||
|
||||
darwin_test_archs(ios
|
||||
DARWIN_ios_ARCHS
|
||||
${toolchain_arches})
|
||||
message(STATUS "iOS supported arches: ${DARWIN_ios_ARCHS}")
|
||||
if(DARWIN_ios_ARCHS)
|
||||
list(APPEND SANITIZER_COMMON_SUPPORTED_OS ios)
|
||||
list(APPEND BUILTIN_SUPPORTED_OS ios)
|
||||
list(APPEND PROFILE_SUPPORTED_OS ios)
|
||||
endif()
|
||||
foreach(arch ${DARWIN_ios_ARCHS})
|
||||
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
|
||||
set(CAN_TARGET_${arch} 1)
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# for list_union
|
||||
include(CompilerRTUtils)
|
||||
|
||||
list_union(BUILTIN_SUPPORTED_ARCH ALL_BUILTIN_SUPPORTED_ARCH toolchain_arches)
|
||||
|
||||
list_union(SANITIZER_COMMON_SUPPORTED_ARCH
|
||||
ALL_SANITIZER_COMMON_SUPPORTED_ARCH
|
||||
COMPILER_RT_SUPPORTED_ARCH
|
||||
)
|
||||
set(LSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
set(UBSAN_COMMON_SUPPORTED_ARCH ${SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
list_union(ASAN_SUPPORTED_ARCH
|
||||
ALL_ASAN_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_union(DFSAN_SUPPORTED_ARCH
|
||||
ALL_DFSAN_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_union(LSAN_SUPPORTED_ARCH
|
||||
ALL_LSAN_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_union(MSAN_SUPPORTED_ARCH
|
||||
ALL_MSAN_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_union(PROFILE_SUPPORTED_ARCH
|
||||
ALL_PROFILE_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_union(TSAN_SUPPORTED_ARCH
|
||||
ALL_TSAN_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_union(UBSAN_SUPPORTED_ARCH
|
||||
ALL_UBSAN_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_union(SAFESTACK_SUPPORTED_ARCH
|
||||
ALL_SAFESTACK_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
list_union(CFI_SUPPORTED_ARCH
|
||||
ALL_CFI_SUPPORTED_ARCH
|
||||
SANITIZER_COMMON_SUPPORTED_ARCH)
|
||||
else()
|
||||
# Architectures supported by compiler-rt libraries.
|
||||
filter_available_targets(BUILTIN_SUPPORTED_ARCH
|
||||
${ALL_BUILTIN_SUPPORTED_ARCH})
|
||||
filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
|
||||
${ALL_SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
# LSan and UBSan common files should be available on all architectures
|
||||
# supported by other sanitizers (even if they build into dummy object files).
|
||||
filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH
|
||||
${SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
filter_available_targets(UBSAN_COMMON_SUPPORTED_ARCH
|
||||
${SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
filter_available_targets(ASAN_SUPPORTED_ARCH ${ALL_ASAN_SUPPORTED_ARCH})
|
||||
filter_available_targets(DFSAN_SUPPORTED_ARCH ${ALL_DFSAN_SUPPORTED_ARCH})
|
||||
filter_available_targets(LSAN_SUPPORTED_ARCH ${ALL_LSAN_SUPPORTED_ARCH})
|
||||
filter_available_targets(MSAN_SUPPORTED_ARCH ${ALL_MSAN_SUPPORTED_ARCH})
|
||||
filter_available_targets(PROFILE_SUPPORTED_ARCH ${ALL_PROFILE_SUPPORTED_ARCH})
|
||||
filter_available_targets(TSAN_SUPPORTED_ARCH ${ALL_TSAN_SUPPORTED_ARCH})
|
||||
filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH})
|
||||
filter_available_targets(SAFESTACK_SUPPORTED_ARCH
|
||||
${ALL_SAFESTACK_SUPPORTED_ARCH})
|
||||
filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH})
|
||||
endif()
|
||||
|
||||
message(STATUS "Compiler-RT supported architectures: ${COMPILER_RT_SUPPORTED_ARCH}")
|
||||
|
||||
if(ANDROID)
|
||||
set(OS_NAME "Android")
|
||||
@ -329,7 +566,7 @@ else()
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Linux|FreeBSD")
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD")
|
||||
set(COMPILER_RT_HAS_TSAN TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_TSAN FALSE)
|
||||
@ -342,17 +579,16 @@ else()
|
||||
set(COMPILER_RT_HAS_UBSAN FALSE)
|
||||
endif()
|
||||
|
||||
# -msse3 flag is not valid for Mips therefore clang gives a warning
|
||||
# message with -msse3. But check_c_compiler_flags() checks only for
|
||||
# compiler error messages. Therefore COMPILER_RT_HAS_MSSE3_FLAG turns out to be
|
||||
# true on Mips, so we make it false here.
|
||||
if("${LLVM_NATIVE_ARCH}" STREQUAL "Mips")
|
||||
set(COMPILER_RT_HAS_MSSE3_FLAG FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND SAFESTACK_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD")
|
||||
set(COMPILER_RT_HAS_SAFESTACK TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_SAFESTACK FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND CFI_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Linux")
|
||||
set(COMPILER_RT_HAS_CFI TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_CFI FALSE)
|
||||
endif()
|
||||
|
@ -110,10 +110,6 @@ extern "C" {
|
||||
void __asan_report_error(void *pc, void *bp, void *sp,
|
||||
void *addr, int is_write, size_t access_size);
|
||||
|
||||
// Sets the exit code to use when reporting an error.
|
||||
// Returns the old value.
|
||||
int __asan_set_error_exit_code(int exit_code);
|
||||
|
||||
// Deprecated. Call __sanitizer_set_death_callback instead.
|
||||
void __asan_set_death_callback(void (*callback)(void));
|
||||
|
||||
|
@ -105,12 +105,29 @@ extern "C" {
|
||||
int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
|
||||
const void *end);
|
||||
|
||||
// Similar to __sanitizer_verify_contiguous_container but returns the address
|
||||
// of the first improperly poisoned byte otherwise. Returns null if the area
|
||||
// is poisoned properly.
|
||||
const void *__sanitizer_contiguous_container_find_bad_address(
|
||||
const void *beg, const void *mid, const void *end);
|
||||
|
||||
// Print the stack trace leading to this call. Useful for debugging user code.
|
||||
void __sanitizer_print_stack_trace();
|
||||
|
||||
// Sets the callback to be called right before death on error.
|
||||
// Passing 0 will unset the callback.
|
||||
void __sanitizer_set_death_callback(void (*callback)(void));
|
||||
|
||||
// Interceptor hooks.
|
||||
// Whenever a libc function interceptor is called it checks if the
|
||||
// corresponding weak hook is defined, and it so -- calls it.
|
||||
// The primary use case is data-flow-guided fuzzing, where the fuzzer needs
|
||||
// to know what is being passed to libc functions, e.g. memcmp.
|
||||
// FIXME: implement more hooks.
|
||||
void __sanitizer_weak_hook_memcmp(void *called_pc, const void *s1,
|
||||
const void *s2, size_t n);
|
||||
void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1,
|
||||
const char *s2, size_t n);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -27,9 +27,11 @@ extern "C" {
|
||||
// descriptor. Returns -1 on failure, or if coverage dumping is disabled.
|
||||
// This is intended for use by sandboxing code.
|
||||
intptr_t __sanitizer_maybe_open_cov_file(const char *name);
|
||||
// Get the number of total unique covered entities (blocks, edges, calls).
|
||||
// Get the number of unique covered blocks (or edges).
|
||||
// This can be useful for coverage-directed in-process fuzzers.
|
||||
uintptr_t __sanitizer_get_total_unique_coverage();
|
||||
// Get the number of unique indirect caller-callee pairs.
|
||||
uintptr_t __sanitizer_get_total_unique_caller_callee_pairs();
|
||||
|
||||
// Reset the basic-block (edge) coverage to the initial state.
|
||||
// Useful for in-process fuzzing to start collecting coverage from scratch.
|
||||
|
@ -91,16 +91,18 @@ void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback);
|
||||
/// <label> <parent label 1> <parent label 2> <label description if any>
|
||||
void dfsan_dump_labels(int fd);
|
||||
|
||||
/// Interceptor hooks.
|
||||
/// Whenever a dfsan's custom function is called the corresponding
|
||||
/// hook is called it non-zero. The hooks should be defined by the user.
|
||||
/// The primary use case is taint-guided fuzzing, where the fuzzer
|
||||
/// needs to see the parameters of the function and the labels.
|
||||
/// FIXME: implement more hooks.
|
||||
|
||||
/// memcmp hook.
|
||||
void dfsan_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2,
|
||||
size_t n, dfsan_label s1_label,
|
||||
dfsan_label s2_label, dfsan_label n_label);
|
||||
void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
|
||||
size_t n, dfsan_label s1_label,
|
||||
dfsan_label s2_label, dfsan_label n_label);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
|
@ -43,7 +43,7 @@ extern "C" {
|
||||
|
||||
// Check for leaks now. This function behaves identically to the default
|
||||
// end-of-process leak check. In particular, it will terminate the process if
|
||||
// leaks are found and the exit_code flag is non-zero.
|
||||
// leaks are found and the exitcode runtime flag is non-zero.
|
||||
// Subsequent calls to this function will have no effect and end-of-process
|
||||
// leak check will not run. Effectively, end-of-process leak check is moved to
|
||||
// the time of first invocation of this function.
|
||||
|
@ -61,10 +61,6 @@ extern "C" {
|
||||
* is not. */
|
||||
void __msan_check_mem_is_initialized(const volatile void *x, size_t size);
|
||||
|
||||
/* Set exit code when error(s) were detected.
|
||||
Value of 0 means don't change the program exit code. */
|
||||
void __msan_set_exit_code(int exit_code);
|
||||
|
||||
/* For testing:
|
||||
__msan_set_expect_umr(1);
|
||||
... some buggy code ...
|
||||
@ -92,14 +88,22 @@ extern "C" {
|
||||
Memory will be marked uninitialized, with origin at the call site. */
|
||||
void __msan_allocated_memory(const volatile void* data, size_t size);
|
||||
|
||||
/* Tell MSan about newly destroyed memory. Mark memory as uninitialized. */
|
||||
void __sanitizer_dtor_callback(const volatile void* data, size_t size);
|
||||
|
||||
/* This function may be optionally provided by user and should return
|
||||
a string containing Msan runtime options. See msan_flags.h for details. */
|
||||
const char* __msan_default_options();
|
||||
|
||||
/* Sets the callback to be called right before death on error.
|
||||
Passing 0 will unset the callback. */
|
||||
/* Deprecated. Call __sanitizer_set_death_callback instead. */
|
||||
void __msan_set_death_callback(void (*callback)(void));
|
||||
|
||||
/* Update shadow for the application copy of size bytes from src to dst.
|
||||
Src and dst are application addresses. This function does not copy the
|
||||
actual application memory, it only updates shadow and origin for such
|
||||
copy. Source and destination regions can overlap. */
|
||||
void __msan_copy_shadow(const volatile void *dst, const volatile void *src,
|
||||
size_t size);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -4,39 +4,47 @@
|
||||
include(AddCompilerRT)
|
||||
include(SanitizerUtils)
|
||||
|
||||
if(COMPILER_RT_HAS_INTERCEPTION)
|
||||
add_subdirectory(interception)
|
||||
if(COMPILER_RT_BUILD_BUILTINS)
|
||||
add_subdirectory(builtins)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_SANITIZER_COMMON)
|
||||
add_subdirectory(sanitizer_common)
|
||||
add_subdirectory(lsan)
|
||||
add_subdirectory(ubsan)
|
||||
endif()
|
||||
if(COMPILER_RT_BUILD_SANITIZERS)
|
||||
if(COMPILER_RT_HAS_INTERCEPTION)
|
||||
add_subdirectory(interception)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_ASAN)
|
||||
add_subdirectory(asan)
|
||||
endif()
|
||||
if(COMPILER_RT_HAS_SANITIZER_COMMON)
|
||||
add_subdirectory(sanitizer_common)
|
||||
add_subdirectory(lsan)
|
||||
add_subdirectory(ubsan)
|
||||
endif()
|
||||
|
||||
add_subdirectory(builtins)
|
||||
if(COMPILER_RT_HAS_ASAN)
|
||||
add_subdirectory(asan)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_DFSAN)
|
||||
add_subdirectory(dfsan)
|
||||
endif()
|
||||
if(COMPILER_RT_HAS_DFSAN)
|
||||
add_subdirectory(dfsan)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_MSAN)
|
||||
add_subdirectory(msan)
|
||||
endif()
|
||||
if(COMPILER_RT_HAS_MSAN)
|
||||
add_subdirectory(msan)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_PROFILE)
|
||||
add_subdirectory(profile)
|
||||
endif()
|
||||
if(COMPILER_RT_HAS_PROFILE)
|
||||
add_subdirectory(profile)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_TSAN)
|
||||
add_subdirectory(tsan)
|
||||
add_subdirectory(tsan/dd)
|
||||
endif()
|
||||
if(COMPILER_RT_HAS_TSAN)
|
||||
add_subdirectory(tsan)
|
||||
add_subdirectory(tsan/dd)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_SAFESTACK)
|
||||
add_subdirectory(safestack)
|
||||
if(COMPILER_RT_HAS_SAFESTACK)
|
||||
add_subdirectory(safestack)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_CFI)
|
||||
add_subdirectory(cfi)
|
||||
endif()
|
||||
endif()
|
||||
|
1
lib/asan/.clang-format
Normal file
1
lib/asan/.clang-format
Normal file
@ -0,0 +1 @@
|
||||
BasedOnStyle: Google
|
@ -70,18 +70,18 @@ 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_LIBSTDCXX stdc++ ASAN_DYNAMIC_LIBS)
|
||||
|
||||
append_list_if(ANDROID log ASAN_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBLOG log ASAN_DYNAMIC_LIBS)
|
||||
|
||||
# Compile ASan sources into an object library.
|
||||
if(APPLE)
|
||||
add_compiler_rt_object_libraries(RTAsan
|
||||
OS ${SANITIZER_COMMON_SUPPORTED_OS}
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
else()
|
||||
|
||||
add_compiler_rt_object_libraries(RTAsan_dynamic
|
||||
OS ${SANITIZER_COMMON_SUPPORTED_OS}
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
|
||||
if(NOT APPLE)
|
||||
add_compiler_rt_object_libraries(RTAsan
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_SOURCES} CFLAGS ${ASAN_CFLAGS}
|
||||
@ -94,11 +94,6 @@ else()
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_PREINIT_SOURCES} CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_libraries(RTAsan_dynamic
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc "")
|
||||
add_compiler_rt_object_libraries(RTAsan_dynamic_version_script_dummy
|
||||
@ -111,49 +106,57 @@ endif()
|
||||
# Build ASan runtimes shipped with Clang.
|
||||
add_custom_target(asan)
|
||||
if(APPLE)
|
||||
foreach (os ${SANITIZER_COMMON_SUPPORTED_OS})
|
||||
add_compiler_rt_darwin_dynamic_runtime(clang_rt.asan_${os}_dynamic ${os}
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan.${os}>
|
||||
$<TARGET_OBJECTS:RTInterception.${os}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${os}>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${os}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${os}>
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
add_dependencies(asan clang_rt.asan_${os}_dynamic)
|
||||
endforeach()
|
||||
add_compiler_rt_runtime(clang_rt.asan
|
||||
SHARED
|
||||
OS ${SANITIZER_COMMON_SUPPORTED_OS}
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
OBJECT_LIBS RTAsan_dynamic
|
||||
RTInterception
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTLSanCommon
|
||||
RTUbsan
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
else()
|
||||
# Build separate libraries for each target.
|
||||
|
||||
set(ASAN_COMMON_RUNTIME_OBJECT_LIBS
|
||||
RTInterception
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTLSanCommon
|
||||
RTUbsan)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan
|
||||
STATIC
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
OBJECT_LIBS RTAsan_preinit
|
||||
RTAsan
|
||||
${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan_cxx
|
||||
STATIC
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
OBJECT_LIBS RTAsan_cxx
|
||||
RTUbsan_cxx
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan-preinit
|
||||
STATIC
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
OBJECT_LIBS RTAsan_preinit
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
|
||||
foreach(arch ${ASAN_SUPPORTED_ARCH})
|
||||
set(ASAN_COMMON_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan-${arch} ${arch} STATIC
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan_preinit.${arch}>
|
||||
$<TARGET_OBJECTS:RTAsan.${arch}>
|
||||
${ASAN_COMMON_RUNTIME_OBJECTS}
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_dependencies(asan clang_rt.asan-${arch})
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan_cxx-${arch} ${arch} STATIC
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan_cxx.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_dependencies(asan clang_rt.asan_cxx-${arch})
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan-preinit-${arch} ${arch} STATIC
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan_preinit.${arch}>
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_dependencies(asan clang_rt.asan-preinit-${arch})
|
||||
|
||||
if (UNIX AND NOT ${arch} MATCHES "i386|i686")
|
||||
add_sanitizer_rt_version_list(clang_rt.asan-dynamic-${arch}
|
||||
LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch}
|
||||
@ -168,48 +171,50 @@ else()
|
||||
set(VERSION_SCRIPT_FLAG)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(SHARED_ASAN_NAME clang_rt.asan_dynamic-${arch}${COMPILER_RT_OS_SUFFIX})
|
||||
else()
|
||||
set(SHARED_ASAN_NAME clang_rt.asan-${arch}${COMPILER_RT_OS_SUFFIX})
|
||||
endif()
|
||||
add_compiler_rt_runtime(clang_rt.asan-dynamic-${arch} ${arch} SHARED
|
||||
OUTPUT_NAME ${SHARED_ASAN_NAME}
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan_dynamic.${arch}>
|
||||
add_compiler_rt_runtime(clang_rt.asan
|
||||
SHARED
|
||||
ARCHS ${arch}
|
||||
OBJECT_LIBS ${ASAN_COMMON_RUNTIME_OBJECT_LIBS}
|
||||
RTAsan_dynamic
|
||||
# The only purpose of RTAsan_dynamic_version_script_dummy is to carry
|
||||
# a dependency of the shared runtime on the version script. With CMake
|
||||
# 3.1 or later it can be replaced with a straightforward
|
||||
# add_dependencies(clang_rt.asan-dynamic-${arch} clang_rt.asan-dynamic-${arch}-version-list)
|
||||
$<TARGET_OBJECTS:RTAsan_dynamic_version_script_dummy.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
|
||||
${ASAN_COMMON_RUNTIME_OBJECTS}
|
||||
RTAsan_dynamic_version_script_dummy
|
||||
RTUbsan_cxx
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
LINKFLAGS ${ASAN_DYNAMIC_LINK_FLAGS}
|
||||
${VERSION_SCRIPT_FLAG}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
target_link_libraries(clang_rt.asan-dynamic-${arch} ${ASAN_DYNAMIC_LIBS})
|
||||
add_dependencies(asan clang_rt.asan-dynamic-${arch})
|
||||
LINK_LIBS ${ASAN_DYNAMIC_LIBS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
|
||||
if (UNIX AND NOT ${arch} MATCHES "i386|i686")
|
||||
add_sanitizer_rt_symbols(clang_rt.asan_cxx-${arch})
|
||||
add_sanitizer_rt_symbols(clang_rt.asan_cxx
|
||||
ARCHS ${arch})
|
||||
add_dependencies(asan clang_rt.asan_cxx-${arch}-symbols)
|
||||
add_sanitizer_rt_symbols(clang_rt.asan-${arch} asan.syms.extra)
|
||||
add_sanitizer_rt_symbols(clang_rt.asan
|
||||
ARCHS ${arch}
|
||||
EXTRA asan.syms.extra)
|
||||
add_dependencies(asan clang_rt.asan-${arch}-symbols)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
add_compiler_rt_runtime(clang_rt.asan_dll_thunk-${arch} ${arch} STATIC
|
||||
add_compiler_rt_runtime(clang_rt.asan_dll_thunk
|
||||
STATIC
|
||||
ARCHS ${arch}
|
||||
SOURCES asan_win_dll_thunk.cc
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
CFLAGS ${ASAN_CFLAGS} -DASAN_DLL_THUNK
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_dependencies(asan clang_rt.asan_dll_thunk-${arch})
|
||||
add_compiler_rt_runtime(clang_rt.asan_dynamic_runtime_thunk-${arch} ${arch}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
add_compiler_rt_runtime(clang_rt.asan_dynamic_runtime_thunk
|
||||
STATIC
|
||||
ARCHS ${arch}
|
||||
SOURCES asan_win_dynamic_runtime_thunk.cc
|
||||
CFLAGS ${ASAN_CFLAGS} -DASAN_DYNAMIC_RUNTIME_THUNK -Zl
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_dependencies(asan clang_rt.asan_dynamic_runtime_thunk-${arch})
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
@ -23,4 +23,4 @@ from the root of your CMake build tree:
|
||||
make check-asan
|
||||
|
||||
For more instructions see:
|
||||
http://code.google.com/p/address-sanitizer/wiki/HowToBuild
|
||||
https://github.com/google/sanitizers/wiki/AddressSanitizerHowToBuild
|
||||
|
@ -38,7 +38,7 @@ static struct AsanDeactivatedFlags {
|
||||
#undef ASAN_ACTIVATION_FLAG
|
||||
#undef COMMON_ACTIVATION_FLAG
|
||||
|
||||
RegisterIncludeFlag(parser, cf);
|
||||
RegisterIncludeFlags(parser, cf);
|
||||
}
|
||||
|
||||
void OverrideFromActivationFlags() {
|
||||
@ -61,11 +61,6 @@ static struct AsanDeactivatedFlags {
|
||||
parser.ParseString(env);
|
||||
}
|
||||
|
||||
// Override from getprop asan.options.
|
||||
char buf[100];
|
||||
GetExtraActivationFlags(buf, sizeof(buf));
|
||||
parser.ParseString(buf);
|
||||
|
||||
SetVerbosity(cf.verbosity);
|
||||
|
||||
if (Verbosity()) ReportUnrecognizedFlags();
|
||||
@ -124,6 +119,8 @@ void AsanActivate() {
|
||||
if (!asan_is_deactivated) return;
|
||||
VReport(1, "Activating ASan\n");
|
||||
|
||||
UpdateProcessName();
|
||||
|
||||
asan_deactivated_flags.OverrideFromActivationFlags();
|
||||
|
||||
SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
|
||||
|
@ -14,8 +14,8 @@
|
||||
// with ThreadSanitizer and MemorySanitizer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "asan_allocator.h"
|
||||
|
||||
#include "asan_allocator.h"
|
||||
#include "asan_mapping.h"
|
||||
#include "asan_poisoning.h"
|
||||
#include "asan_report.h"
|
||||
@ -541,7 +541,7 @@ struct Allocator {
|
||||
u8 chunk_state = m->chunk_state;
|
||||
if (chunk_state != CHUNK_ALLOCATED)
|
||||
ReportInvalidFree(old_ptr, chunk_state, stack);
|
||||
CHECK_NE(REAL(memcpy), (void*)0);
|
||||
CHECK_NE(REAL(memcpy), nullptr);
|
||||
uptr memcpy_size = Min(new_size, m->UsedSize());
|
||||
// If realloc() races with free(), we may start copying freed memory.
|
||||
// However, we will report racy double-free later anyway.
|
||||
@ -579,7 +579,7 @@ struct Allocator {
|
||||
|
||||
// Assumes alloc_beg == allocator.GetBlockBegin(alloc_beg).
|
||||
AsanChunk *GetAsanChunk(void *alloc_beg) {
|
||||
if (!alloc_beg) return 0;
|
||||
if (!alloc_beg) return nullptr;
|
||||
if (!allocator.FromPrimary(alloc_beg)) {
|
||||
uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(alloc_beg));
|
||||
AsanChunk *m = reinterpret_cast<AsanChunk *>(meta[1]);
|
||||
@ -619,7 +619,7 @@ struct Allocator {
|
||||
// The address is in the chunk's left redzone, so maybe it is actually
|
||||
// a right buffer overflow from the other chunk to the left.
|
||||
// Search a bit to the left to see if there is another chunk.
|
||||
AsanChunk *m2 = 0;
|
||||
AsanChunk *m2 = nullptr;
|
||||
for (uptr l = 1; l < GetPageSizeCached(); l++) {
|
||||
m2 = GetAsanChunkByAddr(addr - l);
|
||||
if (m2 == m1) continue; // Still the same chunk.
|
||||
@ -653,7 +653,7 @@ static AsanAllocator &get_allocator() {
|
||||
}
|
||||
|
||||
bool AsanChunkView::IsValid() {
|
||||
return chunk_ != 0 && chunk_->chunk_state != CHUNK_AVAILABLE;
|
||||
return chunk_ && chunk_->chunk_state != CHUNK_AVAILABLE;
|
||||
}
|
||||
uptr AsanChunkView::Beg() { return chunk_->Beg(); }
|
||||
uptr AsanChunkView::End() { return Beg() + UsedSize(); }
|
||||
@ -723,11 +723,11 @@ void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
|
||||
}
|
||||
|
||||
void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) {
|
||||
if (p == 0)
|
||||
if (!p)
|
||||
return instance.Allocate(size, 8, stack, FROM_MALLOC, true);
|
||||
if (size == 0) {
|
||||
instance.Deallocate(p, 0, stack, FROM_MALLOC);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
return instance.Reallocate(p, size, stack);
|
||||
}
|
||||
@ -755,7 +755,7 @@ int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
|
||||
}
|
||||
|
||||
uptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp) {
|
||||
if (ptr == 0) return 0;
|
||||
if (!ptr) return 0;
|
||||
uptr usable_size = instance.AllocationSize(reinterpret_cast<uptr>(ptr));
|
||||
if (flags()->check_malloc_usable_size && (usable_size == 0)) {
|
||||
GET_STACK_TRACE_FATAL(pc, bp);
|
||||
@ -780,7 +780,7 @@ void AsanSoftRssLimitExceededCallback(bool exceeded) {
|
||||
instance.allocator.SetRssLimitIsExceeded(exceeded);
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
// --- Implementation of LSan-specific functions --- {{{1
|
||||
namespace __lsan {
|
||||
@ -881,7 +881,7 @@ int __sanitizer_get_ownership(const void *p) {
|
||||
}
|
||||
|
||||
uptr __sanitizer_get_allocated_size(const void *p) {
|
||||
if (p == 0) return 0;
|
||||
if (!p) return 0;
|
||||
uptr ptr = reinterpret_cast<uptr>(p);
|
||||
uptr allocated_size = instance.AllocationSize(ptr);
|
||||
// Die if p is not malloced or if it is already freed.
|
||||
@ -904,5 +904,5 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||
void __sanitizer_free_hook(void *ptr) {
|
||||
(void)ptr;
|
||||
}
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -114,6 +114,11 @@ struct AsanMapUnmapCallback {
|
||||
# if defined(__powerpc64__)
|
||||
const uptr kAllocatorSpace = 0xa0000000000ULL;
|
||||
const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
|
||||
# elif defined(__aarch64__)
|
||||
// AArch64/SANITIZIER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA
|
||||
// so no need to different values for different VMA.
|
||||
const uptr kAllocatorSpace = 0x10000000000ULL;
|
||||
const uptr kAllocatorSize = 0x10000000000ULL; // 3T.
|
||||
# else
|
||||
const uptr kAllocatorSpace = 0x600000000000ULL;
|
||||
const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
|
||||
|
@ -108,14 +108,14 @@ static uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
using namespace __asan;
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
|
||||
uptr *region_address, uptr *region_size) {
|
||||
AddressDescription descr = { name, name_size, 0, 0, 0 };
|
||||
AddressDescription descr = { name, name_size, 0, 0, nullptr };
|
||||
AsanLocateAddress(addr, &descr);
|
||||
if (region_address) *region_address = descr.region_address;
|
||||
if (region_size) *region_size = descr.region_size;
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
// FakeStack is used to detect use-after-return bugs.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "asan_allocator.h"
|
||||
#include "asan_poisoning.h"
|
||||
#include "asan_thread.h"
|
||||
@ -32,7 +33,8 @@ ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) {
|
||||
if (class_id <= 6) {
|
||||
for (uptr i = 0; i < (1U << class_id); i++) {
|
||||
shadow[i] = magic;
|
||||
SanitizerBreakOptimization(0); // Make sure this does not become memset.
|
||||
// Make sure this does not become memset.
|
||||
SanitizerBreakOptimization(nullptr);
|
||||
}
|
||||
} else {
|
||||
// The size class is too big, it's cheaper to poison only size bytes.
|
||||
@ -80,7 +82,9 @@ void FakeStack::PoisonAll(u8 magic) {
|
||||
magic);
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER) || defined(__clang__)
|
||||
ALWAYS_INLINE USED
|
||||
#endif
|
||||
FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id,
|
||||
uptr real_stack) {
|
||||
CHECK_LT(class_id, kNumberOfSizeClasses);
|
||||
@ -106,7 +110,7 @@ FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id,
|
||||
*SavedFlagPtr(reinterpret_cast<uptr>(res), class_id) = &flags[pos];
|
||||
return res;
|
||||
}
|
||||
return 0; // We are out of fake stack.
|
||||
return nullptr; // We are out of fake stack.
|
||||
}
|
||||
|
||||
uptr FakeStack::AddrIsInFakeStack(uptr ptr, uptr *frame_beg, uptr *frame_end) {
|
||||
@ -183,7 +187,7 @@ void SetTLSFakeStack(FakeStack *fs) { }
|
||||
|
||||
static FakeStack *GetFakeStack() {
|
||||
AsanThread *t = GetCurrentThread();
|
||||
if (!t) return 0;
|
||||
if (!t) return nullptr;
|
||||
return t->fake_stack();
|
||||
}
|
||||
|
||||
@ -191,7 +195,7 @@ static FakeStack *GetFakeStackFast() {
|
||||
if (FakeStack *fs = GetTLSFakeStack())
|
||||
return fs;
|
||||
if (!__asan_option_detect_stack_use_after_return)
|
||||
return 0;
|
||||
return nullptr;
|
||||
return GetFakeStack();
|
||||
}
|
||||
|
||||
@ -212,7 +216,7 @@ ALWAYS_INLINE void OnFree(uptr ptr, uptr class_id, uptr size) {
|
||||
SetShadow(ptr, size, class_id, kMagic8);
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan;
|
||||
@ -245,13 +249,13 @@ SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
|
||||
void **end) {
|
||||
FakeStack *fs = reinterpret_cast<FakeStack*>(fake_stack);
|
||||
if (!fs) return 0;
|
||||
if (!fs) return nullptr;
|
||||
uptr frame_beg, frame_end;
|
||||
FakeFrame *frame = reinterpret_cast<FakeFrame *>(fs->AddrIsInFakeStack(
|
||||
reinterpret_cast<uptr>(addr), &frame_beg, &frame_end));
|
||||
if (!frame) return 0;
|
||||
if (!frame) return nullptr;
|
||||
if (frame->magic != kCurrentStackFrameMagic)
|
||||
return 0;
|
||||
return nullptr;
|
||||
if (beg) *beg = reinterpret_cast<void*>(frame_beg);
|
||||
if (end) *end = reinterpret_cast<void*>(frame_end);
|
||||
return reinterpret_cast<void*>(frame->real_stack);
|
||||
@ -276,4 +280,4 @@ void __asan_allocas_unpoison(uptr top, uptr bottom) {
|
||||
REAL(memset)(reinterpret_cast<void*>(MemToShadow(top)), 0,
|
||||
(bottom - top) / SHADOW_GRANULARITY);
|
||||
}
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
@ -65,6 +65,7 @@ void InitializeFlags() {
|
||||
cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
|
||||
cf.malloc_context_size = kDefaultMallocContextSize;
|
||||
cf.intercept_tls_get_addr = true;
|
||||
cf.exitcode = 1;
|
||||
OverrideCommonFlags(cf);
|
||||
}
|
||||
Flags *f = flags();
|
||||
@ -115,14 +116,6 @@ void InitializeFlags() {
|
||||
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
|
||||
#endif
|
||||
|
||||
// Let activation flags override current settings. On Android they come
|
||||
// from a system property. On other platforms this is no-op.
|
||||
if (!flags()->start_deactivated) {
|
||||
char buf[100];
|
||||
GetExtraActivationFlags(buf, sizeof(buf));
|
||||
asan_parser.ParseString(buf);
|
||||
}
|
||||
|
||||
SetVerbosity(common_flags()->verbosity);
|
||||
|
||||
// TODO(eugenis): dump all flags at verbosity>=2?
|
||||
|
@ -44,9 +44,6 @@ ASAN_FLAG(
|
||||
"to find more errors.")
|
||||
ASAN_FLAG(bool, replace_intrin, true,
|
||||
"If set, uses custom wrappers for memset/memcpy/memmove intinsics.")
|
||||
ASAN_FLAG(bool, mac_ignore_invalid_free, false,
|
||||
"Ignore invalid free() calls to work around some bugs. Used on OS X "
|
||||
"only.")
|
||||
ASAN_FLAG(bool, detect_stack_use_after_return, false,
|
||||
"Enables stack-use-after-return checking at run-time.")
|
||||
ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway.
|
||||
@ -62,8 +59,6 @@ ASAN_FLAG(
|
||||
"bytes that will be filled with malloc_fill_byte on malloc.")
|
||||
ASAN_FLAG(int, malloc_fill_byte, 0xbe,
|
||||
"Value used to fill the newly allocated memory.")
|
||||
ASAN_FLAG(int, exitcode, ASAN_DEFAULT_FAILURE_EXITCODE,
|
||||
"Override the program exit status if the tool found an error.")
|
||||
ASAN_FLAG(bool, allow_user_poisoning, true,
|
||||
"If set, user may manually mark memory regions as poisoned or "
|
||||
"unpoisoned.")
|
||||
@ -77,10 +72,7 @@ ASAN_FLAG(bool, check_malloc_usable_size, true,
|
||||
"295.*.")
|
||||
ASAN_FLAG(bool, unmap_shadow_on_exit, false,
|
||||
"If set, explicitly unmaps the (huge) shadow at exit.")
|
||||
ASAN_FLAG(
|
||||
bool, abort_on_error, false,
|
||||
"If set, the tool calls abort() instead of _exit() after printing the "
|
||||
"error report.")
|
||||
ASAN_FLAG(bool, protect_shadow_gap, true, "If set, mprotect the shadow gap")
|
||||
ASAN_FLAG(bool, print_stats, false,
|
||||
"Print various statistics after printing an error message or if "
|
||||
"atexit=1.")
|
||||
@ -104,8 +96,8 @@ ASAN_FLAG(bool, poison_array_cookie, true,
|
||||
"Poison (or not) the array cookie after operator new[].")
|
||||
|
||||
// Turn off alloc/dealloc mismatch checker on Mac and Windows for now.
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=131
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=309
|
||||
// https://github.com/google/sanitizers/issues/131
|
||||
// https://github.com/google/sanitizers/issues/309
|
||||
// TODO(glider,timurrrr): Fix known issues and enable this back.
|
||||
ASAN_FLAG(bool, alloc_dealloc_mismatch,
|
||||
(SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0),
|
||||
@ -113,9 +105,6 @@ ASAN_FLAG(bool, alloc_dealloc_mismatch,
|
||||
|
||||
ASAN_FLAG(bool, new_delete_type_mismatch, true,
|
||||
"Report errors on mismatch betwen size of new and delete.")
|
||||
ASAN_FLAG(bool, strict_memcmp, true,
|
||||
"If true, assume that memcmp(p1, p2, n) always reads n bytes before "
|
||||
"comparing p1 and p2.")
|
||||
ASAN_FLAG(
|
||||
bool, strict_init_order, false,
|
||||
"If true, assume that dynamic initializers can never access globals from "
|
||||
@ -134,8 +123,8 @@ ASAN_FLAG(
|
||||
"The bigger the value the harder we try.")
|
||||
ASAN_FLAG(
|
||||
bool, detect_container_overflow, true,
|
||||
"If true, honor the container overflow annotations. "
|
||||
"See https://code.google.com/p/address-sanitizer/wiki/ContainerOverflow")
|
||||
"If true, honor the container overflow annotations. See "
|
||||
"https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow")
|
||||
ASAN_FLAG(int, detect_odr_violation, 2,
|
||||
"If >=2, detect violation of One-Definition-Rule (ODR); "
|
||||
"If ==1, detect ODR-violation only if the two variables "
|
||||
@ -143,3 +132,6 @@ ASAN_FLAG(int, detect_odr_violation, 2,
|
||||
ASAN_FLAG(bool, dump_instruction_bytes, false,
|
||||
"If true, dump 16 bytes starting at the instruction that caused SEGV")
|
||||
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!)")
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
// Handle globals.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_mapping.h"
|
||||
@ -167,7 +168,7 @@ static void RegisterGlobal(const Global *g) {
|
||||
l->next = list_of_all_globals;
|
||||
list_of_all_globals = l;
|
||||
if (g->has_dynamic_init) {
|
||||
if (dynamic_init_globals == 0) {
|
||||
if (!dynamic_init_globals) {
|
||||
dynamic_init_globals = new(allocator_for_globals)
|
||||
VectorOfGlobals(kDynamicInitGlobalsInitialCapacity);
|
||||
}
|
||||
@ -206,7 +207,7 @@ void StopInitOrderChecking() {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
@ -27,8 +27,8 @@ extern "C" {
|
||||
// v3=>v4: added '__asan_global_source_location' to __asan_global.
|
||||
// v4=>v5: changed the semantics and format of __asan_stack_malloc_ and
|
||||
// __asan_stack_free_ functions.
|
||||
#define __asan_init __asan_init_v5
|
||||
#define __asan_init_name "__asan_init_v5"
|
||||
// v5=>v6: changed the name of the version check symbol
|
||||
#define __asan_version_mismatch_check __asan_version_mismatch_check_v6
|
||||
}
|
||||
|
||||
#endif // ASAN_INIT_VERSION_H
|
||||
|
@ -11,8 +11,8 @@
|
||||
//
|
||||
// Intercept various libc functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "asan_interceptors.h"
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_allocator.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_mapping.h"
|
||||
@ -27,6 +27,12 @@
|
||||
#include "sanitizer_common/sanitizer_posix.h"
|
||||
#endif
|
||||
|
||||
#if defined(__i386) && SANITIZER_LINUX
|
||||
#define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
|
||||
#elif defined(__mips__) && SANITIZER_LINUX
|
||||
#define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
|
||||
#endif
|
||||
|
||||
namespace __asan {
|
||||
|
||||
// Return true if we can quickly decide that the region is unpoisoned.
|
||||
@ -69,7 +75,7 @@ struct AsanInterceptorContext {
|
||||
} \
|
||||
if (!suppressed) { \
|
||||
GET_CURRENT_PC_BP_SP; \
|
||||
__asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0); \
|
||||
ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
@ -105,7 +111,7 @@ static inline bool RangesOverlap(const char *offset1, uptr length1,
|
||||
|
||||
static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
|
||||
#if ASAN_INTERCEPT_STRNLEN
|
||||
if (REAL(strnlen) != 0) {
|
||||
if (REAL(strnlen)) {
|
||||
return REAL(strnlen)(s, maxlen);
|
||||
}
|
||||
#endif
|
||||
@ -123,7 +129,7 @@ int OnExit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
// ---------------------- Wrappers ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
@ -172,7 +178,7 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
||||
} while (false)
|
||||
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
|
||||
// Strict init-order checking is dlopen-hostile:
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=178
|
||||
// https://github.com/google/sanitizers/issues/178
|
||||
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
|
||||
if (flags()->strict_init_order) { \
|
||||
StopInitOrderChecking(); \
|
||||
@ -216,7 +222,7 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
|
||||
ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
|
||||
AsanThread *t = nullptr;
|
||||
while ((t = reinterpret_cast<AsanThread *>(
|
||||
atomic_load(¶m->t, memory_order_acquire))) == 0)
|
||||
atomic_load(¶m->t, memory_order_acquire))) == nullptr)
|
||||
internal_sched_yield();
|
||||
SetCurrentThread(t);
|
||||
return t->ThreadStart(GetTid(), ¶m->is_registered);
|
||||
@ -231,7 +237,7 @@ INTERCEPTOR(int, pthread_create, void *thread,
|
||||
StopInitOrderChecking();
|
||||
GET_STACK_TRACE_THREAD;
|
||||
int detached = 0;
|
||||
if (attr != 0)
|
||||
if (attr)
|
||||
REAL(pthread_attr_getdetachstate)(attr, &detached);
|
||||
ThreadStartParam param;
|
||||
atomic_store(¶m.t, 0, memory_order_relaxed);
|
||||
@ -270,14 +276,14 @@ INTERCEPTOR(void*, bsd_signal, int signum, void *handler) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
INTERCEPTOR(void*, signal, int signum, void *handler) {
|
||||
if (!IsDeadlySignal(signum) || common_flags()->allow_user_segv_handler) {
|
||||
return REAL(signal)(signum, handler);
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
|
||||
struct sigaction *oldact) {
|
||||
@ -292,7 +298,7 @@ int real_sigaction(int signum, const void *act, void *oldact) {
|
||||
return REAL(sigaction)(signum, (const struct sigaction *)act,
|
||||
(struct sigaction *)oldact);
|
||||
}
|
||||
} // namespace __sanitizer
|
||||
} // namespace __sanitizer
|
||||
|
||||
#elif SANITIZER_POSIX
|
||||
// We need to have defined REAL(sigaction) on posix systems.
|
||||
@ -363,40 +369,6 @@ INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int CharCmp(unsigned char c1, unsigned char c2) {
|
||||
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
|
||||
void *ctx;
|
||||
ASAN_INTERCEPTOR_ENTER(ctx, memcmp);
|
||||
if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
|
||||
ENSURE_ASAN_INITED();
|
||||
if (flags()->replace_intrin) {
|
||||
if (flags()->strict_memcmp) {
|
||||
// Check the entire regions even if the first bytes of the buffers are
|
||||
// different.
|
||||
ASAN_READ_RANGE(ctx, a1, size);
|
||||
ASAN_READ_RANGE(ctx, a2, size);
|
||||
// Fallthrough to REAL(memcmp) below.
|
||||
} else {
|
||||
unsigned char c1 = 0, c2 = 0;
|
||||
const unsigned char *s1 = (const unsigned char*)a1;
|
||||
const unsigned char *s2 = (const unsigned char*)a2;
|
||||
uptr i;
|
||||
for (i = 0; i < size; i++) {
|
||||
c1 = s1[i];
|
||||
c2 = s2[i];
|
||||
if (c1 != c2) break;
|
||||
}
|
||||
ASAN_READ_RANGE(ctx, s1, Min(i + 1, size));
|
||||
ASAN_READ_RANGE(ctx, s2, Min(i + 1, size));
|
||||
return CharCmp(c1, c2);
|
||||
}
|
||||
}
|
||||
return REAL(memcmp(a1, a2, size));
|
||||
}
|
||||
|
||||
// memcpy is called during __asan_init() from the internals of printf(...).
|
||||
// We do not treat memcpy with to==from as a bug.
|
||||
// See http://llvm.org/bugs/show_bug.cgi?id=11763.
|
||||
@ -743,7 +715,7 @@ INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
|
||||
#endif
|
||||
ENSURE_ASAN_INITED();
|
||||
int res = REAL(__cxa_atexit)(func, arg, dso_handle);
|
||||
REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
|
||||
REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
|
||||
return res;
|
||||
}
|
||||
#endif // ASAN_INTERCEPT___CXA_ATEXIT
|
||||
@ -767,7 +739,6 @@ void InitializeAsanInterceptors() {
|
||||
InitializeCommonInterceptors();
|
||||
|
||||
// Intercept mem* functions.
|
||||
ASAN_INTERCEPT_FUNC(memcmp);
|
||||
ASAN_INTERCEPT_FUNC(memmove);
|
||||
ASAN_INTERCEPT_FUNC(memset);
|
||||
if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
|
||||
@ -806,9 +777,8 @@ void InitializeAsanInterceptors() {
|
||||
ASAN_INTERCEPT_FUNC(sigaction);
|
||||
#if SANITIZER_ANDROID
|
||||
ASAN_INTERCEPT_FUNC(bsd_signal);
|
||||
#else
|
||||
ASAN_INTERCEPT_FUNC(signal);
|
||||
#endif
|
||||
ASAN_INTERCEPT_FUNC(signal);
|
||||
#endif
|
||||
#if ASAN_INTERCEPT_SWAPCONTEXT
|
||||
ASAN_INTERCEPT_FUNC(swapcontext);
|
||||
@ -827,7 +797,11 @@ void InitializeAsanInterceptors() {
|
||||
|
||||
// Intercept threading-related functions
|
||||
#if ASAN_INTERCEPT_PTHREAD_CREATE
|
||||
#if defined(ASAN_PTHREAD_CREATE_VERSION)
|
||||
ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
|
||||
#else
|
||||
ASAN_INTERCEPT_FUNC(pthread_create);
|
||||
#endif
|
||||
ASAN_INTERCEPT_FUNC(pthread_join);
|
||||
#endif
|
||||
|
||||
@ -845,4 +819,4 @@ void InitializeAsanInterceptors() {
|
||||
VReport(1, "AddressSanitizer: libc interceptors initialized\n");
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
@ -98,6 +98,12 @@ DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
|
||||
if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
|
||||
VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
|
||||
} while (0)
|
||||
#define ASAN_INTERCEPT_FUNC_VER(name, ver) \
|
||||
do { \
|
||||
if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \
|
||||
VReport( \
|
||||
1, "AddressSanitizer: failed to intercept '" #name "@@" #ver "'\n"); \
|
||||
} while (0)
|
||||
#else
|
||||
// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
|
||||
#define ASAN_INTERCEPT_FUNC(name)
|
||||
|
@ -27,10 +27,14 @@ using __sanitizer::uptr;
|
||||
extern "C" {
|
||||
// This function should be called at the very beginning of the process,
|
||||
// before any instrumented code is executed and before any call to malloc.
|
||||
// Please note that __asan_init is a macro that is replaced with
|
||||
// __asan_init_vXXX at compile-time.
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_init();
|
||||
|
||||
// This function exists purely to get a linker/loader error when using
|
||||
// incompatible versions of instrumentation and runtime library. Please note
|
||||
// that __asan_version_mismatch_check is a macro that is replaced with
|
||||
// __asan_version_mismatch_check_vXXX at compile-time.
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_version_mismatch_check();
|
||||
|
||||
// This structure is used to describe the source location of a place where
|
||||
// global was defined.
|
||||
struct __asan_global_source_location {
|
||||
@ -130,8 +134,6 @@ extern "C" {
|
||||
void __asan_report_error(uptr pc, uptr bp, uptr sp,
|
||||
uptr addr, int is_write, uptr access_size, u32 exp);
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
int __asan_set_error_exit_code(int exit_code);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_set_death_callback(void (*callback)(void));
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
@ -165,6 +167,19 @@ extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN(uptr p, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN(uptr p, uptr size);
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16_noabort(uptr p);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uptr p, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uptr p, uptr size);
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load1(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load2(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load4(uptr p, u32 exp);
|
||||
|
@ -21,8 +21,6 @@
|
||||
#include "sanitizer_common/sanitizer_stacktrace.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
|
||||
#define ASAN_DEFAULT_FAILURE_EXITCODE 1
|
||||
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
# error "The AddressSanitizer run-time should not be"
|
||||
" instrumented by AddressSanitizer"
|
||||
@ -75,12 +73,9 @@ void *AsanDoesNotSupportStaticLinkage();
|
||||
void AsanCheckDynamicRTPrereqs();
|
||||
void AsanCheckIncompatibleRT();
|
||||
|
||||
void AsanOnSIGSEGV(int, void *siginfo, void *context);
|
||||
void AsanOnDeadlySignal(int, void *siginfo, void *context);
|
||||
|
||||
void DisableReexec();
|
||||
void MaybeReexec();
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize);
|
||||
void AsanPlatformThreadInit();
|
||||
void StopInitOrderChecking();
|
||||
|
||||
// Wrapper for TLS/TSD.
|
||||
|
@ -70,14 +70,6 @@ namespace __asan {
|
||||
|
||||
void InitializePlatformInterceptors() {}
|
||||
|
||||
void DisableReexec() {
|
||||
// No need to re-exec on Linux.
|
||||
}
|
||||
|
||||
void MaybeReexec() {
|
||||
// No need to re-exec on Linux.
|
||||
}
|
||||
|
||||
void *AsanDoesNotSupportStaticLinkage() {
|
||||
// This will fail to link with -static.
|
||||
return &_DYNAMIC; // defined in link.h
|
||||
@ -117,7 +109,7 @@ void AsanCheckDynamicRTPrereqs() {
|
||||
return;
|
||||
|
||||
// Ensure that dynamic RT is the first DSO in the list
|
||||
const char *first_dso_name = 0;
|
||||
const char *first_dso_name = nullptr;
|
||||
dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
|
||||
if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
|
||||
Report("ASan runtime does not come first in initial library list; "
|
||||
@ -142,7 +134,8 @@ void AsanCheckIncompatibleRT() {
|
||||
// system libraries, causing crashes later in ASan initialization.
|
||||
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
|
||||
char filename[128];
|
||||
while (proc_maps.Next(0, 0, 0, filename, sizeof(filename), 0)) {
|
||||
while (proc_maps.Next(nullptr, nullptr, nullptr, filename,
|
||||
sizeof(filename), nullptr)) {
|
||||
if (IsDynamicRTName(filename)) {
|
||||
Report("Your application is linked against "
|
||||
"incompatible ASan runtimes.\n");
|
||||
@ -155,11 +148,7 @@ void AsanCheckIncompatibleRT() {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // SANITIZER_ANDROID
|
||||
|
||||
void AsanPlatformThreadInit() {
|
||||
// Nothing here for now.
|
||||
}
|
||||
#endif // SANITIZER_ANDROID
|
||||
|
||||
#if !SANITIZER_ANDROID
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
@ -177,6 +166,6 @@ void *AsanDlSymNext(const char *sym) {
|
||||
return dlsym(RTLD_NEXT, sym);
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
|
||||
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
|
||||
|
@ -24,26 +24,17 @@
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_mac.h"
|
||||
|
||||
#if !SANITIZER_IOS
|
||||
#include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron
|
||||
#else
|
||||
extern "C" {
|
||||
extern char ***_NSGetArgv(void);
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h> // for dladdr()
|
||||
#include <fcntl.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h> // for free()
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h> // for free()
|
||||
#include <unistd.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
namespace __asan {
|
||||
|
||||
@ -52,187 +43,12 @@ void InitializePlatformInterceptors() {}
|
||||
bool PlatformHasDifferentMemcpyAndMemmove() {
|
||||
// On OS X 10.7 memcpy() and memmove() are both resolved
|
||||
// into memmove$VARIANT$sse42.
|
||||
// See also http://code.google.com/p/address-sanitizer/issues/detail?id=34.
|
||||
// See also https://github.com/google/sanitizers/issues/34.
|
||||
// TODO(glider): need to check dynamically that memcpy() and memmove() are
|
||||
// actually the same function.
|
||||
return GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void __asan_init();
|
||||
|
||||
static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
|
||||
LowLevelAllocator allocator_for_env;
|
||||
|
||||
// Change the value of the env var |name|, leaking the original value.
|
||||
// If |name_value| is NULL, the variable is deleted from the environment,
|
||||
// otherwise the corresponding "NAME=value" string is replaced with
|
||||
// |name_value|.
|
||||
void LeakyResetEnv(const char *name, const char *name_value) {
|
||||
char **env = GetEnviron();
|
||||
uptr name_len = internal_strlen(name);
|
||||
while (*env != 0) {
|
||||
uptr len = internal_strlen(*env);
|
||||
if (len > name_len) {
|
||||
const char *p = *env;
|
||||
if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') {
|
||||
// Match.
|
||||
if (name_value) {
|
||||
// Replace the old value with the new one.
|
||||
*env = const_cast<char*>(name_value);
|
||||
} else {
|
||||
// Shift the subsequent pointers back.
|
||||
char **del = env;
|
||||
do {
|
||||
del[0] = del[1];
|
||||
} while (*del++);
|
||||
}
|
||||
}
|
||||
}
|
||||
env++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool reexec_disabled = false;
|
||||
|
||||
void DisableReexec() {
|
||||
reexec_disabled = true;
|
||||
}
|
||||
|
||||
bool DyldNeedsEnvVariable() {
|
||||
// If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if
|
||||
// DYLD_INSERT_LIBRARIES is not set.
|
||||
|
||||
#if SANITIZER_IOSSIM
|
||||
// GetMacosVersion will not work for the simulator, whose kernel version
|
||||
// is tied to the host. Use a weak linking hack for the simulator.
|
||||
// This API was introduced in the same version of the OS as the dyld
|
||||
// optimization.
|
||||
|
||||
// Check for presence of a symbol that is available on OS X 10.11+, iOS 9.0+.
|
||||
return (dlsym(RTLD_NEXT, "mach_memory_info") == nullptr);
|
||||
#else
|
||||
return (GetMacosVersion() <= MACOS_VERSION_YOSEMITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MaybeReexec() {
|
||||
if (reexec_disabled) return;
|
||||
|
||||
// Make sure the dynamic ASan runtime library is preloaded so that the
|
||||
// wrappers work. If it is not, set DYLD_INSERT_LIBRARIES and re-exec
|
||||
// ourselves.
|
||||
Dl_info info;
|
||||
CHECK(dladdr((void*)((uptr)__asan_init), &info));
|
||||
char *dyld_insert_libraries =
|
||||
const_cast<char*>(GetEnv(kDyldInsertLibraries));
|
||||
uptr old_env_len = dyld_insert_libraries ?
|
||||
internal_strlen(dyld_insert_libraries) : 0;
|
||||
uptr fname_len = internal_strlen(info.dli_fname);
|
||||
const char *dylib_name = StripModuleName(info.dli_fname);
|
||||
uptr dylib_name_len = internal_strlen(dylib_name);
|
||||
|
||||
bool lib_is_in_env =
|
||||
dyld_insert_libraries && REAL(strstr)(dyld_insert_libraries, dylib_name);
|
||||
if (DyldNeedsEnvVariable() && !lib_is_in_env) {
|
||||
// DYLD_INSERT_LIBRARIES is not set or does not contain the runtime
|
||||
// library.
|
||||
char program_name[1024];
|
||||
uint32_t buf_size = sizeof(program_name);
|
||||
_NSGetExecutablePath(program_name, &buf_size);
|
||||
char *new_env = const_cast<char*>(info.dli_fname);
|
||||
if (dyld_insert_libraries) {
|
||||
// Append the runtime dylib name to the existing value of
|
||||
// DYLD_INSERT_LIBRARIES.
|
||||
new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2);
|
||||
internal_strncpy(new_env, dyld_insert_libraries, old_env_len);
|
||||
new_env[old_env_len] = ':';
|
||||
// Copy fname_len and add a trailing zero.
|
||||
internal_strncpy(new_env + old_env_len + 1, info.dli_fname,
|
||||
fname_len + 1);
|
||||
// Ok to use setenv() since the wrappers don't depend on the value of
|
||||
// asan_inited.
|
||||
setenv(kDyldInsertLibraries, new_env, /*overwrite*/1);
|
||||
} else {
|
||||
// Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name.
|
||||
setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0);
|
||||
}
|
||||
VReport(1, "exec()-ing the program with\n");
|
||||
VReport(1, "%s=%s\n", kDyldInsertLibraries, new_env);
|
||||
VReport(1, "to enable ASan wrappers.\n");
|
||||
execv(program_name, *_NSGetArgv());
|
||||
|
||||
// We get here only if execv() failed.
|
||||
Report("ERROR: The process is launched without DYLD_INSERT_LIBRARIES, "
|
||||
"which is required for ASan to work. ASan tried to set the "
|
||||
"environment variable and re-execute itself, but execv() failed, "
|
||||
"possibly because of sandbox restrictions. Make sure to launch the "
|
||||
"executable with:\n%s=%s\n", kDyldInsertLibraries, new_env);
|
||||
CHECK("execv failed" && 0);
|
||||
}
|
||||
|
||||
if (!lib_is_in_env)
|
||||
return;
|
||||
|
||||
// DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
|
||||
// the dylib from the environment variable, because interceptors are installed
|
||||
// and we don't want our children to inherit the variable.
|
||||
|
||||
uptr env_name_len = internal_strlen(kDyldInsertLibraries);
|
||||
// Allocate memory to hold the previous env var name, its value, the '='
|
||||
// sign and the '\0' char.
|
||||
char *new_env = (char*)allocator_for_env.Allocate(
|
||||
old_env_len + 2 + env_name_len);
|
||||
CHECK(new_env);
|
||||
internal_memset(new_env, '\0', old_env_len + 2 + env_name_len);
|
||||
internal_strncpy(new_env, kDyldInsertLibraries, env_name_len);
|
||||
new_env[env_name_len] = '=';
|
||||
char *new_env_pos = new_env + env_name_len + 1;
|
||||
|
||||
// Iterate over colon-separated pieces of |dyld_insert_libraries|.
|
||||
char *piece_start = dyld_insert_libraries;
|
||||
char *piece_end = NULL;
|
||||
char *old_env_end = dyld_insert_libraries + old_env_len;
|
||||
do {
|
||||
if (piece_start[0] == ':') piece_start++;
|
||||
piece_end = REAL(strchr)(piece_start, ':');
|
||||
if (!piece_end) piece_end = dyld_insert_libraries + old_env_len;
|
||||
if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break;
|
||||
uptr piece_len = piece_end - piece_start;
|
||||
|
||||
char *filename_start =
|
||||
(char *)internal_memrchr(piece_start, '/', piece_len);
|
||||
uptr filename_len = piece_len;
|
||||
if (filename_start) {
|
||||
filename_start += 1;
|
||||
filename_len = piece_len - (filename_start - piece_start);
|
||||
} else {
|
||||
filename_start = piece_start;
|
||||
}
|
||||
|
||||
// If the current piece isn't the runtime library name,
|
||||
// append it to new_env.
|
||||
if ((dylib_name_len != filename_len) ||
|
||||
(internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) {
|
||||
if (new_env_pos != new_env + env_name_len + 1) {
|
||||
new_env_pos[0] = ':';
|
||||
new_env_pos++;
|
||||
}
|
||||
internal_strncpy(new_env_pos, piece_start, piece_len);
|
||||
new_env_pos += piece_len;
|
||||
}
|
||||
// Move on to the next piece.
|
||||
piece_start = piece_end;
|
||||
} while (piece_start < old_env_end);
|
||||
|
||||
// Can't use setenv() here, because it requires the allocator to be
|
||||
// initialized.
|
||||
// FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
|
||||
// a separate function called after InitializeAllocator().
|
||||
if (new_env_pos == new_env + env_name_len + 1) new_env = NULL;
|
||||
LeakyResetEnv(kDyldInsertLibraries, new_env);
|
||||
}
|
||||
|
||||
// No-op. Mac does not support static linkage anyway.
|
||||
void *AsanDoesNotSupportStaticLinkage() {
|
||||
return 0;
|
||||
@ -244,9 +60,6 @@ void AsanCheckDynamicRTPrereqs() {}
|
||||
// No-op. Mac does not support static linkage anyway.
|
||||
void AsanCheckIncompatibleRT() {}
|
||||
|
||||
void AsanPlatformThreadInit() {
|
||||
}
|
||||
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
@ -26,13 +26,25 @@
|
||||
// ---------------------- Replacement functions ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
static const uptr kCallocPoolSize = 1024;
|
||||
static uptr calloc_memory_for_dlsym[kCallocPoolSize];
|
||||
|
||||
static bool IsInCallocPool(const void *ptr) {
|
||||
sptr off = (sptr)ptr - (sptr)calloc_memory_for_dlsym;
|
||||
return 0 <= off && off < (sptr)kCallocPoolSize;
|
||||
}
|
||||
|
||||
INTERCEPTOR(void, free, void *ptr) {
|
||||
GET_STACK_TRACE_FREE;
|
||||
if (UNLIKELY(IsInCallocPool(ptr)))
|
||||
return;
|
||||
asan_free(ptr, &stack, FROM_MALLOC);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void, cfree, void *ptr) {
|
||||
GET_STACK_TRACE_FREE;
|
||||
if (UNLIKELY(IsInCallocPool(ptr)))
|
||||
return;
|
||||
asan_free(ptr, &stack, FROM_MALLOC);
|
||||
}
|
||||
|
||||
@ -44,8 +56,6 @@ INTERCEPTOR(void*, malloc, uptr size) {
|
||||
INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
|
||||
if (UNLIKELY(!asan_inited)) {
|
||||
// Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
|
||||
const uptr kCallocPoolSize = 1024;
|
||||
static uptr calloc_memory_for_dlsym[kCallocPoolSize];
|
||||
static uptr allocated;
|
||||
uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
|
||||
void *mem = (void*)&calloc_memory_for_dlsym[allocated];
|
||||
@ -59,6 +69,13 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
|
||||
|
||||
INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
if (UNLIKELY(IsInCallocPool(ptr))) {
|
||||
uptr offset = (uptr)ptr - (uptr)calloc_memory_for_dlsym;
|
||||
uptr copy_size = Min(size, kCallocPoolSize - offset);
|
||||
void *new_ptr = asan_malloc(size, &stack);
|
||||
internal_memcpy(new_ptr, ptr, copy_size);
|
||||
return new_ptr;
|
||||
}
|
||||
return asan_realloc(ptr, size, &stack);
|
||||
}
|
||||
|
||||
|
@ -15,348 +15,47 @@
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#if SANITIZER_MAC
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
#include <CoreFoundation/CFBase.h>
|
||||
#include <dlfcn.h>
|
||||
#include <malloc/malloc.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "asan_allocator.h"
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_report.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_stats.h"
|
||||
#include "sanitizer_common/sanitizer_mac.h"
|
||||
|
||||
// Similar code is used in Google Perftools,
|
||||
// http://code.google.com/p/google-perftools.
|
||||
|
||||
// ---------------------- Replacement functions ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
// TODO(glider): do we need both zones?
|
||||
static malloc_zone_t *system_malloc_zone = 0;
|
||||
static malloc_zone_t asan_zone;
|
||||
|
||||
INTERCEPTOR(malloc_zone_t *, malloc_create_zone,
|
||||
vm_size_t start_size, unsigned zone_flags) {
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
uptr page_size = GetPageSizeCached();
|
||||
uptr allocated_size = RoundUpTo(sizeof(asan_zone), page_size);
|
||||
malloc_zone_t *new_zone =
|
||||
(malloc_zone_t*)asan_memalign(page_size, allocated_size,
|
||||
&stack, FROM_MALLOC);
|
||||
internal_memcpy(new_zone, &asan_zone, sizeof(asan_zone));
|
||||
new_zone->zone_name = NULL; // The name will be changed anyway.
|
||||
if (GetMacosVersion() >= MACOS_VERSION_LION) {
|
||||
// Prevent the client app from overwriting the zone contents.
|
||||
// Library functions that need to modify the zone will set PROT_WRITE on it.
|
||||
// This matches the behavior of malloc_create_zone() on OSX 10.7 and higher.
|
||||
mprotect(new_zone, allocated_size, PROT_READ);
|
||||
}
|
||||
return new_zone;
|
||||
}
|
||||
|
||||
INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) {
|
||||
ENSURE_ASAN_INITED();
|
||||
return &asan_zone;
|
||||
}
|
||||
|
||||
INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) {
|
||||
// FIXME: ASan should support purgeable allocations.
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=139
|
||||
ENSURE_ASAN_INITED();
|
||||
return &asan_zone;
|
||||
}
|
||||
|
||||
INTERCEPTOR(void, malloc_make_purgeable, void *ptr) {
|
||||
// FIXME: ASan should support purgeable allocations. Ignoring them is fine
|
||||
// for now.
|
||||
ENSURE_ASAN_INITED();
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) {
|
||||
// FIXME: ASan should support purgeable allocations. Ignoring them is fine
|
||||
// for now.
|
||||
ENSURE_ASAN_INITED();
|
||||
// Must return 0 if the contents were not purged since the last call to
|
||||
// malloc_make_purgeable().
|
||||
return 0;
|
||||
}
|
||||
|
||||
INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) {
|
||||
ENSURE_ASAN_INITED();
|
||||
// Allocate |strlen("asan-") + 1 + internal_strlen(name)| bytes.
|
||||
size_t buflen = 6 + (name ? internal_strlen(name) : 0);
|
||||
InternalScopedString new_name(buflen);
|
||||
if (name && zone->introspect == asan_zone.introspect) {
|
||||
new_name.append("asan-%s", name);
|
||||
name = new_name.data();
|
||||
}
|
||||
|
||||
// Call the system malloc's implementation for both external and our zones,
|
||||
// since that appropriately changes VM region protections on the zone.
|
||||
REAL(malloc_set_zone_name)(zone, name);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void *, malloc, size_t size) {
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
void *res = asan_malloc(size, &stack);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(void, free, void *ptr) {
|
||||
ENSURE_ASAN_INITED();
|
||||
if (!ptr) return;
|
||||
GET_STACK_TRACE_FREE;
|
||||
using namespace __asan;
|
||||
#define COMMON_MALLOC_ZONE_NAME "asan"
|
||||
#define COMMON_MALLOC_ENTER() ENSURE_ASAN_INITED()
|
||||
#define COMMON_MALLOC_SANITIZER_INITIALIZED asan_inited
|
||||
#define COMMON_MALLOC_FORCE_LOCK() asan_mz_force_lock()
|
||||
#define COMMON_MALLOC_FORCE_UNLOCK() asan_mz_force_unlock()
|
||||
#define COMMON_MALLOC_MEMALIGN(alignment, size) \
|
||||
GET_STACK_TRACE_MALLOC; \
|
||||
void *p = asan_memalign(alignment, size, &stack, FROM_MALLOC)
|
||||
#define COMMON_MALLOC_MALLOC(size) \
|
||||
GET_STACK_TRACE_MALLOC; \
|
||||
void *p = asan_malloc(size, &stack)
|
||||
#define COMMON_MALLOC_REALLOC(ptr, size) \
|
||||
GET_STACK_TRACE_MALLOC; \
|
||||
void *p = asan_realloc(ptr, size, &stack);
|
||||
#define COMMON_MALLOC_CALLOC(count, size) \
|
||||
GET_STACK_TRACE_MALLOC; \
|
||||
void *p = asan_calloc(count, size, &stack);
|
||||
#define COMMON_MALLOC_VALLOC(size) \
|
||||
GET_STACK_TRACE_MALLOC; \
|
||||
void *p = asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC);
|
||||
#define COMMON_MALLOC_FREE(ptr) \
|
||||
GET_STACK_TRACE_FREE; \
|
||||
asan_free(ptr, &stack, FROM_MALLOC);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void *, realloc, void *ptr, size_t size) {
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_realloc(ptr, size, &stack);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) {
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_calloc(nmemb, size, &stack);
|
||||
}
|
||||
|
||||
INTERCEPTOR(void *, valloc, size_t size) {
|
||||
ENSURE_ASAN_INITED();
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC);
|
||||
}
|
||||
|
||||
INTERCEPTOR(size_t, malloc_good_size, size_t size) {
|
||||
ENSURE_ASAN_INITED();
|
||||
return asan_zone.introspect->good_size(&asan_zone, size);
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) {
|
||||
ENSURE_ASAN_INITED();
|
||||
CHECK(memptr);
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
void *result = asan_memalign(alignment, size, &stack, FROM_MALLOC);
|
||||
if (result) {
|
||||
*memptr = result;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(glider): the __asan_mz_* functions should be united with the Linux
|
||||
// wrappers, as they are basically copied from there.
|
||||
extern "C"
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
size_t __asan_mz_size(malloc_zone_t* zone, const void* ptr) {
|
||||
return asan_mz_size(ptr);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void *__asan_mz_malloc(malloc_zone_t *zone, uptr size) {
|
||||
if (UNLIKELY(!asan_inited)) {
|
||||
CHECK(system_malloc_zone);
|
||||
return malloc_zone_malloc(system_malloc_zone, size);
|
||||
}
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_malloc(size, &stack);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void *__asan_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) {
|
||||
if (UNLIKELY(!asan_inited)) {
|
||||
// Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
|
||||
const size_t kCallocPoolSize = 1024;
|
||||
static uptr calloc_memory_for_dlsym[kCallocPoolSize];
|
||||
static size_t allocated;
|
||||
size_t size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
|
||||
void *mem = (void*)&calloc_memory_for_dlsym[allocated];
|
||||
allocated += size_in_words;
|
||||
CHECK(allocated < kCallocPoolSize);
|
||||
return mem;
|
||||
}
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_calloc(nmemb, size, &stack);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void *__asan_mz_valloc(malloc_zone_t *zone, size_t size) {
|
||||
if (UNLIKELY(!asan_inited)) {
|
||||
CHECK(system_malloc_zone);
|
||||
return malloc_zone_valloc(system_malloc_zone, size);
|
||||
}
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC);
|
||||
}
|
||||
|
||||
#define GET_ZONE_FOR_PTR(ptr) \
|
||||
malloc_zone_t *zone_ptr = malloc_zone_from_ptr(ptr); \
|
||||
const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name
|
||||
|
||||
void ALWAYS_INLINE free_common(void *context, void *ptr) {
|
||||
if (!ptr) return;
|
||||
GET_STACK_TRACE_FREE;
|
||||
// FIXME: need to retire this flag.
|
||||
if (!flags()->mac_ignore_invalid_free) {
|
||||
asan_free(ptr, &stack, FROM_MALLOC);
|
||||
} else {
|
||||
GET_ZONE_FOR_PTR(ptr);
|
||||
WarnMacFreeUnallocated((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(glider): the allocation callbacks need to be refactored.
|
||||
extern "C"
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_mz_free(malloc_zone_t *zone, void *ptr) {
|
||||
free_common(zone, ptr);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void *__asan_mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) {
|
||||
if (!ptr) {
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_malloc(size, &stack);
|
||||
} else {
|
||||
if (asan_mz_size(ptr)) {
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_realloc(ptr, size, &stack);
|
||||
} else {
|
||||
// We can't recover from reallocating an unknown address, because
|
||||
// this would require reading at most |size| bytes from
|
||||
// potentially unaccessible memory.
|
||||
GET_STACK_TRACE_FREE;
|
||||
GET_ZONE_FOR_PTR(ptr);
|
||||
ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_mz_destroy(malloc_zone_t* zone) {
|
||||
// A no-op -- we will not be destroyed!
|
||||
Report("__asan_mz_destroy() called -- ignoring\n");
|
||||
}
|
||||
|
||||
extern "C"
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void *__asan_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) {
|
||||
if (UNLIKELY(!asan_inited)) {
|
||||
CHECK(system_malloc_zone);
|
||||
return malloc_zone_memalign(system_malloc_zone, align, size);
|
||||
}
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
return asan_memalign(align, size, &stack, FROM_MALLOC);
|
||||
}
|
||||
|
||||
// This function is currently unused, and we build with -Werror.
|
||||
#if 0
|
||||
void __asan_mz_free_definite_size(
|
||||
malloc_zone_t* zone, void *ptr, size_t size) {
|
||||
// TODO(glider): check that |size| is valid.
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
#endif
|
||||
|
||||
kern_return_t mi_enumerator(task_t task, void *,
|
||||
unsigned type_mask, vm_address_t zone_address,
|
||||
memory_reader_t reader,
|
||||
vm_range_recorder_t recorder) {
|
||||
// Should enumerate all the pointers we have. Seems like a lot of work.
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
|
||||
size_t mi_good_size(malloc_zone_t *zone, size_t size) {
|
||||
// I think it's always safe to return size, but we maybe could do better.
|
||||
return size;
|
||||
}
|
||||
|
||||
boolean_t mi_check(malloc_zone_t *zone) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void mi_print(malloc_zone_t *zone, boolean_t verbose) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void mi_log(malloc_zone_t *zone, void *address) {
|
||||
// I don't think we support anything like this
|
||||
}
|
||||
|
||||
void mi_force_lock(malloc_zone_t *zone) {
|
||||
asan_mz_force_lock();
|
||||
}
|
||||
|
||||
void mi_force_unlock(malloc_zone_t *zone) {
|
||||
asan_mz_force_unlock();
|
||||
}
|
||||
|
||||
void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
|
||||
AsanMallocStats malloc_stats;
|
||||
FillMallocStatistics(&malloc_stats);
|
||||
CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats));
|
||||
#define COMMON_MALLOC_SIZE(ptr) \
|
||||
uptr size = asan_mz_size(ptr);
|
||||
#define COMMON_MALLOC_FILL_STATS(zone, stats) \
|
||||
AsanMallocStats malloc_stats; \
|
||||
FillMallocStatistics(&malloc_stats); \
|
||||
CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); \
|
||||
internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t));
|
||||
}
|
||||
#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
|
||||
GET_STACK_TRACE_FREE; \
|
||||
ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
|
||||
#define COMMON_MALLOC_NAMESPACE __asan
|
||||
|
||||
boolean_t mi_zone_locked(malloc_zone_t *zone) {
|
||||
// UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
#include "sanitizer_common/sanitizer_malloc_mac.inc"
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
namespace __asan {
|
||||
|
||||
void ReplaceSystemMalloc() {
|
||||
static malloc_introspection_t asan_introspection;
|
||||
// Ok to use internal_memset, these places are not performance-critical.
|
||||
internal_memset(&asan_introspection, 0, sizeof(asan_introspection));
|
||||
|
||||
asan_introspection.enumerator = &mi_enumerator;
|
||||
asan_introspection.good_size = &mi_good_size;
|
||||
asan_introspection.check = &mi_check;
|
||||
asan_introspection.print = &mi_print;
|
||||
asan_introspection.log = &mi_log;
|
||||
asan_introspection.force_lock = &mi_force_lock;
|
||||
asan_introspection.force_unlock = &mi_force_unlock;
|
||||
asan_introspection.statistics = &mi_statistics;
|
||||
asan_introspection.zone_locked = &mi_zone_locked;
|
||||
|
||||
internal_memset(&asan_zone, 0, sizeof(malloc_zone_t));
|
||||
|
||||
// Use version 6 for OSX >= 10.6.
|
||||
asan_zone.version = 6;
|
||||
asan_zone.zone_name = "asan";
|
||||
asan_zone.size = &__asan_mz_size;
|
||||
asan_zone.malloc = &__asan_mz_malloc;
|
||||
asan_zone.calloc = &__asan_mz_calloc;
|
||||
asan_zone.valloc = &__asan_mz_valloc;
|
||||
asan_zone.free = &__asan_mz_free;
|
||||
asan_zone.realloc = &__asan_mz_realloc;
|
||||
asan_zone.destroy = &__asan_mz_destroy;
|
||||
asan_zone.batch_malloc = 0;
|
||||
asan_zone.batch_free = 0;
|
||||
asan_zone.free_definite_size = 0;
|
||||
asan_zone.memalign = &__asan_mz_memalign;
|
||||
asan_zone.introspect = &asan_introspection;
|
||||
|
||||
// Register the ASan zone.
|
||||
malloc_zone_register(&asan_zone);
|
||||
}
|
||||
} // namespace __asan
|
||||
|
||||
#endif // SANITIZER_MAC
|
||||
#endif
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "asan_internal.h"
|
||||
|
||||
// The full explanation of the memory mapping could be found here:
|
||||
// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
|
||||
// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm
|
||||
//
|
||||
// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000:
|
||||
// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
|
||||
@ -73,6 +73,20 @@
|
||||
// || `[0x2000000000, 0x23ffffffff]` || LowShadow ||
|
||||
// || `[0x0000000000, 0x1fffffffff]` || LowMem ||
|
||||
//
|
||||
// Default Linux/AArch64 (39-bit VMA) mapping:
|
||||
// || `[0x2000000000, 0x7fffffffff]` || highmem ||
|
||||
// || `[0x1400000000, 0x1fffffffff]` || highshadow ||
|
||||
// || `[0x1200000000, 0x13ffffffff]` || shadowgap ||
|
||||
// || `[0x1000000000, 0x11ffffffff]` || lowshadow ||
|
||||
// || `[0x0000000000, 0x0fffffffff]` || lowmem ||
|
||||
//
|
||||
// Default Linux/AArch64 (42-bit VMA) mapping:
|
||||
// || `[0x10000000000, 0x3ffffffffff]` || highmem ||
|
||||
// || `[0x0a000000000, 0x0ffffffffff]` || highshadow ||
|
||||
// || `[0x09000000000, 0x09fffffffff]` || shadowgap ||
|
||||
// || `[0x08000000000, 0x08fffffffff]` || lowshadow ||
|
||||
// || `[0x00000000000, 0x07fffffffff]` || lowmem ||
|
||||
//
|
||||
// Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000:
|
||||
// || `[0x500000000000, 0x7fffffffffff]` || HighMem ||
|
||||
// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow ||
|
||||
@ -113,11 +127,12 @@ static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000
|
||||
static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
|
||||
|
||||
#define SHADOW_SCALE kDefaultShadowScale
|
||||
#if SANITIZER_ANDROID
|
||||
# define SHADOW_OFFSET (0)
|
||||
#else
|
||||
# if SANITIZER_WORDSIZE == 32
|
||||
# if defined(__mips__)
|
||||
|
||||
|
||||
#if SANITIZER_WORDSIZE == 32
|
||||
# if SANITIZER_ANDROID
|
||||
# define SHADOW_OFFSET (0)
|
||||
# elif defined(__mips__)
|
||||
# define SHADOW_OFFSET kMIPS32_ShadowOffset32
|
||||
# elif SANITIZER_FREEBSD
|
||||
# define SHADOW_OFFSET kFreeBSD_ShadowOffset32
|
||||
@ -130,7 +145,7 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
|
||||
# else
|
||||
# define SHADOW_OFFSET kDefaultShadowOffset32
|
||||
# endif
|
||||
# else
|
||||
#else
|
||||
# if defined(__aarch64__)
|
||||
# define SHADOW_OFFSET kAArch64_ShadowOffset64
|
||||
# elif defined(__powerpc64__)
|
||||
@ -148,7 +163,6 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
|
||||
# else
|
||||
# define SHADOW_OFFSET kDefaultShort64bitShadowOffset
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
|
||||
@ -171,7 +185,8 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
|
||||
|
||||
// With the zero shadow base we can not actually map pages starting from 0.
|
||||
// This constant is somewhat arbitrary.
|
||||
#define kZeroBaseShadowStart (1 << 18)
|
||||
#define kZeroBaseShadowStart 0
|
||||
#define kZeroBaseMaxShadowStart (1 << 18)
|
||||
|
||||
#define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \
|
||||
: kZeroBaseShadowStart)
|
||||
|
@ -30,7 +30,7 @@
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
// This code has issues on OSX.
|
||||
// See https://code.google.com/p/address-sanitizer/issues/detail?id=131.
|
||||
// See https://github.com/google/sanitizers/issues/131.
|
||||
|
||||
// Fake std::nothrow_t to avoid including <new>.
|
||||
namespace std {
|
||||
@ -90,11 +90,11 @@ INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
|
||||
|
||||
#if !SANITIZER_MAC
|
||||
CXX_OPERATOR_ATTRIBUTE
|
||||
void operator delete(void *ptr) throw() {
|
||||
void operator delete(void *ptr) NOEXCEPT {
|
||||
OPERATOR_DELETE_BODY(FROM_NEW);
|
||||
}
|
||||
CXX_OPERATOR_ATTRIBUTE
|
||||
void operator delete[](void *ptr) throw() {
|
||||
void operator delete[](void *ptr) NOEXCEPT {
|
||||
OPERATOR_DELETE_BODY(FROM_NEW_BR);
|
||||
}
|
||||
CXX_OPERATOR_ATTRIBUTE
|
||||
@ -106,12 +106,12 @@ void operator delete[](void *ptr, std::nothrow_t const&) {
|
||||
OPERATOR_DELETE_BODY(FROM_NEW_BR);
|
||||
}
|
||||
CXX_OPERATOR_ATTRIBUTE
|
||||
void operator delete(void *ptr, size_t size) throw() {
|
||||
void operator delete(void *ptr, size_t size) NOEXCEPT {
|
||||
GET_STACK_TRACE_FREE;
|
||||
asan_sized_free(ptr, size, &stack, FROM_NEW);
|
||||
}
|
||||
CXX_OPERATOR_ATTRIBUTE
|
||||
void operator delete[](void *ptr, size_t size) throw() {
|
||||
void operator delete[](void *ptr, size_t size) NOEXCEPT {
|
||||
GET_STACK_TRACE_FREE;
|
||||
asan_sized_free(ptr, size, &stack, FROM_NEW_BR);
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ using namespace __asan; // NOLINT
|
||||
// that user program (un)poisons the memory it owns. It poisons memory
|
||||
// conservatively, and unpoisons progressively to make sure asan shadow
|
||||
// mapping invariant is preserved (see detailed mapping description here:
|
||||
// http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm).
|
||||
// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm).
|
||||
//
|
||||
// * if user asks to poison region [left, right), the program poisons
|
||||
// at least [left, AlignDown(right)).
|
||||
@ -354,7 +354,7 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p,
|
||||
// Make a quick sanity check that we are indeed in this state.
|
||||
//
|
||||
// FIXME: Two of these three checks are disabled until we fix
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=258.
|
||||
// https://github.com/google/sanitizers/issues/258.
|
||||
// if (d1 != d2)
|
||||
// CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1);
|
||||
if (a + granularity <= d1)
|
||||
@ -375,10 +375,10 @@ void __sanitizer_annotate_contiguous_container(const void *beg_p,
|
||||
}
|
||||
}
|
||||
|
||||
int __sanitizer_verify_contiguous_container(const void *beg_p,
|
||||
const void *mid_p,
|
||||
const void *end_p) {
|
||||
if (!flags()->detect_container_overflow) return 1;
|
||||
const void *__sanitizer_contiguous_container_find_bad_address(
|
||||
const void *beg_p, const void *mid_p, const void *end_p) {
|
||||
if (!flags()->detect_container_overflow)
|
||||
return nullptr;
|
||||
uptr beg = reinterpret_cast<uptr>(beg_p);
|
||||
uptr end = reinterpret_cast<uptr>(end_p);
|
||||
uptr mid = reinterpret_cast<uptr>(mid_p);
|
||||
@ -395,17 +395,24 @@ int __sanitizer_verify_contiguous_container(const void *beg_p,
|
||||
uptr r3_end = end;
|
||||
for (uptr i = r1_beg; i < r1_end; i++)
|
||||
if (AddressIsPoisoned(i))
|
||||
return 0;
|
||||
return reinterpret_cast<const void *>(i);
|
||||
for (uptr i = r2_beg; i < mid; i++)
|
||||
if (AddressIsPoisoned(i))
|
||||
return 0;
|
||||
return reinterpret_cast<const void *>(i);
|
||||
for (uptr i = mid; i < r2_end; i++)
|
||||
if (!AddressIsPoisoned(i))
|
||||
return 0;
|
||||
return reinterpret_cast<const void *>(i);
|
||||
for (uptr i = r3_beg; i < r3_end; i++)
|
||||
if (!AddressIsPoisoned(i))
|
||||
return 0;
|
||||
return 1;
|
||||
return reinterpret_cast<const void *>(i);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int __sanitizer_verify_contiguous_container(const void *beg_p,
|
||||
const void *mid_p,
|
||||
const void *end_p) {
|
||||
return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p,
|
||||
end_p) == nullptr;
|
||||
}
|
||||
|
||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||
|
@ -33,11 +33,11 @@
|
||||
|
||||
namespace __asan {
|
||||
|
||||
void AsanOnSIGSEGV(int, void *siginfo, void *context) {
|
||||
void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
|
||||
ScopedDeadlySignal signal_scope(GetCurrentThread());
|
||||
int code = (int)((siginfo_t*)siginfo)->si_code;
|
||||
// Write the first message using the bullet-proof write.
|
||||
if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die();
|
||||
if (18 != internal_write(2, "ASAN:DEADLYSIGNAL\n", 18)) Die();
|
||||
SignalContext sig = SignalContext::Create(siginfo, context);
|
||||
|
||||
// Access at a reasonable offset above SP, or slightly below it (to account
|
||||
@ -75,8 +75,12 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
|
||||
// unaligned memory access.
|
||||
if (IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR))
|
||||
ReportStackOverflow(sig);
|
||||
else if (signo == SIGFPE)
|
||||
ReportDeadlySignal("FPE", sig);
|
||||
else if (signo == SIGILL)
|
||||
ReportDeadlySignal("ILL", sig);
|
||||
else
|
||||
ReportSIGSEGV("SEGV", sig);
|
||||
ReportDeadlySignal("SEGV", sig);
|
||||
}
|
||||
|
||||
// ---------------------- TSD ---------------- {{{1
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
// This file contains error reporting code.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "asan_flags.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_mapping.h"
|
||||
@ -27,9 +28,11 @@ namespace __asan {
|
||||
|
||||
// -------------------- User-specified callbacks ----------------- {{{1
|
||||
static void (*error_report_callback)(const char*);
|
||||
static char *error_message_buffer = 0;
|
||||
static char *error_message_buffer = nullptr;
|
||||
static uptr error_message_buffer_pos = 0;
|
||||
static uptr error_message_buffer_size = 0;
|
||||
static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED);
|
||||
static const unsigned kAsanBuggyPcPoolSize = 25;
|
||||
static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
|
||||
|
||||
struct ReportData {
|
||||
uptr pc;
|
||||
@ -45,16 +48,20 @@ static bool report_happened = false;
|
||||
static ReportData report_data = {};
|
||||
|
||||
void AppendToErrorMessageBuffer(const char *buffer) {
|
||||
if (error_message_buffer) {
|
||||
uptr length = internal_strlen(buffer);
|
||||
CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
|
||||
uptr remaining = error_message_buffer_size - error_message_buffer_pos;
|
||||
internal_strncpy(error_message_buffer + error_message_buffer_pos,
|
||||
buffer, remaining);
|
||||
error_message_buffer[error_message_buffer_size - 1] = '\0';
|
||||
// FIXME: reallocate the buffer instead of truncating the message.
|
||||
error_message_buffer_pos += Min(remaining, length);
|
||||
BlockingMutexLock l(&error_message_buf_mutex);
|
||||
if (!error_message_buffer) {
|
||||
error_message_buffer =
|
||||
(char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
|
||||
error_message_buffer_pos = 0;
|
||||
}
|
||||
uptr length = internal_strlen(buffer);
|
||||
RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos);
|
||||
uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos;
|
||||
internal_strncpy(error_message_buffer + error_message_buffer_pos,
|
||||
buffer, remaining);
|
||||
error_message_buffer[kErrorMessageBufferSize - 1] = '\0';
|
||||
// FIXME: reallocate the buffer instead of truncating the message.
|
||||
error_message_buffer_pos += Min(remaining, length);
|
||||
}
|
||||
|
||||
// ---------------------- Decorator ------------------------------ {{{1
|
||||
@ -373,7 +380,7 @@ static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr,
|
||||
uptr next_var_beg) {
|
||||
uptr var_end = var.beg + var.size;
|
||||
uptr addr_end = addr + access_size;
|
||||
const char *pos_descr = 0;
|
||||
const char *pos_descr = nullptr;
|
||||
// If the variable [var.beg, var_end) is the nearest variable to the
|
||||
// current memory access, indicate it in the log.
|
||||
if (addr >= var.beg) {
|
||||
@ -544,7 +551,7 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {
|
||||
StackTrace alloc_stack = chunk.GetAllocStack();
|
||||
char tname[128];
|
||||
Decorator d;
|
||||
AsanThreadContext *free_thread = 0;
|
||||
AsanThreadContext *free_thread = nullptr;
|
||||
if (chunk.FreeTid() != kInvalidTid) {
|
||||
free_thread = GetThreadContextByTidLocked(chunk.FreeTid());
|
||||
Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
|
||||
@ -621,26 +628,93 @@ void DescribeThread(AsanThreadContext *context) {
|
||||
// immediately after printing error report.
|
||||
class ScopedInErrorReport {
|
||||
public:
|
||||
explicit ScopedInErrorReport(ReportData *report = nullptr) {
|
||||
static atomic_uint32_t num_calls;
|
||||
static u32 reporting_thread_tid;
|
||||
if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
|
||||
explicit ScopedInErrorReport(ReportData *report = nullptr,
|
||||
bool fatal = false) {
|
||||
halt_on_error_ = fatal || flags()->halt_on_error;
|
||||
|
||||
if (lock_.TryLock()) {
|
||||
StartReporting(report);
|
||||
return;
|
||||
}
|
||||
|
||||
// ASan found two bugs in different threads simultaneously.
|
||||
|
||||
u32 current_tid = GetCurrentTidOrInvalid();
|
||||
if (reporting_thread_tid_ == current_tid ||
|
||||
reporting_thread_tid_ == kInvalidTid) {
|
||||
// This is either asynch signal or nested error during error reporting.
|
||||
// Fail simple to avoid deadlocks in Report().
|
||||
|
||||
// Can't use Report() here because of potential deadlocks
|
||||
// in nested signal handlers.
|
||||
const char msg[] = "AddressSanitizer: nested bug in the same thread, "
|
||||
"aborting.\n";
|
||||
WriteToFile(kStderrFd, msg, sizeof(msg));
|
||||
|
||||
internal__exit(common_flags()->exitcode);
|
||||
}
|
||||
|
||||
if (halt_on_error_) {
|
||||
// Do not print more than one report, otherwise they will mix up.
|
||||
// Error reporting functions shouldn't return at this situation, as
|
||||
// they are defined as no-return.
|
||||
// they are effectively no-returns.
|
||||
|
||||
Report("AddressSanitizer: while reporting a bug found another one. "
|
||||
"Ignoring.\n");
|
||||
u32 current_tid = GetCurrentTidOrInvalid();
|
||||
if (current_tid != reporting_thread_tid) {
|
||||
// ASan found two bugs in different threads simultaneously. Sleep
|
||||
// long enough to make sure that the thread which started to print
|
||||
// an error report will finish doing it.
|
||||
SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
|
||||
}
|
||||
"Ignoring.\n");
|
||||
|
||||
// Sleep long enough to make sure that the thread which started
|
||||
// to print an error report will finish doing it.
|
||||
SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
|
||||
|
||||
// If we're still not dead for some reason, use raw _exit() instead of
|
||||
// Die() to bypass any additional checks.
|
||||
internal__exit(flags()->exitcode);
|
||||
internal__exit(common_flags()->exitcode);
|
||||
} else {
|
||||
// The other thread will eventually finish reporting
|
||||
// so it's safe to wait
|
||||
lock_.Lock();
|
||||
}
|
||||
|
||||
StartReporting(report);
|
||||
}
|
||||
|
||||
~ScopedInErrorReport() {
|
||||
// Make sure the current thread is announced.
|
||||
DescribeThread(GetCurrentThread());
|
||||
// We may want to grab this lock again when printing stats.
|
||||
asanThreadRegistry().Unlock();
|
||||
// Print memory stats.
|
||||
if (flags()->print_stats)
|
||||
__asan_print_accumulated_stats();
|
||||
|
||||
// Copy the message buffer so that we could start logging without holding a
|
||||
// lock that gets aquired during printing.
|
||||
InternalScopedBuffer<char> buffer_copy(kErrorMessageBufferSize);
|
||||
{
|
||||
BlockingMutexLock l(&error_message_buf_mutex);
|
||||
internal_memcpy(buffer_copy.data(),
|
||||
error_message_buffer, kErrorMessageBufferSize);
|
||||
}
|
||||
|
||||
// Remove color sequences since logs cannot print them.
|
||||
RemoveANSIEscapeSequencesFromString(buffer_copy.data());
|
||||
|
||||
LogFullErrorReport(buffer_copy.data());
|
||||
|
||||
if (error_report_callback) {
|
||||
error_report_callback(buffer_copy.data());
|
||||
}
|
||||
CommonSanitizerReportMutex.Unlock();
|
||||
reporting_thread_tid_ = kInvalidTid;
|
||||
lock_.Unlock();
|
||||
if (halt_on_error_) {
|
||||
Report("ABORTING\n");
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void StartReporting(ReportData *report) {
|
||||
if (report) report_data = *report;
|
||||
report_happened = true;
|
||||
ASAN_ON_ERROR();
|
||||
@ -650,27 +724,19 @@ class ScopedInErrorReport {
|
||||
// recursive reports.
|
||||
asanThreadRegistry().Lock();
|
||||
CommonSanitizerReportMutex.Lock();
|
||||
reporting_thread_tid = GetCurrentTidOrInvalid();
|
||||
reporting_thread_tid_ = GetCurrentTidOrInvalid();
|
||||
Printf("===================================================="
|
||||
"=============\n");
|
||||
}
|
||||
// Destructor is NORETURN, as functions that report errors are.
|
||||
NORETURN ~ScopedInErrorReport() {
|
||||
// Make sure the current thread is announced.
|
||||
DescribeThread(GetCurrentThread());
|
||||
// We may want to grab this lock again when printing stats.
|
||||
asanThreadRegistry().Unlock();
|
||||
// Print memory stats.
|
||||
if (flags()->print_stats)
|
||||
__asan_print_accumulated_stats();
|
||||
if (error_report_callback) {
|
||||
error_report_callback(error_message_buffer);
|
||||
}
|
||||
Report("ABORTING\n");
|
||||
Die();
|
||||
}
|
||||
|
||||
static StaticSpinMutex lock_;
|
||||
static u32 reporting_thread_tid_;
|
||||
bool halt_on_error_;
|
||||
};
|
||||
|
||||
StaticSpinMutex ScopedInErrorReport::lock_;
|
||||
u32 ScopedInErrorReport::reporting_thread_tid_;
|
||||
|
||||
void ReportStackOverflow(const SignalContext &sig) {
|
||||
ScopedInErrorReport in_report;
|
||||
Decorator d;
|
||||
@ -686,8 +752,8 @@ void ReportStackOverflow(const SignalContext &sig) {
|
||||
ReportErrorSummary("stack-overflow", &stack);
|
||||
}
|
||||
|
||||
void ReportSIGSEGV(const char *description, const SignalContext &sig) {
|
||||
ScopedInErrorReport in_report;
|
||||
void ReportDeadlySignal(const char *description, const SignalContext &sig) {
|
||||
ScopedInErrorReport in_report(/*report*/nullptr, /*fatal*/true);
|
||||
Decorator d;
|
||||
Printf("%s", d.Warning());
|
||||
Report(
|
||||
@ -703,7 +769,7 @@ void ReportSIGSEGV(const char *description, const SignalContext &sig) {
|
||||
stack.Print();
|
||||
MaybeDumpInstructionBytes(sig.pc);
|
||||
Printf("AddressSanitizer can not provide additional info.\n");
|
||||
ReportErrorSummary("SEGV", &stack);
|
||||
ReportErrorSummary(description, &stack);
|
||||
}
|
||||
|
||||
void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
|
||||
@ -744,7 +810,7 @@ void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
|
||||
stack.Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
ReportErrorSummary("new-delete-type-mismatch", &stack);
|
||||
Report("HINT: if you don't care about these warnings you may set "
|
||||
Report("HINT: if you don't care about these errors you may set "
|
||||
"ASAN_OPTIONS=new_delete_type_mismatch=0\n");
|
||||
}
|
||||
|
||||
@ -784,7 +850,7 @@ void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
|
||||
stack.Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
ReportErrorSummary("alloc-dealloc-mismatch", &stack);
|
||||
Report("HINT: if you don't care about these warnings you may set "
|
||||
Report("HINT: if you don't care about these errors you may set "
|
||||
"ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
|
||||
}
|
||||
|
||||
@ -886,7 +952,7 @@ void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
|
||||
Printf(" [2]:\n");
|
||||
StackDepotGet(stack_id2).Print();
|
||||
}
|
||||
Report("HINT: if you don't care about these warnings you may set "
|
||||
Report("HINT: if you don't care about these errors you may set "
|
||||
"ASAN_OPTIONS=detect_odr_violation=0\n");
|
||||
InternalScopedString error_msg(256);
|
||||
error_msg.append("odr-violation: global '%s' at %s",
|
||||
@ -925,17 +991,6 @@ static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
|
||||
}
|
||||
// ----------------------- Mac-specific reports ----------------- {{{1
|
||||
|
||||
void WarnMacFreeUnallocated(uptr addr, uptr zone_ptr, const char *zone_name,
|
||||
BufferedStackTrace *stack) {
|
||||
// Just print a warning here.
|
||||
Printf("free_common(%p) -- attempting to free unallocated memory.\n"
|
||||
"AddressSanitizer is ignoring this error on Mac OS now.\n",
|
||||
addr);
|
||||
PrintZoneForPointer(addr, zone_ptr, zone_name);
|
||||
stack->Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
}
|
||||
|
||||
void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
|
||||
BufferedStackTrace *stack) {
|
||||
ScopedInErrorReport in_report;
|
||||
@ -947,24 +1002,23 @@ void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
|
||||
DescribeHeapAddress(addr, 1);
|
||||
}
|
||||
|
||||
void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
|
||||
BufferedStackTrace *stack) {
|
||||
ScopedInErrorReport in_report;
|
||||
Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
|
||||
"This is an unrecoverable problem, exiting now.\n",
|
||||
addr);
|
||||
PrintZoneForPointer(addr, zone_ptr, zone_name);
|
||||
stack->Print();
|
||||
DescribeHeapAddress(addr, 1);
|
||||
// -------------- SuppressErrorReport -------------- {{{1
|
||||
// Avoid error reports duplicating for ASan recover mode.
|
||||
static bool SuppressErrorReport(uptr pc) {
|
||||
if (!common_flags()->suppress_equal_pcs) return false;
|
||||
for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) {
|
||||
uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]);
|
||||
if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp,
|
||||
pc, memory_order_relaxed))
|
||||
return false;
|
||||
if (cmp == pc) return true;
|
||||
}
|
||||
Die();
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
// --------------------------- Interface --------------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
||||
uptr access_size, u32 exp) {
|
||||
void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
|
||||
uptr access_size, u32 exp, bool fatal) {
|
||||
if (!fatal && SuppressErrorReport(pc)) return;
|
||||
ENABLE_FRAME_POINTER;
|
||||
|
||||
// Optimization experiments.
|
||||
@ -1033,7 +1087,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
||||
|
||||
ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size,
|
||||
bug_descr };
|
||||
ScopedInErrorReport in_report(&report);
|
||||
ScopedInErrorReport in_report(&report, fatal);
|
||||
|
||||
Decorator d;
|
||||
Printf("%s", d.Warning());
|
||||
@ -1059,14 +1113,21 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
||||
PrintShadowMemoryForAddress(addr);
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
// --------------------------- Interface --------------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
||||
uptr access_size, u32 exp) {
|
||||
ENABLE_FRAME_POINTER;
|
||||
bool fatal = flags()->halt_on_error;
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal);
|
||||
}
|
||||
|
||||
void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
|
||||
BlockingMutexLock l(&error_message_buf_mutex);
|
||||
error_report_callback = callback;
|
||||
if (callback) {
|
||||
error_message_buffer_size = 1 << 16;
|
||||
error_message_buffer =
|
||||
(char*)MmapOrDie(error_message_buffer_size, __func__);
|
||||
error_message_buffer_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void __asan_describe_address(uptr addr) {
|
||||
@ -1117,7 +1178,7 @@ SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __sanitizer_ptr_cmp(void *a, void *b) {
|
||||
CheckForInvalidPointerPair(a, b);
|
||||
}
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
||||
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
|
||||
// Provide default implementation of __asan_on_error that does nothing
|
||||
|
@ -49,44 +49,39 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size);
|
||||
void DescribeThread(AsanThreadContext *context);
|
||||
|
||||
// Different kinds of error reports.
|
||||
void NORETURN ReportStackOverflow(const SignalContext &sig);
|
||||
void NORETURN ReportSIGSEGV(const char *description, const SignalContext &sig);
|
||||
void NORETURN ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
|
||||
BufferedStackTrace *free_stack);
|
||||
void NORETURN ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack);
|
||||
void NORETURN ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack);
|
||||
void NORETURN ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
|
||||
AllocType alloc_type,
|
||||
AllocType dealloc_type);
|
||||
void NORETURN
|
||||
ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack);
|
||||
void NORETURN
|
||||
ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
|
||||
BufferedStackTrace *stack);
|
||||
void NORETURN
|
||||
ReportStringFunctionMemoryRangesOverlap(const char *function,
|
||||
const char *offset1, uptr length1,
|
||||
const char *offset2, uptr length2,
|
||||
BufferedStackTrace *stack);
|
||||
void NORETURN ReportStringFunctionSizeOverflow(uptr offset, uptr size,
|
||||
BufferedStackTrace *stack);
|
||||
void NORETURN
|
||||
ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
|
||||
uptr old_mid, uptr new_mid,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
|
||||
uptr access_size, u32 exp, bool fatal);
|
||||
void ReportStackOverflow(const SignalContext &sig);
|
||||
void ReportDeadlySignal(const char *description, const SignalContext &sig);
|
||||
void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
|
||||
BufferedStackTrace *free_stack);
|
||||
void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack);
|
||||
void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack);
|
||||
void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
|
||||
AllocType alloc_type,
|
||||
AllocType dealloc_type);
|
||||
void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack);
|
||||
void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportStringFunctionMemoryRangesOverlap(const char *function,
|
||||
const char *offset1, uptr length1,
|
||||
const char *offset2, uptr length2,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
|
||||
uptr old_mid, uptr new_mid,
|
||||
BufferedStackTrace *stack);
|
||||
|
||||
void NORETURN
|
||||
ReportODRViolation(const __asan_global *g1, u32 stack_id1,
|
||||
const __asan_global *g2, u32 stack_id2);
|
||||
void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
|
||||
const __asan_global *g2, u32 stack_id2);
|
||||
|
||||
// Mac-specific errors and warnings.
|
||||
void WarnMacFreeUnallocated(uptr addr, uptr zone_ptr, const char *zone_name,
|
||||
BufferedStackTrace *stack);
|
||||
void NORETURN ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr,
|
||||
const char *zone_name,
|
||||
BufferedStackTrace *stack);
|
||||
void NORETURN ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr,
|
||||
const char *zone_name,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr,
|
||||
const char *zone_name,
|
||||
BufferedStackTrace *stack);
|
||||
void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr,
|
||||
const char *zone_name,
|
||||
BufferedStackTrace *stack);
|
||||
|
||||
} // namespace __asan
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
// Main file of the ASan run-time library.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "asan_activation.h"
|
||||
#include "asan_allocator.h"
|
||||
#include "asan_interceptors.h"
|
||||
@ -56,11 +57,6 @@ static void AsanDie() {
|
||||
UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
|
||||
}
|
||||
}
|
||||
if (common_flags()->coverage)
|
||||
__sanitizer_cov_dump();
|
||||
if (flags()->abort_on_error)
|
||||
Abort();
|
||||
internal__exit(flags()->exitcode);
|
||||
}
|
||||
|
||||
static void AsanCheckFailed(const char *file, int line, const char *cond,
|
||||
@ -117,13 +113,18 @@ static void OnLowLevelAllocate(uptr ptr, uptr size) {
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_report_ ## type ## size(uptr addr) { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size, 0); \
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \
|
||||
} \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size, exp); \
|
||||
}
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \
|
||||
} \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_report_ ## type ## size ## _noabort(uptr addr) { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \
|
||||
} \
|
||||
|
||||
ASAN_REPORT_ERROR(load, false, 1)
|
||||
ASAN_REPORT_ERROR(load, false, 2)
|
||||
@ -136,22 +137,27 @@ ASAN_REPORT_ERROR(store, true, 4)
|
||||
ASAN_REPORT_ERROR(store, true, 8)
|
||||
ASAN_REPORT_ERROR(store, true, 16)
|
||||
|
||||
#define ASAN_REPORT_ERROR_N(type, is_write) \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size, 0); \
|
||||
} \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
#define ASAN_REPORT_ERROR_N(type, is_write) \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \
|
||||
} \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size, exp); \
|
||||
}
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \
|
||||
} \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \
|
||||
} \
|
||||
|
||||
ASAN_REPORT_ERROR_N(load, false)
|
||||
ASAN_REPORT_ERROR_N(store, true)
|
||||
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg) \
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \
|
||||
uptr sp = MEM_TO_SHADOW(addr); \
|
||||
uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
|
||||
: *reinterpret_cast<u16 *>(sp); \
|
||||
@ -163,7 +169,8 @@ ASAN_REPORT_ERROR_N(store, true)
|
||||
*__asan_test_only_reported_buggy_pointer = addr; \
|
||||
} else { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size, exp_arg); \
|
||||
ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, \
|
||||
fatal); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
@ -171,12 +178,16 @@ ASAN_REPORT_ERROR_N(store, true)
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_##type##size(uptr addr) { \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0) \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \
|
||||
} \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_exp_##type##size(uptr addr, u32 exp) { \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp) \
|
||||
}
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \
|
||||
} \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_##type##size ## _noabort(uptr addr) { \
|
||||
ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \
|
||||
} \
|
||||
|
||||
ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1)
|
||||
ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2)
|
||||
@ -194,7 +205,7 @@ NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_loadN(uptr addr, uptr size) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
__asan_report_error(pc, bp, sp, addr, false, size, 0);
|
||||
ReportGenericError(pc, bp, sp, addr, false, size, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,7 +214,16 @@ NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_exp_loadN(uptr addr, uptr size, u32 exp) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
__asan_report_error(pc, bp, sp, addr, false, size, exp);
|
||||
ReportGenericError(pc, bp, sp, addr, false, size, exp, true);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_loadN_noabort(uptr addr, uptr size) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, false, size, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,7 +232,7 @@ NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_storeN(uptr addr, uptr size) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
__asan_report_error(pc, bp, sp, addr, true, size, 0);
|
||||
ReportGenericError(pc, bp, sp, addr, true, size, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +241,16 @@ NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_exp_storeN(uptr addr, uptr size, u32 exp) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
__asan_report_error(pc, bp, sp, addr, true, size, exp);
|
||||
ReportGenericError(pc, bp, sp, addr, true, size, exp, true);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE
|
||||
void __asan_storeN_noabort(uptr addr, uptr size) {
|
||||
if (__asan_region_is_poisoned(addr, size)) {
|
||||
GET_CALLER_PC_BP_SP;
|
||||
ReportGenericError(pc, bp, sp, addr, true, size, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,16 +288,15 @@ static NOINLINE void force_interface_symbols() {
|
||||
case 22: __asan_report_exp_store8(0, 0); break;
|
||||
case 23: __asan_report_exp_store16(0, 0); break;
|
||||
case 24: __asan_report_exp_store_n(0, 0, 0); break;
|
||||
case 25: __asan_register_globals(0, 0); break;
|
||||
case 26: __asan_unregister_globals(0, 0); break;
|
||||
case 27: __asan_set_death_callback(0); break;
|
||||
case 28: __asan_set_error_report_callback(0); break;
|
||||
case 25: __asan_register_globals(nullptr, 0); break;
|
||||
case 26: __asan_unregister_globals(nullptr, 0); break;
|
||||
case 27: __asan_set_death_callback(nullptr); break;
|
||||
case 28: __asan_set_error_report_callback(nullptr); break;
|
||||
case 29: __asan_handle_no_return(); break;
|
||||
case 30: __asan_address_is_poisoned(0); break;
|
||||
case 31: __asan_poison_memory_region(0, 0); break;
|
||||
case 32: __asan_unpoison_memory_region(0, 0); break;
|
||||
case 33: __asan_set_error_exit_code(0); break;
|
||||
case 34: __asan_before_dynamic_init(0); break;
|
||||
case 30: __asan_address_is_poisoned(nullptr); break;
|
||||
case 31: __asan_poison_memory_region(nullptr, 0); break;
|
||||
case 32: __asan_unpoison_memory_region(nullptr, 0); break;
|
||||
case 34: __asan_before_dynamic_init(nullptr); break;
|
||||
case 35: __asan_after_dynamic_init(); break;
|
||||
case 36: __asan_poison_stack_memory(0, 0); break;
|
||||
case 37: __asan_unpoison_stack_memory(0, 0); break;
|
||||
@ -298,9 +326,25 @@ static void InitializeHighMemEnd() {
|
||||
}
|
||||
|
||||
static void ProtectGap(uptr addr, uptr size) {
|
||||
if (!flags()->protect_shadow_gap)
|
||||
return;
|
||||
void *res = MmapNoAccess(addr, size, "shadow gap");
|
||||
if (addr == (uptr)res)
|
||||
return;
|
||||
// A few pages at the start of the address space can not be protected.
|
||||
// But we really want to protect as much as possible, to prevent this memory
|
||||
// being returned as a result of a non-FIXED mmap().
|
||||
if (addr == kZeroBaseShadowStart) {
|
||||
uptr step = GetPageSizeCached();
|
||||
while (size > step && addr < kZeroBaseMaxShadowStart) {
|
||||
addr += step;
|
||||
size -= step;
|
||||
void *res = MmapNoAccess(addr, size, "shadow gap");
|
||||
if (addr == (uptr)res)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Report("ERROR: Failed to protect the shadow gap. "
|
||||
"ASan cannot proceed correctly. ABORTING.\n");
|
||||
DumpProcessMap();
|
||||
@ -363,12 +407,12 @@ static void AsanInitInternal() {
|
||||
CHECK(!asan_init_is_running && "ASan init calls itself!");
|
||||
asan_init_is_running = true;
|
||||
|
||||
CacheBinaryName();
|
||||
|
||||
// Initialize flags. This must be done early, because most of the
|
||||
// initialization steps look at flags().
|
||||
InitializeFlags();
|
||||
|
||||
CacheBinaryName();
|
||||
|
||||
AsanCheckIncompatibleRT();
|
||||
AsanCheckDynamicRTPrereqs();
|
||||
|
||||
@ -381,7 +425,7 @@ static void AsanInitInternal() {
|
||||
AsanDoesNotSupportStaticLinkage();
|
||||
|
||||
// Install tool-specific callbacks in sanitizer_common.
|
||||
SetDieCallback(AsanDie);
|
||||
AddDieCallback(AsanDie);
|
||||
SetCheckFailedCallback(AsanCheckFailed);
|
||||
SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
|
||||
|
||||
@ -457,7 +501,7 @@ static void AsanInitInternal() {
|
||||
}
|
||||
|
||||
AsanTSDInit(PlatformTSDDtor);
|
||||
InstallDeadlySignalHandlers(AsanOnSIGSEGV);
|
||||
InstallDeadlySignalHandlers(AsanOnDeadlySignal);
|
||||
|
||||
AllocatorOptions allocator_options;
|
||||
allocator_options.SetFrom(flags(), common_flags());
|
||||
@ -531,24 +575,26 @@ public: // NOLINT
|
||||
static AsanInitializer asan_initializer;
|
||||
#endif // ASAN_DYNAMIC
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
int NOINLINE __asan_set_error_exit_code(int exit_code) {
|
||||
int old = flags()->exitcode;
|
||||
flags()->exitcode = exit_code;
|
||||
return old;
|
||||
}
|
||||
|
||||
void NOINLINE __asan_handle_no_return() {
|
||||
int local_stack;
|
||||
AsanThread *curr_thread = GetCurrentThread();
|
||||
CHECK(curr_thread);
|
||||
uptr PageSize = GetPageSizeCached();
|
||||
uptr top = curr_thread->stack_top();
|
||||
uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
|
||||
uptr top, bottom;
|
||||
if (curr_thread) {
|
||||
top = curr_thread->stack_top();
|
||||
bottom = ((uptr)&local_stack - PageSize) & ~(PageSize - 1);
|
||||
} else {
|
||||
// If we haven't seen this thread, try asking the OS for stack bounds.
|
||||
uptr tls_addr, tls_size, stack_size;
|
||||
GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr,
|
||||
&tls_size);
|
||||
top = bottom + stack_size;
|
||||
}
|
||||
static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
|
||||
if (top - bottom > kMaxExpectedCleanupSize) {
|
||||
static bool reported_warning = false;
|
||||
@ -559,12 +605,12 @@ void NOINLINE __asan_handle_no_return() {
|
||||
"stack top: %p; bottom %p; size: %p (%zd)\n"
|
||||
"False positive error reports may follow\n"
|
||||
"For details see "
|
||||
"http://code.google.com/p/address-sanitizer/issues/detail?id=189\n",
|
||||
"https://github.com/google/sanitizers/issues/189\n",
|
||||
top, bottom, top - bottom, top - bottom);
|
||||
return;
|
||||
}
|
||||
PoisonShadow(bottom, top - bottom, 0);
|
||||
if (curr_thread->has_fake_stack())
|
||||
if (curr_thread && curr_thread->has_fake_stack())
|
||||
curr_thread->fake_stack()->HandleNoReturn();
|
||||
}
|
||||
|
||||
@ -578,3 +624,7 @@ void __asan_init() {
|
||||
AsanActivate();
|
||||
AsanInitInternal();
|
||||
}
|
||||
|
||||
void __asan_version_mismatch_check() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
// ASan-private header for asan_stack.cc.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASAN_STACK_H
|
||||
#define ASAN_STACK_H
|
||||
|
||||
@ -48,15 +49,15 @@ void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth,
|
||||
uptr stack_bottom = t->stack_bottom();
|
||||
ScopedUnwinding unwind_scope(t);
|
||||
stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast);
|
||||
} else if (t == 0 && !fast) {
|
||||
} else if (!t && !fast) {
|
||||
/* If GetCurrentThread() has failed, try to do slow unwind anyways. */
|
||||
stack->Unwind(max_depth, pc, bp, context, 0, 0, false);
|
||||
}
|
||||
}
|
||||
#endif // SANITIZER_WINDOWS
|
||||
#endif // SANITIZER_WINDOWS
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
|
||||
// as early as possible (in functions exposed to the user), as we generally
|
||||
@ -115,4 +116,4 @@ void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth,
|
||||
stack.Print(); \
|
||||
}
|
||||
|
||||
#endif // ASAN_STACK_H
|
||||
#endif // ASAN_STACK_H
|
||||
|
@ -42,7 +42,7 @@ void AsanThreadContext::OnCreated(void *arg) {
|
||||
|
||||
void AsanThreadContext::OnFinished() {
|
||||
// Drop the link to the AsanThread object.
|
||||
thread = 0;
|
||||
thread = nullptr;
|
||||
}
|
||||
|
||||
// MIPS requires aligned address
|
||||
@ -125,7 +125,7 @@ void AsanThread::Destroy() {
|
||||
FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
|
||||
uptr stack_size = this->stack_size();
|
||||
if (stack_size == 0) // stack_size is not yet available, don't use FakeStack.
|
||||
return 0;
|
||||
return nullptr;
|
||||
uptr old_val = 0;
|
||||
// fake_stack_ has 3 states:
|
||||
// 0 -- not initialized
|
||||
@ -146,11 +146,11 @@ FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
|
||||
SetTLSFakeStack(fake_stack_);
|
||||
return fake_stack_;
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AsanThread::Init() {
|
||||
fake_stack_ = 0; // Will be initialized lazily if needed.
|
||||
fake_stack_ = nullptr; // Will be initialized lazily if needed.
|
||||
CHECK_EQ(this->stack_size(), 0U);
|
||||
SetThreadStackAndTls();
|
||||
CHECK_GT(this->stack_size(), 0U);
|
||||
@ -161,13 +161,12 @@ void AsanThread::Init() {
|
||||
VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
|
||||
(void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
|
||||
&local);
|
||||
AsanPlatformThreadInit();
|
||||
}
|
||||
|
||||
thread_return_t AsanThread::ThreadStart(
|
||||
uptr os_id, atomic_uintptr_t *signal_thread_is_registered) {
|
||||
Init();
|
||||
asanThreadRegistry().StartThread(tid(), os_id, 0);
|
||||
asanThreadRegistry().StartThread(tid(), os_id, nullptr);
|
||||
if (signal_thread_is_registered)
|
||||
atomic_store(signal_thread_is_registered, 1, memory_order_release);
|
||||
|
||||
@ -277,7 +276,7 @@ AsanThread *GetCurrentThread() {
|
||||
return tctx->thread;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
return context->thread;
|
||||
}
|
||||
@ -302,7 +301,7 @@ AsanThread *FindThreadByStackAddress(uptr addr) {
|
||||
AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
|
||||
asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
|
||||
(void *)addr));
|
||||
return tctx ? tctx->thread : 0;
|
||||
return tctx ? tctx->thread : nullptr;
|
||||
}
|
||||
|
||||
void EnsureMainThreadIDIsCorrect() {
|
||||
@ -315,10 +314,10 @@ void EnsureMainThreadIDIsCorrect() {
|
||||
__asan::AsanThread *GetAsanThreadByOsIDLocked(uptr os_id) {
|
||||
__asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
|
||||
__asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
|
||||
if (!context) return 0;
|
||||
if (!context) return nullptr;
|
||||
return context->thread;
|
||||
}
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
// --- Implementation of LSan-specific functions --- {{{1
|
||||
namespace __lsan {
|
||||
@ -355,4 +354,4 @@ void UnlockThreadRegistry() {
|
||||
void EnsureMainThreadIDIsCorrect() {
|
||||
__asan::EnsureMainThreadIDIsCorrect();
|
||||
}
|
||||
} // namespace __lsan
|
||||
} // namespace __lsan
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
// ASan-private header for asan_thread.cc.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASAN_THREAD_H
|
||||
#define ASAN_THREAD_H
|
||||
|
||||
@ -36,7 +37,7 @@ class AsanThreadContext : public ThreadContextBase {
|
||||
explicit AsanThreadContext(int tid)
|
||||
: ThreadContextBase(tid), announced(false),
|
||||
destructor_iterations(GetPthreadDestructorIterations()), stack_id(0),
|
||||
thread(0) {}
|
||||
thread(nullptr) {}
|
||||
bool announced;
|
||||
u8 destructor_iterations;
|
||||
u32 stack_id;
|
||||
@ -84,8 +85,8 @@ class AsanThread {
|
||||
void DeleteFakeStack(int tid) {
|
||||
if (!fake_stack_) return;
|
||||
FakeStack *t = fake_stack_;
|
||||
fake_stack_ = 0;
|
||||
SetTLSFakeStack(0);
|
||||
fake_stack_ = nullptr;
|
||||
SetTLSFakeStack(nullptr);
|
||||
t->Destroy(tid);
|
||||
}
|
||||
|
||||
@ -95,7 +96,7 @@ class AsanThread {
|
||||
|
||||
FakeStack *fake_stack() {
|
||||
if (!__asan_option_detect_stack_use_after_return)
|
||||
return 0;
|
||||
return nullptr;
|
||||
if (!has_fake_stack())
|
||||
return AsyncSignalSafeLazyInitFakeStack();
|
||||
return fake_stack_;
|
||||
@ -179,6 +180,6 @@ AsanThread *FindThreadByStackAddress(uptr addr);
|
||||
|
||||
// Used to handle fork().
|
||||
void EnsureMainThreadIDIsCorrect();
|
||||
} // namespace __asan
|
||||
} // namespace __asan
|
||||
|
||||
#endif // ASAN_THREAD_H
|
||||
#endif // ASAN_THREAD_H
|
||||
|
@ -14,9 +14,9 @@
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#if SANITIZER_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <dbghelp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
@ -175,14 +175,6 @@ void PlatformTSDDtor(void *tsd) {
|
||||
// }}}
|
||||
|
||||
// ---------------------- Various stuff ---------------- {{{
|
||||
void DisableReexec() {
|
||||
// No need to re-exec on Windows.
|
||||
}
|
||||
|
||||
void MaybeReexec() {
|
||||
// No need to re-exec on Windows.
|
||||
}
|
||||
|
||||
void *AsanDoesNotSupportStaticLinkage() {
|
||||
#if defined(_DEBUG)
|
||||
#error Please build the runtime with a non-debug CRT: /MD or /MT
|
||||
@ -194,15 +186,11 @@ void AsanCheckDynamicRTPrereqs() {}
|
||||
|
||||
void AsanCheckIncompatibleRT() {}
|
||||
|
||||
void AsanPlatformThreadInit() {
|
||||
// Nothing here for now.
|
||||
}
|
||||
|
||||
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void AsanOnSIGSEGV(int, void *siginfo, void *context) {
|
||||
void AsanOnDeadlySignal(int, void *siginfo, void *context) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
@ -219,7 +207,7 @@ static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
|
||||
? "access-violation"
|
||||
: "in-page-error";
|
||||
SignalContext sig = SignalContext::Create(exception_record, context);
|
||||
ReportSIGSEGV(description, sig);
|
||||
ReportDeadlySignal(description, sig);
|
||||
}
|
||||
|
||||
// FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
|
||||
@ -257,7 +245,7 @@ int __asan_set_seh_filter() {
|
||||
// Put a pointer to __asan_set_seh_filter at the end of the global list
|
||||
// of C initializers, after the default EH is set by the CRT.
|
||||
#pragma section(".CRT$XIZ", long, read) // NOLINT
|
||||
static __declspec(allocate(".CRT$XIZ"))
|
||||
__declspec(allocate(".CRT$XIZ"))
|
||||
int (*__intercept_seh)() = __asan_set_seh_filter;
|
||||
#endif
|
||||
// }}}
|
||||
|
@ -12,8 +12,7 @@
|
||||
// This file defines a family of thunks that should be statically linked into
|
||||
// the DLLs that have ASan instrumentation in order to delegate the calls to the
|
||||
// shared runtime that lives in the main binary.
|
||||
// See https://code.google.com/p/address-sanitizer/issues/detail?id=209 for the
|
||||
// details.
|
||||
// See https://github.com/google/sanitizers/issues/209 for the details.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Only compile this code when buidling asan_dll_thunk.lib
|
||||
@ -30,8 +29,9 @@ void *__stdcall GetProcAddress(void *module, const char *proc_name);
|
||||
void abort();
|
||||
}
|
||||
|
||||
static void *getRealProcAddressOrDie(const char *name) {
|
||||
void *ret = GetProcAddress(GetModuleHandleA(0), name);
|
||||
static uptr getRealProcAddressOrDie(const char *name) {
|
||||
uptr ret =
|
||||
__interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name);
|
||||
if (!ret)
|
||||
abort();
|
||||
return ret;
|
||||
@ -62,13 +62,12 @@ struct FunctionInterceptor<0> {
|
||||
};
|
||||
|
||||
#define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function) \
|
||||
template<> struct FunctionInterceptor<__LINE__> { \
|
||||
template <> struct FunctionInterceptor<__LINE__> { \
|
||||
static void Execute() { \
|
||||
void *wrapper = getRealProcAddressOrDie(main_function); \
|
||||
if (!__interception::OverrideFunction((uptr)dll_function, \
|
||||
(uptr)wrapper, 0)) \
|
||||
uptr wrapper = getRealProcAddressOrDie(main_function); \
|
||||
if (!__interception::OverrideFunction((uptr)dll_function, wrapper, 0)) \
|
||||
abort(); \
|
||||
FunctionInterceptor<__LINE__-1>::Execute(); \
|
||||
FunctionInterceptor<__LINE__ - 1>::Execute(); \
|
||||
} \
|
||||
};
|
||||
|
||||
@ -210,7 +209,7 @@ extern "C" {
|
||||
// __asan_init is expected to be called by only one thread.
|
||||
if (fn) return;
|
||||
|
||||
fn = (fntype)getRealProcAddressOrDie(__asan_init_name);
|
||||
fn = (fntype)getRealProcAddressOrDie("__asan_init");
|
||||
fn();
|
||||
__asan_option_detect_stack_use_after_return =
|
||||
(__asan_should_detect_stack_use_after_return() != 0);
|
||||
@ -219,6 +218,10 @@ extern "C" {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void __asan_version_mismatch_check() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
INTERFACE_FUNCTION(__asan_handle_no_return)
|
||||
|
||||
INTERFACE_FUNCTION(__asan_report_store1)
|
||||
@ -253,6 +256,9 @@ INTERFACE_FUNCTION(__asan_memcpy);
|
||||
INTERFACE_FUNCTION(__asan_memset);
|
||||
INTERFACE_FUNCTION(__asan_memmove);
|
||||
|
||||
INTERFACE_FUNCTION(__asan_alloca_poison);
|
||||
INTERFACE_FUNCTION(__asan_allocas_unpoison);
|
||||
|
||||
INTERFACE_FUNCTION(__asan_register_globals)
|
||||
INTERFACE_FUNCTION(__asan_unregister_globals)
|
||||
|
||||
@ -296,6 +302,7 @@ INTERFACE_FUNCTION(__asan_stack_free_10)
|
||||
|
||||
// FIXME: we might want to have a sanitizer_win_dll_thunk?
|
||||
INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
|
||||
INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_dump)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_indir_call16)
|
||||
@ -304,6 +311,7 @@ INTERFACE_FUNCTION(__sanitizer_cov_module_init)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_trace_basic_block)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_trace_func_enter)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_trace_switch)
|
||||
INTERFACE_FUNCTION(__sanitizer_cov_with_check)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_coverage_guards)
|
||||
@ -312,6 +320,7 @@ INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_free_bytes)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_heap_size)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_ownership)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_total_unique_caller_callee_pairs)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes)
|
||||
INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file)
|
||||
|
@ -24,6 +24,7 @@
|
||||
// Using #ifdef rather than relying on Makefiles etc.
|
||||
// simplifies the build procedure.
|
||||
#ifdef ASAN_DYNAMIC_RUNTIME_THUNK
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
// First, declare CRT sections we'll be using in this file
|
||||
@ -58,6 +59,7 @@ int __asan_option_detect_stack_use_after_return =
|
||||
// using atexit() that calls a small subset of C terminators
|
||||
// where LLVM global_dtors is placed. Fingers crossed, no other C terminators
|
||||
// are there.
|
||||
extern "C" int __cdecl atexit(void (__cdecl *f)(void));
|
||||
extern "C" void __cdecl _initterm(void *a, void *b);
|
||||
|
||||
namespace {
|
||||
|
@ -88,19 +88,25 @@ function adb_pull {
|
||||
fi
|
||||
}
|
||||
|
||||
function get_device_arch { # OUTVAR
|
||||
function get_device_arch { # OUT OUT64
|
||||
local _outvar=$1
|
||||
local _outvar64=$2
|
||||
local _ABI=$(adb_shell getprop ro.product.cpu.abi)
|
||||
local _ARCH=
|
||||
local _ARCH64=
|
||||
if [[ $_ABI == x86* ]]; then
|
||||
_ARCH=i686
|
||||
elif [[ $_ABI == armeabi* ]]; then
|
||||
_ARCH=arm
|
||||
elif [[ $_ABI == arm64-v8a* ]]; then
|
||||
_ARCH=arm
|
||||
_ARCH64=aarch64
|
||||
else
|
||||
echo "Unrecognized device ABI: $_ABI"
|
||||
exit 1
|
||||
fi
|
||||
eval $_outvar=\$_ARCH
|
||||
eval $_outvar64=\$_ARCH64
|
||||
}
|
||||
|
||||
while [[ $# > 0 ]]; do
|
||||
@ -167,22 +173,33 @@ adb_wait_for_device
|
||||
adb_remount
|
||||
adb_wait_for_device
|
||||
|
||||
get_device_arch ARCH
|
||||
get_device_arch ARCH ARCH64
|
||||
echo "Target architecture: $ARCH"
|
||||
ASAN_RT="libclang_rt.asan-$ARCH-android.so"
|
||||
if [[ -n $ARCH64 ]]; then
|
||||
echo "Target architecture: $ARCH64"
|
||||
ASAN_RT64="libclang_rt.asan-$ARCH64-android.so"
|
||||
fi
|
||||
|
||||
if [[ x$revert == xyes ]]; then
|
||||
echo '>> Uninstalling ASan'
|
||||
|
||||
if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then
|
||||
echo '>> Pre-L device detected.'
|
||||
adb_shell mv /system/bin/app_process.real /system/bin/app_process
|
||||
adb_shell rm /system/bin/asanwrapper
|
||||
echo '>> Pre-L device detected.'
|
||||
adb_shell mv /system/bin/app_process.real /system/bin/app_process
|
||||
adb_shell rm /system/bin/asanwrapper
|
||||
elif ! adb_shell ls -l /system/bin/app_process64.real | grep -o 'No such file or directory' >&/dev/null; then
|
||||
# 64-bit installation.
|
||||
adb_shell mv /system/bin/app_process32.real /system/bin/app_process32
|
||||
adb_shell mv /system/bin/app_process64.real /system/bin/app_process64
|
||||
adb_shell rm /system/bin/asanwrapper
|
||||
adb_shell rm /system/bin/asanwrapper64
|
||||
else
|
||||
adb_shell rm /system/bin/app_process.wrap
|
||||
adb_shell rm /system/bin/asanwrapper
|
||||
adb_shell rm /system/bin/app_process
|
||||
adb_shell ln -s /system/bin/app_process32 /system/bin/app_process
|
||||
# 32-bit installation.
|
||||
adb_shell rm /system/bin/app_process.wrap
|
||||
adb_shell rm /system/bin/asanwrapper
|
||||
adb_shell rm /system/bin/app_process
|
||||
adb_shell ln -s /system/bin/app_process32 /system/bin/app_process
|
||||
fi
|
||||
|
||||
echo '>> Restarting shell'
|
||||
@ -205,8 +222,13 @@ elif [[ -f "$HERE/$ASAN_RT" ]]; then
|
||||
ASAN_RT_PATH="$HERE"
|
||||
elif [[ $(basename "$HERE") == "bin" ]]; then
|
||||
# We could be in the toolchain's base directory.
|
||||
# Consider ../lib, ../lib/asan, ../lib/linux and ../lib/clang/$VERSION/lib/linux.
|
||||
P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$ASAN_RT" "$HERE"/../lib/linux/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1)
|
||||
# Consider ../lib, ../lib/asan, ../lib/linux,
|
||||
# ../lib/clang/$VERSION/lib/linux, and ../lib64/clang/$VERSION/lib/linux.
|
||||
P=$(ls "$HERE"/../lib/"$ASAN_RT" \
|
||||
"$HERE"/../lib/asan/"$ASAN_RT" \
|
||||
"$HERE"/../lib/linux/"$ASAN_RT" \
|
||||
"$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" \
|
||||
"$HERE"/../lib64/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1)
|
||||
if [[ -n "$P" ]]; then
|
||||
ASAN_RT_PATH="$(dirname "$P")"
|
||||
fi
|
||||
@ -217,6 +239,13 @@ if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$ASAN_RT64" ]]; then
|
||||
if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT64" ]]; then
|
||||
echo ">> ASan runtime library not found"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
TMPDIRBASE=$(mktemp -d)
|
||||
TMPDIROLD="$TMPDIRBASE/old"
|
||||
TMPDIR="$TMPDIRBASE/new"
|
||||
@ -241,12 +270,24 @@ if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev
|
||||
fi
|
||||
|
||||
echo '>> Copying files from the device'
|
||||
adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true
|
||||
adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true
|
||||
if [[ -n "$ASAN_RT64" ]]; then
|
||||
adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true
|
||||
adb_pull /system/lib64/"$ASAN_RT64" "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/app_process32 "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/app_process32.real "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/app_process64 "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/app_process64.real "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/asanwrapper64 "$TMPDIROLD" || true
|
||||
else
|
||||
adb_pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/app_process32 "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/app_process.wrap "$TMPDIROLD" || true
|
||||
adb_pull /system/bin/asanwrapper "$TMPDIROLD" || true
|
||||
fi
|
||||
cp -r "$TMPDIROLD" "$TMPDIR"
|
||||
|
||||
if [[ -f "$TMPDIR/app_process.wrap" ]]; then
|
||||
if [[ -f "$TMPDIR/app_process.wrap" || -f "$TMPDIR/app_process64.real" ]]; then
|
||||
echo ">> Previous installation detected"
|
||||
else
|
||||
echo ">> New installation"
|
||||
@ -255,10 +296,27 @@ fi
|
||||
echo '>> Generating wrappers'
|
||||
|
||||
cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/"
|
||||
if [[ -n "$ASAN_RT64" ]]; then
|
||||
cp "$ASAN_RT_PATH/$ASAN_RT64" "$TMPDIR/"
|
||||
fi
|
||||
|
||||
# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup,
|
||||
# which may or may not be a real bug (probably not).
|
||||
ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0
|
||||
ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0,malloc_context_size=0
|
||||
|
||||
function generate_zygote_wrapper { # from, to, asan_rt
|
||||
local _from=$1
|
||||
local _to=$2
|
||||
local _asan_rt=$3
|
||||
cat <<EOF >"$TMPDIR/$_from"
|
||||
#!/system/bin/sh-from-zygote
|
||||
ASAN_OPTIONS=$ASAN_OPTIONS \\
|
||||
ASAN_ACTIVATION_OPTIONS=include_if_exists=/data/local/tmp/asan.options.%b \\
|
||||
LD_PRELOAD=\$LD_PRELOAD:$_asan_rt \\
|
||||
exec $_to \$@
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# On Android-L not allowing user segv handler breaks some applications.
|
||||
if [[ PRE_L -eq 0 ]]; then
|
||||
@ -270,13 +328,19 @@ if [[ x$extra_options != x ]] ; then
|
||||
fi
|
||||
|
||||
# Zygote wrapper.
|
||||
cat <<EOF >"$TMPDIR/app_process.wrap"
|
||||
#!/system/bin/sh-from-zygote
|
||||
ASAN_OPTIONS=$ASAN_OPTIONS \\
|
||||
LD_PRELOAD=\$LD_PRELOAD:$ASAN_RT \\
|
||||
exec /system/bin/app_process32 \$@
|
||||
|
||||
EOF
|
||||
if [[ -f "$TMPDIR/app_process64" ]]; then
|
||||
# A 64-bit device.
|
||||
if [[ ! -f "$TMPDIR/app_process64.real" ]]; then
|
||||
# New installation.
|
||||
mv "$TMPDIR/app_process32" "$TMPDIR/app_process32.real"
|
||||
mv "$TMPDIR/app_process64" "$TMPDIR/app_process64.real"
|
||||
fi
|
||||
generate_zygote_wrapper "app_process32" "/system/bin/app_process32.real" "$ASAN_RT"
|
||||
generate_zygote_wrapper "app_process64" "/system/bin/app_process64.real" "$ASAN_RT64"
|
||||
else
|
||||
# A 32-bit device.
|
||||
generate_zygote_wrapper "app_process.wrap" "/system/bin/app_process32" "$ASAN_RT"
|
||||
fi
|
||||
|
||||
# General command-line tool wrapper (use for anything that's not started as
|
||||
# zygote).
|
||||
@ -287,25 +351,33 @@ exec \$@
|
||||
|
||||
EOF
|
||||
|
||||
if [[ -n "$ASAN_RT64" ]]; then
|
||||
cat <<EOF >"$TMPDIR/asanwrapper64"
|
||||
#!/system/bin/sh
|
||||
LD_PRELOAD=$ASAN_RT64 \\
|
||||
exec \$@
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
function install { # from, to, chmod, chcon
|
||||
local _from=$1
|
||||
local _to=$2
|
||||
local _mode=$3
|
||||
local _context=$4
|
||||
local _basename="$(basename "$_from")"
|
||||
echo "Installing $_to/$_basename $_mode $_context"
|
||||
adb_push "$_from" "$_to/$_basename"
|
||||
adb_shell chown root.shell "$_to/$_basename"
|
||||
if [[ -n "$_mode" ]]; then
|
||||
adb_shell chmod "$_mode" "$_to/$_basename"
|
||||
fi
|
||||
if [[ -n "$_context" ]]; then
|
||||
adb_shell chcon "$_context" "$_to/$_basename"
|
||||
fi
|
||||
}
|
||||
|
||||
if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then
|
||||
echo '>> Pushing files to the device'
|
||||
adb_push "$TMPDIR/$ASAN_RT" /system/lib/
|
||||
adb_push "$TMPDIR/app_process.wrap" /system/bin
|
||||
adb_push "$TMPDIR/asanwrapper" /system/bin
|
||||
|
||||
adb_shell rm /system/bin/app_process
|
||||
adb_shell ln -s /system/bin/app_process.wrap /system/bin/app_process
|
||||
|
||||
adb_shell chown root.shell \
|
||||
/system/lib/"$ASAN_RT" \
|
||||
/system/bin/app_process.wrap \
|
||||
/system/bin/asanwrapper
|
||||
adb_shell chmod 644 \
|
||||
/system/lib/"$ASAN_RT"
|
||||
adb_shell chmod 755 \
|
||||
/system/bin/app_process.wrap \
|
||||
/system/bin/asanwrapper
|
||||
|
||||
# Make SELinux happy by keeping app_process wrapper and the shell
|
||||
# it runs on in zygote domain.
|
||||
ENFORCING=0
|
||||
@ -316,17 +388,35 @@ if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then
|
||||
adb_shell setenforce 0
|
||||
fi
|
||||
|
||||
adb_shell cp /system/bin/sh /system/bin/sh-from-zygote
|
||||
|
||||
if [[ PRE_L -eq 1 ]]; then
|
||||
CTX=u:object_r:system_file:s0
|
||||
else
|
||||
CTX=u:object_r:zygote_exec:s0
|
||||
fi
|
||||
adb_shell chcon $CTX \
|
||||
/system/bin/sh-from-zygote \
|
||||
/system/bin/app_process.wrap \
|
||||
/system/bin/app_process32
|
||||
|
||||
echo '>> Pushing files to the device'
|
||||
|
||||
if [[ -n "$ASAN_RT64" ]]; then
|
||||
install "$TMPDIR/$ASAN_RT" /system/lib 644
|
||||
install "$TMPDIR/$ASAN_RT64" /system/lib64 644
|
||||
install "$TMPDIR/app_process32" /system/bin 755 $CTX
|
||||
install "$TMPDIR/app_process32.real" /system/bin 755 $CTX
|
||||
install "$TMPDIR/app_process64" /system/bin 755 $CTX
|
||||
install "$TMPDIR/app_process64.real" /system/bin 755 $CTX
|
||||
install "$TMPDIR/asanwrapper" /system/bin 755
|
||||
install "$TMPDIR/asanwrapper64" /system/bin 755
|
||||
else
|
||||
install "$TMPDIR/$ASAN_RT" /system/lib 644
|
||||
install "$TMPDIR/app_process32" /system/bin 755 $CTX
|
||||
install "$TMPDIR/app_process.wrap" /system/bin 755 $CTX
|
||||
install "$TMPDIR/asanwrapper" /system/bin 755 $CTX
|
||||
|
||||
adb_shell rm /system/bin/app_process
|
||||
adb_shell ln -s /system/bin/app_process.wrap /system/bin/app_process
|
||||
fi
|
||||
|
||||
adb_shell cp /system/bin/sh /system/bin/sh-from-zygote
|
||||
adb_shell chcon $CTX /system/bin/sh-from-zygote
|
||||
|
||||
if [ $ENFORCING == 1 ]; then
|
||||
adb_shell setenforce 1
|
||||
|
@ -77,7 +77,7 @@ def open_llvm_symbolizer(self):
|
||||
cmd = [self.symbolizer_path,
|
||||
'--use-symbol-table=true',
|
||||
'--demangle=%s' % demangle,
|
||||
'--functions=short',
|
||||
'--functions=linkage',
|
||||
'--inlining=true',
|
||||
'--default-arch=%s' % self.default_arch]
|
||||
if self.system == 'Darwin':
|
||||
@ -135,12 +135,13 @@ def __init__(self, binary):
|
||||
super(Addr2LineSymbolizer, self).__init__()
|
||||
self.binary = binary
|
||||
self.pipe = self.open_addr2line()
|
||||
self.output_terminator = -1
|
||||
|
||||
def open_addr2line(self):
|
||||
addr2line_tool = 'addr2line'
|
||||
if binutils_prefix:
|
||||
addr2line_tool = binutils_prefix + addr2line_tool
|
||||
cmd = [addr2line_tool, '-f']
|
||||
cmd = [addr2line_tool, '-fi']
|
||||
if demangle:
|
||||
cmd += ['--demangle']
|
||||
cmd += ['-e', self.binary]
|
||||
@ -153,16 +154,23 @@ def symbolize(self, addr, binary, offset):
|
||||
"""Overrides Symbolizer.symbolize."""
|
||||
if self.binary != binary:
|
||||
return None
|
||||
lines = []
|
||||
try:
|
||||
print >> self.pipe.stdin, offset
|
||||
function_name = self.pipe.stdout.readline().rstrip()
|
||||
file_name = self.pipe.stdout.readline().rstrip()
|
||||
print >> self.pipe.stdin, self.output_terminator
|
||||
is_first_frame = True
|
||||
while True:
|
||||
function_name = self.pipe.stdout.readline().rstrip()
|
||||
file_name = self.pipe.stdout.readline().rstrip()
|
||||
if is_first_frame:
|
||||
is_first_frame = False
|
||||
elif function_name in ['', '??']:
|
||||
assert file_name == function_name
|
||||
break
|
||||
lines.append((function_name, file_name));
|
||||
except Exception:
|
||||
function_name = ''
|
||||
file_name = ''
|
||||
file_name = fix_filename(file_name)
|
||||
return ['%s in %s %s' % (addr, function_name, file_name)]
|
||||
|
||||
lines.append(('??', '??:0'))
|
||||
return ['%s in %s %s' % (addr, function, fix_filename(file)) for (function, file) in lines]
|
||||
|
||||
class UnbufferedLineConverter(object):
|
||||
"""
|
||||
@ -263,7 +271,7 @@ def BreakpadSymbolizerFactory(binary):
|
||||
def SystemSymbolizerFactory(system, addr, binary):
|
||||
if system == 'Darwin':
|
||||
return DarwinSymbolizer(addr, binary)
|
||||
elif system == 'Linux':
|
||||
elif system == 'Linux' or system == 'FreeBSD':
|
||||
return Addr2LineSymbolizer(binary)
|
||||
|
||||
|
||||
|
@ -106,7 +106,7 @@ append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread
|
||||
|
||||
# TODO(eugenis): move all -l flags above to _LIBS?
|
||||
set(ASAN_UNITTEST_NOINST_LIBS)
|
||||
append_list_if(ANDROID log ASAN_UNITTEST_NOINST_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBLOG log ASAN_UNITTEST_NOINST_LIBS)
|
||||
# NDK r10 requires -latomic almost always.
|
||||
append_list_if(ANDROID atomic ASAN_UNITTEST_NOINST_LIBS)
|
||||
|
||||
@ -217,9 +217,10 @@ macro(add_asan_tests_for_arch_and_kind arch kind)
|
||||
set(ASAN_TEST_RUNTIME RTAsanTest.${arch}${kind})
|
||||
if(APPLE)
|
||||
set(ASAN_TEST_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTAsan.osx>
|
||||
$<TARGET_OBJECTS:RTAsan_dynamic.osx>
|
||||
$<TARGET_OBJECTS:RTInterception.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.osx>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.osx>
|
||||
$<TARGET_OBJECTS:RTUbsan.osx>)
|
||||
else()
|
||||
@ -261,7 +262,11 @@ macro(add_asan_tests_for_arch_and_kind arch kind)
|
||||
endmacro()
|
||||
|
||||
if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID)
|
||||
foreach(arch ${ASAN_SUPPORTED_ARCH})
|
||||
set(ASAN_TEST_ARCH ${ASAN_SUPPORTED_ARCH})
|
||||
if(APPLE)
|
||||
darwin_filter_host_archs(ASAN_SUPPORTED_ARCH ASAN_TEST_ARCH)
|
||||
endif()
|
||||
foreach(arch ${ASAN_TEST_ARCH})
|
||||
add_asan_tests_for_arch_and_kind(${arch} "-inline")
|
||||
add_asan_tests_for_arch_and_kind(${arch} "-with-calls"
|
||||
-mllvm -asan-instrumentation-with-call-threshold=0)
|
||||
|
@ -14,7 +14,10 @@
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
#if defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__))
|
||||
// Assembly instrumentation is broken on x86 Android (x86 + PIC + shared runtime
|
||||
// library). See https://github.com/google/sanitizers/issues/353
|
||||
#if defined(__x86_64__) || \
|
||||
(defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__))
|
||||
|
||||
#include <emmintrin.h>
|
||||
|
||||
@ -70,7 +73,7 @@ DECLARE_ASM_REP_MOVS(U8, "movsq");
|
||||
|
||||
#endif // defined(__x86_64__)
|
||||
|
||||
#if defined(__i386__) && defined(__SSE2__)
|
||||
#if defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__)
|
||||
|
||||
namespace {
|
||||
|
||||
@ -108,7 +111,8 @@ template<> Type asm_read<Type>(Type *ptr) { \
|
||||
|
||||
#endif // defined(__i386__) && defined(__SSE2__)
|
||||
|
||||
#if defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__))
|
||||
#if defined(__x86_64__) || \
|
||||
(defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__))
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -140,16 +140,6 @@ static void DoDoubleFree() {
|
||||
delete Ident(x);
|
||||
}
|
||||
|
||||
TEST(AddressSanitizerInterface, ExitCode) {
|
||||
int original_exit_code = __asan_set_error_exit_code(7);
|
||||
EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(7), "");
|
||||
EXPECT_EQ(7, __asan_set_error_exit_code(8));
|
||||
EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(8), "");
|
||||
EXPECT_EQ(8, __asan_set_error_exit_code(original_exit_code));
|
||||
EXPECT_EXIT(DoDoubleFree(),
|
||||
::testing::ExitedWithCode(original_exit_code), "");
|
||||
}
|
||||
|
||||
static void MyDeathCallback() {
|
||||
fprintf(stderr, "MyDeathCallback\n");
|
||||
fflush(0); // On Windows, stderr doesn't flush on crash.
|
||||
|
@ -216,12 +216,12 @@ TEST(AddressSanitizerMac, NSObjectOOB) {
|
||||
|
||||
// Make sure that correct pointer is passed to free() when deallocating a
|
||||
// NSURL object.
|
||||
// See http://code.google.com/p/address-sanitizer/issues/detail?id=70.
|
||||
// See https://github.com/google/sanitizers/issues/70.
|
||||
TEST(AddressSanitizerMac, NSURLDeallocation) {
|
||||
TestNSURLDeallocation();
|
||||
}
|
||||
|
||||
// See http://code.google.com/p/address-sanitizer/issues/detail?id=109.
|
||||
// See https://github.com/google/sanitizers/issues/109.
|
||||
TEST(AddressSanitizerMac, Mstats) {
|
||||
malloc_statistics_t stats1, stats2;
|
||||
malloc_zone_statistics(/*all zones*/NULL, &stats1);
|
||||
|
@ -34,7 +34,7 @@
|
||||
// Make sure __asan_init is called before any test case is run.
|
||||
struct AsanInitCaller {
|
||||
AsanInitCaller() {
|
||||
__asan::DisableReexec();
|
||||
DisableReexec();
|
||||
__asan_init();
|
||||
}
|
||||
};
|
||||
|
@ -250,12 +250,12 @@ TEST(AddressSanitizer, BitFieldNegativeTest) {
|
||||
#if ASAN_NEEDS_SEGV
|
||||
namespace {
|
||||
|
||||
const char kUnknownCrash[] = "AddressSanitizer: SEGV on unknown address";
|
||||
const char kSEGVCrash[] = "AddressSanitizer: SEGV on unknown address";
|
||||
const char kOverriddenHandler[] = "ASan signal handler has been overridden\n";
|
||||
|
||||
TEST(AddressSanitizer, WildAddressTest) {
|
||||
char *c = (char*)0x123;
|
||||
EXPECT_DEATH(*c = 0, kUnknownCrash);
|
||||
EXPECT_DEATH(*c = 0, kSEGVCrash);
|
||||
}
|
||||
|
||||
void my_sigaction_sighandler(int, siginfo_t*, void*) {
|
||||
@ -279,10 +279,10 @@ TEST(AddressSanitizer, SignalTest) {
|
||||
EXPECT_EQ(0, sigaction(SIGBUS, &sigact, 0));
|
||||
#endif
|
||||
char *c = (char*)0x123;
|
||||
EXPECT_DEATH(*c = 0, kUnknownCrash);
|
||||
EXPECT_DEATH(*c = 0, kSEGVCrash);
|
||||
// ... and signal().
|
||||
EXPECT_EQ(0, signal(SIGSEGV, my_signal_sighandler));
|
||||
EXPECT_DEATH(*c = 0, kUnknownCrash);
|
||||
EXPECT_DEATH(*c = 0, kSEGVCrash);
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
@ -335,6 +335,8 @@ void *ManyThreadsWorker(void *a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(__aarch64__)
|
||||
// FIXME: Infinite loop in AArch64 (PR24389).
|
||||
TEST(AddressSanitizer, ManyThreadsTest) {
|
||||
const size_t kNumThreads =
|
||||
(SANITIZER_WORDSIZE == 32 || ASAN_AVOID_EXPENSIVE_TESTS) ? 30 : 1000;
|
||||
@ -346,6 +348,7 @@ TEST(AddressSanitizer, ManyThreadsTest) {
|
||||
PTHREAD_JOIN(t[i], 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(AddressSanitizer, ReallocTest) {
|
||||
const int kMinElem = 5;
|
||||
@ -607,7 +610,7 @@ NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
|
||||
}
|
||||
|
||||
// Does not work on Power and ARM:
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=185
|
||||
// https://github.com/google/sanitizers/issues/185
|
||||
TEST(AddressSanitizer, BuiltinLongJmpTest) {
|
||||
static jmp_buf buf;
|
||||
if (!__builtin_setjmp((void**)buf)) {
|
||||
@ -1153,9 +1156,9 @@ TEST(AddressSanitizer, AttributeNoSanitizeAddressTest) {
|
||||
// The new/delete/etc mismatch checks don't work on Android,
|
||||
// as calls to new/delete go through malloc/free.
|
||||
// OS X support is tracked here:
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=131
|
||||
// https://github.com/google/sanitizers/issues/131
|
||||
// Windows support is tracked here:
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=309
|
||||
// https://github.com/google/sanitizers/issues/309
|
||||
#if !defined(__ANDROID__) && \
|
||||
!defined(__APPLE__) && \
|
||||
!defined(_WIN32)
|
||||
@ -1252,7 +1255,7 @@ TEST(AddressSanitizer, DISABLED_DemoTooMuchMemoryTest) {
|
||||
}
|
||||
}
|
||||
|
||||
// http://code.google.com/p/address-sanitizer/issues/detail?id=66
|
||||
// https://github.com/google/sanitizers/issues/66
|
||||
TEST(AddressSanitizer, BufferOverflowAfterManyFrees) {
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
delete [] (Ident(new char [8644]));
|
||||
|
@ -11,6 +11,20 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "asan_test_utils.h"
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
|
||||
// Default ASAN_OPTIONS for the unit tests. Let's turn symbolication off to
|
||||
// speed up testing (unit tests don't use it anyway).
|
||||
extern "C" const char* __asan_default_options() {
|
||||
#if SANITIZER_MAC
|
||||
// On Darwin, we default to `abort_on_error=1`, which would make tests run
|
||||
// much slower. Let's override this and run lit tests with 'abort_on_error=0'.
|
||||
// Also, make sure we do not overwhelm the syslog while testing.
|
||||
return "symbolize=false:abort_on_error=0:log_to_syslog=0";
|
||||
#else
|
||||
return "symbolize=false";
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
testing::GTEST_FLAG(death_test_style) = "threadsafe";
|
||||
|
@ -2,6 +2,9 @@
|
||||
# generic implementations of the core runtime library along with optimized
|
||||
# architecture-specific code in various subdirectories.
|
||||
|
||||
# TODO: Need to add a mechanism for logging errors when builtin source files are
|
||||
# added to a sub-directory and not this CMakeLists file.
|
||||
|
||||
set(GENERIC_SOURCES
|
||||
absvdi2.c
|
||||
absvsi2.c
|
||||
@ -38,6 +41,7 @@ set(GENERIC_SOURCES
|
||||
divsc3.c
|
||||
divsf3.c
|
||||
divsi3.c
|
||||
divtc3.c
|
||||
divti3.c
|
||||
divtf3.c
|
||||
divxc3.c
|
||||
@ -139,59 +143,102 @@ set(GENERIC_SOURCES
|
||||
umodsi3.c
|
||||
umodti3.c)
|
||||
|
||||
if(APPLE)
|
||||
set(GENERIC_SOURCES
|
||||
${GENERIC_SOURCES}
|
||||
atomic_flag_clear.c
|
||||
atomic_flag_clear_explicit.c
|
||||
atomic_flag_test_and_set.c
|
||||
atomic_flag_test_and_set_explicit.c
|
||||
atomic_signal_fence.c
|
||||
atomic_thread_fence.c)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 OR MINGW)
|
||||
set(GENERIC_SOURCES
|
||||
${GENERIC_SOURCES}
|
||||
emutls.c)
|
||||
endif()
|
||||
|
||||
if (HAVE_UNWIND_H)
|
||||
set(GENERIC_SOURCES
|
||||
${GENERIC_SOURCES}
|
||||
gcc_personality_v0.c)
|
||||
endif ()
|
||||
|
||||
set(x86_64_SOURCES
|
||||
x86_64/floatdidf.c
|
||||
x86_64/floatdisf.c
|
||||
x86_64/floatdixf.c
|
||||
x86_64/floatundidf.S
|
||||
x86_64/floatundisf.S
|
||||
x86_64/floatundixf.S
|
||||
${GENERIC_SOURCES})
|
||||
|
||||
if(WIN32)
|
||||
if (NOT MSVC)
|
||||
set(x86_64_SOURCES
|
||||
${x86_64_SOURCES}
|
||||
x86_64/chkstk.S)
|
||||
endif()
|
||||
x86_64/chkstk.S
|
||||
x86_64/chkstk2.S
|
||||
x86_64/floatdidf.c
|
||||
x86_64/floatdisf.c
|
||||
x86_64/floatdixf.c
|
||||
x86_64/floatundidf.S
|
||||
x86_64/floatundisf.S
|
||||
x86_64/floatundixf.S
|
||||
${GENERIC_SOURCES})
|
||||
set(x86_64h_SOURCES ${x86_64_SOURCES})
|
||||
|
||||
set(i386_SOURCES
|
||||
i386/ashldi3.S
|
||||
i386/ashrdi3.S
|
||||
i386/divdi3.S
|
||||
i386/floatdidf.S
|
||||
i386/floatdisf.S
|
||||
i386/floatdixf.S
|
||||
i386/floatundidf.S
|
||||
i386/floatundisf.S
|
||||
i386/floatundixf.S
|
||||
i386/lshrdi3.S
|
||||
i386/moddi3.S
|
||||
i386/muldi3.S
|
||||
i386/udivdi3.S
|
||||
i386/umoddi3.S
|
||||
${GENERIC_SOURCES})
|
||||
if (WIN32)
|
||||
set(x86_64_SOURCES
|
||||
${x86_64_SOURCES}
|
||||
x86_64/chkstk.S
|
||||
x86_64/chkstk2.S)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(i386_SOURCES
|
||||
${i386_SOURCES}
|
||||
i386/chkstk.S)
|
||||
endif()
|
||||
i386/ashldi3.S
|
||||
i386/ashrdi3.S
|
||||
i386/chkstk.S
|
||||
i386/chkstk2.S
|
||||
i386/divdi3.S
|
||||
i386/floatdidf.S
|
||||
i386/floatdisf.S
|
||||
i386/floatdixf.S
|
||||
i386/floatundidf.S
|
||||
i386/floatundisf.S
|
||||
i386/floatundixf.S
|
||||
i386/lshrdi3.S
|
||||
i386/moddi3.S
|
||||
i386/muldi3.S
|
||||
i386/udivdi3.S
|
||||
i386/umoddi3.S
|
||||
${GENERIC_SOURCES})
|
||||
|
||||
set(i686_SOURCES
|
||||
${i386_SOURCES})
|
||||
if (WIN32)
|
||||
set(i386_SOURCES
|
||||
${i386_SOURCES}
|
||||
i386/chkstk.S
|
||||
i386/chkstk2.S)
|
||||
endif()
|
||||
|
||||
set(i686_SOURCES
|
||||
${i386_SOURCES})
|
||||
else () # MSVC
|
||||
# Use C versions of functions when building on MSVC
|
||||
# MSVC's assembler takes Intel syntax, not AT&T syntax
|
||||
set(x86_64_SOURCES
|
||||
x86_64/floatdidf.c
|
||||
x86_64/floatdisf.c
|
||||
x86_64/floatdixf.c
|
||||
${GENERIC_SOURCES})
|
||||
set(x86_64h_SOURCES ${x86_64_SOURCES})
|
||||
set(i386_SOURCES ${GENERIC_SOURCES})
|
||||
set(i686_SOURCES ${i386_SOURCES})
|
||||
endif () # if (NOT MSVC)
|
||||
|
||||
set(arm_SOURCES
|
||||
arm/adddf3vfp.S
|
||||
arm/addsf3vfp.S
|
||||
arm/aeabi_cdcmp.S
|
||||
arm/aeabi_cdcmpeq_check_nan.c
|
||||
arm/aeabi_cfcmp.S
|
||||
arm/aeabi_cfcmpeq_check_nan.c
|
||||
arm/aeabi_dcmp.S
|
||||
arm/aeabi_div0.c
|
||||
arm/aeabi_drsub.c
|
||||
arm/aeabi_fcmp.S
|
||||
arm/aeabi_frsub.c
|
||||
arm/aeabi_idivmod.S
|
||||
arm/aeabi_ldivmod.S
|
||||
arm/aeabi_memcmp.S
|
||||
@ -202,6 +249,8 @@ set(arm_SOURCES
|
||||
arm/aeabi_uldivmod.S
|
||||
arm/bswapdi2.S
|
||||
arm/bswapsi2.S
|
||||
arm/clzdi2.S
|
||||
arm/clzsi2.S
|
||||
arm/comparesf2.S
|
||||
arm/divdf3vfp.S
|
||||
arm/divmodsi4.S
|
||||
@ -270,10 +319,50 @@ set(arm_SOURCES
|
||||
arm/unordsf2vfp.S
|
||||
${GENERIC_SOURCES})
|
||||
|
||||
set(aarch64_SOURCES
|
||||
comparetf2.c
|
||||
extenddftf2.c
|
||||
extendsftf2.c
|
||||
fixtfdi.c
|
||||
fixtfsi.c
|
||||
fixtfti.c
|
||||
fixunstfdi.c
|
||||
fixunstfsi.c
|
||||
fixunstfti.c
|
||||
floatditf.c
|
||||
floatsitf.c
|
||||
floatunditf.c
|
||||
floatunsitf.c
|
||||
multc3.c
|
||||
trunctfdf2.c
|
||||
trunctfsf2.c
|
||||
${GENERIC_SOURCES})
|
||||
|
||||
set(armhf_SOURCES ${arm_SOURCES})
|
||||
set(armv7_SOURCES ${arm_SOURCES})
|
||||
set(armv7s_SOURCES ${arm_SOURCES})
|
||||
set(arm64_SOURCES ${aarch64_SOURCES})
|
||||
|
||||
# macho_embedded archs
|
||||
set(armv6m_SOURCES ${GENERIC_SOURCES})
|
||||
set(armv7m_SOURCES ${arm_SOURCES})
|
||||
set(armv7em_SOURCES ${arm_SOURCES})
|
||||
|
||||
set(mips_SOURCES ${GENERIC_SOURCES})
|
||||
set(mipsel_SOURCES ${mips_SOURCES})
|
||||
set(mips64_SOURCES ${mips_SOURCES})
|
||||
set(mips64el_SOURCES ${mips_SOURCES})
|
||||
|
||||
add_custom_target(builtins)
|
||||
|
||||
if (NOT WIN32 OR MINGW)
|
||||
foreach (arch x86_64 i386 i686 arm)
|
||||
if (APPLE)
|
||||
add_subdirectory(Darwin-excludes)
|
||||
add_subdirectory(macho_embedded)
|
||||
darwin_add_builtin_libraries(${BUILTIN_SUPPORTED_OS})
|
||||
elseif (NOT WIN32 OR MINGW)
|
||||
append_string_if(COMPILER_RT_HAS_STD_C99_FLAG -std=c99 maybe_stdc99)
|
||||
|
||||
foreach (arch ${BUILTIN_SUPPORTED_ARCH})
|
||||
if (CAN_TARGET_${arch})
|
||||
# Filter out generic versions of routines that are re-implemented in
|
||||
# architecture specific manner. This prevents multiple definitions of the
|
||||
@ -286,11 +375,12 @@ if (NOT WIN32 OR MINGW)
|
||||
endif ()
|
||||
endforeach ()
|
||||
|
||||
set_source_files_properties(${${arch}_SOURCES} PROPERTIES LANGUAGE C)
|
||||
add_compiler_rt_runtime(clang_rt.builtins-${arch} ${arch} STATIC
|
||||
add_compiler_rt_runtime(clang_rt.builtins
|
||||
STATIC
|
||||
ARCHS ${arch}
|
||||
SOURCES ${${arch}_SOURCES}
|
||||
CFLAGS "-std=c99")
|
||||
add_dependencies(builtins clang_rt.builtins-${arch})
|
||||
CFLAGS ${maybe_stdc99}
|
||||
PARENT_TARGET builtins)
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif ()
|
||||
|
35
lib/builtins/Darwin-excludes/10.4-x86_64.txt
Normal file
35
lib/builtins/Darwin-excludes/10.4-x86_64.txt
Normal file
@ -0,0 +1,35 @@
|
||||
absvti2
|
||||
addvti3
|
||||
ashlti3
|
||||
ashrti3
|
||||
clzti2
|
||||
cmpti2
|
||||
ctzti2
|
||||
divti3
|
||||
ffsti2
|
||||
fixdfti
|
||||
fixsfti
|
||||
fixunsdfti
|
||||
fixunssfti
|
||||
fixunsxfti
|
||||
fixxfti
|
||||
floattidf
|
||||
floattisf
|
||||
floattixf
|
||||
floatuntidf
|
||||
floatuntisf
|
||||
floatuntixf
|
||||
lshrti3
|
||||
modti3
|
||||
muloti4
|
||||
multi3
|
||||
mulvti3
|
||||
negti2
|
||||
negvti2
|
||||
parityti2
|
||||
popcountti2
|
||||
subvti3
|
||||
ucmpti2
|
||||
udivmodti4
|
||||
udivti3
|
||||
umodti3
|
96
lib/builtins/Darwin-excludes/10.4.txt
Normal file
96
lib/builtins/Darwin-excludes/10.4.txt
Normal file
@ -0,0 +1,96 @@
|
||||
apple_versioning
|
||||
absvdi2
|
||||
absvsi2
|
||||
adddf3
|
||||
addsf3
|
||||
addvdi3
|
||||
addvsi3
|
||||
ashldi3
|
||||
ashrdi3
|
||||
clear_cache
|
||||
clzdi2
|
||||
clzsi2
|
||||
cmpdi2
|
||||
ctzdi2
|
||||
ctzsi2
|
||||
divdc3
|
||||
divdf3
|
||||
divdi3
|
||||
divmoddi4
|
||||
divmodsi4
|
||||
divsc3
|
||||
divsf3
|
||||
divsi3
|
||||
divxc3
|
||||
enable_execute_stack
|
||||
comparedf2
|
||||
comparesf2
|
||||
extendhfsf2
|
||||
extendsfdf2
|
||||
ffsdi2
|
||||
fixdfdi
|
||||
fixdfsi
|
||||
fixsfdi
|
||||
fixsfsi
|
||||
fixunsdfdi
|
||||
fixunsdfsi
|
||||
fixunssfdi
|
||||
fixunssfsi
|
||||
fixunsxfdi
|
||||
fixunsxfsi
|
||||
fixxfdi
|
||||
floatdidf
|
||||
floatdisf
|
||||
floatdixf
|
||||
floatsidf
|
||||
floatsisf
|
||||
floatunsidf
|
||||
floatunsisf
|
||||
gcc_personality_v0
|
||||
gnu_f2h_ieee
|
||||
gnu_h2f_ieee
|
||||
lshrdi3
|
||||
moddi3
|
||||
modsi3
|
||||
muldc3
|
||||
muldf3
|
||||
muldi3
|
||||
mulodi4
|
||||
mulosi4
|
||||
mulsc3
|
||||
mulsf3
|
||||
mulvdi3
|
||||
mulvsi3
|
||||
mulxc3
|
||||
negdf2
|
||||
negdi2
|
||||
negsf2
|
||||
negvdi2
|
||||
negvsi2
|
||||
paritydi2
|
||||
paritysi2
|
||||
popcountdi2
|
||||
popcountsi2
|
||||
powidf2
|
||||
powisf2
|
||||
powixf2
|
||||
subdf3
|
||||
subsf3
|
||||
subvdi3
|
||||
subvsi3
|
||||
truncdfhf2
|
||||
truncdfsf2
|
||||
truncsfhf2
|
||||
ucmpdi2
|
||||
udivdi3
|
||||
udivmoddi4
|
||||
udivmodsi4
|
||||
udivsi3
|
||||
umoddi3
|
||||
umodsi3
|
||||
atomic_flag_clear
|
||||
atomic_flag_clear_explicit
|
||||
atomic_flag_test_and_set
|
||||
atomic_flag_test_and_set_explicit
|
||||
atomic_signal_fence
|
||||
atomic_thread_fence
|
4
lib/builtins/Darwin-excludes/CMakeLists.txt
Normal file
4
lib/builtins/Darwin-excludes/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
file(GLOB filter_files ${CMAKE_CURRENT_SOURCE_DIR}/*.txt)
|
||||
foreach(filter_file ${filter_files})
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${filter_file})
|
||||
endforeach()
|
11
lib/builtins/Darwin-excludes/README.TXT
Normal file
11
lib/builtins/Darwin-excludes/README.TXT
Normal file
@ -0,0 +1,11 @@
|
||||
This folder contains list of symbols that should be excluded from the builtin
|
||||
libraries for Darwin. There are two reasons symbols are excluded:
|
||||
|
||||
(1) They aren't supported on Darwin
|
||||
(2) They are contained within the OS on the minimum supported target
|
||||
|
||||
The builtin libraries must contain all symbols not provided by the lowest
|
||||
supported target OS. Meaning if minimum deployment target is iOS 6, all builtins
|
||||
not included in the ios6-<arch>.txt files need to be included. The one catch is
|
||||
that this is per-architecture. Since iOS 6 doesn't support arm64, when supporting
|
||||
iOS 6, the minimum deployment target for arm64 binaries is iOS 7.
|
57
lib/builtins/Darwin-excludes/ios-armv7.txt
Normal file
57
lib/builtins/Darwin-excludes/ios-armv7.txt
Normal file
@ -0,0 +1,57 @@
|
||||
absvti2
|
||||
addtf3
|
||||
addvti3
|
||||
aeabi_cdcmp
|
||||
aeabi_cdcmpeq_check_nan
|
||||
aeabi_cfcmp
|
||||
aeabi_cfcmpeq_check_nan
|
||||
aeabi_dcmp
|
||||
aeabi_div0
|
||||
aeabi_drsub
|
||||
aeabi_fcmp
|
||||
aeabi_frsub
|
||||
aeabi_idivmod
|
||||
aeabi_ldivmod
|
||||
aeabi_memcmp
|
||||
aeabi_memcpy
|
||||
aeabi_memmove
|
||||
aeabi_memset
|
||||
aeabi_uidivmod
|
||||
aeabi_uldivmod
|
||||
ashlti3
|
||||
ashrti3
|
||||
clzti2
|
||||
cmpti2
|
||||
ctzti2
|
||||
divtf3
|
||||
divti3
|
||||
ffsti2
|
||||
fixdfti
|
||||
fixsfti
|
||||
fixunsdfti
|
||||
fixunssfti
|
||||
fixunsxfti
|
||||
fixxfti
|
||||
floattidf
|
||||
floattisf
|
||||
floattixf
|
||||
floatuntidf
|
||||
floatuntisf
|
||||
floatuntixf
|
||||
lshrti3
|
||||
modti3
|
||||
multf3
|
||||
multi3
|
||||
mulvti3
|
||||
negti2
|
||||
negvti2
|
||||
parityti2
|
||||
popcountti2
|
||||
powitf2
|
||||
subtf3
|
||||
subvti3
|
||||
trampoline_setup
|
||||
ucmpti2
|
||||
udivmodti4
|
||||
udivti3
|
||||
umodti3
|
57
lib/builtins/Darwin-excludes/ios-armv7s.txt
Normal file
57
lib/builtins/Darwin-excludes/ios-armv7s.txt
Normal file
@ -0,0 +1,57 @@
|
||||
absvti2
|
||||
addtf3
|
||||
addvti3
|
||||
aeabi_cdcmp
|
||||
aeabi_cdcmpeq_check_nan
|
||||
aeabi_cfcmp
|
||||
aeabi_cfcmpeq_check_nan
|
||||
aeabi_dcmp
|
||||
aeabi_div0
|
||||
aeabi_drsub
|
||||
aeabi_fcmp
|
||||
aeabi_frsub
|
||||
aeabi_idivmod
|
||||
aeabi_ldivmod
|
||||
aeabi_memcmp
|
||||
aeabi_memcpy
|
||||
aeabi_memmove
|
||||
aeabi_memset
|
||||
aeabi_uidivmod
|
||||
aeabi_uldivmod
|
||||
ashlti3
|
||||
ashrti3
|
||||
clzti2
|
||||
cmpti2
|
||||
ctzti2
|
||||
divtf3
|
||||
divti3
|
||||
ffsti2
|
||||
fixdfti
|
||||
fixsfti
|
||||
fixunsdfti
|
||||
fixunssfti
|
||||
fixunsxfti
|
||||
fixxfti
|
||||
floattidf
|
||||
floattisf
|
||||
floattixf
|
||||
floatuntidf
|
||||
floatuntisf
|
||||
floatuntixf
|
||||
lshrti3
|
||||
modti3
|
||||
multf
|
||||
multi3
|
||||
mulvti3
|
||||
negti2
|
||||
negvti2
|
||||
parityti2
|
||||
popcountti2
|
||||
powitf2
|
||||
subtf3
|
||||
subvti3
|
||||
trampoline_setup
|
||||
ucmpti2
|
||||
udivmodti4
|
||||
udivti3
|
||||
umodti3
|
1
lib/builtins/Darwin-excludes/ios.txt
Normal file
1
lib/builtins/Darwin-excludes/ios.txt
Normal file
@ -0,0 +1 @@
|
||||
apple_versioning
|
120
lib/builtins/Darwin-excludes/ios6-armv7.txt
Normal file
120
lib/builtins/Darwin-excludes/ios6-armv7.txt
Normal file
@ -0,0 +1,120 @@
|
||||
absvdi2
|
||||
absvsi2
|
||||
adddf3
|
||||
adddf3vfp
|
||||
addsf3
|
||||
addsf3vfp
|
||||
addvdi3
|
||||
addvsi3
|
||||
ashldi3
|
||||
ashrdi3
|
||||
bswapdi2
|
||||
bswapsi2
|
||||
clzdi2
|
||||
clzsi2
|
||||
cmpdi2
|
||||
ctzdi2
|
||||
ctzsi2
|
||||
divdc3
|
||||
divdf3
|
||||
divdf3vfp
|
||||
divdi3
|
||||
divmodsi4
|
||||
divsc3
|
||||
divsf3
|
||||
divsf3vfp
|
||||
divsi3
|
||||
eqdf2
|
||||
eqdf2vfp
|
||||
eqsf2
|
||||
eqsf2vfp
|
||||
extendsfdf2
|
||||
extendsfdf2vfp
|
||||
ffsdi2
|
||||
fixdfdi
|
||||
fixdfsi
|
||||
fixdfsivfp
|
||||
fixsfdi
|
||||
fixsfsi
|
||||
fixsfsivfp
|
||||
fixunsdfdi
|
||||
fixunsdfsi
|
||||
fixunsdfsivfp
|
||||
fixunssfdi
|
||||
fixunssfsi
|
||||
fixunssfsivfp
|
||||
floatdidf
|
||||
floatdisf
|
||||
floatsidf
|
||||
floatsidfvfp
|
||||
floatsisf
|
||||
floatsisfvfp
|
||||
floatundidf
|
||||
floatundisf
|
||||
floatunsidf
|
||||
floatunsisf
|
||||
floatunssidfvfp
|
||||
floatunssisfvfp
|
||||
gcc_personality_sj0
|
||||
gedf2
|
||||
gedf2vfp
|
||||
gesf2
|
||||
gesf2vfp
|
||||
gtdf2
|
||||
gtdf2vfp
|
||||
gtsf2
|
||||
gtsf2vfp
|
||||
ledf2
|
||||
ledf2vfp
|
||||
lesf2
|
||||
lesf2vfp
|
||||
lshrdi3
|
||||
ltdf2
|
||||
ltdf2vfp
|
||||
ltsf2
|
||||
ltsf2vfp
|
||||
moddi3
|
||||
modsi3
|
||||
muldc3
|
||||
muldf3
|
||||
muldf3vfp
|
||||
muldi3
|
||||
mulodi4
|
||||
mulosi4
|
||||
mulsc3
|
||||
mulsf3
|
||||
mulsf3vfp
|
||||
mulvdi3
|
||||
mulvsi3
|
||||
nedf2
|
||||
nedf2vfp
|
||||
negdi2
|
||||
negvdi2
|
||||
negvsi2
|
||||
nesf2
|
||||
nesf2vfp
|
||||
paritydi2
|
||||
paritysi2
|
||||
popcountdi2
|
||||
popcountsi2
|
||||
powidf2
|
||||
powisf2
|
||||
subdf3
|
||||
subdf3vfp
|
||||
subsf3
|
||||
subsf3vfp
|
||||
subvdi3
|
||||
subvsi3
|
||||
truncdfsf2
|
||||
truncdfsf2vfp
|
||||
ucmpdi2
|
||||
udivdi3
|
||||
udivmoddi4
|
||||
udivmodsi4
|
||||
udivsi3
|
||||
umoddi3
|
||||
umodsi3
|
||||
unorddf2
|
||||
unorddf2vfp
|
||||
unordsf2
|
||||
unordsf2vfp
|
120
lib/builtins/Darwin-excludes/ios6-armv7s.txt
Normal file
120
lib/builtins/Darwin-excludes/ios6-armv7s.txt
Normal file
@ -0,0 +1,120 @@
|
||||
absvdi2
|
||||
absvsi2
|
||||
adddf3
|
||||
adddf3vfp
|
||||
addsf3
|
||||
addsf3vfp
|
||||
addvdi3
|
||||
addvsi3
|
||||
ashldi3
|
||||
ashrdi3
|
||||
bswapdi2
|
||||
bswapsi2
|
||||
clzdi2
|
||||
clzsi2
|
||||
cmpdi2
|
||||
ctzdi2
|
||||
ctzsi2
|
||||
divdc3
|
||||
divdf3
|
||||
divdf3vfp
|
||||
divdi3
|
||||
divmodsi4
|
||||
divsc3
|
||||
divsf3
|
||||
divsf3vfp
|
||||
divsi3
|
||||
eqdf2
|
||||
eqdf2vfp
|
||||
eqsf2
|
||||
eqsf2vfp
|
||||
extendsfdf2
|
||||
extendsfdf2vfp
|
||||
ffsdi2
|
||||
fixdfdi
|
||||
fixdfsi
|
||||
fixdfsivfp
|
||||
fixsfdi
|
||||
fixsfsi
|
||||
fixsfsivfp
|
||||
fixunsdfdi
|
||||
fixunsdfsi
|
||||
fixunsdfsivfp
|
||||
fixunssfdi
|
||||
fixunssfsi
|
||||
fixunssfsivfp
|
||||
floatdidf
|
||||
floatdisf
|
||||
floatsidf
|
||||
floatsidfvfp
|
||||
floatsisf
|
||||
floatsisfvfp
|
||||
floatundidf
|
||||
floatundisf
|
||||
floatunsidf
|
||||
floatunsisf
|
||||
floatunssidfvfp
|
||||
floatunssisfvfp
|
||||
gcc_personality_sj0
|
||||
gedf2
|
||||
gedf2vfp
|
||||
gesf2
|
||||
gesf2vfp
|
||||
gtdf2
|
||||
gtdf2vfp
|
||||
gtsf2
|
||||
gtsf2vfp
|
||||
ledf2
|
||||
ledf2vfp
|
||||
lesf2
|
||||
lesf2vfp
|
||||
lshrdi3
|
||||
ltdf2
|
||||
ltdf2vfp
|
||||
ltsf2
|
||||
ltsf2vfp
|
||||
moddi3
|
||||
modsi3
|
||||
muldc3
|
||||
muldf3
|
||||
muldf3vfp
|
||||
muldi3
|
||||
mulodi4
|
||||
mulosi4
|
||||
mulsc3
|
||||
mulsf3
|
||||
mulsf3vfp
|
||||
mulvdi3
|
||||
mulvsi3
|
||||
nedf2
|
||||
nedf2vfp
|
||||
negdi2
|
||||
negvdi2
|
||||
negvsi2
|
||||
nesf2
|
||||
nesf2vfp
|
||||
paritydi2
|
||||
paritysi2
|
||||
popcountdi2
|
||||
popcountsi2
|
||||
powidf2
|
||||
powisf2
|
||||
subdf3
|
||||
subdf3vfp
|
||||
subsf3
|
||||
subsf3vfp
|
||||
subvdi3
|
||||
subvsi3
|
||||
truncdfsf2
|
||||
truncdfsf2vfp
|
||||
ucmpdi2
|
||||
udivdi3
|
||||
udivmoddi4
|
||||
udivmodsi4
|
||||
udivsi3
|
||||
umoddi3
|
||||
umodsi3
|
||||
unorddf2
|
||||
unorddf2vfp
|
||||
unordsf2
|
||||
unordsf2vfp
|
16
lib/builtins/Darwin-excludes/ios7-arm64.txt
Normal file
16
lib/builtins/Darwin-excludes/ios7-arm64.txt
Normal file
@ -0,0 +1,16 @@
|
||||
clzti2
|
||||
divti3
|
||||
fixdfti
|
||||
fixsfti
|
||||
fixunsdfti
|
||||
floattidf
|
||||
floattisf
|
||||
floatuntidf
|
||||
floatuntisf
|
||||
gcc_personality_v0
|
||||
modti3
|
||||
powidf2
|
||||
powisf2
|
||||
udivmodti4
|
||||
udivti3
|
||||
umodti3
|
82
lib/builtins/Darwin-excludes/iossim-i386.txt
Normal file
82
lib/builtins/Darwin-excludes/iossim-i386.txt
Normal file
@ -0,0 +1,82 @@
|
||||
absvti2
|
||||
addtf3
|
||||
addvti3
|
||||
ashlti3
|
||||
ashrti3
|
||||
clzti2
|
||||
cmpti2
|
||||
ctzti2
|
||||
divti3
|
||||
divtf3
|
||||
ffsti2
|
||||
fixdfti
|
||||
fixsfti
|
||||
fixunsdfti
|
||||
fixunssfti
|
||||
fixunsxfti
|
||||
fixxfti
|
||||
floattidf
|
||||
floattisf
|
||||
floattixf
|
||||
floatuntidf
|
||||
floatuntisf
|
||||
floatuntixf
|
||||
lshrti3
|
||||
modti3
|
||||
muloti4
|
||||
multi3
|
||||
multf3
|
||||
mulvti3
|
||||
negti2
|
||||
negvti2
|
||||
parityti2
|
||||
popcountti2
|
||||
powitf2
|
||||
subvti3
|
||||
subtf3
|
||||
trampoline_setup
|
||||
ucmpti2
|
||||
udivmodti4
|
||||
udivti3
|
||||
umodti3
|
||||
absvti2
|
||||
addtf3
|
||||
addvti3
|
||||
ashlti3
|
||||
ashrti3
|
||||
clzti2
|
||||
cmpti2
|
||||
ctzti2
|
||||
divti3
|
||||
divtf3
|
||||
ffsti2
|
||||
fixdfti
|
||||
fixsfti
|
||||
fixunsdfti
|
||||
fixunssfti
|
||||
fixunsxfti
|
||||
fixxfti
|
||||
floattidf
|
||||
floattisf
|
||||
floattixf
|
||||
floatuntidf
|
||||
floatuntisf
|
||||
floatuntixf
|
||||
lshrti3
|
||||
modti3
|
||||
muloti4
|
||||
multi3
|
||||
multf3
|
||||
mulvti3
|
||||
negti2
|
||||
negvti2
|
||||
parityti2
|
||||
popcountti2
|
||||
powitf2
|
||||
subvti3
|
||||
subtf3
|
||||
trampoline_setup
|
||||
ucmpti2
|
||||
udivmodti4
|
||||
udivti3
|
||||
umodti3
|
12
lib/builtins/Darwin-excludes/iossim-x86_64.txt
Normal file
12
lib/builtins/Darwin-excludes/iossim-x86_64.txt
Normal file
@ -0,0 +1,12 @@
|
||||
addtf3
|
||||
divtf3
|
||||
multf3
|
||||
powitf2
|
||||
subtf3
|
||||
trampoline_setup
|
||||
addtf3
|
||||
divtf3
|
||||
multf3
|
||||
powitf2
|
||||
subtf3
|
||||
trampoline_setup
|
1
lib/builtins/Darwin-excludes/iossim.txt
Normal file
1
lib/builtins/Darwin-excludes/iossim.txt
Normal file
@ -0,0 +1 @@
|
||||
apple_versioning
|
82
lib/builtins/Darwin-excludes/osx-i386.txt
Normal file
82
lib/builtins/Darwin-excludes/osx-i386.txt
Normal file
@ -0,0 +1,82 @@
|
||||
absvti2
|
||||
addtf3
|
||||
addvti3
|
||||
ashlti3
|
||||
ashrti3
|
||||
clzti2
|
||||
cmpti2
|
||||
ctzti2
|
||||
divti3
|
||||
divtf3
|
||||
ffsti2
|
||||
fixdfti
|
||||
fixsfti
|
||||
fixunsdfti
|
||||
fixunssfti
|
||||
fixunsxfti
|
||||
fixxfti
|
||||
floattidf
|
||||
floattisf
|
||||
floattixf
|
||||
floatuntidf
|
||||
floatuntisf
|
||||
floatuntixf
|
||||
lshrti3
|
||||
modti3
|
||||
muloti4
|
||||
multi3
|
||||
multf3
|
||||
mulvti3
|
||||
negti2
|
||||
negvti2
|
||||
parityti2
|
||||
popcountti2
|
||||
powitf2
|
||||
subvti3
|
||||
subtf3
|
||||
trampoline_setup
|
||||
ucmpti2
|
||||
udivmodti4
|
||||
udivti3
|
||||
umodti3
|
||||
absvti2
|
||||
addtf3
|
||||
addvti3
|
||||
ashlti3
|
||||
ashrti3
|
||||
clzti2
|
||||
cmpti2
|
||||
ctzti2
|
||||
divti3
|
||||
divtf3
|
||||
ffsti2
|
||||
fixdfti
|
||||
fixsfti
|
||||
fixunsdfti
|
||||
fixunssfti
|
||||
fixunsxfti
|
||||
fixxfti
|
||||
floattidf
|
||||
floattisf
|
||||
floattixf
|
||||
floatuntidf
|
||||
floatuntisf
|
||||
floatuntixf
|
||||
lshrti3
|
||||
modti3
|
||||
muloti4
|
||||
multi3
|
||||
multf3
|
||||
mulvti3
|
||||
negti2
|
||||
negvti2
|
||||
parityti2
|
||||
popcountti2
|
||||
powitf2
|
||||
subvti3
|
||||
subtf3
|
||||
trampoline_setup
|
||||
ucmpti2
|
||||
udivmodti4
|
||||
udivti3
|
||||
umodti3
|
12
lib/builtins/Darwin-excludes/osx-x86_64.txt
Normal file
12
lib/builtins/Darwin-excludes/osx-x86_64.txt
Normal file
@ -0,0 +1,12 @@
|
||||
addtf3
|
||||
divtf3
|
||||
multf3
|
||||
powitf2
|
||||
subtf3
|
||||
trampoline_setup
|
||||
addtf3
|
||||
divtf3
|
||||
multf3
|
||||
powitf2
|
||||
subtf3
|
||||
trampoline_setup
|
1
lib/builtins/Darwin-excludes/osx.txt
Normal file
1
lib/builtins/Darwin-excludes/osx.txt
Normal file
@ -0,0 +1 @@
|
||||
apple_versioning
|
@ -220,7 +220,9 @@ _Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions,
|
||||
// for use with some implementations of assert() in <assert.h>
|
||||
void __eprintf(const char* format, const char* assertion_expression,
|
||||
const char* line, const char* file);
|
||||
|
||||
|
||||
// for systems with emulated thread local storage
|
||||
void* __emutls_get_address(struct __emutls_control*);
|
||||
|
||||
|
||||
// Power PC specific functions
|
||||
|
96
lib/builtins/arm/aeabi_cdcmp.S
Normal file
96
lib/builtins/arm/aeabi_cdcmp.S
Normal file
@ -0,0 +1,96 @@
|
||||
//===-- aeabi_cdcmp.S - EABI cdcmp* implementation ------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
|
||||
#error big endian support not implemented
|
||||
#endif
|
||||
|
||||
#define APSR_Z (1 << 30)
|
||||
#define APSR_C (1 << 29)
|
||||
|
||||
// void __aeabi_cdcmpeq(double a, double b) {
|
||||
// if (isnan(a) || isnan(b)) {
|
||||
// Z = 0; C = 1;
|
||||
// } else {
|
||||
// __aeabi_cdcmple(a, b);
|
||||
// }
|
||||
// }
|
||||
|
||||
.syntax unified
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
|
||||
push {r0-r3, lr}
|
||||
bl __aeabi_cdcmpeq_check_nan
|
||||
cmp r0, #1
|
||||
pop {r0-r3, lr}
|
||||
|
||||
// NaN has been ruled out, so __aeabi_cdcmple can't trap
|
||||
bne __aeabi_cdcmple
|
||||
|
||||
msr CPSR_f, #APSR_C
|
||||
JMP(lr)
|
||||
END_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
|
||||
|
||||
|
||||
// void __aeabi_cdcmple(double a, double b) {
|
||||
// if (__aeabi_dcmplt(a, b)) {
|
||||
// Z = 0; C = 0;
|
||||
// } else if (__aeabi_dcmpeq(a, b)) {
|
||||
// Z = 1; C = 1;
|
||||
// } else {
|
||||
// Z = 0; C = 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
.syntax unified
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple)
|
||||
// Per the RTABI, this function must preserve r0-r11.
|
||||
// Save lr in the same instruction for compactness
|
||||
push {r0-r3, lr}
|
||||
|
||||
bl __aeabi_dcmplt
|
||||
cmp r0, #1
|
||||
moveq ip, #0
|
||||
beq 1f
|
||||
|
||||
ldm sp, {r0-r3}
|
||||
bl __aeabi_dcmpeq
|
||||
cmp r0, #1
|
||||
moveq ip, #(APSR_C | APSR_Z)
|
||||
movne ip, #(APSR_C)
|
||||
|
||||
1:
|
||||
msr CPSR_f, ip
|
||||
pop {r0-r3}
|
||||
POP_PC()
|
||||
END_COMPILERRT_FUNCTION(__aeabi_cdcmple)
|
||||
|
||||
// int __aeabi_cdrcmple(double a, double b) {
|
||||
// return __aeabi_cdcmple(b, a);
|
||||
// }
|
||||
|
||||
.syntax unified
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_cdrcmple)
|
||||
// Swap r0 and r2
|
||||
mov ip, r0
|
||||
mov r0, r2
|
||||
mov r2, ip
|
||||
|
||||
// Swap r1 and r3
|
||||
mov ip, r1
|
||||
mov r1, r3
|
||||
mov r3, ip
|
||||
|
||||
b __aeabi_cdcmple
|
||||
END_COMPILERRT_FUNCTION(__aeabi_cdrcmple)
|
||||
|
16
lib/builtins/arm/aeabi_cdcmpeq_check_nan.c
Normal file
16
lib/builtins/arm/aeabi_cdcmpeq_check_nan.c
Normal file
@ -0,0 +1,16 @@
|
||||
//===-- lib/arm/aeabi_cdcmpeq_helper.c - Helper for cdcmpeq ---------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
__attribute__((pcs("aapcs")))
|
||||
__attribute__((visibility("hidden")))
|
||||
int __aeabi_cdcmpeq_check_nan(double a, double b) {
|
||||
return __builtin_isnan(a) || __builtin_isnan(b);
|
||||
}
|
91
lib/builtins/arm/aeabi_cfcmp.S
Normal file
91
lib/builtins/arm/aeabi_cfcmp.S
Normal file
@ -0,0 +1,91 @@
|
||||
//===-- aeabi_cfcmp.S - EABI cfcmp* implementation ------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
|
||||
#error big endian support not implemented
|
||||
#endif
|
||||
|
||||
#define APSR_Z (1 << 30)
|
||||
#define APSR_C (1 << 29)
|
||||
|
||||
// void __aeabi_cfcmpeq(float a, float b) {
|
||||
// if (isnan(a) || isnan(b)) {
|
||||
// Z = 0; C = 1;
|
||||
// } else {
|
||||
// __aeabi_cfcmple(a, b);
|
||||
// }
|
||||
// }
|
||||
|
||||
.syntax unified
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
|
||||
push {r0-r3, lr}
|
||||
bl __aeabi_cfcmpeq_check_nan
|
||||
cmp r0, #1
|
||||
pop {r0-r3, lr}
|
||||
|
||||
// NaN has been ruled out, so __aeabi_cfcmple can't trap
|
||||
bne __aeabi_cfcmple
|
||||
|
||||
msr CPSR_f, #APSR_C
|
||||
JMP(lr)
|
||||
END_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
|
||||
|
||||
|
||||
// void __aeabi_cfcmple(float a, float b) {
|
||||
// if (__aeabi_fcmplt(a, b)) {
|
||||
// Z = 0; C = 0;
|
||||
// } else if (__aeabi_fcmpeq(a, b)) {
|
||||
// Z = 1; C = 1;
|
||||
// } else {
|
||||
// Z = 0; C = 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
.syntax unified
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmple)
|
||||
// Per the RTABI, this function must preserve r0-r11.
|
||||
// Save lr in the same instruction for compactness
|
||||
push {r0-r3, lr}
|
||||
|
||||
bl __aeabi_fcmplt
|
||||
cmp r0, #1
|
||||
moveq ip, #0
|
||||
beq 1f
|
||||
|
||||
ldm sp, {r0-r3}
|
||||
bl __aeabi_fcmpeq
|
||||
cmp r0, #1
|
||||
moveq ip, #(APSR_C | APSR_Z)
|
||||
movne ip, #(APSR_C)
|
||||
|
||||
1:
|
||||
msr CPSR_f, ip
|
||||
pop {r0-r3}
|
||||
POP_PC()
|
||||
END_COMPILERRT_FUNCTION(__aeabi_cfcmple)
|
||||
|
||||
// int __aeabi_cfrcmple(float a, float b) {
|
||||
// return __aeabi_cfcmple(b, a);
|
||||
// }
|
||||
|
||||
.syntax unified
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_cfrcmple)
|
||||
// Swap r0 and r1
|
||||
mov ip, r0
|
||||
mov r0, r1
|
||||
mov r1, ip
|
||||
|
||||
b __aeabi_cfcmple
|
||||
END_COMPILERRT_FUNCTION(__aeabi_cfrcmple)
|
||||
|
16
lib/builtins/arm/aeabi_cfcmpeq_check_nan.c
Normal file
16
lib/builtins/arm/aeabi_cfcmpeq_check_nan.c
Normal file
@ -0,0 +1,16 @@
|
||||
//===-- lib/arm/aeabi_cfcmpeq_helper.c - Helper for cdcmpeq ---------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
__attribute__((pcs("aapcs")))
|
||||
__attribute__((visibility("hidden")))
|
||||
int __aeabi_cfcmpeq_check_nan(float a, float b) {
|
||||
return __builtin_isnan(a) || __builtin_isnan(b);
|
||||
}
|
19
lib/builtins/arm/aeabi_drsub.c
Normal file
19
lib/builtins/arm/aeabi_drsub.c
Normal file
@ -0,0 +1,19 @@
|
||||
//===-- lib/arm/aeabi_drsub.c - Double-precision subtraction --------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DOUBLE_PRECISION
|
||||
#include "../fp_lib.h"
|
||||
|
||||
COMPILER_RT_ABI fp_t
|
||||
__aeabi_dsub(fp_t, fp_t);
|
||||
|
||||
COMPILER_RT_ABI fp_t
|
||||
__aeabi_drsub(fp_t a, fp_t b) {
|
||||
return __aeabi_dsub(b, a);
|
||||
}
|
19
lib/builtins/arm/aeabi_frsub.c
Normal file
19
lib/builtins/arm/aeabi_frsub.c
Normal file
@ -0,0 +1,19 @@
|
||||
//===-- lib/arm/aeabi_frsub.c - Single-precision subtraction --------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define SINGLE_PRECISION
|
||||
#include "../fp_lib.h"
|
||||
|
||||
COMPILER_RT_ABI fp_t
|
||||
__aeabi_fsub(fp_t, fp_t);
|
||||
|
||||
COMPILER_RT_ABI fp_t
|
||||
__aeabi_frsub(fp_t a, fp_t b) {
|
||||
return __aeabi_fsub(b, a);
|
||||
}
|
@ -73,6 +73,15 @@
|
||||
#define JMPc(r, c) mov##c pc, r
|
||||
#endif
|
||||
|
||||
// pop {pc} can't switch Thumb mode on ARMv4T
|
||||
#if __ARM_ARCH >= 5
|
||||
#define POP_PC() pop {pc}
|
||||
#else
|
||||
#define POP_PC() \
|
||||
pop {ip}; \
|
||||
JMP(ip)
|
||||
#endif
|
||||
|
||||
#if __ARM_ARCH_ISA_THUMB == 2
|
||||
#define IT(cond) it cond
|
||||
#define ITT(cond) itt cond
|
||||
|
@ -56,13 +56,13 @@ static const long SPINLOCK_MASK = SPINLOCK_COUNT - 1;
|
||||
#include <machine/atomic.h>
|
||||
#include <sys/umtx.h>
|
||||
typedef struct _usem Lock;
|
||||
inline static void unlock(Lock *l) {
|
||||
__inline static void unlock(Lock *l) {
|
||||
__c11_atomic_store((_Atomic(uint32_t)*)&l->_count, 1, __ATOMIC_RELEASE);
|
||||
__c11_atomic_thread_fence(__ATOMIC_SEQ_CST);
|
||||
if (l->_has_waiters)
|
||||
_umtx_op(l, UMTX_OP_SEM_WAKE, 1, 0, 0);
|
||||
}
|
||||
inline static void lock(Lock *l) {
|
||||
__inline static void lock(Lock *l) {
|
||||
uint32_t old = 1;
|
||||
while (!__c11_atomic_compare_exchange_weak((_Atomic(uint32_t)*)&l->_count, &old,
|
||||
0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
|
||||
@ -76,12 +76,12 @@ static Lock locks[SPINLOCK_COUNT] = { [0 ... SPINLOCK_COUNT-1] = {0,1,0} };
|
||||
#elif defined(__APPLE__)
|
||||
#include <libkern/OSAtomic.h>
|
||||
typedef OSSpinLock Lock;
|
||||
inline static void unlock(Lock *l) {
|
||||
__inline static void unlock(Lock *l) {
|
||||
OSSpinLockUnlock(l);
|
||||
}
|
||||
/// Locks a lock. In the current implementation, this is potentially
|
||||
/// unbounded in the contended case.
|
||||
inline static void lock(Lock *l) {
|
||||
__inline static void lock(Lock *l) {
|
||||
OSSpinLockLock(l);
|
||||
}
|
||||
static Lock locks[SPINLOCK_COUNT]; // initialized to OS_SPINLOCK_INIT which is 0
|
||||
@ -89,12 +89,12 @@ static Lock locks[SPINLOCK_COUNT]; // initialized to OS_SPINLOCK_INIT which is 0
|
||||
#else
|
||||
typedef _Atomic(uintptr_t) Lock;
|
||||
/// Unlock a lock. This is a release operation.
|
||||
inline static void unlock(Lock *l) {
|
||||
__inline static void unlock(Lock *l) {
|
||||
__c11_atomic_store(l, 0, __ATOMIC_RELEASE);
|
||||
}
|
||||
/// Locks a lock. In the current implementation, this is potentially
|
||||
/// unbounded in the contended case.
|
||||
inline static void lock(Lock *l) {
|
||||
__inline static void lock(Lock *l) {
|
||||
uintptr_t old = 0;
|
||||
while (!__c11_atomic_compare_exchange_weak(l, &old, 1, __ATOMIC_ACQUIRE,
|
||||
__ATOMIC_RELAXED))
|
||||
@ -106,7 +106,7 @@ static Lock locks[SPINLOCK_COUNT];
|
||||
|
||||
|
||||
/// Returns a lock to use for a given pointer.
|
||||
static inline Lock *lock_for_pointer(void *ptr) {
|
||||
static __inline Lock *lock_for_pointer(void *ptr) {
|
||||
intptr_t hash = (intptr_t)ptr;
|
||||
// Disregard the lowest 4 bits. We want all values that may be part of the
|
||||
// same memory operation to hash to the same value and therefore use the same
|
||||
|
@ -12,8 +12,16 @@
|
||||
*===------------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __has_include
|
||||
#define __has_include(inc) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<stdatomic.h>)
|
||||
|
||||
#include <stdatomic.h>
|
||||
#undef atomic_flag_clear
|
||||
void atomic_flag_clear(volatile atomic_flag *object) {
|
||||
return __c11_atomic_store(&(object)->_Value, 0, __ATOMIC_SEQ_CST);
|
||||
__c11_atomic_store(&(object)->_Value, 0, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -12,9 +12,17 @@
|
||||
*===------------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __has_include
|
||||
#define __has_include(inc) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<stdatomic.h>)
|
||||
|
||||
#include <stdatomic.h>
|
||||
#undef atomic_flag_clear_explicit
|
||||
void atomic_flag_clear_explicit(volatile atomic_flag *object,
|
||||
memory_order order) {
|
||||
return __c11_atomic_store(&(object)->_Value, 0, order);
|
||||
__c11_atomic_store(&(object)->_Value, 0, order);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -12,8 +12,16 @@
|
||||
*===------------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __has_include
|
||||
#define __has_include(inc) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<stdatomic.h>)
|
||||
|
||||
#include <stdatomic.h>
|
||||
#undef atomic_flag_test_and_set
|
||||
_Bool atomic_flag_test_and_set(volatile atomic_flag *object) {
|
||||
return __c11_atomic_exchange(&(object)->_Value, 1, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -12,9 +12,17 @@
|
||||
*===------------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __has_include
|
||||
#define __has_include(inc) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<stdatomic.h>)
|
||||
|
||||
#include <stdatomic.h>
|
||||
#undef atomic_flag_test_and_set_explicit
|
||||
_Bool atomic_flag_test_and_set_explicit(volatile atomic_flag *object,
|
||||
memory_order order) {
|
||||
return __c11_atomic_exchange(&(object)->_Value, 1, order);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -12,8 +12,16 @@
|
||||
*===------------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __has_include
|
||||
#define __has_include(inc) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<stdatomic.h>)
|
||||
|
||||
#include <stdatomic.h>
|
||||
#undef atomic_signal_fence
|
||||
void atomic_signal_fence(memory_order order) {
|
||||
__c11_atomic_signal_fence(order);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -12,8 +12,16 @@
|
||||
*===------------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __has_include
|
||||
#define __has_include(inc) 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<stdatomic.h>)
|
||||
|
||||
#include <stdatomic.h>
|
||||
#undef atomic_thread_fence
|
||||
void atomic_thread_fence(memory_order order) {
|
||||
__c11_atomic_thread_fence(order);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -80,6 +80,11 @@ __ledf2(fp_t a, fp_t b) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__ELF__)
|
||||
// Alias for libgcc compatibility
|
||||
FNALIAS(__cmpdf2, __ledf2);
|
||||
#endif
|
||||
|
||||
enum GE_RESULT {
|
||||
GE_LESS = -1,
|
||||
GE_EQUAL = 0,
|
||||
|
@ -80,6 +80,11 @@ __lesf2(fp_t a, fp_t b) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__ELF__)
|
||||
// Alias for libgcc compatibility
|
||||
FNALIAS(__cmpsf2, __lesf2);
|
||||
#endif
|
||||
|
||||
enum GE_RESULT {
|
||||
GE_LESS = -1,
|
||||
GE_EQUAL = 0,
|
||||
|
@ -79,6 +79,11 @@ COMPILER_RT_ABI enum LE_RESULT __letf2(fp_t a, fp_t b) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__ELF__)
|
||||
// Alias for libgcc compatibility
|
||||
FNALIAS(__cmptf2, __letf2);
|
||||
#endif
|
||||
|
||||
enum GE_RESULT {
|
||||
GE_LESS = -1,
|
||||
GE_EQUAL = 0,
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
/* Returns: the quotient of (a + ib) / (c + id) */
|
||||
|
||||
COMPILER_RT_ABI double _Complex
|
||||
COMPILER_RT_ABI Dcomplex
|
||||
__divdc3(double __a, double __b, double __c, double __d)
|
||||
{
|
||||
int __ilogbw = 0;
|
||||
@ -29,31 +29,31 @@ __divdc3(double __a, double __b, double __c, double __d)
|
||||
__d = crt_scalbn(__d, -__ilogbw);
|
||||
}
|
||||
double __denom = __c * __c + __d * __d;
|
||||
double _Complex z;
|
||||
__real__ z = crt_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
__imag__ z = crt_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(__real__ z) && crt_isnan(__imag__ z))
|
||||
Dcomplex z;
|
||||
COMPLEX_REAL(z) = crt_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
COMPLEX_IMAGINARY(z) = crt_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(COMPLEX_REAL(z)) && crt_isnan(COMPLEX_IMAGINARY(z)))
|
||||
{
|
||||
if ((__denom == 0.0) && (!crt_isnan(__a) || !crt_isnan(__b)))
|
||||
{
|
||||
__real__ z = crt_copysign(CRT_INFINITY, __c) * __a;
|
||||
__imag__ z = crt_copysign(CRT_INFINITY, __c) * __b;
|
||||
COMPLEX_REAL(z) = crt_copysign(CRT_INFINITY, __c) * __a;
|
||||
COMPLEX_IMAGINARY(z) = crt_copysign(CRT_INFINITY, __c) * __b;
|
||||
}
|
||||
else if ((crt_isinf(__a) || crt_isinf(__b)) &&
|
||||
crt_isfinite(__c) && crt_isfinite(__d))
|
||||
{
|
||||
__a = crt_copysign(crt_isinf(__a) ? 1.0 : 0.0, __a);
|
||||
__b = crt_copysign(crt_isinf(__b) ? 1.0 : 0.0, __b);
|
||||
__real__ z = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
__imag__ z = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
COMPLEX_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
COMPLEX_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
}
|
||||
else if (crt_isinf(__logbw) && __logbw > 0.0 &&
|
||||
crt_isfinite(__a) && crt_isfinite(__b))
|
||||
{
|
||||
__c = crt_copysign(crt_isinf(__c) ? 1.0 : 0.0, __c);
|
||||
__d = crt_copysign(crt_isinf(__d) ? 1.0 : 0.0, __d);
|
||||
__real__ z = 0.0 * (__a * __c + __b * __d);
|
||||
__imag__ z = 0.0 * (__b * __c - __a * __d);
|
||||
COMPLEX_REAL(z) = 0.0 * (__a * __c + __b * __d);
|
||||
COMPLEX_IMAGINARY(z) = 0.0 * (__b * __c - __a * __d);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
/* Returns: the quotient of (a + ib) / (c + id) */
|
||||
|
||||
COMPILER_RT_ABI float _Complex
|
||||
COMPILER_RT_ABI Fcomplex
|
||||
__divsc3(float __a, float __b, float __c, float __d)
|
||||
{
|
||||
int __ilogbw = 0;
|
||||
@ -29,31 +29,31 @@ __divsc3(float __a, float __b, float __c, float __d)
|
||||
__d = crt_scalbnf(__d, -__ilogbw);
|
||||
}
|
||||
float __denom = __c * __c + __d * __d;
|
||||
float _Complex z;
|
||||
__real__ z = crt_scalbnf((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
__imag__ z = crt_scalbnf((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(__real__ z) && crt_isnan(__imag__ z))
|
||||
Fcomplex z;
|
||||
COMPLEX_REAL(z) = crt_scalbnf((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
COMPLEX_IMAGINARY(z) = crt_scalbnf((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(COMPLEX_REAL(z)) && crt_isnan(COMPLEX_IMAGINARY(z)))
|
||||
{
|
||||
if ((__denom == 0) && (!crt_isnan(__a) || !crt_isnan(__b)))
|
||||
{
|
||||
__real__ z = crt_copysignf(CRT_INFINITY, __c) * __a;
|
||||
__imag__ z = crt_copysignf(CRT_INFINITY, __c) * __b;
|
||||
COMPLEX_REAL(z) = crt_copysignf(CRT_INFINITY, __c) * __a;
|
||||
COMPLEX_IMAGINARY(z) = crt_copysignf(CRT_INFINITY, __c) * __b;
|
||||
}
|
||||
else if ((crt_isinf(__a) || crt_isinf(__b)) &&
|
||||
crt_isfinite(__c) && crt_isfinite(__d))
|
||||
{
|
||||
__a = crt_copysignf(crt_isinf(__a) ? 1 : 0, __a);
|
||||
__b = crt_copysignf(crt_isinf(__b) ? 1 : 0, __b);
|
||||
__real__ z = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
__imag__ z = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
COMPLEX_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
COMPLEX_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
}
|
||||
else if (crt_isinf(__logbw) && __logbw > 0 &&
|
||||
crt_isfinite(__a) && crt_isfinite(__b))
|
||||
{
|
||||
__c = crt_copysignf(crt_isinf(__c) ? 1 : 0, __c);
|
||||
__d = crt_copysignf(crt_isinf(__d) ? 1 : 0, __d);
|
||||
__real__ z = 0 * (__a * __c + __b * __d);
|
||||
__imag__ z = 0 * (__b * __c - __a * __d);
|
||||
COMPLEX_REAL(z) = 0 * (__a * __c + __b * __d);
|
||||
COMPLEX_IMAGINARY(z) = 0 * (__b * __c - __a * __d);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
|
60
lib/builtins/divtc3.c
Normal file
60
lib/builtins/divtc3.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*===-- divtc3.c - Implement __divtc3 -------------------------------------===
|
||||
*
|
||||
* 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 __divtc3 for the compiler_rt library.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
#include "int_math.h"
|
||||
|
||||
/* Returns: the quotient of (a + ib) / (c + id) */
|
||||
|
||||
COMPILER_RT_ABI long double _Complex
|
||||
__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)));
|
||||
if (crt_isfinite(__logbw))
|
||||
{
|
||||
__ilogbw = (int)__logbw;
|
||||
__c = crt_scalbnl(__c, -__ilogbw);
|
||||
__d = crt_scalbnl(__d, -__ilogbw);
|
||||
}
|
||||
long double __denom = __c * __c + __d * __d;
|
||||
long double _Complex z;
|
||||
__real__ z = crt_scalbnl((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
__imag__ z = crt_scalbnl((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(__real__ z) && crt_isnan(__imag__ z))
|
||||
{
|
||||
if ((__denom == 0.0) && (!crt_isnan(__a) || !crt_isnan(__b)))
|
||||
{
|
||||
__real__ z = crt_copysignl(CRT_INFINITY, __c) * __a;
|
||||
__imag__ z = crt_copysignl(CRT_INFINITY, __c) * __b;
|
||||
}
|
||||
else if ((crt_isinf(__a) || crt_isinf(__b)) &&
|
||||
crt_isfinite(__c) && crt_isfinite(__d))
|
||||
{
|
||||
__a = crt_copysignl(crt_isinf(__a) ? 1.0 : 0.0, __a);
|
||||
__b = crt_copysignl(crt_isinf(__b) ? 1.0 : 0.0, __b);
|
||||
__real__ z = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
__imag__ z = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
}
|
||||
else if (crt_isinf(__logbw) && __logbw > 0.0 &&
|
||||
crt_isfinite(__a) && crt_isfinite(__b))
|
||||
{
|
||||
__c = crt_copysignl(crt_isinf(__c) ? 1.0 : 0.0, __c);
|
||||
__d = crt_copysignl(crt_isinf(__d) ? 1.0 : 0.0, __d);
|
||||
__real__ z = 0.0 * (__a * __c + __b * __d);
|
||||
__imag__ z = 0.0 * (__b * __c - __a * __d);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
|
||||
/* Returns: the quotient of (a + ib) / (c + id) */
|
||||
|
||||
COMPILER_RT_ABI long double _Complex
|
||||
COMPILER_RT_ABI Lcomplex
|
||||
__divxc3(long double __a, long double __b, long double __c, long double __d)
|
||||
{
|
||||
int __ilogbw = 0;
|
||||
@ -30,31 +30,31 @@ __divxc3(long double __a, long double __b, long double __c, long double __d)
|
||||
__d = crt_scalbnl(__d, -__ilogbw);
|
||||
}
|
||||
long double __denom = __c * __c + __d * __d;
|
||||
long double _Complex z;
|
||||
__real__ z = crt_scalbnl((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
__imag__ z = crt_scalbnl((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(__real__ z) && crt_isnan(__imag__ z))
|
||||
Lcomplex z;
|
||||
COMPLEX_REAL(z) = crt_scalbnl((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
COMPLEX_IMAGINARY(z) = crt_scalbnl((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(COMPLEX_REAL(z)) && crt_isnan(COMPLEX_IMAGINARY(z)))
|
||||
{
|
||||
if ((__denom == 0) && (!crt_isnan(__a) || !crt_isnan(__b)))
|
||||
{
|
||||
__real__ z = crt_copysignl(CRT_INFINITY, __c) * __a;
|
||||
__imag__ z = crt_copysignl(CRT_INFINITY, __c) * __b;
|
||||
COMPLEX_REAL(z) = crt_copysignl(CRT_INFINITY, __c) * __a;
|
||||
COMPLEX_IMAGINARY(z) = crt_copysignl(CRT_INFINITY, __c) * __b;
|
||||
}
|
||||
else if ((crt_isinf(__a) || crt_isinf(__b)) &&
|
||||
crt_isfinite(__c) && crt_isfinite(__d))
|
||||
{
|
||||
__a = crt_copysignl(crt_isinf(__a) ? 1 : 0, __a);
|
||||
__b = crt_copysignl(crt_isinf(__b) ? 1 : 0, __b);
|
||||
__real__ z = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
__imag__ z = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
COMPLEX_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
COMPLEX_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
}
|
||||
else if (crt_isinf(__logbw) && __logbw > 0 &&
|
||||
crt_isfinite(__a) && crt_isfinite(__b))
|
||||
{
|
||||
__c = crt_copysignl(crt_isinf(__c) ? 1 : 0, __c);
|
||||
__d = crt_copysignl(crt_isinf(__d) ? 1 : 0, __d);
|
||||
__real__ z = 0 * (__a * __c + __b * __d);
|
||||
__imag__ z = 0 * (__b * __c - __a * __d);
|
||||
COMPLEX_REAL(z) = 0 * (__a * __c + __b * __d);
|
||||
COMPLEX_IMAGINARY(z) = 0 * (__b * __c - __a * __d);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
|
183
lib/builtins/emutls.c
Normal file
183
lib/builtins/emutls.c
Normal file
@ -0,0 +1,183 @@
|
||||
/* ===---------- emutls.c - Implements __emutls_get_address ---------------===
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "int_lib.h"
|
||||
#include "int_util.h"
|
||||
|
||||
/* Default is not to use posix_memalign, so systems like Android
|
||||
* can use thread local data without heavier POSIX memory allocators.
|
||||
*/
|
||||
#ifndef EMUTLS_USE_POSIX_MEMALIGN
|
||||
#define EMUTLS_USE_POSIX_MEMALIGN 0
|
||||
#endif
|
||||
|
||||
/* For every TLS variable xyz,
|
||||
* there is one __emutls_control variable named __emutls_v.xyz.
|
||||
* If xyz has non-zero initial value, __emutls_v.xyz's "value"
|
||||
* will point to __emutls_t.xyz, which has the initial value.
|
||||
*/
|
||||
typedef struct __emutls_control {
|
||||
size_t size; /* size of the object in bytes */
|
||||
size_t align; /* alignment of the object in bytes */
|
||||
union {
|
||||
uintptr_t index; /* data[index-1] is the object address */
|
||||
void* address; /* object address, when in single thread env */
|
||||
} object;
|
||||
void* value; /* null or non-zero initial value for the object */
|
||||
} __emutls_control;
|
||||
|
||||
static __inline void *emutls_memalign_alloc(size_t align, size_t size) {
|
||||
void *base;
|
||||
#if EMUTLS_USE_POSIX_MEMALIGN
|
||||
if (posix_memalign(&base, align, size) != 0)
|
||||
abort();
|
||||
#else
|
||||
#define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void*))
|
||||
char* object;
|
||||
if ((object = malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL)
|
||||
abort();
|
||||
base = (void*)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES))
|
||||
& ~(uintptr_t)(align - 1));
|
||||
|
||||
((void**)base)[-1] = object;
|
||||
#endif
|
||||
return base;
|
||||
}
|
||||
|
||||
static __inline void emutls_memalign_free(void *base) {
|
||||
#if EMUTLS_USE_POSIX_MEMALIGN
|
||||
free(base);
|
||||
#else
|
||||
/* The mallocated address is in ((void**)base)[-1] */
|
||||
free(((void**)base)[-1]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Emulated TLS objects are always allocated at run-time. */
|
||||
static __inline void *emutls_allocate_object(__emutls_control *control) {
|
||||
/* Use standard C types, check with gcc's emutls.o. */
|
||||
typedef unsigned int gcc_word __attribute__((mode(word)));
|
||||
typedef unsigned int gcc_pointer __attribute__((mode(pointer)));
|
||||
COMPILE_TIME_ASSERT(sizeof(size_t) == sizeof(gcc_word));
|
||||
COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(gcc_pointer));
|
||||
COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(void*));
|
||||
|
||||
size_t size = control->size;
|
||||
size_t align = control->align;
|
||||
if (align < sizeof(void*))
|
||||
align = sizeof(void*);
|
||||
/* Make sure that align is power of 2. */
|
||||
if ((align & (align - 1)) != 0)
|
||||
abort();
|
||||
|
||||
void* base = emutls_memalign_alloc(align, size);
|
||||
if (control->value)
|
||||
memcpy(base, control->value, size);
|
||||
else
|
||||
memset(base, 0, size);
|
||||
return base;
|
||||
}
|
||||
|
||||
static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static size_t emutls_num_object = 0; /* number of allocated TLS objects */
|
||||
|
||||
typedef struct emutls_address_array {
|
||||
uintptr_t size; /* number of elements in the 'data' array */
|
||||
void* data[];
|
||||
} emutls_address_array;
|
||||
|
||||
static pthread_key_t emutls_pthread_key;
|
||||
|
||||
static void emutls_key_destructor(void* ptr) {
|
||||
emutls_address_array* array = (emutls_address_array*)ptr;
|
||||
uintptr_t i;
|
||||
for (i = 0; i < array->size; ++i) {
|
||||
if (array->data[i])
|
||||
emutls_memalign_free(array->data[i]);
|
||||
}
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static void emutls_init(void) {
|
||||
if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Returns control->object.index; set index if not allocated yet. */
|
||||
static __inline uintptr_t emutls_get_index(__emutls_control *control) {
|
||||
uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE);
|
||||
if (!index) {
|
||||
static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
pthread_once(&once, emutls_init);
|
||||
pthread_mutex_lock(&emutls_mutex);
|
||||
index = control->object.index;
|
||||
if (!index) {
|
||||
index = ++emutls_num_object;
|
||||
__atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE);
|
||||
}
|
||||
pthread_mutex_unlock(&emutls_mutex);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Updates newly allocated thread local emutls_address_array. */
|
||||
static __inline void emutls_check_array_set_size(emutls_address_array *array,
|
||||
uintptr_t size) {
|
||||
if (array == NULL)
|
||||
abort();
|
||||
array->size = size;
|
||||
pthread_setspecific(emutls_pthread_key, (void*)array);
|
||||
}
|
||||
|
||||
/* Returns the new 'data' array size, number of elements,
|
||||
* which must be no smaller than the given index.
|
||||
*/
|
||||
static __inline uintptr_t emutls_new_data_array_size(uintptr_t index) {
|
||||
/* Need to allocate emutls_address_array with one extra slot
|
||||
* to store the data array size.
|
||||
* Round up the emutls_address_array size to multiple of 16.
|
||||
*/
|
||||
return ((index + 1 + 15) & ~((uintptr_t)15)) - 1;
|
||||
}
|
||||
|
||||
/* Returns the thread local emutls_address_array.
|
||||
* Extends its size if necessary to hold address at index.
|
||||
*/
|
||||
static __inline emutls_address_array *
|
||||
emutls_get_address_array(uintptr_t index) {
|
||||
emutls_address_array* array = pthread_getspecific(emutls_pthread_key);
|
||||
if (array == NULL) {
|
||||
uintptr_t new_size = emutls_new_data_array_size(index);
|
||||
array = calloc(new_size + 1, sizeof(void*));
|
||||
emutls_check_array_set_size(array, new_size);
|
||||
} else if (index > array->size) {
|
||||
uintptr_t orig_size = array->size;
|
||||
uintptr_t new_size = emutls_new_data_array_size(index);
|
||||
array = realloc(array, (new_size + 1) * sizeof(void*));
|
||||
if (array)
|
||||
memset(array->data + orig_size, 0,
|
||||
(new_size - orig_size) * sizeof(void*));
|
||||
emutls_check_array_set_size(array, new_size);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
void* __emutls_get_address(__emutls_control* control) {
|
||||
uintptr_t index = emutls_get_index(control);
|
||||
emutls_address_array* array = emutls_get_address_array(index);
|
||||
if (array->data[index - 1] == NULL)
|
||||
array->data[index - 1] = emutls_allocate_object(control);
|
||||
return array->data[index - 1];
|
||||
}
|
@ -21,8 +21,8 @@
|
||||
#define HAVE_SYSCONF 1
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#ifndef __APPLE__
|
||||
#include <unistd.h>
|
||||
|
@ -12,9 +12,11 @@
|
||||
#define DST_SINGLE
|
||||
#include "fp_extend_impl.inc"
|
||||
|
||||
ARM_EABI_FNALIAS(h2f, extendhfsf2)
|
||||
|
||||
// Use a forwarding definition and noinline to implement a poor man's alias,
|
||||
// as there isn't a good cross-platform way of defining one.
|
||||
COMPILER_RT_ABI __attribute__((noinline)) float __extendhfsf2(uint16_t a) {
|
||||
COMPILER_RT_ABI NOINLINE float __extendhfsf2(uint16_t a) {
|
||||
return __extendXfYf2__(a);
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ COMPILER_RT_ABI du_int
|
||||
__fixunsdfdi(double a)
|
||||
{
|
||||
if (a <= 0.0) return 0;
|
||||
su_int high = a/0x1p32f;
|
||||
su_int low = a - (double)high*0x1p32f;
|
||||
su_int high = a / 4294967296.f; /* a / 0x1p32f; */
|
||||
su_int low = a - (double)high * 4294967296.f; /* high * 0x1p32f; */
|
||||
return ((du_int)high << 32) | low;
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,8 @@ __fixunssfdi(float a)
|
||||
{
|
||||
if (a <= 0.0f) return 0;
|
||||
double da = a;
|
||||
su_int high = da/0x1p32f;
|
||||
su_int low = da - (double)high*0x1p32f;
|
||||
su_int high = da / 4294967296.f; /* da / 0x1p32f; */
|
||||
su_int low = da - (double)high * 4294967296.f; /* high * 0x1p32f; */
|
||||
return ((du_int)high << 32) | low;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user