Import compiler-rt 3.7.0 release (r246257).
This commit is contained in:
parent
cd2dd3df15
commit
f31bcc68c7
@ -139,6 +139,13 @@ 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)
|
||||
endif()
|
||||
|
||||
if ("${COMPILER_RT_TEST_TARGET_ABI}" STREQUAL "androideabi")
|
||||
set(ANDROID 1)
|
||||
@ -160,13 +167,11 @@ include(CompilerRTUtils)
|
||||
|
||||
set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
# Setup custom SDK sysroots.
|
||||
set(COMPILER_RT_LINUX_SDK_SYSROOT ${COMPILER_RT_SOURCE_DIR}/SDKs/linux)
|
||||
|
||||
# We support running instrumented tests when we're not cross compiling
|
||||
# and target a UNIX-like system or Windows.
|
||||
# We can run tests on Android even when we are cross-compiling.
|
||||
if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR MSVC)) OR ANDROID
|
||||
if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR WIN32)) OR ANDROID
|
||||
OR COMPILER_RT_EMULATOR)
|
||||
option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON)
|
||||
else()
|
||||
@ -209,22 +214,22 @@ append_list_if(COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG -fno-exceptions SANITIZER_COM
|
||||
append_list_if(COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG -fomit-frame-pointer SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FUNWIND_TABLES_FLAG -funwind-tables SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG -fno-sanitize=safe-stack SANITIZER_COMMON_CFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS)
|
||||
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)
|
||||
|
||||
if(MSVC)
|
||||
# Replace the /MD[d] flags with /MT.
|
||||
# Replace the /M[DT][d] flags with /MT, and strip any definitions of _DEBUG,
|
||||
# which cause definition mismatches at link time.
|
||||
# FIXME: In fact, sanitizers should support both /MT and /MD, see PR20214.
|
||||
if(COMPILER_RT_HAS_MT_FLAG)
|
||||
foreach(flag_var
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
if(${flag_var} MATCHES "/MD")
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
elseif(${flag_var} MATCHES "/MDd")
|
||||
string(REGEX REPLACE "/MDd" "/MT" ${flag_var} "${${flag_var}}")
|
||||
endif()
|
||||
string(REGEX REPLACE "/M[DT]d" "/MT" ${flag_var} "${${flag_var}}")
|
||||
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
string(REGEX REPLACE "/D_DEBUG" "" ${flag_var} "${${flag_var}}")
|
||||
endforeach()
|
||||
endif()
|
||||
append_list_if(COMPILER_RT_HAS_Oy_FLAG /Oy- SANITIZER_COMMON_CFLAGS)
|
||||
@ -240,12 +245,13 @@ if(NOT COMPILER_RT_DEBUG AND NOT MSVC)
|
||||
endif()
|
||||
|
||||
# Determine if we should restrict stack frame sizes.
|
||||
# Stack frames on PowerPC and in debug biuld can be much larger than
|
||||
# Stack frames on PowerPC and Mips and in debug biuld can be much larger than
|
||||
# anticipated.
|
||||
# FIXME: Fix all sanitizers and add -Wframe-larger-than to
|
||||
# SANITIZER_COMMON_FLAGS
|
||||
if(COMPILER_RT_HAS_WFRAME_LARGER_THAN_FLAG AND NOT COMPILER_RT_DEBUG
|
||||
AND NOT ${LLVM_NATIVE_ARCH} STREQUAL "PowerPC")
|
||||
AND NOT ${LLVM_NATIVE_ARCH} STREQUAL "PowerPC"
|
||||
AND NOT ${LLVM_NATIVE_ARCH} STREQUAL "Mips")
|
||||
set(SANITIZER_LIMIT_FRAME_SIZE TRUE)
|
||||
else()
|
||||
set(SANITIZER_LIMIT_FRAME_SIZE FALSE)
|
||||
@ -292,27 +298,52 @@ if(APPLE)
|
||||
find_darwin_sdk_dir(OSX_SDK_DIR macosx)
|
||||
find_darwin_sdk_dir(IOSSIM_SDK_DIR iphonesimulator)
|
||||
|
||||
string(REGEX MATCH "-mmacosx-version-min="
|
||||
set(SANITIZER_COMMON_SUPPORTED_OS osx)
|
||||
string(REGEX MATCH "-mmacosx-version-min=([.0-9]+)"
|
||||
MACOSX_VERSION_MIN_FLAG "${CMAKE_CXX_FLAGS}")
|
||||
set(SANITIZER_COMMON_SUPPORTED_DARWIN_OS osx)
|
||||
if (IOSSIM_SDK_DIR AND NOT MACOSX_VERSION_MIN_FLAG)
|
||||
list(APPEND SANITIZER_COMMON_SUPPORTED_DARWIN_OS iossim)
|
||||
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(SANITIZER_MIN_OSX_VERSION 10.7)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "") # We're setting the flag manually below.
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "") # We evaluate target OS X version above.
|
||||
set(DARWIN_osx_CFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}
|
||||
-isysroot ${OSX_SDK_DIR} -stdlib=libc++)
|
||||
-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}
|
||||
-isysroot ${OSX_SDK_DIR} -stdlib=libc++)
|
||||
-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
|
||||
# libc++/libc++abi.
|
||||
set(SANITIZER_CAN_USE_CXXABI FALSE)
|
||||
else()
|
||||
set(SANITIZER_CAN_USE_CXXABI TRUE)
|
||||
endif()
|
||||
pythonize_bool(SANITIZER_CAN_USE_CXXABI)
|
||||
|
||||
add_subdirectory(include)
|
||||
|
||||
set(COMPILER_RT_LIBCXX_PATH ${LLVM_MAIN_SRC_DIR}/projects/libcxx)
|
||||
|
@ -14,7 +14,7 @@ Full text of the relevant licenses is included below.
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
|
||||
Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
|
||||
|
||||
All rights reserved.
|
||||
|
||||
@ -55,7 +55,7 @@ SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
|
||||
Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -1,9 +0,0 @@
|
||||
It is often convenient to be able to build compiler-rt libraries for a certain
|
||||
platform without having a full SDK or development environment installed.
|
||||
|
||||
This makes it easy for users to build a compiler which can target a number of
|
||||
different platforms, without having to actively maintain full development
|
||||
environments for those platforms.
|
||||
|
||||
Since compiler-rt's libraries typically have minimal interaction with the
|
||||
system, we achieve this by stubbing out the SDKs of certain platforms.
|
@ -1,2 +0,0 @@
|
||||
This is a stub SDK for Linux. Currently, this has only been tested on i386 and
|
||||
x86_64 using the Clang compiler.
|
@ -1,29 +0,0 @@
|
||||
/* ===-- endian.h - stub SDK header for compiler-rt -------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __ENDIAN_H__
|
||||
#define __ENDIAN_H__
|
||||
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BIG_ENDIAN 4321
|
||||
|
||||
#if defined(__LITTLE_ENDIAN__) || defined(__ORDER_LITTLE_ENDIAN__)
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#else
|
||||
#define __BYTE_ORDER __BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#endif /* __ENDIAN_H__ */
|
@ -1,17 +0,0 @@
|
||||
/* ===-- fcntl.h - stub SDK header for compiler-rt --------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include <sys/fcntl.h>
|
@ -1,23 +0,0 @@
|
||||
/* ===-- limits.h - stub SDK header for compiler-rt -------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __LIMITS_H__
|
||||
#define __LIMITS_H__
|
||||
|
||||
/* This is only here as a landing pad for the include_next from the compiler's
|
||||
built-in limits.h. */
|
||||
|
||||
#endif /* __LIMITS_H__ */
|
@ -1,44 +0,0 @@
|
||||
/* ===-- stdio.h - stub SDK header for compiler-rt --------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __STDIO_H__
|
||||
#define __STDIO_H__
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
struct _IO_FILE;
|
||||
typedef struct _IO_FILE FILE;
|
||||
|
||||
extern struct _IO_FILE *stdin;
|
||||
extern struct _IO_FILE *stdout;
|
||||
extern struct _IO_FILE *stderr;
|
||||
|
||||
#define SEEK_SET 0 /* set file offset to offset */
|
||||
#define SEEK_CUR 1 /* set file offset to current plus offset */
|
||||
#define SEEK_END 2 /* set file offset to EOF plus offset */
|
||||
|
||||
extern int fclose(FILE *);
|
||||
extern int fflush(FILE *);
|
||||
extern FILE *fopen(const char * restrict, const char * restrict);
|
||||
extern FILE *fdopen(int, const char * restrict);
|
||||
extern int fprintf(FILE * restrict, const char * restrict, ...);
|
||||
extern int fputc(int, FILE *);
|
||||
extern size_t fwrite(const void * restrict, size_t, size_t, FILE * restrict);
|
||||
extern size_t fread(void * restrict, size_t, size_t, FILE * restrict);
|
||||
extern long ftell(FILE *);
|
||||
extern int fseek(FILE *, long, int);
|
||||
|
||||
#endif /* __STDIO_H__ */
|
@ -1,36 +0,0 @@
|
||||
/* ===-- stdlib.h - stub SDK header for compiler-rt -------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __STDLIB_H__
|
||||
#define __STDLIB_H__
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
void abort(void) __attribute__((__nothrow__)) __attribute__((__noreturn__));
|
||||
int atexit(void (*)(void)) __attribute__((__nothrow__));
|
||||
int atoi(const char *) __attribute__((__nothrow__));
|
||||
void free(void *) __attribute__((__nothrow__));
|
||||
char *getenv(const char *) __attribute__((__nothrow__))
|
||||
__attribute__((__nonnull__(1)));
|
||||
__attribute__((__warn_unused_result__));
|
||||
void *malloc(size_t) __attribute__((__nothrow__)) __attribute((__malloc__))
|
||||
__attribute__((__warn_unused_result__));
|
||||
void *realloc(void *, size_t) __attribute__((__nothrow__)) __attribute((__malloc__))
|
||||
__attribute__((__warn_unused_result__));
|
||||
|
||||
#endif /* __STDLIB_H__ */
|
@ -1,31 +0,0 @@
|
||||
/* ===-- string.h - stub SDK header for compiler-rt -------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __STRING_H__
|
||||
#define __STRING_H__
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
int memcmp(const void *, const void *, size_t);
|
||||
void *memcpy(void *, const void *, size_t);
|
||||
void *memset(void *, int, size_t);
|
||||
char *strcat(char *, const char *);
|
||||
char *strcpy(char *, const char *);
|
||||
char *strdup(const char *);
|
||||
size_t strlen(const char *);
|
||||
char *strncpy(char *, const char *, size_t);
|
||||
|
||||
#endif /* __STRING_H__ */
|
@ -1,29 +0,0 @@
|
||||
/* ===-- fcntl.h - stub SDK header for compiler-rt --------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef _SYS_FCNTL_H_
|
||||
#define _SYS_FCNTL_H_
|
||||
|
||||
#define O_RDONLY 0x0000
|
||||
#define O_WRONLY 0x0001
|
||||
#define O_RDWR 0x0002
|
||||
#define O_ACCMODE 0x0003
|
||||
|
||||
#define O_CREAT 0x0200
|
||||
|
||||
int open(const char *, int, ...);
|
||||
|
||||
#endif /* _SYS_FCNTL_H_ */
|
@ -1,47 +0,0 @@
|
||||
/* ===-- limits.h - stub SDK header for compiler-rt -------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __SYS_MMAN_H__
|
||||
#define __SYS_MMAN_H__
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
#define PROT_NONE 0x00
|
||||
#define PROT_READ 0x01
|
||||
#define PROT_WRITE 0x02
|
||||
#define PROT_EXEC 0x04
|
||||
|
||||
#define MAP_SHARED 0x0001
|
||||
#define MAP_PRIVATE 0x0002
|
||||
|
||||
#define MAP_FILE 0x0000
|
||||
#define MAP_ANON 0x1000
|
||||
|
||||
#define MS_ASYNC 0x0001
|
||||
#define MS_INVALIDATE 0x0002
|
||||
#define MS_SYNC 0x0010
|
||||
|
||||
extern void *mmap(void *addr, size_t len, int prot, int flags, int fd,
|
||||
long long offset)
|
||||
__attribute__((__nothrow__));
|
||||
extern int munmap(void *addr, size_t len)
|
||||
__attribute__((__nothrow__));
|
||||
extern int msync(void *addr, size_t len, int flags)
|
||||
__attribute__((__nothrow__));
|
||||
extern int mprotect (void *__addr, size_t __len, int __prot)
|
||||
__attribute__((__nothrow__));
|
||||
|
||||
#endif /* __SYS_MMAN_H__ */
|
@ -1,24 +0,0 @@
|
||||
/* ===-- stat.h - stub SDK header for compiler-rt ---------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __SYS_STAT_H__
|
||||
#define __SYS_STAT_H__
|
||||
|
||||
typedef unsigned int mode_t;
|
||||
|
||||
int mkdir(const char *, mode_t);
|
||||
|
||||
#endif /* __SYS_STAT_H__ */
|
@ -1,20 +0,0 @@
|
||||
/* ===-- stat.h - stub SDK header for compiler-rt ---------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __SYS_TYPES_H__
|
||||
#define __SYS_TYPES_H__
|
||||
|
||||
#endif /* __SYS_TYPES_H__ */
|
@ -1,26 +0,0 @@
|
||||
/* ===-- unistd.h - stub SDK header for compiler-rt -------------------------===
|
||||
*
|
||||
* 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 is a stub SDK header file. This file is not part of the interface of
|
||||
* this library nor an official version of the appropriate SDK header. It is
|
||||
* intended only to stub the features of this header required by compiler-rt.
|
||||
*
|
||||
* ===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef __UNISTD_H__
|
||||
#define __UNISTD_H__
|
||||
|
||||
enum {
|
||||
_SC_PAGESIZE = 30
|
||||
};
|
||||
|
||||
extern long int sysconf (int __name) __attribute__ ((__nothrow__));
|
||||
|
||||
#endif /* __UNISTD_H__ */
|
@ -1,42 +1,48 @@
|
||||
include(AddLLVM)
|
||||
include(ExternalProject)
|
||||
include(LLVMParseArguments)
|
||||
include(CompilerRTUtils)
|
||||
|
||||
# Tries to add "object library" target for a given architecture
|
||||
# with name "<name>.<arch>" if architecture can be targeted.
|
||||
# add_compiler_rt_object_library(<name> <arch>
|
||||
# SOURCES <source files>
|
||||
# CFLAGS <compile flags>
|
||||
# DEFS <compile definitions>)
|
||||
macro(add_compiler_rt_object_library name arch)
|
||||
if(CAN_TARGET_${arch})
|
||||
parse_arguments(LIB "SOURCES;CFLAGS;DEFS" "" ${ARGN})
|
||||
add_library(${name}.${arch} OBJECT ${LIB_SOURCES})
|
||||
set_target_compile_flags(${name}.${arch}
|
||||
${CMAKE_CXX_FLAGS} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS})
|
||||
set_property(TARGET ${name}.${arch} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
# Tries to add an "object library" target for a given list of OSs and/or
|
||||
# architectures with name "<name>.<arch>" for non-Darwin platforms if
|
||||
# architecture can be targeted, and "<name>.<os>" for Darwin platforms.
|
||||
# add_compiler_rt_object_libraries(<name>
|
||||
# OS <os names>
|
||||
# ARCHS <architectures>
|
||||
# SOURCES <source files>
|
||||
# CFLAGS <compile flags>
|
||||
# DEFS <compile definitions>)
|
||||
function(add_compiler_rt_object_libraries name)
|
||||
cmake_parse_arguments(LIB "" "" "OS;ARCHS;SOURCES;CFLAGS;DEFS" ${ARGN})
|
||||
set(libnames)
|
||||
if(APPLE)
|
||||
foreach(os ${LIB_OS})
|
||||
set(libname "${name}.${os}")
|
||||
set(libnames ${libnames} ${libname})
|
||||
set(extra_cflags_${libname} ${DARWIN_${os}_CFLAGS})
|
||||
endforeach()
|
||||
else()
|
||||
message(FATAL_ERROR "Archtecture ${arch} can't be targeted")
|
||||
foreach(arch ${LIB_ARCHS})
|
||||
set(libname "${name}.${arch}")
|
||||
set(libnames ${libnames} ${libname})
|
||||
set(extra_cflags_${libname} ${TARGET_${arch}_CFLAGS})
|
||||
if(NOT CAN_TARGET_${arch})
|
||||
message(FATAL_ERROR "Archtecture ${arch} can't be targeted")
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Same as above, but adds universal osx library for either OSX or iOS simulator
|
||||
# with name "<name>.<os>" targeting multiple architectures.
|
||||
# add_compiler_rt_darwin_object_library(<name> <os> ARCH <architectures>
|
||||
# SOURCES <source files>
|
||||
# CFLAGS <compile flags>
|
||||
# DEFS <compile definitions>)
|
||||
macro(add_compiler_rt_darwin_object_library name os)
|
||||
parse_arguments(LIB "ARCH;SOURCES;CFLAGS;DEFS" "" ${ARGN})
|
||||
set(libname "${name}.${os}")
|
||||
add_library(${libname} OBJECT ${LIB_SOURCES})
|
||||
set_target_compile_flags(${libname} ${LIB_CFLAGS} ${DARWIN_${os}_CFLAGS})
|
||||
set_target_properties(${libname} PROPERTIES OSX_ARCHITECTURES "${LIB_ARCH}")
|
||||
set_property(TARGET ${libname} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
endmacro()
|
||||
|
||||
foreach(libname ${libnames})
|
||||
add_library(${libname} OBJECT ${LIB_SOURCES})
|
||||
set_target_compile_flags(${libname}
|
||||
${CMAKE_CXX_FLAGS} ${extra_cflags_${libname}} ${LIB_CFLAGS})
|
||||
set_property(TARGET ${libname} APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS ${LIB_DEFS})
|
||||
if(APPLE)
|
||||
set_target_properties(${libname} PROPERTIES OSX_ARCHITECTURES "${LIB_ARCHS}")
|
||||
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.
|
||||
@ -47,13 +53,13 @@ endmacro()
|
||||
# OUTPUT_NAME <output library name>)
|
||||
macro(add_compiler_rt_runtime name arch type)
|
||||
if(CAN_TARGET_${arch})
|
||||
parse_arguments(LIB "SOURCES;CFLAGS;DEFS;OUTPUT_NAME" "" ${ARGN})
|
||||
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})
|
||||
${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.
|
||||
@ -80,18 +86,18 @@ endmacro()
|
||||
|
||||
# Same as add_compiler_rt_runtime(... STATIC), but creates a universal library
|
||||
# for several architectures.
|
||||
# add_compiler_rt_osx_static_runtime(<name> ARCH <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)
|
||||
parse_arguments(LIB "ARCH;SOURCES;CFLAGS;DEFS" "" ${ARGN})
|
||||
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_ARCH}"
|
||||
OSX_ARCHITECTURES "${LIB_ARCHS}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
|
||||
install(TARGETS ${name}
|
||||
ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
@ -100,20 +106,20 @@ endmacro()
|
||||
# Adds dynamic runtime library on osx/iossim, which supports multiple
|
||||
# architectures.
|
||||
# add_compiler_rt_darwin_dynamic_runtime(<name> <os>
|
||||
# ARCH <architectures>
|
||||
# ARCHS <architectures>
|
||||
# SOURCES <source files>
|
||||
# CFLAGS <compile flags>
|
||||
# DEFS <compile definitions>
|
||||
# LINKFLAGS <link flags>)
|
||||
macro(add_compiler_rt_darwin_dynamic_runtime name os)
|
||||
parse_arguments(LIB "ARCH;SOURCES;CFLAGS;DEFS;LINKFLAGS" "" ${ARGN})
|
||||
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_ARCH}"
|
||||
OSX_ARCHITECTURES "${LIB_ARCHS}"
|
||||
LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR})
|
||||
install(TARGETS ${name}
|
||||
LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR})
|
||||
@ -162,7 +168,7 @@ endif()
|
||||
# DEPS <deps (e.g. runtime libs)>
|
||||
# LINK_FLAGS <link flags>)
|
||||
macro(add_compiler_rt_test test_suite test_name)
|
||||
parse_arguments(TEST "SUBDIR;OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN})
|
||||
cmake_parse_arguments(TEST "" "SUBDIR" "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN})
|
||||
if(TEST_SUBDIR)
|
||||
set(output_bin "${CMAKE_CURRENT_BINARY_DIR}/${TEST_SUBDIR}/${test_name}")
|
||||
else()
|
||||
@ -229,7 +235,7 @@ macro(add_custom_libcxx name prefix)
|
||||
message(FATAL_ERROR "libcxx not found!")
|
||||
endif()
|
||||
|
||||
parse_arguments(LIBCXX "DEPS;CFLAGS" "" ${ARGN})
|
||||
cmake_parse_arguments(LIBCXX "" "" "DEPS;CFLAGS" ${ARGN})
|
||||
foreach(flag ${LIBCXX_CFLAGS})
|
||||
set(flagstr "${flagstr} ${flag}")
|
||||
endforeach()
|
||||
@ -252,6 +258,7 @@ macro(add_custom_libcxx name prefix)
|
||||
LOG_CONFIGURE 1
|
||||
LOG_INSTALL 1
|
||||
)
|
||||
set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
|
||||
ExternalProject_Add_Step(${name} force-reconfigure
|
||||
DEPENDERS configure
|
||||
|
@ -1,4 +1,28 @@
|
||||
include(LLVMParseArguments)
|
||||
# On Windows, CMAKE_*_FLAGS are built for MSVC but we use the GCC clang.exe,
|
||||
# which uses completely different flags. Translate some common flag types, and
|
||||
# drop the rest.
|
||||
function(translate_msvc_cflags out_flags msvc_flags)
|
||||
# Insert an empty string in the list to simplify processing.
|
||||
set(msvc_flags ";${msvc_flags}")
|
||||
|
||||
# Canonicalize /flag to -flag.
|
||||
string(REPLACE ";/" ";-" msvc_flags "${msvc_flags}")
|
||||
|
||||
# Make space separated -D and -U flags into joined flags.
|
||||
string(REGEX REPLACE ";-\([DU]\);" ";-\\1" msvc_flags "${msvc_flags}")
|
||||
|
||||
set(clang_flags "")
|
||||
foreach(flag ${msvc_flags})
|
||||
if ("${flag}" MATCHES "^-[DU]")
|
||||
# Pass through basic command line macro definitions (-DNDEBUG).
|
||||
list(APPEND clang_flags "${flag}")
|
||||
elseif ("${flag}" MATCHES "^-O[2x]")
|
||||
# Canonicalize normal optimization flags to -O2.
|
||||
list(APPEND clang_flags "-O2")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${out_flags} "${clang_flags}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Compile a source into an object file with COMPILER_RT_TEST_COMPILER using
|
||||
# a provided compile flags and dependenices.
|
||||
@ -6,7 +30,7 @@ include(LLVMParseArguments)
|
||||
# CFLAGS <list of compile flags>
|
||||
# DEPS <list of dependencies>)
|
||||
macro(clang_compile object_file source)
|
||||
parse_arguments(SOURCE "CFLAGS;DEPS" "" ${ARGN})
|
||||
cmake_parse_arguments(SOURCE "" "" "CFLAGS;DEPS" ${ARGN})
|
||||
get_filename_component(source_rpath ${source} REALPATH)
|
||||
if(NOT COMPILER_RT_STANDALONE_BUILD)
|
||||
list(APPEND SOURCE_DEPS clang compiler-rt-headers)
|
||||
@ -20,13 +44,11 @@ macro(clang_compile object_file source)
|
||||
else()
|
||||
string(REPLACE " " ";" global_flags "${CMAKE_C_FLAGS}")
|
||||
endif()
|
||||
# On Windows, CMAKE_*_FLAGS are built for MSVC but we use the GCC clang.exe
|
||||
# which doesn't support flags starting with "/smth". Replace those with
|
||||
# "-smth" equivalents.
|
||||
if(MSVC)
|
||||
string(REGEX REPLACE "^/" "-" global_flags "${global_flags}")
|
||||
string(REPLACE ";/" ";-" global_flags "${global_flags}")
|
||||
|
||||
if (MSVC)
|
||||
translate_msvc_cflags(global_flags "${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)
|
||||
|
@ -1,12 +1,10 @@
|
||||
include(LLVMParseArguments)
|
||||
|
||||
# Link a shared library with COMPILER_RT_TEST_COMPILER.
|
||||
# clang_link_shared(<output.so>
|
||||
# OBJECTS <list of input objects>
|
||||
# LINKFLAGS <list of link flags>
|
||||
# DEPS <list of dependencies>)
|
||||
macro(clang_link_shared so_file)
|
||||
parse_arguments(SOURCE "OBJECTS;LINKFLAGS;DEPS" "" ${ARGN})
|
||||
cmake_parse_arguments(SOURCE "" "" "OBJECTS;LINKFLAGS;DEPS" ${ARGN})
|
||||
if(NOT COMPILER_RT_STANDALONE_BUILD)
|
||||
list(APPEND SOURCE_DEPS clang)
|
||||
endif()
|
||||
|
@ -49,3 +49,11 @@ macro(append_no_rtti_flag list)
|
||||
append_list_if(COMPILER_RT_HAS_FNO_RTTI_FLAG -fno-rtti ${list})
|
||||
append_list_if(COMPILER_RT_HAS_GR_FLAG /GR- ${list})
|
||||
endmacro()
|
||||
|
||||
macro(append_have_file_definition filename varname list)
|
||||
check_include_file("${filename}" "${varname}")
|
||||
if (NOT ${varname})
|
||||
set("${varname}" 0)
|
||||
endif()
|
||||
list(APPEND ${list} "${varname}=${${varname}}")
|
||||
endmacro()
|
||||
|
@ -1,5 +1,3 @@
|
||||
include(LLVMParseArguments)
|
||||
|
||||
set(SANITIZER_GEN_DYNAMIC_LIST
|
||||
${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common/scripts/gen_dynamic_list.py)
|
||||
|
||||
@ -13,9 +11,13 @@ set(SANITIZER_LINT_SCRIPT
|
||||
# add_sanitizer_rt_symbols(<name> <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} $<TARGET_FILE:${name}> ${ARGN}
|
||||
${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}
|
||||
@ -44,6 +46,29 @@ macro(add_sanitizer_rt_symbols name)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(add_sanitizer_rt_version_list name)
|
||||
set(vers ${CMAKE_CURRENT_BINARY_DIR}/${name}.vers)
|
||||
cmake_parse_arguments(ARG "" "" "LIBS;EXTRA" ${ARGN})
|
||||
set(args)
|
||||
foreach(arg ${ARG_EXTRA})
|
||||
list(APPEND args "--extra" ${arg})
|
||||
endforeach()
|
||||
foreach(arg ${ARG_LIBS})
|
||||
list(APPEND args "$<TARGET_FILE:${arg}>")
|
||||
endforeach()
|
||||
add_custom_command(OUTPUT ${vers}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${SANITIZER_GEN_DYNAMIC_LIST} --version-list ${args}
|
||||
> ${vers}
|
||||
DEPENDS ${SANITIZER_GEN_DYNAMIC_LIST} ${ARG_EXTRA} ${ARG_LIBS}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Generating version list for ${name}"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(${name}-version-list ALL
|
||||
DEPENDS ${vers})
|
||||
endmacro()
|
||||
|
||||
# Add target to check code style for sanitizer runtimes.
|
||||
if(UNIX)
|
||||
add_custom_target(SanitizerLintCheck
|
||||
|
@ -1,8 +1,16 @@
|
||||
include(CMakePushCheckState)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckSymbolExists)
|
||||
include(TestBigEndian)
|
||||
|
||||
function(check_linker_flag flag out_var)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}")
|
||||
check_cxx_compiler_flag("" ${out_var})
|
||||
cmake_pop_check_state()
|
||||
endfunction()
|
||||
|
||||
# CodeGen options.
|
||||
check_cxx_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG)
|
||||
check_cxx_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG)
|
||||
@ -11,6 +19,7 @@ check_cxx_compiler_flag(-fno-exceptions COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG
|
||||
check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)
|
||||
check_cxx_compiler_flag(-funwind-tables COMPILER_RT_HAS_FUNWIND_TABLES_FLAG)
|
||||
check_cxx_compiler_flag(-fno-stack-protector COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG)
|
||||
check_cxx_compiler_flag(-fno-sanitize=safe-stack COMPILER_RT_HAS_FNO_SANITIZE_SAFE_STACK_FLAG)
|
||||
check_cxx_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG)
|
||||
check_cxx_compiler_flag(-fno-rtti COMPILER_RT_HAS_FNO_RTTI_FLAG)
|
||||
check_cxx_compiler_flag(-ffreestanding COMPILER_RT_HAS_FFREESTANDING_FLAG)
|
||||
@ -54,10 +63,16 @@ check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL)
|
||||
# Libraries.
|
||||
check_library_exists(c printf "" 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)
|
||||
check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD)
|
||||
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)
|
||||
endif()
|
||||
|
||||
# Architectures.
|
||||
|
||||
# List of all architectures we can target.
|
||||
@ -70,22 +85,43 @@ set(COMPILER_RT_SUPPORTED_ARCH)
|
||||
set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc)
|
||||
file(WRITE ${SIMPLE_SOURCE} "#include <stdlib.h>\n#include <limits>\nint main() {}\n")
|
||||
|
||||
# test_target_arch(<arch> <target flags...>)
|
||||
# Sets the target flags for a given architecture and determines if this
|
||||
# architecture is supported by trying to build a simple file.
|
||||
macro(test_target_arch arch)
|
||||
function(check_compile_definition def argstring out_var)
|
||||
if("${def}" STREQUAL "")
|
||||
set(${out_var} TRUE PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${argstring}")
|
||||
check_symbol_exists(${def} "" ${out_var})
|
||||
cmake_pop_check_state()
|
||||
endfunction()
|
||||
|
||||
# test_target_arch(<arch> <def> <target flags...>)
|
||||
# Checks if architecture is supported: runs host compiler with provided
|
||||
# flags to verify that:
|
||||
# 1) <def> is defined (if non-empty)
|
||||
# 2) simple file can be successfully built.
|
||||
# If successful, saves target flags for this architecture.
|
||||
macro(test_target_arch arch def)
|
||||
set(TARGET_${arch}_CFLAGS ${ARGN})
|
||||
set(argstring "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
set(argstring "")
|
||||
foreach(arg ${ARGN})
|
||||
set(argstring "${argstring} ${arg}")
|
||||
endforeach()
|
||||
try_compile(CAN_TARGET_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_SOURCE}
|
||||
COMPILE_DEFINITIONS "${TARGET_${arch}_CFLAGS}"
|
||||
OUTPUT_VARIABLE TARGET_${arch}_OUTPUT
|
||||
CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${argstring}")
|
||||
check_compile_definition("${def}" "${argstring}" HAS_${arch}_DEF)
|
||||
if(NOT HAS_${arch}_DEF)
|
||||
set(CAN_TARGET_${arch} FALSE)
|
||||
else()
|
||||
set(argstring "${CMAKE_EXE_LINKER_FLAGS} ${argstring}")
|
||||
try_compile(CAN_TARGET_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_SOURCE}
|
||||
COMPILE_DEFINITIONS "${TARGET_${arch}_CFLAGS}"
|
||||
OUTPUT_VARIABLE TARGET_${arch}_OUTPUT
|
||||
CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${argstring}")
|
||||
endif()
|
||||
if(${CAN_TARGET_${arch}})
|
||||
list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch})
|
||||
elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "${arch}")
|
||||
elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "${arch}" AND
|
||||
COMPILER_RT_HAS_EXPLICIT_TEST_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()
|
||||
@ -139,33 +175,46 @@ if(ANDROID)
|
||||
else()
|
||||
if("${LLVM_NATIVE_ARCH}" STREQUAL "X86")
|
||||
if(NOT MSVC)
|
||||
test_target_arch(x86_64 "-m64")
|
||||
test_target_arch(i386 "-m32")
|
||||
test_target_arch(x86_64 "" "-m64")
|
||||
# FIXME: We build runtimes for both i686 and i386, as "clang -m32" may
|
||||
# target different variant than "$CMAKE_C_COMPILER -m32". This part should
|
||||
# be gone after we resolve PR14109.
|
||||
test_target_arch(i686 __i686__ "-m32")
|
||||
test_target_arch(i386 __i386__ "-m32")
|
||||
else()
|
||||
test_target_arch(i386 "")
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
test_target_arch(i386 "" "")
|
||||
else()
|
||||
test_target_arch(x86_64 "" "")
|
||||
endif()
|
||||
endif()
|
||||
elseif("${LLVM_NATIVE_ARCH}" STREQUAL "PowerPC")
|
||||
TEST_BIG_ENDIAN(HOST_IS_BIG_ENDIAN)
|
||||
if(HOST_IS_BIG_ENDIAN)
|
||||
test_target_arch(powerpc64 "-m64")
|
||||
test_target_arch(powerpc64 "" "-m64")
|
||||
else()
|
||||
test_target_arch(powerpc64le "-m64")
|
||||
test_target_arch(powerpc64le "" "-m64")
|
||||
endif()
|
||||
elseif("${LLVM_NATIVE_ARCH}" STREQUAL "Mips")
|
||||
# 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 "-m32")
|
||||
test_target_arch(mips64el "-m64")
|
||||
test_target_arch(mipsel "" "-mips32r2" "--target=mipsel-linux-gnu")
|
||||
test_target_arch(mips64el "" "-mips64r2" "-mabi=n64")
|
||||
else()
|
||||
test_target_arch(mips "-m32")
|
||||
test_target_arch(mips64 "-m64")
|
||||
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")
|
||||
test_target_arch(arm "" "-march=armv7-a")
|
||||
elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "aarch32")
|
||||
test_target_arch(aarch32 "-march=armv8-a")
|
||||
test_target_arch(aarch32 "" "-march=armv8-a")
|
||||
elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "aarch64")
|
||||
test_target_arch(aarch64 "-march=armv8-a")
|
||||
test_target_arch(aarch64 "" "-march=armv8-a")
|
||||
endif()
|
||||
set(COMPILER_RT_OS_SUFFIX "")
|
||||
endif()
|
||||
@ -184,6 +233,7 @@ function(filter_available_targets out_var)
|
||||
set(${out_var} ${archs} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Returns a list of architecture specific target cflags in @out_var list.
|
||||
function(get_target_flags_for_arch arch out_var)
|
||||
list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX)
|
||||
if(ARCH_INDEX EQUAL -1)
|
||||
@ -196,19 +246,23 @@ 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)
|
||||
# LSan 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(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)
|
||||
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)
|
||||
|
||||
if(ANDROID)
|
||||
set(OS_NAME "Android")
|
||||
@ -218,13 +272,21 @@ endif()
|
||||
|
||||
if (SANITIZER_COMMON_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
|
||||
(OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD" OR
|
||||
(OS_NAME MATCHES "Windows" AND MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4)))
|
||||
(OS_NAME MATCHES "Windows" AND MSVC)))
|
||||
set(COMPILER_RT_HAS_SANITIZER_COMMON TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_SANITIZER_COMMON FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND ASAN_SUPPORTED_ARCH)
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND
|
||||
(NOT OS_NAME MATCHES "Windows" OR CMAKE_SIZEOF_VOID_P EQUAL 4))
|
||||
set(COMPILER_RT_HAS_INTERCEPTION TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_INTERCEPTION FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND ASAN_SUPPORTED_ARCH AND
|
||||
(NOT OS_NAME MATCHES "Windows" OR CMAKE_SIZEOF_VOID_P EQUAL 4))
|
||||
set(COMPILER_RT_HAS_ASAN TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_ASAN FALSE)
|
||||
@ -246,19 +308,12 @@ else()
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND LSAN_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD")
|
||||
OS_NAME MATCHES "Linux|FreeBSD")
|
||||
set(COMPILER_RT_HAS_LSAN TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_LSAN FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND LSAN_COMMON_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android")
|
||||
set(COMPILER_RT_HAS_LSAN_COMMON TRUE)
|
||||
else()
|
||||
set(COMPILER_RT_HAS_LSAN_COMMON FALSE)
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND MSAN_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Linux")
|
||||
set(COMPILER_RT_HAS_MSAN TRUE)
|
||||
@ -281,9 +336,23 @@ else()
|
||||
endif()
|
||||
|
||||
if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD")
|
||||
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows")
|
||||
set(COMPILER_RT_HAS_UBSAN TRUE)
|
||||
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()
|
||||
|
@ -39,6 +39,23 @@ extern "C" {
|
||||
// Some of the entries in *data will be zero.
|
||||
uintptr_t __sanitizer_get_coverage_guards(uintptr_t **data);
|
||||
|
||||
// The coverage instrumentation may optionally provide imprecise counters.
|
||||
// Rather than exposing the counter values to the user we instead map
|
||||
// the counters to a bitset.
|
||||
// Every counter is associated with 8 bits in the bitset.
|
||||
// We define 8 value ranges: 1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+
|
||||
// The i-th bit is set to 1 if the counter value is in the i-th range.
|
||||
// This counter-based coverage implementation is *not* thread-safe.
|
||||
|
||||
// Returns the number of registered coverage counters.
|
||||
uintptr_t __sanitizer_get_number_of_counters();
|
||||
// Updates the counter 'bitset', clears the counters and returns the number of
|
||||
// new bits in 'bitset'.
|
||||
// If 'bitset' is nullptr, only clears the counters.
|
||||
// Otherwise 'bitset' should be at least
|
||||
// __sanitizer_get_number_of_counters bytes long and 8-aligned.
|
||||
uintptr_t
|
||||
__sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -91,6 +91,16 @@ 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);
|
||||
|
||||
/// 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);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
|
@ -41,14 +41,25 @@ extern "C" {
|
||||
void __lsan_register_root_region(const void *p, size_t size);
|
||||
void __lsan_unregister_root_region(const void *p, size_t size);
|
||||
|
||||
// Calling this function makes LSan enter the leak checking phase immediately.
|
||||
// Use this if normal end-of-process leak checking happens too late (e.g. if
|
||||
// you have intentional memory leaks in your shutdown code). Calling this
|
||||
// function overrides end-of-process leak checking; it must be called at
|
||||
// most once per process. This function will terminate the process if there
|
||||
// are memory leaks and the exit_code flag is non-zero.
|
||||
// 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.
|
||||
// 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.
|
||||
// By calling this function early during process shutdown, you can instruct
|
||||
// LSan to ignore shutdown-only leaks which happen later on.
|
||||
void __lsan_do_leak_check();
|
||||
|
||||
// Check for leaks now. Returns zero if no leaks have been found or if leak
|
||||
// detection is disabled, non-zero otherwise.
|
||||
// This function may be called repeatedly, e.g. to periodically check a
|
||||
// long-running process. It prints a leak report if appropriate, but does not
|
||||
// terminate the process. It does not affect the behavior of
|
||||
// __lsan_do_leak_check() or the end-of-process leak check, and is not
|
||||
// affected by them.
|
||||
int __lsan_do_recoverable_leak_check();
|
||||
|
||||
// The user may optionally provide this function to disallow leak checking
|
||||
// for the program it is linked into (if the return value is non-zero). This
|
||||
// function must be defined as returning a constant value; any behavior beyond
|
||||
|
@ -25,6 +25,11 @@ extern "C" {
|
||||
/* Get raw origin for an address. */
|
||||
uint32_t __msan_get_origin(const volatile void *a);
|
||||
|
||||
/* Test that this_id is a descendant of prev_id (or they are simply equal).
|
||||
* "descendant" here means they are part of the same chain, created with
|
||||
* __msan_chain_origin. */
|
||||
int __msan_origin_is_descendant_or_same(uint32_t this_id, uint32_t prev_id);
|
||||
|
||||
/* Returns non-zero if tracking origins. */
|
||||
int __msan_get_track_origins();
|
||||
|
||||
|
@ -4,9 +4,14 @@
|
||||
include(AddCompilerRT)
|
||||
include(SanitizerUtils)
|
||||
|
||||
if(COMPILER_RT_HAS_SANITIZER_COMMON)
|
||||
if(COMPILER_RT_HAS_INTERCEPTION)
|
||||
add_subdirectory(interception)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_SANITIZER_COMMON)
|
||||
add_subdirectory(sanitizer_common)
|
||||
add_subdirectory(lsan)
|
||||
add_subdirectory(ubsan)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_ASAN)
|
||||
@ -19,10 +24,6 @@ if(COMPILER_RT_HAS_DFSAN)
|
||||
add_subdirectory(dfsan)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_LSAN OR COMPILER_RT_HAS_LSAN_COMMON)
|
||||
add_subdirectory(lsan)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_MSAN)
|
||||
add_subdirectory(msan)
|
||||
endif()
|
||||
@ -36,7 +37,6 @@ if(COMPILER_RT_HAS_TSAN)
|
||||
add_subdirectory(tsan/dd)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_UBSAN)
|
||||
add_subdirectory(ubsan)
|
||||
if(COMPILER_RT_HAS_SAFESTACK)
|
||||
add_subdirectory(safestack)
|
||||
endif()
|
||||
|
||||
|
@ -37,9 +37,22 @@ append_no_rtti_flag(ASAN_CFLAGS)
|
||||
set(ASAN_COMMON_DEFINITIONS
|
||||
ASAN_HAS_EXCEPTIONS=1)
|
||||
|
||||
set(ASAN_DYNAMIC_LINK_FLAGS)
|
||||
|
||||
if(ANDROID)
|
||||
list(APPEND ASAN_COMMON_DEFINITIONS
|
||||
ASAN_LOW_MEMORY=1)
|
||||
# On Android, -z global does not do what it is documented to do.
|
||||
# On Android, -z global moves the library ahead in the lookup order,
|
||||
# placing it right after the LD_PRELOADs. This is used to compensate for the fact
|
||||
# that Android linker does not look at the dependencies of the main executable
|
||||
# that aren't dependencies of the current DSO when resolving symbols from said DSO.
|
||||
# As a net result, this allows running ASan executables without LD_PRELOAD-ing the
|
||||
# ASan runtime library.
|
||||
# The above is applicable to L MR1 or newer.
|
||||
if (COMPILER_RT_HAS_Z_GLOBAL)
|
||||
list(APPEND ASAN_DYNAMIC_LINK_FLAGS -Wl,-z,global)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ASAN_DYNAMIC_DEFINITIONS
|
||||
@ -53,6 +66,7 @@ append_list_if(MSVC /DEBUG ASAN_DYNAMIC_CFLAGS)
|
||||
|
||||
append_list_if(COMPILER_RT_HAS_LIBC c ASAN_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBRT rt ASAN_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBM m ASAN_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread ASAN_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBSTDCXX stdc++ ASAN_DYNAMIC_LIBS)
|
||||
@ -61,41 +75,50 @@ append_list_if(ANDROID log ASAN_DYNAMIC_LIBS)
|
||||
|
||||
# Compile ASan sources into an object library.
|
||||
if(APPLE)
|
||||
foreach(os ${SANITIZER_COMMON_SUPPORTED_DARWIN_OS})
|
||||
add_compiler_rt_darwin_object_library(RTAsan ${os}
|
||||
ARCH ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
endforeach()
|
||||
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()
|
||||
foreach(arch ${ASAN_SUPPORTED_ARCH})
|
||||
add_compiler_rt_object_library(RTAsan ${arch}
|
||||
SOURCES ${ASAN_SOURCES} CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_library(RTAsan_cxx ${arch}
|
||||
SOURCES ${ASAN_CXX_SOURCES} CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_library(RTAsan_preinit ${arch}
|
||||
SOURCES ${ASAN_PREINIT_SOURCES} CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_library(RTAsan_dynamic ${arch}
|
||||
SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES}
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
endforeach()
|
||||
add_compiler_rt_object_libraries(RTAsan
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_SOURCES} CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_libraries(RTAsan_cxx
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${ASAN_CXX_SOURCES} CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_libraries(RTAsan_preinit
|
||||
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
|
||||
ARCHS ${ASAN_SUPPORTED_ARCH}
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cc
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
endif()
|
||||
|
||||
# Build ASan runtimes shipped with Clang.
|
||||
add_custom_target(asan)
|
||||
if(APPLE)
|
||||
foreach (os ${SANITIZER_COMMON_SUPPORTED_DARWIN_OS})
|
||||
foreach (os ${SANITIZER_COMMON_SUPPORTED_OS})
|
||||
add_compiler_rt_darwin_dynamic_runtime(clang_rt.asan_${os}_dynamic ${os}
|
||||
ARCH ${ASAN_SUPPORTED_ARCH}
|
||||
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)
|
||||
@ -106,12 +129,9 @@ else()
|
||||
set(ASAN_COMMON_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
|
||||
if(NOT WIN32)
|
||||
# We can't build Leak Sanitizer on Windows yet.
|
||||
list(APPEND ASAN_COMMON_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>)
|
||||
endif()
|
||||
$<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}>
|
||||
@ -123,6 +143,7 @@ else()
|
||||
|
||||
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})
|
||||
@ -133,6 +154,20 @@ else()
|
||||
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}
|
||||
EXTRA asan.syms.extra)
|
||||
set(VERSION_SCRIPT_FLAG
|
||||
-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers)
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/dummy.cc
|
||||
PROPERTIES
|
||||
OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers)
|
||||
else()
|
||||
set(VERSION_SCRIPT_FLAG)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(SHARED_ASAN_NAME clang_rt.asan_dynamic-${arch}${COMPILER_RT_OS_SUFFIX})
|
||||
else()
|
||||
@ -141,13 +176,21 @@ else()
|
||||
add_compiler_rt_runtime(clang_rt.asan-dynamic-${arch} ${arch} SHARED
|
||||
OUTPUT_NAME ${SHARED_ASAN_NAME}
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan_dynamic.${arch}>
|
||||
# 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}
|
||||
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})
|
||||
|
||||
if (UNIX AND NOT ${arch} STREQUAL "i386" AND NOT ${arch} STREQUAL "i686")
|
||||
if (UNIX AND NOT ${arch} MATCHES "i386|i686")
|
||||
add_sanitizer_rt_symbols(clang_rt.asan_cxx-${arch})
|
||||
add_dependencies(asan clang_rt.asan_cxx-${arch}-symbols)
|
||||
add_sanitizer_rt_symbols(clang_rt.asan-${arch} asan.syms.extra)
|
||||
|
@ -223,7 +223,7 @@ void AllocatorOptions::CopyTo(Flags *f, CommonFlags *cf) {
|
||||
|
||||
struct Allocator {
|
||||
static const uptr kMaxAllowedMallocSize =
|
||||
FIRST_32_SECOND_64(3UL << 30, 64UL << 30);
|
||||
FIRST_32_SECOND_64(3UL << 30, 1UL << 40);
|
||||
static const uptr kMaxThreadLocalQuarantine =
|
||||
FIRST_32_SECOND_64(1 << 18, 1 << 20);
|
||||
|
||||
@ -354,7 +354,7 @@ struct Allocator {
|
||||
}
|
||||
CHECK(IsAligned(needed_size, min_alignment));
|
||||
if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) {
|
||||
Report("WARNING: AddressSanitizer failed to allocate %p bytes\n",
|
||||
Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n",
|
||||
(void*)size);
|
||||
return allocator.ReturnNullOrDie();
|
||||
}
|
||||
@ -437,11 +437,10 @@ struct Allocator {
|
||||
thread_stats.mallocs++;
|
||||
thread_stats.malloced += size;
|
||||
thread_stats.malloced_redzones += needed_size - size;
|
||||
uptr class_id =
|
||||
Min(kNumberOfSizeClasses, SizeClassMap::ClassID(needed_size));
|
||||
thread_stats.malloced_by_size[class_id]++;
|
||||
if (needed_size > SizeClassMap::kMaxSize)
|
||||
thread_stats.malloc_large++;
|
||||
else
|
||||
thread_stats.malloced_by_size[SizeClassMap::ClassID(needed_size)]++;
|
||||
|
||||
void *res = reinterpret_cast<void *>(user_beg);
|
||||
if (can_fill && fl.max_malloc_fill_size) {
|
||||
|
@ -29,7 +29,6 @@ enum AllocType {
|
||||
FROM_NEW_BR = 3 // Memory block came from operator new [ ]
|
||||
};
|
||||
|
||||
static const uptr kNumberOfSizeClasses = 255;
|
||||
struct AsanChunk;
|
||||
|
||||
struct AllocatorOptions {
|
||||
@ -137,6 +136,7 @@ typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 16,
|
||||
AsanMapUnmapCallback> PrimaryAllocator;
|
||||
#endif // SANITIZER_CAN_USE_ALLOCATOR64
|
||||
|
||||
static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
|
||||
typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
|
||||
typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
|
||||
typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
|
||||
|
@ -22,6 +22,9 @@ static const u64 kMagic2 = (kMagic1 << 8) | kMagic1;
|
||||
static const u64 kMagic4 = (kMagic2 << 16) | kMagic2;
|
||||
static const u64 kMagic8 = (kMagic4 << 32) | kMagic4;
|
||||
|
||||
static const u64 kAllocaRedzoneSize = 32UL;
|
||||
static const u64 kAllocaRedzoneMask = 31UL;
|
||||
|
||||
// For small size classes inline PoisonShadow for better performance.
|
||||
ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) {
|
||||
CHECK_EQ(SHADOW_SCALE, 3); // This code expects SHADOW_SCALE=3.
|
||||
@ -253,4 +256,24 @@ void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
|
||||
if (end) *end = reinterpret_cast<void*>(frame_end);
|
||||
return reinterpret_cast<void*>(frame->real_stack);
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_alloca_poison(uptr addr, uptr size) {
|
||||
uptr LeftRedzoneAddr = addr - kAllocaRedzoneSize;
|
||||
uptr PartialRzAddr = addr + size;
|
||||
uptr RightRzAddr = (PartialRzAddr + kAllocaRedzoneMask) & ~kAllocaRedzoneMask;
|
||||
uptr PartialRzAligned = PartialRzAddr & ~(SHADOW_GRANULARITY - 1);
|
||||
FastPoisonShadow(LeftRedzoneAddr, kAllocaRedzoneSize, kAsanAllocaLeftMagic);
|
||||
FastPoisonShadowPartialRightRedzone(
|
||||
PartialRzAligned, PartialRzAddr % SHADOW_GRANULARITY,
|
||||
RightRzAddr - PartialRzAligned, kAsanAllocaRightMagic);
|
||||
FastPoisonShadow(RightRzAddr, kAllocaRedzoneSize, kAsanAllocaRightMagic);
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_allocas_unpoison(uptr top, uptr bottom) {
|
||||
if ((!top) || (top > bottom)) return;
|
||||
REAL(memset)(reinterpret_cast<void*>(MemToShadow(top)), 0,
|
||||
(bottom - top) / SHADOW_GRANULARITY);
|
||||
}
|
||||
} // extern "C"
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_flags.h"
|
||||
#include "sanitizer_common/sanitizer_flag_parser.h"
|
||||
#include "ubsan/ubsan_flags.h"
|
||||
#include "ubsan/ubsan_platform.h"
|
||||
|
||||
namespace __asan {
|
||||
|
||||
@ -72,8 +74,8 @@ void InitializeFlags() {
|
||||
RegisterAsanFlags(&asan_parser, f);
|
||||
RegisterCommonFlags(&asan_parser);
|
||||
|
||||
// Set the default values and prepare for parsing LSan flags (which can also
|
||||
// overwrite common flags).
|
||||
// Set the default values and prepare for parsing LSan and UBSan flags
|
||||
// (which can also overwrite common flags).
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
__lsan::Flags *lf = __lsan::flags();
|
||||
lf->SetDefaults();
|
||||
@ -83,6 +85,15 @@ void InitializeFlags() {
|
||||
RegisterCommonFlags(&lsan_parser);
|
||||
#endif
|
||||
|
||||
#if CAN_SANITIZE_UB
|
||||
__ubsan::Flags *uf = __ubsan::flags();
|
||||
uf->SetDefaults();
|
||||
|
||||
FlagParser ubsan_parser;
|
||||
__ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
|
||||
RegisterCommonFlags(&ubsan_parser);
|
||||
#endif
|
||||
|
||||
// Override from ASan compile definition.
|
||||
const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition();
|
||||
asan_parser.ParseString(asan_compile_def);
|
||||
@ -90,12 +101,19 @@ void InitializeFlags() {
|
||||
// Override from user-specified string.
|
||||
const char *asan_default_options = MaybeCallAsanDefaultOptions();
|
||||
asan_parser.ParseString(asan_default_options);
|
||||
#if CAN_SANITIZE_UB
|
||||
const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
|
||||
ubsan_parser.ParseString(ubsan_default_options);
|
||||
#endif
|
||||
|
||||
// Override from command line.
|
||||
asan_parser.ParseString(GetEnv("ASAN_OPTIONS"));
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
lsan_parser.ParseString(GetEnv("LSAN_OPTIONS"));
|
||||
#endif
|
||||
#if CAN_SANITIZE_UB
|
||||
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.
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "asan_report.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_stats.h"
|
||||
#include "asan_suppressions.h"
|
||||
#include "asan_thread.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_mutex.h"
|
||||
@ -73,7 +74,7 @@ ALWAYS_INLINE void PoisonRedZones(const Global &g) {
|
||||
|
||||
const uptr kMinimalDistanceFromAnotherGlobal = 64;
|
||||
|
||||
bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {
|
||||
static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {
|
||||
if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
|
||||
if (addr >= g.beg + g.size_with_redzone) return false;
|
||||
return true;
|
||||
@ -90,46 +91,8 @@ static void ReportGlobal(const Global &g, const char *prefix) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool DescribeOrGetInfoIfGlobal(uptr addr, uptr size, bool print,
|
||||
Global *output_global) {
|
||||
if (!flags()->report_globals) return false;
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
bool res = false;
|
||||
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
|
||||
const Global &g = *l->g;
|
||||
if (print) {
|
||||
if (flags()->report_globals >= 2)
|
||||
ReportGlobal(g, "Search");
|
||||
res |= DescribeAddressRelativeToGlobal(addr, size, g);
|
||||
} else {
|
||||
if (IsAddressNearGlobal(addr, g)) {
|
||||
CHECK(output_global);
|
||||
*output_global = g;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DescribeAddressIfGlobal(uptr addr, uptr size) {
|
||||
return DescribeOrGetInfoIfGlobal(addr, size, /* print */ true,
|
||||
/* output_global */ nullptr);
|
||||
}
|
||||
|
||||
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {
|
||||
Global g = {};
|
||||
if (DescribeOrGetInfoIfGlobal(addr, /* size */ 1, /* print */ false, &g)) {
|
||||
internal_strncpy(descr->name, g.name, descr->name_size);
|
||||
descr->region_address = g.beg;
|
||||
descr->region_size = g.size;
|
||||
descr->region_kind = "global";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 FindRegistrationSite(const Global *g) {
|
||||
static u32 FindRegistrationSite(const Global *g) {
|
||||
mu_for_globals.CheckLocked();
|
||||
CHECK(global_registration_site_vector);
|
||||
for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) {
|
||||
GlobalRegistrationSite &grs = (*global_registration_site_vector)[i];
|
||||
@ -139,6 +102,38 @@ u32 FindRegistrationSite(const Global *g) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites,
|
||||
int max_globals) {
|
||||
if (!flags()->report_globals) return 0;
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
int res = 0;
|
||||
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
|
||||
const Global &g = *l->g;
|
||||
if (flags()->report_globals >= 2)
|
||||
ReportGlobal(g, "Search");
|
||||
if (IsAddressNearGlobal(addr, g)) {
|
||||
globals[res] = g;
|
||||
if (reg_sites)
|
||||
reg_sites[res] = FindRegistrationSite(&g);
|
||||
res++;
|
||||
if (res == max_globals) break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {
|
||||
Global g = {};
|
||||
if (GetGlobalsForAddress(addr, &g, nullptr, 1)) {
|
||||
internal_strncpy(descr->name, g.name, descr->name_size);
|
||||
descr->region_address = g.beg;
|
||||
descr->region_size = g.size;
|
||||
descr->region_kind = "global";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Register a global variable.
|
||||
// This function may be called more than once for every global
|
||||
// so we store the globals in a map.
|
||||
@ -158,7 +153,8 @@ static void RegisterGlobal(const Global *g) {
|
||||
// the entire redzone of the second global may be within the first global.
|
||||
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
|
||||
if (g->beg == l->g->beg &&
|
||||
(flags()->detect_odr_violation >= 2 || g->size != l->g->size))
|
||||
(flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
|
||||
!IsODRViolationSuppressed(g->name))
|
||||
ReportODRViolation(g, FindRegistrationSite(g),
|
||||
l->g, FindRegistrationSite(l->g));
|
||||
}
|
||||
@ -210,20 +206,6 @@ void StopInitOrderChecking() {
|
||||
}
|
||||
}
|
||||
|
||||
#if SANITIZER_WINDOWS // Should only be called on Windows.
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void UnregisterGlobalsInRange(void *beg, void *end) {
|
||||
if (!flags()->report_globals)
|
||||
return;
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
|
||||
void *address = (void *)l->g->beg;
|
||||
if (beg <= address && address < end)
|
||||
UnregisterGlobal(l->g);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
// ---------------------- Interface ---------------- {{{1
|
||||
@ -232,7 +214,7 @@ using namespace __asan; // NOLINT
|
||||
// Register an array of globals.
|
||||
void __asan_register_globals(__asan_global *globals, uptr n) {
|
||||
if (!flags()->report_globals) return;
|
||||
GET_STACK_TRACE_FATAL_HERE;
|
||||
GET_STACK_TRACE_MALLOC;
|
||||
u32 stack_id = StackDepotPut(stack);
|
||||
BlockingMutexLock lock(&mu_for_globals);
|
||||
if (!global_registration_site_vector)
|
||||
|
@ -23,6 +23,10 @@
|
||||
#include "asan_suppressions.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
|
||||
#if SANITIZER_POSIX
|
||||
#include "sanitizer_common/sanitizer_posix.h"
|
||||
#endif
|
||||
|
||||
namespace __asan {
|
||||
|
||||
// Return true if we can quickly decide that the region is unpoisoned.
|
||||
@ -65,7 +69,7 @@ struct AsanInterceptorContext {
|
||||
} \
|
||||
if (!suppressed) { \
|
||||
GET_CURRENT_PC_BP_SP; \
|
||||
__asan_report_error(pc, bp, sp, __bad, isWrite, __size); \
|
||||
__asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
@ -75,6 +79,13 @@ struct AsanInterceptorContext {
|
||||
#define ASAN_WRITE_RANGE(ctx, offset, size) \
|
||||
ACCESS_MEMORY_RANGE(ctx, offset, size, true)
|
||||
|
||||
#define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
|
||||
ASAN_READ_RANGE((ctx), (s), \
|
||||
common_flags()->strict_string_checks ? (len) + 1 : (n))
|
||||
|
||||
#define ASAN_READ_STRING(ctx, s, n) \
|
||||
ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n))
|
||||
|
||||
// Behavior of functions like "memcpy" or "strcpy" is undefined
|
||||
// if memory intervals overlap. We report error in this case.
|
||||
// Macro is used to avoid creation of new frames.
|
||||
@ -120,17 +131,6 @@ using namespace __asan; // NOLINT
|
||||
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
|
||||
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
||||
|
||||
#if !SANITIZER_MAC
|
||||
#define ASAN_INTERCEPT_FUNC(name) \
|
||||
do { \
|
||||
if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
|
||||
VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
|
||||
} while (0)
|
||||
#else
|
||||
// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
|
||||
#define ASAN_INTERCEPT_FUNC(name)
|
||||
#endif // SANITIZER_MAC
|
||||
|
||||
#define ASAN_INTERCEPTOR_ENTER(ctx, func) \
|
||||
AsanInterceptorContext _ctx = {#func}; \
|
||||
ctx = (void *)&_ctx; \
|
||||
@ -171,11 +171,24 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
||||
do { \
|
||||
} 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
|
||||
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
|
||||
if (flags()->strict_init_order) { \
|
||||
StopInitOrderChecking(); \
|
||||
}
|
||||
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
|
||||
#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
|
||||
CoverageUpdateMapping()
|
||||
#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() CoverageUpdateMapping()
|
||||
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
|
||||
#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
|
||||
if (AsanThread *t = GetCurrentThread()) { \
|
||||
*begin = t->tls_begin(); \
|
||||
*end = t->tls_end(); \
|
||||
} else { \
|
||||
*begin = *end = 0; \
|
||||
}
|
||||
#include "sanitizer_common/sanitizer_common_interceptors.inc"
|
||||
|
||||
// Syscall interceptors don't have contexts, we don't support suppressions
|
||||
@ -200,12 +213,6 @@ struct ThreadStartParam {
|
||||
};
|
||||
|
||||
static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
|
||||
#if SANITIZER_WINDOWS
|
||||
// FIXME: this is a bandaid fix for PR22025.
|
||||
AsanThread *t = (AsanThread*)arg;
|
||||
SetCurrentThread(t);
|
||||
return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr);
|
||||
#else
|
||||
ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
|
||||
AsanThread *t = nullptr;
|
||||
while ((t = reinterpret_cast<AsanThread *>(
|
||||
@ -213,7 +220,6 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
|
||||
internal_sched_yield();
|
||||
SetCurrentThread(t);
|
||||
return t->ThreadStart(GetTid(), ¶m->is_registered);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ASAN_INTERCEPT_PTHREAD_CREATE
|
||||
@ -302,7 +308,7 @@ static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
|
||||
ssize += stack - bottom;
|
||||
ssize = RoundUpTo(ssize, PageSize);
|
||||
static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
|
||||
if (ssize && ssize <= kMaxSaneContextStackSize) {
|
||||
if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) {
|
||||
PoisonShadow(bottom, ssize, 0);
|
||||
}
|
||||
}
|
||||
@ -357,30 +363,6 @@ INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SANITIZER_WINDOWS
|
||||
INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
|
||||
CHECK(REAL(RaiseException));
|
||||
__asan_handle_no_return();
|
||||
REAL(RaiseException)(a, b, c, d);
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
|
||||
CHECK(REAL(_except_handler3));
|
||||
__asan_handle_no_return();
|
||||
return REAL(_except_handler3)(a, b, c, d);
|
||||
}
|
||||
|
||||
#if ASAN_DYNAMIC
|
||||
// This handler is named differently in -MT and -MD CRTs.
|
||||
#define _except_handler4 _except_handler4_common
|
||||
#endif
|
||||
INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
|
||||
CHECK(REAL(_except_handler4));
|
||||
__asan_handle_no_return();
|
||||
return REAL(_except_handler4)(a, b, c, d);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int CharCmp(unsigned char c1, unsigned char c2) {
|
||||
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
|
||||
}
|
||||
@ -511,8 +493,9 @@ INTERCEPTOR(char*, strchr, const char *str, int c) {
|
||||
ENSURE_ASAN_INITED();
|
||||
char *result = REAL(strchr)(str, c);
|
||||
if (flags()->replace_str) {
|
||||
uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1;
|
||||
ASAN_READ_RANGE(ctx, str, bytes_read);
|
||||
uptr len = REAL(strlen)(str);
|
||||
uptr bytes_read = (result ? result - str : len) + 1;
|
||||
ASAN_READ_STRING_OF_LEN(ctx, str, len, bytes_read);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -541,7 +524,7 @@ INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT
|
||||
uptr from_length = REAL(strlen)(from);
|
||||
ASAN_READ_RANGE(ctx, from, from_length + 1);
|
||||
uptr to_length = REAL(strlen)(to);
|
||||
ASAN_READ_RANGE(ctx, to, to_length);
|
||||
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
|
||||
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
|
||||
// If the copying actually happens, the |from| string should not overlap
|
||||
// with the resulting string starting at |to|, which has a length of
|
||||
@ -563,7 +546,7 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
|
||||
uptr copy_length = Min(size, from_length + 1);
|
||||
ASAN_READ_RANGE(ctx, from, copy_length);
|
||||
uptr to_length = REAL(strlen)(to);
|
||||
ASAN_READ_RANGE(ctx, to, to_length);
|
||||
ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
|
||||
ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
|
||||
if (from_length > 0) {
|
||||
CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
|
||||
@ -665,23 +648,6 @@ INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) {
|
||||
}
|
||||
#endif // ASAN_INTERCEPT_STRNLEN
|
||||
|
||||
static inline bool IsValidStrtolBase(int base) {
|
||||
return (base == 0) || (2 <= base && base <= 36);
|
||||
}
|
||||
|
||||
static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
|
||||
CHECK(endptr);
|
||||
if (nptr == *endptr) {
|
||||
// No digits were found at strtol call, we need to find out the last
|
||||
// symbol accessed by strtoll on our own.
|
||||
// We get this symbol by skipping leading blanks and optional +/- sign.
|
||||
while (IsSpace(*nptr)) nptr++;
|
||||
if (*nptr == '+' || *nptr == '-') nptr++;
|
||||
*endptr = const_cast<char *>(nptr);
|
||||
}
|
||||
CHECK(*endptr >= nptr);
|
||||
}
|
||||
|
||||
INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
|
||||
char **endptr, int base) {
|
||||
void *ctx;
|
||||
@ -692,13 +658,7 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
|
||||
}
|
||||
char *real_endptr;
|
||||
long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT
|
||||
if (endptr != 0) {
|
||||
*endptr = real_endptr;
|
||||
}
|
||||
if (IsValidStrtolBase(base)) {
|
||||
FixRealStrtolEndptr(nptr, &real_endptr);
|
||||
ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
}
|
||||
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -719,7 +679,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
|
||||
// different from int). So, we just imitate this behavior.
|
||||
int result = REAL(strtol)(nptr, &real_endptr, 10);
|
||||
FixRealStrtolEndptr(nptr, &real_endptr);
|
||||
ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -736,7 +696,7 @@ INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
|
||||
char *real_endptr;
|
||||
long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT
|
||||
FixRealStrtolEndptr(nptr, &real_endptr);
|
||||
ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -751,16 +711,7 @@ INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT
|
||||
}
|
||||
char *real_endptr;
|
||||
long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT
|
||||
if (endptr != 0) {
|
||||
*endptr = real_endptr;
|
||||
}
|
||||
// If base has unsupported value, strtoll can exit with EINVAL
|
||||
// without reading any characters. So do additional checks only
|
||||
// if base is valid.
|
||||
if (IsValidStrtolBase(base)) {
|
||||
FixRealStrtolEndptr(nptr, &real_endptr);
|
||||
ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
}
|
||||
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -774,7 +725,7 @@ INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
|
||||
char *real_endptr;
|
||||
long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT
|
||||
FixRealStrtolEndptr(nptr, &real_endptr);
|
||||
ASAN_READ_RANGE(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
|
||||
return result;
|
||||
}
|
||||
#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
|
||||
@ -807,36 +758,6 @@ INTERCEPTOR(int, fork, void) {
|
||||
}
|
||||
#endif // ASAN_INTERCEPT_FORK
|
||||
|
||||
#if SANITIZER_WINDOWS
|
||||
INTERCEPTOR_WINAPI(DWORD, CreateThread,
|
||||
void* security, uptr stack_size,
|
||||
DWORD (__stdcall *start_routine)(void*), void* arg,
|
||||
DWORD thr_flags, void* tid) {
|
||||
// Strict init-order checking is thread-hostile.
|
||||
if (flags()->strict_init_order)
|
||||
StopInitOrderChecking();
|
||||
GET_STACK_TRACE_THREAD;
|
||||
// FIXME: The CreateThread interceptor is not the same as a pthread_create
|
||||
// one. This is a bandaid fix for PR22025.
|
||||
bool detached = false; // FIXME: how can we determine it on Windows?
|
||||
u32 current_tid = GetCurrentTidOrInvalid();
|
||||
AsanThread *t =
|
||||
AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
|
||||
return REAL(CreateThread)(security, stack_size,
|
||||
asan_thread_start, t, thr_flags, tid);
|
||||
}
|
||||
|
||||
namespace __asan {
|
||||
void InitializeWindowsInterceptors() {
|
||||
ASAN_INTERCEPT_FUNC(CreateThread);
|
||||
ASAN_INTERCEPT_FUNC(RaiseException);
|
||||
ASAN_INTERCEPT_FUNC(_except_handler3);
|
||||
ASAN_INTERCEPT_FUNC(_except_handler4);
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
#endif
|
||||
|
||||
// ---------------------- InitializeAsanInterceptors ---------------- {{{1
|
||||
namespace __asan {
|
||||
void InitializeAsanInterceptors() {
|
||||
@ -919,10 +840,7 @@ void InitializeAsanInterceptors() {
|
||||
ASAN_INTERCEPT_FUNC(fork);
|
||||
#endif
|
||||
|
||||
// Some Windows-specific interceptors.
|
||||
#if SANITIZER_WINDOWS
|
||||
InitializeWindowsInterceptors();
|
||||
#endif
|
||||
InitializePlatformInterceptors();
|
||||
|
||||
VReport(1, "AddressSanitizer: libc interceptors initialized\n");
|
||||
}
|
||||
|
@ -92,9 +92,21 @@ struct sigaction;
|
||||
DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
|
||||
struct sigaction *oldact)
|
||||
|
||||
#if !SANITIZER_MAC
|
||||
#define ASAN_INTERCEPT_FUNC(name) \
|
||||
do { \
|
||||
if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \
|
||||
VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
|
||||
} while (0)
|
||||
#else
|
||||
// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
|
||||
#define ASAN_INTERCEPT_FUNC(name)
|
||||
#endif // SANITIZER_MAC
|
||||
|
||||
namespace __asan {
|
||||
|
||||
void InitializeAsanInterceptors();
|
||||
void InitializePlatformInterceptors();
|
||||
|
||||
#define ENSURE_ASAN_INITED() do { \
|
||||
CHECK(!asan_init_is_running); \
|
||||
|
@ -128,7 +128,7 @@ extern "C" {
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_report_error(uptr pc, uptr bp, uptr sp,
|
||||
uptr addr, int is_write, uptr access_size);
|
||||
uptr addr, int is_write, uptr access_size, u32 exp);
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
int __asan_set_error_exit_code(int exit_code);
|
||||
@ -165,6 +165,21 @@ 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_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);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load8(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load16(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store1(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store2(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store4(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store8(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store16(uptr p, u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr p, uptr size,
|
||||
u32 exp);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr p, uptr size,
|
||||
u32 exp);
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void* __asan_memcpy(void *dst, const void *src, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
@ -180,6 +195,10 @@ extern "C" {
|
||||
void __asan_poison_intra_object_redzone(uptr p, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_unpoison_intra_object_redzone(uptr p, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_alloca_poison(uptr addr, uptr size);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __asan_allocas_unpoison(uptr top, uptr bottom);
|
||||
} // extern "C"
|
||||
|
||||
#endif // ASAN_INTERFACE_INTERNAL_H
|
||||
|
@ -62,21 +62,6 @@ namespace __asan {
|
||||
class AsanThread;
|
||||
using __sanitizer::StackTrace;
|
||||
|
||||
struct SignalContext {
|
||||
void *context;
|
||||
uptr addr;
|
||||
uptr pc;
|
||||
uptr sp;
|
||||
uptr bp;
|
||||
|
||||
SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) :
|
||||
context(context), addr(addr), pc(pc), sp(sp), bp(bp) {
|
||||
}
|
||||
|
||||
// Creates signal context in a platform-specific manner.
|
||||
static SignalContext Create(void *siginfo, void *context);
|
||||
};
|
||||
|
||||
void AsanInitFromRtl();
|
||||
|
||||
// asan_rtl.cc
|
||||
@ -90,7 +75,6 @@ void *AsanDoesNotSupportStaticLinkage();
|
||||
void AsanCheckDynamicRTPrereqs();
|
||||
void AsanCheckIncompatibleRT();
|
||||
|
||||
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
|
||||
void AsanOnSIGSEGV(int, void *siginfo, void *context);
|
||||
|
||||
void DisableReexec();
|
||||
@ -109,7 +93,7 @@ void AppendToErrorMessageBuffer(const char *buffer);
|
||||
|
||||
void *AsanDlSymNext(const char *sym);
|
||||
|
||||
void ReserveShadowMemoryRange(uptr beg, uptr end);
|
||||
void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name);
|
||||
|
||||
// Platform-specific options.
|
||||
#if SANITIZER_MAC
|
||||
|
@ -68,6 +68,8 @@ asan_rt_version_t __asan_rt_version;
|
||||
|
||||
namespace __asan {
|
||||
|
||||
void InitializePlatformInterceptors() {}
|
||||
|
||||
void DisableReexec() {
|
||||
// No need to re-exec on Linux.
|
||||
}
|
||||
@ -111,6 +113,9 @@ static void ReportIncompatibleRT() {
|
||||
}
|
||||
|
||||
void AsanCheckDynamicRTPrereqs() {
|
||||
if (!ASAN_DYNAMIC)
|
||||
return;
|
||||
|
||||
// Ensure that dynamic RT is the first DSO in the list
|
||||
const char *first_dso_name = 0;
|
||||
dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
|
||||
@ -152,78 +157,6 @@ void AsanCheckIncompatibleRT() {
|
||||
}
|
||||
#endif // SANITIZER_ANDROID
|
||||
|
||||
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
|
||||
#if defined(__arm__)
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.arm_pc;
|
||||
*bp = ucontext->uc_mcontext.arm_fp;
|
||||
*sp = ucontext->uc_mcontext.arm_sp;
|
||||
#elif defined(__aarch64__)
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.pc;
|
||||
*bp = ucontext->uc_mcontext.regs[29];
|
||||
*sp = ucontext->uc_mcontext.sp;
|
||||
#elif defined(__hppa__)
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.sc_iaoq[0];
|
||||
/* GCC uses %r3 whenever a frame pointer is needed. */
|
||||
*bp = ucontext->uc_mcontext.sc_gr[3];
|
||||
*sp = ucontext->uc_mcontext.sc_gr[30];
|
||||
#elif defined(__x86_64__)
|
||||
# if SANITIZER_FREEBSD
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.mc_rip;
|
||||
*bp = ucontext->uc_mcontext.mc_rbp;
|
||||
*sp = ucontext->uc_mcontext.mc_rsp;
|
||||
# else
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.gregs[REG_RIP];
|
||||
*bp = ucontext->uc_mcontext.gregs[REG_RBP];
|
||||
*sp = ucontext->uc_mcontext.gregs[REG_RSP];
|
||||
# endif
|
||||
#elif defined(__i386__)
|
||||
# if SANITIZER_FREEBSD
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.mc_eip;
|
||||
*bp = ucontext->uc_mcontext.mc_ebp;
|
||||
*sp = ucontext->uc_mcontext.mc_esp;
|
||||
# else
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.gregs[REG_EIP];
|
||||
*bp = ucontext->uc_mcontext.gregs[REG_EBP];
|
||||
*sp = ucontext->uc_mcontext.gregs[REG_ESP];
|
||||
# endif
|
||||
#elif defined(__powerpc__) || defined(__powerpc64__)
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.regs->nip;
|
||||
*sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
|
||||
// The powerpc{,64}-linux ABIs do not specify r31 as the frame
|
||||
// pointer, but GCC always uses r31 when we need a frame pointer.
|
||||
*bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
|
||||
#elif defined(__sparc__)
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
uptr *stk_ptr;
|
||||
# if defined (__arch64__)
|
||||
*pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
|
||||
*sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
|
||||
stk_ptr = (uptr *) (*sp + 2047);
|
||||
*bp = stk_ptr[15];
|
||||
# else
|
||||
*pc = ucontext->uc_mcontext.gregs[REG_PC];
|
||||
*sp = ucontext->uc_mcontext.gregs[REG_O6];
|
||||
stk_ptr = (uptr *) *sp;
|
||||
*bp = stk_ptr[15];
|
||||
# endif
|
||||
#elif defined(__mips__)
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
*pc = ucontext->uc_mcontext.gregs[31];
|
||||
*bp = ucontext->uc_mcontext.gregs[30];
|
||||
*sp = ucontext->uc_mcontext.gregs[29];
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
}
|
||||
|
||||
void AsanPlatformThreadInit() {
|
||||
// Nothing here for now.
|
||||
}
|
||||
|
@ -24,7 +24,14 @@
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_mac.h"
|
||||
|
||||
#include <crt_externs.h> // for _NSGetArgv
|
||||
#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 <mach-o/dyld.h>
|
||||
#include <mach-o/loader.h>
|
||||
@ -40,19 +47,7 @@
|
||||
|
||||
namespace __asan {
|
||||
|
||||
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
# if SANITIZER_WORDSIZE == 64
|
||||
*pc = ucontext->uc_mcontext->__ss.__rip;
|
||||
*bp = ucontext->uc_mcontext->__ss.__rbp;
|
||||
*sp = ucontext->uc_mcontext->__ss.__rsp;
|
||||
# else
|
||||
*pc = ucontext->uc_mcontext->__ss.__eip;
|
||||
*bp = ucontext->uc_mcontext->__ss.__ebp;
|
||||
*sp = ucontext->uc_mcontext->__ss.__esp;
|
||||
# endif // SANITIZER_WORDSIZE
|
||||
}
|
||||
|
||||
void InitializePlatformInterceptors() {}
|
||||
|
||||
bool PlatformHasDifferentMemcpyAndMemmove() {
|
||||
// On OS X 10.7 memcpy() and memmove() are both resolved
|
||||
@ -74,30 +69,27 @@ LowLevelAllocator allocator_for_env;
|
||||
// otherwise the corresponding "NAME=value" string is replaced with
|
||||
// |name_value|.
|
||||
void LeakyResetEnv(const char *name, const char *name_value) {
|
||||
char ***env_ptr = _NSGetEnviron();
|
||||
CHECK(env_ptr);
|
||||
char **environ = *env_ptr;
|
||||
CHECK(environ);
|
||||
char **env = GetEnviron();
|
||||
uptr name_len = internal_strlen(name);
|
||||
while (*environ != 0) {
|
||||
uptr len = internal_strlen(*environ);
|
||||
while (*env != 0) {
|
||||
uptr len = internal_strlen(*env);
|
||||
if (len > name_len) {
|
||||
const char *p = *environ;
|
||||
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.
|
||||
*environ = const_cast<char*>(name_value);
|
||||
*env = const_cast<char*>(name_value);
|
||||
} else {
|
||||
// Shift the subsequent pointers back.
|
||||
char **del = environ;
|
||||
char **del = env;
|
||||
do {
|
||||
del[0] = del[1];
|
||||
} while (*del++);
|
||||
}
|
||||
}
|
||||
}
|
||||
environ++;
|
||||
env++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,6 +99,23 @@ 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;
|
||||
|
||||
@ -122,8 +131,10 @@ void MaybeReexec() {
|
||||
uptr fname_len = internal_strlen(info.dli_fname);
|
||||
const char *dylib_name = StripModuleName(info.dli_fname);
|
||||
uptr dylib_name_len = internal_strlen(dylib_name);
|
||||
if (!dyld_insert_libraries ||
|
||||
!REAL(strstr)(dyld_insert_libraries, 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];
|
||||
@ -160,6 +171,9 @@ void MaybeReexec() {
|
||||
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.
|
||||
|
@ -98,9 +98,12 @@
|
||||
|
||||
static const u64 kDefaultShadowScale = 3;
|
||||
static const u64 kDefaultShadowOffset32 = 1ULL << 29; // 0x20000000
|
||||
static const u64 kIosShadowOffset32 = 1ULL << 30; // 0x40000000
|
||||
static const u64 kDefaultShadowOffset64 = 1ULL << 44;
|
||||
static const u64 kDefaultShort64bitShadowOffset = 0x7FFF8000; // < 2G.
|
||||
static const u64 kIosShadowOffset32 = 1ULL << 30; // 0x40000000
|
||||
static const u64 kIosShadowOffset64 = 0x130000000;
|
||||
static const u64 kIosSimShadowOffset32 = 1ULL << 30;
|
||||
static const u64 kIosSimShadowOffset64 = kDefaultShadowOffset64;
|
||||
static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
|
||||
static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;
|
||||
static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37;
|
||||
@ -118,10 +121,12 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
|
||||
# define SHADOW_OFFSET kMIPS32_ShadowOffset32
|
||||
# elif SANITIZER_FREEBSD
|
||||
# define SHADOW_OFFSET kFreeBSD_ShadowOffset32
|
||||
# elif SANITIZER_IOS
|
||||
# define SHADOW_OFFSET kIosShadowOffset32
|
||||
# elif SANITIZER_WINDOWS
|
||||
# define SHADOW_OFFSET kWindowsShadowOffset32
|
||||
# elif SANITIZER_IOSSIM
|
||||
# define SHADOW_OFFSET kIosSimShadowOffset32
|
||||
# elif SANITIZER_IOS
|
||||
# define SHADOW_OFFSET kIosShadowOffset32
|
||||
# else
|
||||
# define SHADOW_OFFSET kDefaultShadowOffset32
|
||||
# endif
|
||||
@ -136,6 +141,10 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
|
||||
# define SHADOW_OFFSET kDefaultShadowOffset64
|
||||
# elif defined(__mips64)
|
||||
# define SHADOW_OFFSET kMIPS64_ShadowOffset64
|
||||
# elif SANITIZER_IOSSIM
|
||||
# define SHADOW_OFFSET kIosSimShadowOffset64
|
||||
# elif SANITIZER_IOS
|
||||
# define SHADOW_OFFSET kIosShadowOffset64
|
||||
# else
|
||||
# define SHADOW_OFFSET kDefaultShort64bitShadowOffset
|
||||
# endif
|
||||
|
@ -112,7 +112,7 @@ void __asan_poison_memory_region(void const volatile *addr, uptr size) {
|
||||
if (!flags()->allow_user_poisoning || size == 0) return;
|
||||
uptr beg_addr = (uptr)addr;
|
||||
uptr end_addr = beg_addr + size;
|
||||
VPrintf(1, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,
|
||||
VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,
|
||||
(void *)end_addr);
|
||||
ShadowSegmentEndpoint beg(beg_addr);
|
||||
ShadowSegmentEndpoint end(end_addr);
|
||||
@ -152,7 +152,7 @@ void __asan_unpoison_memory_region(void const volatile *addr, uptr size) {
|
||||
if (!flags()->allow_user_poisoning || size == 0) return;
|
||||
uptr beg_addr = (uptr)addr;
|
||||
uptr end_addr = beg_addr + size;
|
||||
VPrintf(1, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,
|
||||
VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,
|
||||
(void *)end_addr);
|
||||
ShadowSegmentEndpoint beg(beg_addr);
|
||||
ShadowSegmentEndpoint end(end_addr);
|
||||
@ -218,7 +218,7 @@ uptr __asan_region_is_poisoned(uptr beg, uptr size) {
|
||||
__asan::AddressIsPoisoned(__p + __size - 1))) { \
|
||||
GET_CURRENT_PC_BP_SP; \
|
||||
uptr __bad = __asan_region_is_poisoned(__p, __size); \
|
||||
__asan_report_error(pc, bp, sp, __bad, isWrite, __size);\
|
||||
__asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\
|
||||
} \
|
||||
} while (false); \
|
||||
|
||||
|
@ -64,7 +64,7 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
|
||||
if (page_end != shadow_end) {
|
||||
REAL(memset)((void *)page_end, 0, shadow_end - page_end);
|
||||
}
|
||||
ReserveShadowMemoryRange(page_beg, page_end - 1);
|
||||
ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "asan_report.h"
|
||||
#include "asan_stack.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_posix.h"
|
||||
#include "sanitizer_common/sanitizer_procmaps.h"
|
||||
|
||||
#include <pthread.h>
|
||||
@ -32,13 +33,6 @@
|
||||
|
||||
namespace __asan {
|
||||
|
||||
SignalContext SignalContext::Create(void *siginfo, void *context) {
|
||||
uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
|
||||
uptr pc, sp, bp;
|
||||
GetPcSpBp(context, &pc, &sp, &bp);
|
||||
return SignalContext(context, addr, pc, sp, bp);
|
||||
}
|
||||
|
||||
void AsanOnSIGSEGV(int, void *siginfo, void *context) {
|
||||
ScopedDeadlySignal signal_scope(GetCurrentThread());
|
||||
int code = (int)((siginfo_t*)siginfo)->si_code;
|
||||
|
@ -281,9 +281,8 @@ static void PrintGlobalLocation(InternalScopedString *str,
|
||||
str->append(":%d", g.location->column_no);
|
||||
}
|
||||
|
||||
bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
|
||||
const __asan_global &g) {
|
||||
if (!IsAddressNearGlobal(addr, g)) return false;
|
||||
static void DescribeAddressRelativeToGlobal(uptr addr, uptr size,
|
||||
const __asan_global &g) {
|
||||
InternalScopedString str(4096);
|
||||
Decorator d;
|
||||
str.append("%s", d.Location());
|
||||
@ -306,6 +305,26 @@ bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
|
||||
str.append("%s", d.EndLocation());
|
||||
PrintGlobalNameIfASCII(&str, g);
|
||||
Printf("%s", str.data());
|
||||
}
|
||||
|
||||
static bool DescribeAddressIfGlobal(uptr addr, uptr size,
|
||||
const char *bug_type) {
|
||||
// Assume address is close to at most four globals.
|
||||
const int kMaxGlobalsInReport = 4;
|
||||
__asan_global globals[kMaxGlobalsInReport];
|
||||
u32 reg_sites[kMaxGlobalsInReport];
|
||||
int globals_num =
|
||||
GetGlobalsForAddress(addr, globals, reg_sites, ARRAY_SIZE(globals));
|
||||
if (globals_num == 0)
|
||||
return false;
|
||||
for (int i = 0; i < globals_num; i++) {
|
||||
DescribeAddressRelativeToGlobal(addr, size, globals[i]);
|
||||
if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") &&
|
||||
reg_sites[i]) {
|
||||
Printf(" registered at:\n");
|
||||
StackDepotGet(reg_sites[i]).Print();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -551,12 +570,12 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {
|
||||
DescribeThread(alloc_thread);
|
||||
}
|
||||
|
||||
void DescribeAddress(uptr addr, uptr access_size) {
|
||||
static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) {
|
||||
// Check if this is shadow or shadow gap.
|
||||
if (DescribeAddressIfShadow(addr))
|
||||
return;
|
||||
CHECK(AddrIsInMem(addr));
|
||||
if (DescribeAddressIfGlobal(addr, access_size))
|
||||
if (DescribeAddressIfGlobal(addr, access_size, bug_type))
|
||||
return;
|
||||
if (DescribeAddressIfStack(addr, access_size))
|
||||
return;
|
||||
@ -578,6 +597,11 @@ void DescribeThread(AsanThreadContext *context) {
|
||||
InternalScopedString str(1024);
|
||||
str.append("Thread T%d%s", context->tid,
|
||||
ThreadNameWithParenthesis(context->tid, tname, sizeof(tname)));
|
||||
if (context->parent_tid == kInvalidTid) {
|
||||
str.append(" created by unknown thread\n");
|
||||
Printf("%s", str.data());
|
||||
return;
|
||||
}
|
||||
str.append(
|
||||
" created by T%d%s here:\n", context->parent_tid,
|
||||
ThreadNameWithParenthesis(context->parent_tid, tname, sizeof(tname)));
|
||||
@ -805,8 +829,8 @@ void ReportStringFunctionMemoryRangesOverlap(const char *function,
|
||||
bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
|
||||
Printf("%s", d.EndWarning());
|
||||
stack->Print();
|
||||
DescribeAddress((uptr)offset1, length1);
|
||||
DescribeAddress((uptr)offset2, length2);
|
||||
DescribeAddress((uptr)offset1, length1, bug_type);
|
||||
DescribeAddress((uptr)offset2, length2, bug_type);
|
||||
ReportErrorSummary(bug_type, stack);
|
||||
}
|
||||
|
||||
@ -819,7 +843,7 @@ void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
|
||||
Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size);
|
||||
Printf("%s", d.EndWarning());
|
||||
stack->Print();
|
||||
DescribeAddress(offset, size);
|
||||
DescribeAddress(offset, size, bug_type);
|
||||
ReportErrorSummary(bug_type, stack);
|
||||
}
|
||||
|
||||
@ -834,6 +858,9 @@ void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
|
||||
" old_mid : %p\n"
|
||||
" new_mid : %p\n",
|
||||
beg, end, old_mid, new_mid);
|
||||
uptr granularity = SHADOW_GRANULARITY;
|
||||
if (!IsAligned(beg, granularity))
|
||||
Report("ERROR: beg is not aligned by %d\n", granularity);
|
||||
stack->Print();
|
||||
ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);
|
||||
}
|
||||
@ -871,15 +898,16 @@ void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
|
||||
static NOINLINE void
|
||||
ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {
|
||||
ScopedInErrorReport in_report;
|
||||
const char *bug_type = "invalid-pointer-pair";
|
||||
Decorator d;
|
||||
Printf("%s", d.Warning());
|
||||
Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2);
|
||||
Printf("%s", d.EndWarning());
|
||||
GET_STACK_TRACE_FATAL(pc, bp);
|
||||
stack.Print();
|
||||
DescribeAddress(a1, 1);
|
||||
DescribeAddress(a2, 1);
|
||||
ReportErrorSummary("invalid-pointer-pair", &stack);
|
||||
DescribeAddress(a1, 1, bug_type);
|
||||
DescribeAddress(a2, 1, bug_type);
|
||||
ReportErrorSummary(bug_type, &stack);
|
||||
}
|
||||
|
||||
static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
|
||||
@ -936,9 +964,18 @@ void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
||||
uptr access_size) {
|
||||
uptr access_size, u32 exp) {
|
||||
ENABLE_FRAME_POINTER;
|
||||
|
||||
// Optimization experiments.
|
||||
// The experiments can be used to evaluate potential optimizations that remove
|
||||
// instrumentation (assess false negatives). Instead of completely removing
|
||||
// some instrumentation, compiler can emit special calls into runtime
|
||||
// (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
|
||||
// mask of experiments (exp).
|
||||
// The reaction to a non-zero value of exp is to be defined.
|
||||
(void)exp;
|
||||
|
||||
// Determine the error type.
|
||||
const char *bug_descr = "unknown-crash";
|
||||
if (AddrIsInMem(addr)) {
|
||||
@ -1017,7 +1054,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
||||
GET_STACK_TRACE_FATAL(pc, bp);
|
||||
stack.Print();
|
||||
|
||||
DescribeAddress(addr, access_size);
|
||||
DescribeAddress(addr, access_size, bug_descr);
|
||||
ReportErrorSummary(bug_descr, &stack);
|
||||
PrintShadowMemoryForAddress(addr);
|
||||
}
|
||||
@ -1035,7 +1072,7 @@ void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
|
||||
void __asan_describe_address(uptr addr) {
|
||||
// Thread registry must be locked while we're describing an address.
|
||||
asanThreadRegistry().Lock();
|
||||
DescribeAddress(addr, 1);
|
||||
DescribeAddress(addr, 1, "");
|
||||
asanThreadRegistry().Unlock();
|
||||
}
|
||||
|
||||
|
@ -33,22 +33,19 @@ struct AddressDescription {
|
||||
const char *region_kind;
|
||||
};
|
||||
|
||||
// Returns the number of globals close to the provided address and copies
|
||||
// them to "globals" array.
|
||||
int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,
|
||||
int max_globals);
|
||||
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);
|
||||
// The following functions prints address description depending
|
||||
// on the memory type (shadow/heap/stack/global).
|
||||
void DescribeHeapAddress(uptr addr, uptr access_size);
|
||||
bool DescribeAddressIfGlobal(uptr addr, uptr access_size);
|
||||
bool DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
|
||||
const __asan_global &g);
|
||||
bool IsAddressNearGlobal(uptr addr, const __asan_global &g);
|
||||
bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);
|
||||
bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr = nullptr,
|
||||
bool print = true);
|
||||
bool ParseFrameDescription(const char *frame_descr,
|
||||
InternalMmapVector<StackVarDescr> *vars);
|
||||
bool DescribeAddressIfStack(uptr addr, uptr access_size);
|
||||
// Determines memory type on its own.
|
||||
void DescribeAddress(uptr addr, uptr access_size);
|
||||
|
||||
void DescribeThread(AsanThreadContext *context);
|
||||
|
||||
// Different kinds of error reports.
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_symbolizer.h"
|
||||
#include "lsan/lsan_common.h"
|
||||
#include "ubsan/ubsan_init.h"
|
||||
#include "ubsan/ubsan_platform.h"
|
||||
|
||||
int __asan_option_detect_stack_use_after_return; // Global interface symbol.
|
||||
uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.
|
||||
@ -87,12 +89,12 @@ void ShowStatsAndAbort() {
|
||||
// ---------------------- mmap -------------------- {{{1
|
||||
// Reserve memory range [beg, end].
|
||||
// We need to use inclusive range because end+1 may not be representable.
|
||||
void ReserveShadowMemoryRange(uptr beg, uptr end) {
|
||||
void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
|
||||
CHECK_EQ((beg % GetPageSizeCached()), 0);
|
||||
CHECK_EQ(((end + 1) % GetPageSizeCached()), 0);
|
||||
uptr size = end - beg + 1;
|
||||
DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb.
|
||||
void *res = MmapFixedNoReserve(beg, size);
|
||||
void *res = MmapFixedNoReserve(beg, size, name);
|
||||
if (res != (void*)beg) {
|
||||
Report("ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
|
||||
"Perhaps you're using ulimit -v\n", size);
|
||||
@ -112,11 +114,15 @@ static void OnLowLevelAllocate(uptr ptr, uptr size) {
|
||||
// -------------------------- Run-time entry ------------------- {{{1
|
||||
// exported functions
|
||||
#define ASAN_REPORT_ERROR(type, is_write, size) \
|
||||
extern "C" NOINLINE INTERFACE_ATTRIBUTE \
|
||||
void __asan_report_ ## type ## size(uptr addr); \
|
||||
void __asan_report_ ## type ## size(uptr addr) { \
|
||||
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); \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size, 0); \
|
||||
} \
|
||||
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); \
|
||||
}
|
||||
|
||||
ASAN_REPORT_ERROR(load, false, 1)
|
||||
@ -132,18 +138,20 @@ 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); \
|
||||
void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
|
||||
GET_CALLER_PC_BP_SP; \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size); \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size, 0); \
|
||||
} \
|
||||
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); \
|
||||
}
|
||||
|
||||
ASAN_REPORT_ERROR_N(load, false)
|
||||
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); \
|
||||
void __asan_##type##size(uptr addr) { \
|
||||
#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg) \
|
||||
uptr sp = MEM_TO_SHADOW(addr); \
|
||||
uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
|
||||
: *reinterpret_cast<u16 *>(sp); \
|
||||
@ -155,10 +163,19 @@ 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); \
|
||||
__asan_report_error(pc, bp, sp, addr, is_write, size, exp_arg); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#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) \
|
||||
} \
|
||||
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(load, false, 1)
|
||||
@ -173,18 +190,38 @@ ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8)
|
||||
ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)
|
||||
|
||||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE void __asan_loadN(uptr addr, uptr size) {
|
||||
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);
|
||||
__asan_report_error(pc, bp, sp, addr, false, size, 0);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
NOINLINE INTERFACE_ATTRIBUTE void __asan_storeN(uptr addr, uptr size) {
|
||||
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, true, size);
|
||||
__asan_report_error(pc, bp, sp, addr, false, size, exp);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,26 +240,40 @@ static NOINLINE void force_interface_symbols() {
|
||||
case 3: __asan_report_load4(0); break;
|
||||
case 4: __asan_report_load8(0); break;
|
||||
case 5: __asan_report_load16(0); break;
|
||||
case 6: __asan_report_store1(0); break;
|
||||
case 7: __asan_report_store2(0); break;
|
||||
case 8: __asan_report_store4(0); break;
|
||||
case 9: __asan_report_store8(0); break;
|
||||
case 10: __asan_report_store16(0); break;
|
||||
case 12: __asan_register_globals(0, 0); break;
|
||||
case 13: __asan_unregister_globals(0, 0); break;
|
||||
case 14: __asan_set_death_callback(0); break;
|
||||
case 15: __asan_set_error_report_callback(0); break;
|
||||
case 16: __asan_handle_no_return(); break;
|
||||
case 17: __asan_address_is_poisoned(0); break;
|
||||
case 25: __asan_poison_memory_region(0, 0); break;
|
||||
case 26: __asan_unpoison_memory_region(0, 0); break;
|
||||
case 27: __asan_set_error_exit_code(0); break;
|
||||
case 30: __asan_before_dynamic_init(0); break;
|
||||
case 31: __asan_after_dynamic_init(); break;
|
||||
case 32: __asan_poison_stack_memory(0, 0); break;
|
||||
case 33: __asan_unpoison_stack_memory(0, 0); break;
|
||||
case 34: __asan_region_is_poisoned(0, 0); break;
|
||||
case 35: __asan_describe_address(0); break;
|
||||
case 6: __asan_report_load_n(0, 0); break;
|
||||
case 7: __asan_report_store1(0); break;
|
||||
case 8: __asan_report_store2(0); break;
|
||||
case 9: __asan_report_store4(0); break;
|
||||
case 10: __asan_report_store8(0); break;
|
||||
case 11: __asan_report_store16(0); break;
|
||||
case 12: __asan_report_store_n(0, 0); break;
|
||||
case 13: __asan_report_exp_load1(0, 0); break;
|
||||
case 14: __asan_report_exp_load2(0, 0); break;
|
||||
case 15: __asan_report_exp_load4(0, 0); break;
|
||||
case 16: __asan_report_exp_load8(0, 0); break;
|
||||
case 17: __asan_report_exp_load16(0, 0); break;
|
||||
case 18: __asan_report_exp_load_n(0, 0, 0); break;
|
||||
case 19: __asan_report_exp_store1(0, 0); break;
|
||||
case 20: __asan_report_exp_store2(0, 0); break;
|
||||
case 21: __asan_report_exp_store4(0, 0); break;
|
||||
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 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 35: __asan_after_dynamic_init(); break;
|
||||
case 36: __asan_poison_stack_memory(0, 0); break;
|
||||
case 37: __asan_unpoison_stack_memory(0, 0); break;
|
||||
case 38: __asan_region_is_poisoned(0, 0); break;
|
||||
case 39: __asan_describe_address(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,9 +297,9 @@ static void InitializeHighMemEnd() {
|
||||
CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0);
|
||||
}
|
||||
|
||||
static void ProtectGap(uptr a, uptr size) {
|
||||
void *res = Mprotect(a, size);
|
||||
if (a == (uptr)res)
|
||||
static void ProtectGap(uptr addr, uptr size) {
|
||||
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");
|
||||
@ -296,9 +347,9 @@ static void PrintAddressSpaceLayout() {
|
||||
Printf("malloc_context_size=%zu\n",
|
||||
(uptr)common_flags()->malloc_context_size);
|
||||
|
||||
Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
|
||||
Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
|
||||
Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET);
|
||||
Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE);
|
||||
Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY);
|
||||
Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET);
|
||||
CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
|
||||
if (kMidMemBeg)
|
||||
CHECK(kMidShadowBeg > kLowShadowEnd &&
|
||||
@ -316,6 +367,11 @@ static void AsanInitInternal() {
|
||||
// initialization steps look at flags().
|
||||
InitializeFlags();
|
||||
|
||||
CacheBinaryName();
|
||||
|
||||
AsanCheckIncompatibleRT();
|
||||
AsanCheckDynamicRTPrereqs();
|
||||
|
||||
SetCanPoisonMemory(flags()->poison_heap);
|
||||
SetMallocContextSize(common_flags()->malloc_context_size);
|
||||
|
||||
@ -371,9 +427,9 @@ static void AsanInitInternal() {
|
||||
if (full_shadow_is_available) {
|
||||
// mmap the low shadow plus at least one page at the left.
|
||||
if (kLowShadowBeg)
|
||||
ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
|
||||
ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
|
||||
// mmap the high shadow.
|
||||
ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
|
||||
ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
|
||||
// protect the gap.
|
||||
ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
|
||||
CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
|
||||
@ -382,11 +438,11 @@ static void AsanInitInternal() {
|
||||
MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
|
||||
CHECK(kLowShadowBeg != kLowShadowEnd);
|
||||
// mmap the low shadow plus at least one page at the left.
|
||||
ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
|
||||
ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
|
||||
// mmap the mid shadow.
|
||||
ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd);
|
||||
ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");
|
||||
// mmap the high shadow.
|
||||
ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
|
||||
ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
|
||||
// protect the gaps.
|
||||
ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
|
||||
ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
|
||||
@ -446,6 +502,10 @@ static void AsanInitInternal() {
|
||||
}
|
||||
#endif // CAN_SANITIZE_LEAKS
|
||||
|
||||
#if CAN_SANITIZE_UB
|
||||
__ubsan::InitAsPlugin();
|
||||
#endif
|
||||
|
||||
InitializeSuppressions();
|
||||
|
||||
VReport(1, "AddressSanitizer Init done\n");
|
||||
@ -459,13 +519,11 @@ void AsanInitFromRtl() {
|
||||
|
||||
#if ASAN_DYNAMIC
|
||||
// Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable
|
||||
// (and thus normal initializer from .preinit_array haven't run).
|
||||
// (and thus normal initializers from .preinit_array or modules haven't run).
|
||||
|
||||
class AsanInitializer {
|
||||
public: // NOLINT
|
||||
AsanInitializer() {
|
||||
AsanCheckIncompatibleRT();
|
||||
AsanCheckDynamicRTPrereqs();
|
||||
AsanInitFromRtl();
|
||||
}
|
||||
};
|
||||
@ -517,7 +575,6 @@ void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
|
||||
// Initialize as requested from instrumented application code.
|
||||
// We use this call as a trigger to wake up ASan from deactivated state.
|
||||
void __asan_init() {
|
||||
AsanCheckIncompatibleRT();
|
||||
AsanActivate();
|
||||
AsanInitInternal();
|
||||
}
|
||||
|
@ -51,12 +51,8 @@ void AsanStats::Print() {
|
||||
(mmaped-munmaped)>>20, mmaped>>20, munmaped>>20,
|
||||
mmaps, munmaps);
|
||||
|
||||
PrintMallocStatsArray(" mmaps by size class: ", mmaped_by_size);
|
||||
PrintMallocStatsArray(" mallocs by size class: ", malloced_by_size);
|
||||
PrintMallocStatsArray(" frees by size class: ", freed_by_size);
|
||||
PrintMallocStatsArray(" rfrees by size class: ", really_freed_by_size);
|
||||
Printf("Stats: malloc large: %zu small slow: %zu\n",
|
||||
malloc_large, malloc_small_slow);
|
||||
Printf("Stats: malloc large: %zu\n", malloc_large);
|
||||
}
|
||||
|
||||
void AsanStats::MergeFrom(const AsanStats *stats) {
|
||||
@ -161,8 +157,7 @@ uptr __sanitizer_get_free_bytes() {
|
||||
GetAccumulatedStats(&stats);
|
||||
uptr total_free = stats.mmaped
|
||||
- stats.munmaped
|
||||
+ stats.really_freed
|
||||
+ stats.really_freed_redzones;
|
||||
+ stats.really_freed;
|
||||
uptr total_used = stats.malloced
|
||||
+ stats.malloced_redzones;
|
||||
// Return sane value if total_free < total_used due to racy
|
||||
|
@ -32,20 +32,14 @@ struct AsanStats {
|
||||
uptr freed;
|
||||
uptr real_frees;
|
||||
uptr really_freed;
|
||||
uptr really_freed_redzones;
|
||||
uptr reallocs;
|
||||
uptr realloced;
|
||||
uptr mmaps;
|
||||
uptr mmaped;
|
||||
uptr munmaps;
|
||||
uptr munmaped;
|
||||
uptr mmaped_by_size[kNumberOfSizeClasses];
|
||||
uptr malloced_by_size[kNumberOfSizeClasses];
|
||||
uptr freed_by_size[kNumberOfSizeClasses];
|
||||
uptr really_freed_by_size[kNumberOfSizeClasses];
|
||||
|
||||
uptr malloc_large;
|
||||
uptr malloc_small_slow;
|
||||
uptr malloced_by_size[kNumberOfSizeClasses];
|
||||
|
||||
// Ctor for global AsanStats (accumulated stats for dead threads).
|
||||
explicit AsanStats(LinkerInitialized) { }
|
||||
|
@ -26,14 +26,28 @@ static SuppressionContext *suppression_ctx = nullptr;
|
||||
static const char kInterceptorName[] = "interceptor_name";
|
||||
static const char kInterceptorViaFunction[] = "interceptor_via_fun";
|
||||
static const char kInterceptorViaLibrary[] = "interceptor_via_lib";
|
||||
static const char kODRViolation[] = "odr_violation";
|
||||
static const char *kSuppressionTypes[] = {
|
||||
kInterceptorName, kInterceptorViaFunction, kInterceptorViaLibrary};
|
||||
kInterceptorName, kInterceptorViaFunction, kInterceptorViaLibrary,
|
||||
kODRViolation};
|
||||
|
||||
extern "C" {
|
||||
#if SANITIZER_SUPPORTS_WEAK_HOOKS
|
||||
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||
const char *__asan_default_suppressions();
|
||||
#else
|
||||
// No week hooks, provide empty implementation.
|
||||
const char *__asan_default_suppressions() { return ""; }
|
||||
#endif // SANITIZER_SUPPORTS_WEAK_HOOKS
|
||||
} // extern "C"
|
||||
|
||||
void InitializeSuppressions() {
|
||||
CHECK_EQ(nullptr, suppression_ctx);
|
||||
suppression_ctx = new (suppression_placeholder) // NOLINT
|
||||
SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
|
||||
suppression_ctx->ParseFromFile(flags()->suppressions);
|
||||
if (&__asan_default_suppressions)
|
||||
suppression_ctx->Parse(__asan_default_suppressions());
|
||||
}
|
||||
|
||||
bool IsInterceptorSuppressed(const char *interceptor_name) {
|
||||
@ -49,6 +63,13 @@ bool HaveStackTraceBasedSuppressions() {
|
||||
suppression_ctx->HasSuppressionType(kInterceptorViaLibrary);
|
||||
}
|
||||
|
||||
bool IsODRViolationSuppressed(const char *global_var_name) {
|
||||
CHECK(suppression_ctx);
|
||||
Suppression *s;
|
||||
// Match "odr_violation" suppressions.
|
||||
return suppression_ctx->Match(global_var_name, kODRViolation, &s);
|
||||
}
|
||||
|
||||
bool IsStackTraceSuppressed(const StackTrace *stack) {
|
||||
if (!HaveStackTraceBasedSuppressions())
|
||||
return false;
|
||||
@ -60,14 +81,10 @@ bool IsStackTraceSuppressed(const StackTrace *stack) {
|
||||
uptr addr = stack->trace[i];
|
||||
|
||||
if (suppression_ctx->HasSuppressionType(kInterceptorViaLibrary)) {
|
||||
const char *module_name;
|
||||
uptr module_offset;
|
||||
// Match "interceptor_via_lib" suppressions.
|
||||
if (symbolizer->GetModuleNameAndOffsetForPC(addr, &module_name,
|
||||
&module_offset) &&
|
||||
suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s)) {
|
||||
return true;
|
||||
}
|
||||
if (const char *module_name = symbolizer->GetModuleNameForPc(addr))
|
||||
if (suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (suppression_ctx->HasSuppressionType(kInterceptorViaFunction)) {
|
||||
|
@ -23,6 +23,7 @@ void InitializeSuppressions();
|
||||
bool IsInterceptorSuppressed(const char *interceptor_name);
|
||||
bool HaveStackTraceBasedSuppressions();
|
||||
bool IsStackTraceSuppressed(const StackTrace *stack);
|
||||
bool IsODRViolationSuppressed(const char *global_var_name);
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
|
@ -34,19 +34,16 @@ class AsanThread;
|
||||
class AsanThreadContext : public ThreadContextBase {
|
||||
public:
|
||||
explicit AsanThreadContext(int tid)
|
||||
: ThreadContextBase(tid),
|
||||
announced(false),
|
||||
destructor_iterations(kPthreadDestructorIterations),
|
||||
stack_id(0),
|
||||
thread(0) {
|
||||
}
|
||||
: ThreadContextBase(tid), announced(false),
|
||||
destructor_iterations(GetPthreadDestructorIterations()), stack_id(0),
|
||||
thread(0) {}
|
||||
bool announced;
|
||||
u8 destructor_iterations;
|
||||
u32 stack_id;
|
||||
AsanThread *thread;
|
||||
|
||||
void OnCreated(void *arg);
|
||||
void OnFinished();
|
||||
void OnCreated(void *arg) override;
|
||||
void OnFinished() override;
|
||||
};
|
||||
|
||||
// AsanThreadContext objects are never freed, so we need many of them.
|
||||
|
@ -22,21 +22,134 @@
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_report.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_thread.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_mutex.h"
|
||||
|
||||
using namespace __asan; // NOLINT
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
int __asan_should_detect_stack_use_after_return() {
|
||||
__asan_init();
|
||||
return __asan_option_detect_stack_use_after_return;
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
int __asan_should_detect_stack_use_after_return() {
|
||||
__asan_init();
|
||||
return __asan_option_detect_stack_use_after_return;
|
||||
}
|
||||
|
||||
// -------------------- A workaround for the abscence of weak symbols ----- {{{
|
||||
// We don't have a direct equivalent of weak symbols when using MSVC, but we can
|
||||
// use the /alternatename directive to tell the linker to default a specific
|
||||
// symbol to a specific value, which works nicely for allocator hooks and
|
||||
// __asan_default_options().
|
||||
void __sanitizer_default_malloc_hook(void *ptr, uptr size) { }
|
||||
void __sanitizer_default_free_hook(void *ptr) { }
|
||||
const char* __asan_default_default_options() { return ""; }
|
||||
const char* __asan_default_default_suppressions() { return ""; }
|
||||
void __asan_default_on_error() {}
|
||||
#pragma comment(linker, "/alternatename:___sanitizer_malloc_hook=___sanitizer_default_malloc_hook") // NOLINT
|
||||
#pragma comment(linker, "/alternatename:___sanitizer_free_hook=___sanitizer_default_free_hook") // NOLINT
|
||||
#pragma comment(linker, "/alternatename:___asan_default_options=___asan_default_default_options") // NOLINT
|
||||
#pragma comment(linker, "/alternatename:___asan_default_suppressions=___asan_default_default_suppressions") // NOLINT
|
||||
#pragma comment(linker, "/alternatename:___asan_on_error=___asan_default_on_error") // NOLINT
|
||||
// }}}
|
||||
} // extern "C"
|
||||
|
||||
// ---------------------- Windows-specific inteceptors ---------------- {{{
|
||||
INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
|
||||
CHECK(REAL(RaiseException));
|
||||
__asan_handle_no_return();
|
||||
REAL(RaiseException)(a, b, c, d);
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
|
||||
CHECK(REAL(_except_handler3));
|
||||
__asan_handle_no_return();
|
||||
return REAL(_except_handler3)(a, b, c, d);
|
||||
}
|
||||
|
||||
#if ASAN_DYNAMIC
|
||||
// This handler is named differently in -MT and -MD CRTs.
|
||||
#define _except_handler4 _except_handler4_common
|
||||
#endif
|
||||
INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
|
||||
CHECK(REAL(_except_handler4));
|
||||
__asan_handle_no_return();
|
||||
return REAL(_except_handler4)(a, b, c, d);
|
||||
}
|
||||
|
||||
static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
|
||||
AsanThread *t = (AsanThread*)arg;
|
||||
SetCurrentThread(t);
|
||||
return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr);
|
||||
}
|
||||
|
||||
INTERCEPTOR_WINAPI(DWORD, CreateThread,
|
||||
void* security, uptr stack_size,
|
||||
DWORD (__stdcall *start_routine)(void*), void* arg,
|
||||
DWORD thr_flags, void* tid) {
|
||||
// Strict init-order checking is thread-hostile.
|
||||
if (flags()->strict_init_order)
|
||||
StopInitOrderChecking();
|
||||
GET_STACK_TRACE_THREAD;
|
||||
// FIXME: The CreateThread interceptor is not the same as a pthread_create
|
||||
// one. This is a bandaid fix for PR22025.
|
||||
bool detached = false; // FIXME: how can we determine it on Windows?
|
||||
u32 current_tid = GetCurrentTidOrInvalid();
|
||||
AsanThread *t =
|
||||
AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
|
||||
return REAL(CreateThread)(security, stack_size,
|
||||
asan_thread_start, t, thr_flags, tid);
|
||||
}
|
||||
|
||||
namespace {
|
||||
BlockingMutex mu_for_thread_tracking(LINKER_INITIALIZED);
|
||||
|
||||
void EnsureWorkerThreadRegistered() {
|
||||
// FIXME: GetCurrentThread relies on TSD, which might not play well with
|
||||
// system thread pools. We might want to use something like reference
|
||||
// counting to zero out GetCurrentThread() underlying storage when the last
|
||||
// work item finishes? Or can we disable reclaiming of threads in the pool?
|
||||
BlockingMutexLock l(&mu_for_thread_tracking);
|
||||
if (__asan::GetCurrentThread())
|
||||
return;
|
||||
|
||||
AsanThread *t = AsanThread::Create(
|
||||
/* start_routine */ nullptr, /* arg */ nullptr,
|
||||
/* parent_tid */ -1, /* stack */ nullptr, /* detached */ true);
|
||||
t->Init();
|
||||
asanThreadRegistry().StartThread(t->tid(), 0, 0);
|
||||
SetCurrentThread(t);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
INTERCEPTOR_WINAPI(DWORD, NtWaitForWorkViaWorkerFactory, DWORD a, DWORD b) {
|
||||
// NtWaitForWorkViaWorkerFactory is called from system worker pool threads to
|
||||
// query work scheduled by BindIoCompletionCallback, QueueUserWorkItem, etc.
|
||||
// System worker pool threads are created at arbitraty point in time and
|
||||
// without using CreateThread, so we wrap NtWaitForWorkViaWorkerFactory
|
||||
// instead and don't register a specific parent_tid/stack.
|
||||
EnsureWorkerThreadRegistered();
|
||||
return REAL(NtWaitForWorkViaWorkerFactory)(a, b);
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
namespace __asan {
|
||||
|
||||
// ---------------------- TSD ---------------- {{{1
|
||||
void InitializePlatformInterceptors() {
|
||||
ASAN_INTERCEPT_FUNC(CreateThread);
|
||||
ASAN_INTERCEPT_FUNC(RaiseException);
|
||||
ASAN_INTERCEPT_FUNC(_except_handler3);
|
||||
ASAN_INTERCEPT_FUNC(_except_handler4);
|
||||
|
||||
// NtWaitForWorkViaWorkerFactory is always linked dynamically.
|
||||
CHECK(::__interception::OverrideFunction(
|
||||
"NtWaitForWorkViaWorkerFactory",
|
||||
(uptr)WRAP(NtWaitForWorkViaWorkerFactory),
|
||||
(uptr *)&REAL(NtWaitForWorkViaWorkerFactory)));
|
||||
}
|
||||
|
||||
// ---------------------- TSD ---------------- {{{
|
||||
static bool tsd_key_inited = false;
|
||||
|
||||
static __declspec(thread) void *fake_tsd = 0;
|
||||
@ -59,7 +172,9 @@ void AsanTSDSet(void *tsd) {
|
||||
void PlatformTSDDtor(void *tsd) {
|
||||
AsanThread::TSDDtor(tsd);
|
||||
}
|
||||
// ---------------------- Various stuff ---------------- {{{1
|
||||
// }}}
|
||||
|
||||
// ---------------------- Various stuff ---------------- {{{
|
||||
void DisableReexec() {
|
||||
// No need to re-exec on Windows.
|
||||
}
|
||||
@ -93,23 +208,6 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
|
||||
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
|
||||
|
||||
SignalContext SignalContext::Create(void *siginfo, void *context) {
|
||||
EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo;
|
||||
CONTEXT *context_record = (CONTEXT*)context;
|
||||
|
||||
uptr pc = (uptr)exception_record->ExceptionAddress;
|
||||
#ifdef _WIN64
|
||||
uptr bp = (uptr)context_record->Rbp;
|
||||
uptr sp = (uptr)context_record->Rsp;
|
||||
#else
|
||||
uptr bp = (uptr)context_record->Ebp;
|
||||
uptr sp = (uptr)context_record->Esp;
|
||||
#endif
|
||||
uptr access_addr = exception_record->ExceptionInformation[1];
|
||||
|
||||
return SignalContext(context, access_addr, pc, sp, bp);
|
||||
}
|
||||
|
||||
static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
|
||||
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
|
||||
CONTEXT *context = info->ContextRecord;
|
||||
@ -162,7 +260,7 @@ int __asan_set_seh_filter() {
|
||||
static __declspec(allocate(".CRT$XIZ"))
|
||||
int (*__intercept_seh)() = __asan_set_seh_filter;
|
||||
#endif
|
||||
|
||||
// }}}
|
||||
} // namespace __asan
|
||||
|
||||
#endif // _WIN32
|
||||
|
@ -303,8 +303,8 @@ INTERFACE_FUNCTION(__sanitizer_cov_init)
|
||||
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_with_check)
|
||||
INTERFACE_FUNCTION(__sanitizer_free_hook)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_coverage_guards)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes)
|
||||
@ -314,13 +314,14 @@ INTERFACE_FUNCTION(__sanitizer_get_heap_size)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_ownership)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes)
|
||||
INTERFACE_FUNCTION(__sanitizer_malloc_hook)
|
||||
INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file)
|
||||
INTERFACE_FUNCTION(__sanitizer_print_stack_trace)
|
||||
INTERFACE_FUNCTION(__sanitizer_ptr_cmp)
|
||||
INTERFACE_FUNCTION(__sanitizer_ptr_sub)
|
||||
INTERFACE_FUNCTION(__sanitizer_report_error_summary)
|
||||
INTERFACE_FUNCTION(__sanitizer_reset_coverage)
|
||||
INTERFACE_FUNCTION(__sanitizer_get_number_of_counters)
|
||||
INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters)
|
||||
INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify)
|
||||
INTERFACE_FUNCTION(__sanitizer_set_death_callback)
|
||||
INTERFACE_FUNCTION(__sanitizer_set_report_path)
|
||||
@ -380,11 +381,15 @@ INTERCEPT_LIBRARY_FUNCTION(strcat); // NOLINT
|
||||
INTERCEPT_LIBRARY_FUNCTION(strchr);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcmp);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcpy); // NOLINT
|
||||
INTERCEPT_LIBRARY_FUNCTION(strcspn);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strlen);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strncat);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strncmp);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strncpy);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strnlen);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strpbrk);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strspn);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strstr);
|
||||
INTERCEPT_LIBRARY_FUNCTION(strtol);
|
||||
INTERCEPT_LIBRARY_FUNCTION(wcslen);
|
||||
|
||||
|
@ -15,7 +15,8 @@
|
||||
//
|
||||
// This includes:
|
||||
// - forwarding the detect_stack_use_after_return runtime option
|
||||
// - installing a custom SEH handler
|
||||
// - working around deficiencies of the MD runtime
|
||||
// - installing a custom SEH handlerx
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -24,9 +25,13 @@
|
||||
// simplifies the build procedure.
|
||||
#ifdef ASAN_DYNAMIC_RUNTIME_THUNK
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
|
||||
extern "C" {
|
||||
// First, declare CRT sections we'll be using in this file
|
||||
#pragma section(".CRT$XID", long, read) // NOLINT
|
||||
#pragma section(".CRT$XIZ", long, read) // NOLINT
|
||||
#pragma section(".CRT$XTW", long, read) // NOLINT
|
||||
#pragma section(".CRT$XTY", long, read) // NOLINT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Define a copy of __asan_option_detect_stack_use_after_return that should be
|
||||
// used when linking an MD runtime with a set of object files on Windows.
|
||||
@ -38,82 +43,55 @@ extern "C" {
|
||||
// with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows
|
||||
// just to work around this issue, let's clone the a variable that is
|
||||
// constant after initialization anyways.
|
||||
extern "C" {
|
||||
__declspec(dllimport) int __asan_should_detect_stack_use_after_return();
|
||||
int __asan_option_detect_stack_use_after_return =
|
||||
__asan_should_detect_stack_use_after_return();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// For some reason, the MD CRT doesn't call the C/C++ terminators as MT does.
|
||||
// To work around this, for each DLL we schedule a call to
|
||||
// UnregisterGlobalsInRange atexit() specifying the address range of the DLL
|
||||
// image to unregister globals in that range. We don't do the same
|
||||
// for the main module (.exe) as the asan_globals.cc allocator is destroyed
|
||||
// by the time UnregisterGlobalsInRange is executed.
|
||||
// See PR22545 for the details.
|
||||
namespace __asan {
|
||||
__declspec(dllimport)
|
||||
void UnregisterGlobalsInRange(void *beg, void *end);
|
||||
}
|
||||
// For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL
|
||||
// unload or on exit. ASan relies on LLVM global_dtors to call
|
||||
// __asan_unregister_globals on these events, which unfortunately doesn't work
|
||||
// with the MD runtime, see PR22545 for the details.
|
||||
// To work around this, for each DLL we schedule a call to UnregisterGlobals
|
||||
// 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" void __cdecl _initterm(void *a, void *b);
|
||||
|
||||
namespace {
|
||||
void *this_module_base, *this_module_end;
|
||||
__declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0;
|
||||
__declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0;
|
||||
|
||||
void UnregisterGlobals() {
|
||||
__asan::UnregisterGlobalsInRange(this_module_base, this_module_end);
|
||||
_initterm(&before_global_dtors, &after_global_dtors);
|
||||
}
|
||||
|
||||
int ScheduleUnregisterGlobals() {
|
||||
HMODULE this_module = 0;
|
||||
// Increments the reference counter of the DLL module, so need to call
|
||||
// FreeLibrary later.
|
||||
if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
(LPCTSTR)&UnregisterGlobals, &this_module))
|
||||
return 1;
|
||||
|
||||
// Skip the main module.
|
||||
if (this_module == GetModuleHandle(0))
|
||||
return 0;
|
||||
|
||||
MODULEINFO mi;
|
||||
bool success =
|
||||
GetModuleInformation(GetCurrentProcess(), this_module, &mi, sizeof(mi));
|
||||
if (!FreeLibrary(this_module))
|
||||
return 2;
|
||||
if (!success)
|
||||
return 3;
|
||||
|
||||
this_module_base = mi.lpBaseOfDll;
|
||||
this_module_end = (char*)mi.lpBaseOfDll + mi.SizeOfImage;
|
||||
|
||||
return atexit(UnregisterGlobals);
|
||||
}
|
||||
|
||||
// We need to call 'atexit(UnregisterGlobals);' as early as possible, but after
|
||||
// atexit() is initialized (.CRT$XIC). As this is executed before C++
|
||||
// initializers (think ctors for globals), UnregisterGlobals gets executed after
|
||||
// dtors for C++ globals.
|
||||
__declspec(allocate(".CRT$XID"))
|
||||
int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals;
|
||||
|
||||
} // namespace
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ASan SEH handling.
|
||||
extern "C" __declspec(dllimport) int __asan_set_seh_filter();
|
||||
static int SetSEHFilter() { return __asan_set_seh_filter(); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// We schedule some work at start-up by placing callbacks to our code to the
|
||||
// list of CRT C initializers.
|
||||
//
|
||||
// First, declare sections we'll be using:
|
||||
#pragma section(".CRT$XID", long, read) // NOLINT
|
||||
#pragma section(".CRT$XIZ", long, read) // NOLINT
|
||||
|
||||
// We need to call 'atexit(UnregisterGlobals);' after atexit() is initialized
|
||||
// (.CRT$XIC) but before the C++ constructors (.CRT$XCA).
|
||||
__declspec(allocate(".CRT$XID"))
|
||||
static int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals;
|
||||
|
||||
// We need to set the ASan-specific SEH handler at the end of CRT initialization
|
||||
// of each module (see also asan_win.cc).
|
||||
//
|
||||
extern "C" {
|
||||
__declspec(dllimport) int __asan_set_seh_filter();
|
||||
static int SetSEHFilter() { return __asan_set_seh_filter(); }
|
||||
|
||||
// Unfortunately, putting a pointer to __asan_set_seh_filter into
|
||||
// __asan_intercept_seh gets optimized out, so we have to use an extra function.
|
||||
extern "C" __declspec(allocate(".CRT$XIZ"))
|
||||
int (*__asan_seh_interceptor)() = SetSEHFilter;
|
||||
__declspec(allocate(".CRT$XIZ")) int (*__asan_seh_interceptor)() = SetSEHFilter;
|
||||
}
|
||||
|
||||
#endif // ASAN_DYNAMIC_RUNTIME_THUNK
|
||||
|
@ -23,6 +23,7 @@ sysroot_path = None
|
||||
binary_name_filter = None
|
||||
fix_filename_patterns = None
|
||||
logfile = sys.stdin
|
||||
allow_system_symbolizer = True
|
||||
|
||||
# FIXME: merge the code that calls fix_filename().
|
||||
def fix_filename(file_name):
|
||||
@ -392,6 +393,8 @@ class SymbolizationLoop(object):
|
||||
[BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]])
|
||||
result = symbolizers[binary].symbolize(addr, binary, offset)
|
||||
if result is None:
|
||||
if not allow_system_symbolizer:
|
||||
raise Exception('Failed to launch or use llvm-symbolizer.')
|
||||
# Initialize system symbolizer only if other symbolizers failed.
|
||||
symbolizers[binary].append_symbolizer(
|
||||
SystemSymbolizerFactory(self.system, addr, binary))
|
||||
|
@ -52,6 +52,11 @@ if(APPLE)
|
||||
list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS ${DARWIN_osx_LINKFLAGS})
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# Disable exceptions on Windows until they work reliably.
|
||||
list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -fno-exceptions -DGTEST_HAS_SEH=0)
|
||||
endif()
|
||||
|
||||
set(ASAN_BLACKLIST_FILE "${CMAKE_CURRENT_SOURCE_DIR}/asan_test.ignore")
|
||||
set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS
|
||||
${ASAN_UNITTEST_COMMON_CFLAGS}
|
||||
@ -94,6 +99,7 @@ append_list_if(ANDROID atomic ASAN_UNITTEST_INSTRUMENTED_LIBS)
|
||||
set(ASAN_UNITTEST_NOINST_LINKFLAGS ${ASAN_UNITTEST_COMMON_LINKFLAGS})
|
||||
append_list_if(COMPILER_RT_HAS_LIBM -lm ASAN_UNITTEST_NOINST_LINKFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBDL -ldl ASAN_UNITTEST_NOINST_LINKFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBRT -lrt ASAN_UNITTEST_NOINST_LINKFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread ASAN_UNITTEST_NOINST_LINKFLAGS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread
|
||||
ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINKFLAGS)
|
||||
@ -123,7 +129,7 @@ endmacro()
|
||||
# Link ASan unit test for a given architecture from a set
|
||||
# of objects in with given linker flags.
|
||||
macro(add_asan_test test_suite test_name arch kind)
|
||||
parse_arguments(TEST "OBJECTS;LINKFLAGS;SUBDIR" "WITH_TEST_RUNTIME" ${ARGN})
|
||||
cmake_parse_arguments(TEST "WITH_TEST_RUNTIME" "" "OBJECTS;LINKFLAGS;SUBDIR" ${ARGN})
|
||||
get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS)
|
||||
set(TEST_DEPS ${TEST_OBJECTS})
|
||||
if(NOT COMPILER_RT_STANDALONE_BUILD)
|
||||
@ -214,18 +220,18 @@ macro(add_asan_tests_for_arch_and_kind arch kind)
|
||||
$<TARGET_OBJECTS:RTAsan.osx>
|
||||
$<TARGET_OBJECTS:RTInterception.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.osx>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.osx>)
|
||||
$<TARGET_OBJECTS:RTLSanCommon.osx>
|
||||
$<TARGET_OBJECTS:RTUbsan.osx>)
|
||||
else()
|
||||
set(ASAN_TEST_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTAsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTAsan_cxx.${arch}>
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
|
||||
if(NOT WIN32)
|
||||
list(APPEND ASAN_TEST_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>)
|
||||
endif()
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>)
|
||||
endif()
|
||||
add_library(${ASAN_TEST_RUNTIME} STATIC ${ASAN_TEST_RUNTIME_OBJECTS})
|
||||
set_target_properties(${ASAN_TEST_RUNTIME} PROPERTIES
|
||||
@ -270,6 +276,8 @@ if(ANDROID)
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
|
||||
${COMPILER_RT_GTEST_SOURCE}
|
||||
${ASAN_NOINST_TEST_SOURCES})
|
||||
set_target_compile_flags(AsanNoinstTest ${ASAN_UNITTEST_COMMON_CFLAGS})
|
||||
|
@ -232,7 +232,7 @@ TEST(AddressSanitizer, asm_flags) {
|
||||
long magic = 0x1234;
|
||||
long r = 0x0;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(__x86_64__) && !defined(__ILP32__)
|
||||
__asm__("xorq %%rax, %%rax \n\t"
|
||||
"movq (%[p]), %%rax \n\t"
|
||||
"sete %%al \n\t"
|
||||
@ -248,7 +248,7 @@ TEST(AddressSanitizer, asm_flags) {
|
||||
: [r] "=r"(r)
|
||||
: [p] "r"(&magic)
|
||||
: "eax", "memory");
|
||||
#endif // defined(__x86_64__)
|
||||
#endif // defined(__x86_64__) && !defined(__ILP32__)
|
||||
|
||||
ASSERT_EQ(0x1, r);
|
||||
}
|
||||
|
@ -290,9 +290,6 @@ void RunStrCmpTest(PointerToStrCmp StrCmp) {
|
||||
Ident(StrCmp(s1, s2));
|
||||
Ident(StrCmp(s1, s2 + size - 1));
|
||||
Ident(StrCmp(s1 + size - 1, s2 + size - 1));
|
||||
s1[size - 1] = 'z';
|
||||
s2[size - 1] = 'x';
|
||||
Ident(StrCmp(s1, s2));
|
||||
// One of arguments points to not allocated memory.
|
||||
EXPECT_DEATH(Ident(StrCmp)(s1 - 1, s2), LeftOOBReadMessage(1));
|
||||
EXPECT_DEATH(Ident(StrCmp)(s1, s2 - 1), LeftOOBReadMessage(1));
|
||||
@ -371,17 +368,14 @@ TEST(AddressSanitizer, StrCatOOBTest) {
|
||||
// One of arguments points to not allocated memory.
|
||||
EXPECT_DEATH(strcat(to - 1, from), LeftOOBAccessMessage(1));
|
||||
EXPECT_DEATH(strcat(to, from - 1), LeftOOBReadMessage(1));
|
||||
EXPECT_DEATH(strcat(to + to_size, from), RightOOBWriteMessage(0));
|
||||
EXPECT_DEATH(strcat(to, from + from_size), RightOOBReadMessage(0));
|
||||
|
||||
// "from" is not zero-terminated.
|
||||
from[from_size - 1] = 'z';
|
||||
EXPECT_DEATH(strcat(to, from), RightOOBReadMessage(0));
|
||||
from[from_size - 1] = '\0';
|
||||
// "to" is not zero-terminated.
|
||||
memset(to, 'z', to_size);
|
||||
EXPECT_DEATH(strcat(to, from), RightOOBWriteMessage(0));
|
||||
// "to" is too short to fit "from".
|
||||
memset(to, 'z', to_size);
|
||||
to[to_size - from_size + 1] = '\0';
|
||||
EXPECT_DEATH(strcat(to, from), RightOOBWriteMessage(0));
|
||||
// length of "to" is just enough.
|
||||
@ -409,7 +403,6 @@ TEST(AddressSanitizer, StrNCatOOBTest) {
|
||||
// One of arguments points to not allocated memory.
|
||||
EXPECT_DEATH(strncat(to - 1, from, 2), LeftOOBAccessMessage(1));
|
||||
EXPECT_DEATH(strncat(to, from - 1, 2), LeftOOBReadMessage(1));
|
||||
EXPECT_DEATH(strncat(to + to_size, from, 2), RightOOBWriteMessage(0));
|
||||
EXPECT_DEATH(strncat(to, from + from_size, 2), RightOOBReadMessage(0));
|
||||
|
||||
memset(from, 'z', from_size);
|
||||
@ -417,8 +410,6 @@ TEST(AddressSanitizer, StrNCatOOBTest) {
|
||||
to[0] = '\0';
|
||||
// "from" is too short.
|
||||
EXPECT_DEATH(strncat(to, from, from_size + 1), RightOOBReadMessage(0));
|
||||
// "to" is not zero-terminated.
|
||||
EXPECT_DEATH(strncat(to + 1, from, 1), RightOOBWriteMessage(0));
|
||||
// "to" is too short to fit "from".
|
||||
to[0] = 'z';
|
||||
to[to_size - from_size + 1] = '\0';
|
||||
@ -508,20 +499,15 @@ void RunAtoiOOBTest(PointerToCallAtoi Atoi) {
|
||||
EXPECT_DEATH(Atoi(array - 1), LeftOOBReadMessage(1));
|
||||
// Die if a buffer doesn't have terminating NULL.
|
||||
EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
|
||||
// Make last symbol a terminating NULL or other non-digit.
|
||||
// Make last symbol a terminating NULL
|
||||
array[9] = '\0';
|
||||
Atoi(array);
|
||||
array[9] = 'a';
|
||||
Atoi(array);
|
||||
Atoi(array + 9);
|
||||
// Sometimes we need to detect overflow if no digits are found.
|
||||
memset(array, ' ', 10);
|
||||
EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
|
||||
array[9] = '-';
|
||||
EXPECT_DEATH(Atoi(array), RightOOBReadMessage(0));
|
||||
EXPECT_DEATH(Atoi(array + 9), RightOOBReadMessage(0));
|
||||
array[8] = '-';
|
||||
Atoi(array);
|
||||
free(array);
|
||||
}
|
||||
|
||||
@ -546,7 +532,6 @@ typedef void(*PointerToCallStrtol)(const char*, char**, int);
|
||||
|
||||
void RunStrtolOOBTest(PointerToCallStrtol Strtol) {
|
||||
char *array = MallocAndMemsetString(3);
|
||||
char *endptr = NULL;
|
||||
array[0] = '1';
|
||||
array[1] = '2';
|
||||
array[2] = '3';
|
||||
@ -554,19 +539,12 @@ void RunStrtolOOBTest(PointerToCallStrtol Strtol) {
|
||||
EXPECT_DEATH(Strtol(array + 3, NULL, 0), RightOOBReadMessage(0));
|
||||
EXPECT_DEATH(Strtol(array - 1, NULL, 0), LeftOOBReadMessage(1));
|
||||
// Buffer overflow if there is no terminating null (depends on base).
|
||||
Strtol(array, &endptr, 3);
|
||||
EXPECT_EQ(array + 2, endptr);
|
||||
EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
|
||||
array[2] = 'z';
|
||||
Strtol(array, &endptr, 35);
|
||||
EXPECT_EQ(array + 2, endptr);
|
||||
EXPECT_DEATH(Strtol(array, NULL, 36), RightOOBReadMessage(0));
|
||||
// Add terminating zero to get rid of overflow.
|
||||
array[2] = '\0';
|
||||
Strtol(array, NULL, 36);
|
||||
// Don't check for overflow if base is invalid.
|
||||
Strtol(array - 1, NULL, -1);
|
||||
Strtol(array + 3, NULL, 1);
|
||||
// Sometimes we need to detect overflow if no digits are found.
|
||||
array[0] = array[1] = array[2] = ' ';
|
||||
EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
|
||||
@ -574,13 +552,6 @@ void RunStrtolOOBTest(PointerToCallStrtol Strtol) {
|
||||
EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
|
||||
array[2] = '-';
|
||||
EXPECT_DEATH(Strtol(array, NULL, 0), RightOOBReadMessage(0));
|
||||
array[1] = '+';
|
||||
Strtol(array, NULL, 0);
|
||||
array[1] = array[2] = 'z';
|
||||
Strtol(array, &endptr, 0);
|
||||
EXPECT_EQ(array, endptr);
|
||||
Strtol(array + 2, NULL, 0);
|
||||
EXPECT_EQ(array, endptr);
|
||||
free(array);
|
||||
}
|
||||
|
||||
|
@ -31,13 +31,13 @@ NOINLINE void free_aaa(void *p) { free_bbb(p); break_optimization(0);}
|
||||
|
||||
template<typename T>
|
||||
NOINLINE void uaf_test(int size, int off) {
|
||||
char *p = (char *)malloc_aaa(size);
|
||||
void *p = malloc_aaa(size);
|
||||
free_aaa(p);
|
||||
for (int i = 1; i < 100; i++)
|
||||
free_aaa(malloc_aaa(i));
|
||||
fprintf(stderr, "writing %ld byte(s) at %p with offset %d\n",
|
||||
(long)sizeof(T), p, off);
|
||||
asan_write((T*)(p + off));
|
||||
asan_write((T *)((char *)p + off));
|
||||
}
|
||||
|
||||
TEST(AddressSanitizer, HasFeatureAddressSanitizerTest) {
|
||||
@ -436,10 +436,10 @@ TEST(AddressSanitizer, WrongFreeTest) {
|
||||
|
||||
void DoubleFree() {
|
||||
int *x = (int*)malloc(100 * sizeof(int));
|
||||
fprintf(stderr, "DoubleFree: x=%p\n", x);
|
||||
fprintf(stderr, "DoubleFree: x=%p\n", (void *)x);
|
||||
free(x);
|
||||
free(x);
|
||||
fprintf(stderr, "should have failed in the second free(%p)\n", x);
|
||||
fprintf(stderr, "should have failed in the second free(%p)\n", (void *)x);
|
||||
abort();
|
||||
}
|
||||
|
||||
@ -569,17 +569,6 @@ TEST(AddressSanitizer, LongJmpTest) {
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) // Only basic longjmp is available on Windows.
|
||||
NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
|
||||
// create three red zones for these two stack objects.
|
||||
int a;
|
||||
int b;
|
||||
|
||||
int *A = Ident(&a);
|
||||
int *B = Ident(&b);
|
||||
*A = *B;
|
||||
__builtin_longjmp((void**)buf, 1);
|
||||
}
|
||||
|
||||
NOINLINE void UnderscopeLongJmpFunc1(jmp_buf buf) {
|
||||
// create three red zones for these two stack objects.
|
||||
int a;
|
||||
@ -604,7 +593,19 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {
|
||||
|
||||
#if !defined(__ANDROID__) && !defined(__arm__) && \
|
||||
!defined(__powerpc64__) && !defined(__powerpc__) && \
|
||||
!defined(__aarch64__)
|
||||
!defined(__aarch64__) && !defined(__mips__) && \
|
||||
!defined(__mips64)
|
||||
NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
|
||||
// create three red zones for these two stack objects.
|
||||
int a;
|
||||
int b;
|
||||
|
||||
int *A = Ident(&a);
|
||||
int *B = Ident(&b);
|
||||
*A = *B;
|
||||
__builtin_longjmp((void**)buf, 1);
|
||||
}
|
||||
|
||||
// Does not work on Power and ARM:
|
||||
// https://code.google.com/p/address-sanitizer/issues/detail?id=185
|
||||
TEST(AddressSanitizer, BuiltinLongJmpTest) {
|
||||
@ -616,7 +617,8 @@ TEST(AddressSanitizer, BuiltinLongJmpTest) {
|
||||
}
|
||||
}
|
||||
#endif // !defined(__ANDROID__) && !defined(__powerpc64__) &&
|
||||
// !defined(__powerpc__) && !defined(__arm__)
|
||||
// !defined(__powerpc__) && !defined(__arm__) &&
|
||||
// !defined(__mips__) && !defined(__mips64)
|
||||
|
||||
TEST(AddressSanitizer, UnderscopeLongJmpTest) {
|
||||
static jmp_buf buf;
|
||||
@ -1243,7 +1245,7 @@ TEST(AddressSanitizer, DISABLED_DemoTooMuchMemoryTest) {
|
||||
const size_t kAllocSize = (1 << 28) - 1024;
|
||||
size_t total_size = 0;
|
||||
while (true) {
|
||||
char *x = (char*)malloc(kAllocSize);
|
||||
void *x = malloc(kAllocSize);
|
||||
memset(x, 0, kAllocSize);
|
||||
total_size += kAllocSize;
|
||||
fprintf(stderr, "total: %ldM %p\n", (long)total_size >> 20, x);
|
||||
|
@ -44,6 +44,7 @@ set(GENERIC_SOURCES
|
||||
enable_execute_stack.c
|
||||
eprintf.c
|
||||
extendsfdf2.c
|
||||
extendhfsf2.c
|
||||
ffsdi2.c
|
||||
ffsti2.c
|
||||
fixdfdi.c
|
||||
@ -123,7 +124,9 @@ set(GENERIC_SOURCES
|
||||
subvti3.c
|
||||
subtf3.c
|
||||
trampoline_setup.c
|
||||
truncdfhf2.c
|
||||
truncdfsf2.c
|
||||
truncsfhf2.c
|
||||
ucmpdi2.c
|
||||
ucmpti2.c
|
||||
udivdi3.c
|
||||
@ -151,6 +154,12 @@ set(x86_64_SOURCES
|
||||
x86_64/floatundixf.S
|
||||
${GENERIC_SOURCES})
|
||||
|
||||
if(WIN32)
|
||||
set(x86_64_SOURCES
|
||||
${x86_64_SOURCES}
|
||||
x86_64/chkstk.S)
|
||||
endif()
|
||||
|
||||
set(i386_SOURCES
|
||||
i386/ashldi3.S
|
||||
i386/ashrdi3.S
|
||||
@ -168,6 +177,12 @@ set(i386_SOURCES
|
||||
i386/umoddi3.S
|
||||
${GENERIC_SOURCES})
|
||||
|
||||
if(WIN32)
|
||||
set(i386_SOURCES
|
||||
${i386_SOURCES}
|
||||
i386/chkstk.S)
|
||||
endif()
|
||||
|
||||
set(i686_SOURCES
|
||||
${i386_SOURCES})
|
||||
|
||||
@ -257,7 +272,7 @@ set(arm_SOURCES
|
||||
|
||||
add_custom_target(builtins)
|
||||
|
||||
if (NOT WIN32)
|
||||
if (NOT WIN32 OR MINGW)
|
||||
foreach (arch x86_64 i386 i686 arm)
|
||||
if (CAN_TARGET_${arch})
|
||||
# Filter out generic versions of routines that are re-implemented in
|
||||
|
19
lib/builtins/atomic_flag_clear.c
Normal file
19
lib/builtins/atomic_flag_clear.c
Normal file
@ -0,0 +1,19 @@
|
||||
/*===-- atomic_flag_clear.c -------------------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===------------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements atomic_flag_clear from C11's 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);
|
||||
}
|
20
lib/builtins/atomic_flag_clear_explicit.c
Normal file
20
lib/builtins/atomic_flag_clear_explicit.c
Normal file
@ -0,0 +1,20 @@
|
||||
/*===-- atomic_flag_clear_explicit.c ----------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===------------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements atomic_flag_clear_explicit from C11's 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);
|
||||
}
|
19
lib/builtins/atomic_flag_test_and_set.c
Normal file
19
lib/builtins/atomic_flag_test_and_set.c
Normal file
@ -0,0 +1,19 @@
|
||||
/*===-- atomic_flag_test_and_set.c ------------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===------------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements atomic_flag_test_and_set from C11's 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);
|
||||
}
|
20
lib/builtins/atomic_flag_test_and_set_explicit.c
Normal file
20
lib/builtins/atomic_flag_test_and_set_explicit.c
Normal file
@ -0,0 +1,20 @@
|
||||
/*===-- atomic_flag_test_and_set_explicit.c ---------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===------------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements atomic_flag_test_and_set_explicit from C11's 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);
|
||||
}
|
19
lib/builtins/atomic_signal_fence.c
Normal file
19
lib/builtins/atomic_signal_fence.c
Normal file
@ -0,0 +1,19 @@
|
||||
/*===-- atomic_signal_fence.c -----------------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===------------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements atomic_signal_fence from C11's stdatomic.h.
|
||||
*
|
||||
*===------------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include <stdatomic.h>
|
||||
#undef atomic_signal_fence
|
||||
void atomic_signal_fence(memory_order order) {
|
||||
__c11_atomic_signal_fence(order);
|
||||
}
|
19
lib/builtins/atomic_thread_fence.c
Normal file
19
lib/builtins/atomic_thread_fence.c
Normal file
@ -0,0 +1,19 @@
|
||||
/*===-- atomic_thread_fence.c -----------------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===------------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements atomic_thread_fence from C11's stdatomic.h.
|
||||
*
|
||||
*===------------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include <stdatomic.h>
|
||||
#undef atomic_thread_fence
|
||||
void atomic_thread_fence(memory_order order) {
|
||||
__c11_atomic_thread_fence(order);
|
||||
}
|
@ -9,11 +9,12 @@
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#if __APPLE__
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#endif
|
||||
#if defined(__FreeBSD__) && defined(__arm__)
|
||||
#if (defined(__FreeBSD__) || defined(__Bitrig__)) && defined(__arm__)
|
||||
#include <sys/types.h>
|
||||
#include <machine/sysarch.h>
|
||||
#endif
|
||||
@ -25,6 +26,7 @@
|
||||
#if defined(__mips__)
|
||||
#include <sys/cachectl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#if defined(__ANDROID__) && defined(__LP64__)
|
||||
/*
|
||||
* clear_mips_cache - Invalidates instruction cache for Mips.
|
||||
@ -89,7 +91,7 @@ void __clear_cache(void *start, void *end) {
|
||||
* so there is nothing to do
|
||||
*/
|
||||
#elif defined(__arm__) && !defined(__APPLE__)
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__Bitrig__)
|
||||
struct arm_sync_icache_args arg;
|
||||
|
||||
arg.addr = (uintptr_t)start;
|
||||
@ -126,6 +128,7 @@ void __clear_cache(void *start, void *end) {
|
||||
#elif defined(__aarch64__) && !defined(__APPLE__)
|
||||
uint64_t xstart = (uint64_t)(uintptr_t) start;
|
||||
uint64_t xend = (uint64_t)(uintptr_t) end;
|
||||
uint64_t addr;
|
||||
|
||||
// Get Cache Type Info
|
||||
uint64_t ctr_el0;
|
||||
@ -136,12 +139,12 @@ void __clear_cache(void *start, void *end) {
|
||||
* uintptr_t in case this runs in an IPL32 environment.
|
||||
*/
|
||||
const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
|
||||
for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size)
|
||||
for (addr = xstart; addr < xend; addr += dcache_line_size)
|
||||
__asm __volatile("dc cvau, %0" :: "r"(addr));
|
||||
__asm __volatile("dsb ish");
|
||||
|
||||
const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
|
||||
for (uint64_t addr = xstart; addr < xend; addr += icache_line_size)
|
||||
for (addr = xstart; addr < xend; addr += icache_line_size)
|
||||
__asm __volatile("ic ivau, %0" :: "r"(addr));
|
||||
__asm __volatile("isb sy");
|
||||
#else
|
||||
|
@ -10,7 +10,9 @@
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
/* #include "config.h"
|
||||
* FIXME: CMake - include when cmake system is ready.
|
||||
@ -18,9 +20,14 @@
|
||||
*/
|
||||
#define HAVE_SYSCONF 1
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#else
|
||||
#ifndef __APPLE__
|
||||
#include <unistd.h>
|
||||
#endif /* __APPLE__ */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if __LP64__
|
||||
#define TRAMPOLINE_SIZE 48
|
||||
@ -40,6 +47,12 @@ COMPILER_RT_ABI void
|
||||
__enable_execute_stack(void* addr)
|
||||
{
|
||||
|
||||
#if _WIN32
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
if (!VirtualQuery (addr, &mbi, sizeof(mbi)))
|
||||
return; /* We should probably assert here because there is no return value */
|
||||
VirtualProtect (mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);
|
||||
#else
|
||||
#if __APPLE__
|
||||
/* On Darwin, pagesize is always 4096 bytes */
|
||||
const uintptr_t pageSize = 4096;
|
||||
@ -55,4 +68,5 @@ __enable_execute_stack(void* addr)
|
||||
unsigned char* endPage = (unsigned char*)((p+TRAMPOLINE_SIZE+pageSize) & pageAlignMask);
|
||||
size_t length = endPage - startPage;
|
||||
(void) mprotect((void *)startPage, length, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#endif
|
||||
}
|
||||
|
23
lib/builtins/extendhfsf2.c
Normal file
23
lib/builtins/extendhfsf2.c
Normal file
@ -0,0 +1,23 @@
|
||||
//===-- lib/extendhfsf2.c - half -> single conversion -------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
#define SRC_HALF
|
||||
#define DST_SINGLE
|
||||
#include "fp_extend_impl.inc"
|
||||
|
||||
// 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) {
|
||||
return __extendXfYf2__(a);
|
||||
}
|
||||
|
||||
COMPILER_RT_ABI float __gnu_h2f_ieee(uint16_t a) {
|
||||
return __extendhfsf2(a);
|
||||
}
|
@ -6,40 +6,41 @@
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __fixdfdi for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: convert a to a signed long long, rounding toward zero. */
|
||||
|
||||
/* Assumption: double is a IEEE 64 bit floating point type
|
||||
* su_int is a 32 bit integral type
|
||||
* value in double is representable in di_int (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
|
||||
|
||||
#define DOUBLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
ARM_EABI_FNALIAS(d2lz, fixdfdi)
|
||||
|
||||
#ifndef __SOFT_FP__
|
||||
/* Support for systems that have hardware floating-point; can set the invalid
|
||||
* flag as a side-effect of computation.
|
||||
*/
|
||||
|
||||
COMPILER_RT_ABI du_int __fixunsdfdi(double a);
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__fixdfdi(double a)
|
||||
{
|
||||
double_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
|
||||
if (e < 0)
|
||||
return 0;
|
||||
di_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
|
||||
dwords r;
|
||||
r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
|
||||
r.s.low = fb.u.s.low;
|
||||
if (e > 52)
|
||||
r.all <<= (e - 52);
|
||||
else
|
||||
r.all >>= (52 - e);
|
||||
return (r.all ^ s) - s;
|
||||
}
|
||||
if (a < 0.0) {
|
||||
return -__fixunsdfdi(-a);
|
||||
}
|
||||
return __fixunsdfdi(a);
|
||||
}
|
||||
|
||||
#else
|
||||
/* Support for systems that don't have hardware floating-point; there are no
|
||||
* flags to set, and we don't want to code-gen to an unknown soft-float
|
||||
* implementation.
|
||||
*/
|
||||
|
||||
typedef di_int fixint_t;
|
||||
typedef du_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__fixdfdi(fp_t a) {
|
||||
return __fixint(a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,50 +1,22 @@
|
||||
//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements double-precision to integer conversion for the
|
||||
// compiler-rt library. No range checking is performed; the behavior of this
|
||||
// conversion is undefined for out of range values in the C standard.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/* ===-- fixdfsi.c - Implement __fixdfsi -----------------------------------===
|
||||
*
|
||||
* 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"
|
||||
|
||||
#include "int_lib.h"
|
||||
typedef si_int fixint_t;
|
||||
typedef su_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
ARM_EABI_FNALIAS(d2iz, fixdfsi)
|
||||
|
||||
COMPILER_RT_ABI int
|
||||
COMPILER_RT_ABI si_int
|
||||
__fixdfsi(fp_t a) {
|
||||
|
||||
// Break a into sign, exponent, significand
|
||||
const rep_t aRep = toRep(a);
|
||||
const rep_t aAbs = aRep & absMask;
|
||||
const int sign = aRep & signBit ? -1 : 1;
|
||||
const int exponent = (aAbs >> significandBits) - exponentBias;
|
||||
const rep_t significand = (aAbs & significandMask) | implicitBit;
|
||||
|
||||
// If 0 < exponent < significandBits, right shift to get the result.
|
||||
if ((unsigned int)exponent < significandBits) {
|
||||
return sign * (significand >> (significandBits - exponent));
|
||||
}
|
||||
|
||||
// If exponent is negative, the result is zero.
|
||||
else if (exponent < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If significandBits < exponent, left shift to get the result. This shift
|
||||
// may end up being larger than the type width, which incurs undefined
|
||||
// behavior, but the conversion itself is undefined in that case, so
|
||||
// whatever the compiler decides to do is fine.
|
||||
else {
|
||||
return sign * (significand << (exponent - significandBits));
|
||||
}
|
||||
return __fixint(a);
|
||||
}
|
||||
|
@ -6,40 +6,21 @@
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __fixdfti for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#ifdef CRT_HAS_128BIT
|
||||
#define DOUBLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
/* Returns: convert a to a signed long long, rounding toward zero. */
|
||||
|
||||
/* Assumption: double is a IEEE 64 bit floating point type
|
||||
* su_int is a 32 bit integral type
|
||||
* value in double is representable in ti_int (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
|
||||
typedef ti_int fixint_t;
|
||||
typedef tu_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI ti_int
|
||||
__fixdfti(double a)
|
||||
{
|
||||
double_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
|
||||
if (e < 0)
|
||||
return 0;
|
||||
ti_int s = (si_int)(fb.u.s.high & 0x80000000) >> 31;
|
||||
ti_int r = 0x0010000000000000uLL | (0x000FFFFFFFFFFFFFuLL & fb.u.all);
|
||||
if (e > 52)
|
||||
r <<= (e - 52);
|
||||
else
|
||||
r >>= (52 - e);
|
||||
return (r ^ s) - s;
|
||||
__fixdfti(fp_t a) {
|
||||
return __fixint(a);
|
||||
}
|
||||
|
||||
#endif /* CRT_HAS_128BIT */
|
||||
|
@ -1,43 +1,47 @@
|
||||
/* ===-- fixsfdi.c - Implement __fixsfdi -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
* 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 __fixsfdi for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: convert a to a signed long long, rounding toward zero. */
|
||||
|
||||
/* Assumption: float is a IEEE 32 bit floating point type
|
||||
* su_int is a 32 bit integral type
|
||||
* value in float is representable in di_int (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
ARM_EABI_FNALIAS(f2lz, fixsfdi)
|
||||
|
||||
#ifndef __SOFT_FP__
|
||||
/* Support for systems that have hardware floating-point; can set the invalid
|
||||
* flag as a side-effect of computation.
|
||||
*/
|
||||
|
||||
COMPILER_RT_ABI du_int __fixunssfdi(float a);
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__fixsfdi(float a)
|
||||
{
|
||||
float_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u & 0x7F800000) >> 23) - 127;
|
||||
if (e < 0)
|
||||
return 0;
|
||||
di_int s = (si_int)(fb.u & 0x80000000) >> 31;
|
||||
di_int r = (fb.u & 0x007FFFFF) | 0x00800000;
|
||||
if (e > 23)
|
||||
r <<= (e - 23);
|
||||
else
|
||||
r >>= (23 - e);
|
||||
return (r ^ s) - s;
|
||||
if (a < 0.0f) {
|
||||
return -__fixunssfdi(-a);
|
||||
}
|
||||
return __fixunssfdi(a);
|
||||
}
|
||||
|
||||
#else
|
||||
/* Support for systems that don't have hardware floating-point; there are no
|
||||
* flags to set, and we don't want to code-gen to an unknown soft-float
|
||||
* implementation.
|
||||
*/
|
||||
|
||||
typedef di_int fixint_t;
|
||||
typedef du_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__fixsfdi(fp_t a) {
|
||||
return __fixint(a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,47 +1,22 @@
|
||||
//===-- lib/fixsfsi.c - Single-precision -> integer conversion ----*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements single-precision to integer conversion for the
|
||||
// compiler-rt library. No range checking is performed; the behavior of this
|
||||
// conversion is undefined for out of range values in the C standard.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/* ===-- fixsfsi.c - Implement __fixsfsi -----------------------------------===
|
||||
*
|
||||
* 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"
|
||||
typedef si_int fixint_t;
|
||||
typedef su_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
ARM_EABI_FNALIAS(f2iz, fixsfsi)
|
||||
|
||||
COMPILER_RT_ABI int
|
||||
COMPILER_RT_ABI si_int
|
||||
__fixsfsi(fp_t a) {
|
||||
// Break a into sign, exponent, significand
|
||||
const rep_t aRep = toRep(a);
|
||||
const rep_t aAbs = aRep & absMask;
|
||||
const int sign = aRep & signBit ? -1 : 1;
|
||||
const int exponent = (aAbs >> significandBits) - exponentBias;
|
||||
const rep_t significand = (aAbs & significandMask) | implicitBit;
|
||||
|
||||
// If 0 < exponent < significandBits, right shift to get the result.
|
||||
if ((unsigned int)exponent < significandBits) {
|
||||
return sign * (significand >> (significandBits - exponent));
|
||||
}
|
||||
|
||||
// If exponent is negative, the result is zero.
|
||||
else if (exponent < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If significandBits < exponent, left shift to get the result. This shift
|
||||
// may end up being larger than the type width, which incurs undefined
|
||||
// behavior, but the conversion itself is undefined in that case, so
|
||||
// whatever the compiler decides to do is fine.
|
||||
else {
|
||||
return sign * (significand << (exponent - significandBits));
|
||||
}
|
||||
return __fixint(a);
|
||||
}
|
||||
|
@ -6,40 +6,21 @@
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __fixsfti for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#ifdef CRT_HAS_128BIT
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
/* Returns: convert a to a signed long long, rounding toward zero. */
|
||||
|
||||
/* Assumption: float is a IEEE 32 bit floating point type
|
||||
* su_int is a 32 bit integral type
|
||||
* value in float is representable in ti_int (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
|
||||
typedef ti_int fixint_t;
|
||||
typedef tu_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI ti_int
|
||||
__fixsfti(float a)
|
||||
{
|
||||
float_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u & 0x7F800000) >> 23) - 127;
|
||||
if (e < 0)
|
||||
return 0;
|
||||
ti_int s = (si_int)(fb.u & 0x80000000) >> 31;
|
||||
ti_int r = (fb.u & 0x007FFFFF) | 0x00800000;
|
||||
if (e > 23)
|
||||
r <<= (e - 23);
|
||||
else
|
||||
r >>= (23 - e);
|
||||
return (r ^ s) - s;
|
||||
__fixsfti(fp_t a) {
|
||||
return __fixint(a);
|
||||
}
|
||||
|
||||
#endif /* CRT_HAS_128BIT */
|
||||
|
23
lib/builtins/fixtfdi.c
Normal file
23
lib/builtins/fixtfdi.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* ===-- fixtfdi.c - Implement __fixtfdi -----------------------------------===
|
||||
*
|
||||
* 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 QUAD_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
|
||||
typedef di_int fixint_t;
|
||||
typedef du_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__fixtfdi(fp_t a) {
|
||||
return __fixint(a);
|
||||
}
|
||||
#endif
|
23
lib/builtins/fixtfsi.c
Normal file
23
lib/builtins/fixtfsi.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* ===-- fixtfsi.c - Implement __fixtfsi -----------------------------------===
|
||||
*
|
||||
* 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 QUAD_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
|
||||
typedef si_int fixint_t;
|
||||
typedef su_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI si_int
|
||||
__fixtfsi(fp_t a) {
|
||||
return __fixint(a);
|
||||
}
|
||||
#endif
|
23
lib/builtins/fixtfti.c
Normal file
23
lib/builtins/fixtfti.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* ===-- fixtfti.c - Implement __fixtfti -----------------------------------===
|
||||
*
|
||||
* 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 QUAD_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
|
||||
typedef ti_int fixint_t;
|
||||
typedef tu_int fixuint_t;
|
||||
#include "fp_fixint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI ti_int
|
||||
__fixtfti(fp_t a) {
|
||||
return __fixint(a);
|
||||
}
|
||||
#endif
|
@ -6,42 +6,39 @@
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __fixunsdfdi for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: convert a to a unsigned long long, rounding toward zero.
|
||||
* Negative values all become zero.
|
||||
*/
|
||||
|
||||
/* Assumption: double is a IEEE 64 bit floating point type
|
||||
* du_int is a 64 bit integral type
|
||||
* value in double is representable in du_int or is negative
|
||||
* (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
|
||||
#define DOUBLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
ARM_EABI_FNALIAS(d2ulz, fixunsdfdi)
|
||||
|
||||
#ifndef __SOFT_FP__
|
||||
/* Support for systems that have hardware floating-point; can set the invalid
|
||||
* flag as a side-effect of computation.
|
||||
*/
|
||||
|
||||
COMPILER_RT_ABI du_int
|
||||
__fixunsdfdi(double a)
|
||||
{
|
||||
double_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
|
||||
if (e < 0 || (fb.u.s.high & 0x80000000))
|
||||
return 0;
|
||||
udwords r;
|
||||
r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
|
||||
r.s.low = fb.u.s.low;
|
||||
if (e > 52)
|
||||
r.all <<= (e - 52);
|
||||
else
|
||||
r.all >>= (52 - e);
|
||||
return r.all;
|
||||
if (a <= 0.0) return 0;
|
||||
su_int high = a/0x1p32f;
|
||||
su_int low = a - (double)high*0x1p32f;
|
||||
return ((du_int)high << 32) | low;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Support for systems that don't have hardware floating-point; there are no
|
||||
* flags to set, and we don't want to code-gen to an unknown soft-float
|
||||
* implementation.
|
||||
*/
|
||||
|
||||
typedef du_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI du_int
|
||||
__fixunsdfdi(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -6,39 +6,16 @@
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __fixunsdfsi for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: convert a to a unsigned int, rounding toward zero.
|
||||
* Negative values all become zero.
|
||||
*/
|
||||
|
||||
/* Assumption: double is a IEEE 64 bit floating point type
|
||||
* su_int is a 32 bit integral type
|
||||
* value in double is representable in su_int or is negative
|
||||
* (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
|
||||
#define DOUBLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
typedef su_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
ARM_EABI_FNALIAS(d2uiz, fixunsdfsi)
|
||||
|
||||
COMPILER_RT_ABI su_int
|
||||
__fixunsdfsi(double a)
|
||||
{
|
||||
double_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
|
||||
if (e < 0 || (fb.u.s.high & 0x80000000))
|
||||
return 0;
|
||||
return (
|
||||
0x80000000u |
|
||||
((fb.u.s.high & 0x000FFFFF) << 11) |
|
||||
(fb.u.s.low >> 21)
|
||||
) >> (31 - e);
|
||||
__fixunsdfsi(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
|
@ -6,42 +6,18 @@
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __fixunsdfti for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#ifdef CRT_HAS_128BIT
|
||||
|
||||
/* Returns: convert a to a unsigned long long, rounding toward zero.
|
||||
* Negative values all become zero.
|
||||
*/
|
||||
|
||||
/* Assumption: double is a IEEE 64 bit floating point type
|
||||
* tu_int is a 64 bit integral type
|
||||
* value in double is representable in tu_int or is negative
|
||||
* (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
|
||||
#define DOUBLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
typedef tu_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI tu_int
|
||||
__fixunsdfti(double a)
|
||||
{
|
||||
double_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
|
||||
if (e < 0 || (fb.u.s.high & 0x80000000))
|
||||
return 0;
|
||||
tu_int r = 0x0010000000000000uLL | (fb.u.all & 0x000FFFFFFFFFFFFFuLL);
|
||||
if (e > 52)
|
||||
r <<= (e - 52);
|
||||
else
|
||||
r >>= (52 - e);
|
||||
return r;
|
||||
__fixunsdfti(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
|
||||
#endif /* CRT_HAS_128BIT */
|
||||
|
@ -6,39 +6,40 @@
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __fixunssfdi for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
/* Returns: convert a to a unsigned long long, rounding toward zero.
|
||||
* Negative values all become zero.
|
||||
*/
|
||||
|
||||
/* Assumption: float is a IEEE 32 bit floating point type
|
||||
* du_int is a 64 bit integral type
|
||||
* value in float is representable in du_int or is negative
|
||||
* (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
ARM_EABI_FNALIAS(f2ulz, fixunssfdi)
|
||||
|
||||
#ifndef __SOFT_FP__
|
||||
/* Support for systems that have hardware floating-point; can set the invalid
|
||||
* flag as a side-effect of computation.
|
||||
*/
|
||||
|
||||
COMPILER_RT_ABI du_int
|
||||
__fixunssfdi(float a)
|
||||
{
|
||||
float_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u & 0x7F800000) >> 23) - 127;
|
||||
if (e < 0 || (fb.u & 0x80000000))
|
||||
return 0;
|
||||
du_int r = (fb.u & 0x007FFFFF) | 0x00800000;
|
||||
if (e > 23)
|
||||
r <<= (e - 23);
|
||||
else
|
||||
r >>= (23 - e);
|
||||
return r;
|
||||
if (a <= 0.0f) return 0;
|
||||
double da = a;
|
||||
su_int high = da/0x1p32f;
|
||||
su_int low = da - (double)high*0x1p32f;
|
||||
return ((du_int)high << 32) | low;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Support for systems that don't have hardware floating-point; there are no
|
||||
* flags to set, and we don't want to code-gen to an unknown soft-float
|
||||
* implementation.
|
||||
*/
|
||||
|
||||
typedef du_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI du_int
|
||||
__fixunssfdi(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -12,34 +12,14 @@
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: convert a to a unsigned int, rounding toward zero.
|
||||
* Negative values all become zero.
|
||||
*/
|
||||
|
||||
/* Assumption: float is a IEEE 32 bit floating point type
|
||||
* su_int is a 32 bit integral type
|
||||
* value in float is representable in su_int or is negative
|
||||
* (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
typedef su_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
ARM_EABI_FNALIAS(f2uiz, fixunssfsi)
|
||||
|
||||
COMPILER_RT_ABI su_int
|
||||
__fixunssfsi(float a)
|
||||
{
|
||||
float_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u & 0x7F800000) >> 23) - 127;
|
||||
if (e < 0 || (fb.u & 0x80000000))
|
||||
return 0;
|
||||
su_int r = (fb.u & 0x007FFFFF) | 0x00800000;
|
||||
if (e > 23)
|
||||
r <<= (e - 23);
|
||||
else
|
||||
r >>= (23 - e);
|
||||
return r;
|
||||
__fixunssfsi(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
|
@ -12,36 +12,15 @@
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
#ifdef CRT_HAS_128BIT
|
||||
|
||||
/* Returns: convert a to a unsigned long long, rounding toward zero.
|
||||
* Negative values all become zero.
|
||||
*/
|
||||
|
||||
/* Assumption: float is a IEEE 32 bit floating point type
|
||||
* tu_int is a 64 bit integral type
|
||||
* value in float is representable in tu_int or is negative
|
||||
* (no range checking performed)
|
||||
*/
|
||||
|
||||
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
|
||||
#if defined(CRT_HAS_128BIT)
|
||||
typedef tu_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI tu_int
|
||||
__fixunssfti(float a)
|
||||
{
|
||||
float_bits fb;
|
||||
fb.f = a;
|
||||
int e = ((fb.u & 0x7F800000) >> 23) - 127;
|
||||
if (e < 0 || (fb.u & 0x80000000))
|
||||
return 0;
|
||||
tu_int r = (fb.u & 0x007FFFFF) | 0x00800000;
|
||||
if (e > 23)
|
||||
r <<= (e - 23);
|
||||
else
|
||||
r >>= (23 - e);
|
||||
return r;
|
||||
__fixunssfti(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
|
||||
#endif /* CRT_HAS_128BIT */
|
||||
#endif
|
||||
|
22
lib/builtins/fixunstfdi.c
Normal file
22
lib/builtins/fixunstfdi.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* ===-- fixunstfdi.c - Implement __fixunstfdi -----------------------------===
|
||||
*
|
||||
* 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 QUAD_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
|
||||
typedef du_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI du_int
|
||||
__fixunstfdi(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
#endif
|
22
lib/builtins/fixunstfsi.c
Normal file
22
lib/builtins/fixunstfsi.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===
|
||||
*
|
||||
* 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 QUAD_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
|
||||
typedef su_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI su_int
|
||||
__fixunstfsi(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
#endif
|
22
lib/builtins/fixunstfti.c
Normal file
22
lib/builtins/fixunstfti.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* ===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===
|
||||
*
|
||||
* 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 QUAD_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT)
|
||||
typedef tu_int fixuint_t;
|
||||
#include "fp_fixuint_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI tu_int
|
||||
__fixunstfti(fp_t a) {
|
||||
return __fixuint(a);
|
||||
}
|
||||
#endif
|
@ -38,6 +38,8 @@ __fixunsxfdi(long double a)
|
||||
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
|
||||
if (e < 0 || (fb.u.high.s.low & 0x00008000))
|
||||
return 0;
|
||||
if ((unsigned)e > sizeof(du_int) * CHAR_BIT)
|
||||
return ~(du_int)0;
|
||||
return fb.u.low.all >> (63 - e);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
|
||||
* su_int is a 32 bit integral type
|
||||
* value in long double is representable in su_int or is negative
|
||||
* (no range checking performed)
|
||||
*/
|
||||
|
||||
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
|
||||
@ -38,6 +37,8 @@ __fixunsxfsi(long double a)
|
||||
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
|
||||
if (e < 0 || (fb.u.high.s.low & 0x00008000))
|
||||
return 0;
|
||||
if ((unsigned)e > sizeof(su_int) * CHAR_BIT)
|
||||
return ~(su_int)0;
|
||||
return fb.u.low.s.high >> (31 - e);
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,8 @@
|
||||
*/
|
||||
|
||||
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
|
||||
* tu_int is a 64 bit integral type
|
||||
* tu_int is a 128 bit integral type
|
||||
* value in long double is representable in tu_int or is negative
|
||||
* (no range checking performed)
|
||||
*/
|
||||
|
||||
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
|
||||
@ -38,6 +37,8 @@ __fixunsxfti(long double a)
|
||||
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
|
||||
if (e < 0 || (fb.u.high.s.low & 0x00008000))
|
||||
return 0;
|
||||
if ((unsigned)e > sizeof(tu_int) * CHAR_BIT)
|
||||
return ~(tu_int)0;
|
||||
tu_int r = fb.u.low.all;
|
||||
if (e > 63)
|
||||
r <<= (e - 63);
|
||||
|
@ -19,7 +19,7 @@
|
||||
/* Returns: convert a to a signed long long, rounding toward zero. */
|
||||
|
||||
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
|
||||
* su_int is a 32 bit integral type
|
||||
* di_int is a 64 bit integral type
|
||||
* value in long double is representable in di_int (no range checking performed)
|
||||
*/
|
||||
|
||||
@ -30,11 +30,15 @@
|
||||
COMPILER_RT_ABI di_int
|
||||
__fixxfdi(long double a)
|
||||
{
|
||||
const di_int di_max = (di_int)((~(du_int)0) / 2);
|
||||
const di_int di_min = -di_max - 1;
|
||||
long_double_bits fb;
|
||||
fb.f = a;
|
||||
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
|
||||
if (e < 0)
|
||||
return 0;
|
||||
if ((unsigned)e >= sizeof(di_int) * CHAR_BIT)
|
||||
return a > 0 ? di_max : di_min;
|
||||
di_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15);
|
||||
di_int r = fb.u.low.all;
|
||||
r = (du_int)r >> (63 - e);
|
||||
|
@ -19,8 +19,8 @@
|
||||
/* Returns: convert a to a signed long long, rounding toward zero. */
|
||||
|
||||
/* Assumption: long double is an intel 80 bit floating point type padded with 6 bytes
|
||||
* su_int is a 32 bit integral type
|
||||
* value in long double is representable in ti_int (no range checking performed)
|
||||
* ti_int is a 128 bit integral type
|
||||
* value in long double is representable in ti_int
|
||||
*/
|
||||
|
||||
/* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee eeee |
|
||||
@ -30,6 +30,8 @@
|
||||
COMPILER_RT_ABI ti_int
|
||||
__fixxfti(long double a)
|
||||
{
|
||||
const ti_int ti_max = (ti_int)((~(tu_int)0) / 2);
|
||||
const ti_int ti_min = -ti_max - 1;
|
||||
long_double_bits fb;
|
||||
fb.f = a;
|
||||
int e = (fb.u.high.s.low & 0x00007FFF) - 16383;
|
||||
@ -37,6 +39,8 @@ __fixxfti(long double a)
|
||||
return 0;
|
||||
ti_int s = -(si_int)((fb.u.high.s.low & 0x00008000) >> 15);
|
||||
ti_int r = fb.u.low.all;
|
||||
if ((unsigned)e >= sizeof(ti_int) * CHAR_BIT)
|
||||
return a > 0 ? ti_max : ti_min;
|
||||
if (e > 63)
|
||||
r <<= (e - 63);
|
||||
else
|
||||
|
@ -39,11 +39,24 @@ static inline int src_rep_t_clz(src_rep_t a) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined SRC_HALF
|
||||
typedef uint16_t src_t;
|
||||
typedef uint16_t src_rep_t;
|
||||
#define SRC_REP_C UINT16_C
|
||||
static const int srcSigBits = 10;
|
||||
#define src_rep_t_clz __builtin_clz
|
||||
|
||||
#else
|
||||
#error Source should be single precision or double precision!
|
||||
#error Source should be half, single, or double precision!
|
||||
#endif //end source precision
|
||||
|
||||
#if defined DST_DOUBLE
|
||||
#if defined DST_SINGLE
|
||||
typedef float dst_t;
|
||||
typedef uint32_t dst_rep_t;
|
||||
#define DST_REP_C UINT32_C
|
||||
static const int dstSigBits = 23;
|
||||
|
||||
#elif defined DST_DOUBLE
|
||||
typedef double dst_t;
|
||||
typedef uint64_t dst_rep_t;
|
||||
#define DST_REP_C UINT64_C
|
||||
@ -56,7 +69,7 @@ typedef __uint128_t dst_rep_t;
|
||||
static const int dstSigBits = 112;
|
||||
|
||||
#else
|
||||
#error Destination should be double precision or quad precision!
|
||||
#error Destination should be single, double, or quad precision!
|
||||
#endif //end destination precision
|
||||
|
||||
// End of specialization parameters. Two helper routines for conversion to and
|
||||
|
@ -66,7 +66,9 @@ static inline dst_t __extendXfYf2__(src_t a) {
|
||||
const src_rep_t sign = aRep & srcSignMask;
|
||||
dst_rep_t absResult;
|
||||
|
||||
if (aAbs - srcMinNormal < srcInfinity - srcMinNormal) {
|
||||
// If sizeof(src_rep_t) < sizeof(int), the subtraction result is promoted
|
||||
// to (signed) int. To avoid that, explicitly cast to src_rep_t.
|
||||
if ((src_rep_t)(aAbs - srcMinNormal) < srcInfinity - srcMinNormal) {
|
||||
// a is a normal number.
|
||||
// Extend to the destination type by shifting the significand and
|
||||
// exponent into the proper position and rebiasing the exponent.
|
||||
|
41
lib/builtins/fp_fixint_impl.inc
Normal file
41
lib/builtins/fp_fixint_impl.inc
Normal file
@ -0,0 +1,41 @@
|
||||
//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements float to integer conversion for the
|
||||
// compiler-rt library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "fp_lib.h"
|
||||
|
||||
static inline fixint_t __fixint(fp_t a) {
|
||||
const fixint_t fixint_max = (fixint_t)((~(fixuint_t)0) / 2);
|
||||
const fixint_t fixint_min = -fixint_max - 1;
|
||||
// Break a into sign, exponent, significand
|
||||
const rep_t aRep = toRep(a);
|
||||
const rep_t aAbs = aRep & absMask;
|
||||
const fixint_t sign = aRep & signBit ? -1 : 1;
|
||||
const int exponent = (aAbs >> significandBits) - exponentBias;
|
||||
const rep_t significand = (aAbs & significandMask) | implicitBit;
|
||||
|
||||
// If exponent is negative, the result is zero.
|
||||
if (exponent < 0)
|
||||
return 0;
|
||||
|
||||
// If the value is too large for the integer type, saturate.
|
||||
if ((unsigned)exponent >= sizeof(fixint_t) * CHAR_BIT)
|
||||
return sign == 1 ? fixint_max : fixint_min;
|
||||
|
||||
// If 0 <= exponent < significandBits, right shift to get the result.
|
||||
// Otherwise, shift left.
|
||||
if (exponent < significandBits)
|
||||
return sign * (significand >> (significandBits - exponent));
|
||||
else
|
||||
return sign * ((fixint_t)significand << (exponent - significandBits));
|
||||
}
|
39
lib/builtins/fp_fixuint_impl.inc
Normal file
39
lib/builtins/fp_fixuint_impl.inc
Normal file
@ -0,0 +1,39 @@
|
||||
//===-- lib/fixdfsi.c - Double-precision -> integer conversion ----*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements float to unsigned integer conversion for the
|
||||
// compiler-rt library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "fp_lib.h"
|
||||
|
||||
static inline fixuint_t __fixuint(fp_t a) {
|
||||
// Break a into sign, exponent, significand
|
||||
const rep_t aRep = toRep(a);
|
||||
const rep_t aAbs = aRep & absMask;
|
||||
const int sign = aRep & signBit ? -1 : 1;
|
||||
const int exponent = (aAbs >> significandBits) - exponentBias;
|
||||
const rep_t significand = (aAbs & significandMask) | implicitBit;
|
||||
|
||||
// If either the value or the exponent is negative, the result is zero.
|
||||
if (sign == -1 || exponent < 0)
|
||||
return 0;
|
||||
|
||||
// If the value is too large for the integer type, saturate.
|
||||
if ((unsigned)exponent > sizeof(fixuint_t) * CHAR_BIT)
|
||||
return ~(fixuint_t)0;
|
||||
|
||||
// If 0 <= exponent < significandBits, right shift to get the result.
|
||||
// Otherwise, shift left.
|
||||
if (exponent < significandBits)
|
||||
return significand >> (significandBits - exponent);
|
||||
else
|
||||
return (fixuint_t)significand << (exponent - significandBits);
|
||||
}
|
@ -16,7 +16,13 @@
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if defined SRC_DOUBLE
|
||||
#if defined SRC_SINGLE
|
||||
typedef float src_t;
|
||||
typedef uint32_t src_rep_t;
|
||||
#define SRC_REP_C UINT32_C
|
||||
static const int srcSigBits = 23;
|
||||
|
||||
#elif defined SRC_DOUBLE
|
||||
typedef double src_t;
|
||||
typedef uint64_t src_rep_t;
|
||||
#define SRC_REP_C UINT64_C
|
||||
@ -44,6 +50,12 @@ typedef uint32_t dst_rep_t;
|
||||
#define DST_REP_C UINT32_C
|
||||
static const int dstSigBits = 23;
|
||||
|
||||
#elif defined DST_HALF
|
||||
typedef uint16_t dst_t;
|
||||
typedef uint16_t dst_rep_t;
|
||||
#define DST_REP_C UINT16_C
|
||||
static const int dstSigBits = 10;
|
||||
|
||||
#else
|
||||
#error Destination should be single precision or double precision!
|
||||
#endif //end destination precision
|
||||
|
@ -99,7 +99,7 @@ static inline dst_t __truncXfYf2__(src_t a) {
|
||||
absResult |= dstQNaN;
|
||||
absResult |= ((aAbs & srcNaNCode) >> (srcSigBits - dstSigBits)) & dstNaNCode;
|
||||
}
|
||||
else if (aAbs > overflow) {
|
||||
else if (aAbs >= overflow) {
|
||||
// a overflows to infinity.
|
||||
absResult = (dst_rep_t)dstInfExp << dstSigBits;
|
||||
}
|
||||
|
34
lib/builtins/i386/chkstk.S
Normal file
34
lib/builtins/i386/chkstk.S
Normal file
@ -0,0 +1,34 @@
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
// _chkstk routine
|
||||
// This routine is windows specific
|
||||
// http://msdn.microsoft.com/en-us/library/ms648426.aspx
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
.text
|
||||
.balign 4
|
||||
DEFINE_COMPILERRT_FUNCTION(__chkstk_ms)
|
||||
push %ecx
|
||||
push %eax
|
||||
cmp $0x1000,%eax
|
||||
lea 12(%esp),%ecx
|
||||
jb 1f
|
||||
2:
|
||||
sub $0x1000,%ecx
|
||||
orl $0,(%ecx)
|
||||
sub $0x1000,%eax
|
||||
cmp $0x1000,%eax
|
||||
ja 2b
|
||||
1:
|
||||
sub %eax,%ecx
|
||||
orl $0,(%ecx)
|
||||
pop %eax
|
||||
pop %ecx
|
||||
ret
|
||||
END_COMPILERRT_FUNCTION(__chkstk_ms)
|
||||
|
||||
#endif // __i386__
|
@ -16,6 +16,20 @@
|
||||
#ifndef INT_ENDIANNESS_H
|
||||
#define INT_ENDIANNESS_H
|
||||
|
||||
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
|
||||
defined(__ORDER_LITTLE_ENDIAN__)
|
||||
|
||||
/* Clang and GCC provide built-in endianness definitions. */
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define _YUGA_LITTLE_ENDIAN 0
|
||||
#define _YUGA_BIG_ENDIAN 1
|
||||
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define _YUGA_LITTLE_ENDIAN 1
|
||||
#define _YUGA_BIG_ENDIAN 0
|
||||
#endif /* __BYTE_ORDER__ */
|
||||
|
||||
#else /* Compilers other than Clang or GCC. */
|
||||
|
||||
#if defined(__SVR4) && defined(__sun)
|
||||
#include <sys/byteorder.h>
|
||||
|
||||
@ -84,18 +98,6 @@
|
||||
|
||||
/* .. */
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define _YUGA_LITTLE_ENDIAN 0
|
||||
#define _YUGA_BIG_ENDIAN 1
|
||||
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define _YUGA_LITTLE_ENDIAN 1
|
||||
#define _YUGA_BIG_ENDIAN 0
|
||||
#endif /* __BYTE_ORDER__ */
|
||||
|
||||
#endif /* GNU/Linux */
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#define _YUGA_LITTLE_ENDIAN 1
|
||||
@ -103,6 +105,8 @@
|
||||
|
||||
#endif /* Windows */
|
||||
|
||||
#endif /* Clang or GCC. */
|
||||
|
||||
/* . */
|
||||
|
||||
#if !defined(_YUGA_LITTLE_ENDIAN) || !defined(_YUGA_BIG_ENDIAN)
|
||||
|
@ -28,7 +28,11 @@
|
||||
# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
|
||||
#else
|
||||
# define ARM_EABI_FNALIAS(aeabi_name, name)
|
||||
# define COMPILER_RT_ABI
|
||||
# if defined(__arm__) && defined(_WIN32)
|
||||
# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
|
||||
# else
|
||||
# define COMPILER_RT_ABI
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__) && (defined(_KERNEL) || defined(_STANDALONE))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user