OLD | NEW |
1 //===- NaClBitcodeHeader.cpp ----------------------------------------------===// | 1 //===- NaClBitcodeHeader.cpp ----------------------------------------------===// |
2 // PNaCl bitcode header reader. | 2 // PNaCl bitcode header reader. |
3 // | 3 // |
4 // The LLVM Compiler Infrastructure | 4 // The LLVM Compiler Infrastructure |
5 // | 5 // |
6 // This file is distributed under the University of Illinois Open Source | 6 // This file is distributed under the University of Illinois Open Source |
7 // License. See LICENSE.TXT for details. | 7 // License. See LICENSE.TXT for details. |
8 // | 8 // |
9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
10 | 10 |
11 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" | 11 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" |
| 12 |
| 13 #include "llvm/ADT/SmallSet.h" |
12 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" | 14 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
13 #include "llvm/Bitcode/ReaderWriter.h" | 15 #include "llvm/Bitcode/ReaderWriter.h" |
14 #include "llvm/Support/ErrorHandling.h" | 16 #include "llvm/Support/ErrorHandling.h" |
15 #include "llvm/Support/Format.h" | 17 #include "llvm/Support/Format.h" |
16 #include "llvm/Support/raw_ostream.h" | 18 #include "llvm/Support/raw_ostream.h" |
17 #include "llvm/Support/StreamingMemoryObject.h" | 19 #include "llvm/Support/StreamingMemoryObject.h" |
18 | 20 |
19 #include <limits> | |
20 #include <cstring> | 21 #include <cstring> |
21 #include <iomanip> | 22 #include <iomanip> |
| 23 #include <limits> |
22 | 24 |
23 using namespace llvm; | 25 using namespace llvm; |
24 | 26 |
| 27 namespace { |
| 28 |
| 29 // The name for each ID tag. |
| 30 static const char *TagName[] = { |
| 31 "Invalid", // kInvalid |
| 32 "PNaCl Version", // kPNaClVersion |
| 33 "Align bitcode records" // kAlignBitcodeRecords |
| 34 }; |
| 35 |
| 36 // The name for each field type. |
| 37 static const char *FieldTypeName[] = { |
| 38 "uint8[]", // kBufferType |
| 39 "uint32", // kUInt32Type |
| 40 "flag", // kFlagType |
| 41 "unknown" // kUnknownType |
| 42 }; |
| 43 |
| 44 // The type associated with each ID tag. |
| 45 static const NaClBitcodeHeaderField::FieldType ExpectedType[] = { |
| 46 NaClBitcodeHeaderField::kUnknownType, // kInvalid |
| 47 NaClBitcodeHeaderField::kUInt32Type, // kPNaClVersion |
| 48 NaClBitcodeHeaderField::kFlagType // kAlignBitcodeRecords |
| 49 }; |
| 50 |
| 51 } // end of anonymous namespace |
| 52 |
| 53 const char *NaClBitcodeHeaderField::IDName(Tag ID) { |
| 54 return ID > kTag_MAX ? "???" : TagName[ID]; |
| 55 } |
| 56 |
| 57 const char *NaClBitcodeHeaderField::TypeName(FieldType FType) { |
| 58 return FType > kFieldType_MAX ? "???" : FieldTypeName[FType]; |
| 59 } |
| 60 |
25 NaClBitcodeHeaderField::NaClBitcodeHeaderField() | 61 NaClBitcodeHeaderField::NaClBitcodeHeaderField() |
26 : ID(kInvalid), FType(kBufferType), Len(0), Data(0) {} | 62 : ID(kInvalid), FType(kBufferType), Len(0), Data(0) {} |
| 63 |
| 64 NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID) |
| 65 : ID(MyID), FType(kFlagType), Len(0), Data(0) { |
| 66 assert(MyID <= kTag_MAX); |
| 67 } |
27 | 68 |
28 NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, uint32_t MyValue) | 69 NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, uint32_t MyValue) |
29 : ID(MyID), FType(kUInt32Type), Len(4), Data(new uint8_t[4]) { | 70 : ID(MyID), FType(kUInt32Type), Len(4), Data(new uint8_t[4]) { |
| 71 assert(MyID <= kTag_MAX); |
30 Data[0] = static_cast<uint8_t>(MyValue & 0xFF); | 72 Data[0] = static_cast<uint8_t>(MyValue & 0xFF); |
31 Data[1] = static_cast<uint8_t>((MyValue >> 8) & 0xFF); | 73 Data[1] = static_cast<uint8_t>((MyValue >> 8) & 0xFF); |
32 Data[2] = static_cast<uint8_t>((MyValue >> 16) & 0xFF); | 74 Data[2] = static_cast<uint8_t>((MyValue >> 16) & 0xFF); |
33 Data[3] = static_cast<uint8_t>((MyValue >> 24) & 0xFF); | 75 Data[3] = static_cast<uint8_t>((MyValue >> 24) & 0xFF); |
34 } | 76 } |
35 | 77 |
36 uint32_t NaClBitcodeHeaderField::GetUInt32Value() const { | 78 uint32_t NaClBitcodeHeaderField::GetUInt32Value() const { |
37 assert(FType == kUInt32Type && "Header field must be uint32"); | 79 assert(FType == kUInt32Type && "Header field must be uint32"); |
38 return static_cast<uint32_t>(Data[0]) | | 80 return static_cast<uint32_t>(Data[0]) | |
39 (static_cast<uint32_t>(Data[1]) << 8) | | 81 (static_cast<uint32_t>(Data[1]) << 8) | |
40 (static_cast<uint32_t>(Data[2]) << 16) | | 82 (static_cast<uint32_t>(Data[2]) << 16) | |
41 (static_cast<uint32_t>(Data[2]) << 24); | 83 (static_cast<uint32_t>(Data[2]) << 24); |
42 } | 84 } |
43 | 85 |
44 NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, size_t MyLen, | 86 NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, size_t MyLen, |
45 uint8_t *MyData) | 87 uint8_t *MyData) |
46 : ID(MyID), FType(kBufferType), Len(MyLen), Data(new uint8_t[MyLen]) { | 88 : ID(MyID), FType(kBufferType), Len(MyLen), Data(new uint8_t[MyLen]) { |
| 89 assert(MyID <= kTag_MAX); |
47 for (size_t i = 0; i < MyLen; ++i) { | 90 for (size_t i = 0; i < MyLen; ++i) { |
48 Data[i] = MyData[i]; | 91 Data[i] = MyData[i]; |
49 } | 92 } |
50 } | 93 } |
51 | 94 |
52 bool NaClBitcodeHeaderField::Write(uint8_t *Buf, size_t BufLen) const { | 95 bool NaClBitcodeHeaderField::Write(uint8_t *Buf, size_t BufLen) const { |
53 size_t FieldsLen = kTagLenSize + Len; | 96 size_t FieldsLen = kTagLenSize + Len; |
54 size_t PadLen = (WordSize - (FieldsLen & (WordSize-1))) & (WordSize-1); | 97 size_t PadLen = (WordSize - (FieldsLen & (WordSize-1))) & (WordSize-1); |
55 // Ensure buffer is large enough and that length can be represented | 98 // Ensure buffer is large enough and that length can be represented |
56 // in 32 bits | 99 // in 32 bits |
(...skipping 30 matching lines...) Expand all Loading... |
87 } | 130 } |
88 Len = Length; | 131 Len = Length; |
89 DecodeTypedID(IdField, ID, FType); | 132 DecodeTypedID(IdField, ID, FType); |
90 memcpy(Data, Buf + kTagLenSize, Len); | 133 memcpy(Data, Buf + kTagLenSize, Len); |
91 return true; | 134 return true; |
92 } | 135 } |
93 | 136 |
94 std::string NaClBitcodeHeaderField::Contents() const { | 137 std::string NaClBitcodeHeaderField::Contents() const { |
95 std::string buffer; | 138 std::string buffer; |
96 raw_string_ostream ss(buffer); | 139 raw_string_ostream ss(buffer); |
97 switch (ID) { | 140 ss << IDName() << ": "; |
98 case kPNaClVersion: | 141 switch (FType) { |
99 ss << "PNaCl Version"; | 142 case kFlagType: |
| 143 ss << "true"; |
100 break; | 144 break; |
101 case kInvalid: | |
102 ss << "Invalid"; | |
103 break; | |
104 } | |
105 ss << ": "; | |
106 switch (FType) { | |
107 case kUInt32Type: | 145 case kUInt32Type: |
108 ss << GetUInt32Value(); | 146 ss << GetUInt32Value(); |
109 break; | 147 break; |
110 case kBufferType: | 148 case kBufferType: |
111 ss << "["; | 149 ss << "["; |
112 for (size_t i = 0; i < Len; ++i) { | 150 for (size_t i = 0; i < Len; ++i) { |
113 if (i) | 151 if (i) |
114 ss << " "; | 152 ss << " "; |
115 ss << format("%02x", Data[i]); | 153 ss << format("%02x", Data[i]); |
116 } | 154 } |
117 ss << "]"; | 155 ss << "]"; |
118 break; | 156 break; |
| 157 case kUnknownType: |
| 158 ss << "unknown value"; |
| 159 break; |
119 } | 160 } |
120 return ss.str(); | 161 return ss.str(); |
121 } | 162 } |
122 | 163 |
123 NaClBitcodeHeader::NaClBitcodeHeader() | 164 NaClBitcodeHeader::NaClBitcodeHeader() |
124 : HeaderSize(0), UnsupportedMessage(), IsSupportedFlag(false), | 165 : HeaderSize(0), UnsupportedMessage(), IsSupportedFlag(false), |
125 IsReadableFlag(false), PNaClVersion(0) {} | 166 IsReadableFlag(false), PNaClVersion(0) {} |
126 | 167 |
127 NaClBitcodeHeader::~NaClBitcodeHeader() { | 168 NaClBitcodeHeader::~NaClBitcodeHeader() { |
128 for (std::vector<NaClBitcodeHeaderField *>::const_iterator | 169 for (std::vector<NaClBitcodeHeaderField *>::const_iterator |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 NaClBitcodeHeaderField *Field = new NaClBitcodeHeaderField(); | 209 NaClBitcodeHeaderField *Field = new NaClBitcodeHeaderField(); |
169 Fields.push_back(Field); | 210 Fields.push_back(Field); |
170 if (!Field->Read(BufPtr, BufEnd - BufPtr)) | 211 if (!Field->Read(BufPtr, BufEnd - BufPtr)) |
171 return UnsupportedError("Bitcode read failure"); | 212 return UnsupportedError("Bitcode read failure"); |
172 size_t FieldSize = Field->GetTotalSize(); | 213 size_t FieldSize = Field->GetTotalSize(); |
173 BufPtr += FieldSize; | 214 BufPtr += FieldSize; |
174 } | 215 } |
175 return false; | 216 return false; |
176 } | 217 } |
177 | 218 |
178 bool NaClBitcodeHeader::Read(const unsigned char *&BufPtr, | 219 bool NaClBitcodeHeader::Read(const unsigned char *BufPtr, |
179 const unsigned char *&BufEnd) { | 220 const unsigned char *BufEnd) { |
180 unsigned NumFields; | 221 unsigned NumFields; |
181 unsigned NumBytes; | 222 unsigned NumBytes; |
182 if (ReadPrefix(BufPtr, BufEnd, NumFields, NumBytes)) | 223 if (ReadPrefix(BufPtr, BufEnd, NumFields, NumBytes)) |
183 return true; // ReadPrefix sets UnsupportedMessage | 224 return true; // ReadPrefix sets UnsupportedMessage |
184 BufPtr += 2 * WordSize; | 225 BufPtr += 2 * WordSize; |
185 | 226 |
186 if (ReadFields(BufPtr, BufEnd, NumFields, NumBytes)) | 227 if (ReadFields(BufPtr, BufEnd, NumFields, NumBytes)) |
187 return true; // ReadFields sets UnsupportedMessage | 228 return true; // ReadFields sets UnsupportedMessage |
188 BufPtr += NumBytes; | 229 BufPtr += NumBytes; |
189 InstallFields(); | 230 InstallFields(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 if (NaClBitcodeHeaderField *Version = | 278 if (NaClBitcodeHeaderField *Version = |
238 Header->GetTaggedField(NaClBitcodeHeaderField::kPNaClVersion)) { | 279 Header->GetTaggedField(NaClBitcodeHeaderField::kPNaClVersion)) { |
239 if (Version->GetType() == NaClBitcodeHeaderField::kUInt32Type) { | 280 if (Version->GetType() == NaClBitcodeHeaderField::kUInt32Type) { |
240 return Version; | 281 return Version; |
241 } | 282 } |
242 } | 283 } |
243 return 0; | 284 return 0; |
244 } | 285 } |
245 | 286 |
246 void NaClBitcodeHeader::InstallFields() { | 287 void NaClBitcodeHeader::InstallFields() { |
247 // Assume supported until contradicted. | |
248 bool UpdatedUnsupportedMessage = false; | |
249 IsSupportedFlag = true; | 288 IsSupportedFlag = true; |
250 IsReadableFlag = true; | 289 IsReadableFlag = true; |
251 UnsupportedMessage = "Supported"; | 290 AlignBitcodeRecords = false; |
252 PNaClVersion = 0; | 291 PNaClVersion = 0; |
253 if (NaClBitcodeHeaderField *Version = GetPNaClVersionPtr(this)) { | 292 UnsupportedMessage.clear(); |
254 PNaClVersion = Version->GetUInt32Value(); | 293 SmallSet<unsigned, NaClBitcodeHeaderField::kTag_MAX> FieldIDs; |
255 } | 294 |
256 if (PNaClVersion != 2) { | 295 auto ReportProblem = [&](bool IsReadable=false) { |
| 296 UnsupportedMessage.append("\n"); |
257 IsSupportedFlag = false; | 297 IsSupportedFlag = false; |
258 IsReadableFlag = false; | 298 IsReadableFlag = IsReadableFlag && IsReadable; |
259 UpdatedUnsupportedMessage = true; | 299 }; |
260 UnsupportedMessage.clear(); | 300 |
261 raw_string_ostream UnsupportedStream(UnsupportedMessage); | 301 auto ReportProblemWithContents = [&](NaClBitcodeHeaderField *Field, |
262 UnsupportedStream << "Unsupported PNaCl bitcode version: " | 302 bool IsReadable=false) { |
263 << PNaClVersion << "\n"; | 303 UnsupportedMessage.append(": "); |
264 UnsupportedStream.flush(); | 304 UnsupportedMessage.append(Field->Contents()); |
265 } | 305 ReportProblem(IsReadable); |
266 if (Fields.size() != 1) { | 306 }; |
267 IsSupportedFlag = false; | 307 |
268 IsReadableFlag = false; | 308 for (size_t i = 0, e = NumberFields(); i < e; ++i) { |
269 if (!UpdatedUnsupportedMessage) | 309 // Start by checking expected properties for any field |
270 UnsupportedMessage = "Unknown header field(s) found"; | 310 NaClBitcodeHeaderField *Field = GetField(i); |
| 311 if (!FieldIDs.insert(Field->GetID()).second) { |
| 312 UnsupportedMessage.append("Specified multiple times: "); |
| 313 UnsupportedMessage.append(Field->IDName()); |
| 314 ReportProblem(); |
| 315 continue; |
| 316 } |
| 317 NaClBitcodeHeaderField::FieldType ExpectedTy = ExpectedType[Field->GetID()]; |
| 318 if (Field->GetType() != ExpectedTy) { |
| 319 UnsupportedMessage.append("Expects type "); |
| 320 UnsupportedMessage.append(NaClBitcodeHeaderField::TypeName(ExpectedTy)); |
| 321 ReportProblemWithContents(Field); |
| 322 continue; |
| 323 } |
| 324 if (Field->GetType() == NaClBitcodeHeaderField::kUnknownType) { |
| 325 UnsupportedMessage.append("Unknown value"); |
| 326 ReportProblemWithContents(Field); |
| 327 continue; |
| 328 } |
| 329 |
| 330 // Check specific ID values and install. |
| 331 switch (Field->GetID()) { |
| 332 case NaClBitcodeHeaderField::kInvalid: |
| 333 UnsupportedMessage.append("Unsupported"); |
| 334 ReportProblemWithContents(Field); |
| 335 continue; |
| 336 case NaClBitcodeHeaderField::kPNaClVersion: |
| 337 PNaClVersion = Field->GetUInt32Value(); |
| 338 if (PNaClVersion != 2) { |
| 339 UnsupportedMessage.append("Unsupported"); |
| 340 ReportProblemWithContents(Field); |
| 341 continue; |
| 342 } |
| 343 break; |
| 344 case NaClBitcodeHeaderField::kAlignBitcodeRecords: |
| 345 AlignBitcodeRecords = true; |
| 346 UnsupportedMessage.append("Unsupported"); |
| 347 ReportProblemWithContents(Field, true); |
| 348 continue; |
| 349 } |
271 } | 350 } |
272 } | 351 } |
OLD | NEW |