summaryrefslogtreecommitdiffstats
path: root/compiler-rt/test/asan
diff options
context:
space:
mode:
authorKuba Brecka <kuba.brecka@gmail.com>2014-09-25 23:53:57 +0000
committerKuba Brecka <kuba.brecka@gmail.com>2014-09-25 23:53:57 +0000
commite37e089b665f785f72de898903757dacc4dd8256 (patch)
tree1b920b567477c522f3e9c8c0ba5413d95c6e1581 /compiler-rt/test/asan
parentf7988d73649ba5bafc6114aa4e7a3bf5542cb819 (diff)
downloadbcm5719-llvm-e37e089b665f785f72de898903757dacc4dd8256.tar.gz
bcm5719-llvm-e37e089b665f785f72de898903757dacc4dd8256.zip
[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 debugging 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. llvm-svn: 218481
Diffstat (limited to 'compiler-rt/test/asan')
-rw-r--r--compiler-rt/test/asan/TestCases/debug_locate.cc77
-rw-r--r--compiler-rt/test/asan/TestCases/debug_report.cc48
2 files changed, 125 insertions, 0 deletions
diff --git a/compiler-rt/test/asan/TestCases/debug_locate.cc b/compiler-rt/test/asan/TestCases/debug_locate.cc
new file mode 100644
index 00000000000..6260d65e7c2
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/debug_locate.cc
@@ -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;
+}
diff --git a/compiler-rt/test/asan/TestCases/debug_report.cc b/compiler-rt/test/asan/TestCases/debug_report.cc
new file mode 100644
index 00000000000..acf52f918dd
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/debug_report.cc
@@ -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
OpenPOWER on IntegriCloud