[ARM] Add TLS relocations for FDPIC.

Define and handle TLS relocations for FDPIC in BFD and gas.

In gas, the new relocations are rejected if the --fdpic option was not
specified.

We also define the __tdata_start symbol to mark the start of the
.tdata section. This allows FDPIC static binaries to find the start of
.tdata section, since phdr->p_vaddr of TLS segment is not a valid
value for FDPIC.

2018-04-25  Christophe Lyon  <christophe.lyon@st.com>
	Mickaël Guêné  <mickael.guene@st.com>

	bfd/:
	* bfd-in2.h (BFD_RELOC_ARM_TLS_GD32_FDPIC)
	(BFD_RELOC_ARM_TLS_LDM32_FDPIC, BFD_RELOC_ARM_TLS_IE32_FDPIC): New
	relocations.
	* elf32-arm.c (elf32_arm_howto_table_2): Add R_ARM_TLS_GD32_FDPIC,
	R_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_IE32_FDPIC relocations.
	(elf32_arm_reloc_map): Add R_ARM_TLS_GD32_FDPIC,
	R_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_IE32_FDPIC.
	(struct elf32_arm_link_hash_table): Update comment.
	(elf32_arm_final_link_relocate): Handle TLS FDPIC relocations.
	(IS_ARM_TLS_RELOC): Likewise.
	(elf32_arm_check_relocs): Likewise.
	(allocate_dynrelocs_for_symbol): Likewise.
	(elf32_arm_size_dynamic_sections): Update comment.
	* reloc.c: Add BFD_RELOC_ARM_TLS_GD32_FDPIC,
	BFD_RELOC_ARM_TLS_LDM32_FDPIC, BFD_RELOC_ARM_TLS_IE32_FDPIC.

	gas/
	* config/tc-arm.c (reloc_names): Add TLSGD_FDPIC, TLSLDM_FDPIC,
	GOTTPOFF_FDIC relocations.
	(md_apply_fix): Handle the new TLS FDPIC relocations.
	(tc_gen_reloc): Likewise.
	(arm_fix_adjustable): Likewise.

	include/
	* elf/arm.h: Add R_ARM_TLS_GD32_FDPIC, R_ARM_TLS_LDM32_FDPIC,
	R_ARM_TLS_IE32_FDPIC.

	ld/
	* scripttempl/elf.sc: Define __tdata_start for .tdata section.
This commit is contained in:
Christophe Lyon 2018-03-20 10:55:29 +01:00 committed by Christophe Lyon
parent 7801f98f84
commit 5c5a4843ec
10 changed files with 148 additions and 14 deletions

View File

@ -1,3 +1,22 @@
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
Mickaël Guêné <mickael.guene@st.com>
* bfd-in2.h (BFD_RELOC_ARM_TLS_GD32_FDPIC)
(BFD_RELOC_ARM_TLS_LDM32_FDPIC, BFD_RELOC_ARM_TLS_IE32_FDPIC): New
relocations.
* elf32-arm.c (elf32_arm_howto_table_2): Add R_ARM_TLS_GD32_FDPIC,
R_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_IE32_FDPIC relocations.
(elf32_arm_reloc_map): Add R_ARM_TLS_GD32_FDPIC,
R_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_IE32_FDPIC.
(struct elf32_arm_link_hash_table): Update comment.
(elf32_arm_final_link_relocate): Handle TLS FDPIC relocations.
(IS_ARM_TLS_RELOC): Likewise.
(elf32_arm_check_relocs): Likewise.
(allocate_dynrelocs_for_symbol): Likewise.
(elf32_arm_size_dynamic_sections): Update comment.
* reloc.c: Add BFD_RELOC_ARM_TLS_GD32_FDPIC,
BFD_RELOC_ARM_TLS_LDM32_FDPIC, BFD_RELOC_ARM_TLS_IE32_FDPIC.
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
Mickaël Guêné <mickael.guene@st.com>

View File

@ -3531,6 +3531,9 @@ pc-relative or some form of GOT-indirect relocation. */
BFD_RELOC_ARM_GOTOFFFUNCDESC,
BFD_RELOC_ARM_FUNCDESC,
BFD_RELOC_ARM_FUNCDESC_VALUE,
BFD_RELOC_ARM_TLS_GD32_FDPIC,
BFD_RELOC_ARM_TLS_LDM32_FDPIC,
BFD_RELOC_ARM_TLS_IE32_FDPIC,
/* Relocations for setting up GOTs and PLTs for shared libraries. */
BFD_RELOC_ARM_JUMP_SLOT,

View File

@ -1746,7 +1746,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
};
/* 160 onwards: */
static reloc_howto_type elf32_arm_howto_table_2[5] =
static reloc_howto_type elf32_arm_howto_table_2[8] =
{
HOWTO (R_ARM_IRELATIVE, /* type */
0, /* rightshift */
@ -1813,6 +1813,45 @@ static reloc_howto_type elf32_arm_howto_table_2[5] =
0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_GD32_FDPIC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_GD32_FDPIC",/* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_LDM32_FDPIC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_LDM32_FDPIC",/* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_IE32_FDPIC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_IE32_FDPIC",/* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
};
/* 249-255 extended, currently unused, relocations: */
@ -1970,6 +2009,9 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
{BFD_RELOC_ARM_GOTOFFFUNCDESC, R_ARM_GOTOFFFUNCDESC},
{BFD_RELOC_ARM_FUNCDESC, R_ARM_FUNCDESC},
{BFD_RELOC_ARM_FUNCDESC_VALUE, R_ARM_FUNCDESC_VALUE},
{BFD_RELOC_ARM_TLS_GD32_FDPIC, R_ARM_TLS_GD32_FDPIC},
{BFD_RELOC_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_LDM32_FDPIC},
{BFD_RELOC_ARM_TLS_IE32_FDPIC, R_ARM_TLS_IE32_FDPIC},
{BFD_RELOC_VTABLE_INHERIT, R_ARM_GNU_VTINHERIT},
{BFD_RELOC_VTABLE_ENTRY, R_ARM_GNU_VTENTRY},
{BFD_RELOC_ARM_MOVW, R_ARM_MOVW_ABS_NC},
@ -3280,7 +3322,7 @@ struct elf32_arm_link_hash_table
/* Offset in .plt section of tls_arm_trampoline. */
bfd_vma tls_trampoline;
/* Data for R_ARM_TLS_LDM32 relocations. */
/* Data for R_ARM_TLS_LDM32/R_ARM_TLS_LDM32_FDPIC relocations. */
union
{
bfd_signed_vma refcount;
@ -11523,6 +11565,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
rel->r_addend);
case R_ARM_TLS_LDM32:
case R_ARM_TLS_LDM32_FDPIC:
{
bfd_vma off;
@ -11561,7 +11604,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
globals->tls_ldm_got.offset |= 1;
}
if (globals->fdpic_p)
if (r_type == R_ARM_TLS_LDM32_FDPIC)
{
bfd_put_32(output_bfd,
globals->root.sgot->output_offset + off,
@ -11584,7 +11627,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
case R_ARM_TLS_CALL:
case R_ARM_THM_TLS_CALL:
case R_ARM_TLS_GD32:
case R_ARM_TLS_GD32_FDPIC:
case R_ARM_TLS_IE32:
case R_ARM_TLS_IE32_FDPIC:
case R_ARM_TLS_GOTDESC:
case R_ARM_TLS_DESCSEQ:
case R_ARM_THM_TLS_DESCSEQ:
@ -11772,7 +11817,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
local_got_offsets[r_symndx] |= 1;
}
if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32)
if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32 && r_type != R_ARM_TLS_GD32_FDPIC)
off += 8;
else if (tls_type & GOT_TLS_GDESC)
off = offplt;
@ -11931,8 +11976,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
- (input_section->output_section->vma
+ input_section->output_offset + rel->r_offset));
if (globals->fdpic_p && (r_type == R_ARM_TLS_GD32 ||
r_type == R_ARM_TLS_IE32))
if (globals->fdpic_p && (r_type == R_ARM_TLS_GD32_FDPIC ||
r_type == R_ARM_TLS_IE32_FDPIC))
{
/* For FDPIC relocations, resolve to the offset of the GOT
entry from the start of GOT. */
@ -12845,13 +12890,16 @@ arm_add_to_rel (bfd * abfd,
#define IS_ARM_TLS_RELOC(R_TYPE) \
((R_TYPE) == R_ARM_TLS_GD32 \
|| (R_TYPE) == R_ARM_TLS_GD32_FDPIC \
|| (R_TYPE) == R_ARM_TLS_LDO32 \
|| (R_TYPE) == R_ARM_TLS_LDM32 \
|| (R_TYPE) == R_ARM_TLS_LDM32_FDPIC \
|| (R_TYPE) == R_ARM_TLS_DTPOFF32 \
|| (R_TYPE) == R_ARM_TLS_DTPMOD32 \
|| (R_TYPE) == R_ARM_TLS_TPOFF32 \
|| (R_TYPE) == R_ARM_TLS_LE32 \
|| (R_TYPE) == R_ARM_TLS_IE32 \
|| (R_TYPE) == R_ARM_TLS_IE32_FDPIC \
|| IS_ARM_TLS_GNU_RELOC (R_TYPE))
/* Specific set of relocations for the gnu tls dialect. */
@ -15077,7 +15125,9 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_ARM_GOT32:
case R_ARM_GOT_PREL:
case R_ARM_TLS_GD32:
case R_ARM_TLS_GD32_FDPIC:
case R_ARM_TLS_IE32:
case R_ARM_TLS_IE32_FDPIC:
case R_ARM_TLS_GOTDESC:
case R_ARM_TLS_DESCSEQ:
case R_ARM_THM_TLS_DESCSEQ:
@ -15090,8 +15140,10 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
switch (r_type)
{
case R_ARM_TLS_GD32: tls_type = GOT_TLS_GD; break;
case R_ARM_TLS_GD32_FDPIC: tls_type = GOT_TLS_GD; break;
case R_ARM_TLS_IE32: tls_type = GOT_TLS_IE; break;
case R_ARM_TLS_IE32_FDPIC: tls_type = GOT_TLS_IE; break;
case R_ARM_TLS_GOTDESC:
case R_ARM_TLS_CALL: case R_ARM_THM_TLS_CALL:
@ -15149,7 +15201,8 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
/* Fall through. */
case R_ARM_TLS_LDM32:
if (r_type == R_ARM_TLS_LDM32)
case R_ARM_TLS_LDM32_FDPIC:
if (r_type == R_ARM_TLS_LDM32 || r_type == R_ARM_TLS_LDM32_FDPIC)
htab->tls_ldm_got.refcount++;
/* Fall through. */
@ -16078,15 +16131,17 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
if (tls_type & GOT_TLS_GD)
{
/* R_ARM_TLS_GD32 needs 2 consecutive GOT slots. If
the symbol is both GD and GDESC, got.offset may
have been overwritten. */
/* R_ARM_TLS_GD32 and R_ARM_TLS_GD32_FDPIC need two
consecutive GOT slots. If the symbol is both GD
and GDESC, got.offset may have been
overwritten. */
h->got.offset = s->size;
s->size += 8;
}
if (tls_type & GOT_TLS_IE)
/* R_ARM_TLS_IE32 needs one GOT slot. */
/* R_ARM_TLS_IE32/R_ARM_TLS_IE32_FDPIC need one GOT
slot. */
s->size += 4;
}
@ -16689,7 +16744,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
if (htab->tls_ldm_got.refcount > 0)
{
/* Allocate two GOT entries and one dynamic relocation (if necessary)
for R_ARM_TLS_LDM32 relocations. */
for R_ARM_TLS_LDM32/R_ARM_TLS_LDM32_FDPIC relocations. */
htab->tls_ldm_got.offset = htab->root.sgot->size;
htab->root.sgot->size += 8;
if (bfd_link_pic (info))

View File

@ -3215,6 +3215,12 @@ ENUMX
BFD_RELOC_ARM_FUNCDESC
ENUMX
BFD_RELOC_ARM_FUNCDESC_VALUE
ENUMX
BFD_RELOC_ARM_TLS_GD32_FDPIC
ENUMX
BFD_RELOC_ARM_TLS_LDM32_FDPIC
ENUMX
BFD_RELOC_ARM_TLS_IE32_FDPIC
ENUMDOC
ARM FDPIC specific relocations.

View File

@ -1,3 +1,12 @@
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
Mickaël Guêné <mickael.guene@st.com>
* config/tc-arm.c (reloc_names): Add TLSGD_FDPIC, TLSLDM_FDPIC,
GOTTPOFF_FDIC relocations.
(md_apply_fix): Handle the new TLS FDPIC relocations.
(tc_gen_reloc): Likewise.
(arm_fix_adjustable): Likewise.
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
Mickaël Guêné <mickael.guene@st.com>

View File

@ -19309,7 +19309,10 @@ static struct reloc_entry reloc_names[] =
{ "gotofffuncdesc", BFD_RELOC_ARM_GOTOFFFUNCDESC },
{ "GOTOFFFUNCDESC", BFD_RELOC_ARM_GOTOFFFUNCDESC },
{ "funcdesc", BFD_RELOC_ARM_FUNCDESC },
{ "FUNCDESC", BFD_RELOC_ARM_FUNCDESC }
{ "FUNCDESC", BFD_RELOC_ARM_FUNCDESC },
{ "tlsgd_fdpic", BFD_RELOC_ARM_TLS_GD32_FDPIC }, { "TLSGD_FDPIC", BFD_RELOC_ARM_TLS_GD32_FDPIC },
{ "tlsldm_fdpic", BFD_RELOC_ARM_TLS_LDM32_FDPIC }, { "TLSLDM_FDPIC", BFD_RELOC_ARM_TLS_LDM32_FDPIC },
{ "gottpoff_fdpic", BFD_RELOC_ARM_TLS_IE32_FDPIC }, { "GOTTPOFF_FDIC", BFD_RELOC_ARM_TLS_IE32_FDPIC },
};
#endif
@ -23982,6 +23985,21 @@ md_apply_fix (fixS * fixP,
S_SET_THREAD_LOCAL (fixP->fx_addsy);
break;
/* Same handling as above, but with the arm_fdpic guard. */
case BFD_RELOC_ARM_TLS_GD32_FDPIC:
case BFD_RELOC_ARM_TLS_IE32_FDPIC:
case BFD_RELOC_ARM_TLS_LDM32_FDPIC:
if (arm_fdpic)
{
S_SET_THREAD_LOCAL (fixP->fx_addsy);
}
else
{
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Relocation supported only in FDPIC mode"));
}
break;
case BFD_RELOC_ARM_GOT32:
case BFD_RELOC_ARM_GOTOFF:
break;
@ -24783,9 +24801,12 @@ tc_gen_reloc (asection *section, fixS *fixp)
case BFD_RELOC_ARM_TLS_GOTDESC:
case BFD_RELOC_ARM_TLS_GD32:
case BFD_RELOC_ARM_TLS_GD32_FDPIC:
case BFD_RELOC_ARM_TLS_LE32:
case BFD_RELOC_ARM_TLS_IE32:
case BFD_RELOC_ARM_TLS_IE32_FDPIC:
case BFD_RELOC_ARM_TLS_LDM32:
case BFD_RELOC_ARM_TLS_LDM32_FDPIC:
/* BFD will include the symbol's address in the addend.
But we don't want that, so subtract it out again here. */
if (!S_IS_COMMON (fixp->fx_addsy))
@ -25051,9 +25072,12 @@ arm_fix_adjustable (fixS * fixP)
|| fixP->fx_r_type == BFD_RELOC_ARM_GOT32
|| fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_GD32_FDPIC
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_LE32
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32_FDPIC
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32_FDPIC
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDO32
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_GOTDESC
|| fixP->fx_r_type == BFD_RELOC_ARM_TLS_CALL

View File

@ -1,3 +1,9 @@
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
Mickaël Guêné <mickael.guene@st.com>
* elf/arm.h: Add R_ARM_TLS_GD32_FDPIC, R_ARM_TLS_LDM32_FDPIC,
R_ARM_TLS_IE32_FDPIC.
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
Mickaël Guêné <mickael.guene@st.com>

View File

@ -244,6 +244,9 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
RELOC_NUMBER (R_ARM_GOTOFFFUNCDESC, 162)
RELOC_NUMBER (R_ARM_FUNCDESC, 163)
RELOC_NUMBER (R_ARM_FUNCDESC_VALUE, 164)
RELOC_NUMBER (R_ARM_TLS_GD32_FDPIC, 165)
RELOC_NUMBER (R_ARM_TLS_LDM32_FDPIC, 166)
RELOC_NUMBER (R_ARM_TLS_IE32_FDPIC, 167)
/* Extensions? R=read-only? */
RELOC_NUMBER (R_ARM_RXPC25, 249)

View File

@ -1,3 +1,8 @@
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
Mickaël Guêné <mickael.guene@st.com>
* scripttempl/elf.sc: Define __tdata_start for .tdata section.
2018-04-25 Christophe Lyon <christophe.lyon@st.com>
Mickaël Guêné <mickael.guene@st.com>

View File

@ -587,7 +587,11 @@ cat <<EOF
.exception_ranges ${RELOCATING-0} : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
/* Thread Local Storage sections */
.tdata ${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
.tdata ${RELOCATING-0} :
{
${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__tdata_start = .);}}
*(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*})
}
.tbss ${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
${RELOCATING+${PREINIT_ARRAY}}