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