LLVM  15.0.0git
IRMutator.h
Go to the documentation of this file.
1 //===-- IRMutator.h - Mutation engine for fuzzing IR ------------*- C++ -*-===//
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 //
9 // Provides the IRMutator class, which drives mutations on IR based on a
10 // configurable set of strategies. Some common strategies are also included
11 // here.
12 //
13 // Fuzzer-friendly (de)serialization functions are also provided, as these
14 // are usually needed when mutating IR.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef LLVM_FUZZMUTATE_IRMUTATOR_H
19 #define LLVM_FUZZMUTATE_IRMUTATOR_H
20 
21 #include "llvm/ADT/Optional.h"
24 
25 namespace llvm {
26 class BasicBlock;
27 class Function;
28 class Instruction;
29 class Module;
30 
31 struct RandomIRBuilder;
32 
33 /// Base class for describing how to mutate a module. mutation functions for
34 /// each IR unit forward to the contained unit.
36 public:
37  virtual ~IRMutationStrategy() = default;
38 
39  /// Provide a weight to bias towards choosing this strategy for a mutation.
40  ///
41  /// The value of the weight is arbitrary, but a good default is "the number of
42  /// distinct ways in which this strategy can mutate a unit". This can also be
43  /// used to prefer strategies that shrink the overall size of the result when
44  /// we start getting close to \c MaxSize.
45  virtual uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
46  uint64_t CurrentWeight) = 0;
47 
48  /// @{
49  /// Mutators for each IR unit. By default these forward to a contained
50  /// instance of the next smaller unit.
51  virtual void mutate(Module &M, RandomIRBuilder &IB);
52  virtual void mutate(Function &F, RandomIRBuilder &IB);
53  virtual void mutate(BasicBlock &BB, RandomIRBuilder &IB);
54  virtual void mutate(Instruction &I, RandomIRBuilder &IB) {
55  llvm_unreachable("Strategy does not implement any mutators");
56  }
57  /// @}
58 };
59 
61 
62 /// Entry point for configuring and running IR mutations.
63 class IRMutator {
64  std::vector<TypeGetter> AllowedTypes;
65  std::vector<std::unique_ptr<IRMutationStrategy>> Strategies;
66 
67 public:
68  IRMutator(std::vector<TypeGetter> &&AllowedTypes,
69  std::vector<std::unique_ptr<IRMutationStrategy>> &&Strategies)
70  : AllowedTypes(std::move(AllowedTypes)),
71  Strategies(std::move(Strategies)) {}
72 
73  void mutateModule(Module &M, int Seed, size_t CurSize, size_t MaxSize);
74 };
75 
76 /// Strategy that injects operations into the function.
78  std::vector<fuzzerop::OpDescriptor> Operations;
79 
80  Optional<fuzzerop::OpDescriptor> chooseOperation(Value *Src,
81  RandomIRBuilder &IB);
82 
83 public:
84  InjectorIRStrategy(std::vector<fuzzerop::OpDescriptor> &&Operations)
85  : Operations(std::move(Operations)) {}
86  static std::vector<fuzzerop::OpDescriptor> getDefaultOps();
87 
88  uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
89  uint64_t CurrentWeight) override {
90  return Operations.size();
91  }
92 
94  void mutate(Function &F, RandomIRBuilder &IB) override;
95  void mutate(BasicBlock &BB, RandomIRBuilder &IB) override;
96 };
97 
99 public:
100  uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
101  uint64_t CurrentWeight) override;
102 
104  void mutate(Function &F, RandomIRBuilder &IB) override;
105  void mutate(Instruction &Inst, RandomIRBuilder &IB) override;
106 };
107 
109 public:
110  uint64_t getWeight(size_t CurrentSize, size_t MaxSize,
111  uint64_t CurrentWeight) override {
112  return 4;
113  }
114 
116  void mutate(Instruction &Inst, RandomIRBuilder &IB) override;
117 };
118 
119 /// Fuzzer friendly interface for the llvm bitcode parser.
120 ///
121 /// \param Data Bitcode we are going to parse
122 /// \param Size Size of the 'Data' in bytes
123 /// \return New module or nullptr in case of error
124 std::unique_ptr<Module> parseModule(const uint8_t *Data, size_t Size,
125  LLVMContext &Context);
126 
127 /// Fuzzer friendly interface for the llvm bitcode printer.
128 ///
129 /// \param M Module to print
130 /// \param Dest Location to store serialized module
131 /// \param MaxSize Size of the destination buffer
132 /// \return Number of bytes that were written. When module size exceeds MaxSize
133 /// returns 0 and leaves Dest unchanged.
134 size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize);
135 
136 /// Try to parse module and verify it. May output verification errors to the
137 /// errs().
138 /// \return New module or nullptr in case of error.
139 std::unique_ptr<Module> parseAndVerify(const uint8_t *Data, size_t Size,
140  LLVMContext &Context);
141 
142 } // end llvm namespace
143 
144 #endif // LLVM_FUZZMUTATE_IRMUTATOR_H
OpDescriptor.h
llvm::parseModule
std::unique_ptr< Module > parseModule(const uint8_t *Data, size_t Size, LLVMContext &Context)
Fuzzer friendly interface for the llvm bitcode parser.
Definition: IRMutator.cpp:252
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
Optional.h
llvm::InstModificationIRStrategy::getWeight
uint64_t getWeight(size_t CurrentSize, size_t MaxSize, uint64_t CurrentWeight) override
Provide a weight to bias towards choosing this strategy for a mutation.
Definition: IRMutator.h:110
llvm::Function
Definition: Function.h:60
llvm::InstDeleterIRStrategy::getWeight
uint64_t getWeight(size_t CurrentSize, size_t MaxSize, uint64_t CurrentWeight) override
Provide a weight to bias towards choosing this strategy for a mutation.
Definition: IRMutator.cpp:144
ErrorHandling.h
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::InstModificationIRStrategy::mutate
void mutate(Instruction &Inst, RandomIRBuilder &IB) override
Definition: IRMutator.cpp:209
llvm::Optional
Definition: APInt.h:33
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:55
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::InjectorIRStrategy::InjectorIRStrategy
InjectorIRStrategy(std::vector< fuzzerop::OpDescriptor > &&Operations)
Definition: IRMutator.h:84
llvm::InjectorIRStrategy::getWeight
uint64_t getWeight(size_t CurrentSize, size_t MaxSize, uint64_t CurrentWeight) override
Provide a weight to bias towards choosing this strategy for a mutation.
Definition: IRMutator.h:88
llvm::Instruction
Definition: Instruction.h:42
llvm::InjectorIRStrategy
Strategy that injects operations into the function.
Definition: IRMutator.h:77
llvm::TypeGetter
std::function< Type *(LLVMContext &)> TypeGetter
Definition: IRMutator.h:60
llvm::IRMutationStrategy::mutate
virtual void mutate(Instruction &I, RandomIRBuilder &IB)
Definition: IRMutator.h:54
llvm::InjectorIRStrategy::mutate
void mutate(Function &F, RandomIRBuilder &IB) override
Definition: IRMutator.cpp:84
Seed
static ManagedStatic< cl::opt< uint64_t >, CreateSeed > Seed
Definition: RandomNumberGenerator.cpp:40
llvm::InstDeleterIRStrategy
Definition: IRMutator.h:98
llvm::IRMutator
Entry point for configuring and running IR mutations.
Definition: IRMutator.h:63
uint64_t
llvm::InstModificationIRStrategy
Definition: IRMutator.h:108
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
llvm::IRMutationStrategy::getWeight
virtual uint64_t getWeight(size_t CurrentSize, size_t MaxSize, uint64_t CurrentWeight)=0
Provide a weight to bias towards choosing this strategy for a mutation.
llvm::InstDeleterIRStrategy::mutate
void mutate(Function &F, RandomIRBuilder &IB) override
Definition: IRMutator.cpp:161
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1675
llvm::ISD::BasicBlock
@ BasicBlock
Various leaf nodes.
Definition: ISDOpcodes.h:71
function
print Print MemDeps of function
Definition: MemDepPrinter.cpp:82
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::IRMutationStrategy
Base class for describing how to mutate a module.
Definition: IRMutator.h:35
llvm::IRMutationStrategy::~IRMutationStrategy
virtual ~IRMutationStrategy()=default
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
Module
Machine Check Debug Module
Definition: MachineCheckDebugify.cpp:122
llvm::RandomIRBuilder
Definition: RandomIRBuilder.h:32
llvm::InjectorIRStrategy::getDefaultOps
static std::vector< fuzzerop::OpDescriptor > getDefaultOps()
Definition: IRMutator.cpp:89
std
Definition: BitVector.h:851
llvm::IRMutationStrategy::mutate
virtual void mutate(Module &M, RandomIRBuilder &IB)
Definition: IRMutator.cpp:39
llvm::IRMutator::mutateModule
void mutateModule(Module &M, int Seed, size_t CurSize, size_t MaxSize)
Definition: IRMutator.cpp:59
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::IRMutator::IRMutator
IRMutator(std::vector< TypeGetter > &&AllowedTypes, std::vector< std::unique_ptr< IRMutationStrategy >> &&Strategies)
Definition: IRMutator.h:68
llvm::writeModule
size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize)
Fuzzer friendly interface for the llvm bitcode printer.
Definition: IRMutator.cpp:272
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::parseAndVerify
std::unique_ptr< Module > parseAndVerify(const uint8_t *Data, size_t Size, LLVMContext &Context)
Try to parse module and verify it.
Definition: IRMutator.cpp:284
llvm::codeview::PublicSymFlags::Function
@ Function