diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2024-07-18 16:51:02 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2024-07-18 15:16:09 +0000 |
| commit | f3eecf6982a7243293c7e27986d9584d8decce90 (patch) | |
| tree | 9437a2c679a04726039c729253430c7d021c4f5f /executor/executor.cc | |
| parent | 59ef5a4cd18baff428782ce4a2fafa5ee4c041d0 (diff) | |
executor: deduplicate signal per-call
This kind of deduplication is confusing for the fuzzer, which expects to
control the process itself (by MaxSignal and by specifying the calls for
which full signal must be returned).
There's also a chance that it may contribute to the difficulties during
program triage and minimization.
Let's err on the safe side and deduplicate signal only per-call.
Diffstat (limited to 'executor/executor.cc')
| -rw-r--r-- | executor/executor.cc | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/executor/executor.cc b/executor/executor.cc index bfc27a620..bcd75f612 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -244,7 +244,7 @@ static std::optional<ShmemBuilder> output_builder; static uint32 output_size; static void mmap_output(uint32 size); static uint32 hash(uint32 a); -static bool dedup(uint32 sig); +static bool dedup(uint8 index, uint64 sig); static uint64 start_time_ms = 0; static bool flag_debug; @@ -1041,7 +1041,7 @@ thread_t* schedule_call(int call_index, int call_num, uint64 copyout_index, uint } template <typename cover_data_t> -uint32 write_signal(flatbuffers::FlatBufferBuilder& fbb, cover_t* cov, bool all) +uint32 write_signal(flatbuffers::FlatBufferBuilder& fbb, int index, cover_t* cov, bool all) { // Write out feedback signals. // Currently it is code edges computed as xor of two subsequent basic block PCs. @@ -1064,7 +1064,7 @@ uint32 write_signal(flatbuffers::FlatBufferBuilder& fbb, cover_t* cov, bool all) bool ignore = !filter && !prev_filter; prev_pc = pc; prev_filter = filter; - if (ignore || dedup(sig)) + if (ignore || dedup(index, sig)) continue; if (!all && max_signal && max_signal->Contains(sig)) continue; @@ -1211,9 +1211,9 @@ void write_output(int index, cover_t* cov, rpc::CallFlag flags, uint32 error, bo } else { if (flag_collect_signal) { if (is_kernel_64_bit) - signal_off = write_signal<uint64>(fbb, cov, all_signal); + signal_off = write_signal<uint64>(fbb, index, cov, all_signal); else - signal_off = write_signal<uint32>(fbb, cov, all_signal); + signal_off = write_signal<uint32>(fbb, index, cov, all_signal); } if (flag_collect_cover) { if (is_kernel_64_bit) @@ -1431,23 +1431,25 @@ static uint32 hash(uint32 a) } const uint32 dedup_table_size = 8 << 10; -uint64 dedup_table[dedup_table_size]; +uint64 dedup_table_sig[dedup_table_size]; +uint8 dedup_table_index[dedup_table_size]; // Poorman's best-effort hashmap-based deduplication. -// The hashmap is global which means that we deduplicate across different calls. -// This is OK because we are interested only in new signals. -static bool dedup(uint32 sig) +static bool dedup(uint8 index, uint64 sig) { for (uint32 i = 0; i < 4; i++) { uint32 pos = (sig + i) % dedup_table_size; - if (dedup_table[pos] == sig) + if (dedup_table_sig[pos] == sig && dedup_table_index[pos] == index) return true; - if (dedup_table[pos] == 0) { - dedup_table[pos] = sig; + if (dedup_table_sig[pos] == 0 || dedup_table_index[pos] != index) { + dedup_table_index[pos] = index; + dedup_table_sig[pos] = sig; return false; } } - dedup_table[sig % dedup_table_size] = sig; + uint32 pos = sig % dedup_table_size; + dedup_table_sig[pos] = sig; + dedup_table_index[pos] = index; return false; } |
