In DWARF version 3, DW_FORM_ref_addr changed from using the
compilation unit's address size to using the compilation unit's offset
size. Although that change happened a while ago, gold was never
updated. This patch updates gold.
I'm not sure if there is a reasonable way to test this. GCC never
seems to generate DW_FORM_ref_addr anyhow; it uses DW_FORM_ref4. I
ran across this using the Go compiler, which does DW_FORM_ref_addr
although it should probably also use DW_FORM_ref4.
Anyhow, Cary, does this patch look correct to you? Thanks.
Ian
2017-11-17 Ian Lance Taylor <iant@google.com>
* dwarf_reader.h (class Dwarf_info_reader): Add cu_version
method.
* dwarf_reader.cc (Dwarf_die::read_attributes): On DWARF version 3
and higher, use offset size for DW_FORM_ref_addr.
(Dwarf_die::skip_attributes): Likewise.
-------------- next part --------------
diff --git a/gold/dwarf_reader.cc b/gold/dwarf_reader.cc
index 8c0d593752..6fbea9b5c8 100644
--- a/gold/dwarf_reader.cc
+++ b/gold/dwarf_reader.cc
@@ -739,8 +739,14 @@ Dwarf_die::read_attributes()
case elfcpp::DW_FORM_addr:
case elfcpp::DW_FORM_ref_addr:
{
+ unsigned int address_size = this->dwinfo_->address_size();
+ // In DWARF version 3 DW_FORM_ref_addr changed from the
+ // address size to the compilation unit's offset size.
+ if (form == elfcpp::DW_FORM_ref_addr
+ && this->dwinfo_->cu_version() > 2)
+ address_size = this->dwinfo_->offset_size();
off_t sec_off;
- if (this->dwinfo_->address_size() == 4)
+ if (address_size == 4)
sec_off = this->dwinfo_->read_from_pointer<32>(&pattr);
else
sec_off = this->dwinfo_->read_from_pointer<64>(&pattr);
@@ -948,7 +954,15 @@ Dwarf_die::skip_attributes()
break;
case elfcpp::DW_FORM_addr:
case elfcpp::DW_FORM_ref_addr:
- pattr += this->dwinfo_->address_size();
+ {
+ unsigned int address_size = this->dwinfo_->address_size();
+ // In DWARF version 3 DW_FORM_ref_addr changed from the
+ // address size to the compilation unit's offset size.
+ if (form == elfcpp::DW_FORM_ref_addr
+ && this->dwinfo_->cu_version() > 2)
+ address_size = this->dwinfo_->offset_size();
+ pattr += address_size;
+ }
break;
case elfcpp::DW_FORM_block1:
pattr += 1 + *pattr;
diff --git a/gold/dwarf_reader.h b/gold/dwarf_reader.h
index b41e057621..441800fdf9 100644
--- a/gold/dwarf_reader.h
+++ b/gold/dwarf_reader.h
@@ -754,6 +754,11 @@ class Dwarf_info_reader
const char*
get_string(off_t str_off, unsigned int string_shndx);
+ // Return the version of the current compilation unit.
+ unsigned int
+ cu_version() const
+ { return this->cu_version_; }
+
// Return the size of a DWARF offset.
unsigned int
offset_size() const