[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:17:48 PDT 2017


> On Aug 11, 2017, at 7:16 PM, Kostya Serebryany <kcc at google.com> wrote:
> 
> 
> 
> On Fri, Aug 11, 2017 at 7:05 PM, Vedant Kumar <vsk at apple.com <mailto: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 <mailto: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 <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 <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 <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 <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 <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".

I see, there's no profile written out to disk here.

vedant

>  
> 
> 
>  
> 
> 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 <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 <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 <mailto:llvm-commits at lists.llvm.org>
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits <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/611fed2c/attachment.html>


More information about the llvm-commits mailing list