Merge changes from topic "coverage-build" into main
* changes:
Add Coverage controller
Coverage library on the NS side for the coverage controller
diff --git a/trusty/line-coverage/Android.bp b/trusty/line-coverage/Android.bp
new file mode 100644
index 0000000..36a73aa
--- /dev/null
+++ b/trusty/line-coverage/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2023 The Android Open-Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+ name: "libtrusty_line_coverage",
+ vendor_available: true,
+ srcs: [
+ "coverage.cpp",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ shared_libs: [
+ "libbase",
+ "libext2_uuid",
+ "liblog",
+ "libdmabufheap",
+ "libtrusty",
+ ],
+}
+
diff --git a/trusty/line-coverage/coverage.cpp b/trusty/line-coverage/coverage.cpp
new file mode 100644
index 0000000..57b7025
--- /dev/null
+++ b/trusty/line-coverage/coverage.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2023 The Android Open Sourete Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "line-coverage"
+
+#include <BufferAllocator/BufferAllocator.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <assert.h>
+#include <log/log.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+#include <trusty/line-coverage/coverage.h>
+#include <trusty/line-coverage/tipc.h>
+#include <trusty/tipc.h>
+#include <iostream>
+
+#define LINE_COVERAGE_CLIENT_PORT "com.android.trusty.linecoverage.client"
+
+struct control {
+ /* Written by controller, read by instrumented TA */
+ uint64_t cntrl_flags;
+
+ /* Written by instrumented TA, read by controller */
+ uint64_t oper_flags;
+ uint64_t write_buffer_start_count;
+ uint64_t write_buffer_complete_count;
+};
+
+namespace android {
+namespace trusty {
+namespace line_coverage {
+
+using ::android::base::ErrnoError;
+using ::android::base::Error;
+using ::std::string;
+
+static inline uintptr_t RoundPageUp(uintptr_t val) {
+ return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+}
+
+CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid)
+ : tipc_dev_(std::move(tipc_dev)),
+ coverage_srv_fd_(-1),
+ uuid_(*uuid),
+ record_len_(0),
+ shm_(NULL),
+ shm_len_(0) {}
+
+CoverageRecord::~CoverageRecord() {
+ if (shm_) {
+ munmap((void*)shm_, shm_len_);
+ }
+}
+
+volatile void *CoverageRecord::getShm() {
+ if(!IsOpen()) {
+ fprintf(stderr, "Warning! SHM is NULL!\n");
+ }
+ return shm_;
+}
+
+Result<void> CoverageRecord::Rpc(struct line_coverage_client_req* req, \
+ int req_fd, \
+ struct line_coverage_client_resp* resp) {
+ int rc;
+
+ if (req_fd < 0) {
+ rc = write(coverage_srv_fd_, req, sizeof(*req));
+ } else {
+ iovec iov = {
+ .iov_base = req,
+ .iov_len = sizeof(*req),
+ };
+
+ trusty_shm shm = {
+ .fd = req_fd,
+ .transfer = TRUSTY_SHARE,
+ };
+
+ rc = tipc_send(coverage_srv_fd_, &iov, 1, &shm, 1);
+ }
+
+ if (rc != (int)sizeof(*req)) {
+ return ErrnoError() << "failed to send request to coverage server: ";
+ }
+
+ rc = read(coverage_srv_fd_, resp, sizeof(*resp));
+ if (rc != (int)sizeof(*resp)) {
+ return ErrnoError() << "failed to read reply from coverage server: ";
+ }
+
+ if (resp->hdr.cmd != (req->hdr.cmd | LINE_COVERAGE_CLIENT_CMD_RESP_BIT)) {
+ return ErrnoError() << "unknown response cmd: " << resp->hdr.cmd;
+ }
+
+ return {};
+}
+
+Result<void> CoverageRecord::Open(int fd) {
+ struct line_coverage_client_req req;
+ struct line_coverage_client_resp resp;
+
+ if (shm_) {
+ return {}; /* already initialized */
+ }
+
+ coverage_srv_fd_= fd;
+
+ req.hdr.cmd = LINE_COVERAGE_CLIENT_CMD_OPEN;
+ req.open_args.uuid = uuid_;
+ auto ret = Rpc(&req, -1, &resp);
+ if (!ret.ok()) {
+ return Error() << "failed to open coverage client: " << ret.error();
+ }
+ record_len_ = resp.open_args.record_len;
+ shm_len_ = RoundPageUp(record_len_);
+
+ BufferAllocator allocator;
+
+ fd = allocator.Alloc("system", shm_len_);
+ if (fd < 0) {
+ return ErrnoError() << "failed to create dmabuf of size " << shm_len_
+ << " err code: " << fd;
+ }
+ unique_fd dma_buf(fd);
+
+ void* shm = mmap(0, shm_len_, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0);
+ if (shm == MAP_FAILED) {
+ return ErrnoError() << "failed to map memfd: ";
+ }
+
+ req.hdr.cmd = LINE_COVERAGE_CLIENT_CMD_SHARE_RECORD;
+ req.share_record_args.shm_len = shm_len_;
+ ret = Rpc(&req, dma_buf, &resp);
+ if (!ret.ok()) {
+ return Error() << "failed to send shared memory: " << ret.error();
+ }
+
+ shm_ = shm;
+
+ req.hdr.cmd = LINE_COVERAGE_CLIENT_CMD_OPEN;
+ req.open_args.uuid = uuid_;
+ ret = Rpc(&req, -1, &resp);
+ if (!ret.ok()) {
+ return Error() << "failed to open coverage client: " << ret.error();
+ }
+
+ return {};
+}
+
+bool CoverageRecord::IsOpen() {
+ return shm_;
+}
+
+Result<void> CoverageRecord::SaveFile(const std::string& filename) {
+ if(!IsOpen()) {
+ return ErrnoError() << "Warning! SHM is NULL!";
+ }
+ android::base::unique_fd output_fd(TEMP_FAILURE_RETRY(creat(filename.c_str(), 00644)));
+ if (!output_fd.ok()) {
+ return ErrnoError() << "Could not open output file";
+ }
+
+ uintptr_t* begin = (uintptr_t*)((char *)shm_ + sizeof(struct control));
+ bool ret = WriteFully(output_fd, begin, record_len_);
+ if(!ret) {
+ fprintf(stderr, "Coverage write to file failed\n");
+ }
+
+ return {};
+}
+
+} // namespace line_coverage
+} // namespace trusty
+} // namespace android
diff --git a/trusty/line-coverage/include/trusty/line-coverage/coverage.h b/trusty/line-coverage/include/trusty/line-coverage/coverage.h
new file mode 100644
index 0000000..53901be
--- /dev/null
+++ b/trusty/line-coverage/include/trusty/line-coverage/coverage.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <optional>
+#include <string>
+
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+#include <stdint.h>
+#include <trusty/line-coverage/tipc.h>
+
+namespace android {
+namespace trusty {
+namespace line_coverage {
+
+using android::base::Result;
+using android::base::unique_fd;
+
+class CoverageRecord {
+ public:
+ CoverageRecord(std::string tipc_dev, struct uuid* uuid);
+
+ ~CoverageRecord();
+ Result<void> Open(int fd);
+ bool IsOpen();
+ Result<void> SaveFile(const std::string& filename);
+ volatile void* getShm();
+
+ private:
+ Result<void> Rpc(struct line_coverage_client_req* req, \
+ int req_fd, \
+ struct line_coverage_client_resp* resp);
+
+ Result<std::pair<size_t, size_t>> GetRegionBounds(uint32_t region_type);
+
+ std::string tipc_dev_;
+ int coverage_srv_fd_;
+ struct uuid uuid_;
+ size_t record_len_;
+ volatile void* shm_;
+ size_t shm_len_;
+};
+
+} // namespace line_coverage
+} // namespace trusty
+} // namespace android
diff --git a/trusty/line-coverage/include/trusty/line-coverage/tipc.h b/trusty/line-coverage/include/trusty/line-coverage/tipc.h
new file mode 100644
index 0000000..20e855c
--- /dev/null
+++ b/trusty/line-coverage/include/trusty/line-coverage/tipc.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This file needs to be kept in-sync with its counterpart on Trusty side */
+
+#pragma once
+
+#include <stdint.h>
+#include <trusty/line-coverage/uuid.h>
+
+
+#define LINE_COVERAGE_CLIENT_PORT "com.android.trusty.linecoverage.client"
+
+/**
+ * enum line_coverage_client_cmd - command identifiers for coverage client interface
+ * @LINE_COVERAGE_CLIENT_CMD_RESP_BIT: response bit set as part of response
+ * @LINE_COVERAGE_CLIENT_CMD_SHIFT: number of bits used by response bit
+ * @LINE_COVERAGE_CLIENT_CMD_OPEN: command to open coverage record
+ * @LINE_COVERAGE_CLIENT_CMD_SHARE_RECORD: command to register a shared memory region
+ * where coverage record will be written to
+ */
+enum line_coverage_client_cmd {
+ LINE_COVERAGE_CLIENT_CMD_RESP_BIT = 1U,
+ LINE_COVERAGE_CLIENT_CMD_SHIFT = 1U,
+ LINE_COVERAGE_CLIENT_CMD_OPEN = (1U << LINE_COVERAGE_CLIENT_CMD_SHIFT),
+ LINE_COVERAGE_CLIENT_CMD_SHARE_RECORD = (2U << LINE_COVERAGE_CLIENT_CMD_SHIFT),
+ LINE_COVERAGE_CLIENT_CMD_SEND_LIST = (3U << LINE_COVERAGE_CLIENT_CMD_SHIFT),
+};
+
+/**
+ * struct line_coverage_client_hdr - header for coverage client messages
+ * @cmd: command identifier
+ *
+ * Note that no messages return a status code. Any error on the server side
+ * results in the connection being closed. So, operations can be assumed to be
+ * successful if they return a response.
+ */
+struct line_coverage_client_hdr {
+ uint32_t cmd;
+};
+
+/**
+ * struct line_coverage_client_open_req - arguments for request to open coverage
+ * record
+ * @uuid: UUID of target TA
+ *
+ * There is one coverage record per TA. @uuid is used to identify both the TA
+ * and corresponding coverage record.
+ */
+struct line_coverage_client_open_req {
+ struct uuid uuid;
+};
+
+/**
+ * struct line_coverage_client_open_resp - arguments for response to open coverage
+ * record
+ * @record_len: length of coverage record that will be emitted by target TA
+ *
+ * Shared memory allocated for this coverage record must larger than
+ * @record_len.
+ */
+struct line_coverage_client_open_resp {
+ uint32_t record_len;
+};
+
+/**
+ * struct line_coverage_client_send_list_resp - arguments for response to send list
+ * record
+ * @uuid: UUID of TA that connected to aggregator
+ */
+struct line_coverage_client_send_list_resp {
+ struct uuid uuid;
+};
+
+/**
+ * struct line_coverage_client_send_list_resp - arguments for response to send list
+ * record
+ * @index: index of the list being requested
+ */
+struct line_coverage_client_send_list_req {
+ uint32_t index;
+};
+
+/**
+ * struct line_coverage_client_share_record_req - arguments for request to share
+ * memory for coverage record
+ * @shm_len: length of memory region being shared
+ *
+ * A handle to a memory region must be sent along with this message. This memory
+ * is used to store coverage record.
+ *
+ * Upon success, this memory region can be assumed to be shared between the
+ * client and target TA.
+ */
+struct line_coverage_client_share_record_req {
+ uint32_t shm_len;
+};
+
+/**
+ * struct line_coverage_client_req - structure for a coverage client request
+ * @hdr: message header
+ * @open_args: arguments for %COVERAGE_CLIENT_CMD_OPEN request
+ * @share_record_args: arguments for %COVERAGE_CLIENT_CMD_SHARE_RECORD request
+ * @index: arguments for %COVERAGE_CLIENT_CMD_SHARE_RECORD request
+ */
+struct line_coverage_client_req {
+ struct line_coverage_client_hdr hdr;
+ union {
+ struct line_coverage_client_open_req open_args;
+ struct line_coverage_client_share_record_req share_record_args;
+ struct line_coverage_client_send_list_req send_list_args;
+ };
+};
+
+/**
+ * struct line_coverage_client_resp - structure for a coverage client response
+ * @hdr: message header
+ * @open_args: arguments for %COVERAGE_CLIENT_CMD_OPEN response
+ * @send_list_args: arguments for %COVERAGE_CLIENT_CMD_SHARE_RECORD response
+ */
+struct line_coverage_client_resp {
+ struct line_coverage_client_hdr hdr;
+ union {
+ struct line_coverage_client_open_resp open_args;
+ struct line_coverage_client_send_list_resp send_list_args;
+ };
+};
diff --git a/trusty/line-coverage/include/trusty/line-coverage/uuid.h b/trusty/line-coverage/include/trusty/line-coverage/uuid.h
new file mode 100644
index 0000000..1873980
--- /dev/null
+++ b/trusty/line-coverage/include/trusty/line-coverage/uuid.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string.h>
+
+#define UUCMP(u1, u2) if (u1 != u2) return u1 < u2
+
+struct uuid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_and_node[8];
+
+ bool operator<(const struct uuid& rhs) const
+ {
+ UUCMP(time_low, rhs.time_low);
+ UUCMP(time_mid, rhs.time_mid);
+ UUCMP(time_hi_and_version, rhs.time_hi_and_version);
+ return memcmp(clock_seq_and_node, rhs.clock_seq_and_node, 8);
+ }
+};
diff --git a/trusty/utils/coverage-controller/Android.bp b/trusty/utils/coverage-controller/Android.bp
new file mode 100644
index 0000000..1aa88cc
--- /dev/null
+++ b/trusty/utils/coverage-controller/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+ name: "coverage-controller",
+ vendor: true,
+
+ srcs: ["controller.cpp"],
+ shared_libs: [
+ "libc",
+ "liblog",
+ "libbase",
+ "libdmabufheap",
+ ],
+ static_libs: [
+ "libtrusty",
+ "libtrusty_line_coverage",
+ ],
+}
diff --git a/trusty/utils/coverage-controller/controller.cpp b/trusty/utils/coverage-controller/controller.cpp
new file mode 100644
index 0000000..730c010
--- /dev/null
+++ b/trusty/utils/coverage-controller/controller.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <getopt.h>
+#include <trusty/line-coverage/coverage.h>
+#include <trusty/tipc.h>
+#include <array>
+#include <memory>
+#include <vector>
+
+#include "controller.h"
+
+#define READ_ONCE(x) (*((volatile __typeof__(x) *) &(x)))
+#define WRITE_ONCE(x, val) (*((volatile __typeof__(val) *) &(x)) = (val))
+
+namespace android {
+namespace trusty {
+namespace controller {
+
+using ::android::trusty::line_coverage::CoverageRecord;
+
+void Controller::run(std::string output_dir) {
+ connectCoverageServer();
+ struct control *control;
+ uint64_t complete_cnt = 0, start_cnt = 0, flags;
+
+ while(1) {
+ setUpShm();
+
+ for (int index = 0; index < record_list_.size(); index++) {
+ control = (struct control *)record_list_[index]->getShm();
+ start_cnt = READ_ONCE((control->write_buffer_start_count));
+ complete_cnt = READ_ONCE(control->write_buffer_complete_count);
+ flags = READ_ONCE(control->cntrl_flags);
+
+ if (complete_cnt != counters[index] && start_cnt == complete_cnt) {
+ WRITE_ONCE(control->cntrl_flags, FLAG_NONE);
+ std::string fmt = "/%d.%lu.profraw";
+ int sz = std::snprintf(nullptr, 0, fmt.c_str(), index, counters[index]);
+ std::string filename(sz+1, '.');
+ std::sprintf(filename.data(), fmt.c_str(), index, counters[index]);
+ filename.insert(0, output_dir);
+ android::base::Result<void> res = record_list_[index]->SaveFile(filename);
+ counters[index]++;
+ }
+ if(complete_cnt == counters[index] &&
+ !(flags & FLAG_RUN)) {
+ flags |= FLAG_RUN;
+ WRITE_ONCE(control->cntrl_flags, flags);
+ }
+ }
+ }
+}
+
+void Controller::connectCoverageServer() {
+ coverage_srv_fd = tipc_connect(TIPC_DEV, LINE_COVERAGE_CLIENT_PORT);
+ if (coverage_srv_fd < 0) {
+ fprintf(stderr, \
+ "Error: Failed to connect to Trusty coverage server: %d\n", coverage_srv_fd);
+ return;
+ }
+}
+
+void Controller::setUpShm() {
+ struct line_coverage_client_req req;
+ struct line_coverage_client_resp resp;
+ uint32_t cur_index = record_list_.size();
+ struct uuid zero_uuid = {0, 0, 0, { 0 }};
+ req.hdr.cmd = LINE_COVERAGE_CLIENT_CMD_SEND_LIST;
+ int rc = write(coverage_srv_fd, &req, sizeof(req));
+ if (rc != (int)sizeof(req)) {
+ fprintf(stderr, "failed to send request to coverage server: %d\n", rc);
+ return;
+ }
+
+ while(1) {
+ rc = read(coverage_srv_fd, &resp, sizeof(resp));
+ if (rc != (int)sizeof(resp)) {
+ fprintf(stderr, "failed to read reply from coverage server:: %d\n", rc);
+ }
+
+ if (resp.hdr.cmd == (req.hdr.cmd | LINE_COVERAGE_CLIENT_CMD_RESP_BIT)) {
+ if (!memcmp(&resp.send_list_args.uuid, &zero_uuid, sizeof(struct uuid))) {
+ break;
+ }
+ if(uuid_set_.find(resp.send_list_args.uuid) == uuid_set_.end()) {
+ uuid_set_.insert(resp.send_list_args.uuid);
+ record_list_.push_back(std::make_unique<CoverageRecord>(TIPC_DEV,
+ &resp.send_list_args.uuid));
+ counters.push_back(0);
+ }
+ }
+ else {
+ fprintf(stderr, "Unknown response header\n");
+ }
+ cur_index++;
+ req.hdr.cmd = LINE_COVERAGE_CLIENT_CMD_SEND_LIST;
+ req.send_list_args.index = cur_index;
+ int rc = write(coverage_srv_fd, &req, sizeof(req));
+ if (rc != (int)sizeof(req)) {
+ fprintf(stderr, "failed to send request to coverage server: %d\n", rc);
+ }
+ }
+
+ for(int ind = 0 ; ind < record_list_.size() ; ind++) {
+ record_list_[ind]->Open(coverage_srv_fd);
+ }
+}
+
+
+} // namespace controller
+} // namespace trusty
+} // namespace android
+
+int main(int argc, char* argv[]) {
+
+ std::string optarg = "";
+ do {
+ int c;
+ c = getopt(argc, argv, "o");
+
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'o':
+ break;
+ default:
+ fprintf(stderr, "usage: %s -o [output_directory]\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ } while (1);
+
+ if (argc > optind + 1) {
+ fprintf(stderr, "%s: too many arguments\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (argc > optind) {
+ optarg = argv[optind];
+ }
+ if (optarg.size()==0) {
+ optarg = "data/local/tmp";
+ }
+
+ android::trusty::controller::Controller cur;
+ cur.run(optarg);
+
+ return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/trusty/utils/coverage-controller/controller.h b/trusty/utils/coverage-controller/controller.h
new file mode 100644
index 0000000..b771c16
--- /dev/null
+++ b/trusty/utils/coverage-controller/controller.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <trusty/line-coverage/coverage.h>
+#include <array>
+#include <memory>
+#include <vector>
+#include <set>
+
+#define TIPC_DEV "/dev/trusty-ipc-dev0"
+#define TEST_SRV_PORT "com.android.trusty.sancov.test.srv"
+#define TEST_SRV_MODULE "srv.syms.elf"
+
+#define FLAG_NONE 0x0
+#define FLAG_RUN 0x1
+#define FLAG_TOGGLE_CLEAR 0x2
+
+struct control {
+ /* Written by controller, read by instrumented TA */
+ uint64_t cntrl_flags;
+
+ /* Written by instrumented TA, read by controller */
+ uint64_t oper_flags;
+ uint64_t write_buffer_start_count;
+ uint64_t write_buffer_complete_count;
+};
+
+namespace android {
+namespace trusty {
+namespace controller {
+
+class Controller {
+ public:
+ public:
+ void run(std::string output_dir);
+
+ private:
+ std::vector<std::unique_ptr<line_coverage::CoverageRecord>>record_list_;
+ std::set<struct uuid>uuid_set_;
+ std::vector<uint64_t> counters;
+ int coverage_srv_fd;
+
+ void connectCoverageServer();
+ void setUpShm();
+};
+
+} // namespace controller
+} // namespace trusty
+} // namespace android