summaryrefslogtreecommitdiffstats
path: root/courgette/encoded_program.cc
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-22 20:19:49 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-22 20:19:49 +0000
commitc8240b1c3519b35de243b0fb91af409d59a5808c (patch)
treed7f20f227779c4c32fdd2851037255f1d660673a /courgette/encoded_program.cc
parentd64abe1c12dbe8dab68adee605fa143dc9020f86 (diff)
downloadchromium_src-c8240b1c3519b35de243b0fb91af409d59a5808c.zip
chromium_src-c8240b1c3519b35de243b0fb91af409d59a5808c.tar.gz
chromium_src-c8240b1c3519b35de243b0fb91af409d59a5808c.tar.bz2
Identifying call sites that need to handle out of memory situations in Courgette.
There's no functional change here, only interface changes: * Change methods that are known to fail out in the field to return bool instead of void. * Where those methods are called, check the return value and report errors * In debug builds use a specialized template class that forces callers to check return values (this is possible at compile time in gcc, but unfortunately not in VS). The next step will be to change the implementation to not use STL containers. TEST=Run courgette tests. BUG=74777 Review URL: http://codereview.chromium.org/6716006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79030 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'courgette/encoded_program.cc')
-rw-r--r--courgette/encoded_program.cc165
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;
}