[compiler-rt] r182637 - Disable init-order checking before destructors are run.

Alexey Samsonov samsonov at google.com
Fri May 24 04:46:56 PDT 2013


Author: samsonov
Date: Fri May 24 06:46:56 2013
New Revision: 182637

URL: http://llvm.org/viewvc/llvm-project?rev=182637&view=rev
Log:
Disable init-order checking before destructors are run.

We don't want to report initialization-order bugs when a destructor of a global
variable accesses dynamically initialized global from another
(not necessarily initialized) module. We do this by intercepting __cxa_atexit and
registrering our own callback that unpoisons shadow for all dynamically initialized
global variables.

Added:
    compiler-rt/trunk/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc
    compiler-rt/trunk/lib/asan/lit_tests/init-order-atexit.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_globals.cc
    compiler-rt/trunk/lib/asan/asan_intercepted_functions.h
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_internal.h

Modified: compiler-rt/trunk/lib/asan/asan_globals.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_globals.cc?rev=182637&r1=182636&r2=182637&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_globals.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_globals.cc Fri May 24 06:46:56 2013
@@ -123,6 +123,21 @@ static void UnregisterGlobal(const Globa
   // 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

Modified: compiler-rt/trunk/lib/asan/asan_intercepted_functions.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_intercepted_functions.h?rev=182637&r1=182636&r2=182637&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_intercepted_functions.h (original)
+++ compiler-rt/trunk/lib/asan/asan_intercepted_functions.h Fri May 24 06:46:56 2013
@@ -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.

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=182637&r1=182636&r2=182637&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Fri May 24 06:46:56 2013
@@ -636,6 +636,21 @@ INTERCEPTOR(long long, atoll, const char
 }
 #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();

Modified: compiler-rt/trunk/lib/asan/asan_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_internal.h?rev=182637&r1=182636&r2=182637&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_internal.h Fri May 24 06:46:56 2013
@@ -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));

Added: compiler-rt/trunk/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc?rev=182637&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc Fri May 24 06:46:56 2013
@@ -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; }

Added: compiler-rt/trunk/lib/asan/lit_tests/init-order-atexit.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/init-order-atexit.cc?rev=182637&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/init-order-atexit.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/init-order-atexit.cc Fri May 24 06:46:56 2013
@@ -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;





More information about the llvm-commits mailing list