struct elf32_arm_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf32_arm_link_hash_table);
- ret = (struct elf32_arm_link_hash_table *) bfd_alloc (abfd, amt);
+ ret = (struct elf32_arm_link_hash_table *) bfd_malloc (amt);
if (ret == (struct elf32_arm_link_hash_table *) NULL)
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
elf32_arm_link_hash_newfunc))
{
- bfd_release (abfd, ret);
+ free (ret);
return NULL;
}
return;
}
-/* Select a BFD to be used to hold the sections used by the glue code.
- This function is called from the linker scripts in ld/emultempl/
- {armelf/pe}.em */
+/* Add the glue sections to ABFD. This function is called from the
+ linker scripts in ld/emultempl/{armelf}.em. */
boolean
-bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
+bfd_elf32_arm_add_glue_sections_to_bfd (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
- struct elf32_arm_link_hash_table *globals;
flagword flags;
asection *sec;
- /* If we are only performing a partial link do not bother
- getting a bfd to hold the glue. */
+ /* If we are only performing a partial
+ link do not bother adding the glue. */
if (info->relocateable)
return true;
- globals = elf32_arm_hash_table (info);
-
- BFD_ASSERT (globals != NULL);
-
- if (globals->bfd_of_glue_owner != NULL)
- return true;
-
sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
if (sec == NULL)
sec->gc_mark = 1;
}
+ return true;
+}
+
+/* Select a BFD to be used to hold the sections used by the glue code.
+ This function is called from the linker scripts in ld/emultempl/
+ {armelf/pe}.em */
+
+boolean
+bfd_elf32_arm_get_bfd_for_interworking (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ struct elf32_arm_link_hash_table *globals;
+
+ /* If we are only performing a partial link
+ do not bother getting a bfd to hold the glue. */
+ if (info->relocateable)
+ return true;
+
+ globals = elf32_arm_hash_table (info);
+
+ BFD_ASSERT (globals != NULL);
+
+ if (globals->bfd_of_glue_owner != NULL)
+ return true;
+
/* Save the bfd for later use. */
globals->bfd_of_glue_owner = abfd;
}
skip = false;
+ relocate = false;
outrel.r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section,
rel->r_offset);
if (outrel.r_offset == (bfd_vma) -1)
skip = true;
+ else if (outrel.r_offset == (bfd_vma) -2)
+ skip = true, relocate = true;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
if (skip)
- {
- memset (&outrel, 0, sizeof outrel);
- relocate = false;
- }
+ memset (&outrel, 0, sizeof outrel);
else if (r_type == R_ARM_PC24)
{
BFD_ASSERT (h != NULL && h->dynindx != -1);
- if ((input_section->flags & SEC_ALLOC) != 0)
- relocate = false;
- else
+ if ((input_section->flags & SEC_ALLOC) == 0)
relocate = true;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_PC24);
}
else
{
BFD_ASSERT (h->dynindx != -1);
- if ((input_section->flags & SEC_ALLOC) != 0)
- relocate = false;
- else
+ if ((input_section->flags & SEC_ALLOC) == 0)
relocate = true;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_ABS32);
}
boolean overflow = false;
bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
- bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
+ bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift;
bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
bfd_vma check;
bfd_signed_vma signed_check;
if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
overflow = true;
- /* Put RELOCATION back into the insn. */
- upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff);
- lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff);
-
#ifndef OLD_ARM_ABI
if (r_type == R_ARM_THM_XPC22
&& ((lower_insn & 0x1800) == 0x0800))
- /* Remove bit zero of the adjusted offset. Bit zero can only be
- set if the upper insn is at a half-word boundary, since the
- destination address, an ARM instruction, must always be on a
- word boundary. The semantics of the BLX (1) instruction, however,
- are that bit zero in the offset must always be zero, and the
- corresponding bit one in the target address will be set from bit
- one of the source address. */
- lower_insn &= ~1;
+ /* For a BLX instruction, make sure that the relocation is rounded up
+ to a word boundary. This follows the semantics of the instruction
+ which specifies that bit 1 of the target address will come from bit
+ 1 of the base address. */
+ relocation = (relocation + 2) & ~ 3;
#endif
+ /* Put RELOCATION back into the insn. */
+ upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff);
+ lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff);
+
/* Put the relocated value back in the object file: */
bfd_put_16 (input_bfd, upper_insn, hit_data);
bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
}
break;
+ case R_ARM_THM_PC11:
+ /* Thumb B (branch) instruction). */
+ {
+ bfd_vma relocation;
+ bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
+ bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
+ bfd_vma check;
+ bfd_signed_vma signed_check;
+
+#ifdef USE_REL
+ /* Need to refetch addend. */
+ addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
+ /* ??? Need to determine shift amount from operand size. */
+ addend >>= howto->rightshift;
+#endif
+ relocation = value + addend;
+
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ + rel->r_offset);
+
+ check = relocation >> howto->rightshift;
+
+ /* If this is a signed value, the rightshift just
+ dropped leading 1 bits (assuming twos complement). */
+ if ((bfd_signed_vma) relocation >= 0)
+ signed_check = check;
+ else
+ signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);
+
+ relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask));
+
+ bfd_put_16 (input_bfd, relocation, hit_data);
+
+ /* Assumes two's complement. */
+ if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
+ return bfd_reloc_overflow;
+
+ return bfd_reloc_ok;
+ }
+
case R_ARM_GNU_VTINHERIT:
case R_ARM_GNU_VTENTRY:
return bfd_reloc_ok;
if (sgot == NULL)
return bfd_reloc_notsupported;
+ /* If we are addressing a Thumb function, we need to adjust the
+ address by one, so that attempts to call the function pointer will
+ correctly interpret it as Thumb code. */
+ if (sym_flags == STT_ARM_TFUNC)
+ value += 1;
+
/* Note that sgot->output_offset is not involved in this
calculation. We always want the start of .got. If we
define _GLOBAL_OFFSET_TABLE in a different way, as is
off &= ~1;
else
{
+ /* If we are addressing a Thumb function, we need to
+ adjust the address by one, so that attempts to
+ call the function pointer will correctly
+ interpret it as Thumb code. */
+ if (sym_flags == STT_ARM_TFUNC)
+ value |= 1;
+
bfd_put_32 (output_bfd, value, sgot->contents + off);
h->got.offset |= 1;
}
Elf_Internal_Rela * relend;
const char * name;
+#ifndef USE_REL
+ if (info->relocateable)
+ return true;
+#endif
+
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
#endif
howto = bfd_reloc.howto;
+#ifdef USE_REL
if (info->relocateable)
{
/* This is a relocateable link. We don't have to change
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
{
sec = local_sections[r_symndx];
-#ifdef USE_REL
arm_add_to_rel (input_bfd, contents + rel->r_offset,
howto,
(bfd_signed_vma) (sec->output_offset
+ sym->st_value));
-#else
- rel->r_addend += (sec->output_offset + sym->st_value);
-#endif
}
}
continue;
}
+#endif
/* This is a final link. */
h = NULL;
{
if (flags & EF_ARM_INTERWORK)
(*_bfd_error_handler) (_("\
-Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"),
+Warning: Not setting interworking flag of %s since it has already been specified as non-interworking"),
bfd_archive_filename (abfd));
else
_bfd_error_handler (_("\
-Warning: Clearing the interwork flag of %s due to outside request"),
+Warning: Clearing the interworking flag of %s due to outside request"),
bfd_archive_filename (abfd));
}
}
{
if (out_flags & EF_ARM_INTERWORK)
_bfd_error_handler (_("\
-Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"),
+Warning: Clearing the interworking flag of %s because non-interworking code in %s has been linked with it"),
bfd_get_filename (obfd),
bfd_archive_filename (ibfd));
if (EF_ARM_EABI_VERSION (in_flags) != EF_ARM_EABI_VERSION (out_flags))
{
_bfd_error_handler (_("\
-Error: %s compiled for EABI version %d, whereas %s is compiled for version %d"),
+ERROR: %s is compiled for EABI version %d, whereas %s is compiled for version %d"),
bfd_archive_filename (ibfd),
(in_flags & EF_ARM_EABIMASK) >> 24,
bfd_get_filename (obfd),
if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
{
_bfd_error_handler (_("\
-Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
+ERROR: %s is compiled for APCS-%d, whereas target %s uses APCS-%d"),
bfd_archive_filename (ibfd),
in_flags & EF_ARM_APCS_26 ? 26 : 32,
bfd_get_filename (obfd),
{
if (in_flags & EF_ARM_APCS_FLOAT)
_bfd_error_handler (_("\
-Error: %s passes floats in FP registers, whereas %s passes them in integer registers"),
+ERROR: %s passes floats in float registers, whereas %s passes them in integer registers"),
bfd_archive_filename (ibfd),
bfd_get_filename (obfd));
else
_bfd_error_handler (_("\
-Error: %s passes floats in integer registers, whereas %s passes them in FP registers"),
+ERROR: %s passes floats in integer registers, whereas %s passes them in float registers"),
bfd_archive_filename (ibfd),
bfd_get_filename (obfd));
flags_compatible = false;
}
-#ifdef EF_ARM_SOFT_FLOAT
- if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT))
+ if ((in_flags & EF_ARM_VFP_FLOAT) != (out_flags & EF_ARM_VFP_FLOAT))
{
- if (in_flags & EF_ARM_SOFT_FLOAT)
- _bfd_error_handler (_ ("\
-Error: %s uses software FP, whereas %s uses hardware FP"),
+ if (in_flags & EF_ARM_VFP_FLOAT)
+ _bfd_error_handler (_("\
+ERROR: %s uses VFP instructions, whereas %s uses FPA instructions"),
bfd_archive_filename (ibfd),
bfd_get_filename (obfd));
else
- _bfd_error_handler (_ ("\
-Error: %s uses hardware FP, whereas %s uses software FP"),
+ _bfd_error_handler (_("\
+ERROR: %s uses FPA instructions, whereas %s uses VFP instructions"),
bfd_archive_filename (ibfd),
bfd_get_filename (obfd));
flags_compatible = false;
}
+
+#ifdef EF_ARM_SOFT_FLOAT
+ if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT))
+ {
+ /* We can allow interworking between code that is VFP format
+ layout, and uses either soft float or integer regs for
+ passing floating point arguments and results. We already
+ know that the APCS_FLOAT flags match; similarly for VFP
+ flags. */
+ if ((in_flags & EF_ARM_APCS_FLOAT) != 0
+ || (in_flags & EF_ARM_VFP_FLOAT) == 0)
+ {
+ if (in_flags & EF_ARM_SOFT_FLOAT)
+ _bfd_error_handler (_("\
+ERROR: %s uses software FP, whereas %s uses hardware FP"),
+ bfd_archive_filename (ibfd),
+ bfd_get_filename (obfd));
+ else
+ _bfd_error_handler (_("\
+ERROR: %s uses hardware FP, whereas %s uses software FP"),
+ bfd_archive_filename (ibfd),
+ bfd_get_filename (obfd));
+
+ flags_compatible = false;
+ }
+ }
#endif
/* Interworking mismatch is only a warning. */
_bfd_error_handler (_("\
Warning: %s supports interworking, whereas %s does not"),
bfd_archive_filename (ibfd),
- bfd_get_filename (obfd));
+ bfd_get_filename (obfd));
}
else
{
fprintf (file, _(" [interworking enabled]"));
if (flags & EF_ARM_APCS_26)
- fprintf (file, _(" [APCS-26]"));
+ fprintf (file, " [APCS-26]");
else
- fprintf (file, _(" [APCS-32]"));
+ fprintf (file, " [APCS-32]");
+
+ if (flags & EF_ARM_VFP_FLOAT)
+ fprintf (file, _(" [VFP float format]"));
+ else
+ fprintf (file, _(" [FPA float format]"));
if (flags & EF_ARM_APCS_FLOAT)
fprintf (file, _(" [floats passed in float registers]"));
if (flags & EF_ARM_SOFT_FLOAT)
fprintf (file, _(" [software FP]"));
- flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT | EF_ARM_PIC
- | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI | EF_ARM_SOFT_FLOAT);
+ flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT
+ | EF_ARM_PIC | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI
+ | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT);
break;
case EF_ARM_EABI_VER1:
asection ** spp;
for (spp = &s->output_section->owner->sections;
- *spp != s->output_section;
+ *spp != NULL;
spp = &(*spp)->next)
- ;
- *spp = s->output_section->next;
- --s->output_section->owner->section_count;
-
+ {
+ if (*spp == s->output_section)
+ {
+ bfd_section_list_remove (s->output_section->owner, spp);
+ --s->output_section->owner->section_count;
+ break;
+ }
+ }
continue;
}
{
struct elf32_arm_pcrel_relocs_copied * s;
+ if (h->root.root.type == bfd_link_hash_warning)
+ h = (struct elf32_arm_link_hash_entry *) h->root.root.u.i.link;
+
/* We only discard relocs for symbols defined in a regular object. */
if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
return true;
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_plt_sym 0
+#ifndef USE_REL
+#define elf_backend_rela_normal 1
+#endif
#define elf_backend_got_header_size 12
#define elf_backend_plt_header_size PLT_ENTRY_SIZE