#define elf_backend_hide_symbol ppc64_elf_hide_symbol
#define elf_backend_always_size_sections ppc64_elf_func_desc_adjust
#define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections
+#define elf_backend_action_discarded ppc64_elf_action_discarded
#define elf_backend_relocate_section ppc64_elf_relocate_section
#define elf_backend_finish_dynamic_symbol ppc64_elf_finish_dynamic_symbol
#define elf_backend_reloc_type_class ppc64_elf_reloc_type_class
easily. Oh well. */
asection *s;
+ void *vpp;
+
s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
sec, r_symndx);
if (s == NULL)
return FALSE;
- head = ((struct ppc_dyn_relocs **)
- &elf_section_data (s)->local_dynrel);
+ vpp = &elf_section_data (s)->local_dynrel;
+ head = (struct ppc_dyn_relocs **) vpp;
}
p = *head;
if (h != NULL)
pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
- else if (sym_sec != NULL)
- pp = (struct ppc_dyn_relocs **) &elf_section_data (sym_sec)->local_dynrel;
else
- pp = (struct ppc_dyn_relocs **) &elf_section_data (sec)->local_dynrel;
+ {
+ if (sym_sec != NULL)
+ {
+ void *vpp = &elf_section_data (sym_sec)->local_dynrel;
+ pp = (struct ppc_dyn_relocs **) vpp;
+ }
+ else
+ {
+ void *vpp = &elf_section_data (sec)->local_dynrel;
+ pp = (struct ppc_dyn_relocs **) vpp;
+ }
+
+ /* elf_gc_sweep may have already removed all dyn relocs associated
+ with local syms for a given section. Don't report a dynreloc
+ miscount. */
+ if (*pp == NULL)
+ return TRUE;
+ }
while ((p = *pp) != NULL)
{
if (skip)
{
- if (!info->relocatable
+ if (!NO_OPD_RELOCS
+ && !info->relocatable
&& !dec_dynrel_count (rel->r_info, sec, info,
NULL, h, sym_sec))
goto error_ret;
{
struct ppc_dyn_relocs *p;
- for (p = *((struct ppc_dyn_relocs **)
- &elf_section_data (s)->local_dynrel);
- p != NULL;
- p = p->next)
+ for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
{
if (!bfd_is_abs_section (p->sec)
&& bfd_is_abs_section (p->sec->output_section))
if (h != NULL)
{
- if (h->oh != NULL
- && h->oh->is_func_descriptor)
- h = h->oh;
+ struct ppc_link_hash_entry *fdh = h;
+ if (fdh->oh != NULL
+ && fdh->oh->is_func_descriptor)
+ fdh = fdh->oh;
- if (h->elf.dynindx != -1)
+ if (fdh->elf.dynindx != -1)
{
struct plt_entry *ent;
- for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
+ for (ent = fdh->elf.plt.plist; ent != NULL; ent = ent->next)
if (ent->addend == rel->r_addend
&& ent->plt.offset != (bfd_vma) -1)
{
- *hash = h;
+ *hash = fdh;
return ppc_stub_plt_call;
}
}
- if (!(h->elf.root.type == bfd_link_hash_defined
- || h->elf.root.type == bfd_link_hash_defweak)
- || h->elf.root.u.def.section->output_section == NULL)
+ /* Here, we know we don't have a plt entry. If we don't have a
+ either a defined function descriptor or a defined entry symbol
+ in a regular object file, then it is pointless trying to make
+ any other type of stub. */
+ if (!((fdh->elf.root.type == bfd_link_hash_defined
+ || fdh->elf.root.type == bfd_link_hash_defweak)
+ && fdh->elf.root.u.def.section->output_section != NULL)
+ && !((h->elf.root.type == bfd_link_hash_defined
+ || h->elf.root.type == bfd_link_hash_defweak)
+ && h->elf.root.u.def.section->output_section != NULL))
return ppc_stub_none;
}
}
bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc);
- BFD_ASSERT (off + (1 << 25) < (bfd_vma) (1 << 26));
+ if (off + (1 << 25) >= (bfd_vma) (1 << 26))
+ {
+ (*_bfd_error_handler) (_("long branch stub `%s' offset overflow"),
+ stub_entry->root.string);
+ htab->stub_error = TRUE;
+ return FALSE;
+ }
if (info->emitrelocations)
{
if (br_entry == NULL)
{
(*_bfd_error_handler) (_("can't find branch stub `%s'"),
- stub_entry->root.string + 9);
+ stub_entry->root.string);
htab->stub_error = TRUE;
return FALSE;
}
if (br_entry == NULL)
{
(*_bfd_error_handler) (_("can't build branch stub `%s'"),
- stub_entry->root.string + 9);
+ stub_entry->root.string);
htab->stub_error = TRUE;
return FALSE;
}
curr = tail;
total = tail->size;
- big_sec = total >= stub_group_size;
+ big_sec = total > stub_group_size;
+ if (big_sec)
+ (*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
+ tail->owner, tail);
curr_toc = htab->stub_group[tail->id].toc_off;
while ((prev = PREV_SEC (curr)) != NULL
bfd *input_bfd;
unsigned int bfd_indx;
asection *stub_sec;
- bfd_boolean stub_changed;
htab->stub_iteration += 1;
- stub_changed = FALSE;
for (input_bfd = info->input_bfds, bfd_indx = 0;
input_bfd != NULL;
ok_dest = FALSE;
fdh = NULL;
+ sym_value = 0;
if (hash == NULL)
{
sym_value = sym->st_value;
ok_dest = TRUE;
}
- else
+ else if (hash->elf.root.type == bfd_link_hash_defined
+ || hash->elf.root.type == bfd_link_hash_defweak)
+ {
+ sym_value = hash->elf.root.u.def.value;
+ if (sym_sec->output_section != NULL)
+ ok_dest = TRUE;
+ }
+ else if (hash->elf.root.type == bfd_link_hash_undefweak
+ || hash->elf.root.type == bfd_link_hash_undefined)
{
- sym_value = 0;
/* Recognise an old ABI func code entry sym, and
- use the func descriptor sym instead. */
+ use the func descriptor sym instead if it is
+ defined. */
if (hash->elf.root.root.string[0] == '.'
&& (fdh = get_fdh (hash, htab)) != NULL)
{
else
fdh = NULL;
}
- else if (hash->elf.root.type == bfd_link_hash_defined
- || hash->elf.root.type == bfd_link_hash_defweak)
- {
- sym_value = hash->elf.root.u.def.value;
- if (sym_sec->output_section != NULL)
- ok_dest = TRUE;
- }
- else if (hash->elf.root.type == bfd_link_hash_undefweak)
- ;
- else if (hash->elf.root.type == bfd_link_hash_undefined)
- ;
- else
- {
- bfd_set_error (bfd_error_bad_value);
- goto error_ret_free_internal;
- }
+ }
+ else
+ {
+ bfd_set_error (bfd_error_bad_value);
+ goto error_ret_free_internal;
}
destination = 0;
if (stub_entry->h != NULL)
htab->stub_globals += 1;
-
- stub_changed = TRUE;
}
/* We're done with the internal relocs, free them. */
}
}
- if (!stub_changed)
- break;
-
- /* OK, we've added some stubs. Find out the new size of the
+ /* We may have added some stubs. Find out the new size of the
stub sections. */
for (stub_sec = htab->stub_bfd->sections;
stub_sec != NULL;
stub_sec = stub_sec->next)
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
{
+ stub_sec->rawsize = stub_sec->size;
stub_sec->size = 0;
stub_sec->reloc_count = 0;
}
bfd_hash_traverse (&htab->stub_hash_table, ppc_size_one_stub, info);
+ for (stub_sec = htab->stub_bfd->sections;
+ stub_sec != NULL;
+ stub_sec = stub_sec->next)
+ if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
+ && stub_sec->rawsize != stub_sec->size)
+ break;
+
+ /* Exit from this loop when no stubs have been added, and no stubs
+ have changed size. */
+ if (stub_sec == NULL)
+ break;
+
/* Ask the linker to do its stuff. */
(*htab->layout_sections_again) ();
}
elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info);
}
+/* What to do when ld finds relocations against symbols defined in
+ discarded sections. */
+
+static unsigned int
+ppc64_elf_action_discarded (asection *sec)
+{
+ if (strcmp (".opd", sec->name) == 0)
+ return 0;
+
+ if (strcmp (".toc", sec->name) == 0)
+ return 0;
+
+ return _bfd_elf_default_action_discarded (sec);
+}
+
/* The RELOCATE_SECTION function is called by the ELF backend linker
to handle the relocations for a section.