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