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