LTO: make dynamic map the default
MODIFY
docs/Changelog.md
docs/Changelog.md
@@ -28,6 +28,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
sancov, and also supports function matching!
- fixes for laf-intel float splitting (thanks to mark-griffin for
reporting)
+ - LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR
+ for a fixed map address (eg. 0x10000)
- LTO: autodictionary mode is a default
- LTO: instrim instrumentation disabled, only classic support used
as it is always better

MODIFY
llvm_mode/README.lto.md
llvm_mode/README.lto.md
@@ -17,9 +17,6 @@ This version requires a current llvm 11+ compiled from the github master.
5. If any problems arise be sure to set `AR=llvm-ar RANLIB=llvm-ranlib`.
Some targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`.
-6. If a target uses _init functions or early constructors then additionally
- set `AFL_LLVM_MAP_DYNAMIC=1` as your target will crash otherwise!
-
## Introduction and problem description
A big issue with how afl/afl++ works is that the basic block IDs that are
@@ -128,14 +125,14 @@ on start. This improves coverage statistically by 5-10% :)
## Fixed memory map
-To speed up fuzzing, the shared memory map is hard set to a specific address,
-by default 0x10000. In most cases this will work without any problems.
+To speed up fuzzing, it is possible to set a fixed shared memory map.
+Recommened is the value 0x10000.
+In most cases this will work without any problems. However if a target uses
+early constructors, ifuncs or a deferred forkserver this can crash the target.
On unusual operating systems/processors/kernels or weird libraries this might
fail so to change the fixed address at compile time set
AFL_LLVM_MAP_ADDR with a better value (a value of 0 or empty sets the map address
to be dynamic - the original afl way, which is slower).
-AFL_LLVM_MAP_DYNAMIC can be set so the shared memory address is dynamic (which
-is safer but also slower).
## Document edge IDs
@@ -262,15 +259,6 @@ If this succeeeds then there is an issue with afl-clang-lto. Please report at
Even some targets where clang-12 fails can be build if the fail is just in
`./configure`, see `Solving difficult targets` above.
-### Target crashes immediately
-
-If the target is using early constructors (priority values smaller than 6)
-or have their own _init/.init functions and these are instrumented then the
-target will likely crash when started. This can be avoided by compiling with
-`AFL_LLVM_MAP_DYNAMIC=1` .
-
-This can e.g. happen with OpenSSL.
-
## History
This was originally envisioned by hexcoder- in Summer 2019, however we saw no

MODIFY
llvm_mode/afl-llvm-lto-instrumentation.so.cc
llvm_mode/afl-llvm-lto-instrumentation.so.cc
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Pass.h"
+#include "llvm/IR/Constants.h"
#include "afl-llvm-common.h"
@@ -135,7 +136,10 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (getenv("AFL_LLVM_LTO_AUTODICTIONARY")) autodictionary = 1;
- if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0;
+ // we make this the default as the fixed map has problems with
+ // defered forkserver, early constructors, ifuncs and maybe more
+ /*if (getenv("AFL_LLVM_MAP_DYNAMIC"))*/
+ map_addr = 0;
if (getenv("AFL_LLVM_SKIPSINGLEBLOCK")) function_minimum_size = 2;
@@ -196,7 +200,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
- /* This dumps all inialized global strings - might be useful in the future
+ // This dumps all inialized global strings - might be useful in the future
+ /*
for (auto G=M.getGlobalList().begin(); G!=M.getGlobalList().end(); G++) {
GlobalVariable &GV=*G;
@@ -214,14 +219,32 @@ bool AFLLTOPass::runOnModule(Module &M) {
*/
+ if (map_addr)
+ for (GlobalIFunc &IF : M.ifuncs()) {
+
+ // No clue how to follow these up and find the resolver function.
+ // If we would know that resolver function name we could just skip
+ // instrumenting it and everything would be fine :-(
+ // StringRef ifunc_name = IF.getName();
+ // Constant *r = IF.getResolver();
+ FATAL(
+ "Target uses ifunc attribute, dynamic map cannot be used, remove "
+ "AFL_LLVM_MAP_DYNAMIC");
+
+ }
+
/* Instrument all the things! */
int inst_blocks = 0;
for (auto &F : M) {
- // fprintf(stderr, "DEBUG: Module %s Function %s\n",
- // M.getName().str().c_str(), F.getName().str().c_str());
+ /*For debugging
+ AttributeSet X = F.getAttributes().getFnAttributes();
+ fprintf(stderr, "DEBUG: Module %s Function %s attributes %u\n",
+ M.getName().str().c_str(), F.getName().str().c_str(),
+ X.getNumAttributes());
+ */
if (F.size() < function_minimum_size) continue;
if (isIgnoreFunction(&F)) continue;

MODIFY
src/afl-forkserver.c
src/afl-forkserver.c
@@ -293,8 +293,8 @@ static void report_error_and_exit(int error) {
FATAL(
"the fuzzing target reports that hardcoded map address might be the "
"reason the mmap of the shared memory failed. Solution: recompile "
- "the target with either afl-clang-lto and the environment variable "
- "AFL_LLVM_MAP_DYNAMIC set or recompile with afl-clang-fast.");
+ "the target with either afl-clang-lto and do not set "
+ "AFL_LLVM_MAP_ADDR or recompile with afl-clang-fast.");
break;
case FS_ERROR_SHM_OPEN:
FATAL("the fuzzing target reports that the shm_open() call failed.");
@@ -828,8 +828,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
SAYF("\n" cLRD "[-] " cRST
"Hmm, looks like the target binary terminated before we could"
" complete a handshake with the injected code.\n"
- "If the target was compiled with afl-clang-lto then recompiling with"
- " AFL_LLVM_MAP_DYNAMIC might solve your problem.\n"
+ "If the target was compiled with afl-clang-lto and AFL_LLVM_MAP_ADDR"
+ " then recompiling without this parameter.\n"
"Otherwise there is a horrible bug in the fuzzer.\n"
"Poke <afl-users@googlegroups.com> for troubleshooting tips.\n");
@@ -860,9 +860,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - the target was compiled with afl-clang-lto and a constructor "
"was\n"
- " instrumented, recompiling with AFL_LLVM_MAP_DYNAMIC might solve "
- "your\n"
- " problem\n\n"
+ " instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
+ "your problem\n\n"
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"

LTO: make dynamic map the default