[ASan] Print global registration site in init-order-checker reports.
authorAlexey Samsonov <vonosmas@gmail.com>
Wed, 22 Apr 2015 20:30:19 +0000 (20:30 +0000)
committerAlexey Samsonov <vonosmas@gmail.com>
Wed, 22 Apr 2015 20:30:19 +0000 (20:30 +0000)
llvm-svn: 235540

compiler-rt/lib/asan/asan_globals.cc
compiler-rt/lib/asan/asan_report.cc
compiler-rt/lib/asan/asan_report.h
compiler-rt/test/asan/TestCases/initialization-bug.cc

index 65916f9..c34b1d3 100644 (file)
@@ -91,9 +91,19 @@ static void ReportGlobal(const Global &g, const char *prefix) {
   }
 }
 
-// Returns the number of globals close to the provided address and copies
-// them to "globals" array.
-int GetGlobalsForAddress(uptr addr, Global *globals, int max_globals) {
+static u32 FindRegistrationSite(const Global *g) {
+  mu_for_globals.CheckLocked();
+  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;
+}
+
+int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites,
+                         int max_globals) {
   if (!flags()->report_globals) return 0;
   BlockingMutexLock lock(&mu_for_globals);
   int res = 0;
@@ -102,7 +112,10 @@ int GetGlobalsForAddress(uptr addr, Global *globals, int max_globals) {
     if (flags()->report_globals >= 2)
       ReportGlobal(g, "Search");
     if (IsAddressNearGlobal(addr, g)) {
-      globals[res++] = g;
+      globals[res] = g;
+      if (reg_sites)
+        reg_sites[res] = FindRegistrationSite(&g);
+      res++;
       if (res == max_globals) break;
     }
   }
@@ -111,7 +124,7 @@ int GetGlobalsForAddress(uptr addr, Global *globals, int max_globals) {
 
 bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {
   Global g = {};
-  if (GetGlobalsForAddress(addr, &g, 1)) {
+  if (GetGlobalsForAddress(addr, &g, nullptr, 1)) {
     internal_strncpy(descr->name, g.name, descr->name_size);
     descr->region_address = g.beg;
     descr->region_size = g.size;
@@ -121,16 +134,6 @@ bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {
   return false;
 }
 
-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.
index a4011af..c1681e6 100644 (file)
@@ -307,15 +307,24 @@ static void DescribeAddressRelativeToGlobal(uptr addr, uptr size,
   Printf("%s", str.data());
 }
 
-static bool DescribeAddressIfGlobal(uptr addr, uptr size) {
+static bool DescribeAddressIfGlobal(uptr addr, uptr size,
+                                    const char *bug_type) {
   // Assume address is close to at most four globals.
   const int kMaxGlobalsInReport = 4;
   __asan_global globals[kMaxGlobalsInReport];
-  int globals_num = GetGlobalsForAddress(addr, globals, ARRAY_SIZE(globals));
+  u32 reg_sites[kMaxGlobalsInReport];
+  int globals_num =
+      GetGlobalsForAddress(addr, globals, reg_sites, ARRAY_SIZE(globals));
   if (globals_num == 0)
     return false;
-  for (int i = 0; i < globals_num; i++)
+  for (int i = 0; i < globals_num; i++) {
     DescribeAddressRelativeToGlobal(addr, size, globals[i]);
+    if (0 == internal_strcmp(bug_type, "initialization-order-fiasco") &&
+        reg_sites[i]) {
+      Printf("  registered at:\n");
+      StackDepotGet(reg_sites[i]).Print();
+    }
+  }
   return true;
 }
 
@@ -561,12 +570,12 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {
   DescribeThread(alloc_thread);
 }
 
-void DescribeAddress(uptr addr, uptr access_size) {
+static void DescribeAddress(uptr addr, uptr access_size, const char *bug_type) {
   // Check if this is shadow or shadow gap.
   if (DescribeAddressIfShadow(addr))
     return;
   CHECK(AddrIsInMem(addr));
-  if (DescribeAddressIfGlobal(addr, access_size))
+  if (DescribeAddressIfGlobal(addr, access_size, bug_type))
     return;
   if (DescribeAddressIfStack(addr, access_size))
     return;
@@ -820,8 +829,8 @@ void ReportStringFunctionMemoryRangesOverlap(const char *function,
              bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
   Printf("%s", d.EndWarning());
   stack->Print();
-  DescribeAddress((uptr)offset1, length1);
-  DescribeAddress((uptr)offset2, length2);
+  DescribeAddress((uptr)offset1, length1, bug_type);
+  DescribeAddress((uptr)offset2, length2, bug_type);
   ReportErrorSummary(bug_type, stack);
 }
 
@@ -834,7 +843,7 @@ void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
   Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size);
   Printf("%s", d.EndWarning());
   stack->Print();
-  DescribeAddress(offset, size);
+  DescribeAddress(offset, size, bug_type);
   ReportErrorSummary(bug_type, stack);
 }
 
@@ -889,15 +898,16 @@ void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
 static NOINLINE void
 ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) {
   ScopedInErrorReport in_report;
+  const char *bug_type = "invalid-pointer-pair";
   Decorator d;
   Printf("%s", d.Warning());
   Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2);
   Printf("%s", d.EndWarning());
   GET_STACK_TRACE_FATAL(pc, bp);
   stack.Print();
-  DescribeAddress(a1, 1);
-  DescribeAddress(a2, 1);
-  ReportErrorSummary("invalid-pointer-pair", &stack);
+  DescribeAddress(a1, 1, bug_type);
+  DescribeAddress(a2, 1, bug_type);
+  ReportErrorSummary(bug_type, &stack);
 }
 
 static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
@@ -1044,7 +1054,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
   GET_STACK_TRACE_FATAL(pc, bp);
   stack.Print();
 
-  DescribeAddress(addr, access_size);
+  DescribeAddress(addr, access_size, bug_descr);
   ReportErrorSummary(bug_descr, &stack);
   PrintShadowMemoryForAddress(addr);
 }
@@ -1062,7 +1072,7 @@ void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
 void __asan_describe_address(uptr addr) {
   // Thread registry must be locked while we're describing an address.
   asanThreadRegistry().Lock();
-  DescribeAddress(addr, 1);
+  DescribeAddress(addr, 1, "");
   asanThreadRegistry().Unlock();
 }
 
index ad011e3..e2786b0 100644 (file)
@@ -35,7 +35,8 @@ struct AddressDescription {
 
 // Returns the number of globals close to the provided address and copies
 // them to "globals" array.
-int GetGlobalsForAddress(uptr addr, __asan_global *globals, int max_globals);
+int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,
+                         int max_globals);
 bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);
 // The following functions prints address description depending
 // on the memory type (shadow/heap/stack/global).
@@ -45,9 +46,6 @@ bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr = nullptr,
 bool ParseFrameDescription(const char *frame_descr,
                            InternalMmapVector<StackVarDescr> *vars);
 bool DescribeAddressIfStack(uptr addr, uptr access_size);
-// Determines memory type on its own.
-void DescribeAddress(uptr addr, uptr access_size);
-
 void DescribeThread(AsanThreadContext *context);
 
 // Different kinds of error reports.
index badc6d1..f4ae70a 100644 (file)
@@ -1,7 +1,7 @@
 // Test to make sure basic initialization order errors are caught.
 
-// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t
-// RUN: env ASAN_OPTIONS=check_initialization_order=true not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t-INIT-ORDER-EXE
+// RUN: env ASAN_OPTIONS=check_initialization_order=true not %run %t-INIT-ORDER-EXE 2>&1 | FileCheck %s
 
 // Do not test with optimization -- the error may be optimized away.
 
@@ -32,6 +32,8 @@ int __attribute__((noinline)) initX() {
   // CHECK: {{AddressSanitizer: initialization-order-fiasco}}
   // CHECK: {{READ of size .* at 0x.* thread T0}}
   // CHECK: {{0x.* is located 0 bytes inside of global variable .*(y|z).*}}
+  // CHECK: registered at:
+  // CHECK: 0x{{.*}} in asan.module_ctor {{.*}}INIT-ORDER-EXE
 }
 
 // This initializer begins our initialization order problems.