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.
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.
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]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Get the x86 version of the relocation engine */
27 #define DO_RELOC_LIBLD_X86
32 #include <sys/elf_amd64.h>
35 #include <i386/machdep_x86.h>
40 * This module uses do_reloc_ld() to execute several synthesized relocations.
41 * That function expects to be passed two things that we need to construct
44 * 1) A Rel_desc descriptor for each relocation type, from which the
45 * rel_rtype field, and nothing else, is obtained. This is easily
46 * handled by constructing the necessary descriptors.
48 * 2) A function, which called with the Rel_desc descriptor, returns
49 * a string representing the name of the symbol associated with
50 * the descriptor. The usual function for this is ld_reloc_sym_name().
51 * However, that function will not work in this case, as these synthetic
52 * relocations do not have an associated symbol. We supply the
53 * syn_rdesc_sym_name() function to simply return the fixed name.
55 static Rel_desc rdesc_r_amd64_gotpcrel
= {
56 NULL
, NULL
, NULL
, 0, 0, 0, R_AMD64_GOTPCREL
};
57 static Rel_desc rdesc_r_amd64_32
= {
58 NULL
, NULL
, NULL
, 0, 0, 0, R_AMD64_32
};
59 static Rel_desc rdesc_r_amd64_pc32
= {
60 NULL
, NULL
, NULL
, 0, 0, 0, R_AMD64_PC32
};
64 syn_rdesc_sym_name(Rel_desc
*rdesc
)
66 return (MSG_ORIG(MSG_SYM_PLTENT
));
70 * Search the GOT index list for a GOT entry with a matching reference and the
74 ld_find_got_ndx(Alist
*alp
, Gotref gref
, Ofl_desc
*ofl
, Rel_desc
*rdesc
)
81 if ((gref
== GOT_REF_TLSLD
) && ofl
->ofl_tlsldgotndx
)
82 return (ofl
->ofl_tlsldgotndx
);
84 for (ALIST_TRAVERSE(alp
, idx
, gnp
)) {
85 if ((rdesc
->rel_raddend
== gnp
->gn_addend
) &&
86 (gnp
->gn_gotref
== gref
)) {
94 ld_calc_got_offset(Rel_desc
*rdesc
, Ofl_desc
*ofl
)
96 Os_desc
*osp
= ofl
->ofl_osgot
;
97 Sym_desc
*sdp
= rdesc
->rel_sym
;
102 if (rdesc
->rel_flags
& FLG_REL_DTLS
)
103 gref
= GOT_REF_TLSGD
;
104 else if (rdesc
->rel_flags
& FLG_REL_MTLS
)
105 gref
= GOT_REF_TLSLD
;
106 else if (rdesc
->rel_flags
& FLG_REL_STLS
)
107 gref
= GOT_REF_TLSIE
;
109 gref
= GOT_REF_GENERIC
;
111 gnp
= ld_find_got_ndx(sdp
->sd_GOTndxs
, gref
, ofl
, rdesc
);
114 gotndx
= (Xword
)gnp
->gn_gotndx
;
116 if ((rdesc
->rel_flags
& FLG_REL_DTLS
) &&
117 (rdesc
->rel_rtype
== R_AMD64_DTPOFF64
))
120 return ((Xword
)(osp
->os_shdr
->sh_addr
+ (gotndx
* M_GOT_ENTSIZE
)));
124 ld_init_rel(Rel_desc
*reld
, Word
*typedata
, void *reloc
)
126 Rela
*rel
= (Rela
*)reloc
;
129 reld
->rel_rtype
= (Word
)ELF_R_TYPE(rel
->r_info
, M_MACH
);
130 reld
->rel_roffset
= rel
->r_offset
;
131 reld
->rel_raddend
= rel
->r_addend
;
134 reld
->rel_flags
|= FLG_REL_RELA
;
136 return ((Word
)ELF_R_SYM(rel
->r_info
));
140 ld_mach_eflags(Ehdr
*ehdr
, Ofl_desc
*ofl
)
142 ofl
->ofl_dehdr
->e_flags
|= ehdr
->e_flags
;
146 ld_mach_make_dynamic(Ofl_desc
*ofl
, size_t *cnt
)
148 if (!(ofl
->ofl_flags
& FLG_OF_RELOBJ
)) {
150 * Create this entry if we are going to create a PLT table.
153 (*cnt
)++; /* DT_PLTGOT */
158 ld_mach_update_odynamic(Ofl_desc
*ofl
, Dyn
**dyn
)
160 if (((ofl
->ofl_flags
& FLG_OF_RELOBJ
) == 0) && ofl
->ofl_pltcnt
) {
161 (*dyn
)->d_tag
= DT_PLTGOT
;
163 (*dyn
)->d_un
.d_ptr
= ofl
->ofl_osgot
->os_shdr
->sh_addr
;
165 (*dyn
)->d_un
.d_ptr
= 0;
171 ld_calc_plt_addr(Sym_desc
*sdp
, Ofl_desc
*ofl
)
175 value
= (Xword
)(ofl
->ofl_osplt
->os_shdr
->sh_addr
) +
176 M_PLT_RESERVSZ
+ ((sdp
->sd_aux
->sa_PLTndx
- 1) * M_PLT_ENTSIZE
);
181 * Build a single plt entry - code is:
182 * JMP *name1@GOTPCREL(%rip)
186 static uchar_t pltn_entry
[M_PLT_ENTSIZE
] = {
187 /* 0x00 jmpq *name1@GOTPCREL(%rip) */ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
188 /* 0x06 pushq $index */ 0x68, 0x00, 0x00, 0x00, 0x00,
189 /* 0x0b jmpq .plt0(%rip) */ 0xe9, 0x00, 0x00, 0x00, 0x00
194 plt_entry(Ofl_desc
* ofl
, Sym_desc
* sdp
)
196 uchar_t
*plt0
, *pltent
, *gotent
;
200 int bswap
= (ofl
->ofl_flags1
& FLG_OF1_ENCDIFF
) != 0;
202 got_off
= sdp
->sd_aux
->sa_PLTGOTndx
* M_GOT_ENTSIZE
;
203 plt_off
= M_PLT_RESERVSZ
+ ((sdp
->sd_aux
->sa_PLTndx
- 1) *
205 plt0
= (uchar_t
*)(ofl
->ofl_osplt
->os_outdata
->d_buf
);
206 pltent
= plt0
+ plt_off
;
207 gotent
= (uchar_t
*)(ofl
->ofl_osgot
->os_outdata
->d_buf
) + got_off
;
209 bcopy(pltn_entry
, pltent
, sizeof (pltn_entry
));
211 * Fill in the got entry with the address of the next instruction.
214 *(Word
*)gotent
= ofl
->ofl_osplt
->os_shdr
->sh_addr
+ plt_off
+
218 *(Word
*)gotent
= ld_bswap_Word(*(Word
*)gotent
);
221 * If '-z noreloc' is specified - skip the do_reloc_ld
224 if (!OFL_DO_RELOC(ofl
))
229 * jmpq *name1@gotpcrel(%rip)
231 * NOTE: 0x06 represents next instruction.
233 val1
= (ofl
->ofl_osgot
->os_shdr
->sh_addr
+ got_off
) -
234 (ofl
->ofl_osplt
->os_shdr
->sh_addr
+ plt_off
) - 0x06;
236 if (do_reloc_ld(&rdesc_r_amd64_gotpcrel
, &pltent
[0x02], &val1
,
237 syn_rdesc_sym_name
, MSG_ORIG(MSG_SPECFIL_PLTENT
), bswap
,
238 ofl
->ofl_lml
) == 0) {
239 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_PLT_PLTNFAIL
),
240 sdp
->sd_aux
->sa_PLTndx
, demangle(sdp
->sd_name
));
248 val1
= (Xword
)(sdp
->sd_aux
->sa_PLTndx
- 1);
250 if (do_reloc_ld(&rdesc_r_amd64_32
, &pltent
[0x07], &val1
,
251 syn_rdesc_sym_name
, MSG_ORIG(MSG_SPECFIL_PLTENT
), bswap
,
252 ofl
->ofl_lml
) == 0) {
253 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_PLT_PLTNFAIL
),
254 sdp
->sd_aux
->sa_PLTndx
, demangle(sdp
->sd_name
));
261 * NOTE: 0x10 represents next instruction. The rather complex
262 * series of casts is necessary to sign extend an offset into
263 * a 64-bit value while satisfying various compiler error
264 * checks. Handle with care.
266 val1
= (Xword
)((intptr_t)((uintptr_t)plt0
-
267 (uintptr_t)(&pltent
[0x10])));
269 if (do_reloc_ld(&rdesc_r_amd64_pc32
, &pltent
[0x0c], &val1
,
270 syn_rdesc_sym_name
, MSG_ORIG(MSG_SPECFIL_PLTENT
), bswap
,
271 ofl
->ofl_lml
) == 0) {
272 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_PLT_PLTNFAIL
),
273 sdp
->sd_aux
->sa_PLTndx
, demangle(sdp
->sd_name
));
281 ld_perform_outreloc(Rel_desc
* orsp
, Ofl_desc
* ofl
, Boolean
*remain_seen
)
283 Os_desc
* relosp
, * osp
= 0;
285 Xword roffset
, value
;
289 Sym_desc
* sdp
, * psym
= (Sym_desc
*)0;
292 raddend
= orsp
->rel_raddend
;
296 * If the section this relocation is against has been discarded
297 * (-zignore), then also discard (skip) the relocation itself.
299 if (orsp
->rel_isdesc
&& ((orsp
->rel_flags
&
300 (FLG_REL_GOT
| FLG_REL_BSS
| FLG_REL_PLT
| FLG_REL_NOINFO
)) == 0) &&
301 (orsp
->rel_isdesc
->is_flags
& FLG_IS_DISCARD
)) {
302 DBG_CALL(Dbg_reloc_discard(ofl
->ofl_lml
, M_MACH
, orsp
));
307 * If this is a relocation against a move table, or expanded move
308 * table, adjust the relocation entries.
310 if (RELAUX_GET_MOVE(orsp
))
311 ld_adj_movereloc(ofl
, orsp
);
314 * If this is a relocation against a section then we need to adjust the
315 * raddend field to compensate for the new position of the input section
316 * within the new output section.
318 if (ELF_ST_TYPE(sdp
->sd_sym
->st_info
) == STT_SECTION
) {
319 if (ofl
->ofl_parsyms
&&
320 (sdp
->sd_isc
->is_flags
& FLG_IS_RELUPD
) &&
322 (psym
= ld_am_I_partial(orsp
, orsp
->rel_raddend
))) {
323 DBG_CALL(Dbg_move_outsctadj(ofl
->ofl_lml
, psym
));
325 if (ofl
->ofl_flags
& FLG_OF_RELOBJ
)
326 raddend
= psym
->sd_sym
->st_value
;
328 raddend
= psym
->sd_sym
->st_value
-
329 psym
->sd_isc
->is_osdesc
->os_shdr
->sh_addr
;
331 raddend
+= (Off
)_elf_getxoff(psym
->sd_isc
->is_indata
);
332 if (psym
->sd_isc
->is_shdr
->sh_flags
& SHF_ALLOC
)
334 psym
->sd_isc
->is_osdesc
->os_shdr
->sh_addr
;
337 raddend
+= (Off
)_elf_getxoff(sdp
->sd_isc
->is_indata
);
338 if (sdp
->sd_isc
->is_shdr
->sh_flags
& SHF_ALLOC
)
340 sdp
->sd_isc
->is_osdesc
->os_shdr
->sh_addr
;
344 value
= sdp
->sd_sym
->st_value
;
346 if (orsp
->rel_flags
& FLG_REL_GOT
) {
348 * Note: for GOT relative relocations on amd64
349 * we discard the addend. It was relevant
350 * to the reference - not to the data item
351 * being referenced (ie: that -4 thing).
354 osp
= ofl
->ofl_osgot
;
355 roffset
= ld_calc_got_offset(orsp
, ofl
);
357 } else if (orsp
->rel_flags
& FLG_REL_PLT
) {
359 * Note that relocations for PLT's actually
360 * cause a relocation againt the GOT.
362 osp
= ofl
->ofl_osplt
;
363 roffset
= (ofl
->ofl_osgot
->os_shdr
->sh_addr
) +
364 sdp
->sd_aux
->sa_PLTGOTndx
* M_GOT_ENTSIZE
;
366 if (plt_entry(ofl
, sdp
) == S_ERROR
)
369 } else if (orsp
->rel_flags
& FLG_REL_BSS
) {
371 * This must be a R_AMD64_COPY. For these set the roffset to
372 * point to the new symbols location.
374 osp
= ofl
->ofl_isbss
->is_osdesc
;
378 * The raddend doesn't mean anything in a R_SPARC_COPY
379 * relocation. Null it out because it can confuse people.
383 osp
= RELAUX_GET_OSDESC(orsp
);
386 * Calculate virtual offset of reference point; equals offset
387 * into section + vaddr of section for loadable sections, or
388 * offset plus section displacement for nonloadable sections.
390 roffset
= orsp
->rel_roffset
+
391 (Off
)_elf_getxoff(orsp
->rel_isdesc
->is_indata
);
392 if (!(ofl
->ofl_flags
& FLG_OF_RELOBJ
))
393 roffset
+= orsp
->rel_isdesc
->is_osdesc
->
397 if ((osp
== 0) || ((relosp
= osp
->os_relosdesc
) == 0))
398 relosp
= ofl
->ofl_osrel
;
401 * Assign the symbols index for the output relocation. If the
402 * relocation refers to a SECTION symbol then it's index is based upon
403 * the output sections symbols index. Otherwise the index can be
404 * derived from the symbols index itself.
406 if (orsp
->rel_rtype
== R_AMD64_RELATIVE
)
408 else if ((orsp
->rel_flags
& FLG_REL_SCNNDX
) ||
409 (ELF_ST_TYPE(sdp
->sd_sym
->st_info
) == STT_SECTION
)) {
410 if (sectmoved
== 0) {
412 * Check for a null input section. This can
413 * occur if this relocation references a symbol
414 * generated by sym_add_sym().
416 if (sdp
->sd_isc
&& sdp
->sd_isc
->is_osdesc
)
417 ndx
= sdp
->sd_isc
->is_osdesc
->os_identndx
;
421 ndx
= ofl
->ofl_parexpnndx
;
423 ndx
= sdp
->sd_symndx
;
426 * Add the symbols 'value' to the addend field.
428 if (orsp
->rel_flags
& FLG_REL_ADVAL
)
432 * The addend field for R_AMD64_DTPMOD64 means nothing. The addend
433 * is propagated in the corresponding R_AMD64_DTPOFF64 relocation.
435 if (orsp
->rel_rtype
== R_AMD64_DTPMOD64
)
438 relbits
= (char *)relosp
->os_outdata
->d_buf
;
440 rea
.r_info
= ELF_R_INFO(ndx
, orsp
->rel_rtype
);
441 rea
.r_offset
= roffset
;
442 rea
.r_addend
= raddend
;
443 DBG_CALL(Dbg_reloc_out(ofl
, ELF_DBG_LD
, SHT_RELA
, &rea
, relosp
->os_name
,
444 ld_reloc_sym_name(orsp
)));
447 * Assert we haven't walked off the end of our relocation table.
449 assert(relosp
->os_szoutrels
<= relosp
->os_shdr
->sh_size
);
451 (void) memcpy((relbits
+ relosp
->os_szoutrels
),
452 (char *)&rea
, sizeof (Rela
));
453 relosp
->os_szoutrels
+= (Xword
)sizeof (Rela
);
456 * Determine if this relocation is against a non-writable, allocatable
457 * section. If so we may need to provide a text relocation diagnostic.
458 * Note that relocations against the .plt (R_AMD64_JUMP_SLOT) actually
459 * result in modifications to the .got.
461 if (orsp
->rel_rtype
== R_AMD64_JUMP_SLOT
)
462 osp
= ofl
->ofl_osgot
;
464 ld_reloc_remain_entry(orsp
, osp
, ofl
, remain_seen
);
469 * amd64 Instructions for TLS processing
471 static uchar_t tlsinstr_gd_ie
[] = {
473 * 0x00 movq %fs:0, %rax
475 0x64, 0x48, 0x8b, 0x04, 0x25,
476 0x00, 0x00, 0x00, 0x00,
478 * 0x09 addq x@gottpoff(%rip), %rax
480 0x48, 0x03, 0x05, 0x00, 0x00,
484 static uchar_t tlsinstr_gd_le
[] = {
486 * 0x00 movq %fs:0, %rax
488 0x64, 0x48, 0x8b, 0x04, 0x25,
489 0x00, 0x00, 0x00, 0x00,
491 * 0x09 leaq x@gottpoff(%rip), %rax
493 0x48, 0x8d, 0x80, 0x00, 0x00,
497 static uchar_t tlsinstr_ld_le
[] = {
513 0x64, 0x48, 0x8b, 0x04, 0x25,
514 0x00, 0x00, 0x00, 0x00
521 #define REX_PREFIX 0x40
523 #define REX_RW (REX_PREFIX | REX_R | REX_W)
524 #define REX_BW (REX_PREFIX | REX_B | REX_W)
525 #define REX_BRW (REX_PREFIX | REX_B | REX_R | REX_W)
529 #define INSN_ADDMR 0x03 /* addq mem,reg */
530 #define INSN_ADDIR 0x81 /* addq imm,reg */
531 #define INSN_MOVMR 0x8b /* movq mem,reg */
532 #define INSN_MOVIR 0xc7 /* movq imm,reg */
533 #define INSN_LEA 0x8d /* leaq mem,reg */
536 tls_fixups(Ofl_desc
*ofl
, Rel_desc
*arsp
)
538 Sym_desc
*sdp
= arsp
->rel_sym
;
539 Word rtype
= arsp
->rel_rtype
;
542 offset
= (uchar_t
*)((uintptr_t)arsp
->rel_roffset
+
543 (uintptr_t)_elf_getxoff(arsp
->rel_isdesc
->is_indata
) +
544 (uintptr_t)RELAUX_GET_OSDESC(arsp
)->os_outdata
->d_buf
);
547 * Note that in certain of the original insn sequences below, the
548 * instructions are not necessarily adjacent
550 if (sdp
->sd_ref
== REF_DYN_NEED
) {
561 * 0x01 leaq x@tlsgd(%rip), %rdi
564 * 0x0b call __tls_get_addr@plt
567 * 0x00 movq %fs:0, %rax
568 * 0x09 addq x@gottpoff(%rip), %rax
571 DBG_CALL(Dbg_reloc_transition(ofl
->ofl_lml
, M_MACH
,
572 R_AMD64_GOTTPOFF
, arsp
, ld_reloc_sym_name
));
573 arsp
->rel_rtype
= R_AMD64_GOTTPOFF
;
574 arsp
->rel_roffset
+= 8;
575 arsp
->rel_raddend
= (Sxword
)-4;
578 * Adjust 'offset' to beginning of instruction
582 (void) memcpy(offset
, tlsinstr_gd_ie
,
583 sizeof (tlsinstr_gd_ie
));
588 * Fixup done via the TLS_GD relocation.
590 DBG_CALL(Dbg_reloc_transition(ofl
->ofl_lml
, M_MACH
,
591 R_AMD64_NONE
, arsp
, ld_reloc_sym_name
));
606 * 0x01 leaq x@tlsgd(%rip), %rdi
609 * 0x0b call __tls_get_addr@plt
612 * 0x00 movq %fs:0, %rax
613 * 0x09 leaq x@tpoff(%rax), %rax
616 DBG_CALL(Dbg_reloc_transition(ofl
->ofl_lml
, M_MACH
,
617 R_AMD64_TPOFF32
, arsp
, ld_reloc_sym_name
));
618 arsp
->rel_rtype
= R_AMD64_TPOFF32
;
619 arsp
->rel_roffset
+= 8;
620 arsp
->rel_raddend
= 0;
623 * Adjust 'offset' to beginning of instruction sequence.
626 (void) memcpy(offset
, tlsinstr_gd_le
, sizeof (tlsinstr_gd_le
));
629 case R_AMD64_GOTTPOFF
: {
635 * addq x@gottpoff(%rip), %reg
638 * leaq x@tpoff(%reg), %reg
640 * Transition (as a special case):
641 * movq %fs:0, %r12/%rsp
642 * addq x@gottpoff(%rip), %r12/%rsp
644 * movq %fs:0, %r12/%rsp
645 * addq x@tpoff(%rax), %r12/%rsp
648 * movq x@gottpoff(%rip), %reg
649 * movq %fs:(%reg), %reg
651 * movq x@tpoff(%reg), %reg
652 * movq %fs:(%reg), %reg
654 Conv_inv_buf_t inv_buf
;
655 uint8_t reg
; /* Register */
659 reg
= offset
[2] >> 3; /* Encoded dest. reg. operand */
661 DBG_CALL(Dbg_reloc_transition(ofl
->ofl_lml
, M_MACH
,
662 R_AMD64_TPOFF32
, arsp
, ld_reloc_sym_name
));
663 arsp
->rel_rtype
= R_AMD64_TPOFF32
;
664 arsp
->rel_raddend
= 0;
667 * This is transition 2, and the special case of form 1 where
668 * a normal transition would index %rsp or %r12 and need a SIB
669 * byte in the leaq for which we lack space
671 if ((offset
[1] == INSN_MOVMR
) ||
672 ((offset
[1] == INSN_ADDMR
) && (reg
== REG_ESP
))) {
674 * If we needed an extra bit of MOD.reg to refer to
675 * this register as the dest of the original movq we
676 * need an extra bit of MOD.rm to refer to it in the
677 * dest of the replacement movq or addq.
679 if (offset
[0] == REX_RW
)
682 offset
[1] = (offset
[1] == INSN_MOVMR
) ?
683 INSN_MOVIR
: INSN_ADDIR
;
684 offset
[2] = 0xc0 | reg
;
687 } else if (offset
[1] == INSN_ADDMR
) {
689 * If we needed an extra bit of MOD.reg to refer to
690 * this register in the dest of the addq we need an
691 * extra bit of both MOD.reg and MOD.rm to refer to it
692 * in the source and dest of the leaq
694 if (offset
[0] == REX_RW
)
697 offset
[1] = INSN_LEA
;
698 offset
[2] = 0x80 | (reg
<< 3) | reg
;
703 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_REL_BADTLSINS
),
704 conv_reloc_amd64_type(arsp
->rel_rtype
, 0, &inv_buf
),
705 arsp
->rel_isdesc
->is_file
->ifl_name
,
706 ld_reloc_sym_name(arsp
),
707 arsp
->rel_isdesc
->is_name
,
708 EC_OFF(arsp
->rel_roffset
));
716 * 0x00 leaq x1@tlsgd(%rip), %rdi
717 * 0x07 call __tls_get_addr@plt
723 * 0x03 movq %fs:0, %rax
725 DBG_CALL(Dbg_reloc_transition(ofl
->ofl_lml
, M_MACH
,
726 R_AMD64_NONE
, arsp
, ld_reloc_sym_name
));
728 (void) memcpy(offset
, tlsinstr_ld_le
, sizeof (tlsinstr_ld_le
));
731 case R_AMD64_DTPOFF32
:
736 * 0x00 leaq x1@dtpoff(%rax), %rcx
738 * 0x00 leaq x1@tpoff(%rax), %rcx
740 DBG_CALL(Dbg_reloc_transition(ofl
->ofl_lml
, M_MACH
,
741 R_AMD64_TPOFF32
, arsp
, ld_reloc_sym_name
));
742 arsp
->rel_rtype
= R_AMD64_TPOFF32
;
743 arsp
->rel_raddend
= 0;
751 ld_do_activerelocs(Ofl_desc
*ofl
)
756 uintptr_t return_code
= 1;
757 ofl_flag_t flags
= ofl
->ofl_flags
;
759 if (aplist_nitems(ofl
->ofl_actrels
.rc_list
) != 0)
760 DBG_CALL(Dbg_reloc_doact_title(ofl
->ofl_lml
));
763 * Process active relocations.
765 REL_CACHE_TRAVERSE(&ofl
->ofl_actrels
, idx
, rcbp
, arsp
) {
769 const char *ifl_name
;
776 * If the section this relocation is against has been discarded
777 * (-zignore), then discard (skip) the relocation itself.
779 if ((arsp
->rel_isdesc
->is_flags
& FLG_IS_DISCARD
) &&
780 ((arsp
->rel_flags
& (FLG_REL_GOT
| FLG_REL_BSS
|
781 FLG_REL_PLT
| FLG_REL_NOINFO
)) == 0)) {
782 DBG_CALL(Dbg_reloc_discard(ofl
->ofl_lml
, M_MACH
, arsp
));
787 * We determine what the 'got reference' model (if required)
788 * is at this point. This needs to be done before tls_fixup()
789 * since it may 'transition' our instructions.
791 * The got table entries have already been assigned,
792 * and we bind to those initial entries.
794 if (arsp
->rel_flags
& FLG_REL_DTLS
)
795 gref
= GOT_REF_TLSGD
;
796 else if (arsp
->rel_flags
& FLG_REL_MTLS
)
797 gref
= GOT_REF_TLSLD
;
798 else if (arsp
->rel_flags
& FLG_REL_STLS
)
799 gref
= GOT_REF_TLSIE
;
801 gref
= GOT_REF_GENERIC
;
804 * Perform any required TLS fixups.
806 if (arsp
->rel_flags
& FLG_REL_TLSFIX
) {
809 if ((ret
= tls_fixups(ofl
, arsp
)) == FIX_ERROR
)
816 * If this is a relocation against a move table, or
817 * expanded move table, adjust the relocation entries.
819 if (RELAUX_GET_MOVE(arsp
))
820 ld_adj_movereloc(ofl
, arsp
);
823 refaddr
= arsp
->rel_roffset
+
824 (Off
)_elf_getxoff(arsp
->rel_isdesc
->is_indata
);
826 if ((arsp
->rel_flags
& FLG_REL_CLVAL
) ||
827 (arsp
->rel_flags
& FLG_REL_GOTCL
))
829 else if (ELF_ST_TYPE(sdp
->sd_sym
->st_info
) == STT_SECTION
) {
833 * The value for a symbol pointing to a SECTION
834 * is based off of that sections position.
836 if ((sdp
->sd_isc
->is_flags
& FLG_IS_RELUPD
) &&
838 (sym
= ld_am_I_partial(arsp
, arsp
->rel_raddend
))) {
840 * The symbol was moved, so adjust the value
841 * relative to the new section.
843 value
= sym
->sd_sym
->st_value
;
847 * The original raddend covers the displacement
848 * from the section start to the desired
849 * address. The value computed above gets us
850 * from the section start to the start of the
851 * symbol range. Adjust the old raddend to
852 * remove the offset from section start to
853 * symbol start, leaving the displacement
854 * within the range of the symbol.
856 arsp
->rel_raddend
-= sym
->sd_osym
->st_value
;
858 value
= _elf_getxoff(sdp
->sd_isc
->is_indata
);
859 if (sdp
->sd_isc
->is_shdr
->sh_flags
& SHF_ALLOC
)
860 value
+= sdp
->sd_isc
->is_osdesc
->
863 if (sdp
->sd_isc
->is_shdr
->sh_flags
& SHF_TLS
)
864 value
-= ofl
->ofl_tlsphdr
->p_vaddr
;
866 } else if (IS_SIZE(arsp
->rel_rtype
)) {
868 * Size relocations require the symbols size.
870 value
= sdp
->sd_sym
->st_size
;
872 } else if ((sdp
->sd_flags
& FLG_SY_CAP
) &&
873 sdp
->sd_aux
&& sdp
->sd_aux
->sa_PLTndx
) {
875 * If relocation is against a capabilities symbol, we
876 * need to jump to an associated PLT, so that at runtime
877 * ld.so.1 is involved to determine the best binding
878 * choice. Otherwise, the value is the symbols value.
880 value
= ld_calc_plt_addr(sdp
, ofl
);
882 value
= sdp
->sd_sym
->st_value
;
885 * Relocation against the GLOBAL_OFFSET_TABLE.
887 if ((arsp
->rel_flags
& FLG_REL_GOT
) &&
888 !ld_reloc_set_aux_osdesc(ofl
, arsp
, ofl
->ofl_osgot
))
890 osp
= RELAUX_GET_OSDESC(arsp
);
893 * If loadable and not producing a relocatable object add the
894 * sections virtual address to the reference address.
896 if ((arsp
->rel_flags
& FLG_REL_LOAD
) &&
897 ((flags
& FLG_OF_RELOBJ
) == 0))
898 refaddr
+= arsp
->rel_isdesc
->is_osdesc
->
902 * If this entry has a PLT assigned to it, its value is actually
903 * the address of the PLT (and not the address of the function).
905 if (IS_PLT(arsp
->rel_rtype
)) {
906 if (sdp
->sd_aux
&& sdp
->sd_aux
->sa_PLTndx
)
907 value
= ld_calc_plt_addr(sdp
, ofl
);
911 * Add relocations addend to value. Add extra
912 * relocation addend if needed.
914 * Note: For GOT relative relocations on amd64 we discard the
915 * addend. It was relevant to the reference - not to the
916 * data item being referenced (ie: that -4 thing).
918 if ((arsp
->rel_flags
& FLG_REL_GOT
) == 0)
919 value
+= arsp
->rel_raddend
;
922 * Determine whether the value needs further adjustment. Filter
923 * through the attributes of the relocation to determine what
924 * adjustment is required. Note, many of the following cases
925 * are only applicable when a .got is present. As a .got is
926 * not generated when a relocatable object is being built,
927 * any adjustments that require a .got need to be skipped.
929 if ((arsp
->rel_flags
& FLG_REL_GOT
) &&
930 ((flags
& FLG_OF_RELOBJ
) == 0)) {
937 * Perform relocation against GOT table. Since this
938 * doesn't fit exactly into a relocation we place the
939 * appropriate byte in the GOT directly
941 * Calculate offset into GOT at which to apply
944 gnp
= ld_find_got_ndx(sdp
->sd_GOTndxs
, gref
, ofl
, arsp
);
947 if (arsp
->rel_rtype
== R_AMD64_DTPOFF64
)
948 gotndx
= gnp
->gn_gotndx
+ 1;
950 gotndx
= gnp
->gn_gotndx
;
952 R1addr
= (Xword
)(gotndx
* M_GOT_ENTSIZE
);
955 * Add the GOTs data's offset.
957 R2addr
= R1addr
+ (uintptr_t)osp
->os_outdata
->d_buf
;
959 DBG_CALL(Dbg_reloc_doact(ofl
->ofl_lml
, ELF_DBG_LD_ACT
,
960 M_MACH
, SHT_RELA
, arsp
, R1addr
, value
,
966 if (ofl
->ofl_flags1
& FLG_OF1_ENCDIFF
)
967 *(Xword
*)R2addr
= ld_bswap_Xword(value
);
969 *(Xword
*)R2addr
= value
;
972 } else if (IS_GOT_BASED(arsp
->rel_rtype
) &&
973 ((flags
& FLG_OF_RELOBJ
) == 0)) {
974 value
-= ofl
->ofl_osgot
->os_shdr
->sh_addr
;
976 } else if (IS_GOTPCREL(arsp
->rel_rtype
) &&
977 ((flags
& FLG_OF_RELOBJ
) == 0)) {
984 gnp
= ld_find_got_ndx(sdp
->sd_GOTndxs
, gref
, ofl
, arsp
);
986 value
= (Xword
)(ofl
->ofl_osgot
->os_shdr
-> sh_addr
) +
987 ((Xword
)gnp
->gn_gotndx
* M_GOT_ENTSIZE
) +
988 arsp
->rel_raddend
- refaddr
;
990 } else if (IS_GOT_PC(arsp
->rel_rtype
) &&
991 ((flags
& FLG_OF_RELOBJ
) == 0)) {
992 value
= (Xword
)(ofl
->ofl_osgot
->os_shdr
->
993 sh_addr
) - refaddr
+ arsp
->rel_raddend
;
995 } else if ((IS_PC_RELATIVE(arsp
->rel_rtype
)) &&
996 (((flags
& FLG_OF_RELOBJ
) == 0) ||
997 (osp
== sdp
->sd_isc
->is_osdesc
))) {
1000 } else if (IS_TLS_INS(arsp
->rel_rtype
) &&
1001 IS_GOT_RELATIVE(arsp
->rel_rtype
) &&
1002 ((flags
& FLG_OF_RELOBJ
) == 0)) {
1005 gnp
= ld_find_got_ndx(sdp
->sd_GOTndxs
, gref
, ofl
, arsp
);
1007 value
= (Xword
)gnp
->gn_gotndx
* M_GOT_ENTSIZE
;
1009 } else if (IS_GOT_RELATIVE(arsp
->rel_rtype
) &&
1010 ((flags
& FLG_OF_RELOBJ
) == 0)) {
1013 gnp
= ld_find_got_ndx(sdp
->sd_GOTndxs
, gref
, ofl
, arsp
);
1015 value
= (Xword
)gnp
->gn_gotndx
* M_GOT_ENTSIZE
;
1017 } else if ((arsp
->rel_flags
& FLG_REL_STLS
) &&
1018 ((flags
& FLG_OF_RELOBJ
) == 0)) {
1022 * This is the LE TLS reference model. Static
1023 * offset is hard-coded.
1025 tlsstatsize
= S_ROUND(ofl
->ofl_tlsphdr
->p_memsz
,
1027 value
= tlsstatsize
- value
;
1030 * Since this code is fixed up, it assumes a negative
1031 * offset that can be added to the thread pointer.
1033 if (arsp
->rel_rtype
== R_AMD64_TPOFF32
)
1037 if (arsp
->rel_isdesc
->is_file
)
1038 ifl_name
= arsp
->rel_isdesc
->is_file
->ifl_name
;
1040 ifl_name
= MSG_INTL(MSG_STR_NULL
);
1043 * Make sure we have data to relocate. Compiler and assembler
1044 * developers have been known to generate relocations against
1045 * invalid sections (normally .bss), so for their benefit give
1046 * them sufficient information to help analyze the problem.
1047 * End users should never see this.
1049 if (arsp
->rel_isdesc
->is_indata
->d_buf
== 0) {
1050 Conv_inv_buf_t inv_buf
;
1052 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_REL_EMPTYSEC
),
1053 conv_reloc_amd64_type(arsp
->rel_rtype
, 0, &inv_buf
),
1054 ifl_name
, ld_reloc_sym_name(arsp
),
1055 EC_WORD(arsp
->rel_isdesc
->is_scnndx
),
1056 arsp
->rel_isdesc
->is_name
);
1061 * Get the address of the data item we need to modify.
1063 addr
= (uchar_t
*)((uintptr_t)arsp
->rel_roffset
+
1064 (uintptr_t)_elf_getxoff(arsp
->rel_isdesc
->is_indata
));
1066 DBG_CALL(Dbg_reloc_doact(ofl
->ofl_lml
, ELF_DBG_LD_ACT
,
1067 M_MACH
, SHT_RELA
, arsp
, EC_NATPTR(addr
), value
,
1068 ld_reloc_sym_name
));
1069 addr
+= (uintptr_t)osp
->os_outdata
->d_buf
;
1071 if ((((uintptr_t)addr
- (uintptr_t)ofl
->ofl_nehdr
) >
1072 ofl
->ofl_size
) || (arsp
->rel_roffset
>
1073 osp
->os_shdr
->sh_size
)) {
1075 Conv_inv_buf_t inv_buf
;
1077 if (((uintptr_t)addr
- (uintptr_t)ofl
->ofl_nehdr
) >
1081 class = ERR_WARNING
;
1083 ld_eprintf(ofl
, class, MSG_INTL(MSG_REL_INVALOFFSET
),
1084 conv_reloc_amd64_type(arsp
->rel_rtype
, 0, &inv_buf
),
1085 ifl_name
, EC_WORD(arsp
->rel_isdesc
->is_scnndx
),
1086 arsp
->rel_isdesc
->is_name
, ld_reloc_sym_name(arsp
),
1087 EC_ADDR((uintptr_t)addr
-
1088 (uintptr_t)ofl
->ofl_nehdr
));
1090 if (class == ERR_FATAL
) {
1091 return_code
= S_ERROR
;
1097 * The relocation is additive. Ignore the previous symbol
1098 * value if this local partial symbol is expanded.
1104 * If '-z noreloc' is specified - skip the do_reloc_ld stage.
1106 if (OFL_DO_RELOC(ofl
)) {
1108 * If this is a PROGBITS section and the running linker
1109 * has a different byte order than the target host,
1110 * tell do_reloc_ld() to swap bytes.
1112 if (do_reloc_ld(arsp
, addr
, &value
, ld_reloc_sym_name
,
1113 ifl_name
, OFL_SWAP_RELOC_DATA(ofl
, arsp
),
1114 ofl
->ofl_lml
) == 0) {
1115 ofl
->ofl_flags
|= FLG_OF_FATAL
;
1116 return_code
= S_ERROR
;
1120 return (return_code
);
1124 ld_add_outrel(Word flags
, Rel_desc
*rsp
, Ofl_desc
*ofl
)
1127 Sym_desc
*sdp
= rsp
->rel_sym
;
1130 * Static executables *do not* want any relocations against them.
1131 * Since our engine still creates relocations against a WEAK UNDEFINED
1132 * symbol in a static executable, it's best to disable them here
1133 * instead of through out the relocation code.
1135 if (OFL_IS_STATIC_EXEC(ofl
))
1139 * If we are adding a output relocation against a section
1140 * symbol (non-RELATIVE) then mark that section. These sections
1141 * will be added to the .dynsym symbol table.
1143 if (sdp
&& (rsp
->rel_rtype
!= M_R_RELATIVE
) &&
1144 ((flags
& FLG_REL_SCNNDX
) ||
1145 (ELF_ST_TYPE(sdp
->sd_sym
->st_info
) == STT_SECTION
))) {
1148 * If this is a COMMON symbol - no output section
1149 * exists yet - (it's created as part of sym_validate()).
1150 * So - we mark here that when it's created it should
1151 * be tagged with the FLG_OS_OUTREL flag.
1153 if ((sdp
->sd_flags
& FLG_SY_SPECSEC
) &&
1154 (sdp
->sd_sym
->st_shndx
== SHN_COMMON
)) {
1155 if (ELF_ST_TYPE(sdp
->sd_sym
->st_info
) != STT_TLS
)
1156 ofl
->ofl_flags1
|= FLG_OF1_BSSOREL
;
1158 ofl
->ofl_flags1
|= FLG_OF1_TLSOREL
;
1161 Is_desc
*isp
= sdp
->sd_isc
;
1163 if (isp
&& ((osp
= isp
->is_osdesc
) != NULL
) &&
1164 ((osp
->os_flags
& FLG_OS_OUTREL
) == 0)) {
1165 ofl
->ofl_dynshdrcnt
++;
1166 osp
->os_flags
|= FLG_OS_OUTREL
;
1171 /* Enter it into the output relocation cache */
1172 if ((orsp
= ld_reloc_enter(ofl
, &ofl
->ofl_outrels
, rsp
, flags
)) == NULL
)
1175 if (flags
& FLG_REL_GOT
)
1176 ofl
->ofl_relocgotsz
+= (Xword
)sizeof (Rela
);
1177 else if (flags
& FLG_REL_PLT
)
1178 ofl
->ofl_relocpltsz
+= (Xword
)sizeof (Rela
);
1179 else if (flags
& FLG_REL_BSS
)
1180 ofl
->ofl_relocbsssz
+= (Xword
)sizeof (Rela
);
1181 else if (flags
& FLG_REL_NOINFO
)
1182 ofl
->ofl_relocrelsz
+= (Xword
)sizeof (Rela
);
1184 RELAUX_GET_OSDESC(orsp
)->os_szoutrels
+= (Xword
)sizeof (Rela
);
1186 if (orsp
->rel_rtype
== M_R_RELATIVE
)
1187 ofl
->ofl_relocrelcnt
++;
1190 * We don't perform sorting on PLT relocations because
1191 * they have already been assigned a PLT index and if we
1192 * were to sort them we would have to re-assign the plt indexes.
1194 if (!(flags
& FLG_REL_PLT
))
1195 ofl
->ofl_reloccnt
++;
1198 * Insure a GLOBAL_OFFSET_TABLE is generated if required.
1200 if (IS_GOT_REQUIRED(orsp
->rel_rtype
))
1201 ofl
->ofl_flags
|= FLG_OF_BLDGOT
;
1204 * Identify and possibly warn of a displacement relocation.
1206 if (orsp
->rel_flags
& FLG_REL_DISP
) {
1207 ofl
->ofl_dtflags_1
|= DF_1_DISPRELPND
;
1209 if (ofl
->ofl_flags
& FLG_OF_VERBOSE
)
1210 ld_disp_errmsg(MSG_INTL(MSG_REL_DISPREL4
), orsp
, ofl
);
1212 DBG_CALL(Dbg_reloc_ors_entry(ofl
->ofl_lml
, ELF_DBG_LD
, SHT_RELA
,
1218 * process relocation for a LOCAL symbol
1221 ld_reloc_local(Rel_desc
* rsp
, Ofl_desc
* ofl
)
1223 ofl_flag_t flags
= ofl
->ofl_flags
;
1224 Sym_desc
*sdp
= rsp
->rel_sym
;
1225 Word shndx
= sdp
->sd_sym
->st_shndx
;
1226 Word ortype
= rsp
->rel_rtype
;
1229 * if ((shared object) and (not pc relative relocation) and
1230 * (not against ABS symbol))
1232 * build R_AMD64_RELATIVE
1235 if ((flags
& FLG_OF_SHAROBJ
) && (rsp
->rel_flags
& FLG_REL_LOAD
) &&
1236 !(IS_PC_RELATIVE(rsp
->rel_rtype
)) && !(IS_SIZE(rsp
->rel_rtype
)) &&
1237 !(IS_GOT_BASED(rsp
->rel_rtype
)) &&
1238 !(rsp
->rel_isdesc
!= NULL
&&
1239 (rsp
->rel_isdesc
->is_shdr
->sh_type
== SHT_SUNW_dof
)) &&
1240 (((sdp
->sd_flags
& FLG_SY_SPECSEC
) == 0) ||
1241 (shndx
!= SHN_ABS
) || (sdp
->sd_aux
&& sdp
->sd_aux
->sa_symspec
))) {
1244 * R_AMD64_RELATIVE updates a 64bit address, if this
1245 * relocation isn't a 64bit binding then we can not
1246 * simplify it to a RELATIVE relocation.
1248 if (reloc_table
[ortype
].re_fsize
!= sizeof (Addr
)) {
1249 return (ld_add_outrel(0, rsp
, ofl
));
1252 rsp
->rel_rtype
= R_AMD64_RELATIVE
;
1253 if (ld_add_outrel(FLG_REL_ADVAL
, rsp
, ofl
) == S_ERROR
)
1255 rsp
->rel_rtype
= ortype
;
1260 * If the relocation is against a 'non-allocatable' section
1261 * and we can not resolve it now - then give a warning
1264 * We can not resolve the symbol if either:
1266 * b) it's defined in a shared library and a
1267 * COPY relocation hasn't moved it to the executable
1269 * Note: because we process all of the relocations against the
1270 * text segment before any others - we know whether
1271 * or not a copy relocation will be generated before
1272 * we get here (see reloc_init()->reloc_segments()).
1274 if (!(rsp
->rel_flags
& FLG_REL_LOAD
) &&
1275 ((shndx
== SHN_UNDEF
) ||
1276 ((sdp
->sd_ref
== REF_DYN_NEED
) &&
1277 ((sdp
->sd_flags
& FLG_SY_MVTOCOMM
) == 0)))) {
1278 Conv_inv_buf_t inv_buf
;
1279 Os_desc
*osp
= RELAUX_GET_OSDESC(rsp
);
1282 * If the relocation is against a SHT_SUNW_ANNOTATE
1283 * section - then silently ignore that the relocation
1284 * can not be resolved.
1286 if (osp
&& (osp
->os_shdr
->sh_type
== SHT_SUNW_ANNOTATE
))
1288 ld_eprintf(ofl
, ERR_WARNING
, MSG_INTL(MSG_REL_EXTERNSYM
),
1289 conv_reloc_amd64_type(rsp
->rel_rtype
, 0, &inv_buf
),
1290 rsp
->rel_isdesc
->is_file
->ifl_name
,
1291 ld_reloc_sym_name(rsp
), osp
->os_name
);
1296 * Perform relocation.
1298 return (ld_add_actrel(NULL
, rsp
, ofl
));
1303 ld_reloc_TLS(Boolean local
, Rel_desc
* rsp
, Ofl_desc
* ofl
)
1305 Word rtype
= rsp
->rel_rtype
;
1306 Sym_desc
*sdp
= rsp
->rel_sym
;
1307 ofl_flag_t flags
= ofl
->ofl_flags
;
1311 * If we're building an executable - use either the IE or LE access
1312 * model. If we're building a shared object process any IE model.
1314 if ((flags
& FLG_OF_EXEC
) || (IS_TLS_IE(rtype
))) {
1316 * Set the DF_STATIC_TLS flag.
1318 ofl
->ofl_dtflags
|= DF_STATIC_TLS
;
1320 if (!local
|| ((flags
& FLG_OF_EXEC
) == 0)) {
1322 * Assign a GOT entry for static TLS references.
1324 if ((gnp
= ld_find_got_ndx(sdp
->sd_GOTndxs
,
1325 GOT_REF_TLSIE
, ofl
, rsp
)) == NULL
) {
1327 if (ld_assign_got_TLS(local
, rsp
, ofl
, sdp
,
1328 gnp
, GOT_REF_TLSIE
, FLG_REL_STLS
,
1329 rtype
, R_AMD64_TPOFF64
, 0) == S_ERROR
)
1336 if (IS_TLS_IE(rtype
))
1337 return (ld_add_actrel(FLG_REL_STLS
, rsp
, ofl
));
1340 * Fixups are required for other executable models.
1342 return (ld_add_actrel((FLG_REL_TLSFIX
| FLG_REL_STLS
),
1349 if (IS_TLS_LE(rtype
))
1350 return (ld_add_actrel(FLG_REL_STLS
, rsp
, ofl
));
1352 return (ld_add_actrel((FLG_REL_TLSFIX
| FLG_REL_STLS
),
1357 * Building a shared object.
1359 * Assign a GOT entry for a dynamic TLS reference.
1361 if (IS_TLS_LD(rtype
) && ((gnp
= ld_find_got_ndx(sdp
->sd_GOTndxs
,
1362 GOT_REF_TLSLD
, ofl
, rsp
)) == NULL
)) {
1364 if (ld_assign_got_TLS(local
, rsp
, ofl
, sdp
, gnp
, GOT_REF_TLSLD
,
1365 FLG_REL_MTLS
, rtype
, R_AMD64_DTPMOD64
, NULL
) == S_ERROR
)
1368 } else if (IS_TLS_GD(rtype
) &&
1369 ((gnp
= ld_find_got_ndx(sdp
->sd_GOTndxs
, GOT_REF_TLSGD
,
1370 ofl
, rsp
)) == NULL
)) {
1372 if (ld_assign_got_TLS(local
, rsp
, ofl
, sdp
, gnp
, GOT_REF_TLSGD
,
1373 FLG_REL_DTLS
, rtype
, R_AMD64_DTPMOD64
,
1374 R_AMD64_DTPOFF64
) == S_ERROR
)
1378 if (IS_TLS_LD(rtype
))
1379 return (ld_add_actrel(FLG_REL_MTLS
, rsp
, ofl
));
1381 return (ld_add_actrel(FLG_REL_DTLS
, rsp
, ofl
));
1386 ld_assign_got_ndx(Alist
**alpp
, Gotndx
*pgnp
, Gotref gref
, Ofl_desc
*ofl
,
1387 Rel_desc
*rsp
, Sym_desc
*sdp
)
1394 raddend
= rsp
->rel_raddend
;
1395 if (pgnp
&& (pgnp
->gn_addend
== raddend
) && (pgnp
->gn_gotref
== gref
))
1398 if ((gref
== GOT_REF_TLSGD
) || (gref
== GOT_REF_TLSLD
))
1403 gn
.gn_addend
= raddend
;
1404 gn
.gn_gotndx
= ofl
->ofl_gotcnt
;
1405 gn
.gn_gotref
= gref
;
1407 ofl
->ofl_gotcnt
+= gotents
;
1409 if (gref
== GOT_REF_TLSLD
) {
1410 if (ofl
->ofl_tlsldgotndx
== NULL
) {
1411 if ((gnp
= libld_malloc(sizeof (Gotndx
))) == NULL
)
1413 (void) memcpy(gnp
, &gn
, sizeof (Gotndx
));
1414 ofl
->ofl_tlsldgotndx
= gnp
;
1420 for (ALIST_TRAVERSE(*alpp
, idx
, gnp
)) {
1421 if (gnp
->gn_addend
> raddend
)
1426 * GOT indexes are maintained on an Alist, where there is typically
1427 * only one index. The usage of this list is to scan the list to find
1428 * an index, and then apply that index immediately to a relocation.
1429 * Thus there are no external references to these GOT index structures
1430 * that can be compromised by the Alist being reallocated.
1432 if (alist_insert(alpp
, &gn
, sizeof (Gotndx
),
1433 AL_CNT_SDP_GOT
, idx
) == NULL
)
1440 ld_assign_plt_ndx(Sym_desc
* sdp
, Ofl_desc
*ofl
)
1442 sdp
->sd_aux
->sa_PLTndx
= 1 + ofl
->ofl_pltcnt
++;
1443 sdp
->sd_aux
->sa_PLTGOTndx
= ofl
->ofl_gotcnt
++;
1444 ofl
->ofl_flags
|= FLG_OF_BLDGOT
;
1447 static uchar_t plt0_template
[M_PLT_ENTSIZE
] = {
1448 /* 0x00 PUSHQ GOT+8(%rip) */ 0xff, 0x35, 0x00, 0x00, 0x00, 0x00,
1449 /* 0x06 JMP *GOT+16(%rip) */ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
1450 /* 0x0c NOP */ 0x90,
1451 /* 0x0d NOP */ 0x90,
1452 /* 0x0e NOP */ 0x90,
1457 * Initializes .got[0] with the _DYNAMIC symbol value.
1460 ld_fillin_gotplt(Ofl_desc
*ofl
)
1462 int bswap
= (ofl
->ofl_flags1
& FLG_OF1_ENCDIFF
) != 0;
1464 if (ofl
->ofl_osgot
) {
1467 if ((sdp
= ld_sym_find(MSG_ORIG(MSG_SYM_DYNAMIC_U
),
1468 SYM_NOHASH
, NULL
, ofl
)) != NULL
) {
1471 genptr
= ((uchar_t
*)ofl
->ofl_osgot
->os_outdata
->d_buf
+
1472 (M_GOT_XDYNAMIC
* M_GOT_ENTSIZE
));
1474 *(Xword
*)genptr
= sdp
->sd_sym
->st_value
;
1479 ld_bswap_Xword(*(Xword
*)genptr
);
1484 * Fill in the reserved slot in the procedure linkage table the first
1486 * 0x00 PUSHQ GOT+8(%rip) # GOT[1]
1487 * 0x06 JMP *GOT+16(%rip) # GOT[2]
1493 if ((ofl
->ofl_flags
& FLG_OF_DYNAMIC
) && ofl
->ofl_osplt
) {
1497 pltent
= (uchar_t
*)ofl
->ofl_osplt
->os_outdata
->d_buf
;
1498 bcopy(plt0_template
, pltent
, sizeof (plt0_template
));
1501 * If '-z noreloc' is specified - skip the do_reloc_ld
1504 if (!OFL_DO_RELOC(ofl
))
1509 * PUSHQ GOT + 8(%rip)
1511 * Note: 0x06 below represents the offset to the
1512 * next instruction - which is what %rip will
1515 val1
= (ofl
->ofl_osgot
->os_shdr
->sh_addr
) +
1516 (M_GOT_XLINKMAP
* M_GOT_ENTSIZE
) -
1517 ofl
->ofl_osplt
->os_shdr
->sh_addr
- 0x06;
1519 if (do_reloc_ld(&rdesc_r_amd64_gotpcrel
, &pltent
[0x02],
1520 &val1
, syn_rdesc_sym_name
, MSG_ORIG(MSG_SPECFIL_PLTENT
),
1521 bswap
, ofl
->ofl_lml
) == 0) {
1522 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_PLT_PLT0FAIL
));
1530 val1
= (ofl
->ofl_osgot
->os_shdr
->sh_addr
) +
1531 (M_GOT_XRTLD
* M_GOT_ENTSIZE
) -
1532 ofl
->ofl_osplt
->os_shdr
->sh_addr
- 0x0c;
1534 if (do_reloc_ld(&rdesc_r_amd64_gotpcrel
, &pltent
[0x08],
1535 &val1
, syn_rdesc_sym_name
, MSG_ORIG(MSG_SPECFIL_PLTENT
),
1536 bswap
, ofl
->ofl_lml
) == 0) {
1537 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_PLT_PLT0FAIL
));
1548 * Template for generating "void (*)(void)" function
1550 static const uchar_t nullfunc_tmpl
[] = { /* amd64 */
1551 /* 0x00 */ 0x55, /* pushq %rbp */
1552 /* 0x01 */ 0x48, 0x8b, 0xec, /* movq %rsp,%rbp */
1553 /* 0x04 */ 0x48, 0x8b, 0xe5, /* movq %rbp,%rsp */
1554 /* 0x07 */ 0x5d, /* popq %rbp */
1555 /* 0x08 */ 0xc3 /* ret */
1560 * Function used to provide fill padding in SHF_EXECINSTR sections
1564 * base - base address of section being filled
1565 * offset - starting offset for fill within memory referenced by base
1566 * cnt - # bytes to be filled
1569 * The fill has been completed.
1572 execfill(void *base
, off_t off
, size_t cnt
)
1575 * 0x90 is an X86 NOP instruction in both 32 and 64-bit worlds.
1576 * There are no alignment constraints.
1578 (void) memset(off
+ (char *)base
, 0x90, cnt
);
1583 * Return the ld_targ definition for this target.
1586 ld_targ_init_x86(void)
1588 static const Target _ld_targ
= {
1590 M_MACH
, /* m_mach */
1591 M_MACHPLUS
, /* m_machplus */
1592 M_FLAGSPLUS
, /* m_flagsplus */
1593 M_CLASS
, /* m_class */
1594 M_DATA
, /* m_data */
1596 M_SEGM_ALIGN
, /* m_segm_align */
1597 M_SEGM_ORIGIN
, /* m_segm_origin */
1598 M_SEGM_AORIGIN
, /* m_segm_aorigin */
1599 M_DATASEG_PERM
, /* m_dataseg_perm */
1600 M_STACK_PERM
, /* m_stack_perm */
1601 M_WORD_ALIGN
, /* m_word_align */
1602 MSG_ORIG(MSG_PTH_RTLD_AMD64
), /* m_def_interp */
1604 /* Relocation type codes */
1605 M_R_ARRAYADDR
, /* m_r_arrayaddr */
1606 M_R_COPY
, /* m_r_copy */
1607 M_R_GLOB_DAT
, /* m_r_glob_dat */
1608 M_R_JMP_SLOT
, /* m_r_jmp_slot */
1609 M_R_NUM
, /* m_r_num */
1610 M_R_NONE
, /* m_r_none */
1611 M_R_RELATIVE
, /* m_r_relative */
1612 M_R_REGISTER
, /* m_r_register */
1614 /* Relocation related constants */
1615 M_REL_DT_COUNT
, /* m_rel_dt_count */
1616 M_REL_DT_ENT
, /* m_rel_dt_ent */
1617 M_REL_DT_SIZE
, /* m_rel_dt_size */
1618 M_REL_DT_TYPE
, /* m_rel_dt_type */
1619 M_REL_SHT_TYPE
, /* m_rel_sht_type */
1621 /* GOT related constants */
1622 M_GOT_ENTSIZE
, /* m_got_entsize */
1623 M_GOT_XNumber
, /* m_got_xnumber */
1625 /* PLT related constants */
1626 M_PLT_ALIGN
, /* m_plt_align */
1627 M_PLT_ENTSIZE
, /* m_plt_entsize */
1628 M_PLT_RESERVSZ
, /* m_plt_reservsz */
1629 M_PLT_SHF_FLAGS
, /* m_plt_shf_flags */
1631 /* Section type of .eh_frame/.eh_frame_hdr sections */
1632 SHT_AMD64_UNWIND
, /* m_sht_unwind */
1634 M_DT_REGISTER
, /* m_dt_register */
1636 { /* Target_machid */
1637 M_ID_ARRAY
, /* id_array */
1638 M_ID_BSS
, /* id_bss */
1639 M_ID_CAP
, /* id_cap */
1640 M_ID_CAPINFO
, /* id_capinfo */
1641 M_ID_CAPCHAIN
, /* id_capchain */
1642 M_ID_DATA
, /* id_data */
1643 M_ID_DYNAMIC
, /* id_dynamic */
1644 M_ID_DYNSORT
, /* id_dynsort */
1645 M_ID_DYNSTR
, /* id_dynstr */
1646 M_ID_DYNSYM
, /* id_dynsym */
1647 M_ID_DYNSYM_NDX
, /* id_dynsym_ndx */
1648 M_ID_GOT
, /* id_got */
1649 M_ID_UNKNOWN
, /* id_gotdata (unused) */
1650 M_ID_HASH
, /* id_hash */
1651 M_ID_INTERP
, /* id_interp */
1652 M_ID_LBSS
, /* id_lbss */
1653 M_ID_LDYNSYM
, /* id_ldynsym */
1654 M_ID_NOTE
, /* id_note */
1655 M_ID_NULL
, /* id_null */
1656 M_ID_PLT
, /* id_plt */
1657 M_ID_REL
, /* id_rel */
1658 M_ID_STRTAB
, /* id_strtab */
1659 M_ID_SYMINFO
, /* id_syminfo */
1660 M_ID_SYMTAB
, /* id_symtab */
1661 M_ID_SYMTAB_NDX
, /* id_symtab_ndx */
1662 M_ID_TEXT
, /* id_text */
1663 M_ID_TLS
, /* id_tls */
1664 M_ID_TLSBSS
, /* id_tlsbss */
1665 M_ID_UNKNOWN
, /* id_unknown */
1666 M_ID_UNWIND
, /* id_unwind */
1667 M_ID_UNWINDHDR
, /* id_unwindhdr */
1668 M_ID_USER
, /* id_user */
1669 M_ID_VERSION
, /* id_version */
1671 { /* Target_nullfunc */
1672 nullfunc_tmpl
, /* nf_template */
1673 sizeof (nullfunc_tmpl
), /* nf_size */
1675 { /* Target_fillfunc */
1676 execfill
/* ff_execfill */
1678 { /* Target_machrel */
1681 ld_init_rel
, /* mr_init_rel */
1682 ld_mach_eflags
, /* mr_mach_eflags */
1683 ld_mach_make_dynamic
, /* mr_mach_make_dynamic */
1684 ld_mach_update_odynamic
, /* mr_mach_update_odynamic */
1685 ld_calc_plt_addr
, /* mr_calc_plt_addr */
1686 ld_perform_outreloc
, /* mr_perform_outreloc */
1687 ld_do_activerelocs
, /* mr_do_activerelocs */
1688 ld_add_outrel
, /* mr_add_outrel */
1689 NULL
, /* mr_reloc_register */
1690 ld_reloc_local
, /* mr_reloc_local */
1691 NULL
, /* mr_reloc_GOTOP */
1692 ld_reloc_TLS
, /* mr_reloc_TLS */
1693 NULL
, /* mr_assign_got */
1694 ld_find_got_ndx
, /* mr_find_got_ndx */
1695 ld_calc_got_offset
, /* mr_calc_got_offset */
1696 ld_assign_got_ndx
, /* mr_assign_got_ndx */
1697 ld_assign_plt_ndx
, /* mr_assign_plt_ndx */
1698 NULL
, /* mr_allocate_got */
1699 ld_fillin_gotplt
, /* mr_fillin_gotplt */
1701 { /* Target_machsym */
1702 NULL
, /* ms_reg_check */
1703 NULL
, /* ms_mach_sym_typecheck */
1704 NULL
, /* ms_is_regsym */
1705 NULL
, /* ms_reg_find */
1706 NULL
/* ms_reg_enter */