gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / elf64-mmix.c
index 3c5336b7d28c667615aae624447f38fe01fba578..fee4a0fbd78c778b2d63bb2c6c10b98a7680fcab 100644 (file)
@@ -1,22 +1,24 @@
 /* MMIX-specific support for 64-bit ELF.
-   Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
    Contributed by Hans-Peter Nilsson <hp@bitrange.com>
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* No specific ABI or "processor-specific supplement" defined.  */
 
@@ -26,8 +28,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
    - GETA stub relaxation (call a stub for out of range new
      R_MMIX_GETA_STUBBABLE).  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/mmix.h"
@@ -72,6 +74,13 @@ struct _mmix_elf_section_data
        stubs_size_sum for relocation.  */
     bfd_size_type stub_offset;
   } pjs;
+
+  /* Whether there has been a warning that this section could not be
+     linked due to a specific cause.  FIXME: a way to access the
+     linker info or output section, then stuff the limiter guard
+     there. */
+  bfd_boolean has_warned_bpo;
+  bfd_boolean has_warned_pushj;
 };
 
 #define mmix_elf_section_data(sec) \
@@ -156,78 +165,24 @@ struct bpo_greg_section_info
     struct bpo_reloc_request *reloc_request;
   };
 
-static bfd_boolean mmix_elf_link_output_symbol_hook
-  PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *,
-          asection *, struct elf_link_hash_entry *));
-
-static bfd_reloc_status_type mmix_elf_reloc
-  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
-static reloc_howto_type *bfd_elf64_bfd_reloc_type_lookup
-  PARAMS ((bfd *, bfd_reloc_code_real_type));
-
-static void mmix_info_to_howto_rela
-  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-
-static int mmix_elf_sort_relocs PARAMS ((const PTR, const PTR));
-
-static bfd_boolean mmix_elf_new_section_hook
-  PARAMS ((bfd *, asection *));
-
-static bfd_boolean mmix_elf_check_relocs
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-
-static bfd_boolean mmix_elf_check_common_relocs
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-
-static bfd_boolean mmix_elf_relocate_section
-  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
-          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 
-static asection * mmix_elf_gc_mark_hook
-  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
-          struct elf_link_hash_entry *, Elf_Internal_Sym *));
+extern bfd_boolean mmix_elf_final_link (bfd *, struct bfd_link_info *);
 
-static bfd_boolean mmix_elf_gc_sweep_hook
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-
-static bfd_reloc_status_type mmix_final_link_relocate
-  PARAMS ((reloc_howto_type *, asection *, bfd_byte *,
-          bfd_vma, bfd_signed_vma, bfd_vma, const char *, asection *));
-
-static bfd_reloc_status_type mmix_elf_perform_relocation
-  PARAMS ((asection *, reloc_howto_type *, PTR, bfd_vma, bfd_vma));
-
-static bfd_boolean mmix_elf_section_from_bfd_section
-  PARAMS ((bfd *, asection *, int *));
-
-static bfd_boolean mmix_elf_add_symbol_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
-          const char **, flagword *, asection **, bfd_vma *));
-
-static bfd_boolean mmix_elf_is_local_label_name
-  PARAMS ((bfd *, const char *));
-
-static int bpo_reloc_request_sort_fn PARAMS ((const PTR, const PTR));
-
-static bfd_boolean mmix_elf_relax_section
-  PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
-          bfd_boolean *again));
-
-extern bfd_boolean mmix_elf_final_link PARAMS ((bfd *, struct bfd_link_info *));
-
-extern void mmix_elf_symbol_processing PARAMS ((bfd *, asymbol *));
+extern void mmix_elf_symbol_processing (bfd *, asymbol *);
 
 /* Only intended to be called from a debugger.  */
 extern void mmix_dump_bpo_gregs
-  PARAMS ((struct bfd_link_info *, bfd_error_handler_type));
+  (struct bfd_link_info *, void (*) (const char *, ...));
 
 static void
-mmix_set_relaxable_size
-  PARAMS ((bfd *, asection *, void *));
+mmix_set_relaxable_size (bfd *, asection *, void *);
+static bfd_reloc_status_type
+mmix_elf_reloc (bfd *, arelent *, asymbol *, void *,
+               asection *, bfd *, char **);
+static bfd_reloc_status_type
+mmix_final_link_relocate (reloc_howto_type *, asection *, bfd_byte *, bfd_vma,
+                         bfd_signed_vma, bfd_vma, const char *, asection *,
+                         char **);
 
 
 /* Watch out: this currently needs to have elements with the same index as
@@ -237,11 +192,11 @@ static reloc_howto_type elf_mmix_howto_table[] =
   /* This reloc does nothing.  */
   HOWTO (R_MMIX_NONE,          /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
+        complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_MMIX_NONE",         /* name */
         FALSE,                 /* partial_inplace */
@@ -505,7 +460,7 @@ static reloc_howto_type elf_mmix_howto_table[] =
         FALSE,                 /* partial_inplace */
         ~0x0100ffff,           /* src_mask */
         0x0100ffff,            /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        TRUE),                 /* pcrel_offset */
 
   HOWTO (R_MMIX_CBRANCH_J,     /* type */
         2,                     /* rightshift */
@@ -838,9 +793,8 @@ static const struct mmix_reloc_map mmix_reloc_map[] =
   };
 
 static reloc_howto_type *
-bfd_elf64_bfd_reloc_type_lookup (abfd, code)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     bfd_reloc_code_real_type code;
+bfd_elf64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                bfd_reloc_code_real_type code)
 {
   unsigned int i;
 
@@ -855,18 +809,35 @@ bfd_elf64_bfd_reloc_type_lookup (abfd, code)
   return NULL;
 }
 
+static reloc_howto_type *
+bfd_elf64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (elf_mmix_howto_table) / sizeof (elf_mmix_howto_table[0]);
+       i++)
+    if (elf_mmix_howto_table[i].name != NULL
+       && strcasecmp (elf_mmix_howto_table[i].name, r_name) == 0)
+      return &elf_mmix_howto_table[i];
+
+  return NULL;
+}
+
 static bfd_boolean
-mmix_elf_new_section_hook (abfd, sec)
-     bfd *abfd;
-     asection *sec;
+mmix_elf_new_section_hook (bfd *abfd, asection *sec)
 {
-  struct _mmix_elf_section_data *sdata;
-  bfd_size_type amt = sizeof (*sdata);
+  if (!sec->used_by_bfd)
+    {
+      struct _mmix_elf_section_data *sdata;
+      size_t amt = sizeof (*sdata);
 
-  sdata = (struct _mmix_elf_section_data *) bfd_zalloc (abfd, amt);
-  if (sdata == NULL)
-    return FALSE;
-  sec->used_by_bfd = (PTR) sdata;
+      sdata = bfd_zalloc (abfd, amt);
+      if (sdata == NULL)
+       return FALSE;
+      sec->used_by_bfd = sdata;
+    }
 
   return _bfd_elf_new_section_hook (abfd, sec);
 }
@@ -920,12 +891,9 @@ mmix_elf_new_section_hook (abfd, sec)
    R_MMIX_ADDR19 and R_MMIX_ADDR27 are just filled in.  */
 
 static bfd_reloc_status_type
-mmix_elf_perform_relocation (isec, howto, datap, addr, value)
-     asection *isec;
-     reloc_howto_type *howto;
-     PTR datap;
-     bfd_vma addr;
-     bfd_vma value;
+mmix_elf_perform_relocation (asection *isec, reloc_howto_type *howto,
+                            void *datap, bfd_vma addr, bfd_vma value,
+                            char **error_message)
 {
   bfd *abfd = isec->owner;
   bfd_reloc_status_type flag = bfd_reloc_ok;
@@ -999,6 +967,36 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
               + mmix_elf_section_data (isec)->pjs.stub_offset);
          bfd_vma stubaddr;
 
+         if (mmix_elf_section_data (isec)->pjs.n_pushj_relocs == 0)
+           {
+             /* This shouldn't happen when linking to ELF or mmo, so
+                this is an attempt to link to "binary", right?  We
+                can't access the output bfd, so we can't verify that
+                assumption.  We only know that the critical
+                mmix_elf_check_common_relocs has not been called,
+                which happens when the output format is different
+                from the input format (and is not mmo).  */
+             if (! mmix_elf_section_data (isec)->has_warned_pushj)
+               {
+                 /* For the first such error per input section, produce
+                    a verbose message.  */
+                 *error_message
+                   = _("invalid input relocation when producing"
+                       " non-ELF, non-mmo format output;"
+                       " please use the objcopy program to convert from"
+                       " ELF or mmo,"
+                       " or assemble using"
+                       " \"-no-expand\" (for gcc, \"-Wa,-no-expand\"");
+                 mmix_elf_section_data (isec)->has_warned_pushj = TRUE;
+                 return bfd_reloc_dangerous;
+               }
+
+             /* For subsequent errors, return this one, which is
+                rate-limited but looks a little bit different,
+                hopefully without affecting user-friendliness.  */
+             return bfd_reloc_overflow;
+           }
+
          /* The address doesn't fit, so redirect the PUSHJ to the
             location of the stub.  */
          r = mmix_elf_perform_relocation (isec,
@@ -1011,7 +1009,8 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
                                           + size
                                           + (mmix_elf_section_data (isec)
                                              ->pjs.stub_offset)
-                                          - addr);
+                                          - addr,
+                                          error_message);
          if (r != bfd_reloc_ok)
            return r;
 
@@ -1035,7 +1034,8 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
                                               [R_MMIX_ADDR27],
                                               stubcontents,
                                               stubaddr,
-                                              value + addr - stubaddr);
+                                              value + addr - stubaddr,
+                                              error_message);
              mmix_elf_section_data (isec)->pjs.stub_offset += 4;
 
              if (size + mmix_elf_section_data (isec)->pjs.stub_offset
@@ -1147,26 +1147,56 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
       {
        struct bpo_reloc_section_info *bpodata
          = mmix_elf_section_data (isec)->bpo.reloc;
-       asection *bpo_greg_section
-         = bpodata->bpo_greg_section;
-       struct bpo_greg_section_info *gregdata
-         = mmix_elf_section_data (bpo_greg_section)->bpo.greg;
-       size_t bpo_index
-         = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
+       asection *bpo_greg_section;
+       struct bpo_greg_section_info *gregdata;
+       size_t bpo_index;
+
+       if (bpodata == NULL)
+         {
+           /* This shouldn't happen when linking to ELF or mmo, so
+              this is an attempt to link to "binary", right?  We
+              can't access the output bfd, so we can't verify that
+              assumption.  We only know that the critical
+              mmix_elf_check_common_relocs has not been called, which
+              happens when the output format is different from the
+              input format (and is not mmo).  */
+           if (! mmix_elf_section_data (isec)->has_warned_bpo)
+             {
+               /* For the first such error per input section, produce
+                  a verbose message.  */
+               *error_message
+                 = _("invalid input relocation when producing"
+                     " non-ELF, non-mmo format output;"
+                     " please use the objcopy program to convert from"
+                     " ELF or mmo,"
+                     " or compile using the gcc-option"
+                     " \"-mno-base-addresses\".");
+               mmix_elf_section_data (isec)->has_warned_bpo = TRUE;
+               return bfd_reloc_dangerous;
+             }
+
+           /* For subsequent errors, return this one, which is
+              rate-limited but looks a little bit different,
+              hopefully without affecting user-friendliness.  */
+           return bfd_reloc_overflow;
+         }
+
+       bpo_greg_section = bpodata->bpo_greg_section;
+       gregdata = mmix_elf_section_data (bpo_greg_section)->bpo.greg;
+       bpo_index = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
 
        /* A consistency check: The value we now have in "relocation" must
           be the same as the value we stored for that relocation.  It
           doesn't cost much, so can be left in at all times.  */
        if (value != gregdata->reloc_request[bpo_index].value)
          {
-           (*_bfd_error_handler)
-             (_("%s: Internal inconsistency error for value for\n\
- linker-allocated global register: linked: 0x%lx%08lx != relaxed: 0x%lx%08lx\n"),
-              bfd_get_filename (isec->owner),
-              (unsigned long) (value >> 32), (unsigned long) value,
-              (unsigned long) (gregdata->reloc_request[bpo_index].value
-                               >> 32),
-              (unsigned long) gregdata->reloc_request[bpo_index].value);
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: Internal inconsistency error for value for\n\
+ linker-allocated global register: linked: %#" PRIx64 " != relaxed: %#" PRIx64 ""),
+              isec->owner,
+              (uint64_t) value,
+              (uint64_t) gregdata->reloc_request[bpo_index].value);
            bfd_set_error (bfd_error_bad_value);
            return bfd_reloc_overflow;
          }
@@ -1220,17 +1250,24 @@ mmix_elf_perform_relocation (isec, howto, datap, addr, value)
 
 /* Set the howto pointer for an MMIX ELF reloc (type RELA).  */
 
-static void
-mmix_info_to_howto_rela (abfd, cache_ptr, dst)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     arelent *cache_ptr;
-     Elf_Internal_Rela *dst;
+static bfd_boolean
+mmix_info_to_howto_rela (bfd *abfd,
+                        arelent *cache_ptr,
+                        Elf_Internal_Rela *dst)
 {
   unsigned int r_type;
 
   r_type = ELF64_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < (unsigned int) R_MMIX_max);
+  if (r_type >= (unsigned int) R_MMIX_max)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
   cache_ptr->howto = &elf_mmix_howto_table[r_type];
+  return TRUE;
 }
 
 /* Any MMIX-specific relocation gets here at assembly time or when linking
@@ -1238,22 +1275,19 @@ mmix_info_to_howto_rela (abfd, cache_ptr, dst)
    the reloc_table.  We don't get here for final pure ELF linking.  */
 
 static bfd_reloc_status_type
-mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
-               output_bfd, error_message)
-     bfd *abfd;
-     arelent *reloc_entry;
-     asymbol *symbol;
-     PTR data;
-     asection *input_section;
-     bfd *output_bfd;
-     char **error_message ATTRIBUTE_UNUSED;
+mmix_elf_reloc (bfd *abfd,
+               arelent *reloc_entry,
+               asymbol *symbol,
+               void * data,
+               asection *input_section,
+               bfd *output_bfd,
+               char **error_message)
 {
   bfd_vma relocation;
   bfd_reloc_status_type r;
   asection *reloc_target_output_section;
   bfd_reloc_status_type flag = bfd_reloc_ok;
   bfd_vma output_base = 0;
-  bfd_vma addr;
 
   r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
                             input_section, output_bfd, error_message);
@@ -1281,7 +1315,7 @@ mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
   else
     relocation = symbol->value;
 
-  reloc_target_output_section = bfd_get_output_section (symbol);
+  reloc_target_output_section = bfd_asymbol_section (symbol)->output_section;
 
   /* Here the variable relocation holds the final address of the symbol we
      are relocating against, plus any addend.  */
@@ -1292,9 +1326,6 @@ mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
 
   relocation += output_base + symbol->section->output_offset;
 
-  /* Get position of relocation.  */
-  addr = (reloc_entry->address + input_section->output_section->vma
-         + input_section->output_offset);
   if (output_bfd != (bfd *) NULL)
     {
       /* Add in supplied addend.  */
@@ -1312,23 +1343,22 @@ mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
                                   data, reloc_entry->address,
                                   reloc_entry->addend, relocation,
                                   bfd_asymbol_name (symbol),
-                                  reloc_target_output_section);
+                                  reloc_target_output_section,
+                                  error_message);
 }
 \f
 /* Relocate an MMIX ELF section.  Modified from elf32-fr30.c; look to it
    for guidance if you're thinking of copying this.  */
 
 static bfd_boolean
-mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
-                          contents, relocs, local_syms, local_sections)
-     bfd *output_bfd ATTRIBUTE_UNUSED;
-     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;
+mmix_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
+                          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;
@@ -1369,22 +1399,47 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
       r_symndx = ELF64_R_SYM (rel->r_info);
 
-      if (info->relocatable)
+      howto = elf_mmix_howto_table + ELF64_R_TYPE (rel->r_info);
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info)
+       {
+         sym = local_syms + r_symndx;
+         sec = local_sections [r_symndx];
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+
+         name = bfd_elf_string_from_elf_section (input_bfd,
+                                                 symtab_hdr->sh_link,
+                                                 sym->st_name);
+         if (name == NULL)
+           name = bfd_section_name (sec);
+       }
+      else
+       {
+         bfd_boolean unresolved_reloc, ignored;
+
+         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+                                  r_symndx, symtab_hdr, sym_hashes,
+                                  h, sec, relocation,
+                                  unresolved_reloc, undefined_signalled,
+                                  ignored);
+         name = h->root.root.string;
+       }
+
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend, howto, 0, contents);
+
+      if (bfd_link_relocatable (info))
        {
          /* This is a relocatable link.  For most relocs we don't have to
             change anything, unless the reloc is against a section
             symbol, in which case we have to adjust according to where
             the section symbol winds up in the output section.  */
-         if (r_symndx < symtab_hdr->sh_info)
-           {
-             sym = local_syms + r_symndx;
-
-             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               {
-                 sec = local_sections [r_symndx];
-                 rel->r_addend += sec->output_offset + sym->st_value;
-               }
-           }
+         if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+           rel->r_addend += sec->output_offset;
 
          /* For PUSHJ stub relocs however, we may need to change the
             reloc and the section contents, if the reloc doesn't reach
@@ -1420,7 +1475,7 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                                                + size
                                                + mmix_elf_section_data (input_section)
                                                ->pjs.stub_offset,
-                                               NULL, NULL) != bfd_reloc_ok)
+                                               NULL, NULL, NULL) != bfd_reloc_ok)
                    return FALSE;
 
                  /* Put a JMP insn at the stub; it goes with the
@@ -1458,48 +1513,18 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          continue;
        }
 
-      /* This is a final link.  */
-      howto = elf_mmix_howto_table + ELF64_R_TYPE (rel->r_info);
-      h = NULL;
-      sym = NULL;
-      sec = NULL;
-
-      if (r_symndx < symtab_hdr->sh_info)
-       {
-         sym = local_syms + r_symndx;
-         sec = local_sections [r_symndx];
-         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
-
-         name = bfd_elf_string_from_elf_section (input_bfd,
-                                                 symtab_hdr->sh_link,
-                                                 sym->st_name);
-         if (name == NULL)
-           name = bfd_section_name (input_bfd, sec);
-       }
-      else
-       {
-         bfd_boolean unresolved_reloc;
-
-         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
-                                  r_symndx, symtab_hdr, sym_hashes,
-                                  h, sec, relocation,
-                                  unresolved_reloc, undefined_signalled);
-         name = h->root.root.string;
-       }
-
       r = mmix_final_link_relocate (howto, input_section,
                                    contents, rel->r_offset,
-                                   rel->r_addend, relocation, name, sec);
+                                   rel->r_addend, relocation, name, sec, NULL);
 
       if (r != bfd_reloc_ok)
        {
-         bfd_boolean check_ok = TRUE;
          const char * msg = (const char *) NULL;
 
          switch (r)
            {
            case bfd_reloc_overflow:
-             check_ok = info->callbacks->reloc_overflow
+             info->callbacks->reloc_overflow
                (info, (h ? &h->root : NULL), name, howto->name,
                 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
              break;
@@ -1507,9 +1532,8 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            case bfd_reloc_undefined:
              /* We may have sent this message above.  */
              if (! undefined_signalled)
-               check_ok = info->callbacks->undefined_symbol
-                 (info, name, input_bfd, input_section, rel->r_offset,
-                  TRUE);
+               info->callbacks->undefined_symbol
+                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
              undefined_signalled = TRUE;
              break;
 
@@ -1531,11 +1555,8 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
 
          if (msg)
-           check_ok = info->callbacks->warning
-             (info, msg, name, input_bfd, input_section, rel->r_offset);
-
-         if (! check_ok)
-           return FALSE;
+           (*info->callbacks->warning) (info, msg, name, input_bfd,
+                                        input_section, rel->r_offset);
        }
     }
 
@@ -1546,16 +1567,11 @@ mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
    routines.  A few relocs we have to do ourselves.  */
 
 static bfd_reloc_status_type
-mmix_final_link_relocate (howto, input_section, contents,
-                         r_offset, r_addend, relocation, symname, symsec)
-     reloc_howto_type *howto;
-     asection *input_section;
-     bfd_byte *contents;
-     bfd_vma r_offset;
-     bfd_signed_vma r_addend;
-     bfd_vma relocation;
-     const char *symname;
-     asection *symsec;
+mmix_final_link_relocate (reloc_howto_type *howto, asection *input_section,
+                         bfd_byte *contents, bfd_vma r_offset,
+                         bfd_signed_vma r_addend, bfd_vma relocation,
+                         const char *symname, asection *symsec,
+                         char **error_message)
 {
   bfd_reloc_status_type r = bfd_reloc_ok;
   bfd_vma addr
@@ -1582,7 +1598,7 @@ mmix_final_link_relocate (howto, input_section, contents,
               + r_offset);
 
       r = mmix_elf_perform_relocation (input_section, howto, contents,
-                                      addr, srel);
+                                      addr, srel, error_message);
       break;
 
     case R_MMIX_BASE_PLUS_OFFSET:
@@ -1590,23 +1606,25 @@ mmix_final_link_relocate (howto, input_section, contents,
        return bfd_reloc_undefined;
 
       /* Check that we're not relocating against a register symbol.  */
-      if (strcmp (bfd_get_section_name (symsec->owner, symsec),
+      if (strcmp (bfd_section_name (symsec),
                  MMIX_REG_CONTENTS_SECTION_NAME) == 0
-         || strcmp (bfd_get_section_name (symsec->owner, symsec),
+         || strcmp (bfd_section_name (symsec),
                     MMIX_REG_SECTION_NAME) == 0)
        {
          /* Note: This is separated out into two messages in order
             to ease the translation into other languages.  */
          if (symname == NULL || *symname == 0)
-           (*_bfd_error_handler)
-             (_("%s: base-plus-offset relocation against register symbol: (unknown) in %s"),
-              bfd_get_filename (input_section->owner),
-              bfd_get_section_name (symsec->owner, symsec));
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: base-plus-offset relocation against register symbol:"
+                " (unknown) in %pA"),
+              input_section->owner, symsec);
          else
-           (*_bfd_error_handler)
-             (_("%s: base-plus-offset relocation against register symbol: %s in %s"),
-              bfd_get_filename (input_section->owner), symname,
-              bfd_get_section_name (symsec->owner, symsec));
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: base-plus-offset relocation against register symbol:"
+                " %s in %pA"),
+              input_section->owner, symname, symsec);
          return bfd_reloc_overflow;
        }
       goto do_mmix_reloc;
@@ -1623,7 +1641,7 @@ mmix_final_link_relocate (howto, input_section, contents,
       if (symsec == NULL)
        return bfd_reloc_undefined;
 
-      if (strcmp (bfd_get_section_name (symsec->owner, symsec),
+      if (strcmp (bfd_section_name (symsec),
                  MMIX_REG_CONTENTS_SECTION_NAME) == 0)
        {
          if ((srel & 7) != 0 || srel < 32*8 || srel > 255*8)
@@ -1634,7 +1652,7 @@ mmix_final_link_relocate (howto, input_section, contents,
            }
          srel /= 8;
        }
-      else if (strcmp (bfd_get_section_name (symsec->owner, symsec),
+      else if (strcmp (bfd_section_name (symsec),
                       MMIX_REG_SECTION_NAME) == 0)
        {
          if (srel < 0 || srel > 255)
@@ -1647,15 +1665,17 @@ mmix_final_link_relocate (howto, input_section, contents,
          /* Note: This is separated out into two messages in order
             to ease the translation into other languages.  */
          if (symname == NULL || *symname == 0)
-           (*_bfd_error_handler)
-             (_("%s: register relocation against non-register symbol: (unknown) in %s"),
-              bfd_get_filename (input_section->owner),
-              bfd_get_section_name (symsec->owner, symsec));
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: register relocation against non-register symbol:"
+                " (unknown) in %pA"),
+              input_section->owner, symsec);
          else
-           (*_bfd_error_handler)
-             (_("%s: register relocation against non-register symbol: %s in %s"),
-              bfd_get_filename (input_section->owner), symname,
-              bfd_get_section_name (symsec->owner, symsec));
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: register relocation against non-register symbol:"
+                " %s in %pA"),
+              input_section->owner, symname, symsec);
 
          /* The bfd_reloc_outofrange return value, though intuitively a
             better value, will not get us an error.  */
@@ -1664,7 +1684,7 @@ mmix_final_link_relocate (howto, input_section, contents,
     do_mmix_reloc:
       contents += r_offset;
       r = mmix_elf_perform_relocation (input_section, howto, contents,
-                                      addr, srel);
+                                      addr, srel, error_message);
       break;
 
     case R_MMIX_LOCAL:
@@ -1684,14 +1704,14 @@ mmix_final_link_relocate (howto, input_section, contents,
           accidentally handling it.  */
        if (!bfd_is_abs_section (symsec)
            && !bfd_is_und_section (symsec)
-           && strcmp (bfd_get_section_name (symsec->owner, symsec),
+           && strcmp (bfd_section_name (symsec),
                       MMIX_REG_CONTENTS_SECTION_NAME) != 0
-           && strcmp (bfd_get_section_name (symsec->owner, symsec),
+           && strcmp (bfd_section_name (symsec),
                       MMIX_REG_SECTION_NAME) != 0)
        {
-         (*_bfd_error_handler)
-           (_("%s: directive LOCAL valid only with a register or absolute value"),
-            bfd_get_filename (input_section->owner));
+         _bfd_error_handler
+           (_("%pB: directive LOCAL valid only with a register or absolute value"),
+            input_section->owner);
 
          return bfd_reloc_overflow;
        }
@@ -1702,8 +1722,8 @@ mmix_final_link_relocate (howto, input_section, contents,
        first_global = 255;
       else
        {
-         first_global = bfd_get_section_vma (abfd, regsec) / 8;
-         if (strcmp (bfd_get_section_name (symsec->owner, symsec),
+         first_global = bfd_section_vma (regsec) / 8;
+         if (strcmp (bfd_section_name (symsec),
                      MMIX_REG_CONTENTS_SECTION_NAME) == 0)
            {
              if ((srel & 7) != 0 || srel < 32*8 || srel > 255*8)
@@ -1717,9 +1737,12 @@ mmix_final_link_relocate (howto, input_section, contents,
        if ((bfd_vma) srel >= first_global)
          {
            /* FIXME: Better error message.  */
-           (*_bfd_error_handler)
-             (_("%s: LOCAL directive: Register $%ld is not a local register.  First global register is $%ld."),
-              bfd_get_filename (input_section->owner), (long) srel, (long) first_global);
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: LOCAL directive: "
+                "register $%" PRId64 " is not a local register;"
+                " first global register is $%" PRId64),
+              input_section->owner, (int64_t) srel, (int64_t) first_global);
 
            return bfd_reloc_overflow;
          }
@@ -1740,76 +1763,27 @@ mmix_final_link_relocate (howto, input_section, contents,
    relocation.  */
 
 static asection *
-mmix_elf_gc_mark_hook (sec, info, rel, h, sym)
-     asection *sec;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     Elf_Internal_Rela *rel;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+mmix_elf_gc_mark_hook (asection *sec,
+                      struct bfd_link_info *info,
+                      Elf_Internal_Rela *rel,
+                      struct elf_link_hash_entry *h,
+                      Elf_Internal_Sym *sym)
 {
   if (h != NULL)
-    {
-      switch (ELF64_R_TYPE (rel->r_info))
-       {
-       case R_MMIX_GNU_VTINHERIT:
-       case R_MMIX_GNU_VTENTRY:
-         break;
-
-       default:
-         switch (h->root.type)
-           {
-           case bfd_link_hash_defined:
-           case bfd_link_hash_defweak:
-             return h->root.u.def.section;
-
-           case bfd_link_hash_common:
-             return h->root.u.c.p->section;
-
-           default:
-             break;
-           }
-       }
-    }
-  else
-    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
-  return NULL;
-}
-
-/* Update relocation info for a GC-excluded section.  We could supposedly
-   perform the allocation after GC, but there's no suitable hook between
-   GC (or section merge) and the point when all input sections must be
-   present.  Better to waste some memory and (perhaps) a little time.  */
-
-static bfd_boolean
-mmix_elf_gc_sweep_hook (abfd, info, sec, relocs)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     asection *sec ATTRIBUTE_UNUSED;
-     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
-{
-  struct bpo_reloc_section_info *bpodata
-    = mmix_elf_section_data (sec)->bpo.reloc;
-  asection *allocated_gregs_section;
-
-  /* If no bpodata here, we have nothing to do.  */
-  if (bpodata == NULL)
-    return TRUE;
-
-  allocated_gregs_section = bpodata->bpo_greg_section;
-
-  mmix_elf_section_data (allocated_gregs_section)->bpo.greg->n_bpo_relocs
-    -= bpodata->n_bpo_relocs_this_section;
+    switch (ELF64_R_TYPE (rel->r_info))
+      {
+      case R_MMIX_GNU_VTINHERIT:
+      case R_MMIX_GNU_VTENTRY:
+       return NULL;
+      }
 
-  return TRUE;
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 \f
 /* Sort register relocs to come before expanding relocs.  */
 
 static int
-mmix_elf_sort_relocs (p1, p2)
-     const PTR p1;
-     const PTR p2;
+mmix_elf_sort_relocs (const void * p1, const void * p2)
 {
   const Elf_Internal_Rela *r1 = (const Elf_Internal_Rela *) p1;
   const Elf_Internal_Rela *r2 = (const Elf_Internal_Rela *) p2;
@@ -1842,11 +1816,10 @@ mmix_elf_sort_relocs (p1, p2)
 /* Subset of mmix_elf_check_relocs, common to ELF and mmo linking.  */
 
 static bfd_boolean
-mmix_elf_check_common_relocs  (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+mmix_elf_check_common_relocs  (bfd *abfd,
+                              struct bfd_link_info *info,
+                              asection *sec,
+                              const Elf_Internal_Rela *relocs)
 {
   bfd *bpo_greg_owner = NULL;
   asection *allocated_gregs_section = NULL;
@@ -1865,7 +1838,7 @@ mmix_elf_check_common_relocs  (abfd, info, sec, relocs)
   for (rel = relocs; rel < rel_end; rel++)
     {
       switch (ELF64_R_TYPE (rel->r_info))
-        {
+       {
          /* This relocation causes a GREG allocation.  We need to count
             them, and we need to create a section for them, so we need an
             object to fake as the owner of that section.  We can't use
@@ -1873,13 +1846,13 @@ mmix_elf_check_common_relocs  (abfd, info, sec, relocs)
             DSO-related stuff if that member is non-NULL.  */
        case R_MMIX_BASE_PLUS_OFFSET:
          /* We don't do anything with this reloc for a relocatable link.  */
-         if (info->relocatable)
+         if (bfd_link_relocatable (info))
            break;
 
          if (bpo_greg_owner == NULL)
            {
              bpo_greg_owner = abfd;
-             info->base_file = (PTR) bpo_greg_owner;
+             info->base_file = bpo_greg_owner;
            }
 
          if (allocated_gregs_section == NULL)
@@ -1901,9 +1874,7 @@ mmix_elf_check_common_relocs  (abfd, info, sec, relocs)
                 those flags, as that is what currently happens for usual
                 GREG allocations, and that works.  */
              if (allocated_gregs_section == NULL
-                 || !bfd_set_section_alignment (bpo_greg_owner,
-                                                allocated_gregs_section,
-                                                3))
+                 || !bfd_set_section_alignment (allocated_gregs_section, 3))
                return FALSE;
 
              gregdata = (struct bpo_greg_section_info *)
@@ -1975,33 +1946,29 @@ mmix_elf_check_common_relocs  (abfd, info, sec, relocs)
 /* Look through the relocs for a section during the first phase.  */
 
 static bfd_boolean
-mmix_elf_check_relocs (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+mmix_elf_check_relocs (bfd *abfd,
+                      struct bfd_link_info *info,
+                      asection *sec,
+                      const Elf_Internal_Rela *relocs)
 {
   Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+  struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
-  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf64_External_Sym);
-  if (!elf_bad_symtab (abfd))
-    sym_hashes_end -= symtab_hdr->sh_info;
 
   /* First we sort the relocs so that any register relocs come before
      expansion-relocs to the same insn.  FIXME: Not done for mmo.  */
-  qsort ((PTR) relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
+  qsort ((void *) relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
         mmix_elf_sort_relocs);
 
   /* Do the common part.  */
   if (!mmix_elf_check_common_relocs (abfd, info, sec, relocs))
     return FALSE;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   rel_end = relocs + sec->reloc_count;
@@ -2012,25 +1979,30 @@ mmix_elf_check_relocs (abfd, info, sec, relocs)
 
       r_symndx = ELF64_R_SYM (rel->r_info);
       if (r_symndx < symtab_hdr->sh_info)
-        h = NULL;
+       h = NULL;
       else
-        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+       {
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+       }
 
       switch (ELF64_R_TYPE (rel->r_info))
        {
-        /* This relocation describes the C++ object vtable hierarchy.
-           Reconstruct it for later use during GC.  */
-        case R_MMIX_GNU_VTINHERIT:
-          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-            return FALSE;
-          break;
-
-        /* This relocation describes which C++ vtable entries are actually
-           used.  Record for later use during GC.  */
-        case R_MMIX_GNU_VTENTRY:
-          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-            return FALSE;
-          break;
+       /* This relocation describes the C++ object vtable hierarchy.
+          Reconstruct it for later use during GC.  */
+       case R_MMIX_GNU_VTINHERIT:
+         if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+           return FALSE;
+         break;
+
+       /* This relocation describes which C++ vtable entries are actually
+          used.  Record for later use during GC.  */
+       case R_MMIX_GNU_VTENTRY:
+         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+           return FALSE;
+         break;
        }
     }
 
@@ -2041,9 +2013,7 @@ mmix_elf_check_relocs (abfd, info, sec, relocs)
    Copied from elf_link_add_object_symbols.  */
 
 bfd_boolean
-_bfd_mmix_check_all_relocs (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_mmix_check_all_relocs (bfd *abfd, struct bfd_link_info *info)
 {
   asection *o;
 
@@ -2060,7 +2030,7 @@ _bfd_mmix_check_all_relocs (abfd, info)
        continue;
 
       internal_relocs
-       = _bfd_elf_link_read_relocs (abfd, o, (PTR) NULL,
+       = _bfd_elf_link_read_relocs (abfd, o, NULL,
                                     (Elf_Internal_Rela *) NULL,
                                     info->keep_memory);
       if (internal_relocs == NULL)
@@ -2082,13 +2052,12 @@ _bfd_mmix_check_all_relocs (abfd, info)
    the register section, and scale them down to correspond to the register
    number.  */
 
-static bfd_boolean
-mmix_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     const char *name ATTRIBUTE_UNUSED;
-     Elf_Internal_Sym *sym;
-     asection *input_sec;
-     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED;
+static int
+mmix_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                                 const char *name ATTRIBUTE_UNUSED,
+                                 Elf_Internal_Sym *sym,
+                                 asection *input_sec,
+                                 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
 {
   if (input_sec != NULL
       && input_sec->name != NULL
@@ -2099,7 +2068,7 @@ mmix_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
       sym->st_shndx = SHN_REGISTER;
     }
 
-  return TRUE;
+  return 1;
 }
 
 /* We fake a register section that holds values that are register numbers.
@@ -2113,9 +2082,7 @@ static asymbol *mmix_elf_reg_section_symbol_ptr;
 /* Handle the special section numbers that a symbol may use.  */
 
 void
-mmix_elf_symbol_processing (abfd, asym)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asymbol *asym;
+mmix_elf_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *asym)
 {
   elf_symbol_type *elfsym;
 
@@ -2148,12 +2115,11 @@ mmix_elf_symbol_processing (abfd, asym)
    index.  */
 
 static bfd_boolean
-mmix_elf_section_from_bfd_section (abfd, sec, retval)
-     bfd *                 abfd ATTRIBUTE_UNUSED;
-     asection *            sec;
-     int *                 retval;
+mmix_elf_section_from_bfd_section (bfd *       abfd ATTRIBUTE_UNUSED,
+                                  asection *  sec,
+                                  int *       retval)
 {
-  if (strcmp (bfd_get_section_name (abfd, sec), MMIX_REG_SECTION_NAME) == 0)
+  if (strcmp (bfd_section_name (sec), MMIX_REG_SECTION_NAME) == 0)
     *retval = SHN_REGISTER;
   else
     return FALSE;
@@ -2168,21 +2134,22 @@ mmix_elf_section_from_bfd_section (abfd, sec, retval)
    symbols, since otherwise having two with the same value would cause
    them to be "merged", but with the contents serialized.  */
 
-bfd_boolean
-mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
-     bfd *abfd;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     Elf_Internal_Sym *sym;
-     const char **namep ATTRIBUTE_UNUSED;
-     flagword *flagsp ATTRIBUTE_UNUSED;
-     asection **secp;
-     bfd_vma *valp ATTRIBUTE_UNUSED;
+static bfd_boolean
+mmix_elf_add_symbol_hook (bfd *abfd,
+                         struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                         Elf_Internal_Sym *sym,
+                         const char **namep ATTRIBUTE_UNUSED,
+                         flagword *flagsp ATTRIBUTE_UNUSED,
+                         asection **secp,
+                         bfd_vma *valp ATTRIBUTE_UNUSED)
 {
   if (sym->st_shndx == SHN_REGISTER)
-    *secp = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
+    {
+      *secp = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
+      (*secp)->flags |= SEC_LINKER_CREATED;
+    }
   else if ((*namep)[0] == '_' && (*namep)[1] == '_' && (*namep)[2] == '.'
-          && strncmp (*namep, MMIX_LOC_SECTION_START_SYMBOL_PREFIX,
-                      strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX)) == 0)
+          && CONST_STRNEQ (*namep, MMIX_LOC_SECTION_START_SYMBOL_PREFIX))
     {
       /* See if we have another one.  */
       struct bfd_link_hash_entry *h = bfd_link_hash_lookup (info->hash,
@@ -2195,10 +2162,12 @@ mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
        {
          /* How do we get the asymbol (or really: the filename) from h?
             h->u.def.section->owner is NULL.  */
-         ((*_bfd_error_handler)
-          (_("%s: Error: multiple definition of `%s'; start of %s is set in a earlier linked file\n"),
-           bfd_get_filename (abfd), *namep,
-           *namep + strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX)));
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%pB: error: multiple definition of `%s'; start of %s "
+              "is set in a earlier linked file"),
+            abfd, *namep,
+            *namep + strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX));
           bfd_set_error (bfd_error_bad_value);
           return FALSE;
        }
@@ -2209,10 +2178,8 @@ mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 
 /* We consider symbols matching "L.*:[0-9]+" to be local symbols.  */
 
-bfd_boolean
-mmix_elf_is_local_label_name (abfd, name)
-     bfd *abfd;
-     const char *name;
+static bfd_boolean
+mmix_elf_is_local_label_name (bfd *abfd, const char *name)
 {
   const char *colpos;
   int digits;
@@ -2240,9 +2207,7 @@ mmix_elf_is_local_label_name (abfd, name)
 /* We get rid of the register section here.  */
 
 bfd_boolean
-mmix_elf_final_link (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+mmix_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 {
   /* We never output a register section, though we create one for
      temporary measures.  Check that nobody entered contents into it.  */
@@ -2253,12 +2218,15 @@ mmix_elf_final_link (abfd, info)
   if (reg_section != NULL)
     {
       /* FIXME: Pass error state gracefully.  */
-      if (bfd_get_section_flags (abfd, reg_section) & SEC_HAS_CONTENTS)
-       _bfd_abort (__FILE__, __LINE__, _("Register section has contents\n"));
+      if (bfd_section_flags (reg_section) & SEC_HAS_CONTENTS)
+       _bfd_abort (__FILE__, __LINE__, _("register section has contents\n"));
 
-      /* Really remove the section.  */
-      bfd_section_list_remove (abfd, reg_section);
-      --abfd->section_count;
+      /* Really remove the section, if it hasn't already been done.  */
+      if (!bfd_section_removed_from_list (abfd, reg_section))
+       {
+         bfd_section_list_remove (abfd, reg_section);
+         --abfd->section_count;
+       }
     }
 
   if (! bfd_elf_final_link (abfd, info))
@@ -2286,10 +2254,9 @@ mmix_elf_final_link (abfd, info)
    section size.  This is expected to shrink during linker relaxation.  */
 
 static void
-mmix_set_relaxable_size (abfd, sec, ptr)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *sec;
-     void *ptr;
+mmix_set_relaxable_size (bfd *abfd ATTRIBUTE_UNUSED,
+                        asection *sec,
+                        void *ptr)
 {
   struct bfd_link_info *info = ptr;
 
@@ -2304,7 +2271,7 @@ mmix_set_relaxable_size (abfd, sec, ptr)
 
   /* For use in relocatable link, we start with a max stubs size.  See
      mmix_elf_relax_section.  */
-  if (info->relocatable && sec->output_section)
+  if (bfd_link_relocatable (info) && sec->output_section)
     mmix_elf_section_data (sec->output_section)->pjs.stubs_size_sum
       += (mmix_elf_section_data (sec)->pjs.n_pushj_relocs
          * MAX_PUSHJ_STUB_SIZE);
@@ -2314,9 +2281,8 @@ mmix_set_relaxable_size (abfd, sec, ptr)
    R_MMIX_BASE_PLUS_OFFSET relocs seen by the linker.  */
 
 bfd_boolean
-_bfd_mmix_before_linker_allocation (abfd, info)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+_bfd_mmix_before_linker_allocation (bfd *abfd ATTRIBUTE_UNUSED,
+                                   struct bfd_link_info *info)
 {
   asection *bpo_gregs_section;
   bfd *bpo_greg_owner;
@@ -2328,7 +2294,7 @@ _bfd_mmix_before_linker_allocation (abfd, info)
   bfd *ibfd;
 
   /* Set the initial size of sections.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     bfd_map_over_sections (ibfd, mmix_set_relaxable_size, info);
 
   /* The bpo_greg_owner bfd is supposed to have been set by
@@ -2360,7 +2326,7 @@ _bfd_mmix_before_linker_allocation (abfd, info)
   /* Set the zeroth-order estimate for the GREGs size.  */
   gregs_size = n_gregs * 8;
 
-  if (!bfd_set_section_size (bpo_greg_owner, bpo_gregs_section, gregs_size))
+  if (!bfd_set_section_size (bpo_gregs_section, gregs_size))
     return FALSE;
 
   /* Allocate and set up the GREG arrays.  They're filled in at relaxation
@@ -2393,9 +2359,8 @@ _bfd_mmix_before_linker_allocation (abfd, info)
    calculated at this point; we just move the contents into place here.  */
 
 bfd_boolean
-_bfd_mmix_after_linker_allocation (abfd, link_info)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *link_info;
+_bfd_mmix_after_linker_allocation (bfd *abfd ATTRIBUTE_UNUSED,
+                                  struct bfd_link_info *link_info)
 {
   asection *bpo_gregs_section;
   bfd *bpo_greg_owner;
@@ -2442,11 +2407,12 @@ _bfd_mmix_after_linker_allocation (abfd, link_info)
   if (gregdata->n_remaining_bpo_relocs_this_relaxation_round
       != gregdata->n_bpo_relocs)
     {
-      (*_bfd_error_handler)
-       (_("Internal inconsistency: remaining %u != max %u.\n\
-  Please report this bug."),
-        gregdata->n_remaining_bpo_relocs_this_relaxation_round,
-        gregdata->n_bpo_relocs);
+      _bfd_error_handler
+       /* xgettext:c-format */
+       (_("internal inconsistency: remaining %lu != max %lu;"
+          " please report this bug"),
+        (unsigned long) gregdata->n_remaining_bpo_relocs_this_relaxation_round,
+        (unsigned long) gregdata->n_bpo_relocs);
       return FALSE;
     }
 
@@ -2466,9 +2432,7 @@ _bfd_mmix_after_linker_allocation (abfd, link_info)
    value.  */
 
 static int
-bpo_reloc_request_sort_fn (p1, p2)
-     const PTR p1;
-     const PTR p2;
+bpo_reloc_request_sort_fn (const void * p1, const void * p2)
 {
   const struct bpo_reloc_request *r1 = (const struct bpo_reloc_request *) p1;
   const struct bpo_reloc_request *r2 = (const struct bpo_reloc_request *) p2;
@@ -2496,9 +2460,8 @@ bpo_reloc_request_sort_fn (p1, p2)
    from base-plus-offset relocs.  */
 
 void
-mmix_dump_bpo_gregs (link_info, pf)
-     struct bfd_link_info *link_info;
-     bfd_error_handler_type pf;
+mmix_dump_bpo_gregs (struct bfd_link_info *link_info,
+                    void (*pf) (const char *fmt, ...))
 {
   bfd *bpo_greg_owner;
   asection *bpo_gregs_section;
@@ -2552,18 +2515,17 @@ mmix_dump_bpo_gregs (link_info, pf)
    when the last such reloc is done, an index-array is sorted according to
    the values and iterated over to produce register numbers (indexed by 0
    from the first allocated register number) and offsets for use in real
-   relocation.
+   relocation.  (N.B.: Relocatable runs are handled, not just punted.)
 
    PUSHJ stub accounting is also done here.
 
    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
 
 static bfd_boolean
-mmix_elf_relax_section (abfd, sec, link_info, again)
-     bfd *abfd;
-     asection *sec;
-     struct bfd_link_info *link_info;
-     bfd_boolean *again;
+mmix_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;
@@ -2576,7 +2538,6 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
      spot a missing actual initialization.  */
   size_t bpono = (size_t) -1;
   size_t pjsno = 0;
-  bfd *bpo_greg_owner;
   Elf_Internal_Sym *isymbuf = NULL;
   bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
 
@@ -2592,15 +2553,13 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
       || (sec->flags & SEC_CODE) == 0
       || (sec->flags & SEC_LINKER_CREATED) != 0
       /* If no R_MMIX_BASE_PLUS_OFFSET relocs and no PUSHJ-stub relocs,
-         then nothing to do.  */
+        then nothing to do.  */
       || (bpodata == NULL
          && mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0))
     return TRUE;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
-  bpo_greg_owner = (bfd *) link_info->base_file;
-
   if (bpodata != NULL)
     {
       bpo_gregs_section = bpodata->bpo_greg_section;
@@ -2612,7 +2571,7 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
 
   /* Get a copy of the native relocations.  */
   internal_relocs
-    = _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL,
+    = _bfd_elf_link_read_relocs (abfd, sec, NULL,
                                 (Elf_Internal_Rela *) NULL,
                                 link_info->keep_memory);
   if (internal_relocs == NULL)
@@ -2633,7 +2592,7 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
       /* We process relocs in a distinctly different way when this is a
         relocatable link (for one, we don't look at symbols), so we avoid
         mixing its code with that for the "normal" relaxation.  */
-      if (link_info->relocatable)
+      if (bfd_link_relocatable (link_info))
        {
          /* The only transformation in a relocatable link is to generate
             a full stub at the location of the stub calculated for the
@@ -2718,8 +2677,21 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
          indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
          h = elf_sym_hashes (abfd)[indx];
          BFD_ASSERT (h != NULL);
-         if (h->root.type != bfd_link_hash_defined
-             && h->root.type != bfd_link_hash_defweak)
+         if (h->root.type == bfd_link_hash_undefweak)
+           /* FIXME: for R_MMIX_PUSHJ_STUBBABLE, there are alternatives to
+              the canonical value 0 for an unresolved weak symbol to
+              consider: as the debug-friendly approach, resolve to "abort"
+              (or a port-specific function), or as the space-friendly
+              approach resolve to the next instruction (like some other
+              ports, notably ARM and AArch64).  These alternatives require
+              matching code in mmix_elf_perform_relocation or its caller.  */
+           symval = 0;
+         else if (h->root.type == bfd_link_hash_defined
+                  || h->root.type == bfd_link_hash_defweak)
+           symval = (h->root.u.def.value
+                     + h->root.u.def.section->output_section->vma
+                     + h->root.u.def.section->output_offset);
+         else
            {
              /* This appears to be a reference to an undefined symbol.  Just
                 ignore it--it will be caught by the regular reloc processing.
@@ -2733,10 +2705,6 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
                }
              continue;
            }
-
-         symval = (h->root.u.def.value
-                   + h->root.u.def.section->output_section->vma
-                   + h->root.u.def.section->output_offset);
        }
 
       if (ELF64_R_TYPE (irel->r_info) == (int) R_MMIX_PUSHJ_STUBBABLE)
@@ -2816,7 +2784,7 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
       gregdata->n_remaining_bpo_relocs_this_relaxation_round
        = gregdata->n_bpo_relocs;
 
-      qsort ((PTR) gregdata->reloc_request,
+      qsort (gregdata->reloc_request,
             gregdata->n_max_bpo_relocs,
             sizeof (struct bpo_reloc_request),
             bpo_reloc_request_sort_fn);
@@ -2874,8 +2842,9 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
        }
     }
 
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
+  BFD_ASSERT(pjsno == mmix_elf_section_data (sec)->pjs.n_pushj_relocs);
+
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
 
   if (sec->size < size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
@@ -2890,16 +2859,15 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
   return TRUE;
 
  error_return:
-  if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
+  if ((unsigned char *) isymbuf != symtab_hdr->contents)
     free (isymbuf);
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
   return FALSE;
 }
 \f
 #define ELF_ARCH               bfd_arch_mmix
-#define ELF_MACHINE_CODE       EM_MMIX
+#define ELF_MACHINE_CODE       EM_MMIX
 
 /* According to mmix-doc page 36 (paragraph 45), this should be (1LL << 48LL).
    However, that's too much for something somewhere in the linker part of
@@ -2915,14 +2883,13 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
    alignment.  */
 #define ELF_MAXPAGESIZE 0x100
 
-#define TARGET_BIG_SYM         bfd_elf64_mmix_vec
+#define TARGET_BIG_SYM         mmix_elf64_vec
 #define TARGET_BIG_NAME                "elf64-mmix"
 
 #define elf_info_to_howto_rel          NULL
 #define elf_info_to_howto              mmix_info_to_howto_rela
 #define elf_backend_relocate_section   mmix_elf_relocate_section
 #define elf_backend_gc_mark_hook       mmix_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook      mmix_elf_gc_sweep_hook
 
 #define elf_backend_link_output_symbol_hook \
        mmix_elf_link_output_symbol_hook
@@ -2930,6 +2897,10 @@ mmix_elf_relax_section (abfd, sec, link_info, again)
 
 #define elf_backend_check_relocs       mmix_elf_check_relocs
 #define elf_backend_symbol_processing  mmix_elf_symbol_processing
+#define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
+
+#define bfd_elf64_bfd_copy_link_hash_symbol_type \
+  _bfd_generic_copy_link_hash_symbol_type
 
 #define bfd_elf64_bfd_is_local_label_name \
        mmix_elf_is_local_label_name
This page took 0.048839 seconds and 4 git commands to generate.