Skip to content

Commit 0a83ff8

Browse files
committed
[FuzzMutate] Move LLVM module (de)serialization from FuzzerCLI -> IRMutator. NFC
These are not directly related to the CLI, and are mostly (always?) used when mutating the modules as part of fuzzing. Motivation: split FuzzerCLI into its own library that does not depend on IR. Subprojects that don't use IR should be be fuzzed without the dependency. Differential Revision: https://reviews.llvm.org/D125080
1 parent eeb4457 commit 0a83ff8

File tree

4 files changed

+73
-73
lines changed

4 files changed

+73
-73
lines changed

llvm/include/llvm/FuzzMutate/FuzzerCLI.h

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020

2121
namespace llvm {
2222

23-
class LLVMContext;
24-
class Module;
2523
class StringRef;
2624

2725
/// Parse cl::opts from a fuzz target commandline.
@@ -54,29 +52,6 @@ using FuzzerInitFun = int (*)(int *argc, char ***argv);
5452
int runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
5553
FuzzerInitFun Init = [](int *, char ***) { return 0; });
5654

57-
/// Fuzzer friendly interface for the llvm bitcode parser.
58-
///
59-
/// \param Data Bitcode we are going to parse
60-
/// \param Size Size of the 'Data' in bytes
61-
/// \return New module or nullptr in case of error
62-
std::unique_ptr<Module> parseModule(const uint8_t *Data, size_t Size,
63-
LLVMContext &Context);
64-
65-
/// Fuzzer friendly interface for the llvm bitcode printer.
66-
///
67-
/// \param M Module to print
68-
/// \param Dest Location to store serialized module
69-
/// \param MaxSize Size of the destination buffer
70-
/// \return Number of bytes that were written. When module size exceeds MaxSize
71-
/// returns 0 and leaves Dest unchanged.
72-
size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize);
73-
74-
/// Try to parse module and verify it. May output verification errors to the
75-
/// errs().
76-
/// \return New module or nullptr in case of error.
77-
std::unique_ptr<Module> parseAndVerify(const uint8_t *Data, size_t Size,
78-
LLVMContext &Context);
79-
80-
} // end llvm namespace
55+
} // namespace llvm
8156

8257
#endif // LLVM_FUZZMUTATE_FUZZERCLI_H

llvm/include/llvm/FuzzMutate/IRMutator.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
// configurable set of strategies. Some common strategies are also included
1111
// here.
1212
//
13+
// Fuzzer-friendly (de)serialization functions are also provided, as these
14+
// are usually needed when mutating IR.
15+
//
1316
//===----------------------------------------------------------------------===//
1417

1518
#ifndef LLVM_FUZZMUTATE_IRMUTATOR_H
@@ -113,6 +116,29 @@ class InstModificationIRStrategy : public IRMutationStrategy {
113116
void mutate(Instruction &Inst, RandomIRBuilder &IB) override;
114117
};
115118

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+
116142
} // end llvm namespace
117143

118144
#endif // LLVM_FUZZMUTATE_IRMUTATOR_H

llvm/lib/FuzzMutate/FuzzerCLI.cpp

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,8 @@
99
#include "llvm/FuzzMutate/FuzzerCLI.h"
1010
#include "llvm/ADT/StringRef.h"
1111
#include "llvm/ADT/Triple.h"
12-
#include "llvm/Bitcode/BitcodeReader.h"
13-
#include "llvm/Bitcode/BitcodeWriter.h"
14-
#include "llvm/IR/Verifier.h"
1512
#include "llvm/Support/CommandLine.h"
16-
#include "llvm/Support/Compiler.h"
17-
#include "llvm/Support/Error.h"
1813
#include "llvm/Support/MemoryBuffer.h"
19-
#include "llvm/Support/SourceMgr.h"
2014
#include "llvm/Support/raw_ostream.h"
2115

2216
using namespace llvm;
@@ -165,44 +159,3 @@ int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
165159
}
166160
return 0;
167161
}
168-
169-
std::unique_ptr<Module> llvm::parseModule(
170-
const uint8_t *Data, size_t Size, LLVMContext &Context) {
171-
172-
if (Size <= 1)
173-
// We get bogus data given an empty corpus - just create a new module.
174-
return std::make_unique<Module>("M", Context);
175-
176-
auto Buffer = MemoryBuffer::getMemBuffer(
177-
StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input",
178-
/*RequiresNullTerminator=*/false);
179-
180-
SMDiagnostic Err;
181-
auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context);
182-
if (Error E = M.takeError()) {
183-
errs() << toString(std::move(E)) << "\n";
184-
return nullptr;
185-
}
186-
return std::move(M.get());
187-
}
188-
189-
size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {
190-
std::string Buf;
191-
{
192-
raw_string_ostream OS(Buf);
193-
WriteBitcodeToFile(M, OS);
194-
}
195-
if (Buf.size() > MaxSize)
196-
return 0;
197-
memcpy(Dest, Buf.data(), Buf.size());
198-
return Buf.size();
199-
}
200-
201-
std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size,
202-
LLVMContext &Context) {
203-
auto M = parseModule(Data, Size, Context);
204-
if (!M || verifyModule(*M, &errs()))
205-
return nullptr;
206-
207-
return M;
208-
}

llvm/lib/FuzzMutate/IRMutator.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "llvm/FuzzMutate/IRMutator.h"
1010
#include "llvm/ADT/Optional.h"
1111
#include "llvm/Analysis/TargetLibraryInfo.h"
12+
#include "llvm/Bitcode/BitcodeReader.h"
13+
#include "llvm/Bitcode/BitcodeWriter.h"
1214
#include "llvm/FuzzMutate/Operations.h"
1315
#include "llvm/FuzzMutate/Random.h"
1416
#include "llvm/FuzzMutate/RandomIRBuilder.h"
@@ -17,6 +19,9 @@
1719
#include "llvm/IR/InstIterator.h"
1820
#include "llvm/IR/Instructions.h"
1921
#include "llvm/IR/Module.h"
22+
#include "llvm/IR/Verifier.h"
23+
#include "llvm/Support/MemoryBuffer.h"
24+
#include "llvm/Support/SourceMgr.h"
2025
#include "llvm/Transforms/Scalar/DCE.h"
2126

2227
using namespace llvm;
@@ -243,3 +248,44 @@ void InstModificationIRStrategy::mutate(Instruction &Inst,
243248
if (RS)
244249
RS.getSelection()();
245250
}
251+
252+
std::unique_ptr<Module> llvm::parseModule(const uint8_t *Data, size_t Size,
253+
LLVMContext &Context) {
254+
255+
if (Size <= 1)
256+
// We get bogus data given an empty corpus - just create a new module.
257+
return std::make_unique<Module>("M", Context);
258+
259+
auto Buffer = MemoryBuffer::getMemBuffer(
260+
StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input",
261+
/*RequiresNullTerminator=*/false);
262+
263+
SMDiagnostic Err;
264+
auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context);
265+
if (Error E = M.takeError()) {
266+
errs() << toString(std::move(E)) << "\n";
267+
return nullptr;
268+
}
269+
return std::move(M.get());
270+
}
271+
272+
size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {
273+
std::string Buf;
274+
{
275+
raw_string_ostream OS(Buf);
276+
WriteBitcodeToFile(M, OS);
277+
}
278+
if (Buf.size() > MaxSize)
279+
return 0;
280+
memcpy(Dest, Buf.data(), Buf.size());
281+
return Buf.size();
282+
}
283+
284+
std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size,
285+
LLVMContext &Context) {
286+
auto M = parseModule(Data, Size, Context);
287+
if (!M || verifyModule(*M, &errs()))
288+
return nullptr;
289+
290+
return M;
291+
}

0 commit comments

Comments
 (0)