X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bfd%2Felf32-arm.c;h=cce796dafd9457c520799ada452b2548a1f6c266;hb=refs%2Fheads%2Fsandbox%2Fvbarinov%2Ftizen_6_base;hp=a8d57019c855e192eb6f997554295f562d15f18d;hpb=3a1bb98c3c4f983b950fbaf2797ddcd21fcb5211;p=external%2Fbinutils.git diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index a8d5701..cce796d 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -2300,6 +2300,8 @@ typedef unsigned short int insn16; #define CMSE_PREFIX "__acle_se_" +#define CMSE_STUB_NAME ".gnu.sgstubs" + /* The name of the dynamic interpreter. This is put in the .interp section. */ #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" @@ -2327,6 +2329,11 @@ static const unsigned long dl_tlsdesc_lazy_trampoline [] = 0x00000018, /* 4: .word _GLOBAL_OFFSET_TABLE_ - 2b - 8 */ }; +/* NOTE: [Thumb nop sequence] + When adding code that transitions from Thumb to Arm the instruction that + should be used for the alignment padding should be 0xe7fd (b .-2) instead of + a nop for performance reasons. */ + /* ARM FDPIC PLT entry. */ /* The last 5 words contain PLT lazy fragment code and data. */ static const bfd_vma elf32_arm_fdpic_plt_entry [] = @@ -2444,8 +2451,8 @@ static const bfd_vma elf32_thumb2_plt_entry [] = 0x0c00f240, /* movw ip, #0xNNNN */ 0x0c00f2c0, /* movt ip, #0xNNNN */ 0xf8dc44fc, /* add ip, pc */ - 0xbf00f000 /* ldr.w pc, [ip] */ - /* nop */ + 0xe7fdf000 /* ldr.w pc, [ip] */ + /* b .-2 */ }; /* The format of the first entry in the procedure linkage table @@ -2485,7 +2492,7 @@ static const bfd_vma elf32_arm_vxworks_shared_plt_entry[] = static const bfd_vma elf32_arm_plt_thumb_stub [] = { 0x4778, /* bx pc */ - 0x46c0 /* nop */ + 0xe7fd /* b .-2 */ }; /* The entries in a PLT when using a DLL-based target with multiple @@ -2572,6 +2579,8 @@ typedef struct int reloc_addend; } insn_sequence; +/* See note [Thumb nop sequence] when adding a veneer. */ + /* Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx to reach the stub if necessary. */ static const insn_sequence elf32_arm_stub_long_branch_any_any[] = @@ -2622,7 +2631,7 @@ static const insn_sequence elf32_arm_stub_long_branch_thumb2_only_pure[] = static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb[] = { THUMB16_INSN (0x4778), /* bx pc */ - THUMB16_INSN (0x46c0), /* nop */ + THUMB16_INSN (0xe7fd), /* b .-2 */ ARM_INSN (0xe59fc000), /* ldr ip, [pc, #0] */ ARM_INSN (0xe12fff1c), /* bx ip */ DATA_WORD (0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */ @@ -2633,7 +2642,7 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb[] = static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] = { THUMB16_INSN (0x4778), /* bx pc */ - THUMB16_INSN (0x46c0), /* nop */ + THUMB16_INSN (0xe7fd), /* b .-2 */ ARM_INSN (0xe51ff004), /* ldr pc, [pc, #-4] */ DATA_WORD (0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */ }; @@ -2643,7 +2652,7 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] = static const insn_sequence elf32_arm_stub_short_branch_v4t_thumb_arm[] = { THUMB16_INSN (0x4778), /* bx pc */ - THUMB16_INSN (0x46c0), /* nop */ + THUMB16_INSN (0xe7fd), /* b .-2 */ ARM_REL_INSN (0xea000000, -8), /* b (X-8) */ }; @@ -2681,7 +2690,7 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] = static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] = { THUMB16_INSN (0x4778), /* bx pc */ - THUMB16_INSN (0x46c0), /* nop */ + THUMB16_INSN (0xe7fd), /* b .-2 */ ARM_INSN (0xe59fc000), /* ldr ip, [pc, #0] */ ARM_INSN (0xe08cf00f), /* add pc, ip, pc */ DATA_WORD (0, R_ARM_REL32, -4), /* dcd R_ARM_REL32(X) */ @@ -2705,7 +2714,7 @@ static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] = static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] = { THUMB16_INSN (0x4778), /* bx pc */ - THUMB16_INSN (0x46c0), /* nop */ + THUMB16_INSN (0xe7fd), /* b .-2 */ ARM_INSN (0xe59fc004), /* ldr ip, [pc, #4] */ ARM_INSN (0xe08fc00c), /* add ip, pc, ip */ ARM_INSN (0xe12fff1c), /* bx ip */ @@ -2726,7 +2735,7 @@ static const insn_sequence elf32_arm_stub_long_branch_any_tls_pic[] = static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_tls_pic[] = { THUMB16_INSN (0x4778), /* bx pc */ - THUMB16_INSN (0x46c0), /* nop */ + THUMB16_INSN (0xe7fd), /* b .-2 */ ARM_INSN (0xe59f1000), /* ldr r1, [pc, #0] */ ARM_INSN (0xe081f00f), /* add pc, r1, pc */ DATA_WORD (0, R_ARM_REL32, -4), /* dcd R_ARM_REL32(X) */ @@ -4583,6 +4592,27 @@ elf32_arm_get_stub_entry (const asection *input_section, if ((input_section->flags & SEC_CODE) == 0) return NULL; + /* If the input section is the CMSE stubs one and it needs a long + branch stub to reach it's final destination, give up with an + error message: this is not supported. See PR ld/24709. */ + if (!strncmp (input_section->name, CMSE_STUB_NAME, strlen(CMSE_STUB_NAME))) + { + bfd *output_bfd = htab->obfd; + asection *out_sec = bfd_get_section_by_name (output_bfd, CMSE_STUB_NAME); + + _bfd_error_handler (_("ERROR: CMSE stub (%s section) too far " + "(%#" PRIx64 ") from destination (%#" PRIx64 ")"), + CMSE_STUB_NAME, + (uint64_t)out_sec->output_section->vma + + out_sec->output_offset, + (uint64_t)sym_sec->output_section->vma + + sym_sec->output_offset + + h->root.root.u.def.value); + /* Exit, rather than leave incompletely processed + relocations. */ + xexit(1); + } + /* If this input section is part of a group of sections sharing one stub section, then use the id of the first section in the group. Stub names need to include a section id, as there may well be @@ -4676,7 +4706,7 @@ arm_dedicated_stub_output_section_name (enum elf32_arm_stub_type stub_type) switch (stub_type) { case arm_stub_cmse_branch_thumb_only: - return ".gnu.sgstubs"; + return CMSE_STUB_NAME; default: BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type)); @@ -4881,7 +4911,7 @@ elf32_arm_tls_transition (struct bfd_link_info *info, int r_type, { int is_local = (h == NULL); - if (bfd_link_pic (info) + if (bfd_link_dll (info) || (h && h->root.type == bfd_link_hash_undefweak)) return r_type; @@ -5972,12 +6002,12 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab, if (i < ext_start) { cmse_sym = &local_syms[i]; - /* Not a special symbol. */ - if (!ARM_GET_SYM_CMSE_SPCL (cmse_sym->st_target_internal)) - continue; sym_name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, cmse_sym->st_name); + if (!sym_name || !CONST_STRNEQ (sym_name, CMSE_PREFIX)) + continue; + /* Special symbol with local binding. */ cmse_invalid = TRUE; } @@ -5985,9 +6015,7 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab, { cmse_hash = elf32_arm_hash_entry (sym_hashes[i - ext_start]); sym_name = (char *) cmse_hash->root.root.root.string; - - /* Not a special symbol. */ - if (!ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal)) + if (!CONST_STRNEQ (sym_name, CMSE_PREFIX)) continue; /* Special symbol has incorrect binding or type. */ @@ -7222,7 +7250,7 @@ arm_allocate_glue_section_space (bfd * abfd, bfd_size_type size, const char * na s = bfd_get_linker_section (abfd, name); BFD_ASSERT (s != NULL); - contents = (bfd_byte *) bfd_alloc (abfd, size); + contents = (bfd_byte *) bfd_zalloc (abfd, size); BFD_ASSERT (s->size == size); s->contents = contents; @@ -10293,59 +10321,6 @@ identify_add_or_sub (bfd_vma insn) return 0; } -/* Helper function to compute the Addend for Armv8.1-M Mainline relocations. */ -static bfd_vma -get_value_helper (bfd_vma plt_offset, - asection *splt, - asection *input_section, - asection *sym_sec, - struct elf_link_hash_entry * h, - struct bfd_link_info *info, - bfd *input_bfd, - Elf_Internal_Rela *rel, - const char *sym_name, - unsigned char st_type, - struct elf32_arm_link_hash_table *globals, - bfd_boolean *unresolved_reloc_p) -{ - bfd_vma value = 0; - enum arm_st_branch_type branch_type; - 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 - = (struct elf32_arm_link_hash_entry *)h; - - - if (plt_offset != (bfd_vma) -1) - { - value = (splt->output_section->vma - + splt->output_offset - + plt_offset); - value -= PLT_THUMB_STUB_SIZE; - *unresolved_reloc_p = FALSE; - } - - 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); - } - } - return value; -} - /* Perform a relocation as part of a final link. */ static bfd_reloc_status_type @@ -11722,7 +11697,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, { /* If we don't know the module number, create a relocation for it. */ - if (bfd_link_pic (info)) + if (bfd_link_dll (info)) { Elf_Internal_Rela outrel; @@ -11826,7 +11801,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, now, and emit any relocations. If both an IE GOT and a GD GOT are necessary, we emit the GD first. */ - if ((bfd_link_pic (info) || indx != 0) + if ((bfd_link_dll (info) || indx != 0) && (h == NULL || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT && !resolved_to_zero) @@ -11843,7 +11818,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* We should have relaxed, unless this is an undefined weak symbol. */ BFD_ASSERT ((h && (h->root.type == bfd_link_hash_undefweak)) - || bfd_link_pic (info)); + || bfd_link_dll (info)); BFD_ASSERT (globals->sgotplt_jump_table_size + offplt + 8 <= globals->root.sgotplt->size); @@ -12049,9 +12024,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, unsigned long data, insn; unsigned thumb; - data = bfd_get_32 (input_bfd, hit_data); + data = bfd_get_signed_32 (input_bfd, hit_data); thumb = data & 1; - data &= ~1u; + data &= ~1ul; if (thumb) { @@ -12968,14 +12943,10 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, addend |= (immC << 1); addend |= 1; /* Sign extend. */ - addend = (addend & 0x10000) ? addend - (1 << 17) : addend; + signed_addend = (addend & 0x10000) ? addend - (1 << 17) : addend; } - value = get_value_helper (plt_offset, splt, input_section, sym_sec, h, - info, input_bfd, rel, sym_name, st_type, - globals, unresolved_reloc_p); - - relocation = value + addend; + relocation = value + signed_addend; relocation -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); @@ -13014,13 +12985,10 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, addend |= 1; /* Sign extend. */ addend = (addend & 0x1000) ? addend - (1 << 13) : addend; + signed_addend = addend; } - value = get_value_helper (plt_offset, splt, input_section, sym_sec, h, - info, input_bfd, rel, sym_name, st_type, - globals, unresolved_reloc_p); - - relocation = value + addend; + relocation = value + signed_addend; relocation -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); @@ -13059,13 +13027,10 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, addend |= 1; /* Sign extend. */ addend = (addend & 0x40000) ? addend - (1 << 19) : addend; + signed_addend = addend; } - value = get_value_helper (plt_offset, splt, input_section, sym_sec, h, - info, input_bfd, rel, sym_name, st_type, - globals, unresolved_reloc_p); - - relocation = value + addend; + relocation = value + signed_addend; relocation -= (input_section->output_section->vma + input_section->output_offset + rel->r_offset); @@ -14713,6 +14678,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, struct bfd_link_info *info) case Tag_CPU_unaligned_access: case Tag_T2EE_use: case Tag_MPextension_use: + case Tag_MVE_arch: /* Use the largest value specified. */ if (in_attr[i].i > out_attr[i].i) out_attr[i].i = in_attr[i].i; @@ -15852,7 +15818,7 @@ elf32_arm_update_relocs (asection *o, eadi = get_arm_elf_section_data (i); edit_list = eadi->u.exidx.unwind_edit_list; edit_tail = eadi->u.exidx.unwind_edit_tail; - offset = o->vma + i->output_offset; + offset = i->output_offset; if (eadi->elf.rel.hdr && eadi->elf.rel.hdr->sh_entsize == rel_hdr->sh_entsize) @@ -15965,6 +15931,8 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info, struct elf_link_hash_entry **sym_hashes; struct elf32_arm_link_hash_entry *cmse_hash; bfd_boolean again, is_v8m, first_bfd_browse = TRUE; + bfd_boolean debug_sec_need_to_be_marked = FALSE; + asection *isec; _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook); @@ -16020,13 +15988,31 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info, /* Assume it is a special symbol. If not, cmse_scan will warn about it and user can do something about it. */ - if (ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal)) + if (CONST_STRNEQ (cmse_hash->root.root.root.string, + CMSE_PREFIX)) { cmse_sec = cmse_hash->root.root.u.def.section; if (!cmse_sec->gc_mark && !_bfd_elf_gc_mark (info, cmse_sec, gc_mark_hook)) return FALSE; + /* The debug sections related to these secure entry + functions are marked on enabling below flag. */ + debug_sec_need_to_be_marked = TRUE; + } + } + + if (debug_sec_need_to_be_marked) + { + /* Looping over all the sections of the object file containing + Armv8-M secure entry functions and marking all the debug + sections. */ + for (isec = sub->sections; isec != NULL; isec = isec->next) + { + /* If not a debug sections, skip it. */ + if (!isec->gc_mark && (isec->flags & SEC_DEBUGGING)) + isec->gc_mark = 1 ; } + debug_sec_need_to_be_marked = FALSE; } } } @@ -16045,12 +16031,12 @@ elf32_arm_is_target_special_symbol (bfd * abfd ATTRIBUTE_UNUSED, asymbol * sym) BFD_ARM_SPECIAL_SYM_TYPE_ANY); } -/* This is a copy of elf_find_function() from elf.c except that +/* This is a version of _bfd_elf_find_function() from dwarf2.c except that ARM mapping symbols are ignored when looking for function names and STT_ARM_TFUNC is considered to a function type. */ static bfd_boolean -arm_elf_find_function (bfd * abfd ATTRIBUTE_UNUSED, +arm_elf_find_function (bfd * abfd, asymbol ** symbols, asection * section, bfd_vma offset, @@ -16062,6 +16048,12 @@ arm_elf_find_function (bfd * abfd ATTRIBUTE_UNUSED, bfd_vma low_func = 0; asymbol ** p; + if (symbols == NULL) + return FALSE; + + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return FALSE; + for (p = symbols; *p != NULL; p++) { elf_symbol_type *q; @@ -16126,7 +16118,7 @@ elf32_arm_find_nearest_line (bfd * abfd, if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, filename_ptr, functionname_ptr, line_ptr, discriminator_ptr, - dwarf_debug_sections, 0, + dwarf_debug_sections, & elf_tdata (abfd)->dwarf2_find_line_info)) { if (!*functionname_ptr) @@ -16499,7 +16491,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) indx = h->dynindx; if (tls_type != GOT_NORMAL - && (bfd_link_pic (info) || indx != 0) + && (bfd_link_dll (info) || indx != 0) && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) { @@ -17929,11 +17921,18 @@ elf32_arm_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, } static void -elf32_arm_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) +arm_final_write_processing (bfd *abfd) { bfd_arm_update_notes (abfd, ARM_NOTE_SECTION); } +static bfd_boolean +elf32_arm_final_write_processing (bfd *abfd) +{ + arm_final_write_processing (abfd); + return _bfd_elf_final_write_processing (abfd); +} + /* Return TRUE if this is an unwinding table entry. */ static bfd_boolean @@ -18610,9 +18609,6 @@ elf32_arm_filter_cmse_symbols (bfd *abfd ATTRIBUTE_UNUSED, || cmse_hash->root.type != STT_FUNC) continue; - if (!ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal)) - continue; - syms[dst_count++] = sym; } free (cmse_name); @@ -19693,9 +19689,6 @@ elf32_arm_write_section (bfd *output_bfd, bfd_vma branch_to_veneer = stm32l4xx_errnode->u.b.veneer->vma - stm32l4xx_errnode->vma; - /* The instruction is before the label. */ - target -= 4; - if ((signed) branch_to_veneer < -(1 << 24) || (signed) branch_to_veneer >= (1 << 24)) { @@ -19713,15 +19706,15 @@ elf32_arm_write_section (bfd *output_bfd, output_bfd, (uint64_t) (stm32l4xx_errnode->vma - 4), (int64_t) out_of_range); - - /* Don't leave contents uninitialised. */ - bfd_put_16 (output_bfd, 0, contents + target); continue; } insn = create_instruction_branch_absolute (stm32l4xx_errnode->u.b.veneer->vma - stm32l4xx_errnode->vma); + /* The instruction is before the label. */ + target -= 4; + put_thumb2_insn (globals, output_bfd, (bfd_vma) insn, contents + target); } @@ -19938,9 +19931,6 @@ elf32_arm_swap_symbol_in (bfd * abfd, const void *pshn, Elf_Internal_Sym *dst) { - Elf_Internal_Shdr *symtab_hdr; - const char *name = NULL; - if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst)) return FALSE; dst->st_target_internal = 0; @@ -19969,13 +19959,6 @@ elf32_arm_swap_symbol_in (bfd * abfd, else ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_UNKNOWN); - /* Mark CMSE special symbols. */ - symtab_hdr = & elf_symtab_hdr (abfd); - if (symtab_hdr->sh_size) - name = bfd_elf_sym_name (abfd, symtab_hdr, dst, NULL); - if (name && CONST_STRNEQ (name, CMSE_PREFIX)) - ARM_SET_SYM_CMSE_SPCL (dst->st_target_internal); - return TRUE; } @@ -20610,11 +20593,11 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info) && nacl_modify_segment_map (abfd, info)); } -static void -elf32_arm_nacl_final_write_processing (bfd *abfd, bfd_boolean linker) +static bfd_boolean +elf32_arm_nacl_final_write_processing (bfd *abfd) { - elf32_arm_final_write_processing (abfd, linker); - nacl_final_write_processing (abfd, linker); + arm_final_write_processing (abfd); + return nacl_final_write_processing (abfd); } static bfd_vma @@ -20765,11 +20748,11 @@ elf32_arm_vxworks_link_hash_table_create (bfd *abfd) return ret; } -static void -elf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker) +static bfd_boolean +elf32_arm_vxworks_final_write_processing (bfd *abfd) { - elf32_arm_final_write_processing (abfd, linker); - elf_vxworks_final_write_processing (abfd, linker); + arm_final_write_processing (abfd); + return elf_vxworks_final_write_processing (abfd); } #undef elf32_bed