[compiler-rt] r218481 - [compiler-rt] ASan debugging API for report info extraction and locating addresses

Kuba Brecka kuba.brecka at gmail.com
Thu Sep 25 16:53:57 PDT 2014


Author: kuba.brecka
Date: Thu Sep 25 18:53:57 2014
New Revision: 218481

URL: http://llvm.org/viewvc/llvm-project?rev=218481&view=rev
Log:
[compiler-rt] ASan debugging API for report info extraction and locating addresses

Reviewed at http://reviews.llvm.org/D4527

This patch is part of an effort to implement a more generic debugging API, as proposed in http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-July/074656.html, with first part reviewed at http://reviews.llvm.org/D4466. Now adding several new APIs: __asan_report_present, __asan_get_report_{pc,bp,sp,address,type,size,description}, __asan_locate_address. These return whether an asan report happened yet, the PC, BP, SP, address, access type (read/write), access size and bug description (e.g. "heap-use-after-free"), __asan_locate_address takes a pointer and tries to locate it, i.e. say whether it is a heap pointer, a global or a stack, or whether it's a pointer into the shadow memory. If global or stack, tries to also return the variable name, address and size. If heap, tries to return the chunk address and size. Generally these should serve as an alternative to "asan_describe_address", which only returns all the data in text form. Having an API to get these data could allow having d!
 ebugging 
 scripts/extensions that could show additional information about a variable/expression/pointer. Test cases in test/asan/TestCases/debug_locate.cc and test/asan/TestCasea/debug_report.cc.



Added:
    compiler-rt/trunk/test/asan/TestCases/debug_locate.cc
    compiler-rt/trunk/test/asan/TestCases/debug_report.cc
Modified:
    compiler-rt/trunk/include/sanitizer/asan_interface.h
    compiler-rt/trunk/lib/asan/asan_debugging.cc
    compiler-rt/trunk/lib/asan/asan_globals.cc
    compiler-rt/trunk/lib/asan/asan_interface_internal.h
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_report.h

Modified: compiler-rt/trunk/include/sanitizer/asan_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/asan_interface.h?rev=218481&r1=218480&r2=218481&view=diff
==============================================================================
--- compiler-rt/trunk/include/sanitizer/asan_interface.h (original)
+++ compiler-rt/trunk/include/sanitizer/asan_interface.h Thu Sep 25 18:53:57 2014
@@ -62,6 +62,32 @@ extern "C" {
   // Print the description of addr (useful when debugging in gdb).
   void __asan_describe_address(void *addr);
 
+  // Useful for calling from a debugger to get information about an ASan error.
+  // Returns 1 if an error has been (or is being) reported, otherwise returns 0.
+  int __asan_report_present();
+
+  // Useful for calling from a debugger to get information about an ASan error.
+  // If an error has been (or is being) reported, the following functions return
+  // the pc, bp, sp, address, access type (0 = read, 1 = write), access size and
+  // bug description (e.g. "heap-use-after-free"). Otherwise they return 0.
+  void *__asan_get_report_pc();
+  void *__asan_get_report_bp();
+  void *__asan_get_report_sp();
+  void *__asan_get_report_address();
+  int __asan_get_report_access_type();
+  size_t __asan_get_report_access_size();
+  const char *__asan_get_report_description();
+
+  // Useful for calling from the debugger to get information about a pointer.
+  // Returns the category of the given pointer as a constant string.
+  // Possible return values are "global", "stack", "stack-fake", "heap",
+  // "heap-invalid", "shadow-low", "shadow-gap", "shadow-high", "unknown".
+  // If global or stack, tries to also return the variable name, address and
+  // size. If heap, tries to return the chunk address and size. 'name' should
+  // point to an allocated buffer of size 'name_size'.
+  const char *__asan_locate_address(void *addr, char *name, size_t name_size,
+                                    void **region_address, size_t *region_size);
+
   // Useful for calling from the debugger to get the allocation stack trace
   // and thread ID for a heap address. Stores up to 'size' frames into 'trace',
   // returns the number of stored frames or 0 on error.

Modified: compiler-rt/trunk/lib/asan/asan_debugging.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_debugging.cc?rev=218481&r1=218480&r2=218481&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_debugging.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_debugging.cc Thu Sep 25 18:53:57 2014
@@ -17,10 +17,70 @@
 #include "asan_flags.h"
 #include "asan_internal.h"
 #include "asan_mapping.h"
+#include "asan_report.h"
 #include "asan_thread.h"
 
 namespace __asan {
 
+void GetInfoForStackVar(uptr addr, AddressDescription *descr, AsanThread *t) {
+  descr->name[0] = 0;
+  descr->region_address = 0;
+  descr->region_size = 0;
+  descr->region_kind = "stack";
+
+  uptr offset = 0;
+  uptr frame_pc = 0;
+  const char *frame_descr = t->GetFrameNameByAddr(addr, &offset, &frame_pc);
+  InternalMmapVector<StackVarDescr> vars(16);
+  if (!ParseFrameDescription(frame_descr, &vars)) {
+    return;
+  }
+
+  for (uptr i = 0; i < vars.size(); i++) {
+    if (offset <= vars[i].beg + vars[i].size) {
+      internal_strncat(descr->name, vars[i].name_pos,
+                       Min(descr->name_size, vars[i].name_len));
+      descr->region_address = addr - (offset - vars[i].beg);
+      descr->region_size = vars[i].size;
+      return;
+    }
+  }
+}
+
+void GetInfoForHeapAddress(uptr addr, AddressDescription *descr) {
+  AsanChunkView chunk = FindHeapChunkByAddress(addr);
+
+  descr->name[0] = 0;
+  descr->region_address = 0;
+  descr->region_size = 0;
+
+  if (!chunk.IsValid()) {
+    descr->region_kind = "heap-invalid";
+    return;
+  }
+
+  descr->region_address = chunk.Beg();
+  descr->region_size = chunk.UsedSize();
+  descr->region_kind = "heap";
+}
+
+void AsanLocateAddress(uptr addr, AddressDescription *descr) {
+  if (DescribeAddressIfShadow(addr, descr, /* print */ false)) {
+    return;
+  }
+  if (GetInfoForAddressIfGlobal(addr, descr)) {
+    return;
+  }
+  asanThreadRegistry().Lock();
+  AsanThread *thread = FindThreadByStackAddress(addr);
+  asanThreadRegistry().Unlock();
+  if (thread) {
+    GetInfoForStackVar(addr, descr, thread);
+    return;
+  }
+  GetInfoForHeapAddress(addr, descr);
+}
+
 uptr AsanGetStack(uptr addr, uptr *trace, uptr size, u32 *thread_id,
                   bool alloc_stack) {
   AsanChunkView chunk = FindHeapChunkByAddress(addr);
@@ -56,6 +116,16 @@ uptr AsanGetStack(uptr addr, uptr *trace
 using namespace __asan;
 
 SANITIZER_INTERFACE_ATTRIBUTE
+const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
+                                  uptr *region_address, uptr *region_size) {
+  AddressDescription descr = { name, name_size, 0, 0, 0 };
+  AsanLocateAddress(addr, &descr);
+  if (region_address) *region_address = descr.region_address;
+  if (region_size) *region_size = descr.region_size;
+  return descr.region_kind;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
 uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) {
   return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ true);
 }

Modified: compiler-rt/trunk/lib/asan/asan_globals.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_globals.cc?rev=218481&r1=218480&r2=218481&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_globals.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_globals.cc Thu Sep 25 18:53:57 2014
@@ -71,6 +71,14 @@ ALWAYS_INLINE void PoisonRedZones(const
   }
 }
 
+const uptr kMinimalDistanceFromAnotherGlobal = 64;
+
+bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {
+  if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
+  if (addr >= g.beg + g.size_with_redzone) return false;
+  return true;
+}
+
 static void ReportGlobal(const Global &g, const char *prefix) {
   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,
@@ -82,19 +90,45 @@ static void ReportGlobal(const Global &g
   }
 }
 
-bool DescribeAddressIfGlobal(uptr addr, uptr size) {
+static bool DescribeOrGetInfoIfGlobal(uptr addr, uptr size, bool print,
+                                      Global *output_global) {
   if (!flags()->report_globals) return false;
   BlockingMutexLock lock(&mu_for_globals);
   bool res = false;
   for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
     const Global &g = *l->g;
-    if (flags()->report_globals >= 2)
-      ReportGlobal(g, "Search");
-    res |= DescribeAddressRelativeToGlobal(addr, size, g);
+    if (print) {
+      if (flags()->report_globals >= 2)
+        ReportGlobal(g, "Search");
+      res |= DescribeAddressRelativeToGlobal(addr, size, g);
+    } else {
+      if (IsAddressNearGlobal(addr, g)) {
+        CHECK(output_global);
+        *output_global = g;
+        return true;
+      }
+    }
   }
   return res;
 }
 
+bool DescribeAddressIfGlobal(uptr addr, uptr size) {
+  return DescribeOrGetInfoIfGlobal(addr, size, /* print */ true,
+                                   /* output_global */ nullptr);
+}
+
+bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr) {
+  Global g = {};
+  if (DescribeOrGetInfoIfGlobal(addr, /* size */ 1, /* print */ false, &g)) {
+    internal_strncpy(descr->name, g.name, descr->name_size);
+    descr->region_address = g.beg;
+    descr->region_size = g.size;
+    descr->region_kind = "global";
+    return true;
+  }
+  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++) {

Modified: compiler-rt/trunk/lib/asan/asan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interface_internal.h?rev=218481&r1=218480&r2=218481&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interface_internal.h Thu Sep 25 18:53:57 2014
@@ -91,6 +91,28 @@ extern "C" {
   void __asan_describe_address(uptr addr);
 
   SANITIZER_INTERFACE_ATTRIBUTE
+  int __asan_report_present();
+
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_pc();
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_bp();
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_sp();
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_address();
+  SANITIZER_INTERFACE_ATTRIBUTE
+  int __asan_get_report_access_type();
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_get_report_access_size();
+  SANITIZER_INTERFACE_ATTRIBUTE
+  const char * __asan_get_report_description();
+
+  SANITIZER_INTERFACE_ATTRIBUTE
+  const char * __asan_locate_address(uptr addr, char *name, uptr name_size,
+                                     uptr *region_address, uptr *region_size);
+
+  SANITIZER_INTERFACE_ATTRIBUTE
   uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size,
                               u32 *thread_id);
 

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=218481&r1=218480&r2=218481&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Thu Sep 25 18:53:57 2014
@@ -31,6 +31,19 @@ static char *error_message_buffer = 0;
 static uptr error_message_buffer_pos = 0;
 static uptr error_message_buffer_size = 0;
 
+struct ReportData {
+  uptr pc;
+  uptr sp;
+  uptr bp;
+  uptr addr;
+  bool is_write;
+  uptr access_size;
+  const char *description;
+};
+
+static bool report_happened = false;
+static ReportData report_data = {};
+
 void AppendToErrorMessageBuffer(const char *buffer) {
   if (error_message_buffer) {
     uptr length = internal_strlen(buffer);
@@ -262,9 +275,7 @@ static void PrintGlobalLocation(Internal
 
 bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
                                      const __asan_global &g) {
-  static const uptr kMinimalDistanceFromAnotherGlobal = 64;
-  if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
-  if (addr >= g.beg + g.size_with_redzone) return false;
+  if (!IsAddressNearGlobal(addr, g)) return false;
   InternalScopedString str(4096);
   Decorator d;
   str.append("%s", d.Location());
@@ -290,21 +301,20 @@ bool DescribeAddressRelativeToGlobal(upt
   return true;
 }
 
-bool DescribeAddressIfShadow(uptr addr) {
+bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr, bool print) {
   if (AddrIsInMem(addr))
     return false;
-  static const char kAddrInShadowReport[] =
-      "Address %p is located in the %s.\n";
-  if (AddrIsInShadowGap(addr)) {
-    Printf(kAddrInShadowReport, addr, "shadow gap area");
-    return true;
-  }
-  if (AddrIsInHighShadow(addr)) {
-    Printf(kAddrInShadowReport, addr, "high shadow area");
-    return true;
-  }
-  if (AddrIsInLowShadow(addr)) {
-    Printf(kAddrInShadowReport, addr, "low shadow area");
+  const char *area_type = nullptr;
+  if (AddrIsInShadowGap(addr)) area_type = "shadow gap";
+  else if (AddrIsInHighShadow(addr)) area_type = "high shadow";
+  else if (AddrIsInLowShadow(addr)) area_type = "low shadow";
+  if (area_type != nullptr) {
+    if (print) {
+      Printf("Address %p is located in the %s area.\n", addr, area_type);
+    } else {
+      CHECK(descr);
+      descr->region_kind = area_type;
+    }
     return true;
   }
   CHECK(0 && "Address is not in memory and not in shadow?");
@@ -582,7 +592,7 @@ void DescribeThread(AsanThreadContext *c
 // immediately after printing error report.
 class ScopedInErrorReport {
  public:
-  ScopedInErrorReport() {
+  explicit ScopedInErrorReport(ReportData *report = nullptr) {
     static atomic_uint32_t num_calls;
     static u32 reporting_thread_tid;
     if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
@@ -602,6 +612,8 @@ class ScopedInErrorReport {
       // Die() to bypass any additional checks.
       internal__exit(flags()->exitcode);
     }
+    if (report) report_data = *report;
+    report_happened = true;
     ASAN_ON_ERROR();
     // Make sure the registry and sanitizer report mutexes are locked while
     // we're printing an error report.
@@ -922,8 +934,6 @@ using namespace __asan;  // NOLINT
 
 void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
                          uptr access_size) {
-  ScopedInErrorReport in_report;
-
   // Determine the error type.
   const char *bug_descr = "unknown-crash";
   if (AddrIsInMem(addr)) {
@@ -971,6 +981,11 @@ void __asan_report_error(uptr pc, uptr b
         break;
     }
   }
+
+  ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size,
+                        bug_descr };
+  ScopedInErrorReport in_report(&report);
+
   Decorator d;
   Printf("%s", d.Warning());
   Report("ERROR: AddressSanitizer: %s on address "
@@ -1012,6 +1027,38 @@ void __asan_describe_address(uptr addr)
   asanThreadRegistry().Unlock();
 }
 
+int __asan_report_present() {
+  return report_happened ? 1 : 0;
+}
+
+uptr __asan_get_report_pc() {
+  return report_data.pc;
+}
+
+uptr __asan_get_report_bp() {
+  return report_data.bp;
+}
+
+uptr __asan_get_report_sp() {
+  return report_data.sp;
+}
+
+uptr __asan_get_report_address() {
+  return report_data.addr;
+}
+
+int __asan_get_report_access_type() {
+  return report_data.is_write ? 1 : 0;
+}
+
+uptr __asan_get_report_access_size() {
+  return report_data.access_size;
+}
+
+const char *__asan_get_report_description() {
+  return report_data.description;
+}
+
 extern "C" {
 SANITIZER_INTERFACE_ATTRIBUTE
 void __sanitizer_ptr_sub(void *a, void *b) {

Modified: compiler-rt/trunk/lib/asan/asan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.h?rev=218481&r1=218480&r2=218481&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Thu Sep 25 18:53:57 2014
@@ -25,13 +25,24 @@ struct StackVarDescr {
   uptr name_len;
 };
 
+struct AddressDescription {
+  char *name;
+  uptr name_size;
+  uptr region_address;
+  uptr region_size;
+  const char *region_kind;
+};
+
 // The following functions prints address description depending
 // on the memory type (shadow/heap/stack/global).
 void DescribeHeapAddress(uptr addr, uptr access_size);
 bool DescribeAddressIfGlobal(uptr addr, uptr access_size);
 bool DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
                                      const __asan_global &g);
-bool DescribeAddressIfShadow(uptr addr);
+bool IsAddressNearGlobal(uptr addr, const __asan_global &g);
+bool GetInfoForAddressIfGlobal(uptr addr, AddressDescription *descr);
+bool DescribeAddressIfShadow(uptr addr, AddressDescription *descr = nullptr,
+                             bool print = true);
 bool ParseFrameDescription(const char *frame_descr,
                            InternalMmapVector<StackVarDescr> *vars);
 bool DescribeAddressIfStack(uptr addr, uptr access_size);

Added: compiler-rt/trunk/test/asan/TestCases/debug_locate.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/debug_locate.cc?rev=218481&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/debug_locate.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/debug_locate.cc Thu Sep 25 18:53:57 2014
@@ -0,0 +1,77 @@
+// Checks the ASan memory address type debugging API, makes sure it returns
+// the correct memory type for heap, stack, global and shadow addresses and
+// that it correctly finds out which region (and name and size) the address
+// belongs to.
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t 2>&1
+
+#include <assert.h>
+#include <sanitizer/asan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int global_var;
+
+int main() {
+  int local_var;
+  char *heap_ptr = (char *)malloc(10);
+
+  char name[100];
+  void *region_address;
+  size_t region_size;
+  const char *type;
+
+  type = __asan_locate_address(&global_var, name, 100,
+                               &region_address, &region_size);
+  assert(0 == strcmp(name, "global_var"));
+  assert(0 == strcmp(type, "global"));
+  assert(region_address == &global_var);
+  assert(region_size == sizeof(global_var));
+
+  type = __asan_locate_address((char *)(&global_var)+1, name, 100,
+                               &region_address, &region_size);
+  assert(0 == strcmp(name, "global_var"));
+  assert(0 == strcmp(type, "global"));
+  assert(region_address == &global_var);
+  assert(region_size == sizeof(global_var));
+
+  type = __asan_locate_address(&local_var, name, 100,
+                               &region_address, &region_size);
+  assert(0 == strcmp(name, "local_var"));
+  assert(0 == strcmp(type, "stack"));
+  assert(region_address == &local_var);
+  assert(region_size == sizeof(local_var));
+
+  type = __asan_locate_address((char *)(&local_var)+1, name, 100,
+                               &region_address, &region_size);
+  assert(0 == strcmp(name, "local_var"));
+  assert(0 == strcmp(type, "stack"));
+  assert(region_address == &local_var);
+  assert(region_size == sizeof(local_var));
+
+  type = __asan_locate_address(heap_ptr, name, 100,
+                               &region_address, &region_size);
+  assert(0 == strcmp(type, "heap"));
+  assert(region_address == heap_ptr);
+  assert(10 == region_size);
+
+  type = __asan_locate_address(heap_ptr+1, name, 100,
+                               &region_address, &region_size);
+  assert(0 == strcmp(type, "heap"));
+  assert(region_address == heap_ptr);
+  assert(10 == region_size);
+
+  size_t shadow_scale;
+  size_t shadow_offset;
+  __asan_get_shadow_mapping(&shadow_scale, &shadow_offset);
+
+  intptr_t shadow_ptr = (((intptr_t)heap_ptr) >> shadow_scale) + shadow_offset;
+  type = __asan_locate_address((void *)shadow_ptr, NULL, 0, NULL, NULL);
+  assert((0 == strcmp(type, "high shadow")) || 0 == strcmp(type, "low shadow"));
+
+  intptr_t shadow_gap = (shadow_ptr >> shadow_scale) + shadow_offset;
+  type = __asan_locate_address((void *)shadow_gap, NULL, 0, NULL, NULL);
+  assert(0 == strcmp(type, "shadow gap"));
+
+  return 0;
+}

Added: compiler-rt/trunk/test/asan/TestCases/debug_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/debug_report.cc?rev=218481&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/debug_report.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/debug_report.cc Thu Sep 25 18:53:57 2014
@@ -0,0 +1,48 @@
+// Checks that the ASan debugging API for getting report information
+// returns correct values.
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <sanitizer/asan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+  char *heap_ptr = (char *)malloc(10);
+  free(heap_ptr);
+  int present = __asan_report_present();
+  fprintf(stderr, "%s\n", (present == 0) ? "no report" : "");
+  // CHECK: no report
+  heap_ptr[0] = 'A'; // BOOM
+  return 0;
+}
+
+void __asan_on_error() {
+  int present = __asan_report_present();
+  void *pc = __asan_get_report_pc();
+  void *bp = __asan_get_report_bp();
+  void *sp = __asan_get_report_sp();
+  void *addr = __asan_get_report_address();
+  int is_write = __asan_get_report_access_type();
+  size_t access_size = __asan_get_report_access_size();
+  const char *description = __asan_get_report_description();
+
+  fprintf(stderr, "%s\n", (present == 1) ? "report" : "");
+  // CHECK: report
+  fprintf(stderr, "pc: %p\n", pc);
+  // CHECK: pc: 0x[[PC:[0-9a-f]+]]
+  fprintf(stderr, "bp: %p\n", bp);
+  // CHECK: bp: 0x[[BP:[0-9a-f]+]]
+  fprintf(stderr, "sp: %p\n", sp);
+  // CHECK: sp: 0x[[SP:[0-9a-f]+]]
+  fprintf(stderr, "addr: %p\n", addr);
+  // CHECK: addr: 0x[[ADDR:[0-9a-f]+]]
+  fprintf(stderr, "type: %s\n", (is_write ? "write" : "read"));
+  // CHECK: type: write
+  fprintf(stderr, "access_size: %ld\n", access_size);
+  // CHECK: access_size: 1
+  fprintf(stderr, "description: %s\n", description);
+  // CHECK: description: heap-use-after-free
+}
+
+// CHECK: AddressSanitizer: heap-use-after-free on address {{0x0*}}[[ADDR]] at pc {{0x0*}}[[PC]] bp {{0x0*}}[[BP]] sp {{0x0*}}[[SP]]
+// CHECK: WRITE of size 1 at {{0x0*}}[[ADDR]] thread T0





More information about the llvm-commits mailing list