diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-01-28 22:19:23 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-01-28 22:19:23 +0000 |
commit | a3eaf12bac914d461d0f490d21337b60231eb85d (patch) | |
tree | 9df0798dd0fd0296d4d896a569c503bcff60d16a /gnu | |
parent | 121f460c882d2e62ca6dde72f7f6acedd7fa34d7 (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.c | 56 |
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; } } |