2013-11-15 15:18:15 +08:00
|
|
|
//===-- sanitizer_coverage.cc ---------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Sanitizer Coverage.
|
|
|
|
// This file implements run-time support for a poor man's coverage tool.
|
|
|
|
//
|
|
|
|
// Compiler instrumentation:
|
[asan] extend asan-coverage (still experimental).
- add a mode for collecting per-block coverage (-asan-coverage=2).
So far the implementation is naive (all blocks are instrumented),
the performance overhead on top of asan could be as high as 30%.
- Make sure the one-time calls to __sanitizer_cov are moved to function buttom,
which in turn required to copy the original debug info into the call insn.
Here is the performance data on SPEC 2006
(train data, comparing asan with asan-coverage={0,1,2}):
asan+cov0 asan+cov1 diff 0-1 asan+cov2 diff 0-2 diff 1-2
400.perlbench, 65.60, 65.80, 1.00, 76.20, 1.16, 1.16
401.bzip2, 65.10, 65.50, 1.01, 75.90, 1.17, 1.16
403.gcc, 1.64, 1.69, 1.03, 2.04, 1.24, 1.21
429.mcf, 21.90, 22.60, 1.03, 23.20, 1.06, 1.03
445.gobmk, 166.00, 169.00, 1.02, 205.00, 1.23, 1.21
456.hmmer, 88.30, 87.90, 1.00, 91.00, 1.03, 1.04
458.sjeng, 210.00, 222.00, 1.06, 258.00, 1.23, 1.16
462.libquantum, 1.73, 1.75, 1.01, 2.11, 1.22, 1.21
464.h264ref, 147.00, 152.00, 1.03, 160.00, 1.09, 1.05
471.omnetpp, 115.00, 116.00, 1.01, 140.00, 1.22, 1.21
473.astar, 133.00, 131.00, 0.98, 142.00, 1.07, 1.08
483.xalancbmk, 118.00, 120.00, 1.02, 154.00, 1.31, 1.28
433.milc, 19.80, 20.00, 1.01, 20.10, 1.02, 1.01
444.namd, 16.20, 16.20, 1.00, 17.60, 1.09, 1.09
447.dealII, 41.80, 42.20, 1.01, 43.50, 1.04, 1.03
450.soplex, 7.51, 7.82, 1.04, 8.25, 1.10, 1.05
453.povray, 14.00, 14.40, 1.03, 15.80, 1.13, 1.10
470.lbm, 33.30, 34.10, 1.02, 34.10, 1.02, 1.00
482.sphinx3, 12.40, 12.30, 0.99, 13.00, 1.05, 1.06
llvm-svn: 199488
2014-01-17 19:00:30 +08:00
|
|
|
// For every interesting basic block the compiler injects the following code:
|
2013-11-15 15:18:15 +08:00
|
|
|
// if (*Guard) {
|
[asan] extend asan-coverage (still experimental).
- add a mode for collecting per-block coverage (-asan-coverage=2).
So far the implementation is naive (all blocks are instrumented),
the performance overhead on top of asan could be as high as 30%.
- Make sure the one-time calls to __sanitizer_cov are moved to function buttom,
which in turn required to copy the original debug info into the call insn.
Here is the performance data on SPEC 2006
(train data, comparing asan with asan-coverage={0,1,2}):
asan+cov0 asan+cov1 diff 0-1 asan+cov2 diff 0-2 diff 1-2
400.perlbench, 65.60, 65.80, 1.00, 76.20, 1.16, 1.16
401.bzip2, 65.10, 65.50, 1.01, 75.90, 1.17, 1.16
403.gcc, 1.64, 1.69, 1.03, 2.04, 1.24, 1.21
429.mcf, 21.90, 22.60, 1.03, 23.20, 1.06, 1.03
445.gobmk, 166.00, 169.00, 1.02, 205.00, 1.23, 1.21
456.hmmer, 88.30, 87.90, 1.00, 91.00, 1.03, 1.04
458.sjeng, 210.00, 222.00, 1.06, 258.00, 1.23, 1.16
462.libquantum, 1.73, 1.75, 1.01, 2.11, 1.22, 1.21
464.h264ref, 147.00, 152.00, 1.03, 160.00, 1.09, 1.05
471.omnetpp, 115.00, 116.00, 1.01, 140.00, 1.22, 1.21
473.astar, 133.00, 131.00, 0.98, 142.00, 1.07, 1.08
483.xalancbmk, 118.00, 120.00, 1.02, 154.00, 1.31, 1.28
433.milc, 19.80, 20.00, 1.01, 20.10, 1.02, 1.01
444.namd, 16.20, 16.20, 1.00, 17.60, 1.09, 1.09
447.dealII, 41.80, 42.20, 1.01, 43.50, 1.04, 1.03
450.soplex, 7.51, 7.82, 1.04, 8.25, 1.10, 1.05
453.povray, 14.00, 14.40, 1.03, 15.80, 1.13, 1.10
470.lbm, 33.30, 34.10, 1.02, 34.10, 1.02, 1.00
482.sphinx3, 12.40, 12.30, 0.99, 13.00, 1.05, 1.06
llvm-svn: 199488
2014-01-17 19:00:30 +08:00
|
|
|
// __sanitizer_cov();
|
2013-11-15 15:18:15 +08:00
|
|
|
// *Guard = 1;
|
|
|
|
// }
|
[asan] extend asan-coverage (still experimental).
- add a mode for collecting per-block coverage (-asan-coverage=2).
So far the implementation is naive (all blocks are instrumented),
the performance overhead on top of asan could be as high as 30%.
- Make sure the one-time calls to __sanitizer_cov are moved to function buttom,
which in turn required to copy the original debug info into the call insn.
Here is the performance data on SPEC 2006
(train data, comparing asan with asan-coverage={0,1,2}):
asan+cov0 asan+cov1 diff 0-1 asan+cov2 diff 0-2 diff 1-2
400.perlbench, 65.60, 65.80, 1.00, 76.20, 1.16, 1.16
401.bzip2, 65.10, 65.50, 1.01, 75.90, 1.17, 1.16
403.gcc, 1.64, 1.69, 1.03, 2.04, 1.24, 1.21
429.mcf, 21.90, 22.60, 1.03, 23.20, 1.06, 1.03
445.gobmk, 166.00, 169.00, 1.02, 205.00, 1.23, 1.21
456.hmmer, 88.30, 87.90, 1.00, 91.00, 1.03, 1.04
458.sjeng, 210.00, 222.00, 1.06, 258.00, 1.23, 1.16
462.libquantum, 1.73, 1.75, 1.01, 2.11, 1.22, 1.21
464.h264ref, 147.00, 152.00, 1.03, 160.00, 1.09, 1.05
471.omnetpp, 115.00, 116.00, 1.01, 140.00, 1.22, 1.21
473.astar, 133.00, 131.00, 0.98, 142.00, 1.07, 1.08
483.xalancbmk, 118.00, 120.00, 1.02, 154.00, 1.31, 1.28
433.milc, 19.80, 20.00, 1.01, 20.10, 1.02, 1.01
444.namd, 16.20, 16.20, 1.00, 17.60, 1.09, 1.09
447.dealII, 41.80, 42.20, 1.01, 43.50, 1.04, 1.03
450.soplex, 7.51, 7.82, 1.04, 8.25, 1.10, 1.05
453.povray, 14.00, 14.40, 1.03, 15.80, 1.13, 1.10
470.lbm, 33.30, 34.10, 1.02, 34.10, 1.02, 1.00
482.sphinx3, 12.40, 12.30, 0.99, 13.00, 1.05, 1.06
llvm-svn: 199488
2014-01-17 19:00:30 +08:00
|
|
|
// It's fine to call __sanitizer_cov more than once for a given block.
|
2013-11-15 15:18:15 +08:00
|
|
|
//
|
|
|
|
// Run-time:
|
[asan] extend asan-coverage (still experimental).
- add a mode for collecting per-block coverage (-asan-coverage=2).
So far the implementation is naive (all blocks are instrumented),
the performance overhead on top of asan could be as high as 30%.
- Make sure the one-time calls to __sanitizer_cov are moved to function buttom,
which in turn required to copy the original debug info into the call insn.
Here is the performance data on SPEC 2006
(train data, comparing asan with asan-coverage={0,1,2}):
asan+cov0 asan+cov1 diff 0-1 asan+cov2 diff 0-2 diff 1-2
400.perlbench, 65.60, 65.80, 1.00, 76.20, 1.16, 1.16
401.bzip2, 65.10, 65.50, 1.01, 75.90, 1.17, 1.16
403.gcc, 1.64, 1.69, 1.03, 2.04, 1.24, 1.21
429.mcf, 21.90, 22.60, 1.03, 23.20, 1.06, 1.03
445.gobmk, 166.00, 169.00, 1.02, 205.00, 1.23, 1.21
456.hmmer, 88.30, 87.90, 1.00, 91.00, 1.03, 1.04
458.sjeng, 210.00, 222.00, 1.06, 258.00, 1.23, 1.16
462.libquantum, 1.73, 1.75, 1.01, 2.11, 1.22, 1.21
464.h264ref, 147.00, 152.00, 1.03, 160.00, 1.09, 1.05
471.omnetpp, 115.00, 116.00, 1.01, 140.00, 1.22, 1.21
473.astar, 133.00, 131.00, 0.98, 142.00, 1.07, 1.08
483.xalancbmk, 118.00, 120.00, 1.02, 154.00, 1.31, 1.28
433.milc, 19.80, 20.00, 1.01, 20.10, 1.02, 1.01
444.namd, 16.20, 16.20, 1.00, 17.60, 1.09, 1.09
447.dealII, 41.80, 42.20, 1.01, 43.50, 1.04, 1.03
450.soplex, 7.51, 7.82, 1.04, 8.25, 1.10, 1.05
453.povray, 14.00, 14.40, 1.03, 15.80, 1.13, 1.10
470.lbm, 33.30, 34.10, 1.02, 34.10, 1.02, 1.00
482.sphinx3, 12.40, 12.30, 0.99, 13.00, 1.05, 1.06
llvm-svn: 199488
2014-01-17 19:00:30 +08:00
|
|
|
// - __sanitizer_cov(): record that we've executed the PC (GET_CALLER_PC).
|
2013-11-15 15:18:15 +08:00
|
|
|
// - __sanitizer_cov_dump: dump the coverage data to disk.
|
|
|
|
// For every module of the current process that has coverage data
|
|
|
|
// this will create a file module_name.PID.sancov. The file format is simple:
|
|
|
|
// it's just a sorted sequence of 4-byte offsets in the module.
|
|
|
|
//
|
|
|
|
// Eventually, this coverage implementation should be obsoleted by a more
|
|
|
|
// powerful general purpose Clang/LLVM coverage instrumentation.
|
|
|
|
// Consider this implementation as prototype.
|
|
|
|
//
|
|
|
|
// FIXME: support (or at least test with) dlclose.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "sanitizer_allocator_internal.h"
|
|
|
|
#include "sanitizer_common.h"
|
|
|
|
#include "sanitizer_libc.h"
|
|
|
|
#include "sanitizer_mutex.h"
|
|
|
|
#include "sanitizer_procmaps.h"
|
[asan] extend asan-coverage (still experimental).
- add a mode for collecting per-block coverage (-asan-coverage=2).
So far the implementation is naive (all blocks are instrumented),
the performance overhead on top of asan could be as high as 30%.
- Make sure the one-time calls to __sanitizer_cov are moved to function buttom,
which in turn required to copy the original debug info into the call insn.
Here is the performance data on SPEC 2006
(train data, comparing asan with asan-coverage={0,1,2}):
asan+cov0 asan+cov1 diff 0-1 asan+cov2 diff 0-2 diff 1-2
400.perlbench, 65.60, 65.80, 1.00, 76.20, 1.16, 1.16
401.bzip2, 65.10, 65.50, 1.01, 75.90, 1.17, 1.16
403.gcc, 1.64, 1.69, 1.03, 2.04, 1.24, 1.21
429.mcf, 21.90, 22.60, 1.03, 23.20, 1.06, 1.03
445.gobmk, 166.00, 169.00, 1.02, 205.00, 1.23, 1.21
456.hmmer, 88.30, 87.90, 1.00, 91.00, 1.03, 1.04
458.sjeng, 210.00, 222.00, 1.06, 258.00, 1.23, 1.16
462.libquantum, 1.73, 1.75, 1.01, 2.11, 1.22, 1.21
464.h264ref, 147.00, 152.00, 1.03, 160.00, 1.09, 1.05
471.omnetpp, 115.00, 116.00, 1.01, 140.00, 1.22, 1.21
473.astar, 133.00, 131.00, 0.98, 142.00, 1.07, 1.08
483.xalancbmk, 118.00, 120.00, 1.02, 154.00, 1.31, 1.28
433.milc, 19.80, 20.00, 1.01, 20.10, 1.02, 1.01
444.namd, 16.20, 16.20, 1.00, 17.60, 1.09, 1.09
447.dealII, 41.80, 42.20, 1.01, 43.50, 1.04, 1.03
450.soplex, 7.51, 7.82, 1.04, 8.25, 1.10, 1.05
453.povray, 14.00, 14.40, 1.03, 15.80, 1.13, 1.10
470.lbm, 33.30, 34.10, 1.02, 34.10, 1.02, 1.00
482.sphinx3, 12.40, 12.30, 0.99, 13.00, 1.05, 1.06
llvm-svn: 199488
2014-01-17 19:00:30 +08:00
|
|
|
#include "sanitizer_stacktrace.h"
|
2013-11-15 15:18:15 +08:00
|
|
|
#include "sanitizer_flags.h"
|
|
|
|
|
|
|
|
struct CovData {
|
|
|
|
BlockingMutex mu;
|
|
|
|
InternalMmapVector<uptr> v;
|
2014-02-13 16:50:36 +08:00
|
|
|
atomic_uint32_t guard;
|
2013-11-15 15:18:15 +08:00
|
|
|
};
|
|
|
|
|
2014-02-13 16:50:36 +08:00
|
|
|
static uptr cov_data_placeholder[(sizeof(CovData) / sizeof(uptr)) + 1];
|
2013-11-15 15:18:15 +08:00
|
|
|
COMPILER_CHECK(sizeof(cov_data_placeholder) >= sizeof(CovData));
|
|
|
|
static CovData *cov_data = reinterpret_cast<CovData*>(cov_data_placeholder);
|
|
|
|
|
|
|
|
namespace __sanitizer {
|
|
|
|
|
|
|
|
// Simply add the pc into the vector under lock. If the function is called more
|
|
|
|
// than once for a given PC it will be inserted multiple times, which is fine.
|
|
|
|
static void CovAdd(uptr pc) {
|
|
|
|
BlockingMutexLock lock(&cov_data->mu);
|
|
|
|
cov_data->v.push_back(pc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool CompareLess(const uptr &a, const uptr &b) {
|
|
|
|
return a < b;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dump the coverage on disk.
|
|
|
|
void CovDump() {
|
|
|
|
#if !SANITIZER_WINDOWS
|
2014-02-13 16:50:36 +08:00
|
|
|
if (atomic_fetch_add(&cov_data->guard, 1, memory_order_relaxed) != 0) return;
|
2013-11-15 15:18:15 +08:00
|
|
|
BlockingMutexLock lock(&cov_data->mu);
|
|
|
|
InternalMmapVector<uptr> &v = cov_data->v;
|
|
|
|
InternalSort(&v, v.size(), CompareLess);
|
|
|
|
InternalMmapVector<u32> offsets(v.size());
|
|
|
|
const uptr *vb = v.data();
|
|
|
|
const uptr *ve = vb + v.size();
|
|
|
|
MemoryMappingLayout proc_maps(/*cache_enabled*/false);
|
|
|
|
uptr mb, me, off, prot;
|
|
|
|
InternalScopedBuffer<char> module(4096);
|
|
|
|
InternalScopedBuffer<char> path(4096 * 2);
|
|
|
|
for (int i = 0;
|
|
|
|
proc_maps.Next(&mb, &me, &off, module.data(), module.size(), &prot);
|
|
|
|
i++) {
|
|
|
|
if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
|
|
|
|
continue;
|
|
|
|
if (vb >= ve) break;
|
|
|
|
if (mb <= *vb && *vb < me) {
|
|
|
|
offsets.clear();
|
|
|
|
const uptr *old_vb = vb;
|
|
|
|
CHECK_LE(off, *vb);
|
|
|
|
for (; vb < ve && *vb < me; vb++) {
|
|
|
|
uptr diff = *vb - (i ? mb : 0) + off;
|
|
|
|
CHECK_LE(diff, 0xffffffffU);
|
|
|
|
offsets.push_back(static_cast<u32>(diff));
|
|
|
|
}
|
|
|
|
char *module_name = StripModuleName(module.data());
|
|
|
|
internal_snprintf((char *)path.data(), path.size(), "%s.%zd.sancov",
|
|
|
|
module_name, internal_getpid());
|
|
|
|
InternalFree(module_name);
|
|
|
|
uptr fd = OpenFile(path.data(), true);
|
2014-02-12 23:29:22 +08:00
|
|
|
if (internal_iserror(fd)) {
|
|
|
|
Report(" CovDump: failed to open %s for writing\n", path.data());
|
|
|
|
} else {
|
|
|
|
internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
|
|
|
|
internal_close(fd);
|
|
|
|
VReport(1, " CovDump: %s: %zd PCs written\n", path.data(), vb - old_vb);
|
|
|
|
}
|
2013-11-15 15:18:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // !SANITIZER_WINDOWS
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace __sanitizer
|
|
|
|
|
|
|
|
extern "C" {
|
[asan] extend asan-coverage (still experimental).
- add a mode for collecting per-block coverage (-asan-coverage=2).
So far the implementation is naive (all blocks are instrumented),
the performance overhead on top of asan could be as high as 30%.
- Make sure the one-time calls to __sanitizer_cov are moved to function buttom,
which in turn required to copy the original debug info into the call insn.
Here is the performance data on SPEC 2006
(train data, comparing asan with asan-coverage={0,1,2}):
asan+cov0 asan+cov1 diff 0-1 asan+cov2 diff 0-2 diff 1-2
400.perlbench, 65.60, 65.80, 1.00, 76.20, 1.16, 1.16
401.bzip2, 65.10, 65.50, 1.01, 75.90, 1.17, 1.16
403.gcc, 1.64, 1.69, 1.03, 2.04, 1.24, 1.21
429.mcf, 21.90, 22.60, 1.03, 23.20, 1.06, 1.03
445.gobmk, 166.00, 169.00, 1.02, 205.00, 1.23, 1.21
456.hmmer, 88.30, 87.90, 1.00, 91.00, 1.03, 1.04
458.sjeng, 210.00, 222.00, 1.06, 258.00, 1.23, 1.16
462.libquantum, 1.73, 1.75, 1.01, 2.11, 1.22, 1.21
464.h264ref, 147.00, 152.00, 1.03, 160.00, 1.09, 1.05
471.omnetpp, 115.00, 116.00, 1.01, 140.00, 1.22, 1.21
473.astar, 133.00, 131.00, 0.98, 142.00, 1.07, 1.08
483.xalancbmk, 118.00, 120.00, 1.02, 154.00, 1.31, 1.28
433.milc, 19.80, 20.00, 1.01, 20.10, 1.02, 1.01
444.namd, 16.20, 16.20, 1.00, 17.60, 1.09, 1.09
447.dealII, 41.80, 42.20, 1.01, 43.50, 1.04, 1.03
450.soplex, 7.51, 7.82, 1.04, 8.25, 1.10, 1.05
453.povray, 14.00, 14.40, 1.03, 15.80, 1.13, 1.10
470.lbm, 33.30, 34.10, 1.02, 34.10, 1.02, 1.00
482.sphinx3, 12.40, 12.30, 0.99, 13.00, 1.05, 1.06
llvm-svn: 199488
2014-01-17 19:00:30 +08:00
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov() {
|
|
|
|
CovAdd(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()));
|
2013-11-15 15:18:15 +08:00
|
|
|
}
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
|
|
|
|
} // extern "C"
|