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: fix global symbols in merge sections


The attached patch fixes a problem in gold where a global symbol in a
merge section does not get the correct value. The essence of the fix
was a small change in symtab.cc, but it also required some cleanup of
several uses of -1U that did not properly extend to 64 bits.

Approved offline by Ian.

-cary


2008-09-29  Cary Coutant  <ccoutant@google.com>

	* mapfile.cc (Mapfile::print_input_section): Change -1U to -1ULL.
	* object.cc (Sized_relobj::do_layout): Use constant invalid_address
	instead of -1U.
	(Sized_relobj::do_finalize_local_symbols): Likewise.
	(Sized_relobj::map_to_kept_section): Likewise.
	* object.h (Sized_relobj::invalid_address): New constant.
	(Sized_relobj::do_output_section_offset): Check for invalid_address
	and return -1ULL.
	* output.cc (Output_reloc::local_section_offset): Use constant
	invalid_address instead of -1U.
	(Output_reloc::get_address): Likewise.
	(Output_section::output_address): Change -1U to -1ULL.
	* output.h (Output_reloc::invalid_address): New constant.
	* reloc.cc (Sized_relobj::write_sections): Use constant
	invalid_address instead of -1U.
	(Sized_relobj::relocate_sections): Likewise.
	* symtab.cc (Symbol_table::sized_finalize_symbol): Handle symbol
	values for merge sections.
	* target-reloc.h (relocate_for_relocatable): Use constant
	invalid_address instead of -1U.


Index: mapfile.cc
===================================================================
RCS file: /cvs/src/src/gold/mapfile.cc,v
retrieving revision 1.3
diff -u -p -r1.3 mapfile.cc
--- mapfile.cc	7 Aug 2008 17:02:11 -0000	1.3
+++ mapfile.cc	29 Sep 2008 21:08:49 -0000
@@ -253,7 +253,7 @@ Mapfile::print_input_section(Relobj* rel
     {
       os = relobj->output_section(shndx);
       addr = relobj->output_section_offset(shndx);
-      if (addr != -1U)
+      if (addr != -1ULL)
 	addr += os->address();
     }

Index: object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.77
diff -u -p -r1.77 object.cc
--- object.cc	22 Jul 2008 22:08:43 -0000	1.77
+++ object.cc	29 Sep 2008 21:08:49 -0000
@@ -926,7 +926,7 @@ Sized_relobj<size, big_endian>::do_layou
 	{
 	  // Do not include this section in the link.
 	  out_sections[i] = NULL;
-          out_section_offsets[i] = -1U;
+          out_section_offsets[i] = invalid_address;
 	  continue;
 	}

@@ -967,7 +967,7 @@ Sized_relobj<size, big_endian>::do_layou

       out_sections[i] = os;
       if (offset == -1)
-        out_section_offsets[i] = -1U;
+        out_section_offsets[i] = invalid_address;
       else
         out_section_offsets[i] = convert_types<Address, off_t>(offset);

@@ -1004,7 +1004,7 @@ Sized_relobj<size, big_endian>::do_layou
       if (data_section == NULL)
 	{
 	  out_sections[i] = NULL;
-          out_section_offsets[i] = -1U;
+          out_section_offsets[i] = invalid_address;
 	  continue;
 	}

@@ -1014,7 +1014,7 @@ Sized_relobj<size, big_endian>::do_layou
       Output_section* os = layout->layout_reloc(this, i, shdr, data_section,
 						rr);
       out_sections[i] = os;
-      out_section_offsets[i] = -1U;
+      out_section_offsets[i] = invalid_address;
     }

   // Handle the .eh_frame sections at the end.
@@ -1042,7 +1042,7 @@ Sized_relobj<size, big_endian>::do_layou
 						   &offset);
       out_sections[i] = os;
       if (offset == -1)
-        out_section_offsets[i] = -1U;
+        out_section_offsets[i] = invalid_address;
       else
         out_section_offsets[i] = convert_types<Address, off_t>(offset);

@@ -1266,7 +1266,7 @@ Sized_relobj<size, big_endian>::do_final
               // so we leave the input value unchanged here.
 	      continue;
 	    }
-	  else if (out_offsets[shndx] == -1U)
+	  else if (out_offsets[shndx] == invalid_address)
 	    {
 	      // This is a SHF_MERGE section or one which otherwise
 	      // requires special handling.  We get the output address
@@ -1573,7 +1573,7 @@ Sized_relobj<size, big_endian>::map_to_k
       *found = true;
       Output_section* os = kept->object_->output_section(kept->shndx_);
       Address offset = kept->object_->get_output_section_offset(kept->shndx_);
-      gold_assert(os != NULL && offset != -1U);
+      gold_assert(os != NULL && offset != invalid_address);
       return os->address() + offset;
     }
   *found = false;
Index: object.h
===================================================================
RCS file: /cvs/src/src/gold/object.h,v
retrieving revision 1.65
diff -u -p -r1.65 object.h
--- object.h	19 Sep 2008 22:54:57 -0000	1.65
+++ object.h	29 Sep 2008 21:08:49 -0000
@@ -1202,6 +1202,8 @@ class Sized_relobj : public Relobj
   typedef std::vector<Symbol*> Symbols;
   typedef std::vector<Symbol_value<size> > Local_values;

+  static const Address invalid_address = static_cast<Address>(0) - 1;
+
   Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
 	       const typename elfcpp::Ehdr<size, big_endian>&);

@@ -1457,7 +1459,12 @@ class Sized_relobj : public Relobj
   // Get the offset of a section.
   uint64_t
   do_output_section_offset(unsigned int shndx) const
-  { return this->get_output_section_offset(shndx); }
+  {
+    Address off = this->get_output_section_offset(shndx);
+    if (off == invalid_address)
+      return -1ULL;
+    return off;
+  }

   // Set the offset of a section.
   void
@@ -1699,7 +1706,7 @@ class Sized_relobj : public Relobj
   // for TLS symbols, indexed by symbol number.
   Local_got_offsets local_got_offsets_;
   // For each input section, the offset of the input section in its
-  // output section.  This is -1U if the input section requires a
+  // output section.  This is INVALID_ADDRESS if the input section requires a
   // special mapping.
   std::vector<Address> section_offsets_;
   // Table mapping discarded comdat sections to corresponding kept sections.
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.83
diff -u -p -r1.83 output.cc
--- output.cc	13 Aug 2008 07:37:46 -0000	1.83
+++ output.cc	29 Sep 2008 21:08:49 -0000
@@ -838,11 +838,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, s
   Output_section* os = this->u1_.relobj->output_section(lsi);
   gold_assert(os != NULL);
   Address offset = this->u1_.relobj->get_output_section_offset(lsi);
-  if (offset != -1U)
+  if (offset != invalid_address)
     return offset + addend;
   // This is a merge section.
   offset = os->output_address(this->u1_.relobj, lsi, addend);
-  gold_assert(offset != -1U);
+  gold_assert(offset != invalid_address);
   return offset;
 }

@@ -858,13 +858,13 @@ Output_reloc<elfcpp::SHT_REL, dynamic, s
       Output_section* os = this->u2_.relobj->output_section(this->shndx_);
       gold_assert(os != NULL);
       Address off = this->u2_.relobj->get_output_section_offset(this->shndx_);
-      if (off != -1U)
+      if (off != invalid_address)
 	address += os->address() + off;
       else
 	{
 	  address = os->output_address(this->u2_.relobj, this->shndx_,
 				       address);
-	  gold_assert(address != -1U);
+	  gold_assert(address != invalid_address);
 	}
     }
   else if (this->u2_.od != NULL)
@@ -2043,7 +2043,7 @@ Output_section::output_address(const Rel
       if (p->output_offset(object, shndx, offset, &output_offset))
 	{
 	  if (output_offset == -1)
-	    return -1U;
+	    return -1ULL;
 	  return addr + output_offset;
 	}
       addr += p->data_size();
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.75
diff -u -p -r1.75 output.h
--- output.h	13 Aug 2008 07:37:46 -0000	1.75
+++ output.h	29 Sep 2008 21:08:49 -0000
@@ -874,6 +874,8 @@ class Output_reloc<elfcpp::SHT_REL, dyna
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;

+  static const Address invalid_address = static_cast<Address>(0) - 1;
+
   // An uninitialized entry.  We need this because we want to put
   // instances of this class into an STL container.
   Output_reloc()
@@ -1915,7 +1917,7 @@ class Output_section : public Output_dat

   // Add a new input section SHNDX, named NAME, with header SHDR, from
   // object OBJECT.  RELOC_SHNDX is the index of a relocation section
-  // which applies to this section, or 0 if none, or -1U if more than
+  // which applies to this section, or 0 if none, or -1 if more than
   // one.  HAVE_SECTIONS_SCRIPT is true if we have a SECTIONS clause
   // in a linker script; in that case we need to keep track of input
   // sections associated with an output section.  Return the offset
Index: reloc.cc
===================================================================
RCS file: /cvs/src/src/gold/reloc.cc,v
retrieving revision 1.37
diff -u -p -r1.37 reloc.cc
--- reloc.cc	10 Jul 2008 23:01:19 -0000	1.37
+++ reloc.cc	29 Sep 2008 21:08:49 -0000
@@ -586,8 +586,8 @@ Sized_relobj<size, big_endian>::write_se
       // In the normal case, this input section is simply mapped to
       // the output section at offset OUTPUT_OFFSET.

-      // However, if OUTPUT_OFFSET == -1U, then input data is handled
-      // specially--e.g., a .eh_frame section.  The relocation
+      // However, if OUTPUT_OFFSET == INVALID_ADDRESS, then input data is
+      // handled specially--e.g., a .eh_frame section.  The relocation
       // routines need to check for each reloc where it should be
       // applied.  For this case, we need an input/output view for the
       // entire contents of the section in the output file.  We don't
@@ -619,7 +619,7 @@ Sized_relobj<size, big_endian>::write_se

       off_t view_start;
       section_size_type view_size;
-      if (output_offset != -1U)
+      if (output_offset != invalid_address)
 	{
 	  view_start = output_section_offset + output_offset;
 	  view_size = convert_to_section_size_type(shdr.get_sh_size());
@@ -633,7 +633,7 @@ Sized_relobj<size, big_endian>::write_se
       if (view_size == 0)
 	continue;

-      gold_assert(output_offset == -1U
+      gold_assert(output_offset == invalid_address
 		  || output_offset + view_size <= output_section_size);

       unsigned char* view;
@@ -641,7 +641,7 @@ Sized_relobj<size, big_endian>::write_se
 	{
 	  unsigned char* buffer = os->postprocessing_buffer();
 	  view = buffer + view_start;
-	  if (output_offset != -1U)
+	  if (output_offset != invalid_address)
 	    {
 	      off_t sh_offset = shdr.get_sh_offset();
 	      if (!rm.empty() && rm.back().file_offset > sh_offset)
@@ -652,7 +652,7 @@ Sized_relobj<size, big_endian>::write_se
 	}
       else
 	{
-	  if (output_offset == -1U)
+	  if (output_offset == invalid_address)
 	    view = of->get_input_output_view(view_start, view_size);
 	  else
 	    {
@@ -667,11 +667,11 @@ Sized_relobj<size, big_endian>::write_se

       pvs->view = view;
       pvs->address = os->address();
-      if (output_offset != -1U)
+      if (output_offset != invalid_address)
 	pvs->address += output_offset;
       pvs->offset = view_start;
       pvs->view_size = view_size;
-      pvs->is_input_output_view = output_offset == -1U;
+      pvs->is_input_output_view = output_offset == invalid_address;
       pvs->is_postprocessing_view = os->requires_postprocessing();
     }

@@ -772,7 +772,7 @@ Sized_relobj<size, big_endian>::relocate
 	  continue;
 	}

-      gold_assert(output_offset != -1U
+      gold_assert(output_offset != invalid_address
 		  || this->relocs_must_follow_section_writes());

       relinfo.reloc_shndx = i;
@@ -784,7 +784,7 @@ Sized_relobj<size, big_endian>::relocate
 				   prelocs,
 				   reloc_count,
 				   os,
-				   output_offset == -1U,
+				   output_offset == invalid_address,
 				   (*pviews)[index].view,
 				   (*pviews)[index].address,
 				   (*pviews)[index].view_size);
Index: symtab.cc
===================================================================
RCS file: /cvs/src/src/gold/symtab.cc,v
retrieving revision 1.110
diff -u -p -r1.110 symtab.cc
--- symtab.cc	19 Sep 2008 22:54:57 -0000	1.110
+++ symtab.cc	29 Sep 2008 21:08:49 -0000
@@ -2136,11 +2136,20 @@ Symbol_table::sized_finalize_symbol(Symb
 	      }

             uint64_t secoff64 = relobj->output_section_offset(shndx);
-            Value_type secoff = convert_types<Value_type, uint64_t>(secoff64);
-	    if (sym->type() == elfcpp::STT_TLS)
-	      value = sym->value() + os->tls_offset() + secoff;
-	    else
-	      value = sym->value() + os->address() + secoff;
+            if (secoff64 == -1ULL)
+              {
+                // The section needs special handling (e.g., a merge section).
+	        value = os->output_address(relobj, shndx, sym->value());
+	      }
+            else
+              {
+                Value_type secoff =
+                  convert_types<Value_type, uint64_t>(secoff64);
+	        if (sym->type() == elfcpp::STT_TLS)
+	          value = sym->value() + os->tls_offset() + secoff;
+	        else
+	          value = sym->value() + os->address() + secoff;
+	      }
 	  }
       }
       break;
Index: target-reloc.h
===================================================================
RCS file: /cvs/src/src/gold/target-reloc.h,v
retrieving revision 1.28
diff -u -p -r1.28 target-reloc.h
--- target-reloc.h	16 Sep 2008 17:23:37 -0000	1.28
+++ target-reloc.h	29 Sep 2008 21:08:49 -0000
@@ -450,6 +450,7 @@ relocate_for_relocatable(
   typedef typename Reloc_types<sh_type, size, big_endian>::Reloc_write
     Reltype_write;
   const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
+  const Address invalid_address = static_cast<Address>(0) - 1;

   Sized_relobj<size, big_endian>* const object = relinfo->object;
   const unsigned int local_count = object->local_symbol_count();
@@ -524,7 +525,7 @@ relocate_for_relocatable(

       Address offset = reloc.get_r_offset();
       Address new_offset;
-      if (offset_in_output_section != -1U)
+      if (offset_in_output_section != invalid_address)
 	new_offset = offset + offset_in_output_section;
       else
 	{
@@ -543,7 +544,7 @@ relocate_for_relocatable(
       if (!parameters->options().relocatable())
 	{
 	  new_offset += view_address;
-	  if (offset_in_output_section != -1U)
+	  if (offset_in_output_section != invalid_address)
 	    new_offset -= offset_in_output_section;
 	}


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