blob: 185abe5497f0a827b8cb2351bc8f2b290c6ed225 [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>
32
33#define COVERAGE_CLIENT_PORT "com.android.trusty.coverage.client"
34
35namespace android {
36namespace trusty {
37namespace coverage {
38
39using android::base::ErrnoError;
40using android::base::Error;
41using std::string;
Stephen Crane6bd77df2021-01-13 14:05:41 -080042using std::unique_ptr;
Tri Vo5b40e892020-11-01 13:01:29 -080043
44static inline uintptr_t RoundPageUp(uintptr_t val) {
45 return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
46}
47
48CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid)
49 : tipc_dev_(std::move(tipc_dev)),
50 coverage_srv_fd_(-1),
51 uuid_(*uuid),
Stephen Crane6bd77df2021-01-13 14:05:41 -080052 sancov_filename_(),
53 record_len_(0),
54 shm_(NULL),
55 shm_len_(0) {}
56
57CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid, string sancov_filename)
58 : tipc_dev_(std::move(tipc_dev)),
59 coverage_srv_fd_(-1),
60 uuid_(*uuid),
61 sancov_filename_(sancov_filename),
Tri Vo5b40e892020-11-01 13:01:29 -080062 record_len_(0),
63 shm_(NULL),
64 shm_len_(0) {}
65
66CoverageRecord::~CoverageRecord() {
67 if (shm_) {
Stephen Crane6bd77df2021-01-13 14:05:41 -080068 if (sancov_filename_) {
69 auto res = SaveSancovFile(*sancov_filename_);
70 if (!res.ok()) {
71 ALOGE("Could not write sancov file for module: %s\n", sancov_filename_->c_str());
72 }
73 }
74
Tri Vo5b40e892020-11-01 13:01:29 -080075 munmap((void*)shm_, shm_len_);
76 }
77}
78
79Result<void> CoverageRecord::Rpc(coverage_client_req* req, int req_fd, coverage_client_resp* resp) {
80 int rc;
81
82 if (req_fd < 0) {
83 rc = write(coverage_srv_fd_, req, sizeof(*req));
84 } else {
85 iovec iov = {
86 .iov_base = req,
87 .iov_len = sizeof(*req),
88 };
89
90 trusty_shm shm = {
91 .fd = req_fd,
92 .transfer = TRUSTY_SHARE,
93 };
94
95 rc = tipc_send(coverage_srv_fd_, &iov, 1, &shm, 1);
96 }
97
98 if (rc != (int)sizeof(*req)) {
99 return ErrnoError() << "failed to send request to coverage server: ";
100 }
101
102 rc = read(coverage_srv_fd_, resp, sizeof(*resp));
103 if (rc != (int)sizeof(*resp)) {
104 return ErrnoError() << "failed to read reply from coverage server: ";
105 }
106
107 if (resp->hdr.cmd != (req->hdr.cmd | COVERAGE_CLIENT_CMD_RESP_BIT)) {
108 return ErrnoError() << "unknown response cmd: " << resp->hdr.cmd;
109 }
110
111 return {};
112}
113
114Result<void> CoverageRecord::Open() {
115 coverage_client_req req;
116 coverage_client_resp resp;
117
118 if (shm_) {
119 return {}; /* already initialized */
120 }
121
122 int fd = tipc_connect(tipc_dev_.c_str(), COVERAGE_CLIENT_PORT);
123 if (fd < 0) {
124 return ErrnoError() << "failed to connect to Trusty coverarge server: ";
125 }
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()) {
132 return Error() << "failed to open coverage client: ";
133 }
134 record_len_ = resp.open_args.record_len;
135 shm_len_ = RoundPageUp(record_len_);
136
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()) {
155 return Error() << "failed to send shared memory: ";
156 }
157
158 shm_ = shm;
159 return {};
160}
161
Stephen Cranee9629302020-11-16 18:00:53 -0800162void CoverageRecord::ResetFullRecord() {
163 auto header_region = GetRegionBounds(COV_START);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900164 if (!header_region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800165 // If the header cannot be parsed, we can't reset the proper region yet.
166 return;
167 }
168
169 for (size_t i = header_region->second; i < shm_len_; i++) {
Tri Vo5b40e892020-11-01 13:01:29 -0800170 *((volatile uint8_t*)shm_ + i) = 0;
171 }
172}
173
Stephen Cranee9629302020-11-16 18:00:53 -0800174void CoverageRecord::ResetCounts() {
175 volatile uint8_t* begin = nullptr;
176 volatile uint8_t* end = nullptr;
177 GetRawCounts(&begin, &end);
178
179 for (volatile uint8_t* x = begin; x < end; x++) {
180 *x = 0;
181 }
182}
183
184void CoverageRecord::ResetPCs() {
185 volatile uintptr_t* begin = nullptr;
186 volatile uintptr_t* end = nullptr;
187 GetRawPCs(&begin, &end);
188
189 for (volatile uintptr_t* x = begin; x < end; x++) {
190 *x = 0;
191 }
192}
193
194Result<std::pair<size_t, size_t>> CoverageRecord::GetRegionBounds(uint32_t region_type) {
195 assert(shm_);
196
197 auto header = (volatile struct coverage_record_header*)shm_;
198
199 if (header->type != COV_START) {
200 return Error() << "Header not yet valid";
201 }
202
203 for (++header; header->type != COV_TOTAL_LENGTH; ++header) {
204 if (header->type == region_type) {
205 // Coverage record must end with a COV_TOTAL_LENGTH header entry, so
206 // it is always safe to read the next entry since we don't iterate
207 // over the COV_TOTAL_LENGTH entry.
208 return {{header->offset, (header + 1)->offset}};
209 }
210 }
211
212 return Error() << "Could not find coverage region type: " << region_type;
213}
214
Tri Vo5b40e892020-11-01 13:01:29 -0800215void CoverageRecord::GetRawData(volatile void** begin, volatile void** end) {
216 assert(shm_);
217
218 *begin = shm_;
219 *end = (uint8_t*)(*begin) + record_len_;
220}
221
Stephen Cranee9629302020-11-16 18:00:53 -0800222void CoverageRecord::GetRawCounts(volatile uint8_t** begin, volatile uint8_t** end) {
223 auto region = GetRegionBounds(COV_8BIT_COUNTERS);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900224 if (!region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800225 *begin = 0;
226 *end = 0;
227 return;
228 }
229
230 assert(region->second <= record_len_);
231
232 *begin = (volatile uint8_t*)shm_ + region->first;
233 *end = (volatile uint8_t*)shm_ + region->second;
234}
235
236void CoverageRecord::GetRawPCs(volatile uintptr_t** begin, volatile uintptr_t** end) {
237 auto region = GetRegionBounds(COV_INSTR_PCS);
Bernie Innocenti62ba2b12020-12-19 21:17:16 +0900238 if (!region.ok()) {
Stephen Cranee9629302020-11-16 18:00:53 -0800239 *begin = 0;
240 *end = 0;
241 return;
242 }
243
244 assert(region->second <= record_len_);
245
246 *begin = (volatile uintptr_t*)((volatile uint8_t*)shm_ + region->first);
247 *end = (volatile uintptr_t*)((volatile uint8_t*)shm_ + region->second);
248}
249
250uint64_t CoverageRecord::TotalEdgeCounts() {
Tri Vo5b40e892020-11-01 13:01:29 -0800251 assert(shm_);
252
253 uint64_t counter = 0;
254
255 volatile uint8_t* begin = NULL;
256 volatile uint8_t* end = NULL;
257
Stephen Cranee9629302020-11-16 18:00:53 -0800258 GetRawCounts(&begin, &end);
Tri Vo5b40e892020-11-01 13:01:29 -0800259
260 for (volatile uint8_t* x = begin; x < end; x++) {
261 counter += *x;
262 }
263
264 return counter;
265}
266
Stephen Cranee9629302020-11-16 18:00:53 -0800267Result<void> CoverageRecord::SaveSancovFile(const std::string& filename) {
268 android::base::unique_fd output_fd(TEMP_FAILURE_RETRY(creat(filename.c_str(), 00644)));
269 if (!output_fd.ok()) {
270 return ErrnoError() << "Could not open sancov file";
271 }
272
273 uint64_t magic;
274 if (sizeof(uintptr_t) == 8) {
275 magic = 0xC0BFFFFFFFFFFF64;
276 } else if (sizeof(uintptr_t) == 4) {
277 magic = 0xC0BFFFFFFFFFFF32;
278 }
279 WriteFully(output_fd, &magic, sizeof(magic));
280
281 volatile uintptr_t* begin = nullptr;
282 volatile uintptr_t* end = nullptr;
283
284 GetRawPCs(&begin, &end);
285
286 for (volatile uintptr_t* pc_ptr = begin; pc_ptr < end; pc_ptr++) {
287 uintptr_t pc = *pc_ptr;
288 if (pc) {
289 WriteFully(output_fd, &pc, sizeof(pc));
290 }
291 }
292
293 return {};
294}
295
Tri Vo5b40e892020-11-01 13:01:29 -0800296} // namespace coverage
297} // namespace trusty
298} // namespace android