gold: Allow use_plt_offset to be specified for global relocations.
authorDavid S. Miller <davem@redhat.com>
Tue, 17 Apr 2012 01:50:39 +0000 (01:50 +0000)
committerDavid S. Miller <davem@redhat.com>
Tue, 17 Apr 2012 01:50:39 +0000 (01:50 +0000)
gold/

* output.h (Output_reloc): Allow use_plt_offset for global relocs too.
(class Output_data_reloc): Adjust calls to Output_reloc_type.
(Output_data_reloc::add_global_relative): (RELA only) Add use_plt_offset.
* output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag for
global relocs too.
(Output_reloc::symbol_value): Respect use_plt_offset_ for global symbols.
* powerpc.cc (Target_powerpc::Scan::global): Adjust add_global_relative
calls.
* sparc.cc (Target_sparc::Scan::global): Likewise.
* x86_64.cc (Target_x86_64::Scan::global): Likewise.

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

index 471db35..b88577a 100644 (file)
@@ -1,3 +1,16 @@
+2012-04-16  David S. Miller  <davem@davemloft.net>
+
+       * output.h (Output_reloc): Allow use_plt_offset for global relocs too.
+       (class Output_data_reloc): Adjust calls to Output_reloc_type.
+       (Output_data_reloc::add_global_relative): (RELA only) Add use_plt_offset.
+       * output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag for
+       global relocs too.
+       (Output_reloc::symbol_value): Respect use_plt_offset_ for global symbols.
+       * powerpc.cc (Target_powerpc::Scan::global): Adjust add_global_relative
+       calls.
+       * sparc.cc (Target_sparc::Scan::global): Likewise.
+       * x86_64.cc (Target_x86_64::Scan::global): Likewise.
+
 2012-04-16  Cary Coutant  <ccoutant@google.com>
 
        * archive.cc (Library_base::should_include_member): Check for
index ca19039..2236916 100644 (file)
@@ -705,10 +705,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_data* od,
     Address address,
     bool is_relative,
-    bool is_symbolless)
+    bool is_symbolless,
+    bool use_plt_offset)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
+    is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -726,10 +727,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int shndx,
     Address address,
     bool is_relative,
-    bool is_symbolless)
+    bool is_symbolless,
+    bool use_plt_offset)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
+    is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -1116,7 +1118,14 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
     {
       const Sized_symbol<size>* sym;
       sym = static_cast<const Sized_symbol<size>*>(this->u1_.gsym);
-      return sym->value() + addend;
+      if (this->use_plt_offset_ && sym->has_plt_offset())
+       {
+         uint64_t plt_address =
+           parameters->target().plt_address_for_global(sym);
+         return plt_address + sym->plt_offset();
+       }
+      else
+       return sym->value() + addend;
     }
   gold_assert(this->local_sym_index_ != SECTION_CODE
              && this->local_sym_index_ != TARGET_CODE
index 838ca3d..3796e91 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.
 
index 372443f..b443304 100644 (file)
@@ -1486,7 +1486,7 @@ Target_powerpc<size, big_endian>::Scan::global(
                 rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE,
                                              output_section, object,
                                              data_shndx, reloc.get_r_offset(),
-                                             reloc.get_r_addend());
+                                             reloc.get_r_addend(), false);
               }
             else
               {
@@ -1505,7 +1505,7 @@ Target_powerpc<size, big_endian>::Scan::global(
                                                output_section, object,
                                                data_shndx,
                                                reloc.get_r_offset(),
-                                               reloc.get_r_addend());
+                                               reloc.get_r_addend(), false);
               }
           }
       }
@@ -1574,7 +1574,7 @@ Target_powerpc<size, big_endian>::Scan::global(
 
                gsym->set_got_offset(GOT_TYPE_STANDARD, off);
                rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE,
-                                             got, off, 0);
+                                             got, off, 0, false);
              }
           }
       }
index ee82367..e1bdc8e 100644 (file)
@@ -2333,7 +2333,7 @@ Target_sparc<size, big_endian>::Scan::global(
                 rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
                                              output_section, object,
                                              data_shndx, reloc.get_r_offset(),
-                                             reloc.get_r_addend());
+                                             reloc.get_r_addend(), false);
               }
             else
               {
@@ -2387,7 +2387,7 @@ Target_sparc<size, big_endian>::Scan::global(
 
                gsym->set_got_offset(GOT_TYPE_STANDARD, off);
                rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
-                                             got, off, 0);
+                                             got, off, 0, false);
              }
           }
       }
index 3962e1e..d67924b 100644 (file)
@@ -1667,24 +1667,24 @@ Target_x86_64<size>::reserve_global_got_entry(unsigned int got_index,
                                 this->got_, got_offset, 0);
          else
            rela_dyn->add_global_relative(gsym, 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_global_relative(gsym, elfcpp::R_X86_64_TPOFF64,
-                                   this->got_, got_offset, 0);
+                                   this->got_, got_offset, 0, false);
       break;
     case GOT_TYPE_TLS_PAIR:
       this->got_->reserve_slot(got_index + 1);
       rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_DTPMOD64,
-                                   this->got_, got_offset, 0);
+                                   this->got_, got_offset, 0, false);
       rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_DTPOFF64,
-                                   this->got_, got_offset + 8, 0);
+                                   this->got_, got_offset + 8, 0, false);
       break;
     case GOT_TYPE_TLS_DESC:
       this->got_->reserve_slot(got_index + 1);
       rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_TLSDESC,
-                                   this->got_, got_offset, 0);
+                                   this->got_, got_offset, 0, false);
       break;
     default:
       gold_unreachable();
@@ -2505,7 +2505,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
                                              output_section, object,
                                              data_shndx,
                                              reloc.get_r_offset(),
-                                             reloc.get_r_addend());
+                                             reloc.get_r_addend(), false);
               }
             else
               {
@@ -2612,7 +2612,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
                    unsigned int got_off = gsym->got_offset(GOT_TYPE_STANDARD);
                    rela_dyn->add_global_relative(gsym,
                                                  elfcpp::R_X86_64_RELATIVE,
-                                                 got, got_off, 0);
+                                                 got, got_off, 0, false);
                  }
               }
           }