1919#include < string.h>
2020#include < time.h>
2121
22- #include < algorithm>
2322#include < atomic>
2423#include < cstddef>
2524#include < cstdint>
2625#include < cstdlib>
2726
2827#include " absl/base/const_init.h"
29- #include " absl/base/nullability.h"
30- #include " absl/numeric/bits.h"
3128#include " ./centipede/byte_array_mutator.h"
32- #include " ./centipede/callstack.h"
3329#include " ./centipede/concurrent_bitset.h"
34- #include " ./centipede/concurrent_byteset.h"
3530#include " ./centipede/feature.h"
36- #include " ./centipede/hashed_ring_buffer.h"
3731#include " ./centipede/knobs.h"
38- #include " ./centipede/reverse_pc_table.h"
39- #include " ./centipede/runner_cmp_trace.h"
40- #include " ./centipede/runner_dl_info.h"
41- #include " ./centipede/runner_interface.h"
4232#include " ./centipede/runner_result.h"
43- #include " ./centipede/runner_sancov_object .h"
33+ #include " ./centipede/shared_coverage_state .h"
4434
4535namespace fuzztest ::internal {
4636
@@ -54,79 +44,6 @@ class LockGuard {
5444 pthread_mutex_t &mu_;
5545};
5646
57- // Flags derived from CENTIPEDE_RUNNER_FLAGS.
58- // Flags used in instrumentation callbacks are bit-packed for efficiency.
59- struct RunTimeFlags {
60- uint64_t path_level : 8 ;
61- uint64_t use_pc_features : 1 ;
62- uint64_t use_dataflow_features : 1 ;
63- uint64_t use_cmp_features : 1 ;
64- uint64_t callstack_level : 8 ;
65- uint64_t use_counter_features : 1 ;
66- uint64_t use_auto_dictionary : 1 ;
67- std::atomic<uint64_t > timeout_per_input;
68- uint64_t timeout_per_batch;
69- std::atomic<uint64_t > stack_limit_kb;
70- std::atomic<uint64_t > rss_limit_mb;
71- uint64_t crossover_level;
72- uint64_t skip_seen_features : 1 ;
73- uint64_t ignore_timeout_reports : 1 ;
74- uint64_t max_len;
75- };
76-
77- // One such object is created in runner's TLS.
78- // There is no CTOR, since we don't want to use the brittle and lazy TLS CTORs.
79- // All data members are zero-initialized during thread creation.
80- struct ThreadLocalRunnerState {
81- // Traces the memory comparison of `n` bytes at `s1` and `s2` called at
82- // `caller_pc` with `is_equal` indicating whether the two memory regions have
83- // equal contents. May add cmp features and auto-dictionary entries if
84- // enabled.
85- void TraceMemCmp (uintptr_t caller_pc, const uint8_t *s1, const uint8_t *s2,
86- size_t n, bool is_equal);
87-
88- // Intrusive doubly-linked list of TLS objects.
89- // Guarded by state.tls_list_mu.
90- ThreadLocalRunnerState *next, *prev;
91-
92- // The pthread_create() interceptor calls OnThreadStart() before the thread
93- // callback. The main thread also calls OnThreadStart(). OnThreadStop() will
94- // be called when thread termination is detected internally - see runner.cc.
95- void OnThreadStart ();
96- void OnThreadStop ();
97-
98- // Whether OnThreadStart() is called on this thread. This is used as a proxy
99- // of the readiness of the lower-level runtime.
100- bool started;
101-
102- // Paths are thread-local, so we maintain the current bounded path here.
103- // We allow paths of up to 100, controlled at run-time via the "path_level".
104- static constexpr uint64_t kBoundedPathLength = 100 ;
105- HashedRingBuffer<kBoundedPathLength > path_ring_buffer;
106-
107- // Value of SP in the top call frame of the thread, computed in OnThreadStart.
108- uintptr_t top_frame_sp;
109- // The lower bound of the stack region of this thread. 0 means unknown.
110- uintptr_t stack_region_low;
111- // Lowest observed value of SP.
112- uintptr_t lowest_sp;
113-
114- // The (imprecise) call stack is updated by the PC callback.
115- CallStack<> call_stack;
116-
117- // Cmp traces capture the arguments of CMP instructions, memcmp, etc.
118- // We have dedicated traces for 2-, 4-, and 8-byte comparison, and
119- // a catch-all `cmp_traceN` trace for memcmp, etc.
120- CmpTrace<2 , 64 > cmp_trace2;
121- CmpTrace<4 , 64 > cmp_trace4;
122- CmpTrace<8 , 64 > cmp_trace8;
123- CmpTrace<0 , 64 > cmp_traceN;
124-
125- // Set this to true if the thread needs to be ignored in ForEachTLS.
126- // It should be always false if the state is in the global detached_tls_list.
127- bool ignore;
128- };
129-
13047// One global object of this type is created by the runner at start up.
13148// All data members will be initialized to zero, unless they have initializers.
13249// Accesses to the subobjects should be fast, so we are trying to avoid
@@ -144,79 +61,6 @@ struct GlobalRunnerState {
14461 GlobalRunnerState ();
14562 ~GlobalRunnerState ();
14663
147- // Runner reads flags from CentipedeGetRunnerFlags(). We don't use flags
148- // passed via argv so that argv flags can be passed directly to
149- // LLVMFuzzerInitialize, w/o filtering. The flags are separated with
150- // ':' on both sides, i.e. like this: ":flag1:flag2:flag3=value3".
151- // We do it this way to make the flag parsing code extremely simple. The
152- // interface is private between Centipede and the runner and may change.
153- //
154- // Note that this field reflects the initial runner flags. But some
155- // flags can change later (if wrapped with std::atomic).
156- const char *centipede_runner_flags = CentipedeGetRunnerFlags();
157- const char *arg1 = GetStringFlag(" :arg1=" );
158- const char *arg2 = GetStringFlag(" :arg2=" );
159- const char *arg3 = GetStringFlag(" :arg3=" );
160- // The path to a file where the runner may write the description of failure.
161- const char *failure_description_path =
162- GetStringFlag (" :failure_description_path=" );
163-
164- // Flags.
165- RunTimeFlags run_time_flags = {
166- /* path_level=*/ std::min (ThreadLocalRunnerState::kBoundedPathLength ,
167- HasIntFlag (" :path_level=" , 0 )),
168- /* use_pc_features=*/ HasFlag (" :use_pc_features:" ),
169- /* use_dataflow_features=*/ HasFlag (" :use_dataflow_features:" ),
170- /* use_cmp_features=*/ HasFlag (" :use_cmp_features:" ),
171- /* callstack_level=*/ HasIntFlag (" :callstack_level=" , 0 ),
172- /* use_counter_features=*/ HasFlag (" :use_counter_features:" ),
173- /* use_auto_dictionary=*/ HasFlag (" :use_auto_dictionary:" ),
174- /* timeout_per_input=*/ HasIntFlag (" :timeout_per_input=" , 0 ),
175- /* timeout_per_batch=*/ HasIntFlag (" :timeout_per_batch=" , 0 ),
176- /* stack_limit_kb=*/ HasIntFlag (" :stack_limit_kb=" , 0 ),
177- /* rss_limit_mb=*/ HasIntFlag (" :rss_limit_mb=" , 0 ),
178- /* crossover_level=*/ HasIntFlag (" :crossover_level=" , 50 ),
179- /* skip_seen_features=*/ HasFlag (" :skip_seen_features:" ),
180- /* ignore_timeout_reports=*/ HasFlag (" :ignore_timeout_reports:" ),
181- /* max_len=*/ HasIntFlag (" :max_len=" , 4000 ),
182- };
183-
184- // Returns true iff `flag` is present.
185- // Typical usage: pass ":some_flag:", i.e. the flag name surrounded with ':'.
186- // TODO(ussuri): Refactor `char *` into a `string_view`.
187- bool HasFlag (const char *absl_nonnull flag) const {
188- if (!centipede_runner_flags) return false ;
189- return strstr (centipede_runner_flags, flag) != nullptr ;
190- }
191-
192- // If a flag=value pair is present, returns value,
193- // otherwise returns `default_value`.
194- // Typical usage: pass ":some_flag=".
195- // TODO(ussuri): Refactor `char *` into a `string_view`.
196- uint64_t HasIntFlag (const char *absl_nonnull flag,
197- uint64_t default_value) const {
198- if (!centipede_runner_flags) return default_value;
199- const char *beg = strstr (centipede_runner_flags, flag);
200- if (!beg) return default_value;
201- return atoll (beg + strlen (flag)); // NOLINT: can't use strto64, etc.
202- }
203-
204- // If a :flag=value: pair is present returns value, otherwise returns nullptr.
205- // The result is obtained by calling strndup, so make sure to save
206- // it in `this` to avoid a leak.
207- // Typical usage: pass ":some_flag=".
208- // TODO(ussuri): Refactor `char *` into a `string_view`.
209- const char *absl_nullable GetStringFlag (const char *absl_nonnull flag) const {
210- if (!centipede_runner_flags) return nullptr ;
211- // Extract "value" from ":flag=value:" inside centipede_runner_flags.
212- const char *beg = strstr (centipede_runner_flags, flag);
213- if (!beg) return nullptr ;
214- const char *value_beg = beg + strlen (flag);
215- const char *end = strstr (value_beg, " :" );
216- if (!end) return nullptr ;
217- return strndup (value_beg, end - value_beg);
218- }
219-
22064 pthread_mutex_t execution_result_override_mu = PTHREAD_MUTEX_INITIALIZER;
22165 // If not nullptr, it points to a batch result with either zero or one
22266 // execution. When an execution result present, it will be passed as the
@@ -247,52 +91,11 @@ struct GlobalRunnerState {
24791 // Reclaims all TLSs in detached_tls_list and cleans up the list.
24892 void CleanUpDetachedTls ();
24993
250- // Computed by DlInfo().
251- // Usually, the main object is the executable binary containing main()
252- // and most of the executable code (we assume that the target is
253- // built in mostly-static mode, i.e. -dynamic_mode=off).
254- // When the `dl_path_suffix` runner flag is provided, the main_object refers
255- // to the dynamic library (DSO) pointed to by this flag.
256- //
257- // Note: this runner currently does not support more than one instrumented
258- // DSO in the process, i.e. you either instrument the main binary, or one DSO.
259- // Supporting more than one DSO will require major changes,
260- // major added complexity, and potentially cause slowdown.
261- // There is currently no motivation for such a change.
262- DlInfo main_object;
263-
264- // State for SanitizerCoverage.
265- // See https://clang.llvm.org/docs/SanitizerCoverage.html.
266- SanCovObjectArray sancov_objects;
267- // An arbitrarily large size.
268- static constexpr size_t kDataFlowFeatureSetSize = 1 << 18 ;
269- ConcurrentBitSet<kDataFlowFeatureSetSize > data_flow_feature_set{
270- absl::kConstInit };
271-
27294 // Tracing CMP instructions, capture events from these domains:
27395 // kCMPEq, kCMPModDiff, kCMPHamming, kCMPModDiffLog, kCMPMsbEq.
27496 // See https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow.
275- // An arbitrarily large size.
276- static constexpr size_t kCmpFeatureSetSize = 1 << 18 ;
27797 // TODO(kcc): remove cmp_feature_set.
27898 ConcurrentBitSet<kCmpFeatureSetSize > cmp_feature_set{absl::kConstInit };
279- ConcurrentBitSet<kCmpFeatureSetSize > cmp_eq_set{absl::kConstInit };
280- ConcurrentBitSet<kCmpFeatureSetSize > cmp_moddiff_set{absl::kConstInit };
281- ConcurrentBitSet<kCmpFeatureSetSize > cmp_hamming_set{absl::kConstInit };
282- ConcurrentBitSet<kCmpFeatureSetSize > cmp_difflog_set{absl::kConstInit };
283-
284- // We think that call stack produces rich signal, so we give a few bits to it.
285- static constexpr size_t kCallStackFeatureSetSize = 1 << 24 ;
286- ConcurrentBitSet<kCallStackFeatureSetSize > callstack_set{absl::kConstInit };
287-
288- // kMaxNumPcs is the maximum number of instrumented PCs in the binary.
289- // We can be generous here since the unused memory will not cost anything.
290- // `pc_counter_set` is a static byte set supporting up to kMaxNumPcs PCs.
291- static constexpr size_t kMaxNumPcs = 1 << 28 ;
292- TwoLayerConcurrentByteSet<kMaxNumPcs > pc_counter_set{absl::kConstInit };
293- // This is the actual number of PCs, aligned up to
294- // pc_counter_set::kSizeMultiple, computed at startup.
295- size_t actual_pc_counter_set_size_aligned;
29699
297100 // Initialized in CTOR from the __centipede_extra_features section.
298101 feature_t *user_defined_begin;
@@ -313,19 +116,9 @@ struct GlobalRunnerState {
313116 // * Use call stacks instead of paths (via unwinding or other
314117 // instrumentation).
315118
316- // An arbitrarily large size.
317- static constexpr size_t kPathBitSetSize = 1 << 25 ;
318- // Observed paths. The total number of observed paths for --path_level=N
319- // can be up to NumPCs**N.
320- // So, we make the bitset very large, but it may still saturate.
321- ConcurrentBitSet<kPathBitSetSize > path_feature_set{absl::kConstInit };
322-
323119 // Execution stats for the currently executed input.
324120 ExecutionResult::Stats stats;
325121
326- // Used by trace_pc instrumentation. Populated if `pcs_file_path` flag is set.
327- ReversePCTable reverse_pc_table;
328-
329122 // CentipedeRunnerMain() sets this to true.
330123 bool centipede_runner_main_executed = false ;
331124
@@ -346,20 +139,9 @@ struct GlobalRunnerState {
346139
347140 // The Watchdog thread sets this to true.
348141 std::atomic<bool > watchdog_thread_started;
349-
350- // An arbitrarily large size.
351- static const size_t kMaxFeatures = 1 << 20 ;
352- // FeatureArray used to accumulate features from all sources.
353- FeatureArray<kMaxFeatures > g_features;
354-
355- // Features that were seen before.
356- static constexpr size_t kSeenFeatureSetSize =
357- absl::bit_ceil (feature_domains::kLastDomain .end());
358- ConcurrentBitSet<kSeenFeatureSetSize > seen_features{absl::kConstInit };
359142};
360143
361144extern GlobalRunnerState state;
362- extern __thread ThreadLocalRunnerState tls;
363145
364146// Check for stack limit for the stack pointer `sp` in the current thread.
365147void CheckStackLimit (uintptr_t sp);
0 commit comments