From 8fc249d210ad49e3dd88d1409877ca64d9884690 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 14 Feb 2022 18:01:37 +0100 Subject: Fix sample script for Unicornafl2 (#1329) * Fix the sample script for Unicornafl2 * Make it compatible with unicornafl1 * Sync to the latest unicornafl * Update UNICORNAFL_VERSION * Sync to latest unicornafl to resolve linkage problem * Switch to ucafl2 --- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/samples/compcov_x64/compcov_test_harness.py | 4 ++-- unicorn_mode/samples/speedtest/python/harness.py | 4 ++-- unicorn_mode/unicornafl | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index 4697a492..fe7be8e1 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -46879845 +a44fa94488d01aba60401ccf81f8bebcce685bf2 diff --git a/unicorn_mode/samples/compcov_x64/compcov_test_harness.py b/unicorn_mode/samples/compcov_x64/compcov_test_harness.py index 52f0a286..ce96b882 100644 --- a/unicorn_mode/samples/compcov_x64/compcov_test_harness.py +++ b/unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ -19,7 +19,7 @@ import os import signal from unicornafl import * -from unicornafl.x86_const import * +from unicorn.x86_const import * # Path to the file containing the binary to emulate BINARY_FILE = os.path.join( @@ -160,7 +160,7 @@ def main(): # Emulate the code, allowing it to process the mutated input print("Starting the AFL fuzz") - uc.afl_fuzz( + uc_afl_fuzz(uc, input_file=args.input_file, place_input_callback=place_input_callback, exits=[end_address], diff --git a/unicorn_mode/samples/speedtest/python/harness.py b/unicorn_mode/samples/speedtest/python/harness.py index 801ef4d1..604adf39 100644 --- a/unicorn_mode/samples/speedtest/python/harness.py +++ b/unicorn_mode/samples/speedtest/python/harness.py @@ -20,8 +20,8 @@ import os import struct from unicornafl import * -from unicornafl.unicorn_const import UC_ARCH_X86, UC_HOOK_CODE, UC_MODE_64 -from unicornafl.x86_const import ( +from unicorn.unicorn_const import UC_ARCH_X86, UC_HOOK_CODE, UC_MODE_64 +from unicorn.x86_const import ( UC_X86_REG_RAX, UC_X86_REG_RDI, UC_X86_REG_RIP, diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 46879845..a44fa944 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 468798455a9f9790d2da369a18ed49fda3a64e8c +Subproject commit a44fa94488d01aba60401ccf81f8bebcce685bf2 -- cgit 1.4.1 From dd8ad4dfa35c8b11ebcc6005f44855db02fefb74 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 18 Feb 2022 07:55:26 +0000 Subject: Changes to simplify coverage code --- frida_mode/src/instrument/instrument_x64.c | 344 +++++------------------------ 1 file changed, 59 insertions(+), 285 deletions(-) diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index fb84d6d2..c28285ff 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -23,14 +23,6 @@ #if defined(__x86_64__) - #ifndef MAP_FIXED_NOREPLACE - #ifdef MAP_EXCL - #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED - #else - #define MAP_FIXED_NOREPLACE MAP_FIXED - #endif - #endif - static GHashTable *coverage_blocks = NULL; gboolean instrument_is_coverage_optimize_supported(void) { @@ -45,8 +37,7 @@ static gboolean instrument_coverage_in_range(gssize offset) { } - #ifdef __APPLE__ - #pragma pack(push, 1) + #pragma pack(push, 1) typedef struct { @@ -54,95 +45,28 @@ typedef struct { // shared_mem[cur_location ^ prev_location]++; // prev_location = cur_location >> 1; - // mov QWORD PTR [rsp-0x80],rax - // lahf - // mov QWORD PTR [rsp-0x88],rax - // mov QWORD PTR [rsp-0x90],rbx - // mov eax,DWORD PTR [rip+0x333d5a] # 0x7ffff6ff2740 - // mov DWORD PTR [rip+0x333d3c],0x9fbb # 0x7ffff6ff2740 - // lea rax,[rip + 0x103f77] - // mov bl,BYTE PTR [rax] - // add bl,0x1 - // adc bl,0x0 - // mov BYTE PTR [rax],bl - // mov rbx,QWORD PTR [rsp-0x90] - // mov rax,QWORD PTR [rsp-0x88] - // sahf - // mov rax,QWORD PTR [rsp-0x80] - - uint8_t mov_rax_rsp_88[8]; - uint8_t lahf; - uint8_t mov_rax_rsp_90[8]; - uint8_t mov_rbx_rsp_98[8]; - - uint8_t mov_eax_prev_loc[6]; - uint8_t mov_prev_loc_curr_loc_shr1[10]; - - uint8_t leax_eax_curr_loc[7]; - - uint8_t mov_rbx_ptr_rax[2]; - uint8_t add_bl_1[3]; - uint8_t adc_bl_0[3]; - uint8_t mov_ptr_rax_rbx[2]; - - uint8_t mov_rsp_98_rbx[8]; - uint8_t mov_rsp_90_rax[8]; - uint8_t sahf; - uint8_t mov_rsp_88_rax[8]; - -} afl_log_code_asm_t; - - #pragma pack(pop) - -static const afl_log_code_asm_t template = - { + // mov QWORD PTR [rsp-0x88],rax + // lahf + // mov QWORD PTR [rsp-0x90],rax + // mov QWORD PTR [rsp-0x98],rbx - .mov_rax_rsp_88 = {0x48, 0x89, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF}, - .lahf = 0x9f, - .mov_rax_rsp_90 = {0x48, 0x89, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF}, - .mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF}, - - .mov_eax_prev_loc = {0x8b, 0x05}, - .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, + // mov eax,DWORD PTR [rip+0x1312334] + // xor eax,0x3f77 - .leax_eax_curr_loc = {0x48, 0x8d, 0x05}, - .mov_rbx_ptr_rax = {0x8a, 0x18}, - .add_bl_1 = {0x80, 0xc3, 0x01}, - .adc_bl_0 = {0x80, 0xd3, 0x00}, - .mov_ptr_rax_rbx = {0x88, 0x18}, + // lea rbx,[rip+0x132338] + // add rax,rbx - .mov_rsp_98_rbx = {0x48, 0x8B, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF}, - .mov_rsp_90_rax = {0x48, 0x8B, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF}, - .sahf = 0x9e, - .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF}, + // mov bl,BYTE PTR [rax] + // add bl,0x1 + // adc bl,0x0 + // mov BYTE PTR [rax],bl -} + // mov rbx,QWORD PTR [rsp-0x98] + // mov rax,QWORD PTR [rsp-0x90] + // sahf + // mov rax,QWORD PTR [rsp-0x88] -; - - #else - #pragma pack(push, 1) -typedef struct { - - // cur_location = (block_address >> 4) ^ (block_address << 8); - // shared_mem[cur_location ^ prev_location]++; - // prev_location = cur_location >> 1; - - // mov QWORD PTR [rsp-0x80],rax - // lahf - // mov QWORD PTR [rsp-0x88],rax - // mov QWORD PTR [rsp-0x90],rbx - // mov eax,DWORD PTR [rip+0x333d5a] # 0x7ffff6ff2740 - // mov DWORD PTR [rip+0x333d3c],0x9fbb # 0x7ffff6ff2740 - // xor eax,0x103f77 - // mov bl,BYTE PTR [rax] - // add bl,0x1 - // adc bl,0x0 - // mov BYTE PTR [rax],bl - // mov rbx,QWORD PTR [rsp-0x90] - // mov rax,QWORD PTR [rsp-0x88] - // sahf - // mov rax,QWORD PTR [rsp-0x80] + // mov DWORD PTR [rip+0x13122f8],0x9fbb uint8_t mov_rax_rsp_88[8]; uint8_t lahf; @@ -150,10 +74,11 @@ typedef struct { uint8_t mov_rbx_rsp_98[8]; uint8_t mov_eax_prev_loc[6]; - uint8_t mov_prev_loc_curr_loc_shr1[10]; - uint8_t xor_eax_curr_loc[5]; + uint8_t lea_rbx_area_ptr[7]; + uint8_t add_rax_rbx[3]; + uint8_t mov_rbx_ptr_rax[2]; uint8_t add_bl_1[3]; uint8_t adc_bl_0[3]; @@ -164,9 +89,11 @@ typedef struct { uint8_t sahf; uint8_t mov_rsp_88_rax[8]; + uint8_t mov_prev_loc_curr_loc_shr1[10]; + } afl_log_code_asm_t; - #pragma pack(pop) + #pragma pack(pop) static const afl_log_code_asm_t template = { @@ -177,9 +104,10 @@ static const afl_log_code_asm_t template = .mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF}, .mov_eax_prev_loc = {0x8b, 0x05}, - .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, - .xor_eax_curr_loc = {0x35}, + .lea_rbx_area_ptr = {0x48, 0x8d, 0x1d}, + .add_rax_rbx = {0x48, 0x01, 0xd8}, + .mov_rbx_ptr_rax = {0x8a, 0x18}, .add_bl_1 = {0x80, 0xc3, 0x01}, .adc_bl_0 = {0x80, 0xd3, 0x00}, @@ -190,10 +118,11 @@ static const afl_log_code_asm_t template = .sahf = 0x9e, .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF}, + .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, + } ; - #endif typedef union { @@ -202,171 +131,12 @@ typedef union { } afl_log_code; - #ifdef __APPLE__ - -void instrument_coverage_optimize_init(void) { - -} - - #else - -static gboolean instrument_coverage_find_low(const GumRangeDetails *details, - gpointer user_data) { - - static GumAddress last_limit = (64ULL << 10); - gpointer * address = (gpointer *)user_data; - - last_limit = GUM_ALIGN_SIZE(last_limit, __afl_map_size); - - if ((details->range->base_address - last_limit) > __afl_map_size) { - - *address = GSIZE_TO_POINTER(last_limit); - return FALSE; - - } - - if (details->range->base_address > ((2ULL << 30) - __afl_map_size)) { - - return FALSE; - - } - - /* - * Align our buffer on a 64k boundary so that the low 16-bits of the address - * are zero, then we can just XOR the base address in, when we XOR with the - * current block ID. - */ - last_limit = GUM_ALIGN_SIZE( - details->range->base_address + details->range->size, __afl_map_size); - return TRUE; - -} - -static void instrument_coverage_optimize_map_mmap_anon(gpointer address) { - - __afl_area_ptr = - mmap(address, __afl_map_size, PROT_READ | PROT_WRITE, - MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if (__afl_area_ptr != address) { - - FATAL("Failed to map mmap __afl_area_ptr: %d", errno); - - } - -} - -static void instrument_coverage_optimize_map_mmap(char * shm_file_path, - gpointer address) { - - int shm_fd = -1; - - if (munmap(__afl_area_ptr, __afl_map_size) != 0) { - - FATAL("Failed to unmap previous __afl_area_ptr"); - - } - - __afl_area_ptr = NULL; - - #if !defined(__ANDROID__) - shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION); - if (shm_fd == -1) { FATAL("shm_open() failed\n"); } - #else - shm_fd = open("/dev/ashmem", O_RDWR); - if (shm_fd == -1) { FATAL("open() failed\n"); } - if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) { - - FATAL("ioctl(ASHMEM_SET_NAME) failed"); - - } - - if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) { - - FATAL("ioctl(ASHMEM_SET_SIZE) failed"); - - } - - #endif - - __afl_area_ptr = mmap(address, __afl_map_size, PROT_READ | PROT_WRITE, - MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0); - if (__afl_area_ptr != address) { - - FATAL("Failed to map mmap __afl_area_ptr: %d", errno); - - } - - if (close(shm_fd) != 0) { FATAL("Failed to close shm_fd"); } - -} - -static void instrument_coverage_optimize_map_shm(guint64 shm_env_val, - gpointer address) { - - if (shmdt(__afl_area_ptr) != 0) { - - FATAL("Failed to detach previous __afl_area_ptr"); - - } - - __afl_area_ptr = shmat(shm_env_val, address, 0); - if (__afl_area_ptr != address) { - - FATAL("Failed to map shm __afl_area_ptr: %d", errno); - - } - -} - void instrument_coverage_optimize_init(void) { - gpointer low_address = NULL; - - gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low, - &low_address); - - FVERBOSE("Low address: %p", low_address); - - if (low_address == 0 || - GPOINTER_TO_SIZE(low_address) > ((2UL << 30) - __afl_map_size)) { - - FATAL("Invalid low_address: %p", low_address); - - } - - ranges_print_debug_maps(); - - char *shm_env = getenv(SHM_ENV_VAR); - FVERBOSE("SHM_ENV_VAR: %s", shm_env); - - if (shm_env == NULL) { - - FWARNF("SHM_ENV_VAR not set, using anonymous map for debugging purposes"); - - instrument_coverage_optimize_map_mmap_anon(low_address); - - } else { - - guint64 shm_env_val = g_ascii_strtoull(shm_env, NULL, 10); - - if (shm_env_val == 0) { - - instrument_coverage_optimize_map_mmap(shm_env, low_address); - - } else { - - instrument_coverage_optimize_map_shm(shm_env_val, low_address); - - } - - } - FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr); } - #endif - static void instrument_coverage_switch(GumStalkerObserver *self, gpointer start_address, const cs_insn * from_insn, @@ -465,14 +235,7 @@ void instrument_coverage_optimize(const cs_insn * instr, code.code = template; - gssize curr_loc_shr_1_offset = - offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) + - sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32); - - map_size_pow2 = util_log2(__afl_map_size); - area_offset_ror = util_rotate(area_offset, 1, map_size_pow2); - - *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror); + /* mov_prev_loc_curr_loc_shr1 */ gssize prev_loc_value = GPOINTER_TO_SIZE(instrument_previous_pc_addr) - @@ -490,6 +253,8 @@ void instrument_coverage_optimize(const cs_insn * instr, *((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value; + /* mov_eax_prev_loc */ + gssize prev_loc_value2 = GPOINTER_TO_SIZE(instrument_previous_pc_addr) - (code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) + @@ -505,35 +270,44 @@ void instrument_coverage_optimize(const cs_insn * instr, *((gint *)&code.bytes[prev_loc_value_offset2]) = (gint)prev_loc_value2; - #ifdef __APPLE__ + /* xor_eax_curr_loc */ - gssize xor_curr_loc_offset = offsetof(afl_log_code, code.leax_eax_curr_loc) + - sizeof(code.code.leax_eax_curr_loc) - + gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) + + sizeof(code.code.xor_eax_curr_loc) - sizeof(guint32); - gssize xor_curr_loc_value = - ((GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset) - - (code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) + - sizeof(code.code.mov_eax_prev_loc))); + *((guint32 *)&code.bytes[xor_curr_loc_offset]) = area_offset; - if (!instrument_coverage_in_range(xor_curr_loc_value)) { + /* lea_rbx_area_ptr */ - FATAL("Patch out of range (xor_curr_loc_value): 0x%016lX", - xor_curr_loc_value); + gssize lea_rbx_area_ptr_offset = + offsetof(afl_log_code, code.lea_rbx_area_ptr) + + sizeof(code.code.lea_rbx_area_ptr) - sizeof(guint32); + + gssize lea_rbx_area_ptr_value = + (GPOINTER_TO_SIZE(__afl_area_ptr) - + (code_addr + offsetof(afl_log_code, code.lea_rbx_area_ptr) + + sizeof(code.code.lea_rbx_area_ptr))); + + if (!instrument_coverage_in_range(lea_rbx_area_ptr_value)) { + + FATAL("Patch out of range (lea_rbx_area_ptr_value): 0x%016lX", + lea_rbx_area_ptr_value); } - *((guint32 *)&code.bytes[xor_curr_loc_offset]) = xor_curr_loc_value; + *((guint32 *)&code.bytes[lea_rbx_area_ptr_offset]) = lea_rbx_area_ptr_value; - #else + /* mov_prev_loc_curr_loc_shr1 */ - gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) + - sizeof(code.code.xor_eax_curr_loc) - - sizeof(guint32); + gssize curr_loc_shr_1_offset = + offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) + + sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32); - *((guint32 *)&code.bytes[xor_curr_loc_offset]) = - (guint32)(GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset); - #endif + map_size_pow2 = util_log2(__afl_map_size); + area_offset_ror = util_rotate(area_offset, 1, map_size_pow2); + + *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror); gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); -- cgit 1.4.1 From cb1256499f7e07fd0edf0958d08b958fec63c34c Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 18 Feb 2022 07:55:45 +0000 Subject: Added instrumentation for CMOV instructions --- frida_mode/README.md | 2 + frida_mode/frida.map | 1 + frida_mode/include/instrument.h | 3 + frida_mode/src/instrument/instrument.c | 8 ++ frida_mode/src/instrument/instrument_arm32.c | 9 ++ frida_mode/src/instrument/instrument_arm64.c | 8 ++ frida_mode/src/instrument/instrument_x64.c | 191 +++++++++++++++++++++++---- frida_mode/src/instrument/instrument_x86.c | 8 ++ frida_mode/src/js/api.js | 7 + frida_mode/src/js/js_api.c | 7 + frida_mode/test/cmov/GNUmakefile | 87 ++++++++++++ frida_mode/test/cmov/Makefile | 19 +++ frida_mode/test/cmov/cmov.c | 122 +++++++++++++++++ frida_mode/ts/lib/afl.ts | 12 ++ include/envs.h | 1 + 15 files changed, 457 insertions(+), 28 deletions(-) create mode 100644 frida_mode/test/cmov/GNUmakefile create mode 100644 frida_mode/test/cmov/Makefile create mode 100644 frida_mode/test/cmov/cmov.c diff --git a/frida_mode/README.md b/frida_mode/README.md index e5b46baf..bf5cffec 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -173,6 +173,8 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent * `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled code. Code is considered to be JIT if the executable segment is not backed by a file. +* `AFL_FRIDA_INST_NO_INSN` - Don't generate instrumentation for conditional + instructions (e.g. `CMOV` instructions on x64). * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage instrumentation (the default where available). Required to use `AFL_FRIDA_INST_TRACE`. diff --git a/frida_mode/frida.map b/frida_mode/frida.map index d059bdb6..e9afac1b 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -15,6 +15,7 @@ js_api_set_instrument_debug_file; js_api_set_instrument_jit; js_api_set_instrument_libraries; + js_api_set_instrument_no_instructions; js_api_set_instrument_no_optimize; js_api_set_instrument_seed; js_api_set_instrument_trace; diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index abb89c9f..20312a4b 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -12,6 +12,7 @@ extern gboolean instrument_optimize; extern gboolean instrument_unique; extern guint64 instrument_hash_zero; extern char * instrument_coverage_unstable_filename; +extern gboolean instrument_coverage_insn; extern gboolean instrument_use_fixed_seed; extern guint64 instrument_fixed_seed; @@ -33,6 +34,8 @@ gboolean instrument_is_coverage_optimize_supported(void); void instrument_coverage_optimize_init(void); void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output); +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output); void instrument_debug_config(void); void instrument_debug_init(void); diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 418b35e8..4877f4fb 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -29,6 +29,7 @@ guint64 instrument_hash_seed = 0; gboolean instrument_use_fixed_seed = FALSE; guint64 instrument_fixed_seed = 0; char * instrument_coverage_unstable_filename = NULL; +gboolean instrument_coverage_insn = FALSE; static GumStalkerTransformer *transformer = NULL; @@ -233,6 +234,12 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } + if (instrument_coverage_insn) { + + instrument_coverage_optimize_insn(instr, output); + + } + instrument_debug_instruction(instr->address, instr->size, output); if (likely(!excluded)) { @@ -269,6 +276,7 @@ void instrument_config(void) { instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED", 0); instrument_coverage_unstable_filename = (getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE")); + instrument_coverage_insn = (getenv("AFL_FRIDA_INST_NO_INSN") == NULL); instrument_debug_config(); instrument_coverage_config(); diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 16e8eaab..705faa64 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -20,6 +20,15 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + FFATAL("Optimized coverage not supported on this architecture"); + +} + void instrument_coverage_optimize_init(void) { FWARNF("Optimized coverage not supported on this architecture"); diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 1a704585..4abc0625 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -341,6 +341,14 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + void instrument_coverage_optimize_init(void) { char *shm_env = getenv(SHM_ENV_VAR); diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index c28285ff..4b1a2d68 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -23,6 +23,40 @@ #if defined(__x86_64__) +enum jcc_opcodes { + + OPC_JO = 0x70, + OPC_JNO = 0x71, + OPC_JB = 0x72, + OPC_JAE = 0x73, + OPC_JE = 0x74, + OPC_JNE = 0x75, + OPC_JBE = 0x76, + OPC_JA = 0x77, + OPC_JS = 0x78, + OPC_JNS = 0x79, + OPC_JP = 0x7a, + OPC_JNP = 0x7b, + OPC_JL = 0x7c, + OPC_JGE = 0x7d, + OPC_JLE = 0x7e, + OPC_JG = 0x7f, + +}; + +typedef union { + + struct { + + uint8_t opcode; + uint8_t distance; + + }; + + uint8_t bytes[0]; + +} jcc_insn; + static GHashTable *coverage_blocks = NULL; gboolean instrument_is_coverage_optimize_supported(void) { @@ -201,37 +235,15 @@ static void instrument_coverage_suppress_init(void) { } -void instrument_coverage_optimize(const cs_insn * instr, - GumStalkerOutput *output) { +static void instrument_coverage_write(GumAddress address, + GumStalkerOutput *output) { afl_log_code code = {0}; GumX86Writer *cw = output->writer.x86; - guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); - gsize map_size_pow2; - gsize area_offset_ror; - GumAddress code_addr = 0; - if (instrument_previous_pc_addr == NULL) { - - GumAddressSpec spec = {.near_address = cw->code, - .max_distance = 1ULL << 30}; - - instrument_previous_pc_addr = gum_memory_allocate_near( - &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE); - *instrument_previous_pc_addr = instrument_hash_zero; - FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); - FVERBOSE("code_addr: %p", cw->code); - - } - - instrument_coverage_suppress_init(); - - // gum_x86_writer_put_breakpoint(cw); - code_addr = cw->pc; - if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { - - FATAL("Failed - g_hash_table_add"); - - } + guint64 area_offset = instrument_get_offset_hash(address); + gsize map_size_pow2; + gsize area_offset_ror; + GumAddress code_addr = cw->pc; code.code = template; @@ -313,6 +325,129 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize(const cs_insn * instr, + GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); + if (instrument_previous_pc_addr == NULL) { + + GumAddressSpec spec = {.near_address = cw->code, + .max_distance = 1ULL << 30}; + + instrument_previous_pc_addr = gum_memory_allocate_near( + &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE); + *instrument_previous_pc_addr = instrument_hash_zero; + FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); + FVERBOSE("code_addr: %p", cw->code); + + } + + instrument_coverage_suppress_init(); + + if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + + FATAL("Failed - g_hash_table_add"); + + } + + instrument_coverage_write(GUM_ADDRESS(instr->address), output); + +} + +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + jcc_insn taken, not_taken; + + switch (instr->id) { + + case X86_INS_CMOVA: + taken.opcode = OPC_JA; + not_taken.opcode = OPC_JBE; + break; + case X86_INS_CMOVAE: + taken.opcode = OPC_JAE; + not_taken.opcode = OPC_JB; + break; + case X86_INS_CMOVB: + taken.opcode = OPC_JB; + not_taken.opcode = OPC_JAE; + break; + case X86_INS_CMOVBE: + taken.opcode = OPC_JBE; + not_taken.opcode = OPC_JA; + break; + case X86_INS_CMOVE: + taken.opcode = OPC_JE; + not_taken.opcode = OPC_JNE; + break; + case X86_INS_CMOVG: + taken.opcode = OPC_JG; + not_taken.opcode = OPC_JLE; + break; + case X86_INS_CMOVGE: + taken.opcode = OPC_JGE; + not_taken.opcode = OPC_JL; + break; + case X86_INS_CMOVL: + taken.opcode = OPC_JL; + not_taken.opcode = OPC_JGE; + break; + case X86_INS_CMOVLE: + taken.opcode = OPC_JLE; + not_taken.opcode = OPC_JG; + break; + case X86_INS_CMOVNE: + taken.opcode = OPC_JNE; + not_taken.opcode = OPC_JE; + break; + case X86_INS_CMOVNO: + taken.opcode = OPC_JNO; + not_taken.opcode = OPC_JO; + break; + case X86_INS_CMOVNP: + taken.opcode = OPC_JNP; + not_taken.opcode = OPC_JP; + break; + case X86_INS_CMOVNS: + taken.opcode = OPC_JNS; + not_taken.opcode = OPC_JS; + break; + case X86_INS_CMOVO: + taken.opcode = OPC_JO; + not_taken.opcode = OPC_JNO; + break; + case X86_INS_CMOVP: + taken.opcode = OPC_JP; + not_taken.opcode = OPC_JNP; + break; + case X86_INS_CMOVS: + taken.opcode = OPC_JS; + not_taken.opcode = OPC_JNS; + break; + default: + return; + + } + + taken.distance = sizeof(afl_log_code); + not_taken.distance = sizeof(afl_log_code); + + // gum_x86_writer_put_breakpoint(cw); + + gum_x86_writer_put_bytes(cw, taken.bytes, sizeof(jcc_insn)); + instrument_coverage_write(GUM_ADDRESS(instr->address), output); + + gum_x86_writer_put_bytes(cw, not_taken.bytes, sizeof(jcc_insn)); + instrument_coverage_write(GUM_ADDRESS(instr->address + instr->size), output); + + FVERBOSE("Instrument - 0x%016lx: %s %s", instr->address, instr->mnemonic, + instr->op_str); + +} + void instrument_flush(GumStalkerOutput *output) { gum_x86_writer_flush(output->writer.x86); diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index c4e93324..916cd0e2 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -218,6 +218,14 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + void instrument_coverage_optimize_init(void) { } diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 52e9e45c..c2d9a2d4 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -125,6 +125,12 @@ class Afl { static setInstrumentLibraries() { Afl.jsApiSetInstrumentLibraries(); } + /** + * See `AFL_FRIDA_INST_NO_INSN` + */ + static setInstrumentNoInstructions() { + Afl.jsApiSetInstrumentNoInstructions(); + } /** * See `AFL_FRIDA_INST_NO_OPTIMIZE` */ @@ -299,6 +305,7 @@ Afl.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]); Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []); Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []); +Afl.jsApiSetInstrumentNoInstructions = Afl.jsApiGetFunction("js_api_set_instrument_no_instructions", "void", []); Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []); Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]); Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 94ec8842..613747b8 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -142,6 +142,13 @@ js_api_set_prefetch_backpatch_disable(void) { } +__attribute__((visibility("default"))) void +js_api_set_instrument_no_instructions(void) { + + instrument_coverage_insn = FALSE; + +} + __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize( void) { diff --git a/frida_mode/test/cmov/GNUmakefile b/frida_mode/test/cmov/GNUmakefile new file mode 100644 index 00000000..318b2ad0 --- /dev/null +++ b/frida_mode/test/cmov/GNUmakefile @@ -0,0 +1,87 @@ +PWD:=$(shell pwd)/ +ROOT:=$(PWD)../../../ +BUILD_DIR:=$(PWD)build/ + +TEST_CMOV_SRC:=$(PWD)cmov.c +TEST_CMOV_OBJ:=$(BUILD_DIR)cmov + +TEST_DATA_DIR:=$(BUILD_DIR)in/ +CMP_LOG_INPUT:=$(TEST_DATA_DIR)in +QEMU_OUT:=$(BUILD_DIR)qemu-out +FRIDA_OUT:=$(BUILD_DIR)frida-out + +ADDR_BIN:=$(ROOT)frida_mode/build/addr +GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh + +AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so + +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_CMOV_OBJ) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) + +DUMMY_DATA_FILE:=$(BUILD_DIR)dummy.dat + +.PHONY: all 32 clean frida frida_noinst debug format + +all: $(TEST_CMOV_OBJ) + make -C $(ROOT)frida_mode/ + +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + +$(BUILD_DIR): + mkdir -p $@ + +$(TEST_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(CMP_LOG_INPUT): | $(TEST_DATA_DIR) + echo -n "ABC" > $@ + +$(TEST_CMOV_OBJ): $(TEST_CMOV_SRC) | $(BUILD_DIR) + $(CC) -g $(CFLAGS) $(LDFLAGS) $< -o $@ + +########## DUMMY ####### + +$(DUMMY_DATA_FILE): | $(BUILD_DIR) + dd if=/dev/zero bs=1048576 count=1 of=$@ + +frida: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) $(DUMMY_DATA_FILE) + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -Z \ + -t 10000+ \ + -- \ + $(TEST_CMOV_OBJ) $(DUMMY_DATA_FILE) + +frida_noinst: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) $(DUMMY_DATA_FILE) + AFL_FRIDA_INST_NO_INSN=1 \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -Z \ + -- \ + $(TEST_CMOV_OBJ) $(DUMMY_DATA_FILE) + +debug: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) + gdb \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set disassembly-flavor intel' \ + --ex 'r $(CMP_LOG_INPUT)' \ + --args $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) + +clean: + rm -rf $(BUILD_DIR) + +format: + cd $(ROOT) && echo $(TEST_CMOV_SRC) | xargs -L1 ./.custom-format.py -i diff --git a/frida_mode/test/cmov/Makefile b/frida_mode/test/cmov/Makefile new file mode 100644 index 00000000..9ef6fc8f --- /dev/null +++ b/frida_mode/test/cmov/Makefile @@ -0,0 +1,19 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + +clean: + @gmake clean + +frida: + @gmake frida + +format: + @gmake format + +debug: + @gmake debug diff --git a/frida_mode/test/cmov/cmov.c b/frida_mode/test/cmov/cmov.c new file mode 100644 index 00000000..08c7c132 --- /dev/null +++ b/frida_mode/test/cmov/cmov.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include + +static bool cmov_test(char *x, char *y, size_t len) { + + register char * __rdi __asm__("rdi") = x; + register char * __rsi __asm__("rsi") = y; + register size_t __rcx __asm__("rcx") = len; + + register long __rax __asm__("rax"); + + __asm__ __volatile__( + "mov $0x1, %%rax\n" + "mov $0x0, %%r8\n" + "1:\n" + "mov (%%rsi), %%bl\n" + "mov (%%rdi), %%dl\n" + "cmp %%bl, %%dl\n" + "cmovne %%r8, %%rax\n" + "inc %%rsi\n" + "inc %%rdi\n" + "dec %%rcx\n" + "jnz 1b\n" + : "=r"(__rax) + : "r"(__rdi), "r"(__rsi) + : "r8", "bl", "dl", "memory"); + + return __rax; + +} + +void LLVMFuzzerTestOneInput(char *buf, int len) { + + char match[] = "CBAABC"; + + if (len > sizeof(match)) { return; } + + if (cmov_test(buf, match, sizeof(buf)) != 0) { + + printf("Puzzle solved, congrats!\n"); + abort(); + + } + +} + +int main(int argc, char **argv) { + + char * file; + int fd = -1; + off_t len; + char * buf = NULL; + size_t n_read; + int result = -1; + + if (argc != 2) { return 1; } + + do { + + file = argv[1]; + + dprintf(STDERR_FILENO, "Running: %s\n", file); + + fd = open(file, O_RDONLY); + if (fd < 0) { + + perror("open"); + break; + + } + + len = lseek(fd, 0, SEEK_END); + if (len < 0) { + + perror("lseek (SEEK_END)"); + break; + + } + + if (lseek(fd, 0, SEEK_SET) != 0) { + + perror("lseek (SEEK_SET)"); + break; + + } + + buf = (char *)malloc(len); + if (buf == NULL) { + + perror("malloc"); + break; + + } + + n_read = read(fd, buf, len); + if (n_read != len) { + + perror("read"); + break; + + } + + dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read); + + LLVMFuzzerTestOneInput(buf, len); + dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read); + + result = 0; + + } while (false); + + if (buf != NULL) { free(buf); } + + if (fd != -1) { close(fd); } + + return result; + +} + diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts index 57d7b5b5..9d31370e 100644 --- a/frida_mode/ts/lib/afl.ts +++ b/frida_mode/ts/lib/afl.ts @@ -149,6 +149,13 @@ class Afl { Afl.jsApiSetInstrumentLibraries(); } + /** + * See `AFL_FRIDA_INST_NO_INSN` + */ + public static setInstrumentNoInstructions(): void { + Afl.jsApiSetInstrumentNoInstructions(); + } + /** * See `AFL_FRIDA_INST_NO_OPTIMIZE` */ @@ -377,6 +384,11 @@ class Afl { "void", []); + private static readonly jsApiSetInstrumentNoInstructions = Afl.jsApiGetFunction( + "js_api_set_instrument_no_instructions", + "void", + []); + private static readonly jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction( "js_api_set_instrument_no_optimize", "void", diff --git a/include/envs.h b/include/envs.h index f4327d8c..2ab3a387 100644 --- a/include/envs.h +++ b/include/envs.h @@ -60,6 +60,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", "AFL_FRIDA_INST_JIT", + "AFL_FRIDA_INST_NO_INSN", "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", -- cgit 1.4.1 From 5f45f380c3d9837a5a8457cf749b27a8afbd3f53 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 18 Feb 2022 08:10:19 +0000 Subject: Changes to default CMOV instrumentation to off --- frida_mode/README.md | 4 ++-- frida_mode/frida.map | 2 +- frida_mode/src/instrument/instrument.c | 4 +++- frida_mode/src/js/api.js | 14 +++++++------- frida_mode/src/js/js_api.c | 6 +++--- frida_mode/src/ranges.c | 2 -- frida_mode/test/cmov/GNUmakefile | 2 +- frida_mode/ts/lib/afl.ts | 24 ++++++++++++------------ include/envs.h | 2 +- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/frida_mode/README.md b/frida_mode/README.md index bf5cffec..50e3b8d7 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -170,11 +170,11 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent *** ``` +* `AFL_FRIDA_INST_INSN` - Generate instrumentation for conditional + instructions (e.g. `CMOV` instructions on x64). * `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled code. Code is considered to be JIT if the executable segment is not backed by a file. -* `AFL_FRIDA_INST_NO_INSN` - Don't generate instrumentation for conditional - instructions (e.g. `CMOV` instructions on x64). * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage instrumentation (the default where available). Required to use `AFL_FRIDA_INST_TRACE`. diff --git a/frida_mode/frida.map b/frida_mode/frida.map index e9afac1b..41220d4b 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -15,7 +15,7 @@ js_api_set_instrument_debug_file; js_api_set_instrument_jit; js_api_set_instrument_libraries; - js_api_set_instrument_no_instructions; + js_api_set_instrument_instructions; js_api_set_instrument_no_optimize; js_api_set_instrument_seed; js_api_set_instrument_trace; diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 4877f4fb..43560478 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -276,7 +276,7 @@ void instrument_config(void) { instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED", 0); instrument_coverage_unstable_filename = (getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE")); - instrument_coverage_insn = (getenv("AFL_FRIDA_INST_NO_INSN") == NULL); + instrument_coverage_insn = (getenv("AFL_FRIDA_INST_INSN") != NULL); instrument_debug_config(); instrument_coverage_config(); @@ -302,6 +302,8 @@ void instrument_init(void) { instrument_coverage_unstable_filename == NULL ? " " : instrument_coverage_unstable_filename); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "instructions:" cYEL " [%c]", + instrument_coverage_insn ? 'X' : ' '); if (instrument_tracing && instrument_optimize) { diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index c2d9a2d4..82b8e63d 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -113,6 +113,12 @@ class Afl { static setInstrumentEnableTracing() { Afl.jsApiSetInstrumentTrace(); } + /** + * See `AFL_FRIDA_INST_INSN` + */ + static setInstrumentInstructions() { + Afl.jsApiSetInstrumentInstructions(); + } /** * See `AFL_FRIDA_INST_JIT`. */ @@ -125,12 +131,6 @@ class Afl { static setInstrumentLibraries() { Afl.jsApiSetInstrumentLibraries(); } - /** - * See `AFL_FRIDA_INST_NO_INSN` - */ - static setInstrumentNoInstructions() { - Afl.jsApiSetInstrumentNoInstructions(); - } /** * See `AFL_FRIDA_INST_NO_OPTIMIZE` */ @@ -303,9 +303,9 @@ Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", [] Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]); Afl.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_coverage_file", "void", ["pointer"]); Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]); +Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []); Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []); Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []); -Afl.jsApiSetInstrumentNoInstructions = Afl.jsApiGetFunction("js_api_set_instrument_no_instructions", "void", []); Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []); Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]); Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 613747b8..89df7803 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -142,10 +142,10 @@ js_api_set_prefetch_backpatch_disable(void) { } -__attribute__((visibility("default"))) void -js_api_set_instrument_no_instructions(void) { +__attribute__((visibility("default"))) void js_api_set_instrument_instructions( + void) { - instrument_coverage_insn = FALSE; + instrument_coverage_insn = TRUE; } diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 84803453..d47d1c14 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -595,8 +595,6 @@ void ranges_init(void) { ranges_inst_jit ? 'X' : ' '); FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]", ranges_inst_libs ? 'X' : ' '); - FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]", - ranges_inst_libs ? 'X' : ' '); print_ranges("include", include_ranges); print_ranges("exclude", exclude_ranges); diff --git a/frida_mode/test/cmov/GNUmakefile b/frida_mode/test/cmov/GNUmakefile index 318b2ad0..96f1ae5b 100644 --- a/frida_mode/test/cmov/GNUmakefile +++ b/frida_mode/test/cmov/GNUmakefile @@ -46,6 +46,7 @@ $(DUMMY_DATA_FILE): | $(BUILD_DIR) dd if=/dev/zero bs=1048576 count=1 of=$@ frida: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) $(DUMMY_DATA_FILE) + AFL_FRIDA_INST_INSN=1 \ AFL_FRIDA_PERSISTENT_CNT=1000000 \ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ @@ -60,7 +61,6 @@ frida: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) $(DUMMY_DATA_FILE) $(TEST_CMOV_OBJ) $(DUMMY_DATA_FILE) frida_noinst: $(TEST_CMOV_OBJ) $(CMP_LOG_INPUT) $(DUMMY_DATA_FILE) - AFL_FRIDA_INST_NO_INSN=1 \ AFL_FRIDA_PERSISTENT_CNT=1000000 \ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts index 9d31370e..7999b661 100644 --- a/frida_mode/ts/lib/afl.ts +++ b/frida_mode/ts/lib/afl.ts @@ -135,6 +135,13 @@ class Afl { Afl.jsApiSetInstrumentTrace(); } + /** + * See `AFL_FRIDA_INST_INSN` + */ + public static setInstrumentInstructions(): void { + Afl.jsApiSetInstrumentInstructions(); + } + /** * See `AFL_FRIDA_INST_JIT`. */ @@ -149,13 +156,6 @@ class Afl { Afl.jsApiSetInstrumentLibraries(); } - /** - * See `AFL_FRIDA_INST_NO_INSN` - */ - public static setInstrumentNoInstructions(): void { - Afl.jsApiSetInstrumentNoInstructions(); - } - /** * See `AFL_FRIDA_INST_NO_OPTIMIZE` */ @@ -374,6 +374,11 @@ class Afl { "void", ["pointer"]); + private static readonly jsApiSetInstrumentInstructions = Afl.jsApiGetFunction( + "js_api_set_instrument_instructions", + "void", + []); + private static readonly jsApiSetInstrumentJit = Afl.jsApiGetFunction( "js_api_set_instrument_jit", "void", @@ -384,11 +389,6 @@ class Afl { "void", []); - private static readonly jsApiSetInstrumentNoInstructions = Afl.jsApiGetFunction( - "js_api_set_instrument_no_instructions", - "void", - []); - private static readonly jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction( "js_api_set_instrument_no_optimize", "void", diff --git a/include/envs.h b/include/envs.h index 2ab3a387..1f6d33e6 100644 --- a/include/envs.h +++ b/include/envs.h @@ -59,8 +59,8 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_EXCLUDE_RANGES", "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", + "AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", - "AFL_FRIDA_INST_NO_INSN", "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", -- cgit 1.4.1 From fcd06fa99ceeeb9769102357257be0c1e192641e Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 18 Feb 2022 08:20:51 +0000 Subject: Added test for running python --- frida_mode/test/python/GNUmakefile | 37 +++++++++++++++++++++++++++++++++++++ frida_mode/test/python/Makefile | 17 +++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 frida_mode/test/python/GNUmakefile create mode 100644 frida_mode/test/python/Makefile diff --git a/frida_mode/test/python/GNUmakefile b/frida_mode/test/python/GNUmakefile new file mode 100644 index 00000000..e4f7857b --- /dev/null +++ b/frida_mode/test/python/GNUmakefile @@ -0,0 +1,37 @@ +PWD:=$(shell pwd)/ +ROOT:=$(PWD)../../../ +BUILD_DIR:=$(PWD)build/ +TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/ +FRIDA_OUT:=$(BUILD_DIR)frida-out +QEMU_OUT:=$(BUILD_DIR)qemu-out + +.PHONY: all clean run qemu frida + +all: + make -C $(ROOT)frida_mode/ + +clean: + rm -rf $(BUILD_DIR) + +$(BUILD_DIR): + mkdir -p $@ + +$(TESTINSTR_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +run: + date + /usr/bin/python -c 'print("hi");' + date + +qemu: + date + $(ROOT)afl-qemu-trace \ + /usr/bin/python -c 'print("hi");' + date + +frida: + date + LD_PRELOAD=$(ROOT)afl-frida-trace.so \ + python -c 'print("hi");' + date diff --git a/frida_mode/test/python/Makefile b/frida_mode/test/python/Makefile new file mode 100644 index 00000000..e66cfdef --- /dev/null +++ b/frida_mode/test/python/Makefile @@ -0,0 +1,17 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +clean: + @gmake clean + +run: + @gmake run + +qemu: + @gmake qemu + +frida: + @gmake frida + + -- cgit 1.4.1 From fc7bf33fb144162ede0c2d56b91ad31143113f16 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 18 Feb 2022 08:21:36 +0000 Subject: Reserved used address space on dlclose to prevent re-use --- frida_mode/include/module.h | 11 +++++ frida_mode/src/main.c | 3 ++ frida_mode/src/module.c | 106 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 frida_mode/include/module.h create mode 100644 frida_mode/src/module.c diff --git a/frida_mode/include/module.h b/frida_mode/include/module.h new file mode 100644 index 00000000..b66f7feb --- /dev/null +++ b/frida_mode/include/module.h @@ -0,0 +1,11 @@ +#ifndef _MODULE_H +#define _MODULE_H + +#include "frida-gumjs.h" + +void module_config(void); + +void module_init(void); + +#endif + diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index d8521300..bb6e4109 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -21,6 +21,7 @@ #include "intercept.h" #include "js.h" #include "lib.h" +#include "module.h" #include "output.h" #include "persistent.h" #include "prefetch.h" @@ -197,6 +198,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) { instrument_config(); js_config(); lib_config(); + module_config(); output_config(); persistent_config(); prefetch_config(); @@ -214,6 +216,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) { entry_init(); instrument_init(); lib_init(); + module_init(); persistent_init(); prefetch_init(); seccomp_init(); diff --git a/frida_mode/src/module.c b/frida_mode/src/module.c new file mode 100644 index 00000000..65b394cd --- /dev/null +++ b/frida_mode/src/module.c @@ -0,0 +1,106 @@ +#include "intercept.h" +#include "module.h" +#include "util.h" + +#if defined(__linux__) + #include + #include +#endif + +static guint page_size = 0; +static gboolean handle_dlclose = FALSE; + +void module_config(void) { + +#if defined(__linux__) + handle_dlclose = (getenv("AFL_FRIDA_NO_MODULE") == NULL); +#else + FWARNF("AFL_FRIDA_MODULE not supported"); +#endif + +} + +typedef struct { + + GumMemoryRange range; + GumPageProtection protection; + GumFileMapping file; + +} gum_range_t; + +gboolean found_range(const GumRangeDetails *details, gpointer user_data) { + + gum_range_t range = {0}; + GArray * ranges = (GArray *)user_data; + + range.range = *details->range; + range.protection = details->protection; + if (details->file != NULL) { range.file = *details->file; } + + g_array_append_val(ranges, range); + return FALSE; + +} + +#if defined(__linux__) +static int on_dlclose(void *handle) { + + GArray * ranges = NULL; + struct link_map *lm = NULL; + gum_range_t * range = NULL; + GumAddress base; + GumAddress limit; + gpointer mem; + + if (dlinfo(handle, RTLD_DI_LINKMAP, &lm) < 0) { + + FFATAL("Failed to dlinfo: %s", dlerror()); + + } + + FVERBOSE("on_dlclose: %s", lm->l_name); + + ranges = g_array_new(FALSE, TRUE, sizeof(gum_range_t)); + gum_module_enumerate_ranges(lm->l_name, GUM_PAGE_EXECUTE, found_range, + ranges); + + int ret = dlclose(handle); + if (ret != 0) { + + FWARNF("dlclose returned: %d (%s)", ret, dlerror()); + return ret; + + } + + for (guint i = 0; i < ranges->len; i++) { + + range = &g_array_index(ranges, gum_range_t, i); + base = range->range.base_address; + limit = base + range->range.size; + FVERBOSE("Reserving range: 0x%016lx, 0x%016lX", base, limit); + mem = gum_memory_allocate(GSIZE_TO_POINTER(base), range->range.size, + page_size, GUM_PAGE_NO_ACCESS); + if (mem == NULL) { FATAL("Failed to allocate %p (%d)", mem, errno); } + + } + + g_array_free(ranges, TRUE); + return 0; + +} + +#endif + +void module_init(void) { + + FOKF(cBLU "Module" cRST " - " cYEL " [%c]", handle_dlclose ? 'X' : ' '); + +#if defined(__linux__) + if (!handle_dlclose) { return; } + + page_size = gum_query_page_size(); + intercept_hook(dlclose, on_dlclose, NULL); +#endif + +} + -- cgit 1.4.1 From 852c036cae97113daac3ba5a791554bbbd5c8903 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 18 Feb 2022 17:39:21 +0000 Subject: Add global caching of block translation to instrumentation --- frida_mode/README.md | 30 +- frida_mode/frida.map | 2 + frida_mode/include/instrument.h | 8 + frida_mode/include/util.h | 8 + frida_mode/src/instrument/instrument.c | 4 + frida_mode/src/instrument/instrument_arm32.c | 25 ++ frida_mode/src/instrument/instrument_arm64.c | 22 ++ frida_mode/src/instrument/instrument_x64.c | 9 +- frida_mode/src/instrument/instrument_x64_cache.c | 435 +++++++++++++++++++++++ frida_mode/src/instrument/instrument_x86.c | 25 ++ frida_mode/src/js/api.js | 15 + frida_mode/src/js/js_api.c | 13 + frida_mode/test/cache/GNUmakefile | 97 +++++ frida_mode/test/cache/Makefile | 22 ++ frida_mode/test/cache/cache.c | 115 ++++++ frida_mode/test/vorbis/GNUmakefile | 8 +- frida_mode/ts/lib/afl.ts | 25 ++ include/envs.h | 2 + 18 files changed, 846 insertions(+), 19 deletions(-) create mode 100644 frida_mode/src/instrument/instrument_x64_cache.c create mode 100644 frida_mode/test/cache/GNUmakefile create mode 100644 frida_mode/test/cache/Makefile create mode 100644 frida_mode/test/cache/cache.c diff --git a/frida_mode/README.md b/frida_mode/README.md index 50e3b8d7..4025dba5 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -151,25 +151,25 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent * `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks and their instrumented counterparts during block compilation. - ``` - *** +Creating block for 0x7ffff7953313: + 0x7ffff7953313 mov qword ptr [rax], 0 + 0x7ffff795331a add rsp, 8 + 0x7ffff795331e ret - Creating block for 0x7ffff7953313: - 0x7ffff7953313 mov qword ptr [rax], 0 - 0x7ffff795331a add rsp, 8 - 0x7ffff795331e ret +Generated block 0x7ffff75e98e2 + 0x7ffff75e98e2 mov qword ptr [rax], 0 + 0x7ffff75e98e9 add rsp, 8 + 0x7ffff75e98ed lea rsp, [rsp - 0x80] + 0x7ffff75e98f5 push rcx + 0x7ffff75e98f6 movabs rcx, 0x7ffff795331e + 0x7ffff75e9900 jmp 0x7ffff75e9384 - Generated block 0x7ffff75e98e2 - 0x7ffff75e98e2 mov qword ptr [rax], 0 - 0x7ffff75e98e9 add rsp, 8 - 0x7ffff75e98ed lea rsp, [rsp - 0x80] - 0x7ffff75e98f5 push rcx - 0x7ffff75e98f6 movabs rcx, 0x7ffff795331e - 0x7ffff75e9900 jmp 0x7ffff75e9384 *** ``` - +* `AFL_FRIDA_INST_CACHE_SIZE` - Set the size of the instrumentation cache used +as a look-up table to cache real to instrumented address block translations. +Default is 256Mb. * `AFL_FRIDA_INST_INSN` - Generate instrumentation for conditional instructions (e.g. `CMOV` instructions on x64). * `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled @@ -178,6 +178,8 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage instrumentation (the default where available). Required to use `AFL_FRIDA_INST_TRACE`. +* `AFL_FRIDA_INST_NO_CACHE` - Don't use a look-up table to cache real to +instrumented address block translations. * `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will report instrumented blocks back to the parent so that it can also instrument them and they be inherited by the next child on fork, implies diff --git a/frida_mode/frida.map b/frida_mode/frida.map index 41220d4b..6726dbbd 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -9,8 +9,10 @@ js_api_done; js_api_error; js_api_set_backpatch_disable; + js_api_set_cache_disable; js_api_set_debug_maps; js_api_set_entrypoint; + js_api_set_instrument_cache_size; js_api_set_instrument_coverage_file; js_api_set_instrument_debug_file; js_api_set_instrument_jit; diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index 20312a4b..4a54ee22 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -22,6 +22,9 @@ extern uint32_t __afl_map_size; extern __thread guint64 *instrument_previous_pc_addr; +extern gboolean instrument_cache_enabled; +extern gsize instrument_cache_size; + void instrument_config(void); void instrument_init(void); @@ -59,5 +62,10 @@ void instrument_on_fork(void); guint64 instrument_get_offset_hash(GumAddress current_rip); +void instrument_cache_config(void); +void instrument_cache_init(void); +void instrument_cache_insert(gpointer real_address, gpointer code_address); +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output); + #endif diff --git a/frida_mode/include/util.h b/frida_mode/include/util.h index bd37687c..b04e0a26 100644 --- a/frida_mode/include/util.h +++ b/frida_mode/include/util.h @@ -5,6 +5,14 @@ #include "debug.h" +#ifndef MAP_FIXED_NOREPLACE + #ifdef MAP_EXCL + #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED + #else + #define MAP_FIXED_NOREPLACE MAP_FIXED + #endif +#endif + #define UNUSED_PARAMETER(x) (void)(x) #define IGNORED_RETURN(x) (void)!(x) diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 43560478..003c3d00 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -249,6 +249,8 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } + instrument_cache(instr, output); + if (js_stalker_callback(instr, begin, excluded, output)) { gum_stalker_iterator_keep(iterator); @@ -282,6 +284,7 @@ void instrument_config(void) { instrument_coverage_config(); asan_config(); cmplog_config(); + instrument_cache_config(); } @@ -392,6 +395,7 @@ void instrument_init(void) { instrument_coverage_init(); instrument_coverage_optimize_init(); instrument_debug_init(); + instrument_cache_init(); } diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 705faa64..80f3c26d 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -5,6 +5,9 @@ #if defined(__arm__) +gboolean instrument_cache_enabled = FALSE; +gsize instrument_cache_size = 0; + gboolean instrument_is_coverage_optimize_supported(void) { return false; @@ -55,5 +58,27 @@ gpointer instrument_cur(GumStalkerOutput *output) { } +void instrument_cache_config(void) { + +} + +void instrument_cache_init(void) { + +} + +void instrument_cache_insert(gpointer real_address, gpointer code_address) { + + UNUSED_PARAMETER(real_address); + UNUSED_PARAMETER(code_address); + +} + +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + #endif diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 4abc0625..eb736386 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -379,5 +379,27 @@ gpointer instrument_cur(GumStalkerOutput *output) { } +void instrument_cache_config(void) { + +} + +void instrument_cache_init(void) { + +} + +void instrument_cache_insert(gpointer real_address, gpointer code_address) { + + UNUSED_PARAMETER(real_address); + UNUSED_PARAMETER(code_address); + +} + +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + #endif diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index 4b1a2d68..0bff3e02 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -202,10 +202,17 @@ static void instrument_coverage_switch(GumStalkerObserver *self, } - if (op[0].type != X86_OP_IMM) { return; } + if (op[0].type != X86_OP_IMM) { + + instrument_cache_insert(start_address, *target); + return; + + } break; case X86_INS_RET: + instrument_cache_insert(start_address, + (guint8 *)*target + sizeof(afl_log_code)); break; default: return; diff --git a/frida_mode/src/instrument/instrument_x64_cache.c b/frida_mode/src/instrument/instrument_x64_cache.c new file mode 100644 index 00000000..3ea4421a --- /dev/null +++ b/frida_mode/src/instrument/instrument_x64_cache.c @@ -0,0 +1,435 @@ +#include +#include + +#include "instrument.h" +#include "util.h" + +#if defined(__x86_64__) + + #define INVALID 1 + #define DEFAULT_CACHE_SIZE (256ULL << 20) + +gboolean instrument_cache_enabled = TRUE; +gsize instrument_cache_size = DEFAULT_CACHE_SIZE; +static gpointer *map_base = MAP_FAILED; + +void instrument_cache_config(void) { + + instrument_cache_enabled = (getenv("AFL_FRIDA_INST_NO_CACHE") == NULL); + + if (getenv("AFL_FRIDA_INST_CACHE_SIZE") != NULL) { + + if (!instrument_cache_enabled) { + + FFATAL( + "AFL_FRIDA_INST_CACHE_SIZE incomatible with " + "AFL_FRIDA_INST_NO_CACHE"); + + } + + instrument_cache_size = + util_read_address("AFL_FRIDA_INST_CACHE_SIZE", DEFAULT_CACHE_SIZE); + util_log2(instrument_cache_size); + + } + +} + +void instrument_cache_init(void) { + + FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache:" cYEL " [%c]", + instrument_cache_enabled ? 'X' : ' '); + if (!instrument_cache_enabled) { return; } + + FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache size:" cYEL " [0x%016lX]", + instrument_cache_size); + + const struct rlimit data_limit = {.rlim_cur = RLIM_INFINITY, + .rlim_max = RLIM_INFINITY}; + + if (setrlimit(RLIMIT_AS, &data_limit) != 0) { + + FFATAL("Failed to setrlimit: %d", errno); + + } + + map_base = + gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size, + GUM_PAGE_READ | GUM_PAGE_WRITE); + if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); } + + FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]", + GUM_ADDRESS(map_base)); + +} + +static gpointer *instrument_cache_get_addr(gpointer addr) { + + gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1; + return &map_base[GPOINTER_TO_SIZE(addr) & mask]; + +} + +void instrument_cache_insert(gpointer real_address, gpointer code_address) { + + if (!instrument_cache_enabled) { return; } + + gpointer *target = instrument_cache_get_addr(real_address); + if (*target == code_address) { + + return; + + } else if (*target == NULL) { + + *target = code_address; + + } else { + + *target = GSIZE_TO_POINTER(INVALID); + + } + +} + +static gboolean instrument_cache_relocate(GumAddress old_pc, GumAddress new_pc, + gint32 old_offset, + gint32 *new_offset) { + + guint64 old_target = old_pc + old_offset; + gint64 relocated = old_target - new_pc; + + if (relocated > G_MAXINT32 || relocated < G_MININT32) { return FALSE; } + + *new_offset = relocated; + return TRUE; + +} + +static void instrument_cache_rewrite_branch_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + cs_x86 * x86 = &instr->detail->x86; + guint8 modified[sizeof(instr->bytes)] = {0}; + guint8 offset = 0; + guint8 skip = 0; + + g_assert(sizeof(x86->prefix) == 4); + g_assert(sizeof(x86->opcode) == 4); + + /* + * If the target is simply RAX, we can skip writing the code to load the + * RIP + */ + if (x86->operands[0].type == X86_OP_REG || + x86->operands[0].reg == X86_REG_RAX) { + + return; + + } + + /* Write the prefix */ + for (gsize i = 0; i < sizeof(x86->prefix); i++) { + + if (x86->prefix[i] != 0) { + + if (x86->prefix[i] == 0xf2) { + + skip++; + + } else { + + modified[offset++] = x86->prefix[i]; + skip++; + + } + + } + + } + + /* Write the REX */ + if (x86->rex == 0) { + + /* + * CALL (near) and JMP (near) default to 64-bit operands, MOV does not, + * write REX.W + */ + modified[offset++] = 0x48; + + } else { + + if ((x86->rex & 0xF8) != 0x40) { + + FATAL("Unexpected REX byte: 0x%02x", x86->rex); + + } + + modified[offset++] = x86->rex | 0x08; + skip++; + + } + + /* + * CALL is FF /2, JMP is FF /4. The remaining op-code fields should thus be + * unused + */ + + if (x86->opcode[0] != 0xFF || x86->opcode[1] != 0x00 || + x86->opcode[2] != 0x00 || x86->opcode[3] != 0x00) { + + FFATAL("Unexpected Op-code: 0x%02x 0x%02x 0x%02x 0x%02x", x86->opcode[0], + x86->opcode[1], x86->opcode[2], x86->opcode[3]); + + } + + /* The reg field of the ModRM should be set to 2 for CALL and 4 for JMP */ + guint8 reg = (x86->modrm >> 3) & 7; + if (reg != 0x4 && reg != 0x2) { + + FFATAL("Unexpected Reg: 0x%02x, ModRM: 0x%02x", reg, x86->modrm); + + } + + /* MOV */ + modified[offset++] = 0x8b; + skip++; + + /* Clear the reg field (RAX) */ + modified[offset++] = x86->modrm & 0xc7; + skip++; + + /* Operands */ + guint8 op_len = instr->size - skip; + + /* If our branch was RIP relative, we'll need to fix-up the offset */ + if (x86->operands[0].type == X86_OP_MEM && + x86->operands[0].mem.base == X86_REG_RIP) { + + /* RIP relative offsets should be 32-bits */ + if (op_len != sizeof(gint32)) { + + FFATAL("Unexpected operand length: %d\n", op_len); + + } + + gint32 old_offset = *(gint32 *)&instr->bytes[skip]; + gint32 new_offset = 0; + if (instrument_cache_relocate(instr->address, cw->pc, old_offset, + &new_offset)) { + + gint32 *output = (gint32 *)&modified[offset]; + *output = new_offset; + offset += sizeof(gint32); + + } else { + + GumAddress target = instr->address + old_offset; + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, target); + gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_RAX, GUM_REG_RAX); + return; + + } + + } else { + + for (int i = 0; i < op_len; i++) { + + guint8 val = instr->bytes[i + skip]; + modified[offset++] = val; + + } + + } + + gum_x86_writer_put_bytes(cw, modified, offset); + +} + +static void instrument_cache_write_push_frame(GumX86Writer *cw) { + + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))), + GUM_REG_XAX); + gum_x86_writer_put_lahf(cw); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer))), + GUM_REG_XAX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer))), + GUM_REG_XBX); + +} + +static void instrument_cache_write_pop_frame(GumX86Writer *cw) { + + gum_x86_writer_put_mov_reg_reg_offset_ptr( + cw, GUM_REG_XBX, GUM_REG_XSP, + -(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer)))); + gum_x86_writer_put_mov_reg_reg_offset_ptr( + cw, GUM_REG_XAX, GUM_REG_XSP, + -(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer)))); + gum_x86_writer_put_sahf(cw); + gum_x86_writer_put_mov_reg_reg_offset_ptr( + cw, GUM_REG_XAX, GUM_REG_XSP, + -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer)))); + +} + +static void instrument_cache_write_lookup(GumX86Writer *cw) { + + /* &map_base[GPOINTER_TO_SIZE(addr) & MAP_MASK]; */ + + gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1; + gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_XBX, mask); + gum_x86_writer_put_and_reg_reg(cw, GUM_REG_XAX, GUM_REG_XBX); + gum_x86_writer_put_shl_reg_u8(cw, GUM_REG_XAX, util_log2(sizeof(gpointer))); + gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_XBX, GPOINTER_TO_SIZE(map_base)); + gum_x86_writer_put_add_reg_reg(cw, GUM_REG_XAX, GUM_REG_XBX); + + /* Read the return address lookup */ + gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_XAX, GUM_REG_XAX); + +} + +void instrument_cache_jmp_call(const cs_insn *instr, GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + cs_x86 * x86 = &instr->detail->x86; + + if (x86->op_count != 1) { FFATAL("Unexpected operand count"); } + + if (x86->operands[0].type == X86_OP_IMM) { return; } + + gconstpointer null = cw->code; + + instrument_cache_write_push_frame(cw); + + /* + * We are about to re-write the CALL or JMP instruction, but replace the + * op-code with that for a MOV into RAX. Since we are keeping the operand from + * the JMP exactly the same, it is imperative that the target register state + * be exactly the same as how the target left it. Since `LAHF` spoils `RAX` we + * must restore it from the stack. We also must avoid adjusting `RSP`, so we + * use `MOV` instructions to store our context into the stack beyond the + * red-zone. + */ + gum_x86_writer_put_mov_reg_reg_offset_ptr( + cw, GUM_REG_XAX, GUM_REG_XSP, + -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer)))); + + instrument_cache_rewrite_branch_insn(instr, output); + + instrument_cache_write_lookup(cw); + + /* Test if its set*/ + gum_x86_writer_put_cmp_reg_i32(cw, GUM_REG_XAX, INVALID); + gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY); + + /* If it's set, then stash the address beyond the red-zone */ + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer))), + GUM_REG_XAX); + + if (instr->id == X86_INS_JMP) { + + instrument_cache_write_pop_frame(cw); + gum_x86_writer_put_jmp_reg_offset_ptr( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer)))); + + } else { + + gum_x86_writer_put_mov_reg_address( + cw, GUM_REG_XAX, GUM_ADDRESS(instr->address + instr->size)); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_XSP, + -sizeof(gpointer), GUM_REG_XAX); + + instrument_cache_write_pop_frame(cw); + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_XSP, GUM_REG_XSP, + -sizeof(gpointer)); + gum_x86_writer_put_jmp_reg_offset_ptr( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + ((4 - 1) * sizeof(gpointer)))); + + } + + /* Tidy up our mess and let FRIDA handle it */ + gum_x86_writer_put_label(cw, null); + instrument_cache_write_pop_frame(cw); + +} + +void instrument_cache_ret(const cs_insn *instr, GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + cs_x86 * x86 = &instr->detail->x86; + guint16 n = 0; + + if (x86->op_count != 0) { + + if (x86->operands[0].type != X86_OP_IMM) { + + FFATAL("Unexpected operand type"); + + } + + n = x86->operands[0].imm; + + } + + gconstpointer null = cw->code; + + instrument_cache_write_push_frame(cw); + + gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_XAX, GUM_REG_XSP); + + instrument_cache_write_lookup(cw); + + /* Test if its set*/ + gum_x86_writer_put_cmp_reg_i32(cw, GUM_REG_XAX, INVALID); + gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY); + + /* If it's set, then overwrite our return address and return */ + gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_XSP, GUM_REG_XAX); + instrument_cache_write_pop_frame(cw); + + if (n == 0) { + + gum_x86_writer_put_ret(cw); + + } else { + + gum_x86_writer_put_ret_imm(cw, n); + + } + + /* Tidy up our mess and let FRIDA handle it */ + gum_x86_writer_put_label(cw, null); + instrument_cache_write_pop_frame(cw); + +} + +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { + + if (!instrument_cache_enabled) { return; } + + switch (instr->id) { + + case X86_INS_RET: + instrument_cache_ret(instr, output); + break; + + case X86_INS_CALL: + case X86_INS_JMP: + instrument_cache_jmp_call(instr, output); + break; + + default: + return; + + } + +} + +#endif + diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index 916cd0e2..6a899248 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -6,6 +6,9 @@ #if defined(__i386__) +gboolean instrument_cache_enabled = FALSE; +gsize instrument_cache_size = 0; + static GHashTable *coverage_blocks = NULL; #pragma pack(push, 1) @@ -242,5 +245,27 @@ gpointer instrument_cur(GumStalkerOutput *output) { } +void instrument_cache_config(void) { + +} + +void instrument_cache_init(void) { + +} + +void instrument_cache_insert(gpointer real_address, gpointer code_address) { + + UNUSED_PARAMETER(real_address); + UNUSED_PARAMETER(code_address); + +} + +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + #endif diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 82b8e63d..c1c9d36f 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -68,6 +68,12 @@ class Afl { static setBackpatchDisable() { Afl.jsApiSetBackpatchDisable(); } + /** + * See `AFL_FRIDA_INST_NO_CACHE`. + */ + static setCacheDisable() { + Afl.jsApiSetCacheDisable(); + } /** * See `AFL_FRIDA_DEBUG_MAPS`. */ @@ -91,6 +97,13 @@ class Afl { static setInMemoryFuzzing() { Afl.jsApiAflSharedMemFuzzing.writeInt(1); } + /** + * See `AFL_FRIDA_INST_CACHE_SIZE`. This function takes a single `number` + * as an argument. + */ + static setInstrumentCacheSize(size) { + Afl.jsApiSetInstrumentCacheSize(size); + } /** * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string` * as an argument. @@ -299,8 +312,10 @@ Afl.jsApiAflSharedMemFuzzing = Afl.jsApiGetSymbol("__afl_sharedmem_fuzzing"); Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []); Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]); Afl.jsApiSetBackpatchDisable = Afl.jsApiGetFunction("js_api_set_backpatch_disable", "void", []); +Afl.jsApiSetCacheDisable = Afl.jsApiGetFunction("js_api_set_cache_disable", "void", []); Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []); Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]); +Afl.jsApiSetInstrumentCacheSize = Afl.jsApiGetFunction("js_api_set_instrument_cache_size", "void", ["size_t"]); Afl.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_coverage_file", "void", ["pointer"]); Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]); Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 89df7803..7cc8ffc7 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -262,6 +262,19 @@ __attribute__((visibility("default"))) void js_api_set_stalker_adjacent_blocks( } +__attribute__((visibility("default"))) void js_api_set_cache_disable(void) { + + instrument_cache_enabled = FALSE; + +} + +__attribute__((visibility("default"))) void js_api_set_instrument_cache_size( + gsize size) { + + instrument_cache_size = size; + +} + __attribute__((visibility("default"))) void js_api_set_js_main_hook( const js_main_hook_t hook) { diff --git a/frida_mode/test/cache/GNUmakefile b/frida_mode/test/cache/GNUmakefile new file mode 100644 index 00000000..12736a3f --- /dev/null +++ b/frida_mode/test/cache/GNUmakefile @@ -0,0 +1,97 @@ +PWD:=$(shell pwd)/ +ROOT:=$(PWD)../../../ +BUILD_DIR:=$(PWD)build/ + +TEST_CACHE_SRC:=$(PWD)cache.c +TEST_CACHE_OBJ:=$(BUILD_DIR)cache + +TEST_DATA_DIR:=$(BUILD_DIR)in/ +CACHE_INPUT:=$(TEST_DATA_DIR)in +QEMU_OUT:=$(BUILD_DIR)qemu-out +FRIDA_OUT:=$(BUILD_DIR)frida-out + +ADDR_BIN:=$(ROOT)frida_mode/build/addr +GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh + +AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so + +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_CACHE_OBJ) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) + +DUMMY_DATA_FILE:=$(BUILD_DIR)dummy.dat + +.PHONY: all 32 clean frida frida_noinst debug format + +all: $(TEST_CACHE_OBJ) + make -C $(ROOT)frida_mode/ + +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + +$(BUILD_DIR): + mkdir -p $@ + +$(TEST_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(CACHE_INPUT): | $(TEST_DATA_DIR) + echo -n "ABC" > $@ + +$(TEST_CACHE_OBJ): $(TEST_CACHE_SRC) | $(BUILD_DIR) + $(CC) -g $(CFLAGS) $(LDFLAGS) $< -o $@ + +########## DUMMY ####### + +$(DUMMY_DATA_FILE): | $(BUILD_DIR) + dd if=/dev/zero bs=1048576 count=1 of=$@ + +frida: $(TEST_CACHE_OBJ) $(CACHE_INPUT) $(DUMMY_DATA_FILE) + AFL_FRIDA_INST_INSN=1 \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -Z \ + -t 10000+ \ + -- \ + $(TEST_CACHE_OBJ) $(DUMMY_DATA_FILE) + +frida_nocache: $(TEST_CACHE_OBJ) $(CACHE_INPUT) $(DUMMY_DATA_FILE) + AFL_FRIDA_INST_NO_CACHE=1 \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -Z \ + -- \ + $(TEST_CACHE_OBJ) $(DUMMY_DATA_FILE) + +debug: $(TEST_CACHE_OBJ) $(CACHE_INPUT) + gdb \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set disassembly-flavor intel' \ + --ex 'r $(CACHE_INPUT)' \ + --args $(TEST_CACHE_OBJ) $(CACHE_INPUT) + +show: $(TEST_CACHE_OBJ) $(CACHE_INPUT) + gdb \ + --ex "set disassembly-flavor intel" \ + --ex "set confirm off" \ + --ex "symbol-file $(TEST_CACHE_OBJ)" \ + --ex "x/50i LLVMFuzzerTestOneInput" \ + --ex "r" \ + --args $(TEST_CACHE_OBJ) $(CACHE_INPUT) + +clean: + rm -rf $(BUILD_DIR) + +format: + cd $(ROOT) && echo $(TEST_CACHE_SRC) | xargs -L1 ./.custom-format.py -i diff --git a/frida_mode/test/cache/Makefile b/frida_mode/test/cache/Makefile new file mode 100644 index 00000000..961a284c --- /dev/null +++ b/frida_mode/test/cache/Makefile @@ -0,0 +1,22 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + +frida: + @gmake frida + +frida_nocache: + @gmake frida_nocache + +debug: + @gmake debug + +clean: + @gmake clean + +format: + @gmake format diff --git a/frida_mode/test/cache/cache.c b/frida_mode/test/cache/cache.c new file mode 100644 index 00000000..b4102205 --- /dev/null +++ b/frida_mode/test/cache/cache.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include + +void LLVMFuzzerTestOneInput(char *buf, int len); + +__asm__ ( + "LLVMFuzzerTestOneInput:\n" + ".func LLVMFuzzerTestOneInput\n" + ".global LLVMFuzzerTestOneInput\n" + " jmpq *jmp_offset(%rip)\n" + " nop\n" + " nop\n" + "call_target:\n" + " ret\n" + " nop\n" + " nop\n" + "jmp_target:\n" + " callq *call_offset(%rip)\n" + " nop\n" + " nop\n" + " leaq rax_offset(%rip), %rax\n" + " jmp (%rax)\n" + " nop\n" + " ud2\n" + " nop\n" + "rax_target:\n" + " ret\n" + "\n" + "\n" + ".global jmp_offset\n" + ".p2align 3\n" + "jmp_offset:\n" + " .quad jmp_target\n" + "call_offset:\n" + " .quad call_target\n" + "rax_offset:\n" + " .quad rax_target\n" +); + +int main(int argc, char **argv) { + + char * file; + int fd = -1; + off_t len; + char * buf = NULL; + size_t n_read; + int result = -1; + + if (argc != 2) { return 1; } + + do { + + file = argv[1]; + + dprintf(STDERR_FILENO, "Running: %s\n", file); + + fd = open(file, O_RDONLY); + if (fd < 0) { + + perror("open"); + break; + + } + + len = lseek(fd, 0, SEEK_END); + if (len < 0) { + + perror("lseek (SEEK_END)"); + break; + + } + + if (lseek(fd, 0, SEEK_SET) != 0) { + + perror("lseek (SEEK_SET)"); + break; + + } + + buf = (char *)malloc(len); + if (buf == NULL) { + + perror("malloc"); + break; + + } + + n_read = read(fd, buf, len); + if (n_read != len) { + + perror("read"); + break; + + } + + dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read); + + LLVMFuzzerTestOneInput(buf, len); + dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read); + + result = 0; + + } while (false); + + if (buf != NULL) { free(buf); } + + if (fd != -1) { close(fd); } + + return result; + +} + diff --git a/frida_mode/test/vorbis/GNUmakefile b/frida_mode/test/vorbis/GNUmakefile index 9cce6c9e..4cb5d417 100644 --- a/frida_mode/test/vorbis/GNUmakefile +++ b/frida_mode/test/vorbis/GNUmakefile @@ -125,7 +125,7 @@ vorbis: $(VORBIS_LIB) ########## HARNESS ####### $(DECODE_SRC): - wget -O $@ $(DECODE_URL) + wget -O $@ $(DECODE_URL) || curl -L -o $@ $(DECODE_URL) $(DECODE_OBJ): $(DECODE_SRC) $(CXX) -o $@ -c $< -I$(VORBIS_DIR)include/ -I$(OGG_DIR)include/ @@ -135,7 +135,7 @@ decode: $(DECODE_OBJ) ########## HARNESS ####### $(HARNESS_SRC): - wget -O $@ $(HARNESS_URL) + wget -O $@ $(HARNESS_URL) || curl -L -o $@ $(HARNESS_URL) $(HARNESS_OBJ): $(HARNESS_SRC) $(CC) -o $@ -c $< @@ -165,8 +165,8 @@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) ###### TEST DATA ####### -$(TEST_DATA_FILE): $(TEST_DATA_DIR) - wget -O $@ $(TEST_DATA_SRC) +$(TEST_DATA_FILE): | $(TEST_DATA_DIR) + wget -O $@ $(TEST_DATA_SRC) || curl -L -o $@ $(TEST_DATA_SRC) clean: rm -rf $(BUILD_DIR) diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts index 7999b661..a858f074 100644 --- a/frida_mode/ts/lib/afl.ts +++ b/frida_mode/ts/lib/afl.ts @@ -84,6 +84,13 @@ class Afl { Afl.jsApiSetBackpatchDisable(); } + /** + * See `AFL_FRIDA_INST_NO_CACHE`. + */ + public static setCacheDisable(): void { + Afl.jsApiSetCacheDisable(); + } + /** * See `AFL_FRIDA_DEBUG_MAPS`. */ @@ -110,6 +117,14 @@ class Afl { Afl.jsApiAflSharedMemFuzzing.writeInt(1); } + /** + * See `AFL_FRIDA_INST_CACHE_SIZE`. This function takes a single `number` + * as an argument. + */ + public static setInstrumentCacheSize(size: number): void { + Afl.jsApiSetInstrumentCacheSize(size); + } + /** * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string` * as an argument. @@ -354,6 +369,11 @@ class Afl { "void", []); + private static readonly jsApiSetCacheDisable = Afl.jsApiGetFunction( + "js_api_set_cache_disable", + "void", + []); + private static readonly jsApiSetDebugMaps = Afl.jsApiGetFunction( "js_api_set_debug_maps", "void", @@ -364,6 +384,11 @@ class Afl { "void", ["pointer"]); + private static readonly jsApiSetInstrumentCacheSize = Afl.jsApiGetFunction( + "js_api_set_instrument_cache_size", + "void", + ["size_t"]); + private static readonly jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction( "js_api_set_instrument_coverage_file", "void", diff --git a/include/envs.h b/include/envs.h index 1f6d33e6..fc276f8f 100644 --- a/include/envs.h +++ b/include/envs.h @@ -57,10 +57,12 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_DEBUG_MAPS", "AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES", + "AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", "AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", + "AFL_FRIDA_INST_NO_CACHE", "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", -- cgit 1.4.1 From 92db44363543b510b7737d51ea2b9a4e790bfb07 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 20 Feb 2022 19:51:43 +0100 Subject: Revert "remove new llvm pass manager :(" This reverts commit 55ed2a443c5c61baba37415d4087164454d8a2a8. --- instrumentation/afl-llvm-dict2file.so.cc | 11 ++- instrumentation/afl-llvm-pass.so.cc | 91 +++++++++++++++++- instrumentation/cmplog-instructions-pass.cc | 37 +++++++- instrumentation/compare-transform-pass.so.cc | 104 +++++++++++++++++++-- instrumentation/split-compares-pass.so.cc | 132 ++++++++++++++++++++++++--- instrumentation/split-switches-pass.so.cc | 107 ++++++++++++++++++++-- src/afl-cc.c | 42 ++++++++- 7 files changed, 482 insertions(+), 42 deletions(-) diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 39124660..440b9428 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -589,7 +589,6 @@ bool AFLdict2filePass::runOnModule(Module &M) { if (optLen < 2) { continue; } if (literalLength + 1 == optLen) { // add null byte - thestring.append("\0", 1); } @@ -612,11 +611,17 @@ bool AFLdict2filePass::runOnModule(Module &M) { } */ - if (!isStdString && thestring.find('\0', 0) != std::string::npos) { + + if (!isStdString) { // ensure we do not have garbage size_t offset = thestring.find('\0', 0); - if (offset + 1 < optLen) optLen = offset + 1; + if (offset && offset < optLen && offset + 1 < optLen) { + + optLen = offset + 1; + + } + thestring = thestring.substr(0, optLen); } diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index 5246ba08..32045935 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -45,12 +45,21 @@ typedef long double max_align_t; #endif #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) @@ -68,17 +77,30 @@ using namespace llvm; namespace { +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +class AFLCoverage : public PassInfoMixin { + + public: + AFLCoverage() { + +#else class AFLCoverage : public ModulePass { public: static char ID; AFLCoverage() : ModulePass(ID) { +#endif + initInstrumentList(); } +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else bool runOnModule(Module &M) override; +#endif protected: uint32_t ngram_size = 0; @@ -92,7 +114,55 @@ class AFLCoverage : public ModulePass { } // namespace +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if 1 + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(AFLCoverage()); + + }); + + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + + if (Name == "AFLCoverage") { + + MPM.addPass(AFLCoverage()); + return true; + + } else { + + return false; + + } + + }); + + #endif + + }}; + +} + +#else + char AFLCoverage::ID = 0; +#endif /* needed up to 3.9.0 */ #if LLVM_VERSION_MAJOR == 3 && \ @@ -118,8 +188,15 @@ uint64_t PowerOf2Ceil(unsigned in) { (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) #define AFL_HAVE_VECTOR_INTRINSICS 1 #endif + +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) { + +#else bool AFLCoverage::runOnModule(Module &M) { +#endif + LLVMContext &C = M.getContext(); IntegerType *Int8Ty = IntegerType::getInt8Ty(C); @@ -133,6 +210,10 @@ bool AFLCoverage::runOnModule(Module &M) { u32 rand_seed; unsigned int cur_loc = 0; +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif + /* Setup random() so we get Actually Random(TM) outputs from AFL_R() */ gettimeofday(&tv, &tz); rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); @@ -997,10 +1078,15 @@ bool AFLCoverage::runOnModule(Module &M) { } +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + return PA; +#else return true; +#endif } +#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerAFLPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -1013,4 +1099,5 @@ static RegisterStandardPasses RegisterAFLPass( static RegisterStandardPasses RegisterAFLPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass); +#endif diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 310f5585..b6d51ef3 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -28,11 +28,16 @@ #include "llvm/Config/llvm-config.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#if LLVM_MAJOR >= 11 +// #include "llvm/Passes/PassPlugin.h" +// #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" +#endif #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" @@ -55,6 +60,15 @@ using namespace llvm; namespace { +#if LLVM_MAJOR >= 11 /* use new pass manager */ +class CmpLogInstructions : public PassInfoMixin { + public: + CmpLogInstructions() { + + initInstrumentList(); + + } +#else class CmpLogInstructions : public ModulePass { public: @@ -64,7 +78,11 @@ class CmpLogInstructions : public ModulePass { initInstrumentList(); } +#endif +#if LLVM_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR >= 4 @@ -77,6 +95,7 @@ class CmpLogInstructions : public ModulePass { return "cmplog instructions"; } +#endif private: bool hookInstrs(Module &M); @@ -85,7 +104,9 @@ class CmpLogInstructions : public ModulePass { } // namespace +#if LLVM_MAJOR <= 10 /* use old pass manager */ char CmpLogInstructions::ID = 0; +#endif template Iterator Unique(Iterator first, Iterator last) { @@ -613,7 +634,12 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } +#if LLVM_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses CmpLogInstructions::run(Module & M, + ModuleAnalysisManager &MAM) { +#else bool CmpLogInstructions::runOnModule(Module &M) { +#endif if (getenv("AFL_QUIET") == NULL) printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n"); @@ -622,10 +648,15 @@ bool CmpLogInstructions::runOnModule(Module &M) { hookInstrs(M); verifyModule(M); +#if LLVM_MAJOR >= 11 /* use new pass manager */ + return PreservedAnalyses::all(); +#else return true; +#endif } +#if LLVM_MAJOR < 11 /* use old pass manager */ static void registerCmpLogInstructionsPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -645,4 +676,4 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCmpLogInstructionsPass); #endif - +#endif diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index c3a4ee34..5869a1db 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -26,14 +26,23 @@ #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) @@ -52,28 +61,37 @@ using namespace llvm; namespace { +#if LLVM_MAJOR >= 11 /* use new pass manager */ +class CompareTransform : public PassInfoMixin { + + public: + CompareTransform() { + +#else class CompareTransform : public ModulePass { public: static char ID; CompareTransform() : ModulePass(ID) { +#endif + initInstrumentList(); } - bool runOnModule(Module &M) override; - #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { #else const char *getPassName() const override { - #endif - return "transforms compare functions"; - } +#if LLVM_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else + bool runOnModule(Module &M) override; +#endif private: bool transformCmps(Module &M, const bool processStrcmp, @@ -85,7 +103,54 @@ class CompareTransform : public ModulePass { } // namespace +#if LLVM_MAJOR >= 11 /* use new pass manager */ +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "comparetransform", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if 1 + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(CompareTransform()); + + }); + + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + + if (Name == "comparetransform") { + + MPM.addPass(CompareTransform()); + return true; + + } else { + + return false; + + } + + }); + + #endif + + }}; + +} + +#else char CompareTransform::ID = 0; +#endif bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, const bool processMemcmp, @@ -385,6 +450,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, bool isCaseInsensitive = false; bool needs_null = false; Function * Callee = callInst->getCalledFunction(); + if (Callee) { if (!Callee->getName().compare("memcmp") || @@ -642,8 +708,14 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } +#if LLVM_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses CompareTransform::run(Module &M, ModuleAnalysisManager &MAM) { + +#else bool CompareTransform::runOnModule(Module &M) { +#endif + if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) printf( "Running compare-transform-pass by laf.intel@gmail.com, extended by " @@ -651,13 +723,28 @@ bool CompareTransform::runOnModule(Module &M) { else be_quiet = 1; +#if LLVM_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif + transformCmps(M, true, true, true, true, true); verifyModule(M); +#if LLVM_MAJOR >= 11 /* use new pass manager */ + /* if (modified) { + + PA.abandon(); + + }*/ + + return PA; +#else return true; +#endif } +#if LLVM_MAJOR < 11 /* use old pass manager */ static void registerCompTransPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -672,8 +759,9 @@ static RegisterStandardPasses RegisterCompTransPass( static RegisterStandardPasses RegisterCompTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterCompTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass); + #endif #endif diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index 0f00fa96..d7bb7aba 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -1,6 +1,7 @@ /* * Copyright 2016 laf-intel * extended for floating point by Heiko Eißfeldt + * adapted to new pass manager by Heiko Eißfeldt * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,10 +29,20 @@ #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" + +#if LLVM_MAJOR >= 11 + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/IR/Module.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ @@ -53,27 +64,31 @@ using namespace llvm; namespace { +#if LLVM_MAJOR >= 11 +class SplitComparesTransform : public PassInfoMixin { + + public: + // static char ID; + SplitComparesTransform() : enableFPSplit(0) { + +#else class SplitComparesTransform : public ModulePass { public: static char ID; SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) { +#endif + initInstrumentList(); } - bool runOnModule(Module &M) override; -#if LLVM_VERSION_MAJOR >= 4 - StringRef getPassName() const override { - +#if LLVM_MAJOR >= 11 + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else - const char *getPassName() const override { - + bool runOnModule(Module &M) override; #endif - return "AFL_SplitComparesTransform"; - - } private: int enableFPSplit; @@ -162,7 +177,54 @@ class SplitComparesTransform : public ModulePass { } // namespace +#if LLVM_MAJOR >= 11 +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "splitcompares", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if 1 + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(SplitComparesTransform()); + + }); + + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + + if (Name == "splitcompares") { + + MPM.addPass(SplitComparesTransform()); + return true; + + } else { + + return false; + + } + + }); + + #endif + + }}; + +} + +#else char SplitComparesTransform::ID = 0; +#endif /// This function splits FCMP instructions with xGE or xLE predicates into two /// FCMP instructions with predicate xGT or xLT and EQ @@ -1421,8 +1483,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } +#if LLVM_MAJOR >= 11 +PreservedAnalyses SplitComparesTransform::run(Module & M, + ModuleAnalysisManager &MAM) { + +#else bool SplitComparesTransform::runOnModule(Module &M) { +#endif + char *bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW"); if (!bitw_env) bitw_env = getenv("LAF_SPLIT_COMPARES_BITW"); if (bitw_env) { target_bitwidth = atoi(bitw_env); } @@ -1432,7 +1501,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) { - errs() << "Split-compare-pass by laf.intel@gmail.com, extended by " + errs() << "Split-compare-newpass by laf.intel@gmail.com, extended by " "heiko@hexco.de (splitting icmp to " << target_bitwidth << " bit)\n"; @@ -1444,6 +1513,10 @@ bool SplitComparesTransform::runOnModule(Module &M) { } +#if LLVM_MAJOR >= 11 + auto PA = PreservedAnalyses::all(); +#endif + if (enableFPSplit) { simplifyFPCompares(M); @@ -1473,7 +1546,16 @@ bool SplitComparesTransform::runOnModule(Module &M) { auto op0 = CI->getOperand(0); auto op1 = CI->getOperand(1); - if (!op0 || !op1) { return false; } + if (!op0 || !op1) { + +#if LLVM_MAJOR >= 11 + return PA; +#else + return false; +#endif + + } + auto iTy1 = dyn_cast(op0->getType()); if (iTy1 && isa(op1->getType())) { @@ -1522,10 +1604,29 @@ bool SplitComparesTransform::runOnModule(Module &M) { } + if ((isatty(2) && getenv("AFL_QUIET") == NULL) || + getenv("AFL_DEBUG") != NULL) { + + errs() << count << " comparisons found\n"; + + } + +#if LLVM_MAJOR >= 11 + /* if (modified) { + + PA.abandon(); + + }*/ + + return PA; +#else return true; +#endif } +#if LLVM_MAJOR < 11 /* use old pass manager */ + static void registerSplitComparesPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -1539,14 +1640,15 @@ static RegisterStandardPasses RegisterSplitComparesPass( static RegisterStandardPasses RegisterSplitComparesTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterSplitComparesTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerSplitComparesPass); -#endif + #endif static RegisterPass X("splitcompares", "AFL++ split compares", true /* Only looks at CFG */, true /* Analysis Pass */); +#endif diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index 9f9e7eca..96e01a8b 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -27,14 +27,23 @@ #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ @@ -54,29 +63,42 @@ using namespace llvm; namespace { +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +class SplitSwitchesTransform : public PassInfoMixin { + + public: + SplitSwitchesTransform() { + +#else class SplitSwitchesTransform : public ModulePass { public: static char ID; SplitSwitchesTransform() : ModulePass(ID) { +#endif initInstrumentList(); } - bool runOnModule(Module &M) override; +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else + bool runOnModule(Module &M) override; -#if LLVM_VERSION_MAJOR >= 4 + #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { -#else + #else const char *getPassName() const override { -#endif + #endif return "splits switch constructs"; } +#endif + struct CaseExpr { ConstantInt *Val; @@ -103,7 +125,54 @@ class SplitSwitchesTransform : public ModulePass { } // namespace +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "splitswitches", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if 1 + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(SplitSwitchesTransform()); + + }); + + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + + if (Name == "splitswitches") { + + MPM.addPass(SplitSwitchesTransform()); + return true; + + } else { + + return false; + + } + + }); + + #endif + + }}; + +} + +#else char SplitSwitchesTransform::ID = 0; +#endif /* switchConvert - Transform simple list of Cases into list of CaseRange's */ BasicBlock *SplitSwitchesTransform::switchConvert( @@ -413,19 +482,42 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { } +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses SplitSwitchesTransform::run(Module & M, + ModuleAnalysisManager &MAM) { + +#else bool SplitSwitchesTransform::runOnModule(Module &M) { +#endif + if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) printf("Running split-switches-pass by laf.intel@gmail.com\n"); else be_quiet = 1; + +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif + splitSwitches(M); verifyModule(M); +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + /* if (modified) { + + PA.abandon(); + + }*/ + + return PA; +#else return true; +#endif } +#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerSplitSwitchesTransPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -440,9 +532,10 @@ static RegisterStandardPasses RegisterSplitSwitchesTransPass( static RegisterStandardPasses RegisterSplitSwitchesTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerSplitSwitchesTransPass); + #endif #endif diff --git a/src/afl-cc.c b/src/afl-cc.c index ed57ca1e..8fe0d35d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -462,11 +462,17 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { +#if LLVM_MAJOR >= 11 /* use new pass manager */ + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%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); +#endif } @@ -482,11 +488,17 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { +#if LLVM_MAJOR >= 11 /* use new pass manager */ + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = alloc_printf( + "-fpass-plugin=%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); +#endif } @@ -502,11 +514,18 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { +#if LLVM_MAJOR >= 11 + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path); +// cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; +#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); +#endif } @@ -536,11 +555,17 @@ static void edit_params(u32 argc, char **argv, char **envp) { alloc_printf("%s/cmplog-switches-pass.so", obj_path); // reuse split switches from laf +#if LLVM_MAJOR >= 11 + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%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); +#endif } @@ -548,10 +573,6 @@ static void edit_params(u32 argc, char **argv, char **envp) { } -#if LLVM_MAJOR >= 13 - // fuck you llvm 13 - cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; -#endif if (lto_mode && !have_c) { @@ -601,6 +622,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { + cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; @@ -633,10 +655,16 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { +#if LLVM_MAJOR >= 11 + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/afl-llvm-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/afl-llvm-pass.so", obj_path); +#endif } @@ -653,11 +681,17 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { +#if LLVM_MAJOR >= 11 + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/cmplog-instructions-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/cmplog-instructions-pass.so", obj_path); +#endif cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; -- cgit 1.4.1 From 914eb79cbc14b26b51172a7b14c2a5a3a0ed2875 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 21 Feb 2022 10:32:43 +0100 Subject: todo list --- TODO_LLVM | 10 ++++++++++ src/afl-cc.c | 3 --- 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 TODO_LLVM diff --git a/TODO_LLVM b/TODO_LLVM new file mode 100644 index 00000000..3dea8cca --- /dev/null +++ b/TODO_LLVM @@ -0,0 +1,10 @@ +with LLVM 14: only new pass manager +up to LLVM 13: only old pass manager + +These do not work yet with the new pass manager: +cmplog-instructions-pass.so +compare-transform-pass.so +afl-llvm-dict2file.so +afl-llvm-lto-instrumentlist.so +SanitizerCoverageLTO.so +SanitizerCoveragePCGUARD.so diff --git a/src/afl-cc.c b/src/afl-cc.c index 8fe0d35d..09aa5e35 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -515,10 +515,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { #if LLVM_MAJOR >= 11 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; cc_params[cc_par_cnt++] = alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path); -// cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; #else cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; @@ -622,7 +620,6 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { - cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-Xclang"; -- cgit 1.4.1 From 05119990b6075aaf8f16a385a763651f68b8b1ef Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Tue, 22 Feb 2022 10:54:51 +0100 Subject: LLVM 14 fixes --- instrumentation/SanitizerCoverageLTO.so.cc | 5 +++-- instrumentation/SanitizerCoveragePCGUARD.so.cc | 1 + instrumentation/afl-llvm-dict2file.so.cc | 4 ++-- instrumentation/afl-llvm-lto-instrumentlist.so.cc | 1 + instrumentation/afl-llvm-pass.so.cc | 1 + instrumentation/compare-transform-pass.so.cc | 4 ++-- src/afl-cc.c | 4 ++-- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 6a4a071f..1bdc5376 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -17,6 +17,7 @@ #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ValueTracking.h" @@ -757,7 +758,7 @@ bool ModuleSanitizerCoverage::instrumentModule( if (!HasStr2) { auto *Ptr = dyn_cast(Str2P); - if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { + if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) { if (auto *Var = dyn_cast(Ptr->getOperand(0))) { @@ -838,7 +839,7 @@ bool ModuleSanitizerCoverage::instrumentModule( auto Ptr = dyn_cast(Str1P); - if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { + if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) { if (auto *Var = dyn_cast(Ptr->getOperand(0))) { diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index e4ffeb50..48bb5a2c 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -13,6 +13,7 @@ #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/IR/CFG.h" diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 39124660..94dc6984 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -435,7 +435,7 @@ bool AFLdict2filePass::runOnModule(Module &M) { if (!HasStr2) { auto *Ptr = dyn_cast(Str2P); - if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { + if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) { if (auto *Var = dyn_cast(Ptr->getOperand(0))) { @@ -519,7 +519,7 @@ bool AFLdict2filePass::runOnModule(Module &M) { auto Ptr = dyn_cast(Str1P); - if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { + if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) { if (auto *Var = dyn_cast(Ptr->getOperand(0))) { diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index 35ba9c5a..2ddbc725 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -43,6 +43,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" +#include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/IR/CFG.h" diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index 5246ba08..6419cd1d 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -45,6 +45,7 @@ typedef long double max_align_t; #endif #include "llvm/IR/IRBuilder.h" +#include "llvm/Pass.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Module.h" diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index c3a4ee34..1e250d7a 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -246,7 +246,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, if (!(HasStr1 || HasStr2)) { auto *Ptr = dyn_cast(Str2P); - if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { + if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) { if (auto *Var = dyn_cast(Ptr->getOperand(0))) { @@ -271,7 +271,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, if (!HasStr2) { Ptr = dyn_cast(Str1P); - if (Ptr && Ptr->isGEPWithNoNotionalOverIndexing()) { + if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) { if (auto *Var = dyn_cast(Ptr->getOperand(0))) { diff --git a/src/afl-cc.c b/src/afl-cc.c index ed57ca1e..bacd9de9 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -549,8 +549,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { } #if LLVM_MAJOR >= 13 - // fuck you llvm 13 - cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; + // Use the old pass manager in LLVM 14 which the afl++ passes still use. + cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; #endif if (lto_mode && !have_c) { -- cgit 1.4.1 From e996112fbcf2051865c7d2b7334a1aae9f05f75b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 24 Feb 2022 14:50:44 +0000 Subject: Fix build for the LLVM pass for LLVM >= 13 Due to change of inheritance for more modern LLVM versions, the overridable members are not the same. --- instrumentation/compare-transform-pass.so.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index be4dd513..cd3f0e6f 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -80,12 +80,14 @@ class CompareTransform : public ModulePass { } +#if LLVM_MAJOR < 11 #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { #else const char *getPassName() const override { #endif +#endif #if LLVM_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -- cgit 1.4.1 From 1840c27b6ffa8f6231e477e5cf92009f17a28c17 Mon Sep 17 00:00:00 2001 From: Adam Doupe Date: Sat, 26 Feb 2022 22:08:06 +0000 Subject: Clarify in docs that AFL_TARGET_ENV will apply to QEMU in QEMU mode, and note that QEMU_SET_ENV should be used instead in QEMU mode. Closes #1328 --- docs/env_variables.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index 4626a9b6..edd57fb6 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -518,7 +518,12 @@ checks or alter some of the more exotic semantics of the tool: the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz ... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would theoretically allow fuzzing of AFL++ itself (with 'target' AFL++ using some - AFL_ vars that would disrupt work of 'fuzzer' AFL++). + AFL_ vars that would disrupt work of 'fuzzer' AFL++). Note that when using + QEMU mode, the `AFL_TARGET_ENV` environment variables will apply to QEMU, as + well as the target binary. Therefore, in this case, you might want to use + QEMU's `QEMU_SET_ENV` environment variable (see QEMU's documentation because + the format is different from `AFL_TARGET_ENV`) to apply the environment + variables to the target and not QEMU. - `AFL_TESTCACHE_SIZE` allows you to override the size of `#define TESTCASE_CACHE` in config.h. Recommended values are 50-250MB - or more if -- cgit 1.4.1 From cd02f635db6d7bd08db11622c4dd7e7ac0889cfe Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 28 Feb 2022 17:42:11 +0100 Subject: remove file --- TODO_LLVM | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 TODO_LLVM diff --git a/TODO_LLVM b/TODO_LLVM deleted file mode 100644 index 3dea8cca..00000000 --- a/TODO_LLVM +++ /dev/null @@ -1,10 +0,0 @@ -with LLVM 14: only new pass manager -up to LLVM 13: only old pass manager - -These do not work yet with the new pass manager: -cmplog-instructions-pass.so -compare-transform-pass.so -afl-llvm-dict2file.so -afl-llvm-lto-instrumentlist.so -SanitizerCoverageLTO.so -SanitizerCoveragePCGUARD.so -- cgit 1.4.1 From 5e9286b9eae9fcee43c8a584c434f1f19559a78c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 28 Feb 2022 17:43:58 +0100 Subject: todo list for llvm --- TODO_LLVM | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 TODO_LLVM diff --git a/TODO_LLVM b/TODO_LLVM new file mode 100644 index 00000000..3dea8cca --- /dev/null +++ b/TODO_LLVM @@ -0,0 +1,10 @@ +with LLVM 14: only new pass manager +up to LLVM 13: only old pass manager + +These do not work yet with the new pass manager: +cmplog-instructions-pass.so +compare-transform-pass.so +afl-llvm-dict2file.so +afl-llvm-lto-instrumentlist.so +SanitizerCoverageLTO.so +SanitizerCoveragePCGUARD.so -- cgit 1.4.1 From 744ad172e12e051117e54b2e97f3727532190064 Mon Sep 17 00:00:00 2001 From: martinclauss <51541424+martinclauss@users.noreply.github.com> Date: Tue, 1 Mar 2022 15:42:04 +0100 Subject: Update fuzzing_in_depth.md add libdesock as an additional way to ease the fuzzing for network servers (#1341) --- docs/fuzzing_in_depth.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index ac72c757..a9151a25 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -817,9 +817,9 @@ Here are some of the most important caveats for AFL++: - There is no direct support for fuzzing network services, background daemons, or interactive apps that require UI interaction to work. You may need to make - simple code changes to make them behave in a more traditional way. Preeny may + simple code changes to make them behave in a more traditional way. Preeny or libdesock may offer a relatively simple option, too - see: - [https://github.com/zardus/preeny](https://github.com/zardus/preeny) + [https://github.com/zardus/preeny](https://github.com/zardus/preeny) or [https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock) Some useful tips for modifying network-based services can be also found at: [https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop) -- cgit 1.4.1 From f70760896c7a5d5f2b286d9ea71c8b6d90e98625 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Mar 2022 19:21:31 +0100 Subject: Revert "Merge branch 'newpm2' into dev" This reverts commit fee1acf7e6096533f1aa8cd74035bed21c90fdf6, reversing changes made to 675d17d737ee5dee88766d9c181567771592c94c. --- instrumentation/afl-llvm-dict2file.so.cc | 11 +-- instrumentation/afl-llvm-pass.so.cc | 91 +----------------- instrumentation/cmplog-instructions-pass.cc | 37 +------- instrumentation/compare-transform-pass.so.cc | 105 ++------------------- instrumentation/split-compares-pass.so.cc | 132 +++------------------------ instrumentation/split-switches-pass.so.cc | 107 ++-------------------- src/afl-cc.c | 39 +------- 7 files changed, 41 insertions(+), 481 deletions(-) diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index a554c40e..94dc6984 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -589,6 +589,7 @@ bool AFLdict2filePass::runOnModule(Module &M) { if (optLen < 2) { continue; } if (literalLength + 1 == optLen) { // add null byte + thestring.append("\0", 1); } @@ -611,17 +612,11 @@ bool AFLdict2filePass::runOnModule(Module &M) { } */ - - if (!isStdString) { + if (!isStdString && thestring.find('\0', 0) != std::string::npos) { // ensure we do not have garbage size_t offset = thestring.find('\0', 0); - if (offset && offset < optLen && offset + 1 < optLen) { - - optLen = offset + 1; - - } - + if (offset + 1 < optLen) optLen = offset + 1; thestring = thestring.substr(0, optLen); } diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index be8099bb..6419cd1d 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -46,21 +46,12 @@ typedef long double max_align_t; #include "llvm/IR/IRBuilder.h" #include "llvm/Pass.h" -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - #include "llvm/Passes/PassPlugin.h" - #include "llvm/Passes/PassBuilder.h" - #include "llvm/IR/PassManager.h" -#else - #include "llvm/IR/LegacyPassManager.h" - #include "llvm/Transforms/IPO/PassManagerBuilder.h" -#endif +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" -#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ - #include "llvm/Passes/OptimizationLevel.h" -#endif +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) @@ -78,30 +69,17 @@ using namespace llvm; namespace { -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ -class AFLCoverage : public PassInfoMixin { - - public: - AFLCoverage() { - -#else class AFLCoverage : public ModulePass { public: static char ID; AFLCoverage() : ModulePass(ID) { -#endif - initInstrumentList(); } -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -#else bool runOnModule(Module &M) override; -#endif protected: uint32_t ngram_size = 0; @@ -115,55 +93,7 @@ class AFLCoverage : public ModulePass { } // namespace -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK -llvmGetPassPluginInfo() { - - return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1", - /* lambda to insert our pass into the pass pipeline. */ - [](PassBuilder &PB) { - - #if 1 - #if LLVM_VERSION_MAJOR <= 13 - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - #endif - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { - - MPM.addPass(AFLCoverage()); - - }); - - /* TODO LTO registration */ - #else - using PipelineElement = typename PassBuilder::PipelineElement; - PB.registerPipelineParsingCallback([](StringRef Name, - ModulePassManager &MPM, - ArrayRef) { - - if (Name == "AFLCoverage") { - - MPM.addPass(AFLCoverage()); - return true; - - } else { - - return false; - - } - - }); - - #endif - - }}; - -} - -#else - char AFLCoverage::ID = 0; -#endif /* needed up to 3.9.0 */ #if LLVM_VERSION_MAJOR == 3 && \ @@ -189,15 +119,8 @@ uint64_t PowerOf2Ceil(unsigned in) { (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) #define AFL_HAVE_VECTOR_INTRINSICS 1 #endif - -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ -PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) { - -#else bool AFLCoverage::runOnModule(Module &M) { -#endif - LLVMContext &C = M.getContext(); IntegerType *Int8Ty = IntegerType::getInt8Ty(C); @@ -211,10 +134,6 @@ bool AFLCoverage::runOnModule(Module &M) { u32 rand_seed; unsigned int cur_loc = 0; -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif - /* Setup random() so we get Actually Random(TM) outputs from AFL_R() */ gettimeofday(&tv, &tz); rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); @@ -1079,15 +998,10 @@ bool AFLCoverage::runOnModule(Module &M) { } -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - return PA; -#else return true; -#endif } -#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerAFLPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -1100,5 +1014,4 @@ static RegisterStandardPasses RegisterAFLPass( static RegisterStandardPasses RegisterAFLPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass); -#endif diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index b6d51ef3..310f5585 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -28,16 +28,11 @@ #include "llvm/Config/llvm-config.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#if LLVM_MAJOR >= 11 -// #include "llvm/Passes/PassPlugin.h" -// #include "llvm/Passes/PassBuilder.h" - #include "llvm/IR/PassManager.h" -#else - #include "llvm/IR/LegacyPassManager.h" -#endif +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" @@ -60,15 +55,6 @@ using namespace llvm; namespace { -#if LLVM_MAJOR >= 11 /* use new pass manager */ -class CmpLogInstructions : public PassInfoMixin { - public: - CmpLogInstructions() { - - initInstrumentList(); - - } -#else class CmpLogInstructions : public ModulePass { public: @@ -78,11 +64,7 @@ class CmpLogInstructions : public ModulePass { initInstrumentList(); } -#endif -#if LLVM_MAJOR >= 11 /* use new pass manager */ - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -#else bool runOnModule(Module &M) override; #if LLVM_VERSION_MAJOR >= 4 @@ -95,7 +77,6 @@ class CmpLogInstructions : public ModulePass { return "cmplog instructions"; } -#endif private: bool hookInstrs(Module &M); @@ -104,9 +85,7 @@ class CmpLogInstructions : public ModulePass { } // namespace -#if LLVM_MAJOR <= 10 /* use old pass manager */ char CmpLogInstructions::ID = 0; -#endif template Iterator Unique(Iterator first, Iterator last) { @@ -634,12 +613,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } -#if LLVM_MAJOR >= 11 /* use new pass manager */ -PreservedAnalyses CmpLogInstructions::run(Module & M, - ModuleAnalysisManager &MAM) { -#else bool CmpLogInstructions::runOnModule(Module &M) { -#endif if (getenv("AFL_QUIET") == NULL) printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n"); @@ -648,15 +622,10 @@ bool CmpLogInstructions::runOnModule(Module &M) { hookInstrs(M); verifyModule(M); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - return PreservedAnalyses::all(); -#else return true; -#endif } -#if LLVM_MAJOR < 11 /* use old pass manager */ static void registerCmpLogInstructionsPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -676,4 +645,4 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCmpLogInstructionsPass); #endif -#endif + diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index cd3f0e6f..969a2ef4 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -26,23 +26,14 @@ #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #include "llvm/Passes/PassPlugin.h" - #include "llvm/Passes/PassBuilder.h" - #include "llvm/IR/PassManager.h" -#else - #include "llvm/IR/LegacyPassManager.h" - #include "llvm/Transforms/IPO/PassManagerBuilder.h" -#endif +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" -#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ - #include "llvm/Passes/OptimizationLevel.h" -#endif #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) @@ -61,21 +52,12 @@ using namespace llvm; namespace { -#if LLVM_MAJOR >= 11 /* use new pass manager */ -class CompareTransform : public PassInfoMixin { - - public: - CompareTransform() { - -#else class CompareTransform : public ModulePass { public: static char ID; CompareTransform() : ModulePass(ID) { -#endif - initInstrumentList(); } @@ -83,17 +65,18 @@ class CompareTransform : public ModulePass { #if LLVM_MAJOR < 11 #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { - #else const char *getPassName() const override { #endif + return "transforms compare functions"; + } #endif -#if LLVM_MAJOR >= 11 /* use new pass manager */ - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -#else +//#if LLVM_MAJOR >= 11 /* use new pass manager */ +// PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +//#else bool runOnModule(Module &M) override; -#endif +//#endif private: bool transformCmps(Module &M, const bool processStrcmp, @@ -105,54 +88,7 @@ class CompareTransform : public ModulePass { } // namespace -#if LLVM_MAJOR >= 11 /* use new pass manager */ -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK -llvmGetPassPluginInfo() { - - return {LLVM_PLUGIN_API_VERSION, "comparetransform", "v0.1", - /* lambda to insert our pass into the pass pipeline. */ - [](PassBuilder &PB) { - - #if 1 - #if LLVM_VERSION_MAJOR <= 13 - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - #endif - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { - - MPM.addPass(CompareTransform()); - - }); - - /* TODO LTO registration */ - #else - using PipelineElement = typename PassBuilder::PipelineElement; - PB.registerPipelineParsingCallback([](StringRef Name, - ModulePassManager &MPM, - ArrayRef) { - - if (Name == "comparetransform") { - - MPM.addPass(CompareTransform()); - return true; - - } else { - - return false; - - } - - }); - - #endif - - }}; - -} - -#else char CompareTransform::ID = 0; -#endif bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, const bool processMemcmp, @@ -452,7 +388,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, bool isCaseInsensitive = false; bool needs_null = false; Function * Callee = callInst->getCalledFunction(); - if (Callee) { if (!Callee->getName().compare("memcmp") || @@ -710,14 +645,8 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } -#if LLVM_MAJOR >= 11 /* use new pass manager */ -PreservedAnalyses CompareTransform::run(Module &M, ModuleAnalysisManager &MAM) { - -#else bool CompareTransform::runOnModule(Module &M) { -#endif - if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) printf( "Running compare-transform-pass by laf.intel@gmail.com, extended by " @@ -725,28 +654,13 @@ bool CompareTransform::runOnModule(Module &M) { else be_quiet = 1; -#if LLVM_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif - transformCmps(M, true, true, true, true, true); verifyModule(M); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - /* if (modified) { - - PA.abandon(); - - }*/ - - return PA; -#else return true; -#endif } -#if LLVM_MAJOR < 11 /* use old pass manager */ static void registerCompTransPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -761,9 +675,8 @@ static RegisterStandardPasses RegisterCompTransPass( static RegisterStandardPasses RegisterCompTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass); - #if LLVM_VERSION_MAJOR >= 11 +#if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterCompTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass); - #endif #endif diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index d7bb7aba..0f00fa96 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -1,7 +1,6 @@ /* * Copyright 2016 laf-intel * extended for floating point by Heiko Eißfeldt - * adapted to new pass manager by Heiko Eißfeldt * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,20 +28,10 @@ #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" - -#if LLVM_MAJOR >= 11 - #include "llvm/Passes/PassPlugin.h" - #include "llvm/Passes/PassBuilder.h" - #include "llvm/IR/PassManager.h" -#else - #include "llvm/IR/LegacyPassManager.h" - #include "llvm/Transforms/IPO/PassManagerBuilder.h" -#endif +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/IR/Module.h" -#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ - #include "llvm/Passes/OptimizationLevel.h" -#endif #include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ @@ -64,31 +53,27 @@ using namespace llvm; namespace { -#if LLVM_MAJOR >= 11 -class SplitComparesTransform : public PassInfoMixin { - - public: - // static char ID; - SplitComparesTransform() : enableFPSplit(0) { - -#else class SplitComparesTransform : public ModulePass { public: static char ID; SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) { -#endif - initInstrumentList(); } -#if LLVM_MAJOR >= 11 - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -#else bool runOnModule(Module &M) override; +#if LLVM_VERSION_MAJOR >= 4 + StringRef getPassName() const override { + +#else + const char *getPassName() const override { + #endif + return "AFL_SplitComparesTransform"; + + } private: int enableFPSplit; @@ -177,54 +162,7 @@ class SplitComparesTransform : public ModulePass { } // namespace -#if LLVM_MAJOR >= 11 -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK -llvmGetPassPluginInfo() { - - return {LLVM_PLUGIN_API_VERSION, "splitcompares", "v0.1", - /* lambda to insert our pass into the pass pipeline. */ - [](PassBuilder &PB) { - - #if 1 - #if LLVM_VERSION_MAJOR <= 13 - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - #endif - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { - - MPM.addPass(SplitComparesTransform()); - - }); - - /* TODO LTO registration */ - #else - using PipelineElement = typename PassBuilder::PipelineElement; - PB.registerPipelineParsingCallback([](StringRef Name, - ModulePassManager &MPM, - ArrayRef) { - - if (Name == "splitcompares") { - - MPM.addPass(SplitComparesTransform()); - return true; - - } else { - - return false; - - } - - }); - - #endif - - }}; - -} - -#else char SplitComparesTransform::ID = 0; -#endif /// This function splits FCMP instructions with xGE or xLE predicates into two /// FCMP instructions with predicate xGT or xLT and EQ @@ -1483,15 +1421,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } -#if LLVM_MAJOR >= 11 -PreservedAnalyses SplitComparesTransform::run(Module & M, - ModuleAnalysisManager &MAM) { - -#else bool SplitComparesTransform::runOnModule(Module &M) { -#endif - char *bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW"); if (!bitw_env) bitw_env = getenv("LAF_SPLIT_COMPARES_BITW"); if (bitw_env) { target_bitwidth = atoi(bitw_env); } @@ -1501,7 +1432,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) { - errs() << "Split-compare-newpass by laf.intel@gmail.com, extended by " + errs() << "Split-compare-pass by laf.intel@gmail.com, extended by " "heiko@hexco.de (splitting icmp to " << target_bitwidth << " bit)\n"; @@ -1513,10 +1444,6 @@ bool SplitComparesTransform::runOnModule(Module &M) { } -#if LLVM_MAJOR >= 11 - auto PA = PreservedAnalyses::all(); -#endif - if (enableFPSplit) { simplifyFPCompares(M); @@ -1546,16 +1473,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { auto op0 = CI->getOperand(0); auto op1 = CI->getOperand(1); - if (!op0 || !op1) { - -#if LLVM_MAJOR >= 11 - return PA; -#else - return false; -#endif - - } - + if (!op0 || !op1) { return false; } auto iTy1 = dyn_cast(op0->getType()); if (iTy1 && isa(op1->getType())) { @@ -1604,29 +1522,10 @@ bool SplitComparesTransform::runOnModule(Module &M) { } - if ((isatty(2) && getenv("AFL_QUIET") == NULL) || - getenv("AFL_DEBUG") != NULL) { - - errs() << count << " comparisons found\n"; - - } - -#if LLVM_MAJOR >= 11 - /* if (modified) { - - PA.abandon(); - - }*/ - - return PA; -#else return true; -#endif } -#if LLVM_MAJOR < 11 /* use old pass manager */ - static void registerSplitComparesPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -1640,15 +1539,14 @@ static RegisterStandardPasses RegisterSplitComparesPass( static RegisterStandardPasses RegisterSplitComparesTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass); - #if LLVM_VERSION_MAJOR >= 11 +#if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterSplitComparesTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerSplitComparesPass); - #endif +#endif static RegisterPass X("splitcompares", "AFL++ split compares", true /* Only looks at CFG */, true /* Analysis Pass */); -#endif diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index 96e01a8b..9f9e7eca 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -27,23 +27,14 @@ #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - #include "llvm/Passes/PassPlugin.h" - #include "llvm/Passes/PassBuilder.h" - #include "llvm/IR/PassManager.h" -#else - #include "llvm/IR/LegacyPassManager.h" - #include "llvm/Transforms/IPO/PassManagerBuilder.h" -#endif +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" -#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ - #include "llvm/Passes/OptimizationLevel.h" -#endif #include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ @@ -63,42 +54,29 @@ using namespace llvm; namespace { -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ -class SplitSwitchesTransform : public PassInfoMixin { - - public: - SplitSwitchesTransform() { - -#else class SplitSwitchesTransform : public ModulePass { public: static char ID; SplitSwitchesTransform() : ModulePass(ID) { -#endif initInstrumentList(); } -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -#else - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override; - #if LLVM_VERSION_MAJOR >= 4 +#if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { - #else +#else const char *getPassName() const override { - #endif +#endif return "splits switch constructs"; } -#endif - struct CaseExpr { ConstantInt *Val; @@ -125,54 +103,7 @@ class SplitSwitchesTransform : public ModulePass { } // namespace -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK -llvmGetPassPluginInfo() { - - return {LLVM_PLUGIN_API_VERSION, "splitswitches", "v0.1", - /* lambda to insert our pass into the pass pipeline. */ - [](PassBuilder &PB) { - - #if 1 - #if LLVM_VERSION_MAJOR <= 13 - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - #endif - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { - - MPM.addPass(SplitSwitchesTransform()); - - }); - - /* TODO LTO registration */ - #else - using PipelineElement = typename PassBuilder::PipelineElement; - PB.registerPipelineParsingCallback([](StringRef Name, - ModulePassManager &MPM, - ArrayRef) { - - if (Name == "splitswitches") { - - MPM.addPass(SplitSwitchesTransform()); - return true; - - } else { - - return false; - - } - - }); - - #endif - - }}; - -} - -#else char SplitSwitchesTransform::ID = 0; -#endif /* switchConvert - Transform simple list of Cases into list of CaseRange's */ BasicBlock *SplitSwitchesTransform::switchConvert( @@ -482,42 +413,19 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { } -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ -PreservedAnalyses SplitSwitchesTransform::run(Module & M, - ModuleAnalysisManager &MAM) { - -#else bool SplitSwitchesTransform::runOnModule(Module &M) { -#endif - if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) printf("Running split-switches-pass by laf.intel@gmail.com\n"); else be_quiet = 1; - -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif - splitSwitches(M); verifyModule(M); -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - /* if (modified) { - - PA.abandon(); - - }*/ - - return PA; -#else return true; -#endif } -#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerSplitSwitchesTransPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -532,10 +440,9 @@ static RegisterStandardPasses RegisterSplitSwitchesTransPass( static RegisterStandardPasses RegisterSplitSwitchesTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass); - #if LLVM_VERSION_MAJOR >= 11 +#if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerSplitSwitchesTransPass); - #endif #endif diff --git a/src/afl-cc.c b/src/afl-cc.c index 3e67085e..bacd9de9 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -462,17 +462,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { -#if LLVM_MAJOR >= 11 /* use new pass manager */ - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%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); -#endif } @@ -488,17 +482,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { -#if LLVM_MAJOR >= 11 /* use new pass manager */ - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%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); -#endif } @@ -514,16 +502,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { -#if LLVM_MAJOR >= 11 - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%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); -#endif } @@ -553,17 +536,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { alloc_printf("%s/cmplog-switches-pass.so", obj_path); // reuse split switches from laf -#if LLVM_MAJOR >= 11 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%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); -#endif } @@ -571,8 +548,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { } -#if LLVM_MAJOR == 13 // TODO: set to 14 when done FIXME - // Use the old pass manager in LLVM 13 which the afl++ passes still use. +#if LLVM_MAJOR >= 13 + // Use the old pass manager in LLVM 14 which the afl++ passes still use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; #endif @@ -656,16 +633,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { -#if LLVM_MAJOR >= 11 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-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/afl-llvm-pass.so", obj_path); -#endif } @@ -682,17 +653,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { -#if LLVM_MAJOR >= 11 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-instructions-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/cmplog-instructions-pass.so", obj_path); -#endif cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; -- cgit 1.4.1 From d84a8da1e9b68f03597f17a9c6c53503551fcb51 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Mar 2022 19:30:17 +0100 Subject: allow for -c0 also for src targets --- docs/Changelog.md | 3 +++ docs/fuzzing_binary-only_targets.md | 9 +++++---- src/afl-fuzz.c | 9 ++++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index f4ae0e43..549d5e4a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -12,6 +12,9 @@ sending a mail to . - fix */build_...sh scripts to work outside of git - new custom_mutator: libafl with token fuzzing :) - afl-fuzz: + - when you just want to compile once and set CMPLOG, then just + set -c 0 to tell afl-fuzz that the fuzzing binary is also for + CMPLOG. - new commandline options -g/G to set min/max length of generated fuzz inputs - reintroduced AFL_PERSISTENT and AFL_DEFER_FORKSRV to allow diff --git a/docs/fuzzing_binary-only_targets.md b/docs/fuzzing_binary-only_targets.md index 1a2b27c7..c97af1b9 100644 --- a/docs/fuzzing_binary-only_targets.md +++ b/docs/fuzzing_binary-only_targets.md @@ -48,11 +48,12 @@ The following setup to use QEMU mode is recommended: Then run as many instances as you have cores left with either -Q mode or - even better - use a binary rewriter like Dyninst, RetroWrite, ZAFL, etc. +The binary rewriters all have their own advantages and caveats. +ZAFL is the best but cannot be used in a business/commercial context. -If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for your -binary, then you can use afl-fuzz normally and it will have twice the speed -compared to QEMU mode (but slower than QEMU persistent mode). Note that several -other binary rewriters exist, all with their advantages and caveats. +If a binary rewriter works for your target then you can use afl-fuzz normally +and it will have twice the speed compared to QEMU mode (but slower than QEMU +persistent mode). The speed decrease of QEMU mode is at about 50%. However, various options exist to increase the speed: diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c73ab38b..6b177274 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -167,7 +167,8 @@ static void usage(u8 *argv0, int more_help) { " See docs/README.MOpt.md\n" " -c program - enable CmpLog by specifying a binary compiled for " "it.\n" - " if using QEMU, just use -c 0.\n" + " if using QEMU/FRIDA or if you the fuzzing target is compiled" + " for CmpLog then just use -c 0.\n" " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n" " 1=small files, 2=larger files (default), 3=all " "files,\n" @@ -1458,6 +1459,12 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->use_banner) { afl->use_banner = argv[optind]; } + if (afl->shm.cmplog_mode && (!strcmp("-", afl->cmplog_binary) || !strcmp("0", afl->cmplog_binary))) { + + afl->cmplog_binary = argv[optind]; + + } + if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) { WARNF(cLRD -- cgit 1.4.1 From 7e67545b9de14ae6e425d184581bec93ccf84c6a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Mar 2022 20:01:12 +0100 Subject: code format --- instrumentation/compare-transform-pass.so.cc | 21 +++++++++++++-------- src/afl-fuzz.c | 6 ++++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index 969a2ef4..c668ba95 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -63,20 +63,25 @@ class CompareTransform : public ModulePass { } #if LLVM_MAJOR < 11 -#if LLVM_VERSION_MAJOR >= 4 + #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { -#else + + #else const char *getPassName() const override { -#endif + + #endif return "transforms compare functions"; + } + #endif -//#if LLVM_MAJOR >= 11 /* use new pass manager */ -// PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); -//#else + //#if LLVM_MAJOR >= 11 /* use new pass manager + / /*/ + // PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); + //#else bool runOnModule(Module &M) override; -//#endif + //#endif private: bool transformCmps(Module &M, const bool processStrcmp, @@ -106,7 +111,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, #if LLVM_VERSION_MAJOR >= 9 FunctionCallee tolowerFn; #else - Function * tolowerFn; + Function *tolowerFn; #endif { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 6b177274..a3f57c1e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -167,7 +167,8 @@ static void usage(u8 *argv0, int more_help) { " See docs/README.MOpt.md\n" " -c program - enable CmpLog by specifying a binary compiled for " "it.\n" - " if using QEMU/FRIDA or if you the fuzzing target is compiled" + " if using QEMU/FRIDA or if you the fuzzing target is " + "compiled" " for CmpLog then just use -c 0.\n" " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n" " 1=small files, 2=larger files (default), 3=all " @@ -1459,7 +1460,8 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->use_banner) { afl->use_banner = argv[optind]; } - if (afl->shm.cmplog_mode && (!strcmp("-", afl->cmplog_binary) || !strcmp("0", afl->cmplog_binary))) { + if (afl->shm.cmplog_mode && + (!strcmp("-", afl->cmplog_binary) || !strcmp("0", afl->cmplog_binary))) { afl->cmplog_binary = argv[optind]; -- cgit 1.4.1 From d325fa5db8287e0b4984b12b07b16cf0f643c468 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Mar 2022 20:13:57 +0100 Subject: code format --- instrumentation/cmplog-instructions-pass.cc | 31 +++++++++++++++++----------- instrumentation/compare-transform-pass.so.cc | 23 +++++++++++---------- src/afl-cc.c | 10 ++++----- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index b6d51ef3..b3fe3880 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -60,14 +60,16 @@ using namespace llvm; namespace { -#if LLVM_MAJOR >= 11 /* use new pass manager */ +#if LLVM_MAJOR >= 11 /* use new pass manager */ class CmpLogInstructions : public PassInfoMixin { + public: CmpLogInstructions() { initInstrumentList(); } + #else class CmpLogInstructions : public ModulePass { @@ -78,23 +80,25 @@ class CmpLogInstructions : public ModulePass { initInstrumentList(); } + #endif -#if LLVM_MAJOR >= 11 /* use new pass manager */ +#if LLVM_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else - bool runOnModule(Module &M) override; + bool runOnModule(Module &M) override; -#if LLVM_VERSION_MAJOR >= 4 + #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { -#else + #else const char *getPassName() const override { -#endif + #endif return "cmplog instructions"; } + #endif private: @@ -104,7 +108,7 @@ class CmpLogInstructions : public ModulePass { } // namespace -#if LLVM_MAJOR <= 10 /* use old pass manager */ +#if LLVM_MAJOR <= 10 /* use old pass manager */ char CmpLogInstructions::ID = 0; #endif @@ -634,11 +638,13 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } -#if LLVM_MAJOR >= 11 /* use new pass manager */ +#if LLVM_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses CmpLogInstructions::run(Module & M, - ModuleAnalysisManager &MAM) { + ModuleAnalysisManager &MAM) { + #else bool CmpLogInstructions::runOnModule(Module &M) { + #endif if (getenv("AFL_QUIET") == NULL) @@ -648,7 +654,7 @@ bool CmpLogInstructions::runOnModule(Module &M) { hookInstrs(M); verifyModule(M); -#if LLVM_MAJOR >= 11 /* use new pass manager */ +#if LLVM_MAJOR >= 11 /* use new pass manager */ return PreservedAnalyses::all(); #else return true; @@ -671,9 +677,10 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPass( static RegisterStandardPasses RegisterCmpLogInstructionsPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCmpLogInstructionsPass); + #endif #endif -#endif + diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index cd3f0e6f..4e471ea3 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -81,27 +81,28 @@ class CompareTransform : public ModulePass { } #if LLVM_MAJOR < 11 -#if LLVM_VERSION_MAJOR >= 4 + #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { -#else + #else const char *getPassName() const override { -#endif + + #endif #endif #if LLVM_MAJOR >= 11 /* use new pass manager */ - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); + PreservedAnalyses run(Module & M, ModuleAnalysisManager & MAM); #else bool runOnModule(Module &M) override; #endif - private: - bool transformCmps(Module &M, const bool processStrcmp, - const bool processMemcmp, const bool processStrncmp, - const bool processStrcasecmp, - const bool processStrncasecmp); + private: + bool transformCmps(Module & M, const bool processStrcmp, + const bool processMemcmp, const bool processStrncmp, + const bool processStrcasecmp, + const bool processStrncasecmp); -}; + }; } // namespace @@ -170,7 +171,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, #if LLVM_VERSION_MAJOR >= 9 FunctionCallee tolowerFn; #else - Function * tolowerFn; + Function *tolowerFn; #endif { diff --git a/src/afl-cc.c b/src/afl-cc.c index 3e67085e..fae572f6 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -462,7 +462,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { -#if LLVM_MAJOR >= 11 /* use new pass manager */ +#if LLVM_MAJOR >= 11 /* use new pass manager */ cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; cc_params[cc_par_cnt++] = alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); @@ -488,7 +488,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { -#if LLVM_MAJOR >= 11 /* use new pass manager */ +#if LLVM_MAJOR >= 11 /* use new pass manager */ cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; cc_params[cc_par_cnt++] = alloc_printf( "-fpass-plugin=%s/compare-transform-pass.so", obj_path); @@ -571,7 +571,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } -#if LLVM_MAJOR == 13 // TODO: set to 14 when done FIXME +#if LLVM_MAJOR == 13 // TODO: set to 14 when done FIXME // Use the old pass manager in LLVM 13 which the afl++ passes still use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; #endif @@ -684,8 +684,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { #if LLVM_MAJOR >= 11 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); + cc_params[cc_par_cnt++] = alloc_printf( + "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); #else cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; -- cgit 1.4.1 From f2831419f5ceb28e1bc0cbf67cada012bccfb843 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 3 Mar 2022 08:55:05 +0100 Subject: ported cmplog-instructions-pass --- instrumentation/cmplog-instructions-pass.cc | 29 ++++++++++++++++++++++++++--- instrumentation/cmplog-routines-pass.cc | 24 ++++++++++++++++++++++++ instrumentation/cmplog-switches-pass.cc | 21 +++++++++++++++++++++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index b3fe3880..aa3ad560 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -32,8 +32,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #if LLVM_MAJOR >= 11 -// #include "llvm/Passes/PassPlugin.h" -// #include "llvm/Passes/PassBuilder.h" + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" #include "llvm/IR/PassManager.h" #else #include "llvm/IR/LegacyPassManager.h" @@ -41,6 +41,9 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) @@ -108,7 +111,27 @@ class CmpLogInstructions : public ModulePass { } // namespace -#if LLVM_MAJOR <= 10 /* use old pass manager */ +#if LLVM_MAJOR >= 11 +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "cmploginstructions", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + +#if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; +#endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(CmpLogInstructions()); + + }); + }}; + +} +#else char CmpLogInstructions::ID = 0; #endif diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 2af01a7a..2c2f2fc4 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -83,7 +83,31 @@ class CmpLogRoutines : public ModulePass { } // namespace + +#if LLVM_MAJOR >= 11 && 1 == 0 +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "cmplogroutines", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + +#if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; +#endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(SplitComparesTransform()); + + }); + }}; + +} +#else char CmpLogRoutines::ID = 0; +#endif + + bool CmpLogRoutines::hookRtns(Module &M) { diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index 068650ce..7c591e13 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -84,7 +84,28 @@ class CmpLogInstructions : public ModulePass { } // namespace +#if LLVM_MAJOR >= 11 && 1 == 0 +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "cmplogswitches", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + +#if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; +#endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(SplitComparesTransform()); + + }); + }}; + +} +#else char CmpLogInstructions::ID = 0; +#endif template Iterator Unique(Iterator first, Iterator last) { -- cgit 1.4.1 From 899fa59ab60e3924f986e17814cdfee544418e08 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 3 Mar 2022 17:11:41 +0100 Subject: port cmplog-switches-pass --- instrumentation/cmplog-instructions-pass.cc | 6 +- instrumentation/cmplog-routines-pass.cc | 9 ++- instrumentation/cmplog-switches-pass.cc | 89 +++++++++++++++++++++-------- 3 files changed, 72 insertions(+), 32 deletions(-) diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index aa3ad560..5bd98072 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -119,18 +119,20 @@ llvmGetPassPluginInfo() { /* lambda to insert our pass into the pass pipeline. */ [](PassBuilder &PB) { -#if LLVM_VERSION_MAJOR <= 13 + #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; -#endif + #endif PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(CmpLogInstructions()); }); + }}; } + #else char CmpLogInstructions::ID = 0; #endif diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 2c2f2fc4..d146dfa3 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -83,7 +83,6 @@ class CmpLogRoutines : public ModulePass { } // namespace - #if LLVM_MAJOR >= 11 && 1 == 0 llvmGetPassPluginInfo() { @@ -91,24 +90,24 @@ llvmGetPassPluginInfo() { /* lambda to insert our pass into the pass pipeline. */ [](PassBuilder &PB) { -#if LLVM_VERSION_MAJOR <= 13 + #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; -#endif + #endif PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(SplitComparesTransform()); }); + }}; } + #else char CmpLogRoutines::ID = 0; #endif - - bool CmpLogRoutines::hookRtns(Module &M) { std::vector calls, llvmStdStd, llvmStdC, gccStdStd, gccStdC, diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index 7c591e13..37bf3889 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -28,7 +28,14 @@ #include "llvm/Config/llvm-config.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -37,6 +44,7 @@ #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) #include "llvm/IR/Verifier.h" @@ -54,29 +62,42 @@ using namespace llvm; namespace { -class CmpLogInstructions : public ModulePass { +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +class CmplogSwitches : public PassInfoMixin { + + public: + CmplogSwitches() { + +#else +class CmplogSwitches : public ModulePass { public: static char ID; - CmpLogInstructions() : ModulePass(ID) { + CmplogSwitches() : ModulePass(ID) { +#endif initInstrumentList(); } - bool runOnModule(Module &M) override; +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else + bool runOnModule(Module &M) override; -#if LLVM_VERSION_MAJOR < 4 + #if LLVM_VERSION_MAJOR < 4 const char *getPassName() const override { -#else + #else StringRef getPassName() const override { -#endif - return "cmplog instructions"; + #endif + return "cmplog switch split"; } +#endif + private: bool hookInstrs(Module &M); @@ -84,27 +105,30 @@ class CmpLogInstructions : public ModulePass { } // namespace -#if LLVM_MAJOR >= 11 && 1 == 0 +#if LLVM_MAJOR >= 11 +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() { return {LLVM_PLUGIN_API_VERSION, "cmplogswitches", "v0.1", /* lambda to insert our pass into the pass pipeline. */ [](PassBuilder &PB) { -#if LLVM_VERSION_MAJOR <= 13 + #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; -#endif + #endif PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL) { - MPM.addPass(SplitComparesTransform()); + MPM.addPass(CmplogSwitches()); }); + }}; } + #else -char CmpLogInstructions::ID = 0; +char CmplogSwitches::ID = 0; #endif template @@ -122,7 +146,7 @@ Iterator Unique(Iterator first, Iterator last) { } -bool CmpLogInstructions::hookInstrs(Module &M) { +bool CmplogSwitches::hookInstrs(Module &M) { std::vector switches; LLVMContext & C = M.getContext(); @@ -404,36 +428,51 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } -bool CmpLogInstructions::runOnModule(Module &M) { +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses CmplogSwitches::run(Module &M, ModuleAnalysisManager &MAM) { + +#else +bool CmplogSwitches::runOnModule(Module &M) { + +#endif if (getenv("AFL_QUIET") == NULL) printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n"); else be_quiet = 1; hookInstrs(M); +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif verifyModule(M); +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + return PA; +#else return true; +#endif } -static void registerCmpLogInstructionsPass(const PassManagerBuilder &, - legacy::PassManagerBase &PM) { +#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ +static void registerCmplogSwitchesPass(const PassManagerBuilder &, + legacy::PassManagerBase &PM) { - auto p = new CmpLogInstructions(); + auto p = new CmplogSwitches(); PM.add(p); } -static RegisterStandardPasses RegisterCmpLogInstructionsPass( - PassManagerBuilder::EP_OptimizerLast, registerCmpLogInstructionsPass); +static RegisterStandardPasses RegisterCmplogSwitchesPass( + PassManagerBuilder::EP_OptimizerLast, registerCmplogSwitchesPass); -static RegisterStandardPasses RegisterCmpLogInstructionsPass0( - PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogInstructionsPass); +static RegisterStandardPasses RegisterCmplogSwitchesPass0( + PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmplogSwitchesPass); -#if LLVM_VERSION_MAJOR >= 11 -static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO( + #if LLVM_VERSION_MAJOR >= 11 +static RegisterStandardPasses RegisterCmplogSwitchesPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, - registerCmpLogInstructionsPass); + registerCmplogSwitchesPass); + #endif #endif -- cgit 1.4.1 From a2d54218ad22a5dfe29745422d853e45c5bba0d1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 3 Mar 2022 17:27:50 +0100 Subject: ported cmplog-routines-pass --- instrumentation/cmplog-routines-pass.cc | 54 ++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index d146dfa3..8205cfb0 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -27,7 +27,14 @@ #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -36,6 +43,7 @@ #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) #include "llvm/IR/Verifier.h" @@ -53,29 +61,43 @@ using namespace llvm; namespace { +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +class CmpLogRoutines : public PassInfoMixin { + + public: + CmpLogRoutines() { + +#else class CmpLogRoutines : public ModulePass { public: static char ID; CmpLogRoutines() : ModulePass(ID) { +#endif + initInstrumentList(); } - bool runOnModule(Module &M) override; +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else + bool runOnModule(Module &M) override; -#if LLVM_VERSION_MAJOR >= 4 + #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { -#else + #else const char *getPassName() const override { -#endif + #endif return "cmplog routines"; } +#endif + private: bool hookRtns(Module &M); @@ -83,7 +105,8 @@ class CmpLogRoutines : public ModulePass { } // namespace -#if LLVM_MAJOR >= 11 && 1 == 0 +#if LLVM_MAJOR >= 11 +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() { return {LLVM_PLUGIN_API_VERSION, "cmplogroutines", "v0.1", @@ -96,7 +119,7 @@ llvmGetPassPluginInfo() { PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL) { - MPM.addPass(SplitComparesTransform()); + MPM.addPass(CmpLogRoutines()); }); @@ -720,19 +743,33 @@ bool CmpLogRoutines::hookRtns(Module &M) { } +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses CmpLogRoutines::run(Module &M, ModuleAnalysisManager &MAM) { + +#else bool CmpLogRoutines::runOnModule(Module &M) { +#endif + if (getenv("AFL_QUIET") == NULL) printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n"); else be_quiet = 1; hookRtns(M); +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif verifyModule(M); +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + return PA; +#else return true; +#endif } +#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerCmpLogRoutinesPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -747,9 +784,10 @@ static RegisterStandardPasses RegisterCmpLogRoutinesPass( static RegisterStandardPasses RegisterCmpLogRoutinesPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerCmpLogRoutinesPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterCmpLogRoutinesPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCmpLogRoutinesPass); + #endif #endif -- cgit 1.4.1 From 33e43b11f8981ea97070a1f8b9a75e33b9fc1057 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 3 Mar 2022 18:24:26 +0100 Subject: port instrumentation/afl-llvm-dict2file --- instrumentation/afl-llvm-dict2file.so.cc | 113 +++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 27 deletions(-) diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index a554c40e..37cd8ad0 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -39,7 +39,14 @@ #include "llvm/Config/llvm-config.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Module.h" #include "llvm/IR/DebugInfo.h" @@ -60,31 +67,9 @@ #define O_DSYNC O_SYNC #endif -using namespace llvm; - -namespace { - -class AFLdict2filePass : public ModulePass { - - std::ofstream of; - void dict2file(u8 *, u32); - - public: - static char ID; - - AFLdict2filePass() : ModulePass(ID) { +std::ofstream of; - if (getenv("AFL_DEBUG")) debug = 1; - - } - - bool runOnModule(Module &M) override; - -}; - -} // namespace - -void AFLdict2filePass::dict2file(u8 *mem, u32 len) { +void dict2file(u8 *mem, u32 len) { u32 i, j, binary = 0; char line[MAX_AUTO_EXTRA * 8], tmp[8]; @@ -123,8 +108,74 @@ void AFLdict2filePass::dict2file(u8 *mem, u32 len) { } +using namespace llvm; + +namespace { + +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +class AFLdict2filePass : public PassInfoMixin { + + public: + AFLdict2filePass() { + +#else +class AFLdict2filePass : public ModulePass { + + public: + bool runOnModule(Module &M) override; + AFLdict2filePass() : ModulePass(ID) { + +#endif + + if (getenv("AFL_DEBUG")) debug = 1; + + } + +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#endif + +}; + +} // namespace + +#if LLVM_MAJOR >= 11 +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "dict2file", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(AFLdict2filePass()); + + }); + + }}; + +} + +#else + +char AFLdict2filePass::ID = 0; + +#endif + +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses AFLdict2filePass::run(Module &M, ModuleAnalysisManager &MAM) { + +#else + bool AFLdict2filePass::runOnModule(Module &M) { +#endif + DenseMap valueMap; char * ptr; int found = 0; @@ -663,12 +714,18 @@ bool AFLdict2filePass::runOnModule(Module &M) { } +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + return PA; +#else return true; +#endif } -char AFLdict2filePass::ID = 0; - +#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerAFLdict2filePass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -686,3 +743,5 @@ static RegisterStandardPasses RegisterAFLdict2filePass( static RegisterStandardPasses RegisterAFLdict2filePass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLdict2filePass); +#endif + -- cgit 1.4.1 From 544b68044a299e4de092d908825e0fa8d6a28db6 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 4 Mar 2022 03:36:52 +0100 Subject: fix broken code format --- instrumentation/compare-transform-pass.so.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index c668ba95..9a4e4f00 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -76,8 +76,7 @@ class CompareTransform : public ModulePass { #endif - //#if LLVM_MAJOR >= 11 /* use new pass manager - / /*/ + //#if LLVM_MAJOR >= 11 /* use new pass manager */ // PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); //#else bool runOnModule(Module &M) override; -- cgit 1.4.1 From 7c9b7c0bc0f17f19e39684c4a066c10d08743672 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 4 Mar 2022 05:35:27 +0100 Subject: update submodules --- nyx_mode/LIBNYX_VERSION | 2 +- nyx_mode/PACKER_VERSION | 2 +- nyx_mode/QEMU-Nyx | 2 +- nyx_mode/QEMU_NYX_VERSION | 2 +- nyx_mode/libnyx | 2 +- nyx_mode/packer | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION index b45b4e90..65e119c9 100644 --- a/nyx_mode/LIBNYX_VERSION +++ b/nyx_mode/LIBNYX_VERSION @@ -1 +1 @@ -2e45754 +8a77c71 diff --git a/nyx_mode/PACKER_VERSION b/nyx_mode/PACKER_VERSION index 43488114..d67dee20 100644 --- a/nyx_mode/PACKER_VERSION +++ b/nyx_mode/PACKER_VERSION @@ -1 +1 @@ -76100c5 +5d143ee diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx index c2c69cfc..c08e4ac9 160000 --- a/nyx_mode/QEMU-Nyx +++ b/nyx_mode/QEMU-Nyx @@ -1 +1 @@ -Subproject commit c2c69cfc528398d9db9363b92f8c50db4008c98f +Subproject commit c08e4ac94244a9739b4484b3010abc06b372923e diff --git a/nyx_mode/QEMU_NYX_VERSION b/nyx_mode/QEMU_NYX_VERSION index be13a784..2d9ee5e3 100644 --- a/nyx_mode/QEMU_NYX_VERSION +++ b/nyx_mode/QEMU_NYX_VERSION @@ -1 +1 @@ -c2c69cfc52 +c08e4ac942 diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx index 2e45754e..8a77c71d 160000 --- a/nyx_mode/libnyx +++ b/nyx_mode/libnyx @@ -1 +1 @@ -Subproject commit 2e45754e271463f446c31a6f467231d8657910e8 +Subproject commit 8a77c71dc8a8c0b73abd8fb9c22e30d565184efa diff --git a/nyx_mode/packer b/nyx_mode/packer index 76100c52..5d143eee 160000 --- a/nyx_mode/packer +++ b/nyx_mode/packer @@ -1 +1 @@ -Subproject commit 76100c52db96429350693a6c7284c5c6cbcb6b08 +Subproject commit 5d143eee4e4dcd12a1fc5d6786dd8da25cbb9953 -- cgit 1.4.1 From 0f7419fc9166b1f719372e1658efc4e3b9c88ac5 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 4 Mar 2022 05:41:40 +0100 Subject: write nyx crash logs to AFL++ work directory --- include/forkserver.h | 2 ++ src/afl-forkserver.c | 8 +++++++- src/afl-fuzz-bitmap.c | 14 ++++++++++++++ src/afl-fuzz.c | 4 ++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/forkserver.h b/include/forkserver.h index fd4d283c..cb68ce4f 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -70,6 +70,7 @@ typedef struct { enum NyxReturnValue (*nyx_exec)(void *qemu_process); uint8_t *(*nyx_get_bitmap_buffer)(void *qemu_process); size_t (*nyx_get_bitmap_buffer_size)(void *qemu_process); + uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer, uint32_t size); } nyx_plugin_handler_t; @@ -173,6 +174,7 @@ typedef struct afl_forkserver { void * nyx_runner; /* nyx runner object */ u32 nyx_id; /* nyx runner id (0 -> master) */ u32 nyx_bind_cpu_id; /* nyx runner cpu id */ + char* nyx_aux_string; #endif } afl_forkserver_t; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 8997781d..54f28852 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -450,6 +450,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->nyx_handlers->nyx_option_set_timeout(fsrv->nyx_runner, 2, 0); fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner); + fsrv->nyx_aux_string = malloc(0x1000); + memset(fsrv->nyx_aux_string, 0, 0x1000); + /* dry run */ fsrv->nyx_handlers->nyx_set_afl_input(fsrv->nyx_runner, "INIT", 4); switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) { @@ -1253,7 +1256,10 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) { fsrv->child_pid = -1; #ifdef __linux__ - if (fsrv->nyx_mode) { fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); } + if (fsrv->nyx_mode) { + free(fsrv->nyx_aux_string); + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + } #endif } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index b963caf8..bce1a195 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -771,6 +771,20 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { ck_write(fd, mem, len, fn); close(fd); + if(afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) { + u8 fn_log[PATH_MAX]; + + snprintf(fn_log, PATH_MAX, "%s.log", fn); + + fd = open(fn_log, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); } + + u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string(afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, 0x1000); + + ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log); + close(fd); + } + return keeping; } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a3f57c1e..df6e5404 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -468,6 +468,10 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { dlsym(handle, "nyx_get_bitmap_buffer_size"); if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; } + plugin->nyx_get_aux_string = + dlsym(handle, "nyx_get_aux_string"); + if (plugin->nyx_get_aux_string == NULL) { goto fail; } + OKF("libnyx plugin is ready!"); return plugin; -- cgit 1.4.1 From 713b069f40094482fb41ef17b44150162c062249 Mon Sep 17 00:00:00 2001 From: Sergej Schumilo Date: Fri, 4 Mar 2022 06:01:49 +0100 Subject: fix compile error on non linux targets --- src/afl-fuzz-bitmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index bce1a195..226dfa5c 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -771,6 +771,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { ck_write(fd, mem, len, fn); close(fd); +#ifdef __linux__ if(afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) { u8 fn_log[PATH_MAX]; @@ -784,6 +785,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log); close(fd); } +#endif return keeping; -- cgit 1.4.1 From 2eeba2dbf085b1c679dc82d59a0ec0ddc2c05429 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 4 Mar 2022 09:41:21 +0100 Subject: code format --- include/forkserver.h | 5 +++-- nyx_mode/custom_harness/example.c | 7 ++++--- src/afl-forkserver.c | 5 ++++- src/afl-fuzz-bitmap.c | 11 +++++++---- src/afl-fuzz.c | 3 +-- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/include/forkserver.h b/include/forkserver.h index cb68ce4f..5b66e7ec 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -70,7 +70,8 @@ typedef struct { enum NyxReturnValue (*nyx_exec)(void *qemu_process); uint8_t *(*nyx_get_bitmap_buffer)(void *qemu_process); size_t (*nyx_get_bitmap_buffer_size)(void *qemu_process); - uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer, uint32_t size); + uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer, + uint32_t size); } nyx_plugin_handler_t; @@ -174,7 +175,7 @@ typedef struct afl_forkserver { void * nyx_runner; /* nyx runner object */ u32 nyx_id; /* nyx runner id (0 -> master) */ u32 nyx_bind_cpu_id; /* nyx runner cpu id */ - char* nyx_aux_string; + char * nyx_aux_string; #endif } afl_forkserver_t; diff --git a/nyx_mode/custom_harness/example.c b/nyx_mode/custom_harness/example.c index dd268534..a67d42c6 100644 --- a/nyx_mode/custom_harness/example.c +++ b/nyx_mode/custom_harness/example.c @@ -7,7 +7,7 @@ #define TRACE_BUFFER_SIZE (64) #define PAGE_SIZE 0x1000 -#define MMAP_SIZE(x) ((x & ~(PAGE_SIZE-1)) + PAGE_SIZE) +#define MMAP_SIZE(x) ((x & ~(PAGE_SIZE - 1)) + PAGE_SIZE) int main(int argc, char **argv) { @@ -30,8 +30,9 @@ int main(int argc, char **argv) { /* this is our "bitmap" that is later shared with the fuzzer (you can also * pass the pointer of the bitmap used by compile-time instrumentations in * your target) */ - uint8_t *trace_buffer = mmap(NULL, MMAP_SIZE(TRACE_BUFFER_SIZE), PROT_READ | - PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + uint8_t *trace_buffer = + mmap(NULL, MMAP_SIZE(TRACE_BUFFER_SIZE), PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); memset(trace_buffer, 0, TRACE_BUFFER_SIZE); // makes sure that the bitmap buffer is already // mapped into the guest's memory (alternatively diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 54f28852..628ff590 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1257,9 +1257,12 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) { #ifdef __linux__ if (fsrv->nyx_mode) { + free(fsrv->nyx_aux_string); - fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + } + #endif } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 226dfa5c..a7c77aec 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -772,19 +772,22 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { close(fd); #ifdef __linux__ - if(afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) { - u8 fn_log[PATH_MAX]; + if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) { - snprintf(fn_log, PATH_MAX, "%s.log", fn); + u8 fn_log[PATH_MAX]; + snprintf(fn_log, PATH_MAX, "%s.log", fn); fd = open(fn_log, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); } - u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string(afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, 0x1000); + u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string( + afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, 0x1000); ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log); close(fd); + } + #endif return keeping; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index df6e5404..da1c7602 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -468,8 +468,7 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { dlsym(handle, "nyx_get_bitmap_buffer_size"); if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; } - plugin->nyx_get_aux_string = - dlsym(handle, "nyx_get_aux_string"); + plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string"); if (plugin->nyx_get_aux_string == NULL) { goto fail; } OKF("libnyx plugin is ready!"); -- cgit 1.4.1 From 5385cc7618c387dfbfb6a0a06cfa63ed45b50d15 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 4 Mar 2022 15:03:26 +0100 Subject: sancov will be only for llvm11+ --- instrumentation/SanitizerCoveragePCGUARD.so.cc | 37 ++++---------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 48bb5a2c..d3529fbc 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -37,10 +37,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/SpecialCaseList.h" -#if LLVM_VERSION_MAJOR >= 11 || \ - (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1) - #include "llvm/Support/VirtualFileSystem.h" -#endif +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" @@ -1487,7 +1484,6 @@ std::string ModuleSanitizerCoverage::getSectionEnd( } char ModuleSanitizerCoverageLegacyPass::ID = 0; - INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov", "Pass for instrumenting coverage on functions", false, false) @@ -1496,36 +1492,13 @@ INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov", "Pass for instrumenting coverage on functions", false, false) - ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( - const SanitizerCoverageOptions &Options -#if (LLVM_VERSION_MAJOR >= 11) - , + const SanitizerCoverageOptions &Options, const std::vector &AllowlistFiles, - const std::vector &BlocklistFiles -#endif -) { + const std::vector &BlocklistFiles) { - return new ModuleSanitizerCoverageLegacyPass(Options -#if (LLVM_VERSION_MAJOR >= 11) - , - AllowlistFiles, BlocklistFiles -#endif - ); + return new ModuleSanitizerCoverageLegacyPass(Options, AllowlistFiles, + BlocklistFiles); } -void registerPCGUARDPass(const PassManagerBuilder &, - legacy::PassManagerBase &PM) { - - auto p = new ModuleSanitizerCoverageLegacyPass(); - PM.add(p); - -} - -RegisterStandardPasses RegisterCompTransPass( - PassManagerBuilder::EP_OptimizerLast, registerPCGUARDPass); - -RegisterStandardPasses RegisterCompTransPass0( - PassManagerBuilder::EP_EnabledOnOptLevel0, registerPCGUARDPass); - -- cgit 1.4.1 From 70cc32dc6ddac78b686a5b7d16bfd9ede3daa81a Mon Sep 17 00:00:00 2001 From: mchesser Date: Mon, 7 Mar 2022 14:28:45 +1030 Subject: Fix issue with trim in shared memory mode --- src/afl-fuzz-run.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 5da0e583..2a9d186b 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -232,7 +232,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, memcpy(afl->fsrv.shmem_fuzz, mem, skip_at); - memcpy(afl->fsrv.shmem_fuzz, mem + skip_at + skip_len, tail_len); + memcpy(afl->fsrv.shmem_fuzz + skip_at, mem + skip_at + skip_len, tail_len); } -- cgit 1.4.1 From c2229b506e045bba1864e8b2f8140c8dc6e83a4d Mon Sep 17 00:00:00 2001 From: mchesser Date: Mon, 7 Mar 2022 14:35:25 +1030 Subject: Fix off by one bounds check `is_hex` reads two bytes but caller previously only ensured that one byte was in bounds. --- src/afl-fuzz-redqueen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 1e4b1b3c..66df5c6f 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2136,7 +2136,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if ((i % 2)) { - if (len > idx + i && is_hex(orig_buf + idx + i)) { + if (len > idx + i + 1 && is_hex(orig_buf + idx + i)) { fromhex += 2; -- cgit 1.4.1 From 2a00f32666a847b7babb160bb7c27db59cec9561 Mon Sep 17 00:00:00 2001 From: mchesser Date: Mon, 7 Mar 2022 14:39:36 +1030 Subject: Fix buffer overrun in `rtn_extended_encoding` `idx + i` can range from `0` to `buf.len`, but the memcpy may try and write to offsets from `idx + i` to `idx + 2 * i`. --- src/afl-fuzz-redqueen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 66df5c6f..2f32ef1e 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -2323,7 +2323,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } // fprintf(stderr, "RTN ATTEMPT fromhex %u result %u\n", fromhex, // *status); - memcpy(buf + idx + i, save + i, i + 1 + off); + memcpy(buf + idx, save, i + 1 + off); } -- cgit 1.4.1 From 981a04eb27e7e0117db05eccbcbb0677268d3a38 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 7 Mar 2022 08:13:24 +0100 Subject: new compiler performance options --- GNUmakefile | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 6392fceb..6444ecb8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -76,9 +76,9 @@ else endif endif -ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" - SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli -endif +#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" +# SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli +#endif #ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" # ifndef SOURCE_DATE_EPOCH @@ -92,12 +92,10 @@ ifneq "$(SYS)" "Darwin" # SPECIAL_PERFORMANCE += -march=native #endif # OS X does not like _FORTIFY_SOURCE=2 - ifndef DEBUG - CFLAGS_OPT += -D_FORTIFY_SOURCE=2 - endif -endif - -ifeq "$(SYS)" "Darwin" + ifndef DEBUG + CFLAGS_OPT += -D_FORTIFY_SOURCE=2 + endif +else # On some odd MacOS system configurations, the Xcode sdk path is not set correctly SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib LDFLAGS += $(SDK_LD) @@ -144,12 +142,13 @@ ifdef DEBUG $(info Compiling DEBUG version of binaries) override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT) else - CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) + CFLAGS ?= -O2 $(CFLAGS_OPT) # -funroll-loops is slower on modern compilers endif override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \ -fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \ - -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" + -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" +# -fstack-protector ifeq "$(SYS)" "FreeBSD" override CFLAGS += -I /usr/local/include/ @@ -175,7 +174,7 @@ ifeq "$(SYS)" "Haiku" SHMAT_OK=0 override CFLAGS += -DUSEMMAP=1 -Wno-error=format override LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork - SPECIAL_PERFORMANCE += -DUSEMMAP=1 + #SPECIAL_PERFORMANCE += -DUSEMMAP=1 endif AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c) @@ -247,9 +246,6 @@ else endif ifneq "$(filter Linux GNU%,$(SYS))" "" - ifndef DEBUG - override CFLAGS += -D_FORTIFY_SOURCE=2 - endif override LDFLAGS += -ldl -lrt -lm endif @@ -426,7 +422,7 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86 @ln -sf afl-as as src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h - $(CC) $(CFLAGS) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o + $(CC) $(CFLAGS) $(CFLAGS_OPT) -Iinclude -c src/afl-performance.c -o src/afl-performance.o src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h $(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o -- cgit 1.4.1 From d29773825594e7249e8a3a80b344a69249e7ab9a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 7 Mar 2022 09:37:19 +0100 Subject: nits --- README.md | 2 +- src/afl-fuzz-bitmap.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 66b884e2..a29ce792 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ Step-by-step quick start: 5. You will find found crashes and hangs in the subdirectories `crashes/` and `hangs/` in the `-o output_dir` directory. You can replay the crashes by - feeding them to the target, e.g.: + feeding them to the target, e.g. if your target is using stdin: ``` cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...] diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index a7c77aec..971ac494 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -423,10 +423,10 @@ void write_crash_readme(afl_state_t *afl) { "them to a vendor? Check out the afl-tmin that comes with the fuzzer!\n\n" "Found any cool bugs in open-source tools using afl-fuzz? If yes, please " - "drop\n" - "an mail at once the issues are fixed\n\n" - - " https://github.com/AFLplusplus/AFLplusplus\n\n", + "post\n" + "to https://github.com/AFLplusplus/AFLplusplus/issues/286 once the " + "issues\n" + " are fixed :)\n\n", afl->orig_cmdline, stringify_mem_size(val_buf, sizeof(val_buf), -- cgit 1.4.1 From 2b8fea083e6071fe0934e4a939ab651b44118208 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 15 Mar 2022 07:35:37 +0100 Subject: test --- .../SanitizerCoveragePCGUARD-alternative.so.cc | 1514 ++++++++++++++++++++ instrumentation/SanitizerCoveragePCGUARD.so.cc | 6 +- 2 files changed, 1518 insertions(+), 2 deletions(-) create mode 100644 instrumentation/SanitizerCoveragePCGUARD-alternative.so.cc diff --git a/instrumentation/SanitizerCoveragePCGUARD-alternative.so.cc b/instrumentation/SanitizerCoveragePCGUARD-alternative.so.cc new file mode 100644 index 00000000..982f610a --- /dev/null +++ b/instrumentation/SanitizerCoveragePCGUARD-alternative.so.cc @@ -0,0 +1,1514 @@ +//===-- SanitizerCoverage.cpp - coverage instrumentation for sanitizers ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Coverage instrumentation done on LLVM IR level, works with Sanitizers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Type.h" +#include "llvm/InitializePasses.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/SpecialCaseList.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/IR/PassManager.h" + +#include "config.h" +#include "debug.h" +#include "afl-llvm-common.h" + +using namespace llvm; + +#define DEBUG_TYPE "sancov" + +const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir"; +const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc"; +const char SanCovTraceCmp1[] = "__sanitizer_cov_trace_cmp1"; +const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2"; +const char SanCovTraceCmp4[] = "__sanitizer_cov_trace_cmp4"; +const char SanCovTraceCmp8[] = "__sanitizer_cov_trace_cmp8"; +const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1"; +const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2"; +const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4"; +const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8"; +const char SanCovTraceDiv4[] = "__sanitizer_cov_trace_div4"; +const char SanCovTraceDiv8[] = "__sanitizer_cov_trace_div8"; +const char SanCovTraceGep[] = "__sanitizer_cov_trace_gep"; +const char SanCovTraceSwitchName[] = "__sanitizer_cov_trace_switch"; +const char SanCovModuleCtorTracePcGuardName[] = + "sancov.module_ctor_trace_pc_guard"; +const char SanCovModuleCtor8bitCountersName[] = + "sancov.module_ctor_8bit_counters"; +const char SanCovModuleCtorBoolFlagName[] = "sancov.module_ctor_bool_flag"; +static const uint64_t SanCtorAndDtorPriority = 2; + +const char SanCovTracePCGuardName[] = "__sanitizer_cov_trace_pc_guard"; +const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init"; +const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; +const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; +const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; + +const char SanCovGuardsSectionName[] = "sancov_guards"; +const char SanCovCountersSectionName[] = "sancov_cntrs"; +const char SanCovBoolFlagSectionName[] = "sancov_bools"; +const char SanCovPCsSectionName[] = "sancov_pcs"; + +const char SanCovLowestStackName[] = "__sancov_lowest_stack"; + +static const char *skip_nozero; +static const char *use_threadsafe_counters; + +namespace { + +SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { + + // Sets CoverageType and IndirectCalls. + // SanitizerCoverageOptions CLOpts = getOptions(ClCoverageLevel); + Options.CoverageType = + SanitizerCoverageOptions::SCK_Edge; // std::max(Options.CoverageType, + // CLOpts.CoverageType); + Options.IndirectCalls = false; // CLOpts.IndirectCalls; + Options.TraceCmp = false; //|= ClCMPTracing; + Options.TraceDiv = false; //|= ClDIVTracing; + Options.TraceGep = false; //|= ClGEPTracing; + Options.TracePC = false; //|= ClTracePC; + Options.TracePCGuard = true; // |= ClTracePCGuard; + Options.Inline8bitCounters = 0; //|= ClInline8bitCounters; + // Options.InlineBoolFlag = 0; //|= ClInlineBoolFlag; + Options.PCTable = false; //|= ClCreatePCTable; + Options.NoPrune = false; //|= !ClPruneBlocks; + Options.StackDepth = false; //|= ClStackDepth; + if (!Options.TracePCGuard && !Options.TracePC && + !Options.Inline8bitCounters && !Options.StackDepth /*&& + !Options.InlineBoolFlag*/) + Options.TracePCGuard = true; // TracePCGuard is default. + + return Options; + +} + +using DomTreeCallback = function_ref; +using PostDomTreeCallback = + function_ref; + +class ModuleSanitizerCoverageAFL + : public PassInfoMixin { + + public: + ModuleSanitizerCoverageAFL( + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) + : Options(OverrideFromCL(Options)) { + + } + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); + + bool instrumentModule(Module &M, DomTreeCallback DTCallback, + PostDomTreeCallback PDTCallback); + + private: + void instrumentFunction(Function &F, DomTreeCallback DTCallback, + PostDomTreeCallback PDTCallback); + void InjectCoverageForIndirectCalls(Function & F, + ArrayRef IndirCalls); + void InjectTraceForCmp(Function &F, ArrayRef CmpTraceTargets); + void InjectTraceForDiv(Function & F, + ArrayRef DivTraceTargets); + void InjectTraceForGep(Function & F, + ArrayRef GepTraceTargets); + void InjectTraceForSwitch(Function & F, + ArrayRef SwitchTraceTargets); + bool InjectCoverage(Function &F, ArrayRef AllBlocks, + bool IsLeafFunc = true); + GlobalVariable *CreateFunctionLocalArrayInSection(size_t NumElements, + Function &F, Type *Ty, + const char *Section); + GlobalVariable *CreatePCArray(Function &F, ArrayRef AllBlocks); + void CreateFunctionLocalArrays(Function &F, ArrayRef AllBlocks, + uint32_t special); + void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, + bool IsLeafFunc = true); + Function *CreateInitCallsForSections(Module &M, const char *CtorName, + const char *InitFunctionName, Type *Ty, + const char *Section); + std::pair CreateSecStartEnd(Module &M, const char *Section, + Type *Ty); + + void SetNoSanitizeMetadata(Instruction *I) { + + I->setMetadata(I->getModule()->getMDKindID("nosanitize"), + MDNode::get(*C, None)); + + } + + std::string getSectionName(const std::string &Section) const; + std::string getSectionStart(const std::string &Section) const; + std::string getSectionEnd(const std::string &Section) const; + FunctionCallee SanCovTracePCIndir; + FunctionCallee SanCovTracePC, SanCovTracePCGuard; + FunctionCallee SanCovTraceCmpFunction[4]; + FunctionCallee SanCovTraceConstCmpFunction[4]; + FunctionCallee SanCovTraceDivFunction[2]; + FunctionCallee SanCovTraceGepFunction; + FunctionCallee SanCovTraceSwitchFunction; + GlobalVariable *SanCovLowestStack; + Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, + *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; + Module * CurModule; + std::string CurModuleUniqueId; + Triple TargetTriple; + LLVMContext * C; + const DataLayout *DL; + + GlobalVariable *FunctionGuardArray; // for trace-pc-guard. + GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. + GlobalVariable *FunctionBoolArray; // for inline-bool-flag. + GlobalVariable *FunctionPCsArray; // for pc-table. + SmallVector GlobalsToAppendToUsed; + SmallVector GlobalsToAppendToCompilerUsed; + + SanitizerCoverageOptions Options; + + uint32_t instr = 0, selects = 0, unhandled = 0; + GlobalVariable *AFLMapPtr = NULL; + ConstantInt * One = NULL; + ConstantInt * Zero = NULL; + +}; + +class ModuleSanitizerCoverageLegacyPass : public ModulePass { + + public: + ModuleSanitizerCoverageLegacyPass( + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) + : ModulePass(ID), Options(Options) { + + initializeModuleSanitizerCoverageLegacyPassPass( + *PassRegistry::getPassRegistry()); + + } + + bool runOnModule(Module &M) override { + + ModuleSanitizerCoverageAFL ModuleSancov(Options); + auto DTCallback = [this](Function &F) -> const DominatorTree * { + + return &this->getAnalysis(F).getDomTree(); + + }; + + auto PDTCallback = [this](Function &F) -> const PostDominatorTree * { + + return &this->getAnalysis(F) + .getPostDomTree(); + + }; + + return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback); + + } + + static char ID; // Pass identification, replacement for typeid + StringRef getPassName() const override { + + return "ModuleSanitizerCoverage"; + + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + + AU.addRequired(); + AU.addRequired(); + + } + + private: + SanitizerCoverageOptions Options; + +}; + +} // namespace + +#if 1 + +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "SanitizerCoveragePCGUARD", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(ModuleSanitizerCoverageAFL()); + + }); + + }}; + +} + +#endif + +PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module & M, + ModuleAnalysisManager &MAM) { + + fprintf(stderr, "IS CALLED!\n"); + + ModuleSanitizerCoverageAFL ModuleSancov(Options); + auto &FAM = MAM.getResult(M).getManager(); + auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { + + return &FAM.getResult(F); + + }; + + auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree * { + + return &FAM.getResult(F); + + }; + + if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); + +} + +std::pair ModuleSanitizerCoverageAFL::CreateSecStartEnd( + Module &M, const char *Section, Type *Ty) { + + GlobalVariable *SecStart = new GlobalVariable( + M, Ty->getPointerElementType(), false, + GlobalVariable::ExternalWeakLinkage, nullptr, getSectionStart(Section)); + SecStart->setVisibility(GlobalValue::HiddenVisibility); + GlobalVariable *SecEnd = new GlobalVariable( + M, Ty->getPointerElementType(), false, + GlobalVariable::ExternalWeakLinkage, nullptr, getSectionEnd(Section)); + SecEnd->setVisibility(GlobalValue::HiddenVisibility); + IRBuilder<> IRB(M.getContext()); + if (!TargetTriple.isOSBinFormatCOFF()) + return std::make_pair(SecStart, SecEnd); + + // Account for the fact that on windows-msvc __start_* symbols actually + // point to a uint64_t before the start of the array. + auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); + auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr, + ConstantInt::get(IntptrTy, sizeof(uint64_t))); + return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEnd); + +} + +Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections( + Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty, + const char *Section) { + + auto SecStartEnd = CreateSecStartEnd(M, Section, Ty); + auto SecStart = SecStartEnd.first; + auto SecEnd = SecStartEnd.second; + Function *CtorFunc; + std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( + M, CtorName, InitFunctionName, {Ty, Ty}, {SecStart, SecEnd}); + assert(CtorFunc->getName() == CtorName); + + if (TargetTriple.supportsCOMDAT()) { + + // Use comdat to dedup CtorFunc. + CtorFunc->setComdat(M.getOrInsertComdat(CtorName)); + appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority, CtorFunc); + + } else { + + appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); + + } + + if (TargetTriple.isOSBinFormatCOFF()) { + + // In COFF files, if the contructors are set as COMDAT (they are because + // COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced + // functions and data) is used, the constructors get stripped. To prevent + // this, give the constructors weak ODR linkage and ensure the linker knows + // to include the sancov constructor. This way the linker can deduplicate + // the constructors but always leave one copy. + CtorFunc->setLinkage(GlobalValue::WeakODRLinkage); + appendToUsed(M, CtorFunc); + + } + + return CtorFunc; + +} + +bool ModuleSanitizerCoverageAFL::instrumentModule( + Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { + + setvbuf(stdout, NULL, _IONBF, 0); + if (getenv("AFL_DEBUG")) debug = 1; + + if ((isatty(2) && !getenv("AFL_QUIET")) || debug) { + + SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n"); + + } else + + be_quiet = 1; + + skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); + use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST"); + + initInstrumentList(); + scanForDangerousFunctions(&M); + + if (debug) { + + fprintf(stderr, + "SANCOV: covtype:%u indirect:%d stack:%d noprune:%d " + "createtable:%d tracepcguard:%d tracepc:%d\n", + Options.CoverageType, Options.IndirectCalls == true ? 1 : 0, + Options.StackDepth == true ? 1 : 0, Options.NoPrune == true ? 1 : 0, + // Options.InlineBoolFlag == true ? 1 : 0, + Options.PCTable == true ? 1 : 0, + Options.TracePCGuard == true ? 1 : 0, + Options.TracePC == true ? 1 : 0); + + } + + if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; + C = &(M.getContext()); + DL = &M.getDataLayout(); + CurModule = &M; + CurModuleUniqueId = getUniqueModuleId(CurModule); + TargetTriple = Triple(M.getTargetTriple()); + FunctionGuardArray = nullptr; + Function8bitCounterArray = nullptr; + FunctionBoolArray = nullptr; + FunctionPCsArray = nullptr; + IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); + IntptrPtrTy = PointerType::getUnqual(IntptrTy); + Type * VoidTy = Type::getVoidTy(*C); + IRBuilder<> IRB(*C); + Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty()); + Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); + Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); + Int1PtrTy = PointerType::getUnqual(IRB.getInt1Ty()); + Int64Ty = IRB.getInt64Ty(); + Int32Ty = IRB.getInt32Ty(); + Int16Ty = IRB.getInt16Ty(); + Int8Ty = IRB.getInt8Ty(); + Int1Ty = IRB.getInt1Ty(); + LLVMContext &Ctx = M.getContext(); + + AFLMapPtr = + new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, + GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); + One = ConstantInt::get(IntegerType::getInt8Ty(Ctx), 1); + Zero = ConstantInt::get(IntegerType::getInt8Ty(Ctx), 0); + + SanCovTracePCIndir = + M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy); + // Make sure smaller parameters are zero-extended to i64 if required by the + // target ABI. + AttributeList SanCovTraceCmpZeroExtAL; + SanCovTraceCmpZeroExtAL = + SanCovTraceCmpZeroExtAL.addParamAttribute(*C, 0, Attribute::ZExt); + SanCovTraceCmpZeroExtAL = + SanCovTraceCmpZeroExtAL.addParamAttribute(*C, 1, Attribute::ZExt); + + SanCovTraceCmpFunction[0] = + M.getOrInsertFunction(SanCovTraceCmp1, SanCovTraceCmpZeroExtAL, VoidTy, + IRB.getInt8Ty(), IRB.getInt8Ty()); + SanCovTraceCmpFunction[1] = + M.getOrInsertFunction(SanCovTraceCmp2, SanCovTraceCmpZeroExtAL, VoidTy, + IRB.getInt16Ty(), IRB.getInt16Ty()); + SanCovTraceCmpFunction[2] = + M.getOrInsertFunction(SanCovTraceCmp4, SanCovTraceCmpZeroExtAL, VoidTy, + IRB.getInt32Ty(), IRB.getInt32Ty()); + SanCovTraceCmpFunction[3] = + M.getOrInsertFunction(SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty); + + SanCovTraceConstCmpFunction[0] = M.getOrInsertFunction( + SanCovTraceConstCmp1, SanCovTraceCmpZeroExtAL, VoidTy, Int8Ty, Int8Ty); + SanCovTraceConstCmpFunction[1] = M.getOrInsertFunction( + SanCovTraceConstCmp2, SanCovTraceCmpZeroExtAL, VoidTy, Int16Ty, Int16Ty); + SanCovTraceConstCmpFunction[2] = M.getOrInsertFunction( + SanCovTraceConstCmp4, SanCovTraceCmpZeroExtAL, VoidTy, Int32Ty, Int32Ty); + SanCovTraceConstCmpFunction[3] = + M.getOrInsertFunction(SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty); + + { + + AttributeList AL; + AL = AL.addParamAttribute(*C, 0, Attribute::ZExt); + SanCovTraceDivFunction[0] = + M.getOrInsertFunction(SanCovTraceDiv4, AL, VoidTy, IRB.getInt32Ty()); + + } + + SanCovTraceDivFunction[1] = + M.getOrInsertFunction(SanCovTraceDiv8, VoidTy, Int64Ty); + SanCovTraceGepFunction = + M.getOrInsertFunction(SanCovTraceGep, VoidTy, IntptrTy); + SanCovTraceSwitchFunction = + M.getOrInsertFunction(SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy); + + Constant *SanCovLowestStackConstant = + M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); + SanCovLowestStack = dyn_cast(SanCovLowestStackConstant); + if (!SanCovLowestStack) { + + C->emitError(StringRef("'") + SanCovLowestStackName + + "' should not be declared by the user"); + return true; + + } + + SanCovLowestStack->setThreadLocalMode( + GlobalValue::ThreadLocalMode::InitialExecTLSModel); + if (Options.StackDepth && !SanCovLowestStack->isDeclaration()) + SanCovLowestStack->setInitializer(Constant::getAllOnesValue(IntptrTy)); + + SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy); + SanCovTracePCGuard = + M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy); + + for (auto &F : M) + instrumentFunction(F, DTCallback, PDTCallback); + + Function *Ctor = nullptr; + + if (FunctionGuardArray) + Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName, + SanCovTracePCGuardInitName, Int32PtrTy, + SanCovGuardsSectionName); + if (Function8bitCounterArray) + Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName, + SanCov8bitCountersInitName, Int8PtrTy, + SanCovCountersSectionName); + if (FunctionBoolArray) { + + Ctor = CreateInitCallsForSections(M, SanCovModuleCtorBoolFlagName, + SanCovBoolFlagInitName, Int1PtrTy, + SanCovBoolFlagSectionName); + + } + + if (Ctor && Options.PCTable) { + + auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy); + FunctionCallee InitFunction = declareSanitizerInitFunction( + M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); + IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); + IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); + + } + + // We don't reference these arrays directly in any of our runtime functions, + // so we need to prevent them from being dead stripped. + if (TargetTriple.isOSBinFormatMachO()) appendToUsed(M, GlobalsToAppendToUsed); + appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); + + if (!be_quiet) { + + if (!instr) + WARNF("No instrumentation targets found."); + else { + + char modeline[100]; + snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s", + getenv("AFL_HARDEN") ? "hardened" : "non-hardened", + getenv("AFL_USE_ASAN") ? ", ASAN" : "", + getenv("AFL_USE_MSAN") ? ", MSAN" : "", + getenv("AFL_USE_TSAN") ? ", TSAN" : "", + getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", + getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); + OKF("Instrumented %u locations with no collisions (%s mode) of which are " + "%u handled and %u unhandled selects.", + instr, modeline, selects, unhandled); + + } + + } + + return true; + +} + +// True if block has successors and it dominates all of them. +bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) { + + if (succ_begin(BB) == succ_end(BB)) return false; + + for (const BasicBlock *SUCC : make_range(succ_begin(BB), succ_end(BB))) { + + if (!DT->dominates(BB, SUCC)) return false; + + } + + return true; + +} + +// True if block has predecessors and it postdominates all of them. +bool isFullPostDominator(const BasicBlock *BB, const PostDominatorTree *PDT) { + + if (pred_begin(BB) == pred_end(BB)) return false; + + for (const BasicBlock *PRED : make_range(pred_begin(BB), pred_end(BB))) { + + if (!PDT->dominates(BB, PRED)) return false; + + } + + return true; + +} + +bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, + const DominatorTree * DT, + const PostDominatorTree * PDT, + const SanitizerCoverageOptions &Options) { + + // Don't insert coverage for blocks containing nothing but unreachable: we + // will never call __sanitizer_cov() for them, so counting them in + // NumberOfInstrumentedBlocks() might complicate calculation of code coverage + // percentage. Also, unreachable instructions frequently have no debug + // locations. + if (isa(BB->getFirstNonPHIOrDbgOrLifetime())) return false; + + // Don't insert coverage into blocks without a valid insertion point + // (catchswitch blocks). + if (BB->getFirstInsertionPt() == BB->end()) return false; + + if (Options.NoPrune || &F.getEntryBlock() == BB) return true; + + if (Options.CoverageType == SanitizerCoverageOptions::SCK_Function && + &F.getEntryBlock() != BB) + return false; + + // Do not instrument full dominators, or full post-dominators with multiple + // predecessors. + return !isFullDominator(BB, DT) && + !(isFullPostDominator(BB, PDT) && !BB->getSinglePredecessor()); + +} + +// Returns true iff From->To is a backedge. +// A twist here is that we treat From->To as a backedge if +// * To dominates From or +// * To->UniqueSuccessor dominates From +bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT) { + + if (DT->dominates(To, From)) return true; + if (auto Next = To->getUniqueSuccessor()) + if (DT->dominates(Next, From)) return true; + return false; + +} + +// Prunes uninteresting Cmp instrumentation: +// * CMP instructions that feed into loop backedge branch. +// +// Note that Cmp pruning is controlled by the same flag as the +// BB pruning. +bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, + const SanitizerCoverageOptions &Options) { + + if (!Options.NoPrune) + if (CMP->hasOneUse()) + if (auto BR = dyn_cast(CMP->user_back())) + for (BasicBlock *B : BR->successors()) + if (IsBackEdge(BR->getParent(), B, DT)) return false; + return true; + +} + +void ModuleSanitizerCoverageAFL::instrumentFunction( + Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { + + if (F.empty()) return; + if (!isInInstrumentList(&F, FMNAME)) return; + + if (F.getName().find(".module_ctor") != std::string::npos) + return; // Should not instrument sanitizer init functions. + if (F.getName().startswith("__sanitizer_")) + return; // Don't instrument __sanitizer_* callbacks. + // Don't touch available_externally functions, their actual body is elewhere. + if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return; + // Don't instrument MSVC CRT configuration helpers. They may run before normal + // initialization. + if (F.getName() == "__local_stdio_printf_options" || + F.getName() == "__local_stdio_scanf_options") + return; + if (isa(F.getEntryBlock().getTerminator())) return; + // Don't instrument functions using SEH for now. Splitting basic blocks like + // we do for coverage breaks WinEHPrepare. + // FIXME: Remove this when SEH no longer uses landingpad pattern matching. + if (F.hasPersonalityFn() && + isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) + return; + if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) + SplitAllCriticalEdges( + F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); + SmallVector IndirCalls; + SmallVector BlocksToInstrument; + SmallVector CmpTraceTargets; + SmallVector SwitchTraceTargets; + SmallVector DivTraceTargets; + SmallVector GepTraceTargets; + + const DominatorTree * DT = DTCallback(F); + const PostDominatorTree *PDT = PDTCallback(F); + bool IsLeafFunc = true; + + for (auto &BB : F) { + + if (shouldInstrumentBlock(F, &BB, DT, PDT, Options)) + BlocksToInstrument.push_back(&BB); + for (auto &Inst : BB) { + + if (Options.IndirectCalls) { + + CallBase *CB = dyn_cast(&Inst); + if (CB && !CB->getCalledFunction()) IndirCalls.push_back(&Inst); + + } + + if (Options.TraceCmp) { + + if (ICmpInst *CMP = dyn_cast(&Inst)) + if (IsInterestingCmp(CMP, DT, Options)) + CmpTraceTargets.push_back(&Inst); + if (isa(&Inst)) SwitchTraceTargets.push_back(&Inst); + + } + + if (Options.TraceDiv) + if (BinaryOperator *BO = dyn_cast(&Inst)) + if (BO->getOpcode() == Instruction::SDiv || + BO->getOpcode() == Instruction::UDiv) + DivTraceTargets.push_back(BO); + if (Options.TraceGep) + if (GetElementPtrInst *GEP = dyn_cast(&Inst)) + GepTraceTargets.push_back(GEP); + if (Options.StackDepth) + if (isa(Inst) || + (isa(Inst) && !isa(Inst))) + IsLeafFunc = false; + + } + + } + + InjectCoverage(F, BlocksToInstrument, IsLeafFunc); + InjectCoverageForIndirectCalls(F, IndirCalls); + InjectTraceForCmp(F, CmpTraceTargets); + InjectTraceForSwitch(F, SwitchTraceTargets); + InjectTraceForDiv(F, DivTraceTargets); + InjectTraceForGep(F, GepTraceTargets); + +} + +GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection( + size_t NumElements, Function &F, Type *Ty, const char *Section) { + + ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); + auto Array = new GlobalVariable( + *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(ArrayTy), "__sancov_gen_"); + +#if LLVM_VERSION_MAJOR >= 13 + if (TargetTriple.supportsCOMDAT() && + (TargetTriple.isOSBinFormatELF() || !F.isInterposable())) + if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple)) + Array->setComdat(Comdat); +#else + if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) + if (auto Comdat = + GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) + Array->setComdat(Comdat); +#endif + + Array->setSection(getSectionName(Section)); +#if (LLVM_VERSION_MAJOR >= 11) || \ + (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1) + Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); +#else + Array->setAlignment(Align(4)); // cheating +#endif + GlobalsToAppendToUsed.push_back(Array); + GlobalsToAppendToCompilerUsed.push_back(Array); + MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F)); + Array->addMetadata(LLVMContext::MD_associated, *MD); + + return Array; + +} + +GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( + Function &F, ArrayRef AllBlocks) { + + size_t N = AllBlocks.size(); + assert(N); + SmallVector PCs; + IRBuilder<> IRB(&*F.getEntryBlock().getFirstInsertionPt()); + for (size_t i = 0; i < N; i++) { + + if (&F.getEntryBlock() == AllBlocks[i]) { + + PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); + PCs.push_back((Constant *)IRB.CreateIntToPtr( + ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); + + } else { + + PCs.push_back((Constant *)IRB.CreatePointerCast( + BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); + PCs.push_back((Constant *)IRB.CreateIntToPtr( + ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); + + } + + } + + auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy, + SanCovPCsSectionName); + PCArray->setInitializer( + ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs)); + PCArray->setConstant(true); + + return PCArray; + +} + +void ModuleSanitizerCoverageAFL::CreateFunctionLocalArrays( + Function &F, ArrayRef AllBlocks, uint32_t special) { + + if (Options.TracePCGuard) + FunctionGuardArray = CreateFunctionLocalArrayInSection( + AllBlocks.size() + special, F, Int32Ty, SanCovGuardsSectionName); + + if (Options.Inline8bitCounters) + Function8bitCounterArray = CreateFunctionLocalArrayInSection( + AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName); + /* + if (Options.InlineBoolFlag) + FunctionBoolArray = CreateFunctionLocalArrayInSection( + AllBlocks.size(), F, Int1Ty, SanCovBoolFlagSectionName); + */ + if (Options.PCTable) FunctionPCsArray = CreatePCArray(F, AllBlocks); + +} + +bool ModuleSanitizerCoverageAFL::InjectCoverage( + Function &F, ArrayRef AllBlocks, bool IsLeafFunc) { + + uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0; + + for (auto &BB : F) { + + for (auto &IN : BB) { + + CallInst *callInst = nullptr; + + if ((callInst = dyn_cast(&IN))) { + + Function *Callee = callInst->getCalledFunction(); + if (!Callee) continue; + if (callInst->getCallingConv() != llvm::CallingConv::C) continue; + StringRef FuncName = Callee->getName(); + if (!FuncName.compare(StringRef("dlopen")) || + !FuncName.compare(StringRef("_dlopen"))) { + + fprintf(stderr, + "WARNING: dlopen() detected. To have coverage for a library " + "that your target dlopen()'s this must either happen before " + "__AFL_INIT() or you must use AFL_PRELOAD to preload all " + "dlopen()'ed libraries!\n"); + continue; + + } + + if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; + + cnt_cov++; + + } + + SelectInst *selectInst = nullptr; + + if ((selectInst = dyn_cast(&IN))) { + + Value *c = selectInst->getCondition(); + auto t = c->getType(); + if (t->getTypeID() == llvm::Type::IntegerTyID) { + + cnt_sel++; + cnt_sel_inc += 2; + + } + +#if (LLVM_VERSION_MAJOR >= 12) + else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + + FixedVectorType *tt = dyn_cast(t); + if (tt) { + + cnt_sel++; + cnt_sel_inc += tt->getElementCount().getKnownMinValue(); + + } + + } + +#endif + + } + + } + + } + + /* Create PCGUARD array */ + CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel_inc); + selects += cnt_sel; + + uint32_t special = 0, local_selects = 0, skip_next = 0; + + for (auto &BB : F) { + + for (auto &IN : BB) { + + CallInst *callInst = nullptr; + + /* + std::string errMsg; + raw_string_ostream os(errMsg); + IN.print(os); + fprintf(stderr, "X: %s\n", os.str().c_str()); + */ + if ((callInst = dyn_cast(&IN))) { + + Function *Callee = callInst->getCalledFunction(); + if (!Callee) continue; + if (callInst->getCallingConv() != llvm::CallingConv::C) continue; + StringRef FuncName = Callee->getName(); + if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; + + IRBuilder<> IRB(callInst); + + Value *GuardPtr = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (++special + AllBlocks.size()) * 4)), + Int32PtrTy); + + LoadInst *Idx = IRB.CreateLoad(IRB.getInt32Ty(), GuardPtr); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Idx); + + callInst->setOperand(1, Idx); + + } + + SelectInst *selectInst = nullptr; + + if (!skip_next && (selectInst = dyn_cast(&IN))) { + + uint32_t vector_cnt = 0; + Value * condition = selectInst->getCondition(); + Value * result; + auto t = condition->getType(); + IRBuilder<> IRB(selectInst->getNextNode()); + + if (t->getTypeID() == llvm::Type::IntegerTyID) { + + auto GuardPtr1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), + Int32PtrTy); + + auto GuardPtr2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), + Int32PtrTy); + + result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2); + + } else + +#if LLVM_VERSION_MAJOR >= 14 + if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + + FixedVectorType *tt = dyn_cast(t); + if (tt) { + + uint32_t elements = tt->getElementCount().getFixedValue(); + vector_cnt = elements; + if (elements) { + + FixedVectorType *GuardPtr1 = + FixedVectorType::get(Int32PtrTy, elements); + FixedVectorType *GuardPtr2 = + FixedVectorType::get(Int32PtrTy, elements); + Value *x, *y; + + Value *val1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), + Int32PtrTy); + x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0); + + Value *val2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), + Int32PtrTy); + y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0); + + for (uint64_t i = 1; i < elements; i++) { + + val1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (cnt_cov + ++local_selects + + AllBlocks.size()) * + 4)), + Int32PtrTy); + x = IRB.CreateInsertElement(x, val1, i); + + val2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (cnt_cov + ++local_selects + + AllBlocks.size()) * + 4)), + Int32PtrTy); + y = IRB.CreateInsertElement(y, val2, i); + + } + + /* + std::string errMsg; + raw_string_ostream os(errMsg); + x->print(os); + fprintf(stderr, "X: %s\n", os.str().c_str()); + */ + result = IRB.CreateSelect(condition, x, y); + + } + + } + + } else + +#endif + { + + unhandled++; + continue; + + } + + uint32_t vector_cur = 0; + + /* Load SHM pointer */ + + LoadInst *MapPtr = + IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr); + + /* + std::string errMsg; + raw_string_ostream os(errMsg); + result->print(os); + fprintf(stderr, "X: %s\n", os.str().c_str()); + */ + + while (1) { + + /* Get CurLoc */ + LoadInst *CurLoc = nullptr; + Value * MapPtrIdx = nullptr; + + /* Load counter for CurLoc */ + if (!vector_cnt) { + + CurLoc = IRB.CreateLoad(IRB.getInt32Ty(), result); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(CurLoc); + MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc); + + } else { + + auto element = IRB.CreateExtractElement(result, vector_cur++); + auto elementptr = IRB.CreateIntToPtr(element, Int32PtrTy); + auto elementld = IRB.CreateLoad(IRB.getInt32Ty(), elementptr); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(elementld); + MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, elementld); + + } + + if (use_threadsafe_counters) { + + IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, +#if LLVM_VERSION_MAJOR >= 13 + llvm::MaybeAlign(1), +#endif + llvm::AtomicOrdering::Monotonic); + + } else { + + LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Counter); + + /* Update bitmap */ + + Value *Incr = IRB.CreateAdd(Counter, One); + + if (skip_nozero == NULL) { + + auto cf = IRB.CreateICmpEQ(Incr, Zero); + auto carry = IRB.CreateZExt(cf, Int8Ty); + Incr = IRB.CreateAdd(Incr, carry); + + } + + StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(StoreCtx); + + } + + if (!vector_cnt) { + + vector_cnt = 2; + break; + + } else if (vector_cnt == vector_cur) { + + break; + + } + + } + + skip_next = 1; + instr += vector_cnt; + + } else { + + skip_next = 0; + + } + + } + + } + + if (AllBlocks.empty() && !special && !local_selects) return false; + + if (!AllBlocks.empty()) + for (size_t i = 0, N = AllBlocks.size(); i < N; i++) + InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); + + return true; + +} + +// On every indirect call we call a run-time function +// __sanitizer_cov_indir_call* with two parameters: +// - callee address, +// - global cache array that contains CacheSize pointers (zero-initialized). +// The cache is used to speed up recording the caller-callee pairs. +// The address of the caller is passed implicitly via caller PC. +// CacheSize is encoded in the name of the run-time function. +void ModuleSanitizerCoverageAFL::InjectCoverageForIndirectCalls( + Function &F, ArrayRef IndirCalls) { + + if (IndirCalls.empty()) return; + for (auto I : IndirCalls) { + + IRBuilder<> IRB(I); + CallBase & CB = cast(*I); + Value * Callee = CB.getCalledOperand(); + if (isa(Callee)) continue; + IRB.CreateCall(SanCovTracePCIndir, IRB.CreatePointerCast(Callee, IntptrTy)); + + } + +} + +// For every switch statement we insert a call: +// __sanitizer_cov_trace_switch(CondValue, +// {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... }) + +void ModuleSanitizerCoverageAFL::InjectTraceForSwitch( + Function &, ArrayRef SwitchTraceTargets) { + + for (auto I : SwitchTraceTargets) { + + if (SwitchInst *SI = dyn_cast(I)) { + + IRBuilder<> IRB(I); + SmallVector Initializers; + Value * Cond = SI->getCondition(); + if (Cond->getType()->getScalarSizeInBits() > + Int64Ty->getScalarSizeInBits()) + continue; + Initializers.push_back(ConstantInt::get(Int64Ty, SI->getNumCases())); + Initializers.push_back( + ConstantInt::get(Int64Ty, Cond->getType()->getScalarSizeInBits())); + if (Cond->getType()->getScalarSizeInBits() < + Int64Ty->getScalarSizeInBits()) + Cond = IRB.CreateIntCast(Cond, Int64Ty, false); + for (auto It : SI->cases()) { + + Constant *C = It.getCaseValue(); + if (C->getType()->getScalarSizeInBits() < + Int64Ty->getScalarSizeInBits()) + C = ConstantExpr::getCast(CastInst::ZExt, It.getCaseValue(), Int64Ty); + Initializers.push_back(C); + + } + + llvm::sort(drop_begin(Initializers, 2), + [](const Constant *A, const Constant *B) { + + return cast(A)->getLimitedValue() < + cast(B)->getLimitedValue(); + + }); + + ArrayType *ArrayOfInt64Ty = ArrayType::get(Int64Ty, Initializers.size()); + GlobalVariable *GV = new GlobalVariable( + *CurModule, ArrayOfInt64Ty, false, GlobalVariable::InternalLinkage, + ConstantArray::get(ArrayOfInt64Ty, Initializers), + "__sancov_gen_cov_switch_values"); + IRB.CreateCall(SanCovTraceSwitchFunction, + {Cond, IRB.CreatePointerCast(GV, Int64PtrTy)}); + + } + + } + +} + +void ModuleSanitizerCoverageAFL::InjectTraceForDiv( + Function &, ArrayRef DivTraceTargets) { + + for (auto BO : DivTraceTargets) { + + IRBuilder<> IRB(BO); + Value * A1 = BO->getOperand(1); + if (isa(A1)) continue; + if (!A1->getType()->isIntegerTy()) continue; + uint64_t TypeSize = DL->getTypeStoreSizeInBits(A1->getType()); + int CallbackIdx = TypeSize == 32 ? 0 : TypeSize == 64 ? 1 : -1; + if (CallbackIdx < 0) continue; + auto Ty = Type::getIntNTy(*C, TypeSize); + IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx], + {IRB.CreateIntCast(A1, Ty, true)}); + + } + +} + +void ModuleSanitizerCoverageAFL::InjectTraceForGep( + Function &, ArrayRef GepTraceTargets) { + + for (auto GEP : GepTraceTargets) { + + IRBuilder<> IRB(GEP); + for (Use &Idx : GEP->indices()) + if (!isa(Idx) && Idx->getType()->isIntegerTy()) + IRB.CreateCall(SanCovTraceGepFunction, + {IRB.CreateIntCast(Idx, IntptrTy, true)}); + + } + +} + +void ModuleSanitizerCoverageAFL::InjectTraceForCmp( + Function &, ArrayRef CmpTraceTargets) { + + for (auto I : CmpTraceTargets) { + + if (ICmpInst *ICMP = dyn_cast(I)) { + + IRBuilder<> IRB(ICMP); + Value * A0 = ICMP->getOperand(0); + Value * A1 = ICMP->getOperand(1); + if (!A0->getType()->isIntegerTy()) continue; + uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType()); + int CallbackIdx = TypeSize == 8 ? 0 + : TypeSize == 16 ? 1 + : TypeSize == 32 ? 2 + : TypeSize == 64 ? 3 + : -1; + if (CallbackIdx < 0) continue; + // __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1); + auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx]; + bool FirstIsConst = isa(A0); + bool SecondIsConst = isa(A1); + // If both are const, then we don't need such a comparison. + if (FirstIsConst && SecondIsConst) continue; + // If only one is const, then make it the first callback argument. + if (FirstIsConst || SecondIsConst) { + + CallbackFunc = SanCovTraceConstCmpFunction[CallbackIdx]; + if (SecondIsConst) std::swap(A0, A1); + + } + + auto Ty = Type::getIntNTy(*C, TypeSize); + IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, Ty, true), + IRB.CreateIntCast(A1, Ty, true)}); + + } + + } + +} + +void ModuleSanitizerCoverageAFL::InjectCoverageAtBlock(Function & F, + BasicBlock &BB, + size_t Idx, + bool IsLeafFunc) { + + BasicBlock::iterator IP = BB.getFirstInsertionPt(); + bool IsEntryBB = &BB == &F.getEntryBlock(); + + if (IsEntryBB) { + + // Keep allocas and llvm.localescape calls in the entry block. Even + // if we aren't splitting the block, it's nice for allocas to be before + // calls. + IP = PrepareToSplitEntryBlock(BB, IP); + + } + + IRBuilder<> IRB(&*IP); + + if (Options.TracePC) { + + IRB.CreateCall(SanCovTracePC); + // ->setCannotMerge(); // gets the PC using GET_CALLER_PC. + + } + + if (Options.TracePCGuard) { + + /* Get CurLoc */ + + Value *GuardPtr = IRB.CreateIntToPtr( + IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, Idx * 4)), + Int32PtrTy); + + LoadInst *CurLoc = IRB.CreateLoad(IRB.getInt32Ty(), GuardPtr); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(CurLoc); + + /* Load SHM pointer */ + + LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr); + + /* Load counter for CurLoc */ + + Value *MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc); + + if (use_threadsafe_counters) { + + IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, +#if LLVM_VERSION_MAJOR >= 13 + llvm::MaybeAlign(1), +#endif + llvm::AtomicOrdering::Monotonic); + + } else { + + LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Counter); + + /* Update bitmap */ + + Value *Incr = IRB.CreateAdd(Counter, One); + + if (skip_nozero == NULL) { + + auto cf = IRB.CreateICmpEQ(Incr, Zero); + auto carry = IRB.CreateZExt(cf, Int8Ty); + Incr = IRB.CreateAdd(Incr, carry); + + } + + StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(StoreCtx); + + } + + // done :) + + // IRB.CreateCall(SanCovTracePCGuard, Offset)->setCannotMerge(); + // IRB.CreateCall(SanCovTracePCGuard, GuardPtr)->setCannotMerge(); + ++instr; + + } + + if (Options.Inline8bitCounters) { + + auto CounterPtr = IRB.CreateGEP( + Function8bitCounterArray->getValueType(), Function8bitCounterArray, + {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); + auto Load = IRB.CreateLoad(Int8Ty, CounterPtr); + auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1)); + auto Store = IRB.CreateStore(Inc, CounterPtr); + SetNoSanitizeMetadata(Load); + SetNoSanitizeMetadata(Store); + + } + + /* + if (Options.InlineBoolFlag) { + + auto FlagPtr = IRB.CreateGEP( + FunctionBoolArray->getValueType(), FunctionBoolArray, + {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); + auto Load = IRB.CreateLoad(Int1Ty, FlagPtr); + auto ThenTerm = + SplitBlockAndInsertIfThen(IRB.CreateIsNull(Load), &*IP, false); + IRBuilder<> ThenIRB(ThenTerm); + auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr); + SetNoSanitizeMetadata(Load); + SetNoSanitizeMetadata(Store); + + } + + */ + + if (Options.StackDepth && IsEntryBB && !IsLeafFunc) { + + // Check stack depth. If it's the deepest so far, record it. + Module * M = F.getParent(); + Function *GetFrameAddr = Intrinsic::getDeclaration( + M, Intrinsic::frameaddress, + IRB.getInt8PtrTy(M->getDataLayout().getAllocaAddrSpace())); + auto FrameAddrPtr = + IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)}); + auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy); + auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack); + auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); + auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false); + IRBuilder<> ThenIRB(ThenTerm); + auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); + SetNoSanitizeMetadata(LowestStack); + SetNoSanitizeMetadata(Store); + + } + +} + +std::string ModuleSanitizerCoverageAFL::getSectionName( + const std::string &Section) const { + + if (TargetTriple.isOSBinFormatCOFF()) { + + if (Section == SanCovCountersSectionName) return ".SCOV$CM"; + if (Section == SanCovBoolFlagSectionName) return ".SCOV$BM"; + if (Section == SanCovPCsSectionName) return ".SCOVP$M"; + return ".SCOV$GM"; // For SanCovGuardsSectionName. + + } + + if (TargetTriple.isOSBinFormatMachO()) return "__DATA,__" + Section; + return "__" + Section; + +} + +std::string ModuleSanitizerCoverageAFL::getSectionStart( + const std::string &Section) const { + + if (TargetTriple.isOSBinFormatMachO()) + return "\1section$start$__DATA$__" + Section; + return "__start___" + Section; + +} + +std::string ModuleSanitizerCoverageAFL::getSectionEnd( + const std::string &Section) const { + + if (TargetTriple.isOSBinFormatMachO()) + return "\1section$end$__DATA$__" + Section; + return "__stop___" + Section; + +} + +#if 0 + +char ModuleSanitizerCoverageLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov", + "Pass for instrumenting coverage on functions", false, + false) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) +INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov", + "Pass for instrumenting coverage on functions", false, + false) +ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( + const SanitizerCoverageOptions &Options, + const std::vector &AllowlistFiles, + const std::vector &BlocklistFiles) { + + return new ModuleSanitizerCoverageLegacyPass(Options, AllowlistFiles, + BlocklistFiles); + +} + +#endif + diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index d3529fbc..f87bc068 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -281,6 +281,8 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M, ModuleAnalysisManager &MAM) { + fprintf(stderr, "ModuleSanitizerCoveragePass::run is called!\n"); + ModuleSanitizerCoverage ModuleSancov(Options #if (LLVM_VERSION_MAJOR >= 11) , @@ -1484,12 +1486,12 @@ std::string ModuleSanitizerCoverage::getSectionEnd( } char ModuleSanitizerCoverageLegacyPass::ID = 0; -INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov", +INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancovAFL", "Pass for instrumenting coverage on functions", false, false) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) -INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov", +INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancovAFL", "Pass for instrumenting coverage on functions", false, false) ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( -- cgit 1.4.1 From c08304ad3d649df5033bd69a2096d454a28c36fc Mon Sep 17 00:00:00 2001 From: cd80 Date: Thu, 17 Mar 2022 14:36:41 +0900 Subject: fix typo for error message when using LD_PRELOAD --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c73ab38b..eac01c9a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1675,7 +1675,7 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("LD_PRELOAD")) { WARNF( - "LD_PRELOAD is set, are you sure that is what to you want to do " + "LD_PRELOAD is set, are you sure that is what you want to do " "instead of using AFL_PRELOAD?"); } -- cgit 1.4.1 From 59eaed2f70cd495092d747fd872d429e14f4d6a9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 17 Mar 2022 13:52:48 +0100 Subject: make pcguard work --- .../SanitizerCoveragePCGUARD-alternative.so.cc | 1514 -------------------- instrumentation/SanitizerCoveragePCGUARD.so.cc | 142 +- src/afl-cc.c | 6 + 3 files changed, 80 insertions(+), 1582 deletions(-) delete mode 100644 instrumentation/SanitizerCoveragePCGUARD-alternative.so.cc diff --git a/instrumentation/SanitizerCoveragePCGUARD-alternative.so.cc b/instrumentation/SanitizerCoveragePCGUARD-alternative.so.cc deleted file mode 100644 index 982f610a..00000000 --- a/instrumentation/SanitizerCoveragePCGUARD-alternative.so.cc +++ /dev/null @@ -1,1514 +0,0 @@ -//===-- SanitizerCoverage.cpp - coverage instrumentation for sanitizers ---===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Coverage instrumentation done on LLVM IR level, works with Sanitizers. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Analysis/EHPersonalities.h" -#include "llvm/Analysis/PostDominators.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Mangler.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/Type.h" -#include "llvm/InitializePasses.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/SpecialCaseList.h" -#include "llvm/Support/VirtualFileSystem.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/ModuleUtils.h" -#include "llvm/Passes/PassPlugin.h" -#include "llvm/Passes/PassBuilder.h" -#include "llvm/IR/PassManager.h" - -#include "config.h" -#include "debug.h" -#include "afl-llvm-common.h" - -using namespace llvm; - -#define DEBUG_TYPE "sancov" - -const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir"; -const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc"; -const char SanCovTraceCmp1[] = "__sanitizer_cov_trace_cmp1"; -const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2"; -const char SanCovTraceCmp4[] = "__sanitizer_cov_trace_cmp4"; -const char SanCovTraceCmp8[] = "__sanitizer_cov_trace_cmp8"; -const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1"; -const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2"; -const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4"; -const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8"; -const char SanCovTraceDiv4[] = "__sanitizer_cov_trace_div4"; -const char SanCovTraceDiv8[] = "__sanitizer_cov_trace_div8"; -const char SanCovTraceGep[] = "__sanitizer_cov_trace_gep"; -const char SanCovTraceSwitchName[] = "__sanitizer_cov_trace_switch"; -const char SanCovModuleCtorTracePcGuardName[] = - "sancov.module_ctor_trace_pc_guard"; -const char SanCovModuleCtor8bitCountersName[] = - "sancov.module_ctor_8bit_counters"; -const char SanCovModuleCtorBoolFlagName[] = "sancov.module_ctor_bool_flag"; -static const uint64_t SanCtorAndDtorPriority = 2; - -const char SanCovTracePCGuardName[] = "__sanitizer_cov_trace_pc_guard"; -const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init"; -const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; -const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; -const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; - -const char SanCovGuardsSectionName[] = "sancov_guards"; -const char SanCovCountersSectionName[] = "sancov_cntrs"; -const char SanCovBoolFlagSectionName[] = "sancov_bools"; -const char SanCovPCsSectionName[] = "sancov_pcs"; - -const char SanCovLowestStackName[] = "__sancov_lowest_stack"; - -static const char *skip_nozero; -static const char *use_threadsafe_counters; - -namespace { - -SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { - - // Sets CoverageType and IndirectCalls. - // SanitizerCoverageOptions CLOpts = getOptions(ClCoverageLevel); - Options.CoverageType = - SanitizerCoverageOptions::SCK_Edge; // std::max(Options.CoverageType, - // CLOpts.CoverageType); - Options.IndirectCalls = false; // CLOpts.IndirectCalls; - Options.TraceCmp = false; //|= ClCMPTracing; - Options.TraceDiv = false; //|= ClDIVTracing; - Options.TraceGep = false; //|= ClGEPTracing; - Options.TracePC = false; //|= ClTracePC; - Options.TracePCGuard = true; // |= ClTracePCGuard; - Options.Inline8bitCounters = 0; //|= ClInline8bitCounters; - // Options.InlineBoolFlag = 0; //|= ClInlineBoolFlag; - Options.PCTable = false; //|= ClCreatePCTable; - Options.NoPrune = false; //|= !ClPruneBlocks; - Options.StackDepth = false; //|= ClStackDepth; - if (!Options.TracePCGuard && !Options.TracePC && - !Options.Inline8bitCounters && !Options.StackDepth /*&& - !Options.InlineBoolFlag*/) - Options.TracePCGuard = true; // TracePCGuard is default. - - return Options; - -} - -using DomTreeCallback = function_ref; -using PostDomTreeCallback = - function_ref; - -class ModuleSanitizerCoverageAFL - : public PassInfoMixin { - - public: - ModuleSanitizerCoverageAFL( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) - : Options(OverrideFromCL(Options)) { - - } - - PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); - - bool instrumentModule(Module &M, DomTreeCallback DTCallback, - PostDomTreeCallback PDTCallback); - - private: - void instrumentFunction(Function &F, DomTreeCallback DTCallback, - PostDomTreeCallback PDTCallback); - void InjectCoverageForIndirectCalls(Function & F, - ArrayRef IndirCalls); - void InjectTraceForCmp(Function &F, ArrayRef CmpTraceTargets); - void InjectTraceForDiv(Function & F, - ArrayRef DivTraceTargets); - void InjectTraceForGep(Function & F, - ArrayRef GepTraceTargets); - void InjectTraceForSwitch(Function & F, - ArrayRef SwitchTraceTargets); - bool InjectCoverage(Function &F, ArrayRef AllBlocks, - bool IsLeafFunc = true); - GlobalVariable *CreateFunctionLocalArrayInSection(size_t NumElements, - Function &F, Type *Ty, - const char *Section); - GlobalVariable *CreatePCArray(Function &F, ArrayRef AllBlocks); - void CreateFunctionLocalArrays(Function &F, ArrayRef AllBlocks, - uint32_t special); - void InjectCoverageAtBlock(Function &F, BasicBlock &BB, size_t Idx, - bool IsLeafFunc = true); - Function *CreateInitCallsForSections(Module &M, const char *CtorName, - const char *InitFunctionName, Type *Ty, - const char *Section); - std::pair CreateSecStartEnd(Module &M, const char *Section, - Type *Ty); - - void SetNoSanitizeMetadata(Instruction *I) { - - I->setMetadata(I->getModule()->getMDKindID("nosanitize"), - MDNode::get(*C, None)); - - } - - std::string getSectionName(const std::string &Section) const; - std::string getSectionStart(const std::string &Section) const; - std::string getSectionEnd(const std::string &Section) const; - FunctionCallee SanCovTracePCIndir; - FunctionCallee SanCovTracePC, SanCovTracePCGuard; - FunctionCallee SanCovTraceCmpFunction[4]; - FunctionCallee SanCovTraceConstCmpFunction[4]; - FunctionCallee SanCovTraceDivFunction[2]; - FunctionCallee SanCovTraceGepFunction; - FunctionCallee SanCovTraceSwitchFunction; - GlobalVariable *SanCovLowestStack; - Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, - *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; - Module * CurModule; - std::string CurModuleUniqueId; - Triple TargetTriple; - LLVMContext * C; - const DataLayout *DL; - - GlobalVariable *FunctionGuardArray; // for trace-pc-guard. - GlobalVariable *Function8bitCounterArray; // for inline-8bit-counters. - GlobalVariable *FunctionBoolArray; // for inline-bool-flag. - GlobalVariable *FunctionPCsArray; // for pc-table. - SmallVector GlobalsToAppendToUsed; - SmallVector GlobalsToAppendToCompilerUsed; - - SanitizerCoverageOptions Options; - - uint32_t instr = 0, selects = 0, unhandled = 0; - GlobalVariable *AFLMapPtr = NULL; - ConstantInt * One = NULL; - ConstantInt * Zero = NULL; - -}; - -class ModuleSanitizerCoverageLegacyPass : public ModulePass { - - public: - ModuleSanitizerCoverageLegacyPass( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) - : ModulePass(ID), Options(Options) { - - initializeModuleSanitizerCoverageLegacyPassPass( - *PassRegistry::getPassRegistry()); - - } - - bool runOnModule(Module &M) override { - - ModuleSanitizerCoverageAFL ModuleSancov(Options); - auto DTCallback = [this](Function &F) -> const DominatorTree * { - - return &this->getAnalysis(F).getDomTree(); - - }; - - auto PDTCallback = [this](Function &F) -> const PostDominatorTree * { - - return &this->getAnalysis(F) - .getPostDomTree(); - - }; - - return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback); - - } - - static char ID; // Pass identification, replacement for typeid - StringRef getPassName() const override { - - return "ModuleSanitizerCoverage"; - - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - - AU.addRequired(); - AU.addRequired(); - - } - - private: - SanitizerCoverageOptions Options; - -}; - -} // namespace - -#if 1 - -extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK -llvmGetPassPluginInfo() { - - return {LLVM_PLUGIN_API_VERSION, "SanitizerCoveragePCGUARD", "v0.1", - /* lambda to insert our pass into the pass pipeline. */ - [](PassBuilder &PB) { - - #if LLVM_VERSION_MAJOR <= 13 - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - #endif - PB.registerOptimizerLastEPCallback( - [](ModulePassManager &MPM, OptimizationLevel OL) { - - MPM.addPass(ModuleSanitizerCoverageAFL()); - - }); - - }}; - -} - -#endif - -PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module & M, - ModuleAnalysisManager &MAM) { - - fprintf(stderr, "IS CALLED!\n"); - - ModuleSanitizerCoverageAFL ModuleSancov(Options); - auto &FAM = MAM.getResult(M).getManager(); - auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { - - return &FAM.getResult(F); - - }; - - auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree * { - - return &FAM.getResult(F); - - }; - - if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback)) - return PreservedAnalyses::none(); - return PreservedAnalyses::all(); - -} - -std::pair ModuleSanitizerCoverageAFL::CreateSecStartEnd( - Module &M, const char *Section, Type *Ty) { - - GlobalVariable *SecStart = new GlobalVariable( - M, Ty->getPointerElementType(), false, - GlobalVariable::ExternalWeakLinkage, nullptr, getSectionStart(Section)); - SecStart->setVisibility(GlobalValue::HiddenVisibility); - GlobalVariable *SecEnd = new GlobalVariable( - M, Ty->getPointerElementType(), false, - GlobalVariable::ExternalWeakLinkage, nullptr, getSectionEnd(Section)); - SecEnd->setVisibility(GlobalValue::HiddenVisibility); - IRBuilder<> IRB(M.getContext()); - if (!TargetTriple.isOSBinFormatCOFF()) - return std::make_pair(SecStart, SecEnd); - - // Account for the fact that on windows-msvc __start_* symbols actually - // point to a uint64_t before the start of the array. - auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); - auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr, - ConstantInt::get(IntptrTy, sizeof(uint64_t))); - return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEnd); - -} - -Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections( - Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty, - const char *Section) { - - auto SecStartEnd = CreateSecStartEnd(M, Section, Ty); - auto SecStart = SecStartEnd.first; - auto SecEnd = SecStartEnd.second; - Function *CtorFunc; - std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( - M, CtorName, InitFunctionName, {Ty, Ty}, {SecStart, SecEnd}); - assert(CtorFunc->getName() == CtorName); - - if (TargetTriple.supportsCOMDAT()) { - - // Use comdat to dedup CtorFunc. - CtorFunc->setComdat(M.getOrInsertComdat(CtorName)); - appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority, CtorFunc); - - } else { - - appendToGlobalCtors(M, CtorFunc, SanCtorAndDtorPriority); - - } - - if (TargetTriple.isOSBinFormatCOFF()) { - - // In COFF files, if the contructors are set as COMDAT (they are because - // COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced - // functions and data) is used, the constructors get stripped. To prevent - // this, give the constructors weak ODR linkage and ensure the linker knows - // to include the sancov constructor. This way the linker can deduplicate - // the constructors but always leave one copy. - CtorFunc->setLinkage(GlobalValue::WeakODRLinkage); - appendToUsed(M, CtorFunc); - - } - - return CtorFunc; - -} - -bool ModuleSanitizerCoverageAFL::instrumentModule( - Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { - - setvbuf(stdout, NULL, _IONBF, 0); - if (getenv("AFL_DEBUG")) debug = 1; - - if ((isatty(2) && !getenv("AFL_QUIET")) || debug) { - - SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n"); - - } else - - be_quiet = 1; - - skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); - use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST"); - - initInstrumentList(); - scanForDangerousFunctions(&M); - - if (debug) { - - fprintf(stderr, - "SANCOV: covtype:%u indirect:%d stack:%d noprune:%d " - "createtable:%d tracepcguard:%d tracepc:%d\n", - Options.CoverageType, Options.IndirectCalls == true ? 1 : 0, - Options.StackDepth == true ? 1 : 0, Options.NoPrune == true ? 1 : 0, - // Options.InlineBoolFlag == true ? 1 : 0, - Options.PCTable == true ? 1 : 0, - Options.TracePCGuard == true ? 1 : 0, - Options.TracePC == true ? 1 : 0); - - } - - if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; - C = &(M.getContext()); - DL = &M.getDataLayout(); - CurModule = &M; - CurModuleUniqueId = getUniqueModuleId(CurModule); - TargetTriple = Triple(M.getTargetTriple()); - FunctionGuardArray = nullptr; - Function8bitCounterArray = nullptr; - FunctionBoolArray = nullptr; - FunctionPCsArray = nullptr; - IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits()); - IntptrPtrTy = PointerType::getUnqual(IntptrTy); - Type * VoidTy = Type::getVoidTy(*C); - IRBuilder<> IRB(*C); - Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty()); - Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty()); - Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty()); - Int1PtrTy = PointerType::getUnqual(IRB.getInt1Ty()); - Int64Ty = IRB.getInt64Ty(); - Int32Ty = IRB.getInt32Ty(); - Int16Ty = IRB.getInt16Ty(); - Int8Ty = IRB.getInt8Ty(); - Int1Ty = IRB.getInt1Ty(); - LLVMContext &Ctx = M.getContext(); - - AFLMapPtr = - new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, - GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); - One = ConstantInt::get(IntegerType::getInt8Ty(Ctx), 1); - Zero = ConstantInt::get(IntegerType::getInt8Ty(Ctx), 0); - - SanCovTracePCIndir = - M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy); - // Make sure smaller parameters are zero-extended to i64 if required by the - // target ABI. - AttributeList SanCovTraceCmpZeroExtAL; - SanCovTraceCmpZeroExtAL = - SanCovTraceCmpZeroExtAL.addParamAttribute(*C, 0, Attribute::ZExt); - SanCovTraceCmpZeroExtAL = - SanCovTraceCmpZeroExtAL.addParamAttribute(*C, 1, Attribute::ZExt); - - SanCovTraceCmpFunction[0] = - M.getOrInsertFunction(SanCovTraceCmp1, SanCovTraceCmpZeroExtAL, VoidTy, - IRB.getInt8Ty(), IRB.getInt8Ty()); - SanCovTraceCmpFunction[1] = - M.getOrInsertFunction(SanCovTraceCmp2, SanCovTraceCmpZeroExtAL, VoidTy, - IRB.getInt16Ty(), IRB.getInt16Ty()); - SanCovTraceCmpFunction[2] = - M.getOrInsertFunction(SanCovTraceCmp4, SanCovTraceCmpZeroExtAL, VoidTy, - IRB.getInt32Ty(), IRB.getInt32Ty()); - SanCovTraceCmpFunction[3] = - M.getOrInsertFunction(SanCovTraceCmp8, VoidTy, Int64Ty, Int64Ty); - - SanCovTraceConstCmpFunction[0] = M.getOrInsertFunction( - SanCovTraceConstCmp1, SanCovTraceCmpZeroExtAL, VoidTy, Int8Ty, Int8Ty); - SanCovTraceConstCmpFunction[1] = M.getOrInsertFunction( - SanCovTraceConstCmp2, SanCovTraceCmpZeroExtAL, VoidTy, Int16Ty, Int16Ty); - SanCovTraceConstCmpFunction[2] = M.getOrInsertFunction( - SanCovTraceConstCmp4, SanCovTraceCmpZeroExtAL, VoidTy, Int32Ty, Int32Ty); - SanCovTraceConstCmpFunction[3] = - M.getOrInsertFunction(SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty); - - { - - AttributeList AL; - AL = AL.addParamAttribute(*C, 0, Attribute::ZExt); - SanCovTraceDivFunction[0] = - M.getOrInsertFunction(SanCovTraceDiv4, AL, VoidTy, IRB.getInt32Ty()); - - } - - SanCovTraceDivFunction[1] = - M.getOrInsertFunction(SanCovTraceDiv8, VoidTy, Int64Ty); - SanCovTraceGepFunction = - M.getOrInsertFunction(SanCovTraceGep, VoidTy, IntptrTy); - SanCovTraceSwitchFunction = - M.getOrInsertFunction(SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy); - - Constant *SanCovLowestStackConstant = - M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); - SanCovLowestStack = dyn_cast(SanCovLowestStackConstant); - if (!SanCovLowestStack) { - - C->emitError(StringRef("'") + SanCovLowestStackName + - "' should not be declared by the user"); - return true; - - } - - SanCovLowestStack->setThreadLocalMode( - GlobalValue::ThreadLocalMode::InitialExecTLSModel); - if (Options.StackDepth && !SanCovLowestStack->isDeclaration()) - SanCovLowestStack->setInitializer(Constant::getAllOnesValue(IntptrTy)); - - SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy); - SanCovTracePCGuard = - M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy); - - for (auto &F : M) - instrumentFunction(F, DTCallback, PDTCallback); - - Function *Ctor = nullptr; - - if (FunctionGuardArray) - Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName, - SanCovTracePCGuardInitName, Int32PtrTy, - SanCovGuardsSectionName); - if (Function8bitCounterArray) - Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName, - SanCov8bitCountersInitName, Int8PtrTy, - SanCovCountersSectionName); - if (FunctionBoolArray) { - - Ctor = CreateInitCallsForSections(M, SanCovModuleCtorBoolFlagName, - SanCovBoolFlagInitName, Int1PtrTy, - SanCovBoolFlagSectionName); - - } - - if (Ctor && Options.PCTable) { - - auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy); - FunctionCallee InitFunction = declareSanitizerInitFunction( - M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); - IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); - IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); - - } - - // We don't reference these arrays directly in any of our runtime functions, - // so we need to prevent them from being dead stripped. - if (TargetTriple.isOSBinFormatMachO()) appendToUsed(M, GlobalsToAppendToUsed); - appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); - - if (!be_quiet) { - - if (!instr) - WARNF("No instrumentation targets found."); - else { - - char modeline[100]; - snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s", - getenv("AFL_HARDEN") ? "hardened" : "non-hardened", - getenv("AFL_USE_ASAN") ? ", ASAN" : "", - getenv("AFL_USE_MSAN") ? ", MSAN" : "", - getenv("AFL_USE_TSAN") ? ", TSAN" : "", - getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", - getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); - OKF("Instrumented %u locations with no collisions (%s mode) of which are " - "%u handled and %u unhandled selects.", - instr, modeline, selects, unhandled); - - } - - } - - return true; - -} - -// True if block has successors and it dominates all of them. -bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) { - - if (succ_begin(BB) == succ_end(BB)) return false; - - for (const BasicBlock *SUCC : make_range(succ_begin(BB), succ_end(BB))) { - - if (!DT->dominates(BB, SUCC)) return false; - - } - - return true; - -} - -// True if block has predecessors and it postdominates all of them. -bool isFullPostDominator(const BasicBlock *BB, const PostDominatorTree *PDT) { - - if (pred_begin(BB) == pred_end(BB)) return false; - - for (const BasicBlock *PRED : make_range(pred_begin(BB), pred_end(BB))) { - - if (!PDT->dominates(BB, PRED)) return false; - - } - - return true; - -} - -bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, - const DominatorTree * DT, - const PostDominatorTree * PDT, - const SanitizerCoverageOptions &Options) { - - // Don't insert coverage for blocks containing nothing but unreachable: we - // will never call __sanitizer_cov() for them, so counting them in - // NumberOfInstrumentedBlocks() might complicate calculation of code coverage - // percentage. Also, unreachable instructions frequently have no debug - // locations. - if (isa(BB->getFirstNonPHIOrDbgOrLifetime())) return false; - - // Don't insert coverage into blocks without a valid insertion point - // (catchswitch blocks). - if (BB->getFirstInsertionPt() == BB->end()) return false; - - if (Options.NoPrune || &F.getEntryBlock() == BB) return true; - - if (Options.CoverageType == SanitizerCoverageOptions::SCK_Function && - &F.getEntryBlock() != BB) - return false; - - // Do not instrument full dominators, or full post-dominators with multiple - // predecessors. - return !isFullDominator(BB, DT) && - !(isFullPostDominator(BB, PDT) && !BB->getSinglePredecessor()); - -} - -// Returns true iff From->To is a backedge. -// A twist here is that we treat From->To as a backedge if -// * To dominates From or -// * To->UniqueSuccessor dominates From -bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT) { - - if (DT->dominates(To, From)) return true; - if (auto Next = To->getUniqueSuccessor()) - if (DT->dominates(Next, From)) return true; - return false; - -} - -// Prunes uninteresting Cmp instrumentation: -// * CMP instructions that feed into loop backedge branch. -// -// Note that Cmp pruning is controlled by the same flag as the -// BB pruning. -bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, - const SanitizerCoverageOptions &Options) { - - if (!Options.NoPrune) - if (CMP->hasOneUse()) - if (auto BR = dyn_cast(CMP->user_back())) - for (BasicBlock *B : BR->successors()) - if (IsBackEdge(BR->getParent(), B, DT)) return false; - return true; - -} - -void ModuleSanitizerCoverageAFL::instrumentFunction( - Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { - - if (F.empty()) return; - if (!isInInstrumentList(&F, FMNAME)) return; - - if (F.getName().find(".module_ctor") != std::string::npos) - return; // Should not instrument sanitizer init functions. - if (F.getName().startswith("__sanitizer_")) - return; // Don't instrument __sanitizer_* callbacks. - // Don't touch available_externally functions, their actual body is elewhere. - if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return; - // Don't instrument MSVC CRT configuration helpers. They may run before normal - // initialization. - if (F.getName() == "__local_stdio_printf_options" || - F.getName() == "__local_stdio_scanf_options") - return; - if (isa(F.getEntryBlock().getTerminator())) return; - // Don't instrument functions using SEH for now. Splitting basic blocks like - // we do for coverage breaks WinEHPrepare. - // FIXME: Remove this when SEH no longer uses landingpad pattern matching. - if (F.hasPersonalityFn() && - isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) - return; - if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) - SplitAllCriticalEdges( - F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); - SmallVector IndirCalls; - SmallVector BlocksToInstrument; - SmallVector CmpTraceTargets; - SmallVector SwitchTraceTargets; - SmallVector DivTraceTargets; - SmallVector GepTraceTargets; - - const DominatorTree * DT = DTCallback(F); - const PostDominatorTree *PDT = PDTCallback(F); - bool IsLeafFunc = true; - - for (auto &BB : F) { - - if (shouldInstrumentBlock(F, &BB, DT, PDT, Options)) - BlocksToInstrument.push_back(&BB); - for (auto &Inst : BB) { - - if (Options.IndirectCalls) { - - CallBase *CB = dyn_cast(&Inst); - if (CB && !CB->getCalledFunction()) IndirCalls.push_back(&Inst); - - } - - if (Options.TraceCmp) { - - if (ICmpInst *CMP = dyn_cast(&Inst)) - if (IsInterestingCmp(CMP, DT, Options)) - CmpTraceTargets.push_back(&Inst); - if (isa(&Inst)) SwitchTraceTargets.push_back(&Inst); - - } - - if (Options.TraceDiv) - if (BinaryOperator *BO = dyn_cast(&Inst)) - if (BO->getOpcode() == Instruction::SDiv || - BO->getOpcode() == Instruction::UDiv) - DivTraceTargets.push_back(BO); - if (Options.TraceGep) - if (GetElementPtrInst *GEP = dyn_cast(&Inst)) - GepTraceTargets.push_back(GEP); - if (Options.StackDepth) - if (isa(Inst) || - (isa(Inst) && !isa(Inst))) - IsLeafFunc = false; - - } - - } - - InjectCoverage(F, BlocksToInstrument, IsLeafFunc); - InjectCoverageForIndirectCalls(F, IndirCalls); - InjectTraceForCmp(F, CmpTraceTargets); - InjectTraceForSwitch(F, SwitchTraceTargets); - InjectTraceForDiv(F, DivTraceTargets); - InjectTraceForGep(F, GepTraceTargets); - -} - -GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection( - size_t NumElements, Function &F, Type *Ty, const char *Section) { - - ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); - auto Array = new GlobalVariable( - *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, - Constant::getNullValue(ArrayTy), "__sancov_gen_"); - -#if LLVM_VERSION_MAJOR >= 13 - if (TargetTriple.supportsCOMDAT() && - (TargetTriple.isOSBinFormatELF() || !F.isInterposable())) - if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple)) - Array->setComdat(Comdat); -#else - if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) - if (auto Comdat = - GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) - Array->setComdat(Comdat); -#endif - - Array->setSection(getSectionName(Section)); -#if (LLVM_VERSION_MAJOR >= 11) || \ - (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1) - Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); -#else - Array->setAlignment(Align(4)); // cheating -#endif - GlobalsToAppendToUsed.push_back(Array); - GlobalsToAppendToCompilerUsed.push_back(Array); - MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F)); - Array->addMetadata(LLVMContext::MD_associated, *MD); - - return Array; - -} - -GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( - Function &F, ArrayRef AllBlocks) { - - size_t N = AllBlocks.size(); - assert(N); - SmallVector PCs; - IRBuilder<> IRB(&*F.getEntryBlock().getFirstInsertionPt()); - for (size_t i = 0; i < N; i++) { - - if (&F.getEntryBlock() == AllBlocks[i]) { - - PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); - - } else { - - PCs.push_back((Constant *)IRB.CreatePointerCast( - BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); - - } - - } - - auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy, - SanCovPCsSectionName); - PCArray->setInitializer( - ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs)); - PCArray->setConstant(true); - - return PCArray; - -} - -void ModuleSanitizerCoverageAFL::CreateFunctionLocalArrays( - Function &F, ArrayRef AllBlocks, uint32_t special) { - - if (Options.TracePCGuard) - FunctionGuardArray = CreateFunctionLocalArrayInSection( - AllBlocks.size() + special, F, Int32Ty, SanCovGuardsSectionName); - - if (Options.Inline8bitCounters) - Function8bitCounterArray = CreateFunctionLocalArrayInSection( - AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName); - /* - if (Options.InlineBoolFlag) - FunctionBoolArray = CreateFunctionLocalArrayInSection( - AllBlocks.size(), F, Int1Ty, SanCovBoolFlagSectionName); - */ - if (Options.PCTable) FunctionPCsArray = CreatePCArray(F, AllBlocks); - -} - -bool ModuleSanitizerCoverageAFL::InjectCoverage( - Function &F, ArrayRef AllBlocks, bool IsLeafFunc) { - - uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0; - - for (auto &BB : F) { - - for (auto &IN : BB) { - - CallInst *callInst = nullptr; - - if ((callInst = dyn_cast(&IN))) { - - Function *Callee = callInst->getCalledFunction(); - if (!Callee) continue; - if (callInst->getCallingConv() != llvm::CallingConv::C) continue; - StringRef FuncName = Callee->getName(); - if (!FuncName.compare(StringRef("dlopen")) || - !FuncName.compare(StringRef("_dlopen"))) { - - fprintf(stderr, - "WARNING: dlopen() detected. To have coverage for a library " - "that your target dlopen()'s this must either happen before " - "__AFL_INIT() or you must use AFL_PRELOAD to preload all " - "dlopen()'ed libraries!\n"); - continue; - - } - - if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; - - cnt_cov++; - - } - - SelectInst *selectInst = nullptr; - - if ((selectInst = dyn_cast(&IN))) { - - Value *c = selectInst->getCondition(); - auto t = c->getType(); - if (t->getTypeID() == llvm::Type::IntegerTyID) { - - cnt_sel++; - cnt_sel_inc += 2; - - } - -#if (LLVM_VERSION_MAJOR >= 12) - else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { - - FixedVectorType *tt = dyn_cast(t); - if (tt) { - - cnt_sel++; - cnt_sel_inc += tt->getElementCount().getKnownMinValue(); - - } - - } - -#endif - - } - - } - - } - - /* Create PCGUARD array */ - CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel_inc); - selects += cnt_sel; - - uint32_t special = 0, local_selects = 0, skip_next = 0; - - for (auto &BB : F) { - - for (auto &IN : BB) { - - CallInst *callInst = nullptr; - - /* - std::string errMsg; - raw_string_ostream os(errMsg); - IN.print(os); - fprintf(stderr, "X: %s\n", os.str().c_str()); - */ - if ((callInst = dyn_cast(&IN))) { - - Function *Callee = callInst->getCalledFunction(); - if (!Callee) continue; - if (callInst->getCallingConv() != llvm::CallingConv::C) continue; - StringRef FuncName = Callee->getName(); - if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; - - IRBuilder<> IRB(callInst); - - Value *GuardPtr = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get(IntptrTy, (++special + AllBlocks.size()) * 4)), - Int32PtrTy); - - LoadInst *Idx = IRB.CreateLoad(IRB.getInt32Ty(), GuardPtr); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Idx); - - callInst->setOperand(1, Idx); - - } - - SelectInst *selectInst = nullptr; - - if (!skip_next && (selectInst = dyn_cast(&IN))) { - - uint32_t vector_cnt = 0; - Value * condition = selectInst->getCondition(); - Value * result; - auto t = condition->getType(); - IRBuilder<> IRB(selectInst->getNextNode()); - - if (t->getTypeID() == llvm::Type::IntegerTyID) { - - auto GuardPtr1 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), - Int32PtrTy); - - auto GuardPtr2 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), - Int32PtrTy); - - result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2); - - } else - -#if LLVM_VERSION_MAJOR >= 14 - if (t->getTypeID() == llvm::Type::FixedVectorTyID) { - - FixedVectorType *tt = dyn_cast(t); - if (tt) { - - uint32_t elements = tt->getElementCount().getFixedValue(); - vector_cnt = elements; - if (elements) { - - FixedVectorType *GuardPtr1 = - FixedVectorType::get(Int32PtrTy, elements); - FixedVectorType *GuardPtr2 = - FixedVectorType::get(Int32PtrTy, elements); - Value *x, *y; - - Value *val1 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), - Int32PtrTy); - x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0); - - Value *val2 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), - Int32PtrTy); - y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0); - - for (uint64_t i = 1; i < elements; i++) { - - val1 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get(IntptrTy, (cnt_cov + ++local_selects + - AllBlocks.size()) * - 4)), - Int32PtrTy); - x = IRB.CreateInsertElement(x, val1, i); - - val2 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get(IntptrTy, (cnt_cov + ++local_selects + - AllBlocks.size()) * - 4)), - Int32PtrTy); - y = IRB.CreateInsertElement(y, val2, i); - - } - - /* - std::string errMsg; - raw_string_ostream os(errMsg); - x->print(os); - fprintf(stderr, "X: %s\n", os.str().c_str()); - */ - result = IRB.CreateSelect(condition, x, y); - - } - - } - - } else - -#endif - { - - unhandled++; - continue; - - } - - uint32_t vector_cur = 0; - - /* Load SHM pointer */ - - LoadInst *MapPtr = - IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr); - - /* - std::string errMsg; - raw_string_ostream os(errMsg); - result->print(os); - fprintf(stderr, "X: %s\n", os.str().c_str()); - */ - - while (1) { - - /* Get CurLoc */ - LoadInst *CurLoc = nullptr; - Value * MapPtrIdx = nullptr; - - /* Load counter for CurLoc */ - if (!vector_cnt) { - - CurLoc = IRB.CreateLoad(IRB.getInt32Ty(), result); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(CurLoc); - MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc); - - } else { - - auto element = IRB.CreateExtractElement(result, vector_cur++); - auto elementptr = IRB.CreateIntToPtr(element, Int32PtrTy); - auto elementld = IRB.CreateLoad(IRB.getInt32Ty(), elementptr); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(elementld); - MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, elementld); - - } - - if (use_threadsafe_counters) { - - IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, -#if LLVM_VERSION_MAJOR >= 13 - llvm::MaybeAlign(1), -#endif - llvm::AtomicOrdering::Monotonic); - - } else { - - LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Counter); - - /* Update bitmap */ - - Value *Incr = IRB.CreateAdd(Counter, One); - - if (skip_nozero == NULL) { - - auto cf = IRB.CreateICmpEQ(Incr, Zero); - auto carry = IRB.CreateZExt(cf, Int8Ty); - Incr = IRB.CreateAdd(Incr, carry); - - } - - StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(StoreCtx); - - } - - if (!vector_cnt) { - - vector_cnt = 2; - break; - - } else if (vector_cnt == vector_cur) { - - break; - - } - - } - - skip_next = 1; - instr += vector_cnt; - - } else { - - skip_next = 0; - - } - - } - - } - - if (AllBlocks.empty() && !special && !local_selects) return false; - - if (!AllBlocks.empty()) - for (size_t i = 0, N = AllBlocks.size(); i < N; i++) - InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); - - return true; - -} - -// On every indirect call we call a run-time function -// __sanitizer_cov_indir_call* with two parameters: -// - callee address, -// - global cache array that contains CacheSize pointers (zero-initialized). -// The cache is used to speed up recording the caller-callee pairs. -// The address of the caller is passed implicitly via caller PC. -// CacheSize is encoded in the name of the run-time function. -void ModuleSanitizerCoverageAFL::InjectCoverageForIndirectCalls( - Function &F, ArrayRef IndirCalls) { - - if (IndirCalls.empty()) return; - for (auto I : IndirCalls) { - - IRBuilder<> IRB(I); - CallBase & CB = cast(*I); - Value * Callee = CB.getCalledOperand(); - if (isa(Callee)) continue; - IRB.CreateCall(SanCovTracePCIndir, IRB.CreatePointerCast(Callee, IntptrTy)); - - } - -} - -// For every switch statement we insert a call: -// __sanitizer_cov_trace_switch(CondValue, -// {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... }) - -void ModuleSanitizerCoverageAFL::InjectTraceForSwitch( - Function &, ArrayRef SwitchTraceTargets) { - - for (auto I : SwitchTraceTargets) { - - if (SwitchInst *SI = dyn_cast(I)) { - - IRBuilder<> IRB(I); - SmallVector Initializers; - Value * Cond = SI->getCondition(); - if (Cond->getType()->getScalarSizeInBits() > - Int64Ty->getScalarSizeInBits()) - continue; - Initializers.push_back(ConstantInt::get(Int64Ty, SI->getNumCases())); - Initializers.push_back( - ConstantInt::get(Int64Ty, Cond->getType()->getScalarSizeInBits())); - if (Cond->getType()->getScalarSizeInBits() < - Int64Ty->getScalarSizeInBits()) - Cond = IRB.CreateIntCast(Cond, Int64Ty, false); - for (auto It : SI->cases()) { - - Constant *C = It.getCaseValue(); - if (C->getType()->getScalarSizeInBits() < - Int64Ty->getScalarSizeInBits()) - C = ConstantExpr::getCast(CastInst::ZExt, It.getCaseValue(), Int64Ty); - Initializers.push_back(C); - - } - - llvm::sort(drop_begin(Initializers, 2), - [](const Constant *A, const Constant *B) { - - return cast(A)->getLimitedValue() < - cast(B)->getLimitedValue(); - - }); - - ArrayType *ArrayOfInt64Ty = ArrayType::get(Int64Ty, Initializers.size()); - GlobalVariable *GV = new GlobalVariable( - *CurModule, ArrayOfInt64Ty, false, GlobalVariable::InternalLinkage, - ConstantArray::get(ArrayOfInt64Ty, Initializers), - "__sancov_gen_cov_switch_values"); - IRB.CreateCall(SanCovTraceSwitchFunction, - {Cond, IRB.CreatePointerCast(GV, Int64PtrTy)}); - - } - - } - -} - -void ModuleSanitizerCoverageAFL::InjectTraceForDiv( - Function &, ArrayRef DivTraceTargets) { - - for (auto BO : DivTraceTargets) { - - IRBuilder<> IRB(BO); - Value * A1 = BO->getOperand(1); - if (isa(A1)) continue; - if (!A1->getType()->isIntegerTy()) continue; - uint64_t TypeSize = DL->getTypeStoreSizeInBits(A1->getType()); - int CallbackIdx = TypeSize == 32 ? 0 : TypeSize == 64 ? 1 : -1; - if (CallbackIdx < 0) continue; - auto Ty = Type::getIntNTy(*C, TypeSize); - IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx], - {IRB.CreateIntCast(A1, Ty, true)}); - - } - -} - -void ModuleSanitizerCoverageAFL::InjectTraceForGep( - Function &, ArrayRef GepTraceTargets) { - - for (auto GEP : GepTraceTargets) { - - IRBuilder<> IRB(GEP); - for (Use &Idx : GEP->indices()) - if (!isa(Idx) && Idx->getType()->isIntegerTy()) - IRB.CreateCall(SanCovTraceGepFunction, - {IRB.CreateIntCast(Idx, IntptrTy, true)}); - - } - -} - -void ModuleSanitizerCoverageAFL::InjectTraceForCmp( - Function &, ArrayRef CmpTraceTargets) { - - for (auto I : CmpTraceTargets) { - - if (ICmpInst *ICMP = dyn_cast(I)) { - - IRBuilder<> IRB(ICMP); - Value * A0 = ICMP->getOperand(0); - Value * A1 = ICMP->getOperand(1); - if (!A0->getType()->isIntegerTy()) continue; - uint64_t TypeSize = DL->getTypeStoreSizeInBits(A0->getType()); - int CallbackIdx = TypeSize == 8 ? 0 - : TypeSize == 16 ? 1 - : TypeSize == 32 ? 2 - : TypeSize == 64 ? 3 - : -1; - if (CallbackIdx < 0) continue; - // __sanitizer_cov_trace_cmp((type_size << 32) | predicate, A0, A1); - auto CallbackFunc = SanCovTraceCmpFunction[CallbackIdx]; - bool FirstIsConst = isa(A0); - bool SecondIsConst = isa(A1); - // If both are const, then we don't need such a comparison. - if (FirstIsConst && SecondIsConst) continue; - // If only one is const, then make it the first callback argument. - if (FirstIsConst || SecondIsConst) { - - CallbackFunc = SanCovTraceConstCmpFunction[CallbackIdx]; - if (SecondIsConst) std::swap(A0, A1); - - } - - auto Ty = Type::getIntNTy(*C, TypeSize); - IRB.CreateCall(CallbackFunc, {IRB.CreateIntCast(A0, Ty, true), - IRB.CreateIntCast(A1, Ty, true)}); - - } - - } - -} - -void ModuleSanitizerCoverageAFL::InjectCoverageAtBlock(Function & F, - BasicBlock &BB, - size_t Idx, - bool IsLeafFunc) { - - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - bool IsEntryBB = &BB == &F.getEntryBlock(); - - if (IsEntryBB) { - - // Keep allocas and llvm.localescape calls in the entry block. Even - // if we aren't splitting the block, it's nice for allocas to be before - // calls. - IP = PrepareToSplitEntryBlock(BB, IP); - - } - - IRBuilder<> IRB(&*IP); - - if (Options.TracePC) { - - IRB.CreateCall(SanCovTracePC); - // ->setCannotMerge(); // gets the PC using GET_CALLER_PC. - - } - - if (Options.TracePCGuard) { - - /* Get CurLoc */ - - Value *GuardPtr = IRB.CreateIntToPtr( - IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get(IntptrTy, Idx * 4)), - Int32PtrTy); - - LoadInst *CurLoc = IRB.CreateLoad(IRB.getInt32Ty(), GuardPtr); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(CurLoc); - - /* Load SHM pointer */ - - LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr); - - /* Load counter for CurLoc */ - - Value *MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc); - - if (use_threadsafe_counters) { - - IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, -#if LLVM_VERSION_MAJOR >= 13 - llvm::MaybeAlign(1), -#endif - llvm::AtomicOrdering::Monotonic); - - } else { - - LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Counter); - - /* Update bitmap */ - - Value *Incr = IRB.CreateAdd(Counter, One); - - if (skip_nozero == NULL) { - - auto cf = IRB.CreateICmpEQ(Incr, Zero); - auto carry = IRB.CreateZExt(cf, Int8Ty); - Incr = IRB.CreateAdd(Incr, carry); - - } - - StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx); - ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(StoreCtx); - - } - - // done :) - - // IRB.CreateCall(SanCovTracePCGuard, Offset)->setCannotMerge(); - // IRB.CreateCall(SanCovTracePCGuard, GuardPtr)->setCannotMerge(); - ++instr; - - } - - if (Options.Inline8bitCounters) { - - auto CounterPtr = IRB.CreateGEP( - Function8bitCounterArray->getValueType(), Function8bitCounterArray, - {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); - auto Load = IRB.CreateLoad(Int8Ty, CounterPtr); - auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1)); - auto Store = IRB.CreateStore(Inc, CounterPtr); - SetNoSanitizeMetadata(Load); - SetNoSanitizeMetadata(Store); - - } - - /* - if (Options.InlineBoolFlag) { - - auto FlagPtr = IRB.CreateGEP( - FunctionBoolArray->getValueType(), FunctionBoolArray, - {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); - auto Load = IRB.CreateLoad(Int1Ty, FlagPtr); - auto ThenTerm = - SplitBlockAndInsertIfThen(IRB.CreateIsNull(Load), &*IP, false); - IRBuilder<> ThenIRB(ThenTerm); - auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr); - SetNoSanitizeMetadata(Load); - SetNoSanitizeMetadata(Store); - - } - - */ - - if (Options.StackDepth && IsEntryBB && !IsLeafFunc) { - - // Check stack depth. If it's the deepest so far, record it. - Module * M = F.getParent(); - Function *GetFrameAddr = Intrinsic::getDeclaration( - M, Intrinsic::frameaddress, - IRB.getInt8PtrTy(M->getDataLayout().getAllocaAddrSpace())); - auto FrameAddrPtr = - IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)}); - auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy); - auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack); - auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); - auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false); - IRBuilder<> ThenIRB(ThenTerm); - auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); - SetNoSanitizeMetadata(LowestStack); - SetNoSanitizeMetadata(Store); - - } - -} - -std::string ModuleSanitizerCoverageAFL::getSectionName( - const std::string &Section) const { - - if (TargetTriple.isOSBinFormatCOFF()) { - - if (Section == SanCovCountersSectionName) return ".SCOV$CM"; - if (Section == SanCovBoolFlagSectionName) return ".SCOV$BM"; - if (Section == SanCovPCsSectionName) return ".SCOVP$M"; - return ".SCOV$GM"; // For SanCovGuardsSectionName. - - } - - if (TargetTriple.isOSBinFormatMachO()) return "__DATA,__" + Section; - return "__" + Section; - -} - -std::string ModuleSanitizerCoverageAFL::getSectionStart( - const std::string &Section) const { - - if (TargetTriple.isOSBinFormatMachO()) - return "\1section$start$__DATA$__" + Section; - return "__start___" + Section; - -} - -std::string ModuleSanitizerCoverageAFL::getSectionEnd( - const std::string &Section) const { - - if (TargetTriple.isOSBinFormatMachO()) - return "\1section$end$__DATA$__" + Section; - return "__stop___" + Section; - -} - -#if 0 - -char ModuleSanitizerCoverageLegacyPass::ID = 0; -INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov", - "Pass for instrumenting coverage on functions", false, - false) -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) -INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov", - "Pass for instrumenting coverage on functions", false, - false) -ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( - const SanitizerCoverageOptions &Options, - const std::vector &AllowlistFiles, - const std::vector &BlocklistFiles) { - - return new ModuleSanitizerCoverageLegacyPass(Options, AllowlistFiles, - BlocklistFiles); - -} - -#endif - diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index f87bc068..b837a033 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -42,6 +42,9 @@ #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/ModuleUtils.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/IR/PassManager.h" #include "config.h" #include "debug.h" @@ -121,21 +124,18 @@ using DomTreeCallback = function_ref; using PostDomTreeCallback = function_ref; -class ModuleSanitizerCoverage { +class ModuleSanitizerCoverageAFL + : public PassInfoMixin { public: - ModuleSanitizerCoverage( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions() -#if (LLVM_VERSION_MAJOR >= 11) - , - const SpecialCaseList *Allowlist = nullptr, - const SpecialCaseList *Blocklist = nullptr -#endif - ) + ModuleSanitizerCoverageAFL( + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) : Options(OverrideFromCL(Options)) { } + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); + bool instrumentModule(Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); @@ -213,15 +213,7 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { public: ModuleSanitizerCoverageLegacyPass( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions() -#if LLVM_VERSION_MAJOR >= 11 - , - const std::vector &AllowlistFiles = - std::vector(), - const std::vector &BlocklistFiles = - std::vector() -#endif - ) + const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) : ModulePass(ID), Options(Options) { initializeModuleSanitizerCoverageLegacyPassPass( @@ -231,12 +223,7 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { bool runOnModule(Module &M) override { - ModuleSanitizerCoverage ModuleSancov(Options -#if (LLVM_VERSION_MAJOR >= 11) - , - Allowlist.get(), Blocklist.get() -#endif - ); + ModuleSanitizerCoverageAFL ModuleSancov(Options); auto DTCallback = [this](Function &F) -> const DominatorTree * { return &this->getAnalysis(F).getDomTree(); @@ -271,24 +258,39 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { private: SanitizerCoverageOptions Options; - std::unique_ptr Allowlist; - std::unique_ptr Blocklist; - }; } // namespace -PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M, - ModuleAnalysisManager &MAM) { +#if 1 + +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "SanitizerCoveragePCGUARD", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { - fprintf(stderr, "ModuleSanitizerCoveragePass::run is called!\n"); + MPM.addPass(ModuleSanitizerCoverageAFL()); + + }); + + }}; + +} - ModuleSanitizerCoverage ModuleSancov(Options -#if (LLVM_VERSION_MAJOR >= 11) - , - Allowlist.get(), Blocklist.get() #endif - ); + +PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module & M, + ModuleAnalysisManager &MAM) { + + ModuleSanitizerCoverageAFL ModuleSancov(Options); auto &FAM = MAM.getResult(M).getManager(); auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { @@ -308,7 +310,7 @@ PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M, } -std::pair ModuleSanitizerCoverage::CreateSecStartEnd( +std::pair ModuleSanitizerCoverageAFL::CreateSecStartEnd( Module &M, const char *Section, Type *Ty) { GlobalVariable *SecStart = new GlobalVariable( @@ -332,7 +334,7 @@ std::pair ModuleSanitizerCoverage::CreateSecStartEnd( } -Function *ModuleSanitizerCoverage::CreateInitCallsForSections( +Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections( Module &M, const char *CtorName, const char *InitFunctionName, Type *Ty, const char *Section) { @@ -373,7 +375,7 @@ Function *ModuleSanitizerCoverage::CreateInitCallsForSections( } -bool ModuleSanitizerCoverage::instrumentModule( +bool ModuleSanitizerCoverageAFL::instrumentModule( Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { setvbuf(stdout, NULL, _IONBF, 0); @@ -656,7 +658,7 @@ bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, } -void ModuleSanitizerCoverage::instrumentFunction( +void ModuleSanitizerCoverageAFL::instrumentFunction( Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { if (F.empty()) return; @@ -742,7 +744,7 @@ void ModuleSanitizerCoverage::instrumentFunction( } -GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( +GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection( size_t NumElements, Function &F, Type *Ty, const char *Section) { ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); @@ -778,7 +780,7 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( } -GlobalVariable *ModuleSanitizerCoverage::CreatePCArray( +GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( Function &F, ArrayRef AllBlocks) { size_t N = AllBlocks.size(); @@ -814,7 +816,7 @@ GlobalVariable *ModuleSanitizerCoverage::CreatePCArray( } -void ModuleSanitizerCoverage::CreateFunctionLocalArrays( +void ModuleSanitizerCoverageAFL::CreateFunctionLocalArrays( Function &F, ArrayRef AllBlocks, uint32_t special) { if (Options.TracePCGuard) @@ -833,9 +835,8 @@ void ModuleSanitizerCoverage::CreateFunctionLocalArrays( } -bool ModuleSanitizerCoverage::InjectCoverage(Function & F, - ArrayRef AllBlocks, - bool IsLeafFunc) { +bool ModuleSanitizerCoverageAFL::InjectCoverage( + Function &F, ArrayRef AllBlocks, bool IsLeafFunc) { uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0; @@ -938,7 +939,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, Int32PtrTy); LoadInst *Idx = IRB.CreateLoad(IRB.getInt32Ty(), GuardPtr); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(Idx); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Idx); callInst->setOperand(1, Idx); @@ -1060,7 +1061,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr); /* std::string errMsg; @@ -1079,7 +1080,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, if (!vector_cnt) { CurLoc = IRB.CreateLoad(IRB.getInt32Ty(), result); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(CurLoc); MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc); } else { @@ -1087,7 +1088,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, auto element = IRB.CreateExtractElement(result, vector_cur++); auto elementptr = IRB.CreateIntToPtr(element, Int32PtrTy); auto elementld = IRB.CreateLoad(IRB.getInt32Ty(), elementptr); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(elementld); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(elementld); MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, elementld); } @@ -1103,7 +1104,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } else { LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Counter); /* Update bitmap */ @@ -1118,7 +1119,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreCtx); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(StoreCtx); } @@ -1165,7 +1166,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, // The cache is used to speed up recording the caller-callee pairs. // The address of the caller is passed implicitly via caller PC. // CacheSize is encoded in the name of the run-time function. -void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls( +void ModuleSanitizerCoverageAFL::InjectCoverageForIndirectCalls( Function &F, ArrayRef IndirCalls) { if (IndirCalls.empty()) return; @@ -1185,7 +1186,7 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls( // __sanitizer_cov_trace_switch(CondValue, // {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... }) -void ModuleSanitizerCoverage::InjectTraceForSwitch( +void ModuleSanitizerCoverageAFL::InjectTraceForSwitch( Function &, ArrayRef SwitchTraceTargets) { for (auto I : SwitchTraceTargets) { @@ -1236,7 +1237,7 @@ void ModuleSanitizerCoverage::InjectTraceForSwitch( } -void ModuleSanitizerCoverage::InjectTraceForDiv( +void ModuleSanitizerCoverageAFL::InjectTraceForDiv( Function &, ArrayRef DivTraceTargets) { for (auto BO : DivTraceTargets) { @@ -1256,7 +1257,7 @@ void ModuleSanitizerCoverage::InjectTraceForDiv( } -void ModuleSanitizerCoverage::InjectTraceForGep( +void ModuleSanitizerCoverageAFL::InjectTraceForGep( Function &, ArrayRef GepTraceTargets) { for (auto GEP : GepTraceTargets) { @@ -1271,7 +1272,7 @@ void ModuleSanitizerCoverage::InjectTraceForGep( } -void ModuleSanitizerCoverage::InjectTraceForCmp( +void ModuleSanitizerCoverageAFL::InjectTraceForCmp( Function &, ArrayRef CmpTraceTargets) { for (auto I : CmpTraceTargets) { @@ -1313,9 +1314,10 @@ void ModuleSanitizerCoverage::InjectTraceForCmp( } -void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, - size_t Idx, - bool IsLeafFunc) { +void ModuleSanitizerCoverageAFL::InjectCoverageAtBlock(Function & F, + BasicBlock &BB, + size_t Idx, + bool IsLeafFunc) { BasicBlock::iterator IP = BB.getFirstInsertionPt(); bool IsEntryBB = &BB == &F.getEntryBlock(); @@ -1348,12 +1350,12 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, Int32PtrTy); LoadInst *CurLoc = IRB.CreateLoad(IRB.getInt32Ty(), GuardPtr); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(CurLoc); /* Load SHM pointer */ LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr); /* Load counter for CurLoc */ @@ -1370,7 +1372,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } else { LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(Counter); /* Update bitmap */ @@ -1385,7 +1387,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreCtx); + ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(StoreCtx); } @@ -1450,7 +1452,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } -std::string ModuleSanitizerCoverage::getSectionName( +std::string ModuleSanitizerCoverageAFL::getSectionName( const std::string &Section) const { if (TargetTriple.isOSBinFormatCOFF()) { @@ -1467,7 +1469,7 @@ std::string ModuleSanitizerCoverage::getSectionName( } -std::string ModuleSanitizerCoverage::getSectionStart( +std::string ModuleSanitizerCoverageAFL::getSectionStart( const std::string &Section) const { if (TargetTriple.isOSBinFormatMachO()) @@ -1476,7 +1478,7 @@ std::string ModuleSanitizerCoverage::getSectionStart( } -std::string ModuleSanitizerCoverage::getSectionEnd( +std::string ModuleSanitizerCoverageAFL::getSectionEnd( const std::string &Section) const { if (TargetTriple.isOSBinFormatMachO()) @@ -1485,13 +1487,15 @@ std::string ModuleSanitizerCoverage::getSectionEnd( } +#if 0 + char ModuleSanitizerCoverageLegacyPass::ID = 0; -INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancovAFL", +INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov", "Pass for instrumenting coverage on functions", false, false) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass) -INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancovAFL", +INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov", "Pass for instrumenting coverage on functions", false, false) ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( @@ -1504,3 +1508,5 @@ ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( } +#endif + diff --git a/src/afl-cc.c b/src/afl-cc.c index fae572f6..a7248325 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -624,11 +624,17 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { + #if LLVM_MAJOR >= 11 /* use new pass manager */ + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = alloc_printf( + "-fpass-plugin=%s/SanitizerCoveragePCGUARD.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/SanitizerCoveragePCGUARD.so", obj_path); + #endif } -- cgit 1.4.1 From e4f201707fdfbf9a36b6a48c16f75b0fef2c9e75 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 17 Mar 2022 14:35:15 +0100 Subject: make LTO pass work too plus some fixes --- GNUmakefile | 2 +- GNUmakefile.gcc_plugin | 4 ++-- GNUmakefile.llvm | 14 +++++++------- instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 +- src/afl-cc.c | 3 +++ src/afl-ld-lto.c | 4 ++-- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 6392fceb..48dc6ddf 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -570,7 +570,7 @@ all_done: test_build .PHONY: clean clean: - rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM + rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM lib*.a -$(MAKE) -f GNUmakefile.llvm clean -$(MAKE) -f GNUmakefile.gcc_plugin clean -$(MAKE) -C utils/libdislocator clean diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin index 63b22017..e21203ae 100644 --- a/GNUmakefile.gcc_plugin +++ b/GNUmakefile.gcc_plugin @@ -135,11 +135,11 @@ afl-common.o: ./src/afl-common.c ./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c @printf "[*] Building 32-bit variant of the runtime (-m32)... " - @$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-32.o afl-llvm-rt-32.o; else echo "failed (that's fine)"; fi + @$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi ./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c @printf "[*] Building 64-bit variant of the runtime (-m64)... " - @$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-64.o afl-llvm-rt-64.o; else echo "failed (that's fine)"; fi + @$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi ./afl-gcc-pass.so: instrumentation/afl-gcc-pass.so.cc | test_deps $(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@ diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index f1de28a4..a8f019c6 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -394,7 +394,7 @@ endif ./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps ifeq "$(LLVM_10_OK)" "1" - -$(CXX) $(CLANG_CPPFL) -Wdeprecated -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o + -$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-with-dtor -Wdeprecated instrumentation/afl-llvm-common.o endif ./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o @@ -447,11 +447,11 @@ document: ./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c @printf "[*] Building 32-bit variant of the runtime (-m32)... " - @$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-32.o afl-llvm-rt-32.o; else echo "failed (that's fine)"; fi + @$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi ./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c @printf "[*] Building 64-bit variant of the runtime (-m64)... " - @$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; ln -sf afl-compiler-rt-64.o afl-llvm-rt-64.o; else echo "failed (that's fine)"; fi + @$(CC) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi .PHONY: test_build test_build: $(PROGS) @@ -474,11 +474,11 @@ install: all @install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) @if [ -f ./afl-cc ]; then set -e; install -m 755 ./afl-cc $${DESTDIR}$(BIN_PATH); ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-c++; fi @rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt*.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt*.o - @if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt.o ;fi + @if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-compiler-rt.o ;fi @if [ -f ./afl-lto ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto++; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ./afl-llvm-rt-lto*.o ./afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi @if [ -f ./afl-ld-lto ]; then set -e; install -m 755 ./afl-ld-lto $${DESTDIR}$(BIN_PATH); fi - @if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-32.o ;fi - @if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o ; fi + @if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-compiler-rt-32.o ;fi + @if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-compiler-rt-64.o ; fi @if [ -f ./compare-transform-pass.so ]; then set -e; install -m 755 ./*.so $${DESTDIR}$(HELPER_PATH); fi @if [ -f ./compare-transform-pass.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-fast ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-fast++ ; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang++ ; fi @if [ -f ./SanitizerCoverageLTO.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-lto++ ; fi @@ -520,4 +520,4 @@ endif .PHONY: clean clean: rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo - rm -f $(PROGS) afl-common.o ./afl-c++ ./afl-lto ./afl-lto++ ./afl-clang-lto* ./afl-clang-fast* ./afl-clang*.8 ./ld ./afl-ld ./afl-llvm-rt*.o instrumentation/*.o + rm -f $(PROGS) afl-common.o ./afl-c++ ./afl-lto ./afl-lto++ ./afl-clang-lto* ./afl-clang-fast* ./afl-clang*.8 ./ld ./afl-ld ./afl-compiler-rt*.o ./afl-llvm-rt*.o instrumentation/*.o diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index b837a033..a5d8f895 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -241,7 +241,7 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { } - static char ID; // Pass identification, replacement for typeid + /*static*/ char ID; // Pass identification, replacement for typeid StringRef getPassName() const override { return "ModuleSanitizerCoverage"; diff --git a/src/afl-cc.c b/src/afl-cc.c index a7248325..4c977303 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -599,6 +599,9 @@ static void edit_params(u32 argc, char **argv, char **envp) { free(ld_path); cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 + cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager"; +#endif cc_params[cc_par_cnt++] = alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); cc_params[cc_par_cnt++] = lto_flag; diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 9b58125f..f2f95fd7 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -86,7 +86,7 @@ static void edit_params(int argc, char **argv) { for (i = 1; i < (u32)argc; i++) { if (strstr(argv[i], "/afl-llvm-rt-lto.o") != NULL) rt_lto_present = 1; - if (strstr(argv[i], "/afl-llvm-rt.o") != NULL) rt_present = 1; + if (strstr(argv[i], "/afl-compiler-rt.o") != NULL) rt_present = 1; if (strstr(argv[i], "/afl-llvm-lto-instr") != NULL) inst_present = 1; } @@ -237,7 +237,7 @@ static void edit_params(int argc, char **argv) { } if (!rt_present) - ld_params[ld_param_cnt++] = alloc_printf("%s/afl-llvm-rt.o", afl_path); + ld_params[ld_param_cnt++] = alloc_printf("%s/afl-compiler-rt.o", afl_path); if (!rt_lto_present) ld_params[ld_param_cnt++] = alloc_printf("%s/afl-llvm-rt-lto.o", afl_path); -- cgit 1.4.1 From 3c11a377570512efeb3a197148ff1b7dddbd8e32 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 17 Mar 2022 15:48:06 +0100 Subject: fixes for llvm < 11 --- instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 +- instrumentation/afl-llvm-dict2file.so.cc | 111 ++++++++++++------------- instrumentation/compare-transform-pass.so.cc | 19 +++-- src/afl-ld-lto.c | 3 +- 4 files changed, 69 insertions(+), 66 deletions(-) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index a5d8f895..e234cf57 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -242,7 +242,7 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { } /*static*/ char ID; // Pass identification, replacement for typeid - StringRef getPassName() const override { + StringRef getPassName() const override { return "ModuleSanitizerCoverage"; diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 37cd8ad0..79cdf491 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -45,7 +45,6 @@ #include "llvm/IR/PassManager.h" #else #include "llvm/IR/LegacyPassManager.h" - #include "llvm/Transforms/IPO/PassManagerBuilder.h" #endif #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Module.h" @@ -67,47 +66,6 @@ #define O_DSYNC O_SYNC #endif -std::ofstream of; - -void dict2file(u8 *mem, u32 len) { - - u32 i, j, binary = 0; - char line[MAX_AUTO_EXTRA * 8], tmp[8]; - - strcpy(line, "\""); - j = 1; - for (i = 0; i < len; i++) { - - if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') { - - line[j++] = mem[i]; - - } else { - - if (i + 1 != len || mem[i] != 0 || binary || len == 4 || len == 8) { - - line[j] = 0; - sprintf(tmp, "\\x%02x", (u8)mem[i]); - strcat(line, tmp); - j = strlen(line); - - } - - binary = 1; - - } - - } - - line[j] = 0; - strcat(line, "\"\n"); - of << line; - of.flush(); - - if (!be_quiet) fprintf(stderr, "Found dictionary token: %s", line); - -} - using namespace llvm; namespace { @@ -115,14 +73,22 @@ namespace { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ class AFLdict2filePass : public PassInfoMixin { + std::ofstream of; + void dict2file(u8 *, u32); + public: AFLdict2filePass() { #else + class AFLdict2filePass : public ModulePass { + std::ofstream of; + void dict2file(u8 *, u32); + public: - bool runOnModule(Module &M) override; + static char ID; + AFLdict2filePass() : ModulePass(ID) { #endif @@ -133,6 +99,8 @@ class AFLdict2filePass : public ModulePass { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else + bool runOnModule(Module &M) override; #endif }; @@ -143,7 +111,7 @@ class AFLdict2filePass : public ModulePass { extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() { - return {LLVM_PLUGIN_API_VERSION, "dict2file", "v0.1", + return {LLVM_PLUGIN_API_VERSION, "AFLdict2filePass", "v0.1", /* lambda to insert our pass into the pass pipeline. */ [](PassBuilder &PB) { @@ -162,16 +130,52 @@ llvmGetPassPluginInfo() { } #else - char AFLdict2filePass::ID = 0; - #endif +void AFLdict2filePass::dict2file(u8 *mem, u32 len) { + + u32 i, j, binary = 0; + char line[MAX_AUTO_EXTRA * 8], tmp[8]; + + strcpy(line, "\""); + j = 1; + for (i = 0; i < len; i++) { + + if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') { + + line[j++] = mem[i]; + + } else { + + if (i + 1 != len || mem[i] != 0 || binary || len == 4 || len == 8) { + + line[j] = 0; + sprintf(tmp, "\\x%02x", (u8)mem[i]); + strcat(line, tmp); + j = strlen(line); + + } + + binary = 1; + + } + + } + + line[j] = 0; + strcat(line, "\"\n"); + of << line; + of.flush(); + + if (!be_quiet) fprintf(stderr, "Found dictionary token: %s", line); + +} + #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ PreservedAnalyses AFLdict2filePass::run(Module &M, ModuleAnalysisManager &MAM) { #else - bool AFLdict2filePass::runOnModule(Module &M) { #endif @@ -640,6 +644,7 @@ bool AFLdict2filePass::runOnModule(Module &M) { if (optLen < 2) { continue; } if (literalLength + 1 == optLen) { // add null byte + thestring.append("\0", 1); } @@ -662,17 +667,11 @@ bool AFLdict2filePass::runOnModule(Module &M) { } */ - - if (!isStdString) { + if (!isStdString && thestring.find('\0', 0) != std::string::npos) { // ensure we do not have garbage size_t offset = thestring.find('\0', 0); - if (offset && offset < optLen && offset + 1 < optLen) { - - optLen = offset + 1; - - } - + if (offset + 1 < optLen) optLen = offset + 1; thestring = thestring.substr(0, optLen); } @@ -716,8 +715,6 @@ bool AFLdict2filePass::runOnModule(Module &M) { #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ auto PA = PreservedAnalyses::all(); -#endif -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ return PA; #else return true; diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index 4e471ea3..34c88735 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -88,21 +88,26 @@ class CompareTransform : public ModulePass { const char *getPassName() const override { #endif + + return "cmplog transform"; + + } + #endif #if LLVM_MAJOR >= 11 /* use new pass manager */ - PreservedAnalyses run(Module & M, ModuleAnalysisManager & MAM); + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else bool runOnModule(Module &M) override; #endif - private: - bool transformCmps(Module & M, const bool processStrcmp, - const bool processMemcmp, const bool processStrncmp, - const bool processStrcasecmp, - const bool processStrncasecmp); + private: + bool transformCmps(Module &M, const bool processStrcmp, + const bool processMemcmp, const bool processStrncmp, + const bool processStrcasecmp, + const bool processStrncasecmp); - }; +}; } // namespace diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index f2f95fd7..5797def8 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -237,7 +237,8 @@ static void edit_params(int argc, char **argv) { } if (!rt_present) - ld_params[ld_param_cnt++] = alloc_printf("%s/afl-compiler-rt.o", afl_path); + ld_params[ld_param_cnt++] = + alloc_printf("%s/afl-compiler-rt.o", afl_path); if (!rt_lto_present) ld_params[ld_param_cnt++] = alloc_printf("%s/afl-llvm-rt-lto.o", afl_path); -- cgit 1.4.1 From 3d1be62c96f2f10963b8fa6f3946e44e40e6b8b3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 17 Mar 2022 16:39:40 +0100 Subject: merge fixes --- instrumentation/afl-llvm-pass.so.cc | 91 +++++++++++++++++- instrumentation/cmplog-instructions-pass.cc | 8 +- instrumentation/compare-transform-pass.so.cc | 105 +++++++++++++++++++-- instrumentation/split-compares-pass.so.cc | 132 ++++++++++++++++++++++++--- instrumentation/split-switches-pass.so.cc | 107 ++++++++++++++++++++-- src/afl-cc.c | 37 ++++++-- 6 files changed, 435 insertions(+), 45 deletions(-) diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index 6419cd1d..be8099bb 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -46,12 +46,21 @@ typedef long double max_align_t; #include "llvm/IR/IRBuilder.h" #include "llvm/Pass.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) @@ -69,17 +78,30 @@ using namespace llvm; namespace { +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +class AFLCoverage : public PassInfoMixin { + + public: + AFLCoverage() { + +#else class AFLCoverage : public ModulePass { public: static char ID; AFLCoverage() : ModulePass(ID) { +#endif + initInstrumentList(); } +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else bool runOnModule(Module &M) override; +#endif protected: uint32_t ngram_size = 0; @@ -93,7 +115,55 @@ class AFLCoverage : public ModulePass { } // namespace +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if 1 + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(AFLCoverage()); + + }); + + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + + if (Name == "AFLCoverage") { + + MPM.addPass(AFLCoverage()); + return true; + + } else { + + return false; + + } + + }); + + #endif + + }}; + +} + +#else + char AFLCoverage::ID = 0; +#endif /* needed up to 3.9.0 */ #if LLVM_VERSION_MAJOR == 3 && \ @@ -119,8 +189,15 @@ uint64_t PowerOf2Ceil(unsigned in) { (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) #define AFL_HAVE_VECTOR_INTRINSICS 1 #endif + +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) { + +#else bool AFLCoverage::runOnModule(Module &M) { +#endif + LLVMContext &C = M.getContext(); IntegerType *Int8Ty = IntegerType::getInt8Ty(C); @@ -134,6 +211,10 @@ bool AFLCoverage::runOnModule(Module &M) { u32 rand_seed; unsigned int cur_loc = 0; +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif + /* Setup random() so we get Actually Random(TM) outputs from AFL_R() */ gettimeofday(&tv, &tz); rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); @@ -998,10 +1079,15 @@ bool AFLCoverage::runOnModule(Module &M) { } +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + return PA; +#else return true; +#endif } +#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerAFLPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -1014,4 +1100,5 @@ static RegisterStandardPasses RegisterAFLPass( static RegisterStandardPasses RegisterAFLPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass); +#endif diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 85dec437..7c95d9bb 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -28,7 +28,6 @@ #include "llvm/Config/llvm-config.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -138,7 +137,7 @@ llvmGetPassPluginInfo() { #else char CmpLogInstructions::ID = 0; #endif - + template Iterator Unique(Iterator first, Iterator last) { @@ -686,10 +685,10 @@ bool CmpLogInstructions::runOnModule(Module &M) { #else return true; #endif - + } -#if LLVM_MAJOR < 11 /* use old pass manager */ +#if LLVM_MAJOR < 11 /* use old pass manager */ static void registerCmpLogInstructionsPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -710,3 +709,4 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO( registerCmpLogInstructionsPass); #endif #endif + diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index 9a4e4f00..34c88735 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -26,14 +26,23 @@ #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #if LLVM_VERSION_MAJOR >= 4 || \ (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) @@ -52,12 +61,21 @@ using namespace llvm; namespace { +#if LLVM_MAJOR >= 11 /* use new pass manager */ +class CompareTransform : public PassInfoMixin { + + public: + CompareTransform() { + +#else class CompareTransform : public ModulePass { public: static char ID; CompareTransform() : ModulePass(ID) { +#endif + initInstrumentList(); } @@ -70,17 +88,18 @@ class CompareTransform : public ModulePass { const char *getPassName() const override { #endif - return "transforms compare functions"; + + return "cmplog transform"; } #endif - //#if LLVM_MAJOR >= 11 /* use new pass manager */ - // PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); - //#else +#if LLVM_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else bool runOnModule(Module &M) override; - //#endif +#endif private: bool transformCmps(Module &M, const bool processStrcmp, @@ -92,7 +111,54 @@ class CompareTransform : public ModulePass { } // namespace +#if LLVM_MAJOR >= 11 /* use new pass manager */ +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "comparetransform", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if 1 + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(CompareTransform()); + + }); + + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + + if (Name == "comparetransform") { + + MPM.addPass(CompareTransform()); + return true; + + } else { + + return false; + + } + + }); + + #endif + + }}; + +} + +#else char CompareTransform::ID = 0; +#endif bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, const bool processMemcmp, @@ -392,6 +458,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, bool isCaseInsensitive = false; bool needs_null = false; Function * Callee = callInst->getCalledFunction(); + if (Callee) { if (!Callee->getName().compare("memcmp") || @@ -649,8 +716,14 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, } +#if LLVM_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses CompareTransform::run(Module &M, ModuleAnalysisManager &MAM) { + +#else bool CompareTransform::runOnModule(Module &M) { +#endif + if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) printf( "Running compare-transform-pass by laf.intel@gmail.com, extended by " @@ -658,13 +731,28 @@ bool CompareTransform::runOnModule(Module &M) { else be_quiet = 1; +#if LLVM_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif + transformCmps(M, true, true, true, true, true); verifyModule(M); +#if LLVM_MAJOR >= 11 /* use new pass manager */ + /* if (modified) { + + PA.abandon(); + + }*/ + + return PA; +#else return true; +#endif } +#if LLVM_MAJOR < 11 /* use old pass manager */ static void registerCompTransPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -679,8 +767,9 @@ static RegisterStandardPasses RegisterCompTransPass( static RegisterStandardPasses RegisterCompTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterCompTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass); + #endif #endif diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index 0f00fa96..d7bb7aba 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -1,6 +1,7 @@ /* * Copyright 2016 laf-intel * extended for floating point by Heiko Eißfeldt + * adapted to new pass manager by Heiko Eißfeldt * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,10 +29,20 @@ #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" + +#if LLVM_MAJOR >= 11 + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/IR/Module.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ @@ -53,27 +64,31 @@ using namespace llvm; namespace { +#if LLVM_MAJOR >= 11 +class SplitComparesTransform : public PassInfoMixin { + + public: + // static char ID; + SplitComparesTransform() : enableFPSplit(0) { + +#else class SplitComparesTransform : public ModulePass { public: static char ID; SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) { +#endif + initInstrumentList(); } - bool runOnModule(Module &M) override; -#if LLVM_VERSION_MAJOR >= 4 - StringRef getPassName() const override { - +#if LLVM_MAJOR >= 11 + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); #else - const char *getPassName() const override { - + bool runOnModule(Module &M) override; #endif - return "AFL_SplitComparesTransform"; - - } private: int enableFPSplit; @@ -162,7 +177,54 @@ class SplitComparesTransform : public ModulePass { } // namespace +#if LLVM_MAJOR >= 11 +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "splitcompares", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if 1 + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(SplitComparesTransform()); + + }); + + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + + if (Name == "splitcompares") { + + MPM.addPass(SplitComparesTransform()); + return true; + + } else { + + return false; + + } + + }); + + #endif + + }}; + +} + +#else char SplitComparesTransform::ID = 0; +#endif /// This function splits FCMP instructions with xGE or xLE predicates into two /// FCMP instructions with predicate xGT or xLT and EQ @@ -1421,8 +1483,15 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } +#if LLVM_MAJOR >= 11 +PreservedAnalyses SplitComparesTransform::run(Module & M, + ModuleAnalysisManager &MAM) { + +#else bool SplitComparesTransform::runOnModule(Module &M) { +#endif + char *bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW"); if (!bitw_env) bitw_env = getenv("LAF_SPLIT_COMPARES_BITW"); if (bitw_env) { target_bitwidth = atoi(bitw_env); } @@ -1432,7 +1501,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) { - errs() << "Split-compare-pass by laf.intel@gmail.com, extended by " + errs() << "Split-compare-newpass by laf.intel@gmail.com, extended by " "heiko@hexco.de (splitting icmp to " << target_bitwidth << " bit)\n"; @@ -1444,6 +1513,10 @@ bool SplitComparesTransform::runOnModule(Module &M) { } +#if LLVM_MAJOR >= 11 + auto PA = PreservedAnalyses::all(); +#endif + if (enableFPSplit) { simplifyFPCompares(M); @@ -1473,7 +1546,16 @@ bool SplitComparesTransform::runOnModule(Module &M) { auto op0 = CI->getOperand(0); auto op1 = CI->getOperand(1); - if (!op0 || !op1) { return false; } + if (!op0 || !op1) { + +#if LLVM_MAJOR >= 11 + return PA; +#else + return false; +#endif + + } + auto iTy1 = dyn_cast(op0->getType()); if (iTy1 && isa(op1->getType())) { @@ -1522,10 +1604,29 @@ bool SplitComparesTransform::runOnModule(Module &M) { } + if ((isatty(2) && getenv("AFL_QUIET") == NULL) || + getenv("AFL_DEBUG") != NULL) { + + errs() << count << " comparisons found\n"; + + } + +#if LLVM_MAJOR >= 11 + /* if (modified) { + + PA.abandon(); + + }*/ + + return PA; +#else return true; +#endif } +#if LLVM_MAJOR < 11 /* use old pass manager */ + static void registerSplitComparesPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -1539,14 +1640,15 @@ static RegisterStandardPasses RegisterSplitComparesPass( static RegisterStandardPasses RegisterSplitComparesTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterSplitComparesTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerSplitComparesPass); -#endif + #endif static RegisterPass X("splitcompares", "AFL++ split compares", true /* Only looks at CFG */, true /* Analysis Pass */); +#endif diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index 9f9e7eca..96e01a8b 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -27,14 +27,23 @@ #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + #include "llvm/Passes/PassPlugin.h" + #include "llvm/Passes/PassBuilder.h" + #include "llvm/IR/PassManager.h" +#else + #include "llvm/IR/LegacyPassManager.h" + #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#endif #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #include "llvm/IR/IRBuilder.h" #if LLVM_VERSION_MAJOR >= 4 || \ @@ -54,29 +63,42 @@ using namespace llvm; namespace { +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +class SplitSwitchesTransform : public PassInfoMixin { + + public: + SplitSwitchesTransform() { + +#else class SplitSwitchesTransform : public ModulePass { public: static char ID; SplitSwitchesTransform() : ModulePass(ID) { +#endif initInstrumentList(); } - bool runOnModule(Module &M) override; +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +#else + bool runOnModule(Module &M) override; -#if LLVM_VERSION_MAJOR >= 4 + #if LLVM_VERSION_MAJOR >= 4 StringRef getPassName() const override { -#else + #else const char *getPassName() const override { -#endif + #endif return "splits switch constructs"; } +#endif + struct CaseExpr { ConstantInt *Val; @@ -103,7 +125,54 @@ class SplitSwitchesTransform : public ModulePass { } // namespace +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "splitswitches", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + + #if 1 + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(SplitSwitchesTransform()); + + }); + + /* TODO LTO registration */ + #else + using PipelineElement = typename PassBuilder::PipelineElement; + PB.registerPipelineParsingCallback([](StringRef Name, + ModulePassManager &MPM, + ArrayRef) { + + if (Name == "splitswitches") { + + MPM.addPass(SplitSwitchesTransform()); + return true; + + } else { + + return false; + + } + + }); + + #endif + + }}; + +} + +#else char SplitSwitchesTransform::ID = 0; +#endif /* switchConvert - Transform simple list of Cases into list of CaseRange's */ BasicBlock *SplitSwitchesTransform::switchConvert( @@ -413,19 +482,42 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { } +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ +PreservedAnalyses SplitSwitchesTransform::run(Module & M, + ModuleAnalysisManager &MAM) { + +#else bool SplitSwitchesTransform::runOnModule(Module &M) { +#endif + if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) printf("Running split-switches-pass by laf.intel@gmail.com\n"); else be_quiet = 1; + +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + auto PA = PreservedAnalyses::all(); +#endif + splitSwitches(M); verifyModule(M); +#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ + /* if (modified) { + + PA.abandon(); + + }*/ + + return PA; +#else return true; +#endif } +#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */ static void registerSplitSwitchesTransPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -440,9 +532,10 @@ static RegisterStandardPasses RegisterSplitSwitchesTransPass( static RegisterStandardPasses RegisterSplitSwitchesTransPass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass); -#if LLVM_VERSION_MAJOR >= 11 + #if LLVM_VERSION_MAJOR >= 11 static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO( PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerSplitSwitchesTransPass); + #endif #endif diff --git a/src/afl-cc.c b/src/afl-cc.c index 051e4910..0d5951bb 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -434,21 +434,33 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode && have_instr_env) { +#if LLVM_MAJOR >= 11 /* use new pass manager */ + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = alloc_printf( + "-fpass-plugin=%s/afl-llvm-lto-instrumentlist.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/afl-llvm-lto-instrumentlist.so", obj_path); +#endif } if (getenv("AFL_LLVM_DICT2FILE")) { +#if LLVM_MAJOR >= 11 /* use new pass manager */ + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/afl-llvm-dict2file.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/afl-llvm-dict2file.so", obj_path); +#endif } @@ -473,7 +485,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = alloc_printf("%s/split-switches-pass.so", obj_path); #endif - + } } @@ -499,7 +511,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = alloc_printf("%s/compare-transform-pass.so", obj_path); #endif - + } } @@ -560,10 +572,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { } -//#if LLVM_MAJOR >= 13 -// // Use the old pass manager in LLVM 14 which the afl++ passes still use. -// cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; -//#endif + //#if LLVM_MAJOR >= 13 + // // Use the old pass manager in LLVM 14 which the afl++ passes still + // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; + //#endif if (lto_mode && !have_c) { @@ -654,10 +666,17 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { +#if LLVM_MAJOR >= 11 /* use new pass manager */ + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/afl-llvm-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/afl-llvm-pass.so", obj_path); +#endif } @@ -679,8 +698,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = alloc_printf( "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/cmplog-routines-pass.so", obj_path); + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path); #else cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; @@ -694,7 +713,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = alloc_printf("%s/cmplog-routines-pass.so", obj_path); #endif - + } } -- cgit 1.4.1 From 90fd61d14a3a154ed58461a9e3eaf2c91d094a86 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 17 Mar 2022 19:43:14 +0100 Subject: forgot one pass --- docs/Changelog.md | 2 + instrumentation/afl-llvm-lto-instrumentlist.so.cc | 49 +++++++++++++++++------ instrumentation/afl-llvm-pass.so.cc | 3 +- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 549d5e4a..18a4debf 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -23,6 +23,8 @@ sending a mail to . - add AFL_EARY_FORKSERVER to install the forkserver as earliest as possible in the target (for afl-gcc-fast/afl-clang-fast/ afl-clang-lto) + - afl-cc: + - converted all passed to use the new llvm pass manager for llvm 11+ - frida_mode: - update to new frida release, handles now c++ throw/catch diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index 2ddbc725..70c6b10d 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -45,8 +45,14 @@ #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +//#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/CFG.h" +#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ + #include "llvm/Passes/OptimizationLevel.h" +#endif #include "afl-llvm-common.h" @@ -54,11 +60,10 @@ using namespace llvm; namespace { -class AFLcheckIfInstrument : public ModulePass { +class AFLcheckIfInstrument : public PassInfoMixin { public: - static char ID; - AFLcheckIfInstrument() : ModulePass(ID) { + AFLcheckIfInstrument() { if (getenv("AFL_DEBUG")) debug = 1; @@ -66,12 +71,7 @@ class AFLcheckIfInstrument : public ModulePass { } - bool runOnModule(Module &M) override; - - // StringRef getPassName() const override { - - // return "American Fuzzy Lop Instrumentation"; - // } + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); protected: std::list myInstrumentList; @@ -80,9 +80,29 @@ class AFLcheckIfInstrument : public ModulePass { } // namespace -char AFLcheckIfInstrument::ID = 0; +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "AFLcheckIfInstrument", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + +#if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; +#endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(AFLcheckIfInstrument()); + + }); + + }}; -bool AFLcheckIfInstrument::runOnModule(Module &M) { +} + +PreservedAnalyses AFLcheckIfInstrument::run(Module & M, + ModuleAnalysisManager &MAM) { /* Show a banner */ @@ -131,10 +151,12 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) { } - return true; + auto PA = PreservedAnalyses::all(); + return PA; } +#if 0 static void registerAFLcheckIfInstrumentpass(const PassManagerBuilder &, legacy::PassManagerBase &PM) { @@ -149,4 +171,5 @@ static RegisterStandardPasses RegisterAFLcheckIfInstrumentpass( static RegisterStandardPasses RegisterAFLcheckIfInstrumentpass0( PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLcheckIfInstrumentpass); +#endif diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index be8099bb..fde785bd 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -44,7 +44,6 @@ typedef long double max_align_t; #endif -#include "llvm/IR/IRBuilder.h" #include "llvm/Pass.h" #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ #include "llvm/Passes/PassPlugin.h" @@ -71,6 +70,8 @@ typedef long double max_align_t; #include "llvm/Support/CFG.h" #endif +#include "llvm/IR/IRBuilder.h" + #include "afl-llvm-common.h" #include "llvm-alternative-coverage.h" -- cgit 1.4.1 From bdfac291ba653b34a1d304d6135111d68b8d8267 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 18 Mar 2022 08:47:45 +0100 Subject: fix split pass loading --- docs/Changelog.md | 2 ++ src/afl-cc.c | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 18a4debf..d672686d 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -24,6 +24,8 @@ sending a mail to . possible in the target (for afl-gcc-fast/afl-clang-fast/ afl-clang-lto) - afl-cc: + ! llvm15-dev with LTO and extra features (LAF/CMPLOG etc.) might have + issues at the moment - converted all passed to use the new llvm pass manager for llvm 11+ - frida_mode: - update to new frida release, handles now c++ throw/catch diff --git a/src/afl-cc.c b/src/afl-cc.c index 0d5951bb..487f394e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -526,11 +526,17 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { +#if LLVM_MAJOR >= 11 /* use new pass manager */ + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%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); +#endif } @@ -553,6 +559,16 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { + cc_params[cc_par_cnt++] = "-fno-inline"; + +#if LLVM_MAJOR >= 11 /* use new pass manager */ + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path); + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%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"; @@ -565,11 +581,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = alloc_printf("%s/split-switches-pass.so", obj_path); +#endif } - cc_params[cc_par_cnt++] = "-fno-inline"; - } //#if LLVM_MAJOR >= 13 -- cgit 1.4.1 From 69c9a176eb6ded2e7087ab437950a8ec324cdb1b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 18 Mar 2022 12:57:51 +0100 Subject: our own PCGUARD mode not for llvm 10.0.1 --- docs/Changelog.md | 1 + src/afl-cc.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index d672686d..f47a9b7c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -27,6 +27,7 @@ sending a mail to . ! llvm15-dev with LTO and extra features (LAF/CMPLOG etc.) might have issues at the moment - converted all passed to use the new llvm pass manager for llvm 11+ + - AFL++ PCGUARD mode is not available for 10.0.1 anymore (11+ only) - frida_mode: - update to new frida release, handles now c++ throw/catch diff --git a/src/afl-cc.c b/src/afl-cc.c index 487f394e..df2957b4 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -626,7 +626,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (instrument_mode == INSTRUMENT_PCGUARD) { -#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR >= 1) +#if LLVM_MAJOR >= 11 #if defined __ANDROID__ || ANDROID cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; instrument_mode = INSTRUMENT_LLVMNATIVE; -- cgit 1.4.1 From fa2b0404763f69c3bff0912a44a11e2e8c3734ab Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 18 Mar 2022 15:00:24 +0100 Subject: fix LTO with cmplog and laf --- GNUmakefile.llvm | 2 +- docs/Changelog.md | 2 - instrumentation/SanitizerCoverageLTO.so.cc | 163 ++++++++++----------------- src/afl-cc.c | 171 ++++++++++------------------- src/afl-fuzz-run.c | 3 +- 5 files changed, 121 insertions(+), 220 deletions(-) diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index a8f019c6..f91ff0d1 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -394,7 +394,7 @@ endif ./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps ifeq "$(LLVM_10_OK)" "1" - -$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-with-dtor -Wdeprecated instrumentation/afl-llvm-common.o + -$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-dtor -Wdeprecated instrumentation/afl-llvm-common.o endif ./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o diff --git a/docs/Changelog.md b/docs/Changelog.md index f47a9b7c..74631a88 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -24,8 +24,6 @@ sending a mail to . possible in the target (for afl-gcc-fast/afl-clang-fast/ afl-clang-lto) - afl-cc: - ! llvm15-dev with LTO and extra features (LAF/CMPLOG etc.) might have - issues at the moment - converted all passed to use the new llvm pass manager for llvm 11+ - AFL++ PCGUARD mode is not available for 10.0.1 anymore (11+ only) - frida_mode: diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 1bdc5376..9a48ae6d 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -34,7 +34,6 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Mangler.h" @@ -52,6 +51,9 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/ModuleUtils.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/IR/PassManager.h" #include "config.h" #include "debug.h" @@ -162,27 +164,21 @@ using DomTreeCallback = function_ref; using PostDomTreeCallback = function_ref; -class ModuleSanitizerCoverage { +class ModuleSanitizerCoverageLTO + : public PassInfoMixin { public: - ModuleSanitizerCoverage( + ModuleSanitizerCoverageLTO( const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) : Options(OverrideFromCL(Options)) { - /* , - const SpecialCaseList * Allowlist = nullptr, - const SpecialCaseList * Blocklist = nullptr) - , - Allowlist(Allowlist), - Blocklist(Blocklist) { - - */ - } bool instrumentModule(Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); + private: void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); @@ -280,18 +276,6 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()) : ModulePass(ID), Options(Options) { - /* , - const std::vector &AllowlistFiles = - std::vector(), - const std::vector &BlocklistFiles = - std::vector()) - if (AllowlistFiles.size() > 0) - Allowlist = SpecialCaseList::createOrDie(AllowlistFiles, - *vfs::getRealFileSystem()); - if (BlocklistFiles.size() > 0) - Blocklist = SpecialCaseList::createOrDie(BlocklistFiles, - *vfs::getRealFileSystem()); - */ initializeModuleSanitizerCoverageLegacyPassPass( *PassRegistry::getPassRegistry()); @@ -299,8 +283,7 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { bool runOnModule(Module &M) override { - ModuleSanitizerCoverage ModuleSancov(Options); - // , Allowlist.get(), Blocklist.get()); + ModuleSanitizerCoverageLTO ModuleSancov(Options); auto DTCallback = [this](Function &F) -> const DominatorTree * { return &this->getAnalysis(F).getDomTree(); @@ -321,18 +304,36 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { private: SanitizerCoverageOptions Options; - // std::unique_ptr Allowlist; - // std::unique_ptr Blocklist; - }; } // namespace -PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M, - ModuleAnalysisManager &MAM) { +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "SanitizerCoverageLTO", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { + +#if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; +#endif + // PB.registerFullLinkTimeOptimizationLastEPCallback( + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + + MPM.addPass(ModuleSanitizerCoverageLTO()); + + }); + + }}; + +} + +PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module & M, + ModuleAnalysisManager &MAM) { - ModuleSanitizerCoverage ModuleSancov(Options); - // Allowlist.get(), Blocklist.get()); + ModuleSanitizerCoverageLTO ModuleSancov(Options); auto &FAM = MAM.getResult(M).getManager(); auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { @@ -353,35 +354,7 @@ PreservedAnalyses ModuleSanitizerCoveragePass::run(Module & M, } -/* -std::pair ModuleSanitizerCoverage::CreateSecStartEnd( - Module &M, const char *Section, Type *Ty) { - - GlobalVariable *SecStart = - new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr, - getSectionStart(Section)); - SecStart->setVisibility(GlobalValue::HiddenVisibility); - GlobalVariable *SecEnd = - new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage, nullptr, - getSectionEnd(Section)); - SecEnd->setVisibility(GlobalValue::HiddenVisibility); - IRBuilder<> IRB(M.getContext()); - Value * SecEndPtr = IRB.CreatePointerCast(SecEnd, Ty); - if (!TargetTriple.isOSBinFormatCOFF()) - return std::make_pair(IRB.CreatePointerCast(SecStart, Ty), SecEndPtr); - - // Account for the fact that on windows-msvc __start_* symbols actually - // point to a uint64_t before the start of the array. - auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); - auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr, - ConstantInt::get(IntptrTy, sizeof(uint64_t))); - return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEndPtr); - -} - -*/ - -bool ModuleSanitizerCoverage::instrumentModule( +bool ModuleSanitizerCoverageLTO::instrumentModule( Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; @@ -1045,7 +1018,7 @@ bool ModuleSanitizerCoverage::instrumentModule( M, Int64Tyi, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr"); ConstantInt *MapAddr = ConstantInt::get(Int64Tyi, map_addr); StoreInst * StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreMapAddr); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(StoreMapAddr); } @@ -1060,7 +1033,7 @@ bool ModuleSanitizerCoverage::instrumentModule( "__afl_final_loc"); ConstantInt *const_loc = ConstantInt::get(Int32Tyi, write_loc); StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreFinalLoc); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(StoreFinalLoc); } @@ -1108,7 +1081,7 @@ bool ModuleSanitizerCoverage::instrumentModule( 0, "__afl_dictionary_len"); ConstantInt *const_len = ConstantInt::get(Int32Tyi, offset); StoreInst *StoreDictLen = IRB.CreateStore(const_len, AFLDictionaryLen); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDictLen); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(StoreDictLen); ArrayType *ArrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset); GlobalVariable *AFLInternalDictionary = new GlobalVariable( @@ -1128,7 +1101,7 @@ bool ModuleSanitizerCoverage::instrumentModule( Value *AFLDictPtr = IRB.CreatePointerCast(AFLDictOff, PointerType::get(Int8Tyi, 0)); StoreInst *StoreDict = IRB.CreateStore(AFLDictPtr, AFLDictionary); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDict); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(StoreDict); } @@ -1235,7 +1208,7 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, } -void ModuleSanitizerCoverage::instrumentFunction( +void ModuleSanitizerCoverageLTO::instrumentFunction( Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { if (F.empty()) return; @@ -1390,7 +1363,7 @@ void ModuleSanitizerCoverage::instrumentFunction( /* Load SHM pointer */ LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(MapPtr); while (1) { @@ -1420,7 +1393,7 @@ void ModuleSanitizerCoverage::instrumentFunction( } else { LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(Counter); /* Update bitmap */ @@ -1435,7 +1408,7 @@ void ModuleSanitizerCoverage::instrumentFunction( } auto nosan = IRB.CreateStore(Incr, MapPtrIdx); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(nosan); } @@ -1473,7 +1446,7 @@ void ModuleSanitizerCoverage::instrumentFunction( } -GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( +GlobalVariable *ModuleSanitizerCoverageLTO::CreateFunctionLocalArrayInSection( size_t NumElements, Function &F, Type *Ty, const char *Section) { ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); @@ -1503,7 +1476,7 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( } -GlobalVariable *ModuleSanitizerCoverage::CreatePCArray( +GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray( Function &F, ArrayRef AllBlocks) { size_t N = AllBlocks.size(); @@ -1539,7 +1512,7 @@ GlobalVariable *ModuleSanitizerCoverage::CreatePCArray( } -void ModuleSanitizerCoverage::CreateFunctionLocalArrays( +void ModuleSanitizerCoverageLTO::CreateFunctionLocalArrays( Function &F, ArrayRef AllBlocks) { if (Options.TracePCGuard) @@ -1555,9 +1528,8 @@ void ModuleSanitizerCoverage::CreateFunctionLocalArrays( } -bool ModuleSanitizerCoverage::InjectCoverage(Function & F, - ArrayRef AllBlocks, - bool IsLeafFunc) { +bool ModuleSanitizerCoverageLTO::InjectCoverage( + Function &F, ArrayRef AllBlocks, bool IsLeafFunc) { if (AllBlocks.empty()) return false; CreateFunctionLocalArrays(F, AllBlocks); @@ -1603,7 +1575,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, // The cache is used to speed up recording the caller-callee pairs. // The address of the caller is passed implicitly via caller PC. // CacheSize is encoded in the name of the run-time function. -void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls( +void ModuleSanitizerCoverageLTO::InjectCoverageForIndirectCalls( Function &F, ArrayRef IndirCalls) { if (IndirCalls.empty()) return; @@ -1621,9 +1593,10 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls( } -void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, - size_t Idx, - bool IsLeafFunc) { +void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function & F, + BasicBlock &BB, + size_t Idx, + bool IsLeafFunc) { BasicBlock::iterator IP = BB.getFirstInsertionPt(); bool IsEntryBB = &BB == &F.getEntryBlock(); @@ -1678,7 +1651,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } else { LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(MapPtr); MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc); } @@ -1695,7 +1668,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } else { LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(Counter); Value *Incr = IRB.CreateAdd(Counter, One); @@ -1708,7 +1681,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } auto nosan = IRB.CreateStore(Incr, MapPtrIdx); - ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(nosan); } @@ -1760,7 +1733,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } -std::string ModuleSanitizerCoverage::getSectionName( +std::string ModuleSanitizerCoverageLTO::getSectionName( const std::string &Section) const { if (TargetTriple.isOSBinFormatCOFF()) { @@ -1777,27 +1750,6 @@ std::string ModuleSanitizerCoverage::getSectionName( } -/* -std::string ModuleSanitizerCoverage::getSectionStart( - const std::string &Section) const { - - if (TargetTriple.isOSBinFormatMachO()) - return "\1section$start$__DATA$__" + Section; - return "__start___" + Section; - -} - -std::string ModuleSanitizerCoverage::getSectionEnd( - const std::string &Section) const { - - if (TargetTriple.isOSBinFormatMachO()) - return "\1section$end$__DATA$__" + Section; - return "__stop___" + Section; - -} - -*/ - char ModuleSanitizerCoverageLegacyPass::ID = 0; INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov", @@ -1815,7 +1767,6 @@ ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass( const std::vector &BlocklistFiles) { return new ModuleSanitizerCoverageLegacyPass(Options); - //, AllowlistFiles, BlocklistFiles); } diff --git a/src/afl-cc.c b/src/afl-cc.c index df2957b4..dfcb2a89 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -467,79 +467,52 @@ static void edit_params(u32 argc, char **argv, char **envp) { // laf if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { - if (lto_mode && !have_c) { - - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path); - - } else { - #if LLVM_MAJOR >= 11 /* use new pass manager */ - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%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); + 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); #endif - } - } if (getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { - if (lto_mode && !have_c) { - - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/compare-transform-pass.so", obj_path); - - } else { - #if LLVM_MAJOR >= 11 /* use new pass manager */ - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/compare-transform-pass.so", obj_path); + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%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); + 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); #endif - } - } if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) { - if (lto_mode && !have_c) { - - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/split-compares-pass.so", obj_path); - - } else { - #if LLVM_MAJOR >= 11 /* use new pass manager */ - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path); + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%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); + 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); #endif - } - } // /laf @@ -549,42 +522,30 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (cmplog_mode) { - if (lto_mode && !have_c) { - - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/cmplog-switches-pass.so", obj_path); - - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path); - - } else { - - cc_params[cc_par_cnt++] = "-fno-inline"; + cc_params[cc_par_cnt++] = "-fno-inline"; #if LLVM_MAJOR >= 11 /* use new pass manager */ - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path); - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path); + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%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/cmplog-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-switches-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); + // 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); #endif - } - } //#if LLVM_MAJOR >= 13 @@ -614,10 +575,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { #endif free(ld_path); - cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager"; #endif + + cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; cc_params[cc_par_cnt++] = alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); cc_params[cc_par_cnt++] = lto_flag; @@ -699,38 +661,27 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (cmplog_mode) { - if (lto_mode && !have_c) { - - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path); - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path); - - } else { - #if LLVM_MAJOR >= 11 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path); + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = alloc_printf( + "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); + cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; + cc_params[cc_par_cnt++] = + alloc_printf("-fpass-plugin=%s/cmplog-routines-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/cmplog-instructions-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++] = "-Xclang"; - 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); + 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-routines-pass.so", obj_path); #endif - } - } // cc_params[cc_par_cnt++] = "-Qunused-arguments"; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2a9d186b..ffba3475 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -232,7 +232,8 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, memcpy(afl->fsrv.shmem_fuzz, mem, skip_at); - memcpy(afl->fsrv.shmem_fuzz + skip_at, mem + skip_at + skip_len, tail_len); + memcpy(afl->fsrv.shmem_fuzz + skip_at, mem + skip_at + skip_len, + tail_len); } -- cgit 1.4.1 From a133aa91064df78298f762b5dc52e69ae7b0ae96 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 18 Mar 2022 15:47:20 +0000 Subject: docs: Document linker scripts change required in some projects AFL instrumentation modifies the binary to export extra symbols which must be visible if the main binary dlopen()s an instrumented DLL. This change was required by nbdkit since it uses a linker script to limit the symbols exported from the main binary: https://gitlab.com/nbdkit/nbdkit/-/commit/355cacb812126f5e37a2468f6939821b15017373 Signed-off-by: Richard W.M. Jones --- docs/fuzzing_in_depth.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index ac72c757..f7f5f2e8 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -333,6 +333,24 @@ is a non-standard way to set this, otherwise set up the build normally and edit the generated build environment afterwards manually to point it to the right compiler (and/or `RANLIB` and `AR`). +#### Linker scripts + +If the project uses linker scripts to hide the symbols exported by the +binary, then you may see errors such as: + +``` +undefined symbol: __afl_area_ptr +``` + +The solution is to modify the linker script to add: + +``` +{ + global: + __afl_*; +} +``` + ### f) Better instrumentation If you just fuzz a target program as-is, you are wasting a great opportunity for -- cgit 1.4.1 From c2ae24ab96f16242572b3618b36fa488d29dcc13 Mon Sep 17 00:00:00 2001 From: fuzzah Date: Mon, 21 Mar 2022 22:58:17 +0300 Subject: fix early return in AFL_TARGET_ENV --- src/afl-common.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/afl-common.c b/src/afl-common.c index 7c074acc..eca7d272 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -805,10 +805,7 @@ bool extract_and_set_env(u8 *env_str) { *rest = '\0'; // done with variable value rest += 1; - if (rest < end && *rest != ' ') { goto free_and_return; } - num_pairs++; - setenv(key, val, 1); } -- cgit 1.4.1 From bcf123e1eec4181ffe51e0c80e3b2732fbfd1839 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 23 Mar 2022 09:30:16 +0100 Subject: update qemu mode --- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/qemuafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 0c5c12d3..f39cb77e 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -ce65a7349e +a120c3feb5 diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index ce65a734..a120c3fe 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit ce65a7349e7156e052b37a660422cad8346764d0 +Subproject commit a120c3feb573d4cade292cdeb7c1f6b1ce109efe -- cgit 1.4.1 From d4734f6d9b2bcb3d66fe4cd602991009ea36a4ab Mon Sep 17 00:00:00 2001 From: clchrlls <102234184+clchrlls@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:57:24 +0100 Subject: fix installation packages for debian 10 --- docs/INSTALL.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index b0090e77..26b125b8 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -16,7 +16,21 @@ This image is automatically generated when a push to the stable repo happens. You will find your target source code in `/src` in the container. If you want to build AFL++ yourself, you have many options. The easiest choice -is to build and install everything: +is to build and install everything. + +First install the required packages: + +On Debian 10: +```shell +sudo apt-get update +sudo apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools +# try to install llvm 11 and install the distro default if that fails +sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang +sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev +sudo apt-get install -y ninja-build # for QEMU mode +``` + +On other distributions and versions of Debian: ```shell sudo apt-get update @@ -25,6 +39,10 @@ sudo apt-get install -y build-essential python3-dev automake cmake git flex biso sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev sudo apt-get install -y ninja-build # for QEMU mode +``` + +Then install AFLplusplus +```shell git clone https://github.com/AFLplusplus/AFLplusplus cd AFLplusplus make distrib -- cgit 1.4.1 From d012358748ec7a6100d24ae5f82822b88245e4c0 Mon Sep 17 00:00:00 2001 From: clchrlls <102234184+clchrlls@users.noreply.github.com> Date: Wed, 23 Mar 2022 15:02:47 +0100 Subject: missing column --- docs/INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 26b125b8..a3af2a87 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -41,7 +41,7 @@ sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*// sudo apt-get install -y ninja-build # for QEMU mode ``` -Then install AFLplusplus +Then install AFLplusplus: ```shell git clone https://github.com/AFLplusplus/AFLplusplus cd AFLplusplus -- cgit 1.4.1 From ce0db35f186f442da8c9e2947093e570d35ce251 Mon Sep 17 00:00:00 2001 From: clchrlls <102234184+clchrlls@users.noreply.github.com> Date: Wed, 23 Mar 2022 15:03:56 +0100 Subject: Not sure the fix is needed only for debian 10 --- docs/INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index a3af2a87..381c34fd 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -30,7 +30,7 @@ sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* // sudo apt-get install -y ninja-build # for QEMU mode ``` -On other distributions and versions of Debian: +On other systems: ```shell sudo apt-get update -- cgit 1.4.1 From a601b56627d74b0146e3efab1743f8a63c1a5605 Mon Sep 17 00:00:00 2001 From: clchrlls <102234184+clchrlls@users.noreply.github.com> Date: Wed, 23 Mar 2022 17:09:31 +0100 Subject: reverted to simply changing gcc version retrieval --- docs/INSTALL.md | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 381c34fd..e003e124 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -1,4 +1,4 @@ -# Building and installing AFL++ + ## Linux on x86 @@ -16,11 +16,8 @@ This image is automatically generated when a push to the stable repo happens. You will find your target source code in `/src` in the container. If you want to build AFL++ yourself, you have many options. The easiest choice -is to build and install everything. - -First install the required packages: +is to build and install everything: -On Debian 10: ```shell sudo apt-get update sudo apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools @@ -28,21 +25,6 @@ sudo apt-get install -y build-essential python3-dev automake cmake git flex biso sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev sudo apt-get install -y ninja-build # for QEMU mode -``` - -On other systems: - -```shell -sudo apt-get update -sudo apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools -# try to install llvm 11 and install the distro default if that fails -sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang -sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev -sudo apt-get install -y ninja-build # for QEMU mode -``` - -Then install AFLplusplus: -```shell git clone https://github.com/AFLplusplus/AFLplusplus cd AFLplusplus make distrib @@ -196,4 +178,4 @@ sysctl kern.sysv.shmall=98304 See [http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html) -for documentation for these settings and how to make them permanent. +for documentation for these settings and how to make them permanent. \ No newline at end of file -- cgit 1.4.1 From 0dca6ee038898836a7ac043bb2fc20a0e48815cc Mon Sep 17 00:00:00 2001 From: clchrlls <102234184+clchrlls@users.noreply.github.com> Date: Wed, 23 Mar 2022 17:11:22 +0100 Subject: put back the title of the page deleted by mistake --- docs/INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index e003e124..3fa7fd13 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -1,4 +1,4 @@ - +# Building and installing AFL++ ## Linux on x86 -- cgit 1.4.1 From 3f0d642f9b31ea6afeb4e27aa24eddc27ad36fa1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 26 Mar 2022 19:13:49 +0000 Subject: fix unicornafl test --- test/test-unicorn-mode.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-unicorn-mode.sh b/test/test-unicorn-mode.sh index 182958d6..f8ff4190 100755 --- a/test/test-unicorn-mode.sh +++ b/test/test-unicorn-mode.sh @@ -3,7 +3,7 @@ . ./test-pre.sh $ECHO "$BLUE[*] Testing: unicorn_mode" -test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shellcode && { +test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/Makefile && { test -e ../unicorn_mode/samples/python_simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && { { # We want to see python errors etc. in logs, in case something doesn't work -- cgit 1.4.1 From d2ea1141ebef090b9763b73ef935d6fc45f4a2d7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 23 Mar 2022 11:19:18 +0100 Subject: cleanup --- TODO.md | 2 +- TODO_LLVM | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 TODO_LLVM diff --git a/TODO.md b/TODO.md index e6b095fc..f3192e10 100644 --- a/TODO.md +++ b/TODO.md @@ -29,4 +29,4 @@ QEMU mode/FRIDA mode: using cmplog or __sanitizer_cov_trace_cmp*. maybe we can deduct by follow up edge numbers that both following cmp paths have been found and then disable working on this edge id -> cmplog_intelligence branch - - use cmplog colorization taint result for havoc locations? \ No newline at end of file + - use cmplog colorization taint result for havoc locations? diff --git a/TODO_LLVM b/TODO_LLVM deleted file mode 100644 index 3dea8cca..00000000 --- a/TODO_LLVM +++ /dev/null @@ -1,10 +0,0 @@ -with LLVM 14: only new pass manager -up to LLVM 13: only old pass manager - -These do not work yet with the new pass manager: -cmplog-instructions-pass.so -compare-transform-pass.so -afl-llvm-dict2file.so -afl-llvm-lto-instrumentlist.so -SanitizerCoverageLTO.so -SanitizerCoveragePCGUARD.so -- cgit 1.4.1 From b34751efbf9304128d8e52dfeeb3abe0d4f5ba3b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 29 Mar 2022 10:34:08 +0200 Subject: fix qemu sigunaction tests --- qemu_mode/unsigaction/Makefile | 14 +++++++------- test/test-qemu-mode.sh | 14 ++++---------- unicorn_mode/build_unicorn_support.sh | 4 +++- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/qemu_mode/unsigaction/Makefile b/qemu_mode/unsigaction/Makefile index eabe6c77..f026a2b7 100644 --- a/qemu_mode/unsigaction/Makefile +++ b/qemu_mode/unsigaction/Makefile @@ -12,19 +12,19 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -.POSIX: -_UNIQ=_QINU_ - -TARGETCANDIDATES=unsigaction.so -_TARGETS=$(_UNIQ)$(AFL_NO_X86)$(_UNIQ) -__TARGETS=$(_TARGETS:$(_UNIQ)1$(_UNIQ)=) -TARGETS=$(__TARGETS:$(_UNIQ)$(_UNIQ)=$(TARGETCANDIDATES)) +TARGETS=unsigaction.so unsigaction32.so unsigaction64.so all: $(TARGETS) unsigaction.so: unsigaction.c @if $(CC) -fPIC -shared unsigaction.c -o unsigaction.so 2>/dev/null ; then echo "unsigaction build success"; else echo "unsigaction build failure (that's fine)"; fi +unsigaction32.so: unsigaction.c + @if $(CC) -fPIC -m32 -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi + +unsigaction64.so: unsigaction.c + @if $(CC) -fPIC -m64 -shared unsigaction.c -o unsigaction64.so 2>/dev/null ; then echo "unsigaction64 build success"; else echo "unsigaction64 build failure (that's fine)"; fi + clean: rm -f unsigaction.so diff --git a/test/test-qemu-mode.sh b/test/test-qemu-mode.sh index 85578d55..46b138ff 100755 --- a/test/test-qemu-mode.sh +++ b/test/test-qemu-mode.sh @@ -165,11 +165,8 @@ test -e ../afl-qemu-trace && { CODE=1 } } || { - echo CUT------------------------------------------------------------------CUT - cat errors - echo CUT------------------------------------------------------------------CUT - $ECHO "$RED[!] cannot compile test program (32 bit) for unsigaction library" - CODE=1 + $ECHO "$YELLOW[-] cannot compile test program (32 bit) for unsigaction library" + INCOMPLETE=1 } } || { $ECHO "$YELLOW[-] we cannot test qemu_mode unsigaction library (32 bit) because it is not present" @@ -194,11 +191,8 @@ test -e ../afl-qemu-trace && { } unset LD_PRELOAD } || { - echo CUT------------------------------------------------------------------CUT - cat errors - echo CUT------------------------------------------------------------------CUT - $ECHO "$RED[!] cannot compile test program (64 bit) for unsigaction library" - CODE=1 + $ECHO "$YELLOW[-] cannot compile test program (64 bit) for unsigaction library" + INCOMPLETE=1 } } || { $ECHO "$YELLOW[-] we cannot test qemu_mode unsigaction library (64 bit) because it is not present" diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index a846fd1c..0f8c5e8c 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -217,7 +217,9 @@ cd ../samples/python_simple || echo "Cannot cd" # Run afl-showmap on the sample application. If anything comes out then it must have worked! unset AFL_INST_RATIO -echo 0 | ../../../afl-showmap -U -m none -t 2000 -q -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin || echo "Showmap" +pwd +echo "echo 0 | ../../../afl-showmap -U -m none -t 2000 -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin" +echo 0 | ../../../afl-showmap -U -m none -t 2000 -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin || echo "Showmap" if [ -s ./.test-instr0 ] then -- cgit 1.4.1 From a436ef47e5cf0cb16b4afddccc6530285a6bb6fa Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 30 Mar 2022 09:16:47 +0200 Subject: fix instrumentlist for LTO with clang < 13 --- src/afl-cc.c | 2 ++ test/test-llvm-lto.sh | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/afl-cc.c b/src/afl-cc.c index dfcb2a89..4cec7740 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -577,6 +577,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager"; +#else + cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; #endif cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; diff --git a/test/test-llvm-lto.sh b/test/test-llvm-lto.sh index 9ff2ec10..bb4a9f7c 100755 --- a/test/test-llvm-lto.sh +++ b/test/test-llvm-lto.sh @@ -49,6 +49,9 @@ test -e ../afl-clang-lto -a -e ../SanitizerCoverageLTO.so && { grep -q "No instrumentation targets found" test.out && { $ECHO "$GREEN[+] llvm_mode LTO instrumentlist feature works correctly" } || { + echo CUT------------------------------------------------------------------CUT + cat test.out + echo CUT------------------------------------------------------------------CUT $ECHO "$RED[!] llvm_mode LTO instrumentlist feature failed" CODE=1 } -- cgit 1.4.1 From 77a3abfa5e75228163bb4cf6008f90e436424e64 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 30 Mar 2022 17:09:00 +0200 Subject: remove debug --- unicorn_mode/build_unicorn_support.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index 0f8c5e8c..f24c8ce3 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -217,9 +217,8 @@ cd ../samples/python_simple || echo "Cannot cd" # Run afl-showmap on the sample application. If anything comes out then it must have worked! unset AFL_INST_RATIO -pwd -echo "echo 0 | ../../../afl-showmap -U -m none -t 2000 -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin" -echo 0 | ../../../afl-showmap -U -m none -t 2000 -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin || echo "Showmap" +# pwd; echo "echo 0 | ../../../afl-showmap -U -m none -t 2000 -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin" +echo 0 | ../../../afl-showmap -U -m none -t 2000 -o ./.test-instr0 -- $PYTHONBIN ./simple_test_harness.py ./sample_inputs/sample1.bin >/dev/null 2>&1 || echo "Showmap" if [ -s ./.test-instr0 ] then -- cgit 1.4.1 From 772e33d5500d80f913f7183c616b2eb222b15fc9 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Wed, 30 Mar 2022 20:32:51 +0200 Subject: avoid compiler warning (format-truncation), needed for make DEBUG=1 all --- src/afl-fuzz-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 971ac494..99f37cbf 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -776,7 +776,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { u8 fn_log[PATH_MAX]; - snprintf(fn_log, PATH_MAX, "%s.log", fn); + (void)(snprintf(fn_log, PATH_MAX, "%s.log", fn) + 1); fd = open(fn_log, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); } -- cgit 1.4.1 From 51dbd0e9571db5404b7c74169965367800b093db Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Wed, 30 Mar 2022 20:46:57 +0200 Subject: ignore unused variable to let make DEBUG=1 distrib succeed --- frida_mode/src/instrument/instrument_x64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index 0bff3e02..d54c8353 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -336,7 +336,7 @@ void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output) { GumX86Writer *cw = output->writer.x86; - guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); + /* guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); */ if (instrument_previous_pc_addr == NULL) { GumAddressSpec spec = {.near_address = cw->code, -- cgit 1.4.1 From 285a5cb38b994b514744c49bad409a49210765d4 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 31 Mar 2022 15:35:38 +0000 Subject: Some scan-build fixes --- instrumentation/SanitizerCoveragePCGUARD.so.cc | 27 ++++++++++++++++++++++++++ instrumentation/afl-llvm-dict2file.so.cc | 8 +++++--- instrumentation/cmplog-instructions-pass.cc | 17 ++++++++-------- src/afl-cc.c | 14 ++++++++++++- src/afl-fuzz-cmplog.c | 10 +--------- src/afl-fuzz-redqueen.c | 2 +- 6 files changed, 56 insertions(+), 22 deletions(-) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index e234cf57..f80b1a1e 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -932,6 +932,15 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( IRBuilder<> IRB(callInst); + if (!FunctionGuardArray) { + + fprintf(stderr, + "SANCOV: FunctionGuardArray is NULL, failed to emit " + "instrumentation."); + continue; + + } + Value *GuardPtr = IRB.CreateIntToPtr( IRB.CreateAdd( IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), @@ -957,6 +966,15 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( if (t->getTypeID() == llvm::Type::IntegerTyID) { + if (!FunctionGuardArray) { + + fprintf(stderr, + "SANCOV: FunctionGuardArray is NULL, failed to emit " + "instrumentation."); + continue; + + } + auto GuardPtr1 = IRB.CreateIntToPtr( IRB.CreateAdd( IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), @@ -993,6 +1011,15 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( FixedVectorType::get(Int32PtrTy, elements); Value *x, *y; + if (!FunctionGuardArray) { + + fprintf(stderr, + "SANCOV: FunctionGuardArray is NULL, failed to emit " + "instrumentation."); + continue; + + } + Value *val1 = IRB.CreateIntToPtr( IRB.CreateAdd( IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 79cdf491..31aaab07 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -536,15 +536,17 @@ bool AFLdict2filePass::runOnModule(Module &M) { } - if (optLength > Str2.length()) { optLength = Str2.length(); } - } valueMap[Str1P] = new std::string(Str2); - if (debug) + if (debug) { + fprintf(stderr, "Saved: %s for %p\n", Str2.c_str(), (void *)Str1P); + + } + continue; } diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 7c95d9bb..fd7930a1 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -515,7 +515,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { while (1) { std::vector args; - uint32_t skip = 0; + bool skip = true; if (vector_cnt) { @@ -537,16 +537,18 @@ bool CmpLogInstructions::hookInstrs(Module &M) { if (i0) { cur_val = (uint64_t)i0->getValue().convertToDouble(); - if (last_val0 && last_val0 == cur_val) { skip = 1; } - last_val0 = cur_val; + if (last_val0 && last_val0 == cur_val) { skip = true; + + } last_val0 = cur_val; } if (i1) { cur_val = (uint64_t)i1->getValue().convertToDouble(); - if (last_val1 && last_val1 == cur_val) { skip = 1; } - last_val1 = cur_val; + if (last_val1 && last_val1 == cur_val) { skip = true; + + } last_val1 = cur_val; } @@ -559,7 +561,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { if (i0 && i0->uge(0xffffffffffffffff) == false) { cur_val = i0->getZExtValue(); - if (last_val0 && last_val0 == cur_val) { skip = 1; } + if (last_val0 && last_val0 == cur_val) { skip = true; } last_val0 = cur_val; } @@ -567,7 +569,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { if (i1 && i1->uge(0xffffffffffffffff) == false) { cur_val = i1->getZExtValue(); - if (last_val1 && last_val1 == cur_val) { skip = 1; } + if (last_val1 && last_val1 == cur_val) { skip = true; } last_val1 = cur_val; } @@ -649,7 +651,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) { ++cur; if (cur >= vector_cnt) { break; } - skip = 0; } diff --git a/src/afl-cc.c b/src/afl-cc.c index 4cec7740..ffdda386 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -566,7 +566,19 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (!ld_path || !*ld_path) { ld_path = strdup("ld.lld"); } + if (!ld_path || !*ld_path) { + + if (ld_path) { + + // Freeing empty string + free(ld_path); + + } + + ld_path = strdup("ld.lld"); + + } + if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path); diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 1a8052a0..7d94085d 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -49,7 +49,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u8 fault; - len = write_to_testcase(afl, out_buf, len, 0); + write_to_testcase(afl, out_buf, len, 0); fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); @@ -81,14 +81,6 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { } - /* This handles FAULT_ERROR for us: */ - - /* afl->queued_discovered += save_if_interesting(afl, argv, out_buf, len, - fault); - - if (!(afl->stage_cur % afl->stats_update_freq) || afl->stage_cur + 1 == - afl->stage_max) show_stats(afl); */ - return 0; } diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 2f32ef1e..2dbad5cf 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -1969,7 +1969,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 || ol0 > 31 || ol1 > 31) { - l0 = l1 = ol0 = ol1 = hshape; + l0 = ol0 = hshape; } -- cgit 1.4.1 From 2d7ac5f69c6016af3f9c4c2bbd45816d6db2fc70 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Thu, 31 Mar 2022 18:11:24 +0100 Subject: frida mode fix arm64 build --- frida_mode/src/instrument/instrument_arm64.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index eb736386..e6251cb4 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -18,6 +18,8 @@ #if defined(__aarch64__) +gboolean instrument_cache_enabled = FALSE; +gsize instrument_cache_size = 0; static GHashTable *coverage_blocks = NULL; __attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE]; -- cgit 1.4.1 From 7f56a93f5d67878a9cfe3fa424eb4d17b12a1305 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 31 Mar 2022 18:18:16 +0100 Subject: GNUmakefile.llvm: Avoid creating circular links Building into a DESTDIR gives circular links such as: lrwxrwxrwx. 1 rjones rjones 17 Mar 31 18:09 /home/rjones/rpmbuild/BUILDROOT/american-fuzzy-lop-4.00c-3.git285a5cb3.fc37.x86_64/usr/lib64/afl/afl-compiler-rt.o -> afl-compiler-rt.o I have to admit I've no idea what the original link command is trying to achieve, but it's clearly wrong and deleting it fixes the problem. Signed-off-by: Richard W.M. Jones --- GNUmakefile.llvm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index f91ff0d1..685964b7 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -474,11 +474,11 @@ install: all @install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) @if [ -f ./afl-cc ]; then set -e; install -m 755 ./afl-cc $${DESTDIR}$(BIN_PATH); ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-c++; fi @rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt*.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt*.o - @if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-compiler-rt.o ;fi + @if [ -f ./afl-compiler-rt.o ]; then set -e; install -m 755 ./afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH); fi @if [ -f ./afl-lto ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-lto++; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ./afl-llvm-rt-lto*.o ./afl-llvm-lto-instrumentlist.so $${DESTDIR}$(HELPER_PATH); fi @if [ -f ./afl-ld-lto ]; then set -e; install -m 755 ./afl-ld-lto $${DESTDIR}$(BIN_PATH); fi - @if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-compiler-rt-32.o ;fi - @if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); ln -sf afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-compiler-rt-64.o ; fi + @if [ -f ./afl-compiler-rt-32.o ]; then set -e; install -m 755 ./afl-compiler-rt-32.o $${DESTDIR}$(HELPER_PATH); fi + @if [ -f ./afl-compiler-rt-64.o ]; then set -e; install -m 755 ./afl-compiler-rt-64.o $${DESTDIR}$(HELPER_PATH); fi @if [ -f ./compare-transform-pass.so ]; then set -e; install -m 755 ./*.so $${DESTDIR}$(HELPER_PATH); fi @if [ -f ./compare-transform-pass.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-fast ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-fast++ ; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang++ ; fi @if [ -f ./SanitizerCoverageLTO.so ]; then set -e; ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-clang-lto ; ln -sf ./afl-c++ $${DESTDIR}$(BIN_PATH)/afl-clang-lto++ ; fi -- cgit 1.4.1