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

Commit 64f76a44 authored by Snehal Koukuntla's avatar Snehal Koukuntla Committed by Automerger Merge Worker
Browse files

Merge changes from topic "coverage-build" into main am: 6ac2c169

parents 76f3af72 6ac2c169
Loading
Loading
Loading
Loading
+36 −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_library {
    name: "libtrusty_line_coverage",
    vendor_available: true,
    srcs: [
        "coverage.cpp",
    ],
    export_include_dirs: [
        "include",
    ],
    shared_libs: [
        "libbase",
        "libext2_uuid",
        "liblog",
        "libdmabufheap",
        "libtrusty",
    ],
}
+191 −0
Original line number Diff line number Diff line
/*
 * 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
+61 −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 <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
+140 −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.
 */

/* 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;
    };
};
+37 −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 <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);
    }
};
Loading