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(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(g->odr_indicator); + *odr_indicator = 0; } void StopInitOrderChecking() { 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: 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