[compiler-rt] r231413 - [sanitizer] Reconstruct the function that dumps block/edge coverage, hopefully making it more robust. Also increase the allowed coverage size on 32-bit.
Kostya Serebryany
kcc at google.com
Thu Mar 5 14:19:25 PST 2015
Author: kcc
Date: Thu Mar 5 16:19:25 2015
New Revision: 231413
URL: http://llvm.org/viewvc/llvm-project?rev=231413&view=rev
Log:
[sanitizer] Reconstruct the function that dumps block/edge coverage, hopefully making it more robust. Also increase the allowed coverage size on 32-bit.
Modified:
compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc
compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc
compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc
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=231413&r1=231412&r2=231413&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Thu Mar 5 16:19:25 2015
@@ -79,6 +79,8 @@ class CoverageData {
void DumpTrace();
void DumpAsBitSet();
void DumpCounters();
+ void DumpOffsets();
+ void DumpAll();
ALWAYS_INLINE
void TraceBasicBlock(s32 *id);
@@ -98,7 +100,7 @@ class CoverageData {
private:
// Maximal size pc array may ever grow.
// We MmapNoReserve this space to ensure that the array is contiguous.
- static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 24, 1 << 27);
+ static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 27);
// The amount file mapping for the pc array is grown by.
static const uptr kPcArrayMmapSize = 64 * 1024;
@@ -520,23 +522,23 @@ static void CovWritePacked(int pid, cons
// If packed = true and name == 0: <pid>.<sancov>.<packed>.
// If packed = true and name != 0: <name>.<sancov>.<packed> (name is
// user-supplied).
-static int CovOpenFile(bool packed, const char *name,
- const char *extension = "sancov") {
- InternalScopedString path(kMaxPathLength);
+static int CovOpenFile(InternalScopedString *path, bool packed,
+ const char *name, const char *extension = "sancov") {
+ path->clear();
if (!packed) {
CHECK(name);
- path.append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(),
+ path->append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(),
extension);
} else {
if (!name)
- path.append("%s/%zd.%s.packed", coverage_dir, internal_getpid(),
+ path->append("%s/%zd.%s.packed", coverage_dir, internal_getpid(),
extension);
else
- path.append("%s/%s.%s.packed", coverage_dir, name, extension);
+ path->append("%s/%s.%s.packed", coverage_dir, name, extension);
}
- uptr fd = OpenFile(path.data(), true);
+ uptr fd = OpenFile(path->data(), true);
if (internal_iserror(fd)) {
- Report(" SanitizerCoverage: failed to open %s for writing\n", path.data());
+ Report(" SanitizerCoverage: failed to open %s for writing\n", path->data());
return -1;
}
return fd;
@@ -557,12 +559,13 @@ void CoverageData::DumpTrace() {
&module_address);
out.append("%s 0x%zx\n", module_name, module_address);
}
- int fd = CovOpenFile(false, "trace-points");
+ InternalScopedString path(kMaxPathLength);
+ int fd = CovOpenFile(&path, false, "trace-points");
if (fd < 0) return;
internal_write(fd, out.data(), out.length());
internal_close(fd);
- fd = CovOpenFile(false, "trace-compunits");
+ fd = CovOpenFile(&path, false, "trace-compunits");
if (fd < 0) return;
out.clear();
for (uptr i = 0; i < comp_unit_name_vec.size(); i++)
@@ -570,7 +573,7 @@ void CoverageData::DumpTrace() {
internal_write(fd, out.data(), out.length());
internal_close(fd);
- fd = CovOpenFile(false, "trace-events");
+ fd = CovOpenFile(&path, false, "trace-events");
if (fd < 0) return;
uptr bytes_to_write = max_idx * sizeof(tr_event_array[0]);
u8 *event_bytes = reinterpret_cast<u8*>(tr_event_array);
@@ -621,7 +624,8 @@ void CoverageData::DumpCallerCalleePairs
callee_module_address);
}
}
- int fd = CovOpenFile(false, "caller-callee");
+ InternalScopedString path(kMaxPathLength);
+ int fd = CovOpenFile(&path, false, "caller-callee");
if (fd < 0) return;
internal_write(fd, out.data(), out.length());
internal_close(fd);
@@ -647,6 +651,7 @@ void CoverageData::DumpCounters() {
if (!n) return;
InternalScopedBuffer<u8> bitset(n);
coverage_data.Update8bitCounterBitsetAndClearCounters(bitset.data());
+ InternalScopedString path(kMaxPathLength);
for (uptr m = 0; m < module_name_vec.size(); m++) {
auto r = module_name_vec[m];
@@ -654,7 +659,8 @@ void CoverageData::DumpCounters() {
CHECK_LE(r.beg, r.end);
CHECK_LE(r.end, size());
const char *base_name = StripModuleName(r.name);
- int fd = CovOpenFile(/* packed */ false, base_name, "counters-sancov");
+ int fd =
+ CovOpenFile(&path, /* packed */ false, base_name, "counters-sancov");
if (fd < 0) return;
internal_write(fd, bitset.data() + r.beg, r.end - r.beg);
internal_close(fd);
@@ -667,6 +673,7 @@ void CoverageData::DumpAsBitSet() {
if (!common_flags()->coverage_bitset) return;
if (!size()) return;
InternalScopedBuffer<char> out(size());
+ InternalScopedString path(kMaxPathLength);
for (uptr m = 0; m < module_name_vec.size(); m++) {
uptr n_set_bits = 0;
auto r = module_name_vec[m];
@@ -680,7 +687,7 @@ void CoverageData::DumpAsBitSet() {
n_set_bits++;
}
const char *base_name = StripModuleName(r.name);
- int fd = CovOpenFile(/* packed */ false, base_name, "bitset-sancov");
+ int fd = CovOpenFile(&path, /* packed */ false, base_name, "bitset-sancov");
if (fd < 0) return;
internal_write(fd, out.data() + r.beg, r.end - r.beg);
internal_close(fd);
@@ -690,67 +697,58 @@ void CoverageData::DumpAsBitSet() {
}
}
-// Dump the coverage on disk.
-static void CovDump() {
- if (!coverage_enabled || common_flags()->coverage_direct) return;
-#if !SANITIZER_WINDOWS
- if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
- return;
- coverage_data.DumpAsBitSet();
- coverage_data.DumpCounters();
- coverage_data.DumpTrace();
+void CoverageData::DumpOffsets() {
+ auto sym = Symbolizer::GetOrInit();
if (!common_flags()->coverage_pcs) return;
- uptr size = coverage_data.size();
- InternalMmapVector<u32> offsets(size);
- uptr *vb = coverage_data.data();
- uptr *ve = vb + size;
- SortArray(vb, size);
- MemoryMappingLayout proc_maps(/*cache_enabled*/true);
- uptr mb, me, off, prot;
- InternalScopedString module(kMaxPathLength);
+ CHECK_NE(sym, nullptr);
+ InternalMmapVector<u32> offsets(0);
InternalScopedString path(kMaxPathLength);
- for (int i = 0;
- proc_maps.Next(&mb, &me, &off, module.data(), module.size(), &prot);
- i++) {
- if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
- continue;
- while (vb < ve && *vb < mb) vb++;
- if (vb >= ve) break;
- if (*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));
- }
- const char *module_name = StripModuleName(module.data());
- if (cov_sandboxed) {
- if (cov_fd >= 0) {
- CovWritePacked(internal_getpid(), module_name, offsets.data(),
- offsets.size() * sizeof(u32));
- VReport(1, " CovDump: %zd PCs written to packed file\n", vb - old_vb);
- }
- } else {
- // One file per module per process.
- path.clear();
- path.append("%s/%s.%zd.sancov", coverage_dir, module_name,
- internal_getpid());
- int fd = CovOpenFile(false /* packed */, module_name);
- if (fd > 0) {
- 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);
- }
+ for (uptr m = 0; m < module_name_vec.size(); m++) {
+ offsets.clear();
+ auto r = module_name_vec[m];
+ CHECK(r.name);
+ CHECK_LE(r.beg, r.end);
+ CHECK_LE(r.end, size());
+ const char *module_name = "<unknown>";
+ for (uptr i = r.beg; i < r.end; i++) {
+ uptr pc = data()[i];
+ if (!pc) continue; // Not visited.
+ uptr offset = 0;
+ sym->GetModuleNameAndOffsetForPC(pc, &module_name, &offset);
+ if (!offset || offset > 0xffffffffU) continue;
+ offsets.push_back(static_cast<u32>(offset));
+ }
+ module_name = StripModuleName(r.name);
+ if (cov_sandboxed) {
+ if (cov_fd >= 0) {
+ CovWritePacked(internal_getpid(), module_name, offsets.data(),
+ offsets.size() * sizeof(u32));
+ VReport(1, " CovDump: %zd PCs written to packed file\n",
+ offsets.size());
}
+ } else {
+ // One file per module per process.
+ int fd = CovOpenFile(&path, false /* packed */, module_name);
+ if (fd < 0) continue;
+ internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
+ internal_close(fd);
+ VReport(1, " CovDump: %s: %zd PCs written\n", path.data(),
+ offsets.size());
}
}
if (cov_fd >= 0)
internal_close(cov_fd);
- coverage_data.DumpCallerCalleePairs();
-#endif // !SANITIZER_WINDOWS
+}
+
+void CoverageData::DumpAll() {
+ if (!coverage_enabled || common_flags()->coverage_direct) return;
+ if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
+ return;
+ DumpAsBitSet();
+ DumpCounters();
+ DumpTrace();
+ DumpOffsets();
+ DumpCallerCalleePairs();
}
void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
@@ -760,15 +758,18 @@ void CovPrepareForSandboxing(__sanitizer
if (!cov_sandboxed) return;
cov_fd = args->coverage_fd;
cov_max_block_size = args->coverage_max_block_size;
- if (cov_fd < 0)
+ if (cov_fd < 0) {
+ InternalScopedString path(kMaxPathLength);
// Pre-open the file now. The sandbox won't allow us to do it later.
- cov_fd = CovOpenFile(true /* packed */, 0);
+ cov_fd = CovOpenFile(&path, true /* packed */, 0);
+ }
}
int MaybeOpenCovFile(const char *name) {
CHECK(name);
if (!coverage_enabled) return -1;
- return CovOpenFile(true /* packed */, name);
+ InternalScopedString path(kMaxPathLength);
+ return CovOpenFile(&path, true /* packed */, name);
}
void CovBeforeFork() {
@@ -824,7 +825,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __san
coverage_dir = common_flags()->coverage_dir;
coverage_data.Init();
}
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
+ coverage_data.DumpAll();
+}
SANITIZER_INTERFACE_ATTRIBUTE void
__sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters,
const char *comp_unit_name) {
Modified: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc?rev=231413&r1=231412&r2=231413&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc Thu Mar 5 16:19:25 2015
@@ -50,7 +50,7 @@ int main(int argc, char **argv) {
// CHECK: PID: [[PID:[0-9]+]]
// CHECK: [[PID]].sancov: 1 PCs written
-// CHECK: .so.[[PID]]
-// If we get coverage for both DSOs, it means the module wasn't unloaded and
-// this test is useless.
-// CHECK-NOT: .so.[[PID]]
+// CHECK: test_1.so.[[PID]]
+// CHECK: test_2.so.[[PID]]
+// Even though we've unloaded one of the libs we still dump the coverage file
+// for that lib (although the data will be inaccurate, it at all useful)
Modified: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc?rev=231413&r1=231412&r2=231413&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc Thu Mar 5 16:19:25 2015
@@ -78,8 +78,8 @@ int main(int argc, char **argv) {
#endif
// CHECK-vanilla: PID: [[PID:[0-9]+]]
-// CHECK-vanilla: [[PID]].sancov: 1 PCs written
// CHECK-vanilla: .so.[[PID]].sancov: 258 PCs written
+// CHECK-vanilla: [[PID]].sancov: 1 PCs written
// CHECK-sandbox: PID: [[PID:[0-9]+]]
// CHECK-sandbox: 258 PCs written to packed file
Modified: compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc?rev=231413&r1=231412&r2=231413&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc Thu Mar 5 16:19:25 2015
@@ -57,12 +57,12 @@ int main(int argc, char **argv) {
// CHECK-foo-NOT: .so.[[PID]]
//
// CHECK-bar: PID: [[PID:[0-9]+]]
-// CHECK-bar: [[PID]].sancov: 1 PCs written
// CHECK-bar: .so.[[PID]].sancov: 1 PCs written
+// CHECK-bar: [[PID]].sancov: 1 PCs written
//
// CHECK-foo-bar: PID: [[PID:[0-9]+]]
-// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
// CHECK-foo-bar: so.[[PID]].sancov: 1 PCs written
+// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
//
// CHECK-report: AddressSanitizer: global-buffer-overflow
// CHECK-report: PCs written
More information about the llvm-commits
mailing list