+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-28 Alan Modra <amodra@gmail.com>
* elflink.c (_bfd_elf_create_dynamic_sections): Don't make
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,
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 */
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;
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. */
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 */
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;
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
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;
}
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;
}
}
"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",
BFD_RELOC_PPC_VLE_SDAREL_HA16A
ENUMX
BFD_RELOC_PPC_VLE_SDAREL_HA16D
+ENUMX
+ BFD_RELOC_PPC_16DX_HA
ENUMX
BFD_RELOC_PPC_REL16DX_HA
ENUMX
+2017-02-28 Alan Modra <amodra@gmail.com>
+
+ * config/tc-ppc.c (md_assemble): Use BFD_RELOC_PPC_16DX_HA for addpcis.
+ (md_apply_fix): Remove fx_subsy check. Move code converting to
+ pcrel reloc earlier and handle BFD_RELOC_PPC_16DX_HA. Remove code
+ emiiting errors on seeing fx_pcrel set on unexpected relocs, as
+ that is done now by the generic code via..
+ * config/tc-ppc.h (TC_FORCE_RELOCATION_SUB_LOCAL): ..this. Define.
+ (TC_VALIDATE_FIX_SUB): Define.
+
2017-02-28 Maciej W. Rozycki <macro@imgtec.com>
* testsuite/gas/mips/jalr4.s: Add `jalr $0, $25' instructions.
/* addpcis. */
if (opcode->opcode == (19 << 26) + (2 << 1)
&& reloc == BFD_RELOC_HI16_S)
- reloc = BFD_RELOC_PPC_REL16DX_HA;
+ reloc = BFD_RELOC_PPC_16DX_HA;
/* If VLE-mode convert LO/HI/HA relocations. */
if (opcode->flags & PPC_OPCODE_VLE)
}
#endif
- if (fixP->fx_subsy != (symbolS *) NULL)
+ /* We are only able to convert some relocs to pc-relative. */
+ if (fixP->fx_pcrel)
+ {
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_LO16:
+ fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
+ break;
+
+ case BFD_RELOC_HI16:
+ fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
+ break;
+
+ case BFD_RELOC_HI16_S:
+ fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
+ break;
+
+ case BFD_RELOC_64:
+ fixP->fx_r_type = BFD_RELOC_64_PCREL;
+ break;
+
+ case BFD_RELOC_32:
+ fixP->fx_r_type = BFD_RELOC_32_PCREL;
+ break;
+
+ case BFD_RELOC_16:
+ fixP->fx_r_type = BFD_RELOC_16_PCREL;
+ break;
+
+ case BFD_RELOC_PPC_16DX_HA:
+ fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (!fixP->fx_done
+ && fixP->fx_r_type == BFD_RELOC_PPC_16DX_HA)
{
- /* We can't actually support subtracting a symbol. */
- as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
+ /* addpcis is relative to next insn address. */
+ value -= 4;
+ fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
+ fixP->fx_pcrel = 1;
}
operand = NULL;
case BFD_RELOC_HI16_S:
case BFD_RELOC_HI16_S_PCREL:
+ case BFD_RELOC_PPC_16DX_HA:
case BFD_RELOC_PPC_REL16DX_HA:
#ifdef OBJ_ELF
if (REPORT_OVERFLOW_HI && ppc_obj64)
_("data in executable section"));
}
- /* We are only able to convert some relocs to pc-relative. */
- if (!fixP->fx_done && fixP->fx_pcrel)
- {
- switch (fixP->fx_r_type)
- {
- case BFD_RELOC_LO16:
- fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
- break;
-
- case BFD_RELOC_HI16:
- fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
- break;
-
- case BFD_RELOC_HI16_S:
- fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
- break;
-
- case BFD_RELOC_64:
- fixP->fx_r_type = BFD_RELOC_64_PCREL;
- break;
-
- case BFD_RELOC_32:
- fixP->fx_r_type = BFD_RELOC_32_PCREL;
- break;
-
- case BFD_RELOC_16:
- fixP->fx_r_type = BFD_RELOC_16_PCREL;
- break;
-
- /* Some of course are already pc-relative. */
- case BFD_RELOC_LO16_PCREL:
- case BFD_RELOC_HI16_PCREL:
- case BFD_RELOC_HI16_S_PCREL:
- case BFD_RELOC_PPC_REL16DX_HA:
- case BFD_RELOC_64_PCREL:
- case BFD_RELOC_32_PCREL:
- case BFD_RELOC_16_PCREL:
- case BFD_RELOC_PPC_B16:
- case BFD_RELOC_PPC_B16_BRTAKEN:
- case BFD_RELOC_PPC_B16_BRNTAKEN:
- case BFD_RELOC_PPC_B26:
- case BFD_RELOC_PPC_LOCAL24PC:
- case BFD_RELOC_24_PLT_PCREL:
- case BFD_RELOC_32_PLT_PCREL:
- case BFD_RELOC_64_PLT_PCREL:
- case BFD_RELOC_PPC_VLE_REL8:
- case BFD_RELOC_PPC_VLE_REL15:
- case BFD_RELOC_PPC_VLE_REL24:
- break;
-
- default:
- if (fixP->fx_addsy)
- {
- const char *sfile;
- unsigned int sline;
-
- /* Use expr_symbol_where to see if this is an
- expression symbol. */
- if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("unresolved expression that must"
- " be resolved"));
- else
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("cannot emit PC relative %s relocation"
- " against %s"),
- bfd_get_reloc_code_name (fixP->fx_r_type),
- S_GET_NAME (fixP->fx_addsy));
- }
- else
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("unable to resolve expression"));
- fixP->fx_done = 1;
- break;
- }
- }
-
#ifdef OBJ_ELF
ppc_elf_validate_fix (fixP, seg);
fixP->fx_addnumber = value;
extern int ppc_force_relocation (struct fix *);
#endif
+#ifdef OBJ_ELF
+/* Don't allow the generic code to convert fixups involving the
+ subtraction of a label in the current section to pc-relative if we
+ don't have the necessary pc-relative relocation. */
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) \
+ (!((FIX)->fx_r_type == BFD_RELOC_LO16 \
+ || (FIX)->fx_r_type == BFD_RELOC_HI16 \
+ || (FIX)->fx_r_type == BFD_RELOC_HI16_S \
+ || (FIX)->fx_r_type == BFD_RELOC_64 \
+ || (FIX)->fx_r_type == BFD_RELOC_32 \
+ || (FIX)->fx_r_type == BFD_RELOC_16 \
+ || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA))
+#endif
+
+#define TC_VALIDATE_FIX_SUB(FIX, SEG) 0
+
/* call md_pcrel_from_section, not md_pcrel_from */
#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC)
extern long md_pcrel_from_section (struct fix *, segT);
+2017-02-28 Alan Modra <amodra@gmail.com>
+
+ * elf/ppc64.h (R_PPC64_16DX_HA): New. Expand fake reloc comment.
+ * elf/ppc.h (R_PPC_16DX_HA): Likewise.
+
2017-02-24 Richard Sandiford <richard.sandiford@arm.com>
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4x16)
RELOC_NUMBER (R_PPC_ADDR30, 37)
#ifndef RELOC_MACROS_GEN_FUNC
-/* Fake relocations for branch stubs, only used internally by ld. */
+/* Relocations only used internally by ld. If you need to use these
+ reloc numbers, you can change them to some other unused value
+ without affecting the ABI. They will never appear in object files. */
RELOC_NUMBER (R_PPC_RELAX, 48)
RELOC_NUMBER (R_PPC_RELAX_PLT, 49)
RELOC_NUMBER (R_PPC_RELAX_PLTREL24, 50)
+/* Reloc only used internally by gas. As above, value is unimportant. */
+ RELOC_NUMBER (R_PPC_16DX_HA, 51)
#endif
/* Relocs added to support TLS. */
RELOC_NUMBER (R_PPC64_ENTRY, 118)
#ifndef RELOC_MACROS_GEN_FUNC
-/* Fake relocation only used internally by ld. */
+/* Relocation only used internally by ld. If you need to use these
+ reloc numbers, you can change them to some other unused value
+ without affecting the ABI. They will never appear in object files. */
RELOC_NUMBER (R_PPC64_LO_DS_OPT, 128)
+/* Reloc only used internally by gas. As above, value is unimportant. */
+ RELOC_NUMBER (R_PPC64_16DX_HA, 129)
#endif
/* Power9 split rel16 for addpcis. */
+2017-02-28 Alan Modra <amodra@gmail.com>
+
+ * testsuite/ld-powerpc/addpcis.d: Define ext1 and ext2 at
+ limits of addpcis range.
+
2017-02-28 Maciej W. Rozycki <macro@imgtec.com>
* testsuite/ld-mips-elf/jalr4.dd: Adjust for `jalr $0, $25'
#source: addpcis.s
#as: -a64 -mpower9
-#ld: -melf64ppc -Ttext=0x10000000 --defsym ext1=0 --defsym ext2=0x8fff0000
+#ld: -melf64ppc -Ttext=0x10000000 --defsym ext1=-0x70007ffc --defsym ext2=0x8fff800b
#objdump: -d -Mpower9
.*: file format .*
Disassembly of section \.text:
0+10000000 <_start>:
- 10000000: (4c 60 f0 04|04 f0 60 4c) addpcis r3,-4096
- 10000004: (38 63 ff fc|fc ff 63 38) addi r3,r3,-4
+ 10000000: (4c 60 80 04|04 80 60 4c) addpcis r3,-32768
+ 10000004: (38 63 80 00|00 80 63 38) addi r3,r3,-32768
10000008: (4c 9f 7f c5|c5 7f 9f 4c) addpcis r4,32767
- 1000000c: (38 84 ff f4|f4 ff 84 38) addi r4,r4,-12
+ 1000000c: (38 84 7f ff|ff 7f 84 38) addi r4,r4,32767
10000010: (4c a0 00 05|05 00 a0 4c) addpcis r5,1
10000014: (38 a5 80 00|00 80 a5 38) addi r5,r5,-32768
\.\.\.