X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-arm.c;h=a42db44b2f12f22058844625cdd017ef2f80e3a2;hb=59029f57eba1763bad67167c2805d8df3dfa2285;hp=9eb12e2fed786e9d3a03ca9db3a1063d9e7249a1;hpb=7801f98f84fefa495941c86e2a859ea8c6c37770;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 9eb12e2fed..a42db44b2f 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}, @@ -2209,6 +2251,9 @@ typedef unsigned short int insn16; section. */ #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" +/* FDPIC default stack size. */ +#define DEFAULT_STACK_SIZE 0x8000 + static const unsigned long tls_trampoline [] = { 0xe08e0000, /* add r0, lr, r0 */ @@ -2245,6 +2290,22 @@ static const bfd_vma elf32_arm_fdpic_plt_entry [] = 0xe599f000, /* ldr pc, [r9] */ }; +/* Thumb FDPIC PLT entry. */ +/* The last 5 words contain PLT lazy fragment code and data. */ +static const bfd_vma elf32_arm_fdpic_thumb_plt_entry [] = + { + 0xc00cf8df, /* ldr.w r12, .L1 */ + 0x0c09eb0c, /* add.w r12, r12, r9 */ + 0x9004f8dc, /* ldr.w r9, [r12, #4] */ + 0xf000f8dc, /* ldr.w pc, [r12] */ + 0x00000000, /* .L1 .word foo(GOTOFFFUNCDESC) */ + 0x00000000, /* .L2 .word foo(funcdesc_value_reloc_offset) */ + 0xc008f85f, /* ldr.w r12, .L2 */ + 0xcd04f84d, /* push {r12} */ + 0xc004f8d9, /* ldr.w r12, [r9, #4] */ + 0xf000f8d9, /* ldr.w pc, [r9] */ + }; + #ifdef FOUR_WORD_PLT /* The first entry in a procedure linkage table looks like @@ -3280,7 +3341,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; @@ -3575,6 +3636,8 @@ elf32_arm_get_plt_info (bfd *abfd, struct elf32_arm_link_hash_table *globals, return TRUE; } +static bfd_boolean using_thumb_only (struct elf32_arm_link_hash_table *globals); + /* Return true if the PLT described by ARM_PLT requires a Thumb stub before it. */ @@ -3585,8 +3648,9 @@ elf32_arm_plt_needs_thumb_stub_p (struct bfd_link_info *info, struct elf32_arm_link_hash_table *htab; htab = elf32_arm_hash_table (info); - return (arm_plt->thumb_refcount != 0 - || (!htab->use_blx && arm_plt->maybe_thumb_refcount != 0)); + + return (!using_thumb_only(htab) && (arm_plt->thumb_refcount != 0 + || (!htab->use_blx && arm_plt->maybe_thumb_refcount != 0))); } /* Return a pointer to the head of the dynamic reloc list that should @@ -8912,7 +8976,9 @@ bfd_elf32_arm_set_target_params (struct bfd *output_bfd, return; globals->target1_is_rel = params->target1_is_rel; - if (strcmp (params->target2_type, "rel") == 0) + if (globals->fdpic_p) + globals->target2_reloc = R_ARM_GOT32; + else if (strcmp (params->target2_type, "rel") == 0) globals->target2_reloc = R_ARM_REL32; else if (strcmp (params->target2_type, "abs") == 0) globals->target2_reloc = R_ARM_ABS32; @@ -9682,6 +9748,10 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, } else if (htab->fdpic_p) { + const bfd_vma *plt_entry = using_thumb_only(htab) + ? elf32_arm_fdpic_thumb_plt_entry + : elf32_arm_fdpic_plt_entry; + /* Fill-up Thumb stub if needed. */ if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt)) { @@ -9690,14 +9760,13 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, 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); + /* As we are using 32 bit instructions even for the Thumb + version, we have to use 'put_arm_insn' instead of + 'put_thumb_insn'. */ + put_arm_insn(htab, output_bfd, plt_entry[0], ptr + 0); + put_arm_insn(htab, output_bfd, plt_entry[1], ptr + 4); + put_arm_insn(htab, output_bfd, plt_entry[2], ptr + 8); + put_arm_insn(htab, output_bfd, plt_entry[3], ptr + 12); bfd_put_32 (output_bfd, got_offset, ptr + 16); if (!(info->flags & DF_BIND_NOW)) @@ -9706,14 +9775,10 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, 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); + put_arm_insn(htab, output_bfd, plt_entry[6], ptr + 24); + put_arm_insn(htab, output_bfd, plt_entry[7], ptr + 28); + put_arm_insn(htab, output_bfd, plt_entry[8], ptr + 32); + put_arm_insn(htab, output_bfd, plt_entry[9], ptr + 36); } } else if (using_thumb_only (htab)) @@ -11523,6 +11588,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 +11627,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 +11650,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 +11840,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 +11999,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 +12913,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 +15148,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 +15163,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 +15224,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 +16154,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; } @@ -16430,6 +16508,7 @@ maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) /* Not an error, just cut short the traversal. */ return FALSE; } + return TRUE; } @@ -16689,7 +16768,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)) @@ -16900,6 +16979,9 @@ elf32_arm_always_size_sections (bfd *output_bfd, struct bfd_link_info *info) { asection *tls_sec; + struct elf32_arm_link_hash_table *htab; + + htab = elf32_arm_hash_table (info); if (bfd_link_relocatable (info)) return TRUE; @@ -16932,6 +17014,12 @@ elf32_arm_always_size_sections (bfd *output_bfd, (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE); } } + + if (htab->fdpic_p && !bfd_link_relocatable (info) + && !bfd_elf_stack_segment_size (output_bfd, info, + "__stacksize", DEFAULT_STACK_SIZE)) + return FALSE; + return TRUE; } @@ -17016,10 +17104,10 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, } /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. On VxWorks, - the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it is relative - to the ".got" section. */ + and for FDPIC, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: + it is relative to the ".got" section. */ if (h == htab->root.hdynamic - || (!htab->vxworks_p && h == htab->root.hgot)) + || (!htab->fdpic_p && !htab->vxworks_p && h == htab->root.hgot)) sym->st_shndx = SHN_ABS; return TRUE; @@ -17697,15 +17785,19 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi, } else if (htab->fdpic_p) { + enum map_symbol_type type = using_thumb_only(htab) + ? ARM_MAP_THUMB + : ARM_MAP_ARM; + 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)) + if (!elf32_arm_output_map_sym (osi, type, 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)) + if (!elf32_arm_output_map_sym (osi, type, addr + 24)) return FALSE; } else if (using_thumb_only (htab)) @@ -18064,7 +18156,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0)) return FALSE; } - else if (using_thumb_only (htab)) + else if (using_thumb_only (htab) && !htab->fdpic_p) { if (!elf32_arm_output_map_sym (&osi, ARM_MAP_THUMB, 0)) return FALSE;