about summary refs log tree commit diff
path: root/elf/do-rel.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 /elf/do-rel.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 'elf/do-rel.h')
-rw-r--r--elf/do-rel.h16
1 files changed, 8 insertions, 8 deletions
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 321ac2b359..f441b74919 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -37,8 +37,8 @@
    relocations; they should be set up to call _dl_runtime_resolve, rather
    than fully resolved now.  */
 
-auto inline void __attribute__ ((always_inline))
-elf_dynamic_do_Rel (struct link_map *map,
+static inline void __attribute__ ((always_inline))
+elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
 		    ElfW(Addr) reladdr, ElfW(Addr) relsize,
 		    __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
 		    int lazy, int skip_ifunc)
@@ -68,13 +68,13 @@ elf_dynamic_do_Rel (struct link_map *map,
 	  }
 	else
 # endif
-	  elf_machine_lazy_rel (map, l_addr, r, skip_ifunc);
+	  elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc);
 
 # ifdef ELF_MACHINE_IRELATIVE
       if (r2 != NULL)
 	for (; r2 <= end2; ++r2)
 	  if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
-	    elf_machine_lazy_rel (map, l_addr, r2, skip_ifunc);
+	    elf_machine_lazy_rel (map, scope, l_addr, r2, skip_ifunc);
 # endif
     }
   else
@@ -134,7 +134,7 @@ elf_dynamic_do_Rel (struct link_map *map,
 #endif
 
 	      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);
 	    }
@@ -146,7 +146,7 @@ elf_dynamic_do_Rel (struct link_map *map,
 		{
 		  ElfW(Half) ndx
 		    = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff;
-		  elf_machine_rel (map, r2,
+		  elf_machine_rel (map, scope, r2,
 				   &symtab[ELFW(R_SYM) (r2->r_info)],
 				   &map->l_versions[ndx],
 				   (void *) (l_addr + r2->r_offset),
@@ -167,14 +167,14 @@ elf_dynamic_do_Rel (struct link_map *map,
 	      }
 	    else
 # endif
-	      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);
 
 # ifdef ELF_MACHINE_IRELATIVE
 	  if (r2 != NULL)
 	    for (; r2 <= end2; ++r2)
 	      if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
-		elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
+		elf_machine_rel (map, scope, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
 				 NULL, (void *) (l_addr + r2->r_offset),
 				 skip_ifunc);
 # endif