Chromium Code Reviews| Index: courgette/encoded_program.cc |
| =================================================================== |
| --- courgette/encoded_program.cc (revision 78901) |
| +++ courgette/encoded_program.cc (working copy) |
| @@ -40,14 +40,15 @@ |
| // Serializes a vector of integral values using Varint32 coding. |
| template<typename T, typename A> |
| -void WriteVector(const std::vector<T, A>& items, SinkStream* buffer) { |
| +CheckBool WriteVector(const std::vector<T, A>& items, SinkStream* buffer) { |
| size_t count = items.size(); |
| - buffer->WriteSizeVarint32(count); |
| - for (size_t i = 0; i < count; ++i) { |
| + bool ok = buffer->WriteSizeVarint32(count); |
| + for (size_t i = 0; ok && i < count; ++i) { |
| COMPILE_ASSERT(sizeof(T) <= sizeof(uint32), // NOLINT |
| T_must_fit_in_uint32); |
| - buffer->WriteSizeVarint32(items[i]); |
| + ok = buffer->WriteSizeVarint32(items[i]); |
| } |
| + return ok; |
| } |
| template<typename T, typename A> |
| @@ -62,6 +63,7 @@ |
| uint32 item; |
| if (!buffer->ReadVarint32(&item)) |
| return false; |
| + // TODO(tommi): Handle errors. |
| items->push_back(static_cast<T>(item)); |
| } |
| @@ -70,26 +72,29 @@ |
| // Serializes a vector, using delta coding followed by Varint32 coding. |
| template<typename A> |
| -void WriteU32Delta(const std::vector<uint32, A>& set, SinkStream* buffer) { |
| +CheckBool WriteU32Delta(const std::vector<uint32, A>& set, SinkStream* buffer) { |
| size_t count = set.size(); |
| - buffer->WriteSizeVarint32(count); |
| + bool ok = buffer->WriteSizeVarint32(count); |
| uint32 prev = 0; |
| - for (size_t i = 0; i < count; ++i) { |
| + for (size_t i = 0; ok && i < count; ++i) { |
| uint32 current = set[i]; |
| uint32 delta = current - prev; |
| - buffer->WriteVarint32(delta); |
| + ok = buffer->WriteVarint32(delta); |
| prev = current; |
| } |
| + return ok; |
| } |
| template <typename A> |
| -static bool ReadU32Delta(std::vector<uint32, A>* set, SourceStream* buffer) { |
| +static CheckBool ReadU32Delta(std::vector<uint32, A>* set, |
| + SourceStream* buffer) { |
| uint32 count; |
| if (!buffer->ReadVarint32(&count)) |
| return false; |
| set->clear(); |
| + // TODO(tommi) |
| set->reserve(count); |
| uint32 prev = 0; |
| @@ -98,28 +103,31 @@ |
| if (!buffer->ReadVarint32(&delta)) |
| return false; |
| uint32 current = prev + delta; |
| + // TODO(tommi): handle errors |
| set->push_back(current); |
| prev = current; |
| } |
| + // 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
|
| return true; |
| } |
| // Write a vector as the byte representation of the contents. |
| // |
| // (This only really makes sense for a type T that has sizeof(T)==1, otherwise |
| -// serilized representation is not endian-agnositic. But it is useful to keep |
| +// serialized representation is not endian-agnositic. But it is useful to keep |
| // the possibility of a greater size for experiments comparing Varint32 encoding |
| // of a vector of larger integrals vs a plain form.) |
| // |
| template<typename T, typename A> |
| -void WriteVectorU8(const std::vector<T, A>& items, SinkStream* buffer) { |
| +CheckBool WriteVectorU8(const std::vector<T, A>& items, SinkStream* buffer) { |
| size_t count = items.size(); |
| - buffer->WriteSizeVarint32(count); |
| - if (count != 0) { |
| + bool ok = buffer->WriteSizeVarint32(count); |
| + if (count != 0 && ok) { |
| size_t byte_count = count * sizeof(T); |
| - buffer->Write(static_cast<const void*>(&items[0]), byte_count); |
| + ok = buffer->Write(static_cast<const void*>(&items[0]), byte_count); |
| } |
| + return ok; |
| } |
| template<typename T, typename A> |
| @@ -129,6 +137,7 @@ |
| return false; |
| items->clear(); |
| + // TODO(tommi): check error |
| items->resize(count); |
| if (count != 0) { |
| size_t byte_count = count * sizeof(T); |
| @@ -139,26 +148,29 @@ |
| //////////////////////////////////////////////////////////////////////////////// |
| -void EncodedProgram::DefineRel32Label(int index, RVA value) { |
| - DefineLabelCommon(&rel32_rva_, index, value); |
| +CheckBool EncodedProgram::DefineRel32Label(int index, RVA value) { |
| + return DefineLabelCommon(&rel32_rva_, index, value); |
| } |
| -void EncodedProgram::DefineAbs32Label(int index, RVA value) { |
| - DefineLabelCommon(&abs32_rva_, index, value); |
| +CheckBool EncodedProgram::DefineAbs32Label(int index, RVA value) { |
| + return DefineLabelCommon(&abs32_rva_, index, value); |
| } |
| static const RVA kUnassignedRVA = static_cast<RVA>(-1); |
| -void EncodedProgram::DefineLabelCommon(RvaVector* rvas, |
| - int index, |
| - RVA rva) { |
| +CheckBool EncodedProgram::DefineLabelCommon(RvaVector* rvas, |
| + int index, |
| + RVA rva) { |
| if (static_cast<int>(rvas->size()) <= index) { |
| + // TODO(tommi): handle error |
| rvas->resize(index + 1, kUnassignedRVA); |
| } |
| if ((*rvas)[index] != kUnassignedRVA) { |
| NOTREACHED() << "DefineLabel double assigned " << index; |
| } |
| (*rvas)[index] = rva; |
| + // TODO(tommi) |
| + return true; |
| } |
| void EncodedProgram::EndLabels() { |
| @@ -181,12 +193,15 @@ |
| } |
| } |
| -void EncodedProgram::AddOrigin(RVA origin) { |
| +CheckBool EncodedProgram::AddOrigin(RVA origin) { |
| + //TODO(tommi) |
| ops_.push_back(ORIGIN); |
| origins_.push_back(origin); |
| + return true; |
| } |
| -void EncodedProgram::AddCopy(uint32 count, const void* bytes) { |
| +CheckBool EncodedProgram::AddCopy(uint32 count, const void* bytes) { |
| + //TODO(tommi) |
| const uint8* source = static_cast<const uint8*>(bytes); |
| // Fold adjacent COPY instructions into one. This nearly halves the size of |
| @@ -205,7 +220,7 @@ |
| for (uint32 i = 0; i < count; ++i) { |
| copy_bytes_.push_back(source[i]); |
| } |
| - return; |
| + return true; |
| } |
| } |
| @@ -219,20 +234,28 @@ |
| copy_bytes_.push_back(source[i]); |
| } |
| } |
| + |
| + return true; |
| } |
| -void EncodedProgram::AddAbs32(int label_index) { |
| +CheckBool EncodedProgram::AddAbs32(int label_index) { |
| + //TODO(tommi) |
| ops_.push_back(ABS32); |
| abs32_ix_.push_back(label_index); |
| + return true; |
| } |
| -void EncodedProgram::AddRel32(int label_index) { |
| +CheckBool EncodedProgram::AddRel32(int label_index) { |
| + //TODO(tommi) |
| ops_.push_back(REL32); |
| rel32_ix_.push_back(label_index); |
| + return true; |
| } |
| -void EncodedProgram::AddMakeRelocs() { |
| +CheckBool EncodedProgram::AddMakeRelocs() { |
| + //TODO(tommi) |
| ops_.push_back(MAKE_BASE_RELOCATION_TABLE); |
| + return true; |
| } |
| void EncodedProgram::DebuggingSummary() { |
| @@ -279,7 +302,7 @@ |
| return static_cast<FieldSelect>(~0); |
| } |
| -void EncodedProgram::WriteTo(SinkStreamSet* streams) { |
| +CheckBool EncodedProgram::WriteTo(SinkStreamSet* streams) { |
| FieldSelect select = GetFieldSelect(); |
| // The order of fields must be consistent in WriteTo and ReadFrom, regardless |
| @@ -293,28 +316,46 @@ |
| if (select & INCLUDE_MISC) { |
| // TODO(sra): write 64 bits. |
| - streams->stream(kStreamMisc)->WriteVarint32( |
| - static_cast<uint32>(image_base_)); |
| + if (!streams->stream(kStreamMisc)->WriteVarint32( |
| + static_cast<uint32>(image_base_))) { |
| + return false; |
| + } |
| } |
| - if (select & INCLUDE_ABS32_ADDRESSES) |
| - WriteU32Delta(abs32_rva_, streams->stream(kStreamAbs32Addresses)); |
| - if (select & INCLUDE_REL32_ADDRESSES) |
| - WriteU32Delta(rel32_rva_, streams->stream(kStreamRel32Addresses)); |
| + bool success = true; |
| + |
| + if (select & INCLUDE_ABS32_ADDRESSES) { |
| + 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
|
| + streams->stream(kStreamAbs32Addresses)); |
| + } |
| + |
| + if (select & INCLUDE_REL32_ADDRESSES) { |
| + success &= WriteU32Delta(rel32_rva_, |
| + streams->stream(kStreamRel32Addresses)); |
| + } |
| + |
| if (select & INCLUDE_MISC) |
| - WriteVector(origins_, streams->stream(kStreamOriginAddresses)); |
| + success &= WriteVector(origins_, streams->stream(kStreamOriginAddresses)); |
| + |
| if (select & INCLUDE_OPS) { |
| - streams->stream(kStreamOps)->Reserve(ops_.size() + 5); // 5 for length. |
| - WriteVector(ops_, streams->stream(kStreamOps)); |
| + // 5 for length. |
| + success &= streams->stream(kStreamOps)->Reserve(ops_.size() + 5); |
| + success &= WriteVector(ops_, streams->stream(kStreamOps)); |
| } |
| + |
| if (select & INCLUDE_COPY_COUNTS) |
| - WriteVector(copy_counts_, streams->stream(kStreamCopyCounts)); |
| + success &= WriteVector(copy_counts_, streams->stream(kStreamCopyCounts)); |
| + |
| if (select & INCLUDE_BYTES) |
| - WriteVectorU8(copy_bytes_, streams->stream(kStreamBytes)); |
| + success &= WriteVectorU8(copy_bytes_, streams->stream(kStreamBytes)); |
| + |
| if (select & INCLUDE_ABS32_INDEXES) |
| - WriteVector(abs32_ix_, streams->stream(kStreamAbs32Indexes)); |
| + success &= WriteVector(abs32_ix_, streams->stream(kStreamAbs32Indexes)); |
| + |
| if (select & INCLUDE_REL32_INDEXES) |
| - WriteVector(rel32_ix_, streams->stream(kStreamRel32Indexes)); |
| + success &= WriteVector(rel32_ix_, streams->stream(kStreamRel32Indexes)); |
| + |
| + return success; |
| } |
| bool EncodedProgram::ReadFrom(SourceStreamSet* streams) { |
| @@ -360,7 +401,7 @@ |
| return true; |
| } |
| -bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { |
| +CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { |
| // For the most part, the assembly process walks the various tables. |
| // ix_mumble is the index into the mumble table. |
| size_t ix_origins = 0; |
| @@ -402,7 +443,8 @@ |
| if (!VectorAt(copy_bytes_, ix_copy_bytes, &b)) |
| return false; |
| ++ix_copy_bytes; |
| - output->Write(&b, 1); |
| + if (!output->Write(&b, 1)) |
| + return false; |
| } |
| current_rva += count; |
| break; |
| @@ -413,7 +455,8 @@ |
| if (!VectorAt(copy_bytes_, ix_copy_bytes, &b)) |
| return false; |
| ++ix_copy_bytes; |
| - output->Write(&b, 1); |
| + if (!output->Write(&b, 1)) |
| + return false; |
| current_rva += 1; |
| break; |
| } |
| @@ -427,7 +470,8 @@ |
| if (!VectorAt(rel32_rva_, index, &rva)) |
| return false; |
| uint32 offset = (rva - (current_rva + 4)); |
| - output->Write(&offset, 4); |
| + if (!output->Write(&offset, 4)) |
| + return false; |
| current_rva += 4; |
| break; |
| } |
| @@ -442,7 +486,8 @@ |
| return false; |
| uint32 abs32 = static_cast<uint32>(rva + image_base_); |
| abs32_relocs_.push_back(current_rva); |
| - output->Write(&abs32, 4); |
| + if (!output->Write(&abs32, 4)) |
| + return false; |
| current_rva += 4; |
| break; |
| } |
| @@ -471,8 +516,9 @@ |
| } |
| if (pending_base_relocation_table) { |
| - GenerateBaseRelocations(final_buffer); |
| - final_buffer->Append(&bytes_following_base_relocation_table); |
| + if (!GenerateBaseRelocations(final_buffer) || |
| + !final_buffer->Append(&bytes_following_base_relocation_table)) |
| + return false; |
| } |
| // Final verification check: did we consume all lists? |
| @@ -488,7 +534,6 @@ |
| return true; |
| } |
| - |
| // RelocBlock has the layout of a block of relocations in the base relocation |
| // table file format. |
| // |
| @@ -512,39 +557,45 @@ |
| pod.block_size += 2; |
| } |
| - void Flush(SinkStream* buffer) { |
| + CheckBool Flush(SinkStream* buffer) { |
| + bool ok = true; |
| if (pod.block_size != 8) { |
| if (pod.block_size % 4 != 0) { // Pad to make size multiple of 4 bytes. |
| Add(0); |
| } |
| - buffer->Write(&pod, pod.block_size); |
| + ok = buffer->Write(&pod, pod.block_size); |
| pod.block_size = 8; |
| } |
| + return ok; |
| } |
| RelocBlockPOD pod; |
| }; |
| -void EncodedProgram::GenerateBaseRelocations(SinkStream* buffer) { |
| +CheckBool EncodedProgram::GenerateBaseRelocations(SinkStream* buffer) { |
| std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); |
| RelocBlock block; |
| - for (size_t i = 0; i < abs32_relocs_.size(); ++i) { |
| + bool ok = true; |
| + for (size_t i = 0; ok && i < abs32_relocs_.size(); ++i) { |
| uint32 rva = abs32_relocs_[i]; |
| uint32 page_rva = rva & ~0xFFF; |
| if (page_rva != block.pod.page_rva) { |
| - block.Flush(buffer); |
| + ok &= block.Flush(buffer); |
| block.pod.page_rva = page_rva; |
| } |
| - block.Add(0x3000 | (rva & 0xFFF)); |
| + if (ok) |
| + block.Add(0x3000 | (rva & 0xFFF)); |
| } |
| - block.Flush(buffer); |
| + ok &= block.Flush(buffer); |
| + return ok; |
| } |
| //////////////////////////////////////////////////////////////////////////////// |
| Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) { |
| - encoded->WriteTo(sink); |
| + if (!encoded->WriteTo(sink)) |
| + return C_STREAM_ERROR; |
| return C_OK; |
| } |