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

Side by Side Diff: courgette/encoded_program.cc

Issue 6716006: Identifying call sites that need to handle out of memory situations in Courgette. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "courgette/encoded_program.h" 5 #include "courgette/encoded_program.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
(...skipping 22 matching lines...) Expand all
33 const int kStreamLimit = 9; 33 const int kStreamLimit = 9;
34 34
35 // Constructor is here rather than in the header. Although the constructor 35 // Constructor is here rather than in the header. Although the constructor
36 // appears to do nothing it is fact quite large because of the implict calls to 36 // appears to do nothing it is fact quite large because of the implict calls to
37 // field constructors. Ditto for the destructor. 37 // field constructors. Ditto for the destructor.
38 EncodedProgram::EncodedProgram() : image_base_(0) {} 38 EncodedProgram::EncodedProgram() : image_base_(0) {}
39 EncodedProgram::~EncodedProgram() {} 39 EncodedProgram::~EncodedProgram() {}
40 40
41 // Serializes a vector of integral values using Varint32 coding. 41 // Serializes a vector of integral values using Varint32 coding.
42 template<typename T, typename A> 42 template<typename T, typename A>
43 void WriteVector(const std::vector<T, A>& items, SinkStream* buffer) { 43 CheckBool WriteVector(const std::vector<T, A>& items, SinkStream* buffer) {
44 size_t count = items.size(); 44 size_t count = items.size();
45 buffer->WriteSizeVarint32(count); 45 bool ok = buffer->WriteSizeVarint32(count);
46 for (size_t i = 0; i < count; ++i) { 46 for (size_t i = 0; ok && i < count; ++i) {
47 COMPILE_ASSERT(sizeof(T) <= sizeof(uint32), // NOLINT 47 COMPILE_ASSERT(sizeof(T) <= sizeof(uint32), // NOLINT
48 T_must_fit_in_uint32); 48 T_must_fit_in_uint32);
49 buffer->WriteSizeVarint32(items[i]); 49 ok = buffer->WriteSizeVarint32(items[i]);
50 } 50 }
51 return ok;
51 } 52 }
52 53
53 template<typename T, typename A> 54 template<typename T, typename A>
54 bool ReadVector(std::vector<T, A>* items, SourceStream* buffer) { 55 bool ReadVector(std::vector<T, A>* items, SourceStream* buffer) {
55 uint32 count; 56 uint32 count;
56 if (!buffer->ReadVarint32(&count)) 57 if (!buffer->ReadVarint32(&count))
57 return false; 58 return false;
58 59
59 items->clear(); 60 items->clear();
60 items->reserve(count); 61 items->reserve(count);
61 for (size_t i = 0; i < count; ++i) { 62 for (size_t i = 0; i < count; ++i) {
62 uint32 item; 63 uint32 item;
63 if (!buffer->ReadVarint32(&item)) 64 if (!buffer->ReadVarint32(&item))
64 return false; 65 return false;
66 // TODO(tommi): Handle errors.
65 items->push_back(static_cast<T>(item)); 67 items->push_back(static_cast<T>(item));
66 } 68 }
67 69
68 return true; 70 return true;
69 } 71 }
70 72
71 // Serializes a vector, using delta coding followed by Varint32 coding. 73 // Serializes a vector, using delta coding followed by Varint32 coding.
72 template<typename A> 74 template<typename A>
73 void WriteU32Delta(const std::vector<uint32, A>& set, SinkStream* buffer) { 75 CheckBool WriteU32Delta(const std::vector<uint32, A>& set, SinkStream* buffer) {
74 size_t count = set.size(); 76 size_t count = set.size();
75 buffer->WriteSizeVarint32(count); 77 bool ok = buffer->WriteSizeVarint32(count);
76 uint32 prev = 0; 78 uint32 prev = 0;
77 for (size_t i = 0; i < count; ++i) { 79 for (size_t i = 0; ok && i < count; ++i) {
78 uint32 current = set[i]; 80 uint32 current = set[i];
79 uint32 delta = current - prev; 81 uint32 delta = current - prev;
80 buffer->WriteVarint32(delta); 82 ok = buffer->WriteVarint32(delta);
81 prev = current; 83 prev = current;
82 } 84 }
85 return ok;
83 } 86 }
84 87
85 template <typename A> 88 template <typename A>
86 static bool ReadU32Delta(std::vector<uint32, A>* set, SourceStream* buffer) { 89 static CheckBool ReadU32Delta(std::vector<uint32, A>* set,
90 SourceStream* buffer) {
87 uint32 count; 91 uint32 count;
88 92
89 if (!buffer->ReadVarint32(&count)) 93 if (!buffer->ReadVarint32(&count))
90 return false; 94 return false;
91 95
92 set->clear(); 96 set->clear();
97 // TODO(tommi)
93 set->reserve(count); 98 set->reserve(count);
94 uint32 prev = 0; 99 uint32 prev = 0;
95 100
96 for (size_t i = 0; i < count; ++i) { 101 for (size_t i = 0; i < count; ++i) {
97 uint32 delta; 102 uint32 delta;
98 if (!buffer->ReadVarint32(&delta)) 103 if (!buffer->ReadVarint32(&delta))
99 return false; 104 return false;
100 uint32 current = prev + delta; 105 uint32 current = prev + delta;
106 // TODO(tommi): handle errors
101 set->push_back(current); 107 set->push_back(current);
102 prev = current; 108 prev = current;
103 } 109 }
104 110
111 // TODO(tommi)
robertshield 2011/03/22 18:04:07 Are you going to fix these right away afterwards?
tommi (sloooow) - chröme 2011/03/22 18:37:49 I'm going to fix these afterwards, but you're righ
105 return true; 112 return true;
106 } 113 }
107 114
108 // Write a vector as the byte representation of the contents. 115 // Write a vector as the byte representation of the contents.
109 // 116 //
110 // (This only really makes sense for a type T that has sizeof(T)==1, otherwise 117 // (This only really makes sense for a type T that has sizeof(T)==1, otherwise
111 // serilized representation is not endian-agnositic. But it is useful to keep 118 // serialized representation is not endian-agnositic. But it is useful to keep
112 // the possibility of a greater size for experiments comparing Varint32 encoding 119 // the possibility of a greater size for experiments comparing Varint32 encoding
113 // of a vector of larger integrals vs a plain form.) 120 // of a vector of larger integrals vs a plain form.)
114 // 121 //
115 template<typename T, typename A> 122 template<typename T, typename A>
116 void WriteVectorU8(const std::vector<T, A>& items, SinkStream* buffer) { 123 CheckBool WriteVectorU8(const std::vector<T, A>& items, SinkStream* buffer) {
117 size_t count = items.size(); 124 size_t count = items.size();
118 buffer->WriteSizeVarint32(count); 125 bool ok = buffer->WriteSizeVarint32(count);
119 if (count != 0) { 126 if (count != 0 && ok) {
120 size_t byte_count = count * sizeof(T); 127 size_t byte_count = count * sizeof(T);
121 buffer->Write(static_cast<const void*>(&items[0]), byte_count); 128 ok = buffer->Write(static_cast<const void*>(&items[0]), byte_count);
122 } 129 }
130 return ok;
123 } 131 }
124 132
125 template<typename T, typename A> 133 template<typename T, typename A>
126 bool ReadVectorU8(std::vector<T, A>* items, SourceStream* buffer) { 134 bool ReadVectorU8(std::vector<T, A>* items, SourceStream* buffer) {
127 uint32 count; 135 uint32 count;
128 if (!buffer->ReadVarint32(&count)) 136 if (!buffer->ReadVarint32(&count))
129 return false; 137 return false;
130 138
131 items->clear(); 139 items->clear();
140 // TODO(tommi): check error
132 items->resize(count); 141 items->resize(count);
133 if (count != 0) { 142 if (count != 0) {
134 size_t byte_count = count * sizeof(T); 143 size_t byte_count = count * sizeof(T);
135 return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count); 144 return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count);
136 } 145 }
137 return true; 146 return true;
138 } 147 }
139 148
140 //////////////////////////////////////////////////////////////////////////////// 149 ////////////////////////////////////////////////////////////////////////////////
141 150
142 void EncodedProgram::DefineRel32Label(int index, RVA value) { 151 CheckBool EncodedProgram::DefineRel32Label(int index, RVA value) {
143 DefineLabelCommon(&rel32_rva_, index, value); 152 return DefineLabelCommon(&rel32_rva_, index, value);
144 } 153 }
145 154
146 void EncodedProgram::DefineAbs32Label(int index, RVA value) { 155 CheckBool EncodedProgram::DefineAbs32Label(int index, RVA value) {
147 DefineLabelCommon(&abs32_rva_, index, value); 156 return DefineLabelCommon(&abs32_rva_, index, value);
148 } 157 }
149 158
150 static const RVA kUnassignedRVA = static_cast<RVA>(-1); 159 static const RVA kUnassignedRVA = static_cast<RVA>(-1);
151 160
152 void EncodedProgram::DefineLabelCommon(RvaVector* rvas, 161 CheckBool EncodedProgram::DefineLabelCommon(RvaVector* rvas,
153 int index, 162 int index,
154 RVA rva) { 163 RVA rva) {
155 if (static_cast<int>(rvas->size()) <= index) { 164 if (static_cast<int>(rvas->size()) <= index) {
165 // TODO(tommi): handle error
156 rvas->resize(index + 1, kUnassignedRVA); 166 rvas->resize(index + 1, kUnassignedRVA);
157 } 167 }
158 if ((*rvas)[index] != kUnassignedRVA) { 168 if ((*rvas)[index] != kUnassignedRVA) {
159 NOTREACHED() << "DefineLabel double assigned " << index; 169 NOTREACHED() << "DefineLabel double assigned " << index;
160 } 170 }
161 (*rvas)[index] = rva; 171 (*rvas)[index] = rva;
172 // TODO(tommi)
173 return true;
162 } 174 }
163 175
164 void EncodedProgram::EndLabels() { 176 void EncodedProgram::EndLabels() {
165 FinishLabelsCommon(&abs32_rva_); 177 FinishLabelsCommon(&abs32_rva_);
166 FinishLabelsCommon(&rel32_rva_); 178 FinishLabelsCommon(&rel32_rva_);
167 } 179 }
168 180
169 void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) { 181 void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) {
170 // Replace all unassigned slots with the value at the previous index so they 182 // Replace all unassigned slots with the value at the previous index so they
171 // delta-encode to zero. (There might be better values than zero. The way to 183 // delta-encode to zero. (There might be better values than zero. The way to
172 // get that is have the higher level assembly program assign the unassigned 184 // get that is have the higher level assembly program assign the unassigned
173 // slots.) 185 // slots.)
174 RVA previous = 0; 186 RVA previous = 0;
175 size_t size = rvas->size(); 187 size_t size = rvas->size();
176 for (size_t i = 0; i < size; ++i) { 188 for (size_t i = 0; i < size; ++i) {
177 if ((*rvas)[i] == kUnassignedRVA) 189 if ((*rvas)[i] == kUnassignedRVA)
178 (*rvas)[i] = previous; 190 (*rvas)[i] = previous;
179 else 191 else
180 previous = (*rvas)[i]; 192 previous = (*rvas)[i];
181 } 193 }
182 } 194 }
183 195
184 void EncodedProgram::AddOrigin(RVA origin) { 196 CheckBool EncodedProgram::AddOrigin(RVA origin) {
197 //TODO(tommi)
185 ops_.push_back(ORIGIN); 198 ops_.push_back(ORIGIN);
186 origins_.push_back(origin); 199 origins_.push_back(origin);
200 return true;
187 } 201 }
188 202
189 void EncodedProgram::AddCopy(uint32 count, const void* bytes) { 203 CheckBool EncodedProgram::AddCopy(uint32 count, const void* bytes) {
204 //TODO(tommi)
190 const uint8* source = static_cast<const uint8*>(bytes); 205 const uint8* source = static_cast<const uint8*>(bytes);
191 206
192 // Fold adjacent COPY instructions into one. This nearly halves the size of 207 // Fold adjacent COPY instructions into one. This nearly halves the size of
193 // an EncodedProgram with only COPY1 instructions since there are approx plain 208 // an EncodedProgram with only COPY1 instructions since there are approx plain
194 // 16 bytes per reloc. This has a working-set benefit during decompression. 209 // 16 bytes per reloc. This has a working-set benefit during decompression.
195 // For compression of files with large differences this makes a small (4%) 210 // For compression of files with large differences this makes a small (4%)
196 // improvement in size. For files with small differences this degrades the 211 // improvement in size. For files with small differences this degrades the
197 // compressed size by 1.3% 212 // compressed size by 1.3%
198 if (!ops_.empty()) { 213 if (!ops_.empty()) {
199 if (ops_.back() == COPY1) { 214 if (ops_.back() == COPY1) {
200 ops_.back() = COPY; 215 ops_.back() = COPY;
201 copy_counts_.push_back(1); 216 copy_counts_.push_back(1);
202 } 217 }
203 if (ops_.back() == COPY) { 218 if (ops_.back() == COPY) {
204 copy_counts_.back() += count; 219 copy_counts_.back() += count;
205 for (uint32 i = 0; i < count; ++i) { 220 for (uint32 i = 0; i < count; ++i) {
206 copy_bytes_.push_back(source[i]); 221 copy_bytes_.push_back(source[i]);
207 } 222 }
208 return; 223 return true;
209 } 224 }
210 } 225 }
211 226
212 if (count == 1) { 227 if (count == 1) {
213 ops_.push_back(COPY1); 228 ops_.push_back(COPY1);
214 copy_bytes_.push_back(source[0]); 229 copy_bytes_.push_back(source[0]);
215 } else { 230 } else {
216 ops_.push_back(COPY); 231 ops_.push_back(COPY);
217 copy_counts_.push_back(count); 232 copy_counts_.push_back(count);
218 for (uint32 i = 0; i < count; ++i) { 233 for (uint32 i = 0; i < count; ++i) {
219 copy_bytes_.push_back(source[i]); 234 copy_bytes_.push_back(source[i]);
220 } 235 }
221 } 236 }
237
238 return true;
222 } 239 }
223 240
224 void EncodedProgram::AddAbs32(int label_index) { 241 CheckBool EncodedProgram::AddAbs32(int label_index) {
242 //TODO(tommi)
225 ops_.push_back(ABS32); 243 ops_.push_back(ABS32);
226 abs32_ix_.push_back(label_index); 244 abs32_ix_.push_back(label_index);
245 return true;
227 } 246 }
228 247
229 void EncodedProgram::AddRel32(int label_index) { 248 CheckBool EncodedProgram::AddRel32(int label_index) {
249 //TODO(tommi)
230 ops_.push_back(REL32); 250 ops_.push_back(REL32);
231 rel32_ix_.push_back(label_index); 251 rel32_ix_.push_back(label_index);
252 return true;
232 } 253 }
233 254
234 void EncodedProgram::AddMakeRelocs() { 255 CheckBool EncodedProgram::AddMakeRelocs() {
256 //TODO(tommi)
235 ops_.push_back(MAKE_BASE_RELOCATION_TABLE); 257 ops_.push_back(MAKE_BASE_RELOCATION_TABLE);
258 return true;
236 } 259 }
237 260
238 void EncodedProgram::DebuggingSummary() { 261 void EncodedProgram::DebuggingSummary() {
239 VLOG(1) << "EncodedProgram Summary" 262 VLOG(1) << "EncodedProgram Summary"
240 << "\n image base " << image_base_ 263 << "\n image base " << image_base_
241 << "\n abs32 rvas " << abs32_rva_.size() 264 << "\n abs32 rvas " << abs32_rva_.size()
242 << "\n rel32 rvas " << rel32_rva_.size() 265 << "\n rel32 rvas " << rel32_rva_.size()
243 << "\n ops " << ops_.size() 266 << "\n ops " << ops_.size()
244 << "\n origins " << origins_.size() 267 << "\n origins " << origins_.size()
245 << "\n copy_counts " << copy_counts_.size() 268 << "\n copy_counts " << copy_counts_.size()
(...skipping 26 matching lines...) Expand all
272 scoped_ptr<base::Environment> env(base::Environment::Create()); 295 scoped_ptr<base::Environment> env(base::Environment::Create());
273 std::string s; 296 std::string s;
274 env->GetVar("A_FIELDS", &s); 297 env->GetVar("A_FIELDS", &s);
275 if (!s.empty()) { 298 if (!s.empty()) {
276 return static_cast<FieldSelect>(wcstoul(ASCIIToWide(s).c_str(), 0, 0)); 299 return static_cast<FieldSelect>(wcstoul(ASCIIToWide(s).c_str(), 0, 0));
277 } 300 }
278 #endif 301 #endif
279 return static_cast<FieldSelect>(~0); 302 return static_cast<FieldSelect>(~0);
280 } 303 }
281 304
282 void EncodedProgram::WriteTo(SinkStreamSet* streams) { 305 CheckBool EncodedProgram::WriteTo(SinkStreamSet* streams) {
283 FieldSelect select = GetFieldSelect(); 306 FieldSelect select = GetFieldSelect();
284 307
285 // The order of fields must be consistent in WriteTo and ReadFrom, regardless 308 // The order of fields must be consistent in WriteTo and ReadFrom, regardless
286 // of the streams used. The code can be configured with all kStreamXXX 309 // of the streams used. The code can be configured with all kStreamXXX
287 // constants the same. 310 // constants the same.
288 // 311 //
289 // If we change the code to pipeline reading with assembly (to avoid temporary 312 // If we change the code to pipeline reading with assembly (to avoid temporary
290 // storage vectors by consuming operands directly from the stream) then we 313 // storage vectors by consuming operands directly from the stream) then we
291 // need to read the base address and the random access address tables first, 314 // need to read the base address and the random access address tables first,
292 // the rest can be interleaved. 315 // the rest can be interleaved.
293 316
294 if (select & INCLUDE_MISC) { 317 if (select & INCLUDE_MISC) {
295 // TODO(sra): write 64 bits. 318 // TODO(sra): write 64 bits.
296 streams->stream(kStreamMisc)->WriteVarint32( 319 if (!streams->stream(kStreamMisc)->WriteVarint32(
297 static_cast<uint32>(image_base_)); 320 static_cast<uint32>(image_base_))) {
321 return false;
322 }
298 } 323 }
299 324
300 if (select & INCLUDE_ABS32_ADDRESSES) 325 bool success = true;
301 WriteU32Delta(abs32_rva_, streams->stream(kStreamAbs32Addresses)); 326
302 if (select & INCLUDE_REL32_ADDRESSES) 327 if (select & INCLUDE_ABS32_ADDRESSES) {
303 WriteU32Delta(rel32_rva_, streams->stream(kStreamRel32Addresses)); 328 success &= WriteU32Delta(abs32_rva_,
robertshield 2011/03/22 18:04:07 question probably for the next CL, but do you plan
tommi (sloooow) - chröme 2011/03/22 18:37:49 My plan is to implement it so that once a Write ha
329 streams->stream(kStreamAbs32Addresses));
330 }
331
332 if (select & INCLUDE_REL32_ADDRESSES) {
333 success &= WriteU32Delta(rel32_rva_,
334 streams->stream(kStreamRel32Addresses));
335 }
336
304 if (select & INCLUDE_MISC) 337 if (select & INCLUDE_MISC)
305 WriteVector(origins_, streams->stream(kStreamOriginAddresses)); 338 success &= WriteVector(origins_, streams->stream(kStreamOriginAddresses));
339
306 if (select & INCLUDE_OPS) { 340 if (select & INCLUDE_OPS) {
307 streams->stream(kStreamOps)->Reserve(ops_.size() + 5); // 5 for length. 341 // 5 for length.
308 WriteVector(ops_, streams->stream(kStreamOps)); 342 success &= streams->stream(kStreamOps)->Reserve(ops_.size() + 5);
343 success &= WriteVector(ops_, streams->stream(kStreamOps));
309 } 344 }
345
310 if (select & INCLUDE_COPY_COUNTS) 346 if (select & INCLUDE_COPY_COUNTS)
311 WriteVector(copy_counts_, streams->stream(kStreamCopyCounts)); 347 success &= WriteVector(copy_counts_, streams->stream(kStreamCopyCounts));
348
312 if (select & INCLUDE_BYTES) 349 if (select & INCLUDE_BYTES)
313 WriteVectorU8(copy_bytes_, streams->stream(kStreamBytes)); 350 success &= WriteVectorU8(copy_bytes_, streams->stream(kStreamBytes));
351
314 if (select & INCLUDE_ABS32_INDEXES) 352 if (select & INCLUDE_ABS32_INDEXES)
315 WriteVector(abs32_ix_, streams->stream(kStreamAbs32Indexes)); 353 success &= WriteVector(abs32_ix_, streams->stream(kStreamAbs32Indexes));
354
316 if (select & INCLUDE_REL32_INDEXES) 355 if (select & INCLUDE_REL32_INDEXES)
317 WriteVector(rel32_ix_, streams->stream(kStreamRel32Indexes)); 356 success &= WriteVector(rel32_ix_, streams->stream(kStreamRel32Indexes));
357
358 return success;
318 } 359 }
319 360
320 bool EncodedProgram::ReadFrom(SourceStreamSet* streams) { 361 bool EncodedProgram::ReadFrom(SourceStreamSet* streams) {
321 // TODO(sra): read 64 bits. 362 // TODO(sra): read 64 bits.
322 uint32 temp; 363 uint32 temp;
323 if (!streams->stream(kStreamMisc)->ReadVarint32(&temp)) 364 if (!streams->stream(kStreamMisc)->ReadVarint32(&temp))
324 return false; 365 return false;
325 image_base_ = temp; 366 image_base_ = temp;
326 367
327 if (!ReadU32Delta(&abs32_rva_, streams->stream(kStreamAbs32Addresses))) 368 if (!ReadU32Delta(&abs32_rva_, streams->stream(kStreamAbs32Addresses)))
(...skipping 25 matching lines...) Expand all
353 // Safe, non-throwing version of std::vector::at(). Returns 'true' for success, 394 // Safe, non-throwing version of std::vector::at(). Returns 'true' for success,
354 // 'false' for out-of-bounds index error. 395 // 'false' for out-of-bounds index error.
355 template<typename T, typename A> 396 template<typename T, typename A>
356 bool VectorAt(const std::vector<T, A>& v, size_t index, T* output) { 397 bool VectorAt(const std::vector<T, A>& v, size_t index, T* output) {
357 if (index >= v.size()) 398 if (index >= v.size())
358 return false; 399 return false;
359 *output = v[index]; 400 *output = v[index];
360 return true; 401 return true;
361 } 402 }
362 403
363 bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { 404 CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
364 // For the most part, the assembly process walks the various tables. 405 // For the most part, the assembly process walks the various tables.
365 // ix_mumble is the index into the mumble table. 406 // ix_mumble is the index into the mumble table.
366 size_t ix_origins = 0; 407 size_t ix_origins = 0;
367 size_t ix_copy_counts = 0; 408 size_t ix_copy_counts = 0;
368 size_t ix_copy_bytes = 0; 409 size_t ix_copy_bytes = 0;
369 size_t ix_abs32_ix = 0; 410 size_t ix_abs32_ix = 0;
370 size_t ix_rel32_ix = 0; 411 size_t ix_rel32_ix = 0;
371 412
372 RVA current_rva = 0; 413 RVA current_rva = 0;
373 414
(...skipping 21 matching lines...) Expand all
395 case COPY: { 436 case COPY: {
396 uint32 count; 437 uint32 count;
397 if (!VectorAt(copy_counts_, ix_copy_counts, &count)) 438 if (!VectorAt(copy_counts_, ix_copy_counts, &count))
398 return false; 439 return false;
399 ++ix_copy_counts; 440 ++ix_copy_counts;
400 for (uint32 i = 0; i < count; ++i) { 441 for (uint32 i = 0; i < count; ++i) {
401 uint8 b; 442 uint8 b;
402 if (!VectorAt(copy_bytes_, ix_copy_bytes, &b)) 443 if (!VectorAt(copy_bytes_, ix_copy_bytes, &b))
403 return false; 444 return false;
404 ++ix_copy_bytes; 445 ++ix_copy_bytes;
405 output->Write(&b, 1); 446 if (!output->Write(&b, 1))
447 return false;
406 } 448 }
407 current_rva += count; 449 current_rva += count;
408 break; 450 break;
409 } 451 }
410 452
411 case COPY1: { 453 case COPY1: {
412 uint8 b; 454 uint8 b;
413 if (!VectorAt(copy_bytes_, ix_copy_bytes, &b)) 455 if (!VectorAt(copy_bytes_, ix_copy_bytes, &b))
414 return false; 456 return false;
415 ++ix_copy_bytes; 457 ++ix_copy_bytes;
416 output->Write(&b, 1); 458 if (!output->Write(&b, 1))
459 return false;
417 current_rva += 1; 460 current_rva += 1;
418 break; 461 break;
419 } 462 }
420 463
421 case REL32: { 464 case REL32: {
422 uint32 index; 465 uint32 index;
423 if (!VectorAt(rel32_ix_, ix_rel32_ix, &index)) 466 if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
424 return false; 467 return false;
425 ++ix_rel32_ix; 468 ++ix_rel32_ix;
426 RVA rva; 469 RVA rva;
427 if (!VectorAt(rel32_rva_, index, &rva)) 470 if (!VectorAt(rel32_rva_, index, &rva))
428 return false; 471 return false;
429 uint32 offset = (rva - (current_rva + 4)); 472 uint32 offset = (rva - (current_rva + 4));
430 output->Write(&offset, 4); 473 if (!output->Write(&offset, 4))
474 return false;
431 current_rva += 4; 475 current_rva += 4;
432 break; 476 break;
433 } 477 }
434 478
435 case ABS32: { 479 case ABS32: {
436 uint32 index; 480 uint32 index;
437 if (!VectorAt(abs32_ix_, ix_abs32_ix, &index)) 481 if (!VectorAt(abs32_ix_, ix_abs32_ix, &index))
438 return false; 482 return false;
439 ++ix_abs32_ix; 483 ++ix_abs32_ix;
440 RVA rva; 484 RVA rva;
441 if (!VectorAt(abs32_rva_, index, &rva)) 485 if (!VectorAt(abs32_rva_, index, &rva))
442 return false; 486 return false;
443 uint32 abs32 = static_cast<uint32>(rva + image_base_); 487 uint32 abs32 = static_cast<uint32>(rva + image_base_);
444 abs32_relocs_.push_back(current_rva); 488 abs32_relocs_.push_back(current_rva);
445 output->Write(&abs32, 4); 489 if (!output->Write(&abs32, 4))
490 return false;
446 current_rva += 4; 491 current_rva += 4;
447 break; 492 break;
448 } 493 }
449 494
450 case MAKE_BASE_RELOCATION_TABLE: { 495 case MAKE_BASE_RELOCATION_TABLE: {
451 // We can see the base relocation anywhere, but we only have the 496 // We can see the base relocation anywhere, but we only have the
452 // information to generate it at the very end. So we divert the bytes 497 // information to generate it at the very end. So we divert the bytes
453 // we are generating to a temporary stream. 498 // we are generating to a temporary stream.
454 if (pending_base_relocation_table) // Can't have two base relocation 499 if (pending_base_relocation_table) // Can't have two base relocation
455 // tables. 500 // tables.
456 return false; 501 return false;
457 502
458 pending_base_relocation_table = true; 503 pending_base_relocation_table = true;
459 output = &bytes_following_base_relocation_table; 504 output = &bytes_following_base_relocation_table;
460 break; 505 break;
461 // There is a potential problem *if* the instruction stream contains 506 // There is a potential problem *if* the instruction stream contains
462 // some REL32 relocations following the base relocation and in the same 507 // some REL32 relocations following the base relocation and in the same
463 // section. We don't know the size of the table, so 'current_rva' will 508 // section. We don't know the size of the table, so 'current_rva' will
464 // be wrong, causing REL32 offsets to be miscalculated. This never 509 // be wrong, causing REL32 offsets to be miscalculated. This never
465 // happens; the base relocation table is usually in a section of its 510 // happens; the base relocation table is usually in a section of its
466 // own, a data-only section, and following everything else in the 511 // own, a data-only section, and following everything else in the
467 // executable except some padding zero bytes. We could fix this by 512 // executable except some padding zero bytes. We could fix this by
468 // emitting an ORIGIN after the MAKE_BASE_RELOCATION_TABLE. 513 // emitting an ORIGIN after the MAKE_BASE_RELOCATION_TABLE.
469 } 514 }
470 } 515 }
471 } 516 }
472 517
473 if (pending_base_relocation_table) { 518 if (pending_base_relocation_table) {
474 GenerateBaseRelocations(final_buffer); 519 if (!GenerateBaseRelocations(final_buffer) ||
475 final_buffer->Append(&bytes_following_base_relocation_table); 520 !final_buffer->Append(&bytes_following_base_relocation_table))
521 return false;
476 } 522 }
477 523
478 // Final verification check: did we consume all lists? 524 // Final verification check: did we consume all lists?
479 if (ix_copy_counts != copy_counts_.size()) 525 if (ix_copy_counts != copy_counts_.size())
480 return false; 526 return false;
481 if (ix_copy_bytes != copy_bytes_.size()) 527 if (ix_copy_bytes != copy_bytes_.size())
482 return false; 528 return false;
483 if (ix_abs32_ix != abs32_ix_.size()) 529 if (ix_abs32_ix != abs32_ix_.size())
484 return false; 530 return false;
485 if (ix_rel32_ix != rel32_ix_.size()) 531 if (ix_rel32_ix != rel32_ix_.size())
486 return false; 532 return false;
487 533
488 return true; 534 return true;
489 } 535 }
490 536
491
492 // RelocBlock has the layout of a block of relocations in the base relocation 537 // RelocBlock has the layout of a block of relocations in the base relocation
493 // table file format. 538 // table file format.
494 // 539 //
495 struct RelocBlockPOD { 540 struct RelocBlockPOD {
496 uint32 page_rva; 541 uint32 page_rva;
497 uint32 block_size; 542 uint32 block_size;
498 uint16 relocs[4096]; // Allow up to one relocation per byte of a 4k page. 543 uint16 relocs[4096]; // Allow up to one relocation per byte of a 4k page.
499 }; 544 };
500 545
501 COMPILE_ASSERT(offsetof(RelocBlockPOD, relocs) == 8, reloc_block_header_size); 546 COMPILE_ASSERT(offsetof(RelocBlockPOD, relocs) == 8, reloc_block_header_size);
502 547
503 class RelocBlock { 548 class RelocBlock {
504 public: 549 public:
505 RelocBlock() { 550 RelocBlock() {
506 pod.page_rva = ~0; 551 pod.page_rva = ~0;
507 pod.block_size = 8; 552 pod.block_size = 8;
508 } 553 }
509 554
510 void Add(uint16 item) { 555 void Add(uint16 item) {
511 pod.relocs[(pod.block_size-8)/2] = item; 556 pod.relocs[(pod.block_size-8)/2] = item;
512 pod.block_size += 2; 557 pod.block_size += 2;
513 } 558 }
514 559
515 void Flush(SinkStream* buffer) { 560 CheckBool Flush(SinkStream* buffer) {
561 bool ok = true;
516 if (pod.block_size != 8) { 562 if (pod.block_size != 8) {
517 if (pod.block_size % 4 != 0) { // Pad to make size multiple of 4 bytes. 563 if (pod.block_size % 4 != 0) { // Pad to make size multiple of 4 bytes.
518 Add(0); 564 Add(0);
519 } 565 }
520 buffer->Write(&pod, pod.block_size); 566 ok = buffer->Write(&pod, pod.block_size);
521 pod.block_size = 8; 567 pod.block_size = 8;
522 } 568 }
569 return ok;
523 } 570 }
524 RelocBlockPOD pod; 571 RelocBlockPOD pod;
525 }; 572 };
526 573
527 void EncodedProgram::GenerateBaseRelocations(SinkStream* buffer) { 574 CheckBool EncodedProgram::GenerateBaseRelocations(SinkStream* buffer) {
528 std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); 575 std::sort(abs32_relocs_.begin(), abs32_relocs_.end());
529 576
530 RelocBlock block; 577 RelocBlock block;
531 578
532 for (size_t i = 0; i < abs32_relocs_.size(); ++i) { 579 bool ok = true;
580 for (size_t i = 0; ok && i < abs32_relocs_.size(); ++i) {
533 uint32 rva = abs32_relocs_[i]; 581 uint32 rva = abs32_relocs_[i];
534 uint32 page_rva = rva & ~0xFFF; 582 uint32 page_rva = rva & ~0xFFF;
535 if (page_rva != block.pod.page_rva) { 583 if (page_rva != block.pod.page_rva) {
536 block.Flush(buffer); 584 ok &= block.Flush(buffer);
537 block.pod.page_rva = page_rva; 585 block.pod.page_rva = page_rva;
538 } 586 }
539 block.Add(0x3000 | (rva & 0xFFF)); 587 if (ok)
588 block.Add(0x3000 | (rva & 0xFFF));
540 } 589 }
541 block.Flush(buffer); 590 ok &= block.Flush(buffer);
591 return ok;
542 } 592 }
543 593
544 //////////////////////////////////////////////////////////////////////////////// 594 ////////////////////////////////////////////////////////////////////////////////
545 595
546 Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) { 596 Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) {
547 encoded->WriteTo(sink); 597 if (!encoded->WriteTo(sink))
598 return C_STREAM_ERROR;
548 return C_OK; 599 return C_OK;
549 } 600 }
550 601
551 Status ReadEncodedProgram(SourceStreamSet* streams, EncodedProgram** output) { 602 Status ReadEncodedProgram(SourceStreamSet* streams, EncodedProgram** output) {
552 EncodedProgram* encoded = new EncodedProgram(); 603 EncodedProgram* encoded = new EncodedProgram();
553 if (encoded->ReadFrom(streams)) { 604 if (encoded->ReadFrom(streams)) {
554 *output = encoded; 605 *output = encoded;
555 return C_OK; 606 return C_OK;
556 } 607 }
557 delete encoded; 608 delete encoded;
558 return C_DESERIALIZATION_FAILED; 609 return C_DESERIALIZATION_FAILED;
559 } 610 }
560 611
561 Status Assemble(EncodedProgram* encoded, SinkStream* buffer) { 612 Status Assemble(EncodedProgram* encoded, SinkStream* buffer) {
562 bool assembled = encoded->AssembleTo(buffer); 613 bool assembled = encoded->AssembleTo(buffer);
563 if (assembled) 614 if (assembled)
564 return C_OK; 615 return C_OK;
565 return C_ASSEMBLY_FAILED; 616 return C_ASSEMBLY_FAILED;
566 } 617 }
567 618
568 void DeleteEncodedProgram(EncodedProgram* encoded) { 619 void DeleteEncodedProgram(EncodedProgram* encoded) {
569 delete encoded; 620 delete encoded;
570 } 621 }
571 622
572 } // end namespace 623 } // end namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698