4c1956
This is a partial backport of this commit with only the 'scope'
4c1956
refactoring required to have access to the outer scope value
4c1956
to use with RESOLVE_MAP to implement la_symbind for BIND_NOW.
4c1956
4c1956
We do not backport this entire patch because the nested function
4c1956
changes have significant impact on code generation and would
4c1956
require furhter backports to support and maintain.
4c1956
4c1956
commit 490e6c62aa31a8aa5c4a059f6e646ede121edf0a
4c1956
Author: Fangrui Song <maskray@google.com>
4c1956
Date:   Thu Oct 7 11:55:02 2021 -0700
4c1956
4c1956
    elf: Avoid nested functions in the loader [BZ #27220]
4c1956
    
4c1956
    dynamic-link.h is included more than once in some elf/ files (rtld.c,
4c1956
    dl-conflict.c, dl-reloc.c, dl-reloc-static-pie.c) and uses GCC nested
4c1956
    functions. This harms readability and the nested functions usage
4c1956
    is the biggest obstacle prevents Clang build (Clang doesn't support GCC
4c1956
    nested functions).
4c1956
    
4c1956
    The key idea for unnesting is to add extra parameters (struct link_map
4c1956
    *and struct r_scope_elm *[]) to RESOLVE_MAP,
4c1956
    ELF_MACHINE_BEFORE_RTLD_RELOC, ELF_DYNAMIC_RELOCATE, elf_machine_rel[a],
4c1956
    elf_machine_lazy_rel, and elf_machine_runtime_setup. (This is inspired
4c1956
    by Stan Shebs' ppc64/x86-64 implementation in the
4c1956
    google/grte/v5-2.27/master which uses mixed extra parameters and static
4c1956
    variables.)
4c1956
    
4c1956
    Future simplification:
4c1956
    * If mips elf_machine_runtime_setup no longer needs RESOLVE_GOTSYM,
4c1956
      elf_machine_runtime_setup can drop the `scope` parameter.
4c1956
    * If TLSDESC no longer need to be in elf_machine_lazy_rel,
4c1956
      elf_machine_lazy_rel can drop the `scope` parameter.
4c1956
    
4c1956
    Tested on aarch64, i386, x86-64, powerpc64le, powerpc64, powerpc32,
4c1956
    sparc64, sparcv9, s390x, s390, hppa, ia64, armhf, alpha, and mips64.
4c1956
    In addition, tested build-many-glibcs.py with {arc,csky,microblaze,nios2}-linux-gnu
4c1956
    and riscv64-linux-gnu-rv64imafdc-lp64d.
4c1956
    
4c1956
    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
4c1956
4c1956
diff --git a/elf/dl-conflict.c b/elf/dl-conflict.c
4c1956
index 70f14b04cd383048..31d87ac846427752 100644
4c1956
--- a/elf/dl-conflict.c
4c1956
+++ b/elf/dl-conflict.c
4c1956
@@ -40,7 +40,7 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
4c1956
        data.  */
4c1956
 
4c1956
     /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
4c1956
-#define RESOLVE_MAP(ref, version, flags) (*ref = NULL, NULL)
4c1956
+#define RESOLVE_MAP(map, scope, ref, version, flags) (*ref = NULL, NULL)
4c1956
 #define RESOLVE(ref, version, flags) (*ref = NULL, 0)
4c1956
 #define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \
4c1956
   do {									      \
4c1956
@@ -67,8 +67,8 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
4c1956
     GL(dl_num_cache_relocations) += conflictend - conflict;
4c1956
 
4c1956
     for (; conflict < conflictend; ++conflict)
4c1956
-      elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset,
4c1956
-			0);
4c1956
+      elf_machine_rela (l, NULL, conflict, NULL, NULL,
4c1956
+			(void *) conflict->r_offset, 0);
4c1956
   }
4c1956
 #endif
4c1956
 }
4c1956
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
4c1956
index ab1ce0eacced9d2b..1efbf515c3c1c16d 100644
4c1956
--- a/elf/dl-reloc-static-pie.c
4c1956
+++ b/elf/dl-reloc-static-pie.c
4c1956
@@ -30,7 +30,7 @@ _dl_relocate_static_pie (void)
4c1956
 
4c1956
 # define STATIC_PIE_BOOTSTRAP
4c1956
 # define BOOTSTRAP_MAP (main_map)
4c1956
-# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
4c1956
+# define RESOLVE_MAP(map, scope, sym, version, flags) BOOTSTRAP_MAP
4c1956
 # include "dynamic-link.h"
4c1956
 
4c1956
   /* Figure out the run-time load address of static PIE.  */
4c1956
@@ -46,7 +46,7 @@ _dl_relocate_static_pie (void)
4c1956
 
4c1956
   /* Relocate ourselves so we can do normal function calls and
4c1956
      data access using the global offset table.  */
4c1956
-  ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0);
4c1956
+  ELF_DYNAMIC_RELOCATE (main_map, NULL, 0, 0, 0);
4c1956
   main_map->l_relocated = 1;
4c1956
 
4c1956
   /* Initialize _r_debug.  */
4c1956
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
4c1956
index c6139b89d4ecddc8..19de5de067a5ef07 100644
4c1956
--- a/elf/dl-reloc.c
4c1956
+++ b/elf/dl-reloc.c
4c1956
@@ -250,7 +250,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
4c1956
     const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
4c1956
 
4c1956
     /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
4c1956
-#define RESOLVE_MAP(ref, version, r_type) \
4c1956
+#define RESOLVE_MAP(l, scope, ref, version, r_type) \
4c1956
     ((ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL			      \
4c1956
       && __glibc_likely (!dl_symbol_visibility_binds_local_p (*ref)))	      \
4c1956
      ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0)		      \
4c1956
@@ -275,7 +275,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
4c1956
 
4c1956
 #include "dynamic-link.h"
4c1956
 
4c1956
-    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
4c1956
+    ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
4c1956
 
4c1956
 #ifndef PROF
4c1956
     if (__glibc_unlikely (consider_profiling)
4c1956
diff --git a/elf/do-rel.h b/elf/do-rel.h
4c1956
index 19cb5d236ee30698..0b04d1a0bf28b9f4 100644
4c1956
--- a/elf/do-rel.h
4c1956
+++ b/elf/do-rel.h
4c1956
@@ -38,7 +38,7 @@
4c1956
    than fully resolved now.  */
4c1956
 
4c1956
 auto inline void __attribute__ ((always_inline))
4c1956
-elf_dynamic_do_Rel (struct link_map *map,
4c1956
+elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		    ElfW(Addr) reladdr, ElfW(Addr) relsize,
4c1956
 		    __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
4c1956
 		    int lazy, int skip_ifunc)
4c1956
@@ -68,13 +68,13 @@ elf_dynamic_do_Rel (struct link_map *map,
4c1956
 	  }
4c1956
 	else
4c1956
 # endif
4c1956
-	  elf_machine_lazy_rel (map, l_addr, r, skip_ifunc);
4c1956
+	  elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc);
4c1956
 
4c1956
 # ifdef ELF_MACHINE_IRELATIVE
4c1956
       if (r2 != NULL)
4c1956
 	for (; r2 <= end2; ++r2)
4c1956
 	  if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
4c1956
-	    elf_machine_lazy_rel (map, l_addr, r2, skip_ifunc);
4c1956
+	    elf_machine_lazy_rel (map, scope, l_addr, r2, skip_ifunc);
4c1956
 # endif
4c1956
     }
4c1956
   else
4c1956
@@ -134,7 +134,7 @@ elf_dynamic_do_Rel (struct link_map *map,
4c1956
 #endif
4c1956
 
4c1956
 	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
4c1956
-	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
4c1956
+	      elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)],
4c1956
 			       &map->l_versions[ndx],
4c1956
 			       (void *) (l_addr + r->r_offset), skip_ifunc);
4c1956
 	    }
4c1956
@@ -146,7 +146,7 @@ elf_dynamic_do_Rel (struct link_map *map,
4c1956
 		{
4c1956
 		  ElfW(Half) ndx
4c1956
 		    = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff;
4c1956
-		  elf_machine_rel (map, r2,
4c1956
+		  elf_machine_rel (map, scope, r2,
4c1956
 				   &symtab[ELFW(R_SYM) (r2->r_info)],
4c1956
 				   &map->l_versions[ndx],
4c1956
 				   (void *) (l_addr + r2->r_offset),
4c1956
@@ -167,14 +167,14 @@ elf_dynamic_do_Rel (struct link_map *map,
4c1956
 	      }
4c1956
 	    else
4c1956
 # endif
4c1956
-	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
4c1956
+	      elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
4c1956
 			       (void *) (l_addr + r->r_offset), skip_ifunc);
4c1956
 
4c1956
 # ifdef ELF_MACHINE_IRELATIVE
4c1956
 	  if (r2 != NULL)
4c1956
 	    for (; r2 <= end2; ++r2)
4c1956
 	      if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
4c1956
-		elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
4c1956
+		elf_machine_rel (map, scope, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
4c1956
 				 NULL, (void *) (l_addr + r2->r_offset),
4c1956
 				 skip_ifunc);
4c1956
 # endif
4c1956
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
4c1956
index 2fc3c91b7defe84e..357a2e3c6825e0fc 100644
4c1956
--- a/elf/dynamic-link.h
4c1956
+++ b/elf/dynamic-link.h
4c1956
@@ -60,8 +60,9 @@ int _dl_try_allocate_static_tls (struct link_map *map, bool optional)
4c1956
    unaligned cases.  */
4c1956
 # if ! ELF_MACHINE_NO_REL
4c1956
 auto inline void __attribute__((always_inline))
4c1956
-elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
4c1956
-		 const ElfW(Sym) *sym, const struct r_found_version *version,
4c1956
+elf_machine_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
+		 const ElfW(Rel) *reloc, const ElfW(Sym) *sym,
4c1956
+		 const struct r_found_version *version,
4c1956
 		 void *const reloc_addr, int skip_ifunc);
4c1956
 auto inline void __attribute__((always_inline))
4c1956
 elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
4c1956
@@ -69,8 +70,9 @@ elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
4c1956
 # endif
4c1956
 # if ! ELF_MACHINE_NO_RELA
4c1956
 auto inline void __attribute__((always_inline))
4c1956
-elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
4c1956
-		  const ElfW(Sym) *sym, const struct r_found_version *version,
4c1956
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
4c1956
+		  const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
4c1956
+		  const struct r_found_version *version,
4c1956
 		  void *const reloc_addr, int skip_ifunc);
4c1956
 auto inline void __attribute__((always_inline))
4c1956
 elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
4c1956
@@ -78,12 +80,12 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
4c1956
 # endif
4c1956
 # if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
4c1956
 auto inline void __attribute__((always_inline))
4c1956
-elf_machine_lazy_rel (struct link_map *map,
4c1956
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		      ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
4c1956
 		      int skip_ifunc);
4c1956
 # else
4c1956
 auto inline void __attribute__((always_inline))
4c1956
-elf_machine_lazy_rel (struct link_map *map,
4c1956
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		      ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
4c1956
 		      int skip_ifunc);
4c1956
 # endif
4c1956
@@ -114,7 +116,7 @@ elf_machine_lazy_rel (struct link_map *map,
4c1956
    consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
4c1956
    are completely separate and there is a gap between them.  */
4c1956
 
4c1956
-# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \
4c1956
+# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, test_rel) \
4c1956
   do {									      \
4c1956
     struct { ElfW(Addr) start, size;					      \
4c1956
 	     __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; }  \
4c1956
@@ -152,13 +154,13 @@ elf_machine_lazy_rel (struct link_map *map,
4c1956
       }									      \
4c1956
 									      \
4c1956
     if (ELF_DURING_STARTUP)						      \
4c1956
-      elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size,	      \
4c1956
+      elf_dynamic_do_##reloc ((map), scope, ranges[0].start, ranges[0].size,  \
4c1956
 			      ranges[0].nrelative, 0, skip_ifunc);	      \
4c1956
     else								      \
4c1956
       {									      \
4c1956
 	int ranges_index;						      \
4c1956
 	for (ranges_index = 0; ranges_index < 2; ++ranges_index)	      \
4c1956
-	  elf_dynamic_do_##reloc ((map),				      \
4c1956
+	  elf_dynamic_do_##reloc ((map), scope,				      \
4c1956
 				  ranges[ranges_index].start,		      \
4c1956
 				  ranges[ranges_index].size,		      \
4c1956
 				  ranges[ranges_index].nrelative,	      \
4c1956
@@ -175,29 +177,29 @@ elf_machine_lazy_rel (struct link_map *map,
4c1956
 
4c1956
 # if ! ELF_MACHINE_NO_REL
4c1956
 #  include "do-rel.h"
4c1956
-#  define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \
4c1956
-  _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, lazy, skip_ifunc, _ELF_CHECK_REL)
4c1956
+#  define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) \
4c1956
+  _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
4c1956
 # else
4c1956
-#  define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do.  */
4c1956
+#  define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) /* Nothing to do.  */
4c1956
 # endif
4c1956
 
4c1956
 # if ! ELF_MACHINE_NO_RELA
4c1956
 #  define DO_RELA
4c1956
 #  include "do-rel.h"
4c1956
-#  define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \
4c1956
-  _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, lazy, skip_ifunc, _ELF_CHECK_REL)
4c1956
+#  define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) \
4c1956
+  _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
4c1956
 # else
4c1956
-#  define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do.  */
4c1956
+#  define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do.  */
4c1956
 # endif
4c1956
 
4c1956
 /* This can't just be an inline function because GCC is too dumb
4c1956
    to inline functions containing inlines themselves.  */
4c1956
-# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc) \
4c1956
+# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \
4c1956
   do {									      \
4c1956
-    int edr_lazy = elf_machine_runtime_setup ((map), (lazy),		      \
4c1956
+    int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy),	      \
4c1956
 					      (consider_profile));	      \
4c1956
-    ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc);			      \
4c1956
-    ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc);			      \
4c1956
+    ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc);		      \
4c1956
+    ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc);		      \
4c1956
   } while (0)
4c1956
 
4c1956
 #endif
4c1956
diff --git a/elf/rtld.c b/elf/rtld.c
4c1956
index e107af4014d43777..f3836b8a78faaf27 100644
4c1956
--- a/elf/rtld.c
4c1956
+++ b/elf/rtld.c
4c1956
@@ -514,7 +514,7 @@ _dl_start (void *arg)
4c1956
      is trivial: always the map of ld.so itself.  */
4c1956
 #define RTLD_BOOTSTRAP
4c1956
 #define BOOTSTRAP_MAP (&bootstrap_map)
4c1956
-#define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
4c1956
+#define RESOLVE_MAP(map, scope, sym, version, flags) BOOTSTRAP_MAP
4c1956
 #include "dynamic-link.h"
4c1956
 
4c1956
 #ifdef DONT_USE_BOOTSTRAP_MAP
4c1956
@@ -560,7 +560,7 @@ _dl_start (void *arg)
4c1956
       /* Relocate ourselves so we can do normal function calls and
4c1956
 	 data access using the global offset table.  */
4c1956
 
4c1956
-      ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0);
4c1956
+      ELF_DYNAMIC_RELOCATE (&bootstrap_map, NULL, 0, 0, 0);
4c1956
     }
4c1956
   bootstrap_map.l_relocated = 1;
4c1956
 
4c1956
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
4c1956
index 3fd3c8a265d012b1..5eab544afe2717f7 100644
4c1956
--- a/sysdeps/aarch64/dl-machine.h
4c1956
+++ b/sysdeps/aarch64/dl-machine.h
4c1956
@@ -65,7 +65,8 @@ elf_machine_load_address (void)
4c1956
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
4c1956
 
4c1956
 static inline int __attribute__ ((unused))
4c1956
-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
4c1956
+elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
4c1956
+			   int lazy, int profile)
4c1956
 {
4c1956
   if (l->l_info[DT_JMPREL] && lazy)
4c1956
     {
4c1956
@@ -242,8 +243,9 @@ elf_machine_plt_value (struct link_map *map,
4c1956
 
4c1956
 auto inline void
4c1956
 __attribute__ ((always_inline))
4c1956
-elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
4c1956
-		  const ElfW(Sym) *sym, const struct r_found_version *version,
4c1956
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
4c1956
+		  const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
4c1956
+		  const struct r_found_version *version,
4c1956
 		  void *const reloc_addr_arg, int skip_ifunc)
4c1956
 {
4c1956
   ElfW(Addr) *const reloc_addr = reloc_addr_arg;
4c1956
@@ -256,7 +258,8 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
4c1956
   else
4c1956
     {
4c1956
       const ElfW(Sym) *const refsym = sym;
4c1956
-      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
4c1956
+      struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
4c1956
+					      r_type);
4c1956
       ElfW(Addr) value = SYMBOL_ADDRESS (sym_map, sym, true);
4c1956
 
4c1956
       if (sym != NULL
4c1956
@@ -381,7 +384,7 @@ elf_machine_rela_relative (ElfW(Addr) l_addr,
4c1956
 
4c1956
 inline void
4c1956
 __attribute__ ((always_inline))
4c1956
-elf_machine_lazy_rel (struct link_map *map,
4c1956
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		      ElfW(Addr) l_addr,
4c1956
 		      const ElfW(Rela) *reloc,
4c1956
 		      int skip_ifunc)
4c1956
@@ -408,7 +411,7 @@ elf_machine_lazy_rel (struct link_map *map,
4c1956
 		    (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
4c1956
 		  version = &map->l_versions[vernum[symndx] & 0x7fff];
4c1956
 		}
4c1956
-	      elf_machine_rela (map, reloc, sym, version, reloc_addr,
4c1956
+	      elf_machine_rela (map, scope, reloc, sym, version, reloc_addr,
4c1956
 				skip_ifunc);
4c1956
 	      return;
4c1956
 	    }
4c1956
@@ -435,7 +438,7 @@ elf_machine_lazy_rel (struct link_map *map,
4c1956
 
4c1956
       /* Always initialize TLS descriptors completely, because lazy
4c1956
 	 initialization requires synchronization at every TLS access.  */
4c1956
-      elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
4c1956
+      elf_machine_rela (map, scope, reloc, sym, version, reloc_addr, skip_ifunc);
4c1956
     }
4c1956
   else if (__glibc_unlikely (r_type == AARCH64_R(IRELATIVE)))
4c1956
     {
4c1956
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
4c1956
index 3a30671591284d79..5ba95b9e4af49942 100644
4c1956
--- a/sysdeps/i386/dl-machine.h
4c1956
+++ b/sysdeps/i386/dl-machine.h
4c1956
@@ -61,7 +61,8 @@ elf_machine_load_address (void)
4c1956
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
4c1956
 
4c1956
 static inline int __attribute__ ((unused, always_inline))
4c1956
-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
4c1956
+elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
4c1956
+			   int lazy, int profile)
4c1956
 {
4c1956
   Elf32_Addr *got;
4c1956
   extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden;
4c1956
@@ -293,8 +294,9 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
4c1956
 
4c1956
 auto inline void
4c1956
 __attribute ((always_inline))
4c1956
-elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
4c1956
-		 const Elf32_Sym *sym, const struct r_found_version *version,
4c1956
+elf_machine_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
+		 const Elf32_Rel *reloc, const Elf32_Sym *sym,
4c1956
+		 const struct r_found_version *version,
4c1956
 		 void *const reloc_addr_arg, int skip_ifunc)
4c1956
 {
4c1956
   Elf32_Addr *const reloc_addr = reloc_addr_arg;
4c1956
@@ -327,7 +329,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
4c1956
 # ifndef RTLD_BOOTSTRAP
4c1956
       const Elf32_Sym *const refsym = sym;
4c1956
 # endif
4c1956
-      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
4c1956
+      struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
4c1956
+					      r_type);
4c1956
       Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
4c1956
 
4c1956
       if (sym != NULL
4c1956
@@ -493,8 +496,9 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
4c1956
 # ifndef RTLD_BOOTSTRAP
4c1956
 auto inline void
4c1956
 __attribute__ ((always_inline))
4c1956
-elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
4c1956
-		  const Elf32_Sym *sym, const struct r_found_version *version,
4c1956
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
4c1956
+		  const Elf32_Rela *reloc, const Elf32_Sym *sym,
4c1956
+		  const struct r_found_version *version,
4c1956
 		  void *const reloc_addr_arg, int skip_ifunc)
4c1956
 {
4c1956
   Elf32_Addr *const reloc_addr = reloc_addr_arg;
4c1956
@@ -507,7 +511,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
4c1956
 #  ifndef RESOLVE_CONFLICT_FIND_MAP
4c1956
       const Elf32_Sym *const refsym = sym;
4c1956
 #  endif
4c1956
-      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
4c1956
+      struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
4c1956
+					      r_type);
4c1956
       Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
4c1956
 
4c1956
       if (sym != NULL
4c1956
@@ -661,7 +666,7 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
4c1956
 
4c1956
 auto inline void
4c1956
 __attribute__ ((always_inline))
4c1956
-elf_machine_lazy_rel (struct link_map *map,
4c1956
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		      Elf32_Addr l_addr, const Elf32_Rel *reloc,
4c1956
 		      int skip_ifunc)
4c1956
 {
4c1956
@@ -696,13 +701,13 @@ elf_machine_lazy_rel (struct link_map *map,
4c1956
 	  const ElfW(Half) *const version =
4c1956
 	    (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
4c1956
 	  ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
4c1956
-	  elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
4c1956
+	  elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)],
4c1956
 			   &map->l_versions[ndx],
4c1956
 			   (void *) (l_addr + r->r_offset), skip_ifunc);
4c1956
 	}
4c1956
 # ifndef RTLD_BOOTSTRAP
4c1956
       else
4c1956
-	elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
4c1956
+	elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
4c1956
 			 (void *) (l_addr + r->r_offset), skip_ifunc);
4c1956
 # endif
4c1956
     }
4c1956
@@ -721,7 +726,7 @@ elf_machine_lazy_rel (struct link_map *map,
4c1956
 
4c1956
 auto inline void
4c1956
 __attribute__ ((always_inline))
4c1956
-elf_machine_lazy_rela (struct link_map *map,
4c1956
+elf_machine_lazy_rela (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		       Elf32_Addr l_addr, const Elf32_Rela *reloc,
4c1956
 		       int skip_ifunc)
4c1956
 {
4c1956
@@ -745,7 +750,8 @@ elf_machine_lazy_rela (struct link_map *map,
4c1956
 
4c1956
       /* Always initialize TLS descriptors completely at load time, in
4c1956
 	 case static TLS is allocated for it that requires locking.  */
4c1956
-      elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
4c1956
+      elf_machine_rela (map, scope, reloc, sym, version, reloc_addr,
4c1956
+			skip_ifunc);
4c1956
     }
4c1956
   else if (__glibc_unlikely (r_type == R_386_IRELATIVE))
4c1956
     {
4c1956
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
4c1956
index 99a83d0c82ea0a9c..35996bb9173da231 100644
4c1956
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
4c1956
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
4c1956
@@ -345,7 +345,8 @@ dl_platform_init (void)
4c1956
 /* Set up the loaded object described by MAP so its unrelocated PLT
4c1956
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
4c1956
 static inline int __attribute__ ((always_inline))
4c1956
-elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
4c1956
+elf_machine_runtime_setup (struct link_map *map, struct r_scope_elem *scope[],
4c1956
+			   int lazy, int profile)
4c1956
 {
4c1956
   if (map->l_info[DT_JMPREL])
4c1956
     {
4c1956
@@ -679,7 +680,7 @@ resolve_ifunc (Elf64_Addr value,
4c1956
 /* Perform the relocation specified by RELOC and SYM (which is fully
4c1956
    resolved).  MAP is the object containing the reloc.  */
4c1956
 auto inline void __attribute__ ((always_inline))
4c1956
-elf_machine_rela (struct link_map *map,
4c1956
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		  const Elf64_Rela *reloc,
4c1956
 		  const Elf64_Sym *sym,
4c1956
 		  const struct r_found_version *version,
4c1956
@@ -707,7 +708,7 @@ elf_machine_rela (struct link_map *map,
4c1956
 
4c1956
   /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt
4c1956
      and STT_GNU_IFUNC.  */
4c1956
-  struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
4c1956
+  struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type);
4c1956
   Elf64_Addr value = SYMBOL_ADDRESS (sym_map, sym, true) + reloc->r_addend;
4c1956
 
4c1956
   if (sym != NULL
4c1956
@@ -1036,7 +1037,7 @@ elf_machine_rela (struct link_map *map,
4c1956
 }
4c1956
 
4c1956
 auto inline void __attribute__ ((always_inline))
4c1956
-elf_machine_lazy_rel (struct link_map *map,
4c1956
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		      Elf64_Addr l_addr, const Elf64_Rela *reloc,
4c1956
 		      int skip_ifunc)
4c1956
 {
4c1956
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
4c1956
index f22db7860b4da3ec..36327c40a1972dd7 100644
4c1956
--- a/sysdeps/s390/s390-64/dl-machine.h
4c1956
+++ b/sysdeps/s390/s390-64/dl-machine.h
4c1956
@@ -75,7 +75,8 @@ elf_machine_load_address (void)
4c1956
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
4c1956
 
4c1956
 static inline int __attribute__ ((unused))
4c1956
-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
4c1956
+elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
4c1956
+			   int lazy, int profile)
4c1956
 {
4c1956
   extern void _dl_runtime_resolve (Elf64_Word);
4c1956
   extern void _dl_runtime_profile (Elf64_Word);
4c1956
@@ -270,8 +271,9 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
4c1956
 
4c1956
 auto inline void
4c1956
 __attribute__ ((always_inline))
4c1956
-elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
4c1956
-		  const Elf64_Sym *sym, const struct r_found_version *version,
4c1956
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
4c1956
+		  const Elf64_Rela *reloc, const Elf64_Sym *sym,
4c1956
+		  const struct r_found_version *version,
4c1956
 		  void *const reloc_addr_arg, int skip_ifunc)
4c1956
 {
4c1956
   Elf64_Addr *const reloc_addr = reloc_addr_arg;
4c1956
@@ -304,7 +306,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
4c1956
       /* Only needed for R_390_COPY below.  */
4c1956
       const Elf64_Sym *const refsym = sym;
4c1956
 #endif
4c1956
-      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
4c1956
+      struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
4c1956
+					      r_type);
4c1956
       Elf64_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
4c1956
 
4c1956
       if (sym != NULL
4c1956
@@ -449,7 +452,7 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
4c1956
 
4c1956
 auto inline void
4c1956
 __attribute__ ((always_inline))
4c1956
-elf_machine_lazy_rel (struct link_map *map,
4c1956
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		      Elf64_Addr l_addr, const Elf64_Rela *reloc,
4c1956
 		      int skip_ifunc)
4c1956
 {
4c1956
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
4c1956
index b94d3b39ec1dca64..5262aa69c06aa8db 100644
4c1956
--- a/sysdeps/x86_64/dl-machine.h
4c1956
+++ b/sysdeps/x86_64/dl-machine.h
4c1956
@@ -62,7 +62,8 @@ elf_machine_load_address (void)
4c1956
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
4c1956
 
4c1956
 static inline int __attribute__ ((unused, always_inline))
4c1956
-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
4c1956
+elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
4c1956
+			   int lazy, int profile)
4c1956
 {
4c1956
   Elf64_Addr *got;
4c1956
   extern void _dl_runtime_resolve_fxsave (ElfW(Word)) attribute_hidden;
4c1956
@@ -260,8 +261,9 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rela) *reloc,
4c1956
 
4c1956
 auto inline void
4c1956
 __attribute__ ((always_inline))
4c1956
-elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
4c1956
-		  const ElfW(Sym) *sym, const struct r_found_version *version,
4c1956
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
4c1956
+		  const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
4c1956
+		  const struct r_found_version *version,
4c1956
 		  void *const reloc_addr_arg, int skip_ifunc)
4c1956
 {
4c1956
   ElfW(Addr) *const reloc_addr = reloc_addr_arg;
4c1956
@@ -300,7 +302,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
4c1956
 # ifndef RTLD_BOOTSTRAP
4c1956
       const ElfW(Sym) *const refsym = sym;
4c1956
 # endif
4c1956
-      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
4c1956
+      struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type);
4c1956
       ElfW(Addr) value = SYMBOL_ADDRESS (sym_map, sym, true);
4c1956
 
4c1956
       if (sym != NULL
4c1956
@@ -539,7 +541,7 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
4c1956
 
4c1956
 auto inline void
4c1956
 __attribute ((always_inline))
4c1956
-elf_machine_lazy_rel (struct link_map *map,
4c1956
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
4c1956
 		      ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
4c1956
 		      int skip_ifunc)
4c1956
 {
4c1956
@@ -573,7 +575,7 @@ elf_machine_lazy_rel (struct link_map *map,
4c1956
 
4c1956
       /* Always initialize TLS descriptors completely at load time, in
4c1956
 	 case static TLS is allocated for it that requires locking.  */
4c1956
-      elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
4c1956
+      elf_machine_rela (map, scope, reloc, sym, version, reloc_addr, skip_ifunc);
4c1956
     }
4c1956
   else if (__glibc_unlikely (r_type == R_X86_64_IRELATIVE))
4c1956
     {