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