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 ~NaClBitcodeHeaderField()72 virtual ~NaClBitcodeHeaderField() { 73 if (Data) 74 delete[] Data; 75 } 76 77 /// \brief Number of bytes used to represent header field. GetTotalSize()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); IDName()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); TypeName()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. GetDataSizeFromSerialized(const uint8_t * Buf)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. GetID()112 Tag GetID() const { return ID; } 113 GetType()114 FieldType GetType() const { return FType; } 115 116 /// \brief Return the length of the data (in bytes). GetLen()117 size_t GetLen() const { return Len; } 118 119 /// \brief Return the data. Data is array getData()[getLen()]. GetData()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 EncodeTypedID()128 FixedSubfield EncodeTypedID() const { return (ID << 4) | FType; } 129 // Extract out ID and Type from a fixed subfield. DecodeTypedID(FixedSubfield Subfield,Tag & ID,FieldType & FType)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); WriteFixedSubfield(FixedSubfield Value,uint8_t * Buf)139 static void WriteFixedSubfield(FixedSubfield Value, uint8_t *Buf) { 140 Buf[0] = Value & 0xFF; 141 Buf[1] = (Value >> 8) & 0xFF; 142 } ReadFixedSubfield(FixedSubfield * Value,const uint8_t * Buf)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. push_back(NaClBitcodeHeaderField * Field)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. getHeaderSize()208 size_t getHeaderSize() { return HeaderSize; } 209 210 /// \brief Returns string describing why the header describes 211 /// an unsupported PNaCl Bitcode file. Unsupported()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. IsSupported()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. IsReadable()221 bool IsReadable() const { return IsReadableFlag; } 222 223 /// \brief Returns number of fields defined. NumberFields()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. GetPNaClVersion()235 uint32_t GetPNaClVersion() const { return PNaClVersion; } 236 237 /// \brief Returns if one should byte align bitcode records. getAlignBitcodeRecords()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. UnsupportedError(StringRef Message)254 bool UnsupportedError(StringRef Message) { 255 UnsupportedMessage = Message.str(); 256 return true; 257 } 258 259 }; 260 261 } // namespace llvm 262 263 #endif 264