1*9712c20fSFrederick Mayle // Copyright 2010 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle
29*9712c20fSFrederick Mayle // Original author: Jim Blandy <[email protected]> <[email protected]>
30*9712c20fSFrederick Mayle
31*9712c20fSFrederick Mayle // test_assembler.cc: Implementation of google_breakpad::TestAssembler.
32*9712c20fSFrederick Mayle // See test_assembler.h for details.
33*9712c20fSFrederick Mayle
34*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
35*9712c20fSFrederick Mayle #include <config.h> // Must come first
36*9712c20fSFrederick Mayle #endif
37*9712c20fSFrederick Mayle
38*9712c20fSFrederick Mayle #include "common/test_assembler.h"
39*9712c20fSFrederick Mayle
40*9712c20fSFrederick Mayle #include <assert.h>
41*9712c20fSFrederick Mayle #include <stdio.h>
42*9712c20fSFrederick Mayle
43*9712c20fSFrederick Mayle #include <iterator>
44*9712c20fSFrederick Mayle
45*9712c20fSFrederick Mayle namespace google_breakpad {
46*9712c20fSFrederick Mayle namespace test_assembler {
47*9712c20fSFrederick Mayle
48*9712c20fSFrederick Mayle using std::back_insert_iterator;
49*9712c20fSFrederick Mayle
Label()50*9712c20fSFrederick Mayle Label::Label() : value_(new Binding()) { }
Label(uint64_t value)51*9712c20fSFrederick Mayle Label::Label(uint64_t value) : value_(new Binding(value)) { }
Label(const Label & label)52*9712c20fSFrederick Mayle Label::Label(const Label& label) {
53*9712c20fSFrederick Mayle value_ = label.value_;
54*9712c20fSFrederick Mayle value_->Acquire();
55*9712c20fSFrederick Mayle }
~Label()56*9712c20fSFrederick Mayle Label::~Label() {
57*9712c20fSFrederick Mayle if (value_->Release()) delete value_;
58*9712c20fSFrederick Mayle }
59*9712c20fSFrederick Mayle
operator =(uint64_t value)60*9712c20fSFrederick Mayle Label& Label::operator=(uint64_t value) {
61*9712c20fSFrederick Mayle value_->Set(NULL, value);
62*9712c20fSFrederick Mayle return *this;
63*9712c20fSFrederick Mayle }
64*9712c20fSFrederick Mayle
operator =(const Label & label)65*9712c20fSFrederick Mayle Label& Label::operator=(const Label& label) {
66*9712c20fSFrederick Mayle value_->Set(label.value_, 0);
67*9712c20fSFrederick Mayle return *this;
68*9712c20fSFrederick Mayle }
69*9712c20fSFrederick Mayle
operator +(uint64_t addend) const70*9712c20fSFrederick Mayle Label Label::operator+(uint64_t addend) const {
71*9712c20fSFrederick Mayle Label l;
72*9712c20fSFrederick Mayle l.value_->Set(this->value_, addend);
73*9712c20fSFrederick Mayle return l;
74*9712c20fSFrederick Mayle }
75*9712c20fSFrederick Mayle
operator -(uint64_t subtrahend) const76*9712c20fSFrederick Mayle Label Label::operator-(uint64_t subtrahend) const {
77*9712c20fSFrederick Mayle Label l;
78*9712c20fSFrederick Mayle l.value_->Set(this->value_, -subtrahend);
79*9712c20fSFrederick Mayle return l;
80*9712c20fSFrederick Mayle }
81*9712c20fSFrederick Mayle
82*9712c20fSFrederick Mayle // When NDEBUG is #defined, assert doesn't evaluate its argument. This
83*9712c20fSFrederick Mayle // means you can't simply use assert to check the return value of a
84*9712c20fSFrederick Mayle // function with necessary side effects.
85*9712c20fSFrederick Mayle //
86*9712c20fSFrederick Mayle // ALWAYS_EVALUATE_AND_ASSERT(x) evaluates x regardless of whether
87*9712c20fSFrederick Mayle // NDEBUG is #defined; when NDEBUG is not #defined, it further asserts
88*9712c20fSFrederick Mayle // that x is true.
89*9712c20fSFrederick Mayle #ifdef NDEBUG
90*9712c20fSFrederick Mayle #define ALWAYS_EVALUATE_AND_ASSERT(x) x
91*9712c20fSFrederick Mayle #else
92*9712c20fSFrederick Mayle #define ALWAYS_EVALUATE_AND_ASSERT(x) assert(x)
93*9712c20fSFrederick Mayle #endif
94*9712c20fSFrederick Mayle
operator -(const Label & label) const95*9712c20fSFrederick Mayle uint64_t Label::operator-(const Label& label) const {
96*9712c20fSFrederick Mayle uint64_t offset;
97*9712c20fSFrederick Mayle ALWAYS_EVALUATE_AND_ASSERT(IsKnownOffsetFrom(label, &offset));
98*9712c20fSFrederick Mayle return offset;
99*9712c20fSFrederick Mayle }
100*9712c20fSFrederick Mayle
Value() const101*9712c20fSFrederick Mayle uint64_t Label::Value() const {
102*9712c20fSFrederick Mayle uint64_t v = 0;
103*9712c20fSFrederick Mayle ALWAYS_EVALUATE_AND_ASSERT(IsKnownConstant(&v));
104*9712c20fSFrederick Mayle return v;
105*9712c20fSFrederick Mayle };
106*9712c20fSFrederick Mayle
IsKnownConstant(uint64_t * value_p) const107*9712c20fSFrederick Mayle bool Label::IsKnownConstant(uint64_t* value_p) const {
108*9712c20fSFrederick Mayle Binding* base;
109*9712c20fSFrederick Mayle uint64_t addend;
110*9712c20fSFrederick Mayle value_->Get(&base, &addend);
111*9712c20fSFrederick Mayle if (base != NULL) return false;
112*9712c20fSFrederick Mayle if (value_p) *value_p = addend;
113*9712c20fSFrederick Mayle return true;
114*9712c20fSFrederick Mayle }
115*9712c20fSFrederick Mayle
IsKnownOffsetFrom(const Label & label,uint64_t * offset_p) const116*9712c20fSFrederick Mayle bool Label::IsKnownOffsetFrom(const Label& label, uint64_t* offset_p) const
117*9712c20fSFrederick Mayle {
118*9712c20fSFrederick Mayle Binding* label_base, *this_base;
119*9712c20fSFrederick Mayle uint64_t label_addend, this_addend;
120*9712c20fSFrederick Mayle label.value_->Get(&label_base, &label_addend);
121*9712c20fSFrederick Mayle value_->Get(&this_base, &this_addend);
122*9712c20fSFrederick Mayle // If this and label are related, Get will find their final
123*9712c20fSFrederick Mayle // common ancestor, regardless of how indirect the relation is. This
124*9712c20fSFrederick Mayle // comparison also handles the constant vs. constant case.
125*9712c20fSFrederick Mayle if (this_base != label_base) return false;
126*9712c20fSFrederick Mayle if (offset_p) *offset_p = this_addend - label_addend;
127*9712c20fSFrederick Mayle return true;
128*9712c20fSFrederick Mayle }
129*9712c20fSFrederick Mayle
Binding()130*9712c20fSFrederick Mayle Label::Binding::Binding() : base_(this), addend_(), reference_count_(1) { }
131*9712c20fSFrederick Mayle
Binding(uint64_t addend)132*9712c20fSFrederick Mayle Label::Binding::Binding(uint64_t addend)
133*9712c20fSFrederick Mayle : base_(NULL), addend_(addend), reference_count_(1) { }
134*9712c20fSFrederick Mayle
~Binding()135*9712c20fSFrederick Mayle Label::Binding::~Binding() {
136*9712c20fSFrederick Mayle assert(reference_count_ == 0);
137*9712c20fSFrederick Mayle if (base_ && base_ != this && base_->Release())
138*9712c20fSFrederick Mayle delete base_;
139*9712c20fSFrederick Mayle }
140*9712c20fSFrederick Mayle
Set(Binding * binding,uint64_t addend)141*9712c20fSFrederick Mayle void Label::Binding::Set(Binding* binding, uint64_t addend) {
142*9712c20fSFrederick Mayle if (!base_ && !binding) {
143*9712c20fSFrederick Mayle // We're equating two constants. This could be okay.
144*9712c20fSFrederick Mayle assert(addend_ == addend);
145*9712c20fSFrederick Mayle } else if (!base_) {
146*9712c20fSFrederick Mayle // We are a known constant, but BINDING may not be, so turn the
147*9712c20fSFrederick Mayle // tables and try to set BINDING's value instead.
148*9712c20fSFrederick Mayle binding->Set(NULL, addend_ - addend);
149*9712c20fSFrederick Mayle } else {
150*9712c20fSFrederick Mayle if (binding) {
151*9712c20fSFrederick Mayle // Find binding's final value. Since the final value is always either
152*9712c20fSFrederick Mayle // completely unconstrained or a constant, never a reference to
153*9712c20fSFrederick Mayle // another variable (otherwise, it wouldn't be final), this
154*9712c20fSFrederick Mayle // guarantees we won't create cycles here, even for code like this:
155*9712c20fSFrederick Mayle // l = m, m = n, n = l;
156*9712c20fSFrederick Mayle uint64_t binding_addend;
157*9712c20fSFrederick Mayle binding->Get(&binding, &binding_addend);
158*9712c20fSFrederick Mayle addend += binding_addend;
159*9712c20fSFrederick Mayle }
160*9712c20fSFrederick Mayle
161*9712c20fSFrederick Mayle // It seems likely that setting a binding to itself is a bug
162*9712c20fSFrederick Mayle // (although I can imagine this might turn out to be helpful to
163*9712c20fSFrederick Mayle // permit).
164*9712c20fSFrederick Mayle assert(binding != this);
165*9712c20fSFrederick Mayle
166*9712c20fSFrederick Mayle if (base_ != this) {
167*9712c20fSFrederick Mayle // Set the other bindings on our chain as well. Note that this
168*9712c20fSFrederick Mayle // is sufficient even though binding relationships form trees:
169*9712c20fSFrederick Mayle // All binding operations traverse their chains to the end, and
170*9712c20fSFrederick Mayle // all bindings related to us share some tail of our chain, so
171*9712c20fSFrederick Mayle // they will see the changes we make here.
172*9712c20fSFrederick Mayle base_->Set(binding, addend - addend_);
173*9712c20fSFrederick Mayle // We're not going to use base_ any more.
174*9712c20fSFrederick Mayle if (base_->Release()) delete base_;
175*9712c20fSFrederick Mayle }
176*9712c20fSFrederick Mayle
177*9712c20fSFrederick Mayle // Adopt BINDING as our base. Note that it should be correct to
178*9712c20fSFrederick Mayle // acquire here, after the release above, even though the usual
179*9712c20fSFrederick Mayle // reference-counting rules call for acquiring first, and then
180*9712c20fSFrederick Mayle // releasing: the self-reference assertion above should have
181*9712c20fSFrederick Mayle // complained if BINDING were 'this' or anywhere along our chain,
182*9712c20fSFrederick Mayle // so we didn't release BINDING.
183*9712c20fSFrederick Mayle if (binding) binding->Acquire();
184*9712c20fSFrederick Mayle base_ = binding;
185*9712c20fSFrederick Mayle addend_ = addend;
186*9712c20fSFrederick Mayle }
187*9712c20fSFrederick Mayle }
188*9712c20fSFrederick Mayle
Get(Binding ** base,uint64_t * addend)189*9712c20fSFrederick Mayle void Label::Binding::Get(Binding** base, uint64_t* addend) {
190*9712c20fSFrederick Mayle if (base_ && base_ != this) {
191*9712c20fSFrederick Mayle // Recurse to find the end of our reference chain (the root of our
192*9712c20fSFrederick Mayle // tree), and then rewrite every binding along the chain to refer
193*9712c20fSFrederick Mayle // to it directly, adjusting addends appropriately. (This is why
194*9712c20fSFrederick Mayle // this member function isn't this-const.)
195*9712c20fSFrederick Mayle Binding* final_base;
196*9712c20fSFrederick Mayle uint64_t final_addend;
197*9712c20fSFrederick Mayle base_->Get(&final_base, &final_addend);
198*9712c20fSFrederick Mayle if (final_base) final_base->Acquire();
199*9712c20fSFrederick Mayle if (base_->Release()) delete base_;
200*9712c20fSFrederick Mayle base_ = final_base;
201*9712c20fSFrederick Mayle addend_ += final_addend;
202*9712c20fSFrederick Mayle }
203*9712c20fSFrederick Mayle *base = base_;
204*9712c20fSFrederick Mayle *addend = addend_;
205*9712c20fSFrederick Mayle }
206*9712c20fSFrederick Mayle
207*9712c20fSFrederick Mayle template<typename Inserter>
InsertEndian(test_assembler::Endianness endianness,size_t size,uint64_t number,Inserter dest)208*9712c20fSFrederick Mayle static inline void InsertEndian(test_assembler::Endianness endianness,
209*9712c20fSFrederick Mayle size_t size, uint64_t number, Inserter dest) {
210*9712c20fSFrederick Mayle assert(size > 0);
211*9712c20fSFrederick Mayle if (endianness == kLittleEndian) {
212*9712c20fSFrederick Mayle for (size_t i = 0; i < size; i++) {
213*9712c20fSFrederick Mayle *dest++ = (char) (number & 0xff);
214*9712c20fSFrederick Mayle number >>= 8;
215*9712c20fSFrederick Mayle }
216*9712c20fSFrederick Mayle } else {
217*9712c20fSFrederick Mayle assert(endianness == kBigEndian);
218*9712c20fSFrederick Mayle // The loop condition is odd, but it's correct for size_t.
219*9712c20fSFrederick Mayle for (size_t i = size - 1; i < size; i--)
220*9712c20fSFrederick Mayle *dest++ = (char) ((number >> (i * 8)) & 0xff);
221*9712c20fSFrederick Mayle }
222*9712c20fSFrederick Mayle }
223*9712c20fSFrederick Mayle
Append(Endianness endianness,size_t size,uint64_t number)224*9712c20fSFrederick Mayle Section& Section::Append(Endianness endianness, size_t size, uint64_t number) {
225*9712c20fSFrederick Mayle InsertEndian(endianness, size, number,
226*9712c20fSFrederick Mayle back_insert_iterator<string>(contents_));
227*9712c20fSFrederick Mayle return *this;
228*9712c20fSFrederick Mayle }
229*9712c20fSFrederick Mayle
Append(Endianness endianness,size_t size,const Label & label)230*9712c20fSFrederick Mayle Section& Section::Append(Endianness endianness, size_t size,
231*9712c20fSFrederick Mayle const Label& label) {
232*9712c20fSFrederick Mayle // If this label's value is known, there's no reason to waste an
233*9712c20fSFrederick Mayle // entry in references_ on it.
234*9712c20fSFrederick Mayle uint64_t value;
235*9712c20fSFrederick Mayle if (label.IsKnownConstant(&value))
236*9712c20fSFrederick Mayle return Append(endianness, size, value);
237*9712c20fSFrederick Mayle
238*9712c20fSFrederick Mayle // This will get caught when the references are resolved, but it's
239*9712c20fSFrederick Mayle // nicer to find out earlier.
240*9712c20fSFrederick Mayle assert(endianness != kUnsetEndian);
241*9712c20fSFrederick Mayle
242*9712c20fSFrederick Mayle references_.push_back(Reference(contents_.size(), endianness, size, label));
243*9712c20fSFrederick Mayle contents_.append(size, 0);
244*9712c20fSFrederick Mayle return *this;
245*9712c20fSFrederick Mayle }
246*9712c20fSFrederick Mayle
247*9712c20fSFrederick Mayle #define ENDIANNESS_L kLittleEndian
248*9712c20fSFrederick Mayle #define ENDIANNESS_B kBigEndian
249*9712c20fSFrederick Mayle #define ENDIANNESS(e) ENDIANNESS_ ## e
250*9712c20fSFrederick Mayle
251*9712c20fSFrederick Mayle #define DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \
252*9712c20fSFrederick Mayle Section& Section::e ## bits(uint ## bits ## _t v) { \
253*9712c20fSFrederick Mayle InsertEndian(ENDIANNESS(e), bits / 8, v, \
254*9712c20fSFrederick Mayle back_insert_iterator<string>(contents_)); \
255*9712c20fSFrederick Mayle return *this; \
256*9712c20fSFrederick Mayle }
257*9712c20fSFrederick Mayle
258*9712c20fSFrederick Mayle #define DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) \
259*9712c20fSFrederick Mayle Section& Section::e ## bits(const Label& v) { \
260*9712c20fSFrederick Mayle return Append(ENDIANNESS(e), bits / 8, v); \
261*9712c20fSFrederick Mayle }
262*9712c20fSFrederick Mayle
263*9712c20fSFrederick Mayle // Define L16, B32, and friends.
264*9712c20fSFrederick Mayle #define DEFINE_SHORT_APPEND_ENDIAN(e, bits) \
265*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \
266*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits)
267*9712c20fSFrederick Mayle
268*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_LABEL_ENDIAN(L, 8);
269*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_LABEL_ENDIAN(B, 8);
270*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_ENDIAN(L, 16);
271*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_ENDIAN(L, 32);
272*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_ENDIAN(L, 64);
273*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_ENDIAN(B, 16);
274*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_ENDIAN(B, 32);
275*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_ENDIAN(B, 64);
276*9712c20fSFrederick Mayle
277*9712c20fSFrederick Mayle #define DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \
278*9712c20fSFrederick Mayle Section& Section::D ## bits(uint ## bits ## _t v) { \
279*9712c20fSFrederick Mayle InsertEndian(endianness_, bits / 8, v, \
280*9712c20fSFrederick Mayle back_insert_iterator<string>(contents_)); \
281*9712c20fSFrederick Mayle return *this; \
282*9712c20fSFrederick Mayle }
283*9712c20fSFrederick Mayle #define DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) \
284*9712c20fSFrederick Mayle Section& Section::D ## bits(const Label& v) { \
285*9712c20fSFrederick Mayle return Append(endianness_, bits / 8, v); \
286*9712c20fSFrederick Mayle }
287*9712c20fSFrederick Mayle #define DEFINE_SHORT_APPEND_DEFAULT(bits) \
288*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \
289*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits)
290*9712c20fSFrederick Mayle
291*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_LABEL_DEFAULT(8)
292*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_DEFAULT(16);
293*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_DEFAULT(32);
294*9712c20fSFrederick Mayle DEFINE_SHORT_APPEND_DEFAULT(64);
295*9712c20fSFrederick Mayle
Append(const Section & section)296*9712c20fSFrederick Mayle Section& Section::Append(const Section& section) {
297*9712c20fSFrederick Mayle size_t base = contents_.size();
298*9712c20fSFrederick Mayle contents_.append(section.contents_);
299*9712c20fSFrederick Mayle for (vector<Reference>::const_iterator it = section.references_.begin();
300*9712c20fSFrederick Mayle it != section.references_.end(); it++)
301*9712c20fSFrederick Mayle references_.push_back(Reference(base + it->offset, it->endianness,
302*9712c20fSFrederick Mayle it->size, it->label));
303*9712c20fSFrederick Mayle return *this;
304*9712c20fSFrederick Mayle }
305*9712c20fSFrederick Mayle
LEB128(long long value)306*9712c20fSFrederick Mayle Section& Section::LEB128(long long value) {
307*9712c20fSFrederick Mayle while (value < -0x40 || 0x3f < value) {
308*9712c20fSFrederick Mayle contents_ += (value & 0x7f) | 0x80;
309*9712c20fSFrederick Mayle if (value < 0)
310*9712c20fSFrederick Mayle value = (value >> 7) | ~(((unsigned long long) -1) >> 7);
311*9712c20fSFrederick Mayle else
312*9712c20fSFrederick Mayle value = (value >> 7);
313*9712c20fSFrederick Mayle }
314*9712c20fSFrederick Mayle contents_ += value & 0x7f;
315*9712c20fSFrederick Mayle return *this;
316*9712c20fSFrederick Mayle }
317*9712c20fSFrederick Mayle
ULEB128(uint64_t value)318*9712c20fSFrederick Mayle Section& Section::ULEB128(uint64_t value) {
319*9712c20fSFrederick Mayle while (value > 0x7f) {
320*9712c20fSFrederick Mayle contents_ += (value & 0x7f) | 0x80;
321*9712c20fSFrederick Mayle value = (value >> 7);
322*9712c20fSFrederick Mayle }
323*9712c20fSFrederick Mayle contents_ += value;
324*9712c20fSFrederick Mayle return *this;
325*9712c20fSFrederick Mayle }
326*9712c20fSFrederick Mayle
Align(size_t alignment,uint8_t pad_byte)327*9712c20fSFrederick Mayle Section& Section::Align(size_t alignment, uint8_t pad_byte) {
328*9712c20fSFrederick Mayle // ALIGNMENT must be a power of two.
329*9712c20fSFrederick Mayle assert(((alignment - 1) & alignment) == 0);
330*9712c20fSFrederick Mayle size_t new_size = (contents_.size() + alignment - 1) & ~(alignment - 1);
331*9712c20fSFrederick Mayle contents_.append(new_size - contents_.size(), pad_byte);
332*9712c20fSFrederick Mayle assert((contents_.size() & (alignment - 1)) == 0);
333*9712c20fSFrederick Mayle return *this;
334*9712c20fSFrederick Mayle }
335*9712c20fSFrederick Mayle
Clear()336*9712c20fSFrederick Mayle void Section::Clear() {
337*9712c20fSFrederick Mayle contents_.clear();
338*9712c20fSFrederick Mayle references_.clear();
339*9712c20fSFrederick Mayle }
340*9712c20fSFrederick Mayle
GetContents(string * contents)341*9712c20fSFrederick Mayle bool Section::GetContents(string* contents) {
342*9712c20fSFrederick Mayle // For each label reference, find the label's value, and patch it into
343*9712c20fSFrederick Mayle // the section's contents.
344*9712c20fSFrederick Mayle for (size_t i = 0; i < references_.size(); i++) {
345*9712c20fSFrederick Mayle Reference& r = references_[i];
346*9712c20fSFrederick Mayle uint64_t value;
347*9712c20fSFrederick Mayle if (!r.label.IsKnownConstant(&value)) {
348*9712c20fSFrederick Mayle fprintf(stderr, "Undefined label #%zu at offset 0x%zx\n", i, r.offset);
349*9712c20fSFrederick Mayle return false;
350*9712c20fSFrederick Mayle }
351*9712c20fSFrederick Mayle assert(r.offset < contents_.size());
352*9712c20fSFrederick Mayle assert(contents_.size() - r.offset >= r.size);
353*9712c20fSFrederick Mayle InsertEndian(r.endianness, r.size, value, contents_.begin() + r.offset);
354*9712c20fSFrederick Mayle }
355*9712c20fSFrederick Mayle contents->clear();
356*9712c20fSFrederick Mayle std::swap(contents_, *contents);
357*9712c20fSFrederick Mayle references_.clear();
358*9712c20fSFrederick Mayle return true;
359*9712c20fSFrederick Mayle }
360*9712c20fSFrederick Mayle
361*9712c20fSFrederick Mayle } // namespace test_assembler
362*9712c20fSFrederick Mayle } // namespace google_breakpad
363