summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2013-01-28 22:19:23 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2013-01-28 22:19:23 +0000
commita3eaf12bac914d461d0f490d21337b60231eb85d (patch)
tree9df0798dd0fd0296d4d896a569c503bcff60d16a /gnu
parent121f460c882d2e62ca6dde72f7f6acedd7fa34d7 (diff)
Correctly compute the relocation value of GOT_16[HL] relocations when they can
be resolved at link time, such as when linking a binary from objects which have been compiled PIC (one such case being perl's miniperl). While there, borrow the check and error message for GOT_16[HL] with nonzero addend (which can only happen with badly crafted .s files and do not behave like one may naively think they do) from elf32-ppc.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/binutils/bfd/elf32-m88k.c56
1 files changed, 27 insertions, 29 deletions
diff --git a/gnu/usr.bin/binutils/bfd/elf32-m88k.c b/gnu/usr.bin/binutils/bfd/elf32-m88k.c
index c960d17f946..a0333a7b644 100644
--- a/gnu/usr.bin/binutils/bfd/elf32-m88k.c
+++ b/gnu/usr.bin/binutils/bfd/elf32-m88k.c
@@ -1376,6 +1376,7 @@ elf_m88k_relocate_section (output_bfd, info, input_bfd, input_section,
for (; rel < relend; rel++)
{
int r_type;
+ const char *sym_name;
reloc_howto_type *howto;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
@@ -1404,6 +1405,8 @@ elf_m88k_relocate_section (output_bfd, info, input_bfd, input_section,
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
+ sym_name = bfd_elf_local_sym_name (input_bfd, sym);
+
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
}
else
@@ -1414,6 +1417,8 @@ elf_m88k_relocate_section (output_bfd, info, input_bfd, input_section,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
unresolved_reloc, warned);
+
+ sym_name = h->root.root.string;
}
switch (r_type)
@@ -1509,15 +1514,20 @@ elf_m88k_relocate_section (output_bfd, info, input_bfd, input_section,
}
}
- relocation = sgot->output_offset + off;
- if (r_type == R_88K_GOT_16L
- || r_type == R_88K_GOT_16H)
- {
- /* This relocation does not use the addend. */
- rel->r_addend = 0;
- }
- else
- relocation += sgot->output_section->vma;
+ /* Addends on got relocations don't make much sense.
+ x+off@got is actually x@got+off, and since the got is
+ generated by a hash table traversal, the value in the
+ got at entry m+n bears little relation to the entry m. */
+ if (rel->r_addend != 0)
+ (*_bfd_error_handler)
+ (_("%s(%s+0x%lx): non-zero addend on %s reloc against `%s'"),
+ bfd_archive_filename (input_bfd),
+ bfd_get_section_name (input_bfd, input_section),
+ (long) rel->r_offset,
+ howto->name,
+ sym_name);
+
+ relocation = sgot->output_section->vma + sgot->output_offset + off;
}
break;
@@ -1718,11 +1728,12 @@ elf_m88k_relocate_section (output_bfd, info, input_bfd, input_section,
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
{
(*_bfd_error_handler)
- (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+ (_("%s(%s+0x%lx): unresolvable %s relocation against symbol `%s'"),
bfd_archive_filename (input_bfd),
bfd_get_section_name (input_bfd, input_section),
(long) rel->r_offset,
- h->root.root.string);
+ howto->name,
+ sym_name);
return FALSE;
}
@@ -1732,35 +1743,22 @@ elf_m88k_relocate_section (output_bfd, info, input_bfd, input_section,
if (r != bfd_reloc_ok)
{
- const char *name;
-
- if (h != NULL)
- name = h->root.root.string;
- else
- {
- name = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
- if (name == NULL)
- return FALSE;
- if (*name == '\0')
- name = bfd_section_name (input_bfd, sec);
- }
-
+ if (sym_name == NULL)
+ sym_name = "(null)";
if (r == bfd_reloc_overflow)
{
if (!(info->callbacks->reloc_overflow
- (info, name, howto->name, (bfd_vma) 0,
+ (info, sym_name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset)))
return FALSE;
}
else
{
(*_bfd_error_handler)
- (_("%s(%s+0x%lx): reloc against `%s': error %d"),
+ (_("%s(%s+0x%lx): %s reloc against `%s': error %d"),
bfd_archive_filename (input_bfd),
bfd_get_section_name (input_bfd, input_section),
- (long) rel->r_offset, name, (int) r);
+ (long) rel->r_offset, howto->name, sym_name, (int) r);
return FALSE;
}
}