From 5c5a4843ec385a60954fbbc4bcf5b64763639bd3 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Tue, 20 Mar 2018 10:55:29 +0100 Subject: [PATCH] [ARM] Add TLS relocations for FDPIC. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Mickaël Guêné 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. --- bfd/ChangeLog | 19 +++++++++++ bfd/bfd-in2.h | 3 ++ bfd/elf32-arm.c | 79 ++++++++++++++++++++++++++++++++++++------- bfd/reloc.c | 6 ++++ gas/ChangeLog | 9 +++++ gas/config/tc-arm.c | 26 +++++++++++++- include/ChangeLog | 6 ++++ include/elf/arm.h | 3 ++ ld/ChangeLog | 5 +++ ld/scripttempl/elf.sc | 6 +++- 10 files changed, 148 insertions(+), 14 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 11c4297227a..3e5415e4238 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,22 @@ +2018-04-25 Christophe Lyon + Mickaël Guêné + + * 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 Mickaël Guêné diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index f58c2f73396..927dc9d9f90 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -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, diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 9eb12e2fed7..fb29c0c0108 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -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)) diff --git a/bfd/reloc.c b/bfd/reloc.c index e78e582c1f3..f7e34a993ae 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -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. diff --git a/gas/ChangeLog b/gas/ChangeLog index 122daaaf0c8..ce832e919d9 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2018-04-25 Christophe Lyon + Mickaël Guêné + + * 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 Mickaël Guêné diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 33a88bb3145..760afab4213 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -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 diff --git a/include/ChangeLog b/include/ChangeLog index 6b52420fa40..3e45748e7d5 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2018-04-25 Christophe Lyon + Mickaël Guêné + + * elf/arm.h: Add R_ARM_TLS_GD32_FDPIC, R_ARM_TLS_LDM32_FDPIC, + R_ARM_TLS_IE32_FDPIC. + 2018-04-25 Christophe Lyon Mickaël Guêné diff --git a/include/elf/arm.h b/include/elf/arm.h index 158f7b1652c..fdae08aed70 100644 --- a/include/elf/arm.h +++ b/include/elf/arm.h @@ -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) diff --git a/ld/ChangeLog b/ld/ChangeLog index d9900b5ebb0..30de4cbe663 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2018-04-25 Christophe Lyon + Mickaël Guêné + + * scripttempl/elf.sc: Define __tdata_start for .tdata section. + 2018-04-25 Christophe Lyon Mickaël Guêné diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index 9787ab5dac2..5ccdd415f39 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -587,7 +587,11 @@ cat <