[GOLD] PowerPC64 support for sym+addend GOT entries
authorAlan Modra <amodra@gmail.com>
Thu, 26 Aug 2021 02:47:51 +0000 (12:17 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 17 Sep 2021 22:50:11 +0000 (08:20 +0930)
Pass addends to all the GOT handling functions, plus remove some
extraneous asserts.

PR 28192
* powerpc.cc (Output_data_got_powerpc): Add addend parameter to
all methods creating got entries.
(Target_powerpc::Scan::local): Pass reloc addend to got handling
functions, and when creating dynamic got relocations.
(Target_powerpc::Scan::global): Likewise.
(Target_powerpc::Relocate::relocate): Likewise.  Remove extraneous
assertions.

gold/powerpc.cc

index 0b6405915c2ee6872134831b241e3fb1ea854c16..0cee975f8bd573abe532fd513106ee73480606f3 100644 (file)
@@ -2970,77 +2970,85 @@ public:
   // Override all the Output_data_got methods we use so as to first call
   // reserve_ent().
   bool
-  add_global(Symbol* gsym, unsigned int got_type)
+  add_global(Symbol* gsym, unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
-    return Output_data_got<size, big_endian>::add_global(gsym, got_type);
+    return Output_data_got<size, big_endian>::add_global(gsym, got_type,
+                                                        addend);
   }
 
   bool
-  add_global_plt(Symbol* gsym, unsigned int got_type)
+  add_global_plt(Symbol* gsym, unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
-    return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type);
+    return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type,
+                                                            addend);
   }
 
   bool
-  add_global_tls(Symbol* gsym, unsigned int got_type)
-  { return this->add_global_plt(gsym, got_type); }
+  add_global_tls(Symbol* gsym, unsigned int got_type, uint64_t addend)
+  { return this->add_global_plt(gsym, got_type, addend); }
 
   void
   add_global_with_rel(Symbol* gsym, unsigned int got_type,
-                     Output_data_reloc_generic* rel_dyn, unsigned int r_type)
+                     Output_data_reloc_generic* rel_dyn,
+                     unsigned int r_type, uint64_t addend)
   {
     this->reserve_ent();
     Output_data_got<size, big_endian>::
-      add_global_with_rel(gsym, got_type, rel_dyn, r_type);
+      add_global_with_rel(gsym, got_type, rel_dyn, r_type, addend);
   }
 
   void
   add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
                           Output_data_reloc_generic* rel_dyn,
-                          unsigned int r_type_1, unsigned int r_type_2)
+                          unsigned int r_type_1, unsigned int r_type_2,
+                          uint64_t addend)
   {
     if (gsym->has_got_offset(got_type))
       return;
 
     this->reserve_ent(2);
     Output_data_got<size, big_endian>::
-      add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2);
+      add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2,
+                              addend);
   }
 
   bool
-  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type,
+           uint64_t addend)
   {
     this->reserve_ent();
     return Output_data_got<size, big_endian>::add_local(object, sym_index,
-                                                       got_type);
+                                                       got_type, addend);
   }
 
   bool
-  add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  add_local_plt(Relobj* object, unsigned int sym_index,
+               unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
     return Output_data_got<size, big_endian>::add_local_plt(object, sym_index,
-                                                           got_type);
+                                                           got_type, addend);
   }
 
   bool
-  add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type)
-  { return this->add_local_plt(object, sym_index, got_type); }
+  add_local_tls(Relobj* object, unsigned int sym_index,
+               unsigned int got_type, uint64_t addend)
+  { return this->add_local_plt(object, sym_index, got_type, addend); }
 
   void
   add_local_tls_pair(Relobj* object, unsigned int sym_index,
                     unsigned int got_type,
                     Output_data_reloc_generic* rel_dyn,
-                    unsigned int r_type)
+                    unsigned int r_type, uint64_t addend)
   {
-    if (object->local_has_got_offset(sym_index, got_type))
+    if (object->local_has_got_offset(sym_index, got_type, addend))
       return;
 
     this->reserve_ent(2);
     Output_data_got<size, big_endian>::
-      add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type);
+      add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type, addend);
   }
 
   unsigned int
@@ -8195,29 +8203,30 @@ Target_powerpc<size, big_endian>::Scan::local(
        Output_data_got_powerpc<size, big_endian>* got
          = target->got_section(symtab, layout);
        unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+       uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 
        if (!parameters->options().output_is_position_independent())
          {
            if (is_ifunc
                && (size == 32 || target->abiversion() >= 2))
-             got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
+             got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD, addend);
            else
-             got->add_local(object, r_sym, GOT_TYPE_STANDARD);
+             got->add_local(object, r_sym, GOT_TYPE_STANDARD, addend);
          }
-       else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD))
+       else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD, addend))
          {
            // If we are generating a shared object or a pie, this
            // symbol's GOT entry will be set by a dynamic relocation.
            unsigned int off;
            off = got->add_constant(0);
-           object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
+           object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off, addend);
 
            Reloc_section* rela_dyn = target->rela_dyn_section(symtab, layout,
                                                               is_ifunc);
            unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE
                                   : elfcpp::R_POWERPC_RELATIVE);
            rela_dyn->add_local_relative(object, r_sym, dynrel,
-                                        got, off, 0, false);
+                                        got, off, addend, false);
          }
       }
       break;
@@ -8246,9 +8255,11 @@ Target_powerpc<size, big_endian>::Scan::local(
            Output_data_got_powerpc<size, big_endian>* got
              = target->got_section(symtab, layout);
            unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+           uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
            Reloc_section* rela_dyn = target->rela_dyn_section(layout);
            got->add_local_tls_pair(object, r_sym, GOT_TYPE_TLSGD,
-                                   rela_dyn, elfcpp::R_POWERPC_DTPMOD);
+                                   rela_dyn, elfcpp::R_POWERPC_DTPMOD,
+                                   addend);
          }
        else if (tls_type == tls::TLSOPT_TO_LE)
          {
@@ -8296,7 +8307,8 @@ Target_powerpc<size, big_endian>::Scan::local(
        Output_data_got_powerpc<size, big_endian>* got
          = target->got_section(symtab, layout);
        unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-       got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL);
+       uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
+       got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL, addend);
       }
       break;
 
@@ -8310,17 +8322,18 @@ Target_powerpc<size, big_endian>::Scan::local(
        if (tls_type == tls::TLSOPT_NONE)
          {
            unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-           if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL))
+           uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
+           if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL, addend))
              {
                Output_data_got_powerpc<size, big_endian>* got
                  = target->got_section(symtab, layout);
                unsigned int off = got->add_constant(0);
-               object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off);
+               object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off, addend);
 
                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
                rela_dyn->add_symbolless_local_addend(object, r_sym,
                                                      elfcpp::R_POWERPC_TPREL,
-                                                     got, off, 0);
+                                                     got, off, addend);
              }
          }
        else if (tls_type == tls::TLSOPT_TO_LE)
@@ -8980,22 +8993,23 @@ Target_powerpc<size, big_endian>::Scan::global(
       {
        // The symbol requires a GOT entry.
        Output_data_got_powerpc<size, big_endian>* got;
+       uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 
        got = target->got_section(symtab, layout);
        if (gsym->final_value_is_known())
          {
            if (is_ifunc
                && (size == 32 || target->abiversion() >= 2))
-             got->add_global_plt(gsym, GOT_TYPE_STANDARD);
+             got->add_global_plt(gsym, GOT_TYPE_STANDARD, addend);
            else
-             got->add_global(gsym, GOT_TYPE_STANDARD);
+             got->add_global(gsym, GOT_TYPE_STANDARD, addend);
          }
-       else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
+       else if (!gsym->has_got_offset(GOT_TYPE_STANDARD, addend))
          {
            // If we are generating a shared object or a pie, this
            // symbol's GOT entry will be set by a dynamic relocation.
            unsigned int off = got->add_constant(0);
-           gsym->set_got_offset(GOT_TYPE_STANDARD, off);
+           gsym->set_got_offset(GOT_TYPE_STANDARD, off, addend);
 
            Reloc_section* rela_dyn
              = target->rela_dyn_section(symtab, layout, is_ifunc);
@@ -9008,12 +9022,13 @@ Target_powerpc<size, big_endian>::Scan::global(
              {
                unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE
                                       : elfcpp::R_POWERPC_RELATIVE);
-               rela_dyn->add_global_relative(gsym, dynrel, got, off, 0, false);
+               rela_dyn->add_global_relative(gsym, dynrel, got, off,
+                                             addend, false);
              }
            else
              {
                unsigned int dynrel = elfcpp::R_POWERPC_GLOB_DAT;
-               rela_dyn->add_global(gsym, dynrel, got, off, 0);
+               rela_dyn->add_global(gsym, dynrel, got, off, addend);
              }
          }
       }
@@ -9046,9 +9061,11 @@ Target_powerpc<size, big_endian>::Scan::global(
            Output_data_got_powerpc<size, big_endian>* got
              = target->got_section(symtab, layout);
            Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+           uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
            got->add_global_pair_with_rel(gsym, GOT_TYPE_TLSGD, rela_dyn,
                                          elfcpp::R_POWERPC_DTPMOD,
-                                         elfcpp::R_POWERPC_DTPREL);
+                                         elfcpp::R_POWERPC_DTPREL,
+                                         addend);
          }
        else if (tls_type == tls::TLSOPT_TO_IE)
          {
@@ -9057,11 +9074,12 @@ Target_powerpc<size, big_endian>::Scan::global(
                Output_data_got_powerpc<size, big_endian>* got
                  = target->got_section(symtab, layout);
                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+               uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
                if (gsym->is_undefined()
                    || gsym->is_from_dynobj())
                  {
                    got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn,
-                                            elfcpp::R_POWERPC_TPREL);
+                                            elfcpp::R_POWERPC_TPREL, addend);
                  }
                else
                  {
@@ -9069,7 +9087,7 @@ Target_powerpc<size, big_endian>::Scan::global(
                    gsym->set_got_offset(GOT_TYPE_TPREL, off);
                    unsigned int dynrel = elfcpp::R_POWERPC_TPREL;
                    rela_dyn->add_symbolless_global_addend(gsym, dynrel,
-                                                          got, off, 0);
+                                                          got, off, addend);
                  }
              }
            ppc_object->set_tls_marker();
@@ -9119,15 +9137,16 @@ Target_powerpc<size, big_endian>::Scan::global(
       {
        Output_data_got_powerpc<size, big_endian>* got
          = target->got_section(symtab, layout);
+       uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
        if (!gsym->final_value_is_known()
            && (gsym->is_from_dynobj()
                || gsym->is_undefined()
                || gsym->is_preemptible()))
          got->add_global_with_rel(gsym, GOT_TYPE_DTPREL,
                                   target->rela_dyn_section(layout),
-                                  elfcpp::R_POWERPC_DTPREL);
+                                  elfcpp::R_POWERPC_DTPREL, addend);
        else
-         got->add_global_tls(gsym, GOT_TYPE_DTPREL);
+         got->add_global_tls(gsym, GOT_TYPE_DTPREL, addend);
       }
       break;
 
@@ -9146,11 +9165,12 @@ Target_powerpc<size, big_endian>::Scan::global(
                Output_data_got_powerpc<size, big_endian>* got
                  = target->got_section(symtab, layout);
                Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+               uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
                if (gsym->is_undefined()
                    || gsym->is_from_dynobj())
                  {
                    got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn,
-                                            elfcpp::R_POWERPC_TPREL);
+                                            elfcpp::R_POWERPC_TPREL, addend);
                  }
                else
                  {
@@ -9158,7 +9178,7 @@ Target_powerpc<size, big_endian>::Scan::global(
                    gsym->set_got_offset(GOT_TYPE_TPREL, off);
                    unsigned int dynrel = elfcpp::R_POWERPC_TPREL;
                    rela_dyn->add_symbolless_global_addend(gsym, dynrel,
-                                                          got, off, 0);
+                                                          got, off, addend);
                  }
              }
          }
@@ -10655,16 +10675,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     }
   else if (is_got_reloc(r_type))
     {
+      uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
       if (gsym != NULL)
-       {
-         gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
-         value = gsym->got_offset(GOT_TYPE_STANDARD);
-       }
+       value = gsym->got_offset(GOT_TYPE_STANDARD, addend);
       else
-       {
-         gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
-         value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
-       }
+       value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD, addend);
       if (r_type == elfcpp::R_PPC64_GOT_PCREL34)
        value += target->got_section()->address();
       else
@@ -10764,16 +10779,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
        got_type = GOT_TYPE_TPREL;
       if (got_type != GOT_TYPE_STANDARD)
        {
+         uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
          if (gsym != NULL)
-           {
-             gold_assert(gsym->has_got_offset(got_type));
-             value = gsym->got_offset(got_type);
-           }
+           value = gsym->got_offset(got_type, addend);
          else
-           {
-             gold_assert(object->local_has_got_offset(r_sym, got_type));
-             value = object->local_got_offset(r_sym, got_type);
-           }
+           value = object->local_got_offset(r_sym, got_type, addend);
          if (r_type == elfcpp::R_PPC64_GOT_TLSGD_PCREL34)
            value += target->got_section()->address();
          else
@@ -10920,16 +10930,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     {
       // Accesses relative to a local dynamic sequence address,
       // no optimisation here.
+      uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
       if (gsym != NULL)
-       {
-         gold_assert(gsym->has_got_offset(GOT_TYPE_DTPREL));
-         value = gsym->got_offset(GOT_TYPE_DTPREL);
-       }
+       value = gsym->got_offset(GOT_TYPE_DTPREL, addend);
       else
-       {
-         gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_DTPREL));
-         value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL);
-       }
+       value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL, addend);
       if (r_type == elfcpp::R_PPC64_GOT_DTPREL_PCREL34)
        value += target->got_section()->address();
       else
@@ -10946,16 +10951,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
       if (tls_type == tls::TLSOPT_NONE)
        {
+         uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
          if (gsym != NULL)
-           {
-             gold_assert(gsym->has_got_offset(GOT_TYPE_TPREL));
-             value = gsym->got_offset(GOT_TYPE_TPREL);
-           }
+           value = gsym->got_offset(GOT_TYPE_TPREL, addend);
          else
-           {
-             gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_TPREL));
-             value = object->local_got_offset(r_sym, GOT_TYPE_TPREL);
-           }
+           value = object->local_got_offset(r_sym, GOT_TYPE_TPREL, addend);
          if (r_type == elfcpp::R_PPC64_GOT_TPREL_PCREL34)
            value += target->got_section()->address();
          else