diff options
author | Dan Liew <dan@su-root.co.uk> | 2016-06-07 23:32:50 +0000 |
---|---|---|
committer | Dan Liew <dan@su-root.co.uk> | 2016-06-07 23:32:50 +0000 |
commit | 1873a496e20a391633fc29665d6620c1ca3191f7 (patch) | |
tree | abb6a28df749fed5b9e653269cdcd941af9d7bb1 /llvm/lib/Fuzzer/FuzzerLoop.cpp | |
parent | 32c940de377ec87a072e3d7c3f3200beec6fe90e (diff) | |
download | bcm5719-llvm-1873a496e20a391633fc29665d6620c1ca3191f7.tar.gz bcm5719-llvm-1873a496e20a391633fc29665d6620c1ca3191f7.zip |
[LibFuzzer] Declare and use sanitizer functions in ``fuzzer::ExternalFunctions``
This fixes linking problems on OSX.
Unfortunately it turns out we need to use an instance of the
``fuzzer::ExternalFunctions`` object in several places so this
commit also replaces all instances with a single global instance.
It also turns out initializing a global ``fuzzer::ExternalFunctions``
before main is entered (i.e. letting the object be initialised by the
global initializers) is not safe (on OSX the call to ``Printf()`` in the
CTOR crashes if it is called from a global initializer) so we instead
have a global ``fuzzer::ExternalFunctions*`` and initialize it inside
``FuzzerDriver()``.
Multiple unit tests depend also depend on the
``fuzzer::ExternalFunctions*`` global so a ``main()`` function has been
added that initializes it before running any tests.
Differential Revision: http://reviews.llvm.org/D20943
llvm-svn: 272072
Diffstat (limited to 'llvm/lib/Fuzzer/FuzzerLoop.cpp')
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerLoop.cpp | 78 |
1 files changed, 28 insertions, 50 deletions
diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp index b7422329e05..5cfbad4c327 100644 --- a/llvm/lib/Fuzzer/FuzzerLoop.cpp +++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp @@ -31,47 +31,23 @@ #endif #endif -extern "C" { -// Re-declare some of the sanitizer functions as "weak" so that -// libFuzzer can be linked w/o the sanitizers and sanitizer-coverage -// (in which case it will complain at start-up time). -__attribute__((weak)) void __sanitizer_print_stack_trace(); -__attribute__((weak)) void __sanitizer_reset_coverage(); -__attribute__((weak)) size_t __sanitizer_get_total_unique_caller_callee_pairs(); -__attribute__((weak)) size_t __sanitizer_get_total_unique_coverage(); -__attribute__((weak)) void -__sanitizer_set_death_callback(void (*callback)(void)); -__attribute__((weak)) size_t __sanitizer_get_number_of_counters(); -__attribute__((weak)) uintptr_t -__sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset); -__attribute__((weak)) uintptr_t -__sanitizer_get_coverage_pc_buffer(uintptr_t **data); - -__attribute__((weak)) void __sanitizer_malloc_hook(void *ptr, size_t size); -__attribute__((weak)) void __sanitizer_free_hook(void *ptr); -__attribute__((weak)) void __lsan_enable(); -__attribute__((weak)) void __lsan_disable(); -__attribute__((weak)) int __lsan_do_recoverable_leak_check(); -__attribute__((weak)) int __sanitizer_print_memory_profile(size_t); -} - namespace fuzzer { static const size_t kMaxUnitSizeToPrint = 256; static const size_t TruncateMaxRuns = 1000; thread_local bool Fuzzer::IsMyThread; -static void MissingWeakApiFunction(const char *FnName) { +static void MissingExternalApiFunction(const char *FnName) { Printf("ERROR: %s is not defined. Exiting.\n" "Did you use -fsanitize-coverage=... to build your code?\n", FnName); exit(1); } -#define CHECK_WEAK_API_FUNCTION(fn) \ +#define CHECK_EXTERNAL_FUNCTION(fn) \ do { \ - if (!fn) \ - MissingWeakApiFunction(#fn); \ + if (!(EF->fn)) \ + MissingExternalApiFunction(#fn); \ } while (false) // Only one Fuzzer per process. @@ -79,21 +55,21 @@ static Fuzzer *F; struct CoverageController { static void Reset() { - CHECK_WEAK_API_FUNCTION(__sanitizer_reset_coverage); - __sanitizer_reset_coverage(); + CHECK_EXTERNAL_FUNCTION(__sanitizer_reset_coverage); + EF->__sanitizer_reset_coverage(); PcMapResetCurrent(); } static void ResetCounters(const Fuzzer::FuzzingOptions &Options) { if (Options.UseCounters) { - __sanitizer_update_counter_bitset_and_clear_counters(0); + EF->__sanitizer_update_counter_bitset_and_clear_counters(0); } } static void Prepare(const Fuzzer::FuzzingOptions &Options, Fuzzer::Coverage *C) { if (Options.UseCounters) { - size_t NumCounters = __sanitizer_get_number_of_counters(); + size_t NumCounters = EF->__sanitizer_get_number_of_counters(); C->CounterBitmap.resize(NumCounters); } } @@ -104,16 +80,16 @@ struct CoverageController { Fuzzer::Coverage *C) { bool Res = false; - uint64_t NewBlockCoverage = __sanitizer_get_total_unique_coverage(); + uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage(); if (NewBlockCoverage > C->BlockCoverage) { Res = true; C->BlockCoverage = NewBlockCoverage; } if (Options.UseIndirCalls && - __sanitizer_get_total_unique_caller_callee_pairs) { + EF->__sanitizer_get_total_unique_caller_callee_pairs) { uint64_t NewCallerCalleeCoverage = - __sanitizer_get_total_unique_caller_callee_pairs(); + EF->__sanitizer_get_total_unique_caller_callee_pairs(); if (NewCallerCalleeCoverage > C->CallerCalleeCoverage) { Res = true; C->CallerCalleeCoverage = NewCallerCalleeCoverage; @@ -122,7 +98,7 @@ struct CoverageController { if (Options.UseCounters) { uint64_t CounterDelta = - __sanitizer_update_counter_bitset_and_clear_counters( + EF->__sanitizer_update_counter_bitset_and_clear_counters( C->CounterBitmap.data()); if (CounterDelta > 0) { Res = true; @@ -137,7 +113,8 @@ struct CoverageController { } uintptr_t *CoverageBuf; - uint64_t NewPcBufferLen = __sanitizer_get_coverage_pc_buffer(&CoverageBuf); + uint64_t NewPcBufferLen = + EF->__sanitizer_get_coverage_pc_buffer(&CoverageBuf); if (NewPcBufferLen > C->PcBufferLen) { Res = true; C->PcBufferLen = NewPcBufferLen; @@ -163,8 +140,8 @@ void Fuzzer::LazyAllocateCurrentUnitData() { } void Fuzzer::SetDeathCallback() { - CHECK_WEAK_API_FUNCTION(__sanitizer_set_death_callback); - __sanitizer_set_death_callback(StaticDeathCallback); + CHECK_EXTERNAL_FUNCTION(__sanitizer_set_death_callback); + EF->__sanitizer_set_death_callback(StaticDeathCallback); } void Fuzzer::StaticDeathCallback() { @@ -206,8 +183,8 @@ void Fuzzer::StaticInterruptCallback() { void Fuzzer::CrashCallback() { Printf("==%d== ERROR: libFuzzer: deadly signal\n", GetPid()); - if (__sanitizer_print_stack_trace) - __sanitizer_print_stack_trace(); + if (EF->__sanitizer_print_stack_trace) + EF->__sanitizer_print_stack_trace(); Printf("NOTE: libFuzzer has rudimentary signal handlers.\n" " Combine libFuzzer with AddressSanitizer or similar for better " "crash reports.\n"); @@ -242,8 +219,8 @@ void Fuzzer::AlarmCallback() { DumpCurrentUnit("timeout-"); Printf("==%d== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(), Seconds); - if (__sanitizer_print_stack_trace) - __sanitizer_print_stack_trace(); + if (EF->__sanitizer_print_stack_trace) + EF->__sanitizer_print_stack_trace(); Printf("SUMMARY: libFuzzer: timeout\n"); PrintFinalStats(); _Exit(Options.TimeoutExitCode); // Stop right now. @@ -255,8 +232,8 @@ void Fuzzer::RssLimitCallback() { "==%d== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n", GetPid(), GetPeakRSSMb(), Options.RssLimitMb); Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); - if (__sanitizer_print_memory_profile) - __sanitizer_print_memory_profile(50); + if (EF->__sanitizer_print_memory_profile) + EF->__sanitizer_print_memory_profile(50); DumpCurrentUnit("oom-"); Printf("SUMMARY: libFuzzer: out-of-memory\n"); PrintFinalStats(); @@ -422,7 +399,7 @@ bool Fuzzer::UpdateMaxCoverage() { if (Options.PrintNewCovPcs && PrevBufferLen != MaxCoverage.PcBufferLen) { uintptr_t *CoverageBuf; - __sanitizer_get_coverage_pc_buffer(&CoverageBuf); + EF->__sanitizer_get_coverage_pc_buffer(&CoverageBuf); assert(CoverageBuf); for (size_t I = PrevBufferLen; I < MaxCoverage.PcBufferLen; ++I) { Printf("%p\n", CoverageBuf[I]); @@ -651,13 +628,14 @@ void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, bool DuringInitialCorpusExecution) { if (!HasMoreMallocsThanFrees) return; // mallocs==frees, a leak is unlikely. if (!Options.DetectLeaks) return; - if (!&__lsan_enable || !&__lsan_disable || !__lsan_do_recoverable_leak_check) + if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) || + !(EF->__lsan_do_recoverable_leak_check)) return; // No lsan. // Run the target once again, but with lsan disabled so that if there is // a real leak we do not report it twice. - __lsan_disable(); + EF->__lsan_disable(); RunOne(Data, Size); - __lsan_enable(); + EF->__lsan_enable(); if (!HasMoreMallocsThanFrees) return; // a leak is unlikely. if (NumberOfLeakDetectionAttempts++ > 1000) { Options.DetectLeaks = false; @@ -670,7 +648,7 @@ void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, } // Now perform the actual lsan pass. This is expensive and we must ensure // we don't call it too often. - if (__lsan_do_recoverable_leak_check()) { // Leak is found, report it. + if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it. if (DuringInitialCorpusExecution) Printf("\nINFO: a leak has been found in the initial corpus.\n\n"); Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n"); |