summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/asan/CMakeLists.txt4
-rw-r--r--lib/asan/asan_globals.cc1
-rw-r--r--lib/asan/asan_globals_win.cc54
-rw-r--r--lib/asan/asan_globals_win.h34
-rw-r--r--lib/asan/asan_win.cc4
-rw-r--r--lib/asan/asan_win_dll_thunk.cc3
-rw-r--r--lib/asan/asan_win_dynamic_runtime_thunk.cc3
-rw-r--r--lib/asan/tests/CMakeLists.txt2
-rw-r--r--test/asan/TestCases/Windows/dll_global_dead_strip.c31
-rw-r--r--test/asan/TestCases/Windows/global_dead_strip.c26
10 files changed, 161 insertions, 1 deletions
diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt
index 4cc2b3ded..2a946e491 100644
--- a/lib/asan/CMakeLists.txt
+++ b/lib/asan/CMakeLists.txt
@@ -9,6 +9,7 @@ set(ASAN_SOURCES
asan_fake_stack.cc
asan_flags.cc
asan_globals.cc
+ asan_globals_win.cc
asan_interceptors.cc
asan_linux.cc
asan_mac.cc
@@ -63,6 +64,7 @@ set(ASAN_DYNAMIC_CFLAGS ${ASAN_CFLAGS})
append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC
-ftls-model=initial-exec ASAN_DYNAMIC_CFLAGS)
append_list_if(MSVC /DEBUG ASAN_DYNAMIC_LINK_FLAGS)
+append_list_if(MSVC /INCREMENTAL:NO ASAN_DYNAMIC_LINK_FLAGS)
append_list_if(COMPILER_RT_HAS_LIBC c ASAN_DYNAMIC_LIBS)
append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS)
@@ -205,6 +207,7 @@ else()
STATIC
ARCHS ${arch}
SOURCES asan_win_dll_thunk.cc
+ asan_globals_win.cc
$<TARGET_OBJECTS:RTInterception.${arch}>
CFLAGS ${ASAN_CFLAGS} -DASAN_DLL_THUNK
DEFS ${ASAN_COMMON_DEFINITIONS}
@@ -221,6 +224,7 @@ else()
STATIC
ARCHS ${arch}
SOURCES asan_win_dynamic_runtime_thunk.cc
+ asan_globals_win.cc
CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS}
DEFS ${ASAN_COMMON_DEFINITIONS}
PARENT_TARGET asan)
diff --git a/lib/asan/asan_globals.cc b/lib/asan/asan_globals.cc
index 0482206ad..c99f4e142 100644
--- a/lib/asan/asan_globals.cc
+++ b/lib/asan/asan_globals.cc
@@ -192,6 +192,7 @@ static inline bool UseODRIndicator(const Global *g) {
// This function may be called more than once for every global
// so we store the globals in a map.
static void RegisterGlobal(const Global *g) {
+ CHECK(g->beg);
CHECK(asan_inited);
if (flags()->report_globals >= 2)
ReportGlobal(*g, "Added");
diff --git a/lib/asan/asan_globals_win.cc b/lib/asan/asan_globals_win.cc
new file mode 100644
index 000000000..67d6772b0
--- /dev/null
+++ b/lib/asan/asan_globals_win.cc
@@ -0,0 +1,54 @@
+//===-- asan_globals_win.cc -----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Global registration code that is linked into every Windows DLL and EXE.
+//
+//===----------------------------------------------------------------------===//
+
+#include "asan_interface_internal.h"
+#if SANITIZER_WINDOWS
+
+namespace __asan {
+
+#pragma section(".ASAN$GA", read, write) // NOLINT
+#pragma section(".ASAN$GZ", read, write) // NOLINT
+extern "C" __declspec(allocate(".ASAN$GA"))
+uptr __asan_globals_start = 0;
+extern "C" __declspec(allocate(".ASAN$GZ"))
+uptr __asan_globals_end = 0;
+#pragma comment(linker, "/merge:.ASAN=.data")
+
+static void call_on_globals(void (*hook)(__asan_global *, uptr)) {
+ __asan_global *start = (__asan_global *)(&__asan_globals_start + 1);
+ __asan_global *end = (__asan_global *)&__asan_globals_end;
+ // We know end >= start because the linker sorts the portion after the dollar
+ // sign alphabetically.
+ uptr n = end - start;
+ hook(start, n);
+}
+
+static void register_dso_globals() {
+ call_on_globals(&__asan_register_globals);
+}
+
+static void unregister_dso_globals() {
+ call_on_globals(&__asan_unregister_globals);
+}
+
+// Register globals
+#pragma section(".CRT$XCU", long, read) // NOLINT
+#pragma section(".CRT$XTX", long, read) // NOLINT
+extern "C" __declspec(allocate(".CRT$XCU"))
+void (*const __asan_dso_reg_hook)() = &register_dso_globals;
+extern "C" __declspec(allocate(".CRT$XTX"))
+void (*const __asan_dso_unreg_hook)() = &unregister_dso_globals;
+
+} // namespace __asan
+
+#endif // SANITIZER_WINDOWS
diff --git a/lib/asan/asan_globals_win.h b/lib/asan/asan_globals_win.h
new file mode 100644
index 000000000..d4ed9c1f3
--- /dev/null
+++ b/lib/asan/asan_globals_win.h
@@ -0,0 +1,34 @@
+//===-- asan_globals_win.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Interface to the Windows-specific global management code. Separated into a
+// standalone header to allow inclusion from asan_win_dynamic_runtime_thunk,
+// which defines symbols that clash with other sanitizer headers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_GLOBALS_WIN_H
+#define ASAN_GLOBALS_WIN_H
+
+#if !defined(_MSC_VER)
+#error "this file is Windows-only, and uses MSVC pragmas"
+#endif
+
+#if defined(_WIN64)
+#define SANITIZER_SYM_PREFIX
+#else
+#define SANITIZER_SYM_PREFIX "_"
+#endif
+
+// Use this macro to force linking asan_globals_win.cc into the DSO.
+#define ASAN_LINK_GLOBALS_WIN() \
+ __pragma( \
+ comment(linker, "/include:" SANITIZER_SYM_PREFIX "__asan_dso_reg_hook"))
+
+#endif // ASAN_GLOBALS_WIN_H
diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc
index 4e676de8b..78268d83e 100644
--- a/lib/asan/asan_win.cc
+++ b/lib/asan/asan_win.cc
@@ -19,6 +19,7 @@
#include <stdlib.h>
+#include "asan_globals_win.h"
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_report.h"
@@ -367,8 +368,9 @@ __declspec(allocate(".CRT$XLAB")) void (NTAPI *__asan_tls_init)(void *,
unsigned long, void *) = asan_thread_init;
#endif
+ASAN_LINK_GLOBALS_WIN()
// }}}
} // namespace __asan
-#endif // _WIN32
+#endif // SANITIZER_WINDOWS
diff --git a/lib/asan/asan_win_dll_thunk.cc b/lib/asan/asan_win_dll_thunk.cc
index fb691e3e5..668b93d7f 100644
--- a/lib/asan/asan_win_dll_thunk.cc
+++ b/lib/asan/asan_win_dll_thunk.cc
@@ -20,6 +20,7 @@
// simplifies the build procedure.
#ifdef ASAN_DLL_THUNK
#include "asan_init_version.h"
+#include "asan_globals_win.h"
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_platform_interceptors.h"
@@ -472,4 +473,6 @@ static void WINAPI asan_thread_init(void *mod, unsigned long reason,
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
unsigned long, void *) = asan_thread_init;
+ASAN_LINK_GLOBALS_WIN()
+
#endif // ASAN_DLL_THUNK
diff --git a/lib/asan/asan_win_dynamic_runtime_thunk.cc b/lib/asan/asan_win_dynamic_runtime_thunk.cc
index f38f4cd1f..8e42f03c1 100644
--- a/lib/asan/asan_win_dynamic_runtime_thunk.cc
+++ b/lib/asan/asan_win_dynamic_runtime_thunk.cc
@@ -24,6 +24,7 @@
// Using #ifdef rather than relying on Makefiles etc.
// simplifies the build procedure.
#ifdef ASAN_DYNAMIC_RUNTIME_THUNK
+#include "asan_globals_win.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -121,4 +122,6 @@ __declspec(allocate(".CRT$XCAB")) int (*__asan_seh_interceptor)() =
SetSEHFilter;
}
+ASAN_LINK_GLOBALS_WIN()
+
#endif // ASAN_DYNAMIC_RUNTIME_THUNK
diff --git a/lib/asan/tests/CMakeLists.txt b/lib/asan/tests/CMakeLists.txt
index 3e56763a8..c45d35b55 100644
--- a/lib/asan/tests/CMakeLists.txt
+++ b/lib/asan/tests/CMakeLists.txt
@@ -47,6 +47,8 @@ else()
endif()
if(MSVC)
list(APPEND ASAN_UNITTEST_COMMON_CFLAGS -gcodeview)
+ # Incremental linking appears to break our global registration mechanism.
+ list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS -Wl,-incremental:no)
endif()
list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS -g)
diff --git a/test/asan/TestCases/Windows/dll_global_dead_strip.c b/test/asan/TestCases/Windows/dll_global_dead_strip.c
new file mode 100644
index 000000000..e28d48a1c
--- /dev/null
+++ b/test/asan/TestCases/Windows/dll_global_dead_strip.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+//
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: %env_asan_opts=report_globals=2 %run %t %t.dll 2>&1 | FileCheck %s --check-prefix=NOSTRIP
+// RUN: %clang_cl_asan -LD -O2 %s -Fe%t.dll -link -opt:ref
+// RUN: %env_asan_opts=report_globals=2 %run %t %t.dll 2>&1 | FileCheck %s --check-prefix=STRIP
+
+// FIXME: Remove the XFAIL once the LLVM instrumentation change lands.
+// XFAIL: *
+
+#include <stdio.h>
+
+int dead_global = 42;
+int live_global = 0;
+
+__declspec(dllexport)
+int test_function() {
+ puts("main");
+ return live_global;
+}
+
+// Check that our global registration scheme works with MSVC's linker dead
+// stripping (/OPT:REF).
+
+// NOSTRIP: Added Global{{.*}}name=dead_global
+// NOSTRIP: Added Global{{.*}}name=live_global
+// NOSTRIP: main
+
+// STRIP-NOT: Added Global{{.*}}name=dead_global
+// STRIP: Added Global{{.*}}name=live_global
+// STRIP: main
diff --git a/test/asan/TestCases/Windows/global_dead_strip.c b/test/asan/TestCases/Windows/global_dead_strip.c
new file mode 100644
index 000000000..df5f58ab5
--- /dev/null
+++ b/test/asan/TestCases/Windows/global_dead_strip.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cl_asan /O0 %s /Fe%t.exe
+// RUN: %env_asan_opts=report_globals=2 %t.exe 2>&1 | FileCheck %s --check-prefix=NOSTRIP
+// RUN: %clang_cl_asan /O2 %s /Fe%t.exe -link -opt:ref
+// RUN: %env_asan_opts=report_globals=2 %t.exe 2>&1 | FileCheck %s --check-prefix=STRIP
+
+// FIXME: Remove the XFAIL once the LLVM instrumentation change lands.
+// XFAIL: *
+
+#include <stdio.h>
+int dead_global = 42;
+int live_global = 0;
+int main() {
+ puts("main");
+ return live_global;
+}
+
+// Check that our global registration scheme works with MSVC's linker dead
+// stripping (/OPT:REF).
+
+// NOSTRIP: Added Global{{.*}}name=dead_global
+// NOSTRIP: Added Global{{.*}}name=live_global
+// NOSTRIP: main
+
+// STRIP-NOT: Added Global{{.*}}name=dead_global
+// STRIP: Added Global{{.*}}name=live_global
+// STRIP: main