mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-28 09:34:14 +01:00
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
This commit is contained in:
parent
3e768ed9c0
commit
0de9f43b87
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
691
src/common/dwarf/bytereader_unittest.cc
Normal file
691
src/common/dwarf/bytereader_unittest.cc
Normal file
@ -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);
|
||||
}
|
@ -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__
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user