| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Read the dynamic section at DYN and fill in INFO with indices DT_*. | 
 | 2 |    Copyright (C) 2012-2016 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 |    <http://www.gnu.org/licenses/>.  */ | 
 | 18 |  | 
 | 19 | #include <assert.h> | 
 | 20 | #include <libc-internal.h> | 
 | 21 |  | 
 | 22 | #ifndef RESOLVE_MAP | 
 | 23 | static | 
 | 24 | #else | 
 | 25 | auto | 
 | 26 | #endif | 
 | 27 | inline void __attribute__ ((unused, always_inline)) | 
 | 28 | elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) | 
 | 29 | { | 
 | 30 |   ElfW(Dyn) *dyn = l->l_ld; | 
 | 31 |   ElfW(Dyn) **info; | 
 | 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 RTLD_BOOTSTRAP | 
 | 39 |   if (dyn == NULL) | 
 | 40 |     return; | 
 | 41 | #endif | 
 | 42 |  | 
 | 43 |   info = l->l_info; | 
 | 44 |  | 
 | 45 |   while (dyn->d_tag != DT_NULL) | 
 | 46 |     { | 
 | 47 |       if ((d_tag_utype) dyn->d_tag < DT_NUM) | 
 | 48 | 	info[dyn->d_tag] = dyn; | 
 | 49 |       else if (dyn->d_tag >= DT_LOPROC && | 
 | 50 | 	       dyn->d_tag < DT_LOPROC + DT_THISPROCNUM) | 
 | 51 | 	{ | 
 | 52 | 	  /* This does not violate the array bounds of l->l_info, but | 
 | 53 | 	     gcc 4.6 on sparc somehow does not see this.  */ | 
 | 54 | 	  DIAG_PUSH_NEEDS_COMMENT; | 
 | 55 | 	  DIAG_IGNORE_NEEDS_COMMENT (4.6, | 
 | 56 | 				     "-Warray-bounds"); | 
 | 57 | 	  info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn; | 
 | 58 | 	  DIAG_POP_NEEDS_COMMENT; | 
 | 59 | 	} | 
 | 60 |       else if ((d_tag_utype) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM) | 
 | 61 | 	info[VERSYMIDX (dyn->d_tag)] = dyn; | 
 | 62 |       else if ((d_tag_utype) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM) | 
 | 63 | 	info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM | 
 | 64 | 	     + DT_VERSIONTAGNUM] = dyn; | 
 | 65 |       else if ((d_tag_utype) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM) | 
 | 66 | 	info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM | 
 | 67 | 	     + DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn; | 
 | 68 |       else if ((d_tag_utype) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM) | 
 | 69 | 	info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM | 
 | 70 | 	     + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn; | 
 | 71 |       ++dyn; | 
 | 72 |     } | 
 | 73 |  | 
 | 74 | #define DL_RO_DYN_TEMP_CNT	8 | 
 | 75 |  | 
 | 76 | #ifndef DL_RO_DYN_SECTION | 
 | 77 |   /* Don't adjust .dynamic unnecessarily.  */ | 
 | 78 |   if (l->l_addr != 0) | 
 | 79 |     { | 
 | 80 |       ElfW(Addr) l_addr = l->l_addr; | 
 | 81 |       int cnt = 0; | 
 | 82 |  | 
 | 83 | # define ADJUST_DYN_INFO(tag) \ | 
 | 84 |       do								      \ | 
 | 85 | 	if (info[tag] != NULL)						      \ | 
 | 86 | 	  {								      \ | 
 | 87 | 	    if (temp)							      \ | 
 | 88 | 	      {								      \ | 
 | 89 | 		temp[cnt].d_tag = info[tag]->d_tag;			      \ | 
 | 90 | 		temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr;	      \ | 
 | 91 | 		info[tag] = temp + cnt++;				      \ | 
 | 92 | 	      }								      \ | 
 | 93 | 	    else							      \ | 
 | 94 | 	      info[tag]->d_un.d_ptr += l_addr;				      \ | 
 | 95 | 	  }								      \ | 
 | 96 |       while (0) | 
 | 97 |  | 
 | 98 |       ADJUST_DYN_INFO (DT_HASH); | 
 | 99 |       ADJUST_DYN_INFO (DT_PLTGOT); | 
 | 100 |       ADJUST_DYN_INFO (DT_STRTAB); | 
 | 101 |       ADJUST_DYN_INFO (DT_SYMTAB); | 
 | 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 |       ADJUST_DYN_INFO (DT_JMPREL); | 
 | 109 |       ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM)); | 
 | 110 |       ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM | 
 | 111 | 		       + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM); | 
 | 112 | # undef ADJUST_DYN_INFO | 
 | 113 |       assert (cnt <= DL_RO_DYN_TEMP_CNT); | 
 | 114 |     } | 
 | 115 | #endif | 
 | 116 |   if (info[DT_PLTREL] != NULL) | 
 | 117 |     { | 
 | 118 | #if ELF_MACHINE_NO_RELA | 
 | 119 |       assert (info[DT_PLTREL]->d_un.d_val == DT_REL); | 
 | 120 | #elif ELF_MACHINE_NO_REL | 
 | 121 |       assert (info[DT_PLTREL]->d_un.d_val == DT_RELA); | 
 | 122 | #else | 
 | 123 |       assert (info[DT_PLTREL]->d_un.d_val == DT_REL | 
 | 124 | 	      || info[DT_PLTREL]->d_un.d_val == DT_RELA); | 
 | 125 | #endif | 
 | 126 |     } | 
 | 127 | #if ! ELF_MACHINE_NO_RELA | 
 | 128 |   if (info[DT_RELA] != NULL) | 
 | 129 |     assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela))); | 
 | 130 | # endif | 
 | 131 | # if ! ELF_MACHINE_NO_REL | 
 | 132 |   if (info[DT_REL] != NULL) | 
 | 133 |     assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel))); | 
 | 134 | #endif | 
 | 135 | #ifdef RTLD_BOOTSTRAP | 
 | 136 |   /* Only the bind now flags are allowed.  */ | 
 | 137 |   assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL | 
 | 138 | 	  || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0); | 
 | 139 |   assert (info[DT_FLAGS] == NULL | 
 | 140 | 	  || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); | 
 | 141 |   /* Flags must not be set for ld.so.  */ | 
 | 142 |   assert (info[DT_RUNPATH] == NULL); | 
 | 143 |   assert (info[DT_RPATH] == NULL); | 
 | 144 | #else | 
 | 145 |   if (info[DT_FLAGS] != NULL) | 
 | 146 |     { | 
 | 147 |       /* Flags are used.  Translate to the old form where available. | 
 | 148 | 	 Since these l_info entries are only tested for NULL pointers it | 
 | 149 | 	 is ok if they point to the DT_FLAGS entry.  */ | 
 | 150 |       l->l_flags = info[DT_FLAGS]->d_un.d_val; | 
 | 151 |  | 
 | 152 |       if (l->l_flags & DF_SYMBOLIC) | 
 | 153 | 	info[DT_SYMBOLIC] = info[DT_FLAGS]; | 
 | 154 |       if (l->l_flags & DF_TEXTREL) | 
 | 155 | 	info[DT_TEXTREL] = info[DT_FLAGS]; | 
 | 156 |       if (l->l_flags & DF_BIND_NOW) | 
 | 157 | 	info[DT_BIND_NOW] = info[DT_FLAGS]; | 
 | 158 |     } | 
 | 159 |   if (info[VERSYMIDX (DT_FLAGS_1)] != NULL) | 
 | 160 |     { | 
 | 161 |       l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val; | 
 | 162 |  | 
 | 163 |       /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like | 
 | 164 | 	 to assert this, but we can't. Users have been setting | 
 | 165 | 	 unsupported DF_1_* flags for a long time and glibc has ignored | 
 | 166 | 	 them. Therefore to avoid breaking existing applications the | 
 | 167 | 	 best we can do is add a warning during debugging with the | 
 | 168 | 	 intent of notifying the user of the problem.  */ | 
 | 169 |       if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0) | 
 | 170 | 	  && l->l_flags_1 & ~DT_1_SUPPORTED_MASK) | 
 | 171 | 	_dl_debug_printf ("\nWARNING: Unsupported flag value(s) of 0x%x in DT_FLAGS_1.\n", | 
 | 172 | 			  l->l_flags_1 & ~DT_1_SUPPORTED_MASK); | 
 | 173 |  | 
 | 174 |       if (l->l_flags_1 & DF_1_NOW) | 
 | 175 | 	info[DT_BIND_NOW] = info[VERSYMIDX (DT_FLAGS_1)]; | 
 | 176 |     } | 
 | 177 |   if (info[DT_RUNPATH] != NULL) | 
 | 178 |     /* If both RUNPATH and RPATH are given, the latter is ignored.  */ | 
 | 179 |     info[DT_RPATH] = NULL; | 
 | 180 | #endif | 
 | 181 | } |