This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gold patch committed: Fix ODR violation detection reloc handling


This patch changes the ODR violation detector in gold to include the
reloc addend.  This is clearly the correct thing to do.  Unfortunately I
don't have a reliable test case.  The reloc addend was accidentally
omitted in the past because ODR violations normally happen with
functions with vague linkage, and those are normally always at the start
of a section.  The relevant reloc is the one in the debug info, and it
normally always refers to the start of a section with a reloc of zero.

However, when using multiple inheritance, g++ may add a thunk to the
start of a section, in which case the reloc addend does become relevant.
If you are very unlucky, it is possible to get an incorrect report of an
ODR violation because ignoring the addend can cause gold to deduce
different line numbers.

I committed this patch to mainline to fix the problem.

Ian


2010-12-01  Ian Lance Taylor  <iant@google.com>

	* dwarf_reader.h (class Sized_dwarf_line_info): Add
	track_relocs_type_ field.
	* dwarf_reader.cc (Sized_dwarf_line_info::Sized_dwarf_line_info):
	Set track_relocs_type_.
	(Sized_dwarf_line_info::process_one_opcode): Ignore the section
	contents when using RELA relocs.
	(Sized_dwarf_line_info::read_relocs): Add the reloc addend to
	reloc_map_.
	* reloc.cc (Track_relocs::next_addend): New function.
	* reloc.h (class Track_relocs): Declare next_addend.


Index: dwarf_reader.cc
===================================================================
RCS file: /cvs/src/src/gold/dwarf_reader.cc,v
retrieving revision 1.28
diff -u -u -p -r1.28 dwarf_reader.cc
--- dwarf_reader.cc	17 Nov 2010 01:53:22 -0000	1.28
+++ dwarf_reader.cc	1 Dec 2010 19:40:22 -0000
@@ -1,6 +1,6 @@
 // dwarf_reader.cc -- parse dwarf2/3 debug information
 
-// Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -113,6 +113,7 @@ Sized_dwarf_line_info<size, big_endian>:
 	{
 	  got_relocs = this->track_relocs_.initialize(object, reloc_shndx,
                                                       reloc_sh_type);
+	  this->track_relocs_type_ = reloc_sh_type;
 	  break;
 	}
     }
@@ -392,13 +393,21 @@ Sized_dwarf_line_info<size, big_endian>:
 
           case elfcpp::DW_LNE_set_address:
             {
-              lsm->address = elfcpp::Swap_unaligned<size, big_endian>::readval(start);
+              lsm->address =
+		elfcpp::Swap_unaligned<size, big_endian>::readval(start);
               typename Reloc_map::const_iterator it
-                  = reloc_map_.find(start - this->buffer_);
+                  = this->reloc_map_.find(start - this->buffer_);
               if (it != reloc_map_.end())
                 {
-                  // value + addend.
-                  lsm->address += it->second.second;
+		  // If this is a SHT_RELA section, then ignore the
+		  // section contents.  This assumes that this is a
+		  // straight reloc which just uses the reloc addend.
+		  // The reloc addend has already been included in the
+		  // symbol value.
+		  if (this->track_relocs_type_ == elfcpp::SHT_RELA)
+		    lsm->address = 0;
+		  // Add in the symbol value.
+		  lsm->address += it->second.second;
                   lsm->shndx = it->second.first;
                 }
               else
@@ -536,7 +545,10 @@ Sized_dwarf_line_info<size, big_endian>:
       // There is no reason to record non-ordinary section indexes, or
       // SHN_UNDEF, because they will never match the real section.
       if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
-	this->reloc_map_[reloc_offset] = std::make_pair(shndx, value);
+	{
+	  value += this->track_relocs_.next_addend();
+	  this->reloc_map_[reloc_offset] = std::make_pair(shndx, value);
+	}
 
       this->track_relocs_.advance(reloc_offset + 1);
     }
Index: dwarf_reader.h
===================================================================
RCS file: /cvs/src/src/gold/dwarf_reader.h,v
retrieving revision 1.17
diff -u -u -p -r1.17 dwarf_reader.h
--- dwarf_reader.h	9 Dec 2009 03:02:28 -0000	1.17
+++ dwarf_reader.h	1 Dec 2010 19:40:22 -0000
@@ -1,6 +1,6 @@
 // dwarf_reader.h -- parse dwarf2/3 debug information for gold  -*- C++ -*-
 
-// Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -178,6 +178,8 @@ class Sized_dwarf_line_info : public Dwa
 
   // This has relocations that point into buffer.
   Track_relocs<size, big_endian> track_relocs_;
+  // The type of the reloc section in track_relocs_--SHT_REL or SHT_RELA.
+  unsigned int track_relocs_type_;
 
   // This is used to figure out what section to apply a relocation to.
   const unsigned char* symtab_buffer_;
Index: reloc.cc
===================================================================
RCS file: /cvs/src/src/gold/reloc.cc,v
retrieving revision 1.60
diff -u -u -p -r1.60 reloc.cc
--- reloc.cc	14 Oct 2010 22:10:22 -0000	1.60
+++ reloc.cc	1 Dec 2010 19:40:22 -0000
@@ -1591,6 +1591,20 @@ Track_relocs<size, big_endian>::next_sym
   return elfcpp::elf_r_sym<size>(rel.get_r_info());
 }
 
+// Return the addend of the next reloc, or 0 if there isn't one.
+
+template<int size, bool big_endian>
+uint64_t
+Track_relocs<size, big_endian>::next_addend() const
+{
+  if (this->pos_ >= this->len_)
+    return 0;
+  if (this->reloc_size_ == elfcpp::Elf_sizes<size>::rel_size)
+    return 0;
+  elfcpp::Rela<size, big_endian> rela(this->prelocs_ + this->pos_);
+  return rela.get_r_addend();
+}
+
 // Advance to the next reloc whose r_offset is greater than or equal
 // to OFFSET.  Return the number of relocs we skip.
 
Index: reloc.h
===================================================================
RCS file: /cvs/src/src/gold/reloc.h,v
retrieving revision 1.29
diff -u -u -p -r1.29 reloc.h
--- reloc.h	12 Feb 2010 04:33:53 -0000	1.29
+++ reloc.h	1 Dec 2010 19:40:22 -0000
@@ -678,7 +678,7 @@ class Track_relocs
 	     unsigned int reloc_type);
 
   // Return the offset in the data section to which the next reloc
-  // applies.  THis returns -1 if there is no next reloc.
+  // applies.  This returns -1 if there is no next reloc.
   off_t
   next_offset() const;
 
@@ -687,6 +687,11 @@ class Track_relocs
   unsigned int
   next_symndx() const;
 
+  // Return the addend of the next reloc.  This returns 0 if there is
+  // no next reloc.
+  uint64_t
+  next_addend() const;
+
   // Advance to OFFSET within the data section, and return the number
   // of relocs which would be skipped.
   int

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]