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 objdump the resulting contents. | 11 // an array, and parse/objdump 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 // For simplicity of API, we model records as an array of uint64_t. To | 16 // For simplicity of API, we model records as an array of uint64_t. To |
17 // specify the end of a record in the array, a special "terminator" | 17 // specify the end of a record in the array, a special "terminator" |
18 // value is used. This terminator value must be a uint64_t value that | 18 // value is used. This terminator value must be a uint64_t value that |
19 // is not used by any of the records. | 19 // is not used by any of the records. |
20 // | 20 // |
21 // A record is defined as a sequence of integers consisting of: | 21 // A record is defined as a sequence of integers consisting of: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 56 |
57 #include "llvm/ADT/SmallVector.h" | 57 #include "llvm/ADT/SmallVector.h" |
58 #include "llvm/Support/DataTypes.h" | 58 #include "llvm/Support/DataTypes.h" |
59 #include "llvm/Support/ErrorHandling.h" | 59 #include "llvm/Support/ErrorHandling.h" |
60 #include "llvm/Support/raw_ostream.h" | 60 #include "llvm/Support/raw_ostream.h" |
61 | 61 |
62 #include <string> | 62 #include <string> |
63 | 63 |
64 namespace llvm { | 64 namespace llvm { |
65 | 65 |
| 66 class MemoryBuffer; |
66 class NaClBitstreamWriter; | 67 class NaClBitstreamWriter; |
67 class NaClBitCodeAbbrev; | 68 class NaClBitCodeAbbrev; |
68 | 69 |
69 /// Class to run tests for function llvm::NaClObjDump. | 70 /// Base class to run tests on munged bitcode files. |
70 class NaClBitcodeMunger { | 71 class NaClBitcodeMunger { |
71 public: | 72 public: |
72 /// The types of editing actions that can be applied. | 73 /// The types of editing actions that can be applied. |
73 enum EditAction { | 74 enum EditAction { |
74 AddBefore, // Insert record before record with index. | 75 AddBefore, // Insert record before record with index. |
75 AddAfter, // Insert record after record with index. | 76 AddAfter, // Insert record after record with index. |
76 Remove, // Remove record with index. | 77 Remove, // Remove record with index. |
77 Replace // Replace record with index with specified record. | 78 Replace // Replace record with index with specified record. |
78 }; | 79 }; |
79 | 80 |
80 /// Creates a bitcode munger, based on the given array of values. | 81 /// Creates a bitcode munger, based on the given array of values. |
81 NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize, | 82 NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize, |
82 uint64_t RecordTerminator) | 83 uint64_t RecordTerminator) |
83 : Records(Records), RecordsSize(RecordsSize), | 84 : Records(Records), RecordsSize(RecordsSize), |
84 RecordTerminator(RecordTerminator), WriteBlockID(-1), SetBID(-1), | 85 RecordTerminator(RecordTerminator), WriteBlockID(-1), SetBID(-1), |
85 DumpResults("Error: No previous dump results!\n"), | 86 DumpResults("Error: No previous dump results!\n"), MungedInput(nullptr), |
86 DumpStream(NULL), Writer(NULL), FoundErrors(false), | 87 DumpStream(nullptr), Writer(nullptr), FoundErrors(false), |
87 FatalBuffer(), FatalStream(FatalBuffer) {} | 88 FatalBuffer(), FatalStream(FatalBuffer) {} |
88 | 89 |
89 /// Runs function NaClObjDump on the sequence of records associated | 90 /// Creates MungedInput and DumpStream for running tests, based on |
90 /// with the instance. The memory buffer containing the bitsequence | 91 /// given Munges. |
91 /// associated with the record is automatically generated, and | 92 void setupTest( |
92 /// passed to NaClObjDump. TestName is the name associated with the | 93 const char *TestName, const uint64_t Munges[], size_t MungesSize, |
93 /// memory buffer. If AddHeader is true, test assumes that the | 94 bool AddHeader); |
94 /// sequence of records doesn't contain a header record, and the | |
95 /// test should add one. Arguments NoRecords and NoAssembly are | |
96 /// passed to NaClObjDump. Returns true if test succeeds without | |
97 /// errors. | |
98 bool runTestWithFlags(const char *TestName, bool AddHeader, | |
99 bool NoRecords, bool NoAssembly) { | |
100 uint64_t NoMunges[] = {0}; | |
101 return runTestWithFlags(TestName, NoMunges, 0, AddHeader, NoRecords, | |
102 NoAssembly); | |
103 } | |
104 | 95 |
105 /// Same as above except it runs function NaClObjDump with flags | 96 /// Cleans up state after a test. |
106 /// NoRecords and NoAssembly set to false, and AddHeader set to true. | 97 void cleanupTest(); |
107 bool runTest(const char *TestName) { | |
108 return runTestWithFlags(TestName, true, false, false); | |
109 } | |
110 | 98 |
111 /// Same as runTest, but only print out assembly and errors. | 99 /// Returns the resulting string generated by the corresponding test. |
112 bool runTestForAssembly(const char *TestName) { | |
113 return runTestWithFlags(TestName, true, true, false); | |
114 } | |
115 | |
116 /// Same as runTest, but only generate error messages. | |
117 bool runTestForErrors(const char *TestName) { | |
118 return runTestWithFlags(TestName, true, true, true); | |
119 } | |
120 | |
121 /// Runs function llvm::NaClObjDump on the sequence of records | |
122 /// associated with the instance. Array Munges contains the sequence | |
123 /// of edits to apply to the sequence of records when generating the | |
124 /// bitsequence in a memory buffer. This generated bitsequence is | |
125 /// then passed to NaClObjDump. TestName is the name associated | |
126 /// with the memory buffer. Arguments NoRecords and NoAssembly are | |
127 /// passed to NaClObjDump. Returns true if test succeeds without | |
128 /// errors. | |
129 bool runTestWithFlags(const char* TestName, const uint64_t Munges[], | |
130 size_t MungesSize, bool AddHeader, | |
131 bool NoRecords, bool NoAssembly); | |
132 | |
133 /// Same as above except it runs function NaClObjDump with flags | |
134 /// NoRecords and NoAssembly set to false, and AddHeader set to | |
135 /// true. | |
136 bool runTest(const char* TestName, const uint64_t Munges[], | |
137 size_t MungesSize) { | |
138 return runTestWithFlags(TestName, Munges, MungesSize, true, false, false); | |
139 } | |
140 | |
141 bool runTestForAssembly(const char* TestName, const uint64_t Munges[], | |
142 size_t MungesSize) { | |
143 return runTestWithFlags(TestName, Munges, MungesSize, true, true, false); | |
144 } | |
145 | |
146 bool runTestForErrors(const char* TestName, const uint64_t Munges[], | |
147 size_t MungesSize) { | |
148 return runTestWithFlags(TestName, Munges, MungesSize, true, true, true); | |
149 } | |
150 | |
151 /// Returns the resulting string generated by NaClObjDump. | |
152 const std::string &getTestResults() const { | 100 const std::string &getTestResults() const { |
153 return DumpResults; | 101 return DumpResults; |
154 } | 102 } |
155 | 103 |
156 /// Returns the lines containing the given Substring, from the | 104 /// Returns the lines containing the given Substring, from the |
157 /// string getTestResults(). | 105 /// string getTestResults(). |
158 std::string getLinesWithSubstring(const std::string &Substring) const { | 106 std::string getLinesWithSubstring(const std::string &Substring) const { |
159 return getLinesWithTextMatch(Substring, false); | 107 return getLinesWithTextMatch(Substring, false); |
160 } | 108 } |
161 | 109 |
162 /// Returns the lines starting with the given Prefix, from the string | 110 /// Returns the lines starting with the given Prefix, from the string |
163 /// getTestResults(). | 111 /// getTestResults(). |
164 std::string getLinesWithPrefix(const std::string &Prefix) const { | 112 std::string getLinesWithPrefix(const std::string &Prefix) const { |
165 return getLinesWithTextMatch(Prefix, true); | 113 return getLinesWithTextMatch(Prefix, true); |
166 } | 114 } |
167 | 115 |
168 private: | 116 protected: |
169 // The list of (base) records. | 117 // The list of (base) records. |
170 const uint64_t *Records; | 118 const uint64_t *Records; |
171 // The number of (base) records. | 119 // The number of (base) records. |
172 size_t RecordsSize; | 120 size_t RecordsSize; |
173 // The value used as record terminator. | 121 // The value used as record terminator. |
174 uint64_t RecordTerminator; | 122 uint64_t RecordTerminator; |
175 // The block ID associated with the block being written. | 123 // The block ID associated with the block being written. |
176 int WriteBlockID; | 124 int WriteBlockID; |
177 // The SetBID for the blockinfo block. | 125 // The SetBID for the blockinfo block. |
178 int SetBID; | 126 int SetBID; |
179 // The results buffer of the last dump. | 127 // The results buffer of the last dump. |
180 std::string DumpResults; | 128 std::string DumpResults; |
| 129 // The memory buffer containing the munged input. |
| 130 MemoryBuffer *MungedInput; |
181 // The stream containing errors and the objdump of the generated bitcode file. | 131 // The stream containing errors and the objdump of the generated bitcode file. |
182 raw_ostream *DumpStream; | 132 raw_ostream *DumpStream; |
183 // The bitstream writer to use to generate the bitcode file. | 133 // The bitstream writer to use to generate the bitcode file. |
184 NaClBitstreamWriter *Writer; | 134 NaClBitstreamWriter *Writer; |
185 // True if any errors were reported. | 135 // True if any errors were reported. |
186 bool FoundErrors; | 136 bool FoundErrors; |
187 // The buffer to hold the generated fatal message. | 137 // The buffer to hold the generated fatal message. |
188 std::string FatalBuffer; | 138 std::string FatalBuffer; |
189 // The stream to write the fatal message to. | 139 // The stream to write the fatal message to. |
190 raw_string_ostream FatalStream; | 140 raw_string_ostream FatalStream; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 // updates Index by one. | 182 // updates Index by one. |
233 void emitRecordAtIndex(const uint64_t Record[], size_t RecordSize, | 183 void emitRecordAtIndex(const uint64_t Record[], size_t RecordSize, |
234 size_t &Index); | 184 size_t &Index); |
235 | 185 |
236 // Skips the record starting at Index by advancing Index past the | 186 // Skips the record starting at Index by advancing Index past the |
237 // contents of the record. | 187 // contents of the record. |
238 void deleteRecord(const uint64_t Record[], size_t RecordSize, | 188 void deleteRecord(const uint64_t Record[], size_t RecordSize, |
239 size_t &Index); | 189 size_t &Index); |
240 }; | 190 }; |
241 | 191 |
| 192 /// Class to run tests for function llvm::NaClObjDump. |
| 193 class NaClObjDumpMunger : public NaClBitcodeMunger { |
| 194 public: |
| 195 |
| 196 /// Creates a bitcode munger, based on the given array of values. |
| 197 NaClObjDumpMunger(const uint64_t Records[], size_t RecordsSize, |
| 198 uint64_t RecordTerminator) |
| 199 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} |
| 200 |
| 201 /// Runs function NaClObjDump on the sequence of records associated |
| 202 /// with the instance. The memory buffer containing the bitsequence |
| 203 /// associated with the record is automatically generated, and |
| 204 /// passed to NaClObjDump. TestName is the name associated with the |
| 205 /// memory buffer. If AddHeader is true, test assumes that the |
| 206 /// sequence of records doesn't contain a header record, and the |
| 207 /// test should add one. Arguments NoRecords and NoAssembly are |
| 208 /// passed to NaClObjDump. Returns true if test succeeds without |
| 209 /// errors. |
| 210 bool runTestWithFlags(const char *TestName, bool AddHeader, |
| 211 bool NoRecords, bool NoAssembly) { |
| 212 uint64_t NoMunges[] = {0}; |
| 213 return runTestWithFlags(TestName, NoMunges, 0, AddHeader, NoRecords, |
| 214 NoAssembly); |
| 215 } |
| 216 |
| 217 /// Same as above except it runs function NaClObjDump with flags |
| 218 /// NoRecords and NoAssembly set to false, and AddHeader set to true. |
| 219 bool runTest(const char *TestName) { |
| 220 return runTestWithFlags(TestName, true, false, false); |
| 221 } |
| 222 |
| 223 /// Same as runTest, but only print out assembly and errors. |
| 224 bool runTestForAssembly(const char *TestName) { |
| 225 return runTestWithFlags(TestName, true, true, false); |
| 226 } |
| 227 |
| 228 /// Same as runTest, but only generate error messages. |
| 229 bool runTestForErrors(const char *TestName) { |
| 230 return runTestWithFlags(TestName, true, true, true); |
| 231 } |
| 232 |
| 233 /// Runs function llvm::NaClObjDump on the sequence of records |
| 234 /// associated with the instance. Array Munges contains the sequence |
| 235 /// of edits to apply to the sequence of records when generating the |
| 236 /// bitsequence in a memory buffer. This generated bitsequence is |
| 237 /// then passed to NaClObjDump. TestName is the name associated |
| 238 /// with the memory buffer. Arguments NoRecords and NoAssembly are |
| 239 /// passed to NaClObjDump. Returns true if test succeeds without |
| 240 /// errors. |
| 241 bool runTestWithFlags(const char* TestName, const uint64_t Munges[], |
| 242 size_t MungesSize, bool AddHeader, |
| 243 bool NoRecords, bool NoAssembly); |
| 244 |
| 245 /// Same as above except it runs function NaClObjDump with flags |
| 246 /// NoRecords and NoAssembly set to false, and AddHeader set to |
| 247 /// true. |
| 248 bool runTest(const char* TestName, const uint64_t Munges[], |
| 249 size_t MungesSize) { |
| 250 return runTestWithFlags(TestName, Munges, MungesSize, true, false, false); |
| 251 } |
| 252 |
| 253 bool runTestForAssembly(const char* TestName, const uint64_t Munges[], |
| 254 size_t MungesSize) { |
| 255 return runTestWithFlags(TestName, Munges, MungesSize, true, true, false); |
| 256 } |
| 257 |
| 258 bool runTestForErrors(const char* TestName, const uint64_t Munges[], |
| 259 size_t MungesSize) { |
| 260 return runTestWithFlags(TestName, Munges, MungesSize, true, true, true); |
| 261 } |
| 262 }; |
| 263 |
| 264 // Class to run tests for function NaClParseBitcodeFile. |
| 265 class NaClParseBitcodeMunger : public NaClBitcodeMunger { |
| 266 public: |
| 267 NaClParseBitcodeMunger(const uint64_t Records[], size_t RecordsSize, |
| 268 uint64_t RecordTerminator) |
| 269 : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} |
| 270 |
| 271 /// Runs function llvm::NaClParseBitcodeFile, and puts error messages |
| 272 /// into DumpResults. Returns true if parse is successful. |
| 273 bool runTest(const char* TestName, const uint64_t Munges[], |
| 274 size_t MungesSize, bool VerboseErrors); |
| 275 |
| 276 // Same as above, but without any edits. |
| 277 bool runTest(const char* TestName, bool VerboseErrors) { |
| 278 uint64_t NoMunges[] = {0}; |
| 279 return runTest(TestName, NoMunges, 0, VerboseErrors); |
| 280 } |
| 281 }; |
| 282 |
242 } // end namespace llvm. | 283 } // end namespace llvm. |
243 | 284 |
244 #endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H | 285 #endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H |
OLD | NEW |