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 { return IDName(ID); } 92 93 /// \brief Returns string describing type of field. 94 static const char *TypeName(FieldType FType); TypeName()95 const char *TypeName() const { return TypeName(FType); } 96 97 /// \brief Returns string describing field. 98 std::string Contents() const; 99 100 /// \brief Get the data size from a serialized field to allow allocation. GetDataSizeFromSerialized(const uint8_t * Buf)101 static size_t GetDataSizeFromSerialized(const uint8_t *Buf) { 102 FixedSubfield Length; 103 ReadFixedSubfield(&Length, Buf + sizeof(FixedSubfield)); 104 return Length; 105 } 106 107 /// \brief Return the ID of the field. GetID()108 Tag GetID() const { return ID; } 109 GetType()110 FieldType GetType() const { return FType; } 111 112 /// \brief Return the length of the data (in bytes). GetLen()113 size_t GetLen() const { return Len; } 114 115 /// \brief Return the data. Data is array getData()[getLen()]. GetData()116 const uint8_t *GetData() const { return Data; } 117 118 /// \brief Returns the uint32_t value stored. Requires that 119 /// getType() == kUint32Type 120 uint32_t GetUInt32Value() const; 121 122 private: 123 // Convert ID:Type into a fixed subfield EncodeTypedID()124 FixedSubfield EncodeTypedID() const { return (ID << 4) | FType; } 125 // Extract out ID and Type from a fixed subfield. DecodeTypedID(FixedSubfield Subfield,Tag & ID,FieldType & FType)126 void DecodeTypedID(FixedSubfield Subfield, Tag &ID, FieldType &FType) { 127 FixedSubfield PossibleID = Subfield >> 4; 128 ID = (PossibleID > kTag_MAX ? kInvalid : static_cast<Tag>(PossibleID)); 129 FixedSubfield PossibleFType = Subfield & 0xF; 130 FType = (PossibleFType > kFieldType_MAX 131 ? kUnknownType 132 : static_cast<FieldType>(PossibleFType)); 133 } 134 // Combined size of the fixed subfields 135 const static size_t kTagLenSize = 2 * sizeof(FixedSubfield); WriteFixedSubfield(FixedSubfield Value,uint8_t * Buf)136 static void WriteFixedSubfield(FixedSubfield Value, uint8_t *Buf) { 137 Buf[0] = Value & 0xFF; 138 Buf[1] = (Value >> 8) & 0xFF; 139 } ReadFixedSubfield(FixedSubfield * Value,const uint8_t * Buf)140 static void ReadFixedSubfield(FixedSubfield *Value, const uint8_t *Buf) { 141 *Value = Buf[0] | Buf[1] << 8; 142 } 143 Tag ID; 144 FieldType FType; 145 size_t Len; 146 uint8_t *Data; 147 }; 148 149 /// \brief Class holding parsed header fields in PNaCl bitcode file. 150 class NaClBitcodeHeader { 151 NaClBitcodeHeader(const NaClBitcodeHeader &) = delete; 152 void operator=(const NaClBitcodeHeader &) = delete; 153 154 // The set of parsed header fields. The header takes ownership of 155 // all fields in this vector. 156 std::vector<NaClBitcodeHeaderField *> Fields; 157 // The number of bytes in the PNaCl header. 158 size_t HeaderSize; 159 // String defining why it is unsupported (if unsupported). 160 std::string UnsupportedMessage; 161 // Flag defining if header is supported. 162 bool IsSupportedFlag; 163 // Flag defining if the corresponding bitcode file is readable. 164 bool IsReadableFlag; 165 // Defines the PNaCl version defined by the header file. 166 uint32_t PNaClVersion; 167 // Byte align bitcode records when nonzero. 168 bool AlignBitcodeRecords = false; 169 170 public: 171 static const int WordSize = NaClBitcodeHeaderField::WordSize; 172 173 NaClBitcodeHeader(); 174 ~NaClBitcodeHeader(); 175 176 /// \brief Installs the fields of the header, defining if the header 177 /// is readable and supported. Sets UnsupportedMessage on failure. 178 void InstallFields(); 179 180 /// \brief Adds a field to the list of fields in a header. Takes ownership 181 /// of fields added. push_back(NaClBitcodeHeaderField * Field)182 void push_back(NaClBitcodeHeaderField *Field) { Fields.push_back(Field); } 183 184 /// \brief Read the PNaCl bitcode header, The format of the header is: 185 /// 186 /// 1) 'PEXE' - The four character sequence defining the magic number. 187 /// 2) uint_16 num_fields - The number of NaClBitcodeHeaderField's. 188 /// 3) uint_16 num_bytes - The number of bytes to hold fields in 189 /// the header. 190 /// 4) NaClBitcodeHeaderField f1 - The first bitcode header field. 191 /// ... 192 /// 2 + num_fields) NaClBitcodeHeaderField fn - The last bitcode header 193 /// field. 194 /// 195 /// Returns false if able to read (all of) the bitcode header. 196 bool Read(const unsigned char *BufPtr, const unsigned char *BufEnd); 197 198 // \brief Read the PNaCl bitcode header, recording the fields found 199 // in the header. Returns false if able to read (all of) the bitcode header. 200 bool Read(MemoryObject *Bytes); 201 202 // \brief Returns the number of bytes read to consume the header. getHeaderSize()203 size_t getHeaderSize() { return HeaderSize; } 204 205 /// \brief Returns string describing why the header describes 206 /// an unsupported PNaCl Bitcode file. Unsupported()207 const std::string &Unsupported() const { return UnsupportedMessage; } 208 209 /// \brief Returns true if supported. That is, it can be run in the 210 /// browser. IsSupported()211 bool IsSupported() const { return IsSupportedFlag; } 212 213 /// \brief Returns true if the bitcode file should be readable. Note 214 /// that just because it is readable, it doesn't necessarily mean that 215 /// it is supported. IsReadable()216 bool IsReadable() const { return IsReadableFlag; } 217 218 /// \brief Returns number of fields defined. NumberFields()219 size_t NumberFields() const { return Fields.size(); } 220 221 /// \brief Returns a pointer to the field with the given ID 222 /// (0 if no such field). 223 NaClBitcodeHeaderField *GetTaggedField(NaClBitcodeHeaderField::Tag ID) const; 224 225 /// \brief Returns a pointer to the Nth field in the header 226 /// (0 if no such field). 227 NaClBitcodeHeaderField *GetField(size_t index) const; 228 229 /// \brief Returns the PNaClVersion, as defined by the header. GetPNaClVersion()230 uint32_t GetPNaClVersion() const { return PNaClVersion; } 231 232 /// \brief Returns if one should byte align bitcode records. getAlignBitcodeRecords()233 bool getAlignBitcodeRecords() const { return AlignBitcodeRecords; } 234 235 private: 236 // Reads and verifies the first 8 bytes of the header, consisting 237 // of the magic number 'PEXE', and the value defining the number 238 // of fields and number of bytes used to hold fields. 239 // Returns false if successful, sets UnsupportedMessage otherwise. 240 bool ReadPrefix(const unsigned char *BufPtr, const unsigned char *BufEnd, 241 unsigned &NumFields, unsigned &NumBytes); 242 243 // Reads and verifies the fields in the header. 244 // Returns false if successful, sets UnsupportedMessage otherwise. 245 bool ReadFields(const unsigned char *BufPtr, const unsigned char *BufEnd, 246 unsigned NumFields, unsigned NumBytes); 247 248 // Sets the Unsupported error message and returns true. UnsupportedError(StringRef Message)249 bool UnsupportedError(StringRef Message) { 250 UnsupportedMessage = Message.str(); 251 return true; 252 } 253 }; 254 255 } // namespace llvm 256 257 #endif 258