diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -838,6 +838,8 @@ SharedRuntimes.push_back("hwasan_aliases"); else SharedRuntimes.push_back("hwasan"); + if (!Args.hasArg(options::OPT_shared)) + HelperStaticRuntimes.push_back("hwasan-preinit"); } } diff --git a/compiler-rt/lib/hwasan/CMakeLists.txt b/compiler-rt/lib/hwasan/CMakeLists.txt --- a/compiler-rt/lib/hwasan/CMakeLists.txt +++ b/compiler-rt/lib/hwasan/CMakeLists.txt @@ -27,6 +27,10 @@ hwasan_new_delete.cpp ) +set(HWASAN_RTL_PREINIT_SOURCES + hwasan_preinit.cpp + ) + set(HWASAN_RTL_HEADERS hwasan.h hwasan_allocator.h @@ -103,6 +107,12 @@ ADDITIONAL_HEADERS ${HWASAN_RTL_HEADERS} CFLAGS ${HWASAN_DYNAMIC_CFLAGS} DEFS ${HWASAN_DEFINITIONS}) +add_compiler_rt_object_libraries(RTHwasan_preinit + ARCHS ${HWASAN_SUPPORTED_ARCH} + SOURCES ${HWASAN_RTL_PREINIT_SOURCES} + ADDITIONAL_HEADERS ${HWASAN_RTL_HEADERS} + CFLAGS ${HWASAN_RTL_CFLAGS} + DEFS ${HWASAN_DEFINITIONS}) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "") add_compiler_rt_object_libraries(RTHwasan_dynamic_version_script_dummy @@ -143,6 +153,7 @@ STATIC ARCHS ${arch} OBJECT_LIBS ${hwasan_object_lib} + RTHwasan_preinit RTInterception RTSanitizerCommon RTSanitizerCommonLibc @@ -218,6 +229,13 @@ endif() endforeach() +add_compiler_rt_runtime(clang_rt.hwasan-preinit + STATIC + ARCHS ${HWASAN_SUPPORTED_ARCH} + OBJECT_LIBS RTHwasan_preinit + CFLAGS ${HWASAN_RTL_CFLAGS} + PARENT_TARGET hwasan) + add_compiler_rt_resource_file(hwasan_ignorelist hwasan_ignorelist.txt hwasan) add_subdirectory("scripts") diff --git a/compiler-rt/lib/hwasan/hwasan_preinit.cpp b/compiler-rt/lib/hwasan/hwasan_preinit.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/hwasan/hwasan_preinit.cpp @@ -0,0 +1,23 @@ +//===-- hwasan_preinit.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of HWAddressSanitizer, an address sanity checker. +// +// Call __hwasan_init at the very early stage of process startup. +//===----------------------------------------------------------------------===// +#include "hwasan_interface_internal.h" +#include "sanitizer_common/sanitizer_internal_defs.h" + +#if SANITIZER_CAN_USE_PREINIT_ARRAY +// The symbol is called __local_hwasan_preinit, because it's not intended to +// be exported. +// This code linked into the main executable when -fsanitize=hwaddress is in +// the link flags. It can only use exported interface functions. +__attribute__((section(".preinit_array"), used)) static void ( + *__local_hwasan_preinit)(void) = __hwasan_init; +#endif diff --git a/compiler-rt/test/hwasan/TestCases/preinit_array.c b/compiler-rt/test/hwasan/TestCases/preinit_array.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/preinit_array.c @@ -0,0 +1,12 @@ +// Test that HWASan shadow is initialized before .preinit_array functions run. + +// RUN: %clang_hwasan %s -o %t +// RUN: %run %t + +volatile int Global; +void StoreToGlobal() { Global = 42; } + +__attribute__((section(".preinit_array"), used)) +void (*__StoreToGlobal_preinit)() = StoreToGlobal; + +int main() { return Global != 42; }