forked from OSchip/llvm-project
llvm-mc-fuzzer: A fuzzing tool for the MC layer.
Summary: Only the disassembler is supported in this patch but it has already found a few issues in the Mips disassembler (mostly invalid instructions being successfully disassembled). Reviewers: kcc Subscribers: russell.gallop, silvas, kcc, llvm-commits Differential Revision: http://reviews.llvm.org/D12723 llvm-svn: 247786
This commit is contained in:
parent
d926465342
commit
205d1993bb
|
@ -453,7 +453,14 @@ Trophies
|
|||
|
||||
* llvm-as: https://llvm.org/bugs/show_bug.cgi?id=24639
|
||||
|
||||
|
||||
* Disassembler:
|
||||
* Mips: Discovered a number of untested instructions for the Mips target
|
||||
(see valid-mips*.s in http://reviews.llvm.org/rL247405,
|
||||
http://reviews.llvm.org/rL247414, http://reviews.llvm.org/rL247416,
|
||||
http://reviews.llvm.org/rL247417, http://reviews.llvm.org/rL247420,
|
||||
and http://reviews.llvm.org/rL247422) as well some instructions that
|
||||
successfully disassembled on ISA's where they were not valid (see
|
||||
invalid-xfail.s files in the same commits).
|
||||
|
||||
.. _pcre2: http://www.pcre.org/
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
if( LLVM_USE_SANITIZE_COVERAGE )
|
||||
include_directories(BEFORE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/Fuzzer)
|
||||
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
AllTargetsDescs
|
||||
AllTargetsDisassemblers
|
||||
AllTargetsInfos
|
||||
MC
|
||||
MCDisassembler
|
||||
Support
|
||||
)
|
||||
add_llvm_tool(llvm-mc-fuzzer
|
||||
llvm-mc-fuzzer.cpp)
|
||||
target_link_libraries(llvm-mc-fuzzer
|
||||
LLVMFuzzerNoMain
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,129 @@
|
|||
//===--- llvm-mc-fuzzer.cpp - Fuzzer for the MC layer ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm-c/Disassembler.h"
|
||||
#include "llvm-c/Target.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/MC/SubtargetFeature.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "FuzzerInterface.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
const unsigned AssemblyTextBufSize = 80;
|
||||
|
||||
enum ActionType {
|
||||
AC_Assemble,
|
||||
AC_Disassemble
|
||||
};
|
||||
|
||||
static cl::opt<ActionType>
|
||||
Action(cl::desc("Action to perform:"),
|
||||
cl::init(AC_Assemble),
|
||||
cl::values(clEnumValN(AC_Assemble, "assemble",
|
||||
"Assemble a .s file (default)"),
|
||||
clEnumValN(AC_Disassemble, "disassemble",
|
||||
"Disassemble strings of hex bytes"),
|
||||
clEnumValEnd));
|
||||
|
||||
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::list<std::string>
|
||||
MAttrs("mattr", cl::CommaSeparated,
|
||||
cl::desc("Target specific attributes (-mattr=help for details)"),
|
||||
cl::value_desc("a1,+a2,-a3,..."));
|
||||
// The feature string derived from -mattr's values.
|
||||
std::string FeaturesStr;
|
||||
|
||||
static cl::list<std::string>
|
||||
FuzzerArgv("fuzzer-args", cl::Positional,
|
||||
cl::desc("Options to pass to the fuzzer"), cl::ZeroOrMore,
|
||||
cl::PositionalEatsArgs);
|
||||
|
||||
void 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;
|
||||
do {
|
||||
Consumed = LLVMDisasmInstruction(Ctx, p, Size, 0, AssemblyText,
|
||||
AssemblyTextBufSize);
|
||||
Size -= Consumed;
|
||||
p += Consumed;
|
||||
} while (Consumed != 0);
|
||||
LLVMDisasmDispose(Ctx);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// The command line is unusual compared to other fuzzers due to the need to
|
||||
// specify the target. Options like -triple, -mcpu, and -mattr work like
|
||||
// their counterparts in llvm-mc, while -fuzzer-args collects options for the
|
||||
// fuzzer itself.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// Fuzz the big-endian MIPS32R6 disassembler using 100,000 inputs of up to
|
||||
// 4-bytes each and use the contents of ./corpus as the test corpus:
|
||||
// llvm-mc-fuzzer -triple mips-linux-gnu -mcpu=mips32r6 -disassemble \
|
||||
// -fuzzer-args -max_len=4 -runs=100000 ./corpus
|
||||
//
|
||||
// Infinitely fuzz the little-endian MIPS64R2 disassembler with the MSA
|
||||
// feature enabled using up to 64-byte inputs:
|
||||
// llvm-mc-fuzzer -triple mipsel-linux-gnu -mcpu=mips64r2 -mattr=msa \
|
||||
// -disassemble -fuzzer-args ./corpus
|
||||
//
|
||||
// If your aim is to find instructions that are not tested, then it is
|
||||
// advisable to constrain the maximum input size to a single instruction
|
||||
// using -max_len as in the first example. This results in a test corpus of
|
||||
// individual instructions that test unique paths. Without this constraint,
|
||||
// there will be considerable redundancy in the corpus.
|
||||
|
||||
LLVMInitializeAllTargetInfos();
|
||||
LLVMInitializeAllTargetMCs();
|
||||
LLVMInitializeAllDisassemblers();
|
||||
|
||||
cl::ParseCommandLineOptions(argc, argv);
|
||||
|
||||
// Package up features to be passed to target/subtarget
|
||||
// We have to pass it via a global since the callback doesn't
|
||||
// permit any user data.
|
||||
if (MAttrs.size()) {
|
||||
SubtargetFeatures Features;
|
||||
for (unsigned i = 0; i != MAttrs.size(); ++i)
|
||||
Features.AddFeature(MAttrs[i]);
|
||||
FeaturesStr = Features.getString();
|
||||
}
|
||||
|
||||
// Insert the program name into the FuzzerArgv.
|
||||
FuzzerArgv.insert(FuzzerArgv.begin(), argv[0]);
|
||||
|
||||
if (Action == AC_Assemble)
|
||||
errs() << "error: -assemble is not implemented\n";
|
||||
else if (Action == AC_Disassemble)
|
||||
return fuzzer::FuzzerDriver(FuzzerArgv, DisassembleOneInput);
|
||||
|
||||
llvm_unreachable("Unknown action");
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue