diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 13 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 1 | ||||
-rw-r--r-- | bfd/elf32-ppc.c | 17 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 33 | ||||
-rw-r--r-- | bfd/libbfd.h | 1 | ||||
-rw-r--r-- | bfd/reloc.c | 2 |
6 files changed, 60 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9f3df5f..a791fd0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2017-02-28 Alan Modra <amodra@gmail.com> + + * reloc.c (BFD_RELOC_PPC_16DX_HA): New. + * elf64-ppc.c (ppc64_elf_howto_raw <R_PPC64_16DX_HA>): New howto. + (ppc64_elf_reloc_type_lookup): Translate new bfd reloc. + (ppc64_elf_ha_reloc): Correct overflow test on REL16DX_HA. + (ppc64_elf_relocate_section): Likewise. + * elf32-ppc.c (ppc_elf_howto_raw <R_PPC_16DX_HA>): New howto. + (ppc_elf_reloc_type_lookup): Translate new bfd reloc. + (ppc_elf_check_relocs): Handle R_PPC_16DX_HA to pacify gcc. + * libbfd.h: Regenerate. + * bfd-in2.h: Regenerate. + 2017-02-24 Andrew Waterman <andrew@sifive.com> * elfnn-riscv.c (GP_NAME): New macro. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 816e930..6288c3b 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3360,6 +3360,7 @@ instruction. */ BFD_RELOC_PPC_VLE_SDAREL_HI16D, BFD_RELOC_PPC_VLE_SDAREL_HA16A, BFD_RELOC_PPC_VLE_SDAREL_HA16D, + BFD_RELOC_PPC_16DX_HA, BFD_RELOC_PPC_REL16DX_HA, BFD_RELOC_PPC64_HIGHER, BFD_RELOC_PPC64_HIGHER_S, diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 4ecbc91..b98e60d 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -1746,6 +1746,21 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 0x1fffc1, /* dst_mask */ TRUE), /* pcrel_offset */ + /* A split-field reloc for addpcis, non-relative (gas internal use only). */ + HOWTO (R_PPC_16DX_HA, /* type */ + 16, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc_elf_addr16_ha_reloc, /* special_function */ + "R_PPC_16DX_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1fffc1, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* GNU extension to record C++ vtable hierarchy. */ HOWTO (R_PPC_GNU_VTINHERIT, /* type */ 0, /* rightshift */ @@ -2002,6 +2017,7 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, case BFD_RELOC_LO16_PCREL: r = R_PPC_REL16_LO; break; case BFD_RELOC_HI16_PCREL: r = R_PPC_REL16_HI; break; case BFD_RELOC_HI16_S_PCREL: r = R_PPC_REL16_HA; break; + case BFD_RELOC_PPC_16DX_HA: r = R_PPC_16DX_HA; break; case BFD_RELOC_PPC_REL16DX_HA: r = R_PPC_REL16DX_HA; break; case BFD_RELOC_VTABLE_INHERIT: r = R_PPC_GNU_VTINHERIT; break; case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; break; @@ -4351,6 +4367,7 @@ ppc_elf_check_relocs (bfd *abfd, case R_PPC_RELAX: case R_PPC_RELAX_PLT: case R_PPC_RELAX_PLTREL24: + case R_PPC_16DX_HA: break; /* These should only appear in dynamic objects. */ diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 391ac1d..28fbbb8 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -2045,6 +2045,21 @@ static reloc_howto_type ppc64_elf_howto_raw[] = { 0x1fffc1, /* dst_mask */ TRUE), /* pcrel_offset */ + /* A split-field reloc for addpcis, non-relative (gas internal use only). */ + HOWTO (R_PPC64_16DX_HA, /* type */ + 16, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_ha_reloc, /* special_function */ + "R_PPC64_16DX_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x1fffc1, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* Like R_PPC64_ADDR16_HI, but no overflow. */ HOWTO (R_PPC64_ADDR16_HIGH, /* type */ 16, /* rightshift */ @@ -2450,6 +2465,8 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, break; case BFD_RELOC_HI16_S_PCREL: r = R_PPC64_REL16_HA; break; + case BFD_RELOC_PPC_16DX_HA: r = R_PPC64_16DX_HA; + break; case BFD_RELOC_PPC_REL16DX_HA: r = R_PPC64_REL16DX_HA; break; case BFD_RELOC_PPC64_ENTRY: r = R_PPC64_ENTRY; @@ -2512,7 +2529,7 @@ ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, enum elf_ppc64_reloc_type r_type; long insn; bfd_size_type octets; - bfd_vma value; + bfd_vma value, field; /* If this is a relocatable link (output_bfd test tells us), just call the generic function. Any adjustment will be done at final @@ -2538,14 +2555,14 @@ ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, value -= (reloc_entry->address + input_section->output_offset + input_section->output_section->vma); - value = (bfd_signed_vma) value >> 16; + field = (bfd_signed_vma) value >> 16; octets = reloc_entry->address * bfd_octets_per_byte (abfd); insn = bfd_get_32 (abfd, (bfd_byte *) data + octets); insn &= ~0x1fffc1; - insn |= (value & 0xffc1) | ((value & 0x3e) << 15); + insn |= (field & 0xffc1) | ((field & 0x3e) << 15); bfd_put_32 (abfd, insn, (bfd_byte *) data + octets); - if (value + 0x8000 > 0xffff) + if (value + 0x80000000 > 0xffffffff) return bfd_reloc_overflow; return bfd_reloc_ok; } @@ -15205,17 +15222,19 @@ ppc64_elf_relocate_section (bfd *output_bfd, r = bfd_reloc_outofrange; else { + bfd_signed_vma field; + relocation += addend; relocation -= (rel->r_offset + input_section->output_offset + input_section->output_section->vma); - relocation = (bfd_signed_vma) relocation >> 16; + field = (bfd_signed_vma) relocation >> 16; insn = bfd_get_32 (input_bfd, contents + rel->r_offset); insn &= ~0x1fffc1; - insn |= (relocation & 0xffc1) | ((relocation & 0x3e) << 15); + insn |= (field & 0xffc1) | ((field & 0x3e) << 15); bfd_put_32 (input_bfd, insn, contents + rel->r_offset); r = bfd_reloc_ok; - if (relocation + 0x8000 > 0xffff) + if (relocation + 0x80000000 > 0xffffffff) r = bfd_reloc_overflow; } } diff --git a/bfd/libbfd.h b/bfd/libbfd.h index eb0a97a..3aa042d 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1397,6 +1397,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_PPC_VLE_SDAREL_HI16D", "BFD_RELOC_PPC_VLE_SDAREL_HA16A", "BFD_RELOC_PPC_VLE_SDAREL_HA16D", + "BFD_RELOC_PPC_16DX_HA", "BFD_RELOC_PPC_REL16DX_HA", "BFD_RELOC_PPC64_HIGHER", "BFD_RELOC_PPC64_HIGHER_S", diff --git a/bfd/reloc.c b/bfd/reloc.c index b0d14ed..9021a52 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2901,6 +2901,8 @@ ENUMX ENUMX BFD_RELOC_PPC_VLE_SDAREL_HA16D ENUMX + BFD_RELOC_PPC_16DX_HA +ENUMX BFD_RELOC_PPC_REL16DX_HA ENUMX BFD_RELOC_PPC64_HIGHER |