• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- IRMutator.h - Mutation engine for fuzzing IR ------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Provides the IRMutator class, which drives mutations on IR based on a
11 // configurable set of strategies. Some common strategies are also included
12 // here.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_FUZZMUTATE_IRMUTATOR_H
17 #define LLVM_FUZZMUTATE_IRMUTATOR_H
18 
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/FuzzMutate/OpDescriptor.h"
21 #include "llvm/Support/ErrorHandling.h"
22 
23 namespace llvm {
24 class BasicBlock;
25 class Function;
26 class Instruction;
27 class Module;
28 
29 struct RandomIRBuilder;
30 
31 /// Base class for describing how to mutate a module. mutation functions for
32 /// each IR unit forward to the contained unit.
33 class IRMutationStrategy {
34 public:
35   virtual ~IRMutationStrategy() = default;
36 
37   /// Provide a weight to bias towards choosing this strategy for a mutation.
38   ///
39   /// The value of the weight is arbitrary, but a good default is "the number of
40   /// distinct ways in which this strategy can mutate a unit". This can also be
41   /// used to prefer strategies that shrink the overall size of the result when
42   /// we start getting close to \c MaxSize.
43   virtual uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
44                              uint64_t CurrentWeight) = 0;
45 
46   /// @{
47   /// Mutators for each IR unit. By default these forward to a contained
48   /// instance of the next smaller unit.
49   virtual void mutate(Module &M, RandomIRBuilder &IB);
50   virtual void mutate(Function &F, RandomIRBuilder &IB);
51   virtual void mutate(BasicBlock &BB, RandomIRBuilder &IB);
mutate(Instruction & I,RandomIRBuilder & IB)52   virtual void mutate(Instruction &I, RandomIRBuilder &IB) {
53     llvm_unreachable("Strategy does not implement any mutators");
54   }
55   /// @}
56 };
57 
58 using TypeGetter = std::function<Type *(LLVMContext &)>;
59 
60 /// Entry point for configuring and running IR mutations.
61 class IRMutator {
62   std::vector<TypeGetter> AllowedTypes;
63   std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
64 
65 public:
IRMutator(std::vector<TypeGetter> && AllowedTypes,std::vector<std::unique_ptr<IRMutationStrategy>> && Strategies)66   IRMutator(std::vector<TypeGetter> &&AllowedTypes,
67             std::vector<std::unique_ptr<IRMutationStrategy>> &&Strategies)
68       : AllowedTypes(std::move(AllowedTypes)),
69         Strategies(std::move(Strategies)) {}
70 
71   void mutateModule(Module &M, int Seed, size_t CurSize, size_t MaxSize);
72 };
73 
74 /// Strategy that injects operations into the function.
75 class InjectorIRStrategy : public IRMutationStrategy {
76   std::vector<fuzzerop::OpDescriptor> Operations;
77 
78   Optional<fuzzerop::OpDescriptor> chooseOperation(Value *Src,
79                                                    RandomIRBuilder &IB);
80 
81 public:
InjectorIRStrategy(std::vector<fuzzerop::OpDescriptor> && Operations)82   InjectorIRStrategy(std::vector<fuzzerop::OpDescriptor> &&Operations)
83       : Operations(std::move(Operations)) {}
84   static std::vector<fuzzerop::OpDescriptor> getDefaultOps();
85 
getWeight(size_t CurrentSize,size_t MaxSize,uint64_t CurrentWeight)86   uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
87                      uint64_t CurrentWeight) override {
88     return Operations.size();
89   }
90 
91   using IRMutationStrategy::mutate;
92   void mutate(Function &F, RandomIRBuilder &IB) override;
93   void mutate(BasicBlock &BB, RandomIRBuilder &IB) override;
94 };
95 
96 class InstDeleterIRStrategy : public IRMutationStrategy {
97 public:
98   uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
99                      uint64_t CurrentWeight) override;
100 
101   using IRMutationStrategy::mutate;
102   void mutate(Function &F, RandomIRBuilder &IB) override;
103   void mutate(Instruction &Inst, RandomIRBuilder &IB) override;
104 };
105 
106 } // end llvm namespace
107 
108 #endif // LLVM_FUZZMUTATE_IRMUTATOR_H
109