(root)/
glibc-2.38/
elf/
do-rel.h
       1  /* Do relocations for ELF dynamic linking.
       2     Copyright (C) 1995-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <ldsodefs.h>
      20  
      21  /* This file may be included twice, to define both
      22     `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.  */
      23  
      24  #ifdef DO_RELA
      25  # define elf_dynamic_do_Rel		elf_dynamic_do_Rela
      26  # define Rel				Rela
      27  # define elf_machine_rel		elf_machine_rela
      28  # define elf_machine_rel_relative	elf_machine_rela_relative
      29  #endif
      30  
      31  #ifndef DO_ELF_MACHINE_REL_RELATIVE
      32  # define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
      33    elf_machine_rel_relative (l_addr, relative,				      \
      34  			    (void *) (l_addr + relative->r_offset))
      35  #endif
      36  
      37  /* Perform the relocations in MAP on the running program image as specified
      38     by RELTAG, SZTAG.  If LAZY is nonzero, this is the first pass on PLT
      39     relocations; they should be set up to call _dl_runtime_resolve, rather
      40     than fully resolved now.  */
      41  
      42  static inline void __attribute__ ((always_inline))
      43  elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
      44  		    ElfW(Addr) reladdr, ElfW(Addr) relsize,
      45  		    __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
      46  		    int lazy, int skip_ifunc)
      47  {
      48    const ElfW(Rel) *relative = (const void *) reladdr;
      49    const ElfW(Rel) *r = relative + nrelative;
      50    const ElfW(Rel) *end = (const void *) (reladdr + relsize);
      51    ElfW(Addr) l_addr = map->l_addr;
      52    const ElfW(Sym) *const symtab
      53        = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
      54  
      55  #ifdef RTLD_BOOTSTRAP
      56    for (; relative < r; ++relative)
      57      DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
      58  
      59    const ElfW (Half) *const version
      60        = (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
      61    for (; r < end; ++r)
      62      {
      63        ElfW (Half) ndx = version[ELFW (R_SYM) (r->r_info)] & 0x7fff;
      64        const ElfW (Sym) *sym = &symtab[ELFW (R_SYM) (r->r_info)];
      65        void *const r_addr_arg = (void *) (l_addr + r->r_offset);
      66        const struct r_found_version *rversion = &map->l_versions[ndx];
      67  
      68        elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, skip_ifunc);
      69      }
      70  #else /* !RTLD_BOOTSTRAP */
      71  # if defined ELF_MACHINE_IRELATIVE
      72    const ElfW(Rel) *r2 = NULL;
      73    const ElfW(Rel) *end2 = NULL;
      74  # endif
      75  
      76  #if !defined DO_RELA || !defined ELF_MACHINE_PLT_REL
      77    /* We never bind lazily during ld.so bootstrap.  Unfortunately gcc is
      78       not clever enough to see through all the function calls to realize
      79       that.  */
      80    if (lazy)
      81      {
      82        /* Doing lazy PLT relocations; they need very little info.  */
      83        for (; r < end; ++r)
      84  # ifdef ELF_MACHINE_IRELATIVE
      85  	if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
      86  	  {
      87  	    if (r2 == NULL)
      88  	      r2 = r;
      89  	    end2 = r;
      90  	  }
      91  	else
      92  # endif
      93  	  elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc);
      94  
      95  # ifdef ELF_MACHINE_IRELATIVE
      96        if (r2 != NULL)
      97  	for (; r2 <= end2; ++r2)
      98  	  if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
      99  	    elf_machine_lazy_rel (map, scope, l_addr, r2, skip_ifunc);
     100  # endif
     101      }
     102    else
     103  #endif
     104      {
     105        /* This is defined in rtld.c, but nowhere in the static libc.a; make
     106  	 the reference weak so static programs can still link.  This
     107  	 declaration cannot be done when compiling rtld.c (i.e. #ifdef
     108  	 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
     109  	 _dl_rtld_map, which is incompatible with a weak decl in the same
     110  	 file.  */
     111  # ifndef SHARED
     112        weak_extern (GL(dl_rtld_map));
     113  # endif
     114        if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
     115  # if !defined DO_RELA || defined ELF_MACHINE_REL_RELATIVE
     116  	/* Rela platforms get the offset from r_addend and this must
     117  	   be copied in the relocation address.  Therefore we can skip
     118  	   the relative relocations only if this is for rel
     119  	   relocations or rela relocations if they are computed as
     120  	   memory_loc += l_addr...  */
     121  	if (l_addr != 0)
     122  # endif
     123  	  for (; relative < r; ++relative)
     124  	    DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
     125  
     126        if (map->l_info[VERSYMIDX (DT_VERSYM)])
     127  	{
     128  	  const ElfW(Half) *const version =
     129  	    (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
     130  
     131  	  for (; r < end; ++r)
     132  	    {
     133  	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
     134  	      const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
     135  	      void *const r_addr_arg = (void *) (l_addr + r->r_offset);
     136  	      const struct r_found_version *rversion = &map->l_versions[ndx];
     137  #if defined ELF_MACHINE_IRELATIVE
     138  	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
     139  		{
     140  		  if (r2 == NULL)
     141  		    r2 = r;
     142  		  end2 = r;
     143  		  continue;
     144  		}
     145  #endif
     146  
     147  	      elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg,
     148  			       skip_ifunc);
     149  #if defined SHARED
     150  	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
     151  		  && GLRO(dl_naudit) > 0)
     152  		{
     153  		  struct link_map *sym_map
     154  		    = RESOLVE_MAP (map, scope, &sym, rversion,
     155  				   ELF_MACHINE_JMP_SLOT);
     156  		  if (sym != NULL)
     157  		    _dl_audit_symbind (map, NULL, r, sym, r_addr_arg, sym_map,
     158  				       false);
     159  		}
     160  #endif
     161  	    }
     162  
     163  #if defined ELF_MACHINE_IRELATIVE
     164  	  if (r2 != NULL)
     165  	    for (; r2 <= end2; ++r2)
     166  	      if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
     167  		{
     168  		  ElfW(Half) ndx
     169  		    = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff;
     170  		  elf_machine_rel (map, scope, r2,
     171  				   &symtab[ELFW(R_SYM) (r2->r_info)],
     172  				   &map->l_versions[ndx],
     173  				   (void *) (l_addr + r2->r_offset),
     174  				   skip_ifunc);
     175  		}
     176  #endif
     177  	}
     178        else
     179  	{
     180  	  for (; r < end; ++r)
     181  	    {
     182  	      const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
     183  	      void *const r_addr_arg = (void *) (l_addr + r->r_offset);
     184  # ifdef ELF_MACHINE_IRELATIVE
     185  	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
     186  		{
     187  		  if (r2 == NULL)
     188  		    r2 = r;
     189  		  end2 = r;
     190  		  continue;
     191  		}
     192  # endif
     193  	      elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg,
     194  			       skip_ifunc);
     195  # if defined SHARED
     196  	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
     197  		  && GLRO(dl_naudit) > 0)
     198  		{
     199  		  struct link_map *sym_map
     200  		    = RESOLVE_MAP (map, scope, &sym,
     201  				   (struct r_found_version *) NULL,
     202  				   ELF_MACHINE_JMP_SLOT);
     203  		  if (sym != NULL)
     204  		    _dl_audit_symbind (map, NULL, r, sym,r_addr_arg, sym_map,
     205  				       false);
     206  		}
     207  # endif
     208  	    }
     209  
     210  # ifdef ELF_MACHINE_IRELATIVE
     211  	  if (r2 != NULL)
     212  	    for (; r2 <= end2; ++r2)
     213  	      if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
     214  		elf_machine_rel (map, scope, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
     215  				 NULL, (void *) (l_addr + r2->r_offset),
     216  				 skip_ifunc);
     217  # endif
     218  	}
     219      }
     220  #endif /* !RTLD_BOOTSTRAP */
     221  }
     222  
     223  #undef elf_dynamic_do_Rel
     224  #undef Rel
     225  #undef elf_machine_rel
     226  #undef elf_machine_rel_relative
     227  #undef DO_ELF_MACHINE_REL_RELATIVE
     228  #undef DO_RELA