Support R_PPC_PLTREL24
authorMichael Meissner <gnu@the-meissners.org>
Thu, 12 Dec 1996 20:08:54 +0000 (20:08 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Thu, 12 Dec 1996 20:08:54 +0000 (20:08 +0000)
bfd/ChangeLog
bfd/elf32-ppc.c

index 371d94c..3dd932b 100644 (file)
@@ -1,3 +1,8 @@
+Thu Dec 12 15:07:20 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * elf32-ppc.c (ppc_elf_check_relocs): Move R_PPC_PLTREL24 into the
+       supported relocs.
+
 Thu Dec 12 14:55:41 1996  Ian Lance Taylor  <ian@cygnus.com>
 
        * ppcboot.c (ppcboot_set_arch_mach): Don't define; it's a
index d0a432a..bb4b8d4 100644 (file)
@@ -1113,10 +1113,8 @@ ppc_elf_copy_private_bfd_data (ibfd, obfd)
      bfd *ibfd;
      bfd *obfd;
 {
-  /* This function is selected based on the input vector.  We only
-     want to copy information over if the output BFD also uses Elf
-     format.  */
-  if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return true;
 
   BFD_ASSERT (!elf_flags_init (obfd)
@@ -1152,10 +1150,8 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd)
       return false;
     }
 
-  /* This function is selected based on the input vector.  We only
-     want to copy information over if the output BFD also uses Elf
-     format.  */
-  if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return true;
 
   new_flags = elf_elfheader (ibfd)->e_flags;
@@ -1190,8 +1186,11 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd)
            ("%s: compiled normally and linked with modules compiled with -mrelocatable",
             bfd_get_filename (ibfd));
        }
-      else if ((new_flags & EF_PPC_RELOCATABLE_LIB) != 0)
-       elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE_LIB;
+      /* If -mrelocatable-lib is linked with an object without -mrelocatable-lib, turn off
+        the -mrelocatable-lib, since at least one module isn't relocatable.  */
+      else if ((old_flags & EF_PPC_RELOCATABLE_LIB) != 0
+              && (new_flags & EF_PPC_RELOCATABLE_LIB) == 0)
+       elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB;
 
 
       /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */
@@ -1472,6 +1471,15 @@ ppc_elf_adjust_dynamic_symbol (info, h)
       /* Make room for this entry.  */
       s->_raw_size += PLT_ENTRY_SIZE;
 
+#if 0
+      /* We also need to make an entry in the .got.plt section, which
+        will be placed in the .got section by the linker script.  */
+
+      s = bfd_get_section_by_name (dynobj, ".got.plt");
+      BFD_ASSERT (s != NULL);
+      s->_raw_size += 4;
+#endif
+
       /* We also need to make an entry in the .rela.plt section.  */
 
       s = bfd_get_section_by_name (dynobj, ".rela.plt");
@@ -1610,17 +1618,11 @@ ppc_elf_size_dynamic_sections (output_bfd, info)
          s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
        }
-
-      /* Make space for the trailing nop in .plt.  */
-      s = bfd_get_section_by_name (dynobj, ".plt");
-      BFD_ASSERT (s != NULL);
-      if (s->_raw_size > 0)
-       s->_raw_size += 4;
     }
   else
     {
       /* We may have created entries in the .rela.got, .rela.sdata, and
-        .rela.sdata2 section2.  However, if we are not creating the
+        .rela.sdata2 sections.  However, if we are not creating the
         dynamic sections, we will not actually use these entries.  Reset
         the size of .rela.got, et al, which will cause it to get
         stripped from the output file below.  */
@@ -1820,6 +1822,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
   struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
+  bfd_vma *local_got_offsets;
   elf_linker_section_t *got;
   elf_linker_section_t *plt;
   elf_linker_section_t *sdata;
@@ -1871,6 +1874,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
   dynobj = elf_hash_table (info)->dynobj;
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
+  local_got_offsets = elf_local_got_offsets (abfd);
 
   sreloc = NULL;
 
@@ -2007,6 +2011,10 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
        case R_PPC_SECTOFF_HA:
          break;
 
+         /* This refers only to functions defined in the shared library */
+       case R_PPC_LOCAL24PC:
+         break;
+
          /* When creating a shared object, we must copy these
             relocs into the output file.  We create a reloc
             section in dynobj and make room for the reloc.  */
@@ -2027,6 +2035,10 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
          if (info->shared
              && (sec->flags & SEC_ALLOC) != 0)
            {
+#ifdef DEBUG
+             fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n",
+                      (h && h->root.root.string) ? h->root.root.string : "<unknown>");
+#endif
              if (sreloc == NULL)
                {
                  const char *name;
@@ -2096,8 +2108,28 @@ ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
       elf_linker_section_t *sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
       if (!sdata->bss_section)
        {
-         sdata->bss_section = bfd_make_section (elf_hash_table (info)->dynobj, sdata->bss_name);
-         sdata->bss_section->flags = (sdata->bss_section->flags & ~SEC_LOAD) | SEC_IS_COMMON;
+         /* We don't go through bfd_make_section, because we don't
+             want to attach this common section to DYNOBJ.  The linker
+             will move the symbols to the appropriate output section
+             when it defines common symbols.  */
+         sdata->bss_section = ((asection *)
+                               bfd_zalloc (abfd, sizeof (asection)));
+         if (sdata->bss_section == NULL)
+           return false;
+         sdata->bss_section->name = sdata->bss_name;
+         sdata->bss_section->flags = SEC_IS_COMMON;
+         sdata->bss_section->output_section = sdata->bss_section;
+         sdata->bss_section->symbol =
+           (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+         sdata->bss_section->symbol_ptr_ptr =
+           (asymbol **) bfd_zalloc (abfd, sizeof (asymbol *));
+         if (sdata->bss_section->symbol == NULL
+             || sdata->bss_section->symbol_ptr_ptr == NULL)
+           return false;
+         sdata->bss_section->symbol->name = sdata->bss_name;
+         sdata->bss_section->symbol->flags = BSF_SECTION_SYM;
+         sdata->bss_section->symbol->section = sdata->bss_section;
+         *sdata->bss_section->symbol_ptr_ptr = sdata->bss_section->symbol;
        }
 
       *secp = sdata->bss_section;
@@ -2384,6 +2416,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   elf_linker_section_t *sdata2           = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL;
   Elf_Internal_Rela *rel                 = relocs;
   Elf_Internal_Rela *relend              = relocs + input_section->reloc_count;
+  asection *sreloc                       = NULL;
   boolean ret                            = true;
   long insn;
 
@@ -2476,11 +2509,62 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              || h->root.type == bfd_link_hash_defweak)
            {
              sec = h->root.u.def.section;
-             if (!sec || !sec->output_section)
+             if ((r_type == R_PPC_PLT32
+                  && h->plt_offset != (bfd_vma) -1)
+                 || ((r_type == R_PPC_GOT16
+                      || r_type == R_PPC_GOT16_LO
+                      || r_type == R_PPC_GOT16_HI
+                      || r_type == R_PPC_GOT16_HA)
+                     && elf_hash_table (info)->dynamic_sections_created
+                     && (! info->shared
+                         || ! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0))
+                 || (info->shared
+                     && (! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0)
+                     && (input_section->flags & SEC_ALLOC) != 0
+                     && (r_type == R_PPC_ADDR32
+                         || r_type == R_PPC_ADDR24
+                         || r_type == R_PPC_ADDR16
+                         || r_type == R_PPC_ADDR16_LO
+                         || r_type == R_PPC_ADDR16_HI
+                         || r_type == R_PPC_ADDR16_HA
+                         || r_type == R_PPC_ADDR14
+                         || r_type == R_PPC_ADDR14_BRTAKEN
+                         || r_type == R_PPC_ADDR14_BRNTAKEN
+                         || r_type == R_PPC_PLTREL24
+                         || r_type == R_PPC_COPY
+                         || r_type == R_PPC_GLOB_DAT
+                         || r_type == R_PPC_JMP_SLOT
+                         || r_type == R_PPC_UADDR32
+                         || r_type == R_PPC_UADDR16
+                         || r_type == R_PPC_REL32
+                         || r_type == R_PPC_SDAREL16
+                         || r_type == R_PPC_EMB_NADDR32
+                         || r_type == R_PPC_EMB_NADDR16
+                         || r_type == R_PPC_EMB_NADDR16_LO
+                         || r_type == R_PPC_EMB_NADDR16_HI
+                         || r_type == R_PPC_EMB_NADDR16_HA
+                         || r_type == R_PPC_EMB_SDAI16
+                         || r_type == R_PPC_EMB_SDA2I16
+                         || r_type == R_PPC_EMB_SDA2REL
+                         || r_type == R_PPC_EMB_SDA21
+                         || r_type == R_PPC_EMB_MRKREF
+                         || r_type == R_PPC_EMB_BIT_FLD
+                         || r_type == R_PPC_EMB_RELSDA
+                         || ((r_type == R_PPC_REL24
+                              || r_type == R_PPC_REL14
+                              || r_type == R_PPC_REL14_BRTAKEN
+                              || r_type == R_PPC_REL14_BRNTAKEN
+                              || r_type == R_PPC_RELATIVE)
+                             && strcmp (h->root.root.string,
+                                        "_GLOBAL_OFFSET_TABLE_") != 0))))
                {
-                 (*_bfd_error_handler) ("%s: Section in shared library for symbol %s\n",
-                                        bfd_get_filename (input_bfd),
-                                        sym_name);
+                 /* In these cases, we don't need the relocation
+                     value.  We check specially because in some
+                     obscure cases sec->output_section will be NULL.  */
                  relocation = 0;
                }
              else
@@ -2516,6 +2600,17 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          continue;
 
        /* relocations that need no special processing */
+       case (int)R_PPC_LOCAL24PC:
+         break;
+
+       case (int)R_PPC_REL24:
+       case (int)R_PPC_REL14:
+         if (h != NULL
+             && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+           break;
+         /* fall through */
+
+       /* Relocations that need to be propigated if this is a shared object */
        case (int)R_PPC_NONE:
        case (int)R_PPC_ADDR32:
        case (int)R_PPC_ADDR24:
@@ -2523,11 +2618,108 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        case (int)R_PPC_ADDR16_LO:
        case (int)R_PPC_ADDR16_HI:
        case (int)R_PPC_ADDR14:
-       case (int)R_PPC_REL24:
-       case (int)R_PPC_REL14:
        case (int)R_PPC_UADDR32:
        case (int)R_PPC_UADDR16:
        case (int)R_PPC_REL32:
+       case (int)R_PPC_PLTREL24:
+         if (info->shared
+             && (input_section->flags & SEC_ALLOC) != 0)
+           {
+             Elf_Internal_Rela outrel;
+
+#ifdef DEBUG
+             fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n",
+                      (h && h->root.root.string) ? h->root.root.string : "<unknown>");
+#endif
+
+             /* When generating a shared object, these relocations
+                 are copied into the output file to be resolved at run
+                 time.  */
+
+             if (sreloc == NULL)
+               {
+                 const char *name;
+
+                 name = (bfd_elf_string_from_elf_section
+                         (input_bfd,
+                          elf_elfheader (input_bfd)->e_shstrndx,
+                          elf_section_data (input_section)->rel_hdr.sh_name));
+                 if (name == NULL)
+                   return false;
+
+                 BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+                             && strcmp (bfd_get_section_name (input_bfd,
+                                                              input_section),
+                                        name + 5) == 0);
+
+                 sreloc = bfd_get_section_by_name (dynobj, name);
+                 BFD_ASSERT (sreloc != NULL);
+               }
+
+             outrel.r_offset = (rel->r_offset
+                                + input_section->output_section->vma
+                                + input_section->output_offset);
+             if (h != NULL
+                 && (! info->symbolic
+                     || (h->elf_link_hash_flags
+                         & ELF_LINK_HASH_DEF_REGULAR) == 0))
+               {
+                 BFD_ASSERT (h->dynindx != -1);
+                 outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+                 outrel.r_addend = rel->r_addend;
+               }
+             else
+               {
+                 if (r_type == R_PPC_ADDR32)
+                   {
+                     outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
+                     outrel.r_addend = relocation + rel->r_addend;
+                   }
+                 else
+                   {
+                     long indx;
+
+                     if (h == NULL)
+                       sec = local_sections[r_symndx];
+                     else
+                       {
+                         BFD_ASSERT (h->root.type == bfd_link_hash_defined
+                                     || (h->root.type
+                                         == bfd_link_hash_defweak));
+                         sec = h->root.u.def.section;
+                       }
+                     if (sec != NULL && bfd_is_abs_section (sec))
+                       indx = 0;
+                     else if (sec == NULL || sec->owner == NULL)
+                       {
+                         bfd_set_error (bfd_error_bad_value);
+                         return false;
+                       }
+                     else
+                       {
+                         asection *osec;
+
+                         osec = sec->output_section;
+                         indx = elf_section_data (osec)->dynindx;
+                         if (indx == 0)
+                           abort ();
+                       }
+
+                     outrel.r_info = ELF32_R_INFO (indx, r_type);
+                     outrel.r_addend = relocation + rel->r_addend;
+                   }
+               }
+
+             bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+                                        (((Elf32_External_Rela *)
+                                          sreloc->contents)
+                                         + sreloc->reloc_count));
+             ++sreloc->reloc_count;
+
+             /* This reloc will be computed at runtime, so there's no
+                 need to do anything now.  */
+             continue;
+           }
          break;
 
        /* branch taken prediction relocations */
@@ -2724,12 +2916,10 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        case (int)R_PPC_EMB_MRKREF:
          continue;
 
-       case (int)R_PPC_PLTREL24:
        case (int)R_PPC_COPY:
        case (int)R_PPC_GLOB_DAT:
        case (int)R_PPC_JMP_SLOT:
        case (int)R_PPC_RELATIVE:
-       case (int)R_PPC_LOCAL24PC:
        case (int)R_PPC_PLT32:
        case (int)R_PPC_PLTREL32:
        case (int)R_PPC_PLT16_LO: