]> oss.titaniummirror.com Git - msp430-binutils.git/blobdiff - bfd/elf-m10300.c
Imported binutils-2.20
[msp430-binutils.git] / bfd / elf-m10300.c
index 2b309e5af98aba66f13d79946238bc3fb53f0c66..794d329fe80be3f7f24120dddece95d80cc9c3ae 100644 (file)
@@ -1,6 +1,6 @@
 /* Matsushita 10300 specific support for 32-bit ELF
    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007 Free Software Foundation, Inc.
+   2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/mn10300.h"
-
-static bfd_reloc_status_type mn10300_elf_final_link_relocate
-  PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *,
-          bfd_vma, bfd_vma, bfd_vma,
-          struct elf_link_hash_entry *, unsigned long, struct bfd_link_info *,
-          asection *, int));
-static bfd_boolean mn10300_elf_relocate_section
-  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
-          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-static bfd_boolean mn10300_elf_relax_section
-  PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
-static bfd_byte * mn10300_elf_get_relocated_section_contents
-  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
-          bfd_byte *, bfd_boolean, asymbol **));
-static unsigned long elf_mn10300_mach
-  PARAMS ((flagword));
-void _bfd_mn10300_elf_final_write_processing
-  PARAMS ((bfd *, bfd_boolean));
-bfd_boolean _bfd_mn10300_elf_object_p
-  PARAMS ((bfd *));
-bfd_boolean _bfd_mn10300_elf_merge_private_bfd_data
-  PARAMS ((bfd *,bfd *));
+#include "libiberty.h"
 
 /* The mn10300 linker needs to keep track of the number of relocs that
    it decides to copy in check_relocs for each symbol.  This is so
@@ -53,7 +32,8 @@ bfd_boolean _bfd_mn10300_elf_merge_private_bfd_data
    linking with -Bsymbolic.  We store the information in a field
    extending the regular ELF linker hash table.  */
 
-struct elf32_mn10300_link_hash_entry {
+struct elf32_mn10300_link_hash_entry
+{
   /* The basic elf link hash table entry.  */
   struct elf_link_hash_entry root;
 
@@ -94,7 +74,8 @@ struct elf32_mn10300_link_hash_entry {
 /* We derive a hash table from the main elf linker hash table so
    we can store state variables and a secondary hash table without
    resorting to global variables.  */
-struct elf32_mn10300_link_hash_table {
+struct elf32_mn10300_link_hash_table
+{
   /* The main hash table.  */
   struct elf_link_hash_table root;
 
@@ -108,6 +89,10 @@ struct elf32_mn10300_link_hash_table {
   char flags;
 };
 
+#ifndef streq
+#define streq(a, b) (strcmp ((a),(b)) == 0)
+#endif
+
 /* For MN10300 linker hash table.  */
 
 /* Get the MN10300 ELF linker hash table from a link_info structure.  */
@@ -118,48 +103,11 @@ struct elf32_mn10300_link_hash_table {
 #define elf32_mn10300_link_hash_traverse(table, func, info)            \
   (elf_link_hash_traverse                                              \
    (&(table)->root,                                                    \
-    (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+    (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func),   \
     (info)))
 
-static struct bfd_hash_entry *elf32_mn10300_link_hash_newfunc
-  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static struct bfd_link_hash_table *elf32_mn10300_link_hash_table_create
-  PARAMS ((bfd *));
-static void elf32_mn10300_link_hash_table_free
-  PARAMS ((struct bfd_link_hash_table *));
-
-static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
-  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
-static void mn10300_info_to_howto
-  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-static bfd_boolean mn10300_elf_check_relocs
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-static bfd_boolean mn10300_elf_relax_delete_bytes
-  PARAMS ((bfd *, asection *, bfd_vma, int));
-static bfd_boolean mn10300_elf_symbol_address_p
-  PARAMS ((bfd *, asection *, Elf_Internal_Sym *, bfd_vma));
-static bfd_boolean elf32_mn10300_finish_hash_table_entry
-  PARAMS ((struct bfd_hash_entry *, PTR));
-static void compute_function_info
-  PARAMS ((bfd *, struct elf32_mn10300_link_hash_entry *,
-          bfd_vma, unsigned char *));
-
-static bfd_boolean _bfd_mn10300_elf_create_got_section
-  PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean _bfd_mn10300_elf_create_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean _bfd_mn10300_elf_adjust_dynamic_symbol
-  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static bfd_boolean _bfd_mn10300_elf_size_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean _bfd_mn10300_elf_finish_dynamic_symbol
-  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
-          Elf_Internal_Sym *));
-static bfd_boolean _bfd_mn10300_elf_finish_dynamic_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-
-static reloc_howto_type elf_mn10300_howto_table[] = {
+static reloc_howto_type elf_mn10300_howto_table[] =
+{
   /* Dummy relocation.  Does nothing.  */
   HOWTO (R_MN10300_NONE,
         0,
@@ -259,7 +207,7 @@ static reloc_howto_type elf_mn10300_howto_table[] = {
         0xff,
         TRUE),
 
-  /* GNU extension to record C++ vtable hierarchy */
+  /* GNU extension to record C++ vtable hierarchy */
   HOWTO (R_MN10300_GNU_VTINHERIT, /* type */
         0,                     /* rightshift */
         0,                     /* size (0 = byte, 1 = short, 2 = long) */
@@ -499,14 +447,53 @@ static reloc_howto_type elf_mn10300_howto_table[] = {
         0xffffffff,            /* dst_mask */
         FALSE),                /* pcrel_offset */
 
+  EMPTY_HOWTO (24),
+  EMPTY_HOWTO (25),
+  EMPTY_HOWTO (26),
+  EMPTY_HOWTO (27),
+  EMPTY_HOWTO (28),
+  EMPTY_HOWTO (29),
+  EMPTY_HOWTO (30),
+  EMPTY_HOWTO (31),
+  EMPTY_HOWTO (32),
+  
+  HOWTO (R_MN10300_SYM_DIFF,   /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        NULL,                  /* special handler.  */
+        "R_MN10300_SYM_DIFF",  /* name */
+        FALSE,                 /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  HOWTO (R_MN10300_ALIGN,      /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        NULL,                  /* special handler.  */
+        "R_MN10300_ALIGN",     /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        FALSE)                 /* pcrel_offset */
 };
 
-struct mn10300_reloc_map {
+struct mn10300_reloc_map
+{
   bfd_reloc_code_real_type bfd_reloc_val;
   unsigned char elf_reloc_val;
 };
 
-static const struct mn10300_reloc_map mn10300_reloc_map[] = {
+static const struct mn10300_reloc_map mn10300_reloc_map[] =
+{
   { BFD_RELOC_NONE, R_MN10300_NONE, },
   { BFD_RELOC_32, R_MN10300_32, },
   { BFD_RELOC_16, R_MN10300_16, },
@@ -531,14 +518,15 @@ static const struct mn10300_reloc_map mn10300_reloc_map[] = {
   { BFD_RELOC_MN10300_GLOB_DAT, R_MN10300_GLOB_DAT },
   { BFD_RELOC_MN10300_JMP_SLOT, R_MN10300_JMP_SLOT },
   { BFD_RELOC_MN10300_RELATIVE, R_MN10300_RELATIVE },
+  { BFD_RELOC_MN10300_SYM_DIFF, R_MN10300_SYM_DIFF },
+  { BFD_RELOC_MN10300_ALIGN, R_MN10300_ALIGN }
 };
 
 /* Create the GOT section.  */
 
 static bfd_boolean
-_bfd_mn10300_elf_create_got_section (abfd, info)
-     bfd * abfd;
-     struct bfd_link_info * info;
+_bfd_mn10300_elf_create_got_section (bfd * abfd,
+                                    struct bfd_link_info * info)
 {
   flagword   flags;
   flagword   pltflags;
@@ -621,19 +609,14 @@ _bfd_mn10300_elf_create_got_section (abfd, info)
 }
 
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_type_lookup (abfd, code)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     bfd_reloc_code_real_type code;
+bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                bfd_reloc_code_real_type code)
 {
   unsigned int i;
 
-  for (i = 0;
-       i < sizeof (mn10300_reloc_map) / sizeof (struct mn10300_reloc_map);
-       i++)
-    {
-      if (mn10300_reloc_map[i].bfd_reloc_val == code)
-       return &elf_mn10300_howto_table[mn10300_reloc_map[i].elf_reloc_val];
-    }
+  for (i = ARRAY_SIZE (mn10300_reloc_map); i--;)
+    if (mn10300_reloc_map[i].bfd_reloc_val == code)
+      return &elf_mn10300_howto_table[mn10300_reloc_map[i].elf_reloc_val];
 
   return NULL;
 }
@@ -644,13 +627,10 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 {
   unsigned int i;
 
-  for (i = 0;
-       i < (sizeof (elf_mn10300_howto_table)
-           / sizeof (elf_mn10300_howto_table[0]));
-       i++)
+  for (i = ARRAY_SIZE (elf_mn10300_howto_table); i--;)
     if (elf_mn10300_howto_table[i].name != NULL
        && strcasecmp (elf_mn10300_howto_table[i].name, r_name) == 0)
-      return &elf_mn10300_howto_table[i];
+      return elf_mn10300_howto_table + i;
 
   return NULL;
 }
@@ -658,16 +638,15 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 /* Set the howto pointer for an MN10300 ELF reloc.  */
 
 static void
-mn10300_info_to_howto (abfd, cache_ptr, dst)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     arelent *cache_ptr;
-     Elf_Internal_Rela *dst;
+mn10300_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+                      arelent *cache_ptr,
+                      Elf_Internal_Rela *dst)
 {
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
   BFD_ASSERT (r_type < (unsigned int) R_MN10300_MAX);
-  cache_ptr->howto = &elf_mn10300_howto_table[r_type];
+  cache_ptr->howto = elf_mn10300_howto_table + r_type;
 }
 
 /* Look through the relocs for a section during the first phase.
@@ -675,14 +654,15 @@ mn10300_info_to_howto (abfd, cache_ptr, dst)
    virtual table relocs for gc.  */
 
 static bfd_boolean
-mn10300_elf_check_relocs (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+mn10300_elf_check_relocs (bfd *abfd,
+                         struct bfd_link_info *info,
+                         asection *sec,
+                         const Elf_Internal_Rela *relocs)
 {
+  bfd_boolean sym_diff_reloc_seen;
   Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+  Elf_Internal_Sym * isymbuf = NULL;
+  struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   bfd *      dynobj;
@@ -690,6 +670,7 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
   asection * sgot;
   asection * srelgot;
   asection * sreloc;
+  bfd_boolean result = FALSE;
 
   sgot    = NULL;
   srelgot = NULL;
@@ -699,18 +680,19 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
     return TRUE;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   sym_hashes = elf_sym_hashes (abfd);
-  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
-  if (!elf_bad_symtab (abfd))
-    sym_hashes_end -= symtab_hdr->sh_info;
 
   dynobj = elf_hash_table (info)->dynobj;
   local_got_offsets = elf_local_got_offsets (abfd);
   rel_end = relocs + sec->reloc_count;
+  sym_diff_reloc_seen = FALSE;
+
   for (rel = relocs; rel < rel_end; rel++)
     {
       struct elf_link_hash_entry *h;
       unsigned long r_symndx;
+      unsigned int r_type;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       if (r_symndx < symtab_hdr->sh_info)
@@ -723,10 +705,12 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
        }
 
+      r_type = ELF32_R_TYPE (rel->r_info);
+
       /* Some relocs require a global offset table.  */
       if (dynobj == NULL)
        {
-         switch (ELF32_R_TYPE (rel->r_info))
+         switch (r_type)
            {
            case R_MN10300_GOT32:
            case R_MN10300_GOT24:
@@ -738,7 +722,7 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
            case R_MN10300_GOTPC16:
              elf_hash_table (info)->dynobj = dynobj = abfd;
              if (! _bfd_mn10300_elf_create_got_section (dynobj, info))
-               return FALSE;
+               goto fail;
              break;
 
            default:
@@ -746,21 +730,24 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
            }
        }
 
-      switch (ELF32_R_TYPE (rel->r_info))
+      switch (r_type)
        {
        /* This relocation describes the C++ object vtable hierarchy.
           Reconstruct it for later use during GC.  */
        case R_MN10300_GNU_VTINHERIT:
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-           return FALSE;
+           goto fail;
          break;
 
        /* This relocation describes which C++ vtable entries are actually
           used.  Record for later use during GC.  */
        case R_MN10300_GNU_VTENTRY:
-         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-           return FALSE;
+         BFD_ASSERT (h != NULL);
+         if (h != NULL
+             && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+           goto fail;
          break;
+
        case R_MN10300_GOT32:
        case R_MN10300_GOT24:
        case R_MN10300_GOT16:
@@ -788,7 +775,7 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
                                                          | SEC_READONLY));
                  if (srelgot == NULL
                      || ! bfd_set_section_alignment (dynobj, srelgot, 2))
-                   return FALSE;
+                   goto fail;
                }
            }
 
@@ -804,7 +791,7 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
              if (h->dynindx == -1)
                {
                  if (! bfd_elf_link_record_dynamic_symbol (info, h))
-                   return FALSE;
+                   goto fail;
                }
 
              srelgot->size += sizeof (Elf32_External_Rela);
@@ -819,10 +806,11 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
                  unsigned int i;
 
                  size = symtab_hdr->sh_info * sizeof (bfd_vma);
-                 local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
+                 local_got_offsets = bfd_alloc (abfd, size);
 
                  if (local_got_offsets == NULL)
-                   return FALSE;
+                   goto fail;
+
                  elf_local_got_offsets (abfd) = local_got_offsets;
 
                  for (i = 0; i < symtab_hdr->sh_info; i++)
@@ -843,7 +831,6 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
            }
 
          sgot->size += 4;
-
          break;
 
        case R_MN10300_PLT32:
@@ -865,7 +852,6 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
            break;
 
          h->needs_plt = 1;
-
          break;
 
        case R_MN10300_24:
@@ -878,59 +864,82 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
            h->non_got_ref = 1;
          break;
 
+       case R_MN10300_SYM_DIFF:
+         sym_diff_reloc_seen = TRUE;
+         break;
+
        case R_MN10300_32:
          if (h != NULL)
            h->non_got_ref = 1;
 
-         /* If we are creating a shared library, then we need to copy
-            the reloc into the shared library.  */
+         /* If we are creating a shared library, then we
+            need to copy the reloc into the shared library.  */
          if (info->shared
-             && (sec->flags & SEC_ALLOC) != 0)
+             && (sec->flags & SEC_ALLOC) != 0
+             /* Do not generate a dynamic reloc for a
+                reloc associated with a SYM_DIFF operation.  */
+             && ! sym_diff_reloc_seen)
            {
-             /* When creating a shared object, we must copy these
-                reloc types into the output file.  We create a reloc
-                section in dynobj and make room for this reloc.  */
-             if (sreloc == NULL)
-               {
-                 const char * name;
+             asection * sym_section = NULL;
 
-                 name = (bfd_elf_string_from_elf_section
-                         (abfd,
-                          elf_elfheader (abfd)->e_shstrndx,
-                          elf_section_data (sec)->rel_hdr.sh_name));
-                 if (name == NULL)
-                   return FALSE;
+             /* Find the section containing the
+                symbol involved in the relocation.  */
+             if (h == NULL)
+               {
+                 Elf_Internal_Sym * isym;
 
-                 BFD_ASSERT (CONST_STRNEQ (name, ".rela")
-                             && strcmp (bfd_get_section_name (abfd, sec),
-                                        name + 5) == 0);
+                 if (isymbuf == NULL)
+                   isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+                                                   symtab_hdr->sh_info, 0,
+                                                   NULL, NULL, NULL);
+                 if (isymbuf)
+                   {
+                     isym = isymbuf + r_symndx;
+                     /* All we care about is whether this local symbol is absolute.  */
+                     if (isym->st_shndx == SHN_ABS)
+                       sym_section = bfd_abs_section_ptr;
+                   }
+               }
+             else
+               {
+                 if (h->root.type == bfd_link_hash_defined
+                     || h->root.type == bfd_link_hash_defweak)
+                   sym_section = h->root.u.def.section;
+               }
 
-                 sreloc = bfd_get_section_by_name (dynobj, name);
+             /* If the symbol is absolute then the relocation can
+                be resolved during linking and there is no need for
+                a dynamic reloc.  */
+             if (sym_section != bfd_abs_section_ptr)
+               {
+                 /* When creating a shared object, we must copy these
+                    reloc types into the output file.  We create a reloc
+                    section in dynobj and make room for this reloc.  */
                  if (sreloc == NULL)
                    {
-                     flagword flags;
-
-                     flags = (SEC_HAS_CONTENTS | SEC_READONLY
-                              | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-                     if ((sec->flags & SEC_ALLOC) != 0)
-                       flags |= SEC_ALLOC | SEC_LOAD;
-                     sreloc = bfd_make_section_with_flags (dynobj,
-                                                           name,
-                                                           flags);
-                     if (sreloc == NULL
-                         || ! bfd_set_section_alignment (dynobj, sreloc, 2))
-                       return FALSE;
+                     sreloc = _bfd_elf_make_dynamic_reloc_section
+                       (sec, dynobj, 2, abfd, /*rela?*/ TRUE);
+                     if (sreloc == NULL)
+                       goto fail;
                    }
-               }
 
-             sreloc->size += sizeof (Elf32_External_Rela);
+                 sreloc->size += sizeof (Elf32_External_Rela);
+               }
            }
 
          break;
        }
+
+      if (ELF32_R_TYPE (rel->r_info) != R_MN10300_SYM_DIFF)
+       sym_diff_reloc_seen = FALSE;
     }
 
-  return TRUE;
+  result = TRUE;
+ fail:
+  if (isymbuf != NULL)
+    free (isymbuf);
+
+  return result;
 }
 
 /* Return the section that should be marked against GC for a given
@@ -955,26 +964,27 @@ mn10300_elf_gc_mark_hook (asection *sec,
 }
 
 /* Perform a relocation as part of a final link.  */
+
 static bfd_reloc_status_type
-mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
-                                input_section, contents, offset, value,
-                                addend, h, symndx, info, sym_sec, is_local)
-     reloc_howto_type *howto;
-     bfd *input_bfd;
-     bfd *output_bfd ATTRIBUTE_UNUSED;
-     asection *input_section;
-     bfd_byte *contents;
-     bfd_vma offset;
-     bfd_vma value;
-     bfd_vma addend;
-     struct elf_link_hash_entry * h;
-     unsigned long symndx;
-     struct bfd_link_info *info;
-     asection *sym_sec ATTRIBUTE_UNUSED;
-     int is_local ATTRIBUTE_UNUSED;
+mn10300_elf_final_link_relocate (reloc_howto_type *howto,
+                                bfd *input_bfd,
+                                bfd *output_bfd ATTRIBUTE_UNUSED,
+                                asection *input_section,
+                                bfd_byte *contents,
+                                bfd_vma offset,
+                                bfd_vma value,
+                                bfd_vma addend,
+                                struct elf_link_hash_entry * h,
+                                unsigned long symndx,
+                                struct bfd_link_info *info,
+                                asection *sym_sec ATTRIBUTE_UNUSED,
+                                int is_local ATTRIBUTE_UNUSED)
 {
+  static asection *  sym_diff_section;
+  static bfd_vma     sym_diff_value;
+  bfd_boolean is_sym_diff_reloc;
   unsigned long r_type = howto->type;
-  bfd_byte *hit_data = contents + offset;
+  bfd_byte * hit_data = contents + offset;
   bfd *      dynobj;
   bfd_vma *  local_got_offsets;
   asection * sgot;
@@ -1006,13 +1016,66 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
        return bfd_reloc_dangerous;
     }
 
+  is_sym_diff_reloc = FALSE;
+  if (sym_diff_section != NULL)
+    {
+      BFD_ASSERT (sym_diff_section == input_section);
+
+      switch (r_type)
+       {
+       case R_MN10300_32:
+       case R_MN10300_24:
+       case R_MN10300_16:
+       case R_MN10300_8:
+         value -= sym_diff_value;
+         /* If we are computing a 32-bit value for the location lists
+            and the result is 0 then we add one to the value.  A zero
+            value can result because of linker relaxation deleteing
+            prologue instructions and using a value of 1 (for the begin
+            and end offsets in the location list entry) results in a
+            nul entry which does not prevent the following entries from
+            being parsed.  */
+         if (r_type == R_MN10300_32
+             && value == 0
+             && strcmp (input_section->name, ".debug_loc") == 0)
+           value = 1;
+         sym_diff_section = NULL;
+         is_sym_diff_reloc = TRUE;
+         break;
+
+       default:
+         sym_diff_section = NULL;
+         break;
+       }
+    }
+
   switch (r_type)
     {
+    case R_MN10300_SYM_DIFF:
+      BFD_ASSERT (addend == 0);
+      /* Cache the input section and value.
+        The offset is unreliable, since relaxation may
+        have reduced the following reloc's offset.  */
+      sym_diff_section = input_section;
+      sym_diff_value = value;
+      return bfd_reloc_ok;
+
+    case R_MN10300_ALIGN:
     case R_MN10300_NONE:
       return bfd_reloc_ok;
 
     case R_MN10300_32:
       if (info->shared
+         /* Do not generate relocs when an R_MN10300_32 has been used
+            with an R_MN10300_SYM_DIFF to compute a difference of two
+            symbols.  */
+         && is_sym_diff_reloc == FALSE
+         /* Also, do not generate a reloc when the symbol associated
+            with the R_MN10300_32 reloc is absolute - there is no
+            need for a run time computation in this case.  */
+         && sym_sec != bfd_abs_section_ptr
+         /* If the section is not going to be allocated at load time
+            then there is no need to generate relocs for it.  */
          && (input_section->flags & SEC_ALLOC) != 0)
        {
          Elf_Internal_Rela outrel;
@@ -1023,22 +1086,10 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
             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)
+             sreloc = _bfd_elf_get_dynamic_reloc_section
+               (input_bfd, input_section, /*rela?*/ TRUE);
+             if (sreloc == NULL)
                return FALSE;
-
-             BFD_ASSERT (CONST_STRNEQ (name, ".rela")
-                         && strcmp (bfd_get_section_name (input_bfd,
-                                                          input_section),
-                                    name + 5) == 0);
-
-             sreloc = bfd_get_section_by_name (dynobj, name);
-             BFD_ASSERT (sreloc != NULL);
            }
 
          skip = FALSE;
@@ -1127,7 +1178,7 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
       value -= offset;
       value += addend;
 
-      if ((long) value > 0xff || (long) value < -0x100)
+      if ((long) value > 0x7f || (long) value < -0x80)
        return bfd_reloc_overflow;
 
       bfd_put_8 (input_bfd, value, hit_data);
@@ -1139,7 +1190,7 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
       value -= offset;
       value += addend;
 
-      if ((long) value > 0xffff || (long) value < -0x10000)
+      if ((long) value > 0x7fff || (long) value < -0x8000)
        return bfd_reloc_overflow;
 
       bfd_put_16 (input_bfd, value, hit_data);
@@ -1160,7 +1211,6 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
 
     case R_MN10300_GOTPC32:
       /* Use global offset table as symbol value.  */
-
       value = bfd_get_section_by_name (dynobj,
                                       ".got")->output_section->vma;
       value -= (input_section->output_section->vma
@@ -1173,7 +1223,6 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
 
     case R_MN10300_GOTPC16:
       /* Use global offset table as symbol value.  */
-
       value = bfd_get_section_by_name (dynobj,
                                       ".got")->output_section->vma;
       value -= (input_section->output_section->vma
@@ -1181,7 +1230,7 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
       value -= offset;
       value += addend;
 
-      if ((long) value > 0xffff || (long) value < -0x10000)
+      if ((long) value > 0x7fff || (long) value < -0x8000)
        return bfd_reloc_overflow;
 
       bfd_put_16 (input_bfd, value, hit_data);
@@ -1213,7 +1262,7 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
                                        ".got")->output_section->vma;
       value += addend;
 
-      if ((long) value > 0xffff || (long) value < -0x10000)
+      if ((long) value > 0x7fff || (long) value < -0x8000)
        return bfd_reloc_overflow;
 
       bfd_put_16 (input_bfd, value, hit_data);
@@ -1262,7 +1311,7 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
       value -= offset;
       value += addend;
 
-      if ((long) value > 0xffff || (long) value < -0x10000)
+      if ((long) value > 0x7fff || (long) value < -0x8000)
        return bfd_reloc_overflow;
 
       bfd_put_16 (input_bfd, value, hit_data);
@@ -1350,7 +1399,7 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
        }
       else if (r_type == R_MN10300_GOT16)
        {
-         if ((long) value > 0xffff || (long) value < -0x10000)
+         if ((long) value > 0x7fff || (long) value < -0x8000)
            return bfd_reloc_overflow;
 
          bfd_put_16 (input_bfd, value, hit_data);
@@ -1364,17 +1413,16 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
 }
 \f
 /* Relocate an MN10300 ELF section.  */
+
 static bfd_boolean
-mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
-                             contents, relocs, local_syms, local_sections)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     asection *input_section;
-     bfd_byte *contents;
-     Elf_Internal_Rela *relocs;
-     Elf_Internal_Sym *local_syms;
-     asection **local_sections;
+mn10300_elf_relocate_section (bfd *output_bfd,
+                             struct bfd_link_info *info,
+                             bfd *input_bfd,
+                             asection *input_section,
+                             bfd_byte *contents,
+                             Elf_Internal_Rela *relocs,
+                             Elf_Internal_Sym *local_syms,
+                             asection **local_sections)
 {
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -1442,6 +1490,10 @@ mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      && elf_hash_table (info)->dynamic_sections_created
                      && !SYMBOL_REFERENCES_LOCAL (info, hh))
                  || (r_type == R_MN10300_32
+                     /* _32 relocs in executables force _COPY relocs,
+                        such that the address of the symbol ends up
+                        being local.  */
+                     && !info->executable
                      && !SYMBOL_REFERENCES_LOCAL (info, hh)
                      && ((input_section->flags & SEC_ALLOC) != 0
                          /* DWARF will emit R_MN10300_32 relocations
@@ -1483,14 +1535,14 @@ mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                           input_section,
                                           contents, rel->r_offset,
                                           relocation, rel->r_addend,
-                                          (struct elf_link_hash_entry *)h,
+                                          (struct elf_link_hash_entry *) h,
                                           r_symndx,
                                           info, sec, h == NULL);
 
       if (r != bfd_reloc_ok)
        {
          const char *name;
-         const char *msg = (const char *) 0;
+         const char *msg = NULL;
 
          if (h != NULL)
            name = h->root.root.root.string;
@@ -1538,7 +1590,7 @@ mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
            default:
              msg = _("internal error: unknown error");
-             /* fall through */
+             /* Fall through.  */
 
            common_error:
              if (!((*info->callbacks->warning)
@@ -1554,13 +1606,13 @@ mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 }
 
 /* Finish initializing one hash table entry.  */
+
 static bfd_boolean
-elf32_mn10300_finish_hash_table_entry (gen_entry, in_args)
-     struct bfd_hash_entry *gen_entry;
-     PTR in_args;
+elf32_mn10300_finish_hash_table_entry (struct bfd_hash_entry *gen_entry,
+                                      void * in_args)
 {
   struct elf32_mn10300_link_hash_entry *entry;
-  struct bfd_link_info *link_info = (struct bfd_link_info *)in_args;
+  struct bfd_link_info *link_info = (struct bfd_link_info *) in_args;
   unsigned int byte_count = 0;
 
   entry = (struct elf32_mn10300_link_hash_entry *) gen_entry;
@@ -1618,20 +1670,22 @@ elf32_mn10300_finish_hash_table_entry (gen_entry, in_args)
 }
 
 /* Used to count hash table entries.  */
+
 static bfd_boolean
 elf32_mn10300_count_hash_table_entries (struct bfd_hash_entry *gen_entry ATTRIBUTE_UNUSED,
-                                       PTR in_args)
+                                       void * in_args)
 {
-  int *count = (int *)in_args;
+  int *count = (int *) in_args;
 
   (*count) ++;
   return TRUE;
 }
 
 /* Used to enumerate hash table entries into a linear array.  */
+
 static bfd_boolean
 elf32_mn10300_list_hash_table_entries (struct bfd_hash_entry *gen_entry,
-                                      PTR in_args)
+                                      void * in_args)
 {
   struct bfd_hash_entry ***ptr = (struct bfd_hash_entry ***) in_args;
 
@@ -1641,17 +1695,329 @@ elf32_mn10300_list_hash_table_entries (struct bfd_hash_entry *gen_entry,
 }
 
 /* Used to sort the array created by the above.  */
+
 static int
 sort_by_value (const void *va, const void *vb)
 {
   struct elf32_mn10300_link_hash_entry *a
-    = *(struct elf32_mn10300_link_hash_entry **)va;
+    = *(struct elf32_mn10300_link_hash_entry **) va;
   struct elf32_mn10300_link_hash_entry *b
-    = *(struct elf32_mn10300_link_hash_entry **)vb;
+    = *(struct elf32_mn10300_link_hash_entry **) vb;
+
+  return a->value - b->value;
+}
+
+/* Compute the stack size and movm arguments for the function
+   referred to by HASH at address ADDR in section with
+   contents CONTENTS, store the information in the hash table.  */
+
+static void
+compute_function_info (bfd *abfd,
+                      struct elf32_mn10300_link_hash_entry *hash,
+                      bfd_vma addr,
+                      unsigned char *contents)
+{
+  unsigned char byte1, byte2;
+  /* We only care about a very small subset of the possible prologue
+     sequences here.  Basically we look for:
+
+     movm [d2,d3,a2,a3],sp (optional)
+     add <size>,sp (optional, and only for sizes which fit in an unsigned
+                   8 bit number)
+
+     If we find anything else, we quit.  */
+
+  /* Look for movm [regs],sp.  */
+  byte1 = bfd_get_8 (abfd, contents + addr);
+  byte2 = bfd_get_8 (abfd, contents + addr + 1);
+
+  if (byte1 == 0xcf)
+    {
+      hash->movm_args = byte2;
+      addr += 2;
+      byte1 = bfd_get_8 (abfd, contents + addr);
+      byte2 = bfd_get_8 (abfd, contents + addr + 1);
+    }
+
+  /* Now figure out how much stack space will be allocated by the movm
+     instruction.  We need this kept separate from the function's normal
+     stack space.  */
+  if (hash->movm_args)
+    {
+      /* Space for d2.  */
+      if (hash->movm_args & 0x80)
+       hash->movm_stack_size += 4;
+
+      /* Space for d3.  */
+      if (hash->movm_args & 0x40)
+       hash->movm_stack_size += 4;
+
+      /* Space for a2.  */
+      if (hash->movm_args & 0x20)
+       hash->movm_stack_size += 4;
+
+      /* Space for a3.  */
+      if (hash->movm_args & 0x10)
+       hash->movm_stack_size += 4;
+
+      /* "other" space.  d0, d1, a0, a1, mdr, lir, lar, 4 byte pad.  */
+      if (hash->movm_args & 0x08)
+       hash->movm_stack_size += 8 * 4;
+
+      if (bfd_get_mach (abfd) == bfd_mach_am33
+         || bfd_get_mach (abfd) == bfd_mach_am33_2)
+       {
+         /* "exother" space.  e0, e1, mdrq, mcrh, mcrl, mcvf */
+         if (hash->movm_args & 0x1)
+           hash->movm_stack_size += 6 * 4;
+
+         /* exreg1 space.  e4, e5, e6, e7 */
+         if (hash->movm_args & 0x2)
+           hash->movm_stack_size += 4 * 4;
+
+         /* exreg0 space.  e2, e3  */
+         if (hash->movm_args & 0x4)
+           hash->movm_stack_size += 2 * 4;
+       }
+    }
+
+  /* Now look for the two stack adjustment variants.  */
+  if (byte1 == 0xf8 && byte2 == 0xfe)
+    {
+      int temp = bfd_get_8 (abfd, contents + addr + 2);
+      temp = ((temp & 0xff) ^ (~0x7f)) + 0x80;
+
+      hash->stack_size = -temp;
+    }
+  else if (byte1 == 0xfa && byte2 == 0xfe)
+    {
+      int temp = bfd_get_16 (abfd, contents + addr + 2);
+      temp = ((temp & 0xffff) ^ (~0x7fff)) + 0x8000;
+      temp = -temp;
+
+      if (temp < 255)
+       hash->stack_size = temp;
+    }
+
+  /* If the total stack to be allocated by the call instruction is more
+     than 255 bytes, then we can't remove the stack adjustment by using
+     "call" (we might still be able to remove the "movm" instruction.  */
+  if (hash->stack_size + hash->movm_stack_size > 255)
+    hash->stack_size = 0;
+}
+
+/* Delete some bytes from a section while relaxing.  */
+
+static bfd_boolean
+mn10300_elf_relax_delete_bytes (bfd *abfd,
+                               asection *sec,
+                               bfd_vma addr,
+                               int count)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  unsigned int sec_shndx;
+  bfd_byte *contents;
+  Elf_Internal_Rela *irel, *irelend;
+  Elf_Internal_Rela *irelalign;
+  bfd_vma toaddr;
+  Elf_Internal_Sym *isym, *isymend;
+  struct elf_link_hash_entry **sym_hashes;
+  struct elf_link_hash_entry **end_hashes;
+  unsigned int symcount;
+
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+
+  contents = elf_section_data (sec)->this_hdr.contents;
+
+  irelalign = NULL;
+  toaddr = sec->size;
+
+  irel = elf_section_data (sec)->relocs;
+  irelend = irel + sec->reloc_count;
+
+  if (sec->reloc_count > 0)
+    {
+      /* If there is an align reloc at the end of the section ignore it.
+        GAS creates these relocs for reasons of its own, and they just
+        serve to keep the section artifically inflated.  */
+      if (ELF32_R_TYPE ((irelend - 1)->r_info) == (int) R_MN10300_ALIGN)
+       --irelend;
+      
+      /* The deletion must stop at the next ALIGN reloc for an aligment
+        power larger than, or not a multiple of, the number of bytes we
+        are deleting.  */
+      for (; irel < irelend; irel++)
+       {
+         int alignment = 1 << irel->r_addend;
+
+         if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN
+             && irel->r_offset > addr
+             && irel->r_offset < toaddr
+             && (count < alignment
+                 || alignment % count != 0))
+           {
+             irelalign = irel;
+             toaddr = irel->r_offset;
+             break;
+           }
+       }
+    }
+
+  /* Actually delete the bytes.  */
+  memmove (contents + addr, contents + addr + count,
+          (size_t) (toaddr - addr - count));
+
+  /* Adjust the section's size if we are shrinking it, or else
+     pad the bytes between the end of the shrunken region and
+     the start of the next region with NOP codes.  */
+  if (irelalign == NULL)
+    {
+      sec->size -= count;
+      /* Include symbols at the end of the section, but
+        not at the end of a sub-region of the section.  */
+      toaddr ++;
+    }
+  else
+    {
+      int i;
+
+#define NOP_OPCODE 0xcb
+
+      for (i = 0; i < count; i ++)
+       bfd_put_8 (abfd, (bfd_vma) NOP_OPCODE, contents + toaddr - count + i);
+    }
+
+  /* Adjust all the relocs.  */
+  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
+    {
+      /* Get the new reloc address.  */
+      if ((irel->r_offset > addr
+          && irel->r_offset < toaddr)
+         || (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN
+             && irel->r_offset == toaddr))
+       irel->r_offset -= count;
+    }
+
+  /* Adjust the local symbols in the section, reducing their value
+     by the number of bytes deleted.  Note - symbols within the deleted
+     region are moved to the address of the start of the region, which
+     actually means that they will address the byte beyond the end of
+     the region once the deletion has been completed.  */
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
+    {
+      if (isym->st_shndx == sec_shndx
+         && isym->st_value > addr
+         && isym->st_value < toaddr)
+       {
+         if (isym->st_value < addr + count)
+           isym->st_value = addr;
+         else
+           isym->st_value -= count;
+       }
+      /* Adjust the function symbol's size as well.  */
+      else if (isym->st_shndx == sec_shndx
+              && ELF_ST_TYPE (isym->st_info) == STT_FUNC
+              && isym->st_value + isym->st_size > addr
+              && isym->st_value + isym->st_size < toaddr)
+       isym->st_size -= count;
+    }
+
+  /* Now adjust the global symbols defined in this section.  */
+  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+             - symtab_hdr->sh_info);
+  sym_hashes = elf_sym_hashes (abfd);
+  end_hashes = sym_hashes + symcount;
+  for (; sym_hashes < end_hashes; sym_hashes++)
+    {
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+
+      if ((sym_hash->root.type == bfd_link_hash_defined
+          || sym_hash->root.type == bfd_link_hash_defweak)
+         && sym_hash->root.u.def.section == sec
+         && sym_hash->root.u.def.value > addr
+         && sym_hash->root.u.def.value < toaddr)
+       {
+         if (sym_hash->root.u.def.value < addr + count)
+           sym_hash->root.u.def.value = addr;
+         else
+           sym_hash->root.u.def.value -= count;
+       }
+      /* Adjust the function symbol's size as well.  */
+      else if (sym_hash->root.type == bfd_link_hash_defined
+              && sym_hash->root.u.def.section == sec
+              && sym_hash->type == STT_FUNC
+              && sym_hash->root.u.def.value + sym_hash->size > addr
+              && sym_hash->root.u.def.value + sym_hash->size < toaddr)
+       sym_hash->size -= count;
+    }
+
+  /* See if we can move the ALIGN reloc forward.
+     We have adjusted r_offset for it already.  */
+  if (irelalign != NULL)
+    {
+      bfd_vma alignto, alignaddr;
+
+      if ((int) irelalign->r_addend > 0)
+       {
+         /* This is the old address.  */
+         alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_addend);
+         /* This is where the align points to now.  */
+         alignaddr = BFD_ALIGN (irelalign->r_offset,
+                                1 << irelalign->r_addend);
+         if (alignaddr < alignto)
+           /* Tail recursion.  */
+           return mn10300_elf_relax_delete_bytes (abfd, sec, alignaddr,
+                                                  (int) (alignto - alignaddr));
+       }
+    }
+
+  return TRUE;
+}
+
+/* Return TRUE if a symbol exists at the given address, else return
+   FALSE.  */
+
+static bfd_boolean
+mn10300_elf_symbol_address_p (bfd *abfd,
+                             asection *sec,
+                             Elf_Internal_Sym *isym,
+                             bfd_vma addr)
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  unsigned int sec_shndx;
+  Elf_Internal_Sym *isymend;
+  struct elf_link_hash_entry **sym_hashes;
+  struct elf_link_hash_entry **end_hashes;
+  unsigned int symcount;
+
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+
+  /* Examine all the symbols.  */
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
+    if (isym->st_shndx == sec_shndx
+       && isym->st_value == addr)
+      return TRUE;
+
+  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+             - symtab_hdr->sh_info);
+  sym_hashes = elf_sym_hashes (abfd);
+  end_hashes = sym_hashes + symcount;
+  for (; sym_hashes < end_hashes; sym_hashes++)
+    {
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
 
-  return a->value - b->value;
-}
+      if ((sym_hash->root.type == bfd_link_hash_defined
+          || sym_hash->root.type == bfd_link_hash_defweak)
+         && sym_hash->root.u.def.section == sec
+         && sym_hash->root.u.def.value == addr)
+       return TRUE;
+    }
 
+  return FALSE;
+}
 
 /* This function handles relaxing for the mn10300.
 
@@ -1693,11 +2059,10 @@ sort_by_value (const void *va, const void *vb)
        and somewhat more difficult to support.  */
 
 static bfd_boolean
-mn10300_elf_relax_section (abfd, sec, link_info, again)
-     bfd *abfd;
-     asection *sec;
-     struct bfd_link_info *link_info;
-     bfd_boolean *again;
+mn10300_elf_relax_section (bfd *abfd,
+                          asection *sec,
+                          struct bfd_link_info *link_info,
+                          bfd_boolean *again)
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs = NULL;
@@ -1706,6 +2071,11 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
   Elf_Internal_Sym *isymbuf = NULL;
   struct elf32_mn10300_link_hash_table *hash_table;
   asection *section = sec;
+  bfd_vma align_gap_adjustment;
+
+  if (link_info->relocatable)
+    (*link_info->callbacks->einfo)
+      (_("%P%F: --relax and -r may not be used together\n"));
 
   /* Assume nothing changes.  */
   *again = FALSE;
@@ -1771,12 +2141,10 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
              if ((section->flags & SEC_RELOC) != 0
                  && section->reloc_count != 0)
                {
-
                  /* Get a copy of the native relocations.  */
-                 internal_relocs = (_bfd_elf_link_read_relocs
-                                    (input_bfd, section, (PTR) NULL,
-                                     (Elf_Internal_Rela *) NULL,
-                                     link_info->keep_memory));
+                 internal_relocs = _bfd_elf_link_read_relocs (input_bfd, section,
+                                                              NULL, NULL,
+                                                              link_info->keep_memory);
                  if (internal_relocs == NULL)
                    goto error_return;
 
@@ -1835,7 +2203,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                             local symbol in the global hash table.  */
                          amt = strlen (sym_name) + 10;
                          new_name = bfd_malloc (amt);
-                         if (new_name == 0)
+                         if (new_name == NULL)
                            goto error_return;
 
                          sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
@@ -1944,7 +2312,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                             local symbol in the global hash table.  */
                          amt = strlen (sym_name) + 10;
                          new_name = bfd_malloc (amt);
-                         if (new_name == 0)
+                         if (new_name == NULL)
                            goto error_return;
 
                          sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
@@ -2034,26 +2402,28 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                                          elf32_mn10300_count_hash_table_entries,
                                          &static_count);
 
-       entries = (struct elf32_mn10300_link_hash_entry **)
-         bfd_malloc (static_count * sizeof (struct elf32_mn10300_link_hash_entry *));
+       entries = bfd_malloc (static_count * sizeof (* ptr));
 
        ptr = entries;
        elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
                                          elf32_mn10300_list_hash_table_entries,
-                                         &ptr);
+                                         & ptr);
 
-       qsort (entries, static_count, sizeof(entries[0]), sort_by_value);
+       qsort (entries, static_count, sizeof (entries[0]), sort_by_value);
 
-       for (i=0; i<static_count-1; i++)
+       for (i = 0; i < static_count - 1; i++)
          if (entries[i]->value && entries[i]->value == entries[i+1]->value)
            {
              int v = entries[i]->flags;
              int j;
-             for (j=i+1; j<static_count && entries[j]->value == entries[i]->value; j++)
+
+             for (j = i + 1; j < static_count && entries[j]->value == entries[i]->value; j++)
                v |= entries[j]->flags;
-             for (j=i; j<static_count && entries[j]->value == entries[i]->value; j++)
+
+             for (j = i; j < static_count && entries[j]->value == entries[i]->value; j++)
                entries[j]->flags = v;
-             i = j-1;
+
+             i = j - 1;
            }
       }
 
@@ -2099,10 +2469,9 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
              if (section->reloc_count != 0)
                {
                  /* Get a copy of the native relocations.  */
-                 internal_relocs = (_bfd_elf_link_read_relocs
-                                    (input_bfd, section, (PTR) NULL,
-                                     (Elf_Internal_Rela *) NULL,
-                                     link_info->keep_memory));
+                 internal_relocs = _bfd_elf_link_read_relocs (input_bfd, section,
+                                                              NULL, NULL,
+                                                              link_info->keep_memory);
                  if (internal_relocs == NULL)
                    goto error_return;
                }
@@ -2155,15 +2524,15 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                     local symbol in the global hash table.  */
                  amt = strlen (sym_name) + 10;
                  new_name = bfd_malloc (amt);
-                 if (new_name == 0)
+                 if (new_name == NULL)
                    goto error_return;
                  sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
                  sym_name = new_name;
 
-                 elftab = &hash_table->static_hash_table->root;
-                 sym_hash = ((struct elf32_mn10300_link_hash_entry *)
-                             elf_link_hash_lookup (elftab, sym_name,
-                                                   FALSE, FALSE, FALSE));
+                 elftab = & hash_table->static_hash_table->root;
+                 sym_hash = (struct elf32_mn10300_link_hash_entry *)
+                   elf_link_hash_lookup (elftab, sym_name,
+                                         FALSE, FALSE, FALSE);
 
                  free (new_name);
                  if (sym_hash == NULL)
@@ -2276,10 +2645,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  if (! link_info->keep_memory)
                    free (contents);
                  else
-                   {
-                     /* Cache the section contents for elf_link_input_bfd.  */
-                     elf_section_data (section)->this_hdr.contents = contents;
-                   }
+                   /* Cache the section contents for elf_link_input_bfd.  */
+                   elf_section_data (section)->this_hdr.contents = contents;
                }
              contents = NULL;
            }
@@ -2291,10 +2658,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
              if (! link_info->keep_memory)
                free (isymbuf);
              else
-               {
-                 /* Cache the symbols for elf_link_input_bfd.  */
-                 symtab_hdr->contents = (unsigned char *) isymbuf;
-               }
+               /* Cache the symbols for elf_link_input_bfd.  */
+               symtab_hdr->contents = (unsigned char *) isymbuf;
            }
          isymbuf = NULL;
        }
@@ -2319,17 +2684,45 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
   /* Get a copy of the native relocations.  */
-  internal_relocs = (_bfd_elf_link_read_relocs
-                    (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
-                     link_info->keep_memory));
+  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
+                                              link_info->keep_memory);
   if (internal_relocs == NULL)
     goto error_return;
 
+  /* Scan for worst case alignment gap changes.  Note that this logic
+     is not ideal; what we should do is run this scan for every
+     opcode/address range and adjust accordingly, but that's
+     expensive.  Worst case is that for an alignment of N bytes, we
+     move by 2*N-N-1 bytes, assuming we have aligns of 1, 2, 4, 8, etc
+     all before it.  Plus, this still doesn't cover cross-section
+     jumps with section alignment.  */
+  irelend = internal_relocs + sec->reloc_count;
+  align_gap_adjustment = 0;
+  for (irel = internal_relocs; irel < irelend; irel++)
+    {
+      if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_ALIGN)
+       {
+         bfd_vma adj = 1 << irel->r_addend;
+         bfd_vma aend = irel->r_offset;
+
+         aend = BFD_ALIGN (aend, 1 << irel->r_addend);
+         adj = 2 * adj - adj - 1;
+
+         /* Record the biggest adjustmnet.  Skip any alignment at the
+            end of our section.  */
+         if (align_gap_adjustment < adj
+             && aend < sec->output_section->vma + sec->output_offset + sec->size)
+           align_gap_adjustment = adj;
+       }
+    }
+
   /* Walk through them looking for relaxing opportunities.  */
   irelend = internal_relocs + sec->reloc_count;
   for (irel = internal_relocs; irel < irelend; irel++)
     {
       bfd_vma symval;
+      bfd_signed_vma jump_offset;
+      asection *sym_sec = NULL;
       struct elf32_mn10300_link_hash_entry *h = NULL;
 
       /* If this isn't something that can be relaxed, then ignore
@@ -2369,10 +2762,8 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
        {
          Elf_Internal_Sym *isym;
-         asection *sym_sec = NULL;
          const char *sym_name;
          char *new_name;
-         bfd_vma saved_addend;
 
          /* A local symbol.  */
          isym = isymbuf + ELF32_R_SYM (irel->r_info);
@@ -2390,24 +2781,42 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                                                      isym->st_name);
 
          if ((sym_sec->flags & SEC_MERGE)
-             && ELF_ST_TYPE (isym->st_info) == STT_SECTION
              && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
            {
-             saved_addend = irel->r_addend;
-             symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
-             symval += irel->r_addend;
-             irel->r_addend = saved_addend;
+             symval = isym->st_value;
+
+             /* GAS may reduce relocations against symbols in SEC_MERGE
+                sections to a relocation against the section symbol when
+                the original addend was zero.  When the reloc is against
+                a section symbol we should include the addend in the
+                offset passed to _bfd_merged_section_offset, since the
+                location of interest is the original symbol.  On the
+                other hand, an access to "sym+addend" where "sym" is not
+                a section symbol should not include the addend;  Such an
+                access is presumed to be an offset from "sym";  The
+                location of interest is just "sym".  */
+             if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+               symval += irel->r_addend;
+
+             symval = _bfd_merged_section_offset (abfd, & sym_sec,
+                                                  elf_section_data (sym_sec)->sec_info,
+                                                  symval);
+
+             if (ELF_ST_TYPE (isym->st_info) != STT_SECTION)
+               symval += irel->r_addend;
+
+             symval += sym_sec->output_section->vma
+               + sym_sec->output_offset - irel->r_addend;
            }
          else
-           {
-             symval = (isym->st_value
-                       + sym_sec->output_section->vma
-                       + sym_sec->output_offset);
-           }
+           symval = (isym->st_value
+                     + sym_sec->output_section->vma
+                     + sym_sec->output_offset);
+
          /* Tack on an ID so we can uniquely identify this
             local symbol in the global hash table.  */
          new_name = bfd_malloc ((bfd_size_type) strlen (sym_name) + 10);
-         if (new_name == 0)
+         if (new_name == NULL)
            goto error_return;
          sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
          sym_name = new_name;
@@ -2428,12 +2837,16 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
          BFD_ASSERT (h != NULL);
          if (h->root.root.type != bfd_link_hash_defined
              && h->root.root.type != bfd_link_hash_defweak)
-           {
-             /* This appears to be a reference to an undefined
-               symbol.  Just ignore it--it will be caught by the
-               regular reloc processing.  */
-             continue;
-           }
+           /* This appears to be a reference to an undefined
+              symbol.  Just ignore it--it will be caught by the
+              regular reloc processing.  */
+           continue;
+
+         /* Check for a reference to a discarded symbol and ignore it.  */
+         if (h->root.root.u.def.section->output_section == NULL)
+           continue;
+
+         sym_sec = h->root.root.u.def.section->output_section;
 
          symval = (h->root.root.u.def.value
                    + h->root.root.u.def.section->output_section->vma
@@ -2537,8 +2950,16 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
 
          /* See if the value will fit in 16 bits, note the high value is
             0x7fff + 2 as the target will be two bytes closer if we are
-            able to relax.  */
-         if ((long) value < 0x8001 && (long) value > -0x8000)
+            able to relax, if it's in the same section.  */
+         if (sec->output_section == sym_sec->output_section)
+           jump_offset = 0x8001;
+         else
+           jump_offset = 0x7fff;
+
+         /* Account for jumps across alignment boundaries using
+            align_gap_adjustment.  */
+         if ((bfd_signed_vma) value < jump_offset - (bfd_signed_vma) align_gap_adjustment
+             && ((bfd_signed_vma) value > -0x8000 + (bfd_signed_vma) align_gap_adjustment))
            {
              unsigned char code;
 
@@ -3143,7 +3564,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  case 0x93:
                    /* sp-based offsets are zero-extended.  */
                    if (code >= 0x90 && code <= 0x93
-                       && (long)value < 0)
+                       && (long) value < 0)
                      continue;
 
                    /* Note that we've changed the relocation contents, etc.  */
@@ -3200,7 +3621,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
 
                    /* mov imm16, an zero-extends the immediate.  */
                    if (code == 0xdc
-                       && (long)value < 0)
+                       && (long) value < 0)
                      continue;
 
                    /* Note that we've changed the relocation contents, etc.  */
@@ -3281,12 +3702,12 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                  case 0xe3:
                    /* cmp imm16, an zero-extends the immediate.  */
                    if (code == 0xdc
-                       && (long)value < 0)
+                       && (long) value < 0)
                      continue;
 
                    /* So do sp-based offsets.  */
                    if (code >= 0xb0 && code <= 0xb3
-                       && (long)value < 0)
+                       && (long) value < 0)
                      continue;
 
                    /* Note that we've changed the relocation contents, etc.  */
@@ -3405,242 +3826,16 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
   return FALSE;
 }
 
-/* Compute the stack size and movm arguments for the function
-   referred to by HASH at address ADDR in section with
-   contents CONTENTS, store the information in the hash table.  */
-static void
-compute_function_info (abfd, hash, addr, contents)
-     bfd *abfd;
-     struct elf32_mn10300_link_hash_entry *hash;
-     bfd_vma addr;
-     unsigned char *contents;
-{
-  unsigned char byte1, byte2;
-  /* We only care about a very small subset of the possible prologue
-     sequences here.  Basically we look for:
-
-     movm [d2,d3,a2,a3],sp (optional)
-     add <size>,sp (optional, and only for sizes which fit in an unsigned
-                   8 bit number)
-
-     If we find anything else, we quit.  */
-
-  /* Look for movm [regs],sp */
-  byte1 = bfd_get_8 (abfd, contents + addr);
-  byte2 = bfd_get_8 (abfd, contents + addr + 1);
-
-  if (byte1 == 0xcf)
-    {
-      hash->movm_args = byte2;
-      addr += 2;
-      byte1 = bfd_get_8 (abfd, contents + addr);
-      byte2 = bfd_get_8 (abfd, contents + addr + 1);
-    }
-
-  /* Now figure out how much stack space will be allocated by the movm
-     instruction.  We need this kept separate from the function's normal
-     stack space.  */
-  if (hash->movm_args)
-    {
-      /* Space for d2.  */
-      if (hash->movm_args & 0x80)
-       hash->movm_stack_size += 4;
-
-      /* Space for d3.  */
-      if (hash->movm_args & 0x40)
-       hash->movm_stack_size += 4;
-
-      /* Space for a2.  */
-      if (hash->movm_args & 0x20)
-       hash->movm_stack_size += 4;
-
-      /* Space for a3.  */
-      if (hash->movm_args & 0x10)
-       hash->movm_stack_size += 4;
-
-      /* "other" space.  d0, d1, a0, a1, mdr, lir, lar, 4 byte pad.  */
-      if (hash->movm_args & 0x08)
-       hash->movm_stack_size += 8 * 4;
-
-      if (bfd_get_mach (abfd) == bfd_mach_am33
-         || bfd_get_mach (abfd) == bfd_mach_am33_2)
-       {
-         /* "exother" space.  e0, e1, mdrq, mcrh, mcrl, mcvf */
-         if (hash->movm_args & 0x1)
-           hash->movm_stack_size += 6 * 4;
-
-         /* exreg1 space.  e4, e5, e6, e7 */
-         if (hash->movm_args & 0x2)
-           hash->movm_stack_size += 4 * 4;
-
-         /* exreg0 space.  e2, e3  */
-         if (hash->movm_args & 0x4)
-           hash->movm_stack_size += 2 * 4;
-       }
-    }
-
-  /* Now look for the two stack adjustment variants.  */
-  if (byte1 == 0xf8 && byte2 == 0xfe)
-    {
-      int temp = bfd_get_8 (abfd, contents + addr + 2);
-      temp = ((temp & 0xff) ^ (~0x7f)) + 0x80;
-
-      hash->stack_size = -temp;
-    }
-  else if (byte1 == 0xfa && byte2 == 0xfe)
-    {
-      int temp = bfd_get_16 (abfd, contents + addr + 2);
-      temp = ((temp & 0xffff) ^ (~0x7fff)) + 0x8000;
-      temp = -temp;
-
-      if (temp < 255)
-       hash->stack_size = temp;
-    }
-
-  /* If the total stack to be allocated by the call instruction is more
-     than 255 bytes, then we can't remove the stack adjustment by using
-     "call" (we might still be able to remove the "movm" instruction.  */
-  if (hash->stack_size + hash->movm_stack_size > 255)
-    hash->stack_size = 0;
-
-  return;
-}
-
-/* Delete some bytes from a section while relaxing.  */
-
-static bfd_boolean
-mn10300_elf_relax_delete_bytes (abfd, sec, addr, count)
-     bfd *abfd;
-     asection *sec;
-     bfd_vma addr;
-     int count;
-{
-  Elf_Internal_Shdr *symtab_hdr;
-  unsigned int sec_shndx;
-  bfd_byte *contents;
-  Elf_Internal_Rela *irel, *irelend;
-  Elf_Internal_Rela *irelalign;
-  bfd_vma toaddr;
-  Elf_Internal_Sym *isym, *isymend;
-  struct elf_link_hash_entry **sym_hashes;
-  struct elf_link_hash_entry **end_hashes;
-  unsigned int symcount;
-
-  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
-
-  contents = elf_section_data (sec)->this_hdr.contents;
-
-  /* The deletion must stop at the next ALIGN reloc for an aligment
-     power larger than the number of bytes we are deleting.  */
-
-  irelalign = NULL;
-  toaddr = sec->size;
-
-  irel = elf_section_data (sec)->relocs;
-  irelend = irel + sec->reloc_count;
-
-  /* Actually delete the bytes.  */
-  memmove (contents + addr, contents + addr + count,
-          (size_t) (toaddr - addr - count));
-  sec->size -= count;
-
-  /* Adjust all the relocs.  */
-  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
-    {
-      /* Get the new reloc address.  */
-      if ((irel->r_offset > addr
-          && irel->r_offset < toaddr))
-       irel->r_offset -= count;
-    }
-
-  /* Adjust the local symbols defined in this section.  */
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  isym = (Elf_Internal_Sym *) symtab_hdr->contents;
-  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
-    {
-      if (isym->st_shndx == sec_shndx
-         && isym->st_value > addr
-         && isym->st_value < toaddr)
-       isym->st_value -= count;
-    }
-
-  /* Now adjust the global symbols defined in this section.  */
-  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
-             - symtab_hdr->sh_info);
-  sym_hashes = elf_sym_hashes (abfd);
-  end_hashes = sym_hashes + symcount;
-  for (; sym_hashes < end_hashes; sym_hashes++)
-    {
-      struct elf_link_hash_entry *sym_hash = *sym_hashes;
-      if ((sym_hash->root.type == bfd_link_hash_defined
-          || sym_hash->root.type == bfd_link_hash_defweak)
-         && sym_hash->root.u.def.section == sec
-         && sym_hash->root.u.def.value > addr
-         && sym_hash->root.u.def.value < toaddr)
-       {
-         sym_hash->root.u.def.value -= count;
-       }
-    }
-
-  return TRUE;
-}
-
-/* Return TRUE if a symbol exists at the given address, else return
-   FALSE.  */
-static bfd_boolean
-mn10300_elf_symbol_address_p (abfd, sec, isym, addr)
-     bfd *abfd;
-     asection *sec;
-     Elf_Internal_Sym *isym;
-     bfd_vma addr;
-{
-  Elf_Internal_Shdr *symtab_hdr;
-  unsigned int sec_shndx;
-  Elf_Internal_Sym *isymend;
-  struct elf_link_hash_entry **sym_hashes;
-  struct elf_link_hash_entry **end_hashes;
-  unsigned int symcount;
-
-  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
-
-  /* Examine all the symbols.  */
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
-    {
-      if (isym->st_shndx == sec_shndx
-         && isym->st_value == addr)
-       return TRUE;
-    }
-
-  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
-             - symtab_hdr->sh_info);
-  sym_hashes = elf_sym_hashes (abfd);
-  end_hashes = sym_hashes + symcount;
-  for (; sym_hashes < end_hashes; sym_hashes++)
-    {
-      struct elf_link_hash_entry *sym_hash = *sym_hashes;
-      if ((sym_hash->root.type == bfd_link_hash_defined
-          || sym_hash->root.type == bfd_link_hash_defweak)
-         && sym_hash->root.u.def.section == sec
-         && sym_hash->root.u.def.value == addr)
-       return TRUE;
-    }
-
-  return FALSE;
-}
-
 /* This is a version of bfd_generic_get_relocated_section_contents
    which uses mn10300_elf_relocate_section.  */
 
 static bfd_byte *
-mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
-                                           data, relocatable, symbols)
-     bfd *output_bfd;
-     struct bfd_link_info *link_info;
-     struct bfd_link_order *link_order;
-     bfd_byte *data;
-     bfd_boolean relocatable;
-     asymbol **symbols;
+mn10300_elf_get_relocated_section_contents (bfd *output_bfd,
+                                           struct bfd_link_info *link_info,
+                                           struct bfd_link_order *link_order,
+                                           bfd_byte *data,
+                                           bfd_boolean relocatable,
+                                           asymbol **symbols)
 {
   Elf_Internal_Shdr *symtab_hdr;
   asection *input_section = link_order->u.indirect.section;
@@ -3670,9 +3865,8 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       Elf_Internal_Sym *isym, *isymend;
       bfd_size_type amt;
 
-      internal_relocs = (_bfd_elf_link_read_relocs
-                        (input_bfd, input_section, (PTR) NULL,
-                         (Elf_Internal_Rela *) NULL, FALSE));
+      internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
+                                                  NULL, NULL, FALSE);
       if (internal_relocs == NULL)
        goto error_return;
 
@@ -3689,7 +3883,7 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
 
       amt = symtab_hdr->sh_info;
       amt *= sizeof (asection *);
-      sections = (asection **) bfd_malloc (amt);
+      sections = bfd_malloc (amt);
       if (sections == NULL && amt != 0)
        goto error_return;
 
@@ -3711,8 +3905,8 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
        }
 
       if (! mn10300_elf_relocate_section (output_bfd, link_info, input_bfd,
-                                    input_section, data, internal_relocs,
-                                    isymbuf, sections))
+                                         input_section, data, internal_relocs,
+                                         isymbuf, sections))
        goto error_return;
 
       if (sections != NULL)
@@ -3743,28 +3937,26 @@ mn10300_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
 /* Create an entry in an MN10300 ELF linker hash table.  */
 
 static struct bfd_hash_entry *
-elf32_mn10300_link_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+elf32_mn10300_link_hash_newfunc (struct bfd_hash_entry *entry,
+                                struct bfd_hash_table *table,
+                                const char *string)
 {
   struct elf32_mn10300_link_hash_entry *ret =
     (struct elf32_mn10300_link_hash_entry *) entry;
 
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct elf32_mn10300_link_hash_entry *) NULL)
-    ret = ((struct elf32_mn10300_link_hash_entry *)
-          bfd_hash_allocate (table,
-                             sizeof (struct elf32_mn10300_link_hash_entry)));
-  if (ret == (struct elf32_mn10300_link_hash_entry *) NULL)
+  if (ret == NULL)
+    ret = (struct elf32_mn10300_link_hash_entry *)
+          bfd_hash_allocate (table, sizeof (* ret));
+  if (ret == NULL)
     return (struct bfd_hash_entry *) ret;
 
   /* Call the allocation method of the superclass.  */
-  ret = ((struct elf32_mn10300_link_hash_entry *)
+  ret = (struct elf32_mn10300_link_hash_entry *)
         _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
-                                    table, string));
-  if (ret != (struct elf32_mn10300_link_hash_entry *) NULL)
+                                    table, string);
+  if (ret != NULL)
     {
       ret->direct_calls = 0;
       ret->stack_size = 0;
@@ -3780,14 +3972,13 @@ elf32_mn10300_link_hash_newfunc (entry, table, string)
 /* Create an mn10300 ELF linker hash table.  */
 
 static struct bfd_link_hash_table *
-elf32_mn10300_link_hash_table_create (abfd)
-     bfd *abfd;
+elf32_mn10300_link_hash_table_create (bfd *abfd)
 {
   struct elf32_mn10300_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct elf32_mn10300_link_hash_table);
+  bfd_size_type amt = sizeof (* ret);
 
-  ret = (struct elf32_mn10300_link_hash_table *) bfd_malloc (amt);
-  if (ret == (struct elf32_mn10300_link_hash_table *) NULL)
+  ret = bfd_malloc (amt);
+  if (ret == NULL)
     return NULL;
 
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
@@ -3800,8 +3991,7 @@ elf32_mn10300_link_hash_table_create (abfd)
 
   ret->flags = 0;
   amt = sizeof (struct elf_link_hash_table);
-  ret->static_hash_table
-    = (struct elf32_mn10300_link_hash_table *) bfd_malloc (amt);
+  ret->static_hash_table = bfd_malloc (amt);
   if (ret->static_hash_table == NULL)
     {
       free (ret);
@@ -3816,14 +4006,13 @@ elf32_mn10300_link_hash_table_create (abfd)
       free (ret);
       return NULL;
     }
-  return &ret->root.root;
+  return & ret->root.root;
 }
 
 /* Free an mn10300 ELF linker hash table.  */
 
 static void
-elf32_mn10300_link_hash_table_free (hash)
-     struct bfd_link_hash_table *hash;
+elf32_mn10300_link_hash_table_free (struct bfd_link_hash_table *hash)
 {
   struct elf32_mn10300_link_hash_table *ret
     = (struct elf32_mn10300_link_hash_table *) hash;
@@ -3835,8 +4024,7 @@ elf32_mn10300_link_hash_table_free (hash)
 }
 
 static unsigned long
-elf_mn10300_mach (flags)
-     flagword flags;
+elf_mn10300_mach (flagword flags)
 {
   switch (flags & EF_MN10300_MACH)
     {
@@ -3856,10 +4044,9 @@ elf_mn10300_mach (flags)
    file.  This gets the MN10300 architecture right based on the machine
    number.  */
 
-void
-_bfd_mn10300_elf_final_write_processing (abfd, linker)
-     bfd *abfd;
-     bfd_boolean linker ATTRIBUTE_UNUSED;
+static void
+_bfd_mn10300_elf_final_write_processing (bfd *abfd,
+                                        bfd_boolean linker ATTRIBUTE_UNUSED)
 {
   unsigned long val;
 
@@ -3883,9 +4070,8 @@ _bfd_mn10300_elf_final_write_processing (abfd, linker)
   elf_elfheader (abfd)->e_flags |= val;
 }
 
-bfd_boolean
-_bfd_mn10300_elf_object_p (abfd)
-     bfd *abfd;
+static bfd_boolean
+_bfd_mn10300_elf_object_p (bfd *abfd)
 {
   bfd_default_set_arch_mach (abfd, bfd_arch_mn10300,
                             elf_mn10300_mach (elf_elfheader (abfd)->e_flags));
@@ -3895,10 +4081,8 @@ _bfd_mn10300_elf_object_p (abfd)
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
-bfd_boolean
-_bfd_mn10300_elf_merge_private_bfd_data (ibfd, obfd)
-     bfd *ibfd;
-     bfd *obfd;
+static bfd_boolean
+_bfd_mn10300_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
@@ -3915,9 +4099,9 @@ _bfd_mn10300_elf_merge_private_bfd_data (ibfd, obfd)
   return TRUE;
 }
 
-#define PLT0_ENTRY_SIZE 15
-#define PLT_ENTRY_SIZE 20
-#define PIC_PLT_ENTRY_SIZE 24
+#define PLT0_ENTRY_SIZE     15
+#define PLT_ENTRY_SIZE      20
+#define PIC_PLT_ENTRY_SIZE  24
 
 static const bfd_byte elf_mn10300_plt0_entry[PLT0_ENTRY_SIZE] =
 {
@@ -3961,7 +4145,7 @@ static const bfd_byte elf_mn10300_pic_plt_entry[PIC_PLT_ENTRY_SIZE] =
 /* Return offset of the GOT id in PLT0 entry.  */
 #define elf_mn10300_plt0_gotid_offset(info) 9
 
-/* Return offset of the temporary in PLT entry */
+/* Return offset of the temporary in PLT entry */
 #define elf_mn10300_plt_temp_offset(info) 8
 
 /* Return offset of the symbol in PLT entry.  */
@@ -3978,9 +4162,7 @@ static const bfd_byte elf_mn10300_pic_plt_entry[PIC_PLT_ENTRY_SIZE] =
 /* Create dynamic sections when linking against a dynamic object.  */
 
 static bfd_boolean
-_bfd_mn10300_elf_create_dynamic_sections (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_mn10300_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   flagword   flags;
   asection * s;
@@ -4004,7 +4186,6 @@ _bfd_mn10300_elf_create_dynamic_sections (abfd, info)
 
   /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
      .rel[a].bss sections.  */
-
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
           | SEC_LINKER_CREATED);
 
@@ -4033,7 +4214,7 @@ _bfd_mn10300_elf_create_dynamic_sections (abfd, info)
          continue;
 
        secname = bfd_get_section_name (abfd, sec);
-       relname = (char *) bfd_malloc (strlen (secname) + 6);
+       relname = bfd_malloc (strlen (secname) + 6);
        strcpy (relname, ".rela");
        strcat (relname, secname);
 
@@ -4091,9 +4272,8 @@ _bfd_mn10300_elf_create_dynamic_sections (abfd, info)
    understand.  */
 
 static bfd_boolean
-_bfd_mn10300_elf_adjust_dynamic_symbol (info, h)
-     struct bfd_link_info * info;
-     struct elf_link_hash_entry * h;
+_bfd_mn10300_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
+                                       struct elf_link_hash_entry * h)
 {
   bfd * dynobj;
   asection * s;
@@ -4161,13 +4341,11 @@ _bfd_mn10300_elf_adjust_dynamic_symbol (info, h)
 
       /* 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->size += 4;
 
       /* We also need to make an entry in the .rela.plt section.  */
-
       s = bfd_get_section_by_name (dynobj, ".rela.plt");
       BFD_ASSERT (s != NULL);
       s->size += sizeof (Elf32_External_Rela);
@@ -4242,9 +4420,8 @@ _bfd_mn10300_elf_adjust_dynamic_symbol (info, h)
 /* Set the sizes of the dynamic sections.  */
 
 static bfd_boolean
-_bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
-     bfd * output_bfd;
-     struct bfd_link_info * info;
+_bfd_mn10300_elf_size_dynamic_sections (bfd * output_bfd,
+                                       struct bfd_link_info * info)
 {
   bfd * dynobj;
   asection * s;
@@ -4295,7 +4472,7 @@ _bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
         of the dynobj section names depend upon the input files.  */
       name = bfd_get_section_name (dynobj, s);
 
-      if (strcmp (name, ".plt") == 0)
+      if (streq (name, ".plt"))
        {
          /* Remember whether there is a PLT.  */
          plt = s->size != 0;
@@ -4308,7 +4485,7 @@ _bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
 
              /* Remember whether there are any reloc sections other
                 than .rela.plt.  */
-             if (strcmp (name, ".rela.plt") != 0)
+             if (! streq (name, ".rela.plt"))
                {
                  const char * outname;
 
@@ -4334,7 +4511,7 @@ _bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
            }
        }
       else if (! CONST_STRNEQ (name, ".got")
-              && strcmp (name, ".dynbss") != 0)
+              && ! streq (name, ".dynbss"))
        /* It's not one of our sections, so don't allocate space.  */
        continue;
 
@@ -4361,7 +4538,7 @@ _bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
         section's contents are written out.  This should not happen,
         but this way if it does, we get a R_MN10300_NONE reloc
         instead of garbage.  */
-      s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+      s->contents = bfd_zalloc (dynobj, s->size);
       if (s->contents == NULL)
        return FALSE;
     }
@@ -4411,11 +4588,10 @@ _bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
    dynamic sections here.  */
 
 static bfd_boolean
-_bfd_mn10300_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
-     bfd * output_bfd;
-     struct bfd_link_info * info;
-     struct elf_link_hash_entry * h;
-     Elf_Internal_Sym * sym;
+_bfd_mn10300_elf_finish_dynamic_symbol (bfd * output_bfd,
+                                       struct bfd_link_info * info,
+                                       struct elf_link_hash_entry * h,
+                                       Elf_Internal_Sym * sym)
 {
   bfd * dynobj;
 
@@ -4514,14 +4690,13 @@ _bfd_mn10300_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
       Elf_Internal_Rela rel;
 
       /* This symbol has an entry in the global offset table.  Set it up.  */
-
       sgot = bfd_get_section_by_name (dynobj, ".got");
       srel = bfd_get_section_by_name (dynobj, ".rela.got");
       BFD_ASSERT (sgot != NULL && srel != NULL);
 
       rel.r_offset = (sgot->output_section->vma
                      + sgot->output_offset
-                     + (h->got.offset &1));
+                     + (h->got.offset & ~1));
 
       /* If this is a -Bsymbolic link, and the symbol is defined
         locally, we just want to emit a RELATIVE reloc.  Likewise if
@@ -4569,14 +4744,14 @@ _bfd_mn10300_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
                      + h->root.u.def.section->output_offset);
       rel.r_info = ELF32_R_INFO (h->dynindx, R_MN10300_COPY);
       rel.r_addend = 0;
-      bfd_elf32_swap_reloca_out (output_bfd, &rel,
+      bfd_elf32_swap_reloca_out (output_bfd, & rel,
                                 (bfd_byte *) ((Elf32_External_Rela *) s->contents
                                               + s->reloc_count));
       ++ s->reloc_count;
     }
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+  if (streq (h->root.root.string, "_DYNAMIC")
       || h == elf_hash_table (info)->hgot)
     sym->st_shndx = SHN_ABS;
 
@@ -4586,9 +4761,8 @@ _bfd_mn10300_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
 /* Finish up the dynamic sections.  */
 
 static bfd_boolean
-_bfd_mn10300_elf_finish_dynamic_sections (output_bfd, info)
-     bfd * output_bfd;
-     struct bfd_link_info * info;
+_bfd_mn10300_elf_finish_dynamic_sections (bfd * output_bfd,
+                                         struct bfd_link_info * info)
 {
   bfd *      dynobj;
   asection * sgot;
@@ -4714,14 +4888,10 @@ _bfd_mn10300_elf_reloc_type_class (const Elf_Internal_Rela *rela)
 {
   switch ((int) ELF32_R_TYPE (rela->r_info))
     {
-    case R_MN10300_RELATIVE:
-      return reloc_class_relative;
-    case R_MN10300_JMP_SLOT:
-      return reloc_class_plt;
-    case R_MN10300_COPY:
-      return reloc_class_copy;
-    default:
-      return reloc_class_normal;
+    case R_MN10300_RELATIVE:   return reloc_class_relative;
+    case R_MN10300_JMP_SLOT:   return reloc_class_plt;
+    case R_MN10300_COPY:       return reloc_class_copy;
+    default:                   return reloc_class_normal;
     }
 }