/* american fuzzy lop++ - high-performance binary-only instrumentation ------------------------------------------------------------------- Originally written by Andrew Griffiths and Michal Zalewski TCG instrumentation and block chaining support by Andrea Biondo QEMU 3.1.1 port, TCG thread-safety, CompareCoverage and NeverZero counters by Andrea Fioraldi Copyright 2015, 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 This code is a shim patched into the separately-distributed source code of QEMU 3.1.0. It leverages the built-in QEMU tracing functionality to implement AFL-style instrumentation and to take care of the remaining parts of the AFL fork server logic. The resulting QEMU binary is essentially a standalone instrumentation tool; for an example of how to leverage it for other purposes, you can have a look at afl-showmap.c. */ #include "afl-qemu-common.h" #include "tcg.h" void HELPER(afl_entry_routine)(CPUArchState *env) { afl_forkserver(ENV_GET_CPU(env)); } void HELPER(afl_compcov_16)(target_ulong cur_loc, target_ulong arg1, target_ulong arg2) { register uintptr_t idx = cur_loc; if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(idx); } } void HELPER(afl_compcov_32)(target_ulong cur_loc, target_ulong arg1, target_ulong arg2) { register uintptr_t idx = cur_loc; if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) { INC_AFL_AREA(idx + 2); if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) { INC_AFL_AREA(idx + 1); if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(idx); } } } } void HELPER(afl_compcov_64)(target_ulong cur_loc, target_ulong arg1, target_ulong arg2) { register uintptr_t idx = cur_loc; if ((arg1 & 0xff00000000000000) == (arg2 & 0xff00000000000000)) { INC_AFL_AREA(idx + 6); if ((arg1 & 0xff000000000000) == (arg2 & 0xff000000000000)) { INC_AFL_AREA(idx + 5); if ((arg1 & 0xff0000000000) == (arg2 & 0xff0000000000)) { INC_AFL_AREA(idx + 4); if ((arg1 & 0xff00000000) == (arg2 & 0xff00000000)) { INC_AFL_AREA(idx + 3); if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) { INC_AFL_AREA(idx + 2); if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) { INC_AFL_AREA(idx + 1); if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(idx); } } } } } } } } void HELPER(afl_cmplog_16)(target_ulong cur_loc, target_ulong arg1, target_ulong arg2) { register uintptr_t k = (uintptr_t)cur_loc; u32 hits = __afl_cmp_map->headers[k].hits; __afl_cmp_map->headers[k].hits = hits + 1; // if (!__afl_cmp_map->headers[k].cnt) // __afl_cmp_map->headers[k].cnt = __afl_cmp_counter++; __afl_cmp_map->headers[k].shape = 1; //__afl_cmp_map->headers[k].type = CMP_TYPE_INS; hits &= CMP_MAP_H - 1; __afl_cmp_map->log[k][hits].v0 = arg1; __afl_cmp_map->log[k][hits].v1 = arg2; } void HELPER(afl_cmplog_32)(target_ulong cur_loc, target_ulong arg1, target_ulong arg2) { register uintptr_t k = (uintptr_t)cur_loc; u32 hits = __afl_cmp_map->headers[k].hits; __afl_cmp_map->headers[k].hits = hits + 1; __afl_cmp_map->headers[k].shape = 3; hits &= CMP_MAP_H - 1; __afl_cmp_map->log[k][hits].v0 = arg1; __afl_cmp_map->log[k][hits].v1 = arg2; } void HELPER(afl_cmplog_64)(target_ulong cur_loc, target_ulong arg1, target_ulong arg2) { register uintptr_t k = (uintptr_t)cur_loc; u32 hits = __afl_cmp_map->headers[k].hits; __afl_cmp_map->headers[k].hits = hits + 1; __afl_cmp_map->headers[k].shape = 7; hits &= CMP_MAP_H - 1; __afl_cmp_map->log[k][hits].v0 = arg1; __afl_cmp_map->log[k][hits].v1 = arg2; }