machrel.amd.c revision 1618:8c9a4f31d225
11708Sstevel/*
21708Sstevel * CDDL HEADER START
31708Sstevel *
41708Sstevel * The contents of this file are subject to the terms of the
51708Sstevel * Common Development and Distribution License (the "License").
61708Sstevel * You may not use this file except in compliance with the License.
71708Sstevel *
81708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel * or http://www.opensolaris.org/os/licensing.
101708Sstevel * See the License for the specific language governing permissions
111708Sstevel * and limitations under the License.
121708Sstevel *
131708Sstevel * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel *
191708Sstevel * CDDL HEADER END
201708Sstevel */
211708Sstevel
2210207SJames.McPherson@Sun.COM/*
231708Sstevel * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
241708Sstevel * Use is subject to license terms.
251708Sstevel */
261708Sstevel#pragma ident	"%Z%%M%	%I%	%E% SMI"
271708Sstevel
281708Sstevel#include	<string.h>
291708Sstevel#include	<stdio.h>
301708Sstevel#include	<strings.h>
311708Sstevel#include	<sys/elf_amd64.h>
321708Sstevel#include	<debug.h>
331708Sstevel#include	<reloc.h>
341708Sstevel#include	"msg.h"
351708Sstevel#include	"_libld.h"
361708Sstevel
371708SstevelWord
381708Sstevelld_init_rel(Rel_desc *reld, void *reloc)
391708Sstevel{
401708Sstevel	Rela *	rel = (Rela *)reloc;
411708Sstevel
421708Sstevel	/* LINTED */
431708Sstevel	reld->rel_rtype = (Word)ELF_R_TYPE(rel->r_info);
441708Sstevel	reld->rel_roffset = rel->r_offset;
451708Sstevel	reld->rel_raddend = rel->r_addend;
461708Sstevel	reld->rel_typedata = 0;
471708Sstevel
481708Sstevel	reld->rel_flags |= FLG_REL_RELA;
491708Sstevel
501708Sstevel	return ((Word)ELF_R_SYM(rel->r_info));
511708Sstevel}
521708Sstevel
531708Sstevelvoid
541708Sstevelld_mach_eflags(Ehdr *ehdr, Ofl_desc *ofl)
551708Sstevel{
561708Sstevel	ofl->ofl_dehdr->e_flags |= ehdr->e_flags;
571708Sstevel}
581708Sstevel
591708Sstevelvoid
6010355SAli.Bahrami@Sun.COMld_mach_make_dynamic(Ofl_desc *ofl, size_t *cnt)
6110355SAli.Bahrami@Sun.COM{
621708Sstevel	if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) {
631708Sstevel		/*
641708Sstevel		 * Create this entry if we are going to create a PLT table.
651708Sstevel		 */
661708Sstevel		if (ofl->ofl_pltcnt)
671708Sstevel			(*cnt)++;		/* DT_PLTGOT */
681708Sstevel	}
691708Sstevel}
701708Sstevel
711708Sstevelvoid
721708Sstevelld_mach_update_odynamic(Ofl_desc *ofl, Dyn **dyn)
731708Sstevel{
741708Sstevel	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && ofl->ofl_pltcnt) {
751708Sstevel		(*dyn)->d_tag = DT_PLTGOT;
761708Sstevel		if (ofl->ofl_osgot)
771708Sstevel			(*dyn)->d_un.d_ptr = ofl->ofl_osgot->os_shdr->sh_addr;
781708Sstevel		else
791708Sstevel			(*dyn)->d_un.d_ptr = 0;
801708Sstevel		(*dyn)++;
811708Sstevel	}
8210207SJames.McPherson@Sun.COM}
831708Sstevel
841708SstevelXword
851708Sstevelld_calc_plt_addr(Sym_desc *sdp, Ofl_desc *ofl)
861708Sstevel{
871708Sstevel	Xword	value;
881708Sstevel
891708Sstevel	value = (Xword)(ofl->ofl_osplt->os_shdr->sh_addr) +
901708Sstevel	    M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) * M_PLT_ENTSIZE);
911708Sstevel	return (value);
921708Sstevel}
931708Sstevel
941708Sstevel/*
951708Sstevel *  Build a single plt entry - code is:
961708Sstevel *	JMP	*name1@GOTPCREL(%rip)
971708Sstevel *	PUSHL	$index
981708Sstevel *	JMP	.PLT0
991708Sstevel */
1001708Sstevelstatic uchar_t pltn_entry[M_PLT_ENTSIZE] = {
1011708Sstevel/* 0x00 jmpq *name1@GOTPCREL(%rip) */	0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
1021708Sstevel/* 0x06 pushq $index */			0x68, 0x00, 0x00, 0x00, 0x00,
1031708Sstevel/* 0x0b jmpq  .plt0(%rip) */		0xe9, 0x00, 0x00, 0x00, 0x00
1041708Sstevel/* 0x10 */
1051708Sstevel};
1061708Sstevel
1071708Sstevelstatic uintptr_t
108plt_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
206uintptr_t
207ld_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 */
399static 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
412static 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
425static 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
446static Fixupret
447tls_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
611uintptr_t
612ld_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),
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),
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
981uintptr_t
982ld_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_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 */
1124uintptr_t
1125ld_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 */
1134uintptr_t
1135ld_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 = rsp->rel_sym->sd_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),
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
1215uintptr_t
1216/* ARGSUSED */
1217ld_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
1226uintptr_t
1227ld_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),
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),
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)));
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),
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),
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),
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 */
1402Gotndx *
1403ld_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
1422Xword
1423ld_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 */
1454uintptr_t
1455ld_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
1518void
1519ld_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
1526static 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 */
1538uintptr_t
1539ld_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