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 2005 Sun Microsystems, Inc.  All rights reserved.
24  *	Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include	<string.h>
29 #include	<stdio.h>
30 #include	<strings.h>
31 #include	<sys/elf_amd64.h>
32 #include	<debug.h>
33 #include	<reloc.h>
34 #include	<msg.h>
35 #include	<_libld.h>
36 
37 Word
38 init_rel(Rel_desc *reld, void *reloc)
39 {
40 	Rela *	rel = (Rela *)reloc;
41 
42 	/* LINTED */
43 	reld->rel_rtype = (Word)ELF_R_TYPE(rel->r_info);
44 	reld->rel_roffset = rel->r_offset;
45 	reld->rel_raddend = rel->r_addend;
46 	reld->rel_typedata = 0;
47 
48 	reld->rel_flags |= FLG_REL_RELA;
49 
50 	return ((Word)ELF_R_SYM(rel->r_info));
51 }
52 
53 void
54 mach_eflags(Ehdr *ehdr, Ofl_desc *ofl)
55 {
56 	ofl->ofl_e_flags |= ehdr->e_flags;
57 }
58 
59 void
60 mach_make_dynamic(Ofl_desc *ofl, size_t *cnt)
61 {
62 	if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) {
63 		/*
64 		 * Create this entry if we are going to create a PLT table.
65 		 */
66 		if (ofl->ofl_pltcnt)
67 			(*cnt)++;		/* DT_PLTGOT */
68 	}
69 }
70 
71 void
72 mach_update_odynamic(Ofl_desc * ofl, Dyn ** dyn)
73 {
74 	if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) {
75 		if (ofl->ofl_pltcnt) {
76 			(*dyn)->d_tag = DT_PLTGOT;
77 			(*dyn)->d_un.d_ptr = fillin_gotplt2(ofl);
78 			(*dyn)++;
79 		}
80 	}
81 }
82 
83 Xword
84 calc_plt_addr(Sym_desc *sdp, Ofl_desc *ofl)
85 {
86 	Xword	value;
87 
88 	value = (Xword)(ofl->ofl_osplt->os_shdr->sh_addr) +
89 	    M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) * M_PLT_ENTSIZE);
90 	return (value);
91 }
92 
93 /*
94  *  Build a single plt entry - code is:
95  *	JMP	*name1@GOTPCREL(%rip)
96  *	PUSHL	$index
97  *	JMP	.PLT0
98  */
99 static unsigned char pltn_entry[M_PLT_ENTSIZE] = {
100 /* 0x00 jmpq *name1@GOTPCREL(%rip) */	0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
101 /* 0x06 pushq $index */			0x68, 0x00, 0x00, 0x00, 0x00,
102 /* 0x0b jmpq  .plt0(%rip) */		0xe9, 0x00, 0x00, 0x00, 0x00
103 /* 0x10 */
104 };
105 
106 static uintptr_t
107 plt_entry(Ofl_desc * ofl, Sym_desc * sdp)
108 {
109 	unsigned char	*plt0;
110 	unsigned char	*pltent, *gotent;
111 	Sword		plt_off;
112 	Word		got_off;
113 	Xword		val1;
114 	Word		flags = ofl->ofl_flags;
115 	Word		dtflags1 = ofl->ofl_dtflags_1;
116 
117 	got_off = sdp->sd_aux->sa_PLTGOTndx * M_GOT_ENTSIZE;
118 	plt_off = M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) *
119 	    M_PLT_ENTSIZE);
120 	plt0 = (unsigned char *)(ofl->ofl_osplt->os_outdata->d_buf);
121 	pltent = plt0 + plt_off;
122 	gotent = (unsigned char *)(ofl->ofl_osgot->os_outdata->d_buf) + got_off;
123 
124 	bcopy(pltn_entry, pltent, sizeof (pltn_entry));
125 	/*
126 	 * Fill in the got entry with the address of the next instruction.
127 	 */
128 	/* LINTED */
129 	*(Word *)gotent = ((uintptr_t)ofl->ofl_osplt->os_shdr->sh_addr +
130 		(uintptr_t)plt_off + M_PLT_INSSIZE);
131 
132 	/*
133 	 * patchup:
134 	 *	jmpq	*name1@gotpcrel(%rip)
135 	 *
136 	 * NOTE: 0x06 represents next instruction.
137 	 */
138 	val1 = (ofl->ofl_osgot->os_shdr->sh_addr + got_off) -
139 		(ofl->ofl_osplt->os_shdr->sh_addr + plt_off) - 0x06;
140 
141 	/*
142 	 * If '-z noreloc' is specified - skip the do_reloc
143 	 * stage.
144 	 */
145 	if ((flags & FLG_OF_RELOBJ) ||
146 	    !(dtflags1 & DF_1_NORELOC)) {
147 		if (do_reloc(R_AMD64_GOTPCREL, &pltent[0x02],
148 		    &val1, MSG_ORIG(MSG_SYM_PLTENT),
149 		    MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) {
150 			eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL),
151 				sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name));
152 			return (S_ERROR);
153 		}
154 	}
155 
156 	/*
157 	 * patchup:
158 	 *	pushq	$pltndx
159 	 */
160 	val1 = (Xword)(sdp->sd_aux->sa_PLTndx - 1);
161 	/*
162 	 * If '-z noreloc' is specified - skip the do_reloc
163 	 * stage.
164 	 */
165 	if ((flags & FLG_OF_RELOBJ) ||
166 	    !(dtflags1 & DF_1_NORELOC)) {
167 		if (do_reloc(R_AMD64_32, &pltent[0x07],
168 		    &val1, MSG_ORIG(MSG_SYM_PLTENT),
169 		    MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) {
170 			eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL),
171 				sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name));
172 			return (S_ERROR);
173 		}
174 	}
175 
176 	/*
177 	 * patchup:
178 	 *	jmpq	.plt0(%rip)
179 	 * NOTE: 0x10 represents next instruction
180 	 */
181 	val1 = (Xword)((Xword)plt0 - (uintptr_t)(&pltent[0x10]));
182 	/*
183 	 * If '-z noreloc' is specified - skip the do_reloc
184 	 * stage.
185 	 */
186 	if ((flags & FLG_OF_RELOBJ) ||
187 	    !(dtflags1 & DF_1_NORELOC)) {
188 		if (do_reloc(R_AMD64_PC32, &pltent[0x0c],
189 		    &val1, MSG_ORIG(MSG_SYM_PLTENT),
190 		    MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) {
191 			eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL),
192 				sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name));
193 			return (S_ERROR);
194 		}
195 	}
196 	return (1);
197 }
198 
199 uintptr_t
200 perform_outreloc(Rel_desc * orsp, Ofl_desc * ofl)
201 {
202 	Os_desc *	relosp, * osp = 0;
203 	Word		ndx;
204 	Xword		roffset, value;
205 	Sxword		raddend;
206 	Rela		rea;
207 	char		*relbits;
208 	Sym_desc *	sdp, * psym = (Sym_desc *)0;
209 	int		sectmoved = 0;
210 
211 	raddend = orsp->rel_raddend;
212 	sdp = orsp->rel_sym;
213 
214 	/*
215 	 * If the section this relocation is against has been discarded
216 	 * (-zignore), then also discard (skip) the relocation itself.
217 	 */
218 	if (orsp->rel_isdesc && ((orsp->rel_flags &
219 	    (FLG_REL_GOT | FLG_REL_BSS | FLG_REL_PLT | FLG_REL_NOINFO)) == 0) &&
220 	    (orsp->rel_isdesc->is_flags & FLG_IS_DISCARD)) {
221 		DBG_CALL(Dbg_reloc_discard(M_MACH, orsp));
222 		return (1);
223 	}
224 
225 	/*
226 	 * If this is a relocation against a move table, or expanded move
227 	 * table, adjust the relocation entries.
228 	 */
229 	if (orsp->rel_move)
230 		adj_movereloc(ofl, orsp);
231 
232 	/*
233 	 * If this is a relocation against a section then we need to adjust the
234 	 * raddend field to compensate for the new position of the input section
235 	 * within the new output section.
236 	 */
237 	if (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) {
238 		if (ofl->ofl_parsym.head &&
239 		    (sdp->sd_isc->is_flags & FLG_IS_RELUPD) &&
240 		    /* LINTED */
241 		    (psym = am_I_partial(orsp, orsp->rel_raddend))) {
242 			DBG_CALL(Dbg_move_outsctadj(psym));
243 			sectmoved = 1;
244 			if (ofl->ofl_flags & FLG_OF_RELOBJ)
245 				raddend = psym->sd_sym->st_value;
246 			else
247 				raddend = psym->sd_sym->st_value -
248 				    psym->sd_isc->is_osdesc->os_shdr->sh_addr;
249 			/* LINTED */
250 			raddend += (Off)_elf_getxoff(psym->sd_isc->is_indata);
251 			if (psym->sd_isc->is_shdr->sh_flags & SHF_ALLOC)
252 				raddend +=
253 				psym->sd_isc->is_osdesc->os_shdr->sh_addr;
254 		} else {
255 			/* LINTED */
256 			raddend += (Off)_elf_getxoff(sdp->sd_isc->is_indata);
257 			if (sdp->sd_isc->is_shdr->sh_flags & SHF_ALLOC)
258 				raddend +=
259 				sdp->sd_isc->is_osdesc->os_shdr->sh_addr;
260 		}
261 	}
262 
263 	value = sdp->sd_sym->st_value;
264 
265 	if (orsp->rel_flags & FLG_REL_GOT) {
266 		/*
267 		 * Note: for GOT relative relocations on amd64
268 		 *	 we discard the addend.  It was relevant
269 		 *	 to the reference - not to the data item
270 		 *	 being referenced (ie: that -4 thing).
271 		 */
272 		raddend = 0;
273 		osp = ofl->ofl_osgot;
274 		roffset = calc_got_offset(orsp, ofl);
275 	} else if (orsp->rel_flags & FLG_REL_PLT) {
276 		/*
277 		 * Note that relocations for PLT's actually
278 		 * cause a relocation againt the GOT.
279 		 */
280 		osp = ofl->ofl_osplt;
281 		roffset = (ofl->ofl_osgot->os_shdr->sh_addr) +
282 		    sdp->sd_aux->sa_PLTGOTndx * M_GOT_ENTSIZE;
283 		raddend = 0;
284 		if (plt_entry(ofl, sdp) == S_ERROR)
285 			return (S_ERROR);
286 
287 	} else if (orsp->rel_flags & FLG_REL_BSS) {
288 		/*
289 		 * This must be a R_AMD64_COPY.  For these set the roffset to
290 		 * point to the new symbols location.
291 		 */
292 		osp = ofl->ofl_isbss->is_osdesc;
293 		roffset = value;
294 
295 		/*
296 		 * The raddend doesn't mean anything in a R_SPARC_COPY
297 		 * relocation.  Null it out because it can confuse people.
298 		 */
299 		raddend = 0;
300 	} else {
301 		osp = orsp->rel_osdesc;
302 
303 		/*
304 		 * Calculate virtual offset of reference point; equals offset
305 		 * into section + vaddr of section for loadable sections, or
306 		 * offset plus section displacement for nonloadable sections.
307 		 */
308 		roffset = orsp->rel_roffset +
309 		    (Off)_elf_getxoff(orsp->rel_isdesc->is_indata);
310 		if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
311 			roffset += orsp->rel_isdesc->is_osdesc->
312 			    os_shdr->sh_addr;
313 	}
314 
315 	if ((osp == 0) || ((relosp = osp->os_relosdesc) == 0))
316 		relosp = ofl->ofl_osrel;
317 
318 	/*
319 	 * Assign the symbols index for the output relocation.  If the
320 	 * relocation refers to a SECTION symbol then it's index is based upon
321 	 * the output sections symbols index.  Otherwise the index can be
322 	 * derived from the symbols index itself.
323 	 */
324 	if (orsp->rel_rtype == R_AMD64_RELATIVE)
325 		ndx = STN_UNDEF;
326 	else if ((orsp->rel_flags & FLG_REL_SCNNDX) ||
327 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)) {
328 		if (sectmoved == 0) {
329 			/*
330 			 * Check for a null input section. This can
331 			 * occur if this relocation references a symbol
332 			 * generated by sym_add_sym().
333 			 */
334 			if ((sdp->sd_isc != 0) &&
335 			    (sdp->sd_isc->is_osdesc != 0))
336 				ndx = sdp->sd_isc->is_osdesc->os_scnsymndx;
337 			else
338 				ndx = sdp->sd_shndx;
339 		} else
340 			ndx = ofl->ofl_sunwdata1ndx;
341 	} else
342 		ndx = sdp->sd_symndx;
343 
344 	/*
345 	 * Add the symbols 'value' to the addend field.
346 	 */
347 	if (orsp->rel_flags & FLG_REL_ADVAL)
348 		raddend += value;
349 
350 	/*
351 	 * addend field for R_AMD64_DTPMOD64 means nothing.  The addend
352 	 * is propogated in the corresponding R_AMD64_DTPOFF64
353 	 * relocation.
354 	 */
355 	if (orsp->rel_rtype == R_AMD64_DTPMOD64)
356 		raddend = 0;
357 
358 	relbits = (char *)relosp->os_outdata->d_buf;
359 
360 	rea.r_info = ELF_R_INFO(ndx, orsp->rel_rtype);
361 	rea.r_offset = roffset;
362 	rea.r_addend = raddend;
363 	DBG_CALL(Dbg_reloc_out(M_MACH, SHT_RELA, &rea, orsp->rel_sname,
364 	    relosp->os_name));
365 
366 	/*
367 	 * Assert we haven't walked off the end of our relocation table.
368 	 */
369 	assert(relosp->os_szoutrels <= relosp->os_shdr->sh_size);
370 
371 	(void) memcpy((relbits + relosp->os_szoutrels),
372 	    (char *)&rea, sizeof (Rela));
373 	relosp->os_szoutrels += (Xword)sizeof (Rela);
374 
375 	/*
376 	 * Determine if this relocation is against a non-writable, allocatable
377 	 * section.  If so we may need to provide a text relocation diagnostic.
378 	 * Note that relocations against the .plt (R_AMD64_JUMP_SLOT) actually
379 	 * result in modifications to the .got.
380 	 */
381 	if (orsp->rel_rtype == R_AMD64_JUMP_SLOT)
382 		osp = ofl->ofl_osgot;
383 
384 	reloc_remain_entry(orsp, osp, ofl);
385 	return (1);
386 }
387 
388 /*
389  * amd64 Instructions for TLS processing
390  */
391 static unsigned char tlsinstr_gd_ie[] = {
392 	/*
393 	 *	0x00 movq %fs:0, %rax
394 	 */
395 	0x64, 0x48, 0x8b, 0x04, 0x25,
396 	0x00, 0x00, 0x00, 0x00,
397 	/*
398 	 *	0x09 addq x@gottpoff(%rip), %rax
399 	 */
400 	0x48, 0x03, 0x05, 0x00, 0x00,
401 	0x00, 0x00
402 };
403 
404 static unsigned char tlsinstr_gd_le[] = {
405 	/*
406 	 *	0x00 movq %fs:0, %rax
407 	 */
408 	0x64, 0x48, 0x8b, 0x04, 0x25,
409 	0x00, 0x00, 0x00, 0x00,
410 	/*
411 	 *	0x09 leaq x@gottpoff(%rip), %rax
412 	 */
413 	0x48, 0x8d, 0x80, 0x00, 0x00,
414 	0x00, 0x00
415 };
416 
417 static unsigned char tlsinstr_ld_le[] = {
418 	/*
419 	 * .byte 0x66
420 	 */
421 	0x66,
422 	/*
423 	 * .byte 0x66
424 	 */
425 	0x66,
426 	/*
427 	 * .byte 0x66
428 	 */
429 	0x66,
430 	/*
431 	 * movq %fs:0, %rax
432 	 */
433 	0x64, 0x48, 0x8b, 0x04, 0x25,
434 	0x00, 0x00, 0x00, 0x00
435 };
436 
437 
438 Fixupret
439 tls_fixups(Rel_desc *arsp)
440 {
441 	Sym_desc	*sdp = arsp->rel_sym;
442 	Word		rtype = arsp->rel_rtype;
443 	unsigned char	*offset;
444 
445 	offset = (unsigned char *)(arsp->rel_roffset +
446 		_elf_getxoff(arsp->rel_isdesc->is_indata) +
447 		(uintptr_t)arsp->rel_osdesc->os_outdata->d_buf);
448 
449 
450 	if (sdp->sd_ref == REF_DYN_NEED) {
451 		/*
452 		 * IE reference model
453 		 */
454 		switch (rtype) {
455 		case R_AMD64_TLSGD:
456 			/*
457 			 *  GD -> IE
458 			 *
459 			 * Transition:
460 			 *	0x00 .byte 0x66
461 			 *	0x01 leaq x@tlsgd(%rip), %rdi
462 			 *	0x08 .word 0x6666
463 			 *	0x0a rex64
464 			 *	0x0b call __tls_get_addr@plt
465 			 *	0x10
466 			 * To:
467 			 *	0x00 movq %fs:0, %rax
468 			 *	0x09 addq x@gottpoff(%rip), %rax
469 			 *	0x10
470 			 */
471 			DBG_CALL(Dbg_reloc_transition(M_MACH,
472 				rtype,
473 				R_AMD64_GOTTPOFF,
474 				arsp->rel_roffset,
475 				sdp->sd_name));
476 			arsp->rel_rtype = R_AMD64_GOTTPOFF;
477 			arsp->rel_roffset += 8;
478 			arsp->rel_raddend = (Sxword)-4;
479 			/*
480 			 * Addjust 'offset' to beginning of instruction
481 			 * sequence.
482 			 */
483 			offset -= 4;
484 			(void) memcpy(offset, tlsinstr_gd_ie,
485 				sizeof (tlsinstr_gd_ie));
486 			return (FIX_RELOC);
487 		case R_AMD64_PLT32:
488 			/*
489 			 * Fixup done via the TLS_GD relocation
490 			 */
491 			DBG_CALL(Dbg_reloc_transition(M_MACH,
492 				rtype,
493 				R_AMD64_NONE,
494 				arsp->rel_roffset,
495 				sdp->sd_name));
496 			return (FIX_DONE);
497 		}
498 	}
499 
500 	/*
501 	 * LE reference model
502 	 */
503 	switch (rtype) {
504 	case R_AMD64_TLSGD:
505 		/*
506 		 * GD -> LE
507 		 *
508 		 * Transition:
509 		 *	0x00 .byte 0x66
510 		 *	0x01 leaq x@tlsgd(%rip), %rdi
511 		 *	0x08 .word 0x6666
512 		 *	0x0a rex64
513 		 *	0x0b call __tls_get_addr@plt
514 		 *	0x10
515 		 * To:
516 		 *	0x00 movq %fs:0, %rax
517 		 *	0x09 leaq x@tpoff(%rax), %rax
518 		 *	0x10
519 		 */
520 		DBG_CALL(Dbg_reloc_transition(M_MACH,
521 			rtype,
522 			R_AMD64_TPOFF32,
523 			arsp->rel_roffset,
524 			sdp->sd_name));
525 
526 		arsp->rel_rtype = R_AMD64_TPOFF32;
527 		arsp->rel_roffset += 8;
528 		arsp->rel_raddend = 0;
529 		/*
530 		 * Addjust 'offset' to beginning of instruction
531 		 * sequence.
532 		 */
533 		offset -= 4;
534 		(void) memcpy(offset, tlsinstr_gd_le,
535 			sizeof (tlsinstr_gd_le));
536 		return (FIX_RELOC);
537 	case R_AMD64_GOTTPOFF:
538 		/*
539 		 * IE -> LE
540 		 *
541 		 * Transition:
542 		 *	0x00 movq %fs:0, %rax
543 		 *	0x09 addq x@gottopoff(%rip), %rax
544 		 *	0x10
545 		 * To:
546 		 *	0x00 movq %fs:0, %rax
547 		 *	0x09 leaq x@tpoff(%rax), %rax
548 		 *	0x10
549 		 */
550 		DBG_CALL(Dbg_reloc_transition(M_MACH,
551 			rtype,
552 			R_AMD64_TPOFF32,
553 			arsp->rel_roffset,
554 			sdp->sd_name));
555 
556 		arsp->rel_rtype = R_AMD64_TPOFF32;
557 		arsp->rel_raddend = 0;
558 		/*
559 		 * Addjust 'offset' to beginning of instruction
560 		 * sequence.
561 		 */
562 		offset -= 12;
563 		/*
564 		 * Same code sequence used in the GD -> LE
565 		 * transition.
566 		 */
567 		(void) memcpy(offset, tlsinstr_gd_le,
568 			sizeof (tlsinstr_gd_le));
569 		return (FIX_RELOC);
570 	case R_AMD64_TLSLD:
571 		/*
572 		 * LD -> LE
573 		 *
574 		 * Transition
575 		 *	0x00 leaq x1@tlsgd(%rip), %rdi
576 		 *	0x07 call __tls_get_addr@plt
577 		 *	0x0c
578 		 * To:
579 		 *	0x00 .byte 0x66
580 		 *	0x01 .byte 0x66
581 		 *	0x02 .byte 0x66
582 		 *	0x03 movq %fs:0, %rax
583 		 */
584 		DBG_CALL(Dbg_reloc_transition(M_MACH,
585 			rtype,
586 			R_AMD64_NONE,
587 			arsp->rel_roffset,
588 			sdp->sd_name));
589 		offset -= 3;
590 		(void) memcpy(offset, tlsinstr_ld_le,
591 			sizeof (tlsinstr_ld_le));
592 		return (FIX_DONE);
593 	case R_AMD64_DTPOFF32:
594 		/*
595 		 * LD->LE
596 		 *
597 		 * Transition:
598 		 *	0x00 leaq x1@dtpoff(%rax), %rcx
599 		 * To:
600 		 *	0x00 leaq x1@tpoff(%rax), %rcx
601 		 */
602 		DBG_CALL(Dbg_reloc_transition(M_MACH,
603 			rtype,
604 			R_AMD64_TPOFF32,
605 			arsp->rel_roffset,
606 			sdp->sd_name));
607 		arsp->rel_rtype = R_AMD64_TPOFF32;
608 		arsp->rel_raddend = 0;
609 		return (FIX_RELOC);
610 	}
611 
612 	return (FIX_RELOC);
613 }
614 
615 uintptr_t
616 do_activerelocs(Ofl_desc *ofl)
617 {
618 	Rel_desc *	arsp;
619 	Rel_cache *	rcp;
620 	Listnode *	lnp;
621 	uintptr_t	return_code = 1;
622 	Word		flags = ofl->ofl_flags;
623 	Word		dtflags1 = ofl->ofl_dtflags_1;
624 
625 	DBG_CALL(Dbg_reloc_doactiverel());
626 	/*
627 	 * process active relocs
628 	 */
629 	for (LIST_TRAVERSE(&ofl->ofl_actrels, lnp, rcp)) {
630 		/* LINTED */
631 		for (arsp = (Rel_desc *)(rcp + 1);
632 		    arsp < rcp->rc_free; arsp++) {
633 			unsigned char	*addr;
634 			Xword 		value;
635 			Sym_desc	*sdp;
636 			const char	*ifl_name;
637 			Xword		refaddr;
638 			int		moved = 0;
639 			Gotref		gref;
640 
641 			/*
642 			 * If the section this relocation is against has been
643 			 * discarded (-zignore), then discard (skip) the
644 			 * relocation itself.
645 			 */
646 			if ((arsp->rel_isdesc->is_flags & FLG_IS_DISCARD) &&
647 			    ((arsp->rel_flags &
648 			    (FLG_REL_GOT | FLG_REL_BSS |
649 			    FLG_REL_PLT | FLG_REL_NOINFO)) == 0)) {
650 				DBG_CALL(Dbg_reloc_discard(M_MACH, arsp));
651 				continue;
652 			}
653 
654 			/*
655 			 * We deteremine what the 'got reference'
656 			 * model (if required) is at this point.  This
657 			 * needs to be done before tls_fixup() since
658 			 * it may 'transition' our instructions.
659 			 *
660 			 * The got table entries have already been assigned,
661 			 * and we bind to those initial entries.
662 			 */
663 			if (arsp->rel_flags & FLG_REL_DTLS)
664 				gref = GOT_REF_TLSGD;
665 			else if (arsp->rel_flags & FLG_REL_MTLS)
666 				gref = GOT_REF_TLSLD;
667 			else if (arsp->rel_flags & FLG_REL_STLS)
668 				gref = GOT_REF_TLSIE;
669 			else
670 				gref = GOT_REF_GENERIC;
671 
672 			/*
673 			 * Perform any required TLS fixups.
674 			 */
675 			if (arsp->rel_flags & FLG_REL_TLSFIX) {
676 				Fixupret	ret;
677 				if ((ret = tls_fixups(arsp)) == FIX_ERROR)
678 					return (S_ERROR);
679 				if (ret == FIX_DONE)
680 					continue;
681 			}
682 
683 			/*
684 			 * If this is a relocation against a move table, or
685 			 * expanded move table, adjust the relocation entries.
686 			 */
687 			if (arsp->rel_move)
688 				adj_movereloc(ofl, arsp);
689 
690 			sdp = arsp->rel_sym;
691 			refaddr = arsp->rel_roffset +
692 			    (Off)_elf_getxoff(arsp->rel_isdesc->is_indata);
693 
694 			if ((arsp->rel_flags & FLG_REL_CLVAL) ||
695 			    (arsp->rel_flags & FLG_REL_GOTCL))
696 				value = 0;
697 			else if (ELF_ST_TYPE(sdp->sd_sym->st_info) ==
698 			    STT_SECTION) {
699 				Sym_desc *	sym;
700 
701 				/*
702 				 * The value for a symbol pointing to a SECTION
703 				 * is based off of that sections position.
704 				 *
705 				 * The second argument of the am_I_partial() is
706 				 * the value stored at the target address
707 				 * relocation is going to be applied.
708 				 */
709 				if ((sdp->sd_isc->is_flags & FLG_IS_RELUPD) &&
710 				    /* LINTED */
711 				    (sym = am_I_partial(arsp, *(Xword *)
712 				    ((unsigned char *)
713 				    (arsp->rel_isdesc->is_indata->d_buf) +
714 				    arsp->rel_roffset)))) {
715 					/*
716 					 * If the symbol is moved,
717 					 * adjust the value
718 					 */
719 					value = sym->sd_sym->st_value;
720 					moved = 1;
721 				} else {
722 					value = (Off)_elf_getxoff(sdp->sd_isc->
723 					    is_indata);
724 					if (sdp->sd_isc->is_shdr->sh_flags &
725 					    SHF_ALLOC)
726 					    value += sdp->sd_isc->is_osdesc->
727 					    os_shdr->sh_addr;
728 				}
729 				if (sdp->sd_isc->is_shdr->sh_flags & SHF_TLS)
730 					value -= ofl->ofl_tlsphdr->p_vaddr;
731 			} else
732 				/*
733 				 * else the value is the symbols value
734 				 */
735 				value = sdp->sd_sym->st_value;
736 
737 			/*
738 			 * Relocation against the GLOBAL_OFFSET_TABLE.
739 			 */
740 			if (arsp->rel_flags & FLG_REL_GOT)
741 				arsp->rel_osdesc = ofl->ofl_osgot;
742 
743 			/*
744 			 * If loadable and not producing a relocatable object
745 			 * add the sections virtual address to the reference
746 			 * address.
747 			 */
748 			if ((arsp->rel_flags & FLG_REL_LOAD) &&
749 			    !(ofl->ofl_flags & FLG_OF_RELOBJ))
750 				refaddr += arsp->rel_isdesc->is_osdesc->
751 				    os_shdr->sh_addr;
752 
753 
754 			/*
755 			 * If this entry has a PLT assigned to it, it's
756 			 * value is actually the address of the PLT (and
757 			 * not the address of the function).
758 			 */
759 			if (IS_PLT(arsp->rel_rtype)) {
760 				if (sdp->sd_aux && sdp->sd_aux->sa_PLTndx)
761 					value = calc_plt_addr(sdp, ofl);
762 			}
763 
764 			/*
765 			 * Add relocations addend to value.  Add extra
766 			 * relocation addend if needed.
767 			 *
768 			 * Note: for GOT relative relocations on amd64
769 			 *	 we discard the addend.  It was relevant
770 			 *	 to the reference - not to the data item
771 			 *	 being referenced (ie: that -4 thing).
772 			 */
773 			if ((arsp->rel_flags & FLG_REL_GOT) == 0)
774 				value += arsp->rel_raddend;
775 
776 			if (arsp->rel_flags & FLG_REL_GOT) {
777 				Xword		R1addr;
778 				uintptr_t	R2addr;
779 				Word		gotndx;
780 				Gotndx		*gnp;
781 
782 				/*
783 				 * Perform relocation against GOT table.  Since
784 				 * this doesn't fit exactly into a relocation
785 				 * we place the appropriate byte in the GOT
786 				 * directly
787 				 *
788 				 * Calculate offset into GOT at which to apply
789 				 * the relocation.
790 				 */
791 				gnp = find_gotndx(&(sdp->sd_GOTndxs), gref,
792 				    ofl, arsp);
793 				assert(gnp);
794 
795 				if (arsp->rel_rtype == R_AMD64_DTPOFF64)
796 					gotndx = gnp->gn_gotndx + 1;
797 				else
798 					gotndx = gnp->gn_gotndx;
799 
800 				R1addr = (Xword)(gotndx * M_GOT_ENTSIZE);
801 
802 				/*
803 				 * Add the GOTs data's offset.
804 				 */
805 				R2addr = R1addr + (uintptr_t)
806 				    arsp->rel_osdesc->os_outdata->d_buf;
807 
808 				DBG_CALL(Dbg_reloc_doact(M_MACH,
809 				    arsp->rel_rtype, R1addr, value,
810 				    arsp->rel_sname, arsp->rel_osdesc));
811 
812 				/*
813 				 * And do it.
814 				 */
815 				*(Xword *)R2addr = (Xword)value;
816 				continue;
817 
818 			} else if (IS_GOT_BASED(arsp->rel_rtype)) {
819 				value -= ofl->ofl_osgot->os_shdr->sh_addr;
820 			} else if (IS_GOTPCREL(arsp->rel_rtype)) {
821 				Gotndx *	gnp;
822 				/*
823 				 * Calculation:
824 				 *	G + GOT + A - P
825 				 */
826 				gnp = find_gotndx(&(sdp->sd_GOTndxs),
827 				    gref, ofl, arsp);
828 				assert(gnp != 0);
829 				value = (Xword)(ofl->ofl_osgot->os_shdr->
830 				    sh_addr) + ((Xword)gnp->gn_gotndx *
831 				    M_GOT_ENTSIZE) + arsp->rel_raddend -
832 				    refaddr;
833 			} else if (IS_GOT_PC(arsp->rel_rtype)) {
834 				value = (Xword) (ofl->ofl_osgot->os_shdr->
835 				    sh_addr) - refaddr;
836 			} else if ((IS_PC_RELATIVE(arsp->rel_rtype)) &&
837 			    (!(ofl->ofl_flags & FLG_OF_RELOBJ) ||
838 			    (arsp->rel_osdesc == sdp->sd_isc->is_osdesc))) {
839 				value -= refaddr;
840 			} else if (IS_TLS_INS(arsp->rel_rtype) &&
841 			    IS_GOT_RELATIVE(arsp->rel_rtype)) {
842 				Gotndx	*gnp;
843 
844 				gnp = find_gotndx(&(sdp->sd_GOTndxs), gref,
845 				    ofl, arsp);
846 				assert(gnp != 0);
847 				value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
848 			} else if (IS_GOT_RELATIVE(arsp->rel_rtype)) {
849 				Gotndx *	gnp;
850 
851 				gnp = find_gotndx(&(sdp->sd_GOTndxs),
852 				    gref, ofl, arsp);
853 				assert(gnp);
854 				value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
855 			} else if (arsp->rel_flags & FLG_REL_STLS) {
856 				Xword	tlsstatsize;
857 				/*
858 				 * This is the LE TLS reference model.  Static
859 				 * offset is hard-coded.
860 				 */
861 				tlsstatsize = S_ROUND(ofl->
862 				    ofl_tlsphdr->p_memsz,
863 				    M_TLSSTATALIGN);
864 				value = tlsstatsize - value;
865 				/*
866 				 * Since this code is fixedup
867 				 * it assumes a negative offset
868 				 * that can be added to the thread pointer
869 				 */
870 				if (arsp->rel_rtype == R_AMD64_TPOFF32)
871 					value = -value;
872 			}
873 
874 			if (arsp->rel_isdesc->is_file)
875 				ifl_name = arsp->rel_isdesc->is_file->ifl_name;
876 			else
877 				ifl_name = MSG_INTL(MSG_STR_NULL);
878 
879 			/*
880 			 * Make sure we have data to relocate.  Compiler and
881 			 * assembler developers have been known to generate
882 			 * relocations against invalid sections (normally .bss),
883 			 * so for their benefit give them sufficient information
884 			 * to help analyze the problem.  End users should never
885 			 * see this.
886 			 */
887 			if (arsp->rel_isdesc->is_indata->d_buf == 0) {
888 				eprintf(ERR_FATAL, MSG_INTL(MSG_REL_EMPTYSEC),
889 				    conv_reloc_amd64_type_str(arsp->rel_rtype),
890 				    ifl_name, demangle(arsp->rel_sname),
891 				    arsp->rel_isdesc->is_name);
892 				return (S_ERROR);
893 			}
894 
895 			/*
896 			 * Get the address of the data item we need to modify.
897 			 */
898 			addr = (unsigned char *)_elf_getxoff(arsp->rel_isdesc->
899 			    is_indata) + arsp->rel_roffset;
900 
901 			/* LINTED */
902 			DBG_CALL(Dbg_reloc_doact(M_MACH, arsp->rel_rtype,
903 			    (Xword)addr, value, arsp->rel_sname,
904 			    arsp->rel_osdesc));
905 			addr += (uintptr_t)arsp->rel_osdesc->os_outdata->d_buf;
906 
907 			if ((((uintptr_t)addr - (uintptr_t)ofl->ofl_ehdr) >
908 			    ofl->ofl_size) || (arsp->rel_roffset >
909 			    arsp->rel_osdesc->os_shdr->sh_size)) {
910 				int	class;
911 
912 				if (((uintptr_t)addr - (Xword)ofl->ofl_ehdr) >
913 				    ofl->ofl_size)
914 					class = ERR_FATAL;
915 				else
916 					class = ERR_WARNING;
917 
918 				eprintf(class, MSG_INTL(MSG_REL_INVALOFFSET),
919 				    conv_reloc_amd64_type_str(arsp->rel_rtype),
920 				    ifl_name, arsp->rel_isdesc->is_name,
921 				    demangle(arsp->rel_sname),
922 				    EC_ADDR((uintptr_t)addr -
923 				    (uintptr_t)ofl->ofl_ehdr));
924 
925 				if (class == ERR_FATAL) {
926 					return_code = S_ERROR;
927 					continue;
928 				}
929 			}
930 
931 			/*
932 			 * The relocation is additive.  Ignore the previous
933 			 * symbol value if this local partial symbol is
934 			 * expanded.
935 			 */
936 			if (moved)
937 				value -= *addr;
938 
939 			/*
940 			 * If '-z noreloc' is specified - skip the do_reloc
941 			 * stage.
942 			 */
943 			if ((flags & FLG_OF_RELOBJ) ||
944 			    !(dtflags1 & DF_1_NORELOC)) {
945 				if (do_reloc((unsigned char)arsp->rel_rtype,
946 				    addr, &value, arsp->rel_sname,
947 				    ifl_name) == 0)
948 					return_code = S_ERROR;
949 			}
950 		}
951 	}
952 	return (return_code);
953 }
954 
955 uintptr_t
956 add_outrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
957 {
958 	Rel_desc *	orsp;
959 	Rel_cache *	rcp;
960 	Sym_desc *	sdp = rsp->rel_sym;
961 
962 	/*
963 	 * Static executables *do not* want any relocations against them.
964 	 * Since our engine still creates relocations against a WEAK UNDEFINED
965 	 * symbol in a static executable, it's best to disable them here
966 	 * instead of through out the relocation code.
967 	 */
968 	if ((ofl->ofl_flags & (FLG_OF_STATIC | FLG_OF_EXEC)) ==
969 	    (FLG_OF_STATIC | FLG_OF_EXEC))
970 		return (1);
971 
972 	/*
973 	 * If no relocation cache structures are available allocate
974 	 * a new one and link it into the cache list.
975 	 */
976 	if ((ofl->ofl_outrels.tail == 0) ||
977 	    ((rcp = (Rel_cache *)ofl->ofl_outrels.tail->data) == 0) ||
978 	    ((orsp = rcp->rc_free) == rcp->rc_end)) {
979 		static size_t	nextsize = 0;
980 		size_t		size;
981 
982 		/*
983 		 * Output relocation numbers can vary considerably between
984 		 * building executables or shared objects (pic vs. non-pic),
985 		 * etc.  But, they typically aren't very large, so for these
986 		 * objects use a standard bucket size.  For building relocatable
987 		 * objects, typically there will be an output relocation for
988 		 * every input relocation.
989 		 */
990 		if (nextsize == 0) {
991 			if (ofl->ofl_flags & FLG_OF_RELOBJ) {
992 				if ((size = ofl->ofl_relocincnt) == 0)
993 					size = REL_LOIDESCNO;
994 				if (size > REL_HOIDESCNO)
995 					nextsize = REL_HOIDESCNO;
996 				else
997 					nextsize = REL_LOIDESCNO;
998 			} else
999 				nextsize = size = REL_HOIDESCNO;
1000 		} else
1001 			size = nextsize;
1002 
1003 		size = size * sizeof (Rel_desc);
1004 
1005 		if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) ||
1006 		    (list_appendc(&ofl->ofl_outrels, rcp) == 0))
1007 			return (S_ERROR);
1008 
1009 		/* LINTED */
1010 		rcp->rc_free = orsp = (Rel_desc *)(rcp + 1);
1011 		/* LINTED */
1012 		rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size);
1013 	}
1014 
1015 	/*
1016 	 * If we are adding a output relocation against a section
1017 	 * symbol (non-RELATIVE) then mark that section.  These sections
1018 	 * will be added to the .dynsym symbol table.
1019 	 */
1020 	if (sdp && (rsp->rel_rtype != M_R_RELATIVE) &&
1021 	    ((flags & FLG_REL_SCNNDX) ||
1022 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION))) {
1023 
1024 		/*
1025 		 * If this is a COMMON symbol - no output section
1026 		 * exists yet - (it's created as part of sym_validate()).
1027 		 * So - we mark here that when it's created it should
1028 		 * be tagged with the FLG_OS_OUTREL flag.
1029 		 */
1030 		if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
1031 		    (sdp->sd_shndx == SHN_COMMON))
1032 			if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS)
1033 				ofl->ofl_flags1 |= FLG_OF1_BSSOREL;
1034 			else
1035 				ofl->ofl_flags1 |= FLG_OF1_TLSOREL;
1036 		else {
1037 			Os_desc *	osp = sdp->sd_isc->is_osdesc;
1038 
1039 			if ((osp->os_flags & FLG_OS_OUTREL) == 0) {
1040 				ofl->ofl_dynshdrcnt++;
1041 				osp->os_flags |= FLG_OS_OUTREL;
1042 			}
1043 		}
1044 	}
1045 
1046 	*orsp = *rsp;
1047 	orsp->rel_flags |= flags;
1048 
1049 	rcp->rc_free++;
1050 	ofl->ofl_outrelscnt++;
1051 
1052 	if (flags & FLG_REL_GOT)
1053 		ofl->ofl_relocgotsz += (Xword)sizeof (Rela);
1054 	else if (flags & FLG_REL_PLT)
1055 		ofl->ofl_relocpltsz += (Xword)sizeof (Rela);
1056 	else if (flags & FLG_REL_BSS)
1057 		ofl->ofl_relocbsssz += (Xword)sizeof (Rela);
1058 	else if (flags & FLG_REL_NOINFO)
1059 		ofl->ofl_relocrelsz += (Xword)sizeof (Rela);
1060 	else
1061 		orsp->rel_osdesc->os_szoutrels += (Xword)sizeof (Rela);
1062 
1063 	if (orsp->rel_rtype == M_R_RELATIVE)
1064 		ofl->ofl_relocrelcnt++;
1065 
1066 	/*
1067 	 * We don't perform sorting on PLT relocations because
1068 	 * they have already been assigned a PLT index and if we
1069 	 * were to sort them we would have to re-assign the plt indexes.
1070 	 */
1071 	if (!(flags & FLG_REL_PLT))
1072 		ofl->ofl_reloccnt++;
1073 
1074 	/*
1075 	 * Identify and possibly warn of a displacement relocation.
1076 	 */
1077 	if (orsp->rel_flags & FLG_REL_DISP) {
1078 		ofl->ofl_dtflags_1 |= DF_1_DISPRELPND;
1079 
1080 		if (ofl->ofl_flags & FLG_OF_VERBOSE)
1081 			disp_errmsg(MSG_INTL(MSG_REL_DISPREL4), orsp, ofl);
1082 	}
1083 	DBG_CALL(Dbg_reloc_ors_entry(M_MACH, orsp));
1084 	return (1);
1085 }
1086 
1087 
1088 uintptr_t
1089 add_actrel(Word flags, Rel_desc * rsp, Ofl_desc * ofl)
1090 {
1091 	Rel_desc * 	arsp;
1092 	Rel_cache *	rcp;
1093 
1094 	/*
1095 	 * If no relocation cache structures are available allocate a
1096 	 * new one and link it into the bucket list.
1097 	 */
1098 	if ((ofl->ofl_actrels.tail == 0) ||
1099 	    ((rcp = (Rel_cache *)ofl->ofl_actrels.tail->data) == 0) ||
1100 	    ((arsp = rcp->rc_free) == rcp->rc_end)) {
1101 		static size_t	nextsize = 0;
1102 		size_t		size;
1103 
1104 		/*
1105 		 * Typically, when generating an executable or shared object
1106 		 * there will be a active relocation for every input relocation.
1107 		 */
1108 		if (nextsize == 0) {
1109 			if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
1110 				if ((size = ofl->ofl_relocincnt) == 0)
1111 					size = REL_LAIDESCNO;
1112 				if (size > REL_HAIDESCNO)
1113 					nextsize = REL_HAIDESCNO;
1114 				else
1115 					nextsize = REL_LAIDESCNO;
1116 			} else
1117 				nextsize = size = REL_HAIDESCNO;
1118 		} else
1119 			size = nextsize;
1120 
1121 		size = size * sizeof (Rel_desc);
1122 
1123 		if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) ||
1124 		    (list_appendc(&ofl->ofl_actrels, rcp) == 0))
1125 			return (S_ERROR);
1126 
1127 		/* LINTED */
1128 		rcp->rc_free = arsp = (Rel_desc *)(rcp + 1);
1129 		/* LINTED */
1130 		rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size);
1131 	}
1132 
1133 	*arsp = *rsp;
1134 	arsp->rel_flags |= flags;
1135 
1136 	rcp->rc_free++;
1137 	ofl->ofl_actrelscnt++;
1138 
1139 	/*
1140 	 * If this is a displacement relocation relocation, warn.
1141 	 */
1142 	if (arsp->rel_flags & FLG_REL_DISP) {
1143 		ofl->ofl_dtflags_1 |= DF_1_DISPRELDNE;
1144 
1145 		if (ofl->ofl_flags & FLG_OF_VERBOSE)
1146 			disp_errmsg(MSG_INTL(MSG_REL_DISPREL3), arsp, ofl);
1147 	}
1148 	DBG_CALL(Dbg_reloc_ars_entry(M_MACH, arsp));
1149 	return (1);
1150 }
1151 
1152 
1153 /*
1154  * Stub routine since register symbols are not supported on amd64.
1155  */
1156 /* ARGSUSED */
1157 uintptr_t
1158 reloc_register(Rel_desc * rsp, Is_desc * isp, Ofl_desc * ofl)
1159 {
1160 	eprintf(ERR_FATAL, MSG_INTL(MSG_REL_NOREG));
1161 	return (S_ERROR);
1162 }
1163 
1164 /*
1165  * process relocation for a LOCAL symbol
1166  */
1167 uintptr_t
1168 reloc_local(Rel_desc * rsp, Ofl_desc * ofl)
1169 {
1170 	Word		flags = ofl->ofl_flags;
1171 	Sym_desc	*sdp = rsp->rel_sym;
1172 	Word		shndx = rsp->rel_sym->sd_shndx;
1173 	Word		ortype = rsp->rel_rtype;
1174 
1175 	/*
1176 	 * if ((shared object) and (not pc relative relocation) and
1177 	 *    (not against ABS symbol))
1178 	 * then
1179 	 *	build R_AMD64_RELATIVE
1180 	 * fi
1181 	 */
1182 	if ((flags & FLG_OF_SHAROBJ) && (rsp->rel_flags & FLG_REL_LOAD) &&
1183 	    !(IS_PC_RELATIVE(rsp->rel_rtype)) &&
1184 	    !(IS_GOT_BASED(rsp->rel_rtype)) &&
1185 	    !(rsp->rel_isdesc != NULL &&
1186 	    (rsp->rel_isdesc->is_shdr->sh_type == SHT_SUNW_dof)) &&
1187 	    (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) ||
1188 	    (shndx != SHN_ABS) || (sdp->sd_aux && sdp->sd_aux->sa_symspec))) {
1189 
1190 		/*
1191 		 * R_AMD64_RELATIVE updates a 64bit address, if this
1192 		 * relocation isn't a 64bit binding then we can not
1193 		 * simplify it to a RELATIVE relocation.
1194 		 */
1195 		if (reloc_table[ortype].re_fsize != sizeof (Addr)) {
1196 			return (add_outrel(NULL, rsp, ofl));
1197 		}
1198 
1199 		rsp->rel_rtype = R_AMD64_RELATIVE;
1200 		if (add_outrel(FLG_REL_ADVAL, rsp, ofl) == S_ERROR)
1201 			return (S_ERROR);
1202 		rsp->rel_rtype = ortype;
1203 		return (1);
1204 	}
1205 
1206 	if (!(rsp->rel_flags & FLG_REL_LOAD) &&
1207 	    (shndx == SHN_UNDEF)) {
1208 		(void) eprintf(ERR_WARNING, MSG_INTL(MSG_REL_EXTERNSYM),
1209 		    conv_reloc_amd64_type_str(rsp->rel_rtype),
1210 		    rsp->rel_isdesc->is_file->ifl_name,
1211 		    demangle(rsp->rel_sname), rsp->rel_osdesc->os_name);
1212 		return (1);
1213 	}
1214 
1215 	/*
1216 	 * Perform relocation.
1217 	 */
1218 	return (add_actrel(NULL, rsp, ofl));
1219 }
1220 
1221 
1222 uintptr_t
1223 /* ARGSUSED */
1224 reloc_GOTOP(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
1225 {
1226 	/*
1227 	 * Stub routine for common code compatibility, we shouldn't
1228 	 * actually get here on amd64.
1229 	 */
1230 	return (S_ERROR);
1231 }
1232 
1233 uintptr_t
1234 reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
1235 {
1236 	Word		rtype = rsp->rel_rtype;
1237 	Sym_desc	*sdp = rsp->rel_sym;
1238 	Word		flags = ofl->ofl_flags;
1239 	Word		rflags;
1240 	Gotndx		*gnp;
1241 
1242 	/*
1243 	 * all TLS relocations are illegal in a static executable.
1244 	 */
1245 	if ((ofl->ofl_flags & (FLG_OF_STATIC | FLG_OF_EXEC)) ==
1246 	    (FLG_OF_STATIC | FLG_OF_EXEC)) {
1247 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSSTAT),
1248 		    conv_reloc_386_type_str(rsp->rel_rtype),
1249 		    rsp->rel_isdesc->is_file->ifl_name,
1250 		    demangle(rsp->rel_sname));
1251 		return (S_ERROR);
1252 	}
1253 
1254 	/*
1255 	 * Any TLS relocation must be against a STT_TLS symbol, all others
1256 	 * are illegal.
1257 	 */
1258 	if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS) {
1259 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSBADSYM),
1260 		    conv_reloc_386_type_str(rsp->rel_rtype),
1261 		    rsp->rel_isdesc->is_file->ifl_name,
1262 		    demangle(rsp->rel_sname),
1263 		    conv_info_type_str(ofl->ofl_e_machine,
1264 		    ELF_ST_TYPE(sdp->sd_sym->st_info)));
1265 		return (S_ERROR);
1266 	}
1267 
1268 	/*
1269 	 * We're a executable - use either the IE or LE
1270 	 * access model.
1271 	 */
1272 	if (flags & FLG_OF_EXEC) {
1273 		/*
1274 		 * If we are using either IE or LE reference
1275 		 * model set the DF_STATIC_TLS flag.
1276 		 */
1277 		ofl->ofl_dtflags |= DF_STATIC_TLS;
1278 
1279 		if (!local) {
1280 			Gotref	gref;
1281 			/*
1282 			 * IE access model
1283 			 */
1284 			/*
1285 			 * It's not possible for LD or LE reference
1286 			 * models to reference a symbol external to
1287 			 * the current object.
1288 			 */
1289 			if (IS_TLS_LD(rtype) || IS_TLS_LE(rtype)) {
1290 				eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSBND),
1291 				    conv_reloc_amd64_type_str(rsp->rel_rtype),
1292 				    rsp->rel_isdesc->is_file->ifl_name,
1293 				    demangle(rsp->rel_sname),
1294 				    sdp->sd_file->ifl_name);
1295 				return (S_ERROR);
1296 			}
1297 
1298 			gref = GOT_REF_TLSIE;
1299 
1300 			/*
1301 			 * Assign a GOT entry for static TLS references
1302 			 */
1303 			if ((gnp = find_gotndx(&(sdp->sd_GOTndxs),
1304 			    gref, ofl, rsp)) == 0) {
1305 				if (assign_gotndx(&(sdp->sd_GOTndxs),
1306 				    gnp, gref, ofl, rsp, sdp) == S_ERROR)
1307 					return (S_ERROR);
1308 				rsp->rel_rtype = R_AMD64_TPOFF64;
1309 				if (add_outrel((FLG_REL_GOT | FLG_REL_STLS),
1310 				    rsp, ofl) == S_ERROR)
1311 					return (S_ERROR);
1312 				rsp->rel_rtype = rtype;
1313 			}
1314 			if (IS_TLS_IE(rtype))
1315 				return (add_actrel(FLG_REL_STLS, rsp, ofl));
1316 
1317 			/*
1318 			 * If (GD or LD) reference models - fixups
1319 			 * are required.
1320 			 */
1321 			return (add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS),
1322 			    rsp, ofl));
1323 		}
1324 		/*
1325 		 * LE access model
1326 		 */
1327 		if (IS_TLS_LE(rtype))
1328 			return (add_actrel(FLG_REL_STLS, rsp, ofl));
1329 		return (add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS), rsp, ofl));
1330 	}
1331 
1332 
1333 	/*
1334 	 * Building a shared object
1335 	 */
1336 
1337 	/*
1338 	 * Building a shared object - only GD & LD access models
1339 	 * will work here.
1340 	 */
1341 	if (IS_TLS_IE(rtype) || IS_TLS_LE(rtype)) {
1342 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSIE),
1343 		    conv_reloc_amd64_type_str(rsp->rel_rtype),
1344 		    rsp->rel_isdesc->is_file->ifl_name,
1345 		    demangle(rsp->rel_sname));
1346 		return (S_ERROR);
1347 	}
1348 
1349 	/*
1350 	 * LD access mode can only bind to local symbols.
1351 	 */
1352 	if (!local && IS_TLS_LD(rtype)) {
1353 		eprintf(ERR_FATAL, MSG_INTL(MSG_REL_TLSBND),
1354 		    conv_reloc_amd64_type_str(rsp->rel_rtype),
1355 		    rsp->rel_isdesc->is_file->ifl_name,
1356 		    demangle(rsp->rel_sname),
1357 		    sdp->sd_file->ifl_name);
1358 		return (S_ERROR);
1359 	}
1360 
1361 
1362 	if (IS_TLS_LD(rtype) && ((gnp = find_gotndx(&(sdp->sd_GOTndxs),
1363 	    GOT_REF_TLSLD, ofl, rsp)) == 0)) {
1364 		if (assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSLD,
1365 		    ofl, rsp, sdp) == S_ERROR)
1366 			return (S_ERROR);
1367 		rflags = FLG_REL_GOT | FLG_REL_MTLS;
1368 		if (local)
1369 			rflags |= FLG_REL_SCNNDX;
1370 		rsp->rel_rtype = R_AMD64_DTPMOD64;
1371 		if (add_outrel(rflags, rsp, ofl) == S_ERROR)
1372 			return (S_ERROR);
1373 		rsp->rel_rtype = rtype;
1374 	} else if (IS_TLS_GD(rtype) && ((gnp = find_gotndx(&(sdp->sd_GOTndxs),
1375 	    GOT_REF_TLSGD, ofl, rsp)) == 0)) {
1376 		if (assign_gotndx(&(sdp->sd_GOTndxs), gnp, GOT_REF_TLSGD,
1377 		    ofl, rsp, sdp) == S_ERROR)
1378 			return (S_ERROR);
1379 		rflags = FLG_REL_GOT | FLG_REL_DTLS;
1380 		if (local)
1381 			rflags |= FLG_REL_SCNNDX;
1382 		rsp->rel_rtype = R_AMD64_DTPMOD64;
1383 		if (add_outrel(rflags, rsp, ofl) == S_ERROR)
1384 			return (S_ERROR);
1385 		if (local == TRUE) {
1386 			rsp->rel_rtype = R_AMD64_DTPOFF64;
1387 			if (add_actrel((FLG_REL_GOT | FLG_REL_DTLS), rsp,
1388 			    ofl) == S_ERROR)
1389 				return (S_ERROR);
1390 		} else {
1391 			rsp->rel_rtype = R_AMD64_DTPOFF64;
1392 			if (add_outrel((FLG_REL_GOT | FLG_REL_DTLS), rsp,
1393 			    ofl) == S_ERROR)
1394 				return (S_ERROR);
1395 		}
1396 		rsp->rel_rtype = rtype;
1397 	}
1398 
1399 	if (IS_TLS_LD(rtype))
1400 		return (add_actrel(FLG_REL_MTLS, rsp, ofl));
1401 
1402 	return (add_actrel(FLG_REL_DTLS, rsp, ofl));
1403 }
1404 
1405 uintptr_t
1406 reloc_relobj(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
1407 {
1408 	Word		rtype = rsp->rel_rtype;
1409 	Sym_desc *	sdp = rsp->rel_sym;
1410 	Is_desc *	isp = rsp->rel_isdesc;
1411 	Word		flags = ofl->ofl_flags;
1412 
1413 	/*
1414 	 * Try to determine if we can do any relocations at
1415 	 * this point.  We can if:
1416 	 *
1417 	 * (local_symbol) and (non_GOT_relocation) and
1418 	 * (IS_PC_RELATIVE()) and
1419 	 * (relocation to symbol in same section)
1420 	 */
1421 	if (local && !IS_GOT_RELATIVE(rtype) && !IS_GOT_BASED(rtype) &&
1422 	    !IS_GOT_PC(rtype) && IS_PC_RELATIVE(rtype) &&
1423 	    ((sdp->sd_isc) && (sdp->sd_isc->is_osdesc == isp->is_osdesc))) {
1424 		return (add_actrel(NULL, rsp, ofl));
1425 	}
1426 
1427 	/*
1428 	 * If '-zredlocsym' is in effect make all local sym relocations
1429 	 * against the 'section symbols', since they are the only symbols
1430 	 * which will be added to the .symtab.
1431 	 */
1432 	if (local && (((ofl->ofl_flags1 & FLG_OF1_REDLSYM) &&
1433 	    (ELF_ST_BIND(sdp->sd_sym->st_info) == STB_LOCAL)) ||
1434 	    ((sdp->sd_flags & FLG_SY1_ELIM) && (flags & FLG_OF_PROCRED)))) {
1435 		/*
1436 		 * But if this is a PIC code, don't allow it for now.
1437 		 */
1438 		if (IS_GOT_RELATIVE(rsp->rel_rtype)) {
1439 			eprintf(ERR_FATAL, MSG_INTL(MSG_REL_PICREDLOC),
1440 			    demangle(rsp->rel_sname),
1441 			    rsp->rel_isdesc->is_file->ifl_name,
1442 			    conv_reloc_386_type_str(rsp->rel_rtype));
1443 			return (S_ERROR);
1444 		}
1445 		return (add_actrel(FLG_REL_SCNNDX | FLG_REL_ADVAL, rsp, ofl));
1446 	}
1447 
1448 	return (add_outrel(NULL, rsp, ofl));
1449 }
1450 
1451 
1452 /* ARGSUSED3 */
1453 Gotndx *
1454 find_gotndx(List * lst, Gotref gref, Ofl_desc * ofl, Rel_desc * rdesc)
1455 {
1456 	Listnode *	lnp;
1457 	Gotndx *	gnp;
1458 
1459 	assert(rdesc != 0);
1460 
1461 	if ((gref == GOT_REF_TLSLD) && ofl->ofl_tlsldgotndx)
1462 		return (ofl->ofl_tlsldgotndx);
1463 
1464 	for (LIST_TRAVERSE(lst, lnp, gnp)) {
1465 		if ((rdesc->rel_raddend == gnp->gn_addend) &&
1466 		    (gnp->gn_gotref == gref)) {
1467 			return (gnp);
1468 		}
1469 	}
1470 	return ((Gotndx *)0);
1471 }
1472 
1473 Xword
1474 calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl)
1475 {
1476 	Os_desc		*osp = ofl->ofl_osgot;
1477 	Sym_desc	*sdp = rdesc->rel_sym;
1478 	Xword		gotndx;
1479 	Gotref		gref;
1480 	Gotndx		*gnp;
1481 
1482 	if (rdesc->rel_flags & FLG_REL_DTLS)
1483 		gref = GOT_REF_TLSGD;
1484 	else if (rdesc->rel_flags & FLG_REL_MTLS)
1485 		gref = GOT_REF_TLSLD;
1486 	else if (rdesc->rel_flags & FLG_REL_STLS)
1487 		gref = GOT_REF_TLSIE;
1488 	else
1489 		gref = GOT_REF_GENERIC;
1490 
1491 	gnp = find_gotndx(&(sdp->sd_GOTndxs), gref, ofl, rdesc);
1492 	assert(gnp);
1493 
1494 	gotndx = (Xword)gnp->gn_gotndx;
1495 
1496 	if ((rdesc->rel_flags & FLG_REL_DTLS) &&
1497 	    (rdesc->rel_rtype == R_AMD64_DTPOFF64))
1498 		gotndx++;
1499 
1500 	return ((Xword)(osp->os_shdr->sh_addr + (gotndx * M_GOT_ENTSIZE)));
1501 }
1502 
1503 
1504 /* ARGSUSED5 */
1505 uintptr_t
1506 assign_gotndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl,
1507     Rel_desc * rsp, Sym_desc * sdp)
1508 {
1509 	Xword		raddend;
1510 	Gotndx		*gnp, *_gnp;
1511 	Listnode	*lnp, *plnp;
1512 	uint_t		gotents;
1513 
1514 	raddend = rsp->rel_raddend;
1515 	if (pgnp && (pgnp->gn_addend == raddend) &&
1516 	    (pgnp->gn_gotref == gref))
1517 		return (1);
1518 
1519 	if ((gref == GOT_REF_TLSGD) || (gref == GOT_REF_TLSLD))
1520 		gotents = 2;
1521 	else
1522 		gotents = 1;
1523 
1524 	plnp = 0;
1525 	for (LIST_TRAVERSE(lst, lnp, _gnp)) {
1526 		if (_gnp->gn_addend > raddend)
1527 			break;
1528 		plnp = lnp;
1529 	}
1530 
1531 	/*
1532 	 * Allocate a new entry.
1533 	 */
1534 	if ((gnp = libld_calloc(sizeof (Gotndx), 1)) == 0)
1535 		return (S_ERROR);
1536 	gnp->gn_addend = raddend;
1537 	gnp->gn_gotndx = ofl->ofl_gotcnt;
1538 	gnp->gn_gotref = gref;
1539 
1540 	ofl->ofl_gotcnt += gotents;
1541 
1542 	if (gref == GOT_REF_TLSLD) {
1543 		ofl->ofl_tlsldgotndx = gnp;
1544 		return (1);
1545 	}
1546 
1547 	if (plnp == 0) {
1548 		/*
1549 		 * Insert at head of list
1550 		 */
1551 		if (list_prependc(lst, (void *)gnp) == 0)
1552 			return (S_ERROR);
1553 	} else if (_gnp->gn_addend > raddend) {
1554 		/*
1555 		 * Insert in middle of lest
1556 		 */
1557 		if (list_insertc(lst, (void *)gnp, plnp) == 0)
1558 			return (S_ERROR);
1559 	} else {
1560 		/*
1561 		 * Append to tail of list
1562 		 */
1563 		if (list_appendc(lst, (void *)gnp) == 0)
1564 			return (S_ERROR);
1565 	}
1566 	return (1);
1567 }
1568 
1569 
1570 void
1571 assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl)
1572 {
1573 	sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++;
1574 	sdp->sd_aux->sa_PLTGOTndx = ofl->ofl_gotcnt++;
1575 }
1576 
1577 static unsigned char plt0_template[M_PLT_ENTSIZE] = {
1578 /* 0x00 PUSHQ GOT+8(%rip) */	0xff, 0x35, 0x00, 0x00, 0x00, 0x00,
1579 /* 0x06 JMP   *GOT+16(%rip) */	0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
1580 /* 0x0c NOP */			0x90,
1581 /* 0x0d NOP */			0x90,
1582 /* 0x0e NOP */			0x90,
1583 /* 0x0f NOP */			0x90
1584 };
1585 
1586 /*
1587  * Initializes .got[0] with the _DYNAMIC symbol value.
1588  */
1589 uintptr_t
1590 fillin_gotplt1(Ofl_desc * ofl)
1591 {
1592 	Word	flags = ofl->ofl_flags;
1593 	Word	dtflags1 = ofl->ofl_dtflags_1;
1594 
1595 	if (ofl->ofl_osgot) {
1596 		Sym_desc *	sdp;
1597 
1598 		if ((sdp = sym_find(MSG_ORIG(MSG_SYM_DYNAMIC_U),
1599 		    SYM_NOHASH, 0, ofl)) != NULL) {
1600 			unsigned char	*genptr = ((unsigned char *)
1601 			    ofl->ofl_osgot->os_outdata->d_buf +
1602 			    (M_GOT_XDYNAMIC * M_GOT_ENTSIZE));
1603 			/* LINTED */
1604 			*(Xword *)genptr = sdp->sd_sym->st_value;
1605 		}
1606 	}
1607 
1608 	/*
1609 	 * Fill in the reserved slot in the procedure linkage table the first
1610 	 * entry is:
1611 	 *	0x00 PUSHQ	GOT+8(%rip)	    # GOT[1]
1612 	 *	0x06 JMP	*GOT+16(%rip)	    # GOT[2]
1613 	 *	0x0c NOP
1614 	 *	0x0d NOP
1615 	 *	0x0e NOP
1616 	 *	0x0f NOP
1617 	 */
1618 	if ((flags & FLG_OF_DYNAMIC) && ofl->ofl_osplt) {
1619 		unsigned char	*pltent;
1620 		Xword		val1;
1621 
1622 		pltent = (unsigned char *)ofl->ofl_osplt->os_outdata->d_buf;
1623 		bcopy(plt0_template, pltent, sizeof (plt0_template));
1624 
1625 		/*
1626 		 * filin:
1627 		 *	PUSHQ GOT + 8(%rip)
1628 		 *
1629 		 * Note: 0x06 below represents the offset to the
1630 		 *	 next instruction - which is what %rip will
1631 		 *	 be pointing at.
1632 		 */
1633 		val1 = (ofl->ofl_osgot->os_shdr->sh_addr) +
1634 			(M_GOT_XLINKMAP * M_GOT_ENTSIZE) -
1635 			ofl->ofl_osplt->os_shdr->sh_addr - 0x06;
1636 
1637 		/*
1638 		 * If '-z noreloc' is specified - skip the do_reloc
1639 		 * stage.
1640 		 */
1641 		if ((flags & FLG_OF_RELOBJ) ||
1642 		    !(dtflags1 & DF_1_NORELOC)) {
1643 			if (do_reloc(R_AMD64_GOTPCREL, &pltent[0x02],
1644 			    &val1, MSG_ORIG(MSG_SYM_PLTENT),
1645 			    MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) {
1646 				eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLT0FAIL));
1647 				return (S_ERROR);
1648 			}
1649 		}
1650 
1651 		/*
1652 		 * filin:
1653 		 *  JMP	*GOT+16(%rip)
1654 		 */
1655 		val1 = (ofl->ofl_osgot->os_shdr->sh_addr) +
1656 			(M_GOT_XRTLD * M_GOT_ENTSIZE) -
1657 			ofl->ofl_osplt->os_shdr->sh_addr - 0x0c;
1658 		/*
1659 		 * If '-z noreloc' is specified - skip the do_reloc
1660 		 * stage.
1661 		 */
1662 		if ((flags & FLG_OF_RELOBJ) ||
1663 		    !(dtflags1 & DF_1_NORELOC)) {
1664 			if (do_reloc(R_AMD64_GOTPCREL, &pltent[0x08],
1665 			    &val1, MSG_ORIG(MSG_SYM_PLTENT),
1666 			    MSG_ORIG(MSG_SPECFIL_PLTENT)) == 0) {
1667 				eprintf(ERR_FATAL, MSG_INTL(MSG_PLT_PLT0FAIL));
1668 				return (S_ERROR);
1669 			}
1670 		}
1671 	}
1672 	return (1);
1673 }
1674 
1675 /*
1676  * Return got[0].
1677  */
1678 Addr
1679 fillin_gotplt2(Ofl_desc * ofl)
1680 {
1681 	if (ofl->ofl_osgot) {
1682 		return (ofl->ofl_osgot->os_shdr->sh_addr);
1683 	} else
1684 		return (0);
1685 }
1686