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