[compiler-rt] r289498 - [sancov] __sanitizer_dump_coverage api

Mike Aizatsky via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 12 15:45:39 PST 2016


Author: aizatsky
Date: Mon Dec 12 17:45:38 2016
New Revision: 289498

URL: http://llvm.org/viewvc/llvm-project?rev=289498&view=rev
Log:
[sancov] __sanitizer_dump_coverage api

Subscribers: kubabrecka, mgorny

Differential Revision: https://reviews.llvm.org/D26758

Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc
    compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc
    compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc
Modified:
    compiler-rt/trunk/include/sanitizer/coverage_interface.h
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_interface_internal.h

Modified: compiler-rt/trunk/include/sanitizer/coverage_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/coverage_interface.h?rev=289498&r1=289497&r2=289498&view=diff
==============================================================================
--- compiler-rt/trunk/include/sanitizer/coverage_interface.h (original)
+++ compiler-rt/trunk/include/sanitizer/coverage_interface.h Mon Dec 12 17:45:38 2016
@@ -23,6 +23,11 @@ extern "C" {
   void __sanitizer_cov_init();
   // Record and dump coverage info.
   void __sanitizer_cov_dump();
+
+  //  Dump collected coverage info. Sorts pcs by module into individual
+  //  .sancov files.
+  void __sanitizer_dump_coverage(const uintptr_t *pcs, uintptr_t len);
+
   // Open <name>.sancov.packed in the coverage directory and return the file
   // descriptor. Returns -1 on failure, or if coverage dumping is disabled.
   // This is intended for use by sandboxing code.

Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=289498&r1=289497&r2=289498&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Mon Dec 12 17:45:38 2016
@@ -53,6 +53,7 @@ set(SANITIZER_NOLIBC_SOURCES
 set(SANITIZER_LIBCDEP_SOURCES
   sanitizer_common_libcdep.cc
   sanitizer_coverage_libcdep.cc
+  sanitizer_coverage_libcdep_new.cc
   sanitizer_coverage_mapping_libcdep.cc
   sanitizer_linux_libcdep.cc
   sanitizer_posix_libcdep.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=289498&r1=289497&r2=289498&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Mon Dec 12 17:45:38 2016
@@ -547,6 +547,13 @@ class InternalMmapVectorNoCtor {
   uptr capacity() const {
     return capacity_;
   }
+  void resize(uptr new_size) {
+    Resize(new_size);
+    if (new_size > size_) {
+      internal_memset(&data_[size_], 0, sizeof(T) * (new_size - size_));
+    }
+    size_ = new_size;
+  }
 
   void clear() { size_ = 0; }
   bool empty() const { return size() == 0; }

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc?rev=289498&r1=289497&r2=289498&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Mon Dec 12 17:45:38 2016
@@ -954,6 +954,7 @@ SANITIZER_INTERFACE_ATTRIBUTE void __san
 }
 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
   coverage_data.DumpAll();
+  __sanitizer_dump_trace_pc_guard_coverage();
 }
 SANITIZER_INTERFACE_ATTRIBUTE void
 __sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters,
@@ -1036,10 +1037,6 @@ void __sanitizer_cov_trace_div8() {}
 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
 void __sanitizer_cov_trace_gep() {}
 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
-void __sanitizer_cov_trace_pc_guard() {}
-SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
 void __sanitizer_cov_trace_pc_indir() {}
-SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
-void __sanitizer_cov_trace_pc_guard_init() {}
 #endif  // !SANITIZER_WINDOWS
 } // extern "C"

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc?rev=289498&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cc Mon Dec 12 17:45:38 2016
@@ -0,0 +1,165 @@
+//===-- sanitizer_coverage_libcdep_new.cc ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Sanitizer Coverage Controller for Trace PC Guard.
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+#include "sanitizer_symbolizer.h"
+
+using namespace __sanitizer;
+
+using AddressRange = LoadedModule::AddressRange;
+
+namespace {
+
+static const u64 Magic64 = 0xC0BFFFFFFFFFFF64ULL;
+static const u64 Magic32 = 0xC0BFFFFFFFFFFF32ULL;
+static const u64 Magic = SANITIZER_WORDSIZE == 64 ? Magic64 : Magic32;
+
+static fd_t OpenFile(const char* path) {
+  error_t err;
+  fd_t fd = OpenFile(path, WrOnly, &err);
+  if (fd == kInvalidFd)
+    Report("SanitizerCoverage: failed to open %s for writing (reason: %d)\n",
+           path, err);
+  return fd;
+}
+
+static void GetCoverageFilename(char* path, const char* name,
+                                const char* extension) {
+  CHECK(name);
+  internal_snprintf(path, kMaxPathLength, "%s/%s.%zd.%s",
+                    common_flags()->coverage_dir, name, internal_getpid(),
+                    extension);
+}
+
+static void WriteModuleCoverage(char* file_path, const char* module_name,
+                                const uptr* pcs, uptr len) {
+  GetCoverageFilename(file_path, StripModuleName(module_name), "sancov");
+  fd_t fd = OpenFile(file_path);
+  WriteToFile(fd, &Magic, sizeof(Magic));
+  WriteToFile(fd, pcs, len * sizeof(*pcs));
+  CloseFile(fd);
+  Printf("SanitizerCoverage: %s %zd PCs written\n", file_path, len);
+}
+
+static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) {
+  if (!len) return;
+
+  char* file_path = static_cast<char*>(InternalAlloc(kMaxPathLength));
+  char* module_name = static_cast<char*>(InternalAlloc(kMaxPathLength));
+  uptr* pcs = static_cast<uptr*>(InternalAlloc(len * sizeof(uptr)));
+
+  internal_memcpy(pcs, unsorted_pcs, len * sizeof(uptr));
+  SortArray(pcs, len);
+
+  bool module_found = false;
+  uptr last_base = 0;
+  uptr module_start_idx = 0;
+
+  for (uptr i = 0; i < len; ++i) {
+    const uptr pc = pcs[i];
+    if (!pc) continue;
+
+    if (!__sanitizer_get_module_and_offset_for_pc(pc, nullptr, 0, &pcs[i])) {
+      Printf("ERROR: bad pc %x\n", pc);
+      continue;
+    }
+    uptr module_base = pc - pcs[i];
+
+    if (module_base != last_base || !module_found) {
+      if (module_found) {
+        WriteModuleCoverage(file_path, module_name, &pcs[module_start_idx],
+                            i - module_start_idx);
+      }
+
+      last_base = module_base;
+      module_start_idx = i;
+      module_found = true;
+      __sanitizer_get_module_and_offset_for_pc(pc, module_name, kMaxPathLength,
+                                               &pcs[i]);
+    }
+  }
+
+  if (module_found) {
+    WriteModuleCoverage(file_path, module_name, &pcs[module_start_idx],
+                        len - module_start_idx);
+  }
+
+  InternalFree(file_path);
+  InternalFree(module_name);
+  InternalFree(pcs);
+}
+
+// Collects trace-pc guard coverage.
+// This class relies on zero-initialization.
+class TracePcGuardController {
+ public:
+  void Initialize() {
+    CHECK(!initialized);
+
+    initialized = true;
+    pc_vector.Initialize(0);
+  }
+
+  void InitTracePcGuard(u32* start, u32* end) {
+    if (!initialized) Initialize();
+    CHECK(!*start);
+    CHECK_NE(start, end);
+
+    u32 i = pc_vector.size();
+    for (u32* p = start; p < end; p++) *p = ++i;
+    pc_vector.resize(i);
+  }
+
+  void TracePcGuard(u32* guard, uptr pc) {
+    atomic_uint32_t* guard_ptr = reinterpret_cast<atomic_uint32_t*>(guard);
+    u32 idx = atomic_exchange(guard_ptr, 0, memory_order_relaxed);
+    if (!idx) return;
+    // we start indices from 1.
+    pc_vector[idx - 1] = pc;
+  }
+
+  void Dump() {
+    if (!initialized) return;
+    __sanitizer_dump_coverage(pc_vector.data(), pc_vector.size());
+  }
+
+ private:
+  bool initialized;
+  InternalMmapVectorNoCtor<uptr> pc_vector;
+};
+
+static TracePcGuardController pc_guard_controller;
+
+};  // namespace
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(  // NOLINT
+    const uptr* pcs, uptr len) {
+  return SanitizerDumpCoverage(pcs, len);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_pc_guard(u32* guard) {
+  if (!*guard) return;
+  pc_guard_controller.TracePcGuard(guard, GET_CALLER_PC() - 1);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_pc_guard_init(u32* start, u32* end) {
+  if (start == end || *start) return;
+  pc_guard_controller.InitTracePcGuard(start, end);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage() {
+  pc_guard_controller.Dump();
+}
+}  // extern "C"

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_interface_internal.h?rev=289498&r1=289497&r2=289498&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_interface_internal.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_interface_internal.h Mon Dec 12 17:45:38 2016
@@ -46,8 +46,12 @@ extern "C" {
   SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
   void __sanitizer_report_error_summary(const char *error_summary);
 
-  SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
   SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init();
+  SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
+  SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(
+      const __sanitizer::uptr *pcs, const __sanitizer::uptr len);
+  SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage();
+
   SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(__sanitizer::u32 *guard);
   SANITIZER_INTERFACE_ATTRIBUTE
   void __sanitizer_annotate_contiguous_container(const void *beg,
@@ -60,6 +64,11 @@ extern "C" {
   SANITIZER_INTERFACE_ATTRIBUTE
   const void *__sanitizer_contiguous_container_find_bad_address(
       const void *beg, const void *mid, const void *end);
+
+  SANITIZER_INTERFACE_ATTRIBUTE
+  int __sanitizer_get_module_and_offset_for_pc(
+      __sanitizer::uptr pc, char *module_path,
+      __sanitizer::uptr module_path_len, __sanitizer::uptr *pc_offset);
   } // extern "C"
 
 #endif  // SANITIZER_INTERFACE_INTERNAL_H

Added: compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc?rev=289498&view=auto
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc (added)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard-dso.cc Mon Dec 12 17:45:38 2016
@@ -0,0 +1,72 @@
+// Tests trace pc guard coverage collection.
+//
+// REQUIRES: has_sancovcc
+// XFAIL: tsan
+//
+// RUN: DIR=%t_workdir
+// RUN: CLANG_ARGS="-O0 -fsanitize-coverage=trace-pc-guard"
+// RUN: rm -rf $DIR
+// RUN: mkdir -p $DIR
+// RUN: cd $DIR
+// RUN: %clangxx -DSHARED1 $CLANG_ARGS -shared %s -o %t_1.so -fPIC
+// RUN: %clangxx -DSHARED2 $CLANG_ARGS -shared %s -o %t_2.so -fPIC
+// RUN: %clangxx -DMAIN $CLANG_ARGS %s -o %t %t_1.so %t_2.so
+// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
+// RUN: %sancovcc  -covered-functions -strip_path_prefix=TestCases/ *.sancov \
+// RUN:            %t %t_1.so %t_2.so 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-SANCOV %s
+// RUN: rm -rf $DIR
+
+#include <stdio.h>
+
+extern "C" {
+  int bar();
+  int baz();
+}
+
+#ifdef MAIN
+
+int foo() {
+  fprintf(stderr, "foo\n");
+  return 1;
+}
+
+int main() {
+  fprintf(stderr, "main\n");
+  foo();
+  bar();
+  baz();
+}
+
+#endif // MAIN
+
+extern "C" {
+
+#ifdef SHARED1
+int bar() {
+  fprintf(stderr, "bar\n");
+  return 1;
+}
+#endif
+
+#ifdef SHARED2
+int baz() {
+  fprintf(stderr, "baz\n");
+  return 1;
+}
+#endif
+
+} // extern "C"
+
+// CHECK: main
+// CHECK-NEXT: foo
+// CHECK-NEXT: bar
+// CHECK-NEXT: baz
+// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}.sancov 2 PCs written
+// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_2.so.{{.*}}.sancov 1 PCs written
+// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_1.so.{{.*}}.sancov 1 PCs written
+//
+// CHECK-SANCOV: Ignoring {{.*}}_1.so and its coverage because __sanitizer_cov* functions were not found.
+// CHECK-SANCOV: Ignoring {{.*}}_2.so and its coverage because __sanitizer_cov* functions were not found.
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:29 foo
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:34 main

Added: compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc?rev=289498&view=auto
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc (added)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/sanitizer_coverage_trace_pc_guard.cc Mon Dec 12 17:45:38 2016
@@ -0,0 +1,35 @@
+// Tests trace pc guard coverage collection.
+//
+// REQUIRES: has_sancovcc
+// XFAIL: tsan
+//
+// RUN: DIR=%t_workdir
+// RUN: rm -rf $DIR
+// RUN: mkdir -p $DIR
+// RUN: cd $DIR
+// RUN: %clangxx -O0 -fsanitize-coverage=trace-pc-guard %s -ldl -o %t
+// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
+// RUN: %sancovcc  -covered-functions -strip_path_prefix=TestCases/ *.sancov %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-SANCOV %s
+// RUN: rm -rf $DIR
+
+#include <stdio.h>
+
+int foo() {
+  fprintf(stderr, "foo\n");
+  return 1;
+}
+
+int main() {
+  fprintf(stderr, "main\n");
+  foo();
+  foo();
+}
+
+// CHECK: main
+// CHECK-NEXT: foo
+// CHECK-NEXT: foo
+// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov 2 PCs written
+//
+// CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cc:18 foo
+// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cc:23 main




More information about the llvm-commits mailing list