17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*5aefb655Srie  * Common Development and Distribution License (the "License").
6*5aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*5aefb655Srie 
227c478bd9Sstevel@tonic-gate /*
23*5aefb655Srie  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  *
267c478bd9Sstevel@tonic-gate  * Update any dynamic entry offsets.  One issue with dynamic entries is that
277c478bd9Sstevel@tonic-gate  * you only know whether they refer to a value or an offset if you know each
287c478bd9Sstevel@tonic-gate  * type.  Thus we check for all types we know about, it a type is found that
297c478bd9Sstevel@tonic-gate  * we don't know about then return and error as we have no idea what to do.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include	<libelf.h>
347c478bd9Sstevel@tonic-gate #include	<link.h>
357c478bd9Sstevel@tonic-gate #include	"libld.h"
367c478bd9Sstevel@tonic-gate #include	"msg.h"
377c478bd9Sstevel@tonic-gate #include	"rtld.h"
387c478bd9Sstevel@tonic-gate #include	"_librtld.h"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate int
41*5aefb655Srie update_dynamic(Cache *cache, Cache *_cache, Rt_map *lmp, int flags,
427c478bd9Sstevel@tonic-gate     Addr addr, Off off, const char *file, Xword null, Xword data, Xword func,
437c478bd9Sstevel@tonic-gate     Xword entsize, Xword checksum)
447c478bd9Sstevel@tonic-gate {
45*5aefb655Srie 	Dyn		*dyn = (Dyn *)_cache->c_data->d_buf, *posdyn = 0;
467c478bd9Sstevel@tonic-gate 	const char	*strs;
47*5aefb655Srie 	Cache		*__cache;
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 	/*
507c478bd9Sstevel@tonic-gate 	 * If we're dealing with an object that might have bound to an external
517c478bd9Sstevel@tonic-gate 	 * dependency establish our string table for possible NEEDED processing.
527c478bd9Sstevel@tonic-gate 	 */
537c478bd9Sstevel@tonic-gate 	if (flags & RTLD_REL_DEPENDS) {
547c478bd9Sstevel@tonic-gate 		__cache = &cache[_cache->c_shdr->sh_link];
557c478bd9Sstevel@tonic-gate 		strs = (const char *)__cache->c_data->d_buf;
567c478bd9Sstevel@tonic-gate 	}
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	/*
597c478bd9Sstevel@tonic-gate 	 * Loop through the dynamic table updating all offsets.
607c478bd9Sstevel@tonic-gate 	 */
617c478bd9Sstevel@tonic-gate 	while (dyn->d_tag != DT_NULL) {
627c478bd9Sstevel@tonic-gate 		switch ((Xword)dyn->d_tag) {
637c478bd9Sstevel@tonic-gate 		case DT_NEEDED:
647c478bd9Sstevel@tonic-gate 			if (posdyn) {
65*5aefb655Srie 				Rt_map	*dlmp;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 				/*
687c478bd9Sstevel@tonic-gate 				 * Determine whether this dependency has been
697c478bd9Sstevel@tonic-gate 				 * loaded (this is the most generic way to check
707c478bd9Sstevel@tonic-gate 				 * any alias names), and if it has been bound
717c478bd9Sstevel@tonic-gate 				 * to, undo any lazy-loading position flag.
727c478bd9Sstevel@tonic-gate 				 */
737c478bd9Sstevel@tonic-gate 				if (dlmp = is_so_loaded(LIST(lmp),
747c478bd9Sstevel@tonic-gate 				    (strs + dyn->d_un.d_val), 1)) {
757c478bd9Sstevel@tonic-gate 					Bnd_desc **	bdpp;
767c478bd9Sstevel@tonic-gate 					Aliste		off;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 					for (ALIST_TRAVERSE(DEPENDS(lmp), off,
797c478bd9Sstevel@tonic-gate 					    bdpp)) {
807c478bd9Sstevel@tonic-gate 						if (dlmp == (*bdpp)->b_depend) {
817c478bd9Sstevel@tonic-gate 						    posdyn->d_un.d_val &=
827c478bd9Sstevel@tonic-gate 							~DF_P1_LAZYLOAD;
837c478bd9Sstevel@tonic-gate 						    break;
847c478bd9Sstevel@tonic-gate 						}
857c478bd9Sstevel@tonic-gate 					}
867c478bd9Sstevel@tonic-gate 				}
877c478bd9Sstevel@tonic-gate 			}
887c478bd9Sstevel@tonic-gate 			break;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 		case DT_RELAENT:
917c478bd9Sstevel@tonic-gate 		case DT_STRSZ:
927c478bd9Sstevel@tonic-gate 		case DT_SYMENT:
937c478bd9Sstevel@tonic-gate 		case DT_SONAME:
947c478bd9Sstevel@tonic-gate 		case DT_RPATH:
957c478bd9Sstevel@tonic-gate 		case DT_SYMBOLIC:
967c478bd9Sstevel@tonic-gate 		case DT_RELENT:
977c478bd9Sstevel@tonic-gate 		case DT_PLTREL:
987c478bd9Sstevel@tonic-gate 		case DT_TEXTREL:
997c478bd9Sstevel@tonic-gate 		case DT_VERDEFNUM:
1007c478bd9Sstevel@tonic-gate 		case DT_VERNEEDNUM:
1017c478bd9Sstevel@tonic-gate 		case DT_AUXILIARY:
1027c478bd9Sstevel@tonic-gate 		case DT_USED:
1037c478bd9Sstevel@tonic-gate 		case DT_FILTER:
1047c478bd9Sstevel@tonic-gate 		case DT_DEPRECATED_SPARC_REGISTER:
1057c478bd9Sstevel@tonic-gate 		case M_DT_REGISTER:
1067c478bd9Sstevel@tonic-gate 		case DT_BIND_NOW:
1077c478bd9Sstevel@tonic-gate 		case DT_INIT_ARRAYSZ:
1087c478bd9Sstevel@tonic-gate 		case DT_FINI_ARRAYSZ:
1097c478bd9Sstevel@tonic-gate 		case DT_RUNPATH:
1107c478bd9Sstevel@tonic-gate 		case DT_FLAGS:
1117c478bd9Sstevel@tonic-gate 		case DT_CONFIG:
1127c478bd9Sstevel@tonic-gate 		case DT_DEPAUDIT:
1137c478bd9Sstevel@tonic-gate 		case DT_AUDIT:
1147c478bd9Sstevel@tonic-gate 			break;
1157c478bd9Sstevel@tonic-gate 		case DT_PLTGOT:
1167c478bd9Sstevel@tonic-gate 		case DT_HASH:
1177c478bd9Sstevel@tonic-gate 		case DT_STRTAB:
1187c478bd9Sstevel@tonic-gate 		case DT_SYMTAB:
1197c478bd9Sstevel@tonic-gate 		case DT_INIT:
1207c478bd9Sstevel@tonic-gate 		case DT_FINI:
1217c478bd9Sstevel@tonic-gate 		case DT_VERSYM:
1227c478bd9Sstevel@tonic-gate 		case DT_VERDEF:
1237c478bd9Sstevel@tonic-gate 		case DT_VERNEED:
1247c478bd9Sstevel@tonic-gate 		case DT_INIT_ARRAY:
1257c478bd9Sstevel@tonic-gate 		case DT_FINI_ARRAY:
1267c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr += addr;
1277c478bd9Sstevel@tonic-gate 			break;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 		/*
1307c478bd9Sstevel@tonic-gate 		 * If the memory image is being used, this element would have
1317c478bd9Sstevel@tonic-gate 		 * been initialized to the runtime linkers internal link-map
1327c478bd9Sstevel@tonic-gate 		 * list.  Clear it.
1337c478bd9Sstevel@tonic-gate 		 */
1347c478bd9Sstevel@tonic-gate 		case DT_DEBUG:
1357c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = 0;
1367c478bd9Sstevel@tonic-gate 			break;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 		/*
1397c478bd9Sstevel@tonic-gate 		 * The number of relocations may have been reduced if
1407c478bd9Sstevel@tonic-gate 		 * relocations have been saved in the new image.  Thus we
1417c478bd9Sstevel@tonic-gate 		 * compute the new relocation size and start.
1427c478bd9Sstevel@tonic-gate 		 */
1437c478bd9Sstevel@tonic-gate 		case DT_RELASZ:
1447c478bd9Sstevel@tonic-gate 		case DT_RELSZ:
1457c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = ((data + func) * entsize);
1467c478bd9Sstevel@tonic-gate 			break;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 		case DT_RELA:
1497c478bd9Sstevel@tonic-gate 		case DT_REL:
1507c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = (addr + off + (null * entsize));
1517c478bd9Sstevel@tonic-gate 			break;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 		/*
1547c478bd9Sstevel@tonic-gate 		 * If relative relocations have been processed clear the count.
1557c478bd9Sstevel@tonic-gate 		 */
1567c478bd9Sstevel@tonic-gate 		case DT_RELACOUNT:
1577c478bd9Sstevel@tonic-gate 		case DT_RELCOUNT:
1587c478bd9Sstevel@tonic-gate 			if (flags & RTLD_REL_RELATIVE)
1597c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = 0;
1607c478bd9Sstevel@tonic-gate 			break;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 		case DT_PLTRELSZ:
1637c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = (func * entsize);
1647c478bd9Sstevel@tonic-gate 			break;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 		case DT_JMPREL:
1677c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = (addr + off +
1687c478bd9Sstevel@tonic-gate 				((null + data) * entsize));
1697c478bd9Sstevel@tonic-gate 			break;
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 		/*
1727c478bd9Sstevel@tonic-gate 		 * Recompute the images elf checksum.
1737c478bd9Sstevel@tonic-gate 		 */
1747c478bd9Sstevel@tonic-gate 		case DT_CHECKSUM:
1757c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = checksum;
1767c478bd9Sstevel@tonic-gate 			break;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 		/*
1797c478bd9Sstevel@tonic-gate 		 * If a flag entry is available, indicate if this image has
1807c478bd9Sstevel@tonic-gate 		 * been generated via the configuration process (crle(1)).
1817c478bd9Sstevel@tonic-gate 		 * Because we only started depositing DT_FLAGS_1 entries in all
1827c478bd9Sstevel@tonic-gate 		 * objects starting with Solaris 8, set a feature flag if it
1837c478bd9Sstevel@tonic-gate 		 * is present (these got added in Solaris 7).
1847c478bd9Sstevel@tonic-gate 		 * The runtime linker may use this flag to search for a local
1857c478bd9Sstevel@tonic-gate 		 * configuration file - this is only meaningful in executables
1867c478bd9Sstevel@tonic-gate 		 * but the flag has value for identifying images regardless.
1877c478bd9Sstevel@tonic-gate 		 *
1887c478bd9Sstevel@tonic-gate 		 * If this file is acting as a filter, and dependency
1897c478bd9Sstevel@tonic-gate 		 * relocations have been processed (a filter is thought of as a
1907c478bd9Sstevel@tonic-gate 		 * dependency in terms of symbol binding), we may have bound to
1917c478bd9Sstevel@tonic-gate 		 * the filtee, and hence carried out the relocation.  Indicate
1927c478bd9Sstevel@tonic-gate 		 * that the filtee must be preloaded, as the .plt won't get
1937c478bd9Sstevel@tonic-gate 		 * exercised to cause its normal loading.
1947c478bd9Sstevel@tonic-gate 		 */
1957c478bd9Sstevel@tonic-gate 		case DT_FLAGS_1:
1967c478bd9Sstevel@tonic-gate 			if (flags & RTLD_CONFSET)
1977c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val |= DF_1_CONFALT;
1987c478bd9Sstevel@tonic-gate 			if ((flags & RTLD_REL_DEPENDS) &&
1997c478bd9Sstevel@tonic-gate 			    (FLAGS1(lmp)) & MSK_RT_FILTER)
2007c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val |= DF_1_LOADFLTR;
2017c478bd9Sstevel@tonic-gate 			break;
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 		case DT_FEATURE_1:
2047c478bd9Sstevel@tonic-gate 			if (flags & RTLD_CONFSET)
2057c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val |= DTF_1_CONFEXP;
2067c478bd9Sstevel@tonic-gate 			break;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 		/*
2097c478bd9Sstevel@tonic-gate 		 * If a position flag is available save it for possible update
2107c478bd9Sstevel@tonic-gate 		 * when processing the next NEEDED tag.
2117c478bd9Sstevel@tonic-gate 		 */
2127c478bd9Sstevel@tonic-gate 		case DT_POSFLAG_1:
2137c478bd9Sstevel@tonic-gate 			if (flags & RTLD_REL_DEPENDS) {
2147c478bd9Sstevel@tonic-gate 				posdyn = dyn++;
2157c478bd9Sstevel@tonic-gate 				continue;
2167c478bd9Sstevel@tonic-gate 			}
2177c478bd9Sstevel@tonic-gate 			break;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 		/*
2207c478bd9Sstevel@tonic-gate 		 * Collect the defaults.
2217c478bd9Sstevel@tonic-gate 		 */
2227c478bd9Sstevel@tonic-gate 		default:
2237c478bd9Sstevel@tonic-gate 			/*
2247c478bd9Sstevel@tonic-gate 			 * If d_val is used, don't touch.
2257c478bd9Sstevel@tonic-gate 			 */
2267c478bd9Sstevel@tonic-gate 			if ((dyn->d_tag >= DT_VALRNGLO) &&
2277c478bd9Sstevel@tonic-gate 			    (dyn->d_tag <= DT_VALRNGHI))
2287c478bd9Sstevel@tonic-gate 				break;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 			/*
2317c478bd9Sstevel@tonic-gate 			 * If d_ptr is used, adjust.  Note, some entries that
2327c478bd9Sstevel@tonic-gate 			 * fell into this range are offsets into the dynamic
2337c478bd9Sstevel@tonic-gate 			 * string table.  Although these would need modifying
2347c478bd9Sstevel@tonic-gate 			 * if the section itself were resized, there is no
2357c478bd9Sstevel@tonic-gate 			 * resizing with dldump().  Entries that correspond to
2367c478bd9Sstevel@tonic-gate 			 * offsets are picked off in the initial DT_ loop
2377c478bd9Sstevel@tonic-gate 			 * above.
2387c478bd9Sstevel@tonic-gate 			 */
2397c478bd9Sstevel@tonic-gate 			if ((dyn->d_tag >= DT_ADDRRNGLO) &&
2407c478bd9Sstevel@tonic-gate 			    (dyn->d_tag <= DT_ADDRRNGHI)) {
2417c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr += addr;
2427c478bd9Sstevel@tonic-gate 				break;
2437c478bd9Sstevel@tonic-gate 			}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 			/*
2467c478bd9Sstevel@tonic-gate 			 * Check to see if this DT_ entry conforms
2477c478bd9Sstevel@tonic-gate 			 * to the DT_ENCODING rules.
2487c478bd9Sstevel@tonic-gate 			 */
2497c478bd9Sstevel@tonic-gate 			if ((dyn->d_tag >= DT_ENCODING) &&
2507c478bd9Sstevel@tonic-gate 			    (dyn->d_tag <= DT_HIOS)) {
2517c478bd9Sstevel@tonic-gate 				/*
2527c478bd9Sstevel@tonic-gate 				 * Even tag values are ADDRESS encodings
2537c478bd9Sstevel@tonic-gate 				 */
2547c478bd9Sstevel@tonic-gate 				if ((dyn->d_tag % 2) == 0) {
2557c478bd9Sstevel@tonic-gate 					dyn->d_un.d_ptr += addr;
2567c478bd9Sstevel@tonic-gate 				}
2577c478bd9Sstevel@tonic-gate 				break;
2587c478bd9Sstevel@tonic-gate 			}
259*5aefb655Srie 			eprintf(LIST(lmp), ERR_WARNING,
260*5aefb655Srie 			    MSG_INTL(MSG_DT_UNKNOWN), file,
2617c478bd9Sstevel@tonic-gate 			    EC_XWORD(dyn->d_tag));
2627c478bd9Sstevel@tonic-gate 			return (1);
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 		posdyn = 0;
2657c478bd9Sstevel@tonic-gate 		dyn++;
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 	return (0);
2687c478bd9Sstevel@tonic-gate }
269