|
|
7ab123 |
commit a345bc8d317a159e3e887632d80c5a8282d34f07
|
|
|
7ab123 |
Author: Alan Modra <amodra@gmail.com>
|
|
|
7ab123 |
Date: Fri Nov 1 19:24:20 2013 +1030
|
|
|
7ab123 |
|
|
|
7ab123 |
PowerPC64 ELFv2 symbols defined in plt
|
|
|
7ab123 |
|
|
|
7ab123 |
In a non-pic executable, ELFv2 like other targets, needs to emit a plt
|
|
|
7ab123 |
entry even for non-call references to functions defined in shared
|
|
|
7ab123 |
libraries, and define the function on the plt code.
|
|
|
7ab123 |
|
|
|
7ab123 |
* elf64-ppc.c (ppc64_elf_copy_indirect_symbol): Copy
|
|
|
7ab123 |
pointer_equality_needed flag.
|
|
|
7ab123 |
(ppc64_elf_check_relocs): For ELFv2 arrange to emit plt
|
|
|
7ab123 |
entries for references to functions in shared libraries on
|
|
|
7ab123 |
non-call relocs.
|
|
|
7ab123 |
(readonly_dynrelocs): Split into function of the same name and..
|
|
|
7ab123 |
(maybe_set_textrel): ..this new function. Update call.
|
|
|
7ab123 |
(ppc64_elf_adjust_dynamic_symbol): Don't emit dynrelocs for
|
|
|
7ab123 |
ELFv2 in most cases if we have a plt entry. Use new
|
|
|
7ab123 |
readonly_relocs.
|
|
|
7ab123 |
(allocate_dynrelocs): For ELFv2, don't allocate dynreloc space
|
|
|
7ab123 |
for ifunc in static executables.
|
|
|
7ab123 |
(size_global_entry_stubs): New function.
|
|
|
7ab123 |
(ppc64_elf_size_dynamic_sections): Call size_global_entry_stubs.
|
|
|
7ab123 |
Save end of glink branch table.
|
|
|
7ab123 |
(ppc64_elf_hash_symbol): New function.
|
|
|
7ab123 |
(build_global_entry_stubs): New function.
|
|
|
7ab123 |
(ppc64_elf_build_stubs): Call build_global_entry_stubs. Adjust
|
|
|
7ab123 |
glink sizing.
|
|
|
7ab123 |
(ppc64_elf_relocate_section): Tidy plt16/32/64 reloc code.
|
|
|
7ab123 |
(ppc64_elf_finish_dynamic_symbol): For ELFv2, adjust symbols
|
|
|
7ab123 |
defined on plt code.
|
|
|
7ab123 |
|
|
|
7ab123 |
Index: gdb-7.6.1/bfd/elf64-ppc.c
|
|
|
7ab123 |
===================================================================
|
|
|
7ab123 |
--- gdb-7.6.1.orig/bfd/elf64-ppc.c
|
|
|
7ab123 |
+++ gdb-7.6.1/bfd/elf64-ppc.c
|
|
|
7ab123 |
@@ -109,6 +109,7 @@ static bfd_vma opd_entry_value
|
|
|
7ab123 |
#define elf_backend_maybe_function_sym ppc64_elf_maybe_function_sym
|
|
|
7ab123 |
#define elf_backend_always_size_sections ppc64_elf_func_desc_adjust
|
|
|
7ab123 |
#define elf_backend_size_dynamic_sections ppc64_elf_size_dynamic_sections
|
|
|
7ab123 |
+#define elf_backend_hash_symbol ppc64_elf_hash_symbol
|
|
|
7ab123 |
#define elf_backend_init_index_section _bfd_elf_init_2_index_sections
|
|
|
7ab123 |
#define elf_backend_action_discarded ppc64_elf_action_discarded
|
|
|
7ab123 |
#define elf_backend_relocate_section ppc64_elf_relocate_section
|
|
|
7ab123 |
@@ -174,6 +175,9 @@ static bfd_vma opd_entry_value
|
|
|
7ab123 |
|
|
|
7ab123 |
#define LD_R2_0R1 0xe8410000 /* ld %r2,0(%r1) */
|
|
|
7ab123 |
|
|
|
7ab123 |
+#define ADDIS_R12_R12 0x3d8c0000 /* addis %r12,%r12,xxx@ha */
|
|
|
7ab123 |
+#define LD_R12_0R12 0xe98c0000 /* ld %r12,xxx@l(%r12) */
|
|
|
7ab123 |
+
|
|
|
7ab123 |
/* glink call stub instructions. We enter with the index in R0. */
|
|
|
7ab123 |
#define GLINK_CALL_STUB_SIZE (16*4)
|
|
|
7ab123 |
/* 0: */
|
|
|
7ab123 |
@@ -4502,6 +4506,7 @@ ppc64_elf_copy_indirect_symbol (struct b
|
|
|
7ab123 |
edir->elf.ref_regular |= eind->elf.ref_regular;
|
|
|
7ab123 |
edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
|
|
|
7ab123 |
edir->elf.needs_plt |= eind->elf.needs_plt;
|
|
|
7ab123 |
+ edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
|
|
|
7ab123 |
|
|
|
7ab123 |
/* Copy over any dynamic relocs we may have on the indirect sym. */
|
|
|
7ab123 |
if (eind->dyn_relocs != NULL)
|
|
|
7ab123 |
@@ -5219,6 +5224,14 @@ ppc64_elf_check_relocs (bfd *abfd, struc
|
|
|
7ab123 |
if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
|
|
7ab123 |
rel->r_addend, tls_type))
|
|
|
7ab123 |
return FALSE;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ /* We may also need a plt entry if the symbol turns out to be
|
|
|
7ab123 |
+ an ifunc. */
|
|
|
7ab123 |
+ if (h != NULL && !info->shared && abiversion (abfd) == 2)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
|
|
|
7ab123 |
+ return FALSE;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
break;
|
|
|
7ab123 |
|
|
|
7ab123 |
case R_PPC64_PLT16_HA:
|
|
|
7ab123 |
@@ -5467,12 +5480,6 @@ ppc64_elf_check_relocs (bfd *abfd, struc
|
|
|
7ab123 |
}
|
|
|
7ab123 |
/* Fall through. */
|
|
|
7ab123 |
|
|
|
7ab123 |
- case R_PPC64_REL30:
|
|
|
7ab123 |
- case R_PPC64_REL32:
|
|
|
7ab123 |
- case R_PPC64_REL64:
|
|
|
7ab123 |
- case R_PPC64_ADDR14:
|
|
|
7ab123 |
- case R_PPC64_ADDR14_BRNTAKEN:
|
|
|
7ab123 |
- case R_PPC64_ADDR14_BRTAKEN:
|
|
|
7ab123 |
case R_PPC64_ADDR16:
|
|
|
7ab123 |
case R_PPC64_ADDR16_DS:
|
|
|
7ab123 |
case R_PPC64_ADDR16_HA:
|
|
|
7ab123 |
@@ -5483,6 +5490,23 @@ ppc64_elf_check_relocs (bfd *abfd, struc
|
|
|
7ab123 |
case R_PPC64_ADDR16_HIGHESTA:
|
|
|
7ab123 |
case R_PPC64_ADDR16_LO:
|
|
|
7ab123 |
case R_PPC64_ADDR16_LO_DS:
|
|
|
7ab123 |
+ if (h != NULL && !info->shared && abiversion (abfd) == 2
|
|
|
7ab123 |
+ && rel->r_addend == 0)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ /* We may need a .plt entry if this reloc refers to a
|
|
|
7ab123 |
+ function in a shared lib. */
|
|
|
7ab123 |
+ if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
|
|
|
7ab123 |
+ return FALSE;
|
|
|
7ab123 |
+ h->pointer_equality_needed = 1;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ /* Fall through. */
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ case R_PPC64_REL30:
|
|
|
7ab123 |
+ case R_PPC64_REL32:
|
|
|
7ab123 |
+ case R_PPC64_REL64:
|
|
|
7ab123 |
+ case R_PPC64_ADDR14:
|
|
|
7ab123 |
+ case R_PPC64_ADDR14_BRNTAKEN:
|
|
|
7ab123 |
+ case R_PPC64_ADDR14_BRTAKEN:
|
|
|
7ab123 |
case R_PPC64_ADDR24:
|
|
|
7ab123 |
case R_PPC64_ADDR32:
|
|
|
7ab123 |
case R_PPC64_UADDR16:
|
|
|
7ab123 |
@@ -6667,6 +6691,25 @@ ppc64_elf_func_desc_adjust (bfd *obfd AT
|
|
|
7ab123 |
return TRUE;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
+/* Return true if we have dynamic relocs that apply to read-only sections. */
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+static bfd_boolean
|
|
|
7ab123 |
+readonly_dynrelocs (struct elf_link_hash_entry *h)
|
|
|
7ab123 |
+{
|
|
|
7ab123 |
+ struct ppc_link_hash_entry *eh;
|
|
|
7ab123 |
+ struct elf_dyn_relocs *p;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ eh = (struct ppc_link_hash_entry *) h;
|
|
|
7ab123 |
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ asection *s = p->sec->output_section;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ return FALSE;
|
|
|
7ab123 |
+}
|
|
|
7ab123 |
+
|
|
|
7ab123 |
/* Adjust a symbol defined by a dynamic object and referenced by a
|
|
|
7ab123 |
regular object. The current definition is in some section of the
|
|
|
7ab123 |
dynamic object, but we're not including those sections. We have to
|
|
|
7ab123 |
@@ -6704,6 +6747,26 @@ ppc64_elf_adjust_dynamic_symbol (struct
|
|
|
7ab123 |
h->plt.plist = NULL;
|
|
|
7ab123 |
h->needs_plt = 0;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
+ else if (abiversion (info->output_bfd) == 2)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ /* After adjust_dynamic_symbol, non_got_ref set in the
|
|
|
7ab123 |
+ non-shared case means that we have allocated space in
|
|
|
7ab123 |
+ .dynbss for the symbol and thus dyn_relocs for this
|
|
|
7ab123 |
+ symbol should be discarded.
|
|
|
7ab123 |
+ If we get here we know we are making a PLT entry for this
|
|
|
7ab123 |
+ symbol, and in an executable we'd normally resolve
|
|
|
7ab123 |
+ relocations against this symbol to the PLT entry. Allow
|
|
|
7ab123 |
+ dynamic relocs if the reference is weak, and the dynamic
|
|
|
7ab123 |
+ relocs will not cause text relocation. */
|
|
|
7ab123 |
+ if (!h->ref_regular_nonweak
|
|
|
7ab123 |
+ && h->non_got_ref
|
|
|
7ab123 |
+ && h->type != STT_GNU_IFUNC
|
|
|
7ab123 |
+ && !readonly_dynrelocs (h))
|
|
|
7ab123 |
+ h->non_got_ref = 0;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ /* If making a plt entry, then we don't need copy relocs. */
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
}
|
|
|
7ab123 |
else
|
|
|
7ab123 |
h->plt.plist = NULL;
|
|
|
7ab123 |
@@ -6738,26 +6801,12 @@ ppc64_elf_adjust_dynamic_symbol (struct
|
|
|
7ab123 |
if (!h->def_dynamic || !h->ref_regular || h->def_regular)
|
|
|
7ab123 |
return TRUE;
|
|
|
7ab123 |
|
|
|
7ab123 |
- if (ELIMINATE_COPY_RELOCS)
|
|
|
7ab123 |
+ /* If we didn't find any dynamic relocs in read-only sections, then
|
|
|
7ab123 |
+ we'll be keeping the dynamic relocs and avoiding the copy reloc. */
|
|
|
7ab123 |
+ if (ELIMINATE_COPY_RELOCS && !readonly_dynrelocs (h))
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- struct ppc_link_hash_entry * eh;
|
|
|
7ab123 |
- struct elf_dyn_relocs *p;
|
|
|
7ab123 |
-
|
|
|
7ab123 |
- eh = (struct ppc_link_hash_entry *) h;
|
|
|
7ab123 |
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
|
|
7ab123 |
- {
|
|
|
7ab123 |
- s = p->sec->output_section;
|
|
|
7ab123 |
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
|
|
|
7ab123 |
- break;
|
|
|
7ab123 |
- }
|
|
|
7ab123 |
-
|
|
|
7ab123 |
- /* If we didn't find any dynamic relocs in read-only sections, then
|
|
|
7ab123 |
- we'll be keeping the dynamic relocs and avoiding the copy reloc. */
|
|
|
7ab123 |
- if (p == NULL)
|
|
|
7ab123 |
- {
|
|
|
7ab123 |
- h->non_got_ref = 0;
|
|
|
7ab123 |
- return TRUE;
|
|
|
7ab123 |
- }
|
|
|
7ab123 |
+ h->non_got_ref = 0;
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
if (h->plt.plist != NULL)
|
|
|
7ab123 |
@@ -9167,7 +9216,8 @@ allocate_dynrelocs (struct elf_link_hash
|
|
|
7ab123 |
|
|
|
7ab123 |
if (eh->dyn_relocs == NULL
|
|
|
7ab123 |
|| (!htab->elf.dynamic_sections_created
|
|
|
7ab123 |
- && h->type != STT_GNU_IFUNC))
|
|
|
7ab123 |
+ && (h->type != STT_GNU_IFUNC
|
|
|
7ab123 |
+ || !htab->opd_abi)))
|
|
|
7ab123 |
return TRUE;
|
|
|
7ab123 |
|
|
|
7ab123 |
/* In the shared -Bsymbolic case, discard space allocated for
|
|
|
7ab123 |
@@ -9263,28 +9313,59 @@ allocate_dynrelocs (struct elf_link_hash
|
|
|
7ab123 |
return TRUE;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
-/* Find any dynamic relocs that apply to read-only sections. */
|
|
|
7ab123 |
+/* Called via elf_link_hash_traverse from ppc64_elf_size_dynamic_sections
|
|
|
7ab123 |
+ to set up space for global entry stubs. These are put in glink,
|
|
|
7ab123 |
+ after the branch table. */
|
|
|
7ab123 |
|
|
|
7ab123 |
static bfd_boolean
|
|
|
7ab123 |
-readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|
|
7ab123 |
+size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- struct ppc_link_hash_entry *eh;
|
|
|
7ab123 |
- struct elf_dyn_relocs *p;
|
|
|
7ab123 |
+ struct bfd_link_info *info;
|
|
|
7ab123 |
+ struct ppc_link_hash_table *htab;
|
|
|
7ab123 |
+ struct plt_entry *pent;
|
|
|
7ab123 |
+ asection *s;
|
|
|
7ab123 |
|
|
|
7ab123 |
- eh = (struct ppc_link_hash_entry *) h;
|
|
|
7ab123 |
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
|
|
7ab123 |
- {
|
|
|
7ab123 |
- asection *s = p->sec->output_section;
|
|
|
7ab123 |
+ if (h->root.type == bfd_link_hash_indirect)
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
|
|
|
7ab123 |
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
|
|
|
7ab123 |
- {
|
|
|
7ab123 |
- struct bfd_link_info *info = inf;
|
|
|
7ab123 |
+ if (!h->pointer_equality_needed)
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
|
|
|
7ab123 |
- info->flags |= DF_TEXTREL;
|
|
|
7ab123 |
+ if (h->def_regular)
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
|
|
|
7ab123 |
- /* Not an error, just cut short the traversal. */
|
|
|
7ab123 |
- return FALSE;
|
|
|
7ab123 |
- }
|
|
|
7ab123 |
+ info = inf;
|
|
|
7ab123 |
+ htab = ppc_hash_table (info);
|
|
|
7ab123 |
+ if (htab == NULL)
|
|
|
7ab123 |
+ return FALSE;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ s = htab->glink;
|
|
|
7ab123 |
+ for (pent = h->plt.plist; pent != NULL; pent = pent->next)
|
|
|
7ab123 |
+ if (pent->plt.offset != (bfd_vma) -1
|
|
|
7ab123 |
+ && pent->addend == 0)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ s->size = (s->size + 15) & -16;
|
|
|
7ab123 |
+ s->size += 16;
|
|
|
7ab123 |
+ break;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
+}
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+/* Set DF_TEXTREL if we find any dynamic relocs that apply to
|
|
|
7ab123 |
+ read-only sections. */
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+static bfd_boolean
|
|
|
7ab123 |
+maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
|
|
|
7ab123 |
+{
|
|
|
7ab123 |
+ if (h->root.type == bfd_link_hash_indirect)
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (readonly_dynrelocs (h))
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ /* Not an error, just cut short the traversal. */
|
|
|
7ab123 |
+ return FALSE;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
return TRUE;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
@@ -9435,6 +9516,12 @@ ppc64_elf_size_dynamic_sections (bfd *ou
|
|
|
7ab123 |
/* Allocate global sym .plt and .got entries, and space for global
|
|
|
7ab123 |
sym dynamic relocs. */
|
|
|
7ab123 |
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
|
|
|
7ab123 |
+ /* Stash the end of glink branch table. */
|
|
|
7ab123 |
+ if (htab->glink != NULL)
|
|
|
7ab123 |
+ htab->glink->rawsize = htab->glink->size;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (!htab->opd_abi && !info->shared)
|
|
|
7ab123 |
+ elf_link_hash_traverse (&htab->elf, size_global_entry_stubs, info);
|
|
|
7ab123 |
|
|
|
7ab123 |
first_tlsld = NULL;
|
|
|
7ab123 |
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
|
|
|
7ab123 |
@@ -9632,7 +9719,7 @@ ppc64_elf_size_dynamic_sections (bfd *ou
|
|
|
7ab123 |
/* If any dynamic relocs apply to a read-only section,
|
|
|
7ab123 |
then we need a DT_TEXTREL entry. */
|
|
|
7ab123 |
if ((info->flags & DF_TEXTREL) == 0)
|
|
|
7ab123 |
- elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info);
|
|
|
7ab123 |
+ elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
|
|
|
7ab123 |
|
|
|
7ab123 |
if ((info->flags & DF_TEXTREL) != 0)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
@@ -9646,6 +9733,19 @@ ppc64_elf_size_dynamic_sections (bfd *ou
|
|
|
7ab123 |
return TRUE;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
+/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+static bfd_boolean
|
|
|
7ab123 |
+ppc64_elf_hash_symbol (struct elf_link_hash_entry *h)
|
|
|
7ab123 |
+{
|
|
|
7ab123 |
+ if (h->plt.plist != NULL
|
|
|
7ab123 |
+ && !h->def_regular
|
|
|
7ab123 |
+ && !h->pointer_equality_needed)
|
|
|
7ab123 |
+ return FALSE;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ return _bfd_elf_hash_symbol (h);
|
|
|
7ab123 |
+}
|
|
|
7ab123 |
+
|
|
|
7ab123 |
/* Determine the type of stub needed, if any, for a call. */
|
|
|
7ab123 |
|
|
|
7ab123 |
static inline enum ppc_stub_type
|
|
|
7ab123 |
@@ -12049,6 +12149,79 @@ ppc64_elf_toc (bfd *obfd)
|
|
|
7ab123 |
return TOCstart;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
+/* Called via elf_link_hash_traverse from ppc64_elf_build_stubs to
|
|
|
7ab123 |
+ write out any global entry stubs. */
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+static bfd_boolean
|
|
|
7ab123 |
+build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
|
|
|
7ab123 |
+{
|
|
|
7ab123 |
+ struct bfd_link_info *info;
|
|
|
7ab123 |
+ struct ppc_link_hash_table *htab;
|
|
|
7ab123 |
+ struct plt_entry *pent;
|
|
|
7ab123 |
+ asection *s;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (h->root.type == bfd_link_hash_indirect)
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (!h->pointer_equality_needed)
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (h->def_regular)
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ info = inf;
|
|
|
7ab123 |
+ htab = ppc_hash_table (info);
|
|
|
7ab123 |
+ if (htab == NULL)
|
|
|
7ab123 |
+ return FALSE;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ s = htab->glink;
|
|
|
7ab123 |
+ for (pent = h->plt.plist; pent != NULL; pent = pent->next)
|
|
|
7ab123 |
+ if (pent->plt.offset != (bfd_vma) -1
|
|
|
7ab123 |
+ && pent->addend == 0)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ bfd_byte *p;
|
|
|
7ab123 |
+ asection *plt;
|
|
|
7ab123 |
+ bfd_vma off;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ /* For ELFv2, if this symbol is not defined in a regular file
|
|
|
7ab123 |
+ and we are not generating a shared library or pie, then we
|
|
|
7ab123 |
+ need to define the symbol in the executable on a call stub.
|
|
|
7ab123 |
+ This is to avoid text relocations. */
|
|
|
7ab123 |
+ h->root.u.def.section = s;
|
|
|
7ab123 |
+ h->root.u.def.value = s->size;
|
|
|
7ab123 |
+ s->size += 16;
|
|
|
7ab123 |
+ p = s->contents + h->root.u.def.value;
|
|
|
7ab123 |
+ plt = htab->plt;
|
|
|
7ab123 |
+ if (!htab->elf.dynamic_sections_created
|
|
|
7ab123 |
+ || h->dynindx == -1)
|
|
|
7ab123 |
+ plt = htab->iplt;
|
|
|
7ab123 |
+ off = pent->plt.offset + plt->output_offset + plt->output_section->vma;
|
|
|
7ab123 |
+ off -= h->root.u.def.value + s->output_offset + s->output_section->vma;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (off + 0x80008000 > 0xffffffff || (off & 3) != 0)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ info->callbacks->einfo
|
|
|
7ab123 |
+ (_("%P: linkage table error against `%T'\n"),
|
|
|
7ab123 |
+ h->root.root.string);
|
|
|
7ab123 |
+ bfd_set_error (bfd_error_bad_value);
|
|
|
7ab123 |
+ htab->stub_error = TRUE;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (PPC_HA (off) != 0)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ bfd_put_32 (s->owner, ADDIS_R12_R12 | PPC_HA (off), p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ bfd_put_32 (s->owner, LD_R12_0R12 | PPC_LO (off), p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (s->owner, MTCTR_R12, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (s->owner, BCTR, p);
|
|
|
7ab123 |
+ break;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ return TRUE;
|
|
|
7ab123 |
+}
|
|
|
7ab123 |
+
|
|
|
7ab123 |
/* Build all the stubs associated with the current output file.
|
|
|
7ab123 |
The stubs are kept in a hash table attached to the main linker
|
|
|
7ab123 |
hash table. This function is called via gldelf64ppc_finish. */
|
|
|
7ab123 |
@@ -12184,7 +12357,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_
|
|
|
7ab123 |
|
|
|
7ab123 |
/* Build the .glink lazy link call stubs. */
|
|
|
7ab123 |
indx = 0;
|
|
|
7ab123 |
- while (p < htab->glink->contents + htab->glink->size)
|
|
|
7ab123 |
+ while (p < htab->glink->contents + htab->glink->rawsize)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
if (htab->opd_abi)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
@@ -12207,7 +12380,13 @@ ppc64_elf_build_stubs (bfd_boolean emit_
|
|
|
7ab123 |
indx++;
|
|
|
7ab123 |
p += 4;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
- htab->glink->rawsize = p - htab->glink->contents;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ /* Build .glink global entry stubs. */
|
|
|
7ab123 |
+ if (htab->glink->size > htab->glink->rawsize)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ htab->glink->size = (htab->glink->rawsize + 15) & -16;
|
|
|
7ab123 |
+ elf_link_hash_traverse (&htab->elf, build_global_entry_stubs, info);
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
if (htab->brlt->size != 0)
|
|
|
7ab123 |
@@ -12311,7 +12490,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_
|
|
|
7ab123 |
bfd_put_32 (htab->elf.dynobj, val, p);
|
|
|
7ab123 |
p += 4;
|
|
|
7ab123 |
/* .glink size. */
|
|
|
7ab123 |
- bfd_put_32 (htab->elf.dynobj, htab->glink->rawsize - 8, p);
|
|
|
7ab123 |
+ bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
|
|
|
7ab123 |
p += 4;
|
|
|
7ab123 |
/* Augmentation. */
|
|
|
7ab123 |
p += 1;
|
|
|
7ab123 |
@@ -12361,7 +12540,6 @@ ppc64_elf_build_stubs (bfd_boolean emit_
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
if (stub_sec != NULL
|
|
|
7ab123 |
- || htab->glink->rawsize != htab->glink->size
|
|
|
7ab123 |
|| (htab->glink_eh_frame != NULL
|
|
|
7ab123 |
&& htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
|
|
|
7ab123 |
{
|
|
|
7ab123 |
@@ -13588,13 +13766,14 @@ ppc64_elf_relocate_section (bfd *output_
|
|
|
7ab123 |
{
|
|
|
7ab123 |
struct plt_entry *ent;
|
|
|
7ab123 |
for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
|
|
|
7ab123 |
- if (ent->addend == orig_rel.r_addend
|
|
|
7ab123 |
- && ent->plt.offset != (bfd_vma) -1)
|
|
|
7ab123 |
+ if (ent->plt.offset != (bfd_vma) -1
|
|
|
7ab123 |
+ && ent->addend == orig_rel.r_addend)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
relocation = (htab->plt->output_section->vma
|
|
|
7ab123 |
+ htab->plt->output_offset
|
|
|
7ab123 |
+ ent->plt.offset);
|
|
|
7ab123 |
unresolved_reloc = FALSE;
|
|
|
7ab123 |
+ break;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
}
|
|
|
7ab123 |
break;
|
|
|
7ab123 |
@@ -14297,6 +14476,30 @@ ppc64_elf_finish_dynamic_symbol (bfd *ou
|
|
|
7ab123 |
/ PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
|
|
|
7ab123 |
}
|
|
|
7ab123 |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ if (!htab->opd_abi)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ if (!h->def_regular)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ /* Mark the symbol as undefined, rather than as
|
|
|
7ab123 |
+ defined in glink. Leave the value if there were
|
|
|
7ab123 |
+ any relocations where pointer equality matters
|
|
|
7ab123 |
+ (this is a clue for the dynamic linker, to make
|
|
|
7ab123 |
+ function pointer comparisons work between an
|
|
|
7ab123 |
+ application and shared library), otherwise set it
|
|
|
7ab123 |
+ to zero. */
|
|
|
7ab123 |
+ sym->st_shndx = SHN_UNDEF;
|
|
|
7ab123 |
+ if (!h->pointer_equality_needed)
|
|
|
7ab123 |
+ sym->st_value = 0;
|
|
|
7ab123 |
+ else if (!h->ref_regular_nonweak)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ /* This breaks function pointer comparisons, but
|
|
|
7ab123 |
+ that is better than breaking tests for a NULL
|
|
|
7ab123 |
+ function pointer. */
|
|
|
7ab123 |
+ sym->st_value = 0;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
if (h->needs_copy)
|