OLD | NEW |
(Empty) | |
| 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 &) LLVM_DELETED_FUNCTION; |
| 35 void operator=(const NaClBitcodeHeaderField &)LLVM_DELETED_FUNCTION; |
| 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 // kUint32. |
| 43 } Tag; |
| 44 // Defines the type of value. |
| 45 typedef enum { |
| 46 kBufferType, // Buffer of form uint8_t[len]. |
| 47 kUInt32Type |
| 48 } FieldType; |
| 49 // Defines the number of bytes in a (32-bit) word. |
| 50 static const int WordSize = 4; |
| 51 |
| 52 // Defines the encoding of the fixed fields {i.e. ID:type and data length). |
| 53 typedef uint16_t FixedSubfield; |
| 54 |
| 55 // Create an invalid header field. |
| 56 NaClBitcodeHeaderField(); |
| 57 |
| 58 // Create a header field with an uint32_t value. |
| 59 NaClBitcodeHeaderField(Tag MyID, uint32_t value); |
| 60 |
| 61 // Create a header field for the given data. |
| 62 NaClBitcodeHeaderField(Tag MyID, size_t MyLen, uint8_t *MyData); |
| 63 |
| 64 virtual ~NaClBitcodeHeaderField() { |
| 65 if (Data) |
| 66 delete[] Data; |
| 67 } |
| 68 |
| 69 /// \brief Number of bytes used to represent header field. |
| 70 size_t GetTotalSize() const { |
| 71 // Round up to 4 byte alignment |
| 72 return (kTagLenSize + Len + (WordSize - 1)) & ~(WordSize - 1); |
| 73 } |
| 74 |
| 75 /// \brief Write field into Buf[BufLen]. |
| 76 bool Write(uint8_t *Buf, size_t BufLen) const; |
| 77 |
| 78 /// \brief Read field from Buf[BufLen]. |
| 79 bool Read(const uint8_t *Buf, size_t BufLen); |
| 80 |
| 81 /// \brief Returns string describing field. |
| 82 std::string Contents() const; |
| 83 |
| 84 /// \brief Get the data size from a serialized field to allow allocation. |
| 85 static size_t GetDataSizeFromSerialized(const uint8_t *Buf) { |
| 86 FixedSubfield Length; |
| 87 ReadFixedSubfield(&Length, Buf + sizeof(FixedSubfield)); |
| 88 return Length; |
| 89 } |
| 90 |
| 91 /// \brief Return the ID of the field. |
| 92 Tag GetID() const { return ID; } |
| 93 |
| 94 FieldType GetType() const { return FType; } |
| 95 |
| 96 /// \brief Return the length of the data (in bytes). |
| 97 size_t GetLen() const { return Len; } |
| 98 |
| 99 /// \brief Return the data. Data is array getData()[getLen()]. |
| 100 const uint8_t *GetData() const { return Data; } |
| 101 |
| 102 /// \brief Returns the uint32_t value stored. Requires that |
| 103 /// getType() == kUint32Type |
| 104 uint32_t GetUInt32Value() const; |
| 105 |
| 106 private: |
| 107 // Convert ID:Type into a fixed subfield |
| 108 FixedSubfield EncodeTypedID() const { return (ID << 4) | FType; } |
| 109 // Extract out ID and Type from a fixed subfield. |
| 110 void DecodeTypedID(FixedSubfield Subfield, Tag &ID, FieldType &FType) { |
| 111 ID = static_cast<Tag>(Subfield >> 4); |
| 112 FType = static_cast<FieldType>(Subfield & 0xF); |
| 113 } |
| 114 // Combined size of the fixed subfields |
| 115 const static size_t kTagLenSize = 2 * sizeof(FixedSubfield); |
| 116 static void WriteFixedSubfield(FixedSubfield Value, uint8_t *Buf) { |
| 117 Buf[0] = Value & 0xFF; |
| 118 Buf[1] = (Value >> 8) & 0xFF; |
| 119 } |
| 120 static void ReadFixedSubfield(FixedSubfield *Value, const uint8_t *Buf) { |
| 121 *Value = Buf[0] | Buf[1] << 8; |
| 122 } |
| 123 Tag ID; |
| 124 FieldType FType; |
| 125 size_t Len; |
| 126 uint8_t *Data; |
| 127 }; |
| 128 |
| 129 /// \brief Class holding parsed header fields in PNaCl bitcode file. |
| 130 class NaClBitcodeHeader { |
| 131 NaClBitcodeHeader(const NaClBitcodeHeader &) LLVM_DELETED_FUNCTION; |
| 132 void operator=(const NaClBitcodeHeader &) LLVM_DELETED_FUNCTION; |
| 133 |
| 134 // The set of parsed header fields. The header takes ownership of |
| 135 // all fields in this vector. |
| 136 std::vector<NaClBitcodeHeaderField *> Fields; |
| 137 // The number of bytes in the PNaCl header. |
| 138 size_t HeaderSize; |
| 139 // String defining why it is unsupported (if unsupported). |
| 140 std::string UnsupportedMessage; |
| 141 // Flag defining if header is supported. |
| 142 bool IsSupportedFlag; |
| 143 // Flag defining if the corresponding bitcode file is readable. |
| 144 bool IsReadableFlag; |
| 145 // Defines the PNaCl version defined by the header file. |
| 146 uint32_t PNaClVersion; |
| 147 |
| 148 public: |
| 149 static const int WordSize = NaClBitcodeHeaderField::WordSize; |
| 150 |
| 151 NaClBitcodeHeader(); |
| 152 ~NaClBitcodeHeader(); |
| 153 |
| 154 /// \brief Installs the fields of the header, defining if the header |
| 155 /// is readable and supported. Sets UnsupportedMessage on failure. |
| 156 void InstallFields(); |
| 157 |
| 158 /// \brief Adds a field to the list of fields in a header. Takes ownership |
| 159 /// of fields added. |
| 160 void push_back(NaClBitcodeHeaderField *Field) { |
| 161 Fields.push_back(Field); |
| 162 } |
| 163 |
| 164 /// \brief Read the PNaCl bitcode header, The format of the header is: |
| 165 /// |
| 166 /// 1) 'PEXE' - The four character sequence defining the magic number. |
| 167 /// 2) uint_16 num_fields - The number of NaClBitcodeHeaderField's. |
| 168 /// 3) uint_16 num_bytes - The number of bytes to hold fields in |
| 169 /// the header. |
| 170 /// 4) NaClBitcodeHeaderField f1 - The first bitcode header field. |
| 171 /// ... |
| 172 /// 2 + num_fields) NaClBitcodeHeaderField fn - The last bitcode header |
| 173 /// field. |
| 174 /// |
| 175 /// Returns false if able to read (all of) the bitcode header. |
| 176 bool Read(const unsigned char *&BufPtr, const unsigned char *&BufEnd); |
| 177 |
| 178 // \brief Read the PNaCl bitcode header, recording the fields found |
| 179 // in the header. Returns false if able to read (all of) the bitcode header. |
| 180 bool Read(MemoryObject *Bytes); |
| 181 |
| 182 // \brief Returns the number of bytes read to consume the header. |
| 183 size_t getHeaderSize() { return HeaderSize; } |
| 184 |
| 185 /// \brief Returns string describing why the header describes |
| 186 /// an unsupported PNaCl Bitcode file. |
| 187 const std::string &Unsupported() const { return UnsupportedMessage; } |
| 188 |
| 189 /// \brief Returns true if supported. That is, it can be run in the |
| 190 /// browser. |
| 191 bool IsSupported() const { return IsSupportedFlag; } |
| 192 |
| 193 /// \brief Returns true if the bitcode file should be readable. Note |
| 194 /// that just because it is readable, it doesn't necessarily mean that |
| 195 /// it is supported. |
| 196 bool IsReadable() const { return IsReadableFlag; } |
| 197 |
| 198 /// \brief Returns number of fields defined. |
| 199 size_t NumberFields() const { return Fields.size(); } |
| 200 |
| 201 /// \brief Returns a pointer to the field with the given ID |
| 202 /// (0 if no such field). |
| 203 NaClBitcodeHeaderField *GetTaggedField(NaClBitcodeHeaderField::Tag ID) const; |
| 204 |
| 205 /// \brief Returns a pointer to the Nth field in the header |
| 206 /// (0 if no such field). |
| 207 NaClBitcodeHeaderField *GetField(size_t index) const; |
| 208 |
| 209 /// \brief Returns the PNaClVersion, as defined by the header. |
| 210 uint32_t GetPNaClVersion() const { return PNaClVersion; } |
| 211 |
| 212 private: |
| 213 // Reads and verifies the first 8 bytes of the header, consisting |
| 214 // of the magic number 'PEXE', and the value defining the number |
| 215 // of fields and number of bytes used to hold fields. |
| 216 // Returns false if successful, sets UnsupportedMessage otherwise. |
| 217 bool ReadPrefix(const unsigned char *BufPtr, const unsigned char *BufEnd, |
| 218 unsigned &NumFields, unsigned &NumBytes); |
| 219 |
| 220 // Reads and verifies the fields in the header. |
| 221 // Returns false if successful, sets UnsupportedMessage otherwise. |
| 222 bool ReadFields(const unsigned char *BufPtr, const unsigned char *BufEnd, |
| 223 unsigned NumFields, unsigned NumBytes); |
| 224 |
| 225 // Sets the Unsupported error message and returns true. |
| 226 bool UnsupportedError(StringRef Message) { |
| 227 UnsupportedMessage = Message.str(); |
| 228 return true; |
| 229 } |
| 230 |
| 231 }; |
| 232 |
| 233 } // namespace llvm |
| 234 |
| 235 #endif |
OLD | NEW |