aboutsummaryrefslogtreecommitdiff
path: root/src/common/dwarf
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/dwarf')
-rw-r--r--src/common/dwarf/bytereader-inl.h37
-rw-r--r--src/common/dwarf/bytereader.cc16
-rw-r--r--src/common/dwarf/bytereader.h41
-rw-r--r--src/common/dwarf/bytereader_unittest.cc515
-rw-r--r--src/common/dwarf/cfi_assembler.cc59
-rw-r--r--src/common/dwarf/cfi_assembler.h55
-rw-r--r--src/common/dwarf/dwarf2diehandler.cc30
-rw-r--r--src/common/dwarf/dwarf2diehandler.h31
-rw-r--r--src/common/dwarf/dwarf2diehandler_unittest.cc26
-rw-r--r--src/common/dwarf/dwarf2enums.h73
-rw-r--r--src/common/dwarf/dwarf2reader.cc1211
-rw-r--r--src/common/dwarf/dwarf2reader.h294
-rw-r--r--src/common/dwarf/dwarf2reader_cfi_unittest.cc494
-rw-r--r--src/common/dwarf/dwarf2reader_die_unittest.cc678
-rw-r--r--src/common/dwarf/dwarf2reader_lineinfo_unittest.cc186
-rw-r--r--src/common/dwarf/dwarf2reader_splitfunctions_unittest.cc125
-rw-r--r--src/common/dwarf/dwarf2reader_test_common.h54
-rw-r--r--src/common/dwarf/elf_reader.cc198
-rw-r--r--src/common/dwarf/elf_reader.h44
-rw-r--r--src/common/dwarf/functioninfo.cc27
-rw-r--r--src/common/dwarf/functioninfo.h8
-rw-r--r--src/common/dwarf/line_state_machine.h10
-rw-r--r--src/common/dwarf/types.h4
23 files changed, 2962 insertions, 1254 deletions
diff --git a/src/common/dwarf/bytereader-inl.h b/src/common/dwarf/bytereader-inl.h
index f4c068a2..21026484 100644
--- a/src/common/dwarf/bytereader-inl.h
+++ b/src/common/dwarf/bytereader-inl.h
@@ -1,4 +1,4 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+// Copyright 2006 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -34,13 +34,13 @@
#include <assert.h>
#include <stdint.h>
-namespace dwarf2reader {
+namespace google_breakpad {
-inline uint8_t ByteReader::ReadOneByte(const uint8_t *buffer) const {
+inline uint8_t ByteReader::ReadOneByte(const uint8_t* buffer) const {
return buffer[0];
}
-inline uint16_t ByteReader::ReadTwoBytes(const uint8_t *buffer) const {
+inline uint16_t ByteReader::ReadTwoBytes(const uint8_t* buffer) const {
const uint16_t buffer0 = buffer[0];
const uint16_t buffer1 = buffer[1];
if (endian_ == ENDIANNESS_LITTLE) {
@@ -50,7 +50,18 @@ inline uint16_t ByteReader::ReadTwoBytes(const uint8_t *buffer) const {
}
}
-inline uint64_t ByteReader::ReadFourBytes(const uint8_t *buffer) const {
+inline uint64_t ByteReader::ReadThreeBytes(const uint8_t* buffer) const {
+ const uint32_t buffer0 = buffer[0];
+ const uint32_t buffer1 = buffer[1];
+ const uint32_t buffer2 = buffer[2];
+ if (endian_ == ENDIANNESS_LITTLE) {
+ return buffer0 | buffer1 << 8 | buffer2 << 16;
+ } else {
+ return buffer2 | buffer1 << 8 | buffer0 << 16;
+ }
+}
+
+inline uint64_t ByteReader::ReadFourBytes(const uint8_t* buffer) const {
const uint32_t buffer0 = buffer[0];
const uint32_t buffer1 = buffer[1];
const uint32_t buffer2 = buffer[2];
@@ -62,7 +73,7 @@ inline uint64_t ByteReader::ReadFourBytes(const uint8_t *buffer) const {
}
}
-inline uint64_t ByteReader::ReadEightBytes(const uint8_t *buffer) const {
+inline uint64_t ByteReader::ReadEightBytes(const uint8_t* buffer) const {
const uint64_t buffer0 = buffer[0];
const uint64_t buffer1 = buffer[1];
const uint64_t buffer2 = buffer[2];
@@ -84,7 +95,7 @@ inline uint64_t ByteReader::ReadEightBytes(const uint8_t *buffer) const {
// information, plus one bit saying whether the number continues or
// not.
-inline uint64_t ByteReader::ReadUnsignedLEB128(const uint8_t *buffer,
+inline uint64_t ByteReader::ReadUnsignedLEB128(const uint8_t* buffer,
size_t* len) const {
uint64_t result = 0;
size_t num_read = 0;
@@ -109,7 +120,7 @@ inline uint64_t ByteReader::ReadUnsignedLEB128(const uint8_t *buffer,
// Read a signed LEB128 number. These are like regular LEB128
// numbers, except the last byte may have a sign bit set.
-inline int64_t ByteReader::ReadSignedLEB128(const uint8_t *buffer,
+inline int64_t ByteReader::ReadSignedLEB128(const uint8_t* buffer,
size_t* len) const {
int64_t result = 0;
unsigned int shift = 0;
@@ -129,18 +140,18 @@ inline int64_t ByteReader::ReadSignedLEB128(const uint8_t *buffer,
return result;
}
-inline uint64_t ByteReader::ReadOffset(const uint8_t *buffer) const {
+inline uint64_t ByteReader::ReadOffset(const uint8_t* buffer) const {
assert(this->offset_reader_);
return (this->*offset_reader_)(buffer);
}
-inline uint64_t ByteReader::ReadAddress(const uint8_t *buffer) const {
+inline uint64_t ByteReader::ReadAddress(const uint8_t* buffer) const {
assert(this->address_reader_);
return (this->*address_reader_)(buffer);
}
inline void ByteReader::SetCFIDataBase(uint64_t section_base,
- const uint8_t *buffer_base) {
+ const uint8_t* buffer_base) {
section_base_ = section_base;
buffer_base_ = buffer_base;
have_section_base_ = true;
@@ -165,6 +176,6 @@ inline void ByteReader::ClearFunctionBase() {
have_function_base_ = false;
}
-} // namespace dwarf2reader
+} // namespace google_breakpad
#endif // UTIL_DEBUGINFO_BYTEREADER_INL_H__
diff --git a/src/common/dwarf/bytereader.cc b/src/common/dwarf/bytereader.cc
index 0b27dd58..46bed6d0 100644
--- a/src/common/dwarf/bytereader.cc
+++ b/src/common/dwarf/bytereader.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -33,7 +33,7 @@
#include "common/dwarf/bytereader-inl.h"
#include "common/dwarf/bytereader.h"
-namespace dwarf2reader {
+namespace google_breakpad {
ByteReader::ByteReader(enum Endianness endian)
:offset_reader_(NULL), address_reader_(NULL), endian_(endian),
@@ -63,7 +63,7 @@ void ByteReader::SetAddressSize(uint8_t size) {
}
}
-uint64_t ByteReader::ReadInitialLength(const uint8_t *start, size_t* len) {
+uint64_t ByteReader::ReadInitialLength(const uint8_t* start, size_t* len) {
const uint64_t initial_length = ReadFourBytes(start);
start += 4;
@@ -101,9 +101,9 @@ bool ByteReader::UsableEncoding(DwarfPointerEncoding encoding) const {
}
}
-uint64_t ByteReader::ReadEncodedPointer(const uint8_t *buffer,
+uint64_t ByteReader::ReadEncodedPointer(const uint8_t* buffer,
DwarfPointerEncoding encoding,
- size_t *len) const {
+ size_t* len) const {
// UsableEncoding doesn't approve of DW_EH_PE_omit, so we shouldn't
// see it here.
assert(encoding != DW_EH_PE_omit);
@@ -130,7 +130,7 @@ uint64_t ByteReader::ReadEncodedPointer(const uint8_t *buffer,
// Round up to the next boundary.
uint64_t aligned = (offset + AddressSize() - 1) & -AddressSize();
// Convert back to a pointer.
- const uint8_t *aligned_buffer = buffer_base_ + (aligned - skew);
+ const uint8_t* aligned_buffer = buffer_base_ + (aligned - skew);
// Finally, store the length and actually fetch the pointer.
*len = aligned_buffer - buffer + AddressSize();
return ReadAddress(aligned_buffer);
@@ -247,4 +247,4 @@ Endianness ByteReader::GetEndianness() const {
return endian_;
}
-} // namespace dwarf2reader
+} // namespace google_breakpad
diff --git a/src/common/dwarf/bytereader.h b/src/common/dwarf/bytereader.h
index 2b37a12d..761eaf68 100644
--- a/src/common/dwarf/bytereader.h
+++ b/src/common/dwarf/bytereader.h
@@ -1,6 +1,6 @@
// -*- mode: C++ -*-
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -12,7 +12,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -38,7 +38,7 @@
#include "common/dwarf/types.h"
#include "common/dwarf/dwarf2enums.h"
-namespace dwarf2reader {
+namespace google_breakpad {
// We can't use the obvious name of LITTLE_ENDIAN and BIG_ENDIAN
// because it conflicts with a macro
@@ -62,22 +62,27 @@ class ByteReader {
// Read a single byte from BUFFER and return it as an unsigned 8 bit
// number.
- uint8_t ReadOneByte(const uint8_t *buffer) const;
+ uint8_t ReadOneByte(const uint8_t* buffer) const;
// Read two bytes from BUFFER and return them as an unsigned 16 bit
// number, using this ByteReader's endianness.
- uint16_t ReadTwoBytes(const uint8_t *buffer) const;
+ uint16_t ReadTwoBytes(const uint8_t* buffer) const;
+
+ // Read three bytes from BUFFER and return them as an unsigned 64 bit
+ // number, using this ByteReader's endianness. DWARF 5 uses this encoding
+ // for various index-related DW_FORMs.
+ uint64_t ReadThreeBytes(const uint8_t* buffer) const;
// Read four bytes from BUFFER and return them as an unsigned 32 bit
// number, using this ByteReader's endianness. This function returns
// a uint64_t so that it is compatible with ReadAddress and
// ReadOffset. The number it returns will never be outside the range
// of an unsigned 32 bit integer.
- uint64_t ReadFourBytes(const uint8_t *buffer) const;
+ uint64_t ReadFourBytes(const uint8_t* buffer) const;
// Read eight bytes from BUFFER and return them as an unsigned 64
// bit number, using this ByteReader's endianness.
- uint64_t ReadEightBytes(const uint8_t *buffer) const;
+ uint64_t ReadEightBytes(const uint8_t* buffer) const;
// Read an unsigned LEB128 (Little Endian Base 128) number from
// BUFFER and return it as an unsigned 64 bit integer. Set LEN to
@@ -96,7 +101,7 @@ class ByteReader {
// In other words, we break VALUE into groups of seven bits, put
// them in little-endian order, and then write them as eight-bit
// bytes with the high bit on all but the last.
- uint64_t ReadUnsignedLEB128(const uint8_t *buffer, size_t *len) const;
+ uint64_t ReadUnsignedLEB128(const uint8_t* buffer, size_t* len) const;
// Read a signed LEB128 number from BUFFER and return it as an
// signed 64 bit integer. Set LEN to the number of bytes read.
@@ -115,7 +120,7 @@ class ByteReader {
// In other words, we break VALUE into groups of seven bits, put
// them in little-endian order, and then write them as eight-bit
// bytes with the high bit on all but the last.
- int64_t ReadSignedLEB128(const uint8_t *buffer, size_t *len) const;
+ int64_t ReadSignedLEB128(const uint8_t* buffer, size_t* len) const;
// Indicate that addresses on this architecture are SIZE bytes long. SIZE
// must be either 4 or 8. (DWARF allows addresses to be any number of
@@ -138,7 +143,7 @@ class ByteReader {
// Read an address from BUFFER and return it as an unsigned 64 bit
// integer, respecting this ByteReader's endianness and address size. You
// must call SetAddressSize before calling this function.
- uint64_t ReadAddress(const uint8_t *buffer) const;
+ uint64_t ReadAddress(const uint8_t* buffer) const;
// DWARF actually defines two slightly different formats: 32-bit DWARF
// and 64-bit DWARF. This is *not* related to the size of registers or
@@ -175,14 +180,14 @@ class ByteReader {
// - The 32-bit value 0xffffffff, followed by a 64-bit byte count,
// indicating that the data whose length is being measured uses
// the 64-bit DWARF format.
- uint64_t ReadInitialLength(const uint8_t *start, size_t *len);
+ uint64_t ReadInitialLength(const uint8_t* start, size_t* len);
// Read an offset from BUFFER and return it as an unsigned 64 bit
// integer, respecting the ByteReader's endianness. In 32-bit DWARF, the
// offset is 4 bytes long; in 64-bit DWARF, the offset is eight bytes
// long. You must call ReadInitialLength or SetOffsetSize before calling
// this function; see the comments above for details.
- uint64_t ReadOffset(const uint8_t *buffer) const;
+ uint64_t ReadOffset(const uint8_t* buffer) const;
// Return the current offset size, in bytes.
// A return value of 4 indicates that we are reading 32-bit DWARF.
@@ -237,7 +242,7 @@ class ByteReader {
// 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_t section_base, const uint8_t *buffer_base);
+ void SetCFIDataBase(uint64_t section_base, const uint8_t* 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.
@@ -276,15 +281,15 @@ class ByteReader {
// 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_t ReadEncodedPointer(const uint8_t *buffer,
+ uint64_t ReadEncodedPointer(const uint8_t* buffer,
DwarfPointerEncoding encoding,
- size_t *len) const;
+ size_t* len) const;
Endianness GetEndianness() const;
private:
// Function pointer type for our address and offset readers.
- typedef uint64_t (ByteReader::*AddressReader)(const uint8_t *) const;
+ typedef uint64_t (ByteReader::*AddressReader)(const uint8_t*) const;
// Read an offset from BUFFER and return it as an unsigned 64 bit
// integer. DWARF2/3 define offsets as either 4 or 8 bytes,
@@ -307,9 +312,9 @@ class ByteReader {
bool have_section_base_, have_text_base_, have_data_base_;
bool have_function_base_;
uint64_t section_base_, text_base_, data_base_, function_base_;
- const uint8_t *buffer_base_;
+ const uint8_t* buffer_base_;
};
-} // namespace dwarf2reader
+} // namespace google_breakpad
#endif // COMMON_DWARF_BYTEREADER_H__
diff --git a/src/common/dwarf/bytereader_unittest.cc b/src/common/dwarf/bytereader_unittest.cc
index e66062d1..c23c737b 100644
--- a/src/common/dwarf/bytereader_unittest.cc
+++ b/src/common/dwarf/bytereader_unittest.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2010, Google Inc.
-// All rights reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -29,7 +28,7 @@
// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-// bytereader_unittest.cc: Unit tests for dwarf2reader::ByteReader
+// bytereader_unittest.cc: Unit tests for google_breakpad::ByteReader
#include <stdint.h>
@@ -41,10 +40,10 @@
#include "common/dwarf/cfi_assembler.h"
#include "common/using_std_string.h"
-using dwarf2reader::ByteReader;
-using dwarf2reader::DwarfPointerEncoding;
-using dwarf2reader::ENDIANNESS_BIG;
-using dwarf2reader::ENDIANNESS_LITTLE;
+using google_breakpad::ByteReader;
+using google_breakpad::DwarfPointerEncoding;
+using google_breakpad::ENDIANNESS_BIG;
+using google_breakpad::ENDIANNESS_LITTLE;
using google_breakpad::CFISection;
using google_breakpad::test_assembler::Label;
using google_breakpad::test_assembler::kBigEndian;
@@ -73,7 +72,7 @@ TEST_F(Reader, SimpleConstructor) {
.LEB128(-0x4f337badf4483f83LL)
.D32(0xfec319c9);
ASSERT_TRUE(section.GetContents(&contents));
- const uint8_t *data = reinterpret_cast<const uint8_t *>(contents.data());
+ const uint8_t* data = reinterpret_cast<const uint8_t*>(contents.data());
EXPECT_EQ(0xc0U, reader.ReadOneByte(data));
EXPECT_EQ(0xcf0dU, reader.ReadTwoBytes(data + 1));
EXPECT_EQ(0x96fdd219U, reader.ReadFourBytes(data + 3));
@@ -91,279 +90,279 @@ TEST_F(Reader, SimpleConstructor) {
TEST_F(Reader, ValidEncodings) {
ByteReader reader(ENDIANNESS_LITTLE);
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_absptr)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_omit)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_omit)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_aligned)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_aligned)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_uleb128)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata2)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata4)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata8)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sleb128)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata2)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata4)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata8)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_absptr |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_uleb128 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata2 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata4 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata8 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sleb128 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata2 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata4 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata8 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_absptr |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_uleb128 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata2 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata4 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata8 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sleb128 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata2 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata4 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata8 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_absptr |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_uleb128 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata2 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata4 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata8 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sleb128 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata2 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata4 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata8 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_absptr |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_uleb128 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata2 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata4 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_udata8 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sleb128 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata2 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata4 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_sdata8 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_absptr |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_uleb128 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata2 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata4 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata8 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sleb128 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata2 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata4 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_pcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata8 |
+ google_breakpad::DW_EH_PE_pcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_absptr |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_uleb128 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata2 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata4 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata8 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sleb128 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata2 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata4 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_textrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata8 |
+ google_breakpad::DW_EH_PE_textrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_absptr |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_uleb128 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata2 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata4 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata8 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sleb128 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata2 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata4 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_datarel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata8 |
+ google_breakpad::DW_EH_PE_datarel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_absptr |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_uleb128 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata2 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata4 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_udata8 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sleb128 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata2 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata4 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_funcrel)));
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect |
+ google_breakpad::DW_EH_PE_sdata8 |
+ google_breakpad::DW_EH_PE_funcrel)));
EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x05)));
EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x07)));
@@ -380,7 +379,7 @@ TEST_F(ReaderDeathTest, DW_EH_PE_omit) {
static const uint8_t data[] = { 42 };
ByteReader reader(ENDIANNESS_BIG);
reader.SetAddressSize(4);
- EXPECT_DEATH(reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_omit,
+ EXPECT_DEATH(reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_omit,
&pointer_size),
"encoding != DW_EH_PE_omit");
}
@@ -390,7 +389,7 @@ TEST_F(Reader, DW_EH_PE_absptr4) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(4);
EXPECT_EQ(0x40ea5727U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_absptr,
+ reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_absptr,
&pointer_size));
EXPECT_EQ(4U, pointer_size);
}
@@ -402,7 +401,7 @@ TEST_F(Reader, DW_EH_PE_absptr8) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(8);
EXPECT_EQ(0x010598c240ea5727ULL,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_absptr,
+ reader.ReadEncodedPointer(data + 1, google_breakpad::DW_EH_PE_absptr,
&pointer_size));
EXPECT_EQ(8U, pointer_size);
}
@@ -412,7 +411,7 @@ TEST_F(Reader, DW_EH_PE_uleb128) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(4);
EXPECT_EQ(0x130201U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_uleb128,
+ reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_uleb128,
&pointer_size));
EXPECT_EQ(3U, pointer_size);
}
@@ -422,7 +421,7 @@ TEST_F(Reader, DW_EH_PE_udata2) {
ByteReader reader(ENDIANNESS_BIG);
reader.SetAddressSize(4);
EXPECT_EQ(0xf48dU,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_udata2,
+ reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_udata2,
&pointer_size));
EXPECT_EQ(2U, pointer_size);
}
@@ -432,7 +431,7 @@ TEST_F(Reader, DW_EH_PE_udata4) {
ByteReader reader(ENDIANNESS_BIG);
reader.SetAddressSize(8);
EXPECT_EQ(0xa5628f8b,
- reader.ReadEncodedPointer(data + 2, dwarf2reader::DW_EH_PE_udata4,
+ reader.ReadEncodedPointer(data + 2, google_breakpad::DW_EH_PE_udata4,
&pointer_size));
EXPECT_EQ(4U, pointer_size);
}
@@ -444,7 +443,7 @@ TEST_F(Reader, DW_EH_PE_udata8Addr8) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(8);
EXPECT_EQ(0x8fed199f69047304ULL,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_udata8,
+ reader.ReadEncodedPointer(data + 1, google_breakpad::DW_EH_PE_udata8,
&pointer_size));
EXPECT_EQ(8U, pointer_size);
}
@@ -456,7 +455,7 @@ TEST_F(Reader, DW_EH_PE_udata8Addr4) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(4);
EXPECT_EQ(0x69047304ULL,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_udata8,
+ reader.ReadEncodedPointer(data + 1, google_breakpad::DW_EH_PE_udata8,
&pointer_size));
EXPECT_EQ(8U, pointer_size);
}
@@ -466,7 +465,7 @@ TEST_F(Reader, DW_EH_PE_sleb128) {
ByteReader reader(ENDIANNESS_BIG);
reader.SetAddressSize(4);
EXPECT_EQ(-0x030201U & 0xffffffff,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_sleb128,
+ reader.ReadEncodedPointer(data + 1, google_breakpad::DW_EH_PE_sleb128,
&pointer_size));
EXPECT_EQ(3U, pointer_size);
}
@@ -476,7 +475,7 @@ TEST_F(Reader, DW_EH_PE_sdata2) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(8);
EXPECT_EQ(0xffffffffffffbfb9ULL,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_sdata2,
+ reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_sdata2,
&pointer_size));
EXPECT_EQ(2U, pointer_size);
}
@@ -486,7 +485,7 @@ TEST_F(Reader, DW_EH_PE_sdata4) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(8);
EXPECT_EQ(0xffffffffadc2b8f2ULL,
- reader.ReadEncodedPointer(data + 2, dwarf2reader::DW_EH_PE_sdata4,
+ reader.ReadEncodedPointer(data + 2, google_breakpad::DW_EH_PE_sdata4,
&pointer_size));
EXPECT_EQ(4U, pointer_size);
}
@@ -498,7 +497,7 @@ TEST_F(Reader, DW_EH_PE_sdata8) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(8);
EXPECT_EQ(0x87269b0ce0795766ULL,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_sdata8,
+ reader.ReadEncodedPointer(data + 1, google_breakpad::DW_EH_PE_sdata8,
&pointer_size));
EXPECT_EQ(8U, pointer_size);
}
@@ -510,8 +509,8 @@ TEST_F(Reader, DW_EH_PE_pcrel) {
ByteReader reader(ENDIANNESS_BIG);
reader.SetAddressSize(4);
DwarfPointerEncoding encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_pcrel
- | dwarf2reader::DW_EH_PE_absptr);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_pcrel
+ | google_breakpad::DW_EH_PE_absptr);
reader.SetCFIDataBase(0x89951377, data);
EXPECT_EQ(0x89951377 + 3 + 0x14c8c402,
reader.ReadEncodedPointer(data + 3, encoding, &pointer_size));
@@ -526,8 +525,8 @@ TEST_F(Reader, DW_EH_PE_textrel) {
reader.SetAddressSize(4);
reader.SetTextBase(0xb91beaf0);
DwarfPointerEncoding encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
- | dwarf2reader::DW_EH_PE_sdata2);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_textrel
+ | google_breakpad::DW_EH_PE_sdata2);
EXPECT_EQ((0xb91beaf0 + 0xffffc917) & 0xffffffff,
reader.ReadEncodedPointer(data + 3, encoding, &pointer_size));
EXPECT_EQ(2U, pointer_size);
@@ -541,8 +540,8 @@ TEST_F(Reader, DW_EH_PE_datarel) {
reader.SetAddressSize(8);
reader.SetDataBase(0xbef308bd25ce74f0ULL);
DwarfPointerEncoding encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_datarel
- | dwarf2reader::DW_EH_PE_sleb128);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_datarel
+ | google_breakpad::DW_EH_PE_sleb128);
EXPECT_EQ(0xbef308bd25ce74f0ULL + 0xfffffffffffa013bULL,
reader.ReadEncodedPointer(data + 2, encoding, &pointer_size));
EXPECT_EQ(3U, pointer_size);
@@ -556,8 +555,8 @@ TEST_F(Reader, DW_EH_PE_funcrel) {
reader.SetAddressSize(4);
reader.SetFunctionBase(0x823c3520);
DwarfPointerEncoding encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_funcrel
- | dwarf2reader::DW_EH_PE_udata2);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_funcrel
+ | google_breakpad::DW_EH_PE_udata2);
EXPECT_EQ(0x823c3520 + 0xd148,
reader.ReadEncodedPointer(data + 5, encoding, &pointer_size));
EXPECT_EQ(2U, pointer_size);
@@ -567,48 +566,48 @@ TEST(UsableBase, CFI) {
static const uint8_t data[] = { 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(dwarf2reader::DW_EH_PE_omit));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_absptr));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_pcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_textrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_datarel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_omit));
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(dwarf2reader::DW_EH_PE_omit));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_absptr));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_pcrel));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_textrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_datarel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_omit));
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(dwarf2reader::DW_EH_PE_omit));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_absptr));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_pcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_textrel));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_datarel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_omit));
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(dwarf2reader::DW_EH_PE_omit));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_absptr));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_pcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_textrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_datarel));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_omit));
EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
}
@@ -616,12 +615,12 @@ 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(dwarf2reader::DW_EH_PE_omit));
+ EXPECT_TRUE(reader.UsableEncoding(google_breakpad::DW_EH_PE_absptr));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_pcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_textrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_datarel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_funcrel));
+ EXPECT_FALSE(reader.UsableEncoding(google_breakpad::DW_EH_PE_omit));
EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
}
@@ -641,7 +640,7 @@ 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,
+ reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_aligned,
&pointer_size));
EXPECT_EQ(4U, pointer_size);
}
@@ -649,7 +648,7 @@ TEST_F(Aligned, DW_EH_PE_aligned0) {
TEST_F(Aligned, DW_EH_PE_aligned1) {
reader.SetCFIDataBase(0xb440305d, data);
EXPECT_EQ(0xd834d51cU,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
+ reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_aligned,
&pointer_size));
EXPECT_EQ(7U, pointer_size);
}
@@ -657,7 +656,7 @@ TEST_F(Aligned, DW_EH_PE_aligned1) {
TEST_F(Aligned, DW_EH_PE_aligned2) {
reader.SetCFIDataBase(0xb440305e, data);
EXPECT_EQ(0x93d834d5U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
+ reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_aligned,
&pointer_size));
EXPECT_EQ(6U, pointer_size);
}
@@ -665,7 +664,7 @@ TEST_F(Aligned, DW_EH_PE_aligned2) {
TEST_F(Aligned, DW_EH_PE_aligned3) {
reader.SetCFIDataBase(0xb440305f, data);
EXPECT_EQ(0x6e93d834U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
+ reader.ReadEncodedPointer(data, google_breakpad::DW_EH_PE_aligned,
&pointer_size));
EXPECT_EQ(5U, pointer_size);
}
@@ -674,7 +673,7 @@ TEST_F(Aligned, DW_EH_PE_aligned11) {
reader.SetCFIDataBase(0xb4403061, data);
EXPECT_EQ(0xd834d51cU,
reader.ReadEncodedPointer(data + 1,
- dwarf2reader::DW_EH_PE_aligned,
+ google_breakpad::DW_EH_PE_aligned,
&pointer_size));
EXPECT_EQ(6U, pointer_size);
}
@@ -683,7 +682,7 @@ TEST_F(Aligned, DW_EH_PE_aligned30) {
reader.SetCFIDataBase(0xb4403063, data);
EXPECT_EQ(0x6e93d834U,
reader.ReadEncodedPointer(data + 1,
- dwarf2reader::DW_EH_PE_aligned,
+ google_breakpad::DW_EH_PE_aligned,
&pointer_size));
EXPECT_EQ(4U, pointer_size);
}
@@ -692,7 +691,7 @@ TEST_F(Aligned, DW_EH_PE_aligned23) {
reader.SetCFIDataBase(0xb4403062, data);
EXPECT_EQ(0x1cd3ac2bU,
reader.ReadEncodedPointer(data + 3,
- dwarf2reader::DW_EH_PE_aligned,
+ google_breakpad::DW_EH_PE_aligned,
&pointer_size));
EXPECT_EQ(7U, pointer_size);
}
@@ -701,7 +700,7 @@ TEST_F(Aligned, DW_EH_PE_aligned03) {
reader.SetCFIDataBase(0xb4403064, data);
EXPECT_EQ(0x34d51cd3U,
reader.ReadEncodedPointer(data + 3,
- dwarf2reader::DW_EH_PE_aligned,
+ google_breakpad::DW_EH_PE_aligned,
&pointer_size));
EXPECT_EQ(5U, pointer_size);
}
diff --git a/src/common/dwarf/cfi_assembler.cc b/src/common/dwarf/cfi_assembler.cc
index 2dc22085..9ed979b4 100644
--- a/src/common/dwarf/cfi_assembler.cc
+++ b/src/common/dwarf/cfi_assembler.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2010, Google Inc.
-// All rights reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -38,14 +37,12 @@
#include <stdlib.h>
namespace google_breakpad {
-
-using dwarf2reader::DwarfPointerEncoding;
-CFISection &CFISection::CIEHeader(uint64_t code_alignment_factor,
+CFISection& CFISection::CIEHeader(uint64_t code_alignment_factor,
int data_alignment_factor,
unsigned return_address_register,
uint8_t version,
- const string &augmentation,
+ const string& augmentation,
bool dwarf64,
uint8_t address_size,
uint8_t segment_size) {
@@ -78,7 +75,7 @@ CFISection &CFISection::CIEHeader(uint64_t code_alignment_factor,
return *this;
}
-CFISection &CFISection::FDEHeader(Label cie_pointer,
+CFISection& CFISection::FDEHeader(Label cie_pointer,
uint64_t initial_location,
uint64_t address_range,
bool dwarf64) {
@@ -113,9 +110,9 @@ CFISection &CFISection::FDEHeader(Label cie_pointer,
return *this;
}
-CFISection &CFISection::FinishEntry() {
+CFISection& CFISection::FinishEntry() {
assert(entry_length_);
- Align(address_size_, dwarf2reader::DW_CFA_nop);
+ Align(address_size_, DW_CFA_nop);
entry_length_->length = Here() - entry_length_->start;
delete entry_length_;
entry_length_ = NULL;
@@ -123,28 +120,28 @@ CFISection &CFISection::FinishEntry() {
return *this;
}
-CFISection &CFISection::EncodedPointer(uint64_t address,
+CFISection& CFISection::EncodedPointer(uint64_t address,
DwarfPointerEncoding encoding,
- const EncodedPointerBases &bases) {
+ const EncodedPointerBases& bases) {
// Omitted data is extremely easy to emit.
- if (encoding == dwarf2reader::DW_EH_PE_omit)
+ if (encoding == DW_EH_PE_omit)
return *this;
- // If (encoding & dwarf2reader::DW_EH_PE_indirect) != 0, then we assume
+ // If (encoding & DW_EH_PE_indirect) != 0, then we assume
// that ADDRESS is the address at which the pointer is stored --- in
// other words, that bit has no effect on how we write the pointer.
- encoding = DwarfPointerEncoding(encoding & ~dwarf2reader::DW_EH_PE_indirect);
+ encoding = DwarfPointerEncoding(encoding & ~DW_EH_PE_indirect);
// Find the base address to which this pointer is relative. The upper
// nybble of the encoding specifies this.
uint64_t base;
switch (encoding & 0xf0) {
- case dwarf2reader::DW_EH_PE_absptr: base = 0; break;
- case dwarf2reader::DW_EH_PE_pcrel: base = bases.cfi + Size(); break;
- case dwarf2reader::DW_EH_PE_textrel: base = bases.text; break;
- case dwarf2reader::DW_EH_PE_datarel: base = bases.data; break;
- case dwarf2reader::DW_EH_PE_funcrel: base = fde_start_address_; break;
- case dwarf2reader::DW_EH_PE_aligned: base = 0; break;
+ case DW_EH_PE_absptr: base = 0; break;
+ case DW_EH_PE_pcrel: base = bases.cfi + Size(); break;
+ case DW_EH_PE_textrel: base = bases.text; break;
+ case DW_EH_PE_datarel: base = bases.data; break;
+ case DW_EH_PE_funcrel: base = fde_start_address_; break;
+ case DW_EH_PE_aligned: base = 0; break;
default: abort();
};
@@ -153,7 +150,7 @@ CFISection &CFISection::EncodedPointer(uint64_t address,
address -= base;
// Align the pointer, if required.
- if ((encoding & 0xf0) == dwarf2reader::DW_EH_PE_aligned)
+ if ((encoding & 0xf0) == DW_EH_PE_aligned)
Align(AddressSize());
// Append ADDRESS to this section in the appropriate form. For the
@@ -161,30 +158,30 @@ CFISection &CFISection::EncodedPointer(uint64_t address,
// unsigned encodings, because ADDRESS has already been extended to 64
// bits before it was passed to us.
switch (encoding & 0x0f) {
- case dwarf2reader::DW_EH_PE_absptr:
+ case DW_EH_PE_absptr:
Address(address);
break;
- case dwarf2reader::DW_EH_PE_uleb128:
+ case DW_EH_PE_uleb128:
ULEB128(address);
break;
- case dwarf2reader::DW_EH_PE_sleb128:
+ case DW_EH_PE_sleb128:
LEB128(address);
break;
- case dwarf2reader::DW_EH_PE_udata2:
- case dwarf2reader::DW_EH_PE_sdata2:
+ case DW_EH_PE_udata2:
+ case DW_EH_PE_sdata2:
D16(address);
break;
- case dwarf2reader::DW_EH_PE_udata4:
- case dwarf2reader::DW_EH_PE_sdata4:
+ case DW_EH_PE_udata4:
+ case DW_EH_PE_sdata4:
D32(address);
break;
- case dwarf2reader::DW_EH_PE_udata8:
- case dwarf2reader::DW_EH_PE_sdata8:
+ case DW_EH_PE_udata8:
+ case DW_EH_PE_sdata8:
D64(address);
break;
diff --git a/src/common/dwarf/cfi_assembler.h b/src/common/dwarf/cfi_assembler.h
index bd7354d1..a33d5d84 100644
--- a/src/common/dwarf/cfi_assembler.h
+++ b/src/common/dwarf/cfi_assembler.h
@@ -1,7 +1,6 @@
// -*- mode: C++ -*-
-// Copyright (c) 2010, Google Inc.
-// All rights reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -13,7 +12,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -46,8 +45,6 @@
namespace google_breakpad {
-using dwarf2reader::DwarfPointerEncoding;
-using google_breakpad::test_assembler::Endianness;
using google_breakpad::test_assembler::Label;
using google_breakpad::test_assembler::Section;
@@ -95,10 +92,10 @@ class CFISection: public Section {
// true, use the .eh_frame format, as described by the Linux
// Standards Base Core Specification, instead of the DWARF CFI
// format.
- CFISection(Endianness endianness, size_t address_size,
+ CFISection(google_breakpad::test_assembler::Endianness endianness, size_t address_size,
bool eh_frame = false)
: Section(endianness), address_size_(address_size), eh_frame_(eh_frame),
- pointer_encoding_(dwarf2reader::DW_EH_PE_absptr),
+ pointer_encoding_(DW_EH_PE_absptr),
encoded_pointer_bases_(), entry_length_(NULL), in_fde_(false) {
// The 'start', 'Here', and 'Mark' members of a CFISection all refer
// to section offsets.
@@ -120,7 +117,7 @@ class CFISection: public Section {
// Use the addresses in BASES as the base addresses for encoded
// pointers in subsequent calls to FDEHeader or EncodedPointer.
// This function makes a copy of BASES.
- void SetEncodedPointerBases(const EncodedPointerBases &bases) {
+ void SetEncodedPointerBases(const EncodedPointerBases& bases) {
encoded_pointer_bases_ = bases;
}
@@ -133,11 +130,11 @@ class CFISection: public Section {
// Before calling this function, you will typically want to use Mark
// or Here to make a label to pass to FDEHeader that refers to this
// CIE's position in the section.
- CFISection &CIEHeader(uint64_t code_alignment_factor,
+ CFISection& CIEHeader(uint64_t code_alignment_factor,
int data_alignment_factor,
unsigned return_address_register,
uint8_t version = 3,
- const string &augmentation = "",
+ const string& augmentation = "",
bool dwarf64 = false,
uint8_t address_size = 8,
uint8_t segment_size = 0);
@@ -152,7 +149,7 @@ class CFISection: public Section {
// 0xffffff00 bytes. (The "initial length" is always a 32-bit
// value.) Nor does it support .debug_frame sections longer than
// 0xffffff00 bytes.
- CFISection &FDEHeader(Label cie_pointer,
+ CFISection& FDEHeader(Label cie_pointer,
uint64_t initial_location,
uint64_t address_range,
bool dwarf64 = false);
@@ -161,11 +158,11 @@ class CFISection: public Section {
// started, after padding with DW_CFA_nops for alignment. This
// defines the label representing the entry's length, cited in the
// entry's header. Return a reference to this section.
- CFISection &FinishEntry();
+ CFISection& FinishEntry();
// Append the contents of BLOCK as a DW_FORM_block value: an
// unsigned LEB128 length, followed by that many bytes of data.
- CFISection &Block(const string &block) {
+ CFISection& Block(const string& block) {
ULEB128(block.size());
Append(block);
return *this;
@@ -173,11 +170,11 @@ class CFISection: public Section {
// Append ADDRESS to this section, in the appropriate size and
// endianness. Return a reference to this section.
- CFISection &Address(uint64_t address) {
+ CFISection& Address(uint64_t address) {
Section::Append(endianness(), address_size_, address);
return *this;
}
- CFISection &Address(Label address) {
+ CFISection& Address(Label address) {
Section::Append(endianness(), address_size_, address);
return *this;
}
@@ -191,26 +188,26 @@ class CFISection: public Section {
//
// (C++ doesn't let me use default arguments here, because I want to
// refer to members of *this in the default argument expression.)
- CFISection &EncodedPointer(uint64_t address) {
+ CFISection& EncodedPointer(uint64_t address) {
return EncodedPointer(address, pointer_encoding_, encoded_pointer_bases_);
}
- CFISection &EncodedPointer(uint64_t address, DwarfPointerEncoding encoding) {
+ CFISection& EncodedPointer(uint64_t address, DwarfPointerEncoding encoding) {
return EncodedPointer(address, encoding, encoded_pointer_bases_);
}
- CFISection &EncodedPointer(uint64_t address, DwarfPointerEncoding encoding,
- const EncodedPointerBases &bases);
+ CFISection& EncodedPointer(uint64_t address, DwarfPointerEncoding encoding,
+ const EncodedPointerBases& bases);
// Restate some member functions, to keep chaining working nicely.
- CFISection &Mark(Label *label) { Section::Mark(label); return *this; }
- CFISection &D8(uint8_t v) { Section::D8(v); return *this; }
- CFISection &D16(uint16_t v) { Section::D16(v); return *this; }
- CFISection &D16(Label v) { Section::D16(v); return *this; }
- CFISection &D32(uint32_t v) { Section::D32(v); return *this; }
- CFISection &D32(const Label &v) { Section::D32(v); return *this; }
- CFISection &D64(uint64_t v) { Section::D64(v); return *this; }
- CFISection &D64(const Label &v) { Section::D64(v); return *this; }
- CFISection &LEB128(long long v) { Section::LEB128(v); return *this; }
- CFISection &ULEB128(uint64_t v) { Section::ULEB128(v); return *this; }
+ CFISection& Mark(Label* label) { Section::Mark(label); return *this; }
+ CFISection& D8(uint8_t v) { Section::D8(v); return *this; }
+ CFISection& D16(uint16_t v) { Section::D16(v); return *this; }
+ CFISection& D16(Label v) { Section::D16(v); return *this; }
+ CFISection& D32(uint32_t v) { Section::D32(v); return *this; }
+ CFISection& D32(const Label& v) { Section::D32(v); return *this; }
+ CFISection& D64(uint64_t v) { Section::D64(v); return *this; }
+ CFISection& D64(const Label& v) { Section::D64(v); return *this; }
+ CFISection& LEB128(long long v) { Section::LEB128(v); return *this; }
+ CFISection& ULEB128(uint64_t v) { Section::ULEB128(v); return *this; }
private:
// A length value that we've appended to the section, but is not yet
diff --git a/src/common/dwarf/dwarf2diehandler.cc b/src/common/dwarf/dwarf2diehandler.cc
index 63845018..ea3ac71c 100644
--- a/src/common/dwarf/dwarf2diehandler.cc
+++ b/src/common/dwarf/dwarf2diehandler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -39,11 +39,11 @@
#include "common/dwarf/dwarf2diehandler.h"
#include "common/using_std_string.h"
-namespace dwarf2reader {
+namespace google_breakpad {
DIEDispatcher::~DIEDispatcher() {
while (!die_handlers_.empty()) {
- HandlerStack &entry = die_handlers_.top();
+ HandlerStack& entry = die_handlers_.top();
if (entry.handler_ != root_handler_)
delete entry.handler_;
die_handlers_.pop();
@@ -60,7 +60,7 @@ bool DIEDispatcher::StartCompilationUnit(uint64_t offset, uint8_t address_size,
bool DIEDispatcher::StartDIE(uint64_t offset, enum DwarfTag tag) {
// The stack entry for the parent of this DIE, if there is one.
- HandlerStack *parent = die_handlers_.empty() ? NULL : &die_handlers_.top();
+ HandlerStack* parent = die_handlers_.empty() ? NULL : &die_handlers_.top();
// Does this call indicate that we're done receiving the parent's
// attributes' values? If so, call its EndAttributes member function.
@@ -78,7 +78,7 @@ bool DIEDispatcher::StartDIE(uint64_t offset, enum DwarfTag tag) {
}
// Find a handler for this DIE.
- DIEHandler *handler;
+ DIEHandler* handler;
if (parent) {
if (parent->handler_)
// Ask the parent to find a handler.
@@ -115,7 +115,7 @@ bool DIEDispatcher::StartDIE(uint64_t offset, enum DwarfTag tag) {
void DIEDispatcher::EndDIE(uint64_t offset) {
assert(!die_handlers_.empty());
- HandlerStack *entry = &die_handlers_.top();
+ HandlerStack* entry = &die_handlers_.top();
if (entry->handler_) {
// This entry had better be the handler for this DIE.
assert(entry->offset_ == offset);
@@ -139,7 +139,7 @@ void DIEDispatcher::ProcessAttributeUnsigned(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
uint64_t data) {
- HandlerStack &current = die_handlers_.top();
+ HandlerStack& current = die_handlers_.top();
// This had better be an attribute of the DIE we were meant to handle.
assert(offset == current.offset_);
current.handler_->ProcessAttributeUnsigned(attr, form, data);
@@ -149,7 +149,7 @@ void DIEDispatcher::ProcessAttributeSigned(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
int64_t data) {
- HandlerStack &current = die_handlers_.top();
+ HandlerStack& current = die_handlers_.top();
// This had better be an attribute of the DIE we were meant to handle.
assert(offset == current.offset_);
current.handler_->ProcessAttributeSigned(attr, form, data);
@@ -159,7 +159,7 @@ void DIEDispatcher::ProcessAttributeReference(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
uint64_t data) {
- HandlerStack &current = die_handlers_.top();
+ HandlerStack& current = die_handlers_.top();
// This had better be an attribute of the DIE we were meant to handle.
assert(offset == current.offset_);
current.handler_->ProcessAttributeReference(attr, form, data);
@@ -168,9 +168,9 @@ void DIEDispatcher::ProcessAttributeReference(uint64_t offset,
void DIEDispatcher::ProcessAttributeBuffer(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
- const uint8_t *data,
+ const uint8_t* data,
uint64_t len) {
- HandlerStack &current = die_handlers_.top();
+ HandlerStack& current = die_handlers_.top();
// This had better be an attribute of the DIE we were meant to handle.
assert(offset == current.offset_);
current.handler_->ProcessAttributeBuffer(attr, form, data, len);
@@ -180,7 +180,7 @@ void DIEDispatcher::ProcessAttributeString(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
const string& data) {
- HandlerStack &current = die_handlers_.top();
+ HandlerStack& current = die_handlers_.top();
// This had better be an attribute of the DIE we were meant to handle.
assert(offset == current.offset_);
current.handler_->ProcessAttributeString(attr, form, data);
@@ -190,10 +190,10 @@ void DIEDispatcher::ProcessAttributeSignature(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
uint64_t signature) {
- HandlerStack &current = die_handlers_.top();
+ HandlerStack& current = die_handlers_.top();
// This had better be an attribute of the DIE we were meant to handle.
assert(offset == current.offset_);
current.handler_->ProcessAttributeSignature(attr, form, signature);
}
-} // namespace dwarf2reader
+} // namespace google_breakpad
diff --git a/src/common/dwarf/dwarf2diehandler.h b/src/common/dwarf/dwarf2diehandler.h
index 871ba436..02c22853 100644
--- a/src/common/dwarf/dwarf2diehandler.h
+++ b/src/common/dwarf/dwarf2diehandler.h
@@ -1,6 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -12,7 +12,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -166,7 +166,7 @@
#include "common/dwarf/dwarf2reader.h"
#include "common/using_std_string.h"
-namespace dwarf2reader {
+namespace google_breakpad {
// A base class for handlers for specific DIE types. The series of
// calls made on a DIE handler is as follows:
@@ -208,7 +208,7 @@ class DIEHandler {
uint64_t data) { }
virtual void ProcessAttributeBuffer(enum DwarfAttribute attr,
enum DwarfForm form,
- const uint8_t *data,
+ const uint8_t* data,
uint64_t len) { }
virtual void ProcessAttributeString(enum DwarfAttribute attr,
enum DwarfForm form,
@@ -244,7 +244,7 @@ class DIEHandler {
// it is.
//
// The default definition skips all children.
- virtual DIEHandler *FindChildHandler(uint64_t offset, enum DwarfTag tag) {
+ virtual DIEHandler* FindChildHandler(uint64_t offset, enum DwarfTag tag) {
return NULL;
}
@@ -258,10 +258,13 @@ class DIEHandler {
// A subclass of DIEHandler, with additional kludges for handling the
// compilation unit's root die.
-class RootDIEHandler: public DIEHandler {
+class RootDIEHandler : public DIEHandler {
public:
- RootDIEHandler() { }
- virtual ~RootDIEHandler() { }
+ bool handle_inline;
+
+ explicit RootDIEHandler(bool handle_inline = false)
+ : handle_inline(handle_inline) {}
+ virtual ~RootDIEHandler() {}
// We pass the values reported via Dwarf2Handler::StartCompilationUnit
// to this member function, and skip the entire compilation unit if it
@@ -288,7 +291,7 @@ class DIEDispatcher: public Dwarf2Handler {
// Create a Dwarf2Handler which uses ROOT_HANDLER as the handler for
// the compilation unit's root die, as described for the DIEHandler
// class.
- DIEDispatcher(RootDIEHandler *root_handler) : root_handler_(root_handler) { }
+ DIEDispatcher(RootDIEHandler* root_handler) : root_handler_(root_handler) { }
// Destroying a DIEDispatcher destroys all active handler objects
// except the root handler.
~DIEDispatcher();
@@ -311,12 +314,12 @@ class DIEDispatcher: public Dwarf2Handler {
void ProcessAttributeBuffer(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
- const uint8_t *data,
+ const uint8_t* data,
uint64_t len);
void ProcessAttributeString(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
- const string &data);
+ const string& data);
void ProcessAttributeSignature(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
@@ -335,7 +338,7 @@ class DIEDispatcher: public Dwarf2Handler {
// The handler object interested in this DIE's attributes and
// children. If NULL, we're not interested in either.
- DIEHandler *handler_;
+ DIEHandler* handler_;
// Have we reported the end of this DIE's attributes to the handler?
bool reported_attributes_end_;
@@ -358,8 +361,8 @@ class DIEDispatcher: public Dwarf2Handler {
// The root handler. We don't push it on die_handlers_ until we
// actually get the StartDIE call for the root.
- RootDIEHandler *root_handler_;
+ RootDIEHandler* root_handler_;
};
-} // namespace dwarf2reader
+} // namespace google_breakpad
#endif // COMMON_DWARF_DWARF2DIEHANDLER_H__
diff --git a/src/common/dwarf/dwarf2diehandler_unittest.cc b/src/common/dwarf/dwarf2diehandler_unittest.cc
index 01b70489..67c9489d 100644
--- a/src/common/dwarf/dwarf2diehandler_unittest.cc
+++ b/src/common/dwarf/dwarf2diehandler_unittest.cc
@@ -1,6 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -12,7 +12,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -53,12 +53,12 @@ using ::testing::Return;
using ::testing::Sequence;
using ::testing::StrEq;
-using dwarf2reader::DIEDispatcher;
-using dwarf2reader::DIEHandler;
-using dwarf2reader::DwarfAttribute;
-using dwarf2reader::DwarfForm;
-using dwarf2reader::DwarfTag;
-using dwarf2reader::RootDIEHandler;
+using google_breakpad::DIEDispatcher;
+using google_breakpad::DIEHandler;
+using google_breakpad::DwarfAttribute;
+using google_breakpad::DwarfForm;
+using google_breakpad::DwarfTag;
+using google_breakpad::RootDIEHandler;
class MockDIEHandler: public DIEHandler {
public:
@@ -69,9 +69,9 @@ class MockDIEHandler: public DIEHandler {
MOCK_METHOD3(ProcessAttributeReference,
void(DwarfAttribute, DwarfForm, uint64_t));
MOCK_METHOD4(ProcessAttributeBuffer,
- void(DwarfAttribute, DwarfForm, const uint8_t *, uint64_t));
+ void(DwarfAttribute, DwarfForm, const uint8_t*, uint64_t));
MOCK_METHOD3(ProcessAttributeString,
- void(DwarfAttribute, DwarfForm, const string &));
+ void(DwarfAttribute, DwarfForm, const string&));
MOCK_METHOD3(ProcessAttributeSignature,
void(DwarfAttribute, DwarfForm, uint64_t));
MOCK_METHOD0(EndAttributes, bool());
@@ -88,9 +88,9 @@ class MockRootDIEHandler: public RootDIEHandler {
MOCK_METHOD3(ProcessAttributeReference,
void(DwarfAttribute, DwarfForm, uint64_t));
MOCK_METHOD4(ProcessAttributeBuffer,
- void(DwarfAttribute, DwarfForm, const uint8_t *, uint64_t));
+ void(DwarfAttribute, DwarfForm, const uint8_t*, uint64_t));
MOCK_METHOD3(ProcessAttributeString,
- void(DwarfAttribute, DwarfForm, const string &));
+ void(DwarfAttribute, DwarfForm, const string&));
MOCK_METHOD3(ProcessAttributeSignature,
void(DwarfAttribute, DwarfForm, uint64_t));
MOCK_METHOD0(EndAttributes, bool());
@@ -339,7 +339,7 @@ TEST(Dwarf2DIEHandler, FindAndSkipChildren) {
EXPECT_CALL(mock_root_handler,
FindChildHandler(0x97412be24875de9dLL,
(DwarfTag) 0x505a068b))
- .WillOnce(Return((DIEHandler *) NULL));
+ .WillOnce(Return((DIEHandler*) NULL));
// Third child DIE.
EXPECT_CALL(mock_root_handler,
diff --git a/src/common/dwarf/dwarf2enums.h b/src/common/dwarf/dwarf2enums.h
index 4316a89c..777d9bfc 100644
--- a/src/common/dwarf/dwarf2enums.h
+++ b/src/common/dwarf/dwarf2enums.h
@@ -1,6 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -12,7 +12,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -31,7 +31,7 @@
#ifndef COMMON_DWARF_DWARF2ENUMS_H__
#define COMMON_DWARF_DWARF2ENUMS_H__
-namespace dwarf2reader {
+namespace google_breakpad {
// These enums do not follow the google3 style only because they are
// known universally (specs, other implementations) by the names in
@@ -95,6 +95,10 @@ enum DwarfTag {
DW_TAG_unspecified_type = 0x3b,
DW_TAG_partial_unit = 0x3c,
DW_TAG_imported_unit = 0x3d,
+ // DWARF 4.
+ DW_TAG_type_unit = 0x41,
+ // DWARF 5.
+ DW_TAG_skeleton_unit = 0x4a,
// SGI/MIPS Extensions.
DW_TAG_MIPS_loop = 0x4081,
// HP extensions. See:
@@ -115,6 +119,16 @@ enum DwarfTag {
DW_TAG_PGI_interface_block = 0xA020
};
+enum DwarfUnitHeader {
+ DW_UT_compile = 0x01,
+ DW_UT_type = 0x02,
+ DW_UT_partial = 0x03,
+ DW_UT_skeleton = 0x04,
+ DW_UT_split_compile = 0x05,
+ DW_UT_split_type = 0x06,
+ DW_UT_lo_user = 0x80,
+ DW_UT_hi_user = 0xFF
+};
enum DwarfHasChild {
DW_children_no = 0,
@@ -149,7 +163,33 @@ enum DwarfForm {
DW_FORM_sec_offset = 0x17,
DW_FORM_exprloc = 0x18,
DW_FORM_flag_present = 0x19,
+
+ // Added in DWARF 5:
+ DW_FORM_strx = 0x1a,
+ DW_FORM_addrx = 0x1b,
+ DW_FORM_ref_sup4 = 0x1c,
+ DW_FORM_strp_sup = 0x1d,
+ DW_FORM_data16 = 0x1e,
+ DW_FORM_line_strp = 0x1f,
+
+ // DWARF 4, but value out of order.
DW_FORM_ref_sig8 = 0x20,
+
+ // Added in DWARF 5:
+ DW_FORM_implicit_const = 0x21,
+ DW_FORM_loclistx = 0x22,
+ DW_FORM_rnglistx = 0x23,
+ DW_FORM_ref_sup8 = 0x24,
+ DW_FORM_strx1 = 0x25,
+ DW_FORM_strx2 = 0x26,
+ DW_FORM_strx3 = 0x27,
+ DW_FORM_strx4 = 0x28,
+
+ DW_FORM_addrx1 = 0x29,
+ DW_FORM_addrx2 = 0x2a,
+ DW_FORM_addrx3 = 0x2b,
+ DW_FORM_addrx4 = 0x2c,
+
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
DW_FORM_GNU_addr_index = 0x1f01,
DW_FORM_GNU_str_index = 0x1f02
@@ -234,6 +274,11 @@ enum DwarfAttribute {
DW_AT_call_line = 0x59,
// DWARF 4
DW_AT_linkage_name = 0x6e,
+ // DWARF 5
+ DW_AT_str_offsets_base = 0x72,
+ DW_AT_addr_base = 0x73,
+ DW_AT_rnglists_base = 0x74,
+ DW_AT_dwo_name = 0x76,
// SGI/MIPS extensions.
DW_AT_MIPS_fde = 0x2001,
DW_AT_MIPS_loop_begin = 0x2002,
@@ -286,6 +331,26 @@ enum DwarfAttribute {
DW_AT_PGI_lstride = 0x3a02
};
+// .debug_rngslist entry types
+enum DwarfRngListEntry {
+ DW_RLE_end_of_list = 0,
+ DW_RLE_base_addressx = 1,
+ DW_RLE_startx_endx = 2,
+ DW_RLE_startx_length = 3,
+ DW_RLE_offset_pair = 4,
+ DW_RLE_base_address = 5,
+ DW_RLE_start_end = 6,
+ DW_RLE_start_length = 7,
+};
+
+// Line number content type codes (DWARF 5).
+enum DwarfLineNumberContentType {
+ DW_LNCT_path = 1,
+ DW_LNCT_directory_index = 2,
+ DW_LNCT_timestamp = 3,
+ DW_LNCT_size = 4,
+ DW_LNCT_MD5 = 5,
+};
// Line number opcodes.
enum DwarfLineNumberOps {
@@ -675,5 +740,5 @@ enum DwarfPointerEncoding
DW_EH_PE_indirect = 0x80
};
-} // namespace dwarf2reader
+} // namespace google_breakpad
#endif // COMMON_DWARF_DWARF2ENUMS_H__
diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc
index 6b9ce2b4..b191d78c 100644
--- a/src/common/dwarf/dwarf2reader.cc
+++ b/src/common/dwarf/dwarf2reader.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -28,16 +28,16 @@
// CFI reader author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-// Implementation of dwarf2reader::LineInfo, dwarf2reader::CompilationUnit,
-// and dwarf2reader::CallFrameInfo. See dwarf2reader.h for details.
+// Implementation of LineInfo, CompilationUnit,
+// and CallFrameInfo. See dwarf2reader.h for details.
#include "common/dwarf/dwarf2reader.h"
-#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include <algorithm>
#include <map>
#include <memory>
#include <stack>
@@ -52,7 +52,19 @@
#include "common/using_std_string.h"
#include "google_breakpad/common/breakpad_types.h"
-namespace dwarf2reader {
+namespace google_breakpad {
+
+const SectionMap::const_iterator GetSectionByName(const SectionMap&
+ sections, const char *name) {
+ assert(name[0] == '.');
+ auto iter = sections.find(name);
+ if (iter != sections.end())
+ return iter;
+ std::string macho_name("__");
+ macho_name += name + 1;
+ iter = sections.find(macho_name);
+ return iter;
+}
CompilationUnit::CompilationUnit(const string& path,
const SectionMap& sections, uint64_t offset,
@@ -60,11 +72,12 @@ CompilationUnit::CompilationUnit(const string& path,
: path_(path), offset_from_section_start_(offset), reader_(reader),
sections_(sections), handler_(handler), abbrevs_(),
string_buffer_(NULL), string_buffer_length_(0),
+ line_string_buffer_(NULL), line_string_buffer_length_(0),
str_offsets_buffer_(NULL), str_offsets_buffer_length_(0),
addr_buffer_(NULL), addr_buffer_length_(0),
- is_split_dwarf_(false), dwo_id_(0), dwo_name_(),
+ is_split_dwarf_(false), is_type_unit_(false), dwo_id_(0), dwo_name_(),
skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0),
- have_checked_for_dwp_(false), dwp_path_(),
+ str_offsets_base_(0), have_checked_for_dwp_(false), dwp_path_(),
dwp_byte_reader_(), dwp_reader_() {}
// Initialize a compilation unit from a .dwo or .dwp file.
@@ -99,12 +112,9 @@ void CompilationUnit::ReadAbbrevs() {
if (abbrevs_)
return;
- // First get the debug_abbrev section. ".debug_abbrev" is the name
- // recommended in the DWARF spec, and used on Linux;
- // "__debug_abbrev" is the name used in Mac OS X Mach-O files.
- SectionMap::const_iterator iter = sections_.find(".debug_abbrev");
- if (iter == sections_.end())
- iter = sections_.find("__debug_abbrev");
+ // First get the debug_abbrev section.
+ SectionMap::const_iterator iter =
+ GetSectionByName(sections_, ".debug_abbrev");
assert(iter != sections_.end());
abbrevs_ = new std::vector<Abbrev>;
@@ -113,17 +123,20 @@ void CompilationUnit::ReadAbbrevs() {
// The only way to check whether we are reading over the end of the
// buffer would be to first compute the size of the leb128 data by
// reading it, then go back and read it again.
- const uint8_t *abbrev_start = iter->second.first +
+ const uint8_t* abbrev_start = iter->second.first +
header_.abbrev_offset;
- const uint8_t *abbrevptr = abbrev_start;
+ const uint8_t* abbrevptr = abbrev_start;
#ifndef NDEBUG
const uint64_t abbrev_length = iter->second.second - header_.abbrev_offset;
#endif
+ uint64_t highest_number = 0;
+
while (1) {
CompilationUnit::Abbrev abbrev;
size_t len;
const uint64_t number = reader_->ReadUnsignedLEB128(abbrevptr, &len);
+ highest_number = std::max(highest_number, number);
if (number == 0)
break;
@@ -151,29 +164,42 @@ void CompilationUnit::ReadAbbrevs() {
if (nametemp == 0 && formtemp == 0)
break;
- const enum DwarfAttribute name =
- static_cast<enum DwarfAttribute>(nametemp);
- const enum DwarfForm form = static_cast<enum DwarfForm>(formtemp);
- abbrev.attributes.push_back(std::make_pair(name, form));
+ uint64_t value = 0;
+ if (formtemp == DW_FORM_implicit_const) {
+ value = reader_->ReadUnsignedLEB128(abbrevptr, &len);
+ abbrevptr += len;
+ }
+ AttrForm abbrev_attr(static_cast<enum DwarfAttribute>(nametemp),
+ static_cast<enum DwarfForm>(formtemp),
+ value);
+ abbrev.attributes.push_back(abbrev_attr);
}
- assert(abbrev.number == abbrevs_->size());
abbrevs_->push_back(abbrev);
}
+
+ // Account of cases where entries are out of order.
+ std::sort(abbrevs_->begin(), abbrevs_->end(),
+ [](const CompilationUnit::Abbrev& lhs, const CompilationUnit::Abbrev& rhs) {
+ return lhs.number < rhs.number;
+ });
+
+ // Ensure that there are no missing sections.
+ assert(abbrevs_->size() == highest_number + 1);
}
// Skips a single DIE's attributes.
-const uint8_t *CompilationUnit::SkipDIE(const uint8_t* start,
+const uint8_t* CompilationUnit::SkipDIE(const uint8_t* start,
const Abbrev& abbrev) {
for (AttributeList::const_iterator i = abbrev.attributes.begin();
i != abbrev.attributes.end();
i++) {
- start = SkipAttribute(start, i->second);
+ start = SkipAttribute(start, i->form_);
}
return start;
}
// Skips a single attribute form's data.
-const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
+const uint8_t* CompilationUnit::SkipAttribute(const uint8_t* start,
enum DwarfForm form) {
size_t len;
@@ -185,27 +211,45 @@ const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
return SkipAttribute(start, form);
case DW_FORM_flag_present:
+ case DW_FORM_implicit_const:
return start;
+ case DW_FORM_addrx1:
case DW_FORM_data1:
case DW_FORM_flag:
case DW_FORM_ref1:
+ case DW_FORM_strx1:
return start + 1;
+ case DW_FORM_addrx2:
case DW_FORM_ref2:
case DW_FORM_data2:
+ case DW_FORM_strx2:
return start + 2;
+ case DW_FORM_addrx3:
+ case DW_FORM_strx3:
+ return start + 3;
+ case DW_FORM_addrx4:
case DW_FORM_ref4:
case DW_FORM_data4:
+ case DW_FORM_strx4:
+ case DW_FORM_ref_sup4:
return start + 4;
case DW_FORM_ref8:
case DW_FORM_data8:
case DW_FORM_ref_sig8:
+ case DW_FORM_ref_sup8:
return start + 8;
+ case DW_FORM_data16:
+ return start + 16;
case DW_FORM_string:
- return start + strlen(reinterpret_cast<const char *>(start)) + 1;
+ return start + strlen(reinterpret_cast<const char*>(start)) + 1;
case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_strx:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_addr_index:
+ case DW_FORM_addrx:
+ case DW_FORM_rnglistx:
+ case DW_FORM_loclistx:
reader_->ReadUnsignedLEB128(start, &len);
return start + len;
@@ -237,6 +281,8 @@ const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
return start + size + len;
}
case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ case DW_FORM_strp_sup:
case DW_FORM_sec_offset:
return start + reader_->OffsetSize();
}
@@ -244,13 +290,52 @@ const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
return NULL;
}
-// Read a DWARF2/3 header.
-// The header is variable length in DWARF3 (and DWARF2 as extended by
-// most compilers), and consists of an length field, a version number,
-// the offset in the .debug_abbrev section for our abbrevs, and an
-// address size.
+// Read the abbreviation offset from a compilation unit header.
+size_t CompilationUnit::ReadAbbrevOffset(const uint8_t* headerptr) {
+ assert(headerptr + reader_->OffsetSize() < buffer_ + buffer_length_);
+ header_.abbrev_offset = reader_->ReadOffset(headerptr);
+ return reader_->OffsetSize();
+}
+
+// Read the address size from a compilation unit header.
+size_t CompilationUnit::ReadAddressSize(const uint8_t* headerptr) {
+ // Compare against less than or equal because this may be the last
+ // section in the file.
+ assert(headerptr + 1 <= buffer_ + buffer_length_);
+ header_.address_size = reader_->ReadOneByte(headerptr);
+ reader_->SetAddressSize(header_.address_size);
+ return 1;
+}
+
+// Read the DWO id from a split or skeleton compilation unit header.
+size_t CompilationUnit::ReadDwoId(const uint8_t* headerptr) {
+ assert(headerptr + 8 <= buffer_ + buffer_length_);
+ dwo_id_ = reader_->ReadEightBytes(headerptr);
+ return 8;
+}
+
+// Read the type signature from a type or split type compilation unit header.
+size_t CompilationUnit::ReadTypeSignature(const uint8_t* headerptr) {
+ assert(headerptr + 8 <= buffer_ + buffer_length_);
+ type_signature_ = reader_->ReadEightBytes(headerptr);
+ return 8;
+}
+
+// Read the DWO id from a split or skeleton compilation unit header.
+size_t CompilationUnit::ReadTypeOffset(const uint8_t* headerptr) {
+ assert(headerptr + reader_->OffsetSize() < buffer_ + buffer_length_);
+ type_offset_ = reader_->ReadOffset(headerptr);
+ return reader_->OffsetSize();
+}
+
+
+// Read a DWARF header. The header is variable length in DWARF3 and DWARF4
+// (and DWARF2 as extended by most compilers), and consists of an length
+// field, a version number, the offset in the .debug_abbrev section for our
+// abbrevs, and an address size. DWARF5 adds a unit_type to distinguish
+// between partial-, full-, skeleton-, split-, and type- compilation units.
void CompilationUnit::ReadHeader() {
- const uint8_t *headerptr = buffer_;
+ const uint8_t* headerptr = buffer_;
size_t initial_length_size;
assert(headerptr + 4 < buffer_ + buffer_length_);
@@ -263,17 +348,37 @@ void CompilationUnit::ReadHeader() {
header_.version = reader_->ReadTwoBytes(headerptr);
headerptr += 2;
- assert(headerptr + reader_->OffsetSize() < buffer_ + buffer_length_);
- header_.abbrev_offset = reader_->ReadOffset(headerptr);
- headerptr += reader_->OffsetSize();
-
- // Compare against less than or equal because this may be the last
- // section in the file.
- assert(headerptr + 1 <= buffer_ + buffer_length_);
- header_.address_size = reader_->ReadOneByte(headerptr);
- reader_->SetAddressSize(header_.address_size);
- headerptr += 1;
-
+ if (header_.version <= 4) {
+ // Older versions of dwarf have a relatively simple structure.
+ headerptr += ReadAbbrevOffset(headerptr);
+ headerptr += ReadAddressSize(headerptr);
+ } else {
+ // DWARF5 adds a unit_type field, and various fields based on unit_type.
+ assert(headerptr + 1 < buffer_ + buffer_length_);
+ uint8_t unit_type = reader_->ReadOneByte(headerptr);
+ headerptr += 1;
+ headerptr += ReadAddressSize(headerptr);
+ headerptr += ReadAbbrevOffset(headerptr);
+ switch (unit_type) {
+ case DW_UT_compile:
+ case DW_UT_partial:
+ // nothing else to read
+ break;
+ case DW_UT_skeleton:
+ case DW_UT_split_compile:
+ headerptr += ReadDwoId(headerptr);
+ break;
+ case DW_UT_type:
+ case DW_UT_split_type:
+ is_type_unit_ = true;
+ headerptr += ReadTypeSignature(headerptr);
+ headerptr += ReadTypeOffset(headerptr);
+ break;
+ default:
+ fprintf(stderr, "Unhandled compilation unit type 0x%x", unit_type);
+ break;
+ }
+ }
after_header_ = headerptr;
// This check ensures that we don't have to do checking during the
@@ -284,12 +389,9 @@ void CompilationUnit::ReadHeader() {
}
uint64_t CompilationUnit::Start() {
- // First get the debug_info section. ".debug_info" is the name
- // recommended in the DWARF spec, and used on Linux; "__debug_info"
- // is the name used in Mac OS X Mach-O files.
- SectionMap::const_iterator iter = sections_.find(".debug_info");
- if (iter == sections_.end())
- iter = sections_.find("__debug_info");
+ // First get the debug_info section.
+ SectionMap::const_iterator iter =
+ GetSectionByName(sections_, ".debug_info");
assert(iter != sections_.end());
// Set up our buffer
@@ -315,30 +417,35 @@ uint64_t CompilationUnit::Start() {
header_.length,
header_.version))
return ourlength;
+ else if (header_.version == 5 && is_type_unit_)
+ return ourlength;
// Otherwise, continue by reading our abbreviation entries.
ReadAbbrevs();
- // Set the string section if we have one. ".debug_str" is the name
- // recommended in the DWARF spec, and used on Linux; "__debug_str"
- // is the name used in Mac OS X Mach-O files.
- iter = sections_.find(".debug_str");
- if (iter == sections_.end())
- iter = sections_.find("__debug_str");
+ // Set the string section if we have one.
+ iter = GetSectionByName(sections_, ".debug_str");
if (iter != sections_.end()) {
string_buffer_ = iter->second.first;
string_buffer_length_ = iter->second.second;
}
+ // Set the line string section if we have one.
+ iter = GetSectionByName(sections_, ".debug_line_str");
+ if (iter != sections_.end()) {
+ line_string_buffer_ = iter->second.first;
+ line_string_buffer_length_ = iter->second.second;
+ }
+
// Set the string offsets section if we have one.
- iter = sections_.find(".debug_str_offsets");
+ iter = GetSectionByName(sections_, ".debug_str_offsets");
if (iter != sections_.end()) {
str_offsets_buffer_ = iter->second.first;
str_offsets_buffer_length_ = iter->second.second;
}
// Set the address section if we have one.
- iter = sections_.find(".debug_addr");
+ iter = GetSectionByName(sections_, ".debug_addr");
if (iter != sections_.end()) {
addr_buffer_ = iter->second.first;
addr_buffer_length_ = iter->second.second;
@@ -358,12 +465,189 @@ uint64_t CompilationUnit::Start() {
return ourlength;
}
+void CompilationUnit::ProcessFormStringIndex(
+ uint64_t dieoffset, enum DwarfAttribute attr, enum DwarfForm form,
+ uint64_t str_index) {
+ const size_t kStringOffsetsTableHeaderSize =
+ header_.version >= 5 ? (reader_->OffsetSize() == 8 ? 16 : 8) : 0;
+ const uint8_t* str_offsets_table_after_header = str_offsets_base_ ?
+ str_offsets_buffer_ + str_offsets_base_ :
+ str_offsets_buffer_ + kStringOffsetsTableHeaderSize;
+ const uint8_t* offset_ptr =
+ str_offsets_table_after_header + str_index * reader_->OffsetSize();
+
+ const uint64_t offset = reader_->ReadOffset(offset_ptr);
+ if (offset >= string_buffer_length_) {
+ return;
+ }
+
+ const char* str = reinterpret_cast<const char*>(string_buffer_) + offset;
+ ProcessAttributeString(dieoffset, attr, form, str);
+}
+
+// Special function for pre-processing the
+// DW_AT_str_offsets_base and DW_AT_addr_base in a DW_TAG_compile_unit die (for
+// DWARF v5). We must make sure to find and process the
+// DW_AT_str_offsets_base and DW_AT_addr_base attributes before attempting to
+// read any string and address attribute in the compile unit.
+const uint8_t* CompilationUnit::ProcessOffsetBaseAttribute(
+ uint64_t dieoffset, const uint8_t* start, enum DwarfAttribute attr,
+ enum DwarfForm form, uint64_t implicit_const) {
+ size_t len;
+
+ switch (form) {
+ // DW_FORM_indirect is never used because it is such a space
+ // waster.
+ case DW_FORM_indirect:
+ form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start,
+ &len));
+ start += len;
+ return ProcessOffsetBaseAttribute(dieoffset, start, attr, form,
+ implicit_const);
+
+ case DW_FORM_flag_present:
+ return start;
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ return start + 1;
+ case DW_FORM_data2:
+ return start + 2;
+ case DW_FORM_data4:
+ return start + 4;
+ case DW_FORM_data8:
+ return start + 8;
+ case DW_FORM_data16:
+ // This form is designed for an md5 checksum inside line tables.
+ return start + 16;
+ case DW_FORM_string: {
+ const char* str = reinterpret_cast<const char*>(start);
+ return start + strlen(str) + 1;
+ }
+ case DW_FORM_udata:
+ reader_->ReadUnsignedLEB128(start, &len);
+ return start + len;
+ case DW_FORM_sdata:
+ reader_->ReadSignedLEB128(start, &len);
+ return start + len;
+ case DW_FORM_addr:
+ reader_->ReadAddress(start);
+ return start + reader_->AddressSize();
+
+ // This is the important one here!
+ case DW_FORM_sec_offset:
+ if (attr == DW_AT_str_offsets_base ||
+ attr == DW_AT_addr_base)
+ ProcessAttributeUnsigned(dieoffset, attr, form,
+ reader_->ReadOffset(start));
+ else
+ reader_->ReadOffset(start);
+ return start + reader_->OffsetSize();
+
+ case DW_FORM_ref1:
+ return start + 1;
+ case DW_FORM_ref2:
+ return start + 2;
+ case DW_FORM_ref4:
+ return start + 4;
+ case DW_FORM_ref8:
+ return start + 8;
+ case DW_FORM_ref_udata:
+ reader_->ReadUnsignedLEB128(start, &len);
+ return start + len;
+ case DW_FORM_ref_addr:
+ // DWARF2 and 3/4 differ on whether ref_addr is address size or
+ // offset size.
+ assert(header_.version >= 2);
+ if (header_.version == 2) {
+ reader_->ReadAddress(start);
+ return start + reader_->AddressSize();
+ } else if (header_.version >= 3) {
+ reader_->ReadOffset(start);
+ return start + reader_->OffsetSize();
+ }
+ break;
+ case DW_FORM_ref_sig8:
+ return start + 8;
+ case DW_FORM_implicit_const:
+ return start;
+ case DW_FORM_block1: {
+ uint64_t datalen = reader_->ReadOneByte(start);
+ return start + 1 + datalen;
+ }
+ case DW_FORM_block2: {
+ uint64_t datalen = reader_->ReadTwoBytes(start);
+ return start + 2 + datalen;
+ }
+ case DW_FORM_block4: {
+ uint64_t datalen = reader_->ReadFourBytes(start);
+ return start + 4 + datalen;
+ }
+ case DW_FORM_block:
+ case DW_FORM_exprloc: {
+ uint64_t datalen = reader_->ReadUnsignedLEB128(start, &len);
+ return start + datalen + len;
+ }
+ case DW_FORM_strp: {
+ reader_->ReadOffset(start);
+ return start + reader_->OffsetSize();
+ }
+ case DW_FORM_line_strp: {
+ reader_->ReadOffset(start);
+ return start + reader_->OffsetSize();
+ }
+ case DW_FORM_strp_sup:
+ return start + 4;
+ case DW_FORM_ref_sup4:
+ return start + 4;
+ case DW_FORM_ref_sup8:
+ return start + 8;
+ case DW_FORM_loclistx:
+ reader_->ReadUnsignedLEB128(start, &len);
+ return start + len;
+ case DW_FORM_strx:
+ case DW_FORM_GNU_str_index: {
+ reader_->ReadUnsignedLEB128(start, &len);
+ return start + len;
+ }
+ case DW_FORM_strx1: {
+ return start + 1;
+ }
+ case DW_FORM_strx2: {
+ return start + 2;
+ }
+ case DW_FORM_strx3: {
+ return start + 3;
+ }
+ case DW_FORM_strx4: {
+ return start + 4;
+ }
+
+ case DW_FORM_addrx:
+ case DW_FORM_GNU_addr_index:
+ reader_->ReadUnsignedLEB128(start, &len);
+ return start + len;
+ case DW_FORM_addrx1:
+ return start + 1;
+ case DW_FORM_addrx2:
+ return start + 2;
+ case DW_FORM_addrx3:
+ return start + 3;
+ case DW_FORM_addrx4:
+ return start + 4;
+ case DW_FORM_rnglistx:
+ reader_->ReadUnsignedLEB128(start, &len);
+ return start + len;
+ }
+ fprintf(stderr, "Unhandled form type\n");
+ return NULL;
+}
+
// If one really wanted, you could merge SkipAttribute and
// ProcessAttribute
// This is all boring data manipulation and calling of the handler.
-const uint8_t *CompilationUnit::ProcessAttribute(
- uint64_t dieoffset, const uint8_t *start, enum DwarfAttribute attr,
- enum DwarfForm form) {
+const uint8_t* CompilationUnit::ProcessAttribute(
+ uint64_t dieoffset, const uint8_t* start, enum DwarfAttribute attr,
+ enum DwarfForm form, uint64_t implicit_const) {
size_t len;
switch (form) {
@@ -373,7 +657,7 @@ const uint8_t *CompilationUnit::ProcessAttribute(
form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start,
&len));
start += len;
- return ProcessAttribute(dieoffset, start, attr, form);
+ return ProcessAttribute(dieoffset, start, attr, form, implicit_const);
case DW_FORM_flag_present:
ProcessAttributeUnsigned(dieoffset, attr, form, 1);
@@ -395,8 +679,12 @@ const uint8_t *CompilationUnit::ProcessAttribute(
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadEightBytes(start));
return start + 8;
+ case DW_FORM_data16:
+ // This form is designed for an md5 checksum inside line tables.
+ fprintf(stderr, "Unhandled form type: DW_FORM_data16\n");
+ return start + 16;
case DW_FORM_string: {
- const char *str = reinterpret_cast<const char *>(start);
+ const char* str = reinterpret_cast<const char*>(start);
ProcessAttributeString(dieoffset, attr, form, str);
return start + strlen(str) + 1;
}
@@ -462,7 +750,10 @@ const uint8_t *CompilationUnit::ProcessAttribute(
handler_->ProcessAttributeSignature(dieoffset, attr, form,
reader_->ReadEightBytes(start));
return start + 8;
-
+ case DW_FORM_implicit_const:
+ handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
+ implicit_const);
+ return start;
case DW_FORM_block1: {
uint64_t datalen = reader_->ReadOneByte(start);
handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 1,
@@ -494,45 +785,118 @@ const uint8_t *CompilationUnit::ProcessAttribute(
const uint64_t offset = reader_->ReadOffset(start);
assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_);
- const char *str = reinterpret_cast<const char *>(string_buffer_ + offset);
+ const char* str = reinterpret_cast<const char*>(string_buffer_ + offset);
ProcessAttributeString(dieoffset, attr, form, str);
return start + reader_->OffsetSize();
}
+ case DW_FORM_line_strp: {
+ assert(line_string_buffer_ != NULL);
- case DW_FORM_GNU_str_index: {
- uint64_t str_index = reader_->ReadUnsignedLEB128(start, &len);
- const uint8_t* offset_ptr =
- str_offsets_buffer_ + str_index * reader_->OffsetSize();
- const uint64_t offset = reader_->ReadOffset(offset_ptr);
- if (offset >= string_buffer_length_) {
- return NULL;
- }
+ const uint64_t offset = reader_->ReadOffset(start);
+ assert(line_string_buffer_ + offset <
+ line_string_buffer_ + line_string_buffer_length_);
- const char* str = reinterpret_cast<const char *>(string_buffer_) + offset;
+ const char* str =
+ reinterpret_cast<const char*>(line_string_buffer_ + offset);
ProcessAttributeString(dieoffset, attr, form, str);
- return start + len;
- break;
+ return start + reader_->OffsetSize();
}
- case DW_FORM_GNU_addr_index: {
- uint64_t addr_index = reader_->ReadUnsignedLEB128(start, &len);
- const uint8_t* addr_ptr =
- addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize();
+ case DW_FORM_strp_sup:
+ // No support currently for suplementary object files.
+ fprintf(stderr, "Unhandled form type: DW_FORM_strp_sup\n");
+ return start + 4;
+ case DW_FORM_ref_sup4:
+ // No support currently for suplementary object files.
+ fprintf(stderr, "Unhandled form type: DW_FORM_ref_sup4\n");
+ return start + 4;
+ case DW_FORM_ref_sup8:
+ // No support currently for suplementary object files.
+ fprintf(stderr, "Unhandled form type: DW_FORM_ref_sup8\n");
+ return start + 8;
+ case DW_FORM_loclistx:
ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadAddress(addr_ptr));
+ reader_->ReadUnsignedLEB128(start, &len));
return start + len;
+ case DW_FORM_strx:
+ case DW_FORM_GNU_str_index: {
+ uint64_t str_index = reader_->ReadUnsignedLEB128(start, &len);
+ ProcessFormStringIndex(dieoffset, attr, form, str_index);
+ return start + len;
+ }
+ case DW_FORM_strx1: {
+ uint64_t str_index = reader_->ReadOneByte(start);
+ ProcessFormStringIndex(dieoffset, attr, form, str_index);
+ return start + 1;
+ }
+ case DW_FORM_strx2: {
+ uint64_t str_index = reader_->ReadTwoBytes(start);
+ ProcessFormStringIndex(dieoffset, attr, form, str_index);
+ return start + 2;
+ }
+ case DW_FORM_strx3: {
+ uint64_t str_index = reader_->ReadThreeBytes(start);
+ ProcessFormStringIndex(dieoffset, attr, form, str_index);
+ return start + 3;
+ }
+ case DW_FORM_strx4: {
+ uint64_t str_index = reader_->ReadFourBytes(start);
+ ProcessFormStringIndex(dieoffset, attr, form, str_index);
+ return start + 4;
}
+
+ case DW_FORM_addrx:
+ case DW_FORM_GNU_addr_index:
+ ProcessAttributeAddrIndex(
+ dieoffset, attr, form, reader_->ReadUnsignedLEB128(start, &len));
+ return start + len;
+ case DW_FORM_addrx1:
+ ProcessAttributeAddrIndex(
+ dieoffset, attr, form, reader_->ReadOneByte(start));
+ return start + 1;
+ case DW_FORM_addrx2:
+ ProcessAttributeAddrIndex(
+ dieoffset, attr, form, reader_->ReadTwoBytes(start));
+ return start + 2;
+ case DW_FORM_addrx3:
+ ProcessAttributeAddrIndex(
+ dieoffset, attr, form, reader_->ReadThreeBytes(start));
+ return start + 3;
+ case DW_FORM_addrx4:
+ ProcessAttributeAddrIndex(
+ dieoffset, attr, form, reader_->ReadFourBytes(start));
+ return start + 4;
+ case DW_FORM_rnglistx:
+ ProcessAttributeUnsigned(
+ dieoffset, attr, form, reader_->ReadUnsignedLEB128(start, &len));
+ return start + len;
}
fprintf(stderr, "Unhandled form type\n");
return NULL;
}
-const uint8_t *CompilationUnit::ProcessDIE(uint64_t dieoffset,
- const uint8_t *start,
+const uint8_t* CompilationUnit::ProcessDIE(uint64_t dieoffset,
+ const uint8_t* start,
const Abbrev& abbrev) {
+ // With DWARF v5, the compile_unit die may contain a
+ // DW_AT_str_offsets_base or DW_AT_addr_base. If it does, that attribute must
+ // be found and processed before trying to process the other attributes;
+ // otherwise the string or address values will all come out incorrect.
+ if (abbrev.tag == DW_TAG_compile_unit && header_.version == 5) {
+ uint64_t dieoffset_copy = dieoffset;
+ const uint8_t* start_copy = start;
+ for (AttributeList::const_iterator i = abbrev.attributes.begin();
+ i != abbrev.attributes.end();
+ i++) {
+ start_copy = ProcessOffsetBaseAttribute(dieoffset_copy, start_copy,
+ i->attr_, i->form_,
+ i->value_);
+ }
+ }
+
for (AttributeList::const_iterator i = abbrev.attributes.begin();
i != abbrev.attributes.end();
i++) {
- start = ProcessAttribute(dieoffset, start, i->first, i->second);
+ start = ProcessAttribute(dieoffset, start, i->attr_, i->form_, i->value_);
}
// If this is a compilation unit in a split DWARF object, verify that
@@ -548,12 +912,12 @@ const uint8_t *CompilationUnit::ProcessDIE(uint64_t dieoffset,
}
void CompilationUnit::ProcessDIEs() {
- const uint8_t *dieptr = after_header_;
+ const uint8_t* dieptr = after_header_;
size_t len;
// lengthstart is the place the length field is based on.
// It is the point in the header after the initial length field
- const uint8_t *lengthstart = buffer_;
+ const uint8_t* lengthstart = buffer_;
// In 64 bit dwarf, the initial length is 12 bytes, because of the
// 0xffffffff at the start.
@@ -563,7 +927,7 @@ void CompilationUnit::ProcessDIEs() {
lengthstart += 4;
std::stack<uint64_t> die_stack;
-
+
while (dieptr < (lengthstart + header_.length)) {
// We give the user the absolute offset from the beginning of
// debug_info, since they need it to deal with ref_addr forms.
@@ -589,8 +953,23 @@ void CompilationUnit::ProcessDIEs() {
const enum DwarfTag tag = abbrev.tag;
if (!handler_->StartDIE(absolute_offset, tag)) {
dieptr = SkipDIE(dieptr, abbrev);
+ if (!dieptr) {
+ fprintf(stderr,
+ "An error happens when skipping a DIE's attributes at offset "
+ "0x%" PRIx64
+ ". Stopped processing following DIEs in this CU.\n",
+ absolute_offset);
+ exit(1);
+ }
} else {
dieptr = ProcessDIE(absolute_offset, dieptr, abbrev);
+ if (!dieptr) {
+ fprintf(stderr,
+ "An error happens when processing a DIE at offset 0x%" PRIx64
+ ". Stopped processing following DIEs in this CU.\n",
+ absolute_offset);
+ exit(1);
+ }
}
if (abbrev.has_children) {
@@ -691,7 +1070,7 @@ void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader,
if (section_data != NULL)
sections->insert(std::make_pair(
base_name, std::make_pair(
- reinterpret_cast<const uint8_t *>(section_data),
+ reinterpret_cast<const uint8_t*>(section_data),
section_size)));
}
}
@@ -720,11 +1099,11 @@ void DwpReader::Initialize() {
&string_buffer_size_);
version_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_));
+ reinterpret_cast<const uint8_t*>(cu_index_));
if (version_ == 1) {
nslots_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_)
+ reinterpret_cast<const uint8_t*>(cu_index_)
+ 3 * sizeof(uint32_t));
phash_ = cu_index_ + 4 * sizeof(uint32_t);
pindex_ = phash_ + nslots_ * sizeof(uint64_t);
@@ -732,13 +1111,13 @@ void DwpReader::Initialize() {
if (shndx_pool_ >= cu_index_ + cu_index_size_) {
version_ = 0;
}
- } else if (version_ == 2) {
+ } else if (version_ == 2 || version_ == 5) {
ncolumns_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_) + sizeof(uint32_t));
+ reinterpret_cast<const uint8_t*>(cu_index_) + sizeof(uint32_t));
nunits_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_) + 2 * sizeof(uint32_t));
+ reinterpret_cast<const uint8_t*>(cu_index_) + 2 * sizeof(uint32_t));
nslots_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_) + 3 * sizeof(uint32_t));
+ reinterpret_cast<const uint8_t*>(cu_index_) + 3 * sizeof(uint32_t));
phash_ = cu_index_ + 4 * sizeof(uint32_t);
pindex_ = phash_ + nslots_ * sizeof(uint64_t);
offset_table_ = pindex_ + nslots_ * sizeof(uint32_t);
@@ -766,7 +1145,7 @@ void DwpReader::ReadDebugSectionsForCU(uint64_t dwo_id,
// can read a list of section indexes for the debug sections
// for the CU whose dwo_id we are looking for.
int index = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(pindex_)
+ reinterpret_cast<const uint8_t*>(pindex_)
+ slot * sizeof(uint32_t));
const char* shndx_list = shndx_pool_ + index * sizeof(uint32_t);
for (;;) {
@@ -775,7 +1154,7 @@ void DwpReader::ReadDebugSectionsForCU(uint64_t dwo_id,
return;
}
unsigned int shndx = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(shndx_list));
+ reinterpret_cast<const uint8_t*>(shndx_list));
shndx_list += sizeof(uint32_t);
if (shndx == 0)
break;
@@ -789,28 +1168,28 @@ void DwpReader::ReadDebugSectionsForCU(uint64_t dwo_id,
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_abbrev",
- std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
+ std::make_pair(reinterpret_cast<const uint8_t*> (section_data),
section_size)));
} else if (!strncmp(section_name, ".debug_info", strlen(".debug_info"))) {
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_info",
- std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
+ std::make_pair(reinterpret_cast<const uint8_t*> (section_data),
section_size)));
} else if (!strncmp(section_name, ".debug_str_offsets",
strlen(".debug_str_offsets"))) {
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_str_offsets",
- std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
+ std::make_pair(reinterpret_cast<const uint8_t*> (section_data),
section_size)));
}
}
sections->insert(std::make_pair(
".debug_str",
- std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
+ std::make_pair(reinterpret_cast<const uint8_t*> (string_buffer_),
string_buffer_size_)));
- } else if (version_ == 2) {
+ } else if (version_ == 2 || version_ == 5) {
uint32_t index = LookupCUv2(dwo_id);
if (index == 0) {
return;
@@ -833,33 +1212,33 @@ void DwpReader::ReadDebugSectionsForCU(uint64_t dwo_id,
}
for (unsigned int col = 0u; col < ncolumns_; ++col) {
uint32_t section_id =
- byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(id_row)
+ byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t*>(id_row)
+ col * sizeof(uint32_t));
uint32_t offset = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(offset_row)
+ reinterpret_cast<const uint8_t*>(offset_row)
+ col * sizeof(uint32_t));
uint32_t size = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(size_row) + col * sizeof(uint32_t));
+ reinterpret_cast<const uint8_t*>(size_row) + col * sizeof(uint32_t));
if (section_id == DW_SECT_ABBREV) {
sections->insert(std::make_pair(
".debug_abbrev",
- std::make_pair(reinterpret_cast<const uint8_t *> (abbrev_data_)
+ std::make_pair(reinterpret_cast<const uint8_t*> (abbrev_data_)
+ offset, size)));
} else if (section_id == DW_SECT_INFO) {
sections->insert(std::make_pair(
".debug_info",
- std::make_pair(reinterpret_cast<const uint8_t *> (info_data_)
+ std::make_pair(reinterpret_cast<const uint8_t*> (info_data_)
+ offset, size)));
} else if (section_id == DW_SECT_STR_OFFSETS) {
sections->insert(std::make_pair(
".debug_str_offsets",
- std::make_pair(reinterpret_cast<const uint8_t *> (str_offsets_data_)
+ std::make_pair(reinterpret_cast<const uint8_t*> (str_offsets_data_)
+ offset, size)));
}
}
sections->insert(std::make_pair(
".debug_str",
- std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
+ std::make_pair(reinterpret_cast<const uint8_t*> (string_buffer_),
string_buffer_size_)));
}
}
@@ -867,14 +1246,14 @@ void DwpReader::ReadDebugSectionsForCU(uint64_t dwo_id,
int DwpReader::LookupCU(uint64_t dwo_id) {
uint32_t slot = static_cast<uint32_t>(dwo_id) & (nslots_ - 1);
uint64_t probe = byte_reader_.ReadEightBytes(
- reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64_t));
+ reinterpret_cast<const uint8_t*>(phash_) + slot * sizeof(uint64_t));
if (probe != 0 && probe != dwo_id) {
uint32_t secondary_hash =
(static_cast<uint32_t>(dwo_id >> 32) & (nslots_ - 1)) | 1;
do {
slot = (slot + secondary_hash) & (nslots_ - 1);
probe = byte_reader_.ReadEightBytes(
- reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64_t));
+ reinterpret_cast<const uint8_t*>(phash_) + slot * sizeof(uint64_t));
} while (probe != 0 && probe != dwo_id);
}
if (probe == 0)
@@ -885,28 +1264,35 @@ int DwpReader::LookupCU(uint64_t dwo_id) {
uint32_t DwpReader::LookupCUv2(uint64_t dwo_id) {
uint32_t slot = static_cast<uint32_t>(dwo_id) & (nslots_ - 1);
uint64_t probe = byte_reader_.ReadEightBytes(
- reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64_t));
+ reinterpret_cast<const uint8_t*>(phash_) + slot * sizeof(uint64_t));
uint32_t index = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32_t));
+ reinterpret_cast<const uint8_t*>(pindex_) + slot * sizeof(uint32_t));
if (index != 0 && probe != dwo_id) {
uint32_t secondary_hash =
(static_cast<uint32_t>(dwo_id >> 32) & (nslots_ - 1)) | 1;
do {
slot = (slot + secondary_hash) & (nslots_ - 1);
probe = byte_reader_.ReadEightBytes(
- reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64_t));
+ reinterpret_cast<const uint8_t*>(phash_) + slot * sizeof(uint64_t));
index = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32_t));
+ reinterpret_cast<const uint8_t*>(pindex_) + slot * sizeof(uint32_t));
} while (index != 0 && probe != dwo_id);
}
return index;
}
-LineInfo::LineInfo(const uint8_t *buffer, uint64_t buffer_length,
- ByteReader* reader, LineInfoHandler* handler):
- handler_(handler), reader_(reader), buffer_(buffer) {
+LineInfo::LineInfo(const uint8_t* buffer, uint64_t buffer_length,
+ ByteReader* reader, const uint8_t* string_buffer,
+ size_t string_buffer_length,
+ const uint8_t* line_string_buffer,
+ size_t line_string_buffer_length, LineInfoHandler* handler):
+ handler_(handler), reader_(reader), buffer_(buffer),
+ string_buffer_(string_buffer),
+ line_string_buffer_(line_string_buffer) {
#ifndef NDEBUG
buffer_length_ = buffer_length;
+ string_buffer_length_ = string_buffer_length;
+ line_string_buffer_length_ = line_string_buffer_length;
#endif
header_.std_opcode_lengths = NULL;
}
@@ -917,10 +1303,132 @@ uint64_t LineInfo::Start() {
return after_header_ - buffer_;
}
+void LineInfo::ReadTypesAndForms(const uint8_t** lineptr,
+ uint32_t* content_types,
+ uint32_t* content_forms,
+ uint32_t max_types,
+ uint32_t* format_count) {
+ size_t len;
+
+ uint32_t count = reader_->ReadUnsignedLEB128(*lineptr, &len);
+ *lineptr += len;
+ if (count < 1 || count > max_types) {
+ return;
+ }
+ for (uint32_t col = 0; col < count; ++col) {
+ content_types[col] = reader_->ReadUnsignedLEB128(*lineptr, &len);
+ *lineptr += len;
+ content_forms[col] = reader_->ReadUnsignedLEB128(*lineptr, &len);
+ *lineptr += len;
+ }
+ *format_count = count;
+}
+
+const char* LineInfo::ReadStringForm(uint32_t form, const uint8_t** lineptr) {
+ const char* name = nullptr;
+ if (form == DW_FORM_string) {
+ name = reinterpret_cast<const char*>(*lineptr);
+ *lineptr += strlen(name) + 1;
+ return name;
+ } else if (form == DW_FORM_strp) {
+ uint64_t offset = reader_->ReadOffset(*lineptr);
+ assert(offset < string_buffer_length_);
+ *lineptr += reader_->OffsetSize();
+ if (string_buffer_ != nullptr) {
+ name = reinterpret_cast<const char*>(string_buffer_) + offset;
+ return name;
+ }
+ } else if (form == DW_FORM_line_strp) {
+ uint64_t offset = reader_->ReadOffset(*lineptr);
+ assert(offset < line_string_buffer_length_);
+ *lineptr += reader_->OffsetSize();
+ if (line_string_buffer_ != nullptr) {
+ name = reinterpret_cast<const char*>(line_string_buffer_) + offset;
+ return name;
+ }
+ }
+ // Shouldn't be called with a non-string-form, and
+ // if there is a string form but no string buffer,
+ // that is a problem too.
+ assert(0);
+ return nullptr;
+}
+
+uint64_t LineInfo::ReadUnsignedData(uint32_t form, const uint8_t** lineptr) {
+ size_t len;
+ uint64_t value;
+
+ switch (form) {
+ case DW_FORM_data1:
+ value = reader_->ReadOneByte(*lineptr);
+ *lineptr += 1;
+ return value;
+ case DW_FORM_data2:
+ value = reader_->ReadTwoBytes(*lineptr);
+ *lineptr += 2;
+ return value;
+ case DW_FORM_data4:
+ value = reader_->ReadFourBytes(*lineptr);
+ *lineptr += 4;
+ return value;
+ case DW_FORM_data8:
+ value = reader_->ReadEightBytes(*lineptr);
+ *lineptr += 8;
+ return value;
+ case DW_FORM_udata:
+ value = reader_->ReadUnsignedLEB128(*lineptr, &len);
+ *lineptr += len;
+ return value;
+ default:
+ fprintf(stderr, "Unrecognized data form.");
+ return 0;
+ }
+}
+
+void LineInfo::ReadFileRow(const uint8_t** lineptr,
+ const uint32_t* content_types,
+ const uint32_t* content_forms, uint32_t row,
+ uint32_t format_count) {
+ const char* filename = nullptr;
+ uint64_t dirindex = 0;
+ uint64_t mod_time = 0;
+ uint64_t filelength = 0;
+
+ for (uint32_t col = 0; col < format_count; ++col) {
+ switch (content_types[col]) {
+ case DW_LNCT_path:
+ filename = ReadStringForm(content_forms[col], lineptr);
+ break;
+ case DW_LNCT_directory_index:
+ dirindex = ReadUnsignedData(content_forms[col], lineptr);
+ break;
+ case DW_LNCT_timestamp:
+ mod_time = ReadUnsignedData(content_forms[col], lineptr);
+ break;
+ case DW_LNCT_size:
+ filelength = ReadUnsignedData(content_forms[col], lineptr);
+ break;
+ case DW_LNCT_MD5:
+ // MD5 entries help a debugger sort different versions of files with
+ // the same name. It is always paired with a DW_FORM_data16 and is
+ // unused in this case.
+ *lineptr += 16;
+ break;
+ default:
+ fprintf(stderr, "Unrecognized form in line table header. %d\n",
+ content_types[col]);
+ assert(false);
+ break;
+ }
+ }
+ assert(filename != nullptr);
+ handler_->DefineFile(filename, row, dirindex, mod_time, filelength);
+}
+
// The header for a debug_line section is mildly complicated, because
// the line info is very tightly encoded.
void LineInfo::ReadHeader() {
- const uint8_t *lineptr = buffer_;
+ const uint8_t* lineptr = buffer_;
size_t initial_length_size;
const uint64_t initial_length
@@ -931,12 +1439,24 @@ void LineInfo::ReadHeader() {
assert(buffer_ + initial_length_size + header_.total_length <=
buffer_ + buffer_length_);
- // Address size *must* be set by CU ahead of time.
- assert(reader_->AddressSize() != 0);
header_.version = reader_->ReadTwoBytes(lineptr);
lineptr += 2;
+ if (header_.version >= 5) {
+ uint8_t address_size = reader_->ReadOneByte(lineptr);
+ reader_->SetAddressSize(address_size);
+ lineptr += 1;
+ uint8_t segment_selector_size = reader_->ReadOneByte(lineptr);
+ if (segment_selector_size != 0) {
+ fprintf(stderr,"No support for segmented memory.");
+ }
+ lineptr += 1;
+ } else {
+ // Address size *must* be set by CU ahead of time.
+ assert(reader_->AddressSize() != 0);
+ }
+
header_.prologue_length = reader_->ReadOffset(lineptr);
lineptr += reader_->OffsetSize();
@@ -970,53 +1490,96 @@ void LineInfo::ReadHeader() {
lineptr += 1;
}
- // It is legal for the directory entry table to be empty.
- if (*lineptr) {
- uint32_t dirindex = 1;
- while (*lineptr) {
- const char *dirname = reinterpret_cast<const char *>(lineptr);
- handler_->DefineDir(dirname, dirindex);
- lineptr += strlen(dirname) + 1;
- dirindex++;
+ if (header_.version <= 4) {
+ // Directory zero is assumed to be the compilation directory and special
+ // cased where used. It is not actually stored in the dwarf data. But an
+ // empty entry here avoids off-by-one errors elsewhere in the code.
+ handler_->DefineDir("", 0);
+ // It is legal for the directory entry table to be empty.
+ if (*lineptr) {
+ uint32_t dirindex = 1;
+ while (*lineptr) {
+ const char* dirname = reinterpret_cast<const char*>(lineptr);
+ handler_->DefineDir(dirname, dirindex);
+ lineptr += strlen(dirname) + 1;
+ dirindex++;
+ }
}
- }
- lineptr++;
-
- // It is also legal for the file entry table to be empty.
- if (*lineptr) {
- uint32_t fileindex = 1;
+ lineptr++;
+ // It is also legal for the file entry table to be empty.
+
+ // Similarly for file zero.
+ handler_->DefineFile("", 0, 0, 0, 0);
+ if (*lineptr) {
+ uint32_t fileindex = 1;
+ size_t len;
+ while (*lineptr) {
+ const char* filename = ReadStringForm(DW_FORM_string, &lineptr);
+
+ uint64_t dirindex = reader_->ReadUnsignedLEB128(lineptr, &len);
+ lineptr += len;
+
+ uint64_t mod_time = reader_->ReadUnsignedLEB128(lineptr, &len);
+ lineptr += len;
+
+ uint64_t filelength = reader_->ReadUnsignedLEB128(lineptr, &len);
+ lineptr += len;
+ handler_->DefineFile(filename, fileindex,
+ static_cast<uint32_t>(dirindex), mod_time,
+ filelength);
+ fileindex++;
+ }
+ }
+ lineptr++;
+ } else {
+ // Read the DWARF-5 directory table.
+
+ // Dwarf5 supports five different types and forms per directory- and
+ // file-table entry. Theoretically, there could be duplicate entries
+ // in this table, but that would be quite unusual.
+ static const uint32_t kMaxTypesAndForms = 5;
+ uint32_t content_types[kMaxTypesAndForms];
+ uint32_t content_forms[kMaxTypesAndForms];
+ uint32_t format_count;
size_t len;
- while (*lineptr) {
- const char *filename = reinterpret_cast<const char *>(lineptr);
- lineptr += strlen(filename) + 1;
- uint64_t dirindex = reader_->ReadUnsignedLEB128(lineptr, &len);
- lineptr += len;
+ ReadTypesAndForms(&lineptr, content_types, content_forms, kMaxTypesAndForms,
+ &format_count);
+ uint32_t entry_count = reader_->ReadUnsignedLEB128(lineptr, &len);
+ lineptr += len;
+ for (uint32_t row = 0; row < entry_count; ++row) {
+ const char* dirname = nullptr;
+ for (uint32_t col = 0; col < format_count; ++col) {
+ // The path is the only relevant content type for this implementation.
+ if (content_types[col] == DW_LNCT_path) {
+ dirname = ReadStringForm(content_forms[col], &lineptr);
+ }
+ }
+ handler_->DefineDir(dirname, row);
+ }
- uint64_t mod_time = reader_->ReadUnsignedLEB128(lineptr, &len);
- lineptr += len;
+ // Read the DWARF-5 filename table.
+ ReadTypesAndForms(&lineptr, content_types, content_forms, kMaxTypesAndForms,
+ &format_count);
+ entry_count = reader_->ReadUnsignedLEB128(lineptr, &len);
+ lineptr += len;
- uint64_t filelength = reader_->ReadUnsignedLEB128(lineptr, &len);
- lineptr += len;
- handler_->DefineFile(filename, fileindex, static_cast<uint32_t>(dirindex),
- mod_time, filelength);
- fileindex++;
+ for (uint32_t row = 0; row < entry_count; ++row) {
+ ReadFileRow(&lineptr, content_types, content_forms, row, format_count);
}
}
- lineptr++;
-
after_header_ = lineptr;
}
/* static */
bool LineInfo::ProcessOneOpcode(ByteReader* reader,
LineInfoHandler* handler,
- const struct LineInfoHeader &header,
- const uint8_t *start,
+ const struct LineInfoHeader& header,
+ const uint8_t* start,
struct LineStateMachine* lsm,
size_t* len,
uintptr pc,
- bool *lsm_passes_pc) {
+ bool* lsm_passes_pc) {
size_t oplen = 0;
size_t templen;
uint8_t opcode = reader->ReadOneByte(start);
@@ -1153,7 +1716,7 @@ bool LineInfo::ProcessOneOpcode(ByteReader* reader,
}
break;
case DW_LNE_define_file: {
- const char *filename = reinterpret_cast<const char *>(start);
+ const char* filename = reinterpret_cast<const char*>(start);
templen = strlen(filename) + 1;
start += templen;
@@ -1170,7 +1733,7 @@ bool LineInfo::ProcessOneOpcode(ByteReader* reader,
oplen += templen;
if (handler) {
- handler->DefineFile(filename, -1, static_cast<uint32_t>(dirindex),
+ handler->DefineFile(filename, -1, static_cast<uint32_t>(dirindex),
mod_time, filelength);
}
}
@@ -1200,7 +1763,7 @@ void LineInfo::ReadLines() {
// lengthstart is the place the length field is based on.
// It is the point in the header after the initial length field
- const uint8_t *lengthstart = buffer_;
+ const uint8_t* lengthstart = buffer_;
// In 64 bit dwarf, the initial length is 12 bytes, because of the
// 0xffffffff at the start.
@@ -1209,7 +1772,7 @@ void LineInfo::ReadLines() {
else
lengthstart += 4;
- const uint8_t *lineptr = after_header_;
+ const uint8_t* lineptr = after_header_;
lsm.Reset(header_.default_is_stmt);
// The LineInfoHandler interface expects each line's length along
@@ -1232,7 +1795,7 @@ void LineInfo::ReadLines() {
pending_file_num, pending_line_num,
pending_column_num);
if (lsm.end_sequence) {
- lsm.Reset(header_.default_is_stmt);
+ lsm.Reset(header_.default_is_stmt);
have_pending_line = false;
} else {
pending_address = lsm.address;
@@ -1248,11 +1811,25 @@ void LineInfo::ReadLines() {
after_header_ = lengthstart + header_.total_length;
}
-RangeListReader::RangeListReader(const uint8_t *buffer, uint64_t size,
- ByteReader *reader, RangeListHandler *handler)
- : buffer_(buffer), size_(size), reader_(reader), handler_(handler) { }
+bool RangeListReader::ReadRanges(enum DwarfForm form, uint64_t data) {
+ if (form == DW_FORM_sec_offset) {
+ if (cu_info_->version_ <= 4) {
+ return ReadDebugRanges(data);
+ } else {
+ return ReadDebugRngList(data);
+ }
+ } else if (form == DW_FORM_rnglistx) {
+ offset_array_ = cu_info_->ranges_base_;
+ uint64_t index_offset = reader_->OffsetSize() * data;
+ uint64_t range_list_offset =
+ reader_->ReadOffset(cu_info_->buffer_ + offset_array_ + index_offset);
-bool RangeListReader::ReadRangeList(uint64_t offset) {
+ return ReadDebugRngList(offset_array_ + range_list_offset);
+ }
+ return false;
+}
+
+bool RangeListReader::ReadDebugRanges(uint64_t offset) {
const uint64_t max_address =
(reader_->AddressSize() == 4) ? 0xffffffffUL
: 0xffffffffffffffffULL;
@@ -1260,21 +1837,22 @@ bool RangeListReader::ReadRangeList(uint64_t offset) {
bool list_end = false;
do {
- if (offset > size_ - entry_size) {
+ if (offset > cu_info_->size_ - entry_size) {
return false; // Invalid range detected
}
- uint64_t start_address = reader_->ReadAddress(buffer_ + offset);
- uint64_t end_address =
- reader_->ReadAddress(buffer_ + offset + reader_->AddressSize());
+ uint64_t start_address = reader_->ReadAddress(cu_info_->buffer_ + offset);
+ uint64_t end_address = reader_->ReadAddress(
+ cu_info_->buffer_ + offset + reader_->AddressSize());
if (start_address == max_address) { // Base address selection
- handler_->SetBaseAddress(end_address);
+ cu_info_->base_address_ = end_address;
} else if (start_address == 0 && end_address == 0) { // End-of-list
handler_->Finish();
list_end = true;
} else { // Add a range entry
- handler_->AddRange(start_address, end_address);
+ handler_->AddRange(start_address + cu_info_->base_address_,
+ end_address + cu_info_->base_address_);
}
offset += entry_size;
@@ -1283,6 +1861,62 @@ bool RangeListReader::ReadRangeList(uint64_t offset) {
return true;
}
+bool RangeListReader::ReadDebugRngList(uint64_t offset) {
+ uint64_t start = 0;
+ uint64_t end = 0;
+ uint64_t range_len = 0;
+ uint64_t index = 0;
+ // A uleb128's length isn't known until after it has been read, so overruns
+ // are only caught after an entire entry.
+ while (offset < cu_info_->size_) {
+ uint8_t entry_type = reader_->ReadOneByte(cu_info_->buffer_ + offset);
+ offset += 1;
+ // Handle each entry type per Dwarf 5 Standard, section 2.17.3.
+ switch (entry_type) {
+ case DW_RLE_end_of_list:
+ handler_->Finish();
+ return true;
+ case DW_RLE_base_addressx:
+ offset += ReadULEB(offset, &index);
+ cu_info_->base_address_ = GetAddressAtIndex(index);
+ break;
+ case DW_RLE_startx_endx:
+ offset += ReadULEB(offset, &index);
+ start = GetAddressAtIndex(index);
+ offset += ReadULEB(offset, &index);
+ end = GetAddressAtIndex(index);
+ handler_->AddRange(start, end);
+ break;
+ case DW_RLE_startx_length:
+ offset += ReadULEB(offset, &index);
+ start = GetAddressAtIndex(index);
+ offset += ReadULEB(offset, &range_len);
+ handler_->AddRange(start, start + range_len);
+ break;
+ case DW_RLE_offset_pair:
+ offset += ReadULEB(offset, &start);
+ offset += ReadULEB(offset, &end);
+ handler_->AddRange(start + cu_info_->base_address_,
+ end + cu_info_->base_address_);
+ break;
+ case DW_RLE_base_address:
+ offset += ReadAddress(offset, &cu_info_->base_address_);
+ break;
+ case DW_RLE_start_end:
+ offset += ReadAddress(offset, &start);
+ offset += ReadAddress(offset, &end);
+ handler_->AddRange(start, end);
+ break;
+ case DW_RLE_start_length:
+ offset += ReadAddress(offset, &start);
+ offset += ReadULEB(offset, &end);
+ handler_->AddRange(start, start + end);
+ break;
+ }
+ }
+ return false;
+}
+
// A DWARF rule for recovering the address or value of a register, or
// computing the canonical frame address. There is one subclass of this for
// each '*Rule' member function in CallFrameInfo::Handler.
@@ -1305,17 +1939,17 @@ class CallFrameInfo::Rule {
// this rule. If REG is kCFARegister, then this rule describes how to compute
// the canonical frame address. Return what the HANDLER member function
// returned.
- virtual bool Handle(Handler *handler,
+ virtual bool Handle(Handler* handler,
uint64_t address, int reg) const = 0;
// Equality on rules. We use these to decide which rules we need
// to report after a DW_CFA_restore_state instruction.
- virtual bool operator==(const Rule &rhs) const = 0;
+ virtual bool operator==(const Rule& rhs) const = 0;
- bool operator!=(const Rule &rhs) const { return ! (*this == rhs); }
+ bool operator!=(const Rule& rhs) const { return ! (*this == rhs); }
// Return a pointer to a copy of this rule.
- virtual Rule *Copy() const = 0;
+ virtual Rule* Copy() const = 0;
// If this is a base+offset rule, change its base register to REG.
// Otherwise, do nothing. (Ugly, but required for DW_CFA_def_cfa_register.)
@@ -1331,16 +1965,16 @@ class CallFrameInfo::UndefinedRule: public CallFrameInfo::Rule {
public:
UndefinedRule() { }
~UndefinedRule() { }
- bool Handle(Handler *handler, uint64_t address, int reg) const {
+ bool Handle(Handler* handler, uint64_t address, int reg) const {
return handler->UndefinedRule(address, reg);
}
- bool operator==(const Rule &rhs) const {
+ bool operator==(const Rule& rhs) const {
// dynamic_cast is allowed by the Google C++ Style Guide, if the use has
// been carefully considered; cheap RTTI-like workarounds are forbidden.
- const UndefinedRule *our_rhs = dynamic_cast<const UndefinedRule *>(&rhs);
+ const UndefinedRule* our_rhs = dynamic_cast<const UndefinedRule*>(&rhs);
return (our_rhs != NULL);
}
- Rule *Copy() const { return new UndefinedRule(*this); }
+ Rule* Copy() const { return new UndefinedRule(*this); }
};
// Rule: the register's value is the same as that it had in the caller.
@@ -1348,16 +1982,16 @@ class CallFrameInfo::SameValueRule: public CallFrameInfo::Rule {
public:
SameValueRule() { }
~SameValueRule() { }
- bool Handle(Handler *handler, uint64_t address, int reg) const {
+ bool Handle(Handler* handler, uint64_t address, int reg) const {
return handler->SameValueRule(address, reg);
}
- bool operator==(const Rule &rhs) const {
+ bool operator==(const Rule& rhs) const {
// dynamic_cast is allowed by the Google C++ Style Guide, if the use has
// been carefully considered; cheap RTTI-like workarounds are forbidden.
- const SameValueRule *our_rhs = dynamic_cast<const SameValueRule *>(&rhs);
+ const SameValueRule* our_rhs = dynamic_cast<const SameValueRule*>(&rhs);
return (our_rhs != NULL);
}
- Rule *Copy() const { return new SameValueRule(*this); }
+ Rule* Copy() const { return new SameValueRule(*this); }
};
// Rule: the register is saved at OFFSET from BASE_REGISTER. BASE_REGISTER
@@ -1367,18 +2001,18 @@ class CallFrameInfo::OffsetRule: public CallFrameInfo::Rule {
OffsetRule(int base_register, long offset)
: base_register_(base_register), offset_(offset) { }
~OffsetRule() { }
- bool Handle(Handler *handler, uint64_t address, int reg) const {
+ bool Handle(Handler* handler, uint64_t address, int reg) const {
return handler->OffsetRule(address, reg, base_register_, offset_);
}
- bool operator==(const Rule &rhs) const {
+ bool operator==(const Rule& rhs) const {
// dynamic_cast is allowed by the Google C++ Style Guide, if the use has
// been carefully considered; cheap RTTI-like workarounds are forbidden.
- const OffsetRule *our_rhs = dynamic_cast<const OffsetRule *>(&rhs);
+ const OffsetRule* our_rhs = dynamic_cast<const OffsetRule*>(&rhs);
return (our_rhs &&
base_register_ == our_rhs->base_register_ &&
offset_ == our_rhs->offset_);
}
- Rule *Copy() const { return new OffsetRule(*this); }
+ Rule* Copy() const { return new OffsetRule(*this); }
// We don't actually need SetBaseRegister or SetOffset here, since they
// are only ever applied to CFA rules, for DW_CFA_def_cfa_offset, and it
// doesn't make sense to use OffsetRule for computing the CFA: it
@@ -1396,18 +2030,18 @@ class CallFrameInfo::ValOffsetRule: public CallFrameInfo::Rule {
ValOffsetRule(int base_register, long offset)
: base_register_(base_register), offset_(offset) { }
~ValOffsetRule() { }
- bool Handle(Handler *handler, uint64_t address, int reg) const {
+ bool Handle(Handler* handler, uint64_t address, int reg) const {
return handler->ValOffsetRule(address, reg, base_register_, offset_);
}
- bool operator==(const Rule &rhs) const {
+ bool operator==(const Rule& rhs) const {
// dynamic_cast is allowed by the Google C++ Style Guide, if the use has
// been carefully considered; cheap RTTI-like workarounds are forbidden.
- const ValOffsetRule *our_rhs = dynamic_cast<const ValOffsetRule *>(&rhs);
+ const ValOffsetRule* our_rhs = dynamic_cast<const ValOffsetRule*>(&rhs);
return (our_rhs &&
base_register_ == our_rhs->base_register_ &&
offset_ == our_rhs->offset_);
}
- Rule *Copy() const { return new ValOffsetRule(*this); }
+ Rule* Copy() const { return new ValOffsetRule(*this); }
void SetBaseRegister(unsigned reg) { base_register_ = reg; }
void SetOffset(long long offset) { offset_ = offset; }
private:
@@ -1421,16 +2055,16 @@ class CallFrameInfo::RegisterRule: public CallFrameInfo::Rule {
explicit RegisterRule(int register_number)
: register_number_(register_number) { }
~RegisterRule() { }
- bool Handle(Handler *handler, uint64_t address, int reg) const {
+ bool Handle(Handler* handler, uint64_t address, int reg) const {
return handler->RegisterRule(address, reg, register_number_);
}
- bool operator==(const Rule &rhs) const {
+ bool operator==(const Rule& rhs) const {
// dynamic_cast is allowed by the Google C++ Style Guide, if the use has
// been carefully considered; cheap RTTI-like workarounds are forbidden.
- const RegisterRule *our_rhs = dynamic_cast<const RegisterRule *>(&rhs);
+ const RegisterRule* our_rhs = dynamic_cast<const RegisterRule*>(&rhs);
return (our_rhs && register_number_ == our_rhs->register_number_);
}
- Rule *Copy() const { return new RegisterRule(*this); }
+ Rule* Copy() const { return new RegisterRule(*this); }
private:
int register_number_;
};
@@ -1438,19 +2072,19 @@ class CallFrameInfo::RegisterRule: public CallFrameInfo::Rule {
// Rule: EXPRESSION evaluates to the address at which the register is saved.
class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule {
public:
- explicit ExpressionRule(const string &expression)
+ explicit ExpressionRule(const string& expression)
: expression_(expression) { }
~ExpressionRule() { }
- bool Handle(Handler *handler, uint64_t address, int reg) const {
+ bool Handle(Handler* handler, uint64_t address, int reg) const {
return handler->ExpressionRule(address, reg, expression_);
}
- bool operator==(const Rule &rhs) const {
+ bool operator==(const Rule& rhs) const {
// dynamic_cast is allowed by the Google C++ Style Guide, if the use has
// been carefully considered; cheap RTTI-like workarounds are forbidden.
- const ExpressionRule *our_rhs = dynamic_cast<const ExpressionRule *>(&rhs);
+ const ExpressionRule* our_rhs = dynamic_cast<const ExpressionRule*>(&rhs);
return (our_rhs && expression_ == our_rhs->expression_);
}
- Rule *Copy() const { return new ExpressionRule(*this); }
+ Rule* Copy() const { return new ExpressionRule(*this); }
private:
string expression_;
};
@@ -1458,20 +2092,20 @@ class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule {
// Rule: EXPRESSION evaluates to the address at which the register is saved.
class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule {
public:
- explicit ValExpressionRule(const string &expression)
+ explicit ValExpressionRule(const string& expression)
: expression_(expression) { }
~ValExpressionRule() { }
- bool Handle(Handler *handler, uint64_t address, int reg) const {
+ bool Handle(Handler* handler, uint64_t address, int reg) const {
return handler->ValExpressionRule(address, reg, expression_);
}
- bool operator==(const Rule &rhs) const {
+ bool operator==(const Rule& rhs) const {
// dynamic_cast is allowed by the Google C++ Style Guide, if the use has
// been carefully considered; cheap RTTI-like workarounds are forbidden.
- const ValExpressionRule *our_rhs =
- dynamic_cast<const ValExpressionRule *>(&rhs);
+ const ValExpressionRule* our_rhs =
+ dynamic_cast<const ValExpressionRule*>(&rhs);
return (our_rhs && expression_ == our_rhs->expression_);
}
- Rule *Copy() const { return new ValExpressionRule(*this); }
+ Rule* Copy() const { return new ValExpressionRule(*this); }
private:
string expression_;
};
@@ -1480,51 +2114,51 @@ class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule {
class CallFrameInfo::RuleMap {
public:
RuleMap() : cfa_rule_(NULL) { }
- RuleMap(const RuleMap &rhs) : cfa_rule_(NULL) { *this = rhs; }
+ RuleMap(const RuleMap& rhs) : cfa_rule_(NULL) { *this = rhs; }
~RuleMap() { Clear(); }
- RuleMap &operator=(const RuleMap &rhs);
+ RuleMap& operator=(const RuleMap& rhs);
// Set the rule for computing the CFA to RULE. Take ownership of RULE.
- void SetCFARule(Rule *rule) { delete cfa_rule_; cfa_rule_ = rule; }
+ void SetCFARule(Rule* rule) { delete cfa_rule_; cfa_rule_ = rule; }
// Return the current CFA rule. Unlike RegisterRule, this RuleMap retains
// ownership of the rule. We use this for DW_CFA_def_cfa_offset and
// DW_CFA_def_cfa_register, and for detecting references to the CFA before
// a rule for it has been established.
- Rule *CFARule() const { return cfa_rule_; }
+ Rule* CFARule() const { return cfa_rule_; }
// Return the rule for REG, or NULL if there is none. The caller takes
// ownership of the result.
- Rule *RegisterRule(int reg) const;
+ Rule* RegisterRule(int reg) const;
// Set the rule for computing REG to RULE. Take ownership of RULE.
- void SetRegisterRule(int reg, Rule *rule);
+ void SetRegisterRule(int reg, Rule* rule);
// Make all the appropriate calls to HANDLER as if we were changing from
// this RuleMap to NEW_RULES at ADDRESS. We use this to implement
// DW_CFA_restore_state, where lots of rules can change simultaneously.
// Return true if all handlers returned true; otherwise, return false.
- bool HandleTransitionTo(Handler *handler, uint64_t address,
- const RuleMap &new_rules) const;
+ bool HandleTransitionTo(Handler* handler, uint64_t address,
+ const RuleMap& new_rules) const;
private:
// A map from register numbers to Rules.
- typedef std::map<int, Rule *> RuleByNumber;
+ typedef std::map<int, Rule*> RuleByNumber;
// Remove all register rules and clear cfa_rule_.
void Clear();
// The rule for computing the canonical frame address. This RuleMap owns
// this rule.
- Rule *cfa_rule_;
+ Rule* cfa_rule_;
// A map from register numbers to postfix expressions to recover
// their values. This RuleMap owns the Rules the map refers to.
RuleByNumber registers_;
};
-CallFrameInfo::RuleMap &CallFrameInfo::RuleMap::operator=(const RuleMap &rhs) {
+CallFrameInfo::RuleMap& CallFrameInfo::RuleMap::operator=(const RuleMap& rhs) {
Clear();
// Since each map owns the rules it refers to, assignment must copy them.
if (rhs.cfa_rule_) cfa_rule_ = rhs.cfa_rule_->Copy();
@@ -1534,7 +2168,7 @@ CallFrameInfo::RuleMap &CallFrameInfo::RuleMap::operator=(const RuleMap &rhs) {
return *this;
}
-CallFrameInfo::Rule *CallFrameInfo::RuleMap::RegisterRule(int reg) const {
+CallFrameInfo::Rule* CallFrameInfo::RuleMap::RegisterRule(int reg) const {
assert(reg != Handler::kCFARegister);
RuleByNumber::const_iterator it = registers_.find(reg);
if (it != registers_.end())
@@ -1543,18 +2177,18 @@ CallFrameInfo::Rule *CallFrameInfo::RuleMap::RegisterRule(int reg) const {
return NULL;
}
-void CallFrameInfo::RuleMap::SetRegisterRule(int reg, Rule *rule) {
+void CallFrameInfo::RuleMap::SetRegisterRule(int reg, Rule* rule) {
assert(reg != Handler::kCFARegister);
assert(rule);
- Rule **slot = &registers_[reg];
+ Rule** slot = &registers_[reg];
delete *slot;
*slot = rule;
}
bool CallFrameInfo::RuleMap::HandleTransitionTo(
- Handler *handler,
+ Handler* handler,
uint64_t address,
- const RuleMap &new_rules) const {
+ const RuleMap& new_rules) const {
// Transition from cfa_rule_ to new_rules.cfa_rule_.
if (cfa_rule_ && new_rules.cfa_rule_) {
if (*cfa_rule_ != *new_rules.cfa_rule_ &&
@@ -1634,7 +2268,7 @@ class CallFrameInfo::State {
public:
// Create a call frame information interpreter state with the given
// reporter, reader, handler, and initial call frame info address.
- State(ByteReader *reader, Handler *handler, Reporter *reporter,
+ State(ByteReader* reader, Handler* handler, Reporter* reporter,
uint64_t address)
: reader_(reader), handler_(handler), reporter_(reporter),
address_(address), entry_(NULL), cursor_(NULL) { }
@@ -1642,13 +2276,13 @@ class CallFrameInfo::State {
// Interpret instructions from CIE, save the resulting rule set for
// DW_CFA_restore instructions, and return true. On error, report
// the problem to reporter_ and return false.
- bool InterpretCIE(const CIE &cie);
+ bool InterpretCIE(const CIE& cie);
// Interpret instructions from FDE, and return true. On error,
// report the problem to reporter_ and return false.
- bool InterpretFDE(const FDE &fde);
+ bool InterpretFDE(const FDE& fde);
- private:
+ private:
// The operands of a CFI instruction, for ParseOperands.
struct Operands {
unsigned register_number; // A register number.
@@ -1676,7 +2310,7 @@ class CallFrameInfo::State {
// '8' an eight-byte offset (OPERANDS->offset)
// 'e' a DW_FORM_block holding a (OPERANDS->expression)
// DWARF expression
- bool ParseOperands(const char *format, Operands *operands);
+ bool ParseOperands(const char* format, Operands* operands);
// Interpret one CFI instruction from STATE's instruction stream, update
// STATE, report any rule changes to handler_, and return true. On
@@ -1699,7 +2333,7 @@ class CallFrameInfo::State {
// Specify that REG can be recovered using RULE, and return true. On
// failure, report and return false.
- bool DoRule(unsigned reg, Rule *rule);
+ bool DoRule(unsigned reg, Rule* rule);
// Specify that REG can be found at OFFSET from the CFA, and return true.
// On failure, report and return false. (Subroutine for DW_CFA_offset,
@@ -1727,23 +2361,23 @@ class CallFrameInfo::State {
}
// For reading multi-byte values with the appropriate endianness.
- ByteReader *reader_;
+ ByteReader* reader_;
// The handler to which we should report the data we find.
- Handler *handler_;
+ Handler* handler_;
// For reporting problems in the info we're parsing.
- Reporter *reporter_;
+ Reporter* reporter_;
// The code address to which the next instruction in the stream applies.
uint64_t address_;
// The entry whose instructions we are currently processing. This is
// first a CIE, and then an FDE.
- const Entry *entry_;
+ const Entry* entry_;
// The next instruction to process.
- const uint8_t *cursor_;
+ const uint8_t* cursor_;
// The current set of rules.
RuleMap rules_;
@@ -1758,7 +2392,7 @@ class CallFrameInfo::State {
std::stack<RuleMap> saved_rules_;
};
-bool CallFrameInfo::State::InterpretCIE(const CIE &cie) {
+bool CallFrameInfo::State::InterpretCIE(const CIE& cie) {
entry_ = &cie;
cursor_ = entry_->instructions;
while (cursor_ < entry_->end)
@@ -1770,7 +2404,7 @@ bool CallFrameInfo::State::InterpretCIE(const CIE &cie) {
return true;
}
-bool CallFrameInfo::State::InterpretFDE(const FDE &fde) {
+bool CallFrameInfo::State::InterpretFDE(const FDE& fde) {
entry_ = &fde;
cursor_ = entry_->instructions;
while (cursor_ < entry_->end)
@@ -1779,10 +2413,10 @@ bool CallFrameInfo::State::InterpretFDE(const FDE &fde) {
return true;
}
-bool CallFrameInfo::State::ParseOperands(const char *format,
- Operands *operands) {
+bool CallFrameInfo::State::ParseOperands(const char* format,
+ Operands* operands) {
size_t len;
- const char *operand;
+ const char* operand;
for (operand = format; *operand; operand++) {
size_t bytes_left = entry_->end - cursor_;
@@ -1841,7 +2475,7 @@ bool CallFrameInfo::State::ParseOperands(const char *format,
if (len > bytes_left || expression_length > bytes_left - len)
return ReportIncomplete();
cursor_ += len;
- operands->expression = string(reinterpret_cast<const char *>(cursor_),
+ operands->expression = string(reinterpret_cast<const char*>(cursor_),
expression_length);
cursor_ += expression_length;
break;
@@ -1856,7 +2490,7 @@ bool CallFrameInfo::State::ParseOperands(const char *format,
}
bool CallFrameInfo::State::DoInstruction() {
- CIE *cie = entry_->cie;
+ CIE* cie = entry_->cie;
Operands ops;
// Our entry's kind should have been set by now.
@@ -1909,19 +2543,19 @@ bool CallFrameInfo::State::DoInstruction() {
if (!ParseOperands("1", &ops)) return false;
address_ += ops.offset * cie->code_alignment_factor;
break;
-
+
// Advance the address.
case DW_CFA_advance_loc2:
if (!ParseOperands("2", &ops)) return false;
address_ += ops.offset * cie->code_alignment_factor;
break;
-
+
// Advance the address.
case DW_CFA_advance_loc4:
if (!ParseOperands("4", &ops)) return false;
address_ += ops.offset * cie->code_alignment_factor;
break;
-
+
// Advance the address.
case DW_CFA_MIPS_advance_loc8:
if (!ParseOperands("8", &ops)) return false;
@@ -1946,7 +2580,7 @@ bool CallFrameInfo::State::DoInstruction() {
// Change the base register used to compute the CFA.
case DW_CFA_def_cfa_register: {
if (!ParseOperands("r", &ops)) return false;
- Rule *cfa_rule = rules_.CFARule();
+ Rule* cfa_rule = rules_.CFARule();
if (!cfa_rule) {
if (!DoDefCFA(ops.register_number, ops.offset)) {
reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
@@ -1979,7 +2613,7 @@ bool CallFrameInfo::State::DoInstruction() {
case DW_CFA_def_cfa_expression: {
if (!ParseOperands("e", &ops))
return false;
- Rule *rule = new ValExpressionRule(ops.expression);
+ Rule* rule = new ValExpressionRule(ops.expression);
rules_.SetCFARule(rule);
if (!rule->Handle(handler_, address_,
Handler::kCFARegister))
@@ -2086,7 +2720,7 @@ bool CallFrameInfo::State::DoInstruction() {
CursorOffset());
return false;
}
- const RuleMap &new_rules = saved_rules_.top();
+ const RuleMap& new_rules = saved_rules_.top();
if (rules_.CFARule() && !new_rules.CFARule()) {
reporter_->ClearingCFARule(entry_->offset, entry_->kind,
CursorOffset());
@@ -2102,23 +2736,32 @@ bool CallFrameInfo::State::DoInstruction() {
case DW_CFA_nop:
break;
- // A SPARC register window save: Registers 8 through 15 (%o0-%o7)
- // are saved in registers 24 through 31 (%i0-%i7), and registers
- // 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets
- // (0-15 * the register size). The register numbers must be
- // hard-coded. A GNU extension, and not a pretty one.
+ // case DW_CFA_AARCH64_negate_ra_state
case DW_CFA_GNU_window_save: {
- // Save %o0-%o7 in %i0-%i7.
- for (int i = 8; i < 16; i++)
- if (!DoRule(i, new RegisterRule(i + 16)))
- return false;
- // Save %l0-%l7 and %i0-%i7 at the CFA.
- for (int i = 16; i < 32; i++)
- // Assume that the byte reader's address size is the same as
- // the architecture's register size. !@#%*^ hilarious.
- if (!DoRule(i, new OffsetRule(Handler::kCFARegister,
- (i - 16) * reader_->AddressSize())))
- return false;
+ if (handler_->Architecture() == "arm64") {
+ // Indicates that the return address, x30 has been signed.
+ // Breakpad will speculatively remove pointer-authentication codes when
+ // interpreting return addresses, regardless of this bit.
+ } else if (handler_->Architecture() == "sparc" ||
+ handler_->Architecture() == "sparcv9") {
+ // A SPARC register window save: Registers 8 through 15 (%o0-%o7)
+ // are saved in registers 24 through 31 (%i0-%i7), and registers
+ // 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets
+ // (0-15 * the register size). The register numbers must be
+ // hard-coded. A GNU extension, and not a pretty one.
+
+ // Save %o0-%o7 in %i0-%i7.
+ for (int i = 8; i < 16; i++)
+ if (!DoRule(i, new RegisterRule(i + 16)))
+ return false;
+ // Save %l0-%l7 and %i0-%i7 at the CFA.
+ for (int i = 16; i < 32; i++)
+ // Assume that the byte reader's address size is the same as
+ // the architecture's register size. !@#%*^ hilarious.
+ if (!DoRule(i, new OffsetRule(Handler::kCFARegister,
+ (i - 16) * reader_->AddressSize())))
+ return false;
+ }
break;
}
@@ -2138,14 +2781,14 @@ bool CallFrameInfo::State::DoInstruction() {
}
bool CallFrameInfo::State::DoDefCFA(unsigned base_register, long offset) {
- Rule *rule = new ValOffsetRule(base_register, offset);
+ Rule* rule = new ValOffsetRule(base_register, offset);
rules_.SetCFARule(rule);
return rule->Handle(handler_, address_,
Handler::kCFARegister);
}
bool CallFrameInfo::State::DoDefCFAOffset(long offset) {
- Rule *cfa_rule = rules_.CFARule();
+ Rule* cfa_rule = rules_.CFARule();
if (!cfa_rule) {
reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
return false;
@@ -2155,7 +2798,7 @@ bool CallFrameInfo::State::DoDefCFAOffset(long offset) {
Handler::kCFARegister);
}
-bool CallFrameInfo::State::DoRule(unsigned reg, Rule *rule) {
+bool CallFrameInfo::State::DoRule(unsigned reg, Rule* rule) {
rules_.SetRegisterRule(reg, rule);
return rule->Handle(handler_, address_, reg);
}
@@ -2184,7 +2827,7 @@ bool CallFrameInfo::State::DoRestore(unsigned reg) {
reporter_->RestoreInCIE(entry_->offset, CursorOffset());
return false;
}
- Rule *rule = cie_rules_.RegisterRule(reg);
+ Rule* rule = cie_rules_.RegisterRule(reg);
if (!rule) {
// This isn't really the right thing to do, but since CFI generally
// only mentions callee-saves registers, and GCC's convention for
@@ -2195,8 +2838,8 @@ bool CallFrameInfo::State::DoRestore(unsigned reg) {
return DoRule(reg, rule);
}
-bool CallFrameInfo::ReadEntryPrologue(const uint8_t *cursor, Entry *entry) {
- const uint8_t *buffer_end = buffer_ + buffer_length_;
+bool CallFrameInfo::ReadEntryPrologue(const uint8_t* cursor, Entry* entry) {
+ const uint8_t* buffer_end = buffer_ + buffer_length_;
// Initialize enough of ENTRY for use in error reporting.
entry->offset = cursor - buffer_;
@@ -2222,7 +2865,7 @@ bool CallFrameInfo::ReadEntryPrologue(const uint8_t *cursor, Entry *entry) {
// Validate the length.
if (length > size_t(buffer_end - cursor))
return ReportIncomplete(entry);
-
+
// The length is the number of bytes after the initial length field;
// we have that position handy at this point, so compute the end
// now. (If we're parsing 64-bit-offset DWARF on a 32-bit machine,
@@ -2264,7 +2907,7 @@ bool CallFrameInfo::ReadEntryPrologue(const uint8_t *cursor, Entry *entry) {
// Now advance cursor past the id.
cursor += offset_size;
-
+
// The fields specific to this kind of entry start here.
entry->fields = cursor;
@@ -2273,8 +2916,8 @@ bool CallFrameInfo::ReadEntryPrologue(const uint8_t *cursor, Entry *entry) {
return true;
}
-bool CallFrameInfo::ReadCIEFields(CIE *cie) {
- const uint8_t *cursor = cie->fields;
+bool CallFrameInfo::ReadCIEFields(CIE* cie) {
+ const uint8_t* cursor = cie->fields;
size_t len;
assert(cie->kind == kCIE);
@@ -2305,13 +2948,13 @@ bool CallFrameInfo::ReadCIEFields(CIE *cie) {
return false;
}
- const uint8_t *augmentation_start = cursor;
- const uint8_t *augmentation_end =
- reinterpret_cast<const uint8_t *>(memchr(augmentation_start, '\0',
+ const uint8_t* augmentation_start = cursor;
+ const uint8_t* augmentation_end =
+ reinterpret_cast<const uint8_t*>(memchr(augmentation_start, '\0',
cie->end - augmentation_start));
if (! augmentation_end) return ReportIncomplete(cie);
cursor = augmentation_end;
- cie->augmentation = string(reinterpret_cast<const char *>(augmentation_start),
+ cie->augmentation = string(reinterpret_cast<const char*>(augmentation_start),
cursor - augmentation_start);
// Skip the terminating '\0'.
cursor++;
@@ -2372,9 +3015,9 @@ bool CallFrameInfo::ReadCIEFields(CIE *cie) {
if (size_t(cie->end - cursor) < len + data_size)
return ReportIncomplete(cie);
cursor += len;
- const uint8_t *data = cursor;
+ const uint8_t* data = cursor;
cursor += data_size;
- const uint8_t *data_end = cursor;
+ const uint8_t* data_end = cursor;
cie->has_z_lsda = false;
cie->has_z_personality = false;
@@ -2465,8 +3108,8 @@ bool CallFrameInfo::ReadCIEFields(CIE *cie) {
return true;
}
-bool CallFrameInfo::ReadFDEFields(FDE *fde) {
- const uint8_t *cursor = fde->fields;
+bool CallFrameInfo::ReadFDEFields(FDE* fde) {
+ const uint8_t* cursor = fde->fields;
size_t size;
fde->address = reader_->ReadEncodedPointer(cursor, fde->cie->pointer_encoding,
@@ -2492,7 +3135,7 @@ bool CallFrameInfo::ReadFDEFields(FDE *fde) {
if (size_t(fde->end - cursor) < size + data_size)
return ReportIncomplete(fde);
cursor += size;
-
+
// In the abstract, we should walk the augmentation string, and extract
// items from the FDE's augmentation data as we encounter augmentation
// string characters that specify their presence: the ordering of items
@@ -2530,12 +3173,12 @@ bool CallFrameInfo::ReadFDEFields(FDE *fde) {
return true;
}
-
+
bool CallFrameInfo::Start() {
- const uint8_t *buffer_end = buffer_ + buffer_length_;
- const uint8_t *cursor;
+ const uint8_t* buffer_end = buffer_ + buffer_length_;
+ const uint8_t* cursor;
bool all_ok = true;
- const uint8_t *entry_end;
+ const uint8_t* entry_end;
bool ok;
// Traverse all the entries in buffer_, skipping CIEs and offering
@@ -2587,7 +3230,7 @@ bool CallFrameInfo::Start() {
reporter_->CIEPointerOutOfRange(fde.offset, fde.id);
continue;
}
-
+
CIE cie;
// Parse this FDE's CIE header.
@@ -2626,7 +3269,7 @@ bool CallFrameInfo::Start() {
ok = true;
continue;
}
-
+
if (cie.has_z_augmentation) {
// Report the personality routine address, if we have one.
if (cie.has_z_personality) {
@@ -2666,7 +3309,7 @@ bool CallFrameInfo::Start() {
return all_ok;
}
-const char *CallFrameInfo::KindName(EntryKind kind) {
+const char* CallFrameInfo::KindName(EntryKind kind) {
if (kind == CallFrameInfo::kUnknown)
return "entry";
else if (kind == CallFrameInfo::kCIE)
@@ -2679,7 +3322,7 @@ const char *CallFrameInfo::KindName(EntryKind kind) {
}
}
-bool CallFrameInfo::ReportIncomplete(Entry *entry) {
+bool CallFrameInfo::ReportIncomplete(Entry* entry) {
reporter_->Incomplete(entry->offset, entry->kind);
return false;
}
@@ -2738,7 +3381,7 @@ void CallFrameInfo::Reporter::UnrecognizedVersion(uint64_t offset, int version)
}
void CallFrameInfo::Reporter::UnrecognizedAugmentation(uint64_t offset,
- const string &aug) {
+ const string& aug) {
fprintf(stderr,
"%s: CFI frame description entry at offset 0x%" PRIx64 " in '%s':"
" CIE specifies unrecognized augmentation: '%s'\n",
@@ -2813,4 +3456,4 @@ void CallFrameInfo::Reporter::ClearingCFARule(uint64_t offset,
section_.c_str(), insn_offset);
}
-} // namespace dwarf2reader
+} // namespace google_breakpad
diff --git a/src/common/dwarf/dwarf2reader.h b/src/common/dwarf/dwarf2reader.h
index 0b194c17..ddcdd801 100644
--- a/src/common/dwarf/dwarf2reader.h
+++ b/src/common/dwarf/dwarf2reader.h
@@ -1,6 +1,6 @@
// -*- mode: C++ -*-
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -12,7 +12,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -40,6 +40,7 @@
#ifndef COMMON_DWARF_DWARF2READER_H__
#define COMMON_DWARF_DWARF2READER_H__
+#include <assert.h>
#include <stdint.h>
#include <list>
@@ -55,7 +56,7 @@
#include "common/using_std_string.h"
#include "common/dwarf/elf_reader.h"
-namespace dwarf2reader {
+namespace google_breakpad {
struct LineStateMachine;
class Dwarf2Handler;
class LineInfoHandler;
@@ -63,9 +64,27 @@ class DwpReader;
// This maps from a string naming a section to a pair containing a
// the data for the section, and the size of the section.
-typedef std::map<string, std::pair<const uint8_t *, uint64_t> > SectionMap;
-typedef std::list<std::pair<enum DwarfAttribute, enum DwarfForm> >
- AttributeList;
+typedef std::map<string, std::pair<const uint8_t*, uint64_t> > SectionMap;
+
+// Abstract away the difference between elf and mach-o section names.
+// Elf-names use ".section_name, mach-o uses "__section_name". Pass "name" in
+// the elf form, ".section_name".
+const SectionMap::const_iterator GetSectionByName(const SectionMap&
+ sections, const char* name);
+
+// Most of the time, this struct functions as a simple attribute and form pair.
+// However, Dwarf5 DW_FORM_implicit_const means that a form may have its value
+// in line in the abbrev table, and that value must be associated with the
+// pair until the attr's value is needed.
+struct AttrForm {
+ AttrForm(enum DwarfAttribute attr, enum DwarfForm form, uint64_t value) :
+ attr_(attr), form_(form), value_(value) { }
+
+ enum DwarfAttribute attr_;
+ enum DwarfForm form_;
+ uint64_t value_;
+};
+typedef std::list<AttrForm> AttributeList;
typedef AttributeList::iterator AttributeIterator;
typedef AttributeList::const_iterator ConstAttributeIterator;
@@ -80,7 +99,7 @@ struct LineInfoHeader {
uint8_t opcode_base;
// Use a pointer so that signalsafe_addr2line is able to use this structure
// without heap allocation problem.
- std::vector<unsigned char> *std_opcode_lengths;
+ std::vector<unsigned char>* std_opcode_lengths;
};
class LineInfo {
@@ -90,8 +109,10 @@ class LineInfo {
// to the beginning and length of the line information to read.
// Reader is a ByteReader class that has the endianness set
// properly.
- LineInfo(const uint8_t *buffer_, uint64_t buffer_length,
- ByteReader* reader, LineInfoHandler* handler);
+ LineInfo(const uint8_t* buffer, uint64_t buffer_length,
+ ByteReader* reader, const uint8_t* string_buffer,
+ size_t string_buffer_length, const uint8_t* line_string_buffer,
+ size_t line_string_buffer_length, LineInfoHandler* handler);
virtual ~LineInfo() {
if (header_.std_opcode_lengths) {
@@ -115,12 +136,12 @@ class LineInfo {
// lsm's old address < PC <= lsm's new address
static bool ProcessOneOpcode(ByteReader* reader,
LineInfoHandler* handler,
- const struct LineInfoHeader &header,
- const uint8_t *start,
+ const struct LineInfoHeader& header,
+ const uint8_t* start,
struct LineStateMachine* lsm,
size_t* len,
uintptr pc,
- bool *lsm_passes_pc);
+ bool* lsm_passes_pc);
private:
// Reads the DWARF2/3 header for this line info.
@@ -129,26 +150,54 @@ class LineInfo {
// Reads the DWARF2/3 line information
void ReadLines();
+ // Read the DWARF5 types and forms for the file and directory tables.
+ void ReadTypesAndForms(const uint8_t** lineptr, uint32_t* content_types,
+ uint32_t* content_forms, uint32_t max_types,
+ uint32_t* format_count);
+
+ // Read a row from the dwarf5 LineInfo file table.
+ void ReadFileRow(const uint8_t** lineptr, const uint32_t* content_types,
+ const uint32_t* content_forms, uint32_t row,
+ uint32_t format_count);
+
+ // Read and return the data at *lineptr according to form. Advance
+ // *lineptr appropriately.
+ uint64_t ReadUnsignedData(uint32_t form, const uint8_t** lineptr);
+
+ // Read and return the data at *lineptr according to form. Advance
+ // *lineptr appropriately.
+ const char* ReadStringForm(uint32_t form, const uint8_t** lineptr);
+
// The associated handler to call processing functions in
LineInfoHandler* handler_;
// The associated ByteReader that handles endianness issues for us
ByteReader* reader_;
- // A DWARF2/3 line info header. This is not the same size as
- // in the actual file, as the one in the file may have a 32 bit or
- // 64 bit lengths
+ // A DWARF line info header. This is not the same size as in the actual file,
+ // as the one in the file may have a 32 bit or 64 bit lengths
struct LineInfoHeader header_;
// buffer is the buffer for our line info, starting at exactly where
// the line info to read is. after_header is the place right after
// the end of the line information header.
- const uint8_t *buffer_;
+ const uint8_t* buffer_;
#ifndef NDEBUG
uint64_t buffer_length_;
#endif
- const uint8_t *after_header_;
+ // Convenience pointers into .debug_str and .debug_line_str. These exactly
+ // correspond to those in the compilation unit.
+ const uint8_t* string_buffer_;
+#ifndef NDEBUG
+ uint64_t string_buffer_length_;
+#endif
+ const uint8_t* line_string_buffer_;
+#ifndef NDEBUG
+ uint64_t line_string_buffer_length_;
+#endif
+
+ const uint8_t* after_header_;
};
// This class is the main interface between the line info reader and
@@ -196,25 +245,75 @@ class RangeListHandler {
// Add a range.
virtual void AddRange(uint64_t begin, uint64_t end) { };
- // A new base address must be set for computing the ranges' addresses.
- virtual void SetBaseAddress(uint64_t base_address) { };
-
// Finish processing the range list.
virtual void Finish() { };
};
class RangeListReader {
public:
- RangeListReader(const uint8_t *buffer, uint64_t size, ByteReader *reader,
- RangeListHandler *handler);
+ // Reading a range list requires quite a bit of information
+ // from the compilation unit. Package it conveniently.
+ struct CURangesInfo {
+ CURangesInfo() :
+ version_(0), base_address_(0), ranges_base_(0),
+ buffer_(nullptr), size_(0), addr_buffer_(nullptr),
+ addr_buffer_size_(0), addr_base_(0) { }
+
+ uint16_t version_;
+ // Ranges base address. Ordinarily the CU's low_pc.
+ uint64_t base_address_;
+ // Offset into .debug_rnglists for this CU's rangelists.
+ uint64_t ranges_base_;
+ // Contents of either .debug_ranges or .debug_rnglists.
+ const uint8_t* buffer_;
+ uint64_t size_;
+ // Contents of .debug_addr. This cu's contribution starts at
+ // addr_base_
+ const uint8_t* addr_buffer_;
+ uint64_t addr_buffer_size_;
+ uint64_t addr_base_;
+ };
+
+ RangeListReader(ByteReader* reader, CURangesInfo* cu_info,
+ RangeListHandler* handler) :
+ reader_(reader), cu_info_(cu_info), handler_(handler),
+ offset_array_(0) { }
- bool ReadRangeList(uint64_t offset);
+ // Read ranges from cu_info as specified by form and data.
+ bool ReadRanges(enum DwarfForm form, uint64_t data);
private:
- const uint8_t *buffer_;
- uint64_t size_;
+ // Read dwarf4 .debug_ranges at offset.
+ bool ReadDebugRanges(uint64_t offset);
+ // Read dwarf5 .debug_rngslist at offset.
+ bool ReadDebugRngList(uint64_t offset);
+
+ // Convenience functions to handle the mechanics of reading entries in the
+ // ranges section.
+ uint64_t ReadULEB(uint64_t offset, uint64_t* value) {
+ size_t len;
+ *value = reader_->ReadUnsignedLEB128(cu_info_->buffer_ + offset, &len);
+ return len;
+ }
+
+ uint64_t ReadAddress(uint64_t offset, uint64_t* value) {
+ *value = reader_->ReadAddress(cu_info_->buffer_ + offset);
+ return reader_->AddressSize();
+ }
+
+ // Read the address at this CU's addr_index in the .debug_addr section.
+ uint64_t GetAddressAtIndex(uint64_t addr_index) {
+ assert(cu_info_->addr_buffer_ != nullptr);
+ uint64_t offset =
+ cu_info_->addr_base_ + addr_index * reader_->AddressSize();
+ assert(offset < cu_info_->addr_buffer_size_);
+ return reader_->ReadAddress(cu_info_->addr_buffer_ + offset);
+ }
+
ByteReader* reader_;
- RangeListHandler *handler_;
+ CURangesInfo* cu_info_;
+ RangeListHandler* handler_;
+ uint64_t offset_array_;
};
// This class is the main interface between the reader and the
@@ -288,7 +387,7 @@ class Dwarf2Handler {
virtual void ProcessAttributeBuffer(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
- const uint8_t *data,
+ const uint8_t* data,
uint64_t len) { }
// Called when we have an attribute with string data to give to our handler.
@@ -410,18 +509,42 @@ class CompilationUnit {
// Reads the DWARF2/3 abbreviations for this compilation unit
void ReadAbbrevs();
+ // Read the abbreviation offset for this compilation unit
+ size_t ReadAbbrevOffset(const uint8_t* headerptr);
+
+ // Read the address size for this compilation unit
+ size_t ReadAddressSize(const uint8_t* headerptr);
+
+ // Read the DWO id from a split or skeleton compilation unit header
+ size_t ReadDwoId(const uint8_t* headerptr);
+
+ // Read the type signature from a type or split type compilation unit header
+ size_t ReadTypeSignature(const uint8_t* headerptr);
+
+ // Read the DWO id from a split or skeleton compilation unit header
+ size_t ReadTypeOffset(const uint8_t* headerptr);
+
// Processes a single DIE for this compilation unit and return a new
// pointer just past the end of it
- const uint8_t *ProcessDIE(uint64_t dieoffset,
- const uint8_t *start,
+ const uint8_t* ProcessDIE(uint64_t dieoffset,
+ const uint8_t* start,
const Abbrev& abbrev);
// Processes a single attribute and return a new pointer just past the
// end of it
- const uint8_t *ProcessAttribute(uint64_t dieoffset,
- const uint8_t *start,
+ const uint8_t* ProcessAttribute(uint64_t dieoffset,
+ const uint8_t* start,
enum DwarfAttribute attr,
- enum DwarfForm form);
+ enum DwarfForm form,
+ uint64_t implicit_const);
+
+ // Special version of ProcessAttribute, for finding str_offsets_base and
+ // DW_AT_addr_base in DW_TAG_compile_unit, for DWARF v5.
+ const uint8_t* ProcessOffsetBaseAttribute(uint64_t dieoffset,
+ const uint8_t* start,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ uint64_t implicit_const);
// Called when we have an attribute with unsigned data to give to
// our handler. The attribute is for the DIE at OFFSET from the
@@ -436,10 +559,13 @@ class CompilationUnit {
if (attr == DW_AT_GNU_dwo_id) {
dwo_id_ = data;
}
- else if (attr == DW_AT_GNU_addr_base) {
+ else if (attr == DW_AT_GNU_addr_base || attr == DW_AT_addr_base) {
addr_base_ = data;
}
- else if (attr == DW_AT_GNU_ranges_base) {
+ else if (attr == DW_AT_str_offsets_base) {
+ str_offsets_base_ = data;
+ }
+ else if (attr == DW_AT_GNU_ranges_base || attr == DW_AT_rnglists_base) {
ranges_base_ = data;
}
// TODO(yunlian): When we add DW_AT_ranges_base from DWARF-5,
@@ -475,6 +601,14 @@ class CompilationUnit {
handler_->ProcessAttributeBuffer(offset, attr, form, data, len);
}
+ // Handles the common parts of DW_FORM_GNU_str_index, DW_FORM_strx,
+ // DW_FORM_strx1, DW_FORM_strx2, DW_FORM_strx3, and DW_FORM_strx4.
+ // Retrieves the data and calls through to ProcessAttributeString.
+ void ProcessFormStringIndex(uint64_t offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ uint64_t str_index);
+
// Called when we have an attribute with string data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
@@ -485,21 +619,33 @@ class CompilationUnit {
enum DwarfAttribute attr,
enum DwarfForm form,
const char* data) {
- if (attr == DW_AT_GNU_dwo_name)
+ if (attr == DW_AT_GNU_dwo_name || attr == DW_AT_dwo_name)
dwo_name_ = data;
handler_->ProcessAttributeString(offset, attr, form, data);
}
+ // Called to handle common portions of DW_FORM_addrx and variations, as well
+ // as DW_FORM_GNU_addr_index.
+ void ProcessAttributeAddrIndex(uint64_t offset,
+ enum DwarfAttribute attr,
+ enum DwarfForm form,
+ uint64_t addr_index) {
+ const uint8_t* addr_ptr =
+ addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize();
+ ProcessAttributeUnsigned(
+ offset, attr, form, reader_->ReadAddress(addr_ptr));
+ }
+
// Processes all DIEs for this compilation unit
void ProcessDIEs();
// Skips the die with attributes specified in ABBREV starting at
// START, and return the new place to position the stream to.
- const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev);
+ const uint8_t* SkipDIE(const uint8_t* start, const Abbrev& abbrev);
// Skips the attribute starting at START, with FORM, and return the
// new place to position the stream to.
- const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form);
+ const uint8_t* SkipAttribute(const uint8_t* start, enum DwarfForm form);
// Process the actual debug information in a split DWARF file.
void ProcessSplitDwarf();
@@ -518,9 +664,9 @@ class CompilationUnit {
// buffer is the buffer for our CU, starting at .debug_info + offset
// passed in from constructor.
// after_header points to right after the compilation unit header.
- const uint8_t *buffer_;
+ const uint8_t* buffer_;
uint64_t buffer_length_;
- const uint8_t *after_header_;
+ const uint8_t* after_header_;
// The associated ByteReader that handles endianness issues for us
ByteReader* reader_;
@@ -539,9 +685,13 @@ class CompilationUnit {
// String section buffer and length, if we have a string section.
// This is here to avoid doing a section lookup for strings in
// ProcessAttribute, which is in the hot path for DWARF2 reading.
- const uint8_t *string_buffer_;
+ const uint8_t* string_buffer_;
uint64_t string_buffer_length_;
+ // Similarly for .debug_line_string.
+ const uint8_t* line_string_buffer_;
+ uint64_t line_string_buffer_length_;
+
// String offsets section buffer and length, if we have a string offsets
// section (.debug_str_offsets or .debug_str_offsets.dwo).
const uint8_t* str_offsets_buffer_;
@@ -561,9 +711,18 @@ class CompilationUnit {
// associated with the skeleton compilation unit.
bool is_split_dwarf_;
+ // Flag indicating if it's a Type Unit (only applicable to DWARF v5).
+ bool is_type_unit_;
+
// The value of the DW_AT_GNU_dwo_id attribute, if any.
uint64_t dwo_id_;
+ // The value of the DW_AT_GNU_type_signature attribute, if any.
+ uint64_t type_signature_;
+
+ // The value of the DW_AT_GNU_type_offset attribute, if any.
+ size_t type_offset_;
+
// The value of the DW_AT_GNU_dwo_name attribute, if any.
const char* dwo_name_;
@@ -571,12 +730,16 @@ class CompilationUnit {
// from the skeleton CU.
uint64_t skeleton_dwo_id_;
- // The value of the DW_AT_GNU_ranges_base attribute, if any.
+ // The value of the DW_AT_GNU_ranges_base or DW_AT_rnglists_base attribute,
+ // if any.
uint64_t ranges_base_;
// The value of the DW_AT_GNU_addr_base attribute, if any.
uint64_t addr_base_;
+ // The value of DW_AT_str_offsets_base attribute, if any.
+ uint64_t str_offsets_base_;
+
// True if we have already looked for a .dwp file.
bool have_checked_for_dwp_;
@@ -905,8 +1068,8 @@ class CallFrameInfo {
// The mechanics of C++ exception handling, personality routines,
// and language-specific data areas are described here, rather nicely:
// http://www.codesourcery.com/public/cxx-abi/abi-eh.html
- CallFrameInfo(const uint8_t *buffer, size_t buffer_length,
- ByteReader *reader, Handler *handler, Reporter *reporter,
+ CallFrameInfo(const uint8_t* buffer, size_t buffer_length,
+ ByteReader* reader, Handler* handler, Reporter* reporter,
bool eh_frame = false)
: buffer_(buffer), buffer_length_(buffer_length),
reader_(reader), handler_(handler), reporter_(reporter),
@@ -920,7 +1083,7 @@ class CallFrameInfo {
bool Start();
// Return the textual name of KIND. For error reporting.
- static const char *KindName(EntryKind kind);
+ static const char* KindName(EntryKind kind);
private:
@@ -933,7 +1096,7 @@ class CallFrameInfo {
size_t offset;
// The start of this entry in the buffer.
- const uint8_t *start;
+ const uint8_t* start;
// Which kind of entry this is.
//
@@ -944,16 +1107,16 @@ class CallFrameInfo {
// The end of this entry's common prologue (initial length and id), and
// the start of this entry's kind-specific fields.
- const uint8_t *fields;
+ const uint8_t* fields;
// The start of this entry's instructions.
- const uint8_t *instructions;
+ const uint8_t* instructions;
// The address past the entry's last byte in the buffer. (Note that
// since offset points to the entry's initial length field, and the
// length field is the number of bytes after that field, this is not
// simply buffer_ + offset + length.)
- const uint8_t *end;
+ const uint8_t* end;
// For both DWARF CFI and .eh_frame sections, this is the CIE id in a
// CIE, and the offset of the associated CIE in an FDE.
@@ -961,7 +1124,7 @@ class CallFrameInfo {
// The CIE that applies to this entry, if we've parsed it. If this is a
// CIE, then this field points to this structure.
- CIE *cie;
+ CIE* cie;
};
// A common information entry (CIE).
@@ -1035,14 +1198,14 @@ class CallFrameInfo {
// true. On failure, report the problem, and return false. Even if we
// return false, set ENTRY->end to the first byte after the entry if we
// were able to figure that out, or NULL if we weren't.
- bool ReadEntryPrologue(const uint8_t *cursor, Entry *entry);
+ bool ReadEntryPrologue(const uint8_t* cursor, Entry* entry);
// Parse the fields of a CIE after the entry prologue, including any 'z'
// augmentation data. Assume that the 'Entry' fields of CIE are
// populated; use CIE->fields and CIE->end as the start and limit for
// parsing. On success, populate the rest of *CIE, and return true; on
// failure, report the problem and return false.
- bool ReadCIEFields(CIE *cie);
+ bool ReadCIEFields(CIE* cie);
// Parse the fields of an FDE after the entry prologue, including any 'z'
// augmentation data. Assume that the 'Entry' fields of *FDE are
@@ -1050,12 +1213,12 @@ class CallFrameInfo {
// parsing. Assume that FDE->cie is fully initialized. On success,
// populate the rest of *FDE, and return true; on failure, report the
// problem and return false.
- bool ReadFDEFields(FDE *fde);
+ bool ReadFDEFields(FDE* fde);
// Report that ENTRY is incomplete, and return false. This is just a
// trivial wrapper for invoking reporter_->Incomplete; it provides a
// little brevity.
- bool ReportIncomplete(Entry *entry);
+ bool ReportIncomplete(Entry* entry);
// Return true if ENCODING has the DW_EH_PE_indirect bit set.
static bool IsIndirectEncoding(DwarfPointerEncoding encoding) {
@@ -1063,17 +1226,17 @@ class CallFrameInfo {
}
// The contents of the DWARF .debug_info section we're parsing.
- const uint8_t *buffer_;
+ const uint8_t* buffer_;
size_t buffer_length_;
// For reading multi-byte values with the appropriate endianness.
- ByteReader *reader_;
+ ByteReader* reader_;
// The handler to which we should report the data we find.
- Handler *handler_;
+ Handler* handler_;
// For reporting problems in the info we're parsing.
- Reporter *reporter_;
+ Reporter* reporter_;
// True if we are processing .eh_frame-format data.
bool eh_frame_;
@@ -1106,7 +1269,7 @@ class CallFrameInfo::Handler {
// process a given FDE, the parser reiterates the appropriate CIE's
// contents at the beginning of the FDE's rules.
virtual bool Entry(size_t offset, uint64_t address, uint64_t length,
- uint8_t version, const string &augmentation,
+ uint8_t version, const string& augmentation,
unsigned return_address) = 0;
// When the Entry function returns true, the parser calls these
@@ -1155,13 +1318,13 @@ class CallFrameInfo::Handler {
// At ADDRESS, the DWARF expression EXPRESSION yields the address at
// which REG was saved.
virtual bool ExpressionRule(uint64_t address, int reg,
- const string &expression) = 0;
+ const string& expression) = 0;
// At ADDRESS, the DWARF expression EXPRESSION yields the caller's
// value for REG. (This rule doesn't provide an address at which the
// register's value is saved.)
virtual bool ValExpressionRule(uint64_t address, int reg,
- const string &expression) = 0;
+ const string& expression) = 0;
// Indicate that the rules for the address range reported by the
// last call to Entry are complete. End should return true if
@@ -1169,6 +1332,9 @@ class CallFrameInfo::Handler {
// should stop.
virtual bool End() = 0;
+ // The target architecture for the data.
+ virtual string Architecture() = 0;
+
// Handler functions for Linux C++ exception handling data. These are
// only called if the data includes 'z' augmentation strings.
@@ -1238,8 +1404,8 @@ class CallFrameInfo::Reporter {
// in a Mach-O section named __debug_frame. If we support
// Linux-style exception handling data, we could be reading an
// .eh_frame section.
- Reporter(const string &filename,
- const string &section = ".debug_frame")
+ Reporter(const string& filename,
+ const string& section = ".debug_frame")
: filename_(filename), section_(section) { }
virtual ~Reporter() { }
@@ -1279,7 +1445,7 @@ class CallFrameInfo::Reporter {
// which we don't recognize. We cannot parse DWARF CFI if it uses
// augmentations we don't recognize.
virtual void UnrecognizedAugmentation(uint64_t offset,
- const string &augmentation);
+ const string& augmentation);
// The pointer encoding ENCODING, specified by the CIE at OFFSET, is not
// a valid encoding.
@@ -1326,6 +1492,6 @@ class CallFrameInfo::Reporter {
string section_;
};
-} // namespace dwarf2reader
+} // namespace google_breakpad
#endif // UTIL_DEBUGINFO_DWARF2READER_H__
diff --git a/src/common/dwarf/dwarf2reader_cfi_unittest.cc b/src/common/dwarf/dwarf2reader_cfi_unittest.cc
index ebe612e1..dc4418c7 100644
--- a/src/common/dwarf/dwarf2reader_cfi_unittest.cc
+++ b/src/common/dwarf/dwarf2reader_cfi_unittest.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2010, Google Inc.
-// All rights reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -29,7 +28,7 @@
// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-// dwarf2reader_cfi_unittest.cc: Unit tests for dwarf2reader::CallFrameInfo
+// dwarf2reader_cfi_unittest.cc: Unit tests for google_breakpad::CallFrameInfo
#include <stdint.h>
#include <stdlib.h>
@@ -72,11 +71,11 @@ using google_breakpad::test_assembler::kBigEndian;
using google_breakpad::test_assembler::kLittleEndian;
using google_breakpad::test_assembler::Section;
-using dwarf2reader::DwarfPointerEncoding;
-using dwarf2reader::ENDIANNESS_BIG;
-using dwarf2reader::ENDIANNESS_LITTLE;
-using dwarf2reader::ByteReader;
-using dwarf2reader::CallFrameInfo;
+using google_breakpad::DwarfPointerEncoding;
+using google_breakpad::ENDIANNESS_BIG;
+using google_breakpad::ENDIANNESS_LITTLE;
+using google_breakpad::ByteReader;
+using google_breakpad::CallFrameInfo;
using std::vector;
using testing::InSequence;
@@ -87,7 +86,7 @@ using testing::_;
#ifdef WRITE_ELF
void WriteELFFrameSection(const char *filename, const char *section_name,
- const CFISection &section);
+ const CFISection& section);
#define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section) \
WriteELFFrameSection("cfitest-" name, ".debug_frame", section);
#define PERHAPS_WRITE_EH_FRAME_FILE(name, section) \
@@ -100,7 +99,7 @@ void WriteELFFrameSection(const char *filename, const char *section_name,
class MockCallFrameInfoHandler: public CallFrameInfo::Handler {
public:
MOCK_METHOD6(Entry, bool(size_t offset, uint64_t address, uint64_t length,
- uint8_t version, const string &augmentation,
+ uint8_t version, const string& augmentation,
unsigned return_address));
MOCK_METHOD2(UndefinedRule, bool(uint64_t address, int reg));
MOCK_METHOD2(SameValueRule, bool(uint64_t address, int reg));
@@ -110,10 +109,11 @@ class MockCallFrameInfoHandler: public CallFrameInfo::Handler {
long offset));
MOCK_METHOD3(RegisterRule, bool(uint64_t address, int reg, int base_register));
MOCK_METHOD3(ExpressionRule, bool(uint64_t address, int reg,
- const string &expression));
+ const string& expression));
MOCK_METHOD3(ValExpressionRule, bool(uint64_t address, int reg,
- const string &expression));
+ const string& expression));
MOCK_METHOD0(End, bool());
+ MOCK_METHOD0(Architecture, string());
MOCK_METHOD2(PersonalityRoutine, bool(uint64_t address, bool indirect));
MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64_t address, bool indirect));
MOCK_METHOD0(SignalHandler, bool());
@@ -129,7 +129,7 @@ class MockCallFrameErrorReporter: public CallFrameInfo::Reporter {
MOCK_METHOD2(UnexpectedAddressSize, void(uint64_t, uint8_t));
MOCK_METHOD2(UnexpectedSegmentSize, void(uint64_t, uint8_t));
MOCK_METHOD2(UnrecognizedVersion, void(uint64_t, int version));
- MOCK_METHOD2(UnrecognizedAugmentation, void(uint64_t, const string &));
+ MOCK_METHOD2(UnrecognizedAugmentation, void(uint64_t, const string&));
MOCK_METHOD2(InvalidPointerEncoding, void(uint64_t, uint8_t));
MOCK_METHOD2(UnusablePointerEncoding, void(uint64_t, uint8_t));
MOCK_METHOD2(RestoreInCIE, void(uint64_t, uint64_t));
@@ -218,7 +218,7 @@ TEST_F(CFI, IncompleteLength32) {
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(8);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size() - 2,
&byte_reader, &handler, &reporter);
EXPECT_FALSE(parser.Start());
@@ -244,7 +244,7 @@ TEST_F(CFI, IncompleteLength64) {
ByteReader byte_reader(ENDIANNESS_LITTLE);
byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size() - 4,
&byte_reader, &handler, &reporter);
EXPECT_FALSE(parser.Start());
@@ -269,7 +269,7 @@ TEST_F(CFI, IncompleteId32) {
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(8);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_FALSE(parser.Start());
@@ -296,7 +296,7 @@ TEST_F(CFI, BadId32) {
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(8);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_FALSE(parser.Start());
@@ -306,7 +306,7 @@ TEST_F(CFI, BadId32) {
TEST_F(CFI, SingleCIE) {
CFISection section(kLittleEndian, 4);
section.CIEHeader(0xffe799a8, 0x3398dcdd, 0x6e9683de, 3, "");
- section.Append(10, dwarf2reader::DW_CFA_nop);
+ section.Append(10, google_breakpad::DW_CFA_nop);
section.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("SingleCIE", section);
@@ -318,7 +318,7 @@ TEST_F(CFI, SingleCIE) {
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_LITTLE);
byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_TRUE(parser.Start());
@@ -349,7 +349,7 @@ TEST_F(CFI, OneFDE) {
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_TRUE(parser.Start());
@@ -393,7 +393,7 @@ TEST_F(CFI, TwoFDEsOneCIE) {
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_TRUE(parser.Start());
@@ -443,7 +443,7 @@ TEST_F(CFI, TwoFDEsTwoCIEs) {
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_LITTLE);
byte_reader.SetAddressSize(8);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_TRUE(parser.Start());
@@ -488,7 +488,7 @@ TEST_F(CFI, BadVersion) {
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_FALSE(parser.Start());
@@ -533,7 +533,7 @@ TEST_F(CFI, BadAugmentation) {
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_FALSE(parser.Start());
@@ -568,7 +568,7 @@ TEST_F(CFI, CIEVersion1ReturnColumn) {
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_TRUE(parser.Start());
@@ -603,7 +603,7 @@ TEST_F(CFI, CIEVersion3ReturnColumn) {
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_TRUE(parser.Start());
@@ -633,7 +633,7 @@ TEST_F(CFI, CIEVersion4AdditionalFields) {
string contents;
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_TRUE(parser.Start());
@@ -663,7 +663,7 @@ TEST_F(CFI, CIEVersion4AdditionalFields32BitAddress) {
string contents;
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_TRUE(parser.Start());
@@ -690,7 +690,7 @@ TEST_F(CFI, CIEVersion4AdditionalFieldsUnexpectedAddressSize) {
string contents;
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_FALSE(parser.Start());
@@ -715,7 +715,7 @@ TEST_F(CFI, CIEVersion4AdditionalFieldsUnexpectedSegmentSize) {
string contents;
EXPECT_TRUE(section.GetContents(&contents));
ByteReader byte_reader(ENDIANNESS_BIG);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
EXPECT_FALSE(parser.Start());
@@ -763,7 +763,7 @@ struct CFIInsnFixture: public CFIFixture {
.Mark(&cie_label)
.CIEHeader(code_factor, data_factor, return_register, version,
"")
- .D8(dwarf2reader::DW_CFA_def_cfa)
+ .D8(google_breakpad::DW_CFA_def_cfa)
.ULEB128(cfa_base_register)
.ULEB128(cfa_offset)
.FinishEntry();
@@ -788,7 +788,7 @@ struct CFIInsnFixture: public CFIFixture {
void ParseSection(CFISection *section, bool succeeds = true) {
string contents;
EXPECT_TRUE(section->GetContents(&contents));
- dwarf2reader::Endianness endianness;
+ google_breakpad::Endianness endianness;
if (section->endianness() == kBigEndian)
endianness = ENDIANNESS_BIG;
else {
@@ -797,7 +797,7 @@ struct CFIInsnFixture: public CFIFixture {
}
ByteReader byte_reader(endianness);
byte_reader.SetAddressSize(section->AddressSize());
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter);
if (succeeds)
@@ -823,10 +823,10 @@ TEST_F(CFIInsn, DW_CFA_set_loc) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_set_loc).D32(0xb1ee3e7a)
+ .D8(google_breakpad::DW_CFA_set_loc).D32(0xb1ee3e7a)
// Use DW_CFA_def_cfa to force a handler call that we can use to
// check the effect of the DW_CFA_set_loc.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x4defb431).ULEB128(0x6d17b0ee)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x4defb431).ULEB128(0x6d17b0ee)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_set_loc", section);
@@ -844,10 +844,10 @@ TEST_F(CFIInsn, DW_CFA_advance_loc) {
CFISection section(kBigEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x2a)
+ .D8(google_breakpad::DW_CFA_advance_loc | 0x2a)
// Use DW_CFA_def_cfa to force a handler call that we can use to
// check the effect of the DW_CFA_advance_loc.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x5bbb3715).ULEB128(0x0186c7bf)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x5bbb3715).ULEB128(0x0186c7bf)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc", section);
@@ -866,8 +866,8 @@ TEST_F(CFIInsn, DW_CFA_advance_loc1) {
CFISection section(kLittleEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_advance_loc1).D8(0xd8)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x69d5696a).ULEB128(0x1eb7fc93)
+ .D8(google_breakpad::DW_CFA_advance_loc1).D8(0xd8)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x69d5696a).ULEB128(0x1eb7fc93)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc1", section);
@@ -886,8 +886,8 @@ TEST_F(CFIInsn, DW_CFA_advance_loc2) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_advance_loc2).D16(0x3adb)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x3a368bed).ULEB128(0x3194ee37)
+ .D8(google_breakpad::DW_CFA_advance_loc2).D16(0x3adb)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x3a368bed).ULEB128(0x3194ee37)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc2", section);
@@ -906,8 +906,8 @@ TEST_F(CFIInsn, DW_CFA_advance_loc4) {
CFISection section(kBigEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_advance_loc4).D32(0x15813c88)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x135270c5).ULEB128(0x24bad7cb)
+ .D8(google_breakpad::DW_CFA_advance_loc4).D32(0x15813c88)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x135270c5).ULEB128(0x24bad7cb)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc4", section);
@@ -927,8 +927,8 @@ TEST_F(CFIInsn, DW_CFA_MIPS_advance_loc8) {
CFISection section(kBigEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_MIPS_advance_loc8).D64(0x3c4f3945b92c14ULL)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0xe17ed602).ULEB128(0x3d162e7f)
+ .D8(google_breakpad::DW_CFA_MIPS_advance_loc8).D64(0x3c4f3945b92c14ULL)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0xe17ed602).ULEB128(0x3d162e7f)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc8", section);
@@ -947,7 +947,7 @@ TEST_F(CFIInsn, DW_CFA_def_cfa) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x4e363a85).ULEB128(0x815f9aa7)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x4e363a85).ULEB128(0x815f9aa7)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_def_cfa", section);
@@ -964,8 +964,8 @@ TEST_F(CFIInsn, DW_CFA_def_cfa_sf) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_def_cfa_sf).ULEB128(0x8ccb32b7).LEB128(0x9ea)
- .D8(dwarf2reader::DW_CFA_def_cfa_sf).ULEB128(0x9b40f5da).LEB128(-0x40a2)
+ .D8(google_breakpad::DW_CFA_def_cfa_sf).ULEB128(0x8ccb32b7).LEB128(0x9ea)
+ .D8(google_breakpad::DW_CFA_def_cfa_sf).ULEB128(0x9b40f5da).LEB128(-0x40a2)
.FinishEntry();
EXPECT_CALL(handler,
@@ -985,7 +985,7 @@ TEST_F(CFIInsn, DW_CFA_def_cfa_register) {
CFISection section(kLittleEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_def_cfa_register).ULEB128(0x3e7e9363)
+ .D8(google_breakpad::DW_CFA_def_cfa_register).ULEB128(0x3e7e9363)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1002,8 +1002,8 @@ TEST_F(CFIInsn, DW_CFA_def_cfa_registerBadRule) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("needle in a haystack")
- .D8(dwarf2reader::DW_CFA_def_cfa_register).ULEB128(0xf1b49e49)
+ .D8(google_breakpad::DW_CFA_def_cfa_expression).Block("needle in a haystack")
+ .D8(google_breakpad::DW_CFA_def_cfa_register).ULEB128(0xf1b49e49)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1019,7 +1019,7 @@ TEST_F(CFIInsn, DW_CFA_def_cfa_offset) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
+ .D8(google_breakpad::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1035,8 +1035,8 @@ TEST_F(CFIInsn, DW_CFA_def_cfa_offset_sf) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_def_cfa_offset_sf).LEB128(0x970)
- .D8(dwarf2reader::DW_CFA_def_cfa_offset_sf).LEB128(-0x2cd)
+ .D8(google_breakpad::DW_CFA_def_cfa_offset_sf).LEB128(0x970)
+ .D8(google_breakpad::DW_CFA_def_cfa_offset_sf).LEB128(-0x2cd)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1058,8 +1058,8 @@ TEST_F(CFIInsn, DW_CFA_def_cfa_offsetBadRule) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("six ways to Sunday")
- .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
+ .D8(google_breakpad::DW_CFA_def_cfa_expression).Block("six ways to Sunday")
+ .D8(google_breakpad::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1074,7 +1074,7 @@ TEST_F(CFIInsn, DW_CFA_def_cfa_expression) {
CFISection section(kLittleEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("eating crow")
+ .D8(google_breakpad::DW_CFA_def_cfa_expression).Block("eating crow")
.FinishEntry();
EXPECT_CALL(handler, ValExpressionRule(fde_start, kCFARegister,
@@ -1089,7 +1089,7 @@ TEST_F(CFIInsn, DW_CFA_undefined) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x300ce45d)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x300ce45d)
.FinishEntry();
EXPECT_CALL(handler, UndefinedRule(fde_start, 0x300ce45d))
@@ -1103,7 +1103,7 @@ TEST_F(CFIInsn, DW_CFA_same_value) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x3865a760)
+ .D8(google_breakpad::DW_CFA_same_value).ULEB128(0x3865a760)
.FinishEntry();
EXPECT_CALL(handler, SameValueRule(fde_start, 0x3865a760))
@@ -1117,7 +1117,7 @@ TEST_F(CFIInsn, DW_CFA_offset) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_offset | 0x2c).ULEB128(0x9f6)
+ .D8(google_breakpad::DW_CFA_offset | 0x2c).ULEB128(0x9f6)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1132,7 +1132,7 @@ TEST_F(CFIInsn, DW_CFA_offset_extended) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_offset_extended).ULEB128(0x402b).ULEB128(0xb48)
+ .D8(google_breakpad::DW_CFA_offset_extended).ULEB128(0x402b).ULEB128(0xb48)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1147,9 +1147,9 @@ TEST_F(CFIInsn, DW_CFA_offset_extended_sf) {
CFISection section(kBigEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_offset_extended_sf)
+ .D8(google_breakpad::DW_CFA_offset_extended_sf)
.ULEB128(0x997c23ee).LEB128(0x2d00)
- .D8(dwarf2reader::DW_CFA_offset_extended_sf)
+ .D8(google_breakpad::DW_CFA_offset_extended_sf)
.ULEB128(0x9519eb82).LEB128(-0xa77)
.FinishEntry();
@@ -1170,7 +1170,7 @@ TEST_F(CFIInsn, DW_CFA_val_offset) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x623562fe).ULEB128(0x673)
+ .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0x623562fe).ULEB128(0x673)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1186,8 +1186,8 @@ TEST_F(CFIInsn, DW_CFA_val_offset_sf) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_offset_sf).ULEB128(0x6f4f).LEB128(0xaab)
- .D8(dwarf2reader::DW_CFA_val_offset_sf).ULEB128(0x2483).LEB128(-0x8a2)
+ .D8(google_breakpad::DW_CFA_val_offset_sf).ULEB128(0x6f4f).LEB128(0xaab)
+ .D8(google_breakpad::DW_CFA_val_offset_sf).ULEB128(0x2483).LEB128(-0x8a2)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1207,7 +1207,7 @@ TEST_F(CFIInsn, DW_CFA_register) {
CFISection section(kLittleEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x278d18f9).ULEB128(0x1a684414)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0x278d18f9).ULEB128(0x1a684414)
.FinishEntry();
EXPECT_CALL(handler, RegisterRule(fde_start, 0x278d18f9, 0x1a684414))
@@ -1221,7 +1221,7 @@ TEST_F(CFIInsn, DW_CFA_expression) {
CFISection section(kBigEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0xa1619fb2)
+ .D8(google_breakpad::DW_CFA_expression).ULEB128(0xa1619fb2)
.Block("plus ça change, plus c'est la même chose")
.FinishEntry();
@@ -1238,7 +1238,7 @@ TEST_F(CFIInsn, DW_CFA_val_expression) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0xc5e4a9e3)
+ .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0xc5e4a9e3)
.Block("he who has the gold makes the rules")
.FinishEntry();
@@ -1265,18 +1265,18 @@ TEST_F(CFIInsn, DW_CFA_restore) {
.CIEHeader(code_factor, data_factor, return_register, version,
"")
// Provide a CFA rule, because register rules require them.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x6ca1d50e).ULEB128(0x372e38e8)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x6ca1d50e).ULEB128(0x372e38e8)
// Provide an offset(N) rule for register 0x3c.
- .D8(dwarf2reader::DW_CFA_offset | 0x3c).ULEB128(0xb348)
+ .D8(google_breakpad::DW_CFA_offset | 0x3c).ULEB128(0xb348)
.FinishEntry()
// In the FDE...
.FDEHeader(cie, fde_start, fde_size)
// At a second address, provide a new offset(N) rule for register 0x3c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x13)
- .D8(dwarf2reader::DW_CFA_offset | 0x3c).ULEB128(0x9a50)
+ .D8(google_breakpad::DW_CFA_advance_loc | 0x13)
+ .D8(google_breakpad::DW_CFA_offset | 0x3c).ULEB128(0x9a50)
// At a third address, restore the original rule for register 0x3c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x01)
- .D8(dwarf2reader::DW_CFA_restore | 0x3c)
+ .D8(google_breakpad::DW_CFA_advance_loc | 0x01)
+ .D8(google_breakpad::DW_CFA_restore | 0x3c)
.FinishEntry();
{
@@ -1321,16 +1321,16 @@ TEST_F(CFIInsn, DW_CFA_restoreNoRule) {
.Mark(&cie)
.CIEHeader(code_factor, data_factor, return_register, version, "")
// Provide a CFA rule, because register rules require them.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x470aa334).ULEB128(0x099ef127)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x470aa334).ULEB128(0x099ef127)
.FinishEntry()
// In the FDE...
.FDEHeader(cie, fde_start, fde_size)
// At a second address, provide an offset(N) rule for register 0x2c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x7)
- .D8(dwarf2reader::DW_CFA_offset | 0x2c).ULEB128(0x1f47)
+ .D8(google_breakpad::DW_CFA_advance_loc | 0x7)
+ .D8(google_breakpad::DW_CFA_offset | 0x2c).ULEB128(0x1f47)
// At a third address, restore the (missing) CIE rule for register 0x2c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0xb)
- .D8(dwarf2reader::DW_CFA_restore | 0x2c)
+ .D8(google_breakpad::DW_CFA_advance_loc | 0xb)
+ .D8(google_breakpad::DW_CFA_restore | 0x2c)
.FinishEntry();
{
@@ -1371,20 +1371,20 @@ TEST_F(CFIInsn, DW_CFA_restore_extended) {
.CIEHeader(code_factor, data_factor, return_register, version,
"", true /* dwarf64 */ )
// Provide a CFA rule, because register rules require them.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x56fa0edd).ULEB128(0x097f78a5)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x56fa0edd).ULEB128(0x097f78a5)
// Provide an offset(N) rule for register 0x0f9b8a1c.
- .D8(dwarf2reader::DW_CFA_offset_extended)
+ .D8(google_breakpad::DW_CFA_offset_extended)
.ULEB128(0x0f9b8a1c).ULEB128(0xc979)
.FinishEntry()
// In the FDE...
.FDEHeader(cie, fde_start, fde_size)
// At a second address, provide a new offset(N) rule for reg 0x0f9b8a1c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x3)
- .D8(dwarf2reader::DW_CFA_offset_extended)
+ .D8(google_breakpad::DW_CFA_advance_loc | 0x3)
+ .D8(google_breakpad::DW_CFA_offset_extended)
.ULEB128(0x0f9b8a1c).ULEB128(0x3b7b)
// At a third address, restore the original rule for register 0x0f9b8a1c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x04)
- .D8(dwarf2reader::DW_CFA_restore_extended).ULEB128(0x0f9b8a1c)
+ .D8(google_breakpad::DW_CFA_advance_loc | 0x04)
+ .D8(google_breakpad::DW_CFA_restore_extended).ULEB128(0x0f9b8a1c)
.FinishEntry();
{
@@ -1433,21 +1433,21 @@ TEST_F(CFIInsn, DW_CFA_remember_and_restore_state) {
// 5 offset(N) no rule new "same value" rule
section
// Create the "incoming" state, which we will save and later restore.
- .D8(dwarf2reader::DW_CFA_offset | 2).ULEB128(0x9806)
- .D8(dwarf2reader::DW_CFA_offset | 3).ULEB128(0x995d)
- .D8(dwarf2reader::DW_CFA_offset | 4).ULEB128(0x7055)
- .D8(dwarf2reader::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_offset | 2).ULEB128(0x9806)
+ .D8(google_breakpad::DW_CFA_offset | 3).ULEB128(0x995d)
+ .D8(google_breakpad::DW_CFA_offset | 4).ULEB128(0x7055)
+ .D8(google_breakpad::DW_CFA_remember_state)
// Advance to a new instruction; an implementation could legitimately
// ignore all but the final rule for a given register at a given address.
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
// Create the "outgoing" state, which we will discard.
- .D8(dwarf2reader::DW_CFA_offset | 1).ULEB128(0xea1a)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(2).ULEB128(0x1d2a3767)
- .D8(dwarf2reader::DW_CFA_offset | 3).ULEB128(0xdd29)
- .D8(dwarf2reader::DW_CFA_offset | 5).ULEB128(0xf1ce)
+ .D8(google_breakpad::DW_CFA_offset | 1).ULEB128(0xea1a)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(2).ULEB128(0x1d2a3767)
+ .D8(google_breakpad::DW_CFA_offset | 3).ULEB128(0xdd29)
+ .D8(google_breakpad::DW_CFA_offset | 5).ULEB128(0xf1ce)
// At a third address, restore the incoming state.
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
uint64_t addr = fde_start;
@@ -1496,11 +1496,11 @@ TEST_F(CFIInsn, DW_CFA_remember_and_restore_stateCFA) {
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x90481102)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_def_cfa_offset).ULEB128(0x90481102)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, kCFARegister,
@@ -1519,9 +1519,9 @@ TEST_F(CFIInsn, DW_CFA_nop) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_nop)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x3fb8d4f1).ULEB128(0x078dc67b)
- .D8(dwarf2reader::DW_CFA_nop)
+ .D8(google_breakpad::DW_CFA_nop)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x3fb8d4f1).ULEB128(0x078dc67b)
+ .D8(google_breakpad::DW_CFA_nop)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1536,9 +1536,11 @@ TEST_F(CFIInsn, DW_CFA_GNU_window_save) {
CFISection section(kBigEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_GNU_window_save)
+ .D8(google_breakpad::DW_CFA_GNU_window_save)
.FinishEntry();
+ EXPECT_CALL(handler, Architecture()).WillRepeatedly(Return("sparc"));
+
// Don't include all the rules in any particular sequence.
// The caller's %o0-%o7 have become the callee's %i0-%i7. This is
@@ -1561,9 +1563,9 @@ TEST_F(CFIInsn, DW_CFA_GNU_args_size) {
CFISection section(kLittleEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_GNU_args_size).ULEB128(0xeddfa520)
+ .D8(google_breakpad::DW_CFA_GNU_args_size).ULEB128(0xeddfa520)
// Verify that we see this, meaning we parsed the above properly.
- .D8(dwarf2reader::DW_CFA_offset | 0x23).ULEB128(0x269)
+ .D8(google_breakpad::DW_CFA_offset | 0x23).ULEB128(0x269)
.FinishEntry();
EXPECT_CALL(handler,
@@ -1578,7 +1580,7 @@ TEST_F(CFIInsn, DW_CFA_GNU_negative_offset_extended) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_GNU_negative_offset_extended)
+ .D8(google_breakpad::DW_CFA_GNU_negative_offset_extended)
.ULEB128(0x430cc87a).ULEB128(0x613)
.FinishEntry();
@@ -1599,19 +1601,19 @@ TEST_F(CFIInsn, SkipFDE) {
// CIE, used by all FDEs.
.Mark(&cie)
.CIEHeader(0x010269f2, 0x9177, 0xedca5849, 2, "")
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x42ed390b).ULEB128(0x98f43aad)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x42ed390b).ULEB128(0x98f43aad)
.FinishEntry()
// First FDE.
.FDEHeader(cie, 0xa870ebdd, 0x60f6aa4)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x3a860351).ULEB128(0x6c9a6bcf)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0x3a860351).ULEB128(0x6c9a6bcf)
.FinishEntry()
// Second FDE.
.FDEHeader(cie, 0xc534f7c0, 0xf6552e9, true /* dwarf64 */)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x1b62c234).ULEB128(0x26586b18)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0x1b62c234).ULEB128(0x26586b18)
.FinishEntry()
// Third FDE.
.FDEHeader(cie, 0xf681cfc8, 0x7e4594e)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x26c53934).ULEB128(0x18eeb8a4)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0x26c53934).ULEB128(0x18eeb8a4)
.FinishEntry();
{
@@ -1652,8 +1654,8 @@ TEST_F(CFIInsn, QuitMidentry) {
CFISection section(kLittleEndian, 8);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0xe0cf850d).ULEB128(0x15aab431)
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x46750aa5).Block("meat")
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0xe0cf850d).ULEB128(0x15aab431)
+ .D8(google_breakpad::DW_CFA_expression).ULEB128(0x46750aa5).Block("meat")
.FinishEntry();
EXPECT_CALL(handler, RegisterRule(fde_start, 0xe0cf850d, 0x15aab431))
@@ -1670,10 +1672,10 @@ TEST_F(CFIRestore, RestoreUndefinedRuleUnchanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x0bac878e)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x0bac878e)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, UndefinedRule(fde_start, 0x0bac878e))
@@ -1687,12 +1689,12 @@ TEST_F(CFIRestore, RestoreUndefinedRuleChanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x7dedff5f)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x7dedff5f)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x7dedff5f)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_same_value).ULEB128(0x7dedff5f)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, UndefinedRule(fde_start, 0x7dedff5f))
@@ -1710,10 +1712,10 @@ TEST_F(CFIRestore, RestoreSameValueRuleUnchanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0xadbc9b3a)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_same_value).ULEB128(0xadbc9b3a)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, SameValueRule(fde_start, 0xadbc9b3a))
@@ -1727,12 +1729,12 @@ TEST_F(CFIRestore, RestoreSameValueRuleChanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x3d90dcb5)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x3d90dcb5)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_same_value).ULEB128(0x3d90dcb5)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x3d90dcb5)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, SameValueRule(fde_start, 0x3d90dcb5))
@@ -1750,10 +1752,10 @@ TEST_F(CFIRestore, RestoreOffsetRuleUnchanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_offset | 0x14).ULEB128(0xb6f)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_offset | 0x14).ULEB128(0xb6f)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, OffsetRule(fde_start, 0x14,
@@ -1768,12 +1770,12 @@ TEST_F(CFIRestore, RestoreOffsetRuleChanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0xeb7)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x21)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_offset | 0x21).ULEB128(0xeb7)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x21)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, OffsetRule(fde_start, 0x21,
@@ -1793,12 +1795,12 @@ TEST_F(CFIRestore, RestoreOffsetRuleChangedOffset) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0x134)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0xf4f)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_offset | 0x21).ULEB128(0x134)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_offset | 0x21).ULEB128(0xf4f)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, OffsetRule(fde_start, 0x21,
@@ -1819,10 +1821,10 @@ TEST_F(CFIRestore, RestoreValOffsetRuleUnchanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x829caee6).ULEB128(0xe4c)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0x829caee6).ULEB128(0xe4c)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x829caee6,
@@ -1837,12 +1839,12 @@ TEST_F(CFIRestore, RestoreValOffsetRuleChanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0xf17c36d6).ULEB128(0xeb7)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xf17c36d6)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0xf17c36d6).ULEB128(0xeb7)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0xf17c36d6)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, ValOffsetRule(fde_start, 0xf17c36d6,
@@ -1862,12 +1864,12 @@ TEST_F(CFIRestore, RestoreValOffsetRuleChangedValOffset) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0x562)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0xe88)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0x562)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0xe88)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x2cf0ab1b,
@@ -1888,10 +1890,10 @@ TEST_F(CFIRestore, RestoreRegisterRuleUnchanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x77514acc).ULEB128(0x464de4ce)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0x77514acc).ULEB128(0x464de4ce)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, RegisterRule(fde_start, 0x77514acc, 0x464de4ce))
@@ -1905,12 +1907,12 @@ TEST_F(CFIRestore, RestoreRegisterRuleChanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0xe39acce5).ULEB128(0x095f1559)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xe39acce5)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0xe39acce5).ULEB128(0x095f1559)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0xe39acce5)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, RegisterRule(fde_start, 0xe39acce5, 0x095f1559))
@@ -1929,12 +1931,12 @@ TEST_F(CFIRestore, RestoreRegisterRuleChangedRegister) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0x16607d6a)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0xbabb4742)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0x16607d6a)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0xbabb4742)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, RegisterRule(fde_start, 0xd40e21b1, 0x16607d6a))
@@ -1954,10 +1956,10 @@ TEST_F(CFIRestore, RestoreExpressionRuleUnchanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x666ae152).Block("dwarf")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_expression).ULEB128(0x666ae152).Block("dwarf")
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, ExpressionRule(fde_start, 0x666ae152, "dwarf"))
@@ -1971,12 +1973,12 @@ TEST_F(CFIRestore, RestoreExpressionRuleChanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0xb5ca5c46).Block("elf")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xb5ca5c46)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_expression).ULEB128(0xb5ca5c46).Block("elf")
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0xb5ca5c46)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, ExpressionRule(fde_start, 0xb5ca5c46, "elf"))
@@ -1995,12 +1997,12 @@ TEST_F(CFIRestore, RestoreExpressionRuleChangedExpression) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x500f5739).Block("smurf")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x500f5739).Block("orc")
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_expression).ULEB128(0x500f5739).Block("smurf")
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_expression).ULEB128(0x500f5739).Block("orc")
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, ExpressionRule(fde_start, 0x500f5739, "smurf"))
@@ -2021,11 +2023,11 @@ TEST_F(CFIRestore, RestoreValExpressionRuleUnchanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x666ae152)
+ .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0x666ae152)
.Block("hideous")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x666ae152, "hideous"))
@@ -2039,13 +2041,13 @@ TEST_F(CFIRestore, RestoreValExpressionRuleChanged) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0xb5ca5c46)
+ .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0xb5ca5c46)
.Block("revolting")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xb5ca5c46)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0xb5ca5c46)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChanged", section);
@@ -2066,14 +2068,14 @@ TEST_F(CFIRestore, RestoreValExpressionRuleChangedValExpression) {
CFISection section(kLittleEndian, 4);
StockCIEAndFDE(&section);
section
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x500f5739)
+ .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0x500f5739)
.Block("repulsive")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x500f5739)
+ .D8(google_breakpad::DW_CFA_remember_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0x500f5739)
.Block("nauseous")
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
+ .D8(google_breakpad::DW_CFA_advance_loc | 1)
+ .D8(google_breakpad::DW_CFA_restore_state)
.FinishEntry();
PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChangedValExpression",
@@ -2110,7 +2112,7 @@ struct EHFrameFixture: public CFIInsnFixture {
EXPECT_TRUE(section->ContainsEHFrame());
string contents;
EXPECT_TRUE(section->GetContents(&contents));
- dwarf2reader::Endianness endianness;
+ google_breakpad::Endianness endianness;
if (section->endianness() == kBigEndian)
endianness = ENDIANNESS_BIG;
else {
@@ -2120,10 +2122,10 @@ struct EHFrameFixture: public CFIInsnFixture {
ByteReader byte_reader(endianness);
byte_reader.SetAddressSize(section->AddressSize());
byte_reader.SetCFIDataBase(encoded_pointer_bases.cfi,
- reinterpret_cast<const uint8_t *>(contents.data()));
+ reinterpret_cast<const uint8_t*>(contents.data()));
byte_reader.SetTextBase(encoded_pointer_bases.text);
byte_reader.SetDataBase(encoded_pointer_bases.data);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
+ CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
contents.size(),
&byte_reader, &handler, &reporter, true);
if (succeeds)
@@ -2142,11 +2144,11 @@ TEST_F(EHFrame, Terminator) {
section
.Mark(&cie)
.CIEHeader(9968, 2466, 67, 1, "")
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(3772).ULEB128(1372)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(3772).ULEB128(1372)
.FinishEntry()
.FDEHeader(cie, 0x848037a1, 0x7b30475e)
- .D8(dwarf2reader::DW_CFA_set_loc).D32(0x17713850)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(5721)
+ .D8(google_breakpad::DW_CFA_set_loc).D32(0x17713850)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(5721)
.FinishEntry()
.D32(0) // Terminate the sequence.
// This FDE should be ignored.
@@ -2172,12 +2174,12 @@ TEST_F(EHFrame, Terminator) {
// The parser should recognize the Linux Standards Base 'z' augmentations.
TEST_F(EHFrame, SimpleFDE) {
DwarfPointerEncoding lsda_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect
- | dwarf2reader::DW_EH_PE_datarel
- | dwarf2reader::DW_EH_PE_sdata2);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect
+ | google_breakpad::DW_EH_PE_datarel
+ | google_breakpad::DW_EH_PE_sdata2);
DwarfPointerEncoding fde_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
- | dwarf2reader::DW_EH_PE_udata2);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_textrel
+ | google_breakpad::DW_EH_PE_udata2);
section.SetPointerEncoding(fde_encoding);
section.SetEncodedPointerBases(encoded_pointer_bases);
@@ -2187,17 +2189,17 @@ TEST_F(EHFrame, SimpleFDE) {
.CIEHeader(4873, 7012, 100, 1, "zSLPR")
.ULEB128(7) // Augmentation data length
.D8(lsda_encoding) // LSDA pointer format
- .D8(dwarf2reader::DW_EH_PE_pcrel) // personality pointer format
- .EncodedPointer(0x97baa00, dwarf2reader::DW_EH_PE_pcrel) // and value
+ .D8(google_breakpad::DW_EH_PE_pcrel) // personality pointer format
+ .EncodedPointer(0x97baa00, google_breakpad::DW_EH_PE_pcrel) // and value
.D8(fde_encoding) // FDE pointer format
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(6706).ULEB128(31)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(6706).ULEB128(31)
.FinishEntry()
.FDEHeader(cie, 0x540f6b56, 0xf686)
.ULEB128(2) // Augmentation data length
.EncodedPointer(0xe3eab475, lsda_encoding) // LSDA pointer, signed
- .D8(dwarf2reader::DW_CFA_set_loc)
+ .D8(google_breakpad::DW_CFA_set_loc)
.EncodedPointer(0x540fa4ce, fde_encoding)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x675e)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x675e)
.FinishEntry()
.D32(0); // terminator
@@ -2228,12 +2230,12 @@ TEST_F(EHFrame, EmptyZ) {
.Mark(&cie)
.CIEHeader(5955, 5805, 228, 1, "z")
.ULEB128(0) // Augmentation data length
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(3629).ULEB128(247)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(3629).ULEB128(247)
.FinishEntry()
.FDEHeader(cie, 0xda007738, 0xfb55c641)
.ULEB128(0) // Augmentation data length
- .D8(dwarf2reader::DW_CFA_advance_loc1).D8(11)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(3769)
+ .D8(google_breakpad::DW_CFA_advance_loc1).D8(11)
+ .D8(google_breakpad::DW_CFA_undefined).ULEB128(3769)
.FinishEntry();
PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.EmptyZ", section);
@@ -2257,12 +2259,12 @@ TEST_F(EHFrame, BadZ) {
.Mark(&cie)
.CIEHeader(6937, 1045, 142, 1, "zQ")
.ULEB128(0) // Augmentation data length
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(9006).ULEB128(7725)
+ .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(9006).ULEB128(7725)
.FinishEntry()
.FDEHeader(cie, 0x1293efa8, 0x236f53f2)
.ULEB128(0) // Augmentation data length
- .D8(dwarf2reader::DW_CFA_advance_loc | 12)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(5667).ULEB128(3462)
+ .D8(google_breakpad::DW_CFA_advance_loc | 12)
+ .D8(google_breakpad::DW_CFA_register).ULEB128(5667).ULEB128(3462)
.FinishEntry();
PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.BadZ", section);
@@ -2276,8 +2278,8 @@ TEST_F(EHFrame, BadZ) {
TEST_F(EHFrame, zL) {
Label cie;
DwarfPointerEncoding lsda_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_funcrel
- | dwarf2reader::DW_EH_PE_udata2);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_funcrel
+ | google_breakpad::DW_EH_PE_udata2);
section
.Mark(&cie)
.CIEHeader(9285, 9959, 54, 1, "zL")
@@ -2306,8 +2308,8 @@ TEST_F(EHFrame, zL) {
TEST_F(EHFrame, zP) {
Label cie;
DwarfPointerEncoding personality_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_datarel
- | dwarf2reader::DW_EH_PE_udata2);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_datarel
+ | google_breakpad::DW_EH_PE_udata2);
section
.Mark(&cie)
.CIEHeader(1097, 6313, 17, 1, "zP")
@@ -2335,8 +2337,8 @@ TEST_F(EHFrame, zP) {
TEST_F(EHFrame, zR) {
Label cie;
DwarfPointerEncoding pointer_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
- | dwarf2reader::DW_EH_PE_sdata2);
+ DwarfPointerEncoding(google_breakpad::DW_EH_PE_textrel
+ | google_breakpad::DW_EH_PE_sdata2);
section.SetPointerEncoding(pointer_encoding);
section
.Mark(&cie)
@@ -2468,7 +2470,7 @@ struct ELFSectionHeader {
uint64_t entry_size;
};
-void AppendSectionHeader(CFISection *table, const ELFSectionHeader &header) {
+void AppendSectionHeader(CFISection* table, const ELFSectionHeader& header) {
(*table)
.D32(header.name) // name, index in string tbl
.D32(header.type) // type
@@ -2483,7 +2485,7 @@ void AppendSectionHeader(CFISection *table, const ELFSectionHeader &header) {
}
void WriteELFFrameSection(const char *filename, const char *cfi_name,
- const CFISection &cfi) {
+ const CFISection& cfi) {
int elf_class = cfi.AddressSize() == 4 ? ELFCLASS32 : ELFCLASS64;
int elf_data = (cfi.endianness() == kBigEndian
? ELFDATA2MSB : ELFDATA2LSB);
diff --git a/src/common/dwarf/dwarf2reader_die_unittest.cc b/src/common/dwarf/dwarf2reader_die_unittest.cc
index ca44cad0..fc639a64 100644
--- a/src/common/dwarf/dwarf2reader_die_unittest.cc
+++ b/src/common/dwarf/dwarf2reader_die_unittest.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
+// Copyright 2012 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -29,7 +28,7 @@
// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-// dwarf2reader_die_unittest.cc: Unit tests for dwarf2reader::CompilationUnit
+// dwarf2reader_die_unittest.cc: Unit tests for google_breakpad::CompilationUnit
#include <stdint.h>
#include <stdlib.h>
@@ -51,16 +50,16 @@ using google_breakpad::test_assembler::Section;
using google_breakpad::test_assembler::kBigEndian;
using google_breakpad::test_assembler::kLittleEndian;
-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 google_breakpad::ByteReader;
+using google_breakpad::CompilationUnit;
+using google_breakpad::Dwarf2Handler;
+using google_breakpad::DwarfAttribute;
+using google_breakpad::DwarfForm;
+using google_breakpad::DwarfHasChild;
+using google_breakpad::DwarfTag;
+using google_breakpad::ENDIANNESS_BIG;
+using google_breakpad::ENDIANNESS_LITTLE;
+using google_breakpad::SectionMap;
using std::vector;
using testing::InSequence;
@@ -93,7 +92,7 @@ class MockDwarf2Handler: public Dwarf2Handler {
MOCK_METHOD5(ProcessAttributeBuffer, void(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
- const uint8_t *data,
+ const uint8_t* data,
uint64_t len));
MOCK_METHOD4(ProcessAttributeString, void(uint64_t offset,
enum DwarfAttribute attr,
@@ -128,17 +127,17 @@ struct DIEFixture {
// 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() {
+ 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
- = reinterpret_cast<const uint8_t *>(info_contents.data());
+ = reinterpret_cast<const uint8_t*>(info_contents.data());
section_map[".debug_info"].second = info_contents.size();
section_map[".debug_abbrev"].first
- = reinterpret_cast<const uint8_t *>(abbrevs_contents.data());
+ = reinterpret_cast<const uint8_t*>(abbrevs_contents.data());
section_map[".debug_abbrev"].second = abbrevs_contents.size();
return section_map;
}
@@ -152,13 +151,15 @@ struct DIEFixture {
struct DwarfHeaderParams {
DwarfHeaderParams(Endianness endianness, size_t format_size,
- int version, size_t address_size)
+ int version, size_t address_size, int header_type)
: endianness(endianness), format_size(format_size),
- version(version), address_size(address_size) { }
+ version(version), address_size(address_size), header_type(header_type)
+ { }
Endianness endianness;
size_t format_size; // 4-byte or 8-byte DWARF offsets
int version;
size_t address_size;
+ int header_type; // DW_UT_{compile, type, partial, skeleton, etc}
};
class DwarfHeader: public DIEFixture,
@@ -166,16 +167,17 @@ class DwarfHeader: public DIEFixture,
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)
+ abbrevs.Abbrev(1, google_breakpad::DW_TAG_compile_unit,
+ google_breakpad::DW_children_yes)
+ .Attribute(google_breakpad::DW_AT_name, google_breakpad::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)
+ info.Header(GetParam().version, abbrev_table, GetParam().address_size,
+ google_breakpad::DW_UT_compile)
.ULEB128(1) // DW_TAG_compile_unit, with children
.AppendCString("sam") // DW_AT_name, DW_FORM_string
.D8(0); // end of children
@@ -188,10 +190,10 @@ TEST_P(DwarfHeader, Header) {
GetParam().format_size, _,
GetParam().version))
.WillOnce(Return(true));
- EXPECT_CALL(handler, StartDIE(_, dwarf2reader::DW_TAG_compile_unit))
+ EXPECT_CALL(handler, StartDIE(_, google_breakpad::DW_TAG_compile_unit))
.WillOnce(Return(true));
- EXPECT_CALL(handler, ProcessAttributeString(_, dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_string,
+ EXPECT_CALL(handler, ProcessAttributeString(_, google_breakpad::DW_AT_name,
+ google_breakpad::DW_FORM_string,
"sam"))
.WillOnce(Return());
EXPECT_CALL(handler, EndDIE(_))
@@ -204,44 +206,91 @@ TEST_P(DwarfHeader, Header) {
EXPECT_EQ(parser.Start(), info_contents.size());
}
-INSTANTIATE_TEST_CASE_P(
+TEST_P(DwarfHeader, TypeUnitHeader) {
+ Label abbrev_table = abbrevs.Here();
+ int version = 5;
+ abbrevs.Abbrev(1, google_breakpad::DW_TAG_type_unit,
+ google_breakpad::DW_children_yes)
+ .Attribute(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_string)
+ .EndAbbrev()
+ .EndTable();
+
+ info.set_format_size(GetParam().format_size);
+ info.set_endianness(GetParam().endianness);
+
+ info.Header(version, abbrev_table, GetParam().address_size,
+ google_breakpad::DW_UT_type)
+ .ULEB128(0x41) // DW_TAG_type_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, _,
+ version))
+ .WillOnce(Return(true));
+ // If the type unit is handled properly, these calls will be skipped.
+ EXPECT_CALL(handler, StartDIE(_, google_breakpad::DW_TAG_type_unit))
+ .Times(0);
+ EXPECT_CALL(handler, ProcessAttributeString(_, google_breakpad::DW_AT_name,
+ google_breakpad::DW_FORM_string,
+ "sam"))
+ .Times(0);
+ EXPECT_CALL(handler, EndDIE(_))
+ .Times(0);
+ }
+
+ 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_SUITE_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)));
+ ::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 2, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 3, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 3, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 4, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 4, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 2, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 2, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 3, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 3, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 4, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 4, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 5, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 5, 8, 1),
+ DwarfHeaderParams(kBigEndian, 4, 2, 4, 1),
+ DwarfHeaderParams(kBigEndian, 4, 2, 8, 1),
+ DwarfHeaderParams(kBigEndian, 4, 3, 4, 1),
+ DwarfHeaderParams(kBigEndian, 4, 3, 8, 1),
+ DwarfHeaderParams(kBigEndian, 4, 4, 4, 1),
+ DwarfHeaderParams(kBigEndian, 4, 4, 8, 1),
+ DwarfHeaderParams(kBigEndian, 8, 2, 4, 1),
+ DwarfHeaderParams(kBigEndian, 8, 2, 8, 1),
+ DwarfHeaderParams(kBigEndian, 8, 3, 4, 1),
+ DwarfHeaderParams(kBigEndian, 8, 3, 8, 1),
+ DwarfHeaderParams(kBigEndian, 8, 4, 4, 1),
+ DwarfHeaderParams(kBigEndian, 8, 4, 8, 1),
+ DwarfHeaderParams(kBigEndian, 8, 5, 4, 1),
+ DwarfHeaderParams(kBigEndian, 8, 5, 8, 1)));
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,
+ 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)
+ abbrevs.Abbrev(1, tag, google_breakpad::DW_children_no)
.Attribute(name, form)
.EndAbbrev()
.EndTable();
@@ -249,14 +298,15 @@ struct DwarfFormsFixture: public DIEFixture {
// 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)
+ info.Header(params.version, abbrev_table, params.address_size,
+ google_breakpad::DW_UT_compile)
.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,
+ void ExpectBeginCompilationUnit(const DwarfHeaderParams& params,
DwarfTag tag, uint64_t offset=0) {
EXPECT_CALL(handler,
StartCompilationUnit(offset, params.address_size,
@@ -275,7 +325,7 @@ struct DwarfFormsFixture: public DIEFixture {
.WillOnce(Return());
}
- void ParseCompilationUnit(const DwarfHeaderParams &params,
+ void ParseCompilationUnit(const DwarfHeaderParams& params,
uint64_t offset=0) {
ByteReader byte_reader(params.endianness == kLittleEndian ?
ENDIANNESS_LITTLE : ENDIANNESS_BIG);
@@ -291,9 +341,9 @@ 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);
+ StartSingleAttributeDIE(GetParam(), google_breakpad::DW_TAG_compile_unit,
+ google_breakpad::DW_AT_low_pc,
+ google_breakpad::DW_FORM_addr);
uint64_t value;
if (GetParam().address_size == 4) {
value = 0xc8e9ffcc;
@@ -304,9 +354,93 @@ TEST_P(DwarfForms, addr) {
}
info.Finish();
- ExpectBeginCompilationUnit(GetParam(), dwarf2reader::DW_TAG_compile_unit);
- EXPECT_CALL(handler, ProcessAttributeUnsigned(_, dwarf2reader::DW_AT_low_pc,
- dwarf2reader::DW_FORM_addr,
+ ExpectBeginCompilationUnit(GetParam(), google_breakpad::DW_TAG_compile_unit);
+ EXPECT_CALL(handler, ProcessAttributeUnsigned(_, google_breakpad::DW_AT_low_pc,
+ google_breakpad::DW_FORM_addr,
+ value))
+ .InSequence(s)
+ .WillOnce(Return());
+ ExpectEndCompilationUnit();
+
+ ParseCompilationUnit(GetParam());
+}
+
+TEST_P(DwarfForms, strx1) {
+ if (GetParam().version != 5) {
+ return;
+ }
+ Label abbrev_table = abbrevs.Here();
+ abbrevs.Abbrev(1, google_breakpad::DW_TAG_compile_unit,
+ google_breakpad::DW_children_no)
+ .Attribute(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_strx1)
+ .Attribute(google_breakpad::DW_AT_low_pc, google_breakpad::DW_FORM_addr)
+ .Attribute(google_breakpad::DW_AT_str_offsets_base,
+ google_breakpad::DW_FORM_sec_offset)
+ .EndAbbrev()
+ .EndTable();
+
+ info.set_format_size(GetParam().format_size);
+ info.set_endianness(GetParam().endianness);
+ info.Header(GetParam().version, abbrev_table, GetParam().address_size,
+ google_breakpad::DW_UT_compile)
+ .ULEB128(1) // abbrev index
+ .D8(2); // string index
+
+ uint64_t value;
+ uint64_t offsets_base;
+ if (GetParam().address_size == 4) {
+ value = 0xc8e9ffcc;
+ offsets_base = 8;
+ info.D32(value); // low pc
+ info.D32(offsets_base); // str_offsets_base
+ } else {
+ value = 0xe942517fc2768564ULL;
+ offsets_base = 16;
+ info.D64(value); // low_pc
+ info.D64(offsets_base); // str_offsets_base
+ }
+ info.Finish();
+
+ Section debug_strings;
+ // no header, just a series of null-terminated strings.
+ debug_strings.AppendCString("apple"); // offset = 0
+ debug_strings.AppendCString("bird"); // offset = 6
+ debug_strings.AppendCString("canary"); // offset = 11
+ debug_strings.AppendCString("dinosaur"); // offset = 18
+
+ Section str_offsets;
+ str_offsets.set_endianness(GetParam().endianness);
+ // Header for .debug_str_offsets
+ if (GetParam().address_size == 4) {
+ str_offsets.D32(24); // section length (4 bytes)
+ } else {
+ str_offsets.D32(0xffffffff);
+ str_offsets.D64(48); // section length (12 bytes)
+ }
+ str_offsets.D16(GetParam().version); // version (2 bytes)
+ str_offsets.D16(0); // padding (2 bytes)
+
+ // .debug_str_offsets data (the offsets)
+ if (GetParam().address_size == 4) {
+ str_offsets.D32(0);
+ str_offsets.D32(6);
+ str_offsets.D32(11);
+ str_offsets.D32(18);
+ } else {
+ str_offsets.D64(0);
+ str_offsets.D64(6);
+ str_offsets.D64(11);
+ str_offsets.D64(18);
+ }
+
+
+ ExpectBeginCompilationUnit(GetParam(), google_breakpad::DW_TAG_compile_unit);
+ EXPECT_CALL(handler, ProcessAttributeString(_, google_breakpad::DW_AT_name,
+ google_breakpad::DW_FORM_strx1,
+ "bird"))
+ .WillOnce(Return());
+ EXPECT_CALL(handler, ProcessAttributeUnsigned(_, google_breakpad::DW_AT_low_pc,
+ google_breakpad::DW_FORM_addr,
value))
.InSequence(s)
.WillOnce(Return());
@@ -318,13 +452,13 @@ TEST_P(DwarfForms, addr) {
TEST_P(DwarfForms, block2_empty) {
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x16e4d2f7,
(DwarfAttribute) 0xe52c4463,
- dwarf2reader::DW_FORM_block2);
+ google_breakpad::DW_FORM_block2);
info.D16(0);
info.Finish();
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x16e4d2f7);
EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xe52c4463,
- dwarf2reader::DW_FORM_block2,
+ google_breakpad::DW_FORM_block2,
_, 0))
.InSequence(s)
.WillOnce(Return());
@@ -336,7 +470,7 @@ TEST_P(DwarfForms, block2_empty) {
TEST_P(DwarfForms, block2) {
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x16e4d2f7,
(DwarfAttribute) 0xe52c4463,
- dwarf2reader::DW_FORM_block2);
+ google_breakpad::DW_FORM_block2);
unsigned char data[258];
memset(data, '*', sizeof(data));
info.D16(sizeof(data))
@@ -345,7 +479,7 @@ TEST_P(DwarfForms, block2) {
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x16e4d2f7);
EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xe52c4463,
- dwarf2reader::DW_FORM_block2,
+ google_breakpad::DW_FORM_block2,
Pointee('*'), 258))
.InSequence(s)
.WillOnce(Return());
@@ -357,14 +491,14 @@ TEST_P(DwarfForms, block2) {
TEST_P(DwarfForms, flag_present) {
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x3e449ac2,
(DwarfAttribute) 0x359d1972,
- dwarf2reader::DW_FORM_flag_present);
+ google_breakpad::DW_FORM_flag_present);
// DW_FORM_flag_present occupies no space in the DIE.
info.Finish();
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x3e449ac2);
EXPECT_CALL(handler,
ProcessAttributeUnsigned(_, (DwarfAttribute) 0x359d1972,
- dwarf2reader::DW_FORM_flag_present,
+ google_breakpad::DW_FORM_flag_present,
1))
.InSequence(s)
.WillOnce(Return());
@@ -376,7 +510,7 @@ TEST_P(DwarfForms, flag_present) {
TEST_P(DwarfForms, sec_offset) {
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x1d971689,
(DwarfAttribute) 0xa060bfd1,
- dwarf2reader::DW_FORM_sec_offset);
+ google_breakpad::DW_FORM_sec_offset);
uint64_t value;
if (GetParam().format_size == 4) {
value = 0xacc9c388;
@@ -389,7 +523,7 @@ TEST_P(DwarfForms, sec_offset) {
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x1d971689);
EXPECT_CALL(handler, ProcessAttributeUnsigned(_, (DwarfAttribute) 0xa060bfd1,
- dwarf2reader::DW_FORM_sec_offset,
+ google_breakpad::DW_FORM_sec_offset,
value))
.InSequence(s)
.WillOnce(Return());
@@ -401,14 +535,14 @@ TEST_P(DwarfForms, sec_offset) {
TEST_P(DwarfForms, exprloc) {
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0xb6d167bb,
(DwarfAttribute) 0xba3ae5cb,
- dwarf2reader::DW_FORM_exprloc);
+ google_breakpad::DW_FORM_exprloc);
info.ULEB128(29)
.Append(29, 173);
info.Finish();
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0xb6d167bb);
EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xba3ae5cb,
- dwarf2reader::DW_FORM_exprloc,
+ google_breakpad::DW_FORM_exprloc,
Pointee(173), 29))
.InSequence(s)
.WillOnce(Return());
@@ -420,13 +554,13 @@ TEST_P(DwarfForms, exprloc) {
TEST_P(DwarfForms, ref_sig8) {
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x253e7b2b,
(DwarfAttribute) 0xd708d908,
- dwarf2reader::DW_FORM_ref_sig8);
+ google_breakpad::DW_FORM_ref_sig8);
info.D64(0xf72fa0cb6ddcf9d6ULL);
info.Finish();
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b);
EXPECT_CALL(handler, ProcessAttributeSignature(_, (DwarfAttribute) 0xd708d908,
- dwarf2reader::DW_FORM_ref_sig8,
+ google_breakpad::DW_FORM_ref_sig8,
0xf72fa0cb6ddcf9d6ULL))
.InSequence(s)
.WillOnce(Return());
@@ -444,13 +578,13 @@ TEST_P(DwarfForms, ref_sig8_not_first) {
info.Append(98, '*');
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x253e7b2b,
(DwarfAttribute) 0xd708d908,
- dwarf2reader::DW_FORM_ref_sig8);
+ google_breakpad::DW_FORM_ref_sig8);
info.D64(0xf72fa0cb6ddcf9d6ULL);
info.Finish();
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b, 98);
EXPECT_CALL(handler, ProcessAttributeSignature(_, (DwarfAttribute) 0xd708d908,
- dwarf2reader::DW_FORM_ref_sig8,
+ google_breakpad::DW_FORM_ref_sig8,
0xf72fa0cb6ddcf9d6ULL))
.InSequence(s)
.WillOnce(Return());
@@ -459,31 +593,371 @@ TEST_P(DwarfForms, ref_sig8_not_first) {
ParseCompilationUnit(GetParam(), 98);
}
+TEST_P(DwarfForms, implicit_const) {
+ const DwarfHeaderParams& params = GetParam();
+ const uint64_t implicit_constant_value = 0x1234;
+ // Create the abbreviation table.
+ Label abbrev_table = abbrevs.Here();
+ abbrevs.Abbrev(1, (DwarfTag) 0x253e7b2b, google_breakpad::DW_children_no)
+ .Attribute((DwarfAttribute) 0xd708d908,
+ google_breakpad::DW_FORM_implicit_const)
+ .ULEB128(implicit_constant_value);
+ abbrevs.EndAbbrev().EndTable();
+
+ info.set_format_size(params.format_size);
+ info.set_endianness(params.endianness);
+ info.Header(params.version, abbrev_table, params.address_size,
+ google_breakpad::DW_UT_compile)
+ .ULEB128(1); // abbrev code
+ info.Finish();
+
+ ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b);
+ EXPECT_CALL(handler,
+ ProcessAttributeUnsigned(_, (DwarfAttribute) 0xd708d908,
+ google_breakpad::DW_FORM_implicit_const,
+ implicit_constant_value))
+ .InSequence(s)
+ .WillOnce(Return());
+ ExpectEndCompilationUnit();
+
+ ParseCompilationUnit(GetParam());
+}
+
// Tests for the other attribute forms could go here.
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_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)));
+ ::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 2, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 3, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 3, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 4, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 4, 4, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 2, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 2, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 3, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 3, 8, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 4, 4, 1),
+ DwarfHeaderParams(kLittleEndian, 8, 4, 8, 1),
+ DwarfHeaderParams(kBigEndian, 4, 2, 4, 1),
+ DwarfHeaderParams(kBigEndian, 4, 2, 8, 1),
+ DwarfHeaderParams(kBigEndian, 4, 3, 4, 1),
+ DwarfHeaderParams(kBigEndian, 4, 3, 8, 1),
+ DwarfHeaderParams(kBigEndian, 4, 4, 4, 1),
+ DwarfHeaderParams(kBigEndian, 4, 4, 8, 1),
+ DwarfHeaderParams(kBigEndian, 8, 2, 4, 1),
+ DwarfHeaderParams(kBigEndian, 8, 2, 8, 1),
+ DwarfHeaderParams(kBigEndian, 8, 3, 4, 1),
+ DwarfHeaderParams(kBigEndian, 8, 3, 8, 1),
+ DwarfHeaderParams(kBigEndian, 8, 4, 4, 1),
+ DwarfHeaderParams(kBigEndian, 8, 4, 8, 1)));
+
+class MockRangeListHandler: public google_breakpad::RangeListHandler {
+ public:
+ MOCK_METHOD(void, AddRange, (uint64_t begin, uint64_t end));
+ MOCK_METHOD(void, Finish, ());
+};
+
+TEST(RangeList, Dwarf4ReadRangeList) {
+ using google_breakpad::RangeListReader;
+ using google_breakpad::DW_FORM_sec_offset;
+
+ // Create a dwarf4 .debug_ranges section.
+ google_breakpad::test_assembler::Section ranges(kBigEndian);
+ std::string padding_offset = "padding offset";
+ ranges.Append(padding_offset);
+ const uint64_t section_offset = ranges.Size();
+ ranges.D32(1).D32(2); // (2, 3)
+ ranges.D32(0xFFFFFFFF).D32(3); // base_address = 3.
+ ranges.D32(1).D32(2); // (4, 5)
+ ranges.D32(0).D32(1); // (3, 4) An out of order entry is legal.
+ ranges.D32(0).D32(0); // End of range.
+
+ std::string section_contents;
+ ranges.GetContents(&section_contents);
+
+ ByteReader byte_reader(ENDIANNESS_BIG);
+ byte_reader.SetAddressSize(4);
+
+ RangeListReader::CURangesInfo cu_info;
+ // Only set the fields that matter for dwarf 4.
+ cu_info.version_ = 4;
+ cu_info.base_address_ = 1;
+ cu_info.buffer_ = reinterpret_cast<const uint8_t*>(section_contents.data());
+ cu_info.size_ = section_contents.size();
+
+ MockRangeListHandler handler;
+ google_breakpad::RangeListReader range_list_reader(&byte_reader, &cu_info,
+ &handler);
+ EXPECT_CALL(handler, AddRange(2, 3));
+ EXPECT_CALL(handler, AddRange(4, 5));
+ EXPECT_CALL(handler, AddRange(3, 4));
+ EXPECT_CALL(handler, Finish());
+ EXPECT_TRUE(range_list_reader.ReadRanges(DW_FORM_sec_offset,
+ section_offset));
+}
+
+TEST(RangeList, Dwarf5ReadRangeList_rnglists) {
+ using google_breakpad::RangeListReader;
+ using google_breakpad::DW_RLE_base_addressx;
+ using google_breakpad::DW_RLE_startx_endx;
+ using google_breakpad::DW_RLE_startx_length;
+ using google_breakpad::DW_RLE_offset_pair;
+ using google_breakpad::DW_RLE_end_of_list;
+ using google_breakpad::DW_RLE_base_address;
+ using google_breakpad::DW_RLE_start_end;
+ using google_breakpad::DW_RLE_start_length;
+ using google_breakpad::DW_FORM_sec_offset;
+ using google_breakpad::DW_FORM_rnglistx;
+
+ // Size of header
+ const uint64_t header_size = 12;
+ // Size of length field in header
+ const uint64_t length_size = 4;
+
+ // .debug_addr for the indexed entries like startx.
+ Section addr;
+ addr.set_endianness(kBigEndian);
+ // Test addr_base handling with a padding address at 0.
+ addr.D32(0).D32(1).D32(2).D32(3).D32(4);
+ std::string addr_contents;
+ assert(addr.GetContents(&addr_contents));
+
+ // .debug_rnglists is the dwarf 5 section.
+ Section rnglists1(kBigEndian);
+ Section rnglists2(kBigEndian);
+
+ // First header and body.
+ Label section_size1;
+ rnglists1.Append(kBigEndian, length_size, section_size1);
+ rnglists1.D16(5); // Version
+ rnglists1.D8(4); // Address size
+ rnglists1.D8(0); // Segment selector size
+ rnglists1.D32(2); // Offset entry count
+ const uint64_t ranges_base_1 = rnglists1.Size();
+
+ // Offset entries.
+ Label range0;
+ rnglists1.Append(kBigEndian, 4, range0);
+ Label range1;
+ rnglists1.Append(kBigEndian, 4, range1);
+
+ // Range 0 (will be read via DW_AT_ranges, DW_FORM_rnglistx).
+ range0 = rnglists1.Size() - header_size;
+ rnglists1.D8(DW_RLE_base_addressx).ULEB128(0); // base_addr = 1
+ rnglists1.D8(DW_RLE_startx_endx).ULEB128(1).ULEB128(2); // [2, 3)
+ rnglists1.D8(DW_RLE_startx_length).ULEB128(3).ULEB128(1); // [4, 5)
+ rnglists1.D8(DW_RLE_offset_pair).ULEB128(5).ULEB128(6); // [6, 7)
+ rnglists1.D8(DW_RLE_end_of_list);
+
+ // Range 1 (will be read via DW_AT_ranges, DW_FORM_rnglistx).
+ range1 = rnglists1.Size() - header_size;
+ rnglists1.D8(DW_RLE_base_address).D32(8); // base_addr = 8
+ rnglists1.D8(DW_RLE_offset_pair).ULEB128(1).ULEB128(2); // [9, 10)
+ rnglists1.D8(DW_RLE_start_end).D32(10).D32(11); // [10, 11)
+ rnglists1.D8(DW_RLE_start_length).D32(12).ULEB128(1); // [12, 13)
+ rnglists1.D8(DW_RLE_end_of_list);
+ // The size doesn't include the size of length field itself.
+ section_size1 = rnglists1.Size() - length_size;
+
+ // Second header and body.
+ Label section_size2;
+ rnglists2.Append(kBigEndian, length_size, section_size2);
+ rnglists2.D16(5); // Version
+ rnglists2.D8(4); // Address size
+ rnglists2.D8(0); // Segment selector size
+ rnglists2.D32(2); // Offset entry count
+ const uint64_t ranges_base_2 = rnglists1.Size() + rnglists2.Size();
+
+ // Offset entries.
+ Label range2;
+ rnglists2.Append(kBigEndian, 4, range2);
+ Label range3;
+ rnglists2.Append(kBigEndian, 4, range3);
+
+ // Range 2 (will be read via DW_AT_ranges, DW_FORM_sec_offset).
+ range2 = rnglists2.Size() - header_size;
+ rnglists2.D8(DW_RLE_base_addressx).ULEB128(0); // base_addr = 1
+ rnglists2.D8(DW_RLE_startx_endx).ULEB128(1).ULEB128(2); // [2, 3)
+ rnglists2.D8(DW_RLE_startx_length).ULEB128(3).ULEB128(1); // [4, 5)
+ rnglists2.D8(DW_RLE_offset_pair).ULEB128(5).ULEB128(6); // [6, 7)
+ rnglists2.D8(DW_RLE_end_of_list);
+
+ // Range 3 (will be read via DW_AT_ranges, DW_FORM_rnglistx).
+ range3 = rnglists2.Size() - header_size;
+ rnglists2.D8(DW_RLE_base_address).D32(15); // base_addr = 15
+ rnglists2.D8(DW_RLE_offset_pair).ULEB128(1).ULEB128(2); // [16, 17)
+ rnglists2.D8(DW_RLE_start_end).D32(17).D32(18); // [17, 18)
+ rnglists2.D8(DW_RLE_start_length).D32(19).ULEB128(1); // [19, 20)
+ rnglists2.D8(DW_RLE_end_of_list);
+ // The size doesn't include the size of length field itself.
+ section_size2 = rnglists2.Size() - length_size;
+
+ rnglists1.Append(rnglists2);
+ string rnglists_contents;
+ assert(rnglists1.GetContents(&rnglists_contents));
+
+ RangeListReader::CURangesInfo cu_info;
+ cu_info.version_ = 5;
+ cu_info.base_address_ = 1;
+ cu_info.ranges_base_ = ranges_base_1;
+ cu_info.buffer_ =
+ reinterpret_cast<const uint8_t*>(rnglists_contents.data());
+ cu_info.size_ = rnglists_contents.size();
+ cu_info.addr_buffer_ =
+ reinterpret_cast<const uint8_t*>(addr_contents.data());
+ cu_info.addr_buffer_size_ = addr_contents.size();
+ cu_info.addr_base_ = 4;
+
+ ByteReader byte_reader(ENDIANNESS_BIG);
+ byte_reader.SetOffsetSize(4);
+ byte_reader.SetAddressSize(4);
+ MockRangeListHandler handler;
+ google_breakpad::RangeListReader range_list_reader1(&byte_reader, &cu_info,
+ &handler);
+ EXPECT_CALL(handler, AddRange(2, 3));
+ EXPECT_CALL(handler, AddRange(4, 5));
+ EXPECT_CALL(handler, AddRange(6, 7));
+ EXPECT_CALL(handler, AddRange(9, 10));
+ EXPECT_CALL(handler, AddRange(10, 11));
+ EXPECT_CALL(handler, AddRange(12, 13));
+ EXPECT_CALL(handler, Finish()).Times(2);
+ EXPECT_TRUE(range_list_reader1.ReadRanges(DW_FORM_rnglistx, 0));
+ EXPECT_TRUE(range_list_reader1.ReadRanges(DW_FORM_rnglistx, 1));
+ // Out of range index, should result in no calls.
+ EXPECT_FALSE(range_list_reader1.ReadRanges(DW_FORM_rnglistx, 2));
+
+ // Set to new ranges_base
+ cu_info.ranges_base_ = ranges_base_2;
+ google_breakpad::RangeListReader range_list_reader2(&byte_reader, &cu_info,
+ &handler);
+ EXPECT_CALL(handler, AddRange(2, 3));
+ EXPECT_CALL(handler, AddRange(4, 5));
+ EXPECT_CALL(handler, AddRange(6, 7));
+ EXPECT_CALL(handler, AddRange(16, 17));
+ EXPECT_CALL(handler, AddRange(17, 18));
+ EXPECT_CALL(handler, AddRange(19, 20));
+ EXPECT_CALL(handler, Finish()).Times(2);
+ EXPECT_TRUE(range_list_reader2.ReadRanges(DW_FORM_rnglistx, 0));
+ EXPECT_TRUE(range_list_reader2.ReadRanges(DW_FORM_rnglistx, 1));
+ // Out of range index, should result in no calls.
+ EXPECT_FALSE(range_list_reader2.ReadRanges(DW_FORM_rnglistx, 2));
+}
+
+TEST(RangeList, Dwarf5ReadRangeList_sec_offset) {
+ using google_breakpad::RangeListReader;
+ using google_breakpad::DW_RLE_base_addressx;
+ using google_breakpad::DW_RLE_startx_endx;
+ using google_breakpad::DW_RLE_startx_length;
+ using google_breakpad::DW_RLE_offset_pair;
+ using google_breakpad::DW_RLE_end_of_list;
+ using google_breakpad::DW_RLE_base_address;
+ using google_breakpad::DW_RLE_start_end;
+ using google_breakpad::DW_RLE_start_length;
+ using google_breakpad::DW_FORM_sec_offset;
+ using google_breakpad::DW_FORM_rnglistx;
+
+ // Size of length field in header
+ const uint64_t length_size = 4;
+
+ // .debug_addr for the indexed entries like startx.
+ Section addr;
+ addr.set_endianness(kBigEndian);
+ // Test addr_base handling with a padding address at 0.
+ addr.D32(0).D32(1).D32(2).D32(3).D32(4).D32(21).D32(22);
+ std::string addr_contents;
+ assert(addr.GetContents(&addr_contents));
+
+ // .debug_rnglists is the dwarf 5 section.
+ Section rnglists1(kBigEndian);
+ Section rnglists2(kBigEndian);
+
+ // First header and body.
+ Label section_size1;
+ rnglists1.Append(kBigEndian, length_size, section_size1);
+ rnglists1.D16(5); // Version
+ rnglists1.D8(4); // Address size
+ rnglists1.D8(0); // Segment selector size
+ rnglists1.D32(0); // Offset entry count
+
+ const uint64_t offset1 = rnglists1.Size();
+
+ rnglists1.D8(DW_RLE_base_addressx).ULEB128(0); // base_addr = 1
+ rnglists1.D8(DW_RLE_startx_endx).ULEB128(1).ULEB128(2); // [2, 3)
+ rnglists1.D8(DW_RLE_startx_length).ULEB128(3).ULEB128(1); // [4, 5)
+ rnglists1.D8(DW_RLE_offset_pair).ULEB128(5).ULEB128(6); // [6, 7)
+ rnglists1.D8(DW_RLE_base_address).D32(8); // base_addr = 8
+ rnglists1.D8(DW_RLE_offset_pair).ULEB128(1).ULEB128(2); // [9, 10)
+ rnglists1.D8(DW_RLE_start_end).D32(10).D32(11); // [10, 11)
+ rnglists1.D8(DW_RLE_start_length).D32(12).ULEB128(1); // [12, 13)
+ rnglists1.D8(DW_RLE_end_of_list);
+ // The size doesn't include the size of length field itself.
+ section_size1 = rnglists1.Size() - length_size;
+
+ // Second header and body.
+ Label section_size2;
+ rnglists2.Append(kBigEndian, length_size, section_size2);
+ rnglists2.D16(5); // Version
+ rnglists2.D8(4); // Address size
+ rnglists2.D8(0); // Segment selector size
+ rnglists2.D32(0); // Offset entry count
+
+ const uint64_t offset2 = rnglists1.Size() + rnglists2.Size();
+
+ rnglists2.D8(DW_RLE_base_addressx).ULEB128(0); // base_addr = 1
+ rnglists2.D8(DW_RLE_startx_endx).ULEB128(1).ULEB128(2); // [2, 3)
+ rnglists2.D8(DW_RLE_startx_length).ULEB128(3).ULEB128(1); // [4, 5)
+ rnglists2.D8(DW_RLE_offset_pair).ULEB128(5).ULEB128(6); // [6, 7)
+ rnglists2.D8(DW_RLE_base_address).D32(15); // base_addr = 15
+ rnglists2.D8(DW_RLE_offset_pair).ULEB128(1).ULEB128(2); // [16, 17)
+ rnglists2.D8(DW_RLE_start_end).D32(17).D32(18); // [17, 18)
+ rnglists2.D8(DW_RLE_start_length).D32(19).ULEB128(1); // [19, 20)
+ rnglists2.D8(DW_RLE_end_of_list);
+ // The size doesn't include the size of length field itself.
+ section_size2 = rnglists2.Size() - length_size;
+
+ rnglists1.Append(rnglists2);
+ string rnglists_contents;
+ assert(rnglists1.GetContents(&rnglists_contents));
+
+ RangeListReader::CURangesInfo cu_info;
+ cu_info.version_ = 5;
+ cu_info.base_address_ = 1;
+ cu_info.buffer_ =
+ reinterpret_cast<const uint8_t*>(rnglists_contents.data());
+ cu_info.size_ = rnglists_contents.size();
+ cu_info.addr_buffer_ =
+ reinterpret_cast<const uint8_t*>(addr_contents.data());
+ cu_info.addr_buffer_size_ = addr_contents.size();
+ cu_info.addr_base_ = 4;
+
+ ByteReader byte_reader(ENDIANNESS_BIG);
+ byte_reader.SetOffsetSize(4);
+ byte_reader.SetAddressSize(4);
+ MockRangeListHandler handler;
+ google_breakpad::RangeListReader range_list_reader(&byte_reader, &cu_info,
+ &handler);
+ EXPECT_CALL(handler, AddRange(2, 3));
+ EXPECT_CALL(handler, AddRange(4, 5));
+ EXPECT_CALL(handler, AddRange(6, 7));
+ EXPECT_CALL(handler, AddRange(9, 10));
+ EXPECT_CALL(handler, AddRange(10, 11));
+ EXPECT_CALL(handler, AddRange(12, 13));
+ EXPECT_CALL(handler, Finish()).Times(1);
+ EXPECT_TRUE(range_list_reader.ReadRanges(DW_FORM_sec_offset, offset1));
+ // Out of range index, should result in no calls.
+ EXPECT_FALSE(range_list_reader.ReadRanges(DW_FORM_sec_offset,
+ rnglists_contents.size()));
+
+ EXPECT_CALL(handler, AddRange(2, 3));
+ EXPECT_CALL(handler, AddRange(4, 5));
+ EXPECT_CALL(handler, AddRange(6, 7));
+ EXPECT_CALL(handler, AddRange(16, 17));
+ EXPECT_CALL(handler, AddRange(17, 18));
+ EXPECT_CALL(handler, AddRange(19, 20));
+ EXPECT_CALL(handler, Finish()).Times(1);
+ EXPECT_TRUE(range_list_reader.ReadRanges(DW_FORM_sec_offset, offset2));
+ // Out of range index, should result in no calls.
+ EXPECT_FALSE(range_list_reader.ReadRanges(DW_FORM_sec_offset,
+ rnglists_contents.size()));
+}
diff --git a/src/common/dwarf/dwarf2reader_lineinfo_unittest.cc b/src/common/dwarf/dwarf2reader_lineinfo_unittest.cc
new file mode 100644
index 00000000..033c6333
--- /dev/null
+++ b/src/common/dwarf/dwarf2reader_lineinfo_unittest.cc
@@ -0,0 +1,186 @@
+// Copyright 2020 Google LLC
+//
+// 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 LLC 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: Sterling Augustine <saugustine@google.com>
+
+// dwarf2reader_lineinfo_unittest.cc: Unit tests for google_breakpad::LineInfo
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <string>
+#include <vector>
+
+#include "breakpad_googletest_includes.h"
+#include "common/dwarf/bytereader.h"
+#include "common/dwarf/dwarf2reader.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+using std::vector;
+using testing::InSequence;
+using testing::Return;
+using testing::Sequence;
+using testing::Test;
+using testing::_;
+
+using namespace google_breakpad;
+
+namespace {
+
+const uint8_t dwarf5_line_program[] = {
+ 0x40, 0x0, 0x0, 0x0, // unit_length (end - begin)
+ // begin
+ 0x05, 0x0, // version
+ 0x8, // address_size
+ 0x0, // segment_selector_size
+ 0x26, 0x0, 0x0, 0x0, // header_length (end_header_end - begin_header)
+ // begin_header:
+ 0x1, // minimum_instruction_length
+ 0x1, // maximum_operations_per_instruction
+ 0x1, // default_is_stmt
+ 0xfb, // line_base
+ 0xe, // line_range
+ 0xd, // opcode_base and lengths
+ 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1,
+ 0x1, // directory entry format count
+ DW_LNCT_path, DW_FORM_strp,
+ 0x1, // directories count
+ 0x1, 0x0, 0x0, 0x0, // offset into .debug_line_str
+ 0x2, // file_name_entry_format_count
+ DW_LNCT_directory_index, DW_FORM_data1,
+ DW_LNCT_path, DW_FORM_line_strp,
+ 0x1, // filename count
+ 0x0, // directory index
+ 0x1, 0x0, 0x0, 0x0, // offset into .debug_str
+ // end_header
+ DW_LNS_set_file, 0x0,
+ // set address to 0x0
+ 0x0, 0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ // Advance Address by 0 and line by 3
+ 0x15,
+ // Advance PC by 1
+ 0x2, 0x1,
+ 0x0,
+ DW_LNE_end_sequence,
+ DW_LNE_end_sequence,
+ // end
+};
+
+const uint8_t dwarf4_line_program[] = {
+ 0x37, 0x0, 0x0, 0x0, // unit_length (end - begin)
+ // begin
+ 0x04, 0x0, // version
+ 0x1d, 0x0, 0x0, 0x0, // header_length (end_header - begin_header)
+ // begin_header:
+ 0x1, // minimum_instruction_length
+ 0x1, // maximum_operations_per_instruction
+ 0x1, // default_is_stmt
+ 0xfb, // line_base
+ 0xe, // line_range
+ 0xd, // opcode_base and lengths
+ 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1,
+ '/', 'a', '\0', // directory entry 1 (zeroth entry implied)
+ '\0', // end of directory table
+ 'b', '/', 'c', '\0', // file entry 1 (zeroth entry implied)
+ 0, // file 1 directory
+ 0, // file 1 modification time
+ 0, // file 1 length
+ '\0', // end of file table
+ // end_header
+ DW_LNS_set_file, 0x0,
+ // set address to 0x0
+ 0x0, 0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ // Advance Address by 0 and line by 3
+ 0x15,
+ // Advance PC by 1
+ 0x2, 0x1,
+ 0x0,
+ DW_LNE_end_sequence,
+ DW_LNE_end_sequence,
+ // end
+};
+
+class MockLineInfoHandler: public LineInfoHandler {
+ public:
+ MOCK_METHOD(void, DefineDir, (const string&, uint32_t dir_num), (override));
+ MOCK_METHOD(void, DefineFile, (const string& name, int32_t file_num,
+ uint32_t dir_num, uint64_t mod_time,
+ uint64_t length), (override));
+ MOCK_METHOD(void, AddLine, (uint64_t address, uint64_t length,
+ uint32_t file_num, uint32_t line_num,
+ uint32_t column_num), (override));
+};
+
+const uint8_t string_section[] = {'x', '/', 'a', '\0'};
+const uint8_t line_string_section[] = {'x', 'b', '/', 'c', '\0' };
+
+struct LineProgram: public Test {
+ MockLineInfoHandler handler_;
+};
+
+TEST_F(LineProgram, ReadLinesDwarf5) {
+ ByteReader byte_reader(ENDIANNESS_LITTLE);
+ // LineTables don't specify the offset size like Compilation Units do.
+ byte_reader.SetOffsetSize(4);
+ LineInfo line_reader(dwarf5_line_program,
+ sizeof(dwarf5_line_program),
+ &byte_reader,
+ string_section,
+ sizeof(string_section),
+ line_string_section,
+ sizeof(line_string_section),
+ &handler_);
+ EXPECT_CALL(handler_, DefineDir("/a", 0)).Times(1);
+ EXPECT_CALL(handler_, DefineFile("b/c", 0, 0, 0, 0)).Times(1);
+ EXPECT_CALL(handler_, AddLine(0, 1, 0, 4, 0)).Times(1);
+ EXPECT_EQ(line_reader.Start(), sizeof(dwarf5_line_program));
+}
+
+TEST_F(LineProgram, ReadLinesDwarf4) {
+ ByteReader byte_reader(ENDIANNESS_LITTLE);
+ // LineTables don't specify the offset size like Compilation Units do.
+ byte_reader.SetOffsetSize(4);
+ // dwarf4 line info headers don't encode the address size.
+ byte_reader.SetAddressSize(8);
+ LineInfo line_reader(dwarf4_line_program,
+ sizeof(dwarf4_line_program),
+ &byte_reader,
+ // dwarf4 line tables can't access the string sections
+ // so pass values likely to make assertions fail if
+ // the code uses them improperly.
+ nullptr, 0, nullptr, 0,
+ &handler_);
+ EXPECT_CALL(handler_, DefineDir("", 0)).Times(1);
+ EXPECT_CALL(handler_, DefineDir("/a", 1)).Times(1);
+ EXPECT_CALL(handler_, DefineFile("", 0, 0, 0, 0)).Times(1);
+ EXPECT_CALL(handler_, DefineFile("b/c", 1, 0, 0, 0)).Times(1);
+ EXPECT_CALL(handler_, AddLine(0, 1, 0, 4, 0)).Times(1);
+ EXPECT_EQ(line_reader.Start(), sizeof(dwarf4_line_program));
+}
+
+} // anonymous namespace
diff --git a/src/common/dwarf/dwarf2reader_splitfunctions_unittest.cc b/src/common/dwarf/dwarf2reader_splitfunctions_unittest.cc
new file mode 100644
index 00000000..9ceea109
--- /dev/null
+++ b/src/common/dwarf/dwarf2reader_splitfunctions_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2020 Google LLC
+//
+// 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 LLC 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: Snehasish Kumar <snehasishk@google.com>
+
+// dwarf2reader_splitfunctions_unittest.cc: Unit tests for with a focus on debug
+// information generated when with splitting optimizations such as
+// -fsplit-machine-functions (clang) -freorder-blocks-and-partition (gcc).
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "common/dwarf/bytereader.h"
+#include "common/dwarf/dwarf2reader.h"
+#include "google_breakpad/common/breakpad_types.h"
+
+using testing::_;
+using namespace google_breakpad;
+
+namespace {
+
+class MockLineInfoHandler: public LineInfoHandler {
+ public:
+ MOCK_METHOD(void, DefineFile, (const string& name, int32_t file_num,
+ uint32_t dir_num, uint64_t mod_time,
+ uint64_t length), (override));
+ MOCK_METHOD(void, AddLine, (uint64_t address, uint64_t length,
+ uint32_t file_num, uint32_t line_num,
+ uint32_t column_num), (override));
+};
+
+struct LineProgram: public testing::Test {
+ MockLineInfoHandler handler_;
+};
+
+// The debug information is generated from the following program --
+// $ cat -n split_functions.c
+// 1 #include <stdio.h>
+// 2
+// 3 __attribute__((noinline)) int foo(int i) {
+// 4 if (i % 100) {
+// 5 return i + 1;
+// 6 } else {
+// 7 return i * 10 % 3;
+// 8 }
+// 9 }
+// 10
+// 11
+// 12 int main(int argc, char *argv[]) {
+// 13 int total = 0;
+// 14 for (int i = 0; i < 1000; ++i) {
+// 15 total += foo(i);
+// 16 }
+// 17 printf("%d\n", total);
+// 18 }
+//
+// $ bin/clang -fprofile-generate -O2 split_functions.c
+// $ ./a.out > /dev/null
+// $ bin/llvm-profdata merge -o default.profdata default_*.profraw
+// $ bin/clang -fprofile-use -O2 -gmlt -gdwarf-5 -fsplit-machine-functions \
+// split_functions.c -o split.out
+//
+// For the test we pick the first instruction in foo.cold which should be the
+// else part of the function foo above.
+
+const uint8_t debug_line[] = {
+ 0xb0,0x0,0x0,0x0,0x5,0x0,0x8,0x0,0x37,0x0,0x0,0x0,0x1,0x1,0x1,0xfb,0xe,0xd,0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x1,0x1,0x1f,0x1,0x0,0x0,0x0,0x0,0x3,0x1,0x1f,0x2,0xf,0x5,0x1e,0x1,0x3d,0x0,0x0,0x0,0x0,0x24,0xb2,0xb6,0xb5,0xbb,0xf,0xf7,0x6d,0x27,0x92,0xab,0x55,0x3a,0x29,0x48,0x81,0x4,0x0,0x0,0x9,0x2,0x40,0x10,0x40,0x0,0x0,0x0,0x0,0x0,0x14,0x5,0x9,0xa,0x2f,0x5,0x7,0x6,0x8,0x4a,0x5,0xe,0x6,0x67,0x5,0x1,0x40,0x5,0x0,0xf5,0x5,0xe,0xa,0xf5,0x5,0xb,0x6,0x74,0x5,0x1d,0x6,0x2d,0x5,0x15,0x6,0x3c,0x5,0x3,0x66,0x2,0x7,0x0,0x1,0x1,0x4,0x0,0x5,0xe,0x0,0x9,0x2,0x84,0x11,0x40,0x0,0x0,0x0,0x0,0x0,0x18,0x5,0x13,0x6,0x58,0x5,0x1,0x6,0x8,0xa0,0x2,0x1,0x0,0x1,0x1,0x4,0x0,0x5,0x3,0x0,0x9,0x2,0xa5,0x11,0x40,0x0,0x0,0x0,0x0,0x0,0x3,0x10,0x1,0x5,0x1,0xd7,0x2,0x9,0x0,0x1,0x1
+};
+
+const uint8_t debug_str[] = {
+ 0x63,0x6c,0x61,0x6e,0x67,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,0x32,0x2e,0x30,0x2e,0x30,0x20,0x28,0x67,0x69,0x74,0x40,0x67,0x69,0x74,0x68,0x75,0x62,0x2e,0x63,0x6f,0x6d,0x3a,0x6c,0x6c,0x76,0x6d,0x2f,0x6c,0x6c,0x76,0x6d,0x2d,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x2e,0x67,0x69,0x74,0x20,0x63,0x37,0x35,0x61,0x30,0x61,0x31,0x65,0x39,0x64,0x63,0x32,0x39,0x62,0x65,0x34,0x65,0x30,0x30,0x64,0x33,0x37,0x64,0x30,0x64,0x30,0x30,0x32,0x38,0x38,0x61,0x66,0x63,0x31,0x61,0x36,0x31,0x35,0x33,0x66,0x29,0x0,0x73,0x70,0x6c,0x69,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x2e,0x63,0x0,0x2f,0x75,0x73,0x72,0x2f,0x6c,0x6f,0x63,0x61,0x6c,0x2f,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x73,0x6e,0x65,0x68,0x61,0x73,0x69,0x73,0x68,0x6b,0x2f,0x77,0x6f,0x72,0x6b,0x69,0x6e,0x67,0x2f,0x6c,0x6c,0x76,0x6d,0x2d,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x2f,0x62,0x75,0x69,0x6c,0x64,0x0,0x66,0x6f,0x6f,0x0,0x69,0x6e,0x74,0x0,0x6d,0x61,0x69,0x6e,0x0,0x69,0x0,0x61,0x72,0x67,0x63,0x0,0x61,0x72,0x67,0x76,0x0,0x63,0x68,0x61,0x72,0x0,0x74,0x6f,0x74,0x61,0x6c,0x0
+};
+
+const uint8_t debug_line_str[] = {
+ 0x2f,0x75,0x73,0x72,0x2f,0x6c,0x6f,0x63,0x61,0x6c,0x2f,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x73,0x6e,0x65,0x68,0x61,0x73,0x69,0x73,0x68,0x6b,0x2f,0x77,0x6f,0x72,0x6b,0x69,0x6e,0x67,0x2f,0x6c,0x6c,0x76,0x6d,0x2d,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x2f,0x62,0x75,0x69,0x6c,0x64,0x0,0x73,0x70,0x6c,0x69,0x74,0x5f,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x2e,0x63,0x0
+};
+
+TEST_F(LineProgram, ReadLinesSplitFunctions) {
+ ByteReader byte_reader(ENDIANNESS_LITTLE);
+ // LineTables don't specify the offset size like Compilation Units do.
+ byte_reader.SetOffsetSize(4);
+ LineInfo line_reader(debug_line,
+ sizeof(debug_line),
+ &byte_reader,
+ debug_str,
+ sizeof(debug_str),
+ debug_line_str,
+ sizeof(debug_line_str),
+ &handler_);
+ EXPECT_CALL(handler_, DefineFile("split_functions.c", 0, 0, 0, 0)).Times(1);
+ EXPECT_CALL(handler_, AddLine(_, _, _, _, _)).Times(testing::AtLeast(1));
+ // Pick the first address from the foo.cold symbol and check the line number.
+ EXPECT_CALL(handler_, AddLine(testing::Eq(0x401184lu), _, _, /*line_num*/ 7, _)).Times(1);
+ EXPECT_EQ(line_reader.Start(), sizeof(debug_line));
+}
+
+} // anonymous namespace
diff --git a/src/common/dwarf/dwarf2reader_test_common.h b/src/common/dwarf/dwarf2reader_test_common.h
index e91de906..1c45d527 100644
--- a/src/common/dwarf/dwarf2reader_test_common.h
+++ b/src/common/dwarf/dwarf2reader_test_common.h
@@ -1,7 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
+// Copyright 2012 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -13,7 +12,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -45,9 +44,9 @@
// 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::DwarfTag DwarfTag;
+ typedef google_breakpad::DwarfAttribute DwarfAttribute;
+ typedef google_breakpad::DwarfForm DwarfForm;
typedef google_breakpad::test_assembler::Label Label;
// Set the section's DWARF format size (the 32-bit DWARF format or the
@@ -57,7 +56,7 @@ class TestCompilationUnit: public google_breakpad::test_assembler::Section {
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>
@@ -70,8 +69,8 @@ class TestCompilationUnit: public google_breakpad::test_assembler::Section {
// 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) {
+ TestCompilationUnit& Header(int version, const Label& abbrev_offset,
+ size_t address_size, int header_type) {
if (format_size_ == 4) {
D32(length_);
} else {
@@ -80,13 +79,28 @@ class TestCompilationUnit: public google_breakpad::test_assembler::Section {
}
post_length_offset_ = Size();
D16(version);
- SectionOffset(abbrev_offset);
- D8(address_size);
+ if (version <= 4) {
+ SectionOffset(abbrev_offset);
+ D8(address_size);
+ } else {
+ D8(header_type); // DW_UT_compile, DW_UT_type, etc.
+ D8(address_size);
+ SectionOffset(abbrev_offset);
+ if (header_type == google_breakpad::DW_UT_type) {
+ uint64_t dummy_type_signature = 0xdeadbeef;
+ uint64_t dummy_type_offset = 0x2b;
+ D64(dummy_type_signature);
+ if (format_size_ == 4)
+ D32(dummy_type_offset);
+ else
+ D64(dummy_type_offset);
+ }
+ }
return *this;
}
// Mark the end of this header's DIEs.
- TestCompilationUnit &Finish() {
+ TestCompilationUnit& Finish() {
length_ = Size() - post_length_offset_;
return *this;
}
@@ -107,16 +121,16 @@ class TestCompilationUnit: public google_breakpad::test_assembler::Section {
// 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::DwarfTag DwarfTag;
+ typedef google_breakpad::DwarfAttribute DwarfAttribute;
+ typedef google_breakpad::DwarfForm DwarfForm;
+ typedef google_breakpad::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) {
+ TestAbbrevTable& Abbrev(int code, DwarfTag tag, DwarfHasChild has_children) {
assert(code != 0);
ULEB128(code);
ULEB128(static_cast<unsigned>(tag));
@@ -126,21 +140,21 @@ class TestAbbrevTable: public google_breakpad::test_assembler::Section {
// Add an attribute to the current abbreviation code whose name is |name|
// and whose form is |form|.
- TestAbbrevTable &Attribute(DwarfAttribute name, DwarfForm 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() {
+ TestAbbrevTable& EndAbbrev() {
ULEB128(0);
ULEB128(0);
return *this;
}
// Finish the current abbreviation table.
- TestAbbrevTable &EndTable() {
+ TestAbbrevTable& EndTable() {
ULEB128(0);
return *this;
}
diff --git a/src/common/dwarf/elf_reader.cc b/src/common/dwarf/elf_reader.cc
index 1b665213..7664377c 100644
--- a/src/common/dwarf/elf_reader.cc
+++ b/src/common/dwarf/elf_reader.cc
@@ -1,4 +1,4 @@
-// Copyright 2005 Google Inc. All Rights Reserved.
+// Copyright 2005 Google LLC
// Author: chatham@google.com (Andrew Chatham)
// Author: satorux@google.com (Satoru Takabayashi)
//
@@ -41,6 +41,7 @@
#include <algorithm>
#include <map>
#include <string>
+#include <string_view>
#include <vector>
// TODO(saugustine): Add support for compressed debug.
// Also need to add configure tests for zlib.
@@ -106,9 +107,15 @@ const int kAARCH64PLT0Size = 0x20;
// Suffix for PLT functions when it needs to be explicitly identified as such.
const char kPLTFunctionSuffix[] = "@plt";
+// Replace callsites of this function to std::string_view::starts_with after
+// adopting C++20.
+bool StringViewStartsWith(std::string_view sv, std::string_view prefix) {
+ return sv.compare(0, prefix.size(), prefix) == 0;
+}
+
} // namespace
-namespace dwarf2reader {
+namespace google_breakpad {
template <class ElfArch> class ElfReaderImpl;
@@ -130,11 +137,11 @@ class Elf32 {
static const int kElfClass = ELFCLASS32;
// Given a symbol pointer, return the binding type (eg STB_WEAK).
- static char Bind(const Elf32_Sym *sym) {
+ static char Bind(const Elf32_Sym* sym) {
return ELF32_ST_BIND(sym->st_info);
}
// Given a symbol pointer, return the symbol type (eg STT_FUNC).
- static char Type(const Elf32_Sym *sym) {
+ static char Type(const Elf32_Sym* sym) {
return ELF32_ST_TYPE(sym->st_info);
}
@@ -158,10 +165,10 @@ class Elf64 {
// What should be in the EI_CLASS header.
static const int kElfClass = ELFCLASS64;
- static char Bind(const Elf64_Sym *sym) {
+ static char Bind(const Elf64_Sym* sym) {
return ELF64_ST_BIND(sym->st_info);
}
- static char Type(const Elf64_Sym *sym) {
+ static char Type(const Elf64_Sym* sym) {
return ELF64_ST_TYPE(sym->st_info);
}
static int r_sym(const Elf64_Xword r_info) {
@@ -182,8 +189,8 @@ class Elf64 {
template<class ElfArch>
class ElfSectionReader {
public:
- ElfSectionReader(const char *name, const string &path, int fd,
- const typename ElfArch::Shdr &section_header)
+ ElfSectionReader(const char* cname, const string& path, int fd,
+ const typename ElfArch::Shdr& section_header)
: contents_aligned_(NULL),
contents_(NULL),
header_(section_header) {
@@ -196,14 +203,25 @@ class ElfSectionReader {
// to process its contents.
if (header_.sh_type == SHT_NOBITS || header_.sh_size == 0)
return;
+ // extra sh_type check for string table.
+ std::string_view name{cname};
+ if ((name == ".strtab" || name == ".shstrtab") &&
+ header_.sh_type != SHT_STRTAB) {
+ fprintf(stderr,
+ "Invalid sh_type for string table section: expected "
+ "SHT_STRTAB or SHT_DYNSYM, but got %d\n",
+ header_.sh_type);
+ return;
+ }
+
contents_aligned_ = mmap(NULL, size_aligned_, PROT_READ, MAP_SHARED,
fd, offset_aligned);
// Set where the offset really should begin.
- contents_ = reinterpret_cast<char *>(contents_aligned_) +
+ contents_ = reinterpret_cast<char*>(contents_aligned_) +
(header_.sh_offset - offset_aligned);
// Check for and handle any compressed contents.
- //if (strncmp(name, ".zdebug_", strlen(".zdebug_")) == 0)
+ //if (StringViewStartsWith(name, ".zdebug_"))
// DecompressZlibContents();
// TODO(saugustine): Add support for proposed elf-section flag
// "SHF_COMPRESS".
@@ -217,24 +235,24 @@ class ElfSectionReader {
}
// Return the section header for this section.
- typename ElfArch::Shdr const &header() const { return header_; }
+ typename ElfArch::Shdr const& header() const { return header_; }
// Return memory at the given offset within this section.
- const char *GetOffset(typename ElfArch::Word bytes) const {
+ const char* GetOffset(typename ElfArch::Word bytes) const {
return contents_ + bytes;
}
- const char *contents() const { return contents_; }
+ const char* contents() const { return contents_; }
size_t section_size() const { return section_size_; }
private:
// page-aligned file contents
- void *contents_aligned_;
+ void* contents_aligned_;
// contents as usable by the client. For non-compressed sections,
// pointer within contents_aligned_ to where the section data
// begins; for compressed sections, pointer to the decompressed
// data.
- char *contents_;
+ char* contents_;
// size of contents_aligned_
size_t size_aligned_;
// size of contents.
@@ -249,7 +267,7 @@ class ElfSectionReader {
template<class ElfArch>
class SymbolIterator {
public:
- SymbolIterator(ElfReaderImpl<ElfArch> *reader,
+ SymbolIterator(ElfReaderImpl<ElfArch>* reader,
typename ElfArch::Word section_type)
: symbol_section_(reader->GetSectionByType(section_type)),
string_section_(NULL),
@@ -280,7 +298,7 @@ class SymbolIterator {
// Return a pointer to the current symbol.
// REQUIRES: !done()
- const typename ElfArch::Sym *GetSymbol() const {
+ const typename ElfArch::Sym* GetSymbol() const {
return reinterpret_cast<const typename ElfArch::Sym*>(
symbol_section_->GetOffset(symbol_within_section_ *
symbol_section_->header().sh_entsize));
@@ -288,7 +306,7 @@ class SymbolIterator {
// Return the name of the current symbol, NULL if it has none.
// REQUIRES: !done()
- const char *GetSymbolName() const {
+ const char* GetSymbolName() const {
int name_offset = GetSymbol()->st_name;
if (name_offset == 0)
return NULL;
@@ -300,8 +318,8 @@ class SymbolIterator {
}
private:
- const ElfSectionReader<ElfArch> *const symbol_section_;
- const ElfSectionReader<ElfArch> *string_section_;
+ const ElfSectionReader<ElfArch>* const symbol_section_;
+ const ElfSectionReader<ElfArch>* string_section_;
int num_symbols_in_section_;
int symbol_within_section_;
};
@@ -326,7 +344,7 @@ static inline bool MyHasSuffixString(const string& str, const string& suffix) {
template<class ElfArch>
class ElfReaderImpl {
public:
- explicit ElfReaderImpl(const string &path, int fd)
+ explicit ElfReaderImpl(const string& path, int fd)
: path_(path),
fd_(fd),
section_headers_(NULL),
@@ -347,8 +365,8 @@ class ElfReaderImpl {
// "opd_section_" must always be checked for NULL before use.
opd_section_ = GetSectionInfoByName(".opd", &opd_info_);
for (unsigned int k = 0u; k < GetNumSections(); ++k) {
- const char *name = GetSectionName(section_headers_[k].sh_name);
- if (strncmp(name, ".text", strlen(".text")) == 0) {
+ std::string_view name{GetSectionName(section_headers_[k].sh_name)};
+ if (StringViewStartsWith(name, ".text")) {
base_for_text_ =
section_headers_[k].sh_addr - section_headers_[k].sh_offset;
break;
@@ -384,7 +402,7 @@ class ElfReaderImpl {
// to see if the ELF file appears to match the current
// architecture. If error is non-NULL, it will be set with a reason
// in case of failure.
- static bool IsArchElfFile(int fd, string *error) {
+ static bool IsArchElfFile(int fd, string* error) {
unsigned char header[EI_NIDENT];
if (pread(fd, header, sizeof(header), 0) != sizeof(header)) {
if (error != NULL) *error = "Could not read header";
@@ -415,7 +433,7 @@ class ElfReaderImpl {
}
// Return true if we can use this symbol in Address-to-Symbol map.
- bool CanUseSymbol(const char *name, const typename ElfArch::Sym *sym) {
+ bool CanUseSymbol(const char* name, const typename ElfArch::Sym* sym) {
// For now we only save FUNC and NOTYPE symbols. For now we just
// care about functions, but some functions written in assembler
// don't have a proper ELF type attached to them, so we store
@@ -444,7 +462,7 @@ class ElfReaderImpl {
// Iterate over the symbols in a section, either SHT_DYNSYM or
// SHT_SYMTAB. Add all symbols to the given SymbolMap.
/*
- void GetSymbolPositions(SymbolMap *symbols,
+ void GetSymbolPositions(SymbolMap* symbols,
typename ElfArch::Word section_type,
uint64_t mem_offset,
uint64_t file_offset) {
@@ -453,10 +471,10 @@ class ElfReaderImpl {
AddrToSymMap addr_to_sym_map;
for (SymbolIterator<ElfArch> it(this, section_type);
!it.done(); it.Next()) {
- const char *name = it.GetSymbolName();
+ const char* name = it.GetSymbolName();
if (name == NULL)
continue;
- const typename ElfArch::Sym *sym = it.GetSymbol();
+ const typename ElfArch::Sym* sym = it.GetSymbol();
if (CanUseSymbol(name, sym)) {
const int sec = sym->st_shndx;
@@ -519,9 +537,9 @@ class ElfReaderImpl {
if (addr_to_sym_map.empty()) {
return;
}
- const ElfSectionReader<ElfArch> *const symbol_section =
+ const ElfSectionReader<ElfArch>* const symbol_section =
this->GetSectionByType(section_type);
- const ElfSectionReader<ElfArch> *const string_section =
+ const ElfSectionReader<ElfArch>* const string_section =
this->GetSection(symbol_section->header().sh_link);
typename AddrToSymMap::iterator curr = addr_to_sym_map.begin();
@@ -532,8 +550,8 @@ class ElfReaderImpl {
for (; curr != addr_to_sym_map.end(); ++curr) {
const uint64_t prev_addr = prev->first;
const uint64_t curr_addr = curr->first;
- const typename ElfArch::Sym *const prev_sym = prev->second;
- const typename ElfArch::Sym *const curr_sym = curr->second;
+ const typename ElfArch::Sym* const prev_sym = prev->second;
+ const typename ElfArch::Sym* const curr_sym = curr->second;
if (prev_addr + prev_sym->st_size <= curr_addr ||
// The next condition is true if two symbols overlap like this:
//
@@ -552,7 +570,7 @@ class ElfReaderImpl {
// (e.g. 0619e071) will produce the current symbol,
// which is the desired outcome.
prev_addr + prev_sym->st_size < curr_addr + curr_sym->st_size) {
- const char *name = string_section->GetOffset(curr_sym->st_name);
+ const char* name = string_section->GetOffset(curr_sym->st_name);
symbols->AddSymbol(name, curr_addr, curr_sym->st_size);
prev = curr;
} else {
@@ -572,20 +590,20 @@ class ElfReaderImpl {
*/
void VisitSymbols(typename ElfArch::Word section_type,
- ElfReader::SymbolSink *sink) {
+ ElfReader::SymbolSink* sink) {
VisitSymbols(section_type, sink, -1, -1, false);
}
void VisitSymbols(typename ElfArch::Word section_type,
- ElfReader::SymbolSink *sink,
+ ElfReader::SymbolSink* sink,
int symbol_binding,
int symbol_type,
bool get_raw_symbol_values) {
for (SymbolIterator<ElfArch> it(this, section_type);
!it.done(); it.Next()) {
- const char *name = it.GetSymbolName();
+ const char* name = it.GetSymbolName();
if (!name) continue;
- const typename ElfArch::Sym *sym = it.GetSymbol();
+ const typename ElfArch::Sym* sym = it.GetSymbol();
if ((symbol_binding < 0 || ElfArch::Bind(sym) == symbol_binding) &&
(symbol_type < 0 || ElfArch::Type(sym) == symbol_type)) {
typename ElfArch::Sym symbol = *sym;
@@ -691,7 +709,7 @@ class ElfReaderImpl {
// Return an ElfSectionReader for the first section of the given
// type by iterating through all section headers. Returns NULL if
// the section type is not found.
- const ElfSectionReader<ElfArch> *GetSectionByType(
+ const ElfSectionReader<ElfArch>* GetSectionByType(
typename ElfArch::Word section_type) {
for (unsigned int k = 0u; k < GetNumSections(); ++k) {
if (section_headers_[k].sh_type == section_type) {
@@ -703,14 +721,14 @@ class ElfReaderImpl {
// Return the name of section "shndx". Returns NULL if the section
// is not found.
- const char *GetSectionNameByIndex(int shndx) {
+ const char* GetSectionNameByIndex(int shndx) {
return GetSectionName(section_headers_[shndx].sh_name);
}
// Return a pointer to section "shndx", and store the size in
// "size". Returns NULL if the section is not found.
- const char *GetSectionContentsByIndex(int shndx, size_t *size) {
- const ElfSectionReader<ElfArch> *section = GetSection(shndx);
+ const char* GetSectionContentsByIndex(int shndx, size_t* size) {
+ const ElfSectionReader<ElfArch>* section = GetSection(shndx);
if (section != NULL) {
*size = section->section_size();
return section->contents();
@@ -721,16 +739,16 @@ class ElfReaderImpl {
// Return a pointer to the first section of the given name by
// iterating through all section headers, and store the size in
// "size". Returns NULL if the section name is not found.
- const char *GetSectionContentsByName(const string &section_name,
- size_t *size) {
+ const char* GetSectionContentsByName(const string& section_name,
+ size_t* size) {
for (unsigned int k = 0u; k < GetNumSections(); ++k) {
// When searching for sections in a .dwp file, the sections
// we're looking for will always be at the end of the section
// table, so reverse the direction of iteration.
int shndx = is_dwp_ ? GetNumSections() - k - 1 : k;
- const char *name = GetSectionName(section_headers_[shndx].sh_name);
+ const char* name = GetSectionName(section_headers_[shndx].sh_name);
if (name != NULL && ElfReader::SectionNamesMatch(section_name, name)) {
- const ElfSectionReader<ElfArch> *section = GetSection(shndx);
+ const ElfSectionReader<ElfArch>* section = GetSection(shndx);
if (section == NULL) {
return NULL;
} else {
@@ -744,16 +762,16 @@ class ElfReaderImpl {
// This is like GetSectionContentsByName() but it returns a lot of extra
// information about the section.
- const char *GetSectionInfoByName(const string &section_name,
- ElfReader::SectionInfo *info) {
+ const char* GetSectionInfoByName(const string& section_name,
+ ElfReader::SectionInfo* info) {
for (unsigned int k = 0u; k < GetNumSections(); ++k) {
// When searching for sections in a .dwp file, the sections
// we're looking for will always be at the end of the section
// table, so reverse the direction of iteration.
int shndx = is_dwp_ ? GetNumSections() - k - 1 : k;
- const char *name = GetSectionName(section_headers_[shndx].sh_name);
+ const char* name = GetSectionName(section_headers_[shndx].sh_name);
if (name != NULL && ElfReader::SectionNamesMatch(section_name, name)) {
- const ElfSectionReader<ElfArch> *section = GetSection(shndx);
+ const ElfSectionReader<ElfArch>* section = GetSection(shndx);
if (section == NULL) {
return NULL;
} else {
@@ -797,9 +815,11 @@ class ElfReaderImpl {
// Debug sections are likely to be near the end, so reverse the
// direction of iteration.
for (int k = GetNumSections() - 1; k >= 0; --k) {
- const char *name = GetSectionName(section_headers_[k].sh_name);
- if (strncmp(name, ".debug", strlen(".debug")) == 0) return true;
- if (strncmp(name, ".zdebug", strlen(".zdebug")) == 0) return true;
+ std::string_view name{GetSectionName(section_headers_[k].sh_name)};
+ if (StringViewStartsWith(name, ".debug") ||
+ StringViewStartsWith(name, ".zdebug")) {
+ return true;
+ }
}
return false;
}
@@ -816,7 +836,7 @@ class ElfReaderImpl {
}
private:
- typedef vector<pair<uint64_t, const typename ElfArch::Sym *> > AddrToSymMap;
+ typedef vector<pair<uint64_t, const typename ElfArch::Sym*> > AddrToSymMap;
static bool AddrToSymSorter(const typename AddrToSymMap::value_type& lhs,
const typename AddrToSymMap::value_type& rhs) {
@@ -854,8 +874,8 @@ class ElfReaderImpl {
// Given an offset into the section header string table, return the
// section name.
- const char *GetSectionName(typename ElfArch::Word sh_name) {
- const ElfSectionReader<ElfArch> *shstrtab =
+ const char* GetSectionName(typename ElfArch::Word sh_name) {
+ const ElfSectionReader<ElfArch>* shstrtab =
GetSection(GetStringTableIndex());
if (shstrtab != NULL) {
return shstrtab->GetOffset(sh_name);
@@ -865,25 +885,25 @@ class ElfReaderImpl {
// Return an ElfSectionReader for the given section. The reader will
// be freed when this object is destroyed.
- const ElfSectionReader<ElfArch> *GetSection(int num) {
- const char *name;
+ const ElfSectionReader<ElfArch>* GetSection(int num) {
+ const char* name;
// Hard-coding the name for the section-name string table prevents
// infinite recursion.
if (num == GetStringTableIndex())
name = ".shstrtab";
else
name = GetSectionNameByIndex(num);
- ElfSectionReader<ElfArch> *& reader = sections_[num];
+ ElfSectionReader<ElfArch>*& reader = sections_[num];
if (reader == NULL)
reader = new ElfSectionReader<ElfArch>(name, path_, fd_,
section_headers_[num]);
- return reader;
+ return reader->contents() ? reader : nullptr;
}
// Parse out the overall header information from the file and assert
// that it looks sane. This contains information like the magic
// number and target architecture.
- bool ParseHeaders(int fd, const string &path) {
+ bool ParseHeaders(int fd, const string& path) {
// Read in the global ELF header.
if (pread(fd, &header_, sizeof(header_), 0) != sizeof(header_)) {
return false;
@@ -985,11 +1005,11 @@ class ElfReaderImpl {
// Array of GetNumSections() section headers, allocated when we read
// in the global header.
- typename ElfArch::Shdr *section_headers_;
+ typename ElfArch::Shdr* section_headers_;
// Array of GetNumProgramHeaders() program headers, allocated when we read
// in the global header.
- typename ElfArch::Phdr *program_headers_;
+ typename ElfArch::Phdr* program_headers_;
// An array of pointers to ElfSectionReaders. Sections are
// mmaped as they're needed and not released until this object is
@@ -1000,7 +1020,7 @@ class ElfReaderImpl {
// values for funtion symbols values. Function descriptors are kept in the
// .opd section and are dereferenced to find the function address.
ElfReader::SectionInfo opd_info_;
- const char *opd_section_; // Must be checked for NULL before use.
+ const char* opd_section_; // Must be checked for NULL before use.
int64_t base_for_text_;
// Read PLT-related sections for the current architecture.
@@ -1026,7 +1046,7 @@ class ElfReaderImpl {
bool is_dwp_;
};
-ElfReader::ElfReader(const string &path)
+ElfReader::ElfReader(const string& path)
: path_(path), fd_(-1), impl32_(NULL), impl64_(NULL) {
// linux 2.6.XX kernel can show deleted files like this:
// /var/run/nscd/dbYLJYaE (deleted)
@@ -1063,7 +1083,7 @@ ElfReader::~ElfReader() {
#endif
template <typename ElfArch>
-static bool IsElfFile(const int fd, const string &path) {
+static bool IsElfFile(const int fd, const string& path) {
if (fd < 0)
return false;
if (!ElfReaderImpl<ElfArch>::IsArchElfFile(fd, NULL)) {
@@ -1086,7 +1106,7 @@ bool ElfReader::IsElf64File() const {
}
/*
-void ElfReader::AddSymbols(SymbolMap *symbols,
+void ElfReader::AddSymbols(SymbolMap* symbols,
uint64_t mem_offset, uint64_t file_offset,
uint64_t length) {
if (fd_ < 0)
@@ -1109,17 +1129,17 @@ void ElfReader::AddSymbols(SymbolMap *symbols,
}
*/
-void ElfReader::VisitSymbols(ElfReader::SymbolSink *sink) {
+void ElfReader::VisitSymbols(ElfReader::SymbolSink* sink) {
VisitSymbols(sink, -1, -1);
}
-void ElfReader::VisitSymbols(ElfReader::SymbolSink *sink,
+void ElfReader::VisitSymbols(ElfReader::SymbolSink* sink,
int symbol_binding,
int symbol_type) {
VisitSymbols(sink, symbol_binding, symbol_type, false);
}
-void ElfReader::VisitSymbols(ElfReader::SymbolSink *sink,
+void ElfReader::VisitSymbols(ElfReader::SymbolSink* sink,
int symbol_binding,
int symbol_type,
bool get_raw_symbol_values) {
@@ -1148,7 +1168,7 @@ uint64_t ElfReader::VaddrOfFirstLoadSegment() {
}
}
-const char *ElfReader::GetSectionName(int shndx) {
+const char* ElfReader::GetSectionName(int shndx) {
if (shndx < 0 || static_cast<unsigned int>(shndx) >= GetNumSections()) return NULL;
if (IsElf32File()) {
return GetImpl32()->GetSectionNameByIndex(shndx);
@@ -1169,7 +1189,7 @@ uint64_t ElfReader::GetNumSections() {
}
}
-const char *ElfReader::GetSectionByIndex(int shndx, size_t *size) {
+const char* ElfReader::GetSectionByIndex(int shndx, size_t* size) {
if (IsElf32File()) {
return GetImpl32()->GetSectionContentsByIndex(shndx, size);
} else if (IsElf64File()) {
@@ -1179,8 +1199,8 @@ const char *ElfReader::GetSectionByIndex(int shndx, size_t *size) {
}
}
-const char *ElfReader::GetSectionByName(const string &section_name,
- size_t *size) {
+const char* ElfReader::GetSectionByName(const string& section_name,
+ size_t* size) {
if (IsElf32File()) {
return GetImpl32()->GetSectionContentsByName(section_name, size);
} else if (IsElf64File()) {
@@ -1190,8 +1210,8 @@ const char *ElfReader::GetSectionByName(const string &section_name,
}
}
-const char *ElfReader::GetSectionInfoByName(const string &section_name,
- SectionInfo *info) {
+const char* ElfReader::GetSectionInfoByName(const string& section_name,
+ SectionInfo* info) {
if (IsElf32File()) {
return GetImpl32()->GetSectionInfoByName(section_name, info);
} else if (IsElf64File()) {
@@ -1201,11 +1221,15 @@ const char *ElfReader::GetSectionInfoByName(const string &section_name,
}
}
-bool ElfReader::SectionNamesMatch(const string &name, const string &sh_name) {
- if ((name.find(".debug_", 0) == 0) && (sh_name.find(".zdebug_", 0) == 0)) {
- const string name_suffix(name, strlen(".debug_"));
- const string sh_name_suffix(sh_name, strlen(".zdebug_"));
- return name_suffix == sh_name_suffix;
+bool ElfReader::SectionNamesMatch(std::string_view name,
+ std::string_view sh_name) {
+ std::string_view debug_prefix{".debug_"};
+ std::string_view zdebug_prefix{".zdebug_"};
+ if (StringViewStartsWith(name, debug_prefix) &&
+ StringViewStartsWith(sh_name, zdebug_prefix)) {
+ name.remove_prefix(debug_prefix.length());
+ sh_name.remove_prefix(zdebug_prefix.length());
+ return name == sh_name;
}
return name == sh_name;
}
@@ -1220,14 +1244,14 @@ bool ElfReader::IsDynamicSharedObject() {
}
}
-ElfReaderImpl<Elf32> *ElfReader::GetImpl32() {
+ElfReaderImpl<Elf32>* ElfReader::GetImpl32() {
if (impl32_ == NULL) {
impl32_ = new ElfReaderImpl<Elf32>(path_, fd_);
}
return impl32_;
}
-ElfReaderImpl<Elf64> *ElfReader::GetImpl64() {
+ElfReaderImpl<Elf64>* ElfReader::GetImpl64() {
if (impl64_ == NULL) {
impl64_ = new ElfReaderImpl<Elf64>(path_, fd_);
}
@@ -1238,7 +1262,7 @@ ElfReaderImpl<Elf64> *ElfReader::GetImpl64() {
// debug info (debug_only=true) or symbol table (debug_only=false).
// Otherwise, return false.
template <typename ElfArch>
-static bool IsNonStrippedELFBinaryImpl(const string &path, const int fd,
+static bool IsNonStrippedELFBinaryImpl(const string& path, const int fd,
bool debug_only) {
if (!ElfReaderImpl<ElfArch>::IsArchElfFile(fd, NULL)) return false;
ElfReaderImpl<ElfArch> elf_reader(path, fd);
@@ -1248,7 +1272,7 @@ static bool IsNonStrippedELFBinaryImpl(const string &path, const int fd,
}
// Helper for the IsNon[Debug]StrippedELFBinary functions.
-static bool IsNonStrippedELFBinaryHelper(const string &path,
+static bool IsNonStrippedELFBinaryHelper(const string& path,
bool debug_only) {
const int fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
@@ -1264,11 +1288,11 @@ static bool IsNonStrippedELFBinaryHelper(const string &path,
return false;
}
-bool ElfReader::IsNonStrippedELFBinary(const string &path) {
+bool ElfReader::IsNonStrippedELFBinary(const string& path) {
return IsNonStrippedELFBinaryHelper(path, false);
}
-bool ElfReader::IsNonDebugStrippedELFBinary(const string &path) {
+bool ElfReader::IsNonDebugStrippedELFBinary(const string& path) {
return IsNonStrippedELFBinaryHelper(path, true);
}
-} // namespace dwarf2reader
+} // namespace google_breakpad
diff --git a/src/common/dwarf/elf_reader.h b/src/common/dwarf/elf_reader.h
index 8eaa5aa9..a6dec755 100644
--- a/src/common/dwarf/elf_reader.h
+++ b/src/common/dwarf/elf_reader.h
@@ -1,4 +1,4 @@
-// Copyright 2005 Google Inc. All Rights Reserved.
+// Copyright 2005 Google LLC
// Author: chatham@google.com (Andrew Chatham)
// Author: satorux@google.com (Satoru Takabayashi)
//
@@ -16,6 +16,7 @@
#define COMMON_DWARF_ELF_READER_H__
#include <string>
+#include <string_view>
#include <vector>
#include "common/dwarf/types.h"
@@ -24,7 +25,7 @@
using std::vector;
using std::pair;
-namespace dwarf2reader {
+namespace google_breakpad {
class SymbolMap;
class Elf32;
@@ -34,7 +35,7 @@ class ElfReaderImpl;
class ElfReader {
public:
- explicit ElfReader(const string &path);
+ explicit ElfReader(const string& path);
~ElfReader();
// Parse the ELF prologue of this file and return whether it was
@@ -62,29 +63,29 @@ class ElfReader {
// mem_offset - position at which the segment is mapped into memory
// file_offset - offset in the file where the mapping begins
// length - length of the mapped segment
- void AddSymbols(SymbolMap *symbols,
+ void AddSymbols(SymbolMap* symbols,
uint64_t mem_offset, uint64_t file_offset,
uint64_t length);
class SymbolSink {
public:
virtual ~SymbolSink() {}
- virtual void AddSymbol(const char *name, uint64_t address,
+ virtual void AddSymbol(const char* name, uint64_t address,
uint64_t size) = 0;
};
// Like AddSymbols above, but with no address correction.
// Processes any SHT_SYMTAB section, followed by any SHT_DYNSYM section.
- void VisitSymbols(SymbolSink *sink);
+ void VisitSymbols(SymbolSink* sink);
// Like VisitSymbols above, but for a specific symbol binding/type.
// A negative value for the binding and type parameters means any
// binding or type.
- void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type);
+ void VisitSymbols(SymbolSink* sink, int symbol_binding, int symbol_type);
// Like VisitSymbols above but can optionally export raw symbol values instead
// of adjusted ones.
- void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type,
+ void VisitSymbols(SymbolSink* sink, int symbol_binding, int symbol_type,
bool get_raw_symbol_values);
// p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD
@@ -95,7 +96,7 @@ class ElfReader {
// Return the name of section "shndx". Returns NULL if the section
// is not found.
- const char *GetSectionName(int shndx);
+ const char* GetSectionName(int shndx);
// Return the number of sections in the given ELF file.
uint64_t GetNumSections();
@@ -104,14 +105,14 @@ class ElfReader {
// the pointer to the section and store the size in "size".
// On error, return NULL. The returned section data is only valid
// until the ElfReader gets destroyed.
- const char *GetSectionByIndex(int shndx, size_t *size);
+ const char* GetSectionByIndex(int shndx, size_t* size);
// Get section with "section_name" (ex. ".text", ".symtab") in the
// given ELF file. On success, return the pointer to the section
// and store the size in "size". On error, return NULL. The
// returned section data is only valid until the ElfReader gets
// destroyed.
- const char *GetSectionByName(const string &section_name, size_t *size);
+ const char* GetSectionByName(const string& section_name, size_t* size);
// This is like GetSectionByName() but it returns a lot of extra information
// about the section. The SectionInfo structure is almost identical to
@@ -129,39 +130,40 @@ class ElfReader {
uint64_t addralign; // Section alignment.
uint64_t entsize; // Entry size if section holds a table.
};
- const char *GetSectionInfoByName(const string &section_name,
- SectionInfo *info);
+ const char* GetSectionInfoByName(const string& section_name,
+ SectionInfo* info);
// Check if "path" is an ELF binary that has not been stripped of symbol
// tables. This function supports both 32-bit and 64-bit ELF binaries.
- static bool IsNonStrippedELFBinary(const string &path);
+ static bool IsNonStrippedELFBinary(const string& path);
// Check if "path" is an ELF binary that has not been stripped of debug
// info. Unlike IsNonStrippedELFBinary, this function will return
// false for binaries passed through "strip -S".
- static bool IsNonDebugStrippedELFBinary(const string &path);
+ static bool IsNonDebugStrippedELFBinary(const string& path);
// Match a requested section name with the section name as it
// appears in the elf-file, adjusting for compressed debug section
// names. For example, returns true if name == ".debug_abbrev" and
// sh_name == ".zdebug_abbrev"
- static bool SectionNamesMatch(const string &name, const string &sh_name);
+ static bool SectionNamesMatch(std::string_view name,
+ std::string_view sh_name);
private:
// Lazily initialize impl32_ and return it.
- ElfReaderImpl<Elf32> *GetImpl32();
+ ElfReaderImpl<Elf32>* GetImpl32();
// Ditto for impl64_.
- ElfReaderImpl<Elf64> *GetImpl64();
+ ElfReaderImpl<Elf64>* GetImpl64();
// Path of the file we're reading.
const string path_;
// Read-only file descriptor for the file. May be -1 if there was an
// error during open.
int fd_;
- ElfReaderImpl<Elf32> *impl32_;
- ElfReaderImpl<Elf64> *impl64_;
+ ElfReaderImpl<Elf32>* impl32_;
+ ElfReaderImpl<Elf64>* impl64_;
};
-} // namespace dwarf2reader
+} // namespace google_breakpad
#endif // COMMON_DWARF_ELF_READER_H__
diff --git a/src/common/dwarf/functioninfo.cc b/src/common/dwarf/functioninfo.cc
index 358a6eef..d8fdb842 100644
--- a/src/common/dwarf/functioninfo.cc
+++ b/src/common/dwarf/functioninfo.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -42,24 +42,16 @@
#include "common/scoped_ptr.h"
#include "common/using_std_string.h"
-using google_breakpad::scoped_ptr;
-
-namespace dwarf2reader {
+namespace google_breakpad {
CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files,
std::vector<string>* dirs,
LineMap* linemap):linemap_(linemap),
files_(files),
dirs_(dirs) {
- // The dirs and files are 1 indexed, so just make sure we put
- // nothing in the 0 vector.
- assert(dirs->size() == 0);
- assert(files->size() == 0);
- dirs->push_back("");
- SourceFileInfo s;
- s.name = "";
- s.lowpc = ULLONG_MAX;
- files->push_back(s);
+ // In dwarf4, the dirs and files are 1 indexed, and in dwarf5 they are zero
+ // indexed. This is handled in the LineInfo reader, so empty files are not
+ // needed here.
}
void CULineInfoHandler::DefineDir(const string& name, uint32_t dir_num) {
@@ -150,7 +142,7 @@ bool CUFunctionInfoHandler::StartDIE(uint64_t offset, enum DwarfTag tag) {
void CUFunctionInfoHandler::ProcessAttributeString(uint64_t offset,
enum DwarfAttribute attr,
enum DwarfForm form,
- const string &data) {
+ const string& data) {
if (current_function_info_) {
if (attr == DW_AT_name)
current_function_info_->name = data;
@@ -164,7 +156,8 @@ void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64_t offset,
enum DwarfForm form,
uint64_t data) {
if (attr == DW_AT_stmt_list) {
- SectionMap::const_iterator iter = sections_.find("__debug_line");
+ SectionMap::const_iterator iter =
+ GetSectionByName(sections_, ".debug_line");
assert(iter != sections_.end());
scoped_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data,
@@ -232,4 +225,4 @@ void CUFunctionInfoHandler::EndDIE(uint64_t offset) {
current_function_info_));
}
-} // namespace dwarf2reader
+} // namespace google_breakpad
diff --git a/src/common/dwarf/functioninfo.h b/src/common/dwarf/functioninfo.h
index 5c733c6d..1387c5ba 100644
--- a/src/common/dwarf/functioninfo.h
+++ b/src/common/dwarf/functioninfo.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 Google Inc. All Rights Reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -43,7 +43,7 @@
#include "common/using_std_string.h"
-namespace dwarf2reader {
+namespace google_breakpad {
struct FunctionInfo {
// Name of the function
@@ -187,5 +187,5 @@ class CUFunctionInfoHandler: public Dwarf2Handler {
uint64_t current_compilation_unit_offset_;
};
-} // namespace dwarf2reader
+} // namespace google_breakpad
#endif // COMMON_DWARF_FUNCTIONINFO_H__
diff --git a/src/common/dwarf/line_state_machine.h b/src/common/dwarf/line_state_machine.h
index fc301c76..1797e3bc 100644
--- a/src/common/dwarf/line_state_machine.h
+++ b/src/common/dwarf/line_state_machine.h
@@ -1,4 +1,4 @@
-// Copyright 2008 Google Inc. All Rights Reserved.
+// Copyright 2008 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
@@ -30,7 +30,9 @@
#ifndef COMMON_DWARF_LINE_STATE_MACHINE_H__
#define COMMON_DWARF_LINE_STATE_MACHINE_H__
-namespace dwarf2reader {
+#include <stdint.h>
+
+namespace google_breakpad {
// This is the format of a DWARF2/3 line state machine that we process
// opcodes using. There is no need for anything outside the lineinfo
@@ -55,7 +57,7 @@ struct LineStateMachine {
bool end_sequence;
};
-} // namespace dwarf2reader
+} // namespace google_breakpad
#endif // COMMON_DWARF_LINE_STATE_MACHINE_H__
diff --git a/src/common/dwarf/types.h b/src/common/dwarf/types.h
index 23412d0e..b14d7a3e 100644
--- a/src/common/dwarf/types.h
+++ b/src/common/dwarf/types.h
@@ -1,4 +1,4 @@
-// Copyright 2008 Google, Inc. All Rights reserved
+// Copyright 2008 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
// 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
+// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//