[llvm] r310771 - [libFuzzer] experimental support for Clang's coverage (fprofile-instr-generate), Linux-only

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 11 19:05:09 PDT 2017


Hi,

You can simplify this a bit if libFuzzer has access to the profiling runtime.

> On Aug 11, 2017, at 4:03 PM, Kostya Serebryany via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> 
> Author: kcc
> Date: Fri Aug 11 16:03:22 2017
> New Revision: 310771
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=310771&view=rev
> Log:
> [libFuzzer] experimental support for Clang's coverage (fprofile-instr-generate), Linux-only
> 
> Added:
>    llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp
>    llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test
> Modified:
>    llvm/trunk/lib/Fuzzer/CMakeLists.txt
>    llvm/trunk/lib/Fuzzer/FuzzerDefs.h
>    llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
>    llvm/trunk/lib/Fuzzer/FuzzerTracePC.h
> 
> Modified: llvm/trunk/lib/Fuzzer/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/CMakeLists.txt?rev=310771&r1=310770&r2=310771&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Fuzzer/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Fuzzer/CMakeLists.txt Fri Aug 11 16:03:22 2017
> @@ -31,6 +31,7 @@ endif()
> 
> if (LIBFUZZER_ENABLE)
>   add_library(LLVMFuzzerNoMainObjects OBJECT
> +      FuzzerClangCounters.cpp
>       FuzzerCrossOver.cpp
>       FuzzerDriver.cpp
>       FuzzerExtFunctionsDlsym.cpp
> 
> Added: llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp?rev=310771&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp (added)
> +++ llvm/trunk/lib/Fuzzer/FuzzerClangCounters.cpp Fri Aug 11 16:03:22 2017
> @@ -0,0 +1,49 @@
> +//===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +// Coverage counters from Clang's SourceBasedCodeCoverage.
> +//===----------------------------------------------------------------------===//
> +
> +// Support for SourceBasedCodeCoverage is experimental:
> +// * Works only for the main binary, not DSOs yet.
> +// * Works only on Linux.
> +// * Does not implement print_pcs/print_coverage yet.
> +// * Is not fully evaluated for performance and sensitivity.
> +//   We expect large performance drop due to 64-bit counters,
> +//   and *maybe* better sensitivity due to more fine-grained counters.
> +//   Preliminary comparison on a single benchmark (RE2) shows
> +//   a bit worse sensitivity though.
> +
> +#include "FuzzerDefs.h"
> +
> +#if LIBFUZZER_LINUX
> +__attribute__((weak)) extern uint64_t __start___llvm_prf_cnts;
> +__attribute__((weak)) extern uint64_t __stop___llvm_prf_cnts;
> +namespace fuzzer {
> +uint64_t *ClangCountersBegin() { return &__start___llvm_prf_cnts; }
> +uint64_t *ClangCountersEnd() { return &__stop___llvm_prf_cnts; }
> +}  // namespace fuzzer
> +#else
> +// TODO: Implement on Mac (if the data shows it's worth it).
> +//__attribute__((visibility("hidden")))
> +//extern uint64_t CountersStart __asm("section$start$__DATA$__llvm_prf_cnts");
> +//__attribute__((visibility("hidden")))
> +//extern uint64_t CountersEnd __asm("section$end$__DATA$__llvm_prf_cnts");
> +namespace fuzzer {
> +uint64_t *ClangCountersBegin() { return nullptr; }

Use: uint64_t *__llvm_profile_begin_counters(void), and *_end_counters()?

> +uint64_t *ClangCountersEnd() { return  nullptr; }
> +}  // namespace fuzzer
> +#endif
> +
> +namespace fuzzer {
> +ATTRIBUTE_NO_SANITIZE_ALL
> +void ClearClangCounters() {  // hand-written memset, don't asan-ify.
> +  for (auto P = ClangCountersBegin(); P < ClangCountersEnd(); P++)
> +    *P = 0;
> +}

Use: void __llvm_profile_reset_counters(void); ?

> +}
> 
> Modified: llvm/trunk/lib/Fuzzer/FuzzerDefs.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDefs.h?rev=310771&r1=310770&r2=310771&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Fuzzer/FuzzerDefs.h (original)
> +++ llvm/trunk/lib/Fuzzer/FuzzerDefs.h Fri Aug 11 16:03:22 2017
> @@ -123,6 +123,10 @@ uint8_t *ExtraCountersBegin();
> uint8_t *ExtraCountersEnd();
> void ClearExtraCounters();
> 
> +uint64_t *ClangCountersBegin();
> +uint64_t *ClangCountersEnd();
> +void ClearClangCounters();
> +
> }  // namespace fuzzer
> 
> #endif  // LLVM_FUZZER_DEFS_H
> 
> Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp?rev=310771&r1=310770&r2=310771&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp (original)
> +++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.cpp Fri Aug 11 16:03:22 2017
> @@ -126,6 +126,8 @@ void TracePC::PrintModuleInfo() {
>       _Exit(1);
>     }
>   }
> +  if (size_t NumClangCounters = ClangCountersEnd() - ClangCountersBegin())
> +    Printf("INFO: %zd Clang Coverage Counters\n", NumClangCounters);
> }
> 
> ATTRIBUTE_NO_SANITIZE_ALL
> @@ -137,13 +139,12 @@ void TracePC::HandleCallerCallee(uintptr
> }
> 
> void TracePC::UpdateObservedPCs() {

I'm a bit confused by what this is doing. Why is it interesting to track the indices of covered counters? Isn't this something the recorded profile can tell you?

best,
vedant

> +  auto Observe = [&](uintptr_t PC) {
> +    bool Inserted = ObservedPCs.insert(PC).second;
> +    if (Inserted && DoPrintNewPCs)
> +      PrintPC("\tNEW_PC: %p %F %L\n", "\tNEW_PC: %p\n", PC + 1);
> +  };
>   if (NumPCsInPCTables) {
> -    auto Observe = [&](uintptr_t PC) {
> -      bool Inserted = ObservedPCs.insert(PC).second;
> -      if (Inserted && DoPrintNewPCs)
> -        PrintPC("\tNEW_PC: %p %F %L\n", "\tNEW_PC: %p\n", PC + 1);
> -    };
> -
>     if (NumInline8bitCounters == NumPCsInPCTables) {
>       for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
>         uint8_t *Beg = ModuleCounters[i].Start;
> @@ -167,6 +168,13 @@ void TracePC::UpdateObservedPCs() {
>       }
>     }
>   }
> +  if (size_t NumClangCounters =
> +      ClangCountersEnd() - ClangCountersBegin()) {
> +    auto P = ClangCountersBegin();
> +    for (size_t Idx = 0; Idx < NumClangCounters; Idx++)
> +      if (P[Idx])
> +        Observe((uintptr_t)Idx);
> +  }
> }
> 
> inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
> 
> Modified: llvm/trunk/lib/Fuzzer/FuzzerTracePC.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerTracePC.h?rev=310771&r1=310770&r2=310771&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Fuzzer/FuzzerTracePC.h (original)
> +++ llvm/trunk/lib/Fuzzer/FuzzerTracePC.h Fri Aug 11 16:03:22 2017
> @@ -91,6 +91,7 @@ class TracePC {
>       memset(Counters(), 0, GetNumPCs());
>     ClearExtraCounters();
>     ClearInlineCounters();
> +    ClearClangCounters();
>   }
> 
>   void ClearInlineCounters();
> @@ -196,14 +197,9 @@ void ForEachNonZeroByte(const uint8_t *B
>       Handle8bitCounter(FirstFeature, P - Begin, V);
> }
> 
> -template <class Callback>  // bool Callback(size_t Feature)
> -ATTRIBUTE_NO_SANITIZE_ADDRESS
> -__attribute__((noinline))
> -void TracePC::CollectFeatures(Callback HandleFeature) const {
> -  uint8_t *Counters = this->Counters();
> -  size_t N = GetNumPCs();
> -  auto Handle8bitCounter = [&](size_t FirstFeature,
> -                               size_t Idx, uint8_t Counter) {
> +// Given a non-zero Counters returns a number in [0,7].
> +template<class T>
> +unsigned CounterToFeature(T Counter) {
>     assert(Counter);
>     unsigned Bit = 0;
>     /**/ if (Counter >= 128) Bit = 7;
> @@ -213,7 +209,18 @@ void TracePC::CollectFeatures(Callback H
>     else if (Counter >= 4) Bit = 3;
>     else if (Counter >= 3) Bit = 2;
>     else if (Counter >= 2) Bit = 1;
> -    HandleFeature(FirstFeature + Idx * 8 + Bit);
> +    return Bit;
> +}
> +
> +template <class Callback>  // bool Callback(size_t Feature)
> +ATTRIBUTE_NO_SANITIZE_ADDRESS
> +__attribute__((noinline))
> +void TracePC::CollectFeatures(Callback HandleFeature) const {
> +  uint8_t *Counters = this->Counters();
> +  size_t N = GetNumPCs();
> +  auto Handle8bitCounter = [&](size_t FirstFeature,
> +                               size_t Idx, uint8_t Counter) {
> +    HandleFeature(FirstFeature + Idx * 8 + CounterToFeature(Counter));
>   };
> 
>   size_t FirstFeature = 0;
> @@ -231,6 +238,14 @@ void TracePC::CollectFeatures(Callback H
>     }
>   }
> 
> +  if (size_t NumClangCounters = ClangCountersEnd() - ClangCountersBegin()) {
> +    auto P = ClangCountersBegin();
> +    for (size_t Idx = 0; Idx < NumClangCounters; Idx++)
> +      if (auto Cnt = P[Idx])
> +        HandleFeature(FirstFeature + Idx * 8 + CounterToFeature(Cnt));
> +    FirstFeature += NumClangCounters;
> +  }
> +
>   ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature,
>                      Handle8bitCounter);
>   FirstFeature += (ExtraCountersEnd() - ExtraCountersBegin()) * 8;
> 
> Added: llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test?rev=310771&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test (added)
> +++ llvm/trunk/lib/Fuzzer/test/fprofile-instr-generate.test Fri Aug 11 16:03:22 2017
> @@ -0,0 +1,7 @@
> +# Test libFuzzer + -fprofile-instr-generate
> +REQUIRES: linux
> +RUN: %cpp_compiler %S/SimpleTest.cpp -fsanitize-coverage=0 -fprofile-instr-generate -o %t-SimpleTest-fprofile-instr-generate
> +CHECK-NOT: INFO: Loaded 1 modules
> +CHECK: INFO: {{.*}} Clang Coverage Counters
> +CHECK: BINGO
> +RUN: not %t-SimpleTest-fprofile-instr-generate -runs=1000000 -seed=1 2>&1 | FileCheck %s
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list