Add missing parts of ChangeLog entry for my change of 2000/02/19 00:59:26 to coff...
[deliverable/binutils-gdb.git] / bfd / elf32-sh.c
index ebbe352456ebbb0bb20752b3a9be04dd8a43b8df..ad60e07fd57c66fd2971c04722f8da808b4ce6ef 100644 (file)
@@ -1,5 +1,5 @@
 /* Hitachi SH specific support for 32-bit ELF
-   Copyright 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright 1996, 97, 98, 1999, 2000 Free Software Foundation, Inc.
    Contributed by Ian Lance Taylor, Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -33,6 +33,14 @@ static reloc_howto_type *sh_elf_reloc_type_lookup
   PARAMS ((bfd *, bfd_reloc_code_real_type));
 static void sh_elf_info_to_howto
   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+static boolean sh_elf_set_private_flags
+  PARAMS ((bfd *, flagword));
+static boolean sh_elf_copy_private_data
+  PARAMS ((bfd *, bfd *));
+static boolean sh_elf_merge_private_data
+  PARAMS ((bfd *, bfd *));
+boolean sh_elf_set_mach_from_flags
+  PARAMS ((bfd *));
 static boolean sh_elf_relax_section
   PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
 static boolean sh_elf_relax_delete_bytes
@@ -207,21 +215,21 @@ static reloc_howto_type sh_elf_howto_table[] =
         0xff,                  /* dst_mask */
         true),                 /* pcrel_offset */
 
-  { 10 },
-  { 11 },
-  { 12 },
-  { 13 },
-  { 14 },
-  { 15 },
-  { 16 },
-  { 17 },
-  { 18 },
-  { 19 },
-  { 20 },
-  { 21 },
-  { 22 },
-  { 23 },
-  { 24 },
+  EMPTY_HOWTO (10),
+  EMPTY_HOWTO (11),
+  EMPTY_HOWTO (12),
+  EMPTY_HOWTO (13),
+  EMPTY_HOWTO (14),
+  EMPTY_HOWTO (15),
+  EMPTY_HOWTO (16),
+  EMPTY_HOWTO (17),
+  EMPTY_HOWTO (18),
+  EMPTY_HOWTO (19),
+  EMPTY_HOWTO (20),
+  EMPTY_HOWTO (21),
+  EMPTY_HOWTO (22),
+  EMPTY_HOWTO (23),
+  EMPTY_HOWTO (24),
 
   /* The remaining relocs are a GNU extension used for relaxing.  The
      final pass of the linker never needs to do anything with any of
@@ -426,7 +434,7 @@ sh_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
      PTR data;
      asection *input_section;
      bfd *output_bfd;
-     char **error_message;
+     char **error_message ATTRIBUTE_UNUSED;
 {
   unsigned long insn;
   bfd_vma sym_value;
@@ -497,13 +505,13 @@ sh_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
 static bfd_reloc_status_type
 sh_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
                     output_bfd, error_message)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      arelent *reloc_entry;
-     asymbol *symbol;
-     PTR data;
+     asymbol *symbol ATTRIBUTE_UNUSED;
+     PTR data ATTRIBUTE_UNUSED;
      asection *input_section;
      bfd *output_bfd;
-     char **error_message;
+     char **error_message ATTRIBUTE_UNUSED;
 {
   if (output_bfd != NULL)
     reloc_entry->address += input_section->output_offset;
@@ -548,7 +556,7 @@ static const struct elf_reloc_map sh_reloc_map[] =
 
 static reloc_howto_type *
 sh_elf_reloc_type_lookup (abfd, code)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      bfd_reloc_code_real_type code;
 {
   unsigned int i;
@@ -566,7 +574,7 @@ sh_elf_reloc_type_lookup (abfd, code)
 
 static void
 sh_elf_info_to_howto (abfd, cache_ptr, dst)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      arelent *cache_ptr;
      Elf_Internal_Rela *dst;
 {
@@ -1161,13 +1169,15 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
        case R_SH_SWITCH32:
          /* These relocs types represent
               .word L2-L1
-            The r_offset field holds the difference between the reloc
+            The r_addend field holds the difference between the reloc
             address and L1.  That is the start of the reloc, and
             adding in the contents gives us the top.  We must adjust
-            both the r_offset field and the section contents.  */
+            both the r_offset field and the section contents.
+            N.B. in gas / coff bfd, the elf bfd r_addend is called r_offset,
+            and the elf bfd r_offset is called r_vaddr.  */
 
-         start = irel->r_offset;
-         stop = (bfd_vma) ((bfd_signed_vma) start - (long) irel->r_addend);
+         stop = irel->r_offset;
+         start = (bfd_vma) ((bfd_signed_vma) stop - (long) irel->r_addend);
 
          if (start > addr
              && start < toaddr
@@ -1178,8 +1188,6 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
                   && (start <= addr || start >= toaddr))
            irel->r_addend -= count;
 
-         start = stop;
-
          if (ELF32_R_TYPE (irel->r_info) == (int) R_SH_SWITCH16)
            voff = bfd_get_signed_16 (abfd, contents + nraddr);
          else if (ELF32_R_TYPE (irel->r_info) == (int) R_SH_SWITCH8)
@@ -1307,6 +1315,56 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
        {
          Elf_Internal_Sym sym;
 
+         /* Dwarf line numbers use R_SH_SWITCH32 relocs.  */
+         if (ELF32_R_TYPE (irelscan->r_info) == (int) R_SH_SWITCH32)
+           {
+             bfd_vma start, stop;
+             bfd_signed_vma voff;
+
+             if (ocontents == NULL)
+               {
+                 if (elf_section_data (o)->this_hdr.contents != NULL)
+                   ocontents = elf_section_data (o)->this_hdr.contents;
+                 else
+                   {
+                     /* We always cache the section contents.
+                         Perhaps, if info->keep_memory is false, we
+                         should free them, if we are permitted to,
+                         when we leave sh_coff_relax_section.  */
+                     ocontents = (bfd_byte *) bfd_malloc (o->_raw_size);
+                     if (ocontents == NULL)
+                       return false;
+                     if (! bfd_get_section_contents (abfd, o, ocontents,
+                                                     (file_ptr) 0,
+                                                     o->_raw_size))
+                       return false;
+                     elf_section_data (o)->this_hdr.contents = ocontents;
+                   }
+               }
+
+             stop = irelscan->r_offset;
+             start
+               = (bfd_vma) ((bfd_signed_vma) stop - (long) irelscan->r_addend);
+
+             /* STOP is in a different section, so it won't change.  */
+             if (start > addr && start < toaddr)
+               irelscan->r_addend += count;
+
+             voff = bfd_get_signed_32 (abfd, ocontents + irelscan->r_offset);
+             stop = (bfd_vma) ((bfd_signed_vma) start + voff);
+
+             if (start > addr
+                 && start < toaddr
+                 && (stop <= addr || stop >= toaddr))
+               bfd_put_signed_32 (abfd, voff + count,
+                                  ocontents + irelscan->r_offset);
+             else if (stop > addr
+                      && stop < toaddr
+                      && (start <= addr || start >= toaddr))
+               bfd_put_signed_32 (abfd, voff - count,
+                                  ocontents + irelscan->r_offset);
+           }
+
          if (ELF32_R_TYPE (irelscan->r_info) != (int) R_SH_DIR32)
            continue;
 
@@ -1621,7 +1679,7 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr)
 static boolean
 sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                         contents, relocs, local_syms, local_sections)
-     bfd *output_bfd;
+     bfd *output_bfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
      bfd *input_bfd;
      asection *input_section;
@@ -1731,7 +1789,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            {
              if (! ((*info->callbacks->undefined_symbol)
                     (info, h->root.root.string, input_bfd,
-                     input_section, rel->r_offset)))
+                     input_section, rel->r_offset, true)))
                return false;
              relocation = 0;
            }
@@ -1927,7 +1985,7 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
 static asection *
 sh_elf_gc_mark_hook (abfd, info, rel, h, sym)
        bfd *abfd;
-       struct bfd_link_info *info;
+       struct bfd_link_info *info ATTRIBUTE_UNUSED;
        Elf_Internal_Rela *rel;
        struct elf_link_hash_entry *h;
        Elf_Internal_Sym *sym;
@@ -1949,6 +2007,9 @@ sh_elf_gc_mark_hook (abfd, info, rel, h, sym)
 
           case bfd_link_hash_common:
             return h->root.u.c.p->section;
+
+         default:
+           break;
           }
        }
      }
@@ -1967,10 +2028,10 @@ sh_elf_gc_mark_hook (abfd, info, rel, h, sym)
 
 static boolean
 sh_elf_gc_sweep_hook (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     asection *sec ATTRIBUTE_UNUSED;
+     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
 {
   /* we don't use got and plt entries for sh. */
   return true;
@@ -2034,6 +2095,109 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
   return true;
 }
 
+boolean
+sh_elf_set_mach_from_flags (abfd)
+     bfd *    abfd;
+{
+  flagword flags = elf_elfheader (abfd)->e_flags;
+
+  switch (flags & EF_SH_MACH_MASK)
+    {
+    case EF_SH1:
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh);
+      break;
+    case EF_SH2:
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh2);
+      break;
+    case EF_SH_DSP:
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh_dsp);
+      break;
+    case EF_SH3:
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3);
+      break;
+    case EF_SH3_DSP:
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3_dsp);
+      break;
+    case EF_SH3E:
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh3e);
+      break;
+    case EF_SH_UNKNOWN:
+    case EF_SH4:
+      bfd_default_set_arch_mach (abfd, bfd_arch_sh, bfd_mach_sh4);
+      break;
+    default:
+      return false;
+    }
+  return true;
+}
+
+/* Function to keep SH specific file flags. */
+static boolean
+sh_elf_set_private_flags (abfd, flags)
+     bfd *    abfd;
+     flagword flags;
+{
+  BFD_ASSERT (! elf_flags_init (abfd)
+             || elf_elfheader (abfd)->e_flags == flags);
+
+  elf_elfheader (abfd)->e_flags = flags;
+  elf_flags_init (abfd) = true;
+  return sh_elf_set_mach_from_flags (abfd);
+}
+
+/* Copy backend specific data from one object module to another */
+static boolean
+sh_elf_copy_private_data (ibfd, obfd)
+     bfd * ibfd;
+     bfd * obfd;
+{
+  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return true;
+
+  return sh_elf_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
+}
+
+/* This routine checks for linking big and little endian objects
+   together, and for linking sh-dsp with sh3e / sh4 objects.  */
+
+static boolean
+sh_elf_merge_private_data (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  flagword old_flags, new_flags;
+
+  if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
+    return false;
+
+  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return true;
+
+  if (! elf_flags_init (obfd))
+    {
+      elf_flags_init (obfd) = true;
+      elf_elfheader (obfd)->e_flags = 0;
+    }
+  old_flags = elf_elfheader (obfd)->e_flags;
+  new_flags = elf_elfheader (ibfd)->e_flags;
+  if ((EF_SH_HAS_DSP (old_flags) && EF_SH_HAS_FP (new_flags))
+      || (EF_SH_HAS_DSP (new_flags) && EF_SH_HAS_FP (old_flags)))
+    {
+      (*_bfd_error_handler)
+       ("%s: uses %s instructions while previous modules use %s instructions",
+        bfd_get_filename (ibfd),
+        EF_SH_HAS_DSP (new_flags) ? "dsp" : "floating point",
+        EF_SH_HAS_DSP (new_flags) ? "floating point" : "dsp");
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+  elf_elfheader (obfd)->e_flags = EF_SH_MERGE_MACH (old_flags, new_flags);
+
+  return sh_elf_set_mach_from_flags (obfd);
+}
+
 #define TARGET_BIG_SYM         bfd_elf32_sh_vec
 #define TARGET_BIG_NAME                "elf32-sh"
 #define TARGET_LITTLE_SYM      bfd_elf32_shl_vec
@@ -2050,6 +2214,13 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
 #define elf_backend_relocate_section   sh_elf_relocate_section
 #define bfd_elf32_bfd_get_relocated_section_contents \
                                        sh_elf_get_relocated_section_contents
+#define elf_backend_object_p           sh_elf_set_mach_from_flags
+#define bfd_elf32_bfd_set_private_bfd_flags \
+                                       sh_elf_set_private_flags
+#define bfd_elf32_bfd_copy_private_bfd_data \
+                                       sh_elf_copy_private_data
+#define bfd_elf32_bfd_merge_private_bfd_data \
+                                       sh_elf_merge_private_data
 
 #define elf_backend_gc_mark_hook        sh_elf_gc_mark_hook
 #define elf_backend_gc_sweep_hook       sh_elf_gc_sweep_hook
This page took 0.028114 seconds and 4 git commands to generate.