(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
static bfd_reloc_status_type ppc_elf_unhandled_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static void ppc_elf_vle_split16
- (bfd *, bfd_byte *, bfd_vma, bfd_vma, split16_format_type);
/* Branch prediction bit for branch taken relocs. */
#define BRANCH_PREDICT_BIT 0x200000
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_NONE", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR32", /* name */
FALSE, /* partial_inplace */
26, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR24", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR14", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR14_BRTAKEN",/* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_ADDR14_BRNTAKEN",/* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_GOT16_HI", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
ppc_elf_addr16_ha_reloc, /* special_function */
"R_PPC_GOT16_HA", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_COPY", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_GLOB_DAT", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_JMP_SLOT", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_RELATIVE", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_UADDR32", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_REL32", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PLT32", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PLTREL32", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_PLT16_HI", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
ppc_elf_addr16_ha_reloc, /* special_function */
"R_PPC_PLT16_HA", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_SECTOFF", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_SECTOFF_HI", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
ppc_elf_addr16_ha_reloc, /* special_function */
"R_PPC_SECTOFF_HA", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_NADDR32", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_EMB_NADDR16", /* name */
FALSE, /* partial_inplace */
HOWTO (R_PPC_VLE_LO16A, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_LO16A", /* name */
FALSE, /* partial_inplace */
HOWTO (R_PPC_VLE_LO16D, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_LO16D", /* name */
FALSE, /* partial_inplace */
/* Bits 16-31 split16a format. */
HOWTO (R_PPC_VLE_HI16A, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_HI16A", /* name */
FALSE, /* partial_inplace */
/* Bits 16-31 split16d format. */
HOWTO (R_PPC_VLE_HI16D, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_HI16D", /* name */
FALSE, /* partial_inplace */
/* Bits 16-31 (High Adjusted) in split16a format. */
HOWTO (R_PPC_VLE_HA16A, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_HA16A", /* name */
FALSE, /* partial_inplace */
/* Bits 16-31 (High Adjusted) in split16d format. */
HOWTO (R_PPC_VLE_HA16D, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_HA16D", /* name */
FALSE, /* partial_inplace */
0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
- /* This reloc does nothing. */
- HOWTO (R_PPC_VLE_SDA21, /* type */
+ /* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i
+ instructions. If the register base is 0 then the linker changes
+ the e_add16i to an e_li instruction. */
+ HOWTO (R_PPC_VLE_SDA21, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_SDA21", /* name */
FALSE, /* partial_inplace */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
- /* This reloc does nothing. */
+ /* Like R_PPC_VLE_SDA21 but ignore overflow. */
HOWTO (R_PPC_VLE_SDA21_LO, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_SDA21_LO", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0, /* dst_mask */
+ 0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* The 16 LSBS relative to _SDA_BASE_ in split16a format. */
HOWTO (R_PPC_VLE_SDAREL_LO16A,/* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_SDAREL_LO16A", /* name */
FALSE, /* partial_inplace */
FALSE), /* pcrel_offset */
/* The 16 LSBS relative to _SDA_BASE_ in split16d format. */
- /* This reloc does nothing. */
HOWTO (R_PPC_VLE_SDAREL_LO16D, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_SDAREL_LO16D", /* name */
FALSE, /* partial_inplace */
/* Bits 16-31 relative to _SDA_BASE_ in split16a format. */
HOWTO (R_PPC_VLE_SDAREL_HI16A, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_SDAREL_HI16A", /* name */
FALSE, /* partial_inplace */
/* Bits 16-31 relative to _SDA_BASE_ in split16d format. */
HOWTO (R_PPC_VLE_SDAREL_HI16D, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_SDAREL_HI16D", /* name */
FALSE, /* partial_inplace */
/* Bits 16-31 (HA) relative to _SDA_BASE split16a format. */
HOWTO (R_PPC_VLE_SDAREL_HA16A, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_SDAREL_HA16A", /* name */
FALSE, /* partial_inplace */
/* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */
HOWTO (R_PPC_VLE_SDAREL_HA16D, /* type */
- 0, /* rightshift */
+ 16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_SDAREL_HA16D", /* name */
FALSE, /* partial_inplace */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_IRELATIVE", /* name */
FALSE, /* partial_inplace */
16, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield, /* complain_on_overflow */
+ complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_REL16", /* name */
FALSE, /* partial_inplace */
}
static void
-ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *contents,
- bfd_vma offset, bfd_vma relocation,
- split16_format_type split16_format)
+ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *loc,
+ bfd_vma value,
+ split16_format_type split16_format)
{
- bfd_vma insn, top5, bottom11;
+ unsigned int insn, top5;
- insn = bfd_get_32 (output_bfd, contents + offset);
- top5 = relocation >> 11;
- top5 = top5 << (split16_format == split16a_type ? 20 : 16);
- bottom11 = relocation & 0x7ff;
+ insn = bfd_get_32 (output_bfd, loc);
+ top5 = value & 0xf800;
+ top5 = top5 << (split16_format == split16a_type ? 9 : 5);
insn |= top5;
- insn |= bottom11;
- bfd_put_32 (output_bfd, insn, contents + offset);
+ insn |= value & 0x7ff;
+ bfd_put_32 (output_bfd, insn, loc);
}
\f
bfd_boolean warned;
unsigned int tls_type, tls_mask, tls_gd;
struct plt_entry **ifunc;
+ struct reloc_howto_struct alt_howto;
r_type = ELF32_R_TYPE (rel->r_info);
sym = NULL;
howto->name,
sym_name);
}
- break;
+ break;
- /* Relocations that need no special processing. */
+ /* Relocations that need no special processing. */
case R_PPC_LOCAL24PC:
/* It makes no sense to point a local relocation
at a symbol not in this object. */
break;
case R_PPC_VLE_LO16A:
- relocation = (relocation + addend) & 0xffff;
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- relocation, split16a_type);
+ relocation = relocation + addend;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ relocation, split16a_type);
continue;
case R_PPC_VLE_LO16D:
- relocation = (relocation + addend) & 0xffff;
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- relocation, split16d_type);
+ relocation = relocation + addend;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ relocation, split16d_type);
continue;
case R_PPC_VLE_HI16A:
- relocation = ((relocation + addend) >> 16) & 0xffff;
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- relocation, split16a_type);
+ relocation = (relocation + addend) >> 16;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ relocation, split16a_type);
continue;
case R_PPC_VLE_HI16D:
- relocation = ((relocation + addend) >> 16) & 0xffff;
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- relocation, split16d_type);
+ relocation = (relocation + addend) >> 16;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ relocation, split16d_type);
continue;
case R_PPC_VLE_HA16A:
- {
- bfd_vma value = relocation + addend;
- value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff);
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- value, split16a_type);
- }
+ relocation = (relocation + addend + 0x8000) >> 16;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ relocation, split16a_type);
continue;
case R_PPC_VLE_HA16D:
- {
- bfd_vma value = relocation + addend;
- value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff);
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- value, split16d_type);
- }
+ relocation = (relocation + addend + 0x8000) >> 16;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ relocation, split16d_type);
continue;
/* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */
{
const char *name;
int reg;
+ unsigned int insn;
struct elf_link_hash_entry *sda = NULL;
if (sec == NULL || sec->output_section == NULL)
addend -= SYM_VAL (sda);
}
+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
if (reg == 0
&& (r_type == R_PPC_VLE_SDA21
|| r_type == R_PPC_VLE_SDA21_LO))
{
- /* Use the split20 format. */
- bfd_vma insn, bits12to15, bits21to31;
- bfd_vma value = (relocation + rel->r_offset) & 0xffff;
- /* Propagate sign bit, if necessary. */
- insn = (value & 0x8000) ? 0x70107800 : 0x70000000;
- bits12to15 = value & 0x700;
- bits21to31 = value & 0x7ff;
- insn |= bits12to15;
- insn |= bits21to31;
- bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
- continue;
+ relocation = relocation + addend;
+ addend = 0;
+
+ /* Force e_li insn, keeping RT from original insn. */
+ insn &= 0x1f << 21;
+ insn |= 28u << 26;
+
+ /* We have an li20 field, bits 17..20, 11..15, 21..31. */
+ /* Top 4 bits of value to 17..20. */
+ insn |= (relocation & 0xf0000) >> 5;
+ /* Next 5 bits of the value to 11..15. */
+ insn |= (relocation & 0xf800) << 5;
+ /* And the final 11 bits of the value to bits 21 to 31. */
+ insn |= relocation & 0x7ff;
+
+ /* Use _bfd_final_link_relocate to report overflow,
+ but do so with a value that won't modify the insn. */
+ if (relocation + 0x80000 > 0x100000)
+ addend = 0x100000;
+ relocation = 0;
}
else if (r_type == R_PPC_EMB_SDA21
|| r_type == R_PPC_VLE_SDA21
|| r_type == R_PPC_VLE_SDA21_LO)
{
- bfd_vma insn; /* Fill in register field. */
-
- insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+ /* Fill in register field. */
insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
- bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
}
+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
}
break;
}
}
- value = sda->root.u.def.section->output_section->vma
- + sda->root.u.def.section->output_offset;
-
- if (r_type == R_PPC_VLE_SDAREL_LO16A)
- {
- value = (value + addend) & 0xffff;
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- value, split16a_type);
- }
- else if (r_type == R_PPC_VLE_SDAREL_LO16D)
- {
- value = (value + addend) & 0xffff;
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- value, split16d_type);
- }
- else if (r_type == R_PPC_VLE_SDAREL_HI16A)
+ value = (sda->root.u.def.section->output_section->vma
+ + sda->root.u.def.section->output_offset
+ + addend);
+
+ if (r_type == R_PPC_VLE_SDAREL_LO16A)
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ value, split16a_type);
+ else if (r_type == R_PPC_VLE_SDAREL_LO16D)
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ value, split16d_type);
+ else if (r_type == R_PPC_VLE_SDAREL_HI16A)
{
- value = ((value + addend) >> 16) & 0xffff;
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- value, split16a_type);
+ value = value >> 16;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ value, split16a_type);
}
- else if (r_type == R_PPC_VLE_SDAREL_HI16D)
+ else if (r_type == R_PPC_VLE_SDAREL_HI16D)
{
- value = ((value + addend) >> 16) & 0xffff;
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- value, split16d_type);
+ value = value >> 16;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ value, split16d_type);
}
- else if (r_type == R_PPC_VLE_SDAREL_HA16A)
+ else if (r_type == R_PPC_VLE_SDAREL_HA16A)
{
- value += addend;
- value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff);
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- value, split16a_type);
+ value = (value + 0x8000) >> 16;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ value, split16a_type);
}
- else if (r_type == R_PPC_VLE_SDAREL_HA16D)
+ else if (r_type == R_PPC_VLE_SDAREL_HA16D)
{
- value += addend;
- value = (((value >> 16) + ((value & 0x8000) ? 1 : 0)) & 0xffff);
- ppc_elf_vle_split16 (output_bfd, contents, rel->r_offset,
- value, split16d_type);
+ value = (value + 0x8000) >> 16;
+ ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
+ value, split16d_type);
}
}
continue;
ret = FALSE;
}
- r = _bfd_final_link_relocate (howto,
- input_bfd,
- input_section,
- contents,
- rel->r_offset,
- relocation,
- addend);
+ /* 16-bit fields in insns mostly have signed values, but a
+ few insns have 16-bit unsigned values. Really, we should
+ have different reloc types. */
+ if (howto->complain_on_overflow != complain_overflow_dont
+ && howto->dst_mask == 0xffff
+ && (input_section->flags & SEC_CODE) != 0)
+ {
+ enum complain_overflow complain = complain_overflow_signed;
+
+ if ((elf_section_flags (input_section) & SHF_PPC_VLE) == 0)
+ {
+ unsigned int insn;
+
+ insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
+ if ((insn & (0x3f << 26)) == 28u << 26 /* andi */
+ || (insn & (0x3f << 26)) == 24u << 26 /* ori */
+ || (insn & (0x3f << 26)) == 26u << 26 /* xori */
+ || (insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
+ complain = complain_overflow_unsigned;
+ }
+ if (howto->complain_on_overflow != complain)
+ {
+ alt_howto = *howto;
+ alt_howto.complain_on_overflow = complain;
+ howto = &alt_howto;
+ }
+ }
+
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
+ rel->r_offset, relocation, addend);
if (r != bfd_reloc_ok)
{