/* 32-bit ELF support for ARM
- Copyright (C) 1998-2016 Free Software Foundation, Inc.
+ Copyright (C) 1998-2017 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* How many R_ARM_TLS_DESC relocations were generated so far. */
bfd_vma num_tls_desc;
- /* Short-cuts to get to dynamic linker sections. */
- asection *sdynbss;
- asection *srelbss;
-
/* The (unloaded but important) VxWorks .rela.plt.unloaded section. */
asection *srelplt2;
}
static inline int
-popcount (unsigned int mask)
+elf32_arm_popcount (unsigned int mask)
{
#if GCC_VERSION >= 3004
return __builtin_popcount (mask);
#else
- unsigned int i, sum = 0;
+ unsigned int i;
+ int sum = 0;
for (i = 0; i < 8 * sizeof (mask); i++)
{
if (!_bfd_elf_create_dynamic_sections (dynobj, info))
return FALSE;
- htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
- if (!bfd_link_pic (info))
- htab->srelbss = bfd_get_linker_section (dynobj,
- RELOC_SECTION (htab, ".bss"));
-
if (htab->vxworks_p)
{
if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
if (!htab->root.splt
|| !htab->root.srelplt
- || !htab->sdynbss
- || (!bfd_link_pic (info) && !htab->srelbss))
+ || !htab->root.sdynbss
+ || (!bfd_link_pic (info) && !htab->root.srelbss))
abort ();
return TRUE;
if (!thumb_only)
{
if (input_sec->flags & SEC_ELF_PURECODE)
- _bfd_error_handler (_("\
-%B(%A): warning: long branch veneers used in section with SHF_ARM_PURECODE section \
-attribute is only supported for M-profile targets that implement the movw instruction."),
- input_sec);
+ _bfd_error_handler
+ (_("%B(%A): warning: long branch veneers used in"
+ " section with SHF_ARM_PURECODE section"
+ " attribute is only supported for M-profile"
+ " targets that implement the movw instruction."),
+ input_bfd, input_sec);
stub_type = (bfd_link_pic (info) | globals->pic_veneer)
/* PIC stubs. */
else
{
if (input_sec->flags & SEC_ELF_PURECODE)
- _bfd_error_handler (_("\
-%B(%A): warning: long branch veneers used in section with SHF_ARM_PURECODE section \
-attribute is only supported for M-profile targets that implement the movw instruction."),
- input_sec);
+ _bfd_error_handler
+ (_("%B(%A): warning: long branch veneers used in"
+ " section with SHF_ARM_PURECODE section"
+ " attribute is only supported for M-profile"
+ " targets that implement the movw instruction."),
+ input_bfd, input_sec);
stub_type = (bfd_link_pic (info) | globals->pic_veneer)
/* PIC stub. */
else
{
if (input_sec->flags & SEC_ELF_PURECODE)
- _bfd_error_handler (_("%B(%s): warning: long branch "
- " veneers used in section with "
- "SHF_ARM_PURECODE section "
- "attribute is only supported"
- " for M-profile targets that "
- "implement the movw "
- "instruction."));
+ _bfd_error_handler
+ (_("%B(%A): warning: long branch veneers used in"
+ " section with SHF_ARM_PURECODE section"
+ " attribute is only supported" " for M-profile"
+ " targets that implement the movw instruction."),
+ input_bfd, input_sec);
/* Thumb to arm. */
if (sym_sec != NULL
_bfd_error_handler
(_("%B(%s): warning: interworking not enabled.\n"
" first occurrence: %B: Thumb call to ARM"),
- sym_sec->owner, input_bfd, name);
+ sym_sec->owner, name, input_bfd);
}
stub_type =
|| r_type == R_ARM_TLS_CALL)
{
if (input_sec->flags & SEC_ELF_PURECODE)
- _bfd_error_handler (_("%B(%s): warning: long branch "
- " veneers used in section with "
- "SHF_ARM_PURECODE section "
- "attribute is only supported"
- " for M-profile targets that "
- "implement the movw "
- "instruction."));
+ _bfd_error_handler
+ (_("%B(%A): warning: long branch veneers used in"
+ " section with SHF_ARM_PURECODE section"
+ " attribute is only supported for M-profile"
+ " targets that implement the movw instruction."),
+ input_bfd, input_sec);
if (branch_type == ST_BRANCH_TO_THUMB)
{
/* Arm to thumb. */
{
if (section == NULL)
section = stub_sec;
- _bfd_error_handler (_("%s: cannot create stub entry %s"),
+ _bfd_error_handler (_("%B: cannot create stub entry %s"),
section->owner, stub_name);
return NULL;
}
TRUE, FALSE);
if (stub_entry == NULL)
{
- _bfd_error_handler (_("%s: cannot create stub entry %s"),
+ _bfd_error_handler (_("%B: cannot create stub entry %s"),
section->owner, stub_name);
return FALSE;
}
/* The field encoding the register list is the same for both LDMIA
and LDMDB encodings. */
if (is_thumb2_ldmia (insn) || is_thumb2_ldmdb (insn))
- nb_words = popcount (insn & 0x0000ffff);
+ nb_words = elf32_arm_popcount (insn & 0x0000ffff);
else if (is_thumb2_vldm (insn))
nb_words = (insn & 0xff);
if (is_not_last_in_it_block)
{
_bfd_error_handler
- /* Note - overlong line used here to allow for translation. */
/* xgettext:c-format */
- (_("\
-%B(%A+0x%lx): error: multiple load detected in non-last IT block instruction : STM32L4XX veneer cannot be generated.\n"
- "Use gcc option -mrestrict-it to generate only one instruction per IT block.\n"),
+ (_("%B(%A+0x%lx): error: multiple load detected"
+ " in non-last IT block instruction :"
+ " STM32L4XX veneer cannot be generated.\n"
+ "Use gcc option -mrestrict-it to generate"
+ " only one instruction per IT block.\n"),
abfd, sec, (long) i);
}
else
_bfd_error_handler
(_("%B(%s): warning: interworking not enabled.\n"
" first occurrence: %B: Thumb call to ARM"),
- sym_sec->owner, input_bfd, name);
+ sym_sec->owner, name, input_bfd);
return FALSE;
}
_bfd_error_handler
(_("%B(%s): warning: interworking not enabled.\n"
" first occurrence: %B: arm call to thumb"),
- sym_sec->owner, input_bfd, name);
+ sym_sec->owner, name, input_bfd);
}
--my_offset;
struct elf_link_hash_entry * h)
{
bfd * dynobj;
- asection * s;
+ asection *s, *srel;
struct elf32_arm_link_hash_entry * eh;
struct elf32_arm_link_hash_table *globals;
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_linker_section (dynobj, ".dynbss");
- BFD_ASSERT (s != NULL);
-
/* If allowed, we must generate a R_ARM_COPY reloc to tell the dynamic
linker to copy the initial value out of the dynamic object and into
the runtime process image. We need to remember the offset into the
.rel(a).bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = globals->root.sdynrelro;
+ srel = globals->root.sreldynrelro;
+ }
+ else
+ {
+ s = globals->root.sdynbss;
+ srel = globals->root.srelbss;
+ }
if (info->nocopyreloc == 0
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
&& h->size != 0)
{
- asection *srel;
-
- srel = bfd_get_linker_section (dynobj, RELOC_SECTION (globals, ".bss"));
elf32_arm_allocate_dynrelocs (info, srel, 1);
h->needs_copy = 1;
}
if (!bfd_elf32_arm_process_before_allocation (ibfd, info)
|| !bfd_elf32_arm_vfp11_erratum_scan (ibfd, info)
|| !bfd_elf32_arm_stm32l4xx_erratum_scan (ibfd, info))
- _bfd_error_handler (_("Errors encountered processing file %s"),
- ibfd->filename);
+ _bfd_error_handler (_("Errors encountered processing file %B"), ibfd);
}
/* Allocate space for the glue sections now that we've sized them. */
&& s != htab->root.sgotplt
&& s != htab->root.iplt
&& s != htab->root.igotplt
- && s != htab->sdynbss)
+ && s != htab->root.sdynbss
+ && s != htab->root.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));
- s = htab->srelbss;
- BFD_ASSERT (s != NULL);
-
rel.r_addend = 0;
rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_COPY);
+ if (h->root.u.def.section == htab->root.sdynrelro)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
elf32_arm_add_dynreloc (output_bfd, info, s, &rel);
}
int insn_all_registers = initial_insn & 0x0000ffff;
int insn_low_registers, insn_high_registers;
int usable_register_mask;
- int nb_registers = popcount (insn_all_registers);
+ int nb_registers = elf32_arm_popcount (insn_all_registers);
int restore_pc = (insn_all_registers & (1 << 15)) ? 1 : 0;
int restore_rn = (insn_all_registers & (1 << rn)) ? 1 : 0;
bfd_byte *current_stub_contents = base_stub_contents;
BFD_ASSERT (!wback || !restore_rn);
/* - nb_registers > 8. */
- BFD_ASSERT (popcount (insn_all_registers) > 8);
+ BFD_ASSERT (elf32_arm_popcount (insn_all_registers) > 8);
/* At this point, LDMxx initial insn loads between 9 and 14 registers. */
int usable_register_mask;
int restore_pc = (insn_all_registers & (1 << 15)) ? 1 : 0;
int restore_rn = (insn_all_registers & (1 << rn)) ? 1 : 0;
- int nb_registers = popcount (insn_all_registers);
+ int nb_registers = elf32_arm_popcount (insn_all_registers);
bfd_byte *current_stub_contents = base_stub_contents;
BFD_ASSERT (is_thumb2_ldmdb (initial_insn));
BFD_ASSERT (!wback || !restore_rn);
/* - nb_registers > 8. */
- BFD_ASSERT (popcount (insn_all_registers) > 8);
+ BFD_ASSERT (elf32_arm_popcount (insn_all_registers) > 8);
/* At this point, LDMxx initial insn loads between 9 and 14 registers. */
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_plt_sym 0
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 1
#define elf_backend_may_use_rela_p 0
#define elf_backend_default_use_rela_p 0
{
_bfd_error_handler
(_("error: Source object %B has EABI version %d, but target %B has EABI version %d"),
- ibfd, obfd,
- (in_flags & EF_ARM_EABIMASK) >> 24,
- (out_flags & EF_ARM_EABIMASK) >> 24);
+ ibfd, (in_flags & EF_ARM_EABIMASK) >> 24,
+ obfd, (out_flags & EF_ARM_EABIMASK) >> 24);
return FALSE;
}
{
_bfd_error_handler
(_("error: %B is compiled for APCS-%d, whereas target %B uses APCS-%d"),
- ibfd, obfd,
- in_flags & EF_ARM_APCS_26 ? 26 : 32,
- out_flags & EF_ARM_APCS_26 ? 26 : 32);
+ ibfd, in_flags & EF_ARM_APCS_26 ? 26 : 32,
+ obfd, out_flags & EF_ARM_APCS_26 ? 26 : 32);
flags_compatible = FALSE;
}