summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2014-06-20 08:24:12 +0000
committerKostya Serebryany <kcc@google.com>2014-06-20 08:24:12 +0000
commit92c399bfd84362506ea7f97299022ae63706a8d9 (patch)
treeaed881bd3538eea578d52c4789d26c533ca4eda5
parent96d89e4e46f7ea7583fb6fa7863256ea2a044a17 (diff)
downloadcompiler-rt-92c399bfd84362506ea7f97299022ae63706a8d9.tar.gz
[asan] when reporting an ODR violation, also print the stack traces where the globals have been registered (thus show the name of shared library or exe to which the global belongs). The reports become a bit too verbose but I do not see any *simple* way to make them more compact. This should be especially helpful when the ODR happens because the same .cc file is used twice in the project in differend DSOs
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@211343 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_globals.cc37
-rw-r--r--lib/asan/asan_report.cc13
-rw-r--r--lib/asan/asan_report.h3
-rw-r--r--test/asan/TestCases/Linux/odr-violation.cc24
4 files changed, 62 insertions, 15 deletions
diff --git a/lib/asan/asan_globals.cc b/lib/asan/asan_globals.cc
index cecabc015..a8442015e 100644
--- a/lib/asan/asan_globals.cc
+++ b/lib/asan/asan_globals.cc
@@ -22,6 +22,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
namespace __asan {
@@ -45,6 +46,14 @@ typedef InternalMmapVector<DynInitGlobal> VectorOfGlobals;
// Lazy-initialized and never deleted.
static VectorOfGlobals *dynamic_init_globals;
+// We want to remember where a certain range of globals was registered.
+struct GlobalRegistrationSite {
+ u32 stack_id;
+ Global *g_first, *g_last;
+};
+typedef InternalMmapVector<GlobalRegistrationSite> GlobalRegistrationSiteVector;
+static GlobalRegistrationSiteVector *global_registration_site_vector;
+
ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) {
FastPoisonShadow(g->beg, g->size_with_redzone, value);
}
@@ -63,8 +72,8 @@ ALWAYS_INLINE void PoisonRedZones(const Global &g) {
}
static void ReportGlobal(const Global &g, const char *prefix) {
- Report("%s Global: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n",
- prefix, (void*)g.beg, g.size, g.size_with_redzone, g.name,
+ Report("%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n",
+ prefix, &g, (void*)g.beg, g.size, g.size_with_redzone, g.name,
g.module_name, g.has_dynamic_init);
}
@@ -81,6 +90,16 @@ bool DescribeAddressIfGlobal(uptr addr, uptr size) {
return res;
}
+u32 FindRegistrationSite(const Global *g) {
+ CHECK(global_registration_site_vector);
+ for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) {
+ GlobalRegistrationSite &grs = (*global_registration_site_vector)[i];
+ if (g >= grs.g_first && g <= grs.g_last)
+ return grs.stack_id;
+ }
+ return 0;
+}
+
// Register a global variable.
// This function may be called more than once for every global
// so we store the globals in a map.
@@ -101,7 +120,8 @@ static void RegisterGlobal(const Global *g) {
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
if (g->beg == l->g->beg &&
(flags()->detect_odr_violation >= 2 || g->size != l->g->size))
- ReportODRViolation(g, l->g);
+ ReportODRViolation(g, FindRegistrationSite(g),
+ l->g, FindRegistrationSite(l->g));
}
}
}
@@ -157,7 +177,18 @@ using namespace __asan; // NOLINT
// Register an array of globals.
void __asan_register_globals(__asan_global *globals, uptr n) {
if (!flags()->report_globals) return;
+ GET_STACK_TRACE_FATAL_HERE;
+ u32 stack_id = StackDepotPut(stack.trace, stack.size);
BlockingMutexLock lock(&mu_for_globals);
+ if (!global_registration_site_vector)
+ global_registration_site_vector =
+ new(allocator_for_globals) GlobalRegistrationSiteVector(128);
+ GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]};
+ global_registration_site_vector->push_back(site);
+ if (flags()->report_globals >= 2) {
+ PRINT_CURRENT_STACK();
+ Printf("=== ID %d; %p %p\n", stack_id, &globals[0], &globals[n - 1]);
+ }
for (uptr i = 0; i < n; i++) {
RegisterGlobal(&globals[i]);
}
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index f8b843199..3b8fa3e80 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -735,7 +735,8 @@ void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);
}
-void ReportODRViolation(const __asan_global *g1, const __asan_global *g2) {
+void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
+ const __asan_global *g2, u32 stack_id2) {
ScopedInErrorReport in_report;
Decorator d;
Printf("%s", d.Warning());
@@ -743,6 +744,16 @@ void ReportODRViolation(const __asan_global *g1, const __asan_global *g2) {
Printf("%s", d.EndWarning());
Printf(" [1] size=%zd %s %s\n", g1->size, g1->name, g1->module_name);
Printf(" [2] size=%zd %s %s\n", g2->size, g2->name, g2->module_name);
+ if (stack_id1 && stack_id2) {
+ Printf("These globals were registered at these points:\n");
+ Printf(" [1]:\n");
+ uptr stack_size;
+ const uptr *stack_trace = StackDepotGet(stack_id1, &stack_size);
+ StackTrace::PrintStack(stack_trace, stack_size);
+ Printf(" [2]:\n");
+ stack_trace = StackDepotGet(stack_id2, &stack_size);
+ StackTrace::PrintStack(stack_trace, stack_size);
+ }
Report("HINT: if you don't care about these warnings you may set "
"ASAN_OPTIONS=detect_odr_violation=0\n");
ReportErrorSummary("odr-violation", g1->module_name, 0, g1->name);
diff --git a/lib/asan/asan_report.h b/lib/asan/asan_report.h
index 1cf7c59b8..42ad1aa25 100644
--- a/lib/asan/asan_report.h
+++ b/lib/asan/asan_report.h
@@ -55,7 +55,8 @@ ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, uptr old_mid,
uptr new_mid, StackTrace *stack);
void NORETURN
-ReportODRViolation(const __asan_global *g1, const __asan_global *g2);
+ReportODRViolation(const __asan_global *g1, u32 stack_id1,
+ const __asan_global *g2, u32 stack_id2);
// Mac-specific errors and warnings.
void WarnMacFreeUnallocated(
diff --git a/test/asan/TestCases/Linux/odr-violation.cc b/test/asan/TestCases/Linux/odr-violation.cc
index c496c24e0..48e0907cf 100644
--- a/test/asan/TestCases/Linux/odr-violation.cc
+++ b/test/asan/TestCases/Linux/odr-violation.cc
@@ -2,18 +2,18 @@
// XFAIL: android
//
// Different size: detect a bug if detect_odr_violation>=1
-// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so
-// RUN: %clangxx_asan %s %t.so -Wl,-R. -o %t
-// RUN: ASAN_OPTIONS=detect_odr_violation=1 not %run %t 2>&1 | FileCheck %s
-// RUN: ASAN_OPTIONS=detect_odr_violation=2 not %run %t 2>&1 | FileCheck %s
-// RUN: ASAN_OPTIONS=detect_odr_violation=0 %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED
-// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-ODR-SO.so
+// RUN: %clangxx_asan %s %t-ODR-SO.so -Wl,-R. -o %t-ODR-EXE
+// RUN: ASAN_OPTIONS=detect_odr_violation=1 not %run %t-ODR-EXE 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=detect_odr_violation=2 not %run %t-ODR-EXE 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=detect_odr_violation=0 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED
+// RUN: not %run %t-ODR-EXE 2>&1 | FileCheck %s
//
// Same size: report a bug only if detect_odr_violation>=2.
-// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so -DSZ=100
-// RUN: ASAN_OPTIONS=detect_odr_violation=1 %run %t 2>&1 | FileCheck %s --check-prefix=DISABLED
-// RUN: ASAN_OPTIONS=detect_odr_violation=2 not %run %t 2>&1 | FileCheck %s
-// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-ODR-SO.so -DSZ=100
+// RUN: ASAN_OPTIONS=detect_odr_violation=1 %run %t-ODR-EXE 2>&1 | FileCheck %s --check-prefix=DISABLED
+// RUN: ASAN_OPTIONS=detect_odr_violation=2 not %run %t-ODR-EXE 2>&1 | FileCheck %s
+// RUN: not %run %t-ODR-EXE 2>&1 | FileCheck %s
// GNU driver doesn't handle .so files properly.
// REQUIRES: Clang
@@ -34,4 +34,8 @@ int main(int argc, char **argv) {
// CHECK: ERROR: AddressSanitizer: odr-violation
// CHECK: size=100 G
+// CHECK: size={{4|100}} G
+// CHECK: These globals were registered at these points:
+// CHECK: ODR-EXE
+// CHECK: ODR-SO
// DISABLED: PASS