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: Accept negative addend for merge section symbol


PR 6658 is about an object file which is arguably malformed.  It
contains a reloc against a section symbol of a merge section with a
negative addend.  When the linker sees a reloc against a section
symbol of a merge section, it must use the addend to identify the part
of the merge section in the input file, and map that to a part of the
merge section in the output file.  That only works for a positive
addend.  This object file should really be using a local symbol rather
than a section symbol.

Worse, this is a 32-bit reloc in a 64-bit object file, so it's not
even particularly obvious that the addend, 0xfffffffc, is negative.

Still, we want gold to work, so I patched gold to try to handle this
case correctly.

Ian


2008-07-23  Ian Lance Taylor  <iant@google.com>

	PR 6658
	* object.h (Merged_symbol_value::value): Do our best to handle a
	negative addend.


Index: object.h
===================================================================
RCS file: /cvs/src/src/gold/object.h,v
retrieving revision 1.62
diff -u -p -r1.62 object.h
--- object.h	22 Jul 2008 22:08:43 -0000	1.62
+++ object.h	24 Jul 2008 01:20:26 -0000
@@ -822,13 +822,36 @@ class Merged_symbol_value
   Value
   value(const Relobj* object, unsigned int input_shndx, Value addend) const
   {
-    Value input_offset = this->input_value_ + addend;
+    // This is a relocation against a section symbol.  ADDEND is the
+    // offset in the section.  The result should be the start of some
+    // merge area.  If the object file wants something else, it should
+    // use a regular symbol rather than a section symbol.
+    // Unfortunately, PR 6658 shows a case in which the object file
+    // refers to the section symbol, but uses a negative ADDEND to
+    // compensate for a PC relative reloc.  We can't handle the
+    // general case.  However, we can handle the special case of a
+    // negative addend, by assuming that it refers to the start of the
+    // section.  Of course, that means that we have to guess when
+    // ADDEND is negative.  It is normal to see a 32-bit value here
+    // even when the template parameter size is 64, as 64-bit object
+    // file formats have 32-bit relocations.  We know this is a merge
+    // section, so we know it has to fit into memory.  So we assume
+    // that we won't see a value larger than a large 32-bit unsigned
+    // value.  This will break objects with very very large merge
+    // sections; they probably break in other ways anyhow.
+    Value input_offset = this->input_value_;
+    if (addend < 0xffffff00)
+      {
+	input_offset += addend;
+	addend = 0;
+      }
     typename Output_addresses::const_iterator p =
       this->output_addresses_.find(input_offset);
     if (p != this->output_addresses_.end())
-      return p->second;
+      return p->second + addend;
 
-    return this->value_from_output_section(object, input_shndx, input_offset);
+    return (this->value_from_output_section(object, input_shndx, input_offset)
+	    + addend);
   }
 
  private:

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