xref: /illumos-gate/usr/src/cmd/sgs/libld/common/resolve.c (revision 15d9d0b5)
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 static void
61 sym_visibility_diag(Error err, Sym_desc *sdp, Sym *osym, Sym *nsym,
62     Ifl_desc *ifl, Ofl_desc *ofl)
63 {
64 	Conv_inv_buf_t	inv_obuf, inv_nbuf;
65 
66 	eprintf(ofl->ofl_lml, err, MSG_INTL(MSG_SYM_CONFVIS),
67 	    demangle(sdp->sd_name));
68 	eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_VISTYPES),
69 	    sdp->sd_file->ifl_name, conv_sym_other(osym->st_other, &inv_obuf),
70 	    ifl->ifl_name, conv_sym_other(nsym->st_other, &inv_nbuf));
71 
72 	if (err == ERR_FATAL)
73 		ofl->ofl_flags |= FLG_OF_FATAL;
74 	else
75 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
76 		    ifl->ifl_name);
77 }
78 
79 /*
80  * STV_VISIBILITY rules for STV_DEFAULT/INTERNAL/HIDDEN/PROTECTED say that the
81  * most restrictive visibility value should be taken.  The precedence is:
82  *
83  *    (most restrictive) INTERNAL -> HIDDEN -> PROTECTED -> DEFAULT  (least)
84  *
85  * The STV_EXPORT and STV_SINGLETON visibilities are slightly different, in that
86  * the visibility must remain global and can not be reduced in any way.
87  *
88  * Resolution of different visibilities between two relocatable objects can
89  * take the following actions:
90  *
91  *  i.     if applicable, the most restrictive action is silently taken.
92  *  ii.    if a mapfile visibility definition competes with a more restrictive
93  *         relocatable object definition, then a warning is generated, but the
94  *         the more restrictive visibility is taken.
95  *  iii.   in the case of conflicts with an EXPORTED or SINGLETON symbol with
96  *	   any type of visibility between relocatable objects, the combination
97  *	   is deemed fatal.
98  *
99  *                                  new visibility
100  *                    D        I         H         P         X         S
101  *                 ------------------------------------------------------------
102  *              D |   D        I(mw)     H(mw)     P         X         S
103  *   original   I |   I        I         I         I         X(mw/of)  S(mw/of)
104  *  visibility  H |   H        I(mw)     H         H         X(mw/of)  S(mw/of)
105  *              P |   P        I(mw)     H(mw)     P         X(mw/of)  S(mw/of)
106  *              X |   X        I(mw/of)  H(mw/of)  P(mw/of)  X         S
107  *              S |   S        I(mw/of)  H(mw/of)  P(mw/of)  S         S
108  * where:
109  *
110  *  mw -  mapfile warning: if the original symbol originates from a mapfile
111  *        then warn the user that their scope definition is being overridden.
112  *  of -  object definitions are fatal: any combination of relocatable object
113  *        visibilities that conflict with a SINGLETON and EXPORTED are fatal.
114  *
115  * Note, an eliminate symbol (STV_ELIMINATE) is treated as hidden (STV_HIDDEN)
116  * for processing through this state table.
117  */
118 static Half
119 sym_visibility(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl)
120 {
121 	Sym	*osym = sdp->sd_sym;
122 	uchar_t	wovis, ovis;
123 	uchar_t	wnvis, nvis;
124 
125 	wovis = ovis = ELF_ST_VISIBILITY(osym->st_other);
126 	wnvis = nvis = ELF_ST_VISIBILITY(nsym->st_other);
127 
128 	/*
129 	 * If the original visibilities are eliminate, assign them hidden for
130 	 * the state table processing.  The original visibility, rather than
131 	 * the working visibility, will be returned to the caller.
132 	 */
133 	if (wovis == STV_ELIMINATE)
134 		wovis = STV_HIDDEN;
135 	if (wnvis == STV_ELIMINATE)
136 		wnvis = STV_HIDDEN;
137 
138 	/*
139 	 * The most complex visibility resolution is between two relocatable
140 	 * objects.  However, in the case of SINGLETONS we also want to catch
141 	 * any singleton definitions within shared objects.  Relocatable objects
142 	 * that bind to these symbols inherit the singleton visibility as this
143 	 * efficiently triggers ld.so.1 into carrying out the appropriate
144 	 * runtime symbol search.  Any other resolution between a relocatable
145 	 * object and a shared object will retain the relocatable objects
146 	 * visibility.
147 	 */
148 	if ((sdp->sd_ref == REF_REL_NEED) &&
149 	    (ifl->ifl_ehdr->e_type == ET_DYN)) {
150 		if ((sdp->sd_sym->st_shndx == SHN_UNDEF) &&
151 		    (nsym->st_shndx != SHN_UNDEF) && (wnvis == STV_SINGLETON))
152 			return (STV_SINGLETON);
153 		else
154 			return (ovis);
155 	}
156 	if ((sdp->sd_ref != REF_REL_NEED) &&
157 	    (ifl->ifl_ehdr->e_type == ET_REL)) {
158 		if ((sdp->sd_sym->st_shndx != SHN_UNDEF) &&
159 		    (nsym->st_shndx == SHN_UNDEF) && (wovis == STV_SINGLETON))
160 			return (STV_SINGLETON);
161 		else
162 			return (nvis);
163 	}
164 
165 	/*
166 	 * If the visibilities are the same, we're done.  If the working
167 	 * visibilities differ from the original, then one must have been
168 	 * STV_HIDDEN and the other STV_ELIMINATE.
169 	 */
170 	if (wovis == wnvis) {
171 		if (ovis == nvis)
172 			return (nvis);
173 		else
174 			return (STV_ELIMINATE);
175 	}
176 
177 	/*
178 	 * An EXPORTED symbol or SINGLETON symbol can not be demoted, any
179 	 * conflicting visibility from another object is fatal.  A conflicting
180 	 * visibility from a mapfile produces a warning, as the mapfile
181 	 * definition can be overridden.
182 	 */
183 	if ((wnvis == STV_EXPORTED) || (wnvis == STV_SINGLETON)) {
184 		if ((wovis != STV_DEFAULT) && (wovis != STV_EXPORTED) &&
185 		    (wovis != STV_SINGLETON)) {
186 			if (sdp->sd_flags1 & FLG_SY1_MAPFILE) {
187 				sym_visibility_diag(ERR_WARNING, sdp, osym,
188 				    nsym, ifl, ofl);
189 			} else {
190 				sym_visibility_diag(ERR_FATAL, sdp, osym,
191 				    nsym, ifl, ofl);
192 			}
193 		}
194 		return (nvis);
195 	}
196 	if (wovis == STV_SINGLETON) {
197 		if ((wnvis == STV_EXPORTED) || (wnvis == STV_DEFAULT))
198 			return (STV_SINGLETON);
199 		if (sdp->sd_flags1 & FLG_SY1_MAPFILE) {
200 			sym_visibility_diag(ERR_WARNING, sdp, osym,
201 			    nsym, ifl, ofl);
202 		} else {
203 			sym_visibility_diag(ERR_FATAL, sdp, osym,
204 			    nsym, ifl, ofl);
205 		}
206 		return (nvis);
207 	}
208 	if (wovis == STV_EXPORTED) {
209 		if (wnvis == STV_SINGLETON)
210 			return (STV_SINGLETON);
211 		if (wnvis == STV_DEFAULT)
212 			return (STV_EXPORTED);
213 		if (sdp->sd_flags1 & FLG_SY1_MAPFILE) {
214 			sym_visibility_diag(ERR_WARNING, sdp, osym,
215 			    nsym, ifl, ofl);
216 		} else {
217 			sym_visibility_diag(ERR_FATAL, sdp, osym,
218 			    nsym, ifl, ofl);
219 		}
220 		return (nvis);
221 	}
222 
223 	/*
224 	 * Now that symbols with the same visibility, and all instances of
225 	 * SINGLETON's have been dealt with, we're left with visibilities that
226 	 * differ, but can be dealt with in the order of how restrictive the
227 	 * visibilities are.  When a differing visibility originates from a
228 	 * mapfile definition, produces a warning, as the mapfile definition
229 	 * can be overridden by the relocatable object.
230 	 */
231 	if ((wnvis == STV_INTERNAL) || (wovis == STV_INTERNAL)) {
232 		if ((wnvis == STV_INTERNAL) &&
233 		    (sdp->sd_flags1 & FLG_SY1_MAPFILE)) {
234 			sym_visibility_diag(ERR_WARNING, sdp, osym, nsym,
235 			    ifl, ofl);
236 		}
237 		return (STV_INTERNAL);
238 
239 	} else if ((wnvis == STV_HIDDEN) || (wovis == STV_HIDDEN)) {
240 		if ((wnvis == STV_HIDDEN) &&
241 		    (sdp->sd_flags1 & FLG_SY1_MAPFILE)) {
242 			sym_visibility_diag(ERR_WARNING, sdp, osym, nsym,
243 			    ifl, ofl);
244 		}
245 
246 		/*
247 		 * In the case of STV_ELIMINATE and STV_HIDDEN, the working
248 		 * visibility can differ from the original visibility, so make
249 		 * sure to return the original visibility.
250 		 */
251 		if ((ovis == STV_ELIMINATE) || (nvis == STV_ELIMINATE))
252 			return (STV_ELIMINATE);
253 		else
254 			return (STV_HIDDEN);
255 
256 	} else if ((wnvis == STV_PROTECTED) || (wovis == STV_PROTECTED))
257 		return (STV_PROTECTED);
258 
259 	return (STV_DEFAULT);
260 }
261 
262 /*
263  * Check if two symbols types are compatible
264  */
265 /*ARGSUSED4*/
266 static void
267 sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
268 	int ndx, Word nshndx, Word nsymflags)
269 {
270 	uchar_t		otype = ELF_ST_TYPE(sdp->sd_sym->st_info);
271 	uchar_t		ntype = ELF_ST_TYPE(nsym->st_info);
272 	Conv_inv_buf_t	inv_buf1, inv_buf2;
273 
274 	/*
275 	 * Perform any machine specific type checking.
276 	 */
277 	if (ld_mach_sym_typecheck(sdp, nsym, ifl, ofl))
278 		return;
279 
280 	/*
281 	 * NOTYPE's can be combined with other types, only give an error if
282 	 * combining two differing types without NOTYPE.
283 	 */
284 	if ((otype == ntype) || (otype == STT_NOTYPE) || (ntype == STT_NOTYPE))
285 		return;
286 
287 	eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
288 	    demangle(sdp->sd_name));
289 	eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
290 	    sdp->sd_file->ifl_name,
291 	    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype, 0, &inv_buf1),
292 	    ifl->ifl_name,
293 	    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype, 0, &inv_buf2));
294 }
295 
296 /*ARGSUSED4*/
297 static void
298 sym_mach_check(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
299 	int ndx, Word nshndx, Word nsymflags)
300 {
301 	/*
302 	 * Perform any machine specific type checking.
303 	 */
304 	(void) ld_mach_sym_typecheck(sdp, nsym, ifl, ofl);
305 }
306 
307 /*
308  * Promote the symbols reference.
309  */
310 static void
311 /* ARGSUSED4 */
312 sym_promote(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
313     int ndx, Word nshndx, Word nsymflags)
314 {
315 	Word	shndx = nsym->st_shndx;
316 
317 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
318 
319 	/*
320 	 * If the old symbol is from a shared object and the new symbol is a
321 	 * reference from a relocatable object, promote the old symbols
322 	 * reference.
323 	 */
324 	if ((sdp->sd_ref == REF_DYN_SEEN) &&
325 	    (ifl->ifl_ehdr->e_type == ET_REL)) {
326 		sdp->sd_ref = REF_DYN_NEED;
327 
328 		/*
329 		 * If this is an undefined symbol it must be a relocatable
330 		 * object overriding a shared object.  In this case also
331 		 * override the reference name so that any undefined symbol
332 		 * diagnostics will refer to the relocatable object name.
333 		 */
334 		if (shndx == SHN_UNDEF)
335 			sdp->sd_aux->sa_rfile = ifl->ifl_name;
336 
337 		/*
338 		 * If this symbol is an undefined, or common, determine whether
339 		 * it is a global or weak reference (see build_osym(), where
340 		 * REF_DYN_NEED definitions are returned back to undefines).
341 		 */
342 		if (((shndx == SHN_UNDEF) || ((nsymflags & FLG_SY_SPECSEC) &&
343 		    (shndx == SHN_COMMON))) &&
344 		    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
345 			sdp->sd_flags |= FLG_SY_GLOBREF;
346 
347 	} else if ((shndx != SHN_UNDEF) && (ofl->ofl_dtflags_1 & DF_1_TRANS) &&
348 	    (sdp->sd_aux->sa_bindto == 0) && (sdp->sd_ref == REF_REL_NEED) &&
349 	    (ifl->ifl_ehdr->e_type == ET_DYN)) {
350 		/*
351 		 * If building a translator then record the symbol
352 		 * we would 'bindto' with direct bindings.
353 		 */
354 		sdp->sd_aux->sa_bindto = ifl;
355 	}
356 }
357 
358 /*
359  * Override a symbol.
360  */
361 static void
362 sym_override(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
363     int ndx, Word nshndx, Word nsymflags)
364 {
365 	Sym	*osym = sdp->sd_sym;
366 	Word	link;
367 
368 	/*
369 	 * In the case of a WEAK UNDEF symbol don't let a symbol from an
370 	 * unavailable object override the symbol definition.  This is because
371 	 * this symbol *may* not be present in a future object and by promoting
372 	 * this symbol we are actually causing bindings (PLTS) to be formed
373 	 * to this symbol.  Instead let the 'generic' weak binding take place.
374 	 */
375 	if ((ELF_ST_BIND(osym->st_info) == STB_WEAK) &&
376 	    (sdp->sd_sym->st_shndx == SHN_UNDEF) &&
377 	    ((ifl->ifl_flags & FLG_IF_NEEDED) == 0))
378 		return;
379 
380 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
381 
382 	/*
383 	 * This symbol has already been compared to an SO definition,
384 	 * as per the runtime behavior, ignore extra definitions.
385 	 */
386 	if ((sdp->sd_flags & FLG_SY_SOFOUND) &&
387 	    (ifl->ifl_ehdr->e_type == ET_DYN))
388 		return;
389 
390 	/*
391 	 * Mark the symbol as available and copy the new symbols contents.
392 	 */
393 	sdp->sd_flags &= ~FLG_SY_NOTAVAIL;
394 	*osym = *nsym;
395 	sdp->sd_shndx = nshndx;
396 	sdp->sd_flags &= ~FLG_SY_SPECSEC;
397 	sdp->sd_flags |= (nsymflags & (FLG_SY_SPECSEC | FLG_SY_TENTSYM));
398 
399 	/*
400 	 * If the new symbol has PROTECTED visibility, mark it.  If a PROTECTED
401 	 * symbol is copy relocated, a warning message will be printed.  See
402 	 * reloc_exec().
403 	 */
404 	if (ELF_ST_VISIBILITY(nsym->st_other) == STV_PROTECTED)
405 		sdp->sd_flags |= FLG_SY_PROT;
406 	else
407 		sdp->sd_flags &= ~FLG_SY_PROT;
408 
409 	/*
410 	 * Establish the symbols reference.  If the new symbol originates from a
411 	 * relocatable object then this reference becomes needed, otherwise
412 	 * the new symbol must be from a shared object.  In this case only
413 	 * promote the symbol to needed if we presently have a reference from a
414 	 * relocatable object.
415 	 */
416 	if (ifl->ifl_ehdr->e_type == ET_REL) {
417 		sdp->sd_ref = REF_REL_NEED;
418 
419 		if (nsym->st_shndx == SHN_UNDEF) {
420 			/*
421 			 * If this is an undefined symbol it must be a
422 			 * relocatable object overriding a shared object.  In
423 			 * this case also override the reference name so that
424 			 * any undefined symbol diagnostics will refer to the
425 			 * relocatable object name.
426 			 */
427 			sdp->sd_aux->sa_rfile = ifl->ifl_name;
428 		} else {
429 			/*
430 			 * Under -Bnodirect, all exported interfaces that have
431 			 * not explicitly been defined protected or directly
432 			 * bound to, are tagged to prevent direct binding.
433 			 */
434 			if ((ofl->ofl_flags1 & FLG_OF1_ALNODIR) &&
435 			    ((sdp->sd_flags1 &
436 			    (FLG_SY1_PROTECT | FLG_SY1_DIR)) == 0))
437 				sdp->sd_flags1 |= FLG_SY1_NDIR;
438 		}
439 
440 		/*
441 		 * If this symbol is an undefined, or common, determine whether
442 		 * it is a global or weak reference (see build_osym(), where
443 		 * REF_DYN_NEED definitions are returned back to undefines).
444 		 */
445 		if (((nsym->st_shndx == SHN_UNDEF) ||
446 		    ((nsymflags & FLG_SY_SPECSEC) &&
447 		    (nsym->st_shndx == SHN_COMMON))) &&
448 		    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
449 			sdp->sd_flags |= FLG_SY_GLOBREF;
450 		else
451 			sdp->sd_flags &= ~FLG_SY_GLOBREF;
452 	} else {
453 		if (sdp->sd_ref == REF_REL_NEED)
454 			sdp->sd_ref = REF_DYN_NEED;
455 
456 		/*
457 		 * Determine the symbols availability.  A symbol is determined
458 		 * to be unavailable if it belongs to a version of a shared
459 		 * object that this user does not wish to use, or if it belongs
460 		 * to an implicit shared object.
461 		 */
462 		if (ifl->ifl_vercnt) {
463 			Ver_index	*vip;
464 			Half		vndx = ifl->ifl_versym[ndx];
465 
466 			sdp->sd_aux->sa_dverndx = vndx;
467 			vip = &ifl->ifl_verndx[vndx];
468 			if (!(vip->vi_flags & FLG_VER_AVAIL)) {
469 				sdp->sd_flags |= FLG_SY_NOTAVAIL;
470 				/*
471 				 * If this is the first occurrence of an
472 				 * unavailable symbol record it for possible
473 				 * use in later error diagnostics
474 				 * (see sym_undef).
475 				 */
476 				if (!(sdp->sd_aux->sa_vfile))
477 					sdp->sd_aux->sa_vfile = ifl->ifl_name;
478 			}
479 		}
480 		if (!(ifl->ifl_flags & FLG_IF_NEEDED))
481 			sdp->sd_flags |= FLG_SY_NOTAVAIL;
482 	}
483 
484 	/*
485 	 * Make sure any symbol association maintained by the original symbol
486 	 * is cleared and then update the symbols file reference.
487 	 */
488 	if ((link = sdp->sd_aux->sa_linkndx) != 0) {
489 		Sym_desc *	_sdp;
490 
491 		_sdp = sdp->sd_file->ifl_oldndx[link];
492 		_sdp->sd_aux->sa_linkndx = 0;
493 		sdp->sd_aux->sa_linkndx = 0;
494 	}
495 	sdp->sd_file = ifl;
496 
497 	/*
498 	 * Update the input section descriptor to that of the new input file
499 	 */
500 	if (((nsymflags & FLG_SY_SPECSEC) == 0) &&
501 	    (nsym->st_shndx != SHN_UNDEF)) {
502 		if ((sdp->sd_isc = ifl->ifl_isdesc[nshndx]) == 0) {
503 			eprintf(ofl->ofl_lml, ERR_FATAL,
504 			    MSG_INTL(MSG_SYM_NOSECDEF), demangle(sdp->sd_name),
505 			    ifl->ifl_name);
506 			ofl->ofl_flags |= FLG_OF_FATAL;
507 		}
508 	}
509 }
510 
511 /*
512  * Resolve two undefines (only called for two relocatable objects).
513  */
514 static void
515 sym_twoundefs(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
516 	int ndx, Word nshndx, Word nsymflags)
517 {
518 	Sym	*osym = sdp->sd_sym;
519 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
520 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
521 
522 	/*
523 	 * If two relocatable objects define a weak and non-weak undefined
524 	 * reference, take the non-weak definition.
525 	 *
526 	 *		-- or --
527 	 *
528 	 * If two relocatable objects define a NOTYPE & another, then
529 	 * take the other.
530 	 */
531 	if (((obind == STB_WEAK) && (nbind != STB_WEAK)) ||
532 	    (obind == STT_NOTYPE) && (nbind != STT_NOTYPE)) {
533 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
534 		return;
535 	}
536 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
537 }
538 
539 /*
540  * Resolve two real definitions.
541  */
542 static void
543 sym_tworeals(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
544 	int ndx, Word nshndx, Word nsymflags)
545 {
546 	Conv_inv_buf_t inv_buf1, inv_buf2;
547 	Sym	*osym = sdp->sd_sym;
548 	uchar_t	otype = ELF_ST_TYPE(osym->st_info);
549 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
550 	uchar_t	ntype = ELF_ST_TYPE(nsym->st_info);
551 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
552 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
553 	Half	nfile = ifl->ifl_ehdr->e_type;
554 	int	warn = 0;
555 
556 	/*
557 	 * If both definitions are from relocatable objects, and have non-weak
558 	 * binding then this is a fatal condition.
559 	 */
560 	if ((ofile == ET_REL) && (nfile == ET_REL) && (obind != STB_WEAK) &&
561 	    (nbind != STB_WEAK) && (!(ofl->ofl_flags & FLG_OF_MULDEFS))) {
562 		eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_SYM_MULDEF),
563 		    demangle(sdp->sd_name));
564 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
565 		    sdp->sd_file->ifl_name,
566 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
567 		    0, &inv_buf1), ifl->ifl_name,
568 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
569 		    0, &inv_buf2));
570 		ofl->ofl_flags |= FLG_OF_FATAL;
571 		return;
572 	}
573 
574 	/*
575 	 * Perform any machine specific type checking.
576 	 */
577 	if (ld_mach_sym_typecheck(sdp, nsym, ifl, ofl))
578 		return;
579 
580 	/*
581 	 * Check the symbols type and size.
582 	 */
583 	if (otype != ntype) {
584 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
585 		    demangle(sdp->sd_name));
586 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
587 		    sdp->sd_file->ifl_name,
588 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
589 		    0, &inv_buf1), ifl->ifl_name,
590 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
591 		    0, &inv_buf2));
592 		warn++;
593 	} else if ((otype == STT_OBJECT) && (osym->st_size != nsym->st_size)) {
594 		if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
595 			eprintf(ofl->ofl_lml, ERR_WARNING,
596 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
597 			    MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
598 			    EC_XWORD(osym->st_size), ifl->ifl_name,
599 			    EC_XWORD(nsym->st_size));
600 			warn++;
601 		}
602 	}
603 
604 	/*
605 	 * Having provided the user with any necessary warnings, take the
606 	 * appropriate symbol:
607 	 *
608 	 *  o	if one symbol is from a shared object and the other is from a
609 	 *	relocatable object, take the relocatable objects symbol (the
610 	 *	run-time linker is always going to find the relocatable object
611 	 *	symbol regardless of the binding), else
612 	 *
613 	 * o	if both symbols are from relocatable objects and one symbol is
614 	 *	weak take the non-weak symbol (two non-weak symbols would have
615 	 *	generated the fatal error condition above unless -z muldefs is
616 	 *	in effect), else
617 	 *
618 	 *  o	take the first symbol definition encountered.
619 	 */
620 	if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
621 		if (warn)
622 			eprintf(ofl->ofl_lml, ERR_NONE,
623 			    MSG_INTL(MSG_SYM_DEFTAKEN), sdp->sd_file->ifl_name);
624 		return;
625 	} else if ((nfile == ET_REL) && ((ofile == ET_DYN) ||
626 	    ((obind == STB_WEAK) && (nbind != STB_WEAK)))) {
627 		if (warn)
628 			eprintf(ofl->ofl_lml, ERR_NONE,
629 			    MSG_INTL(MSG_SYM_DEFTAKEN), ifl->ifl_name);
630 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
631 		return;
632 	} else {
633 		if (warn)
634 			eprintf(ofl->ofl_lml, ERR_NONE,
635 			    MSG_INTL(MSG_SYM_DEFTAKEN), sdp->sd_file->ifl_name);
636 		sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
637 		return;
638 	}
639 }
640 
641 /*
642  * Resolve a real and tentative definition.
643  */
644 static void
645 sym_realtent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
646 	int ndx, Word nshndx, Word nsymflags)
647 {
648 	Conv_inv_buf_t inv_buf1, inv_buf2;
649 	Sym	*osym = sdp->sd_sym;
650 	uchar_t otype = ELF_ST_TYPE(osym->st_info);
651 	uchar_t obind = ELF_ST_BIND(osym->st_info);
652 	uchar_t ntype = ELF_ST_TYPE(nsym->st_info);
653 	uchar_t nbind = ELF_ST_BIND(nsym->st_info);
654 	Boolean	otent = FALSE, ntent = FALSE;
655 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
656 	Half	nfile = ifl->ifl_ehdr->e_type;
657 	int	warn = 0;
658 	uchar_t	ovis = ELF_ST_VISIBILITY(osym->st_other);
659 	uchar_t	nvis = ELF_ST_VISIBILITY(nsym->st_other);
660 
661 	/*
662 	 * Special rules for functions.
663 	 *
664 	 *  o	If both definitions are from relocatable objects, have the same
665 	 *	binding (ie. two weaks or two non-weaks), and the real
666 	 *	definition is a function (the other must be tentative), treat
667 	 *	this as a multiply defined symbol error, else
668 	 *
669 	 *  o	if the real symbol definition is a function within a shared
670 	 *	library and the tentative symbol is a relocatable object, and
671 	 *	the tentative is not weak and the function real, then retain the
672 	 *	tentative definition.
673 	 */
674 	if ((ofile == ET_REL) && (nfile == ET_REL) && (obind == nbind) &&
675 	    ((otype == STT_FUNC) || (ntype == STT_FUNC))) {
676 		if (ofl->ofl_flags & FLG_OF_MULDEFS) {
677 			eprintf(ofl->ofl_lml, ERR_WARNING,
678 			    MSG_INTL(MSG_SYM_DIFFTYPE), demangle(sdp->sd_name));
679 			sym_promote(sdp, nsym, ifl, ofl, ndx,
680 			    nshndx, nsymflags);
681 		} else {
682 			eprintf(ofl->ofl_lml, ERR_FATAL,
683 			    MSG_INTL(MSG_SYM_MULDEF), demangle(sdp->sd_name));
684 			ofl->ofl_flags |= FLG_OF_FATAL;
685 		}
686 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
687 		    sdp->sd_file->ifl_name,
688 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
689 		    0, &inv_buf1), ifl->ifl_name,
690 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
691 		    0, &inv_buf2));
692 		return;
693 	} else if (ofile != nfile) {
694 
695 
696 		if ((ofile == ET_DYN) && (otype == STT_FUNC)) {
697 			if ((otype != STB_WEAK) && (ntype == STB_WEAK))
698 				return;
699 			else {
700 				sym_override(sdp, nsym, ifl, ofl, ndx,
701 				    nshndx, nsymflags);
702 				return;
703 			}
704 		}
705 		if ((nfile == ET_DYN) && (ntype == STT_FUNC)) {
706 			if ((ntype != STB_WEAK) && (otype == STB_WEAK)) {
707 				sym_override(sdp, nsym, ifl, ofl, ndx,
708 				    nshndx, nsymflags);
709 				return;
710 			} else
711 				return;
712 		}
713 	}
714 
715 	if (sdp->sd_flags & FLG_SY_TENTSYM)
716 		otent = TRUE;
717 	if (nsymflags & FLG_SY_TENTSYM)
718 		ntent = TRUE;
719 
720 
721 	/*
722 	 * Check the symbols type and size.
723 	 */
724 	if (otype != ntype) {
725 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
726 		    demangle(sdp->sd_name));
727 		eprintf(ofl->ofl_lml, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
728 		    sdp->sd_file->ifl_name,
729 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
730 		    0, &inv_buf1), ifl->ifl_name,
731 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
732 		    0, &inv_buf2));
733 		warn++;
734 	} else if (osym->st_size != nsym->st_size) {
735 		/*
736 		 * If both definitions are from relocatable objects we have a
737 		 * potential fatal error condition.  If the tentative is larger
738 		 * than the real definition treat this as a multiple definition.
739 		 * Note that if only one symbol is weak, the non-weak will be
740 		 * taken.
741 		 */
742 		if (((ofile == ET_REL) && (nfile == ET_REL) &&
743 		    (obind == nbind)) &&
744 		    ((otent && (osym->st_size > nsym->st_size)) ||
745 		    (ntent && (osym->st_size < nsym->st_size)))) {
746 			eprintf(ofl->ofl_lml, ERR_FATAL,
747 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
748 			    MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
749 			    EC_XWORD(osym->st_size), ifl->ifl_name,
750 			    EC_XWORD(nsym->st_size));
751 			eprintf(ofl->ofl_lml, ERR_NONE,
752 			    MSG_INTL(MSG_SYM_TENTERR));
753 			ofl->ofl_flags |= FLG_OF_FATAL;
754 		} else {
755 			if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
756 				eprintf(ofl->ofl_lml, ERR_WARNING,
757 				    MSG_INTL(MSG_SYM_DIFFATTR),
758 				    demangle(sdp->sd_name),
759 				    MSG_INTL(MSG_STR_SIZES),
760 				    sdp->sd_file->ifl_name,
761 				    EC_XWORD(osym->st_size),
762 				    ifl->ifl_name, EC_XWORD(nsym->st_size));
763 				warn++;
764 			}
765 		}
766 	}
767 
768 	/*
769 	 * Having provided the user with any necessary warnings, take the
770 	 * appropriate symbol:
771 	 *
772 	 *  o   if the original symbol is from relocatable file and it is
773 	 *	a protected tentative symbol, take the original one.
774 	 *
775 	 *  o 	if the original symbol is from shared object and the new
776 	 *	symbol is a protected tentative symbol from a relocatable file,
777 	 *	take the new one.
778 	 *
779 	 *  o	if the original symbol is tentative, and providing the original
780 	 *	symbol isn't strong and the new symbol weak, take the real
781 	 *	symbol, else
782 	 *
783 	 *  o	if the original symbol is weak and the new tentative symbol is
784 	 *	strong take the new symbol.
785 	 *
786 	 * Refer to the System V ABI Page 4-27 for a description of the binding
787 	 * requirements of tentative and weak symbols.
788 	 */
789 	if ((ofile == ET_REL) && (nfile == ET_DYN) && (otent == TRUE) &&
790 	    (ovis == STV_PROTECTED)) {
791 		return;
792 	}
793 
794 	if ((ofile == ET_DYN) && (nfile == ET_REL) && (ntent == TRUE) &&
795 	    (nvis == STV_PROTECTED)) {
796 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
797 		return;
798 	}
799 
800 	if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
801 		if (warn)
802 			eprintf(ofl->ofl_lml, ERR_NONE,
803 			    MSG_INTL(MSG_SYM_DEFTAKEN), sdp->sd_file->ifl_name);
804 		return;
805 	}
806 
807 	if (((otent) && (!((obind != STB_WEAK) && (nbind == STB_WEAK)))) ||
808 	    ((obind == STB_WEAK) && (nbind != STB_WEAK))) {
809 		if (warn)
810 			eprintf(ofl->ofl_lml, ERR_NONE,
811 			    MSG_INTL(MSG_SYM_DEFTAKEN), ifl->ifl_name);
812 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
813 		return;
814 	} else {
815 		if (warn)
816 			eprintf(ofl->ofl_lml, ERR_NONE,
817 			    MSG_INTL(MSG_SYM_DEFTAKEN), sdp->sd_file->ifl_name);
818 		sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
819 		return;
820 	}
821 }
822 
823 /*
824  * Resolve two tentative symbols.
825  */
826 static void
827 sym_twotent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
828 	int ndx, Word nshndx, Word nsymflags)
829 {
830 	Sym	*osym = sdp->sd_sym;
831 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
832 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
833 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
834 	Half	nfile = ifl->ifl_ehdr->e_type;
835 	size_t	size = 0;
836 	Xword	value = 0;
837 
838 #if	defined(__x86) && defined(_ELF64)
839 	/*
840 	 * If the original and new symbols are both COMMON, but of a different
841 	 * size model, take the small one.
842 	 */
843 	if ((sdp->sd_sym->st_shndx == SHN_COMMON) &&
844 	    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
845 		/*
846 		 * Take the original symbol.
847 		 */
848 		return;
849 
850 	} else if ((sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
851 	    (nsym->st_shndx == SHN_COMMON)) {
852 		/*
853 		 * Take the new symbol.
854 		 */
855 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
856 		return;
857 	}
858 #endif
859 
860 	/*
861 	 * Check the alignment of the symbols.  This can only be tested for if
862 	 * the symbols are not real definitions to a SHT_NOBITS section (ie.
863 	 * they were originally tentative), as in this case the symbol would
864 	 * have a displacement value rather than an alignment.  In other words
865 	 * we can only test this for two relocatable objects.
866 	 */
867 	/* BEGIN CSTYLED */
868 	if ((osym->st_value != nsym->st_value) &&
869 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
870 	    (sdp->sd_sym->st_shndx == SHN_COMMON) &&
871 	    (nsymflags & FLG_SY_SPECSEC) &&
872 #if	defined(__x86) && defined(_ELF64)
873 	    (nsym->st_shndx == SHN_COMMON)) ||
874 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
875 	    (sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
876 	    (nsymflags & FLG_SY_SPECSEC) &&
877 	    (nsym->st_shndx == SHN_X86_64_LCOMMON))) {
878 #else
879 	    (nsym->st_shndx == SHN_COMMON))) {
880 #endif
881 	/* END CSTYLED */
882 
883 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
884 		const char	*file;
885 		Xword		salign;
886 		Xword		balign;
887 		uint_t		alignscompliment;
888 
889 		if (osym->st_value < nsym->st_value) {
890 			salign = osym->st_value;
891 			balign = nsym->st_value;
892 		} else {
893 			salign = nsym->st_value;
894 			balign = osym->st_value;
895 		}
896 
897 		/*
898 		 * If the smaller alignment fits smoothly into the
899 		 * larger alignment - we take it with no warning.
900 		 */
901 		if (S_ALIGN(balign, salign) == balign)
902 			alignscompliment = 1;
903 		else
904 			alignscompliment = 0;
905 
906 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
907 			eprintf(ofl->ofl_lml, ERR_WARNING,
908 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
909 			    MSG_INTL(MSG_STR_ALIGNMENTS),
910 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_value),
911 			    ifl->ifl_name, EC_XWORD(nsym->st_value));
912 
913 		/*
914 		 * Having provided the necessary warning indicate which
915 		 * relocatable object we are going to take.
916 		 *
917 		 *  o	if one symbol is weak and the other is non-weak
918 		 *	take the non-weak symbol, else
919 		 *
920 		 *  o	take the largest alignment (as we still have to check
921 		 *	the symbols size simply save the largest value for
922 		 *	updating later).
923 		 */
924 		if ((obind == STB_WEAK) && (nbind != STB_WEAK))
925 			file = ifl->ifl_name;
926 		else if (obind != nbind)
927 			file = sdp->sd_file->ifl_name;
928 		else {
929 			emsg = MSG_INTL(MSG_SYM_LARGER);
930 			value = balign;
931 		}
932 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
933 			eprintf(ofl->ofl_lml, ERR_NONE, emsg, file);
934 	}
935 
936 	/*
937 	 * Check the size of the symbols.
938 	 */
939 	if (osym->st_size != nsym->st_size) {
940 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
941 		const char	*file;
942 
943 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
944 			eprintf(ofl->ofl_lml, ERR_WARNING,
945 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
946 			    MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
947 			    EC_XWORD(osym->st_size), ifl->ifl_name,
948 			    EC_XWORD(nsym->st_size));
949 
950 
951 		/*
952 		 * This symbol has already been compared to an SO definition,
953 		 * as per the runtime behavior, ignore extra definitions.
954 		 */
955 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
956 			if (!(ofl->ofl_flags & FLG_OF_NOWARN))
957 				eprintf(ofl->ofl_lml, ERR_NONE, emsg,
958 				    sdp->sd_file->ifl_name);
959 			return;
960 		}
961 
962 		/*
963 		 * Having provided the necessary warning indicate what course
964 		 * of action we are going to take.
965 		 *
966 		 *  o	if the file types differ, take the relocatable object
967 		 *	and apply the largest symbol size, else
968 		 *  o	if one symbol is weak and the other is non-weak, take
969 		 *	the non-weak symbol, else
970 		 *  o	simply take the largest symbol reference.
971 		 */
972 		if (nfile != ofile) {
973 			if (nfile == ET_REL) {
974 				file = ifl->ifl_name;
975 				if (osym->st_size > nsym->st_size) {
976 					size = (size_t)osym->st_size;
977 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
978 				}
979 				sym_override(sdp, nsym, ifl, ofl, ndx,
980 				    nshndx, nsymflags);
981 			} else {
982 				file = sdp->sd_file->ifl_name;
983 				if (osym->st_size < nsym->st_size) {
984 					size = (size_t)nsym->st_size;
985 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
986 				}
987 				sym_promote(sdp, nsym, ifl, ofl, ndx,
988 				    nshndx, nsymflags);
989 			}
990 		} else if (obind != nbind) {
991 			if ((obind == STB_WEAK) && (nbind != STB_WEAK)) {
992 				sym_override(sdp, nsym, ifl, ofl, ndx,
993 				    nshndx, nsymflags);
994 				file = ifl->ifl_name;
995 			} else
996 				file = sdp->sd_file->ifl_name;
997 		} else {
998 			if (osym->st_size < nsym->st_size) {
999 				sym_override(sdp, nsym, ifl, ofl, ndx,
1000 				    nshndx, nsymflags);
1001 				file = ifl->ifl_name;
1002 			} else
1003 				file = sdp->sd_file->ifl_name;
1004 		}
1005 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
1006 			eprintf(ofl->ofl_lml, ERR_NONE, emsg, file);
1007 		if (size)
1008 			sdp->sd_sym->st_size = (Xword)size;
1009 	} else {
1010 		/*
1011 		 * If the sizes are the same
1012 		 *
1013 		 *  o	if the file types differ, take the relocatable object,
1014 		 *	else
1015 		 *
1016 		 *  o	if one symbol is weak and the other is non-weak, take
1017 		 *	the non-weak symbol, else
1018 		 *
1019 		 *  o	take the first reference.
1020 		 */
1021 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN))
1022 			return;
1023 		else if (((ofile != nfile) && (nfile == ET_REL)) ||
1024 		    (((obind == STB_WEAK) && (nbind != STB_WEAK)) &&
1025 		    (!((ofile != nfile) && (ofile == ET_REL)))))
1026 			sym_override(sdp, nsym, ifl, ofl, ndx,
1027 			    nshndx, nsymflags);
1028 		else
1029 			sym_promote(sdp, nsym, ifl, ofl, ndx,
1030 			    nshndx, nsymflags);
1031 	}
1032 
1033 	/*
1034 	 * Enforce the largest alignment if necessary.
1035 	 */
1036 	if (value)
1037 		sdp->sd_sym->st_value = value;
1038 }
1039 
1040 /*
1041  * Symbol resolution state table.  `Action' describes the required
1042  * procedure to be called (if any).
1043  */
1044 static void (*Action[REF_NUM * SYM_NUM * 2][SYM_NUM])(Sym_desc *,
1045 	Sym *, Ifl_desc *, Ofl_desc *, int, Word, Word) = {
1046 
1047 /*				defined		undef		tent	*/
1048 /*				ET_REL		ET_REL		ET_REL	*/
1049 
1050 /*  0 defined REF_DYN_SEEN */	sym_tworeals,	sym_promote,	sym_realtent,
1051 /*  1   undef REF_DYN_SEEN */	sym_override,	sym_override,	sym_override,
1052 /*  2    tent REF_DYN_SEEN */	sym_realtent,	sym_promote,	sym_twotent,
1053 /*  3 defined REF_DYN_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
1054 /*  4   undef REF_DYN_NEED */	sym_override,	sym_override,	sym_override,
1055 /*  5    tent REF_DYN_NEED */	sym_realtent,	sym_typecheck,	sym_twotent,
1056 /*  6 defined REF_REL_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
1057 /*  7   undef REF_REL_NEED */	sym_override,	sym_twoundefs,	sym_override,
1058 /*  8    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent,
1059 
1060 /*				defined		undef		tent	*/
1061 /*				ET_DYN		ET_DYN		ET_DYN	*/
1062 
1063 /*  9 defined REF_DYN_SEEN */	sym_tworeals,	sym_null,	sym_realtent,
1064 /* 10   undef REF_DYN_SEEN */	sym_override,	sym_mach_check,	sym_override,
1065 /* 11    tent REF_DYN_SEEN */	sym_realtent,	sym_null,	sym_twotent,
1066 /* 12 defined REF_DYN_NEED */	sym_tworeals,	sym_null,	sym_realtent,
1067 /* 13   undef REF_DYN_NEED */	sym_override,	sym_null,	sym_override,
1068 /* 14    tent REF_DYN_NEED */	sym_realtent,	sym_null,	sym_twotent,
1069 /* 15 defined REF_REL_NEED */	sym_tworeals,	sym_null,	sym_realtent,
1070 /* 16   undef REF_REL_NEED */	sym_override,	sym_mach_check,	sym_override,
1071 /* 17    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent
1072 
1073 };
1074 
1075 uintptr_t
1076 ld_sym_resolve(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl, int ndx,
1077     Word nshndx, Word nsymflags)
1078 {
1079 	int		row, column;		/* State table coordinates */
1080 	Sym		*osym = sdp->sd_sym;
1081 	Is_desc		*isp;
1082 	Half		vis = 0, nfile = ifl->ifl_ehdr->e_type;
1083 	Half		oref = sdp->sd_ref;
1084 
1085 	/*
1086 	 * Determine the original symbols definition (defines row in Action[]).
1087 	 */
1088 	if (sdp->sd_flags & FLG_SY_TENTSYM)
1089 		row = SYM_TENTATIVE;
1090 	else if ((sdp->sd_sym->st_shndx == SHN_UNDEF) ||
1091 	    (sdp->sd_sym->st_shndx == SHN_SUNW_IGNORE))
1092 		row = SYM_UNDEFINED;
1093 	else
1094 		row = SYM_DEFINED;
1095 
1096 	/*
1097 	 * If the input file is an implicit shared object then we don't need
1098 	 * to bind to any symbols within it other than to verify that any
1099 	 * undefined references will be closed (implicit shared objects are only
1100 	 * processed when no undefined symbols are required as a result of the
1101 	 * link-edit (see process_dynamic())).
1102 	 */
1103 	if ((nfile == ET_DYN) && !(ifl->ifl_flags & FLG_IF_NEEDED) &&
1104 	    (row != SYM_UNDEFINED))
1105 		return (1);
1106 
1107 	/*
1108 	 * Finish computing the Action[] row by applying the symbols reference
1109 	 * together with the input files type.
1110 	 */
1111 	row = row + (REF_NUM * sdp->sd_ref);
1112 	if (nfile == ET_DYN)
1113 		row += (REF_NUM * SYM_NUM);
1114 
1115 	/*
1116 	 * If either the original or new symbol originates from a relocatable
1117 	 * object, determine the appropriate visibility for the resolved symbol.
1118 	 */
1119 	if ((oref == REF_REL_NEED) || (nfile == ET_REL))
1120 		vis = sym_visibility(sdp, nsym, ifl, ofl);
1121 
1122 	/*
1123 	 * Determine the new symbols definition (defines column in Action[]).
1124 	 */
1125 	if ((nsymflags & FLG_SY_SPECSEC) &&
1126 	    (nsym->st_shndx == SHN_COMMON)) {
1127 		column = SYM_TENTATIVE;
1128 		nsymflags |= FLG_SY_TENTSYM;
1129 #if	defined(__x86) && defined(_ELF64)
1130 	} else if ((nsymflags & FLG_SY_SPECSEC) &&
1131 	    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
1132 		column = SYM_TENTATIVE;
1133 		nsymflags |= FLG_SY_TENTSYM;
1134 #endif
1135 	} else if ((nsym->st_shndx == SHN_UNDEF) ||
1136 	    (nsym->st_shndx == SHN_SUNW_IGNORE)) {
1137 		column = SYM_UNDEFINED;
1138 		nshndx = SHN_UNDEF;
1139 	} else {
1140 		column = SYM_DEFINED;
1141 		/*
1142 		 * If the new symbol is from a shared library and it is
1143 		 * associated with a SHT_NOBITS section then this symbol
1144 		 * originated from a tentative symbol.
1145 		 */
1146 		if (((nsymflags & FLG_SY_SPECSEC) == 0) && (nfile == ET_DYN)) {
1147 			isp = ifl->ifl_isdesc[nshndx];
1148 			if (isp && (isp->is_shdr->sh_type == SHT_NOBITS)) {
1149 				column = SYM_TENTATIVE;
1150 				nsymflags |= FLG_SY_TENTSYM;
1151 			}
1152 		}
1153 	}
1154 
1155 	DBG_CALL(Dbg_syms_resolving(ofl, ndx, sdp->sd_name, row, column,
1156 	    osym, nsym, sdp, ifl));
1157 
1158 	/*
1159 	 * Record the input filename on the defined files list for possible
1160 	 * later diagnostics.  The `sa_dfiles' list is used to maintain the list
1161 	 * of shared objects that define the same symbol.  This list is only
1162 	 * generated when the -m option is in effect and is used to list
1163 	 * multiple (interposed) definitions of a symbol (refer to ldmap_out()).
1164 	 */
1165 	if ((ofl->ofl_flags & FLG_OF_GENMAP) && (nsym->st_shndx != SHN_UNDEF) &&
1166 	    ((nsymflags & FLG_SY_SPECSEC) == 0))
1167 		if (list_appendc(&sdp->sd_aux->sa_dfiles, ifl->ifl_name) == 0)
1168 			return (S_ERROR);
1169 
1170 	/*
1171 	 * Perform the required resolution.
1172 	 */
1173 	Action[row][column](sdp, nsym, ifl, ofl, ndx, nshndx, nsymflags);
1174 
1175 	/*
1176 	 * Apply any visibility requirements.  If a SINGLETON has been
1177 	 * established, make sure no symbol reduction indicators remain
1178 	 * associated with the symbol, and indicate that the symbol can not
1179 	 * be directly bound to.
1180 	 */
1181 	if ((oref == REF_REL_NEED) || (nfile == ET_REL)) {
1182 		if ((vis == STV_EXPORTED) || (vis == STV_SINGLETON)) {
1183 			sdp->sd_flags1 &= ~(FLG_SY1_PROTECT | FLG_SY1_ELIM |
1184 			    FLG_SY1_HIDDEN);
1185 
1186 			if (vis == STV_EXPORTED)
1187 				sdp->sd_flags1 |= FLG_SY1_EXPORT;
1188 			else {
1189 				sdp->sd_flags1 |=
1190 				    (FLG_SY1_NDIR | FLG_SY1_SINGLE);
1191 
1192 				if (sdp->sd_ref == REF_REL_NEED)
1193 					ofl->ofl_flags1 |= FLG_OF1_NDIRECT;
1194 			}
1195 		} else if (vis == STV_PROTECTED) {
1196 			sdp->sd_flags1 |= FLG_SY1_PROTECT;
1197 		} else if ((vis == STV_INTERNAL) || (vis == STV_HIDDEN)) {
1198 			sdp->sd_flags1 |= FLG_SY1_HIDDEN;
1199 		} else if (vis == STV_ELIMINATE) {
1200 			sdp->sd_flags1 |= (FLG_SY1_HIDDEN | FLG_SY1_ELIM);
1201 		}
1202 
1203 		sdp->sd_sym->st_other =
1204 		    (sdp->sd_sym->st_other & ~MSK_SYM_VISIBILITY) | vis;
1205 	}
1206 
1207 	/*
1208 	 * If the symbol has been resolved to the new input file, and this is
1209 	 * a versioned relocatable object, then the version information of the
1210 	 * new symbol must be promoted to the versioning of the output file.
1211 	 */
1212 	if ((sdp->sd_file == ifl) && (nfile == ET_REL) && (ifl->ifl_versym) &&
1213 	    (nsym->st_shndx != SHN_UNDEF))
1214 		ld_vers_promote(sdp, ndx, ifl, ofl);
1215 
1216 	/*
1217 	 * Determine whether a mapfile reference has been satisfied.  Mapfile
1218 	 * symbol references augment symbols that should be contributed from
1219 	 * the relocatable objects used to build the output image.  If a
1220 	 * relocatable object doesn't provide one of the mapfile symbol
1221 	 * references then somethings amiss, and will be flagged during symbol
1222 	 * validation.
1223 	 */
1224 	if ((nfile == ET_REL) && ((sdp->sd_flags &
1225 	    (FLG_SY_MAPREF | FLG_SY_MAPUSED)) == FLG_SY_MAPREF)) {
1226 		/*
1227 		 * Extern and parent references are satisfied by references from
1228 		 * a relocatable object.  Note that we let *any* symbol type
1229 		 * satisfy this reference, to be as flexible as possible with
1230 		 * user written mapfiles.  It could be questionable, for
1231 		 * example, if what a user expects to be an extern reference is
1232 		 * actually found to be a definition in a relocatable object.
1233 		 *
1234 		 * Any other mapfile reference (typically for versioning
1235 		 * information) simply augments a relocatables definition.
1236 		 */
1237 		if ((sdp->sd_flags & (FLG_SY_EXTERN | FLG_SY_PARENT)) ||
1238 		    ((sdp->sd_sym->st_shndx != SHN_UNDEF) &&
1239 		    (sdp->sd_ref == REF_REL_NEED)))
1240 			sdp->sd_flags |= FLG_SY_MAPUSED;
1241 	}
1242 
1243 	DBG_CALL(Dbg_syms_resolved(ofl, sdp));
1244 
1245 	return (1);
1246 }
1247