summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc')
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc359
1 files changed, 0 insertions, 359 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc b/toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc
deleted file mode 100644
index 1e783b45c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc
+++ /dev/null
@@ -1,359 +0,0 @@
-// Copyright (c) 2010, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// test_assembler.cc: Implementation of google_breakpad::TestAssembler.
-// See test_assembler.h for details.
-
-#include "common/test_assembler.h"
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <iterator>
-
-namespace google_breakpad {
-namespace test_assembler {
-
-using std::back_insert_iterator;
-
-Label::Label() : value_(new Binding()) { }
-Label::Label(uint64_t value) : value_(new Binding(value)) { }
-Label::Label(const Label &label) {
- value_ = label.value_;
- value_->Acquire();
-}
-Label::~Label() {
- if (value_->Release()) delete value_;
-}
-
-Label &Label::operator=(uint64_t value) {
- value_->Set(NULL, value);
- return *this;
-}
-
-Label &Label::operator=(const Label &label) {
- value_->Set(label.value_, 0);
- return *this;
-}
-
-Label Label::operator+(uint64_t addend) const {
- Label l;
- l.value_->Set(this->value_, addend);
- return l;
-}
-
-Label Label::operator-(uint64_t subtrahend) const {
- Label l;
- l.value_->Set(this->value_, -subtrahend);
- return l;
-}
-
-// When NDEBUG is #defined, assert doesn't evaluate its argument. This
-// means you can't simply use assert to check the return value of a
-// function with necessary side effects.
-//
-// ALWAYS_EVALUATE_AND_ASSERT(x) evaluates x regardless of whether
-// NDEBUG is #defined; when NDEBUG is not #defined, it further asserts
-// that x is true.
-#ifdef NDEBUG
-#define ALWAYS_EVALUATE_AND_ASSERT(x) x
-#else
-#define ALWAYS_EVALUATE_AND_ASSERT(x) assert(x)
-#endif
-
-uint64_t Label::operator-(const Label &label) const {
- uint64_t offset;
- ALWAYS_EVALUATE_AND_ASSERT(IsKnownOffsetFrom(label, &offset));
- return offset;
-}
-
-uint64_t Label::Value() const {
- uint64_t v = 0;
- ALWAYS_EVALUATE_AND_ASSERT(IsKnownConstant(&v));
- return v;
-};
-
-bool Label::IsKnownConstant(uint64_t *value_p) const {
- Binding *base;
- uint64_t addend;
- value_->Get(&base, &addend);
- if (base != NULL) return false;
- if (value_p) *value_p = addend;
- return true;
-}
-
-bool Label::IsKnownOffsetFrom(const Label &label, uint64_t *offset_p) const
-{
- Binding *label_base, *this_base;
- uint64_t label_addend, this_addend;
- label.value_->Get(&label_base, &label_addend);
- value_->Get(&this_base, &this_addend);
- // If this and label are related, Get will find their final
- // common ancestor, regardless of how indirect the relation is. This
- // comparison also handles the constant vs. constant case.
- if (this_base != label_base) return false;
- if (offset_p) *offset_p = this_addend - label_addend;
- return true;
-}
-
-Label::Binding::Binding() : base_(this), addend_(), reference_count_(1) { }
-
-Label::Binding::Binding(uint64_t addend)
- : base_(NULL), addend_(addend), reference_count_(1) { }
-
-Label::Binding::~Binding() {
- assert(reference_count_ == 0);
- if (base_ && base_ != this && base_->Release())
- delete base_;
-}
-
-void Label::Binding::Set(Binding *binding, uint64_t addend) {
- if (!base_ && !binding) {
- // We're equating two constants. This could be okay.
- assert(addend_ == addend);
- } else if (!base_) {
- // We are a known constant, but BINDING may not be, so turn the
- // tables and try to set BINDING's value instead.
- binding->Set(NULL, addend_ - addend);
- } else {
- if (binding) {
- // Find binding's final value. Since the final value is always either
- // completely unconstrained or a constant, never a reference to
- // another variable (otherwise, it wouldn't be final), this
- // guarantees we won't create cycles here, even for code like this:
- // l = m, m = n, n = l;
- uint64_t binding_addend;
- binding->Get(&binding, &binding_addend);
- addend += binding_addend;
- }
-
- // It seems likely that setting a binding to itself is a bug
- // (although I can imagine this might turn out to be helpful to
- // permit).
- assert(binding != this);
-
- if (base_ != this) {
- // Set the other bindings on our chain as well. Note that this
- // is sufficient even though binding relationships form trees:
- // All binding operations traverse their chains to the end, and
- // all bindings related to us share some tail of our chain, so
- // they will see the changes we make here.
- base_->Set(binding, addend - addend_);
- // We're not going to use base_ any more.
- if (base_->Release()) delete base_;
- }
-
- // Adopt BINDING as our base. Note that it should be correct to
- // acquire here, after the release above, even though the usual
- // reference-counting rules call for acquiring first, and then
- // releasing: the self-reference assertion above should have
- // complained if BINDING were 'this' or anywhere along our chain,
- // so we didn't release BINDING.
- if (binding) binding->Acquire();
- base_ = binding;
- addend_ = addend;
- }
-}
-
-void Label::Binding::Get(Binding **base, uint64_t *addend) {
- if (base_ && base_ != this) {
- // Recurse to find the end of our reference chain (the root of our
- // tree), and then rewrite every binding along the chain to refer
- // to it directly, adjusting addends appropriately. (This is why
- // this member function isn't this-const.)
- Binding *final_base;
- uint64_t final_addend;
- base_->Get(&final_base, &final_addend);
- if (final_base) final_base->Acquire();
- if (base_->Release()) delete base_;
- base_ = final_base;
- addend_ += final_addend;
- }
- *base = base_;
- *addend = addend_;
-}
-
-template<typename Inserter>
-static inline void InsertEndian(test_assembler::Endianness endianness,
- size_t size, uint64_t number, Inserter dest) {
- assert(size > 0);
- if (endianness == kLittleEndian) {
- for (size_t i = 0; i < size; i++) {
- *dest++ = (char) (number & 0xff);
- number >>= 8;
- }
- } else {
- assert(endianness == kBigEndian);
- // The loop condition is odd, but it's correct for size_t.
- for (size_t i = size - 1; i < size; i--)
- *dest++ = (char) ((number >> (i * 8)) & 0xff);
- }
-}
-
-Section &Section::Append(Endianness endianness, size_t size, uint64_t number) {
- InsertEndian(endianness, size, number,
- back_insert_iterator<string>(contents_));
- return *this;
-}
-
-Section &Section::Append(Endianness endianness, size_t size,
- const Label &label) {
- // If this label's value is known, there's no reason to waste an
- // entry in references_ on it.
- uint64_t value;
- if (label.IsKnownConstant(&value))
- return Append(endianness, size, value);
-
- // This will get caught when the references are resolved, but it's
- // nicer to find out earlier.
- assert(endianness != kUnsetEndian);
-
- references_.push_back(Reference(contents_.size(), endianness, size, label));
- contents_.append(size, 0);
- return *this;
-}
-
-#define ENDIANNESS_L kLittleEndian
-#define ENDIANNESS_B kBigEndian
-#define ENDIANNESS(e) ENDIANNESS_ ## e
-
-#define DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \
- Section &Section::e ## bits(uint ## bits ## _t v) { \
- InsertEndian(ENDIANNESS(e), bits / 8, v, \
- back_insert_iterator<string>(contents_)); \
- return *this; \
- }
-
-#define DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) \
- Section &Section::e ## bits(const Label &v) { \
- return Append(ENDIANNESS(e), bits / 8, v); \
- }
-
-// Define L16, B32, and friends.
-#define DEFINE_SHORT_APPEND_ENDIAN(e, bits) \
- DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \
- DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits)
-
-DEFINE_SHORT_APPEND_LABEL_ENDIAN(L, 8);
-DEFINE_SHORT_APPEND_LABEL_ENDIAN(B, 8);
-DEFINE_SHORT_APPEND_ENDIAN(L, 16);
-DEFINE_SHORT_APPEND_ENDIAN(L, 32);
-DEFINE_SHORT_APPEND_ENDIAN(L, 64);
-DEFINE_SHORT_APPEND_ENDIAN(B, 16);
-DEFINE_SHORT_APPEND_ENDIAN(B, 32);
-DEFINE_SHORT_APPEND_ENDIAN(B, 64);
-
-#define DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \
- Section &Section::D ## bits(uint ## bits ## _t v) { \
- InsertEndian(endianness_, bits / 8, v, \
- back_insert_iterator<string>(contents_)); \
- return *this; \
- }
-#define DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) \
- Section &Section::D ## bits(const Label &v) { \
- return Append(endianness_, bits / 8, v); \
- }
-#define DEFINE_SHORT_APPEND_DEFAULT(bits) \
- DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \
- DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits)
-
-DEFINE_SHORT_APPEND_LABEL_DEFAULT(8)
-DEFINE_SHORT_APPEND_DEFAULT(16);
-DEFINE_SHORT_APPEND_DEFAULT(32);
-DEFINE_SHORT_APPEND_DEFAULT(64);
-
-Section &Section::Append(const Section &section) {
- size_t base = contents_.size();
- contents_.append(section.contents_);
- for (vector<Reference>::const_iterator it = section.references_.begin();
- it != section.references_.end(); it++)
- references_.push_back(Reference(base + it->offset, it->endianness,
- it->size, it->label));
- return *this;
-}
-
-Section &Section::LEB128(long long value) {
- while (value < -0x40 || 0x3f < value) {
- contents_ += (value & 0x7f) | 0x80;
- if (value < 0)
- value = (value >> 7) | ~(((unsigned long long) -1) >> 7);
- else
- value = (value >> 7);
- }
- contents_ += value & 0x7f;
- return *this;
-}
-
-Section &Section::ULEB128(uint64_t value) {
- while (value > 0x7f) {
- contents_ += (value & 0x7f) | 0x80;
- value = (value >> 7);
- }
- contents_ += value;
- return *this;
-}
-
-Section &Section::Align(size_t alignment, uint8_t pad_byte) {
- // ALIGNMENT must be a power of two.
- assert(((alignment - 1) & alignment) == 0);
- size_t new_size = (contents_.size() + alignment - 1) & ~(alignment - 1);
- contents_.append(new_size - contents_.size(), pad_byte);
- assert((contents_.size() & (alignment - 1)) == 0);
- return *this;
-}
-
-void Section::Clear() {
- contents_.clear();
- references_.clear();
-}
-
-bool Section::GetContents(string *contents) {
- // For each label reference, find the label's value, and patch it into
- // the section's contents.
- for (size_t i = 0; i < references_.size(); i++) {
- Reference &r = references_[i];
- uint64_t value;
- if (!r.label.IsKnownConstant(&value)) {
- fprintf(stderr, "Undefined label #%zu at offset 0x%zx\n", i, r.offset);
- return false;
- }
- assert(r.offset < contents_.size());
- assert(contents_.size() - r.offset >= r.size);
- InsertEndian(r.endianness, r.size, value, contents_.begin() + r.offset);
- }
- contents->clear();
- std::swap(contents_, *contents);
- references_.clear();
- return true;
-}
-
-} // namespace test_assembler
-} // namespace google_breakpad