diff options
Diffstat (limited to 'src/processor')
-rw-r--r-- | src/processor/stackwalker_amd64_unittest.cc | 2 | ||||
-rw-r--r-- | src/processor/stackwalker_arm_unittest.cc | 2 | ||||
-rw-r--r-- | src/processor/stackwalker_x86_unittest.cc | 2 | ||||
-rw-r--r-- | src/processor/synth_minidump.h | 2 | ||||
-rw-r--r-- | src/processor/synth_minidump_unittest.cc | 3 | ||||
-rw-r--r-- | src/processor/test_assembler.cc | 357 | ||||
-rw-r--r-- | src/processor/test_assembler.h | 472 | ||||
-rw-r--r-- | src/processor/test_assembler_unittest.cc | 1644 |
8 files changed, 6 insertions, 2478 deletions
diff --git a/src/processor/stackwalker_amd64_unittest.cc b/src/processor/stackwalker_amd64_unittest.cc index 7b56fb1c..6db04ffc 100644 --- a/src/processor/stackwalker_amd64_unittest.cc +++ b/src/processor/stackwalker_amd64_unittest.cc @@ -36,6 +36,7 @@ #include <vector> #include "breakpad_googletest_includes.h" +#include "common/test_assembler.h" #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" @@ -43,7 +44,6 @@ #include "google_breakpad/processor/stack_frame_cpu.h" #include "processor/stackwalker_unittest_utils.h" #include "processor/stackwalker_amd64.h" -#include "processor/test_assembler.h" using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; diff --git a/src/processor/stackwalker_arm_unittest.cc b/src/processor/stackwalker_arm_unittest.cc index 37103241..036b322c 100644 --- a/src/processor/stackwalker_arm_unittest.cc +++ b/src/processor/stackwalker_arm_unittest.cc @@ -36,6 +36,7 @@ #include <vector> #include "breakpad_googletest_includes.h" +#include "common/test_assembler.h" #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" @@ -43,7 +44,6 @@ #include "google_breakpad/processor/stack_frame_cpu.h" #include "processor/stackwalker_unittest_utils.h" #include "processor/stackwalker_arm.h" -#include "processor/test_assembler.h" #include "processor/windows_frame_info.h" using google_breakpad::BasicSourceLineResolver; diff --git a/src/processor/stackwalker_x86_unittest.cc b/src/processor/stackwalker_x86_unittest.cc index 464b94ed..5af516d4 100644 --- a/src/processor/stackwalker_x86_unittest.cc +++ b/src/processor/stackwalker_x86_unittest.cc @@ -35,6 +35,7 @@ #include <vector> #include "breakpad_googletest_includes.h" +#include "common/test_assembler.h" #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" @@ -42,7 +43,6 @@ #include "google_breakpad/processor/stack_frame_cpu.h" #include "processor/stackwalker_unittest_utils.h" #include "processor/stackwalker_x86.h" -#include "processor/test_assembler.h" #include "processor/windows_frame_info.h" using google_breakpad::BasicSourceLineResolver; diff --git a/src/processor/synth_minidump.h b/src/processor/synth_minidump.h index 28677805..690ec399 100644 --- a/src/processor/synth_minidump.h +++ b/src/processor/synth_minidump.h @@ -112,9 +112,9 @@ #include <iostream> #include <string> +#include "common/test_assembler.h" #include "google_breakpad/common/breakpad_types.h" #include "google_breakpad/common/minidump_format.h" -#include "processor/test_assembler.h" namespace google_breakpad { diff --git a/src/processor/synth_minidump_unittest.cc b/src/processor/synth_minidump_unittest.cc index 755468d5..888053bd 100644 --- a/src/processor/synth_minidump_unittest.cc +++ b/src/processor/synth_minidump_unittest.cc @@ -29,7 +29,8 @@ // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> -// test_assembler_unittest.cc: Unit tests for google_breakpad::TestAssembler. +// synth_minidump_unittest.cc: Unit tests for google_breakpad::SynthMinidump +// classes. #include <sstream> #include <string> diff --git a/src/processor/test_assembler.cc b/src/processor/test_assembler.cc deleted file mode 100644 index 5a36166a..00000000 --- a/src/processor/test_assembler.cc +++ /dev/null @@ -1,357 +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 <cassert> -#include <cstdio> -#include <iterator> - -#include "processor/test_assembler.h" - -namespace google_breakpad { -namespace TestAssembler { - -using std::back_insert_iterator; - -Label::Label() : value_(new Binding()) { } -Label::Label(u_int64_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=(u_int64_t value) { - value_->Set(NULL, value); - return *this; -} - -Label &Label::operator=(const Label &label) { - value_->Set(label.value_, 0); - return *this; -} - -Label Label::operator+(u_int64_t addend) const { - Label l; - l.value_->Set(this->value_, addend); - return l; -} - -Label Label::operator-(u_int64_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 - -u_int64_t Label::operator-(const Label &label) const { - u_int64_t offset; - ALWAYS_EVALUATE_AND_ASSERT(IsKnownOffsetFrom(label, &offset)); - return offset; -} - -u_int64_t Label::Value() const { - u_int64_t v; - ALWAYS_EVALUATE_AND_ASSERT(IsKnownConstant(&v)); - return v; -}; - -bool Label::IsKnownConstant(u_int64_t *value_p) const { - Binding *base; - u_int64_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, u_int64_t *offset_p) const -{ - Binding *label_base, *this_base; - u_int64_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(u_int64_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, u_int64_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; - u_int64_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, u_int64_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; - u_int64_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(TestAssembler::Endianness endianness, - size_t size, u_int64_t number, Inserter dest) { - 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, u_int64_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. - u_int64_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(u_int ## 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(u_int ## 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 §ion) { - 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(u_int64_t value) { - while (value > 0x7f) { - contents_ += (value & 0x7f) | 0x80; - value = (value >> 7); - } - contents_ += value; - return *this; -} - -Section &Section::Align(size_t alignment, u_int8_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]; - u_int64_t value; - if (!r.label.IsKnownConstant(&value)) { - fprintf(stderr, "Undefined label #%d at offset 0x%x\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 TestAssembler -} // namespace google_breakpad diff --git a/src/processor/test_assembler.h b/src/processor/test_assembler.h deleted file mode 100644 index 560f7aef..00000000 --- a/src/processor/test_assembler.h +++ /dev/null @@ -1,472 +0,0 @@ -// -*- mode: C++ -*- - -// 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.h: interface to class for building complex binary streams. - -// To test the Breakpad symbol dumper and processor thoroughly, for -// all combinations of host system and minidump processor -// architecture, we need to be able to easily generate complex test -// data like debugging information and minidump files. -// -// For example, if we want our unit tests to provide full code -// coverage for stack walking, it may be difficult to persuade the -// compiler to generate every possible sort of stack walking -// information that we want to support; there are probably DWARF CFI -// opcodes that GCC never emits. Similarly, if we want to test our -// error handling, we will need to generate damaged minidumps or -// debugging information that (we hope) the client or compiler will -// never produce on its own. -// -// google_breakpad::TestAssembler provides a predictable and -// (relatively) simple way to generate complex formatted data streams -// like minidumps and CFI. Furthermore, because TestAssembler is -// portable, developers without access to (say) Visual Studio or a -// SPARC assembler can still work on test data for those targets. - -#ifndef PROCESSOR_TEST_ASSEMBLER_H_ -#define PROCESSOR_TEST_ASSEMBLER_H_ - -#include <list> -#include <vector> -#include <string> - -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -using std::list; -using std::string; -using std::vector; - -namespace TestAssembler { - -// A Label represents a value not yet known that we need to store in a -// section. As long as all the labels a section refers to are defined -// by the time we retrieve its contents as bytes, we can use undefined -// labels freely in that section's construction. -// -// A label can be in one of three states: -// - undefined, -// - defined as the sum of some other label and a constant, or -// - a constant. -// -// A label's value never changes, but it can accumulate constraints. -// Adding labels and integers is permitted, and yields a label. -// Subtracting a constant from a label is permitted, and also yields a -// label. Subtracting two labels that have some relationship to each -// other is permitted, and yields a constant. -// -// For example: -// -// Label a; // a's value is undefined -// Label b; // b's value is undefined -// { -// Label c = a + 4; // okay, even though a's value is unknown -// b = c + 4; // also okay; b is now a+8 -// } -// Label d = b - 2; // okay; d == a+6, even though c is gone -// d.Value(); // error: d's value is not yet known -// d - a; // is 6, even though their values are not known -// a = 12; // now b == 20, and d == 18 -// d.Value(); // 18: no longer an error -// b.Value(); // 20 -// d = 10; // error: d is already defined. -// -// Label objects' lifetimes are unconstrained: notice that, in the -// above example, even though a and b are only related through c, and -// c goes out of scope, the assignment to a sets b's value as well. In -// particular, it's not necessary to ensure that a Label lives beyond -// Sections that refer to it. -class Label { - public: - Label(); // An undefined label. - Label(u_int64_t value); // A label with a fixed value - Label(const Label &value); // A label equal to another. - ~Label(); - - // Return this label's value; it must be known. - // - // Providing this as a cast operator is nifty, but the conversions - // happen in unexpected places. In particular, ISO C++ says that - // Label + size_t becomes ambigious, because it can't decide whether - // to convert the Label to a u_int64_t and then to a size_t, or use - // the overloaded operator that returns a new label, even though the - // former could fail if the label is not yet defined and the latter won't. - u_int64_t Value() const; - - Label &operator=(u_int64_t value); - Label &operator=(const Label &value); - Label operator+(u_int64_t addend) const; - Label operator-(u_int64_t subtrahend) const; - u_int64_t operator-(const Label &subtrahend) const; - - // We could also provide == and != that work on undefined, but - // related, labels. - - // Return true if this label's value is known. If VALUE_P is given, - // set *VALUE_P to the known value if returning true. - bool IsKnownConstant(u_int64_t *value_p = NULL) const; - - // Return true if the offset from LABEL to this label is known. If - // OFFSET_P is given, set *OFFSET_P to the offset when returning true. - // - // You can think of l.KnownOffsetFrom(m, &d) as being like 'd = l-m', - // except that it also returns a value indicating whether the - // subtraction is possible given what we currently know of l and m. - // It can be possible even if we don't know l and m's values. For - // example: - // - // Label l, m; - // m = l + 10; - // l.IsKnownConstant(); // false - // m.IsKnownConstant(); // false - // u_int64_t d; - // l.IsKnownOffsetFrom(m, &d); // true, and sets d to -10. - // l-m // -10 - // m-l // 10 - // m.Value() // error: m's value is not known - bool IsKnownOffsetFrom(const Label &label, u_int64_t *offset_p = NULL) const; - - private: - // A label's value, or if that is not yet known, how the value is - // related to other labels' values. A binding may be: - // - a known constant, - // - constrained to be equal to some other binding plus a constant, or - // - unconstrained, and free to take on any value. - // - // Many labels may point to a single binding, and each binding may - // refer to another, so bindings and labels form trees whose leaves - // are labels, whose interior nodes (and roots) are bindings, and - // where links point from children to parents. Bindings are - // reference counted, allowing labels to be lightweight, copyable, - // assignable, placed in containers, and so on. - class Binding { - public: - Binding(); - Binding(u_int64_t addend); - ~Binding(); - - // Increment our reference count. - void Acquire() { reference_count_++; }; - // Decrement our reference count, and return true if it is zero. - bool Release() { return --reference_count_ == 0; } - - // Set this binding to be equal to BINDING + ADDEND. If BINDING is - // NULL, then set this binding to the known constant ADDEND. - // Update every binding on this binding's chain to point directly - // to BINDING, or to be a constant, with addends adjusted - // appropriately. - void Set(Binding *binding, u_int64_t value); - - // Return what we know about the value of this binding. - // - If this binding's value is a known constant, set BASE to - // NULL, and set ADDEND to its value. - // - If this binding is not a known constant but related to other - // bindings, set BASE to the binding at the end of the relation - // chain (which will always be unconstrained), and set ADDEND to the - // value to add to that binding's value to get this binding's - // value. - // - If this binding is unconstrained, set BASE to this, and leave - // ADDEND unchanged. - void Get(Binding **base, u_int64_t *addend); - - private: - // There are three cases: - // - // - A binding representing a known constant value has base_ NULL, - // and addend_ equal to the value. - // - // - A binding representing a completely unconstrained value has - // base_ pointing to this; addend_ is unused. - // - // - A binding whose value is related to some other binding's - // value has base_ pointing to that other binding, and addend_ - // set to the amount to add to that binding's value to get this - // binding's value. We only represent relationships of the form - // x = y+c. - // - // Thus, the bind_ links form a chain terminating in either a - // known constant value or a completely unconstrained value. Most - // operations on bindings do path compression: they change every - // binding on the chain to point directly to the final value, - // adjusting addends as appropriate. - Binding *base_; - u_int64_t addend_; - - // The number of Labels and Bindings pointing to this binding. - // (When a binding points to itself, indicating a completely - // unconstrained binding, that doesn't count as a reference.) - int reference_count_; - }; - - // This label's value. - Binding *value_; -}; - -inline Label operator+(u_int64_t a, const Label &l) { return l + a; } -// Note that int-Label isn't defined, as negating a Label is not an -// operation we support. - -// Conventions for representing larger numbers as sequences of bytes. -enum Endianness { - kBigEndian, // Big-endian: the most significant byte comes first. - kLittleEndian, // Little-endian: the least significant byte comes first. - kUnsetEndian, // used internally -}; - -// A section is a sequence of bytes, constructed by appending bytes -// to the end. Sections have a convenient and flexible set of member -// functions for appending data in various formats: big-endian and -// little-endian signed and unsigned values of different sizes; -// LEB128 and ULEB128 values (see below), and raw blocks of bytes. -// -// If you need to append a value to a section that is not convenient -// to compute immediately, you can create a label, append the -// label's value to the section, and then set the label's value -// later, when it's convenient to do so. Once a label's value is -// known, the section class takes care of updating all previously -// appended references to it. -// -// Once all the labels to which a section refers have had their -// values determined, you can get a copy of the section's contents -// as a string. -// -// Note that there is no specified "start of section" label. This is -// because there are typically several different meanings for "the -// start of a section": the offset of the section within an object -// file, the address in memory at which the section's content appear, -// and so on. It's up to the code that uses the Section class to -// keep track of these explicitly, as they depend on the application. -class Section { - public: - Section(Endianness endianness = kUnsetEndian) - : endianness_(endianness) { }; - ~Section() { }; - - // Set the default endianness of this section to ENDIANNESS. This - // sets the behavior of the D<N> appending functions. If the - // assembler's default endianness was set, this is the - void set_endianness(Endianness endianness) { - endianness_ = endianness; - } - - // Return the default endianness of this section. - Endianness endianness() const { return endianness_; } - - // Append the SIZE bytes at DATA or the contents of STRING to the - // end of this section. Return a reference to this section. - Section &Append(const u_int8_t *data, size_t size) { - contents_.append(reinterpret_cast<const char *>(data), size); - return *this; - }; - Section &Append(const string &data) { - contents_.append(data); - return *this; - }; - - // Append SIZE copies of BYTE to the end of this section. Return a - // reference to this section. - Section &Append(size_t size, u_int8_t byte) { - contents_.append(size, (char) byte); - return *this; - } - - // Append NUMBER to this section. ENDIANNESS is the endianness to - // use to write the number. SIZE is the length of the number in - // bytes. Return a reference to this section. - Section &Append(Endianness endianness, size_t size, u_int64_t number); - Section &Append(Endianness endianness, size_t size, const Label &label); - - // Append SECTION to the end of this section. The labels SECTION - // refers to need not be defined yet. - // - // Note that this has no effect on any Labels' values, or on - // SECTION. If placing SECTION within 'this' provides new - // constraints on existing labels' values, then it's up to the - // caller to fiddle with those labels as needed. - Section &Append(const Section §ion); - - // Append the contents of DATA as a series of bytes terminated by - // a NULL character. - Section &AppendCString(const string &data) { - Append(data); - contents_ += '\0'; - return *this; - } - - // Append VALUE or LABEL to this section, with the given bit width and - // endianness. Return a reference to this section. - // - // The names of these functions have the form <ENDIANNESS><BITWIDTH>: - // <ENDIANNESS> is either 'L' (little-endian, least significant byte first), - // 'B' (big-endian, most significant byte first), or - // 'D' (default, the section's default endianness) - // <BITWIDTH> is 8, 16, 32, or 64. - // - // Since endianness doesn't matter for a single byte, all the - // <BITWIDTH>=8 functions are equivalent. - // - // These can be used to write both signed and unsigned values, as - // the compiler will properly sign-extend a signed value before - // passing it to the function, at which point the function's - // behavior is the same either way. - Section &L8(u_int8_t value) { contents_ += value; return *this; } - Section &B8(u_int8_t value) { contents_ += value; return *this; } - Section &D8(u_int8_t value) { contents_ += value; return *this; } - Section &L16(u_int16_t), &L32(u_int32_t), &L64(u_int64_t), - &B16(u_int16_t), &B32(u_int32_t), &B64(u_int64_t), - &D16(u_int16_t), &D32(u_int32_t), &D64(u_int64_t); - Section &L8(const Label &label), &L16(const Label &label), - &L32(const Label &label), &L64(const Label &label), - &B8(const Label &label), &B16(const Label &label), - &B32(const Label &label), &B64(const Label &label), - &D8(const Label &label), &D16(const Label &label), - &D32(const Label &label), &D64(const Label &label); - - // Append VALUE in a signed LEB128 (Little-Endian Base 128) form. - // - // The signed LEB128 representation of an integer N is a variable - // number of bytes: - // - // - If N is between -0x40 and 0x3f, then its signed LEB128 - // representation is a single byte whose value is N. - // - // - Otherwise, its signed LEB128 representation is (N & 0x7f) | - // 0x80, followed by the signed LEB128 representation of N / 128, - // rounded towards negative infinity. - // - // In other words, we break VALUE into groups of seven bits, put - // them in little-endian order, and then write them as eight-bit - // bytes with the high bit on all but the last. - // - // Note that VALUE cannot be a Label (we would have to implement - // relaxation). - Section &LEB128(long long value); - - // Append VALUE in unsigned LEB128 (Little-Endian Base 128) form. - // - // The unsigned LEB128 representation of an integer N is a variable - // number of bytes: - // - // - If N is between 0 and 0x7f, then its unsigned LEB128 - // representation is a single byte whose value is N. - // - // - Otherwise, its unsigned LEB128 representation is (N & 0x7f) | - // 0x80, followed by the unsigned LEB128 representation of N / - // 128, rounded towards negative infinity. - // - // Note that VALUE cannot be a Label (we would have to implement - // relaxation). - Section &ULEB128(u_int64_t value); - - // Jump to the next location aligned on an ALIGNMENT-byte boundary, - // relative to the start of the section. Fill the gap with PAD_BYTE. - // ALIGNMENT must be a power of two. Return a reference to this - // section. - Section &Align(size_t alignment, u_int8_t pad_byte = 0); - - // Clear the contents of this section. - void Clear(); - - // Return the current size of the section. - size_t Size() const { return contents_.size(); } - - // Return a label representing the start of the section. - // - // It is up to the user whether this label represents the section's - // position in an object file, the section's address in memory, or - // what have you; some applications may need both, in which case - // this simple-minded interface won't be enough. This class only - // provides a single start label, for use with the Here and Mark - // member functions. - // - // Ideally, we'd provide this in a subclass that actually knows more - // about the application at hand and can provide an appropriate - // collection of start labels. But then the appending member - // functions like Append and D32 would return a reference to the - // base class, not the derived class, and the chaining won't work. - // Since the only value here is in pretty notation, that's a fatal - // flaw. - Label start() const { return start_; } - - // Return a label representing the point at which the next Appended - // item will appear in the section, relative to start(). - Label Here() const { return start_ + Size(); } - - // Set *LABEL to Here, and return a reference to this section. - Section &Mark(Label *label) { *label = Here(); return *this; } - - // If there are no undefined label references left in this - // section, set CONTENTS to the contents of this section, as a - // string, and clear this section. Return true on success, or false - // if there were still undefined labels. - bool GetContents(string *contents); - - private: - // Used internally. A reference to a label's value. - struct Reference { - Reference(size_t set_offset, Endianness set_endianness, size_t set_size, - const Label &set_label) - : offset(set_offset), endianness(set_endianness), size(set_size), - label(set_label) { } - - // The offset of the reference within the section. - size_t offset; - - // The endianness of the reference. - Endianness endianness; - - // The size of the reference. - size_t size; - - // The label to which this is a reference. - Label label; - }; - - // The default endianness of this section. - Endianness endianness_; - - // The contents of the section. - string contents_; - - // References to labels within those contents. - vector<Reference> references_; - - // A label referring to the beginning of the section. - Label start_; -}; - -} // namespace TestAssembler -} // namespace google_breakpad - -#endif // PROCESSOR_TEST_ASSEMBLER_H_ diff --git a/src/processor/test_assembler_unittest.cc b/src/processor/test_assembler_unittest.cc deleted file mode 100644 index 97009605..00000000 --- a/src/processor/test_assembler_unittest.cc +++ /dev/null @@ -1,1644 +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_unittest.cc: Unit tests for google_breakpad::TestAssembler. - -#include <string> -#include <string.h> - -#include "breakpad_googletest_includes.h" -#include "processor/test_assembler.h" - -using google_breakpad::TestAssembler::Label; -using google_breakpad::TestAssembler::Section; -using google_breakpad::TestAssembler::kBigEndian; -using google_breakpad::TestAssembler::kLittleEndian; -using std::string; -using testing::Test; - -TEST(ConstructLabel, Simple) { - Label l; -} - -TEST(ConstructLabel, Undefined) { - Label l; - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(ConstructLabelDeathTest, Undefined) { - Label l; - ASSERT_DEATH(l.Value(), "IsKnownConstant\\(&v\\)"); -} - -TEST(ConstructLabel, Constant) { - Label l(0x060b9f974eaf301eULL); - u_int64_t v; - EXPECT_TRUE(l.IsKnownConstant(&v)); - EXPECT_EQ(v, 0x060b9f974eaf301eULL); - EXPECT_EQ(l.Value(), 0x060b9f974eaf301eULL); -} - -TEST(ConstructLabel, Copy) { - Label l; - Label m(l); - u_int64_t v; - EXPECT_TRUE(l.IsKnownOffsetFrom(m, &v)); - EXPECT_EQ(0U, v); -} - -// The left-hand-side of a label assignment can be either -// unconstrained, related, or known. The right-hand-side can be any of -// those, or an integer. -TEST(Assignment, UnconstrainedToUnconstrained) { - Label l, m; - l = m; - EXPECT_EQ(0U, l-m); - EXPECT_TRUE(l.IsKnownOffsetFrom(m)); - u_int64_t d; - EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); - EXPECT_EQ(0U, d); - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(Assignment, UnconstrainedToRelated) { - Label l, m, n; - l = n; - l = m; - EXPECT_EQ(0U, l-m); - EXPECT_TRUE(l.IsKnownOffsetFrom(m)); - u_int64_t d; - EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); - EXPECT_EQ(0U, d); - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(Assignment, UnconstrainedToKnown) { - Label l, m; - l = 0x8fd16e55b20a39c1ULL; - l = m; - EXPECT_EQ(0U, l-m); - EXPECT_TRUE(l.IsKnownOffsetFrom(m)); - u_int64_t d; - EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); - EXPECT_EQ(0U, d); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x8fd16e55b20a39c1ULL, m.Value()); -} - -TEST(Assignment, RelatedToUnconstrained) { - Label l, m, n; - m = n; - l = m; - EXPECT_EQ(0U, l-n); - EXPECT_TRUE(l.IsKnownOffsetFrom(n)); - u_int64_t d; - EXPECT_TRUE(l.IsKnownOffsetFrom(n, &d)); - EXPECT_EQ(0U, d); - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(Assignment, RelatedToRelated) { - Label l, m, n, o; - l = n; - m = o; - l = m; - EXPECT_EQ(0U, n-o); - EXPECT_TRUE(n.IsKnownOffsetFrom(o)); - u_int64_t d; - EXPECT_TRUE(n.IsKnownOffsetFrom(o, &d)); - EXPECT_EQ(0U, d); - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(Assignment, RelatedToKnown) { - Label l, m, n; - m = n; - l = 0xd2011f8c82ad56f2ULL; - l = m; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0xd2011f8c82ad56f2ULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0xd2011f8c82ad56f2ULL, m.Value()); - EXPECT_TRUE(n.IsKnownConstant()); - EXPECT_EQ(0xd2011f8c82ad56f2ULL, n.Value()); -} - -TEST(Assignment, KnownToUnconstrained) { - Label l, m; - m = 0x50b024c0d6073887ULL; - l = m; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0x50b024c0d6073887ULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x50b024c0d6073887ULL, m.Value()); -} - -TEST(Assignment, KnownToRelated) { - Label l, m, n; - l = n; - m = 0x5348883655c727e5ULL; - l = m; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0x5348883655c727e5ULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x5348883655c727e5ULL, m.Value()); - EXPECT_TRUE(n.IsKnownConstant()); - EXPECT_EQ(0x5348883655c727e5ULL, n.Value()); -} - -TEST(Assignment, KnownToKnown) { - Label l, m; - l = 0x36c209c20987564eULL; - m = 0x36c209c20987564eULL; - l = m; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0x36c209c20987564eULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x36c209c20987564eULL, m.Value()); -} - -TEST(Assignment, ConstantToUnconstrained) { - Label l; - l = 0xc02495f4d7f5a957ULL; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0xc02495f4d7f5a957ULL, l.Value()); -} - -TEST(Assignment, ConstantToRelated) { - Label l, m; - l = m; - l = 0x4577901cf275488dULL; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0x4577901cf275488dULL, l.Value()); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x4577901cf275488dULL, m.Value()); -} - -TEST(Assignment, ConstantToKnown) { - Label l; - l = 0xec0b9c369b7e8ea7ULL; - l = 0xec0b9c369b7e8ea7ULL; - EXPECT_TRUE(l.IsKnownConstant()); - EXPECT_EQ(0xec0b9c369b7e8ea7ULL, l.Value()); -} - -TEST(AssignmentDeathTest, Self) { - Label l; - ASSERT_DEATH(l = l, "binding != this"); -} - -TEST(AssignmentDeathTest, IndirectCycle) { - Label l, m, n; - l = m; - m = n; - ASSERT_DEATH(n = l, "binding != this"); -} - -TEST(AssignmentDeathTest, Cycle) { - Label l, m, n, o; - l = m; - m = n; - o = n; - ASSERT_DEATH(o = l, "binding != this"); -} - -TEST(Addition, LabelConstant) { - Label l, m; - m = l + 0x5248d93e8bbe9497ULL; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - u_int64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(0x5248d93e8bbe9497ULL, d); - EXPECT_FALSE(m.IsKnownConstant()); -} - -TEST(Addition, ConstantLabel) { - Label l, m; - m = 0xf51e94e00d6e3c84ULL + l; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - u_int64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(0xf51e94e00d6e3c84ULL, d); - EXPECT_FALSE(m.IsKnownConstant()); -} - -TEST(Addition, KnownLabelConstant) { - Label l, m; - l = 0x16286307042ce0d8ULL; - m = l + 0x3fdddd91306719d7ULL; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - u_int64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(0x3fdddd91306719d7ULL, d); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x16286307042ce0d8ULL + 0x3fdddd91306719d7ULL, m.Value()); -} - -TEST(Addition, ConstantKnownLabel) { - Label l, m; - l = 0x50f62d0cdd1031deULL; - m = 0x1b13462d8577c538ULL + l; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - u_int64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(0x1b13462d8577c538ULL, d); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x50f62d0cdd1031deULL + 0x1b13462d8577c538ULL, m.Value()); -} - -TEST(Subtraction, LabelConstant) { - Label l, m; - m = l - 0x0620884d21d3138eULL; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - u_int64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(-0x0620884d21d3138eULL, d); - EXPECT_FALSE(m.IsKnownConstant()); -} - -TEST(Subtraction, KnownLabelConstant) { - Label l, m; - l = 0x6237fbaf9ef7929eULL; - m = l - 0x317730995d2ab6eeULL; - EXPECT_TRUE(m.IsKnownOffsetFrom(l)); - u_int64_t d; - EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); - EXPECT_EQ(-0x317730995d2ab6eeULL, d); - EXPECT_TRUE(m.IsKnownConstant()); - EXPECT_EQ(0x6237fbaf9ef7929eULL - 0x317730995d2ab6eeULL, m.Value()); -} - -TEST(SubtractionDeathTest, LabelLabel) { - Label l, m; - ASSERT_DEATH(l - m, "IsKnownOffsetFrom\\(label, &offset\\)"); -} - -TEST(Subtraction, LabelLabel) { - Label l, m; - l = m + 0x7fa77ec63e28a17aULL; - EXPECT_EQ(0x7fa77ec63e28a17aULL, l - m); - EXPECT_EQ(-0x7fa77ec63e28a17aULL, m - l); -} - -TEST(IsKnownConstant, Undefined) { - Label l; - EXPECT_FALSE(l.IsKnownConstant()); -} - -TEST(IsKnownConstant, RelatedLabel) { - Label l, m; - l = m; - EXPECT_FALSE(l.IsKnownConstant()); - EXPECT_FALSE(m.IsKnownConstant()); -} - -TEST(IsKnownConstant, Constant) { - Label l; - l = 0xf374b1bdd6a22576ULL; - EXPECT_TRUE(l.IsKnownConstant()); -} - -TEST(IsKnownOffsetFrom, Unrelated) { - Label l, m; - EXPECT_FALSE(l.IsKnownOffsetFrom(m)); -} - -TEST(IsKnownOffsetFrom, Related) { - Label l, m; - l = m; - EXPECT_TRUE(l.IsKnownOffsetFrom(m)); -} - -// Test the construction of chains of related labels, and the -// propagation of values through them. -// -// Although the relations between labels are supposed to behave -// symmetrically --- that is, 'a = b' should put a and b in -// indistinguishable states --- there's a distinction made internally -// between the target (a) and the source (b). -// -// So there are five test axes to cover: -// -// - Do we construct the chain with assignment ("Assign") or with constructors -// ("Construct")? -// -// - Do we set the value of the label at the start of the chain -// ("Start") or the label at the end ("End")? -// -// - Are we testing the propagation of a relationship between variable -// values ("Relation"), or the propagation of a known constant value -// ("Value")? -// -// - Do we set the value before building the chain ("Before") or after -// the chain has been built ("After")? -// -// - Do we add new relationships to the end of the existing chain -// ("Forward") or to the beginning ("Backward")? -// -// Of course, "Construct" and "Backward" can't be combined, which -// eliminates eight combinations, and "Construct", "End", and "Before" -// can't be combined, which eliminates two more, so there are are 22 -// combinations, not 32. - -TEST(LabelChain, AssignStartRelationBeforeForward) { - Label a, b, c, d; - Label x; - a = x; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, AssignStartRelationBeforeBackward) { - Label a, b, c, d; - Label x; - a = x; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, AssignStartRelationAfterForward) { - Label a, b, c, d; - Label x; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - a = x; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, AssignStartRelationAfterBackward) { - Label a, b, c, d; - Label x; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - a = x; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, AssignStartValueBeforeForward) { - Label a, b, c, d; - a = 0xa131200190546ac2ULL; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - EXPECT_EQ(0xa131200190546ac2ULL + 0x111U, d.Value()); - EXPECT_EQ(0xa131200190546ac2ULL + 0x11U, c.Value()); - EXPECT_EQ(0xa131200190546ac2ULL + 0x1U, b.Value()); - EXPECT_EQ(0xa131200190546ac2ULL + 0U, a.Value()); -} - -TEST(LabelChain, AssignStartValueBeforeBackward) { - Label a, b, c, d; - a = 0x8da17e1670ad4fa2ULL; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x111U, d.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x11U, c.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x1U, b.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0U, a.Value()); -} - -TEST(LabelChain, AssignStartValueAfterForward) { - Label a, b, c, d; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - a = 0x99b8f51bafd41adaULL; - EXPECT_EQ(0x99b8f51bafd41adaULL + 0x111U, d.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL + 0x11U, c.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL + 0x1U, b.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL + 0U, a.Value()); -} - -TEST(LabelChain, AssignStartValueAfterBackward) { - Label a, b, c, d; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - a = 0xc86ca1d97ab5df6eULL; - EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x111U, d.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x11U, c.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x1U, b.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0U, a.Value()); -} - -TEST(LabelChain, AssignEndRelationBeforeForward) { - Label a, b, c, d; - Label x; - x = d; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - EXPECT_EQ(-(u_int64_t)0x111U, a-x); - EXPECT_EQ(-(u_int64_t)0x110U, b-x); - EXPECT_EQ(-(u_int64_t)0x100U, c-x); - EXPECT_EQ(-(u_int64_t)0U, d-x); -} - -TEST(LabelChain, AssignEndRelationBeforeBackward) { - Label a, b, c, d; - Label x; - x = d; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - EXPECT_EQ(-(u_int64_t)0x111U, a-x); - EXPECT_EQ(-(u_int64_t)0x110U, b-x); - EXPECT_EQ(-(u_int64_t)0x100U, c-x); - EXPECT_EQ(-(u_int64_t)0U, d-x); -} - -TEST(LabelChain, AssignEndRelationAfterForward) { - Label a, b, c, d; - Label x; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - x = d; - EXPECT_EQ(-(u_int64_t)0x111U, a-x); - EXPECT_EQ(-(u_int64_t)0x110U, b-x); - EXPECT_EQ(-(u_int64_t)0x100U, c-x); - EXPECT_EQ(-(u_int64_t)0x000U, d-x); -} - -TEST(LabelChain, AssignEndRelationAfterBackward) { - Label a, b, c, d; - Label x; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - x = d; - EXPECT_EQ(-(u_int64_t)0x111U, a-x); - EXPECT_EQ(-(u_int64_t)0x110U, b-x); - EXPECT_EQ(-(u_int64_t)0x100U, c-x); - EXPECT_EQ(-(u_int64_t)0x000U, d-x); -} - -TEST(LabelChain, AssignEndValueBeforeForward) { - Label a, b, c, d; - d = 0xa131200190546ac2ULL; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - EXPECT_EQ(0xa131200190546ac2ULL - 0x111, a.Value()); - EXPECT_EQ(0xa131200190546ac2ULL - 0x110, b.Value()); - EXPECT_EQ(0xa131200190546ac2ULL - 0x100, c.Value()); - EXPECT_EQ(0xa131200190546ac2ULL - 0x000, d.Value()); -} - -TEST(LabelChain, AssignEndValueBeforeBackward) { - Label a, b, c, d; - d = 0x8da17e1670ad4fa2ULL; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x111, a.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x110, b.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x100, c.Value()); - EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x000, d.Value()); -} - -TEST(LabelChain, AssignEndValueAfterForward) { - Label a, b, c, d; - b = a + 0x1; - c = b + 0x10; - d = c + 0x100; - d = 0x99b8f51bafd41adaULL; - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x111, a.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x110, b.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x100, c.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x000, d.Value()); -} - -TEST(LabelChain, AssignEndValueAfterBackward) { - Label a, b, c, d; - d = c + 0x100; - c = b + 0x10; - b = a + 0x1; - d = 0xc86ca1d97ab5df6eULL; - EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x111, a.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x110, b.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x100, c.Value()); - EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x000, d.Value()); -} - -TEST(LabelChain, ConstructStartRelationBeforeForward) { - Label x; - Label a(x); - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, ConstructStartRelationAfterForward) { - Label x; - Label a; - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - a = x; - EXPECT_EQ(0x111U, d-x); - EXPECT_EQ(0x11U, c-x); - EXPECT_EQ(0x1U, b-x); - EXPECT_EQ(0U, a-x); -} - -TEST(LabelChain, ConstructStartValueBeforeForward) { - Label a(0x5d234d177d01ccc8ULL); - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x111U, d.Value()); - EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x011U, c.Value()); - EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x001U, b.Value()); - EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x000U, a.Value()); -} - -TEST(LabelChain, ConstructStartValueAfterForward) { - Label a; - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - a = 0xded85d54586e84fcULL; - EXPECT_EQ(0xded85d54586e84fcULL + 0x111U, d.Value()); - EXPECT_EQ(0xded85d54586e84fcULL + 0x011U, c.Value()); - EXPECT_EQ(0xded85d54586e84fcULL + 0x001U, b.Value()); - EXPECT_EQ(0xded85d54586e84fcULL + 0x000U, a.Value()); -} - -TEST(LabelChain, ConstructEndRelationAfterForward) { - Label x; - Label a; - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - x = d; - EXPECT_EQ(-(u_int64_t)0x111U, a-x); - EXPECT_EQ(-(u_int64_t)0x110U, b-x); - EXPECT_EQ(-(u_int64_t)0x100U, c-x); - EXPECT_EQ(-(u_int64_t)0x000U, d-x); -} - -TEST(LabelChain, ConstructEndValueAfterForward) { - Label a; - Label b(a + 0x1); - Label c(b + 0x10); - Label d(c + 0x100); - d = 0x99b8f51bafd41adaULL; - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x111, a.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x110, b.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x100, c.Value()); - EXPECT_EQ(0x99b8f51bafd41adaULL - 0x000, d.Value()); -} - -TEST(LabelTree, KnownValue) { - Label l, m, n, o, p; - l = m; - m = n; - o = p; - p = n; - l = 0x536b5de3d468a1b5ULL; - EXPECT_EQ(0x536b5de3d468a1b5ULL, o.Value()); -} - -TEST(LabelTree, Related) { - Label l, m, n, o, p; - l = m - 1; - m = n - 10; - o = p + 100; - p = n + 1000; - EXPECT_EQ(1111U, o - l); -} - -TEST(EquationDeathTest, EqualConstants) { - Label m = 0x0d3962f280f07d24ULL; - Label n = 0x0d3962f280f07d24ULL; - m = n; // no death expected -} - -TEST(EquationDeathTest, EqualIndirectConstants) { - Label m = 0xa347f1e5238fe6a1ULL; - Label n; - Label o = n; - n = 0xa347f1e5238fe6a1ULL; - n = m; // no death expected -} - -TEST(EquationDeathTest, ConstantClash) { - Label m = 0xd4cc0f4f630ec741ULL; - Label n = 0x934cd2d8254fc3eaULL; - ASSERT_DEATH(m = n, "addend_ == addend"); -} - -TEST(EquationDeathTest, IndirectConstantClash) { - Label m = 0xd4cc0f4f630ec741ULL; - Label n, o; - n = o; - o = 0xcfbe3b83ac49ce86ULL; - ASSERT_DEATH(m = n, "addend_ == addend"); -} - -// Assigning to a related label may free the next Binding on its -// chain. This test always passes; it is interesting to memory -// checkers and coverage analysis. -TEST(LabelReferenceCount, AssignmentFree) { - Label l; - { - Label m; - l = m; - } - // This should free m's Binding. - l = 0xca8bae92f0376d4fULL; - ASSERT_EQ(0xca8bae92f0376d4fULL, l.Value()); -} - -// Finding the value of a label may free the Binding it refers to. This test -// always passes; it is interesting to memory checkers and coverage analysis. -TEST(LabelReferenceCount, FindValueFree) { - Label l; - { - Label m, n; - l = m; - m = n; - n = 0x7a0b0c576672daafULL; - // At this point, l's Binding refers to m's Binding, which refers - // to n's binding. - } - // Now, l is the only reference keeping the three Bindings alive. - // Resolving its value should free l's and m's original bindings. - ASSERT_EQ(0x7a0b0c576672daafULL, l.Value()); -} - -TEST(ConstructSection, Simple) { - Section s; -} - -TEST(ConstructSection, WithEndian) { - Section s(kBigEndian); -} - -// A fixture class for TestAssembler::Section tests. -class SectionFixture { - public: - Section section; - string contents; - static const u_int8_t data[]; - static const size_t data_size; -}; - -const u_int8_t SectionFixture::data[] = { - 0x87, 0x4f, 0x43, 0x67, 0x30, 0xd0, 0xd4, 0x0e -}; - -#define I0() -#define I1(a) { a } -#define I2(a,b) { a,b } -#define I3(a,b,c) { a,b,c } -#define I4(a,b,c,d) { a,b,c,d } -#define I5(a,b,c,d,e) { a,b,c,d,e } -#define I6(a,b,c,d,e,f) { a,b,c,d,e,f } -#define I7(a,b,c,d,e,f,g) { a,b,c,d,e,f,g } -#define I8(a,b,c,d,e,f,g,h) { a,b,c,d,e,f,g,h } -#define I9(a,b,c,d,e,f,g,h,i) { a,b,c,d,e,f,g,h,i } -#define ASSERT_BYTES(s, b) \ - do \ - { \ - static const u_int8_t expected_bytes[] = b; \ - ASSERT_EQ(sizeof(expected_bytes), s.size()); \ - ASSERT_TRUE(memcmp(s.data(), (const char *) expected_bytes, \ - sizeof(expected_bytes)) == 0); \ - } \ - while(0) - -class Append: public SectionFixture, public Test { }; - -TEST_F(Append, Bytes) { - section.Append(data, sizeof(data)); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_EQ(sizeof(data), contents.size()); - EXPECT_TRUE(0 == memcmp(contents.data(), (const char *) data, sizeof(data))); -} - -TEST_F(Append, BytesTwice) { - section.Append(data, sizeof(data)); - section.Append(data, sizeof(data)); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_EQ(2 * sizeof(data), contents.size()); - ASSERT_TRUE(0 == memcmp(contents.data(), (const char *) data, sizeof(data))); - ASSERT_TRUE(0 == memcmp(contents.data() + sizeof(data), - (const char *) data, sizeof(data))); -} - -TEST_F(Append, String) { - string s1 = "howdy "; - string s2 = "there"; - section.Append(s1); - section.Append(s2); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_STREQ(contents.c_str(), "howdy there"); -} - -TEST_F(Append, RepeatedBytes) { - section.Append((size_t) 10, '*'); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_STREQ(contents.c_str(), "**********"); -} - -TEST_F(Append, GeneralLE1) { - section.Append(kLittleEndian, 1, 42); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(42)); -} - -TEST_F(Append, GeneralLE2) { - section.Append(kLittleEndian, 2, 0x15a1); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0xa1, 0x15)); -} - -TEST_F(Append, GeneralLE3) { - section.Append(kLittleEndian, 3, 0x59ae8d); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x8d, 0xae, 0x59)); -} - -TEST_F(Append, GeneralLE4) { - section.Append(kLittleEndian, 4, 0x51603c56); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I4(0x56, 0x3c, 0x60, 0x51)); -} - -TEST_F(Append, GeneralLE5) { - section.Append(kLittleEndian, 5, 0x385e2803b4ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0xb4, 0x03, 0x28, 0x5e, 0x38)); -} - -TEST_F(Append, GeneralLE6) { - section.Append(kLittleEndian, 6, 0xc7db9534dd1fULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I6(0x1f, 0xdd, 0x34, 0x95, 0xdb, 0xc7)); -} - -TEST_F(Append, GeneralLE7) { - section.Append(kLittleEndian, 7, 0x1445c9f1b843e6ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I7(0xe6, 0x43, 0xb8, 0xf1, 0xc9, 0x45, 0x14)); -} - -TEST_F(Append, GeneralLE8) { - section.Append(kLittleEndian, 8, 0xaf48019dfe5c01e5ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I8(0xe5, 0x01, 0x5c, 0xfe, 0x9d, 0x01, 0x48, 0xaf)); -} - -TEST_F(Append, GeneralBE1) { - section.Append(kBigEndian, 1, 0xd0ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(0xd0)); -} - -TEST_F(Append, GeneralBE2) { - section.Append(kBigEndian, 2, 0x2e7eULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2e, 0x7e)); -} - -TEST_F(Append, GeneralBE3) { - section.Append(kBigEndian, 3, 0x37dad6ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x37, 0xda, 0xd6)); -} - -TEST_F(Append, GeneralBE4) { - section.Append(kBigEndian, 4, 0x715935c7ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I4(0x71, 0x59, 0x35, 0xc7)); -} - -TEST_F(Append, GeneralBE5) { - section.Append(kBigEndian, 5, 0x42baeb02b7ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x42, 0xba, 0xeb, 0x02, 0xb7)); -} - -TEST_F(Append, GeneralBE6) { - section.Append(kBigEndian, 6, 0xf1cdf10e7b18ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I6(0xf1, 0xcd, 0xf1, 0x0e, 0x7b, 0x18)); -} - -TEST_F(Append, GeneralBE7) { - section.Append(kBigEndian, 7, 0xf50a724f0b0d20ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I7(0xf5, 0x0a, 0x72, 0x4f, 0x0b, 0x0d, 0x20)); -} - -TEST_F(Append, GeneralBE8) { - section.Append(kBigEndian, 8, 0xa6b2cb5e98dc9c16ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I8(0xa6, 0xb2, 0xcb, 0x5e, 0x98, 0xdc, 0x9c, 0x16)); -} - -TEST_F(Append, GeneralLE1Label) { - Label l; - section.Append(kLittleEndian, 1, l); - l = 42; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(42)); -} - -TEST_F(Append, GeneralLE2Label) { - Label l; - section.Append(kLittleEndian, 2, l); - l = 0x15a1; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0xa1, 0x15)); -} - -TEST_F(Append, GeneralLE3Label) { - Label l; - section.Append(kLittleEndian, 3, l); - l = 0x59ae8d; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x8d, 0xae, 0x59)); -} - -TEST_F(Append, GeneralLE4Label) { - Label l; - section.Append(kLittleEndian, 4, l); - l = 0x51603c56; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I4(0x56, 0x3c, 0x60, 0x51)); -} - -TEST_F(Append, GeneralLE5Label) { - Label l; - section.Append(kLittleEndian, 5, l); - l = 0x385e2803b4ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0xb4, 0x03, 0x28, 0x5e, 0x38)); -} - -TEST_F(Append, GeneralLE6Label) { - Label l; - section.Append(kLittleEndian, 6, l); - l = 0xc7db9534dd1fULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I6(0x1f, 0xdd, 0x34, 0x95, 0xdb, 0xc7)); -} - -TEST_F(Append, GeneralLE7Label) { - Label l; - section.Append(kLittleEndian, 7, l); - l = 0x1445c9f1b843e6ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I7(0xe6, 0x43, 0xb8, 0xf1, 0xc9, 0x45, 0x14)); -} - -TEST_F(Append, GeneralLE8Label) { - Label l; - section.Append(kLittleEndian, 8, l); - l = 0xaf48019dfe5c01e5ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I8(0xe5, 0x01, 0x5c, 0xfe, 0x9d, 0x01, 0x48, 0xaf)); -} - -TEST_F(Append, GeneralBE1Label) { - Label l; - section.Append(kBigEndian, 1, l); - l = 0xd0ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(0xd0)); -} - -TEST_F(Append, GeneralBE2Label) { - Label l; - section.Append(kBigEndian, 2, l); - l = 0x2e7eULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2e, 0x7e)); -} - -TEST_F(Append, GeneralBE3Label) { - Label l; - section.Append(kBigEndian, 3, l); - l = 0x37dad6ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x37, 0xda, 0xd6)); -} - -TEST_F(Append, GeneralBE4Label) { - Label l; - section.Append(kBigEndian, 4, l); - l = 0x715935c7ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I4(0x71, 0x59, 0x35, 0xc7)); -} - -TEST_F(Append, GeneralBE5Label) { - Label l; - section.Append(kBigEndian, 5, l); - l = 0x42baeb02b7ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x42, 0xba, 0xeb, 0x02, 0xb7)); -} - -TEST_F(Append, GeneralBE6Label) { - Label l; - section.Append(kBigEndian, 6, l); - l = 0xf1cdf10e7b18ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I6(0xf1, 0xcd, 0xf1, 0x0e, 0x7b, 0x18)); -} - -TEST_F(Append, GeneralBE7Label) { - Label l; - section.Append(kBigEndian, 7, l); - l = 0xf50a724f0b0d20ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I7(0xf5, 0x0a, 0x72, 0x4f, 0x0b, 0x0d, 0x20)); -} - -TEST_F(Append, GeneralBE8Label) { - Label l; - section.Append(kBigEndian, 8, l); - l = 0xa6b2cb5e98dc9c16ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I8(0xa6, 0xb2, 0xcb, 0x5e, 0x98, 0xdc, 0x9c, 0x16)); -} - -TEST_F(Append, B8) { - section.Append(1, 0x2a); - section.B8(0xd3U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0xd3)); -} - -TEST_F(Append, B8Label) { - Label l; - section.Append(1, 0x2a); - section.B8(l); - l = 0x4bU; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0x4b)); -} - -TEST_F(Append, B16) { - section.Append(1, 0x2a); - section.B16(0x472aU); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x47, 0x2a)); -} - -TEST_F(Append, B16Label) { - Label l; - section.Append(1, 0x2a); - section.B16(l); - l = 0x55e8U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x55, 0xe8)); -} - -TEST_F(Append, B32) { - section.Append(1, 0x2a); - section.B32(0xbd412cbcU); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0xbd, 0x41, 0x2c, 0xbc)); -} - -TEST_F(Append, B32Label) { - Label l; - section.Append(1, 0x2a); - section.B32(l); - l = 0x208e37d5U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x20, 0x8e, 0x37, 0xd5)); -} - -TEST_F(Append, B64) { - section.Append(1, 0x2a); - section.B64(0x3402a013111e68adULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0x34, 0x02, 0xa0, 0x13, 0x11, 0x1e, 0x68, 0xad)); -} - -TEST_F(Append, B64Label) { - Label l; - section.Append(1, 0x2a); - section.B64(l); - l = 0x355dbfbb4ac6d57fULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0x35, 0x5d, 0xbf, 0xbb, 0x4a, 0xc6, 0xd5, 0x7f)); -} - -TEST_F(Append, L8) { - section.Append(1, 0x2a); - section.L8(0x26U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0x26)); -} - -TEST_F(Append, L8Label) { - Label l; - section.Append(1, 0x2a); - section.L8(l); - l = 0xa8U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0xa8)); -} - -TEST_F(Append, L16) { - section.Append(1, 0x2a); - section.L16(0xca6dU); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x6d, 0xca)); -} - -TEST_F(Append, L16Label) { - Label l; - section.Append(1, 0x2a); - section.L16(l); - l = 0xd21fU; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x1f, 0xd2)); -} - -TEST_F(Append, L32) { - section.Append(1, 0x2a); - section.L32(0x558f6181U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x81, 0x61, 0x8f, 0x55)); -} - -TEST_F(Append, L32Label) { - Label l; - section.Append(1, 0x2a); - section.L32(l); - l = 0x4b810f82U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x82, 0x0f, 0x81, 0x4b)); -} - -TEST_F(Append, L64) { - section.Append(1, 0x2a); - section.L64(0x564384f7579515bfULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0xbf, 0x15, 0x95, 0x57, 0xf7, 0x84, 0x43, 0x56)); -} - -TEST_F(Append, L64Label) { - Label l; - section.Append(1, 0x2a); - section.L64(l); - l = 0x424b1d020667c8dbULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0xdb, 0xc8, 0x67, 0x06, 0x02, 0x1d, 0x4b, 0x42)); -} - -TEST_F(Append, D8Big) { - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D8(0xe6U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0xe6)); -} - -TEST_F(Append, D8BigLabel) { - Label l; - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D8(l); - l = 0xeeU; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0xee)); -} - -TEST_F(Append, D16Big) { - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D16(0x83b1U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x83, 0xb1)); -} - -TEST_F(Append, D16BigLabel) { - Label l; - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D16(l); - l = 0x5b55U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x5b, 0x55)); -} - -TEST_F(Append, D32Big) { - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D32(0xd0b0e431U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0xd0, 0xb0, 0xe4, 0x31)); -} - -TEST_F(Append, D32BigLabel) { - Label l; - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D32(l); - l = 0x312fb340U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x31, 0x2f, 0xb3, 0x40)); -} - -TEST_F(Append, D64Big) { - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D64(0xb109843500dbcb16ULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0xb1, 0x09, 0x84, 0x35, 0x00, 0xdb, 0xcb, 0x16)); -} - -TEST_F(Append, D64BigLabel) { - Label l; - section.set_endianness(kBigEndian); - section.Append(1, 0x2a); - section.D64(l); - l = 0x9a0d61b70f671fd7ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0x9a, 0x0d, 0x61, 0xb7, 0x0f, 0x67, 0x1f, 0xd7)); -} - -TEST_F(Append, D8Little) { - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D8(0x42U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0x42)); -} - -TEST_F(Append, D8LittleLabel) { - Label l; - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D8(l); - l = 0x05U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I2(0x2a, 0x05)); -} - -TEST_F(Append, D16Little) { - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D16(0xc5c5U); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0xc5, 0xc5)); -} - -TEST_F(Append, D16LittleLabel) { - Label l; - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D16(l); - l = 0xb620U; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I3(0x2a, 0x20, 0xb6)); -} - -TEST_F(Append, D32Little) { - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D32(0x1a87d0feU); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0xfe, 0xd0, 0x87, 0x1a)); -} - -TEST_F(Append, D32LittleLabel) { - Label l; - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D32(l); - l = 0xb8012d6bU; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I5(0x2a, 0x6b, 0x2d, 0x01, 0xb8)); -} - -TEST_F(Append, D64Little) { - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D64(0x42de75c61375a1deULL); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0xde, 0xa1, 0x75, 0x13, 0xc6, 0x75, 0xde, 0x42)); -} - -TEST_F(Append, D64LittleLabel) { - Label l; - section.set_endianness(kLittleEndian); - section.Append(1, 0x2a); - section.D64(l); - l = 0x8b3bececf3fb5312ULL; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, - I9(0x2a, 0x12, 0x53, 0xfb, 0xf3, 0xec, 0xec, 0x3b, 0x8b)); -} - -TEST_F(Append, Variety) { - Label a, b, c, d, e, f, g, h; - section.Append(kBigEndian, 1, a) - .Append(kLittleEndian, 8, h) - .Append(kBigEndian, 1, 0x8bULL) - .Append(kLittleEndian, 8, 0x0ea56540448f4439ULL) - .Append(kBigEndian, 2, b) - .Append(kLittleEndian, 7, g) - .Append(kBigEndian, 2, 0xcf15ULL) - .Append(kLittleEndian, 7, 0x29694f04c5724aULL) - .Append(kBigEndian, 3, c) - .Append(kLittleEndian, 6, f) - .Append(kBigEndian, 3, 0x8c3ffdULL) - .Append(kLittleEndian, 6, 0x6f11ba80187aULL) - .Append(kBigEndian, 4, d) - .Append(kLittleEndian, 5, e) - .Append(kBigEndian, 4, 0x2fda2472ULL) - .Append(kLittleEndian, 5, 0x0aa02d423fULL) - .Append(kBigEndian, 5, e) - .Append(kLittleEndian, 4, d) - .Append(kBigEndian, 5, 0x53ba432138ULL) - .Append(kLittleEndian, 4, 0xf139ae60ULL) - .Append(kBigEndian, 6, f) - .Append(kLittleEndian, 3, c) - .Append(kBigEndian, 6, 0x168e436af716ULL) - .Append(kLittleEndian, 3, 0x3ef189ULL) - .Append(kBigEndian, 7, g) - .Append(kLittleEndian, 2, b) - .Append(kBigEndian, 7, 0xacd4ef233e47d9ULL) - .Append(kLittleEndian, 2, 0x5311ULL) - .Append(kBigEndian, 8, h) - .Append(kLittleEndian, 1, a) - .Append(kBigEndian, 8, 0x4668d5f1c93637a1ULL) - .Append(kLittleEndian, 1, 0x65ULL); - a = 0x79ac9bd8aa256b35ULL; - b = 0x22d13097ef86c91cULL; - c = 0xf204968b0a05862fULL; - d = 0x163177f15a0eb4ecULL; - e = 0xbd1b0f1d977f2246ULL; - f = 0x2b0842eee83c6461ULL; - g = 0x92f4b928a4bf875eULL; - h = 0x61a199a8f7286ba6ULL; - ASSERT_EQ(8 * 18U, section.Size()); - ASSERT_TRUE(section.GetContents(&contents)); - - static const u_int8_t expected[] = { - 0x35, 0xa6, 0x6b, 0x28, 0xf7, 0xa8, 0x99, 0xa1, 0x61, - 0x8b, 0x39, 0x44, 0x8f, 0x44, 0x40, 0x65, 0xa5, 0x0e, - 0xc9, 0x1c, 0x5e, 0x87, 0xbf, 0xa4, 0x28, 0xb9, 0xf4, - 0xcf, 0x15, 0x4a, 0x72, 0xc5, 0x04, 0x4f, 0x69, 0x29, - 0x05, 0x86, 0x2f, 0x61, 0x64, 0x3c, 0xe8, 0xee, 0x42, - 0x8c, 0x3f, 0xfd, 0x7a, 0x18, 0x80, 0xba, 0x11, 0x6f, - 0x5a, 0x0e, 0xb4, 0xec, 0x46, 0x22, 0x7f, 0x97, 0x1d, - 0x2f, 0xda, 0x24, 0x72, 0x3f, 0x42, 0x2d, 0xa0, 0x0a, - 0x1d, 0x97, 0x7f, 0x22, 0x46, 0xec, 0xb4, 0x0e, 0x5a, - 0x53, 0xba, 0x43, 0x21, 0x38, 0x60, 0xae, 0x39, 0xf1, - 0x42, 0xee, 0xe8, 0x3c, 0x64, 0x61, 0x2f, 0x86, 0x05, - 0x16, 0x8e, 0x43, 0x6a, 0xf7, 0x16, 0x89, 0xf1, 0x3e, - 0xf4, 0xb9, 0x28, 0xa4, 0xbf, 0x87, 0x5e, 0x1c, 0xc9, - 0xac, 0xd4, 0xef, 0x23, 0x3e, 0x47, 0xd9, 0x11, 0x53, - 0x61, 0xa1, 0x99, 0xa8, 0xf7, 0x28, 0x6b, 0xa6, 0x35, - 0x46, 0x68, 0xd5, 0xf1, 0xc9, 0x36, 0x37, 0xa1, 0x65, - }; - - ASSERT_TRUE(0 == memcmp(contents.data(), expected, sizeof(expected))); -} - -TEST_F(Append, Section) { - section.Append("murder"); - { - Section middle; - middle.Append(" she"); - section.Append(middle); - } - section.Append(" wrote"); - EXPECT_EQ(16U, section.Size()); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_STREQ(contents.c_str(), "murder she wrote"); -} - -TEST_F(Append, SectionRefs) { - section.Append("sugar "); - Label l; - { - Section middle; - Label m; - middle.B32(m); - section.Append(middle); - m = 0x66726565; - } - section.Append(" jazz"); - EXPECT_EQ(15U, section.Size()); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_STREQ(contents.c_str(), "sugar free jazz"); -} - -TEST_F(Append, LEB128_0) { - section.LEB128(0); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\0", 1), contents); -} - -TEST_F(Append, LEB128_0x3f) { - section.LEB128(0x3f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x3f", 1), contents); -} - -TEST_F(Append, LEB128_0x40) { - section.LEB128(0x40); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xc0\x00", 2), contents); -} - -TEST_F(Append, LEB128_0x7f) { - section.LEB128(0x7f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x00", 2), contents); -} - -TEST_F(Append, LEB128_0x80) { - section.LEB128(0x80); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x01", 2), contents); -} - -TEST_F(Append, LEB128_0xff) { - section.LEB128(0xff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x01", 2), contents); -} - -TEST_F(Append, LEB128_0x1fff) { - section.LEB128(0x1fff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x3f", 2), contents); -} - -TEST_F(Append, LEB128_0x2000) { - section.LEB128(0x2000); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\xc0\x00", 3), contents); -} - -TEST_F(Append, LEB128_n1) { - section.LEB128(-1); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x7f", 1), contents); -} - -TEST_F(Append, LEB128_n0x40) { - section.LEB128(-0x40); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x40", 1), contents); -} - -TEST_F(Append, LEB128_n0x41) { - section.LEB128(-0x41); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xbf\x7f", 2), contents); -} - -TEST_F(Append, LEB128_n0x7f) { - section.LEB128(-0x7f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x81\x7f", 2), contents); -} - -TEST_F(Append, LEB128_n0x80) { - section.LEB128(-0x80); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x7f", 2), contents); -} - -TEST_F(Append, LEB128_n0x2000) { - section.LEB128(-0x2000); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x40", 2), contents); -} - -TEST_F(Append, LEB128_n0x2001) { - section.LEB128(-0x2001); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\xbf\x7f", 3), contents); -} - -TEST_F(Append,ULEB128_0) { - section.ULEB128(0); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\0", 1), contents); -} - -TEST_F(Append,ULEB128_1) { - section.ULEB128(1); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x01", 1), contents); -} - -TEST_F(Append,ULEB128_0x3f) { - section.ULEB128(0x3f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x3f", 1), contents); -} - -TEST_F(Append,ULEB128_0x40) { - section.ULEB128(0x40); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x40", 1), contents); -} - -TEST_F(Append,ULEB128_0x7f) { - section.ULEB128(0x7f); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x7f", 1), contents); -} - -TEST_F(Append,ULEB128_0x80) { - section.ULEB128(0x80); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x01", 2), contents); -} - -TEST_F(Append,ULEB128_0xff) { - section.ULEB128(0xff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x01", 2), contents); -} - -TEST_F(Append,ULEB128_0x100) { - section.ULEB128(0x100); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x02", 2), contents); -} - -TEST_F(Append,ULEB128_0x1fff) { - section.ULEB128(0x1fff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x3f", 2), contents); -} - -TEST_F(Append,ULEB128_0x2000) { - section.ULEB128(0x2000); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x40", 2), contents); -} - -TEST_F(Append,ULEB128_0x3fff) { - section.ULEB128(0x3fff); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xff\x7f", 2), contents); -} - -TEST_F(Append,ULEB128_0x4000) { - section.ULEB128(0x4000); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x80\x01", 3), contents); -} - -TEST_F(Append,ULEB128_12857) { - section.ULEB128(12857); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\xb9\x64", 2), contents); -} - -TEST_F(Append, LEBChain) { - section.LEB128(-0x80).ULEB128(12857).Append("*"); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x80\x7f\xb9\x64*", 5), contents); -} - - -class GetContents: public SectionFixture, public Test { }; - -TEST_F(GetContents, Undefined) { - Label l; - section.Append(kLittleEndian, 8, l); - ASSERT_FALSE(section.GetContents(&contents)); -} - -TEST_F(GetContents, ClearsContents) { - section.Append((size_t) 10, '*'); - EXPECT_EQ(10U, section.Size()); - EXPECT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(0U, section.Size()); -} - -TEST_F(GetContents, ClearsReferences) { - Label l; - section.Append(kBigEndian, 1, l); - l = 42; - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_BYTES(contents, I1(42)); - ASSERT_TRUE(section.GetContents(&contents)); // should not die -} - -class Miscellanea: public SectionFixture, public Test { }; - -TEST_F(Miscellanea, Clear) { - section.Append("howdy"); - Label l; - section.L32(l); - EXPECT_EQ(9U, section.Size()); - section.Clear(); - EXPECT_EQ(0U, section.Size()); - l = 0x8d231bf0U; - ASSERT_TRUE(section.GetContents(&contents)); // should not die -} - -TEST_F(Miscellanea, Align) { - section.Append("*"); - EXPECT_EQ(1U, section.Size()); - section.Align(4).Append("*"); - EXPECT_EQ(5U, section.Size()); - section.Append("*").Align(2); - EXPECT_EQ(6U, section.Size()); -} - -TEST_F(Miscellanea, AlignPad) { - section.Append("*"); - EXPECT_EQ(1U, section.Size()); - section.Align(4, ' ').Append("*"); - EXPECT_EQ(5U, section.Size()); - section.Append("*").Align(2, ' '); - EXPECT_EQ(6U, section.Size()); - ASSERT_TRUE(section.GetContents(&contents)); - ASSERT_EQ(string("* **"), contents); -} - -TEST_F(Miscellanea, StartHereMark) { - Label m; - section.Append(42, ' ').Mark(&m).Append(13, '+'); - EXPECT_EQ(42U, m - section.start()); - EXPECT_EQ(42U + 13U, section.Here() - section.start()); - EXPECT_FALSE(section.start().IsKnownConstant()); - EXPECT_FALSE(m.IsKnownConstant()); - EXPECT_FALSE(section.Here().IsKnownConstant()); -} - -TEST_F(Miscellanea, Endianness) { - section.set_endianness(kBigEndian); - EXPECT_EQ(kBigEndian, section.endianness()); - section.set_endianness(kLittleEndian); - EXPECT_EQ(kLittleEndian, section.endianness()); -} |