xref: /titanic_52/usr/src/cmd/sgs/libld/common/resolve.c (revision c2e7b48d563d0e56b74d853118918af352e75cbb)
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 #if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
654 	/*
655 	 * If original and new are both COMMON but
656 	 * different size model, take the small one.
657 	 */
658 	if ((sdp->sd_shndx == SHN_COMMON) &&
659 	    (nshndx == SHN_X86_64_LCOMMON)) {
660 		/*
661 		 * Take the original one.
662 		 */
663 		return;
664 	} else if ((sdp->sd_shndx == SHN_X86_64_LCOMMON) &&
665 	    (nshndx == SHN_COMMON)) {
666 		/*
667 		 * Take the new symbol.
668 		 */
669 		sym_override(sdp, nsym, ifl, ofl, ndx,
670 		    nshndx, nsymflags);
671 		return;
672 	}
673 #endif
674 
675 	/*
676 	 * Check the alignment of the symbols.  This can only be tested for if
677 	 * the symbols are not real definitions to a SHT_NOBITS section (ie.
678 	 * they were originally tentative), as in this case the symbol would
679 	 * have a displacement value rather than an alignment.  In other words
680 	 * we can only test this for two relocatable objects.
681 	 */
682 	if ((osym->st_value != nsym->st_value) &&
683 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
684 	    (sdp->sd_shndx == SHN_COMMON) &&
685 	    (nsymflags & FLG_SY_SPECSEC) &&
686 #if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
687 	    (nshndx == SHN_COMMON)) ||
688 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
689 	    (sdp->sd_shndx == SHN_X86_64_LCOMMON) &&
690 	    (nsymflags & FLG_SY_SPECSEC) &&
691 	    (nshndx == SHN_X86_64_LCOMMON))) {
692 #else
693 	    (nshndx == SHN_COMMON))) {
694 #endif
695 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
696 		const char	*file;
697 		Xword		salign;
698 		Xword		balign;
699 		uint_t		alignscompliment;
700 
701 		if (osym->st_value < nsym->st_value) {
702 			salign = osym->st_value;
703 			balign = nsym->st_value;
704 		} else {
705 			salign = nsym->st_value;
706 			balign = osym->st_value;
707 		}
708 
709 		/*
710 		 * If the smaller alignment fits smoothly into the
711 		 * larger alignment - we take it with no warning.
712 		 */
713 		if (S_ALIGN(balign, salign) == balign)
714 			alignscompliment = 1;
715 		else
716 			alignscompliment = 0;
717 
718 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
719 			eprintf(ERR_WARNING, MSG_INTL(MSG_SYM_DIFFATTR),
720 			    demangle(sdp->sd_name),
721 			    MSG_INTL(MSG_STR_ALIGNMENTS),
722 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_value),
723 			    ifl->ifl_name, EC_XWORD(nsym->st_value));
724 
725 		/*
726 		 * Having provided the necessary warning indicate which
727 		 * relocatable object we are going to take.
728 		 *
729 		 *  o	if one symbol is weak and the other is non-weak
730 		 *	take the non-weak symbol, else
731 		 *
732 		 *  o	take the largest alignment (as we still have to check
733 		 *	the symbols size simply save the largest value for
734 		 *	updating later).
735 		 */
736 		if ((obind == STB_WEAK) && (nbind != STB_WEAK))
737 			file = ifl->ifl_name;
738 		else if (obind != nbind)
739 			file = sdp->sd_file->ifl_name;
740 		else {
741 			emsg = MSG_INTL(MSG_SYM_LARGER);
742 			value = balign;
743 		}
744 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
745 			eprintf(ERR_NONE, emsg, file);
746 	}
747 
748 	/*
749 	 * Check the size of the symbols.
750 	 */
751 	if (osym->st_size != nsym->st_size) {
752 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
753 		const char	*file;
754 
755 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
756 			eprintf(ERR_WARNING, MSG_INTL(MSG_SYM_DIFFATTR),
757 			    demangle(sdp->sd_name), MSG_INTL(MSG_STR_SIZES),
758 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_size),
759 			    ifl->ifl_name, EC_XWORD(nsym->st_size));
760 
761 
762 		/*
763 		 * This symbol has already been compared to an SO definition,
764 		 * as per the runtime behavior, ignore extra definitions.
765 		 */
766 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
767 			if (!(ofl->ofl_flags & FLG_OF_NOWARN))
768 				eprintf(ERR_NONE, emsg,
769 				    sdp->sd_file->ifl_name);
770 			return;
771 		}
772 
773 		/*
774 		 * Having provided the necessary warning indicate what course
775 		 * of action we are going to take.
776 		 *
777 		 *  o	if the file types differ, take the relocatable object
778 		 *	and apply the largest symbol size, else
779 		 *  o	if one symbol is weak and the other is non-weak, take
780 		 *	the non-weak symbol, else
781 		 *  o	simply take the largest symbol reference.
782 		 */
783 		if (nfile != ofile) {
784 			if (nfile == ET_REL) {
785 				file = ifl->ifl_name;
786 				if (osym->st_size > nsym->st_size) {
787 					size = (size_t)osym->st_size;
788 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
789 				}
790 				sym_override(sdp, nsym, ifl, ofl, ndx,
791 				    nshndx, nsymflags);
792 			} else {
793 				file = sdp->sd_file->ifl_name;
794 				if (osym->st_size < nsym->st_size) {
795 					size = (size_t)nsym->st_size;
796 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
797 				}
798 				sym_promote(sdp, nsym, ifl, ofl, ndx,
799 					nshndx, nsymflags);
800 			}
801 		} else if (obind != nbind) {
802 			if ((obind == STB_WEAK) && (nbind != STB_WEAK)) {
803 				sym_override(sdp, nsym, ifl, ofl, ndx,
804 					nshndx, nsymflags);
805 				file = ifl->ifl_name;
806 			} else
807 				file = sdp->sd_file->ifl_name;
808 		} else {
809 			if (osym->st_size < nsym->st_size) {
810 				sym_override(sdp, nsym, ifl, ofl, ndx,
811 					nshndx, nsymflags);
812 				file = ifl->ifl_name;
813 			} else
814 				file = sdp->sd_file->ifl_name;
815 		}
816 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
817 			eprintf(ERR_NONE, emsg, file);
818 		if (size)
819 			sdp->sd_sym->st_size = (Xword)size;
820 	} else {
821 		/*
822 		 * If the sizes are the same
823 		 *
824 		 *  o	if the file types differ, take the relocatable object,
825 		 *	else
826 		 *
827 		 *  o	if one symbol is weak and the other is non-weak, take
828 		 *	the non-weak symbol, else
829 		 *
830 		 *  o	take the first reference.
831 		 */
832 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN))
833 			return;
834 		else if (((ofile != nfile) && (nfile == ET_REL)) ||
835 		    (((obind == STB_WEAK) && (nbind != STB_WEAK)) &&
836 		    (!((ofile != nfile) && (ofile == ET_REL)))))
837 			sym_override(sdp, nsym, ifl, ofl, ndx,
838 				nshndx, nsymflags);
839 		else
840 			sym_promote(sdp, nsym, ifl, ofl, ndx,
841 				nshndx, nsymflags);
842 	}
843 
844 	/*
845 	 * Enforce the largest alignment if necessary.
846 	 */
847 	if (value)
848 		sdp->sd_sym->st_value = value;
849 }
850 
851 /*
852  * Symbol resolution state table.  `Action' describes the required
853  * procedure to be called (if any).
854  */
855 static void (*Action[REF_NUM * SYM_NUM * 2][SYM_NUM])(Sym_desc *,
856 	Sym *, Ifl_desc *, Ofl_desc *, int, Word, Word) = {
857 
858 /*				defined		undef		tent	*/
859 /*				ET_REL		ET_REL		ET_REL	*/
860 
861 /*  0 defined REF_DYN_SEEN */	sym_tworeals,	sym_promote,	sym_realtent,
862 /*  1   undef REF_DYN_SEEN */	sym_override,	sym_override,	sym_override,
863 /*  2    tent REF_DYN_SEEN */	sym_realtent,	sym_promote,	sym_twotent,
864 /*  3 defined REF_DYN_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
865 /*  4   undef REF_DYN_NEED */	sym_override,	sym_override,	sym_override,
866 /*  5    tent REF_DYN_NEED */	sym_realtent,	sym_typecheck,	sym_twotent,
867 /*  6 defined REF_REL_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
868 /*  7   undef REF_REL_NEED */	sym_override,	sym_twoundefs,	sym_override,
869 /*  8    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent,
870 
871 /*				defined		undef		tent	*/
872 /*				ET_DYN		ET_DYN		ET_DYN	*/
873 
874 /*  9 defined REF_DYN_SEEN */	sym_tworeals,	sym_null,	sym_realtent,
875 /* 10   undef REF_DYN_SEEN */	sym_override,	sym_mach_check,	sym_override,
876 /* 11    tent REF_DYN_SEEN */	sym_realtent,	sym_null,	sym_twotent,
877 /* 12 defined REF_DYN_NEED */	sym_tworeals,	sym_null,	sym_realtent,
878 /* 13   undef REF_DYN_NEED */	sym_override,	sym_null,	sym_override,
879 /* 14    tent REF_DYN_NEED */	sym_realtent,	sym_null,	sym_twotent,
880 /* 15 defined REF_REL_NEED */	sym_tworeals,	sym_null,	sym_realtent,
881 /* 16   undef REF_REL_NEED */	sym_override,	sym_mach_check,	sym_override,
882 /* 17    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent
883 
884 };
885 
886 uintptr_t
887 sym_resolve(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl, int ndx,
888 	Word nshndx, Word nsymflags)
889 {
890 	int		row, column;		/* State table coordinates */
891 	Sym		*osym = sdp->sd_sym;
892 	Is_desc		*isp;
893 	Half		nfile = ifl->ifl_ehdr->e_type;
894 
895 	/*
896 	 * Determine the original symbols definition (defines row in Action[]).
897 	 */
898 	if (sdp->sd_flags & FLG_SY_TENTSYM)
899 		row = SYM_TENTATIVE;
900 	else if (sdp->sd_shndx == SHN_UNDEF)
901 		row = SYM_UNDEFINED;
902 	else
903 		row = SYM_DEFINED;
904 
905 	/*
906 	 * If the input file is an implicit shared object then we don't need
907 	 * to bind to any symbols within it other than to verify that any
908 	 * undefined references will be closed (implicit shared objects are only
909 	 * processed when no undefined symbols are required as a result of the
910 	 * link-edit (see process_dynamic())).
911 	 */
912 	if ((nfile == ET_DYN) && !(ifl->ifl_flags & FLG_IF_NEEDED) &&
913 	    (row != SYM_UNDEFINED))
914 		return (1);
915 
916 	/*
917 	 * Finish computing the Action[] row by applying the symbols reference
918 	 * together with the input files type.
919 	 */
920 	row = row + (REF_NUM * sdp->sd_ref);
921 	if (nfile == ET_DYN)
922 		row += (REF_NUM * SYM_NUM);
923 
924 	/*
925 	 * Determine the new symbols definition (defines column in Action[]).
926 	 */
927 	if ((nsymflags & FLG_SY_SPECSEC) &&
928 	    (nshndx == SHN_COMMON)) {
929 		column = SYM_TENTATIVE;
930 		nsymflags |= FLG_SY_TENTSYM;
931 #if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
932 	} else if ((nsymflags & FLG_SY_SPECSEC) &&
933 	    (nshndx == SHN_X86_64_LCOMMON)) {
934 		column = SYM_TENTATIVE;
935 		nsymflags |= FLG_SY_TENTSYM;
936 #endif
937 	} else if ((nshndx == SHN_UNDEF) || (nshndx == SHN_SUNW_IGNORE)) {
938 		column = SYM_UNDEFINED;
939 		nshndx = SHN_UNDEF;
940 	} else {
941 		column = SYM_DEFINED;
942 		/*
943 		 * If the new symbol is from a shared library and it is
944 		 * associated with a SHT_NOBITS section then this symbol
945 		 * originated from a tentative symbol.
946 		 */
947 		if (((nsymflags & FLG_SY_SPECSEC) == 0) && (nfile == ET_DYN)) {
948 			isp = ifl->ifl_isdesc[nshndx];
949 			if (isp && (isp->is_shdr->sh_type == SHT_NOBITS)) {
950 				column = SYM_TENTATIVE;
951 				nsymflags |= FLG_SY_TENTSYM;
952 			}
953 		}
954 	}
955 
956 	DBG_CALL(Dbg_syms_resolving1(ndx, sdp->sd_name, row, column));
957 	DBG_CALL(Dbg_syms_resolving2(ifl->ifl_ehdr, osym, nsym, sdp, ifl));
958 
959 	/*
960 	 * Record the input filename on the defined files list for possible
961 	 * later diagnostics.  The `sa_dfiles' list is used to maintain the list
962 	 * of shared objects that define the same symbol.  This list is only
963 	 * generated when the -m option is in effect and is used to list
964 	 * multiple (interposed) definitions of a symbol (refer to ldmap_out()).
965 	 */
966 	if ((ofl->ofl_flags & FLG_OF_GENMAP) && (nshndx != SHN_UNDEF) &&
967 	    ((nsymflags & FLG_SY_SPECSEC) == 0))
968 		if (list_appendc(&sdp->sd_aux->sa_dfiles, ifl->ifl_name) == 0)
969 			return (S_ERROR);
970 
971 	/*
972 	 * Perform the required resolution.
973 	 */
974 	Action[row][column](sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
975 
976 	/*
977 	 * If the symbol has been resolved to the new input file, and this is
978 	 * a versioned relocatable object, then the version information of the
979 	 * new symbol must be promoted to the versioning of the output file.
980 	 */
981 	if ((sdp->sd_file == ifl) && (nfile == ET_REL) && (ifl->ifl_versym) &&
982 	    (nshndx != SHN_UNDEF))
983 		vers_promote(sdp, ndx, ifl, ofl);
984 
985 	/*
986 	 * Determine whether a mapfile reference has been satisfied.  Mapfile
987 	 * symbol references augment symbols that should be contributed from
988 	 * the relocatable objects used to build the output image.  If a
989 	 * relocatable object doesn't provide one of the mapfile symbol
990 	 * references then somethings amiss, and will be flagged during symbol
991 	 * validation.
992 	 */
993 	if ((nfile == ET_REL) && ((sdp->sd_flags &
994 	    (FLG_SY_MAPREF | FLG_SY_MAPUSED)) == FLG_SY_MAPREF)) {
995 		/*
996 		 * Extern and parent references are satisfied by references from
997 		 * a relocatable object.  Note that we let *any* symbol type
998 		 * satisfy this reference, to be as flexible as possible with
999 		 * user written mapfiles.  It could be questionable, for
1000 		 * example, if what a user expects to be an extern reference is
1001 		 * actually found to be a definition in a relocatable object.
1002 		 *
1003 		 * Any other mapfile reference (typically for versioning
1004 		 * information) simply augments a relocatables definition.
1005 		 */
1006 		if ((sdp->sd_flags & (FLG_SY_EXTERN | FLG_SY_PARENT)) ||
1007 		    ((sdp->sd_shndx != SHN_UNDEF) &&
1008 		    (sdp->sd_ref == REF_REL_NEED)))
1009 			sdp->sd_flags |= FLG_SY_MAPUSED;
1010 	}
1011 
1012 	DBG_CALL(Dbg_syms_resolved(ifl->ifl_ehdr, sdp));
1013 
1014 	return (1);
1015 }
1016