diff options
Diffstat (limited to 'trusty/coverage/coverage.cpp')
-rw-r--r-- | trusty/coverage/coverage.cpp | 152 |
1 files changed, 139 insertions, 13 deletions
diff --git a/trusty/coverage/coverage.cpp b/trusty/coverage/coverage.cpp index 1162f42aa..185abe549 100644 --- a/trusty/coverage/coverage.cpp +++ b/trusty/coverage/coverage.cpp @@ -16,12 +16,17 @@ #define LOG_TAG "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/coverage/coverage.h> +#include <trusty/coverage/record.h> #include <trusty/coverage/tipc.h> #include <trusty/tipc.h> @@ -34,6 +39,7 @@ namespace coverage { using android::base::ErrnoError; using android::base::Error; using std::string; +using std::unique_ptr; static inline uintptr_t RoundPageUp(uintptr_t val) { return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); @@ -43,12 +49,29 @@ CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid) : tipc_dev_(std::move(tipc_dev)), coverage_srv_fd_(-1), uuid_(*uuid), + sancov_filename_(), + record_len_(0), + shm_(NULL), + shm_len_(0) {} + +CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid, string sancov_filename) + : tipc_dev_(std::move(tipc_dev)), + coverage_srv_fd_(-1), + uuid_(*uuid), + sancov_filename_(sancov_filename), record_len_(0), shm_(NULL), shm_len_(0) {} CoverageRecord::~CoverageRecord() { if (shm_) { + if (sancov_filename_) { + auto res = SaveSancovFile(*sancov_filename_); + if (!res.ok()) { + ALOGE("Could not write sancov file for module: %s\n", sancov_filename_->c_str()); + } + } + munmap((void*)shm_, shm_len_); } } @@ -111,24 +134,23 @@ Result<void> CoverageRecord::Open() { record_len_ = resp.open_args.record_len; shm_len_ = RoundPageUp(record_len_); - fd = memfd_create("trusty-coverage", 0); - if (fd < 0) { - return ErrnoError() << "failed to create memfd: "; - } - unique_fd memfd(fd); + BufferAllocator allocator; - if (ftruncate(memfd, shm_len_) < 0) { - return ErrnoError() << "failed to resize memfd: "; + 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, memfd, 0); + 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 = COVERAGE_CLIENT_CMD_SHARE_RECORD; req.share_record_args.shm_len = shm_len_; - ret = Rpc(&req, memfd, &resp); + ret = Rpc(&req, dma_buf, &resp); if (!ret.ok()) { return Error() << "failed to send shared memory: "; } @@ -137,12 +159,59 @@ Result<void> CoverageRecord::Open() { return {}; } -void CoverageRecord::Reset() { - for (size_t i = 0; i < shm_len_; i++) { +void CoverageRecord::ResetFullRecord() { + auto header_region = GetRegionBounds(COV_START); + if (!header_region.ok()) { + // If the header cannot be parsed, we can't reset the proper region yet. + return; + } + + for (size_t i = header_region->second; i < shm_len_; i++) { *((volatile uint8_t*)shm_ + i) = 0; } } +void CoverageRecord::ResetCounts() { + volatile uint8_t* begin = nullptr; + volatile uint8_t* end = nullptr; + GetRawCounts(&begin, &end); + + for (volatile uint8_t* x = begin; x < end; x++) { + *x = 0; + } +} + +void CoverageRecord::ResetPCs() { + volatile uintptr_t* begin = nullptr; + volatile uintptr_t* end = nullptr; + GetRawPCs(&begin, &end); + + for (volatile uintptr_t* x = begin; x < end; x++) { + *x = 0; + } +} + +Result<std::pair<size_t, size_t>> CoverageRecord::GetRegionBounds(uint32_t region_type) { + assert(shm_); + + auto header = (volatile struct coverage_record_header*)shm_; + + if (header->type != COV_START) { + return Error() << "Header not yet valid"; + } + + for (++header; header->type != COV_TOTAL_LENGTH; ++header) { + if (header->type == region_type) { + // Coverage record must end with a COV_TOTAL_LENGTH header entry, so + // it is always safe to read the next entry since we don't iterate + // over the COV_TOTAL_LENGTH entry. + return {{header->offset, (header + 1)->offset}}; + } + } + + return Error() << "Could not find coverage region type: " << region_type; +} + void CoverageRecord::GetRawData(volatile void** begin, volatile void** end) { assert(shm_); @@ -150,7 +219,35 @@ void CoverageRecord::GetRawData(volatile void** begin, volatile void** end) { *end = (uint8_t*)(*begin) + record_len_; } -uint64_t CoverageRecord::CountEdges() { +void CoverageRecord::GetRawCounts(volatile uint8_t** begin, volatile uint8_t** end) { + auto region = GetRegionBounds(COV_8BIT_COUNTERS); + if (!region.ok()) { + *begin = 0; + *end = 0; + return; + } + + assert(region->second <= record_len_); + + *begin = (volatile uint8_t*)shm_ + region->first; + *end = (volatile uint8_t*)shm_ + region->second; +} + +void CoverageRecord::GetRawPCs(volatile uintptr_t** begin, volatile uintptr_t** end) { + auto region = GetRegionBounds(COV_INSTR_PCS); + if (!region.ok()) { + *begin = 0; + *end = 0; + return; + } + + assert(region->second <= record_len_); + + *begin = (volatile uintptr_t*)((volatile uint8_t*)shm_ + region->first); + *end = (volatile uintptr_t*)((volatile uint8_t*)shm_ + region->second); +} + +uint64_t CoverageRecord::TotalEdgeCounts() { assert(shm_); uint64_t counter = 0; @@ -158,7 +255,7 @@ uint64_t CoverageRecord::CountEdges() { volatile uint8_t* begin = NULL; volatile uint8_t* end = NULL; - GetRawData((volatile void**)&begin, (volatile void**)&end); + GetRawCounts(&begin, &end); for (volatile uint8_t* x = begin; x < end; x++) { counter += *x; @@ -167,6 +264,35 @@ uint64_t CoverageRecord::CountEdges() { return counter; } +Result<void> CoverageRecord::SaveSancovFile(const std::string& filename) { + android::base::unique_fd output_fd(TEMP_FAILURE_RETRY(creat(filename.c_str(), 00644))); + if (!output_fd.ok()) { + return ErrnoError() << "Could not open sancov file"; + } + + uint64_t magic; + if (sizeof(uintptr_t) == 8) { + magic = 0xC0BFFFFFFFFFFF64; + } else if (sizeof(uintptr_t) == 4) { + magic = 0xC0BFFFFFFFFFFF32; + } + WriteFully(output_fd, &magic, sizeof(magic)); + + volatile uintptr_t* begin = nullptr; + volatile uintptr_t* end = nullptr; + + GetRawPCs(&begin, &end); + + for (volatile uintptr_t* pc_ptr = begin; pc_ptr < end; pc_ptr++) { + uintptr_t pc = *pc_ptr; + if (pc) { + WriteFully(output_fd, &pc, sizeof(pc)); + } + } + + return {}; +} + } // namespace coverage } // namespace trusty } // namespace android |