• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- NaClBitstreamReader.cpp --------------------------------------------===//
2 //     NaClBitstreamReader implementation
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 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/Bitcode/NaCl/NaClBitstreamReader.h"
13 #include "llvm/Support/Format.h"
14 #include "llvm/Support/raw_ostream.h"
15 
16 using namespace llvm;
17 
18 namespace {
19 
20 static const char *ErrorLevelName[] = {
21   "Warning",
22   "Error",
23   "Fatal"
24 };
25 
26 } // End of anonymous namespace.
27 
getBitAddress(uint64_t Bit)28 std::string llvm::naclbitc::getBitAddress(uint64_t Bit) {
29   std::string Buffer;
30   raw_string_ostream Stream(Buffer);
31   Stream << (Bit / 8) << ":" << (Bit % 8);
32   return Stream.str();
33 }
34 
ErrorAt(raw_ostream & Out,ErrorLevel Level,uint64_t BitPosition)35 raw_ostream &llvm::naclbitc::ErrorAt(
36     raw_ostream &Out, ErrorLevel Level, uint64_t BitPosition) {
37   assert(Level < array_lengthof(::ErrorLevelName));
38   return Out << ErrorLevelName[Level] << "("
39              << naclbitc::getBitAddress(BitPosition) << "): ";
40 }
41 
42 //===----------------------------------------------------------------------===//
43 //  NaClBitstreamCursor implementation
44 //===----------------------------------------------------------------------===//
45 
46 void NaClBitstreamCursor::ErrorHandler::
Fatal(const std::string & ErrorMessage) const47 Fatal(const std::string &ErrorMessage) const {
48   // Default implementation is simply print message, and the bit where
49   // the error occurred.
50   std::string Buffer;
51   raw_string_ostream StrBuf(Buffer);
52   naclbitc::ErrorAt(StrBuf, naclbitc::Fatal,
53                     Cursor.getErrorBitNo(getCurrentBitNo())) << ErrorMessage;
54   report_fatal_error(StrBuf.str());
55 }
56 
reportInvalidAbbrevNumber(unsigned AbbrevNo) const57 void NaClBitstreamCursor::reportInvalidAbbrevNumber(unsigned AbbrevNo) const {
58   std::string Buffer;
59   raw_string_ostream StrBuf(Buffer);
60   StrBuf << "Invalid abbreviation # " << AbbrevNo << " defined for record";
61   ErrHandler->Fatal(StrBuf.str());
62 }
63 
reportInvalidJumpToBit(uint64_t BitNo) const64 void NaClBitstreamCursor::reportInvalidJumpToBit(uint64_t BitNo) const {
65   std::string Buffer;
66   raw_string_ostream StrBuf(Buffer);
67   StrBuf << "Invalid jump to bit " << BitNo;
68   ErrHandler->Fatal(StrBuf.str());
69 }
70 
71 /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
72 /// the block, and return true if the block has an error.
EnterSubBlock(unsigned BlockID,unsigned * NumWordsP)73 bool NaClBitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
74   const bool IsFixed = true;
75   NaClBitcodeSelectorAbbrev
76       CodeAbbrev(IsFixed, ReadVBR(naclbitc::CodeLenWidth));
77   BlockScope.push_back(Block(BitStream->getBlockInfo(BlockID), CodeAbbrev));
78   SkipToFourByteBoundary();
79   unsigned NumWords = Read(naclbitc::BlockSizeWidth);
80   if (NumWordsP) *NumWordsP = NumWords;
81 
82   // Validate that this block is sane.
83   if (BlockScope.back().getCodeAbbrev().NumBits == 0 || AtEndOfStream())
84     return true;
85 
86   return false;
87 }
88 
skipAbbreviatedField(const NaClBitCodeAbbrevOp & Op)89 void NaClBitstreamCursor::skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op) {
90   // Decode the value as we are commanded.
91   switch (Op.getEncoding()) {
92   case NaClBitCodeAbbrevOp::Literal:
93     // No read necessary for literal.
94     break;
95   case NaClBitCodeAbbrevOp::Fixed:
96     (void)Read((unsigned)Op.getValue());
97     break;
98   case NaClBitCodeAbbrevOp::VBR:
99     (void)ReadVBR64((unsigned)Op.getValue());
100     break;
101   case NaClBitCodeAbbrevOp::Array:
102     // This can't happen because the abbreviation must be valid.
103     llvm_unreachable("Bad array abbreviation encoding!");
104     break;
105   case NaClBitCodeAbbrevOp::Char6:
106     (void)Read(6);
107     break;
108   }
109 }
110 
111 /// skipRecord - Read the current record and discard it.
skipRecord(unsigned AbbrevID)112 void NaClBitstreamCursor::skipRecord(unsigned AbbrevID) {
113   // Skip unabbreviated records by reading past their entries.
114   if (AbbrevID == naclbitc::UNABBREV_RECORD) {
115     unsigned Code = ReadVBR(6);
116     (void)Code;
117     unsigned NumElts = ReadVBR(6);
118     for (unsigned i = 0; i != NumElts; ++i)
119       (void)ReadVBR64(6);
120     SkipToByteBoundaryIfAligned();
121     return;
122   }
123 
124   const NaClBitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
125 
126   for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) {
127     const NaClBitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
128     switch (Op.getEncoding()) {
129     default:
130       skipAbbreviatedField(Op);
131       break;
132     case NaClBitCodeAbbrevOp::Literal:
133       break;
134     case NaClBitCodeAbbrevOp::Array: {
135       // Array case.  Read the number of elements as a vbr6.
136       unsigned NumElts = ReadVBR(6);
137 
138       // Get the element encoding.
139       const NaClBitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
140 
141       // Read all the elements.
142       for (; NumElts; --NumElts)
143         skipAbbreviatedField(EltEnc);
144       break;
145     }
146     }
147   }
148   SkipToByteBoundaryIfAligned();
149 }
150 
readRecordAbbrevField(const NaClBitCodeAbbrevOp & Op,uint64_t & Value)151 bool NaClBitstreamCursor::readRecordAbbrevField(
152     const NaClBitCodeAbbrevOp &Op, uint64_t &Value) {
153   switch (Op.getEncoding()) {
154   case NaClBitCodeAbbrevOp::Literal:
155     Value = Op.getValue();
156     break;
157   case NaClBitCodeAbbrevOp::Array:
158     // Returns number of elements in the array.
159     Value = ReadVBR(6);
160     return true;
161   case NaClBitCodeAbbrevOp::Fixed:
162     Value = Read((unsigned)Op.getValue());
163     break;
164   case NaClBitCodeAbbrevOp::VBR:
165     Value = ReadVBR64((unsigned)Op.getValue());
166     break;
167   case NaClBitCodeAbbrevOp::Char6:
168     Value = NaClBitCodeAbbrevOp::DecodeChar6(Read(6));
169     break;
170   }
171   return false;
172 }
173 
readArrayAbbreviatedField(const NaClBitCodeAbbrevOp & Op)174 uint64_t NaClBitstreamCursor::readArrayAbbreviatedField(
175     const NaClBitCodeAbbrevOp &Op) {
176   // Decode the value as we are commanded.
177   switch (Op.getEncoding()) {
178   case NaClBitCodeAbbrevOp::Literal:
179     return Op.getValue();
180   case NaClBitCodeAbbrevOp::Fixed:
181     return Read((unsigned)Op.getValue());
182   case NaClBitCodeAbbrevOp::VBR:
183     return ReadVBR64((unsigned)Op.getValue());
184   case NaClBitCodeAbbrevOp::Array:
185     // This can't happen because the abbreviation must be valid.
186     llvm_unreachable("Bad array abbreviation encoding!");
187     break;
188   case NaClBitCodeAbbrevOp::Char6:
189     return NaClBitCodeAbbrevOp::DecodeChar6(Read(6));
190   }
191   llvm_unreachable("Illegal abbreviation encoding for field!");
192 }
193 
readArrayAbbrev(const NaClBitCodeAbbrevOp & Op,unsigned NumArrayElements,SmallVectorImpl<uint64_t> & Vals)194 void NaClBitstreamCursor::readArrayAbbrev(
195     const NaClBitCodeAbbrevOp &Op, unsigned NumArrayElements,
196     SmallVectorImpl<uint64_t> &Vals) {
197   for (; NumArrayElements; --NumArrayElements) {
198     Vals.push_back(readArrayAbbreviatedField(Op));
199   }
200 }
201 
readRecord(unsigned AbbrevID,SmallVectorImpl<uint64_t> & Vals)202 unsigned NaClBitstreamCursor::readRecord(unsigned AbbrevID,
203                                          SmallVectorImpl<uint64_t> &Vals) {
204   if (AbbrevID == naclbitc::UNABBREV_RECORD) {
205     unsigned Code = ReadVBR(6);
206     unsigned NumElts = ReadVBR(6);
207     for (unsigned i = 0; i != NumElts; ++i)
208       Vals.push_back(ReadVBR64(6));
209     SkipToByteBoundaryIfAligned();
210     return Code;
211   }
212 
213   // Read code.
214   const NaClBitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
215   uint64_t Value;
216   unsigned Code;
217   if (readRecordAbbrevField(Abbv->getOperandInfo(0), Value)) {
218     // Array found, use to read all elements.
219     if (Value == 0)
220       ErrHandler->Fatal("No code found for record!");
221     const NaClBitCodeAbbrevOp &Op = Abbv->getOperandInfo(1);
222     Code = readArrayAbbreviatedField(Op);
223     readArrayAbbrev(Op, Value - 1, Vals);
224     SkipToByteBoundaryIfAligned();
225     return Code;
226   }
227   Code = Value;
228 
229   // Read arguments.
230   unsigned NumOperands = Abbv->getNumOperandInfos();
231   for (unsigned i = 1; i != NumOperands; ++i) {
232     if (readRecordAbbrevField(Abbv->getOperandInfo(i), Value)) {
233       ++i;
234       readArrayAbbrev(Abbv->getOperandInfo(i), Value, Vals);
235       SkipToByteBoundaryIfAligned();
236       return Code;
237     }
238     Vals.push_back(Value);
239   }
240   SkipToByteBoundaryIfAligned();
241   return Code;
242 }
243 
244 
245 NaClBitCodeAbbrevOp::Encoding NaClBitstreamCursor::
getEncoding(uint64_t Value)246 getEncoding(uint64_t Value) {
247   if (!NaClBitCodeAbbrevOp::isValidEncoding(Value)) {
248     std::string Buffer;
249     raw_string_ostream StrBuf(Buffer);
250     StrBuf << "Invalid abbreviation encoding specified in bitcode file: "
251            << Value;
252     ErrHandler->Fatal(StrBuf.str());
253   }
254   return NaClBitCodeAbbrevOp::Encoding(Value);
255 }
256 
ReadAbbrevRecord(bool IsLocal,NaClAbbrevListener * Listener)257 void NaClBitstreamCursor::ReadAbbrevRecord(bool IsLocal,
258                                            NaClAbbrevListener *Listener) {
259   NaClBitCodeAbbrev *Abbv = BlockScope.back().appendLocalCreate();
260   unsigned NumOpInfo = ReadVBR(5);
261   if (Listener) Listener->Values.push_back(NumOpInfo);
262   for (unsigned i = 0; i != NumOpInfo; ++i) {
263     bool IsLiteral = Read(1) ? true : false;
264     if (Listener) Listener->Values.push_back(IsLiteral);
265     if (IsLiteral) {
266       uint64_t Value = ReadVBR64(8);
267       if (Listener) Listener->Values.push_back(Value);
268       Abbv->Add(NaClBitCodeAbbrevOp(Value));
269       continue;
270     }
271     NaClBitCodeAbbrevOp::Encoding E = getEncoding(Read(3));
272     if (Listener) Listener->Values.push_back(E);
273     if (NaClBitCodeAbbrevOp::hasValue(E)) {
274       unsigned Data = ReadVBR64(5);
275       if (Listener) Listener->Values.push_back(Data);
276 
277       // As a special case, handle fixed(0) (i.e., a fixed field with zero bits)
278       // and vbr(0) as a literal zero.  This is decoded the same way, and avoids
279       // a slow path in Read() to have to handle reading zero bits.
280       if ((E == NaClBitCodeAbbrevOp::Fixed || E == NaClBitCodeAbbrevOp::VBR) &&
281           Data == 0) {
282         if (Listener) Listener->Values.push_back(0);
283         Abbv->Add(NaClBitCodeAbbrevOp(0));
284         continue;
285       }
286       if (!NaClBitCodeAbbrevOp::isValid(E, Data)) {
287         std::string Buffer;
288         raw_string_ostream StrBuf(Buffer);
289         StrBuf << "Invalid abbreviation encoding ("
290                << NaClBitCodeAbbrevOp::getEncodingName(E)
291                << ", " << Data << ")";
292         ErrHandler->Fatal(StrBuf.str());
293       }
294       Abbv->Add(NaClBitCodeAbbrevOp(E, Data));
295     } else {
296       if (!NaClBitCodeAbbrevOp::isValid(E)) {
297         std::string Buffer;
298         raw_string_ostream StrBuf(Buffer);
299         StrBuf << "Invalid abbreviation encoding ("
300                << NaClBitCodeAbbrevOp::getEncodingName(E) << ")";
301         ErrHandler->Fatal(StrBuf.str());
302       }
303       Abbv->Add(NaClBitCodeAbbrevOp(E));
304     }
305   }
306   SkipToByteBoundaryIfAligned();
307   if (!Abbv->isValid())
308     ErrHandler->Fatal("Invalid abbreviation specified in bitcode file");
309   if (Listener) {
310     Listener->ProcessAbbreviation(Abbv, IsLocal);
311     // Reset record information of the listener.
312     Listener->Values.clear();
313     Listener->StartBit = GetCurrentBitNo();
314   }
315 }
316 
SkipAbbrevRecord()317 void NaClBitstreamCursor::SkipAbbrevRecord() {
318   unsigned NumOpInfo = ReadVBR(5);
319   for (unsigned i = 0; i != NumOpInfo; ++i) {
320     bool IsLiteral = Read(1) ? true : false;
321     if (IsLiteral) {
322       ReadVBR64(8);
323       continue;
324     }
325     NaClBitCodeAbbrevOp::Encoding E = getEncoding(Read(3));
326     if (NaClBitCodeAbbrevOp::hasValue(E)) {
327       ReadVBR64(5);
328     }
329   }
330   SkipToByteBoundaryIfAligned();
331 }
332 
333 namespace {
334 
335 unsigned ValidBlockIDs[] = {
336   naclbitc::BLOCKINFO_BLOCK_ID,
337   naclbitc::CONSTANTS_BLOCK_ID,
338   naclbitc::FUNCTION_BLOCK_ID,
339   naclbitc::GLOBALVAR_BLOCK_ID,
340   naclbitc::MODULE_BLOCK_ID,
341   naclbitc::TOP_LEVEL_BLOCKID,
342   naclbitc::TYPE_BLOCK_ID_NEW,
343   naclbitc::VALUE_SYMTAB_BLOCK_ID
344 };
345 
346 } // end of anonymous namespace
347 
348 NaClBitstreamReader::BlockInfoRecordsMap::
BlockInfoRecordsMap()349 BlockInfoRecordsMap() : IsFrozen(false) {
350   for (size_t BlockID : ValidBlockIDs) {
351     std::unique_ptr<BlockInfo> Info(new BlockInfo(BlockID));
352     KnownInfos.emplace(BlockID, std::move(Info));
353   }
354 }
355 
356 NaClBitstreamReader::BlockInfo * NaClBitstreamReader::BlockInfoRecordsMap::
getOrCreateUnknownBlockInfo(unsigned BlockID)357 getOrCreateUnknownBlockInfo(unsigned BlockID) {
358   std::unique_lock<std::mutex> Lock(UnknownBlockInfoLock);
359   while (true) {
360     auto Pos = UnknownInfos.find(BlockID);
361     if (Pos != UnknownInfos.end())
362       return Pos->second.get();
363     // Install, then let next iteration find.
364     std::unique_ptr<BlockInfo> Info(new BlockInfo(BlockID));
365     UnknownInfos.emplace(BlockID, std::move(Info));
366   }
367 }
368 
369 NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock::
UpdateLock(BlockInfoRecordsMap & BlockInfoRecords)370 UpdateLock(BlockInfoRecordsMap &BlockInfoRecords)
371     : BlockInfoRecords(BlockInfoRecords),
372       Lock(BlockInfoRecords.UpdateRecordsLock) {}
373 
374 NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock::
~UpdateLock()375 ~UpdateLock() {
376   if (BlockInfoRecords.freeze())
377     report_fatal_error("Global abbreviations block frozen while building.");
378 }
379 
ReadBlockInfoBlock(NaClAbbrevListener * Listener)380 bool NaClBitstreamCursor::ReadBlockInfoBlock(NaClAbbrevListener *Listener) {
381   // If this is the second read of the block info block, skip it.
382   if (BitStream->BlockInfoRecords->isFrozen())
383     return SkipBlock();
384 
385   NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock
386       Lock(*BitStream->BlockInfoRecords);
387   unsigned NumWords;
388   if (EnterSubBlock(naclbitc::BLOCKINFO_BLOCK_ID, &NumWords)) return true;
389 
390   if (Listener) Listener->BeginBlockInfoBlock(NumWords);
391 
392   NaClBitcodeRecordVector Record;
393   Block &CurBlock = BlockScope.back();
394   NaClBitstreamReader::AbbrevList *UpdateAbbrevs =
395       &CurBlock.GlobalAbbrevs->getAbbrevs();
396   bool FoundSetBID = false;
397 
398   // Read records of the BlockInfo block.
399   while (1) {
400     if (Listener) Listener->StartBit = GetCurrentBitNo();
401     NaClBitstreamEntry Entry = advance(AF_DontAutoprocessAbbrevs, Listener);
402 
403     switch (Entry.Kind) {
404     case llvm::NaClBitstreamEntry::SubBlock:  // PNaCl doesn't allow!
405     case llvm::NaClBitstreamEntry::Error:
406       return true;
407     case llvm::NaClBitstreamEntry::EndBlock:
408       if (Listener) Listener->EndBlockInfoBlock();
409       return false;
410     case llvm::NaClBitstreamEntry::Record:
411       // The interesting case.
412       break;
413     }
414 
415     // Read abbrev records, associate them with CurBID.
416     if (Entry.ID == naclbitc::DEFINE_ABBREV) {
417       ReadAbbrevRecord(false, Listener);
418 
419       // ReadAbbrevRecord installs a local abbreviation.  Move it to the
420       // appropriate BlockInfo if the corresponding SetBID record has been
421       // found.
422       if (FoundSetBID)
423         CurBlock.moveLocalAbbrevToAbbrevList(UpdateAbbrevs);
424       continue;
425     }
426 
427     // Read a record.
428     Record.clear();
429     switch (readRecord(Entry.ID, Record)) {
430       default:
431         // No other records should be found!
432         return true;
433       case naclbitc::BLOCKINFO_CODE_SETBID:
434         if (Record.size() < 1) return true;
435         FoundSetBID = true;
436         UpdateAbbrevs =
437             &BitStream->getBlockInfo((unsigned)Record[0])->getAbbrevs();
438         if (Listener) {
439           Listener->Values = Record;
440           Listener->SetBID();
441         }
442         break;
443     }
444   }
445 }
446