| Index: pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h
|
| diff --git a/pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h b/pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..50ca5aaed86e65b132b5055ccfb4d6cfbdc74bab
|
| --- /dev/null
|
| +++ b/pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h
|
| @@ -0,0 +1,263 @@
|
| +//===-- llvm/Bitcode/NaCl/NaClBitcodeHeader.h - ----------------*- C++ -*-===//
|
| +// NaCl Bitcode header reader.
|
| +//
|
| +// The LLVM Compiler Infrastructure
|
| +//
|
| +// This file is distributed under the University of Illinois Open Source
|
| +// License. See LICENSE.TXT for details.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +//
|
| +// This header defines interfaces to read and write NaCl bitcode wire format
|
| +// file headers.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +
|
| +#ifndef LLVM_BITCODE_NACL_NACLBITCODEHEADER_H
|
| +#define LLVM_BITCODE_NACL_NACLBITCODEHEADER_H
|
| +
|
| +#include "llvm/ADT/StringRef.h"
|
| +#include "llvm/Support/Compiler.h"
|
| +#include "llvm/Support/DataTypes.h"
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +namespace llvm {
|
| +class MemoryObject;
|
| +
|
| +// Class representing a variable-size metadata field in the bitcode header.
|
| +// Also contains the list of known (typed) Tag IDs.
|
| +//
|
| +// The serialized format has 2 fixed subfields (ID:type and data length) and the
|
| +// variable-length data subfield
|
| +class NaClBitcodeHeaderField {
|
| + NaClBitcodeHeaderField(const NaClBitcodeHeaderField &) = delete;
|
| + void operator=(const NaClBitcodeHeaderField &) = delete;
|
| +
|
| +public:
|
| + // Defines the ID associated with the value. Valid values are in
|
| + // {0x0, ..., 0xFFF}
|
| + typedef enum {
|
| + kInvalid = 0, // KUnknownType.
|
| + kPNaClVersion = 1, // kUint32Type.
|
| + kAlignBitcodeRecords = 2, // kFlagType.
|
| + kTag_MAX = kAlignBitcodeRecords
|
| + } Tag;
|
| + // Defines the type of value.
|
| + typedef enum {
|
| + kBufferType, // Buffer of form uint8_t[len].
|
| + kUInt32Type,
|
| + kFlagType,
|
| + kUnknownType,
|
| + kFieldType_MAX = kUnknownType
|
| + } FieldType;
|
| + // Defines the number of bytes in a (32-bit) word.
|
| + static const int WordSize = 4;
|
| +
|
| + // Defines the encoding of the fixed fields {i.e. ID:type and data length).
|
| + typedef uint16_t FixedSubfield;
|
| +
|
| + // Create an invalid header field.
|
| + NaClBitcodeHeaderField();
|
| +
|
| + // Creates a header field where MyID is a flag.
|
| + NaClBitcodeHeaderField(Tag MyID);
|
| +
|
| + // Create a header field with an uint32_t value.
|
| + NaClBitcodeHeaderField(Tag MyID, uint32_t value);
|
| +
|
| + // Create a header field for the given data.
|
| + NaClBitcodeHeaderField(Tag MyID, size_t MyLen, uint8_t *MyData);
|
| +
|
| + virtual ~NaClBitcodeHeaderField() {
|
| + if (Data)
|
| + delete[] Data;
|
| + }
|
| +
|
| + /// \brief Number of bytes used to represent header field.
|
| + size_t GetTotalSize() const {
|
| + // Round up to 4 byte alignment
|
| + return (kTagLenSize + Len + (WordSize - 1)) & ~(WordSize - 1);
|
| + }
|
| +
|
| + /// \brief Write field into Buf[BufLen].
|
| + bool Write(uint8_t *Buf, size_t BufLen) const;
|
| +
|
| + /// \brief Read field from Buf[BufLen].
|
| + bool Read(const uint8_t *Buf, size_t BufLen);
|
| +
|
| + /// \brief Returns string describing ID of field.
|
| + static const char *IDName(Tag ID);
|
| + const char *IDName() const {
|
| + return IDName(ID);
|
| + }
|
| +
|
| + /// \brief Returns string describing type of field.
|
| + static const char *TypeName(FieldType FType);
|
| + const char *TypeName() const {
|
| + return TypeName(FType);
|
| + }
|
| +
|
| + /// \brief Returns string describing field.
|
| + std::string Contents() const;
|
| +
|
| + /// \brief Get the data size from a serialized field to allow allocation.
|
| + static size_t GetDataSizeFromSerialized(const uint8_t *Buf) {
|
| + FixedSubfield Length;
|
| + ReadFixedSubfield(&Length, Buf + sizeof(FixedSubfield));
|
| + return Length;
|
| + }
|
| +
|
| + /// \brief Return the ID of the field.
|
| + Tag GetID() const { return ID; }
|
| +
|
| + FieldType GetType() const { return FType; }
|
| +
|
| + /// \brief Return the length of the data (in bytes).
|
| + size_t GetLen() const { return Len; }
|
| +
|
| + /// \brief Return the data. Data is array getData()[getLen()].
|
| + const uint8_t *GetData() const { return Data; }
|
| +
|
| + /// \brief Returns the uint32_t value stored. Requires that
|
| + /// getType() == kUint32Type
|
| + uint32_t GetUInt32Value() const;
|
| +
|
| +private:
|
| + // Convert ID:Type into a fixed subfield
|
| + FixedSubfield EncodeTypedID() const { return (ID << 4) | FType; }
|
| + // Extract out ID and Type from a fixed subfield.
|
| + void DecodeTypedID(FixedSubfield Subfield, Tag &ID, FieldType &FType) {
|
| + FixedSubfield PossibleID = Subfield >> 4;
|
| + ID = (PossibleID > kTag_MAX ? kInvalid : static_cast<Tag>(PossibleID));
|
| + FixedSubfield PossibleFType = Subfield & 0xF;
|
| + FType = (PossibleFType > kFieldType_MAX
|
| + ? kUnknownType : static_cast<FieldType>(PossibleFType));
|
| + }
|
| + // Combined size of the fixed subfields
|
| + const static size_t kTagLenSize = 2 * sizeof(FixedSubfield);
|
| + static void WriteFixedSubfield(FixedSubfield Value, uint8_t *Buf) {
|
| + Buf[0] = Value & 0xFF;
|
| + Buf[1] = (Value >> 8) & 0xFF;
|
| + }
|
| + static void ReadFixedSubfield(FixedSubfield *Value, const uint8_t *Buf) {
|
| + *Value = Buf[0] | Buf[1] << 8;
|
| + }
|
| + Tag ID;
|
| + FieldType FType;
|
| + size_t Len;
|
| + uint8_t *Data;
|
| +};
|
| +
|
| +/// \brief Class holding parsed header fields in PNaCl bitcode file.
|
| +class NaClBitcodeHeader {
|
| + NaClBitcodeHeader(const NaClBitcodeHeader &) = delete;
|
| + void operator=(const NaClBitcodeHeader &) = delete;
|
| +
|
| + // The set of parsed header fields. The header takes ownership of
|
| + // all fields in this vector.
|
| + std::vector<NaClBitcodeHeaderField *> Fields;
|
| + // The number of bytes in the PNaCl header.
|
| + size_t HeaderSize;
|
| + // String defining why it is unsupported (if unsupported).
|
| + std::string UnsupportedMessage;
|
| + // Flag defining if header is supported.
|
| + bool IsSupportedFlag;
|
| + // Flag defining if the corresponding bitcode file is readable.
|
| + bool IsReadableFlag;
|
| + // Defines the PNaCl version defined by the header file.
|
| + uint32_t PNaClVersion;
|
| + // Byte align bitcode records when nonzero.
|
| + bool AlignBitcodeRecords = false;
|
| +
|
| +public:
|
| + static const int WordSize = NaClBitcodeHeaderField::WordSize;
|
| +
|
| + NaClBitcodeHeader();
|
| + ~NaClBitcodeHeader();
|
| +
|
| + /// \brief Installs the fields of the header, defining if the header
|
| + /// is readable and supported. Sets UnsupportedMessage on failure.
|
| + void InstallFields();
|
| +
|
| + /// \brief Adds a field to the list of fields in a header. Takes ownership
|
| + /// of fields added.
|
| + void push_back(NaClBitcodeHeaderField *Field) {
|
| + Fields.push_back(Field);
|
| + }
|
| +
|
| + /// \brief Read the PNaCl bitcode header, The format of the header is:
|
| + ///
|
| + /// 1) 'PEXE' - The four character sequence defining the magic number.
|
| + /// 2) uint_16 num_fields - The number of NaClBitcodeHeaderField's.
|
| + /// 3) uint_16 num_bytes - The number of bytes to hold fields in
|
| + /// the header.
|
| + /// 4) NaClBitcodeHeaderField f1 - The first bitcode header field.
|
| + /// ...
|
| + /// 2 + num_fields) NaClBitcodeHeaderField fn - The last bitcode header
|
| + /// field.
|
| + ///
|
| + /// Returns false if able to read (all of) the bitcode header.
|
| + bool Read(const unsigned char *BufPtr, const unsigned char *BufEnd);
|
| +
|
| + // \brief Read the PNaCl bitcode header, recording the fields found
|
| + // in the header. Returns false if able to read (all of) the bitcode header.
|
| + bool Read(MemoryObject *Bytes);
|
| +
|
| + // \brief Returns the number of bytes read to consume the header.
|
| + size_t getHeaderSize() { return HeaderSize; }
|
| +
|
| + /// \brief Returns string describing why the header describes
|
| + /// an unsupported PNaCl Bitcode file.
|
| + const std::string &Unsupported() const { return UnsupportedMessage; }
|
| +
|
| + /// \brief Returns true if supported. That is, it can be run in the
|
| + /// browser.
|
| + bool IsSupported() const { return IsSupportedFlag; }
|
| +
|
| + /// \brief Returns true if the bitcode file should be readable. Note
|
| + /// that just because it is readable, it doesn't necessarily mean that
|
| + /// it is supported.
|
| + bool IsReadable() const { return IsReadableFlag; }
|
| +
|
| + /// \brief Returns number of fields defined.
|
| + size_t NumberFields() const { return Fields.size(); }
|
| +
|
| + /// \brief Returns a pointer to the field with the given ID
|
| + /// (0 if no such field).
|
| + NaClBitcodeHeaderField *GetTaggedField(NaClBitcodeHeaderField::Tag ID) const;
|
| +
|
| + /// \brief Returns a pointer to the Nth field in the header
|
| + /// (0 if no such field).
|
| + NaClBitcodeHeaderField *GetField(size_t index) const;
|
| +
|
| + /// \brief Returns the PNaClVersion, as defined by the header.
|
| + uint32_t GetPNaClVersion() const { return PNaClVersion; }
|
| +
|
| + /// \brief Returns if one should byte align bitcode records.
|
| + bool getAlignBitcodeRecords() const { return AlignBitcodeRecords; }
|
| +
|
| +private:
|
| + // Reads and verifies the first 8 bytes of the header, consisting
|
| + // of the magic number 'PEXE', and the value defining the number
|
| + // of fields and number of bytes used to hold fields.
|
| + // Returns false if successful, sets UnsupportedMessage otherwise.
|
| + bool ReadPrefix(const unsigned char *BufPtr, const unsigned char *BufEnd,
|
| + unsigned &NumFields, unsigned &NumBytes);
|
| +
|
| + // Reads and verifies the fields in the header.
|
| + // Returns false if successful, sets UnsupportedMessage otherwise.
|
| + bool ReadFields(const unsigned char *BufPtr, const unsigned char *BufEnd,
|
| + unsigned NumFields, unsigned NumBytes);
|
| +
|
| + // Sets the Unsupported error message and returns true.
|
| + bool UnsupportedError(StringRef Message) {
|
| + UnsupportedMessage = Message.str();
|
| + return true;
|
| + }
|
| +
|
| +};
|
| +
|
| +} // namespace llvm
|
| +
|
| +#endif
|
|
|