mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 11:08:06 +00:00
Collect persistent coverage data and dump it at the end of the run
With CODE_COVERAGE builds, we need to collect the coverage data of each iteration in a persistant buffer that has the same size as the regular trace buffer used for fuzzing. We dump this information at the end of the run and when combined with pointer data and module info, this can be used to calculate code coverage.
This commit is contained in:
@ -206,6 +206,10 @@ typedef struct afl_forkserver {
|
|||||||
s32 nyx_log_fd;
|
s32 nyx_log_fd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __AFL_CODE_COVERAGE
|
||||||
|
u8 *persistent_trace_bits; /* Persistent copy of bitmap */
|
||||||
|
#endif
|
||||||
|
|
||||||
} afl_forkserver_t;
|
} afl_forkserver_t;
|
||||||
|
|
||||||
typedef enum fsrv_run_result {
|
typedef enum fsrv_run_result {
|
||||||
|
@ -252,6 +252,10 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
|
|||||||
fsrv->uses_crash_exitcode = false;
|
fsrv->uses_crash_exitcode = false;
|
||||||
fsrv->uses_asan = false;
|
fsrv->uses_asan = false;
|
||||||
|
|
||||||
|
#ifdef __AFL_CODE_COVERAGE
|
||||||
|
fsrv->persistent_trace_bits = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
fsrv->init_child_func = fsrv_exec_child;
|
fsrv->init_child_func = fsrv_exec_child;
|
||||||
list_append(&fsrv_list, fsrv);
|
list_append(&fsrv_list, fsrv);
|
||||||
|
|
||||||
@ -278,6 +282,10 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
|
|||||||
fsrv_to->fsrv_kill_signal = from->fsrv_kill_signal;
|
fsrv_to->fsrv_kill_signal = from->fsrv_kill_signal;
|
||||||
fsrv_to->debug = from->debug;
|
fsrv_to->debug = from->debug;
|
||||||
|
|
||||||
|
#ifdef __AFL_CODE_COVERAGE
|
||||||
|
fsrv_to->persistent_trace_bits = from->persistent_trace_bits;
|
||||||
|
#endif
|
||||||
|
|
||||||
// These are forkserver specific.
|
// These are forkserver specific.
|
||||||
fsrv_to->out_dir_fd = -1;
|
fsrv_to->out_dir_fd = -1;
|
||||||
fsrv_to->child_pid = -1;
|
fsrv_to->child_pid = -1;
|
||||||
|
@ -60,6 +60,27 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
|
|||||||
|
|
||||||
fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon);
|
fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon);
|
||||||
|
|
||||||
|
#ifdef __AFL_CODE_COVERAGE
|
||||||
|
if (unlikely(!fsrv->persistent_trace_bits)) {
|
||||||
|
|
||||||
|
// On the first run, we allocate the persistent map to collect coverage.
|
||||||
|
fsrv->persistent_trace_bits = (u8 *)malloc(fsrv->map_size);
|
||||||
|
memset(fsrv->persistent_trace_bits, 0, fsrv->map_size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < fsrv->map_size; ++i) {
|
||||||
|
|
||||||
|
if (fsrv->persistent_trace_bits[i] != 255 && fsrv->trace_bits[i]) {
|
||||||
|
|
||||||
|
fsrv->persistent_trace_bits[i]++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If post_run() function is defined in custom mutator, the function will be
|
/* If post_run() function is defined in custom mutator, the function will be
|
||||||
called each time after AFL++ executes the target program. */
|
called each time after AFL++ executes the target program. */
|
||||||
|
|
||||||
|
@ -3130,6 +3130,28 @@ stop_fuzzing:
|
|||||||
write_bitmap(afl);
|
write_bitmap(afl);
|
||||||
save_auto(afl);
|
save_auto(afl);
|
||||||
|
|
||||||
|
#ifdef __AFL_CODE_COVERAGE
|
||||||
|
if (afl->fsrv.persistent_trace_bits) {
|
||||||
|
|
||||||
|
char cfn[4096];
|
||||||
|
snprintf(cfn, sizeof(cfn), "%s/covmap.dump", afl->out_dir);
|
||||||
|
|
||||||
|
FILE *cov_fd;
|
||||||
|
if ((cov_fd = fopen(cfn, "w")) == NULL) {
|
||||||
|
|
||||||
|
PFATAL("could not create '%s'", cfn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the real map size, as the map size must exactly match the pointer
|
||||||
|
// map in length.
|
||||||
|
fwrite(afl->fsrv.persistent_trace_bits, 1, afl->fsrv.real_map_size, cov_fd);
|
||||||
|
fclose(cov_fd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
if (afl->pizza_is_served) {
|
if (afl->pizza_is_served) {
|
||||||
|
|
||||||
SAYF(CURSOR_SHOW cLRD "\n\n+++ Baking aborted %s +++\n" cRST,
|
SAYF(CURSOR_SHOW cLRD "\n\n+++ Baking aborted %s +++\n" cRST,
|
||||||
|
Reference in New Issue
Block a user