Set addr_base_ before parsing attributes.

If there is an address index reference to .debug_addr section before
DW_AT_addr_base, addr_base_ will be 0. It will retrieve wrong address.
An example could be DW_AT_loc_pc occurs before DW_AT_addr_base.

Change-Id: Id2b337f5235470cc9beaf05a62efebbde797dacf
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/2900806
Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
Zequan Wu 2021-05-17 12:50:42 -07:00 committed by Sterling Augustine
parent 13ba5a1549
commit 6842fa5aa8
2 changed files with 19 additions and 17 deletions

View file

@ -467,11 +467,12 @@ void CompilationUnit::ProcessFormStringIndex(
ProcessAttributeString(dieoffset, attr, form, str); ProcessAttributeString(dieoffset, attr, form, str);
} }
// Special function for pre-processing the DW_AT_str_offsets_base in a // Special function for pre-processing the
// DW_TAG_compile_unit die (for DWARF v5). We must make sure to find and // DW_AT_str_offsets_base and DW_AT_addr_base in a DW_TAG_compile_unit die (for
// process the DW_AT_str_offsets_base attribute before attempting to read // DWARF v5). We must make sure to find and process the
// any string attribute in the compile unit. // DW_AT_str_offsets_base and DW_AT_addr_base attributes before attempting to
const uint8_t* CompilationUnit::ProcessStrOffsetBaseAttribute( // 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, uint64_t dieoffset, const uint8_t* start, enum DwarfAttribute attr,
enum DwarfForm form, uint64_t implicit_const) { enum DwarfForm form, uint64_t implicit_const) {
size_t len; size_t len;
@ -483,7 +484,7 @@ const uint8_t* CompilationUnit::ProcessStrOffsetBaseAttribute(
form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start, form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start,
&len)); &len));
start += len; start += len;
return ProcessStrOffsetBaseAttribute(dieoffset, start, attr, form, return ProcessOffsetBaseAttribute(dieoffset, start, attr, form,
implicit_const); implicit_const);
case DW_FORM_flag_present: case DW_FORM_flag_present:
@ -516,11 +517,12 @@ const uint8_t* CompilationUnit::ProcessStrOffsetBaseAttribute(
// This is the important one here! // This is the important one here!
case DW_FORM_sec_offset: case DW_FORM_sec_offset:
if (attr == dwarf2reader::DW_AT_str_offsets_base) if (attr == dwarf2reader::DW_AT_str_offsets_base ||
ProcessAttributeUnsigned(dieoffset, attr, form, attr == dwarf2reader::DW_AT_addr_base)
reader_->ReadOffset(start)); ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadOffset(start));
else else
reader_->ReadOffset(start); reader_->ReadOffset(start);
return start + reader_->OffsetSize(); return start + reader_->OffsetSize();
case DW_FORM_ref1: case DW_FORM_ref1:
@ -858,16 +860,16 @@ const uint8_t* CompilationUnit::ProcessDIE(uint64_t dieoffset,
const uint8_t* start, const uint8_t* start,
const Abbrev& abbrev) { const Abbrev& abbrev) {
// With DWARF v5, the compile_unit die may contain a // With DWARF v5, the compile_unit die may contain a
// DW_AT_str_offsets_base. If it does, that attribute must be found // DW_AT_str_offsets_base or DW_AT_addr_base. If it does, that attribute must
// and processed before trying to process the other attributes; otherwise // be found and processed before trying to process the other attributes;
// the string values will all come out incorrect. // otherwise the string or address values will all come out incorrect.
if (abbrev.tag == DW_TAG_compile_unit && header_.version == 5) { if (abbrev.tag == DW_TAG_compile_unit && header_.version == 5) {
uint64_t dieoffset_copy = dieoffset; uint64_t dieoffset_copy = dieoffset;
const uint8_t* start_copy = start; const uint8_t* start_copy = start;
for (AttributeList::const_iterator i = abbrev.attributes.begin(); for (AttributeList::const_iterator i = abbrev.attributes.begin();
i != abbrev.attributes.end(); i != abbrev.attributes.end();
i++) { i++) {
start_copy = ProcessStrOffsetBaseAttribute(dieoffset_copy, start_copy, start_copy = ProcessOffsetBaseAttribute(dieoffset_copy, start_copy,
i->attr_, i->form_, i->attr_, i->form_,
i->value_); i->value_);
} }

View file

@ -538,9 +538,9 @@ class CompilationUnit {
enum DwarfForm form, enum DwarfForm form,
uint64_t implicit_const); uint64_t implicit_const);
// Special version of ProcessAttribute, for finding str_offsets_base in // Special version of ProcessAttribute, for finding str_offsets_base and
// DW_TAG_compile_unit, for DWARF v5. // DW_AT_addr_base in DW_TAG_compile_unit, for DWARF v5.
const uint8_t* ProcessStrOffsetBaseAttribute(uint64_t dieoffset, const uint8_t* ProcessOffsetBaseAttribute(uint64_t dieoffset,
const uint8_t* start, const uint8_t* start,
enum DwarfAttribute attr, enum DwarfAttribute attr,
enum DwarfForm form, enum DwarfForm form,