/* 32-bit ELF support for ARM
- Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ Copyright (C) 1998-2016 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
elf32_vfp11_erratum_list *erratumlist;
unsigned int stm32l4xx_erratumcount;
elf32_stm32l4xx_erratum_list *stm32l4xx_erratumlist;
+ unsigned int additional_reloc_count;
/* Information about unwind tables. */
union
{
static bfd_boolean
using_thumb_only (struct elf32_arm_link_hash_table *globals)
{
- int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
- Tag_CPU_arch);
- int profile;
+ int arch;
+ int profile = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+ Tag_CPU_arch_profile);
- if (arch == TAG_CPU_ARCH_V6_M || arch == TAG_CPU_ARCH_V6S_M)
- return TRUE;
+ if (profile)
+ return profile == 'M';
- if (arch != TAG_CPU_ARCH_V7 && arch != TAG_CPU_ARCH_V7E_M)
- return FALSE;
+ arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, Tag_CPU_arch);
- profile = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
- Tag_CPU_arch_profile);
+ if (arch == TAG_CPU_ARCH_V6_M
+ || arch == TAG_CPU_ARCH_V6S_M
+ || arch == TAG_CPU_ARCH_V7E_M
+ || arch == TAG_CPU_ARCH_V8M_BASE
+ || arch == TAG_CPU_ARCH_V8M_MAIN)
+ return TRUE;
- return profile == 'M';
+ return FALSE;
}
/* Determine if we're dealing with a Thumb-2 object. */
htab->plt_entry_size
= 4 * ARRAY_SIZE (elf32_arm_vxworks_exec_plt_entry);
}
+
+ if (elf_elfheader (dynobj))
+ elf_elfheader (dynobj)->e_ident[EI_CLASS] = ELFCLASS32;
}
else
{
&exidx_arm_data->u.exidx.unwind_edit_tail,
INSERT_EXIDX_CANTUNWIND_AT_END, text_sec, UINT_MAX);
+ exidx_arm_data->additional_reloc_count++;
+
adjust_exidx_size(exidx_sec, 8);
}
/* An error? */
continue;
+ if (last_unwind_type > 0)
+ {
+ unsigned int first_word = bfd_get_32 (ibfd, contents);
+ /* Add cantunwind if first unwind item does not match section
+ start. */
+ if (first_word != sec->vma)
+ {
+ insert_cantunwind_after (last_text_sec, last_exidx_sec);
+ last_unwind_type = 0;
+ }
+ }
+
for (j = 0; j < hdr->sh_size; j += 8)
{
unsigned int second_word = bfd_get_32 (ibfd, contents + j + 4);
else
unwind_type = 2;
- if (elide)
+ if (elide && !bfd_link_relocatable (info))
{
add_unwind_table_edit (&unwind_edit_head, &unwind_edit_tail,
DELETE_EXIDX_ENTRY, NULL, j / 8);
}
/* Add terminating CANTUNWIND entry. */
- if (last_exidx_sec && last_unwind_type != 0)
+ if (!bfd_link_relocatable (info) && last_exidx_sec
+ && last_unwind_type != 0)
insert_cantunwind_after(last_text_sec, last_exidx_sec);
return TRUE;
T(V8), /* V7E_M. */
T(V8) /* V8. */
};
+ const int v8m_baseline[] =
+ {
+ -1, /* PRE_V4. */
+ -1, /* V4. */
+ -1, /* V4T. */
+ -1, /* V5T. */
+ -1, /* V5TE. */
+ -1, /* V5TEJ. */
+ -1, /* V6. */
+ -1, /* V6KZ. */
+ -1, /* V6T2. */
+ -1, /* V6K. */
+ -1, /* V7. */
+ T(V8M_BASE), /* V6_M. */
+ T(V8M_BASE), /* V6S_M. */
+ -1, /* V7E_M. */
+ -1, /* V8. */
+ -1,
+ T(V8M_BASE) /* V8-M BASELINE. */
+ };
+ const int v8m_mainline[] =
+ {
+ -1, /* PRE_V4. */
+ -1, /* V4. */
+ -1, /* V4T. */
+ -1, /* V5T. */
+ -1, /* V5TE. */
+ -1, /* V5TEJ. */
+ -1, /* V6. */
+ -1, /* V6KZ. */
+ -1, /* V6T2. */
+ -1, /* V6K. */
+ T(V8M_MAIN), /* V7. */
+ T(V8M_MAIN), /* V6_M. */
+ T(V8M_MAIN), /* V6S_M. */
+ T(V8M_MAIN), /* V7E_M. */
+ -1, /* V8. */
+ -1,
+ T(V8M_MAIN), /* V8-M BASELINE. */
+ T(V8M_MAIN) /* V8-M MAINLINE. */
+ };
const int v4t_plus_v6_m[] =
{
-1, /* PRE_V4. */
T(V6S_M), /* V6S_M. */
T(V7E_M), /* V7E_M. */
T(V8), /* V8. */
+ -1, /* Unused. */
+ T(V8M_BASE), /* V8-M BASELINE. */
+ T(V8M_MAIN), /* V8-M MAINLINE. */
T(V4T_PLUS_V6_M) /* V4T plus V6_M. */
};
const int *comb[] =
v6s_m,
v7e_m,
v8,
+ NULL,
+ v8m_baseline,
+ v8m_mainline,
/* Pseudo-architecture. */
v4t_plus_v6_m
};
if (tagh <= TAG_CPU_ARCH_V6KZ)
return result;
- result = comb[tagh - T(V6T2)][tagl];
+ result = comb[tagh - T(V6T2)] ? comb[tagh - T(V6T2)][tagl] : -1;
/* Use Tag_CPU_arch == V4T and Tag_also_compatible_with (Tag_CPU_arch V6_M)
as the canonical version. */
"ARM v7",
"ARM v6-M",
"ARM v6S-M",
- "ARM v8"
+ "ARM v8",
+ "",
+ "ARM v8-M.baseline",
+ "ARM v8-M.mainline",
};
/* Merge Tag_CPU_arch and Tag_also_compatible_with. */
may_need_local_target_p = TRUE;
break;
}
+ else goto jump_over;
+
/* Fall through. */
case R_ARM_MOVW_ABS_NC:
/* Fall through. */
case R_ARM_ABS32:
case R_ARM_ABS32_NOI:
+ jump_over:
if (h != NULL && bfd_link_executable (info))
{
h->pointer_equality_needed = 1;
return reloc_class_plt;
case R_ARM_COPY:
return reloc_class_copy;
+ case R_ARM_IRELATIVE:
+ return reloc_class_ifunc;
default:
return reloc_class_normal;
}
/* End of stm32l4xx work-around. */
+static void
+elf32_arm_add_relocation (bfd *output_bfd, struct bfd_link_info *info,
+ asection *output_sec, Elf_Internal_Rela *rel)
+{
+ BFD_ASSERT (output_sec && rel);
+ struct bfd_elf_section_reloc_data *output_reldata;
+ struct elf32_arm_link_hash_table *htab;
+ struct bfd_elf_section_data *oesd = elf_section_data (output_sec);
+ Elf_Internal_Shdr *rel_hdr;
+
+
+ if (oesd->rel.hdr)
+ {
+ rel_hdr = oesd->rel.hdr;
+ output_reldata = &(oesd->rel);
+ }
+ else if (oesd->rela.hdr)
+ {
+ rel_hdr = oesd->rela.hdr;
+ output_reldata = &(oesd->rela);
+ }
+ else
+ {
+ abort ();
+ }
+
+ bfd_byte *erel = rel_hdr->contents;
+ erel += output_reldata->count * rel_hdr->sh_entsize;
+ htab = elf32_arm_hash_table (info);
+ SWAP_RELOC_OUT (htab) (output_bfd, rel, erel);
+ output_reldata->count++;
+}
+
/* Do code byteswapping. Return FALSE afterwards so that the section is
written out as normal. */
usual BFD method. */
prel31_offset = (text_offset - exidx_offset)
& 0x7ffffffful;
+ if (bfd_link_relocatable (link_info))
+ {
+ /* Here relocation for new EXIDX_CANTUNWIND is
+ created, so there is no need to
+ adjust offset by hand. */
+ prel31_offset = text_sec->output_offset
+ + text_sec->size;
+
+ /* New relocation entity. */
+ asection *text_out = text_sec->output_section;
+ Elf_Internal_Rela rel;
+ rel.r_addend = 0;
+ rel.r_offset = exidx_offset;
+ rel.r_info = ELF32_R_INFO (text_out->target_index,
+ R_ARM_PREL31);
+
+ elf32_arm_add_relocation (output_bfd, link_info,
+ sec->output_section,
+ &rel);
+ }
/* First address we can't unwind. */
bfd_put_32 (output_bfd, prel31_offset,
return n;
}
-static const struct bfd_elf_special_section
-elf32_arm_special_sections[] =
-{
-/* Catch sections with .text.noread prefix and apply allocate, execute and
- noread section attributes. */
- { STRING_COMMA_LEN (".text.noread"), -2, SHT_PROGBITS,
- SHF_ALLOC + SHF_EXECINSTR + SHF_ARM_NOREAD },
- { NULL, 0, 0, 0, 0 }
-};
-
static bfd_boolean
elf32_arm_section_flags (flagword *flags, const Elf_Internal_Shdr * hdr)
{
return SEC_NO_FLAGS;
}
+static unsigned int
+elf32_arm_count_additional_relocs (asection *sec)
+{
+ struct _arm_elf_section_data *arm_data;
+ arm_data = get_arm_elf_section_data (sec);
+ return arm_data->additional_reloc_count;
+}
+
#define ELF_ARCH bfd_arch_arm
#define ELF_TARGET_ID ARM_ELF_DATA
#define ELF_MACHINE_CODE EM_ARM
#define elf_backend_output_arch_local_syms elf32_arm_output_arch_local_syms
#define elf_backend_begin_write_processing elf32_arm_begin_write_processing
#define elf_backend_add_symbol_hook elf32_arm_add_symbol_hook
+#define elf_backend_count_additional_relocs elf32_arm_count_additional_relocs
#define elf_backend_can_refcount 1
#define elf_backend_can_gc_sections 1
#define elf_backend_obj_attrs_order elf32_arm_obj_attrs_order
#define elf_backend_obj_attrs_handle_unknown elf32_arm_obj_attrs_handle_unknown
-#undef elf_backend_special_sections
-#define elf_backend_special_sections elf32_arm_special_sections
#undef elf_backend_section_flags
#define elf_backend_section_flags elf32_arm_section_flags
#undef elf_backend_lookup_section_flags_hook