blob: 99bcc1dd51850ebf4a7bddd0bdbd241e9dcc2663 [file] [log] [blame]
// Copyright 2021 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 "src/sys/fuzzing/framework/testing/process-proxy.h"
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include "src/sys/fuzzing/framework/target/module.h"
namespace fuzzing {
FakeProcessProxy::FakeProcessProxy(ExecutorPtr executor, ModulePoolPtr pool)
: binding_(this), eventpair_(std::move(executor)), pool_(std::move(pool)) {}
bool FakeProcessProxy::has_module(FakeFrameworkModule* module) const {
auto id = module->id();
auto iter = ids_.find(id[0]);
return iter != ids_.end() && iter->second == id[1];
}
void FakeProcessProxy::Configure(OptionsPtr options) { options_ = std::move(options); }
fidl::InterfaceRequestHandler<Instrumentation> FakeProcessProxy::GetHandler() {
return [this](fidl::InterfaceRequest<Instrumentation> request) {
binding_.Bind(std::move(request));
};
}
void FakeProcessProxy::FakeProcessProxy::Initialize(InstrumentedProcess instrumented,
InitializeCallback callback) {
// The coverage component invokes the callback, but the process waits for the engine's signal.
callback(CopyOptions(*options_));
auto* eventpair = instrumented.mutable_eventpair();
eventpair_.Pair(std::move(*eventpair));
zx_info_handle_basic_t info;
auto status =
instrumented.process().get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
FX_DCHECK(status == ZX_OK) << zx_status_get_string(status);
process_koid_ = info.koid;
status = SignalPeer(kSync);
FX_DCHECK(status == ZX_OK) << zx_status_get_string(status);
}
void FakeProcessProxy::AddLlvmModule(LlvmModule llvm_module, AddLlvmModuleCallback callback) {
// The coverage component invokes the callback, but the process waits for the engine's signal.
callback();
SharedMemory counters;
auto* inline_8bit_counters = llvm_module.mutable_inline_8bit_counters();
auto status = counters.Link(std::move(*inline_8bit_counters));
FX_DCHECK(status == ZX_OK) << zx_status_get_string(status);
auto id = llvm_module.id();
ids_[id[0]] = id[1];
auto* module = pool_->Get(id, counters.size());
module->Add(counters.data(), counters.size());
counters_.push_back(std::move(counters));
status = SignalPeer(kSync);
FX_DCHECK(status == ZX_OK) << zx_status_get_string(status);
}
zx_status_t FakeProcessProxy::SignalPeer(Signal signal) {
auto status = eventpair_.SignalPeer(0, signal);
if (completer_) {
completer_.complete_ok(signal);
}
return status;
}
Promise<> FakeProcessProxy::AwaitReceived(Signal signal) {
return eventpair_.WaitFor(signal)
.and_then([this](const zx_signals_t& observed) {
return AsZxResult(eventpair_.SignalSelf(observed, 0));
})
.or_else([](const zx_status_t& status) { return fpromise::error(); })
.wrap_with(scope_);
}
Promise<> FakeProcessProxy::AwaitSent(Signal signal) {
Bridge<zx_signals_t> bridge;
completer_ = std::move(bridge.completer);
return bridge.consumer.promise_or(fpromise::error())
.and_then([signal](const zx_signals_t& observed) -> Result<> {
if (signal != observed) {
return fpromise::error();
}
return fpromise::ok();
});
}
} // namespace fuzzing