2005-05-05 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / bfd / elf32-m68k.c
index a7696cd074496a5a1b6b9d7bbdea3da440627978..2c6e29b883bdbb3ee51e346ed766a37893ba3565 100644 (file)
@@ -1,6 +1,6 @@
 /* Motorola 68k series support for 32-bit ELF
    Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004 Free Software Foundation, Inc.
+   2004, 2005 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -16,7 +16,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -217,6 +217,37 @@ static const bfd_byte elf_m68k_plt_entry[PLT_ENTRY_SIZE] =
   0, 0, 0, 0             /* replaced with offset to start of .plt.  */
 };
 
+
+#define CFV4E_PLT_ENTRY_SIZE 24 
+
+#define CFV4E_FLAG(abfd)  (elf_elfheader (abfd)->e_flags & EF_CFV4E)
+
+static const bfd_byte elf_cfv4e_plt0_entry[CFV4E_PLT_ENTRY_SIZE] =
+{
+  0x20, 0x3c,
+  0, 0, 0, 0,             /* Replaced with offset to .got + 4.  */
+  0x2f, 0x3b, 0x08, 0xfa, /* move.l (%pc,addr),-(%sp) */
+  0x20, 0x3c,
+  0, 0, 0, 0,             /* Replaced with offset to .got + 8.  */
+  0x20, 0x7b, 0x08, 0x00, /* move.l (%pc,%d0:l), %a0 */
+  0x4e, 0xd0,             /* jmp (%a0) */
+  0x4e, 0x71             /* nop */
+};
+
+/* Subsequent entries in a procedure linkage table look like this.  */
+
+static const bfd_byte elf_cfv4e_plt_entry[CFV4E_PLT_ENTRY_SIZE] =
+{
+  0x20, 0x3c,
+  0, 0, 0, 0,             /* Replaced with offset to symbol's .got entry.  */
+  0x20, 0x7b, 0x08, 0x00, /* move.l (%pc,%d0:l), %a0 */
+  0x4e, 0xd0,             /* jmp (%a0) */
+  0x2f, 0x3c,             /* move.l #offset,-(%sp) */
+  0, 0, 0, 0,             /* Replaced with offset into relocation table.  */
+  0x60, 0xff,             /* bra.l .plt */
+  0, 0, 0, 0              /* Replaced with offset to start of .plt.  */
+};
+
 #define CPU32_FLAG(abfd)  (elf_elfheader (abfd)->e_flags & EF_CPU32)
 
 #define PLT_CPU32_ENTRY_SIZE 24
@@ -486,15 +517,15 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
              srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
              if (srelgot == NULL)
                {
-                 srelgot = bfd_make_section (dynobj, ".rela.got");
+                 srelgot = bfd_make_section_with_flags (dynobj,
+                                                        ".rela.got",
+                                                        (SEC_ALLOC
+                                                         | SEC_LOAD
+                                                         | SEC_HAS_CONTENTS
+                                                         | SEC_IN_MEMORY
+                                                         | SEC_LINKER_CREATED
+                                                         | SEC_READONLY));
                  if (srelgot == NULL
-                     || !bfd_set_section_flags (dynobj, srelgot,
-                                                (SEC_ALLOC
-                                                 | SEC_LOAD
-                                                 | SEC_HAS_CONTENTS
-                                                 | SEC_IN_MEMORY
-                                                 | SEC_LINKER_CREATED
-                                                 | SEC_READONLY))
                      || !bfd_set_section_alignment (dynobj, srelgot, 2))
                    return FALSE;
                }
@@ -660,15 +691,15 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
                  sreloc = bfd_get_section_by_name (dynobj, name);
                  if (sreloc == NULL)
                    {
-                     sreloc = bfd_make_section (dynobj, name);
+                     sreloc = bfd_make_section_with_flags (dynobj,
+                                                           name,
+                                                           (SEC_ALLOC
+                                                            | SEC_LOAD
+                                                            | SEC_HAS_CONTENTS
+                                                            | SEC_IN_MEMORY
+                                                            | SEC_LINKER_CREATED
+                                                            | SEC_READONLY));
                      if (sreloc == NULL
-                         || !bfd_set_section_flags (dynobj, sreloc,
-                                                    (SEC_ALLOC
-                                                     | SEC_LOAD
-                                                     | SEC_HAS_CONTENTS
-                                                     | SEC_IN_MEMORY
-                                                     | SEC_LINKER_CREATED
-                                                     | SEC_READONLY))
                          || !bfd_set_section_alignment (dynobj, sreloc, 2))
                        return FALSE;
                    }
@@ -835,7 +866,16 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs)
   for (rel = relocs; rel < relend; rel++)
     {
       unsigned long r_symndx;
-      struct elf_link_hash_entry *h;
+      struct elf_link_hash_entry *h = NULL;
+
+      r_symndx = ELF32_R_SYM (rel->r_info);
+      if (r_symndx >= symtab_hdr->sh_info)
+       {
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+       }
 
       switch (ELF32_R_TYPE (rel->r_info))
        {
@@ -845,10 +885,8 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs)
        case R_68K_GOT8O:
        case R_68K_GOT16O:
        case R_68K_GOT32O:
-         r_symndx = ELF32_R_SYM (rel->r_info);
-         if (r_symndx >= symtab_hdr->sh_info)
+         if (h != NULL)
            {
-             h = sym_hashes[r_symndx - symtab_hdr->sh_info];
              if (h->got.refcount > 0)
                {
                  --h->got.refcount;
@@ -888,10 +926,8 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs)
        case R_68K_8:
        case R_68K_16:
        case R_68K_32:
-         r_symndx = ELF32_R_SYM (rel->r_info);
-         if (r_symndx >= symtab_hdr->sh_info)
+         if (h != NULL)
            {
-             h = sym_hashes[r_symndx - symtab_hdr->sh_info];
              if (h->plt.refcount > 0)
                --h->plt.refcount;
            }
@@ -925,7 +961,7 @@ elf_m68k_adjust_dynamic_symbol (info, h)
   /* Make sure we know what is going on here.  */
   BFD_ASSERT (dynobj != NULL
              && (h->needs_plt
-                 || h->weakdef != NULL
+                 || h->u.weakdef != NULL
                  || (h->def_dynamic
                      && h->ref_regular
                      && !h->def_regular)));
@@ -936,9 +972,10 @@ elf_m68k_adjust_dynamic_symbol (info, h)
   if (h->type == STT_FUNC
       || h->needs_plt)
     {
-      if (! info->shared
-         && !h->def_dynamic
-         && !h->ref_dynamic
+      if ((h->plt.refcount <= 0
+           || SYMBOL_CALLS_LOCAL (info, h)
+          || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+              && h->root.type == bfd_link_hash_undefweak))
          /* We must always create the plt entry if it was referenced
             by a PLTxxO relocation.  In this case we already recorded
             it as a dynamic symbol.  */
@@ -946,19 +983,11 @@ elf_m68k_adjust_dynamic_symbol (info, h)
        {
          /* This case can occur if we saw a PLTxx reloc in an input
             file, but the symbol was never referred to by a dynamic
-            object.  In such a case, we don't actually need to build
-            a procedure linkage table, and we can just do a PCxx
-            reloc instead.  */
-         BFD_ASSERT (h->needs_plt);
+            object, or if all references were garbage collected.  In
+            such a case, we don't actually need to build a procedure
+            linkage table, and we can just do a PCxx reloc instead.  */
          h->plt.offset = (bfd_vma) -1;
-         return TRUE;
-       }
-
-      /* GC may have rendered this entry unused.  */
-      if (h->plt.refcount <= 0)
-       {
          h->needs_plt = 0;
-         h->plt.offset = (bfd_vma) -1;
          return TRUE;
        }
 
@@ -979,6 +1008,8 @@ elf_m68k_adjust_dynamic_symbol (info, h)
        {
          if (CPU32_FLAG (dynobj))
            s->size += PLT_CPU32_ENTRY_SIZE;
+         else if (CFV4E_FLAG (dynobj))
+           s->size += CFV4E_PLT_ENTRY_SIZE;
          else
            s->size += PLT_ENTRY_SIZE;
        }
@@ -1000,6 +1031,8 @@ elf_m68k_adjust_dynamic_symbol (info, h)
       /* Make room for this entry.  */
       if (CPU32_FLAG (dynobj))
         s->size += PLT_CPU32_ENTRY_SIZE;
+      else if (CFV4E_FLAG (dynobj))
+       s->size += CFV4E_PLT_ENTRY_SIZE;
       else
         s->size += PLT_ENTRY_SIZE;
 
@@ -1024,12 +1057,12 @@ elf_m68k_adjust_dynamic_symbol (info, h)
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->weakdef != NULL)
+  if (h->u.weakdef != NULL)
     {
-      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
-                 || h->weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->weakdef->root.u.def.section;
-      h->root.u.def.value = h->weakdef->root.u.def.value;
+      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+                 || h->u.weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->u.weakdef->root.u.def.section;
+      h->root.u.def.value = h->u.weakdef->root.u.def.value;
       return TRUE;
     }
 
@@ -1208,7 +1241,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
 
       if (strip)
        {
-         _bfd_strip_section_from_output (info, s);
+         s->flags |= SEC_EXCLUDE;
          continue;
        }
 
@@ -1731,8 +1764,9 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
          if (r == bfd_reloc_overflow)
            {
              if (!(info->callbacks->reloc_overflow
-                   (info, name, howto->name, (bfd_vma) 0,
-                    input_bfd, input_section, rel->r_offset)))
+                   (info, (h ? &h->root : NULL), name, howto->name,
+                    (bfd_vma) 0, input_bfd, input_section,
+                    rel->r_offset)))
                return FALSE;
            }
          else
@@ -1788,17 +1822,19 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
         corresponds to this symbol.  This is the index of this symbol
         in all the symbols for which we are making plt entries.  The
         first entry in the procedure linkage table is reserved.  */
-      if ( CPU32_FLAG (output_bfd))
-        plt_index = h->plt.offset / PLT_CPU32_ENTRY_SIZE - 1;
+      if (CPU32_FLAG (output_bfd))
+        plt_index = (h->plt.offset / PLT_CPU32_ENTRY_SIZE) - 1;
+      else if (CFV4E_FLAG (output_bfd))
+       plt_index = (h->plt.offset / CFV4E_PLT_ENTRY_SIZE) - 1;
       else
-        plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
+        plt_index = (h->plt.offset / PLT_ENTRY_SIZE) - 1;
 
       /* Get the offset into the .got table of the entry that
         corresponds to this function.  Each .got entry is 4 bytes.
         The first three are reserved.  */
       got_offset = (plt_index + 3) * 4;
 
-      if ( CPU32_FLAG (output_bfd))
+      if (CPU32_FLAG (output_bfd))
         {
           /* Fill in the entry in the procedure linkage table.  */
           memcpy (splt->contents + h->plt.offset, elf_cpu32_plt_entry,
@@ -1807,6 +1843,14 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
           plt_off2 = 12;
           plt_off3 = 18;
         }
+      else if (CFV4E_FLAG (output_bfd))
+        {
+          memcpy (splt->contents + h->plt.offset, elf_cfv4e_plt_entry,
+                 CFV4E_PLT_ENTRY_SIZE);
+          plt_off1 = 2;
+          plt_off2 = 14;
+          plt_off3 = 20;
+       }
       else
         {
           /* Fill in the entry in the procedure linkage table.  */
@@ -1819,11 +1863,12 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       /* The offset is relative to the first extension word.  */
       bfd_put_32 (output_bfd,
-                 (sgot->output_section->vma
-                  + sgot->output_offset
-                  + got_offset
-                  - (splt->output_section->vma
-                     + h->plt.offset + 2)),
+                 sgot->output_section->vma
+                 + sgot->output_offset
+                 + got_offset
+                 - (splt->output_section->vma
+                    + h->plt.offset
+                    + CFV4E_FLAG (output_bfd) ? 8 : 2),
                  splt->contents + h->plt.offset + plt_off1);
 
       bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
@@ -1836,7 +1881,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
                  (splt->output_section->vma
                   + splt->output_offset
                   + h->plt.offset
-                  + 8),
+                  + CFV4E_FLAG (output_bfd) ? 12 : 8),
                  sgot->contents + got_offset);
 
       /* Fill in the entry in the .rela.plt section.  */
@@ -2014,9 +2059,25 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
       /* Fill in the first entry in the procedure linkage table.  */
       if (splt->size > 0)
        {
-          if (!CPU32_FLAG (output_bfd))
+         if (CFV4E_FLAG (output_bfd))
+           {
+            memcpy (splt->contents, elf_cfv4e_plt0_entry, CFV4E_PLT_ENTRY_SIZE);
+             bfd_put_32 (output_bfd,
+                         (sgot->output_section->vma
+                          + sgot->output_offset + 4
+                          - (splt->output_section->vma + 2)),
+                         splt->contents + 2);
+             bfd_put_32 (output_bfd,
+                         (sgot->output_section->vma
+                          + sgot->output_offset + 8
+                          - (splt->output_section->vma + 10) - 8),
+                         splt->contents + 12);
+             elf_section_data (splt->output_section)->this_hdr.sh_entsize
+              = CFV4E_PLT_ENTRY_SIZE;
+           }
+         else if (CPU32_FLAG (output_bfd))
             {
-             memcpy (splt->contents, elf_m68k_plt0_entry, PLT_ENTRY_SIZE);
+              memcpy (splt->contents, elf_cpu32_plt0_entry, PLT_CPU32_ENTRY_SIZE);
              bfd_put_32 (output_bfd,
                          (sgot->output_section->vma
                           + sgot->output_offset + 4
@@ -2028,11 +2089,11 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
                           - (splt->output_section->vma + 10)),
                          splt->contents + 12);
               elf_section_data (splt->output_section)->this_hdr.sh_entsize
-               = PLT_ENTRY_SIZE;
+               = PLT_CPU32_ENTRY_SIZE;
             }
-          else /* cpu32 */
+          else
             {
-              memcpy (splt->contents, elf_cpu32_plt0_entry, PLT_CPU32_ENTRY_SIZE);
+             memcpy (splt->contents, elf_m68k_plt0_entry, PLT_ENTRY_SIZE);
              bfd_put_32 (output_bfd,
                          (sgot->output_section->vma
                           + sgot->output_offset + 4
@@ -2044,7 +2105,7 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
                           - (splt->output_section->vma + 10)),
                          splt->contents + 12);
               elf_section_data (splt->output_section)->this_hdr.sh_entsize
-               = PLT_CPU32_ENTRY_SIZE;
+               = PLT_ENTRY_SIZE;
             }
        }
     }
@@ -2171,7 +2232,7 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
       bfd_put_32 (abfd, irel->r_offset + datasec->output_offset, p);
       memset (p + 4, 0, 8);
       if (targetsec != NULL)
-       strncpy (p + 4, targetsec->output_section->name, 8);
+       strncpy ((char *) p + 4, targetsec->output_section->name, 8);
     }
 
   if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
@@ -2207,6 +2268,18 @@ elf32_m68k_reloc_type_class (rela)
     }
 }
 
+/* Return address for Ith PLT stub in section PLT, for relocation REL
+   or (bfd_vma) -1 if it should not be included.  */
+
+static bfd_vma
+elf_m68k_plt_sym_val (bfd_vma i, const asection *plt,
+                     const arelent *rel ATTRIBUTE_UNUSED)
+{
+  if (CPU32_FLAG (plt->owner))
+    return plt->vma + (i + 1) * PLT_CPU32_ENTRY_SIZE;
+  return plt->vma + (i + 1) * PLT_ENTRY_SIZE;
+}
+
 #define TARGET_BIG_SYM                 bfd_elf32_m68k_vec
 #define TARGET_BIG_NAME                        "elf32-m68k"
 #define ELF_MACHINE_CODE               EM_68K
@@ -2236,6 +2309,7 @@ elf32_m68k_reloc_type_class (rela)
 #define bfd_elf32_bfd_print_private_bfd_data \
                                         elf32_m68k_print_private_bfd_data
 #define elf_backend_reloc_type_class   elf32_m68k_reloc_type_class
+#define elf_backend_plt_sym_val                elf_m68k_plt_sym_val
 
 #define elf_backend_can_gc_sections 1
 #define elf_backend_can_refcount 1
This page took 0.029075 seconds and 4 git commands to generate.