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 &) = 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 |
OLD | NEW |