[asan] Fix dead stripping of globals on Linux (compiler-rt).
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Thu, 6 Apr 2017 19:55:52 +0000 (19:55 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Thu, 6 Apr 2017 19:55:52 +0000 (19:55 +0000)
This is a re-land of r298173, r298169, r298159.

llvm-svn: 299698

compiler-rt/lib/asan/asan_globals.cc
compiler-rt/lib/asan/asan_interface.inc
compiler-rt/lib/asan/asan_interface_internal.h
compiler-rt/test/asan/CMakeLists.txt
compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cc [new file with mode: 0644]
compiler-rt/test/asan/TestCases/Linux/global-overflow-lld.cc [new file with mode: 0644]
compiler-rt/test/asan/TestCases/Linux/globals-gc-sections-lld.cc [new file with mode: 0644]
compiler-rt/test/asan/TestCases/Linux/globals-gc-sections.cc [deleted file]

index b7233067358c321e69eb5923f48d0f08e33b1378..eebada804f07c466a8bc4392f3922c814a8f7f8a 100644 (file)
@@ -332,6 +332,26 @@ void __asan_unregister_image_globals(uptr *flag) {
   *flag = 0;
 }
 
+void __asan_register_elf_globals(uptr *flag, void *start, void *stop) {
+  if (*flag) return;
+  if (!start) return;
+  CHECK_EQ(0, ((uptr)stop - (uptr)start) % sizeof(__asan_global));
+  __asan_global *globals_start = (__asan_global*)start;
+  __asan_global *globals_stop = (__asan_global*)stop;
+  __asan_register_globals(globals_start, globals_stop - globals_start);
+  *flag = 1;
+}
+
+void __asan_unregister_elf_globals(uptr *flag, void *start, void *stop) {
+  if (!*flag) return;
+  if (!start) return;
+  CHECK_EQ(0, ((uptr)stop - (uptr)start) % sizeof(__asan_global));
+  __asan_global *globals_start = (__asan_global*)start;
+  __asan_global *globals_stop = (__asan_global*)stop;
+  __asan_unregister_globals(globals_start, globals_stop - globals_start);
+  *flag = 0;
+}
+
 // Register an array of globals.
 void __asan_register_globals(__asan_global *globals, uptr n) {
   if (!flags()->report_globals) return;
index 351be4da51086acc00c3787343cc0b41a28fabca..e65f61722b10382a33aecff8b840a9960cc6df54 100644 (file)
@@ -64,6 +64,7 @@ INTERFACE_FUNCTION(__asan_poison_stack_memory)
 INTERFACE_FUNCTION(__asan_print_accumulated_stats)
 INTERFACE_FUNCTION(__asan_region_is_poisoned)
 INTERFACE_FUNCTION(__asan_register_globals)
+INTERFACE_FUNCTION(__asan_register_elf_globals)
 INTERFACE_FUNCTION(__asan_register_image_globals)
 INTERFACE_FUNCTION(__asan_report_error)
 INTERFACE_FUNCTION(__asan_report_exp_load1)
@@ -149,6 +150,7 @@ INTERFACE_FUNCTION(__asan_unpoison_intra_object_redzone)
 INTERFACE_FUNCTION(__asan_unpoison_memory_region)
 INTERFACE_FUNCTION(__asan_unpoison_stack_memory)
 INTERFACE_FUNCTION(__asan_unregister_globals)
+INTERFACE_FUNCTION(__asan_unregister_elf_globals)
 INTERFACE_FUNCTION(__asan_unregister_image_globals)
 INTERFACE_FUNCTION(__asan_version_mismatch_check_v8)
 INTERFACE_FUNCTION(__sanitizer_finish_switch_fiber)
index b18c3154886048fde676098c104088e6da64e688..b974c0cc4b43034675d0e4fedc99e72a2f45a36a 100644 (file)
@@ -67,6 +67,11 @@ extern "C" {
   SANITIZER_INTERFACE_ATTRIBUTE
   void __asan_unregister_image_globals(uptr *flag);
 
+  SANITIZER_INTERFACE_ATTRIBUTE
+  void __asan_register_elf_globals(uptr *flag, void *start, void *stop);
+  SANITIZER_INTERFACE_ATTRIBUTE
+  void __asan_unregister_elf_globals(uptr *flag, void *start, void *stop);
+
   // These two functions should be called by the instrumented code.
   // 'globals' is an array of structures describing 'n' globals.
   SANITIZER_INTERFACE_ATTRIBUTE
index 4b4fdf19d18c723ed8f50bd3ae24359e5450d583..597a3e10d9223f9da1bc9ea2e514fb656471c18b 100644 (file)
@@ -22,7 +22,7 @@ endmacro()
 set(ASAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
 if(NOT COMPILER_RT_STANDALONE_BUILD)
   list(APPEND ASAN_TEST_DEPS asan)
-  if(WIN32 AND COMPILER_RT_HAS_LLD)
+  if(NOT APPLE AND COMPILER_RT_HAS_LLD)
     list(APPEND ASAN_TEST_DEPS
       lld
     )
diff --git a/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cc b/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cc
new file mode 100644 (file)
index 0000000..117a761
--- /dev/null
@@ -0,0 +1,18 @@
+// Test that gc-sections-friendly instrumentation of globals does not introduce
+// false negatives with the BFD linker.
+// RUN: %clangxx_asan -fuse-ld=bfd -Wl,-gc-sections -ffunction-sections -fdata-sections -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <string.h>
+int main(int argc, char **argv) {
+  static char XXX[10];
+  static char YYY[10];
+  static char ZZZ[10];
+  memset(XXX, 0, 10);
+  memset(YYY, 0, 10);
+  memset(ZZZ, 0, 10);
+  int res = YYY[argc * 10];  // BOOOM
+  // CHECK: {{READ of size 1 at}}
+  // CHECK: {{located 0 bytes to the right of global variable}}
+  res += XXX[argc] + ZZZ[argc];
+  return res;
+}
diff --git a/compiler-rt/test/asan/TestCases/Linux/global-overflow-lld.cc b/compiler-rt/test/asan/TestCases/Linux/global-overflow-lld.cc
new file mode 100644 (file)
index 0000000..f4d0bc9
--- /dev/null
@@ -0,0 +1,19 @@
+// Test that gc-sections-friendly instrumentation of globals does not introduce
+// false negatives with the LLD linker.
+// RUN: %clangxx_asan -fuse-ld=lld -Wl,-gc-sections -ffunction-sections -fdata-sections -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// REQUIRES: lld
+
+#include <string.h>
+int main(int argc, char **argv) {
+  static char XXX[10];
+  static char YYY[10];
+  static char ZZZ[10];
+  memset(XXX, 0, 10);
+  memset(YYY, 0, 10);
+  memset(ZZZ, 0, 10);
+  int res = YYY[argc * 10];  // BOOOM
+  // CHECK: {{READ of size 1 at}}
+  // CHECK: {{located 0 bytes to the right of global variable}}
+  res += XXX[argc] + ZZZ[argc];
+  return res;
+}
diff --git a/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections-lld.cc b/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections-lld.cc
new file mode 100644 (file)
index 0000000..0d8bcdd
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -fuse-ld=lld -ffunction-sections -fdata-sections -mllvm -asan-globals=0
+// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -fuse-ld=lld -ffunction-sections -fdata-sections -mllvm -asan-globals=1
+
+// https://code.google.com/p/address-sanitizer/issues/detail?id=260
+// REQUIRES: lld
+
+int undefined();
+
+// On i386 clang adds --export-dynamic when linking with ASan, which adds all
+// non-hidden globals to GC roots.
+__attribute__((visibility("hidden"))) int (*unused)() = undefined;
+
+int main() {
+        return 0;
+}
diff --git a/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections.cc b/compiler-rt/test/asan/TestCases/Linux/globals-gc-sections.cc
deleted file mode 100644 (file)
index 72a9e94..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -ffunction-sections -mllvm -asan-globals=0
-// RUN: %clangxx_asan %s -o %t -Wl,--gc-sections -ffunction-sections -mllvm -asan-globals=1
-
-// https://code.google.com/p/address-sanitizer/issues/detail?id=260
-// XFAIL: *
-
-int undefined();
-
-int (*unused)() = undefined;
-
-int main() {
-        return 0;
-}