Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 //===- llvm/unittest/Bitcode/NaClMungeWriteErrorTests.cpp -----------------===// | |
| 2 // Tests parser for PNaCl bitcode instructions. | |
| 3 // | |
| 4 // The LLVM Compiler Infrastructure | |
| 5 // | |
| 6 // This file is distributed under the University of Illinois Open Source | |
| 7 // License. See LICENSE.TXT for details. | |
| 8 // | |
| 9 //===----------------------------------------------------------------------===// | |
| 10 | |
| 11 // Tests write errors for munged bitcode. | |
| 12 | |
| 13 #include "llvm/ADT/STLExtras.h" | |
| 14 #include "llvm/Bitcode/NaCl/NaClBitcodeMunge.h" | |
| 15 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" | |
| 16 #include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h" | |
| 17 | |
| 18 #include "gtest/gtest.h" | |
| 19 | |
| 20 using namespace llvm; | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 // Test list of bitcode records. | |
| 25 static const uint64_t Terminator = 0x5768798008978675LL; | |
| 26 const uint64_t BitcodeRecords[] = { | |
| 27 1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID, 2, Terminator, | |
| 28 1, naclbitc::BLK_CODE_ENTER, naclbitc::TYPE_BLOCK_ID_NEW, 3, Terminator, | |
| 29 3, naclbitc::TYPE_CODE_NUMENTRY, 2, Terminator, | |
| 30 3, naclbitc::TYPE_CODE_VOID, Terminator, | |
| 31 3, naclbitc::TYPE_CODE_FUNCTION, 0, 0, Terminator, | |
| 32 0, naclbitc::BLK_CODE_EXIT, Terminator, | |
| 33 3, naclbitc::MODULE_CODE_FUNCTION, 1, 0, 0, 0, Terminator, | |
| 34 1, naclbitc::BLK_CODE_ENTER, naclbitc::FUNCTION_BLOCK_ID, 2, Terminator, | |
| 35 3, naclbitc::FUNC_CODE_DECLAREBLOCKS, 1, Terminator, | |
| 36 3, naclbitc::FUNC_CODE_INST_RET, Terminator, | |
| 37 0, naclbitc::BLK_CODE_EXIT, Terminator, | |
| 38 0, naclbitc::BLK_CODE_EXIT, Terminator | |
| 39 }; | |
| 40 | |
| 41 // Expected output when bitcode records are dumped. | |
| 42 const char* ExpectedDump = | |
| 43 " 0:0|<65532, 80, 69, 88, 69, 1, 0,|Magic Number: 'PEXE' (80, 69, " | |
| 44 "88, 69)\n" | |
| 45 " | 8, 0, 17, 0, 4, 0, 2, 0, 0, |PNaCl Version: 2\n" | |
| 46 " | 0> |\n" | |
| 47 " 16:0|1: <65535, 8, 2> |module { // BlockID = 8\n" | |
| 48 " 24:0| 1: <65535, 17, 3> | types { // BlockID = 17\n" | |
| 49 " 32:0| 3: <1, 2> | count 2;\n" | |
| 50 " 34:5| 3: <2> | @t0 = void;\n" | |
| 51 " 36:4| 3: <21, 0, 0> | @t1 = void ();\n" | |
| 52 " 39:7| 0: <65534> | }\n" | |
| 53 " 44:0| 3: <8, 1, 0, 0, 0> | define external void @f0();\n" | |
| 54 " 48:6| 1: <65535, 12, 2> | function void @f0() { \n" | |
| 55 " | | // BlockID " | |
| 56 "= 12\n" | |
| 57 " 56:0| 3: <1, 1> | blocks 1;\n" | |
| 58 " | | %b0:\n" | |
| 59 " 58:4| 3: <10> | ret void;\n" | |
| 60 " 60:2| 0: <65534> | }\n" | |
| 61 " 64:0|0: <65534> |}\n" | |
| 62 ; | |
| 63 | |
| 64 // Edit to change void type with an illegal abbreviation index. | |
| 65 const uint64_t VoidTypeIndex = 3; // Index for "@t0 = void". | |
| 66 const uint64_t AbbrevIndex4VoidTypeEdit[] = { | |
| 67 VoidTypeIndex, NaClMungedBitcode::Replace, | |
| 68 4, naclbitc::TYPE_CODE_VOID, Terminator, | |
| 69 }; | |
| 70 | |
| 71 // Edit to add local abbreviation for "ret void", and then use on that | |
| 72 // instruction. | |
| 73 const uint64_t RetVoidIndex = 9; // return void; | |
| 74 const uint64_t UseLocalRetVoidAbbrevEdits[] = { | |
| 75 RetVoidIndex, NaClMungedBitcode::AddBefore, | |
| 76 2, naclbitc::BLK_CODE_DEFINE_ABBREV, 1, 1, | |
| 77 naclbitc::FUNC_CODE_INST_RET, Terminator, | |
| 78 RetVoidIndex, NaClMungedBitcode::Replace, | |
| 79 4, naclbitc::FUNC_CODE_INST_RET, Terminator | |
| 80 }; | |
| 81 | |
| 82 #define ARRAY_ARGS(Records) Records, array_lengthof(Records) | |
| 83 | |
| 84 #define ARRAY_ARGS_TERM(Records) ARRAY_ARGS(Records), Terminator | |
| 85 | |
| 86 std::string stringify(NaClBitcodeMunger &Munger) { | |
| 87 std::string Buffer; | |
| 88 raw_string_ostream StrBuf(Buffer); | |
| 89 Munger.getMungedBitcode().print(StrBuf); | |
| 90 return StrBuf.str(); | |
| 91 } | |
| 92 | |
| 93 // Show that we can dump the bitcode records | |
| 94 TEST(NaClMungeWriteErrorTests, DumpBitcodeRecords) { | |
| 95 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 96 EXPECT_TRUE(Munger.runTest("DumpBitcodeRecords")); | |
| 97 EXPECT_EQ(ExpectedDump, Munger.getTestResults()); | |
| 98 } | |
| 99 | |
| 100 // Show that by default, one can't write a bad abbreviation index. | |
| 101 TEST(NaClMungeWriteErrorTests, CantWriteBadAbbrevIndex) { | |
| 102 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 103 EXPECT_FALSE(Munger.runTest("CantWriteBadAbbrevIndex", | |
| 104 ARRAY_ARGS(AbbrevIndex4VoidTypeEdit))); | |
| 105 EXPECT_EQ( | |
| 106 "Error (Block 17): Uses illegal abbreviation index: 4: [2]\n" | |
| 107 "Error (Block 17): Missing close block.\n" | |
| 108 "Error (Block 8): Missing close block.\n" | |
| 109 "Error: Unable to generate bitcode file due to write errors\n", | |
| 110 Munger.getTestResults()); | |
| 111 } | |
| 112 | |
| 113 // Show that we can't write more local abbreviations than specified in | |
| 114 // the corresponding enclosing block. | |
| 115 TEST(NaClMungeWriteErrorTests, CantDumpTooManyLocalAbbreviations) { | |
|
jvoung (off chromium)
2015/05/13 00:58:17
Maybe "define" instead of "dump"? I think of the o
Karl
2015/05/13 21:39:25
Changing CantWriteTooManyLocallAbbreviations.
| |
| 116 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 117 Munger.munge(ARRAY_ARGS(UseLocalRetVoidAbbrevEdits)); | |
| 118 EXPECT_EQ( | |
| 119 " 1: [65535, 8, 2]\n" | |
| 120 " 1: [65535, 17, 3]\n" | |
| 121 " 3: [1, 2]\n" | |
| 122 " 3: [2]\n" | |
| 123 " 3: [21, 0, 0]\n" | |
| 124 " 0: [65534]\n" | |
| 125 " 3: [8, 1, 0, 0, 0]\n" | |
| 126 " 1: [65535, 12, 2]\n" | |
| 127 " 3: [1, 1]\n" | |
| 128 " 2: [65533, 1, 1, 10]\n" | |
| 129 " 4: [10]\n" | |
| 130 " 0: [65534]\n" | |
| 131 " 0: [65534]\n", | |
| 132 stringify(Munger)); | |
| 133 | |
| 134 EXPECT_FALSE(Munger.runTest("CantDumpTooManyLocalAbbreviations")); | |
| 135 EXPECT_EQ( | |
| 136 "Error (Block 12): Exceeds abbreviation index limit of 3: 2:" | |
| 137 " [65533, 1, 1, 10]\n" | |
| 138 "Error (Block 12): Missing close block.\n" | |
| 139 "Error (Block 8): Missing close block.\n" | |
| 140 "Error: Unable to generate bitcode file due to write errors\n", | |
| 141 Munger.getTestResults()); | |
| 142 } | |
| 143 | |
| 144 // Show what happens when there are more enter blocks then exit blocks. | |
| 145 TEST(NaClMungeWriteErrorTests, TooManyEnterBlocks) { | |
| 146 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 147 // Remove all but first two records (i.e. two enter blocks). | |
| 148 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode(); | |
| 149 for (size_t i = 2; i < MungedBitcode.getBaseRecords().size(); ++i) { | |
| 150 MungedBitcode.remove(i); | |
| 151 } | |
| 152 | |
| 153 EXPECT_FALSE(Munger.runTest("TooManyEnterBlocks")); | |
| 154 EXPECT_EQ( | |
| 155 "Error (Block 17): Missing close block.\n" | |
| 156 "Error (Block 8): Missing close block.\n" | |
| 157 "Error: Unable to generate bitcode file due to write errors\n", | |
| 158 Munger.getTestResults()); | |
| 159 } | |
| 160 | |
| 161 // Show what happens when there are fewer enter blocks than exit | |
| 162 // blocks. | |
| 163 TEST(NaClMungeWriteErrorTests, TooFewExitBlocks) { | |
|
jvoung (off chromium)
2015/05/13 00:58:17
re: TooFewExitBlocks, in this case there are too f
Karl
2015/05/13 21:39:24
Fixing to TooMayExitBlocks.
| |
| 164 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 165 // Add two exit blocks. | |
| 166 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode(); | |
| 167 NaClRecordVector Values; | |
| 168 NaClBitcodeAbbrevRecord Record(0, naclbitc::BLK_CODE_EXIT, Values); | |
| 169 for (size_t i = 0; i < 2; ++i) | |
| 170 MungedBitcode.addAfter(MungedBitcode.getBaseRecords().size() - 1, Record); | |
| 171 | |
| 172 EXPECT_FALSE(Munger.runTest("TooFewExitBlocks")); | |
|
jvoung (off chromium)
2015/05/13 00:58:17
"TooFewExitBlocks" -> ?
Karl
2015/05/13 21:39:24
Done.
| |
| 173 EXPECT_EQ( | |
| 174 "Error (Block unknown): Extraneous exit block: 0: [65534]\n" | |
| 175 "Error: Unable to generate bitcode file due to write errors\n", | |
| 176 Munger.getTestResults()); | |
| 177 } | |
| 178 | |
| 179 // Show that an error occurs when writing a bitcode record that isn't | |
| 180 // in any block. | |
| 181 TEST(NaClMungeWriteErrorTests, CantWriteRecordOutsideBlock) { | |
| 182 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 183 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode(); | |
| 184 NaClRecordVector Values; | |
| 185 Values.push_back(4); | |
| 186 NaClBitcodeAbbrevRecord Record(naclbitc::UNABBREV_RECORD, | |
| 187 naclbitc::MODULE_CODE_VERSION, | |
| 188 Values); | |
| 189 | |
| 190 MungedBitcode.addAfter(MungedBitcode.getBaseRecords().size() - 1, Record); | |
| 191 EXPECT_FALSE(Munger.runTest("CantWriteRecordOutsideBlock")); | |
| 192 EXPECT_EQ( | |
| 193 "Error (Block unknown): Record outside block: 3: [1, 4]\n" | |
| 194 "Error: Unable to generate bitcode file due to write errors\n", | |
| 195 Munger.getTestResults()); | |
| 196 } | |
| 197 | |
| 198 // Show that error recovery works when parsing bitcode with a bad | |
| 199 // abbreviation index. | |
|
jvoung (off chromium)
2015/05/13 00:58:17
So to be clear -- the error recovery is in the wri
Karl
2015/05/13 21:39:24
Yes.
Rewriting error recovery comments to be clea
| |
| 200 TEST(NaClMungeWriteErrorTests, RecoverWhenParsingBadAbbrevIndex) { | |
| 201 NaClParseBitcodeMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 202 Munger.setTryToRecoverOnWrite(true); | |
| 203 EXPECT_TRUE( | |
| 204 Munger.runTest("RecoverWhenParsingBadAbbrevIndex", | |
| 205 ARRAY_ARGS(AbbrevIndex4VoidTypeEdit), true)); | |
| 206 EXPECT_EQ( | |
| 207 "Error (Block 17): Uses illegal abbreviation index: 4: [2]\n" | |
| 208 "Successful parse!\n", | |
| 209 Munger.getTestResults()); | |
| 210 } | |
| 211 | |
| 212 // Show that error recovery works when dumping bitcode with a bad | |
| 213 // abbreviation index. | |
| 214 TEST(NaClMungeWriteErrorTests, RecoverWhenParsingBadAbbreviationIndex) { | |
| 215 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 216 Munger.setTryToRecoverOnWrite(true); | |
| 217 EXPECT_TRUE(Munger.runTest("RecoverWhenParsingBadAbbreviationIndex", | |
| 218 ARRAY_ARGS(AbbrevIndex4VoidTypeEdit))); | |
| 219 std::string Results( | |
| 220 "Error (Block 17): Uses illegal abbreviation index: 4: [2]\n"); | |
| 221 Results.append(ExpectedDump); | |
| 222 EXPECT_EQ(Results, Munger.getTestResults()); | |
| 223 } | |
| 224 | |
| 225 // Show that error recovery works when there is too many locally | |
| 226 // defined abbreviations for the corresponding number of bits defined | |
| 227 // in the corresponding enter block. | |
| 228 TEST(NaClMungeWriteErrorTests, RecoverTooManyLocalAbbreviations) { | |
| 229 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 230 Munger.setTryToRecoverOnWrite(true); | |
| 231 Munger.munge(ARRAY_ARGS(UseLocalRetVoidAbbrevEdits)); | |
| 232 | |
| 233 EXPECT_TRUE(Munger.runTest("RecoverTooManyLocalAbbreviations")); | |
| 234 std::string Results( | |
| 235 "Error (Block 12): Exceeds abbreviation index limit of 3: 2:" | |
| 236 " [65533, 1, 1, 10]\n" | |
| 237 "Error (Block 12): Uses illegal abbreviation index: 4: [10]\n"); | |
| 238 Results.append(ExpectedDump); | |
| 239 EXPECT_EQ( | |
| 240 Results, | |
| 241 Munger.getTestResults()); | |
| 242 } | |
| 243 | |
| 244 // Show that error recovery works when there are more enter blocks than | |
| 245 // exit blocks. | |
| 246 TEST(NaClMungeWriteErrorTests, RecoverTooManyEnterBlocks) { | |
| 247 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 248 // Remove all but first two records (i.e. two enter blocks). | |
| 249 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode(); | |
| 250 for (size_t i = 2; i < MungedBitcode.getBaseRecords().size(); ++i) { | |
| 251 MungedBitcode.remove(i); | |
| 252 } | |
| 253 | |
| 254 Munger.setTryToRecoverOnWrite(true); | |
| 255 EXPECT_TRUE(Munger.runTest("RecoverTooManyEnterBlocks")); | |
| 256 EXPECT_EQ( | |
| 257 "Error (Block 17): Missing close block.\n" | |
| 258 "Error (Block 8): Missing close block.\n" | |
| 259 " 0:0|<65532, 80, 69, 88, 69, 1, 0,|Magic Number: 'PEXE' (80, 69," | |
| 260 " 88, 69)\n" | |
| 261 " | 8, 0, 17, 0, 4, 0, 2, 0, 0, |PNaCl Version: 2\n" | |
| 262 " | 0> |\n" | |
| 263 " 16:0|1: <65535, 8, 2> |module { // BlockID = 8\n" | |
| 264 " 24:0| 1: <65535, 17, 3> | types { // BlockID = 17\n" | |
| 265 " 32:0| 0: <65534> | }\n" | |
| 266 " 36:0|0: <65534> |}\n", | |
| 267 Munger.getTestResults()); | |
| 268 } | |
| 269 | |
| 270 // Show that error recovery works when there are fewer enter blocks | |
| 271 // than exit blocks. | |
|
jvoung (off chromium)
2015/05/13 00:58:17
Similar comment to TooFewExitBlocks
| |
| 272 TEST(NaClMungeWriteErrorTests, RecoverTooFewExitBlocks) { | |
| 273 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 274 // Add two exit blocks. | |
| 275 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode(); | |
| 276 NaClRecordVector Values; | |
| 277 NaClBitcodeAbbrevRecord Record(0, naclbitc::BLK_CODE_EXIT, Values); | |
| 278 for (size_t i = 0; i < 2; ++i) | |
| 279 MungedBitcode.addAfter(MungedBitcode.getBaseRecords().size() - 1, Record); | |
| 280 | |
| 281 Munger.setTryToRecoverOnWrite(true); | |
| 282 EXPECT_TRUE(Munger.runTest("RecoverTooFewExitBlocks")); | |
| 283 std::string Results( | |
| 284 "Error (Block unknown): Extraneous exit block: 0: [65534]\n" | |
| 285 "Error (Block unknown): Extraneous exit block: 0: [65534]\n"); | |
| 286 Results.append(ExpectedDump); | |
| 287 EXPECT_EQ( | |
| 288 Results, | |
| 289 Munger.getTestResults()); | |
| 290 } | |
| 291 | |
| 292 // Show that error recovery works when writing a bitcode record that | |
| 293 // isn't in any block. | |
| 294 TEST(NaClMungeWriteErrorTests, RecoverWriteRecordOutsideBlock) { | |
| 295 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords)); | |
| 296 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode(); | |
| 297 NaClRecordVector Values; | |
| 298 Values.push_back(4); | |
| 299 NaClBitcodeAbbrevRecord Record(naclbitc::UNABBREV_RECORD, | |
| 300 naclbitc::MODULE_CODE_VERSION, | |
| 301 Values); | |
| 302 MungedBitcode.addAfter(MungedBitcode.getBaseRecords().size() - 1, Record); | |
| 303 | |
| 304 Munger.setTryToRecoverOnWrite(true); | |
| 305 EXPECT_TRUE(Munger.runTest("RecoverWriteRecordOutsideBlock")); | |
| 306 EXPECT_EQ( | |
| 307 "Error (Block unknown): Record outside block: 3: [1, 4]\n" | |
| 308 "Error (Block unknown): Missing close block.\n" | |
| 309 " 1: [65535, 8, 2]\n" | |
| 310 " 1: [65535, 17, 3]\n" | |
| 311 " 3: [1, 2]\n" | |
| 312 " 3: [2]\n" | |
| 313 " 3: [21, 0, 0]\n" | |
| 314 " 0: [65534]\n" | |
| 315 " 3: [8, 1, 0, 0, 0]\n" | |
| 316 " 1: [65535, 12, 2]\n" | |
| 317 " 3: [1, 1]\n" | |
| 318 " 3: [10]\n" | |
| 319 " 0: [65534]\n" | |
| 320 " 0: [65534]\n" | |
| 321 " 1: [65535, 4294967295, 3]\n" | |
| 322 " 3: [1, 4]\n" | |
| 323 " 0: [65534]\n", | |
| 324 Munger.getTestResults()); | |
| 325 } | |
| 326 | |
| 327 } // end of anonymous namespace. | |
| OLD | NEW |