summary refs log tree commit diff
path: root/sysdeps/i386/dl-machine.h
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2021-10-07 11:55:02 -0700
committerFangrui Song <maskray@google.com>2021-10-07 11:55:02 -0700
commit490e6c62aa31a8aa5c4a059f6e646ede121edf0a (patch)
tree40bedb62d8b555792f91c82127b0f599da90ef39 /sysdeps/i386/dl-machine.h
parent349b0441dab375099b1d7f6909c1742286a67da9 (diff)
downloadglibc-490e6c62aa31a8aa5c4a059f6e646ede121edf0a.tar.gz
glibc-490e6c62aa31a8aa5c4a059f6e646ede121edf0a.tar.xz
glibc-490e6c62aa31a8aa5c4a059f6e646ede121edf0a.zip
elf: Avoid nested functions in the loader [BZ #27220]
dynamic-link.h is included more than once in some elf/ files (rtld.c,
dl-conflict.c, dl-reloc.c, dl-reloc-static-pie.c) and uses GCC nested
functions. This harms readability and the nested functions usage
is the biggest obstacle prevents Clang build (Clang doesn't support GCC
nested functions).

The key idea for unnesting is to add extra parameters (struct link_map
*and struct r_scope_elm *[]) to RESOLVE_MAP,
ELF_MACHINE_BEFORE_RTLD_RELOC, ELF_DYNAMIC_RELOCATE, elf_machine_rel[a],
elf_machine_lazy_rel, and elf_machine_runtime_setup. (This is inspired
by Stan Shebs' ppc64/x86-64 implementation in the
google/grte/v5-2.27/master which uses mixed extra parameters and static
variables.)

Future simplification:
* If mips elf_machine_runtime_setup no longer needs RESOLVE_GOTSYM,
  elf_machine_runtime_setup can drop the `scope` parameter.
* If TLSDESC no longer need to be in elf_machine_lazy_rel,
  elf_machine_lazy_rel can drop the `scope` parameter.

Tested on aarch64, i386, x86-64, powerpc64le, powerpc64, powerpc32,
sparc64, sparcv9, s390x, s390, hppa, ia64, armhf, alpha, and mips64.
In addition, tested build-many-glibcs.py with {arc,csky,microblaze,nios2}-linux-gnu
and riscv64-linux-gnu-rv64imafdc-lp64d.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps/i386/dl-machine.h')
-rw-r--r--sysdeps/i386/dl-machine.h40
1 files changed, 23 insertions, 17 deletions
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 0401888508..9f578e536a 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -54,7 +54,8 @@ elf_machine_dynamic (void)
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
 
 static inline int __attribute__ ((unused, always_inline))
-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
+			   int lazy, int profile)
 {
   Elf32_Addr *got;
   extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden;
@@ -284,9 +285,10 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
 
-auto inline void
+static inline void
 __attribute ((always_inline))
-elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
+elf_machine_rel (struct link_map *map, struct r_scope_elem *scope[],
+		 const Elf32_Rel *reloc,
 		 const Elf32_Sym *sym, const struct r_found_version *version,
 		 void *const reloc_addr_arg, int skip_ifunc)
 {
@@ -320,7 +322,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 # ifndef RTLD_BOOTSTRAP
       const Elf32_Sym *const refsym = sym;
 # endif
-      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
+					      r_type);
       Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
 
       if (sym != NULL
@@ -491,10 +494,11 @@ and creates an unsatisfiable circular dependency.\n",
 }
 
 # ifndef RTLD_BOOTSTRAP
-auto inline void
+static inline void
 __attribute__ ((always_inline))
-elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
-		  const Elf32_Sym *sym, const struct r_found_version *version,
+elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
+		  const Elf32_Rela *reloc, const Elf32_Sym *sym,
+		  const struct r_found_version *version,
 		  void *const reloc_addr_arg, int skip_ifunc)
 {
   Elf32_Addr *const reloc_addr = reloc_addr_arg;
@@ -507,7 +511,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 #  ifndef RESOLVE_CONFLICT_FIND_MAP
       const Elf32_Sym *const refsym = sym;
 #  endif
-      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
+					      r_type);
       Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
 
       if (sym != NULL
@@ -640,7 +645,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 }
 # endif	/* !RTLD_BOOTSTRAP */
 
-auto inline void
+static inline void
 __attribute ((always_inline))
 elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
 			  void *const reloc_addr_arg)
@@ -651,7 +656,7 @@ elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
 }
 
 # ifndef RTLD_BOOTSTRAP
-auto inline void
+static inline void
 __attribute__ ((always_inline))
 elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
 			   void *const reloc_addr_arg)
@@ -661,9 +666,9 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
 }
 # endif	/* !RTLD_BOOTSTRAP */
 
-auto inline void
+static inline void
 __attribute__ ((always_inline))
-elf_machine_lazy_rel (struct link_map *map,
+elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
 		      Elf32_Addr l_addr, const Elf32_Rel *reloc,
 		      int skip_ifunc)
 {
@@ -698,13 +703,13 @@ elf_machine_lazy_rel (struct link_map *map,
 	  const ElfW(Half) *const version =
 	    (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
 	  ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
-	  elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
+	  elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)],
 			   &map->l_versions[ndx],
 			   (void *) (l_addr + r->r_offset), skip_ifunc);
 	}
 # ifndef RTLD_BOOTSTRAP
       else
-	elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
+	elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
 			 (void *) (l_addr + r->r_offset), skip_ifunc);
 # endif
     }
@@ -721,9 +726,9 @@ elf_machine_lazy_rel (struct link_map *map,
 
 # ifndef RTLD_BOOTSTRAP
 
-auto inline void
+static inline void
 __attribute__ ((always_inline))
-elf_machine_lazy_rela (struct link_map *map,
+elf_machine_lazy_rela (struct link_map *map, struct r_scope_elem *scope[],
 		       Elf32_Addr l_addr, const Elf32_Rela *reloc,
 		       int skip_ifunc)
 {
@@ -747,7 +752,8 @@ elf_machine_lazy_rela (struct link_map *map,
 
       /* Always initialize TLS descriptors completely at load time, in
 	 case static TLS is allocated for it that requires locking.  */
-      elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
+      elf_machine_rela (map, scope, reloc, sym, version, reloc_addr,
+			skip_ifunc);
     }
   else if (__glibc_unlikely (r_type == R_386_IRELATIVE))
     {