aboutsummaryrefslogtreecommitdiff
path: root/llvm_mode
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-08-17 23:42:45 +0200
committerGitHub <noreply@github.com>2020-08-17 23:42:45 +0200
commit0a6084f3613f15d2508d43334d28e671f5c6c573 (patch)
treea58da1d2ed34cef4020c1fccbd70c4679d7e59fb /llvm_mode
parent8044ae28be2dd109ac16719ce2e304074fa74efd (diff)
parent9532499ef5280ae4c7aa3d189dd7a924a38e8358 (diff)
downloadafl++-0a6084f3613f15d2508d43334d28e671f5c6c573.tar.gz
Merge pull request #499 from AFLplusplus/dev
important push to stable
Diffstat (limited to 'llvm_mode')
-rw-r--r--llvm_mode/GNUmakefile9
-rw-r--r--llvm_mode/LLVMInsTrim.so.cc8
-rw-r--r--llvm_mode/README.instrument_list.md18
-rw-r--r--llvm_mode/afl-clang-fast.c122
-rw-r--r--llvm_mode/afl-ld-lto.c2
-rw-r--r--llvm_mode/afl-llvm-common.cc357
-rw-r--r--llvm_mode/afl-llvm-common.h1
-rw-r--r--llvm_mode/afl-llvm-lto-instrumentation.so.cc174
-rw-r--r--llvm_mode/afl-llvm-pass.so.cc9
-rw-r--r--llvm_mode/afl-llvm-rt.o.c151
-rw-r--r--llvm_mode/cmplog-instructions-pass.cc6
-rw-r--r--llvm_mode/cmplog-routines-pass.cc6
-rw-r--r--llvm_mode/compare-transform-pass.so.cc10
-rw-r--r--llvm_mode/split-compares-pass.so.cc6
-rw-r--r--llvm_mode/split-switches-pass.so.cc6
15 files changed, 503 insertions, 382 deletions
diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile
index 0fa9b12e..fb4e8537 100644
--- a/llvm_mode/GNUmakefile
+++ b/llvm_mode/GNUmakefile
@@ -206,6 +206,9 @@ AFL_CLANG_FUSELD=
ifeq "$(LLVM_LTO)" "1"
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
AFL_CLANG_FUSELD=1
+ ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(LLVM_BINDIR)/ld.lld -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
+ AFL_CLANG_LDPATH=1
+ endif
else
$(warn -fuse-ld is not working, cannot enable LTO mode)
LLVM_LTO = 0
@@ -218,7 +221,9 @@ CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ../include/ \
-DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
-DLLVM_LIBDIR=\"$(LLVM_LIBDIR)\" -DLLVM_VERSION=\"$(LLVMVER)\" \
-DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \
- -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
+ -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \
+ -DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" \
+ -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
-DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function
override CFLAGS += $(CFLAGS_SAFE)
@@ -236,7 +241,7 @@ endif
ifneq "$(LLVM_CONFIG)" ""
CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
endif
-CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC $(CXXFLAGS)
+CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC $(CXXFLAGS) -Wno-deprecated-declarations
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc
index 4d8c4719..206e2682 100644
--- a/llvm_mode/LLVMInsTrim.so.cc
+++ b/llvm_mode/LLVMInsTrim.so.cc
@@ -94,7 +94,7 @@ struct InsTrim : public ModulePass {
}
-#if LLVM_VERSION_MAJOR >= 4 || \
+#if LLVM_VERSION_MAJOR > 4 || \
(LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
#define AFL_HAVE_VECTOR_INTRINSICS 1
#endif
@@ -144,7 +144,7 @@ struct InsTrim : public ModulePass {
#ifdef AFL_HAVE_VECTOR_INTRINSICS
unsigned int ngram_size = 0;
/* Decide previous location vector size (must be a power of two) */
- VectorType *PrevLocTy;
+ VectorType *PrevLocTy = NULL;
if (ngram_size_str)
if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
@@ -194,7 +194,7 @@ struct InsTrim : public ModulePass {
new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
GlobalVariable *AFLPrevLoc;
- GlobalVariable *AFLContext;
+ GlobalVariable *AFLContext = NULL;
LoadInst * PrevCtx = NULL; // for CTX sensitive coverage
if (ctx_str)
@@ -256,6 +256,8 @@ struct InsTrim : public ModulePass {
u64 total_rs = 0;
u64 total_hs = 0;
+ scanForDangerousFunctions(&M);
+
for (Function &F : M) {
if (debug) {
diff --git a/llvm_mode/README.instrument_list.md b/llvm_mode/README.instrument_list.md
index d4739dda..1fc06414 100644
--- a/llvm_mode/README.instrument_list.md
+++ b/llvm_mode/README.instrument_list.md
@@ -14,13 +14,13 @@ disturbance by uninteresting code being exercised.
For this purpose, a "partial instrumentation" support en par with llvm sancov
is provided by afl++ that allows you to specify on a source file and function
-level which should be compiled with or without instrumentation.
+level which function should be compiled with or without instrumentation.
Note: When using PCGUARD mode - and have llvm 12+ - you can use this instead:
https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation
-the llvm sancov list format is fully supported by afl++, however afl++ has
-more flexbility.
+The llvm sancov list format is fully supported by afl++, however afl++ has
+more flexibility.
## 2) Building the LLVM module
@@ -35,13 +35,13 @@ The only required change is that you need to set either the environment variable
AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST set with a filename.
That file then contains the filenames or functions that should be instrumented
-(AFL_LLVM_ALLOWLIST) or should specifically NOT instrumentd (AFL_LLVM_DENYLIST).
+(AFL_LLVM_ALLOWLIST) or should specifically NOT be instrumented (AFL_LLVM_DENYLIST).
For matching, the function/filename that is being compiled must end in the
-function/filename entry contained in this the instrument file list (to avoid
+function/filename entry contained in this instrument file list (to avoid
breaking the matching when absolute paths are used during compilation).
-**NOTE:** In optimization functions might be inlined and then not match!
+**NOTE:** In builds with optimization enabled functions might be inlined and would not match!
For example if your source tree looks like this:
```
@@ -52,7 +52,7 @@ project/feature_b/b1.cpp
project/feature_b/b2.cpp
```
-and you only want to test feature_a, then create a the instrument file list file containing:
+and you only want to test feature_a, then create a instrument file list file containing:
```
feature_a/a1.cpp
feature_a/a2.cpp
@@ -69,7 +69,7 @@ exists somewhere else in the project directories.
You can also specify function names. Note that for C++ the function names
must be mangled to match!
-afl++ is intelligent to identify if an entry is a filename or a function.
+afl++ is able to identify if an entry is a filename or a function.
However if you want to be sure (and compliant to the sancov allow/blocklist
format), you can specify source file entries like this:
```
@@ -79,7 +79,7 @@ and function entries like this:
```
fun: MallocFoo
```
-Note that whitespace is ignored and comments (`# foo`) supported.
+Note that whitespace is ignored and comments (`# foo`) are supported.
## 4) UNIX-style pattern matching
You can add UNIX-style pattern matching in the the instrument file list entries.
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index efaba122..99b17430 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -246,33 +246,60 @@ static void edit_params(u32 argc, char **argv, char **envp) {
// laf
if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/split-switches-pass.so", obj_path);
+ if (lto_mode) {
+
+ cc_params[cc_par_cnt++] =
+ alloc_printf("-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
+
+ } else {
+
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] = "-load";
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("%s/split-switches-pass.so", obj_path);
+
+ }
}
if (getenv("LAF_TRANSFORM_COMPARES") ||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/compare-transform-pass.so", obj_path);
+ if (lto_mode) {
+
+ cc_params[cc_par_cnt++] = alloc_printf(
+ "-Wl,-mllvm=-load=%s/compare-transform-pass.so", obj_path);
+
+ } else {
+
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] = "-load";
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("%s/compare-transform-pass.so", obj_path);
+
+ }
}
if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/split-compares-pass.so", obj_path);
+ if (lto_mode) {
+
+ cc_params[cc_par_cnt++] =
+ alloc_printf("-Wl,-mllvm=-load=%s/split-compares-pass.so", obj_path);
+
+ } else {
+
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] = "-load";
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("%s/split-compares-pass.so", obj_path);
+
+ }
}
@@ -282,24 +309,37 @@ static void edit_params(u32 argc, char **argv, char **envp) {
unsetenv("AFL_LD_CALLER");
if (cmplog_mode) {
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/cmplog-routines-pass.so", obj_path);
+ if (lto_mode) {
- // reuse split switches from laf
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/split-switches-pass.so", obj_path);
+ cc_params[cc_par_cnt++] =
+ alloc_printf("-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path);
+ cc_params[cc_par_cnt++] =
+ alloc_printf("-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
+ cc_params[cc_par_cnt++] = alloc_printf(
+ "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path);
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
+ } else {
+
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] = "-load";
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("%s/cmplog-routines-pass.so", obj_path);
+
+ // reuse split switches from laf
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] = "-load";
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("%s/split-switches-pass.so", obj_path);
+
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] = "-load";
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
+
+ }
cc_params[cc_par_cnt++] = "-fno-inline";
@@ -312,8 +352,17 @@ static void edit_params(u32 argc, char **argv, char **envp) {
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";
+ cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_ptr);
+ cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", AFL_REAL_LD);
+#else
cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", AFL_REAL_LD);
+#endif
+
cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
+
/*
The current LTO instrim mode is not good, so we disable it
if (instrument_mode == INSTRUMENT_CFG)
@@ -321,6 +370,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
alloc_printf("-Wl,-mllvm=-load=%s/afl-llvm-lto-instrim.so",
obj_path); else
*/
+
cc_params[cc_par_cnt++] = alloc_printf(
"-Wl,-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", obj_path);
cc_params[cc_par_cnt++] = lto_flag;
@@ -329,8 +379,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (instrument_mode == INSTRUMENT_PCGUARD) {
+#if LLVM_VERSION_MAJOR > 4 || \
+ (LLVM_VERSION_MAJOR == 4 && \
+ (LLVM_VERSION_MINOR > 0 || LLVM_VERSION_PATCH >= 1))
cc_params[cc_par_cnt++] =
"-fsanitize-coverage=trace-pc-guard"; // edge coverage by default
+#else
+ FATAL("pcguard instrumentation requires llvm 4.0.1+");
+#endif
} else {
@@ -965,6 +1021,10 @@ int main(int argc, char **argv, char **envp) {
#ifdef AFL_CLANG_FLTO
SAYF(
"\nafl-clang-lto specific environment variables:\n"
+ "AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), e.g. "
+ "0x10000\n"
+ "AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
+ "functions they are in into this file\n"
"AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
"global var\n"
"AFL_LLVM_LTO_STARTID: from which ID to start counting from for a "
diff --git a/llvm_mode/afl-ld-lto.c b/llvm_mode/afl-ld-lto.c
index 1b59bb4a..771e2d0d 100644
--- a/llvm_mode/afl-ld-lto.c
+++ b/llvm_mode/afl-ld-lto.c
@@ -278,7 +278,7 @@ int main(int argc, char **argv) {
if (debug) {
- (void)getcwd(thecwd, sizeof(thecwd));
+ if (getcwd(thecwd, sizeof(thecwd)) != 0) strcpy(thecwd, ".");
SAYF(cMGN "[D] " cRST "cd \"%s\";", thecwd);
for (i = 0; i < argc; i++)
diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc
index 0b50c547..d9e63bd3 100644
--- a/llvm_mode/afl-llvm-common.cc
+++ b/llvm_mode/afl-llvm-common.cc
@@ -67,8 +67,11 @@ bool isIgnoreFunction(const llvm::Function *F) {
"__libc_csu",
"__asan",
"__msan",
+ "__cmplog",
+ "__sancov",
"msan.",
"LLVMFuzzer",
+ "__decide_deferred",
"maybe_duplicate_stderr",
"discard_output",
"close_stdout",
@@ -253,101 +256,63 @@ void initInstrumentList() {
}
-bool isInInstrumentList(llvm::Function *F) {
-
- // is this a function with code? If it is external we dont instrument it
- // anyway and cant be in the the instrument file list. Or if it is ignored.
- if (!F->size() || isIgnoreFunction(F)) return false;
-
- // if we do not have a the instrument file list return true
- if (!allowListFiles.empty() || !allowListFunctions.empty()) {
-
- if (!allowListFunctions.empty()) {
-
- std::string instFunction = F->getName().str();
-
- for (std::list<std::string>::iterator it = allowListFunctions.begin();
- it != allowListFunctions.end(); ++it) {
-
- /* We don't check for filename equality here because
- * filenames might actually be full paths. Instead we
- * check that the actual filename ends in the filename
- * specified in the list. We also allow UNIX-style pattern
- * matching */
-
- if (instFunction.length() >= it->length()) {
-
- if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
-
- if (debug)
- SAYF(cMGN "[D] " cRST
- "Function %s is in the allow function list, "
- "instrumenting ... \n",
- instFunction.c_str());
- return true;
-
- }
-
- }
-
- }
+void scanForDangerousFunctions(llvm::Module *M) {
- }
+ if (!M) return;
- if (!allowListFiles.empty()) {
+#if LLVM_VERSION_MAJOR > 3 || \
+ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 9)
- // let's try to get the filename for the function
- auto bb = &F->getEntryBlock();
- BasicBlock::iterator IP = bb->getFirstInsertionPt();
- IRBuilder<> IRB(&(*IP));
- DebugLoc Loc = IP->getDebugLoc();
+ for (GlobalIFunc &IF : M->ifuncs()) {
-#if LLVM_VERSION_MAJOR >= 4 || \
- (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
- if (Loc) {
+ StringRef ifunc_name = IF.getName();
+ Constant *r = IF.getResolver();
+ StringRef r_name = cast<Function>(r->getOperand(0))->getName();
+ if (!be_quiet)
+ fprintf(stderr,
+ "Info: Found an ifunc with name %s that points to resolver "
+ "function %s, we will not instrument this, putting it into the "
+ "block list.\n",
+ ifunc_name.str().c_str(), r_name.str().c_str());
+ denyListFunctions.push_back(r_name.str());
- DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
-
- unsigned int instLine = cDILoc->getLine();
- StringRef instFilename = cDILoc->getFilename();
+ }
- if (instFilename.str().empty()) {
+ GlobalVariable *GV = M->getNamedGlobal("llvm.global_ctors");
+ if (GV && !GV->isDeclaration() && !GV->hasLocalLinkage()) {
- /* If the original location is empty, try using the inlined location
- */
- DILocation *oDILoc = cDILoc->getInlinedAt();
- if (oDILoc) {
+ ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
- instFilename = oDILoc->getFilename();
- instLine = oDILoc->getLine();
+ if (InitList) {
- }
+ for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
- }
+ if (ConstantStruct *CS =
+ dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
- /* Continue only if we know where we actually are */
- if (!instFilename.str().empty()) {
+ if (CS->getNumOperands() >= 2) {
- for (std::list<std::string>::iterator it = allowListFiles.begin();
- it != allowListFiles.end(); ++it) {
+ if (CS->getOperand(1)->isNullValue())
+ break; // Found a null terminator, stop here.
- /* We don't check for filename equality here because
- * filenames might actually be full paths. Instead we
- * check that the actual filename ends in the filename
- * specified in the list. We also allow UNIX-style pattern
- * matching */
+ ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
+ int Priority = CI ? CI->getSExtValue() : 0;
- if (instFilename.str().length() >= it->length()) {
+ Constant *FP = CS->getOperand(1);
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
+ if (CE->isCast()) FP = CE->getOperand(0);
+ if (Function *F = dyn_cast<Function>(FP)) {
- if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
- 0) {
+ if (!F->isDeclaration() &&
+ strncmp(F->getName().str().c_str(), "__afl", 5) != 0) {
- if (debug)
- SAYF(cMGN "[D] " cRST
- "Function %s is in the allowlist (%s), "
- "instrumenting ... \n",
- F->getName().str().c_str(), instFilename.str().c_str());
- return true;
+ if (!be_quiet)
+ fprintf(stderr,
+ "Info: Found constructor function %s with prio "
+ "%u, we will not instrument this, putting it into a "
+ "block list.\n",
+ F->getName().str().c_str(), Priority);
+ denyListFunctions.push_back(F->getName().str());
}
@@ -361,63 +326,67 @@ bool isInInstrumentList(llvm::Function *F) {
}
-#else
- if (!Loc.isUnknown()) {
+ }
- DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
+#endif
- unsigned int instLine = cDILoc.getLineNumber();
- StringRef instFilename = cDILoc.getFilename();
+}
- (void)instLine;
- /* Continue only if we know where we actually are */
- if (!instFilename.str().empty()) {
+static std::string getSourceName(llvm::Function *F) {
- for (std::list<std::string>::iterator it = allowListFiles.begin();
- it != allowListFiles.end(); ++it) {
+ // let's try to get the filename for the function
+ auto bb = &F->getEntryBlock();
+ BasicBlock::iterator IP = bb->getFirstInsertionPt();
+ IRBuilder<> IRB(&(*IP));
+ DebugLoc Loc = IP->getDebugLoc();
- /* We don't check for filename equality here because
- * filenames might actually be full paths. Instead we
- * check that the actual filename ends in the filename
- * specified in the list. We also allow UNIX-style pattern
- * matching */
+#if LLVM_VERSION_MAJOR >= 4 || \
+ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
+ if (Loc) {
- if (instFilename.str().length() >= it->length()) {
+ DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
- if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
- 0) {
+ StringRef instFilename = cDILoc->getFilename();
- return true;
+ if (instFilename.str().empty()) {
- }
+ /* If the original location is empty, try using the inlined location
+ */
+ DILocation *oDILoc = cDILoc->getInlinedAt();
+ if (oDILoc) { instFilename = oDILoc->getFilename(); }
- }
+ }
- }
+ return instFilename.str();
- }
+ }
- }
+#else
+ if (!Loc.isUnknown()) {
- }
+ DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
+
+ StringRef instFilename = cDILoc.getFilename();
+
+ /* Continue only if we know where we actually are */
+ return instFilename.str();
+
+ }
#endif
- else {
- // we could not find out the location. in this case we say it is not
- // in the the instrument file list
- if (!be_quiet)
- WARNF(
- "No debug information found for function %s, will not be "
- "instrumented (recompile with -g -O[1-3]).",
- F->getName().str().c_str());
- return false;
+ return std::string("");
- }
+}
- return false;
+bool isInInstrumentList(llvm::Function *F) {
- }
+ bool return_default = true;
+
+ // is this a function with code? If it is external we don't instrument it
+ // anyway and it can't be in the instrument file list. Or if it is it is
+ // ignored.
+ if (!F->size() || isIgnoreFunction(F)) return false;
if (!denyListFiles.empty() || !denyListFunctions.empty()) {
@@ -455,62 +424,75 @@ bool isInInstrumentList(llvm::Function *F) {
if (!denyListFiles.empty()) {
- // let's try to get the filename for the function
- auto bb = &F->getEntryBlock();
- BasicBlock::iterator IP = bb->getFirstInsertionPt();
- IRBuilder<> IRB(&(*IP));
- DebugLoc Loc = IP->getDebugLoc();
+ std::string source_file = getSourceName(F);
-#if LLVM_VERSION_MAJOR >= 4 || \
- (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
- if (Loc) {
+ if (!source_file.empty()) {
- DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+ for (std::list<std::string>::iterator it = denyListFiles.begin();
+ it != denyListFiles.end(); ++it) {
- unsigned int instLine = cDILoc->getLine();
- StringRef instFilename = cDILoc->getFilename();
+ /* We don't check for filename equality here because
+ * filenames might actually be full paths. Instead we
+ * check that the actual filename ends in the filename
+ * specified in the list. We also allow UNIX-style pattern
+ * matching */
- if (instFilename.str().empty()) {
+ if (source_file.length() >= it->length()) {
- /* If the original location is empty, try using the inlined location
- */
- DILocation *oDILoc = cDILoc->getInlinedAt();
- if (oDILoc) {
+ if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
- instFilename = oDILoc->getFilename();
- instLine = oDILoc->getLine();
+ return false;
+
+ }
}
}
- /* Continue only if we know where we actually are */
- if (!instFilename.str().empty()) {
+ } else {
- for (std::list<std::string>::iterator it = denyListFiles.begin();
- it != denyListFiles.end(); ++it) {
+ // we could not find out the location. in this case we say it is not
+ // in the instrument file list
+ if (!be_quiet)
+ WARNF(
+ "No debug information found for function %s, will be "
+ "instrumented (recompile with -g -O[1-3]).",
+ F->getName().str().c_str());
- /* We don't check for filename equality here because
- * filenames might actually be full paths. Instead we
- * check that the actual filename ends in the filename
- * specified in the list. We also allow UNIX-style pattern
- * matching */
+ }
- if (instFilename.str().length() >= it->length()) {
+ }
- if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
- 0) {
+ }
- if (debug)
- SAYF(cMGN "[D] " cRST
- "Function %s is in the denylist (%s), not "
- "instrumenting ... \n",
- F->getName().str().c_str(), instFilename.str().c_str());
- return false;
+ // if we do not have a instrument file list return true
+ if (!allowListFiles.empty() || !allowListFunctions.empty()) {
- }
+ return_default = false;
- }
+ if (!allowListFunctions.empty()) {
+
+ std::string instFunction = F->getName().str();
+
+ for (std::list<std::string>::iterator it = allowListFunctions.begin();
+ it != allowListFunctions.end(); ++it) {
+
+ /* We don't check for filename equality here because
+ * filenames might actually be full paths. Instead we
+ * check that the actual filename ends in the filename
+ * specified in the list. We also allow UNIX-style pattern
+ * matching */
+
+ if (instFunction.length() >= it->length()) {
+
+ if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) {
+
+ if (debug)
+ SAYF(cMGN "[D] " cRST
+ "Function %s is in the allow function list, "
+ "instrumenting ... \n",
+ instFunction.c_str());
+ return true;
}
@@ -520,35 +502,31 @@ bool isInInstrumentList(llvm::Function *F) {
}
-#else
- if (!Loc.isUnknown()) {
-
- DILocation cDILoc(Loc.getAsMDNode(F->getContext()));
-
- unsigned int instLine = cDILoc.getLineNumber();
- StringRef instFilename = cDILoc.getFilename();
+ if (!allowListFiles.empty()) {
- (void)instLine;
- /* Continue only if we know where we actually are */
- if (!instFilename.str().empty()) {
+ std::string source_file = getSourceName(F);
- for (std::list<std::string>::iterator it = denyListFiles.begin();
- it != denyListFiles.end(); ++it) {
+ if (!source_file.empty()) {
- /* We don't check for filename equality here because
- * filenames might actually be full paths. Instead we
- * check that the actual filename ends in the filename
- * specified in the list. We also allow UNIX-style pattern
- * matching */
+ for (std::list<std::string>::iterator it = allowListFiles.begin();
+ it != allowListFiles.end(); ++it) {
- if (instFilename.str().length() >= it->length()) {
+ /* We don't check for filename equality here because
+ * filenames might actually be full paths. Instead we
+ * check that the actual filename ends in the filename
+ * specified in the list. We also allow UNIX-style pattern
+ * matching */
- if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) ==
- 0) {
+ if (source_file.length() >= it->length()) {
- return false;
+ if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) {
- }
+ if (debug)
+ SAYF(cMGN "[D] " cRST
+ "Function %s is in the allowlist (%s), "
+ "instrumenting ... \n",
+ F->getName().str().c_str(), source_file.c_str());
+ return true;
}
@@ -556,29 +534,24 @@ bool isInInstrumentList(llvm::Function *F) {
}
- }
+ } else {
- }
+ // we could not find out the location. In this case we say it is not
+ // in the instrument file list
+ if (!be_quiet)
+ WARNF(
+ "No debug information found for function %s, will not be "
+ "instrumented (recompile with -g -O[1-3]).",
+ F->getName().str().c_str());
+ return false;
-#endif
- else {
-
- // we could not find out the location. in this case we say it is not
- // in the the instrument file list
- if (!be_quiet)
- WARNF(
- "No debug information found for function %s, will be "
- "instrumented (recompile with -g -O[1-3]).",
- F->getName().str().c_str());
- return true;
+ }
}
- return true;
-
}
- return true; // not reached
+ return return_default;
}
diff --git a/llvm_mode/afl-llvm-common.h b/llvm_mode/afl-llvm-common.h
index 5b96be43..a1561d9c 100644
--- a/llvm_mode/afl-llvm-common.h
+++ b/llvm_mode/afl-llvm-common.h
@@ -37,6 +37,7 @@ bool isIgnoreFunction(const llvm::Function *F);
void initInstrumentList();
bool isInInstrumentList(llvm::Function *F);
unsigned long long int calculateCollisions(uint32_t edges);
+void scanForDangerousFunctions(llvm::Module *M);
#ifndef IS_EXTERN
#define IS_EXTERN
diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
index fd8e48a7..300951fb 100644
--- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
@@ -103,6 +103,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
std::vector<std::string> dictionary;
std::vector<CallInst *> calls;
DenseMap<Value *, std::string *> valueMap;
+ std::vector<BasicBlock *> BlockList;
char * ptr;
FILE * documentFile = NULL;
@@ -150,7 +151,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
map_addr = 0;
- } else if (map_addr == 0) {
+ } else if (getenv("AFL_LLVM_MAP_DYNAMIC")) {
FATAL(
"AFL_LLVM_MAP_ADDR and AFL_LLVM_MAP_DYNAMIC cannot be used together");
@@ -217,79 +218,9 @@ bool AFLLTOPass::runOnModule(Module &M) {
}
- */
-
- std::vector<std::string> module_block_list;
-
- if (map_addr) {
-
- for (GlobalIFunc &IF : M.ifuncs()) {
-
- StringRef ifunc_name = IF.getName();
- Constant *r = IF.getResolver();
- StringRef r_name = cast<Function>(r->getOperand(0))->getName();
- if (!be_quiet)
- fprintf(stderr,
- "Warning: Found an ifunc with name %s that points to resolver "
- "function %s, we cannot instrument this, putting it into a "
- "block list.\n",
- ifunc_name.str().c_str(), r_name.str().c_str());
- module_block_list.push_back(r_name.str());
-
- }
-
- GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors");
- if (GV && !GV->isDeclaration() && !GV->hasLocalLinkage()) {
-
- ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
-
- if (InitList) {
-
- for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
-
- if (ConstantStruct *CS =
- dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
-
- if (CS->getNumOperands() >= 2) {
-
- if (CS->getOperand(1)->isNullValue())
- break; // Found a null terminator, stop here.
-
- ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
- int Priority = CI ? CI->getSExtValue() : 0;
-
- Constant *FP = CS->getOperand(1);
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
- if (CE->isCast()) FP = CE->getOperand(0);
- if (Function *F = dyn_cast<Function>(FP)) {
-
- if (!F->isDeclaration() &&
- strncmp(F->getName().str().c_str(), "__afl", 5) != 0 &&
- Priority <= 5) {
-
- if (!be_quiet)
- fprintf(stderr,
- "Warning: Found constructor function %s with prio "
- "%u, we cannot instrument this, putting it into a "
- "block list.\n",
- F->getName().str().c_str(), Priority);
- module_block_list.push_back(F->getName().str());
-
- }
-
- }
-
- }
-
- }
-
- }
-
- }
-
- }
+ */
- }
+ scanForDangerousFunctions(&M);
/* Instrument all the things! */
@@ -307,26 +238,6 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (F.size() < function_minimum_size) continue;
if (isIgnoreFunction(&F)) continue;
- if (module_block_list.size()) {
-
- for (auto bname : module_block_list) {
-
- std::string fname = F.getName().str();
-
- if (fname.compare(bname) == 0) {
-
- if (!be_quiet)
- WARNF(
- "Skipping instrumentation of dangerous early running function "
- "%s",
- fname.c_str());
-
- }
-
- }
-
- }
-
// the instrument file list check
AttributeList Attrs = F.getAttributes();
if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
@@ -380,14 +291,14 @@ bool AFLLTOPass::runOnModule(Module &M) {
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;
+ bool isStrcmp = true;
+ bool isMemcmp = true;
+ bool isStrncmp = true;
+ bool isStrcasecmp = true;
+ bool isStrncasecmp = true;
+ bool isIntMemcpy = true;
+ bool addedNull = false;
+ size_t optLen = 0;
Function *Callee = callInst->getCalledFunction();
if (!Callee) continue;
@@ -400,6 +311,24 @@ bool AFLLTOPass::runOnModule(Module &M) {
isStrncasecmp &= !FuncName.compare("strncasecmp");
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
+ /* we do something different here, putting this BB and the
+ successors in a block map */
+ if (!FuncName.compare("__afl_persistent_loop")) {
+
+ BlockList.push_back(&BB);
+ /*
+ for (succ_iterator SI = succ_begin(&BB), SE =
+ succ_end(&BB); SI != SE; ++SI) {
+
+ BasicBlock *succ = *SI;
+ BlockList.push_back(succ);
+
+ }
+
+ */
+
+ }
+
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
!isStrncasecmp && !isIntMemcpy)
continue;
@@ -617,18 +546,27 @@ bool AFLLTOPass::runOnModule(Module &M) {
// add null byte if this is a string compare function and a null
// was not already added
- if (addedNull == false && !isMemcmp) {
+ if (!isMemcmp) {
+
+ if (addedNull == false) {
- thestring.append("\0", 1); // add null byte
- optLen++;
+ thestring.append("\0", 1); // add null byte
+ optLen++;
+
+ }
+
+ // ensure we do not have garbage
+ size_t offset = thestring.find('\0', 0);
+ if (offset + 1 < optLen) optLen = offset + 1;
+ thestring = thestring.substr(0, optLen);
}
if (!be_quiet) {
std::string outstring;
- fprintf(stderr, "%s: length %u/%u \"", FuncName.c_str(), optLen,
- (unsigned int)thestring.length());
+ fprintf(stderr, "%s: length %zu/%zu \"", FuncName.c_str(), optLen,
+ thestring.length());
for (uint8_t i = 0; i < thestring.length(); i++) {
uint8_t c = thestring[i];
@@ -686,13 +624,35 @@ bool AFLLTOPass::runOnModule(Module &M) {
do {
--i;
- BasicBlock * newBB;
+ BasicBlock * newBB = NULL;
BasicBlock * origBB = &(*InsBlocks[i]);
std::vector<BasicBlock *> Successors;
Instruction * TI = origBB->getTerminator();
uint32_t fs = origBB->getParent()->size();
uint32_t countto;
+ if (BlockList.size()) {
+
+ int skip = 0;
+ for (uint32_t k = 0; k < BlockList.size(); k++) {
+
+ if (origBB == BlockList[k]) {
+
+ if (debug)
+ fprintf(
+ stderr,
+ "DEBUG: Function %s skipping BB with/after __afl_loop\n",
+ F.getName().str().c_str());
+ skip = 1;
+
+ }
+
+ }
+
+ if (skip) continue;
+
+ }
+
for (succ_iterator SI = succ_begin(origBB), SE = succ_end(origBB);
SI != SE; ++SI) {
diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc
index 618abe48..a791d720 100644
--- a/llvm_mode/afl-llvm-pass.so.cc
+++ b/llvm_mode/afl-llvm-pass.so.cc
@@ -112,7 +112,7 @@ uint64_t PowerOf2Ceil(unsigned in) {
#endif
/* #if LLVM_VERSION_STRING >= "4.0.1" */
-#if LLVM_VERSION_MAJOR >= 4 || \
+#if LLVM_VERSION_MAJOR > 4 || \
(LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
#define AFL_HAVE_VECTOR_INTRINSICS 1
#endif
@@ -194,7 +194,7 @@ bool AFLCoverage::runOnModule(Module &M) {
#ifdef AFL_HAVE_VECTOR_INTRINSICS
/* Decide previous location vector size (must be a power of two) */
- VectorType *PrevLocTy;
+ VectorType *PrevLocTy = NULL;
if (ngram_size_str)
if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
@@ -236,7 +236,7 @@ bool AFLCoverage::runOnModule(Module &M) {
new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
GlobalVariable *AFLPrevLoc;
- GlobalVariable *AFLContext;
+ GlobalVariable *AFLContext = NULL;
if (ctx_str)
#ifdef __ANDROID__
@@ -292,11 +292,12 @@ bool AFLCoverage::runOnModule(Module &M) {
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
- LoadInst *PrevCtx; // CTX sensitive coverage
+ LoadInst *PrevCtx = NULL; // CTX sensitive coverage
/* Instrument all the things! */
int inst_blocks = 0;
+ scanForDangerousFunctions(&M);
for (auto &F : M) {
diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c
index a567593e..d00fd26f 100644
--- a/llvm_mode/afl-llvm-rt.o.c
+++ b/llvm_mode/afl-llvm-rt.o.c
@@ -35,6 +35,8 @@
#include <string.h>
#include <assert.h>
#include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
#include <errno.h>
#include <sys/mman.h>
@@ -52,8 +54,6 @@
Basically, we need to make sure that the forkserver is initialized after
the LLVM-generated runtime initialization pass, not before. */
-#define CONST_PRIO 5
-
#ifndef MAP_FIXED_NOREPLACE
#ifdef MAP_EXCL
#define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
@@ -62,6 +62,8 @@
#endif
#endif
+#define CTOR_PRIO 3
+
#include <sys/mman.h>
#include <fcntl.h>
@@ -75,11 +77,7 @@
#define MAP_INITIAL_SIZE MAP_SIZE
#endif
-#ifdef AFL_REAL_LD
-u8 __afl_area_initial[MAP_INITIAL_SIZE];
-#else
-u8 __afl_area_initial[MAP_SIZE];
-#endif
+u8 __afl_area_initial[MAP_INITIAL_SIZE];
u8 * __afl_area_ptr = __afl_area_initial;
u8 * __afl_dictionary;
u8 * __afl_fuzz_ptr;
@@ -109,6 +107,10 @@ struct cmp_map *__afl_cmp_map;
static u8 is_persistent;
+/* Are we in sancov mode? */
+
+static u8 _is_sancov;
+
/* Error reporting to forkserver controller */
void send_forkserver_error(int error) {
@@ -186,7 +188,7 @@ static void __afl_map_shm_fuzz() {
static void __afl_map_shm(void) {
// we we are not running in afl ensure the map exists
- if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
+ if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_initial; }
char *id_str = getenv(SHM_ENV_VAR);
@@ -194,8 +196,8 @@ static void __afl_map_shm(void) {
if (__afl_final_loc % 8)
__afl_final_loc = (((__afl_final_loc + 7) >> 3) << 3);
-
__afl_map_size = __afl_final_loc;
+
if (__afl_final_loc > MAP_SIZE) {
char *ptr;
@@ -205,10 +207,12 @@ static void __afl_map_shm(void) {
if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) {
- fprintf(stderr,
- "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to "
- "be able to run this instrumented program!\n",
- __afl_final_loc);
+ if (!getenv("AFL_QUIET"))
+ fprintf(stderr,
+ "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u "
+ "to be able to run this instrumented program!\n",
+ __afl_final_loc);
+
if (id_str) {
send_forkserver_error(FS_ERROR_MAP_SIZE);
@@ -218,10 +222,11 @@ static void __afl_map_shm(void) {
} else {
- fprintf(stderr,
- "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to "
- "be able to run this instrumented program!\n",
- __afl_final_loc);
+ if (!getenv("AFL_QUIET"))
+ fprintf(stderr,
+ "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u "
+ "to be able to run this instrumented program!\n",
+ __afl_final_loc);
}
@@ -237,13 +242,25 @@ static void __afl_map_shm(void) {
if (getenv("AFL_DEBUG"))
fprintf(stderr,
- "DEBUG: id_str %s, __afl_map_addr 0x%llx, MAP_SIZE %u, "
- "__afl_final_loc %u, max_size_forkserver %u/0x%x\n",
- id_str == NULL ? "<null>" : id_str, __afl_map_addr, MAP_SIZE,
- __afl_final_loc, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
+ "DEBUG: id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
+ "__afl_map_addr 0x%llx, MAP_SIZE %u, __afl_final_loc %u, "
+ "max_size_forkserver %u/0x%x\n",
+ id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
+ __afl_area_initial, __afl_map_addr, MAP_SIZE, __afl_final_loc,
+ FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
if (id_str) {
+ if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) {
+
+ if (__afl_map_addr)
+ munmap((void *)__afl_map_addr, __afl_final_loc);
+ else
+ free(__afl_area_ptr);
+ __afl_area_ptr = __afl_area_initial;
+
+ }
+
#ifdef USEMMAP
const char * shm_file_path = id_str;
int shm_fd = -1;
@@ -312,11 +329,14 @@ static void __afl_map_shm(void) {
__afl_area_ptr[0] = 1;
- } else if (__afl_map_addr) {
+ } else if ((!__afl_area_ptr || __afl_area_ptr == __afl_area_initial) &&
+
+ __afl_map_addr) {
__afl_area_ptr =
mmap((void *)__afl_map_addr, __afl_map_size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+
if (__afl_area_ptr == MAP_FAILED) {
fprintf(stderr, "can not aquire mmap for address %p\n",
@@ -325,6 +345,14 @@ static void __afl_map_shm(void) {
}
+ } else if (_is_sancov && __afl_area_ptr != __afl_area_initial) {
+
+ free(__afl_area_ptr);
+ __afl_area_ptr = NULL;
+ if (__afl_final_loc > MAP_INITIAL_SIZE)
+ __afl_area_ptr = malloc(__afl_final_loc);
+ if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
+
}
id_str = getenv(CMPLOG_SHM_ENV_VAR);
@@ -842,9 +870,22 @@ void __afl_manual_init(void) {
static u8 init_done;
+ if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) {
+
+ init_done = 1;
+ is_persistent = 0;
+ __afl_sharedmem_fuzzing = 0;
+ if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_initial;
+
+ if (getenv("AFL_DEBUG"))
+ fprintf(stderr,
+ "DEBUG: disabled instrumentation because of "
+ "AFL_DISABLE_LLVM_INSTRUMENTATION\n");
+
+ }
+
if (!init_done) {
- __afl_map_shm();
__afl_start_forkserver();
init_done = 1;
@@ -852,11 +893,11 @@ void __afl_manual_init(void) {
}
-/* Proper initialization routine. */
+/* Initialization of the forkserver - latest possible */
-__attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
+__attribute__((constructor())) void __afl_auto_init(void) {
- is_persistent = !!getenv(PERSIST_ENV_VAR);
+ if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
if (getenv(DEFER_ENV_VAR)) return;
@@ -864,6 +905,57 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
}
+/* Initialization of the shmem - earliest possible because of LTO fixed mem. */
+
+__attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) {
+
+ is_persistent = !!getenv(PERSIST_ENV_VAR);
+
+ if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+
+ __afl_map_shm();
+
+}
+
+/* preset __afl_area_ptr #2 */
+
+__attribute__((constructor(1))) void __afl_auto_second(void) {
+
+ if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+ u8 *ptr;
+
+ if (__afl_final_loc) {
+
+ if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial)
+ free(__afl_area_ptr);
+
+ if (__afl_map_addr)
+ ptr = (u8 *)mmap((void *)__afl_map_addr, __afl_final_loc,
+ PROT_READ | PROT_WRITE,
+ MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ else
+ ptr = (u8 *)malloc(__afl_final_loc);
+
+ if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
+
+ }
+
+}
+
+/* preset __afl_area_ptr #1 - at constructor level 0 global variables have
+ not been set */
+
+__attribute__((constructor(0))) void __afl_auto_first(void) {
+
+ if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+ u8 *ptr;
+
+ ptr = (u8 *)malloc(1024000);
+
+ if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
+
+}
+
/* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard.
It remains non-operational in the traditional, plugin-backed LLVM mode.
For more info about 'trace-pc-guard', see llvm_mode/README.md.
@@ -874,7 +966,7 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
// For stability analysis, if you want to know to which function unstable
- // edge IDs belong to - uncomment, recompile+install llvm_mode, recompile
+ // edge IDs belong - uncomment, recompile+install llvm_mode, recompile
// the target. libunwind and libbacktrace are better solutions.
// Set AFL_DEBUG_CHILD_OUTPUT=1 and run afl-fuzz with 2>file to capture
// the backtrace output
@@ -912,7 +1004,8 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
#else
- __afl_area_ptr[*guard] = __afl_area_ptr[*guard] + 1 + (__afl_area_ptr[*guard] == 255 ? 1 : 0);
+ __afl_area_ptr[*guard] =
+ __afl_area_ptr[*guard] + 1 + (__afl_area_ptr[*guard] == 255 ? 1 : 0);
#endif
@@ -927,6 +1020,8 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
u32 inst_ratio = 100;
char *x;
+ _is_sancov = 1;
+
if (getenv("AFL_DEBUG")) {
fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p\n",
diff --git a/llvm_mode/cmplog-instructions-pass.cc b/llvm_mode/cmplog-instructions-pass.cc
index 7c48d906..d5de3dbb 100644
--- a/llvm_mode/cmplog-instructions-pass.cc
+++ b/llvm_mode/cmplog-instructions-pass.cc
@@ -284,3 +284,9 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPass(
static RegisterStandardPasses RegisterCmpLogInstructionsPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass);
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO(
+ PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
+ registerCmpLogInstructionsPass);
+#endif
+
diff --git a/llvm_mode/cmplog-routines-pass.cc b/llvm_mode/cmplog-routines-pass.cc
index a0f8f64f..c44f38c4 100644
--- a/llvm_mode/cmplog-routines-pass.cc
+++ b/llvm_mode/cmplog-routines-pass.cc
@@ -204,3 +204,9 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPass(
static RegisterStandardPasses RegisterCmpLogRoutinesPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogRoutinesPass);
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO(
+ PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
+ registerCmpLogRoutinesPass);
+#endif
+
diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc
index bed3597a..acdd0f3b 100644
--- a/llvm_mode/compare-transform-pass.so.cc
+++ b/llvm_mode/compare-transform-pass.so.cc
@@ -137,7 +137,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
bool isStrcasecmp = processStrcasecmp;
bool isStrncasecmp = processStrncasecmp;
bool isIntMemcpy = true;
- bool indirect = false;
Function *Callee = callInst->getCalledFunction();
if (!Callee) continue;
@@ -264,8 +263,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
}
- if ((HasStr1 || HasStr2)) indirect = true;
-
}
if (isIntMemcpy) continue;
@@ -278,7 +275,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
Str1 = StringRef(*val);
HasStr1 = true;
- indirect = true;
// fprintf(stderr, "loaded1 %s\n", Str1.str().c_str());
} else {
@@ -288,7 +284,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
Str2 = StringRef(*val);
HasStr2 = true;
- indirect = true;
// fprintf(stderr, "loaded2 %s\n", Str2.str().c_str());
}
@@ -585,3 +580,8 @@ static RegisterStandardPasses RegisterCompTransPass(
static RegisterStandardPasses RegisterCompTransPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass);
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterCompTransPassLTO(
+ PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass);
+#endif
+
diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc
index 3630bd8c..617b55de 100644
--- a/llvm_mode/split-compares-pass.so.cc
+++ b/llvm_mode/split-compares-pass.so.cc
@@ -1342,3 +1342,9 @@ static RegisterStandardPasses RegisterSplitComparesPass(
static RegisterStandardPasses RegisterSplitComparesTransPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass);
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterSplitComparesTransPassLTO(
+ PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
+ registerSplitComparesPass);
+#endif
+
diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc
index f025df77..a79d4114 100644
--- a/llvm_mode/split-switches-pass.so.cc
+++ b/llvm_mode/split-switches-pass.so.cc
@@ -439,3 +439,9 @@ static RegisterStandardPasses RegisterSplitSwitchesTransPass(
static RegisterStandardPasses RegisterSplitSwitchesTransPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass);
+#if LLVM_VERSION_MAJOR >= 11
+static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO(
+ PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
+ registerSplitSwitchesTransPass);
+#endif
+