gold patch RFC: fix address size of DW_FORM_ref_addr

Ian Lance Taylor via binutils binutils@sourceware.org
Fri Nov 17 18:19:00 GMT 2017


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


More information about the Binutils mailing list