xref: /aosp_15_r20/external/AFLplusplus/instrumentation/afl-llvm-lto-instrumentlist.so.cc (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1 /*
2    american fuzzy lop++ - LLVM-mode instrumentation pass
3    ---------------------------------------------------
4 
5    Written by Laszlo Szekeres <[email protected]> and
6               Michal Zalewski
7 
8    LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted
9    from afl-as.c are Michal's fault.
10 
11    Copyright 2015, 2016 Google Inc. All rights reserved.
12    Copyright 2019-2024 AFLplusplus Project. All rights reserved.
13 
14    Licensed under the Apache License, Version 2.0 (the "License");
15    you may not use this file except in compliance with the License.
16    You may obtain a copy of the License at:
17 
18      https://www.apache.org/licenses/LICENSE-2.0
19 
20    This library is plugged into LLVM when invoking clang through afl-clang-fast.
21    It tells the compiler to add code roughly equivalent to the bits discussed
22    in ../afl-as.h.
23 
24  */
25 
26 #define AFL_LLVM_PASS
27 
28 #include "config.h"
29 #include "debug.h"
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 
35 #include <list>
36 #include <string>
37 #include <fstream>
38 #include <sys/time.h>
39 #include <fnmatch.h>
40 
41 #include "llvm/IR/DebugInfo.h"
42 #include "llvm/IR/BasicBlock.h"
43 #include "llvm/IR/IRBuilder.h"
44 #include "llvm/IR/LegacyPassManager.h"
45 #include "llvm/IR/Module.h"
46 #include "llvm/Pass.h"
47 #include "llvm/Support/Debug.h"
48 // #include "llvm/Transforms/IPO/PassManagerBuilder.h"
49 #include "llvm/Passes/PassPlugin.h"
50 #include "llvm/Passes/PassBuilder.h"
51 #include "llvm/IR/PassManager.h"
52 #include "llvm/IR/CFG.h"
53 #if LLVM_VERSION_MAJOR >= 14                /* how about stable interfaces? */
54   #include "llvm/Passes/OptimizationLevel.h"
55 #endif
56 
57 #include "afl-llvm-common.h"
58 
59 using namespace llvm;
60 
61 namespace {
62 
63 class AFLcheckIfInstrument : public PassInfoMixin<AFLcheckIfInstrument> {
64 
65  public:
AFLcheckIfInstrument()66   AFLcheckIfInstrument() {
67 
68     if (getenv("AFL_DEBUG")) debug = 1;
69 
70     initInstrumentList();
71 
72   }
73 
74   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
75 
76  protected:
77   std::list<std::string> myInstrumentList;
78 
79 };
80 
81 }  // namespace
82 
83 extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo()84 llvmGetPassPluginInfo() {
85 
86   return {LLVM_PLUGIN_API_VERSION, "AFLcheckIfInstrument", "v0.1",
87           /* lambda to insert our pass into the pass pipeline. */
88           [](PassBuilder &PB) {
89 
90 #if LLVM_VERSION_MAJOR <= 13
91             using OptimizationLevel = typename PassBuilder::OptimizationLevel;
92 #endif
93             PB.registerOptimizerLastEPCallback(
94                 [](ModulePassManager &MPM, OptimizationLevel OL) {
95 
96                   MPM.addPass(AFLcheckIfInstrument());
97 
98                 });
99 
100           }};
101 
102 }
103 
run(Module & M,ModuleAnalysisManager & MAM)104 PreservedAnalyses AFLcheckIfInstrument::run(Module                &M,
105                                             ModuleAnalysisManager &MAM) {
106 
107   /* Show a banner */
108 
109   setvbuf(stdout, NULL, _IONBF, 0);
110 
111   if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
112 
113     SAYF(cCYA "afl-llvm-lto-instrumentlist" VERSION cRST
114               " by Marc \"vanHauser\" Heuse <[email protected]>\n");
115 
116   } else if (getenv("AFL_QUIET"))
117 
118     be_quiet = 1;
119 
120   for (auto &F : M) {
121 
122     if (F.size() < 1) continue;
123 
124     // fprintf(stderr, "F:%s\n", F.getName().str().c_str());
125 
126     if (isInInstrumentList(&F, MNAME)) {
127 
128       if (debug)
129         DEBUGF("function %s is in the instrument file list\n",
130                F.getName().str().c_str());
131 
132     } else {
133 
134       if (debug)
135         DEBUGF("function %s is NOT in the instrument file list\n",
136                F.getName().str().c_str());
137 
138       auto         &Ctx = F.getContext();
139       AttributeList Attrs = F.getAttributes();
140 #if LLVM_VERSION_MAJOR >= 14
141       AttributeList NewAttrs = Attrs.addFnAttribute(Ctx, "skipinstrument");
142       F.setAttributes(NewAttrs);
143 #else
144       AttrBuilder NewAttrs;
145       NewAttrs.addAttribute("skipinstrument");
146       F.setAttributes(
147           Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs));
148 #endif
149 
150     }
151 
152   }
153 
154   auto PA = PreservedAnalyses::all();
155   return PA;
156 
157 }
158 
159 #if 0
160 static void registerAFLcheckIfInstrumentpass(const PassManagerBuilder &,
161                                              legacy::PassManagerBase &PM) {
162 
163   PM.add(new AFLcheckIfInstrument());
164 
165 }
166 
167 static RegisterStandardPasses RegisterAFLcheckIfInstrumentpass(
168     PassManagerBuilder::EP_ModuleOptimizerEarly,
169     registerAFLcheckIfInstrumentpass);
170 
171 static RegisterStandardPasses RegisterAFLcheckIfInstrumentpass0(
172     PassManagerBuilder::EP_EnabledOnOptLevel0,
173     registerAFLcheckIfInstrumentpass);
174 #endif
175 
176