[compiler-rt] r225016 - [asan] fix coverage between fork() and exec(): reinitialize the guards after fork()

Kostya Serebryany kcc at google.com
Tue Dec 30 15:16:12 PST 2014


Author: kcc
Date: Tue Dec 30 17:16:12 2014
New Revision: 225016

URL: http://llvm.org/viewvc/llvm-project?rev=225016&view=rev
Log:
[asan] fix coverage between fork() and exec(): reinitialize the guards after fork()

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
    compiler-rt/trunk/test/asan/TestCases/Linux/coverage-fork.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=225016&r1=225015&r2=225016&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Tue Dec 30 17:16:12 2014
@@ -380,14 +380,14 @@ INLINE int ToLower(int c) {
 // small vectors.
 // WARNING: The current implementation supports only POD types.
 template<typename T>
-class InternalMmapVector {
+class InternalMmapVectorNoCtor {
  public:
-  explicit InternalMmapVector(uptr initial_capacity) {
+  void Initialize(uptr initial_capacity) {
     capacity_ = Max(initial_capacity, (uptr)1);
     size_ = 0;
-    data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVector");
+    data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVectorNoCtor");
   }
-  ~InternalMmapVector() {
+  void Destroy() {
     UnmapOrDie(data_, capacity_ * sizeof(T));
   }
   T &operator[](uptr i) {
@@ -438,15 +438,24 @@ class InternalMmapVector {
     UnmapOrDie(old_data, capacity_ * sizeof(T));
     capacity_ = new_capacity;
   }
-  // Disallow evil constructors.
-  InternalMmapVector(const InternalMmapVector&);
-  void operator=(const InternalMmapVector&);
 
   T *data_;
   uptr capacity_;
   uptr size_;
 };
 
+template<typename T>
+class InternalMmapVector : public InternalMmapVectorNoCtor<T> {
+ public:
+  explicit InternalMmapVector(uptr initial_capacity) {
+    InternalMmapVectorNoCtor<T>::Initialize(initial_capacity);
+  }
+  ~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); }
+  // Disallow evil constructors.
+  InternalMmapVector(const InternalMmapVector&);
+  void operator=(const InternalMmapVector&);
+};
+
 // HeapSort for arrays and InternalMmapVector.
 template<class Container, class Compare>
 void InternalSort(Container *v, uptr size, Compare comp) {

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=225016&r1=225015&r2=225016&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Tue Dec 30 17:16:12 2014
@@ -79,6 +79,7 @@ class CoverageData {
   ALWAYS_INLINE
   void TraceBasicBlock(uptr *cache);
 
+  void InitializeGuardArray(s32 *guards);
   void InitializeGuards(s32 *guards, uptr n);
 
   uptr *data();
@@ -103,6 +104,9 @@ class CoverageData {
   // Descriptor of the file mapped pc array.
   int pc_fd;
 
+  // Vector of coverage guard arrays, protected by mu.
+  InternalMmapVectorNoCtor<s32*> guard_array_vec;
+
   // Caller-Callee (cc) array, size and current index.
   static const uptr kCcArrayMaxSize = FIRST_32_SECOND_64(1 << 18, 1 << 24);
   uptr **cc_array;
@@ -181,6 +185,14 @@ void CoverageData::Init() {
   tr_pc_array_index = 0;
 }
 
+void CoverageData::InitializeGuardArray(s32 *guards) {
+  s32 n = guards[0];
+  for (s32 j = 1; j <= n; j++) {
+    uptr idx = atomic_fetch_add(&pc_array_index, 1, memory_order_relaxed);
+    guards[j] = -static_cast<s32>(idx + 1);
+  }
+}
+
 void CoverageData::ReInit() {
   if (pc_array) {
     internal_munmap(pc_array, sizeof(uptr) * kPcArrayMaxSize);
@@ -199,6 +211,11 @@ void CoverageData::ReInit() {
       Init();
     }
   }
+  // Re-initialize the guards.
+  // We are single-threaded now, no need to grab any lock.
+  CHECK_EQ(atomic_load(&pc_array_index, memory_order_relaxed), 0);
+  for (uptr i = 0; i < guard_array_vec.size(); i++)
+    InitializeGuardArray(guard_array_vec[i]);
 }
 
 void CoverageData::BeforeFork() {
@@ -251,10 +268,9 @@ void CoverageData::InitializeGuards(s32
   // to store 'n'.
   CHECK_LT(n, 1 << 30);
   guards[0] = static_cast<s32>(n);
-  for (uptr i = 1; i <= n; i++) {
-    uptr idx = atomic_fetch_add(&pc_array_index, 1, memory_order_relaxed);
-    guards[i] = -static_cast<s32>(idx + 1);
-  }
+  InitializeGuardArray(guards);
+  SpinMutexLock l(&mu);
+  guard_array_vec.push_back(guards);
 }
 
 // If guard is negative, atomically set it to -guard and store the PC in

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-fork.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-fork.cc?rev=225016&r1=225015&r2=225016&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-fork.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-fork.cc Tue Dec 30 17:16:12 2014
@@ -33,7 +33,6 @@ int main(int argc, char **argv) {
 }
 
 // CHECK-DAG: Child PID: [[ChildPID:[0-9]+]]
-// Coverage in the child (after fork,before exec) is not expected to work.
-// (disabled): [[ChildPID]].sancov: 1 PCs written
+// CHECK-DAG: [[ChildPID]].sancov: 1 PCs written
 // CHECK-DAG: Parent PID: [[ParentPID:[0-9]+]]
 // CHECK-DAG: [[ParentPID]].sancov: 3 PCs written





More information about the llvm-commits mailing list