PR gold/13249
authorCary Coutant <ccoutant@google.com>
Mon, 10 Oct 2011 17:29:52 +0000 (17:29 +0000)
committerCary Coutant <ccoutant@google.com>
Mon, 10 Oct 2011 17:29:52 +0000 (17:29 +0000)
* gold/output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag.
(Output_reloc::symbol_value): Return PLT offset if flag is set.
* gold/output.h (class Output_reloc): Add use_plt_offset flag.
(Output_reloc::type_): Adjust size of bit field.
(Output_reloc::use_plt_offset_): New bit field.
(class Output_data_reloc): Adjust all calls to Output_reloc_type.
(Output_data_reloc::add_local_relative): (RELA only) Add use_plt_offset
flag.  Adjust all callers.
* gold/x86_64.cc (Target_x86_64::Scan::local): Check for IFUNC when
creating RELATIVE relocations.

gold/ChangeLog
gold/output.cc
gold/output.h
gold/powerpc.cc
gold/sparc.cc
gold/x86_64.cc

index 5e0a3352c7f80effc0dbb5766cb798b7c9d8817e..318e5156d28f054ef870fc6a133a978b27f28fb7 100644 (file)
@@ -1,3 +1,17 @@
+2011-10-10  Cary Coutant  <ccoutant@google.com>
+
+       PR gold/13249
+       * gold/output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag.
+       (Output_reloc::symbol_value): Return PLT offset if flag is set.
+       * gold/output.h (class Output_reloc): Add use_plt_offset flag.
+       (Output_reloc::type_): Adjust size of bit field.
+       (Output_reloc::use_plt_offset_): New bit field.
+       (class Output_data_reloc): Adjust all calls to Output_reloc_type.
+       (Output_data_reloc::add_local_relative): (RELA only) Add use_plt_offset
+       flag.  Adjust all callers.
+       * gold/x86_64.cc (Target_x86_64::Scan::local): Check for IFUNC when
+       creating RELATIVE relocations.
+
 2011-10-10  Nick Clifton  <nickc@redhat.com>
 
        * po/es.po: Updated Spanish translation.
index 63f01090c89000022e06f2fc364993f96828ff95..d6bdabacbc5a0e2c4a4b34693f6d884c914f00d1 100644 (file)
@@ -706,7 +706,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     bool is_symbolless)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -727,7 +727,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     bool is_symbolless)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(false), shndx_(shndx)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -749,10 +749,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address,
     bool is_relative,
     bool is_symbolless,
-    bool is_section_symbol)
+    bool is_section_symbol,
+    bool use_plt_offset)
   : address_(address), local_sym_index_(local_sym_index), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(is_section_symbol), shndx_(INVALID_CODE)
+    is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset),
+    shndx_(INVALID_CODE)
 {
   gold_assert(local_sym_index != GSYM_CODE
               && local_sym_index != INVALID_CODE);
@@ -773,10 +775,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address,
     bool is_relative,
     bool is_symbolless,
-    bool is_section_symbol)
+    bool is_section_symbol,
+    bool use_plt_offset)
   : address_(address), local_sym_index_(local_sym_index), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(is_section_symbol), shndx_(shndx)
+    is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset),
+    shndx_(shndx)
 {
   gold_assert(local_sym_index != GSYM_CODE
               && local_sym_index != INVALID_CODE);
@@ -799,7 +803,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(true), shndx_(INVALID_CODE)
+    is_section_symbol_(true), use_plt_offset_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -820,7 +824,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(true), shndx_(shndx)
+    is_section_symbol_(true), use_plt_offset_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -842,7 +846,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(0), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -858,7 +862,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(0), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(false), shndx_(shndx)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -877,7 +881,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(TARGET_CODE), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -894,7 +898,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(TARGET_CODE), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(false), shndx_(shndx)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -1121,6 +1125,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
   Sized_relobj_file<size, big_endian>* relobj =
       this->u1_.relobj->sized_relobj();
   gold_assert(relobj != NULL);
+  if (this->use_plt_offset_)
+    {
+      uint64_t plt_address =
+         parameters->target().plt_address_for_local(relobj, lsi);
+      return plt_address + relobj->local_plt_offset(lsi);
+    }
   const Symbol_value<size>* symval = relobj->local_symbol(lsi);
   return symval->value(relobj, addend);
 }
index cabec5c8d376ea9506e50e9de6c40a516ca68b79..e704213b0cb2ee20bdb37c0a4038161acd443430 100644 (file)
@@ -1033,12 +1033,14 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   Output_reloc(Sized_relobj<size, big_endian>* relobj,
               unsigned int local_sym_index, unsigned int type,
               Output_data* od, Address address, bool is_relative,
-               bool is_symbolless, bool is_section_symbol);
+               bool is_symbolless, bool is_section_symbol,
+               bool use_plt_offset);
 
   Output_reloc(Sized_relobj<size, big_endian>* relobj,
               unsigned int local_sym_index, unsigned int type,
               unsigned int shndx, Address address, bool is_relative,
-               bool is_symbolless, bool is_section_symbol);
+               bool is_symbolless, bool is_section_symbol,
+               bool use_plt_offset);
 
   // A reloc against the STT_SECTION symbol of an output section.
 
@@ -1216,7 +1218,7 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // input file.
   unsigned int local_sym_index_;
   // The reloc type--a processor specific code.
-  unsigned int type_ : 29;
+  unsigned int type_ : 28;
   // True if the relocation is a RELATIVE relocation.
   bool is_relative_ : 1;
   // True if the relocation is one which should not use
@@ -1224,6 +1226,10 @@ 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.
+  // (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
   // section index.  This is INVALID_CODE if the reloc address is
   // specified in some other way.
@@ -1268,9 +1274,10 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
               unsigned int local_sym_index, unsigned int type,
               Output_data* od, Address address,
               Addend addend, bool is_relative,
-              bool is_symbolless, bool is_section_symbol)
+              bool is_symbolless, bool is_section_symbol,
+              bool use_plt_offset)
     : rel_(relobj, local_sym_index, type, od, address, is_relative,
-           is_symbolless, is_section_symbol),
+           is_symbolless, is_section_symbol, use_plt_offset),
       addend_(addend)
   { }
 
@@ -1278,9 +1285,10 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
               unsigned int local_sym_index, unsigned int type,
               unsigned int shndx, Address address,
               Addend addend, bool is_relative,
-              bool is_symbolless, bool is_section_symbol)
+              bool is_symbolless, bool is_section_symbol,
+              bool use_plt_offset)
     : rel_(relobj, local_sym_index, type, shndx, address, is_relative,
-           is_symbolless, is_section_symbol),
+           is_symbolless, is_section_symbol, use_plt_offset),
       addend_(addend)
   { }
 
@@ -1571,7 +1579,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
            Output_data* od, Address address)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
-                                    address, false, false, false));
+                                    address, false, false, false, false));
   }
 
   void
@@ -1580,7 +1588,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
            Output_data* od, unsigned int shndx, Address address)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                   address, false, false, false));
+                                   address, false, false, false, false));
   }
 
   // Add a RELATIVE reloc against a local symbol.
@@ -1591,7 +1599,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
                     Output_data* od, Address address)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
-                                    address, true, true, false));
+                                    address, true, true, false, false));
   }
 
   void
@@ -1600,7 +1608,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
                     Output_data* od, unsigned int shndx, Address address)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                   address, true, true, false));
+                                   address, true, true, false, false));
   }
 
   // Add a local relocation which does not use a symbol for the relocation,
@@ -1612,7 +1620,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
                              Output_data* od, Address address)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
-                                    address, false, true, false));
+                                    address, false, true, false, false));
   }
 
   void
@@ -1622,7 +1630,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
                              Address address)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                   address, false, true, false));
+                                   address, false, true, false, false));
   }
 
   // Add a reloc against a local section symbol.  This will be
@@ -1635,7 +1643,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
                     Output_data* od, Address address)
   {
     this->add(od, Output_reloc_type(relobj, input_shndx, type, od,
-                                    address, false, false, true));
+                                    address, false, false, true, false));
   }
 
   void
@@ -1644,7 +1652,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
                     Output_data* od, unsigned int shndx, Address address)
   {
     this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx,
-                                    address, false, false, true));
+                                    address, false, false, true, false));
   }
 
   // A reloc against the STT_SECTION symbol of an output section.
@@ -1767,7 +1775,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
            Output_data* od, Address address, Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
-                                   addend, false, false, false));
+                                   addend, false, false, false, false));
   }
 
   void
@@ -1777,7 +1785,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
            Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                    address, addend, false, false, false));
+                                    address, addend, false, false, false,
+                                    false));
   }
 
   // Add a RELATIVE reloc against a local symbol.
@@ -1785,20 +1794,23 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   void
   add_local_relative(Sized_relobj<size, big_endian>* relobj,
                     unsigned int local_sym_index, unsigned int type,
-                    Output_data* od, Address address, Addend addend)
+                    Output_data* od, Address address, Addend addend,
+                    bool use_plt_offset)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
-                                   addend, true, true, false));
+                                   addend, true, true, false,
+                                   use_plt_offset));
   }
 
   void
   add_local_relative(Sized_relobj<size, big_endian>* relobj,
                     unsigned int local_sym_index, unsigned int type,
                     Output_data* od, unsigned int shndx, Address address,
-                    Addend addend)
+                    Addend addend, bool use_plt_offset)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                    address, addend, true, true, false));
+                                    address, addend, true, true, false,
+                                    use_plt_offset));
   }
 
   // Add a local relocation which does not use a symbol for the relocation,
@@ -1810,7 +1822,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
                              Output_data* od, Address address, Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
-                                   addend, false, true, false));
+                                   addend, false, true, false, false));
   }
 
   void
@@ -1820,7 +1832,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
                              Address address, Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                    address, addend, false, true, false));
+                                    address, addend, false, true, false,
+                                    false));
   }
 
   // Add a reloc against a local section symbol.  This will be
@@ -1833,7 +1846,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
                     Output_data* od, Address address, Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, input_shndx, type, od, address,
-                                   addend, false, false, true));
+                                   addend, false, false, true, false));
   }
 
   void
@@ -1843,7 +1856,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
                    Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx,
-                                    address, addend, false, false, true));
+                                    address, addend, false, false, true,
+                                    false));
   }
 
   // A reloc against the STT_SECTION symbol of an output section.
index 45783c3933f81589c1041b384c6da87151e1a187..62a17ca7ac63467beee1e2c3f0d074d0622e4971 100644 (file)
@@ -1329,7 +1329,7 @@ Target_powerpc<size, big_endian>::Scan::local(
               rela_dyn->add_local_relative(object, r_sym, r_type,
                                           output_section, data_shndx,
                                           reloc.get_r_offset(),
-                                          reloc.get_r_addend());
+                                          reloc.get_r_addend(), false);
             }
         }
       break;
@@ -1372,7 +1372,7 @@ Target_powerpc<size, big_endian>::Scan::local(
                object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
                rela_dyn->add_local_relative(object, r_sym,
                                             elfcpp::R_POWERPC_RELATIVE,
-                                            got, off, 0);
+                                            got, off, 0, false);
              }
           }
        else
index 9145fcb0ead0880e4828b178aef100b19bba1e8e..1d2cbad319d156289d50c661aa66333d163dd6b6 100644 (file)
@@ -1852,7 +1852,7 @@ Target_sparc<size, big_endian>::Scan::local(
           rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE,
                                       output_section, data_shndx,
                                       reloc.get_r_offset(),
-                                      reloc.get_r_addend());
+                                      reloc.get_r_addend(), false);
         }
       break;
 
@@ -1943,7 +1943,7 @@ Target_sparc<size, big_endian>::Scan::local(
                object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
                rela_dyn->add_local_relative(object, r_sym,
                                             elfcpp::R_SPARC_RELATIVE,
-                                            got, off, 0);
+                                            got, off, 0, false);
              }
          }
        else
index e6b00210762f3effb40adda27e070c9326daa448..e61d7d1bf590f8e30ea8ff07f1427a173a10bfc7 100644 (file)
@@ -1549,7 +1549,7 @@ Target_x86_64::reserve_local_got_entry(
     case GOT_TYPE_STANDARD:
       if (parameters->options().output_is_position_independent())
        rela_dyn->add_local_relative(obj, r_sym, elfcpp::R_X86_64_RELATIVE,
-                                    this->got_, got_offset, 0);
+                                    this->got_, got_offset, 0, false);
       break;
     case GOT_TYPE_TLS_OFFSET:
       rela_dyn->add_local(obj, r_sym, elfcpp::R_X86_64_TPOFF64,
@@ -1953,8 +1953,8 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
                            const elfcpp::Sym<64, false>& lsym)
 {
   // A local STT_GNU_IFUNC symbol may require a PLT entry.
-  if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC
-      && this->reloc_needs_plt_for_ifunc(object, r_type))
+  bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
+  if (is_ifunc && this->reloc_needs_plt_for_ifunc(object, r_type))
     {
       unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
       target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym);
@@ -1982,7 +1982,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
                                       elfcpp::R_X86_64_RELATIVE,
                                       output_section, data_shndx,
                                       reloc.get_r_offset(),
-                                      reloc.get_r_addend());
+                                      reloc.get_r_addend(), is_ifunc);
         }
       break;
 
@@ -2058,7 +2058,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
        // lets function pointers compare correctly with shared
        // libraries.  Otherwise we would need an IRELATIVE reloc.
        bool is_new;
-       if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC)
+       if (is_ifunc)
          is_new = got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
        else
          is_new = got->add_local(object, r_sym, GOT_TYPE_STANDARD);
@@ -2076,7 +2076,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
                      object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
                    rela_dyn->add_local_relative(object, r_sym,
                                                 elfcpp::R_X86_64_RELATIVE,
-                                                got, got_offset, 0);
+                                                got, got_offset, 0, is_ifunc);
                  }
                 else
                   {
This page took 0.03961 seconds and 4 git commands to generate.