#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
-#include "elf/ppc.h"
#include "elf/ppc64.h"
#include "elf64-ppc.h"
/* Copy the extra info we tack onto an elf_link_hash_entry. */
static void
-ppc64_elf_copy_indirect_symbol (struct elf_backend_data *bed ATTRIBUTE_UNUSED,
- struct elf_link_hash_entry *dir,
- struct elf_link_hash_entry *ind)
+ppc64_elf_copy_indirect_symbol
+ (const struct elf_backend_data *bed ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *dir,
+ struct elf_link_hash_entry *ind)
{
struct ppc_link_hash_entry *edir, *eind;
flagword mask;
/* If a code section has a function that uses the TOC then we need
to use the right TOC (obviously). Also, make sure that .opd gets
- the correct TOC value. */
+ the correct TOC value for R_PPC64_TOC relocs that don't have or
+ can't find their function symbol (shouldn't ever happen now). */
if (isec->has_gp_reloc || (isec->flags & SEC_CODE) == 0)
{
if (elf_gp (isec->owner) != 0)
r_type = ELF64_R_TYPE (rel->r_info);
r_symndx = ELF64_R_SYM (rel->r_info);
+
+ /* For old style R_PPC64_TOC relocs with a zero symbol, use the
+ symbol of the previous ADDR64 reloc. The symbol gives us the
+ proper TOC base to use. */
+ if (rel->r_info == ELF64_R_INFO (0, R_PPC64_TOC)
+ && rel != relocs
+ && ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_ADDR64
+ && is_opd)
+ r_symndx = ELF64_R_SYM (rel[-1].r_info);
+
sym = NULL;
sec = NULL;
h = NULL;
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd, input_section,
- rel->r_offset, (!info->shared
+ rel->r_offset, (info->executable
|| info->no_undefined
|| ELF_ST_VISIBILITY (h->other)))))
return FALSE;
if ((insn & 1) == 0)
can_plt_call = 1;
}
+ else if (h != NULL
+ && strcmp (h->root.root.string,
+ ".__libc_start_main") == 0)
+ {
+ /* Allow crt1 branch to go via a toc adjusting stub. */
+ can_plt_call = 1;
+ }
else
{
if (strcmp (input_section->output_section->name,