Home | History | Annotate | Download | only in pnacl-llvm
      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 
     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 
     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::
     47 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 
     57 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 
     64 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.
     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 
     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.
    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 
    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 
    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 
    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 
    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::
    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 
    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 
    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::
    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::
    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::
    370 UpdateLock(BlockInfoRecordsMap &BlockInfoRecords)
    371     : BlockInfoRecords(BlockInfoRecords),
    372       Lock(BlockInfoRecords.UpdateRecordsLock) {}
    373 
    374 NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock::
    375 ~UpdateLock() {
    376   if (BlockInfoRecords.freeze())
    377     report_fatal_error("Global abbreviations block frozen while building.");
    378 }
    379 
    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