diff --git a/src/common/dwarf/dwarf2enums.h b/src/common/dwarf/dwarf2enums.h index b93510a7..b9aae059 100644 --- a/src/common/dwarf/dwarf2enums.h +++ b/src/common/dwarf/dwarf2enums.h @@ -162,20 +162,25 @@ enum DwarfForm { // 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_addrx = 0x1b, DW_FORM_addrx1 = 0x29, DW_FORM_addrx2 = 0x2a, DW_FORM_addrx3 = 0x2b, diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc index f1f4007d..367d936f 100644 --- a/src/common/dwarf/dwarf2reader.cc +++ b/src/common/dwarf/dwarf2reader.cc @@ -160,10 +160,15 @@ void CompilationUnit::ReadAbbrevs() { if (nametemp == 0 && formtemp == 0) break; - const enum DwarfAttribute name = - static_cast(nametemp); - const enum DwarfForm form = static_cast(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(nametemp), + static_cast(formtemp), + value); + abbrev.attributes.push_back(abbrev_attr); } assert(abbrev.number == abbrevs_->size()); abbrevs_->push_back(abbrev); @@ -176,7 +181,7 @@ const uint8_t* CompilationUnit::SkipDIE(const uint8_t* start, 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; } @@ -194,6 +199,7 @@ 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: @@ -213,11 +219,15 @@ const uint8_t* CompilationUnit::SkipAttribute(const uint8_t* start, 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(start)) + 1; case DW_FORM_udata: @@ -227,6 +237,7 @@ const uint8_t* CompilationUnit::SkipAttribute(const uint8_t* start, 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; @@ -458,7 +469,7 @@ void CompilationUnit::ProcessFormStringIndex( // 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) { + enum DwarfForm form, uint64_t implicit_const) { size_t len; switch (form) { @@ -468,7 +479,7 @@ const uint8_t* CompilationUnit::ProcessAttribute( form = static_cast(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); @@ -490,6 +501,10 @@ 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(start); ProcessAttributeString(dieoffset, attr, form, str); @@ -557,7 +572,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, @@ -609,7 +627,18 @@ const uint8_t* CompilationUnit::ProcessAttribute( // 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_->ReadUnsignedLEB128(start, &len)); + return start + len; case DW_FORM_strx: case DW_FORM_GNU_str_index: { uint64_t str_index = reader_->ReadUnsignedLEB128(start, &len); @@ -673,7 +702,7 @@ const uint8_t* CompilationUnit::ProcessDIE(uint64_t dieoffset, 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 diff --git a/src/common/dwarf/dwarf2reader.h b/src/common/dwarf/dwarf2reader.h index d041dd86..8da190c2 100644 --- a/src/common/dwarf/dwarf2reader.h +++ b/src/common/dwarf/dwarf2reader.h @@ -72,8 +72,19 @@ typedef std::map > SectionMap; const SectionMap::const_iterator GetSectionByName(const SectionMap& sections, const char* name); -typedef std::list > - AttributeList; +// 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 AttributeList; typedef AttributeList::iterator AttributeIterator; typedef AttributeList::const_iterator ConstAttributeIterator; @@ -527,7 +538,8 @@ class CompilationUnit { const uint8_t* ProcessAttribute(uint64_t dieoffset, const uint8_t* start, enum DwarfAttribute attr, - enum DwarfForm form); + 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 diff --git a/src/common/dwarf/dwarf2reader_die_unittest.cc b/src/common/dwarf/dwarf2reader_die_unittest.cc index 0d8811bb..57b8f71a 100644 --- a/src/common/dwarf/dwarf2reader_die_unittest.cc +++ b/src/common/dwarf/dwarf2reader_die_unittest.cc @@ -463,6 +463,35 @@ 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, dwarf2reader::DW_children_no) + .Attribute((DwarfAttribute) 0xd708d908, + dwarf2reader::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) + .ULEB128(1); // abbrev code + info.Finish(); + + ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b); + EXPECT_CALL(handler, + ProcessAttributeUnsigned(_, (DwarfAttribute) 0xd708d908, + dwarf2reader::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(