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