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