xref: /illumos-gate/usr/src/cmd/sgs/libld/common/resolve.c (revision 6a634c9d)
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 (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
27  */
28 
29 /*
30  * Symbol table resolution
31  */
32 #define	ELF_TARGET_AMD64
33 
34 #include	<stdio.h>
35 #include	<debug.h>
36 #include	"msg.h"
37 #include	"_libld.h"
38 
39 
40 /*
41  * Categorize the symbol types that are applicable to the resolution process.
42  */
43 typedef	enum {
44 	SYM_DEFINED,		/* Defined symbol (SHN_ABS or shndx != 0) */
45 	SYM_UNDEFINED,		/* Undefined symbol (SHN_UNDEF) */
46 	SYM_TENTATIVE,		/* Tentative symbol (SHN_COMMON) */
47 	SYM_NUM			/* the number of symbol types */
48 } Symtype;
49 
50 /*
51  * Do nothing.
52  */
53 /* ARGSUSED0 */
54 static void
sym_null(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)55 sym_null(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
56     int ndx, Word nshndx, sd_flag_t nsdflags)
57 {
58 }
59 
60 static void
sym_visibility_diag(Error err,Sym_desc * sdp,Sym * osym,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl)61 sym_visibility_diag(Error err, Sym_desc *sdp, Sym *osym, Sym *nsym,
62     Ifl_desc *ifl, Ofl_desc *ofl)
63 {
64 	Conv_inv_buf_t	inv_obuf, inv_nbuf;
65 
66 	/* Warnings are only issued when -z verbose is specified */
67 	if (!(ofl->ofl_flags & FLG_OF_VERBOSE) && (err != ERR_FATAL))
68 		return;
69 
70 	ld_eprintf(ofl, err, MSG_INTL(MSG_SYM_CONFVIS), demangle(sdp->sd_name));
71 	ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_VISTYPES),
72 	    sdp->sd_file->ifl_name, conv_sym_other(osym->st_other, &inv_obuf),
73 	    ifl->ifl_name, conv_sym_other(nsym->st_other, &inv_nbuf));
74 
75 	if (err != ERR_FATAL)
76 		ld_eprintf(ofl, 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
sym_visibility(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl)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_flags & FLG_SY_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_flags & FLG_SY_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_flags & FLG_SY_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_flags & FLG_SY_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_flags & FLG_SY_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
sym_typecheck(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)268 sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
269     int ndx, Word nshndx, sd_flag_t nsdflags)
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 	ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
290 	    demangle(sdp->sd_name));
291 	ld_eprintf(ofl, 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
sym_mach_check(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)300 sym_mach_check(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
301     int ndx, Word nshndx, sd_flag_t nsdflags)
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 */
sym_promote(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)316 sym_promote(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
317     int ndx, Word nshndx, sd_flag_t nsdflags)
318 {
319 	Word	shndx = nsym->st_shndx;
320 
321 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
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) || ((nsdflags & 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 	}
352 }
353 
354 /*
355  * Override a symbol.
356  */
357 static void
sym_override(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)358 sym_override(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
359     int ndx, Word nshndx, sd_flag_t nsdflags)
360 {
361 	Sym	*osym = sdp->sd_sym;
362 	Word	link;
363 
364 	/*
365 	 * In the case of a WEAK UNDEF symbol don't let a symbol from an
366 	 * unavailable object override the symbol definition.  This is because
367 	 * this symbol *may* not be present in a future object and by promoting
368 	 * this symbol we are actually causing bindings (PLTS) to be formed
369 	 * to this symbol.  Instead let the 'generic' weak binding take place.
370 	 */
371 	if ((ELF_ST_BIND(osym->st_info) == STB_WEAK) &&
372 	    (sdp->sd_sym->st_shndx == SHN_UNDEF) &&
373 	    ((ifl->ifl_flags & FLG_IF_NEEDED) == 0))
374 		return;
375 
376 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
377 
378 	/*
379 	 * This symbol has already been compared to an SO definition,
380 	 * as per the runtime behavior, ignore extra definitions.
381 	 */
382 	if ((sdp->sd_flags & FLG_SY_SOFOUND) &&
383 	    (ifl->ifl_ehdr->e_type == ET_DYN))
384 		return;
385 
386 	/*
387 	 * Mark the symbol as available and copy the new symbols contents.
388 	 */
389 	sdp->sd_flags &= ~FLG_SY_NOTAVAIL;
390 	*osym = *nsym;
391 	sdp->sd_shndx = nshndx;
392 	sdp->sd_flags &= ~FLG_SY_SPECSEC;
393 	sdp->sd_flags |= (nsdflags & (FLG_SY_SPECSEC | FLG_SY_TENTSYM));
394 
395 	/*
396 	 * If the new symbol has PROTECTED visibility, mark it.  If a PROTECTED
397 	 * symbol is copy relocated, a warning message will be printed.  See
398 	 * reloc_exec().
399 	 */
400 	if (ELF_ST_VISIBILITY(nsym->st_other) == STV_PROTECTED)
401 		sdp->sd_flags |= FLG_SY_PROT;
402 	else
403 		sdp->sd_flags &= ~FLG_SY_PROT;
404 
405 	/*
406 	 * Establish the symbols reference.  If the new symbol originates from a
407 	 * relocatable object then this reference becomes needed, otherwise
408 	 * the new symbol must be from a shared object.  In this case only
409 	 * promote the symbol to needed if we presently have a reference from a
410 	 * relocatable object.
411 	 */
412 	if (ifl->ifl_ehdr->e_type == ET_REL) {
413 		sdp->sd_ref = REF_REL_NEED;
414 
415 		if (nsym->st_shndx == SHN_UNDEF) {
416 			/*
417 			 * If this is an undefined symbol, then we can only be
418 			 * attempting to override an existing undefined symbol.
419 			 * The original symbol is either:
420 			 *
421 			 *  -	a mapfile definition
422 			 *  -	a previous relocatable object whose visibility
423 			 *	or type should be overridden by this new symbol
424 			 *  -	a previous shared object
425 			 *
426 			 * If the original undefined symbol stems from a mapfile
427 			 * then don't alter the reference file name.  Should we
428 			 * end up with some form of 'undefined' symbol error,
429 			 * the characteristics of that error are most likely to
430 			 * have originated from a mapfile.
431 			 *
432 			 * Otherwise, update the reference file name to indicate
433 			 * this symbol.
434 			 */
435 			if ((sdp->sd_flags & FLG_SY_MAPREF) == 0)
436 				sdp->sd_aux->sa_rfile = ifl->ifl_name;
437 		} else {
438 			/*
439 			 * Under -Bnodirect, all exported interfaces that have
440 			 * not explicitly been defined protected or directly
441 			 * bound to, are tagged to prevent direct binding.
442 			 */
443 			if ((ofl->ofl_flags1 & FLG_OF1_ALNODIR) &&
444 			    ((sdp->sd_flags &
445 			    (FLG_SY_PROTECT | FLG_SY_DIR)) == 0))
446 				sdp->sd_flags |= FLG_SY_NDIR;
447 		}
448 
449 		/*
450 		 * If this symbol is an undefined, or common, determine whether
451 		 * it is a global or weak reference (see build_osym(), where
452 		 * REF_DYN_NEED definitions are returned back to undefines).
453 		 */
454 		if (((nsym->st_shndx == SHN_UNDEF) ||
455 		    ((nsdflags & FLG_SY_SPECSEC) &&
456 		    (nsym->st_shndx == SHN_COMMON))) &&
457 		    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
458 			sdp->sd_flags |= FLG_SY_GLOBREF;
459 		else
460 			sdp->sd_flags &= ~FLG_SY_GLOBREF;
461 	} else {
462 		if (sdp->sd_ref == REF_REL_NEED)
463 			sdp->sd_ref = REF_DYN_NEED;
464 
465 		/*
466 		 * Determine the symbols availability.  A symbol is determined
467 		 * to be unavailable if it belongs to a version of a shared
468 		 * object that this user does not wish to use, or if it belongs
469 		 * to an implicit shared object.
470 		 */
471 		if (ifl->ifl_vercnt) {
472 			Ver_index	*vip;
473 			Half		vndx = ifl->ifl_versym[ndx];
474 
475 			sdp->sd_aux->sa_dverndx = vndx;
476 			vip = &ifl->ifl_verndx[vndx];
477 			if (!(vip->vi_flags & FLG_VER_AVAIL)) {
478 				sdp->sd_flags |= FLG_SY_NOTAVAIL;
479 				/*
480 				 * If this is the first occurrence of an
481 				 * unavailable symbol record it for possible
482 				 * use in later error diagnostics
483 				 * (see sym_undef).
484 				 */
485 				if (!(sdp->sd_aux->sa_vfile))
486 					sdp->sd_aux->sa_vfile = ifl->ifl_name;
487 			}
488 		}
489 		if (!(ifl->ifl_flags & FLG_IF_NEEDED))
490 			sdp->sd_flags |= FLG_SY_NOTAVAIL;
491 	}
492 
493 	/*
494 	 * Make sure any symbol association maintained by the original symbol
495 	 * is cleared and then update the symbols file reference.
496 	 */
497 	if ((link = sdp->sd_aux->sa_linkndx) != 0) {
498 		Sym_desc *	_sdp;
499 
500 		_sdp = sdp->sd_file->ifl_oldndx[link];
501 		_sdp->sd_aux->sa_linkndx = 0;
502 		sdp->sd_aux->sa_linkndx = 0;
503 	}
504 	sdp->sd_file = ifl;
505 
506 	/*
507 	 * Update the input section descriptor to that of the new input file
508 	 */
509 	if (((nsdflags & FLG_SY_SPECSEC) == 0) &&
510 	    (nsym->st_shndx != SHN_UNDEF) &&
511 	    ((sdp->sd_isc = ifl->ifl_isdesc[nshndx]) == NULL))
512 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_NOSECDEF),
513 		    demangle(sdp->sd_name), ifl->ifl_name);
514 }
515 
516 /*
517  * Resolve two undefines (only called for two relocatable objects).
518  */
519 static void
sym_twoundefs(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)520 sym_twoundefs(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
521     int ndx, Word nshndx, sd_flag_t nsdflags)
522 {
523 	Sym	*osym = sdp->sd_sym;
524 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
525 	uchar_t	otype = ELF_ST_TYPE(osym->st_info);
526 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
527 	uchar_t	ntype = ELF_ST_TYPE(nsym->st_info);
528 
529 	/*
530 	 * If two relocatable objects define a weak and non-weak undefined
531 	 * reference, take the non-weak definition.
532 	 *
533 	 *		-- or --
534 	 *
535 	 * If two relocatable objects define a NOTYPE & another, then
536 	 * take the other.
537 	 */
538 	if (((obind == STB_WEAK) && (nbind != STB_WEAK)) ||
539 	    (otype == STT_NOTYPE) && (ntype != STT_NOTYPE)) {
540 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
541 		return;
542 	}
543 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
544 }
545 
546 /*
547  * Resolve two real definitions.
548  */
549 static void
sym_tworeals(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)550 sym_tworeals(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
551     int ndx, Word nshndx, sd_flag_t nsdflags)
552 {
553 	Conv_inv_buf_t inv_buf1, inv_buf2;
554 	Sym	*osym = sdp->sd_sym;
555 	uchar_t	otype = ELF_ST_TYPE(osym->st_info);
556 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
557 	uchar_t	ntype = ELF_ST_TYPE(nsym->st_info);
558 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
559 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
560 	Half	nfile = ifl->ifl_ehdr->e_type;
561 	int	warn = 0;
562 
563 	/*
564 	 * If both definitions are from relocatable objects, and have non-weak
565 	 * binding then this is a fatal condition.
566 	 */
567 	if ((ofile == ET_REL) && (nfile == ET_REL) && (obind != STB_WEAK) &&
568 	    (nbind != STB_WEAK) && (!(ofl->ofl_flags & FLG_OF_MULDEFS))) {
569 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_MULDEF),
570 		    demangle(sdp->sd_name));
571 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
572 		    sdp->sd_file->ifl_name,
573 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
574 		    0, &inv_buf1), ifl->ifl_name,
575 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
576 		    0, &inv_buf2));
577 		return;
578 	}
579 
580 	/*
581 	 * Perform any machine specific type checking.
582 	 */
583 	if ((ld_targ.t_ms.ms_mach_sym_typecheck != NULL) &&
584 	    (*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym, ifl, ofl))
585 		return;
586 
587 	/*
588 	 * Check the symbols type and size.
589 	 */
590 	if (otype != ntype) {
591 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
592 		    demangle(sdp->sd_name));
593 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
594 		    sdp->sd_file->ifl_name,
595 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
596 		    0, &inv_buf1), ifl->ifl_name,
597 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
598 		    0, &inv_buf2));
599 		warn++;
600 	} else if ((otype == STT_OBJECT) && (osym->st_size != nsym->st_size)) {
601 		if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
602 			ld_eprintf(ofl, ERR_WARNING,
603 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
604 			    MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
605 			    EC_XWORD(osym->st_size), ifl->ifl_name,
606 			    EC_XWORD(nsym->st_size));
607 			warn++;
608 		}
609 	}
610 
611 	/*
612 	 * Having provided the user with any necessary warnings, take the
613 	 * appropriate symbol:
614 	 *
615 	 *  -	if one symbol is from a shared object and the other is from a
616 	 *	relocatable object, take the relocatable objects symbol (the
617 	 *	run-time linker is always going to find the relocatable object
618 	 *	symbol regardless of the binding), else
619 	 *
620 	 *  -	if both symbols are from relocatable objects and one symbol is
621 	 *	weak take the non-weak symbol (two non-weak symbols would have
622 	 *	generated the fatal error condition above unless -z muldefs is
623 	 *	in effect), else
624 	 *
625 	 *  -	take the first symbol definition encountered.
626 	 */
627 	if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
628 		if (warn)
629 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
630 			    sdp->sd_file->ifl_name);
631 		return;
632 	} else if ((nfile == ET_REL) && ((ofile == ET_DYN) ||
633 	    ((obind == STB_WEAK) && (nbind != STB_WEAK)))) {
634 		if (warn)
635 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
636 			    ifl->ifl_name);
637 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
638 		return;
639 	} else {
640 		if (warn)
641 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
642 			    sdp->sd_file->ifl_name);
643 		sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
644 		return;
645 	}
646 }
647 
648 /*
649  * Resolve a real and tentative definition.
650  */
651 static void
sym_realtent(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)652 sym_realtent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
653     int ndx, Word nshndx, sd_flag_t nsdflags)
654 {
655 	Conv_inv_buf_t inv_buf1, inv_buf2;
656 	Sym	*osym = sdp->sd_sym;
657 	uchar_t otype = ELF_ST_TYPE(osym->st_info);
658 	uchar_t obind = ELF_ST_BIND(osym->st_info);
659 	uchar_t ntype = ELF_ST_TYPE(nsym->st_info);
660 	uchar_t nbind = ELF_ST_BIND(nsym->st_info);
661 	Boolean	otent = FALSE, ntent = FALSE;
662 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
663 	Half	nfile = ifl->ifl_ehdr->e_type;
664 	int	warn = 0;
665 	uchar_t	ovis = ELF_ST_VISIBILITY(osym->st_other);
666 	uchar_t	nvis = ELF_ST_VISIBILITY(nsym->st_other);
667 
668 	/*
669 	 * Special rules for functions.
670 	 *
671 	 *  -	If both definitions are from relocatable objects, have the same
672 	 *	binding (ie. two weaks or two non-weaks), and the real
673 	 *	definition is a function (the other must be tentative), treat
674 	 *	this as a multiply defined symbol error, else
675 	 *
676 	 *  -	if the real symbol definition is a function within a shared
677 	 *	library and the tentative symbol is a relocatable object, and
678 	 *	the tentative is not weak and the function real, then retain the
679 	 *	tentative definition.
680 	 */
681 	if ((ofile == ET_REL) && (nfile == ET_REL) && (obind == nbind) &&
682 	    ((otype == STT_FUNC) || (ntype == STT_FUNC))) {
683 		if (ofl->ofl_flags & FLG_OF_MULDEFS) {
684 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
685 			    demangle(sdp->sd_name));
686 			sym_promote(sdp, nsym, ifl, ofl, ndx,
687 			    nshndx, nsdflags);
688 		} else {
689 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_MULDEF),
690 			    demangle(sdp->sd_name));
691 		}
692 		ld_eprintf(ofl, 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, nsdflags);
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, nsdflags);
715 				return;
716 			} else
717 				return;
718 		}
719 	}
720 
721 	if (sdp->sd_flags & FLG_SY_TENTSYM)
722 		otent = TRUE;
723 	if (nsdflags & FLG_SY_TENTSYM)
724 		ntent = TRUE;
725 
726 
727 	/*
728 	 * Check the symbols type and size.
729 	 */
730 	if (otype != ntype) {
731 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
732 		    demangle(sdp->sd_name));
733 		ld_eprintf(ofl, 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 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_DIFFATTR),
753 			    demangle(sdp->sd_name), MSG_INTL(MSG_STR_SIZES),
754 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_size),
755 			    ifl->ifl_name, EC_XWORD(nsym->st_size));
756 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_TENTERR));
757 		} else {
758 			if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
759 				ld_eprintf(ofl, ERR_WARNING,
760 				    MSG_INTL(MSG_SYM_DIFFATTR),
761 				    demangle(sdp->sd_name),
762 				    MSG_INTL(MSG_STR_SIZES),
763 				    sdp->sd_file->ifl_name,
764 				    EC_XWORD(osym->st_size),
765 				    ifl->ifl_name, EC_XWORD(nsym->st_size));
766 				warn++;
767 			}
768 		}
769 	}
770 
771 	/*
772 	 * Having provided the user with any necessary warnings, take the
773 	 * appropriate symbol:
774 	 *
775 	 *  -	if the original symbol is from relocatable file and it is
776 	 *	a protected tentative symbol, take the original one.
777 	 *
778 	 *  -	if the original symbol is from shared object and the new
779 	 *	symbol is a protected tentative symbol from a relocatable file,
780 	 *	take the new one.
781 	 *
782 	 *  -	if the original symbol is tentative, and providing the original
783 	 *	symbol isn't strong and the new symbol weak, take the real
784 	 *	symbol, else
785 	 *
786 	 *  -	if the original symbol is weak and the new tentative symbol is
787 	 *	strong take the new symbol.
788 	 *
789 	 * Refer to the System V ABI Page 4-27 for a description of the binding
790 	 * requirements of tentative and weak symbols.
791 	 */
792 	if ((ofile == ET_REL) && (nfile == ET_DYN) && (otent == TRUE) &&
793 	    (ovis == STV_PROTECTED)) {
794 		return;
795 	}
796 
797 	if ((ofile == ET_DYN) && (nfile == ET_REL) && (ntent == TRUE) &&
798 	    (nvis == STV_PROTECTED)) {
799 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
800 		return;
801 	}
802 
803 	if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
804 		if (warn)
805 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
806 			    sdp->sd_file->ifl_name);
807 		return;
808 	}
809 
810 	if (((otent) && (!((obind != STB_WEAK) && (nbind == STB_WEAK)))) ||
811 	    ((obind == STB_WEAK) && (nbind != STB_WEAK))) {
812 		if (warn)
813 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
814 			    ifl->ifl_name);
815 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
816 		return;
817 	} else {
818 		if (warn)
819 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
820 			    sdp->sd_file->ifl_name);
821 		sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
822 		return;
823 	}
824 }
825 
826 /*
827  * Resolve two tentative symbols.
828  */
829 static void
sym_twotent(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)830 sym_twotent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
831     int ndx, Word nshndx, sd_flag_t nsdflags)
832 {
833 	Sym	*osym = sdp->sd_sym;
834 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
835 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
836 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
837 	Half	nfile = ifl->ifl_ehdr->e_type;
838 	size_t	size = 0;
839 	Xword	value = 0;
840 
841 #if	defined(_ELF64)
842 	if (ld_targ.t_m.m_mach == EM_AMD64) {
843 		/*
844 		 * If the original and new symbols are both COMMON, but of
845 		 * a different size model, take the small one.
846 		 */
847 		if ((sdp->sd_sym->st_shndx == SHN_COMMON) &&
848 		    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
849 			/*
850 			 * Take the original symbol.
851 			 */
852 			return;
853 
854 		} else if ((sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
855 		    (nsym->st_shndx == SHN_COMMON)) {
856 			/*
857 			 * Take the new symbol.
858 			 */
859 			sym_override(sdp, nsym, ifl, ofl, ndx, nshndx,
860 			    nsdflags);
861 			return;
862 		}
863 	}
864 #endif
865 
866 	/*
867 	 * Check the alignment of the symbols.  This can only be tested for if
868 	 * the symbols are not real definitions to a SHT_NOBITS section (ie.
869 	 * they were originally tentative), as in this case the symbol would
870 	 * have a displacement value rather than an alignment.  In other words
871 	 * we can only test this for two relocatable objects.
872 	 */
873 	/* BEGIN CSTYLED */
874 	if ((osym->st_value != nsym->st_value) &&
875 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
876 	    (sdp->sd_sym->st_shndx == SHN_COMMON) &&
877 	    (nsdflags & FLG_SY_SPECSEC) &&
878 #if	defined(_ELF64)
879 	    (nsym->st_shndx == SHN_COMMON)) ||
880 	    ((ld_targ.t_m.m_mach == EM_AMD64) &&
881 	    (sdp->sd_flags & FLG_SY_SPECSEC) &&
882 	    (sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
883 	    (nsdflags & FLG_SY_SPECSEC) &&
884 	    (nsym->st_shndx == SHN_X86_64_LCOMMON))) {
885 #else
886 	    (nsym->st_shndx == SHN_COMMON))) {
887 #endif
888 	/* END CSTYLED */
889 
890 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
891 		const char	*file;
892 		Xword		salign;
893 		Xword		balign;
894 		uint_t		alignscompliment;
895 
896 		if (osym->st_value < nsym->st_value) {
897 			salign = osym->st_value;
898 			balign = nsym->st_value;
899 		} else {
900 			salign = nsym->st_value;
901 			balign = osym->st_value;
902 		}
903 
904 		/*
905 		 * If the smaller alignment fits smoothly into the
906 		 * larger alignment - we take it with no warning.
907 		 */
908 		if (S_ALIGN(balign, salign) == balign)
909 			alignscompliment = 1;
910 		else
911 			alignscompliment = 0;
912 
913 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
914 			ld_eprintf(ofl, ERR_WARNING,
915 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
916 			    MSG_INTL(MSG_STR_ALIGNMENTS),
917 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_value),
918 			    ifl->ifl_name, EC_XWORD(nsym->st_value));
919 
920 		/*
921 		 * Having provided the necessary warning indicate which
922 		 * relocatable object we are going to take.
923 		 *
924 		 *  -	if one symbol is weak and the other is non-weak
925 		 *	take the non-weak symbol, else
926 		 *
927 		 *  -	take the largest alignment (as we still have to check
928 		 *	the symbols size simply save the largest value for
929 		 *	updating later).
930 		 */
931 		if ((obind == STB_WEAK) && (nbind != STB_WEAK))
932 			file = ifl->ifl_name;
933 		else if (obind != nbind)
934 			file = sdp->sd_file->ifl_name;
935 		else {
936 			emsg = MSG_INTL(MSG_SYM_LARGER);
937 			value = balign;
938 		}
939 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
940 			ld_eprintf(ofl, ERR_NONE, emsg, file);
941 	}
942 
943 	/*
944 	 * Check the size of the symbols.
945 	 */
946 	if (osym->st_size != nsym->st_size) {
947 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
948 		const char	*file;
949 
950 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
951 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFATTR),
952 			    demangle(sdp->sd_name), MSG_INTL(MSG_STR_SIZES),
953 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_size),
954 			    ifl->ifl_name, EC_XWORD(nsym->st_size));
955 
956 
957 		/*
958 		 * This symbol has already been compared to an SO definition,
959 		 * as per the runtime behavior, ignore extra definitions.
960 		 */
961 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
962 			if (!(ofl->ofl_flags & FLG_OF_NOWARN))
963 				ld_eprintf(ofl, ERR_NONE, emsg,
964 				    sdp->sd_file->ifl_name);
965 			return;
966 		}
967 
968 		/*
969 		 * Having provided the necessary warning indicate what course
970 		 * of action we are going to take.
971 		 *
972 		 *  -	if the file types differ, take the relocatable object
973 		 *	and apply the largest symbol size, else
974 		 *  -	if one symbol is weak and the other is non-weak, take
975 		 *	the non-weak symbol, else
976 		 *  -	simply take the largest symbol reference.
977 		 */
978 		if (nfile != ofile) {
979 			if (nfile == ET_REL) {
980 				file = ifl->ifl_name;
981 				if (osym->st_size > nsym->st_size) {
982 					size = (size_t)osym->st_size;
983 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
984 				}
985 				sym_override(sdp, nsym, ifl, ofl, ndx,
986 				    nshndx, nsdflags);
987 			} else {
988 				file = sdp->sd_file->ifl_name;
989 				if (osym->st_size < nsym->st_size) {
990 					size = (size_t)nsym->st_size;
991 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
992 				}
993 				sym_promote(sdp, nsym, ifl, ofl, ndx,
994 				    nshndx, nsdflags);
995 			}
996 		} else if (obind != nbind) {
997 			if ((obind == STB_WEAK) && (nbind != STB_WEAK)) {
998 				sym_override(sdp, nsym, ifl, ofl, ndx,
999 				    nshndx, nsdflags);
1000 				file = ifl->ifl_name;
1001 			} else
1002 				file = sdp->sd_file->ifl_name;
1003 		} else {
1004 			if (osym->st_size < nsym->st_size) {
1005 				sym_override(sdp, nsym, ifl, ofl, ndx,
1006 				    nshndx, nsdflags);
1007 				file = ifl->ifl_name;
1008 			} else
1009 				file = sdp->sd_file->ifl_name;
1010 		}
1011 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
1012 			ld_eprintf(ofl, ERR_NONE, emsg, file);
1013 		if (size)
1014 			sdp->sd_sym->st_size = (Xword)size;
1015 	} else {
1016 		/*
1017 		 * If the sizes are the same
1018 		 *
1019 		 *  -	if the file types differ, take the relocatable object,
1020 		 *	else
1021 		 *
1022 		 *  -	if one symbol is weak and the other is non-weak, take
1023 		 *	the non-weak symbol, else
1024 		 *
1025 		 *  -	take the first reference.
1026 		 */
1027 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN))
1028 			return;
1029 		else if (((ofile != nfile) && (nfile == ET_REL)) ||
1030 		    (((obind == STB_WEAK) && (nbind != STB_WEAK)) &&
1031 		    (!((ofile != nfile) && (ofile == ET_REL)))))
1032 			sym_override(sdp, nsym, ifl, ofl, ndx,
1033 			    nshndx, nsdflags);
1034 		else
1035 			sym_promote(sdp, nsym, ifl, ofl, ndx,
1036 			    nshndx, nsdflags);
1037 	}
1038 
1039 	/*
1040 	 * Enforce the largest alignment if necessary.
1041 	 */
1042 	if (value)
1043 		sdp->sd_sym->st_value = value;
1044 }
1045 
1046 /*
1047  * Symbol resolution state table.  `Action' describes the required
1048  * procedure to be called (if any).
1049  */
1050 static void (*Action[REF_NUM * SYM_NUM * 2][SYM_NUM])(Sym_desc *,
1051     Sym *, Ifl_desc *, Ofl_desc *, int, Word, sd_flag_t) = {
1052 
1053 /*				defined		undef		tent	*/
1054 /*				ET_REL		ET_REL		ET_REL	*/
1055 
1056 /*  0 defined REF_DYN_SEEN */	sym_tworeals,	sym_promote,	sym_realtent,
1057 /*  1   undef REF_DYN_SEEN */	sym_override,	sym_override,	sym_override,
1058 /*  2    tent REF_DYN_SEEN */	sym_realtent,	sym_promote,	sym_twotent,
1059 /*  3 defined REF_DYN_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
1060 /*  4   undef REF_DYN_NEED */	sym_override,	sym_override,	sym_override,
1061 /*  5    tent REF_DYN_NEED */	sym_realtent,	sym_typecheck,	sym_twotent,
1062 /*  6 defined REF_REL_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
1063 /*  7   undef REF_REL_NEED */	sym_override,	sym_twoundefs,	sym_override,
1064 /*  8    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent,
1065 
1066 /*				defined		undef		tent	*/
1067 /*				ET_DYN		ET_DYN		ET_DYN	*/
1068 
1069 /*  9 defined REF_DYN_SEEN */	sym_tworeals,	sym_null,	sym_realtent,
1070 /* 10   undef REF_DYN_SEEN */	sym_override,	sym_mach_check,	sym_override,
1071 /* 11    tent REF_DYN_SEEN */	sym_realtent,	sym_null,	sym_twotent,
1072 /* 12 defined REF_DYN_NEED */	sym_tworeals,	sym_null,	sym_realtent,
1073 /* 13   undef REF_DYN_NEED */	sym_override,	sym_null,	sym_override,
1074 /* 14    tent REF_DYN_NEED */	sym_realtent,	sym_null,	sym_twotent,
1075 /* 15 defined REF_REL_NEED */	sym_tworeals,	sym_null,	sym_realtent,
1076 /* 16   undef REF_REL_NEED */	sym_override,	sym_mach_check,	sym_override,
1077 /* 17    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent
1078 
1079 };
1080 
1081 uintptr_t
1082 ld_sym_resolve(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl, int ndx,
1083     Word nshndx, sd_flag_t nsdflags)
1084 {
1085 	int		row, column;		/* State table coordinates */
1086 	Sym		*osym = sdp->sd_sym;
1087 	sd_flag_t	osdflags = sdp->sd_flags;
1088 	Is_desc		*isp;
1089 	Half		vis = 0, nfile = ifl->ifl_ehdr->e_type;
1090 	Half		oref = sdp->sd_ref;
1091 
1092 	/*
1093 	 * Determine the original symbols definition (defines row in Action[]).
1094 	 */
1095 	if (osdflags & FLG_SY_TENTSYM)
1096 		row = SYM_TENTATIVE;
1097 	else if ((sdp->sd_sym->st_shndx == SHN_UNDEF) ||
1098 	    (sdp->sd_sym->st_shndx == SHN_SUNW_IGNORE))
1099 		row = SYM_UNDEFINED;
1100 	else
1101 		row = SYM_DEFINED;
1102 
1103 	/*
1104 	 * If the input file is an implicit shared object then we don't need
1105 	 * to bind to any symbols within it other than to verify that any
1106 	 * undefined references will be closed (implicit shared objects are only
1107 	 * processed when no undefined symbols are required as a result of the
1108 	 * link-edit (see process_dynamic())).
1109 	 */
1110 	if ((nfile == ET_DYN) && !(ifl->ifl_flags & FLG_IF_NEEDED) &&
1111 	    (row != SYM_UNDEFINED))
1112 		return (1);
1113 
1114 	/*
1115 	 * Finish computing the Action[] row by applying the symbols reference
1116 	 * together with the input files type.
1117 	 */
1118 	row = row + (REF_NUM * sdp->sd_ref);
1119 	if (nfile == ET_DYN)
1120 		row += (REF_NUM * SYM_NUM);
1121 
1122 	/*
1123 	 * If either the original or new symbol originates from a relocatable
1124 	 * object, determine the appropriate visibility for the resolved symbol.
1125 	 */
1126 	if ((oref == REF_REL_NEED) || (nfile == ET_REL))
1127 		vis = sym_visibility(sdp, nsym, ifl, ofl);
1128 
1129 	/*
1130 	 * Determine the new symbols definition (defines column in Action[]).
1131 	 */
1132 	if ((nsdflags & FLG_SY_SPECSEC) &&
1133 	    (nsym->st_shndx == SHN_COMMON)) {
1134 		column = SYM_TENTATIVE;
1135 		nsdflags |= FLG_SY_TENTSYM;
1136 #if	defined(_ELF64)
1137 	} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
1138 	    (nsdflags & FLG_SY_SPECSEC) &&
1139 	    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
1140 		column = SYM_TENTATIVE;
1141 		nsdflags |= FLG_SY_TENTSYM;
1142 #endif
1143 	} else if ((nsym->st_shndx == SHN_UNDEF) ||
1144 	    (nsym->st_shndx == SHN_SUNW_IGNORE)) {
1145 		column = SYM_UNDEFINED;
1146 		nshndx = SHN_UNDEF;
1147 	} else {
1148 		column = SYM_DEFINED;
1149 		/*
1150 		 * If the new symbol is from a shared library and it is
1151 		 * associated with a SHT_NOBITS section then this symbol
1152 		 * originated from a tentative symbol.
1153 		 */
1154 		if (((nsdflags & FLG_SY_SPECSEC) == 0) && (nfile == ET_DYN)) {
1155 			isp = ifl->ifl_isdesc[nshndx];
1156 			if (isp && (isp->is_shdr->sh_type == SHT_NOBITS)) {
1157 				column = SYM_TENTATIVE;
1158 				nsdflags |= FLG_SY_TENTSYM;
1159 			}
1160 		}
1161 	}
1162 
1163 	DBG_CALL(Dbg_syms_resolving(ofl, ndx, sdp->sd_name, row, column,
1164 	    osym, nsym, sdp, ifl));
1165 
1166 	/*
1167 	 * Record the input filename on the defined files list for possible
1168 	 * later diagnostics.  The `sa_dfiles' list is used to maintain the list
1169 	 * of shared objects that define the same symbol.  This list is only
1170 	 * generated when the -m option is in effect and is used to list
1171 	 * multiple (interposed) definitions of a symbol (refer to ldmap_out()).
1172 	 */
1173 	if ((ofl->ofl_flags & FLG_OF_GENMAP) && (nsym->st_shndx != SHN_UNDEF) &&
1174 	    ((nsdflags & FLG_SY_SPECSEC) == 0))
1175 		if (aplist_append(&sdp->sd_aux->sa_dfiles, ifl->ifl_name,
1176 		    AL_CNT_SDP_DFILES) == NULL)
1177 			return (S_ERROR);
1178 
1179 	/*
1180 	 * Perform the required resolution.
1181 	 */
1182 	Action[row][column](sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
1183 
1184 	/*
1185 	 * Apply any visibility requirements.  If a SINGLETON has been
1186 	 * established, make sure no symbol reduction indicators remain
1187 	 * associated with the symbol, and indicate that the symbol can not
1188 	 * be directly bound to.
1189 	 */
1190 	if ((oref == REF_REL_NEED) || (nfile == ET_REL)) {
1191 		if ((vis == STV_EXPORTED) || (vis == STV_SINGLETON)) {
1192 			sdp->sd_flags &= ~MSK_SY_LOCAL;
1193 
1194 			if (vis == STV_EXPORTED)
1195 				sdp->sd_flags |= FLG_SY_EXPORT;
1196 			else {
1197 				sdp->sd_flags |= (FLG_SY_NDIR | FLG_SY_SINGLE);
1198 
1199 				if (sdp->sd_ref == REF_REL_NEED) {
1200 					ofl->ofl_flags1 |=
1201 					    (FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
1202 				}
1203 			}
1204 		} else if (vis == STV_PROTECTED) {
1205 			sdp->sd_flags |= FLG_SY_PROTECT;
1206 		} else if ((vis == STV_INTERNAL) || (vis == STV_HIDDEN)) {
1207 			sdp->sd_flags |= FLG_SY_HIDDEN;
1208 		} else if (vis == STV_ELIMINATE) {
1209 			sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM);
1210 		}
1211 
1212 		sdp->sd_sym->st_other =
1213 		    (sdp->sd_sym->st_other & ~MSK_SYM_VISIBILITY) | vis;
1214 	}
1215 
1216 	/*
1217 	 * If the symbol has been resolved to the new input file, and this is
1218 	 * a versioned relocatable object, then the version information of the
1219 	 * new symbol must be promoted to the versioning of the output file.
1220 	 */
1221 	if ((sdp->sd_file == ifl) && (nfile == ET_REL) && (ifl->ifl_versym) &&
1222 	    (nsym->st_shndx != SHN_UNDEF))
1223 		ld_vers_promote(sdp, ndx, ifl, ofl);
1224 
1225 	/*
1226 	 * Determine whether a mapfile reference has been satisfied.  Mapfile
1227 	 * symbol references augment symbols that should be contributed from
1228 	 * the relocatable objects used to build the output image.  If a
1229 	 * relocatable object doesn't provide one of the mapfile symbol
1230 	 * references then somethings amiss, and will be flagged during symbol
1231 	 * validation.
1232 	 */
1233 	if ((nfile == ET_REL) && ((sdp->sd_flags &
1234 	    (FLG_SY_MAPREF | FLG_SY_MAPUSED)) == FLG_SY_MAPREF)) {
1235 		/*
1236 		 * Extern and parent references are satisfied by references from
1237 		 * a relocatable object.  Note that we let *any* symbol type
1238 		 * satisfy this reference, to be as flexible as possible with
1239 		 * user written mapfiles.  It could be questionable, for
1240 		 * example, if what a user expects to be an extern reference is
1241 		 * actually found to be a definition in a relocatable object.
1242 		 *
1243 		 * Any other mapfile reference (typically for versioning
1244 		 * information) simply augments a relocatables definition.
1245 		 */
1246 		if ((sdp->sd_flags & (FLG_SY_EXTERN | FLG_SY_PARENT)) ||
1247 		    ((sdp->sd_sym->st_shndx != SHN_UNDEF) &&
1248 		    (sdp->sd_ref == REF_REL_NEED)))
1249 			sdp->sd_flags |= FLG_SY_MAPUSED;
1250 	}
1251 
1252 	/*
1253 	 * Make sure any special symbol requirements are carried over.
1254 	 */
1255 	if ((osdflags & FLG_SY_CAP) || (nsdflags & FLG_SY_CAP))
1256 		sdp->sd_flags |= FLG_SY_CAP;
1257 
1258 	DBG_CALL(Dbg_syms_resolved(ofl, sdp));
1259 
1260 	return (1);
1261 }
1262