| Index: include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h
|
| diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h b/include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2281a222a8a43fb8db1cc39fd3196db69bc92031
|
| --- /dev/null
|
| +++ b/include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h
|
| @@ -0,0 +1,286 @@
|
| +//===- NaClBitcodeMunge.h - Bitcode Munger ----------------------*- C++ -*-===//
|
| +//
|
| +// The LLVM Compiler Infrastructure
|
| +//
|
| +// This file is distributed under the University of Illinois Open Source
|
| +// License. See LICENSE.TXT for details.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +//
|
| +// Test harness for generating a PNaCl bitcode memory buffer from
|
| +// an array, and parse/objdump the resulting contents.
|
| +//
|
| +// Generates a bitcode memory buffer from an array containing 1 or
|
| +// more PNaCl records. Used to test errors in PNaCl bitcode.
|
| +//
|
| +// For simplicity of API, we model records as an array of uint64_t. To
|
| +// specify the end of a record in the array, a special "terminator"
|
| +// value is used. This terminator value must be a uint64_t value that
|
| +// is not used by any of the records.
|
| +//
|
| +// A record is defined as a sequence of integers consisting of:
|
| +// * The abbreviation index associated with the record.
|
| +// * The record code associated with the record.
|
| +// * The sequence of values associated with the record code.
|
| +// * The terminator value.
|
| +//
|
| +// Note: Since the header record doesn't have any abbreviation indices
|
| +// associated with it, one can use any value. The value will simply be
|
| +// ignored.
|
| +//
|
| +// In addition to specifying the sequence of records, one can also
|
| +// define a sequence of edits to be applied to the original sequence
|
| +// of records. This allows the same record sequence to be used in
|
| +// multiple tests.
|
| +//
|
| +// An edit consists of:
|
| +//
|
| +// * A record number defining where the edit is to be applied.
|
| +// * An action defining the type of edit.
|
| +// * An optional record associated with the action.
|
| +//
|
| +// Note that edits must be sorted by record number, so that the records
|
| +// and edits can be processed with a linear pass.
|
| +//
|
| +// Generally, you can generate any legal/illegal record
|
| +// sequence. However, abbreviations are intimately tied to the
|
| +// internals of the bitstream writer and can't contain illegal
|
| +// data. Whenever class NaClBitcodeMunger is unable to accept illegal
|
| +// data, a corresponding "Fatal" error is generated and execution
|
| +// is terminated.
|
| +//
|
| +// ===---------------------------------------------------------------------===//
|
| +
|
| +#ifndef LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H
|
| +#define LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H
|
| +
|
| +#include "llvm/ADT/SmallVector.h"
|
| +#include "llvm/IR/Module.h"
|
| +#include "llvm/Support/DataTypes.h"
|
| +#include "llvm/Support/ErrorHandling.h"
|
| +#include "llvm/Support/MemoryBuffer.h"
|
| +#include "llvm/Support/raw_ostream.h"
|
| +
|
| +#include <string>
|
| +
|
| +namespace llvm {
|
| +
|
| +class NaClBitstreamWriter;
|
| +class NaClBitCodeAbbrev;
|
| +
|
| +/// Base class to run tests on munged bitcode files.
|
| +class NaClBitcodeMunger {
|
| +public:
|
| + /// The types of editing actions that can be applied.
|
| + enum EditAction {
|
| + AddBefore, // Insert record before record with index.
|
| + AddAfter, // Insert record after record with index.
|
| + Remove, // Remove record with index.
|
| + Replace // Replace record with index with specified record.
|
| + };
|
| +
|
| + /// Creates a bitcode munger, based on the given array of values.
|
| + NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize,
|
| + uint64_t RecordTerminator)
|
| + : Records(Records), RecordsSize(RecordsSize),
|
| + RecordTerminator(RecordTerminator), WriteBlockID(-1), SetBID(-1),
|
| + DumpResults("Error: No previous dump results!\n"),
|
| + DumpStream(nullptr), Writer(nullptr), FoundErrors(false),
|
| + FatalBuffer(), FatalStream(FatalBuffer) {}
|
| +
|
| + /// Creates MungedInput and DumpStream for running tests, based on
|
| + /// given Munges.
|
| + void setupTest(
|
| + const char *TestName, const uint64_t Munges[], size_t MungesSize,
|
| + bool AddHeader);
|
| +
|
| + /// Cleans up state after a test.
|
| + void cleanupTest();
|
| +
|
| + /// Returns the resulting string generated by the corresponding test.
|
| + const std::string &getTestResults() const {
|
| + return DumpResults;
|
| + }
|
| +
|
| + /// Returns the lines containing the given Substring, from the
|
| + /// string getTestResults().
|
| + std::string getLinesWithSubstring(const std::string &Substring) const {
|
| + return getLinesWithTextMatch(Substring, false);
|
| + }
|
| +
|
| + /// Returns the lines starting with the given Prefix, from the string
|
| + /// getTestResults().
|
| + std::string getLinesWithPrefix(const std::string &Prefix) const {
|
| + return getLinesWithTextMatch(Prefix, true);
|
| + }
|
| +
|
| +protected:
|
| + // The list of (base) records.
|
| + const uint64_t *Records;
|
| + // The number of (base) records.
|
| + size_t RecordsSize;
|
| + // The value used as record terminator.
|
| + uint64_t RecordTerminator;
|
| + // The block ID associated with the block being written.
|
| + int WriteBlockID;
|
| + // The SetBID for the blockinfo block.
|
| + int SetBID;
|
| + // The results buffer of the last dump.
|
| + std::string DumpResults;
|
| + // The memory buffer containing the munged input.
|
| + std::unique_ptr<MemoryBuffer> MungedInput;
|
| + // The stream containing errors and the objdump of the generated bitcode file.
|
| + raw_ostream *DumpStream;
|
| + // The bitstream writer to use to generate the bitcode file.
|
| + NaClBitstreamWriter *Writer;
|
| + // True if any errors were reported.
|
| + bool FoundErrors;
|
| + // The buffer to hold the generated fatal message.
|
| + std::string FatalBuffer;
|
| + // The stream to write the fatal message to.
|
| + raw_string_ostream FatalStream;
|
| +
|
| + // Records that an error occurred, and returns stream to print error
|
| + // message to.
|
| + raw_ostream &Error() {
|
| + FoundErrors = true;
|
| + return *DumpStream << "Error: ";
|
| + }
|
| +
|
| + // Returns stream to print fatal error message to.
|
| + // Note: Once the fatal error message has been dumped to the stream,
|
| + // one must call ReportFatalError to display the error and terminate
|
| + // execution.
|
| + raw_ostream &Fatal() {
|
| + return FatalStream << "Fatal: ";
|
| + }
|
| +
|
| + // Displays the fatal error message and exits the program.
|
| + void ReportFatalError() {
|
| + report_fatal_error(FatalStream.str());
|
| + }
|
| +
|
| + /// Returns the lines containing the given Substring, from the
|
| + /// string getTestResults(). If MustBePrefix, then Substring must
|
| + /// match at the beginning of the line.
|
| + std::string getLinesWithTextMatch(const std::string &Substring,
|
| + bool MustBePrefix = false) const;
|
| +
|
| + // Writes out sequence of records, applying the given sequence of
|
| + // munges.
|
| + void writeMungedData(const uint64_t Munges[], size_t MungesSize,
|
| + bool AddHeader);
|
| +
|
| + // Emits the given record to the bitcode file.
|
| + void emitRecord(unsigned AbbrevIndex, unsigned RecordCode,
|
| + SmallVectorImpl<uint64_t> &Values);
|
| +
|
| + // Converts the abbreviation record to the corresponding abbreviation.
|
| + NaClBitCodeAbbrev *buildAbbrev(unsigned RecordCode,
|
| + SmallVectorImpl<uint64_t> &Values);
|
| +
|
| + // Emits the record at the given Index to the bitcode file. Then
|
| + // updates Index by one.
|
| + void emitRecordAtIndex(const uint64_t Record[], size_t RecordSize,
|
| + size_t &Index);
|
| +
|
| + // Skips the record starting at Index by advancing Index past the
|
| + // contents of the record.
|
| + void deleteRecord(const uint64_t Record[], size_t RecordSize,
|
| + size_t &Index);
|
| +};
|
| +
|
| +/// Class to run tests for function llvm::NaClObjDump.
|
| +class NaClObjDumpMunger : public NaClBitcodeMunger {
|
| +public:
|
| +
|
| + /// Creates a bitcode munger, based on the given array of values.
|
| + NaClObjDumpMunger(const uint64_t Records[], size_t RecordsSize,
|
| + uint64_t RecordTerminator)
|
| + : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {}
|
| +
|
| + /// Runs function NaClObjDump on the sequence of records associated
|
| + /// with the instance. The memory buffer containing the bitsequence
|
| + /// associated with the record is automatically generated, and
|
| + /// passed to NaClObjDump. TestName is the name associated with the
|
| + /// memory buffer. If AddHeader is true, test assumes that the
|
| + /// sequence of records doesn't contain a header record, and the
|
| + /// test should add one. Arguments NoRecords and NoAssembly are
|
| + /// passed to NaClObjDump. Returns true if test succeeds without
|
| + /// errors.
|
| + bool runTestWithFlags(const char *TestName, bool AddHeader,
|
| + bool NoRecords, bool NoAssembly) {
|
| + uint64_t NoMunges[] = {0};
|
| + return runTestWithFlags(TestName, NoMunges, 0, AddHeader, NoRecords,
|
| + NoAssembly);
|
| + }
|
| +
|
| + /// Same as above except it runs function NaClObjDump with flags
|
| + /// NoRecords and NoAssembly set to false, and AddHeader set to true.
|
| + bool runTest(const char *TestName) {
|
| + return runTestWithFlags(TestName, true, false, false);
|
| + }
|
| +
|
| + /// Same as runTest, but only print out assembly and errors.
|
| + bool runTestForAssembly(const char *TestName) {
|
| + return runTestWithFlags(TestName, true, true, false);
|
| + }
|
| +
|
| + /// Same as runTest, but only generate error messages.
|
| + bool runTestForErrors(const char *TestName) {
|
| + return runTestWithFlags(TestName, true, true, true);
|
| + }
|
| +
|
| + /// Runs function llvm::NaClObjDump on the sequence of records
|
| + /// associated with the instance. Array Munges contains the sequence
|
| + /// of edits to apply to the sequence of records when generating the
|
| + /// bitsequence in a memory buffer. This generated bitsequence is
|
| + /// then passed to NaClObjDump. TestName is the name associated
|
| + /// with the memory buffer. Arguments NoRecords and NoAssembly are
|
| + /// passed to NaClObjDump. Returns true if test succeeds without
|
| + /// errors.
|
| + bool runTestWithFlags(const char* TestName, const uint64_t Munges[],
|
| + size_t MungesSize, bool AddHeader,
|
| + bool NoRecords, bool NoAssembly);
|
| +
|
| + /// Same as above except it runs function NaClObjDump with flags
|
| + /// NoRecords and NoAssembly set to false, and AddHeader set to
|
| + /// true.
|
| + bool runTest(const char* TestName, const uint64_t Munges[],
|
| + size_t MungesSize) {
|
| + return runTestWithFlags(TestName, Munges, MungesSize, true, false, false);
|
| + }
|
| +
|
| + bool runTestForAssembly(const char* TestName, const uint64_t Munges[],
|
| + size_t MungesSize) {
|
| + return runTestWithFlags(TestName, Munges, MungesSize, true, true, false);
|
| + }
|
| +
|
| + bool runTestForErrors(const char* TestName, const uint64_t Munges[],
|
| + size_t MungesSize) {
|
| + return runTestWithFlags(TestName, Munges, MungesSize, true, true, true);
|
| + }
|
| +};
|
| +
|
| +// Class to run tests for function NaClParseBitcodeFile.
|
| +class NaClParseBitcodeMunger : public NaClBitcodeMunger {
|
| +public:
|
| + NaClParseBitcodeMunger(const uint64_t Records[], size_t RecordsSize,
|
| + uint64_t RecordTerminator)
|
| + : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {}
|
| +
|
| + /// Runs function llvm::NaClParseBitcodeFile, and puts error messages
|
| + /// into DumpResults. Returns true if parse is successful.
|
| + bool runTest(const char* TestName, const uint64_t Munges[],
|
| + size_t MungesSize, bool VerboseErrors);
|
| +
|
| + // Same as above, but without any edits.
|
| + bool runTest(const char* TestName, bool VerboseErrors) {
|
| + uint64_t NoMunges[] = {0};
|
| + return runTest(TestName, NoMunges, 0, VerboseErrors);
|
| + }
|
| +};
|
| +
|
| +} // end namespace llvm.
|
| +
|
| +#endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H
|
|
|