├── HOWTO ├── INSTALL ├── LICENSE-LLVM.TXT ├── Makefile ├── README ├── alloc-inl.h ├── config.h ├── debug.h ├── example.cpp ├── llcov-clang.c ├── llcov-llvm-pass.so.cc ├── llcov-llvm-rt.o.cc ├── llcov_assert.cc ├── llcov_network.cc └── types.h /HOWTO: -------------------------------------------------------------------------------- 1 | == Quick Usage Guide == 2 | 3 | After following the steps in INSTALL, you will find a wrapper 4 | binary in this directory called llcov-clang. 5 | 6 | Using this wrapper instead of the regular CC and CXX, you can 7 | build your programs easily with LLCov support. 8 | 9 | The code in llcov-llvm-rt.o.cc is automatically linked to your 10 | executable program and the default implementation supports: 11 | 12 | * Printing to stderr (run program with LLCOV_STDERR=1) 13 | * Printing to a file (run program with LLCOV_FILE=yourfile) 14 | * Aborting (run program with LLCOV_ABORT=1) 15 | 16 | === Example === 17 | 18 | To demonstrate how LLCov works, we'll use the example.cpp 19 | provided in this project. If you have a look at that file, 20 | you'll see that it's a simple C++ program that outputs several 21 | messages based on the argument count (argc). It also sets the 22 | exit code according to that variable. 23 | 24 | We'll first compile the program with LLCov: 25 | 26 | $ ./llcov-clang++ -o example example.cpp 27 | 28 | If your clang and clang++ binaries are not on PATH, you need to specify them: 29 | 30 | $ CC=/usr/bin/clang-3.7 CXX=/usr/bin/clang++-3.7 ./llcov-clang++ -o example example.cpp 31 | 32 | Now we run the file with a different number of arguments 33 | (note that the filename itself is an argument as well): 34 | 35 | $ ./example 36 | Block executed in file example.cpp, line 3 37 | One argument 38 | Block executed in file example.cpp, line 6 39 | Block executed in file example.cpp, line 16 40 | Block executed in file example.cpp, line 19 41 | Block executed in file example.cpp, line 20 42 | 43 | $ ./example 1 44 | Block executed in file example.cpp, line 3 45 | Two or three arguments 46 | Block executed in file example.cpp, line 10 47 | Block executed in file example.cpp, line 16 48 | Block executed in file example.cpp, line 19 49 | Block executed in file example.cpp, line 20 50 | 51 | $ ./example 1 2 52 | Block executed in file example.cpp, line 3 53 | Two or three arguments 54 | Block executed in file example.cpp, line 10 55 | Block executed in file example.cpp, line 16 56 | Block executed in file example.cpp, line 17 57 | Block executed in file example.cpp, line 20 58 | 59 | $ ./example 1 2 3 60 | Block executed in file example.cpp, line 3 61 | More than three arguments 62 | Block executed in file example.cpp, line 13 63 | Block executed in file example.cpp, line 16 64 | Block executed in file example.cpp, line 17 65 | Block executed in file example.cpp, line 20 66 | 67 | 68 | As you can see from the output, some blocks are always executed, 69 | (e.g. the block at the beginning of the main function (line 3+), the 70 | basic block containing the if statement (line 16) and a final block 71 | (line 20)). The other blocks are only executed conditionally as 72 | indicated by the output. 73 | 74 | === Using black- and whitelists === 75 | 76 | Black- and whitelists allow you to have a fine-grained control over 77 | what is instrumented and what not. Each list is a file containing 78 | one entry per line. The files are supplied using the enviroment variables 79 | LLCOV_BLACKLIST and LLCOV_WHITELIST. Here is an example of list file: 80 | 81 | file:example.cpp line:16 82 | file:example.cpp func:bar 83 | file:someotherfile.cpp 84 | func:baz 85 | 86 | As a whitelist, this file would mean to instrument line 16 in example.cpp, 87 | the function bar in example.cpp, everything in someotherfile.cpp and every 88 | function called "baz". Used as a blacklist file, these would NOT be 89 | instrumented. You can also combine the "file", "func" and "line" options 90 | in a single entry, although that is probably not too helpful. These three 91 | options are the only ones available right now. When specifying only a "func" 92 | but no "file", specifying a "line" is not allowed as it would be meaningless. 93 | 94 | When no whitelist file is in use, the implementation will instrument 95 | everything that is NOT on the blacklist. When the whitelist file contains 96 | at least one entry, ONLY those will be instrumented. If the blacklist matches 97 | any of these, they will not be instrumented (i.e. a blacklist match always 98 | dominates and will cause the instrumentation not to happen). This behavior 99 | allows easy combinations of both, e.g. you can specify some files to be 100 | instrumented in the whitelist but specify certain functions in the blacklist 101 | that should be left alone. 102 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | == Quick Installation Guide == 2 | 3 | # If your llvm-config, clang and clang++ are on PATH, simply run 4 | 5 | make 6 | 7 | # You can additionally specify the location of your binaries, e.g.: 8 | 9 | LLVM_CONFIG=llvm-config-3.7 CC=clang-3.7 CXX=clang++-3.7 make 10 | 11 | 12 | # If you want to build with LLVM 3.4, 3.5 or 3.6, you need to pass a define, e.g.: 13 | 14 | LLVM_CONFIG=llvm-config-3.6 CC=clang-3.6 CXX=clang++-3.6 CXXFLAGS="-DLLVM36" make 15 | 16 | # Currently, LLVM34, LLVM35 and LLVM36 defines are supported. 17 | -------------------------------------------------------------------------------- /LICENSE-LLVM.TXT: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | LLVM Release License 3 | ============================================================================== 4 | University of Illinois/NCSA 5 | Open Source License 6 | 7 | Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign. 8 | All rights reserved. 9 | 10 | Developed by: 11 | 12 | LLVM Team 13 | 14 | University of Illinois at Urbana-Champaign 15 | 16 | http://llvm.org 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a copy of 19 | this software and associated documentation files (the "Software"), to deal with 20 | the Software without restriction, including without limitation the rights to 21 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 22 | of the Software, and to permit persons to whom the Software is furnished to do 23 | so, subject to the following conditions: 24 | 25 | * Redistributions of source code must retain the above copyright notice, 26 | this list of conditions and the following disclaimers. 27 | 28 | * Redistributions in binary form must reproduce the above copyright notice, 29 | this list of conditions and the following disclaimers in the 30 | documentation and/or other materials provided with the distribution. 31 | 32 | * Neither the names of the LLVM Team, University of Illinois at 33 | Urbana-Champaign, nor the names of its contributors may be used to 34 | endorse or promote products derived from this Software without specific 35 | prior written permission. 36 | 37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 39 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE 43 | SOFTWARE. 44 | 45 | ============================================================================== 46 | Copyrights and Licenses for Third Party Software Distributed with LLVM: 47 | ============================================================================== 48 | The LLVM software contains code written by third parties. Such software will 49 | have its own individual LICENSE.TXT file in the directory in which it appears. 50 | This file will describe the copyrights, license, and restrictions which apply 51 | to that code. 52 | 53 | The disclaimer of warranty in the University of Illinois Open Source License 54 | applies to all code in the LLVM Distribution, and nothing in any of the 55 | other licenses gives permission to use the names of the LLVM Team or the 56 | University of Illinois to endorse or promote products derived from this 57 | Software. 58 | 59 | The following pieces of software have additional or alternate copyrights, 60 | licenses, and/or restrictions: 61 | 62 | Program Directory 63 | ------- --------- 64 | Autoconf llvm/autoconf 65 | llvm/projects/ModuleMaker/autoconf 66 | llvm/projects/sample/autoconf 67 | CellSPU backend llvm/lib/Target/CellSPU/README.txt 68 | Google Test llvm/utils/unittest/googletest 69 | OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} 70 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # LLCov - LLVM Live Coverage instrumentation 3 | # ----------------------------------------- 4 | # 5 | # This file was derived from the AFLFuzz project. 6 | # 7 | # Modifications by Christian Holler 8 | # 9 | # Original code written by Michal Zalewski 10 | # 11 | # Copyright 2013, 2014, 2015 Google Inc. All rights reserved. 12 | # 13 | # Licensed under the Apache License, Version 2.0 (the "License"); 14 | # you may not use this file except in compliance with the License. 15 | # You may obtain a copy of the License at: 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | 19 | PREFIX ?= /usr/local 20 | HELPER_PATH = $(PREFIX)/lib/llcov 21 | BIN_PATH = $(PREFIX)/bin 22 | 23 | LLVM_CONFIG ?= llvm-config 24 | 25 | CFLAGS ?= -O2 26 | CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ 27 | -DLLCOV_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" 28 | 29 | CXXFLAGS ?= -O2 30 | CXXFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign 31 | 32 | CLANG_CFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti $(CXXFLAGS) 33 | CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS) 34 | 35 | ifeq "$(shell uname)" "Darwin" 36 | CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress 37 | endif 38 | 39 | ifeq "$(origin CC)" "default" 40 | CC = clang 41 | CXX = clang++ 42 | endif 43 | 44 | PROGS = llcov-clang llcov-llvm-pass.so llcov-llvm-rt.o 45 | 46 | all: test_deps $(PROGS) all_done 47 | 48 | test_deps: 49 | @echo "[*] Checking for working 'llvm-config'..." 50 | @which $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 ) 51 | @echo "[*] Checking for working '$(CC)'..." 52 | @which $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 ) 53 | @echo "[+] All set and ready to build." 54 | 55 | llcov-clang: llcov-clang.c | test_deps 56 | $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) 57 | ln -sf llcov-clang llcov-clang++ 58 | 59 | llcov-llvm-pass.so: llcov-llvm-pass.so.cc | test_deps 60 | $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) 61 | 62 | llcov-llvm-rt.o: llcov-llvm-rt.o.cc | test_deps 63 | $(CC) $(CFLAGS) -fPIC -c $< -o $@ 64 | 65 | all_done: $(PROGS) 66 | @echo "[+] All done! You can now use 'llcov-clang' to compile programs." 67 | 68 | .NOTPARALLEL: clean 69 | 70 | clean: 71 | rm -f *.o *.so *~ a.out core core.[1-9][0-9]* 72 | rm -f $(PROGS) llcov-clang++ 73 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | For a short installation guide, see the INSTALL file. 2 | 3 | For examples on how to use this tool, see HOWTO. 4 | 5 | == Introducing LLCov == 6 | 7 | === What is LLCov? === 8 | 9 | LLCov is a C/C++ code instrumentation tool that can be used to measure block coverage. 10 | Unlike the popular GCOV coverage tool for GCC, LLCov instruments each basic block in 11 | the code with a call to an external function (provided by an arbitrary runtime library). 12 | In addition, the instrumentation can be limited to parts of the code (e.g. individual 13 | files, functions or blocks) to improve performance and focus on the relevant code parts. 14 | LLCov is based on LLVM and integrates into the Clang C/C++ compiler. 15 | 16 | === Why would I need this? === 17 | 18 | There are several scenarios where LLCov could aid the development process while GCOV 19 | would not be suitable for the purpose: 20 | 21 | * Instrument only code that is not covered by tests: Almost all projects have one or 22 | more test suites that cover a certain amount of the code base. Adding an 23 | instrumentation to the "untested" code can be helpful for automatic testing tools 24 | to detect when such a part of the code is executed. 25 | * Instrument only code changed by a patch: Whenever a patch is submitted, only the 26 | code that is changed by the patch could be instrumented, to see if it is covered 27 | by the test suites and to what extent. Only instrumenting the patched part should 28 | provide a great performance boost. 29 | * Use coverage information while the program is running (as a "feedback"), e.g. in a 30 | fuzzer: If the fuzzer knows that it just covered a piece of code that should be 31 | tested more extensively, it can focus further on that part. This kind of feedback 32 | can also be used to adjust probabilities in the fuzzer automatically to provide a 33 | better balance between different branches during testing. 34 | * Get coverage information via alternative ways: The runtime library of LLCov can 35 | easily be replaced/extended, e.g. to send all coverage information over a network 36 | link. Wouldn't it be nice to get coverage information from a mobile/embedded device 37 | directly over the network? 38 | -------------------------------------------------------------------------------- /alloc-inl.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file was derived from the AFLFuzz project. 3 | 4 | Modifications by Christian Holler 5 | 6 | Original code written by Michal Zalewski 7 | 8 | Copyright 2013, 2014, 2015 Google Inc. All rights reserved. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at: 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | This allocator is not designed to resist malicious attackers (the canaries 17 | are small and predictable), but provides a robust and portable way to detect 18 | use-after-free, off-by-one writes, stale pointers, and so on. 19 | 20 | */ 21 | 22 | #ifndef _HAVE_ALLOC_INL_H 23 | #define _HAVE_ALLOC_INL_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "config.h" 30 | #include "types.h" 31 | #include "debug.h" 32 | 33 | /* User-facing macro to sprintf() to a dynamically allocated buffer. */ 34 | 35 | #define alloc_printf(_str...) ({ \ 36 | u8* _tmp; \ 37 | s32 _len = snprintf(NULL, 0, _str); \ 38 | if (_len < 0) FATAL("Whoa, snprintf() fails?!"); \ 39 | _tmp = ck_alloc(_len + 1); \ 40 | snprintf((char*)_tmp, _len + 1, _str); \ 41 | _tmp; \ 42 | }) 43 | 44 | /* Macro to enforce allocation limits as a last-resort defense against 45 | integer overflows. */ 46 | 47 | #define ALLOC_CHECK_SIZE(_s) do { \ 48 | if ((_s) > MAX_ALLOC) \ 49 | ABORT("Bad alloc request: %u bytes", (_s)); \ 50 | } while (0) 51 | 52 | /* Macro to check malloc() failures and the like. */ 53 | 54 | #define ALLOC_CHECK_RESULT(_r, _s) do { \ 55 | if (!(_r)) \ 56 | ABORT("Out of memory: can't allocate %u bytes", (_s)); \ 57 | } while (0) 58 | 59 | /* Magic tokens used to mark used / freed chunks. */ 60 | 61 | #define ALLOC_MAGIC_C1 0xFF00FF00 /* Used head (dword) */ 62 | #define ALLOC_MAGIC_F 0xFE00FE00 /* Freed head (dword) */ 63 | #define ALLOC_MAGIC_C2 0xF0 /* Used tail (byte) */ 64 | 65 | /* Positions of guard tokens in relation to the user-visible pointer. */ 66 | 67 | #define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2]) 68 | #define ALLOC_S(_ptr) (((u32*)(_ptr))[-1]) 69 | #define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)]) 70 | 71 | #define ALLOC_OFF_HEAD 8 72 | #define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1) 73 | 74 | /* Allocator increments for ck_realloc_block(). */ 75 | 76 | #define ALLOC_BLK_INC 256 77 | 78 | /* Sanity-checking macros for pointers. */ 79 | 80 | #define CHECK_PTR(_p) do { \ 81 | if (_p) { \ 82 | if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\ 83 | if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ 84 | ABORT("Use after free."); \ 85 | else ABORT("Corrupted head alloc canary."); \ 86 | } \ 87 | if (ALLOC_C2(_p) ^ ALLOC_MAGIC_C2) \ 88 | ABORT("Corrupted tail alloc canary."); \ 89 | } \ 90 | } while (0) 91 | 92 | #define CHECK_PTR_EXPR(_p) ({ \ 93 | typeof (_p) _tmp = (_p); \ 94 | CHECK_PTR(_tmp); \ 95 | _tmp; \ 96 | }) 97 | 98 | 99 | /* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized 100 | requests. */ 101 | 102 | static inline void* DFL_ck_alloc_nozero(u32 size) { 103 | 104 | void* ret; 105 | 106 | if (!size) return NULL; 107 | 108 | ALLOC_CHECK_SIZE(size); 109 | ret = malloc(size + ALLOC_OFF_TOTAL); 110 | ALLOC_CHECK_RESULT(ret, size); 111 | 112 | ret += ALLOC_OFF_HEAD; 113 | 114 | ALLOC_C1(ret) = ALLOC_MAGIC_C1; 115 | ALLOC_S(ret) = size; 116 | ALLOC_C2(ret) = ALLOC_MAGIC_C2; 117 | 118 | return ret; 119 | 120 | } 121 | 122 | 123 | /* Allocate a buffer, returning zeroed memory. */ 124 | 125 | static inline void* DFL_ck_alloc(u32 size) { 126 | 127 | void* mem; 128 | 129 | if (!size) return NULL; 130 | mem = DFL_ck_alloc_nozero(size); 131 | 132 | return memset(mem, 0, size); 133 | 134 | } 135 | 136 | 137 | /* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD 138 | is set, the old memory will be also clobbered with 0xFF. */ 139 | 140 | static inline void DFL_ck_free(void* mem) { 141 | 142 | if (!mem) return; 143 | 144 | CHECK_PTR(mem); 145 | 146 | #ifdef DEBUG_BUILD 147 | 148 | /* Catch pointer issues sooner. */ 149 | memset(mem, 0xFF, ALLOC_S(mem)); 150 | 151 | #endif /* DEBUG_BUILD */ 152 | 153 | ALLOC_C1(mem) = ALLOC_MAGIC_F; 154 | 155 | free(mem - ALLOC_OFF_HEAD); 156 | 157 | } 158 | 159 | 160 | /* Re-allocate a buffer, checking for issues and zeroing any newly-added tail. 161 | With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the 162 | old memory is clobbered with 0xFF. */ 163 | 164 | static inline void* DFL_ck_realloc(void* orig, u32 size) { 165 | 166 | void* ret; 167 | u32 old_size = 0; 168 | 169 | if (!size) { 170 | 171 | DFL_ck_free(orig); 172 | return NULL; 173 | 174 | } 175 | 176 | if (orig) { 177 | 178 | CHECK_PTR(orig); 179 | 180 | #ifndef DEBUG_BUILD 181 | ALLOC_C1(orig) = ALLOC_MAGIC_F; 182 | #endif /* !DEBUG_BUILD */ 183 | 184 | old_size = ALLOC_S(orig); 185 | orig -= ALLOC_OFF_HEAD; 186 | 187 | ALLOC_CHECK_SIZE(old_size); 188 | 189 | } 190 | 191 | ALLOC_CHECK_SIZE(size); 192 | 193 | #ifndef DEBUG_BUILD 194 | 195 | ret = realloc(orig, size + ALLOC_OFF_TOTAL); 196 | ALLOC_CHECK_RESULT(ret, size); 197 | 198 | #else 199 | 200 | /* Catch pointer issues sooner: force relocation and make sure that the 201 | original buffer is wiped. */ 202 | 203 | ret = malloc(size + ALLOC_OFF_TOTAL); 204 | ALLOC_CHECK_RESULT(ret, size); 205 | 206 | if (orig) { 207 | 208 | memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size)); 209 | memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size); 210 | 211 | ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; 212 | 213 | free(orig); 214 | 215 | } 216 | 217 | #endif /* ^!DEBUG_BUILD */ 218 | 219 | ret += ALLOC_OFF_HEAD; 220 | 221 | ALLOC_C1(ret) = ALLOC_MAGIC_C1; 222 | ALLOC_S(ret) = size; 223 | ALLOC_C2(ret) = ALLOC_MAGIC_C2; 224 | 225 | if (size > old_size) 226 | memset(ret + old_size, 0, size - old_size); 227 | 228 | return ret; 229 | 230 | } 231 | 232 | 233 | /* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up 234 | repeated small reallocs without complicating the user code). */ 235 | 236 | static inline void* DFL_ck_realloc_block(void* orig, u32 size) { 237 | 238 | #ifndef DEBUG_BUILD 239 | 240 | if (orig) { 241 | 242 | CHECK_PTR(orig); 243 | 244 | if (ALLOC_S(orig) >= size) return orig; 245 | 246 | size += ALLOC_BLK_INC; 247 | 248 | } 249 | 250 | #endif /* !DEBUG_BUILD */ 251 | 252 | return DFL_ck_realloc(orig, size); 253 | 254 | } 255 | 256 | 257 | /* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */ 258 | 259 | static inline u8* DFL_ck_strdup(u8* str) { 260 | 261 | void* ret; 262 | u32 size; 263 | 264 | if (!str) return NULL; 265 | 266 | size = strlen((char*)str) + 1; 267 | 268 | ALLOC_CHECK_SIZE(size); 269 | ret = malloc(size + ALLOC_OFF_TOTAL); 270 | ALLOC_CHECK_RESULT(ret, size); 271 | 272 | ret += ALLOC_OFF_HEAD; 273 | 274 | ALLOC_C1(ret) = ALLOC_MAGIC_C1; 275 | ALLOC_S(ret) = size; 276 | ALLOC_C2(ret) = ALLOC_MAGIC_C2; 277 | 278 | return memcpy(ret, str, size); 279 | 280 | } 281 | 282 | 283 | /* Create a buffer with a copy of a memory block. Returns NULL for zero-sized 284 | or NULL inputs. */ 285 | 286 | static inline void* DFL_ck_memdup(void* mem, u32 size) { 287 | 288 | void* ret; 289 | 290 | if (!mem || !size) return NULL; 291 | 292 | ALLOC_CHECK_SIZE(size); 293 | ret = malloc(size + ALLOC_OFF_TOTAL); 294 | ALLOC_CHECK_RESULT(ret, size); 295 | 296 | ret += ALLOC_OFF_HEAD; 297 | 298 | ALLOC_C1(ret) = ALLOC_MAGIC_C1; 299 | ALLOC_S(ret) = size; 300 | ALLOC_C2(ret) = ALLOC_MAGIC_C2; 301 | 302 | return memcpy(ret, mem, size); 303 | 304 | } 305 | 306 | 307 | /* Create a buffer with a block of text, appending a NUL terminator at the end. 308 | Returns NULL for zero-sized or NULL inputs. */ 309 | 310 | static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { 311 | 312 | u8* ret; 313 | 314 | if (!mem || !size) return NULL; 315 | 316 | ALLOC_CHECK_SIZE(size); 317 | ret = malloc(size + ALLOC_OFF_TOTAL + 1); 318 | ALLOC_CHECK_RESULT(ret, size); 319 | 320 | ret += ALLOC_OFF_HEAD; 321 | 322 | ALLOC_C1(ret) = ALLOC_MAGIC_C1; 323 | ALLOC_S(ret) = size; 324 | ALLOC_C2(ret) = ALLOC_MAGIC_C2; 325 | 326 | memcpy(ret, mem, size); 327 | ret[size] = 0; 328 | 329 | return ret; 330 | 331 | } 332 | 333 | 334 | #ifndef DEBUG_BUILD 335 | 336 | /* In non-debug mode, we just do straightforward aliasing of the above functions 337 | to user-visible names such as ck_alloc(). */ 338 | 339 | #define ck_alloc DFL_ck_alloc 340 | #define ck_alloc_nozero DFL_ck_alloc_nozero 341 | #define ck_realloc DFL_ck_realloc 342 | #define ck_realloc_block DFL_ck_realloc_block 343 | #define ck_strdup DFL_ck_strdup 344 | #define ck_memdup DFL_ck_memdup 345 | #define ck_memdup_str DFL_ck_memdup_str 346 | #define ck_free DFL_ck_free 347 | 348 | #define alloc_report() 349 | 350 | #else 351 | 352 | /* In debugging mode, we also track allocations to detect memory leaks, and the 353 | flow goes through one more layer of indirection. */ 354 | 355 | /* Alloc tracking data structures: */ 356 | 357 | #define ALLOC_BUCKETS 4096 358 | 359 | struct TRK_obj { 360 | void *ptr; 361 | char *file, *func; 362 | u32 line; 363 | }; 364 | 365 | #ifdef AFL_MAIN 366 | 367 | struct TRK_obj* TRK[ALLOC_BUCKETS]; 368 | u32 TRK_cnt[ALLOC_BUCKETS]; 369 | 370 | # define alloc_report() TRK_report() 371 | 372 | #else 373 | 374 | extern struct TRK_obj* TRK[ALLOC_BUCKETS]; 375 | extern u32 TRK_cnt[ALLOC_BUCKETS]; 376 | 377 | # define alloc_report() 378 | 379 | #endif /* ^AFL_MAIN */ 380 | 381 | /* Bucket-assigning function for a given pointer: */ 382 | 383 | #define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS) 384 | 385 | 386 | /* Add a new entry to the list of allocated objects. */ 387 | 388 | static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func, 389 | u32 line) { 390 | 391 | u32 i, bucket; 392 | 393 | if (!ptr) return; 394 | 395 | bucket = TRKH(ptr); 396 | 397 | /* Find a free slot in the list of entries for that bucket. */ 398 | 399 | for (i = 0; i < TRK_cnt[bucket]; i++) 400 | 401 | if (!TRK[bucket][i].ptr) { 402 | 403 | TRK[bucket][i].ptr = ptr; 404 | TRK[bucket][i].file = (char*)file; 405 | TRK[bucket][i].func = (char*)func; 406 | TRK[bucket][i].line = line; 407 | return; 408 | 409 | } 410 | 411 | /* No space available - allocate more. */ 412 | 413 | TRK[bucket] = DFL_ck_realloc_block(TRK[bucket], 414 | (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj)); 415 | 416 | TRK[bucket][i].ptr = ptr; 417 | TRK[bucket][i].file = (char*)file; 418 | TRK[bucket][i].func = (char*)func; 419 | TRK[bucket][i].line = line; 420 | 421 | TRK_cnt[bucket]++; 422 | 423 | } 424 | 425 | 426 | /* Remove entry from the list of allocated objects. */ 427 | 428 | static inline void TRK_free_buf(void* ptr, const char* file, const char* func, 429 | u32 line) { 430 | 431 | u32 i, bucket; 432 | 433 | if (!ptr) return; 434 | 435 | bucket = TRKH(ptr); 436 | 437 | /* Find the element on the list... */ 438 | 439 | for (i = 0; i < TRK_cnt[bucket]; i++) 440 | 441 | if (TRK[bucket][i].ptr == ptr) { 442 | 443 | TRK[bucket][i].ptr = 0; 444 | return; 445 | 446 | } 447 | 448 | WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)", 449 | func, file, line); 450 | 451 | } 452 | 453 | 454 | /* Do a final report on all non-deallocated objects. */ 455 | 456 | static inline void TRK_report(void) { 457 | 458 | u32 i, bucket; 459 | 460 | fflush(0); 461 | 462 | for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++) 463 | for (i = 0; i < TRK_cnt[bucket]; i++) 464 | if (TRK[bucket][i].ptr) 465 | WARNF("ALLOC: Memory never freed, created in %s (%s:%u)", 466 | TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line); 467 | 468 | } 469 | 470 | 471 | /* Simple wrappers for non-debugging functions: */ 472 | 473 | static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func, 474 | u32 line) { 475 | 476 | void* ret = DFL_ck_alloc(size); 477 | TRK_alloc_buf(ret, file, func, line); 478 | return ret; 479 | 480 | } 481 | 482 | 483 | static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file, 484 | const char* func, u32 line) { 485 | 486 | void* ret = DFL_ck_realloc(orig, size); 487 | TRK_free_buf(orig, file, func, line); 488 | TRK_alloc_buf(ret, file, func, line); 489 | return ret; 490 | 491 | } 492 | 493 | 494 | static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file, 495 | const char* func, u32 line) { 496 | 497 | void* ret = DFL_ck_realloc_block(orig, size); 498 | TRK_free_buf(orig, file, func, line); 499 | TRK_alloc_buf(ret, file, func, line); 500 | return ret; 501 | 502 | } 503 | 504 | 505 | static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func, 506 | u32 line) { 507 | 508 | void* ret = DFL_ck_strdup(str); 509 | TRK_alloc_buf(ret, file, func, line); 510 | return ret; 511 | 512 | } 513 | 514 | 515 | static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file, 516 | const char* func, u32 line) { 517 | 518 | void* ret = DFL_ck_memdup(mem, size); 519 | TRK_alloc_buf(ret, file, func, line); 520 | return ret; 521 | 522 | } 523 | 524 | 525 | static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file, 526 | const char* func, u32 line) { 527 | 528 | void* ret = DFL_ck_memdup_str(mem, size); 529 | TRK_alloc_buf(ret, file, func, line); 530 | return ret; 531 | 532 | } 533 | 534 | 535 | static inline void TRK_ck_free(void* ptr, const char* file, 536 | const char* func, u32 line) { 537 | 538 | TRK_free_buf(ptr, file, func, line); 539 | DFL_ck_free(ptr); 540 | 541 | } 542 | 543 | /* Aliasing user-facing names to tracking functions: */ 544 | 545 | #define ck_alloc(_p1) \ 546 | TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) 547 | 548 | #define ck_alloc_nozero(_p1) \ 549 | TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) 550 | 551 | #define ck_realloc(_p1, _p2) \ 552 | TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) 553 | 554 | #define ck_realloc_block(_p1, _p2) \ 555 | TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) 556 | 557 | #define ck_strdup(_p1) \ 558 | TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) 559 | 560 | #define ck_memdup(_p1, _p2) \ 561 | TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) 562 | 563 | #define ck_memdup_str(_p1, _p2) \ 564 | TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) 565 | 566 | #define ck_free(_p1) \ 567 | TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) 568 | 569 | #endif /* ^!DEBUG_BUILD */ 570 | 571 | #endif /* ! _HAVE_ALLOC_INL_H */ 572 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* 2 | american fuzzy lop - vaguely configurable bits 3 | ---------------------------------------------- 4 | 5 | Written and maintained by Michal Zalewski 6 | 7 | Copyright 2013, 2014, 2015 Google Inc. All rights reserved. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at: 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | */ 16 | 17 | #ifndef _HAVE_CONFIG_H 18 | #define _HAVE_CONFIG_H 19 | 20 | #include "types.h" 21 | 22 | /****************************************************** 23 | * * 24 | * Settings that may be of interest to power users: * 25 | * * 26 | ******************************************************/ 27 | 28 | /* Comment out to disable terminal colors: */ 29 | 30 | #define USE_COLOR 31 | 32 | /* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ 33 | 34 | #define FANCY_BOXES 35 | 36 | /* Default timeout for fuzzed code (milliseconds): */ 37 | 38 | #define EXEC_TIMEOUT 1000 39 | 40 | /* Timeout rounding factor when auto-scaling (milliseconds): */ 41 | 42 | #define EXEC_TM_ROUND 20 43 | 44 | /* Default memory limit for child process (MB): */ 45 | 46 | #ifndef __x86_64__ 47 | # define MEM_LIMIT 25 48 | #else 49 | # define MEM_LIMIT 50 50 | #endif /* ^!__x86_64__ */ 51 | 52 | /* Default memory limit when running in QEMU mode (MB): */ 53 | 54 | #define MEM_LIMIT_QEMU 200 55 | 56 | /* Number of calibration cycles per every new test case (and for test 57 | cases that show variable behavior): */ 58 | 59 | #define CAL_CYCLES 10 60 | #define CAL_CYCLES_LONG 40 61 | 62 | /* The same, but when AFL_NO_VAR_CHECK is set in the environment: */ 63 | 64 | #define CAL_CYCLES_NO_VAR 4 65 | 66 | /* Number of subsequent hangs before abandoning an input file: */ 67 | 68 | #define HANG_LIMIT 250 69 | 70 | /* Maximum number of unique hangs or crashes to record: */ 71 | 72 | #define KEEP_UNIQUE_HANG 500 73 | #define KEEP_UNIQUE_CRASH 5000 74 | 75 | /* Baseline number of random tweaks during a single 'havoc' stage: */ 76 | 77 | #define HAVOC_CYCLES 5000 78 | 79 | /* Maximum multiplier for the above (should be a power of two, beware 80 | of 32-bit int overflows): */ 81 | 82 | #define HAVOC_MAX_MULT 16 83 | 84 | /* Absolute minimum number of havoc cycles (after all adjustments): */ 85 | 86 | #define HAVOC_MIN 10 87 | 88 | /* Maximum stacking for havoc-stage tweaks. The actual value is calculated 89 | like this: 90 | 91 | n = random between 1 and HAVOC_STACK_POW2 92 | stacking = 2^n 93 | 94 | In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or 95 | 128 stacked tweaks: */ 96 | 97 | #define HAVOC_STACK_POW2 7 98 | 99 | /* Caps on block sizes for cloning and deletion operations. Each of these 100 | ranges has a 33% probability of getting picked, except for the first 101 | two cycles where smaller blocks are favored: */ 102 | 103 | #define HAVOC_BLK_SMALL 32 104 | #define HAVOC_BLK_MEDIUM 128 105 | #define HAVOC_BLK_LARGE 1500 106 | 107 | /* Probabilities of skipping non-favored entries in the queue, expressed as 108 | percentages: */ 109 | 110 | #define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ 111 | #define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ 112 | #define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */ 113 | 114 | /* Splicing cycle count: */ 115 | 116 | #define SPLICE_CYCLES 20 117 | 118 | /* Nominal per-splice havoc cycle length: */ 119 | 120 | #define SPLICE_HAVOC 500 121 | 122 | /* Maximum offset for integer addition / subtraction stages: */ 123 | 124 | #define ARITH_MAX 35 125 | 126 | /* Limits for the test case trimmer. The absolute minimum chunk size; and 127 | the starting and ending divisors for chopping up the input file: */ 128 | 129 | #define TRIM_MIN_BYTES 4 130 | #define TRIM_START_STEPS 16 131 | #define TRIM_END_STEPS 1024 132 | 133 | /* Maximum size of input file, in bytes (keep under 100MB): */ 134 | 135 | #define MAX_FILE (1 * 1024 * 1024) 136 | 137 | /* The same, for the test case minimizer: */ 138 | 139 | #define TMIN_MAX_FILE (10 * 1024 * 1024) 140 | 141 | /* Block normalization steps for afl-tmin: */ 142 | 143 | #define TMIN_SET_MIN_SIZE 4 144 | #define TMIN_SET_STEPS 128 145 | 146 | /* Maximum dictionary token size (-x), in bytes: */ 147 | 148 | #define MAX_DICT_FILE 128 149 | 150 | /* Length limits for auto-detected dictionary tokens: */ 151 | 152 | #define MIN_AUTO_EXTRA 3 153 | #define MAX_AUTO_EXTRA 32 154 | 155 | /* Maximum number of user-specified dictionary tokens to use in deterministic 156 | steps; past this point, the "extras/user" step will be still carried out, 157 | but with proportionally lower odds: */ 158 | 159 | #define MAX_DET_EXTRAS 200 160 | 161 | /* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing 162 | (first value), and to keep in memory as candidates. The latter should be much 163 | higher than the former. */ 164 | 165 | #define USE_AUTO_EXTRAS 50 166 | #define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10) 167 | 168 | /* Scaling factor for the effector map used to skip some of the more 169 | expensive deterministic steps. The actual divisor is set to 170 | 2^EFF_MAP_SCALE2 bytes: */ 171 | 172 | #define EFF_MAP_SCALE2 3 173 | 174 | /* Minimum input file length at which the effector logic kicks in: */ 175 | 176 | #define EFF_MIN_LEN 128 177 | 178 | /* Maximum effector density past which everything is just fuzzed 179 | unconditionally (%): */ 180 | 181 | #define EFF_MAX_PERC 90 182 | 183 | /* UI refresh frequency (Hz): */ 184 | 185 | #define UI_TARGET_HZ 5 186 | 187 | /* Fuzzer stats file and plot update intervals (sec): */ 188 | 189 | #define STATS_UPDATE_SEC 60 190 | #define PLOT_UPDATE_SEC 5 191 | 192 | /* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ 193 | 194 | #define AVG_SMOOTHING 16 195 | 196 | /* Sync interval (every n havoc cycles): */ 197 | 198 | #define SYNC_INTERVAL 5 199 | 200 | /* Output directory reuse grace period (minutes): */ 201 | 202 | #define OUTPUT_GRACE 25 203 | 204 | /* Uncomment to use simple file names (id_NNNNNN): */ 205 | 206 | // #define SIMPLE_FILES 207 | 208 | /* List of interesting values to use in fuzzing. */ 209 | 210 | #define INTERESTING_8 \ 211 | -128, /* Overflow signed 8-bit when decremented */ \ 212 | -1, /* */ \ 213 | 0, /* */ \ 214 | 1, /* */ \ 215 | 16, /* One-off with common buffer size */ \ 216 | 32, /* One-off with common buffer size */ \ 217 | 64, /* One-off with common buffer size */ \ 218 | 100, /* One-off with common buffer size */ \ 219 | 127 /* Overflow signed 8-bit when incremented */ 220 | 221 | #define INTERESTING_16 \ 222 | -32768, /* Overflow signed 16-bit when decremented */ \ 223 | -129, /* Overflow signed 8-bit */ \ 224 | 128, /* Overflow signed 8-bit */ \ 225 | 255, /* Overflow unsig 8-bit when incremented */ \ 226 | 256, /* Overflow unsig 8-bit */ \ 227 | 512, /* One-off with common buffer size */ \ 228 | 1000, /* One-off with common buffer size */ \ 229 | 1024, /* One-off with common buffer size */ \ 230 | 4096, /* One-off with common buffer size */ \ 231 | 32767 /* Overflow signed 16-bit when incremented */ 232 | 233 | #define INTERESTING_32 \ 234 | -2147483648LL, /* Overflow signed 32-bit when decremented */ \ 235 | -100663046, /* Large negative number (endian-agnostic) */ \ 236 | -32769, /* Overflow signed 16-bit */ \ 237 | 32768, /* Overflow signed 16-bit */ \ 238 | 65535, /* Overflow unsig 16-bit when incremented */ \ 239 | 65536, /* Overflow unsig 16 bit */ \ 240 | 100663045, /* Large positive number (endian-agnostic) */ \ 241 | 2147483647 /* Overflow signed 32-bit when incremented */ 242 | 243 | /*********************************************************** 244 | * * 245 | * Really exotic stuff you probably don't want to touch: * 246 | * * 247 | ***********************************************************/ 248 | 249 | /* Call count interval between reseeding the libc PRNG from /dev/urandom: */ 250 | 251 | #define RESEED_RNG 10000 252 | 253 | /* Maximum line length passed from GCC to 'as' and used for parsing 254 | configuration files: */ 255 | 256 | #define MAX_LINE 8192 257 | 258 | /* Environment variable used to pass SHM ID to the called program. */ 259 | 260 | #define SHM_ENV_VAR "__AFL_SHM_ID" 261 | 262 | /* Other less interesting, internal-only variables. */ 263 | 264 | #define CLANG_ENV_VAR "__AFL_CLANG_MODE" 265 | #define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" 266 | #define PERSIST_ENV_VAR "__AFL_PERSISTENT" 267 | #define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" 268 | 269 | /* In-code signatures for deferred and persistent mode. */ 270 | 271 | #define PERSIST_SIG "##SIG_AFL_PERSISTENT##" 272 | #define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" 273 | 274 | /* Distinctive bitmap signature used to indicate failed execution: */ 275 | 276 | #define EXEC_FAIL_SIG 0xfee1dead 277 | 278 | /* Distinctive exit code used to indicate MSAN trip condition: */ 279 | 280 | #define MSAN_ERROR 86 281 | 282 | /* Designated file descriptors for forkserver commands (the application will 283 | use FORKSRV_FD and FORKSRV_FD + 1): */ 284 | 285 | #define FORKSRV_FD 198 286 | 287 | /* Fork server init timeout multiplier: we'll wait the user-selected 288 | timeout plus this much for the fork server to spin up. */ 289 | 290 | #define FORK_WAIT_MULT 10 291 | 292 | /* Calibration timeout adjustments, to be a bit more generous when resuming 293 | fuzzing sessions or trying to calibrate already-added internal finds. 294 | The first value is a percentage, the other is in milliseconds: */ 295 | 296 | #define CAL_TMOUT_PERC 125 297 | #define CAL_TMOUT_ADD 50 298 | 299 | /* Number of chances to calibrate a case before giving up: */ 300 | 301 | #define CAL_CHANCES 3 302 | 303 | /* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than 304 | 2; you probably want to keep it under 18 or so for performance reasons 305 | (adjusting AFL_INST_RATIO when compiling is probably a better way to solve 306 | problems with complex programs). You need to recompile the target binary 307 | after changing this - otherwise, SEGVs may ensue. */ 308 | 309 | #define MAP_SIZE_POW2 16 310 | #define MAP_SIZE (1 << MAP_SIZE_POW2) 311 | 312 | /* Maximum allocator request size (keep well under INT_MAX): */ 313 | 314 | #define MAX_ALLOC 0x40000000 315 | 316 | /* A made-up hashing seed: */ 317 | 318 | #define HASH_CONST 0xa5b35705 319 | 320 | /* Constants for afl-gotcpu to control busy loop timing: */ 321 | 322 | #define CTEST_TARGET_MS 5000 323 | #define CTEST_BUSY_CYCLES (10 * 1000 * 1000) 324 | 325 | /* Uncomment this to use inferior block-coverage-based instrumentation. Note 326 | that you need to recompile the target binary for this to have any effect: */ 327 | 328 | // #define COVERAGE_ONLY 329 | 330 | /* Uncomment this to ignore hit counts and output just one bit per tuple. 331 | As with the previous setting, you will need to recompile the target 332 | binary: */ 333 | 334 | // #define SKIP_COUNTS 335 | 336 | /* Uncomment this to use instrumentation data to record newly discovered paths, 337 | but do not use them as seeds for fuzzing. This is useful for conveniently 338 | measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ 339 | 340 | // #define IGNORE_FINDS 341 | 342 | #endif /* ! _HAVE_CONFIG_H */ 343 | -------------------------------------------------------------------------------- /debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file was derived from the AFLFuzz project. 3 | 4 | Modifications by Christian Holler 5 | 6 | Original code written by Michal Zalewski 7 | 8 | Copyright 2013, 2014, 2015 Google Inc. All rights reserved. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at: 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | */ 17 | 18 | #ifndef _HAVE_DEBUG_H 19 | #define _HAVE_DEBUG_H 20 | 21 | #include 22 | 23 | #include "types.h" 24 | #include "config.h" 25 | 26 | /******************* 27 | * Terminal colors * 28 | *******************/ 29 | 30 | #ifdef USE_COLOR 31 | 32 | # define cBLK "\x1b[0;30m" 33 | # define cRED "\x1b[0;31m" 34 | # define cGRN "\x1b[0;32m" 35 | # define cBRN "\x1b[0;33m" 36 | # define cBLU "\x1b[0;34m" 37 | # define cMGN "\x1b[0;35m" 38 | # define cCYA "\x1b[0;36m" 39 | # define cNOR "\x1b[0;37m" 40 | # define cGRA "\x1b[1;30m" 41 | # define cLRD "\x1b[1;31m" 42 | # define cLGN "\x1b[1;32m" 43 | # define cYEL "\x1b[1;33m" 44 | # define cLBL "\x1b[1;34m" 45 | # define cPIN "\x1b[1;35m" 46 | # define cLCY "\x1b[1;36m" 47 | # define cBRI "\x1b[1;37m" 48 | # define cRST "\x1b[0m" 49 | 50 | #else 51 | 52 | # define cBLK "" 53 | # define cRED "" 54 | # define cGRN "" 55 | # define cBRN "" 56 | # define cBLU "" 57 | # define cMGN "" 58 | # define cCYA "" 59 | # define cNOR "" 60 | # define cGRA "" 61 | # define cLRD "" 62 | # define cLGN "" 63 | # define cYEL "" 64 | # define cLBL "" 65 | # define cPIN "" 66 | # define cLCY "" 67 | # define cBRI "" 68 | # define cRST "" 69 | 70 | #endif /* ^USE_COLOR */ 71 | 72 | /************************* 73 | * Box drawing sequences * 74 | *************************/ 75 | 76 | #ifdef FANCY_BOXES 77 | 78 | # define SET_G1 "\x1b)0" /* Set G1 for box drawing */ 79 | # define RESET_G1 "\x1b)B" /* Reset G1 to ASCII */ 80 | # define bSTART "\x0e" /* Enter G1 drawing mode */ 81 | # define bSTOP "\x0f" /* Leave G1 drawing mode */ 82 | # define bH "q" /* Horizontal line */ 83 | # define bV "x" /* Vertical line */ 84 | # define bLT "l" /* Left top corner */ 85 | # define bRT "k" /* Right top corner */ 86 | # define bLB "m" /* Left bottom corner */ 87 | # define bRB "j" /* Right bottom corner */ 88 | # define bX "n" /* Cross */ 89 | # define bVR "t" /* Vertical, branch right */ 90 | # define bVL "u" /* Vertical, branch left */ 91 | # define bHT "v" /* Horizontal, branch top */ 92 | # define bHB "w" /* Horizontal, branch bottom */ 93 | 94 | #else 95 | 96 | # define SET_G1 "" 97 | # define RESET_G1 "" 98 | # define bSTART "" 99 | # define bSTOP "" 100 | # define bH "-" 101 | # define bV "|" 102 | # define bLT "+" 103 | # define bRT "+" 104 | # define bLB "+" 105 | # define bRB "+" 106 | # define bX "+" 107 | # define bVR "+" 108 | # define bVL "+" 109 | # define bHT "+" 110 | # define bHB "+" 111 | 112 | #endif /* ^FANCY_BOXES */ 113 | 114 | /*********************** 115 | * Misc terminal codes * 116 | ***********************/ 117 | 118 | #define TERM_HOME "\x1b[H" 119 | #define TERM_CLEAR TERM_HOME "\x1b[2J" 120 | #define cEOL "\x1b[0K" 121 | #define CURSOR_HIDE "\x1b[?25l" 122 | #define CURSOR_SHOW "\x1b[?25h" 123 | 124 | /************************ 125 | * Debug & error macros * 126 | ************************/ 127 | 128 | /* Just print stuff to the appropriate stream. */ 129 | 130 | #ifdef MESSAGES_TO_STDOUT 131 | # define SAYF(x...) printf(x) 132 | #else 133 | # define SAYF(x...) fprintf(stderr, x) 134 | #endif /* ^MESSAGES_TO_STDOUT */ 135 | 136 | /* Show a prefixed warning. */ 137 | 138 | #define WARNF(x...) do { \ 139 | SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \ 140 | SAYF(cRST "\n"); \ 141 | } while (0) 142 | 143 | /* Show a prefixed "doing something" message. */ 144 | 145 | #define ACTF(x...) do { \ 146 | SAYF(cLBL "[*] " cRST x); \ 147 | SAYF(cRST "\n"); \ 148 | } while (0) 149 | 150 | /* Show a prefixed "success" message. */ 151 | 152 | #define OKF(x...) do { \ 153 | SAYF(cLGN "[+] " cRST x); \ 154 | SAYF(cRST "\n"); \ 155 | } while (0) 156 | 157 | /* Show a prefixed fatal error message (not used in afl). */ 158 | 159 | #define BADF(x...) do { \ 160 | SAYF(cLRD "\n[-] " cRST x); \ 161 | SAYF(cRST "\n"); \ 162 | } while (0) 163 | 164 | /* Die with a verbose non-OS fatal error message. */ 165 | 166 | #define FATAL(x...) do { \ 167 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cLRD "\n[-] PROGRAM ABORT : " cBRI x); \ 168 | SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", \ 169 | __FUNCTION__, __FILE__, __LINE__); \ 170 | exit(1); \ 171 | } while (0) 172 | 173 | /* Die by calling abort() to provide a core dump. */ 174 | 175 | #define ABORT(x...) do { \ 176 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cLRD "\n[-] PROGRAM ABORT : " cBRI x); \ 177 | SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", \ 178 | __FUNCTION__, __FILE__, __LINE__); \ 179 | abort(); \ 180 | } while (0) 181 | 182 | /* Die while also including the output of perror(). */ 183 | 184 | #define PFATAL(x...) do { \ 185 | fflush(stdout); \ 186 | SAYF(bSTOP RESET_G1 CURSOR_SHOW cLRD "\n[-] SYSTEM ERROR : " cBRI x); \ 187 | SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", \ 188 | __FUNCTION__, __FILE__, __LINE__); \ 189 | SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ 190 | exit(1); \ 191 | } while (0) 192 | 193 | /* Die with FAULT() or PFAULT() depending on the value of res (used to 194 | interpret different failure modes for read(), write(), etc). */ 195 | 196 | #define RPFATAL(res, x...) do { \ 197 | if (res < 0) PFATAL(x); else FATAL(x); \ 198 | } while (0) 199 | 200 | /* Error-checking versions of read() and write() that call RPFATAL() as 201 | appropriate. */ 202 | 203 | #define ck_write(fd, buf, len, fn) do { \ 204 | u32 _len = (len); \ 205 | s32 _res = write(fd, buf, _len); \ 206 | if (_res != _len) RPFATAL(_res, "Short write to %s", fn); \ 207 | } while (0) 208 | 209 | #define ck_read(fd, buf, len, fn) do { \ 210 | u32 _len = (len); \ 211 | s32 _res = read(fd, buf, _len); \ 212 | if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ 213 | } while (0) 214 | 215 | #endif /* ! _HAVE_DEBUG_H */ 216 | -------------------------------------------------------------------------------- /example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) { 4 | switch(argc) { 5 | case 1: 6 | std::cout << "One argument" << std::endl; 7 | break; 8 | case 2: 9 | case 3: 10 | std::cout << "Two or three arguments" << std::endl; 11 | break; 12 | default: 13 | std::cout << "More than three arguments" << std::endl; 14 | } 15 | 16 | if (argc > 2) 17 | return 0; 18 | 19 | return 1; 20 | } 21 | -------------------------------------------------------------------------------- /llcov-clang.c: -------------------------------------------------------------------------------- 1 | /* 2 | LLCov - LLVM Live Coverage instrumentation 3 | ----------------------------------------- 4 | 5 | Modified by Christian Holler 6 | 7 | This wrapper was derived from the LLVM integration of AFLFuzz, 8 | 9 | written by Laszlo Szekeres and 10 | Michal Zalewski 11 | 12 | Copyright 2013, 2014, 2015 Google Inc. All rights reserved. 13 | 14 | Licensed under the Apache License, Version 2.0 (the "License"); 15 | you may not use this file except in compliance with the License. 16 | You may obtain a copy of the License at: 17 | 18 | http://www.apache.org/licenses/LICENSE-2.0 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "config.h" 27 | #include "types.h" 28 | #include "debug.h" 29 | #include "alloc-inl.h" 30 | 31 | #define VERSION "0.9a" 32 | 33 | static u8* obj_path; /* Path to runtime libraries */ 34 | static u8** cc_params; /* Parameters passed to the real CC */ 35 | static u32 cc_par_cnt = 1; /* Param count, including argv0 */ 36 | 37 | 38 | /* Try to find the runtime libraries. If that fails, abort. */ 39 | 40 | static void find_obj(u8* argv0) { 41 | 42 | u8 *llcov_path = getenv("LLCOV_PATH"); 43 | u8 *slash, *tmp; 44 | 45 | if (llcov_path) { 46 | 47 | tmp = alloc_printf("%s/llcov-llvm-rt.o", llcov_path); 48 | 49 | if (!access(tmp, R_OK)) { 50 | obj_path = llcov_path; 51 | ck_free(tmp); 52 | return; 53 | } 54 | 55 | ck_free(tmp); 56 | 57 | } 58 | 59 | slash = strrchr(argv0, '/'); 60 | 61 | if (slash) { 62 | 63 | u8 *dir; 64 | 65 | *slash = 0; 66 | dir = ck_strdup(argv0); 67 | *slash = '/'; 68 | 69 | tmp = alloc_printf("%s/llcov-llvm-rt.o", dir); 70 | 71 | if (!access(tmp, R_OK)) { 72 | obj_path = dir; 73 | ck_free(tmp); 74 | return; 75 | } 76 | 77 | ck_free(tmp); 78 | ck_free(dir); 79 | 80 | } 81 | 82 | if (!access(LLCOV_PATH "/llcov-llvm-rt.o", R_OK)) { 83 | obj_path = LLCOV_PATH; 84 | return; 85 | } 86 | 87 | FATAL("Unable to find 'llcov-llvm-rt.o' or 'llcov-llvm-pass.so'. Please set LLCOV_PATH"); 88 | 89 | } 90 | 91 | 92 | /* Copy argv to cc_params, making the necessary edits. */ 93 | 94 | static void edit_params(u32 argc, char** argv) { 95 | 96 | u8 x_set = 0, maybe_linking = 1; 97 | u8 *name; 98 | 99 | cc_params = ck_alloc((argc + 64) * sizeof(u8*)); 100 | 101 | name = strrchr(argv[0], '/'); 102 | if (!name) name = argv[0]; else name++; 103 | 104 | if (!strcmp(name, "llcov-clang++")) { 105 | u8* alt_cxx = getenv("LLCOV_CXX"); 106 | cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; 107 | } else { 108 | u8* alt_cc = getenv("LLCOV_CC"); 109 | cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; 110 | } 111 | 112 | cc_params[cc_par_cnt++] = "-Xclang"; 113 | cc_params[cc_par_cnt++] = "-load"; 114 | cc_params[cc_par_cnt++] = "-Xclang"; 115 | cc_params[cc_par_cnt++] = alloc_printf("%s/llcov-llvm-pass.so", obj_path); 116 | cc_params[cc_par_cnt++] = "-Qunused-arguments"; 117 | 118 | while (--argc) { 119 | u8* cur = *(++argv); 120 | 121 | #if defined(__x86_64__) 122 | if (!strcmp(cur, "-m32")) FATAL("-m32 is not supported"); 123 | #endif 124 | 125 | if (!strcmp(cur, "-x")) x_set = 1; 126 | 127 | if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E") || 128 | !strcmp(cur, "-v")) maybe_linking = 0; 129 | 130 | cc_params[cc_par_cnt++] = cur; 131 | 132 | } 133 | 134 | /* Debug information is required to properly resolve the original 135 | locations of the instrumented basic blocks */ 136 | cc_params[cc_par_cnt++] = "-g"; 137 | 138 | if (maybe_linking) { 139 | 140 | if (x_set) { 141 | cc_params[cc_par_cnt++] = "-x"; 142 | cc_params[cc_par_cnt++] = "none"; 143 | } 144 | 145 | cc_params[cc_par_cnt++] = alloc_printf("%s/llcov-llvm-rt.o", obj_path); 146 | 147 | } 148 | 149 | cc_params[cc_par_cnt] = NULL; 150 | 151 | } 152 | 153 | 154 | /* Main entry point */ 155 | 156 | int main(int argc, char** argv) { 157 | 158 | if (isatty(2) && !getenv("LLCOV_QUIET")) { 159 | 160 | SAYF(cCYA "llcov-clang " cBRI VERSION cRST " by \n"); 161 | 162 | } 163 | 164 | if (argc < 2) { 165 | 166 | SAYF("\n" 167 | "This is a compiler wrapper for LLCOV. It serves as a drop-in replacement\n" 168 | "for clang, letting you recompile third-party code with the required runtime\n" 169 | "instrumentation. A common use pattern would be one of the following:\n\n" 170 | 171 | " CC=%s/llcov-clang ./configure\n" 172 | " CXX=%s/llcov-clang++ ./configure\n\n" 173 | 174 | "You can specify custom next-stage toolchain via LLCOV_CC and LLCOV_CXX.\n\n", 175 | BIN_PATH, BIN_PATH); 176 | 177 | exit(1); 178 | 179 | } 180 | 181 | 182 | find_obj(argv[0]); 183 | 184 | edit_params(argc, argv); 185 | 186 | execvp(cc_params[0], (char**)cc_params); 187 | 188 | FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); 189 | 190 | return 0; 191 | 192 | } 193 | -------------------------------------------------------------------------------- /llcov-llvm-pass.so.cc: -------------------------------------------------------------------------------- 1 | //===- LLCov.cpp - Live Coverage Instrumentation Pass for LLVM -----------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE-LLVM.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements a block coverage instrumentation that calls 11 | // into a runtime library whenever a basic block is executed. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #define DEBUG_TYPE "llcov" 16 | 17 | #include "llvm/ADT/Statistic.h" 18 | #include "llvm/IR/IRBuilder.h" 19 | #include "llvm/IR/LegacyPassManager.h" 20 | #include "llvm/IR/Module.h" 21 | #include "llvm/Support/Debug.h" 22 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 23 | 24 | #if defined(LLVM34) 25 | #include "llvm/DebugInfo.h" 26 | #else 27 | #include "llvm/IR/DebugInfo.h" 28 | #endif 29 | 30 | #if defined(LLVM34) || defined(LLVM35) || defined(LLVM36) 31 | #define LLVM_OLD_DEBUG_API 32 | #endif 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | using namespace llvm; 42 | 43 | /* Start of helper classes */ 44 | 45 | /* Container class for our list entries */ 46 | struct LLCovListEntry { 47 | public: 48 | LLCovListEntry() : myHasLine(false), myHasRelblock(false) {} 49 | 50 | bool matchFileName(const std::string &fileName) { 51 | /* 52 | * We don't check for filename equality here because 53 | * filenames might actually be full paths. Instead we 54 | * check that the actual filename ends in the filename 55 | * specified in the list. 56 | */ 57 | if (fileName.length() >= myFilename.length()) { 58 | return (fileName.compare(fileName.length() - myFilename.length(), myFilename.length(), myFilename) == 0); 59 | } else { 60 | return false; 61 | } 62 | } 63 | 64 | bool matchFuncName(const std::string &funcName) { 65 | return (funcName == myFunction); 66 | } 67 | 68 | bool matchFileFuncName(const std::string &fileName, const std::string &funcName) { 69 | return (matchFileName(fileName) && matchFuncName(funcName)); 70 | } 71 | 72 | bool matchAll(const std::string &fileName, const std::string &funcName, unsigned int line) { 73 | return ((line == myLine) && matchFileFuncName(fileName, funcName)); 74 | } 75 | 76 | bool matchAllRelblock(const std::string &fileName, const std::string &funcName, unsigned int line, unsigned int relblock) { 77 | return ((myRelblock == relblock) && matchAll(fileName, funcName, line)); 78 | } 79 | 80 | bool matchFileLine(const std::string &fileName, unsigned int line) { 81 | return ((line == myLine) && matchFileName(fileName)); 82 | } 83 | 84 | bool matchFileLineRelblock(const std::string &fileName, unsigned int line, unsigned int relblock) { 85 | return (matchFileLine(fileName, line) && myRelblock == relblock); 86 | } 87 | bool hasFilename() { return myFilename.size(); } 88 | bool hasFunction() { return myFunction.size(); } 89 | bool hasLine() { return myHasLine; } 90 | bool hasRelblock() { return myHasRelblock; } 91 | 92 | const std::string& getFilename() { return myFilename; } 93 | 94 | void setFilename(const std::string &fileName) { 95 | myFilename = fileName; 96 | } 97 | 98 | void setFunction(const std::string &funcName) { 99 | myFunction = funcName; 100 | } 101 | 102 | void setLine(unsigned int line) { 103 | myLine = line; 104 | myHasLine = true; 105 | } 106 | 107 | void setRelblock(unsigned int relblock) { 108 | myRelblock = relblock; 109 | myHasRelblock = true; 110 | } 111 | protected: 112 | bool myHasLine; 113 | bool myHasRelblock; 114 | std::string myFilename; 115 | std::string myFunction; 116 | unsigned int myLine; 117 | unsigned int myRelblock; 118 | }; 119 | 120 | struct LLCovList { 121 | public: 122 | LLCovList(const std::string &path); 123 | virtual bool doCoarseMatch( StringRef filename, Function &F ); 124 | virtual bool doExactMatch( StringRef filename, Function &F ); 125 | virtual bool doExactMatch( StringRef filename, Function &F, unsigned int line ); 126 | virtual bool doExactMatch( StringRef filename, unsigned int line ); 127 | virtual bool doExactMatch( StringRef filename, Function &F, unsigned int line, unsigned int relblock ); 128 | virtual bool doExactMatch( StringRef filename, unsigned int line, unsigned int relblock ); 129 | virtual bool isEmpty() { return myEntries.empty(); } 130 | protected: 131 | virtual bool doMatch(StringRef filename, Function &F, bool exact); 132 | std::multimap myEntries; 133 | }; 134 | 135 | bool LLCovList::doMatch(StringRef filename, Function &F, bool exact) { 136 | /* 137 | * Search one entry that mentiones either this file 138 | * or this function to return true. 139 | */ 140 | // XXX: TODO: This and all of the following commented equal_range optimizations don't work because we're having trouble 141 | // with absolute vs. relative paths used for the filenames. Filename matching requires a substring match to the end. 142 | // Maybe a custom key comparison operator can solve this problem to make compilation with huge black- and whitelists 143 | // faster. 144 | 145 | /*std::pair::iterator, std::multimap::iterator> peqr 146 | = myEntries.equal_range(filename.str()); 147 | 148 | for (std::multimap::iterator it = peqr.first; it != peqr.second; ++it) {*/ 149 | for (std::multimap::iterator it = myEntries.begin(); it != myEntries.end(); ++it) { 150 | if (exact && (it->second.hasLine() || it->second.hasRelblock())) { continue; } 151 | if (it->second.hasFilename()) { 152 | if (exact && it->second.hasFunction()) { 153 | if (it->second.matchFileFuncName(filename, F.getName().str())) { return true; } 154 | } else { 155 | if (it->second.matchFileName(filename)) { return true; } 156 | } 157 | } else { 158 | /* Must have function */ 159 | if (it->second.matchFuncName(F.getName().str())) { 160 | return true; 161 | } 162 | } 163 | } 164 | 165 | return false; 166 | } 167 | 168 | /* Check if there are any list entries that mention this file OR function */ 169 | bool LLCovList::doCoarseMatch( StringRef filename, Function &F ) { 170 | return doMatch(filename, F, false); 171 | } 172 | 173 | /* Check if there are any list entries that mention this file OR function (and no line). 174 | * Additionally, if the file is specified, the function must match too. */ 175 | bool LLCovList::doExactMatch( StringRef filename, Function &F ) { 176 | return doMatch(filename, F, true); 177 | } 178 | 179 | /* Check if there are any list entries that match all three attributes exactly. */ 180 | bool LLCovList::doExactMatch( StringRef filename, Function &F, unsigned int line ) { 181 | /*std::pair::iterator, std::multimap::iterator> peqr 182 | = myEntries.equal_range(filename.str()); 183 | 184 | for (std::multimap::iterator it = peqr.first; it != peqr.second; ++it) {*/ 185 | for (std::multimap::iterator it = myEntries.begin(); it != myEntries.end(); ++it) { 186 | if (!it->second.hasLine() || !it->second.hasFunction() || !it->second.hasFilename() || it->second.hasRelblock()) continue; 187 | if (it->second.matchAll(filename, F.getName().str(), line)) return true; 188 | } 189 | return false; 190 | } 191 | 192 | /* Check if there are any list entries that match all four attributes exactly. */ 193 | bool LLCovList::doExactMatch( StringRef filename, Function &F, unsigned int line, unsigned int relblock ) { 194 | /*std::pair::iterator, std::multimap::iterator> peqr 195 | = myEntries.equal_range(filename.str()); 196 | 197 | for (std::multimap::iterator it = peqr.first; it != peqr.second; ++it) {*/ 198 | for (std::multimap::iterator it = myEntries.begin(); it != myEntries.end(); ++it) { 199 | if (!it->second.hasLine() || !it->second.hasFunction() || !it->second.hasFilename() || !it->second.hasRelblock()) continue; 200 | if (it->second.matchAllRelblock(filename, F.getName().str(), line, relblock)) return true; 201 | } 202 | return false; 203 | } 204 | 205 | /* Check if there are any list entries that match the function/line attributes exactly. */ 206 | bool LLCovList::doExactMatch( StringRef filename, unsigned int line ) { 207 | /* std::pair::iterator, std::multimap::iterator> peqr 208 | = myEntries.equal_range(filename.str()); 209 | 210 | for (std::multimap::iterator it = peqr.first; it != peqr.second; ++it) {*/ 211 | for (std::multimap::iterator it = myEntries.begin(); it != myEntries.end(); ++it) { 212 | if (!it->second.hasLine() || !it->second.hasFilename() || it->second.hasRelblock()) continue; 213 | if (it->second.matchFileLine(filename, line)) return true; 214 | } 215 | return false; 216 | } 217 | 218 | 219 | /* Check if there are any list entries that match the function/line/relblock attributes exactly. */ 220 | bool LLCovList::doExactMatch( StringRef filename, unsigned int line, unsigned int relblock ) { 221 | /*std::pair::iterator, std::multimap::iterator> peqr 222 | = myEntries.equal_range(filename.str()); 223 | 224 | for (std::multimap::iterator it = peqr.first; it != peqr.second; ++it) {*/ 225 | for (std::multimap::iterator it = myEntries.begin(); it != myEntries.end(); ++it) { 226 | if (!it->second.hasLine() || !it->second.hasFilename() || !it->second.hasRelblock()) continue; 227 | if (it->second.matchFileLineRelblock(filename, line, relblock)) return true; 228 | } 229 | return false; 230 | } 231 | 232 | LLCovList::LLCovList(const std::string &path) : myEntries() { 233 | /* If no file is specified, do nothing */ 234 | if (!path.size()) return; 235 | 236 | std::ifstream fileStream; 237 | fileStream.open(path.c_str()); 238 | 239 | if (!fileStream) { 240 | report_fatal_error("Unable to open specified file " + path); 241 | } 242 | 243 | std::string configLine; 244 | getline(fileStream, configLine); 245 | while (fileStream) { 246 | /* Process one line here */ 247 | std::string token; 248 | std::istringstream tokStream(configLine); 249 | 250 | std::string file; 251 | std::string func; 252 | std::string line; 253 | std::string relblock; 254 | 255 | tokStream >> token; 256 | while(tokStream) { 257 | /* Process one token here */ 258 | std::istringstream entryStream(token); 259 | 260 | std::string type; 261 | std::string val; 262 | getline(entryStream, type, ':'); 263 | getline(entryStream, val, ':'); 264 | 265 | if (type == "file") { 266 | file = val; 267 | } else if (type == "func") { 268 | func = val; 269 | } else if (type == "line") { 270 | line = val; 271 | } else if (type == "relblock") { 272 | relblock = val; 273 | } else { 274 | report_fatal_error("Invalid type \"" + type + "\" in file " + path); 275 | } 276 | 277 | if (!entryStream) { 278 | report_fatal_error("Malformed token: " + token); 279 | } 280 | 281 | tokStream >> token; 282 | } 283 | 284 | LLCovListEntry entry; 285 | 286 | if ( file.size() ) { 287 | entry.setFilename( file ); 288 | 289 | if ( func.size() ) 290 | entry.setFunction( func ); 291 | 292 | if ( line.size() ) 293 | entry.setLine( atoi( line.c_str() ) ); 294 | if ( relblock.size() ) { 295 | if ( !line.size() ) 296 | report_fatal_error( "Cannot use relblock without line in file " + path ); 297 | entry.setRelblock( atoi( relblock.c_str() ) ); 298 | } 299 | 300 | } else if ( func.size() ) { 301 | if ( line.size() ) 302 | report_fatal_error( "Cannot use line without file in file " + path ); 303 | 304 | entry.setFunction( func ); 305 | } else { 306 | report_fatal_error( "Must either specify file or function in file " + path ); 307 | } 308 | 309 | myEntries.insert(std::pair(file, entry)); 310 | 311 | getline(fileStream, configLine); 312 | } 313 | } 314 | 315 | /* End of helper classes */ 316 | 317 | /*static cl::opt ClBlackListFile("llcov-blacklist", 318 | cl::desc("File containing the list of functions/files/lines " 319 | "to ignore during instrumentation"), cl::Hidden); 320 | 321 | static cl::opt ClWhiteListFile("llcov-whitelist", 322 | cl::desc("File containing the list of functions/files/lines " 323 | "to instrument (all others are ignored)"), cl::Hidden);*/ 324 | 325 | struct LLCov: public ModulePass { 326 | public: 327 | static char ID; // Pass identification, replacement for typeid 328 | LLCov(); 329 | virtual ~LLCov(); 330 | 331 | virtual bool runOnModule( Module &M ); 332 | 333 | protected: 334 | virtual bool runOnFunction( Function &F, StringRef filename ); 335 | Constant* getInstrumentationFunction(); 336 | 337 | Module* M; 338 | LLCovList* myBlackList; 339 | LLCovList* myWhiteList; 340 | 341 | std::ofstream myLogInstStream; 342 | bool myDoLogInstrumentation; 343 | bool myDoLogInstrumentationDebug; 344 | }; 345 | 346 | char LLCov::ID = 0; 347 | //INITIALIZE_PASS(LLCov, "llcov", "LLCov: allow live coverage measurement of program code.", false, false) 348 | 349 | LLCov::LLCov() : ModulePass( ID ), M(NULL), 350 | myBlackList(new LLCovList(getenv("LLCOV_BLACKLIST") != NULL ? std::string(getenv("LLCOV_BLACKLIST")) : "" )), 351 | myWhiteList(new LLCovList(getenv("LLCOV_WHITELIST") != NULL ? std::string(getenv("LLCOV_WHITELIST")) : "" )), 352 | myDoLogInstrumentation(false), myDoLogInstrumentationDebug(false) { 353 | 354 | if (getenv("LLCOV_LOGINSTFILE") != NULL) { 355 | myDoLogInstrumentation = true; 356 | myLogInstStream.open(getenv("LLCOV_LOGINSTFILE"), std::ios::out | std::ios::app); 357 | if (getenv("LLCOV_LOGINSTDEBUG") != NULL) { 358 | myDoLogInstrumentationDebug = true; 359 | } 360 | } 361 | } 362 | 363 | LLCov::~LLCov() { 364 | if (myDoLogInstrumentation) { 365 | myLogInstStream.close(); 366 | } 367 | } 368 | 369 | bool LLCov::runOnModule( Module &M ) { 370 | this->M = &M; 371 | 372 | bool modified = false; 373 | 374 | NamedMDNode *CU_Nodes = this->M->getNamedMetadata("llvm.dbg.cu"); 375 | if (!CU_Nodes) return false; 376 | 377 | /* Iterate through all compilation units */ 378 | for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 379 | /* Iterate through all sub programs */ 380 | #ifdef LLVM_OLD_DEBUG_API 381 | DICompileUnit CU(CU_Nodes->getOperand(i)); 382 | DIArray SPs = CU.getSubprograms(); 383 | 384 | for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { 385 | DISubprogram SP(SPs.getElement(i)); 386 | if (!SP.Verify()) continue; 387 | 388 | Function *F = SP.getFunction(); 389 | if (!F) continue; 390 | 391 | modified |= runOnFunction( *F, SP.getFilename() ); 392 | } 393 | #else 394 | DICompileUnit *CU = dyn_cast(CU_Nodes->getOperand(i)); 395 | DISubprogramArray SPs = CU->getSubprograms(); 396 | 397 | for (auto *SP : SPs) { 398 | Function *F = SP->getFunction(); 399 | if (!F) continue; 400 | 401 | modified |= runOnFunction( *F, SP->getFilename() ); 402 | } 403 | #endif /* LLVM_OLD_DEBUG_API */ 404 | 405 | 406 | } 407 | 408 | return modified; 409 | } 410 | 411 | bool LLCov::runOnFunction( Function &F, StringRef filename ) { 412 | //errs() << "Hello: "; 413 | //errs().write_escaped( F.getName() ) << '\n'; 414 | 415 | bool ret = false; 416 | 417 | /* 418 | * White/BlackList logic: If the whitelist contains something, 419 | * then the set of all instrumented blocks is limited to that. 420 | * The blacklist can further restrict that set. 421 | */ 422 | 423 | bool whiteListEmptyOrExactMatch = myWhiteList->isEmpty() || myWhiteList->doExactMatch(filename, F); 424 | /* 425 | * Determine if the filename, the function, or the combination 426 | * of both is whitelisted and the blacklist does not restrict 427 | * that further. In that case, we don't need to check any more 428 | * lists during the basic block iteration which saves time. 429 | */ 430 | bool instrumentAll = whiteListEmptyOrExactMatch // Whitelist is either empty or must yield a match for function or filename 431 | && !myBlackList->doCoarseMatch(filename, F); // and blacklist must not have any coarse matches 432 | 433 | if (myBlackList->doExactMatch(filename, F)) { 434 | /* 435 | * If the filename, the function, or the combination of both 436 | * is on the blacklist, don't do anything here 437 | */ 438 | return false; 439 | } 440 | int lastBBLine = -1; 441 | unsigned int relblock = 0; 442 | 443 | /* Iterate over all basic blocks in this function */ 444 | for ( Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB ) { 445 | /* 446 | * If the whitelist is empty, we start with the assumption that we 447 | * need to instrument the block (can be changed by blacklist). 448 | * If the whitelist is not empty, then the default depends on the whole 449 | * file or function being whitelisted entirely. 450 | */ 451 | bool instrumentBlock = whiteListEmptyOrExactMatch; 452 | 453 | TerminatorInst *TI = BB->getTerminator(); 454 | 455 | IRBuilder<> Builder( TI ); 456 | 457 | bool haveLine = false; 458 | unsigned int line = 0; 459 | 460 | StringRef blockFilename; 461 | 462 | /* Iterate over the instructions in the BasicBlock to find line number */ 463 | for ( BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I ) { 464 | DebugLoc Loc = I->getDebugLoc(); 465 | 466 | #ifdef LLVM_OLD_DEBUG_API 467 | if ( Loc.isUnknown() ) 468 | #else 469 | if ( ! Loc ) 470 | #endif /* LLVM_OLD_DEBUG_API */ 471 | continue; 472 | 473 | #ifdef LLVM_OLD_DEBUG_API 474 | DILocation cDILoc(Loc.getAsMDNode(M->getContext())); 475 | DILocation oDILoc = cDILoc.getOrigLocation(); 476 | 477 | unsigned int instLine = oDILoc.getLineNumber(); 478 | StringRef instFilename = oDILoc.getFilename(); 479 | 480 | if (instFilename.str().empty()) { 481 | /* If the original location is empty, use the actual location */ 482 | instFilename = cDILoc.getFilename(); 483 | instLine = cDILoc.getLineNumber(); 484 | } 485 | #else 486 | DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); 487 | 488 | unsigned int instLine = cDILoc->getLine(); 489 | StringRef instFilename = cDILoc->getFilename(); 490 | 491 | if (instFilename.str().empty()) { 492 | /* If the original location is empty, try using the inlined location */ 493 | DILocation *oDILoc = cDILoc->getInlinedAt(); 494 | if (oDILoc) { 495 | instFilename = oDILoc->getFilename(); 496 | instLine = oDILoc->getLine(); 497 | } 498 | } 499 | #endif /* LLVM_OLD_DEBUG_API */ 500 | 501 | /* If that fails as well (no location at all), skip this block */ 502 | if (instFilename.str().empty()) continue; 503 | 504 | /* Save the line if we don't have it yet */ 505 | if (!haveLine) { 506 | line = instLine; 507 | haveLine = true; 508 | /* If we're still in the same line as the last basic block was, 509 | * increase the relative basic block count to distinguish the 510 | * the blocks in the callback later */ 511 | if (line == lastBBLine) { 512 | relblock++; 513 | } else { 514 | /* New line, reset relative basic block count to 0 */ 515 | relblock = 0; 516 | } 517 | 518 | /* Store away line of last basic block */ 519 | lastBBLine = line; 520 | 521 | // Also resolve the file now that this block originally belonged to 522 | blockFilename = instFilename; 523 | 524 | if (blockFilename != filename) { 525 | if (myBlackList->doCoarseMatch(blockFilename, F)) { 526 | // The file we are including from is blacklisted 527 | instrumentBlock = false; 528 | break; 529 | } 530 | 531 | if (!myWhiteList->isEmpty() && !myWhiteList->doExactMatch(blockFilename, F)) { 532 | // The file we are including isn't whitelisted 533 | instrumentBlock = false; 534 | break; 535 | } 536 | } 537 | 538 | /* No need to iterate further if we know already that we should instrument */ 539 | if (instrumentAll) { 540 | break; 541 | } 542 | } 543 | if (myDoLogInstrumentationDebug && myDoLogInstrumentation) 544 | myLogInstStream << "Checking " << instFilename.str() << " line: " << instLine << " blockline " << line << " relblock " << relblock << std::endl; 545 | 546 | /* Check white- and blacklists. A blacklist match immediately aborts */ 547 | if (!instrumentBlock) { 548 | instrumentBlock = instrumentBlock 549 | || myWhiteList->doExactMatch(instFilename, instLine) 550 | || myWhiteList->doExactMatch(instFilename, instLine, relblock); 551 | //if (instrumentBlock) myLogInstStream << "Decision made for " << instFilename.str() << " line: " << instLine << " blockline " << line << std::endl; 552 | } 553 | if (myBlackList->doExactMatch(instFilename, instLine) || myBlackList->doExactMatch(instFilename, instLine, relblock)) { 554 | instrumentBlock = false; 555 | break; 556 | } 557 | } 558 | 559 | if ((instrumentAll && haveLine && blockFilename == filename) || (haveLine && instrumentBlock)) { 560 | /* Create arguments for our function */ 561 | Value* funcNameVal = Builder.CreateGlobalStringPtr(F.getName()); 562 | Value* filenameVal = Builder.CreateGlobalStringPtr(blockFilename); 563 | Value* lineVal = ConstantInt::get(Type::getInt32Ty(M->getContext()), line, false); 564 | Value* relblockVal = ConstantInt::get(Type::getInt32Ty(M->getContext()), relblock, false); 565 | 566 | /* Add function call: void func(const char* function, const char* filename, uint32_t line, uint32_t relblock); */ 567 | Builder.CreateCall( getInstrumentationFunction(), { funcNameVal, filenameVal, lineVal, relblockVal }); 568 | 569 | if (myDoLogInstrumentation) { 570 | myLogInstStream << "file:" << blockFilename.str() << " " << "func:" << F.getName().str() << " " << "line:" << line << std::endl; 571 | } 572 | 573 | ret = true; 574 | } else { 575 | if (myDoLogInstrumentationDebug && myDoLogInstrumentation) { 576 | myLogInstStream << "DEBUG: " << myWhiteList->doExactMatch(filename, F) << instrumentAll << haveLine << (blockFilename == filename) << instrumentBlock << " " << blockFilename.str() << " " << filename.str() << std::endl; 577 | } 578 | } 579 | } 580 | 581 | return ret; 582 | } 583 | 584 | 585 | /* The function returned here will reside in an .so */ 586 | Constant* LLCov::getInstrumentationFunction() { 587 | Type *Args[] = { 588 | Type::getInt8PtrTy( M->getContext() ), // uint8_t* function 589 | Type::getInt8PtrTy( M->getContext() ), // uint8_t* filename 590 | Type::getInt32Ty( M->getContext() ), // uint32_t line 591 | Type::getInt32Ty( M->getContext() ) // uint32_t relblock 592 | }; 593 | FunctionType *FTy = FunctionType::get( Type::getVoidTy( M->getContext() ), Args, false ); 594 | return M->getOrInsertFunction( "llvm_llcov_block_call", FTy ); 595 | } 596 | 597 | static void registerLLCovPass(const PassManagerBuilder &, 598 | legacy::PassManagerBase &PM) { 599 | PM.add(new LLCov()); 600 | 601 | } 602 | 603 | static RegisterStandardPasses RegisterAFLPass( 604 | PassManagerBuilder::EP_OptimizerLast, registerLLCovPass); 605 | 606 | static RegisterStandardPasses RegisterAFLPass0( 607 | PassManagerBuilder::EP_EnabledOnOptLevel0, registerLLCovPass); 608 | -------------------------------------------------------------------------------- /llcov-llvm-rt.o.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static FILE* filefd = NULL; 8 | 9 | inline __attribute__((always_inline)) 10 | void writeData(const char* funcname, const char* filename, uint32_t line, uint32_t relblock) { 11 | fprintf(filefd, "file:%s line:%u relblock:%u\n", filename, line, relblock); 12 | fflush(filefd); 13 | } 14 | 15 | extern "C" void llvm_llcov_block_call(const char* funcname, const char* filename, uint32_t line, uint32_t relblock) 16 | __attribute__((visibility("default"))); 17 | 18 | extern "C" void llvm_llcov_block_call(const char* funcname, const char* filename, uint32_t line, uint32_t relblock) { 19 | if (filefd != NULL) { 20 | writeData(funcname, filename, line, relblock); 21 | } else if (getenv("LLCOV_ABORT")) { 22 | fprintf(stderr, "Assertion failure: LLCov: Block executed in file %s, line %u (function %s, line-relative block %u)\n", filename, line, funcname, relblock); 23 | abort(); 24 | } else if (getenv("LLCOV_STDERR")) { 25 | fprintf(stderr, "file:%s line:%u func:%s relblock:%u\n", filename, line, funcname, relblock); 26 | } else if (getenv("LLCOV_FILE")) { 27 | filefd = fopen(getenv("LLCOV_FILE"), "a"); 28 | if (filefd != NULL) { 29 | writeData(funcname, filename, line, relblock); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /llcov_assert.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static FILE* filefd = NULL; 10 | 11 | inline __attribute__((always_inline)) 12 | void writeData(const char* funcname, const char* filename, uint32_t line, uint32_t relblock) { 13 | static std::set< std::tuple > seen; 14 | std::tuple tup(line, relblock, std::string(filename)); 15 | if (seen.find(tup) == seen.end()) { 16 | fprintf(filefd, "file:%s line:%u relblock:%u\n", filename, line, relblock); 17 | /*fwrite(funcname, strlen(funcname)+1, 1, filefd); 18 | fwrite(filename, strlen(filename)+1, 1, filefd); 19 | fwrite(&line, sizeof(uint32_t), 1, filefd); 20 | fwrite(&relblock, sizeof(uint32_t), 1, filefd);*/ 21 | fflush(filefd); 22 | seen.insert(tup); 23 | } 24 | } 25 | 26 | extern "C" void llvm_llcov_block_call(const char* funcname, const char* filename, uint32_t line, uint32_t relblock) 27 | __attribute__((visibility("default"))); 28 | 29 | extern "C" void llvm_llcov_block_call(const char* funcname, const char* filename, uint32_t line, uint32_t relblock) { 30 | if (filefd != NULL) { 31 | writeData(funcname, filename, line, relblock); 32 | } else if (getenv("LLCOV_ABORT")) { 33 | fprintf(stderr, "Assertion failure: LLCov: Block executed in file %s, line %u (function %s, line-relative block %u)\n", filename, line, funcname, relblock); 34 | abort(); 35 | } else if (getenv("LLCOV_STDERR")) { 36 | fprintf(stderr, "file:%s line:%u func:%s relblock:%u\n", filename, line, funcname, relblock); 37 | } else if (getenv("LLCOV_FILE")) { 38 | filefd = fopen(getenv("LLCOV_FILE"), "a"); 39 | if (filefd != NULL) { 40 | writeData(funcname, filename, line, relblock); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /llcov_network.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static int sockfd = 0; 6 | 7 | extern "C" void llvm_llcov_block_call(const char* funcname, const char* filename, uint32_t line, uint32_t relblock) 8 | __attribute__((visibility("default"))); 9 | 10 | extern "C" void llvm_llcov_block_call(const char* funcname, const char* filename, uint32_t line, uint32_t relblock) { 11 | if (getenv("LLCOV_ABORT")) { 12 | fprintf(stderr, "Assertion failure: LLCov: Block executed in file %s, line %u (function %s, line-relative block %u)\n", filename, line, funcname, relblock); 13 | abort(); 14 | } else if (sockfd > 0) { 15 | 16 | } else if (getenv("LLCOV_STDERR")) { 17 | fprintf(stderr, "file:%s line:%u function:%s relblock:%u\n", filename, line, funcname, relblock); 18 | } else if (sockfd == 0) { 19 | char* llcov_host = getenv("LLCOV_HOST"); 20 | if (llcov_host) { 21 | struct sockaddr_in pin; 22 | struct hostent *hp; 23 | 24 | if ((hp = gethostbyname(llcov_host)) == 0) { 25 | perror("gethostbyname"); 26 | sockfd = -1; 27 | return; 28 | } 29 | 30 | memset(&pin, 0, sizeof(pin)); 31 | pin.sin_family = AF_INET; 32 | pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; 33 | pin.sin_port = htons(7777); 34 | 35 | if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 36 | perror("socket"); 37 | sockfd = -1; 38 | return; 39 | } 40 | 41 | if (connect(sockfd,(struct sockaddr *) &pin, sizeof(pin)) == -1) { 42 | perror("connect"); 43 | sockfd = -1; 44 | return; 45 | } 46 | } else { 47 | sockfd = -1; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file was derived from the AFLFuzz project. 3 | 4 | Modifications by Christian Holler 5 | 6 | Original code written by Michal Zalewski 7 | 8 | Copyright 2013, 2014, 2015 Google Inc. All rights reserved. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at: 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | */ 17 | 18 | #ifndef _HAVE_TYPES_H 19 | #define _HAVE_TYPES_H 20 | 21 | #include 22 | #include 23 | 24 | typedef uint8_t u8; 25 | typedef uint16_t u16; 26 | typedef uint32_t u32; 27 | 28 | /* 29 | 30 | Ugh. There is an unintended compiler / glibc #include glitch caused by 31 | combining the u64 type an %llu in format strings, necessitating a workaround. 32 | 33 | In essence, the compiler is always looking for 'unsigned long long' for %llu. 34 | On 32-bit systems, the u64 type (aliased to uint64_t) is expanded to 35 | 'unsigned long long' in , so everything checks out. 36 | 37 | But on 64-bit systems, it is #ifdef'ed in the same file as 'unsigned long'. 38 | Now, it only happens in circumstances where the type happens to have the 39 | expected bit width, *but* the compiler does not know that... and complains 40 | about 'unsigned long' being unsafe to pass to %llu. 41 | 42 | */ 43 | 44 | #ifdef __x86_64__ 45 | typedef unsigned long long u64; 46 | #else 47 | typedef uint64_t u64; 48 | #endif /* ^sizeof(...) */ 49 | 50 | typedef int8_t s8; 51 | typedef int16_t s16; 52 | typedef int32_t s32; 53 | typedef int64_t s64; 54 | 55 | #ifndef MIN 56 | # define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a)) 57 | # define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b)) 58 | #endif /* !MIN */ 59 | 60 | #define SWAP16(_x) ({ \ 61 | u16 _ret = (_x); \ 62 | (u16)((_ret << 8) | (_ret >> 8)); \ 63 | }) 64 | 65 | #define SWAP32(_x) ({ \ 66 | u32 _ret = (_x); \ 67 | (u32)((_ret << 24) | (_ret >> 24) | \ 68 | ((_ret << 8) & 0x00FF0000) | \ 69 | ((_ret >> 8) & 0x0000FF00)); \ 70 | }) 71 | 72 | #define R(x) (random() % (x)) 73 | 74 | #define STRINGIFY_INTERNAL(x) #x 75 | #define STRINGIFY(x) STRINGIFY_INTERNAL(x) 76 | 77 | #define MEM_BARRIER() \ 78 | asm volatile("" ::: "memory") 79 | 80 | #endif /* ! _HAVE_TYPES_H */ 81 | --------------------------------------------------------------------------------