diff options
Diffstat (limited to 'courgette/encoded_program.cc')
-rw-r--r-- | courgette/encoded_program.cc | 165 |
1 files changed, 108 insertions, 57 deletions
diff --git a/courgette/encoded_program.cc b/courgette/encoded_program.cc index 5169c16..ad41bca 100644 --- a/courgette/encoded_program.cc +++ b/courgette/encoded_program.cc @@ -40,14 +40,15 @@ EncodedProgram::~EncodedProgram() {} // 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 @@ bool ReadVector(std::vector<T, A>* items, SourceStream* buffer) { uint32 item; if (!buffer->ReadVarint32(&item)) return false; + // TODO(tommi): Handle errors. items->push_back(static_cast<T>(item)); } @@ -70,26 +72,29 @@ bool ReadVector(std::vector<T, A>* items, SourceStream* buffer) { // 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): Handle errors. set->reserve(count); uint32 prev = 0; @@ -98,28 +103,31 @@ static bool ReadU32Delta(std::vector<uint32, A>* set, SourceStream* buffer) { if (!buffer->ReadVarint32(&delta)) return false; uint32 current = prev + delta; + // TODO(tommi): handle errors set->push_back(current); prev = current; } + // TODO(tommi): Handle errors. 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 @@ bool ReadVectorU8(std::vector<T, A>* items, SourceStream* buffer) { 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 @@ bool ReadVectorU8(std::vector<T, A>* items, SourceStream* buffer) { //////////////////////////////////////////////////////////////////////////////// -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): Handle errors + return true; } void EncodedProgram::EndLabels() { @@ -181,12 +193,15 @@ void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) { } } -void EncodedProgram::AddOrigin(RVA origin) { +CheckBool EncodedProgram::AddOrigin(RVA origin) { + //TODO(tommi): Handle errors 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): Handle errors const uint8* source = static_cast<const uint8*>(bytes); // Fold adjacent COPY instructions into one. This nearly halves the size of @@ -205,7 +220,7 @@ void EncodedProgram::AddCopy(uint32 count, const void* bytes) { for (uint32 i = 0; i < count; ++i) { copy_bytes_.push_back(source[i]); } - return; + return true; } } @@ -219,20 +234,28 @@ void EncodedProgram::AddCopy(uint32 count, const void* bytes) { copy_bytes_.push_back(source[i]); } } + + return true; } -void EncodedProgram::AddAbs32(int label_index) { +CheckBool EncodedProgram::AddAbs32(int label_index) { + //TODO(tommi): Handle errors 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): Handle errors ops_.push_back(REL32); rel32_ix_.push_back(label_index); + return true; } -void EncodedProgram::AddMakeRelocs() { +CheckBool EncodedProgram::AddMakeRelocs() { + //TODO(tommi): Handle errors ops_.push_back(MAKE_BASE_RELOCATION_TABLE); + return true; } void EncodedProgram::DebuggingSummary() { @@ -279,7 +302,7 @@ static FieldSelect GetFieldSelect() { 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 @@ void EncodedProgram::WriteTo(SinkStreamSet* streams) { 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; + } + } + + bool success = true; + + if (select & INCLUDE_ABS32_ADDRESSES) { + success &= WriteU32Delta(abs32_rva_, + streams->stream(kStreamAbs32Addresses)); + } + + if (select & INCLUDE_REL32_ADDRESSES) { + success &= WriteU32Delta(rel32_rva_, + streams->stream(kStreamRel32Addresses)); } - if (select & INCLUDE_ABS32_ADDRESSES) - WriteU32Delta(abs32_rva_, streams->stream(kStreamAbs32Addresses)); - if (select & INCLUDE_REL32_ADDRESSES) - 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 @@ bool VectorAt(const std::vector<T, A>& v, size_t index, T* output) { 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 @@ bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { 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 @@ bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { 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 @@ bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { 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 @@ bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { 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 @@ bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { } 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 @@ bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { return true; } - // RelocBlock has the layout of a block of relocations in the base relocation // table file format. // @@ -512,39 +557,45 @@ class RelocBlock { 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; } |