Process the execution metadata when finalizing coverage.
This avoids noise (from the framework integration) between finalizing coverage and sending it out.
PiperOrigin-RevId: 791691734
diff --git a/centipede/runner.cc b/centipede/runner.cc
index ff98a27..2e73d85 100644
--- a/centipede/runner.cc
+++ b/centipede/runner.cc
@@ -454,9 +454,10 @@
return false;
}
- ExecutionMetadata metadata;
- if (!CopyCmpTracesToMetadata(&metadata)) return false;
- if (!BatchResult::WriteMetadata(metadata, outputs_blobseq)) return false;
+ if (!BatchResult::WriteMetadata(SanCovRuntimeGetExecutionMetadata(),
+ outputs_blobseq)) {
+ return false;
+ }
// Write the stats.
if (!BatchResult::WriteStats(state->stats, outputs_blobseq)) return false;
diff --git a/centipede/sancov_state.cc b/centipede/sancov_state.cc
index 5360ba8..25bcd73 100644
--- a/centipede/sancov_state.cc
+++ b/centipede/sancov_state.cc
@@ -356,8 +356,31 @@
}
}
+// Calls ExecutionMetadata::AppendCmpEntry for every CMP arg pair
+// found in `cmp_trace`.
+// Returns true if all appending succeeded.
+// "noinline" so that we see it in a profile, if it becomes hot.
+template <typename CmpTrace>
+__attribute__((noinline)) void AppendCmpEntries(CmpTrace& cmp_trace,
+ ExecutionMetadata& metadata) {
+ cmp_trace.ForEachNonZero(
+ [&](uint8_t size, const uint8_t* v0, const uint8_t* v1) {
+ (void)metadata.AppendCmpEntry({v0, size}, {v1, size});
+ });
+}
+
void PostProcessSancov(bool reject_input) {
sancov_state->g_features.clear();
+ sancov_state->metadata.cmp_data.clear();
+
+ if (sancov_state->flags.use_auto_dictionary && !reject_input) {
+ sancov_state->ForEachTls([](ThreadLocalSancovState& tls) {
+ AppendCmpEntries(tls.cmp_trace2, sancov_state->metadata);
+ AppendCmpEntries(tls.cmp_trace4, sancov_state->metadata);
+ AppendCmpEntries(tls.cmp_trace8, sancov_state->metadata);
+ AppendCmpEntries(tls.cmp_traceN, sancov_state->metadata);
+ });
+ }
std::function<void(feature_t)> feature_handler = MaybeAddFeature;
if (reject_input) {
@@ -461,46 +484,15 @@
}
}
-// Calls ExecutionMetadata::AppendCmpEntry for every CMP arg pair
-// found in `cmp_trace`.
-// Returns true if all appending succeeded.
-// "noinline" so that we see it in a profile, if it becomes hot.
-template <typename CmpTrace>
-__attribute__((noinline)) bool AppendCmpEntries(CmpTrace &cmp_trace,
- ExecutionMetadata &metadata) {
- bool append_failed = false;
- cmp_trace.ForEachNonZero(
- [&](uint8_t size, const uint8_t *v0, const uint8_t *v1) {
- if (!metadata.AppendCmpEntry({v0, size}, {v1, size}))
- append_failed = true;
- });
- return !append_failed;
-}
-
-bool CopyCmpTracesToMetadata(ExecutionMetadata *metadata) {
- if (sancov_state->flags.use_auto_dictionary) {
- bool append_failed = false;
- sancov_state->ForEachTls(
- [&metadata, &append_failed](ThreadLocalSancovState& tls) {
- if (!AppendCmpEntries(tls.cmp_trace2, *metadata))
- append_failed = true;
- if (!AppendCmpEntries(tls.cmp_trace4, *metadata))
- append_failed = true;
- if (!AppendCmpEntries(tls.cmp_trace8, *metadata))
- append_failed = true;
- if (!AppendCmpEntries(tls.cmp_traceN, *metadata))
- append_failed = true;
- });
- if (append_failed) return false;
- }
- return true;
-}
-
SanCovRuntimeRawFeatureParts SanCovRuntimeGetFeatures() {
return {fuzztest::internal::sancov_state->g_features.data(),
fuzztest::internal::sancov_state->g_features.size()};
}
+const ExecutionMetadata& SanCovRuntimeGetExecutionMetadata() {
+ return fuzztest::internal::sancov_state->metadata;
+}
+
} // namespace fuzztest::internal
// Can be overridden to not depend explicitly on CENTIPEDE_RUNNER_FLAGS.
diff --git a/centipede/sancov_state.h b/centipede/sancov_state.h
index 8df1c1d..3afb6c4 100644
--- a/centipede/sancov_state.h
+++ b/centipede/sancov_state.h
@@ -251,6 +251,10 @@
static const size_t kMaxFeatures = 1 << 20;
// FeatureArray used to accumulate features from all sources.
FeatureArray<kMaxFeatures> g_features;
+ // Execution metadata gathered by `PostProcessSancov`.
+ //
+ // TODO: b/443264359 - export it in the runtime interface.
+ ExecutionMetadata metadata;
// Features that were seen before.
static constexpr size_t kSeenFeatureSetSize =
@@ -262,8 +266,6 @@
feature_t *user_defined_end;
};
-bool CopyCmpTracesToMetadata(ExecutionMetadata *metadata);
-
// Clears all the thread-local data updated during execution.
__attribute__((noinline)) // so that we see it in profile.
void CleanUpSancovTls();
@@ -291,6 +293,9 @@
// Returns a pointer to `g_features` and its length.
SanCovRuntimeRawFeatureParts SanCovRuntimeGetFeatures();
+// Gets the execution metadata gathered in `PostProcessSancov`.
+const ExecutionMetadata& SanCovRuntimeGetExecutionMetadata();
+
// Check for stack limit for the stack pointer `sp` in the current thread.
__attribute__((weak)) void CheckStackLimit(uintptr_t sp);