#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/types.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
#ifndef MAP_ANONYMOUS
# define MAP_ANONYMOUS MAP_ANON
#endif
#ifndef MIN
# define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a))
# define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b))
#endif
u8 __afl_area_initial[MAP_SIZE];
u8* __afl_area_ptr = __afl_area_initial;
__thread u32 __afl_prev_loc;
static u8 is_persistent;
static void __afl_map_shm(void) {
u8 *id_str = getenv(SHM_ENV_VAR);
if (id_str) {
u32 shm_id = atoi(id_str);
__afl_area_ptr = shmat(shm_id, NULL, 0);
if (__afl_area_ptr == (void *)-1) _exit(1);
__afl_area_ptr[0] = 1;
}
}
static void __afl_start_forkserver(void) {
static u8 tmp[4];
s32 child_pid;
u8 child_stopped = 0;
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
while (1) {
u32 was_killed;
int status;
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
if (child_stopped && was_killed) {
child_stopped = 0;
if (waitpid(child_pid, &status, 0) < 0) _exit(1);
}
if (!child_stopped) {
child_pid = fork();
if (child_pid < 0) _exit(1);
if (!child_pid) {
close(FORKSRV_FD);
close(FORKSRV_FD + 1);
return;
}
} else {
kill(child_pid, SIGCONT);
child_stopped = 0;
}
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) _exit(1);
if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0)
_exit(1);
if (WIFSTOPPED(status)) child_stopped = 1;
if (write(FORKSRV_FD + 1, &status, 4) != 4) _exit(1);
}
}
int __afl_persistent_loop(unsigned int max_cnt) {
static u8 first_pass = 1;
static u32 cycle_cnt;
if (first_pass) {
cycle_cnt = max_cnt;
first_pass = 0;
return 1;
}
if (is_persistent && --cycle_cnt) {
raise(SIGSTOP);
return 1;
} else return 0;
}
void __afl_manual_init(void) {
static u8 init_done;
if (!init_done) {
__afl_map_shm();
__afl_start_forkserver();
init_done = 1;
}
}
static void __afl_trace_pc_init(void);
__attribute__((constructor(0))) void __afl_auto_init(void) {
is_persistent = !!getenv(PERSIST_ENV_VAR);
__afl_trace_pc_init();
if (getenv(DEFER_ENV_VAR)) return;
__afl_manual_init();
}
static u32 inst_ratio_scaled = MIN(4096, MAP_SIZE);
void __sanitizer_cov_trace_pc(void) {
u32 cur = ((u32)__builtin_return_address(0)) & MIN(4095, MAP_SIZE - 1);
if (cur > inst_ratio_scaled) return;
__afl_area_ptr[cur ^ __afl_prev_loc]++;
#if MAP_SIZE_POW2 > 12
__afl_prev_loc = cur << (MAP_SIZE_POW2 - 12);
#else
__afl_prev_loc = cur >> 1;
#endif
}
static void __afl_trace_pc_init(void) {
u8* x = getenv("AFL_INST_RATIO");
if (!x) return;
inst_ratio_scaled = atoi(x);
if (!inst_ratio_scaled || inst_ratio_scaled > 100) {
fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n");
abort();
}
inst_ratio_scaled = inst_ratio_scaled * MIN(4096, MAP_SIZE) / 100;
}
void __sanitizer_cov_module_init(void) __attribute__((weak));
void __sanitizer_cov_module_init(void) { }