Really remove operands64.d, operands64.s, operands.d and operands.s as
[deliverable/binutils-gdb.git] / bfd / elf32-m68k.c
index db320c229cd69686f3681e2ca2cf4e08afdb4b23..50b962dad3fc213528d036910869d2deeb6c8b98 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, 2005 Free Software Foundation, Inc.
+   2004, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -24,6 +24,7 @@
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/m68k.h"
+#include "opcode/m68k.h"
 
 static reloc_howto_type *reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
@@ -36,12 +37,6 @@ static struct bfd_link_hash_table *elf_m68k_link_hash_table_create
 static bfd_boolean elf_m68k_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           const Elf_Internal_Rela *));
-static asection *elf_m68k_gc_mark_hook
-  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
-          struct elf_link_hash_entry *, Elf_Internal_Sym *));
-static bfd_boolean elf_m68k_gc_sweep_hook
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
 static bfd_boolean elf_m68k_adjust_dynamic_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 static bfd_boolean elf_m68k_size_dynamic_sections
@@ -189,6 +184,40 @@ reloc_type_lookup (abfd, code)
 
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
 
+/* Describes one of the various PLT styles.  */
+
+struct elf_m68k_plt_info
+{
+  /* The size of each PLT entry.  */
+  bfd_vma size;
+
+  /* The template for the first PLT entry.  */
+  const bfd_byte *plt0_entry;
+
+  /* Offsets of fields in PLT0_ENTRY that require R_68K_PC32 relocations.
+     The comments by each member indicate the value that the relocation
+     is against.  */
+  struct {
+    unsigned int got4; /* .got + 4 */
+    unsigned int got8; /* .got + 8 */
+  } plt0_relocs;
+
+  /* The template for a symbol's PLT entry.  */
+  const bfd_byte *symbol_entry;
+
+  /* Offsets of fields in SYMBOL_ENTRY that require R_68K_PC32 relocations.
+     The comments by each member indicate the value that the relocation
+     is against.  */
+  struct {
+    unsigned int got; /* the symbol's .got.plt entry */
+    unsigned int plt; /* .plt */
+  } symbol_relocs;
+
+  /* The offset of the resolver stub from the start of SYMBOL_ENTRY.
+     The stub starts with "move.l #relocoffset,%d0".  */
+  bfd_vma symbol_resolve_entry;
+};
+
 /* The size in bytes of an entry in the procedure linkage table.  */
 
 #define PLT_ENTRY_SIZE 20
@@ -199,9 +228,9 @@ reloc_type_lookup (abfd, code)
 static const bfd_byte elf_m68k_plt0_entry[PLT_ENTRY_SIZE] =
 {
   0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */
-  0, 0, 0, 0,            /* replaced with offset to .got + 4.  */
+  0, 0, 0, 2,            /* + (.got + 4) - . */
   0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,addr]) */
-  0, 0, 0, 0,            /* replaced with offset to .got + 8.  */
+  0, 0, 0, 2,            /* + (.got + 8) - . */
   0, 0, 0, 0             /* pad out to 20 bytes.  */
 };
 
@@ -210,71 +239,84 @@ static const bfd_byte elf_m68k_plt0_entry[PLT_ENTRY_SIZE] =
 static const bfd_byte elf_m68k_plt_entry[PLT_ENTRY_SIZE] =
 {
   0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,symbol@GOTPC]) */
-  0, 0, 0, 0,            /* replaced with offset to symbol's .got entry.  */
+  0, 0, 0, 2,            /* + (.got.plt entry) - . */
   0x2f, 0x3c,            /* move.l #offset,-(%sp) */
-  0, 0, 0, 0,            /* replaced with offset into relocation table.  */
+  0, 0, 0, 0,            /* + reloc index */
   0x60, 0xff,            /* bra.l .plt */
-  0, 0, 0, 0             /* replaced with offset to start of .plt.  */
+  0, 0, 0, 0             /* + .plt - . */
 };
 
+static const struct elf_m68k_plt_info elf_m68k_plt_info = {
+  PLT_ENTRY_SIZE,
+  elf_m68k_plt0_entry, { 4, 12 },
+  elf_m68k_plt_entry, { 4, 16 }, 8
+};
 
-#define CFV4E_PLT_ENTRY_SIZE 24 
-
-#define CFV4E_FLAG(abfd)  (elf_elfheader (abfd)->e_flags & EF_CFV4E)
+#define ISAB_PLT_ENTRY_SIZE 24 
 
-static const bfd_byte elf_cfv4e_plt0_entry[CFV4E_PLT_ENTRY_SIZE] =
+static const bfd_byte elf_isab_plt0_entry[ISAB_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 */
+  0x20, 0x3c,             /* move.l #offset,%d0 */
+  0, 0, 0, 0,             /* + (.got + 4) - . */
+  0x2f, 0x3b, 0x08, 0xfa, /* move.l (-6,%pc,%d0:l),-(%sp) */
+  0x20, 0x3c,             /* move.l #offset,%d0 */
+  0, 0, 0, 0,             /* + (.got + 8) - . */
+  0x20, 0x7b, 0x08, 0xfa, /* move.l (-6,%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] =
+static const bfd_byte elf_isab_plt_entry[ISAB_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 */
+  0x20, 0x3c,             /* move.l #offset,%d0 */
+  0, 0, 0, 0,             /* + (.got.plt entry) - . */
+  0x20, 0x7b, 0x08, 0xfa, /* move.l (-6,%pc,%d0:l), %a0 */
   0x4e, 0xd0,             /* jmp (%a0) */
   0x2f, 0x3c,             /* move.l #offset,-(%sp) */
-  0, 0, 0, 0,             /* Replaced with offset into relocation table.  */
+  0, 0, 0, 0,             /* + reloc index */
   0x60, 0xff,             /* bra.l .plt */
-  0, 0, 0, 0              /* Replaced with offset to start of .plt.  */
+  0, 0, 0, 0              /* + .plt - . */
 };
 
-#define CPU32_FLAG(abfd)  (elf_elfheader (abfd)->e_flags & EF_CPU32)
+static const struct elf_m68k_plt_info elf_isab_plt_info = {
+  ISAB_PLT_ENTRY_SIZE,
+  elf_isab_plt0_entry, { 2, 12 },
+  elf_isab_plt_entry, { 2, 20 }, 12
+};
 
-#define PLT_CPU32_ENTRY_SIZE 24
+#define CPU32_PLT_ENTRY_SIZE 24
 /* Procedure linkage table entries for the cpu32 */
-static const bfd_byte elf_cpu32_plt0_entry[PLT_CPU32_ENTRY_SIZE] =
+static const bfd_byte elf_cpu32_plt0_entry[CPU32_PLT_ENTRY_SIZE] =
 {
   0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */
-  0, 0, 0, 0,             /* replaced with offset to .got + 4.  */
+  0, 0, 0, 2,             /* + (.got + 4) - . */
   0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */
-  0, 0, 0, 0,             /* replace with offset to .got +8.  */
+  0, 0, 0, 2,             /* + (.got + 8) - . */
   0x4e, 0xd1,             /* jmp %a1@ */
   0, 0, 0, 0,             /* pad out to 24 bytes.  */
   0, 0
 };
 
-static const bfd_byte elf_cpu32_plt_entry[PLT_CPU32_ENTRY_SIZE] =
+static const bfd_byte elf_cpu32_plt_entry[CPU32_PLT_ENTRY_SIZE] =
 {
   0x22, 0x7b, 0x01, 0x70,  /* moveal %pc@(0xc), %a1 */
-  0, 0, 0, 0,              /* replaced with offset to symbol's .got entry.  */
+  0, 0, 0, 2,              /* + (.got.plt entry) - . */
   0x4e, 0xd1,              /* jmp %a1@ */
   0x2f, 0x3c,              /* move.l #offset,-(%sp) */
-  0, 0, 0, 0,              /* replaced with offset into relocation table.  */
+  0, 0, 0, 0,              /* + reloc index */
   0x60, 0xff,              /* bra.l .plt */
-  0, 0, 0, 0,              /* replaced with offset to start of .plt.  */
+  0, 0, 0, 0,              /* + .plt - . */
   0, 0
 };
 
+static const struct elf_m68k_plt_info elf_cpu32_plt_info = {
+  CPU32_PLT_ENTRY_SIZE,
+  elf_cpu32_plt0_entry, { 4, 12 },
+  elf_cpu32_plt_entry, { 4, 18 }, 10
+};
+
 /* The m68k linker needs to keep track of the number of relocs that it
    decides to copy in check_relocs for each symbol.  This is so that it
    can discard PC relative relocs if it doesn't need them when linking
@@ -314,6 +356,10 @@ struct elf_m68k_link_hash_table
 
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
+
+  /* The PLT format used by this link, or NULL if the format has not
+     yet been chosen.  */
+  const struct elf_m68k_plt_info *plt_info;
 };
 
 /* Get the m68k ELF linker hash table from a link_info structure.  */
@@ -360,18 +406,72 @@ elf_m68k_link_hash_table_create (abfd)
   if (ret == (struct elf_m68k_link_hash_table *) NULL)
     return NULL;
 
-  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
-                                      elf_m68k_link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+                                     elf_m68k_link_hash_newfunc,
+                                     sizeof (struct elf_m68k_link_hash_entry)))
     {
       free (ret);
       return NULL;
     }
 
   ret->sym_sec.abfd = NULL;
+  ret->plt_info = NULL;
 
   return &ret->root.root;
 }
 
+/* Set the right machine number.  */
+
+static bfd_boolean
+elf32_m68k_object_p (bfd *abfd)
+{
+  unsigned int mach = 0;
+  unsigned features = 0;
+  flagword eflags = elf_elfheader (abfd)->e_flags;
+
+  if (eflags & EF_M68K_M68000)
+    features |= m68000;
+  else if (eflags & EF_M68K_CPU32)
+    features |= cpu32;
+  else if (eflags & EF_M68K_ISA_MASK)
+    {
+      switch (eflags & EF_M68K_ISA_MASK)
+       {
+       case EF_M68K_ISA_A_NODIV:
+         features |= mcfisa_a;
+         break;
+       case EF_M68K_ISA_A:
+         features |= mcfisa_a|mcfhwdiv;
+         break;
+       case EF_M68K_ISA_A_PLUS:
+         features |= mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp;
+         break;
+       case EF_M68K_ISA_B_NOUSP:
+         features |= mcfisa_a|mcfisa_b|mcfhwdiv;
+         break;
+       case EF_M68K_ISA_B:
+         features |= mcfisa_a|mcfisa_b|mcfhwdiv|mcfusp;
+         break;
+       }
+      switch (eflags & EF_M68K_MAC_MASK)
+       {
+       case EF_M68K_MAC:
+         features |= mcfmac;
+         break;
+       case EF_M68K_EMAC:
+         features |= mcfemac;
+         break;
+       }
+      if (eflags & EF_M68K_FLOAT)
+       features |= cfloat;
+    }
+
+  mach = bfd_m68k_features_to_mach (features);
+  bfd_default_set_arch_mach (abfd, bfd_arch_m68k, mach);
+
+  return TRUE;
+}
+
 /* Keep m68k-specific flags in the ELF header.  */
 static bfd_boolean
 elf32_m68k_set_private_flags (abfd, flags)
@@ -392,19 +492,39 @@ elf32_m68k_merge_private_bfd_data (ibfd, obfd)
 {
   flagword out_flags;
   flagword in_flags;
-
+  flagword out_isa;
+  flagword in_isa;
+  const bfd_arch_info_type *arch_info;
+  
   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return TRUE;
-
-  in_flags  = elf_elfheader (ibfd)->e_flags;
-  out_flags = elf_elfheader (obfd)->e_flags;
-
+    return FALSE;
+
+  /* Get the merged machine.  This checks for incompatibility between
+     Coldfire & non-Coldfire flags, incompability between different
+     Coldfire ISAs, and incompability between different MAC types.  */
+  arch_info = bfd_arch_get_compatible (ibfd, obfd, FALSE);
+  if (!arch_info)
+    return FALSE;
+
+  bfd_set_arch_mach (obfd, bfd_arch_m68k, arch_info->mach);
+  
+  in_flags = elf_elfheader (ibfd)->e_flags;
   if (!elf_flags_init (obfd))
     {
       elf_flags_init (obfd) = TRUE;
-      elf_elfheader (obfd)->e_flags = in_flags;
+      out_flags = in_flags;
     }
+  else
+    {
+      out_flags = elf_elfheader (obfd)->e_flags;
+      in_isa = (in_flags & EF_M68K_ISA_MASK);
+      out_isa = (out_flags & EF_M68K_ISA_MASK);
+      if (in_isa > out_isa)
+       out_flags ^= in_isa ^ out_isa;
+      out_flags |= in_flags ^ in_isa;
+    }
+  elf_elfheader (obfd)->e_flags = out_flags;
 
   return TRUE;
 }
@@ -416,6 +536,7 @@ elf32_m68k_print_private_bfd_data (abfd, ptr)
      PTR ptr;
 {
   FILE *file = (FILE *) ptr;
+  flagword eflags = elf_elfheader (abfd)->e_flags;
 
   BFD_ASSERT (abfd != NULL && ptr != NULL);
 
@@ -427,12 +548,60 @@ elf32_m68k_print_private_bfd_data (abfd, ptr)
   /* xgettext:c-format */
   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
 
-  if (elf_elfheader (abfd)->e_flags & EF_CPU32)
-    fprintf (file, _(" [cpu32]"));
+  if (eflags & EF_M68K_CPU32)
+    fprintf (file, " [cpu32]");
+
+  if (eflags & EF_M68K_M68000)
+    fprintf (file, " [m68000]");
 
-  if (elf_elfheader (abfd)->e_flags & EF_M68000)
-    fprintf (file, _(" [m68000]"));
+  if (eflags & EF_M68K_CFV4E)
+    fprintf (file, " [cfv4e]");
 
+  if (eflags & EF_M68K_ISA_MASK)
+    {
+      char const *isa = _("unknown");
+      char const *mac = _("unknown");
+      char const *additional = "";
+      
+      switch (eflags & EF_M68K_ISA_MASK)
+       {
+       case EF_M68K_ISA_A_NODIV:
+         isa = "A";
+         additional = " [nodiv]";
+         break;
+       case EF_M68K_ISA_A:
+         isa = "A";
+         break;
+       case EF_M68K_ISA_A_PLUS:
+         isa = "A+";
+         break;
+       case EF_M68K_ISA_B_NOUSP:
+         isa = "B";
+         additional = " [nousp]";
+         break;
+       case EF_M68K_ISA_B:
+         isa = "B";
+         break;
+       }
+      fprintf (file, " [isa %s]%s", isa, additional);
+      if (eflags & EF_M68K_FLOAT)
+       fprintf (file, " [float]");
+      switch (eflags & EF_M68K_MAC_MASK)
+       {
+       case 0:
+         mac = NULL;
+         break;
+       case EF_M68K_MAC:
+         mac = "mac";
+         break;
+       case EF_M68K_EMAC:
+         mac = "emac";
+         break;
+       }
+      if (mac)
+       fprintf (file, " [%s]", mac);
+    }
+  
   fputc ('\n', file);
 
   return TRUE;
@@ -689,7 +858,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
                  if (name == NULL)
                    return FALSE;
 
-                 BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+                 BFD_ASSERT (CONST_STRNEQ (name, ".rela")
                              && strcmp (bfd_get_section_name (abfd, sec),
                                         name + 5) == 0);
 
@@ -745,14 +914,16 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
                  else
                    {
                      asection *s;
+                     void *vpp;
+
                      s = (bfd_section_from_r_symndx
                           (abfd, &elf_m68k_hash_table (info)->sym_sec,
                            sec, r_symndx));
                      if (s == NULL)
                        return FALSE;
 
-                     head = ((struct elf_m68k_pcrel_relocs_copied **)
-                             &elf_section_data (s)->local_dynrel);
+                     vpp = &elf_section_data (s)->local_dynrel;
+                     head = (struct elf_m68k_pcrel_relocs_copied **) vpp;
                    }
 
                  for (p = *head; p != NULL; p = p->next)
@@ -803,50 +974,30 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
    relocation.  */
 
 static asection *
-elf_m68k_gc_mark_hook (sec, info, rel, h, sym)
-     asection *sec;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     Elf_Internal_Rela *rel;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+elf_m68k_gc_mark_hook (asection *sec,
+                      struct bfd_link_info *info,
+                      Elf_Internal_Rela *rel,
+                      struct elf_link_hash_entry *h,
+                      Elf_Internal_Sym *sym)
 {
   if (h != NULL)
-    {
-      switch (ELF32_R_TYPE (rel->r_info))
-       {
-       case R_68K_GNU_VTINHERIT:
-       case R_68K_GNU_VTENTRY:
-         break;
-
-       default:
-         switch (h->root.type)
-           {
-           default:
-             break;
-
-           case bfd_link_hash_defined:
-           case bfd_link_hash_defweak:
-             return h->root.u.def.section;
-
-           case bfd_link_hash_common:
-             return h->root.u.c.p->section;
-           }
-       }
-    }
-  else
-    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
-  return NULL;
+    switch (ELF32_R_TYPE (rel->r_info))
+      {
+      case R_68K_GNU_VTINHERIT:
+      case R_68K_GNU_VTENTRY:
+       return NULL;
+      }
+
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
 /* Update the got entry reference counts for the section being removed.  */
 
 static bfd_boolean
-elf_m68k_gc_sweep_hook (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+elf_m68k_gc_sweep_hook (bfd *abfd,
+                       struct bfd_link_info *info,
+                       asection *sec,
+                       const Elf_Internal_Rela *relocs)
 {
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -945,6 +1096,32 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs)
 
   return TRUE;
 }
+\f
+/* Return the type of PLT associated with OUTPUT_BFD.  */
+
+static const struct elf_m68k_plt_info *
+elf_m68k_get_plt_info (bfd *output_bfd)
+{
+  unsigned int features;
+
+  features = bfd_m68k_mach_to_features (bfd_get_mach (output_bfd));
+  if (features & cpu32)
+    return &elf_cpu32_plt_info;
+  if (features & mcfisa_b)
+    return &elf_isab_plt_info;
+  return &elf_m68k_plt_info;
+}
+
+/* This function is called after all the input files have been read,
+   and the input sections have been assigned to output sections.
+   It's a convenient place to determine the PLT style.  */
+
+static bfd_boolean
+elf_m68k_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+{
+  elf_m68k_hash_table (info)->plt_info = elf_m68k_get_plt_info (output_bfd);
+  return TRUE;
+}
 
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
@@ -957,10 +1134,12 @@ elf_m68k_adjust_dynamic_symbol (info, h)
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
 {
+  struct elf_m68k_link_hash_table *htab;
   bfd *dynobj;
   asection *s;
   unsigned int power_of_two;
 
+  htab = elf_m68k_hash_table (info);
   dynobj = elf_hash_table (info)->dynobj;
 
   /* Make sure we know what is going on here.  */
@@ -1010,14 +1189,7 @@ elf_m68k_adjust_dynamic_symbol (info, h)
       /* If this is the first .plt entry, make room for the special
         first entry.  */
       if (s->size == 0)
-       {
-         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;
-       }
+       s->size = htab->plt_info->size;
 
       /* If this symbol is not defined in a regular file, and we are
         not generating a shared library, then set the symbol to this
@@ -1034,12 +1206,7 @@ elf_m68k_adjust_dynamic_symbol (info, h)
       h->plt.offset = s->size;
 
       /* 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;
+      s->size += htab->plt_info->size;
 
       /* We also need to make an entry in the .got.plt section, which
         will be placed in the .got section by the linker script.  */
@@ -1081,6 +1248,13 @@ elf_m68k_adjust_dynamic_symbol (info, h)
   if (info->shared)
     return TRUE;
 
+  if (h->size == 0)
+    {
+      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
+                            h->root.root.string);
+      return TRUE;
+    }
+
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
      an entry for this symbol in the .dynsym section.  The dynamic
@@ -1202,7 +1376,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
          /* Remember whether there is a PLT.  */
          plt = s->size != 0;
        }
-      else if (strncmp (name, ".rela", 5) == 0)
+      else if (CONST_STRNEQ (name, ".rela"))
        {
          if (s->size != 0)
            {
@@ -1213,7 +1387,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
              s->reloc_count = 0;
            }
        }
-      else if (strncmp (name, ".got", 4) != 0
+      else if (! CONST_STRNEQ (name, ".got")
               && strcmp (name, ".dynbss") != 0)
        {
          /* It's not one of our sections, so don't allocate space.  */
@@ -1725,10 +1899,11 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
               && h->def_dynamic))
        {
          (*_bfd_error_handler)
-           (_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"),
+           (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
             input_bfd,
             input_section,
             (long) rel->r_offset,
+            howto->name,
             h->root.root.string);
          return FALSE;
        }
@@ -1776,6 +1951,21 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
   return TRUE;
 }
 
+/* Install an M_68K_PC32 relocation against VALUE at offset OFFSET
+   into section SEC.  */
+
+static void
+elf_m68k_install_pc32 (asection *sec, bfd_vma offset, bfd_vma value)
+{
+  /* Make VALUE PC-relative.  */
+  value -= sec->output_section->vma + offset;
+
+  /* Apply any in-place addend.  */
+  value += bfd_get_32 (sec->owner, sec->contents + offset);
+
+  bfd_put_32 (sec->owner, value, sec->contents + offset);
+}
+
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
@@ -1787,12 +1977,12 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
      Elf_Internal_Sym *sym;
 {
   bfd *dynobj;
-  int plt_off1, plt_off2, plt_off3;
 
   dynobj = elf_hash_table (info)->dynobj;
 
   if (h->plt.offset != (bfd_vma) -1)
     {
+      const struct elf_m68k_plt_info *plt_info;
       asection *splt;
       asection *sgot;
       asection *srela;
@@ -1806,6 +1996,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       BFD_ASSERT (h->dynindx != -1);
 
+      plt_info = elf_m68k_hash_table (info)->plt_info;
       splt = bfd_get_section_by_name (dynobj, ".plt");
       sgot = bfd_get_section_by_name (dynobj, ".got.plt");
       srela = bfd_get_section_by_name (dynobj, ".rela.plt");
@@ -1815,66 +2006,36 @@ 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;
-      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_info->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))
-        {
-          /* Fill in the entry in the procedure linkage table.  */
-          memcpy (splt->contents + h->plt.offset, elf_cpu32_plt_entry,
-                 PLT_CPU32_ENTRY_SIZE);
-          plt_off1 = 4;
-          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.  */
-          memcpy (splt->contents + h->plt.offset, elf_m68k_plt_entry,
-                 PLT_ENTRY_SIZE);
-          plt_off1 = 4;
-          plt_off2 = 10;
-          plt_off3 = 16;
-        }
-
-      /* 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
-                    + CFV4E_FLAG (output_bfd) ? 8 : 2),
-                 splt->contents + h->plt.offset + plt_off1);
+      memcpy (splt->contents + h->plt.offset,
+             plt_info->symbol_entry,
+             plt_info->size);
+
+      elf_m68k_install_pc32 (splt, h->plt.offset + plt_info->symbol_relocs.got,
+                            (sgot->output_section->vma
+                             + sgot->output_offset
+                             + got_offset));
 
       bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
-                 splt->contents + h->plt.offset + plt_off2);
-      bfd_put_32 (output_bfd, - (h->plt.offset + plt_off3),
-                 splt->contents + h->plt.offset + plt_off3);
+                 splt->contents
+                 + h->plt.offset
+                 + plt_info->symbol_resolve_entry + 2);
+
+      elf_m68k_install_pc32 (splt, h->plt.offset + plt_info->symbol_relocs.plt,
+                            splt->output_section->vma);
 
       /* Fill in the entry in the global offset table.  */
       bfd_put_32 (output_bfd,
                  (splt->output_section->vma
                   + splt->output_offset
                   + h->plt.offset
-                  + CFV4E_FLAG (output_bfd) ? 12 : 8),
+                  + plt_info->symbol_resolve_entry),
                  sgot->contents + got_offset);
 
       /* Fill in the entry in the .rela.plt section.  */
@@ -1968,7 +2129,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+      || h == elf_hash_table (info)->hgot)
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
@@ -2052,54 +2213,23 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
       /* Fill in the first entry in the procedure linkage table.  */
       if (splt->size > 0)
        {
-         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_cpu32_plt0_entry, PLT_CPU32_ENTRY_SIZE);
-             bfd_put_32 (output_bfd,
-                         (sgot->output_section->vma
-                          + sgot->output_offset + 4
-                          - (splt->output_section->vma + 2)),
-                         splt->contents + 4);
-             bfd_put_32 (output_bfd,
-                         (sgot->output_section->vma
-                          + sgot->output_offset + 8
-                          - (splt->output_section->vma + 10)),
-                         splt->contents + 12);
-              elf_section_data (splt->output_section)->this_hdr.sh_entsize
-               = PLT_CPU32_ENTRY_SIZE;
-            }
-          else
-            {
-             memcpy (splt->contents, elf_m68k_plt0_entry, PLT_ENTRY_SIZE);
-             bfd_put_32 (output_bfd,
-                         (sgot->output_section->vma
-                          + sgot->output_offset + 4
-                          - (splt->output_section->vma + 2)),
-                         splt->contents + 4);
-             bfd_put_32 (output_bfd,
-                         (sgot->output_section->vma
-                          + sgot->output_offset + 8
-                          - (splt->output_section->vma + 10)),
-                         splt->contents + 12);
-              elf_section_data (splt->output_section)->this_hdr.sh_entsize
-               = PLT_ENTRY_SIZE;
-            }
+         const struct elf_m68k_plt_info *plt_info;
+
+         plt_info = elf_m68k_hash_table (info)->plt_info;
+         memcpy (splt->contents, plt_info->plt0_entry, plt_info->size);
+
+         elf_m68k_install_pc32 (splt, plt_info->plt0_relocs.got4,
+                                (sgot->output_section->vma
+                                 + sgot->output_offset
+                                 + 4));
+
+         elf_m68k_install_pc32 (splt, plt_info->plt0_relocs.got8,
+                                (sgot->output_section->vma
+                                 + sgot->output_offset
+                                 + 8));
+
+         elf_section_data (splt->output_section)->this_hdr.sh_entsize
+           = plt_info->size;
        }
     }
 
@@ -2268,9 +2398,7 @@ 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;
+  return plt->vma + (i + 1) * elf_m68k_get_plt_info (plt->owner)->size;
 }
 
 #define TARGET_BIG_SYM                 bfd_elf32_m68k_vec
@@ -2284,6 +2412,8 @@ elf_m68k_plt_sym_val (bfd_vma i, const asection *plt,
 #define bfd_elf32_bfd_final_link       bfd_elf_gc_common_final_link
 
 #define elf_backend_check_relocs       elf_m68k_check_relocs
+#define elf_backend_always_size_sections \
+                                       elf_m68k_always_size_sections
 #define elf_backend_adjust_dynamic_symbol \
                                        elf_m68k_adjust_dynamic_symbol
 #define elf_backend_size_dynamic_sections \
@@ -2303,6 +2433,7 @@ elf_m68k_plt_sym_val (bfd_vma i, const asection *plt,
                                         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_object_p           elf32_m68k_object_p
 
 #define elf_backend_can_gc_sections 1
 #define elf_backend_can_refcount 1
This page took 0.051061 seconds and 4 git commands to generate.