Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 806e70bb authored by Snehal's avatar Snehal Committed by Snehal Koukuntla
Browse files

Add Coverage controller

Bug: 289523068

Change-Id: I5b36c274acc7da4e2d6b9cf91409a7b1af5f0d34
parent ed34b6e2
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
// 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",
    ],
}
+164 −0
Original line number Diff line number Diff line
/*
 * 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
+64 −0
Original line number Diff line number Diff line
/*
 * 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