Skip to content

Commit

Permalink
llvm-isel-fuzzer: Handle a subset of backend flags in the executable …
Browse files Browse the repository at this point in the history
…name

Here we add a secondary option parser to llvm-isel-fuzzer (and provide
it for use with other fuzzers). With this, you can copy the fuzzer to
a name like llvm-isel-fuzzer:aarch64-gisel for a fuzzer that fuzzer
AArch64 with GlobalISel enabled, or fuzzer:x86_64 to fuzz x86, with no
flags required. This should be useful for running these in OSS-Fuzz.

Note that this handrolls a subset of cl::opts to recognize, rather
than embedding a complete command parser for argv[0]. If we find we
really need the flexibility of handling arbitrary options at some
point we can rethink this.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315545 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
bogner committed Oct 12, 2017
1 parent 89b77ce commit 58e4a84
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 1 deletion.
7 changes: 7 additions & 0 deletions docs/FuzzingLLVM.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ the following command would fuzz AArch64 with :doc:`GlobalISel`:
% bin/llvm-isel-fuzzer <corpus-dir> -ignore_remaining_args=1 -mtriple aarch64 -global-isel -O0
Some flags can also be specified in the binary name itself in order to support
OSS Fuzz, which has trouble with required arguments. To do this, you can copy
or move ``llvm-isel-fuzzer`` to ``llvm-isel-fuzzer:x-y-z``, where x, y, and z
are architecture names (``aarch64``, ``x86_64``), optimization levels (``O0``,
``O2``), or specific keywords like ``gisel`` for enabling global instruction
selection.

llvm-mc-assemble-fuzzer
-----------------------

Expand Down
12 changes: 12 additions & 0 deletions include/llvm/FuzzMutate/FuzzerCLI.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef LLVM_FUZZMUTATE_FUZZER_CLI_H
#define LLVM_FUZZMUTATE_FUZZER_CLI_H

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"

namespace llvm {
Expand All @@ -24,6 +25,17 @@ namespace llvm {
/// This handles all arguments after -ignore_remaining_args=1 as cl::opts.
void parseFuzzerCLOpts(int ArgC, char *ArgV[]);

/// Handle backend options that are encoded in the executable name.
///
/// Parses some common backend options out of a specially crafted executable
/// name (argv[0]). For example, a name like llvm-foo-fuzzer:aarch64-gisel might
/// set up an AArch64 triple and the Global ISel selector. This should be called
/// *before* parseFuzzerCLOpts if calling both.
///
/// This is meant to be used for environments like OSS-Fuzz that aren't capable
/// of passing in command line arguments in the normal way.
void handleExecNameEncodedBEOpts(StringRef ExecName);

using FuzzerTestFun = int (*)(const uint8_t *Data, size_t Size);
using FuzzerInitFun = int (*)(int *argc, char ***argv);

Expand Down
38 changes: 37 additions & 1 deletion lib/FuzzMutate/FuzzerCLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//

#include "llvm/FuzzMutate/FuzzerCLI.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Error.h"
Expand All @@ -31,6 +31,42 @@ void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) {
cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
}

void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) {
std::vector<std::string> Args{ExecName};

auto NameAndArgs = ExecName.split(':');
if (NameAndArgs.second.empty())
return;

SmallVector<StringRef, 4> Opts;
NameAndArgs.second.split(Opts, '-');
for (StringRef Opt : Opts) {
if (Opt.equals("gisel")) {
Args.push_back("-global-isel");
// For now we default GlobalISel to -O0
Args.push_back("-O0");
} else if (Opt.startswith("O")) {
Args.push_back("-" + Opt.str());
} else if (auto Arch = Triple::getArchTypeForLLVMName(Opt)) {
Args.push_back("-mtriple=" + Opt.str());
} else {
errs() << ExecName << ": Unknown option: " << Opt << ".\n";
exit(1);
}
}
errs() << NameAndArgs.first << ": Injected args:";
for (int I = 1, E = Args.size(); I < E; ++I)
errs() << " " << Args[I];
errs() << "\n";

std::vector<const char *> CLArgs;
CLArgs.reserve(Args.size());
for (std::string &S : Args)
CLArgs.push_back(S.c_str());

cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
}

int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
FuzzerInitFun Init) {
errs() << "*** This tool was not linked to libFuzzer.\n"
Expand Down
15 changes: 15 additions & 0 deletions test/tools/llvm-isel-fuzzer/aarch64-execname-options.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; REQUIRES: aarch64-registered-target

; RUN: echo > %t.input

; RUN: cp llvm-isel-fuzzer %t.bin:aarch64
; RUN: %t.bin:aarch64 %t.input 2>&1 | FileCheck -check-prefix=AARCH64 %s
; AARCH64: Injected args: -mtriple=aarch64

; RUN: mv %t.bin:aarch64 %t.bin:aarch64-O1
; RUN: %t.bin:aarch64-O1 %t.input 2>&1 | FileCheck -check-prefix=OPT-AFTER %s
; OPT-AFTER: Injected args: -mtriple=aarch64 -O1

; RUN: mv %t.bin:aarch64-O1 %t.bin:O3-aarch64
; RUN: %t.bin:O3-aarch64 %t.input 2>&1 | FileCheck -check-prefix=OPT-BEFORE %s
; OPT-BEFORE: Injected args: -O3 -mtriple=aarch64
15 changes: 15 additions & 0 deletions test/tools/llvm-isel-fuzzer/execname-options.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; RUN: echo > %t.input

; RUN: cp llvm-isel-fuzzer %t.bin:gisel
; RUN: not %t.bin:gisel %t.input 2>&1 | FileCheck -check-prefix=GISEL %s
; GISEL: Injected args: -global-isel -O0
; GISEL: -mtriple must be specified

; RUN: cp llvm-isel-fuzzer %t.bin:gisel-O2
; RUN: not %t.bin:gisel-O2 %t.input 2>&1 | FileCheck -check-prefix=GISEL-O2 %s
; GISEL-O2: Injected args: -global-isel -O0 -O2
; GISEL-O2: -mtriple must be specified

; RUN: cp llvm-isel-fuzzer %t.bin:unexist
; RUN: not %t.bin:unexist %t.input 2>&1 | FileCheck -check-prefix=NO-OPT %s
; NO-OPT: Unknown option:
1 change: 1 addition & 0 deletions tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(int *argc,
InitializeAllAsmPrinters();
InitializeAllAsmParsers();

handleExecNameEncodedBEOpts(*argv[0]);
parseFuzzerCLOpts(*argc, *argv);

if (TargetTriple.empty()) {
Expand Down

0 comments on commit 58e4a84

Please sign in to comment.