[compiler-rt] r179843 - [ASan] Make init-order checker allow access to already initialized globals.
Alexey Samsonov
samsonov at google.com
Fri Apr 19 01:35:17 PDT 2013
Author: samsonov
Date: Fri Apr 19 03:35:16 2013
New Revision: 179843
URL: http://llvm.org/viewvc/llvm-project?rev=179843&view=rev
Log:
[ASan] Make init-order checker allow access to already initialized globals.
This change adds ASan runtime option "strict-init-order" (off by default)
that makes init-order checker bark if global initializer accesses any global from different
translation unit (even if the latter is already initialized). strict init-order checking
doesn't play well with, e.g. LLVM registration machineries, and causes issue
https://code.google.com/p/address-sanitizer/issues/detail?id=178.
Added:
compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc
compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc
Modified:
compiler-rt/trunk/lib/asan/asan_flags.h
compiler-rt/trunk/lib/asan/asan_globals.cc
compiler-rt/trunk/lib/asan/asan_rtl.cc
compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc
Modified: compiler-rt/trunk/lib/asan/asan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.h?rev=179843&r1=179842&r2=179843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.h (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.h Fri Apr 19 03:35:16 2013
@@ -113,6 +113,9 @@ struct Flags {
// If true, assume that memcmp(p1, p2, n) always reads n bytes before
// comparing p1 and p2.
bool strict_memcmp;
+ // If true, assume that dynamic initializers can never access globals from
+ // other modules, even if the latter are already initialized.
+ bool strict_init_order;
};
extern Flags asan_flags_dont_use_directly;
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=179843&r1=179842&r2=179843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_globals.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_globals.cc Fri Apr 19 03:35:16 2013
@@ -37,7 +37,11 @@ static LowLevelAllocator allocator_for_g
static ListOfGlobals *list_of_all_globals;
static const int kDynamicInitGlobalsInitialCapacity = 512;
-typedef InternalVector<Global> VectorOfGlobals;
+struct DynInitGlobal {
+ Global g;
+ bool initialized;
+};
+typedef InternalVector<DynInitGlobal> VectorOfGlobals;
// Lazy-initialized and never deleted.
static VectorOfGlobals *dynamic_init_globals;
@@ -101,7 +105,8 @@ static void RegisterGlobal(const Global
dynamic_init_globals = new(mem)
VectorOfGlobals(kDynamicInitGlobalsInitialCapacity);
}
- dynamic_init_globals->push_back(*g);
+ DynInitGlobal dyn_global = { *g, false };
+ dynamic_init_globals->push_back(dyn_global);
}
}
@@ -150,6 +155,7 @@ void __asan_before_dynamic_init(const ch
if (!flags()->check_initialization_order ||
!flags()->poison_heap)
return;
+ bool strict_init_order = flags()->strict_init_order;
CHECK(dynamic_init_globals);
CHECK(module_name);
CHECK(asan_inited);
@@ -157,9 +163,14 @@ void __asan_before_dynamic_init(const ch
if (flags()->report_globals >= 3)
Printf("DynInitPoison module: %s\n", module_name);
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
- const Global *g = &(*dynamic_init_globals)[i];
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ if (dyn_g.initialized)
+ continue;
if (g->module_name != module_name)
PoisonShadowForGlobal(g, kAsanInitializationOrderMagic);
+ else if (!strict_init_order)
+ dyn_g.initialized = true;
}
}
@@ -174,10 +185,13 @@ void __asan_after_dynamic_init() {
BlockingMutexLock lock(&mu_for_globals);
// FIXME: Optionally report that we're unpoisoning globals from a module.
for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
- const Global *g = &(*dynamic_init_globals)[i];
- // Unpoison the whole global.
- PoisonShadowForGlobal(g, 0);
- // Poison redzones back.
- PoisonRedZones(*g);
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ if (!dyn_g.initialized) {
+ // Unpoison the whole global.
+ PoisonShadowForGlobal(g, 0);
+ // Poison redzones back.
+ PoisonRedZones(*g);
+ }
}
}
Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=179843&r1=179842&r2=179843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Fri Apr 19 03:35:16 2013
@@ -125,6 +125,7 @@ static void ParseFlagsFromString(Flags *
ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
ParseFlag(str, &f->use_stack_depot, "use_stack_depot");
ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
+ ParseFlag(str, &f->strict_init_order, "strict_init_order");
}
static const char *asan_external_symbolizer;
@@ -170,6 +171,7 @@ void InitializeFlags(Flags *f, const cha
f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0);;
f->use_stack_depot = true; // Only affects allocator2.
f->strict_memcmp = true;
+ f->strict_init_order = false;
// Override from compile definition.
ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());
Modified: compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc?rev=179843&r1=179842&r2=179843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc Fri Apr 19 03:35:16 2013
@@ -1,12 +1,13 @@
// Test to make sure basic initialization order errors are caught.
// Check that on Linux initialization order bugs are caught
-// independently on order in which we list source files.
+// independently on order in which we list source files (if we specify
+// strict init-order checking).
// RUN: %clangxx_asan -m64 -O0 %s %p/../Helpers/initialization-bug-extra.cc -o %t
-// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 \
+// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 \
// RUN: | %symbolize | FileCheck %s
// RUN: %clangxx_asan -m64 -O0 %p/../Helpers/initialization-bug-extra.cc %s -o %t
-// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 \
+// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 \
// RUN: | %symbolize | FileCheck %s
// Do not test with optimization -- the error may be optimized away.
Added: compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc?rev=179843&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc Fri Apr 19 03:35:16 2013
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <unistd.h>
+
+void inc_global();
+
+int slow_init() {
+ sleep(1);
+ inc_global();
+ return 42;
+}
+
+int slowly_init_glob = slow_init();
Added: compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc?rev=179843&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc Fri Apr 19 03:35:16 2013
@@ -0,0 +1,47 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=178
+
+// RUN: %clangxx_asan -m64 -O0 %p/SharedLibs/init-order-dlopen-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m64 -O0 %s -o %t -Wl,--export-dynamic
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 | FileCheck %s
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#include <string>
+
+using std::string;
+
+int foo() {
+ return 42;
+}
+int global = foo();
+
+__attribute__((visibility("default")))
+void inc_global() {
+ global++;
+}
+
+void *global_poller(void *arg) {
+ while (true) {
+ if (global != 42)
+ break;
+ usleep(100);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ pthread_t p;
+ pthread_create(&p, 0, global_poller, 0);
+ string path = string(argv[0]) + "-so.so";
+ if (0 == dlopen(path.c_str(), RTLD_NOW)) {
+ fprintf(stderr, "dlerror: %s\n", dlerror());
+ return 1;
+ }
+ pthread_join(p, 0);
+ printf("PASSED\n");
+ // CHECK: PASSED
+ return 0;
+}
More information about the llvm-commits
mailing list