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