diff options
author | Emmett Neyman <eneyman@google.com> | 2018-06-22 18:05:00 +0000 |
---|---|---|
committer | Emmett Neyman <eneyman@google.com> | 2018-06-22 18:05:00 +0000 |
commit | e5f4a9ff7675c7207be84f448a2cf005e8edf363 (patch) | |
tree | 13c57bf5304f7fc4e19d68f17ea5d3785254224a /clang/tools/clang-fuzzer/proto-to-llvm | |
parent | cd18bb523ce7b5840d69252d954a88c78825072a (diff) | |
download | bcm5719-llvm-e5f4a9ff7675c7207be84f448a2cf005e8edf363.tar.gz bcm5719-llvm-e5f4a9ff7675c7207be84f448a2cf005e8edf363.zip |
Implemented proto to LLVM conversion and LLVM fuzz target
Differential Revision: https://reviews.llvm.org/D48106
llvm-svn: 335374
Diffstat (limited to 'clang/tools/clang-fuzzer/proto-to-llvm')
4 files changed, 224 insertions, 0 deletions
diff --git a/clang/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt b/clang/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt new file mode 100644 index 00000000000..ae58523f227 --- /dev/null +++ b/clang/tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD}) +set(CMAKE_CXX_FLAGS ${CXX_FLAGS_NOFUZZ}) + +# Needed by LLVM's CMake checks because this file defines multiple targets. +set(LLVM_OPTIONAL_SOURCES loop_proto_to_llvm.cpp loop_proto_to_llvm_main.cpp) + +add_clang_library(clangLoopProtoToLLVM loop_proto_to_llvm.cpp + DEPENDS clangCXXLoopProto + LINK_LIBS clangCXXLoopProto ${PROTOBUF_LIBRARIES} + ) + +add_clang_executable(clang-loop-proto-to-llvm loop_proto_to_llvm_main.cpp) + +target_link_libraries(clang-loop-proto-to-llvm PRIVATE clangLoopProtoToLLVM) diff --git a/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp b/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp new file mode 100644 index 00000000000..16dbcb7b49b --- /dev/null +++ b/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp @@ -0,0 +1,156 @@ +//==-- loop_proto_to_llvm.cpp - Protobuf-C++ conversion +//---------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements functions for converting between protobufs and LLVM IR. +// +// +//===----------------------------------------------------------------------===// + +#include "loop_proto_to_llvm.h" +#include "cxx_loop_proto.pb.h" + +// The following is needed to convert protos in human-readable form +#include <google/protobuf/text_format.h> + +#include <ostream> +#include <sstream> + +namespace clang_fuzzer { + +// Forward decls +std::string BinopToString(std::ostream &os, const BinaryOp &x); +std::string StateSeqToString(std::ostream &os, const StatementSeq &x); + +// Counter variable to generate new LLVM IR variable names and wrapper function +std::string get_var() { + static int ctr = 0; + return "%var" + std::to_string(ctr++); +} + +// Proto to LLVM. + +std::string ConstToString(const Const &x) { + return std::to_string(x.val()); +} +std::string VarRefToString(std::ostream &os, const VarRef &x) { + std::string arr; + switch(x.arr()) { + case VarRef::ARR_A: + arr = "%a"; + break; + case VarRef::ARR_B: + arr = "%b"; + break; + case VarRef::ARR_C: + arr = "%c"; + break; + } + std::string ptr_var = get_var(); + os << ptr_var << " = getelementptr i32, i32* " << arr << ", i64 %ct\n"; + return ptr_var; +} +std::string RvalueToString(std::ostream &os, const Rvalue &x) { + if(x.has_cons()) + return ConstToString(x.cons()); + if(x.has_binop()) + return BinopToString(os, x.binop()); + if(x.has_varref()) { + std::string var_ref = VarRefToString(os, x.varref()); + std::string val_var = get_var(); + os << val_var << " = load i32, i32* " << var_ref << "\n"; + return val_var; + } + return "1"; + +} +std::string BinopToString(std::ostream &os, const BinaryOp &x) { + std::string left = RvalueToString(os, x.left()); + std::string right = RvalueToString(os, x.right()); + std::string op; + switch (x.op()) { + case BinaryOp::PLUS: + op = "add"; + break; + case BinaryOp::MINUS: + op = "sub"; + break; + case BinaryOp::MUL: + op = "mul"; + break; + case BinaryOp::XOR: + op = "xor"; + break; + case BinaryOp::AND: + op = "and"; + break; + case BinaryOp::OR: + op = "or"; + break; + // Support for Boolean operators will be added later + case BinaryOp::EQ: + case BinaryOp::NE: + case BinaryOp::LE: + case BinaryOp::GE: + case BinaryOp::LT: + case BinaryOp::GT: + op = "add"; + break; + } + std::string val_var = get_var(); + os << val_var << " = " << op << " i32 " << left << ", " << right << "\n"; + return val_var; +} +std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { + std::string rvalue = RvalueToString(os, x.rvalue()); + std::string var_ref = VarRefToString(os, x.varref()); + return os << "store i32 " << rvalue << ", i32* " << var_ref << "\n"; +} +std::ostream &operator<<(std::ostream &os, const Statement &x) { + return os << x.assignment(); +} +std::ostream &operator<<(std::ostream &os, const StatementSeq &x) { + for (auto &st : x.statements()) { + os << st; + } + return os; +} +std::ostream &operator<<(std::ostream &os, const LoopFunction &x) { + return os << "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n" + << "%i = alloca i64\n" + << "store i64 0, i64* %i\n" + << "br label %loop\n\n" + << "loop:\n" + << "%ct = load i64, i64* %i\n" + << "%comp = icmp eq i64 %ct, %s\n" + << "br i1 %comp, label %endloop, label %body\n\n" + << "body:\n" + << x.statements() + << "%z = add i64 1, %ct\n" + << "store i64 %z, i64* %i\n" + << "br label %loop\n\n" + << "endloop:\n" + << "ret void\n}\n"; +} + +// --------------------------------- + +std::string LoopFunctionToLLVMString(const LoopFunction &input) { + std::ostringstream os; + os << input; + return os.str(); +} +std::string LoopProtoToLLVM(const uint8_t *data, size_t size) { + LoopFunction message; + if (!message.ParsePartialFromArray(data, size)) + return "#error invalid proto\n"; + return LoopFunctionToLLVMString(message); +} + +} // namespace clang_fuzzer diff --git a/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h b/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h new file mode 100644 index 00000000000..51660fcb710 --- /dev/null +++ b/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h @@ -0,0 +1,23 @@ +//==-- loop_proto_to_llvm.h - Protobuf-C++ conversion ----------------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines functions for converting between protobufs and LLVM IR. +// +//===----------------------------------------------------------------------===// + +#include <cstdint> +#include <cstddef> +#include <string> + +namespace clang_fuzzer { +class LoopFunction; + +std::string LoopFunctionToLLVMString(const LoopFunction &input); +std::string LoopProtoToLLVM(const uint8_t *data, size_t size); +} diff --git a/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp b/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp new file mode 100644 index 00000000000..17ca15ec27f --- /dev/null +++ b/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp @@ -0,0 +1,31 @@ +//==-- loop_proto_to_llvm_main.cpp - Driver for protobuf-LLVM conversion----==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements a simple driver to print a LLVM program from a protobuf with loops +// +//===----------------------------------------------------------------------===// + + +#include <fstream> +#include <iostream> +#include <streambuf> +#include <string> + +#include "loop_proto_to_llvm.h" + +int main(int argc, char **argv) { + for (int i = 1; i < argc; i++) { + std::fstream in(argv[i]); + std::string str((std::istreambuf_iterator<char>(in)), + std::istreambuf_iterator<char>()); + std::cout << ";; " << argv[i] << std::endl; + std::cout << clang_fuzzer::LoopProtoToLLVM( + reinterpret_cast<const uint8_t *>(str.data()), str.size()); + } +} |