FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_GOT16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_GOT16_LO", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_GOT16_HI", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- ppc_elf_addr16_ha_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_GOT16_HA", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
26, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_PLTREL24", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_COPY", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_GLOB_DAT", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_JMP_SLOT", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_PLT32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_PLTREL32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_PLT16_LO", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_PLT16_HI", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- ppc_elf_addr16_ha_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_PLT16_HA", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_SDAREL16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_SECTOFF", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_SECTOFF_LO", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_SECTOFF_HI", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- ppc_elf_addr16_ha_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_SECTOFF_HA", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_NADDR32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_NADDR16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_ADDR16_LO", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_NADDR16_HI", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- ppc_elf_addr16_ha_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_NADDR16_HA", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_SDAI16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_SDA2I16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_SDA2REL", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_SDA21", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_EMB_RELSDA", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
"R_PPC_VLE_REL15", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0xfe, /* dst_mask */
+ 0xfffe, /* dst_mask */
TRUE), /* pcrel_offset */
/* A relative 24 bit branch. */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_VLE_LO16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_LO16D", /* name */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_LO16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f07ff, /* dst_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_HI16A", /* name */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_HI16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f007ff, /* dst_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_HI16D", /* name */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_HI16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f07ff, /* dst_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_HA16A", /* name */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_HA16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f007ff, /* dst_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_HA16D", /* name */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_HA16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f07ff, /* dst_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_SDA21", /* name */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_SDA21", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0xffff, /* dst_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_VLE_SDA21_LO", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_SDAREL_LO16A", /* name */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_SDAREL_LO16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f007ff, /* dst_mask */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_SDAREL_LO16D", /* name */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_SDAREL_LO16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 relative to _SDA_BASE_ in split16a format. */
- HOWTO (R_PPC_VLE_SDAREL_HI16A, /* type */
+ HOWTO (R_PPC_VLE_SDAREL_HI16A, /* type */
16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_SDAREL_HI16A", /* name */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_SDAREL_HI16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 relative to _SDA_BASE_ in split16d format. */
- HOWTO (R_PPC_VLE_SDAREL_HI16D, /* type */
+ HOWTO (R_PPC_VLE_SDAREL_HI16D, /* type */
16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_SDAREL_HI16D", /* name */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_SDAREL_HI16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 (HA) relative to _SDA_BASE split16a format. */
- HOWTO (R_PPC_VLE_SDAREL_HA16A, /* type */
+ HOWTO (R_PPC_VLE_SDAREL_HA16A, /* type */
16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_SDAREL_HA16A", /* name */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_SDAREL_HA16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */
- HOWTO (R_PPC_VLE_SDAREL_HA16D, /* type */
+ HOWTO (R_PPC_VLE_SDAREL_HA16D, /* type */
16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_PPC_VLE_SDAREL_HA16D", /* name */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_elf_unhandled_reloc, /* special_function */
+ "R_PPC_VLE_SDAREL_HA16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x1f07ff, /* dst_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_IRELATIVE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ ppc_elf_unhandled_reloc, /* special_function */
"R_PPC_TOC16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
PPC32_ELF_DATA);
}
+/* When defaulting arch/mach, decode apuinfo to find a better match. */
+
+bfd_boolean
+_bfd_elf_ppc_set_arch (bfd *abfd)
+{
+ unsigned long mach = 0;
+ asection *s;
+ unsigned char *contents;
+
+ if (abfd->arch_info->bits_per_word == 32
+ && bfd_big_endian (abfd))
+ {
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ if ((elf_section_data (s)->this_hdr.sh_flags & SHF_PPC_VLE) != 0)
+ break;
+ if (s != NULL)
+ mach = bfd_mach_ppc_vle;
+ }
+
+ if (mach == 0)
+ {
+ s = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
+ if (s != NULL && bfd_malloc_and_get_section (abfd, s, &contents))
+ {
+ unsigned int apuinfo_size = bfd_get_32 (abfd, contents + 4);
+ unsigned int i;
+
+ for (i = 20; i < apuinfo_size + 20 && i + 4 <= s->size; i += 4)
+ {
+ unsigned int val = bfd_get_32 (abfd, contents + i);
+ switch (val >> 16)
+ {
+ case PPC_APUINFO_PMR:
+ case PPC_APUINFO_RFMCI:
+ if (mach == 0)
+ mach = bfd_mach_ppc_titan;
+ break;
+
+ case PPC_APUINFO_ISEL:
+ case PPC_APUINFO_CACHELCK:
+ if (mach == bfd_mach_ppc_titan)
+ mach = bfd_mach_ppc_e500mc;
+ break;
+
+ case PPC_APUINFO_SPE:
+ case PPC_APUINFO_EFS:
+ case PPC_APUINFO_BRLOCK:
+ if (mach != bfd_mach_ppc_vle)
+ mach = bfd_mach_ppc_e500;
+
+ case PPC_APUINFO_VLE:
+ mach = bfd_mach_ppc_vle;
+ break;
+
+ default:
+ mach = -1ul;
+ }
+ }
+ free (contents);
+ }
+ }
+
+ if (mach != 0 && mach != -1ul)
+ {
+ const bfd_arch_info_type *arch;
+
+ for (arch = abfd->arch_info->next; arch; arch = arch->next)
+ if (arch->mach == mach)
+ {
+ abfd->arch_info = arch;
+ break;
+ }
+ }
+ return TRUE;
+}
+
/* Fix bad default arch selected for a 32 bit input bfd when the
- default is 64 bit. */
+ default is 64 bit. Also select arch based on apuinfo. */
static bfd_boolean
ppc_elf_object_p (bfd *abfd)
{
- if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 64)
+ if (!abfd->arch_info->the_default)
+ return TRUE;
+
+ if (abfd->arch_info->bits_per_word == 64)
{
Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd);
BFD_ASSERT (abfd->arch_info->bits_per_word == 32);
}
}
- return TRUE;
+ return _bfd_elf_ppc_set_arch (abfd);
}
/* Function to set whether a module needs the -mrelocatable bit set. */
static const struct bfd_elf_special_section ppc_elf_special_sections[] =
{
- { STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, SHF_ALLOC + SHF_EXECINSTR },
- { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
- { STRING_COMMA_LEN (".sbss2"), -2, SHT_PROGBITS, SHF_ALLOC },
- { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { STRING_COMMA_LEN (".sdata2"), -2, SHT_PROGBITS, SHF_ALLOC },
- { STRING_COMMA_LEN (".tags"), 0, SHT_ORDERED, SHF_ALLOC },
- { STRING_COMMA_LEN (".PPC.EMB.apuinfo"), 0, SHT_NOTE, 0 },
- { STRING_COMMA_LEN (".PPC.EMB.sbss0"), 0, SHT_PROGBITS, SHF_ALLOC },
- { STRING_COMMA_LEN (".PPC.EMB.sdata0"), 0, SHT_PROGBITS, SHF_ALLOC },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".sbss2"), -2, SHT_PROGBITS, SHF_ALLOC },
+ { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".sdata2"), -2, SHT_PROGBITS, SHF_ALLOC },
+ { STRING_COMMA_LEN (".tags"), 0, SHT_ORDERED, SHF_ALLOC },
+ { STRING_COMMA_LEN (APUINFO_SECTION_NAME), 0, SHT_NOTE, 0 },
+ { STRING_COMMA_LEN (".PPC.EMB.sbss0"), 0, SHT_PROGBITS, SHF_ALLOC },
+ { STRING_COMMA_LEN (".PPC.EMB.sdata0"), 0, SHT_PROGBITS, SHF_ALLOC },
+ { NULL, 0, 0, 0, 0 }
};
/* This is what we want for new plt/got. */
head = NULL;
}
-#define APUINFO_SECTION_NAME ".PPC.EMB.apuinfo"
-#define APUINFO_LABEL "APUinfo"
-
/* Scan the input BFDs and create a linked list of
the APUinfo values that will need to be emitted. */
ppc_elf_link_hash_table_create (bfd *abfd)
{
struct ppc_elf_link_hash_table *ret;
- static struct ppc_elf_params default_params = { PLT_OLD, 0, 1, 0, 0, 12, 0 };
+ static struct ppc_elf_params default_params
+ = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0 };
ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
if (ret == NULL)
if (htab)
htab->params = params;
+ params->pagesize_p2 = bfd_log2 (params->pagesize);
}
/* Create .got and the related sections. */
*valp = sym->st_size;
}
- if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
- || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
+ if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
&& (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
- elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any;
+ elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc;
return TRUE;
}
|| r_type == R_PPC_ADDR24
|| r_type == R_PPC_ADDR14
|| r_type == R_PPC_ADDR14_BRTAKEN
- || r_type == R_PPC_ADDR14_BRNTAKEN);
+ || r_type == R_PPC_ADDR14_BRNTAKEN
+ || r_type == R_PPC_VLE_REL24);
}
static void
}
if (h != NULL && h->type == STT_GNU_IFUNC)
{
- if (bfd_link_pic (info))
- {
- info->callbacks->einfo
- (_("%P: %H: @local call to ifunc %s\n"),
- abfd, sec, rel->r_offset,
- h->root.root.string);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
h->needs_plt = 1;
if (!update_plt_info (abfd, &h->plt.plist, NULL, 0))
return FALSE;
insn = bfd_get_32 (output_bfd, loc);
top5 = value & 0xf800;
top5 = top5 << (split16_format == split16a_type ? 9 : 5);
+ insn &= (split16_format == split16a_type ? ~0x1f007ff : ~0x1f07ff);
insn |= top5;
insn |= value & 0x7ff;
bfd_put_32 (output_bfd, insn, loc);
tga->root.type = bfd_link_hash_indirect;
tga->root.u.i.link = &opt->root;
ppc_elf_copy_indirect_symbol (info, opt, tga);
+ opt->forced_local = 0;
if (opt->dynindx != -1)
{
/* Use __tls_get_addr_opt in dynamic relocations. */
&& htab->elf.dynamic_sections_created)
{
htab->glink_pltresolve = htab->glink->size;
- /* Space for the branch table. */
+ /* Space for the branch table. ??? We don't need entries for
+ non-dynamic symbols in this table. This case can arise with
+ static ifuncs or forced local ifuncs. */
htab->glink->size += htab->glink->size / (GLINK_ENTRY_SIZE / 4) - 4;
/* Pad out to align the start of PLTresolve. */
htab->glink->size += -htab->glink->size & (htab->params->ppc476_workaround
}
if (ent != NULL)
{
+ if (bfd_link_pic (info)
+ && ent->sec != got2
+ && htab->plt_type != PLT_NEW
+ && (!htab->elf.dynamic_sections_created
+ || h == NULL
+ || h->dynindx == -1))
+ {
+ /* Uh oh, we are going to create a pic glink stub
+ for an ifunc (here for h == NULL and later in
+ finish_dynamic_symbol for h != NULL), and
+ apparently are using code compiled with
+ -mbss-plt. The difficulty is that -mbss-plt code
+ gives no indication via a magic PLTREL24 addend
+ whether r30 is equal to _GLOBAL_OFFSET_TABLE_ or
+ is pointing into a .got2 section (and how far
+ into .got2). */
+ info->callbacks->einfo
+ (_("%X%P: %H: unsupported bss-plt -fPIC ifunc %s\n"),
+ input_bfd, input_section, rel->r_offset, sym_name);
+ }
if (h == NULL && (ent->plt.offset & 1) == 0)
{
Elf_Internal_Rela rela;
at a symbol not in this object. */
if (unresolved_reloc)
{
- if (! (*info->callbacks->undefined_symbol) (info,
- h->root.root.string,
- input_bfd,
- input_section,
- rel->r_offset,
- TRUE))
- return FALSE;
+ (*info->callbacks->undefined_symbol) (info,
+ h->root.root.string,
+ input_bfd,
+ input_section,
+ rel->r_offset,
+ TRUE);
goto copy_reloc;
}
+ if (h != NULL && h->type == STT_GNU_IFUNC && bfd_link_pic (info))
+ {
+ /* @local on an ifunc does not really make sense since
+ the ifunc resolver can take you anywhere. More
+ seriously, calls to ifuncs must go through a plt call
+ stub, and for pic the plt call stubs uses r30 to
+ access the PLT. The problem is that a call that is
+ local won't have the +32k reloc addend trick marking
+ -fPIC code, so the linker won't know whether r30 is
+ _GLOBAL_OFFSET_TABLE_ or pointing into a .got2 section. */
+ info->callbacks->einfo (_("%X%P: %H: @local call to ifunc %s\n"),
+ input_bfd, input_section, rel->r_offset,
+ h->root.root.string);
+ }
break;
case R_PPC_DTPREL16:
&& (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_undefined)
&& is_branch_reloc (r_type)))
- {
- if (!((*info->callbacks->reloc_overflow)
- (info, (h ? &h->root : NULL), sym_name,
- howto->name, rel->r_addend,
- input_bfd, input_section, rel->r_offset)))
- return FALSE;
- }
+ info->callbacks->reloc_overflow
+ (info, (h ? &h->root : NULL), sym_name, howto->name,
+ rel->r_addend, input_bfd, input_section, rel->r_offset);
}
else
{