X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-arm.c;h=e2f8a9607ae65420f56c943a91b99977b18544f0;hb=95830fd17d6ae253d8f6c2595188cadd59058799;hp=826dd7e0be2b3a66a6d17feaaba210c8f4e06406;hpb=466911340d972c2ecad9f56874735a4ced97d6ff;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 826dd7e0be..e2f8a9607a 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -23,6 +23,7 @@ #include #include "bfd.h" +#include "bfd_stdint.h" #include "libiberty.h" #include "libbfd.h" #include "elf-bfd.h" @@ -62,6 +63,9 @@ #define ARM_ELF_ABI_VERSION 0 #define ARM_ELF_OS_ABI_VERSION ELFOSABI_ARM +/* The Adjusted Place, as defined by AAELF. */ +#define Pa(X) ((X) & 0xfffffffc) + static bfd_boolean elf32_arm_write_section (bfd *output_bfd, struct bfd_link_info *link_info, asection *sec, @@ -2208,21 +2212,21 @@ static const bfd_vma elf32_arm_nacl_plt0_entry [] = 0xe08cc00f, /* add ip, ip, pc */ 0xe52dc008, /* str ip, [sp, #-8]! */ /* Second bundle: */ - 0xe7dfcf1f, /* bfc ip, #30, #2 */ - 0xe59cc000, /* ldr ip, [ip] */ + 0xe3ccc103, /* bic ip, ip, #0xc0000000 */ + 0xe59cc000, /* ldr ip, [ip] */ 0xe3ccc13f, /* bic ip, ip, #0xc000000f */ - 0xe12fff1c, /* bx ip */ + 0xe12fff1c, /* bx ip */ /* Third bundle: */ - 0xe320f000, /* nop */ - 0xe320f000, /* nop */ - 0xe320f000, /* nop */ + 0xe320f000, /* nop */ + 0xe320f000, /* nop */ + 0xe320f000, /* nop */ /* .Lplt_tail: */ 0xe50dc004, /* str ip, [sp, #-4] */ /* Fourth bundle: */ - 0xe7dfcf1f, /* bfc ip, #30, #2 */ - 0xe59cc000, /* ldr ip, [ip] */ + 0xe3ccc103, /* bic ip, ip, #0xc0000000 */ + 0xe59cc000, /* ldr ip, [ip] */ 0xe3ccc13f, /* bic ip, ip, #0xc000000f */ - 0xe12fff1c, /* bx ip */ + 0xe12fff1c, /* bx ip */ }; #define ARM_NACL_PLT_TAIL_OFFSET (11 * 4) @@ -3255,8 +3259,8 @@ create_ifunc_sections (struct bfd_link_info *info) if (htab->root.iplt == NULL) { - s = bfd_make_section_with_flags (dynobj, ".iplt", - flags | SEC_READONLY | SEC_CODE); + s = bfd_make_section_anyway_with_flags (dynobj, ".iplt", + flags | SEC_READONLY | SEC_CODE); if (s == NULL || !bfd_set_section_alignment (dynobj, s, bed->plt_alignment)) return FALSE; @@ -3265,8 +3269,9 @@ create_ifunc_sections (struct bfd_link_info *info) if (htab->root.irelplt == NULL) { - s = bfd_make_section_with_flags (dynobj, RELOC_SECTION (htab, ".iplt"), - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (dynobj, + RELOC_SECTION (htab, ".iplt"), + flags | SEC_READONLY); if (s == NULL || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align)) return FALSE; @@ -3275,7 +3280,7 @@ create_ifunc_sections (struct bfd_link_info *info) if (htab->root.igotplt == NULL) { - s = bfd_make_section_with_flags (dynobj, ".igot.plt", flags); + s = bfd_make_section_anyway_with_flags (dynobj, ".igot.plt", flags); if (s == NULL || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align)) return FALSE; @@ -3303,10 +3308,10 @@ elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) if (!_bfd_elf_create_dynamic_sections (dynobj, info)) return FALSE; - htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); + htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); if (!info->shared) - htab->srelbss = bfd_get_section_by_name (dynobj, - RELOC_SECTION (htab, ".bss")); + htab->srelbss = bfd_get_linker_section (dynobj, + RELOC_SECTION (htab, ".bss")); if (htab->vxworks_p) { @@ -4982,6 +4987,9 @@ elf32_arm_size_stubs (bfd *output_bfd, asection *section; Elf_Internal_Sym *local_syms = NULL; + if (!is_arm_elf (input_bfd)) + continue; + num_a8_relocs = 0; /* We'll need the symbol table in a second. */ @@ -5653,7 +5661,7 @@ arm_allocate_glue_section_space (bfd * abfd, bfd_size_type size, const char * na /* Do not include empty glue sections in the output. */ if (abfd != NULL) { - s = bfd_get_section_by_name (abfd, name); + s = bfd_get_linker_section (abfd, name); if (s != NULL) s->flags |= SEC_EXCLUDE; } @@ -5662,7 +5670,7 @@ arm_allocate_glue_section_space (bfd * abfd, bfd_size_type size, const char * na BFD_ASSERT (abfd != NULL); - s = bfd_get_section_by_name (abfd, name); + s = bfd_get_linker_section (abfd, name); BFD_ASSERT (s != NULL); contents = (bfd_byte *) bfd_alloc (abfd, size); @@ -5718,7 +5726,7 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info, BFD_ASSERT (globals != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL); - s = bfd_get_section_by_name + s = bfd_get_linker_section (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); @@ -5794,7 +5802,7 @@ record_arm_bx_glue (struct bfd_link_info * link_info, int reg) if (globals->bx_glue_offset[reg]) return; - s = bfd_get_section_by_name + s = bfd_get_linker_section (globals->bfd_of_glue_owner, ARM_BX_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); @@ -5885,7 +5893,7 @@ record_vfp11_erratum_veneer (struct bfd_link_info *link_info, BFD_ASSERT (hash_table != NULL); BFD_ASSERT (hash_table->bfd_of_glue_owner != NULL); - s = bfd_get_section_by_name + s = bfd_get_linker_section (hash_table->bfd_of_glue_owner, VFP11_ERRATUM_VENEER_SECTION_NAME); sec_data = elf32_arm_section_data (s); @@ -5992,12 +6000,12 @@ arm_make_glue_section (bfd * abfd, const char * name) { asection * sec; - sec = bfd_get_section_by_name (abfd, name); + sec = bfd_get_linker_section (abfd, name); if (sec != NULL) /* Already made. */ return TRUE; - sec = bfd_make_section_with_flags (abfd, name, ARM_GLUE_SECTION_FLAGS); + sec = bfd_make_section_anyway_with_flags (abfd, name, ARM_GLUE_SECTION_FLAGS); if (sec == NULL || !bfd_set_section_alignment (abfd, sec, 2)) @@ -7017,8 +7025,8 @@ elf32_thumb_to_arm_stub (struct bfd_link_info * info, my_offset = myh->root.u.def.value; - s = bfd_get_section_by_name (globals->bfd_of_glue_owner, - THUMB2ARM_GLUE_SECTION_NAME); + s = bfd_get_linker_section (globals->bfd_of_glue_owner, + THUMB2ARM_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); BFD_ASSERT (s->contents != NULL); @@ -7207,8 +7215,8 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info, BFD_ASSERT (globals != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL); - s = bfd_get_section_by_name (globals->bfd_of_glue_owner, - ARM2THUMB_GLUE_SECTION_NAME); + s = bfd_get_linker_section (globals->bfd_of_glue_owner, + ARM2THUMB_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); BFD_ASSERT (s->contents != NULL); BFD_ASSERT (s->output_section != NULL); @@ -7261,8 +7269,8 @@ elf32_arm_to_thumb_export_stub (struct elf_link_hash_entry *h, void * inf) BFD_ASSERT (globals != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL); - s = bfd_get_section_by_name (globals->bfd_of_glue_owner, - ARM2THUMB_GLUE_SECTION_NAME); + s = bfd_get_linker_section (globals->bfd_of_glue_owner, + ARM2THUMB_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); BFD_ASSERT (s->contents != NULL); BFD_ASSERT (s->output_section != NULL); @@ -7296,8 +7304,8 @@ elf32_arm_bx_glue (struct bfd_link_info * info, int reg) BFD_ASSERT (globals != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL); - s = bfd_get_section_by_name (globals->bfd_of_glue_owner, - ARM_BX_GLUE_SECTION_NAME); + s = bfd_get_linker_section (globals->bfd_of_glue_owner, + ARM_BX_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); BFD_ASSERT (s->contents != NULL); BFD_ASSERT (s->output_section != NULL); @@ -7629,7 +7637,7 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, { /* Calculate the displacement between the PLT slot and the common tail that's part of the special initial PLT slot. */ - bfd_vma tail_displacement + int32_t tail_displacement = ((splt->output_section->vma + splt->output_offset + ARM_NACL_PLT_TAIL_OFFSET) - (plt_address + htab->plt_entry_size + 4)); @@ -7642,7 +7650,8 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, /* Calculate the displacement between the PLT slot and the entry in the GOT. The offset accounts for the value produced by adding to pc in the penultimate instruction of the PLT stub. */ - got_displacement = got_address - (plt_address + htab->plt_entry_size); + got_displacement = (got_address + - (plt_address + htab->plt_entry_size)); /* NaCl does not support interworking at all. */ BFD_ASSERT (!elf32_arm_plt_needs_thumb_stub_p (info, arm_plt)); @@ -8616,9 +8625,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, } relocation = value + signed_addend; - relocation -= (input_section->output_section->vma - + input_section->output_offset - + rel->r_offset); + relocation -= Pa (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset); value = abs (relocation); @@ -8648,12 +8657,12 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, insn = bfd_get_16 (input_bfd, hit_data); if (globals->use_rel) - addend = (insn & 0x00ff) << 2; + addend = ((((insn & 0x00ff) << 2) + 4) & 0x3ff) -4; relocation = value + addend; - relocation -= (input_section->output_section->vma - + input_section->output_offset - + rel->r_offset); + relocation -= Pa (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset); value = abs (relocation); @@ -8688,9 +8697,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, } relocation = value + signed_addend; - relocation -= (input_section->output_section->vma - + input_section->output_offset - + rel->r_offset); + relocation -= Pa (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset); value = abs (relocation); @@ -10883,7 +10892,7 @@ elf32_arm_output_glue_section (struct bfd_link_info *info, bfd *obfd, { asection *sec, *osec; - sec = bfd_get_section_by_name (ibfd, name); + sec = bfd_get_linker_section (ibfd, name); if (sec == NULL || (sec->flags & SEC_EXCLUDE) != 0) return TRUE; @@ -10982,7 +10991,7 @@ bfd_arm_get_mach_from_attributes (bfd * abfd) return bfd_mach_arm_iWMMXt2; if (strcmp (name, "IWMMXT") == 0) - return bfd_mach_arm_iWMMXt; + return bfd_mach_arm_iWMMXt; } return bfd_mach_arm_5TE; @@ -11324,6 +11333,24 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out, T(V7E_M), /* V6S_M. */ T(V7E_M) /* V7E_M. */ }; + const int v8[] = + { + T(V8), /* PRE_V4. */ + T(V8), /* V4. */ + T(V8), /* V4T. */ + T(V8), /* V5T. */ + T(V8), /* V5TE. */ + T(V8), /* V5TEJ. */ + T(V8), /* V6. */ + T(V8), /* V6KZ. */ + T(V8), /* V6T2. */ + T(V8), /* V6K. */ + T(V8), /* V7. */ + T(V8), /* V6_M. */ + T(V8), /* V6S_M. */ + T(V8), /* V7E_M. */ + T(V8) /* V8. */ + }; const int v4t_plus_v6_m[] = { -1, /* PRE_V4. */ @@ -11340,6 +11367,7 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out, T(V6_M), /* V6_M. */ T(V6S_M), /* V6S_M. */ T(V7E_M), /* V7E_M. */ + T(V8), /* V8. */ T(V4T_PLUS_V6_M) /* V4T plus V6_M. */ }; const int *comb[] = @@ -11350,6 +11378,7 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out, v6_m, v6s_m, v7e_m, + v8, /* Pseudo-architecture. */ v4t_plus_v6_m }; @@ -11551,7 +11580,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) "ARM v6K", "ARM v7", "ARM v6-M", - "ARM v6S-M" + "ARM v6S-M", + "ARM v8" }; /* Merge Tag_CPU_arch and Tag_also_compatible_with. */ @@ -11696,11 +11726,12 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) when it's 0. It might mean absence of FP hardware if Tag_FP_arch is zero, otherwise it is effectively SP + DP. */ +#define VFP_VERSION_COUNT 8 static const struct { int ver; int regs; - } vfp_versions[7] = + } vfp_versions[VFP_VERSION_COUNT] = { {0, 0}, {1, 16}, @@ -11708,7 +11739,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) {3, 32}, {3, 16}, {4, 32}, - {4, 16} + {4, 16}, + {8, 32} }; int ver; int regs; @@ -11748,9 +11780,10 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) /* Now we can handle Tag_FP_arch. */ - /* Values greater than 6 aren't defined, so just pick the - biggest */ - if (in_attr[i].i > 6 && in_attr[i].i > out_attr[i].i) + /* Values of VFP_VERSION_COUNT or more aren't defined, so just + pick the biggest. */ + if (in_attr[i].i >= VFP_VERSION_COUNT + && in_attr[i].i > out_attr[i].i) { out_attr[i] = in_attr[i]; break; @@ -11765,7 +11798,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) regs = vfp_versions[out_attr[i].i].regs; /* This assumes all possible supersets are also a valid options. */ - for (newval = 6; newval > 0; newval--) + for (newval = VFP_VERSION_COUNT - 1; newval > 0; newval--) { if (regs == vfp_versions[newval].regs && ver == vfp_versions[newval].ver) @@ -12083,6 +12116,15 @@ elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr) case EF_ARM_EABI_VER5: fprintf (file, _(" [Version5 EABI]")); + + if (flags & EF_ARM_ABI_FLOAT_SOFT) + fprintf (file, _(" [soft-float ABI]")); + + if (flags & EF_ARM_ABI_FLOAT_HARD) + fprintf (file, _(" [hard-float ABI]")); + + flags &= ~(EF_ARM_ABI_FLOAT_SOFT | EF_ARM_ABI_FLOAT_HARD); + eabi: if (flags & EF_ARM_BE8) fprintf (file, _(" [BE8]")); @@ -12666,7 +12708,8 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, /* If the symbol is a function that doesn't bind locally, this relocation will need a PLT entry. */ - root_plt->refcount += 1; + if (root_plt->refcount != -1) + root_plt->refcount += 1; if (!call_reloc_p) arm_plt->noncall_refcount++; @@ -12882,7 +12925,7 @@ elf32_arm_find_nearest_line (bfd * abfd, if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections, section, symbols, offset, filename_ptr, functionname_ptr, - line_ptr, 0, + line_ptr, NULL, 0, & elf_tdata (abfd)->dwarf2_find_line_info)) { if (!*functionname_ptr) @@ -13036,7 +13079,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info, determine the address it must put in the global offset table, so both the dynamic object and the regular object will refer to the same memory location for the variable. */ - s = bfd_get_section_by_name (dynobj, ".dynbss"); + s = bfd_get_linker_section (dynobj, ".dynbss"); BFD_ASSERT (s != NULL); /* We must generate a R_ARM_COPY reloc to tell the dynamic linker to @@ -13047,7 +13090,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info, { asection *srel; - srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (globals, ".bss")); + srel = bfd_get_linker_section (dynobj, RELOC_SECTION (globals, ".bss")); elf32_arm_allocate_dynrelocs (info, srel, 1); h->needs_copy = 1; } @@ -13489,7 +13532,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, /* Set the contents of the .interp section to the interpreter. */ if (info->executable) { - s = bfd_get_section_by_name (dynobj, ".interp"); + s = bfd_get_linker_section (dynobj, ".interp"); BFD_ASSERT (s != NULL); s->size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; @@ -13975,7 +14018,7 @@ 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. */ - if (strcmp (h->root.root.string, "_DYNAMIC") == 0 + if (h == htab->root.hdynamic || (!htab->vxworks_p && h == htab->root.hgot)) sym->st_shndx = SHN_ABS; @@ -14021,7 +14064,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info Catch this here so that we do not seg-fault later on. */ if (sgot != NULL && bfd_is_abs_section (sgot->output_section)) return FALSE; - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); if (elf_hash_table (info)->dynamic_sections_created) { @@ -14079,7 +14122,14 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info name = RELOC_SECTION (htab, ".plt"); get_vma: s = bfd_get_section_by_name (output_bfd, name); - BFD_ASSERT (s != NULL); + if (s == NULL) + { + /* PR ld/14397: Issue an error message if a required section is missing. */ + (*_bfd_error_handler) + (_("error: required section '%s' not found in the linker script"), name); + bfd_set_error (bfd_error_invalid_operation); + return FALSE; + } if (!htab->symbian_p) dyn.d_un.d_ptr = s->vma; else @@ -14382,6 +14432,16 @@ elf32_arm_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATT if (globals != NULL && globals->byteswap_code) i_ehdrp->e_flags |= EF_ARM_BE8; } + + if (EF_ARM_EABI_VERSION (i_ehdrp->e_flags) == EF_ARM_EABI_VER5 + && ((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) + i_ehdrp->e_flags |= EF_ARM_ABI_FLOAT_HARD; + else + i_ehdrp->e_flags |= EF_ARM_ABI_FLOAT_SOFT; + } } static enum elf_reloc_type_class @@ -14806,8 +14866,8 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, /* ARM->Thumb glue. */ if (htab->arm_glue_size > 0) { - osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner, - ARM2THUMB_GLUE_SECTION_NAME); + osi.sec = bfd_get_linker_section (htab->bfd_of_glue_owner, + ARM2THUMB_GLUE_SECTION_NAME); osi.sec_shndx = _bfd_elf_section_from_bfd_section (output_bfd, osi.sec->output_section); @@ -14829,8 +14889,8 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, /* Thumb->ARM glue. */ if (htab->thumb_glue_size > 0) { - osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner, - THUMB2ARM_GLUE_SECTION_NAME); + osi.sec = bfd_get_linker_section (htab->bfd_of_glue_owner, + THUMB2ARM_GLUE_SECTION_NAME); osi.sec_shndx = _bfd_elf_section_from_bfd_section (output_bfd, osi.sec->output_section); @@ -14846,8 +14906,8 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, /* ARMv4 BX veneers. */ if (htab->bx_glue_size > 0) { - osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner, - ARM_BX_GLUE_SECTION_NAME); + osi.sec = bfd_get_linker_section (htab->bfd_of_glue_owner, + ARM_BX_GLUE_SECTION_NAME); osi.sec_shndx = _bfd_elf_section_from_bfd_section (output_bfd, osi.sec->output_section);