| OLD | NEW |
| 1 //===- NaClBitcodeMunge.h - Bitcode Munger ----------------------*- C++ -*-===// | 1 //===- NaClBitcodeMunge.h - Bitcode Munger ----------------------*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // Test harness for generating a PNaCl bitcode memory buffer from | 10 // Test harness for generating a PNaCl bitcode memory buffer from |
| 11 // an array, and parse/objdump/compress the resulting contents. | 11 // an array, and parse/objdump/compress the resulting contents. |
| 12 // | 12 // |
| 13 // Generates a bitcode memory buffer from an array containing 1 or | 13 // Generates a bitcode memory buffer from an array containing 1 or |
| 14 // more PNaCl records. Used to test errors in PNaCl bitcode. | 14 // more PNaCl records. Used to test errors in PNaCl bitcode. |
| 15 // | 15 // |
| 16 // Bitcode records are modeleled using arrays using the format | 16 // Bitcode records are modeled using arrays using the format |
| 17 // specified in NaClBitcodeMungeUtils.h. | 17 // specified in NaClBitcodeMungeUtils.h. |
| 18 // | 18 // |
| 19 // Note: Since the header record doesn't have any abbreviation indices | 19 // Note: Since the header record doesn't have any abbreviation indices |
| 20 // associated with it, one can use any value. The value will simply be | 20 // associated with it, one can use any value. The value will simply be |
| 21 // ignored. | 21 // ignored. |
| 22 // | 22 // |
| 23 // In addition to specifying the sequence of records, one can also | 23 // In addition to specifying the sequence of records, one can also |
| 24 // define a sequence of edits to be applied to the original sequence | 24 // define a sequence of edits to be applied to the original sequence |
| 25 // of records. This allows the same record sequence to be used in | 25 // of records. This allows the same record sequence to be used in |
| 26 // multiple tests. Again, see NaClBitcodeMungeUtils.h for the | 26 // multiple tests. Again, see NaClBitcodeMungeUtils.h for the |
| (...skipping 13 matching lines...) Expand all Loading... |
| 40 | 40 |
| 41 #include "llvm/ADT/SmallVector.h" | 41 #include "llvm/ADT/SmallVector.h" |
| 42 #include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" | 42 #include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" |
| 43 #include "llvm/Support/MemoryBuffer.h" | 43 #include "llvm/Support/MemoryBuffer.h" |
| 44 #include "llvm/Support/raw_ostream.h" | 44 #include "llvm/Support/raw_ostream.h" |
| 45 | 45 |
| 46 #include <string> | 46 #include <string> |
| 47 | 47 |
| 48 namespace llvm { | 48 namespace llvm { |
| 49 | 49 |
| 50 class NaClBitstreamWriter; | |
| 51 class NaClBitCodeAbbrev; | 50 class NaClBitCodeAbbrev; |
| 52 | 51 |
| 53 /// Base class to run tests on munged bitcode files. | 52 /// Base class to run tests on munged bitcode files. |
| 54 class NaClBitcodeMunger { | 53 class NaClBitcodeMunger { |
| 55 public: | 54 public: |
| 56 /// Creates a bitcode munger, based on the given array of values. | 55 /// Creates a bitcode munger, based on the given array of values. |
| 57 NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize, | 56 NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize, |
| 58 uint64_t RecordTerminator) | 57 uint64_t RecordTerminator) |
| 59 : MungedBitcode(Records, RecordsSize, RecordTerminator), | 58 : MungedBitcode(Records, RecordsSize, RecordTerminator), |
| 60 RecordTerminator(RecordTerminator), WriteBlockID(-1), SetBID(-1), | 59 RecordTerminator(RecordTerminator), |
| 61 DumpResults("Error: No previous dump results!\n"), | 60 DumpResults("Error: No previous dump results!\n"), |
| 62 DumpStream(nullptr), Writer(nullptr), FoundErrors(false), | 61 DumpStream(nullptr), FoundErrors(false), RunAsDeathTest(false) {} |
| 63 FatalBuffer(), FatalStream(FatalBuffer) {} | 62 |
| 63 /// Returns true if running as death test. |
| 64 bool getRunAsDeathTest() const { |
| 65 return RunAsDeathTest; |
| 66 } |
| 67 |
| 68 /// Sets death test flag. When true, output will be redirected to |
| 69 /// the errs() (rather than buffered) so that the test can be |
| 70 /// debugged. |
| 71 void setRunAsDeathTest(bool NewValue) { |
| 72 RunAsDeathTest = NewValue; |
| 73 } |
| 64 | 74 |
| 65 /// Creates MungedInput and DumpStream for running tests, based on | 75 /// Creates MungedInput and DumpStream for running tests, based on |
| 66 /// given Munges. | 76 /// given Munges. |
| 67 void setupTest( | 77 void setupTest( |
| 68 const char *TestName, const uint64_t Munges[], size_t MungesSize, | 78 const char *TestName, const uint64_t Munges[], size_t MungesSize, |
| 69 bool AddHeader); | 79 bool AddHeader); |
| 70 | 80 |
| 71 /// Cleans up state after a test. | 81 /// Cleans up state after a test. |
| 72 void cleanupTest(); | 82 void cleanupTest(); |
| 73 | 83 |
| 74 /// Returns the resulting string generated by the corresponding test. | 84 /// Returns the resulting string generated by the corresponding test. |
| 75 const std::string &getTestResults() const { | 85 const std::string &getTestResults() const { |
| 76 return DumpResults; | 86 return DumpResults; |
| 77 } | 87 } |
| 78 | 88 |
| 79 /// Returns the lines containing the given Substring, from the | 89 /// Returns the lines containing the given Substring, from the |
| 80 /// string getTestResults(). | 90 /// string getTestResults(). |
| 81 std::string getLinesWithSubstring(const std::string &Substring) const { | 91 std::string getLinesWithSubstring(const std::string &Substring) const { |
| 82 return getLinesWithTextMatch(Substring, false); | 92 return getLinesWithTextMatch(Substring, false); |
| 83 } | 93 } |
| 84 | 94 |
| 85 /// Returns the lines starting with the given Prefix, from the string | 95 /// Returns the lines starting with the given Prefix, from the string |
| 86 /// getTestResults(). | 96 /// getTestResults(). |
| 87 std::string getLinesWithPrefix(const std::string &Prefix) const { | 97 std::string getLinesWithPrefix(const std::string &Prefix) const { |
| 88 return getLinesWithTextMatch(Prefix, true); | 98 return getLinesWithTextMatch(Prefix, true); |
| 89 } | 99 } |
| 90 | 100 |
| 101 /// When NewValue, use error recovery when writing bitcode during |
| 102 /// next test. |
| 103 void setTryToRecoverOnWrite(bool NewValue) { |
| 104 WriteFlags.setTryToRecover(NewValue); |
| 105 } |
| 106 |
| 107 /// When NewValue, write bad abbreviation index into bitcode when |
| 108 /// writing during next test. |
| 109 void setWriteBadAbbrevIndex(bool NewValue) { |
| 110 WriteFlags.setWriteBadAbbrevIndex(NewValue); |
| 111 } |
| 112 |
| 91 protected: | 113 protected: |
| 92 // The bitcode records being munged. | 114 // The bitcode records being munged. |
| 93 NaClMungedBitcode MungedBitcode; | 115 NaClMungedBitcode MungedBitcode; |
| 94 // The value used as record terminator. | 116 // The value used as record terminator. |
| 95 uint64_t RecordTerminator; | 117 uint64_t RecordTerminator; |
| 96 // The block ID associated with the block being written. | |
| 97 int WriteBlockID; | |
| 98 // The SetBID for the blockinfo block. | |
| 99 int SetBID; | |
| 100 // The results buffer of the last dump. | 118 // The results buffer of the last dump. |
| 101 std::string DumpResults; | 119 std::string DumpResults; |
| 102 // The memory buffer containing the munged input. | 120 // The memory buffer containing the munged input. |
| 103 std::unique_ptr<MemoryBuffer> MungedInput; | 121 std::unique_ptr<MemoryBuffer> MungedInput; |
| 104 // The stream containing errors and the objdump of the generated bitcode file. | 122 // The stream containing errors and the objdump of the generated bitcode file. |
| 105 raw_ostream *DumpStream; | 123 raw_ostream *DumpStream; |
| 106 // The bitstream writer to use to generate the bitcode file. | |
| 107 NaClBitstreamWriter *Writer; | |
| 108 // True if any errors were reported. | 124 // True if any errors were reported. |
| 109 bool FoundErrors; | 125 bool FoundErrors; |
| 110 // The buffer to hold the generated fatal message. | |
| 111 std::string FatalBuffer; | |
| 112 // The stream to write the fatal message to. | |
| 113 raw_string_ostream FatalStream; | |
| 114 // The stack of maximum abbreviation indices allowed by block enter record. | |
| 115 SmallVector<uint64_t, 3> AbbrevIndexLimitStack; | |
| 116 // The buffer for the contents of the munged input. | 126 // The buffer for the contents of the munged input. |
| 117 SmallVector<char, 1024> MungedInputBuffer; | 127 SmallVector<char, 1024> MungedInputBuffer; |
| 128 /// The write flags to use when writing bitcode. |
| 129 NaClMungedBitcode::WriteFlags WriteFlags; |
| 130 // Flag to redirect dump stream if running death test. |
| 131 bool RunAsDeathTest; |
| 118 | 132 |
| 119 // Records that an error occurred, and returns stream to print error | 133 // Records that an error occurred, and returns stream to print error |
| 120 // message to. | 134 // message to. |
| 121 raw_ostream &Error() { | 135 raw_ostream &Error() { |
| 122 FoundErrors = true; | 136 FoundErrors = true; |
| 123 return *DumpStream << "Error: "; | 137 return getDumpStream() << "Error: "; |
| 124 } | |
| 125 | |
| 126 // Returns stream to print fatal error message to. | |
| 127 // Note: Once the fatal error message has been dumped to the stream, | |
| 128 // one must call ReportFatalError to display the error and terminate | |
| 129 // execution. | |
| 130 raw_ostream &Fatal() { | |
| 131 return FatalStream << "Fatal: "; | |
| 132 } | |
| 133 | |
| 134 // Displays the fatal error message and exits the program. | |
| 135 void ReportFatalError() { | |
| 136 report_fatal_error(FatalStream.str()); | |
| 137 } | 138 } |
| 138 | 139 |
| 139 // Returns the lines containing the given Substring, from the string | 140 // Returns the lines containing the given Substring, from the string |
| 140 // getTestResults(). If MustBePrefix, then Substring must match at | 141 // getTestResults(). If MustBePrefix, then Substring must match at |
| 141 // the beginning of the line. | 142 // the beginning of the line. |
| 142 std::string getLinesWithTextMatch(const std::string &Substring, | 143 std::string getLinesWithTextMatch(const std::string &Substring, |
| 143 bool MustBePrefix = false) const; | 144 bool MustBePrefix = false) const; |
| 144 | 145 |
| 145 // Writes out munged bitcode records. | 146 // Returns the log stream to use. When running death tests, redirect output |
| 146 void writeMungedBitcode(const NaClMungedBitcode &Bitcode, bool AddHeader); | 147 // to the error stream (rather than buffering in DumpStream), so that |
| 147 | 148 // the output can be seen in gtest death tests. |
| 148 // Emits the given record to the bitcode file. | 149 raw_ostream &getDumpStream() const { |
| 149 void emitRecord(const NaClBitcodeAbbrevRecord &Record); | 150 return RunAsDeathTest ? errs() : *DumpStream; |
| 150 | 151 } |
| 151 // Converts the abbreviation record to the corresponding abbreviation. | |
| 152 NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record); | |
| 153 }; | 152 }; |
| 154 | 153 |
| 155 /// Class to run tests for function llvm::NaClObjDump. | 154 /// Class to run tests for function llvm::NaClObjDump. |
| 156 class NaClObjDumpMunger : public NaClBitcodeMunger { | 155 class NaClObjDumpMunger : public NaClBitcodeMunger { |
| 157 public: | 156 public: |
| 158 | 157 |
| 159 /// Creates a bitcode munger, based on the given array of values. | 158 /// Creates a bitcode munger, based on the given array of values. |
| 160 NaClObjDumpMunger(const uint64_t Records[], size_t RecordsSize, | 159 NaClObjDumpMunger(const uint64_t Records[], size_t RecordsSize, |
| 161 uint64_t RecordTerminator) | 160 uint64_t RecordTerminator) |
| 162 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator), | 161 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} |
| 163 RunAsDeathTest(false) {} | |
| 164 | 162 |
| 165 /// Runs function NaClObjDump on the sequence of records associated | 163 /// Runs function NaClObjDump on the sequence of records associated |
| 166 /// with the instance. The memory buffer containing the bitsequence | 164 /// with the instance. The memory buffer containing the bitsequence |
| 167 /// associated with the record is automatically generated, and | 165 /// associated with the record is automatically generated, and |
| 168 /// passed to NaClObjDump. TestName is the name associated with the | 166 /// passed to NaClObjDump. TestName is the name associated with the |
| 169 /// memory buffer. If AddHeader is true, test assumes that the | 167 /// memory buffer. If AddHeader is true, test assumes that the |
| 170 /// sequence of records doesn't contain a header record, and the | 168 /// sequence of records doesn't contain a header record, and the |
| 171 /// test should add one. Arguments NoRecords and NoAssembly are | 169 /// test should add one. Arguments NoRecords and NoAssembly are |
| 172 /// passed to NaClObjDump. Returns true if test succeeds without | 170 /// passed to NaClObjDump. Returns true if test succeeds without |
| 173 /// errors. | 171 /// errors. |
| 174 bool runTestWithFlags(const char *TestName, bool AddHeader, | 172 bool runTestWithFlags(const char *TestName, bool AddHeader, |
| 175 bool NoRecords, bool NoAssembly) { | 173 bool NoRecords, bool NoAssembly) { |
| 176 uint64_t NoMunges[] = {0}; | 174 uint64_t NoMunges[] = {0}; |
| 177 return runTestWithFlags(TestName, NoMunges, 0, AddHeader, NoRecords, | 175 return runTestWithFlags(TestName, NoMunges, 0, AddHeader, NoRecords, |
| 178 NoAssembly); | 176 NoAssembly); |
| 179 } | 177 } |
| 180 | 178 |
| 181 /// Returns true if running as death test. | |
| 182 bool getRunAsDeathTest() const { | |
| 183 return RunAsDeathTest; | |
| 184 } | |
| 185 | |
| 186 /// Sets death test flag. When true, output will be redirected to | |
| 187 /// the errs() (rather than buffered) so that the test can be | |
| 188 /// debugged. | |
| 189 void setRunAsDeathTest(bool NewValue) { | |
| 190 RunAsDeathTest = NewValue; | |
| 191 } | |
| 192 | |
| 193 /// Same as above except it runs function NaClObjDump with flags | 179 /// Same as above except it runs function NaClObjDump with flags |
| 194 /// NoRecords and NoAssembly set to false, and AddHeader set to true. | 180 /// NoRecords and NoAssembly set to false, and AddHeader set to true. |
| 195 bool runTest(const char *TestName) { | 181 bool runTest(const char *TestName) { |
| 196 return runTestWithFlags(TestName, true, false, false); | 182 return runTestWithFlags(TestName, true, false, false); |
| 197 } | 183 } |
| 198 | 184 |
| 199 /// Same as runTest, but only print out assembly and errors. | 185 /// Same as runTest, but only print out assembly and errors. |
| 200 bool runTestForAssembly(const char *TestName) { | 186 bool runTestForAssembly(const char *TestName) { |
| 201 return runTestWithFlags(TestName, true, true, false); | 187 return runTestWithFlags(TestName, true, true, false); |
| 202 } | 188 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 228 | 214 |
| 229 bool runTestForAssembly(const char* TestName, const uint64_t Munges[], | 215 bool runTestForAssembly(const char* TestName, const uint64_t Munges[], |
| 230 size_t MungesSize) { | 216 size_t MungesSize) { |
| 231 return runTestWithFlags(TestName, Munges, MungesSize, true, true, false); | 217 return runTestWithFlags(TestName, Munges, MungesSize, true, true, false); |
| 232 } | 218 } |
| 233 | 219 |
| 234 bool runTestForErrors(const char* TestName, const uint64_t Munges[], | 220 bool runTestForErrors(const char* TestName, const uint64_t Munges[], |
| 235 size_t MungesSize) { | 221 size_t MungesSize) { |
| 236 return runTestWithFlags(TestName, Munges, MungesSize, true, true, true); | 222 return runTestWithFlags(TestName, Munges, MungesSize, true, true, true); |
| 237 } | 223 } |
| 238 | |
| 239 private: | |
| 240 // Flag to redirect dump stream if running death test. | |
| 241 bool RunAsDeathTest; | |
| 242 | |
| 243 }; | 224 }; |
| 244 | 225 |
| 245 // Class to run tests for function NaClParseBitcodeFile. | 226 // Class to run tests for function NaClParseBitcodeFile. |
| 246 class NaClParseBitcodeMunger : public NaClBitcodeMunger { | 227 class NaClParseBitcodeMunger : public NaClBitcodeMunger { |
| 247 public: | 228 public: |
| 248 NaClParseBitcodeMunger(const uint64_t Records[], size_t RecordsSize, | 229 NaClParseBitcodeMunger(const uint64_t Records[], size_t RecordsSize, |
| 249 uint64_t RecordTerminator) | 230 uint64_t RecordTerminator) |
| 250 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} | 231 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} |
| 251 | 232 |
| 252 /// Runs function llvm::NaClParseBitcodeFile, and puts error messages | 233 /// Runs function llvm::NaClParseBitcodeFile, and puts error messages |
| (...skipping 20 matching lines...) Expand all Loading... |
| 273 | 254 |
| 274 bool runTest(const char* TestName) { | 255 bool runTest(const char* TestName) { |
| 275 uint64_t NoMunges[] = {0}; | 256 uint64_t NoMunges[] = {0}; |
| 276 return runTest(TestName, NoMunges, 0); | 257 return runTest(TestName, NoMunges, 0); |
| 277 } | 258 } |
| 278 }; | 259 }; |
| 279 | 260 |
| 280 } // end namespace llvm. | 261 } // end namespace llvm. |
| 281 | 262 |
| 282 #endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H | 263 #endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H |
| OLD | NEW |