aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-08-20 18:57:05 +0200
committervan Hauser <vh@thc.org>2020-08-20 18:57:05 +0200
commit4ce5ed370a1c18c8c7d7f6ad4fa029a34e1326e4 (patch)
tree107c1d6e552c01001d6c53f20376b3ef46673e31
parentf7bac482e9bae7b835ef014dabcea87408d80880 (diff)
downloadafl++-4ce5ed370a1c18c8c7d7f6ad4fa029a34e1326e4.tar.gz
LTO: sancov made default, deprecated SKIPSINGLEBLOCK, deactivate LTO autodict for cmplog binaries
-rw-r--r--docs/Changelog.md10
-rw-r--r--llvm_mode/GNUmakefile9
-rw-r--r--llvm_mode/LLVMInsTrim.so.cc4
-rw-r--r--llvm_mode/SanitizerCoverageLTO.so.cc2
-rw-r--r--llvm_mode/afl-clang-fast.c15
-rw-r--r--llvm_mode/afl-llvm-lto-instrim.so.cc951
-rw-r--r--llvm_mode/afl-llvm-lto-instrumentation.so.cc4
-rw-r--r--llvm_mode/afl-llvm-pass.so.cc4
8 files changed, 22 insertions, 977 deletions
diff --git a/docs/Changelog.md b/docs/Changelog.md
index efb5ed0b..d00d59d7 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -10,8 +10,14 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++2.67d (develop)
- - Further llvm 12 support (fast moving target like afl++ :-) )
- - Fix for auto dictionary not to throw out a -x dictionary
+ - afl-fuzz:
+ - Fix for auto dictionary entries found during fuzzing to not throw out
+ a -x dictionary
+ - llvm_mode:
+ - Ported SanCov to LTO, and made it the default for LTO. better
+ instrumentation locations
+ - Further llvm 12 support (fast moving target like afl++ :-) )
+ - deprecated LLVM SKIPSINGLEBLOCK env environment
### Version ++2.67c (release)
diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile
index 72295bc8..5d938469 100644
--- a/llvm_mode/GNUmakefile
+++ b/llvm_mode/GNUmakefile
@@ -274,7 +274,7 @@ ifeq "$(TEST_MMAP)" "1"
LDFLAGS += -Wno-deprecated-declarations
endif
- PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-ld-lto ../afl-llvm-lto-instrumentlist.so ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so ../SanitizerCoverageLTO.so
+ PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-ld-lto ../afl-llvm-lto-instrumentlist.so ../afl-llvm-lto-instrumentation.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so ../SanitizerCoverageLTO.so
# If prerequisites are not given, warn, do not build anything, and exit with code 0
ifeq "$(LLVMVER)" ""
@@ -374,11 +374,6 @@ ifeq "$(LLVM_LTO)" "1"
@$(CLANG_BIN) $(CFLAGS_SAFE) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
endif
-../afl-llvm-lto-instrim.so: afl-llvm-lto-instrim.so.cc afl-llvm-common.o
-ifeq "$(LLVM_LTO)" "1"
- $(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL) afl-llvm-common.o
-endif
-
# laf
../split-switches-pass.so: split-switches-pass.so.cc afl-llvm-common.o | test_deps
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
@@ -427,7 +422,7 @@ all_done: test_build
install: all
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
- if [ -f ../afl-clang-lto ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../afl-llvm-rt-lto*.o ../afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
+ if [ -f ../afl-clang-lto ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-llvm-lto-instrumentation.so ../afl-llvm-rt-lto*.o ../afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi
if [ -f ../afl-ld-lto ]; then set -e; install -m 755 ../afl-ld-lto $${DESTDIR}$(BIN_PATH); fi
if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc
index 6b2aaf23..775e9591 100644
--- a/llvm_mode/LLVMInsTrim.so.cc
+++ b/llvm_mode/LLVMInsTrim.so.cc
@@ -132,10 +132,6 @@ struct InsTrim : public ModulePass {
}
- if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") ||
- getenv("AFL_LLVM_SKIPSINGLEBLOCK"))
- function_minimum_size = 2;
-
unsigned int PrevLocSize = 0;
char * ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE");
diff --git a/llvm_mode/SanitizerCoverageLTO.so.cc b/llvm_mode/SanitizerCoverageLTO.so.cc
index 412582fa..95834a36 100644
--- a/llvm_mode/SanitizerCoverageLTO.so.cc
+++ b/llvm_mode/SanitizerCoverageLTO.so.cc
@@ -425,6 +425,8 @@ bool ModuleSanitizerCoverage::instrumentModule(
if ((afl_global_id = atoi(ptr)) < 0)
FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is negative\n", ptr);
+ if (getenv("AFL_LLVM_CMPLOG")) autodictionary = 0;
+
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
if ((documentFile = fopen(ptr, "a")) == NULL)
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index 70d7181a..cafc9265 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -347,11 +347,6 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (lto_mode) {
- if (cmplog_mode)
- unsetenv("AFL_LLVM_LTO_AUTODICTIONARY");
- else
- setenv("AFL_LLVM_LTO_AUTODICTIONARY", "1", 1);
-
#if defined(AFL_CLANG_LDPATH) && LLVM_VERSION_MAJOR >= 12
u8 *ld_ptr = strrchr(AFL_REAL_LD, '/');
if (!ld_ptr) ld_ptr = "ld.lld";
@@ -753,7 +748,13 @@ int main(int argc, char **argv, char **envp) {
if (strncasecmp(ptr, "afl", strlen("afl")) == 0 ||
strncasecmp(ptr, "classic", strlen("classic")) == 0) {
- if (!instrument_mode || instrument_mode == INSTRUMENT_AFL)
+ if (instrument_mode == INSTRUMENT_LTO) {
+
+ instrument_mode = INSTRUMENT_CLASSIC;
+ lto_mode = 1;
+
+ } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL)
+
instrument_mode = INSTRUMENT_AFL;
else
FATAL("main instrumentation mode already set with %s",
@@ -845,7 +846,7 @@ int main(int argc, char **argv, char **envp) {
callname = "afl-clang-lto";
if (!instrument_mode) {
- instrument_mode = INSTRUMENT_LTO;
+ instrument_mode = INSTRUMENT_CFG;
ptr = instrument_mode_string[instrument_mode];
}
diff --git a/llvm_mode/afl-llvm-lto-instrim.so.cc b/llvm_mode/afl-llvm-lto-instrim.so.cc
deleted file mode 100644
index 98e9ff9a..00000000
--- a/llvm_mode/afl-llvm-lto-instrim.so.cc
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- american fuzzy lop++ - LLVM-mode instrumentation pass
- ---------------------------------------------------
-
- Copyright 2019-2020 AFLplusplus Project. All rights reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at:
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- This library is plugged into LLVM when invoking clang through afl-clang-fast
- or afl-clang-lto with AFL_LLVM_INSTRUMENT=CFG or =INSTRIM
-
- */
-
-#define AFL_LLVM_PASS
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include <unordered_set>
-#include <list>
-#include <string>
-#include <fstream>
-#include <set>
-
-#include "llvm/Config/llvm-config.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/CFG.h"
-#include "llvm/IR/Dominators.h"
-#include "llvm/IR/DebugInfo.h"
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/IR/Module.h"
-#include "llvm/IR/Verifier.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/Analysis/MemorySSAUpdater.h"
-#include "llvm/Analysis/ValueTracking.h"
-
-#include "MarkNodes.h"
-#include "afl-llvm-common.h"
-
-#include "config.h"
-#include "debug.h"
-
-using namespace llvm;
-
-static cl::opt<bool> MarkSetOpt("markset", cl::desc("MarkSet"),
- cl::init(false));
-static cl::opt<bool> LoopHeadOpt("loophead", cl::desc("LoopHead"),
- cl::init(false));
-
-namespace {
-
-struct InsTrimLTO : public ModulePass {
-
- protected:
- uint32_t function_minimum_size = 1;
- char * skip_nozero = NULL;
- int afl_global_id = 1, autodictionary = 1;
- uint32_t inst_blocks = 0, inst_funcs = 0;
- uint64_t map_addr = 0x10000;
-
- public:
- static char ID;
-
- InsTrimLTO() : ModulePass(ID) {
-
- char *ptr;
-
- if (getenv("AFL_DEBUG")) debug = 1;
- if ((ptr = getenv("AFL_LLVM_LTO_STARTID")) != NULL)
- if ((afl_global_id = atoi(ptr)) < 0 || afl_global_id >= MAP_SIZE)
- FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is not between 0 and %d\n",
- ptr, MAP_SIZE - 1);
-
- skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
-
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
-
- ModulePass::getAnalysisUsage(AU);
- AU.addRequired<DominatorTreeWrapperPass>();
- AU.addRequired<LoopInfoWrapperPass>();
-
- }
-
- StringRef getPassName() const override {
-
- return "InstTrim LTO Instrumentation";
-
- }
-
- bool runOnModule(Module &M) override {
-
- char be_quiet = 0;
- char * ptr;
- uint32_t locations = 0, functions = 0;
-
- setvbuf(stdout, NULL, _IONBF, 0);
-
- if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
-
- SAYF(cCYA "InsTrimLTO" VERSION cRST
- " by csienslab and Marc \"vanHauser\" Heuse\n");
-
- } else
-
- be_quiet = 1;
-
- /* Process environment variables */
-
- if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0;
-
- if ((ptr = getenv("AFL_LLVM_MAP_ADDR"))) {
-
- uint64_t val;
- if (!*ptr || !strcmp(ptr, "0") || !strcmp(ptr, "0x0")) {
-
- map_addr = 0;
-
- } else if (map_addr == 0) {
-
- FATAL(
- "AFL_LLVM_MAP_ADDR and AFL_LLVM_MAP_DYNAMIC cannot be used "
- "together");
-
- } else if (strncmp(ptr, "0x", 2) != 0) {
-
- map_addr = 0x10000; // the default
-
- } else {
-
- val = strtoull(ptr, NULL, 16);
- if (val < 0x100 || val > 0xffffffff00000000) {
-
- FATAL(
- "AFL_LLVM_MAP_ADDR must be a value between 0x100 and "
- "0xffffffff00000000");
-
- }
-
- map_addr = val;
-
- }
-
- }
-
- if (debug) { fprintf(stderr, "map address is %lu\n", map_addr); }
-
- if (getenv("AFL_LLVM_INSTRIM_LOOPHEAD") != NULL ||
- getenv("LOOPHEAD") != NULL) {
-
- LoopHeadOpt = true;
-
- }
-
- if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") ||
- getenv("AFL_LLVM_SKIPSINGLEBLOCK"))
- function_minimum_size = 2;
-
- // this is our default
- MarkSetOpt = true;
-
- /* Initialize LLVM instrumentation */
-
- LLVMContext & C = M.getContext();
- std::vector<std::string> dictionary;
- std::vector<CallInst *> calls;
- DenseMap<Value *, std::string *> valueMap;
-
- IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
- IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
- IntegerType *Int64Ty = IntegerType::getInt64Ty(C);
-
- ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
- ConstantInt *One = ConstantInt::get(Int8Ty, 1);
-
- /* Get/set globals for the SHM region. */
-
- GlobalVariable *AFLMapPtr = NULL;
- Value * MapPtrFixed = NULL;
-
- if (!map_addr) {
-
- AFLMapPtr =
- new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
- GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
-
- } else {
-
- ConstantInt *MapAddr = ConstantInt::get(Int64Ty, map_addr);
- MapPtrFixed =
- ConstantExpr::getIntToPtr(MapAddr, PointerType::getUnqual(Int8Ty));
-
- }
-
- if (autodictionary) {
-
- /* Some implementation notes.
- *
- * We try to handle 3 cases:
- * - memcmp("foo", arg, 3) <- literal string
- * - static char globalvar[] = "foo";
- * memcmp(globalvar, arg, 3) <- global variable
- * - char localvar[] = "foo";
- * memcmp(locallvar, arg, 3) <- local variable
- *
- * The local variable case is the hardest. We can only detect that
- * case if there is no reassignment or change in the variable.
- * And it might not work across llvm version.
- * What we do is hooking the initializer function for local variables
- * (llvm.memcpy.p0i8.p0i8.i64) and note the string and the assigned
- * variable. And if that variable is then used in a compare function
- * we use that noted string.
- * This seems not to work for tokens that have a size <= 4 :-(
- *
- * - if the compared length is smaller than the string length we
- * save the full string. This is likely better for fuzzing but
- * might be wrong in a few cases depending on optimizers
- *
- * - not using StringRef because there is a bug in the llvm 11
- * checkout I am using which sometimes points to wrong strings
- *
- * Over and out. Took me a full day. damn. mh/vh
- */
-
- for (Function &F : M) {
-
- for (auto &BB : F) {
-
- for (auto &IN : BB) {
-
- CallInst *callInst = nullptr;
-
- if ((callInst = dyn_cast<CallInst>(&IN))) {
-
- bool isStrcmp = true;
- bool isMemcmp = true;
- bool isStrncmp = true;
- bool isStrcasecmp = true;
- bool isStrncasecmp = true;
- bool isIntMemcpy = true;
- bool addedNull = false;
- uint8_t optLen = 0;
-
- Function *Callee = callInst->getCalledFunction();
- if (!Callee) continue;
- if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
- std::string FuncName = Callee->getName().str();
- isStrcmp &= !FuncName.compare("strcmp");
- isMemcmp &= !FuncName.compare("memcmp");
- isStrncmp &= !FuncName.compare("strncmp");
- isStrcasecmp &= !FuncName.compare("strcasecmp");
- isStrncasecmp &= !FuncName.compare("strncasecmp");
- isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
-
- if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
- !isStrncasecmp && !isIntMemcpy)
- continue;
-
- /* Verify the strcmp/memcmp/strncmp/strcasecmp/strncasecmp
- * function prototype */
- FunctionType *FT = Callee->getFunctionType();
-
- isStrcmp &= FT->getNumParams() == 2 &&
- FT->getReturnType()->isIntegerTy(32) &&
- FT->getParamType(0) == FT->getParamType(1) &&
- FT->getParamType(0) ==
- IntegerType::getInt8PtrTy(M.getContext());
- isStrcasecmp &= FT->getNumParams() == 2 &&
- FT->getReturnType()->isIntegerTy(32) &&
- FT->getParamType(0) == FT->getParamType(1) &&
- FT->getParamType(0) ==
- IntegerType::getInt8PtrTy(M.getContext());
- isMemcmp &= FT->getNumParams() == 3 &&
- FT->getReturnType()->isIntegerTy(32) &&
- FT->getParamType(0)->isPointerTy() &&
- FT->getParamType(1)->isPointerTy() &&
- FT->getParamType(2)->isIntegerTy();
- isStrncmp &= FT->getNumParams() == 3 &&
- FT->getReturnType()->isIntegerTy(32) &&
- FT->getParamType(0) == FT->getParamType(1) &&
- FT->getParamType(0) ==
- IntegerType::getInt8PtrTy(M.getContext()) &&
- FT->getParamType(2)->isIntegerTy();
- isStrncasecmp &= FT->getNumParams() == 3 &&
- FT->getReturnType()->isIntegerTy(32) &&
- FT->getParamType(0) == FT->getParamType(1) &&
- FT->getParamType(0) ==
- IntegerType::getInt8PtrTy(M.getContext()) &&
- FT->getParamType(2)->isIntegerTy();
-
- if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
- !isStrncasecmp && !isIntMemcpy)
- continue;
-
- /* is a str{n,}{case,}cmp/memcmp, check if we have
- * str{case,}cmp(x, "const") or str{case,}cmp("const", x)
- * strn{case,}cmp(x, "const", ..) or strn{case,}cmp("const", x,
- * ..) memcmp(x, "const", ..) or memcmp("const", x, ..) */
- Value *Str1P = callInst->getArgOperand(0),
- *Str2P = callInst->getArgOperand(1);
- std::string Str1, Str2;
- StringRef TmpStr;
- bool HasStr1 = getConstantStringInfo(Str1P, TmpStr);
- if (TmpStr.empty())
- HasStr1 = false;
- else
- Str1 = TmpStr.str();
- bool HasStr2 = getConstantStringInfo(Str2P, TmpStr);
- if (TmpStr.empty())
- HasStr2 = false;
- else
- Str2 = TmpStr.str();
-
- if (debug)
- fprintf(stderr, "F:%s %p(%s)->\"%s\"(%s) %p(%s)->\"%s\"(%s)\n",
- FuncName.c_str(), Str1P, Str1P->getName().str().c_str(),
- Str1.c_str(), HasStr1 == true ? "true" : "false", Str2P,
- Str2P->getName().str().c_str(), Str2.c_str(),
- HasStr2 == true ? "true" : "false");
-
- // we handle the 2nd parameter first because of llvm memcpy
- if (!HasStr2) {
-
- auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
- if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
-
- if (auto *Var =
- dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
-
- if (Var->hasInitializer()) {
-
- if (auto *Array = dyn_cast<ConstantDataArray>(
- Var->getInitializer())) {
-
- HasStr2 = true;
- Str2 = Array->getAsString().str();
-
- }
-
- }
-
- }
-
- }
-
- }
-
- // for the internal memcpy routine we only care for the second
- // parameter and are not reporting anything.
- if (isIntMemcpy == true) {
-
- if (HasStr2 == true) {
-
- Value * op2 = callInst->getArgOperand(2);
- ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
- if (ilen) {
-
- uint64_t literalLength = Str2.size();
- uint64_t optLength = ilen->getZExtValue();
- if (literalLength + 1 == optLength) {
-
- Str2.append("\0", 1); // add null byte
- addedNull = true;
-
- }
-
- }
-
- valueMap[Str1P] = new std::string(Str2);
-
- if (debug)
- fprintf(stderr, "Saved: %s for %p\n", Str2.c_str(), Str1P);
- continue;
-
- }
-
- continue;
-
- }
-
- // Neither a literal nor a global variable?
- // maybe it is a local variable that we saved
- if (!HasStr2) {
-
- std::string *strng = valueMap[Str2P];
- if (strng && !strng->empty()) {
-
- Str2 = *strng;
- HasStr2 = true;
- if (debug)
- fprintf(stderr, "Filled2: %s for %p\n", strng->c_str(),
- Str2P);
-
- }
-
- }
-
- if (!HasStr1) {
-
- auto Ptr = dyn_cast<ConstantExpr>(Str1P);
-
- if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) {
-
- if (auto *Var =
- dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
-
- if (Var->hasInitializer()) {
-
- if (auto *Array = dyn_cast<ConstantDataArray>(
- Var->getInitializer())) {
-
- HasStr1 = true;
- Str1 = Array->getAsString().str();
-
- }
-
- }
-
- }
-
- }
-
- }
-
- // Neither a literal nor a global variable?
- // maybe it is a local variable that we saved
- if (!HasStr1) {
-
- std::string *strng = valueMap[Str1P];
- if (strng && !strng->empty()) {
-
- Str1 = *strng;
- HasStr1 = true;
- if (debug)
- fprintf(stderr, "Filled1: %s for %p\n", strng->c_str(),
- Str1P);
-
- }
-
- }
-
- /* handle cases of one string is const, one string is variable */
- if (!(HasStr1 ^ HasStr2)) continue;
-
- std::string thestring;
-
- if (HasStr1)
- thestring = Str1;
- else
- thestring = Str2;
-
- optLen = thestring.length();
-
- if (isMemcmp || isStrncmp || isStrncasecmp) {
-
- Value * op2 = callInst->getArgOperand(2);
- ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
- if (ilen) {
-
- uint64_t literalLength = optLen;
- optLen = ilen->getZExtValue();
- if (literalLength + 1 == optLen) { // add null byte
- thestring.append("\0", 1);
- addedNull = true;
-
- }
-
- }
-
- }
-
- // add null byte if this is a string compare function and a null
- // was not already added
- if (addedNull == false && !isMemcmp) {
-
- thestring.append("\0", 1); // add null byte
- optLen++;
-
- }
-
- if (!be_quiet) {
-
- std::string outstring;
- fprintf(stderr, "%s: length %u/%u \"", FuncName.c_str(), optLen,
- (unsigned int)thestring.length());
- for (uint8_t i = 0; i < thestring.length(); i++) {
-
- uint8_t c = thestring[i];
- if (c <= 32 || c >= 127)
- fprintf(stderr, "\\x%02x", c);
- else
- fprintf(stderr, "%c", c);
-
- }
-
- fprintf(stderr, "\"\n");
-
- }
-
- // we take the longer string, even if the compare was to a
- // shorter part. Note that depending on the optimizer of the
- // compiler this can be wrong, but it is more likely that this
- // is helping the fuzzer
- if (optLen != thestring.length()) optLen = thestring.length();
- if (optLen > MAX_AUTO_EXTRA) optLen = MAX_AUTO_EXTRA;
- if (optLen < MIN_AUTO_EXTRA) // too short? skip
- continue;
-
- dictionary.push_back(thestring.substr(0, optLen));
-
- }
-
- }
-
- }
-
- }
-
- }
-
- /* InsTrim instrumentation starts here */
-
- u64 total_rs = 0;
- u64 total_hs = 0;
-
- for (Function &F : M) {
-
- if (debug) {
-
- uint32_t bb_cnt = 0;
-
- for (auto &BB : F)
- if (BB.size() > 0) ++bb_cnt;
- SAYF(cMGN "[D] " cRST "Function %s size %zu %u\n",
- F.getName().str().c_str(), F.size(), bb_cnt);
-
- }
-
- // if the function below our minimum size skip it (1 or 2)
- if (F.size() < function_minimum_size) continue;
- if (isIgnoreFunction(&F)) continue;
-
- functions++;
-
- // the instrument file list check
- AttributeList Attrs = F.getAttributes();
- if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
-
- if (debug)
- fprintf(stderr,
- "DEBUG: Function %s is not the instrument file listed\n",
- F.getName().str().c_str());
- continue;
-
- }
-
- std::unordered_set<BasicBlock *> MS;
- if (!MarkSetOpt) {
-
- for (auto &BB : F) {
-
- MS.insert(&BB);
-
- }
-
- total_rs += F.size();
-
- } else {
-
- auto Result = markNodes(&F);
- auto RS = Result.first;
- auto HS = Result.second;
-
- MS.insert(RS.begin(), RS.end());
- if (!LoopHeadOpt) {
-
- MS.insert(HS.begin(), HS.end());
- total_rs += MS.size();
-
- } else {
-
- DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeSet;
- DominatorTreeWrapperPass * DTWP =
- &getAnalysis<DominatorTreeWrapperPass>(F);
- auto DT = &DTWP->getDomTree();
-
- total_rs += RS.size();
- total_hs += HS.size();
-
- for (BasicBlock *BB : HS) {
-
- bool Inserted = false;
- for (auto BI = pred_begin(BB), BE = pred_end(BB); BI != BE; ++BI) {
-
- auto Edge = BasicBlockEdge(*BI, BB);
- if (Edge.isSingleEdge() && DT->dominates(Edge, BB)) {
-
- EdgeSet.insert({*BI, BB});
- Inserted = true;
- break;
-
- }
-
- }
-
- if (!Inserted) {
-
- MS.insert(BB);
- total_rs += 1;
- total_hs -= 1;
-
- }
-
- }
-
- for (auto I = EdgeSet.begin(), E = EdgeSet.end(); I != E; ++I) {
-
- auto PredBB = I->first;
- auto SuccBB = I->second;
- auto NewBB = SplitBlockPredecessors(SuccBB, {PredBB}, ".split", DT,
- nullptr, nullptr, false);
- MS.insert(NewBB);
-
- }
-
- }
-
- }
-
- for (BasicBlock &BB : F) {
-
- auto PI = pred_begin(&BB);
- auto PE = pred_end(&BB);
- IRBuilder<> IRB(&*BB.getFirstInsertionPt());
- Value * L = NULL;
-
- if (MarkSetOpt && MS.find(&BB) == MS.end()) { continue; }
-
- if (PI == PE) {
-
- L = ConstantInt::get(Int32Ty, afl_global_id++);
- locations++;
-
- } else {
-
- auto *PN = PHINode::Create(Int32Ty, 0, "", &*BB.begin());
- DenseMap<BasicBlock *, unsigned> PredMap;
- for (auto PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
-
- BasicBlock *PBB = *PI;
- auto It = PredMap.insert({PBB, afl_global_id++});
- unsigned Label = It.first->second;
- PN->addIncoming(ConstantInt::get(Int32Ty, Label), PBB);
- locations++;
-
- }
-
- L = PN;
-
- }
-
- /* Load SHM pointer */
- Value *MapPtrIdx;
-
- if (map_addr) {
-
- MapPtrIdx = IRB.CreateGEP(MapPtrFixed, L);
-
- } else {
-
- LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
- MapPtr->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
- MapPtrIdx = IRB.CreateGEP(MapPtr, L);
-
- }
-
- /* Update bitmap */
- LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
- Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-
- Value *Incr = IRB.CreateAdd(Counter, One);
-
- if (skip_nozero == NULL) {
-
- auto cf = IRB.CreateICmpEQ(Incr, Zero);
- auto carry = IRB.CreateZExt(cf, Int8Ty);
- Incr = IRB.CreateAdd(Incr, carry);
-
- }
-
- IRB.CreateStore(Incr, MapPtrIdx)
- ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-
- // done :)
-
- inst_blocks++;
-
- }
-
- }
-
- // save highest location ID to global variable
- // do this after each function to fail faster
- if (!be_quiet && afl_global_id > MAP_SIZE &&
- afl_global_id > FS_OPT_MAX_MAPSIZE) {
-
- uint32_t pow2map = 1, map = afl_global_id;
- while ((map = map >> 1))
- pow2map++;
- WARNF(
- "We have %u blocks to instrument but the map size is only %u. Either "
- "edit config.h and set MAP_SIZE_POW2 from %u to %u, then recompile "
- "afl-fuzz and llvm_mode and then make this target - or set "
- "AFL_MAP_SIZE with at least size %u when running afl-fuzz with this "
- "target.",
- afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map, afl_global_id);
-
- }
-
- if (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr) {
-
- // yes we could create our own function, insert it into ctors ...
- // but this would be a pain in the butt ... so we use afl-llvm-rt-lto.o
-
- Function *f = M.getFunction("__afl_auto_init_globals");
-
- if (!f) {
-
- fprintf(stderr,
- "Error: init function could not be found (this should not "
- "happen)\n");
- exit(-1);
-
- }
-
- BasicBlock *bb = &f->getEntryBlock();
- if (!bb) {
-
- fprintf(stderr,
- "Error: init function does not have an EntryBlock (this should "
- "not happen)\n");
- exit(-1);
-
- }
-
- BasicBlock::iterator IP = bb->getFirstInsertionPt();
- IRBuilder<> IRB(&(*IP));
-
- if (map_addr) {
-
- GlobalVariable *AFLMapAddrFixed =
- new GlobalVariable(M, Int64Ty, true, GlobalValue::ExternalLinkage,
- 0, "__afl_map_addr");
- ConstantInt *MapAddr = ConstantInt::get(Int64Ty, map_addr);
- StoreInst * StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed);
- StoreMapAddr->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- }
-
- if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL) {
-
- uint32_t write_loc = afl_global_id;
-
- if (afl_global_id % 8) write_loc = (((afl_global_id + 8) >> 3) << 3);
-
- GlobalVariable *AFLFinalLoc =
- new GlobalVariable(M, Int32Ty, true, GlobalValue::ExternalLinkage,
- 0, "__afl_final_loc");
- ConstantInt *const_loc = ConstantInt::get(Int32Ty, write_loc);
- StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc);
- StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- }
-
- if (dictionary.size()) {
-
- size_t memlen = 0, count = 0, offset = 0;
- char * ptr;
-
- for (auto token : dictionary) {
-
- memlen += token.length();
- count++;
-
- }
-
- if (!be_quiet)
- printf("AUTODICTIONARY: %lu string%s found\n", count,
- count == 1 ? "" : "s");
-
- if (count) {
-
- if ((ptr = (char *)malloc(memlen + count)) == NULL) {
-
- fprintf(stderr, "Error: malloc for %lu bytes failed!\n",
- memlen + count);
- exit(-1);
-
- }
-
- count = 0;
-
- for (auto token : dictionary) {
-
- if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
-
- ptr[offset++] = (uint8_t)token.length();
- memcpy(ptr + offset, token.c_str(), token.length());
- offset += token.length();
- count++;
-
- }
-
- }
-
- GlobalVariable *AFLDictionaryLen = new GlobalVariable(
- M, Int32Ty, false, GlobalValue::ExternalLinkage, 0,
- "__afl_dictionary_len");
- ConstantInt *const_len = ConstantInt::get(Int32Ty, offset);
- StoreInst * StoreDictLen =
- IRB.CreateStore(const_len, AFLDictionaryLen);
- StoreDictLen->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- ArrayType *ArrayTy = ArrayType::get(IntegerType::get(C, 8), offset);
- GlobalVariable *AFLInternalDictionary = new GlobalVariable(
- M, ArrayTy, true, GlobalValue::ExternalLinkage,
- ConstantDataArray::get(
- C, *(new ArrayRef<char>((char *)ptr, offset))),
- "__afl_internal_dictionary");
- AFLInternalDictionary->setInitializer(ConstantDataArray::get(
- C, *(new ArrayRef<char>((char *)ptr, offset))));
- AFLInternalDictionary->setConstant(true);
-
- GlobalVariable *AFLDictionary = new GlobalVariable(
- M, PointerType::get(Int8Ty, 0), false,
- GlobalValue::ExternalLinkage, 0, "__afl_dictionary");
-
- Value *AFLDictOff = IRB.CreateGEP(AFLInternalDictionary, Zero);
- Value *AFLDictPtr =
- IRB.CreatePointerCast(AFLDictOff, PointerType::get(Int8Ty, 0));
- StoreInst *StoreDict = IRB.CreateStore(AFLDictPtr, AFLDictionary);
- StoreDict->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- }
-
- }
-
- }
-
- // count basic blocks for comparison with classic instrumentation
-
- u32 edges = 0;
- for (auto &F : M) {
-
- if (F.size() < function_minimum_size) continue;
-
- for (auto &BB : F) {
-
- bool would_instrument = false;
-
- for (BasicBlock *Pred : predecessors(&BB)) {
-
- int count = 0;
- for (BasicBlock *Succ : successors(Pred))
- if (Succ != NULL) count++;
-
- if (count > 1) would_instrument = true;
-
- }
-
- if (would_instrument == true) edges++;
-
- }
-
- }
-
- /* Say something nice. */
-
- if (!be_quiet) {
-
- if (!inst_blocks)
- WARNF("No instrumentation targets found.");
- else {
-
- char modeline[100];
- snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
- getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
- getenv("AFL_USE_ASAN") ? ", ASAN" : "",
- getenv("AFL_USE_MSAN") ? ", MSAN" : "",
- getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
- getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
- OKF("Instrumented %u locations for %u edges in %u functions (%llu, "
- "%llu) with no collisions (on "
- "average %llu collisions would be in afl-gcc/afl-clang-fast for %u "
- "edges) (%s mode).",
- inst_blocks, locations, functions, total_rs, total_hs,
- calculateCollisions(edges), edges, modeline);
-
- }
-
- }
-
- return true;
-
- }
-
-}; // end of struct InsTrim
-
-} // end of anonymous namespace
-
-char InsTrimLTO::ID = 0;
-
-static void registerInsTrimLTO(const PassManagerBuilder &,
- legacy::PassManagerBase &PM) {
-
- PM.add(new InsTrimLTO());
-
-}
-
-static RegisterPass<InsTrimLTO> X("afl-lto-instrim",
- "afl++ InsTrim LTO instrumentation pass",
- false, false);
-
-static RegisterStandardPasses RegisterInsTrimLTO(
- PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerInsTrimLTO);
-
diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
index 18bee7a5..12509ab2 100644
--- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
@@ -128,6 +128,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
be_quiet = 1;
+ if (getenv("AFL_LLVM_CMPLOG")) autodictionary = 0;
+
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
if ((documentFile = fopen(ptr, "a")) == NULL)
@@ -142,8 +144,6 @@ bool AFLLTOPass::runOnModule(Module &M) {
/*if (getenv("AFL_LLVM_MAP_DYNAMIC"))*/
map_addr = 0;
- if (getenv("AFL_LLVM_SKIPSINGLEBLOCK")) function_minimum_size = 2;
-
if ((ptr = getenv("AFL_LLVM_MAP_ADDR"))) {
uint64_t val;
diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc
index 0206080f..86c6f3c6 100644
--- a/llvm_mode/afl-llvm-pass.so.cc
+++ b/llvm_mode/afl-llvm-pass.so.cc
@@ -182,10 +182,6 @@ bool AFLCoverage::runOnModule(Module &M) {
#endif
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
- if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") ||
- getenv("AFL_LLVM_SKIPSINGLEBLOCK"))
- function_minimum_size = 2;
-
unsigned PrevLocSize = 0;
char *ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");