Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: include/llvm/Bitcode/NaCl/NaClBitstreamReader.h

Issue 932953002: Fix the NaCl bitstream reader to report fatal errors. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Fix nits. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===// 1 //===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===//
2 // Low-level bitstream reader interface 2 // Low-level bitstream reader interface
3 // 3 //
4 // The LLVM Compiler Infrastructure 4 // The LLVM Compiler Infrastructure
5 // 5 //
6 // This file is distributed under the University of Illinois Open Source 6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details. 7 // License. See LICENSE.TXT for details.
8 // 8 //
9 //===----------------------------------------------------------------------===// 9 //===----------------------------------------------------------------------===//
10 // 10 //
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 Info.Abbrevs[i]->dropRef(); 83 Info.Abbrevs[i]->dropRef();
84 BlockInfoRecords.pop_back(); 84 BlockInfoRecords.pop_back();
85 } 85 }
86 } 86 }
87 87
88 /// \brief Returns the initial address (after the header) of the input stream. 88 /// \brief Returns the initial address (after the header) of the input stream.
89 size_t getInitialAddress() const { 89 size_t getInitialAddress() const {
90 return InitialAddress; 90 return InitialAddress;
91 } 91 }
92 92
93 /// Returns the Bit as a Byte:BitInByte string. MinByteWidth is the
94 /// minimum number of characters to print out the Byte value (blank
95 /// fills).
96 static std::string getBitAddress(uint64_t Bit, unsigned MinByteWidth=1);
97
93 //===--------------------------------------------------------------------===// 98 //===--------------------------------------------------------------------===//
94 // Block Manipulation 99 // Block Manipulation
95 //===--------------------------------------------------------------------===// 100 //===--------------------------------------------------------------------===//
96 101
97 /// hasBlockInfoRecords - Return true if we've already read and processed the 102 /// hasBlockInfoRecords - Return true if we've already read and processed the
98 /// block info block for this Bitstream. We only process it for the first 103 /// block info block for this Bitstream. We only process it for the first
99 /// cursor that walks over it. 104 /// cursor that walks over it.
100 bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } 105 bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); }
101 106
102 /// getBlockInfo - If there is block info for the specified ID, return it, 107 /// getBlockInfo - If there is block info for the specified ID, return it,
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 uint64_t StartBit; 207 uint64_t StartBit;
203 }; 208 };
204 209
205 /// NaClBitstreamCursor - This represents a position within a bitcode 210 /// NaClBitstreamCursor - This represents a position within a bitcode
206 /// file. There may be multiple independent cursors reading within 211 /// file. There may be multiple independent cursors reading within
207 /// one bitstream, each maintaining their own local state. 212 /// one bitstream, each maintaining their own local state.
208 /// 213 ///
209 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects 214 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects
210 /// that should not be passed by value. 215 /// that should not be passed by value.
211 class NaClBitstreamCursor { 216 class NaClBitstreamCursor {
217 public:
218 /// This class handles errors in the bitstream reader. Redirects
219 /// fatal error messages to virtual method Fatal.
220 class ErrorHandler {
221 ErrorHandler(const ErrorHandler &) = delete;
222 ErrorHandler &operator=(const ErrorHandler &) = delete;
223 public:
224 explicit ErrorHandler(NaClBitstreamCursor &Cursor) : Cursor(Cursor) {}
225 LLVM_ATTRIBUTE_NORETURN
226 virtual void Fatal(const std::string &ErrorMessage) const;
227 virtual ~ErrorHandler() {}
228 uint64_t getCurrentBitNo() const {
229 return Cursor.GetCurrentBitNo();
230 }
231 private:
232 NaClBitstreamCursor &Cursor;
233 };
234
235 private:
212 friend class Deserializer; 236 friend class Deserializer;
213 NaClBitstreamReader *BitStream; 237 NaClBitstreamReader *BitStream;
214 size_t NextChar; 238 size_t NextChar;
239 // The current error handler for the bitstream reader.
240 std::unique_ptr<ErrorHandler> ErrHandler;
215 241
216 /// CurWord/word_t - This is the current data we have pulled from the stream 242 /// CurWord/word_t - This is the current data we have pulled from the stream
217 /// but have not returned to the client. This is specifically and 243 /// but have not returned to the client. This is specifically and
218 /// intentionally defined to follow the word size of the host machine for 244 /// intentionally defined to follow the word size of the host machine for
219 /// efficiency. We use word_t in places that are aware of this to make it 245 /// efficiency. We use word_t in places that are aware of this to make it
220 /// perfectly explicit what is going on. 246 /// perfectly explicit what is going on.
221 typedef uint32_t word_t; 247 typedef uint32_t word_t;
222 word_t CurWord; 248 word_t CurWord;
223 249
224 /// BitsInCurWord - This is the number of bits in CurWord that are valid. This 250 /// BitsInCurWord - This is the number of bits in CurWord that are valid. This
(...skipping 16 matching lines...) Expand all
241 }; 267 };
242 268
243 /// BlockScope - This tracks the codesize of parent blocks. 269 /// BlockScope - This tracks the codesize of parent blocks.
244 SmallVector<Block, 8> BlockScope; 270 SmallVector<Block, 8> BlockScope;
245 271
246 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION; 272 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION;
247 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT ION; 273 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT ION;
248 274
249 public: 275 public:
250 276
251 NaClBitstreamCursor() { 277 NaClBitstreamCursor() : ErrHandler(new ErrorHandler(*this)) {
252 init(nullptr); 278 init(nullptr);
253 } 279 }
254 280
255 explicit NaClBitstreamCursor(NaClBitstreamReader &R) { init(&R); } 281 explicit NaClBitstreamCursor(NaClBitstreamReader &R)
282 : ErrHandler(new ErrorHandler(*this)) { init(&R); }
256 283
257 void init(NaClBitstreamReader *R) { 284 void init(NaClBitstreamReader *R) {
258 freeState(); 285 freeState();
259 BitStream = R; 286 BitStream = R;
260 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); 287 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress();
261 CurWord = 0; 288 CurWord = 0;
262 BitsInCurWord = 0; 289 BitsInCurWord = 0;
263 } 290 }
264 291
265 ~NaClBitstreamCursor() { 292 ~NaClBitstreamCursor() {
266 freeState(); 293 freeState();
267 } 294 }
268 295
269 void freeState(); 296 void freeState();
270 297
298 // Replaces the current bitstream error handler with the new
299 // handler. Takes ownership of the new handler and deletes it when
300 // it is no longer needed.
301 void setErrorHandler(std::unique_ptr<ErrorHandler> &NewHandler) {
302 ErrHandler = std::move(NewHandler);
303 }
304
271 bool isEndPos(size_t pos) { 305 bool isEndPos(size_t pos) {
272 return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); 306 return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos));
273 } 307 }
274 308
275 bool canSkipToPos(size_t pos) const { 309 bool canSkipToPos(size_t pos) const {
276 // pos can be skipped to if it is a valid address or one byte past the end. 310 // pos can be skipped to if it is a valid address or one byte past the end.
277 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( 311 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
278 static_cast<uint64_t>(pos - 1)); 312 static_cast<uint64_t>(pos - 1));
279 } 313 }
280 314
281 bool AtEndOfStream() { 315 bool AtEndOfStream() {
282 return BitsInCurWord == 0 && isEndPos(NextChar); 316 return BitsInCurWord == 0 && isEndPos(NextChar);
283 } 317 }
284 318
285 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. 319 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
286 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } 320 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; }
287 321
288 /// GetCurrentBitNo - Return the bit # of the bit we are reading. 322 /// GetCurrentBitNo - Return the bit # of the bit we are reading.
289 uint64_t GetCurrentBitNo() const { 323 uint64_t GetCurrentBitNo() const {
290 return NextChar*CHAR_BIT - BitsInCurWord; 324 return NextChar*CHAR_BIT - BitsInCurWord;
291 } 325 }
292 326
293 NaClBitstreamReader *getBitStreamReader() { 327 NaClBitstreamReader *getBitStreamReader() {
294 return BitStream; 328 return BitStream;
295 } 329 }
296 const NaClBitstreamReader *getBitStreamReader() const { 330 const NaClBitstreamReader *getBitStreamReader() const {
297 return BitStream; 331 return BitStream;
298 } 332 }
299 333
334 /// Returns Bit as a Byte::BitInByte string. MinByteWidth is the
335 /// minimum number of characters to print out the Byte value (blank
336 /// fills).
337 std::string getBitAddress(uint64_t Bit, unsigned MinByteWidth=1) const {
338 return BitStream->getBitAddress(Bit, MinByteWidth);
jvoung (off chromium) 2015/02/23 18:58:56 Is it useful to have this wrapper or can the bitst
Karl 2015/02/23 20:46:22 Removed.
339 }
340
341 /// Returns the current bit address (string) of the bit cursor.
342 /// MinByteWidth is the minimum number of characters to print out
343 /// the Byte value (blank fills).
344 std::string getCurrentBitAddress(unsigned MinByteWidth=1) const {
345 return BitStream->getBitAddress(GetCurrentBitNo(), MinByteWidth);
346 }
347
300 /// Flags that modify the behavior of advance(). 348 /// Flags that modify the behavior of advance().
301 enum { 349 enum {
302 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does 350 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does
303 /// not automatically pop the block scope when the end of a block is 351 /// not automatically pop the block scope when the end of a block is
304 /// reached. 352 /// reached.
305 AF_DontPopBlockAtEnd = 1, 353 AF_DontPopBlockAtEnd = 1,
306 354
307 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are 355 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are
308 /// returned just like normal records. 356 /// returned just like normal records.
309 AF_DontAutoprocessAbbrevs = 2 357 AF_DontAutoprocessAbbrevs = 2
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 // If we found a sub-block, just skip over it and check the next entry. 396 // If we found a sub-block, just skip over it and check the next entry.
349 if (SkipBlock()) 397 if (SkipBlock())
350 return NaClBitstreamEntry::getError(); 398 return NaClBitstreamEntry::getError();
351 } 399 }
352 } 400 }
353 401
354 /// JumpToBit - Reset the stream to the specified bit number. 402 /// JumpToBit - Reset the stream to the specified bit number.
355 void JumpToBit(uint64_t BitNo) { 403 void JumpToBit(uint64_t BitNo) {
356 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); 404 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1);
357 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); 405 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
358 assert(canSkipToPos(ByteNo) && "Invalid location"); 406 if (!canSkipToPos(ByteNo))
407 reportInvalidJumpToBit(BitNo);
359 408
360 // Move the cursor to the right word. 409 // Move the cursor to the right word.
361 NextChar = ByteNo; 410 NextChar = ByteNo;
362 BitsInCurWord = 0; 411 BitsInCurWord = 0;
363 CurWord = 0; 412 CurWord = 0;
364 413
365 // Skip over any bits that are already consumed. 414 // Skip over any bits that are already consumed.
366 if (WordBitNo) { 415 if (WordBitNo) {
367 if (sizeof(word_t) > 4) 416 if (sizeof(word_t) > 4)
368 Read64(WordBitNo); 417 Read64(WordBitNo);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 595
547 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); 596 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
548 BlockScope.pop_back(); 597 BlockScope.pop_back();
549 } 598 }
550 599
551 //===--------------------------------------------------------------------===// 600 //===--------------------------------------------------------------------===//
552 // Record Processing 601 // Record Processing
553 //===--------------------------------------------------------------------===// 602 //===--------------------------------------------------------------------===//
554 603
555 private: 604 private:
605 // Returns abbreviation encoding associated with Value.
606 NaClBitCodeAbbrevOp::Encoding getEncoding(uint64_t Value);
607
556 void skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op); 608 void skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op);
557 609
558 // Reads the next Value using the abbreviation Op. Returns true only 610 // Reads the next Value using the abbreviation Op. Returns true only
559 // if Op is an array (and sets Value to the number of elements in the 611 // if Op is an array (and sets Value to the number of elements in the
560 // array). 612 // array).
561 inline bool readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op, 613 inline bool readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op,
562 uint64_t &Value); 614 uint64_t &Value);
563 615
564 // Reads and returns the next value using the abbreviation Op, 616 // Reads and returns the next value using the abbreviation Op,
565 // assuming Op appears after an array abbreviation. 617 // assuming Op appears after an array abbreviation.
566 inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op); 618 inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op);
567 619
568 // Reads the array abbreviation Op, NumArrayElements times, putting 620 // Reads the array abbreviation Op, NumArrayElements times, putting
569 // the read values in Vals. 621 // the read values in Vals.
570 inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op, 622 inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op,
571 unsigned NumArrayElements, 623 unsigned NumArrayElements,
572 SmallVectorImpl<uint64_t> &Vals); 624 SmallVectorImpl<uint64_t> &Vals);
573 625
626 // Reports that that abbreviation Index is not valid.
627 void reportInvalidAbbrevNumber(unsigned Index) const;
628
629 // Reports that jumping to Bit is not valid.
630 void reportInvalidJumpToBit(uint64_t Bit) const;
631
574 public: 632 public:
575 633
576 /// getAbbrev - Return the abbreviation for the specified AbbrevId. 634 /// getAbbrev - Return the abbreviation for the specified AbbrevId.
577 const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const { 635 const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const {
578 unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV; 636 unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV;
579 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); 637 if (AbbrevNo >= CurAbbrevs.size())
638 reportInvalidAbbrevNumber(AbbrevID);
580 return CurAbbrevs[AbbrevNo]; 639 return CurAbbrevs[AbbrevNo];
581 } 640 }
582 641
583 /// skipRecord - Read the current record and discard it. 642 /// skipRecord - Read the current record and discard it.
584 void skipRecord(unsigned AbbrevID); 643 void skipRecord(unsigned AbbrevID);
585 644
586 unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals); 645 unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals);
587 646
588 //===--------------------------------------------------------------------===// 647 //===--------------------------------------------------------------------===//
589 // Abbrev Processing 648 // Abbrev Processing
590 //===--------------------------------------------------------------------===// 649 //===--------------------------------------------------------------------===//
591 // IsLocal indicates where the abbreviation occurs. If it is in the 650 // IsLocal indicates where the abbreviation occurs. If it is in the
592 // BlockInfo block, IsLocal is false. In all other cases, IsLocal is 651 // BlockInfo block, IsLocal is false. In all other cases, IsLocal is
593 // true. 652 // true.
594 void ReadAbbrevRecord(bool IsLocal, 653 void ReadAbbrevRecord(bool IsLocal,
595 NaClAbbrevListener *Listener); 654 NaClAbbrevListener *Listener);
596 655
597 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord, 656 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord,
598 // except that no abbreviation is built. 657 // except that no abbreviation is built.
599 void SkipAbbrevRecord(); 658 void SkipAbbrevRecord();
600 659
601 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener); 660 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener);
602 }; 661 };
603 662
604 } // End llvm namespace 663 } // End llvm namespace
605 664
606 #endif 665 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698