X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf32-arm.c;h=367dff38c0d8398d227cf66e06b6d01b4b716198;hb=a496fbc8802f0a5719db6347a43cc869e03d83c9;hp=4692a0579b8fc7f74085e50db939605b6249b421;hpb=4b95cf5c0c75d6efc1b2f96af72317aecca079f1;p=binutils-gdb.git diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 4692a0579b8..367dff38c0d 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -1,5 +1,5 @@ /* 32-bit ELF support for ARM - Copyright (C) 1998-2014 Free Software Foundation, Inc. + Copyright (C) 1998-2015 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -79,7 +79,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] = /* No relocation. */ HOWTO (R_ARM_NONE, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -1606,7 +1606,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + NULL, /* special_function */ "R_ARM_TLS_LE32", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -2040,9 +2040,9 @@ elf32_arm_nabi_write_core_note (bfd *abfd, char *buf, int *bufsiz, } } -#define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec +#define TARGET_LITTLE_SYM arm_elf32_le_vec #define TARGET_LITTLE_NAME "elf32-littlearm" -#define TARGET_BIG_SYM bfd_elf32_bigarm_vec +#define TARGET_BIG_SYM arm_elf32_be_vec #define TARGET_BIG_NAME "elf32-bigarm" #define elf_backend_grok_prstatus elf32_arm_nabi_grok_prstatus @@ -2172,7 +2172,7 @@ static const bfd_vma elf32_thumb2_plt0_entry [] = an instruction maybe encoded to one or two array elements. */ 0xf8dfb500, /* push {lr} */ 0x44fee008, /* ldr.w lr, [pc, #8] */ - /* add lr, pc */ + /* add lr, pc */ 0xff08f85e, /* ldr.w pc, [lr, #8]! */ 0x00000000, /* &GOT[0] - . */ }; @@ -2187,7 +2187,7 @@ static const bfd_vma elf32_thumb2_plt_entry [] = 0x0c00f2c0, /* movt ip, #0xNNNN */ 0xf8dc44fc, /* add ip, pc */ 0xbf00f000 /* ldr.w pc, [ip] */ - /* nop */ + /* nop */ }; /* The format of the first entry in the procedure linkage table @@ -2283,6 +2283,8 @@ static const bfd_vma elf32_arm_nacl_plt_entry [] = #define THM_MAX_BWD_BRANCH_OFFSET (-(1 << 22) + 4) #define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4) #define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4) +#define THM2_MAX_FWD_COND_BRANCH_OFFSET (((1 << 20) -2) + 4) +#define THM2_MAX_BWD_COND_BRANCH_OFFSET (-(1 << 20) + 4) enum stub_insn_type { @@ -2569,7 +2571,7 @@ enum elf32_arm_stub_type { arm_stub_none, DEF_STUBS - /* Note the first a8_veneer type */ + /* Note the first a8_veneer type. */ arm_stub_a8_veneer_lwm = arm_stub_a8_veneer_b_cond }; #undef DEF_STUB @@ -3523,6 +3525,18 @@ elf32_arm_copy_indirect_symbol (struct bfd_link_info *info, _bfd_elf_link_hash_copy_indirect (info, dir, ind); } +/* Destroy an ARM elf linker hash table. */ + +static void +elf32_arm_link_hash_table_free (bfd *obfd) +{ + struct elf32_arm_link_hash_table *ret + = (struct elf32_arm_link_hash_table *) obfd->link.hash; + + bfd_hash_table_free (&ret->stub_hash_table); + _bfd_elf_link_hash_table_free (obfd); +} + /* Create an ARM elf linker hash table. */ static struct bfd_link_hash_table * @@ -3558,25 +3572,14 @@ elf32_arm_link_hash_table_create (bfd *abfd) if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc, sizeof (struct elf32_arm_stub_hash_entry))) { - free (ret); + _bfd_elf_link_hash_table_free (abfd); return NULL; } + ret->root.root.hash_table_free = elf32_arm_link_hash_table_free; return &ret->root.root; } -/* Free the derived linker hash table. */ - -static void -elf32_arm_hash_table_free (struct bfd_link_hash_table *hash) -{ - struct elf32_arm_link_hash_table *ret - = (struct elf32_arm_link_hash_table *) hash; - - bfd_hash_table_free (&ret->stub_hash_table); - _bfd_elf_link_hash_table_free (hash); -} - /* Determine what kind of NOPs are available. */ static bfd_boolean @@ -3666,7 +3669,8 @@ arm_type_of_stub (struct bfd_link_info *info, /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we are considering a function call relocation. */ - if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24) + if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24 + || r_type == R_ARM_THM_JUMP19) && branch_type == ST_BRANCH_TO_ARM) branch_type = ST_BRANCH_TO_THUMB; @@ -3710,7 +3714,7 @@ arm_type_of_stub (struct bfd_link_info *info, branch_offset = (bfd_signed_vma)(destination - location); if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24 - || r_type == R_ARM_THM_TLS_CALL) + || r_type == R_ARM_THM_TLS_CALL || r_type == R_ARM_THM_JUMP19) { /* Handle cases where: - this call goes too far (different Thumb/Thumb2 max @@ -3726,10 +3730,15 @@ arm_type_of_stub (struct bfd_link_info *info, || (thumb2 && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET))) + || (thumb2 + && (branch_offset > THM2_MAX_FWD_COND_BRANCH_OFFSET + || (branch_offset < THM2_MAX_BWD_COND_BRANCH_OFFSET)) + && (r_type == R_ARM_THM_JUMP19)) || (branch_type == ST_BRANCH_TO_ARM && (((r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_TLS_CALL) && !globals->use_blx) - || (r_type == R_ARM_THM_JUMP24)) + || (r_type == R_ARM_THM_JUMP24) + || (r_type == R_ARM_THM_JUMP19)) && !use_plt)) { if (branch_type == ST_BRANCH_TO_THUMB) @@ -3783,7 +3792,7 @@ arm_type_of_stub (struct bfd_link_info *info, (info->shared | globals->pic_veneer) /* PIC stubs. */ ? (r_type == R_ARM_THM_TLS_CALL - /* TLS PIC stubs */ + /* TLS PIC stubs. */ ? (globals->use_blx ? arm_stub_long_branch_any_tls_pic : arm_stub_long_branch_v4t_thumb_tls_pic) : ((globals->use_blx && r_type == R_ARM_THM_CALL) @@ -3860,7 +3869,7 @@ arm_type_of_stub (struct bfd_link_info *info, (info->shared | globals->pic_veneer) /* PIC stubs. */ ? (r_type == R_ARM_TLS_CALL - /* TLS PIC Stub */ + /* TLS PIC Stub. */ ? arm_stub_long_branch_any_tls_pic : (globals->nacl_p ? arm_stub_long_branch_arm_nacl_pic @@ -4436,7 +4445,7 @@ elf32_arm_setup_section_lists (bfd *output_bfd, /* Count the number of input BFDs and find the top input section id. */ for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0; input_bfd != NULL; - input_bfd = input_bfd->link_next) + input_bfd = input_bfd->link.next) { bfd_count += 1; for (section = input_bfd->sections; @@ -5045,7 +5054,7 @@ elf32_arm_size_stubs (bfd *output_bfd, num_a8_fixes = 0; for (input_bfd = info->input_bfds, bfd_indx = 0; input_bfd != NULL; - input_bfd = input_bfd->link_next, bfd_indx++) + input_bfd = input_bfd->link.next, bfd_indx++) { Elf_Internal_Shdr *symtab_hdr; asection *section; @@ -5195,7 +5204,7 @@ elf32_arm_size_stubs (bfd *output_bfd, if (!sym_sec) /* This is an undefined symbol. It can never - be resolved. */ + be resolved. */ continue; if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) @@ -5346,7 +5355,8 @@ elf32_arm_size_stubs (bfd *output_bfd, /* For historical reasons, use the existing names for ARM-to-Thumb and Thumb-to-ARM stubs. */ if ((r_type == (unsigned int) R_ARM_THM_CALL - || r_type == (unsigned int) R_ARM_THM_JUMP24) + || r_type == (unsigned int) R_ARM_THM_JUMP24 + || r_type == (unsigned int) R_ARM_THM_JUMP19) && branch_type == ST_BRANCH_TO_ARM) sprintf (stub_entry->output_name, THUMB2ARM_GLUE_ENTRY_NAME, sym_name); @@ -7521,6 +7531,8 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info, first entry. */ if (splt->size == 0) splt->size += htab->plt_header_size; + + htab->next_tls_desc_index++; } /* Allocate the PLT entry itself, including any leading Thumb stub. */ @@ -7533,7 +7545,10 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info, { /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ - arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc; + if (is_iplt_entry) + arm_plt->got_offset = sgotplt->size; + else + arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc; sgotplt->size += 4; } } @@ -7754,7 +7769,7 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, else if (using_thumb_only (htab)) { /* PR ld/16017: Generate thumb only PLT entries. */ - if (!using_thumb2 (htab)) + if (!using_thumb2 (htab)) { /* FIXME: We ought to be able to generate thumb-1 PLT instructions... */ @@ -8075,7 +8090,7 @@ elf32_arm_tls_relax (struct elf32_arm_link_hash_table *globals, break; case R_ARM_THM_TLS_CALL: - /* GD->IE relaxation */ + /* GD->IE relaxation. */ if (!is_local) /* add r0,pc; ldr r0, [r0] */ insn = 0x44786800; @@ -8219,18 +8234,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, if (r_type != howto->type) howto = elf32_arm_howto_from_type (r_type); - /* If the start address has been set, then set the EF_ARM_HASENTRY - flag. Setting this more than once is redundant, but the cost is - not too high, and it keeps the code simple. - - The test is done here, rather than somewhere else, because the - start address is only set just before the final link commences. - - Note - if the user deliberately sets a start address of 0, the - flag will not be set. */ - if (bfd_get_start_address (output_bfd) != 0) - elf_elfheader (output_bfd)->e_flags |= EF_ARM_HASENTRY; - eh = (struct elf32_arm_link_hash_entry *) h; sgot = globals->root.sgot; local_got_offsets = elf_local_got_offsets (input_bfd); @@ -8401,6 +8404,21 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, Elf_Internal_Rela outrel; bfd_boolean skip, relocate; + if ((r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI) + && !h->def_regular) + { + char *v = _("shared object"); + + if (info->executable) + v = _("PIE executable"); + + (*_bfd_error_handler) + (_("%B: relocation %s against external or undefined symbol `%s'" + " can not be used when making a %s; recompile with -fPIC"), input_bfd, + elf32_arm_howto_table_1[r_type].name, h->root.root.string, v); + return bfd_reloc_notsupported; + } + *unresolved_reloc_p = FALSE; if (sreloc == NULL && globals->root.dynamic_sections_created) @@ -8431,7 +8449,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, else if (h != NULL && h->dynindx != -1 && (!info->shared - || !info->symbolic + || !SYMBOLIC_BIND (info, h) || !h->def_regular)) outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); else @@ -9119,6 +9137,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, bfd_signed_vma reloc_signed_max = 0xffffe; bfd_signed_vma reloc_signed_min = -0x100000; bfd_signed_vma signed_check; + enum elf32_arm_stub_type stub_type = arm_stub_none; + struct elf32_arm_stub_hash_entry *stub_entry; + struct elf32_arm_link_hash_entry *hash; /* Need to refetch the addend, reconstruct the top three bits, and squish the two 11 bit pieces together. */ @@ -9150,8 +9171,25 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, *unresolved_reloc_p = FALSE; } - /* ??? Should handle interworking? GCC might someday try to - use this for tail calls. */ + hash = (struct elf32_arm_link_hash_entry *)h; + + stub_type = arm_type_of_stub (info, input_section, rel, + st_type, &branch_type, + hash, value, sym_sec, + input_bfd, sym_name); + if (stub_type != arm_stub_none) + { + stub_entry = elf32_arm_get_stub_entry (input_section, + sym_sec, h, + rel, globals, + stub_type); + if (stub_entry != NULL) + { + value = (stub_entry->stub_offset + + stub_entry->stub_sec->output_offset + + stub_entry->stub_sec->output_section->vma); + } + } relocation = value + signed_addend; relocation -= (input_section->output_section->vma @@ -9743,7 +9781,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, else { lower_insn = 0xc000; - /* Round up the offset to a word boundary */ + /* Round up the offset to a word boundary. */ offset = (offset + 2) & ~2; } @@ -9762,7 +9800,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* These relocations needs special care, as besides the fact they point somewhere in .gotplt, the addend must be adjusted accordingly depending on the type of instruction - we refer to */ + we refer to. */ else if ((r_type == R_ARM_TLS_GOTDESC) && (tls_type & GOT_TLS_GDESC)) { unsigned long data, insn; @@ -10714,7 +10752,7 @@ elf32_arm_relocate_section (bfd * output_bfd, done, i.e., the relaxation produced the final output we want, and we won't let anybody mess with it. Also, we have to do addend adjustments in case of a R_ARM_TLS_GOTDESC relocation - both in relaxed and non-relaxed cases */ + both in relaxed and non-relaxed cases. */ if ((elf32_arm_tls_transition (info, r_type, h) != (unsigned)r_type) || (IS_ARM_TLS_GNU_RELOC (r_type) && !((h ? elf32_arm_hash_entry (h)->tls_type : @@ -10911,7 +10949,7 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order, /* Walk over all EXIDX sections, and create backlinks from the corrsponding text sections. */ - for (inp = info->input_bfds; inp != NULL; inp = inp->link_next) + for (inp = info->input_bfds; inp != NULL; inp = inp->link.next) { asection *sec; @@ -11665,6 +11703,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) static const int order_021[3] = {0, 2, 1}; int i; bfd_boolean result = TRUE; + const char *sec_name = get_elf_backend_data (ibfd)->obj_attrs_section; /* Skip the linker stubs file. This preserves previous behavior of accepting unknown attributes in the first input file - but @@ -11672,6 +11711,12 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) if (ibfd->flags & BFD_LINKER_CREATED) return TRUE; + /* Skip any input that hasn't attribute section. + This enables to link object files without attribute section with + any others. */ + if (bfd_get_section_by_name (ibfd, sec_name) == NULL) + return TRUE; + if (!elf_known_obj_attributes_proc (obfd)[0].i) { /* This is the first object. Copy the attributes. */ @@ -11711,10 +11756,14 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) /* This needs to happen before Tag_ABI_FP_number_model is merged. */ if (in_attr[Tag_ABI_VFP_args].i != out_attr[Tag_ABI_VFP_args].i) { - /* Ignore mismatches if the object doesn't use floating point. */ - if (out_attr[Tag_ABI_FP_number_model].i == 0) + /* Ignore mismatches if the object doesn't use floating point or is + floating point ABI independent. */ + if (out_attr[Tag_ABI_FP_number_model].i == AEABI_FP_number_model_none + || (in_attr[Tag_ABI_FP_number_model].i != AEABI_FP_number_model_none + && out_attr[Tag_ABI_VFP_args].i == AEABI_VFP_args_compatible)) out_attr[Tag_ABI_VFP_args].i = in_attr[Tag_ABI_VFP_args].i; - else if (in_attr[Tag_ABI_FP_number_model].i != 0) + else if (in_attr[Tag_ABI_FP_number_model].i != AEABI_FP_number_model_none + && in_attr[Tag_ABI_VFP_args].i != AEABI_VFP_args_compatible) { _bfd_error_handler (_("error: %B uses VFP register arguments, %B does not"), @@ -11731,7 +11780,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) { case Tag_CPU_raw_name: case Tag_CPU_name: - /* These are merged after Tag_CPU_arch. */ + /* These are merged after Tag_CPU_arch. */ break; case Tag_ABI_optimization_goals: @@ -11743,7 +11792,9 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) { int secondary_compat = -1, secondary_compat_out = -1; unsigned int saved_out_attr = out_attr[i].i; - static const char *name_table[] = { + int arch_attr; + static const char *name_table[] = + { /* These aren't real CPU names, but we can't guess that from the architecture version alone. */ "Pre v4", @@ -11765,10 +11816,17 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) /* Merge Tag_CPU_arch and Tag_also_compatible_with. */ secondary_compat = get_secondary_compatible_arch (ibfd); secondary_compat_out = get_secondary_compatible_arch (obfd); - out_attr[i].i = tag_cpu_arch_combine (ibfd, out_attr[i].i, - &secondary_compat_out, - in_attr[i].i, - secondary_compat); + arch_attr = tag_cpu_arch_combine (ibfd, out_attr[i].i, + &secondary_compat_out, + in_attr[i].i, + secondary_compat); + + /* Return with error if failed to merge. */ + if (arch_attr == -1) + return FALSE; + + out_attr[i].i = arch_attr; + set_secondary_compatible_arch (obfd, secondary_compat_out); /* Merge Tag_CPU_name and Tag_CPU_raw_name. */ @@ -11885,7 +11943,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) else if (in_attr[i].i == 0 || (in_attr[i].i == 'S' && (out_attr[i].i == 'A' || out_attr[i].i == 'R'))) - ; /* Do nothing. */ + ; /* Do nothing. */ else { _bfd_error_handler @@ -11902,9 +11960,9 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) /* Tag_ABI_HardFP_use is handled along with Tag_FP_arch since the meaning of Tag_ABI_HardFP_use depends on Tag_FP_arch when it's 0. It might mean absence of FP hardware if - Tag_FP_arch is zero, otherwise it is effectively SP + DP. */ + Tag_FP_arch is zero. */ -#define VFP_VERSION_COUNT 8 +#define VFP_VERSION_COUNT 9 static const struct { int ver; @@ -11918,7 +11976,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) {3, 16}, {4, 32}, {4, 16}, - {8, 32} + {8, 32}, + {8, 16} }; int ver; int regs; @@ -11943,7 +12002,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) } /* Both the input and the output have nonzero Tag_FP_arch. - So Tag_ABI_HardFP_use is (SP & DP) when it's zero. */ + So Tag_ABI_HardFP_use is implied by Tag_FP_arch when it's zero. */ /* If both the input and the output have zero Tag_ABI_HardFP_use, do nothing. */ @@ -11951,10 +12010,10 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) && out_attr[Tag_ABI_HardFP_use].i == 0) ; /* If the input and the output have different Tag_ABI_HardFP_use, - the combination of them is 3 (SP & DP). */ + the combination of them is 0 (implied by Tag_FP_arch). */ else if (in_attr[Tag_ABI_HardFP_use].i != out_attr[Tag_ABI_HardFP_use].i) - out_attr[Tag_ABI_HardFP_use].i = 3; + out_attr[Tag_ABI_HardFP_use].i = 0; /* Now we can handle Tag_FP_arch. */ @@ -12323,10 +12382,7 @@ elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr) if (flags & EF_ARM_RELEXEC) fprintf (file, _(" [relocatable executable]")); - if (flags & EF_ARM_HASENTRY) - fprintf (file, _(" [has entry point]")); - - flags &= ~ (EF_ARM_RELEXEC | EF_ARM_HASENTRY); + flags &= ~EF_ARM_RELEXEC; if (flags) fprintf (file, _("")); @@ -12494,7 +12550,7 @@ elf32_arm_gc_sweep_hook (bfd * abfd, && (sec->flags & SEC_ALLOC) != 0) { if (h == NULL - && (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI)) + && elf32_arm_howto_from_type (r_type)->pc_relative) { call_reloc_p = TRUE; may_need_local_target_p = TRUE; @@ -12705,6 +12761,9 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, default: tls_type = GOT_NORMAL; break; } + if (!info->executable && (tls_type & GOT_TLS_IE)) + info->flags |= DF_STATIC_TLS; + if (h != NULL) { h->got.refcount++; @@ -12735,7 +12794,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, /* If the symbol is accessed in both IE and GDESC method, we're able to relax. Turn off the GDESC flag, without messing up with any other kind of tls types - that may be involved */ + that may be involved. */ if ((tls_type & GOT_TLS_IE) && (tls_type & GOT_TLS_GDESC)) tls_type &= ~GOT_TLS_GDESC; @@ -12800,6 +12859,11 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, /* Fall through. */ case R_ARM_ABS32: case R_ARM_ABS32_NOI: + if (h != NULL && info->executable) + { + h->pointer_equality_needed = 1; + } + /* Fall through. */ case R_ARM_REL32: case R_ARM_REL32_NOI: case R_ARM_MOVW_PREL_NC: @@ -12812,7 +12876,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, && (sec->flags & SEC_ALLOC) != 0) { if (h == NULL - && (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI)) + && elf32_arm_howto_from_type (r_type)->pc_relative) { /* In shared libraries and relocatable executables, we treat local relative references as calls; @@ -12958,7 +13022,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, p->pc_count = 0; } - if (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI) + if (elf32_arm_howto_from_type (r_type)->pc_relative) p->pc_count += 1; p->count += 1; } @@ -12986,7 +13050,7 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info, while (again) { again = FALSE; - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { asection *o; @@ -13031,8 +13095,8 @@ elf32_arm_is_target_special_symbol (bfd * abfd ATTRIBUTE_UNUSED, asymbol * sym) static bfd_boolean arm_elf_find_function (bfd * abfd ATTRIBUTE_UNUSED, - asection * section, asymbol ** symbols, + asection * section, bfd_vma offset, const char ** filename_ptr, const char ** functionname_ptr) @@ -13093,31 +13157,33 @@ arm_elf_find_function (bfd * abfd ATTRIBUTE_UNUSED, static bfd_boolean elf32_arm_find_nearest_line (bfd * abfd, - asection * section, asymbol ** symbols, + asection * section, bfd_vma offset, const char ** filename_ptr, const char ** functionname_ptr, - unsigned int * line_ptr) + unsigned int * line_ptr, + unsigned int * discriminator_ptr) { bfd_boolean found = FALSE; - /* We skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain uses it. */ - - if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections, - section, symbols, offset, + if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, filename_ptr, functionname_ptr, - line_ptr, NULL, 0, + line_ptr, discriminator_ptr, + dwarf_debug_sections, 0, & elf_tdata (abfd)->dwarf2_find_line_info)) { if (!*functionname_ptr) - arm_elf_find_function (abfd, section, symbols, offset, + arm_elf_find_function (abfd, symbols, section, offset, *filename_ptr ? NULL : filename_ptr, functionname_ptr); return TRUE; } + /* Skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain + uses DWARF1. */ + if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, & found, filename_ptr, functionname_ptr, line_ptr, @@ -13130,7 +13196,7 @@ elf32_arm_find_nearest_line (bfd * abfd, if (symbols == NULL) return FALSE; - if (! arm_elf_find_function (abfd, section, symbols, offset, + if (! arm_elf_find_function (abfd, symbols, section, offset, filename_ptr, functionname_ptr)) return FALSE; @@ -13277,7 +13343,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info, h->needs_copy = 1; } - return _bfd_elf_adjust_dynamic_copy (h, s); + return _bfd_elf_adjust_dynamic_copy (info, h, s); } /* Allocate space in .plt, .got and associated reloc sections for @@ -13354,8 +13420,6 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) h->target_internal = ST_BRANCH_TO_ARM; } - htab->next_tls_desc_index++; - /* VxWorks executables have a second set of relocations for each PLT entry. They go in a separate relocation section, which is processed by the kernel loader. */ @@ -13539,12 +13603,12 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) if (info->shared || htab->root.is_relocatable_executable) { - /* The only relocs that use pc_count are R_ARM_REL32 and - R_ARM_REL32_NOI, which will appear on something like - ".long foo - .". We want calls to protected symbols to resolve - directly to the function rather than going via the plt. If people - want function pointer comparisons to work as expected then they - should avoid writing assembly like ".long foo - .". */ + /* Relocs that use pc_count are PC-relative forms, which will appear + on something like ".long foo - ." or "movw REG, foo - .". We want + calls to protected symbols to resolve directly to the function + rather than going via the plt. If people want function pointer + comparisons to work as expected then they should avoid writing + assembly like ".long foo - .". */ if (SYMBOL_CALLS_LOCAL (info, h)) { struct elf_dyn_relocs **pp; @@ -13724,7 +13788,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, /* Set up .got offsets for local syms, and space for local dynamic relocs. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { bfd_signed_vma *local_got; bfd_signed_vma *end_local_got; @@ -13901,7 +13965,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, elf_link_hash_traverse (& htab->root, allocate_dynrelocs_for_symbol, info); /* Here we rummage through the found bfds to collect glue information. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { if (! is_arm_elf (ibfd)) continue; @@ -14159,13 +14223,17 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, if (!h->def_regular) { /* Mark the symbol as undefined, rather than as defined in - the .plt section. Leave the value alone. */ + the .plt section. */ sym->st_shndx = SHN_UNDEF; - /* If the symbol is weak, we do need to clear the value. + /* If the symbol is weak we need to clear the value. Otherwise, the PLT entry would provide a definition for the symbol even if the symbol wasn't defined anywhere, - and so the symbol would never be NULL. */ - if (!h->ref_regular_nonweak) + and so the symbol would never be NULL. Leave the value if + there were any relocations where pointer equality matters + (this is a clue for the dynamic linker, to make function + pointer comparisons work between an application and shared + library). */ + if (!h->ref_regular_nonweak || !h->pointer_equality_needed) sym->st_value = 0; } else if (eh->is_iplt && eh->plt.noncall_refcount != 0) @@ -14659,7 +14727,7 @@ elf32_arm_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATT && ((i_ehdrp->e_type == ET_DYN) || (i_ehdrp->e_type == ET_EXEC))) { int abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_PROC, Tag_ABI_VFP_args); - if (abi) + if (abi == AEABI_VFP_args_vfp) i_ehdrp->e_flags |= EF_ARM_ABI_FLOAT_HARD; else i_ehdrp->e_flags |= EF_ARM_ABI_FLOAT_SOFT; @@ -14859,7 +14927,7 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi, { if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr)) return FALSE; - } + } else { bfd_boolean thumb_stub_p; @@ -15067,7 +15135,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, mapping symbols. */ for (input_bfd = info->input_bfds; input_bfd != NULL; - input_bfd = input_bfd->link_next) + input_bfd = input_bfd->link.next) { if ((input_bfd->flags & (BFD_LINKER_CREATED | HAS_SYMS)) == HAS_SYMS) for (osi.sec = input_bfd->sections; @@ -15225,7 +15293,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, elf_link_hash_traverse (&htab->root, elf32_arm_output_plt_map, &osi); for (input_bfd = info->input_bfds; input_bfd != NULL; - input_bfd = input_bfd->link_next) + input_bfd = input_bfd->link.next) { struct arm_local_iplt_info **local_iplt; unsigned int i, num_syms; @@ -15856,11 +15924,15 @@ elf32_arm_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, const char **namep, flagword *flagsp, asection **secp, bfd_vma *valp) { - if ((abfd->flags & DYNAMIC) == 0 - && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) + if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC + || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + && (abfd->flags & DYNAMIC) == 0 + && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; + if (elf32_arm_hash_table (info) == NULL) + return FALSE; + if (elf32_arm_hash_table (info)->vxworks_p && !elf_vxworks_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)) @@ -15900,13 +15972,212 @@ const struct elf_size_info elf32_arm_size_info = bfd_elf32_swap_reloca_out }; +static bfd_vma +read_code32 (const bfd *abfd, const bfd_byte *addr) +{ + /* V7 BE8 code is always little endian. */ + if ((elf_elfheader (abfd)->e_flags & EF_ARM_BE8) != 0) + return bfd_getl32 (addr); + + return bfd_get_32 (abfd, addr); +} + +static bfd_vma +read_code16 (const bfd *abfd, const bfd_byte *addr) +{ + /* V7 BE8 code is always little endian. */ + if ((elf_elfheader (abfd)->e_flags & EF_ARM_BE8) != 0) + return bfd_getl16 (addr); + + return bfd_get_16 (abfd, addr); +} + +/* Return size of plt0 entry starting at ADDR + or (bfd_vma) -1 if size can not be determined. */ + +static bfd_vma +elf32_arm_plt0_size (const bfd *abfd, const bfd_byte *addr) +{ + bfd_vma first_word; + bfd_vma plt0_size; + + first_word = read_code32 (abfd, addr); + + if (first_word == elf32_arm_plt0_entry[0]) + plt0_size = 4 * ARRAY_SIZE (elf32_arm_plt0_entry); + else if (first_word == elf32_thumb2_plt0_entry[0]) + plt0_size = 4 * ARRAY_SIZE (elf32_thumb2_plt0_entry); + else + /* We don't yet handle this PLT format. */ + return (bfd_vma) -1; + + return plt0_size; +} + +/* Return size of plt entry starting at offset OFFSET + of plt section located at address START + or (bfd_vma) -1 if size can not be determined. */ + +static bfd_vma +elf32_arm_plt_size (const bfd *abfd, const bfd_byte *start, bfd_vma offset) +{ + bfd_vma first_insn; + bfd_vma plt_size = 0; + const bfd_byte *addr = start + offset; + + /* PLT entry size if fixed on Thumb-only platforms. */ + if (read_code32 (abfd, start) == elf32_thumb2_plt0_entry[0]) + return 4 * ARRAY_SIZE (elf32_thumb2_plt_entry); + + /* Respect Thumb stub if necessary. */ + if (read_code16 (abfd, addr) == elf32_arm_plt_thumb_stub[0]) + { + plt_size += 2 * ARRAY_SIZE(elf32_arm_plt_thumb_stub); + } + + /* Strip immediate from first add. */ + first_insn = read_code32 (abfd, addr + plt_size) & 0xffffff00; + +#ifdef FOUR_WORD_PLT + if (first_insn == elf32_arm_plt_entry[0]) + plt_size += 4 * ARRAY_SIZE (elf32_arm_plt_entry); +#else + if (first_insn == elf32_arm_plt_entry_long[0]) + plt_size += 4 * ARRAY_SIZE (elf32_arm_plt_entry_long); + else if (first_insn == elf32_arm_plt_entry_short[0]) + plt_size += 4 * ARRAY_SIZE (elf32_arm_plt_entry_short); +#endif + else + /* We don't yet handle this PLT format. */ + return (bfd_vma) -1; + + return plt_size; +} + +/* Implementation is shamelessly borrowed from _bfd_elf_get_synthetic_symtab. */ + +static long +elf32_arm_get_synthetic_symtab (bfd *abfd, + long symcount ATTRIBUTE_UNUSED, + asymbol **syms ATTRIBUTE_UNUSED, + long dynsymcount, + asymbol **dynsyms, + asymbol **ret) +{ + asection *relplt; + asymbol *s; + arelent *p; + long count, i, n; + size_t size; + Elf_Internal_Shdr *hdr; + char *names; + asection *plt; + bfd_vma offset; + bfd_byte *data; + + *ret = NULL; + + if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0) + return 0; + + if (dynsymcount <= 0) + return 0; + + relplt = bfd_get_section_by_name (abfd, ".rel.plt"); + if (relplt == NULL) + return 0; + + hdr = &elf_section_data (relplt)->this_hdr; + if (hdr->sh_link != elf_dynsymtab (abfd) + || (hdr->sh_type != SHT_REL && hdr->sh_type != SHT_RELA)) + return 0; + + plt = bfd_get_section_by_name (abfd, ".plt"); + if (plt == NULL) + return 0; + + if (!elf32_arm_size_info.slurp_reloc_table (abfd, relplt, dynsyms, TRUE)) + return -1; + + data = plt->contents; + if (data == NULL) + { + if (!bfd_get_full_section_contents(abfd, (asection *) plt, &data) || data == NULL) + return -1; + bfd_cache_section_contents((asection *) plt, data); + } + + count = relplt->size / hdr->sh_entsize; + size = count * sizeof (asymbol); + p = relplt->relocation; + for (i = 0; i < count; i++, p += elf32_arm_size_info.int_rels_per_ext_rel) + { + size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt"); + if (p->addend != 0) + size += sizeof ("+0x") - 1 + 8; + } + + s = *ret = (asymbol *) bfd_malloc (size); + if (s == NULL) + return -1; + + offset = elf32_arm_plt0_size (abfd, data); + if (offset == (bfd_vma) -1) + return -1; + + names = (char *) (s + count); + p = relplt->relocation; + n = 0; + for (i = 0; i < count; i++, p += elf32_arm_size_info.int_rels_per_ext_rel) + { + size_t len; + + bfd_vma plt_size = elf32_arm_plt_size (abfd, data, offset); + if (plt_size == (bfd_vma) -1) + break; + + *s = **p->sym_ptr_ptr; + /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since + we are defining a symbol, ensure one of them is set. */ + if ((s->flags & BSF_LOCAL) == 0) + s->flags |= BSF_GLOBAL; + s->flags |= BSF_SYNTHETIC; + s->section = plt; + s->value = offset; + s->name = names; + s->udata.p = NULL; + len = strlen ((*p->sym_ptr_ptr)->name); + memcpy (names, (*p->sym_ptr_ptr)->name, len); + names += len; + if (p->addend != 0) + { + char buf[30], *a; + + memcpy (names, "+0x", sizeof ("+0x") - 1); + names += sizeof ("+0x") - 1; + bfd_sprintf_vma (abfd, buf, p->addend); + for (a = buf; *a == '0'; ++a) + ; + len = strlen (a); + memcpy (names, a, len); + names += len; + } + memcpy (names, "@plt", sizeof ("@plt")); + names += sizeof ("@plt"); + ++s, ++n; + offset += plt_size; + } + + return n; +} + #define ELF_ARCH bfd_arch_arm #define ELF_TARGET_ID ARM_ELF_DATA #define ELF_MACHINE_CODE EM_ARM #ifdef __QNXTARGET__ #define ELF_MAXPAGESIZE 0x1000 #else -#define ELF_MAXPAGESIZE 0x8000 +#define ELF_MAXPAGESIZE 0x10000 #endif #define ELF_MINPAGESIZE 0x1000 #define ELF_COMMONPAGESIZE 0x1000 @@ -15918,7 +16189,6 @@ const struct elf_size_info elf32_arm_size_info = #define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags #define bfd_elf32_bfd_print_private_bfd_data elf32_arm_print_private_bfd_data #define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create -#define bfd_elf32_bfd_link_hash_table_free elf32_arm_hash_table_free #define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup #define bfd_elf32_bfd_reloc_name_lookup elf32_arm_reloc_name_lookup #define bfd_elf32_find_nearest_line elf32_arm_find_nearest_line @@ -15926,6 +16196,7 @@ const struct elf_size_info elf32_arm_size_info = #define bfd_elf32_new_section_hook elf32_arm_new_section_hook #define bfd_elf32_bfd_is_target_special_symbol elf32_arm_is_target_special_symbol #define bfd_elf32_bfd_final_link elf32_arm_final_link +#define bfd_elf32_get_synthetic_symtab elf32_arm_get_synthetic_symtab #define elf_backend_get_symbol_type elf32_arm_get_symbol_type #define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook @@ -15982,11 +16253,11 @@ const struct elf_size_info elf32_arm_size_info = /* Native Client targets. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_littlearm_nacl_vec +#define TARGET_LITTLE_SYM arm_elf32_nacl_le_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-littlearm-nacl" #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_bigarm_nacl_vec +#define TARGET_BIG_SYM arm_elf32_nacl_be_vec #undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-bigarm-nacl" @@ -16030,23 +16301,32 @@ elf32_arm_nacl_final_write_processing (bfd *abfd, bfd_boolean linker) nacl_final_write_processing (abfd, linker); } +static bfd_vma +elf32_arm_nacl_plt_sym_val (bfd_vma i, const asection *plt, + const arelent *rel ATTRIBUTE_UNUSED) +{ + return plt->vma + + 4 * (ARRAY_SIZE (elf32_arm_nacl_plt0_entry) + + i * ARRAY_SIZE (elf32_arm_nacl_plt_entry)); +} #undef elf32_bed -#define elf32_bed elf32_arm_nacl_bed +#define elf32_bed elf32_arm_nacl_bed #undef bfd_elf32_bfd_link_hash_table_create #define bfd_elf32_bfd_link_hash_table_create \ elf32_arm_nacl_link_hash_table_create #undef elf_backend_plt_alignment -#define elf_backend_plt_alignment 4 +#define elf_backend_plt_alignment 4 #undef elf_backend_modify_segment_map #define elf_backend_modify_segment_map elf32_arm_nacl_modify_segment_map #undef elf_backend_modify_program_headers #define elf_backend_modify_program_headers nacl_modify_program_headers #undef elf_backend_final_write_processing #define elf_backend_final_write_processing elf32_arm_nacl_final_write_processing +#undef bfd_elf32_get_synthetic_symtab +#undef elf_backend_plt_sym_val +#define elf_backend_plt_sym_val elf32_arm_nacl_plt_sym_val -#undef ELF_MAXPAGESIZE -#define ELF_MAXPAGESIZE 0x10000 #undef ELF_MINPAGESIZE #undef ELF_COMMONPAGESIZE @@ -16069,11 +16349,11 @@ elf32_arm_nacl_final_write_processing (bfd *abfd, bfd_boolean linker) /* VxWorks Targets. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_littlearm_vxworks_vec +#define TARGET_LITTLE_SYM arm_elf32_vxworks_le_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-littlearm-vxworks" #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_bigarm_vxworks_vec +#define TARGET_BIG_SYM arm_elf32_vxworks_be_vec #undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-bigarm-vxworks" @@ -16355,11 +16635,11 @@ elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd) /* Symbian OS Targets. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_littlearm_symbian_vec +#define TARGET_LITTLE_SYM arm_elf32_symbian_le_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-littlearm-symbian" #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_bigarm_symbian_vec +#define TARGET_BIG_SYM arm_elf32_symbian_be_vec #undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-bigarm-symbian"