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