• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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