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