blob: cfb8a2545f68e90ffa42311732cb6afe55aea595 [file] [log] [blame] [edit]
// 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.
#ifndef SRC_LIB_FUZZING_FIDL_COVERAGE_H_
#define SRC_LIB_FUZZING_FIDL_COVERAGE_H_
#include <fuchsia/fuzzer/cpp/fidl.h>
#include <fuchsia/mem/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fit/function.h>
#include <lib/fxl/synchronization/thread_annotations.h>
#include <lib/sync/completion.h>
#include <lib/zx/time.h>
#include <stddef.h>
#include <zircon/types.h>
#include <map>
#include <mutex>
#include <thread>
#include <vector>
#include "shared-memory.h"
#include "traced-instruction.h"
namespace fuzzing {
namespace {
using ::fuchsia::fuzzer::Coverage;
using ::fuchsia::mem::Buffer;
} // namespace
// Forward declaration
class AggregatedCoverage;
// The Coverage service aggregates coverage information from multiple processes and passes it to the
// __sanitizer_cov_* interface. See also |SanitizerCovProxy|, the per-process client of the service.
class CoverageImpl : public Coverage {
public:
explicit CoverageImpl(AggregatedCoverage *aggregate);
virtual ~CoverageImpl();
// FIDL Methods
void AddInline8BitCounters(Buffer ctrs, AddInline8BitCountersCallback callback) override;
void AddPcTable(Buffer pcs, AddPcTableCallback callback) override;
void AddTraces(zx::vmo traces, AddTracesCallback callback) override;
private:
// If |status| indicates an error, asks the AggregatedCoverage to close its binding and returns
// false, otherwise returns true.
bool Check(zx_status_t status);
// Memory from other processes shared with this service.
std::vector<SharedMemory> mapped_;
SharedMemory traces_;
// Interface to the __sanitizer_cov_trace_* calls.
AggregatedCoverage *aggregate_;
};
// The AggregatedCoverage class manages a collection of single-client Coverage connections. It also
// coordinates and provides thread-safety for invoking the __sanitizer_cov_trace_* interface.
class AggregatedCoverage final {
public:
AggregatedCoverage();
~AggregatedCoverage();
fidl::InterfaceRequestHandler<Coverage> GetHandler();
// Signals all connected proxies that the current iteration is complete, i.e. they should ensure
// their coverage data is updated.
zx_status_t CompleteIteration();
// Returns this instance to its original state.
void Reset();
protected:
friend class CoverageImpl;
// Adds a wait item for the shared memory from a call to |Coverage::AddTraces|.
zx_status_t Add(const SharedMemory &traces) FXL_LOCKS_EXCLUDED(lock_);
// Close and removes the binding for an associated coverage instance.
void Close(CoverageImpl *coverage, zx_status_t epitaph);
private:
// Starts processing coverage.
void Start();
// Manage the shared VMOs' signals and process the data from the proxies accordingly.
void ProcessAll();
void ProcessTraces(Instruction *traces, uint64_t distinguisher);
// Stops processing coverage.
void Stop();
// Binding set that owns the Coverage objects.
fidl::BindingSet<Coverage, std::unique_ptr<Coverage>> bindings_;
// Thread used to run |ProcessAll|.
std::thread processor_;
// An array of wait items used to monitor connected Coverage/Proxy pairs.
zx_wait_item_t items_[ZX_WAIT_MANY_MAX_ITEMS];
std::atomic<size_t> num_items_;
// The instruction trace data associated with each wait item. This object MUST keep the two arrays
// in sync.
Instruction *traces_[ZX_WAIT_MANY_MAX_ITEMS];
uint64_t distinguishers_[ZX_WAIT_MANY_MAX_ITEMS];
uint64_t num_distinguishers_;
// The first wait item always corresponds to an event used to control iteration state.
zx::event controller_;
// This lock guards against concurrent calls to |Add|.
std::mutex lock_;
// Synchronization objects used to coordinate iterations.
std::atomic<size_t> pending_;
sync_completion_t sync_;
};
} // namespace fuzzing
#endif // SRC_LIB_FUZZING_FIDL_COVERAGE_H_