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"
3430#include " ./centipede/concurrent_byteset.h"
3531#include " ./centipede/feature.h"
36- #include " ./centipede/hashed_ring_buffer.h"
3732#include " ./centipede/knobs.h"
3833#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"
4234#include " ./centipede/runner_result.h"
4335#include " ./centipede/runner_sancov_object.h"
36+ #include " ./centipede/shared_coverage_state.h"
4437
4538namespace fuzztest ::internal {
4639
@@ -54,79 +47,6 @@ class LockGuard {
5447 pthread_mutex_t &mu_;
5548};
5649
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-
13050// One global object of this type is created by the runner at start up.
13151// All data members will be initialized to zero, unless they have initializers.
13252// Accesses to the subobjects should be fast, so we are trying to avoid
@@ -144,79 +64,6 @@ struct GlobalRunnerState {
14464 GlobalRunnerState ();
14565 ~GlobalRunnerState ();
14666
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-
22067 pthread_mutex_t execution_result_override_mu = PTHREAD_MUTEX_INITIALIZER;
22168 // If not nullptr, it points to a batch result with either zero or one
22269 // execution. When an execution result present, it will be passed as the
@@ -247,20 +94,6 @@ struct GlobalRunnerState {
24794 // Reclaims all TLSs in detached_tls_list and cleans up the list.
24895 void CleanUpDetachedTls ();
24996
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-
26497 // State for SanitizerCoverage.
26598 // See https://clang.llvm.org/docs/SanitizerCoverage.html.
26699 SanCovObjectArray sancov_objects;
@@ -272,14 +105,8 @@ struct GlobalRunnerState {
272105 // Tracing CMP instructions, capture events from these domains:
273106 // kCMPEq, kCMPModDiff, kCMPHamming, kCMPModDiffLog, kCMPMsbEq.
274107 // See https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow.
275- // An arbitrarily large size.
276- static constexpr size_t kCmpFeatureSetSize = 1 << 18 ;
277108 // TODO(kcc): remove cmp_feature_set.
278109 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 };
283110
284111 // We think that call stack produces rich signal, so we give a few bits to it.
285112 static constexpr size_t kCallStackFeatureSetSize = 1 << 24 ;
@@ -346,20 +173,9 @@ struct GlobalRunnerState {
346173
347174 // The Watchdog thread sets this to true.
348175 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 };
359176};
360177
361178extern GlobalRunnerState state;
362- extern __thread ThreadLocalRunnerState tls;
363179
364180// Check for stack limit for the stack pointer `sp` in the current thread.
365181void CheckStackLimit (uintptr_t sp);
0 commit comments