summaryrefslogtreecommitdiff
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2003-05-23 18:40:58 +0000
committerDavid Carlton <carlton@bactrian.org>2003-05-23 18:40:58 +0000
commit1732cb683af26151ca0b2f4950ffcab06364f4ac (patch)
tree0eb15e23041d2e4d096abec1126f1d3c2d2d8bf4 /bfd/elf64-ppc.c
parent79d4acc4ef30db17c32eac3695f62c6884065592 (diff)
downloadgdb-1732cb683af26151ca0b2f4950ffcab06364f4ac.tar.gz
2003-05-23 David Carlton <carlton@bactrian.org>
* Merge with mainline; tag is carlton_dictionary-20030523-merge.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r--bfd/elf64-ppc.c104
1 files changed, 58 insertions, 46 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 29c90fe32e4..f32d261fe6e 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -3272,6 +3272,7 @@ ppc64_elf_copy_indirect_symbol (bed, dir, ind)
struct elf_link_hash_entry *dir, *ind;
{
struct ppc_link_hash_entry *edir, *eind;
+ flagword mask;
edir = (struct ppc_link_hash_entry *) dir;
eind = (struct ppc_link_hash_entry *) ind;
@@ -3316,20 +3317,24 @@ ppc64_elf_copy_indirect_symbol (bed, dir, ind)
edir->is_entry |= eind->is_entry;
edir->tls_mask |= eind->tls_mask;
- /* Copy down any references that we may have already seen to the
- symbol which just became indirect. */
- edir->elf.elf_link_hash_flags |=
- (eind->elf.elf_link_hash_flags
- & (ELF_LINK_HASH_REF_DYNAMIC
- | ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR_NONWEAK
- | ELF_LINK_NON_GOT_REF));
+ mask = (ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR
+ | ELF_LINK_HASH_REF_REGULAR_NONWEAK | ELF_LINK_NON_GOT_REF);
+ /* If called to transfer flags for a weakdef during processing
+ of elf_adjust_dynamic_symbol, don't copy ELF_LINK_NON_GOT_REF.
+ We clear it ourselves for ELIMINATE_COPY_RELOCS. */
+ if (ELIMINATE_COPY_RELOCS
+ && eind->elf.root.type != bfd_link_hash_indirect
+ && (edir->elf.elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
+ mask &= ~ELF_LINK_NON_GOT_REF;
+
+ edir->elf.elf_link_hash_flags |= eind->elf.elf_link_hash_flags & mask;
/* If we were called to copy over info for a weak sym, that's all. */
if (eind->elf.root.type != bfd_link_hash_indirect)
return;
- /* Copy over got entries. */
+ /* Copy over got entries that we may have already seen to the
+ symbol which just became indirect. */
if (eind->elf.got.glist != NULL)
{
if (edir->elf.got.glist != NULL)
@@ -3877,6 +3882,10 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
case R_PPC64_UADDR32:
case R_PPC64_UADDR64:
case R_PPC64_TOC:
+ if (h != NULL && !info->shared)
+ /* We may need a copy reloc. */
+ h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
/* Don't propagate .opd relocs. */
if (NO_OPD_RELOCS && opd_sym_map != NULL)
break;
@@ -4496,15 +4505,13 @@ ppc64_elf_adjust_dynamic_symbol (info, h)
break;
if (!((struct ppc_link_hash_entry *) h)->is_func_descriptor
|| ent == NULL
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
- || (! info->shared
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
- && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0))
+ || SYMBOL_CALLS_LOCAL (info, h)
+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak))
{
h->plt.plist = NULL;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
- return TRUE;
}
else
h->plt.plist = NULL;
@@ -4864,9 +4871,9 @@ ppc64_elf_edit_opd (obfd, info)
sym_hashes = elf_sym_hashes (ibfd);
/* Read the relocations. */
- relstart = _bfd_elf64_link_read_relocs (ibfd, sec, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory);
+ relstart = _bfd_elf_link_read_relocs (ibfd, sec, (PTR) NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory);
if (relstart == NULL)
return FALSE;
@@ -5187,9 +5194,9 @@ ppc64_elf_tls_optimize (obfd, info)
int expecting_tls_get_addr;
/* Read the relocations. */
- relstart = _bfd_elf64_link_read_relocs (ibfd, sec, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory);
+ relstart = _bfd_elf_link_read_relocs (ibfd, sec, (PTR) NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory);
if (relstart == NULL)
return FALSE;
@@ -5588,8 +5595,10 @@ allocate_dynrelocs (h, inf)
s->_raw_size
+= (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8;
dyn = htab->elf.dynamic_sections_created;
- if (info->shared
- || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
+ if ((info->shared
+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
+ && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak))
htab->srelgot->_raw_size
+= (gent->tls_type & eh->tls_mask & TLS_GD
? 2 * sizeof (Elf64_External_Rela)
@@ -5609,9 +5618,13 @@ allocate_dynrelocs (h, inf)
if (info->shared)
{
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
- && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
- || info->symbolic))
+ /* Relocs that use pc_count are those that appear on a call insn,
+ or certain REL relocs (see MUST_BE_DYN_RELOC) that can be
+ generated via assembly. We want calls to protected symbols to
+ resolve directly to the function rather than going via the plt.
+ If people want function pointer comparisons to work as expected
+ then they should avoid writing weird assembly. */
+ if (SYMBOL_CALLS_LOCAL (info, h))
{
struct ppc_dyn_relocs **pp;
@@ -5625,6 +5638,12 @@ allocate_dynrelocs (h, inf)
pp = &p->next;
}
}
+
+ /* Also discard relocs on undefined weak syms with non-default
+ visibility. */
+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak)
+ eh->dyn_relocs = NULL;
}
else if (ELIMINATE_COPY_RELOCS)
{
@@ -6575,9 +6594,9 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size,
/* Get the relocs. */
internal_relocs
- = _bfd_elf64_link_read_relocs (input_bfd, section, NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory);
+ = _bfd_elf_link_read_relocs (input_bfd, section, NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory);
if (internal_relocs == NULL)
goto error_ret_free_local;
@@ -7585,12 +7604,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
bfd_boolean dyn = htab->elf.dynamic_sections_created;
if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
|| (info->shared
- && (info->symbolic
- || h->dynindx == -1
- || (h->elf_link_hash_flags
- & ELF_LINK_FORCED_LOCAL))
- && (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR)))
+ && SYMBOL_REFERENCES_LOCAL (info, h)))
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
locally, or the symbol was forced to be local
@@ -7631,7 +7645,10 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
the case of TLSLD where we'll use one entry per
module. */
*offp = off | 1;
- if (info->shared || indx != 0)
+ if ((info->shared || indx != 0)
+ && (h == NULL
+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak))
{
outrel.r_offset = (htab->sgot->output_section->vma
+ htab->sgot->output_offset
@@ -7855,12 +7872,12 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
break;
if ((info->shared
+ && (h == NULL
+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak)
&& (MUST_BE_DYN_RELOC (r_type)
|| (h != NULL
- && h->dynindx != -1
- && (! info->symbolic
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+ && !SYMBOL_CALLS_LOCAL (info, h))))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
&& h != NULL
@@ -7895,13 +7912,8 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
if (skip)
memset (&outrel, 0, sizeof outrel);
else if (h != NULL
- && h->dynindx != -1
- && !is_opd
- && (!MUST_BE_DYN_RELOC (r_type)
- || !info->shared
- || !info->symbolic
- || (h->elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ && !SYMBOL_REFERENCES_LOCAL (info, h)
+ && !is_opd)
outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
else
{