17d449d31SJustin Bogner //===-- IRMutator.cpp -----------------------------------------------------===//
27d449d31SJustin Bogner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67d449d31SJustin Bogner //
77d449d31SJustin Bogner //===----------------------------------------------------------------------===//
87d449d31SJustin Bogner 
97d449d31SJustin Bogner #include "llvm/FuzzMutate/IRMutator.h"
10ce6f2d01SIgor Laevsky #include "llvm/ADT/Optional.h"
117d449d31SJustin Bogner #include "llvm/Analysis/TargetLibraryInfo.h"
12*0a83ff83SSam McCall #include "llvm/Bitcode/BitcodeReader.h"
13*0a83ff83SSam McCall #include "llvm/Bitcode/BitcodeWriter.h"
147d449d31SJustin Bogner #include "llvm/FuzzMutate/Operations.h"
157d449d31SJustin Bogner #include "llvm/FuzzMutate/Random.h"
167d449d31SJustin Bogner #include "llvm/FuzzMutate/RandomIRBuilder.h"
177d449d31SJustin Bogner #include "llvm/IR/BasicBlock.h"
187d449d31SJustin Bogner #include "llvm/IR/Function.h"
197d449d31SJustin Bogner #include "llvm/IR/InstIterator.h"
20ce6f2d01SIgor Laevsky #include "llvm/IR/Instructions.h"
217d449d31SJustin Bogner #include "llvm/IR/Module.h"
22*0a83ff83SSam McCall #include "llvm/IR/Verifier.h"
23*0a83ff83SSam McCall #include "llvm/Support/MemoryBuffer.h"
24*0a83ff83SSam McCall #include "llvm/Support/SourceMgr.h"
257d449d31SJustin Bogner #include "llvm/Transforms/Scalar/DCE.h"
267d449d31SJustin Bogner 
277d449d31SJustin Bogner using namespace llvm;
287d449d31SJustin Bogner 
createEmptyFunction(Module & M)297d449d31SJustin Bogner static void createEmptyFunction(Module &M) {
307d449d31SJustin Bogner   // TODO: Some arguments and a return value would probably be more interesting.
317d449d31SJustin Bogner   LLVMContext &Context = M.getContext();
327d449d31SJustin Bogner   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Context), {},
337d449d31SJustin Bogner                                                    /*isVarArg=*/false),
347d449d31SJustin Bogner                                  GlobalValue::ExternalLinkage, "f", &M);
357d449d31SJustin Bogner   BasicBlock *BB = BasicBlock::Create(Context, "BB", F);
367d449d31SJustin Bogner   ReturnInst::Create(Context, BB);
377d449d31SJustin Bogner }
387d449d31SJustin Bogner 
mutate(Module & M,RandomIRBuilder & IB)397d449d31SJustin Bogner void IRMutationStrategy::mutate(Module &M, RandomIRBuilder &IB) {
407d449d31SJustin Bogner   auto RS = makeSampler<Function *>(IB.Rand);
417d449d31SJustin Bogner   for (Function &F : M)
427d449d31SJustin Bogner     if (!F.isDeclaration())
437d449d31SJustin Bogner       RS.sample(&F, /*Weight=*/1);
44a3aac569SNikita Popov 
45a3aac569SNikita Popov   if (RS.isEmpty())
46a3aac569SNikita Popov     createEmptyFunction(M);
47a3aac569SNikita Popov   else
487d449d31SJustin Bogner     mutate(*RS.getSelection(), IB);
497d449d31SJustin Bogner }
507d449d31SJustin Bogner 
mutate(Function & F,RandomIRBuilder & IB)517d449d31SJustin Bogner void IRMutationStrategy::mutate(Function &F, RandomIRBuilder &IB) {
527d449d31SJustin Bogner   mutate(*makeSampler(IB.Rand, make_pointer_range(F)).getSelection(), IB);
537d449d31SJustin Bogner }
547d449d31SJustin Bogner 
mutate(BasicBlock & BB,RandomIRBuilder & IB)557d449d31SJustin Bogner void IRMutationStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
567d449d31SJustin Bogner   mutate(*makeSampler(IB.Rand, make_pointer_range(BB)).getSelection(), IB);
577d449d31SJustin Bogner }
587d449d31SJustin Bogner 
mutateModule(Module & M,int Seed,size_t CurSize,size_t MaxSize)597d449d31SJustin Bogner void IRMutator::mutateModule(Module &M, int Seed, size_t CurSize,
607d449d31SJustin Bogner                              size_t MaxSize) {
617d449d31SJustin Bogner   std::vector<Type *> Types;
627d449d31SJustin Bogner   for (const auto &Getter : AllowedTypes)
637d449d31SJustin Bogner     Types.push_back(Getter(M.getContext()));
647d449d31SJustin Bogner   RandomIRBuilder IB(Seed, Types);
657d449d31SJustin Bogner 
667d449d31SJustin Bogner   auto RS = makeSampler<IRMutationStrategy *>(IB.Rand);
677d449d31SJustin Bogner   for (const auto &Strategy : Strategies)
687d449d31SJustin Bogner     RS.sample(Strategy.get(),
697d449d31SJustin Bogner               Strategy->getWeight(CurSize, MaxSize, RS.totalWeight()));
707d449d31SJustin Bogner   auto Strategy = RS.getSelection();
717d449d31SJustin Bogner 
727d449d31SJustin Bogner   Strategy->mutate(M, IB);
737d449d31SJustin Bogner }
747d449d31SJustin Bogner 
eliminateDeadCode(Function & F)757d449d31SJustin Bogner static void eliminateDeadCode(Function &F) {
767d449d31SJustin Bogner   FunctionPassManager FPM;
777d449d31SJustin Bogner   FPM.addPass(DCEPass());
787d449d31SJustin Bogner   FunctionAnalysisManager FAM;
797d449d31SJustin Bogner   FAM.registerPass([&] { return TargetLibraryAnalysis(); });
80ee8d31c4SFedor Sergeev   FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
817d449d31SJustin Bogner   FPM.run(F, FAM);
827d449d31SJustin Bogner }
837d449d31SJustin Bogner 
mutate(Function & F,RandomIRBuilder & IB)847d449d31SJustin Bogner void InjectorIRStrategy::mutate(Function &F, RandomIRBuilder &IB) {
857d449d31SJustin Bogner   IRMutationStrategy::mutate(F, IB);
867d449d31SJustin Bogner   eliminateDeadCode(F);
877d449d31SJustin Bogner }
887d449d31SJustin Bogner 
getDefaultOps()897d449d31SJustin Bogner std::vector<fuzzerop::OpDescriptor> InjectorIRStrategy::getDefaultOps() {
907d449d31SJustin Bogner   std::vector<fuzzerop::OpDescriptor> Ops;
917d449d31SJustin Bogner   describeFuzzerIntOps(Ops);
927d449d31SJustin Bogner   describeFuzzerFloatOps(Ops);
937d449d31SJustin Bogner   describeFuzzerControlFlowOps(Ops);
947d449d31SJustin Bogner   describeFuzzerPointerOps(Ops);
957d449d31SJustin Bogner   describeFuzzerAggregateOps(Ops);
967d449d31SJustin Bogner   describeFuzzerVectorOps(Ops);
977d449d31SJustin Bogner   return Ops;
987d449d31SJustin Bogner }
997d449d31SJustin Bogner 
100ce6f2d01SIgor Laevsky Optional<fuzzerop::OpDescriptor>
chooseOperation(Value * Src,RandomIRBuilder & IB)1017d449d31SJustin Bogner InjectorIRStrategy::chooseOperation(Value *Src, RandomIRBuilder &IB) {
1027d449d31SJustin Bogner   auto OpMatchesPred = [&Src](fuzzerop::OpDescriptor &Op) {
1037d449d31SJustin Bogner     return Op.SourcePreds[0].matches({}, Src);
1047d449d31SJustin Bogner   };
1057d449d31SJustin Bogner   auto RS = makeSampler(IB.Rand, make_filter_range(Operations, OpMatchesPred));
1067d449d31SJustin Bogner   if (RS.isEmpty())
107ce6f2d01SIgor Laevsky     return None;
1087d449d31SJustin Bogner   return *RS;
1097d449d31SJustin Bogner }
1107d449d31SJustin Bogner 
mutate(BasicBlock & BB,RandomIRBuilder & IB)1117d449d31SJustin Bogner void InjectorIRStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
1127d449d31SJustin Bogner   SmallVector<Instruction *, 32> Insts;
1137d449d31SJustin Bogner   for (auto I = BB.getFirstInsertionPt(), E = BB.end(); I != E; ++I)
1147d449d31SJustin Bogner     Insts.push_back(&*I);
1150cdf7fdcSIgor Laevsky   if (Insts.size() < 1)
1160cdf7fdcSIgor Laevsky     return;
1177d449d31SJustin Bogner 
1187d449d31SJustin Bogner   // Choose an insertion point for our new instruction.
1197d449d31SJustin Bogner   size_t IP = uniform<size_t>(IB.Rand, 0, Insts.size() - 1);
1207d449d31SJustin Bogner 
1217d449d31SJustin Bogner   auto InstsBefore = makeArrayRef(Insts).slice(0, IP);
1227d449d31SJustin Bogner   auto InstsAfter = makeArrayRef(Insts).slice(IP);
1237d449d31SJustin Bogner 
1247d449d31SJustin Bogner   // Choose a source, which will be used to constrain the operation selection.
1257d449d31SJustin Bogner   SmallVector<Value *, 2> Srcs;
1267d449d31SJustin Bogner   Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore));
1277d449d31SJustin Bogner 
1287d449d31SJustin Bogner   // Choose an operation that's constrained to be valid for the type of the
1297d449d31SJustin Bogner   // source, collect any other sources it needs, and then build it.
130ce6f2d01SIgor Laevsky   auto OpDesc = chooseOperation(Srcs[0], IB);
131ce6f2d01SIgor Laevsky   // Bail if no operation was found
132ce6f2d01SIgor Laevsky   if (!OpDesc)
133ce6f2d01SIgor Laevsky     return;
134ce6f2d01SIgor Laevsky 
135ce6f2d01SIgor Laevsky   for (const auto &Pred : makeArrayRef(OpDesc->SourcePreds).slice(1))
1367d449d31SJustin Bogner     Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
137ce6f2d01SIgor Laevsky 
138ce6f2d01SIgor Laevsky   if (Value *Op = OpDesc->BuilderFunc(Srcs, Insts[IP])) {
1397d449d31SJustin Bogner     // Find a sink and wire up the results of the operation.
1407d449d31SJustin Bogner     IB.connectToSink(BB, InstsAfter, Op);
1417d449d31SJustin Bogner   }
1427d449d31SJustin Bogner }
1437d449d31SJustin Bogner 
getWeight(size_t CurrentSize,size_t MaxSize,uint64_t CurrentWeight)1447d449d31SJustin Bogner uint64_t InstDeleterIRStrategy::getWeight(size_t CurrentSize, size_t MaxSize,
1457d449d31SJustin Bogner                                           uint64_t CurrentWeight) {
1467d449d31SJustin Bogner   // If we have less than 200 bytes, panic and try to always delete.
1477d449d31SJustin Bogner   if (CurrentSize > MaxSize - 200)
1487d449d31SJustin Bogner     return CurrentWeight ? CurrentWeight * 100 : 1;
1497d449d31SJustin Bogner   // Draw a line starting from when we only have 1k left and increasing linearly
1507d449d31SJustin Bogner   // to double the current weight.
1517e976cd4SJustin Bogner   int64_t Line = (-2 * static_cast<int64_t>(CurrentWeight)) *
1527e976cd4SJustin Bogner                  (static_cast<int64_t>(MaxSize) -
1537e976cd4SJustin Bogner                   static_cast<int64_t>(CurrentSize) - 1000) /
1547e976cd4SJustin Bogner                  1000;
1557d449d31SJustin Bogner   // Clamp negative weights to zero.
1567d449d31SJustin Bogner   if (Line < 0)
1577d449d31SJustin Bogner     return 0;
1587d449d31SJustin Bogner   return Line;
1597d449d31SJustin Bogner }
1607d449d31SJustin Bogner 
mutate(Function & F,RandomIRBuilder & IB)1617d449d31SJustin Bogner void InstDeleterIRStrategy::mutate(Function &F, RandomIRBuilder &IB) {
1627d449d31SJustin Bogner   auto RS = makeSampler<Instruction *>(IB.Rand);
1637a43f26dSIgor Laevsky   for (Instruction &Inst : instructions(F)) {
1647a43f26dSIgor Laevsky     // TODO: We can't handle these instructions.
1657a43f26dSIgor Laevsky     if (Inst.isTerminator() || Inst.isEHPad() ||
1667a43f26dSIgor Laevsky         Inst.isSwiftError() || isa<PHINode>(Inst))
1677a43f26dSIgor Laevsky       continue;
1687a43f26dSIgor Laevsky 
1697d449d31SJustin Bogner     RS.sample(&Inst, /*Weight=*/1);
1707a43f26dSIgor Laevsky   }
171444afc82SIgor Laevsky   if (RS.isEmpty())
172444afc82SIgor Laevsky     return;
173444afc82SIgor Laevsky 
1747d449d31SJustin Bogner   // Delete the instruction.
1757d449d31SJustin Bogner   mutate(*RS.getSelection(), IB);
1767d449d31SJustin Bogner   // Clean up any dead code that's left over after removing the instruction.
1777d449d31SJustin Bogner   eliminateDeadCode(F);
1787d449d31SJustin Bogner }
1797d449d31SJustin Bogner 
mutate(Instruction & Inst,RandomIRBuilder & IB)1807d449d31SJustin Bogner void InstDeleterIRStrategy::mutate(Instruction &Inst, RandomIRBuilder &IB) {
1817d449d31SJustin Bogner   assert(!Inst.isTerminator() && "Deleting terminators invalidates CFG");
1827d449d31SJustin Bogner 
1837d449d31SJustin Bogner   if (Inst.getType()->isVoidTy()) {
1847d449d31SJustin Bogner     // Instructions with void type (ie, store) have no uses to worry about. Just
1857d449d31SJustin Bogner     // erase it and move on.
1867d449d31SJustin Bogner     Inst.eraseFromParent();
1877d449d31SJustin Bogner     return;
1887d449d31SJustin Bogner   }
1897d449d31SJustin Bogner 
1907d449d31SJustin Bogner   // Otherwise we need to find some other value with the right type to keep the
1917d449d31SJustin Bogner   // users happy.
1927d449d31SJustin Bogner   auto Pred = fuzzerop::onlyType(Inst.getType());
1937d449d31SJustin Bogner   auto RS = makeSampler<Value *>(IB.Rand);
1947d449d31SJustin Bogner   SmallVector<Instruction *, 32> InstsBefore;
1957d449d31SJustin Bogner   BasicBlock *BB = Inst.getParent();
1967d449d31SJustin Bogner   for (auto I = BB->getFirstInsertionPt(), E = Inst.getIterator(); I != E;
1977d449d31SJustin Bogner        ++I) {
1987d449d31SJustin Bogner     if (Pred.matches({}, &*I))
1997d449d31SJustin Bogner       RS.sample(&*I, /*Weight=*/1);
2007d449d31SJustin Bogner     InstsBefore.push_back(&*I);
2017d449d31SJustin Bogner   }
2027d449d31SJustin Bogner   if (!RS)
2037d449d31SJustin Bogner     RS.sample(IB.newSource(*BB, InstsBefore, {}, Pred), /*Weight=*/1);
2047d449d31SJustin Bogner 
2057d449d31SJustin Bogner   Inst.replaceAllUsesWith(RS.getSelection());
2067a43f26dSIgor Laevsky   Inst.eraseFromParent();
2077d449d31SJustin Bogner }
208166d40f2SFlorian Hahn 
mutate(Instruction & Inst,RandomIRBuilder & IB)209166d40f2SFlorian Hahn void InstModificationIRStrategy::mutate(Instruction &Inst,
210166d40f2SFlorian Hahn                                         RandomIRBuilder &IB) {
211166d40f2SFlorian Hahn   SmallVector<std::function<void()>, 8> Modifications;
212166d40f2SFlorian Hahn   CmpInst *CI = nullptr;
213166d40f2SFlorian Hahn   GetElementPtrInst *GEP = nullptr;
214166d40f2SFlorian Hahn   switch (Inst.getOpcode()) {
215166d40f2SFlorian Hahn   default:
216166d40f2SFlorian Hahn     break;
217166d40f2SFlorian Hahn   case Instruction::Add:
218166d40f2SFlorian Hahn   case Instruction::Mul:
219166d40f2SFlorian Hahn   case Instruction::Sub:
220166d40f2SFlorian Hahn   case Instruction::Shl:
221166d40f2SFlorian Hahn     Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(true); }),
222166d40f2SFlorian Hahn         Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(false); });
223166d40f2SFlorian Hahn     Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(true); });
224166d40f2SFlorian Hahn     Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(false); });
225166d40f2SFlorian Hahn 
226166d40f2SFlorian Hahn     break;
227166d40f2SFlorian Hahn   case Instruction::ICmp:
228166d40f2SFlorian Hahn     CI = cast<ICmpInst>(&Inst);
229166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_EQ); });
230166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_NE); });
231166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_UGT); });
232166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_UGE); });
233166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_ULT); });
234166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_ULE); });
235166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SGT); });
236166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SGE); });
237166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SLT); });
238166d40f2SFlorian Hahn     Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SLE); });
239166d40f2SFlorian Hahn     break;
240166d40f2SFlorian Hahn   case Instruction::GetElementPtr:
241166d40f2SFlorian Hahn     GEP = cast<GetElementPtrInst>(&Inst);
242166d40f2SFlorian Hahn     Modifications.push_back([GEP]() { GEP->setIsInBounds(true); });
243166d40f2SFlorian Hahn     Modifications.push_back([GEP]() { GEP->setIsInBounds(false); });
244166d40f2SFlorian Hahn     break;
245166d40f2SFlorian Hahn   }
246166d40f2SFlorian Hahn 
247166d40f2SFlorian Hahn   auto RS = makeSampler(IB.Rand, Modifications);
248166d40f2SFlorian Hahn   if (RS)
249166d40f2SFlorian Hahn     RS.getSelection()();
250166d40f2SFlorian Hahn }
251*0a83ff83SSam McCall 
parseModule(const uint8_t * Data,size_t Size,LLVMContext & Context)252*0a83ff83SSam McCall std::unique_ptr<Module> llvm::parseModule(const uint8_t *Data, size_t Size,
253*0a83ff83SSam McCall                                           LLVMContext &Context) {
254*0a83ff83SSam McCall 
255*0a83ff83SSam McCall   if (Size <= 1)
256*0a83ff83SSam McCall     // We get bogus data given an empty corpus - just create a new module.
257*0a83ff83SSam McCall     return std::make_unique<Module>("M", Context);
258*0a83ff83SSam McCall 
259*0a83ff83SSam McCall   auto Buffer = MemoryBuffer::getMemBuffer(
260*0a83ff83SSam McCall       StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input",
261*0a83ff83SSam McCall       /*RequiresNullTerminator=*/false);
262*0a83ff83SSam McCall 
263*0a83ff83SSam McCall   SMDiagnostic Err;
264*0a83ff83SSam McCall   auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context);
265*0a83ff83SSam McCall   if (Error E = M.takeError()) {
266*0a83ff83SSam McCall     errs() << toString(std::move(E)) << "\n";
267*0a83ff83SSam McCall     return nullptr;
268*0a83ff83SSam McCall   }
269*0a83ff83SSam McCall   return std::move(M.get());
270*0a83ff83SSam McCall }
271*0a83ff83SSam McCall 
writeModule(const Module & M,uint8_t * Dest,size_t MaxSize)272*0a83ff83SSam McCall size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {
273*0a83ff83SSam McCall   std::string Buf;
274*0a83ff83SSam McCall   {
275*0a83ff83SSam McCall     raw_string_ostream OS(Buf);
276*0a83ff83SSam McCall     WriteBitcodeToFile(M, OS);
277*0a83ff83SSam McCall   }
278*0a83ff83SSam McCall   if (Buf.size() > MaxSize)
279*0a83ff83SSam McCall     return 0;
280*0a83ff83SSam McCall   memcpy(Dest, Buf.data(), Buf.size());
281*0a83ff83SSam McCall   return Buf.size();
282*0a83ff83SSam McCall }
283*0a83ff83SSam McCall 
parseAndVerify(const uint8_t * Data,size_t Size,LLVMContext & Context)284*0a83ff83SSam McCall std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size,
285*0a83ff83SSam McCall                                              LLVMContext &Context) {
286*0a83ff83SSam McCall   auto M = parseModule(Data, Size, Context);
287*0a83ff83SSam McCall   if (!M || verifyModule(*M, &errs()))
288*0a83ff83SSam McCall     return nullptr;
289*0a83ff83SSam McCall 
290*0a83ff83SSam McCall   return M;
291*0a83ff83SSam McCall }
292