Home | History | Annotate | Download | only in common
      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 2008 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), NULL)) {
     75 					Bnd_desc	*bdp;
     76 					Aliste		idx;
     77 
     78 					for (APLIST_TRAVERSE(DEPENDS(lmp), idx,
     79 					    bdp)) {
     80 						if (dlmp == bdp->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