blob: ff2bcaa1174b3fb1811581eec79f40cab5ebecc0 [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 Cranee9629302020-11-16 18:00:53 -080024#include <stdio.h>
Tri Vo5b40e892020-11-01 13:01:29 -080025#include <sys/mman.h>
26#include <sys/uio.h>
27#include <trusty/coverage/coverage.h>
Stephen Cranee9629302020-11-16 18:00:53 -080028#include <trusty/coverage/record.h>
Tri Vo5b40e892020-11-01 13:01:29 -080029#include <trusty/coverage/tipc.h>
30#include <trusty/tipc.h>
31
32#define COVERAGE_CLIENT_PORT "com.android.trusty.coverage.client"
33
34namespace android {
35namespace trusty {
36namespace coverage {
37
38using android::base::ErrnoError;
39using android::base::Error;
40using std::string;
41
42static inline uintptr_t RoundPageUp(uintptr_t val) {
43 return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
44}
45
46CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid)
47 : tipc_dev_(std::move(tipc_dev)),
48 coverage_srv_fd_(-1),
49 uuid_(*uuid),
50 record_len_(0),
51 shm_(NULL),
52 shm_len_(0) {}
53
54CoverageRecord::~CoverageRecord() {
55 if (shm_) {
56 munmap((void*)shm_, shm_len_);
57 }
58}
59
60Result<void> CoverageRecord::Rpc(coverage_client_req* req, int req_fd, coverage_client_resp* resp) {
61 int rc;
62
63 if (req_fd < 0) {
64 rc = write(coverage_srv_fd_, req, sizeof(*req));
65 } else {
66 iovec iov = {
67 .iov_base = req,
68 .iov_len = sizeof(*req),
69 };
70
71 trusty_shm shm = {
72 .fd = req_fd,
73 .transfer = TRUSTY_SHARE,
74 };
75
76 rc = tipc_send(coverage_srv_fd_, &iov, 1, &shm, 1);
77 }
78
79 if (rc != (int)sizeof(*req)) {
80 return ErrnoError() << "failed to send request to coverage server: ";
81 }
82
83 rc = read(coverage_srv_fd_, resp, sizeof(*resp));
84 if (rc != (int)sizeof(*resp)) {
85 return ErrnoError() << "failed to read reply from coverage server: ";
86 }
87
88 if (resp->hdr.cmd != (req->hdr.cmd | COVERAGE_CLIENT_CMD_RESP_BIT)) {
89 return ErrnoError() << "unknown response cmd: " << resp->hdr.cmd;
90 }
91
92 return {};
93}
94
95Result<void> CoverageRecord::Open() {
96 coverage_client_req req;
97 coverage_client_resp resp;
98
99 if (shm_) {
100 return {}; /* already initialized */
101 }
102
103 int fd = tipc_connect(tipc_dev_.c_str(), COVERAGE_CLIENT_PORT);
104 if (fd < 0) {
105 return ErrnoError() << "failed to connect to Trusty coverarge server: ";
106 }
107 coverage_srv_fd_.reset(fd);
108
109 req.hdr.cmd = COVERAGE_CLIENT_CMD_OPEN;
110 req.open_args.uuid = uuid_;
111 auto ret = Rpc(&req, -1, &resp);
112 if (!ret.ok()) {
113 return Error() << "failed to open coverage client: ";
114 }
115 record_len_ = resp.open_args.record_len;
116 shm_len_ = RoundPageUp(record_len_);
117
Stephen Crane0d671312021-01-13 14:05:41 -0800118 BufferAllocator allocator;
119
120 fd = allocator.Alloc("system", shm_len_);
Tri Vo5b40e892020-11-01 13:01:29 -0800121 if (fd < 0) {
Stephen Crane0d671312021-01-13 14:05:41 -0800122 return ErrnoError() << "failed to create dmabuf of size " << shm_len_
123 << " err code: " << fd;
Tri Vo5b40e892020-11-01 13:01:29 -0800124 }
Stephen Crane0d671312021-01-13 14:05:41 -0800125 unique_fd dma_buf(fd);
Tri Vo5b40e892020-11-01 13:01:29 -0800126
Stephen Crane0d671312021-01-13 14:05:41 -0800127 void* shm = mmap(0, shm_len_, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0);
Tri Vo5b40e892020-11-01 13:01:29 -0800128 if (shm == MAP_FAILED) {
129 return ErrnoError() << "failed to map memfd: ";
130 }
131
132 req.hdr.cmd = COVERAGE_CLIENT_CMD_SHARE_RECORD;
133 req.share_record_args.shm_len = shm_len_;
Stephen Crane0d671312021-01-13 14:05:41 -0800134 ret = Rpc(&req, dma_buf, &resp);
Tri Vo5b40e892020-11-01 13:01:29 -0800135 if (!ret.ok()) {
136 return Error() << "failed to send shared memory: ";
137 }
138
139 shm_ = shm;
140 return {};
141}
142
Stephen Cranee9629302020-11-16 18:00:53 -0800143void CoverageRecord::ResetFullRecord() {
144 auto header_region = GetRegionBounds(COV_START);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900145 if (!header_region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800146 // If the header cannot be parsed, we can't reset the proper region yet.
147 return;
148 }
149
150 for (size_t i = header_region->second; i < shm_len_; i++) {
Tri Vo5b40e892020-11-01 13:01:29 -0800151 *((volatile uint8_t*)shm_ + i) = 0;
152 }
153}
154
Stephen Cranee9629302020-11-16 18:00:53 -0800155void CoverageRecord::ResetCounts() {
156 volatile uint8_t* begin = nullptr;
157 volatile uint8_t* end = nullptr;
158 GetRawCounts(&begin, &end);
159
160 for (volatile uint8_t* x = begin; x < end; x++) {
161 *x = 0;
162 }
163}
164
165void CoverageRecord::ResetPCs() {
166 volatile uintptr_t* begin = nullptr;
167 volatile uintptr_t* end = nullptr;
168 GetRawPCs(&begin, &end);
169
170 for (volatile uintptr_t* x = begin; x < end; x++) {
171 *x = 0;
172 }
173}
174
175Result<std::pair<size_t, size_t>> CoverageRecord::GetRegionBounds(uint32_t region_type) {
176 assert(shm_);
177
178 auto header = (volatile struct coverage_record_header*)shm_;
179
180 if (header->type != COV_START) {
181 return Error() << "Header not yet valid";
182 }
183
184 for (++header; header->type != COV_TOTAL_LENGTH; ++header) {
185 if (header->type == region_type) {
186 // Coverage record must end with a COV_TOTAL_LENGTH header entry, so
187 // it is always safe to read the next entry since we don't iterate
188 // over the COV_TOTAL_LENGTH entry.
189 return {{header->offset, (header + 1)->offset}};
190 }
191 }
192
193 return Error() << "Could not find coverage region type: " << region_type;
194}
195
Tri Vo5b40e892020-11-01 13:01:29 -0800196void CoverageRecord::GetRawData(volatile void** begin, volatile void** end) {
197 assert(shm_);
198
199 *begin = shm_;
200 *end = (uint8_t*)(*begin) + record_len_;
201}
202
Stephen Cranee9629302020-11-16 18:00:53 -0800203void CoverageRecord::GetRawCounts(volatile uint8_t** begin, volatile uint8_t** end) {
204 auto region = GetRegionBounds(COV_8BIT_COUNTERS);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900205 if (!region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800206 *begin = 0;
207 *end = 0;
208 return;
209 }
210
211 assert(region->second <= record_len_);
212
213 *begin = (volatile uint8_t*)shm_ + region->first;
214 *end = (volatile uint8_t*)shm_ + region->second;
215}
216
217void CoverageRecord::GetRawPCs(volatile uintptr_t** begin, volatile uintptr_t** end) {
218 auto region = GetRegionBounds(COV_INSTR_PCS);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900219 if (!region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800220 *begin = 0;
221 *end = 0;
222 return;
223 }
224
225 assert(region->second <= record_len_);
226
227 *begin = (volatile uintptr_t*)((volatile uint8_t*)shm_ + region->first);
228 *end = (volatile uintptr_t*)((volatile uint8_t*)shm_ + region->second);
229}
230
231uint64_t CoverageRecord::TotalEdgeCounts() {
Tri Vo5b40e892020-11-01 13:01:29 -0800232 assert(shm_);
233
234 uint64_t counter = 0;
235
236 volatile uint8_t* begin = NULL;
237 volatile uint8_t* end = NULL;
238
Stephen Cranee9629302020-11-16 18:00:53 -0800239 GetRawCounts(&begin, &end);
Tri Vo5b40e892020-11-01 13:01:29 -0800240
241 for (volatile uint8_t* x = begin; x < end; x++) {
242 counter += *x;
243 }
244
245 return counter;
246}
247
Stephen Cranee9629302020-11-16 18:00:53 -0800248Result<void> CoverageRecord::SaveSancovFile(const std::string& filename) {
249 android::base::unique_fd output_fd(TEMP_FAILURE_RETRY(creat(filename.c_str(), 00644)));
250 if (!output_fd.ok()) {
251 return ErrnoError() << "Could not open sancov file";
252 }
253
254 uint64_t magic;
255 if (sizeof(uintptr_t) == 8) {
256 magic = 0xC0BFFFFFFFFFFF64;
257 } else if (sizeof(uintptr_t) == 4) {
258 magic = 0xC0BFFFFFFFFFFF32;
259 }
260 WriteFully(output_fd, &magic, sizeof(magic));
261
262 volatile uintptr_t* begin = nullptr;
263 volatile uintptr_t* end = nullptr;
264
265 GetRawPCs(&begin, &end);
266
267 for (volatile uintptr_t* pc_ptr = begin; pc_ptr < end; pc_ptr++) {
268 uintptr_t pc = *pc_ptr;
269 if (pc) {
270 WriteFully(output_fd, &pc, sizeof(pc));
271 }
272 }
273
274 return {};
275}
276
Tri Vo5b40e892020-11-01 13:01:29 -0800277} // namespace coverage
278} // namespace trusty
279} // namespace android