forked from OSchip/llvm-project
[scudo] Implement stricter separation of C vs C++
Summary: Initially, Scudo had a monolithic design where both C and C++ functions were living in the same library. This was not necessarily ideal, and with the work on -fsanitize=scudo, it became more apparent that this needed to change. We are splitting the new/delete interceptor in their own C++ library. This allows more flexibility, notably with regard to std::bad_alloc when the work is done. This also allows us to not link new & delete when using pure C. Additionally, we add the UBSan runtimes with Scudo, in order to be able to have a -fsanitize=scudo,undefined in Clang (see work in D39334). The changes in this patch: - split the cxx specific code in the scudo cmake file into a new library; (remove the spurious foreach loop, that was not necessary) - add the UBSan runtimes (both C and C++); - change the test cmake file to allow for specific C & C++ tests; - make C tests pure C, rename their extension accordingly. Reviewers: alekseyshl Reviewed By: alekseyshl Subscribers: srhines, mgorny, llvm-commits Differential Revision: https://reviews.llvm.org/D39461 llvm-svn: 317097
This commit is contained in:
parent
2b09f39b4d
commit
d937b0a10c
|
@ -12,12 +12,14 @@ set(SCUDO_SOURCES
|
|||
scudo_flags.cpp
|
||||
scudo_crc32.cpp
|
||||
scudo_interceptors.cpp
|
||||
scudo_new_delete.cpp
|
||||
scudo_termination.cpp
|
||||
scudo_tsd_exclusive.cpp
|
||||
scudo_tsd_shared.cpp
|
||||
scudo_utils.cpp)
|
||||
|
||||
set(SCUDO_CXX_SOURCES
|
||||
scudo_new_delete.cpp)
|
||||
|
||||
# Enable the SSE 4.2 instruction set for scudo_crc32.cpp, if available.
|
||||
if (COMPILER_RT_HAS_MSSE4_2_FLAG)
|
||||
set_source_files_properties(scudo_crc32.cpp PROPERTIES COMPILE_FLAGS -msse4.2)
|
||||
|
@ -36,26 +38,35 @@ if(COMPILER_RT_HAS_SCUDO)
|
|||
append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread SCUDO_DYNAMIC_LIBS)
|
||||
append_list_if(COMPILER_RT_HAS_LIBLOG log SCUDO_DYNAMIC_LIBS)
|
||||
|
||||
foreach(arch ${SCUDO_SUPPORTED_ARCH})
|
||||
add_compiler_rt_runtime(clang_rt.scudo
|
||||
STATIC
|
||||
ARCHS ${arch}
|
||||
SOURCES ${SCUDO_SOURCES}
|
||||
OBJECT_LIBS RTSanitizerCommonNoTermination
|
||||
RTSanitizerCommonLibc
|
||||
RTInterception
|
||||
CFLAGS ${SCUDO_CFLAGS}
|
||||
PARENT_TARGET scudo)
|
||||
add_compiler_rt_runtime(clang_rt.scudo
|
||||
STATIC
|
||||
ARCHS ${SCUDO_SUPPORTED_ARCH}
|
||||
SOURCES ${SCUDO_SOURCES}
|
||||
OBJECT_LIBS RTSanitizerCommonNoTermination
|
||||
RTSanitizerCommonLibc
|
||||
RTInterception
|
||||
RTUbsan
|
||||
CFLAGS ${SCUDO_CFLAGS}
|
||||
PARENT_TARGET scudo)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.scudo
|
||||
SHARED
|
||||
ARCHS ${arch}
|
||||
SOURCES ${SCUDO_SOURCES}
|
||||
OBJECT_LIBS RTSanitizerCommonNoTermination
|
||||
RTSanitizerCommonLibc
|
||||
RTInterception
|
||||
CFLAGS ${SCUDO_CFLAGS}
|
||||
LINK_LIBS ${SCUDO_DYNAMIC_LIBS}
|
||||
PARENT_TARGET scudo)
|
||||
endforeach()
|
||||
add_compiler_rt_runtime(clang_rt.scudo_cxx
|
||||
STATIC
|
||||
ARCHS ${SCUDO_SUPPORTED_ARCH}
|
||||
SOURCES ${SCUDO_CXX_SOURCES}
|
||||
OBJECT_LIBS RTUbsan_cxx
|
||||
CFLAGS ${SCUDO_CFLAGS}
|
||||
PARENT_TARGET scudo)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.scudo
|
||||
SHARED
|
||||
ARCHS ${SCUDO_SUPPORTED_ARCH}
|
||||
SOURCES ${SCUDO_SOURCES} ${SCUDO_CXX_SOURCES}
|
||||
OBJECT_LIBS RTSanitizerCommonNoTermination
|
||||
RTSanitizerCommonLibc
|
||||
RTInterception
|
||||
RTUbsan
|
||||
RTUbsan_cxx
|
||||
CFLAGS ${SCUDO_CFLAGS}
|
||||
LINK_LIBS ${SCUDO_DYNAMIC_LIBS}
|
||||
PARENT_TARGET scudo)
|
||||
endif()
|
||||
|
|
|
@ -15,7 +15,7 @@ int main(int argc, char **argv)
|
|||
if (!strcmp(argv[1], "pointers")) {
|
||||
void *p = malloc(1U << 16);
|
||||
assert(p);
|
||||
free(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) | 1));
|
||||
free((void *)((uintptr_t)p | 1));
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo %s -o %t
|
||||
// RUN: %clangxx_scudo %s -o %t
|
||||
// RUN: not %run %t malloc 2>&1 | FileCheck %s
|
||||
// RUN: not %run %t new 2>&1 | FileCheck %s
|
||||
// RUN: not %run %t newarray 2>&1 | FileCheck %s
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo %s -lstdc++ -o %t
|
||||
// RUN: %clangxx_scudo %s -lstdc++ -o %t
|
||||
// RUN: %run %t ownership 2>&1
|
||||
// RUN: %run %t ownership-and-size 2>&1
|
||||
// RUN: %run %t heap-size 2>&1
|
||||
|
|
|
@ -11,21 +11,24 @@ config.test_source_root = os.path.dirname(__file__)
|
|||
# Path to the shared & static libraries
|
||||
shared_libscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo-%s.so" % config.target_arch)
|
||||
static_libscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo-%s.a" % config.target_arch)
|
||||
static_libscudo_cxx = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo_cxx-%s.a" % config.target_arch)
|
||||
|
||||
whole_archive = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % static_libscudo
|
||||
whole_archive_cxx = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % static_libscudo_cxx
|
||||
|
||||
# Test suffixes.
|
||||
config.suffixes = ['.c', '.cc', '.cpp']
|
||||
|
||||
# C flags.
|
||||
# C & CXX flags.
|
||||
c_flags = ([config.target_cflags] +
|
||||
["-std=c++11",
|
||||
"-pthread",
|
||||
["-pthread",
|
||||
"-fPIE",
|
||||
"-pie",
|
||||
"-O0",
|
||||
"-UNDEBUG",
|
||||
"-ldl",
|
||||
"-Wl,--gc-sections"])
|
||||
cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++11"])
|
||||
|
||||
# Android doesn't want -lrt.
|
||||
if not config.android:
|
||||
|
@ -37,6 +40,7 @@ def build_invocation(compile_flags):
|
|||
# Add clang substitutions.
|
||||
config.substitutions.append(("%clang ", build_invocation(c_flags)))
|
||||
config.substitutions.append(("%clang_scudo ", build_invocation(c_flags) + whole_archive))
|
||||
config.substitutions.append(("%clangxx_scudo ", build_invocation(cxx_flags) + whole_archive + whole_archive_cxx))
|
||||
config.substitutions.append(("%shared_libscudo", shared_libscudo))
|
||||
|
||||
# Platform-specific default SCUDO_OPTIONS for lit tests.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo %s -lstdc++ -o %t
|
||||
// RUN: %clangxx_scudo %s -lstdc++ -o %t
|
||||
// RUN: %run %t 2>&1
|
||||
|
||||
// Tests that a regular workflow of allocation, memory fill and free works as
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
#include <unistd.h>
|
||||
|
||||
// Sometimes the headers may not have this...
|
||||
extern "C" void *aligned_alloc(size_t alignment, size_t size);
|
||||
void *aligned_alloc(size_t alignment, size_t size);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *p = nullptr;
|
||||
void *p = NULL;
|
||||
size_t alignment = 1U << 12;
|
||||
size_t size = 1U << 12;
|
||||
int err;
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo %s -o %t
|
||||
// RUN: %clangxx_scudo %s -o %t
|
||||
// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t mallocdel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
|
||||
// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t mallocdel 2>&1
|
||||
// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t newfree 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo %s -o %t
|
||||
// RUN: %clangxx_scudo %s -o %t
|
||||
// RUN: %run %t 2>&1
|
||||
// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t 2>&1
|
||||
// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t 2>&1 | FileCheck %s
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void *global_p = nullptr;
|
||||
static void *global_p = NULL;
|
||||
|
||||
void __init(void) {
|
||||
global_p = malloc(1);
|
|
@ -1,19 +1,19 @@
|
|||
// Test that the preloaded runtime works without linking the static library.
|
||||
|
||||
// RUN: %clang %s -o %t
|
||||
// RUN: %clang %s -lstdc++ -o %t
|
||||
// RUN: env LD_PRELOAD=%shared_libscudo not %run %t 2>&1 | FileCheck %s
|
||||
|
||||
// This way of setting LD_PRELOAD does not work with Android test runner.
|
||||
// REQUIRES: !android
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void *p = malloc(sizeof(int));
|
||||
int *p = new int;
|
||||
assert(p);
|
||||
free(p);
|
||||
free(p);
|
||||
*p = 0;
|
||||
delete p;
|
||||
delete p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ int main(int argc, char **argv)
|
|||
free(p);
|
||||
|
||||
// Eventually the chunk should become available again.
|
||||
bool found = false;
|
||||
char found = 0;
|
||||
for (int i = 0; i < 0x200 && !found; i++) {
|
||||
p = malloc(size);
|
||||
assert(p);
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo %s -o %t
|
||||
// RUN: %clangxx_scudo %s -o %t
|
||||
// RUN: rm -rf %T/random_shuffle_tmp_dir
|
||||
// RUN: mkdir %T/random_shuffle_tmp_dir
|
||||
// RUN: %run %t 100 > %T/random_shuffle_tmp_dir/out1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo %s -lstdc++ -o %t
|
||||
// RUN: %clangxx_scudo %s -lstdc++ -o %t
|
||||
// RUN: %run %t pointers 2>&1
|
||||
// RUN: %run %t contents 2>&1
|
||||
// RUN: %run %t usablesize 2>&1
|
||||
|
|
|
@ -36,7 +36,7 @@ int main(int argc, char **argv)
|
|||
assert(p);
|
||||
memset(p, 'A', size); // This should not trigger anything.
|
||||
// Set up the SIGSEGV handler now, as the rest should trigger an AV.
|
||||
sigaction(SIGSEGV, &a, nullptr);
|
||||
sigaction(SIGSEGV, &a, NULL);
|
||||
if (!strcmp(argv[1], "after")) {
|
||||
for (int i = 0; i < page_size; i++)
|
||||
p[size + i] = 'A';
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo -fsized-deallocation %s -o %t
|
||||
// RUN: %clangxx_scudo -fsized-deallocation %s -o %t
|
||||
// RUN: %env_scudo_opts=DeleteSizeMismatch=1 %run %t gooddel 2>&1
|
||||
// RUN: %env_scudo_opts=DeleteSizeMismatch=1 not %run %t baddel 2>&1 | FileCheck %s
|
||||
// RUN: %env_scudo_opts=DeleteSizeMismatch=0 %run %t baddel 2>&1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_scudo %s -lstdc++ -o %t
|
||||
// RUN: %clangxx_scudo %s -lstdc++ -o %t
|
||||
// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s
|
||||
// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t malloc 2>&1
|
||||
// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s
|
||||
|
|
|
@ -20,7 +20,7 @@ pthread_t tid[kMaxNumThreads];
|
|||
|
||||
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
bool go = false;
|
||||
char go = 0;
|
||||
|
||||
void *thread_fun(void *arg) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
@ -51,7 +51,7 @@ int main(int argc, char** argv) {
|
|||
for (int i = 0; i < num_threads; i++)
|
||||
pthread_create(&tid[i], 0, thread_fun, 0);
|
||||
pthread_mutex_lock(&mutex);
|
||||
go = true;
|
||||
go = 1;
|
||||
pthread_cond_broadcast(&cond);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
for (int i = 0; i < num_threads; i++)
|
|
@ -19,7 +19,7 @@ size_t round_up_to(size_t size, size_t alignment) {
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *p = nullptr;
|
||||
void *p = NULL;
|
||||
size_t size, page_size;
|
||||
|
||||
assert(argc == 2);
|
Loading…
Reference in New Issue