1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Update any dynamic entry offsets. One issue with dynamic entries is that 27 * you only know whether they refer to a value or an offset if you know each 28 * type. Thus we check for all types we know about, it a type is found that 29 * we don't know about then return and error as we have no idea what to do. 30 */ 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <libelf.h> 34 #include <link.h> 35 #include "libld.h" 36 #include "msg.h" 37 #include "rtld.h" 38 #include "_librtld.h" 39 40 int 41 update_dynamic(Cache *cache, Cache *_cache, Rt_map *lmp, int flags, 42 Addr addr, Off off, const char *file, Xword null, Xword data, Xword func, 43 Xword entsize, Xword checksum) 44 { 45 Dyn *dyn = (Dyn *)_cache->c_data->d_buf, *posdyn = 0; 46 const char *strs; 47 Cache *__cache; 48 49 /* 50 * If we're dealing with an object that might have bound to an external 51 * dependency establish our string table for possible NEEDED processing. 52 */ 53 if (flags & RTLD_REL_DEPENDS) { 54 __cache = &cache[_cache->c_shdr->sh_link]; 55 strs = (const char *)__cache->c_data->d_buf; 56 } 57 58 /* 59 * Loop through the dynamic table updating all offsets. 60 */ 61 while (dyn->d_tag != DT_NULL) { 62 switch ((Xword)dyn->d_tag) { 63 case DT_NEEDED: 64 if (posdyn) { 65 Rt_map *dlmp; 66 67 /* 68 * Determine whether this dependency has been 69 * loaded (this is the most generic way to check 70 * any alias names), and if it has been bound 71 * to, undo any lazy-loading position flag. 72 */ 73 if (dlmp = is_so_loaded(LIST(lmp), 74 (strs + dyn->d_un.d_val))) { 75 Bnd_desc **bdpp; 76 Aliste off; 77 78 for (ALIST_TRAVERSE(DEPENDS(lmp), off, 79 bdpp)) { 80 if (dlmp == (*bdpp)->b_depend) { 81 posdyn->d_un.d_val &= 82 ~DF_P1_LAZYLOAD; 83 break; 84 } 85 } 86 } 87 } 88 break; 89 90 case DT_RELAENT: 91 case DT_STRSZ: 92 case DT_SYMENT: 93 case DT_SONAME: 94 case DT_RPATH: 95 case DT_SYMBOLIC: 96 case DT_RELENT: 97 case DT_PLTREL: 98 case DT_TEXTREL: 99 case DT_VERDEFNUM: 100 case DT_VERNEEDNUM: 101 case DT_AUXILIARY: 102 case DT_USED: 103 case DT_FILTER: 104 case DT_DEPRECATED_SPARC_REGISTER: 105 case M_DT_REGISTER: 106 case DT_BIND_NOW: 107 case DT_INIT_ARRAYSZ: 108 case DT_FINI_ARRAYSZ: 109 case DT_RUNPATH: 110 case DT_FLAGS: 111 case DT_CONFIG: 112 case DT_DEPAUDIT: 113 case DT_AUDIT: 114 case DT_SUNW_SYMSZ: 115 break; 116 case DT_PLTGOT: 117 case DT_HASH: 118 case DT_STRTAB: 119 case DT_SYMTAB: 120 case DT_SUNW_SYMTAB: 121 case DT_INIT: 122 case DT_FINI: 123 case DT_VERSYM: 124 case DT_VERDEF: 125 case DT_VERNEED: 126 case DT_INIT_ARRAY: 127 case DT_FINI_ARRAY: 128 dyn->d_un.d_ptr += addr; 129 break; 130 131 /* 132 * If the memory image is being used, this element would have 133 * been initialized to the runtime linkers internal link-map 134 * list. Clear it. 135 */ 136 case DT_DEBUG: 137 dyn->d_un.d_val = 0; 138 break; 139 140 /* 141 * The number of relocations may have been reduced if 142 * relocations have been saved in the new image. Thus we 143 * compute the new relocation size and start. 144 */ 145 case DT_RELASZ: 146 case DT_RELSZ: 147 dyn->d_un.d_val = ((data + func) * entsize); 148 break; 149 150 case DT_RELA: 151 case DT_REL: 152 dyn->d_un.d_ptr = (addr + off + (null * entsize)); 153 break; 154 155 /* 156 * If relative relocations have been processed clear the count. 157 */ 158 case DT_RELACOUNT: 159 case DT_RELCOUNT: 160 if (flags & RTLD_REL_RELATIVE) 161 dyn->d_un.d_val = 0; 162 break; 163 164 case DT_PLTRELSZ: 165 dyn->d_un.d_val = (func * entsize); 166 break; 167 168 case DT_JMPREL: 169 dyn->d_un.d_ptr = (addr + off + 170 ((null + data) * entsize)); 171 break; 172 173 /* 174 * Recompute the images elf checksum. 175 */ 176 case DT_CHECKSUM: 177 dyn->d_un.d_val = checksum; 178 break; 179 180 /* 181 * If a flag entry is available, indicate if this image has 182 * been generated via the configuration process (crle(1)). 183 * Because we only started depositing DT_FLAGS_1 entries in all 184 * objects starting with Solaris 8, set a feature flag if it 185 * is present (these got added in Solaris 7). 186 * The runtime linker may use this flag to search for a local 187 * configuration file - this is only meaningful in executables 188 * but the flag has value for identifying images regardless. 189 * 190 * If this file is acting as a filter, and dependency 191 * relocations have been processed (a filter is thought of as a 192 * dependency in terms of symbol binding), we may have bound to 193 * the filtee, and hence carried out the relocation. Indicate 194 * that the filtee must be preloaded, as the .plt won't get 195 * exercised to cause its normal loading. 196 */ 197 case DT_FLAGS_1: 198 if (flags & RTLD_CONFSET) 199 dyn->d_un.d_val |= DF_1_CONFALT; 200 if ((flags & RTLD_REL_DEPENDS) && 201 (FLAGS1(lmp)) & MSK_RT_FILTER) 202 dyn->d_un.d_val |= DF_1_LOADFLTR; 203 break; 204 205 case DT_FEATURE_1: 206 if (flags & RTLD_CONFSET) 207 dyn->d_un.d_val |= DTF_1_CONFEXP; 208 break; 209 210 /* 211 * If a position flag is available save it for possible update 212 * when processing the next NEEDED tag. 213 */ 214 case DT_POSFLAG_1: 215 if (flags & RTLD_REL_DEPENDS) { 216 posdyn = dyn++; 217 continue; 218 } 219 break; 220 221 /* 222 * Collect the defaults. 223 */ 224 default: 225 /* 226 * If d_val is used, don't touch. 227 */ 228 if ((dyn->d_tag >= DT_VALRNGLO) && 229 (dyn->d_tag <= DT_VALRNGHI)) 230 break; 231 232 /* 233 * If d_ptr is used, adjust. Note, some entries that 234 * fell into this range are offsets into the dynamic 235 * string table. Although these would need modifying 236 * if the section itself were resized, there is no 237 * resizing with dldump(). Entries that correspond to 238 * offsets are picked off in the initial DT_ loop 239 * above. 240 */ 241 if ((dyn->d_tag >= DT_ADDRRNGLO) && 242 (dyn->d_tag <= DT_ADDRRNGHI)) { 243 dyn->d_un.d_ptr += addr; 244 break; 245 } 246 247 /* 248 * Check to see if this DT_ entry conforms 249 * to the DT_ENCODING rules. 250 */ 251 if ((dyn->d_tag >= DT_ENCODING) && 252 (dyn->d_tag <= DT_HIOS)) { 253 /* 254 * Even tag values are ADDRESS encodings 255 */ 256 if ((dyn->d_tag % 2) == 0) { 257 dyn->d_un.d_ptr += addr; 258 } 259 break; 260 } 261 eprintf(LIST(lmp), ERR_WARNING, 262 MSG_INTL(MSG_DT_UNKNOWN), file, 263 EC_XWORD(dyn->d_tag)); 264 return (1); 265 } 266 posdyn = 0; 267 dyn++; 268 } 269 return (0); 270 } 271