summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/asan/asan_globals.cc15
-rw-r--r--compiler-rt/lib/asan/asan_intercepted_functions.h6
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.cc20
-rw-r--r--compiler-rt/lib/asan/asan_internal.h1
-rw-r--r--compiler-rt/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc16
-rw-r--r--compiler-rt/lib/asan/lit_tests/init-order-atexit.cc31
6 files changed, 89 insertions, 0 deletions
diff --git a/compiler-rt/lib/asan/asan_globals.cc b/compiler-rt/lib/asan/asan_globals.cc
index 972afe6505e..301ea44f2ca 100644
--- a/compiler-rt/lib/asan/asan_globals.cc
+++ b/compiler-rt/lib/asan/asan_globals.cc
@@ -123,6 +123,21 @@ static void UnregisterGlobal(const Global *g) {
// implementation. It might not be worth doing anyway.
}
+void StopInitOrderChecking() {
+ BlockingMutexLock lock(&mu_for_globals);
+ if (!flags()->check_initialization_order || !dynamic_init_globals)
+ return;
+ flags()->check_initialization_order = false;
+ for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ // Unpoison the whole global.
+ PoisonShadowForGlobal(g, 0);
+ // Poison redzones back.
+ PoisonRedZones(*g);
+ }
+}
+
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
diff --git a/compiler-rt/lib/asan/asan_intercepted_functions.h b/compiler-rt/lib/asan/asan_intercepted_functions.h
index 676a842a3e7..842781cdb17 100644
--- a/compiler-rt/lib/asan/asan_intercepted_functions.h
+++ b/compiler-rt/lib/asan/asan_intercepted_functions.h
@@ -77,6 +77,12 @@ using __sanitizer::uptr;
# define ASAN_INTERCEPT___CXA_THROW 0
#endif
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT___CXA_ATEXIT 1
+#else
+# define ASAN_INTERCEPT___CXA_ATEXIT 0
+#endif
+
# if SANITIZER_WINDOWS
extern "C" {
// Windows threads.
diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc
index 0c467b36ca9..7e7deea2963 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cc
+++ b/compiler-rt/lib/asan/asan_interceptors.cc
@@ -636,6 +636,21 @@ INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
}
#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+static void AtCxaAtexit(void *unused) {
+ (void)unused;
+ StopInitOrderChecking();
+}
+
+#if ASAN_INTERCEPT___CXA_ATEXIT
+INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
+ void *dso_handle) {
+ ENSURE_ASAN_INITED();
+ int res = REAL(__cxa_atexit)(func, arg, dso_handle);
+ REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
+ return res;
+}
+#endif // ASAN_INTERCEPT___CXA_ATEXIT
+
#define ASAN_INTERCEPT_FUNC(name) do { \
if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
@@ -746,6 +761,11 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(pthread_create);
#endif
+ // Intercept atexit function.
+#if ASAN_INTERCEPT___CXA_ATEXIT
+ ASAN_INTERCEPT_FUNC(__cxa_atexit);
+#endif
+
// Some Windows-specific interceptors.
#if SANITIZER_WINDOWS
InitializeWindowsInterceptors();
diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h
index b79acf31c17..7a4d74472bc 100644
--- a/compiler-rt/lib/asan/asan_internal.h
+++ b/compiler-rt/lib/asan/asan_internal.h
@@ -92,6 +92,7 @@ void UnsetAlternateSignalStack();
void InstallSignalHandlers();
void ReadContextStack(void *context, uptr *stack, uptr *ssize);
void AsanPlatformThreadInit();
+void StopInitOrderChecking();
// Wrapper for TLS/TSD.
void AsanTSDInit(void (*destructor)(void *tsd));
diff --git a/compiler-rt/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc b/compiler-rt/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc
new file mode 100644
index 00000000000..e4189d19d09
--- /dev/null
+++ b/compiler-rt/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+class C {
+ public:
+ C() { value = 42; }
+ ~C() { }
+ int value;
+};
+
+C c;
+
+void AccessC() {
+ printf("C value: %d\n", c.value);
+}
+
+int main() { return 0; }
diff --git a/compiler-rt/lib/asan/lit_tests/init-order-atexit.cc b/compiler-rt/lib/asan/lit_tests/init-order-atexit.cc
new file mode 100644
index 00000000000..45f4f17c0cb
--- /dev/null
+++ b/compiler-rt/lib/asan/lit_tests/init-order-atexit.cc
@@ -0,0 +1,31 @@
+// Test for the following situation:
+// (1) global A is constructed.
+// (2) exit() is called during construction of global B.
+// (3) destructor of A reads uninitialized global C from another module.
+// We do *not* want to report init-order bug in this case.
+
+// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/init-order-atexit-extra.cc -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void AccessC();
+
+class A {
+ public:
+ A() { }
+ ~A() { AccessC(); printf("PASSED\n"); }
+ // CHECK-NOT: AddressSanitizer
+ // CHECK: PASSED
+};
+
+A a;
+
+class B {
+ public:
+ B() { exit(1); }
+ ~B() { }
+};
+
+B b;
OpenPOWER on IntegriCloud