IRMutator.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. //===-- IRMutator.cpp -----------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/FuzzMutate/IRMutator.h"
  9. #include "llvm/ADT/Optional.h"
  10. #include "llvm/Analysis/TargetLibraryInfo.h"
  11. #include "llvm/FuzzMutate/Operations.h"
  12. #include "llvm/FuzzMutate/Random.h"
  13. #include "llvm/FuzzMutate/RandomIRBuilder.h"
  14. #include "llvm/IR/BasicBlock.h"
  15. #include "llvm/IR/Function.h"
  16. #include "llvm/IR/InstIterator.h"
  17. #include "llvm/IR/Instructions.h"
  18. #include "llvm/IR/Module.h"
  19. #include "llvm/Support/Debug.h"
  20. #include "llvm/Transforms/Scalar/DCE.h"
  21. using namespace llvm;
  22. static void createEmptyFunction(Module &M) {
  23. // TODO: Some arguments and a return value would probably be more interesting.
  24. LLVMContext &Context = M.getContext();
  25. Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Context), {},
  26. /*isVarArg=*/false),
  27. GlobalValue::ExternalLinkage, "f", &M);
  28. BasicBlock *BB = BasicBlock::Create(Context, "BB", F);
  29. ReturnInst::Create(Context, BB);
  30. }
  31. void IRMutationStrategy::mutate(Module &M, RandomIRBuilder &IB) {
  32. if (M.empty())
  33. createEmptyFunction(M);
  34. auto RS = makeSampler<Function *>(IB.Rand);
  35. for (Function &F : M)
  36. if (!F.isDeclaration())
  37. RS.sample(&F, /*Weight=*/1);
  38. mutate(*RS.getSelection(), IB);
  39. }
  40. void IRMutationStrategy::mutate(Function &F, RandomIRBuilder &IB) {
  41. mutate(*makeSampler(IB.Rand, make_pointer_range(F)).getSelection(), IB);
  42. }
  43. void IRMutationStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
  44. mutate(*makeSampler(IB.Rand, make_pointer_range(BB)).getSelection(), IB);
  45. }
  46. void IRMutator::mutateModule(Module &M, int Seed, size_t CurSize,
  47. size_t MaxSize) {
  48. std::vector<Type *> Types;
  49. for (const auto &Getter : AllowedTypes)
  50. Types.push_back(Getter(M.getContext()));
  51. RandomIRBuilder IB(Seed, Types);
  52. auto RS = makeSampler<IRMutationStrategy *>(IB.Rand);
  53. for (const auto &Strategy : Strategies)
  54. RS.sample(Strategy.get(),
  55. Strategy->getWeight(CurSize, MaxSize, RS.totalWeight()));
  56. auto Strategy = RS.getSelection();
  57. Strategy->mutate(M, IB);
  58. }
  59. static void eliminateDeadCode(Function &F) {
  60. FunctionPassManager FPM;
  61. FPM.addPass(DCEPass());
  62. FunctionAnalysisManager FAM;
  63. FAM.registerPass([&] { return TargetLibraryAnalysis(); });
  64. FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
  65. FPM.run(F, FAM);
  66. }
  67. void InjectorIRStrategy::mutate(Function &F, RandomIRBuilder &IB) {
  68. IRMutationStrategy::mutate(F, IB);
  69. eliminateDeadCode(F);
  70. }
  71. std::vector<fuzzerop::OpDescriptor> InjectorIRStrategy::getDefaultOps() {
  72. std::vector<fuzzerop::OpDescriptor> Ops;
  73. describeFuzzerIntOps(Ops);
  74. describeFuzzerFloatOps(Ops);
  75. describeFuzzerControlFlowOps(Ops);
  76. describeFuzzerPointerOps(Ops);
  77. describeFuzzerAggregateOps(Ops);
  78. describeFuzzerVectorOps(Ops);
  79. return Ops;
  80. }
  81. Optional<fuzzerop::OpDescriptor>
  82. InjectorIRStrategy::chooseOperation(Value *Src, RandomIRBuilder &IB) {
  83. auto OpMatchesPred = [&Src](fuzzerop::OpDescriptor &Op) {
  84. return Op.SourcePreds[0].matches({}, Src);
  85. };
  86. auto RS = makeSampler(IB.Rand, make_filter_range(Operations, OpMatchesPred));
  87. if (RS.isEmpty())
  88. return None;
  89. return *RS;
  90. }
  91. void InjectorIRStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
  92. SmallVector<Instruction *, 32> Insts;
  93. for (auto I = BB.getFirstInsertionPt(), E = BB.end(); I != E; ++I)
  94. Insts.push_back(&*I);
  95. if (Insts.size() < 1)
  96. return;
  97. // Choose an insertion point for our new instruction.
  98. size_t IP = uniform<size_t>(IB.Rand, 0, Insts.size() - 1);
  99. auto InstsBefore = makeArrayRef(Insts).slice(0, IP);
  100. auto InstsAfter = makeArrayRef(Insts).slice(IP);
  101. // Choose a source, which will be used to constrain the operation selection.
  102. SmallVector<Value *, 2> Srcs;
  103. Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore));
  104. // Choose an operation that's constrained to be valid for the type of the
  105. // source, collect any other sources it needs, and then build it.
  106. auto OpDesc = chooseOperation(Srcs[0], IB);
  107. // Bail if no operation was found
  108. if (!OpDesc)
  109. return;
  110. for (const auto &Pred : makeArrayRef(OpDesc->SourcePreds).slice(1))
  111. Srcs.push_back(IB.findOrCreateSource(BB, InstsBefore, Srcs, Pred));
  112. if (Value *Op = OpDesc->BuilderFunc(Srcs, Insts[IP])) {
  113. // Find a sink and wire up the results of the operation.
  114. IB.connectToSink(BB, InstsAfter, Op);
  115. }
  116. }
  117. uint64_t InstDeleterIRStrategy::getWeight(size_t CurrentSize, size_t MaxSize,
  118. uint64_t CurrentWeight) {
  119. // If we have less than 200 bytes, panic and try to always delete.
  120. if (CurrentSize > MaxSize - 200)
  121. return CurrentWeight ? CurrentWeight * 100 : 1;
  122. // Draw a line starting from when we only have 1k left and increasing linearly
  123. // to double the current weight.
  124. int64_t Line = (-2 * static_cast<int64_t>(CurrentWeight)) *
  125. (static_cast<int64_t>(MaxSize) -
  126. static_cast<int64_t>(CurrentSize) - 1000) /
  127. 1000;
  128. // Clamp negative weights to zero.
  129. if (Line < 0)
  130. return 0;
  131. return Line;
  132. }
  133. void InstDeleterIRStrategy::mutate(Function &F, RandomIRBuilder &IB) {
  134. auto RS = makeSampler<Instruction *>(IB.Rand);
  135. for (Instruction &Inst : instructions(F)) {
  136. // TODO: We can't handle these instructions.
  137. if (Inst.isTerminator() || Inst.isEHPad() ||
  138. Inst.isSwiftError() || isa<PHINode>(Inst))
  139. continue;
  140. RS.sample(&Inst, /*Weight=*/1);
  141. }
  142. if (RS.isEmpty())
  143. return;
  144. // Delete the instruction.
  145. mutate(*RS.getSelection(), IB);
  146. // Clean up any dead code that's left over after removing the instruction.
  147. eliminateDeadCode(F);
  148. }
  149. void InstDeleterIRStrategy::mutate(Instruction &Inst, RandomIRBuilder &IB) {
  150. assert(!Inst.isTerminator() && "Deleting terminators invalidates CFG");
  151. if (Inst.getType()->isVoidTy()) {
  152. // Instructions with void type (ie, store) have no uses to worry about. Just
  153. // erase it and move on.
  154. Inst.eraseFromParent();
  155. return;
  156. }
  157. // Otherwise we need to find some other value with the right type to keep the
  158. // users happy.
  159. auto Pred = fuzzerop::onlyType(Inst.getType());
  160. auto RS = makeSampler<Value *>(IB.Rand);
  161. SmallVector<Instruction *, 32> InstsBefore;
  162. BasicBlock *BB = Inst.getParent();
  163. for (auto I = BB->getFirstInsertionPt(), E = Inst.getIterator(); I != E;
  164. ++I) {
  165. if (Pred.matches({}, &*I))
  166. RS.sample(&*I, /*Weight=*/1);
  167. InstsBefore.push_back(&*I);
  168. }
  169. if (!RS)
  170. RS.sample(IB.newSource(*BB, InstsBefore, {}, Pred), /*Weight=*/1);
  171. Inst.replaceAllUsesWith(RS.getSelection());
  172. Inst.eraseFromParent();
  173. }
  174. void InstModificationIRStrategy::mutate(Instruction &Inst,
  175. RandomIRBuilder &IB) {
  176. SmallVector<std::function<void()>, 8> Modifications;
  177. CmpInst *CI = nullptr;
  178. GetElementPtrInst *GEP = nullptr;
  179. switch (Inst.getOpcode()) {
  180. default:
  181. break;
  182. case Instruction::Add:
  183. case Instruction::Mul:
  184. case Instruction::Sub:
  185. case Instruction::Shl:
  186. Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(true); }),
  187. Modifications.push_back([&Inst]() { Inst.setHasNoSignedWrap(false); });
  188. Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(true); });
  189. Modifications.push_back([&Inst]() { Inst.setHasNoUnsignedWrap(false); });
  190. break;
  191. case Instruction::ICmp:
  192. CI = cast<ICmpInst>(&Inst);
  193. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_EQ); });
  194. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_NE); });
  195. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_UGT); });
  196. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_UGE); });
  197. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_ULT); });
  198. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_ULE); });
  199. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SGT); });
  200. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SGE); });
  201. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SLT); });
  202. Modifications.push_back([CI]() { CI->setPredicate(CmpInst::ICMP_SLE); });
  203. break;
  204. case Instruction::GetElementPtr:
  205. GEP = cast<GetElementPtrInst>(&Inst);
  206. Modifications.push_back([GEP]() { GEP->setIsInBounds(true); });
  207. Modifications.push_back([GEP]() { GEP->setIsInBounds(false); });
  208. break;
  209. }
  210. auto RS = makeSampler(IB.Rand, Modifications);
  211. if (RS)
  212. RS.getSelection()();
  213. }