gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / bfd / elf32-score.c
index 1246e26156d619dcbddb97d6c3cb59a58fb6d1eb..d1a910f2795e9701fd96b291183bf9411164948f 100644 (file)
@@ -1,6 +1,7 @@
 /* 32-bit ELF support for S+core.
-   Copyright 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006-2020 Free Software Foundation, Inc.
    Contributed by
+   Brain.lin (brain.lin@sunplusct.com)
    Mei Ligang (ligang@sunnorth.com.cn)
    Pei-Lin Tsai (pltsai@sunplus.com)
 
@@ -8,7 +9,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "libiberty.h"
 #include "elf-bfd.h"
 #include "elf/common.h"
 #include "elf/internal.h"
 #include "hashtab.h"
+#include "elf32-score.h"
 
 
-/* Score ELF linker hash table.  */
-
-struct score_elf_link_hash_table
-{
-  /* The main hash table.  */
-  struct elf_link_hash_table root;
-};
+int score3 = 0;
+int score7 = 1;
 
 /* The SCORE ELF linker needs additional information for each symbol in
    the global hash table.  */
-
 struct score_elf_link_hash_entry
 {
   struct elf_link_hash_entry root;
@@ -64,14 +61,10 @@ struct score_elf_link_hash_entry
 /* Traverse a score ELF linker hash table.  */
 #define score_elf_link_hash_traverse(table, func, info) \
   (elf_link_hash_traverse \
-   (&(table)->root, \
+   ((table),                                                        \
     (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \
     (info)))
 
-/* Get the SCORE elf linker hash table from a link_info structure.  */
-#define score_elf_hash_table(info) \
-  ((struct score_elf_link_hash_table *) ((info)->hash))
-
 /* This structure is used to hold .got entries while estimating got sizes.  */
 struct score_got_entry
 {
@@ -174,7 +167,7 @@ struct _score_elf_section_data
 #define SCORE_ELF_STUB_SECTION_NAME  (".SCORE.stub")
 #define SCORE_FUNCTION_STUB_SIZE (16)
 
-#define STUB_LW             0xc3bcc010     /* lw r29, [r28, -0x3ff0]  */
+#define STUB_LW      0xc3bcc010     /* lw r29, [r28, -0x3ff0]  */
 #define STUB_MOVE    0x8363bc56     /* mv r27, r3  */
 #define STUB_LI16    0x87548000     /* ori r26, .dynsym_index  */
 #define STUB_BRL     0x801dbc09     /* brl r29  */
@@ -183,7 +176,7 @@ struct _score_elf_section_data
   (get_elf_backend_data (abfd)->s->arch_size / 8)
 
 #define SCORE_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \
-        (_bfd_elf_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
+       (_bfd_elf_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val))
 
 /* The size of an external dynamic table entry.  */
 #define SCORE_ELF_DYN_SIZE(abfd) \
@@ -197,10 +190,6 @@ struct _score_elf_section_data
 #define SCORE_ELF_LOG_FILE_ALIGN(abfd)\
   (get_elf_backend_data (abfd)->s->log_file_align)
 
-#ifndef NUM_ELEM
-#define NUM_ELEM(a)  (sizeof (a) / (sizeof (a)[0]))
-#endif
-
 static bfd_byte *hi16_rel_addr;
 
 /* This will be used when we sort the dynamic relocation records.  */
@@ -215,6 +204,104 @@ static asection score_elf_scom_section;
 static asymbol  score_elf_scom_symbol;
 static asymbol  *score_elf_scom_symbol_ptr;
 
+static bfd_vma
+score_bfd_get_16 (bfd *abfd, const void *data)
+{
+  return bfd_get_16 (abfd, data);
+}
+
+static bfd_vma
+score3_bfd_getl32 (const void *p)
+{
+  const bfd_byte *addr = p;
+  unsigned long v;
+
+  v = (unsigned long) addr[2];
+  v |= (unsigned long) addr[3] << 8;
+  v |= (unsigned long) addr[0] << 16;
+  v |= (unsigned long) addr[1] << 24;
+  return v;
+}
+
+static bfd_vma
+score3_bfd_getl48 (const void *p)
+{
+  const bfd_byte *addr = p;
+  bfd_uint64_t v;
+
+  v = (bfd_uint64_t) addr[4];
+  v |= (bfd_uint64_t) addr[5] << 8;
+  v |= (bfd_uint64_t) addr[2] << 16;
+  v |= (bfd_uint64_t) addr[3] << 24;
+  v |= (bfd_uint64_t) addr[0] << 32;
+  v |= (bfd_uint64_t) addr[1] << 40;
+  return v;
+}
+
+static bfd_vma
+score_bfd_get_32 (bfd *abfd, const void *data)
+{
+  if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
+    return score3_bfd_getl32 (data);
+  else
+    return bfd_get_32 (abfd, data);
+}
+
+static bfd_vma
+score_bfd_get_48 (bfd *abfd, const void *p)
+{
+  if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
+    return score3_bfd_getl48 (p);
+  else
+    return bfd_get_bits (p, 48, 1);
+}
+
+static void
+score_bfd_put_16 (bfd *abfd, bfd_vma addr, void *data)
+{
+  return bfd_put_16 (abfd, addr, data);
+}
+
+static void
+score3_bfd_putl32 (bfd_vma data, void *p)
+{
+  bfd_byte *addr = p;
+  addr[0] = (data >> 16) & 0xff;
+  addr[1] = (data >> 24) & 0xff;
+  addr[2] = data & 0xff;
+  addr[3] = (data >>  8) & 0xff;
+}
+
+static void
+score3_bfd_putl48 (bfd_vma data, void *p)
+{
+  bfd_byte *addr = p;
+  addr[0] = (data >> 32) & 0xff;
+  addr[1] = (data >> 40) & 0xff;
+  addr[2] = (data >> 16) & 0xff;
+  addr[3] = (data >> 24) & 0xff;
+  addr[4] = data & 0xff;
+  addr[5] = (data >>  8) & 0xff;
+}
+
+static void
+score_bfd_put_32 (bfd *abfd, bfd_vma addr, void *data)
+{
+  if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
+    return score3_bfd_putl32 (addr, data);
+  else
+    return bfd_put_32 (abfd, addr, data);
+}
+
+static void
+score_bfd_put_48 (bfd *abfd, bfd_vma val, void *p)
+{
+  if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
+    return score3_bfd_putl48 (val, p);
+  else
+    return bfd_put_bits (val, p, 48, 1);
+}
+
 static bfd_reloc_status_type
 score_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                      arelent *reloc_entry,
@@ -241,9 +328,9 @@ score_elf_lo16_reloc (bfd *abfd,
   unsigned long val;
   unsigned long hi16_offset, hi16_value, uvalue;
 
-  hi16_value = bfd_get_32 (abfd, hi16_rel_addr);
+  hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr);
   hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
-  addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+  addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
   offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
   val = reloc_entry->addend;
   if (reloc_entry->address > input_section->size)
@@ -251,10 +338,10 @@ score_elf_lo16_reloc (bfd *abfd,
   uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
   hi16_offset = (uvalue >> 16) << 1;
   hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
-  bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
+  score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
   offset = (uvalue & 0xffff) << 1;
   addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
-  bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
+  score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
   return bfd_reloc_ok;
 }
 
@@ -312,12 +399,11 @@ score_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp)
    BFD.  If we can't find it, we're stuck.  We cache it in the ELF
    target data.  We don't need to adjust the symbol value for an
    external symbol if we are producing relocatable output.  */
-
 static bfd_reloc_status_type
 score_elf_final_gp (bfd *output_bfd,
                    asymbol *symbol,
                    bfd_boolean relocatable,
-                   char **error_message,
+                    char **error_message,
                    bfd_vma *pgp)
 {
   if (bfd_is_und_section (symbol->section)
@@ -371,13 +457,13 @@ score_elf_gprel15_with_gp (bfd *abfd,
   if (reloc_entry->address > input_section->size)
     return bfd_reloc_outofrange;
 
-  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+  insn = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
   if (((reloc_entry->addend & 0xffffc000) != 0)
       && ((reloc_entry->addend & 0xffffc000) != 0xffffc000))
     return bfd_reloc_overflow;
 
   insn = (insn & ~0x7fff) | (reloc_entry->addend & 0x7fff);
-  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+  score_bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
   if (relocateable)
     reloc_entry->address += input_section->output_offset;
 
@@ -407,7 +493,7 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry,
   val = reloc_entry->addend;
 
   if (reloc_entry->howto->partial_inplace)
-    val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+    val += score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
 
   /* Adjust val for the final section location and GP value.  If we
      are producing relocatable output, we don't want to do this for
@@ -417,7 +503,7 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry,
     val += relocation - gp;
 
   if (reloc_entry->howto->partial_inplace)
-    bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
+    score_bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
   else
     reloc_entry->addend = val;
 
@@ -440,13 +526,13 @@ score_elf_gprel15_reloc (bfd *abfd,
   bfd_reloc_status_type ret;
   bfd_vma gp;
 
-  if (output_bfd != (bfd *) NULL
+  if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
-  if (output_bfd != (bfd *) NULL)
+  if (output_bfd != NULL)
     relocateable = TRUE;
   else
     {
@@ -459,7 +545,7 @@ score_elf_gprel15_reloc (bfd *abfd,
     return ret;
 
   return score_elf_gprel15_with_gp (abfd, symbol, reloc_entry,
-                                         input_section, relocateable, data, gp);
+                                        input_section, relocateable, data, gp);
 }
 
 /* Do a R_SCORE_GPREL32 relocation.  This is a 32 bit value which must
@@ -496,7 +582,7 @@ score_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   if (ret != bfd_reloc_ok)
     return ret;
 
-  gp = 0;   /* FIXME.  */
+  gp = 0;
   return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
                          relocatable, data, gp);
 }
@@ -504,15 +590,14 @@ score_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 /* A howto special_function for R_SCORE_GOT15 relocations.  This is just
    like any other 16-bit relocation when applied to global symbols, but is
    treated in the same as R_SCORE_HI16 when applied to local symbols.  */
-
 static bfd_reloc_status_type
 score_elf_got15_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
                       void *data, asection *input_section,
                       bfd *output_bfd, char **error_message)
 {
   if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
-      || bfd_is_und_section (bfd_get_section (symbol))
-      || bfd_is_com_section (bfd_get_section (symbol)))
+      || bfd_is_und_section (bfd_asymbol_section (symbol))
+      || bfd_is_com_section (bfd_asymbol_section (symbol)))
     /* The relocation is against a global symbol.  */
     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
                                  input_section, output_bfd,
@@ -524,20 +609,20 @@ score_elf_got15_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 score_elf_got_lo16_reloc (bfd *abfd,
-                         arelent *reloc_entry,
-                         asymbol *symbol ATTRIBUTE_UNUSED,
-                         void * data,
-                         asection *input_section,
-                         bfd *output_bfd ATTRIBUTE_UNUSED,
-                         char **error_message ATTRIBUTE_UNUSED)
+                         arelent *reloc_entry,
+                         asymbol *symbol ATTRIBUTE_UNUSED,
+                         void * data,
+                         asection *input_section,
+                         bfd *output_bfd ATTRIBUTE_UNUSED,
+                         char **error_message ATTRIBUTE_UNUSED)
 {
   bfd_vma addend = 0, offset = 0;
   signed long val;
   signed long hi16_offset, hi16_value, uvalue;
 
-  hi16_value = bfd_get_32 (abfd, hi16_rel_addr);
+  hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr);
   hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
-  addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+  addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
   offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
   val = reloc_entry->addend;
   if (reloc_entry->address > input_section->size)
@@ -548,314 +633,344 @@ score_elf_got_lo16_reloc (bfd *abfd,
   else
     hi16_offset = (uvalue >> 16) & 0x7fff;
   hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
-  bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
+  score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
   offset = (uvalue & 0xffff) << 1;
   addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
-  bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
+  score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address);
   return bfd_reloc_ok;
 }
 
 static reloc_howto_type elf32_score_howto_table[] =
 {
   /* No relocation.  */
-  HOWTO (R_SCORE_NONE,          /* type */
-         0,                     /* rightshift */
-         0,                     /* size (0 = byte, 1 = short, 2 = long) */
-         0,                     /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE_NONE",        /* name */
-         FALSE,                 /* partial_inplace */
-         0,                     /* src_mask */
-         0,                     /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_NONE,         /* type */
+        0,                     /* rightshift */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_NONE",        /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* R_SCORE_HI16 */
-  HOWTO (R_SCORE_HI16,          /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         1,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-        score_elf_hi16_reloc,  /* special_function */
-         "R_SCORE_HI16",        /* name */
-         TRUE,                  /* partial_inplace */
-         0x37fff,               /* src_mask */
-         0x37fff,               /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_HI16,         /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        1,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        score_elf_hi16_reloc,  /* special_function */
+        "R_SCORE_HI16",        /* name */
+        TRUE,                  /* partial_inplace */
+        0x37fff,               /* src_mask */
+        0x37fff,               /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* R_SCORE_LO16 */
-  HOWTO (R_SCORE_LO16,          /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         1,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         score_elf_lo16_reloc,  /* special_function */
-         "R_SCORE_LO16",        /* name */
-         TRUE,                  /* partial_inplace */
-         0x37fff,               /* src_mask */
-         0x37fff,               /* dst_mask */
-         FALSE),                /* pcrel_offset */
-
-  /*  R_SCORE_DUMMY1 */
-  HOWTO (R_SCORE_DUMMY1,        /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         1,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE_DUMMY1",      /* name */
-         TRUE,                  /* partial_inplace */
-         0x0000ffff,            /* src_mask */
-         0x0000ffff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_LO16,         /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        1,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        score_elf_lo16_reloc,  /* special_function */
+        "R_SCORE_LO16",        /* name */
+        TRUE,                  /* partial_inplace */
+        0x37fff,               /* src_mask */
+        0x37fff,               /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /*  R_SCORE_BCMP */
+  HOWTO (R_SCORE_BCMP,         /* type */
+        1,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        TRUE,                  /* pc_relative */
+        1,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_BCMP",        /* name */
+        FALSE,                 /* partial_inplace */
+        0x03e00381,            /* src_mask */
+        0x03e00381,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /*R_SCORE_24 */
-  HOWTO (R_SCORE_24,            /* type */
-         1,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         24,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         1,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE_24",          /* name */
-         FALSE,                 /* partial_inplace */
-         0x3ff7fff,             /* src_mask */
-         0x3ff7fff,             /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_24,           /* type */
+        1,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        24,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        1,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_24",          /* name */
+        FALSE,                 /* partial_inplace */
+        0x3ff7fff,             /* src_mask */
+        0x3ff7fff,             /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /*R_SCORE_PC19 */
-  HOWTO (R_SCORE_PC19,          /* type */
-         1,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         19,                    /* bitsize */
-         TRUE,                  /* pc_relative */
-         1,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE_PC19",        /* name */
-         FALSE,                 /* partial_inplace */
-         0x3ff03fe,             /* src_mask */
-         0x3ff03fe,             /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_PC19,         /* type */
+        1,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        19,                    /* bitsize */
+        TRUE,                  /* pc_relative */
+        1,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_PC19",        /* name */
+        FALSE,                 /* partial_inplace */
+        0x3ff03fe,             /* src_mask */
+        0x3ff03fe,             /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /*R_SCORE16_11 */
-  HOWTO (R_SCORE16_11,          /* type */
-         1,                     /* rightshift */
-         1,                     /* size (0 = byte, 1 = short, 2 = long) */
-         11,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         1,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE16_11",        /* name */
-         FALSE,                 /* partial_inplace */
-         0x000000ffe,           /* src_mask */
-         0x000000ffe,           /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE16_11,         /* type */
+        1,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        11,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        1,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE16_11",        /* name */
+        FALSE,                 /* partial_inplace */
+        0x000000ffe,           /* src_mask */
+        0x000000ffe,           /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* R_SCORE16_PC8 */
-  HOWTO (R_SCORE16_PC8,         /* type */
-         1,                     /* rightshift */
-         1,                     /* size (0 = byte, 1 = short, 2 = long) */
-         8,                     /* bitsize */
-         TRUE,                  /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE16_PC8",       /* name */
-         FALSE,                 /* partial_inplace */
-         0x000000ff,            /* src_mask */
-         0x000000ff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE16_PC8,                /* type */
+        1,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        9,                     /* bitsize */
+        TRUE,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE16_PC8",       /* name */
+        FALSE,                 /* partial_inplace */
+        0x000001ff,            /* src_mask */
+        0x000001ff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* 32 bit absolute */
-  HOWTO (R_SCORE_ABS32,         /* type  8 */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         32,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_bitfield,    /* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE_ABS32",       /* name */
-         FALSE,                 /* partial_inplace */
-         0xffffffff,            /* src_mask */
-         0xffffffff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_ABS32,                /* type  8 */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield,    /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_ABS32",       /* name */
+        FALSE,                 /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* 16 bit absolute */
-  HOWTO (R_SCORE_ABS16,         /* type 11 */
-         0,                     /* rightshift */
-         1,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_bitfield,    /* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE_ABS16",       /* name */
-         FALSE,                 /* partial_inplace */
-         0x0000ffff,            /* src_mask */
-         0x0000ffff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_ABS16,                /* type 11 */
+        0,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield,    /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_ABS16",       /* name */
+        FALSE,                 /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* R_SCORE_DUMMY2 */
-  HOWTO (R_SCORE_DUMMY2,        /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE_DUMMY2",      /* name */
-         TRUE,                  /* partial_inplace */
-         0x00007fff,            /* src_mask */
-         0x00007fff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_DUMMY2,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_DUMMY2",      /* name */
+        TRUE,                  /* partial_inplace */
+        0x00007fff,            /* src_mask */
+        0x00007fff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* R_SCORE_GP15 */
-  HOWTO (R_SCORE_GP15,          /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         score_elf_gprel15_reloc,/* special_function */
-         "R_SCORE_GP15",        /* name */
-         TRUE,                  /* partial_inplace */
-         0x00007fff,            /* src_mask */
-         0x00007fff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_GP15,         /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        score_elf_gprel15_reloc,/* special_function */
+        "R_SCORE_GP15",        /* name */
+        TRUE,                  /* partial_inplace */
+        0x00007fff,            /* src_mask */
+        0x00007fff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* GNU extension to record C++ vtable hierarchy.  */
   HOWTO (R_SCORE_GNU_VTINHERIT, /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         0,                     /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         NULL,                  /* special_function */
-         "R_SCORE_GNU_VTINHERIT",       /* name */
-         FALSE,                 /* partial_inplace */
-         0,                     /* src_mask */
-         0,                     /* dst_mask */
-         FALSE),                /* pcrel_offset */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        NULL,                  /* special_function */
+        "R_SCORE_GNU_VTINHERIT",       /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* GNU extension to record C++ vtable member usage */
-  HOWTO (R_SCORE_GNU_VTENTRY,   /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         0,                     /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
-         "R_SCORE_GNU_VTENTRY", /* name */
-         FALSE,                 /* partial_inplace */
-         0,                     /* src_mask */
-         0,                     /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_GNU_VTENTRY,  /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
+        "R_SCORE_GNU_VTENTRY", /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* Reference to global offset table.  */
-  HOWTO (R_SCORE_GOT15,         /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_signed,      /* complain_on_overflow */
-         score_elf_got15_reloc, /* special_function */
-         "R_SCORE_GOT15",       /* name */
-         TRUE,                  /* partial_inplace */
-         0x00007fff,            /* src_mask */
-         0x00007fff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_GOT15,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed,      /* complain_on_overflow */
+        score_elf_got15_reloc, /* special_function */
+        "R_SCORE_GOT15",       /* name */
+        TRUE,                  /* partial_inplace */
+        0x00007fff,            /* src_mask */
+        0x00007fff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* Low 16 bits of displacement in global offset table.  */
-  HOWTO (R_SCORE_GOT_LO16,      /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         1,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         score_elf_got_lo16_reloc, /* special_function */
-         "R_SCORE_GOT_LO16",    /* name */
-         TRUE,                  /* partial_inplace */
-         0x37ffe,               /* src_mask */
-         0x37ffe,               /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_GOT_LO16,     /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        1,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        score_elf_got_lo16_reloc, /* special_function */
+        "R_SCORE_GOT_LO16",    /* name */
+        TRUE,                  /* partial_inplace */
+        0x37ffe,               /* src_mask */
+        0x37ffe,               /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* 15 bit call through global offset table.  */
-  HOWTO (R_SCORE_CALL15,        /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_signed, /* complain_on_overflow */
-         bfd_elf_generic_reloc, /* special_function */
-         "R_SCORE_CALL15",      /* name */
-         TRUE,                  /* partial_inplace */
-         0x0000ffff,            /* src_mask */
-         0x0000ffff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_CALL15,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_CALL15",      /* name */
+        TRUE,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* 32 bit GP relative reference.  */
-  HOWTO (R_SCORE_GPREL32,       /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         32,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         0,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-         score_elf_gprel32_reloc, /* special_function */
-         "R_SCORE_GPREL32",     /* name */
-         TRUE,                  /* partial_inplace */
-         0xffffffff,            /* src_mask */
-         0xffffffff,            /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_GPREL32,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        score_elf_gprel32_reloc, /* special_function */
+        "R_SCORE_GPREL32",     /* name */
+        TRUE,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* 32 bit symbol relative relocation.  */
-  HOWTO (R_SCORE_REL32,         /* type */
-        0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
+  HOWTO (R_SCORE_REL32,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
         complain_overflow_dont,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
-        "R_SCORE_REL32",       /* name */
-        TRUE,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        "R_SCORE_REL32",       /* name */
+        TRUE,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
 
   /* R_SCORE_DUMMY_HI16 */
-  HOWTO (R_SCORE_DUMMY_HI16,    /* type */
-         0,                     /* rightshift */
-         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-         16,                    /* bitsize */
-         FALSE,                 /* pc_relative */
-         1,                     /* bitpos */
-         complain_overflow_dont,/* complain_on_overflow */
-        score_elf_hi16_reloc,  /* special_function */
-         "R_SCORE_DUMMY_HI16",  /* name */
-         TRUE,                  /* partial_inplace */
-         0x37fff,               /* src_mask */
-         0x37fff,               /* dst_mask */
-         FALSE),                /* pcrel_offset */
+  HOWTO (R_SCORE_DUMMY_HI16,   /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        1,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        score_elf_hi16_reloc,  /* special_function */
+        "R_SCORE_DUMMY_HI16",  /* name */
+        TRUE,                  /* partial_inplace */
+        0x37fff,               /* src_mask */
+        0x37fff,               /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* R_SCORE_IMM30 */
+  HOWTO (R_SCORE_IMM30,                /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        30,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        7,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_IMM30",       /* name */
+        FALSE,                 /* partial_inplace */
+        0x7f7fff7f80LL,        /* src_mask */
+        0x7f7fff7f80LL,        /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* R_SCORE_IMM32 */
+  HOWTO (R_SCORE_IMM32,                /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        5,                     /* bitpos */
+        complain_overflow_dont,/* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SCORE_IMM32",       /* name */
+        FALSE,                 /* partial_inplace */
+        0x7f7fff7fe0LL,        /* src_mask */
+        0x7f7fff7fe0LL,        /* dst_mask */
+        FALSE),                /* pcrel_offset */
 };
 
 struct score_reloc_map
@@ -866,32 +981,33 @@ struct score_reloc_map
 
 static const struct score_reloc_map elf32_score_reloc_map[] =
 {
-  {BFD_RELOC_NONE,               R_SCORE_NONE},
-  {BFD_RELOC_HI16_S,             R_SCORE_HI16},
-  {BFD_RELOC_LO16,               R_SCORE_LO16},
-  {BFD_RELOC_SCORE_DUMMY1,       R_SCORE_DUMMY1},
-  {BFD_RELOC_SCORE_JMP,          R_SCORE_24},
-  {BFD_RELOC_SCORE_BRANCH,       R_SCORE_PC19},
-  {BFD_RELOC_SCORE16_JMP,        R_SCORE16_11},
-  {BFD_RELOC_SCORE16_BRANCH,     R_SCORE16_PC8},
-  {BFD_RELOC_32,                 R_SCORE_ABS32},
-  {BFD_RELOC_16,                 R_SCORE_ABS16},
-  {BFD_RELOC_SCORE_DUMMY2,       R_SCORE_DUMMY2},
-  {BFD_RELOC_SCORE_GPREL15,      R_SCORE_GP15},
-  {BFD_RELOC_VTABLE_INHERIT,     R_SCORE_GNU_VTINHERIT},
-  {BFD_RELOC_VTABLE_ENTRY,       R_SCORE_GNU_VTENTRY},
-  {BFD_RELOC_SCORE_GOT15,        R_SCORE_GOT15},
-  {BFD_RELOC_SCORE_GOT_LO16,     R_SCORE_GOT_LO16},
-  {BFD_RELOC_SCORE_CALL15,       R_SCORE_CALL15},
-  {BFD_RELOC_GPREL32,            R_SCORE_GPREL32},
-  {BFD_RELOC_32_PCREL,           R_SCORE_REL32},
-  {BFD_RELOC_SCORE_DUMMY_HI16,   R_SCORE_DUMMY_HI16},
+  {BFD_RELOC_NONE,              R_SCORE_NONE},
+  {BFD_RELOC_HI16_S,            R_SCORE_HI16},
+  {BFD_RELOC_LO16,              R_SCORE_LO16},
+  {BFD_RELOC_SCORE_BCMP,        R_SCORE_BCMP},
+  {BFD_RELOC_SCORE_JMP,                 R_SCORE_24},
+  {BFD_RELOC_SCORE_BRANCH,      R_SCORE_PC19},
+  {BFD_RELOC_SCORE16_JMP,       R_SCORE16_11},
+  {BFD_RELOC_SCORE16_BRANCH,    R_SCORE16_PC8},
+  {BFD_RELOC_32,                R_SCORE_ABS32},
+  {BFD_RELOC_16,                R_SCORE_ABS16},
+  {BFD_RELOC_SCORE_DUMMY2,      R_SCORE_DUMMY2},
+  {BFD_RELOC_SCORE_GPREL15,     R_SCORE_GP15},
+  {BFD_RELOC_VTABLE_INHERIT,    R_SCORE_GNU_VTINHERIT},
+  {BFD_RELOC_VTABLE_ENTRY,      R_SCORE_GNU_VTENTRY},
+  {BFD_RELOC_SCORE_GOT15,       R_SCORE_GOT15},
+  {BFD_RELOC_SCORE_GOT_LO16,    R_SCORE_GOT_LO16},
+  {BFD_RELOC_SCORE_CALL15,      R_SCORE_CALL15},
+  {BFD_RELOC_GPREL32,           R_SCORE_GPREL32},
+  {BFD_RELOC_32_PCREL,          R_SCORE_REL32},
+  {BFD_RELOC_SCORE_DUMMY_HI16,  R_SCORE_DUMMY_HI16},
+  {BFD_RELOC_SCORE_IMM30,       R_SCORE_IMM30},
+  {BFD_RELOC_SCORE_IMM32,       R_SCORE_IMM32},
 };
 
 /* got_entries only match if they're identical, except for gotidx, so
    use all fields to compute the hash, and compare the appropriate
    union members.  */
-
 static hashval_t
 score_elf_got_entry_hash (const void *entry_)
 {
@@ -916,15 +1032,11 @@ score_elf_got_entry_eq (const void *entry1, const void *entry2)
 /* If H needs a GOT entry, assign it the highest available dynamic
    index.  Otherwise, assign it the lowest available dynamic
    index.  */
-
 static bfd_boolean
 score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data)
 {
   struct score_elf_hash_sort_data *hsd = data;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link;
-
   /* Symbols without dynamic symbol table entries aren't interesting at all.  */
   if (h->root.dynindx == -1)
     return TRUE;
@@ -953,7 +1065,7 @@ score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data)
 static asection *
 score_elf_got_section (bfd *abfd, bfd_boolean maybe_excluded)
 {
-  asection *sgot = bfd_get_section_by_name (abfd, ".got");
+  asection *sgot = bfd_get_linker_section (abfd, ".got");
 
   if (sgot == NULL || (! maybe_excluded && (sgot->flags & SEC_EXCLUDE) != 0))
     return NULL;
@@ -962,7 +1074,6 @@ score_elf_got_section (bfd *abfd, bfd_boolean maybe_excluded)
 
 /* Returns the GOT information associated with the link indicated by
    INFO.  If SGOTP is non-NULL, it is filled in with the GOT section.  */
-
 static struct score_got_info *
 score_elf_got_info (bfd *abfd, asection **sgotp)
 {
@@ -984,9 +1095,8 @@ score_elf_got_info (bfd *abfd, asection **sgotp)
    appear towards the end.  This reduces the amount of GOT space
    required.  MAX_LOCAL is used to set the number of local symbols
    known to be in the dynamic symbol table.  During
-   _bfd_score_elf_size_dynamic_sections, this value is 1.  Afterward, the
+   s3_bfd_score_elf_size_dynamic_sections, this value is 1.  Afterward, the
    section symbols are added and the count is higher.  */
-
 static bfd_boolean
 score_elf_sort_hash_table (struct bfd_link_info *info,
                           unsigned long max_local)
@@ -1011,10 +1121,9 @@ score_elf_sort_hash_table (struct bfd_link_info *info,
        too large offsets.  */
     - (g->next ? g->assigned_gotno : 0);
   hsd.max_non_got_dynindx = max_local;
-  score_elf_link_hash_traverse (((struct score_elf_link_hash_table *)
-                                elf_hash_table (info)),
-                                score_elf_sort_hash_table_f,
-                                &hsd);
+  score_elf_link_hash_traverse (elf_hash_table (info),
+                               score_elf_sort_hash_table_f,
+                               &hsd);
 
   /* There should have been enough room in the symbol table to
      accommodate both the GOT and non-GOT symbols.  */
@@ -1036,17 +1145,17 @@ score_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
                             struct bfd_hash_table *table,
                             const char *string)
 {
-  struct score_elf_link_hash_entry *ret = (struct score_elf_link_hash_entry *)entry;
+  struct score_elf_link_hash_entry *ret = (struct score_elf_link_hash_entry *) entry;
 
   /* Allocate the structure if it has not already been allocated by a subclass.  */
   if (ret == NULL)
     ret = bfd_hash_allocate (table, sizeof (struct score_elf_link_hash_entry));
   if (ret == NULL)
-    return (struct bfd_hash_entry *)ret;
+    return (struct bfd_hash_entry *) ret;
 
   /* Call the allocation method of the superclass.  */
   ret = ((struct score_elf_link_hash_entry *)
-         _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *)ret, table, string));
+        _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
 
   if (ret != NULL)
     {
@@ -1056,15 +1165,14 @@ score_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
       ret->forced_local = FALSE;
     }
 
-  return (struct bfd_hash_entry *)ret;
+  return (struct bfd_hash_entry *) ret;
 }
 
 /* Returns the first relocation of type r_type found, beginning with
    RELOCATION.  RELEND is one-past-the-end of the relocation table.  */
-
 static const Elf_Internal_Rela *
 score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
-                          const Elf_Internal_Rela *relocation,
+                           const Elf_Internal_Rela *relocation,
                           const Elf_Internal_Rela *relend)
 {
   while (relocation < relend)
@@ -1082,7 +1190,6 @@ score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type,
 
 /* This function is called via qsort() to sort the dynamic relocation
    entries by increasing r_symndx value.  */
-
 static int
 score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2)
 {
@@ -1096,7 +1203,6 @@ score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2)
 }
 
 /* Return whether a relocation is against a local symbol.  */
-
 static bfd_boolean
 score_elf_local_relocation_p (bfd *input_bfd,
                              const Elf_Internal_Rela *relocation,
@@ -1134,29 +1240,28 @@ score_elf_local_relocation_p (bfd *input_bfd,
 }
 
 /* Returns the dynamic relocation section for DYNOBJ.  */
-
 static asection *
 score_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p)
 {
   static const char dname[] = ".rel.dyn";
   asection *sreloc;
 
-  sreloc = bfd_get_section_by_name (dynobj, dname);
+  sreloc = bfd_get_linker_section (dynobj, dname);
   if (sreloc == NULL && create_p)
     {
-      sreloc = bfd_make_section_with_flags (dynobj, dname,
-                                            (SEC_ALLOC
-                                             | SEC_LOAD
-                                             | SEC_HAS_CONTENTS
-                                             | SEC_IN_MEMORY
-                                             | SEC_LINKER_CREATED
-                                             | SEC_READONLY));
+      sreloc = bfd_make_section_anyway_with_flags (dynobj, dname,
+                                                  (SEC_ALLOC
+                                                   | SEC_LOAD
+                                                   | SEC_HAS_CONTENTS
+                                                   | SEC_IN_MEMORY
+                                                   | SEC_LINKER_CREATED
+                                                   | SEC_READONLY));
       if (sreloc == NULL
-         || ! bfd_set_section_alignment (dynobj, sreloc,
-                                         SCORE_ELF_LOG_FILE_ALIGN (dynobj)))
+         || !bfd_set_section_alignment (sreloc,
+                                        SCORE_ELF_LOG_FILE_ALIGN (dynobj)))
        return NULL;
     }
-  return sreloc; 
+  return sreloc;
 }
 
 static void
@@ -1180,7 +1285,6 @@ score_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n)
    is the original relocation, which is now being transformed into a
    dynamic relocation.  The ADDENDP is adjusted if necessary; the
    caller should store the result in place of the original addend.  */
-
 static bfd_boolean
 score_elf_create_dynamic_relocation (bfd *output_bfd,
                                     struct bfd_link_info *info,
@@ -1298,7 +1402,7 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
 
 static bfd_boolean
 score_elf_create_got_section (bfd *abfd,
-                              struct bfd_link_info *info,
+                             struct bfd_link_info *info,
                              bfd_boolean maybe_exclude)
 {
   flagword flags;
@@ -1306,7 +1410,7 @@ score_elf_create_got_section (bfd *abfd,
   struct elf_link_hash_entry *h;
   struct bfd_link_hash_entry *bh;
   struct score_got_info *g;
-  bfd_size_type amt;
+  size_t amt;
 
   /* This function may be called more than once.  */
   s = score_elf_got_section (abfd, TRUE);
@@ -1324,9 +1428,10 @@ score_elf_create_got_section (bfd *abfd,
 
   /* We have to use an alignment of 2**4 here because this is hardcoded
      in the function stub generation and in the linker script.  */
-  s = bfd_make_section_with_flags (abfd, ".got", flags);
-   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, 4))
+  s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
+  elf_hash_table (info)->sgot = s;
+  if (s == NULL
+      || !bfd_set_section_alignment (s, 4))
     return FALSE;
 
   /* Define the symbol _GLOBAL_OFFSET_TABLE_.  We don't do this in the
@@ -1342,8 +1447,9 @@ score_elf_create_got_section (bfd *abfd,
   h->non_elf = 0;
   h->def_regular = 1;
   h->type = STT_OBJECT;
+  elf_hash_table (info)->hgot = h;
 
-  if (info->shared && ! bfd_elf_link_record_dynamic_symbol (info, h))
+  if (bfd_link_pic (info) && ! bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
 
   amt = sizeof (struct score_got_info);
@@ -1369,7 +1475,6 @@ score_elf_create_got_section (bfd *abfd,
 }
 
 /* Calculate the %high function.  */
-
 static bfd_vma
 score_elf_high (bfd_vma value)
 {
@@ -1378,10 +1483,9 @@ score_elf_high (bfd_vma value)
 
 /* Create a local GOT entry for VALUE.  Return the index of the entry,
    or -1 if it could not be created.  */
-
 static struct score_got_entry *
 score_elf_create_local_got_entry (bfd *abfd,
-                                  bfd *ibfd ATTRIBUTE_UNUSED,
+                                 bfd *ibfd ATTRIBUTE_UNUSED,
                                  struct score_got_info *gg,
                                  asection *sgot, bfd_vma value,
                                  unsigned long r_symndx ATTRIBUTE_UNUSED,
@@ -1413,23 +1517,22 @@ score_elf_create_local_got_entry (bfd *abfd,
     {
       (*loc)->gotidx = -1;
       /* We didn't allocate enough space in the GOT.  */
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("not enough GOT space for local GOT entries"));
       bfd_set_error (bfd_error_bad_value);
       return NULL;
     }
 
-  bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx));
+  score_bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx));
 
   return *loc;
 }
 
 /* Find a GOT entry whose higher-order 16 bits are the same as those
    for value.  Return the index into the GOT for this entry.  */
-
 static bfd_vma
 score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
-                     bfd_vma value, bfd_boolean external)
+                      bfd_vma value, bfd_boolean external)
 {
   asection *sgot;
   struct score_got_info *g;
@@ -1455,9 +1558,9 @@ score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
 }
 
 static void
-_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
-                           struct elf_link_hash_entry *entry,
-                           bfd_boolean force_local)
+s3_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
+                             struct elf_link_hash_entry *entry,
+                             bfd_boolean force_local)
 {
   bfd *dynobj;
   asection *got;
@@ -1517,7 +1620,7 @@ _bfd_score_elf_hide_symbol (struct bfd_link_info *info,
       else if (h->root.got.offset == 1)
        {
          /* If we're past non-multi-GOT allocation and this symbol had
-                 been marked for a global got entry, give it a local entry
+                 been marked for a global got entry, give it a local entry
                  instead.  */
          BFD_ASSERT (g->global_gotno > 0);
          g->local_gotno++;
@@ -1531,11 +1634,10 @@ _bfd_score_elf_hide_symbol (struct bfd_link_info *info,
 /* If H is a symbol that needs a global GOT entry, but has a dynamic
    symbol table index lower than any we've seen to date, record it for
    posterity.  */
-
 static bfd_boolean
 score_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
-                                   bfd *abfd,
-                                    struct bfd_link_info *info,
+                                   bfd *abfd,
+                                   struct bfd_link_info *info,
                                    struct score_got_info *g)
 {
   struct score_got_entry entry, **loc;
@@ -1547,7 +1649,7 @@ score_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
        {
        case STV_INTERNAL:
        case STV_HIDDEN:
-         _bfd_score_elf_hide_symbol (info, h, TRUE);
+         s3_bfd_score_elf_hide_symbol (info, h, TRUE);
          break;
        }
       if (!bfd_elf_link_record_dynamic_symbol (info, h))
@@ -1586,12 +1688,11 @@ score_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
 
 /* Reserve space in G for a GOT entry containing the value of symbol
    SYMNDX in input bfd ABDF, plus ADDEND.  */
-
 static bfd_boolean
 score_elf_record_local_got_symbol (bfd *abfd,
-                                   long symndx,
-                                   bfd_vma addend,
-                                  struct score_got_info *g)
+                                  long symndx,
+                                  bfd_vma addend,
+                                  struct score_got_info *g)
 {
   struct score_got_entry entry, **loc;
 
@@ -1617,11 +1718,10 @@ score_elf_record_local_got_symbol (bfd *abfd,
 /* Returns the GOT offset at which the indicated address can be found.
    If there is not yet a GOT entry for this value, create one.
    Returns -1 if no satisfactory GOT offset can be found.  */
-
 static bfd_vma
 score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
-                         bfd_vma value, unsigned long r_symndx,
-                         struct score_elf_link_hash_entry *h, int r_type)
+                          bfd_vma value, unsigned long r_symndx,
+                          struct score_elf_link_hash_entry *h, int r_type)
 {
   asection *sgot;
   struct score_got_info *g;
@@ -1630,7 +1730,7 @@ score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
   g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
 
   entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value,
-                                           r_symndx, h, r_type);
+                                            r_symndx, h, r_type);
   if (!entry)
     return MINUS_ONE;
 
@@ -1643,7 +1743,7 @@ score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
 static bfd_vma
 score_elf_global_got_index (bfd *abfd, struct elf_link_hash_entry *h)
 {
-  bfd_vma index;
+  bfd_vma got_index;
   asection *sgot;
   struct score_got_info *g;
   long global_got_dynindx = 0;
@@ -1657,26 +1757,27 @@ score_elf_global_got_index (bfd *abfd, struct elf_link_hash_entry *h)
      indices into the GOT.  That makes it easy to calculate the GOT
      offset.  */
   BFD_ASSERT (h->dynindx >= global_got_dynindx);
-  index = ((h->dynindx - global_got_dynindx + g->local_gotno) * SCORE_ELF_GOT_SIZE (abfd));
-  BFD_ASSERT (index < sgot->size);
+  got_index = ((h->dynindx - global_got_dynindx + g->local_gotno) * SCORE_ELF_GOT_SIZE (abfd));
+  BFD_ASSERT (got_index < sgot->size);
 
-  return index;
+  return got_index;
 }
 
 /* Returns the offset for the entry at the INDEXth position in the GOT.  */
 
 static bfd_vma
-score_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd,
-                                bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma index)
+score_elf_got_offset_from_index (bfd *dynobj,
+                                bfd *output_bfd,
+                                bfd *input_bfd ATTRIBUTE_UNUSED,
+                                bfd_vma got_index)
 {
   asection *sgot;
   bfd_vma gp;
-  struct score_got_info *g;
 
-  g = score_elf_got_info (dynobj, &sgot);
+  score_elf_got_info (dynobj, &sgot);
   gp = _bfd_get_gp_value (output_bfd);
 
-  return sgot->output_section->vma + sgot->output_offset + index - gp;
+  return sgot->output_section->vma + sgot->output_offset + got_index - gp;
 }
 
 /* Follow indirect and warning hash entries so that each got entry
@@ -1743,7 +1844,6 @@ score_elf_resolve_final_got_entries (struct score_got_info *g)
 }
 
 /* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS. for -r  */
-
 static void
 score_elf_add_to_rel (bfd *abfd,
                      bfd_byte *address,
@@ -1756,7 +1856,7 @@ score_elf_add_to_rel (bfd *abfd,
   unsigned long r_type = howto->type;
   unsigned long hi16_addend, hi16_offset, hi16_value, uvalue;
 
-  contents = bfd_get_32 (abfd, address);
+  contents = score_bfd_get_32 (abfd, address);
   /* Get the (signed) value from the instruction.  */
   addend = contents & howto->src_mask;
   if (addend & ((howto->src_mask + 1) >> 1))
@@ -1772,65 +1872,94 @@ score_elf_add_to_rel (bfd *abfd,
     {
     case R_SCORE_PC19:
       offset =
-        (((contents & howto->src_mask) & 0x3ff0000) >> 6) | ((contents & howto->src_mask) & 0x3ff);
+       (((contents & howto->src_mask) & 0x3ff0000) >> 6) | ((contents & howto->src_mask) & 0x3ff);
       offset += increment;
       contents =
-        (contents & ~howto->
-         src_mask) | (((offset << 6) & howto->src_mask) & 0x3ff0000) | (offset & 0x3ff);
-      bfd_put_32 (abfd, contents, address);
+       (contents & ~howto->
+        src_mask) | (((offset << 6) & howto->src_mask) & 0x3ff0000) | (offset & 0x3ff);
+      score_bfd_put_32 (abfd, contents, address);
       break;
     case R_SCORE_HI16:
       break;
     case R_SCORE_LO16:
-      hi16_addend = bfd_get_32 (abfd, address - 4);
+      hi16_addend = score_bfd_get_32 (abfd, address - 4);
       hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
       offset = ((((contents >> 16) & 0x3) << 15) | (contents & 0x7fff)) >> 1;
       offset = (hi16_offset << 16) | (offset & 0xffff);
       uvalue = increment + offset;
       hi16_offset = (uvalue >> 16) << 1;
       hi16_value = (hi16_addend & (~(howto->dst_mask)))
-        | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
-      bfd_put_32 (abfd, hi16_value, address - 4);
+       | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
+      score_bfd_put_32 (abfd, hi16_value, address - 4);
       offset = (uvalue & 0xffff) << 1;
       contents = (contents & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
-      bfd_put_32 (abfd, contents, address);
+      score_bfd_put_32 (abfd, contents, address);
       break;
     case R_SCORE_24:
       offset =
-        (((contents & howto->src_mask) >> 1) & 0x1ff8000) | ((contents & howto->src_mask) & 0x7fff);
+       (((contents & howto->src_mask) >> 1) & 0x1ff8000) | ((contents & howto->src_mask) & 0x7fff);
       offset += increment;
       contents =
-        (contents & ~howto->
-         src_mask) | (((offset << 1) & howto->src_mask) & 0x3ff0000) | (offset & 0x7fff);
-      bfd_put_32 (abfd, contents, address);
+       (contents & ~howto->
+        src_mask) | (((offset << 1) & howto->src_mask) & 0x3ff0000) | (offset & 0x7fff);
+      score_bfd_put_32 (abfd, contents, address);
       break;
+
     case R_SCORE16_11:
 
-      contents = bfd_get_16 (abfd, address);
+      contents = score_bfd_get_16 (abfd, address);
       offset = contents & howto->src_mask;
       offset += increment;
       contents = (contents & ~howto->src_mask) | (offset & howto->src_mask);
-      bfd_put_16 (abfd, contents, address);
+      score_bfd_put_16 (abfd, contents, address);
 
       break;
     case R_SCORE16_PC8:
 
-      contents = bfd_get_16 (abfd, address);
-      offset = (contents & howto->src_mask) + ((increment >> 1) & 0xff);
+      contents = score_bfd_get_16 (abfd, address);
+      offset = (contents & howto->src_mask) + ((increment >> 1) & 0x1ff);
+      contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
+      score_bfd_put_16 (abfd, contents, address);
+
+      break;
+
+    case R_SCORE_BCMP:
+      contents = score_bfd_get_32 (abfd, address);
+      offset = (contents & howto->src_mask);
+      offset <<= howto->rightshift;
+      offset += increment;
+      offset >>= howto->rightshift;
+      contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
+      score_bfd_put_32 (abfd, contents, address);
+      break;
+
+    case R_SCORE_IMM30:
+      contents = score_bfd_get_48 (abfd, address);
+      offset = (contents & howto->src_mask);
+      offset <<= howto->rightshift;
+      offset += increment;
+      offset >>= howto->rightshift;
       contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
-      bfd_put_16 (abfd, contents, address);
+      score_bfd_put_48 (abfd, contents, address);
+      break;
 
+    case R_SCORE_IMM32:
+      contents = score_bfd_get_48 (abfd, address);
+      offset = (contents & howto->src_mask);
+      offset += increment;
+      contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask);
+      score_bfd_put_48 (abfd, contents, address);
       break;
+
     default:
       addend += increment;
       contents = (contents & ~howto->dst_mask) | (addend & howto->dst_mask);
-      bfd_put_32 (abfd, contents, address);
+      score_bfd_put_32 (abfd, contents, address);
       break;
     }
 }
 
 /* Perform a relocation as part of a final link.  */
-
 static bfd_reloc_status_type
 score_elf_final_link_relocate (reloc_howto_type *howto,
                               bfd *input_bfd,
@@ -1844,8 +1973,8 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
                               const char *sym_name ATTRIBUTE_UNUSED,
                               int sym_flags ATTRIBUTE_UNUSED,
                               struct score_elf_link_hash_entry *h,
-                              asection **local_sections,
-                               bfd_boolean gp_disp_p)
+                              asection **local_sections,
+                              bfd_boolean gp_disp_p)
 {
   unsigned long r_type;
   unsigned long r_symndx;
@@ -1856,8 +1985,6 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
   bfd_vma gp = MINUS_ONE;
   /* The place (section offset or address) of the storage unit being relocated.  */
   bfd_vma rel_addr;
-  /* The value of GP used to create the relocatable object.  */
-  bfd_vma gp0 = MINUS_ONE;
   /* The offset into the global offset table at which the address of the relocation entry
      symbol, adjusted by the addend, resides during execution.  */
   bfd_vma g = MINUS_ONE;
@@ -1867,33 +1994,34 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
   bfd_vma value = symbol;
   unsigned long hi16_addend, hi16_offset, hi16_value, uvalue, offset, abs_value = 0;
 
+
   if (elf_gp (output_bfd) == 0)
     {
       struct bfd_link_hash_entry *bh;
       asection *o;
 
       bh = bfd_link_hash_lookup (info->hash, "_gp", 0, 0, 1);
-      if (bh != (struct bfd_link_hash_entry *)NULL && bh->type == bfd_link_hash_defined)
-        elf_gp (output_bfd) = (bh->u.def.value
-                               + bh->u.def.section->output_section->vma
-                               + bh->u.def.section->output_offset);
-      else if (info->relocatable)
-        {
-          bfd_vma lo = -1;
-
-          /* Find the GP-relative section with the lowest offset.  */
-          for (o = output_bfd->sections; o != (asection *) NULL; o = o->next)
-            if (o->vma < lo)
-              lo = o->vma;
-          /* And calculate GP relative to that.  */
-          elf_gp (output_bfd) = lo + ELF_SCORE_GP_OFFSET (input_bfd);
-        }
+      if (bh != NULL && bh->type == bfd_link_hash_defined)
+       elf_gp (output_bfd) = (bh->u.def.value
+                              + bh->u.def.section->output_section->vma
+                              + bh->u.def.section->output_offset);
+      else if (bfd_link_relocatable (info))
+       {
+         bfd_vma lo = -1;
+
+         /* Find the GP-relative section with the lowest offset.  */
+         for (o = output_bfd->sections; o != NULL; o = o->next)
+           if (o->vma < lo)
+             lo = o->vma;
+         /* And calculate GP relative to that.  */
+         elf_gp (output_bfd) = lo + ELF_SCORE_GP_OFFSET (input_bfd);
+       }
       else
-        {
-          /* If the relocate_section function needs to do a reloc
-             involving the GP value, it should make a reloc_dangerous
-             callback to warn that GP is not defined.  */
-        }
+       {
+         /* If the relocate_section function needs to do a reloc
+            involving the GP value, it should make a reloc_dangerous
+            callback to warn that GP is not defined.  */
+       }
     }
 
   /* Parse the relocation.  */
@@ -1906,24 +2034,27 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
     {
       const Elf_Internal_Rela *relend;
       const Elf_Internal_Rela *lo16_rel;
-      const struct elf_backend_data *bed;
       bfd_vma lo_value = 0;
 
-      bed = get_elf_backend_data (output_bfd);
-      relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
+      relend = relocs + input_section->reloc_count;
       lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
       if ((local_p) && (lo16_rel != NULL))
        {
          bfd_vma tmp = 0;
-         tmp = bfd_get_32 (input_bfd, contents + lo16_rel->r_offset);
+         tmp = score_bfd_get_32 (input_bfd, contents + lo16_rel->r_offset);
          lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1);
        }
       addend = lo_value;
     }
-  else
+  /* For score3 R_SCORE_ABS32.  */
+  else if (r_type == R_SCORE_ABS32 || r_type == R_SCORE_REL32)
     {
       addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
     }
+  else
+    {
+      addend = (score_bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
+    }
 
   /* If we haven't already determined the GOT offset, or the GP value,
      and we're going to need it, get it now.  */
@@ -1932,35 +2063,35 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
     case R_SCORE_CALL15:
     case R_SCORE_GOT15:
       if (!local_p)
-        {
-          g = score_elf_global_got_index (elf_hash_table (info)->dynobj,
-                                          (struct elf_link_hash_entry *) h);
-          if ((! elf_hash_table(info)->dynamic_sections_created
-               || (info->shared
-                   && (info->symbolic || h->root.dynindx == -1)
-                   && h->root.def_regular)))
-            {
-              /* This is a static link or a -Bsymbolic link.  The
-                 symbol is defined locally, or was forced to be local.
-                 We must initialize this entry in the GOT.  */
-              bfd *tmpbfd = elf_hash_table (info)->dynobj;
-              asection *sgot = score_elf_got_section (tmpbfd, FALSE);
-              bfd_put_32 (tmpbfd, value, sgot->contents + g);
-            }
-        }
+       {
+         g = score_elf_global_got_index (elf_hash_table (info)->dynobj,
+                                         (struct elf_link_hash_entry *) h);
+         if ((! elf_hash_table (info)->dynamic_sections_created
+              || (bfd_link_pic (info)
+                  && (info->symbolic || h->root.dynindx == -1)
+                  && h->root.def_regular)))
+           {
+             /* This is a static link or a -Bsymbolic link.  The
+                symbol is defined locally, or was forced to be local.
+                We must initialize this entry in the GOT.  */
+             bfd *tmpbfd = elf_hash_table (info)->dynobj;
+             asection *sgot = score_elf_got_section (tmpbfd, FALSE);
+             score_bfd_put_32 (tmpbfd, value, sgot->contents + g);
+           }
+       }
       else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15)
-        {
+       {
          /* There's no need to create a local GOT entry here; the
             calculation for a local GOT15 entry does not involve G.  */
          ;
        }
       else
-        {
+       {
          g = score_elf_local_got_index (output_bfd, input_bfd, info,
-                                         symbol + addend, r_symndx, h, r_type);
-         if (g == MINUS_ONE)
+                                        symbol + addend, r_symndx, h, r_type);
+           if (g == MINUS_ONE)
            return bfd_reloc_outofrange;
-        }
+       }
 
       /* Convert GOT indices to actual offsets.  */
       g = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj,
@@ -1970,7 +2101,6 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
     case R_SCORE_HI16:
     case R_SCORE_LO16:
     case R_SCORE_GPREL32:
-      gp0 = _bfd_get_gp_value (input_bfd);
       gp = _bfd_get_gp_value (output_bfd);
       break;
 
@@ -1988,29 +2118,29 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
 
     case R_SCORE_ABS32:
     case R_SCORE_REL32:
-      if ((info->shared
+      if ((bfd_link_pic (info)
           || (elf_hash_table (info)->dynamic_sections_created
               && h != NULL
               && h->root.def_dynamic
               && !h->root.def_regular))
-          && r_symndx != 0
+          && r_symndx != STN_UNDEF
           && (input_section->flags & SEC_ALLOC) != 0)
        {
          /* If we're creating a shared library, or this relocation is against a symbol
-             in a shared library, then we can't know where the symbol will end up.
-             So, we create a relocation record in the output, and leave the job up
-             to the dynamic linker.  */
+            in a shared library, then we can't know where the symbol will end up.
+            So, we create a relocation record in the output, and leave the job up
+            to the dynamic linker.  */
          value = addend;
          if (!score_elf_create_dynamic_relocation (output_bfd, info, rel, h,
                                                    symbol, &value,
                                                    input_section))
            return bfd_reloc_undefined;
        }
-      else if (r_symndx == 0)
-        /* r_symndx will be zero only for relocs against symbols
-           from removed linkonce sections, or sections discarded by
-           a linker script.  */
-        value = 0;
+      else if (r_symndx == STN_UNDEF)
+       /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
+          from removed linkonce sections, or sections discarded by
+          a linker script.  */
+       value = 0;
       else
        {
          if (r_type != R_SCORE_REL32)
@@ -2025,68 +2155,137 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
     case R_SCORE_ABS16:
       value += addend;
       if ((long)value > 0x7fff || (long)value < -0x8000)
-        return bfd_reloc_overflow;
-      bfd_put_16 (input_bfd, value, hit_data);
+       return bfd_reloc_overflow;
+      score_bfd_put_16 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE_24:
-      addend = bfd_get_32 (input_bfd, hit_data);
+      addend = score_bfd_get_32 (input_bfd, hit_data);
       offset = (((addend & howto->src_mask) >> 1) & 0x1ff8000) | ((addend & howto->src_mask) & 0x7fff);
       if ((offset & 0x1000000) != 0)
-        offset |= 0xfe000000;
+       offset |= 0xfe000000;
       value += offset;
+      abs_value = value - rel_addr;
+      if ((abs_value & 0xfe000000) != 0)
+       return bfd_reloc_overflow;
       addend = (addend & ~howto->src_mask)
-                | (((value << 1) & howto->src_mask) & 0x3ff0000) | (value & 0x7fff);
-      bfd_put_32 (input_bfd, addend, hit_data);
+               | (((value << 1) & howto->src_mask) & 0x3ff0000) | (value & 0x7fff);
+      score_bfd_put_32 (input_bfd, addend, hit_data);
       return bfd_reloc_ok;
 
+    /* signed imm32.  */
+    case R_SCORE_IMM30:
+      {
+       int not_word_align_p = 0;
+       bfd_vma imm_offset = 0;
+       addend = score_bfd_get_48 (input_bfd, hit_data);
+       imm_offset = ((addend >> 7) & 0xff)
+                    | (((addend >> 16) & 0x7fff) << 8)
+                    | (((addend >> 32) & 0x7f) << 23);
+       imm_offset <<= howto->rightshift;
+       value += imm_offset;
+       value &= 0xffffffff;
+
+       /* Check lw48/sw48 rd, value/label word align.  */
+       if ((value & 0x3) != 0)
+         not_word_align_p = 1;
+
+       value >>= howto->rightshift;
+       addend = (addend & ~howto->src_mask)
+                | (((value & 0xff) >> 0) << 7)
+                | (((value & 0x7fff00) >> 8) << 16)
+                | (((value & 0x3f800000) >> 23) << 32);
+       score_bfd_put_48 (input_bfd, addend, hit_data);
+       if (not_word_align_p)
+         return bfd_reloc_other;
+       else
+         return bfd_reloc_ok;
+      }
+
+    case R_SCORE_IMM32:
+      {
+       bfd_vma imm_offset = 0;
+       addend = score_bfd_get_48 (input_bfd, hit_data);
+       imm_offset = ((addend >> 5) & 0x3ff)
+                    | (((addend >> 16) & 0x7fff) << 10)
+                    | (((addend >> 32) & 0x7f) << 25);
+       value += imm_offset;
+       value &= 0xffffffff;
+       addend = (addend & ~howto->src_mask)
+                | ((value & 0x3ff) << 5)
+                | (((value >> 10) & 0x7fff) << 16)
+                | (((value >> 25) & 0x7f) << 32);
+       score_bfd_put_48 (input_bfd, addend, hit_data);
+       return bfd_reloc_ok;
+      }
+
     case R_SCORE_PC19:
-      addend = bfd_get_32 (input_bfd, hit_data);
+      addend = score_bfd_get_32 (input_bfd, hit_data);
       offset = (((addend & howto->src_mask) & 0x3ff0000) >> 6) | ((addend & howto->src_mask) & 0x3ff);
       if ((offset & 0x80000) != 0)
-        offset |= 0xfff00000;
+       offset |= 0xfff00000;
       abs_value = value = value - rel_addr + offset;
       /* exceed 20 bit : overflow.  */
       if ((abs_value & 0x80000000) == 0x80000000)
-        abs_value = 0xffffffff - value + 1;
+       abs_value = 0xffffffff - value + 1;
       if ((abs_value & 0xfff80000) != 0)
-        return bfd_reloc_overflow;
+       return bfd_reloc_overflow;
       addend = (addend & ~howto->src_mask)
-                | (((value << 6) & howto->src_mask) & 0x3ff0000) | (value & 0x3ff);
-      bfd_put_32 (input_bfd, addend, hit_data);
+               | (((value << 6) & howto->src_mask) & 0x3ff0000) | (value & 0x3ff);
+      score_bfd_put_32 (input_bfd, addend, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE16_11:
-      addend = bfd_get_16 (input_bfd, hit_data);
+      addend = score_bfd_get_16 (input_bfd, hit_data);
       offset = addend & howto->src_mask;
-      if ((offset & 0x800) != 0)        /* Offset is negative.  */
-        offset |= 0xfffff000;
+      if ((offset & 0x800) != 0)       /* Offset is negative.  */
+       offset |= 0xfffff000;
       value += offset;
+      abs_value = value - rel_addr;
+      if ((abs_value & 0xfffff000) != 0)
+       return bfd_reloc_overflow;
       addend = (addend & ~howto->src_mask) | (value & howto->src_mask);
-      bfd_put_16 (input_bfd, addend, hit_data);
+      score_bfd_put_16 (input_bfd, addend, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE16_PC8:
-      addend = bfd_get_16 (input_bfd, hit_data);
+      addend = score_bfd_get_16 (input_bfd, hit_data);
       offset = (addend & howto->src_mask) << 1;
-      if ((offset & 0x100) != 0)        /* Offset is negative.  */
-        offset |= 0xfffffe00;
+      if ((offset & 0x200) != 0)       /* Offset is negative.  */
+       offset |= 0xfffffe00;
       abs_value = value = value - rel_addr + offset;
       /* Sign bit + exceed 9 bit.  */
-      if (((value & 0xffffff00) != 0) && ((value & 0xffffff00) != 0xffffff00))
-        return bfd_reloc_overflow;
+      if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00))
+       return bfd_reloc_overflow;
       value >>= 1;
       addend = (addend & ~howto->src_mask) | (value & howto->src_mask);
-      bfd_put_16 (input_bfd, addend, hit_data);
+      score_bfd_put_16 (input_bfd, addend, hit_data);
+      return bfd_reloc_ok;
+
+    case R_SCORE_BCMP:
+      addend = score_bfd_get_32 (input_bfd, hit_data);
+      offset = (addend & howto->src_mask) << howto->rightshift;
+      if ((offset & 0x200) != 0)       /* Offset is negative.  */
+       offset |= 0xfffffe00;
+      value = value - rel_addr + offset;
+      /* Sign bit + exceed 9 bit.  */
+      if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00))
+       return bfd_reloc_overflow;
+      value >>= howto->rightshift;
+      addend = (addend & ~howto->src_mask)
+              | (value & 0x1)
+              | (((value >> 1) & 0x7) << 7)
+              | (((value >> 4) & 0x1f) << 21);
+      score_bfd_put_32 (input_bfd, addend, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE_HI16:
       return bfd_reloc_ok;
 
     case R_SCORE_LO16:
-      hi16_addend = bfd_get_32 (input_bfd, hit_data - 4);
+      hi16_addend = score_bfd_get_32 (input_bfd, hit_data - 4);
       hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
-      addend = bfd_get_32 (input_bfd, hit_data);
+      addend = score_bfd_get_32 (input_bfd, hit_data);
       offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
       offset = (hi16_offset << 16) | (offset & 0xffff);
 
@@ -2097,23 +2296,23 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
 
       hi16_offset = (uvalue >> 16) << 1;
       hi16_value = (hi16_addend & (~(howto->dst_mask)))
-                        | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
-      bfd_put_32 (input_bfd, hi16_value, hit_data - 4);
+                       | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
+      score_bfd_put_32 (input_bfd, hi16_value, hit_data - 4);
       offset = (uvalue & 0xffff) << 1;
       value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
-      bfd_put_32 (input_bfd, value, hit_data);
+      score_bfd_put_32 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE_GP15:
-      addend = bfd_get_32 (input_bfd, hit_data);
+      addend = score_bfd_get_32 (input_bfd, hit_data);
       offset = addend & 0x7fff;
       if ((offset & 0x4000) == 0x4000)
-        offset |= 0xffffc000;
+       offset |= 0xffffc000;
       value = value + offset - gp;
       if (((value & 0xffffc000) != 0) && ((value & 0xffffc000) != 0xffffc000))
-        return bfd_reloc_overflow;
+       return bfd_reloc_overflow;
       value = (addend & ~howto->src_mask) | (value & howto->src_mask);
-      bfd_put_32 (input_bfd, value, hit_data);
+      score_bfd_put_32 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE_GOT15:
@@ -2123,7 +2322,7 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
          bfd_boolean forced;
 
          /* The special case is when the symbol is forced to be local.  We need the
-             full address in the GOT since no R_SCORE_GOT_LO16 relocation follows.  */
+            full address in the GOT since no R_SCORE_GOT_LO16 relocation follows.  */
          forced = ! score_elf_local_relocation_p (input_bfd, rel,
                                                   local_sections, FALSE);
          value = score_elf_got16_entry (output_bfd, input_bfd, info,
@@ -2139,27 +2338,27 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
        }
 
       if ((long) value > 0x3fff || (long) value < -0x4000)
-        return bfd_reloc_overflow;
+       return bfd_reloc_overflow;
 
-      addend = bfd_get_32 (input_bfd, hit_data);
+      addend = score_bfd_get_32 (input_bfd, hit_data);
       value = (addend & ~howto->dst_mask) | (value & howto->dst_mask);
-      bfd_put_32 (input_bfd, value, hit_data);
+      score_bfd_put_32 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE_GPREL32:
       value = (addend + symbol - gp);
       value &= howto->dst_mask;
-      bfd_put_32 (input_bfd, value, hit_data);
+      score_bfd_put_32 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE_GOT_LO16:
-      addend = bfd_get_32 (input_bfd, hit_data);
+      addend = score_bfd_get_32 (input_bfd, hit_data);
       value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1);
       value += symbol;
-      value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1)  
-               | (((value >> 14) & 0x3) << 16);
+      value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1)
+              | (((value >> 14) & 0x3) << 16);
 
-      bfd_put_32 (input_bfd, value, hit_data);
+      score_bfd_put_32 (input_bfd, value, hit_data);
       return bfd_reloc_ok;
 
     case R_SCORE_DUMMY_HI16:
@@ -2176,35 +2375,33 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
 }
 
 /* Score backend functions.  */
-
-static void
-_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
-                         arelent *bfd_reloc,
-                         Elf_Internal_Rela *elf_reloc)
+static bfd_boolean
+s3_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+                           arelent *bfd_reloc,
+                           Elf_Internal_Rela *elf_reloc)
 {
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (elf_reloc->r_info);
-  if (r_type >= NUM_ELEM (elf32_score_howto_table))
-    bfd_reloc->howto = NULL;
-  else
-    bfd_reloc->howto = &elf32_score_howto_table[r_type];
+  if (r_type >= ARRAY_SIZE (elf32_score_howto_table))
+    return FALSE;
+
+  bfd_reloc->howto = &elf32_score_howto_table[r_type];
+  return TRUE;
 }
 
 /* Relocate an score ELF section.  */
-
 static bfd_boolean
-_bfd_score_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)
+s3_bfd_score_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;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
   const char *name;
@@ -2213,16 +2410,11 @@ _bfd_score_elf_relocate_section (bfd *output_bfd,
   size_t extsymoff;
   bfd_boolean gp_disp_p = FALSE;
 
-#ifndef USE_REL
-  if (info->relocatable)
-    return TRUE;
-#endif
-
   /* Sort dynsym.  */
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       bfd_size_type dynsecsymcount = 0;
-      if (info->shared)
+      if (bfd_link_pic (info))
        {
          asection * p;
          const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
@@ -2240,7 +2432,6 @@ _bfd_score_elf_relocate_section (bfd *output_bfd,
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info;
-  sym_hashes = elf_sym_hashes (input_bfd);
   rel = relocs;
   relend = relocs + input_section->reloc_count;
   for (; rel < relend; rel++)
@@ -2258,109 +2449,169 @@ _bfd_score_elf_relocate_section (bfd *output_bfd,
       r_symndx = ELF32_R_SYM (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
 
-      _bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel);
+      if (! s3_bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel))
+       continue;
       howto = bfd_reloc.howto;
 
-      if (info->relocatable)
-        {
-          /* This is a relocatable link.  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];
-                  score_elf_add_to_rel (input_bfd, contents + rel->r_offset,
-                                    howto, (bfd_signed_vma) (sec->output_offset + sym->st_value));
-                }
-            }
-          continue;
-        }
-
-      /* This is a final link.  */
       h = NULL;
       sym = NULL;
       sec = NULL;
 
       if (r_symndx < extsymoff)
-        {
-          sym = local_syms + r_symndx;
-          sec = local_sections[r_symndx];
-          relocation = (sec->output_section->vma
+       {
+         sym = local_syms + r_symndx;
+         sec = local_sections[r_symndx];
+         relocation = (sec->output_section->vma
                        + sec->output_offset
                        + sym->st_value);
-          name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
+         name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
 
-          if ((sec->flags & SEC_MERGE)
+         if (!bfd_link_relocatable (info)
+             && (sec->flags & SEC_MERGE)
              && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-            {
-              asection *msec;
-              bfd_vma addend, value;
-
-              switch (r_type)
-                {
-                case R_SCORE_HI16:
-                  break;
-                case R_SCORE_LO16:
-                  hi16_addend = bfd_get_32 (input_bfd, contents + rel->r_offset - 4);
-                  hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
-                  value = bfd_get_32 (input_bfd, contents + rel->r_offset);
-                  offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1;
-                  addend = (hi16_offset << 16) | (offset & 0xffff);
-                  msec = sec;
-                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
-                  addend -= relocation;
-                  addend += msec->output_section->vma + msec->output_offset;
-                  uvalue = addend;
-                  hi16_offset = (uvalue >> 16) << 1;
-                  hi16_value = (hi16_addend & (~(howto->dst_mask)))
-                    | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
-                  bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4);
-                  offset = (uvalue & 0xffff) << 1;
-                  value = (value & (~(howto->dst_mask)))
-                    | (offset & 0x7fff) | ((offset << 1) & 0x30000);
-                  bfd_put_32 (input_bfd, value, contents + rel->r_offset);
-                  break;
-                case R_SCORE_GOT_LO16:
-                  value = bfd_get_32 (input_bfd, contents + rel->r_offset);
-                  addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
-                  msec = sec;
-                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
-                  addend += msec->output_section->vma + msec->output_offset;
-                  value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
-                           | (((addend >> 14) & 0x3) << 16);
-
-                  bfd_put_32 (input_bfd, value, contents + rel->r_offset);
-                  break;
-                default:
-                  value = bfd_get_32 (input_bfd, contents + rel->r_offset);
-                  /* Get the (signed) value from the instruction.  */
-                  addend = value & howto->src_mask;
-                  if (addend & ((howto->src_mask + 1) >> 1))
-                    {
-                      bfd_signed_vma mask;
-
-                      mask = -1;
-                      mask &= ~howto->src_mask;
-                      addend |= mask;
-                    }
-                  msec = sec;
-                  addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
-                  addend += msec->output_section->vma + msec->output_offset;
-                  value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
-                  bfd_put_32 (input_bfd, value, contents + rel->r_offset);
-                  break;
-                }
-            }
-        }
+           {
+             asection *msec;
+             bfd_vma addend, value;
+
+             switch (r_type)
+               {
+               case R_SCORE_HI16:
+                 break;
+               case R_SCORE_LO16:
+                 hi16_addend = score_bfd_get_32 (input_bfd, contents + rel->r_offset - 4);
+                 hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1;
+                 value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
+                 offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1;
+                 addend = (hi16_offset << 16) | (offset & 0xffff);
+                 msec = sec;
+                 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
+                 addend -= relocation;
+                 addend += msec->output_section->vma + msec->output_offset;
+                 uvalue = addend;
+                 hi16_offset = (uvalue >> 16) << 1;
+                 hi16_value = (hi16_addend & (~(howto->dst_mask)))
+                   | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
+                 score_bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4);
+                 offset = (uvalue & 0xffff) << 1;
+                 value = (value & (~(howto->dst_mask)))
+                   | (offset & 0x7fff) | ((offset << 1) & 0x30000);
+                 score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+                 break;
+
+               case R_SCORE_IMM32:
+                 {
+                   value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
+                   addend = ((value >> 5) & 0x3ff)
+                             | (((value >> 16) & 0x7fff) << 10)
+                             | (((value >> 32) & 0x7f) << 25);
+                   msec = sec;
+                   addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
+                   addend -= relocation;
+                   addend += msec->output_section->vma + msec->output_offset;
+                   addend &= 0xffffffff;
+                   value = (value & ~howto->src_mask)
+                            | ((addend & 0x3ff) << 5)
+                            | (((addend >> 10) & 0x7fff) << 16)
+                            | (((addend >> 25) & 0x7f) << 32);
+                   score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
+                   break;
+                 }
+
+               case R_SCORE_IMM30:
+                 {
+                   int not_word_align_p = 0;
+                   value = score_bfd_get_48 (input_bfd, contents + rel->r_offset);
+                   addend = ((value >> 7) & 0xff)
+                             | (((value >> 16) & 0x7fff) << 8)
+                             | (((value >> 32) & 0x7f) << 23);
+                   addend <<= howto->rightshift;
+                   msec = sec;
+                   addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
+                   addend -= relocation;
+                   addend += msec->output_section->vma + msec->output_offset;
+                   addend &= 0xffffffff;
+
+                   /* Check lw48/sw48 rd, value/label word align.  */
+                   if ((addend & 0x3) != 0)
+                     not_word_align_p = 1;
+
+                   addend >>= howto->rightshift;
+                   value = (value & ~howto->src_mask)
+                            | (((addend & 0xff) >> 0) << 7)
+                            | (((addend & 0x7fff00) >> 8) << 16)
+                            | (((addend & 0x3f800000) >> 23) << 32);
+                   score_bfd_put_48 (input_bfd, value, contents + rel->r_offset);
+
+                   if (not_word_align_p)
+                     return bfd_reloc_other;
+                   else
+                     break;
+                 }
+
+               case R_SCORE_GOT_LO16:
+                 value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
+                 addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
+                 msec = sec;
+                 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
+                 addend += msec->output_section->vma + msec->output_offset;
+                 value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
+                          | (((addend >> 14) & 0x3) << 16);
+
+                 score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+                 break;
+
+               case R_SCORE_ABS32:
+               case R_SCORE_REL32:
+                 value = bfd_get_32 (input_bfd, contents + rel->r_offset);
+                 /* Get the (signed) value from the instruction.  */
+                 addend = value & howto->src_mask;
+                 if (addend & ((howto->src_mask + 1) >> 1))
+                   {
+                     bfd_signed_vma mask;
+
+                     mask = -1;
+                     mask &= ~howto->src_mask;
+                     addend |= mask;
+                   }
+                 msec = sec;
+                 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
+                 addend += msec->output_section->vma + msec->output_offset;
+                 value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
+                 bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+                 break;
+
+               default:
+                 value = score_bfd_get_32 (input_bfd, contents + rel->r_offset);
+                 /* Get the (signed) value from the instruction.  */
+                 addend = value & howto->src_mask;
+                 if (addend & ((howto->src_mask + 1) >> 1))
+                   {
+                     bfd_signed_vma mask;
+
+                     mask = -1;
+                     mask &= ~howto->src_mask;
+                     addend |= mask;
+                   }
+                 msec = sec;
+                 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
+                 addend += msec->output_section->vma + msec->output_offset;
+                 value = (value & ~howto->dst_mask) | (addend & howto->dst_mask);
+                 score_bfd_put_32 (input_bfd, value, contents + rel->r_offset);
+                 break;
+               }
+           }
+       }
       else
-        {
+       {
          /* For global symbols we look up the symbol in the hash-table.  */
          h = ((struct score_elf_link_hash_entry *)
               elf_sym_hashes (input_bfd) [r_symndx - extsymoff]);
+
+         if (info->wrap_hash != NULL
+             && (input_section->flags & SEC_DEBUGGING) != 0)
+           h = ((struct score_elf_link_hash_entry *)
+                unwrap_hash_lookup (info, input_bfd, &h->root.root));
+
          /* Find the real hash-table entry for this symbol.  */
          while (h->root.root.type == bfd_link_hash_indirect
                 || h->root.root.type == bfd_link_hash_warning)
@@ -2410,76 +2661,102 @@ _bfd_score_elf_relocate_section (bfd *output_bfd,
          else if (strcmp (name, "_DYNAMIC_LINK") == 0)
            {
              /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol
-                in _bfd_score_elf_create_dynamic_sections.  Otherwise, we should define
-                 the symbol with a value of 0.  */
-             BFD_ASSERT (! info->shared);
+                in s3_bfd_score_elf_create_dynamic_sections.  Otherwise, we should define
+                the symbol with a value of 0.  */
+             BFD_ASSERT (! bfd_link_pic (info));
              BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL);
              relocation = 0;
            }
-         else
+         else if (!bfd_link_relocatable (info))
            {
-             if (! ((*info->callbacks->undefined_symbol)
-                    (info, h->root.root.root.string, input_bfd,
-                     input_section, rel->r_offset,
-                     (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
-                     || ELF_ST_VISIBILITY (h->root.other))))
-               return bfd_reloc_undefined;
-             relocation = 0;
+              info->callbacks->undefined_symbol
+               (info, h->root.root.root.string, input_bfd, input_section,
+                rel->r_offset,
+                (info->unresolved_syms_in_objects == RM_DIAGNOSE
+                 && !info->warn_unresolved_syms)
+                || ELF_ST_VISIBILITY (h->root.other));
+              relocation = 0;
+            }
+       }
+
+      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.  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];
+                 score_elf_add_to_rel (input_bfd, contents + rel->r_offset,
+                                   howto, (bfd_signed_vma) (sec->output_offset + sym->st_value));
+               }
            }
-        }
+         continue;
+       }
 
+      /* This is a final link.  */
       r = score_elf_final_link_relocate (howto, input_bfd, output_bfd,
-                                         input_section, contents, rel, relocs,
-                                         relocation, info, name,
-                                         (h ? ELF_ST_TYPE ((unsigned int)h->root.root.type) :
+                                        input_section, contents, rel, relocs,
+                                        relocation, info, name,
+                                        (h ? ELF_ST_TYPE ((unsigned int)h->root.root.type) :
                                         ELF_ST_TYPE ((unsigned int)sym->st_info)), h, local_sections,
-                                         gp_disp_p);
+                                        gp_disp_p);
 
       if (r != bfd_reloc_ok)
-        {
-          const char *msg = (const char *)0;
-
-          switch (r)
-            {
-            case bfd_reloc_overflow:
-              /* If the overflowing reloc was to an undefined symbol,
-                 we have already printed one error message and there
-                 is no point complaining again.  */
-              if (((!h) || (h->root.root.type != bfd_link_hash_undefined))
-                  && (!((*info->callbacks->reloc_overflow)
-                        (info, NULL, name, howto->name, (bfd_vma) 0,
-                         input_bfd, input_section, rel->r_offset))))
-                return FALSE;
-              break;
-            case bfd_reloc_undefined:
-              if (!((*info->callbacks->undefined_symbol)
-                    (info, name, input_bfd, input_section, rel->r_offset, TRUE)))
-                return FALSE;
-              break;
-
-            case bfd_reloc_outofrange:
-              msg = _("internal error: out of range error");
-              goto common_error;
-
-            case bfd_reloc_notsupported:
-              msg = _("internal error: unsupported relocation error");
-              goto common_error;
-
-            case bfd_reloc_dangerous:
-              msg = _("internal error: dangerous error");
-              goto common_error;
-
-            default:
-              msg = _("internal error: unknown error");
-              /* fall through */
-
-            common_error:
-              if (!((*info->callbacks->warning)
-                    (info, msg, name, input_bfd, input_section, rel->r_offset)))
-                return FALSE;
-              break;
-            }
-        }
+       {
+         const char *msg = (const char *)0;
+
+         switch (r)
+           {
+           case bfd_reloc_overflow:
+             /* If the overflowing reloc was to an undefined symbol,
+                we have already printed one error message and there
+                is no point complaining again.  */
+             if (!h || h->root.root.type != bfd_link_hash_undefined)
+               (*info->callbacks->reloc_overflow)
+                 (info, NULL, name, howto->name, (bfd_vma) 0,
+                  input_bfd, input_section, rel->r_offset);
+             break;
+           case bfd_reloc_undefined:
+             (*info->callbacks->undefined_symbol)
+               (info, name, input_bfd, input_section, rel->r_offset, TRUE);
+             break;
+
+           case bfd_reloc_outofrange:
+             msg = _("internal error: out of range error");
+             goto common_error;
+
+           case bfd_reloc_notsupported:
+             msg = _("internal error: unsupported relocation error");
+             goto common_error;
+
+           case bfd_reloc_dangerous:
+             msg = _("internal error: dangerous error");
+             goto common_error;
+
+           /* Use bfd_reloc_other to check lw48, sw48 word align.  */
+           case bfd_reloc_other:
+             msg = _("address not word aligned");
+             goto common_error;
+
+           default:
+             msg = _("internal error: unknown error");
+             /* Fall through.  */
+
+           common_error:
+             (*info->callbacks->warning) (info, msg, name, input_bfd,
+                                          input_section, rel->r_offset);
+             break;
+           }
+       }
     }
 
   return TRUE;
@@ -2487,14 +2764,12 @@ _bfd_score_elf_relocate_section (bfd *output_bfd,
 
 /* Look through the relocs for a section during the first phase, and
    allocate space in the global offset table.  */
-
 static bfd_boolean
-_bfd_score_elf_check_relocs (bfd *abfd,
-                            struct bfd_link_info *info,
-                            asection *sec,
-                            const Elf_Internal_Rela *relocs)
+s3_bfd_score_elf_check_relocs (bfd *abfd,
+                              struct bfd_link_info *info,
+                              asection *sec,
+                              const Elf_Internal_Rela *relocs)
 {
-  const char *name;
   bfd *dynobj;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -2504,9 +2779,8 @@ _bfd_score_elf_check_relocs (bfd *abfd,
   const Elf_Internal_Rela *rel_end;
   asection *sgot;
   asection *sreloc;
-  const struct elf_backend_data *bed;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   dynobj = elf_hash_table (info)->dynobj;
@@ -2514,8 +2788,6 @@ _bfd_score_elf_check_relocs (bfd *abfd,
   sym_hashes = elf_sym_hashes (abfd);
   extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
 
-  name = bfd_get_section_name (abfd, sec);
-
   if (dynobj == NULL)
     {
       sgot = NULL;
@@ -2525,18 +2797,17 @@ _bfd_score_elf_check_relocs (bfd *abfd,
     {
       sgot = score_elf_got_section (dynobj, FALSE);
       if (sgot == NULL)
-        g = NULL;
+       g = NULL;
       else
-        {
-          BFD_ASSERT (score_elf_section_data (sgot) != NULL);
-          g = score_elf_section_data (sgot)->u.got_info;
-          BFD_ASSERT (g != NULL);
-        }
+       {
+         BFD_ASSERT (score_elf_section_data (sgot) != NULL);
+         g = score_elf_section_data (sgot)->u.got_info;
+         BFD_ASSERT (g != NULL);
+       }
     }
 
   sreloc = NULL;
-  bed = get_elf_backend_data (abfd);
-  rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+  rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; ++rel)
     {
       unsigned long r_symndx;
@@ -2548,63 +2819,68 @@ _bfd_score_elf_check_relocs (bfd *abfd,
 
       if (r_symndx < extsymoff)
        {
-          h = NULL;
+         h = NULL;
        }
       else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
-        {
-          (*_bfd_error_handler) (_("%s: Malformed reloc detected for section %s"), abfd, name);
-          bfd_set_error (bfd_error_bad_value);
-          return FALSE;
-        }
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%pB: malformed reloc detected for section %pA"), abfd, sec);
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
       else
-        {
-          h = sym_hashes[r_symndx - extsymoff];
-
-          /* This may be an indirect symbol created because of a version.  */
-          if (h != NULL)
-            {
-              while (h->root.type == bfd_link_hash_indirect)
-                h = (struct elf_link_hash_entry *)h->root.u.i.link;
-            }
-        }
+       {
+         h = sym_hashes[r_symndx - extsymoff];
+
+         /* This may be an indirect symbol created because of a version.  */
+         if (h != NULL)
+           {
+             while (h->root.type == bfd_link_hash_indirect)
+               h = (struct elf_link_hash_entry *)h->root.u.i.link;
+           }
+       }
 
       /* Some relocs require a global offset table.  */
       if (dynobj == NULL || sgot == NULL)
-        {
-          switch (r_type)
-            {
-            case R_SCORE_GOT15:
-            case R_SCORE_CALL15:
-              if (dynobj == NULL)
-                elf_hash_table (info)->dynobj = dynobj = abfd;
-              if (!score_elf_create_got_section (dynobj, info, FALSE))
-                return FALSE;
-              g = score_elf_got_info (dynobj, &sgot);
-              break;
-            case R_SCORE_ABS32:
-            case R_SCORE_REL32:
-              if (dynobj == NULL && (info->shared || h != NULL) && (sec->flags & SEC_ALLOC) != 0)
-                elf_hash_table (info)->dynobj = dynobj = abfd;
-              break;
-            default:
-              break;
-            }
-        }
+       {
+         switch (r_type)
+           {
+           case R_SCORE_GOT15:
+           case R_SCORE_CALL15:
+             if (dynobj == NULL)
+               elf_hash_table (info)->dynobj = dynobj = abfd;
+             if (!score_elf_create_got_section (dynobj, info, FALSE))
+               return FALSE;
+             g = score_elf_got_info (dynobj, &sgot);
+             break;
+           case R_SCORE_ABS32:
+           case R_SCORE_REL32:
+             if (dynobj == NULL
+                 && (bfd_link_pic (info) || h != NULL)
+                 && (sec->flags & SEC_ALLOC) != 0)
+               elf_hash_table (info)->dynobj = dynobj = abfd;
+             break;
+           default:
+             break;
+           }
+       }
 
       if (!h && (r_type == R_SCORE_GOT_LO16))
-        {
+       {
          if (! score_elf_record_local_got_symbol (abfd, r_symndx, rel->r_addend, g))
            return FALSE;
-        }
+       }
 
       switch (r_type)
-        {
-        case R_SCORE_CALL15:
+       {
+       case R_SCORE_CALL15:
          if (h == NULL)
            {
-             (*_bfd_error_handler)
-               (_("%B: CALL15 reloc at 0x%lx not against global symbol"),
-                abfd, (unsigned long) rel->r_offset);
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%pB: CALL15 reloc at %#" PRIx64 " not against global symbol"),
+                abfd, (uint64_t) rel->r_offset);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
            }
@@ -2615,18 +2891,19 @@ _bfd_score_elf_check_relocs (bfd *abfd,
                return FALSE;
 
              /* We need a stub, not a plt entry for the undefined function.  But we record
-                 it as if it needs plt.  See _bfd_elf_adjust_dynamic_symbol.  */
+                it as if it needs plt.  See _bfd_elf_adjust_dynamic_symbol.  */
              h->needs_plt = 1;
              h->type = STT_FUNC;
            }
-          break;
+         break;
        case R_SCORE_GOT15:
          if (h && ! score_elf_record_global_got_symbol (h, abfd, info, g))
            return FALSE;
          break;
-        case R_SCORE_ABS32:
-        case R_SCORE_REL32:
-         if ((info->shared || h != NULL) && (sec->flags & SEC_ALLOC) != 0)
+       case R_SCORE_ABS32:
+       case R_SCORE_REL32:
+         if ((bfd_link_pic (info) || h != NULL)
+             && (sec->flags & SEC_ALLOC) != 0)
            {
              if (sreloc == NULL)
                {
@@ -2635,11 +2912,11 @@ _bfd_score_elf_check_relocs (bfd *abfd,
                    return FALSE;
                }
 #define SCORE_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY)
-             if (info->shared)
+             if (bfd_link_pic (info))
                {
                  /* When creating a shared object, we must copy these reloc types into
-                     the output file as R_SCORE_REL32 relocs.  We make room for this reloc
-                     in the .rel.dyn reloc section.  */
+                    the output file as R_SCORE_REL32 relocs.  We make room for this reloc
+                    in the .rel.dyn reloc section.  */
                  score_elf_allocate_dynamic_relocations (dynobj, 1);
                  if ((sec->flags & SCORE_READONLY_SECTION)
                      == SCORE_READONLY_SECTION)
@@ -2652,7 +2929,7 @@ _bfd_score_elf_check_relocs (bfd *abfd,
                  struct score_elf_link_hash_entry *hscore;
 
                  /* We only need to copy this reloc if the symbol is
-                     defined in a dynamic object.  */
+                    defined in a dynamic object.  */
                  hscore = (struct score_elf_link_hash_entry *)h;
                  ++hscore->possibly_dynamic_relocs;
                  if ((sec->flags & SCORE_READONLY_SECTION)
@@ -2663,8 +2940,8 @@ _bfd_score_elf_check_relocs (bfd *abfd,
                }
 
              /* Even though we don't directly need a GOT entry for this symbol,
-                 a symbol must have a dynamic symbol table index greater that
-                 DT_SCORE_GOTSYM if there are dynamic relocations against it.  */
+                a symbol must have a dynamic symbol table index greater that
+                DT_SCORE_GOTSYM if there are dynamic relocations against it.  */
              if (h != NULL)
                {
                  if (dynobj == NULL)
@@ -2678,25 +2955,25 @@ _bfd_score_elf_check_relocs (bfd *abfd,
            }
          break;
 
-          /* This relocation describes the C++ object vtable hierarchy.
-             Reconstruct it for later use during GC.  */
-        case R_SCORE_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_SCORE_GNU_VTENTRY:
-          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
-            return FALSE;
-          break;
-        default:
-          break;
-        }
+         /* This relocation describes the C++ object vtable hierarchy.
+            Reconstruct it for later use during GC.  */
+       case R_SCORE_GNU_VTINHERIT:
+         if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+           return FALSE;
+         break;
 
-      /* We must not create a stub for a symbol that has relocations
-         related to taking the function's address.  */
+         /* This relocation describes which C++ vtable entries are actually
+            used.  Record for later use during GC.  */
+       case R_SCORE_GNU_VTENTRY:
+         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+           return FALSE;
+         break;
+       default:
+         break;
+       }
+
+      /* We must not create a stub for a symbol that has relocations
+        related to taking the function's address.  */
       switch (r_type)
        {
        default:
@@ -2717,19 +2994,19 @@ _bfd_score_elf_check_relocs (bfd *abfd,
 }
 
 static bfd_boolean
-_bfd_score_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)
+s3_bfd_score_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)
 {
   switch (sym->st_shndx)
     {
     case SHN_COMMON:
       if (sym->st_size > elf_gp_size (abfd))
-        break;
+       break;
       /* Fall through.  */
     case SHN_SCORE_SCOMMON:
       *secp = bfd_make_section_old_way (abfd, ".scommon");
@@ -2742,7 +3019,7 @@ _bfd_score_elf_add_symbol_hook (bfd *abfd,
 }
 
 static void
-_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
+s3_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
 {
   elf_symbol_type *elfsym;
 
@@ -2751,34 +3028,34 @@ _bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
     {
     case SHN_COMMON:
       if (asym->value > elf_gp_size (abfd))
-        break;
+       break;
       /* Fall through.  */
     case SHN_SCORE_SCOMMON:
       if (score_elf_scom_section.name == NULL)
-        {
-          /* Initialize the small common section.  */
-          score_elf_scom_section.name = ".scommon";
-          score_elf_scom_section.flags = SEC_IS_COMMON;
-          score_elf_scom_section.output_section = &score_elf_scom_section;
-          score_elf_scom_section.symbol = &score_elf_scom_symbol;
-          score_elf_scom_section.symbol_ptr_ptr = &score_elf_scom_symbol_ptr;
-          score_elf_scom_symbol.name = ".scommon";
-          score_elf_scom_symbol.flags = BSF_SECTION_SYM;
-          score_elf_scom_symbol.section = &score_elf_scom_section;
-          score_elf_scom_symbol_ptr = &score_elf_scom_symbol;
-        }
+       {
+         /* Initialize the small common section.  */
+         score_elf_scom_section.name = ".scommon";
+         score_elf_scom_section.flags = SEC_IS_COMMON;
+         score_elf_scom_section.output_section = &score_elf_scom_section;
+         score_elf_scom_section.symbol = &score_elf_scom_symbol;
+         score_elf_scom_section.symbol_ptr_ptr = &score_elf_scom_symbol_ptr;
+         score_elf_scom_symbol.name = ".scommon";
+         score_elf_scom_symbol.flags = BSF_SECTION_SYM;
+         score_elf_scom_symbol.section = &score_elf_scom_section;
+         score_elf_scom_symbol_ptr = &score_elf_scom_symbol;
+       }
       asym->section = &score_elf_scom_section;
       asym->value = elfsym->internal_elf_sym.st_size;
       break;
     }
 }
 
-static bfd_boolean
-_bfd_score_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)
+static int
+s3_bfd_score_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 we see a common symbol, which implies a relocatable link, then
      if a symbol was small common in an input file, mark it as small
@@ -2786,15 +3063,15 @@ _bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNU
   if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0)
     sym->st_shndx = SHN_SCORE_SCOMMON;
 
-  return TRUE;
+  return 1;
 }
 
 static bfd_boolean
-_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
-                                        asection *sec,
-                                        int *retval)
+s3_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+                                          asection *sec,
+                                          int *retval)
 {
-  if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
+  if (strcmp (bfd_section_name (sec), ".scommon") == 0)
     {
       *retval = SHN_SCORE_SCOMMON;
       return TRUE;
@@ -2807,10 +3084,9 @@ _bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
    change the definition to something the rest of the link can understand.  */
-
 static bfd_boolean
-_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
-                                     struct elf_link_hash_entry *h)
+s3_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
+                                       struct elf_link_hash_entry *h)
 {
   bfd *dynobj;
   struct score_elf_link_hash_entry *hscore;
@@ -2820,59 +3096,59 @@ _bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   /* Make sure we know what is going on here.  */
   BFD_ASSERT (dynobj != NULL
-              && (h->needs_plt
-                  || h->u.weakdef != NULL
-                  || (h->def_dynamic && h->ref_regular && !h->def_regular)));
+             && (h->needs_plt
+                 || h->is_weakalias
+                 || (h->def_dynamic && h->ref_regular && !h->def_regular)));
 
   /* If this symbol is defined in a dynamic object, we need to copy
      any R_SCORE_ABS32 or R_SCORE_REL32 relocs against it into the output
      file.  */
   hscore = (struct score_elf_link_hash_entry *)h;
-  if (!info->relocatable
+  if (!bfd_link_relocatable (info)
       && hscore->possibly_dynamic_relocs != 0
       && (h->root.type == bfd_link_hash_defweak || !h->def_regular))
     {
       score_elf_allocate_dynamic_relocations (dynobj, hscore->possibly_dynamic_relocs);
       if (hscore->readonly_reloc)
-        /* We tell the dynamic linker that there are relocations
-           against the text segment.  */
-        info->flags |= DF_TEXTREL;
+       /* We tell the dynamic linker that there are relocations
+          against the text segment.  */
+       info->flags |= DF_TEXTREL;
     }
 
   /* For a function, create a stub, if allowed.  */
   if (!hscore->no_fn_stub && h->needs_plt)
     {
       if (!elf_hash_table (info)->dynamic_sections_created)
-        return TRUE;
+       return TRUE;
 
       /* If this symbol is not defined in a regular file, then set
-         the symbol to the stub location.  This is required to make
-         function pointers compare as equal between the normal
-         executable and the shared library.  */
+        the symbol to the stub location.  This is required to make
+        function pointers compare as equal between the normal
+        executable and the shared library.  */
       if (!h->def_regular)
-        {
-          /* We need .stub section.  */
-          s = bfd_get_section_by_name (dynobj, SCORE_ELF_STUB_SECTION_NAME);
-          BFD_ASSERT (s != NULL);
+       {
+         /* We need .stub section.  */
+         s = bfd_get_linker_section (dynobj, SCORE_ELF_STUB_SECTION_NAME);
+         BFD_ASSERT (s != NULL);
 
-          h->root.u.def.section = s;
-          h->root.u.def.value = s->size;
+         h->root.u.def.section = s;
+         h->root.u.def.value = s->size;
 
-          /* XXX Write this stub address somewhere.  */
-          h->plt.offset = s->size;
+         /* XXX Write this stub address somewhere.  */
+         h->plt.offset = s->size;
 
-          /* Make room for this stub code.  */
-          s->size += SCORE_FUNCTION_STUB_SIZE;
+         /* Make room for this stub code.  */
+         s->size += SCORE_FUNCTION_STUB_SIZE;
 
-          /* The last half word of the stub will be filled with the index
-             of this symbol in .dynsym section.  */
-          return TRUE;
-        }
+         /* The last half word of the stub will be filled with the index
+            of this symbol in .dynsym section.  */
+         return TRUE;
+       }
     }
   else if ((h->type == STT_FUNC) && !h->needs_plt)
     {
       /* This will set the entry for this symbol in the GOT to 0, and
-         the dynamic linker will take care of this.  */
+        the dynamic linker will take care of this.  */
       h->root.u.def.value = 0;
       return TRUE;
     }
@@ -2880,12 +3156,12 @@ _bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   /* If this is a weak symbol, and there is a real definition, the
      processor independent code will have arranged for us to see the
      real definition first, and we can just use the same value.  */
-  if (h->u.weakdef != NULL)
+  if (h->is_weakalias)
     {
-      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
-                  || h->u.weakdef->root.type == bfd_link_hash_defweak);
-      h->root.u.def.section = h->u.weakdef->root.u.def.section;
-      h->root.u.def.value = h->u.weakdef->root.u.def.value;
+      struct elf_link_hash_entry *def = weakdef (h);
+      BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+      h->root.u.def.section = def->root.u.def.section;
+      h->root.u.def.value = def->root.u.def.value;
       return TRUE;
     }
 
@@ -2896,10 +3172,9 @@ _bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
 /* This function is called after all the input files have been read,
    and the input sections have been assigned to output sections.  */
-
 static bfd_boolean
-_bfd_score_elf_always_size_sections (bfd *output_bfd,
-                                    struct bfd_link_info *info)
+s3_bfd_score_elf_always_size_sections (bfd *output_bfd,
+                                      struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *s;
@@ -2920,7 +3195,7 @@ _bfd_score_elf_always_size_sections (bfd *output_bfd,
 
   /* Calculate the total loadable size of the output.  That will give us the
      maximum number of GOT_PAGE entries required.  */
-  for (sub = info->input_bfds; sub; sub = sub->link_next)
+  for (sub = info->input_bfds; sub; sub = sub->link.next)
     {
       asection *subsection;
 
@@ -2974,9 +3249,8 @@ _bfd_score_elf_always_size_sections (bfd *output_bfd,
 }
 
 /* Set the sizes of the dynamic sections.  */
-
 static bfd_boolean
-_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
+s3_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *s;
@@ -2988,13 +3262,13 @@ _bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (!info->shared)
-        {
-          s = bfd_get_section_by_name (dynobj, ".interp");
-          BFD_ASSERT (s != NULL);
-          s->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
-          s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
-        }
+      if (bfd_link_executable (info) && !info->nointerp)
+       {
+         s = bfd_get_linker_section (dynobj, ".interp");
+         BFD_ASSERT (s != NULL);
+         s->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
+         s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
+       }
     }
 
   /* The check_relocs and adjust_dynamic_symbol entry points have
@@ -3006,83 +3280,82 @@ _bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf
       const char *name;
 
       if ((s->flags & SEC_LINKER_CREATED) == 0)
-        continue;
+       continue;
 
       /* It's OK to base decisions on the section name, because none
-         of the dynobj section names depend upon the input files.  */
-      name = bfd_get_section_name (dynobj, s);
+        of the dynobj section names depend upon the input files.  */
+      name = bfd_section_name (s);
 
       if (CONST_STRNEQ (name, ".rel"))
-        {
-          if (s->size == 0)
-            {
-              /* We only strip the section if the output section name
-                 has the same name.  Otherwise, there might be several
-                 input sections for this output section.  FIXME: This
-                 code is probably not needed these days anyhow, since
-                 the linker now does not create empty output sections.  */
-              if (s->output_section != NULL
-                  && strcmp (name,
-                             bfd_get_section_name (s->output_section->owner,
-                                                   s->output_section)) == 0)
-                s->flags |= SEC_EXCLUDE;
-            }
-          else
-            {
-              const char *outname;
-              asection *target;
-
-              /* If this relocation section applies to a read only
-                 section, then we probably need a DT_TEXTREL entry.
-                 If the relocation section is .rel.dyn, we always
-                 assert a DT_TEXTREL entry rather than testing whether
-                 there exists a relocation to a read only section or
-                 not.  */
-              outname = bfd_get_section_name (output_bfd, s->output_section);
-              target = bfd_get_section_by_name (output_bfd, outname + 4);
-              if ((target != NULL
-                   && (target->flags & SEC_READONLY) != 0
-                   && (target->flags & SEC_ALLOC) != 0) || strcmp (outname, ".rel.dyn") == 0)
-                reltext = TRUE;
-
-              /* We use the reloc_count field as a counter if we need
-                 to copy relocs into the output file.  */
-              if (strcmp (name, ".rel.dyn") != 0)
-                s->reloc_count = 0;
-            }
-        }
+       {
+         if (s->size == 0)
+           {
+             /* We only strip the section if the output section name
+                has the same name.  Otherwise, there might be several
+                input sections for this output section.  FIXME: This
+                code is probably not needed these days anyhow, since
+                the linker now does not create empty output sections.  */
+             if (s->output_section != NULL
+                 && strcmp (name,
+                            bfd_section_name (s->output_section)) == 0)
+               s->flags |= SEC_EXCLUDE;
+           }
+         else
+           {
+             const char *outname;
+             asection *target;
+
+             /* If this relocation section applies to a read only
+                section, then we probably need a DT_TEXTREL entry.
+                If the relocation section is .rel.dyn, we always
+                assert a DT_TEXTREL entry rather than testing whether
+                there exists a relocation to a read only section or
+                not.  */
+             outname = bfd_section_name (s->output_section);
+             target = bfd_get_section_by_name (output_bfd, outname + 4);
+             if ((target != NULL
+                  && (target->flags & SEC_READONLY) != 0
+                  && (target->flags & SEC_ALLOC) != 0) || strcmp (outname, ".rel.dyn") == 0)
+               reltext = TRUE;
+
+             /* We use the reloc_count field as a counter if we need
+                to copy relocs into the output file.  */
+             if (strcmp (name, ".rel.dyn") != 0)
+               s->reloc_count = 0;
+           }
+       }
       else if (CONST_STRNEQ (name, ".got"))
-        {
-         /* _bfd_score_elf_always_size_sections() has already done
+       {
+         /* s3_bfd_score_elf_always_size_sections() has already done
             most of the work, but some symbols may have been mapped
             to versions that we must now resolve in the got_entries
             hash tables.  */
-        }
+       }
       else if (strcmp (name, SCORE_ELF_STUB_SECTION_NAME) == 0)
-        {
-          /* IRIX rld assumes that the function stub isn't at the end
-             of .text section. So put a dummy. XXX  */
-          s->size += SCORE_FUNCTION_STUB_SIZE;
-        }
+       {
+         /* IRIX rld assumes that the function stub isn't at the end
+            of .text section. So put a dummy. XXX  */
+         s->size += SCORE_FUNCTION_STUB_SIZE;
+       }
       else if (! CONST_STRNEQ (name, ".init"))
-        {
-          /* It's not one of our sections, so don't allocate space.  */
-          continue;
-        }
+       {
+         /* It's not one of our sections, so don't allocate space.  */
+         continue;
+       }
 
       /* Allocate memory for the section contents.  */
       s->contents = bfd_zalloc (dynobj, s->size);
       if (s->contents == NULL && s->size != 0)
-        {
-          bfd_set_error (bfd_error_no_memory);
-          return FALSE;
-        }
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return FALSE;
+       }
     }
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Add some entries to the .dynamic section.  We fill in the
-        values later, in _bfd_score_elf_finish_dynamic_sections, but we
+        values later, in s3_bfd_score_elf_finish_dynamic_sections, but we
         must add the entries now so that we get the correct size for
         the .dynamic section.  The DT_DEBUG entry is filled in by the
         dynamic linker and used by the debugger.  */
@@ -3115,19 +3388,19 @@ _bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf
        }
 
       if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_BASE_ADDRESS, 0))
-        return FALSE;
+       return FALSE;
 
       if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_LOCAL_GOTNO, 0))
-        return FALSE;
+       return FALSE;
 
       if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_SYMTABNO, 0))
-        return FALSE;
+       return FALSE;
 
       if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_UNREFEXTNO, 0))
-        return FALSE;
+       return FALSE;
 
       if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_GOTSYM, 0))
-        return FALSE;
+       return FALSE;
 
       if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_HIPAGENO, 0))
        return FALSE;
@@ -3137,7 +3410,7 @@ _bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf
 }
 
 static bfd_boolean
-_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
+s3_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   struct elf_link_hash_entry *h;
   struct bfd_link_hash_entry *bh;
@@ -3145,14 +3418,14 @@ _bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   asection *s;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
-           | SEC_LINKER_CREATED | SEC_READONLY);
+          | SEC_LINKER_CREATED | SEC_READONLY);
 
   /* ABI requests the .dynamic section to be read only.  */
-  s = bfd_get_section_by_name (abfd, ".dynamic");
+  s = bfd_get_linker_section (abfd, ".dynamic");
   if (s != NULL)
     {
-      if (!bfd_set_section_flags (abfd, s, flags))
-        return FALSE;
+      if (!bfd_set_section_flags (s, flags))
+       return FALSE;
     }
 
   /* We need to create .got section.  */
@@ -3163,26 +3436,26 @@ _bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   /* Create .stub section.  */
-  if (bfd_get_section_by_name (abfd, SCORE_ELF_STUB_SECTION_NAME) == NULL)
+  if (bfd_get_linker_section (abfd, SCORE_ELF_STUB_SECTION_NAME) == NULL)
     {
-      s = bfd_make_section_with_flags (abfd, SCORE_ELF_STUB_SECTION_NAME,
-                                       flags | SEC_CODE);
+      s = bfd_make_section_anyway_with_flags (abfd, SCORE_ELF_STUB_SECTION_NAME,
+                                             flags | SEC_CODE);
       if (s == NULL
-          || !bfd_set_section_alignment (abfd, s, 2))
+         || !bfd_set_section_alignment (s, 2))
 
-        return FALSE;
+       return FALSE;
     }
 
-  if (!info->shared)
+  if (!bfd_link_pic (info))
     {
       const char *name;
 
       name = "_DYNAMIC_LINK";
       bh = NULL;
       if (!(_bfd_generic_link_add_one_symbol
-            (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
-             (bfd_vma) 0, (const char *)NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
-        return FALSE;
+           (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr,
+            (bfd_vma) 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh)))
+       return FALSE;
 
       h = (struct elf_link_hash_entry *)bh;
       h->non_elf = 0;
@@ -3190,7 +3463,7 @@ _bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       h->type = STT_SECTION;
 
       if (!bfd_elf_link_record_dynamic_symbol (info, h))
-        return FALSE;
+       return FALSE;
     }
 
   return TRUE;
@@ -3199,12 +3472,11 @@ _bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
-
 static bfd_boolean
-_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
-                                     struct bfd_link_info *info,
-                                     struct elf_link_hash_entry *h,
-                                     Elf_Internal_Sym *sym)
+s3_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
+                                       struct bfd_link_info *info,
+                                       struct elf_link_hash_entry *h,
+                                       Elf_Internal_Sym *sym)
 {
   bfd *dynobj;
   asection *sgot;
@@ -3221,7 +3493,7 @@ _bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
       /* This symbol has a stub.  Set it up.  */
       BFD_ASSERT (h->dynindx != -1);
 
-      s = bfd_get_section_by_name (dynobj, SCORE_ELF_STUB_SECTION_NAME);
+      s = bfd_get_linker_section (dynobj, SCORE_ELF_STUB_SECTION_NAME);
       BFD_ASSERT (s != NULL);
 
       /* FIXME: Can h->dynindex be more than 64K?  */
@@ -3229,10 +3501,10 @@ _bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
        return FALSE;
 
       /* Fill the stub.  */
-      bfd_put_32 (output_bfd, STUB_LW, stub);
-      bfd_put_32 (output_bfd, STUB_MOVE, stub + 4);
-      bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8);
-      bfd_put_32 (output_bfd, STUB_BRL, stub + 12);
+      score_bfd_put_32 (output_bfd, STUB_LW, stub);
+      score_bfd_put_32 (output_bfd, STUB_MOVE, stub + 4);
+      score_bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8);
+      score_bfd_put_32 (output_bfd, STUB_BRL, stub + 12);
 
       BFD_ASSERT (h->plt.offset <= s->size);
       memcpy (s->contents + h->plt.offset, stub, SCORE_FUNCTION_STUB_SIZE);
@@ -3264,12 +3536,13 @@ _bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       value = sym->st_value;
       offset = score_elf_global_got_index (dynobj, h);
-      bfd_put_32 (output_bfd, value, sgot->contents + offset);
+      score_bfd_put_32 (output_bfd, value, sgot->contents + offset);
     }
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
   name = h->root.root.string;
-  if (strcmp (name, "_DYNAMIC") == 0 || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+  if (h == elf_hash_table (info)->hdynamic
+      || h == elf_hash_table (info)->hgot)
     sym->st_shndx = SHN_ABS;
   else if (strcmp (name, "_DYNAMIC_LINK") == 0)
     {
@@ -3288,10 +3561,9 @@ _bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
 }
 
 /* Finish up the dynamic sections.  */
-
 static bfd_boolean
-_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
-                                       struct bfd_link_info *info)
+s3_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
+                                         struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *sdyn;
@@ -3301,7 +3573,7 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
 
   dynobj = elf_hash_table (info)->dynobj;
 
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   sgot = score_elf_got_section (dynobj, FALSE);
   if (sgot == NULL)
@@ -3338,21 +3610,18 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
          switch (dyn.d_tag)
            {
            case DT_RELENT:
-             s = score_elf_rel_dyn_section (dynobj, FALSE);
-             BFD_ASSERT (s != NULL);
              dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj);
              break;
 
            case DT_STRSZ:
              /* Rewrite DT_STRSZ.  */
-             dyn.d_un.d_val = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
-                   break;
+             dyn.d_un.d_val
+               = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
+             break;
 
            case DT_PLTGOT:
-             name = ".got";
-             s = bfd_get_section_by_name (output_bfd, name);
-             BFD_ASSERT (s != NULL);
-             dyn.d_un.d_ptr = s->vma;
+             s = elf_hash_table (info)->sgot;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_SCORE_BASE_ADDRESS:
@@ -3380,14 +3649,13 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
                }
              /* In case if we don't have global got symbols we default
                  to setting DT_SCORE_GOTSYM to the same value as
-                 DT_SCORE_SYMTABNO, so we just fall through.  */
+                 DT_SCORE_SYMTABNO.  */
+             /* Fall through.  */
 
            case DT_SCORE_SYMTABNO:
              name = ".dynsym";
              elemsize = SCORE_ELF_SYM_SIZE (output_bfd);
-             s = bfd_get_section_by_name (output_bfd, name);
-             BFD_ASSERT (s != NULL);
-
+             s = bfd_get_linker_section (dynobj, name);
              dyn.d_un.d_val = s->size / elemsize;
              break;
 
@@ -3410,8 +3678,8 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
      This isn't the case of IRIX rld.  */
   if (sgot != NULL && sgot->size > 0)
     {
-      bfd_put_32 (output_bfd, 0, sgot->contents);
-      bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd));
+      score_bfd_put_32 (output_bfd, 0, sgot->contents);
+      score_bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd));
     }
 
   if (sgot != NULL)
@@ -3434,15 +3702,14 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
 
 /* This function set up the ELF section header for a BFD section in preparation for writing
    it out.  This is where the flags and type fields are set for unusual sections.  */
-
 static bfd_boolean
-_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
-                             Elf_Internal_Shdr *hdr,
-                             asection *sec)
+s3_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
+                               Elf_Internal_Shdr *hdr,
+                               asection *sec)
 {
   const char *name;
 
-  name = bfd_get_section_name (abfd, sec);
+  name = bfd_section_name (sec);
 
   if (strcmp (name, ".got") == 0
       || strcmp (name, ".srdata") == 0
@@ -3460,13 +3727,12 @@ _bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
    warning message will be issued.  backend_fake_section is called before
    assign_file_positions_except_relocs(); backend_section_processing after it.  so, we
    modify section flag there, but not backend_fake_section.  */
-
 static bfd_boolean
-_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
+s3_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
 {
   if (hdr->bfd_section != NULL)
     {
-      const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
+      const char *name = bfd_section_name (hdr->bfd_section);
 
       if (strcmp (name, ".sdata") == 0)
        {
@@ -3489,7 +3755,7 @@ _bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr
 }
 
 static bfd_boolean
-_bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents)
+s3_bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents)
 {
   bfd_byte *to, *from, *end;
   int i;
@@ -3505,26 +3771,25 @@ _bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents
   for (from = contents, i = 0; from < end; from += PDR_SIZE, i++)
     {
       if ((score_elf_section_data (sec)->u.tdata)[i] == 1)
-        continue;
+       continue;
 
       if (to != from)
-        memcpy (to, from, PDR_SIZE);
+       memcpy (to, from, PDR_SIZE);
 
       to += PDR_SIZE;
     }
   bfd_set_section_contents (output_bfd, sec->output_section, contents,
-                            (file_ptr) sec->output_offset, sec->size);
+                           (file_ptr) sec->output_offset, sec->size);
 
   return TRUE;
 }
 
 /* Copy data from a SCORE ELF indirect symbol to its direct symbol, hiding the old
    indirect symbol.  Process additional relocation information.  */
-
 static void
-_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
-                                    struct elf_link_hash_entry *dir,
-                                    struct elf_link_hash_entry *ind)
+s3_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
+                                      struct elf_link_hash_entry *dir,
+                                      struct elf_link_hash_entry *ind)
 {
   struct score_elf_link_hash_entry *dirscore, *indscore;
 
@@ -3545,10 +3810,9 @@ _bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
 }
 
 /* Remove information about discarded functions from other sections which mention them.  */
-
 static bfd_boolean
-_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
-                         struct bfd_link_info *info)
+s3_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
+                              struct bfd_link_info *info)
 {
   asection *o;
   bfd_boolean ret = FALSE;
@@ -3577,10 +3841,10 @@ _bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
   for (i = 0, skip = 0; i < o->size; i++)
     {
       if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie))
-        {
-          tdata[i] = 1;
-          skip++;
-        }
+       {
+         tdata[i] = 1;
+         skip++;
+       }
     }
 
   if (skip != 0)
@@ -3599,9 +3863,8 @@ _bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
 }
 
 /* Signal that discard_info() has removed the discarded relocations for this section.  */
-
 static bfd_boolean
-_bfd_score_elf_ignore_discarded_relocs (asection *sec)
+s3_bfd_score_elf_ignore_discarded_relocs (asection *sec)
 {
   if (strcmp (sec->name, ".pdr") == 0)
     return TRUE;
@@ -3610,13 +3873,12 @@ _bfd_score_elf_ignore_discarded_relocs (asection *sec)
 
 /* Return the section that should be marked against GC for a given
    relocation.  */
-
 static asection *
-_bfd_score_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)
+s3_bfd_score_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 (ELF32_R_TYPE (rel->r_info))
@@ -3632,7 +3894,7 @@ _bfd_score_elf_gc_mark_hook (asection *sec,
 /* Support for core dump NOTE sections.  */
 
 static bfd_boolean
-_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
+s3_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   int offset;
   unsigned int raw_size;
@@ -3642,12 +3904,14 @@ _bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
     default:
       return FALSE;
 
-    case 148:                  /* Linux/Score 32-bit.  */
+    case 148:                 /* Linux/Score 32-bit.  */
       /* pr_cursig */
-      elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+      elf_tdata (abfd)->core->signal
+       = score_bfd_get_16 (abfd, note->descdata + 12);
 
       /* pr_pid */
-      elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+      elf_tdata (abfd)->core->lwpid
+       = score_bfd_get_32 (abfd, note->descdata + 24);
 
       /* pr_reg */
       offset = 72;
@@ -3657,20 +3921,23 @@ _bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
     }
 
   /* Make a ".reg/999" section.  */
-  return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size, note->descpos + offset);
+  return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size,
+                                         note->descpos + offset);
 }
 
 static bfd_boolean
-_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
+s3_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 {
   switch (note->descsz)
     {
     default:
       return FALSE;
 
-    case 124:                  /* Linux/Score elf_prpsinfo.  */
-      elf_tdata (abfd)->core_program = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
-      elf_tdata (abfd)->core_command = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
+    case 124:                 /* Linux/Score elf_prpsinfo.  */
+      elf_tdata (abfd)->core->program
+       = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
+      elf_tdata (abfd)->core->command
+       = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
     }
 
   /* Note that for some reason, a spurious space is tacked
@@ -3678,7 +3945,7 @@ _bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
      implementations, so strip it off if it exists.  */
 
   {
-    char *command = elf_tdata (abfd)->core_command;
+    char *command = elf_tdata (abfd)->core->command;
     int n = strlen (command);
 
     if (0 < n && command[n - 1] == ' ')
@@ -3690,43 +3957,37 @@ _bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 
 
 /* Score BFD functions.  */
-
 static reloc_howto_type *
-elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
+s3_elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
 {
   unsigned int i;
 
-  for (i = 0; i < NUM_ELEM (elf32_score_reloc_map); i++)
+  for (i = 0; i < ARRAY_SIZE (elf32_score_reloc_map); i++)
     if (elf32_score_reloc_map[i].bfd_reloc_val == code)
       return &elf32_score_howto_table[elf32_score_reloc_map[i].elf_reloc_val];
 
   return NULL;
 }
 
-/* Create a score elf linker hash table.  */
-
-static struct bfd_link_hash_table *
-elf32_score_link_hash_table_create (bfd *abfd)
+static reloc_howto_type *
+elf32_score_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                              const char *r_name)
 {
-  struct score_elf_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct score_elf_link_hash_table);
+  unsigned int i;
 
-  ret = bfd_malloc (amt);
-  if (ret == NULL)
-    return NULL;
+  for (i = 0;
+       i < (sizeof (elf32_score_howto_table)
+           / sizeof (elf32_score_howto_table[0]));
+       i++)
+    if (elf32_score_howto_table[i].name != NULL
+       && strcasecmp (elf32_score_howto_table[i].name, r_name) == 0)
+      return &elf32_score_howto_table[i];
 
-  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, score_elf_link_hash_newfunc,
-                                     sizeof (struct score_elf_link_hash_entry)))
-    {
-      free (ret);
-      return NULL;
-    }
-
-  return &ret->root.root;
+  return NULL;
 }
 
 static bfd_boolean
-elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
+s3_elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
 {
   FILE *file = (FILE *) ptr;
 
@@ -3751,14 +4012,19 @@ elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
 }
 
 static bfd_boolean
-elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+s3_elf32_score_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 {
+  bfd *obfd = info->output_bfd;
   flagword in_flags;
   flagword out_flags;
 
-  if (!_bfd_generic_verify_endian_match (ibfd, obfd))
+  if (!_bfd_generic_verify_endian_match (ibfd, info))
     return FALSE;
 
+  /* FIXME: What should be checked when linking shared libraries?  */
+  if ((ibfd->flags & DYNAMIC) != 0)
+    return TRUE;
+
   in_flags  = elf_elfheader (ibfd)->e_flags;
   out_flags = elf_elfheader (obfd)->e_flags;
 
@@ -3784,9 +4050,8 @@ elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
     }
 
   if (((in_flags & EF_SCORE_PIC) != 0) != ((out_flags & EF_SCORE_PIC) != 0))
-    {
-      (*_bfd_error_handler) (_("%B: warning: linking PIC files with non-PIC files"), ibfd);
-    }
+    _bfd_error_handler
+      (_("%pB: warning: linking PIC files with non-PIC files"), ibfd);
 
   /* FIXME: Maybe dependency fix compatibility should be checked here.  */
 
@@ -3794,10 +4059,10 @@ elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 }
 
 static bfd_boolean
-elf32_score_new_section_hook (bfd *abfd, asection *sec)
+s3_elf32_score_new_section_hook (bfd *abfd, asection *sec)
 {
   struct _score_elf_section_data *sdata;
-  bfd_size_type amt = sizeof (*sdata);
+  size_t amt = sizeof (*sdata);
 
   sdata = bfd_zalloc (abfd, amt);
   if (sdata == NULL)
@@ -3807,22 +4072,396 @@ elf32_score_new_section_hook (bfd *abfd, asection *sec)
   return _bfd_elf_new_section_hook (abfd, sec);
 }
 
+/*****************************************************************************/
+
+/* s3_s7: backend hooks.  */
+static bfd_boolean
+_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+                         arelent *bfd_reloc,
+                         Elf_Internal_Rela *elf_reloc)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc);
+  else
+    return s7_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc);
+}
+
+static bfd_boolean
+_bfd_score_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)
+{
+  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_relocate_section (output_bfd,
+            info, input_bfd, input_section, contents, relocs,
+            local_syms, local_sections);
+  else
+    return s7_bfd_score_elf_relocate_section (output_bfd,
+            info, input_bfd, input_section, contents, relocs,
+            local_syms, local_sections);
+}
 
-#define USE_REL                         1
-#define TARGET_LITTLE_SYM               bfd_elf32_littlescore_vec
-#define TARGET_LITTLE_NAME              "elf32-littlescore"
-#define TARGET_BIG_SYM                  bfd_elf32_bigscore_vec
-#define TARGET_BIG_NAME                 "elf32-bigscore"
-#define ELF_ARCH                        bfd_arch_score
-#define ELF_MACHINE_CODE                EM_SCORE
-#define ELF_MAXPAGESIZE                 0x8000
+static bfd_boolean
+_bfd_score_elf_check_relocs (bfd *abfd,
+                            struct bfd_link_info *info,
+                            asection *sec,
+                            const Elf_Internal_Rela *relocs)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_check_relocs (abfd, info, sec, relocs);
+  else
+    return s7_bfd_score_elf_check_relocs (abfd, info, sec, relocs);
+}
+
+static bfd_boolean
+_bfd_score_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)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp,
+                                            secp, valp);
+  else
+    return s7_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp,
+                                            secp, valp);
+}
+
+static void
+_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_symbol_processing (abfd, asym);
+  else
+    return s7_bfd_score_elf_symbol_processing (abfd, asym);
+}
+
+static int
+_bfd_score_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 link a empty .o, then this filed is NULL.  */
+  if (info->input_bfds == NULL)
+    {
+      /* If we see a common symbol, which implies a relocatable link, then
+        if a symbol was small common in an input file, mark it as small
+        common in the output file.  */
+      if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0)
+       sym->st_shndx = SHN_SCORE_SCOMMON;
+      return 1;
+    }
+
+  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
+    return s3_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h);
+  else
+    return s7_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h);
+}
+
+static bfd_boolean
+_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+                                        asection *sec,
+                                        int *retval)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_section_from_bfd_section (abfd, sec, retval);
+  else
+    return s7_bfd_score_elf_section_from_bfd_section (abfd, sec, retval);
+}
+
+static bfd_boolean
+_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
+                                     struct elf_link_hash_entry *h)
+{
+  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
+    return s3_bfd_score_elf_adjust_dynamic_symbol (info, h);
+  else
+    return s7_bfd_score_elf_adjust_dynamic_symbol (info, h);
+}
+
+static bfd_boolean
+_bfd_score_elf_always_size_sections (bfd *output_bfd,
+                                    struct bfd_link_info *info)
+{
+  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_always_size_sections (output_bfd, info);
+  else
+    return s7_bfd_score_elf_always_size_sections (output_bfd, info);
+}
+
+static bfd_boolean
+_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
+{
+  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_size_dynamic_sections (output_bfd, info);
+  else
+    return s7_bfd_score_elf_size_dynamic_sections (output_bfd, info);
+}
+
+static bfd_boolean
+_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_create_dynamic_sections (abfd, info);
+  else
+    return s7_bfd_score_elf_create_dynamic_sections (abfd, info);
+}
+
+static bfd_boolean
+_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd,
+                                     struct bfd_link_info *info,
+                                     struct elf_link_hash_entry *h,
+                                     Elf_Internal_Sym *sym)
+{
+  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym);
+  else
+    return s7_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym);
+}
+
+static bfd_boolean
+_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd,
+                                       struct bfd_link_info *info)
+{
+  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_finish_dynamic_sections (output_bfd, info);
+  else
+    return s7_bfd_score_elf_finish_dynamic_sections (output_bfd, info);
+}
+
+static bfd_boolean
+_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
+                             Elf_Internal_Shdr *hdr,
+                             asection *sec)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_fake_sections (abfd, hdr, sec);
+  else
+    return s7_bfd_score_elf_fake_sections (abfd, hdr, sec);
+}
+
+static bfd_boolean
+_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_section_processing (abfd, hdr);
+  else
+    return s7_bfd_score_elf_section_processing (abfd, hdr);
+}
+
+static bfd_boolean
+_bfd_score_elf_write_section (bfd *output_bfd,
+                             struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
+                             asection *sec, bfd_byte *contents)
+{
+  if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_write_section (output_bfd, sec, contents);
+  else
+    return s7_bfd_score_elf_write_section (output_bfd, sec, contents);
+}
+
+static void
+_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info,
+                                    struct elf_link_hash_entry *dir,
+                                    struct elf_link_hash_entry *ind)
+{
+  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
+    return s3_bfd_score_elf_copy_indirect_symbol (info, dir, ind);
+  else
+    return s7_bfd_score_elf_copy_indirect_symbol (info, dir, ind);
+}
+
+static void
+_bfd_score_elf_hide_symbol (struct bfd_link_info *info,
+                           struct elf_link_hash_entry *entry,
+                           bfd_boolean force_local)
+{
+  if (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
+    return s3_bfd_score_elf_hide_symbol (info, entry, force_local);
+  else
+    return s7_bfd_score_elf_hide_symbol (info, entry, force_local);
+}
+
+static bfd_boolean
+_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
+                        struct bfd_link_info *info)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_discard_info (abfd, cookie, info);
+  else
+    return s7_bfd_score_elf_discard_info (abfd, cookie, info);
+}
+
+static bfd_boolean
+_bfd_score_elf_ignore_discarded_relocs (asection *sec)
+{
+  if (bfd_get_mach (sec->owner) == bfd_mach_score3)
+    return s3_bfd_score_elf_ignore_discarded_relocs (sec);
+  else
+    return s7_bfd_score_elf_ignore_discarded_relocs (sec);
+}
+
+static asection *
+_bfd_score_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 (bfd_get_mach (info->input_bfds) == bfd_mach_score3)
+    return s3_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym);
+  else
+    return s7_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym);
+}
+
+static bfd_boolean
+_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_grok_prstatus (abfd, note);
+  else
+    return s7_bfd_score_elf_grok_prstatus (abfd, note);
+}
+
+static bfd_boolean
+_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_bfd_score_elf_grok_psinfo (abfd, note);
+  else
+    return s7_bfd_score_elf_grok_psinfo (abfd, note);
+}
+
+static reloc_howto_type *
+elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
+{
+  /* s3: NOTE!!!
+     gas will call elf32_score_reloc_type_lookup, and don't write elf file.
+     So just using score3, but we don't know ld will call this or not.
+     If so, this way can't work.  */
+
+  if (score3)
+    return s3_elf32_score_reloc_type_lookup (abfd, code);
+  else
+    return s7_elf32_score_reloc_type_lookup (abfd, code);
+}
+
+/* Create a score elf linker hash table.
+   This is a copy of _bfd_elf_link_hash_table_create() except with a
+   different hash table entry creation function.  */
+
+static struct bfd_link_hash_table *
+elf32_score_link_hash_table_create (bfd *abfd)
+{
+  struct elf_link_hash_table *ret;
+  size_t amt = sizeof (struct elf_link_hash_table);
+
+  ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
+  if (ret == NULL)
+    return NULL;
+
+  if (!_bfd_elf_link_hash_table_init (ret, abfd, score_elf_link_hash_newfunc,
+                                     sizeof (struct score_elf_link_hash_entry),
+                                     GENERIC_ELF_DATA))
+    {
+      free (ret);
+      return NULL;
+    }
+
+  return &ret->root;
+}
+
+static bfd_boolean
+elf32_score_print_private_bfd_data (bfd *abfd, void * ptr)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_elf32_score_print_private_bfd_data (abfd, ptr);
+  else
+    return s7_elf32_score_print_private_bfd_data (abfd, ptr);
+}
+
+static bfd_boolean
+elf32_score_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
+{
+  if (bfd_get_mach (info->output_bfd) == bfd_mach_score3)
+    return s3_elf32_score_merge_private_bfd_data (ibfd, info);
+  else
+    return s7_elf32_score_merge_private_bfd_data (ibfd, info);
+}
+
+static bfd_boolean
+elf32_score_new_section_hook (bfd *abfd, asection *sec)
+{
+  if (bfd_get_mach (abfd) == bfd_mach_score3)
+    return s3_elf32_score_new_section_hook (abfd, sec);
+  else
+    return s7_elf32_score_new_section_hook (abfd, sec);
+}
+
+
+/* s3_s7: don't need to split.  */
+
+/* Set the right machine number.  */
+static bfd_boolean
+_bfd_score_elf_score_object_p (bfd * abfd)
+{
+  int e_set = bfd_mach_score7;
+
+  if (elf_elfheader (abfd)->e_machine == EM_SCORE)
+    {
+      int e_mach = elf_elfheader (abfd)->e_flags & EF_SCORE_MACH & EF_OMIT_PIC_FIXDD;
+      switch (e_mach)
+       {
+       /* Set default target is score7.  */
+       default:
+       case E_SCORE_MACH_SCORE7:
+         e_set = bfd_mach_score7;
+         break;
+
+       case E_SCORE_MACH_SCORE3:
+         e_set = bfd_mach_score3;
+         break;
+       }
+    }
+
+  return bfd_default_set_arch_mach (abfd, bfd_arch_score, e_set);
+}
+
+bfd_boolean
+_bfd_score_elf_common_definition (Elf_Internal_Sym *sym)
+{
+  return (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_SCORE_SCOMMON);
+}
 
-#define elf_info_to_howto               0
-#define elf_info_to_howto_rel           _bfd_score_info_to_howto
-#define elf_backend_relocate_section    _bfd_score_elf_relocate_section
-#define elf_backend_check_relocs        _bfd_score_elf_check_relocs
-#define elf_backend_add_symbol_hook     _bfd_score_elf_add_symbol_hook
-#define elf_backend_symbol_processing   _bfd_score_elf_symbol_processing
+/*****************************************************************************/
+
+
+#define USE_REL                                1
+#define TARGET_LITTLE_SYM              score_elf32_le_vec
+#define TARGET_LITTLE_NAME             "elf32-littlescore"
+#define TARGET_BIG_SYM                 score_elf32_be_vec
+#define TARGET_BIG_NAME                        "elf32-bigscore"
+#define ELF_ARCH                       bfd_arch_score
+#define ELF_MACHINE_CODE               EM_SCORE
+#define ELF_MACHINE_ALT1               EM_SCORE_OLD
+#define ELF_MAXPAGESIZE                        0x8000
+
+#define elf_info_to_howto              NULL
+#define elf_info_to_howto_rel          _bfd_score_info_to_howto
+#define elf_backend_relocate_section   _bfd_score_elf_relocate_section
+#define elf_backend_check_relocs       _bfd_score_elf_check_relocs
+#define elf_backend_add_symbol_hook    _bfd_score_elf_add_symbol_hook
+#define elf_backend_symbol_processing  _bfd_score_elf_symbol_processing
 #define elf_backend_link_output_symbol_hook \
   _bfd_score_elf_link_output_symbol_hook
 #define elf_backend_section_from_bfd_section \
@@ -3833,36 +4472,38 @@ elf32_score_new_section_hook (bfd *abfd, asection *sec)
   _bfd_score_elf_always_size_sections
 #define elf_backend_size_dynamic_sections \
   _bfd_score_elf_size_dynamic_sections
-#define elf_backend_omit_section_dynsym \
-  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
+#define elf_backend_omit_section_dynsym   _bfd_elf_omit_section_dynsym_all
 #define elf_backend_create_dynamic_sections \
   _bfd_score_elf_create_dynamic_sections
 #define elf_backend_finish_dynamic_symbol \
   _bfd_score_elf_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
   _bfd_score_elf_finish_dynamic_sections
-#define elf_backend_fake_sections         _bfd_score_elf_fake_sections
-#define elf_backend_section_processing    _bfd_score_elf_section_processing
-#define elf_backend_write_section         _bfd_score_elf_write_section
+#define elf_backend_fake_sections        _bfd_score_elf_fake_sections
+#define elf_backend_section_processing   _bfd_score_elf_section_processing
+#define elf_backend_write_section        _bfd_score_elf_write_section
 #define elf_backend_copy_indirect_symbol  _bfd_score_elf_copy_indirect_symbol
-#define elf_backend_hide_symbol           _bfd_score_elf_hide_symbol
-#define elf_backend_discard_info          _bfd_score_elf_discard_info
+#define elf_backend_hide_symbol                  _bfd_score_elf_hide_symbol
+#define elf_backend_discard_info         _bfd_score_elf_discard_info
 #define elf_backend_ignore_discarded_relocs \
   _bfd_score_elf_ignore_discarded_relocs
-#define elf_backend_gc_mark_hook          _bfd_score_elf_gc_mark_hook
-#define elf_backend_grok_prstatus         _bfd_score_elf_grok_prstatus
-#define elf_backend_grok_psinfo           _bfd_score_elf_grok_psinfo
-#define elf_backend_can_gc_sections       1
-#define elf_backend_want_plt_sym          0
-#define elf_backend_got_header_size       (4 * SCORE_RESERVED_GOTNO)
-#define elf_backend_plt_header_size       0
-#define elf_backend_collect               TRUE
-#define elf_backend_type_change_ok        TRUE
-
-#define bfd_elf32_bfd_reloc_type_lookup      elf32_score_reloc_type_lookup
+#define elf_backend_gc_mark_hook         _bfd_score_elf_gc_mark_hook
+#define elf_backend_grok_prstatus        _bfd_score_elf_grok_prstatus
+#define elf_backend_grok_psinfo                  _bfd_score_elf_grok_psinfo
+#define elf_backend_can_gc_sections      1
+#define elf_backend_want_plt_sym         0
+#define elf_backend_got_header_size      (4 * SCORE_RESERVED_GOTNO)
+#define elf_backend_plt_header_size      0
+#define elf_backend_collect              TRUE
+#define elf_backend_type_change_ok       TRUE
+#define elf_backend_object_p                 _bfd_score_elf_score_object_p
+
+#define bfd_elf32_bfd_reloc_type_lookup             elf32_score_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup \
+  elf32_score_reloc_name_lookup
 #define bfd_elf32_bfd_link_hash_table_create elf32_score_link_hash_table_create
 #define bfd_elf32_bfd_print_private_bfd_data elf32_score_print_private_bfd_data
 #define bfd_elf32_bfd_merge_private_bfd_data elf32_score_merge_private_bfd_data
-#define bfd_elf32_new_section_hook           elf32_score_new_section_hook
+#define bfd_elf32_new_section_hook          elf32_score_new_section_hook
 
 #include "elf32-target.h"
This page took 0.140644 seconds and 4 git commands to generate.