mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-17 04:18:06 +00:00
LTO: apply laf-intel+redqueen/cmplog at link time
This commit is contained in:
@ -97,7 +97,13 @@ ifneq "$(shell uname -m)" "x86_64"
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
|
ifdef DEBUG
|
||||||
|
$(info Compiling DEBUG version of binaries)
|
||||||
|
CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror
|
||||||
|
else
|
||||||
|
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
|
||||||
|
endif
|
||||||
|
|
||||||
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
|
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
|
||||||
-I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
|
-I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
|
||||||
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
|
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
|
||||||
@ -305,6 +311,7 @@ help:
|
|||||||
@echo "=========================================="
|
@echo "=========================================="
|
||||||
@echo STATIC - compile AFL++ static
|
@echo STATIC - compile AFL++ static
|
||||||
@echo ASAN_BUILD - compiles with memory sanitizer for debug purposes
|
@echo ASAN_BUILD - compiles with memory sanitizer for debug purposes
|
||||||
|
@echo DEBUG - no optimization, -ggdb3, all warnings and -Werror
|
||||||
@echo PROFILING - compile afl-fuzz with profiling information
|
@echo PROFILING - compile afl-fuzz with profiling information
|
||||||
@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
|
@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
|
||||||
@echo "=========================================="
|
@echo "=========================================="
|
||||||
|
27
README.md
27
README.md
@ -178,6 +178,7 @@ These build options exist:
|
|||||||
|
|
||||||
* STATIC - compile AFL++ static
|
* STATIC - compile AFL++ static
|
||||||
* ASAN_BUILD - compiles with memory sanitizer for debug purposes
|
* ASAN_BUILD - compiles with memory sanitizer for debug purposes
|
||||||
|
* DEBUG - no optimization, -ggdb3, all warnings and -Werror
|
||||||
* PROFILING - compile with profiling information (gprof)
|
* PROFILING - compile with profiling information (gprof)
|
||||||
* NO_PYTHON - disable python support
|
* NO_PYTHON - disable python support
|
||||||
* AFL_NO_X86 - if compiling on non-intel/amd platforms
|
* AFL_NO_X86 - if compiling on non-intel/amd platforms
|
||||||
@ -509,8 +510,8 @@ fuzz your target.
|
|||||||
|
|
||||||
On the same machine - due to the design of how afl++ works - there is a maximum
|
On the same machine - due to the design of how afl++ works - there is a maximum
|
||||||
number of CPU cores/threads that are useful, use more and the overall performance
|
number of CPU cores/threads that are useful, use more and the overall performance
|
||||||
degrades instead. This value depends on the target and the limit is between 48
|
degrades instead. This value depends on the target, and the limit is between 32
|
||||||
and 96 cores/threads per machine.
|
and 64 cores/threads per machine.
|
||||||
|
|
||||||
There should be one main fuzzer (`-M main` option) and as many secondary
|
There should be one main fuzzer (`-M main` option) and as many secondary
|
||||||
fuzzers (eg `-S variant1`) as you have cores that you use.
|
fuzzers (eg `-S variant1`) as you have cores that you use.
|
||||||
@ -562,11 +563,18 @@ To have only the summary use the `-s` switch e.g.: `afl-whatsup -s output/`
|
|||||||
The `paths found` value is a bad indicator how good the coverage is.
|
The `paths found` value is a bad indicator how good the coverage is.
|
||||||
|
|
||||||
A better indicator - if you use default llvm instrumentation with at least
|
A better indicator - if you use default llvm instrumentation with at least
|
||||||
version 9 - to use `afl-showmap` on the target with all inputs of the
|
version 9 - is to use `afl-showmap` with the collect coverage option `-C` on
|
||||||
queue/ directory one after another and collecting the found edge IDs (`-o N.out`),
|
the output directory:
|
||||||
removing the counters of the edge IDs, making them unique - and there you have
|
```
|
||||||
the total number of found instrumented edges.
|
$ afl-showmap -C -i out -o /dev/null -- ./target -params @@
|
||||||
|
...
|
||||||
|
[*] Using SHARED MEMORY FUZZING feature.
|
||||||
|
[*] Target map size: 9960
|
||||||
|
[+] Processed 7849 input files.
|
||||||
|
[+] Captured 4331 tuples (highest value 255, total values 67130596) in '/dev/nul
|
||||||
|
l'.
|
||||||
|
[+] A coverage of 4331 edges were achieved out of 9960 existing (43.48%) with 7849 input files.
|
||||||
|
```
|
||||||
It is even better to check out the exact lines of code that have been reached -
|
It is even better to check out the exact lines of code that have been reached -
|
||||||
and which have not been found so far.
|
and which have not been found so far.
|
||||||
|
|
||||||
@ -580,6 +588,11 @@ then terminate it. The main node will pick it up and make it available to the
|
|||||||
other secondary nodes over time. Set `export AFL_NO_AFFINITY=1` if you have no
|
other secondary nodes over time. Set `export AFL_NO_AFFINITY=1` if you have no
|
||||||
free core.
|
free core.
|
||||||
|
|
||||||
|
Note that you in nearly all cases you can never reach full coverage. A lot of
|
||||||
|
functionality is usually behind options that were not activated or fuzz e.g.
|
||||||
|
if you fuzz a library to convert image formats and your target is the png to
|
||||||
|
tiff API then you will not touch any of the other library APIs and features.
|
||||||
|
|
||||||
#### e) How long to fuzz a target?
|
#### e) How long to fuzz a target?
|
||||||
|
|
||||||
This is a difficult question.
|
This is a difficult question.
|
||||||
|
1
TODO.md
1
TODO.md
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
- AFL_MAP_SIZE for qemu_mode and unicorn_mode
|
- AFL_MAP_SIZE for qemu_mode and unicorn_mode
|
||||||
- CPU affinity for many cores? There seems to be an issue > 96 cores
|
- CPU affinity for many cores? There seems to be an issue > 96 cores
|
||||||
- feature for afl-showmap to generate the coverage for all queue entries
|
|
||||||
- afl-plot to support multiple plot_data
|
- afl-plot to support multiple plot_data
|
||||||
|
|
||||||
## Further down the road
|
## Further down the road
|
||||||
|
@ -32,6 +32,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
- skipping ctors and ifuncs for instrumentation
|
- skipping ctors and ifuncs for instrumentation
|
||||||
- LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR
|
- LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR
|
||||||
for a fixed map address (eg. 0x10000)
|
for a fixed map address (eg. 0x10000)
|
||||||
|
- LTO: laf-intel and redqueen/cmplogare are now applied at link time
|
||||||
|
to prevent llvm optimizing away the splits
|
||||||
- LTO: autodictionary mode is a default
|
- LTO: autodictionary mode is a default
|
||||||
- LTO: instrim instrumentation disabled, only classic support used
|
- LTO: instrim instrumentation disabled, only classic support used
|
||||||
as it is always better
|
as it is always better
|
||||||
|
@ -246,33 +246,60 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
// laf
|
// laf
|
||||||
if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
|
if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
if (lto_mode) {
|
||||||
cc_params[cc_par_cnt++] = "-load";
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
cc_params[cc_par_cnt++] =
|
||||||
cc_params[cc_par_cnt++] =
|
alloc_printf("-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
|
||||||
alloc_printf("%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") ||
|
if (getenv("LAF_TRANSFORM_COMPARES") ||
|
||||||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
|
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
if (lto_mode) {
|
||||||
cc_params[cc_par_cnt++] = "-load";
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
cc_params[cc_par_cnt++] = alloc_printf(
|
||||||
cc_params[cc_par_cnt++] =
|
"-Wl,-mllvm=-load=%s/compare-transform-pass.so", obj_path);
|
||||||
alloc_printf("%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") ||
|
if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
|
||||||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
|
getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
if (lto_mode) {
|
||||||
cc_params[cc_par_cnt++] = "-load";
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
cc_params[cc_par_cnt++] =
|
||||||
cc_params[cc_par_cnt++] =
|
alloc_printf("-Wl,-mllvm=-load=%s/split-compares-pass.so", obj_path);
|
||||||
alloc_printf("%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");
|
unsetenv("AFL_LD_CALLER");
|
||||||
if (cmplog_mode) {
|
if (cmplog_mode) {
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
if (lto_mode) {
|
||||||
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++] =
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
alloc_printf("-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path);
|
||||||
cc_params[cc_par_cnt++] = "-load";
|
cc_params[cc_par_cnt++] =
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
alloc_printf("-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
|
||||||
cc_params[cc_par_cnt++] =
|
cc_params[cc_par_cnt++] = alloc_printf(
|
||||||
alloc_printf("%s/split-switches-pass.so", obj_path);
|
"-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path);
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
} else {
|
||||||
cc_params[cc_par_cnt++] = "-load";
|
|
||||||
cc_params[cc_par_cnt++] = "-Xclang";
|
cc_params[cc_par_cnt++] = "-Xclang";
|
||||||
cc_params[cc_par_cnt++] =
|
cc_params[cc_par_cnt++] = "-load";
|
||||||
alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
|
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";
|
cc_params[cc_par_cnt++] = "-fno-inline";
|
||||||
|
|
||||||
@ -314,6 +354,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", AFL_REAL_LD);
|
cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", AFL_REAL_LD);
|
||||||
cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
|
cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The current LTO instrim mode is not good, so we disable it
|
The current LTO instrim mode is not good, so we disable it
|
||||||
if (instrument_mode == INSTRUMENT_CFG)
|
if (instrument_mode == INSTRUMENT_CFG)
|
||||||
@ -321,6 +362,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
alloc_printf("-Wl,-mllvm=-load=%s/afl-llvm-lto-instrim.so",
|
alloc_printf("-Wl,-mllvm=-load=%s/afl-llvm-lto-instrim.so",
|
||||||
obj_path); else
|
obj_path); else
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cc_params[cc_par_cnt++] = alloc_printf(
|
cc_params[cc_par_cnt++] = alloc_printf(
|
||||||
"-Wl,-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", obj_path);
|
"-Wl,-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", obj_path);
|
||||||
cc_params[cc_par_cnt++] = lto_flag;
|
cc_params[cc_par_cnt++] = lto_flag;
|
||||||
|
@ -284,3 +284,7 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPass(
|
|||||||
static RegisterStandardPasses RegisterCmpLogInstructionsPass0(
|
static RegisterStandardPasses RegisterCmpLogInstructionsPass0(
|
||||||
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass);
|
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass);
|
||||||
|
|
||||||
|
static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO(
|
||||||
|
PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
|
||||||
|
registerCmpLogInstructionsPass);
|
||||||
|
|
||||||
|
@ -204,3 +204,7 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPass(
|
|||||||
static RegisterStandardPasses RegisterCmpLogRoutinesPass0(
|
static RegisterStandardPasses RegisterCmpLogRoutinesPass0(
|
||||||
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogRoutinesPass);
|
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogRoutinesPass);
|
||||||
|
|
||||||
|
static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO(
|
||||||
|
PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
|
||||||
|
registerCmpLogRoutinesPass);
|
||||||
|
|
||||||
|
@ -585,3 +585,6 @@ static RegisterStandardPasses RegisterCompTransPass(
|
|||||||
static RegisterStandardPasses RegisterCompTransPass0(
|
static RegisterStandardPasses RegisterCompTransPass0(
|
||||||
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass);
|
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass);
|
||||||
|
|
||||||
|
static RegisterStandardPasses RegisterCompTransPassLTO(
|
||||||
|
PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass);
|
||||||
|
|
||||||
|
@ -1342,3 +1342,7 @@ static RegisterStandardPasses RegisterSplitComparesPass(
|
|||||||
static RegisterStandardPasses RegisterSplitComparesTransPass0(
|
static RegisterStandardPasses RegisterSplitComparesTransPass0(
|
||||||
PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass);
|
PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass);
|
||||||
|
|
||||||
|
static RegisterStandardPasses RegisterSplitComparesTransPassLTO(
|
||||||
|
PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
|
||||||
|
registerSplitComparesPass);
|
||||||
|
|
||||||
|
@ -439,3 +439,7 @@ static RegisterStandardPasses RegisterSplitSwitchesTransPass(
|
|||||||
static RegisterStandardPasses RegisterSplitSwitchesTransPass0(
|
static RegisterStandardPasses RegisterSplitSwitchesTransPass0(
|
||||||
PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass);
|
PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass);
|
||||||
|
|
||||||
|
static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO(
|
||||||
|
PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
|
||||||
|
registerSplitSwitchesTransPass);
|
||||||
|
|
||||||
|
@ -68,9 +68,11 @@ static char *stdin_file; /* stdin file */
|
|||||||
static u8 *in_dir = NULL, /* input folder */
|
static u8 *in_dir = NULL, /* input folder */
|
||||||
*out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
|
*out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
|
||||||
|
|
||||||
static u8 *in_data; /* Input data */
|
static u8 *in_data, /* Input data */
|
||||||
|
*coverage_map; /* Coverage map */
|
||||||
|
|
||||||
static u32 total, highest; /* tuple content information */
|
static u64 total; /* tuple content information */
|
||||||
|
static u32 tcnt, highest; /* tuple content information */
|
||||||
|
|
||||||
static u32 in_len, /* Input data length */
|
static u32 in_len, /* Input data length */
|
||||||
arg_offset; /* Total number of execs */
|
arg_offset; /* Total number of execs */
|
||||||
@ -83,7 +85,8 @@ static u8 quiet_mode, /* Hide non-essential messages? */
|
|||||||
cmin_mode, /* Generate output in afl-cmin mode? */
|
cmin_mode, /* Generate output in afl-cmin mode? */
|
||||||
binary_mode, /* Write output as a binary map */
|
binary_mode, /* Write output as a binary map */
|
||||||
keep_cores, /* Allow coredumps? */
|
keep_cores, /* Allow coredumps? */
|
||||||
remove_shm = 1; /* remove shmem? */
|
remove_shm = 1, /* remove shmem? */
|
||||||
|
collect_coverage; /* collect coverage */
|
||||||
|
|
||||||
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||||
child_crashed; /* Child crashed? */
|
child_crashed; /* Child crashed? */
|
||||||
@ -175,6 +178,25 @@ static void at_exit_handler(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Analyze results. */
|
||||||
|
|
||||||
|
static void analyze_results(afl_forkserver_t *fsrv) {
|
||||||
|
|
||||||
|
u32 i;
|
||||||
|
for (i = 0; i < map_size; i++) {
|
||||||
|
|
||||||
|
if (fsrv->trace_bits[i]) {
|
||||||
|
|
||||||
|
total += fsrv->trace_bits[i];
|
||||||
|
if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i];
|
||||||
|
if (!coverage_map[i]) { coverage_map[i] = 1; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Write results. */
|
/* Write results. */
|
||||||
|
|
||||||
static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
|
static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
|
||||||
@ -588,9 +610,14 @@ static void usage(u8 *argv0) {
|
|||||||
" (Not necessary, here for consistency with other afl-* "
|
" (Not necessary, here for consistency with other afl-* "
|
||||||
"tools)\n\n"
|
"tools)\n\n"
|
||||||
"Other settings:\n"
|
"Other settings:\n"
|
||||||
" -i dir - process all files in this directory, -o must be a "
|
" -i dir - process all files in this directory, must be combined "
|
||||||
|
"with -o.\n"
|
||||||
|
" With -C, -o is a file, without -C it must be a "
|
||||||
"directory\n"
|
"directory\n"
|
||||||
" and each bitmap will be written there individually.\n"
|
" and each bitmap will be written there individually.\n"
|
||||||
|
" -C - collect coverage, writes all edges to -o and gives a "
|
||||||
|
"summary\n"
|
||||||
|
" Must be combined with -i.\n"
|
||||||
" -q - sink program's output and don't show messages\n"
|
" -q - sink program's output and don't show messages\n"
|
||||||
" -e - show edge coverage only, ignore hit counts\n"
|
" -e - show edge coverage only, ignore hit counts\n"
|
||||||
" -r - show real tuple values instead of AFL filter values\n"
|
" -r - show real tuple values instead of AFL filter values\n"
|
||||||
@ -624,7 +651,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
s32 opt, i;
|
s32 opt, i;
|
||||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
||||||
u32 tcnt = 0;
|
|
||||||
char **use_argv;
|
char **use_argv;
|
||||||
|
|
||||||
char **argv = argv_cpy_dup(argc, argv_orig);
|
char **argv = argv_cpy_dup(argc, argv_orig);
|
||||||
@ -639,10 +665,14 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; }
|
if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; }
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqZQUWbcrh")) > 0) {
|
while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZQUWbcrh")) > 0) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
collect_coverage = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
if (in_dir) { FATAL("Multiple -i options not supported"); }
|
if (in_dir) { FATAL("Multiple -i options not supported"); }
|
||||||
in_dir = optarg;
|
in_dir = optarg;
|
||||||
@ -820,6 +850,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (optind == argc || !out_file) { usage(argv[0]); }
|
if (optind == argc || !out_file) { usage(argv[0]); }
|
||||||
|
|
||||||
|
if (in_dir) {
|
||||||
|
|
||||||
|
if (!out_file && !collect_coverage)
|
||||||
|
FATAL("for -i you need to specify either -C and/or -o");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (fsrv->qemu_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
|
if (fsrv->qemu_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
|
||||||
if (unicorn_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
|
if (unicorn_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
|
||||||
|
|
||||||
@ -910,7 +947,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (in_dir) {
|
if (in_dir) {
|
||||||
|
|
||||||
DIR * dir_in, *dir_out;
|
DIR * dir_in, *dir_out = NULL;
|
||||||
struct dirent *dir_ent;
|
struct dirent *dir_ent;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
u8 infile[PATH_MAX], outfile[PATH_MAX];
|
u8 infile[PATH_MAX], outfile[PATH_MAX];
|
||||||
@ -924,20 +961,43 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
|
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
|
||||||
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
||||||
|
|
||||||
|
// if a queue subdirectory exists switch to that
|
||||||
|
u8 *dn = alloc_printf("%s/queue", in_dir);
|
||||||
|
if ((dir_in = opendir(in_dir))) {
|
||||||
|
|
||||||
|
closedir(dir_in);
|
||||||
|
in_dir = dn;
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
ck_free(dn);
|
||||||
|
if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
|
||||||
|
|
||||||
if (!(dir_in = opendir(in_dir))) {
|
if (!(dir_in = opendir(in_dir))) {
|
||||||
|
|
||||||
PFATAL("cannot open directory %s", in_dir);
|
PFATAL("cannot open directory %s", in_dir);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dir_out = opendir(out_file))) {
|
if (!collect_coverage) {
|
||||||
|
|
||||||
if (mkdir(out_file, 0700)) {
|
if (!(dir_out = opendir(out_file))) {
|
||||||
|
|
||||||
PFATAL("cannot create output directory %s", out_file);
|
if (mkdir(out_file, 0700)) {
|
||||||
|
|
||||||
|
PFATAL("cannot create output directory %s", out_file);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if ((coverage_map = (u8 *)malloc(map_size)) == NULL)
|
||||||
|
FATAL("coult not grab memory");
|
||||||
|
edges_only = 0;
|
||||||
|
raw_instr_output = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *use_dir = ".";
|
u8 *use_dir = ".";
|
||||||
@ -978,6 +1038,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
afl_fsrv_start(fsrv, use_argv, &stop_soon,
|
afl_fsrv_start(fsrv, use_argv, &stop_soon,
|
||||||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
|
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
|
||||||
|
map_size = fsrv->map_size;
|
||||||
|
|
||||||
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
||||||
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
|
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
|
||||||
@ -1005,7 +1066,8 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue;
|
if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name);
|
if (!collect_coverage)
|
||||||
|
snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name);
|
||||||
|
|
||||||
if (read_file(infile)) {
|
if (read_file(infile)) {
|
||||||
|
|
||||||
@ -1019,7 +1081,10 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
showmap_run_target_forkserver(fsrv, in_data, in_len);
|
showmap_run_target_forkserver(fsrv, in_data, in_len);
|
||||||
ck_free(in_data);
|
ck_free(in_data);
|
||||||
tcnt = write_results_to_file(fsrv, outfile);
|
if (collect_coverage)
|
||||||
|
analyze_results(fsrv);
|
||||||
|
else
|
||||||
|
tcnt = write_results_to_file(fsrv, outfile);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1030,6 +1095,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
closedir(dir_in);
|
closedir(dir_in);
|
||||||
if (dir_out) { closedir(dir_out); }
|
if (dir_out) { closedir(dir_out); }
|
||||||
|
|
||||||
|
if (collect_coverage) {
|
||||||
|
|
||||||
|
memcpy(fsrv->trace_bits, coverage_map, map_size);
|
||||||
|
tcnt = write_results_to_file(fsrv, out_file);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
||||||
@ -1043,8 +1115,14 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
if (!quiet_mode) {
|
if (!quiet_mode) {
|
||||||
|
|
||||||
if (!tcnt) { FATAL("No instrumentation detected" cRST); }
|
if (!tcnt) { FATAL("No instrumentation detected" cRST); }
|
||||||
OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST,
|
OKF("Captured %u tuples (highest value %u, total values %llu) in "
|
||||||
|
"'%s'." cRST,
|
||||||
tcnt, highest, total, out_file);
|
tcnt, highest, total, out_file);
|
||||||
|
if (collect_coverage)
|
||||||
|
OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) "
|
||||||
|
"with %llu input files.",
|
||||||
|
tcnt, map_size, ((float)tcnt * 100) / (float)map_size,
|
||||||
|
fsrv->total_execs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user