#include "llvm-c/Disassembler.h"
#include "llvm-c/Target.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
const unsigned AssemblyTextBufSize = 80;
static cl::opt<std::string>
TripleName("triple", cl::desc("Target triple to assemble for, "
"see -version for available targets"));
static cl::opt<std::string>
MCPU("mcpu",
cl::desc("Target a specific cpu type (-mcpu=help for details)"),
cl::value_desc("cpu-name"), cl::init(""));
static cl::opt<unsigned> InsnLimit(
"insn-limit",
cl::desc("Limit the number of instructions to process (0 for no limit)"),
cl::value_desc("count"), cl::init(0));
static cl::list<std::string>
MAttrs("mattr", cl::CommaSeparated,
cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,..."));
std::string FeaturesStr;
static cl::list<std::string>
FuzzerArgs("fuzzer-args", cl::Positional,
cl::desc("Options to pass to the fuzzer"),
cl::PositionalEatsArgs);
static std::vector<char *> ModifiedArgv;
int DisassembleOneInput(const uint8_t *Data, size_t Size) {
char AssemblyText[AssemblyTextBufSize];
std::vector<uint8_t> DataCopy(Data, Data + Size);
LLVMDisasmContextRef Ctx = LLVMCreateDisasmCPUFeatures(
TripleName.c_str(), MCPU.c_str(), FeaturesStr.c_str(), nullptr, 0,
nullptr, nullptr);
assert(Ctx);
uint8_t *p = DataCopy.data();
unsigned Consumed;
unsigned InstructionsProcessed = 0;
do {
Consumed = LLVMDisasmInstruction(Ctx, p, Size, 0, AssemblyText,
AssemblyTextBufSize);
Size -= Consumed;
p += Consumed;
InstructionsProcessed ++;
if (InsnLimit != 0 && InstructionsProcessed < InsnLimit)
break;
} while (Consumed != 0);
LLVMDisasmDispose(Ctx);
return 0;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return DisassembleOneInput(Data, Size);
}
extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(int *argc,
char ***argv) {
char **OriginalArgv = *argv;
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();
cl::ParseCommandLineOptions(*argc, OriginalArgv);
ModifiedArgv.push_back(OriginalArgv[0]);
for (const auto &FuzzerArg : FuzzerArgs) {
for (int i = 1; i < *argc; ++i) {
if (FuzzerArg == OriginalArgv[i])
ModifiedArgv.push_back(OriginalArgv[i]);
}
}
*argc = ModifiedArgv.size();
*argv = ModifiedArgv.data();
if (MAttrs.size()) {
SubtargetFeatures Features;
for (unsigned i = 0; i != MAttrs.size(); ++i)
Features.AddFeature(MAttrs[i]);
FeaturesStr = Features.getString();
}
if (TripleName.empty())
TripleName = sys::getDefaultTargetTriple();
return 0;
}