blob: bb7ab992a0a2215d838f61e6949ee4f6229c23ee [file] [log] [blame]
// Copyright 2022 The Centipede Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_CENTIPEDE_ENVIRONMENT_H_
#define THIRD_PARTY_CENTIPEDE_ENVIRONMENT_H_
#include <cstddef>
#include <string>
#include <vector>
#include "absl/time/time.h"
#include "./centipede/knobs.h"
namespace centipede {
// Fuzzing environment that is initialized at startup and doesn't change.
// Data fields are copied from the FLAGS defined in centipede_interface.cc,
// or derived from them. See FLAGS descriptions for comments.
// Users or tests can override any of the non-const fields after the object
// is constructed, but before it is passed to CentipedeMain.
struct Environment {
// Life cycle ----------------------------------------------------------------
explicit Environment(const std::vector<std::string>& argv = {});
Environment(int argc, char **argv)
: Environment(std::vector<std::string>{argv, argv + argc}) {}
// Copy-constructible only (due to const members).
Environment(const Environment&) = default;
Environment& operator=(const Environment&) = delete;
Environment(Environment&&) noexcept = delete;
Environment& operator=(Environment&&) noexcept = delete;
// Data ----------------------------------------------------------------------
// Global params. Set in CTOR from the flags in environment.cc ---------------
std::string binary;
std::string coverage_binary;
std::string clang_coverage_binary;
std::vector<std::string> extra_binaries;
std::string workdir;
std::string merge_from;
size_t num_runs;
size_t total_shards;
size_t my_shard_index;
size_t num_threads;
size_t max_len;
size_t batch_size;
size_t mutate_batch_size;
bool use_legacy_default_mutator;
size_t load_other_shard_frequency;
bool serialize_shard_loads;
size_t seed;
size_t prune_frequency;
size_t address_space_limit_mb;
size_t rss_limit_mb;
size_t timeout_per_input;
size_t timeout_per_batch;
absl::Time stop_at;
bool fork_server;
bool full_sync;
bool use_corpus_weights;
bool use_coverage_frontier;
size_t max_corpus_size;
size_t crossover_level;
bool use_pc_features;
size_t path_level;
bool use_cmp_features;
size_t callstack_level;
bool use_auto_dictionary;
bool use_dataflow_features;
bool use_counter_features;
bool use_pcpair_features;
size_t feature_frequency_threshold;
bool require_pc_table;
int telemetry_frequency;
bool print_runner_log;
bool distill;
size_t distill_shards;
size_t log_features_shards;
std::string knobs_file;
std::string save_corpus_to_local_dir;
std::string export_corpus_from_local_dir;
std::vector<std::string> corpus_dir;
std::string symbolizer_path;
std::string objdump_path;
std::string runner_dl_path_suffix;
std::string input_filter;
std::vector<std::string> dictionary;
std::string function_filter;
std::string for_each_blob;
std::string experiment;
bool analyze;
bool exit_on_crash;
size_t max_num_crash_reports;
std::string minimize_crash_file_path;
size_t shmem_size_mb;
bool use_posix_shmem = false;
bool dry_run = false;
// Command line-related fields -----------------------------------------------
std::string exec_name; // copied from argv[0]
std::vector<std::string> args; // copied from argv[1:].
// The command to execute the binary (may contain arguments).
const std::string cmd;
const std::string binary_name; // Name of `coverage_binary`, w/o directories.
const std::string binary_hash; // Hash of the `coverage_binary` file.
bool has_input_wildcards = false; // Set to true iff `binary` contains "@@".
// Experiment-related settings -----------------------------------------------
std::string experiment_name; // Set by `UpdateForExperiment`.
std::string experiment_flags; // Set by `UpdateForExperiment`.
// Other ---------------------------------------------------------------------
Knobs knobs; // Read from a file by `ReadKnobsFileIfSpecified`, see knobs.h.
// Defines internal logging level. Set to zero to reduce logging in tests.
// TODO(ussuri): Retire in favor of VLOGs?
size_t log_level = 1;
// Path to a file with PCs. This file is created and the field is set in
// `CentipedeMain()` once per process if trace_pc instrumentation is detected.
std::string pcs_file_path;
// APIs ----------------------------------------------------------------------
// Paths to various input and output files and directories -------------------
// Returns the path to the coverage dir.
std::string MakeCoverageDirPath() const;
// Returns the path to the crash reproducer dir.
std::string MakeCrashReproducerDirPath() const;
// Returns the path for a corpus file by its shard_index.
std::string MakeCorpusPath(size_t shard_index) const;
// Returns the path for a features file by its shard_index.
std::string MakeFeaturesPath(size_t shard_index) const;
// Returns the path to the coverage profile for this shard.
std::string MakeSourceBasedCoverageRawProfilePath() const;
// Returns the path to the indexed code coverage file.
std::string MakeSourceBasedCoverageIndexedProfilePath() const;
// Returns the path for the distilled corpus file for my_shard_index.
std::string MakeDistilledPath() const;
// Returns the path for the coverage report file for my_shard_index.
// Non-default `annotation` becomes a part of the returned filename.
// `annotation` must not start with a '.'.
std::string MakeCoverageReportPath(std::string_view annotation = "") const;
// Returns the path for the corpus stats report file for my_shard_index.
// Non-default `annotation` becomes a part of the returned filename.
// `annotation` must not start with a '.'.
std::string MakeCorpusStatsPath(std::string_view annotation = "") const;
// Returns the path for the fuzzing progress stats report file for
// `my_shard_index`.
// Non-default `annotation` becomes a part of the returned filename.
// `annotation` must not start with a '.'.
std::string MakeFuzzingStatsPath(std::string_view annotation = "") const;
// Returns the path to the source-based coverage report directory.
std::string MakeSourceBasedCoverageReportPath(
std::string_view annotation = "") const;
// Returns the path for the performance report file for my_shard_index.
// Non-default `annotation` becomes a part of the returned filename.
// `annotation` must not start with a '.'.
std::string MakeRUsageReportPath(std::string_view annotation = "") const;
// Returns all shards' raw profile paths by scanning the coverage directory.
std::vector<std::string> EnumerateRawCoverageProfiles() const;
// Should certain actions be performed ---------------------------------------
// Returns true if we want to distill the corpus in this shard before fuzzing.
bool DistillingInThisShard() const { return my_shard_index < distill_shards; }
// Returns true if we want to log features as symbols in this shard.
bool LogFeaturesInThisShard() const {
return my_shard_index < log_features_shards;
}
// Returns true if we want to generate the corpus telemetry files (coverage
// report, corpus stats, etc.) in this shard.
bool DumpCorpusTelemetryInThisShard() const;
// Returns true if we want to generate the resource usage report in this
// shard. See the related RUsageTelemetryScope().
bool DumpRUsageTelemetryInThisShard() const;
// Returns true if we want to generate the telemetry files (coverage report,
// the corpus stats, etc.) after processing `batch_index`-th batch.
bool DumpTelemetryForThisBatch(size_t batch_index) const;
// Experiment-related functions ----------------------------------------------
// Updates `this` according to the `--experiment` flag.
// The `--experiment` flag, if not empty, has this form:
// foo=1,2,3:bar=10,20
// where foo and bar are some of the flag names supported for experimentation,
// see `SetFlag()`.
// `--experiment` defines the flag values to be set differently in different
// shards. E.g. in this case,
// shard 0 will have {foo=1,bar=10},
// shard 1 will have {foo=1,bar=20},
// ...
// shard 3 will have {foo=2,bar=10},
// ...
// shard 5 will have {foo=2,bar=30},
// and so on.
//
// CHECK-fails if the `--experiment` flag is not well-formed,
// or if num_threads is not a multiple of the number of flag combinations
// (which is 6 in this example).
//
// Sets load_other_shard_frequency=0 (experiments should be independent).
//
// Sets this->experiment_name to a string like "E01",
// which means "value #0 is used for foo and value #1 is used for bar".
void UpdateForExperiment();
// Sets flag 'name' to `value` for an experiment. CHECK-fails on
// invalid name/value combination. Used in `UpdateForExperiment()`.
void SetFlagForExperiment(std::string_view name, std::string_view value);
// Other ---------------------------------------------------------------------
// Reads `knobs` from `knobs_file`. Does nothing if the `knobs_file` is empty.
void ReadKnobsFileIfSpecified();
};
} // namespace centipede
#endif // THIRD_PARTY_CENTIPEDE_ENVIRONMENT_H_