Page MenuHomePhabricator

Implement llvm-isel-fuzzer for fuzzing instruction selection
ClosedPublic

Authored by bogner on Aug 3 2017, 11:02 AM.

Details

Reviewers
kcc
bogner
Summary

This implements a fuzzer tool for instruction selection, as described in my EuroLLVM 2017 talk.

The fuzzer must be given both libFuzzer args and llc-like args to configure the backend. For example, to fuzz AArch64 GlobalISel at -O0, you could invoke like so:

llvm-isel-fuzzer <corpus dirs> -ignore_remaining_args=1 \
                 -mtriple arm64-apple-ios -global-isel -O0

If you would like to seed the fuzzer with an initial corpus, simply provide a directory of valid LLVM bitcode (not textual IR) as one of the corpus dirs.

Diff Detail

Event Timeline

bogner created this revision.Aug 3 2017, 11:02 AM
kcc added inline comments.Aug 3 2017, 1:08 PM
tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
112

You assume that libFuzzer will feed "\n" as a dummy input.
But this is not part of the contract.

118

currently the non-zero return value for LLVMFuzzerTestOneInput will call an error in libFuzzer.
Also, an ideal fuzz target must tolerate any kind of input, even if we never expect to see it.

kcc added inline comments.Aug 3 2017, 1:17 PM
tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
100

Will it be simpler and better to just assume that Size <= 1 is uninteresting and means a new module?

bogner updated this revision to Diff 109634.Aug 3 2017, 2:15 PM
bogner marked 3 inline comments as done.
bogner added inline comments.
tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
100

Makes sense, I'll do that.

118

Calling an error is kind of the point here. We get here when the mutator can't do any work (due to MutateImpl giving up and returning ' ', which is also not part of the contract), but to return 0 would mean we just spin forever doing nothing rather than alert the user that there's a problem.

That said, this is much less of a problem now that the default max_len was bumped to 4096. When it was 64 you'd hit this very quickly if you forgot to override that. I'm fairly comfortable just returning zero here now, I think.

kcc edited edge metadata.Aug 11 2017, 1:24 PM

LGTM from fuzzing POV, let's see how this works.

Do you want me to also review https://reviews.llvm.org/D36274?
(I can't promise a detailed one until after Aug 21)

bogner accepted this revision.Aug 28 2017, 5:24 PM
This revision is now accepted and ready to land.Aug 28 2017, 5:24 PM
bogner closed this revision.Aug 28 2017, 5:24 PM

r311964

kcc added a comment.Aug 28 2017, 6:37 PM

I've run ./bin/llvm-isel-fuzzer -ignore_remaining_args=1 -mtriple x86_64-unknown-linux-gnu for a few minutes and I got this:

25482==ERROR: AddressSanitizer: use-after-poison on address 0x621001698040 at pc 0x00000086c29f bp 0x7ffe31189870 sp 0x7ffe31189868

READ of size 8 at 0x621001698040 thread T0

#0 0x86c29e in llvm::SDNode::use_empty() const /usr/local/google/home/kcc/llvm/include/llvm/CodeGen/SelectionDAGNodes.h:666:35
#1 0x39bea98 in (anonymous namespace)::DAGCombiner::useDivRem(llvm::SDNode*) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:2778:31
#2 0x393fb48 in (anonymous namespace)::DAGCombiner::visitSDIV(llvm::SDNode*) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:2912:26
#3 0x392b092 in (anonymous namespace)::DAGCombiner::visit(llvm::SDNode*) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1488:40
#4 0x3929270 in (anonymous namespace)::DAGCombiner::combine(llvm::SDNode*) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1579:16
#5 0x3927a83 in (anonymous namespace)::DAGCombiner::Run(llvm::CombineLevel) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1427:18
#6 0x39268f9 in llvm::SelectionDAG::Combine(llvm::CombineLevel, llvm::AAResults*, llvm::CodeGenOpt::Level) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:17450:36
#7 0x3c43f89 in llvm::SelectionDAGISel::CodeGenAndEmitDAG() /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:744:13
#8 0x3c43654 in llvm::SelectionDAGISel::SelectBasicBlock(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, true>, llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, true>, bool&) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:665:3
#9 0x3c42a8d in llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1609:7
#10 0x3c3de2f in llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) /usr/local/google/home/kcc/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:466:3

Impressive.
Let's get it to oss-fuzz!
(But as we discussed, need to encode the options in the binary name somehow)