aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-03-16 16:34:52 +0000
committerjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-03-16 16:34:52 +0000
commit0de9f43b879cc4e31766d4607e895641bdda1c21 (patch)
treed5c59115ad2dae2e201df971768eb7ccec028be8 /src
parentBreakpad Linux dumper: Add support for dumping DWARF CFI as STACK CFI records. (diff)
downloadbreakpad-0de9f43b879cc4e31766d4607e895641bdda1c21.tar.xz
Breakpad DWARF parser: Add support for parsing .eh_frame encoded pointers.
The Linux C++ exception handling data format (.eh_frame) can specify a number of different encodings for the addresses it contains. This patch extends dwarf2reader::ByteReader to read pointers encoded in these ways. a=jimblandy, r=nealsid git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@551 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src')
-rw-r--r--src/common/dwarf/bytereader-inl.h26
-rw-r--r--src/common/dwarf/bytereader.cc160
-rw-r--r--src/common/dwarf/bytereader.h97
-rw-r--r--src/common/dwarf/bytereader_unittest.cc691
-rw-r--r--src/common/dwarf/dwarf2enums.h24
-rw-r--r--src/tools/linux/dump_syms/Makefile21
6 files changed, 1014 insertions, 5 deletions
diff --git a/src/common/dwarf/bytereader-inl.h b/src/common/dwarf/bytereader-inl.h
index e8b4efaa..57fce448 100644
--- a/src/common/dwarf/bytereader-inl.h
+++ b/src/common/dwarf/bytereader-inl.h
@@ -144,6 +144,32 @@ inline uint64 ByteReader::ReadAddress(const char* buffer) const {
return (this->*address_reader_)(buffer);
}
+inline void ByteReader::SetCFIDataBase(uint64 section_base,
+ const char *buffer_base) {
+ section_base_ = section_base;
+ buffer_base_ = buffer_base;
+ have_section_base_ = true;
+}
+
+inline void ByteReader::SetTextBase(uint64 text_base) {
+ text_base_ = text_base;
+ have_text_base_ = true;
+}
+
+inline void ByteReader::SetDataBase(uint64 data_base) {
+ data_base_ = data_base;
+ have_data_base_ = true;
+}
+
+inline void ByteReader::SetFunctionBase(uint64 function_base) {
+ function_base_ = function_base;
+ have_function_base_ = true;
+}
+
+inline void ByteReader::ClearFunctionBase() {
+ have_function_base_ = false;
+}
+
} // namespace dwarf2reader
#endif // UTIL_DEBUGINFO_BYTEREADER_INL_H__
diff --git a/src/common/dwarf/bytereader.cc b/src/common/dwarf/bytereader.cc
index ca072980..7d784659 100644
--- a/src/common/dwarf/bytereader.cc
+++ b/src/common/dwarf/bytereader.cc
@@ -27,6 +27,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
+#include <stdlib.h>
#include "common/dwarf/bytereader-inl.h"
#include "common/dwarf/bytereader.h"
@@ -35,8 +36,9 @@ namespace dwarf2reader {
ByteReader::ByteReader(enum Endianness endian)
:offset_reader_(NULL), address_reader_(NULL), endian_(endian),
- address_size_(0), offset_size_(0)
-{ }
+ address_size_(0), offset_size_(0),
+ have_section_base_(), have_text_base_(), have_data_base_(),
+ have_function_base_() { }
ByteReader::~ByteReader() { }
@@ -77,4 +79,158 @@ uint64 ByteReader::ReadInitialLength(const char* start, size_t* len) {
return initial_length;
}
+bool ByteReader::ValidEncoding(DwarfPointerEncoding encoding) const {
+ if (encoding == DW_EH_PE_omit) return true;
+ if (encoding == DW_EH_PE_aligned) return true;
+ if (DwarfPointerEncoding(encoding & 0x7) > DW_EH_PE_udata8) return false;
+ if (DwarfPointerEncoding(encoding & 0x70) > DW_EH_PE_funcrel) return false;
+ return true;
+}
+
+bool ByteReader::UsableEncoding(DwarfPointerEncoding encoding) const {
+ switch (DwarfPointerEncoding(encoding & 0x70)) {
+ case DW_EH_PE_absptr: return true;
+ case DW_EH_PE_pcrel: return have_section_base_;
+ case DW_EH_PE_textrel: return have_text_base_;
+ case DW_EH_PE_datarel: return have_data_base_;
+ case DW_EH_PE_funcrel: return have_function_base_;
+ default: return false;
+ }
+}
+
+uint64 ByteReader::ReadEncodedPointer(const char *buffer,
+ DwarfPointerEncoding encoding,
+ size_t *len) const {
+ // This is what the GCC unwinder does.
+ if (encoding == DW_EH_PE_omit) {
+ *len = 0;
+ return 0;
+ }
+
+ // Aligned pointers are always absolute machine-sized and -signed pointers.
+ if (encoding == DW_EH_PE_aligned) {
+ assert(have_section_base_);
+
+ // We don't need to align BUFFER in *our* address space. Rather, we
+ // need to find the next position in our buffer that would be aligned
+ // when the .eh_frame section the buffer contains is loaded into the
+ // program's memory. So align assuming that buffer_base_ gets loaded at
+ // address section_base_, where section_base_ itself may or may not be
+ // aligned.
+
+ // First, find the offset to START from the closest prior aligned
+ // address.
+ size_t skew = section_base_ & (AddressSize() - 1);
+ // Now find the offset from that aligned address to buffer.
+ size_t offset = skew + (buffer - buffer_base_);
+ // Round up to the next boundary.
+ size_t aligned = (offset + AddressSize() - 1) & -AddressSize();
+ // Convert back to a pointer.
+ const char *aligned_buffer = buffer_base_ + (aligned - skew);
+ // Finally, store the length and actually fetch the pointer.
+ *len = aligned_buffer - buffer + AddressSize();
+ return ReadAddress(aligned_buffer);
+ }
+
+ // Extract the value first, ignoring whether it's a pointer or an
+ // offset relative to some base.
+ uint64 offset;
+ switch (DwarfPointerEncoding(encoding & 0x0f)) {
+ case DW_EH_PE_absptr:
+ // As the low nybble value, DW_EH_PE_absptr simply means a
+ // machine-sized and -signed address; it doesn't mean it's absolute.
+ // So it is correct for us to relocate after this.
+ offset = ReadAddress(buffer);
+ *len = AddressSize();
+ break;
+
+ case DW_EH_PE_uleb128:
+ offset = ReadUnsignedLEB128(buffer, len);
+ break;
+
+ case DW_EH_PE_udata2:
+ offset = ReadTwoBytes(buffer);
+ *len = 2;
+ break;
+
+ case DW_EH_PE_udata4:
+ offset = ReadFourBytes(buffer);
+ *len = 4;
+ break;
+
+ case DW_EH_PE_udata8:
+ offset = ReadEightBytes(buffer);
+ *len = 8;
+ break;
+
+ case DW_EH_PE_sleb128:
+ offset = ReadSignedLEB128(buffer, len);
+ break;
+
+ case DW_EH_PE_sdata2:
+ offset = ReadTwoBytes(buffer);
+ // Sign-extend from 16 bits.
+ offset = (offset ^ 0x8000) - 0x8000;
+ *len = 2;
+ break;
+
+ case DW_EH_PE_sdata4:
+ offset = ReadFourBytes(buffer);
+ // Sign-extend from 32 bits.
+ offset = (offset ^ 0x80000000ULL) - 0x80000000ULL;
+ *len = 4;
+ break;
+
+ case DW_EH_PE_sdata8:
+ // No need to sign-extend; this is the full width of our type.
+ offset = ReadEightBytes(buffer);
+ *len = 8;
+ break;
+
+ default:
+ abort();
+ }
+
+ // Find the appropriate base address.
+ uint64 base;
+ switch (DwarfPointerEncoding(encoding & 0x70)) {
+ case DW_EH_PE_absptr:
+ base = 0;
+ break;
+
+ case DW_EH_PE_pcrel:
+ assert(have_section_base_);
+ base = section_base_ + (buffer - buffer_base_);
+ break;
+
+ case DW_EH_PE_textrel:
+ assert(have_text_base_);
+ base = text_base_;
+ break;
+
+ case DW_EH_PE_datarel:
+ assert(have_data_base_);
+ base = data_base_;
+ break;
+
+ case DW_EH_PE_funcrel:
+ assert(have_function_base_);
+ base = function_base_;
+ break;
+
+ default:
+ abort();
+ }
+
+ uint64 pointer = base + offset;
+
+ // Remove inappropriate upper bits.
+ if (AddressSize() == 4)
+ pointer = pointer & 0xffffffff;
+ else
+ assert(AddressSize() == sizeof(uint64));
+
+ return pointer;
+}
+
} // namespace dwarf2reader
diff --git a/src/common/dwarf/bytereader.h b/src/common/dwarf/bytereader.h
index bda450d1..aaa97c4f 100644
--- a/src/common/dwarf/bytereader.h
+++ b/src/common/dwarf/bytereader.h
@@ -33,6 +33,7 @@
#include <string>
#include "common/dwarf/types.h"
+#include "common/dwarf/dwarf2enums.h"
namespace dwarf2reader {
@@ -45,13 +46,14 @@ enum Endianness {
// A ByteReader knows how to read single- and multi-byte values of
// various endiannesses, sizes, and encodings, as used in DWARF
-// debugging information.
+// debugging information and Linux C++ exception handling data.
class ByteReader {
public:
// Construct a ByteReader capable of reading one-, two-, four-, and
// eight-byte values according to ENDIANNESS, absolute machine-sized
- // addresses, DWARF-style "initial length" values, and signed and
- // unsigned LEB128 numbers.
+ // addresses, DWARF-style "initial length" values, signed and
+ // unsigned LEB128 numbers, and Linux C++ exception handling data's
+ // encoded pointers.
explicit ByteReader(enum Endianness endianness);
virtual ~ByteReader();
@@ -191,6 +193,89 @@ class ByteReader {
// automatically.
void SetOffsetSize(uint8 size);
+ // The Linux C++ ABI uses a variant of DWARF call frame information
+ // for exception handling. This data is included in the program's
+ // address space as the ".eh_frame" section, and intepreted at
+ // runtime to walk the stack, find exception handlers, and run
+ // cleanup code. The format is mostly the same as DWARF CFI, with
+ // some adjustments made to provide the additional
+ // exception-handling data, and to make the data easier to work with
+ // in memory --- for example, to allow it to be placed in read-only
+ // memory even when describing position-independent code.
+ //
+ // In particular, exception handling data can select a number of
+ // different encodings for pointers that appear in the data, as
+ // described by the DwarfPointerEncoding enum. There are actually
+ // four axes(!) to the encoding:
+ //
+ // - The pointer size: pointers can be 2, 4, or 8 bytes long, or use
+ // the DWARF LEB128 encoding.
+ //
+ // - The pointer's signedness: pointers can be signed or unsigned.
+ //
+ // - The pointer's base address: the data stored in the exception
+ // handling data can be the actual address (that is, an absolute
+ // pointer), or relative to one of a number of different base
+ // addreses --- including that of the encoded pointer itself, for
+ // a form of "pc-relative" addressing.
+ //
+ // - The pointer may be indirect: it may be the address where the
+ // true pointer is stored. (This is used to refer to things via
+ // global offset table entries, program linkage table entries, or
+ // other tricks used in position-independent code.)
+ //
+ // There are also two options that fall outside that matrix
+ // altogether: the pointer may be omitted, or it may have padding to
+ // align it on an appropriate address boundary. (That last option
+ // may seem like it should be just another axis, but it is not.)
+
+ // Indicate that the exception handling data is loaded starting at
+ // SECTION_BASE, and that the start of its buffer in our own memory
+ // is BUFFER_BASE. This allows us to find the address that a given
+ // byte in our buffer would have when loaded into the program the
+ // data describes. We need this to resolve DW_EH_PE_pcrel pointers.
+ void SetCFIDataBase(uint64 section_base, const char *buffer_base);
+
+ // Indicate that the base address of the program's ".text" section
+ // is TEXT_BASE. We need this to resolve DW_EH_PE_textrel pointers.
+ void SetTextBase(uint64 text_base);
+
+ // Indicate that the base address for DW_EH_PE_datarel pointers is
+ // DATA_BASE. The proper value depends on the ABI; it is usually the
+ // address of the global offset table, held in a designated register in
+ // position-independent code. You will need to look at the startup code
+ // for the target system to be sure. I tried; my eyes bled.
+ void SetDataBase(uint64 data_base);
+
+ // Indicate that the base address for the FDE we are processing is
+ // FUNCTION_BASE. This is the start address of DW_EH_PE_funcrel
+ // pointers. (This encoding does not seem to be used by the GNU
+ // toolchain.)
+ void SetFunctionBase(uint64 function_base);
+
+ // Indicate that we are no longer processing any FDE, so any use of
+ // a DW_EH_PE_funcrel encoding is an error.
+ void ClearFunctionBase();
+
+ // Return true if ENCODING is a valid pointer encoding.
+ bool ValidEncoding(DwarfPointerEncoding encoding) const;
+
+ // Return true if we have all the information we need to read a
+ // pointer that uses ENCODING. This checks that the appropriate
+ // SetFooBase function for ENCODING has been called.
+ bool UsableEncoding(DwarfPointerEncoding encoding) const;
+
+ // Read an encoded pointer from BUFFER using ENCODING; return the
+ // absolute address it represents, and set *LEN to the pointer's
+ // length in bytes, including any padding for aligned pointers.
+ //
+ // This function calls 'abort' if ENCODING is invalid or refers to a
+ // base address this reader hasn't been given, so you should check
+ // with ValidEncoding and UsableEncoding first if you would rather
+ // die in a more helpful way.
+ uint64 ReadEncodedPointer(const char *buffer, DwarfPointerEncoding encoding,
+ size_t *len) const;
+
private:
// Function pointer type for our address and offset readers.
@@ -212,6 +297,12 @@ class ByteReader {
Endianness endian_;
uint8 address_size_;
uint8 offset_size_;
+
+ // Base addresses for Linux C++ exception handling data's encoded pointers.
+ bool have_section_base_, have_text_base_, have_data_base_;
+ bool have_function_base_;
+ uint64 section_base_, text_base_, data_base_, function_base_;
+ const char *buffer_base_;
};
} // namespace dwarf2reader
diff --git a/src/common/dwarf/bytereader_unittest.cc b/src/common/dwarf/bytereader_unittest.cc
new file mode 100644
index 00000000..5e854c6e
--- /dev/null
+++ b/src/common/dwarf/bytereader_unittest.cc
@@ -0,0 +1,691 @@
+// 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>
+
+// bytereader_unittest.cc: Unit tests for dwarf2reader::ByteReader
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "common/dwarf/bytereader.h"
+#include "common/dwarf/bytereader-inl.h"
+#include "common/dwarf/cfi_assembler.h"
+
+using dwarf2reader::ByteReader;
+using dwarf2reader::DwarfPointerEncoding;
+using dwarf2reader::ENDIANNESS_BIG;
+using dwarf2reader::ENDIANNESS_LITTLE;
+using google_breakpad::CFISection;
+using google_breakpad::TestAssembler::Label;
+using google_breakpad::TestAssembler::kBigEndian;
+using google_breakpad::TestAssembler::kLittleEndian;
+using google_breakpad::TestAssembler::Section;
+using std::string;
+using testing::Test;
+
+struct ReaderFixture {
+ string contents;
+ size_t pointer_size;
+};
+
+class Reader: public ReaderFixture, public Test { };
+
+TEST_F(Reader, SimpleConstructor) {
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetAddressSize(4);
+ CFISection section(kBigEndian, 4);
+ section
+ .D8(0xc0)
+ .D16(0xcf0d)
+ .D32(0x96fdd219)
+ .D64(0xbbf55fef0825f117ULL)
+ .ULEB128(0xa0927048ba8121afULL)
+ .LEB128(-0x4f337badf4483f83LL)
+ .D32(0xfec319c9);
+ ASSERT_TRUE(section.GetContents(&contents));
+ const char *data = contents.data();
+ EXPECT_EQ(0xc0U, reader.ReadOneByte(data));
+ EXPECT_EQ(0xcf0dU, reader.ReadTwoBytes(data + 1));
+ EXPECT_EQ(0x96fdd219U, reader.ReadFourBytes(data + 3));
+ EXPECT_EQ(0xbbf55fef0825f117ULL, reader.ReadEightBytes(data + 7));
+ size_t leb128_size;
+ EXPECT_EQ(0xa0927048ba8121afULL,
+ reader.ReadUnsignedLEB128(data + 15, &leb128_size));
+ EXPECT_EQ(10U, leb128_size);
+ EXPECT_EQ(-0x4f337badf4483f83LL,
+ reader.ReadSignedLEB128(data + 25, &leb128_size));
+ EXPECT_EQ(10U, leb128_size);
+ EXPECT_EQ(0xfec319c9, reader.ReadAddress(data + 35));
+}
+
+TEST_F(Reader, ValidEncodings) {
+ ByteReader reader(ENDIANNESS_LITTLE);
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_omit)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_aligned)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_absptr |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_uleb128 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata2 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata4 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata8 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sleb128 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata2 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata4 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata8 |
+ dwarf2reader::DW_EH_PE_pcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_absptr |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_uleb128 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata2 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata4 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata8 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sleb128 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata2 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata4 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata8 |
+ dwarf2reader::DW_EH_PE_textrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_absptr |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_uleb128 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata2 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata4 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata8 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sleb128 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata2 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata4 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata8 |
+ dwarf2reader::DW_EH_PE_datarel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_absptr |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_uleb128 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata2 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata4 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_udata8 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sleb128 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata2 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata4 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+ EXPECT_TRUE(reader.ValidEncoding(
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
+ dwarf2reader::DW_EH_PE_sdata8 |
+ dwarf2reader::DW_EH_PE_funcrel)));
+
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x05)));
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x07)));
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x0d)));
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x0f)));
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x51)));
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x60)));
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x70)));
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0xf0)));
+ EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0xd0)));
+}
+
+TEST_F(Reader, DW_EH_PE_omit) {
+ static const char data[1] = { 42 };
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetAddressSize(4);
+ EXPECT_EQ(0U, reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_omit,
+ &pointer_size));
+ EXPECT_EQ(0U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_absptr4) {
+ static const char data[] = { 0x27, 0x57, 0xea, 0x40 };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(4);
+ EXPECT_EQ(0x40ea5727U,
+ reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_absptr,
+ &pointer_size));
+ EXPECT_EQ(4U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_absptr8) {
+ static const char data[] = {
+ 0x60, 0x27, 0x57, 0xea, 0x40, 0xc2, 0x98, 0x05, 0x01, 0x50
+ };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(8);
+ EXPECT_EQ(0x010598c240ea5727ULL,
+ reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_absptr,
+ &pointer_size));
+ EXPECT_EQ(8U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_uleb128) {
+ static const char data[] = { 0x81, 0x84, 0x4c };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(4);
+ EXPECT_EQ(0x130201U,
+ reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_uleb128,
+ &pointer_size));
+ EXPECT_EQ(3U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_udata2) {
+ static const char data[] = { 0xf4, 0x8d };
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetAddressSize(4);
+ EXPECT_EQ(0xf48dU,
+ reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_udata2,
+ &pointer_size));
+ EXPECT_EQ(2U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_udata4) {
+ static const char data[] = { 0xb2, 0x68, 0xa5, 0x62, 0x8f, 0x8b };
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetAddressSize(8);
+ EXPECT_EQ(0xa5628f8b,
+ reader.ReadEncodedPointer(data + 2, dwarf2reader::DW_EH_PE_udata4,
+ &pointer_size));
+ EXPECT_EQ(4U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_udata8Addr8) {
+ static const char data[] = {
+ 0x27, 0x04, 0x73, 0x04, 0x69, 0x9f, 0x19, 0xed, 0x8f, 0xfe
+ };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(8);
+ EXPECT_EQ(0x8fed199f69047304ULL,
+ reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_udata8,
+ &pointer_size));
+ EXPECT_EQ(8U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_udata8Addr4) {
+ static const char data[] = {
+ 0x27, 0x04, 0x73, 0x04, 0x69, 0x9f, 0x19, 0xed, 0x8f, 0xfe
+ };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(4);
+ EXPECT_EQ(0x69047304ULL,
+ reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_udata8,
+ &pointer_size));
+ EXPECT_EQ(8U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_sleb128) {
+ static const char data[] = { 0x42, 0xff, 0xfb, 0x73 };
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetAddressSize(4);
+ EXPECT_EQ(-0x030201U & 0xffffffff,
+ reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_sleb128,
+ &pointer_size));
+ EXPECT_EQ(3U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_sdata2) {
+ static const char data[] = { 0xb9, 0xbf };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(8);
+ EXPECT_EQ(0xffffffffffffbfb9ULL,
+ reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_sdata2,
+ &pointer_size));
+ EXPECT_EQ(2U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_sdata4) {
+ static const char data[] = { 0xa0, 0xca, 0xf2, 0xb8, 0xc2, 0xad };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(8);
+ EXPECT_EQ(0xffffffffadc2b8f2ULL,
+ reader.ReadEncodedPointer(data + 2, dwarf2reader::DW_EH_PE_sdata4,
+ &pointer_size));
+ EXPECT_EQ(4U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_sdata8) {
+ static const char data[] = {
+ 0xf6, 0x66, 0x57, 0x79, 0xe0, 0x0c, 0x9b, 0x26, 0x87
+ };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(8);
+ EXPECT_EQ(0x87269b0ce0795766ULL,
+ reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_sdata8,
+ &pointer_size));
+ EXPECT_EQ(8U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_pcrel) {
+ static const char data[] = { 0x4a, 0x8b, 0x1b, 0x14, 0xc8, 0xc4, 0x02, 0xce };
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetAddressSize(4);
+ DwarfPointerEncoding encoding =
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_pcrel
+ | dwarf2reader::DW_EH_PE_absptr);
+ reader.SetCFIDataBase(0x89951377, data);
+ EXPECT_EQ(0x89951377 + 3 + 0x14c8c402,
+ reader.ReadEncodedPointer(data + 3, encoding, &pointer_size));
+ EXPECT_EQ(4U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_textrel) {
+ static const char data[] = { 0xd9, 0x0d, 0x05, 0x17, 0xc9, 0x7a, 0x42, 0x1e };
+ ByteReader reader(ENDIANNESS_LITTLE);
+ reader.SetAddressSize(4);
+ reader.SetTextBase(0xb91beaf0);
+ DwarfPointerEncoding encoding =
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
+ | dwarf2reader::DW_EH_PE_sdata2);
+ EXPECT_EQ((0xb91beaf0 + 0xffffc917) & 0xffffffff,
+ reader.ReadEncodedPointer(data + 3, encoding, &pointer_size));
+ EXPECT_EQ(2U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_datarel) {
+ static const char data[] = { 0x16, 0xf2, 0xbb, 0x82, 0x68, 0xa7, 0xbc, 0x39 };
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetAddressSize(8);
+ reader.SetDataBase(0xbef308bd25ce74f0ULL);
+ DwarfPointerEncoding encoding =
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_datarel
+ | dwarf2reader::DW_EH_PE_sleb128);
+ EXPECT_EQ(0xbef308bd25ce74f0ULL + 0xfffffffffffa013bULL,
+ reader.ReadEncodedPointer(data + 2, encoding, &pointer_size));
+ EXPECT_EQ(3U, pointer_size);
+}
+
+TEST_F(Reader, DW_EH_PE_funcrel) {
+ static const char data[] = { 0x84, 0xf8, 0x14, 0x01, 0x61, 0xd1, 0x48, 0xc9 };
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetAddressSize(4);
+ reader.SetFunctionBase(0x823c3520);
+ DwarfPointerEncoding encoding =
+ DwarfPointerEncoding(dwarf2reader::DW_EH_PE_funcrel
+ | dwarf2reader::DW_EH_PE_udata2);
+ EXPECT_EQ(0x823c3520 + 0xd148,
+ reader.ReadEncodedPointer(data + 5, encoding, &pointer_size));
+ EXPECT_EQ(2U, pointer_size);
+}
+
+TEST(UsableBase, CFI) {
+ static const char data[1] = { 0x42 };
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetCFIDataBase(0xb31cbd20, data);
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
+}
+
+TEST(UsableBase, Text) {
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetTextBase(0xa899ccb9);
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
+}
+
+TEST(UsableBase, Data) {
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetDataBase(0xf7b10bcd);
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
+}
+
+TEST(UsableBase, Function) {
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetFunctionBase(0xc2c0ed81);
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
+}
+
+TEST(UsableBase, ClearFunction) {
+ ByteReader reader(ENDIANNESS_BIG);
+ reader.SetFunctionBase(0xc2c0ed81);
+ reader.ClearFunctionBase();
+ EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
+ EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
+}
+
+struct AlignedFixture {
+ AlignedFixture() : reader(ENDIANNESS_BIG) { reader.SetAddressSize(4); }
+ static const char data[10];
+ ByteReader reader;
+ size_t pointer_size;
+};
+
+const char AlignedFixture::data[10] = {
+ 0xfe, 0x6e, 0x93, 0xd8, 0x34, 0xd5, 0x1c, 0xd3, 0xac, 0x2b
+};
+
+class Aligned: public AlignedFixture, public Test { };
+
+TEST_F(Aligned, DW_EH_PE_aligned0) {
+ reader.SetCFIDataBase(0xb440305c, data);
+ EXPECT_EQ(0xfe6e93d8U,
+ reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
+ &pointer_size));
+ EXPECT_EQ(4U, pointer_size);
+}
+
+TEST_F(Aligned, DW_EH_PE_aligned1) {
+ reader.SetCFIDataBase(0xb440305d, data);
+ EXPECT_EQ(0xd834d51cU,
+ reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
+ &pointer_size));
+ EXPECT_EQ(7U, pointer_size);
+}
+
+TEST_F(Aligned, DW_EH_PE_aligned2) {
+ reader.SetCFIDataBase(0xb440305e, data);
+ EXPECT_EQ(0x93d834d5U,
+ reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
+ &pointer_size));
+ EXPECT_EQ(6U, pointer_size);
+}
+
+TEST_F(Aligned, DW_EH_PE_aligned3) {
+ reader.SetCFIDataBase(0xb440305f, data);
+ EXPECT_EQ(0x6e93d834U,
+ reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
+ &pointer_size));
+ EXPECT_EQ(5U, pointer_size);
+}
+
+TEST_F(Aligned, DW_EH_PE_aligned11) {
+ reader.SetCFIDataBase(0xb4403061, data);
+ EXPECT_EQ(0xd834d51cU,
+ reader.ReadEncodedPointer(data + 1,
+ dwarf2reader::DW_EH_PE_aligned,
+ &pointer_size));
+ EXPECT_EQ(6U, pointer_size);
+}
+
+TEST_F(Aligned, DW_EH_PE_aligned30) {
+ reader.SetCFIDataBase(0xb4403063, data);
+ EXPECT_EQ(0x6e93d834U,
+ reader.ReadEncodedPointer(data + 1,
+ dwarf2reader::DW_EH_PE_aligned,
+ &pointer_size));
+ EXPECT_EQ(4U, pointer_size);
+}
+
+TEST_F(Aligned, DW_EH_PE_aligned23) {
+ reader.SetCFIDataBase(0xb4403062, data);
+ EXPECT_EQ(0x1cd3ac2bU,
+ reader.ReadEncodedPointer(data + 3,
+ dwarf2reader::DW_EH_PE_aligned,
+ &pointer_size));
+ EXPECT_EQ(7U, pointer_size);
+}
+
+TEST_F(Aligned, DW_EH_PE_aligned03) {
+ reader.SetCFIDataBase(0xb4403064, data);
+ EXPECT_EQ(0x34d51cd3U,
+ reader.ReadEncodedPointer(data + 3,
+ dwarf2reader::DW_EH_PE_aligned,
+ &pointer_size));
+ EXPECT_EQ(5U, pointer_size);
+}
diff --git a/src/common/dwarf/dwarf2enums.h b/src/common/dwarf/dwarf2enums.h
index 1f8e628c..8444821a 100644
--- a/src/common/dwarf/dwarf2enums.h
+++ b/src/common/dwarf/dwarf2enums.h
@@ -573,5 +573,29 @@ enum DwarfCFI
DW_CFA_GNU_negative_offset_extended = 0x2f
};
+// Exception handling frame description pointer formats, as described
+// by the Linux Standard Base Core Specification 4.0, section 11.5,
+// DWARF Extensions.
+enum DwarfPointerEncoding
+ {
+ DW_EH_PE_absptr = 0x00,
+ DW_EH_PE_omit = 0xff,
+ DW_EH_PE_uleb128 = 0x01,
+ DW_EH_PE_udata2 = 0x02,
+ DW_EH_PE_udata4 = 0x03,
+ DW_EH_PE_udata8 = 0x04,
+ DW_EH_PE_sleb128 = 0x09,
+ DW_EH_PE_sdata2 = 0x0A,
+ DW_EH_PE_sdata4 = 0x0B,
+ DW_EH_PE_sdata8 = 0x0C,
+ DW_EH_PE_signed = 0x08,
+ DW_EH_PE_pcrel = 0x10,
+ DW_EH_PE_textrel = 0x20,
+ DW_EH_PE_datarel = 0x30,
+ DW_EH_PE_funcrel = 0x40,
+ DW_EH_PE_aligned = 0x50,
+ DW_EH_PE_indirect = 0x80
+ };
+
} // namespace dwarf2reader
#endif // COMMON_DWARF_DWARF2ENUMS_H__
diff --git a/src/tools/linux/dump_syms/Makefile b/src/tools/linux/dump_syms/Makefile
index f00c34af..3629cb46 100644
--- a/src/tools/linux/dump_syms/Makefile
+++ b/src/tools/linux/dump_syms/Makefile
@@ -115,6 +115,7 @@ COVERAGE_SOURCES += stabs_reader.cc
VPATH += $(SRC)/common/dwarf
bytereader.o: bytereader.cc
+COVERAGE_SOURCES += bytereader.cc
cfi_assembler.o: cfi_assembler.cc
dwarf2diehandler.o: dwarf2diehandler.cc
COVERAGE_SOURCES += dwarf2diehandler.cc
@@ -311,6 +312,26 @@ clean::
+### Unit tests for google_breakpad::ByteReader
+check: check-bytereader_unittest
+check-bytereader_unittest: bytereader_unittest
+bytereader_unittest: \
+ bytereader.o \
+ cfi_assembler.o \
+ gtest-all.o \
+ gtest_main.o \
+ module.o \
+ test_assembler.o \
+ $(empty)
+CPP_EXECUTABLES += bytereader_unittest
+bytereader_unittest.o: bytereader_unittest.cc
+bytereader_unittest.o: override CPPFLAGS += $(GTEST_CPPFLAGS) \
+ $(GMOCK_CPPFLAGS)
+clean::
+ rm -f bytereader_unittest
+
+
+
### Generic compilation rules.
# Link C++ executables using the C++ compiler; see CPP_EXECUTABLES above.