blob: 8fc2f5ca8329ba7ac6f9495f4a2e992977128a14 [file] [log] [blame]
Tri Vo5b40e892020-11-01 13:01:29 -08001/*
2 * Copyright (C) 2020 The Android Open Sourete Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "coverage"
18
Stephen Crane0d671312021-01-13 14:05:41 -080019#include <BufferAllocator/BufferAllocator.h>
Stephen Cranee9629302020-11-16 18:00:53 -080020#include <android-base/file.h>
Tri Vo5b40e892020-11-01 13:01:29 -080021#include <android-base/logging.h>
22#include <android-base/unique_fd.h>
23#include <assert.h>
Stephen Crane6bd77df2021-01-13 14:05:41 -080024#include <log/log.h>
Stephen Cranee9629302020-11-16 18:00:53 -080025#include <stdio.h>
Tri Vo5b40e892020-11-01 13:01:29 -080026#include <sys/mman.h>
27#include <sys/uio.h>
28#include <trusty/coverage/coverage.h>
Stephen Cranee9629302020-11-16 18:00:53 -080029#include <trusty/coverage/record.h>
Tri Vo5b40e892020-11-01 13:01:29 -080030#include <trusty/coverage/tipc.h>
31#include <trusty/tipc.h>
Tri Vo19eccb42021-02-10 15:29:57 -080032#include <iostream>
Tri Vo5b40e892020-11-01 13:01:29 -080033
34#define COVERAGE_CLIENT_PORT "com.android.trusty.coverage.client"
35
36namespace android {
37namespace trusty {
38namespace coverage {
39
40using android::base::ErrnoError;
41using android::base::Error;
42using std::string;
Tri Vo315967e2021-01-14 18:39:19 -080043using std::to_string;
Stephen Crane6bd77df2021-01-13 14:05:41 -080044using std::unique_ptr;
Tri Vo5b40e892020-11-01 13:01:29 -080045
Tri Vo5b40e892020-11-01 13:01:29 -080046CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid)
47 : tipc_dev_(std::move(tipc_dev)),
48 coverage_srv_fd_(-1),
49 uuid_(*uuid),
Stephen Crane6bd77df2021-01-13 14:05:41 -080050 sancov_filename_(),
51 record_len_(0),
52 shm_(NULL),
53 shm_len_(0) {}
54
Tri Vo315967e2021-01-14 18:39:19 -080055CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid, string module_name)
Stephen Crane6bd77df2021-01-13 14:05:41 -080056 : tipc_dev_(std::move(tipc_dev)),
57 coverage_srv_fd_(-1),
58 uuid_(*uuid),
Tri Vo315967e2021-01-14 18:39:19 -080059 sancov_filename_(module_name + "." + to_string(getpid()) + ".sancov"),
Tri Vo5b40e892020-11-01 13:01:29 -080060 record_len_(0),
61 shm_(NULL),
62 shm_len_(0) {}
63
64CoverageRecord::~CoverageRecord() {
65 if (shm_) {
Stephen Crane6bd77df2021-01-13 14:05:41 -080066 if (sancov_filename_) {
67 auto res = SaveSancovFile(*sancov_filename_);
68 if (!res.ok()) {
69 ALOGE("Could not write sancov file for module: %s\n", sancov_filename_->c_str());
70 }
71 }
72
Tri Vo5b40e892020-11-01 13:01:29 -080073 munmap((void*)shm_, shm_len_);
74 }
75}
76
77Result<void> CoverageRecord::Rpc(coverage_client_req* req, int req_fd, coverage_client_resp* resp) {
78 int rc;
79
80 if (req_fd < 0) {
81 rc = write(coverage_srv_fd_, req, sizeof(*req));
82 } else {
83 iovec iov = {
84 .iov_base = req,
85 .iov_len = sizeof(*req),
86 };
87
88 trusty_shm shm = {
89 .fd = req_fd,
90 .transfer = TRUSTY_SHARE,
91 };
92
93 rc = tipc_send(coverage_srv_fd_, &iov, 1, &shm, 1);
94 }
95
96 if (rc != (int)sizeof(*req)) {
97 return ErrnoError() << "failed to send request to coverage server: ";
98 }
99
100 rc = read(coverage_srv_fd_, resp, sizeof(*resp));
101 if (rc != (int)sizeof(*resp)) {
102 return ErrnoError() << "failed to read reply from coverage server: ";
103 }
104
105 if (resp->hdr.cmd != (req->hdr.cmd | COVERAGE_CLIENT_CMD_RESP_BIT)) {
106 return ErrnoError() << "unknown response cmd: " << resp->hdr.cmd;
107 }
108
109 return {};
110}
111
112Result<void> CoverageRecord::Open() {
113 coverage_client_req req;
114 coverage_client_resp resp;
115
116 if (shm_) {
117 return {}; /* already initialized */
118 }
119
120 int fd = tipc_connect(tipc_dev_.c_str(), COVERAGE_CLIENT_PORT);
121 if (fd < 0) {
Tri Vo19eccb42021-02-10 15:29:57 -0800122 // Don't error out to support fuzzing builds without coverage, e.g. for repros.
123 std::cerr << "WARNING!!! Failed to connect to Trusty coverarge server." << std::endl;
124 return {};
Tri Vo5b40e892020-11-01 13:01:29 -0800125 }
126 coverage_srv_fd_.reset(fd);
127
128 req.hdr.cmd = COVERAGE_CLIENT_CMD_OPEN;
129 req.open_args.uuid = uuid_;
130 auto ret = Rpc(&req, -1, &resp);
131 if (!ret.ok()) {
Tri Voce812a22021-02-10 13:31:22 -0800132 return Error() << "failed to open coverage client: " << ret.error();
Tri Vo5b40e892020-11-01 13:01:29 -0800133 }
134 record_len_ = resp.open_args.record_len;
Kalesh Singh623d1402023-09-06 11:32:53 -0700135 shm_len_ = record_len_;
Tri Vo5b40e892020-11-01 13:01:29 -0800136
Stephen Crane0d671312021-01-13 14:05:41 -0800137 BufferAllocator allocator;
138
139 fd = allocator.Alloc("system", shm_len_);
Tri Vo5b40e892020-11-01 13:01:29 -0800140 if (fd < 0) {
Stephen Crane0d671312021-01-13 14:05:41 -0800141 return ErrnoError() << "failed to create dmabuf of size " << shm_len_
142 << " err code: " << fd;
Tri Vo5b40e892020-11-01 13:01:29 -0800143 }
Stephen Crane0d671312021-01-13 14:05:41 -0800144 unique_fd dma_buf(fd);
Tri Vo5b40e892020-11-01 13:01:29 -0800145
Stephen Crane0d671312021-01-13 14:05:41 -0800146 void* shm = mmap(0, shm_len_, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0);
Tri Vo5b40e892020-11-01 13:01:29 -0800147 if (shm == MAP_FAILED) {
148 return ErrnoError() << "failed to map memfd: ";
149 }
150
151 req.hdr.cmd = COVERAGE_CLIENT_CMD_SHARE_RECORD;
152 req.share_record_args.shm_len = shm_len_;
Stephen Crane0d671312021-01-13 14:05:41 -0800153 ret = Rpc(&req, dma_buf, &resp);
Tri Vo5b40e892020-11-01 13:01:29 -0800154 if (!ret.ok()) {
Tri Voce812a22021-02-10 13:31:22 -0800155 return Error() << "failed to send shared memory: " << ret.error();
Tri Vo5b40e892020-11-01 13:01:29 -0800156 }
157
158 shm_ = shm;
159 return {};
160}
161
Tri Vo19eccb42021-02-10 15:29:57 -0800162bool CoverageRecord::IsOpen() {
163 return shm_;
164}
165
Stephen Cranee9629302020-11-16 18:00:53 -0800166void CoverageRecord::ResetFullRecord() {
167 auto header_region = GetRegionBounds(COV_START);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900168 if (!header_region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800169 // If the header cannot be parsed, we can't reset the proper region yet.
170 return;
171 }
172
173 for (size_t i = header_region->second; i < shm_len_; i++) {
Tri Vo5b40e892020-11-01 13:01:29 -0800174 *((volatile uint8_t*)shm_ + i) = 0;
175 }
176}
177
Stephen Cranee9629302020-11-16 18:00:53 -0800178void CoverageRecord::ResetCounts() {
179 volatile uint8_t* begin = nullptr;
180 volatile uint8_t* end = nullptr;
181 GetRawCounts(&begin, &end);
182
183 for (volatile uint8_t* x = begin; x < end; x++) {
184 *x = 0;
185 }
186}
187
188void CoverageRecord::ResetPCs() {
189 volatile uintptr_t* begin = nullptr;
190 volatile uintptr_t* end = nullptr;
191 GetRawPCs(&begin, &end);
192
193 for (volatile uintptr_t* x = begin; x < end; x++) {
194 *x = 0;
195 }
196}
197
198Result<std::pair<size_t, size_t>> CoverageRecord::GetRegionBounds(uint32_t region_type) {
199 assert(shm_);
200
201 auto header = (volatile struct coverage_record_header*)shm_;
202
203 if (header->type != COV_START) {
204 return Error() << "Header not yet valid";
205 }
206
207 for (++header; header->type != COV_TOTAL_LENGTH; ++header) {
208 if (header->type == region_type) {
209 // Coverage record must end with a COV_TOTAL_LENGTH header entry, so
210 // it is always safe to read the next entry since we don't iterate
211 // over the COV_TOTAL_LENGTH entry.
212 return {{header->offset, (header + 1)->offset}};
213 }
214 }
215
216 return Error() << "Could not find coverage region type: " << region_type;
217}
218
Tri Vo5b40e892020-11-01 13:01:29 -0800219void CoverageRecord::GetRawData(volatile void** begin, volatile void** end) {
220 assert(shm_);
221
222 *begin = shm_;
223 *end = (uint8_t*)(*begin) + record_len_;
224}
225
Stephen Cranee9629302020-11-16 18:00:53 -0800226void CoverageRecord::GetRawCounts(volatile uint8_t** begin, volatile uint8_t** end) {
227 auto region = GetRegionBounds(COV_8BIT_COUNTERS);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900228 if (!region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800229 *begin = 0;
230 *end = 0;
231 return;
232 }
233
234 assert(region->second <= record_len_);
235
236 *begin = (volatile uint8_t*)shm_ + region->first;
237 *end = (volatile uint8_t*)shm_ + region->second;
238}
239
240void CoverageRecord::GetRawPCs(volatile uintptr_t** begin, volatile uintptr_t** end) {
241 auto region = GetRegionBounds(COV_INSTR_PCS);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900242 if (!region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800243 *begin = 0;
244 *end = 0;
245 return;
246 }
247
248 assert(region->second <= record_len_);
249
250 *begin = (volatile uintptr_t*)((volatile uint8_t*)shm_ + region->first);
251 *end = (volatile uintptr_t*)((volatile uint8_t*)shm_ + region->second);
252}
253
254uint64_t CoverageRecord::TotalEdgeCounts() {
Tri Vo5b40e892020-11-01 13:01:29 -0800255 assert(shm_);
256
257 uint64_t counter = 0;
258
259 volatile uint8_t* begin = NULL;
260 volatile uint8_t* end = NULL;
261
Stephen Cranee9629302020-11-16 18:00:53 -0800262 GetRawCounts(&begin, &end);
Tri Vo5b40e892020-11-01 13:01:29 -0800263
264 for (volatile uint8_t* x = begin; x < end; x++) {
265 counter += *x;
266 }
267
268 return counter;
269}
270
Stephen Cranee9629302020-11-16 18:00:53 -0800271Result<void> CoverageRecord::SaveSancovFile(const std::string& filename) {
272 android::base::unique_fd output_fd(TEMP_FAILURE_RETRY(creat(filename.c_str(), 00644)));
273 if (!output_fd.ok()) {
274 return ErrnoError() << "Could not open sancov file";
275 }
276
277 uint64_t magic;
278 if (sizeof(uintptr_t) == 8) {
279 magic = 0xC0BFFFFFFFFFFF64;
280 } else if (sizeof(uintptr_t) == 4) {
281 magic = 0xC0BFFFFFFFFFFF32;
282 }
283 WriteFully(output_fd, &magic, sizeof(magic));
284
285 volatile uintptr_t* begin = nullptr;
286 volatile uintptr_t* end = nullptr;
287
288 GetRawPCs(&begin, &end);
289
290 for (volatile uintptr_t* pc_ptr = begin; pc_ptr < end; pc_ptr++) {
291 uintptr_t pc = *pc_ptr;
292 if (pc) {
293 WriteFully(output_fd, &pc, sizeof(pc));
294 }
295 }
296
297 return {};
298}
299
Tri Vo5b40e892020-11-01 13:01:29 -0800300} // namespace coverage
301} // namespace trusty
302} // namespace android