(root)/
glibc-2.38/
elf/
get-dynamic-info.h
       1  /* Read the dynamic section at DYN and fill in INFO with indices DT_*.
       2     Copyright (C) 2012-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  /* Populate dynamic tags in l_info.  */
      20  
      21  #ifndef _GET_DYNAMIC_INFO_H
      22  #define _GET_DYNAMIC_INFO_H
      23  
      24  #include <assert.h>
      25  #include <dl-machine-rel.h>
      26  #include <libc-diag.h>
      27  
      28  static inline void __attribute__ ((unused, always_inline))
      29  elf_get_dynamic_info (struct link_map *l, bool bootstrap,
      30  		      bool static_pie_bootstrap)
      31  {
      32  #if __ELF_NATIVE_CLASS == 32
      33    typedef Elf32_Word d_tag_utype;
      34  #elif __ELF_NATIVE_CLASS == 64
      35    typedef Elf64_Xword d_tag_utype;
      36  #endif
      37  
      38  #ifndef STATIC_PIE_BOOTSTRAP
      39    if (!bootstrap && l->l_ld == NULL)
      40      return;
      41  #endif
      42  
      43    ElfW(Dyn) **info = l->l_info;
      44  
      45    for (ElfW(Dyn) *dyn = l->l_ld; dyn->d_tag != DT_NULL; dyn++)
      46      {
      47        d_tag_utype i;
      48  
      49        if ((d_tag_utype) dyn->d_tag < DT_NUM)
      50  	i = dyn->d_tag;
      51        else if (dyn->d_tag >= DT_LOPROC
      52  	       && dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
      53  	i = dyn->d_tag - DT_LOPROC + DT_NUM;
      54        else if ((d_tag_utype) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
      55  	i = VERSYMIDX (dyn->d_tag);
      56        else if ((d_tag_utype) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
      57  	i = DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
      58  	    + DT_VERSIONTAGNUM;
      59        else if ((d_tag_utype) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
      60  	i = DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
      61  	    + DT_VERSIONTAGNUM + DT_EXTRANUM;
      62        else if ((d_tag_utype) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
      63  	i = DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
      64  	    + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM;
      65        else
      66  	continue;
      67  
      68        info[i] = dyn;
      69      }
      70  
      71    /* Don't adjust .dynamic unnecessarily.  */
      72    if (l->l_addr != 0 && dl_relocate_ld (l))
      73      {
      74        ElfW(Addr) l_addr = l->l_addr;
      75  
      76  # define ADJUST_DYN_INFO(tag) \
      77        do								      \
      78  	{								      \
      79  	  if (info[tag] != NULL)					      \
      80  	  info[tag]->d_un.d_ptr += l_addr;				      \
      81  	}								      \
      82        while (0)
      83  
      84        ADJUST_DYN_INFO (DT_HASH);
      85        ADJUST_DYN_INFO (DT_PLTGOT);
      86        ADJUST_DYN_INFO (DT_STRTAB);
      87        ADJUST_DYN_INFO (DT_SYMTAB);
      88        ADJUST_DYN_INFO (DT_RELR);
      89        ADJUST_DYN_INFO (DT_JMPREL);
      90        ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
      91        ADJUST_DYN_INFO (ADDRIDX (DT_GNU_HASH));
      92  # undef ADJUST_DYN_INFO
      93  
      94        /* DT_RELA/DT_REL are mandatory.  But they may have zero value if
      95  	 there is DT_RELR.  Don't relocate them if they are zero.  */
      96  # define ADJUST_DYN_INFO(tag) \
      97        do								      \
      98  	if (info[tag] != NULL && info[tag]->d_un.d_ptr != 0)		      \
      99           info[tag]->d_un.d_ptr += l_addr;				      \
     100        while (0)
     101  
     102  # if ! ELF_MACHINE_NO_RELA
     103        ADJUST_DYN_INFO (DT_RELA);
     104  # endif
     105  # if ! ELF_MACHINE_NO_REL
     106        ADJUST_DYN_INFO (DT_REL);
     107  # endif
     108  # undef ADJUST_DYN_INFO
     109      }
     110    if (info[DT_PLTREL] != NULL)
     111      {
     112  #if ELF_MACHINE_NO_RELA
     113        assert (info[DT_PLTREL]->d_un.d_val == DT_REL);
     114  #elif ELF_MACHINE_NO_REL
     115        assert (info[DT_PLTREL]->d_un.d_val == DT_RELA);
     116  #else
     117        assert (info[DT_PLTREL]->d_un.d_val == DT_REL
     118  	      || info[DT_PLTREL]->d_un.d_val == DT_RELA);
     119  #endif
     120      }
     121  #if ! ELF_MACHINE_NO_RELA
     122    if (info[DT_RELA] != NULL)
     123      assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
     124  # endif
     125  # if ! ELF_MACHINE_NO_REL
     126    if (info[DT_REL] != NULL)
     127      assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
     128  #endif
     129    if (info[DT_RELR] != NULL)
     130      assert (info[DT_RELRENT]->d_un.d_val == sizeof (ElfW(Relr)));
     131    if (bootstrap || static_pie_bootstrap)
     132      {
     133        assert (info[DT_RUNPATH] == NULL);
     134        assert (info[DT_RPATH] == NULL);
     135      }
     136    if (bootstrap)
     137      {
     138        /* Only the bind now flags are allowed.  */
     139        assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL
     140  	      || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0);
     141        /* Flags must not be set for ld.so.  */
     142        assert (info[DT_FLAGS] == NULL
     143  	      || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
     144      }
     145    else
     146      {
     147        if (info[DT_FLAGS] != NULL)
     148  	{
     149  	  /* Flags are used.  Translate to the old form where available.
     150  	     Since these l_info entries are only tested for NULL pointers it
     151  	     is ok if they point to the DT_FLAGS entry.  */
     152  	  l->l_flags = info[DT_FLAGS]->d_un.d_val;
     153  
     154  	  if (l->l_flags & DF_SYMBOLIC)
     155  	    info[DT_SYMBOLIC] = info[DT_FLAGS];
     156  	  if (l->l_flags & DF_TEXTREL)
     157  	    info[DT_TEXTREL] = info[DT_FLAGS];
     158  	  if (l->l_flags & DF_BIND_NOW)
     159  	    info[DT_BIND_NOW] = info[DT_FLAGS];
     160  	}
     161  
     162        if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
     163  	{
     164  	  l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
     165  	  if (l->l_flags_1 & DF_1_NODELETE)
     166  	    l->l_nodelete_pending = true;
     167  
     168  	  /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like
     169  	     to assert this, but we can't. Users have been setting
     170  	     unsupported DF_1_* flags for a long time and glibc has ignored
     171  	     them. Therefore to avoid breaking existing applications the
     172  	     best we can do is add a warning during debugging with the
     173  	     intent of notifying the user of the problem.  */
     174  	  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)
     175  	      && l->l_flags_1 & ~DT_1_SUPPORTED_MASK)
     176  	    _dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x "
     177  			      "in DT_FLAGS_1.\n",
     178  			     l->l_flags_1 & ~DT_1_SUPPORTED_MASK);
     179  
     180  	 if (l->l_flags_1 & DF_1_NOW)
     181  	   info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)];
     182         }
     183  
     184      if (info[DT_RUNPATH] != NULL)
     185        /* If both RUNPATH and RPATH are given, the latter is ignored.  */
     186        info[DT_RPATH] = NULL;
     187     }
     188  }
     189  
     190  #endif