Home | History | Annotate | Download | only in NaCl
      1 //===-- llvm/Bitcode/NaCl/NaClBitcodeHeader.h - ----------------*- C++ -*-===//
      2 //      NaCl Bitcode header reader.
      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 // This header defines interfaces to read and write NaCl bitcode wire format
     12 // file headers.
     13 //
     14 //===----------------------------------------------------------------------===//
     15 
     16 #ifndef LLVM_BITCODE_NACL_NACLBITCODEHEADER_H
     17 #define LLVM_BITCODE_NACL_NACLBITCODEHEADER_H
     18 
     19 #include "llvm/ADT/StringRef.h"
     20 #include "llvm/Support/Compiler.h"
     21 #include "llvm/Support/DataTypes.h"
     22 #include <string>
     23 #include <vector>
     24 
     25 namespace llvm {
     26 class MemoryObject;
     27 
     28 // Class representing a variable-size metadata field in the bitcode header.
     29 // Also contains the list of known (typed) Tag IDs.
     30 //
     31 // The serialized format has 2 fixed subfields (ID:type and data length) and the
     32 // variable-length data subfield
     33 class NaClBitcodeHeaderField {
     34   NaClBitcodeHeaderField(const NaClBitcodeHeaderField &) = delete;
     35   void operator=(const NaClBitcodeHeaderField &) = delete;
     36 
     37 public:
     38   // Defines the ID associated with the value. Valid values are in
     39   // {0x0, ..., 0xFFF}
     40   typedef enum {
     41     kInvalid = 0,             // KUnknownType.
     42     kPNaClVersion = 1,        // kUint32Type.
     43     kAlignBitcodeRecords = 2, // kFlagType.
     44     kTag_MAX = kAlignBitcodeRecords
     45   } Tag;
     46   // Defines the type of value.
     47   typedef enum {
     48     kBufferType, // Buffer of form uint8_t[len].
     49     kUInt32Type,
     50     kFlagType,
     51     kUnknownType,
     52     kFieldType_MAX = kUnknownType
     53   } FieldType;
     54   // Defines the number of bytes in a (32-bit) word.
     55   static const int WordSize = 4;
     56 
     57   // Defines the encoding of the fixed fields {i.e. ID:type and data length).
     58   typedef uint16_t FixedSubfield;
     59 
     60   // Create an invalid header field.
     61   NaClBitcodeHeaderField();
     62 
     63   // Creates a header field where MyID is a flag.
     64   NaClBitcodeHeaderField(Tag MyID);
     65 
     66   // Create a header field with an uint32_t value.
     67   NaClBitcodeHeaderField(Tag MyID, uint32_t value);
     68 
     69   // Create a header field for the given data.
     70   NaClBitcodeHeaderField(Tag MyID, size_t MyLen, uint8_t *MyData);
     71 
     72   virtual ~NaClBitcodeHeaderField() {
     73     if (Data)
     74       delete[] Data;
     75   }
     76 
     77   /// \brief Number of bytes used to represent header field.
     78   size_t GetTotalSize() const {
     79     // Round up to 4 byte alignment
     80     return (kTagLenSize + Len + (WordSize - 1)) & ~(WordSize - 1);
     81   }
     82 
     83   /// \brief Write field into Buf[BufLen].
     84   bool Write(uint8_t *Buf, size_t BufLen) const;
     85 
     86   /// \brief Read field from Buf[BufLen].
     87   bool Read(const uint8_t *Buf, size_t BufLen);
     88 
     89   /// \brief Returns string describing ID of field.
     90   static const char *IDName(Tag ID);
     91   const char *IDName() const {
     92     return IDName(ID);
     93   }
     94 
     95   /// \brief Returns string describing type of field.
     96   static const char *TypeName(FieldType FType);
     97   const char *TypeName() const {
     98     return TypeName(FType);
     99   }
    100 
    101   /// \brief Returns string describing field.
    102   std::string Contents() const;
    103 
    104   /// \brief Get the data size from a serialized field to allow allocation.
    105   static size_t GetDataSizeFromSerialized(const uint8_t *Buf) {
    106     FixedSubfield Length;
    107     ReadFixedSubfield(&Length, Buf + sizeof(FixedSubfield));
    108     return Length;
    109   }
    110 
    111   /// \brief Return the ID of the field.
    112   Tag GetID() const { return ID; }
    113 
    114   FieldType GetType() const { return FType; }
    115 
    116   /// \brief Return the length of the data (in bytes).
    117   size_t GetLen() const { return Len; }
    118 
    119   /// \brief Return the data. Data is array getData()[getLen()].
    120   const uint8_t *GetData() const { return Data; }
    121 
    122   /// \brief Returns the uint32_t value stored. Requires that
    123   /// getType() == kUint32Type
    124   uint32_t GetUInt32Value() const;
    125 
    126 private:
    127   // Convert ID:Type into a fixed subfield
    128   FixedSubfield EncodeTypedID() const { return (ID << 4) | FType; }
    129   // Extract out ID and Type from a fixed subfield.
    130   void DecodeTypedID(FixedSubfield Subfield, Tag &ID, FieldType &FType) {
    131     FixedSubfield PossibleID = Subfield >> 4;
    132     ID = (PossibleID > kTag_MAX ? kInvalid : static_cast<Tag>(PossibleID));
    133     FixedSubfield PossibleFType = Subfield & 0xF;
    134     FType = (PossibleFType > kFieldType_MAX
    135              ? kUnknownType : static_cast<FieldType>(PossibleFType));
    136   }
    137   // Combined size of the fixed subfields
    138   const static size_t kTagLenSize = 2 * sizeof(FixedSubfield);
    139   static void WriteFixedSubfield(FixedSubfield Value, uint8_t *Buf) {
    140     Buf[0] = Value & 0xFF;
    141     Buf[1] = (Value >> 8) & 0xFF;
    142   }
    143   static void ReadFixedSubfield(FixedSubfield *Value, const uint8_t *Buf) {
    144     *Value = Buf[0] | Buf[1] << 8;
    145   }
    146   Tag ID;
    147   FieldType FType;
    148   size_t Len;
    149   uint8_t *Data;
    150 };
    151 
    152 /// \brief Class holding parsed header fields in PNaCl bitcode file.
    153 class NaClBitcodeHeader {
    154   NaClBitcodeHeader(const NaClBitcodeHeader &) = delete;
    155   void operator=(const NaClBitcodeHeader &) = delete;
    156 
    157   // The set of parsed header fields. The header takes ownership of
    158   // all fields in this vector.
    159   std::vector<NaClBitcodeHeaderField *> Fields;
    160   // The number of bytes in the PNaCl header.
    161   size_t HeaderSize;
    162   // String defining why it is unsupported (if unsupported).
    163   std::string UnsupportedMessage;
    164   // Flag defining if header is supported.
    165   bool IsSupportedFlag;
    166   // Flag defining if the corresponding bitcode file is readable.
    167   bool IsReadableFlag;
    168   // Defines the PNaCl version defined by the header file.
    169   uint32_t PNaClVersion;
    170   // Byte align bitcode records when nonzero.
    171   bool AlignBitcodeRecords = false;
    172 
    173 public:
    174   static const int WordSize = NaClBitcodeHeaderField::WordSize;
    175 
    176   NaClBitcodeHeader();
    177   ~NaClBitcodeHeader();
    178 
    179   /// \brief Installs the fields of the header, defining if the header
    180   /// is readable and supported. Sets UnsupportedMessage on failure.
    181   void InstallFields();
    182 
    183   /// \brief Adds a field to the list of fields in a header. Takes ownership
    184   /// of fields added.
    185   void push_back(NaClBitcodeHeaderField *Field) {
    186     Fields.push_back(Field);
    187   }
    188 
    189   /// \brief Read the PNaCl bitcode header, The format of the header is:
    190   ///
    191   ///    1) 'PEXE' - The four character sequence defining the magic number.
    192   ///    2) uint_16 num_fields - The number of NaClBitcodeHeaderField's.
    193   ///    3) uint_16 num_bytes - The number of bytes to hold fields in
    194   ///                           the header.
    195   ///    4) NaClBitcodeHeaderField f1 - The first bitcode header field.
    196   ///    ...
    197   ///    2 + num_fields) NaClBitcodeHeaderField fn - The last bitcode header
    198   /// field.
    199   ///
    200   /// Returns false if able to read (all of) the bitcode header.
    201   bool Read(const unsigned char *BufPtr, const unsigned char *BufEnd);
    202 
    203   // \brief Read the PNaCl bitcode header, recording the fields found
    204   // in the header. Returns false if able to read (all of) the bitcode header.
    205   bool Read(MemoryObject *Bytes);
    206 
    207   // \brief Returns the number of bytes read to consume the header.
    208   size_t getHeaderSize() { return HeaderSize; }
    209 
    210   /// \brief Returns string describing why the header describes
    211   /// an unsupported PNaCl Bitcode file.
    212   const std::string &Unsupported() const { return UnsupportedMessage; }
    213 
    214   /// \brief Returns true if supported. That is, it can be run in the
    215   /// browser.
    216   bool IsSupported() const { return IsSupportedFlag; }
    217 
    218   /// \brief Returns true if the bitcode file should be readable. Note
    219   /// that just because it is readable, it doesn't necessarily mean that
    220   /// it is supported.
    221   bool IsReadable() const { return IsReadableFlag; }
    222 
    223   /// \brief Returns number of fields defined.
    224   size_t NumberFields() const { return Fields.size(); }
    225 
    226   /// \brief Returns a pointer to the field with the given ID
    227   /// (0 if no such field).
    228   NaClBitcodeHeaderField *GetTaggedField(NaClBitcodeHeaderField::Tag ID) const;
    229 
    230   /// \brief Returns a pointer to the Nth field in the header
    231   /// (0 if no such field).
    232   NaClBitcodeHeaderField *GetField(size_t index) const;
    233 
    234   /// \brief Returns the PNaClVersion, as defined by the header.
    235   uint32_t GetPNaClVersion() const { return PNaClVersion; }
    236 
    237   /// \brief Returns if one should byte align bitcode records.
    238   bool getAlignBitcodeRecords() const { return AlignBitcodeRecords; }
    239 
    240 private:
    241   // Reads and verifies the first 8 bytes of the header, consisting
    242   // of the magic number 'PEXE', and the value defining the number
    243   // of fields and number of bytes used to hold fields.
    244   // Returns false if successful, sets UnsupportedMessage otherwise.
    245   bool ReadPrefix(const unsigned char *BufPtr, const unsigned char *BufEnd,
    246                   unsigned &NumFields, unsigned &NumBytes);
    247 
    248   // Reads and verifies the fields in the header.
    249   // Returns false if successful, sets UnsupportedMessage otherwise.
    250   bool ReadFields(const unsigned char *BufPtr, const unsigned char *BufEnd,
    251                   unsigned NumFields, unsigned NumBytes);
    252 
    253   // Sets the Unsupported error message and returns true.
    254   bool UnsupportedError(StringRef Message) {
    255     UnsupportedMessage = Message.str();
    256     return true;
    257   }
    258 
    259 };
    260 
    261 } // namespace llvm
    262 
    263 #endif
    264