daily update
[deliverable/binutils-gdb.git] / bfd / elf32-m68k.c
index 4820e47d263a3d60d28af14e5ff5b768f85ff583..ffa1668ada49e66ec27703d8ec715a4e35d4a8bf 100644 (file)
@@ -1,12 +1,12 @@
 /* Motorola 68k series support for 32-bit ELF
    Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005, 2006 Free Software Foundation, Inc.
+   2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
@@ -174,7 +175,21 @@ reloc_type_lookup (abfd, code)
   return 0;
 }
 
+static reloc_howto_type *
+reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++)
+    if (howto_table[i].name != NULL
+       && strcasecmp (howto_table[i].name, r_name) == 0)
+      return &howto_table[i];
+
+  return NULL;
+}
+
 #define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup reloc_name_lookup
 #define ELF_ARCH bfd_arch_m68k
 \f
 /* Functions for the m68k ELF linker.  */
@@ -286,6 +301,40 @@ static const struct elf_m68k_plt_info elf_isab_plt_info = {
   elf_isab_plt_entry, { 2, 20 }, 12
 };
 
+#define ISAC_PLT_ENTRY_SIZE 24 
+
+static const bfd_byte elf_isac_plt0_entry[ISAC_PLT_ENTRY_SIZE] =
+{
+  0x20, 0x3c,            /* move.l #offset,%d0 */
+  0, 0, 0, 0,            /* replaced with .got + 4 - . */
+  0x2e, 0xbb, 0x08, 0xfa, /* move.l (-6,%pc,%d0:l),(%sp) */
+  0x20, 0x3c,            /* move.l #offset,%d0 */
+  0, 0, 0, 0,            /* replaced with .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_isac_plt_entry[ISAC_PLT_ENTRY_SIZE] =
+{
+  0x20, 0x3c,            /* move.l #offset,%d0 */
+  0, 0, 0, 0,            /* replaced with (.got 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 */
+  0x61, 0xff,            /* bsr.l .plt */
+  0, 0, 0, 0             /* replaced with .plt - . */
+};
+
+static const struct elf_m68k_plt_info elf_isac_plt_info = {
+  ISAC_PLT_ENTRY_SIZE,
+  elf_isac_plt0_entry, { 2, 12},
+  elf_isac_plt_entry, { 2, 20 }, 12
+};
+
 #define CPU32_PLT_ENTRY_SIZE 24
 /* Procedure linkage table entries for the cpu32 */
 static const bfd_byte elf_cpu32_plt0_entry[CPU32_PLT_ENTRY_SIZE] =
@@ -429,11 +478,13 @@ elf32_m68k_object_p (bfd *abfd)
   unsigned features = 0;
   flagword eflags = elf_elfheader (abfd)->e_flags;
 
-  if (eflags & EF_M68K_M68000)
+  if ((eflags & EF_M68K_ARCH_MASK) == EF_M68K_M68000)
     features |= m68000;
-  else if (eflags & EF_M68K_CPU32)
+  else if ((eflags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32)
     features |= cpu32;
-  else if (eflags & EF_M68K_CF_ISA_MASK)
+  else if ((eflags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO)
+    features |= fido_a;
+  else
     {
       switch (eflags & EF_M68K_CF_ISA_MASK)
        {
@@ -452,6 +503,9 @@ elf32_m68k_object_p (bfd *abfd)
        case EF_M68K_CF_ISA_B:
          features |= mcfisa_a|mcfisa_b|mcfhwdiv|mcfusp;
          break;
+       case EF_M68K_CF_ISA_C:
+         features |= mcfisa_a|mcfisa_c|mcfhwdiv|mcfusp;
+         break;
        }
       switch (eflags & EF_M68K_CF_MAC_MASK)
        {
@@ -518,10 +572,27 @@ elf32_m68k_merge_private_bfd_data (ibfd, obfd)
   else
     {
       out_flags = elf_elfheader (obfd)->e_flags;
-      in_isa = (in_flags & EF_M68K_CF_ISA_MASK);
-      out_isa = (out_flags & EF_M68K_CF_ISA_MASK);
+      unsigned int variant_mask;
+
+      if ((in_flags & EF_M68K_ARCH_MASK) == EF_M68K_M68000)
+       variant_mask = 0;
+      else if ((in_flags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32)
+       variant_mask = 0;
+      else if ((in_flags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO)
+       variant_mask = 0;
+      else
+       variant_mask = EF_M68K_CF_ISA_MASK;
+
+      in_isa = (in_flags & variant_mask);
+      out_isa = (out_flags & variant_mask);
       if (in_isa > out_isa)
        out_flags ^= in_isa ^ out_isa;
+      if (((in_flags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32
+          && (out_flags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO)
+         || ((in_flags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO
+             && (out_flags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32))
+       out_flags = EF_M68K_FIDO;
+      else
       out_flags |= in_flags ^ in_isa;
     }
   elf_elfheader (obfd)->e_flags = out_flags;
@@ -548,58 +619,64 @@ elf32_m68k_print_private_bfd_data (abfd, ptr)
   /* xgettext:c-format */
   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
 
-  if (eflags & EF_M68K_CPU32)
-    fprintf (file, " [cpu32]");
-
-  if (eflags & EF_M68K_M68000)
+  if ((eflags & EF_M68K_ARCH_MASK) == EF_M68K_M68000)
     fprintf (file, " [m68000]");
-
-  if (eflags & EF_M68K_CFV4E)
-    fprintf (file, " [cfv4e]");
-
-  if (eflags & EF_M68K_CF_ISA_MASK)
+  else if ((eflags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32)
+    fprintf (file, " [cpu32]");
+  else if ((eflags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO)
+    fprintf (file, " [fido]");
+  else
     {
-      char const *isa = _("unknown");
-      char const *mac = _("unknown");
-      char const *additional = "";
-      
-      switch (eflags & EF_M68K_CF_ISA_MASK)
-       {
-       case EF_M68K_CF_ISA_A_NODIV:
-         isa = "A";
-         additional = " [nodiv]";
-         break;
-       case EF_M68K_CF_ISA_A:
-         isa = "A";
-         break;
-       case EF_M68K_CF_ISA_A_PLUS:
-         isa = "A+";
-         break;
-       case EF_M68K_CF_ISA_B_NOUSP:
-         isa = "B";
-         additional = " [nousp]";
-         break;
-       case EF_M68K_CF_ISA_B:
-         isa = "B";
-         break;
-       }
-      fprintf (file, " [isa %s]%s", isa, additional);
-      if (eflags & EF_M68K_CF_FLOAT)
-       fprintf (file, " [float]");
-      switch (eflags & EF_M68K_CF_MAC_MASK)
+      if ((eflags & EF_M68K_ARCH_MASK) == EF_M68K_CFV4E)
+       fprintf (file, " [cfv4e]");
+
+      if (eflags & EF_M68K_CF_ISA_MASK)
        {
-       case 0:
-         mac = NULL;
-         break;
-       case EF_M68K_CF_MAC:
-         mac = "mac";
-         break;
-       case EF_M68K_CF_EMAC:
-         mac = "emac";
-         break;
+         char const *isa = _("unknown");
+         char const *mac = _("unknown");
+         char const *additional = "";
+      
+         switch (eflags & EF_M68K_CF_ISA_MASK)
+           {
+           case EF_M68K_CF_ISA_A_NODIV:
+             isa = "A";
+             additional = " [nodiv]";
+             break;
+           case EF_M68K_CF_ISA_A:
+             isa = "A";
+             break;
+           case EF_M68K_CF_ISA_A_PLUS:
+             isa = "A+";
+             break;
+           case EF_M68K_CF_ISA_B_NOUSP:
+             isa = "B";
+             additional = " [nousp]";
+             break;
+           case EF_M68K_CF_ISA_B:
+             isa = "B";
+             break;
+           case EF_M68K_CF_ISA_C:
+             isa = "C";
+             break;
+           }
+         fprintf (file, " [isa %s]%s", isa, additional);
+         if (eflags & EF_M68K_CF_FLOAT)
+           fprintf (file, " [float]");
+         switch (eflags & EF_M68K_CF_MAC_MASK)
+           {
+           case 0:
+             mac = NULL;
+             break;
+           case EF_M68K_CF_MAC:
+             mac = "mac";
+             break;
+           case EF_M68K_CF_EMAC:
+             mac = "emac";
+             break;
+           }
+         if (mac)
+           fprintf (file, " [%s]", mac);
        }
-      if (mac)
-       fprintf (file, " [%s]", mac);
     }
   
   fputc ('\n', file);
@@ -1109,6 +1186,8 @@ elf_m68k_get_plt_info (bfd *output_bfd)
     return &elf_cpu32_plt_info;
   if (features & mcfisa_b)
     return &elf_isab_plt_info;
+  if (features & mcfisa_c)
+    return &elf_isac_plt_info;
   return &elf_m68k_plt_info;
 }
 
@@ -1137,7 +1216,6 @@ elf_m68k_adjust_dynamic_symbol (info, 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;
@@ -1282,28 +1360,7 @@ elf_m68k_adjust_dynamic_symbol (info, h)
       h->needs_copy = 1;
     }
 
-  /* We need to figure out the alignment required for this symbol.  I
-     have no idea how ELF linkers handle this.  */
-  power_of_two = bfd_log2 (h->size);
-  if (power_of_two > 3)
-    power_of_two = 3;
-
-  /* Apply the required alignment.  */
-  s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
-  if (power_of_two > bfd_get_section_alignment (dynobj, s))
-    {
-      if (!bfd_set_section_alignment (dynobj, s, power_of_two))
-       return FALSE;
-    }
-
-  /* Define the symbol as being at this point in the section.  */
-  h->root.u.def.section = s;
-  h->root.u.def.value = s->size;
-
-  /* Increment the section size to make room for the symbol.  */
-  s->size += h->size;
-
-  return TRUE;
+  return _bfd_elf_adjust_dynamic_copy (h, s);
 }
 
 /* Set the sizes of the dynamic sections.  */
@@ -1543,9 +1600,6 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
-  if (info->relocatable)
-    return TRUE;
-
   dynobj = elf_hash_table (info)->dynobj;
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
@@ -1600,6 +1654,20 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
                                   unresolved_reloc, warned);
        }
 
+      if (sec != NULL && elf_discarded_section (sec))
+       {
+         /* For relocs against symbols from removed linkonce sections,
+            or sections discarded by a linker script, we just want the
+            section contents zeroed.  Avoid any special processing.  */
+         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+         rel->r_info = 0;
+         rel->r_addend = 0;
+         continue;
+       }
+
+      if (info->relocatable)
+       continue;
+
       switch (r_type)
        {
        case R_68K_GOT8:
This page took 0.033494 seconds and 4 git commands to generate.