[ARM] Implement PLT for FDPIC.
FDPIC requires special PLT entries, defined in this patch. Note that lazy binding is not supported because of a race condition for lack of an atomic 64-bits load instruction. 2018-04-25 Christophe Lyon <christophe.lyon@st.com> Mickaël Guêné <mickael.guene@st.com> bfd/ * elf32-arm.c (elf32_arm_fdpic_plt_entry): New. (elf32_arm_create_dynamic_sections): Handle FDPIC. (elf32_arm_allocate_plt_entry): Likewise. (elf32_arm_populate_plt_entry): Likewise. (elf32_arm_output_plt_map_1): Likewise.
This commit is contained in:
parent
e8b09b8710
commit
7801f98f84
|
@ -1,3 +1,12 @@
|
|||
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
|
||||
Mickaël Guêné <mickael.guene@st.com>
|
||||
|
||||
* elf32-arm.c (elf32_arm_fdpic_plt_entry): New.
|
||||
(elf32_arm_create_dynamic_sections): Handle FDPIC.
|
||||
(elf32_arm_allocate_plt_entry): Likewise.
|
||||
(elf32_arm_populate_plt_entry): Likewise.
|
||||
(elf32_arm_output_plt_map_1): Likewise.
|
||||
|
||||
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
|
||||
Mickaël Guêné <mickael.guene@st.com>
|
||||
|
||||
|
|
152
bfd/elf32-arm.c
152
bfd/elf32-arm.c
|
@ -2229,6 +2229,22 @@ static const unsigned long dl_tlsdesc_lazy_trampoline [] =
|
|||
0x00000018, /* 4: .word _GLOBAL_OFFSET_TABLE_ - 2b - 8 */
|
||||
};
|
||||
|
||||
/* ARM FDPIC PLT entry. */
|
||||
/* The last 5 words contain PLT lazy fragment code and data. */
|
||||
static const bfd_vma elf32_arm_fdpic_plt_entry [] =
|
||||
{
|
||||
0xe59fc008, /* ldr r12, .L1 */
|
||||
0xe08cc009, /* add r12, r12, r9 */
|
||||
0xe59c9004, /* ldr r9, [r12, #4] */
|
||||
0xe59cf000, /* ldr pc, [r12] */
|
||||
0x00000000, /* L1. .word foo(GOTOFFFUNCDESC) */
|
||||
0x00000000, /* L1. .word foo(funcdesc_value_reloc_offset) */
|
||||
0xe51fc00c, /* ldr r12, [pc, #-12] */
|
||||
0xe92d1000, /* push {r12} */
|
||||
0xe599c004, /* ldr r12, [r9, #4] */
|
||||
0xe599f000, /* ldr pc, [r9] */
|
||||
};
|
||||
|
||||
#ifdef FOUR_WORD_PLT
|
||||
|
||||
/* The first entry in a procedure linkage table looks like
|
||||
|
@ -3856,6 +3872,14 @@ elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
|
|||
htab->obfd = saved_obfd;
|
||||
}
|
||||
|
||||
if (htab->fdpic_p) {
|
||||
htab->plt_header_size = 0;
|
||||
if (info->flags & DF_BIND_NOW)
|
||||
htab->plt_entry_size = 4 * (ARRAY_SIZE(elf32_arm_fdpic_plt_entry) - 5);
|
||||
else
|
||||
htab->plt_entry_size = 4 * ARRAY_SIZE(elf32_arm_fdpic_plt_entry);
|
||||
}
|
||||
|
||||
if (!htab->root.splt
|
||||
|| !htab->root.srelplt
|
||||
|| !htab->root.sdynbss
|
||||
|
@ -9392,8 +9416,22 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info,
|
|||
splt = htab->root.splt;
|
||||
sgotplt = htab->root.sgotplt;
|
||||
|
||||
/* Allocate room for an R_JUMP_SLOT relocation in .rel.plt. */
|
||||
elf32_arm_allocate_dynrelocs (info, htab->root.srelplt, 1);
|
||||
if (htab->fdpic_p)
|
||||
{
|
||||
/* Allocate room for R_ARM_FUNCDESC_VALUE. */
|
||||
/* For lazy binding, relocations will be put into .rel.plt, in
|
||||
.rel.got otherwise. */
|
||||
/* FIXME: today we don't support lazy binding so put it in .rel.got */
|
||||
if (info->flags & DF_BIND_NOW)
|
||||
elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
|
||||
else
|
||||
elf32_arm_allocate_dynrelocs (info, htab->root.srelplt, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate room for an R_JUMP_SLOT relocation in .rel.plt. */
|
||||
elf32_arm_allocate_dynrelocs (info, htab->root.srelplt, 1);
|
||||
}
|
||||
|
||||
/* If this is the first .plt entry, make room for the special
|
||||
first entry. */
|
||||
|
@ -9417,7 +9455,11 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info,
|
|||
arm_plt->got_offset = sgotplt->size;
|
||||
else
|
||||
arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc;
|
||||
sgotplt->size += 4;
|
||||
if (htab->fdpic_p)
|
||||
/* Function descriptor takes 64 bits in GOT. */
|
||||
sgotplt->size += 8;
|
||||
else
|
||||
sgotplt->size += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9526,7 +9568,11 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
|
|||
in all the symbols for which we are making plt entries.
|
||||
After the reserved .got.plt entries, all symbols appear in
|
||||
the same order as in .plt. */
|
||||
plt_index = (got_offset - got_header_size) / 4;
|
||||
if (htab->fdpic_p)
|
||||
/* Function descriptor takes 8 bytes. */
|
||||
plt_index = (got_offset - got_header_size) / 8;
|
||||
else
|
||||
plt_index = (got_offset - got_header_size) / 4;
|
||||
|
||||
/* Calculate the address of the GOT entry. */
|
||||
got_address = (sgot->output_section->vma
|
||||
|
@ -9634,6 +9680,42 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
|
|||
| (tail_displacement & 0x00ffffff),
|
||||
ptr + 12);
|
||||
}
|
||||
else if (htab->fdpic_p)
|
||||
{
|
||||
/* Fill-up Thumb stub if needed. */
|
||||
if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt))
|
||||
{
|
||||
put_thumb_insn (htab, output_bfd,
|
||||
elf32_arm_plt_thumb_stub[0], ptr - 4);
|
||||
put_thumb_insn (htab, output_bfd,
|
||||
elf32_arm_plt_thumb_stub[1], ptr - 2);
|
||||
}
|
||||
put_arm_insn(htab, output_bfd,
|
||||
elf32_arm_fdpic_plt_entry[0], ptr + 0);
|
||||
put_arm_insn(htab, output_bfd,
|
||||
elf32_arm_fdpic_plt_entry[1], ptr + 4);
|
||||
put_arm_insn(htab, output_bfd,
|
||||
elf32_arm_fdpic_plt_entry[2], ptr + 8);
|
||||
put_arm_insn(htab, output_bfd,
|
||||
elf32_arm_fdpic_plt_entry[3], ptr + 12);
|
||||
bfd_put_32 (output_bfd, got_offset, ptr + 16);
|
||||
|
||||
if (!(info->flags & DF_BIND_NOW))
|
||||
{
|
||||
/* funcdesc_value_reloc_offset. */
|
||||
bfd_put_32 (output_bfd,
|
||||
htab->root.srelplt->reloc_count * RELOC_SIZE (htab),
|
||||
ptr + 20);
|
||||
put_arm_insn(htab, output_bfd,
|
||||
elf32_arm_fdpic_plt_entry[6], ptr + 24);
|
||||
put_arm_insn(htab, output_bfd,
|
||||
elf32_arm_fdpic_plt_entry[7], ptr + 28);
|
||||
put_arm_insn(htab, output_bfd,
|
||||
elf32_arm_fdpic_plt_entry[8], ptr + 32);
|
||||
put_arm_insn(htab, output_bfd,
|
||||
elf32_arm_fdpic_plt_entry[9], ptr + 36);
|
||||
}
|
||||
}
|
||||
else if (using_thumb_only (htab))
|
||||
{
|
||||
/* PR ld/16017: Generate thumb only PLT entries. */
|
||||
|
@ -9744,22 +9826,61 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
|
|||
}
|
||||
else
|
||||
{
|
||||
rel.r_info = ELF32_R_INFO (dynindx, R_ARM_JUMP_SLOT);
|
||||
initial_got_entry = (splt->output_section->vma
|
||||
+ splt->output_offset);
|
||||
/* For FDPIC we will have to resolve a R_ARM_FUNCDESC_VALUE
|
||||
used by PLT entry. */
|
||||
if (htab->fdpic_p)
|
||||
{
|
||||
rel.r_info = ELF32_R_INFO (dynindx, R_ARM_FUNCDESC_VALUE);
|
||||
initial_got_entry = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rel.r_info = ELF32_R_INFO (dynindx, R_ARM_JUMP_SLOT);
|
||||
initial_got_entry = (splt->output_section->vma
|
||||
+ splt->output_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in the entry in the global offset table. */
|
||||
bfd_put_32 (output_bfd, initial_got_entry,
|
||||
sgot->contents + got_offset);
|
||||
|
||||
if (htab->fdpic_p && !(info->flags & DF_BIND_NOW))
|
||||
{
|
||||
/* Setup initial funcdesc value. */
|
||||
/* FIXME: we don't support lazy binding because there is a
|
||||
race condition between both words getting written and
|
||||
some other thread attempting to read them. The ARM
|
||||
architecture does not have an atomic 64 bit load/store
|
||||
instruction that could be used to prevent it; it is
|
||||
recommended that threaded FDPIC applications run with the
|
||||
LD_BIND_NOW environment variable set. */
|
||||
bfd_put_32(output_bfd, plt_address + 0x18,
|
||||
sgot->contents + got_offset);
|
||||
bfd_put_32(output_bfd, -1 /*TODO*/,
|
||||
sgot->contents + got_offset + 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (dynindx == -1)
|
||||
elf32_arm_add_dynreloc (output_bfd, info, srel, &rel);
|
||||
else
|
||||
{
|
||||
loc = srel->contents + plt_index * RELOC_SIZE (htab);
|
||||
SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
|
||||
if (htab->fdpic_p)
|
||||
{
|
||||
/* For FDPIC we put PLT relocationss into .rel.got when not
|
||||
lazy binding otherwise we put them in .rel.plt. For now,
|
||||
we don't support lazy binding so put it in .rel.got. */
|
||||
if (info->flags & DF_BIND_NOW)
|
||||
elf32_arm_add_dynreloc(output_bfd, info, htab->root.srelgot, &rel);
|
||||
else
|
||||
elf32_arm_add_dynreloc(output_bfd, info, htab->root.srelplt, &rel);
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = srel->contents + plt_index * RELOC_SIZE (htab);
|
||||
SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -17574,6 +17695,19 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi,
|
|||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
|
||||
return FALSE;
|
||||
}
|
||||
else if (htab->fdpic_p)
|
||||
{
|
||||
if (elf32_arm_plt_needs_thumb_stub_p (osi->info, arm_plt))
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr - 4))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 16))
|
||||
return FALSE;
|
||||
if (htab->plt_entry_size == 4 * ARRAY_SIZE(elf32_arm_fdpic_plt_entry))
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 24))
|
||||
return FALSE;
|
||||
}
|
||||
else if (using_thumb_only (htab))
|
||||
{
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr))
|
||||
|
|
Loading…
Reference in New Issue