generic-poky/meta/packages/binutils/binutils-2.16/binutils-2.16-thumb-trampol...

293 lines
9.6 KiB
Diff

--- binutils-2.16/.pc/binutils-2.16-thumb-trampoline.patch/bfd/elf32-arm.c 2005-05-02 12:43:06.000000000 -0700
+++ binutils-2.16/bfd/elf32-arm.c 2005-09-19 22:58:49.834931044 -0700
@@ -24,6 +24,8 @@
#include "libbfd.h"
#include "elf-bfd.h"
+#define NOTE_DEBUG 0
+
#ifndef NUM_ELEM
#define NUM_ELEM(a) (sizeof (a) / (sizeof (a)[0]))
#endif
@@ -1127,6 +1129,10 @@
used, we need to record the index into .got.plt instead of
recomputing it from the PLT offset. */
bfd_signed_vma plt_got_offset;
+
+ /* This is used to sanity check that the Thumb trampoline space
+ really was allocated. */
+ int accomodate_trampoline;
};
/* Traverse an arm ELF linker hash table. */
@@ -1219,9 +1225,15 @@
table, string));
if (ret != NULL)
{
+#if NOTE_DEBUG
+ _bfd_error_handler(
+ _("NOTE: %x(%s): New hash entry (plt refcount %d)"),
+ ret, string, ret->root.plt.refcount);
+#endif
ret->relocs_copied = NULL;
ret->plt_thumb_refcount = 0;
ret->plt_got_offset = -1;
+ ret->accomodate_trampoline = 0;
}
return (struct bfd_hash_entry *) ret;
@@ -1335,16 +1347,38 @@
eind->relocs_copied = NULL;
}
- /* If the direct symbol already has an associated PLT entry, the
- indirect symbol should not. If it doesn't, swap refcount information
- from the indirect symbol. */
- if (edir->plt_thumb_refcount == 0)
+ if (ind->root.type == bfd_link_hash_indirect)
{
- edir->plt_thumb_refcount = eind->plt_thumb_refcount;
- eind->plt_thumb_refcount = 0;
+ bfd_signed_vma tmp;
+ bfd_signed_vma lowest_valid = bed->can_refcount;
+
+ /* If the direct symbol already has an associated PLT entry, the
+ indirect symbol should not. If it doesn't, swap refcount information
+ from the indirect symbol. */
+#if NOTE_DEBUG
+ _bfd_error_handler(_("NOTE: %x(%s,%d,%d) <== %x(%s,%d,%d)"),
+ dir, dir->root.root.string, dir->plt.refcount, edir->plt_thumb_refcount,
+ ind, ind->root.root.string, ind->plt.refcount, eind->plt_thumb_refcount);
+#endif
+
+ /* Copy over the global and procedure linkage table refcount entries.
+ These may have been already set up by a check_relocs routine. This
+ code duplicates that for the plt refcount in elf.c
+ _bfd_elf_link_hash_copy_indirect */
+ tmp = dir->plt.refcount;
+ /* this obfuscated test evaluates to bed->can_refcount && plt.refcount == 0
+ * || plt.refcount < 0.
+ */
+ if (tmp < lowest_valid)
+ {
+ tmp = edir->plt_thumb_refcount;
+ edir->plt_thumb_refcount = eind->plt_thumb_refcount;
+ eind->plt_thumb_refcount = tmp;
+ BFD_ASSERT(eind->accomodate_trampoline == 0);
+ }
+ else
+ BFD_ASSERT (eind->plt_thumb_refcount == 0);
}
- else
- BFD_ASSERT (eind->plt_thumb_refcount == 0);
_bfd_elf_link_hash_copy_indirect (bed, dir, ind);
}
@@ -2060,7 +2094,7 @@
(*_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;
}
@@ -2165,7 +2199,7 @@
(*_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;
@@ -2481,7 +2515,7 @@
instruction instead ? */
if (sym_flags != STT_ARM_TFUNC)
(*_bfd_error_handler)
- (_("\%B: Warning: Arm BLX instruction targets Arm function '%s'."),
+ (_("%B: Warning: Arm BLX instruction targets Arm function '%s'."),
input_bfd,
h ? h->root.root.string : "(local)");
}
@@ -2697,6 +2731,20 @@
/* Handle calls via the PLT. */
if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1)
{
+ struct elf32_arm_link_hash_entry *eh;
+ eh = (struct elf32_arm_link_hash_entry *) h;
+ if (!eh->accomodate_trampoline)
+ {
+ /* %B of output_bfd crashes here, so %x is used instead */
+ _bfd_error_handler(
+ _("ERROR: %B: %x(%s): missing thumb trampoline, refcount(thumb %d, plt %d) in %x at %x+%x+%x"),
+ input_bfd, h, h->root.root.string, eh->plt_thumb_refcount,
+ h->plt.refcount, output_bfd, splt->output_section->vma,
+ splt->output_offset, h->plt.offset);
+ /* The relocation would point to garbage, it gets skipped... */
+ return bfd_reloc_dangerous;
+ }
+
value = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset);
@@ -3525,8 +3573,9 @@
{
_bfd_error_handler
(_("ERROR: Source object %B has EABI version %d, but target %B has EABI version %d"),
- ibfd, obfd,
+ ibfd,
(in_flags & EF_ARM_EABIMASK) >> 24,
+ obfd,
(out_flags & EF_ARM_EABIMASK) >> 24);
return FALSE;
}
@@ -3538,8 +3587,9 @@
{
_bfd_error_handler
(_("ERROR: %B is compiled for APCS-%d, whereas target %B uses APCS-%d"),
- ibfd, obfd,
+ ibfd,
in_flags & EF_ARM_APCS_26 ? 26 : 32,
+ obfd,
out_flags & EF_ARM_APCS_26 ? 26 : 32);
flags_compatible = FALSE;
}
@@ -3903,10 +3953,18 @@
eh = (struct elf32_arm_link_hash_entry *) h;
if (h->plt.refcount > 0)
+ h->plt.refcount -= 1;
+
+ if (ELF32_R_TYPE (rel->r_info) == R_ARM_THM_PC22)
{
- h->plt.refcount -= 1;
- if (ELF32_R_TYPE (rel->r_info) == R_ARM_THM_PC22)
- eh->plt_thumb_refcount--;
+ BFD_ASSERT (eh->plt_thumb_refcount > 0);
+ eh->plt_thumb_refcount--;
+ BFD_ASSERT (eh->accomodate_trampoline == 0);
+#if NOTE_DEBUG
+ _bfd_error_handler(
+ _("NOTE: %B: %x(%s): Thumb refcount decremented to %d (plt refcount %d)"),
+ abfd, h, h->root.root.string, eh->plt_thumb_refcount, h->plt.refcount);
+#endif
}
if (r_type == R_ARM_ABS32
@@ -3994,6 +4052,10 @@
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
eh = (struct elf32_arm_link_hash_entry *) h;
+#if NOTE_DEBUG
+ if (h != NULL)
+ _bfd_error_handler(_("NOTE: %B: %x(%s): verify relocation"), abfd, h, h->root.root.string);
+#endif
switch (r_type)
{
@@ -4078,10 +4140,30 @@
/* If we create a PLT entry, this relocation will reference
it, even if it's an ABS32 relocation. */
- h->plt.refcount += 1;
+ if (h->plt.refcount >= 0)
+ h->plt.refcount += 1;
+ else
+ {
+ /* This happens, I suspect it happens with glue code because,
+ * somehow, the backend data had can_refcount==0. Expert required...
+ */
+ _bfd_error_handler(
+ _("WARNING: %B: %x(%s): PLT refcount was %d (set to 1)"),
+ abfd, h, h->root.root.string, h->plt.refcount);
+ h->plt.refcount = 1;
+ }
if (r_type == R_ARM_THM_PC22)
- eh->plt_thumb_refcount += 1;
+ {
+ eh->plt_thumb_refcount += 1;
+ BFD_ASSERT (eh->plt_thumb_refcount <= h->plt.refcount);
+ BFD_ASSERT (eh->accomodate_trampoline == 0);
+#if NOTE_DEBUG
+ _bfd_error_handler(
+ _("NOTE: %B: %x(%s): Thumb refcount incremented to %d (plt refcount %d)"),
+ abfd, h, h->root.root.string, eh->plt_thumb_refcount, h->plt.refcount);
+#endif
+ }
}
/* If we are creating a shared library or relocatable executable,
@@ -4376,8 +4458,15 @@
object, or if all references were garbage collected. In
such a case, we don't actually need to build a procedure
linkage table, and we can just do a PC24 reloc instead. */
+#if NOTE_DEBUG
+ _bfd_error_handler(
+ _("NOTE: %x(%s): Thumb refcount zeroed (plt refcount %d, thumb %d) (%s)"),
+ h, h->root.root.string, h->plt.refcount, eh->plt_thumb_refcount,
+ SYMBOL_CALLS_LOCAL (info, h) ? "local call" : "invisible");
+#endif
h->plt.offset = (bfd_vma) -1;
eh->plt_thumb_refcount = 0;
+ BFD_ASSERT (eh->accomodate_trampoline == 0);
h->needs_plt = 0;
}
@@ -4390,8 +4479,14 @@
in check_relocs. We can't decide accurately between function
and non-function syms in check-relocs; Objects loaded later in
the link may change h->type. So fix it now. */
+#if NOTE_DEBUG
+ _bfd_error_handler(
+ _("NOTE: %x(%s): Thumb refcount zeroed (%d, plt refcount %d)"),
+ h, h->root.root.string, eh->plt_thumb_refcount, h->plt.refcount);
+#endif
h->plt.offset = (bfd_vma) -1;
eh->plt_thumb_refcount = 0;
+ BFD_ASSERT (eh->accomodate_trampoline == 0);
}
/* If this is a weak symbol, and there is a real definition, the
@@ -4521,8 +4616,14 @@
for it. */
if (!htab->symbian_p && eh->plt_thumb_refcount > 0)
{
+#if NOTE_DEBUG
+ _bfd_error_handler(_("NOTE: %x(%s): Thumb trampoline created at %x"),
+ h, h->root.root.string, h->plt.offset);
+#endif
h->plt.offset += PLT_THUMB_STUB_SIZE;
s->size += PLT_THUMB_STUB_SIZE;
+ BFD_ASSERT (eh->accomodate_trampoline == 0);
+ eh->accomodate_trampoline = 1;
}
/* If this symbol is not defined in a regular file, and we are
@@ -5014,10 +5115,20 @@
if (eh->plt_thumb_refcount > 0)
{
- bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[0],
- splt->contents + h->plt.offset - 4);
- bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[1],
- splt->contents + h->plt.offset - 2);
+ if (eh->accomodate_trampoline == 1)
+ {
+ bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[0],
+ splt->contents + h->plt.offset - 4);
+ bfd_put_16 (output_bfd, elf32_arm_plt_thumb_stub[1],
+ splt->contents + h->plt.offset - 2);
+ }
+ else
+ {
+ (*_bfd_error_handler) (
+ _("%B: no space for THUMB trampoline at %x[%x]"),
+ output_bfd, h->plt.offset, got_offset);
+ return FALSE;
+ }
}
bfd_put_32 (output_bfd, elf32_arm_plt_entry[0] | ((got_displacement & 0x0ff00000) >> 20),