about summary refs log tree commit diff
path: root/instrumentation
diff options
context:
space:
mode:
Diffstat (limited to 'instrumentation')
-rw-r--r--instrumentation/SanitizerCoverageLTO.so.cc29
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc44
-rw-r--r--instrumentation/afl-compiler-rt.o.c130
-rw-r--r--instrumentation/afl-llvm-dict2file.so.cc7
4 files changed, 135 insertions, 75 deletions
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc
index a09f28a9..63ea71c1 100644
--- a/instrumentation/SanitizerCoverageLTO.so.cc
+++ b/instrumentation/SanitizerCoverageLTO.so.cc
@@ -214,8 +214,12 @@ class ModuleSanitizerCoverageLTO
 
   void SetNoSanitizeMetadata(Instruction *I) {
 
+#if LLVM_VERSION_MAJOR >= 19
+    I->setNoSanitizeMetadata();
+#else
     I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
                    MDNode::get(*C, None));
+#endif
 
   }
 
@@ -225,7 +229,7 @@ class ModuleSanitizerCoverageLTO
   FunctionCallee SanCovTracePCIndir;
   FunctionCallee SanCovTracePC /*, SanCovTracePCGuard*/;
   Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
-      *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
+      *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
   Module           *CurModule;
   std::string       CurModuleUniqueId;
   Triple            TargetTriple;
@@ -416,6 +420,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
   Int16Ty = IRB.getInt16Ty();
   Int8Ty = IRB.getInt8Ty();
   Int1Ty = IRB.getInt1Ty();
+  PtrTy = PointerType::getUnqual(*C);
 
   /* AFL++ START */
   char        *ptr;
@@ -1350,7 +1355,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
     Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
 
   if (F.empty()) return;
-  if (F.getName().find(".module_ctor") != std::string::npos)
+  if (F.getName().contains(".module_ctor"))
     return;  // Should not instrument sanitizer init functions.
 #if LLVM_VERSION_MAJOR >= 18
   if (F.getName().starts_with("__sanitizer_"))
@@ -1372,6 +1377,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
   if (F.hasPersonalityFn() &&
       isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
     return;
+  if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
+#if LLVM_VERSION_MAJOR >= 19
+  if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return;
+#endif
   // if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName()))
   //  return;
   // if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))
@@ -2023,16 +2032,20 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray(
 
     if (&F.getEntryBlock() == AllBlocks[i]) {
 
-      PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
-      PCs.push_back((Constant *)IRB.CreateIntToPtr(
-          ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
+      PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
+      PCs.push_back(
+          (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
 
     } else {
 
       PCs.push_back((Constant *)IRB.CreatePointerCast(
-          BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
-      PCs.push_back((Constant *)IRB.CreateIntToPtr(
-          ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
+          BlockAddress::get(AllBlocks[i]), PtrTy));
+#if LLVM_VERSION_MAJOR >= 16
+      PCs.push_back(Constant::getNullValue(PtrTy));
+#else
+      PCs.push_back(
+          (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 0), PtrTy));
+#endif
 
     }
 
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index 01881f28..49fe904b 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -161,7 +161,9 @@ class ModuleSanitizerCoverageAFL
 
   void SetNoSanitizeMetadata(Instruction *I) {
 
-#if LLVM_VERSION_MAJOR >= 16
+#if LLVM_VERSION_MAJOR >= 19
+    I->setNoSanitizeMetadata();
+#elif LLVM_VERSION_MAJOR >= 16
     I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt));
 #else
     I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
@@ -179,7 +181,7 @@ class ModuleSanitizerCoverageAFL
   FunctionCallee  SanCovTraceSwitchFunction;
   GlobalVariable *SanCovLowestStack;
   Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
-      *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
+      *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
   Module           *CurModule;
   std::string       CurModuleUniqueId;
   Triple            TargetTriple;
@@ -272,13 +274,19 @@ std::pair<Value *, Value *> ModuleSanitizerCoverageAFL::CreateSecStartEnd(
   if (!TargetTriple.isOSBinFormatCOFF())
     return std::make_pair(SecStart, SecEnd);
 
-  // Account for the fact that on windows-msvc __start_* symbols actually
-  // point to a uint64_t before the start of the array.
+    // Account for the fact that on windows-msvc __start_* symbols actually
+    // point to a uint64_t before the start of the array.
+#if LLVM_VERSION_MAJOR >= 19
+  auto GEP =
+      IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
+  return std::make_pair(GEP, SecEnd);
+#else
   auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy);
   auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr,
                            ConstantInt::get(IntptrTy, sizeof(uint64_t)));
   return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)),
                         SecEnd);
+#endif
 
 }
 
@@ -370,6 +378,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
   Int16Ty = IRB.getInt16Ty();
   Int8Ty = IRB.getInt8Ty();
   Int1Ty = IRB.getInt1Ty();
+  PtrTy = PointerType::getUnqual(*C);
 
   LLVMContext &Ctx = M.getContext();
   AFLMapPtr =
@@ -572,7 +581,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
 
   if (F.empty()) return;
   if (!isInInstrumentList(&F, FMNAME)) return;
-  if (F.getName().find(".module_ctor") != std::string::npos)
+  // if (F.getName().find(".module_ctor") != std::string::npos)
+  if (F.getName().contains(".module_ctor"))
     return;  // Should not instrument sanitizer init functions.
 #if LLVM_VERSION_MAJOR >= 18
   if (F.getName().starts_with("__sanitizer_"))
@@ -595,6 +605,9 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
       isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
     return;
   if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
+#if LLVM_VERSION_MAJOR >= 19
+  if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return;
+#endif
   if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
     SplitAllCriticalEdges(
         F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
@@ -692,16 +705,16 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
 
     if (&F.getEntryBlock() == AllBlocks[i]) {
 
-      PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
-      PCs.push_back((Constant *)IRB.CreateIntToPtr(
-          ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
+      PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
+      PCs.push_back(
+          (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
 
     } else {
 
       PCs.push_back((Constant *)IRB.CreatePointerCast(
-          BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
+          BlockAddress::get(AllBlocks[i]), PtrTy));
 #if LLVM_VERSION_MAJOR >= 16
-      PCs.push_back(Constant::getNullValue(IntptrPtrTy));
+      PCs.push_back(Constant::getNullValue(PtrTy));
 #else
       PCs.push_back((Constant *)IRB.CreateIntToPtr(
           ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
@@ -711,10 +724,10 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
 
   }
 
-  auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy,
-                                                    SanCovPCsSectionName);
+  auto *PCArray =
+      CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName);
   PCArray->setInitializer(
-      ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs));
+      ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs));
   PCArray->setConstant(true);
 
   return PCArray;
@@ -822,7 +835,12 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
         StringRef FuncName = Callee->getName();
         if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
 
+#if LLVM_VERSION_MAJOR >= 20
+        // test canary
+        InstrumentationIRBuilder IRB(callInst);
+#else
         IRBuilder<> IRB(callInst);
+#endif
 
         if (!FunctionGuardArray) {
 
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index c08e6380..0da689b2 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -118,6 +118,7 @@ u32 __afl_map_size = MAP_SIZE;
 u32 __afl_dictionary_len;
 u64 __afl_map_addr;
 u32 __afl_first_final_loc;
+u32 __afl_old_forkserver;
 
 #ifdef __AFL_CODE_COVERAGE
 typedef struct afl_module_info_t afl_module_info_t;
@@ -616,7 +617,7 @@ static void __afl_map_shm(void) {
     fprintf(stderr,
             "DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
             "__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE "
-            "%u, __afl_final_loc %u, __afl_map_size %u",
+            "%u, __afl_final_loc %u, __afl_map_size %u\n",
             id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
             __afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
             __afl_final_loc, __afl_map_size);
@@ -856,7 +857,7 @@ static void __afl_start_forkserver(void) {
   signal(SIGTERM, at_exit);
 
   u32 already_read_first = 0;
-  u32 was_killed;
+  u32 was_killed = 0;
   u32 version = 0x41464c00 + FS_NEW_VERSION_MAX;
   u32 tmp = version ^ 0xffffffff, status2, status = version;
   u8 *msg = (u8 *)&status;
@@ -866,75 +867,95 @@ static void __afl_start_forkserver(void) {
 
   void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
 
-  /* Phone home and tell the parent that we're OK. If parent isn't there,
-     assume we're not running in forkserver mode and just execute program. */
+  if (getenv("AFL_OLD_FORKSERVER")) {
 
-  // return because possible non-forkserver usage
-  if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
+    __afl_old_forkserver = 1;
+    status = 0;
 
-  if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
-  if (tmp != status2) {
+    if (__afl_final_loc > MAP_SIZE) {
 
-    write_error("wrong forkserver message from AFL++ tool");
-    _exit(1);
+      fprintf(stderr,
+              "Warning: AFL_OLD_FORKSERVER is used with a target compiled with "
+              "non-colliding coverage instead of AFL_LLVM_INSTRUMENT=CLASSIC - "
+              "this target may crash!\n");
+
+    }
 
   }
 
-  // send the set/requested options to forkserver
-  status = FS_NEW_OPT_MAPSIZE;  // we always send the map size
-  if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
-  if (__afl_dictionary_len && __afl_dictionary) {
+  /* Phone home and tell the parent that we're OK. If parent isn't there,
+     assume we're not running in forkserver mode and just execute program. */
 
-    status |= FS_NEW_OPT_AUTODICT;
+  if (!__afl_old_forkserver) {
 
-  }
+    // return because possible non-forkserver usage
+    if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
 
-  if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
+    if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
+    if (tmp != status2) {
 
-  // Now send the parameters for the set options, increasing by option number
+      write_error("wrong forkserver message from AFL++ tool");
+      _exit(1);
 
-  // FS_NEW_OPT_MAPSIZE - we always send the map size
-  status = __afl_map_size;
-  if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
+    }
 
-  // FS_NEW_OPT_SHDMEM_FUZZ - no data
+    // send the set/requested options to forkserver
+    status = FS_NEW_OPT_MAPSIZE;  // we always send the map size
+    if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
+    if (__afl_dictionary_len && __afl_dictionary) {
 
-  // FS_NEW_OPT_AUTODICT - send autodictionary
-  if (__afl_dictionary_len && __afl_dictionary) {
+      status |= FS_NEW_OPT_AUTODICT;
 
-    // pass the dictionary through the forkserver FD
-    u32 len = __afl_dictionary_len, offset = 0;
+    }
 
-    if (write(FORKSRV_FD + 1, &len, 4) != 4) {
+    if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
 
-      write(2, "Error: could not send dictionary len\n",
-            strlen("Error: could not send dictionary len\n"));
-      _exit(1);
+    // Now send the parameters for the set options, increasing by option number
 
-    }
+    // FS_NEW_OPT_MAPSIZE - we always send the map size
+    status = __afl_map_size;
+    if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
+
+    // FS_NEW_OPT_SHDMEM_FUZZ - no data
 
-    while (len != 0) {
+    // FS_NEW_OPT_AUTODICT - send autodictionary
+    if (__afl_dictionary_len && __afl_dictionary) {
 
-      s32 ret;
-      ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
+      // pass the dictionary through the forkserver FD
+      u32 len = __afl_dictionary_len, offset = 0;
 
-      if (ret < 1) {
+      if (write(FORKSRV_FD + 1, &len, 4) != 4) {
 
-        write_error("could not send dictionary");
+        write(2, "Error: could not send dictionary len\n",
+              strlen("Error: could not send dictionary len\n"));
         _exit(1);
 
       }
 
-      len -= ret;
-      offset += ret;
+      while (len != 0) {
+
+        s32 ret;
+        ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
+
+        if (ret < 1) {
+
+          write_error("could not send dictionary");
+          _exit(1);
+
+        }
+
+        len -= ret;
+        offset += ret;
+
+      }
 
     }
 
-  }
+    // send welcome message as final message
+    status = version;
+    if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
 
-  // send welcome message as final message
-  status = version;
-  if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
+  }
 
   // END forkserver handshake
 
@@ -948,13 +969,13 @@ static void __afl_start_forkserver(void) {
 
     /* Wait for parent by reading from the pipe. Abort if read fails. */
 
-    if (already_read_first) {
+    if (unlikely(already_read_first)) {
 
       already_read_first = 0;
 
     } else {
 
-      if (read(FORKSRV_FD, &was_killed, 4) != 4) {
+      if (unlikely(read(FORKSRV_FD, &was_killed, 4) != 4)) {
 
         write_error("read from AFL++ tool");
         _exit(1);
@@ -993,10 +1014,10 @@ static void __afl_start_forkserver(void) {
        condition and afl-fuzz already issued SIGKILL, write off the old
        process. */
 
-    if (child_stopped && was_killed) {
+    if (unlikely(child_stopped && was_killed)) {
 
       child_stopped = 0;
-      if (waitpid(child_pid, &status, 0) < 0) {
+      if (unlikely(waitpid(child_pid, &status, 0) < 0)) {
 
         write_error("child_stopped && was_killed");
         _exit(1);
@@ -1005,12 +1026,12 @@ static void __afl_start_forkserver(void) {
 
     }
 
-    if (!child_stopped) {
+    if (unlikely(!child_stopped)) {
 
       /* Once woken up, create a clone of our process. */
 
       child_pid = fork();
-      if (child_pid < 0) {
+      if (unlikely(child_pid < 0)) {
 
         write_error("fork");
         _exit(1);
@@ -1019,7 +1040,7 @@ static void __afl_start_forkserver(void) {
 
       /* In child process: close fds, resume execution. */
 
-      if (!child_pid) {
+      if (unlikely(!child_pid)) {  // just to signal afl-fuzz faster
 
         //(void)nice(-20);
 
@@ -1044,14 +1065,15 @@ static void __afl_start_forkserver(void) {
 
     /* In parent process: write PID to pipe, then wait for child. */
 
-    if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) {
+    if (unlikely(write(FORKSRV_FD + 1, &child_pid, 4) != 4)) {
 
       write_error("write to afl-fuzz");
       _exit(1);
 
     }
 
-    if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) {
+    if (unlikely(waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) <
+                 0)) {
 
       write_error("waitpid");
       _exit(1);
@@ -1062,11 +1084,11 @@ static void __afl_start_forkserver(void) {
        a successful run. In this case, we want to wake it up without forking
        again. */
 
-    if (WIFSTOPPED(status)) child_stopped = 1;
+    if (likely(WIFSTOPPED(status))) { child_stopped = 1; }
 
     /* Relay wait status to pipe, then loop back. */
 
-    if (write(FORKSRV_FD + 1, &status, 4) != 4) {
+    if (unlikely(write(FORKSRV_FD + 1, &status, 4) != 4)) {
 
       write_error("writing to afl-fuzz");
       _exit(1);
@@ -2704,7 +2726,7 @@ void __afl_coverage_skip() {
 // mark this area as especially interesting
 void __afl_coverage_interesting(u8 val, u32 id) {
 
-  __afl_area_ptr[id] = val;
+  __afl_area_ptr[id % __afl_map_size] = val;
 
 }
 
diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc
index b93f61f0..6559bc84 100644
--- a/instrumentation/afl-llvm-dict2file.so.cc
+++ b/instrumentation/afl-llvm-dict2file.so.cc
@@ -661,6 +661,13 @@ bool AFLdict2filePass::runOnModule(Module &M) {
             Value       *op2 = callInst->getArgOperand(2);
             ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
 
+            if (!ilen) {
+
+              op2 = callInst->getArgOperand(1);
+              ilen = dyn_cast<ConstantInt>(op2);
+
+            }
+
             if (ilen) {
 
               uint64_t literalLength = optLen;