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

Unified Diff: pnacl-llvm/NaClBitcodeHeader.cpp

Issue 1960393002: Subzero: Add necessary PNaCl files for standalone build. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero@master
Patch Set: make format Created 4 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pnacl-llvm/NaClBitcodeDecoders.cpp ('k') | pnacl-llvm/NaClBitcodeParser.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pnacl-llvm/NaClBitcodeHeader.cpp
diff --git a/pnacl-llvm/NaClBitcodeHeader.cpp b/pnacl-llvm/NaClBitcodeHeader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8a65f50829b601a0d09426267ac1b8f70f0989b9
--- /dev/null
+++ b/pnacl-llvm/NaClBitcodeHeader.cpp
@@ -0,0 +1,351 @@
+//===- NaClBitcodeHeader.cpp ----------------------------------------------===//
+// PNaCl bitcode header reader.
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/StreamingMemoryObject.h"
+
+#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) {}
+
+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);
+ Data[3] = static_cast<uint8_t>((MyValue >> 24) & 0xFF);
+}
+
+uint32_t NaClBitcodeHeaderField::GetUInt32Value() const {
+ assert(FType == kUInt32Type && "Header field must be uint32");
+ return static_cast<uint32_t>(Data[0]) |
+ (static_cast<uint32_t>(Data[1]) << 8) |
+ (static_cast<uint32_t>(Data[2]) << 16) |
+ (static_cast<uint32_t>(Data[2]) << 24);
+}
+
+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];
+ }
+}
+
+bool NaClBitcodeHeaderField::Write(uint8_t *Buf, size_t BufLen) const {
+ size_t FieldsLen = kTagLenSize + Len;
+ size_t PadLen = (WordSize - (FieldsLen & (WordSize-1))) & (WordSize-1);
+ // Ensure buffer is large enough and that length can be represented
+ // in 32 bits
+ if (BufLen < FieldsLen + PadLen ||
+ Len > std::numeric_limits<FixedSubfield>::max())
+ return false;
+
+ WriteFixedSubfield(EncodeTypedID(), Buf);
+ WriteFixedSubfield(static_cast<FixedSubfield>(Len),
+ Buf + sizeof(FixedSubfield));
+ memcpy(Buf + kTagLenSize, Data, Len);
+ // Pad out to word alignment
+ if (PadLen) {
+ memset(Buf + FieldsLen, 0, PadLen);
+ }
+ return true;
+}
+
+bool NaClBitcodeHeaderField::Read(const uint8_t *Buf, size_t BufLen) {
+ if (BufLen < kTagLenSize)
+ return false;
+ FixedSubfield IdField;
+ ReadFixedSubfield(&IdField, Buf);
+ FixedSubfield LengthField;
+ ReadFixedSubfield(&LengthField, Buf + sizeof(FixedSubfield));
+ size_t Length = static_cast<size_t>(LengthField);
+ if (BufLen < kTagLenSize + Length)
+ return false;
+ if (Len != Length) {
+ // Need to reallocate data buffer.
+ if (Data)
+ delete[] Data;
+ Data = new uint8_t[Length];
+ }
+ Len = Length;
+ DecodeTypedID(IdField, ID, FType);
+ memcpy(Data, Buf + kTagLenSize, Len);
+ return true;
+}
+
+std::string NaClBitcodeHeaderField::Contents() const {
+ std::string buffer;
+ raw_string_ostream ss(buffer);
+ ss << IDName() << ": ";
+ switch (FType) {
+ case kFlagType:
+ ss << "true";
+ break;
+ case kUInt32Type:
+ ss << GetUInt32Value();
+ break;
+ case kBufferType:
+ ss << "[";
+ for (size_t i = 0; i < Len; ++i) {
+ if (i)
+ ss << " ";
+ ss << format("%02x", Data[i]);
+ }
+ ss << "]";
+ break;
+ case kUnknownType:
+ ss << "unknown value";
+ break;
+ }
+ return ss.str();
+}
+
+NaClBitcodeHeader::NaClBitcodeHeader()
+ : HeaderSize(0), UnsupportedMessage(), IsSupportedFlag(false),
+ IsReadableFlag(false), PNaClVersion(0) {}
+
+NaClBitcodeHeader::~NaClBitcodeHeader() {
+ for (std::vector<NaClBitcodeHeaderField *>::const_iterator
+ Iter = Fields.begin(),
+ IterEnd = Fields.end();
+ Iter != IterEnd; ++Iter) {
+ delete *Iter;
+ }
+}
+
+bool NaClBitcodeHeader::ReadPrefix(const unsigned char *BufPtr,
+ const unsigned char *BufEnd,
+ unsigned &NumFields, unsigned &NumBytes) {
+ // Must contain PEXE.
+ if (!isNaClBitcode(BufPtr, BufEnd)) {
+ UnsupportedMessage = "Invalid PNaCl bitcode header";
+ if (isBitcode(BufPtr, BufEnd)) {
+ UnsupportedMessage += " (to run in Chrome, bitcode files must be "
+ "finalized using pnacl-finalize)";
+ }
+ return true;
+ }
+ BufPtr += WordSize;
+
+ // Read #Fields and number of bytes needed for the header.
+ if (BufPtr + WordSize > BufEnd)
+ return UnsupportedError("Bitcode read failure");
+ NumFields = static_cast<unsigned>(BufPtr[0]) |
+ (static_cast<unsigned>(BufPtr[1]) << 8);
+ NumBytes = static_cast<unsigned>(BufPtr[2]) |
+ (static_cast<unsigned>(BufPtr[3]) << 8);
+ BufPtr += WordSize;
+ return false;
+}
+
+bool NaClBitcodeHeader::ReadFields(const unsigned char *BufPtr,
+ const unsigned char *BufEnd,
+ unsigned NumFields, unsigned NumBytes) {
+ HeaderSize = NumBytes + (2 * WordSize);
+
+ // Read in each field.
+ for (size_t i = 0; i < NumFields; ++i) {
+ NaClBitcodeHeaderField *Field = new NaClBitcodeHeaderField();
+ Fields.push_back(Field);
+ if (!Field->Read(BufPtr, BufEnd - BufPtr))
+ return UnsupportedError("Bitcode read failure");
+ size_t FieldSize = Field->GetTotalSize();
+ BufPtr += FieldSize;
+ }
+ return false;
+}
+
+bool NaClBitcodeHeader::Read(const unsigned char *BufPtr,
+ const unsigned char *BufEnd) {
+ unsigned NumFields;
+ unsigned NumBytes;
+ if (ReadPrefix(BufPtr, BufEnd, NumFields, NumBytes))
+ return true; // ReadPrefix sets UnsupportedMessage
+ BufPtr += 2 * WordSize;
+
+ if (ReadFields(BufPtr, BufEnd, NumFields, NumBytes))
+ return true; // ReadFields sets UnsupportedMessage
+ BufPtr += NumBytes;
+ InstallFields();
+ return false;
+}
+
+bool NaClBitcodeHeader::Read(MemoryObject *Bytes) {
+ unsigned NumFields;
+ unsigned NumBytes;
+ // First, read the prefix, which is 2 * WordSize, to determine the
+ // NumBytes and NumFields.
+ {
+ unsigned char Buffer[2 * WordSize];
+ if (Bytes->readBytes(Buffer, sizeof(Buffer), 0) != sizeof(Buffer))
+ return UnsupportedError("Bitcode read failure");
+ if (ReadPrefix(Buffer, Buffer + sizeof(Buffer), NumFields, NumBytes))
+ return true; // ReadPrefix sets UnsupportedMessage
+ }
+ // Then read the rest, starting after the 2 * WordSize of the prefix.
+ uint8_t *Header = new uint8_t[NumBytes];
+ bool failed =
+ Bytes->readBytes(Header, NumBytes, 2 * WordSize) != NumBytes ||
+ ReadFields(Header, Header + NumBytes, NumFields, NumBytes);
+ delete[] Header;
+ if (failed)
+ return UnsupportedError("Bitcode read failure");
+ InstallFields();
+ return false;
+}
+
+NaClBitcodeHeaderField *
+NaClBitcodeHeader::GetTaggedField(NaClBitcodeHeaderField::Tag ID) const {
+ for (std::vector<NaClBitcodeHeaderField *>::const_iterator
+ Iter = Fields.begin(),
+ IterEnd = Fields.end();
+ Iter != IterEnd; ++Iter) {
+ if ((*Iter)->GetID() == ID) {
+ return *Iter;
+ }
+ }
+ return 0;
+}
+
+NaClBitcodeHeaderField *NaClBitcodeHeader::GetField(size_t index) const {
+ if (index >= Fields.size())
+ return 0;
+ return Fields[index];
+}
+
+NaClBitcodeHeaderField *GetPNaClVersionPtr(NaClBitcodeHeader *Header) {
+ if (NaClBitcodeHeaderField *Version =
+ Header->GetTaggedField(NaClBitcodeHeaderField::kPNaClVersion)) {
+ if (Version->GetType() == NaClBitcodeHeaderField::kUInt32Type) {
+ return Version;
+ }
+ }
+ return 0;
+}
+
+void NaClBitcodeHeader::InstallFields() {
+ IsSupportedFlag = true;
+ IsReadableFlag = true;
+ AlignBitcodeRecords = false;
+ PNaClVersion = 0;
+ UnsupportedMessage.clear();
+ SmallSet<unsigned, NaClBitcodeHeaderField::kTag_MAX> FieldIDs;
+
+ auto ReportProblem = [&](bool IsReadable) {
+ UnsupportedMessage.append("\n");
+ IsSupportedFlag = false;
+ IsReadableFlag = IsReadableFlag && IsReadable;
+ };
+
+ auto ReportProblemWithContents = [&](NaClBitcodeHeaderField *Field,
+ bool IsReadable) {
+ 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(false);
+ continue;
+ }
+ NaClBitcodeHeaderField::FieldType ExpectedTy = ExpectedType[Field->GetID()];
+ if (Field->GetType() != ExpectedTy) {
+ UnsupportedMessage.append("Expects type ");
+ UnsupportedMessage.append(NaClBitcodeHeaderField::TypeName(ExpectedTy));
+ ReportProblemWithContents(Field, false);
+ continue;
+ }
+ if (Field->GetType() == NaClBitcodeHeaderField::kUnknownType) {
+ UnsupportedMessage.append("Unknown value");
+ ReportProblemWithContents(Field, false);
+ continue;
+ }
+
+ // Check specific ID values and install.
+ switch (Field->GetID()) {
+ case NaClBitcodeHeaderField::kInvalid:
+ UnsupportedMessage.append("Unsupported");
+ ReportProblemWithContents(Field, false);
+ continue;
+ case NaClBitcodeHeaderField::kPNaClVersion:
+ PNaClVersion = Field->GetUInt32Value();
+ if (PNaClVersion != 2) {
+ UnsupportedMessage.append("Unsupported");
+ ReportProblemWithContents(Field, false);
+ continue;
+ }
+ break;
+ case NaClBitcodeHeaderField::kAlignBitcodeRecords:
+ AlignBitcodeRecords = true;
+ UnsupportedMessage.append("Unsupported");
+ ReportProblemWithContents(Field, true);
+ continue;
+ }
+ }
+}
« no previous file with comments | « pnacl-llvm/NaClBitcodeDecoders.cpp ('k') | pnacl-llvm/NaClBitcodeParser.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698