ppc_howto_init ();
type = ELF64_R_TYPE (dst->r_info);
- BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table)
- / sizeof (ppc64_elf_howto_table[0])));
+ if (type >= (sizeof (ppc64_elf_howto_table)
+ / sizeof (ppc64_elf_howto_table[0])))
+ {
+ (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+ abfd, (int) type);
+ type = R_PPC64_NONE;
+ }
cache_ptr->howto = ppc64_elf_howto_table[type];
}
/* Add extra PPC sections. */
-static struct bfd_elf_special_section const
- ppc64_special_sections_p[]=
+static const struct bfd_elf_special_section ppc64_elf_special_sections[]=
{
{ ".plt", 4, 0, SHT_NOBITS, 0 },
- { NULL, 0, 0, 0, 0 }
-};
-
-static struct bfd_elf_special_section const
- ppc64_special_sections_s[]=
-{
- { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
- { NULL, 0, 0, 0, 0 }
-};
-
-static struct bfd_elf_special_section const
- ppc64_special_sections_t[]=
-{
+ { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ ".toc", 4, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ ".toc1", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ ".tocbss", 7, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ NULL, 0, 0, 0, 0 }
};
-static struct bfd_elf_special_section const *
- ppc64_elf_special_sections[27]=
-{
- NULL, /* 'a' */
- NULL, /* 'b' */
- NULL, /* 'c' */
- NULL, /* 'd' */
- NULL, /* 'e' */
- NULL, /* 'f' */
- NULL, /* 'g' */
- NULL, /* 'h' */
- NULL, /* 'i' */
- NULL, /* 'j' */
- NULL, /* 'k' */
- NULL, /* 'l' */
- NULL, /* 'm' */
- NULL, /* 'n' */
- NULL, /* 'o' */
- ppc64_special_sections_p, /* 'p' */
- NULL, /* 'q' */
- NULL, /* 'r' */
- ppc64_special_sections_s, /* 's' */
- ppc64_special_sections_t, /* 't' */
- NULL, /* 'u' */
- NULL, /* 'v' */
- NULL, /* 'w' */
- NULL, /* 'x' */
- NULL, /* 'y' */
- NULL, /* 'z' */
- NULL /* other */
-};
-
struct _ppc64_elf_section_data
{
struct bfd_elf_section_data elf;
/* Base hash table entry structure. */
struct bfd_hash_entry root;
- /* Offset within .branch_lt. */
+ /* Offset within branch lookup table. */
unsigned int offset;
/* Generation marker. */
{
len = 8 + 1 + strlen (h->elf.root.root.string) + 1 + 8 + 1;
stub_name = bfd_malloc (len);
- if (stub_name != NULL)
- {
- sprintf (stub_name, "%08x.%s+%x",
- input_section->id & 0xffffffff,
- h->elf.root.root.string,
- (int) rel->r_addend & 0xffffffff);
- }
+ if (stub_name == NULL)
+ return stub_name;
+
+ sprintf (stub_name, "%08x.%s+%x",
+ input_section->id & 0xffffffff,
+ h->elf.root.root.string,
+ (int) rel->r_addend & 0xffffffff);
}
else
{
len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
stub_name = bfd_malloc (len);
- if (stub_name != NULL)
- {
- sprintf (stub_name, "%08x.%x:%x+%x",
- input_section->id & 0xffffffff,
- sym_sec->id & 0xffffffff,
- (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
- (int) rel->r_addend & 0xffffffff);
- }
+ if (stub_name == NULL)
+ return stub_name;
+
+ sprintf (stub_name, "%08x.%x:%x+%x",
+ input_section->id & 0xffffffff,
+ sym_sec->id & 0xffffffff,
+ (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
+ (int) rel->r_addend & 0xffffffff);
}
if (stub_name[len - 2] == '+' && stub_name[len - 1] == '0')
stub_name[len - 2] = 0;
|| ! bfd_set_section_alignment (dynobj, htab->glink, 2))
return FALSE;
- /* Create .branch_lt for plt_branch stubs. */
- flags = (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- htab->brlt = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt",
- flags);
+ /* Create branch lookup table for plt_branch stubs. */
+ if (info->shared)
+ {
+ flags = (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ htab->brlt
+ = bfd_make_section_anyway_with_flags (dynobj, ".data.rel.ro.brlt",
+ flags);
+ }
+ else
+ {
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ htab->brlt
+ = bfd_make_section_anyway_with_flags (dynobj, ".rodata.brlt", flags);
+ }
+
if (htab->brlt == NULL
|| ! bfd_set_section_alignment (dynobj, htab->brlt, 3))
return FALSE;
- if (info->shared || info->emitrelocations)
+ if (info->shared)
{
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj,
- ".rela.branch_lt",
- flags);
- if (!htab->relbrlt
- || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
- return FALSE;
+ htab->relbrlt
+ = bfd_make_section_anyway_with_flags (dynobj, ".rela.data.rel.ro.brlt",
+ flags);
}
+ else if (info->emitrelocations)
+ {
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ htab->relbrlt
+ = bfd_make_section_anyway_with_flags (dynobj, ".rela.rodata.brlt",
+ flags);
+ }
+ else
+ return TRUE;
+
+ if (!htab->relbrlt
+ || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
+ return FALSE;
+
return TRUE;
}
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
- got = bfd_make_section_with_flags (abfd, ".got", flags);
+ got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
if (!got
|| !bfd_set_section_alignment (abfd, got, 3))
return FALSE;
- relgot = bfd_make_section_with_flags (abfd, ".rela.got",
- flags | SEC_READONLY);
+ relgot = bfd_make_section_anyway_with_flags (abfd, ".rela.got",
+ flags | SEC_READONLY);
if (!relgot
|| ! bfd_set_section_alignment (abfd, relgot, 3))
return FALSE;
else
fdh->elf.ref_regular = 1;
}
- else if (fdh != NULL
- && (fdh->elf.root.type == bfd_link_hash_defined
- || fdh->elf.root.type == bfd_link_hash_defweak))
+ else if (fdh != NULL)
{
unsigned entry_vis = ELF_ST_VISIBILITY (eh->elf.other) - 1;
unsigned descr_vis = ELF_ST_VISIBILITY (fdh->elf.other) - 1;
else if (entry_vis > descr_vis)
eh->elf.other += descr_vis - entry_vis;
- if (eh->elf.root.type == bfd_link_hash_undefined)
+ if ((fdh->elf.root.type == bfd_link_hash_defined
+ || fdh->elf.root.type == bfd_link_hash_defweak)
+ && eh->elf.root.type == bfd_link_hash_undefined)
{
eh->elf.root.type = bfd_link_hash_undefweak;
eh->was_undefined = 1;
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ }
r_type = ELF64_R_TYPE (rel->r_info);
switch (r_type)
if (!rsec->gc_mark)
_bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
- rsec = opd_sym_section[sym->st_value / 8];
+ rsec = opd_sym_section[(sym->st_value + rel->r_addend) / 8];
}
}
bfd_boolean
ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
+ bfd_boolean no_opd_opt,
bfd_boolean non_overlapping)
{
bfd *ibfd;
bfd_size_type cnt_16b = 0;
sec = bfd_get_section_by_name (ibfd, ".opd");
- if (sec == NULL)
+ if (sec == NULL || sec->size == 0)
continue;
amt = sec->size * sizeof (long) / 8;
{
/* check_relocs hasn't been called. Must be a ld -r link
or --just-symbols object. */
- opd_adjust = bfd_zalloc (obfd, amt);
+ opd_adjust = bfd_alloc (obfd, amt);
+ if (opd_adjust == NULL)
+ return FALSE;
ppc64_elf_section_data (sec)->opd.adjust = opd_adjust;
}
memset (opd_adjust, 0, amt);
+ if (no_opd_opt)
+ continue;
+
if (sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
continue;
elf_section_data (sec)->relocs = relstart;
- wptr = sec->contents;
- rptr = sec->contents;
new_contents = sec->contents;
-
if (add_aux_fields)
{
new_contents = bfd_malloc (sec->size + cnt_16b * 8);
if (new_contents == NULL)
return FALSE;
need_pad = FALSE;
- wptr = new_contents;
}
+ wptr = new_contents;
+ rptr = sec->contents;
write_rel = relstart;
skip = FALSE;
continue;
else if (s == htab->got
|| s == htab->plt
- || s == htab->glink)
+ || s == htab->glink
+ || s == htab->dynbss)
{
/* Strip this section if we don't need it; see the
comment below. */
}
else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
{
- if (s->size == 0)
- {
- /* If we don't need this section, strip it from the
- output file. This is mostly to handle .rela.bss and
- .rela.plt. We must create both sections in
- create_dynamic_sections, because they must be created
- before the linker maps input sections to output
- sections. The linker does that before
- adjust_dynamic_symbol is called, and it is that
- function which decides whether anything needs to go
- into these sections. */
- }
- else
+ if (s->size != 0)
{
if (s != htab->relplt)
relocs = TRUE;
if (s->size == 0)
{
+ /* If we don't need this section, strip it from the
+ output file. This is mostly to handle .rela.bss and
+ .rela.plt. We must create both sections in
+ create_dynamic_sections, because they must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
s->flags |= SEC_EXCLUDE;
continue;
}
- /* .plt is in the bss section. We don't initialise it. */
- if (s == htab->plt)
+ if ((s->flags & SEC_HAS_CONTENTS) == 0)
continue;
/* Allocate memory for the section contents. We use bfd_zalloc
(*htab->layout_sections_again) ();
}
- /* It would be nice to strip .branch_lt from the output if the
+ /* It would be nice to strip htab->brlt from the output if the
section is empty, but it's too late. If we strip sections here,
the dynamic symbol table is corrupted since the section symbol
for the stripped section isn't written. */