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