1 /*
2 american fuzzy lop++ - compiler instrumentation wrapper
3 -------------------------------------------------------
4
5 Written by Michal Zalewski, Laszlo Szekeres and Marc Heuse
6
7 Copyright 2015, 2016 Google Inc. All rights reserved.
8 Copyright 2019-2022 AFLplusplus Project. 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 https://www.apache.org/licenses/LICENSE-2.0
15
16 */
17
18 #define AFL_MAIN
19
20 #include "common.h"
21 #include "config.h"
22 #include "types.h"
23 #include "debug.h"
24 #include "alloc-inl.h"
25 #include "llvm-alternative-coverage.h"
26
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <limits.h>
33 #include <assert.h>
34
35 #if (LLVM_MAJOR - 0 == 0)
36 #undef LLVM_MAJOR
37 #endif
38 #if !defined(LLVM_MAJOR)
39 #define LLVM_MAJOR 0
40 #endif
41 #if (LLVM_MINOR - 0 == 0)
42 #undef LLVM_MINOR
43 #endif
44 #if !defined(LLVM_MINOR)
45 #define LLVM_MINOR 0
46 #endif
47
48 static u8 * obj_path; /* Path to runtime libraries */
49 static u8 **cc_params; /* Parameters passed to the real CC */
50 static u32 cc_par_cnt = 1; /* Param count, including argv0 */
51 static u8 clang_mode; /* Invoked as afl-clang*? */
52 static u8 llvm_fullpath[PATH_MAX];
53 static u8 instrument_mode, instrument_opt_mode, ngram_size, ctx_k, lto_mode;
54 static u8 compiler_mode, plusplus_mode, have_instr_env = 0;
55 static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto, have_instr_list = 0;
56 static u8 * lto_flag = AFL_CLANG_FLTO, *argvnull;
57 static u8 debug;
58 static u8 cwd[4096];
59 static u8 cmplog_mode;
60 u8 use_stdin; /* dummy */
61 static int passthrough;
62 // static u8 *march_opt = CFLAGS_OPT;
63
64 enum {
65
66 INSTRUMENT_DEFAULT = 0,
67 INSTRUMENT_CLASSIC = 1,
68 INSTRUMENT_AFL = 1,
69 INSTRUMENT_PCGUARD = 2,
70 INSTRUMENT_CFG = 3,
71 INSTRUMENT_LTO = 4,
72 INSTRUMENT_LLVMNATIVE = 5,
73 INSTRUMENT_GCC = 6,
74 INSTRUMENT_CLANG = 7,
75 INSTRUMENT_OPT_CTX = 8,
76 INSTRUMENT_OPT_NGRAM = 16,
77 INSTRUMENT_OPT_CALLER = 32,
78 INSTRUMENT_OPT_CTX_K = 64,
79
80 };
81
82 char instrument_mode_string[18][18] = {
83
84 "DEFAULT",
85 "CLASSIC",
86 "PCGUARD",
87 "CFG",
88 "LTO",
89 "PCGUARD-NATIVE",
90 "GCC",
91 "CLANG",
92 "CTX",
93 "CALLER",
94 "",
95 "",
96 "",
97 "",
98 "",
99 "",
100 "NGRAM",
101 ""
102
103 };
104
105 enum {
106
107 UNSET = 0,
108 LTO = 1,
109 LLVM = 2,
110 GCC_PLUGIN = 3,
111 GCC = 4,
112 CLANG = 5
113
114 };
115
116 char compiler_mode_string[7][12] = {
117
118 "AUTOSELECT", "LLVM-LTO", "LLVM", "GCC_PLUGIN",
119 "GCC", "CLANG", ""
120
121 };
122
getthecwd()123 u8 *getthecwd() {
124
125 if (getcwd(cwd, sizeof(cwd)) == NULL) {
126
127 static u8 fail[] = "";
128 return fail;
129
130 }
131
132 return cwd;
133
134 }
135
136 /* Try to find a specific runtime we need, returns NULL on fail. */
137
138 /*
139 in find_object() we look here:
140
141 1. if obj_path is already set we look there first
142 2. then we check the $AFL_PATH environment variable location if set
143 3. next we check argv[0] if it has path information and use it
144 a) we also check ../lib/afl
145 4. if 3. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and
146 FreeBSD with procfs)
147 a) and check here in ../lib/afl too
148 5. we look into the AFL_PATH define (usually /usr/local/lib/afl)
149 6. we finally try the current directory
150
151 if all these attempts fail - we return NULL and the caller has to decide
152 what to do.
153 */
154
find_object(u8 * obj,u8 * argv0)155 static u8 *find_object(u8 *obj, u8 *argv0) {
156
157 u8 *afl_path = getenv("AFL_PATH");
158 u8 *slash = NULL, *tmp;
159
160 if (afl_path) {
161
162 tmp = alloc_printf("%s/%s", afl_path, obj);
163
164 if (debug) DEBUGF("Trying %s\n", tmp);
165
166 if (!access(tmp, R_OK)) {
167
168 obj_path = afl_path;
169 return tmp;
170
171 }
172
173 ck_free(tmp);
174
175 }
176
177 if (argv0) {
178
179 slash = strrchr(argv0, '/');
180
181 if (slash) {
182
183 u8 *dir = ck_strdup(argv0);
184
185 slash = strrchr(dir, '/');
186 *slash = 0;
187
188 tmp = alloc_printf("%s/%s", dir, obj);
189
190 if (debug) DEBUGF("Trying %s\n", tmp);
191
192 if (!access(tmp, R_OK)) {
193
194 obj_path = dir;
195 return tmp;
196
197 }
198
199 ck_free(tmp);
200 tmp = alloc_printf("%s/../lib/afl/%s", dir, obj);
201
202 if (debug) DEBUGF("Trying %s\n", tmp);
203
204 if (!access(tmp, R_OK)) {
205
206 u8 *dir2 = alloc_printf("%s/../lib/afl", dir);
207 obj_path = dir2;
208 ck_free(dir);
209 return tmp;
210
211 }
212
213 ck_free(tmp);
214 ck_free(dir);
215
216 }
217
218 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) || \
219 defined(__ANDROID__) || defined(__NetBSD__)
220 #define HAS_PROC_FS 1
221 #endif
222 #ifdef HAS_PROC_FS
223 else {
224
225 char *procname = NULL;
226 #if defined(__FreeBSD__) || defined(__DragonFly__)
227 procname = "/proc/curproc/file";
228 #elif defined(__linux__) || defined(__ANDROID__)
229 procname = "/proc/self/exe";
230 #elif defined(__NetBSD__)
231 procname = "/proc/curproc/exe";
232 #endif
233 if (procname) {
234
235 char exepath[PATH_MAX];
236 ssize_t exepath_len = readlink(procname, exepath, sizeof(exepath));
237 if (exepath_len > 0 && exepath_len < PATH_MAX) {
238
239 exepath[exepath_len] = 0;
240 slash = strrchr(exepath, '/');
241
242 if (slash) {
243
244 *slash = 0;
245 tmp = alloc_printf("%s/%s", exepath, obj);
246
247 if (!access(tmp, R_OK)) {
248
249 u8 *dir = alloc_printf("%s", exepath);
250 obj_path = dir;
251 return tmp;
252
253 }
254
255 ck_free(tmp);
256 tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj);
257
258 if (debug) DEBUGF("Trying %s\n", tmp);
259
260 if (!access(tmp, R_OK)) {
261
262 u8 *dir = alloc_printf("%s/../lib/afl/", exepath);
263 obj_path = dir;
264 return tmp;
265
266 }
267
268 }
269
270 }
271
272 }
273
274 }
275
276 #endif
277 #undef HAS_PROC_FS
278
279 }
280
281 tmp = alloc_printf("%s/%s", AFL_PATH, obj);
282
283 if (debug) DEBUGF("Trying %s\n", tmp);
284
285 if (!access(tmp, R_OK)) {
286
287 obj_path = AFL_PATH;
288 return tmp;
289
290 }
291
292 ck_free(tmp);
293
294 tmp = alloc_printf("./%s", obj);
295
296 if (debug) DEBUGF("Trying %s\n", tmp);
297
298 if (!access(tmp, R_OK)) {
299
300 obj_path = ".";
301 return tmp;
302
303 }
304
305 ck_free(tmp);
306
307 if (debug) DEBUGF("Trying ... giving up\n");
308
309 return NULL;
310
311 }
312
313 /* Copy argv to cc_params, making the necessary edits. */
314
edit_params(u32 argc,char ** argv,char ** envp)315 static void edit_params(u32 argc, char **argv, char **envp) {
316
317 u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0,
318 preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0,
319 have_c = 0, partial_linking = 0;
320
321 cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
322
323 if (lto_mode) {
324
325 if (lto_flag[0] != '-')
326 FATAL(
327 "Using afl-clang-lto is not possible because Makefile magic did not "
328 "identify the correct -flto flag");
329 else
330 compiler_mode = LTO;
331
332 }
333
334 if (plusplus_mode) {
335
336 u8 *alt_cxx = getenv("AFL_CXX");
337
338 if (!alt_cxx) {
339
340 if (compiler_mode >= GCC_PLUGIN) {
341
342 if (compiler_mode == GCC) {
343
344 alt_cxx = clang_mode ? "clang++" : "g++";
345
346 } else if (compiler_mode == CLANG) {
347
348 alt_cxx = "clang++";
349
350 } else {
351
352 alt_cxx = "g++";
353
354 }
355
356 } else {
357
358 if (USE_BINDIR)
359 snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++",
360 LLVM_BINDIR);
361 else
362 snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN);
363 alt_cxx = llvm_fullpath;
364
365 }
366
367 }
368
369 cc_params[0] = alt_cxx;
370
371 } else {
372
373 u8 *alt_cc = getenv("AFL_CC");
374
375 if (!alt_cc) {
376
377 if (compiler_mode >= GCC_PLUGIN) {
378
379 if (compiler_mode == GCC) {
380
381 alt_cc = clang_mode ? "clang" : "gcc";
382
383 } else if (compiler_mode == CLANG) {
384
385 alt_cc = "clang";
386
387 } else {
388
389 alt_cc = "gcc";
390
391 }
392
393 } else {
394
395 if (USE_BINDIR)
396 snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang",
397 LLVM_BINDIR);
398 else
399 snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN);
400 alt_cc = llvm_fullpath;
401
402 }
403
404 }
405
406 cc_params[0] = alt_cc;
407
408 }
409
410 if (compiler_mode == GCC || compiler_mode == CLANG) {
411
412 cc_params[cc_par_cnt++] = "-B";
413 cc_params[cc_par_cnt++] = obj_path;
414
415 if (clang_mode || compiler_mode == CLANG) {
416
417 cc_params[cc_par_cnt++] = "-no-integrated-as";
418
419 }
420
421 }
422
423 if (compiler_mode == GCC_PLUGIN) {
424
425 char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
426 cc_params[cc_par_cnt++] = fplugin_arg;
427 cc_params[cc_par_cnt++] = "-fno-if-conversion";
428 cc_params[cc_par_cnt++] = "-fno-if-conversion2";
429
430 }
431
432 if (compiler_mode == LLVM || compiler_mode == LTO) {
433
434 cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
435
436 if (lto_mode && have_instr_env) {
437
438 #if LLVM_MAJOR >= 11 /* use new pass manager */
439 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
440 cc_params[cc_par_cnt++] = alloc_printf(
441 "-fpass-plugin=%s/afl-llvm-lto-instrumentlist.so", obj_path);
442 #else
443 cc_params[cc_par_cnt++] = "-Xclang";
444 cc_params[cc_par_cnt++] = "-load";
445 cc_params[cc_par_cnt++] = "-Xclang";
446 cc_params[cc_par_cnt++] =
447 alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
448 #endif
449
450 }
451
452 if (getenv("AFL_LLVM_DICT2FILE")) {
453
454 #if LLVM_MAJOR >= 11 /* use new pass manager */
455 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
456 cc_params[cc_par_cnt++] =
457 alloc_printf("-fpass-plugin=%s/afl-llvm-dict2file.so", obj_path);
458 #else
459 cc_params[cc_par_cnt++] = "-Xclang";
460 cc_params[cc_par_cnt++] = "-load";
461 cc_params[cc_par_cnt++] = "-Xclang";
462 cc_params[cc_par_cnt++] =
463 alloc_printf("%s/afl-llvm-dict2file.so", obj_path);
464 #endif
465
466 }
467
468 // laf
469 if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
470
471 #if LLVM_MAJOR >= 11 /* use new pass manager */
472 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
473 cc_params[cc_par_cnt++] =
474 alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path);
475 #else
476 cc_params[cc_par_cnt++] = "-Xclang";
477 cc_params[cc_par_cnt++] = "-load";
478 cc_params[cc_par_cnt++] = "-Xclang";
479 cc_params[cc_par_cnt++] =
480 alloc_printf("%s/split-switches-pass.so", obj_path);
481 #endif
482
483 }
484
485 if (getenv("LAF_TRANSFORM_COMPARES") ||
486 getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
487
488 #if LLVM_MAJOR >= 11 /* use new pass manager */
489 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
490 cc_params[cc_par_cnt++] =
491 alloc_printf("-fpass-plugin=%s/compare-transform-pass.so", obj_path);
492 #else
493 cc_params[cc_par_cnt++] = "-Xclang";
494 cc_params[cc_par_cnt++] = "-load";
495 cc_params[cc_par_cnt++] = "-Xclang";
496 cc_params[cc_par_cnt++] =
497 alloc_printf("%s/compare-transform-pass.so", obj_path);
498 #endif
499
500 }
501
502 if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
503 getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
504
505 #if LLVM_MAJOR >= 11 /* use new pass manager */
506 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
507 cc_params[cc_par_cnt++] =
508 alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path);
509 #else
510 cc_params[cc_par_cnt++] = "-Xclang";
511 cc_params[cc_par_cnt++] = "-load";
512 cc_params[cc_par_cnt++] = "-Xclang";
513 cc_params[cc_par_cnt++] =
514 alloc_printf("%s/split-compares-pass.so", obj_path);
515 #endif
516
517 }
518
519 // /laf
520
521 unsetenv("AFL_LD");
522 unsetenv("AFL_LD_CALLER");
523
524 if (cmplog_mode) {
525
526 cc_params[cc_par_cnt++] = "-fno-inline";
527
528 #if LLVM_MAJOR >= 11 /* use new pass manager */
529 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
530 cc_params[cc_par_cnt++] =
531 alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path);
532 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
533 cc_params[cc_par_cnt++] =
534 alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path);
535 #else
536 cc_params[cc_par_cnt++] = "-Xclang";
537 cc_params[cc_par_cnt++] = "-load";
538 cc_params[cc_par_cnt++] = "-Xclang";
539 cc_params[cc_par_cnt++] =
540 alloc_printf("%s/cmplog-switches-pass.so", obj_path);
541
542 // reuse split switches from laf
543 cc_params[cc_par_cnt++] = "-Xclang";
544 cc_params[cc_par_cnt++] = "-load";
545 cc_params[cc_par_cnt++] = "-Xclang";
546 cc_params[cc_par_cnt++] =
547 alloc_printf("%s/split-switches-pass.so", obj_path);
548 #endif
549
550 }
551
552 //#if LLVM_MAJOR >= 13
553 // // Use the old pass manager in LLVM 14 which the afl++ passes still
554 // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
555 //#endif
556
557 if (lto_mode && !have_c) {
558
559 u8 *ld_path = NULL;
560 if (getenv("AFL_REAL_LD")) {
561
562 ld_path = strdup(getenv("AFL_REAL_LD"));
563
564 } else {
565
566 ld_path = strdup(AFL_REAL_LD);
567
568 }
569
570 if (!ld_path || !*ld_path) {
571
572 if (ld_path) {
573
574 // Freeing empty string
575 free(ld_path);
576
577 }
578
579 ld_path = strdup("ld.lld");
580
581 }
582
583 if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); }
584 #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12
585 cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path);
586 #else
587 cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_path);
588 #endif
589 free(ld_path);
590
591 #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13
592 cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager";
593 #else
594 cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager";
595 #endif
596
597 cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
598 cc_params[cc_par_cnt++] =
599 alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
600 cc_params[cc_par_cnt++] = lto_flag;
601
602 } else {
603
604 if (instrument_mode == INSTRUMENT_PCGUARD) {
605
606 #if LLVM_MAJOR >= 11
607 #if defined __ANDROID__ || ANDROID
608 cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
609 instrument_mode = INSTRUMENT_LLVMNATIVE;
610 #else
611 if (have_instr_list) {
612
613 if (!be_quiet)
614 SAYF(
615 "Using unoptimized trace-pc-guard, due usage of "
616 "-fsanitize-coverage-allow/denylist, you can use "
617 "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n");
618 cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
619 instrument_mode = INSTRUMENT_LLVMNATIVE;
620
621 } else {
622
623 #if LLVM_MAJOR >= 11 /* use new pass manager */
624 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
625 cc_params[cc_par_cnt++] = alloc_printf(
626 "-fpass-plugin=%s/SanitizerCoveragePCGUARD.so", obj_path);
627 #else
628 cc_params[cc_par_cnt++] = "-Xclang";
629 cc_params[cc_par_cnt++] = "-load";
630 cc_params[cc_par_cnt++] = "-Xclang";
631 cc_params[cc_par_cnt++] =
632 alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
633 #endif
634
635 }
636
637 #endif
638 #else
639 #if LLVM_MAJOR >= 4
640 if (!be_quiet)
641 SAYF(
642 "Using unoptimized trace-pc-guard, upgrade to llvm 10.0.1+ for "
643 "enhanced version.\n");
644 cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
645 instrument_mode = INSTRUMENT_LLVMNATIVE;
646 #else
647 FATAL("pcguard instrumentation requires llvm 4.0.1+");
648 #endif
649 #endif
650
651 } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) {
652
653 #if LLVM_MAJOR >= 4
654 cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
655 #else
656 FATAL("pcguard instrumentation requires llvm 4.0.1+");
657 #endif
658
659 } else {
660
661 #if LLVM_MAJOR >= 11 /* use new pass manager */
662 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
663 cc_params[cc_par_cnt++] =
664 alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path);
665 #else
666
667 cc_params[cc_par_cnt++] = "-Xclang";
668 cc_params[cc_par_cnt++] = "-load";
669 cc_params[cc_par_cnt++] = "-Xclang";
670 cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
671 #endif
672
673 }
674
675 }
676
677 if (cmplog_mode) {
678
679 #if LLVM_MAJOR >= 11
680 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
681 cc_params[cc_par_cnt++] = alloc_printf(
682 "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path);
683 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
684 cc_params[cc_par_cnt++] =
685 alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path);
686 #else
687 cc_params[cc_par_cnt++] = "-Xclang";
688 cc_params[cc_par_cnt++] = "-load";
689 cc_params[cc_par_cnt++] = "-Xclang";
690 cc_params[cc_par_cnt++] =
691 alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
692
693 cc_params[cc_par_cnt++] = "-Xclang";
694 cc_params[cc_par_cnt++] = "-load";
695 cc_params[cc_par_cnt++] = "-Xclang";
696 cc_params[cc_par_cnt++] =
697 alloc_printf("%s/cmplog-routines-pass.so", obj_path);
698 #endif
699
700 }
701
702 // cc_params[cc_par_cnt++] = "-Qunused-arguments";
703
704 if (lto_mode && argc > 1) {
705
706 u32 idx;
707 for (idx = 1; idx < argc; idx++) {
708
709 if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1;
710
711 }
712
713 if (!have_pic) cc_params[cc_par_cnt++] = "-fPIC";
714
715 }
716
717 }
718
719 /* Detect stray -v calls from ./configure scripts. */
720
721 u8 skip_next = 0, non_dash = 0;
722 while (--argc) {
723
724 u8 *cur = *(++argv);
725
726 if (skip_next) {
727
728 skip_next = 0;
729 continue;
730
731 }
732
733 if (cur[0] != '-') { non_dash = 1; }
734 if (!strncmp(cur, "--afl", 5)) continue;
735 if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
736 if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
737 if (!strncmp(cur, "-fno-unroll", 11)) continue;
738 if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
739 if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
740 !strcmp(cur, "--no-undefined")) {
741
742 continue;
743
744 }
745
746 if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
747
748 u8 *param = *(argv + 1);
749 if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
750
751 skip_next = 1;
752 continue;
753
754 }
755
756 }
757
758 if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
759 !strncmp(cur, "-stdlib=", 8)) {
760
761 if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
762 continue;
763
764 }
765
766 if ((!strncmp(cur, "-fsanitize=fuzzer-", strlen("-fsanitize=fuzzer-")) ||
767 !strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) &&
768 (strncmp(cur, "sanitize-coverage-allow",
769 strlen("sanitize-coverage-allow")) &&
770 strncmp(cur, "sanitize-coverage-deny",
771 strlen("sanitize-coverage-deny")) &&
772 instrument_mode != INSTRUMENT_LLVMNATIVE)) {
773
774 if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
775 continue;
776
777 }
778
779 if (!strcmp(cur, "-fsanitize=fuzzer")) {
780
781 u8 *afllib = find_object("libAFLDriver.a", argv[0]);
782
783 if (!be_quiet) {
784
785 OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
786
787 }
788
789 if (!afllib) {
790
791 if (!be_quiet) {
792
793 WARNF(
794 "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
795 "the flags - this will fail!");
796
797 }
798
799 } else {
800
801 cc_params[cc_par_cnt++] = afllib;
802
803 #ifdef __APPLE__
804 cc_params[cc_par_cnt++] = "-undefined";
805 cc_params[cc_par_cnt++] = "dynamic_lookup";
806 #endif
807
808 }
809
810 continue;
811
812 }
813
814 if (!strcmp(cur, "-m32")) bit_mode = 32;
815 if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
816 if (!strcmp(cur, "-m64")) bit_mode = 64;
817
818 if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list="))
819 have_instr_list = 1;
820
821 if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
822 asan_set = 1;
823
824 if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
825
826 if (!strcmp(cur, "-x")) x_set = 1;
827 if (!strcmp(cur, "-E")) preprocessor_only = 1;
828 if (!strcmp(cur, "-shared")) shared_linking = 1;
829 if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
830 if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1;
831 if (!strcmp(cur, "-Wl,-r")) partial_linking = 1;
832 if (!strcmp(cur, "-Wl,-i")) partial_linking = 1;
833 if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1;
834 if (!strcmp(cur, "-r")) partial_linking = 1;
835 if (!strcmp(cur, "--relocatable")) partial_linking = 1;
836 if (!strcmp(cur, "-c")) have_c = 1;
837
838 if (!strncmp(cur, "-O", 2)) have_o = 1;
839 if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
840
841 cc_params[cc_par_cnt++] = cur;
842
843 }
844
845 // in case LLVM is installed not via a package manager or "make install"
846 // e.g. compiled download or compiled from github then its ./lib directory
847 // might not be in the search path. Add it if so.
848 u8 *libdir = strdup(LLVM_LIBDIR);
849 if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) &&
850 strncmp(libdir, "/lib", 4)) {
851
852 cc_params[cc_par_cnt++] = "-rpath";
853 cc_params[cc_par_cnt++] = libdir;
854
855 } else {
856
857 free(libdir);
858
859 }
860
861 if (getenv("AFL_HARDEN")) {
862
863 cc_params[cc_par_cnt++] = "-fstack-protector-all";
864
865 if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
866
867 }
868
869 if (!asan_set) {
870
871 if (getenv("AFL_USE_ASAN")) {
872
873 if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive");
874
875 if (getenv("AFL_HARDEN"))
876 FATAL("ASAN and AFL_HARDEN are mutually exclusive");
877
878 cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
879 cc_params[cc_par_cnt++] = "-fsanitize=address";
880
881 } else if (getenv("AFL_USE_MSAN")) {
882
883 if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive");
884
885 if (getenv("AFL_HARDEN"))
886 FATAL("MSAN and AFL_HARDEN are mutually exclusive");
887
888 cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
889 cc_params[cc_par_cnt++] = "-fsanitize=memory";
890
891 }
892
893 }
894
895 if (getenv("AFL_USE_UBSAN")) {
896
897 cc_params[cc_par_cnt++] = "-fsanitize=undefined";
898 cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error";
899 cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all";
900 cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer";
901
902 }
903
904 if (getenv("AFL_USE_TSAN")) {
905
906 cc_params[cc_par_cnt++] = "-fsanitize=thread";
907 cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer";
908
909 }
910
911 if (getenv("AFL_USE_LSAN")) {
912
913 cc_params[cc_par_cnt++] = "-fsanitize=leak";
914 cc_params[cc_par_cnt++] = "-includesanitizer/lsan_interface.h";
915 cc_params[cc_par_cnt++] =
916 "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) "
917 "_exit(23); }";
918 cc_params[cc_par_cnt++] = "-D__AFL_LSAN_OFF()=__lsan_disable();";
919 cc_params[cc_par_cnt++] = "-D__AFL_LSAN_ON()=__lsan_enable();";
920
921 }
922
923 if (getenv("AFL_USE_CFISAN")) {
924
925 if (!lto_mode) {
926
927 uint32_t i = 0, found = 0;
928 while (envp[i] != NULL && !found)
929 if (strncmp("-flto", envp[i++], 5) == 0) found = 1;
930 if (!found) cc_params[cc_par_cnt++] = "-flto";
931
932 }
933
934 cc_params[cc_par_cnt++] = "-fsanitize=cfi";
935 cc_params[cc_par_cnt++] = "-fvisibility=hidden";
936
937 }
938
939 if (!getenv("AFL_DONT_OPTIMIZE")) {
940
941 cc_params[cc_par_cnt++] = "-g";
942 if (!have_o) cc_params[cc_par_cnt++] = "-O3";
943 if (!have_unroll) cc_params[cc_par_cnt++] = "-funroll-loops";
944 // if (strlen(march_opt) > 1 && march_opt[0] == '-')
945 // cc_params[cc_par_cnt++] = march_opt;
946
947 }
948
949 if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
950 getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") ||
951 lto_mode) {
952
953 cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
954 cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
955 cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
956 cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
957 cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
958 cc_params[cc_par_cnt++] = "-fno-builtin-bcmp";
959 cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
960 cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
961
962 }
963
964 #if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__
965 if (!have_c) cc_params[cc_par_cnt++] = "-lrt";
966 #endif
967
968 cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
969 cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
970 cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
971
972 /* When the user tries to use persistent or deferred forkserver modes by
973 appending a single line to the program, we want to reliably inject a
974 signature into the binary (to be picked up by afl-fuzz) and we want
975 to call a function from the runtime .o file. This is unnecessarily
976 painful for three reasons:
977
978 1) We need to convince the compiler not to optimize out the signature.
979 This is done with __attribute__((used)).
980
981 2) We need to convince the linker, when called with -Wl,--gc-sections,
982 not to do the same. This is done by forcing an assignment to a
983 'volatile' pointer.
984
985 3) We need to declare __afl_persistent_loop() in the global namespace,
986 but doing this within a method in a class is hard - :: and extern "C"
987 are forbidden and __attribute__((alias(...))) doesn't work. Hence the
988 __asm__ aliasing trick.
989
990 */
991
992 cc_params[cc_par_cnt++] =
993 "-D__AFL_FUZZ_INIT()="
994 "int __afl_sharedmem_fuzzing = 1;"
995 "extern unsigned int *__afl_fuzz_len;"
996 "extern unsigned char *__afl_fuzz_ptr;"
997 "unsigned char __afl_fuzz_alt[1048576];"
998 "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
999
1000 if (plusplus_mode) {
1001
1002 cc_params[cc_par_cnt++] =
1003 "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
1004 "extern \"C\" void __afl_coverage_discard();"
1005 "extern \"C\" void __afl_coverage_skip();"
1006 "extern \"C\" void __afl_coverage_on();"
1007 "extern \"C\" void __afl_coverage_off();";
1008
1009 } else {
1010
1011 cc_params[cc_par_cnt++] =
1012 "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
1013 "void __afl_coverage_discard();"
1014 "void __afl_coverage_skip();"
1015 "void __afl_coverage_on();"
1016 "void __afl_coverage_off();";
1017
1018 }
1019
1020 cc_params[cc_par_cnt++] =
1021 "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = "
1022 "1;";
1023 cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_ON()=__afl_coverage_on()";
1024 cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()";
1025 cc_params[cc_par_cnt++] =
1026 "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()";
1027 cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()";
1028 cc_params[cc_par_cnt++] =
1029 "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : "
1030 "__afl_fuzz_alt_ptr)";
1031 cc_params[cc_par_cnt++] =
1032 "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : "
1033 "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff "
1034 "? 0 : *__afl_fuzz_len)";
1035
1036 cc_params[cc_par_cnt++] =
1037 "-D__AFL_LOOP(_A)="
1038 "({ static volatile char *_B __attribute__((used,unused)); "
1039 " _B = (char*)\"" PERSIST_SIG
1040 "\"; "
1041 #ifdef __APPLE__
1042 "__attribute__((visibility(\"default\"))) "
1043 "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
1044 #else
1045 "__attribute__((visibility(\"default\"))) "
1046 "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
1047 #endif /* ^__APPLE__ */
1048 "_L(_A); })";
1049
1050 cc_params[cc_par_cnt++] =
1051 "-D__AFL_INIT()="
1052 "do { static volatile char *_A __attribute__((used,unused)); "
1053 " _A = (char*)\"" DEFER_SIG
1054 "\"; "
1055 #ifdef __APPLE__
1056 "__attribute__((visibility(\"default\"))) "
1057 "void _I(void) __asm__(\"___afl_manual_init\"); "
1058 #else
1059 "__attribute__((visibility(\"default\"))) "
1060 "void _I(void) __asm__(\"__afl_manual_init\"); "
1061 #endif /* ^__APPLE__ */
1062 "_I(); } while (0)";
1063
1064 if (x_set) {
1065
1066 cc_params[cc_par_cnt++] = "-x";
1067 cc_params[cc_par_cnt++] = "none";
1068
1069 }
1070
1071 // prevent unnecessary build errors
1072 if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) {
1073
1074 cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
1075
1076 }
1077
1078 if (preprocessor_only || have_c || !non_dash) {
1079
1080 /* In the preprocessor_only case (-E), we are not actually compiling at
1081 all but requesting the compiler to output preprocessed sources only.
1082 We must not add the runtime in this case because the compiler will
1083 simply output its binary content back on stdout, breaking any build
1084 systems that rely on a separate source preprocessing step. */
1085 cc_params[cc_par_cnt] = NULL;
1086 return;
1087
1088 }
1089
1090 #ifndef __ANDROID__
1091
1092 if (compiler_mode != GCC && compiler_mode != CLANG) {
1093
1094 switch (bit_mode) {
1095
1096 case 0:
1097 if (!shared_linking && !partial_linking)
1098 cc_params[cc_par_cnt++] =
1099 alloc_printf("%s/afl-compiler-rt.o", obj_path);
1100 if (lto_mode)
1101 cc_params[cc_par_cnt++] =
1102 alloc_printf("%s/afl-llvm-rt-lto.o", obj_path);
1103 break;
1104
1105 case 32:
1106 if (!shared_linking && !partial_linking) {
1107
1108 cc_params[cc_par_cnt++] =
1109 alloc_printf("%s/afl-compiler-rt-32.o", obj_path);
1110 if (access(cc_params[cc_par_cnt - 1], R_OK))
1111 FATAL("-m32 is not supported by your compiler");
1112
1113 }
1114
1115 if (lto_mode) {
1116
1117 cc_params[cc_par_cnt++] =
1118 alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path);
1119 if (access(cc_params[cc_par_cnt - 1], R_OK))
1120 FATAL("-m32 is not supported by your compiler");
1121
1122 }
1123
1124 break;
1125
1126 case 64:
1127 if (!shared_linking && !partial_linking) {
1128
1129 cc_params[cc_par_cnt++] =
1130 alloc_printf("%s/afl-compiler-rt-64.o", obj_path);
1131 if (access(cc_params[cc_par_cnt - 1], R_OK))
1132 FATAL("-m64 is not supported by your compiler");
1133
1134 }
1135
1136 if (lto_mode) {
1137
1138 cc_params[cc_par_cnt++] =
1139 alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path);
1140 if (access(cc_params[cc_par_cnt - 1], R_OK))
1141 FATAL("-m64 is not supported by your compiler");
1142
1143 }
1144
1145 break;
1146
1147 }
1148
1149 #if !defined(__APPLE__) && !defined(__sun)
1150 if (!shared_linking && !partial_linking)
1151 cc_params[cc_par_cnt++] =
1152 alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
1153 #endif
1154
1155 #if defined(__APPLE__)
1156 if (shared_linking || partial_linking) {
1157
1158 cc_params[cc_par_cnt++] = "-Wl,-U";
1159 cc_params[cc_par_cnt++] = "-Wl,___afl_area_ptr";
1160 cc_params[cc_par_cnt++] = "-Wl,-U";
1161 cc_params[cc_par_cnt++] = "-Wl,___sanitizer_cov_trace_pc_guard_init";
1162
1163 }
1164
1165 #endif
1166
1167 }
1168
1169 #if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__
1170 cc_params[cc_par_cnt++] = "-lrt";
1171 #endif
1172
1173 #endif
1174
1175 cc_params[cc_par_cnt] = NULL;
1176
1177 }
1178
1179 /* Main entry point */
1180
main(int argc,char ** argv,char ** envp)1181 int main(int argc, char **argv, char **envp) {
1182
1183 int i;
1184 char *callname = argv[0], *ptr = NULL;
1185
1186 if (getenv("AFL_DEBUG")) {
1187
1188 debug = 1;
1189 if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG");
1190
1191 } else if (getenv("AFL_QUIET"))
1192
1193 be_quiet = 1;
1194
1195 if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") ||
1196 getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") ||
1197 getenv("AFL_LLVM_BLOCKLIST")) {
1198
1199 have_instr_env = 1;
1200
1201 }
1202
1203 if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) {
1204
1205 passthrough = 1;
1206 if (!debug) { be_quiet = 1; }
1207
1208 }
1209
1210 if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1;
1211 argvnull = (u8 *)argv[0];
1212 check_environment_vars(envp);
1213
1214 if ((ptr = find_object("as", argv[0])) != NULL) {
1215
1216 have_gcc = 1;
1217 ck_free(ptr);
1218
1219 }
1220
1221 #if (LLVM_MAJOR >= 3)
1222
1223 if ((ptr = find_object("SanitizerCoverageLTO.so", argv[0])) != NULL) {
1224
1225 have_lto = 1;
1226 ck_free(ptr);
1227
1228 }
1229
1230 if ((ptr = find_object("cmplog-routines-pass.so", argv[0])) != NULL) {
1231
1232 have_llvm = 1;
1233 ck_free(ptr);
1234
1235 }
1236
1237 #endif
1238
1239 #ifdef __ANDROID__
1240 have_llvm = 1;
1241 #endif
1242
1243 if ((ptr = find_object("afl-gcc-pass.so", argv[0])) != NULL) {
1244
1245 have_gcc_plugin = 1;
1246 ck_free(ptr);
1247
1248 }
1249
1250 #if (LLVM_MAJOR >= 3)
1251
1252 if (strncmp(callname, "afl-clang-fast", 14) == 0) {
1253
1254 compiler_mode = LLVM;
1255
1256 } else if (strncmp(callname, "afl-clang-lto", 13) == 0 ||
1257
1258 strncmp(callname, "afl-lto", 7) == 0) {
1259
1260 compiler_mode = LTO;
1261
1262 } else
1263
1264 #endif
1265 if (strncmp(callname, "afl-gcc-fast", 12) == 0 ||
1266
1267 strncmp(callname, "afl-g++-fast", 12) == 0) {
1268
1269 compiler_mode = GCC_PLUGIN;
1270
1271 } else if (strncmp(callname, "afl-gcc", 7) == 0 ||
1272
1273 strncmp(callname, "afl-g++", 7) == 0) {
1274
1275 compiler_mode = GCC;
1276
1277 } else if (strcmp(callname, "afl-clang") == 0 ||
1278
1279 strcmp(callname, "afl-clang++") == 0) {
1280
1281 compiler_mode = CLANG;
1282
1283 }
1284
1285 if ((ptr = getenv("AFL_CC_COMPILER"))) {
1286
1287 if (compiler_mode) {
1288
1289 if (!be_quiet) {
1290
1291 WARNF(
1292 "\"AFL_CC_COMPILER\" is set but a specific compiler was already "
1293 "selected by command line parameter or symlink, ignoring the "
1294 "environment variable!");
1295
1296 }
1297
1298 } else {
1299
1300 if (strncasecmp(ptr, "LTO", 3) == 0) {
1301
1302 compiler_mode = LTO;
1303
1304 } else if (strncasecmp(ptr, "LLVM", 4) == 0) {
1305
1306 compiler_mode = LLVM;
1307
1308 } else if (strncasecmp(ptr, "GCC_P", 5) == 0 ||
1309
1310 strncasecmp(ptr, "GCC-P", 5) == 0 ||
1311 strncasecmp(ptr, "GCCP", 4) == 0) {
1312
1313 compiler_mode = GCC_PLUGIN;
1314
1315 } else if (strcasecmp(ptr, "GCC") == 0) {
1316
1317 compiler_mode = GCC;
1318
1319 } else
1320
1321 FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr);
1322
1323 }
1324
1325 }
1326
1327 if (strcmp(callname, "afl-clang") == 0 ||
1328 strcmp(callname, "afl-clang++") == 0) {
1329
1330 clang_mode = 1;
1331 compiler_mode = CLANG;
1332
1333 if (strcmp(callname, "afl-clang++") == 0) { plusplus_mode = 1; }
1334
1335 }
1336
1337 for (i = 1; i < argc; i++) {
1338
1339 if (strncmp(argv[i], "--afl", 5) == 0) {
1340
1341 if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) {
1342
1343 passthrough = 1;
1344 argv[i] = "-g"; // we have to overwrite it, -g is always good
1345 continue;
1346
1347 }
1348
1349 if (compiler_mode && !be_quiet) {
1350
1351 WARNF(
1352 "--afl-... compiler mode supersedes the AFL_CC_COMPILER and "
1353 "symlink compiler selection!");
1354
1355 }
1356
1357 ptr = argv[i];
1358 ptr += 5;
1359 while (*ptr == '-')
1360 ptr++;
1361
1362 if (strncasecmp(ptr, "LTO", 3) == 0) {
1363
1364 compiler_mode = LTO;
1365
1366 } else if (strncasecmp(ptr, "LLVM", 4) == 0) {
1367
1368 compiler_mode = LLVM;
1369
1370 } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 ||
1371
1372 strncasecmp(ptr, "PC-GUARD", 8) == 0) {
1373
1374 compiler_mode = LLVM;
1375 instrument_mode = INSTRUMENT_PCGUARD;
1376
1377 } else if (strcasecmp(ptr, "INSTRIM") == 0 ||
1378
1379 strcasecmp(ptr, "CFG") == 0) {
1380
1381 FATAL(
1382 "InsTrim instrumentation was removed. Use a modern LLVM and "
1383 "PCGUARD (default in afl-cc).\n");
1384
1385 } else if (strcasecmp(ptr, "AFL") == 0 ||
1386
1387 strcasecmp(ptr, "CLASSIC") == 0) {
1388
1389 compiler_mode = LLVM;
1390 instrument_mode = INSTRUMENT_CLASSIC;
1391
1392 } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 ||
1393
1394 strcasecmp(ptr, "NATIVE") == 0 ||
1395 strcasecmp(ptr, "LLVM-NATIVE") == 0) {
1396
1397 compiler_mode = LLVM;
1398 instrument_mode = INSTRUMENT_LLVMNATIVE;
1399
1400 } else if (strncasecmp(ptr, "GCC_P", 5) == 0 ||
1401
1402 strncasecmp(ptr, "GCC-P", 5) == 0 ||
1403 strncasecmp(ptr, "GCCP", 4) == 0) {
1404
1405 compiler_mode = GCC_PLUGIN;
1406
1407 } else if (strcasecmp(ptr, "GCC") == 0) {
1408
1409 compiler_mode = GCC;
1410
1411 } else if (strncasecmp(ptr, "CLANG", 5) == 0) {
1412
1413 compiler_mode = CLANG;
1414
1415 } else
1416
1417 FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]);
1418
1419 }
1420
1421 }
1422
1423 if (strlen(callname) > 2 &&
1424 (strncmp(callname + strlen(callname) - 2, "++", 2) == 0 ||
1425 strstr(callname, "-g++") != NULL))
1426 plusplus_mode = 1;
1427
1428 if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") ||
1429 getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) {
1430
1431 if (instrument_mode == 0)
1432 instrument_mode = INSTRUMENT_PCGUARD;
1433 else if (instrument_mode != INSTRUMENT_PCGUARD)
1434 FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
1435
1436 }
1437
1438 if (have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) {
1439
1440 WARNF(
1441 "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined "
1442 "for file matching, only function matching!");
1443
1444 }
1445
1446 if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
1447 getenv("INSTRIM_LIB")) {
1448
1449 FATAL(
1450 "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD "
1451 "(default in afl-cc).\n");
1452
1453 }
1454
1455 if (getenv("AFL_LLVM_CTX")) instrument_opt_mode |= INSTRUMENT_OPT_CTX;
1456 if (getenv("AFL_LLVM_CALLER")) instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
1457
1458 if (getenv("AFL_LLVM_NGRAM_SIZE")) {
1459
1460 instrument_opt_mode |= INSTRUMENT_OPT_NGRAM;
1461 ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE"));
1462 if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX)
1463 FATAL(
1464 "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX "
1465 "(%u)",
1466 NGRAM_SIZE_MAX);
1467
1468 }
1469
1470 if (getenv("AFL_LLVM_CTX_K")) {
1471
1472 ctx_k = atoi(getenv("AFL_LLVM_CTX_K"));
1473 if (ctx_k < 1 || ctx_k > CTX_MAX_K)
1474 FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)",
1475 CTX_MAX_K);
1476 if (ctx_k == 1) {
1477
1478 setenv("AFL_LLVM_CALLER", "1", 1);
1479 unsetenv("AFL_LLVM_CTX_K");
1480 instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
1481
1482 } else {
1483
1484 instrument_opt_mode |= INSTRUMENT_OPT_CTX_K;
1485
1486 }
1487
1488 }
1489
1490 if (getenv("AFL_LLVM_INSTRUMENT")) {
1491
1492 u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;");
1493
1494 while (ptr2) {
1495
1496 if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 ||
1497 strncasecmp(ptr2, "classic", strlen("classic")) == 0) {
1498
1499 if (instrument_mode == INSTRUMENT_LTO) {
1500
1501 instrument_mode = INSTRUMENT_CLASSIC;
1502 lto_mode = 1;
1503
1504 } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL)
1505
1506 instrument_mode = INSTRUMENT_AFL;
1507 else
1508 FATAL("main instrumentation mode already set with %s",
1509 instrument_mode_string[instrument_mode]);
1510
1511 }
1512
1513 if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 ||
1514 strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) {
1515
1516 if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD)
1517 instrument_mode = INSTRUMENT_PCGUARD;
1518 else
1519 FATAL("main instrumentation mode already set with %s",
1520 instrument_mode_string[instrument_mode]);
1521
1522 }
1523
1524 if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 ||
1525 strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0) {
1526
1527 if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE)
1528 instrument_mode = INSTRUMENT_LLVMNATIVE;
1529 else
1530 FATAL("main instrumentation mode already set with %s",
1531 instrument_mode_string[instrument_mode]);
1532
1533 }
1534
1535 if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
1536 strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
1537
1538 FATAL(
1539 "InsTrim instrumentation was removed. Use a modern LLVM and "
1540 "PCGUARD (default in afl-cc).\n");
1541
1542 }
1543
1544 if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) {
1545
1546 lto_mode = 1;
1547 if (!instrument_mode || instrument_mode == INSTRUMENT_LTO)
1548 instrument_mode = INSTRUMENT_LTO;
1549 else
1550 FATAL("main instrumentation mode already set with %s",
1551 instrument_mode_string[instrument_mode]);
1552
1553 }
1554
1555 if (strcasecmp(ptr2, "gcc") == 0) {
1556
1557 if (!instrument_mode || instrument_mode == INSTRUMENT_GCC)
1558 instrument_mode = INSTRUMENT_GCC;
1559 else if (instrument_mode != INSTRUMENT_GCC)
1560 FATAL("main instrumentation mode already set with %s",
1561 instrument_mode_string[instrument_mode]);
1562 compiler_mode = GCC;
1563
1564 }
1565
1566 if (strcasecmp(ptr2, "clang") == 0) {
1567
1568 if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG)
1569 instrument_mode = INSTRUMENT_CLANG;
1570 else if (instrument_mode != INSTRUMENT_CLANG)
1571 FATAL("main instrumentation mode already set with %s",
1572 instrument_mode_string[instrument_mode]);
1573 compiler_mode = CLANG;
1574
1575 }
1576
1577 if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 ||
1578 strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 ||
1579 strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) {
1580
1581 u8 *ptr3 = ptr2;
1582 while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9'))
1583 ptr3++;
1584
1585 if (!*ptr3) {
1586
1587 if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL)
1588 FATAL(
1589 "you must set the K-CTX K with (e.g. for value 2) "
1590 "AFL_LLVM_INSTRUMENT=ctx-2");
1591
1592 }
1593
1594 ctx_k = atoi(ptr3);
1595 if (ctx_k < 1 || ctx_k > CTX_MAX_K)
1596 FATAL(
1597 "K-CTX instrumentation option must be between 1 and CTX_MAX_K "
1598 "(%u)",
1599 CTX_MAX_K);
1600
1601 if (ctx_k == 1) {
1602
1603 instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
1604 setenv("AFL_LLVM_CALLER", "1", 1);
1605 unsetenv("AFL_LLVM_CTX_K");
1606
1607 } else {
1608
1609 instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K);
1610 u8 *ptr4 = alloc_printf("%u", ctx_k);
1611 setenv("AFL_LLVM_CTX_K", ptr4, 1);
1612
1613 }
1614
1615 }
1616
1617 if (strcasecmp(ptr2, "ctx") == 0) {
1618
1619 instrument_opt_mode |= INSTRUMENT_OPT_CTX;
1620 setenv("AFL_LLVM_CTX", "1", 1);
1621
1622 }
1623
1624 if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) {
1625
1626 instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
1627 setenv("AFL_LLVM_CALLER", "1", 1);
1628
1629 }
1630
1631 if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) {
1632
1633 u8 *ptr3 = ptr2 + strlen("ngram");
1634 while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9'))
1635 ptr3++;
1636
1637 if (!*ptr3) {
1638
1639 if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL)
1640 FATAL(
1641 "you must set the NGRAM size with (e.g. for value 2) "
1642 "AFL_LLVM_INSTRUMENT=ngram-2");
1643
1644 }
1645
1646 ngram_size = atoi(ptr3);
1647 if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX)
1648 FATAL(
1649 "NGRAM instrumentation option must be between 2 and "
1650 "NGRAM_SIZE_MAX (%u)",
1651 NGRAM_SIZE_MAX);
1652 instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM);
1653 u8 *ptr4 = alloc_printf("%u", ngram_size);
1654 setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1);
1655
1656 }
1657
1658 ptr2 = strtok(NULL, ":,;");
1659
1660 }
1661
1662 }
1663
1664 if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) &&
1665 (instrument_opt_mode & INSTRUMENT_OPT_CALLER)) {
1666
1667 FATAL("you cannot set CTX and CALLER together");
1668
1669 }
1670
1671 if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) &&
1672 (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) {
1673
1674 FATAL("you cannot set CTX and K-CTX together");
1675
1676 }
1677
1678 if ((instrument_opt_mode & INSTRUMENT_OPT_CALLER) &&
1679 (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) {
1680
1681 FATAL("you cannot set CALLER and K-CTX together");
1682
1683 }
1684
1685 if (instrument_opt_mode && instrument_mode == INSTRUMENT_DEFAULT &&
1686 (compiler_mode == LLVM || compiler_mode == UNSET)) {
1687
1688 instrument_mode = INSTRUMENT_CLASSIC;
1689 compiler_mode = LLVM;
1690
1691 }
1692
1693 if (!compiler_mode) {
1694
1695 // lto is not a default because outside of afl-cc RANLIB and AR have to
1696 // be set to llvm versions so this would work
1697 if (have_llvm)
1698 compiler_mode = LLVM;
1699 else if (have_gcc_plugin)
1700 compiler_mode = GCC_PLUGIN;
1701 else if (have_gcc)
1702 #ifdef __APPLE__
1703 // on OSX clang masquerades as GCC
1704 compiler_mode = CLANG;
1705 #else
1706 compiler_mode = GCC;
1707 #endif
1708 else if (have_lto)
1709 compiler_mode = LTO;
1710 else
1711 FATAL("no compiler mode available");
1712
1713 }
1714
1715 if (compiler_mode == GCC) {
1716
1717 if (clang_mode) {
1718
1719 instrument_mode = INSTRUMENT_CLANG;
1720
1721 } else {
1722
1723 instrument_mode = INSTRUMENT_GCC;
1724
1725 }
1726
1727 }
1728
1729 if (compiler_mode == CLANG) {
1730
1731 instrument_mode = INSTRUMENT_CLANG;
1732 setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as
1733
1734 }
1735
1736 if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) {
1737
1738 printf("afl-cc" VERSION
1739 " by Michal Zalewski, Laszlo Szekeres, Marc Heuse\n");
1740
1741 SAYF(
1742 "\n"
1743 "afl-cc/afl-c++ [options]\n"
1744 "\n"
1745 "This is a helper application for afl-fuzz. It serves as a drop-in "
1746 "replacement\n"
1747 "for gcc and clang, letting you recompile third-party code with the "
1748 "required\n"
1749 "runtime instrumentation. A common use pattern would be one of the "
1750 "following:\n\n"
1751
1752 " CC=afl-cc CXX=afl-c++ ./configure --disable-shared\n"
1753 " cmake -DCMAKE_C_COMPILERC=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ .\n"
1754 " CC=afl-cc CXX=afl-c++ meson\n\n");
1755
1756 SAYF(
1757 " |------------- FEATURES "
1758 "-------------|\n"
1759 "MODES: NCC PERSIST DICT LAF "
1760 "CMPLOG SELECT\n"
1761 " [LTO] llvm LTO: %s%s\n"
1762 " PCGUARD DEFAULT yes yes yes yes yes "
1763 " yes\n"
1764 " CLASSIC yes yes yes yes yes "
1765 " yes\n"
1766 " [LLVM] llvm: %s%s\n"
1767 " PCGUARD %s yes yes module yes yes "
1768 "yes\n"
1769 " CLASSIC %s no yes module yes yes "
1770 "yes\n"
1771 " - NORMAL\n"
1772 " - CALLER\n"
1773 " - CTX\n"
1774 " - NGRAM-{2-16}\n"
1775 " [GCC_PLUGIN] gcc plugin: %s%s\n"
1776 " CLASSIC DEFAULT no yes no no no "
1777 "yes\n"
1778 " [GCC/CLANG] simple gcc/clang: %s%s\n"
1779 " CLASSIC DEFAULT no no no no no "
1780 "no\n\n",
1781 have_lto ? "AVAILABLE" : "unavailable!",
1782 compiler_mode == LTO ? " [SELECTED]" : "",
1783 have_llvm ? "AVAILABLE" : "unavailable!",
1784 compiler_mode == LLVM ? " [SELECTED]" : "",
1785 LLVM_MAJOR >= 7 ? "DEFAULT" : " ",
1786 LLVM_MAJOR >= 7 ? " " : "DEFAULT",
1787 have_gcc_plugin ? "AVAILABLE" : "unavailable!",
1788 compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "",
1789 have_gcc ? "AVAILABLE" : "unavailable!",
1790 (compiler_mode == GCC || compiler_mode == CLANG) ? " [SELECTED]" : "");
1791
1792 SAYF(
1793 "Modes:\n"
1794 " To select the compiler mode use a symlink version (e.g. "
1795 "afl-clang-fast), set\n"
1796 " the environment variable AFL_CC_COMPILER to a mode (e.g. LLVM) or "
1797 "use the\n"
1798 " command line parameter --afl-MODE (e.g. --afl-llvm). If none is "
1799 "selected,\n"
1800 " afl-cc will select the best available (LLVM -> GCC_PLUGIN -> GCC).\n"
1801 " The best is LTO but it often needs RANLIB and AR settings outside "
1802 "of afl-cc.\n\n");
1803
1804 #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
1805 #define NATIVE_MSG \
1806 " LLVM-NATIVE: use llvm's native PCGUARD instrumentation (less " \
1807 "performant)\n"
1808 #else
1809 #define NATIVE_MSG ""
1810 #endif
1811
1812 SAYF(
1813 "Sub-Modes: (set via env AFL_LLVM_INSTRUMENT, afl-cc selects the best "
1814 "available)\n"
1815 " PCGUARD: Dominator tree instrumentation (best!) (README.llvm.md)\n"
1816
1817 NATIVE_MSG
1818
1819 " CLASSIC: decision target instrumentation (README.llvm.md)\n"
1820 " CALLER: CLASSIC + single callee context "
1821 "(instrumentation/README.ctx.md)\n"
1822 " CTX: CLASSIC + full callee context "
1823 "(instrumentation/README.ctx.md)\n"
1824 " NGRAM-x: CLASSIC + previous path "
1825 "((instrumentation/README.ngram.md)\n\n");
1826
1827 #undef NATIVE_MSG
1828
1829 SAYF(
1830 "Features: (see documentation links)\n"
1831 " NCC: non-colliding coverage [automatic] (that is an amazing "
1832 "thing!)\n"
1833 " (instrumentation/README.lto.md)\n"
1834 " PERSIST: persistent mode support [code] (huge speed increase!)\n"
1835 " (instrumentation/README.persistent_mode.md)\n"
1836 " DICT: dictionary in the target [yes=automatic or llvm module "
1837 "pass]\n"
1838 " (instrumentation/README.lto.md + "
1839 "instrumentation/README.llvm.md)\n"
1840 " LAF: comparison splitting [env] "
1841 "(instrumentation/README.laf-intel.md)\n"
1842 " CMPLOG: input2state exploration [env] "
1843 "(instrumentation/README.cmplog.md)\n"
1844 " SELECT: selective instrumentation (allow/deny) on filename or "
1845 "function [env]\n"
1846 " (instrumentation/README.instrument_list.md)\n\n");
1847
1848 if (argc < 2 || strncmp(argv[1], "-hh", 3)) {
1849
1850 SAYF(
1851 "To see all environment variables for the configuration of afl-cc "
1852 "use \"-hh\".\n");
1853
1854 } else {
1855
1856 SAYF(
1857 "Environment variables used:\n"
1858 " AFL_CC: path to the C compiler to use\n"
1859 " AFL_CXX: path to the C++ compiler to use\n"
1860 " AFL_DEBUG: enable developer debugging output\n"
1861 " AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n"
1862 " AFL_NO_BUILTIN: no builtins for string compare functions (for "
1863 "libtokencap.so)\n"
1864 " AFL_NOOP: behave like a normal compiler (to pass configure "
1865 "tests)\n"
1866 " AFL_PATH: path to instrumenting pass and runtime "
1867 "(afl-compiler-rt.*o)\n"
1868 " AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
1869 " AFL_INST_RATIO: percentage of branches to instrument\n"
1870 " AFL_QUIET: suppress verbose output\n"
1871 " AFL_HARDEN: adds code hardening to catch memory bugs\n"
1872 " AFL_USE_ASAN: activate address sanitizer\n"
1873 " AFL_USE_CFISAN: activate control flow sanitizer\n"
1874 " AFL_USE_MSAN: activate memory sanitizer\n"
1875 " AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
1876 " AFL_USE_TSAN: activate thread sanitizer\n"
1877 " AFL_USE_LSAN: activate leak-checker sanitizer\n");
1878
1879 if (have_gcc_plugin)
1880 SAYF(
1881 "\nGCC Plugin-specific environment variables:\n"
1882 " AFL_GCC_OUT_OF_LINE: disable inlined instrumentation\n"
1883 " AFL_GCC_SKIP_NEVERZERO: do not skip zero on trace counters\n"
1884 " AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
1885 "filename\n");
1886
1887 #if LLVM_MAJOR >= 9
1888 #define COUNTER_BEHAVIOUR \
1889 " AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
1890 #else
1891 #define COUNTER_BEHAVIOUR \
1892 " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
1893 #endif
1894 if (have_llvm)
1895 SAYF(
1896 "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment "
1897 "variables:\n"
1898 " AFL_LLVM_THREADSAFE_INST: instrument with thread safe counters, "
1899 "disables neverzero\n"
1900
1901 COUNTER_BEHAVIOUR
1902
1903 " AFL_LLVM_DICT2FILE: generate an afl dictionary based on found "
1904 "comparisons\n"
1905 " AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n"
1906 " AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n"
1907 " AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n"
1908 " AFL_LLVM_LAF_SPLIT_SWITCHES: cascaded comparisons on switches\n"
1909 " AFL_LLVM_LAF_SPLIT_FLOATS: cascaded comparisons on floats\n"
1910 " AFL_LLVM_LAF_TRANSFORM_COMPARES: cascade comparisons for string "
1911 "functions\n"
1912 " AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST: enable "
1913 "instrument allow/\n"
1914 " deny listing (selective instrumentation)\n");
1915
1916 if (have_llvm)
1917 SAYF(
1918 " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen "
1919 "mutator)\n"
1920 " AFL_LLVM_INSTRUMENT: set instrumentation mode:\n"
1921 " CLASSIC, PCGUARD, LTO, GCC, CLANG, CALLER, CTX, NGRAM-2 "
1922 "..-16\n"
1923 " You can also use the old environment variables instead:\n"
1924 " AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n"
1925 " AFL_LLVM_CALLER: use single context sensitive coverage (for "
1926 "CLASSIC)\n"
1927 " AFL_LLVM_CTX: use full context sensitive coverage (for "
1928 "CLASSIC)\n"
1929 " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for "
1930 "CLASSIC)\n");
1931
1932 #ifdef AFL_CLANG_FLTO
1933 if (have_lto)
1934 SAYF(
1935 "\nLTO/afl-clang-lto specific environment variables:\n"
1936 " AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), "
1937 "e.g. "
1938 "0x10000\n"
1939 " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
1940 "functions\n"
1941 " into this file\n"
1942 " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
1943 "global var\n"
1944 " AFL_LLVM_LTO_STARTID: from which ID to start counting from for "
1945 "a "
1946 "bb\n"
1947 " AFL_REAL_LD: use this lld linker instead of the compiled in "
1948 "path\n"
1949 "If anything fails - be sure to read README.lto.md!\n");
1950 #endif
1951
1952 SAYF(
1953 "\nYou can supply --afl-noopt to not instrument, like AFL_NOOPT. "
1954 "(this is helpful\n"
1955 "in some build systems if you do not want to instrument "
1956 "everything.\n");
1957
1958 }
1959
1960 SAYF(
1961 "\nFor any information on the available instrumentations and options "
1962 "please \n"
1963 "consult the README.md, especially section 3.1 about instrumenting "
1964 "targets.\n\n");
1965
1966 #if (LLVM_MAJOR >= 3)
1967 if (have_lto)
1968 SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO);
1969 if (have_llvm)
1970 SAYF("afl-cc LLVM version %d using the binary path \"%s\".\n", LLVM_MAJOR,
1971 LLVM_BINDIR);
1972 #endif
1973
1974 #ifdef USEMMAP
1975 #if !defined(__HAIKU__)
1976 SAYF("Compiled with shm_open support.\n");
1977 #else
1978 SAYF("Compiled with shm_open support (adds -lrt when linking).\n");
1979 #endif
1980 #else
1981 SAYF("Compiled with shmat support.\n");
1982 #endif
1983 SAYF("\n");
1984
1985 SAYF(
1986 "Do not be overwhelmed :) afl-cc uses good defaults if no options are "
1987 "selected.\n"
1988 "Read the documentation for FEATURES though, all are good but few are "
1989 "defaults.\n"
1990 "Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast "
1991 "with\n"
1992 "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n");
1993
1994 exit(1);
1995
1996 }
1997
1998 if (compiler_mode == LTO) {
1999
2000 if (instrument_mode == 0 || instrument_mode == INSTRUMENT_LTO ||
2001 instrument_mode == INSTRUMENT_CFG ||
2002 instrument_mode == INSTRUMENT_PCGUARD) {
2003
2004 lto_mode = 1;
2005 // force CFG
2006 // if (!instrument_mode) {
2007
2008 instrument_mode = INSTRUMENT_PCGUARD;
2009 // ptr = instrument_mode_string[instrument_mode];
2010 // }
2011
2012 } else if (instrument_mode == INSTRUMENT_CLASSIC) {
2013
2014 lto_mode = 1;
2015
2016 } else {
2017
2018 if (!be_quiet) {
2019
2020 WARNF("afl-clang-lto called with mode %s, using that mode instead",
2021 instrument_mode_string[instrument_mode]);
2022
2023 }
2024
2025 }
2026
2027 }
2028
2029 if (instrument_mode == 0 && compiler_mode < GCC_PLUGIN) {
2030
2031 #if LLVM_MAJOR >= 7
2032 #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
2033 if (have_instr_env) {
2034
2035 instrument_mode = INSTRUMENT_AFL;
2036 if (!be_quiet) {
2037
2038 WARNF(
2039 "Switching to classic instrumentation because "
2040 "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1.");
2041
2042 }
2043
2044 } else
2045
2046 #endif
2047 instrument_mode = INSTRUMENT_PCGUARD;
2048
2049 #else
2050 instrument_mode = INSTRUMENT_AFL;
2051 #endif
2052
2053 }
2054
2055 if (instrument_opt_mode && compiler_mode != LLVM)
2056 FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode");
2057
2058 if (!instrument_opt_mode) {
2059
2060 if (lto_mode && instrument_mode == INSTRUMENT_CFG)
2061 instrument_mode = INSTRUMENT_PCGUARD;
2062 ptr = instrument_mode_string[instrument_mode];
2063
2064 } else {
2065
2066 char *ptr2 = alloc_printf(" + NGRAM-%u", ngram_size);
2067 char *ptr3 = alloc_printf(" + K-CTX-%u", ctx_k);
2068
2069 ptr = alloc_printf(
2070 "%s%s%s%s%s", instrument_mode_string[instrument_mode],
2071 (instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "",
2072 (instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "",
2073 (instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "",
2074 (instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : "");
2075
2076 ck_free(ptr2);
2077 ck_free(ptr3);
2078
2079 }
2080
2081 #ifndef AFL_CLANG_FLTO
2082 if (lto_mode)
2083 FATAL(
2084 "instrumentation mode LTO specified but LLVM support not available "
2085 "(requires LLVM 11 or higher)");
2086 #endif
2087
2088 if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
2089 FATAL(
2090 "CALLER, CTX and NGRAM instrumentation options can only be used with "
2091 "the LLVM CLASSIC instrumentation mode.");
2092
2093 if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO"))
2094 FATAL(
2095 "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set "
2096 "together");
2097
2098 #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
2099 if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) {
2100
2101 FATAL(
2102 "Instrumentation type PCGUARD does not support "
2103 "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead.");
2104
2105 }
2106
2107 #endif
2108
2109 u8 *ptr2;
2110
2111 if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/')
2112 FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path");
2113
2114 if ((isatty(2) && !be_quiet) || debug) {
2115
2116 SAYF(cCYA
2117 "afl-cc" VERSION cRST
2118 " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n",
2119 compiler_mode_string[compiler_mode], ptr);
2120
2121 }
2122
2123 if (!be_quiet && (compiler_mode == GCC || compiler_mode == CLANG)) {
2124
2125 WARNF(
2126 "You are using outdated instrumentation, install LLVM and/or "
2127 "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast "
2128 "instead!");
2129
2130 }
2131
2132 if (debug) {
2133
2134 DEBUGF("cd '%s';", getthecwd());
2135 for (i = 0; i < argc; i++)
2136 SAYF(" '%s'", argv[i]);
2137 SAYF("\n");
2138 fflush(stdout);
2139 fflush(stderr);
2140
2141 }
2142
2143 if (getenv("AFL_LLVM_LAF_ALL")) {
2144
2145 setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1);
2146 setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1);
2147 setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1);
2148 setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1);
2149
2150 }
2151
2152 cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG");
2153 if (!be_quiet && cmplog_mode)
2154 printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
2155
2156 #if !defined(__ANDROID__) && !defined(ANDROID)
2157 ptr = find_object("afl-compiler-rt.o", argv[0]);
2158
2159 if (!ptr) {
2160
2161 FATAL(
2162 "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH "
2163 "environment variable.");
2164
2165 }
2166
2167 if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); }
2168
2169 ck_free(ptr);
2170 #endif
2171
2172 edit_params(argc, argv, envp);
2173
2174 if (debug) {
2175
2176 DEBUGF("cd '%s';", getthecwd());
2177 for (i = 0; i < (s32)cc_par_cnt; i++)
2178 SAYF(" '%s'", cc_params[i]);
2179 SAYF("\n");
2180 fflush(stdout);
2181 fflush(stderr);
2182
2183 }
2184
2185 if (passthrough) {
2186
2187 argv[0] = cc_params[0];
2188 execvp(cc_params[0], (char **)argv);
2189
2190 } else {
2191
2192 execvp(cc_params[0], (char **)cc_params);
2193
2194 }
2195
2196 FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
2197
2198 return 0;
2199
2200 }
2201
2202