xref: /titanic_51/usr/src/cmd/sgs/libld/common/relocate.c (revision 5c88ba20fc79ecf19255b4a04f03d77630b6d0e7)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  *	Copyright (c) 1988 AT&T
25  *	  All Rights Reserved
26  *
27  *
28  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
29  * Use is subject to license terms.
30  */
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /*
34  * set-up for relocations
35  */
36 #include	<string.h>
37 #include	<stdio.h>
38 #include	<alloca.h>
39 #include	"debug.h"
40 #include	"reloc.h"
41 #include	"msg.h"
42 #include	"_libld.h"
43 
44 /*
45  * Structure to hold copy relocation items.
46  */
47 typedef struct copy_rel {
48 	Sym_desc *	copyrel_symd;	/* symbol descriptor to be copied */
49 	Addr 		copyrel_stval;	/* Original symbol value */
50 } Copy_rel;
51 
52 /*
53  * For each copy relocation symbol, determine if the symbol is:
54  * 	1) to be *disp* relocated at runtime
55  *	2) a reference symbol for *disp* relocation
56  *	3) possibly *disp* relocated at ld time.
57  *
58  * The first and the second are serious errors.
59  */
60 static void
61 is_disp_copied(Ofl_desc *ofl, Copy_rel *cpy)
62 {
63 	Ifl_desc	*ifl = cpy->copyrel_symd->sd_file;
64 	Sym_desc	*sdp = cpy->copyrel_symd;
65 	Is_desc		*irel;
66 	Addr		symaddr = cpy->copyrel_stval;
67 	Listnode	*lnp1;
68 
69 	/*
70 	 * This symbol may not be *disp* relocated at run time, but could
71 	 * already have been *disp* relocated when the shared object was
72 	 * created.  Warn the user.
73 	 */
74 	if ((ifl->ifl_flags & FLG_IF_DISPDONE) &&
75 	    (ofl->ofl_flags & FLG_OF_VERBOSE))
76 		eprintf(ERR_WARNING, MSG_INTL(MSG_REL_DISPREL2),
77 		    conv_reloc_type_str(ifl->ifl_ehdr->e_machine, M_R_COPY),
78 		    ifl->ifl_name, demangle(sdp->sd_name));
79 
80 	if ((ifl->ifl_flags & FLG_IF_DISPPEND) == 0)
81 		return;
82 
83 	/*
84 	 * Traverse the input relocation sections.
85 	 */
86 	for (LIST_TRAVERSE(&ifl->ifl_relsect, lnp1, irel)) {
87 		Sym_desc	*rsdp;
88 		Is_desc		*trel;
89 		Rel		*rend, *reloc;
90 		Xword		rsize, entsize;
91 
92 		trel = ifl->ifl_isdesc[irel->is_shdr->sh_info];
93 		rsize = irel->is_shdr->sh_size;
94 		entsize = irel->is_shdr->sh_entsize;
95 		reloc = (Rel *)irel->is_indata->d_buf;
96 
97 		/*
98 		 * Decide entry size
99 		 */
100 		if ((entsize == 0) || (entsize > rsize)) {
101 			if (irel->is_shdr->sh_type == SHT_RELA)
102 				entsize = sizeof (Rela);
103 			else
104 				entsize = sizeof (Rel);
105 		}
106 
107 		/*
108 		 * Traverse the relocation entries.
109 		 */
110 		for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize);
111 		    reloc < rend;
112 		    reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) {
113 			const char	*str;
114 			Word		rstndx;
115 
116 			if (IS_PC_RELATIVE(ELF_R_TYPE(reloc->r_info)) == 0)
117 				continue;
118 
119 			/*
120 			 * First, check if this symbol is reference symbol
121 			 * for this relocation entry.
122 			 */
123 			rstndx = (Word) ELF_R_SYM(reloc->r_info);
124 			rsdp = ifl->ifl_oldndx[rstndx];
125 			if (rsdp == sdp) {
126 				if ((str = demangle(rsdp->sd_name)) !=
127 				    rsdp->sd_name) {
128 					char	*_str = alloca(strlen(str) + 1);
129 					(void) strcpy(_str, str);
130 					str = (const char *)_str;
131 				}
132 				eprintf(ERR_WARNING, MSG_INTL(MSG_REL_DISPREL1),
133 				    conv_reloc_type_str(
134 				    ifl->ifl_ehdr->e_machine,
135 				    (uint_t)ELF_R_TYPE(reloc->r_info)),
136 				    ifl->ifl_name, str,
137 				    MSG_INTL(MSG_STR_UNKNOWN),
138 				    EC_XWORD(reloc->r_offset),
139 				    demangle(sdp->sd_name));
140 			}
141 
142 			/*
143 			 * Then check if this relocation entry is relocating
144 			 * this symbol.
145 			 */
146 			if ((sdp->sd_isc != trel) ||
147 			    (reloc->r_offset < symaddr) ||
148 			    (reloc->r_offset >=
149 			    (symaddr + sdp->sd_sym->st_size)))
150 				continue;
151 
152 			/*
153 			 * This symbol is truely *disp* relocated, so should
154 			 * really be fixed by user.
155 			 */
156 			if ((str = demangle(sdp->sd_name)) != sdp->sd_name) {
157 				char	*_str = alloca(strlen(str) + 1);
158 				(void) strcpy(_str, str);
159 				str = (const char *)_str;
160 			}
161 			eprintf(ERR_WARNING, MSG_INTL(MSG_REL_DISPREL1),
162 			    conv_reloc_type_str(ifl->ifl_ehdr->e_machine,
163 			    (uint_t)ELF_R_TYPE(reloc->r_info)), ifl->ifl_name,
164 			    demangle(rsdp->sd_name), str,
165 			    EC_XWORD(reloc->r_offset), str);
166 		}
167 	}
168 }
169 
170 /*
171  * The number of symbols provided by some objects can be very large.  Use a
172  * binary search to match the associated value to a symbol table entry.
173  */
174 static int
175 disp_bsearch(const void *key, const void *array)
176 {
177 	Addr		kvalue, avalue;
178 	Ssv_desc	*ssvp = (Ssv_desc *)array;
179 
180 	kvalue = *((Addr *)key);
181 	avalue = ssvp->ssv_value;
182 
183 	if (avalue > kvalue)
184 		return (-1);
185 	if ((avalue < kvalue) &&
186 	    ((avalue + ssvp->ssv_sdp->sd_sym->st_size) <= kvalue))
187 		return (1);
188 	return (0);
189 }
190 
191 /*
192  * Given a sorted list of symbols, look for a symbol in which the relocation
193  * offset falls between the [sym.st_value - sym.st_value + sym.st_size].  Since
194  * the symbol list is maintained in sorted order,  we can bail once the
195  * relocation offset becomes less than the symbol values.  The symbol is
196  * returned for use in error diagnostics.
197  */
198 static Sym_desc *
199 disp_scansyms(Ifl_desc * ifl, Rel_desc *rld, Boolean rlocal, int inspect,
200     Ofl_desc * ofl)
201 {
202 	Sym_desc	*tsdp, *rsdp;
203 	Sym		*rsym, *tsym;
204 	Ssv_desc	*ssvp;
205 	uchar_t		rtype, ttype;
206 	Addr		value;
207 
208 	/*
209 	 * Sorted symbol values have been uniquified by adding their associated
210 	 * section offset.  Uniquify the relocation offset by adding its
211 	 * associated section offset, and search for the symbol.
212 	 */
213 	value = rld->rel_roffset;
214 	if (rld->rel_isdesc->is_shdr)
215 		value += rld->rel_isdesc->is_shdr->sh_offset;
216 
217 	if ((ssvp = bsearch((void *)&value, (void *)ifl->ifl_sortsyms,
218 	    ifl->ifl_sortcnt, sizeof (Ssv_desc), &disp_bsearch)) != 0)
219 		tsdp = ssvp->ssv_sdp;
220 	else
221 		tsdp = 0;
222 
223 	if (inspect)
224 		return (tsdp);
225 
226 	/*
227 	 * Determine the relocation reference symbol and its type.
228 	 */
229 	rsdp = rld->rel_sym;
230 	rsym = rsdp->sd_sym;
231 	rtype = ELF_ST_TYPE(rsym->st_info);
232 
233 	/*
234 	 * If there is no target symbol to match the relocation offset, then the
235 	 * offset is effectively local data.  If the relocation symbol is global
236 	 * data we have a potential for this displacement relocation to be
237 	 * invalidated should the global symbol be copied.
238 	 */
239 	if (tsdp == 0) {
240 		if ((rlocal == TRUE) ||
241 		    ((rtype != STT_OBJECT) && (rtype != STT_SECTION)))
242 		return (tsdp);
243 	} else {
244 		/*
245 		 * If both symbols are local, no copy relocations can occur to
246 		 * either.
247 		 */
248 		if ((rlocal == TRUE) && ((tsdp->sd_flags1 & FLG_SY1_LOCL) ||
249 		    ((ofl->ofl_flags & FLG_OF_AUTOLCL) &&
250 		    (tsdp->sd_flags1 & FLG_SY1_GLOB) == 0) ||
251 		    (ELF_ST_BIND(tsdp->sd_sym->st_info) != STB_GLOBAL)))
252 			return (tsdp);
253 
254 		/*
255 		 * Determine the relocation target symbols type.
256 		 */
257 		tsym = tsdp->sd_sym;
258 		ttype = ELF_ST_TYPE(tsym->st_info);
259 
260 		/*
261 		 * One of the symbols must reference a data element.
262 		 */
263 		if ((rtype != STT_OBJECT) && (rtype != STT_SECTION) &&
264 		    (ttype != STT_OBJECT) && (ttype != STT_SECTION))
265 			return (tsdp);
266 	}
267 
268 	/*
269 	 * We have two global symbols, at least one of which is a data item.
270 	 * The last case where a displacement relocation can be ignored, is
271 	 * if the reference symbol is included in the target symbol.
272 	 */
273 	value = rsym->st_value;
274 	value += rld->rel_raddend;
275 
276 	if ((rld->rel_roffset >= value) &&
277 	    (rld->rel_roffset < (value + rsym->st_size)))
278 		return (tsdp);
279 
280 	/*
281 	 * We have a displacement relocation that could be compromised by a
282 	 * copy relocation of one of the associated data items.
283 	 */
284 	rld->rel_flags |= FLG_REL_DISP;
285 	return (tsdp);
286 }
287 
288 void
289 disp_errmsg(const char *msg, Rel_desc *rsp, Ofl_desc *ofl)
290 {
291 	Sym_desc	*sdp;
292 	const char	*str;
293 	Ifl_desc	*ifl = rsp->rel_isdesc->is_file;
294 
295 	if ((sdp = disp_scansyms(ifl, rsp, 0, 1, ofl)) != 0)
296 		str = demangle(sdp->sd_name);
297 	else
298 		str = MSG_INTL(MSG_STR_UNKNOWN);
299 
300 	eprintf(ERR_WARNING, msg, conv_reloc_type_str(ifl->ifl_ehdr->e_machine,
301 	    rsp->rel_rtype), ifl->ifl_name, rsp->rel_sname, str,
302 	    EC_OFF(rsp->rel_roffset));
303 }
304 
305 /*
306  * qsort(3C) comparison routine used for the disp_sortsyms().
307  */
308 static int
309 disp_qsort(const void * s1, const void * s2)
310 {
311 	Ssv_desc	*ssvp1 = ((Ssv_desc *)s1);
312 	Ssv_desc	*ssvp2 = ((Ssv_desc *)s2);
313 	Addr		val1 = ssvp1->ssv_value;
314 	Addr		val2 = ssvp2->ssv_value;
315 
316 	if (val1 > val2)
317 		return (1);
318 	if (val1 < val2)
319 		return (-1);
320 	return (0);
321 }
322 
323 /*
324  * Determine whether a displacement relocation is between a local and global
325  * symbol pair.  One symbol is used to perform the relocation, and the other
326  * is the destination offset of the relocation.
327  */
328 static uintptr_t
329 disp_inspect(Ofl_desc *ofl, Rel_desc *rld, Boolean rlocal)
330 {
331 	Is_desc		*isp = rld->rel_isdesc;
332 	Ifl_desc	*ifl = rld->rel_isdesc->is_file;
333 
334 	/*
335 	 * If the input files symbols haven't been sorted yet, do so.
336 	 */
337 	if (ifl->ifl_sortsyms == 0) {
338 		Word	ondx, nndx;
339 
340 		if ((ifl->ifl_sortsyms = libld_malloc((ifl->ifl_symscnt + 1) *
341 		    sizeof (Ssv_desc))) == 0)
342 			return (S_ERROR);
343 
344 		for (ondx = 0, nndx = 0; ondx < ifl->ifl_symscnt; ondx++) {
345 			Sym_desc	*sdp;
346 			Addr		value;
347 
348 			/*
349 			 * As symbol resolution has already occurred, various
350 			 * symbols from this object may have been satisfied
351 			 * from other objects.  Only select symbols from this
352 			 * object.  For the displacement test, we only really
353 			 * need to observe data definitions, however, later as
354 			 * part of providing warning disgnostics, relating the
355 			 * relocation offset to a symbol is desirable.  Thus,
356 			 * collect all symbols that define a memory area.
357 			 */
358 			if (((sdp = ifl->ifl_oldndx[ondx]) == 0) ||
359 			    (sdp->sd_shndx == SHN_UNDEF) ||
360 			    (sdp->sd_shndx >= SHN_LORESERVE) ||
361 			    (sdp->sd_ref != REF_REL_NEED) ||
362 			    (sdp->sd_file != ifl) ||
363 			    (sdp->sd_sym->st_size == 0))
364 				continue;
365 
366 			/*
367 			 * As a further optimization for later checking, mark
368 			 * this section if this a global data definition.
369 			 */
370 			if (sdp->sd_isc && (ondx >= ifl->ifl_locscnt))
371 				sdp->sd_isc->is_flags |= FLG_IS_GDATADEF;
372 
373 			/*
374 			 * Capture the symbol.  Within relocatable objects, a
375 			 * symbols value is its offset within its associated
376 			 * section.  Add the section offset to this value to
377 			 * uniquify the symbol.
378 			 */
379 			value = sdp->sd_sym->st_value;
380 			if (sdp->sd_isc && sdp->sd_isc->is_shdr)
381 				value += sdp->sd_isc->is_shdr->sh_offset;
382 
383 			ifl->ifl_sortsyms[nndx].ssv_value = value;
384 			ifl->ifl_sortsyms[nndx].ssv_sdp = sdp;
385 			nndx++;
386 		}
387 
388 		/*
389 		 * Sort the list based on the symbols value (address).
390 		 */
391 		if ((ifl->ifl_sortcnt = nndx) != 0)
392 			qsort(ifl->ifl_sortsyms, nndx, sizeof (Ssv_desc),
393 			    &disp_qsort);
394 	}
395 
396 	/*
397 	 * If the reference symbol is local, and the section being relocated
398 	 * contains no global definitions, neither can be the target of a copy
399 	 * relocation.
400 	 */
401 	if ((rlocal == FALSE) && ((isp->is_flags & FLG_IS_GDATADEF) == 0))
402 		return (1);
403 
404 	/*
405 	 * Otherwise determine whether this relocation symbol and its offset
406 	 * could be candidates for a copy relocation.
407 	 */
408 	if (ifl->ifl_sortcnt)
409 		(void) disp_scansyms(ifl, rld, rlocal, 0, ofl);
410 	return (1);
411 }
412 
413 uintptr_t
414 reloc_GOT_relative(Boolean local, Rel_desc *rsp, Ofl_desc *ofl)
415 {
416 	Sym_desc	*sdp;
417 	Word		flags = ofl->ofl_flags;
418 	Gotndx		*gnp;
419 
420 	sdp = rsp->rel_sym;
421 
422 	/*
423 	 * If this is the first time we've seen this symbol in a GOT
424 	 * relocation we need to assign it a GOT token.  Once we've got
425 	 * all of the GOT's assigned we can assign the actual indexes.
426 	 */
427 	if ((gnp = find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_GENERIC,
428 	    ofl, rsp)) == 0) {
429 		Word	rtype = rsp->rel_rtype;
430 
431 		if (assign_gotndx(&(sdp->sd_GOTndxs), 0, GOT_REF_GENERIC,
432 		    ofl, rsp, sdp) == S_ERROR)
433 			return (S_ERROR);
434 
435 		/*
436 		 * Now we initialize the GOT table entry.
437 		 *
438 		 * Pseudo code to describe the the decisions below:
439 		 *
440 		 * If (local)
441 		 * then
442 		 *	enter symbol value in GOT table entry
443 		 *	if (Shared Object)
444 		 *	then
445 		 *		create Relative relocation against symbol
446 		 *	fi
447 		 * else
448 		 *	clear GOT table entry
449 		 *	create a GLOB_DAT relocation against symbol
450 		 * fi
451 		 */
452 		if (local == TRUE) {
453 			if (flags & FLG_OF_SHAROBJ) {
454 				if (add_actrel((FLG_REL_GOT | FLG_REL_GOTCL),
455 				    rsp, ofl) == S_ERROR)
456 					return (S_ERROR);
457 
458 				/*
459 				 * Add a RELATIVE relocation if this is
460 				 * anything but a ABS symbol.
461 				 */
462 				if ((((sdp->sd_flags & FLG_SY_SPECSEC) == 0) ||
463 				    (sdp->sd_shndx != SHN_ABS)) ||
464 				    (sdp->sd_aux && sdp->sd_aux->sa_symspec)) {
465 					rsp->rel_rtype = M_R_RELATIVE;
466 					if (add_outrel((FLG_REL_GOT |
467 					    FLG_REL_ADVAL), rsp,
468 					    ofl) == S_ERROR)
469 						return (S_ERROR);
470 					rsp->rel_rtype = rtype;
471 				}
472 			} else {
473 				if (add_actrel(FLG_REL_GOT, rsp,
474 				    ofl) == S_ERROR)
475 					return (S_ERROR);
476 			}
477 		} else {
478 			rsp->rel_rtype = M_R_GLOB_DAT;
479 			if (add_outrel(FLG_REL_GOT, rsp, ofl) == S_ERROR)
480 				return (S_ERROR);
481 			rsp->rel_rtype = rtype;
482 		}
483 	} else {
484 		if (assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_GENERIC,
485 		    ofl, rsp, sdp) == S_ERROR)
486 			return (S_ERROR);
487 	}
488 
489 	/*
490 	 * Perform relocation to GOT table entry.
491 	 */
492 	return (add_actrel(NULL, rsp, ofl));
493 }
494 
495 
496 /*
497  * Perform relocations for PLT's
498  */
499 uintptr_t
500 reloc_plt(Rel_desc *rsp, Ofl_desc *ofl)
501 {
502 	Sym_desc	*sdp = rsp->rel_sym;
503 
504 #if defined(__i386) || defined(__amd64)
505 #if defined(_ELF64)
506 	/*
507 	 * AMD64 TLS code sequences do not use a unique
508 	 * TLS relocation to reference the __tls_get_addr()
509 	 * function call.
510 	 */
511 	if ((ofl->ofl_flags & FLG_OF_EXEC) &&
512 	    (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_U)) == 0)) {
513 		return (add_actrel(FLG_REL_TLSFIX, rsp, ofl));
514 	}
515 #else
516 	/*
517 	 * GNUC IA32 TLS code sequences do not use a unique
518 	 * TLS relocation to reference the ___tls_get_addr()
519 	 * function call.
520 	 */
521 	if ((ofl->ofl_flags & FLG_OF_EXEC) &&
522 	    (strcmp(sdp->sd_name, MSG_ORIG(MSG_SYM_TLSGETADDR_UU)) == 0)) {
523 		return (add_actrel(FLG_REL_TLSFIX, rsp, ofl));
524 	}
525 #endif
526 #endif	/* __i386 && __amd64 */
527 
528 	/*
529 	 * if (not PLT yet assigned)
530 	 * then
531 	 *	assign PLT index to symbol
532 	 *	build output JMP_SLOT relocation
533 	 * fi
534 	 */
535 	if (sdp->sd_aux->sa_PLTndx == 0) {
536 		Word	ortype = rsp->rel_rtype;
537 
538 		assign_plt_ndx(sdp, ofl);
539 
540 		/*
541 		 * If this symbol is binding to a LAZYLOADED object then
542 		 * set the LAZYLD symbol flag.
543 		 */
544 		if ((sdp->sd_aux->sa_bindto &&
545 		    (sdp->sd_aux->sa_bindto->ifl_flags & FLG_IF_LAZYLD)) ||
546 		    (sdp->sd_file &&
547 		    (sdp->sd_file->ifl_flags & FLG_IF_LAZYLD)))
548 			sdp->sd_flags |= FLG_SY_LAZYLD;
549 
550 		rsp->rel_rtype = M_R_JMP_SLOT;
551 		if (add_outrel(FLG_REL_PLT, rsp, ofl) == S_ERROR)
552 			return (S_ERROR);
553 		rsp->rel_rtype = ortype;
554 	}
555 
556 	/*
557 	 * Perform relocation to PLT table entry.
558 	 */
559 	if ((ofl->ofl_flags & FLG_OF_SHAROBJ) &&
560 	    IS_ADD_RELATIVE(rsp->rel_rtype)) {
561 		Word	ortype	= rsp->rel_rtype;
562 
563 		rsp->rel_rtype = M_R_RELATIVE;
564 		if (add_outrel(FLG_REL_ADVAL, rsp, ofl) == S_ERROR)
565 			return (S_ERROR);
566 		rsp->rel_rtype = ortype;
567 		return (1);
568 	} else
569 		return (add_actrel(NULL, rsp, ofl));
570 }
571 
572 /*
573  * process GLOBAL undefined and ref_dyn_need symbols.
574  */
575 uintptr_t
576 reloc_exec(Rel_desc *rsp, Ofl_desc *ofl)
577 {
578 	Sym_desc	*_sdp, *sdp = rsp->rel_sym;
579 	Sym_aux		*sap = sdp->sd_aux;
580 	Sym		*sym = sdp->sd_sym;
581 	Addr		stval;
582 
583 	/*
584 	 * Reference is to a function so simply create a plt entry for it.
585 	 */
586 	if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
587 		return (reloc_plt(rsp, ofl));
588 
589 	/*
590 	 * Catch absolutes - these may cause a text relocation.
591 	 */
592 	if ((sdp->sd_flags & FLG_SY_SPECSEC) && (sdp->sd_shndx == SHN_ABS)) {
593 		if ((ofl->ofl_flags1 & FLG_OF1_ABSEXEC) == 0)
594 			return (add_outrel(NULL, rsp, ofl));
595 		/*
596 		 * If -zabsexec is set then promote the ABSOLUTE
597 		 * symbol to current the current object and
598 		 * perform the relocation now.
599 		 */
600 		sdp->sd_ref = REF_REL_NEED;
601 		return (add_actrel(NULL, rsp, ofl));
602 	}
603 
604 	/*
605 	 * If the relocation is against a writable section simply compute the
606 	 * necessary output relocation.  As an optimization, if the symbol has
607 	 * already been transformed into a copy relocation then we can perform
608 	 * the relocation directly (copy relocations should only be generated
609 	 * for references from the text segment and these relocations are
610 	 * normally carried out before we get to the data segment relocations).
611 	 */
612 	if ((ELF_ST_TYPE(sym->st_info) == STT_OBJECT) &&
613 	    (rsp->rel_osdesc->os_shdr->sh_flags & SHF_WRITE)) {
614 		if (sdp->sd_flags & FLG_SY_MVTOCOMM)
615 			return (add_actrel(NULL, rsp, ofl));
616 		else
617 			return (add_outrel(NULL, rsp, ofl));
618 	}
619 
620 	/*
621 	 * If the reference isn't to an object (normally because some idiot
622 	 * hasn't defined a .type directive in some assembler source), then
623 	 * simply apply a generic relocation (this has a tendency to result in
624 	 * text relocations).
625 	 */
626 	if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) {
627 		eprintf(ERR_WARNING, MSG_INTL(MSG_REL_UNEXPSYM),
628 		    conv_info_type_str(ofl->ofl_e_machine,
629 		    ELF_ST_TYPE(sym->st_info)),
630 		    rsp->rel_isdesc->is_file->ifl_name,
631 		    demangle(rsp->rel_sname), sdp->sd_file->ifl_name);
632 		return (add_outrel(NULL, rsp, ofl));
633 	}
634 
635 	/*
636 	 * Prepare for generating a copy relocation.
637 	 *
638 	 * If this symbol is one of an alias pair, we need to insure both
639 	 * symbols become part of the output (the strong symbol will be used to
640 	 * maintain the symbols state).  And, if we did raise the precedence of
641 	 * a symbol we need to check and see if this is a weak symbol.  If it is
642 	 * we want to use it's strong counter part.
643 	 *
644 	 * The results of this logic should be:
645 	 *	rel_usym: assigned to strong
646 	 *	 rel_sym: assigned to symbol to perform
647 	 *		  copy_reloc against (weak or strong).
648 	 */
649 	if (sap->sa_linkndx) {
650 		_sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx];
651 
652 		if (_sdp->sd_ref < sdp->sd_ref) {
653 			_sdp->sd_ref = sdp->sd_ref;
654 			_sdp->sd_flags |= FLG_SY_REFRSD;
655 
656 			/*
657 			 * As we're going to replicate a symbol from a shared
658 			 * object, retain its correct binding status.
659 			 */
660 			if (ELF_ST_BIND(_sdp->sd_sym->st_info) == STB_GLOBAL)
661 				_sdp->sd_flags |= FLG_SY_GLOBREF;
662 
663 		} else if (_sdp->sd_ref > sdp->sd_ref) {
664 			sdp->sd_ref = _sdp->sd_ref;
665 			sdp->sd_flags |= FLG_SY_REFRSD;
666 
667 			/*
668 			 * As we're going to replicate a symbol from a shared
669 			 * object, retain its correct binding status.
670 			 */
671 			if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL)
672 				sdp->sd_flags |= FLG_SY_GLOBREF;
673 		}
674 
675 		/*
676 		 * If this is a weak symbol then we want to move the strong
677 		 * symbol into local .bss.  If there is a copy_reloc to be
678 		 * performed, that should still occur against the WEAK symbol.
679 		 */
680 		if ((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_WEAK) ||
681 		    (sdp->sd_flags & FLG_SY_WEAKDEF))
682 			rsp->rel_usym = _sdp;
683 	} else
684 		_sdp = 0;
685 
686 	/*
687 	 * If the reference is to an object then allocate space for the object
688 	 * within the executables .bss.  Relocations will now be performed from
689 	 * this new location.  If the original shared objects data is
690 	 * initialized, then generate a copy relocation that will copy the data
691 	 * to the executables .bss at runtime.
692 	 */
693 	if (!(rsp->rel_usym->sd_flags & FLG_SY_MVTOCOMM)) {
694 		Word	rtype = rsp->rel_rtype;
695 		Copy_rel *cpy_rel;
696 
697 		/*
698 		 * Indicate that the symbol(s) against which we're relocating
699 		 * have been moved to the executables common.  Also, insure that
700 		 * the symbol(s) remain marked as global, as the shared object
701 		 * from which they are copied must be able to relocate to the
702 		 * new common location within the executable.
703 		 *
704 		 * Note that even though a new symbol has been generated in the
705 		 * output files' .bss, the symbol must remain REF_DYN_NEED and
706 		 * not be promoted to REF_REL_NEED.  sym_validate() still needs
707 		 * to carry out a number of checks against the symbols binding
708 		 * that are triggered by the REF_DYN_NEED state.
709 		 */
710 		sdp->sd_flags |= FLG_SY_MVTOCOMM;
711 		sdp->sd_flags1 |= FLG_SY1_GLOB;
712 		sdp->sd_flags1 &= ~FLG_SY1_LOCL;
713 		sdp->sd_sym->st_other &= ~MSK_SYM_VISIBILITY;
714 		if (_sdp) {
715 			_sdp->sd_flags |= FLG_SY_MVTOCOMM;
716 			_sdp->sd_flags1 |= FLG_SY1_GLOB;
717 			_sdp->sd_flags1 &= ~FLG_SY1_LOCL;
718 			_sdp->sd_sym->st_other &= ~MSK_SYM_VISIBILITY;
719 
720 			/*
721 			 * Make sure the symbol has a reference in case of any
722 			 * error diagnostics against it (perhaps this belongs
723 			 * to a version that isn't allowable for this build).
724 			 * The resulting diagnostic (see sym_undef_entry())
725 			 * might seem a little bogus, as the symbol hasn't
726 			 * really been referenced by this file, but has been
727 			 * promoted as a consequence of its alias reference.
728 			 */
729 			if (!(_sdp->sd_aux->sa_rfile))
730 				_sdp->sd_aux->sa_rfile = sdp->sd_aux->sa_rfile;
731 		}
732 
733 		/*
734 		 * Assign the symbol to the bss and insure sufficient alignment
735 		 * (we don't know the real alignment so we have to make the
736 		 * worst case guess).
737 		 */
738 		_sdp = rsp->rel_usym;
739 		stval = _sdp->sd_sym->st_value;
740 		if (sym_copy(_sdp) == S_ERROR)
741 			return (S_ERROR);
742 		_sdp->sd_shndx = _sdp->sd_sym->st_shndx = SHN_COMMON;
743 		_sdp->sd_flags |= FLG_SY_SPECSEC;
744 		_sdp->sd_sym->st_value =
745 		    (_sdp->sd_sym->st_size < (M_WORD_ALIGN * 2)) ?
746 		    M_WORD_ALIGN : M_WORD_ALIGN * 2;
747 
748 		/*
749 		 * Whether or not the symbol references initialized
750 		 * data we generate a copy relocation - this differs
751 		 * from the past where we would not create the COPY_RELOC
752 		 * if we were binding against .bss.  This is done
753 		 * for *two* reasons.
754 		 *
755 		 *  o If the symbol in the shared object changes to
756 		 *    a initialized data - we need the COPY to pick it
757 		 *    up.
758 		 *  o without the COPY RELOC we can't tell that the
759 		 *    symbol from the COPY'd object has been moved
760 		 *    and all bindings to it should bind here.
761 		 */
762 
763 		/*
764 		 * Keep this symbol in the copy relocation list
765 		 * to check the validity later.
766 		 */
767 		if ((cpy_rel = libld_malloc(sizeof (Copy_rel))) == 0)
768 			return (S_ERROR);
769 		cpy_rel->copyrel_symd = _sdp;
770 		cpy_rel->copyrel_stval = stval;
771 		if (list_appendc(&ofl->ofl_copyrels, cpy_rel) == 0)
772 			return (S_ERROR);
773 
774 		rsp->rel_rtype = M_R_COPY;
775 		if (add_outrel(FLG_REL_BSS, rsp, ofl) == S_ERROR)
776 			return (S_ERROR);
777 		rsp->rel_rtype = rtype;
778 
779 		/*
780 		 * If this symbol is a protected symbol, warn it.
781 		 */
782 		if (_sdp->sd_flags & FLG_SY_PROT)
783 			eprintf(ERR_WARNING, MSG_INTL(MSG_REL_COPY),
784 			conv_reloc_type_str(_sdp->sd_file->ifl_ehdr->e_machine,
785 			M_R_COPY), _sdp->sd_file->ifl_name, _sdp->sd_name);
786 		DBG_CALL(Dbg_syms_reloc(sdp->sd_file->ifl_ehdr, sdp));
787 	}
788 	return (add_actrel(NULL, rsp, ofl));
789 }
790 
791 /*
792  * All relocations should have been handled by the other routines.  This
793  * routine is hear as a catch all, if we do enter it we've goofed - but
794  * we'll try and to the best we can.
795  */
796 uintptr_t
797 reloc_generic(Rel_desc *rsp, Ofl_desc *ofl)
798 {
799 	Word	flags = ofl->ofl_flags;
800 
801 	eprintf(ERR_WARNING, MSG_INTL(MSG_REL_UNEXPREL),
802 	    conv_reloc_type_str(ofl->ofl_e_machine, rsp->rel_rtype),
803 	    rsp->rel_isdesc->is_file->ifl_name, demangle(rsp->rel_sname));
804 
805 	/*
806 	 * If building a shared object then put the relocation off
807 	 * until runtime.
808 	 */
809 	if (flags & FLG_OF_SHAROBJ)
810 		return (add_outrel(NULL, rsp, ofl));
811 
812 	/*
813 	 * Otherwise process relocation now.
814 	 */
815 	return (add_actrel(NULL, rsp, ofl));
816 }
817 
818 
819 uintptr_t
820 process_sym_reloc(Ofl_desc * ofl, Rel_desc * reld, Rel * reloc,
821     Is_desc * isp, const char *isname)
822 {
823 	Word		rtype = reld->rel_rtype;
824 	Word		flags = ofl->ofl_flags;
825 	Sym_desc	*sdp = reld->rel_sym;
826 	Sym_aux		*sap;
827 	Boolean		local;
828 
829 	DBG_CALL(Dbg_reloc_in(M_MACH, M_REL_SHT_TYPE, (void *)reloc,
830 	    reld->rel_sname, isname));
831 
832 	/*
833 	 * Indicate this symbol is being used for relocation and therefore must
834 	 * have its output address updated accordingly (refer to update_osym()).
835 	 */
836 	sdp->sd_flags |= FLG_SY_UPREQD;
837 
838 	/*
839 	 * Indicate the section this symbol is defined in has been referenced,
840 	 * therefor it *is not* a candidate for elimination.
841 	 */
842 	if (sdp->sd_isc) {
843 		sdp->sd_isc->is_flags |= FLG_IS_SECTREF;
844 		sdp->sd_isc->is_file->ifl_flags |= FLG_IF_FILEREF;
845 	}
846 
847 	reld->rel_usym = sdp;
848 
849 	/*
850 	 * Determine if this symbol is actually an alias to another symbol.  If
851 	 * so, and the alias is not REF_DYN_SEEN, set rel_usym to point to the
852 	 * weak symbols strong counter-part.  The one exception is if the
853 	 * FLG_SY_MVTOCOMM flag is set on the weak symbol.  If this is the case,
854 	 * the strong is only here because of its promotion, and the weak symbol
855 	 * should still be used for the relocation reference (see reloc_exec()).
856 	 */
857 	sap = sdp->sd_aux;
858 	if (sap && sap->sa_linkndx &&
859 	    ((ELF_ST_BIND(sdp->sd_sym->st_info) == STB_WEAK) ||
860 	    (sdp->sd_flags & FLG_SY_WEAKDEF)) &&
861 	    (!(sdp->sd_flags & FLG_SY_MVTOCOMM))) {
862 		Sym_desc *	_sdp;
863 
864 		_sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx];
865 		if (_sdp->sd_ref != REF_DYN_SEEN)
866 			reld->rel_usym = _sdp;
867 	}
868 
869 	/*
870 	 * Determine whether this symbol should be bound locally or not.
871 	 * Symbols will be bound locally if one of the following is true:
872 	 *
873 	 *  o	the symbol is of type STB_LOCAL
874 	 *
875 	 *  o	the output image is not a relocatable object and the
876 	 *	relocation is relative to the .got
877 	 *
878 	 *  o	the section being relocated is of type SHT_SUNW_dof;
879 	 *	these sections are bound to the functions in the
880 	 *	containing object and don't care about interpositioning
881 	 *
882 	 *  o	the symbol has been reduced (scoped to a local or
883 	 *	symbolic) and reductions are being processed
884 	 *
885 	 *  o	the -Bsymbolic flag is in use when building a shared
886 	 *	object or an executable (fixed address) is being created
887 	 *
888 	 *  o	Building an executable and the symbol is defined
889 	 *	in the executable.
890 	 *
891 	 *  o	the relocation is against a segment which will not
892 	 *	be loaded into memory.  If that is the case we need
893 	 *	to resolve the relocation now because ld.so.1 won't
894 	 *	be able to.
895 	 */
896 	local = FALSE;
897 	if (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) {
898 		local = TRUE;
899 	} else if (!(reld->rel_flags & FLG_REL_LOAD)) {
900 		local = TRUE;
901 	} else if (sdp->sd_shndx != SHN_UNDEF) {
902 		if (reld->rel_isdesc &&
903 		    reld->rel_isdesc->is_shdr->sh_type == SHT_SUNW_dof) {
904 			local = TRUE;
905 		} else if (!(flags & FLG_OF_RELOBJ) &&
906 		    (IS_LOCALBND(rtype) || IS_SEG_RELATIVE(rtype))) {
907 			local = TRUE;
908 		} else if (sdp->sd_ref == REF_REL_NEED) {
909 			if ((sdp->sd_flags1 & (FLG_SY1_LOCL | FLG_SY1_PROT)))
910 				local = TRUE;
911 			else if (flags & (FLG_OF_SYMBOLIC | FLG_OF_EXEC))
912 				local = TRUE;
913 		}
914 	}
915 
916 	/*
917 	 * If this is a PC_RELATIVE relocation, the relocation could be
918 	 * compromised if the relocated address is later used as a copy
919 	 * relocated symbol (PSARC 1999/636, bugid 4187211).  Scan the input
920 	 * files symbol table to cross reference this relocation offset.
921 	 */
922 	if ((ofl->ofl_flags & FLG_OF_SHAROBJ) && IS_PC_RELATIVE(rtype) &&
923 	    (IS_GOT_PC(rtype) == 0) && (IS_PLT(rtype) == 0)) {
924 		if (disp_inspect(ofl, reld, local) == S_ERROR)
925 			return (S_ERROR);
926 	}
927 
928 	/*
929 	 * GOT based relocations must bind to the object being built - since
930 	 * they are relevant to the current GOT.  If not building a relocatable
931 	 * object - give a appropriate error message.
932 	 */
933 	if (!local && !(flags & FLG_OF_RELOBJ) && IS_GOT_BASED(rtype)) {
934 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_BADGOTBASED),
935 		    conv_reloc_type_str(ofl->ofl_e_machine, rtype),
936 		    reld->rel_isdesc->is_file->ifl_name,
937 		    demangle(sdp->sd_name));
938 		return (S_ERROR);
939 	}
940 
941 	/*
942 	 * TLS symbols can only have TLS relocations.
943 	 */
944 	if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_TLS) && !IS_TLS(rtype)) {
945 		/*
946 		 * The above test is relaxed if the target section is
947 		 * non-allocable.
948 		 */
949 		if (reld->rel_osdesc->os_shdr->sh_flags & SHF_ALLOC) {
950 			eprintf(ERR_FATAL, MSG_INTL(MSG_REL_BADTLS),
951 			    conv_reloc_type_str(ofl->ofl_e_machine, rtype),
952 			    reld->rel_isdesc->is_file->ifl_name,
953 			    demangle(sdp->sd_name));
954 			return (S_ERROR);
955 		}
956 	}
957 
958 	/*
959 	 * Select the relocation to perform.
960 	 */
961 	if (IS_REGISTER(rtype))
962 		return (reloc_register(reld, isp, ofl));
963 
964 	if (flags & FLG_OF_RELOBJ)
965 		return (reloc_relobj(local, reld, ofl));
966 
967 	if (IS_TLS_INS(rtype))
968 		return (reloc_TLS(local, reld, ofl));
969 
970 	if (IS_GOT_INS(rtype))
971 		return (reloc_GOTOP(local, reld, ofl));
972 
973 	if (IS_GOT_RELATIVE(rtype))
974 		return (reloc_GOT_relative(local, reld, ofl));
975 
976 	if (local)
977 		return (reloc_local(reld, ofl));
978 
979 	if ((IS_PLT(rtype)) && ((flags & FLG_OF_BFLAG) == 0))
980 		return (reloc_plt(reld, ofl));
981 
982 	if ((sdp->sd_ref == REF_REL_NEED) ||
983 	    (flags & FLG_OF_BFLAG) || (flags & FLG_OF_SHAROBJ) ||
984 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_NOTYPE))
985 		return (add_outrel(NULL, reld, ofl));
986 
987 	if (sdp->sd_ref == REF_DYN_NEED)
988 		return (reloc_exec(reld, ofl));
989 
990 	/*
991 	 * IS_NOT_REL(rtype)
992 	 */
993 	return (reloc_generic(reld, ofl));
994 }
995 
996 /*
997  * Generate relocation descriptor and dispatch
998  */
999 static uintptr_t
1000 process_reld(Ofl_desc *ofl, Is_desc *isp, Rel_desc *reld, Word rsndx,
1001     Rel *reloc)
1002 {
1003 	Ifl_desc	*ifl = isp->is_file;
1004 	Word		rtype = reld->rel_rtype;
1005 	Sym_desc	*sdp;
1006 
1007 	/*
1008 	 * Make sure the relocation is in the valid range.
1009 	 */
1010 	if (rtype >= M_R_NUM) {
1011 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_INVALRELT), ifl->ifl_name,
1012 		    isp->is_name, rtype);
1013 		return (S_ERROR);
1014 	}
1015 
1016 	ofl->ofl_entrelscnt++;
1017 
1018 	/*
1019 	 * Special case: a register symbol associated with symbol index 0 is
1020 	 * initialized (i.e., relocated) to a constant from the r_addend field
1021 	 * rather than from a symbol value.
1022 	 */
1023 	if (IS_REGISTER(rtype) && (rsndx == 0)) {
1024 		reld->rel_sym = 0;
1025 		reld->rel_sname = MSG_ORIG(MSG_STR_EMPTY);
1026 
1027 		DBG_CALL(Dbg_reloc_in(M_MACH, isp->is_shdr->sh_type,
1028 		    (void *)reloc, reld->rel_sname, isp->is_name));
1029 		return (reloc_register(reld, isp, ofl));
1030 	}
1031 
1032 	/*
1033 	 * Determine whether we're dealing with a named symbol.  Note, bogus
1034 	 * relocations can result in a null symbol descriptor (sdp), the error
1035 	 * condition should be caught below after determining whether a valid
1036 	 * symbol name exists.
1037 	 */
1038 	sdp = ifl->ifl_oldndx[rsndx];
1039 	if (sdp != NULL && sdp->sd_name && *sdp->sd_name)
1040 		reld->rel_sname = sdp->sd_name;
1041 	else {
1042 		static char *strunknown;
1043 
1044 		if (strunknown == 0)
1045 			strunknown = (char *)MSG_INTL(MSG_STR_UNKNOWN);
1046 		reld->rel_sname = strunknown;
1047 	}
1048 
1049 	/*
1050 	 * If for some reason we have a null relocation record issue a
1051 	 * warning and continue (the compiler folks can get into this
1052 	 * state some time).  Normal users should never see this error.
1053 	 */
1054 	if (rtype == M_R_NONE) {
1055 		DBG_CALL(Dbg_reloc_in(M_MACH, M_REL_SHT_TYPE, (void *)reloc,
1056 		    reld->rel_sname, isp->is_name));
1057 		eprintf(ERR_WARNING, MSG_INTL(MSG_REL_NULL), ifl->ifl_name,
1058 		    isp->is_name);
1059 		return (1);
1060 	}
1061 
1062 	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && IS_NOTSUP(rtype)) {
1063 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NOTSUP),
1064 		    conv_reloc_type_str(ifl->ifl_ehdr->e_machine, rtype),
1065 		    ifl->ifl_name, isp->is_name);
1066 		return (S_ERROR);
1067 	}
1068 
1069 	/*
1070 	 * If we are here, we know that the relocation requires reference
1071 	 * symbol. If no symbol is assigned, this is a fatal error.
1072 	 */
1073 	if (sdp == NULL) {
1074 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NOSYMBOL),
1075 		    conv_reloc_type_str(ifl->ifl_ehdr->e_machine, rtype),
1076 		    isp->is_name, ifl->ifl_name, EC_XWORD(reloc->r_offset));
1077 		return (S_ERROR);
1078 	}
1079 
1080 	if (sdp->sd_flags1 & FLG_SY1_IGNORE)
1081 		return (1);
1082 
1083 	/*
1084 	 * If this symbol is part of a DISCARDED section attempt to find another
1085 	 * definition.
1086 	 */
1087 	if (sdp->sd_flags & FLG_SY_ISDISC) {
1088 		Sym_desc *	nsdp;
1089 
1090 		if ((reld->rel_sname != sdp->sd_name) ||
1091 		    (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL) ||
1092 		    ((nsdp = sym_find(sdp->sd_name, SYM_NOHASH, 0,
1093 		    ofl)) == 0)) {
1094 			eprintf(ERR_FATAL, MSG_INTL(MSG_REL_SYMDISC),
1095 			    ifl->ifl_name, isp->is_name, demangle(sdp->sd_name),
1096 			    sdp->sd_isc->is_name);
1097 			return (S_ERROR);
1098 		}
1099 		ifl->ifl_oldndx[rsndx] = sdp = nsdp;
1100 	}
1101 
1102 	/*
1103 	 * If this is a global symbol, determine whether its visibility needs
1104 	 * adjusting.
1105 	 */
1106 	if (sdp->sd_aux && ((sdp->sd_flags & FLG_SY_VISIBLE) == 0))
1107 		sym_adjust_vis(sdp, ofl);
1108 
1109 	/*
1110 	 * Ignore any relocation against a section that will not be in the
1111 	 * output file (has been stripped).
1112 	 */
1113 	if ((sdp->sd_isc == 0) &&
1114 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION))
1115 		return (1);
1116 
1117 	/*
1118 	 * If the symbol for this relocation is invalid (which should have
1119 	 * generated a message during symbol processing), or the relocation
1120 	 * record's symbol reference is in any other way invalid, then it's
1121 	 * about time we gave up.
1122 	 */
1123 	if ((sdp->sd_flags & FLG_SY_INVALID) || (rsndx == 0) ||
1124 	    (rsndx >= ifl->ifl_symscnt)) {
1125 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_UNKNWSYM),
1126 		    M_REL_CONTYPSTR(rtype), ifl->ifl_name, isp->is_name,
1127 		    demangle(reld->rel_sname), EC_XWORD(reloc->r_offset),
1128 		    EC_WORD(rsndx));
1129 		return (S_ERROR);
1130 	}
1131 
1132 	reld->rel_sym = sdp;
1133 	return (process_sym_reloc(ofl, reld, reloc, isp, isp->is_name));
1134 }
1135 
1136 static uintptr_t
1137 reloc_section(Ofl_desc *ofl, Is_desc *isect, Is_desc *rsect, Os_desc *osect)
1138 {
1139 	Rel		*rend;		/* end of relocation section data */
1140 	Rel		*reloc;		/* current relocation entry */
1141 	Xword		rsize;		/* size of relocation section data */
1142 	Xword		entsize;	/* size of relocation entry */
1143 	Rel_desc	reld;		/* relocation descriptor */
1144 	Shdr *		shdr;
1145 	Word		flags = 0;
1146 
1147 	shdr = rsect->is_shdr;
1148 	rsize = shdr->sh_size;
1149 	reloc = (Rel *)rsect->is_indata->d_buf;
1150 
1151 	/*
1152 	 * Decide entry size.
1153 	 */
1154 	if (((entsize = shdr->sh_entsize) == 0) || (entsize > rsize)) {
1155 		if (shdr->sh_type == SHT_RELA)
1156 			entsize = sizeof (Rela);
1157 		else
1158 			entsize = sizeof (Rel);
1159 	}
1160 
1161 	/*
1162 	 * Build up the basic information in for the Rel_desc structure.
1163 	 */
1164 	reld.rel_osdesc = osect;
1165 	reld.rel_isdesc = isect;
1166 	reld.rel_move = 0;
1167 
1168 	if ((ofl->ofl_flags & FLG_OF_RELOBJ) ||
1169 	    (osect && (osect->os_sgdesc->sg_phdr.p_type == PT_LOAD)))
1170 		flags |= FLG_REL_LOAD;
1171 
1172 	if (shdr->sh_info == 0)
1173 		flags |= FLG_REL_NOINFO;
1174 
1175 	DBG_CALL(Dbg_reloc_proc(osect, isect, rsect));
1176 
1177 	for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize);
1178 	    reloc < rend;
1179 	    reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) {
1180 		Word	rsndx;
1181 
1182 		/*
1183 		 * Initialize the relocation record information and process
1184 		 * the individual relocation.  Reinitialize the flags to
1185 		 * insure we don't carry any state over from the previous
1186 		 * relocation records processing.
1187 		 */
1188 		reld.rel_flags = flags;
1189 		rsndx = init_rel(&reld, (void *)reloc);
1190 
1191 		if (process_reld(ofl, rsect, &reld, rsndx, reloc) == S_ERROR)
1192 			return (S_ERROR);
1193 	}
1194 	return (1);
1195 }
1196 
1197 
1198 uintptr_t
1199 reloc_segments(int wr_flag, Ofl_desc *ofl)
1200 {
1201 	Listnode	*lnp1;
1202 	Sg_desc		*sgp;
1203 	Is_desc		*isp;
1204 
1205 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) {
1206 		Os_desc		*osp;
1207 		Listnode	*lnp2;
1208 
1209 		if ((sgp->sg_phdr.p_flags & PF_W) != wr_flag)
1210 			continue;
1211 
1212 		for (LIST_TRAVERSE(&(sgp->sg_osdescs), lnp2, osp)) {
1213 			Is_desc		*risp;
1214 			Listnode	*lnp3;
1215 
1216 			osp->os_szoutrels = 0;
1217 			for (LIST_TRAVERSE(&(osp->os_relisdescs), lnp3, risp)) {
1218 				Word	indx;
1219 
1220 				/*
1221 				 * Determine the input section that this
1222 				 * relocation information refers to.
1223 				 */
1224 				indx = risp->is_shdr->sh_info;
1225 				isp = risp->is_file->ifl_isdesc[indx];
1226 
1227 				/*
1228 				 * Do not process relocations against sections
1229 				 * which are being discarded (COMDAT)
1230 				 */
1231 				if (isp->is_flags & FLG_IS_DISCARD)
1232 					continue;
1233 
1234 				if (reloc_section(ofl, isp, risp, osp) ==
1235 				    S_ERROR)
1236 					return (S_ERROR);
1237 			}
1238 
1239 			/*
1240 			 * Check for relocations against non-writable
1241 			 * allocatable sections.
1242 			 */
1243 			if ((osp->os_szoutrels) &&
1244 			    (sgp->sg_phdr.p_type == PT_LOAD) &&
1245 			    ((sgp->sg_phdr.p_flags & PF_W) == 0)) {
1246 				ofl->ofl_flags |= FLG_OF_TEXTREL;
1247 				ofl->ofl_dtflags |= DF_TEXTREL;
1248 			}
1249 		}
1250 	}
1251 
1252 	return (1);
1253 }
1254 
1255 /*
1256  * Move Section related function
1257  * Get move entry
1258  */
1259 static Move *
1260 get_move_entry(Is_desc *rsect, Xword roffset)
1261 {
1262 	Ifl_desc	*ifile = rsect->is_file;
1263 	Shdr		*rshdr = rsect->is_shdr;
1264 	Is_desc		*misp;
1265 	Shdr		*mshdr;
1266 	Xword 		midx;
1267 	Move		*ret;
1268 
1269 	/*
1270 	 * Set info for the target move section
1271 	 */
1272 	misp = ifile->ifl_isdesc[rshdr->sh_info];
1273 	mshdr = (ifile->ifl_isdesc[rshdr->sh_info])->is_shdr;
1274 
1275 	if (mshdr->sh_entsize == 0)
1276 		return ((Move *)0);
1277 	midx = roffset / mshdr->sh_entsize;
1278 
1279 	ret = (Move *)misp->is_indata->d_buf;
1280 	ret += midx;
1281 
1282 	/*
1283 	 * If this is an illgal entry, retun NULL.
1284 	 */
1285 	if ((midx * mshdr->sh_entsize) >= mshdr->sh_size)
1286 		return ((Move *)0);
1287 	return (ret);
1288 }
1289 
1290 /*
1291  * Relocation against Move Table.
1292  */
1293 static uintptr_t
1294 process_movereloc(Ofl_desc *ofl, Is_desc *rsect)
1295 {
1296 	Ifl_desc	*file = rsect->is_file;
1297 	Rel		*rend, *reloc;
1298 	Xword 		rsize, entsize;
1299 	static Rel_desc reld_zero;
1300 	Rel_desc 	reld;
1301 
1302 	rsize = rsect->is_shdr->sh_size;
1303 	reloc = (Rel *)rsect->is_indata->d_buf;
1304 
1305 	reld = reld_zero;
1306 
1307 	/*
1308 	 * Decide entry size
1309 	 */
1310 	entsize = rsect->is_shdr->sh_entsize;
1311 	if ((entsize == 0) ||
1312 	    (entsize > rsect->is_shdr->sh_size)) {
1313 		if (rsect->is_shdr->sh_type == SHT_RELA)
1314 			entsize = sizeof (Rela);
1315 		else
1316 			entsize = sizeof (Rel);
1317 	}
1318 
1319 	/*
1320 	 * Go through the relocation entries.
1321 	 */
1322 	for (rend = (Rel *)((uintptr_t)reloc + (uintptr_t)rsize);
1323 	    reloc < rend;
1324 	    reloc = (Rel *)((uintptr_t)reloc + (uintptr_t)entsize)) {
1325 		Sym_desc *	psdp;
1326 		Move *		mp;
1327 		Word		rsndx;
1328 
1329 		/*
1330 		 * Initialize the relocation record information.
1331 		 */
1332 		reld.rel_flags = FLG_REL_LOAD;
1333 		rsndx = init_rel(&reld, (void *)reloc);
1334 
1335 		if (((mp = get_move_entry(rsect, reloc->r_offset)) == 0) ||
1336 		    ((reld.rel_move = libld_malloc(sizeof (Mv_desc))) == 0))
1337 			return (S_ERROR);
1338 
1339 		psdp = file->ifl_oldndx[ELF_M_SYM(mp->m_info)];
1340 		reld.rel_move->mvd_move = mp;
1341 		reld.rel_move->mvd_sym = psdp;
1342 
1343 		if (psdp->sd_flags & FLG_SY_PAREXPN) {
1344 			int	_num, num;
1345 
1346 			reld.rel_osdesc = ofl->ofl_issunwdata1->is_osdesc;
1347 			reld.rel_isdesc = ofl->ofl_issunwdata1;
1348 			reld.rel_roffset = mp->m_poffset;
1349 
1350 			for (num = mp->m_repeat, _num = 0; _num < num; _num++) {
1351 				reld.rel_roffset +=
1352 					/* LINTED */
1353 					(_num * ELF_M_SIZE(mp->m_info));
1354 				/*
1355 				 * Generate Reld
1356 				 */
1357 				if (process_reld(ofl,
1358 				    rsect, &reld, rsndx, reloc) == S_ERROR)
1359 					return (S_ERROR);
1360 			}
1361 		} else {
1362 			/*
1363 			 * Generate Reld
1364 			 */
1365 			reld.rel_flags |= FLG_REL_MOVETAB;
1366 			reld.rel_osdesc = ofl->ofl_osmove;
1367 			reld.rel_isdesc =
1368 				ofl->ofl_osmove->os_isdescs.head->data;
1369 			if (process_reld(ofl,
1370 			    rsect, &reld, rsndx, reloc) == S_ERROR)
1371 				return (S_ERROR);
1372 		}
1373 	}
1374 	return (1);
1375 }
1376 
1377 /*
1378  * This function is similar to reloc_init().
1379  *
1380  * This function is called when the SHT_SUNW_move table is expanded
1381  * and there were relocation against the SHT_SUNW_move section.
1382  */
1383 static uintptr_t
1384 reloc_movesections(Ofl_desc *ofl)
1385 {
1386 	Listnode	*lnp1;
1387 	Is_desc		*risp;
1388 
1389 	/*
1390 	 * Generate/Expand relocation entries
1391 	 */
1392 	for (LIST_TRAVERSE(&ofl->ofl_mvrelisdescs, lnp1, risp)) {
1393 		if (process_movereloc(ofl, risp) == S_ERROR)
1394 			return (S_ERROR);
1395 	}
1396 
1397 	return (1);
1398 }
1399 
1400 /*
1401  * Count the number of output relocation entries, global offset table entries,
1402  * and procedure linkage table entries.  This function searches the segment and
1403  * outsect lists and passes each input reloc section to process_reloc().
1404  * It allocates space for any output relocations needed.  And builds up
1405  * the relocation structures for later processing.
1406  */
1407 uintptr_t
1408 reloc_init(Ofl_desc *ofl)
1409 {
1410 	Listnode	*lnp;
1411 	Is_desc		*isp;
1412 
1413 	/*
1414 	 * At this point we have finished processing all input symbols.  Make
1415 	 * sure we add any absolute (internal) symbols before continuing with
1416 	 * any relocation processing.
1417 	 */
1418 	if (sym_spec(ofl) == S_ERROR)
1419 		return (S_ERROR);
1420 
1421 	ofl->ofl_gotcnt = M_GOT_XNumber;
1422 
1423 	/*
1424 	 * First process all of the relocations against NON-writable
1425 	 * segments followed by relocations against the writeable segments.
1426 	 *
1427 	 * This separation is so that when the writable segments are processed
1428 	 * we know whether or not a COPYRELOC will be produced for any symbols.
1429 	 * If relocations aren't processed in this order, a COPYRELOC and a
1430 	 * regular relocation can be produced against the same symbol.  The
1431 	 * regular relocation would be redundant.
1432 	 */
1433 	if (reloc_segments(0, ofl) == S_ERROR)
1434 		return (S_ERROR);
1435 
1436 	if (reloc_segments(PF_W, ofl) == S_ERROR)
1437 		return (S_ERROR);
1438 
1439 	/*
1440 	 * Process any extra relocations.  These are relocation sections that
1441 	 * have a NULL sh_info.
1442 	 */
1443 	for (LIST_TRAVERSE(&ofl->ofl_extrarels, lnp, isp)) {
1444 		if (reloc_section(ofl, NULL, isp, NULL) == S_ERROR)
1445 			return (S_ERROR);
1446 	}
1447 
1448 	/*
1449 	 * If there were relocation against move table,
1450 	 * process the relocation sections.
1451 	 */
1452 	if (reloc_movesections(ofl) == S_ERROR)
1453 		return (S_ERROR);
1454 
1455 	/*
1456 	 * Now all the relocations are pre-processed,
1457 	 * check the validity of copy relocations.
1458 	 */
1459 	if (ofl->ofl_copyrels.head != 0) {
1460 		Copy_rel *	cpyrel;
1461 
1462 		for (LIST_TRAVERSE(&ofl->ofl_copyrels, lnp, cpyrel)) {
1463 			Sym_desc *	sdp;
1464 
1465 			sdp = cpyrel->copyrel_symd;
1466 			/*
1467 			 * If there were no displacement relocation
1468 			 * in this file, don't worry about it.
1469 			 */
1470 			if (sdp->sd_file->ifl_flags &
1471 			    (FLG_IF_DISPPEND | FLG_IF_DISPDONE))
1472 				is_disp_copied(ofl, cpyrel);
1473 		}
1474 	}
1475 
1476 	/*
1477 	 * Make a got section if:
1478 	 *
1479 	 *	BLDGOT flag set
1480 	 *		or
1481 	 *	ofl_gotcnt != GOT_XNumber
1482 	 *		or
1483 	 *	not-relobj & GOT symbol referenced
1484 	 *
1485 	 */
1486 	if ((ofl->ofl_flags & FLG_OF_BLDGOT) ||
1487 	    (ofl->ofl_gotcnt != M_GOT_XNumber) ||
1488 	    (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) &&
1489 	    ((sym_find(MSG_ORIG(MSG_SYM_GOFTBL), SYM_NOHASH, 0, ofl) != 0) ||
1490 	    (sym_find(MSG_ORIG(MSG_SYM_GOFTBL_U), SYM_NOHASH, 0, ofl) != 0)))) {
1491 		if (make_got(ofl) == S_ERROR)
1492 			return (S_ERROR);
1493 
1494 #if defined(sparc) || defined(__sparcv9)
1495 		if (allocate_got(ofl) == S_ERROR)
1496 			return (S_ERROR);
1497 #elif defined(i386) || defined(__amd64)
1498 /* nothing to do */
1499 #else
1500 #error Unknown architecture!
1501 #endif
1502 	}
1503 
1504 	return (1);
1505 }
1506 
1507 /*
1508  * Simple comparison routine to be used by qsort() for
1509  * the sorting of the output relocation list.
1510  *
1511  * The reloc_compare() routine results in a relocation
1512  * table which is located on:
1513  *
1514  *	file referenced (NEEDED NDX)
1515  *	referenced symbol
1516  *	relocation offset
1517  *
1518  * This provides the most efficient traversal of the relocation
1519  * table at run-time.
1520  */
1521 int
1522 reloc_compare(Reloc_list *i, Reloc_list *j)
1523 {
1524 
1525 	/*
1526 	 * first - sort on neededndx
1527 	 */
1528 	if (i->rl_key1 > j->rl_key1)
1529 		return (1);
1530 	if (i->rl_key1 < j->rl_key1)
1531 		return (-1);
1532 
1533 	/*
1534 	 * Then sort on symbol
1535 	 */
1536 	if ((uintptr_t)i->rl_key2 > (uintptr_t)j->rl_key2)
1537 		return (1);
1538 	if ((uintptr_t)i->rl_key2 < (uintptr_t)j->rl_key2)
1539 		return (-1);
1540 
1541 	/*
1542 	 * i->key2 == j->key2
1543 	 *
1544 	 * At this point we fall back to key2 (offsets) to
1545 	 * sort the output relocations.  Ideally this will
1546 	 * make for the most efficient processing of these
1547 	 * relocations at run-time.
1548 	 */
1549 	if (i->rl_key3 > j->rl_key3)
1550 		return (1);
1551 	if (i->rl_key3 < j->rl_key3)
1552 		return (-1);
1553 	return (0);
1554 }
1555 
1556 
1557 uintptr_t
1558 do_sorted_outrelocs(Ofl_desc *ofl)
1559 {
1560 	Rel_desc	*orsp;
1561 	Rel_cache	*rcp;
1562 	Listnode	*lnp;
1563 	Reloc_list	*sorted_list;
1564 	Word		index = 0;
1565 	int		debug = 0;
1566 	uintptr_t	error = 1;
1567 
1568 	if ((sorted_list = libld_malloc((size_t)(sizeof (Reloc_list) *
1569 	    ofl->ofl_reloccnt))) == NULL)
1570 		return (S_ERROR);
1571 
1572 	/*
1573 	 * All but the PLT output relocations are sorted in the output file
1574 	 * based upon their sym_desc.  By doing this multiple relocations
1575 	 * against the same symbol are grouped together, thus when the object
1576 	 * is later relocated by ld.so.1 it will take advantage of the symbol
1577 	 * cache that ld.so.1 has.  This can significantly reduce the runtime
1578 	 * relocation cost of a dynamic object.
1579 	 *
1580 	 * PLT relocations are not sorted because the order of the PLT
1581 	 * relocations is used by ld.so.1 to determine what symbol a PLT
1582 	 * relocation is against.
1583 	 */
1584 	for (LIST_TRAVERSE(&ofl->ofl_outrels, lnp, rcp)) {
1585 		/*LINTED*/
1586 		for (orsp = (Rel_desc *)(rcp + 1);
1587 		    orsp < rcp->rc_free; orsp++) {
1588 			if (debug == 0) {
1589 				DBG_CALL(Dbg_reloc_dooutrel(M_REL_SHT_TYPE));
1590 				debug = 1;
1591 			}
1592 
1593 			/*
1594 			 * If it's a PLT relocation we output it now in the
1595 			 * order that it was originally processed.
1596 			 */
1597 			if (orsp->rel_flags & FLG_REL_PLT) {
1598 				if (perform_outreloc(orsp, ofl) == S_ERROR)
1599 					error = S_ERROR;
1600 				continue;
1601 			}
1602 
1603 			if ((orsp->rel_rtype == M_R_RELATIVE) ||
1604 			    (orsp->rel_rtype == M_R_REGISTER)) {
1605 				sorted_list[index].rl_key1 = 0;
1606 				sorted_list[index].rl_key2 =
1607 				    /* LINTED */
1608 				    (Sym_desc *)(uintptr_t)orsp->rel_rtype;
1609 			} else {
1610 				sorted_list[index].rl_key1 =
1611 				    orsp->rel_sym->sd_file->ifl_neededndx;
1612 				sorted_list[index].rl_key2 =
1613 				    orsp->rel_sym;
1614 			}
1615 
1616 			if (orsp->rel_flags & FLG_REL_GOT)
1617 				sorted_list[index].rl_key3 =
1618 					calc_got_offset(orsp, ofl);
1619 			else {
1620 				if (orsp->rel_rtype == M_R_REGISTER)
1621 					sorted_list[index].rl_key3 = 0;
1622 				else {
1623 					sorted_list[index].rl_key3 =
1624 						orsp->rel_roffset +
1625 						(Xword)_elf_getxoff(orsp->
1626 						rel_isdesc->
1627 						is_indata) +
1628 						orsp->rel_isdesc->is_osdesc->
1629 						os_shdr->sh_addr;
1630 				}
1631 			}
1632 
1633 			sorted_list[index++].rl_rsp = orsp;
1634 		}
1635 	}
1636 
1637 	qsort(sorted_list, (size_t)ofl->ofl_reloccnt, sizeof (Reloc_list),
1638 		(int (*)(const void *, const void *))reloc_compare);
1639 
1640 	/*
1641 	 * All output relocations have now been sorted, go through
1642 	 * and process each relocation.
1643 	 */
1644 	for (index = 0; index < ofl->ofl_reloccnt; index++) {
1645 		if (perform_outreloc(sorted_list[index].rl_rsp, ofl) ==
1646 		    S_ERROR)
1647 			error = S_ERROR;
1648 	}
1649 
1650 	return (error);
1651 }
1652 
1653 /*
1654  * Process relocations.  Finds every input relocation section for each output
1655  * section and invokes reloc_sec() to relocate that section.
1656  */
1657 uintptr_t
1658 reloc_process(Ofl_desc *ofl)
1659 {
1660 	Listnode	*lnp1;
1661 	Sg_desc		*sgp;
1662 	Word		ndx = 0, flags = ofl->ofl_flags;
1663 	Shdr		*shdr;
1664 
1665 	/*
1666 	 * Determine the index of the symbol table that will be referenced by
1667 	 * the relocation entries.
1668 	 */
1669 	if ((flags & (FLG_OF_DYNAMIC|FLG_OF_RELOBJ)) == FLG_OF_DYNAMIC)
1670 		/* LINTED */
1671 		ndx = (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn);
1672 	else if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ))
1673 		/* LINTED */
1674 		ndx = (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn);
1675 
1676 	/*
1677 	 * Re-initialize counters. These are used to provide relocation
1678 	 * offsets within the output buffers.
1679 	 */
1680 	ofl->ofl_relocpltsz = 0;
1681 	ofl->ofl_relocgotsz = 0;
1682 	ofl->ofl_relocbsssz = 0;
1683 
1684 	/*
1685 	 * Now that the output file is created and symbol update has occurred,
1686 	 * process the relocations collected in process_reloc().
1687 	 */
1688 	if (do_sorted_outrelocs(ofl) == S_ERROR)
1689 		return (S_ERROR);
1690 
1691 	if (do_activerelocs(ofl) == S_ERROR)
1692 		return (S_ERROR);
1693 
1694 	if ((ofl->ofl_flags1 & FLG_OF1_RELCNT) == 0) {
1695 		/*
1696 		 * Process the relocation sections:
1697 		 *
1698 		 *  o	for each relocation section generated for the output
1699 		 *	image update its shdr information to reflect the
1700 		 *	symbol table it needs (sh_link) and the section to
1701 		 *	which the relocation must be applied (sh_info).
1702 		 */
1703 		for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) {
1704 			Listnode *	lnp2;
1705 			Os_desc *	osp;
1706 
1707 			for (LIST_TRAVERSE(&(sgp->sg_osdescs), lnp2, osp)) {
1708 				if (osp->os_relosdesc == 0)
1709 					continue;
1710 
1711 				shdr = osp->os_relosdesc->os_shdr;
1712 				shdr->sh_link = ndx;
1713 				/* LINTED */
1714 				shdr->sh_info = (Word)elf_ndxscn(osp->os_scn);
1715 			}
1716 		}
1717 
1718 		/*
1719 		 * Since the .rel[a] section is not tied to any specific
1720 		 * section, we'd of not found it above.
1721 		 */
1722 		if (ofl->ofl_osrel) {
1723 			shdr = ofl->ofl_osrel->os_shdr;
1724 			shdr->sh_link = ndx;
1725 			shdr->sh_info = 0;
1726 		}
1727 	} else {
1728 		/*
1729 		 * We only have two relocation sections here, (PLT's,
1730 		 * coalesced) so just hit them directly instead of stepping
1731 		 * over the output sections.
1732 		 */
1733 		if (ofl->ofl_osrelhead) {
1734 			shdr = ofl->ofl_osrelhead->os_shdr;
1735 			shdr->sh_link = ndx;
1736 			shdr->sh_info = 0;
1737 		}
1738 		if (ofl->ofl_osplt && ofl->ofl_osplt->os_relosdesc) {
1739 			shdr = ofl->ofl_osplt->os_relosdesc->os_shdr;
1740 			shdr->sh_link = ndx;
1741 			/* LINTED */
1742 			shdr->sh_info =
1743 			    (Word)elf_ndxscn(ofl->ofl_osplt->os_scn);
1744 		}
1745 	}
1746 
1747 	/*
1748 	 * If the -z text option was given, and we have output relocations
1749 	 * against a non-writable, allocatable section, issue a diagnostic and
1750 	 * return (the actual entries that caused this error would have been
1751 	 * output during the relocating section phase).
1752 	 */
1753 	if ((flags & (FLG_OF_PURETXT | FLG_OF_TEXTREL)) ==
1754 	    (FLG_OF_PURETXT | FLG_OF_TEXTREL)) {
1755 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_REMAIN_3));
1756 		return (S_ERROR);
1757 	}
1758 
1759 	/*
1760 	 * Finally, initialize the first got entry with the address of the
1761 	 * .dynamic section (_DYNAMIC).
1762 	 */
1763 	if (flags & FLG_OF_DYNAMIC) {
1764 		if (fillin_gotplt1(ofl) == S_ERROR)
1765 			return (S_ERROR);
1766 	}
1767 
1768 	return (1);
1769 }
1770 
1771 /*
1772  * If the -z text option was given, and we have output relocations against a
1773  * non-writable, allocatable section, issue a diagnostic. Print offending
1774  * symbols in tabular form similar to the way undefined symbols are presented.
1775  * Called from reloc_count().  The actual fatal error condition is triggered on
1776  * in reloc_process() above.
1777  *
1778  * Note.  For historic reasons -ztext is not a default option (however all OS
1779  * shared object builds use this option).  It can be argued that this option
1780  * should also be default when generating an a.out (see 1163979).  However, if
1781  * an a.out contains text relocations it is either because the user is creating
1782  * something pretty weird (they've used the -b or -znodefs options), or because
1783  * the library against which they're building wasn't constructed correctly (ie.
1784  * a function has a NOTYPE type, in which case the a.out won't generate an
1785  * associated plt).  In the latter case the builder of the a.out can't do
1786  * anything to fix the error - thus we've chosen not to give the user an error,
1787  * or warning, for this case.
1788  */
1789 
1790 void
1791 reloc_remain_title(int warning)
1792 {
1793 	const char	*str1;
1794 
1795 	if (warning)
1796 		str1 = MSG_INTL(MSG_REL_RMN_ITM_13);
1797 	else
1798 		str1 = MSG_INTL(MSG_REL_RMN_ITM_11);
1799 
1800 	eprintf(ERR_NONE, MSG_INTL(MSG_REL_REMAIN_FMT_1),
1801 		str1,
1802 		MSG_INTL(MSG_REL_RMN_ITM_31),
1803 		MSG_INTL(MSG_REL_RMN_ITM_12),
1804 		MSG_INTL(MSG_REL_RMN_ITM_2),
1805 		MSG_INTL(MSG_REL_RMN_ITM_32));
1806 
1807 }
1808 
1809 void
1810 reloc_remain_entry(Rel_desc *orsp, Os_desc *osp, Ofl_desc *ofl)
1811 {
1812 	static Boolean	reloc_title = TRUE;
1813 
1814 	/*
1815 	 * -ztextoff
1816 	 */
1817 	if (ofl->ofl_flags1 & FLG_OF1_TEXTOFF)
1818 		return;
1819 
1820 	/*
1821 	 * Only give relocation errors against loadable read-only segments.
1822 	 */
1823 	if ((orsp->rel_rtype == M_R_REGISTER) || (!osp) ||
1824 	    (osp->os_sgdesc->sg_phdr.p_type != PT_LOAD) ||
1825 	    (osp->os_sgdesc->sg_phdr.p_flags & PF_W))
1826 		return;
1827 
1828 	/*
1829 	 * If we are in -ztextwarn mode, it's a silent error if a relocation is
1830 	 * due to a 'WEAK REFERENCE'.  This is because if the symbol is not
1831 	 * provided at run-time we will not perform a text-relocation.
1832 	 */
1833 	if (((ofl->ofl_flags & FLG_OF_PURETXT) == 0) &&
1834 	    (ELF_ST_BIND(orsp->rel_sym->sd_sym->st_info) == STB_WEAK) &&
1835 	    (orsp->rel_sym->sd_shndx == SHN_UNDEF))
1836 		return;
1837 
1838 	if (reloc_title) {
1839 		/*
1840 		 * If building with '-ztext' then emit a fatal error.  If
1841 		 * building a executable then only emit a 'warning'.
1842 		 */
1843 		if (ofl->ofl_flags & FLG_OF_PURETXT)
1844 			reloc_remain_title(0);
1845 		else
1846 			reloc_remain_title(1);
1847 		reloc_title = FALSE;
1848 	}
1849 
1850 	eprintf(ERR_NONE, MSG_INTL(MSG_REL_REMAIN_2), demangle(orsp->rel_sname),
1851 	    EC_OFF(orsp->rel_roffset), orsp->rel_isdesc->is_file->ifl_name);
1852 }
1853 
1854 /*
1855  * The following functions are called from
1856  * machine functions defined in {sparc,i386,sparcv9}/machrel.c
1857  */
1858 
1859 /*
1860  * Move Section related function
1861  */
1862 static uintptr_t
1863 newroffset_for_move(Sym_desc *symd,
1864 	Move *mventry, Xword offset1, Xword *offset2)
1865 {
1866 	Psym_info	*psym = symd->sd_psyminfo;
1867 	Mv_itm		*itm;
1868 	Listnode	*lnp1;
1869 	int 		found = 0;
1870 
1871 	/*
1872 	 * Search for matching move entry
1873 	 */
1874 	found = 0;
1875 	for (LIST_TRAVERSE(&psym->psym_mvs, lnp1, itm)) {
1876 		if (itm->mv_ientry == mventry) {
1877 			found = 1;
1878 			break;
1879 		}
1880 	}
1881 	if (found == 0) {
1882 		/*
1883 		 * This should never happen.
1884 		 */
1885 		return (S_ERROR);
1886 	}
1887 
1888 	/*
1889 	 * Update r_offset
1890 	 */
1891 	*offset2 = (Xword)((itm->mv_oidx - 1)*sizeof (Move) +
1892 		offset1 % sizeof (Move));
1893 	return (1);
1894 }
1895 
1896 void
1897 adj_movereloc(Ofl_desc *ofl, Rel_desc *arsp)
1898 {
1899 	Move		*move = arsp->rel_move->mvd_move;
1900 	Sym_desc	*psdp = arsp->rel_move->mvd_sym;
1901 	Xword		newoffset;
1902 
1903 	if (arsp->rel_flags & FLG_REL_MOVETAB) {
1904 		/*
1905 		 * We are relocating the move table itself.
1906 		 */
1907 		(void) newroffset_for_move(psdp, move, arsp->rel_roffset,
1908 		    &newoffset);
1909 		DBG_CALL(Dbg_move_adjmovereloc(arsp->rel_roffset, newoffset,
1910 		    psdp->sd_name));
1911 		arsp->rel_roffset = newoffset;
1912 	} else {
1913 		/*
1914 		 * We are expanding the partial symbol.  So we are generating
1915 		 * the relocation entry relocating the expanded partial symbol.
1916 		 */
1917 		arsp->rel_roffset +=
1918 		    psdp->sd_sym->st_value -
1919 		    ofl->ofl_issunwdata1->is_osdesc->os_shdr->sh_addr;
1920 		DBG_CALL(Dbg_move_adjexpandreloc(arsp->rel_roffset,
1921 		    psdp->sd_name));
1922 	}
1923 }
1924 
1925 /*
1926  * Partially Initialized Symbol Handling routines
1927  * For sparc architecture, the second argument is reld->rel_raddend.
1928  * For i386  acrchitecure, the second argument is the value stored
1929  *	at the relocation target address.
1930  */
1931 Sym_desc *
1932 am_I_partial(Rel_desc *reld, Xword val)
1933 {
1934 	Ifl_desc *	ifile = reld->rel_sym->sd_isc->is_file;
1935 	int 		nlocs = ifile->ifl_locscnt, i;
1936 
1937 	for (i = 1; i < nlocs; i++) {
1938 		Sym *		osym;
1939 		Sym_desc *	symd = ifile->ifl_oldndx[i];
1940 
1941 		if ((osym = symd->sd_osym) == 0)
1942 			continue;
1943 		if ((symd->sd_flags & FLG_SY_PAREXPN) == 0)
1944 			continue;
1945 		if ((osym->st_value <= val) &&
1946 		    (osym->st_value + osym->st_size  > val))
1947 			return (symd);
1948 	}
1949 	return ((Sym_desc *) 0);
1950 }
1951 
1952 /*
1953  * Because of the combinations of 32-bit lib providing 64-bit support, and
1954  * visa-versa, the use of krtld's dorelocs can result in differing message
1955  * requirements that make msg.c/msg.h creation and chkmsg "interesting".
1956  * Thus the actual message files contain a couple of entries to satisfy
1957  * each architectures build.  Here we add dummy calls to quieten chkmsg.
1958  *
1959  * chkmsg: MSG_INTL(MSG_REL_NOFIT)
1960  * chkmsg: MSG_INTL(MSG_REL_NONALIGN)
1961  */
1962