Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1174)

Side by Side Diff: lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //===- NaClBitcodeHeader.cpp ----------------------------------------------===//
2 // PNaCl 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 #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
12 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
13 #include "llvm/Bitcode/ReaderWriter.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/Support/Format.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include "llvm/Support/StreamingMemoryObject.h"
18
19 #include <limits>
20 #include <cstring>
21 #include <iomanip>
22
23 using namespace llvm;
24
25 NaClBitcodeHeaderField::NaClBitcodeHeaderField()
26 : ID(kInvalid), FType(kBufferType), Len(0), Data(0) {}
27
28 NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, uint32_t MyValue)
29 : ID(MyID), FType(kUInt32Type), Len(4), Data(new uint8_t[4]) {
30 Data[0] = static_cast<uint8_t>(MyValue & 0xFF);
31 Data[1] = static_cast<uint8_t>((MyValue >> 8) & 0xFF);
32 Data[2] = static_cast<uint8_t>((MyValue >> 16) & 0xFF);
33 Data[3] = static_cast<uint8_t>((MyValue >> 24) & 0xFF);
34 }
35
36 uint32_t NaClBitcodeHeaderField::GetUInt32Value() const {
37 assert(FType == kUInt32Type && "Header field must be uint32");
38 return static_cast<uint32_t>(Data[0]) |
39 (static_cast<uint32_t>(Data[1]) << 8) |
40 (static_cast<uint32_t>(Data[2]) << 16) |
41 (static_cast<uint32_t>(Data[2]) << 24);
42 }
43
44 NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, size_t MyLen,
45 uint8_t *MyData)
46 : ID(MyID), FType(kBufferType), Len(MyLen), Data(new uint8_t[MyLen]) {
47 for (size_t i = 0; i < MyLen; ++i) {
48 Data[i] = MyData[i];
49 }
50 }
51
52 bool NaClBitcodeHeaderField::Write(uint8_t *Buf, size_t BufLen) const {
53 size_t FieldsLen = kTagLenSize + Len;
54 size_t PadLen = (WordSize - (FieldsLen & (WordSize-1))) & (WordSize-1);
55 // Ensure buffer is large enough and that length can be represented
56 // in 32 bits
57 if (BufLen < FieldsLen + PadLen ||
58 Len > std::numeric_limits<FixedSubfield>::max())
59 return false;
60
61 WriteFixedSubfield(EncodeTypedID(), Buf);
62 WriteFixedSubfield(static_cast<FixedSubfield>(Len),
63 Buf + sizeof(FixedSubfield));
64 memcpy(Buf + kTagLenSize, Data, Len);
65 // Pad out to word alignment
66 if (PadLen) {
67 memset(Buf + FieldsLen, 0, PadLen);
68 }
69 return true;
70 }
71
72 bool NaClBitcodeHeaderField::Read(const uint8_t *Buf, size_t BufLen) {
73 if (BufLen < kTagLenSize)
74 return false;
75 FixedSubfield IdField;
76 ReadFixedSubfield(&IdField, Buf);
77 FixedSubfield LengthField;
78 ReadFixedSubfield(&LengthField, Buf + sizeof(FixedSubfield));
79 size_t Length = static_cast<size_t>(LengthField);
80 if (BufLen < kTagLenSize + Length)
81 return false;
82 if (Len != Length) {
83 // Need to reallocate data buffer.
84 if (Data)
85 delete[] Data;
86 Data = new uint8_t[Length];
87 }
88 Len = Length;
89 DecodeTypedID(IdField, ID, FType);
90 memcpy(Data, Buf + kTagLenSize, Len);
91 return true;
92 }
93
94 std::string NaClBitcodeHeaderField::Contents() const {
95 std::string buffer;
96 raw_string_ostream ss(buffer);
97 switch (ID) {
98 case kPNaClVersion:
99 ss << "PNaCl Version";
100 break;
101 case kInvalid:
102 ss << "Invalid";
103 break;
104 }
105 ss << ": ";
106 switch (FType) {
107 case kUInt32Type:
108 ss << GetUInt32Value();
109 break;
110 case kBufferType:
111 ss << "[";
112 for (size_t i = 0; i < Len; ++i) {
113 if (i)
114 ss << " ";
115 ss << format("%02x", Data[i]);
116 }
117 ss << "]";
118 break;
119 }
120 return ss.str();
121 }
122
123 NaClBitcodeHeader::NaClBitcodeHeader()
124 : HeaderSize(0), UnsupportedMessage(), IsSupportedFlag(false),
125 IsReadableFlag(false), PNaClVersion(0) {}
126
127 NaClBitcodeHeader::~NaClBitcodeHeader() {
128 for (std::vector<NaClBitcodeHeaderField *>::const_iterator
129 Iter = Fields.begin(),
130 IterEnd = Fields.end();
131 Iter != IterEnd; ++Iter) {
132 delete *Iter;
133 }
134 }
135
136 bool NaClBitcodeHeader::ReadPrefix(const unsigned char *BufPtr,
137 const unsigned char *BufEnd,
138 unsigned &NumFields, unsigned &NumBytes) {
139 // Must contain PEXE.
140 if (!isNaClBitcode(BufPtr, BufEnd)) {
141 UnsupportedMessage = "Invalid PNaCl bitcode header";
142 if (isBitcode(BufPtr, BufEnd)) {
143 UnsupportedMessage += " (to run in Chrome, bitcode files must be "
144 "finalized using pnacl-finalize)";
145 }
146 return true;
147 }
148 BufPtr += WordSize;
149
150 // Read #Fields and number of bytes needed for the header.
151 if (BufPtr + WordSize > BufEnd)
152 return UnsupportedError("Bitcode read failure");
153 NumFields = static_cast<unsigned>(BufPtr[0]) |
154 (static_cast<unsigned>(BufPtr[1]) << 8);
155 NumBytes = static_cast<unsigned>(BufPtr[2]) |
156 (static_cast<unsigned>(BufPtr[3]) << 8);
157 BufPtr += WordSize;
158 return false;
159 }
160
161 bool NaClBitcodeHeader::ReadFields(const unsigned char *BufPtr,
162 const unsigned char *BufEnd,
163 unsigned NumFields, unsigned NumBytes) {
164 HeaderSize = NumBytes + (2 * WordSize);
165
166 // Read in each field.
167 for (size_t i = 0; i < NumFields; ++i) {
168 NaClBitcodeHeaderField *Field = new NaClBitcodeHeaderField();
169 Fields.push_back(Field);
170 if (!Field->Read(BufPtr, BufEnd - BufPtr))
171 return UnsupportedError("Bitcode read failure");
172 size_t FieldSize = Field->GetTotalSize();
173 BufPtr += FieldSize;
174 }
175 return false;
176 }
177
178 bool NaClBitcodeHeader::Read(const unsigned char *&BufPtr,
179 const unsigned char *&BufEnd) {
180 unsigned NumFields;
181 unsigned NumBytes;
182 if (ReadPrefix(BufPtr, BufEnd, NumFields, NumBytes))
183 return true; // ReadPrefix sets UnsupportedMessage
184 BufPtr += 2 * WordSize;
185
186 if (ReadFields(BufPtr, BufEnd, NumFields, NumBytes))
187 return true; // ReadFields sets UnsupportedMessage
188 BufPtr += NumBytes;
189 InstallFields();
190 return false;
191 }
192
193 bool NaClBitcodeHeader::Read(MemoryObject *Bytes) {
194 unsigned NumFields;
195 unsigned NumBytes;
196 // First, read the prefix, which is 2 * WordSize, to determine the
197 // NumBytes and NumFields.
198 {
199 unsigned char Buffer[2 * WordSize];
200 if (Bytes->readBytes(Buffer, sizeof(Buffer), 0) != sizeof(Buffer))
201 return UnsupportedError("Bitcode read failure");
202 if (ReadPrefix(Buffer, Buffer + sizeof(Buffer), NumFields, NumBytes))
203 return true; // ReadPrefix sets UnsupportedMessage
204 }
205 // Then read the rest, starting after the 2 * WordSize of the prefix.
206 uint8_t *Header = new uint8_t[NumBytes];
207 bool failed =
208 Bytes->readBytes(Header, NumBytes, 2 * WordSize) != NumBytes ||
209 ReadFields(Header, Header + NumBytes, NumFields, NumBytes);
210 delete[] Header;
211 if (failed)
212 return UnsupportedError("Bitcode read failure");
213 InstallFields();
214 return false;
215 }
216
217 NaClBitcodeHeaderField *
218 NaClBitcodeHeader::GetTaggedField(NaClBitcodeHeaderField::Tag ID) const {
219 for (std::vector<NaClBitcodeHeaderField *>::const_iterator
220 Iter = Fields.begin(),
221 IterEnd = Fields.end();
222 Iter != IterEnd; ++Iter) {
223 if ((*Iter)->GetID() == ID) {
224 return *Iter;
225 }
226 }
227 return 0;
228 }
229
230 NaClBitcodeHeaderField *NaClBitcodeHeader::GetField(size_t index) const {
231 if (index >= Fields.size())
232 return 0;
233 return Fields[index];
234 }
235
236 NaClBitcodeHeaderField *GetPNaClVersionPtr(NaClBitcodeHeader *Header) {
237 if (NaClBitcodeHeaderField *Version =
238 Header->GetTaggedField(NaClBitcodeHeaderField::kPNaClVersion)) {
239 if (Version->GetType() == NaClBitcodeHeaderField::kUInt32Type) {
240 return Version;
241 }
242 }
243 return 0;
244 }
245
246 void NaClBitcodeHeader::InstallFields() {
247 // Assume supported until contradicted.
248 bool UpdatedUnsupportedMessage = false;
249 IsSupportedFlag = true;
250 IsReadableFlag = true;
251 UnsupportedMessage = "Supported";
252 PNaClVersion = 0;
253 if (NaClBitcodeHeaderField *Version = GetPNaClVersionPtr(this)) {
254 PNaClVersion = Version->GetUInt32Value();
255 }
256 if (PNaClVersion != 2) {
257 IsSupportedFlag = false;
258 IsReadableFlag = false;
259 UpdatedUnsupportedMessage = true;
260 UnsupportedMessage.clear();
261 raw_string_ostream UnsupportedStream(UnsupportedMessage);
262 UnsupportedStream << "Unsupported PNaCl bitcode version: "
263 << PNaClVersion << "\n";
264 UnsupportedStream.flush();
265 }
266 if (Fields.size() != 1) {
267 IsSupportedFlag = false;
268 IsReadableFlag = false;
269 if (!UpdatedUnsupportedMessage)
270 UnsupportedMessage = "Unknown header field(s) found";
271 }
272 }
OLDNEW
« no previous file with comments | « lib/Bitcode/NaCl/Reader/NaClBitcodeDecoders.cpp ('k') | lib/Bitcode/NaCl/Reader/NaClBitcodeParser.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698