[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