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