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