OSDN Git Service

* elf64-ppc.c: Remove stale part of ABI comment.
authorAlan Modra <amodra@bigpond.net.au>
Wed, 23 Jan 2002 11:21:18 +0000 (11:21 +0000)
committerAlan Modra <amodra@bigpond.net.au>
Wed, 23 Jan 2002 11:21:18 +0000 (11:21 +0000)
(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.

bfd/ChangeLog
bfd/elf64-ppc.c

index 4a03937..03000ea 100644 (file)
@@ -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.
index 17d6d0a..da339bb 100644 (file)
@@ -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
 \f
 /* 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.  */