xref: /illumos-gate/usr/src/cmd/sgs/libld/common/version.c (revision 96b6509c)
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 (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include	<string.h>
27 #include	<stdio.h>
28 #include	<debug.h>
29 #include	"msg.h"
30 #include	"_libld.h"
31 
32 /*
33  * Locate a version descriptor.
34  */
35 Ver_desc *
ld_vers_find(const char * name,Word hash,APlist * alp)36 ld_vers_find(const char *name, Word hash, APlist *alp)
37 {
38 	Aliste		idx;
39 	Ver_desc	*vdp;
40 
41 	for (APLIST_TRAVERSE(alp, idx, vdp)) {
42 		if (vdp->vd_hash != hash)
43 			continue;
44 		if (strcmp(vdp->vd_name, name) == 0)
45 			return (vdp);
46 	}
47 	return (NULL);
48 }
49 
50 /*
51  * Add a new version descriptor to a version descriptor list.  Note, users of
52  * this are responsible for determining if the version descriptor already
53  * exists (this can reduce the need to allocate storage for descriptor names
54  * until it is determined a descriptor need be created (see map_symbol())).
55  */
56 Ver_desc *
ld_vers_desc(const char * name,Word hash,APlist ** alpp)57 ld_vers_desc(const char *name, Word hash, APlist **alpp)
58 {
59 	Ver_desc	*vdp;
60 
61 	if ((vdp = libld_calloc(sizeof (Ver_desc), 1)) == NULL)
62 		return ((Ver_desc *)S_ERROR);
63 
64 	vdp->vd_name = name;
65 	vdp->vd_hash = hash;
66 
67 	if (aplist_append(alpp, vdp, AL_CNT_VERDESCS) == NULL)
68 		return ((Ver_desc *)S_ERROR);
69 
70 	return (vdp);
71 }
72 
73 /*
74  * Now that all explict files have been processed validate any version
75  * definitions.  Insure that any version references are available (a version
76  * has been defined when it's been assigned an index).  Also calculate the
77  * number of .version section entries that will be required to hold this
78  * information.
79  */
80 #define	_NUM_OF_VERS_	40	/* twice as big as the depth for libc version */
81 typedef struct {
82 	Ver_desc	**ver_stk;
83 	int 		ver_sp;
84 	int 		ver_lmt;
85 } Ver_Stack;
86 
87 static uintptr_t
vers_visit_children(Ofl_desc * ofl,Ver_desc * vp,int flag)88 vers_visit_children(Ofl_desc *ofl, Ver_desc *vp, int flag)
89 {
90 	Aliste			idx;
91 	Ver_desc		*vdp;
92 	static int		err = 0;
93 	static Ver_Stack	ver_stk = {0, 0, 0};
94 	int			tmp_sp;
95 
96 	/*
97 	 * If there was any fatal error,
98 	 * just return.
99 	 */
100 	if (err == S_ERROR)
101 		return (err);
102 
103 	/*
104 	 * if this is called from, ver_check_defs(), initialize sp.
105 	 */
106 	if (flag == 0)
107 		ver_stk.ver_sp = 0;
108 
109 	/*
110 	 * Check if passed version pointer vp is already in the stack.
111 	 */
112 	for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) {
113 		Ver_desc *v;
114 
115 		v = ver_stk.ver_stk[tmp_sp];
116 		if (v == vp) {
117 			/*
118 			 * cyclic dependency.
119 			 */
120 			if (err == 0) {
121 				ld_eprintf(ofl, ERR_FATAL,
122 				    MSG_INTL(MSG_VER_CYCLIC));
123 				err = 1;
124 			}
125 			for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) {
126 				v = ver_stk.ver_stk[tmp_sp];
127 				if ((v->vd_flags & FLG_VER_CYCLIC) == 0) {
128 					v->vd_flags |= FLG_VER_CYCLIC;
129 					ld_eprintf(ofl, ERR_NONE,
130 					    MSG_INTL(MSG_VER_ADDVER),
131 					    v->vd_name);
132 				}
133 			}
134 			if ((vp->vd_flags & FLG_VER_CYCLIC) == 0) {
135 				vp->vd_flags |= FLG_VER_CYCLIC;
136 				ld_eprintf(ofl, ERR_NONE,
137 				    MSG_INTL(MSG_VER_ADDVER), vp->vd_name);
138 			}
139 			return (err);
140 		}
141 	}
142 
143 	/*
144 	 * Push version on the stack.
145 	 */
146 	if (ver_stk.ver_sp >= ver_stk.ver_lmt) {
147 		ver_stk.ver_lmt += _NUM_OF_VERS_;
148 		if ((ver_stk.ver_stk = (Ver_desc **)
149 		    libld_realloc((void *)ver_stk.ver_stk,
150 		    ver_stk.ver_lmt * sizeof (Ver_desc *))) == NULL)
151 			return (S_ERROR);
152 	}
153 	ver_stk.ver_stk[(ver_stk.ver_sp)++] = vp;
154 
155 	/*
156 	 * Now visit children.
157 	 */
158 	for (APLIST_TRAVERSE(vp->vd_deps, idx, vdp))
159 		if (vers_visit_children(ofl, vdp, 1) == S_ERROR)
160 			return (S_ERROR);
161 
162 	/*
163 	 * Pop version from the stack.
164 	 */
165 	(ver_stk.ver_sp)--;
166 
167 	return (err);
168 }
169 
170 uintptr_t
ld_vers_check_defs(Ofl_desc * ofl)171 ld_vers_check_defs(Ofl_desc *ofl)
172 {
173 	Aliste		idx1;
174 	Ver_desc	*vdp;
175 	uintptr_t 	is_cyclic = 0;
176 
177 	DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, ofl->ofl_name));
178 
179 	/*
180 	 * First check if there are any cyclic dependency
181 	 */
182 	for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp))
183 		if ((is_cyclic = vers_visit_children(ofl, vdp, 0)) == S_ERROR)
184 			return (S_ERROR);
185 
186 	if (is_cyclic)
187 		ofl->ofl_flags |= FLG_OF_FATAL;
188 
189 	for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) {
190 		Byte		cnt;
191 		Sym		*sym;
192 		Sym_desc	*sdp;
193 		const char	*name = vdp->vd_name;
194 		uchar_t		bind;
195 		Ver_desc	*_vdp __unused;
196 		avl_index_t	where;
197 		Aliste		idx2;
198 
199 		if (vdp->vd_ndx == 0) {
200 			ld_eprintf(ofl, ERR_FATAL,
201 			    MSG_INTL(MSG_VER_UNDEF), name, vdp->vd_ref->vd_name,
202 			    vdp->vd_ref->vd_file->ifl_name);
203 			continue;
204 		}
205 
206 		DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, vdp));
207 
208 		/*
209 		 * If a version definition contains no symbols this is possibly
210 		 * a mapfile error.
211 		 */
212 		if ((vdp->vd_flags &
213 		    (VER_FLG_BASE | VER_FLG_WEAK | FLG_VER_REFER)) == 0)
214 			DBG_CALL(Dbg_ver_nointerface(ofl->ofl_lml,
215 			    vdp->vd_name));
216 
217 		/*
218 		 * Update the version entry count to account for this new
219 		 * version descriptor (the count is the size in bytes).
220 		 */
221 		ofl->ofl_verdefsz += sizeof (Verdef);
222 
223 		/*
224 		 * Traverse this versions dependency list to determine what
225 		 * additional version dependencies we must account for against
226 		 * this descriptor.
227 		 */
228 		cnt = 1;
229 		for (APLIST_TRAVERSE(vdp->vd_deps, idx2, _vdp)) {
230 #if	defined(__lint)
231 			/* get lint to think `_vdp' is used... */
232 			vdp = _vdp;
233 #endif
234 			cnt++;
235 		}
236 		ofl->ofl_verdefsz += (cnt * sizeof (Verdaux));
237 
238 		/*
239 		 * Except for the base version descriptor, generate an absolute
240 		 * symbol to reflect this version.
241 		 */
242 		if (vdp->vd_flags & VER_FLG_BASE)
243 			continue;
244 
245 		if (vdp->vd_flags & VER_FLG_WEAK)
246 			bind = STB_WEAK;
247 		else
248 			bind = STB_GLOBAL;
249 
250 		if (sdp = ld_sym_find(name, vdp->vd_hash, &where, ofl)) {
251 			/*
252 			 * If the symbol already exists and is undefined or was
253 			 * defined in a shared library, convert it to an
254 			 * absolute.
255 			 */
256 			if ((sdp->sd_sym->st_shndx == SHN_UNDEF) ||
257 			    (sdp->sd_ref != REF_REL_NEED)) {
258 				sdp->sd_shndx = sdp->sd_sym->st_shndx = SHN_ABS;
259 				sdp->sd_sym->st_info =
260 				    ELF_ST_INFO(bind, STT_OBJECT);
261 				sdp->sd_ref = REF_REL_NEED;
262 				sdp->sd_flags |= (FLG_SY_SPECSEC |
263 				    FLG_SY_DEFAULT | FLG_SY_EXPDEF);
264 				sdp->sd_aux->sa_overndx = vdp->vd_ndx;
265 
266 				/*
267 				 * If the reference originated from a mapfile
268 				 * insure we mark the symbol as used.
269 				 */
270 				if (sdp->sd_flags & FLG_SY_MAPREF)
271 					sdp->sd_flags |= FLG_SY_MAPUSED;
272 
273 			} else if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
274 			    (sdp->sd_sym->st_shndx != SHN_ABS) &&
275 			    (sdp->sd_ref == REF_REL_NEED)) {
276 				ld_eprintf(ofl, ERR_WARNING,
277 				    MSG_INTL(MSG_VER_DEFINED), name,
278 				    sdp->sd_file->ifl_name);
279 			}
280 		} else {
281 			/*
282 			 * If the symbol does not exist create it.
283 			 */
284 			if ((sym = libld_calloc(sizeof (Sym), 1)) == NULL)
285 				return (S_ERROR);
286 
287 			sym->st_shndx = SHN_ABS;
288 			sym->st_info = ELF_ST_INFO(bind, STT_OBJECT);
289 			DBG_CALL(Dbg_ver_symbol(ofl->ofl_lml, name));
290 
291 			if ((sdp = ld_sym_enter(name, sym, vdp->vd_hash,
292 			    vdp->vd_file, ofl, 0, SHN_ABS,
293 			    (FLG_SY_SPECSEC | FLG_SY_DEFAULT | FLG_SY_EXPDEF),
294 			    &where)) == (Sym_desc *)S_ERROR)
295 				return (S_ERROR);
296 
297 			sdp->sd_ref = REF_REL_NEED;
298 			sdp->sd_aux->sa_overndx = vdp->vd_ndx;
299 		}
300 	}
301 	return (1);
302 }
303 
304 /*
305  * Dereference dependencies as a part of normalizing (allows recursion).
306  */
307 static void
vers_derefer(Ifl_desc * ifl,Ver_desc * vdp,int weak)308 vers_derefer(Ifl_desc *ifl, Ver_desc *vdp, int weak)
309 {
310 	Aliste		idx;
311 	Ver_desc	*_vdp;
312 	Ver_index	*vip = &ifl->ifl_verndx[vdp->vd_ndx];
313 
314 	/*
315 	 * Set the INFO bit on all dependencies that ld.so.1
316 	 * can skip verification for. These are the dependencies
317 	 * that are inherited by others -- verifying the inheriting
318 	 * version implicitily covers this one.
319 	 *
320 	 * If the head of the list was a weak then we only mark
321 	 * weak dependencies, but if the head of the list was 'strong'
322 	 * we set INFO on all dependencies.
323 	 */
324 	if ((weak && (vdp->vd_flags & VER_FLG_WEAK)) || (!weak))
325 		vip->vi_flags |= VER_FLG_INFO;
326 
327 	for (APLIST_TRAVERSE(vdp->vd_deps, idx, _vdp))
328 		vers_derefer(ifl, _vdp, weak);
329 }
330 
331 /*
332  * If we need to record the versions of any needed dependencies traverse the
333  * shared object dependency list and calculate what version needed entries are
334  * required.
335  */
336 uintptr_t
ld_vers_check_need(Ofl_desc * ofl)337 ld_vers_check_need(Ofl_desc *ofl)
338 {
339 	Aliste		idx1;
340 	Ifl_desc	*ifl;
341 	Half		needndx;
342 	Str_tbl		*strtbl;
343 
344 
345 	/*
346 	 * Determine which string table is appropriate.
347 	 */
348 	strtbl = (OFL_IS_STATIC_OBJ(ofl)) ? ofl->ofl_strtab :
349 	    ofl->ofl_dynstrtab;
350 
351 	/*
352 	 * Versym indexes for needed versions start with the next
353 	 * available version after the final definied version.
354 	 * However, it can never be less than 2. 0 is always for local
355 	 * scope, and 1 is always the first global definition.
356 	 */
357 	needndx = (ofl->ofl_vercnt > 0) ? (ofl->ofl_vercnt + 1) : 2;
358 
359 	/*
360 	 * Traverse the shared object list looking for dependencies.
361 	 */
362 	for (APLIST_TRAVERSE(ofl->ofl_sos, idx1, ifl)) {
363 		Aliste		idx2;
364 		Ver_index	*vip;
365 		Ver_desc	*vdp;
366 		Byte		cnt, need = 0;
367 
368 		if (!(ifl->ifl_flags & FLG_IF_NEEDED))
369 			continue;
370 
371 		if (ifl->ifl_vercnt <= VER_NDX_GLOBAL)
372 			continue;
373 
374 		/*
375 		 * Scan the version index list and if any weak version
376 		 * definition has been referenced by the user promote the
377 		 * dependency to be non-weak.  Weak version dependencies do not
378 		 * cause fatal errors from the runtime linker, non-weak
379 		 * dependencies do.
380 		 */
381 		for (cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) {
382 			vip = &ifl->ifl_verndx[cnt];
383 			vdp = vip->vi_desc;
384 
385 			if ((vip->vi_flags & (FLG_VER_REFER | VER_FLG_WEAK)) ==
386 			    (FLG_VER_REFER | VER_FLG_WEAK))
387 				vdp->vd_flags &= ~VER_FLG_WEAK;
388 
389 			/*
390 			 * Mark any weak reference as referred to so as to
391 			 * simplify normalization and later version dependency
392 			 * manipulation.
393 			 */
394 			if (vip->vi_flags & VER_FLG_WEAK)
395 				vip->vi_flags |= FLG_VER_REFER;
396 		}
397 
398 		/*
399 		 * Scan the version dependency list to normalize the referenced
400 		 * dependencies.  Any needed version that is inherited by
401 		 * another like version is dereferenced as it is not necessary
402 		 * to make this part of the version dependencies.
403 		 */
404 		for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx2, vdp)) {
405 			Aliste		idx3;
406 			Ver_desc	*_vdp;
407 			int		type;
408 
409 			vip = &ifl->ifl_verndx[vdp->vd_ndx];
410 
411 			if (!(vip->vi_flags & FLG_VER_REFER))
412 				continue;
413 
414 			type = vdp->vd_flags & VER_FLG_WEAK;
415 			for (APLIST_TRAVERSE(vdp->vd_deps, idx3, _vdp))
416 				vers_derefer(ifl, _vdp, type);
417 		}
418 
419 		/*
420 		 * Finally, determine how many of the version dependencies need
421 		 * to be recorded.
422 		 */
423 		for (cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) {
424 			vip = &ifl->ifl_verndx[cnt];
425 
426 			/*
427 			 * If a version has been referenced then record it as a
428 			 * version dependency.
429 			 */
430 			if (vip->vi_flags & FLG_VER_REFER) {
431 				/* Assign a VERSYM index for it */
432 				vip->vi_overndx = needndx++;
433 
434 				ofl->ofl_verneedsz += sizeof (Vernaux);
435 				if (st_insert(strtbl, vip->vi_name) == -1)
436 					return (S_ERROR);
437 				need++;
438 			}
439 		}
440 
441 		if (need) {
442 			ifl->ifl_flags |= FLG_IF_VERNEED;
443 			ofl->ofl_verneedsz += sizeof (Verneed);
444 			if (st_insert(strtbl, ifl->ifl_soname) == -1)
445 				return (S_ERROR);
446 		}
447 	}
448 
449 	/*
450 	 * If no version needed information is required unset the output file
451 	 * flag.
452 	 */
453 	if (ofl->ofl_verneedsz == 0)
454 		ofl->ofl_flags &= ~FLG_OF_VERNEED;
455 
456 	return (1);
457 }
458 
459 /*
460  * Indicate dependency selection (allows recursion).
461  */
462 static void
vers_select(Ofl_desc * ofl,Ifl_desc * ifl,Ver_desc * vdp,const char * ref)463 vers_select(Ofl_desc *ofl, Ifl_desc *ifl, Ver_desc *vdp, const char *ref)
464 {
465 	Aliste		idx;
466 	Ver_desc	*_vdp;
467 	Ver_index	*vip = &ifl->ifl_verndx[vdp->vd_ndx];
468 
469 	vip->vi_flags |= FLG_VER_AVAIL;
470 	DBG_CALL(Dbg_ver_avail_entry(ofl->ofl_lml, vip, ref));
471 
472 	for (APLIST_TRAVERSE(vdp->vd_deps, idx, _vdp))
473 		vers_select(ofl, ifl, _vdp, ref);
474 }
475 
476 static Ver_index *
vers_index(Ofl_desc * ofl,Ifl_desc * ifl,int avail)477 vers_index(Ofl_desc *ofl, Ifl_desc *ifl, int avail)
478 {
479 	Aliste		idx1;
480 	Ver_desc	*vdp;
481 	Ver_index	*vip;
482 	Sdf_desc	*sdf = ifl->ifl_sdfdesc;
483 	Word		count = ifl->ifl_vercnt;
484 	Sdv_desc	*sdv;
485 
486 	/*
487 	 * Allocate an index array large enough to hold all of the files
488 	 * version descriptors.
489 	 */
490 	if ((vip = libld_calloc(sizeof (Ver_index), (count + 1))) == NULL)
491 		return ((Ver_index *)S_ERROR);
492 
493 	for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx1, vdp)) {
494 		int	ndx = vdp->vd_ndx;
495 
496 		vip[ndx].vi_name = vdp->vd_name;
497 		vip[ndx].vi_desc = vdp;
498 
499 		/*
500 		 * Any relocatable object versions, and the `base' version are
501 		 * always available.
502 		 */
503 		if (avail || (vdp->vd_flags & VER_FLG_BASE))
504 			vip[ndx].vi_flags |= FLG_VER_AVAIL;
505 
506 		/*
507 		 * If this is a weak version mark it as such.  Weak versions
508 		 * are always dragged into any version dependencies created,
509 		 * and if a weak version is referenced it will be promoted to
510 		 * a non-weak version dependency.
511 		 */
512 		if (vdp->vd_flags & VER_FLG_WEAK)
513 			vip[ndx].vi_flags |= VER_FLG_WEAK;
514 		/*
515 		 * If this version is mentioned in a mapfile using ADDVERS
516 		 * syntax then check to see if it corresponds to an actual
517 		 * version in the file.
518 		 */
519 		if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) {
520 			Aliste	idx2;
521 
522 			for (ALIST_TRAVERSE(sdf->sdf_verneed, idx2, sdv)) {
523 				if (strcmp(vip[ndx].vi_name, sdv->sdv_name))
524 					continue;
525 
526 				vip[ndx].vi_flags |= FLG_VER_REFER;
527 				sdv->sdv_flags |= FLG_SDV_MATCHED;
528 				break;
529 			}
530 		}
531 	}
532 
533 	/*
534 	 * if $ADDVER was specified for this object verify that
535 	 * all of it's dependent upon versions were refered to.
536 	 */
537 	if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) {
538 		int	fail = 0;
539 
540 		for (ALIST_TRAVERSE(sdf->sdf_verneed, idx1, sdv)) {
541 			if (sdv->sdv_flags & FLG_SDV_MATCHED)
542 				continue;
543 
544 			if (fail++ == 0) {
545 				ld_eprintf(ofl, ERR_NONE,
546 				    MSG_INTL(MSG_VER_ADDVERS), sdf->sdf_rfile,
547 				    sdf->sdf_name);
548 			}
549 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_VER_ADDVER),
550 			    sdv->sdv_name);
551 		}
552 		if (fail)
553 			return ((Ver_index *)S_ERROR);
554 	}
555 
556 	return (vip);
557 }
558 
559 /*
560  * Process a version symbol index section.
561  */
562 int
ld_vers_sym_process(Ofl_desc * ofl,Is_desc * isp,Ifl_desc * ifl)563 ld_vers_sym_process(Ofl_desc *ofl, Is_desc *isp, Ifl_desc *ifl)
564 {
565 	Shdr	*symshdr;
566 	Shdr	*vershdr = isp->is_shdr;
567 
568 	/*
569 	 * Verify that the versym is the same size as the linked symbol table.
570 	 * If these two get out of sync the file is considered corrupted.
571 	 */
572 	symshdr = ifl->ifl_isdesc[vershdr->sh_link]->is_shdr;
573 	if ((symshdr->sh_size / symshdr->sh_entsize) != (vershdr->sh_size /
574 	    vershdr->sh_entsize)) {
575 		Is_desc	*sym_isp = ifl->ifl_isdesc[vershdr->sh_link];
576 
577 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ELF_VERSYM),
578 		    ifl->ifl_name, EC_WORD(isp->is_scnndx), isp->is_name,
579 		    EC_WORD(vershdr->sh_size / vershdr->sh_entsize),
580 		    EC_WORD(sym_isp->is_scnndx), sym_isp->is_name,
581 		    EC_WORD(symshdr->sh_size / symshdr->sh_entsize));
582 		return (1);
583 	}
584 	ifl->ifl_versym = (Versym *)isp->is_indata->d_buf;
585 	return (1);
586 }
587 
588 /*
589  * Process a version definition section from an input file.  A list of version
590  * descriptors is created and associated with the input files descriptor.  If
591  * this is a shared object these descriptors will be used to indicate the
592  * availability of each version.  If this is a relocatable object then these
593  * descriptors will be promoted (concatenated) to the output files image.
594  */
595 uintptr_t
ld_vers_def_process(Is_desc * isp,Ifl_desc * ifl,Ofl_desc * ofl)596 ld_vers_def_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl)
597 {
598 	const char	*str, *file = ifl->ifl_name;
599 	Sdf_desc	*sdf = ifl->ifl_sdfdesc;
600 	Sdv_desc	*sdv;
601 	Word		num, _num;
602 	Verdef		*vdf;
603 	int		relobj;
604 
605 	/*
606 	 * If there is no version section then simply indicate that all version
607 	 * definitions asked for do not exist.
608 	 */
609 	if (isp == NULL) {
610 		Aliste	idx;
611 
612 		for (ALIST_TRAVERSE(sdf->sdf_vers, idx, sdv)) {
613 			ld_eprintf(ofl, ERR_FATAL,
614 			    MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
615 			    sdv->sdv_name, sdv->sdv_ref);
616 		}
617 		return (0);
618 	}
619 
620 	vdf = (Verdef *)isp->is_indata->d_buf;
621 
622 	/*
623 	 * Verify the version revision.  We only check the first version
624 	 * structure as it is assumed all other version structures in this
625 	 * data section will be of the same revision.
626 	 */
627 	if (vdf->vd_version > VER_DEF_CURRENT)
628 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_VER_HIGHER),
629 		    ifl->ifl_name, vdf->vd_version, VER_DEF_CURRENT);
630 
631 
632 	num = isp->is_shdr->sh_info;
633 	str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf;
634 
635 	if (ifl->ifl_ehdr->e_type == ET_REL)
636 		relobj = 1;
637 	else
638 		relobj = 0;
639 
640 	DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, file));
641 
642 	/*
643 	 * Loop through the version information setting up a version descriptor
644 	 * for each version definition.
645 	 */
646 	for (_num = 1; _num <= num; _num++,
647 	    vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) {
648 		const char	*name;
649 		Ver_desc	*ivdp, *ovdp = NULL;
650 		Word		hash;
651 		Half 		cnt = vdf->vd_cnt;
652 		Half		ndx = vdf->vd_ndx;
653 		Verdaux		*vdap = (Verdaux *)((uintptr_t)vdf +
654 		    vdf->vd_aux);
655 
656 		/*
657 		 * Keep track of the largest index for use in creating a
658 		 * version index array later, and create a version descriptor.
659 		 */
660 		if (ndx > ifl->ifl_vercnt)
661 			ifl->ifl_vercnt = ndx;
662 
663 		name = (char *)(str + vdap->vda_name);
664 		/* LINTED */
665 		hash = (Word)elf_hash(name);
666 		if (((ivdp = ld_vers_find(name, hash,
667 		    ifl->ifl_verdesc)) == NULL) &&
668 		    ((ivdp = ld_vers_desc(name, hash,
669 		    &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR))
670 			return (S_ERROR);
671 
672 		ivdp->vd_ndx = ndx;
673 		ivdp->vd_file = ifl;
674 		ivdp->vd_flags = vdf->vd_flags;
675 
676 		/*
677 		 * If we're processing a relocatable object then this version
678 		 * definition needs to be propagated to the output file.
679 		 * Generate a new output file version and associated this input
680 		 * version to it.  During symbol processing the version index of
681 		 * the symbol will be promoted from the input file to the output
682 		 * files version definition.
683 		 */
684 		if (relobj) {
685 			if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
686 				ofl->ofl_flags |= FLG_OF_PROCRED;
687 
688 			if ((ivdp->vd_flags & VER_FLG_BASE) == 0) {
689 				/*
690 				 * If no version descriptors have yet been set
691 				 * up, initialize a base version to represent
692 				 * the output file itself.  This `base' version
693 				 * catches any internally generated symbols
694 				 * (_end, _etext, etc.) and
695 				 * serves to initialize the output version
696 				 * descriptor count.
697 				 */
698 				if (ofl->ofl_vercnt == 0) {
699 					if (ld_vers_base(ofl) ==
700 					    (Ver_desc *)S_ERROR)
701 						return (S_ERROR);
702 				}
703 				ofl->ofl_flags |= FLG_OF_VERDEF;
704 				if ((ovdp = ld_vers_find(name, hash,
705 				    ofl->ofl_verdesc)) == NULL) {
706 					if ((ovdp = ld_vers_desc(name, hash,
707 					    &ofl->ofl_verdesc)) ==
708 					    (Ver_desc *)S_ERROR)
709 						return (S_ERROR);
710 
711 					/* LINTED */
712 					ovdp->vd_ndx = (Half)++ofl->ofl_vercnt;
713 					ovdp->vd_file = ifl;
714 					ovdp->vd_flags = vdf->vd_flags;
715 				}
716 			}
717 
718 			/*
719 			 * Maintain the association between the input version
720 			 * descriptor and the output version descriptor so that
721 			 * an associated symbols will be assigned to the
722 			 * correct version.
723 			 */
724 			ivdp->vd_ref = ovdp;
725 		}
726 
727 		/*
728 		 * Process any dependencies this version may have.
729 		 */
730 		vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
731 		for (cnt--; cnt; cnt--,
732 		    vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next)) {
733 			Ver_desc	*_ivdp;
734 
735 			name = (char *)(str + vdap->vda_name);
736 			/* LINTED */
737 			hash = (Word)elf_hash(name);
738 
739 			if (((_ivdp = ld_vers_find(name, hash,
740 			    ifl->ifl_verdesc)) == NULL) &&
741 			    ((_ivdp = ld_vers_desc(name, hash,
742 			    &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR))
743 				return (S_ERROR);
744 
745 			if (aplist_append(&ivdp->vd_deps, _ivdp,
746 			    AL_CNT_VERDESCS) == NULL)
747 				return (S_ERROR);
748 		}
749 		DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, ivdp));
750 	}
751 
752 	/*
753 	 * Now that we know the total number of version definitions for this
754 	 * file, build an index array for fast access when processing symbols.
755 	 */
756 	if ((ifl->ifl_verndx =
757 	    vers_index(ofl, ifl, relobj)) == (Ver_index *)S_ERROR)
758 		return (S_ERROR);
759 
760 	if (relobj)
761 		return (1);
762 
763 	/*
764 	 * If this object has version control definitions against it then these
765 	 * must be processed so as to select those version definitions to which
766 	 * symbol bindings can occur.  Otherwise simply mark all versions as
767 	 * available.
768 	 */
769 	DBG_CALL(Dbg_ver_avail_title(ofl->ofl_lml, file));
770 
771 	if (sdf && (sdf->sdf_flags & FLG_SDF_SELECT)) {
772 		Aliste	idx1;
773 
774 		for (ALIST_TRAVERSE(sdf->sdf_vers, idx1, sdv)) {
775 			Aliste		idx2;
776 			Ver_desc	*vdp;
777 			int		found = 0;
778 
779 			for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx2, vdp)) {
780 				if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) {
781 					found++;
782 					break;
783 				}
784 			}
785 			if (found)
786 				vers_select(ofl, ifl, vdp, sdv->sdv_ref);
787 			else
788 				ld_eprintf(ofl, ERR_FATAL,
789 				    MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
790 				    sdv->sdv_name, sdv->sdv_ref);
791 		}
792 	} else {
793 		Ver_index	*vip;
794 		int		cnt;
795 
796 		for (cnt = VER_NDX_GLOBAL; cnt <= ifl->ifl_vercnt; cnt++) {
797 			vip = &ifl->ifl_verndx[cnt];
798 			vip->vi_flags |= FLG_VER_AVAIL;
799 			DBG_CALL(Dbg_ver_avail_entry(ofl->ofl_lml, vip, 0));
800 		}
801 	}
802 
803 	/*
804 	 * If this is an explict dependency indicate that this file is a
805 	 * candidate for requiring version needed information to be recorded in
806 	 * the image we're creating.
807 	 */
808 	if (ifl->ifl_flags & FLG_IF_NEEDED)
809 		ofl->ofl_flags |= FLG_OF_VERNEED;
810 
811 	return (1);
812 }
813 
814 /*
815  * Process a version needed section.
816  */
817 uintptr_t
ld_vers_need_process(Is_desc * isp,Ifl_desc * ifl,Ofl_desc * ofl)818 ld_vers_need_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl)
819 {
820 	const char	*str, *file = ifl->ifl_name;
821 	Word		num, _num;
822 	Verneed		*vnd;
823 
824 	vnd = (Verneed *)isp->is_indata->d_buf;
825 
826 	/*
827 	 * Verify the version revision.  We only check the first version
828 	 * structure as it is assumed all other version structures in this
829 	 * data section will be of the same revision.
830 	 */
831 	if (vnd->vn_version > VER_DEF_CURRENT) {
832 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_VER_HIGHER),
833 		    ifl->ifl_name, vnd->vn_version, VER_DEF_CURRENT);
834 	}
835 
836 	num = isp->is_shdr->sh_info;
837 	str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf;
838 
839 	DBG_CALL(Dbg_ver_need_title(ofl->ofl_lml, file));
840 
841 	/*
842 	 * Loop through the version information setting up a version descriptor
843 	 * for each version definition.
844 	 */
845 	for (_num = 1; _num <= num; _num++,
846 	    vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
847 		Sdf_desc	*sdf;
848 		const char	*name;
849 		Half		cnt = vnd->vn_cnt;
850 		Vernaux		*vnap = (Vernaux *)((uintptr_t)vnd +
851 		    vnd->vn_aux);
852 		Half		_cnt;
853 
854 		name = (char *)(str + vnd->vn_file);
855 
856 		/*
857 		 * Set up a shared object descriptor and add to it the necessary
858 		 * needed versions.  This information may also have been added
859 		 * by a mapfile (see map_dash()).
860 		 */
861 		if ((sdf = sdf_find(name, ofl->ofl_soneed)) == NULL) {
862 			if ((sdf = sdf_add(name, &ofl->ofl_soneed)) ==
863 			    (Sdf_desc *)S_ERROR)
864 				return (S_ERROR);
865 			sdf->sdf_rfile = file;
866 			sdf->sdf_flags |= FLG_SDF_VERIFY;
867 		}
868 
869 		for (_cnt = 0; cnt; _cnt++, cnt--,
870 		    vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next)) {
871 			Sdv_desc	sdv;
872 
873 			sdv.sdv_name = str + vnap->vna_name;
874 			sdv.sdv_ref = file;
875 			sdv.sdv_flags = 0;
876 
877 			if (alist_append(&sdf->sdf_vers, &sdv,
878 			    sizeof (Sdv_desc), AL_CNT_SDF_VERSIONS) == NULL)
879 				return (S_ERROR);
880 
881 			DBG_CALL(Dbg_ver_need_entry(ofl->ofl_lml, _cnt, name,
882 			    sdv.sdv_name));
883 		}
884 	}
885 	return (1);
886 }
887 
888 /*
889  * If a symbol is obtained from a versioned relocatable object then the symbols
890  * version association must be promoted to the version definition as it will be
891  * represented in the output file.
892  */
893 void
ld_vers_promote(Sym_desc * sdp,Word ndx,Ifl_desc * ifl,Ofl_desc * ofl)894 ld_vers_promote(Sym_desc *sdp, Word ndx, Ifl_desc *ifl, Ofl_desc *ofl)
895 {
896 	Half 	vndx;
897 
898 	/*
899 	 * A version symbol index of 0 implies the symbol is local.  A value of
900 	 * VER_NDX_GLOBAL implies the symbol is global but has not been
901 	 * assigned to a specfic version definition.
902 	 */
903 	vndx = ifl->ifl_versym[ndx];
904 	if (vndx == 0) {
905 		sdp->sd_flags |= (FLG_SY_REDUCED | FLG_SY_HIDDEN);
906 		return;
907 	}
908 
909 	if (vndx == VER_NDX_ELIMINATE) {
910 		sdp->sd_flags |= (FLG_SY_REDUCED | FLG_SY_HIDDEN | FLG_SY_ELIM);
911 		return;
912 	}
913 
914 	if (vndx == VER_NDX_GLOBAL) {
915 		if (!SYM_IS_HIDDEN(sdp))
916 			sdp->sd_flags |= (FLG_SY_DEFAULT | FLG_SY_EXPDEF);
917 		if (sdp->sd_aux->sa_overndx <= VER_NDX_GLOBAL)
918 			sdp->sd_aux->sa_overndx = VER_NDX_GLOBAL;
919 		return;
920 	}
921 
922 	/*
923 	 * Any other version index requires association to the appropriate
924 	 * version definition.
925 	 */
926 	if ((ifl->ifl_verndx == 0) || (vndx > ifl->ifl_vercnt)) {
927 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_VER_INVALNDX),
928 		    sdp->sd_name, ifl->ifl_name, vndx);
929 		return;
930 	}
931 
932 	if (!SYM_IS_HIDDEN(sdp))
933 		sdp->sd_flags |= (FLG_SY_DEFAULT | FLG_SY_EXPDEF);
934 
935 	/*
936 	 * Promote the symbols version index to the appropriate output version
937 	 * definition.
938 	 */
939 	if (!(sdp->sd_flags & FLG_SY_VERSPROM)) {
940 		Ver_index	*vip;
941 
942 		vip = &ifl->ifl_verndx[vndx];
943 		sdp->sd_aux->sa_overndx = vip->vi_desc->vd_ref->vd_ndx;
944 		sdp->sd_flags |= FLG_SY_VERSPROM;
945 	}
946 }
947 
948 /*
949  * If any versioning is called for make sure an initial version descriptor is
950  * assigned to represent the file itself.  Known as the base version.
951  */
952 Ver_desc *
ld_vers_base(Ofl_desc * ofl)953 ld_vers_base(Ofl_desc *ofl)
954 {
955 	Ver_desc	*vdp;
956 	const char	*name;
957 
958 	/*
959 	 * Determine the filename to associate to the version descriptor.  This
960 	 * is either the SONAME (if one has been supplied) or the basename of
961 	 * the output file.
962 	 */
963 	if ((name = ofl->ofl_soname) == NULL) {
964 		const char	*str = ofl->ofl_name;
965 
966 		while (*str != '\0') {
967 			if (*str++ == '/')
968 				name = str;
969 		}
970 		if (name == NULL)
971 			name = ofl->ofl_name;
972 	}
973 
974 	/*
975 	 * Generate the version descriptor.
976 	 */
977 	/* LINTED */
978 	if ((vdp = ld_vers_desc(name, (Word)elf_hash(name),
979 	    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
980 		return ((Ver_desc *)S_ERROR);
981 
982 	/*
983 	 * Assign the base index to this version and initialize the output file
984 	 * descriptor with the number of version descriptors presently in use.
985 	 */
986 	vdp->vd_ndx = ofl->ofl_vercnt = VER_NDX_GLOBAL;
987 	vdp->vd_flags |= VER_FLG_BASE;
988 
989 	return (vdp);
990 }
991 
992 /*
993  * Now that all input shared objects have been processed, verify that all
994  * version requirements have been met.  Any version control requirements will
995  * have been specified by the user (and placed on the ofl_oscntl list) and are
996  * verified at the time the object was processed (see ver_def_process()).
997  * Here we process all version requirements established from shared objects
998  * themselves (ie,. NEEDED dependencies).
999  */
1000 int
ld_vers_verify(Ofl_desc * ofl)1001 ld_vers_verify(Ofl_desc *ofl)
1002 {
1003 	Aliste		idx1;
1004 	Sdf_desc	*sdf;
1005 	char		*nv;
1006 
1007 	/*
1008 	 * As with the runtime environment, disable all version verification if
1009 	 * requested.
1010 	 */
1011 #if	defined(_ELF64)
1012 	if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_64))) == NULL)
1013 #else
1014 	if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_32))) == NULL)
1015 #endif
1016 		nv = getenv(MSG_ORIG(MSG_LD_NOVERSION));
1017 
1018 	if (nv && nv[0])
1019 		return (1);
1020 
1021 	for (APLIST_TRAVERSE(ofl->ofl_soneed, idx1, sdf)) {
1022 		Aliste		idx2;
1023 		Sdv_desc	*sdv;
1024 		Ifl_desc	*ifl = sdf->sdf_file;
1025 
1026 		if (!(sdf->sdf_flags & FLG_SDF_VERIFY))
1027 			continue;
1028 
1029 		/*
1030 		 * If this file contains no version definitions then ignore
1031 		 * any versioning verification.  This is the same model as
1032 		 * carried out by ld.so.1 and is intended to allow backward
1033 		 * compatibility should a shared object with a version
1034 		 * requirement be returned to an older system on which a
1035 		 * non-versioned shared object exists.
1036 		 */
1037 		if ((ifl == NULL) || (ifl->ifl_verdesc == NULL))
1038 			continue;
1039 
1040 		/*
1041 		 * If individual versions were specified for this file make
1042 		 * sure that they actually exist in the appropriate file, and
1043 		 * that they are available for binding.
1044 		 */
1045 		for (ALIST_TRAVERSE(sdf->sdf_vers, idx2, sdv)) {
1046 			Aliste		idx3;
1047 			Ver_desc	*vdp;
1048 			int		found = 0;
1049 
1050 			for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx3, vdp)) {
1051 				if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) {
1052 					found++;
1053 					break;
1054 				}
1055 			}
1056 			if (found) {
1057 				Ver_index	*vip;
1058 
1059 				vip = &ifl->ifl_verndx[vdp->vd_ndx];
1060 				if (!(vip->vi_flags & FLG_VER_AVAIL)) {
1061 					ld_eprintf(ofl, ERR_FATAL,
1062 					    MSG_INTL(MSG_VER_UNAVAIL),
1063 					    ifl->ifl_name, sdv->sdv_name,
1064 					    sdv->sdv_ref);
1065 				}
1066 			} else {
1067 				ld_eprintf(ofl, ERR_FATAL,
1068 				    MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
1069 				    sdv->sdv_name, sdv->sdv_ref);
1070 			}
1071 		}
1072 	}
1073 	return (1);
1074 }
1075