Vendor import of compiler-rt trunk r256633:

https://llvm.org/svn/llvm-project/compiler-rt/trunk@256633
This commit is contained in:
Dimitry Andric 2015-12-30 11:52:19 +00:00
parent f31bcc68c7
commit 5c909fa013
767 changed files with 19607 additions and 5527 deletions

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

@ -0,0 +1 @@
BasedOnStyle: Google

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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(&param->t, memory_order_acquire))) == 0)
atomic_load(&param->t, memory_order_acquire))) == nullptr)
internal_sched_yield();
SetCurrentThread(t);
return t->ThreadStart(GetTid(), &param->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(&param.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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,7 +34,7 @@
// Make sure __asan_init is called before any test case is run.
struct AsanInitCaller {
AsanInitCaller() {
__asan::DisableReexec();
DisableReexec();
__asan_init();
}
};

View File

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

View File

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

View File

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

View 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

View 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

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

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

View 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

View 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

View File

@ -0,0 +1 @@
apple_versioning

View 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

View 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

View File

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

View 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

View File

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

View File

@ -0,0 +1 @@
apple_versioning

View 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

View File

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

View File

@ -0,0 +1 @@
apple_versioning

View File

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

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

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

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

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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