• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 Code Intelligence GmbH
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "sanitizer_hooks_with_pc.h"
16 
17 #include <algorithm>
18 #include <cmath>
19 #include <cstdint>
20 #include <iostream>
21 
22 #include "gtest/gtest.h"
23 
24 static std::vector<uint16_t> gCoverageMap(512);
25 
RecordCoverage()26 inline void __attribute__((always_inline)) RecordCoverage() {
27   auto return_address =
28       reinterpret_cast<uintptr_t>(__builtin_return_address(0));
29   auto idx = return_address & (gCoverageMap.size() - 1);
30   gCoverageMap[idx]++;
31 }
32 
33 extern "C" {
__sanitizer_cov_trace_cmp4(uint32_t arg1,uint32_t arg2)34 void __sanitizer_cov_trace_cmp4(uint32_t arg1, uint32_t arg2) {
35   RecordCoverage();
36 }
37 
__sanitizer_cov_trace_cmp8(uint64_t arg1,uint64_t arg2)38 void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2) {
39   RecordCoverage();
40 }
41 
__sanitizer_cov_trace_switch(uint64_t val,uint64_t * cases)42 void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
43   RecordCoverage();
44 }
45 
__sanitizer_cov_trace_div4(uint32_t val)46 void __sanitizer_cov_trace_div4(uint32_t val) { RecordCoverage(); }
47 
__sanitizer_cov_trace_div8(uint64_t val)48 void __sanitizer_cov_trace_div8(uint64_t val) { RecordCoverage(); }
49 
__sanitizer_cov_trace_gep(uintptr_t idx)50 void __sanitizer_cov_trace_gep(uintptr_t idx) { RecordCoverage(); }
51 
__sanitizer_cov_trace_pc_indir(uintptr_t callee)52 void __sanitizer_cov_trace_pc_indir(uintptr_t callee) { RecordCoverage(); }
53 }
54 
ClearCoverage()55 void ClearCoverage() { std::fill(gCoverageMap.begin(), gCoverageMap.end(), 0); }
56 
HasAllPcsCovered()57 bool HasAllPcsCovered() {
58   return 0 == std::count(gCoverageMap.cbegin(), gCoverageMap.cend(), 0);
59 }
60 
HasSingleCoveredPc()61 bool HasSingleCoveredPc() {
62   return gCoverageMap.size() - 1 ==
63          std::count(gCoverageMap.cbegin(), gCoverageMap.cend(), 0);
64 }
65 
PrettyPrintCoverage()66 std::string PrettyPrintCoverage() {
67   std::ostringstream out;
68   std::size_t break_after = 16;
69   out << "Coverage:" << std::endl;
70   for (uintptr_t i = 0; i < gCoverageMap.size(); i++) {
71     out << (gCoverageMap[i] ? "X" : "_");
72     if (i % break_after == break_after - 1) out << std::endl;
73   }
74   return out.str();
75 }
76 
77 class TestFakePcTrampoline : public ::testing::Test {
78  protected:
TestFakePcTrampoline()79   TestFakePcTrampoline() {
80     ClearCoverage();
81     CalibrateTrampoline();
82   }
83 };
84 
TEST_F(TestFakePcTrampoline,TraceCmp4Direct)85 TEST_F(TestFakePcTrampoline, TraceCmp4Direct) {
86   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
87     __sanitizer_cov_trace_cmp4(i, i);
88   }
89   EXPECT_TRUE(HasSingleCoveredPc()) << PrettyPrintCoverage();
90 }
91 
TEST_F(TestFakePcTrampoline,TraceCmp8Direct)92 TEST_F(TestFakePcTrampoline, TraceCmp8Direct) {
93   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
94     __sanitizer_cov_trace_cmp8(i, i);
95   }
96   EXPECT_TRUE(HasSingleCoveredPc()) << PrettyPrintCoverage();
97 }
98 
TEST_F(TestFakePcTrampoline,TraceSwitchDirect)99 TEST_F(TestFakePcTrampoline, TraceSwitchDirect) {
100   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
101     __sanitizer_cov_trace_switch(i, nullptr);
102   }
103   EXPECT_TRUE(HasSingleCoveredPc()) << PrettyPrintCoverage();
104 }
105 
TEST_F(TestFakePcTrampoline,TraceDiv4Direct)106 TEST_F(TestFakePcTrampoline, TraceDiv4Direct) {
107   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
108     __sanitizer_cov_trace_div4(i);
109   }
110   EXPECT_TRUE(HasSingleCoveredPc()) << PrettyPrintCoverage();
111 }
112 
TEST_F(TestFakePcTrampoline,TraceDiv8Direct)113 TEST_F(TestFakePcTrampoline, TraceDiv8Direct) {
114   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
115     __sanitizer_cov_trace_div8(i);
116   }
117   EXPECT_TRUE(HasSingleCoveredPc()) << PrettyPrintCoverage();
118 }
119 
TEST_F(TestFakePcTrampoline,TraceGepDirect)120 TEST_F(TestFakePcTrampoline, TraceGepDirect) {
121   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
122     __sanitizer_cov_trace_gep(i);
123   }
124   EXPECT_TRUE(HasSingleCoveredPc()) << PrettyPrintCoverage();
125 }
126 
TEST_F(TestFakePcTrampoline,TracePcIndirDirect)127 TEST_F(TestFakePcTrampoline, TracePcIndirDirect) {
128   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
129     __sanitizer_cov_trace_pc_indir(i);
130   }
131   EXPECT_TRUE(HasSingleCoveredPc()) << PrettyPrintCoverage();
132 }
133 
TEST_F(TestFakePcTrampoline,TraceCmp4Trampoline)134 TEST_F(TestFakePcTrampoline, TraceCmp4Trampoline) {
135   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
136     __sanitizer_cov_trace_cmp4_with_pc(reinterpret_cast<void *>(i), i, i);
137     EXPECT_EQ(1, gCoverageMap[i]);
138   }
139   EXPECT_TRUE(HasAllPcsCovered()) << PrettyPrintCoverage();
140 }
141 
TEST_F(TestFakePcTrampoline,TraceCmp8Trampoline)142 TEST_F(TestFakePcTrampoline, TraceCmp8Trampoline) {
143   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
144     __sanitizer_cov_trace_cmp8_with_pc(reinterpret_cast<void *>(i), i, i);
145     EXPECT_EQ(1, gCoverageMap[i]);
146   }
147   EXPECT_TRUE(HasAllPcsCovered()) << PrettyPrintCoverage();
148 }
149 
TEST_F(TestFakePcTrampoline,TraceSwitchTrampoline)150 TEST_F(TestFakePcTrampoline, TraceSwitchTrampoline) {
151   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
152     __sanitizer_cov_trace_switch_with_pc(reinterpret_cast<void *>(i), i,
153                                          nullptr);
154     EXPECT_EQ(1, gCoverageMap[i]);
155   }
156   EXPECT_TRUE(HasAllPcsCovered()) << PrettyPrintCoverage();
157 }
158 
TEST_F(TestFakePcTrampoline,TraceDiv4Trampoline)159 TEST_F(TestFakePcTrampoline, TraceDiv4Trampoline) {
160   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
161     __sanitizer_cov_trace_div4_with_pc(reinterpret_cast<void *>(i), i);
162     EXPECT_EQ(1, gCoverageMap[i]);
163   }
164   EXPECT_TRUE(HasAllPcsCovered()) << PrettyPrintCoverage();
165 }
166 
TEST_F(TestFakePcTrampoline,TraceDiv8Trampoline)167 TEST_F(TestFakePcTrampoline, TraceDiv8Trampoline) {
168   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
169     __sanitizer_cov_trace_div8_with_pc(reinterpret_cast<void *>(i), i);
170     EXPECT_EQ(1, gCoverageMap[i]);
171   }
172   EXPECT_TRUE(HasAllPcsCovered()) << PrettyPrintCoverage();
173 }
174 
TEST_F(TestFakePcTrampoline,TraceGepTrampoline)175 TEST_F(TestFakePcTrampoline, TraceGepTrampoline) {
176   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
177     __sanitizer_cov_trace_gep_with_pc(reinterpret_cast<void *>(i), i);
178     EXPECT_EQ(1, gCoverageMap[i]);
179   }
180   EXPECT_TRUE(HasAllPcsCovered()) << PrettyPrintCoverage();
181 }
182 
TEST_F(TestFakePcTrampoline,TracePcIndirTrampoline)183 TEST_F(TestFakePcTrampoline, TracePcIndirTrampoline) {
184   for (uint32_t i = 0; i < gCoverageMap.size(); ++i) {
185     __sanitizer_cov_trace_pc_indir_with_pc(reinterpret_cast<void *>(i), i);
186   }
187   EXPECT_TRUE(HasAllPcsCovered()) << PrettyPrintCoverage();
188 }
189