static boolean ppc64_elf_create_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static void ppc64_elf_copy_indirect_symbol
- PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *));
+ PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
+ struct elf_link_hash_entry *));
static boolean ppc64_elf_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
/* Copy the extra info we tack onto an elf_link_hash_entry. */
static void
-ppc64_elf_copy_indirect_symbol (dir, ind)
+ppc64_elf_copy_indirect_symbol (bed, dir, ind)
+ struct elf_backend_data *bed;
struct elf_link_hash_entry *dir, *ind;
{
struct ppc_link_hash_entry *edir, *eind;
edir->is_func_descriptor |= eind->is_func_descriptor;
edir->is_entry |= eind->is_entry;
- _bfd_elf_link_hash_copy_indirect (dir, ind);
+ _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
}
/* Set a flag, used by ppc64_elf_gc_mark_hook, on the entry symbol and
{
bfd *abfd;
asymbol *newsym;
+ struct bfd_link_hash_entry *bh;
abfd = h->root.u.undef.abfd;
newsym = bfd_make_empty_symbol (abfd);
if (h->root.type == bfd_link_hash_undefweak)
newsym->flags |= BSF_WEAK;
+ bh = &fdh->root;
if ( !(_bfd_generic_link_add_one_symbol
(info, abfd, newsym->name, newsym->flags,
- newsym->section, newsym->value, NULL, false, false,
- (struct bfd_link_hash_entry **) &fdh)))
+ newsym->section, newsym->value, NULL, false, false, &bh)))
{
return false;
}
+ fdh = (struct elf_link_hash_entry *) bh;
fdh->elf_link_hash_flags &= ~ELF_LINK_NON_ELF;
}
break;
}
- if (sym_sec->output_section == bfd_abs_section_ptr)
- {
- /* OK, we've found a function that's excluded from the
- link. */
- need_edit = true;
- }
+ /* opd entries are always for functions defined in the
+ current input bfd. If the symbol isn't defined in the
+ input bfd, then we won't be using the function in this
+ bfd; It must be defined in a linkonce section in another
+ bfd, or is weak. It's also possible that we are
+ discarding the function due to a linker script /DISCARD/,
+ which we test for via the output_section. */
+ if (sym_sec->owner != ibfd
+ || sym_sec->output_section == bfd_abs_section_ptr)
+ need_edit = true;
offset += 24;
}
sym->st_shndx);
}
- skip = sym_sec->output_section == bfd_abs_section_ptr;
- if (!skip)
+ skip = (sym_sec->owner != ibfd
+ || sym_sec->output_section == bfd_abs_section_ptr);
+ if (skip)
+ {
+ if (h != NULL && sym_sec->owner == ibfd)
+ {
+ /* Arrange for the function descriptor sym
+ to be dropped. */
+ struct elf_link_hash_entry *fdh;
+ struct ppc_link_hash_entry *fh;
+
+ fh = (struct ppc_link_hash_entry *) h;
+ BFD_ASSERT (fh->is_func);
+ fdh = fh->oh;
+ fdh->root.u.def.value = 0;
+ fdh->root.u.def.section = sym_sec;
+ }
+ }
+ else
{
/* We'll be keeping this opd entry. */
for the function descriptor sym which we
don't have at the moment. So keep an
array of adjustments. */
- adjust[(rel->r_offset + wptr - rptr) / 24]
- = wptr - rptr;
+ adjust[rel->r_offset / 24] = wptr - rptr;
}
if (wptr != rptr)
break;
case ppc_stub_plt_call:
- /* Build the .glink lazy link call stub. */
- p = htab->sglink->contents + htab->sglink->_cooked_size;
- indx = htab->sglink->reloc_count;
- if (indx < 0x8000)
- {
- bfd_put_32 (htab->sglink->owner, LI_R0_0 | indx, p);
- p += 4;
- }
- else
- {
- bfd_put_32 (htab->sglink->owner, LIS_R0_0 | PPC_HI (indx), p);
- p += 4;
- bfd_put_32 (htab->sglink->owner, ORI_R0_R0_0 | PPC_LO (indx), p);
- p += 4;
- }
- bfd_put_32 (htab->sglink->owner,
- B_DOT | ((htab->sglink->contents - p) & 0x3fffffc), p);
- p += 4;
- htab->sglink->_cooked_size = p - htab->sglink->contents;
- htab->sglink->reloc_count += 1;
-
/* Do the best we can for shared libraries built without
exporting ".foo" for each "foo". This can happen when symbol
versioning scripts strip all bar a subset of symbols. */
if (htab->splt != NULL)
{
+ unsigned int indx;
+
/* Build the .glink plt call stub. */
plt_r2 = (htab->splt->output_offset
+ htab->splt->output_section->vma
- TOC_BASE_OFF);
p = htab->sglink->contents;
p = build_plt_stub (htab->sglink->owner, p, (int) plt_r2, 1);
- while (p - htab->sglink->contents < GLINK_CALL_STUB_SIZE)
+ while (p < htab->sglink->contents + GLINK_CALL_STUB_SIZE)
{
bfd_put_32 (htab->sglink->owner, NOP, p);
p += 4;
}
- htab->sglink->_cooked_size = p - htab->sglink->contents;
- /* Use reloc_count to count entries. */
- htab->sglink->reloc_count = 0;
+ /* Build the .glink lazy link call stubs. */
+ indx = 0;
+ while (p < htab->sglink->contents + htab->sglink->_raw_size)
+ {
+ if (indx < 0x8000)
+ {
+ bfd_put_32 (htab->sglink->owner, LI_R0_0 | indx, p);
+ p += 4;
+ }
+ else
+ {
+ bfd_put_32 (htab->sglink->owner, LIS_R0_0 | PPC_HI (indx), p);
+ p += 4;
+ bfd_put_32 (htab->sglink->owner, ORI_R0_R0_0 | PPC_LO (indx), p);
+ p += 4;
+ }
+ bfd_put_32 (htab->sglink->owner,
+ B_DOT | ((htab->sglink->contents - p) & 0x3fffffc), p);
+ indx++;
+ p += 4;
+ }
+ htab->sglink->_cooked_size = p - htab->sglink->contents;
}
if (htab->sbrlt->_raw_size != 0)
/* Build the stubs as directed by the stub hash table. */
bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
- htab->sglink->reloc_count = 0;
for (stub_sec = htab->stub_bfd->sections;
stub_sec != NULL;