blob: 187d382edab5fe99ed016cc9078145cea26a387f [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fake-coverage.h"
#include <string.h>
#include <zircon/errors.h>
#include "sanitizer-cov-proxy.h"
namespace fuzzing {
FakeCoverage::FakeCoverage() : binding_(this), vmo_(nullptr), traces_(nullptr) {
memset(counts_, 0, sizeof(counts_));
}
FakeCoverage::~FakeCoverage() {}
fidl::InterfaceRequestHandler<Coverage> FakeCoverage::GetHandler() {
return [this](fidl::InterfaceRequest<Coverage> request) {
if (binding_.is_bound()) {
binding_.Unbind();
}
binding_.Bind(std::move(request));
};
}
void FakeCoverage::Configure() {
auto proxy = SanitizerCovProxy::GetInstance();
traces_ = proxy->traces();
memset(traces_, 0, kMaxInstructions * sizeof(Instruction));
vmo_ = proxy->vmo();
vmo_->signal(kBetweenIterations | kReadableSignalA | kReadableSignalB,
kInIteration | kWritableSignalA | kWritableSignalB);
}
void FakeCoverage::AddInline8BitCounters(Buffer inline_8bit_counters,
AddInline8BitCountersCallback callback) {
pending_.push_back(std::move(inline_8bit_counters));
callback();
}
void FakeCoverage::AddPcTable(Buffer pcs, AddPcTableCallback callback) {
pending_.push_back(std::move(pcs));
callback();
}
void FakeCoverage::AddTraces(zx::vmo traces, AddTracesCallback callback) {}
bool FakeCoverage::MapPending(SharedMemory *out) {
if (pending_.empty()) {
return false;
}
Buffer buffer = std::move(pending_.front());
pending_.pop_front();
return out->Link(buffer.vmo, buffer.size) == ZX_OK;
}
void FakeCoverage::SendIterationComplete() {
vmo_->signal(kInIteration, kBetweenIterations);
vmo_->wait_one(kReadableSignalA | kReadableSignalB, zx::time::infinite(), nullptr);
Resolve();
}
void FakeCoverage::Resolve() {
if (vmo_->wait_one(kReadableSignalA, zx::deadline_after(zx::nsec(0)), nullptr) == ZX_OK) {
for (size_t i = 0; i < kInstructionBufferLen; ++i) {
counts_[traces_[i].type] += 1;
}
vmo_->signal(kReadableSignalA, kWritableSignalA);
}
if (vmo_->wait_one(kReadableSignalB, zx::deadline_after(zx::nsec(0)), nullptr) == ZX_OK) {
for (size_t i = kInstructionBufferLen; i < kMaxInstructions; ++i) {
counts_[traces_[i].type] += 1;
}
vmo_->signal(kReadableSignalB, kWritableSignalB);
}
}
size_t FakeCoverage::Count(Instruction::Type type) {
if (type > Instruction::kMaxValue) {
return 0;
}
return counts_[type];
}
bool FakeCoverage::HasCompleted() { return counts_[Instruction::kSentinel] != 0; }
} // namespace fuzzing