summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2002-01-23 11:21:18 +0000
committerAlan Modra <amodra@gmail.com>2002-01-23 11:21:18 +0000
commit41bd81abfa5ec20e7050c925c77662d2c720cbe7 (patch)
treebaa4f55dc5924be91a40b78deadeaf89a4d2e508
parent13fc0c2f38ad82e07263ae624593a22deffaf157 (diff)
downloadbinutils-gdb-41bd81abfa5ec20e7050c925c77662d2c720cbe7.tar.gz
* elf64-ppc.c: Remove stale part of ABI comment.
(NO_OPD_RELOCS): Define. (ppc64_elf_check_relocs): Use it. (ppc64_elf_relocate_section): Here too. (build_one_stub): Don't point function syms at the stub. Instead, hijack plt.offset. (ppc64_elf_relocate_section): Check whether REL24 relocs should really go to the stub. Make all dynamic relocs in opd against locals. (ppc64_elf_finish_dynamic_symbol): Allow for non-standard use of plt.offset.
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/elf64-ppc.c101
2 files changed, 70 insertions, 45 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4a03937c264..03000ea2eec 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+2002-01-23 Alan Modra <amodra@bigpond.net.au>
+
+ * elf64-ppc.c: Remove stale part of ABI comment.
+ (NO_OPD_RELOCS): Define.
+ (ppc64_elf_check_relocs): Use it.
+ (ppc64_elf_relocate_section): Here too.
+ (build_one_stub): Don't point function syms at the stub. Instead,
+ hijack plt.offset.
+ (ppc64_elf_relocate_section): Check whether REL24 relocs should
+ really go to the stub. Make all dynamic relocs in opd against
+ locals.
+ (ppc64_elf_finish_dynamic_symbol): Allow for non-standard use of
+ plt.offset.
+
2002-01-22 Richard Henderson <rth@redhat.com>
* elf64-alpha.c (INSN_UNOP): Encode with RB as $sp.
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 17d6d0ad953..da339bb512d 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -152,6 +152,18 @@ static boolean ppc64_elf_finish_dynamic_sections
a branch. */
#define LIS_R0_0 0x3c000000 /* lis %r0,0 */
#define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */
+
+/* Since .opd is an array of descriptors and each entry will end up
+ with identical R_PPC64_RELATIVE relocs, there is really no need to
+ propagate .opd relocs; The dynamic linker should be taught to
+ relocate .opd without reloc entries. FIXME: the dynamic linker
+ will need to know where and how large .opd is via a couple of new
+ DT_PPC64_* tags, or perhaps just with one reloc that specifies the
+ start of .opd via its offset and the size via its addend. Also,
+ .opd should be trimmed of unused values. */
+#ifndef NO_OPD_RELOCS
+#define NO_OPD_RELOCS 0
+#endif
/* Relocation HOWTO's. */
static reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC_max];
@@ -1648,10 +1660,7 @@ ppc64_elf_section_from_shdr (abfd, hdr, name)
creating a shared library containing foo, we need to have both symbols
dynamic so that references to .foo are satisfied during the early
stages of linking. Otherwise the linker might decide to pull in a
- definition from some other object, eg. a static library. Thirdly, we'd
- like to use .foo as the stub symbol to avoid creating another symbol.
- We need to make sure that when .foo labels a stub in a shared library,
- it isn't exported. */
+ definition from some other object, eg. a static library. */
/* The linker needs to keep track of the number of relocs that it
decides to copy as dynamic relocs in check_relocs for each symbol.
@@ -2123,11 +2132,9 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
case R_PPC64_UADDR32:
case R_PPC64_UADDR64:
case R_PPC64_TOC:
-#if 0
- /* Don't propagate .opd relocs. */
- if (is_opd)
+ /* Don't propagate .opd relocs. */
+ if (NO_OPD_RELOCS && is_opd)
break;
-#endif
/* If we are creating a shared library, and this is a reloc
against a global symbol, or a non PC relative reloc
@@ -3313,7 +3320,8 @@ build_one_stub (h, inf)
htab = ppc_hash_table (info);
if (htab->elf.dynamic_sections_created
- && h->plt.offset != (bfd_vma) -1)
+ && h->plt.offset != (bfd_vma) -1
+ && ((struct ppc_link_hash_entry *) h)->is_func_descriptor)
{
struct elf_link_hash_entry *fh;
asection *s;
@@ -3321,8 +3329,6 @@ build_one_stub (h, inf)
bfd_byte *p;
unsigned int indx;
- BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor);
-
fh = elf_link_hash_lookup (&htab->elf, h->root.root.string - 1,
false, false, true);
@@ -3331,14 +3337,6 @@ build_one_stub (h, inf)
BFD_ASSERT (((struct ppc_link_hash_entry *) fh)->is_func);
- /* Point the function at the linkage stub. This works because
- the only references to the function code sym are calls.
- Function pointer comparisons use the function descriptor. */
- s = htab->sstub;
- fh->root.type = bfd_link_hash_defined;
- fh->root.u.def.section = s;
- fh->root.u.def.value = s->_cooked_size;
-
/* Build the .plt call stub. */
plt_r2 = (htab->splt->output_section->vma
+ htab->splt->output_offset
@@ -3356,6 +3354,10 @@ build_one_stub (h, inf)
htab->plt_overflow = true;
return false;
}
+
+ s = htab->sstub;
+ /* Steal plt.offset to store the stub offset. */
+ fh->plt.offset = s->_cooked_size;
p = s->contents + s->_cooked_size;
p = build_plt_stub (s->owner, p, (int) plt_r2, 0);
s->_cooked_size = p - s->contents;
@@ -3501,6 +3503,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
bfd_vma *local_got_offsets;
bfd_vma TOCstart;
boolean ret = true;
+ boolean is_opd;
/* Initialize howto table if needed. */
if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
@@ -3511,6 +3514,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
TOCstart = elf_gp (output_bfd);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
+ is_opd = strcmp (bfd_get_section_name (abfd, input_section), ".opd") == 0;
rel = relocs;
relend = relocs + input_section->reloc_count;
@@ -3616,7 +3620,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|| info->no_undefined
|| ELF_ST_VISIBILITY (h->other)))))
return false;
- relocation = 0;
}
}
@@ -3659,24 +3662,33 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
recognized by their need for a PLT entry. */
has_nop = 0;
if (h != NULL
- && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
+ && h->plt.offset != (bfd_vma) -1
+ && htab->sstub != NULL)
+ {
+ /* plt.offset here is the offset into the stub section. */
+ relocation = (htab->sstub->output_section->vma
+ + htab->sstub->output_offset
+ + h->plt.offset);
+ unresolved_reloc = false;
+
/* Make sure that there really is an instruction after
the branch that we can decode. */
- && offset + 8 <= input_section->_cooked_size)
- {
- bfd_byte *pnext;
+ if (offset + 8 <= input_section->_cooked_size)
+ {
+ bfd_byte *pnext;
- pnext = contents + offset + 4;
- insn = bfd_get_32 (input_bfd, pnext);
+ pnext = contents + offset + 4;
+ insn = bfd_get_32 (input_bfd, pnext);
- if (insn == 0x60000000 /* nop (ori r0,r0,0) */
- || insn == 0x4def7b82 /* cror 15,15,15 */
- || insn == 0x4ffffb82) /* cror 31,31,31 */
- {
- bfd_put_32 (input_bfd,
- (bfd_vma) 0xe8410028, /* ld r2,40(r1) */
- pnext);
- has_nop = 1;
+ if (insn == 0x60000000 /* nop (ori r0,r0,0) */
+ || insn == 0x4def7b82 /* cror 15,15,15 */
+ || insn == 0x4ffffb82) /* cror 31,31,31 */
+ {
+ bfd_put_32 (input_bfd,
+ (bfd_vma) 0xe8410028, /* ld r2,40(r1) */
+ pnext);
+ has_nop = 1;
+ }
}
}
@@ -3912,6 +3924,9 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
if ((input_section->flags & SEC_ALLOC) == 0)
break;
+ if (NO_OPD_RELOCS && is_opd)
+ break;
+
if ((info->shared
&& (IS_ABSOLUTE_RELOC (r_type)
|| (h != NULL
@@ -3935,12 +3950,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
asection *sreloc;
Elf64_External_Rela *loc;
-#if 0
- if (strcmp (bfd_get_section_name (output_bfd, input_section),
- ".opd") == 0)
- break;
-#endif
-
/* When generating a dynamic object, these relocations
are copied into the output file to be resolved at run
time. */
@@ -3964,6 +3973,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
}
else if (h != NULL
&& h->dynindx != -1
+ && !is_opd
&& (!IS_ABSOLUTE_RELOC (r_type)
|| !info->shared
|| !info->symbolic
@@ -3975,7 +3985,9 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
}
else
{
- /* This symbol is local, or marked to become local. */
+ /* This symbol is local, or marked to become local,
+ or this is an opd section reloc which must point
+ at a local function. */
outrel.r_addend += relocation;
relocate = true;
if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
@@ -3986,7 +3998,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
{
long indx = 0;
- if (r_type == R_PPC64_TOC || bfd_is_abs_section (sec))
+ if (bfd_is_abs_section (sec))
;
else if (sec == NULL || sec->owner == NULL)
{
@@ -4185,7 +4197,8 @@ ppc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
htab = ppc_hash_table (info);
dynobj = htab->elf.dynobj;
- if (h->plt.offset != (bfd_vma) -1)
+ if (h->plt.offset != (bfd_vma) -1
+ && ((struct ppc_link_hash_entry *) h)->is_func_descriptor)
{
Elf_Internal_Rela rela;
Elf64_External_Rela *loc;
@@ -4198,8 +4211,6 @@ ppc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|| htab->sglink == NULL)
abort ();
- BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor);
-
/* Create a JMP_SLOT reloc to inform the dynamic linker to
fill in the PLT entry. */