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 371d94cabdf378230e18252de7217c43d6b29682..3dd932b1959b00a1bd343dba6b99547430cac1f5 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 d0a432a11d7cb9466ee78af0e942a8a8aed72f44..bb4b8d4600f433a7e9b3c50a75a9fb67081ca95f 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: