xref: /titanic_50/usr/src/cmd/sgs/libld/common/machrel.amd.c (revision 7010c12ad3ac2cada55cf126121a8c46957d3632)
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 	 * The addend field for R_AMD64_DTPMOD64 means nothing.  The addend
360 	 * is propagated in the corresponding R_AMD64_DTPOFF64 relocation.
361 	 */
362 	if (orsp->rel_rtype == R_AMD64_DTPMOD64)
363 		raddend = 0;
364 
365 	relbits = (char *)relosp->os_outdata->d_buf;
366 
367 	rea.r_info = ELF_R_INFO(ndx, orsp->rel_rtype);
368 	rea.r_offset = roffset;
369 	rea.r_addend = raddend;
370 	DBG_CALL(Dbg_reloc_out(ofl, ELF_DBG_LD, SHT_RELA, &rea, relosp->os_name,
371 	    orsp->rel_sname));
372 
373 	/*
374 	 * Assert we haven't walked off the end of our relocation table.
375 	 */
376 	assert(relosp->os_szoutrels <= relosp->os_shdr->sh_size);
377 
378 	(void) memcpy((relbits + relosp->os_szoutrels),
379 	    (char *)&rea, sizeof (Rela));
380 	relosp->os_szoutrels += (Xword)sizeof (Rela);
381 
382 	/*
383 	 * Determine if this relocation is against a non-writable, allocatable
384 	 * section.  If so we may need to provide a text relocation diagnostic.
385 	 * Note that relocations against the .plt (R_AMD64_JUMP_SLOT) actually
386 	 * result in modifications to the .got.
387 	 */
388 	if (orsp->rel_rtype == R_AMD64_JUMP_SLOT)
389 		osp = ofl->ofl_osgot;
390 
391 	ld_reloc_remain_entry(orsp, osp, ofl);
392 	return (1);
393 }
394 
395 /*
396  * amd64 Instructions for TLS processing
397  */
398 static uchar_t tlsinstr_gd_ie[] = {
399 	/*
400 	 *	0x00 movq %fs:0, %rax
401 	 */
402 	0x64, 0x48, 0x8b, 0x04, 0x25,
403 	0x00, 0x00, 0x00, 0x00,
404 	/*
405 	 *	0x09 addq x@gottpoff(%rip), %rax
406 	 */
407 	0x48, 0x03, 0x05, 0x00, 0x00,
408 	0x00, 0x00
409 };
410 
411 static uchar_t tlsinstr_gd_le[] = {
412 	/*
413 	 *	0x00 movq %fs:0, %rax
414 	 */
415 	0x64, 0x48, 0x8b, 0x04, 0x25,
416 	0x00, 0x00, 0x00, 0x00,
417 	/*
418 	 *	0x09 leaq x@gottpoff(%rip), %rax
419 	 */
420 	0x48, 0x8d, 0x80, 0x00, 0x00,
421 	0x00, 0x00
422 };
423 
424 static uchar_t tlsinstr_ld_le[] = {
425 	/*
426 	 * .byte 0x66
427 	 */
428 	0x66,
429 	/*
430 	 * .byte 0x66
431 	 */
432 	0x66,
433 	/*
434 	 * .byte 0x66
435 	 */
436 	0x66,
437 	/*
438 	 * movq %fs:0, %rax
439 	 */
440 	0x64, 0x48, 0x8b, 0x04, 0x25,
441 	0x00, 0x00, 0x00, 0x00
442 };
443 
444 
445 static Fixupret
446 tls_fixups(Ofl_desc *ofl, Rel_desc *arsp)
447 {
448 	Sym_desc	*sdp = arsp->rel_sym;
449 	Word		rtype = arsp->rel_rtype;
450 	uchar_t		*offset;
451 
452 	offset = (uchar_t *)((uintptr_t)arsp->rel_roffset +
453 	    (uintptr_t)_elf_getxoff(arsp->rel_isdesc->is_indata) +
454 	    (uintptr_t)arsp->rel_osdesc->os_outdata->d_buf);
455 
456 	if (sdp->sd_ref == REF_DYN_NEED) {
457 		/*
458 		 * IE reference model
459 		 */
460 		switch (rtype) {
461 		case R_AMD64_TLSGD:
462 			/*
463 			 *  GD -> IE
464 			 *
465 			 * Transition:
466 			 *	0x00 .byte 0x66
467 			 *	0x01 leaq x@tlsgd(%rip), %rdi
468 			 *	0x08 .word 0x6666
469 			 *	0x0a rex64
470 			 *	0x0b call __tls_get_addr@plt
471 			 *	0x10
472 			 * To:
473 			 *	0x00 movq %fs:0, %rax
474 			 *	0x09 addq x@gottpoff(%rip), %rax
475 			 *	0x10
476 			 */
477 			DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
478 			    rtype, R_AMD64_GOTTPOFF, arsp->rel_roffset,
479 			    sdp->sd_name));
480 			arsp->rel_rtype = R_AMD64_GOTTPOFF;
481 			arsp->rel_roffset += 8;
482 			arsp->rel_raddend = (Sxword)-4;
483 
484 			/*
485 			 * Addjust 'offset' to beginning of instruction
486 			 * sequence.
487 			 */
488 			offset -= 4;
489 			(void) memcpy(offset, tlsinstr_gd_ie,
490 			    sizeof (tlsinstr_gd_ie));
491 			return (FIX_RELOC);
492 
493 		case R_AMD64_PLT32:
494 			/*
495 			 * Fixup done via the TLS_GD relocation
496 			 */
497 			DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
498 			    rtype, R_AMD64_NONE, arsp->rel_roffset,
499 			    sdp->sd_name));
500 			return (FIX_DONE);
501 		}
502 	}
503 
504 	/*
505 	 * LE reference model
506 	 */
507 	switch (rtype) {
508 	case R_AMD64_TLSGD:
509 		/*
510 		 * GD -> LE
511 		 *
512 		 * Transition:
513 		 *	0x00 .byte 0x66
514 		 *	0x01 leaq x@tlsgd(%rip), %rdi
515 		 *	0x08 .word 0x6666
516 		 *	0x0a rex64
517 		 *	0x0b call __tls_get_addr@plt
518 		 *	0x10
519 		 * To:
520 		 *	0x00 movq %fs:0, %rax
521 		 *	0x09 leaq x@tpoff(%rax), %rax
522 		 *	0x10
523 		 */
524 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
525 		    rtype, R_AMD64_TPOFF32, arsp->rel_roffset, sdp->sd_name));
526 
527 		arsp->rel_rtype = R_AMD64_TPOFF32;
528 		arsp->rel_roffset += 8;
529 		arsp->rel_raddend = 0;
530 
531 		/*
532 		 * Addjust 'offset' to beginning of instruction
533 		 * sequence.
534 		 */
535 		offset -= 4;
536 		(void) memcpy(offset, tlsinstr_gd_le, sizeof (tlsinstr_gd_le));
537 		return (FIX_RELOC);
538 
539 	case R_AMD64_GOTTPOFF:
540 		/*
541 		 * IE -> LE
542 		 *
543 		 * Transition:
544 		 *	0x00 movq %fs:0, %rax
545 		 *	0x09 addq x@gottopoff(%rip), %rax
546 		 *	0x10
547 		 * To:
548 		 *	0x00 movq %fs:0, %rax
549 		 *	0x09 leaq x@tpoff(%rax), %rax
550 		 *	0x10
551 		 */
552 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH, rtype,
553 		    R_AMD64_TPOFF32, arsp->rel_roffset, sdp->sd_name));
554 
555 		arsp->rel_rtype = R_AMD64_TPOFF32;
556 		arsp->rel_raddend = 0;
557 
558 		/*
559 		 * Addjust 'offset' to beginning of instruction
560 		 * sequence.
561 		 */
562 		offset -= 12;
563 
564 		/*
565 		 * Same code sequence used in the GD -> LE
566 		 * transition.
567 		 */
568 		(void) memcpy(offset, tlsinstr_gd_le, sizeof (tlsinstr_gd_le));
569 		return (FIX_RELOC);
570 
571 	case R_AMD64_TLSLD:
572 		/*
573 		 * LD -> LE
574 		 *
575 		 * Transition
576 		 *	0x00 leaq x1@tlsgd(%rip), %rdi
577 		 *	0x07 call __tls_get_addr@plt
578 		 *	0x0c
579 		 * To:
580 		 *	0x00 .byte 0x66
581 		 *	0x01 .byte 0x66
582 		 *	0x02 .byte 0x66
583 		 *	0x03 movq %fs:0, %rax
584 		 */
585 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH, rtype,
586 		    R_AMD64_NONE, arsp->rel_roffset, sdp->sd_name));
587 		offset -= 3;
588 		(void) memcpy(offset, tlsinstr_ld_le, sizeof (tlsinstr_ld_le));
589 		return (FIX_DONE);
590 
591 	case R_AMD64_DTPOFF32:
592 		/*
593 		 * LD->LE
594 		 *
595 		 * Transition:
596 		 *	0x00 leaq x1@dtpoff(%rax), %rcx
597 		 * To:
598 		 *	0x00 leaq x1@tpoff(%rax), %rcx
599 		 */
600 		DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH, rtype,
601 		    R_AMD64_TPOFF32, arsp->rel_roffset, sdp->sd_name));
602 		arsp->rel_rtype = R_AMD64_TPOFF32;
603 		arsp->rel_raddend = 0;
604 		return (FIX_RELOC);
605 	}
606 
607 	return (FIX_RELOC);
608 }
609 
610 uintptr_t
611 ld_do_activerelocs(Ofl_desc *ofl)
612 {
613 	Rel_desc	*arsp;
614 	Rel_cache	*rcp;
615 	Listnode	*lnp;
616 	uintptr_t	return_code = 1;
617 	Word		flags = ofl->ofl_flags;
618 	Word		dtflags1 = ofl->ofl_dtflags_1;
619 
620 	if (ofl->ofl_actrels.head)
621 		DBG_CALL(Dbg_reloc_doact_title(ofl->ofl_lml));
622 
623 	/*
624 	 * Process active relocations.
625 	 */
626 	for (LIST_TRAVERSE(&ofl->ofl_actrels, lnp, rcp)) {
627 		/* LINTED */
628 		for (arsp = (Rel_desc *)(rcp + 1);
629 		    arsp < rcp->rc_free; arsp++) {
630 			uchar_t		*addr;
631 			Xword 		value;
632 			Sym_desc	*sdp;
633 			const char	*ifl_name;
634 			Xword		refaddr;
635 			int		moved = 0;
636 			Gotref		gref;
637 
638 			/*
639 			 * If the section this relocation is against has been
640 			 * discarded (-zignore), then discard (skip) the
641 			 * relocation itself.
642 			 */
643 			if ((arsp->rel_isdesc->is_flags & FLG_IS_DISCARD) &&
644 			    ((arsp->rel_flags &
645 			    (FLG_REL_GOT | FLG_REL_BSS |
646 			    FLG_REL_PLT | FLG_REL_NOINFO)) == 0)) {
647 				DBG_CALL(Dbg_reloc_discard(ofl->ofl_lml,
648 				    M_MACH, arsp));
649 				continue;
650 			}
651 
652 			/*
653 			 * We deteremine what the 'got reference'
654 			 * model (if required) is at this point.  This
655 			 * needs to be done before tls_fixup() since
656 			 * it may 'transition' our instructions.
657 			 *
658 			 * The got table entries have already been assigned,
659 			 * and we bind to those initial entries.
660 			 */
661 			if (arsp->rel_flags & FLG_REL_DTLS)
662 				gref = GOT_REF_TLSGD;
663 			else if (arsp->rel_flags & FLG_REL_MTLS)
664 				gref = GOT_REF_TLSLD;
665 			else if (arsp->rel_flags & FLG_REL_STLS)
666 				gref = GOT_REF_TLSIE;
667 			else
668 				gref = GOT_REF_GENERIC;
669 
670 			/*
671 			 * Perform any required TLS fixups.
672 			 */
673 			if (arsp->rel_flags & FLG_REL_TLSFIX) {
674 				Fixupret	ret;
675 
676 				if ((ret = tls_fixups(ofl, arsp)) == FIX_ERROR)
677 					return (S_ERROR);
678 				if (ret == FIX_DONE)
679 					continue;
680 			}
681 
682 			/*
683 			 * If this is a relocation against a move table, or
684 			 * expanded move table, adjust the relocation entries.
685 			 */
686 			if (arsp->rel_move)
687 				ld_adj_movereloc(ofl, arsp);
688 
689 			sdp = arsp->rel_sym;
690 			refaddr = arsp->rel_roffset +
691 			    (Off)_elf_getxoff(arsp->rel_isdesc->is_indata);
692 
693 			if ((arsp->rel_flags & FLG_REL_CLVAL) ||
694 			    (arsp->rel_flags & FLG_REL_GOTCL))
695 				value = 0;
696 			else if (ELF_ST_TYPE(sdp->sd_sym->st_info) ==
697 			    STT_SECTION) {
698 				Sym_desc	*sym;
699 
700 				/*
701 				 * The value for a symbol pointing to a SECTION
702 				 * is based off of that sections position.
703 				 *
704 				 * The second argument of the ld_am_I_partial()
705 				 * is the value stored at the target address
706 				 * relocation is going to be applied.
707 				 */
708 				if ((sdp->sd_isc->is_flags & FLG_IS_RELUPD) &&
709 				    /* LINTED */
710 				    (sym = ld_am_I_partial(arsp, *(Xword *)
711 				    ((uchar_t *)
712 				    arsp->rel_isdesc->is_indata->d_buf +
713 				    arsp->rel_roffset)))) {
714 					/*
715 					 * If the symbol is moved,
716 					 * adjust the value
717 					 */
718 					value = sym->sd_sym->st_value;
719 					moved = 1;
720 				} else {
721 					value = _elf_getxoff(
722 					    sdp->sd_isc->is_indata);
723 					if (sdp->sd_isc->is_shdr->sh_flags &
724 					    SHF_ALLOC)
725 					    value += sdp->sd_isc->is_osdesc->
726 					    os_shdr->sh_addr;
727 				}
728 				if (sdp->sd_isc->is_shdr->sh_flags & SHF_TLS)
729 					value -= ofl->ofl_tlsphdr->p_vaddr;
730 			} else {
731 				/*
732 				 * Else the value is the symbols value.
733 				 */
734 				value = sdp->sd_sym->st_value;
735 			}
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 			    ((flags & FLG_OF_RELOBJ) == 0))
750 				refaddr += arsp->rel_isdesc->is_osdesc->
751 				    os_shdr->sh_addr;
752 
753 			/*
754 			 * If this entry has a PLT assigned to it, it's
755 			 * value is actually the address of the PLT (and
756 			 * not the address of the function).
757 			 */
758 			if (IS_PLT(arsp->rel_rtype)) {
759 				if (sdp->sd_aux && sdp->sd_aux->sa_PLTndx)
760 					value = ld_calc_plt_addr(sdp, ofl);
761 			}
762 
763 			/*
764 			 * Add relocations addend to value.  Add extra
765 			 * relocation addend if needed.
766 			 *
767 			 * Note: for GOT relative relocations on amd64
768 			 *	 we discard the addend.  It was relevant
769 			 *	 to the reference - not to the data item
770 			 *	 being referenced (ie: that -4 thing).
771 			 */
772 			if ((arsp->rel_flags & FLG_REL_GOT) == 0)
773 				value += arsp->rel_raddend;
774 
775 			/*
776 			 * Determine whether the value needs further adjustment.
777 			 * Filter through the attributes of the relocation to
778 			 * determine what adjustment is required.  Note, many
779 			 * of the following cases are only applicable when a
780 			 * .got is present.  As a .got is not generated when a
781 			 * relocatable object is being built, any adjustments
782 			 * that require a .got need to be skipped.
783 			 */
784 			if ((arsp->rel_flags & FLG_REL_GOT) &&
785 			    ((flags & FLG_OF_RELOBJ) == 0)) {
786 				Xword		R1addr;
787 				uintptr_t	R2addr;
788 				Word		gotndx;
789 				Gotndx		*gnp;
790 
791 				/*
792 				 * Perform relocation against GOT table.  Since
793 				 * this doesn't fit exactly into a relocation
794 				 * we place the appropriate byte in the GOT
795 				 * directly
796 				 *
797 				 * Calculate offset into GOT at which to apply
798 				 * the relocation.
799 				 */
800 				gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), gref,
801 				    ofl, arsp);
802 				assert(gnp);
803 
804 				if (arsp->rel_rtype == R_AMD64_DTPOFF64)
805 					gotndx = gnp->gn_gotndx + 1;
806 				else
807 					gotndx = gnp->gn_gotndx;
808 
809 				R1addr = (Xword)(gotndx * M_GOT_ENTSIZE);
810 
811 				/*
812 				 * Add the GOTs data's offset.
813 				 */
814 				R2addr = R1addr + (uintptr_t)
815 				    arsp->rel_osdesc->os_outdata->d_buf;
816 
817 				DBG_CALL(Dbg_reloc_doact(ofl->ofl_lml,
818 				    ELF_DBG_LD, M_MACH, SHT_RELA,
819 				    arsp->rel_rtype, R1addr, value,
820 				    arsp->rel_sname, arsp->rel_osdesc));
821 
822 				/*
823 				 * And do it.
824 				 */
825 				*(Xword *)R2addr = value;
826 				continue;
827 
828 			} else if (IS_GOT_BASED(arsp->rel_rtype) &&
829 			    ((flags & FLG_OF_RELOBJ) == 0)) {
830 				value -= ofl->ofl_osgot->os_shdr->sh_addr;
831 
832 			} else if (IS_GOTPCREL(arsp->rel_rtype) &&
833 			    ((flags & FLG_OF_RELOBJ) == 0)) {
834 				Gotndx *gnp;
835 
836 				/*
837 				 * Calculation:
838 				 *	G + GOT + A - P
839 				 */
840 				gnp = ld_find_gotndx(&(sdp->sd_GOTndxs),
841 				    gref, ofl, arsp);
842 				assert(gnp);
843 				value = (Xword)(ofl->ofl_osgot->os_shdr->
844 				    sh_addr) + ((Xword)gnp->gn_gotndx *
845 				    M_GOT_ENTSIZE) + arsp->rel_raddend -
846 				    refaddr;
847 
848 			} else if (IS_GOT_PC(arsp->rel_rtype) &&
849 			    ((flags & FLG_OF_RELOBJ) == 0)) {
850 				value = (Xword)(ofl->ofl_osgot->os_shdr->
851 				    sh_addr) - refaddr + arsp->rel_raddend;
852 
853 			} else if ((IS_PC_RELATIVE(arsp->rel_rtype)) &&
854 			    (((flags & FLG_OF_RELOBJ) == 0) ||
855 			    (arsp->rel_osdesc == sdp->sd_isc->is_osdesc))) {
856 				value -= refaddr;
857 
858 			} else if (IS_TLS_INS(arsp->rel_rtype) &&
859 			    IS_GOT_RELATIVE(arsp->rel_rtype) &&
860 			    ((flags & FLG_OF_RELOBJ) == 0)) {
861 				Gotndx	*gnp;
862 
863 				gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), gref,
864 				    ofl, arsp);
865 				assert(gnp);
866 				value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
867 
868 			} else if (IS_GOT_RELATIVE(arsp->rel_rtype) &&
869 			    ((flags & FLG_OF_RELOBJ) == 0)) {
870 				Gotndx *gnp;
871 
872 				gnp = ld_find_gotndx(&(sdp->sd_GOTndxs),
873 				    gref, ofl, arsp);
874 				assert(gnp);
875 				value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
876 
877 			} else if ((arsp->rel_flags & FLG_REL_STLS) &&
878 			    ((flags & FLG_OF_RELOBJ) == 0)) {
879 				Xword	tlsstatsize;
880 
881 				/*
882 				 * This is the LE TLS reference model.  Static
883 				 * offset is hard-coded.
884 				 */
885 				tlsstatsize =
886 				    S_ROUND(ofl->ofl_tlsphdr->p_memsz,
887 				    M_TLSSTATALIGN);
888 				value = tlsstatsize - value;
889 
890 				/*
891 				 * Since this code is fixed up, it assumes a
892 				 * negative offset that can be added to the
893 				 * thread pointer.
894 				 */
895 				if (arsp->rel_rtype == R_AMD64_TPOFF32)
896 					value = -value;
897 			}
898 
899 			if (arsp->rel_isdesc->is_file)
900 				ifl_name = arsp->rel_isdesc->is_file->ifl_name;
901 			else
902 				ifl_name = MSG_INTL(MSG_STR_NULL);
903 
904 			/*
905 			 * Make sure we have data to relocate.  Compiler and
906 			 * assembler developers have been known to generate
907 			 * relocations against invalid sections (normally .bss),
908 			 * so for their benefit give them sufficient information
909 			 * to help analyze the problem.  End users should never
910 			 * see this.
911 			 */
912 			if (arsp->rel_isdesc->is_indata->d_buf == 0) {
913 				eprintf(ofl->ofl_lml, ERR_FATAL,
914 				    MSG_INTL(MSG_REL_EMPTYSEC),
915 				    conv_reloc_amd64_type(arsp->rel_rtype, 0),
916 				    ifl_name, demangle(arsp->rel_sname),
917 				    arsp->rel_isdesc->is_name);
918 				return (S_ERROR);
919 			}
920 
921 			/*
922 			 * Get the address of the data item we need to modify.
923 			 */
924 			addr = (uchar_t *)((uintptr_t)arsp->rel_roffset +
925 			    (uintptr_t)_elf_getxoff(arsp->rel_isdesc->
926 			    is_indata));
927 
928 			DBG_CALL(Dbg_reloc_doact(ofl->ofl_lml, ELF_DBG_LD,
929 			    M_MACH, SHT_RELA, arsp->rel_rtype, EC_NATPTR(addr),
930 			    value, arsp->rel_sname, arsp->rel_osdesc));
931 			addr += (uintptr_t)arsp->rel_osdesc->os_outdata->d_buf;
932 
933 			if ((((uintptr_t)addr - (uintptr_t)ofl->ofl_nehdr) >
934 			    ofl->ofl_size) || (arsp->rel_roffset >
935 			    arsp->rel_osdesc->os_shdr->sh_size)) {
936 				int	class;
937 
938 				if (((uintptr_t)addr -
939 				    (uintptr_t)ofl->ofl_nehdr) > ofl->ofl_size)
940 					class = ERR_FATAL;
941 				else
942 					class = ERR_WARNING;
943 
944 				eprintf(ofl->ofl_lml, class,
945 				    MSG_INTL(MSG_REL_INVALOFFSET),
946 				    conv_reloc_amd64_type(arsp->rel_rtype, 0),
947 				    ifl_name, arsp->rel_isdesc->is_name,
948 				    demangle(arsp->rel_sname),
949 				    EC_ADDR((uintptr_t)addr -
950 				    (uintptr_t)ofl->ofl_nehdr));
951 
952 				if (class == ERR_FATAL) {
953 					return_code = S_ERROR;
954 					continue;
955 				}
956 			}
957 
958 			/*
959 			 * The relocation is additive.  Ignore the previous
960 			 * symbol value if this local partial symbol is
961 			 * expanded.
962 			 */
963 			if (moved)
964 				value -= *addr;
965 
966 			/*
967 			 * If '-z noreloc' is specified - skip the do_reloc
968 			 * stage.
969 			 */
970 			if ((flags & FLG_OF_RELOBJ) ||
971 			    !(dtflags1 & DF_1_NORELOC)) {
972 				if (do_reloc((uchar_t)arsp->rel_rtype,
973 				    addr, &value, arsp->rel_sname, ifl_name,
974 				    ofl->ofl_lml) == 0)
975 					return_code = S_ERROR;
976 			}
977 		}
978 	}
979 	return (return_code);
980 }
981 
982 uintptr_t
983 ld_add_outrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
984 {
985 	Rel_desc	*orsp;
986 	Rel_cache	*rcp;
987 	Sym_desc	*sdp = rsp->rel_sym;
988 
989 	/*
990 	 * Static executables *do not* want any relocations against them.
991 	 * Since our engine still creates relocations against a WEAK UNDEFINED
992 	 * symbol in a static executable, it's best to disable them here
993 	 * instead of through out the relocation code.
994 	 */
995 	if ((ofl->ofl_flags & (FLG_OF_STATIC | FLG_OF_EXEC)) ==
996 	    (FLG_OF_STATIC | FLG_OF_EXEC))
997 		return (1);
998 
999 	/*
1000 	 * If no relocation cache structures are available allocate
1001 	 * a new one and link it into the cache list.
1002 	 */
1003 	if ((ofl->ofl_outrels.tail == 0) ||
1004 	    ((rcp = (Rel_cache *)ofl->ofl_outrels.tail->data) == 0) ||
1005 	    ((orsp = rcp->rc_free) == rcp->rc_end)) {
1006 		static size_t	nextsize = 0;
1007 		size_t		size;
1008 
1009 		/*
1010 		 * Output relocation numbers can vary considerably between
1011 		 * building executables or shared objects (pic vs. non-pic),
1012 		 * etc.  But, they typically aren't very large, so for these
1013 		 * objects use a standard bucket size.  For building relocatable
1014 		 * objects, typically there will be an output relocation for
1015 		 * every input relocation.
1016 		 */
1017 		if (nextsize == 0) {
1018 			if (ofl->ofl_flags & FLG_OF_RELOBJ) {
1019 				if ((size = ofl->ofl_relocincnt) == 0)
1020 					size = REL_LOIDESCNO;
1021 				if (size > REL_HOIDESCNO)
1022 					nextsize = REL_HOIDESCNO;
1023 				else
1024 					nextsize = REL_LOIDESCNO;
1025 			} else
1026 				nextsize = size = REL_HOIDESCNO;
1027 		} else
1028 			size = nextsize;
1029 
1030 		size = size * sizeof (Rel_desc);
1031 
1032 		if (((rcp = libld_malloc(sizeof (Rel_cache) + size)) == 0) ||
1033 		    (list_appendc(&ofl->ofl_outrels, rcp) == 0))
1034 			return (S_ERROR);
1035 
1036 		/* LINTED */
1037 		rcp->rc_free = orsp = (Rel_desc *)(rcp + 1);
1038 		/* LINTED */
1039 		rcp->rc_end = (Rel_desc *)((char *)rcp->rc_free + size);
1040 	}
1041 
1042 	/*
1043 	 * If we are adding a output relocation against a section
1044 	 * symbol (non-RELATIVE) then mark that section.  These sections
1045 	 * will be added to the .dynsym symbol table.
1046 	 */
1047 	if (sdp && (rsp->rel_rtype != M_R_RELATIVE) &&
1048 	    ((flags & FLG_REL_SCNNDX) ||
1049 	    (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION))) {
1050 
1051 		/*
1052 		 * If this is a COMMON symbol - no output section
1053 		 * exists yet - (it's created as part of sym_validate()).
1054 		 * So - we mark here that when it's created it should
1055 		 * be tagged with the FLG_OS_OUTREL flag.
1056 		 */
1057 		if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
1058 		    (sdp->sd_sym->st_shndx == SHN_COMMON)) {
1059 			if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS)
1060 				ofl->ofl_flags1 |= FLG_OF1_BSSOREL;
1061 			else
1062 				ofl->ofl_flags1 |= FLG_OF1_TLSOREL;
1063 		} else {
1064 			Os_desc	*osp = sdp->sd_isc->is_osdesc;
1065 
1066 			if (osp && ((osp->os_flags & FLG_OS_OUTREL) == 0)) {
1067 				ofl->ofl_dynshdrcnt++;
1068 				osp->os_flags |= FLG_OS_OUTREL;
1069 			}
1070 		}
1071 	}
1072 
1073 	*orsp = *rsp;
1074 	orsp->rel_flags |= flags;
1075 
1076 	rcp->rc_free++;
1077 	ofl->ofl_outrelscnt++;
1078 
1079 	if (flags & FLG_REL_GOT)
1080 		ofl->ofl_relocgotsz += (Xword)sizeof (Rela);
1081 	else if (flags & FLG_REL_PLT)
1082 		ofl->ofl_relocpltsz += (Xword)sizeof (Rela);
1083 	else if (flags & FLG_REL_BSS)
1084 		ofl->ofl_relocbsssz += (Xword)sizeof (Rela);
1085 	else if (flags & FLG_REL_NOINFO)
1086 		ofl->ofl_relocrelsz += (Xword)sizeof (Rela);
1087 	else
1088 		orsp->rel_osdesc->os_szoutrels += (Xword)sizeof (Rela);
1089 
1090 	if (orsp->rel_rtype == M_R_RELATIVE)
1091 		ofl->ofl_relocrelcnt++;
1092 
1093 	/*
1094 	 * We don't perform sorting on PLT relocations because
1095 	 * they have already been assigned a PLT index and if we
1096 	 * were to sort them we would have to re-assign the plt indexes.
1097 	 */
1098 	if (!(flags & FLG_REL_PLT))
1099 		ofl->ofl_reloccnt++;
1100 
1101 	/*
1102 	 * Insure a GLOBAL_OFFSET_TABLE is generated if required.
1103 	 */
1104 	if (IS_GOT_REQUIRED(orsp->rel_rtype))
1105 		ofl->ofl_flags |= FLG_OF_BLDGOT;
1106 
1107 	/*
1108 	 * Identify and possibly warn of a displacement relocation.
1109 	 */
1110 	if (orsp->rel_flags & FLG_REL_DISP) {
1111 		ofl->ofl_dtflags_1 |= DF_1_DISPRELPND;
1112 
1113 		if (ofl->ofl_flags & FLG_OF_VERBOSE)
1114 			ld_disp_errmsg(MSG_INTL(MSG_REL_DISPREL4), orsp, ofl);
1115 	}
1116 	DBG_CALL(Dbg_reloc_ors_entry(ofl->ofl_lml, ELF_DBG_LD, SHT_RELA,
1117 	    M_MACH, orsp));
1118 	return (1);
1119 }
1120 
1121 /*
1122  * Stub routine since register symbols are not supported on amd64.
1123  */
1124 /* ARGSUSED */
1125 uintptr_t
1126 ld_reloc_register(Rel_desc * rsp, Is_desc * isp, Ofl_desc * ofl)
1127 {
1128 	eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_REL_NOREG));
1129 	return (S_ERROR);
1130 }
1131 
1132 /*
1133  * process relocation for a LOCAL symbol
1134  */
1135 uintptr_t
1136 ld_reloc_local(Rel_desc * rsp, Ofl_desc * ofl)
1137 {
1138 	Word		flags = ofl->ofl_flags;
1139 	Sym_desc	*sdp = rsp->rel_sym;
1140 	Word		shndx = sdp->sd_sym->st_shndx;
1141 	Word		ortype = rsp->rel_rtype;
1142 
1143 	/*
1144 	 * if ((shared object) and (not pc relative relocation) and
1145 	 *    (not against ABS symbol))
1146 	 * then
1147 	 *	build R_AMD64_RELATIVE
1148 	 * fi
1149 	 */
1150 	if ((flags & FLG_OF_SHAROBJ) && (rsp->rel_flags & FLG_REL_LOAD) &&
1151 	    !(IS_PC_RELATIVE(rsp->rel_rtype)) &&
1152 	    !(IS_GOT_BASED(rsp->rel_rtype)) &&
1153 	    !(rsp->rel_isdesc != NULL &&
1154 	    (rsp->rel_isdesc->is_shdr->sh_type == SHT_SUNW_dof)) &&
1155 	    (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) ||
1156 	    (shndx != SHN_ABS) || (sdp->sd_aux && sdp->sd_aux->sa_symspec))) {
1157 
1158 		/*
1159 		 * R_AMD64_RELATIVE updates a 64bit address, if this
1160 		 * relocation isn't a 64bit binding then we can not
1161 		 * simplify it to a RELATIVE relocation.
1162 		 */
1163 		if (reloc_table[ortype].re_fsize != sizeof (Addr)) {
1164 			return (ld_add_outrel(NULL, rsp, ofl));
1165 		}
1166 
1167 		rsp->rel_rtype = R_AMD64_RELATIVE;
1168 		if (ld_add_outrel(FLG_REL_ADVAL, rsp, ofl) == S_ERROR)
1169 			return (S_ERROR);
1170 		rsp->rel_rtype = ortype;
1171 		return (1);
1172 	}
1173 
1174 	/*
1175 	 * If the relocation is against a 'non-allocatable' section
1176 	 * and we can not resolve it now - then give a warning
1177 	 * message.
1178 	 *
1179 	 * We can not resolve the symbol if either:
1180 	 *	a) it's undefined
1181 	 *	b) it's defined in a shared library and a
1182 	 *	   COPY relocation hasn't moved it to the executable
1183 	 *
1184 	 * Note: because we process all of the relocations against the
1185 	 *	text segment before any others - we know whether
1186 	 *	or not a copy relocation will be generated before
1187 	 *	we get here (see reloc_init()->reloc_segments()).
1188 	 */
1189 	if (!(rsp->rel_flags & FLG_REL_LOAD) &&
1190 	    ((shndx == SHN_UNDEF) ||
1191 	    ((sdp->sd_ref == REF_DYN_NEED) &&
1192 	    ((sdp->sd_flags & FLG_SY_MVTOCOMM) == 0)))) {
1193 		/*
1194 		 * If the relocation is against a SHT_SUNW_ANNOTATE
1195 		 * section - then silently ignore that the relocation
1196 		 * can not be resolved.
1197 		 */
1198 		if (rsp->rel_osdesc &&
1199 		    (rsp->rel_osdesc->os_shdr->sh_type == SHT_SUNW_ANNOTATE))
1200 			return (0);
1201 		(void) eprintf(ofl->ofl_lml, ERR_WARNING,
1202 		    MSG_INTL(MSG_REL_EXTERNSYM),
1203 		    conv_reloc_amd64_type(rsp->rel_rtype, 0),
1204 		    rsp->rel_isdesc->is_file->ifl_name,
1205 		    demangle(rsp->rel_sname), rsp->rel_osdesc->os_name);
1206 		return (1);
1207 	}
1208 
1209 	/*
1210 	 * Perform relocation.
1211 	 */
1212 	return (ld_add_actrel(NULL, rsp, ofl));
1213 }
1214 
1215 
1216 uintptr_t
1217 /* ARGSUSED */
1218 ld_reloc_GOTOP(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
1219 {
1220 	/*
1221 	 * Stub routine for common code compatibility, we shouldn't
1222 	 * actually get here on amd64.
1223 	 */
1224 	assert(0);
1225 	return (S_ERROR);
1226 }
1227 
1228 uintptr_t
1229 ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
1230 {
1231 	Word		rtype = rsp->rel_rtype;
1232 	Sym_desc	*sdp = rsp->rel_sym;
1233 	Word		flags = ofl->ofl_flags;
1234 	Gotndx		*gnp;
1235 
1236 	/*
1237 	 * If we're building an executable - use either the IE or LE access
1238 	 * model.  If we're building a shared object process any IE model.
1239 	 */
1240 	if ((flags & FLG_OF_EXEC) || (IS_TLS_IE(rtype))) {
1241 		/*
1242 		 * Set the DF_STATIC_TLS flag.
1243 		 */
1244 		ofl->ofl_dtflags |= DF_STATIC_TLS;
1245 
1246 		if (!local || ((flags & FLG_OF_EXEC) == 0)) {
1247 			/*
1248 			 * Assign a GOT entry for static TLS references.
1249 			 */
1250 			if ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs),
1251 			    GOT_REF_TLSIE, ofl, rsp)) == 0) {
1252 
1253 				if (ld_assign_got_TLS(local, rsp, ofl, sdp,
1254 				    gnp, GOT_REF_TLSIE, FLG_REL_STLS,
1255 				    rtype, R_AMD64_TPOFF64, 0) == S_ERROR)
1256 					return (S_ERROR);
1257 			}
1258 
1259 			/*
1260 			 * IE access model.
1261 			 */
1262 			if (IS_TLS_IE(rtype))
1263 				return (ld_add_actrel(FLG_REL_STLS, rsp, ofl));
1264 
1265 			/*
1266 			 * Fixups are required for other executable models.
1267 			 */
1268 			return (ld_add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS),
1269 			    rsp, ofl));
1270 		}
1271 
1272 		/*
1273 		 * LE access model.
1274 		 */
1275 		if (IS_TLS_LE(rtype))
1276 			return (ld_add_actrel(FLG_REL_STLS, rsp, ofl));
1277 
1278 		return (ld_add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS),
1279 		    rsp, ofl));
1280 	}
1281 
1282 	/*
1283 	 * Building a shared object.
1284 	 *
1285 	 * Assign a GOT entry for a dynamic TLS reference.
1286 	 */
1287 	if (IS_TLS_LD(rtype) && ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs),
1288 	    GOT_REF_TLSLD, ofl, rsp)) == 0)) {
1289 
1290 		if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSLD,
1291 		    FLG_REL_MTLS, rtype, R_AMD64_DTPMOD64, 0) == S_ERROR)
1292 			return (S_ERROR);
1293 
1294 	} else if (IS_TLS_GD(rtype) &&
1295 	    ((gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), GOT_REF_TLSGD,
1296 	    ofl, rsp)) == 0)) {
1297 
1298 		if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSGD,
1299 		    FLG_REL_DTLS, rtype, R_AMD64_DTPMOD64,
1300 		    R_AMD64_DTPOFF64) == S_ERROR)
1301 			return (S_ERROR);
1302 	}
1303 
1304 	if (IS_TLS_LD(rtype))
1305 		return (ld_add_actrel(FLG_REL_MTLS, rsp, ofl));
1306 
1307 	return (ld_add_actrel(FLG_REL_DTLS, rsp, ofl));
1308 }
1309 
1310 /* ARGSUSED3 */
1311 Gotndx *
1312 ld_find_gotndx(List * lst, Gotref gref, Ofl_desc * ofl, Rel_desc * rdesc)
1313 {
1314 	Listnode *	lnp;
1315 	Gotndx *	gnp;
1316 
1317 	assert(rdesc != 0);
1318 
1319 	if ((gref == GOT_REF_TLSLD) && ofl->ofl_tlsldgotndx)
1320 		return (ofl->ofl_tlsldgotndx);
1321 
1322 	for (LIST_TRAVERSE(lst, lnp, gnp)) {
1323 		if ((rdesc->rel_raddend == gnp->gn_addend) &&
1324 		    (gnp->gn_gotref == gref)) {
1325 			return (gnp);
1326 		}
1327 	}
1328 	return ((Gotndx *)0);
1329 }
1330 
1331 Xword
1332 ld_calc_got_offset(Rel_desc * rdesc, Ofl_desc * ofl)
1333 {
1334 	Os_desc		*osp = ofl->ofl_osgot;
1335 	Sym_desc	*sdp = rdesc->rel_sym;
1336 	Xword		gotndx;
1337 	Gotref		gref;
1338 	Gotndx		*gnp;
1339 
1340 	if (rdesc->rel_flags & FLG_REL_DTLS)
1341 		gref = GOT_REF_TLSGD;
1342 	else if (rdesc->rel_flags & FLG_REL_MTLS)
1343 		gref = GOT_REF_TLSLD;
1344 	else if (rdesc->rel_flags & FLG_REL_STLS)
1345 		gref = GOT_REF_TLSIE;
1346 	else
1347 		gref = GOT_REF_GENERIC;
1348 
1349 	gnp = ld_find_gotndx(&(sdp->sd_GOTndxs), gref, ofl, rdesc);
1350 	assert(gnp);
1351 
1352 	gotndx = (Xword)gnp->gn_gotndx;
1353 
1354 	if ((rdesc->rel_flags & FLG_REL_DTLS) &&
1355 	    (rdesc->rel_rtype == R_AMD64_DTPOFF64))
1356 		gotndx++;
1357 
1358 	return ((Xword)(osp->os_shdr->sh_addr + (gotndx * M_GOT_ENTSIZE)));
1359 }
1360 
1361 
1362 /* ARGSUSED5 */
1363 uintptr_t
1364 ld_assign_got_ndx(List * lst, Gotndx * pgnp, Gotref gref, Ofl_desc * ofl,
1365     Rel_desc * rsp, Sym_desc * sdp)
1366 {
1367 	Xword		raddend;
1368 	Gotndx		*gnp, *_gnp;
1369 	Listnode	*lnp, *plnp;
1370 	uint_t		gotents;
1371 
1372 	raddend = rsp->rel_raddend;
1373 	if (pgnp && (pgnp->gn_addend == raddend) &&
1374 	    (pgnp->gn_gotref == gref))
1375 		return (1);
1376 
1377 	if ((gref == GOT_REF_TLSGD) || (gref == GOT_REF_TLSLD))
1378 		gotents = 2;
1379 	else
1380 		gotents = 1;
1381 
1382 	plnp = 0;
1383 	for (LIST_TRAVERSE(lst, lnp, _gnp)) {
1384 		if (_gnp->gn_addend > raddend)
1385 			break;
1386 		plnp = lnp;
1387 	}
1388 
1389 	/*
1390 	 * Allocate a new entry.
1391 	 */
1392 	if ((gnp = libld_calloc(sizeof (Gotndx), 1)) == 0)
1393 		return (S_ERROR);
1394 	gnp->gn_addend = raddend;
1395 	gnp->gn_gotndx = ofl->ofl_gotcnt;
1396 	gnp->gn_gotref = gref;
1397 
1398 	ofl->ofl_gotcnt += gotents;
1399 
1400 	if (gref == GOT_REF_TLSLD) {
1401 		ofl->ofl_tlsldgotndx = gnp;
1402 		return (1);
1403 	}
1404 
1405 	if (plnp == 0) {
1406 		/*
1407 		 * Insert at head of list
1408 		 */
1409 		if (list_prependc(lst, (void *)gnp) == 0)
1410 			return (S_ERROR);
1411 	} else if (_gnp->gn_addend > raddend) {
1412 		/*
1413 		 * Insert in middle of lest
1414 		 */
1415 		if (list_insertc(lst, (void *)gnp, plnp) == 0)
1416 			return (S_ERROR);
1417 	} else {
1418 		/*
1419 		 * Append to tail of list
1420 		 */
1421 		if (list_appendc(lst, (void *)gnp) == 0)
1422 			return (S_ERROR);
1423 	}
1424 	return (1);
1425 }
1426 
1427 void
1428 ld_assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl)
1429 {
1430 	sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++;
1431 	sdp->sd_aux->sa_PLTGOTndx = ofl->ofl_gotcnt++;
1432 	ofl->ofl_flags |= FLG_OF_BLDGOT;
1433 }
1434 
1435 static uchar_t plt0_template[M_PLT_ENTSIZE] = {
1436 /* 0x00 PUSHQ GOT+8(%rip) */	0xff, 0x35, 0x00, 0x00, 0x00, 0x00,
1437 /* 0x06 JMP   *GOT+16(%rip) */	0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
1438 /* 0x0c NOP */			0x90,
1439 /* 0x0d NOP */			0x90,
1440 /* 0x0e NOP */			0x90,
1441 /* 0x0f NOP */			0x90
1442 };
1443 
1444 /*
1445  * Initializes .got[0] with the _DYNAMIC symbol value.
1446  */
1447 uintptr_t
1448 ld_fillin_gotplt(Ofl_desc *ofl)
1449 {
1450 	Word	flags = ofl->ofl_flags;
1451 	Word	dtflags1 = ofl->ofl_dtflags_1;
1452 
1453 	if (ofl->ofl_osgot) {
1454 		Sym_desc	*sdp;
1455 
1456 		if ((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_DYNAMIC_U),
1457 		    SYM_NOHASH, 0, ofl)) != NULL) {
1458 			uchar_t	*genptr;
1459 
1460 			genptr = ((uchar_t *)ofl->ofl_osgot->os_outdata->d_buf +
1461 			    (M_GOT_XDYNAMIC * M_GOT_ENTSIZE));
1462 			/* LINTED */
1463 			*(Xword *)genptr = sdp->sd_sym->st_value;
1464 		}
1465 	}
1466 
1467 	/*
1468 	 * Fill in the reserved slot in the procedure linkage table the first
1469 	 * entry is:
1470 	 *	0x00 PUSHQ	GOT+8(%rip)	    # GOT[1]
1471 	 *	0x06 JMP	*GOT+16(%rip)	    # GOT[2]
1472 	 *	0x0c NOP
1473 	 *	0x0d NOP
1474 	 *	0x0e NOP
1475 	 *	0x0f NOP
1476 	 */
1477 	if ((flags & FLG_OF_DYNAMIC) && ofl->ofl_osplt) {
1478 		uchar_t	*pltent;
1479 		Xword	val1;
1480 
1481 		pltent = (uchar_t *)ofl->ofl_osplt->os_outdata->d_buf;
1482 		bcopy(plt0_template, pltent, sizeof (plt0_template));
1483 
1484 		/*
1485 		 * filin:
1486 		 *	PUSHQ GOT + 8(%rip)
1487 		 *
1488 		 * Note: 0x06 below represents the offset to the
1489 		 *	 next instruction - which is what %rip will
1490 		 *	 be pointing at.
1491 		 */
1492 		val1 = (ofl->ofl_osgot->os_shdr->sh_addr) +
1493 			(M_GOT_XLINKMAP * M_GOT_ENTSIZE) -
1494 			ofl->ofl_osplt->os_shdr->sh_addr - 0x06;
1495 
1496 		/*
1497 		 * If '-z noreloc' is specified - skip the do_reloc
1498 		 * stage.
1499 		 */
1500 		if ((flags & FLG_OF_RELOBJ) ||
1501 		    !(dtflags1 & DF_1_NORELOC)) {
1502 			if (do_reloc(R_AMD64_GOTPCREL, &pltent[0x02],
1503 			    &val1, MSG_ORIG(MSG_SYM_PLTENT),
1504 			    MSG_ORIG(MSG_SPECFIL_PLTENT), ofl->ofl_lml) == 0) {
1505 				eprintf(ofl->ofl_lml, ERR_FATAL,
1506 				    MSG_INTL(MSG_PLT_PLT0FAIL));
1507 				return (S_ERROR);
1508 			}
1509 		}
1510 
1511 		/*
1512 		 * filin:
1513 		 *  JMP	*GOT+16(%rip)
1514 		 */
1515 		val1 = (ofl->ofl_osgot->os_shdr->sh_addr) +
1516 			(M_GOT_XRTLD * M_GOT_ENTSIZE) -
1517 			ofl->ofl_osplt->os_shdr->sh_addr - 0x0c;
1518 		/*
1519 		 * If '-z noreloc' is specified - skip the do_reloc
1520 		 * stage.
1521 		 */
1522 		if ((flags & FLG_OF_RELOBJ) ||
1523 		    !(dtflags1 & DF_1_NORELOC)) {
1524 			if (do_reloc(R_AMD64_GOTPCREL, &pltent[0x08],
1525 			    &val1, MSG_ORIG(MSG_SYM_PLTENT),
1526 			    MSG_ORIG(MSG_SPECFIL_PLTENT), ofl->ofl_lml) == 0) {
1527 				eprintf(ofl->ofl_lml, ERR_FATAL,
1528 				    MSG_INTL(MSG_PLT_PLT0FAIL));
1529 				return (S_ERROR);
1530 			}
1531 		}
1532 	}
1533 	return (1);
1534 }
1535