xref: /aosp_15_r20/external/llvm/tools/llvm-mc-fuzzer/llvm-mc-fuzzer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===--- llvm-mc-fuzzer.cpp - Fuzzer for the MC layer ---------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
11*9880d681SAndroid Build Coastguard Worker 
12*9880d681SAndroid Build Coastguard Worker #include "FuzzerInterface.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm-c/Disassembler.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm-c/Target.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/SubtargetFeature.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
18*9880d681SAndroid Build Coastguard Worker 
19*9880d681SAndroid Build Coastguard Worker using namespace llvm;
20*9880d681SAndroid Build Coastguard Worker 
21*9880d681SAndroid Build Coastguard Worker const unsigned AssemblyTextBufSize = 80;
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker enum ActionType {
24*9880d681SAndroid Build Coastguard Worker   AC_Assemble,
25*9880d681SAndroid Build Coastguard Worker   AC_Disassemble
26*9880d681SAndroid Build Coastguard Worker };
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker static cl::opt<ActionType>
29*9880d681SAndroid Build Coastguard Worker Action(cl::desc("Action to perform:"),
30*9880d681SAndroid Build Coastguard Worker        cl::init(AC_Assemble),
31*9880d681SAndroid Build Coastguard Worker        cl::values(clEnumValN(AC_Assemble, "assemble",
32*9880d681SAndroid Build Coastguard Worker                              "Assemble a .s file (default)"),
33*9880d681SAndroid Build Coastguard Worker                   clEnumValN(AC_Disassemble, "disassemble",
34*9880d681SAndroid Build Coastguard Worker                              "Disassemble strings of hex bytes"),
35*9880d681SAndroid Build Coastguard Worker                   clEnumValEnd));
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string>
38*9880d681SAndroid Build Coastguard Worker     TripleName("triple", cl::desc("Target triple to assemble for, "
39*9880d681SAndroid Build Coastguard Worker                                   "see -version for available targets"));
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string>
42*9880d681SAndroid Build Coastguard Worker     MCPU("mcpu",
43*9880d681SAndroid Build Coastguard Worker          cl::desc("Target a specific cpu type (-mcpu=help for details)"),
44*9880d681SAndroid Build Coastguard Worker          cl::value_desc("cpu-name"), cl::init(""));
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker // This is useful for variable-length instruction sets.
47*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned> InsnLimit(
48*9880d681SAndroid Build Coastguard Worker     "insn-limit",
49*9880d681SAndroid Build Coastguard Worker     cl::desc("Limit the number of instructions to process (0 for no limit)"),
50*9880d681SAndroid Build Coastguard Worker     cl::value_desc("count"), cl::init(0));
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker static cl::list<std::string>
53*9880d681SAndroid Build Coastguard Worker     MAttrs("mattr", cl::CommaSeparated,
54*9880d681SAndroid Build Coastguard Worker            cl::desc("Target specific attributes (-mattr=help for details)"),
55*9880d681SAndroid Build Coastguard Worker            cl::value_desc("a1,+a2,-a3,..."));
56*9880d681SAndroid Build Coastguard Worker // The feature string derived from -mattr's values.
57*9880d681SAndroid Build Coastguard Worker std::string FeaturesStr;
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker static cl::list<std::string>
60*9880d681SAndroid Build Coastguard Worker     FuzzerArgs("fuzzer-args", cl::Positional,
61*9880d681SAndroid Build Coastguard Worker                cl::desc("Options to pass to the fuzzer"), cl::ZeroOrMore,
62*9880d681SAndroid Build Coastguard Worker                cl::PositionalEatsArgs);
63*9880d681SAndroid Build Coastguard Worker static std::vector<char *> ModifiedArgv;
64*9880d681SAndroid Build Coastguard Worker 
DisassembleOneInput(const uint8_t * Data,size_t Size)65*9880d681SAndroid Build Coastguard Worker int DisassembleOneInput(const uint8_t *Data, size_t Size) {
66*9880d681SAndroid Build Coastguard Worker   char AssemblyText[AssemblyTextBufSize];
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   std::vector<uint8_t> DataCopy(Data, Data + Size);
69*9880d681SAndroid Build Coastguard Worker 
70*9880d681SAndroid Build Coastguard Worker   LLVMDisasmContextRef Ctx = LLVMCreateDisasmCPUFeatures(
71*9880d681SAndroid Build Coastguard Worker       TripleName.c_str(), MCPU.c_str(), FeaturesStr.c_str(), nullptr, 0,
72*9880d681SAndroid Build Coastguard Worker       nullptr, nullptr);
73*9880d681SAndroid Build Coastguard Worker   assert(Ctx);
74*9880d681SAndroid Build Coastguard Worker   uint8_t *p = DataCopy.data();
75*9880d681SAndroid Build Coastguard Worker   unsigned Consumed;
76*9880d681SAndroid Build Coastguard Worker   unsigned InstructionsProcessed = 0;
77*9880d681SAndroid Build Coastguard Worker   do {
78*9880d681SAndroid Build Coastguard Worker     Consumed = LLVMDisasmInstruction(Ctx, p, Size, 0, AssemblyText,
79*9880d681SAndroid Build Coastguard Worker                                      AssemblyTextBufSize);
80*9880d681SAndroid Build Coastguard Worker     Size -= Consumed;
81*9880d681SAndroid Build Coastguard Worker     p += Consumed;
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker     InstructionsProcessed ++;
84*9880d681SAndroid Build Coastguard Worker     if (InsnLimit != 0 && InstructionsProcessed < InsnLimit)
85*9880d681SAndroid Build Coastguard Worker       break;
86*9880d681SAndroid Build Coastguard Worker   } while (Consumed != 0);
87*9880d681SAndroid Build Coastguard Worker   LLVMDisasmDispose(Ctx);
88*9880d681SAndroid Build Coastguard Worker   return 0;
89*9880d681SAndroid Build Coastguard Worker }
90*9880d681SAndroid Build Coastguard Worker 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)91*9880d681SAndroid Build Coastguard Worker int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
92*9880d681SAndroid Build Coastguard Worker   if (Action == AC_Assemble)
93*9880d681SAndroid Build Coastguard Worker     errs() << "error: -assemble is not implemented\n";
94*9880d681SAndroid Build Coastguard Worker   else if (Action == AC_Disassemble)
95*9880d681SAndroid Build Coastguard Worker     return DisassembleOneInput(Data, Size);
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Unknown action");
98*9880d681SAndroid Build Coastguard Worker   return 0;
99*9880d681SAndroid Build Coastguard Worker }
100*9880d681SAndroid Build Coastguard Worker 
LLVMFuzzerInitialize(int * argc,char *** argv)101*9880d681SAndroid Build Coastguard Worker int LLVMFuzzerInitialize(int *argc, char ***argv) {
102*9880d681SAndroid Build Coastguard Worker   // The command line is unusual compared to other fuzzers due to the need to
103*9880d681SAndroid Build Coastguard Worker   // specify the target. Options like -triple, -mcpu, and -mattr work like
104*9880d681SAndroid Build Coastguard Worker   // their counterparts in llvm-mc, while -fuzzer-args collects options for the
105*9880d681SAndroid Build Coastguard Worker   // fuzzer itself.
106*9880d681SAndroid Build Coastguard Worker   //
107*9880d681SAndroid Build Coastguard Worker   // Examples:
108*9880d681SAndroid Build Coastguard Worker   //
109*9880d681SAndroid Build Coastguard Worker   // Fuzz the big-endian MIPS32R6 disassembler using 100,000 inputs of up to
110*9880d681SAndroid Build Coastguard Worker   // 4-bytes each and use the contents of ./corpus as the test corpus:
111*9880d681SAndroid Build Coastguard Worker   //   llvm-mc-fuzzer -triple mips-linux-gnu -mcpu=mips32r6 -disassemble \
112*9880d681SAndroid Build Coastguard Worker   //       -fuzzer-args -max_len=4 -runs=100000 ./corpus
113*9880d681SAndroid Build Coastguard Worker   //
114*9880d681SAndroid Build Coastguard Worker   // Infinitely fuzz the little-endian MIPS64R2 disassembler with the MSA
115*9880d681SAndroid Build Coastguard Worker   // feature enabled using up to 64-byte inputs:
116*9880d681SAndroid Build Coastguard Worker   //   llvm-mc-fuzzer -triple mipsel-linux-gnu -mcpu=mips64r2 -mattr=msa \
117*9880d681SAndroid Build Coastguard Worker   //       -disassemble -fuzzer-args ./corpus
118*9880d681SAndroid Build Coastguard Worker   //
119*9880d681SAndroid Build Coastguard Worker   // If your aim is to find instructions that are not tested, then it is
120*9880d681SAndroid Build Coastguard Worker   // advisable to constrain the maximum input size to a single instruction
121*9880d681SAndroid Build Coastguard Worker   // using -max_len as in the first example. This results in a test corpus of
122*9880d681SAndroid Build Coastguard Worker   // individual instructions that test unique paths. Without this constraint,
123*9880d681SAndroid Build Coastguard Worker   // there will be considerable redundancy in the corpus.
124*9880d681SAndroid Build Coastguard Worker 
125*9880d681SAndroid Build Coastguard Worker   char **OriginalArgv = *argv;
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker   LLVMInitializeAllTargetInfos();
128*9880d681SAndroid Build Coastguard Worker   LLVMInitializeAllTargetMCs();
129*9880d681SAndroid Build Coastguard Worker   LLVMInitializeAllDisassemblers();
130*9880d681SAndroid Build Coastguard Worker 
131*9880d681SAndroid Build Coastguard Worker   cl::ParseCommandLineOptions(*argc, OriginalArgv);
132*9880d681SAndroid Build Coastguard Worker 
133*9880d681SAndroid Build Coastguard Worker   // Rebuild the argv without the arguments llvm-mc-fuzzer consumed so that
134*9880d681SAndroid Build Coastguard Worker   // the driver can parse its arguments.
135*9880d681SAndroid Build Coastguard Worker   //
136*9880d681SAndroid Build Coastguard Worker   // FuzzerArgs cannot provide the non-const pointer that OriginalArgv needs.
137*9880d681SAndroid Build Coastguard Worker   // Re-use the strings from OriginalArgv instead of copying FuzzerArg to a
138*9880d681SAndroid Build Coastguard Worker   // non-const buffer to avoid the need to clean up when the fuzzer terminates.
139*9880d681SAndroid Build Coastguard Worker   ModifiedArgv.push_back(OriginalArgv[0]);
140*9880d681SAndroid Build Coastguard Worker   for (const auto &FuzzerArg : FuzzerArgs) {
141*9880d681SAndroid Build Coastguard Worker     for (int i = 1; i < *argc; ++i) {
142*9880d681SAndroid Build Coastguard Worker       if (FuzzerArg == OriginalArgv[i])
143*9880d681SAndroid Build Coastguard Worker         ModifiedArgv.push_back(OriginalArgv[i]);
144*9880d681SAndroid Build Coastguard Worker     }
145*9880d681SAndroid Build Coastguard Worker   }
146*9880d681SAndroid Build Coastguard Worker   *argc = ModifiedArgv.size();
147*9880d681SAndroid Build Coastguard Worker   *argv = ModifiedArgv.data();
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker   // Package up features to be passed to target/subtarget
150*9880d681SAndroid Build Coastguard Worker   // We have to pass it via a global since the callback doesn't
151*9880d681SAndroid Build Coastguard Worker   // permit any user data.
152*9880d681SAndroid Build Coastguard Worker   if (MAttrs.size()) {
153*9880d681SAndroid Build Coastguard Worker     SubtargetFeatures Features;
154*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i != MAttrs.size(); ++i)
155*9880d681SAndroid Build Coastguard Worker       Features.AddFeature(MAttrs[i]);
156*9880d681SAndroid Build Coastguard Worker     FeaturesStr = Features.getString();
157*9880d681SAndroid Build Coastguard Worker   }
158*9880d681SAndroid Build Coastguard Worker 
159*9880d681SAndroid Build Coastguard Worker   return 0;
160*9880d681SAndroid Build Coastguard Worker }
161