mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[libFuzzer] change trace-pc to use 8-byte guards
llvm-svn: 281810
This commit is contained in:
parent
6f62f4753a
commit
4b0efbfd4a
@ -358,8 +358,8 @@ private:
|
||||
// See TracePC.cpp
|
||||
class TracePC {
|
||||
public:
|
||||
void HandleTrace(uint8_t *guard, uintptr_t PC);
|
||||
void HandleInit(uint8_t *start, uint8_t *stop);
|
||||
void HandleTrace(uint64_t *guard, uintptr_t PC);
|
||||
void HandleInit(uint64_t *start, uint64_t *stop);
|
||||
void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
|
||||
size_t GetTotalCoverage() { return TotalCoverage; }
|
||||
void SetUseCounters(bool UC) { UseCounters = UC; }
|
||||
@ -374,6 +374,16 @@ class TracePC {
|
||||
return Res;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
TotalCoverage = 0;
|
||||
TotalCounterBits = 0;
|
||||
NumNewPCs = 0;
|
||||
CounterMap.Reset();
|
||||
TotalCoverageMap.Reset();
|
||||
}
|
||||
|
||||
void PrintModuleInfo();
|
||||
|
||||
private:
|
||||
bool UseCounters = false;
|
||||
size_t TotalCoverage = 0;
|
||||
@ -384,7 +394,14 @@ private:
|
||||
size_t NumNewPCs = 0;
|
||||
void AddNewPC(uintptr_t PC) { NewPCs[(NumNewPCs++) % kMaxNewPCs] = PC; }
|
||||
|
||||
uint8_t *Start, *Stop;
|
||||
struct Module {
|
||||
uint64_t *Start, *Stop;
|
||||
};
|
||||
|
||||
Module Modules[4096];
|
||||
size_t NumModules = 0;
|
||||
size_t NumGuards = 0;
|
||||
|
||||
ValueBitMap CounterMap;
|
||||
ValueBitMap TotalCoverageMap;
|
||||
};
|
||||
|
@ -170,6 +170,8 @@ Fuzzer::Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options)
|
||||
PcBuffer = new uintptr_t[PcBufferLen];
|
||||
EF->__sanitizer_set_coverage_pc_buffer(PcBuffer, PcBufferLen);
|
||||
}
|
||||
if (Options.Verbosity)
|
||||
TPC.PrintModuleInfo();
|
||||
}
|
||||
|
||||
Fuzzer::~Fuzzer() { }
|
||||
@ -735,6 +737,7 @@ size_t Fuzzer::ChooseUnitIdxToMutate() {
|
||||
void Fuzzer::ResetCoverage() {
|
||||
ResetEdgeCoverage();
|
||||
MaxCoverage.Reset();
|
||||
TPC.Reset();
|
||||
PrepareCounters(&MaxCoverage);
|
||||
}
|
||||
|
||||
|
@ -18,49 +18,67 @@ namespace fuzzer {
|
||||
|
||||
TracePC TPC;
|
||||
|
||||
void TracePC::HandleTrace(uint8_t *Guard, uintptr_t PC) {
|
||||
void TracePC::HandleTrace(uint64_t *Guard, uintptr_t PC) {
|
||||
const uint64_t kBit63 = 1ULL << 63;
|
||||
uint64_t Value = *Guard;
|
||||
if (Value & kBit63) return;
|
||||
// Printf(" >> %16zx %p\n", Value, Guard);
|
||||
if (UseCounters) {
|
||||
uintptr_t GV = *Guard;
|
||||
if (GV == 0) {
|
||||
size_t Idx = Guard - Start;
|
||||
uint64_t Counter = Value & 0xff;
|
||||
if (Counter == 0) {
|
||||
size_t Idx = Value >> 32;
|
||||
if (TotalCoverageMap.AddValue(Idx)) {
|
||||
TotalCoverage++;
|
||||
AddNewPC(PC);
|
||||
}
|
||||
}
|
||||
if (GV < 255)
|
||||
GV++;
|
||||
*Guard = GV;
|
||||
if (Counter < 255)
|
||||
Value++;
|
||||
} else {
|
||||
*Guard = 0xff;
|
||||
Value |= kBit63;
|
||||
TotalCoverage++;
|
||||
AddNewPC(PC);
|
||||
}
|
||||
// Printf(" << %16zx\n", Value);
|
||||
*Guard = Value;
|
||||
}
|
||||
|
||||
void TracePC::HandleInit(uint8_t *Start, uint8_t *Stop) {
|
||||
// TODO: this handles only one DSO/binary.
|
||||
this->Start = Start;
|
||||
this->Stop = Stop;
|
||||
void TracePC::HandleInit(uint64_t *Start, uint64_t *Stop) {
|
||||
if (Start == Stop || *Start) return;
|
||||
assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
|
||||
for (uint64_t *P = Start; P < Stop; P++)
|
||||
*P = (++NumGuards) << 32;
|
||||
Modules[NumModules].Start = Start;
|
||||
Modules[NumModules].Stop = Stop;
|
||||
NumModules++;
|
||||
}
|
||||
|
||||
void TracePC::PrintModuleInfo() {
|
||||
Printf("INFO: Loaded %zd modules (%zd guards): ", NumModules, NumGuards);
|
||||
for (size_t i = 0; i < NumModules; i++)
|
||||
Printf("[%p, %p), ", Modules[i].Start, Modules[i].Stop);
|
||||
Printf("\n");
|
||||
}
|
||||
|
||||
void TracePC::FinalizeTrace() {
|
||||
if (UseCounters && TotalCoverage) {
|
||||
for (uint8_t *X = Start; X < Stop; X++) {
|
||||
uint8_t Value = *X;
|
||||
size_t Idx = X - Start;
|
||||
if (Value >= 1) {
|
||||
unsigned Bit = 0;
|
||||
/**/ if (Value >= 128) Bit = 7;
|
||||
else if (Value >= 32) Bit = 6;
|
||||
else if (Value >= 16) Bit = 5;
|
||||
else if (Value >= 8) Bit = 4;
|
||||
else if (Value >= 4) Bit = 3;
|
||||
else if (Value >= 3) Bit = 2;
|
||||
else if (Value >= 2) Bit = 1;
|
||||
CounterMap.AddValue(Idx * 8 + Bit);
|
||||
for (size_t M = 0; M < NumModules; M++) {
|
||||
for (uint64_t *X = Modules[M].Start; X < Modules[M].Stop; X++) {
|
||||
uint64_t Value = *X & 0xff;
|
||||
uint64_t Idx = *X >> 32;
|
||||
if (Value >= 1) {
|
||||
unsigned Bit = 0;
|
||||
/**/ if (Value >= 128) Bit = 7;
|
||||
else if (Value >= 32) Bit = 6;
|
||||
else if (Value >= 16) Bit = 5;
|
||||
else if (Value >= 8) Bit = 4;
|
||||
else if (Value >= 4) Bit = 3;
|
||||
else if (Value >= 3) Bit = 2;
|
||||
else if (Value >= 2) Bit = 1;
|
||||
CounterMap.AddValue(Idx * 8 + Bit);
|
||||
}
|
||||
*X = Idx << 32;
|
||||
}
|
||||
*X = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,13 +101,13 @@ void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
|
||||
|
||||
extern "C" {
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_pc_guard(uint8_t *Guard) {
|
||||
void __sanitizer_cov_trace_pc_guard(uint64_t *Guard) {
|
||||
uintptr_t PC = (uintptr_t)__builtin_return_address(0);
|
||||
fuzzer::TPC.HandleTrace(Guard, PC);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void __sanitizer_cov_trace_pc_guard_init(uint8_t *Start, uint8_t *Stop) {
|
||||
void __sanitizer_cov_trace_pc_guard_init(uint64_t *Start, uint64_t *Stop) {
|
||||
fuzzer::TPC.HandleInit(Start, Stop);
|
||||
}
|
||||
|
||||
|
11
lib/Fuzzer/test/DSO1.cpp
Normal file
11
lib/Fuzzer/test/DSO1.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// Source code for a simple DSO.
|
||||
|
||||
int DSO1(int a) {
|
||||
if (a < 123456)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
11
lib/Fuzzer/test/DSO2.cpp
Normal file
11
lib/Fuzzer/test/DSO2.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// Source code for a simple DSO.
|
||||
|
||||
int DSO2(int a) {
|
||||
if (a < 3598235)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
11
lib/Fuzzer/test/DSOTestExtra.cpp
Normal file
11
lib/Fuzzer/test/DSOTestExtra.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// Source code for a simple DSO.
|
||||
|
||||
int DSOTestExtra(int a) {
|
||||
if (a < 452345)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
27
lib/Fuzzer/test/DSOTestMain.cpp
Normal file
27
lib/Fuzzer/test/DSOTestMain.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
|
||||
// Source code for a simple DSO.
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
extern int DSO1(int a);
|
||||
extern int DSO2(int a);
|
||||
extern int DSOTestExtra(int a);
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
if (Size < sizeof(int) * 3) return 0;
|
||||
int x, y, z;
|
||||
memcpy(&x, Data + 0 * sizeof(int), sizeof(int));
|
||||
memcpy(&y, Data + 1 * sizeof(int), sizeof(int));
|
||||
memcpy(&z, Data + 2 * sizeof(int), sizeof(int));
|
||||
int sum = DSO1(x) + DSO2(y) + DSOTestExtra(z);
|
||||
if (sum == 3) {
|
||||
fprintf(stderr, "BINGO %d %d %d\n", x, y, z);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -9,7 +9,7 @@ RUN: rm -f fuzz-{0,1}.log
|
||||
RUN: LLVMFuzzer-EmptyTest -max_total_time=4 -jobs=2 -workers=2 FuzzerJobsTestCORPUS > %t-fuzzer-jobs-test.log 2>&1 & export FUZZER_PID=$!
|
||||
# Wait a short while to give time for the child processes
|
||||
# to start fuzzing
|
||||
RUN: sleep 1
|
||||
RUN: sleep 2
|
||||
# If the instances are running in parallel they should have created their log
|
||||
# files by now.
|
||||
RUN: ls fuzz-0.log
|
||||
|
@ -49,3 +49,7 @@ OOB: is located 0 bytes to the right of 3-byte region
|
||||
|
||||
RUN: not LLVMFuzzer-InitializeTest 2>&1 | FileCheck %s
|
||||
|
||||
RUN: not LLVMFuzzer-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO
|
||||
DSO: INFO: Loaded 3 modules
|
||||
DSO: BINGO
|
||||
|
||||
|
@ -15,3 +15,25 @@ endforeach()
|
||||
|
||||
# Propagate value into parent directory
|
||||
set(TestBinaries ${TestBinaries} PARENT_SCOPE)
|
||||
|
||||
add_library(LLVMFuzzer-DSO1 SHARED ../DSO1.cpp)
|
||||
add_library(LLVMFuzzer-DSO2 SHARED ../DSO2.cpp)
|
||||
|
||||
add_executable(LLVMFuzzer-DSOTest
|
||||
../DSOTestMain.cpp
|
||||
../DSOTestExtra.cpp)
|
||||
|
||||
target_link_libraries(LLVMFuzzer-DSOTest
|
||||
LLVMFuzzer-DSO1
|
||||
LLVMFuzzer-DSO2
|
||||
LLVMFuzzer
|
||||
)
|
||||
|
||||
set_target_properties(LLVMFuzzer-DSOTest PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
||||
"${CMAKE_BINARY_DIR}/lib/Fuzzer/test")
|
||||
set_target_properties(LLVMFuzzer-DSO1 PROPERTIES LIBRARY_OUTPUT_DIRECTORY
|
||||
"${CMAKE_BINARY_DIR}/lib/Fuzzer/lib")
|
||||
set_target_properties(LLVMFuzzer-DSO2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY
|
||||
"${CMAKE_BINARY_DIR}/lib/Fuzzer/lib")
|
||||
|
||||
set(TestBinaries ${TestBinaries} LLVMFuzzer-DSOTest)
|
||||
|
Loading…
Reference in New Issue
Block a user