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