aboutsummaryrefslogtreecommitdiff
path: root/src/common/dwarf/dwarf2reader.cc
diff options
context:
space:
mode:
authorSterling Augustine <saugustine@google.com>2020-06-25 14:55:48 -0700
committerSterling Augustine <saugustine@google.com>2020-06-25 21:56:34 +0000
commit8efe0f1c3b45b79bab3046c0776283a2bdf6193f (patch)
treebcbd90467782fb0c0e6758414c92bc50c96008ef /src/common/dwarf/dwarf2reader.cc
parentAdd and handle various dwarf5 addrx forms. (diff)
downloadbreakpad-8efe0f1c3b45b79bab3046c0776283a2bdf6193f.tar.xz
Read dwarf5 compilation unit headers.
Change-Id: Ia85b2fb7b3cb821ad353a0003223d8b8465e792d Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/2265259 Reviewed-by: Mike Frysinger <vapier@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org>
Diffstat (limited to 'src/common/dwarf/dwarf2reader.cc')
-rw-r--r--src/common/dwarf/dwarf2reader.cc90
1 files changed, 74 insertions, 16 deletions
diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc
index fbfff275..138f9200 100644
--- a/src/common/dwarf/dwarf2reader.cc
+++ b/src/common/dwarf/dwarf2reader.cc
@@ -253,11 +253,50 @@ 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_;
size_t initial_length_size;
@@ -272,17 +311,36 @@ 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:
+ 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