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