xref: /titanic_41/usr/src/cmd/sgs/libld/common/resolve.c (revision f4da9be01648d6afa604495d9b9956dddeb92a8c)
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) 1988 AT&T
24  *	  All Rights Reserved
25  *
26  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVR4 6.2/18.2 */
30 
31 /*
32  * Symbol table resolution
33  */
34 #include	<stdio.h>
35 #include	<debug.h>
36 #include	"msg.h"
37 #include	"_libld.h"
38 
39 
40 /*
41  * Categorize the symbol types that are applicable to the resolution process.
42  */
43 typedef	enum {
44 	SYM_DEFINED,		/* Defined symbol (SHN_ABS or shndx != 0) */
45 	SYM_UNDEFINED,		/* Undefined symbol (SHN_UNDEF) */
46 	SYM_TENTATIVE,		/* Tentative symbol (SHN_COMMON) */
47 	SYM_NUM			/* the number of symbol types */
48 } Symtype;
49 
50 /*
51  * Do nothing.
52  */
53 /* ARGSUSED0 */
54 static void
55 sym_null(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
56 	int ndx, Word nshndx, Word nsymflags)
57 {
58 }
59 
60 /*
61  * Check if two symbols types are compatible
62  */
63 /*ARGSUSED4*/
64 static void
65 sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
66 	int ndx, Word nshndx, Word nsymflags)
67 {
68 	uchar_t	otype = ELF_ST_TYPE(sdp->sd_sym->st_info);
69 	uchar_t	ntype = ELF_ST_TYPE(nsym->st_info);
70 
71 	/*
72 	 * Perform any machine specific type checking.
73 	 */
74 	if (ld_mach_sym_typecheck(sdp, nsym, ifl, ofl))
75 		return;
76 
77 	/*
78 	 * STV_VISIBILITY rules say that you must take the most restrictive
79 	 * value for a symbols reference.  If we see a reference from two
80 	 * objects, even if a symbol isn't promoted/overridden, make sure that
81 	 * the more restrictive visibility is saved.
82 	 */
83 	if (ifl->ifl_ehdr->e_type == ET_REL) {
84 		Sym *	osym = sdp->sd_sym;
85 		Half	ovis = ELF_ST_VISIBILITY(osym->st_other);
86 		Half	nvis = ELF_ST_VISIBILITY(nsym->st_other);
87 
88 		if ((nvis > STV_DEFAULT) &&
89 		    ((ovis == STV_DEFAULT) || (nvis < ovis))) {
90 			osym->st_other =
91 				(osym->st_other & ~MSK_SYM_VISIBILITY) | nvis;
92 		}
93 	}
94 
95 	/*
96 	 * NOTYPE's can be combind with other types, only give an error if
97 	 * combining two differing types without NOTYPE
98 	 */
99 	if ((otype == ntype) || (otype == STT_NOTYPE) || (ntype == STT_NOTYPE))
100 		return;
101 
102 	eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
103 	    demangle(sdp->sd_name));
104 	eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
105 	    sdp->sd_file->ifl_name,
106 	    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype, 0),
107 	    ifl->ifl_name,
108 	    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype, 0));
109 }
110 
111 /*ARGSUSED4*/
112 static void
113 sym_mach_check(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
114 	int ndx, Word nshndx, Word nsymflags)
115 {
116 	/*
117 	 * Perform any machine specific type checking.
118 	 */
119 	(void) ld_mach_sym_typecheck(sdp, nsym, ifl, ofl);
120 }
121 
122 /*
123  * Promote the symbols reference.
124  */
125 static void
126 /* ARGSUSED4 */
127 sym_promote(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
128     int ndx, Word nshndx, Word nsymflags)
129 {
130 	Word	shndx = nsym->st_shndx;
131 
132 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
133 
134 	/*
135 	 * If the old symbol is from a shared object and the new symbol is a
136 	 * reference from a relocatable object, promote the old symbols
137 	 * reference.
138 	 */
139 	if ((sdp->sd_ref == REF_DYN_SEEN) &&
140 	    (ifl->ifl_ehdr->e_type == ET_REL)) {
141 		sdp->sd_ref = REF_DYN_NEED;
142 
143 		/*
144 		 * If this is an undefined symbol it must be a relocatable
145 		 * object overriding a shared object.  In this case also
146 		 * override the reference name so that any undefined symbol
147 		 * diagnostics will refer to the relocatable object name.
148 		 */
149 		if (shndx == SHN_UNDEF)
150 			sdp->sd_aux->sa_rfile = ifl->ifl_name;
151 
152 		/*
153 		 * If this symbol is an undefined, or common, determine whether
154 		 * it is a global or weak reference (see build_osym(), where
155 		 * REF_DYN_NEED definitions are returned back to undefines).
156 		 */
157 		if (((shndx == SHN_UNDEF) || ((nsymflags & FLG_SY_SPECSEC) &&
158 		    (shndx == SHN_COMMON))) &&
159 		    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
160 			sdp->sd_flags |= FLG_SY_GLOBREF;
161 
162 	} else if ((shndx != SHN_UNDEF) && (ofl->ofl_dtflags_1 & DF_1_TRANS) &&
163 	    (sdp->sd_aux->sa_bindto == 0) && (sdp->sd_ref == REF_REL_NEED) &&
164 	    (ifl->ifl_ehdr->e_type == ET_DYN)) {
165 		/*
166 		 * If building a translator then record the symbol
167 		 * we would 'bindto' with direct bindings.
168 		 */
169 		sdp->sd_aux->sa_bindto = ifl;
170 	}
171 }
172 
173 /*
174  * Override a symbol.
175  */
176 static void
177 sym_override(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
178 	int ndx, Word nshndx, Word nsymflags)
179 {
180 	Sym		*osym = sdp->sd_sym;
181 	Half		ovis = ELF_ST_VISIBILITY(osym->st_other);
182 	Half		nvis = ELF_ST_VISIBILITY(nsym->st_other);
183 	Word		link;
184 
185 	/*
186 	 * In the case of a WEAK UNDEF symbol don't let a symbol from an
187 	 * unavailable object override the symbol definition.  This is because
188 	 * this symbol *may* not be present in a future object and by promoting
189 	 * this symbol we are actually causing bindings (PLTS) to be formed
190 	 * to this symbol.  Instead let the 'generic' weak binding take place.
191 	 */
192 	if ((ELF_ST_BIND(osym->st_info) == STB_WEAK) &&
193 	    (sdp->sd_sym->st_shndx == SHN_UNDEF) &&
194 	    ((ifl->ifl_flags & FLG_IF_NEEDED) == 0))
195 		return;
196 
197 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
198 
199 	/*
200 	 * This symbol has already been compared to an SO definition,
201 	 * as per the runtime behavior, ignore extra definitions.
202 	 */
203 	if ((sdp->sd_flags & FLG_SY_SOFOUND) &&
204 	    (ifl->ifl_ehdr->e_type == ET_DYN))
205 		return;
206 
207 	/*
208 	 * Mark the symbol as available and copy the new symbols contents.
209 	 */
210 	sdp->sd_flags &= ~FLG_SY_NOTAVAIL;
211 	*osym = *nsym;
212 	sdp->sd_shndx = nshndx;
213 	sdp->sd_flags &= ~FLG_SY_SPECSEC;
214 	sdp->sd_flags |= (nsymflags & (FLG_SY_SPECSEC | FLG_SY_TENTSYM));
215 
216 	/*
217 	 * If the new symbol has PROTECTED visibility, mark it.  If a PROTECTED
218 	 * symbol is copy relocated, a warning message will be printed. See
219 	 * reloc_exec().
220 	 */
221 	if (ELF_ST_VISIBILITY(nsym->st_other) == STV_PROTECTED)
222 		sdp->sd_flags |= FLG_SY_PROT;
223 	else
224 		sdp->sd_flags &= ~FLG_SY_PROT;
225 
226 	/*
227 	 * Establish the symbols reference.  If the new symbol originates from a
228 	 * relocatable object then this reference becomes needed, otherwise
229 	 * the new symbol must be from a shared object.  In this case only
230 	 * promote the symbol to needed if we presently have a reference from a
231 	 * relocatable object.
232 	 */
233 	if (ifl->ifl_ehdr->e_type == ET_REL) {
234 		/*
235 		 * Maintain the more restrictive visiblity
236 		 */
237 		if ((ovis > STV_DEFAULT) &&
238 		    ((nvis == STV_DEFAULT) || (ovis < nvis))) {
239 			osym->st_other =
240 				(osym->st_other & ~MSK_SYM_VISIBILITY) | ovis;
241 		}
242 		sdp->sd_ref = REF_REL_NEED;
243 
244 		if (nsym->st_shndx == SHN_UNDEF) {
245 			/*
246 			 * If this is an undefined symbol it must be a
247 			 * relocatable object overriding a shared object.  In
248 			 * this case also override the reference name so that
249 			 * any undefined symbol diagnostics will refer to the
250 			 * relocatable object name.
251 			 */
252 			sdp->sd_aux->sa_rfile = ifl->ifl_name;
253 		} else {
254 			/*
255 			 * Under -Bnodirect, all exported interfaces that have
256 			 * not explicitly been defined protected or directly
257 			 * bound to, are tagged to prevent direct binding.
258 			 */
259 			if ((ofl->ofl_flags1 & FLG_OF1_ALNODIR) &&
260 			    ((sdp->sd_flags1 &
261 			    (FLG_SY1_PROT | FLG_SY1_DIR)) == 0))
262 				sdp->sd_flags1 |= FLG_SY1_NDIR;
263 		}
264 
265 		/*
266 		 * If this symbol is an undefined, or common, determine whether
267 		 * it is a global or weak reference (see build_osym(), where
268 		 * REF_DYN_NEED definitions are returned back to undefines).
269 		 */
270 		if (((nsym->st_shndx == SHN_UNDEF) ||
271 		    ((nsymflags & FLG_SY_SPECSEC) &&
272 		    (nsym->st_shndx == SHN_COMMON))) &&
273 		    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
274 			sdp->sd_flags |= FLG_SY_GLOBREF;
275 		else
276 			sdp->sd_flags &= ~FLG_SY_GLOBREF;
277 	} else {
278 		if (sdp->sd_ref == REF_REL_NEED)
279 			sdp->sd_ref = REF_DYN_NEED;
280 
281 		/*
282 		 * Visibility from a DYN symbol does not override
283 		 * previous symbol visibility.
284 		 */
285 		osym->st_other = (osym->st_other & ~MSK_SYM_VISIBILITY) |
286 			ovis;
287 
288 		/*
289 		 * Determine the symbols availability.  A symbol is determined
290 		 * to be unavailable if it belongs to a version of a shared
291 		 * object that this user does not wish to use, or if it belongs
292 		 * to an implicit shared object.
293 		 */
294 		if (ifl->ifl_vercnt) {
295 			Ver_index *	vip;
296 			Half		vndx = ifl->ifl_versym[ndx];
297 
298 			sdp->sd_aux->sa_dverndx = vndx;
299 			vip = &ifl->ifl_verndx[vndx];
300 			if (!(vip->vi_flags & FLG_VER_AVAIL)) {
301 				sdp->sd_flags |= FLG_SY_NOTAVAIL;
302 				/*
303 				 * If this is the first occurance of an
304 				 * unavailable symbol record it for possible
305 				 * use in later error diagnostics
306 				 * (see sym_undef).
307 				 */
308 				if (!(sdp->sd_aux->sa_vfile))
309 					sdp->sd_aux->sa_vfile = ifl->ifl_name;
310 			}
311 		}
312 		if (!(ifl->ifl_flags & FLG_IF_NEEDED))
313 			sdp->sd_flags |= FLG_SY_NOTAVAIL;
314 	}
315 
316 	/*
317 	 * Make sure any symbol association maintained by the original symbol
318 	 * is cleared and then update the symbols file reference.
319 	 */
320 	if ((link = sdp->sd_aux->sa_linkndx) != 0) {
321 		Sym_desc *	_sdp;
322 
323 		_sdp = sdp->sd_file->ifl_oldndx[link];
324 		_sdp->sd_aux->sa_linkndx = 0;
325 		sdp->sd_aux->sa_linkndx = 0;
326 	}
327 	sdp->sd_file = ifl;
328 
329 	/*
330 	 * Update the input section descriptor to that of the new input file
331 	 */
332 	if (((nsymflags & FLG_SY_SPECSEC) == 0) &&
333 	    (nsym->st_shndx != SHN_UNDEF)) {
334 		if ((sdp->sd_isc = ifl->ifl_isdesc[nshndx]) == 0) {
335 			eprintf(ofl->ofl_lml, ERR_FATAL,
336 			    MSG_INTL(MSG_SYM_NOSECDEF), demangle(sdp->sd_name),
337 			    ifl->ifl_name);
338 			ofl->ofl_flags |= FLG_OF_FATAL;
339 		}
340 	}
341 }
342 
343 /*
344  * Resolve two undefines (only called for two relocatable objects).
345  */
346 static void
347 sym_twoundefs(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
348 	int ndx, Word nshndx, Word nsymflags)
349 {
350 	Sym	*osym = sdp->sd_sym;
351 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
352 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
353 
354 	/*
355 	 * If two relocatable objects define a weak and non-weak undefined
356 	 * reference, take the non-weak definition.
357 	 *
358 	 *		-- or --
359 	 *
360 	 * If two relocatable objects define a NOTYPE & another, then
361 	 * take the other.
362 	 */
363 	if (((obind == STB_WEAK) && (nbind != STB_WEAK)) ||
364 	    (obind == STT_NOTYPE) && (nbind != STT_NOTYPE)) {
365 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
366 		return;
367 	}
368 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
369 }
370 
371 /*
372  * Resolve two real definitions.
373  */
374 static void
375 sym_tworeals(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
376 	int ndx, Word nshndx, Word nsymflags)
377 {
378 	Sym	*osym = sdp->sd_sym;
379 	uchar_t	otype = ELF_ST_TYPE(osym->st_info);
380 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
381 	uchar_t	ntype = ELF_ST_TYPE(nsym->st_info);
382 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
383 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
384 	Half	nfile = ifl->ifl_ehdr->e_type;
385 	int	warn = 0;
386 
387 	/*
388 	 * If both definitions are from relocatable objects, and have non-weak
389 	 * binding then this is a fatal condition.
390 	 */
391 	if ((ofile == ET_REL) && (nfile == ET_REL) && (obind != STB_WEAK) &&
392 	    (nbind != STB_WEAK) && (!(ofl->ofl_flags & FLG_OF_MULDEFS))) {
393 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYM_MULDEF),
394 		    demangle(sdp->sd_name));
395 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
396 		    sdp->sd_file->ifl_name,
397 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype, 0),
398 		    ifl->ifl_name,
399 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype, 0));
400 		ofl->ofl_flags |= FLG_OF_FATAL;
401 		return;
402 	}
403 
404 	/*
405 	 * Perform any machine specific type checking.
406 	 */
407 	if (ld_mach_sym_typecheck(sdp, nsym, ifl, ofl))
408 		return;
409 
410 	/*
411 	 * Check the symbols type and size.
412 	 */
413 	if (otype != ntype) {
414 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
415 		    demangle(sdp->sd_name));
416 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
417 		    sdp->sd_file->ifl_name,
418 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype, 0),
419 		    ifl->ifl_name, conv_sym_info_type(ofl->ofl_dehdr->e_machine,
420 		    ntype, 0));
421 		warn++;
422 	} else if ((otype == STT_OBJECT) && (osym->st_size != nsym->st_size)) {
423 		if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
424 			eprintf(ofl->ofl_lml, ERR_WARNING,
425 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
426 			    MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
427 			    EC_XWORD(osym->st_size), ifl->ifl_name,
428 			    EC_XWORD(nsym->st_size));
429 			warn++;
430 		}
431 	}
432 
433 	/*
434 	 * Having provided the user with any necessary warnings, take the
435 	 * appropriate symbol:
436 	 *
437 	 *  o	if one symbol is from a shared object and the other is from a
438 	 *	relocatable object, take the relocatable objects symbol (the
439 	 *	run-time linker is always going to find the relocatable object
440 	 *	symbol regardless of the binding), else
441 	 *
442 	 * o	if both symbols are from relocatable objects and one symbol is
443 	 *	weak take the non-weak symbol (two non-weak symbols would have
444 	 *	generated the fatal error condition above unless -z muldefs is
445 	 *	in effect), else
446 	 *
447 	 *  o	take the first symbol definition encountered.
448 	 */
449 	if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
450 		if (warn)
451 			eprintf(ofl->ofl_lml, ERR_NONE,
452 			    MSG_INTL(MSG_SYM_DEFTAKEN), sdp->sd_file->ifl_name);
453 		return;
454 	} else if ((nfile == ET_REL) && ((ofile == ET_DYN) ||
455 	    ((obind == STB_WEAK) && (nbind != STB_WEAK)))) {
456 		if (warn)
457 			eprintf(ofl->ofl_lml, ERR_NONE,
458 			    MSG_INTL(MSG_SYM_DEFTAKEN), ifl->ifl_name);
459 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
460 		return;
461 	} else {
462 		if (warn)
463 			eprintf(ofl->ofl_lml, ERR_NONE,
464 			    MSG_INTL(MSG_SYM_DEFTAKEN), sdp->sd_file->ifl_name);
465 		sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
466 		return;
467 	}
468 }
469 
470 /*
471  * Resolve a real and tentative definition.
472  */
473 static void
474 sym_realtent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
475 	int ndx, Word nshndx, Word nsymflags)
476 {
477 	Sym	*osym = sdp->sd_sym;
478 	uchar_t otype = ELF_ST_TYPE(osym->st_info);
479 	uchar_t obind = ELF_ST_BIND(osym->st_info);
480 	uchar_t ntype = ELF_ST_TYPE(nsym->st_info);
481 	uchar_t nbind = ELF_ST_BIND(nsym->st_info);
482 	Boolean	otent = FALSE, ntent = FALSE;
483 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
484 	Half	nfile = ifl->ifl_ehdr->e_type;
485 	int	warn = 0;
486 	Word	osymvis = ELF_ST_VISIBILITY(osym->st_other);
487 	Word	nsymvis = ELF_ST_VISIBILITY(nsym->st_other);
488 
489 	/*
490 	 * Special rules for functions.
491 	 *
492 	 *  o	If both definitions are from relocatable objects, have the same
493 	 *	binding (ie. two weaks or two non-weaks), and the real
494 	 *	definition is a function (the other must be tentative), treat
495 	 *	this as a multiply defined symbol error, else
496 	 *
497 	 *  o	if the real symbol definition is a function within a shared
498 	 *	library and the tentative symbol is a relocatable object, and
499 	 *	the tentative is not weak and the function real, then retain the
500 	 *	tentative definition.
501 	 */
502 	if ((ofile == ET_REL) && (nfile == ET_REL) && (obind == nbind) &&
503 	    ((otype == STT_FUNC) || (ntype == STT_FUNC))) {
504 		if (ofl->ofl_flags & FLG_OF_MULDEFS) {
505 			eprintf(ofl->ofl_lml, ERR_WARNING,
506 			    MSG_INTL(MSG_SYM_DIFFTYPE), demangle(sdp->sd_name));
507 			sym_promote(sdp, nsym, ifl, ofl, ndx,
508 				nshndx, nsymflags);
509 		} else {
510 			eprintf(ofl->ofl_lml, ERR_FATAL,
511 			    MSG_INTL(MSG_SYM_MULDEF), demangle(sdp->sd_name));
512 			ofl->ofl_flags |= FLG_OF_FATAL;
513 		}
514 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
515 		    sdp->sd_file->ifl_name,
516 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype, 0),
517 		    ifl->ifl_name, conv_sym_info_type(ofl->ofl_dehdr->e_machine,
518 		    ntype, 0));
519 		return;
520 	} else if (ofile != nfile) {
521 
522 
523 		if ((ofile == ET_DYN) && (otype == STT_FUNC)) {
524 			if ((otype != STB_WEAK) && (ntype == STB_WEAK))
525 				return;
526 			else {
527 				sym_override(sdp, nsym, ifl, ofl, ndx,
528 				    nshndx, nsymflags);
529 				return;
530 			}
531 		}
532 		if ((nfile == ET_DYN) && (ntype == STT_FUNC)) {
533 			if ((ntype != STB_WEAK) && (otype == STB_WEAK)) {
534 				sym_override(sdp, nsym, ifl, ofl, ndx,
535 					nshndx, nsymflags);
536 				return;
537 			} else
538 				return;
539 		}
540 	}
541 
542 	if (sdp->sd_flags & FLG_SY_TENTSYM)
543 		otent = TRUE;
544 	if (nsymflags & FLG_SY_TENTSYM)
545 		ntent = TRUE;
546 
547 
548 	/*
549 	 * Check the symbols type and size.
550 	 */
551 	if (otype != ntype) {
552 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
553 		    demangle(sdp->sd_name));
554 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
555 		    sdp->sd_file->ifl_name,
556 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype, 0),
557 		    ifl->ifl_name, conv_sym_info_type(ofl->ofl_dehdr->e_machine,
558 		    ntype, 0));
559 		warn++;
560 	} else if (osym->st_size != nsym->st_size) {
561 		/*
562 		 * If both definitions are from relocatable objects we have a
563 		 * potential fatal error condition.  If the tentative is larger
564 		 * than the real definition treat this as a multiple definition.
565 		 * Note that if only one symbol is weak, the non-weak will be
566 		 * taken.
567 		 */
568 		if (((ofile == ET_REL) && (nfile == ET_REL) &&
569 		    (obind == nbind)) &&
570 		    ((otent && (osym->st_size > nsym->st_size)) ||
571 		    (ntent && (osym->st_size < nsym->st_size)))) {
572 			eprintf(ofl->ofl_lml, ERR_FATAL,
573 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
574 			    MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
575 			    EC_XWORD(osym->st_size), ifl->ifl_name,
576 			    EC_XWORD(nsym->st_size));
577 			eprintf(ofl->ofl_lml, ERR_NONE,
578 			    MSG_INTL(MSG_SYM_TENTERR));
579 			ofl->ofl_flags |= FLG_OF_FATAL;
580 		} else {
581 			if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
582 				eprintf(ofl->ofl_lml, ERR_WARNING,
583 				    MSG_INTL(MSG_SYM_DIFFATTR),
584 				    demangle(sdp->sd_name),
585 				    MSG_INTL(MSG_STR_SIZES),
586 				    sdp->sd_file->ifl_name,
587 				    EC_XWORD(osym->st_size),
588 				    ifl->ifl_name, EC_XWORD(nsym->st_size));
589 				warn++;
590 			}
591 		}
592 	}
593 
594 	/*
595 	 * Having provided the user with any necessary warnings, take the
596 	 * appropriate symbol:
597 	 *
598 	 *  o   if the original symbol is from relocatable file and it is
599 	 *	a protected tentative symbol, take the original one.
600 	 *
601 	 *  o 	if the original symbol is from shared object and the new
602 	 *	symbol is a protected tentative symbol from a relocatable file,
603 	 *	take the new one.
604 	 *
605 	 *  o	if the original symbol is tentative, and providing the original
606 	 *	symbol isn't strong and the new symbol weak, take the real
607 	 *	symbol, else
608 	 *
609 	 *  o	if the original symbol is weak and the new tentative symbol is
610 	 *	strong take the new symbol.
611 	 *
612 	 * Refer to the System V ABI Page 4-27 for a description of the binding
613 	 * requirements of tentative and weak symbols.
614 	 */
615 	if ((ofile == ET_REL) && (nfile == ET_DYN) && (otent == TRUE) &&
616 	    (osymvis == STV_PROTECTED)) {
617 		return;
618 	}
619 
620 	if ((ofile == ET_DYN) && (nfile == ET_REL) && (ntent == TRUE) &&
621 	    (nsymvis == STV_PROTECTED)) {
622 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
623 		return;
624 	}
625 
626 	if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
627 		if (warn)
628 			eprintf(ofl->ofl_lml, ERR_NONE,
629 			    MSG_INTL(MSG_SYM_DEFTAKEN), sdp->sd_file->ifl_name);
630 		return;
631 	}
632 
633 	if (((otent) && (!((obind != STB_WEAK) && (nbind == STB_WEAK)))) ||
634 	    ((obind == STB_WEAK) && (nbind != STB_WEAK))) {
635 		if (warn)
636 			eprintf(ofl->ofl_lml, ERR_NONE,
637 			    MSG_INTL(MSG_SYM_DEFTAKEN), ifl->ifl_name);
638 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
639 		return;
640 	} else {
641 		if (warn)
642 			eprintf(ofl->ofl_lml, ERR_NONE,
643 			    MSG_INTL(MSG_SYM_DEFTAKEN), sdp->sd_file->ifl_name);
644 		sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
645 		return;
646 	}
647 }
648 
649 /*
650  * Resolve two tentative symbols.
651  */
652 static void
653 sym_twotent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
654 	int ndx, Word nshndx, Word nsymflags)
655 {
656 	Sym	*osym = sdp->sd_sym;
657 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
658 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
659 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
660 	Half	nfile = ifl->ifl_ehdr->e_type;
661 	size_t	size = 0;
662 	Xword	value = 0;
663 
664 #if	defined(__x86) && defined(_ELF64)
665 	/*
666 	 * If the original and new symbols are both COMMON, but of a different
667 	 * size model, take the small one.
668 	 */
669 	if ((sdp->sd_sym->st_shndx == SHN_COMMON) &&
670 	    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
671 		/*
672 		 * Take the original symbol.
673 		 */
674 		return;
675 
676 	} else if ((sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
677 	    (nsym->st_shndx == SHN_COMMON)) {
678 		/*
679 		 * Take the new symbol.
680 		 */
681 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
682 		return;
683 	}
684 #endif
685 
686 	/*
687 	 * Check the alignment of the symbols.  This can only be tested for if
688 	 * the symbols are not real definitions to a SHT_NOBITS section (ie.
689 	 * they were originally tentative), as in this case the symbol would
690 	 * have a displacement value rather than an alignment.  In other words
691 	 * we can only test this for two relocatable objects.
692 	 */
693 	if ((osym->st_value != nsym->st_value) &&
694 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
695 	    (sdp->sd_sym->st_shndx == SHN_COMMON) &&
696 	    (nsymflags & FLG_SY_SPECSEC) &&
697 #if	defined(__x86) && defined(_ELF64)
698 	    (nsym->st_shndx == SHN_COMMON)) ||
699 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
700 	    (sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
701 	    (nsymflags & FLG_SY_SPECSEC) &&
702 	    (nsym->st_shndx == SHN_X86_64_LCOMMON))) {
703 #else
704 	    (nsym->st_shndx == SHN_COMMON))) {
705 #endif
706 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
707 		const char	*file;
708 		Xword		salign;
709 		Xword		balign;
710 		uint_t		alignscompliment;
711 
712 		if (osym->st_value < nsym->st_value) {
713 			salign = osym->st_value;
714 			balign = nsym->st_value;
715 		} else {
716 			salign = nsym->st_value;
717 			balign = osym->st_value;
718 		}
719 
720 		/*
721 		 * If the smaller alignment fits smoothly into the
722 		 * larger alignment - we take it with no warning.
723 		 */
724 		if (S_ALIGN(balign, salign) == balign)
725 			alignscompliment = 1;
726 		else
727 			alignscompliment = 0;
728 
729 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
730 			eprintf(ofl->ofl_lml, ERR_WARNING,
731 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
732 			    MSG_INTL(MSG_STR_ALIGNMENTS),
733 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_value),
734 			    ifl->ifl_name, EC_XWORD(nsym->st_value));
735 
736 		/*
737 		 * Having provided the necessary warning indicate which
738 		 * relocatable object we are going to take.
739 		 *
740 		 *  o	if one symbol is weak and the other is non-weak
741 		 *	take the non-weak symbol, else
742 		 *
743 		 *  o	take the largest alignment (as we still have to check
744 		 *	the symbols size simply save the largest value for
745 		 *	updating later).
746 		 */
747 		if ((obind == STB_WEAK) && (nbind != STB_WEAK))
748 			file = ifl->ifl_name;
749 		else if (obind != nbind)
750 			file = sdp->sd_file->ifl_name;
751 		else {
752 			emsg = MSG_INTL(MSG_SYM_LARGER);
753 			value = balign;
754 		}
755 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
756 			eprintf(ofl->ofl_lml, ERR_NONE, emsg, file);
757 	}
758 
759 	/*
760 	 * Check the size of the symbols.
761 	 */
762 	if (osym->st_size != nsym->st_size) {
763 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
764 		const char	*file;
765 
766 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
767 			eprintf(ofl->ofl_lml, ERR_WARNING,
768 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
769 			    MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
770 			    EC_XWORD(osym->st_size), ifl->ifl_name,
771 			    EC_XWORD(nsym->st_size));
772 
773 
774 		/*
775 		 * This symbol has already been compared to an SO definition,
776 		 * as per the runtime behavior, ignore extra definitions.
777 		 */
778 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
779 			if (!(ofl->ofl_flags & FLG_OF_NOWARN))
780 				eprintf(ofl->ofl_lml, ERR_NONE, emsg,
781 				    sdp->sd_file->ifl_name);
782 			return;
783 		}
784 
785 		/*
786 		 * Having provided the necessary warning indicate what course
787 		 * of action we are going to take.
788 		 *
789 		 *  o	if the file types differ, take the relocatable object
790 		 *	and apply the largest symbol size, else
791 		 *  o	if one symbol is weak and the other is non-weak, take
792 		 *	the non-weak symbol, else
793 		 *  o	simply take the largest symbol reference.
794 		 */
795 		if (nfile != ofile) {
796 			if (nfile == ET_REL) {
797 				file = ifl->ifl_name;
798 				if (osym->st_size > nsym->st_size) {
799 					size = (size_t)osym->st_size;
800 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
801 				}
802 				sym_override(sdp, nsym, ifl, ofl, ndx,
803 				    nshndx, nsymflags);
804 			} else {
805 				file = sdp->sd_file->ifl_name;
806 				if (osym->st_size < nsym->st_size) {
807 					size = (size_t)nsym->st_size;
808 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
809 				}
810 				sym_promote(sdp, nsym, ifl, ofl, ndx,
811 				    nshndx, nsymflags);
812 			}
813 		} else if (obind != nbind) {
814 			if ((obind == STB_WEAK) && (nbind != STB_WEAK)) {
815 				sym_override(sdp, nsym, ifl, ofl, ndx,
816 				    nshndx, nsymflags);
817 				file = ifl->ifl_name;
818 			} else
819 				file = sdp->sd_file->ifl_name;
820 		} else {
821 			if (osym->st_size < nsym->st_size) {
822 				sym_override(sdp, nsym, ifl, ofl, ndx,
823 				    nshndx, nsymflags);
824 				file = ifl->ifl_name;
825 			} else
826 				file = sdp->sd_file->ifl_name;
827 		}
828 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
829 			eprintf(ofl->ofl_lml, ERR_NONE, emsg, file);
830 		if (size)
831 			sdp->sd_sym->st_size = (Xword)size;
832 	} else {
833 		/*
834 		 * If the sizes are the same
835 		 *
836 		 *  o	if the file types differ, take the relocatable object,
837 		 *	else
838 		 *
839 		 *  o	if one symbol is weak and the other is non-weak, take
840 		 *	the non-weak symbol, else
841 		 *
842 		 *  o	take the first reference.
843 		 */
844 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN))
845 			return;
846 		else if (((ofile != nfile) && (nfile == ET_REL)) ||
847 		    (((obind == STB_WEAK) && (nbind != STB_WEAK)) &&
848 		    (!((ofile != nfile) && (ofile == ET_REL)))))
849 			sym_override(sdp, nsym, ifl, ofl, ndx,
850 			    nshndx, nsymflags);
851 		else
852 			sym_promote(sdp, nsym, ifl, ofl, ndx,
853 			    nshndx, nsymflags);
854 	}
855 
856 	/*
857 	 * Enforce the largest alignment if necessary.
858 	 */
859 	if (value)
860 		sdp->sd_sym->st_value = value;
861 }
862 
863 /*
864  * Symbol resolution state table.  `Action' describes the required
865  * procedure to be called (if any).
866  */
867 static void (*Action[REF_NUM * SYM_NUM * 2][SYM_NUM])(Sym_desc *,
868 	Sym *, Ifl_desc *, Ofl_desc *, int, Word, Word) = {
869 
870 /*				defined		undef		tent	*/
871 /*				ET_REL		ET_REL		ET_REL	*/
872 
873 /*  0 defined REF_DYN_SEEN */	sym_tworeals,	sym_promote,	sym_realtent,
874 /*  1   undef REF_DYN_SEEN */	sym_override,	sym_override,	sym_override,
875 /*  2    tent REF_DYN_SEEN */	sym_realtent,	sym_promote,	sym_twotent,
876 /*  3 defined REF_DYN_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
877 /*  4   undef REF_DYN_NEED */	sym_override,	sym_override,	sym_override,
878 /*  5    tent REF_DYN_NEED */	sym_realtent,	sym_typecheck,	sym_twotent,
879 /*  6 defined REF_REL_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
880 /*  7   undef REF_REL_NEED */	sym_override,	sym_twoundefs,	sym_override,
881 /*  8    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent,
882 
883 /*				defined		undef		tent	*/
884 /*				ET_DYN		ET_DYN		ET_DYN	*/
885 
886 /*  9 defined REF_DYN_SEEN */	sym_tworeals,	sym_null,	sym_realtent,
887 /* 10   undef REF_DYN_SEEN */	sym_override,	sym_mach_check,	sym_override,
888 /* 11    tent REF_DYN_SEEN */	sym_realtent,	sym_null,	sym_twotent,
889 /* 12 defined REF_DYN_NEED */	sym_tworeals,	sym_null,	sym_realtent,
890 /* 13   undef REF_DYN_NEED */	sym_override,	sym_null,	sym_override,
891 /* 14    tent REF_DYN_NEED */	sym_realtent,	sym_null,	sym_twotent,
892 /* 15 defined REF_REL_NEED */	sym_tworeals,	sym_null,	sym_realtent,
893 /* 16   undef REF_REL_NEED */	sym_override,	sym_mach_check,	sym_override,
894 /* 17    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent
895 
896 };
897 
898 uintptr_t
899 ld_sym_resolve(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl, int ndx,
900     Word nshndx, Word nsymflags)
901 {
902 	int		row, column;		/* State table coordinates */
903 	Sym		*osym = sdp->sd_sym;
904 	Is_desc		*isp;
905 	Half		nfile = ifl->ifl_ehdr->e_type;
906 
907 	/*
908 	 * Determine the original symbols definition (defines row in Action[]).
909 	 */
910 	if (sdp->sd_flags & FLG_SY_TENTSYM)
911 		row = SYM_TENTATIVE;
912 	else if ((sdp->sd_sym->st_shndx == SHN_UNDEF) ||
913 	    (sdp->sd_sym->st_shndx == SHN_SUNW_IGNORE))
914 		row = SYM_UNDEFINED;
915 	else
916 		row = SYM_DEFINED;
917 
918 	/*
919 	 * If the input file is an implicit shared object then we don't need
920 	 * to bind to any symbols within it other than to verify that any
921 	 * undefined references will be closed (implicit shared objects are only
922 	 * processed when no undefined symbols are required as a result of the
923 	 * link-edit (see process_dynamic())).
924 	 */
925 	if ((nfile == ET_DYN) && !(ifl->ifl_flags & FLG_IF_NEEDED) &&
926 	    (row != SYM_UNDEFINED))
927 		return (1);
928 
929 	/*
930 	 * Finish computing the Action[] row by applying the symbols reference
931 	 * together with the input files type.
932 	 */
933 	row = row + (REF_NUM * sdp->sd_ref);
934 	if (nfile == ET_DYN)
935 		row += (REF_NUM * SYM_NUM);
936 
937 	/*
938 	 * Determine the new symbols definition (defines column in Action[]).
939 	 */
940 	if ((nsymflags & FLG_SY_SPECSEC) &&
941 	    (nsym->st_shndx == SHN_COMMON)) {
942 		column = SYM_TENTATIVE;
943 		nsymflags |= FLG_SY_TENTSYM;
944 #if	defined(__x86) && defined(_ELF64)
945 	} else if ((nsymflags & FLG_SY_SPECSEC) &&
946 	    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
947 		column = SYM_TENTATIVE;
948 		nsymflags |= FLG_SY_TENTSYM;
949 #endif
950 	} else if ((nsym->st_shndx == SHN_UNDEF) ||
951 	    (nsym->st_shndx == SHN_SUNW_IGNORE)) {
952 		column = SYM_UNDEFINED;
953 		nshndx = SHN_UNDEF;
954 	} else {
955 		column = SYM_DEFINED;
956 		/*
957 		 * If the new symbol is from a shared library and it is
958 		 * associated with a SHT_NOBITS section then this symbol
959 		 * originated from a tentative symbol.
960 		 */
961 		if (((nsymflags & FLG_SY_SPECSEC) == 0) && (nfile == ET_DYN)) {
962 			isp = ifl->ifl_isdesc[nshndx];
963 			if (isp && (isp->is_shdr->sh_type == SHT_NOBITS)) {
964 				column = SYM_TENTATIVE;
965 				nsymflags |= FLG_SY_TENTSYM;
966 			}
967 		}
968 	}
969 
970 	DBG_CALL(Dbg_syms_resolving(ofl, ndx, sdp->sd_name, row, column,
971 	    osym, nsym, sdp, ifl));
972 
973 	/*
974 	 * Record the input filename on the defined files list for possible
975 	 * later diagnostics.  The `sa_dfiles' list is used to maintain the list
976 	 * of shared objects that define the same symbol.  This list is only
977 	 * generated when the -m option is in effect and is used to list
978 	 * multiple (interposed) definitions of a symbol (refer to ldmap_out()).
979 	 */
980 	if ((ofl->ofl_flags & FLG_OF_GENMAP) && (nsym->st_shndx != SHN_UNDEF) &&
981 	    ((nsymflags & FLG_SY_SPECSEC) == 0))
982 		if (list_appendc(&sdp->sd_aux->sa_dfiles, ifl->ifl_name) == 0)
983 			return (S_ERROR);
984 
985 	/*
986 	 * Perform the required resolution.
987 	 */
988 	Action[row][column](sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
989 
990 	/*
991 	 * If the symbol has been resolved to the new input file, and this is
992 	 * a versioned relocatable object, then the version information of the
993 	 * new symbol must be promoted to the versioning of the output file.
994 	 */
995 	if ((sdp->sd_file == ifl) && (nfile == ET_REL) && (ifl->ifl_versym) &&
996 	    (nsym->st_shndx != SHN_UNDEF))
997 		ld_vers_promote(sdp, ndx, ifl, ofl);
998 
999 	/*
1000 	 * Determine whether a mapfile reference has been satisfied.  Mapfile
1001 	 * symbol references augment symbols that should be contributed from
1002 	 * the relocatable objects used to build the output image.  If a
1003 	 * relocatable object doesn't provide one of the mapfile symbol
1004 	 * references then somethings amiss, and will be flagged during symbol
1005 	 * validation.
1006 	 */
1007 	if ((nfile == ET_REL) && ((sdp->sd_flags &
1008 	    (FLG_SY_MAPREF | FLG_SY_MAPUSED)) == FLG_SY_MAPREF)) {
1009 		/*
1010 		 * Extern and parent references are satisfied by references from
1011 		 * a relocatable object.  Note that we let *any* symbol type
1012 		 * satisfy this reference, to be as flexible as possible with
1013 		 * user written mapfiles.  It could be questionable, for
1014 		 * example, if what a user expects to be an extern reference is
1015 		 * actually found to be a definition in a relocatable object.
1016 		 *
1017 		 * Any other mapfile reference (typically for versioning
1018 		 * information) simply augments a relocatables definition.
1019 		 */
1020 		if ((sdp->sd_flags & (FLG_SY_EXTERN | FLG_SY_PARENT)) ||
1021 		    ((sdp->sd_sym->st_shndx != SHN_UNDEF) &&
1022 		    (sdp->sd_ref == REF_REL_NEED)))
1023 			sdp->sd_flags |= FLG_SY_MAPUSED;
1024 	}
1025 
1026 	DBG_CALL(Dbg_syms_resolved(ofl, sdp));
1027 
1028 	return (1);
1029 }
1030