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