| Index: lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
|
| diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
|
| index 6162c24cc93b9918ef1fa41e1156fea9dbd3f01d..7b12de8bc78227dc5052004e1c332b7c37eed283 100644
|
| --- a/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
|
| +++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
|
| @@ -9,6 +9,8 @@
|
| //===----------------------------------------------------------------------===//
|
|
|
| #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
|
| +
|
| +#include "llvm/ADT/SmallSet.h"
|
| #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
|
| #include "llvm/Bitcode/ReaderWriter.h"
|
| #include "llvm/Support/ErrorHandling.h"
|
| @@ -16,17 +18,57 @@
|
| #include "llvm/Support/raw_ostream.h"
|
| #include "llvm/Support/StreamingMemoryObject.h"
|
|
|
| -#include <limits>
|
| #include <cstring>
|
| #include <iomanip>
|
| +#include <limits>
|
|
|
| using namespace llvm;
|
|
|
| +namespace {
|
| +
|
| +// The name for each ID tag.
|
| +static const char *TagName[] = {
|
| + "Invalid", // kInvalid
|
| + "PNaCl Version", // kPNaClVersion
|
| + "Align bitcode records" // kAlignBitcodeRecords
|
| +};
|
| +
|
| +// The name for each field type.
|
| +static const char *FieldTypeName[] = {
|
| + "uint8[]", // kBufferType
|
| + "uint32", // kUInt32Type
|
| + "flag", // kFlagType
|
| + "unknown" // kUnknownType
|
| +};
|
| +
|
| +// The type associated with each ID tag.
|
| +static const NaClBitcodeHeaderField::FieldType ExpectedType[] = {
|
| + NaClBitcodeHeaderField::kUnknownType, // kInvalid
|
| + NaClBitcodeHeaderField::kUInt32Type, // kPNaClVersion
|
| + NaClBitcodeHeaderField::kFlagType // kAlignBitcodeRecords
|
| +};
|
| +
|
| +} // end of anonymous namespace
|
| +
|
| +const char *NaClBitcodeHeaderField::IDName(Tag ID) {
|
| + return ID > kTag_MAX ? "???" : TagName[ID];
|
| +}
|
| +
|
| +const char *NaClBitcodeHeaderField::TypeName(FieldType FType) {
|
| + return FType > kFieldType_MAX ? "???" : FieldTypeName[FType];
|
| +}
|
| +
|
| NaClBitcodeHeaderField::NaClBitcodeHeaderField()
|
| - : ID(kInvalid), FType(kBufferType), Len(0), Data(0) {}
|
| + : ID(kInvalid), FType(kBufferType), Len(0), Data(0) {}
|
| +
|
| +NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID)
|
| + : ID(MyID), FType(kFlagType), Len(0), Data(0) {
|
| + assert(MyID <= kTag_MAX);
|
| +}
|
|
|
| NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, uint32_t MyValue)
|
| : ID(MyID), FType(kUInt32Type), Len(4), Data(new uint8_t[4]) {
|
| + assert(MyID <= kTag_MAX);
|
| Data[0] = static_cast<uint8_t>(MyValue & 0xFF);
|
| Data[1] = static_cast<uint8_t>((MyValue >> 8) & 0xFF);
|
| Data[2] = static_cast<uint8_t>((MyValue >> 16) & 0xFF);
|
| @@ -44,6 +86,7 @@ uint32_t NaClBitcodeHeaderField::GetUInt32Value() const {
|
| NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, size_t MyLen,
|
| uint8_t *MyData)
|
| : ID(MyID), FType(kBufferType), Len(MyLen), Data(new uint8_t[MyLen]) {
|
| + assert(MyID <= kTag_MAX);
|
| for (size_t i = 0; i < MyLen; ++i) {
|
| Data[i] = MyData[i];
|
| }
|
| @@ -94,16 +137,11 @@ bool NaClBitcodeHeaderField::Read(const uint8_t *Buf, size_t BufLen) {
|
| std::string NaClBitcodeHeaderField::Contents() const {
|
| std::string buffer;
|
| raw_string_ostream ss(buffer);
|
| - switch (ID) {
|
| - case kPNaClVersion:
|
| - ss << "PNaCl Version";
|
| - break;
|
| - case kInvalid:
|
| - ss << "Invalid";
|
| - break;
|
| - }
|
| - ss << ": ";
|
| + ss << IDName() << ": ";
|
| switch (FType) {
|
| + case kFlagType:
|
| + ss << "true";
|
| + break;
|
| case kUInt32Type:
|
| ss << GetUInt32Value();
|
| break;
|
| @@ -116,6 +154,9 @@ std::string NaClBitcodeHeaderField::Contents() const {
|
| }
|
| ss << "]";
|
| break;
|
| + case kUnknownType:
|
| + ss << "unknown value";
|
| + break;
|
| }
|
| return ss.str();
|
| }
|
| @@ -175,8 +216,8 @@ bool NaClBitcodeHeader::ReadFields(const unsigned char *BufPtr,
|
| return false;
|
| }
|
|
|
| -bool NaClBitcodeHeader::Read(const unsigned char *&BufPtr,
|
| - const unsigned char *&BufEnd) {
|
| +bool NaClBitcodeHeader::Read(const unsigned char *BufPtr,
|
| + const unsigned char *BufEnd) {
|
| unsigned NumFields;
|
| unsigned NumBytes;
|
| if (ReadPrefix(BufPtr, BufEnd, NumFields, NumBytes))
|
| @@ -244,29 +285,67 @@ NaClBitcodeHeaderField *GetPNaClVersionPtr(NaClBitcodeHeader *Header) {
|
| }
|
|
|
| void NaClBitcodeHeader::InstallFields() {
|
| - // Assume supported until contradicted.
|
| - bool UpdatedUnsupportedMessage = false;
|
| IsSupportedFlag = true;
|
| IsReadableFlag = true;
|
| - UnsupportedMessage = "Supported";
|
| + AlignBitcodeRecords = false;
|
| PNaClVersion = 0;
|
| - if (NaClBitcodeHeaderField *Version = GetPNaClVersionPtr(this)) {
|
| - PNaClVersion = Version->GetUInt32Value();
|
| - }
|
| - if (PNaClVersion != 2) {
|
| - IsSupportedFlag = false;
|
| - IsReadableFlag = false;
|
| - UpdatedUnsupportedMessage = true;
|
| - UnsupportedMessage.clear();
|
| - raw_string_ostream UnsupportedStream(UnsupportedMessage);
|
| - UnsupportedStream << "Unsupported PNaCl bitcode version: "
|
| - << PNaClVersion << "\n";
|
| - UnsupportedStream.flush();
|
| - }
|
| - if (Fields.size() != 1) {
|
| + UnsupportedMessage.clear();
|
| + SmallSet<unsigned, NaClBitcodeHeaderField::kTag_MAX> FieldIDs;
|
| +
|
| + auto ReportProblem = [&](bool IsReadable=false) {
|
| + UnsupportedMessage.append("\n");
|
| IsSupportedFlag = false;
|
| - IsReadableFlag = false;
|
| - if (!UpdatedUnsupportedMessage)
|
| - UnsupportedMessage = "Unknown header field(s) found";
|
| + IsReadableFlag = IsReadableFlag && IsReadable;
|
| + };
|
| +
|
| + auto ReportProblemWithContents = [&](NaClBitcodeHeaderField *Field,
|
| + bool IsReadable=false) {
|
| + UnsupportedMessage.append(": ");
|
| + UnsupportedMessage.append(Field->Contents());
|
| + ReportProblem(IsReadable);
|
| + };
|
| +
|
| + for (size_t i = 0, e = NumberFields(); i < e; ++i) {
|
| + // Start by checking expected properties for any field
|
| + NaClBitcodeHeaderField *Field = GetField(i);
|
| + if (!FieldIDs.insert(Field->GetID()).second) {
|
| + UnsupportedMessage.append("Specified multiple times: ");
|
| + UnsupportedMessage.append(Field->IDName());
|
| + ReportProblem();
|
| + continue;
|
| + }
|
| + NaClBitcodeHeaderField::FieldType ExpectedTy = ExpectedType[Field->GetID()];
|
| + if (Field->GetType() != ExpectedTy) {
|
| + UnsupportedMessage.append("Expects type ");
|
| + UnsupportedMessage.append(NaClBitcodeHeaderField::TypeName(ExpectedTy));
|
| + ReportProblemWithContents(Field);
|
| + continue;
|
| + }
|
| + if (Field->GetType() == NaClBitcodeHeaderField::kUnknownType) {
|
| + UnsupportedMessage.append("Unknown value");
|
| + ReportProblemWithContents(Field);
|
| + continue;
|
| + }
|
| +
|
| + // Check specific ID values and install.
|
| + switch (Field->GetID()) {
|
| + case NaClBitcodeHeaderField::kInvalid:
|
| + UnsupportedMessage.append("Unsupported");
|
| + ReportProblemWithContents(Field);
|
| + continue;
|
| + case NaClBitcodeHeaderField::kPNaClVersion:
|
| + PNaClVersion = Field->GetUInt32Value();
|
| + if (PNaClVersion != 2) {
|
| + UnsupportedMessage.append("Unsupported");
|
| + ReportProblemWithContents(Field);
|
| + continue;
|
| + }
|
| + break;
|
| + case NaClBitcodeHeaderField::kAlignBitcodeRecords:
|
| + AlignBitcodeRecords = true;
|
| + UnsupportedMessage.append("Unsupported");
|
| + ReportProblemWithContents(Field, true);
|
| + continue;
|
| + }
|
| }
|
| }
|
|
|