Skip to content

Commit aaa6370

Browse files
committedDec 12, 2016
[sancov] __sanitizer_dump_coverage api
Subscribers: kubabrecka, mgorny Differential Revision: https://reviews.llvm.org/D26758 llvm-svn: 289498
1 parent e96abc6 commit aaa6370

8 files changed

+296
-5
lines changed
 

‎compiler-rt/include/sanitizer/coverage_interface.h

+5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ extern "C" {
2323
void __sanitizer_cov_init();
2424
// Record and dump coverage info.
2525
void __sanitizer_cov_dump();
26+
27+
// Dump collected coverage info. Sorts pcs by module into individual
28+
// .sancov files.
29+
void __sanitizer_dump_coverage(const uintptr_t *pcs, uintptr_t len);
30+
2631
// Open <name>.sancov.packed in the coverage directory and return the file
2732
// descriptor. Returns -1 on failure, or if coverage dumping is disabled.
2833
// This is intended for use by sandboxing code.

‎compiler-rt/lib/sanitizer_common/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ set(SANITIZER_NOLIBC_SOURCES
5353
set(SANITIZER_LIBCDEP_SOURCES
5454
sanitizer_common_libcdep.cc
5555
sanitizer_coverage_libcdep.cc
56+
sanitizer_coverage_libcdep_new.cc
5657
sanitizer_coverage_mapping_libcdep.cc
5758
sanitizer_linux_libcdep.cc
5859
sanitizer_posix_libcdep.cc

‎compiler-rt/lib/sanitizer_common/sanitizer_common.h

+7
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,13 @@ class InternalMmapVectorNoCtor {
547547
uptr capacity() const {
548548
return capacity_;
549549
}
550+
void resize(uptr new_size) {
551+
Resize(new_size);
552+
if (new_size > size_) {
553+
internal_memset(&data_[size_], 0, sizeof(T) * (new_size - size_));
554+
}
555+
size_ = new_size;
556+
}
550557

551558
void clear() { size_ = 0; }
552559
bool empty() const { return size() == 0; }

‎compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc

+1-4
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() {
954954
}
955955
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
956956
coverage_data.DumpAll();
957+
__sanitizer_dump_trace_pc_guard_coverage();
957958
}
958959
SANITIZER_INTERFACE_ATTRIBUTE void
959960
__sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters,
@@ -1036,10 +1037,6 @@ void __sanitizer_cov_trace_div8() {}
10361037
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
10371038
void __sanitizer_cov_trace_gep() {}
10381039
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
1039-
void __sanitizer_cov_trace_pc_guard() {}
1040-
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
10411040
void __sanitizer_cov_trace_pc_indir() {}
1042-
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
1043-
void __sanitizer_cov_trace_pc_guard_init() {}
10441041
#endif // !SANITIZER_WINDOWS
10451042
} // extern "C"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
//===-- sanitizer_coverage_libcdep_new.cc ---------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
// Sanitizer Coverage Controller for Trace PC Guard.
10+
11+
#include "sanitizer_allocator_internal.h"
12+
#include "sanitizer_atomic.h"
13+
#include "sanitizer_common.h"
14+
#include "sanitizer_symbolizer.h"
15+
16+
using namespace __sanitizer;
17+
18+
using AddressRange = LoadedModule::AddressRange;
19+
20+
namespace {
21+
22+
static const u64 Magic64 = 0xC0BFFFFFFFFFFF64ULL;
23+
static const u64 Magic32 = 0xC0BFFFFFFFFFFF32ULL;
24+
static const u64 Magic = SANITIZER_WORDSIZE == 64 ? Magic64 : Magic32;
25+
26+
static fd_t OpenFile(const char* path) {
27+
error_t err;
28+
fd_t fd = OpenFile(path, WrOnly, &err);
29+
if (fd == kInvalidFd)
30+
Report("SanitizerCoverage: failed to open %s for writing (reason: %d)\n",
31+
path, err);
32+
return fd;
33+
}
34+
35+
static void GetCoverageFilename(char* path, const char* name,
36+
const char* extension) {
37+
CHECK(name);
38+
internal_snprintf(path, kMaxPathLength, "%s/%s.%zd.%s",
39+
common_flags()->coverage_dir, name, internal_getpid(),
40+
extension);
41+
}
42+
43+
static void WriteModuleCoverage(char* file_path, const char* module_name,
44+
const uptr* pcs, uptr len) {
45+
GetCoverageFilename(file_path, StripModuleName(module_name), "sancov");
46+
fd_t fd = OpenFile(file_path);
47+
WriteToFile(fd, &Magic, sizeof(Magic));
48+
WriteToFile(fd, pcs, len * sizeof(*pcs));
49+
CloseFile(fd);
50+
Printf("SanitizerCoverage: %s %zd PCs written\n", file_path, len);
51+
}
52+
53+
static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) {
54+
if (!len) return;
55+
56+
char* file_path = static_cast<char*>(InternalAlloc(kMaxPathLength));
57+
char* module_name = static_cast<char*>(InternalAlloc(kMaxPathLength));
58+
uptr* pcs = static_cast<uptr*>(InternalAlloc(len * sizeof(uptr)));
59+
60+
internal_memcpy(pcs, unsorted_pcs, len * sizeof(uptr));
61+
SortArray(pcs, len);
62+
63+
bool module_found = false;
64+
uptr last_base = 0;
65+
uptr module_start_idx = 0;
66+
67+
for (uptr i = 0; i < len; ++i) {
68+
const uptr pc = pcs[i];
69+
if (!pc) continue;
70+
71+
if (!__sanitizer_get_module_and_offset_for_pc(pc, nullptr, 0, &pcs[i])) {
72+
Printf("ERROR: bad pc %x\n", pc);
73+
continue;
74+
}
75+
uptr module_base = pc - pcs[i];
76+
77+
if (module_base != last_base || !module_found) {
78+
if (module_found) {
79+
WriteModuleCoverage(file_path, module_name, &pcs[module_start_idx],
80+
i - module_start_idx);
81+
}
82+
83+
last_base = module_base;
84+
module_start_idx = i;
85+
module_found = true;
86+
__sanitizer_get_module_and_offset_for_pc(pc, module_name, kMaxPathLength,
87+
&pcs[i]);
88+
}
89+
}
90+
91+
if (module_found) {
92+
WriteModuleCoverage(file_path, module_name, &pcs[module_start_idx],
93+
len - module_start_idx);
94+
}
95+
96+
InternalFree(file_path);
97+
InternalFree(module_name);
98+
InternalFree(pcs);
99+
}
100+
101+
// Collects trace-pc guard coverage.
102+
// This class relies on zero-initialization.
103+
class TracePcGuardController {
104+
public:
105+
void Initialize() {
106+
CHECK(!initialized);
107+
108+
initialized = true;
109+
pc_vector.Initialize(0);
110+
}
111+
112+
void InitTracePcGuard(u32* start, u32* end) {
113+
if (!initialized) Initialize();
114+
CHECK(!*start);
115+
CHECK_NE(start, end);
116+
117+
u32 i = pc_vector.size();
118+
for (u32* p = start; p < end; p++) *p = ++i;
119+
pc_vector.resize(i);
120+
}
121+
122+
void TracePcGuard(u32* guard, uptr pc) {
123+
atomic_uint32_t* guard_ptr = reinterpret_cast<atomic_uint32_t*>(guard);
124+
u32 idx = atomic_exchange(guard_ptr, 0, memory_order_relaxed);
125+
if (!idx) return;
126+
// we start indices from 1.
127+
pc_vector[idx - 1] = pc;
128+
}
129+
130+
void Dump() {
131+
if (!initialized) return;
132+
__sanitizer_dump_coverage(pc_vector.data(), pc_vector.size());
133+
}
134+
135+
private:
136+
bool initialized;
137+
InternalMmapVectorNoCtor<uptr> pc_vector;
138+
};
139+
140+
static TracePcGuardController pc_guard_controller;
141+
142+
}; // namespace
143+
144+
extern "C" {
145+
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage( // NOLINT
146+
const uptr* pcs, uptr len) {
147+
return SanitizerDumpCoverage(pcs, len);
148+
}
149+
150+
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
151+
__sanitizer_cov_trace_pc_guard(u32* guard) {
152+
if (!*guard) return;
153+
pc_guard_controller.TracePcGuard(guard, GET_CALLER_PC() - 1);
154+
}
155+
156+
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
157+
__sanitizer_cov_trace_pc_guard_init(u32* start, u32* end) {
158+
if (start == end || *start) return;
159+
pc_guard_controller.InitTracePcGuard(start, end);
160+
}
161+
162+
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage() {
163+
pc_guard_controller.Dump();
164+
}
165+
} // extern "C"

‎compiler-rt/lib/sanitizer_common/sanitizer_interface_internal.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,12 @@ extern "C" {
4646
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
4747
void __sanitizer_report_error_summary(const char *error_summary);
4848

49-
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
5049
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init();
50+
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
51+
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(
52+
const __sanitizer::uptr *pcs, const __sanitizer::uptr len);
53+
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage();
54+
5155
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(__sanitizer::u32 *guard);
5256
SANITIZER_INTERFACE_ATTRIBUTE
5357
void __sanitizer_annotate_contiguous_container(const void *beg,
@@ -60,6 +64,11 @@ extern "C" {
6064
SANITIZER_INTERFACE_ATTRIBUTE
6165
const void *__sanitizer_contiguous_container_find_bad_address(
6266
const void *beg, const void *mid, const void *end);
67+
68+
SANITIZER_INTERFACE_ATTRIBUTE
69+
int __sanitizer_get_module_and_offset_for_pc(
70+
__sanitizer::uptr pc, char *module_path,
71+
__sanitizer::uptr module_path_len, __sanitizer::uptr *pc_offset);
6372
} // extern "C"
6473

6574
#endif // SANITIZER_INTERFACE_INTERNAL_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Tests trace pc guard coverage collection.
2+
//
3+
// REQUIRES: has_sancovcc
4+
// XFAIL: tsan
5+
//
6+
// RUN: DIR=%t_workdir
7+
// RUN: CLANG_ARGS="-O0 -fsanitize-coverage=trace-pc-guard"
8+
// RUN: rm -rf $DIR
9+
// RUN: mkdir -p $DIR
10+
// RUN: cd $DIR
11+
// RUN: %clangxx -DSHARED1 $CLANG_ARGS -shared %s -o %t_1.so -fPIC
12+
// RUN: %clangxx -DSHARED2 $CLANG_ARGS -shared %s -o %t_2.so -fPIC
13+
// RUN: %clangxx -DMAIN $CLANG_ARGS %s -o %t %t_1.so %t_2.so
14+
// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
15+
// RUN: %sancovcc -covered-functions -strip_path_prefix=TestCases/ *.sancov \
16+
// RUN: %t %t_1.so %t_2.so 2>&1 | \
17+
// RUN: FileCheck --check-prefix=CHECK-SANCOV %s
18+
// RUN: rm -rf $DIR
19+
20+
#include <stdio.h>
21+
22+
extern "C" {
23+
int bar();
24+
int baz();
25+
}
26+
27+
#ifdef MAIN
28+
29+
int foo() {
30+
fprintf(stderr, "foo\n");
31+
return 1;
32+
}
33+
34+
int main() {
35+
fprintf(stderr, "main\n");
36+
foo();
37+
bar();
38+
baz();
39+
}
40+
41+
#endif // MAIN
42+
43+
extern "C" {
44+
45+
#ifdef SHARED1
46+
int bar() {
47+
fprintf(stderr, "bar\n");
48+
return 1;
49+
}
50+
#endif
51+
52+
#ifdef SHARED2
53+
int baz() {
54+
fprintf(stderr, "baz\n");
55+
return 1;
56+
}
57+
#endif
58+
59+
} // extern "C"
60+
61+
// CHECK: main
62+
// CHECK-NEXT: foo
63+
// CHECK-NEXT: bar
64+
// CHECK-NEXT: baz
65+
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}.sancov 2 PCs written
66+
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_2.so.{{.*}}.sancov 1 PCs written
67+
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard-dso.{{.*}}_1.so.{{.*}}.sancov 1 PCs written
68+
//
69+
// CHECK-SANCOV: Ignoring {{.*}}_1.so and its coverage because __sanitizer_cov* functions were not found.
70+
// CHECK-SANCOV: Ignoring {{.*}}_2.so and its coverage because __sanitizer_cov* functions were not found.
71+
// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:29 foo
72+
// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard-dso.cc:34 main
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Tests trace pc guard coverage collection.
2+
//
3+
// REQUIRES: has_sancovcc
4+
// XFAIL: tsan
5+
//
6+
// RUN: DIR=%t_workdir
7+
// RUN: rm -rf $DIR
8+
// RUN: mkdir -p $DIR
9+
// RUN: cd $DIR
10+
// RUN: %clangxx -O0 -fsanitize-coverage=trace-pc-guard %s -ldl -o %t
11+
// RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s
12+
// RUN: %sancovcc -covered-functions -strip_path_prefix=TestCases/ *.sancov %t 2>&1 | \
13+
// RUN: FileCheck --check-prefix=CHECK-SANCOV %s
14+
// RUN: rm -rf $DIR
15+
16+
#include <stdio.h>
17+
18+
int foo() {
19+
fprintf(stderr, "foo\n");
20+
return 1;
21+
}
22+
23+
int main() {
24+
fprintf(stderr, "main\n");
25+
foo();
26+
foo();
27+
}
28+
29+
// CHECK: main
30+
// CHECK-NEXT: foo
31+
// CHECK-NEXT: foo
32+
// CHECK-NEXT: SanitizerCoverage: ./sanitizer_coverage_trace_pc_guard.{{.*}}.sancov 2 PCs written
33+
//
34+
// CHECK-SANCOV: sanitizer_coverage_trace_pc_guard.cc:18 foo
35+
// CHECK-SANCOV-NEXT: sanitizer_coverage_trace_pc_guard.cc:23 main

0 commit comments

Comments
 (0)
Please sign in to comment.