xref: /titanic_50/usr/src/cmd/sgs/libld/common/relocate.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21c174926fSrie 
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate  *	  All Rights Reserved
257c478bd9Sstevel@tonic-gate  *
26bf994817SAli Bahrami  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * set-up for relocations
317c478bd9Sstevel@tonic-gate  */
32ba2be530Sab196087 
33ba2be530Sab196087 #define	ELF_TARGET_AMD64
34ba2be530Sab196087 #define	ELF_TARGET_SPARC
35ba2be530Sab196087 
367c478bd9Sstevel@tonic-gate #include	<string.h>
377c478bd9Sstevel@tonic-gate #include	<stdio.h>
387c478bd9Sstevel@tonic-gate #include	<alloca.h>
395aefb655Srie #include	<debug.h>
407c478bd9Sstevel@tonic-gate #include	"msg.h"
417c478bd9Sstevel@tonic-gate #include	"_libld.h"
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /*
44ba2be530Sab196087  * Set up the relocation table flag test macros so that they use the
45ba2be530Sab196087  * relocation table for the current target machine.
46ba2be530Sab196087  */
47ba2be530Sab196087 #define	IS_PLT(X)	RELTAB_IS_PLT(X, ld_targ.t_mr.mr_reloc_table)
48ba2be530Sab196087 #define	IS_GOT_RELATIVE(X) \
49ba2be530Sab196087 	RELTAB_IS_GOT_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
50ba2be530Sab196087 #define	IS_GOT_PC(X)	RELTAB_IS_GOT_PC(X, ld_targ.t_mr.mr_reloc_table)
51ba2be530Sab196087 #define	IS_GOTPCREL(X)	RELTAB_IS_GOTPCREL(X, ld_targ.t_mr.mr_reloc_table)
52ba2be530Sab196087 #define	IS_GOT_BASED(X)	RELTAB_IS_GOT_BASED(X, ld_targ.t_mr.mr_reloc_table)
53ba2be530Sab196087 #define	IS_GOT_OPINS(X)	RELTAB_IS_GOT_OPINS(X, ld_targ.t_mr.mr_reloc_table)
54ba2be530Sab196087 #define	IS_GOT_REQUIRED(X) \
55ba2be530Sab196087 	RELTAB_IS_GOT_REQUIRED(X, ld_targ.t_mr.mr_reloc_table)
56ba2be530Sab196087 #define	IS_PC_RELATIVE(X) RELTAB_IS_PC_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
57ba2be530Sab196087 #define	IS_ADD_RELATIVE(X) \
58ba2be530Sab196087 	RELTAB_IS_ADD_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
59ba2be530Sab196087 #define	IS_REGISTER(X)	RELTAB_IS_REGISTER(X, ld_targ.t_mr.mr_reloc_table)
60ba2be530Sab196087 #define	IS_NOTSUP(X)	RELTAB_IS_NOTSUP(X, ld_targ.t_mr.mr_reloc_table)
61ba2be530Sab196087 #define	IS_SEG_RELATIVE(X) \
62ba2be530Sab196087 	RELTAB_IS_SEG_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
63ba2be530Sab196087 #define	IS_EXTOFFSET(X)	RELTAB_IS_EXTOFFSET(X, ld_targ.t_mr.mr_reloc_table)
64ba2be530Sab196087 #define	IS_SEC_RELATIVE(X) \
65ba2be530Sab196087 	RELTAB_IS_SEC_RELATIVE(X, ld_targ.t_mr.mr_reloc_table)
66ba2be530Sab196087 #define	IS_TLS_INS(X)	RELTAB_IS_TLS_INS(X, ld_targ.t_mr.mr_reloc_table)
67ba2be530Sab196087 #define	IS_TLS_GD(X)	RELTAB_IS_TLS_GD(X, ld_targ.t_mr.mr_reloc_table)
68ba2be530Sab196087 #define	IS_TLS_LD(X)	RELTAB_IS_TLS_LD(X, ld_targ.t_mr.mr_reloc_table)
69ba2be530Sab196087 #define	IS_TLS_IE(X)	RELTAB_IS_TLS_IE(X, ld_targ.t_mr.mr_reloc_table)
70ba2be530Sab196087 #define	IS_TLS_LE(X)	RELTAB_IS_TLS_LE(X, ld_targ.t_mr.mr_reloc_table)
71ba2be530Sab196087 #define	IS_LOCALBND(X)	RELTAB_IS_LOCALBND(X, ld_targ.t_mr.mr_reloc_table)
72ba2be530Sab196087 #define	IS_SIZE(X)	RELTAB_IS_SIZE(X, ld_targ.t_mr.mr_reloc_table)
73ba2be530Sab196087 
74ba2be530Sab196087 /*
757c478bd9Sstevel@tonic-gate  * Structure to hold copy relocation items.
767c478bd9Sstevel@tonic-gate  */
777c478bd9Sstevel@tonic-gate typedef struct copy_rel {
7857ef7aa9SRod Evans 	Sym_desc	*c_sdp;		/* symbol descriptor to be copied */
7957ef7aa9SRod Evans 	Addr 		c_val;		/* original symbol value */
807c478bd9Sstevel@tonic-gate } Copy_rel;
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * For each copy relocation symbol, determine if the symbol is:
847c478bd9Sstevel@tonic-gate  * 	1) to be *disp* relocated at runtime
857c478bd9Sstevel@tonic-gate  *	2) a reference symbol for *disp* relocation
867c478bd9Sstevel@tonic-gate  *	3) possibly *disp* relocated at ld time.
877c478bd9Sstevel@tonic-gate  *
887c478bd9Sstevel@tonic-gate  * The first and the second are serious errors.
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate static void
is_disp_copied(Ofl_desc * ofl,Copy_rel * crp)9157ef7aa9SRod Evans is_disp_copied(Ofl_desc *ofl, Copy_rel *crp)
927c478bd9Sstevel@tonic-gate {
9357ef7aa9SRod Evans 	Ifl_desc	*ifl = crp->c_sdp->sd_file;
9457ef7aa9SRod Evans 	Sym_desc	*sdp = crp->c_sdp;
9557ef7aa9SRod Evans 	Addr		symaddr = crp->c_val;
967c478bd9Sstevel@tonic-gate 	Is_desc		*irel;
9757ef7aa9SRod Evans 	Aliste		idx;
98de777a60Sab196087 	Conv_inv_buf_t	inv_buf;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	/*
1017c478bd9Sstevel@tonic-gate 	 * This symbol may not be *disp* relocated at run time, but could
1027c478bd9Sstevel@tonic-gate 	 * already have been *disp* relocated when the shared object was
1037c478bd9Sstevel@tonic-gate 	 * created.  Warn the user.
1047c478bd9Sstevel@tonic-gate 	 */
1057c478bd9Sstevel@tonic-gate 	if ((ifl->ifl_flags & FLG_IF_DISPDONE) &&
1067c478bd9Sstevel@tonic-gate 	    (ofl->ofl_flags & FLG_OF_VERBOSE))
107*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_DISPREL2),
108ba2be530Sab196087 		    conv_reloc_type(ifl->ifl_ehdr->e_machine,
109ba2be530Sab196087 		    ld_targ.t_m.m_r_copy, 0, &inv_buf),
110ba2be530Sab196087 		    ifl->ifl_name, demangle(sdp->sd_name));
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	if ((ifl->ifl_flags & FLG_IF_DISPPEND) == 0)
1137c478bd9Sstevel@tonic-gate 		return;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	/*
1167c478bd9Sstevel@tonic-gate 	 * Traverse the input relocation sections.
1177c478bd9Sstevel@tonic-gate 	 */
11857ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ifl->ifl_relsect, idx, irel)) {
1197c478bd9Sstevel@tonic-gate 		Sym_desc	*rsdp;
1207c478bd9Sstevel@tonic-gate 		Is_desc		*trel;
1217c478bd9Sstevel@tonic-gate 		Rel		*rend, *reloc;
1227c478bd9Sstevel@tonic-gate 		Xword		rsize, entsize;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 		trel = ifl->ifl_isdesc[irel->is_shdr->sh_info];
1257c478bd9Sstevel@tonic-gate 		rsize = irel->is_shdr->sh_size;
1267c478bd9Sstevel@tonic-gate 		entsize = irel->is_shdr->sh_entsize;
1277c478bd9Sstevel@tonic-gate 		reloc = (Rel *)irel->is_indata->d_buf;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 		/*
1307c478bd9Sstevel@tonic-gate 		 * Decide entry size
1317c478bd9Sstevel@tonic-gate 		 */
1327c478bd9Sstevel@tonic-gate 		if ((entsize == 0) || (entsize > rsize)) {
1337c478bd9Sstevel@tonic-gate 			if (irel->is_shdr->sh_type == SHT_RELA)
1347c478bd9Sstevel@tonic-gate 				entsize = sizeof (Rela);
1357c478bd9Sstevel@tonic-gate 			else
1367c478bd9Sstevel@tonic-gate 				entsize = sizeof (Rel);
1377c478bd9Sstevel@tonic-gate 		}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 		/*
1407c478bd9Sstevel@tonic-gate 		 * Traverse the relocation entries.
1417c478bd9Sstevel@tonic-gate 		 */
1427c478bd9Sstevel@tonic-gate 		for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize);
1437c478bd9Sstevel@tonic-gate 		    reloc < rend;
144b3fbe5e6Sseizo 		    reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) {
1457c478bd9Sstevel@tonic-gate 			const char	*str;
1467c478bd9Sstevel@tonic-gate 			Word		rstndx;
1477c478bd9Sstevel@tonic-gate 
148ba2be530Sab196087 			if (IS_PC_RELATIVE(ELF_R_TYPE(reloc->r_info,
149ba2be530Sab196087 			    ld_targ.t_m.m_mach)) == 0)
1507c478bd9Sstevel@tonic-gate 				continue;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 			/*
153635216b6SRod Evans 			 * Determine if symbol is referenced from a relocation.
1547c478bd9Sstevel@tonic-gate 			 */
1557c478bd9Sstevel@tonic-gate 			rstndx = (Word) ELF_R_SYM(reloc->r_info);
1567c478bd9Sstevel@tonic-gate 			rsdp = ifl->ifl_oldndx[rstndx];
1577c478bd9Sstevel@tonic-gate 			if (rsdp == sdp) {
1587c478bd9Sstevel@tonic-gate 				if ((str = demangle(rsdp->sd_name)) !=
1597c478bd9Sstevel@tonic-gate 				    rsdp->sd_name) {
1607c478bd9Sstevel@tonic-gate 					char	*_str = alloca(strlen(str) + 1);
1617c478bd9Sstevel@tonic-gate 					(void) strcpy(_str, str);
1627c478bd9Sstevel@tonic-gate 					str = (const char *)_str;
1637c478bd9Sstevel@tonic-gate 				}
164*1007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_WARNING,
165*1007fd6fSAli Bahrami 				    MSG_INTL(MSG_REL_DISPREL1),
1665aefb655Srie 				    conv_reloc_type(ifl->ifl_ehdr->e_machine,
167ba2be530Sab196087 				    (uint_t)ELF_R_TYPE(reloc->r_info,
168ba2be530Sab196087 				    ld_targ.t_m.m_mach),
169de777a60Sab196087 				    0, &inv_buf), ifl->ifl_name, str,
1707c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_STR_UNKNOWN),
1717c478bd9Sstevel@tonic-gate 				    EC_XWORD(reloc->r_offset),
1727c478bd9Sstevel@tonic-gate 				    demangle(sdp->sd_name));
1737c478bd9Sstevel@tonic-gate 			}
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 			/*
176635216b6SRod Evans 			 * Determine whether the relocation entry is relocating
1777c478bd9Sstevel@tonic-gate 			 * this symbol.
1787c478bd9Sstevel@tonic-gate 			 */
1797c478bd9Sstevel@tonic-gate 			if ((sdp->sd_isc != trel) ||
1807c478bd9Sstevel@tonic-gate 			    (reloc->r_offset < symaddr) ||
1817c478bd9Sstevel@tonic-gate 			    (reloc->r_offset >=
1827c478bd9Sstevel@tonic-gate 			    (symaddr + sdp->sd_sym->st_size)))
1837c478bd9Sstevel@tonic-gate 				continue;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 			/*
1867c478bd9Sstevel@tonic-gate 			 * This symbol is truely *disp* relocated, so should
1877c478bd9Sstevel@tonic-gate 			 * really be fixed by user.
1887c478bd9Sstevel@tonic-gate 			 */
1897c478bd9Sstevel@tonic-gate 			if ((str = demangle(sdp->sd_name)) != sdp->sd_name) {
1907c478bd9Sstevel@tonic-gate 				char	*_str = alloca(strlen(str) + 1);
1917c478bd9Sstevel@tonic-gate 				(void) strcpy(_str, str);
1927c478bd9Sstevel@tonic-gate 				str = (const char *)_str;
1937c478bd9Sstevel@tonic-gate 			}
194*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_DISPREL1),
1955aefb655Srie 			    conv_reloc_type(ifl->ifl_ehdr->e_machine,
196ba2be530Sab196087 			    (uint_t)ELF_R_TYPE(reloc->r_info,
197ba2be530Sab196087 			    ld_targ.t_m.m_mach), 0, &inv_buf),
198c13de8f6Sab196087 			    ifl->ifl_name, demangle(rsdp->sd_name), str,
1997c478bd9Sstevel@tonic-gate 			    EC_XWORD(reloc->r_offset), str);
2007c478bd9Sstevel@tonic-gate 		}
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate  * The number of symbols provided by some objects can be very large.  Use a
2067c478bd9Sstevel@tonic-gate  * binary search to match the associated value to a symbol table entry.
2077c478bd9Sstevel@tonic-gate  */
2087c478bd9Sstevel@tonic-gate static int
disp_bsearch(const void * key,const void * array)2097c478bd9Sstevel@tonic-gate disp_bsearch(const void *key, const void *array)
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate 	Addr		kvalue, avalue;
2127c478bd9Sstevel@tonic-gate 	Ssv_desc	*ssvp = (Ssv_desc *)array;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	kvalue = *((Addr *)key);
2157c478bd9Sstevel@tonic-gate 	avalue = ssvp->ssv_value;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	if (avalue > kvalue)
2187c478bd9Sstevel@tonic-gate 		return (-1);
2197c478bd9Sstevel@tonic-gate 	if ((avalue < kvalue) &&
2207c478bd9Sstevel@tonic-gate 	    ((avalue + ssvp->ssv_sdp->sd_sym->st_size) <= kvalue))
2217c478bd9Sstevel@tonic-gate 		return (1);
2227c478bd9Sstevel@tonic-gate 	return (0);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate  * Given a sorted list of symbols, look for a symbol in which the relocation
2277c478bd9Sstevel@tonic-gate  * offset falls between the [sym.st_value - sym.st_value + sym.st_size].  Since
2287c478bd9Sstevel@tonic-gate  * the symbol list is maintained in sorted order,  we can bail once the
2297c478bd9Sstevel@tonic-gate  * relocation offset becomes less than the symbol values.  The symbol is
2307c478bd9Sstevel@tonic-gate  * returned for use in error diagnostics.
2317c478bd9Sstevel@tonic-gate  */
2327c478bd9Sstevel@tonic-gate static Sym_desc *
disp_scansyms(Ifl_desc * ifl,Rel_desc * rld,Boolean rlocal,int inspect,Ofl_desc * ofl)2337c478bd9Sstevel@tonic-gate disp_scansyms(Ifl_desc * ifl, Rel_desc *rld, Boolean rlocal, int inspect,
2347c478bd9Sstevel@tonic-gate     Ofl_desc *ofl)
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate 	Sym_desc	*tsdp, *rsdp;
2377c478bd9Sstevel@tonic-gate 	Sym		*rsym, *tsym;
2387c478bd9Sstevel@tonic-gate 	Ssv_desc	*ssvp;
2397c478bd9Sstevel@tonic-gate 	uchar_t		rtype, ttype;
2407c478bd9Sstevel@tonic-gate 	Addr		value;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	/*
2437c478bd9Sstevel@tonic-gate 	 * Sorted symbol values have been uniquified by adding their associated
2447c478bd9Sstevel@tonic-gate 	 * section offset.  Uniquify the relocation offset by adding its
2457c478bd9Sstevel@tonic-gate 	 * associated section offset, and search for the symbol.
2467c478bd9Sstevel@tonic-gate 	 */
2477c478bd9Sstevel@tonic-gate 	value = rld->rel_roffset;
2487c478bd9Sstevel@tonic-gate 	if (rld->rel_isdesc->is_shdr)
2497c478bd9Sstevel@tonic-gate 		value += rld->rel_isdesc->is_shdr->sh_offset;
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	if ((ssvp = bsearch((void *)&value, (void *)ifl->ifl_sortsyms,
2527c478bd9Sstevel@tonic-gate 	    ifl->ifl_sortcnt, sizeof (Ssv_desc), &disp_bsearch)) != 0)
2537c478bd9Sstevel@tonic-gate 		tsdp = ssvp->ssv_sdp;
2547c478bd9Sstevel@tonic-gate 	else
2557c478bd9Sstevel@tonic-gate 		tsdp = 0;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	if (inspect)
2587c478bd9Sstevel@tonic-gate 		return (tsdp);
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	/*
2617c478bd9Sstevel@tonic-gate 	 * Determine the relocation reference symbol and its type.
2627c478bd9Sstevel@tonic-gate 	 */
2637c478bd9Sstevel@tonic-gate 	rsdp = rld->rel_sym;
2647c478bd9Sstevel@tonic-gate 	rsym = rsdp->sd_sym;
2657c478bd9Sstevel@tonic-gate 	rtype = ELF_ST_TYPE(rsym->st_info);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	/*
2687c478bd9Sstevel@tonic-gate 	 * If there is no target symbol to match the relocation offset, then the
2697c478bd9Sstevel@tonic-gate 	 * offset is effectively local data.  If the relocation symbol is global
2707c478bd9Sstevel@tonic-gate 	 * data we have a potential for this displacement relocation to be
2717c478bd9Sstevel@tonic-gate 	 * invalidated should the global symbol be copied.
2727c478bd9Sstevel@tonic-gate 	 */
2737c478bd9Sstevel@tonic-gate 	if (tsdp == 0) {
2747c478bd9Sstevel@tonic-gate 		if ((rlocal == TRUE) ||
2757c478bd9Sstevel@tonic-gate 		    ((rtype != STT_OBJECT) && (rtype != STT_SECTION)))
2767c478bd9Sstevel@tonic-gate 		return (tsdp);
2777c478bd9Sstevel@tonic-gate 	} else {
2787c478bd9Sstevel@tonic-gate 		/*
2797c478bd9Sstevel@tonic-gate 		 * If both symbols are local, no copy relocations can occur to
28060758829Srie 		 * either symbol.  Note, this test is very similar to the test
28160758829Srie 		 * used in ld_sym_adjust_vis().
2827c478bd9Sstevel@tonic-gate 		 */
28308278a5eSRod Evans 		if ((rlocal == TRUE) && (SYM_IS_HIDDEN(tsdp) ||
28460758829Srie 		    (ELF_ST_BIND(tsdp->sd_sym->st_info) != STB_GLOBAL) ||
28544bac77bSrie 		    ((ofl->ofl_flags & (FLG_OF_AUTOLCL | FLG_OF_AUTOELM)) &&
286635216b6SRod Evans 		    ((tsdp->sd_flags & MSK_SY_NOAUTO) == 0))))
2877c478bd9Sstevel@tonic-gate 			return (tsdp);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 		/*
2907c478bd9Sstevel@tonic-gate 		 * Determine the relocation target symbols type.
2917c478bd9Sstevel@tonic-gate 		 */
2927c478bd9Sstevel@tonic-gate 		tsym = tsdp->sd_sym;
2937c478bd9Sstevel@tonic-gate 		ttype = ELF_ST_TYPE(tsym->st_info);
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		/*
296141040e8Srie 		 * If the reference symbol is local, and the target isn't a
297141040e8Srie 		 * data element, then no copy relocations can occur to either
298141040e8Srie 		 * symbol.  Note, this catches pc-relative relocations against
299141040e8Srie 		 * the _GLOBAL_OFFSET_TABLE_, which is effectively treated as
300141040e8Srie 		 * a local symbol.
301141040e8Srie 		 */
302141040e8Srie 		if ((rlocal == TRUE) && (ttype != STT_OBJECT) &&
303141040e8Srie 		    (ttype != STT_SECTION))
304141040e8Srie 			return (tsdp);
305141040e8Srie 
306141040e8Srie 		/*
307141040e8Srie 		 * Finally, one of the symbols must reference a data element.
3087c478bd9Sstevel@tonic-gate 		 */
3097c478bd9Sstevel@tonic-gate 		if ((rtype != STT_OBJECT) && (rtype != STT_SECTION) &&
3107c478bd9Sstevel@tonic-gate 		    (ttype != STT_OBJECT) && (ttype != STT_SECTION))
3117c478bd9Sstevel@tonic-gate 			return (tsdp);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	/*
3157c478bd9Sstevel@tonic-gate 	 * We have two global symbols, at least one of which is a data item.
3167c478bd9Sstevel@tonic-gate 	 * The last case where a displacement relocation can be ignored, is
3177c478bd9Sstevel@tonic-gate 	 * if the reference symbol is included in the target symbol.
3187c478bd9Sstevel@tonic-gate 	 */
3197c478bd9Sstevel@tonic-gate 	value = rsym->st_value;
320cce0e03bSab196087 	if ((rld->rel_flags & FLG_REL_RELA) == FLG_REL_RELA)
3217c478bd9Sstevel@tonic-gate 		value += rld->rel_raddend;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	if ((rld->rel_roffset >= value) &&
3247c478bd9Sstevel@tonic-gate 	    (rld->rel_roffset < (value + rsym->st_size)))
3257c478bd9Sstevel@tonic-gate 		return (tsdp);
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	/*
3287c478bd9Sstevel@tonic-gate 	 * We have a displacement relocation that could be compromised by a
3297c478bd9Sstevel@tonic-gate 	 * copy relocation of one of the associated data items.
3307c478bd9Sstevel@tonic-gate 	 */
3317c478bd9Sstevel@tonic-gate 	rld->rel_flags |= FLG_REL_DISP;
3327c478bd9Sstevel@tonic-gate 	return (tsdp);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate void
ld_disp_errmsg(const char * msg,Rel_desc * rsp,Ofl_desc * ofl)3365aefb655Srie ld_disp_errmsg(const char *msg, Rel_desc *rsp, Ofl_desc *ofl)
3377c478bd9Sstevel@tonic-gate {
3387c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
3397c478bd9Sstevel@tonic-gate 	const char	*str;
3407c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl = rsp->rel_isdesc->is_file;
341de777a60Sab196087 	Conv_inv_buf_t	inv_buf;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	if ((sdp = disp_scansyms(ifl, rsp, 0, 1, ofl)) != 0)
3447c478bd9Sstevel@tonic-gate 		str = demangle(sdp->sd_name);
3457c478bd9Sstevel@tonic-gate 	else
3467c478bd9Sstevel@tonic-gate 		str = MSG_INTL(MSG_STR_UNKNOWN);
3477c478bd9Sstevel@tonic-gate 
348*1007fd6fSAli Bahrami 	ld_eprintf(ofl, ERR_WARNING, msg,
349de777a60Sab196087 	    conv_reloc_type(ifl->ifl_ehdr->e_machine, rsp->rel_rtype,
350bf994817SAli Bahrami 	    0, &inv_buf), ifl->ifl_name, ld_reloc_sym_name(rsp), str,
351de777a60Sab196087 	    EC_OFF(rsp->rel_roffset));
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate /*
3557c478bd9Sstevel@tonic-gate  * qsort(3C) comparison routine used for the disp_sortsyms().
3567c478bd9Sstevel@tonic-gate  */
3577c478bd9Sstevel@tonic-gate static int
disp_qsort(const void * s1,const void * s2)3587c478bd9Sstevel@tonic-gate disp_qsort(const void * s1, const void * s2)
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate 	Ssv_desc	*ssvp1 = ((Ssv_desc *)s1);
3617c478bd9Sstevel@tonic-gate 	Ssv_desc	*ssvp2 = ((Ssv_desc *)s2);
3627c478bd9Sstevel@tonic-gate 	Addr		val1 = ssvp1->ssv_value;
3637c478bd9Sstevel@tonic-gate 	Addr		val2 = ssvp2->ssv_value;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	if (val1 > val2)
3667c478bd9Sstevel@tonic-gate 		return (1);
3677c478bd9Sstevel@tonic-gate 	if (val1 < val2)
3687c478bd9Sstevel@tonic-gate 		return (-1);
3697c478bd9Sstevel@tonic-gate 	return (0);
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate  * Determine whether a displacement relocation is between a local and global
3747c478bd9Sstevel@tonic-gate  * symbol pair.  One symbol is used to perform the relocation, and the other
3757c478bd9Sstevel@tonic-gate  * is the destination offset of the relocation.
3767c478bd9Sstevel@tonic-gate  */
3777c478bd9Sstevel@tonic-gate static uintptr_t
disp_inspect(Ofl_desc * ofl,Rel_desc * rld,Boolean rlocal)3787c478bd9Sstevel@tonic-gate disp_inspect(Ofl_desc *ofl, Rel_desc *rld, Boolean rlocal)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate 	Is_desc		*isp = rld->rel_isdesc;
3817c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl = rld->rel_isdesc->is_file;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	/*
3847c478bd9Sstevel@tonic-gate 	 * If the input files symbols haven't been sorted yet, do so.
3857c478bd9Sstevel@tonic-gate 	 */
3867c478bd9Sstevel@tonic-gate 	if (ifl->ifl_sortsyms == 0) {
3877c478bd9Sstevel@tonic-gate 		Word	ondx, nndx;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_sortsyms = libld_malloc((ifl->ifl_symscnt + 1) *
3907c478bd9Sstevel@tonic-gate 		    sizeof (Ssv_desc))) == 0)
3917c478bd9Sstevel@tonic-gate 			return (S_ERROR);
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 		for (ondx = 0, nndx = 0; ondx < ifl->ifl_symscnt; ondx++) {
3947c478bd9Sstevel@tonic-gate 			Sym_desc	*sdp;
3957c478bd9Sstevel@tonic-gate 			Addr		value;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 			/*
3987c478bd9Sstevel@tonic-gate 			 * As symbol resolution has already occurred, various
3997c478bd9Sstevel@tonic-gate 			 * symbols from this object may have been satisfied
4007c478bd9Sstevel@tonic-gate 			 * from other objects.  Only select symbols from this
4017c478bd9Sstevel@tonic-gate 			 * object.  For the displacement test, we only really
4027c478bd9Sstevel@tonic-gate 			 * need to observe data definitions, however, later as
4037c478bd9Sstevel@tonic-gate 			 * part of providing warning disgnostics, relating the
4047c478bd9Sstevel@tonic-gate 			 * relocation offset to a symbol is desirable.  Thus,
4057c478bd9Sstevel@tonic-gate 			 * collect all symbols that define a memory area.
4067c478bd9Sstevel@tonic-gate 			 */
4077c478bd9Sstevel@tonic-gate 			if (((sdp = ifl->ifl_oldndx[ondx]) == 0) ||
4080bc07c75Srie 			    (sdp->sd_sym->st_shndx == SHN_UNDEF) ||
4090bc07c75Srie 			    (sdp->sd_sym->st_shndx >= SHN_LORESERVE) ||
4107c478bd9Sstevel@tonic-gate 			    (sdp->sd_ref != REF_REL_NEED) ||
4117c478bd9Sstevel@tonic-gate 			    (sdp->sd_file != ifl) ||
4127c478bd9Sstevel@tonic-gate 			    (sdp->sd_sym->st_size == 0))
4137c478bd9Sstevel@tonic-gate 				continue;
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 			/*
4167c478bd9Sstevel@tonic-gate 			 * As a further optimization for later checking, mark
4177c478bd9Sstevel@tonic-gate 			 * this section if this a global data definition.
4187c478bd9Sstevel@tonic-gate 			 */
4197c478bd9Sstevel@tonic-gate 			if (sdp->sd_isc && (ondx >= ifl->ifl_locscnt))
4207c478bd9Sstevel@tonic-gate 				sdp->sd_isc->is_flags |= FLG_IS_GDATADEF;
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 			/*
4237c478bd9Sstevel@tonic-gate 			 * Capture the symbol.  Within relocatable objects, a
4247c478bd9Sstevel@tonic-gate 			 * symbols value is its offset within its associated
4257c478bd9Sstevel@tonic-gate 			 * section.  Add the section offset to this value to
4267c478bd9Sstevel@tonic-gate 			 * uniquify the symbol.
4277c478bd9Sstevel@tonic-gate 			 */
4287c478bd9Sstevel@tonic-gate 			value = sdp->sd_sym->st_value;
4297c478bd9Sstevel@tonic-gate 			if (sdp->sd_isc && sdp->sd_isc->is_shdr)
4307c478bd9Sstevel@tonic-gate 				value += sdp->sd_isc->is_shdr->sh_offset;
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 			ifl->ifl_sortsyms[nndx].ssv_value = value;
4337c478bd9Sstevel@tonic-gate 			ifl->ifl_sortsyms[nndx].ssv_sdp = sdp;
4347c478bd9Sstevel@tonic-gate 			nndx++;
4357c478bd9Sstevel@tonic-gate 		}
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 		/*
4387c478bd9Sstevel@tonic-gate 		 * Sort the list based on the symbols value (address).
4397c478bd9Sstevel@tonic-gate 		 */
4407c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_sortcnt = nndx) != 0)
4417c478bd9Sstevel@tonic-gate 			qsort(ifl->ifl_sortsyms, nndx, sizeof (Ssv_desc),
4427c478bd9Sstevel@tonic-gate 			    &disp_qsort);
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	/*
4467c478bd9Sstevel@tonic-gate 	 * If the reference symbol is local, and the section being relocated
4477c478bd9Sstevel@tonic-gate 	 * contains no global definitions, neither can be the target of a copy
4487c478bd9Sstevel@tonic-gate 	 * relocation.
4497c478bd9Sstevel@tonic-gate 	 */
4507c478bd9Sstevel@tonic-gate 	if ((rlocal == FALSE) && ((isp->is_flags & FLG_IS_GDATADEF) == 0))
4517c478bd9Sstevel@tonic-gate 		return (1);
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	/*
4547c478bd9Sstevel@tonic-gate 	 * Otherwise determine whether this relocation symbol and its offset
4557c478bd9Sstevel@tonic-gate 	 * could be candidates for a copy relocation.
4567c478bd9Sstevel@tonic-gate 	 */
4577c478bd9Sstevel@tonic-gate 	if (ifl->ifl_sortcnt)
4587c478bd9Sstevel@tonic-gate 		(void) disp_scansyms(ifl, rld, rlocal, 0, ofl);
4597c478bd9Sstevel@tonic-gate 	return (1);
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate 
462141040e8Srie /*
463bf994817SAli Bahrami  * Return a Rel_cachebuf with an available Rel_desc entry from the
464bf994817SAli Bahrami  * specified cache, allocating a cache buffer if necessary.
465bf994817SAli Bahrami  *
466bf994817SAli Bahrami  * entry:
467bf994817SAli Bahrami  *	ofl - Output file descriptor
468bf994817SAli Bahrami  *	rcp - Relocation cache to allocate the descriptor from.
469bf994817SAli Bahrami  *		One of &ofl->ofl_actrels or &ofl->ofl_outrels.
470bf994817SAli Bahrami  *
471bf994817SAli Bahrami  * exit:
472bf994817SAli Bahrami  *	Returns the allocated descriptor, or NULL if the allocation fails.
47357ef7aa9SRod Evans  */
474bf994817SAli Bahrami static Rel_cachebuf *
ld_add_rel_cache(Ofl_desc * ofl,Rel_cache * rcp)475bf994817SAli Bahrami ld_add_rel_cache(Ofl_desc *ofl, Rel_cache *rcp)
47657ef7aa9SRod Evans {
477bf994817SAli Bahrami 	Rel_cachebuf	*rcbp;
478bf994817SAli Bahrami 	size_t		nelts, size, alloc_cnt;
47957ef7aa9SRod Evans 
48057ef7aa9SRod Evans 	/*
48157ef7aa9SRod Evans 	 * If there is space available in the present cache bucket, return the
48257ef7aa9SRod Evans 	 * next free entry.
48357ef7aa9SRod Evans 	 */
484bf994817SAli Bahrami 	alloc_cnt = aplist_nitems(rcp->rc_list);
485bf994817SAli Bahrami 	if (rcp->rc_list &&
486bf994817SAli Bahrami 	    ((rcbp = rcp->rc_list->apl_data[alloc_cnt - 1]) != NULL) &&
487bf994817SAli Bahrami 	    (rcbp->rc_free < rcbp->rc_end))
488bf994817SAli Bahrami 		return (rcbp);
48957ef7aa9SRod Evans 
49057ef7aa9SRod Evans 	/*
491bf994817SAli Bahrami 	 * Allocate a new bucket. As we cannot know the number of relocations
492bf994817SAli Bahrami 	 * we'll have in the active and output cache until after the link is
493bf994817SAli Bahrami 	 * complete, the size of the bucket is a heuristic.
494bf994817SAli Bahrami 	 *
495bf994817SAli Bahrami 	 * In general, if the output object is an executable, or a sharable
496bf994817SAli Bahrami 	 * object, then the size of the active relocation list will be nearly
497bf994817SAli Bahrami 	 * the same as the number of input relocations, and the output
498bf994817SAli Bahrami 	 * relocation list will be very short. If the output object is a
499bf994817SAli Bahrami 	 * relocatable object, then the reverse is true. Therefore, the initial
500bf994817SAli Bahrami 	 * allocation for the appropriate list is sized to fit all the input
501bf994817SAli Bahrami 	 * allocations in a single shot.
502bf994817SAli Bahrami 	 *
503bf994817SAli Bahrami 	 * All other allocations are done in units of REL_CACHEBUF_ALLOC,
504bf994817SAli Bahrami 	 * which is chosen to be large enough to cover most common cases,
505bf994817SAli Bahrami 	 * but small enough that not using it fully is inconsequential.
506bf994817SAli Bahrami 	 *
507bf994817SAli Bahrami 	 * In an ideal scenario, this results in one allocation on each list.
50857ef7aa9SRod Evans 	 */
509bf994817SAli Bahrami 	nelts = REL_CACHEBUF_ALLOC;
510bf994817SAli Bahrami 	if ((alloc_cnt == 0) && (ofl->ofl_relocincnt > REL_CACHEBUF_ALLOC)) {
511bf994817SAli Bahrami 		Boolean is_rel = (ofl->ofl_flags & FLG_OF_RELOBJ) != 0;
51257ef7aa9SRod Evans 
513bf994817SAli Bahrami 		if (((rcp == &ofl->ofl_actrels) && !is_rel) ||
514bf994817SAli Bahrami 		    ((rcp == &ofl->ofl_outrels) && is_rel))
515bf994817SAli Bahrami 			nelts = ofl->ofl_relocincnt;
516bf994817SAli Bahrami 	}
51757ef7aa9SRod Evans 
518bf994817SAli Bahrami 	/*
519bf994817SAli Bahrami 	 * Compute the total number of bytes to allocate. The first element
520bf994817SAli Bahrami 	 * of the array is built into the Rel_cachebuf header, so we subtract
521bf994817SAli Bahrami 	 * one from nelts.
522bf994817SAli Bahrami 	 */
523bf994817SAli Bahrami 	size = sizeof (Rel_cachebuf) + ((nelts - 1) * sizeof (Rel_desc));
52457ef7aa9SRod Evans 
525bf994817SAli Bahrami 	if (((rcbp = libld_malloc(size)) == NULL) ||
526bf994817SAli Bahrami 	    (aplist_append(&rcp->rc_list, rcbp, AL_CNT_OFL_RELS) == NULL))
527bf994817SAli Bahrami 		return (NULL);
52857ef7aa9SRod Evans 
529bf994817SAli Bahrami 	rcbp->rc_free = rcbp->rc_arr;
530bf994817SAli Bahrami 	rcbp->rc_end = rcbp->rc_arr + nelts;
531bf994817SAli Bahrami 
532bf994817SAli Bahrami 	return (rcbp);
533bf994817SAli Bahrami }
534bf994817SAli Bahrami 
535bf994817SAli Bahrami /*
536bf994817SAli Bahrami  * Allocate a Rel_aux descriptor and attach it to the given Rel_desc,
537bf994817SAli Bahrami  * allocating an auxiliary cache buffer if necessary.
538bf994817SAli Bahrami  *
539bf994817SAli Bahrami  * entry:
540bf994817SAli Bahrami  *	ofl - Output file descriptor
541bf994817SAli Bahrami  *	rdp - Rel_desc descriptor that requires an auxiliary block
542bf994817SAli Bahrami  *
543bf994817SAli Bahrami  * exit:
544bf994817SAli Bahrami  *	Returns TRUE on success, and FALSE if the allocation fails.
545bf994817SAli Bahrami  *	On success, the caller is responsible for initializing the
546bf994817SAli Bahrami  *	auxiliary block properly.
547bf994817SAli Bahrami  */
548bf994817SAli Bahrami static Boolean
ld_add_rel_aux(Ofl_desc * ofl,Rel_desc * rdesc)549bf994817SAli Bahrami ld_add_rel_aux(Ofl_desc *ofl, Rel_desc *rdesc)
550bf994817SAli Bahrami {
551bf994817SAli Bahrami 	Rel_aux_cachebuf	*racp = NULL;
552bf994817SAli Bahrami 	size_t			size;
553bf994817SAli Bahrami 
554bf994817SAli Bahrami 	/*
555bf994817SAli Bahrami 	 * If there is space available in the present cache bucket, use it.
556bf994817SAli Bahrami 	 * Otherwise, allocate a new bucket.
557bf994817SAli Bahrami 	 */
558bf994817SAli Bahrami 	if (ofl->ofl_relaux) {
559bf994817SAli Bahrami 		racp = ofl->ofl_relaux->apl_data[
560bf994817SAli Bahrami 		    ofl->ofl_relaux->apl_nitems - 1];
561bf994817SAli Bahrami 
562bf994817SAli Bahrami 		if (racp && (racp->rac_free >= racp->rac_end))
563bf994817SAli Bahrami 			racp = NULL;
564bf994817SAli Bahrami 	}
565bf994817SAli Bahrami 	if (racp == NULL) {
566bf994817SAli Bahrami 		/*
567bf994817SAli Bahrami 		 * Compute the total number of bytes to allocate. The first
568bf994817SAli Bahrami 		 * element of the array is built into the Rel_aux_cachebuf
569bf994817SAli Bahrami 		 * header, so we subtract one from the number of elements.
570bf994817SAli Bahrami 		 */
571bf994817SAli Bahrami 		size = sizeof (Rel_aux_cachebuf) +
572bf994817SAli Bahrami 		    ((RELAUX_CACHEBUF_ALLOC - 1) * sizeof (Rel_aux));
573bf994817SAli Bahrami 		if (((racp = libld_malloc(size)) == NULL) ||
574bf994817SAli Bahrami 		    (aplist_append(&ofl->ofl_relaux, racp, AL_CNT_OFL_RELS) ==
575bf994817SAli Bahrami 		    NULL))
576bf994817SAli Bahrami 			return (FALSE);
577bf994817SAli Bahrami 
578bf994817SAli Bahrami 		racp->rac_free = racp->rac_arr;
579bf994817SAli Bahrami 		racp->rac_end = racp->rac_arr + RELAUX_CACHEBUF_ALLOC;
580bf994817SAli Bahrami 	}
581bf994817SAli Bahrami 
582bf994817SAli Bahrami 	/* Take an auxiliary descriptor from the cache and add it to rdesc */
583bf994817SAli Bahrami 	rdesc->rel_aux = racp->rac_free++;
584bf994817SAli Bahrami 
585bf994817SAli Bahrami 	return (TRUE);
586bf994817SAli Bahrami }
587bf994817SAli Bahrami 
588bf994817SAli Bahrami /*
589bf994817SAli Bahrami  * Enter a copy of the given Rel_desc relocation descriptor, and
590bf994817SAli Bahrami  * any associated auxiliary Rel_aux it may reference, into the
591bf994817SAli Bahrami  * specified relocation cache.
592bf994817SAli Bahrami  *
593bf994817SAli Bahrami  * entry:
594bf994817SAli Bahrami  *	ofl - Output file descriptor
595bf994817SAli Bahrami  *	rcp - Relocation descriptor cache to recieve relocation
596bf994817SAli Bahrami  *	rdesc - Rel_desc image to be inserted
597bf994817SAli Bahrami  *	flags - Flags to add to rdest->rel_flags in the inserted descriptor
598bf994817SAli Bahrami  *
599bf994817SAli Bahrami  * exit:
600bf994817SAli Bahrami  *	Returns the pointer to the inserted descriptor on success.
601bf994817SAli Bahrami  *	Returns NULL if an allocation error occurs.
602bf994817SAli Bahrami  */
603bf994817SAli Bahrami Rel_desc *
ld_reloc_enter(Ofl_desc * ofl,Rel_cache * rcp,Rel_desc * rdesc,Word flags)604bf994817SAli Bahrami ld_reloc_enter(Ofl_desc *ofl, Rel_cache *rcp, Rel_desc *rdesc, Word flags)
605bf994817SAli Bahrami {
606bf994817SAli Bahrami 	Rel_desc	*arsp;
607bf994817SAli Bahrami 	Rel_aux		*auxp;
608bf994817SAli Bahrami 	Rel_cachebuf	*rcbp;
609bf994817SAli Bahrami 
610bf994817SAli Bahrami 
611bf994817SAli Bahrami 	/*
612bf994817SAli Bahrami 	 * If no relocation cache structures are available, allocate a new
613bf994817SAli Bahrami 	 * one and link it to the buffer list.
614bf994817SAli Bahrami 	 */
615bf994817SAli Bahrami 	rcbp = ld_add_rel_cache(ofl, rcp);
616bf994817SAli Bahrami 	if (rcbp == NULL)
617bf994817SAli Bahrami 		return (NULL);
618bf994817SAli Bahrami 	arsp = rcbp->rc_free;
619bf994817SAli Bahrami 
620bf994817SAli Bahrami 	/*
621bf994817SAli Bahrami 	 * If there is an auxiliary block on the original, allocate
622bf994817SAli Bahrami 	 * one for the clone. Save the pointer, because the struct copy
623bf994817SAli Bahrami 	 * below will crush it.
624bf994817SAli Bahrami 	 */
625bf994817SAli Bahrami 	if (rdesc->rel_aux != NULL) {
626bf994817SAli Bahrami 		if (!ld_add_rel_aux(ofl, arsp))
627bf994817SAli Bahrami 			return (NULL);
628bf994817SAli Bahrami 		auxp = arsp->rel_aux;
629bf994817SAli Bahrami 	}
630bf994817SAli Bahrami 
631bf994817SAli Bahrami 	/* Copy contents of the original into the clone */
632bf994817SAli Bahrami 	*arsp = *rdesc;
633bf994817SAli Bahrami 
634bf994817SAli Bahrami 	/*
635bf994817SAli Bahrami 	 * If there is an auxiliary block, restore the clone's pointer to
636bf994817SAli Bahrami 	 * it, and copy the auxiliary contents.
637bf994817SAli Bahrami 	 */
638bf994817SAli Bahrami 	if (rdesc->rel_aux != NULL) {
639bf994817SAli Bahrami 		arsp->rel_aux = auxp;
640bf994817SAli Bahrami 		*auxp = *rdesc->rel_aux;
641bf994817SAli Bahrami 	}
642bf994817SAli Bahrami 	arsp->rel_flags |= flags;
643bf994817SAli Bahrami 
644bf994817SAli Bahrami 	rcbp->rc_free++;
645bf994817SAli Bahrami 	rcp->rc_cnt++;
646bf994817SAli Bahrami 
647bf994817SAli Bahrami 	return (arsp);
648bf994817SAli Bahrami }
649bf994817SAli Bahrami 
650bf994817SAli Bahrami /*
651bf994817SAli Bahrami  * Initialize a relocation descriptor auxiliary block to default
652bf994817SAli Bahrami  * values.
653bf994817SAli Bahrami  *
654bf994817SAli Bahrami  * entry:
655bf994817SAli Bahrami  *	rdesc - Relocation descriptor, with a non-NULL rel_aux field
656bf994817SAli Bahrami  *		pointing at the auxiliary block to be initialized.
657bf994817SAli Bahrami  *
658bf994817SAli Bahrami  * exit:
659bf994817SAli Bahrami  *	Each field in rdesc->rel_aux has been set to its default value
660bf994817SAli Bahrami  */
661bf994817SAli Bahrami static void
ld_init_rel_aux(Rel_desc * rdesc)662bf994817SAli Bahrami ld_init_rel_aux(Rel_desc *rdesc)
663bf994817SAli Bahrami {
664bf994817SAli Bahrami 	Rel_aux	*rap = rdesc->rel_aux;
665bf994817SAli Bahrami 
666bf994817SAli Bahrami 	/*
667bf994817SAli Bahrami 	 * The default output section is the one the input section
668bf994817SAli Bahrami 	 * is assigned to, assuming that there is an input section.
669bf994817SAli Bahrami 	 * Failing that, NULL is the only possibility, and we expect
670bf994817SAli Bahrami 	 * that the caller will assign an explicit value.
671bf994817SAli Bahrami 	 */
672bf994817SAli Bahrami 	rap->ra_osdesc = (rdesc->rel_isdesc == NULL) ? NULL :
673bf994817SAli Bahrami 	    rdesc->rel_isdesc->is_osdesc;
674bf994817SAli Bahrami 
675bf994817SAli Bahrami 	/* The ra_usym defaults to the value in rel_sym */
676bf994817SAli Bahrami 	rap->ra_usym = rdesc->rel_sym;
677bf994817SAli Bahrami 
678bf994817SAli Bahrami 	/* Remaining fields are zeroed */
679bf994817SAli Bahrami 	rap->ra_move = NULL;
680bf994817SAli Bahrami 	rap->ra_typedata = 0;
681bf994817SAli Bahrami }
682bf994817SAli Bahrami 
683bf994817SAli Bahrami /*
684bf994817SAli Bahrami  * The ld_reloc_set_aux_XXX() functions are used to set the value of an
685bf994817SAli Bahrami  * auxiliary relocation item on a relocation descriptor that exists in
686bf994817SAli Bahrami  * the active or output relocation cache. These descriptors are created
687bf994817SAli Bahrami  * via a call to ld_reloc_enter().
688bf994817SAli Bahrami  *
689bf994817SAli Bahrami  * These functions preserve the illusion that every relocation descriptor
690bf994817SAli Bahrami  * has a non-NULL auxiliary block into which values can be set, while
691bf994817SAli Bahrami  * only creating an auxiliary block if one is actually necessary, preventing
692bf994817SAli Bahrami  * the large memory allocations that would otherwise occur. They operate
693bf994817SAli Bahrami  * as follows:
694bf994817SAli Bahrami  *
695bf994817SAli Bahrami  * -	If an auxiliary block already exists, set the desired value and
696bf994817SAli Bahrami  *	and return TRUE.
697bf994817SAli Bahrami  *
698bf994817SAli Bahrami  * -	If no auxiliary block exists, but the desired value is the default
699bf994817SAli Bahrami  *	value for the specified item, then no auxiliary block is needed,
700bf994817SAli Bahrami  *	and TRUE is returned.
701bf994817SAli Bahrami  *
702bf994817SAli Bahrami  * -	If no auxiliary block exists, and the desired value is not the
703bf994817SAli Bahrami  *	default for the specified item, allocate an auxiliary block for
704bf994817SAli Bahrami  *	the descriptor, initialize its contents to default values for all
705bf994817SAli Bahrami  *	items, set the specified value, and return TRUE.
706bf994817SAli Bahrami  *
707bf994817SAli Bahrami  * -	If an auxiliary block needs to be added, but the allocation fails,
708bf994817SAli Bahrami  *	an error is issued, and FALSE is returned.
709bf994817SAli Bahrami  *
710bf994817SAli Bahrami  * Note that we only provide an ld_reloc_set_aux_XXX() function for those
711bf994817SAli Bahrami  * auxiliary items that libld actually modifies in Rel_desc descriptors
712bf994817SAli Bahrami  * in the active or output caches. If another one is needed, add it here.
713bf994817SAli Bahrami  *
714bf994817SAli Bahrami  * The PROCESS_NULL_REL_AUX macro is used to provide a single implementation
715bf994817SAli Bahrami  * for the logic that determines if an auxiliary block is needed or not,
716bf994817SAli Bahrami  * and handles the details of allocating and initializing it. It accepts
717bf994817SAli Bahrami  * one argument, _isdefault_predicate, which should be a call to the
718bf994817SAli Bahrami  * RELAUX_ISDEFAULT_xxx() macro appropriate for the auxiliary item
719bf994817SAli Bahrami  */
720bf994817SAli Bahrami 
721bf994817SAli Bahrami #define	PROCESS_NULL_REL_AUX(_isdefault_predicate) \
722bf994817SAli Bahrami 	if (rdesc->rel_aux == NULL) { \
723bf994817SAli Bahrami 		/* If requested value is the default, no need for aux block */ \
724bf994817SAli Bahrami 		if (_isdefault_predicate) \
725bf994817SAli Bahrami 			return (TRUE); \
726bf994817SAli Bahrami 		/* Allocate and attach an auxiliary block */ \
727bf994817SAli Bahrami 		if (!ld_add_rel_aux(ofl, rdesc)) \
728bf994817SAli Bahrami 			return (FALSE); \
729bf994817SAli Bahrami 		/* Initialize the auxiliary block with default values */ \
730bf994817SAli Bahrami 		ld_init_rel_aux(rdesc); \
731bf994817SAli Bahrami 	}
732bf994817SAli Bahrami 
733bf994817SAli Bahrami Boolean
ld_reloc_set_aux_osdesc(Ofl_desc * ofl,Rel_desc * rdesc,Os_desc * osp)734bf994817SAli Bahrami ld_reloc_set_aux_osdesc(Ofl_desc *ofl, Rel_desc *rdesc, Os_desc *osp)
735bf994817SAli Bahrami {
736bf994817SAli Bahrami 	PROCESS_NULL_REL_AUX(RELAUX_ISDEFAULT_OSDESC(rdesc, osp))
737bf994817SAli Bahrami 	rdesc->rel_aux->ra_osdesc = osp;
738bf994817SAli Bahrami 	return (TRUE);
739bf994817SAli Bahrami }
740bf994817SAli Bahrami 
741bf994817SAli Bahrami Boolean
ld_reloc_set_aux_usym(Ofl_desc * ofl,Rel_desc * rdesc,Sym_desc * sdp)742bf994817SAli Bahrami ld_reloc_set_aux_usym(Ofl_desc *ofl, Rel_desc *rdesc, Sym_desc *sdp)
743bf994817SAli Bahrami {
744bf994817SAli Bahrami 	PROCESS_NULL_REL_AUX(RELAUX_ISDEFAULT_USYM(rdesc, sdp))
745bf994817SAli Bahrami 	rdesc->rel_aux->ra_usym = sdp;
746bf994817SAli Bahrami 	return (TRUE);
747bf994817SAli Bahrami }
748bf994817SAli Bahrami 
749bf994817SAli Bahrami #undef PROCESS_NULL_REL_AUX
750bf994817SAli Bahrami 
751bf994817SAli Bahrami /*
752bf994817SAli Bahrami  * Return a descriptive name for the symbol associated with the
753bf994817SAli Bahrami  * given relocation descriptor. This will be the actual symbol
754bf994817SAli Bahrami  * name if one exists, or a suitable alternative otherwise.
755bf994817SAli Bahrami  *
756bf994817SAli Bahrami  * entry:
757bf994817SAli Bahrami  *	rsp - Relocation descriptor
758bf994817SAli Bahrami  */
759bf994817SAli Bahrami const char *
ld_reloc_sym_name(Rel_desc * rsp)760bf994817SAli Bahrami ld_reloc_sym_name(Rel_desc *rsp)
761bf994817SAli Bahrami {
762bf994817SAli Bahrami 	Sym_desc	*sdp = rsp->rel_sym;
763bf994817SAli Bahrami 
764bf994817SAli Bahrami 	if (sdp != NULL) {
765bf994817SAli Bahrami 		/* If the symbol has a valid name use it */
766bf994817SAli Bahrami 		if (sdp->sd_name && *sdp->sd_name)
767bf994817SAli Bahrami 			return (demangle(sdp->sd_name));
768bf994817SAli Bahrami 
769bf994817SAli Bahrami 		/*
770bf994817SAli Bahrami 		 * If the symbol is STT_SECTION, and the corresponding
771bf994817SAli Bahrami 		 * section symbol has the specially prepared string intended
772bf994817SAli Bahrami 		 * for this use, use that string. The string is of the form
773bf994817SAli Bahrami 		 *	secname (section)
774bf994817SAli Bahrami 		 */
775bf994817SAli Bahrami 		if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) &&
776bf994817SAli Bahrami 		    (sdp->sd_isc != NULL) && (sdp->sd_isc->is_sym_name != NULL))
777bf994817SAli Bahrami 			return (demangle(sdp->sd_isc->is_sym_name));
778bf994817SAli Bahrami 	} else {
779bf994817SAli Bahrami 		/*
780bf994817SAli Bahrami 		 * Use an empty name for a register relocation with
781bf994817SAli Bahrami 		 * no symbol.
782bf994817SAli Bahrami 		 */
783bf994817SAli Bahrami 		if (IS_REGISTER(rsp->rel_rtype))
784bf994817SAli Bahrami 			return (MSG_ORIG(MSG_STR_EMPTY));
785bf994817SAli Bahrami 	}
786bf994817SAli Bahrami 
787bf994817SAli Bahrami 	/* If all else fails, report it as <unknown> */
788bf994817SAli Bahrami 	return (MSG_INTL(MSG_STR_UNKNOWN));
78957ef7aa9SRod Evans }
79057ef7aa9SRod Evans 
79157ef7aa9SRod Evans /*
792141040e8Srie  * Add an active relocation record.
793141040e8Srie  */
794141040e8Srie uintptr_t
ld_add_actrel(Word flags,Rel_desc * rsp,Ofl_desc * ofl)7955aefb655Srie ld_add_actrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
796141040e8Srie {
797141040e8Srie 	Rel_desc	*arsp;
798141040e8Srie 
799bf994817SAli Bahrami 	if ((arsp = ld_reloc_enter(ofl, &ofl->ofl_actrels, rsp, flags)) == NULL)
800141040e8Srie 		return (S_ERROR);
801141040e8Srie 
802141040e8Srie 	/*
803141040e8Srie 	 * Any GOT relocation reference requires the creation of a .got table.
804141040e8Srie 	 * Most references to a .got require a .got entry,  which is accounted
805141040e8Srie 	 * for with the ofl_gotcnt counter.  However, some references are
806141040e8Srie 	 * relative to the .got table, but require no .got entry.  This test
807141040e8Srie 	 * insures a .got is created regardless of the type of reference.
808141040e8Srie 	 */
809141040e8Srie 	if (IS_GOT_REQUIRED(arsp->rel_rtype))
810141040e8Srie 		ofl->ofl_flags |= FLG_OF_BLDGOT;
811141040e8Srie 
812141040e8Srie 	/*
813141040e8Srie 	 * If this is a displacement relocation generate a warning.
814141040e8Srie 	 */
815141040e8Srie 	if (arsp->rel_flags & FLG_REL_DISP) {
816141040e8Srie 		ofl->ofl_dtflags_1 |= DF_1_DISPRELDNE;
817141040e8Srie 
818141040e8Srie 		if (ofl->ofl_flags & FLG_OF_VERBOSE)
8195aefb655Srie 			ld_disp_errmsg(MSG_INTL(MSG_REL_DISPREL3), arsp, ofl);
820141040e8Srie 	}
821141040e8Srie 
8225aefb655Srie 	DBG_CALL(Dbg_reloc_ars_entry(ofl->ofl_lml, ELF_DBG_LD,
823ba2be530Sab196087 	    arsp->rel_isdesc->is_shdr->sh_type, ld_targ.t_m.m_mach, arsp));
824141040e8Srie 	return (1);
825141040e8Srie }
826141040e8Srie 
827f3324781Sab196087 /*
828f3324781Sab196087  * In the platform specific machrel.XXX.c files, we sometimes write
829ba2be530Sab196087  * a value directly into the got/plt. These function can be used when
830f3324781Sab196087  * the running linker has the opposite byte order of the object being
831f3324781Sab196087  * produced.
832f3324781Sab196087  */
833ba2be530Sab196087 Word
ld_bswap_Word(Word v)834ba2be530Sab196087 ld_bswap_Word(Word v)
835f3324781Sab196087 {
836ba2be530Sab196087 	return (BSWAP_WORD(v));
837ba2be530Sab196087 }
838ba2be530Sab196087 
839ba2be530Sab196087 
840ba2be530Sab196087 Xword
ld_bswap_Xword(Xword v)841ba2be530Sab196087 ld_bswap_Xword(Xword v)
842ba2be530Sab196087 {
843ba2be530Sab196087 	return (BSWAP_XWORD(v));
844f3324781Sab196087 }
845f3324781Sab196087 
846f3324781Sab196087 
8477c478bd9Sstevel@tonic-gate uintptr_t
ld_reloc_GOT_relative(Boolean local,Rel_desc * rsp,Ofl_desc * ofl)8485aefb655Srie ld_reloc_GOT_relative(Boolean local, Rel_desc *rsp, Ofl_desc *ofl)
8497c478bd9Sstevel@tonic-gate {
85057ef7aa9SRod Evans 	Sym_desc	*sdp = rsp->rel_sym;
8511d9df23bSab196087 	ofl_flag_t	flags = ofl->ofl_flags;
8527c478bd9Sstevel@tonic-gate 	Gotndx		*gnp;
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	/*
8557c478bd9Sstevel@tonic-gate 	 * If this is the first time we've seen this symbol in a GOT
8567c478bd9Sstevel@tonic-gate 	 * relocation we need to assign it a GOT token.  Once we've got
8577c478bd9Sstevel@tonic-gate 	 * all of the GOT's assigned we can assign the actual indexes.
8587c478bd9Sstevel@tonic-gate 	 */
85957ef7aa9SRod Evans 	if ((gnp = (*ld_targ.t_mr.mr_find_got_ndx)(sdp->sd_GOTndxs,
860ba2be530Sab196087 	    GOT_REF_GENERIC, ofl, rsp)) == 0) {
8617c478bd9Sstevel@tonic-gate 		Word	rtype = rsp->rel_rtype;
8627c478bd9Sstevel@tonic-gate 
86357ef7aa9SRod Evans 		if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), NULL,
864ba2be530Sab196087 		    GOT_REF_GENERIC, ofl, rsp, sdp) == S_ERROR)
8657c478bd9Sstevel@tonic-gate 			return (S_ERROR);
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 		/*
868c1d50c4dSAli Bahrami 		 * Initialize the GOT table entry.
8697c478bd9Sstevel@tonic-gate 		 *
870c1d50c4dSAli Bahrami 		 * For global symbols, we clear the GOT table entry and create
871c1d50c4dSAli Bahrami 		 * a GLOB_DAT relocation against the symbol.
8727c478bd9Sstevel@tonic-gate 		 *
873c1d50c4dSAli Bahrami 		 * For local symbols, we enter the symbol value into a GOT
874c1d50c4dSAli Bahrami 		 * table entry and create a relative relocation if all of
875c1d50c4dSAli Bahrami 		 * the following hold:
876c1d50c4dSAli Bahrami 		 *
877c1d50c4dSAli Bahrami 		 * -	Output is a shared object
878c1d50c4dSAli Bahrami 		 * -	Symbol is not ABS
879c1d50c4dSAli Bahrami 		 * -	Relocation is not against one of the special sections
880c1d50c4dSAli Bahrami 		 *	(COMMON, ...)
881c1d50c4dSAli Bahrami 		 * -	This is not one of the generated symbols we have
882c1d50c4dSAli Bahrami 		 *	to update after the output object has been fully
883c1d50c4dSAli Bahrami 		 *	laid out (_START_, _END_, ...)
884c1d50c4dSAli Bahrami 		 *
885c1d50c4dSAli Bahrami 		 * Local symbols that don't meet the above requirements
886c1d50c4dSAli Bahrami 		 * are processed as is.
8877c478bd9Sstevel@tonic-gate 		 */
8887c478bd9Sstevel@tonic-gate 		if (local == TRUE) {
889c1d50c4dSAli Bahrami 			if ((flags & FLG_OF_SHAROBJ) &&
890c1d50c4dSAli Bahrami 			    (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) ||
891c1d50c4dSAli Bahrami 			    ((sdp->sd_sym->st_shndx != SHN_ABS)) ||
892c1d50c4dSAli Bahrami 			    (sdp->sd_aux && sdp->sd_aux->sa_symspec))) {
8935aefb655Srie 				if (ld_add_actrel((FLG_REL_GOT | FLG_REL_GOTCL),
8947c478bd9Sstevel@tonic-gate 				    rsp, ofl) == S_ERROR)
8957c478bd9Sstevel@tonic-gate 					return (S_ERROR);
8967c478bd9Sstevel@tonic-gate 
897c1d50c4dSAli Bahrami 				rsp->rel_rtype = ld_targ.t_m.m_r_relative;
898c1d50c4dSAli Bahrami 
899ba2be530Sab196087 				if ((*ld_targ.t_mr.mr_add_outrel)
900c1d50c4dSAli Bahrami 				    ((FLG_REL_GOT | FLG_REL_ADVAL),
901c1d50c4dSAli Bahrami 				    rsp, ofl) == S_ERROR)
9027c478bd9Sstevel@tonic-gate 					return (S_ERROR);
903c1d50c4dSAli Bahrami 
9047c478bd9Sstevel@tonic-gate 				rsp->rel_rtype = rtype;
9057c478bd9Sstevel@tonic-gate 			} else {
9065aefb655Srie 				if (ld_add_actrel(FLG_REL_GOT, rsp,
9077c478bd9Sstevel@tonic-gate 				    ofl) == S_ERROR)
9087c478bd9Sstevel@tonic-gate 					return (S_ERROR);
9097c478bd9Sstevel@tonic-gate 			}
9107c478bd9Sstevel@tonic-gate 		} else {
911ba2be530Sab196087 			rsp->rel_rtype = ld_targ.t_m.m_r_glob_dat;
912ba2be530Sab196087 			if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_GOT,
913ba2be530Sab196087 			    rsp, ofl) == S_ERROR)
9147c478bd9Sstevel@tonic-gate 				return (S_ERROR);
9157c478bd9Sstevel@tonic-gate 			rsp->rel_rtype = rtype;
9167c478bd9Sstevel@tonic-gate 		}
9177c478bd9Sstevel@tonic-gate 	} else {
918ba2be530Sab196087 		if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), gnp,
919ba2be530Sab196087 		    GOT_REF_GENERIC, ofl, rsp, sdp) == S_ERROR)
9207c478bd9Sstevel@tonic-gate 			return (S_ERROR);
9217c478bd9Sstevel@tonic-gate 	}
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 	/*
9247c478bd9Sstevel@tonic-gate 	 * Perform relocation to GOT table entry.
9257c478bd9Sstevel@tonic-gate 	 */
9265aefb655Srie 	return (ld_add_actrel(NULL, rsp, ofl));
9277c478bd9Sstevel@tonic-gate }
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate /*
9307c478bd9Sstevel@tonic-gate  * Perform relocations for PLT's
9317c478bd9Sstevel@tonic-gate  */
9327c478bd9Sstevel@tonic-gate uintptr_t
ld_reloc_plt(Rel_desc * rsp,Ofl_desc * ofl)9335aefb655Srie ld_reloc_plt(Rel_desc *rsp, Ofl_desc *ofl)
9347c478bd9Sstevel@tonic-gate {
9357c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp = rsp->rel_sym;
9367c478bd9Sstevel@tonic-gate 
937ba2be530Sab196087 	switch (ld_targ.t_m.m_mach) {
938ba2be530Sab196087 	case EM_AMD64:
9397c478bd9Sstevel@tonic-gate 		/*
940ba2be530Sab196087 		 * AMD64 TLS code sequences do not use a unique TLS
941ba2be530Sab196087 		 * relocation to reference the __tls_get_addr() function call.
9427c478bd9Sstevel@tonic-gate 		 */
9437c478bd9Sstevel@tonic-gate 		if ((ofl->ofl_flags & FLG_OF_EXEC) &&
944ba2be530Sab196087 		    (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_U)) ==
945ba2be530Sab196087 		    0))
9465aefb655Srie 			return (ld_add_actrel(FLG_REL_TLSFIX, rsp, ofl));
947ba2be530Sab196087 		break;
948ba2be530Sab196087 
949ba2be530Sab196087 	case EM_386:
9507c478bd9Sstevel@tonic-gate 		/*
951ba2be530Sab196087 		 * GNUC IA32 TLS code sequences do not use a unique TLS
952ba2be530Sab196087 		 * relocation to reference the ___tls_get_addr() function call.
9537c478bd9Sstevel@tonic-gate 		 */
9547c478bd9Sstevel@tonic-gate 		if ((ofl->ofl_flags & FLG_OF_EXEC) &&
955ba2be530Sab196087 		    (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_UU)) ==
956ba2be530Sab196087 		    0))
9575aefb655Srie 			return (ld_add_actrel(FLG_REL_TLSFIX, rsp, ofl));
958ba2be530Sab196087 		break;
9597c478bd9Sstevel@tonic-gate 	}
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	/*
9627c478bd9Sstevel@tonic-gate 	 * if (not PLT yet assigned)
9637c478bd9Sstevel@tonic-gate 	 * then
9647c478bd9Sstevel@tonic-gate 	 *	assign PLT index to symbol
9657c478bd9Sstevel@tonic-gate 	 *	build output JMP_SLOT relocation
9667c478bd9Sstevel@tonic-gate 	 * fi
9677c478bd9Sstevel@tonic-gate 	 */
9687c478bd9Sstevel@tonic-gate 	if (sdp->sd_aux->sa_PLTndx == 0) {
9697c478bd9Sstevel@tonic-gate 		Word	ortype = rsp->rel_rtype;
9707c478bd9Sstevel@tonic-gate 
971ba2be530Sab196087 		(*ld_targ.t_mr.mr_assign_plt_ndx)(sdp, ofl);
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 		/*
974f441771bSRod Evans 		 * If this symbol is binding to a lazy loadable, or deferred
975f441771bSRod Evans 		 * dependency, then identify the symbol.
9767c478bd9Sstevel@tonic-gate 		 */
977f441771bSRod Evans 		if (sdp->sd_file) {
978f441771bSRod Evans 			if (sdp->sd_file->ifl_flags & FLG_IF_LAZYLD)
9797c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_LAZYLD;
980f441771bSRod Evans 			if (sdp->sd_file->ifl_flags & FLG_IF_DEFERRED)
981f441771bSRod Evans 				sdp->sd_flags |= FLG_SY_DEFERRED;
982f441771bSRod Evans 		}
9837c478bd9Sstevel@tonic-gate 
984ba2be530Sab196087 		rsp->rel_rtype = ld_targ.t_m.m_r_jmp_slot;
985ba2be530Sab196087 		if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_PLT, rsp, ofl) ==
986ba2be530Sab196087 		    S_ERROR)
9877c478bd9Sstevel@tonic-gate 			return (S_ERROR);
9887c478bd9Sstevel@tonic-gate 		rsp->rel_rtype = ortype;
9897c478bd9Sstevel@tonic-gate 	}
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 	/*
9927c478bd9Sstevel@tonic-gate 	 * Perform relocation to PLT table entry.
9937c478bd9Sstevel@tonic-gate 	 */
9947c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_flags & FLG_OF_SHAROBJ) &&
9957c478bd9Sstevel@tonic-gate 	    IS_ADD_RELATIVE(rsp->rel_rtype)) {
9967c478bd9Sstevel@tonic-gate 		Word	ortype	= rsp->rel_rtype;
9977c478bd9Sstevel@tonic-gate 
998ba2be530Sab196087 		rsp->rel_rtype = ld_targ.t_m.m_r_relative;
999ba2be530Sab196087 		if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_ADVAL, rsp, ofl) ==
1000ba2be530Sab196087 		    S_ERROR)
10017c478bd9Sstevel@tonic-gate 			return (S_ERROR);
10027c478bd9Sstevel@tonic-gate 		rsp->rel_rtype = ortype;
10037c478bd9Sstevel@tonic-gate 		return (1);
10047c478bd9Sstevel@tonic-gate 	} else
10055aefb655Srie 		return (ld_add_actrel(NULL, rsp, ofl));
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate /*
100902938ba2SRod Evans  * Round up to the next power of 2.  Used to ensure section alignments that can
101002938ba2SRod Evans  * be used for copy relocation symbol alignments are sane values.
101102938ba2SRod Evans  */
101202938ba2SRod Evans static Word
nlpo2(Word val)101302938ba2SRod Evans nlpo2(Word val)
101402938ba2SRod Evans {
101502938ba2SRod Evans 	val--;
101602938ba2SRod Evans 	val |= (val >> 1);
101702938ba2SRod Evans 	val |= (val >> 2);
101802938ba2SRod Evans 	val |= (val >> 4);
101902938ba2SRod Evans 	val |= (val >> 8);
102002938ba2SRod Evans 	val |= (val >> 16);
102102938ba2SRod Evans 	return (++val);
102202938ba2SRod Evans }
102302938ba2SRod Evans 
102402938ba2SRod Evans /*
10257c478bd9Sstevel@tonic-gate  * process GLOBAL undefined and ref_dyn_need symbols.
10267c478bd9Sstevel@tonic-gate  */
10275aefb655Srie static uintptr_t
reloc_exec(Rel_desc * rsp,Ofl_desc * ofl)10287c478bd9Sstevel@tonic-gate reloc_exec(Rel_desc *rsp, Ofl_desc *ofl)
10297c478bd9Sstevel@tonic-gate {
10307c478bd9Sstevel@tonic-gate 	Sym_desc	*_sdp, *sdp = rsp->rel_sym;
10317c478bd9Sstevel@tonic-gate 	Sym_aux		*sap = sdp->sd_aux;
10327c478bd9Sstevel@tonic-gate 	Sym		*sym = sdp->sd_sym;
10337c478bd9Sstevel@tonic-gate 	Addr		stval;
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	/*
10367c478bd9Sstevel@tonic-gate 	 * Reference is to a function so simply create a plt entry for it.
10377c478bd9Sstevel@tonic-gate 	 */
10387c478bd9Sstevel@tonic-gate 	if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
10395aefb655Srie 		return (ld_reloc_plt(rsp, ofl));
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 	/*
10427c478bd9Sstevel@tonic-gate 	 * Catch absolutes - these may cause a text relocation.
10437c478bd9Sstevel@tonic-gate 	 */
10440bc07c75Srie 	if ((sdp->sd_flags & FLG_SY_SPECSEC) && (sym->st_shndx == SHN_ABS)) {
10457c478bd9Sstevel@tonic-gate 		if ((ofl->ofl_flags1 & FLG_OF1_ABSEXEC) == 0)
1046ba2be530Sab196087 			return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl));
10475aefb655Srie 
10487c478bd9Sstevel@tonic-gate 		/*
10495aefb655Srie 		 * If -zabsexec is set then promote the ABSOLUTE symbol to
10505aefb655Srie 		 * current the current object and perform the relocation now.
10517c478bd9Sstevel@tonic-gate 		 */
10527c478bd9Sstevel@tonic-gate 		sdp->sd_ref = REF_REL_NEED;
10535aefb655Srie 		return (ld_add_actrel(NULL, rsp, ofl));
10547c478bd9Sstevel@tonic-gate 	}
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate 	/*
10577c478bd9Sstevel@tonic-gate 	 * If the relocation is against a writable section simply compute the
10587c478bd9Sstevel@tonic-gate 	 * necessary output relocation.  As an optimization, if the symbol has
10597c478bd9Sstevel@tonic-gate 	 * already been transformed into a copy relocation then we can perform
10607c478bd9Sstevel@tonic-gate 	 * the relocation directly (copy relocations should only be generated
10617c478bd9Sstevel@tonic-gate 	 * for references from the text segment and these relocations are
10627c478bd9Sstevel@tonic-gate 	 * normally carried out before we get to the data segment relocations).
10637c478bd9Sstevel@tonic-gate 	 */
10647c478bd9Sstevel@tonic-gate 	if ((ELF_ST_TYPE(sym->st_info) == STT_OBJECT) &&
1065bf994817SAli Bahrami 	    (RELAUX_GET_OSDESC(rsp)->os_shdr->sh_flags & SHF_WRITE)) {
10667c478bd9Sstevel@tonic-gate 		if (sdp->sd_flags & FLG_SY_MVTOCOMM)
10675aefb655Srie 			return (ld_add_actrel(NULL, rsp, ofl));
10687c478bd9Sstevel@tonic-gate 		else
1069ba2be530Sab196087 			return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl));
10707c478bd9Sstevel@tonic-gate 	}
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 	/*
10735aefb655Srie 	 * If the reference isn't to an object (normally because a .type
107402938ba2SRod Evans 	 * directive wasn't defined in some assembler source), then apply
10755aefb655Srie 	 * a generic relocation (this has a tendency to result in text
10765aefb655Srie 	 * relocations).
10777c478bd9Sstevel@tonic-gate 	 */
10787c478bd9Sstevel@tonic-gate 	if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) {
1079de777a60Sab196087 		Conv_inv_buf_t inv_buf;
1080de777a60Sab196087 
1081*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_UNEXPSYM),
10825aefb655Srie 		    conv_sym_info_type(sdp->sd_file->ifl_ehdr->e_machine,
1083de777a60Sab196087 		    ELF_ST_TYPE(sym->st_info), 0, &inv_buf),
10847c478bd9Sstevel@tonic-gate 		    rsp->rel_isdesc->is_file->ifl_name,
1085bf994817SAli Bahrami 		    ld_reloc_sym_name(rsp), sdp->sd_file->ifl_name);
1086ba2be530Sab196087 		return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl));
10877c478bd9Sstevel@tonic-gate 	}
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 	/*
10907c478bd9Sstevel@tonic-gate 	 * Prepare for generating a copy relocation.
10917c478bd9Sstevel@tonic-gate 	 *
109202938ba2SRod Evans 	 * If this symbol is one of an alias pair, we need to ensure both
10937c478bd9Sstevel@tonic-gate 	 * symbols become part of the output (the strong symbol will be used to
10947c478bd9Sstevel@tonic-gate 	 * maintain the symbols state).  And, if we did raise the precedence of
10957c478bd9Sstevel@tonic-gate 	 * a symbol we need to check and see if this is a weak symbol.  If it is
10967c478bd9Sstevel@tonic-gate 	 * we want to use it's strong counter part.
10977c478bd9Sstevel@tonic-gate 	 *
10987c478bd9Sstevel@tonic-gate 	 * The results of this logic should be:
1099bf994817SAli Bahrami 	 *	ra_usym: assigned to strong
11007c478bd9Sstevel@tonic-gate 	 *	rel_sym: assigned to symbol to perform
11017c478bd9Sstevel@tonic-gate 	 *		copy_reloc against (weak or strong).
11027c478bd9Sstevel@tonic-gate 	 */
11037c478bd9Sstevel@tonic-gate 	if (sap->sa_linkndx) {
11047c478bd9Sstevel@tonic-gate 		_sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx];
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate 		if (_sdp->sd_ref < sdp->sd_ref) {
11077c478bd9Sstevel@tonic-gate 			_sdp->sd_ref = sdp->sd_ref;
11087c478bd9Sstevel@tonic-gate 			_sdp->sd_flags |= FLG_SY_REFRSD;
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 			/*
11117c478bd9Sstevel@tonic-gate 			 * As we're going to replicate a symbol from a shared
11127c478bd9Sstevel@tonic-gate 			 * object, retain its correct binding status.
11137c478bd9Sstevel@tonic-gate 			 */
11147c478bd9Sstevel@tonic-gate 			if (ELF_ST_BIND(_sdp->sd_sym->st_info) == STB_GLOBAL)
11157c478bd9Sstevel@tonic-gate 				_sdp->sd_flags |= FLG_SY_GLOBREF;
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 		} else if (_sdp->sd_ref > sdp->sd_ref) {
11187c478bd9Sstevel@tonic-gate 			sdp->sd_ref = _sdp->sd_ref;
11197c478bd9Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_REFRSD;
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 			/*
11227c478bd9Sstevel@tonic-gate 			 * As we're going to replicate a symbol from a shared
11237c478bd9Sstevel@tonic-gate 			 * object, retain its correct binding status.
11247c478bd9Sstevel@tonic-gate 			 */
11257c478bd9Sstevel@tonic-gate 			if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL)
11267c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_GLOBREF;
11277c478bd9Sstevel@tonic-gate 		}
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 		/*
11307c478bd9Sstevel@tonic-gate 		 * If this is a weak symbol then we want to move the strong
11317c478bd9Sstevel@tonic-gate 		 * symbol into local .bss.  If there is a copy_reloc to be
11327c478bd9Sstevel@tonic-gate 		 * performed, that should still occur against the WEAK symbol.
11337c478bd9Sstevel@tonic-gate 		 */
1134bf994817SAli Bahrami 		if (((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_WEAK) ||
1135bf994817SAli Bahrami 		    (sdp->sd_flags & FLG_SY_WEAKDEF)) &&
1136bf994817SAli Bahrami 		    !ld_reloc_set_aux_usym(ofl, rsp, _sdp))
1137bf994817SAli Bahrami 			return (S_ERROR);
11387c478bd9Sstevel@tonic-gate 	} else
11397c478bd9Sstevel@tonic-gate 		_sdp = 0;
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 	/*
11427c478bd9Sstevel@tonic-gate 	 * If the reference is to an object then allocate space for the object
11437c478bd9Sstevel@tonic-gate 	 * within the executables .bss.  Relocations will now be performed from
11447c478bd9Sstevel@tonic-gate 	 * this new location.  If the original shared objects data is
11457c478bd9Sstevel@tonic-gate 	 * initialized, then generate a copy relocation that will copy the data
11467c478bd9Sstevel@tonic-gate 	 * to the executables .bss at runtime.
11477c478bd9Sstevel@tonic-gate 	 */
1148bf994817SAli Bahrami 	if (!(RELAUX_GET_USYM(rsp)->sd_flags & FLG_SY_MVTOCOMM)) {
114902938ba2SRod Evans 		Word		rtype = rsp->rel_rtype, w2align;
115057ef7aa9SRod Evans 		Copy_rel	cr;
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 		/*
115302938ba2SRod Evans 		 * Diagnose the original copy reference, as this symbol
115402938ba2SRod Evans 		 * information will be overridden with the new destination.
115502938ba2SRod Evans 		 */
115602938ba2SRod Evans 		DBG_CALL(Dbg_syms_copy_reloc(ofl, sdp, 0));
115702938ba2SRod Evans 
115802938ba2SRod Evans 		/*
11597c478bd9Sstevel@tonic-gate 		 * Indicate that the symbol(s) against which we're relocating
11607c478bd9Sstevel@tonic-gate 		 * have been moved to the executables common.  Also, insure that
11617c478bd9Sstevel@tonic-gate 		 * the symbol(s) remain marked as global, as the shared object
11627c478bd9Sstevel@tonic-gate 		 * from which they are copied must be able to relocate to the
11637c478bd9Sstevel@tonic-gate 		 * new common location within the executable.
11647c478bd9Sstevel@tonic-gate 		 *
11657c478bd9Sstevel@tonic-gate 		 * Note that even though a new symbol has been generated in the
11667c478bd9Sstevel@tonic-gate 		 * output files' .bss, the symbol must remain REF_DYN_NEED and
11677c478bd9Sstevel@tonic-gate 		 * not be promoted to REF_REL_NEED.  sym_validate() still needs
11687c478bd9Sstevel@tonic-gate 		 * to carry out a number of checks against the symbols binding
11697c478bd9Sstevel@tonic-gate 		 * that are triggered by the REF_DYN_NEED state.
11707c478bd9Sstevel@tonic-gate 		 */
1171635216b6SRod Evans 		sdp->sd_flags |=
1172635216b6SRod Evans 		    (FLG_SY_MVTOCOMM | FLG_SY_DEFAULT | FLG_SY_EXPDEF);
1173635216b6SRod Evans 		sdp->sd_flags &= ~MSK_SY_LOCAL;
11747c478bd9Sstevel@tonic-gate 		sdp->sd_sym->st_other &= ~MSK_SYM_VISIBILITY;
11757c478bd9Sstevel@tonic-gate 		if (_sdp) {
1176635216b6SRod Evans 			_sdp->sd_flags |= (FLG_SY_MVTOCOMM |
1177635216b6SRod Evans 			    FLG_SY_DEFAULT | FLG_SY_EXPDEF);
1178635216b6SRod Evans 			_sdp->sd_flags &= ~MSK_SY_LOCAL;
11797c478bd9Sstevel@tonic-gate 			_sdp->sd_sym->st_other &= ~MSK_SYM_VISIBILITY;
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 			/*
11827c478bd9Sstevel@tonic-gate 			 * Make sure the symbol has a reference in case of any
11837c478bd9Sstevel@tonic-gate 			 * error diagnostics against it (perhaps this belongs
11847c478bd9Sstevel@tonic-gate 			 * to a version that isn't allowable for this build).
11857c478bd9Sstevel@tonic-gate 			 * The resulting diagnostic (see sym_undef_entry())
11867c478bd9Sstevel@tonic-gate 			 * might seem a little bogus, as the symbol hasn't
11877c478bd9Sstevel@tonic-gate 			 * really been referenced by this file, but has been
11887c478bd9Sstevel@tonic-gate 			 * promoted as a consequence of its alias reference.
11897c478bd9Sstevel@tonic-gate 			 */
11907c478bd9Sstevel@tonic-gate 			if (!(_sdp->sd_aux->sa_rfile))
11917c478bd9Sstevel@tonic-gate 				_sdp->sd_aux->sa_rfile = sdp->sd_aux->sa_rfile;
11927c478bd9Sstevel@tonic-gate 		}
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 		/*
119502938ba2SRod Evans 		 * Assign the symbol to the bss.
11967c478bd9Sstevel@tonic-gate 		 */
1197bf994817SAli Bahrami 		_sdp = RELAUX_GET_USYM(rsp);
11987c478bd9Sstevel@tonic-gate 		stval = _sdp->sd_sym->st_value;
11995aefb655Srie 		if (ld_sym_copy(_sdp) == S_ERROR)
12007c478bd9Sstevel@tonic-gate 			return (S_ERROR);
12017c478bd9Sstevel@tonic-gate 		_sdp->sd_shndx = _sdp->sd_sym->st_shndx = SHN_COMMON;
12027c478bd9Sstevel@tonic-gate 		_sdp->sd_flags |= FLG_SY_SPECSEC;
120302938ba2SRod Evans 
120402938ba2SRod Evans 		/*
120502938ba2SRod Evans 		 * Ensure the symbol has sufficient alignment.  The symbol
120602938ba2SRod Evans 		 * definition has no alignment information that can be used,
120702938ba2SRod Evans 		 * hence we use a heuristic.  Historically, twice the native
120802938ba2SRod Evans 		 * word alignment was sufficient for any data type, however,
120902938ba2SRod Evans 		 * the developer may have requested larger alignments (pragma
121002938ba2SRod Evans 		 * align).  The most conservative approach is to use a power
121102938ba2SRod Evans 		 * of two alignment, determined from the alignment of the
121202938ba2SRod Evans 		 * section containing the symbol definition.  Note that this
121302938ba2SRod Evans 		 * can result in some bloat to the .bss as the not every item
121402938ba2SRod Evans 		 * of copied data might need the section alignment.
121502938ba2SRod Evans 		 *
121602938ba2SRod Evans 		 * COMMON symbols carry their alignment requirements in the
121702938ba2SRod Evans 		 * symbols st_value field.  This alignment is applied to the
121802938ba2SRod Evans 		 * symbol when it is eventually transformed into .bss.
121902938ba2SRod Evans 		 */
122002938ba2SRod Evans 		w2align = ld_targ.t_m.m_word_align * 2;
122102938ba2SRod Evans 		if (_sdp->sd_sym->st_size < w2align)
122202938ba2SRod Evans 			_sdp->sd_sym->st_value = ld_targ.t_m.m_word_align;
122302938ba2SRod Evans 		else {
122402938ba2SRod Evans 			Shdr	*shdr;
122502938ba2SRod Evans 			Word	isalign;
122602938ba2SRod Evans 
122702938ba2SRod Evans 			if (_sdp->sd_isc &&
122802938ba2SRod Evans 			    ((shdr = _sdp->sd_isc->is_shdr) != NULL) &&
122902938ba2SRod Evans 			    ((isalign = shdr->sh_addralign) != 0))
123002938ba2SRod Evans 				_sdp->sd_sym->st_value = nlpo2(isalign);
123102938ba2SRod Evans 			else
123202938ba2SRod Evans 				_sdp->sd_sym->st_value = w2align;
123302938ba2SRod Evans 		}
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 		/*
123657ef7aa9SRod Evans 		 * Whether or not the symbol references initialized data we
123757ef7aa9SRod Evans 		 * generate a copy relocation - this differs from the past
123857ef7aa9SRod Evans 		 * where we would not create the COPY_RELOC if we were binding
123957ef7aa9SRod Evans 		 * against .bss.  This is done for *two* reasons.
12407c478bd9Sstevel@tonic-gate 		 *
124157ef7aa9SRod Evans 		 *  -	If the symbol in the shared object changes to a
124257ef7aa9SRod Evans 		 *	initialized data - we need the COPY to pick it up.
124357ef7aa9SRod Evans 		 *  -	Without the COPY RELOC we can't tell that the symbol
124457ef7aa9SRod Evans 		 *	from the COPY'd object has been moved and all bindings
124557ef7aa9SRod Evans 		 *	to it should bind here.
124657ef7aa9SRod Evans 		 *
124757ef7aa9SRod Evans 		 * Keep this symbol in the copy relocation list to check the
124857ef7aa9SRod Evans 		 * validity later.
12497c478bd9Sstevel@tonic-gate 		 */
125057ef7aa9SRod Evans 		cr.c_sdp = _sdp;
125157ef7aa9SRod Evans 		cr.c_val = stval;
125257ef7aa9SRod Evans 		if (alist_append(&ofl->ofl_copyrels, &cr, sizeof (Copy_rel),
125357ef7aa9SRod Evans 		    AL_CNT_OFL_COPYRELS) == NULL)
12547c478bd9Sstevel@tonic-gate 			return (S_ERROR);
12557c478bd9Sstevel@tonic-gate 
1256ba2be530Sab196087 		rsp->rel_rtype = ld_targ.t_m.m_r_copy;
1257ba2be530Sab196087 		if ((*ld_targ.t_mr.mr_add_outrel)(FLG_REL_BSS, rsp, ofl) ==
1258ba2be530Sab196087 		    S_ERROR)
12597c478bd9Sstevel@tonic-gate 			return (S_ERROR);
12607c478bd9Sstevel@tonic-gate 		rsp->rel_rtype = rtype;
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 		/*
126302938ba2SRod Evans 		 * If this symbol is a protected symbol, warn the user.  A
126402938ba2SRod Evans 		 * potential issue exists as the copy relocated symbol within
126502938ba2SRod Evans 		 * the executable can be visible to others, whereas the shared
126602938ba2SRod Evans 		 * object that defined the original copy data symbol is pre-
126702938ba2SRod Evans 		 * bound to reference it's own definition.  Any modification
126802938ba2SRod Evans 		 * of the symbols data could lead to inconsistencies for the
126902938ba2SRod Evans 		 * various users.
12707c478bd9Sstevel@tonic-gate 		 */
1271de777a60Sab196087 		if (_sdp->sd_flags & FLG_SY_PROT) {
1272de777a60Sab196087 			Conv_inv_buf_t inv_buf;
1273de777a60Sab196087 
1274*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_COPY),
12755aefb655Srie 			    conv_reloc_type(_sdp->sd_file->ifl_ehdr->e_machine,
1276ba2be530Sab196087 			    ld_targ.t_m.m_r_copy, 0, &inv_buf),
1277ba2be530Sab196087 			    _sdp->sd_file->ifl_name, _sdp->sd_name);
1278de777a60Sab196087 		}
127902938ba2SRod Evans 		DBG_CALL(Dbg_syms_copy_reloc(ofl, _sdp,
128002938ba2SRod Evans 		    _sdp->sd_sym->st_value));
12817c478bd9Sstevel@tonic-gate 	}
12825aefb655Srie 	return (ld_add_actrel(NULL, rsp, ofl));
12837c478bd9Sstevel@tonic-gate }
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate /*
12867c478bd9Sstevel@tonic-gate  * All relocations should have been handled by the other routines.  This
12875aefb655Srie  * routine is here as a catch all, if we do enter it we've goofed - but
1288635216b6SRod Evans  * we'll try and do the best we can.
12897c478bd9Sstevel@tonic-gate  */
12905aefb655Srie static uintptr_t
reloc_generic(Rel_desc * rsp,Ofl_desc * ofl)12917c478bd9Sstevel@tonic-gate reloc_generic(Rel_desc *rsp, Ofl_desc *ofl)
12927c478bd9Sstevel@tonic-gate {
12935aefb655Srie 	Ifl_desc	*ifl = rsp->rel_isdesc->is_file;
1294de777a60Sab196087 	Conv_inv_buf_t	inv_buf;
12957c478bd9Sstevel@tonic-gate 
1296*1007fd6fSAli Bahrami 	ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_UNEXPREL),
1297de777a60Sab196087 	    conv_reloc_type(ifl->ifl_ehdr->e_machine, rsp->rel_rtype,
1298bf994817SAli Bahrami 	    0, &inv_buf), ifl->ifl_name, ld_reloc_sym_name(rsp));
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate 	/*
13017c478bd9Sstevel@tonic-gate 	 * If building a shared object then put the relocation off
13027c478bd9Sstevel@tonic-gate 	 * until runtime.
13037c478bd9Sstevel@tonic-gate 	 */
13045aefb655Srie 	if (ofl->ofl_flags & FLG_OF_SHAROBJ)
1305ba2be530Sab196087 		return ((*ld_targ.t_mr.mr_add_outrel)(NULL, rsp, ofl));
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate 	/*
13087c478bd9Sstevel@tonic-gate 	 * Otherwise process relocation now.
13097c478bd9Sstevel@tonic-gate 	 */
13105aefb655Srie 	return (ld_add_actrel(NULL, rsp, ofl));
13117c478bd9Sstevel@tonic-gate }
13127c478bd9Sstevel@tonic-gate 
1313141040e8Srie /*
1314141040e8Srie  * Process relocations when building a relocatable object.  Typically, there
1315141040e8Srie  * aren't many relocations that can be caught at this point, most are simply
1316141040e8Srie  * passed through to the output relocatable object.
1317141040e8Srie  */
1318141040e8Srie static uintptr_t
reloc_relobj(Boolean local,Rel_desc * rsp,Ofl_desc * ofl)1319141040e8Srie reloc_relobj(Boolean local, Rel_desc *rsp, Ofl_desc *ofl)
1320141040e8Srie {
1321141040e8Srie 	Word		rtype = rsp->rel_rtype;
1322141040e8Srie 	Sym_desc	*sdp = rsp->rel_sym;
1323141040e8Srie 	Is_desc		*isp = rsp->rel_isdesc;
1324141040e8Srie 	Word		oflags = NULL;
1325141040e8Srie 
1326141040e8Srie 	/*
1327141040e8Srie 	 * Determine if we can do any relocations at this point.  We can if:
1328141040e8Srie 	 *
1329141040e8Srie 	 *	this is local_symbol and a non-GOT relocation, and
1330141040e8Srie 	 *	the relocation is pc-relative, and
1331141040e8Srie 	 *	the relocation is against a symbol in same section
1332141040e8Srie 	 */
1333ba2be530Sab196087 	if (local && !IS_GOT_RELATIVE(rtype) &&
1334ba2be530Sab196087 	    !IS_GOT_BASED(rtype) && !IS_GOT_PC(rtype) &&
1335ba2be530Sab196087 	    IS_PC_RELATIVE(rtype) &&
1336141040e8Srie 	    ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc)))
13375aefb655Srie 		return (ld_add_actrel(NULL, rsp, ofl));
1338141040e8Srie 
1339141040e8Srie 	/*
1340141040e8Srie 	 * If -zredlocsym is in effect, translate all local symbol relocations
134160758829Srie 	 * to be against section symbols, since section symbols are the only
134260758829Srie 	 * local symbols which will be added to the .symtab.
1343141040e8Srie 	 */
134444bac77bSrie 	if (local && (((ofl->ofl_flags & FLG_OF_REDLSYM) &&
1345141040e8Srie 	    (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) ||
1346635216b6SRod Evans 	    ((sdp->sd_flags & FLG_SY_ELIM) &&
1347141040e8Srie 	    (ofl->ofl_flags & FLG_OF_PROCRED)))) {
1348141040e8Srie 		/*
1349141040e8Srie 		 * But if this is PIC code, don't allow it for now.
1350141040e8Srie 		 */
1351141040e8Srie 		if (IS_GOT_RELATIVE(rsp->rel_rtype)) {
1352141040e8Srie 			Ifl_desc	*ifl = rsp->rel_isdesc->is_file;
1353de777a60Sab196087 			Conv_inv_buf_t inv_buf;
1354141040e8Srie 
1355*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_PICREDLOC),
1356bf994817SAli Bahrami 			    ld_reloc_sym_name(rsp), ifl->ifl_name,
13575aefb655Srie 			    conv_reloc_type(ifl->ifl_ehdr->e_machine,
1358de777a60Sab196087 			    rsp->rel_rtype, 0, &inv_buf));
1359141040e8Srie 			return (S_ERROR);
1360141040e8Srie 		}
1361141040e8Srie 
1362141040e8Srie 		/*
1363141040e8Srie 		 * Indicate that this relocation should be processed the same
1364ba2be530Sab196087 		 * as a section symbol.  For RELA, indicate that the addend
1365ba2be530Sab196087 		 * also needs to be applied to this relocation.
1366141040e8Srie 		 */
1367ba2be530Sab196087 		if ((rsp->rel_flags & FLG_REL_RELA) == FLG_REL_RELA)
1368141040e8Srie 			oflags = FLG_REL_SCNNDX | FLG_REL_ADVAL;
1369ba2be530Sab196087 		else
1370ba2be530Sab196087 			oflags = FLG_REL_SCNNDX;
1371141040e8Srie 	}
1372141040e8Srie 
1373ba2be530Sab196087 	if ((rsp->rel_flags & FLG_REL_RELA) == 0) {
1374141040e8Srie 		/*
1375ba2be530Sab196087 		 * Intel (Rel) relocations do not contain an addend.  Any
1376ba2be530Sab196087 		 * addend is contained within the file at the location
1377ba2be530Sab196087 		 * identified by the relocation offset.  Therefore, if we're
1378ba2be530Sab196087 		 * processing a section symbol, or a -zredlocsym relocation
1379ba2be530Sab196087 		 * (that basically transforms a local symbol reference into
1380ba2be530Sab196087 		 * a section reference), perform an active relocation to
1381141040e8Srie 		 * propagate any addend.
1382141040e8Srie 		 */
1383141040e8Srie 		if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) ||
1384141040e8Srie 		    (oflags == FLG_REL_SCNNDX))
13855aefb655Srie 			if (ld_add_actrel(NULL, rsp, ofl) == S_ERROR)
1386141040e8Srie 				return (S_ERROR);
1387ba2be530Sab196087 	}
1388ba2be530Sab196087 	return ((*ld_targ.t_mr.mr_add_outrel)(oflags, rsp, ofl));
1389141040e8Srie }
13907c478bd9Sstevel@tonic-gate 
1391d326b23bSrie /*
1392d326b23bSrie  * Perform any generic TLS validations before passing control to machine
1393d326b23bSrie  * specific routines.  At this point we know we are dealing with an executable
1394d326b23bSrie  * or shared object - relocatable objects have already been processed.
1395d326b23bSrie  */
1396d326b23bSrie static uintptr_t
reloc_TLS(Boolean local,Rel_desc * rsp,Ofl_desc * ofl)1397d326b23bSrie reloc_TLS(Boolean local, Rel_desc *rsp, Ofl_desc *ofl)
1398d326b23bSrie {
13991d9df23bSab196087 	Word		rtype = rsp->rel_rtype;
14001d9df23bSab196087 	ofl_flag_t	flags = ofl->ofl_flags;
1401d326b23bSrie 	Ifl_desc	*ifl = rsp->rel_isdesc->is_file;
1402d326b23bSrie 	Half		mach = ifl->ifl_ehdr->e_machine;
1403d326b23bSrie 	Sym_desc	*sdp = rsp->rel_sym;
1404d326b23bSrie 	unsigned char	type;
1405de777a60Sab196087 	Conv_inv_buf_t	inv_buf1, inv_buf2;
1406d326b23bSrie 
1407d326b23bSrie 	/*
1408d326b23bSrie 	 * All TLS relocations are illegal in a static executable.
1409d326b23bSrie 	 */
1410635216b6SRod Evans 	if (OFL_IS_STATIC_EXEC(ofl)) {
1411*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_TLSSTAT),
1412de777a60Sab196087 		    conv_reloc_type(mach, rtype, 0, &inv_buf1), ifl->ifl_name,
1413bf994817SAli Bahrami 		    ld_reloc_sym_name(rsp));
1414d326b23bSrie 		return (S_ERROR);
1415d326b23bSrie 	}
1416d326b23bSrie 
1417d326b23bSrie 	/*
1418d326b23bSrie 	 * Any TLS relocation must be against a STT_TLS symbol, all others
1419d326b23bSrie 	 * are illegal.
1420d326b23bSrie 	 */
1421d326b23bSrie 	if ((type = ELF_ST_TYPE(sdp->sd_sym->st_info)) != STT_TLS) {
1422*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_TLSBADSYM),
1423de777a60Sab196087 		    conv_reloc_type(mach, rtype, 0, &inv_buf1), ifl->ifl_name,
1424bf994817SAli Bahrami 		    ld_reloc_sym_name(rsp),
1425de777a60Sab196087 		    conv_sym_info_type(mach, type, 0, &inv_buf2));
1426d326b23bSrie 		return (S_ERROR);
1427d326b23bSrie 	}
1428d326b23bSrie 
1429d326b23bSrie 	/*
1430d326b23bSrie 	 * A dynamic executable can not use the LD or LE reference models to
1431d326b23bSrie 	 * reference an external symbol.  A shared object can not use the LD
1432d326b23bSrie 	 * reference model to reference an external symbol.
1433d326b23bSrie 	 */
1434d326b23bSrie 	if (!local && (IS_TLS_LD(rtype) ||
1435d326b23bSrie 	    ((flags & FLG_OF_EXEC) && IS_TLS_LE(rtype)))) {
1436*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_TLSBND),
1437de777a60Sab196087 		    conv_reloc_type(mach, rtype, 0, &inv_buf1), ifl->ifl_name,
1438bf994817SAli Bahrami 		    ld_reloc_sym_name(rsp), sdp->sd_file->ifl_name);
1439d326b23bSrie 		return (S_ERROR);
1440d326b23bSrie 	}
1441d326b23bSrie 
1442d326b23bSrie 	/*
1443d326b23bSrie 	 * The TLS LE model is only allowed for dynamic executables.  The TLS IE
1444d326b23bSrie 	 * model is allowed for shared objects, but this model has restrictions.
1445d326b23bSrie 	 * This model can only be used freely in dependencies that are loaded
1446d326b23bSrie 	 * immediately as part of process initialization.  However, during the
1447d326b23bSrie 	 * initial runtime handshake with libc that establishes the thread
1448d326b23bSrie 	 * pointer, a small backup TLS reservation is created.  This area can
1449d326b23bSrie 	 * be used by objects that are loaded after threads are initialized.
1450d326b23bSrie 	 * However, this area is limited in size and may have already been
1451d326b23bSrie 	 * used.  This area is intended for specialized applications, and does
1452d326b23bSrie 	 * not provide the degree of flexibility dynamic TLS can offer.  Under
1453d326b23bSrie 	 * -z verbose indicate this restriction to the user.
1454d326b23bSrie 	 */
1455d326b23bSrie 	if ((flags & FLG_OF_EXEC) == 0) {
1456d326b23bSrie 		if (IS_TLS_LE(rtype)) {
1457*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_TLSLE),
1458de777a60Sab196087 			    conv_reloc_type(mach, rtype, 0, &inv_buf1),
1459bf994817SAli Bahrami 			    ifl->ifl_name, ld_reloc_sym_name(rsp));
1460d326b23bSrie 			return (S_ERROR);
1461d326b23bSrie 
1462ba2be530Sab196087 		} else if ((IS_TLS_IE(rtype)) &&
1463ba2be530Sab196087 		    (flags & FLG_OF_VERBOSE)) {
1464*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_TLSIE),
1465de777a60Sab196087 			    conv_reloc_type(mach, rtype, 0, &inv_buf1),
1466bf994817SAli Bahrami 			    ifl->ifl_name, ld_reloc_sym_name(rsp));
1467d326b23bSrie 		}
1468d326b23bSrie 	}
1469d326b23bSrie 
1470ba2be530Sab196087 	return ((*ld_targ.t_mr.mr_reloc_TLS)(local, rsp, ofl));
1471d326b23bSrie }
1472d326b23bSrie 
14737c478bd9Sstevel@tonic-gate uintptr_t
ld_process_sym_reloc(Ofl_desc * ofl,Rel_desc * reld,Rel * reloc,Is_desc * isp,const char * isname,Word isscnndx)14745aefb655Srie ld_process_sym_reloc(Ofl_desc *ofl, Rel_desc *reld, Rel *reloc, Is_desc *isp,
1475e23c41c9SAli Bahrami     const char *isname, Word isscnndx)
14767c478bd9Sstevel@tonic-gate {
14777c478bd9Sstevel@tonic-gate 	Word		rtype = reld->rel_rtype;
14781d9df23bSab196087 	ofl_flag_t	flags = ofl->ofl_flags;
14797c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp = reld->rel_sym;
14807c478bd9Sstevel@tonic-gate 	Sym_aux		*sap;
14817c478bd9Sstevel@tonic-gate 	Boolean		local;
1482de777a60Sab196087 	Conv_inv_buf_t	inv_buf;
14837c478bd9Sstevel@tonic-gate 
1484ba2be530Sab196087 	DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD, ld_targ.t_m.m_mach,
1485e23c41c9SAli Bahrami 	    ld_targ.t_m.m_rel_sht_type, (void *)reloc, isname, isscnndx,
1486bf994817SAli Bahrami 	    ld_reloc_sym_name(reld)));
14877c478bd9Sstevel@tonic-gate 
14887c478bd9Sstevel@tonic-gate 	/*
14897c478bd9Sstevel@tonic-gate 	 * Indicate this symbol is being used for relocation and therefore must
14907c478bd9Sstevel@tonic-gate 	 * have its output address updated accordingly (refer to update_osym()).
14917c478bd9Sstevel@tonic-gate 	 */
14927c478bd9Sstevel@tonic-gate 	sdp->sd_flags |= FLG_SY_UPREQD;
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 	/*
14957c478bd9Sstevel@tonic-gate 	 * Indicate the section this symbol is defined in has been referenced,
14967c478bd9Sstevel@tonic-gate 	 * therefor it *is not* a candidate for elimination.
14977c478bd9Sstevel@tonic-gate 	 */
14987c478bd9Sstevel@tonic-gate 	if (sdp->sd_isc) {
14997c478bd9Sstevel@tonic-gate 		sdp->sd_isc->is_flags |= FLG_IS_SECTREF;
15007c478bd9Sstevel@tonic-gate 		sdp->sd_isc->is_file->ifl_flags |= FLG_IF_FILEREF;
15017c478bd9Sstevel@tonic-gate 	}
15027c478bd9Sstevel@tonic-gate 
1503bf994817SAli Bahrami 	if (!ld_reloc_set_aux_usym(ofl, reld, sdp))
1504bf994817SAli Bahrami 		return (S_ERROR);
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 	/*
15077c478bd9Sstevel@tonic-gate 	 * Determine if this symbol is actually an alias to another symbol.  If
1508bf994817SAli Bahrami 	 * so, and the alias is not REF_DYN_SEEN, set ra_usym to point to the
15097c478bd9Sstevel@tonic-gate 	 * weak symbols strong counter-part.  The one exception is if the
15107c478bd9Sstevel@tonic-gate 	 * FLG_SY_MVTOCOMM flag is set on the weak symbol.  If this is the case,
15117c478bd9Sstevel@tonic-gate 	 * the strong is only here because of its promotion, and the weak symbol
15127c478bd9Sstevel@tonic-gate 	 * should still be used for the relocation reference (see reloc_exec()).
15137c478bd9Sstevel@tonic-gate 	 */
15147c478bd9Sstevel@tonic-gate 	sap = sdp->sd_aux;
15157c478bd9Sstevel@tonic-gate 	if (sap && sap->sa_linkndx &&
15167c478bd9Sstevel@tonic-gate 	    ((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_WEAK) ||
15177c478bd9Sstevel@tonic-gate 	    (sdp->sd_flags & FLG_SY_WEAKDEF)) &&
15187c478bd9Sstevel@tonic-gate 	    (!(sdp->sd_flags & FLG_SY_MVTOCOMM))) {
15197c478bd9Sstevel@tonic-gate 		Sym_desc	*_sdp;
15207c478bd9Sstevel@tonic-gate 
15217c478bd9Sstevel@tonic-gate 		_sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx];
1522bf994817SAli Bahrami 		if ((_sdp->sd_ref != REF_DYN_SEEN) &&
1523bf994817SAli Bahrami 		    !ld_reloc_set_aux_usym(ofl, reld, _sdp))
1524bf994817SAli Bahrami 			return (S_ERROR);
15257c478bd9Sstevel@tonic-gate 	}
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate 	/*
15287c478bd9Sstevel@tonic-gate 	 * Determine whether this symbol should be bound locally or not.
15299a411307Srie 	 * Symbols are bound locally if one of the following is true:
15307c478bd9Sstevel@tonic-gate 	 *
1531635216b6SRod Evans 	 *  -	the symbol is of type STB_LOCAL.
15327c478bd9Sstevel@tonic-gate 	 *
1533635216b6SRod Evans 	 *  -	the output image is not a relocatable object and the relocation
15349a411307Srie 	 *	is relative to the .got.
15357c478bd9Sstevel@tonic-gate 	 *
1536635216b6SRod Evans 	 *  -	the section being relocated is of type SHT_SUNW_dof.  These
15379a411307Srie 	 *	sections must be bound to the functions in the containing
15389a411307Srie 	 *	object and can not be interposed upon.
15397c478bd9Sstevel@tonic-gate 	 *
1540635216b6SRod Evans 	 *  -	the symbol has been reduced (scoped to a local or symbolic) and
15419a411307Srie 	 *	reductions are being processed.
15427c478bd9Sstevel@tonic-gate 	 *
1543635216b6SRod Evans 	 *  -	the -Bsymbolic flag is in use when building a shared object,
15449a411307Srie 	 *	and the symbol hasn't explicitly been defined as nodirect.
15457c478bd9Sstevel@tonic-gate 	 *
1546635216b6SRod Evans 	 *  -	an executable (fixed address) is being created, and the symbol
15479a411307Srie 	 *	is defined in the executable.
15487c478bd9Sstevel@tonic-gate 	 *
1549635216b6SRod Evans 	 *  -	the relocation is against a segment which will not be loaded
15509a411307Srie 	 *	into memory.  In this case, the relocation must be resolved
15519a411307Srie 	 *	now, as ld.so.1 can not process relocations against unmapped
15529a411307Srie 	 *	segments.
15537c478bd9Sstevel@tonic-gate 	 */
15547c478bd9Sstevel@tonic-gate 	local = FALSE;
15557c478bd9Sstevel@tonic-gate 	if (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) {
15567c478bd9Sstevel@tonic-gate 		local = TRUE;
15577c478bd9Sstevel@tonic-gate 	} else if (!(reld->rel_flags & FLG_REL_LOAD)) {
15587c478bd9Sstevel@tonic-gate 		local = TRUE;
15590bc07c75Srie 	} else if (sdp->sd_sym->st_shndx != SHN_UNDEF) {
15607c478bd9Sstevel@tonic-gate 		if (reld->rel_isdesc &&
15617c478bd9Sstevel@tonic-gate 		    reld->rel_isdesc->is_shdr->sh_type == SHT_SUNW_dof) {
15627c478bd9Sstevel@tonic-gate 			local = TRUE;
15637c478bd9Sstevel@tonic-gate 		} else if (!(flags & FLG_OF_RELOBJ) &&
1564635216b6SRod Evans 		    (IS_LOCALBND(rtype) || IS_SEG_RELATIVE(rtype))) {
15657c478bd9Sstevel@tonic-gate 			local = TRUE;
156608278a5eSRod Evans 		} else if ((sdp->sd_ref == REF_REL_NEED) &&
156708278a5eSRod Evans 		    ((sdp->sd_flags & FLG_SY_CAP) == 0)) {
15689a411307Srie 			/*
15699a411307Srie 			 * Global symbols may have been individually reduced in
15709a411307Srie 			 * scope.  If the whole object is to be self contained,
15719a411307Srie 			 * such as when generating an executable or a symbolic
15729a411307Srie 			 * shared object, make sure all relocation symbol
15739a411307Srie 			 * references (sections too) are treated locally.  Note,
15749a411307Srie 			 * explicit no-direct symbols should not be bound to
15759a411307Srie 			 * locally.
15769a411307Srie 			 */
1577635216b6SRod Evans 			if ((sdp->sd_flags &
1578635216b6SRod Evans 			    (FLG_SY_HIDDEN | FLG_SY_PROTECT)))
15797c478bd9Sstevel@tonic-gate 				local = TRUE;
15809a411307Srie 			else if ((flags & FLG_OF_EXEC) ||
15819a411307Srie 			    ((flags & FLG_OF_SYMBOLIC) &&
1582635216b6SRod Evans 			    ((sdp->sd_flags & FLG_SY_NDIR) == 0))) {
15837c478bd9Sstevel@tonic-gate 				local = TRUE;
15847c478bd9Sstevel@tonic-gate 			}
15857c478bd9Sstevel@tonic-gate 		}
1586635216b6SRod Evans 	}
15877c478bd9Sstevel@tonic-gate 
15887c478bd9Sstevel@tonic-gate 	/*
15897c478bd9Sstevel@tonic-gate 	 * If this is a PC_RELATIVE relocation, the relocation could be
15907c478bd9Sstevel@tonic-gate 	 * compromised if the relocated address is later used as a copy
15917c478bd9Sstevel@tonic-gate 	 * relocated symbol (PSARC 1999/636, bugid 4187211).  Scan the input
15927c478bd9Sstevel@tonic-gate 	 * files symbol table to cross reference this relocation offset.
15937c478bd9Sstevel@tonic-gate 	 */
1594ba2be530Sab196087 	if ((ofl->ofl_flags & FLG_OF_SHAROBJ) &&
1595ba2be530Sab196087 	    IS_PC_RELATIVE(rtype) &&
1596ba2be530Sab196087 	    (IS_GOT_PC(rtype) == 0) &&
1597ba2be530Sab196087 	    (IS_PLT(rtype) == 0)) {
15987c478bd9Sstevel@tonic-gate 		if (disp_inspect(ofl, reld, local) == S_ERROR)
15997c478bd9Sstevel@tonic-gate 			return (S_ERROR);
16007c478bd9Sstevel@tonic-gate 	}
16017c478bd9Sstevel@tonic-gate 
16027c478bd9Sstevel@tonic-gate 	/*
16037c478bd9Sstevel@tonic-gate 	 * GOT based relocations must bind to the object being built - since
16047c478bd9Sstevel@tonic-gate 	 * they are relevant to the current GOT.  If not building a relocatable
16057c478bd9Sstevel@tonic-gate 	 * object - give a appropriate error message.
16067c478bd9Sstevel@tonic-gate 	 */
1607ba2be530Sab196087 	if (!local && !(flags & FLG_OF_RELOBJ) &&
1608ba2be530Sab196087 	    IS_GOT_BASED(rtype)) {
16095aefb655Srie 		Ifl_desc	*ifl = reld->rel_isdesc->is_file;
16105aefb655Srie 
1611*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_BADGOTBASED),
1612de777a60Sab196087 		    conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype,
1613de777a60Sab196087 		    0, &inv_buf), ifl->ifl_name, demangle(sdp->sd_name));
16147c478bd9Sstevel@tonic-gate 		return (S_ERROR);
16157c478bd9Sstevel@tonic-gate 	}
16167c478bd9Sstevel@tonic-gate 
16177c478bd9Sstevel@tonic-gate 	/*
16187c478bd9Sstevel@tonic-gate 	 * TLS symbols can only have TLS relocations.
16197c478bd9Sstevel@tonic-gate 	 */
1620d326b23bSrie 	if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_TLS) &&
1621d326b23bSrie 	    (IS_TLS_INS(rtype) == 0)) {
16227c478bd9Sstevel@tonic-gate 		/*
16237c478bd9Sstevel@tonic-gate 		 * The above test is relaxed if the target section is
16247c478bd9Sstevel@tonic-gate 		 * non-allocable.
16257c478bd9Sstevel@tonic-gate 		 */
1626bf994817SAli Bahrami 		if (RELAUX_GET_OSDESC(reld)->os_shdr->sh_flags & SHF_ALLOC) {
16275aefb655Srie 			Ifl_desc	*ifl = reld->rel_isdesc->is_file;
16285aefb655Srie 
1629*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_BADTLS),
1630c13de8f6Sab196087 			    conv_reloc_type(ifl->ifl_ehdr->e_machine,
1631de777a60Sab196087 			    rtype, 0, &inv_buf), ifl->ifl_name,
1632de777a60Sab196087 			    demangle(sdp->sd_name));
16337c478bd9Sstevel@tonic-gate 			return (S_ERROR);
16347c478bd9Sstevel@tonic-gate 		}
16357c478bd9Sstevel@tonic-gate 	}
16367c478bd9Sstevel@tonic-gate 
16377c478bd9Sstevel@tonic-gate 	/*
16387c478bd9Sstevel@tonic-gate 	 * Select the relocation to perform.
16397c478bd9Sstevel@tonic-gate 	 */
1640ba2be530Sab196087 	if (IS_REGISTER(rtype)) {
1641ba2be530Sab196087 		if (ld_targ.t_mr.mr_reloc_register == NULL) {
1642*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_NOREG));
1643ba2be530Sab196087 			return (S_ERROR);
1644ba2be530Sab196087 		}
1645ba2be530Sab196087 		return ((*ld_targ.t_mr.mr_reloc_register)(reld, isp, ofl));
1646ba2be530Sab196087 	}
16477c478bd9Sstevel@tonic-gate 
16487c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_RELOBJ)
16497c478bd9Sstevel@tonic-gate 		return (reloc_relobj(local, reld, ofl));
16507c478bd9Sstevel@tonic-gate 
16517c478bd9Sstevel@tonic-gate 	if (IS_TLS_INS(rtype))
1652d326b23bSrie 		return (reloc_TLS(local, reld, ofl));
16537c478bd9Sstevel@tonic-gate 
1654ba2be530Sab196087 	if (IS_GOT_OPINS(rtype)) {
1655ba2be530Sab196087 		if (ld_targ.t_mr.mr_reloc_GOTOP == NULL) {
1656ba2be530Sab196087 			assert(0);
1657ba2be530Sab196087 			return (S_ERROR);
1658ba2be530Sab196087 		}
1659ba2be530Sab196087 		return ((*ld_targ.t_mr.mr_reloc_GOTOP)(local, reld, ofl));
1660ba2be530Sab196087 	}
16617c478bd9Sstevel@tonic-gate 
16627c478bd9Sstevel@tonic-gate 	if (IS_GOT_RELATIVE(rtype))
16635aefb655Srie 		return (ld_reloc_GOT_relative(local, reld, ofl));
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate 	if (local)
1666ba2be530Sab196087 		return ((*ld_targ.t_mr.mr_reloc_local)(reld, ofl));
16677c478bd9Sstevel@tonic-gate 
166808278a5eSRod Evans 	if ((IS_PLT(rtype) || ((sdp->sd_flags & FLG_SY_CAP) &&
166908278a5eSRod Evans 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_FUNC))) &&
167008278a5eSRod Evans 	    ((flags & FLG_OF_BFLAG) == 0))
16715aefb655Srie 		return (ld_reloc_plt(reld, ofl));
16727c478bd9Sstevel@tonic-gate 
16737c478bd9Sstevel@tonic-gate 	if ((sdp->sd_ref == REF_REL_NEED) ||
16747c478bd9Sstevel@tonic-gate 	    (flags & FLG_OF_BFLAG) || (flags & FLG_OF_SHAROBJ) ||
16757c478bd9Sstevel@tonic-gate 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_NOTYPE))
1676ba2be530Sab196087 		return ((*ld_targ.t_mr.mr_add_outrel)(NULL, reld, ofl));
16777c478bd9Sstevel@tonic-gate 
16787c478bd9Sstevel@tonic-gate 	if (sdp->sd_ref == REF_DYN_NEED)
16797c478bd9Sstevel@tonic-gate 		return (reloc_exec(reld, ofl));
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 	/*
16827c478bd9Sstevel@tonic-gate 	 * IS_NOT_REL(rtype)
16837c478bd9Sstevel@tonic-gate 	 */
16847c478bd9Sstevel@tonic-gate 	return (reloc_generic(reld, ofl));
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate 
16877c478bd9Sstevel@tonic-gate /*
16880e233487SRod Evans  * Given a relocation that references a local symbol from a discarded COMDAT
16890e233487SRod Evans  * section, replace the symbol with the corresponding symbol from the section
16900e233487SRod Evans  * that was kept.
1691d2ef9fe9Sab196087  *
1692d2ef9fe9Sab196087  * entry:
1693d2ef9fe9Sab196087  *	reld - Relocation
16946b3ba5bdSAli Bahrami  *	sdp - Symbol to be replaced. Must be a local symbol (STB_LOCAL).
169540e53e87SAli Bahrami  *	reject - Address of variable to receive rejection code
169640e53e87SAli Bahrami  *		if no replacement symbol is found.
1697d2ef9fe9Sab196087  *
1698d2ef9fe9Sab196087  * exit:
1699d2ef9fe9Sab196087  *	Returns address of replacement symbol descriptor if one was
17006b3ba5bdSAli Bahrami  *	found, and NULL otherwise. The result is also cached in
17016b3ba5bdSAli Bahrami  *	ofl->ofl_sr_cache as an optimization to speed following calls
17026b3ba5bdSAli Bahrami  *	for the same value of sdp.
1703d2ef9fe9Sab196087  *
170440e53e87SAli Bahrami  *	On success (non-NULL result), *reject is set to RLXREL_REJ_NONE.
170540e53e87SAli Bahrami  *	On failure (NULL result), *reject is filled in with a code
170640e53e87SAli Bahrami  *	describing the underlying reason.
170740e53e87SAli Bahrami  *
1708d2ef9fe9Sab196087  * note:
17090e233487SRod Evans  *	The word "COMDAT" is used to refer to actual COMDAT sections, COMDAT
17100e233487SRod Evans  *	groups tied together with an SHF_GROUP section, and .gnu.linkonce
17110e233487SRod Evans  *	sections which provide a simplified COMDAT requirement.  COMDAT
17120e233487SRod Evans  *	sections are identified with the FLG_IS_COMDAT section flag.
1713d2ef9fe9Sab196087  *
1714d2ef9fe9Sab196087  *	In principle, this sort of sloppy relocation remapping is
1715d2ef9fe9Sab196087  *	a questionable practice. All self-referential sections should
1716d2ef9fe9Sab196087  *	be in a common SHF_GROUP so that they are all kept or removed
1717d2ef9fe9Sab196087  *	together. The problem is that there is no way to ensure that the
1718d2ef9fe9Sab196087  *	two sections are similar enough that the replacement section will
1719d2ef9fe9Sab196087  *	really supply the correct information. However, we see a couple of
1720d2ef9fe9Sab196087  *	situations where it is useful to do this: (1) Older Sun C compilers
1721d2ef9fe9Sab196087  *	generated DWARF sections that would refer to one of the COMDAT
17226b3ba5bdSAli Bahrami  *	sections, and (2) gcc, when its GNU linkonce COMDAT feature is enabled.
1723d2ef9fe9Sab196087  *	It turns out that the GNU ld does these sloppy remappings.
1724d2ef9fe9Sab196087  *
1725d2ef9fe9Sab196087  *	The GNU ld takes an approach that hard wires special section
1726d2ef9fe9Sab196087  *	names and treats them specially. We avoid that practice and
1727d2ef9fe9Sab196087  *	try to get the necessary work done relying only on the ELF
1728d2ef9fe9Sab196087  *	attributes of the sections and symbols involved. This means
1729d2ef9fe9Sab196087  *	that our heuristic is somewhat different than theirs, but the
1730d2ef9fe9Sab196087  *	end result is close enough to solve the same problem.
1731d2ef9fe9Sab196087  *
17326b3ba5bdSAli Bahrami  *	gcc is in the process of converting to SHF_GROUP. This will
17336b3ba5bdSAli Bahrami  *	eventually phase out the need for sloppy relocations, and
17340e233487SRod Evans  *	then this logic won't be needed. In the meantime, relaxed relocation
17350e233487SRod Evans  *	processing allows us to interoperate.
1736d2ef9fe9Sab196087  */
1737d2ef9fe9Sab196087 static Sym_desc *
sloppy_comdat_reloc(Ofl_desc * ofl,Rel_desc * reld,Sym_desc * sdp,Rlxrel_rej * reject)173840e53e87SAli Bahrami sloppy_comdat_reloc(Ofl_desc *ofl, Rel_desc *reld, Sym_desc *sdp,
173940e53e87SAli Bahrami     Rlxrel_rej *reject)
1740d2ef9fe9Sab196087 {
1741d2ef9fe9Sab196087 	Is_desc		*rep_isp;
17426b3ba5bdSAli Bahrami 	Sym		*sym, *rep_sym;
17436b3ba5bdSAli Bahrami 	Is_desc		*isp;
17446b3ba5bdSAli Bahrami 	Ifl_desc	*ifl;
1745de777a60Sab196087 	Conv_inv_buf_t	inv_buf;
17466b3ba5bdSAli Bahrami 	Word		scnndx, symscnt;
17476b3ba5bdSAli Bahrami 	Sym_desc	**oldndx, *rep_sdp;
174840e53e87SAli Bahrami 	const char	*is_name;
174940e53e87SAli Bahrami 
175040e53e87SAli Bahrami 
175140e53e87SAli Bahrami 	/*
175240e53e87SAli Bahrami 	 * Sloppy relocations are never applied to .eh_frame or
175340e53e87SAli Bahrami 	 * .gcc_except_table sections. The entries in these sections
175440e53e87SAli Bahrami 	 * for discarded sections are better left uninitialized.
175540e53e87SAli Bahrami 	 *
175640e53e87SAli Bahrami 	 * We match these sections by name, because on most platforms they
175740e53e87SAli Bahrami 	 * are SHT_PROGBITS, and cannot be identified otherwise. On amd64
175840e53e87SAli Bahrami 	 * architectures, .eh_frame is SHT_AMD64_UNWIND, but that is ambiguous
175940e53e87SAli Bahrami 	 * (.eh_frame_hdr is also SHT_AMD64_UNWIND), so we still match it by
176040e53e87SAli Bahrami 	 * name.
176140e53e87SAli Bahrami 	 */
176240e53e87SAli Bahrami 	is_name = reld->rel_isdesc->is_name;
176340e53e87SAli Bahrami 	if (((is_name[1] == 'e') &&
176440e53e87SAli Bahrami 	    (strcmp(is_name, MSG_ORIG(MSG_SCN_EHFRAME)) == 0)) ||
176540e53e87SAli Bahrami 	    ((is_name[1] == 'g') &&
176640e53e87SAli Bahrami 	    (strcmp(is_name, MSG_ORIG(MSG_SCN_GCC_X_TBL)) == 0))) {
176740e53e87SAli Bahrami 		*reject = RLXREL_REJ_TARGET;
176840e53e87SAli Bahrami 		return (NULL);
176940e53e87SAli Bahrami 	}
1770d2ef9fe9Sab196087 
1771d2ef9fe9Sab196087 	/*
17726b3ba5bdSAli Bahrami 	 * If we looked up the same symbol on the previous call, we can
17736b3ba5bdSAli Bahrami 	 * return the cached value.
17746b3ba5bdSAli Bahrami 	 */
177540e53e87SAli Bahrami 	if (sdp == ofl->ofl_sr_cache.sr_osdp) {
177640e53e87SAli Bahrami 		*reject = ofl->ofl_sr_cache.sr_rej;
17776b3ba5bdSAli Bahrami 		return (ofl->ofl_sr_cache.sr_rsdp);
177840e53e87SAli Bahrami 	}
17796b3ba5bdSAli Bahrami 
17806b3ba5bdSAli Bahrami 	ofl->ofl_sr_cache.sr_osdp = sdp;
17816b3ba5bdSAli Bahrami 	sym = sdp->sd_sym;
17826b3ba5bdSAli Bahrami 	isp = sdp->sd_isc;
17836b3ba5bdSAli Bahrami 	ifl = sdp->sd_file;
17846b3ba5bdSAli Bahrami 
17856b3ba5bdSAli Bahrami 	/*
17866b3ba5bdSAli Bahrami 	 * When a COMDAT section is discarded in favor of another COMDAT
17876b3ba5bdSAli Bahrami 	 * section, the replacement is recorded in its section descriptor
17886b3ba5bdSAli Bahrami 	 * (is_comdatkeep). We must validate the replacement before using
17896b3ba5bdSAli Bahrami 	 * it. The replacement section must:
1790d2ef9fe9Sab196087 	 *	- Not have been discarded
1791ca4eed8bSAli Bahrami 	 *	- Have the same size (*)
17920e233487SRod Evans 	 *	- Have the same section type
1793d2ef9fe9Sab196087 	 *	- Have the same SHF_GROUP flag setting (either on or off)
1794d2ef9fe9Sab196087 	 *	- Must be a COMDAT section of one form or the other.
1795ca4eed8bSAli Bahrami 	 *
1796ca4eed8bSAli Bahrami 	 * (*) One might imagine that the replacement section could be
1797ca4eed8bSAli Bahrami 	 * larger than the original, rather than the exact size. However,
1798ca4eed8bSAli Bahrami 	 * we have verified that this is the same policy used by the GNU
1799ca4eed8bSAli Bahrami 	 * ld. If the sections are not the same size, the chance of them
1800ca4eed8bSAli Bahrami 	 * being interchangeable drops significantly.
1801d2ef9fe9Sab196087 	 */
18026b3ba5bdSAli Bahrami 	if (((rep_isp = isp->is_comdatkeep) == NULL) ||
18036b3ba5bdSAli Bahrami 	    ((rep_isp->is_flags & FLG_IS_DISCARD) != 0) ||
18046b3ba5bdSAli Bahrami 	    ((rep_isp->is_flags & FLG_IS_COMDAT) == 0) ||
18056b3ba5bdSAli Bahrami 	    (isp->is_indata->d_size != rep_isp->is_indata->d_size) ||
18066b3ba5bdSAli Bahrami 	    (isp->is_shdr->sh_type != rep_isp->is_shdr->sh_type) ||
18076b3ba5bdSAli Bahrami 	    ((isp->is_shdr->sh_flags & SHF_GROUP) !=
180840e53e87SAli Bahrami 	    (rep_isp->is_shdr->sh_flags & SHF_GROUP))) {
180940e53e87SAli Bahrami 		*reject = ofl->ofl_sr_cache.sr_rej = RLXREL_REJ_SECTION;
18106b3ba5bdSAli Bahrami 		return (ofl->ofl_sr_cache.sr_rsdp = NULL);
181140e53e87SAli Bahrami 	}
1812d2ef9fe9Sab196087 
1813d2ef9fe9Sab196087 	/*
1814d2ef9fe9Sab196087 	 * We found the kept COMDAT section. Now, look at all of the
1815d2ef9fe9Sab196087 	 * symbols from the input file that contains it to find the
1816d2ef9fe9Sab196087 	 * symbol that corresponds to the one we started with:
1817d2ef9fe9Sab196087 	 *	- Hasn't been discarded
1818d2ef9fe9Sab196087 	 *	- Has section index of kept section
1819d2ef9fe9Sab196087 	 *	- If one symbol has a name, the other must have
1820d2ef9fe9Sab196087 	 *		the same name. The st_name field of a symbol
1821d2ef9fe9Sab196087 	 *		is 0 if there is no name, and is a string
1822d2ef9fe9Sab196087 	 *		table offset otherwise. The string table
1823d2ef9fe9Sab196087 	 *		offsets may well not agree --- it is the
1824d2ef9fe9Sab196087 	 *		actual string that matters.
1825d2ef9fe9Sab196087 	 *	- Type and binding attributes match (st_info)
1826d2ef9fe9Sab196087 	 *	- Values match (st_value)
1827d2ef9fe9Sab196087 	 *	- Sizes match (st_size)
1828d2ef9fe9Sab196087 	 *	- Visibility matches (st_other)
1829d2ef9fe9Sab196087 	 */
18306b3ba5bdSAli Bahrami 	scnndx = rep_isp->is_scnndx;
18316b3ba5bdSAli Bahrami 	oldndx = rep_isp->is_file->ifl_oldndx;
18326b3ba5bdSAli Bahrami 	symscnt = rep_isp->is_file->ifl_symscnt;
1833d2ef9fe9Sab196087 	while (symscnt--) {
1834d2ef9fe9Sab196087 		rep_sdp = *oldndx++;
18356b3ba5bdSAli Bahrami 		if ((rep_sdp == NULL) || (rep_sdp->sd_flags & FLG_SY_ISDISC) ||
18366b3ba5bdSAli Bahrami 		    ((rep_sym = rep_sdp->sd_sym)->st_shndx != scnndx) ||
18376b3ba5bdSAli Bahrami 		    ((sym->st_name == 0) != (rep_sym->st_name == 0)) ||
18386b3ba5bdSAli Bahrami 		    ((sym->st_name != 0) &&
18396b3ba5bdSAli Bahrami 		    (strcmp(sdp->sd_name, rep_sdp->sd_name) != 0)) ||
18406b3ba5bdSAli Bahrami 		    (sym->st_info != rep_sym->st_info) ||
18416b3ba5bdSAli Bahrami 		    (sym->st_value != rep_sym->st_value) ||
18426b3ba5bdSAli Bahrami 		    (sym->st_size != rep_sym->st_size) ||
18436b3ba5bdSAli Bahrami 		    (sym->st_other != rep_sym->st_other))
18446b3ba5bdSAli Bahrami 			continue;
18456b3ba5bdSAli Bahrami 
1846d2ef9fe9Sab196087 
1847d2ef9fe9Sab196087 		if (ofl->ofl_flags & FLG_OF_VERBOSE) {
1848d2ef9fe9Sab196087 			if (sym->st_name != 0) {
1849*1007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_WARNING,
1850d2ef9fe9Sab196087 				    MSG_INTL(MSG_REL_SLOPCDATNAM),
1851d2ef9fe9Sab196087 				    conv_reloc_type(ifl->ifl_ehdr->e_machine,
1852de777a60Sab196087 				    reld->rel_rtype, 0, &inv_buf),
18534a8d0ea7SAli Bahrami 				    ifl->ifl_name,
18544a8d0ea7SAli Bahrami 				    EC_WORD(reld->rel_isdesc->is_scnndx),
18554a8d0ea7SAli Bahrami 				    reld->rel_isdesc->is_name,
18564a8d0ea7SAli Bahrami 				    rep_sdp->sd_name,
18574a8d0ea7SAli Bahrami 				    EC_WORD(isp->is_scnndx), isp->is_name,
1858d2ef9fe9Sab196087 				    rep_sdp->sd_file->ifl_name);
1859d2ef9fe9Sab196087 			} else {
1860*1007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_WARNING,
1861d2ef9fe9Sab196087 				    MSG_INTL(MSG_REL_SLOPCDATNONAM),
18626b3ba5bdSAli Bahrami 				    conv_reloc_type(ifl->ifl_ehdr->e_machine,
1863de777a60Sab196087 				    reld->rel_rtype, 0, &inv_buf),
18644a8d0ea7SAli Bahrami 				    ifl->ifl_name,
18654a8d0ea7SAli Bahrami 				    EC_WORD(reld->rel_isdesc->is_scnndx),
18664a8d0ea7SAli Bahrami 				    reld->rel_isdesc->is_name,
18674a8d0ea7SAli Bahrami 				    EC_WORD(isp->is_scnndx), isp->is_name,
18684a8d0ea7SAli Bahrami 				    rep_sdp->sd_file->ifl_name);
1869d2ef9fe9Sab196087 			}
1870d2ef9fe9Sab196087 		}
1871e23c41c9SAli Bahrami 		DBG_CALL(Dbg_reloc_sloppycomdat(ofl->ofl_lml, rep_sdp));
187240e53e87SAli Bahrami 		*reject = ofl->ofl_sr_cache.sr_rej = RLXREL_REJ_NONE;
18736b3ba5bdSAli Bahrami 		return (ofl->ofl_sr_cache.sr_rsdp = rep_sdp);
1874d2ef9fe9Sab196087 	}
1875d2ef9fe9Sab196087 
1876d2ef9fe9Sab196087 	/* If didn't return above, we didn't find it */
187740e53e87SAli Bahrami 	*reject = ofl->ofl_sr_cache.sr_rej = RLXREL_REJ_SYMBOL;
18786b3ba5bdSAli Bahrami 	return (ofl->ofl_sr_cache.sr_rsdp = NULL);
1879d2ef9fe9Sab196087 }
1880d2ef9fe9Sab196087 
1881cce0e03bSab196087 /*
18827c478bd9Sstevel@tonic-gate  * Generate relocation descriptor and dispatch
18837c478bd9Sstevel@tonic-gate  */
18847c478bd9Sstevel@tonic-gate static uintptr_t
process_reld(Ofl_desc * ofl,Is_desc * isp,Rel_desc * reld,Word rsndx,Rel * reloc)18857c478bd9Sstevel@tonic-gate process_reld(Ofl_desc *ofl, Is_desc *isp, Rel_desc *reld, Word rsndx,
18867c478bd9Sstevel@tonic-gate     Rel *reloc)
18877c478bd9Sstevel@tonic-gate {
18887c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl = isp->is_file;
18897c478bd9Sstevel@tonic-gate 	Word		rtype = reld->rel_rtype;
18907c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
1891de777a60Sab196087 	Conv_inv_buf_t	inv_buf;
18927c478bd9Sstevel@tonic-gate 
18937c478bd9Sstevel@tonic-gate 	/*
18947c478bd9Sstevel@tonic-gate 	 * Make sure the relocation is in the valid range.
18957c478bd9Sstevel@tonic-gate 	 */
1896ba2be530Sab196087 	if (rtype >= ld_targ.t_m.m_r_num) {
1897*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_INVALRELT),
18984a8d0ea7SAli Bahrami 		    ifl->ifl_name, EC_WORD(isp->is_scnndx), isp->is_name,
18994a8d0ea7SAli Bahrami 		    rtype);
19007c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19017c478bd9Sstevel@tonic-gate 	}
19027c478bd9Sstevel@tonic-gate 
1903c174926fSrie 	ofl->ofl_entrelscnt++;
1904c174926fSrie 
19057c478bd9Sstevel@tonic-gate 	/*
19067c478bd9Sstevel@tonic-gate 	 * Special case: a register symbol associated with symbol index 0 is
19077c478bd9Sstevel@tonic-gate 	 * initialized (i.e., relocated) to a constant from the r_addend field
19087c478bd9Sstevel@tonic-gate 	 * rather than from a symbol value.
19097c478bd9Sstevel@tonic-gate 	 */
19107c478bd9Sstevel@tonic-gate 	if (IS_REGISTER(rtype) && (rsndx == 0)) {
1911bf994817SAli Bahrami 		reld->rel_sym = NULL;
1912ba2be530Sab196087 		DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD,
1913ba2be530Sab196087 		    ld_targ.t_m.m_mach, isp->is_shdr->sh_type,
1914e23c41c9SAli Bahrami 		    (void *)reloc, isp->is_name, isp->is_scnndx,
1915bf994817SAli Bahrami 		    ld_reloc_sym_name(reld)));
1916ba2be530Sab196087 		if (ld_targ.t_mr.mr_reloc_register == NULL) {
1917*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_NOREG));
1918ba2be530Sab196087 			return (S_ERROR);
1919ba2be530Sab196087 		}
1920ba2be530Sab196087 		return ((*ld_targ.t_mr.mr_reloc_register)(reld, isp, ofl));
19217c478bd9Sstevel@tonic-gate 	}
19227c478bd9Sstevel@tonic-gate 
19237c478bd9Sstevel@tonic-gate 	/*
1924bf994817SAli Bahrami 	 * If this is a STT_SECTION symbol, make sure the associated
1925bf994817SAli Bahrami 	 * section has a descriptive non-NULL is_sym_name field that can
1926bf994817SAli Bahrami 	 * be accessed by ld_reloc_sym_name() to satisfy debugging output
1927bf994817SAli Bahrami 	 * and errors.
1928bf994817SAli Bahrami 	 *
1929bf994817SAli Bahrami 	 * In principle, we could add this string to every input section
1930bf994817SAli Bahrami 	 * as it is created, but we defer it until we see a relocation
1931bf994817SAli Bahrami 	 * symbol that might need it. Not every section will have such
1932bf994817SAli Bahrami 	 * a relocation, so we create fewer of them this way.
19337c478bd9Sstevel@tonic-gate 	 */
1934bf994817SAli Bahrami 	sdp = reld->rel_sym = ifl->ifl_oldndx[rsndx];
1935bf994817SAli Bahrami 	if ((sdp != NULL) &&
1936cce0e03bSab196087 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) &&
1937bf994817SAli Bahrami 	    (sdp->sd_isc != NULL) && (sdp->sd_isc->is_name != NULL) &&
1938bf994817SAli Bahrami 	    (sdp->sd_isc->is_sym_name == NULL) &&
1939bf994817SAli Bahrami 	    (ld_stt_section_sym_name(sdp->sd_isc) == NULL))
1940cce0e03bSab196087 		return (S_ERROR);
19417c478bd9Sstevel@tonic-gate 
19427c478bd9Sstevel@tonic-gate 	/*
19437c478bd9Sstevel@tonic-gate 	 * If for some reason we have a null relocation record issue a
19447c478bd9Sstevel@tonic-gate 	 * warning and continue (the compiler folks can get into this
19457c478bd9Sstevel@tonic-gate 	 * state some time).  Normal users should never see this error.
19467c478bd9Sstevel@tonic-gate 	 */
1947ba2be530Sab196087 	if (rtype == ld_targ.t_m.m_r_none) {
1948ba2be530Sab196087 		DBG_CALL(Dbg_reloc_in(ofl->ofl_lml, ELF_DBG_LD,
1949ba2be530Sab196087 		    ld_targ.t_m.m_mach, ld_targ.t_m.m_rel_sht_type,
1950e23c41c9SAli Bahrami 		    (void *)reloc, isp->is_name, isp->is_scnndx,
1951bf994817SAli Bahrami 		    ld_reloc_sym_name(reld)));
1952*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_NULL),
19534a8d0ea7SAli Bahrami 		    ifl->ifl_name, EC_WORD(isp->is_scnndx), isp->is_name);
19547c478bd9Sstevel@tonic-gate 		return (1);
19557c478bd9Sstevel@tonic-gate 	}
19567c478bd9Sstevel@tonic-gate 
1957ba2be530Sab196087 	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) &&
1958ba2be530Sab196087 	    IS_NOTSUP(rtype)) {
1959*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_NOTSUP),
1960de777a60Sab196087 		    conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype,
19614a8d0ea7SAli Bahrami 		    0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx),
19624a8d0ea7SAli Bahrami 		    isp->is_name);
19637c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19647c478bd9Sstevel@tonic-gate 	}
19657c478bd9Sstevel@tonic-gate 
19667c478bd9Sstevel@tonic-gate 	/*
19677c478bd9Sstevel@tonic-gate 	 * If we are here, we know that the relocation requires reference
19687c478bd9Sstevel@tonic-gate 	 * symbol. If no symbol is assigned, this is a fatal error.
19697c478bd9Sstevel@tonic-gate 	 */
19707c478bd9Sstevel@tonic-gate 	if (sdp == NULL) {
1971*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_NOSYMBOL),
1972de777a60Sab196087 		    conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype,
19734a8d0ea7SAli Bahrami 		    0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx),
19744a8d0ea7SAli Bahrami 		    isp->is_name, EC_XWORD(reloc->r_offset));
19757c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19767c478bd9Sstevel@tonic-gate 	}
19777c478bd9Sstevel@tonic-gate 
1978635216b6SRod Evans 	if (sdp->sd_flags & FLG_SY_IGNORE)
19797c478bd9Sstevel@tonic-gate 		return (1);
19807c478bd9Sstevel@tonic-gate 
19817c478bd9Sstevel@tonic-gate 	/*
19827c478bd9Sstevel@tonic-gate 	 * If this symbol is part of a DISCARDED section attempt to find another
19837c478bd9Sstevel@tonic-gate 	 * definition.
19847c478bd9Sstevel@tonic-gate 	 */
19857c478bd9Sstevel@tonic-gate 	if (sdp->sd_flags & FLG_SY_ISDISC) {
1986d2ef9fe9Sab196087 		Sym_desc	*nsdp = NULL;
198740e53e87SAli Bahrami 		Rlxrel_rej	reject;
19887c478bd9Sstevel@tonic-gate 
1989d2ef9fe9Sab196087 		if (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) {
1990d2ef9fe9Sab196087 			/*
19910e233487SRod Evans 			 * If "-z relaxreloc", and the input section is COMDAT
19920e233487SRod Evans 			 * that has been assigned to an output section, then
19930e233487SRod Evans 			 * determine if this is a reference to a discarded
19940e233487SRod Evans 			 * COMDAT section that can be replaced with a COMDAT
19950e233487SRod Evans 			 * that has been kept.
1996d2ef9fe9Sab196087 			 */
19970e233487SRod Evans 			if ((ofl->ofl_flags1 & FLG_OF1_RLXREL) &&
19980e233487SRod Evans 			    sdp->sd_isc->is_osdesc &&
19990e233487SRod Evans 			    (sdp->sd_isc->is_flags & FLG_IS_COMDAT) &&
20000e233487SRod Evans 			    ((nsdp = sloppy_comdat_reloc(ofl, reld,
200140e53e87SAli Bahrami 			    sdp, &reject)) == NULL)) {
2002ca4eed8bSAli Bahrami 				Shdr	*is_shdr = reld->rel_isdesc->is_shdr;
2003ca4eed8bSAli Bahrami 
2004ca4eed8bSAli Bahrami 				/*
2005ca4eed8bSAli Bahrami 				 * A matching symbol was not found. We will
2006635216b6SRod Evans 				 * ignore this relocation.  Determine whether
2007635216b6SRod Evans 				 * or not to issue a warning.
2008ca4eed8bSAli Bahrami 				 * Warnings are always issued under -z verbose,
2009ca4eed8bSAli Bahrami 				 * but otherwise, we will follow the lead of
2010ca4eed8bSAli Bahrami 				 * the GNU ld and suppress them for certain
2011ca4eed8bSAli Bahrami 				 * cases:
2012635216b6SRod Evans 				 *
2013ca4eed8bSAli Bahrami 				 *  -	It is a non-allocable debug section.
2014ca4eed8bSAli Bahrami 				 *	The GNU ld tests for these by name,
2015ca4eed8bSAli Bahrami 				 *	but we are willing to extend it to
2016ca4eed8bSAli Bahrami 				 *	any non-allocable section.
201740e53e87SAli Bahrami 				 *  -	The target section is excluded from
201840e53e87SAli Bahrami 				 *	sloppy relocations by policy.
2019ca4eed8bSAli Bahrami 				 */
202040e53e87SAli Bahrami 				if (((ofl->ofl_flags & FLG_OF_VERBOSE) != 0) ||
202140e53e87SAli Bahrami 				    ((is_shdr->sh_flags & SHF_ALLOC) &&
202240e53e87SAli Bahrami 				    (reject != RLXREL_REJ_TARGET)))
2023*1007fd6fSAli Bahrami 					ld_eprintf(ofl, ERR_WARNING,
20240e233487SRod Evans 					    MSG_INTL(MSG_REL_SLOPCDATNOSYM),
202540e53e87SAli Bahrami 					    conv_reloc_type(
202640e53e87SAli Bahrami 					    ifl->ifl_ehdr->e_machine,
20270e233487SRod Evans 					    reld->rel_rtype, 0, &inv_buf),
20284a8d0ea7SAli Bahrami 					    ifl->ifl_name,
20294a8d0ea7SAli Bahrami 					    EC_WORD(isp->is_scnndx),
20304a8d0ea7SAli Bahrami 					    isp->is_name,
2031bf994817SAli Bahrami 					    ld_reloc_sym_name(reld),
20324a8d0ea7SAli Bahrami 					    EC_WORD(sdp->sd_isc->is_scnndx),
20330e233487SRod Evans 					    sdp->sd_isc->is_name);
20340e233487SRod Evans 				return (1);
2035d2ef9fe9Sab196087 			}
2036bf994817SAli Bahrami 		} else if ((sdp != NULL) && sdp->sd_name && *sdp->sd_name)
2037635216b6SRod Evans 			nsdp = ld_sym_find(sdp->sd_name, SYM_NOHASH, NULL, ofl);
20380e233487SRod Evans 
20390e233487SRod Evans 		if (nsdp == NULL) {
2040*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_SYMDISC),
20410e233487SRod Evans 			    conv_reloc_type(ifl->ifl_ehdr->e_machine,
20420e233487SRod Evans 			    reld->rel_rtype, 0, &inv_buf), ifl->ifl_name,
20434a8d0ea7SAli Bahrami 			    EC_WORD(isp->is_scnndx), isp->is_name,
2044bf994817SAli Bahrami 			    ld_reloc_sym_name(reld),
20454a8d0ea7SAli Bahrami 			    EC_WORD(sdp->sd_isc->is_scnndx),
20460e233487SRod Evans 			    sdp->sd_isc->is_name);
20477c478bd9Sstevel@tonic-gate 			return (S_ERROR);
20487c478bd9Sstevel@tonic-gate 		}
20497c478bd9Sstevel@tonic-gate 		ifl->ifl_oldndx[rsndx] = sdp = nsdp;
2050bf994817SAli Bahrami 		if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) &&
2051bf994817SAli Bahrami 		    (sdp->sd_isc != NULL) && (sdp->sd_isc->is_name != NULL) &&
2052bf994817SAli Bahrami 		    (sdp->sd_isc->is_sym_name == NULL) &&
2053bf994817SAli Bahrami 		    (ld_stt_section_sym_name(sdp->sd_isc) == NULL))
2054bf994817SAli Bahrami 			return (S_ERROR);
20557c478bd9Sstevel@tonic-gate 	}
20567c478bd9Sstevel@tonic-gate 
20577c478bd9Sstevel@tonic-gate 	/*
20587c478bd9Sstevel@tonic-gate 	 * If this is a global symbol, determine whether its visibility needs
20597c478bd9Sstevel@tonic-gate 	 * adjusting.
20607c478bd9Sstevel@tonic-gate 	 */
20617c478bd9Sstevel@tonic-gate 	if (sdp->sd_aux && ((sdp->sd_flags & FLG_SY_VISIBLE) == 0))
20625aefb655Srie 		ld_sym_adjust_vis(sdp, ofl);
20637c478bd9Sstevel@tonic-gate 
20647c478bd9Sstevel@tonic-gate 	/*
20657c478bd9Sstevel@tonic-gate 	 * Ignore any relocation against a section that will not be in the
20667c478bd9Sstevel@tonic-gate 	 * output file (has been stripped).
20677c478bd9Sstevel@tonic-gate 	 */
20687c478bd9Sstevel@tonic-gate 	if ((sdp->sd_isc == 0) &&
20697c478bd9Sstevel@tonic-gate 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION))
20707c478bd9Sstevel@tonic-gate 		return (1);
20717c478bd9Sstevel@tonic-gate 
20727c478bd9Sstevel@tonic-gate 	/*
2073c1c6f601Srie 	 * If the input section exists, but the section has not been associated
2074c1c6f601Srie 	 * to an output section, then this is a little suspicious.
2075c1c6f601Srie 	 */
2076c1c6f601Srie 	if (sdp->sd_isc && (sdp->sd_isc->is_osdesc == 0) &&
2077c1c6f601Srie 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)) {
2078*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_RELINVSEC),
2079de777a60Sab196087 		    conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype,
20804a8d0ea7SAli Bahrami 		    0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx),
20814a8d0ea7SAli Bahrami 		    isp->is_name, EC_WORD(sdp->sd_isc->is_scnndx),
2082de777a60Sab196087 		    sdp->sd_isc->is_name);
2083c1c6f601Srie 		return (1);
2084c1c6f601Srie 	}
2085c1c6f601Srie 
2086c1c6f601Srie 	/*
20877c478bd9Sstevel@tonic-gate 	 * If the symbol for this relocation is invalid (which should have
20887c478bd9Sstevel@tonic-gate 	 * generated a message during symbol processing), or the relocation
20897c478bd9Sstevel@tonic-gate 	 * record's symbol reference is in any other way invalid, then it's
20907c478bd9Sstevel@tonic-gate 	 * about time we gave up.
20917c478bd9Sstevel@tonic-gate 	 */
20927c478bd9Sstevel@tonic-gate 	if ((sdp->sd_flags & FLG_SY_INVALID) || (rsndx == 0) ||
20937c478bd9Sstevel@tonic-gate 	    (rsndx >= ifl->ifl_symscnt)) {
2094*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_UNKNWSYM),
2095de777a60Sab196087 		    conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype,
20964a8d0ea7SAli Bahrami 		    0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx),
2097bf994817SAli Bahrami 		    isp->is_name, ld_reloc_sym_name(reld),
20984a8d0ea7SAli Bahrami 		    EC_XWORD(reloc->r_offset), EC_WORD(rsndx));
20997c478bd9Sstevel@tonic-gate 		return (S_ERROR);
21007c478bd9Sstevel@tonic-gate 	}
21017c478bd9Sstevel@tonic-gate 
21022926dd2eSrie 	/*
21032926dd2eSrie 	 * Size relocations against section symbols are presently unsupported.
21042926dd2eSrie 	 * There is a question as to whether the input section size, or output
21052926dd2eSrie 	 * section size would be used.  Until an explicit requirement is
21062926dd2eSrie 	 * established for either case, we'll punt.
21072926dd2eSrie 	 */
21082926dd2eSrie 	if (IS_SIZE(rtype) &&
21092926dd2eSrie 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)) {
2110*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSIZE),
2111de777a60Sab196087 		    conv_reloc_type(ifl->ifl_ehdr->e_machine, rtype,
21124a8d0ea7SAli Bahrami 		    0, &inv_buf), ifl->ifl_name, EC_WORD(isp->is_scnndx),
21134a8d0ea7SAli Bahrami 		    isp->is_name);
21142926dd2eSrie 		return (S_ERROR);
21152926dd2eSrie 	}
21162926dd2eSrie 
21177c478bd9Sstevel@tonic-gate 	reld->rel_sym = sdp;
2118bf994817SAli Bahrami 	if (reld->rel_aux)
2119bf994817SAli Bahrami 		reld->rel_aux->ra_usym = sdp;
2120e23c41c9SAli Bahrami 	return (ld_process_sym_reloc(ofl, reld, reloc, isp, isp->is_name,
2121e23c41c9SAli Bahrami 	    isp->is_scnndx));
21227c478bd9Sstevel@tonic-gate }
21237c478bd9Sstevel@tonic-gate 
21247c478bd9Sstevel@tonic-gate static uintptr_t
reloc_section(Ofl_desc * ofl,Is_desc * isect,Is_desc * rsect,Os_desc * osect)21257c478bd9Sstevel@tonic-gate reloc_section(Ofl_desc *ofl, Is_desc *isect, Is_desc *rsect, Os_desc *osect)
21267c478bd9Sstevel@tonic-gate {
21277c478bd9Sstevel@tonic-gate 	Rel		*rend;		/* end of relocation section data */
21287c478bd9Sstevel@tonic-gate 	Rel		*reloc;		/* current relocation entry */
21297c478bd9Sstevel@tonic-gate 	Xword		rsize;		/* size of relocation section data */
21307c478bd9Sstevel@tonic-gate 	Xword		entsize;	/* size of relocation entry */
21317c478bd9Sstevel@tonic-gate 	Rel_desc	reld;		/* relocation descriptor */
2132bf994817SAli Bahrami 	Rel_aux	rel_aux;
21337c478bd9Sstevel@tonic-gate 	Shdr *		shdr;
21347c478bd9Sstevel@tonic-gate 	Word		flags = 0;
213502ca3e02Srie 	uintptr_t	ret = 1;
21367c478bd9Sstevel@tonic-gate 
21377c478bd9Sstevel@tonic-gate 	shdr = rsect->is_shdr;
21387c478bd9Sstevel@tonic-gate 	rsize = shdr->sh_size;
21397c478bd9Sstevel@tonic-gate 	reloc = (Rel *)rsect->is_indata->d_buf;
21407c478bd9Sstevel@tonic-gate 
21417c478bd9Sstevel@tonic-gate 	/*
21427c478bd9Sstevel@tonic-gate 	 * Decide entry size.
21437c478bd9Sstevel@tonic-gate 	 */
21447c478bd9Sstevel@tonic-gate 	if (((entsize = shdr->sh_entsize) == 0) || (entsize > rsize)) {
21457c478bd9Sstevel@tonic-gate 		if (shdr->sh_type == SHT_RELA)
21467c478bd9Sstevel@tonic-gate 			entsize = sizeof (Rela);
21477c478bd9Sstevel@tonic-gate 		else
21487c478bd9Sstevel@tonic-gate 			entsize = sizeof (Rel);
21497c478bd9Sstevel@tonic-gate 	}
21507c478bd9Sstevel@tonic-gate 
21517c478bd9Sstevel@tonic-gate 	/*
21527c478bd9Sstevel@tonic-gate 	 * Build up the basic information in for the Rel_desc structure.
21537c478bd9Sstevel@tonic-gate 	 */
21547c478bd9Sstevel@tonic-gate 	reld.rel_isdesc = isect;
2155bf994817SAli Bahrami 	reld.rel_aux = &rel_aux;
2156bf994817SAli Bahrami 	ld_init_rel_aux(&reld);
2157bf994817SAli Bahrami 	rel_aux.ra_osdesc = osect;
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_flags & FLG_OF_RELOBJ) ||
21607c478bd9Sstevel@tonic-gate 	    (osect && (osect->os_sgdesc->sg_phdr.p_type == PT_LOAD)))
21617c478bd9Sstevel@tonic-gate 		flags |= FLG_REL_LOAD;
21627c478bd9Sstevel@tonic-gate 
21637c478bd9Sstevel@tonic-gate 	if (shdr->sh_info == 0)
21647c478bd9Sstevel@tonic-gate 		flags |= FLG_REL_NOINFO;
21657c478bd9Sstevel@tonic-gate 
21665aefb655Srie 	DBG_CALL(Dbg_reloc_proc(ofl->ofl_lml, osect, isect, rsect));
21677c478bd9Sstevel@tonic-gate 
21687c478bd9Sstevel@tonic-gate 	for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize);
21697c478bd9Sstevel@tonic-gate 	    reloc < rend;
2170b3fbe5e6Sseizo 	    reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) {
21717c478bd9Sstevel@tonic-gate 		Word	rsndx;
21727c478bd9Sstevel@tonic-gate 
21737c478bd9Sstevel@tonic-gate 		/*
21747c478bd9Sstevel@tonic-gate 		 * Initialize the relocation record information and process
21757c478bd9Sstevel@tonic-gate 		 * the individual relocation.  Reinitialize the flags to
21767c478bd9Sstevel@tonic-gate 		 * insure we don't carry any state over from the previous
21777c478bd9Sstevel@tonic-gate 		 * relocation records processing.
21787c478bd9Sstevel@tonic-gate 		 */
21797c478bd9Sstevel@tonic-gate 		reld.rel_flags = flags;
2180bf994817SAli Bahrami 		rsndx = (*ld_targ.t_mr.mr_init_rel)(&reld,
2181bf994817SAli Bahrami 		    &rel_aux.ra_typedata, (void *)reloc);
2182bf994817SAli Bahrami 
2183bf994817SAli Bahrami 		/*
2184bf994817SAli Bahrami 		 * Determine whether or not to pass an auxiliary block
2185bf994817SAli Bahrami 		 * in with this Rel_desc. It is not needed if both the
2186bf994817SAli Bahrami 		 * osdesc and typedata fields have default values.
2187bf994817SAli Bahrami 		 */
2188bf994817SAli Bahrami 		reld.rel_aux =
2189bf994817SAli Bahrami 		    (RELAUX_ISDEFAULT_OSDESC(&reld, rel_aux.ra_osdesc) &&
2190bf994817SAli Bahrami 		    RELAUX_ISDEFAULT_TYPEDATA(&reld, rel_aux.ra_typedata)) ?
2191bf994817SAli Bahrami 		    NULL : &rel_aux;
21927c478bd9Sstevel@tonic-gate 
21937c478bd9Sstevel@tonic-gate 		if (process_reld(ofl, rsect, &reld, rsndx, reloc) == S_ERROR)
219402ca3e02Srie 			ret = S_ERROR;
21957c478bd9Sstevel@tonic-gate 	}
219602ca3e02Srie 	return (ret);
21977c478bd9Sstevel@tonic-gate }
21987c478bd9Sstevel@tonic-gate 
21995aefb655Srie static uintptr_t
reloc_segments(int wr_flag,Ofl_desc * ofl)22007c478bd9Sstevel@tonic-gate reloc_segments(int wr_flag, Ofl_desc *ofl)
22017c478bd9Sstevel@tonic-gate {
220257ef7aa9SRod Evans 	Aliste		idx1;
22037c478bd9Sstevel@tonic-gate 	Sg_desc		*sgp;
22047c478bd9Sstevel@tonic-gate 	Is_desc		*isp;
22057c478bd9Sstevel@tonic-gate 
220657ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
2207cce0e03bSab196087 		Os_desc	*osp;
220857ef7aa9SRod Evans 		Aliste	idx2;
22097c478bd9Sstevel@tonic-gate 
22107c478bd9Sstevel@tonic-gate 		if ((sgp->sg_phdr.p_flags & PF_W) != wr_flag)
22117c478bd9Sstevel@tonic-gate 			continue;
22127c478bd9Sstevel@tonic-gate 
221357ef7aa9SRod Evans 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
22147c478bd9Sstevel@tonic-gate 			Is_desc	*risp;
221557ef7aa9SRod Evans 			Aliste	idx3;
22167c478bd9Sstevel@tonic-gate 
22177c478bd9Sstevel@tonic-gate 			osp->os_szoutrels = 0;
221857ef7aa9SRod Evans 			for (APLIST_TRAVERSE(osp->os_relisdescs, idx3, risp)) {
22197c478bd9Sstevel@tonic-gate 				Word	indx;
22207c478bd9Sstevel@tonic-gate 
22217c478bd9Sstevel@tonic-gate 				/*
22227c478bd9Sstevel@tonic-gate 				 * Determine the input section that this
22237c478bd9Sstevel@tonic-gate 				 * relocation information refers to.
22247c478bd9Sstevel@tonic-gate 				 */
22257c478bd9Sstevel@tonic-gate 				indx = risp->is_shdr->sh_info;
22267c478bd9Sstevel@tonic-gate 				isp = risp->is_file->ifl_isdesc[indx];
22277c478bd9Sstevel@tonic-gate 
22287c478bd9Sstevel@tonic-gate 				/*
22297c478bd9Sstevel@tonic-gate 				 * Do not process relocations against sections
22307c478bd9Sstevel@tonic-gate 				 * which are being discarded (COMDAT)
22317c478bd9Sstevel@tonic-gate 				 */
22327c478bd9Sstevel@tonic-gate 				if (isp->is_flags & FLG_IS_DISCARD)
22337c478bd9Sstevel@tonic-gate 					continue;
22347c478bd9Sstevel@tonic-gate 
22357c478bd9Sstevel@tonic-gate 				if (reloc_section(ofl, isp, risp, osp) ==
22367c478bd9Sstevel@tonic-gate 				    S_ERROR)
22377c478bd9Sstevel@tonic-gate 					return (S_ERROR);
22387c478bd9Sstevel@tonic-gate 			}
22397c478bd9Sstevel@tonic-gate 
22407c478bd9Sstevel@tonic-gate 			/*
22417c478bd9Sstevel@tonic-gate 			 * Check for relocations against non-writable
22427c478bd9Sstevel@tonic-gate 			 * allocatable sections.
22437c478bd9Sstevel@tonic-gate 			 */
22446b3ba5bdSAli Bahrami 			if (osp->os_szoutrels &&
22457c478bd9Sstevel@tonic-gate 			    (sgp->sg_phdr.p_type == PT_LOAD) &&
22467c478bd9Sstevel@tonic-gate 			    ((sgp->sg_phdr.p_flags & PF_W) == 0)) {
22477c478bd9Sstevel@tonic-gate 				ofl->ofl_flags |= FLG_OF_TEXTREL;
22487c478bd9Sstevel@tonic-gate 				ofl->ofl_dtflags |= DF_TEXTREL;
22497c478bd9Sstevel@tonic-gate 			}
22507c478bd9Sstevel@tonic-gate 		}
22517c478bd9Sstevel@tonic-gate 	}
22527c478bd9Sstevel@tonic-gate 
22537c478bd9Sstevel@tonic-gate 	return (1);
22547c478bd9Sstevel@tonic-gate }
22557c478bd9Sstevel@tonic-gate 
22567c478bd9Sstevel@tonic-gate /*
22577c478bd9Sstevel@tonic-gate  * Move Section related function
22587c478bd9Sstevel@tonic-gate  * Get move entry
22597c478bd9Sstevel@tonic-gate  */
22607c478bd9Sstevel@tonic-gate static Move *
get_move_entry(Is_desc * rsect,Xword roffset)22617c478bd9Sstevel@tonic-gate get_move_entry(Is_desc *rsect, Xword roffset)
22627c478bd9Sstevel@tonic-gate {
22637c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifile = rsect->is_file;
22647c478bd9Sstevel@tonic-gate 	Shdr		*rshdr = rsect->is_shdr;
22657c478bd9Sstevel@tonic-gate 	Is_desc		*misp;
22667c478bd9Sstevel@tonic-gate 	Shdr		*mshdr;
22677c478bd9Sstevel@tonic-gate 	Xword 		midx;
226857ef7aa9SRod Evans 	Move		*mvp;
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate 	/*
22717c478bd9Sstevel@tonic-gate 	 * Set info for the target move section
22727c478bd9Sstevel@tonic-gate 	 */
22737c478bd9Sstevel@tonic-gate 	misp = ifile->ifl_isdesc[rshdr->sh_info];
227457ef7aa9SRod Evans 	mshdr = misp->is_shdr;
22757c478bd9Sstevel@tonic-gate 
22767c478bd9Sstevel@tonic-gate 	if (mshdr->sh_entsize == 0)
227757ef7aa9SRod Evans 		return (NULL);
22787c478bd9Sstevel@tonic-gate 
22797c478bd9Sstevel@tonic-gate 	/*
228057ef7aa9SRod Evans 	 * If this is an invalid entry, return NULL.
22817c478bd9Sstevel@tonic-gate 	 */
228257ef7aa9SRod Evans 	midx = roffset / mshdr->sh_entsize;
22837c478bd9Sstevel@tonic-gate 	if ((midx * mshdr->sh_entsize) >= mshdr->sh_size)
228457ef7aa9SRod Evans 		return (NULL);
228557ef7aa9SRod Evans 
228657ef7aa9SRod Evans 	mvp = (Move *)misp->is_indata->d_buf;
228757ef7aa9SRod Evans 	mvp += midx;
228857ef7aa9SRod Evans 	return (mvp);
22897c478bd9Sstevel@tonic-gate }
22907c478bd9Sstevel@tonic-gate 
22917c478bd9Sstevel@tonic-gate /*
22927c478bd9Sstevel@tonic-gate  * Relocation against Move Table.
22937c478bd9Sstevel@tonic-gate  */
22947c478bd9Sstevel@tonic-gate static uintptr_t
process_movereloc(Ofl_desc * ofl,Is_desc * rsect)22957c478bd9Sstevel@tonic-gate process_movereloc(Ofl_desc *ofl, Is_desc *rsect)
22967c478bd9Sstevel@tonic-gate {
22977c478bd9Sstevel@tonic-gate 	Ifl_desc	*file = rsect->is_file;
22987c478bd9Sstevel@tonic-gate 	Rel		*rend, *reloc;
22997c478bd9Sstevel@tonic-gate 	Xword 		rsize, entsize;
23007c478bd9Sstevel@tonic-gate 	Rel_desc 	reld;
2301bf994817SAli Bahrami 	Rel_aux	rel_aux;
23027c478bd9Sstevel@tonic-gate 
23037c478bd9Sstevel@tonic-gate 	rsize = rsect->is_shdr->sh_size;
23047c478bd9Sstevel@tonic-gate 	reloc = (Rel *)rsect->is_indata->d_buf;
23057c478bd9Sstevel@tonic-gate 
23067c478bd9Sstevel@tonic-gate 	/*
230757ef7aa9SRod Evans 	 * Decide entry size.
23087c478bd9Sstevel@tonic-gate 	 */
23097c478bd9Sstevel@tonic-gate 	entsize = rsect->is_shdr->sh_entsize;
23107c478bd9Sstevel@tonic-gate 	if ((entsize == 0) ||
23117c478bd9Sstevel@tonic-gate 	    (entsize > rsect->is_shdr->sh_size)) {
23127c478bd9Sstevel@tonic-gate 		if (rsect->is_shdr->sh_type == SHT_RELA)
23137c478bd9Sstevel@tonic-gate 			entsize = sizeof (Rela);
23147c478bd9Sstevel@tonic-gate 		else
23157c478bd9Sstevel@tonic-gate 			entsize = sizeof (Rel);
23167c478bd9Sstevel@tonic-gate 	}
23177c478bd9Sstevel@tonic-gate 
23187c478bd9Sstevel@tonic-gate 	/*
2319bf994817SAli Bahrami 	 * The requirement for move data ensures that we have to supply a
2320bf994817SAli Bahrami 	 * Rel_aux auxiliary block.
2321bf994817SAli Bahrami 	 */
2322bf994817SAli Bahrami 	reld.rel_aux = &rel_aux;
2323bf994817SAli Bahrami 	ld_init_rel_aux(&reld);
2324bf994817SAli Bahrami 
2325bf994817SAli Bahrami 	/*
23267c478bd9Sstevel@tonic-gate 	 * Go through the relocation entries.
23277c478bd9Sstevel@tonic-gate 	 */
23287c478bd9Sstevel@tonic-gate 	for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize);
23297c478bd9Sstevel@tonic-gate 	    reloc < rend;
2330b3fbe5e6Sseizo 	    reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) {
23317c478bd9Sstevel@tonic-gate 		Sym_desc	*psdp;
233257ef7aa9SRod Evans 		Move		*mvp;
23337c478bd9Sstevel@tonic-gate 		Word		rsndx;
23347c478bd9Sstevel@tonic-gate 
23357c478bd9Sstevel@tonic-gate 		/*
23367c478bd9Sstevel@tonic-gate 		 * Initialize the relocation record information.
23377c478bd9Sstevel@tonic-gate 		 */
23387c478bd9Sstevel@tonic-gate 		reld.rel_flags = FLG_REL_LOAD;
2339bf994817SAli Bahrami 		rsndx = (*ld_targ.t_mr.mr_init_rel)(&reld,
2340bf994817SAli Bahrami 		    &rel_aux.ra_typedata, (void *)reloc);
23417c478bd9Sstevel@tonic-gate 
234257ef7aa9SRod Evans 		if (((mvp = get_move_entry(rsect, reloc->r_offset)) == NULL) ||
2343bf994817SAli Bahrami 		    ((rel_aux.ra_move =
2344bf994817SAli Bahrami 		    libld_malloc(sizeof (Mv_reloc))) == NULL))
23457c478bd9Sstevel@tonic-gate 			return (S_ERROR);
23467c478bd9Sstevel@tonic-gate 
234757ef7aa9SRod Evans 		psdp = file->ifl_oldndx[ELF_M_SYM(mvp->m_info)];
2348bf994817SAli Bahrami 		rel_aux.ra_move->mr_move = mvp;
2349bf994817SAli Bahrami 		rel_aux.ra_move->mr_sym = psdp;
23507c478bd9Sstevel@tonic-gate 
23517c478bd9Sstevel@tonic-gate 		if (psdp->sd_flags & FLG_SY_PAREXPN) {
235257ef7aa9SRod Evans 			int	_num, num = mvp->m_repeat;
23537c478bd9Sstevel@tonic-gate 
2354bf994817SAli Bahrami 			rel_aux.ra_osdesc = ofl->ofl_isparexpn->is_osdesc;
235535450702SAli Bahrami 			reld.rel_isdesc = ofl->ofl_isparexpn;
235657ef7aa9SRod Evans 			reld.rel_roffset = mvp->m_poffset;
23577c478bd9Sstevel@tonic-gate 
235857ef7aa9SRod Evans 			for (_num = 0; _num < num; _num++) {
23597c478bd9Sstevel@tonic-gate 				reld.rel_roffset +=
23607c478bd9Sstevel@tonic-gate 				    /* LINTED */
236157ef7aa9SRod Evans 				    (_num * ELF_M_SIZE(mvp->m_info));
236260758829Srie 
23637c478bd9Sstevel@tonic-gate 				/*
23647c478bd9Sstevel@tonic-gate 				 * Generate Reld
23657c478bd9Sstevel@tonic-gate 				 */
23667c478bd9Sstevel@tonic-gate 				if (process_reld(ofl,
23677c478bd9Sstevel@tonic-gate 				    rsect, &reld, rsndx, reloc) == S_ERROR)
23687c478bd9Sstevel@tonic-gate 					return (S_ERROR);
23697c478bd9Sstevel@tonic-gate 			}
23707c478bd9Sstevel@tonic-gate 		} else {
23717c478bd9Sstevel@tonic-gate 			/*
23727c478bd9Sstevel@tonic-gate 			 * Generate Reld
23737c478bd9Sstevel@tonic-gate 			 */
23747c478bd9Sstevel@tonic-gate 			reld.rel_flags |= FLG_REL_MOVETAB;
2375bf994817SAli Bahrami 			rel_aux.ra_osdesc = ofl->ofl_osmove;
23761dd9d86fSAli Bahrami 			reld.rel_isdesc = ld_os_first_isdesc(ofl->ofl_osmove);
237760758829Srie 
23787c478bd9Sstevel@tonic-gate 			if (process_reld(ofl,
23797c478bd9Sstevel@tonic-gate 			    rsect, &reld, rsndx, reloc) == S_ERROR)
23807c478bd9Sstevel@tonic-gate 				return (S_ERROR);
23817c478bd9Sstevel@tonic-gate 		}
23827c478bd9Sstevel@tonic-gate 	}
23837c478bd9Sstevel@tonic-gate 	return (1);
23847c478bd9Sstevel@tonic-gate }
23857c478bd9Sstevel@tonic-gate 
23867c478bd9Sstevel@tonic-gate /*
23877c478bd9Sstevel@tonic-gate  * This function is similar to reloc_init().
23887c478bd9Sstevel@tonic-gate  *
238957ef7aa9SRod Evans  * This function is called when the SHT_SUNW_move table is expanded and there
239057ef7aa9SRod Evans  * are relocations against the SHT_SUNW_move section.
23917c478bd9Sstevel@tonic-gate  */
23927c478bd9Sstevel@tonic-gate static uintptr_t
reloc_movesections(Ofl_desc * ofl)23937c478bd9Sstevel@tonic-gate reloc_movesections(Ofl_desc *ofl)
23947c478bd9Sstevel@tonic-gate {
239557ef7aa9SRod Evans 	Aliste		idx;
23967c478bd9Sstevel@tonic-gate 	Is_desc		*risp;
239702ca3e02Srie 	uintptr_t	ret = 1;
23987c478bd9Sstevel@tonic-gate 
23997c478bd9Sstevel@tonic-gate 	/*
24007c478bd9Sstevel@tonic-gate 	 * Generate/Expand relocation entries
24017c478bd9Sstevel@tonic-gate 	 */
240257ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_ismoverel, idx, risp)) {
24037c478bd9Sstevel@tonic-gate 		if (process_movereloc(ofl, risp) == S_ERROR)
240402ca3e02Srie 			ret = S_ERROR;
24057c478bd9Sstevel@tonic-gate 	}
24067c478bd9Sstevel@tonic-gate 
240702ca3e02Srie 	return (ret);
24087c478bd9Sstevel@tonic-gate }
24097c478bd9Sstevel@tonic-gate 
24107c478bd9Sstevel@tonic-gate /*
24117c478bd9Sstevel@tonic-gate  * Count the number of output relocation entries, global offset table entries,
24127c478bd9Sstevel@tonic-gate  * and procedure linkage table entries.  This function searches the segment and
24137c478bd9Sstevel@tonic-gate  * outsect lists and passes each input reloc section to process_reloc().
24147c478bd9Sstevel@tonic-gate  * It allocates space for any output relocations needed.  And builds up
24157c478bd9Sstevel@tonic-gate  * the relocation structures for later processing.
24167c478bd9Sstevel@tonic-gate  */
24177c478bd9Sstevel@tonic-gate uintptr_t
ld_reloc_init(Ofl_desc * ofl)24185aefb655Srie ld_reloc_init(Ofl_desc *ofl)
24197c478bd9Sstevel@tonic-gate {
242057ef7aa9SRod Evans 	Aliste		idx;
24217c478bd9Sstevel@tonic-gate 	Is_desc		*isp;
24229a411307Srie 	Sym_desc	*sdp;
24237c478bd9Sstevel@tonic-gate 
24242017c965SRod Evans 	DBG_CALL(Dbg_basic_collect(ofl->ofl_lml));
24252017c965SRod Evans 
24267c478bd9Sstevel@tonic-gate 	/*
24277c478bd9Sstevel@tonic-gate 	 * At this point we have finished processing all input symbols.  Make
24287c478bd9Sstevel@tonic-gate 	 * sure we add any absolute (internal) symbols before continuing with
24297c478bd9Sstevel@tonic-gate 	 * any relocation processing.
24307c478bd9Sstevel@tonic-gate 	 */
24315aefb655Srie 	if (ld_sym_spec(ofl) == S_ERROR)
24327c478bd9Sstevel@tonic-gate 		return (S_ERROR);
24337c478bd9Sstevel@tonic-gate 
2434ba2be530Sab196087 	ofl->ofl_gotcnt = ld_targ.t_m.m_got_xnumber;
24357c478bd9Sstevel@tonic-gate 
24367c478bd9Sstevel@tonic-gate 	/*
2437635216b6SRod Evans 	 * Process all of the relocations against NON-writable segments
2438635216b6SRod Evans 	 * followed by relocations against the writable segments.
24397c478bd9Sstevel@tonic-gate 	 *
24407c478bd9Sstevel@tonic-gate 	 * This separation is so that when the writable segments are processed
24417c478bd9Sstevel@tonic-gate 	 * we know whether or not a COPYRELOC will be produced for any symbols.
24427c478bd9Sstevel@tonic-gate 	 * If relocations aren't processed in this order, a COPYRELOC and a
24437c478bd9Sstevel@tonic-gate 	 * regular relocation can be produced against the same symbol.  The
24447c478bd9Sstevel@tonic-gate 	 * regular relocation would be redundant.
24457c478bd9Sstevel@tonic-gate 	 */
24467c478bd9Sstevel@tonic-gate 	if (reloc_segments(0, ofl) == S_ERROR)
24477c478bd9Sstevel@tonic-gate 		return (S_ERROR);
24487c478bd9Sstevel@tonic-gate 
24497c478bd9Sstevel@tonic-gate 	if (reloc_segments(PF_W, ofl) == S_ERROR)
24507c478bd9Sstevel@tonic-gate 		return (S_ERROR);
24517c478bd9Sstevel@tonic-gate 
24527c478bd9Sstevel@tonic-gate 	/*
24537c478bd9Sstevel@tonic-gate 	 * Process any extra relocations.  These are relocation sections that
24547c478bd9Sstevel@tonic-gate 	 * have a NULL sh_info.
24557c478bd9Sstevel@tonic-gate 	 */
245657ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_extrarels, idx, isp)) {
24577c478bd9Sstevel@tonic-gate 		if (reloc_section(ofl, NULL, isp, NULL) == S_ERROR)
24587c478bd9Sstevel@tonic-gate 			return (S_ERROR);
24597c478bd9Sstevel@tonic-gate 	}
24607c478bd9Sstevel@tonic-gate 
24617c478bd9Sstevel@tonic-gate 	/*
24627c478bd9Sstevel@tonic-gate 	 * If there were relocation against move table,
24637c478bd9Sstevel@tonic-gate 	 * process the relocation sections.
24647c478bd9Sstevel@tonic-gate 	 */
24657c478bd9Sstevel@tonic-gate 	if (reloc_movesections(ofl) == S_ERROR)
24667c478bd9Sstevel@tonic-gate 		return (S_ERROR);
24677c478bd9Sstevel@tonic-gate 
24687c478bd9Sstevel@tonic-gate 	/*
24697c478bd9Sstevel@tonic-gate 	 * Now all the relocations are pre-processed,
24707c478bd9Sstevel@tonic-gate 	 * check the validity of copy relocations.
24717c478bd9Sstevel@tonic-gate 	 */
247257ef7aa9SRod Evans 	if (ofl->ofl_copyrels) {
247357ef7aa9SRod Evans 		Copy_rel	*crp;
24747c478bd9Sstevel@tonic-gate 
247557ef7aa9SRod Evans 		for (ALIST_TRAVERSE(ofl->ofl_copyrels, idx, crp)) {
24767c478bd9Sstevel@tonic-gate 			/*
24777c478bd9Sstevel@tonic-gate 			 * If there were no displacement relocation
24787c478bd9Sstevel@tonic-gate 			 * in this file, don't worry about it.
24797c478bd9Sstevel@tonic-gate 			 */
248057ef7aa9SRod Evans 			if (crp->c_sdp->sd_file->ifl_flags &
24817c478bd9Sstevel@tonic-gate 			    (FLG_IF_DISPPEND | FLG_IF_DISPDONE))
248257ef7aa9SRod Evans 				is_disp_copied(ofl, crp);
24837c478bd9Sstevel@tonic-gate 		}
24847c478bd9Sstevel@tonic-gate 	}
24857c478bd9Sstevel@tonic-gate 
24867c478bd9Sstevel@tonic-gate 	/*
2487141040e8Srie 	 * GOT sections are created for dynamic executables and shared objects
2488141040e8Srie 	 * if the FLG_OF_BLDGOT is set, or explicit reference has been made to
2489141040e8Srie 	 * a GOT symbol.
24907c478bd9Sstevel@tonic-gate 	 */
2491141040e8Srie 	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) &&
2492141040e8Srie 	    ((ofl->ofl_flags & FLG_OF_BLDGOT) ||
24939a411307Srie 	    ((((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_GOFTBL),
2494635216b6SRod Evans 	    SYM_NOHASH, NULL, ofl)) != NULL) ||
24959a411307Srie 	    ((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_GOFTBL_U),
2496635216b6SRod Evans 	    SYM_NOHASH, NULL, ofl)) != NULL)) &&
2497635216b6SRod Evans 	    (sdp->sd_ref != REF_DYN_SEEN)))) {
24985aefb655Srie 		if (ld_make_got(ofl) == S_ERROR)
24997c478bd9Sstevel@tonic-gate 			return (S_ERROR);
25007c478bd9Sstevel@tonic-gate 
2501ba2be530Sab196087 		/* Allocate the GOT if required by target */
2502ba2be530Sab196087 		if ((ld_targ.t_mr.mr_allocate_got != NULL) &&
2503ba2be530Sab196087 		    ((*ld_targ.t_mr.mr_allocate_got)(ofl) == S_ERROR))
25047c478bd9Sstevel@tonic-gate 			return (S_ERROR);
25057c478bd9Sstevel@tonic-gate 	}
25067c478bd9Sstevel@tonic-gate 
25077c478bd9Sstevel@tonic-gate 	return (1);
25087c478bd9Sstevel@tonic-gate }
25097c478bd9Sstevel@tonic-gate 
25107c478bd9Sstevel@tonic-gate /*
25117c478bd9Sstevel@tonic-gate  * Simple comparison routine to be used by qsort() for
25127c478bd9Sstevel@tonic-gate  * the sorting of the output relocation list.
25137c478bd9Sstevel@tonic-gate  *
25147c478bd9Sstevel@tonic-gate  * The reloc_compare() routine results in a relocation
25157c478bd9Sstevel@tonic-gate  * table which is located on:
25167c478bd9Sstevel@tonic-gate  *
25177c478bd9Sstevel@tonic-gate  *	file referenced (NEEDED NDX)
25187c478bd9Sstevel@tonic-gate  *	referenced symbol
25197c478bd9Sstevel@tonic-gate  *	relocation offset
25207c478bd9Sstevel@tonic-gate  *
25217c478bd9Sstevel@tonic-gate  * This provides the most efficient traversal of the relocation
25227c478bd9Sstevel@tonic-gate  * table at run-time.
25237c478bd9Sstevel@tonic-gate  */
25245aefb655Srie static int
reloc_compare(Reloc_list * i,Reloc_list * j)25257c478bd9Sstevel@tonic-gate reloc_compare(Reloc_list *i, Reloc_list *j)
25267c478bd9Sstevel@tonic-gate {
25277c478bd9Sstevel@tonic-gate 
25287c478bd9Sstevel@tonic-gate 	/*
25297c478bd9Sstevel@tonic-gate 	 * first - sort on neededndx
25307c478bd9Sstevel@tonic-gate 	 */
25317c478bd9Sstevel@tonic-gate 	if (i->rl_key1 > j->rl_key1)
25327c478bd9Sstevel@tonic-gate 		return (1);
25337c478bd9Sstevel@tonic-gate 	if (i->rl_key1 < j->rl_key1)
25347c478bd9Sstevel@tonic-gate 		return (-1);
25357c478bd9Sstevel@tonic-gate 
25367c478bd9Sstevel@tonic-gate 	/*
25377c478bd9Sstevel@tonic-gate 	 * Then sort on symbol
25387c478bd9Sstevel@tonic-gate 	 */
25397c478bd9Sstevel@tonic-gate 	if ((uintptr_t)i->rl_key2 > (uintptr_t)j->rl_key2)
25407c478bd9Sstevel@tonic-gate 		return (1);
25417c478bd9Sstevel@tonic-gate 	if ((uintptr_t)i->rl_key2 < (uintptr_t)j->rl_key2)
25427c478bd9Sstevel@tonic-gate 		return (-1);
25437c478bd9Sstevel@tonic-gate 
25447c478bd9Sstevel@tonic-gate 	/*
25457c478bd9Sstevel@tonic-gate 	 * i->key2 == j->key2
25467c478bd9Sstevel@tonic-gate 	 *
25477c478bd9Sstevel@tonic-gate 	 * At this point we fall back to key2 (offsets) to
25487c478bd9Sstevel@tonic-gate 	 * sort the output relocations.  Ideally this will
25497c478bd9Sstevel@tonic-gate 	 * make for the most efficient processing of these
25507c478bd9Sstevel@tonic-gate 	 * relocations at run-time.
25517c478bd9Sstevel@tonic-gate 	 */
25527c478bd9Sstevel@tonic-gate 	if (i->rl_key3 > j->rl_key3)
25537c478bd9Sstevel@tonic-gate 		return (1);
25547c478bd9Sstevel@tonic-gate 	if (i->rl_key3 < j->rl_key3)
25557c478bd9Sstevel@tonic-gate 		return (-1);
25567c478bd9Sstevel@tonic-gate 	return (0);
25577c478bd9Sstevel@tonic-gate }
25587c478bd9Sstevel@tonic-gate 
25595aefb655Srie static uintptr_t
do_sorted_outrelocs(Ofl_desc * ofl)25607c478bd9Sstevel@tonic-gate do_sorted_outrelocs(Ofl_desc *ofl)
25617c478bd9Sstevel@tonic-gate {
25627c478bd9Sstevel@tonic-gate 	Rel_desc	*orsp;
2563bf994817SAli Bahrami 	Rel_cachebuf	*rcbp;
256457ef7aa9SRod Evans 	Aliste		idx;
25657c478bd9Sstevel@tonic-gate 	Reloc_list	*sorted_list;
25667c478bd9Sstevel@tonic-gate 	Word		index = 0;
25677c478bd9Sstevel@tonic-gate 	int		debug = 0;
25687c478bd9Sstevel@tonic-gate 	uintptr_t	error = 1;
2569*1007fd6fSAli Bahrami 	Boolean		remain_seen = FALSE;
25707c478bd9Sstevel@tonic-gate 
25717c478bd9Sstevel@tonic-gate 	if ((sorted_list = libld_malloc((size_t)(sizeof (Reloc_list) *
25727c478bd9Sstevel@tonic-gate 	    ofl->ofl_reloccnt))) == NULL)
25737c478bd9Sstevel@tonic-gate 		return (S_ERROR);
25747c478bd9Sstevel@tonic-gate 
25757c478bd9Sstevel@tonic-gate 	/*
25767c478bd9Sstevel@tonic-gate 	 * All but the PLT output relocations are sorted in the output file
25777c478bd9Sstevel@tonic-gate 	 * based upon their sym_desc.  By doing this multiple relocations
25787c478bd9Sstevel@tonic-gate 	 * against the same symbol are grouped together, thus when the object
25797c478bd9Sstevel@tonic-gate 	 * is later relocated by ld.so.1 it will take advantage of the symbol
25807c478bd9Sstevel@tonic-gate 	 * cache that ld.so.1 has.  This can significantly reduce the runtime
25817c478bd9Sstevel@tonic-gate 	 * relocation cost of a dynamic object.
25827c478bd9Sstevel@tonic-gate 	 *
25837c478bd9Sstevel@tonic-gate 	 * PLT relocations are not sorted because the order of the PLT
25847c478bd9Sstevel@tonic-gate 	 * relocations is used by ld.so.1 to determine what symbol a PLT
25857c478bd9Sstevel@tonic-gate 	 * relocation is against.
25867c478bd9Sstevel@tonic-gate 	 */
2587bf994817SAli Bahrami 	REL_CACHE_TRAVERSE(&ofl->ofl_outrels, idx, rcbp, orsp) {
25887c478bd9Sstevel@tonic-gate 		if (debug == 0) {
25895aefb655Srie 			DBG_CALL(Dbg_reloc_dooutrel(ofl->ofl_lml,
2590ba2be530Sab196087 			    ld_targ.t_m.m_rel_sht_type));
25917c478bd9Sstevel@tonic-gate 			debug = 1;
25927c478bd9Sstevel@tonic-gate 		}
25937c478bd9Sstevel@tonic-gate 
25947c478bd9Sstevel@tonic-gate 		/*
25957c478bd9Sstevel@tonic-gate 		 * If it's a PLT relocation we output it now in the
25967c478bd9Sstevel@tonic-gate 		 * order that it was originally processed.
25977c478bd9Sstevel@tonic-gate 		 */
25987c478bd9Sstevel@tonic-gate 		if (orsp->rel_flags & FLG_REL_PLT) {
2599*1007fd6fSAli Bahrami 			if ((*ld_targ.t_mr.mr_perform_outreloc)
2600*1007fd6fSAli Bahrami 			    (orsp, ofl, &remain_seen) == S_ERROR)
26017c478bd9Sstevel@tonic-gate 				error = S_ERROR;
26027c478bd9Sstevel@tonic-gate 			continue;
26037c478bd9Sstevel@tonic-gate 		}
26047c478bd9Sstevel@tonic-gate 
2605ba2be530Sab196087 		if ((orsp->rel_rtype == ld_targ.t_m.m_r_relative) ||
2606ba2be530Sab196087 		    (orsp->rel_rtype == ld_targ.t_m.m_r_register)) {
26077c478bd9Sstevel@tonic-gate 			sorted_list[index].rl_key1 = 0;
26087c478bd9Sstevel@tonic-gate 			sorted_list[index].rl_key2 =
26097c478bd9Sstevel@tonic-gate 			    /* LINTED */
26107c478bd9Sstevel@tonic-gate 			    (Sym_desc *)(uintptr_t)orsp->rel_rtype;
26117c478bd9Sstevel@tonic-gate 		} else {
26127c478bd9Sstevel@tonic-gate 			sorted_list[index].rl_key1 =
26137c478bd9Sstevel@tonic-gate 			    orsp->rel_sym->sd_file->ifl_neededndx;
2614bf994817SAli Bahrami 			sorted_list[index].rl_key2 = orsp->rel_sym;
26157c478bd9Sstevel@tonic-gate 		}
26167c478bd9Sstevel@tonic-gate 
2617bf994817SAli Bahrami 		if (orsp->rel_flags & FLG_REL_GOT) {
26187c478bd9Sstevel@tonic-gate 			sorted_list[index].rl_key3 =
2619bf994817SAli Bahrami 			    (*ld_targ.t_mr.mr_calc_got_offset)(orsp, ofl);
2620bf994817SAli Bahrami 		} else {
2621bf994817SAli Bahrami 			if (orsp->rel_rtype == ld_targ.t_m.m_r_register) {
26227c478bd9Sstevel@tonic-gate 					sorted_list[index].rl_key3 = 0;
2623bf994817SAli Bahrami 			} else {
2624bf994817SAli Bahrami 				sorted_list[index].rl_key3 = orsp->rel_roffset +
26257c478bd9Sstevel@tonic-gate 				    (Xword)_elf_getxoff(orsp->
2626de777a60Sab196087 				    rel_isdesc->is_indata) +
26277c478bd9Sstevel@tonic-gate 				    orsp->rel_isdesc->is_osdesc->
26287c478bd9Sstevel@tonic-gate 				    os_shdr->sh_addr;
26297c478bd9Sstevel@tonic-gate 			}
26307c478bd9Sstevel@tonic-gate 		}
26317c478bd9Sstevel@tonic-gate 
26327c478bd9Sstevel@tonic-gate 		sorted_list[index++].rl_rsp = orsp;
26337c478bd9Sstevel@tonic-gate 	}
26347c478bd9Sstevel@tonic-gate 
26357c478bd9Sstevel@tonic-gate 	qsort(sorted_list, (size_t)ofl->ofl_reloccnt, sizeof (Reloc_list),
26367c478bd9Sstevel@tonic-gate 	    (int (*)(const void *, const void *))reloc_compare);
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate 	/*
26397c478bd9Sstevel@tonic-gate 	 * All output relocations have now been sorted, go through
26407c478bd9Sstevel@tonic-gate 	 * and process each relocation.
26417c478bd9Sstevel@tonic-gate 	 */
26427c478bd9Sstevel@tonic-gate 	for (index = 0; index < ofl->ofl_reloccnt; index++) {
2643ba2be530Sab196087 		if ((*ld_targ.t_mr.mr_perform_outreloc)
2644*1007fd6fSAli Bahrami 		    (sorted_list[index].rl_rsp, ofl, &remain_seen) == S_ERROR)
26457c478bd9Sstevel@tonic-gate 			error = S_ERROR;
26467c478bd9Sstevel@tonic-gate 	}
26477c478bd9Sstevel@tonic-gate 
2648*1007fd6fSAli Bahrami 	/* Guidance: Use -z text when building shared objects */
2649*1007fd6fSAli Bahrami 	if (remain_seen && OFL_GUIDANCE(ofl, FLG_OFG_NO_TEXT))
2650*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_TEXT));
2651*1007fd6fSAli Bahrami 
26527c478bd9Sstevel@tonic-gate 	return (error);
26537c478bd9Sstevel@tonic-gate }
26547c478bd9Sstevel@tonic-gate 
26557c478bd9Sstevel@tonic-gate /*
26567c478bd9Sstevel@tonic-gate  * Process relocations.  Finds every input relocation section for each output
2657cce0e03bSab196087  * section and invokes reloc_section() to relocate that section.
26587c478bd9Sstevel@tonic-gate  */
26597c478bd9Sstevel@tonic-gate uintptr_t
ld_reloc_process(Ofl_desc * ofl)26605aefb655Srie ld_reloc_process(Ofl_desc *ofl)
26617c478bd9Sstevel@tonic-gate {
26627c478bd9Sstevel@tonic-gate 	Sg_desc		*sgp;
2663d326b23bSrie 	Os_desc		*osp;
26641d9df23bSab196087 	Word		ndx = 0;
26651d9df23bSab196087 	ofl_flag_t	flags = ofl->ofl_flags;
26667c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
26677c478bd9Sstevel@tonic-gate 
26682017c965SRod Evans 	DBG_CALL(Dbg_basic_relocate(ofl->ofl_lml));
26692017c965SRod Evans 
26707c478bd9Sstevel@tonic-gate 	/*
26717c478bd9Sstevel@tonic-gate 	 * Determine the index of the symbol table that will be referenced by
26727c478bd9Sstevel@tonic-gate 	 * the relocation entries.
26737c478bd9Sstevel@tonic-gate 	 */
2674635216b6SRod Evans 	if (OFL_ALLOW_DYNSYM(ofl))
26757c478bd9Sstevel@tonic-gate 		/* LINTED */
26767c478bd9Sstevel@tonic-gate 		ndx = (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn);
26777c478bd9Sstevel@tonic-gate 	else if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ))
26787c478bd9Sstevel@tonic-gate 		/* LINTED */
26797c478bd9Sstevel@tonic-gate 		ndx = (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn);
26807c478bd9Sstevel@tonic-gate 
26817c478bd9Sstevel@tonic-gate 	/*
26827c478bd9Sstevel@tonic-gate 	 * Re-initialize counters. These are used to provide relocation
26837c478bd9Sstevel@tonic-gate 	 * offsets within the output buffers.
26847c478bd9Sstevel@tonic-gate 	 */
26857c478bd9Sstevel@tonic-gate 	ofl->ofl_relocpltsz = 0;
26867c478bd9Sstevel@tonic-gate 	ofl->ofl_relocgotsz = 0;
26877c478bd9Sstevel@tonic-gate 	ofl->ofl_relocbsssz = 0;
26887c478bd9Sstevel@tonic-gate 
26897c478bd9Sstevel@tonic-gate 	/*
26907c478bd9Sstevel@tonic-gate 	 * Now that the output file is created and symbol update has occurred,
26917c478bd9Sstevel@tonic-gate 	 * process the relocations collected in process_reloc().
26927c478bd9Sstevel@tonic-gate 	 */
26937c478bd9Sstevel@tonic-gate 	if (do_sorted_outrelocs(ofl) == S_ERROR)
26947c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26957c478bd9Sstevel@tonic-gate 
2696ba2be530Sab196087 	if ((*ld_targ.t_mr.mr_do_activerelocs)(ofl) == S_ERROR)
26977c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26987c478bd9Sstevel@tonic-gate 
26991d9df23bSab196087 	if ((flags & FLG_OF_COMREL) == 0) {
270057ef7aa9SRod Evans 		Aliste	idx1;
270157ef7aa9SRod Evans 
27027c478bd9Sstevel@tonic-gate 		/*
2703635216b6SRod Evans 		 * Process the relocation sections.  For each relocation
2704635216b6SRod Evans 		 * section generated for the output image update its shdr
2705635216b6SRod Evans 		 * information to reflect the symbol table it needs (sh_link)
2706635216b6SRod Evans 		 * and the section to which the relocation must be applied
2707635216b6SRod Evans 		 * (sh_info).
27087c478bd9Sstevel@tonic-gate 		 */
270957ef7aa9SRod Evans 		for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
2710cce0e03bSab196087 			Os_desc *osp;
271157ef7aa9SRod Evans 			Aliste	idx2;
27127c478bd9Sstevel@tonic-gate 
271357ef7aa9SRod Evans 			for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
27147c478bd9Sstevel@tonic-gate 				if (osp->os_relosdesc == 0)
27157c478bd9Sstevel@tonic-gate 					continue;
27167c478bd9Sstevel@tonic-gate 
27177c478bd9Sstevel@tonic-gate 				shdr = osp->os_relosdesc->os_shdr;
27187c478bd9Sstevel@tonic-gate 				shdr->sh_link = ndx;
27197c478bd9Sstevel@tonic-gate 				/* LINTED */
27207c478bd9Sstevel@tonic-gate 				shdr->sh_info = (Word)elf_ndxscn(osp->os_scn);
27217c478bd9Sstevel@tonic-gate 			}
27227c478bd9Sstevel@tonic-gate 		}
27237c478bd9Sstevel@tonic-gate 
27247c478bd9Sstevel@tonic-gate 		/*
27257c478bd9Sstevel@tonic-gate 		 * Since the .rel[a] section is not tied to any specific
2726d326b23bSrie 		 * section, we'd not have found it above.
27277c478bd9Sstevel@tonic-gate 		 */
2728d326b23bSrie 		if ((osp = ofl->ofl_osrel) != NULL) {
2729d326b23bSrie 			shdr = osp->os_shdr;
27307c478bd9Sstevel@tonic-gate 			shdr->sh_link = ndx;
27317c478bd9Sstevel@tonic-gate 			shdr->sh_info = 0;
27327c478bd9Sstevel@tonic-gate 		}
27337c478bd9Sstevel@tonic-gate 	} else {
27347c478bd9Sstevel@tonic-gate 		/*
27357c478bd9Sstevel@tonic-gate 		 * We only have two relocation sections here, (PLT's,
27367c478bd9Sstevel@tonic-gate 		 * coalesced) so just hit them directly instead of stepping
27377c478bd9Sstevel@tonic-gate 		 * over the output sections.
27387c478bd9Sstevel@tonic-gate 		 */
2739d326b23bSrie 		if ((osp = ofl->ofl_osrelhead) != NULL) {
2740d326b23bSrie 			shdr = osp->os_shdr;
27417c478bd9Sstevel@tonic-gate 			shdr->sh_link = ndx;
27427c478bd9Sstevel@tonic-gate 			shdr->sh_info = 0;
27437c478bd9Sstevel@tonic-gate 		}
2744d326b23bSrie 		if (((osp = ofl->ofl_osplt) != NULL) && osp->os_relosdesc) {
2745d326b23bSrie 			shdr = osp->os_relosdesc->os_shdr;
27467c478bd9Sstevel@tonic-gate 			shdr->sh_link = ndx;
27477c478bd9Sstevel@tonic-gate 			/* LINTED */
2748d326b23bSrie 			shdr->sh_info = (Word)elf_ndxscn(osp->os_scn);
27497c478bd9Sstevel@tonic-gate 		}
27507c478bd9Sstevel@tonic-gate 	}
27517c478bd9Sstevel@tonic-gate 
27527c478bd9Sstevel@tonic-gate 	/*
27537c478bd9Sstevel@tonic-gate 	 * If the -z text option was given, and we have output relocations
27547c478bd9Sstevel@tonic-gate 	 * against a non-writable, allocatable section, issue a diagnostic and
27557c478bd9Sstevel@tonic-gate 	 * return (the actual entries that caused this error would have been
27567c478bd9Sstevel@tonic-gate 	 * output during the relocating section phase).
27577c478bd9Sstevel@tonic-gate 	 */
27587c478bd9Sstevel@tonic-gate 	if ((flags & (FLG_OF_PURETXT | FLG_OF_TEXTREL)) ==
27597c478bd9Sstevel@tonic-gate 	    (FLG_OF_PURETXT | FLG_OF_TEXTREL)) {
2760*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_REMAIN_3));
27617c478bd9Sstevel@tonic-gate 		return (S_ERROR);
27627c478bd9Sstevel@tonic-gate 	}
27637c478bd9Sstevel@tonic-gate 
27647c478bd9Sstevel@tonic-gate 	/*
27657c478bd9Sstevel@tonic-gate 	 * Finally, initialize the first got entry with the address of the
27667c478bd9Sstevel@tonic-gate 	 * .dynamic section (_DYNAMIC).
27677c478bd9Sstevel@tonic-gate 	 */
27687c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_DYNAMIC) {
2769ba2be530Sab196087 		if ((*ld_targ.t_mr.mr_fillin_gotplt)(ofl) == S_ERROR)
27707c478bd9Sstevel@tonic-gate 			return (S_ERROR);
27717c478bd9Sstevel@tonic-gate 	}
27727c478bd9Sstevel@tonic-gate 
2773d326b23bSrie 	/*
2774d326b23bSrie 	 * Now that any GOT information has been written, display the debugging
2775d326b23bSrie 	 * information if required.
2776d326b23bSrie 	 */
2777d326b23bSrie 	if ((osp = ofl->ofl_osgot) != NULL)
2778ba2be530Sab196087 		DBG_CALL(Dbg_got_display(ofl, osp->os_shdr->sh_addr, 1,
2779ba2be530Sab196087 		    ld_targ.t_m.m_got_xnumber, ld_targ.t_m.m_got_entsize));
2780d326b23bSrie 
27817c478bd9Sstevel@tonic-gate 	return (1);
27827c478bd9Sstevel@tonic-gate }
27837c478bd9Sstevel@tonic-gate 
27847c478bd9Sstevel@tonic-gate /*
27857c478bd9Sstevel@tonic-gate  * If the -z text option was given, and we have output relocations against a
27867c478bd9Sstevel@tonic-gate  * non-writable, allocatable section, issue a diagnostic. Print offending
27877c478bd9Sstevel@tonic-gate  * symbols in tabular form similar to the way undefined symbols are presented.
27887c478bd9Sstevel@tonic-gate  * Called from reloc_count().  The actual fatal error condition is triggered on
27897c478bd9Sstevel@tonic-gate  * in reloc_process() above.
27907c478bd9Sstevel@tonic-gate  *
27917c478bd9Sstevel@tonic-gate  * Note.  For historic reasons -ztext is not a default option (however all OS
27927c478bd9Sstevel@tonic-gate  * shared object builds use this option).  It can be argued that this option
27937c478bd9Sstevel@tonic-gate  * should also be default when generating an a.out (see 1163979).  However, if
27947c478bd9Sstevel@tonic-gate  * an a.out contains text relocations it is either because the user is creating
27957c478bd9Sstevel@tonic-gate  * something pretty weird (they've used the -b or -znodefs options), or because
27967c478bd9Sstevel@tonic-gate  * the library against which they're building wasn't constructed correctly (ie.
27977c478bd9Sstevel@tonic-gate  * a function has a NOTYPE type, in which case the a.out won't generate an
27987c478bd9Sstevel@tonic-gate  * associated plt).  In the latter case the builder of the a.out can't do
27997c478bd9Sstevel@tonic-gate  * anything to fix the error - thus we've chosen not to give the user an error,
28007c478bd9Sstevel@tonic-gate  * or warning, for this case.
28017c478bd9Sstevel@tonic-gate  */
28027c478bd9Sstevel@tonic-gate void
ld_reloc_remain_entry(Rel_desc * orsp,Os_desc * osp,Ofl_desc * ofl,Boolean * remain_seen)2803*1007fd6fSAli Bahrami ld_reloc_remain_entry(Rel_desc *orsp, Os_desc *osp, Ofl_desc *ofl,
2804*1007fd6fSAli Bahrami     Boolean *remain_seen)
28057c478bd9Sstevel@tonic-gate {
28067c478bd9Sstevel@tonic-gate 
28077c478bd9Sstevel@tonic-gate 	/*
28087c478bd9Sstevel@tonic-gate 	 * -ztextoff
28097c478bd9Sstevel@tonic-gate 	 */
28107c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags1 & FLG_OF1_TEXTOFF)
28117c478bd9Sstevel@tonic-gate 		return;
28127c478bd9Sstevel@tonic-gate 
28137c478bd9Sstevel@tonic-gate 	/*
28147c478bd9Sstevel@tonic-gate 	 * Only give relocation errors against loadable read-only segments.
28157c478bd9Sstevel@tonic-gate 	 */
2816ba2be530Sab196087 	if ((orsp->rel_rtype == ld_targ.t_m.m_r_register) || (!osp) ||
28177c478bd9Sstevel@tonic-gate 	    (osp->os_sgdesc->sg_phdr.p_type != PT_LOAD) ||
28187c478bd9Sstevel@tonic-gate 	    (osp->os_sgdesc->sg_phdr.p_flags & PF_W))
28197c478bd9Sstevel@tonic-gate 		return;
28207c478bd9Sstevel@tonic-gate 
28217c478bd9Sstevel@tonic-gate 	/*
28227c478bd9Sstevel@tonic-gate 	 * If we are in -ztextwarn mode, it's a silent error if a relocation is
28237c478bd9Sstevel@tonic-gate 	 * due to a 'WEAK REFERENCE'.  This is because if the symbol is not
28247c478bd9Sstevel@tonic-gate 	 * provided at run-time we will not perform a text-relocation.
28257c478bd9Sstevel@tonic-gate 	 */
28267c478bd9Sstevel@tonic-gate 	if (((ofl->ofl_flags & FLG_OF_PURETXT) == 0) &&
28277c478bd9Sstevel@tonic-gate 	    (ELF_ST_BIND(orsp->rel_sym->sd_sym->st_info) == STB_WEAK) &&
28280bc07c75Srie 	    (orsp->rel_sym->sd_sym->st_shndx == SHN_UNDEF))
28297c478bd9Sstevel@tonic-gate 		return;
28307c478bd9Sstevel@tonic-gate 
2831*1007fd6fSAli Bahrami 	if (*remain_seen == FALSE) {
28327c478bd9Sstevel@tonic-gate 		/*
28337c478bd9Sstevel@tonic-gate 		 * If building with '-ztext' then emit a fatal error.  If
28347c478bd9Sstevel@tonic-gate 		 * building a executable then only emit a 'warning'.
28357c478bd9Sstevel@tonic-gate 		 */
2836*1007fd6fSAli Bahrami 		const char *str1 = (ofl->ofl_flags & FLG_OF_PURETXT) ?
2837*1007fd6fSAli Bahrami 		    MSG_INTL(MSG_REL_RMN_ITM_11) : MSG_INTL(MSG_REL_RMN_ITM_13);
2838*1007fd6fSAli Bahrami 
2839*1007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_REL_REMAIN_FMT_1), str1,
2840*1007fd6fSAli Bahrami 		    MSG_INTL(MSG_REL_RMN_ITM_31), MSG_INTL(MSG_REL_RMN_ITM_12),
2841*1007fd6fSAli Bahrami 		    MSG_INTL(MSG_REL_RMN_ITM_2), MSG_INTL(MSG_REL_RMN_ITM_32));
2842*1007fd6fSAli Bahrami 
2843*1007fd6fSAli Bahrami 		*remain_seen = TRUE;
28447c478bd9Sstevel@tonic-gate 	}
28457c478bd9Sstevel@tonic-gate 
2846*1007fd6fSAli Bahrami 	ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_REL_REMAIN_2),
2847bf994817SAli Bahrami 	    ld_reloc_sym_name(orsp), EC_OFF(orsp->rel_roffset),
28485aefb655Srie 	    orsp->rel_isdesc->is_file->ifl_name);
28497c478bd9Sstevel@tonic-gate }
28507c478bd9Sstevel@tonic-gate 
28517c478bd9Sstevel@tonic-gate /*
2852d326b23bSrie  * Generic encapsulation for generating a TLS got index.
28537c478bd9Sstevel@tonic-gate  */
2854d326b23bSrie uintptr_t
ld_assign_got_TLS(Boolean local,Rel_desc * rsp,Ofl_desc * ofl,Sym_desc * sdp,Gotndx * gnp,Gotref gref,Word rflag,Word ortype,Word rtype1,Word rtype2)2855d326b23bSrie ld_assign_got_TLS(Boolean local, Rel_desc *rsp, Ofl_desc *ofl, Sym_desc *sdp,
2856d326b23bSrie     Gotndx *gnp, Gotref gref, Word rflag, Word ortype, Word rtype1, Word rtype2)
2857d326b23bSrie {
2858d326b23bSrie 	Word	rflags;
2859d326b23bSrie 
2860ba2be530Sab196087 	if ((*ld_targ.t_mr.mr_assign_got_ndx)(&(sdp->sd_GOTndxs), gnp,
2861ba2be530Sab196087 	    gref, ofl, rsp, sdp) == S_ERROR)
2862d326b23bSrie 		return (S_ERROR);
2863d326b23bSrie 
2864d326b23bSrie 	rflags = FLG_REL_GOT | rflag;
2865d326b23bSrie 	if (local)
2866d326b23bSrie 		rflags |= FLG_REL_SCNNDX;
2867d326b23bSrie 	rsp->rel_rtype = rtype1;
2868d326b23bSrie 
2869ba2be530Sab196087 	if ((*ld_targ.t_mr.mr_add_outrel)(rflags, rsp, ofl) == S_ERROR)
2870d326b23bSrie 		return (S_ERROR);
2871d326b23bSrie 
2872d326b23bSrie 	if (local && (gref == GOT_REF_TLSIE)) {
2873d326b23bSrie 		/*
2874d326b23bSrie 		 * If this is a local LE TLS symbol, then the symbol won't be
2875d326b23bSrie 		 * available at runtime.  The value of the local symbol will
2876d326b23bSrie 		 * be placed in the associated got entry, and the got
2877d326b23bSrie 		 * relocation is reassigned to a section symbol.
2878d326b23bSrie 		 */
2879d326b23bSrie 		if (ld_add_actrel(rflags, rsp, ofl) == S_ERROR)
2880d326b23bSrie 			return (S_ERROR);
2881d326b23bSrie 	}
2882d326b23bSrie 
2883d326b23bSrie 	if (rtype2) {
2884d326b23bSrie 		rflags = FLG_REL_GOT | rflag;
2885d326b23bSrie 		rsp->rel_rtype = rtype2;
2886d326b23bSrie 
2887d326b23bSrie 		if (local) {
2888d326b23bSrie 			if (ld_add_actrel(rflags, rsp, ofl) == S_ERROR)
2889d326b23bSrie 				return (S_ERROR);
2890d326b23bSrie 		} else {
2891ba2be530Sab196087 			if ((*ld_targ.t_mr.mr_add_outrel)(rflags, rsp, ofl) ==
2892ba2be530Sab196087 			    S_ERROR)
2893d326b23bSrie 				return (S_ERROR);
2894d326b23bSrie 		}
2895d326b23bSrie 	}
2896d326b23bSrie 
2897d326b23bSrie 	rsp->rel_rtype = ortype;
2898d326b23bSrie 
2899d326b23bSrie 	return (1);
2900d326b23bSrie }
29017c478bd9Sstevel@tonic-gate 
29027c478bd9Sstevel@tonic-gate /*
29037c478bd9Sstevel@tonic-gate  * Move Section related function
29047c478bd9Sstevel@tonic-gate  */
290557ef7aa9SRod Evans static void
newroffset_for_move(Sym_desc * sdp,Move * mvp,Xword offset1,Xword * offset2)290657ef7aa9SRod Evans newroffset_for_move(Sym_desc *sdp, Move *mvp, Xword offset1, Xword *offset2)
29077c478bd9Sstevel@tonic-gate {
290857ef7aa9SRod Evans 	Mv_desc		*mdp;
290957ef7aa9SRod Evans 	Aliste		idx;
29107c478bd9Sstevel@tonic-gate 
29117c478bd9Sstevel@tonic-gate 	/*
291257ef7aa9SRod Evans 	 * Search for matching move entry.
29137c478bd9Sstevel@tonic-gate 	 */
291457ef7aa9SRod Evans 	for (ALIST_TRAVERSE(sdp->sd_move, idx, mdp)) {
291557ef7aa9SRod Evans 		if (mdp->md_move == mvp) {
29167c478bd9Sstevel@tonic-gate 			/*
29177c478bd9Sstevel@tonic-gate 			 * Update r_offset
29187c478bd9Sstevel@tonic-gate 			 */
291957ef7aa9SRod Evans 			*offset2 = (Xword)((mdp->md_oidx - 1) * sizeof (Move) +
29207c478bd9Sstevel@tonic-gate 			    offset1 % sizeof (Move));
292157ef7aa9SRod Evans 			return;
292257ef7aa9SRod Evans 		}
292357ef7aa9SRod Evans 	}
29247c478bd9Sstevel@tonic-gate }
29257c478bd9Sstevel@tonic-gate 
29267c478bd9Sstevel@tonic-gate void
ld_adj_movereloc(Ofl_desc * ofl,Rel_desc * arsp)29275aefb655Srie ld_adj_movereloc(Ofl_desc *ofl, Rel_desc *arsp)
29287c478bd9Sstevel@tonic-gate {
2929bf994817SAli Bahrami 	Move		*move = arsp->rel_aux->ra_move->mr_move;
2930bf994817SAli Bahrami 	Sym_desc	*psdp = arsp->rel_aux->ra_move->mr_sym;
29317c478bd9Sstevel@tonic-gate 	Xword		newoffset;
29327c478bd9Sstevel@tonic-gate 
29337c478bd9Sstevel@tonic-gate 	if (arsp->rel_flags & FLG_REL_MOVETAB) {
29347c478bd9Sstevel@tonic-gate 		/*
29357c478bd9Sstevel@tonic-gate 		 * We are relocating the move table itself.
29367c478bd9Sstevel@tonic-gate 		 */
293757ef7aa9SRod Evans 		newroffset_for_move(psdp, move, arsp->rel_roffset,
29387c478bd9Sstevel@tonic-gate 		    &newoffset);
29395aefb655Srie 		DBG_CALL(Dbg_move_adjmovereloc(ofl->ofl_lml, arsp->rel_roffset,
29405aefb655Srie 		    newoffset, psdp->sd_name));
29417c478bd9Sstevel@tonic-gate 		arsp->rel_roffset = newoffset;
29427c478bd9Sstevel@tonic-gate 	} else {
29437c478bd9Sstevel@tonic-gate 		/*
29447c478bd9Sstevel@tonic-gate 		 * We are expanding the partial symbol.  So we are generating
29457c478bd9Sstevel@tonic-gate 		 * the relocation entry relocating the expanded partial symbol.
29467c478bd9Sstevel@tonic-gate 		 */
29475aefb655Srie 		arsp->rel_roffset += psdp->sd_sym->st_value -
294835450702SAli Bahrami 		    ofl->ofl_isparexpn->is_osdesc->os_shdr->sh_addr;
29495aefb655Srie 		DBG_CALL(Dbg_move_adjexpandreloc(ofl->ofl_lml,
29505aefb655Srie 		    arsp->rel_roffset, psdp->sd_name));
29517c478bd9Sstevel@tonic-gate 	}
29527c478bd9Sstevel@tonic-gate }
29537c478bd9Sstevel@tonic-gate 
29547c478bd9Sstevel@tonic-gate /*
29557c478bd9Sstevel@tonic-gate  * Partially Initialized Symbol Handling routines
2956635216b6SRod Evans  * For RELA architecture, the second argument is reld->rel_raddend.  For REL
2957635216b6SRod Evans  * architecure, the second argument is the value stored at the relocation
2958635216b6SRod Evans  * target address.
29597c478bd9Sstevel@tonic-gate  */
29607c478bd9Sstevel@tonic-gate Sym_desc *
ld_am_I_partial(Rel_desc * reld,Xword val)29615aefb655Srie ld_am_I_partial(Rel_desc *reld, Xword val)
29627c478bd9Sstevel@tonic-gate {
29637c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifile = reld->rel_sym->sd_isc->is_file;
29647c478bd9Sstevel@tonic-gate 	int 		nlocs = ifile->ifl_locscnt, i;
29657c478bd9Sstevel@tonic-gate 
29667c478bd9Sstevel@tonic-gate 	for (i = 1; i < nlocs; i++) {
29677c478bd9Sstevel@tonic-gate 		Sym		*osym;
29687c478bd9Sstevel@tonic-gate 		Sym_desc	*symd = ifile->ifl_oldndx[i];
29697c478bd9Sstevel@tonic-gate 
29707c478bd9Sstevel@tonic-gate 		if ((osym = symd->sd_osym) == 0)
29717c478bd9Sstevel@tonic-gate 			continue;
29727c478bd9Sstevel@tonic-gate 		if ((symd->sd_flags & FLG_SY_PAREXPN) == 0)
29737c478bd9Sstevel@tonic-gate 			continue;
29747c478bd9Sstevel@tonic-gate 		if ((osym->st_value <= val) &&
29757c478bd9Sstevel@tonic-gate 		    (osym->st_value + osym->st_size > val))
29767c478bd9Sstevel@tonic-gate 			return (symd);
29777c478bd9Sstevel@tonic-gate 	}
297857ef7aa9SRod Evans 	return (NULL);
29797c478bd9Sstevel@tonic-gate }
29807c478bd9Sstevel@tonic-gate 
2981ba2be530Sab196087 /*
2982ba2be530Sab196087  * Return True (1) if the code processing the given relocation
2983ba2be530Sab196087  * needs to perform byte swapping when accessing the section data.
2984ba2be530Sab196087  */
2985ba2be530Sab196087 int
ld_swap_reloc_data(Ofl_desc * ofl,Rel_desc * rsp)2986ba2be530Sab196087 ld_swap_reloc_data(Ofl_desc *ofl, Rel_desc *rsp)
2987ba2be530Sab196087 {
2988ba2be530Sab196087 	/*
2989ba2be530Sab196087 	 * In a cross-link situation where the linker host and target
2990ba2be530Sab196087 	 * have opposite byte orders, it can be necessary to swap bytes
2991ba2be530Sab196087 	 * when doing relocation processing. This is indicated by the
2992ba2be530Sab196087 	 * presence of the FLG_OF1_ENCDIFF flag bit. However, swapping
2993ba2be530Sab196087 	 * is only needed for the section types that libelf doesn't
2994ba2be530Sab196087 	 * automatically xlate.
2995ba2be530Sab196087 	 */
2996ba2be530Sab196087 	if ((ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0) {
2997bf994817SAli Bahrami 		switch (RELAUX_GET_OSDESC(rsp)->os_shdr->sh_type) {
2998ba2be530Sab196087 		case SHT_PROGBITS:
2999ba2be530Sab196087 			return (1);
3000ba2be530Sab196087 
3001ba2be530Sab196087 		case SHT_SPARC_GOTDATA:
3002ba2be530Sab196087 			if (ld_targ.t_m.m_mach ==
3003ba2be530Sab196087 			    LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9))
3004ba2be530Sab196087 				return (1);
3005ba2be530Sab196087 			break;
3006ba2be530Sab196087 
3007ba2be530Sab196087 		case SHT_AMD64_UNWIND:
3008ba2be530Sab196087 			if (ld_targ.t_m.m_mach == EM_AMD64)
3009ba2be530Sab196087 				return (1);
3010ba2be530Sab196087 			break;
3011ba2be530Sab196087 		}
3012ba2be530Sab196087 	}
3013ba2be530Sab196087 
3014ba2be530Sab196087 	/*
3015ba2be530Sab196087 	 * If FLG_OF1_ENCDIFF isn't set, or the section isn't
3016ba2be530Sab196087 	 * progbits (or similar), then no swapping is needed.
3017ba2be530Sab196087 	 */
3018ba2be530Sab196087 	return (0);
3019ba2be530Sab196087 }
3020ba2be530Sab196087 
3021ba2be530Sab196087 
3022ba2be530Sab196087 
3023cce0e03bSab196087 /*
3024cce0e03bSab196087  * Obtain the current value at the given relocation target.
3025cce0e03bSab196087  *
3026cce0e03bSab196087  * entry:
3027cce0e03bSab196087  *	ofl - Output file descriptor
3028cce0e03bSab196087  *	rsp - Relocation record
3029cce0e03bSab196087  *	data - Pointer to relocation target
3030cce0e03bSab196087  *	value - Address of variable to recieve value
3031cce0e03bSab196087  *
3032cce0e03bSab196087  * exit:
3033cce0e03bSab196087  *	The value of the data at the relocation target has
3034cce0e03bSab196087  *	been stored in value.
3035cce0e03bSab196087  */
3036cce0e03bSab196087 int
ld_reloc_targval_get(Ofl_desc * ofl,Rel_desc * rsp,uchar_t * data,Xword * value)3037cce0e03bSab196087 ld_reloc_targval_get(Ofl_desc *ofl, Rel_desc *rsp, uchar_t *data, Xword *value)
3038cce0e03bSab196087 {
3039cce0e03bSab196087 	const Rel_entry	*rep;
3040cce0e03bSab196087 
3041ba2be530Sab196087 	rep = &ld_targ.t_mr.mr_reloc_table[rsp->rel_rtype];
3042cce0e03bSab196087 
3043cce0e03bSab196087 	switch (rep->re_fsize) {
3044cce0e03bSab196087 	case 1:
3045cce0e03bSab196087 		/* LINTED */
3046cce0e03bSab196087 		*value = (Xword) *((uchar_t *)data);
3047cce0e03bSab196087 		break;
3048cce0e03bSab196087 	case 2:
3049ba2be530Sab196087 		{
3050ba2be530Sab196087 			Half	v;
3051ba2be530Sab196087 			uchar_t	*v_bytes = (uchar_t *)&v;
3052ba2be530Sab196087 
3053ba2be530Sab196087 			if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
3054ba2be530Sab196087 				UL_ASSIGN_BSWAP_HALF(v_bytes, data);
3055ba2be530Sab196087 			} else {
3056ba2be530Sab196087 				UL_ASSIGN_HALF(v_bytes, data);
3057ba2be530Sab196087 			}
3058ba2be530Sab196087 			*value = (Xword) v;
3059ba2be530Sab196087 		}
3060cce0e03bSab196087 		break;
3061cce0e03bSab196087 	case 4:
3062ba2be530Sab196087 		{
3063ba2be530Sab196087 			Word	v;
3064ba2be530Sab196087 			uchar_t	*v_bytes = (uchar_t *)&v;
3065ba2be530Sab196087 
3066ba2be530Sab196087 			if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
3067ba2be530Sab196087 				UL_ASSIGN_BSWAP_WORD(v_bytes, data);
3068ba2be530Sab196087 			} else {
3069ba2be530Sab196087 				UL_ASSIGN_WORD(v_bytes, data);
3070ba2be530Sab196087 			}
3071ba2be530Sab196087 			*value = (Xword) v;
3072ba2be530Sab196087 		}
3073cce0e03bSab196087 		break;
3074cce0e03bSab196087 	default:
3075ba2be530Sab196087 		{
3076ba2be530Sab196087 			Conv_inv_buf_t inv_buf;
3077*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ),
3078ba2be530Sab196087 			    conv_reloc_type(ld_targ.t_m.m_mach, rsp->rel_rtype,
3079ba2be530Sab196087 			    0, &inv_buf), rsp->rel_isdesc->is_file->ifl_name,
3080bf994817SAli Bahrami 			    ld_reloc_sym_name(rsp), (int)rep->re_fsize);
3081ba2be530Sab196087 		}
3082cce0e03bSab196087 		return (0);
3083cce0e03bSab196087 	}
3084cce0e03bSab196087 	return (1);
3085cce0e03bSab196087 }
3086cce0e03bSab196087 
3087cce0e03bSab196087 
3088cce0e03bSab196087 /*
3089cce0e03bSab196087  * Set the value at the given relocation target.
3090cce0e03bSab196087  *
3091cce0e03bSab196087  * entry:
3092cce0e03bSab196087  *	ofl - Output file descriptor
3093cce0e03bSab196087  *	rsp - Relocation record
3094cce0e03bSab196087  *	data - Pointer to relocation target
3095cce0e03bSab196087  *	value - Address of variable to recieve value
3096cce0e03bSab196087  *
3097cce0e03bSab196087  * exit:
3098cce0e03bSab196087  *	The value of the data at the relocation target has
3099cce0e03bSab196087  *	been stored in value.
3100cce0e03bSab196087  */
3101cce0e03bSab196087 int
ld_reloc_targval_set(Ofl_desc * ofl,Rel_desc * rsp,uchar_t * data,Xword value)3102cce0e03bSab196087 ld_reloc_targval_set(Ofl_desc *ofl, Rel_desc *rsp, uchar_t *data, Xword value)
3103cce0e03bSab196087 {
3104cce0e03bSab196087 	const Rel_entry	*rep;
3105cce0e03bSab196087 
3106ba2be530Sab196087 	rep = &ld_targ.t_mr.mr_reloc_table[rsp->rel_rtype];
3107cce0e03bSab196087 
3108cce0e03bSab196087 	switch (rep->re_fsize) {
3109cce0e03bSab196087 	case 1:
3110cce0e03bSab196087 		/* LINTED */
3111cce0e03bSab196087 		*((uchar_t *)data) = (uchar_t)value;
3112cce0e03bSab196087 		break;
3113cce0e03bSab196087 	case 2:
3114ba2be530Sab196087 		{
3115ba2be530Sab196087 			Half	v = (Half)value;
3116ba2be530Sab196087 			uchar_t	*v_bytes = (uchar_t *)&v;
3117ba2be530Sab196087 
3118ba2be530Sab196087 			if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
3119ba2be530Sab196087 				UL_ASSIGN_BSWAP_HALF(data, v_bytes);
3120ba2be530Sab196087 			} else {
3121ba2be530Sab196087 				UL_ASSIGN_HALF(data, v_bytes);
3122ba2be530Sab196087 			}
3123ba2be530Sab196087 		}
3124cce0e03bSab196087 		break;
3125cce0e03bSab196087 	case 4:
3126ba2be530Sab196087 		{
3127ba2be530Sab196087 			Word	v = (Word)value;
3128ba2be530Sab196087 			uchar_t	*v_bytes = (uchar_t *)&v;
3129ba2be530Sab196087 
3130ba2be530Sab196087 			if (OFL_SWAP_RELOC_DATA(ofl, rsp)) {
3131ba2be530Sab196087 				UL_ASSIGN_BSWAP_WORD(data, v_bytes);
3132ba2be530Sab196087 			} else {
3133ba2be530Sab196087 				UL_ASSIGN_WORD(data, v_bytes);
3134ba2be530Sab196087 			}
3135ba2be530Sab196087 		}
3136cce0e03bSab196087 		break;
3137cce0e03bSab196087 	default:
3138ba2be530Sab196087 		{
3139ba2be530Sab196087 			Conv_inv_buf_t inv_buf;
3140*1007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ),
3141ba2be530Sab196087 			    conv_reloc_type(ld_targ.t_m.m_mach, rsp->rel_rtype,
3142ba2be530Sab196087 			    0, &inv_buf), rsp->rel_isdesc->is_file->ifl_name,
3143bf994817SAli Bahrami 			    ld_reloc_sym_name(rsp), (int)rep->re_fsize);
3144ba2be530Sab196087 		}
3145cce0e03bSab196087 		return (0);
3146cce0e03bSab196087 	}
3147cce0e03bSab196087 	return (1);
3148cce0e03bSab196087 }
3149cce0e03bSab196087 
3150cce0e03bSab196087 
31517c478bd9Sstevel@tonic-gate /*
31527c478bd9Sstevel@tonic-gate  * Because of the combinations of 32-bit lib providing 64-bit support, and
31537c478bd9Sstevel@tonic-gate  * visa-versa, the use of krtld's dorelocs can result in differing message
31547c478bd9Sstevel@tonic-gate  * requirements that make msg.c/msg.h creation and chkmsg "interesting".
31557c478bd9Sstevel@tonic-gate  * Thus the actual message files contain a couple of entries to satisfy
31567c478bd9Sstevel@tonic-gate  * each architectures build.  Here we add dummy calls to quieten chkmsg.
31577c478bd9Sstevel@tonic-gate  *
31587c478bd9Sstevel@tonic-gate  * chkmsg: MSG_INTL(MSG_REL_NOFIT)
31597c478bd9Sstevel@tonic-gate  * chkmsg: MSG_INTL(MSG_REL_NONALIGN)
31607c478bd9Sstevel@tonic-gate  */
3161