[GOLD] PR22602, handle __tls_get_addr forwarders properly
authorAlan Modra <amodra@gmail.com>
Fri, 15 Dec 2017 04:29:58 +0000 (14:59 +1030)
committerAlan Modra <amodra@gmail.com>
Fri, 15 Dec 2017 04:39:15 +0000 (15:09 +1030)
We never need to resolve_forwards() a symbol found by hash table lookup
such as target->tls_get_addr_opt() but we do potentially need to do so
for random symbols seen on relocs.  So these calls were in the wrong
order, resulting in missing stubs and an assertion failure.

PR 22602
* powerpc.cc (Target_powerpc::Branch_info::mark_pltcall): Resolve
forwards before replacing __tls_get_addr.
(Target_powerpc::Branch_info::make_stub): Likewise.

gold/ChangeLog
gold/powerpc.cc

index bc0413dfcaa38e947d14bb094a944c23360a42ae..108631edc83a9aa9dde9e810f54ad31fa1c0cbbc 100644 (file)
@@ -1,3 +1,10 @@
+2017-12-15  Alan Modra  <amodra@gmail.com>
+
+       PR 22602
+       * powerpc.cc (Target_powerpc::Branch_info::mark_pltcall): Resolve
+       forwards before replacing __tls_get_addr.
+       (Target_powerpc::Branch_info::make_stub): Likewise.
+
 2017-12-11  Stephen Crane  <sjc@immunant.com>
 
        * plugin.cc (Plugin::load): Include hooks for register_new_input
index d52951984cdf6f68c289632057f58b897b7c7329..91353418c5091a95ba645fe9634d74aa409eb57e 100644 (file)
@@ -3102,10 +3102,10 @@ Target_powerpc<size, big_endian>::Branch_info::mark_pltcall(
     return false;
 
   Symbol* sym = this->object_->global_symbol(this->r_sym_);
-  if (target->replace_tls_get_addr(sym))
-    sym = target->tls_get_addr_opt();
   if (sym != NULL && sym->is_forwarder())
     sym = symtab->resolve_forwards(sym);
+  if (target->replace_tls_get_addr(sym))
+    sym = target->tls_get_addr_opt();
   const Sized_symbol<size>* gsym = static_cast<const Sized_symbol<size>*>(sym);
   if (gsym != NULL
       ? (gsym->use_plt_offset(Scan::get_reference_flags(this->r_type_, target))
@@ -3132,10 +3132,10 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
   Target_powerpc<size, big_endian>* target =
     static_cast<Target_powerpc<size, big_endian>*>(
       parameters->sized_target<size, big_endian>());
-  if (target->replace_tls_get_addr(sym))
-    sym = target->tls_get_addr_opt();
   if (sym != NULL && sym->is_forwarder())
     sym = symtab->resolve_forwards(sym);
+  if (target->replace_tls_get_addr(sym))
+    sym = target->tls_get_addr_opt();
   const Sized_symbol<size>* gsym = static_cast<const Sized_symbol<size>*>(sym);
   bool ok = true;
 
This page took 0.04617 seconds and 4 git commands to generate.