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