• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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