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

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 11 19:16:24 PDT 2017


On Fri, Aug 11, 2017 at 7:05 PM, Vedant Kumar <vsk at apple.com> wrote:

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


libFuzzer should be able to link w/ and w/o -fprofile-instr-generate, so
these functions will need to be declared "weak"
But yes, thanks for the hint.
Next time I touch this code I'll simplify it as you suggest.
At this moment it is very experimental and the preliminary results are not
promising,
so this code may not survive in the long term.

>
> > 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?


This is just for printing statistics: how many different PCs are covered in
total during the run.


> Isn't this something the recorded profile can tell you?
>

What's "recorded profile"?
Given that I flush the array of counters after every input, there is no
"recorded profile".




>
> 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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170811/eed03dbc/attachment.html>


More information about the llvm-commits mailing list