blob: 0dd477d5987ba402a35482b03abc64b978197779 [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.
#ifndef SRC_SYS_FUZZING_FRAMEWORK_ENGINE_MODULE_PROXY_H_
#define SRC_SYS_FUZZING_FRAMEWORK_ENGINE_MODULE_PROXY_H_
#include <fuchsia/fuzzer/cpp/fidl.h>
#include <fuchsia/mem/cpp/fidl.h>
#include <stddef.h>
#include <stdint.h>
#include <array>
#include <memory>
#include <mutex>
#include <vector>
#include "src/lib/fxl/macros.h"
#include "src/sys/fuzzing/common/shared-memory.h"
namespace fuzzing {
using Identifier = std::array<uint64_t, 2>;
// This class in the fuzzer engine is analogous to |fuzzing::Module| in an instrumented process.
// This association is one-to-many: The engine collects feedback from multiple processes which may
// possibly even restart. As a result it maintains a single |ModuleProxy| for all instances of a
// particular LLVM module across multiple processes, uniquely identified by the combination of its
// |fuchsia.fuzzer.Identifier| and its number of PCs, e.g. its size.
class ModuleProxy final {
public:
ModuleProxy(Identifier id, size_t size);
~ModuleProxy() = default;
Identifier id() const { return id_; }
size_t size() const { return num_u64s_ * sizeof(uint64_t); }
// De/registers the shared memory as a source of counter values. This object does not take
// ownership of the memory; it must remain valid between calls to |Add| and |Remove|.
void Add(void* counters, size_t counters_len);
void Remove(void* counters);
// Collects counters for linked instances of the associated module, converts them to opaque
// features and returns the number of new features. This method does not record the features, and
// so is useful for evaluating a set of inputs as compared to a base set of features, e.g. from a
// seed corpus. For info on "features", see: http://lcamtuf.coredump.cx/afl/technical_details.txt.
size_t Measure();
// Like |Measure|, but additionally records the new features, making the method useful for
// incrementally growing a corpus.
size_t Accumulate();
// Returns how many PCs have accumulated at least one feature. If |out_num_features| is not null,
// sets it to how many features have been accumulated in total.
size_t GetCoverage(size_t* out_num_features);
// Resets the recorded features.
void Clear();
private:
size_t MeasureImpl(bool accumulate);
const Identifier id_;
const size_t num_u64s_;
std::vector<uint64_t*> counters_;
// TODO(fxbug.dev/84363): Smaller inputs that cover previously observed features are currently
// discarded. To help minimize the corpus, this object could also track the smallest input size
// for each feature, in order to save smaller inputs and prefer them in a subsequent (possibly
// periodic) merge.
std::unique_ptr<uint64_t[]> features_;
std::unique_ptr<uint64_t[]> accumulated_;
FXL_DISALLOW_COPY_ASSIGN_AND_MOVE(ModuleProxy);
};
} // namespace fuzzing
#endif // SRC_SYS_FUZZING_FRAMEWORK_ENGINE_MODULE_PROXY_H_