Created
July 3, 2017 08:28
-
-
Save NeatMonster/b5ab334047567bf1cc9b2f721003dcdc to your computer and use it in GitHub Desktop.
This small patch adds support for value profiling into AFL 2.44b.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -Naur a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c | |
--- a/llvm_mode/afl-llvm-rt.o.c 2017-02-01 02:59:41.000000000 +0100 | |
+++ b/llvm_mode/afl-llvm-rt.o.c 2017-06-29 15:55:53.052681442 +0200 | |
@@ -304,3 +304,205 @@ | |
} | |
} | |
+ | |
+/* This function is called on every indirect call, but only if the binary has | |
+ been compiled with -fsanitize-coverage=trace-pc,indirect-calls. */ | |
+ | |
+void __sanitizer_cov_trace_pc_indir(uptr callee) { | |
+ | |
+ uptr caller = (uptr)__builtin_return_address(0); | |
+ | |
+ const uptr bits = MAP_SIZE_POW2 / 2; | |
+ const uptr mask = (1 << bits) - 1; | |
+ | |
+ /* For now we use the less significant bits of the caller and the callee | |
+ addresses to add an hit to the output map. */ | |
+ | |
+ uptr index = (caller & mask) | ((callee & mask) << bits); | |
+ __afl_area_ptr[index]++; | |
+} | |
+ | |
+/* This function is called by all functions operating on integers. It computes | |
+ an index using the program counter and the two values being compared. */ | |
+ | |
+void __afl_handle_cmp(uptr pc, u64 arg1, u64 arg2, u8 size) { | |
+ | |
+ u64 dist = 0; | |
+ u64 xor = arg1 ^ arg2; | |
+ if (xor & 0x00000000000000ff) dist++; | |
+ if (xor & 0x000000000000ff00) dist++; | |
+ if (xor & 0x0000000000ff0000) dist++; | |
+ if (xor & 0x00000000ff000000) dist++; | |
+ if (xor & 0x000000ff00000000) dist++; | |
+ if (xor & 0x0000ff0000000000) dist++; | |
+ if (xor & 0x00ff000000000000) dist++; | |
+ if (xor & 0xff00000000000000) dist++; | |
+ | |
+ /* If the two values have nothing in common, do not reward. */ | |
+ | |
+ if (dist >= size) return; | |
+ | |
+ const u64 bits = MAP_SIZE_POW2 - 3; | |
+ const u64 mask = (1 << bits) - 1; | |
+ | |
+ /* For now we use the less significant bits of the program counter, and the | |
+ number of bytes in common between the two values. */ | |
+ | |
+ uptr index = (pc & mask) | (dist << bits); | |
+ __afl_area_ptr[index]++; | |
+} | |
+ | |
+/* The functions below are called on every integer comparison, but only if the | |
+ binary has been compiled with -fsanitize-coverage=trace-cmp. */ | |
+ | |
+//void __sanitizer_cov_trace_cmp1(u8 arg1, u8 arg2) { | |
+// | |
+// uptr pc = (uptr)__builtin_return_address(0); | |
+// | |
+// __afl_handle_cmp(pc, arg1, arg2, 1); | |
+//} | |
+ | |
+void __sanitizer_cov_trace_cmp2(u16 arg1, u16 arg2) { | |
+ | |
+ uptr pc = (uptr)__builtin_return_address(0); | |
+ | |
+ __afl_handle_cmp(pc, arg1, arg2, 2); | |
+} | |
+ | |
+void __sanitizer_cov_trace_cmp4(u32 arg1, u32 arg2) { | |
+ | |
+ uptr pc = (uptr)__builtin_return_address(0); | |
+ | |
+ __afl_handle_cmp(pc, arg1, arg2, 4); | |
+} | |
+ | |
+void __sanitizer_cov_trace_cmp8(u64 arg1, u64 arg2) { | |
+ | |
+ uptr pc = (uptr)__builtin_return_address(0); | |
+ | |
+ __afl_handle_cmp(pc, arg1, arg2, 8); | |
+} | |
+ | |
+/* This function are called on every switch being executed, but only if the | |
+ binary has been compiled with -fsanitize-coverage=trace-cmp. */ | |
+ | |
+void __sanitizer_cov_trace_switch(u64 val, u64 *cases) { | |
+ | |
+ u64 len = cases[0]; | |
+ u64 size = cases[2]; | |
+ u64 *vals = cases + 2; | |
+ | |
+ if (size < 16) return; /* Ignore integers smaller than 16 bits. */ | |
+ | |
+ uptr pc = (uptr)__builtin_return_address(0); | |
+ | |
+ u64 i = 0, token = 0; | |
+ for (i = 0; i < len; ++i) { | |
+ token = val ^ vals[i]; | |
+ if (val < vals[i]) break; | |
+ } | |
+ | |
+ __afl_handle_cmp(pc + i, token, 0, MAX(1, size / 8)); | |
+} | |
+ | |
+/* The functions below are called on every division, but only if the binary has | |
+ been compiled with -fsanitize-coverage=trace-div. */ | |
+ | |
+void __sanitizer_cov_trace_div4(u32 val) { | |
+ | |
+ uptr pc = (uptr)__builtin_return_address(0); | |
+ | |
+ __afl_handle_cmp(pc, val, 0, 4); | |
+} | |
+ | |
+void __sanitizer_cov_trace_div8(u64 val) { | |
+ | |
+ uptr pc = (uptr)__builtin_return_address(0); | |
+ | |
+ __afl_handle_cmp(pc, val, 0, 8); | |
+} | |
+ | |
+/* This function are called on every array indexing, but only if the binary has | |
+ been compiled with -fsanitize-coverage=trace-gep. */ | |
+ | |
+void __sanitizer_cov_trace_gep(uptr idx) { | |
+ | |
+ uptr pc = (uptr)__builtin_return_address(0); | |
+ | |
+ __afl_handle_cmp(pc, idx, 0, sizeof(size_t)); | |
+} | |
+ | |
+#ifdef USE_WEAK_HOOKS | |
+ | |
+/* This function is called when doing memory comparisons. It computes an index | |
+ using the program counter and the two strings being compared. */ | |
+ | |
+void __afl_handle_memcmp(void *caller_pc, const void *s1, const void *s2, | |
+ size_t n, int is_str) { | |
+ | |
+ const u8 *b1 = (const u8 *)s1; | |
+ const u8 *b2 = (const u8 *)s2; | |
+ | |
+ /* Count how many starting bytes the two strings have in common. */ | |
+ | |
+ size_t i, len = MIN(n, 32); | |
+ for (i = 0; i < len; ++i) | |
+ if (b1[i] != b2[i] || (is_str && (b1[i] == 0 || b2[i] == 0))) break; | |
+ | |
+ const u64 bits = MAP_SIZE_POW2 - 5; | |
+ const u64 mask = (1 << bits) - 1; | |
+ | |
+ /* For now we use the less significant bits of the program counter, and the | |
+ number of starting bytes in common between the two strings. */ | |
+ | |
+ size_t pc = (size_t)caller_pc; | |
+ size_t index = (pc & mask) | (i << bits); | |
+ __afl_area_ptr[index]++; | |
+} | |
+ | |
+/* The functions below are called on every call to their eponymous function, but | |
+ only if the binary has been compiled with at least a sanitizer enabled. */ | |
+ | |
+void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, | |
+ const void *s2, size_t n, int result) { | |
+ | |
+ if (!result || n <= 1) return; | |
+ | |
+ __afl_handle_memcmp(caller_pc, s1, s2, n, 0); | |
+} | |
+ | |
+void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1, | |
+ const char *s2, int result) { | |
+ | |
+ if (!result) return; | |
+ | |
+ /* We need to calculate the length ourselves . */ | |
+ | |
+ size_t n = 0; | |
+ while (s1[n] && s2[n]) ++n; | |
+ if (n <= 1) return; | |
+ | |
+ __afl_handle_memcmp(caller_pc, s1, s2, n, 1); | |
+} | |
+ | |
+void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, | |
+ const char *s2, size_t n, int result) { | |
+ | |
+ if (!result || n <= 1) return; | |
+ | |
+ __afl_handle_memcmp(caller_pc, s1, s2, n, 1); | |
+} | |
+ | |
+void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, | |
+ const char *s2, int result) { | |
+ | |
+ return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); | |
+} | |
+ | |
+void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, | |
+ const char *s2, size_t n, int result) { | |
+ | |
+ return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); | |
+} | |
+ | |
+#endif /* USE_WEAK_HOOKS */ | |
diff -Naur a/llvm_mode/Makefile b/llvm_mode/Makefile | |
--- a/llvm_mode/Makefile 2016-06-24 04:38:49.000000000 +0200 | |
+++ b/llvm_mode/Makefile 2017-06-29 13:12:50.003040093 +0200 | |
@@ -30,6 +30,9 @@ | |
-DVERSION=\"$(VERSION)\" | |
ifdef AFL_TRACE_PC | |
CFLAGS += -DUSE_TRACE_PC=1 | |
+ ifdef AFL_WEAK_HOOKS | |
+ CFLAGS += -DUSE_WEAK_HOOKS=1 | |
+ endif | |
endif | |
CXXFLAGS ?= -O3 -funroll-loops | |
diff -Naur a/types.h b/types.h | |
--- a/types.h 2017-06-02 08:34:36.000000000 +0200 | |
+++ b/types.h 2017-06-29 10:15:00.309117731 +0200 | |
@@ -45,6 +45,7 @@ | |
#else | |
typedef uint64_t u64; | |
#endif /* ^__x86_64__ */ | |
+typedef uintptr_t uptr; | |
typedef int8_t s8; | |
typedef int16_t s16; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment