[PATCH] D15644: [asan] Use private aliases for global variables (compiler-rt part).

Maxim Ostapenko via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 18 08:23:33 PST 2015


m.ostapenko created this revision.
m.ostapenko added reviewers: kcc, eugenis, samsonov.
m.ostapenko added subscribers: ygribov, llvm-commits.
m.ostapenko set the repository for this revision to rL LLVM.

This is a compiler-rt part of this http://reviews.llvm.org/differential/diff/43231/ patch. Here, we change the way how we detect ODR violation. Instead of using __asan_region_is_poisoned(g->beg, g->size_with_redzone) on global address (that would be false now due to using private alias), we use new globally visible indicator symbol to perform the check.

Does this look like a reasonable approach?

Repository:
  rL LLVM

http://reviews.llvm.org/D15644

Files:
  lib/asan/asan_globals.cc
  lib/asan/asan_interface_internal.h
  test/asan/TestCases/Linux/local_alias.cc

Index: test/asan/TestCases/Linux/local_alias.cc
===================================================================
--- /dev/null
+++ test/asan/TestCases/Linux/local_alias.cc
@@ -0,0 +1,30 @@
+// RUN: %clangxx_asan -DBUILD_FOO_SO=1 -fPIC -shared %s -o %t-FOO-SO.so
+// RUN: %clangxx -DBUILD_BAR_SO=1 -fPIC -shared %s -o %t-BAR-SO.so
+// RUN: %clangxx %s -c -o %t.o
+// RUN: %clangxx_asan %t.o %t-BAR-SO.so %t-FOO-SO.so -o %t-EXE
+// RUN: %run %t-EXE
+
+#if defined (BUILD_FOO_SO)
+long h = 15;
+long f = 4;
+long foo(long *p) {
+  return *p;
+}
+#elif defined (BUILD_BAR_SO)
+long foo(long *);
+long h = 12;
+long i = 13;
+long f = 5;
+
+int bar() {
+  if (foo(&f) != 5 || foo(&h) != 12 || foo(&i) != 13)
+    return 1;
+  return 0;
+}
+#else
+extern int bar();
+
+int main() {
+  return bar();
+}
+#endif
Index: lib/asan/asan_interface_internal.h
===================================================================
--- lib/asan/asan_interface_internal.h
+++ lib/asan/asan_interface_internal.h
@@ -45,7 +45,8 @@
 
   // This structure describes an instrumented global variable.
   struct __asan_global {
-    uptr beg;                // The address of the global.
+    uptr beg;                // The private address of the global.
+    uptr odr_indicator;      // The address of the ODR indicator symbol.
     uptr size;               // The original size of the global.
     uptr size_with_redzone;  // The size with the redzone.
     const char *name;        // Name as a C string.
Index: lib/asan/asan_globals.cc
===================================================================
--- lib/asan/asan_globals.cc
+++ lib/asan/asan_globals.cc
@@ -149,17 +149,21 @@
   if (flags()->detect_odr_violation) {
     // Try detecting ODR (One Definition Rule) violation, i.e. the situation
     // where two globals with the same name are defined in different modules.
-    if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
+    u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator);
+    // If *odr_indicator is not zero, some module have already registred
+    // externally visible symbol with the same name. This is an ODR vioation.
+    if (*odr_indicator != 0) {
       // This check may not be enough: if the first global is much larger
       // the entire redzone of the second global may be within the first global.
       for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
-        if (g->beg == l->g->beg &&
+        if (g->odr_indicator == l->g->odr_indicator &&
             (flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
             !IsODRViolationSuppressed(g->name))
           ReportODRViolation(g, FindRegistrationSite(g),
                              l->g, FindRegistrationSite(l->g));
       }
     }
+    *odr_indicator = 1;
   }
   if (CanPoisonMemory())
     PoisonRedZones(*g);
@@ -190,6 +194,10 @@
   // We unpoison the shadow memory for the global but we do not remove it from
   // the list because that would require O(n^2) time with the current list
   // implementation. It might not be worth doing anyway.
+
+  // Release ODR indicator.
+  u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator);
+  *odr_indicator = 0;
 }
 
 void StopInitOrderChecking() {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D15644.43231.patch
Type: text/x-patch
Size: 3239 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151218/f12f7605/attachment.bin>


More information about the llvm-commits mailing list