[ASan] Move __asan_report_error implementation to asan_report.cc

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@161574 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index f61c421..0cb6c35 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -20,6 +20,25 @@
 
 namespace __asan {
 
+// ---------------------- Error report callback ------------------- {{{1
+static void (*error_report_callback)(const char*);
+static char *error_message_buffer = 0;
+static uptr error_message_buffer_pos = 0;
+static uptr error_message_buffer_size = 0;
+
+void AppendToErrorMessageBuffer(const char *buffer) {
+  if (error_message_buffer) {
+    uptr length = internal_strlen(buffer);
+    CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
+    uptr remaining = error_message_buffer_size - error_message_buffer_pos;
+    internal_strncpy(error_message_buffer + error_message_buffer_pos,
+                     buffer, remaining);
+    error_message_buffer[error_message_buffer_size - 1] = '\0';
+    // FIXME: reallocate the buffer instead of truncating the message.
+    error_message_buffer_pos += remaining > length ? length : remaining;
+  }
+}
+
 // ---------------------- Address Descriptions ------------------- {{{1
 
 static bool IsASCII(unsigned char c) {
@@ -192,4 +211,134 @@
   ShowStatsAndAbort();
 }
 
+static void PrintBytes(const char *before, uptr *a) {
+  u8 *bytes = (u8*)a;
+  uptr byte_num = (__WORDSIZE) / 8;
+  AsanPrintf("%s%p:", before, (void*)a);
+  for (uptr i = 0; i < byte_num; i++) {
+    AsanPrintf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
+  }
+  AsanPrintf("\n");
+}
+
+void ReportInvalidMemoryAccess(uptr pc, uptr bp, uptr sp, uptr addr,
+                               bool is_write, uptr access_size) {
+  static atomic_uint32_t num_calls;
+  if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
+    // Do not print more than one report, otherwise they will mix up.
+    // We can not return here because the function is marked as never-return.
+    AsanPrintf("AddressSanitizer: while reporting a bug found another one."
+               "Ignoring.\n");
+    SleepForSeconds(5);
+    Die();
+  }
+
+  AsanPrintf("===================================================="
+             "=============\n");
+  const char *bug_descr = "unknown-crash";
+  if (AddrIsInMem(addr)) {
+    u8 *shadow_addr = (u8*)MemToShadow(addr);
+    // If we are accessing 16 bytes, look at the second shadow byte.
+    if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
+      shadow_addr++;
+    // If we are in the partial right redzone, look at the next shadow byte.
+    if (*shadow_addr > 0 && *shadow_addr < 128)
+      shadow_addr++;
+    switch (*shadow_addr) {
+      case kAsanHeapLeftRedzoneMagic:
+      case kAsanHeapRightRedzoneMagic:
+        bug_descr = "heap-buffer-overflow";
+        break;
+      case kAsanHeapFreeMagic:
+        bug_descr = "heap-use-after-free";
+        break;
+      case kAsanStackLeftRedzoneMagic:
+        bug_descr = "stack-buffer-underflow";
+        break;
+      case kAsanStackMidRedzoneMagic:
+      case kAsanStackRightRedzoneMagic:
+      case kAsanStackPartialRedzoneMagic:
+        bug_descr = "stack-buffer-overflow";
+        break;
+      case kAsanStackAfterReturnMagic:
+        bug_descr = "stack-use-after-return";
+        break;
+      case kAsanUserPoisonedMemoryMagic:
+        bug_descr = "use-after-poison";
+        break;
+      case kAsanGlobalRedzoneMagic:
+        bug_descr = "global-buffer-overflow";
+        break;
+    }
+  }
+
+  AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
+  u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+
+  if (curr_thread) {
+    // We started reporting an error message. Stop using the fake stack
+    // in case we will call an instrumented function from a symbolizer.
+    curr_thread->fake_stack().StopUsingFakeStack();
+  }
+
+  AsanReport("ERROR: AddressSanitizer %s on address "
+             "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
+             bug_descr, (void*)addr, pc, bp, sp);
+
+  AsanPrintf("%s of size %zu at %p thread T%d\n",
+             access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
+             access_size, (void*)addr, curr_tid);
+
+  if (flags()->debug) {
+    PrintBytes("PC: ", (uptr*)pc);
+  }
+
+  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
+  stack.PrintStack();
+
+  DescribeAddress(addr, access_size);
+
+  if (AddrIsInMem(addr)) {
+    uptr shadow_addr = MemToShadow(addr);
+    AsanReport("ABORTING\n");
+    __asan_print_accumulated_stats();
+    AsanPrintf("Shadow byte and word:\n");
+    AsanPrintf("  %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr);
+    uptr aligned_shadow = shadow_addr & ~(kWordSize - 1);
+    PrintBytes("  ", (uptr*)(aligned_shadow));
+    AsanPrintf("More shadow bytes:\n");
+    PrintBytes("  ", (uptr*)(aligned_shadow-4*kWordSize));
+    PrintBytes("  ", (uptr*)(aligned_shadow-3*kWordSize));
+    PrintBytes("  ", (uptr*)(aligned_shadow-2*kWordSize));
+    PrintBytes("  ", (uptr*)(aligned_shadow-1*kWordSize));
+    PrintBytes("=>", (uptr*)(aligned_shadow+0*kWordSize));
+    PrintBytes("  ", (uptr*)(aligned_shadow+1*kWordSize));
+    PrintBytes("  ", (uptr*)(aligned_shadow+2*kWordSize));
+    PrintBytes("  ", (uptr*)(aligned_shadow+3*kWordSize));
+    PrintBytes("  ", (uptr*)(aligned_shadow+4*kWordSize));
+  }
+  if (error_report_callback) {
+    error_report_callback(error_message_buffer);
+  }
+  Die();
+}
+
 }  // namespace __asan
+
+// --------------------------- Interface --------------------- {{{1
+using namespace __asan;  // NOLINT
+
+void __asan_report_error(uptr pc, uptr bp, uptr sp,
+                         uptr addr, bool is_write, uptr access_size) {
+  ReportInvalidMemoryAccess(pc, bp, sp, addr, is_write, access_size);
+}
+
+void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
+  error_report_callback = callback;
+  if (callback) {
+    error_message_buffer_size = 1 << 16;
+    error_message_buffer =
+        (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
+    error_message_buffer_pos = 0;
+  }
+}
diff --git a/lib/asan/asan_report.h b/lib/asan/asan_report.h
index 101797e..070ee46 100644
--- a/lib/asan/asan_report.h
+++ b/lib/asan/asan_report.h
@@ -39,5 +39,8 @@
 void NORETURN ReportStringFunctionMemoryRangesOverlap(
     const char *function, const char *offset1, uptr length1,
     const char *offset2, uptr length2, AsanStackTrace *stack);
+// Generic error report.
+void NORETURN ReportInvalidMemoryAccess(uptr pc, uptr bp, uptr sp, uptr addr,
+                                        bool is_write, uptr access_size);
 
 }  // namespace __asan
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index 46ed421..39d9ef1 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -147,10 +147,6 @@
 int asan_inited;
 bool asan_init_is_running;
 void (*death_callback)(void);
-static void (*error_report_callback)(const char*);
-char *error_message_buffer = 0;
-uptr error_message_buffer_pos = 0;
-uptr error_message_buffer_size = 0;
 
 // -------------------------- Misc ---------------- {{{1
 void ShowStatsAndAbort() {
@@ -158,29 +154,6 @@
   Die();
 }
 
-static void PrintBytes(const char *before, uptr *a) {
-  u8 *bytes = (u8*)a;
-  uptr byte_num = (__WORDSIZE) / 8;
-  AsanPrintf("%s%p:", before, (void*)a);
-  for (uptr i = 0; i < byte_num; i++) {
-    AsanPrintf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
-  }
-  AsanPrintf("\n");
-}
-
-void AppendToErrorMessageBuffer(const char *buffer) {
-  if (error_message_buffer) {
-    uptr length = internal_strlen(buffer);
-    CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
-    uptr remaining = error_message_buffer_size - error_message_buffer_pos;
-    internal_strncpy(error_message_buffer + error_message_buffer_pos,
-                     buffer, remaining);
-    error_message_buffer[error_message_buffer_size - 1] = '\0';
-    // FIXME: reallocate the buffer instead of truncating the message.
-    error_message_buffer_pos += remaining > length ? length : remaining;
-  }
-}
-
 // ---------------------- mmap -------------------- {{{1
 // Reserve memory range [beg, end].
 static void ReserveShadowMemoryRange(uptr beg, uptr end) {
@@ -258,7 +231,6 @@
   }
 }
 
-// -------------------------- Init ------------------- {{{1
 static void asan_atexit() {
   AsanPrintf("AddressSanitizer exit stats:\n");
   __asan_print_accumulated_stats();
@@ -288,119 +260,6 @@
   death_callback = callback;
 }
 
-void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
-  error_report_callback = callback;
-  if (callback) {
-    error_message_buffer_size = 1 << 16;
-    error_message_buffer =
-        (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
-    error_message_buffer_pos = 0;
-  }
-}
-
-void __asan_report_error(uptr pc, uptr bp, uptr sp,
-                         uptr addr, bool is_write, uptr access_size) {
-  static atomic_uint32_t num_calls;
-  if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
-    // Do not print more than one report, otherwise they will mix up.
-    // We can not return here because the function is marked as never-return.
-    AsanPrintf("AddressSanitizer: while reporting a bug found another one."
-               "Ignoring.\n");
-    SleepForSeconds(5);
-    Die();
-  }
-
-  AsanPrintf("===================================================="
-             "=============\n");
-  const char *bug_descr = "unknown-crash";
-  if (AddrIsInMem(addr)) {
-    u8 *shadow_addr = (u8*)MemToShadow(addr);
-    // If we are accessing 16 bytes, look at the second shadow byte.
-    if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
-      shadow_addr++;
-    // If we are in the partial right redzone, look at the next shadow byte.
-    if (*shadow_addr > 0 && *shadow_addr < 128)
-      shadow_addr++;
-    switch (*shadow_addr) {
-      case kAsanHeapLeftRedzoneMagic:
-      case kAsanHeapRightRedzoneMagic:
-        bug_descr = "heap-buffer-overflow";
-        break;
-      case kAsanHeapFreeMagic:
-        bug_descr = "heap-use-after-free";
-        break;
-      case kAsanStackLeftRedzoneMagic:
-        bug_descr = "stack-buffer-underflow";
-        break;
-      case kAsanStackMidRedzoneMagic:
-      case kAsanStackRightRedzoneMagic:
-      case kAsanStackPartialRedzoneMagic:
-        bug_descr = "stack-buffer-overflow";
-        break;
-      case kAsanStackAfterReturnMagic:
-        bug_descr = "stack-use-after-return";
-        break;
-      case kAsanUserPoisonedMemoryMagic:
-        bug_descr = "use-after-poison";
-        break;
-      case kAsanGlobalRedzoneMagic:
-        bug_descr = "global-buffer-overflow";
-        break;
-    }
-  }
-
-  AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
-  u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
-
-  if (curr_thread) {
-    // We started reporting an error message. Stop using the fake stack
-    // in case we will call an instrumented function from a symbolizer.
-    curr_thread->fake_stack().StopUsingFakeStack();
-  }
-
-  AsanReport("ERROR: AddressSanitizer %s on address "
-             "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
-             bug_descr, (void*)addr, pc, bp, sp);
-
-  AsanPrintf("%s of size %zu at %p thread T%d\n",
-             access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
-             access_size, (void*)addr, curr_tid);
-
-  if (flags()->debug) {
-    PrintBytes("PC: ", (uptr*)pc);
-  }
-
-  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
-  stack.PrintStack();
-
-  DescribeAddress(addr, access_size);
-
-  if (AddrIsInMem(addr)) {
-    uptr shadow_addr = MemToShadow(addr);
-    AsanReport("ABORTING\n");
-    __asan_print_accumulated_stats();
-    AsanPrintf("Shadow byte and word:\n");
-    AsanPrintf("  %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr);
-    uptr aligned_shadow = shadow_addr & ~(kWordSize - 1);
-    PrintBytes("  ", (uptr*)(aligned_shadow));
-    AsanPrintf("More shadow bytes:\n");
-    PrintBytes("  ", (uptr*)(aligned_shadow-4*kWordSize));
-    PrintBytes("  ", (uptr*)(aligned_shadow-3*kWordSize));
-    PrintBytes("  ", (uptr*)(aligned_shadow-2*kWordSize));
-    PrintBytes("  ", (uptr*)(aligned_shadow-1*kWordSize));
-    PrintBytes("=>", (uptr*)(aligned_shadow+0*kWordSize));
-    PrintBytes("  ", (uptr*)(aligned_shadow+1*kWordSize));
-    PrintBytes("  ", (uptr*)(aligned_shadow+2*kWordSize));
-    PrintBytes("  ", (uptr*)(aligned_shadow+3*kWordSize));
-    PrintBytes("  ", (uptr*)(aligned_shadow+4*kWordSize));
-  }
-  if (error_report_callback) {
-    error_report_callback(error_message_buffer);
-  }
-  Die();
-}
-
-
 void __asan_init() {
   if (asan_inited) return;
   asan_init_is_running = true;