• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source 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 TLOG_TAG "cov-shm"
18 
19 #include <lib/coverage/common/cov_shm.h>
20 #include <interface/line-coverage/aggregator.h>
21 #include <interface/line-coverage/client.h>
22 #include <lib/coverage/common/ipc.h>
23 #include <lib/line-coverage/shm.h>
24 #include <lib/tipc/tipc.h>
25 #include <lk/macros.h>
26 #include <lk/compiler.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/auxv.h>
31 #include <sys/mman.h>
32 #include <trusty/memref.h>
33 #include <trusty_log.h>
34 #include <uapi/err.h>
35 
36 #ifdef UNITTEST_COVERAGE
37 #define PAGE_SIZE getauxval(AT_PAGESZ)
38 static struct cov_ctx ctx;
39 /*
40 This symbol is exported to each instrumented shared library and
41 exectuable to instruct the linker to skip loading the object which
42 contains the profiling runtime's static initialiser
43 */
44 
45 int __llvm_profile_runtime;
46 
47 /*
48 These functions have to be forward declared and then called
49 when we want profiling runtime without static initialisers
50 */
51 uint64_t __llvm_profile_get_size_for_buffer(void);
52 int __llvm_profile_write_buffer(char *Buffer);
53 void __llvm_profile_reset_counters(void);
54 
dump_shm(void)55 void dump_shm(void) {
56     if (!cov_shm_is_mapped(&ctx.data)) {
57         return;
58     }
59     struct control *control = (struct control *)ctx.data.base;
60     uint64_t flags = READ_ONCE(control->cntrl_flags);
61     uint64_t read_cnt = READ_ONCE(control->read_buffer_cnt);
62     if ( ((flags & FLAG_RUN) != 0) && (read_cnt == control->write_buffer_start_count) ) {
63         uint64_t count =  control->write_buffer_start_count + 1;
64         WRITE_ONCE(control->write_buffer_start_count, count);
65         __llvm_profile_write_buffer((char *)control + sizeof(struct control));
66         __llvm_profile_reset_counters();
67         WRITE_ONCE(control->write_buffer_complete_count, count);
68     }
69 }
70 
setup_shm(void)71 int setup_shm(void) {
72     int rc;
73     handle_t memref;
74     struct coverage_aggregator_req cov_req;
75     struct coverage_aggregator_resp cov_resp;
76     size_t shm_len;
77 
78     if(ctx.mailbox.base == NULL) {
79         // For aggregator and client, mailbox is expected to be NULL
80         // Skip print for such cases
81         if(!ctx.skip_mailbox) {
82             TLOGE("Mailbox not setup\n");
83         }
84         return -1;
85     }
86 
87     int* app_mailbox = (int*)(ctx.mailbox.base) + ctx.idx;
88     int event = READ_ONCE(*app_mailbox);
89 
90     if (event != COVERAGE_MAILBOX_RECORD_READY) {
91         TLOGE("NS memory not shared yet\n");
92         return -1;
93     }
94     if (cov_shm_is_mapped(&ctx.data)) {
95         TLOGD("SHM already setup\n");
96         return NO_ERROR;
97     }
98 
99     memset(&cov_req, 0, sizeof(struct coverage_aggregator_req));
100     cov_req.hdr.cmd = COVERAGE_AGGREGATOR_CMD_GET_RECORD;
101 
102     rc = coverage_aggregator_rpc(ctx.coverage_srv, &cov_req, NULL, &cov_resp, &memref);
103     if (rc != NO_ERROR) {
104         TLOGE("failed (%d) coverage aggregator RPC\n", rc);
105         return rc;
106     }
107     shm_len = cov_resp.get_record_args.shm_len;
108 
109     if (shm_len < ctx.record_len) {
110         TLOGE("not enough shared memory, received: %zu, need at least: %zu\n",
111             shm_len, ctx.record_len);
112         rc = ERR_BAD_LEN;
113         return rc;
114     }
115 
116     rc = cov_shm_mmap(&ctx.data, memref, cov_resp.get_record_args.shm_len);
117     if (rc != NO_ERROR) {
118         TLOGE("failed to mmap() coverage record shared memory\n");
119         return rc;
120     }
121     return NO_ERROR;
122 }
123 
setup_mailbox(const struct tipc_port * ports,uint32_t num_ports)124 int setup_mailbox(const struct tipc_port* ports, uint32_t num_ports) {
125     uint64_t buf_len = __llvm_profile_get_size_for_buffer();
126     int rc;
127     uint32_t i;
128     handle_t chan;
129     handle_t memref;
130     struct coverage_aggregator_req req;
131     struct coverage_aggregator_resp resp;
132 
133     ctx.skip_mailbox = false;
134 
135     for (i = 0; i < num_ports; i++) {
136         // Skip for coverage aggregator and client
137         if (strcmp(ports[i].name, LINE_COVERAGE_AGGREGATOR_PORT) == 0 ||
138                 strcmp(ports[i].name, LINE_COVERAGE_CLIENT_PORT) == 0) {
139             ctx.skip_mailbox = true;
140             ctx.coverage_srv = INVALID_IPC_HANDLE;
141             ctx.mailbox.base = NULL;
142             return -1;
143         }
144     }
145 
146     rc = tipc_connect(&chan, LINE_COVERAGE_AGGREGATOR_PORT);
147     if (rc != NO_ERROR) {
148         TLOGE("failed (%d) to connect to coverage aggregator service\n", rc);
149         return rc;
150     }
151 
152     memset(&req, 0, sizeof(struct coverage_aggregator_req));
153     req.hdr.cmd = COVERAGE_AGGREGATOR_CMD_REGISTER;
154     req.register_args.record_len = round_up(buf_len + sizeof(struct control), PAGE_SIZE);
155 
156     rc = coverage_aggregator_rpc(chan, &req, NULL, &resp, &memref);
157     if (rc != NO_ERROR) {
158         TLOGE("sys_state: failed (%d) coverage aggregator RPC\n", rc);
159         close(chan);
160         return rc;
161     }
162 
163     rc = cov_shm_mmap(&(ctx.mailbox), memref, resp.register_args.mailbox_len);
164     if (rc != NO_ERROR) {
165         TLOGE("failed to mmap() mailbox shared memory\n");
166         close(memref);
167         close(chan);
168         return rc;
169     }
170 
171     ctx.record_len = buf_len + sizeof(struct control);
172     ctx.coverage_srv = chan;
173     ctx.idx = resp.register_args.idx;
174 
175     close(memref);
176     return NO_ERROR;
177 }
178 
179 #else
dump_shm(void)180 void dump_shm(void) {
181     return;
182 }
183 
setup_shm(void)184 int setup_shm(void) {
185     return NO_ERROR;
186 }
187 
setup_mailbox(const struct tipc_port * ports,uint32_t num_ports)188 int setup_mailbox(const struct tipc_port* ports, uint32_t num_ports) {
189     return NO_ERROR;
190 }
191 #endif
192