Add Coverage controller

Bug: 289523068

Change-Id: I5b36c274acc7da4e2d6b9cf91409a7b1af5f0d34
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