aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2012-02-01 14:57:58 +0000
committerjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2012-02-01 14:57:58 +0000
commit6eccfe32b112c68446e3fc4da30ceb1af8465e51 (patch)
treecd46ce692ad3e374a07fba577e4d8fe239c18140 /src/common
parentChange some functions in linux_libc_support.h to use intmax_t instead of int. (diff)
downloadbreakpad-6eccfe32b112c68446e3fc4da30ceb1af8465e51.tar.xz
Add partial unit tests for dwarf2reader::CompilationUnit.
This is really incomplete --- it's just what's needed to get started testing support for the DWARF 4 attribute forms. git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@910 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common')
-rw-r--r--src/common/dwarf/dwarf2reader_die_unittest.cc377
-rw-r--r--src/common/dwarf/dwarf2reader_test_common.h149
2 files changed, 526 insertions, 0 deletions
diff --git a/src/common/dwarf/dwarf2reader_die_unittest.cc b/src/common/dwarf/dwarf2reader_die_unittest.cc
new file mode 100644
index 00000000..50c01dd6
--- /dev/null
+++ b/src/common/dwarf/dwarf2reader_die_unittest.cc
@@ -0,0 +1,377 @@
+// Copyright (c) 2012, 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>
+
+// dwarf2reader_die_unittest.cc: Unit tests for dwarf2reader::CompilationUnit
+
+#include <stdlib.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/dwarf/bytereader-inl.h"
+#include "common/dwarf/dwarf2reader_test_common.h"
+#include "common/dwarf/dwarf2reader.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+using google_breakpad::test_assembler::Endianness;
+using google_breakpad::test_assembler::Label;
+using google_breakpad::test_assembler::Section;
+using google_breakpad::test_assembler::kBigEndian;
+using google_breakpad::test_assembler::kLittleEndian;
+
+using dwarf2reader::AttributeList;
+using dwarf2reader::ByteReader;
+using dwarf2reader::CompilationUnit;
+using dwarf2reader::Dwarf2Handler;
+using dwarf2reader::DwarfAttribute;
+using dwarf2reader::DwarfForm;
+using dwarf2reader::DwarfHasChild;
+using dwarf2reader::DwarfTag;
+using dwarf2reader::ENDIANNESS_BIG;
+using dwarf2reader::ENDIANNESS_LITTLE;
+using dwarf2reader::SectionMap;
+
+using std::string;
+using std::vector;
+using testing::InSequence;
+using testing::Pointee;
+using testing::Return;
+using testing::Sequence;
+using testing::Test;
+using testing::TestWithParam;
+using testing::_;
+
+class MockDwarf2Handler: public Dwarf2Handler {
+ public:
+ MOCK_METHOD5(StartCompilationUnit, bool(uint64 offset, uint8 address_size,
+ uint8 offset_size, uint64 cu_length,
+ uint8 dwarf_version));
+ MOCK_METHOD3(StartDIE, bool(uint64 offset, enum DwarfTag tag,
+ const AttributeList& attrs));
+ MOCK_METHOD4(ProcessAttributeUnsigned, void(uint64 offset,
+ DwarfAttribute attr,
+ enum DwarfForm form,
+ uint64 data));
+ MOCK_METHOD4(ProcessAttributeSigned, void(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ int64 data));
+ MOCK_METHOD4(ProcessAttributeReference, void(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ uint64 data));
+ MOCK_METHOD5(ProcessAttributeBuffer, void(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ const char* data,
+ uint64 len));
+ MOCK_METHOD4(ProcessAttributeString, void(uint64 offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ const std::string& data));
+ MOCK_METHOD1(EndDIE, void(uint64 offset));
+};
+
+struct DIEFixture {
+
+ DIEFixture() {
+ // Fix the initial offset of the .debug_info and .debug_abbrev sections.
+ info.start() = 0;
+ abbrevs.start() = 0;
+
+ // Default expectations for the data handler.
+ EXPECT_CALL(handler, StartCompilationUnit(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(handler, StartDIE(_, _, _)).Times(0);
+ EXPECT_CALL(handler, ProcessAttributeUnsigned(_, _, _, _)).Times(0);
+ EXPECT_CALL(handler, ProcessAttributeSigned(_, _, _, _)).Times(0);
+ EXPECT_CALL(handler, ProcessAttributeReference(_, _, _, _)).Times(0);
+ EXPECT_CALL(handler, ProcessAttributeBuffer(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(handler, ProcessAttributeString(_, _, _, _)).Times(0);
+ EXPECT_CALL(handler, EndDIE(_)).Times(0);
+ }
+
+ // Return a reference to a section map whose .debug_info section refers
+ // to |info|, and whose .debug_abbrev section refers to |abbrevs|. This
+ // function returns a reference to the same SectionMap each time; new
+ // calls wipe out maps established by earlier calls.
+ const SectionMap &MakeSectionMap() {
+ // Copy the sections' contents into strings that will live as long as
+ // the map itself.
+ assert(info.GetContents(&info_contents));
+ assert(abbrevs.GetContents(&abbrevs_contents));
+ section_map.clear();
+ section_map[".debug_info"].first = info_contents.data();
+ section_map[".debug_info"].second = info_contents.size();
+ section_map[".debug_abbrev"].first = abbrevs_contents.data();
+ section_map[".debug_abbrev"].second = abbrevs_contents.size();
+ return section_map;
+ }
+
+ TestCompilationUnit info;
+ TestAbbrevTable abbrevs;
+ MockDwarf2Handler handler;
+ string abbrevs_contents, info_contents;
+ SectionMap section_map;
+};
+
+struct DwarfHeaderParams {
+ DwarfHeaderParams(Endianness endianness, size_t format_size,
+ int version, size_t address_size)
+ : endianness(endianness), format_size(format_size),
+ version(version), address_size(address_size) { }
+ Endianness endianness;
+ size_t format_size; // 4-byte or 8-byte DWARF offsets
+ int version;
+ size_t address_size;
+};
+
+class DwarfHeader: public DIEFixture,
+ public TestWithParam<DwarfHeaderParams> { };
+
+TEST_P(DwarfHeader, Header) {
+ Label abbrev_table = abbrevs.Here();
+ abbrevs.Abbrev(1, dwarf2reader::DW_TAG_compile_unit,
+ dwarf2reader::DW_children_yes)
+ .Attribute(dwarf2reader::DW_AT_name, dwarf2reader::DW_FORM_string)
+ .EndAbbrev()
+ .EndTable();
+
+ info.set_format_size(GetParam().format_size);
+ info.set_endianness(GetParam().endianness);
+
+ info.Header(GetParam().version, abbrev_table, GetParam().address_size)
+ .ULEB128(1) // DW_TAG_compile_unit, with children
+ .AppendCString("sam") // DW_AT_name, DW_FORM_string
+ .D8(0); // end of children
+ info.Finish();
+
+ {
+ InSequence s;
+ EXPECT_CALL(handler,
+ StartCompilationUnit(0, GetParam().address_size,
+ GetParam().format_size, _,
+ GetParam().version))
+ .WillOnce(Return(true));
+ EXPECT_CALL(handler, StartDIE(_, dwarf2reader::DW_TAG_compile_unit, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(handler, ProcessAttributeString(_, dwarf2reader::DW_AT_name,
+ dwarf2reader::DW_FORM_string,
+ "sam"))
+ .WillOnce(Return());
+ EXPECT_CALL(handler, EndDIE(_))
+ .WillOnce(Return());
+ }
+
+ ByteReader byte_reader(GetParam().endianness == kLittleEndian ?
+ ENDIANNESS_LITTLE : ENDIANNESS_BIG);
+ CompilationUnit parser(MakeSectionMap(), 0, &byte_reader, &handler);
+ EXPECT_EQ(parser.Start(), info_contents.size());
+}
+
+INSTANTIATE_TEST_CASE_P(
+ HeaderVariants, DwarfHeader,
+ ::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4),
+ DwarfHeaderParams(kLittleEndian, 4, 2, 8),
+ DwarfHeaderParams(kLittleEndian, 4, 3, 4),
+ DwarfHeaderParams(kLittleEndian, 4, 3, 8),
+ DwarfHeaderParams(kLittleEndian, 4, 4, 4),
+ DwarfHeaderParams(kLittleEndian, 4, 4, 8),
+ DwarfHeaderParams(kLittleEndian, 8, 2, 4),
+ DwarfHeaderParams(kLittleEndian, 8, 2, 8),
+ DwarfHeaderParams(kLittleEndian, 8, 3, 4),
+ DwarfHeaderParams(kLittleEndian, 8, 3, 8),
+ DwarfHeaderParams(kLittleEndian, 8, 4, 4),
+ DwarfHeaderParams(kLittleEndian, 8, 4, 8),
+ DwarfHeaderParams(kBigEndian, 4, 2, 4),
+ DwarfHeaderParams(kBigEndian, 4, 2, 8),
+ DwarfHeaderParams(kBigEndian, 4, 3, 4),
+ DwarfHeaderParams(kBigEndian, 4, 3, 8),
+ DwarfHeaderParams(kBigEndian, 4, 4, 4),
+ DwarfHeaderParams(kBigEndian, 4, 4, 8),
+ DwarfHeaderParams(kBigEndian, 8, 2, 4),
+ DwarfHeaderParams(kBigEndian, 8, 2, 8),
+ DwarfHeaderParams(kBigEndian, 8, 3, 4),
+ DwarfHeaderParams(kBigEndian, 8, 3, 8),
+ DwarfHeaderParams(kBigEndian, 8, 4, 4),
+ DwarfHeaderParams(kBigEndian, 8, 4, 8)));
+
+struct DwarfFormsFixture: public DIEFixture {
+ // Start a compilation unit, as directed by |params|, containing one
+ // childless DIE of the given tag, with one attribute of the given name
+ // and form. The 'info' fixture member is left just after the abbrev
+ // code, waiting for the attribute value to be appended.
+ void StartSingleAttributeDIE(const DwarfHeaderParams &params,
+ DwarfTag tag, DwarfAttribute name,
+ DwarfForm form) {
+ // Create the abbreviation table.
+ Label abbrev_table = abbrevs.Here();
+ abbrevs.Abbrev(1, tag, dwarf2reader::DW_children_no)
+ .Attribute(name, form)
+ .EndAbbrev()
+ .EndTable();
+
+ // Create the compilation unit, up to the attribute value.
+ info.set_format_size(params.format_size);
+ info.set_endianness(params.endianness);
+ info.Header(params.version, abbrev_table, params.address_size)
+ .ULEB128(1); // abbrev code
+ }
+
+ // Set up handler to expect a compilation unit matching |params|,
+ // containing one childless DIE of the given tag, in the sequence s. Stop
+ // just before the expectations.
+ void ExpectBeginCompilationUnit(const DwarfHeaderParams &params,
+ DwarfTag tag) {
+ EXPECT_CALL(handler,
+ StartCompilationUnit(0, params.address_size,
+ params.format_size, _,
+ params.version))
+ .InSequence(s)
+ .WillOnce(Return(true));
+ EXPECT_CALL(handler, StartDIE(_, tag, _))
+ .InSequence(s)
+ .WillOnce(Return(true));
+ }
+
+ void ExpectEndCompilationUnit() {
+ EXPECT_CALL(handler, EndDIE(_))
+ .InSequence(s)
+ .WillOnce(Return());
+ }
+
+ void ParseCompilationUnit(const DwarfHeaderParams &params) {
+ ByteReader byte_reader(params.endianness == kLittleEndian ?
+ ENDIANNESS_LITTLE : ENDIANNESS_BIG);
+ CompilationUnit parser(MakeSectionMap(), 0, &byte_reader, &handler);
+ EXPECT_EQ(parser.Start(), info_contents.size());
+ }
+
+ // The sequence to which the fixture's methods append expectations.
+ Sequence s;
+};
+
+struct DwarfForms: public DwarfFormsFixture,
+ public TestWithParam<DwarfHeaderParams> { };
+
+TEST_P(DwarfForms, addr) {
+ StartSingleAttributeDIE(GetParam(), dwarf2reader::DW_TAG_compile_unit,
+ dwarf2reader::DW_AT_low_pc,
+ dwarf2reader::DW_FORM_addr);
+ u_int64_t value;
+ if (GetParam().address_size == 4) {
+ value = 0xc8e9ffcc;
+ info.D32(value);
+ } else {
+ value = 0xe942517fc2768564ULL;
+ info.D64(value);
+ }
+ info.Finish();
+
+ ExpectBeginCompilationUnit(GetParam(), dwarf2reader::DW_TAG_compile_unit);
+ EXPECT_CALL(handler, ProcessAttributeUnsigned(_, dwarf2reader::DW_AT_low_pc,
+ dwarf2reader::DW_FORM_addr,
+ value))
+ .InSequence(s)
+ .WillOnce(Return());
+ ExpectEndCompilationUnit();
+
+ ParseCompilationUnit(GetParam());
+}
+
+TEST_P(DwarfForms, block2_empty) {
+ StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x16e4d2f7,
+ (DwarfAttribute) 0xe52c4463,
+ dwarf2reader::DW_FORM_block2);
+ info.D16(0);
+ info.Finish();
+
+ ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x16e4d2f7);
+ EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xe52c4463,
+ dwarf2reader::DW_FORM_block2,
+ _, 0))
+ .InSequence(s)
+ .WillOnce(Return());
+ ExpectEndCompilationUnit();
+
+ ParseCompilationUnit(GetParam());
+}
+
+TEST_P(DwarfForms, block2) {
+ StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x16e4d2f7,
+ (DwarfAttribute) 0xe52c4463,
+ dwarf2reader::DW_FORM_block2);
+ unsigned char data[258];
+ memset(data, '*', sizeof(data));
+ info.D16(sizeof(data))
+ .Append(data, sizeof(data));
+ info.Finish();
+
+ ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x16e4d2f7);
+ EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xe52c4463,
+ dwarf2reader::DW_FORM_block2,
+ Pointee('*'), 258))
+ .InSequence(s)
+ .WillOnce(Return());
+ ExpectEndCompilationUnit();
+
+ ParseCompilationUnit(GetParam());
+}
+
+// Tests for the other attribute forms could go here.
+
+INSTANTIATE_TEST_CASE_P(
+ HeaderVariants, DwarfForms,
+ ::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4),
+ DwarfHeaderParams(kLittleEndian, 4, 2, 8),
+ DwarfHeaderParams(kLittleEndian, 4, 3, 4),
+ DwarfHeaderParams(kLittleEndian, 4, 3, 8),
+ DwarfHeaderParams(kLittleEndian, 4, 4, 4),
+ DwarfHeaderParams(kLittleEndian, 4, 4, 8),
+ DwarfHeaderParams(kLittleEndian, 8, 2, 4),
+ DwarfHeaderParams(kLittleEndian, 8, 2, 8),
+ DwarfHeaderParams(kLittleEndian, 8, 3, 4),
+ DwarfHeaderParams(kLittleEndian, 8, 3, 8),
+ DwarfHeaderParams(kLittleEndian, 8, 4, 4),
+ DwarfHeaderParams(kLittleEndian, 8, 4, 8),
+ DwarfHeaderParams(kBigEndian, 4, 2, 4),
+ DwarfHeaderParams(kBigEndian, 4, 2, 8),
+ DwarfHeaderParams(kBigEndian, 4, 3, 4),
+ DwarfHeaderParams(kBigEndian, 4, 3, 8),
+ DwarfHeaderParams(kBigEndian, 4, 4, 4),
+ DwarfHeaderParams(kBigEndian, 4, 4, 8),
+ DwarfHeaderParams(kBigEndian, 8, 2, 4),
+ DwarfHeaderParams(kBigEndian, 8, 2, 8),
+ DwarfHeaderParams(kBigEndian, 8, 3, 4),
+ DwarfHeaderParams(kBigEndian, 8, 3, 8),
+ DwarfHeaderParams(kBigEndian, 8, 4, 4),
+ DwarfHeaderParams(kBigEndian, 8, 4, 8)));
diff --git a/src/common/dwarf/dwarf2reader_test_common.h b/src/common/dwarf/dwarf2reader_test_common.h
new file mode 100644
index 00000000..e46931a4
--- /dev/null
+++ b/src/common/dwarf/dwarf2reader_test_common.h
@@ -0,0 +1,149 @@
+// -*- mode: c++ -*-
+
+// Copyright (c) 2012, 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>
+
+// dwarf2reader_test_common.h: Define TestCompilationUnit and
+// TestAbbrevTable, classes for creating properly (and improperly)
+// formatted DWARF compilation unit data for unit tests.
+
+#ifndef COMMON_DWARF_DWARF2READER_TEST_COMMON_H__
+#define COMMON_DWARF_DWARF2READER_TEST_COMMON_H__
+
+#include "common/test_assembler.h"
+#include "common/dwarf/dwarf2enums.h"
+
+// A subclass of test_assembler::Section, specialized for constructing
+// DWARF compilation units.
+class TestCompilationUnit: public google_breakpad::test_assembler::Section {
+ public:
+ typedef dwarf2reader::DwarfTag DwarfTag;
+ typedef dwarf2reader::DwarfAttribute DwarfAttribute;
+ typedef dwarf2reader::DwarfForm DwarfForm;
+ typedef google_breakpad::test_assembler::Label Label;
+
+ // Set the section's DWARF format size (the 32-bit DWARF format or the
+ // 64-bit DWARF format, for lengths and section offsets --- not the
+ // address size) to format_size.
+ void set_format_size(size_t format_size) {
+ assert(format_size == 4 || format_size == 8);
+ format_size_ = format_size;
+ }
+
+ // Append a DWARF section offset value, of the appropriate size for this
+ // compilation unit.
+ template<typename T>
+ void SectionOffset(T offset) {
+ if (format_size_ == 4)
+ D32(offset);
+ else
+ D64(offset);
+ }
+
+ // Append a DWARF compilation unit header to the section, with the given
+ // DWARF version, abbrev table offset, and address size.
+ TestCompilationUnit &Header(int version, const Label &abbrev_offset,
+ size_t address_size) {
+ if (format_size_ == 4) {
+ D32(length_);
+ } else {
+ D32(0xffffffff);
+ D64(length_);
+ }
+ post_length_offset_ = Size();
+ D16(version);
+ SectionOffset(abbrev_offset);
+ D8(address_size);
+ return *this;
+ }
+
+ // Mark the end of this header's DIEs.
+ TestCompilationUnit &Finish() {
+ length_ = Size() - post_length_offset_;
+ return *this;
+ }
+
+ private:
+ // The DWARF format size for this compilation unit.
+ size_t format_size_;
+
+ // The offset of the point in the compilation unit header immediately
+ // after the initial length field.
+ u_int64_t post_length_offset_;
+
+ // The length of the compilation unit, not including the initial length field.
+ Label length_;
+};
+
+// A subclass of test_assembler::Section specialized for constructing DWARF
+// abbreviation tables.
+class TestAbbrevTable: public google_breakpad::test_assembler::Section {
+ public:
+ typedef dwarf2reader::DwarfTag DwarfTag;
+ typedef dwarf2reader::DwarfAttribute DwarfAttribute;
+ typedef dwarf2reader::DwarfForm DwarfForm;
+ typedef dwarf2reader::DwarfHasChild DwarfHasChild;
+ typedef google_breakpad::test_assembler::Label Label;
+
+ // Start a new abbreviation table entry for abbreviation code |code|,
+ // encoding a DIE whose tag is |tag|, and which has children if and only
+ // if |has_children| is true.
+ TestAbbrevTable &Abbrev(int code, DwarfTag tag, DwarfHasChild has_children) {
+ assert(code != 0);
+ ULEB128(code);
+ ULEB128(static_cast<unsigned>(tag));
+ D8(static_cast<unsigned>(has_children));
+ return *this;
+ };
+
+ // Add an attribute to the current abbreviation code whose name is |name|
+ // and whose form is |form|.
+ TestAbbrevTable &Attribute(DwarfAttribute name, DwarfForm form) {
+ ULEB128(static_cast<unsigned>(name));
+ ULEB128(static_cast<unsigned>(form));
+ return *this;
+ }
+
+ // Finish the current abbreviation code.
+ TestAbbrevTable &EndAbbrev() {
+ ULEB128(0);
+ ULEB128(0);
+ return *this;
+ }
+
+ // Finish the current abbreviation table.
+ TestAbbrevTable &EndTable() {
+ ULEB128(0);
+ return *this;
+ }
+};
+
+#endif // COMMON_DWARF_DWARF2READER_TEST_COMMON_H__