gold: Fix 64-bit sparc GOLD crash in gdb-index code.
[binutils-gdb.git] / gold / output.h
index db38236f3de999fdb9d5a8216e9a5a08b1041174..3796e9120cea9dac483edc20d9460f9d471519fd 100644 (file)
@@ -1021,12 +1021,13 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // A reloc against a global symbol.
 
   Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
-              Address address, bool is_relative, bool is_symbolless);
+              Address address, bool is_relative, bool is_symbolless,
+              bool use_plt_offset);
 
   Output_reloc(Symbol* gsym, unsigned int type,
                Sized_relobj<size, big_endian>* relobj,
               unsigned int shndx, Address address, bool is_relative,
-              bool is_symbolless);
+              bool is_symbolless, bool use_plt_offset);
 
   // A reloc against a local symbol or local section symbol.
 
@@ -1226,8 +1227,7 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   bool is_symbolless_ : 1;
   // True if the relocation is against a section symbol.
   bool is_section_symbol_ : 1;
-  // True if the addend should be the PLT offset.  This is used only
-  // for RELATIVE relocations to local symbols.
+  // True if the addend should be the PLT offset.
   // (Used only for RELA, but stored here for space.)
   bool use_plt_offset_ : 1;
   // If the reloc address is an input section in an object, the
@@ -1255,17 +1255,18 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
               Address address, Addend addend, bool is_relative,
-              bool is_symbolless)
-    : rel_(gsym, type, od, address, is_relative, is_symbolless),
+              bool is_symbolless, bool use_plt_offset)
+    : rel_(gsym, type, od, address, is_relative, is_symbolless,
+          use_plt_offset),
       addend_(addend)
   { }
 
   Output_reloc(Symbol* gsym, unsigned int type,
                Sized_relobj<size, big_endian>* relobj,
               unsigned int shndx, Address address, Addend addend,
-              bool is_relative, bool is_symbolless)
+              bool is_relative, bool is_symbolless, bool use_plt_offset)
     : rel_(gsym, type, relobj, shndx, address, is_relative,
-          is_symbolless), addend_(addend)
+          is_symbolless, use_plt_offset), addend_(addend)
   { }
 
   // A reloc against a local symbol.
@@ -1558,14 +1559,14 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address)
-  { this->add(od, Output_reloc_type(gsym, type, od, address, false, false)); }
+  { this->add(od, Output_reloc_type(gsym, type, od, address, false, false, false)); }
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
              Sized_relobj<size, big_endian>* relobj,
             unsigned int shndx, Address address)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
-                                    false, false)); }
+                                    false, false, false)); }
 
   void
   add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
@@ -1574,7 +1575,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
     gold_assert(addend == 0);
     this->add(od, Output_reloc_type(gsym, type, od,
                                    convert_types<Address, uint64_t>(address),
-                                   false, false));
+                                   false, false, false));
   }
 
   void
@@ -1587,7 +1588,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
       static_cast<Sized_relobj<size, big_endian>*>(relobj);
     this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx,
                                    convert_types<Address, uint64_t>(address),
-                                   false, false));
+                                   false, false, false));
   }
 
   // Add a RELATIVE reloc against a global symbol.  The final relocation
@@ -1596,7 +1597,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
                       Address address)
-  { this->add(od, Output_reloc_type(gsym, type, od, address, true, true)); }
+  { this->add(od, Output_reloc_type(gsym, type, od, address, true, true,
+                                   false)); }
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
@@ -1604,7 +1606,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
                       unsigned int shndx, Address address)
   {
     this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
-                                    true, true));
+                                    true, true, false));
   }
 
   // Add a global relocation which does not use a symbol for the relocation,
@@ -1613,7 +1615,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   void
   add_symbolless_global_addend(Symbol* gsym, unsigned int type,
                               Output_data* od, Address address)
-  { this->add(od, Output_reloc_type(gsym, type, od, address, false, true)); }
+  { this->add(od, Output_reloc_type(gsym, type, od, address, false, true,
+                                   false)); }
 
   void
   add_symbolless_global_addend(Symbol* gsym, unsigned int type,
@@ -1622,7 +1625,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
                               unsigned int shndx, Address address)
   {
     this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
-                                    false, true));
+                                    false, true, false));
   }
 
   // Add a reloc against a local symbol.
@@ -1825,7 +1828,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
             Address address, Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, od, address, addend,
-                                    false, false)); }
+                                    false, false, false)); }
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
@@ -1833,7 +1836,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
             unsigned int shndx, Address address,
             Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
-                                    addend, false, false)); }
+                                    addend, false, false, false)); }
 
   void
   add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
@@ -1842,7 +1845,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
     this->add(od, Output_reloc_type(gsym, type, od,
                                    convert_types<Address, uint64_t>(address),
                                    convert_types<Addend, uint64_t>(addend),
-                                   false, false));
+                                   false, false, false));
   }
 
   void
@@ -1855,7 +1858,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
     this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx,
                                    convert_types<Address, uint64_t>(address),
                                    convert_types<Addend, uint64_t>(addend),
-                                   false, false));
+                                   false, false, false));
   }
 
   // Add a RELATIVE reloc against a global symbol.  The final output
@@ -1865,16 +1868,17 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
-                     Address address, Addend addend)
+                     Address address, Addend addend, bool use_plt_offset)
   { this->add(od, Output_reloc_type(gsym, type, od, address, addend, true,
-                                   true)); }
+                                   true, use_plt_offset)); }
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
                       Sized_relobj<size, big_endian>* relobj,
-                      unsigned int shndx, Address address, Addend addend)
+                      unsigned int shndx, Address address, Addend addend,
+                     bool use_plt_offset)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
-                                    addend, true, true)); }
+                                    addend, true, true, use_plt_offset)); }
 
   // Add a global relocation which does not use a symbol for the relocation,
   // but which gets its addend from a symbol.
@@ -1883,7 +1887,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   add_symbolless_global_addend(Symbol* gsym, unsigned int type, Output_data* od,
                               Address address, Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, od, address, addend,
-                                   false, true)); }
+                                   false, true, false)); }
 
   void
   add_symbolless_global_addend(Symbol* gsym, unsigned int type,
@@ -1891,7 +1895,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
                               Sized_relobj<size, big_endian>* relobj,
                               unsigned int shndx, Address address, Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
-                                    addend, false, true)); }
+                                    addend, false, true, false)); }
 
   // Add a reloc against a local symbol.
 
@@ -2151,20 +2155,42 @@ class Output_data_group : public Output_section_data
 // needed.  The GOT_SIZE template parameter is the size in bits of a
 // GOT entry, typically 32 or 64.
 
+class Output_data_got_base : public Output_section_data_build
+{
+ public:
+  Output_data_got_base(uint64_t align)
+    : Output_section_data_build(align)
+  { }
+
+  Output_data_got_base(off_t data_size, uint64_t align)
+    : Output_section_data_build(data_size, align)
+  { }
+
+  // Reserve the slot at index I in the GOT.
+  void
+  reserve_slot(unsigned int i)
+  { this->do_reserve_slot(i); }
+
+ protected:
+  // Reserve the slot at index I in the GOT.
+  virtual void
+  do_reserve_slot(unsigned int i) = 0;
+};
+
 template<int got_size, bool big_endian>
-class Output_data_got : public Output_section_data_build
+class Output_data_got : public Output_data_got_base
 {
  public:
   typedef typename elfcpp::Elf_types<got_size>::Elf_Addr Valtype;
 
   Output_data_got()
-    : Output_section_data_build(Output_data::default_alignment_for_size(got_size)),
+    : Output_data_got_base(Output_data::default_alignment_for_size(got_size)),
       entries_(), free_list_()
   { }
 
   Output_data_got(off_t data_size)
-    : Output_section_data_build(data_size,
-                               Output_data::default_alignment_for_size(got_size)),
+    : Output_data_got_base(data_size,
+                          Output_data::default_alignment_for_size(got_size)),
       entries_(), free_list_()
   {
     // For an incremental update, we have an existing GOT section.
@@ -2231,11 +2257,6 @@ class Output_data_got : public Output_section_data_build
     return got_offset;
   }
 
-  // Reserve a slot in the GOT.
-  void
-  reserve_slot(unsigned int i)
-  { this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); }
-
   // Reserve a slot in the GOT for a local symbol.
   void
   reserve_local(unsigned int i, Relobj* object, unsigned int sym_index,
@@ -2255,6 +2276,11 @@ class Output_data_got : public Output_section_data_build
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** GOT")); }
 
+  // Reserve the slot at index I in the GOT.
+  virtual void
+  do_reserve_slot(unsigned int i)
+  { this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); }
+
  private:
   // This POD class holds a single GOT entry.
   class Got_entry