X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-sh.c;h=9200e6a19291b2af48b8a9903f8892933dae0b7d;hb=75c6c844d9df37761e0e834df057b89e41816e55;hp=c10691e422ca50fc228c29b70d8bcb34679ed87d;hpb=6d6c25c8eaaf42755a759beeb2996502322b960c;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index c10691e422..9200e6a192 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -1,5 +1,5 @@ /* Renesas / SuperH SH specific support for 32-bit ELF - Copyright (C) 1996-2019 Free Software Foundation, Inc. + Copyright (C) 1996-2020 Free Software Foundation, Inc. Contributed by Ian Lance Taylor, Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -30,6 +30,9 @@ #include "libiberty.h" #include "../opcodes/sh-opc.h" +/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ +#define OCTETS_PER_BYTE(ABFD, SEC) 1 + static bfd_reloc_status_type sh_elf_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type sh_elf_ignore_reloc @@ -229,11 +232,12 @@ sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in, void *data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { - unsigned long insn; + bfd_vma insn; bfd_vma sym_value; enum elf_sh_reloc_type r_type; bfd_vma addr = reloc_entry->address; - bfd_byte *hit_data = addr + (bfd_byte *) data; + bfd_size_type octets = addr * OCTETS_PER_BYTE (abfd, input_section); + bfd_byte *hit_data = (bfd_byte *) data + octets; r_type = (enum elf_sh_reloc_type) reloc_entry->howto->type; @@ -254,7 +258,7 @@ sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in, return bfd_reloc_undefined; /* PR 17512: file: 9891ca98. */ - if (addr * bfd_octets_per_byte (abfd) + bfd_get_reloc_size (reloc_entry->howto) + if (octets + bfd_get_reloc_size (reloc_entry->howto) > bfd_get_section_limit_octets (abfd, input_section)) return bfd_reloc_outofrange; @@ -270,7 +274,7 @@ sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in, case R_SH_DIR32: insn = bfd_get_32 (abfd, hit_data); insn += sym_value + reloc_entry->addend; - bfd_put_32 (abfd, (bfd_vma) insn, hit_data); + bfd_put_32 (abfd, insn, hit_data); break; case R_SH_IND12W: insn = bfd_get_16 (abfd, hit_data); @@ -279,12 +283,10 @@ sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in, + input_section->output_offset + addr + 4); - sym_value += (insn & 0xfff) << 1; - if (insn & 0x800) - sym_value -= 0x1000; - insn = (insn & 0xf000) | (sym_value & 0xfff); - bfd_put_16 (abfd, (bfd_vma) insn, hit_data); - if (sym_value < (bfd_vma) -0x1000 || sym_value >= 0x1000) + sym_value += (((insn & 0xfff) ^ 0x800) - 0x800) << 1; + insn = (insn & 0xf000) | ((sym_value >> 1) & 0xfff); + bfd_put_16 (abfd, insn, hit_data); + if (sym_value + 0x1000 >= 0x2000 || (sym_value & 1) != 0) return bfd_reloc_overflow; break; default: