* elf-bfd.h (struct elf_reloc_cookie): Remove locsym_shndx,
[deliverable/binutils-gdb.git] / bfd / elf32-sh.c
index 74b725a0ee264fec867a674f71792d276a8bcd06..522b81680f0e4e605144d378046e2b7219e4a336 100644 (file)
@@ -1,5 +1,5 @@
 /* Hitachi SH specific support for 32-bit ELF
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
    Contributed by Ian Lance Taylor, Cygnus Support.
 
@@ -78,13 +78,16 @@ static bfd_reloc_status_type sh_elf_reloc_loop
 static boolean sh_elf_create_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
 static asection * sh_elf_gc_mark_hook
-  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
           struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static boolean sh_elf_gc_sweep_hook
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           const Elf_Internal_Rela *));
 static enum elf_reloc_type_class sh_elf_reloc_type_class
   PARAMS ((const Elf_Internal_Rela *));
+#ifdef INCLUDE_SHMEDIA
+inline static void movi_shori_putval PARAMS ((bfd *, unsigned long, char *));
+#endif
 
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
@@ -492,6 +495,114 @@ static reloc_howto_type sh_elf_howto_table[] =
   EMPTY_HOWTO (42),
   EMPTY_HOWTO (43),
   EMPTY_HOWTO (44),
+
+#ifdef INCLUDE_SHMEDIA
+  /* Used in SHLLI.L and SHLRI.L.  */
+  HOWTO (R_SH_DIR5U,           /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        5,                     /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_unsigned, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_DIR5U",          /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xfc00,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in SHARI, SHLLI et al.  */
+  HOWTO (R_SH_DIR6U,           /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        6,                     /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_unsigned, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_DIR6U",          /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xfc00,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in BxxI, LDHI.L et al.  */
+  HOWTO (R_SH_DIR6S,           /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        6,                     /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_DIR6S",          /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xfc00,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in ADDI, ANDI et al.  */
+  HOWTO (R_SH_DIR10S,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        10,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_DIR10S",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffc00,               /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in LD.UW, ST.W et al.  */
+  HOWTO (R_SH_DIR10SW, /* type */
+        1,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        11,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_DIR10SW",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffc00,               /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_DIR10SL, /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        12,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_DIR10SL",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffc00,               /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_DIR10SQ, /* type */
+        3,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        13,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_DIR10SQ",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffc00,               /* dst_mask */
+        false),                /* pcrel_offset */
+
+#else
   EMPTY_HOWTO (45),
   EMPTY_HOWTO (46),
   EMPTY_HOWTO (47),
@@ -499,6 +610,8 @@ static reloc_howto_type sh_elf_howto_table[] =
   EMPTY_HOWTO (49),
   EMPTY_HOWTO (50),
   EMPTY_HOWTO (51),
+#endif
+
   EMPTY_HOWTO (52),
   EMPTY_HOWTO (53),
   EMPTY_HOWTO (54),
@@ -664,62 +777,760 @@ static reloc_howto_type sh_elf_howto_table[] =
         0xffffffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  HOWTO (R_SH_JMP_SLOT,                /* type */
-        0,                     /* rightshift */
+  HOWTO (R_SH_JMP_SLOT,                /* type */
+        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, /* */
+        "R_SH_JMP_SLOT",       /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_SH_RELATIVE,                /* type */
+        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, /* */
+        "R_SH_RELATIVE",       /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_SH_GOTOFF,          /* type */
+        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, /* */
+        "R_SH_GOTOFF",         /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_SH_GOTPC,           /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* */
+        "R_SH_GOTPC",          /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  HOWTO (R_SH_GOTPLT32,                /* type */
+        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, /* */
+        "R_SH_GOTPLT32",       /* name */
+        false,                 /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+#ifdef INCLUDE_SHMEDIA
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOT_LOW16,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOT_LOW16",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOT_MEDLOW16,    /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOT_MEDLOW16",   /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOT_MEDHI16,     /* type */
+        32,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOT_MEDHI16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOT_HI16,                /* type */
+        48,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOT_HI16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTPLT_LOW16,    /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPLT_LOW16",   /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTPLT_MEDLOW16, /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPLT_MEDLOW16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTPLT_MEDHI16,  /* type */
+        32,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPLT_MEDHI16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTPLT_HI16,     /* type */
+        48,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPLT_HI16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_PLT_LOW16,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_PLT_LOW16",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_PLT_MEDLOW16,    /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_PLT_MEDLOW16",   /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_PLT_MEDHI16,     /* type */
+        32,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_PLT_MEDHI16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_PLT_HI16,                /* type */
+        48,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_PLT_HI16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTOFF_LOW16,    /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTOFF_LOW16",   /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTOFF_MEDLOW16, /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTOFF_MEDLOW16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTOFF_MEDHI16,  /* type */
+        32,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTOFF_MEDHI16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTOFF_HI16,     /* type */
+        48,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTOFF_HI16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_GOTPC_LOW16,     /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPC_LOW16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_GOTPC_MEDLOW16,  /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPC_MEDLOW16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_GOTPC_MEDHI16,   /* type */
+        32,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPC_MEDHI16",  /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_GOTPC_HI16,      /* type */
+        48,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPC_HI16",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_GOT10BY4,                /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        12,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOT10BY4",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffc00,               /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in LD.L, FLD.S et al.  */
+  HOWTO (R_SH_GOTPLT10BY4,     /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        12,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPLT10BY4",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffc00,               /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_GOT10BY8,                /* type */
+        3,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        13,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOT10BY8",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffc00,               /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in FLD.D, FST.P et al.  */
+  HOWTO (R_SH_GOTPLT10BY8,     /* type */
+        3,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        13,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GOTPLT10BY8",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffc00,               /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_SH_COPY64,          /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_COPY64",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        ((bfd_vma) 0) - 1,     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_SH_GLOB_DAT64,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_GLOB_DAT64",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        ((bfd_vma) 0) - 1,     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_SH_JMP_SLOT64,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_JMP_SLOT64",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        ((bfd_vma) 0) - 1,     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_SH_RELATIVE64,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_RELATIVE64",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        ((bfd_vma) 0) - 1,     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  EMPTY_HOWTO (197),
+  EMPTY_HOWTO (198),
+  EMPTY_HOWTO (199),
+  EMPTY_HOWTO (200),
+  EMPTY_HOWTO (201),
+  EMPTY_HOWTO (202),
+  EMPTY_HOWTO (203),
+  EMPTY_HOWTO (204),
+  EMPTY_HOWTO (205),
+  EMPTY_HOWTO (206),
+  EMPTY_HOWTO (207),
+  EMPTY_HOWTO (208),
+  EMPTY_HOWTO (209),
+  EMPTY_HOWTO (210),
+  EMPTY_HOWTO (211),
+  EMPTY_HOWTO (212),
+  EMPTY_HOWTO (213),
+  EMPTY_HOWTO (214),
+  EMPTY_HOWTO (215),
+  EMPTY_HOWTO (216),
+  EMPTY_HOWTO (217),
+  EMPTY_HOWTO (218),
+  EMPTY_HOWTO (219),
+  EMPTY_HOWTO (220),
+  EMPTY_HOWTO (221),
+  EMPTY_HOWTO (222),
+  EMPTY_HOWTO (223),
+  EMPTY_HOWTO (224),
+  EMPTY_HOWTO (225),
+  EMPTY_HOWTO (226),
+  EMPTY_HOWTO (227),
+  EMPTY_HOWTO (228),
+  EMPTY_HOWTO (229),
+  EMPTY_HOWTO (230),
+  EMPTY_HOWTO (231),
+  EMPTY_HOWTO (232),
+  EMPTY_HOWTO (233),
+  EMPTY_HOWTO (234),
+  EMPTY_HOWTO (235),
+  EMPTY_HOWTO (236),
+  EMPTY_HOWTO (237),
+  EMPTY_HOWTO (238),
+  EMPTY_HOWTO (239),
+  EMPTY_HOWTO (240),
+  EMPTY_HOWTO (241),
+
+  /* Relocations for SHmedia code.  None of these are partial_inplace or
+     use the field being relocated (except R_SH_PT_16).  */
+
+  /* The assembler will generate this reloc before a block of SHmedia
+     instructions.  A section should be processed as assuming it contains
+     data, unless this reloc is seen.  Note that a block of SHcompact
+     instructions are instead preceded by R_SH_CODE.
+     This is currently not implemented, but should be used for SHmedia
+     linker relaxation.  */
+  HOWTO (R_SH_SHMEDIA_CODE,    /* type */
+        0,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_unsigned, /* complain_on_overflow */
+        sh_elf_ignore_reloc,   /* special_function */
+        "R_SH_SHMEDIA_CODE",   /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* The assembler will generate this reloc at a PTA or PTB instruction,
+     and the linker checks the right type of target, or changes a PTA to a
+     PTB, if the original insn was PT.  */
+  HOWTO (R_SH_PT_16,           /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        18,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_PT_16",          /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in unexpanded MOVI.  */
+  HOWTO (R_SH_IMMS16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMMS16",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in SHORI.  */
+  HOWTO (R_SH_IMMU16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_unsigned, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMMU16",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI (x & 65536).  */
+  HOWTO (R_SH_IMM_LOW16,       /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMM_LOW16",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x - $) & 65536).  */
+  HOWTO (R_SH_IMM_LOW16_PCREL, /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMM_LOW16_PCREL", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 16) & 65536).  */
+  HOWTO (R_SH_IMM_MEDLOW16,    /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMM_MEDLOW16",   /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used in MOVI and SHORI (((x - $) >> 16) & 65536).  */
+  HOWTO (R_SH_IMM_MEDLOW16_PCREL, /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMM_MEDLOW16_PCREL", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 32) & 65536).  */
+  HOWTO (R_SH_IMM_MEDHI16,     /* type */
+        32,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        64,                    /* bitsize */
         false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* */
-        "R_SH_JMP_SLOT",       /* name */
-        true,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMM_MEDHI16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
 
-  HOWTO (R_SH_RELATIVE,                /* type */
-        0,                     /* rightshift */
+  /* Used in MOVI and SHORI (((x - $) >> 32) & 65536).  */
+  HOWTO (R_SH_IMM_MEDHI16_PCREL, /* type */
+        32,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMM_MEDHI16_PCREL", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* Used in MOVI and SHORI ((x >> 48) & 65536).  */
+  HOWTO (R_SH_IMM_HI16,                /* type */
+        48,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
         false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* */
-        "R_SH_RELATIVE",       /* name */
-        true,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMM_HI16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        false),                /* pcrel_offset */
 
-  HOWTO (R_SH_GOTOFF,          /* type */
-        0,                     /* rightshift */
+  /* Used in MOVI and SHORI (((x - $) >> 48) & 65536).  */
+  HOWTO (R_SH_IMM_HI16_PCREL,  /* type */
+        48,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        64,                    /* bitsize */
+        true,                  /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_IMM_HI16_PCREL", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3fffc00,             /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* For the .uaquad pseudo.  */
+  HOWTO (R_SH_64,              /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* */
-        "R_SH_GOTOFF",         /* name */
-        true,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_64",             /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        ((bfd_vma) 0) - 1,     /* dst_mask */
+        false),                /* pcrel_offset */
 
-  HOWTO (R_SH_GOTPC,           /* type */
-        0,                     /* rightshift */
+  /* For the .uaquad pseudo, (x - $).  */
+  HOWTO (R_SH_64_PCREL,                /* type */
+        48,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        64,                    /* bitsize */
         true,                  /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* */
-        "R_SH_GOTPC",          /* name */
-        true,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
+        10,                    /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_SH_64_PCREL",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        ((bfd_vma) 0) - 1,     /* dst_mask */
         true),                 /* pcrel_offset */
 
+#endif
 };
 
 static bfd_reloc_status_type
@@ -735,7 +1546,6 @@ sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr,
 {
   static bfd_vma last_addr;
   static asection *last_symbol_section;
-  bfd_byte *free_contents = NULL;
   bfd_byte *start_ptr, *ptr, *last_ptr;
   int diff, cum_diff;
   bfd_signed_vma x;
@@ -770,7 +1580,6 @@ sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr,
          contents = (bfd_byte *) bfd_malloc (symbol_section->_raw_size);
          if (contents == NULL)
            return bfd_reloc_outofrange;
-         free_contents = contents;
          if (! bfd_get_section_contents (input_bfd, symbol_section, contents,
                                          (file_ptr) 0,
                                          symbol_section->_raw_size))
@@ -810,8 +1619,9 @@ sh_elf_reloc_loop (r_type, input_bfd, input_section, contents, addr,
       end = start0;
     }
 
-  if (free_contents)
-    free (free_contents);
+  if (contents != NULL
+      && elf_section_data (symbol_section)->this_hdr.contents != contents)
+    free (contents);
 
   insn = bfd_get_16 (input_bfd, contents + addr);
 
@@ -965,6 +1775,58 @@ static const struct elf_reloc_map sh_reloc_map[] =
   { BFD_RELOC_SH_RELATIVE, R_SH_RELATIVE },
   { BFD_RELOC_32_GOTOFF, R_SH_GOTOFF },
   { BFD_RELOC_SH_GOTPC, R_SH_GOTPC },
+  { BFD_RELOC_SH_GOTPLT32, R_SH_GOTPLT32 },
+#ifdef INCLUDE_SHMEDIA
+  { BFD_RELOC_SH_GOT_LOW16, R_SH_GOT_LOW16 },
+  { BFD_RELOC_SH_GOT_MEDLOW16, R_SH_GOT_MEDLOW16 },
+  { BFD_RELOC_SH_GOT_MEDHI16, R_SH_GOT_MEDHI16 },
+  { BFD_RELOC_SH_GOT_HI16, R_SH_GOT_HI16 },
+  { BFD_RELOC_SH_GOTPLT_LOW16, R_SH_GOTPLT_LOW16 },
+  { BFD_RELOC_SH_GOTPLT_MEDLOW16, R_SH_GOTPLT_MEDLOW16 },
+  { BFD_RELOC_SH_GOTPLT_MEDHI16, R_SH_GOTPLT_MEDHI16 },
+  { BFD_RELOC_SH_GOTPLT_HI16, R_SH_GOTPLT_HI16 },
+  { BFD_RELOC_SH_PLT_LOW16, R_SH_PLT_LOW16 },
+  { BFD_RELOC_SH_PLT_MEDLOW16, R_SH_PLT_MEDLOW16 },
+  { BFD_RELOC_SH_PLT_MEDHI16, R_SH_PLT_MEDHI16 },
+  { BFD_RELOC_SH_PLT_HI16, R_SH_PLT_HI16 },
+  { BFD_RELOC_SH_GOTOFF_LOW16, R_SH_GOTOFF_LOW16 },
+  { BFD_RELOC_SH_GOTOFF_MEDLOW16, R_SH_GOTOFF_MEDLOW16 },
+  { BFD_RELOC_SH_GOTOFF_MEDHI16, R_SH_GOTOFF_MEDHI16 },
+  { BFD_RELOC_SH_GOTOFF_HI16, R_SH_GOTOFF_HI16 },
+  { BFD_RELOC_SH_GOTPC_LOW16, R_SH_GOTPC_LOW16 },
+  { BFD_RELOC_SH_GOTPC_MEDLOW16, R_SH_GOTPC_MEDLOW16 },
+  { BFD_RELOC_SH_GOTPC_MEDHI16, R_SH_GOTPC_MEDHI16 },
+  { BFD_RELOC_SH_GOTPC_HI16, R_SH_GOTPC_HI16 },
+  { BFD_RELOC_SH_COPY64, R_SH_COPY64 },
+  { BFD_RELOC_SH_GLOB_DAT64, R_SH_GLOB_DAT64 },
+  { BFD_RELOC_SH_JMP_SLOT64, R_SH_JMP_SLOT64 },
+  { BFD_RELOC_SH_RELATIVE64, R_SH_RELATIVE64 },
+  { BFD_RELOC_SH_GOT10BY4, R_SH_GOT10BY4 },
+  { BFD_RELOC_SH_GOT10BY8, R_SH_GOT10BY8 },
+  { BFD_RELOC_SH_GOTPLT10BY4, R_SH_GOTPLT10BY4 },
+  { BFD_RELOC_SH_GOTPLT10BY8, R_SH_GOTPLT10BY8 },
+  { BFD_RELOC_SH_PT_16, R_SH_PT_16 },
+  { BFD_RELOC_SH_SHMEDIA_CODE, R_SH_SHMEDIA_CODE },
+  { BFD_RELOC_SH_IMMU5, R_SH_DIR5U },
+  { BFD_RELOC_SH_IMMS6, R_SH_DIR6S },
+  { BFD_RELOC_SH_IMMU6, R_SH_DIR6U },
+  { BFD_RELOC_SH_IMMS10, R_SH_DIR10S },
+  { BFD_RELOC_SH_IMMS10BY2, R_SH_DIR10SW },
+  { BFD_RELOC_SH_IMMS10BY4, R_SH_DIR10SL },
+  { BFD_RELOC_SH_IMMS10BY8, R_SH_DIR10SQ },
+  { BFD_RELOC_SH_IMMS16, R_SH_IMMS16 },
+  { BFD_RELOC_SH_IMMU16, R_SH_IMMU16 },
+  { BFD_RELOC_SH_IMM_LOW16, R_SH_IMM_LOW16 },
+  { BFD_RELOC_SH_IMM_LOW16_PCREL, R_SH_IMM_LOW16_PCREL },
+  { BFD_RELOC_SH_IMM_MEDLOW16, R_SH_IMM_MEDLOW16 },
+  { BFD_RELOC_SH_IMM_MEDLOW16_PCREL, R_SH_IMM_MEDLOW16_PCREL },
+  { BFD_RELOC_SH_IMM_MEDHI16, R_SH_IMM_MEDHI16 },
+  { BFD_RELOC_SH_IMM_MEDHI16_PCREL, R_SH_IMM_MEDHI16_PCREL },
+  { BFD_RELOC_SH_IMM_HI16, R_SH_IMM_HI16 },
+  { BFD_RELOC_SH_IMM_HI16_PCREL, R_SH_IMM_HI16_PCREL },
+  { BFD_RELOC_64, R_SH_64 },
+  { BFD_RELOC_64_PCREL, R_SH_64_PCREL },
+#endif /* not INCLUDE_SHMEDIA */
 };
 
 /* Given a BFD reloc code, return the howto structure for the
@@ -1001,6 +1863,8 @@ sh_elf_info_to_howto (abfd, cache_ptr, dst)
   BFD_ASSERT (r < (unsigned int) R_SH_max);
   BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC || r > R_SH_LAST_INVALID_RELOC);
   BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_2 || r > R_SH_LAST_INVALID_RELOC_2);
+  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_3 || r > R_SH_LAST_INVALID_RELOC_3);
+  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_4 || r > R_SH_LAST_INVALID_RELOC_4);
 
   cache_ptr->howto = &sh_elf_howto_table[r];
 }
@@ -1024,13 +1888,10 @@ sh_elf_relax_section (abfd, sec, link_info, again)
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs;
-  Elf_Internal_Rela *free_relocs = NULL;
   boolean have_code;
   Elf_Internal_Rela *irel, *irelend;
   bfd_byte *contents = NULL;
-  bfd_byte *free_contents = NULL;
-  Elf32_External_Sym *extsyms = NULL;
-  Elf32_External_Sym *free_extsyms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   *again = false;
 
@@ -1039,6 +1900,14 @@ sh_elf_relax_section (abfd, sec, link_info, again)
       || sec->reloc_count == 0)
     return true;
 
+#ifdef INCLUDE_SHMEDIA
+  if (elf_section_data (sec)->this_hdr.sh_flags
+      & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED))
+    {
+      return true;
+    }
+#endif
+
   /* If this is the first time we have been called for this section,
      initialize the cooked size.  */
   if (sec->_cooked_size == 0)
@@ -1051,8 +1920,6 @@ sh_elf_relax_section (abfd, sec, link_info, again)
                      link_info->keep_memory));
   if (internal_relocs == NULL)
     goto error_return;
-  if (! link_info->keep_memory)
-    free_relocs = internal_relocs;
 
   have_code = false;
 
@@ -1080,7 +1947,6 @@ sh_elf_relax_section (abfd, sec, link_info, again)
              contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
              if (contents == NULL)
                goto error_return;
-             free_contents = contents;
 
              if (! bfd_get_section_contents (abfd, sec, contents,
                                              (file_ptr) 0, sec->_raw_size))
@@ -1145,34 +2011,26 @@ sh_elf_relax_section (abfd, sec, link_info, again)
        }
 
       /* Read this BFD's symbols if we haven't done so already.  */
-      if (extsyms == NULL)
+      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
        {
-         if (symtab_hdr->contents != NULL)
-           extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
-         else
-           {
-             extsyms = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
-             if (extsyms == NULL)
-               goto error_return;
-             free_extsyms = extsyms;
-             if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-                 || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd)
-                     != symtab_hdr->sh_size))
-               goto error_return;
-           }
+         isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+         if (isymbuf == NULL)
+           isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+                                           symtab_hdr->sh_info, 0,
+                                           NULL, NULL, NULL);
+         if (isymbuf == NULL)
+           goto error_return;
        }
 
       /* Get the value of the symbol referred to by the reloc.  */
       if (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info)
        {
-         Elf_Internal_Sym isym;
-
          /* A local symbol.  */
-         bfd_elf32_swap_symbol_in (abfd,
-                                   extsyms + ELF32_R_SYM (irelfn->r_info),
-                                   &isym);
+         Elf_Internal_Sym *isym;
 
-         if (isym.st_shndx != _bfd_elf_section_from_bfd_section (abfd, sec))
+         isym = isymbuf + ELF32_R_SYM (irelfn->r_info);
+         if (isym->st_shndx
+             != (unsigned int) _bfd_elf_section_from_bfd_section (abfd, sec))
            {
              ((*_bfd_error_handler)
               (_("%s: 0x%lx: warning: symbol in unexpected section"),
@@ -1180,7 +2038,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
              continue;
            }
 
-         symval = (isym.st_value
+         symval = (isym->st_value
                    + sec->output_section->vma
                    + sec->output_offset);
        }
@@ -1231,13 +2089,8 @@ sh_elf_relax_section (abfd, sec, link_info, again)
         the linker is run.  */
 
       elf_section_data (sec)->relocs = internal_relocs;
-      free_relocs = NULL;
-
       elf_section_data (sec)->this_hdr.contents = contents;
-      free_contents = NULL;
-
-      symtab_hdr->contents = (bfd_byte *) extsyms;
-      free_extsyms = NULL;
+      symtab_hdr->contents = (unsigned char *) isymbuf;
 
       /* Replace the jsr with a bsr.  */
 
@@ -1342,7 +2195,6 @@ sh_elf_relax_section (abfd, sec, link_info, again)
              contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
              if (contents == NULL)
                goto error_return;
-             free_contents = contents;
 
              if (! bfd_get_section_contents (abfd, sec, contents,
                                              (file_ptr) 0, sec->_raw_size))
@@ -1357,55 +2209,52 @@ sh_elf_relax_section (abfd, sec, link_info, again)
       if (swapped)
        {
          elf_section_data (sec)->relocs = internal_relocs;
-         free_relocs = NULL;
-
          elf_section_data (sec)->this_hdr.contents = contents;
-         free_contents = NULL;
-
-         symtab_hdr->contents = (bfd_byte *) extsyms;
-         free_extsyms = NULL;
+         symtab_hdr->contents = (unsigned char *) isymbuf;
        }
     }
 
-  if (free_relocs != NULL)
-    {
-      free (free_relocs);
-      free_relocs = NULL;
-    }
-
-  if (free_contents != NULL)
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
     {
       if (! link_info->keep_memory)
-       free (free_contents);
+       free (isymbuf);
       else
        {
-         /* Cache the section contents for elf_link_input_bfd.  */
-         elf_section_data (sec)->this_hdr.contents = contents;
+         /* Cache the symbols for elf_link_input_bfd.  */
+         symtab_hdr->contents = (unsigned char *) isymbuf;
        }
-      free_contents = NULL;
     }
 
-  if (free_extsyms != NULL)
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
     {
       if (! link_info->keep_memory)
-       free (free_extsyms);
+       free (contents);
       else
        {
-         /* Cache the symbols for elf_link_input_bfd.  */
-         symtab_hdr->contents = (unsigned char *) extsyms;
+         /* Cache the section contents for elf_link_input_bfd.  */
+         elf_section_data (sec)->this_hdr.contents = contents;
        }
-      free_extsyms = NULL;
     }
 
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
   return true;
 
  error_return:
-  if (free_relocs != NULL)
-    free (free_relocs);
-  if (free_contents != NULL)
-    free (free_contents);
-  if (free_extsyms != NULL)
-    free (free_extsyms);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (contents != NULL
+      && elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+  if (internal_relocs != NULL
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+
   return false;
 }
 
@@ -1421,20 +2270,21 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
      int count;
 {
   Elf_Internal_Shdr *symtab_hdr;
-  Elf32_External_Sym *extsyms;
-  int shndx, index;
+  unsigned int sec_shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
   Elf_Internal_Rela *irelalign;
   bfd_vma toaddr;
-  Elf32_External_Sym *esym, *esymend;
-  struct elf_link_hash_entry *sym_hash;
+  Elf_Internal_Sym *isymbuf, *isym, *isymend;
+  struct elf_link_hash_entry **sym_hashes;
+  struct elf_link_hash_entry **end_hashes;
+  unsigned int symcount;
   asection *o;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
+  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
 
-  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
   contents = elf_section_data (sec)->this_hdr.contents;
 
@@ -1480,7 +2330,6 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
       bfd_vma nraddr, stop;
       bfd_vma start = 0;
       int insn = 0;
-      Elf_Internal_Sym sym;
       int off, adjust, oinsn;
       bfd_signed_vma voff = 0;
       boolean overflow;
@@ -1534,17 +2383,15 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
              range to be adjusted, and hence must be changed.  */
          if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
            {
-             bfd_elf32_swap_symbol_in (abfd,
-                                       extsyms + ELF32_R_SYM (irel->r_info),
-                                       &sym);
-             if (sym.st_shndx == shndx
-                 && (sym.st_value <= addr
-                     || sym.st_value >= toaddr))
+             isym = isymbuf + ELF32_R_SYM (irel->r_info);
+             if (isym->st_shndx == sec_shndx
+                 && (isym->st_value <= addr
+                     || isym->st_value >= toaddr))
                {
                  bfd_vma val;
 
                  val = bfd_get_32 (abfd, contents + nraddr);
-                 val += sym.st_value;
+                 val += isym->st_value;
                  if (val > addr && val < toaddr)
                    bfd_put_32 (abfd, val - count, contents + nraddr);
                }
@@ -1737,8 +2584,6 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
       irelscanend = internal_relocs + o->reloc_count;
       for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
        {
-         Elf_Internal_Sym sym;
-
          /* Dwarf line numbers use R_SH_SWITCH32 relocs.  */
          if (ELF32_R_TYPE (irelscan->r_info) == (int) R_SH_SWITCH32)
            {
@@ -1795,13 +2640,11 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
          if (ELF32_R_SYM (irelscan->r_info) >= symtab_hdr->sh_info)
            continue;
 
-         bfd_elf32_swap_symbol_in (abfd,
-                                   extsyms + ELF32_R_SYM (irelscan->r_info),
-                                   &sym);
 
-         if (sym.st_shndx == shndx
-             && (sym.st_value <= addr
-                 || sym.st_value >= toaddr))
+         isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
+         if (isym->st_shndx == sec_shndx
+             && (isym->st_value <= addr
+                 || isym->st_value >= toaddr))
            {
              bfd_vma val;
 
@@ -1827,7 +2670,7 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
                }
 
              val = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
-             val += sym.st_value;
+             val += isym->st_value;
              if (val > addr && val < toaddr)
                bfd_put_32 (abfd, val - count,
                            ocontents + irelscan->r_offset);
@@ -1836,40 +2679,30 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
     }
 
   /* Adjust the local symbols defined in this section.  */
-  esym = extsyms;
-  esymend = esym + symtab_hdr->sh_info;
-  for (; esym < esymend; esym++)
+  isymend = isymbuf + symtab_hdr->sh_info;
+  for (isym = isymbuf; isym < isymend; isym++)
     {
-      Elf_Internal_Sym isym;
-
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
-
-      if (isym.st_shndx == shndx
-         && isym.st_value > addr
-         && isym.st_value < toaddr)
-       {
-         isym.st_value -= count;
-         bfd_elf32_swap_symbol_out (abfd, &isym, esym);
-       }
+      if (isym->st_shndx == sec_shndx
+         && isym->st_value > addr
+         && isym->st_value < toaddr)
+       isym->st_value -= count;
     }
 
   /* Now adjust the global symbols defined in this section.  */
-  esym = extsyms + symtab_hdr->sh_info;
-  esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
-  for (index = 0; esym < esymend; esym++, index++)
+  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+             - symtab_hdr->sh_info);
+  sym_hashes = elf_sym_hashes (abfd);
+  end_hashes = sym_hashes + symcount;
+  for (; sym_hashes < end_hashes; sym_hashes++)
     {
-      Elf_Internal_Sym isym;
-
-      bfd_elf32_swap_symbol_in (abfd, esym, &isym);
-      sym_hash = elf_sym_hashes (abfd)[index];
-      if (isym.st_shndx == shndx
-         && ((sym_hash)->root.type == bfd_link_hash_defined
-             || (sym_hash)->root.type == bfd_link_hash_defweak)
-         && (sym_hash)->root.u.def.section == sec
-         && (sym_hash)->root.u.def.value > addr
-         && (sym_hash)->root.u.def.value < toaddr)
+      struct elf_link_hash_entry *sym_hash = *sym_hashes;
+      if ((sym_hash->root.type == bfd_link_hash_defined
+          || sym_hash->root.type == bfd_link_hash_defweak)
+         && sym_hash->root.u.def.section == sec
+         && sym_hash->root.u.def.value > addr
+         && sym_hash->root.u.def.value < toaddr)
        {
-         (sym_hash)->root.u.def.value -= count;
+         sym_hash->root.u.def.value -= count;
        }
     }
 
@@ -1898,10 +2731,10 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
 
 static boolean
 sh_elf_align_loads (abfd, sec, internal_relocs, contents, pswapped)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      asection *sec;
      Elf_Internal_Rela *internal_relocs;
-     bfd_byte *contents;
+     bfd_byte *contents ATTRIBUTE_UNUSED;
      boolean *pswapped;
 {
   Elf_Internal_Rela *irel, *irelend;
@@ -2101,6 +2934,178 @@ sh_elf_swap_insns (abfd, sec, relocs, contents, addr)
   return true;
 }
 \f
+#ifdef INCLUDE_SHMEDIA
+
+/* The size in bytes of an entry in the procedure linkage table.  */
+
+#define PLT_ENTRY_SIZE 64
+
+/* First entry in an absolute procedure linkage table look like this.  */
+
+static const bfd_byte elf_sh_plt0_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x10, /* movi  .got.plt >> 16, r17 */
+  0xc8, 0x00, 0x01, 0x10, /* shori .got.plt & 65535, r17 */
+  0x89, 0x10, 0x09, 0x90, /* ld.l  r17, 8, r25 */
+  0x6b, 0xf1, 0x46, 0x00, /* ptabs r17, tr0 */
+  0x89, 0x10, 0x05, 0x10, /* ld.l  r17, 4, r17 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+};
+
+static const bfd_byte elf_sh_plt0_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x10, 0x01, 0x00, 0xcc, /* movi  .got.plt >> 16, r17 */
+  0x10, 0x01, 0x00, 0xc8, /* shori .got.plt & 65535, r17 */
+  0x90, 0x09, 0x10, 0x89, /* ld.l  r17, 8, r25 */
+  0x00, 0x46, 0xf1, 0x6b, /* ptabs r17, tr0 */
+  0x10, 0x05, 0x10, 0x89, /* ld.l  r17, 4, r17 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+};
+
+/* Sebsequent entries in an absolute procedure linkage table look like
+   this.  */
+
+static const bfd_byte elf_sh_plt_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x90, /* movi  nameN-in-GOT >> 16, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori nameN-in-GOT & 65535, r25 */
+  0x89, 0x90, 0x01, 0x90, /* ld.l  r25, 0, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0xcc, 0x00, 0x01, 0x90, /* movi  .PLT0 >> 16, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori .PLT0 & 65535, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0xcc, 0x00, 0x01, 0x50, /* movi  reloc-offset >> 16, r21 */
+  0xc8, 0x00, 0x01, 0x50, /* shori reloc-offset & 65535, r21 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+};
+
+static const bfd_byte elf_sh_plt_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x90, 0x01, 0x00, 0xcc, /* movi  nameN-in-GOT >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori nameN-in-GOT & 65535, r25 */
+  0x90, 0x01, 0x90, 0x89, /* ld.l  r25, 0, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0x90, 0x01, 0x00, 0xcc, /* movi  .PLT0 >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori .PLT0 & 65535, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0x50, 0x01, 0x00, 0xcc, /* movi  reloc-offset >> 16, r21 */
+  0x50, 0x01, 0x00, 0xc8, /* shori reloc-offset & 65535, r21 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+};
+
+/* Entries in a PIC procedure linkage table look like this.  */
+
+static const bfd_byte elf_sh_pic_plt_entry_be[PLT_ENTRY_SIZE] =
+{
+  0xcc, 0x00, 0x01, 0x90, /* movi  nameN@GOT >> 16, r25 */
+  0xc8, 0x00, 0x01, 0x90, /* shori nameN@GOT & 65535, r25 */
+  0x40, 0xc2, 0x65, 0x90, /* ldx.l r12, r25, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0x6f, 0xf0, 0xff, 0xf0, /* nop */
+  0xce, 0x00, 0x01, 0x10, /* movi  -GOT_BIAS, r17 */
+  0x00, 0xca, 0x45, 0x10, /* sub.l r12, r17, r17 */
+  0x89, 0x10, 0x09, 0x90, /* ld.l  r17, 8, r25 */
+  0x6b, 0xf1, 0x66, 0x00, /* ptabs r25, tr0 */
+  0x89, 0x10, 0x05, 0x10, /* ld.l  r17, 4, r17 */
+  0xcc, 0x00, 0x01, 0x50, /* movi  reloc-offset >> 16, r21 */
+  0xc8, 0x00, 0x01, 0x50, /* shori reloc-offset & 65535, r21 */
+  0x44, 0x01, 0xff, 0xf0, /* blink tr0, r63 */
+};
+
+static const bfd_byte elf_sh_pic_plt_entry_le[PLT_ENTRY_SIZE] =
+{
+  0x90, 0x01, 0x00, 0xcc, /* movi  nameN@GOT >> 16, r25 */
+  0x90, 0x01, 0x00, 0xc8, /* shori nameN@GOT & 65535, r25 */
+  0x90, 0x65, 0xc2, 0x40, /* ldx.l r12, r25, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0xf0, 0xff, 0xf0, 0x6f, /* nop */
+  0x10, 0x01, 0x00, 0xce, /* movi  -GOT_BIAS, r17 */
+  0x10, 0x45, 0xca, 0x00, /* sub.l r12, r17, r17 */
+  0x90, 0x09, 0x10, 0x89, /* ld.l  r17, 8, r25 */
+  0x00, 0x66, 0xf1, 0x6b, /* ptabs r25, tr0 */
+  0x10, 0x05, 0x10, 0x89, /* ld.l  r17, 4, r17 */
+  0x50, 0x01, 0x00, 0xcc, /* movi  reloc-offset >> 16, r21 */
+  0x50, 0x01, 0x00, 0xc8, /* shori reloc-offset & 65535, r21 */
+  0xf0, 0xff, 0x01, 0x44, /* blink tr0, r63 */
+};
+
+static const bfd_byte *elf_sh_plt0_entry;
+static const bfd_byte *elf_sh_plt_entry;
+static const bfd_byte *elf_sh_pic_plt_entry;
+
+/* Return size of a PLT entry.  */
+#define elf_sh_sizeof_plt(info) PLT_ENTRY_SIZE
+
+/* Return offset of the PLT0 address in an absolute PLT entry.  */
+#define elf_sh_plt_plt0_offset(info) 32
+
+/* Return offset of the linker in PLT0 entry.  */
+#define elf_sh_plt0_gotplt_offset(info) 0
+
+/* Return offset of the trampoline in PLT entry */
+#define elf_sh_plt_temp_offset(info) 33 /* Add one because it's SHmedia.  */
+
+/* Return offset of the symbol in PLT entry.  */
+#define elf_sh_plt_symbol_offset(info) 0
+
+/* Return offset of the relocation in PLT entry.  */
+#define elf_sh_plt_reloc_offset(info) (info->shared ? 52 : 44)
+
+inline static void
+movi_shori_putval (output_bfd, value, addr)
+     bfd *output_bfd;
+     unsigned long value;
+     char *addr;
+{
+  bfd_put_32 (output_bfd,
+             bfd_get_32 (output_bfd, addr)
+             | ((value >> 6) & 0x3fffc00),
+             addr);
+  bfd_put_32 (output_bfd,
+             bfd_get_32 (output_bfd, addr + 4)
+             | ((value << 10) & 0x3fffc00),
+             addr + 4);
+}
+
+#else
 /* The size in bytes of an entry in the procedure linkage table.  */
 
 #define PLT_ENTRY_SIZE 28
@@ -2340,6 +3345,7 @@ static const bfd_byte *elf_sh_pic_plt_entry;
 
 /* Return offset of the relocation in PLT entry.  */
 #define elf_sh_plt_reloc_offset(info) 24
+#endif
 
 /* The sh linker needs to keep track of the number of relocs that it
    decides to copy in check_relocs for each symbol.  This is so that
@@ -2366,6 +3372,10 @@ struct elf_sh_link_hash_entry
 {
   struct elf_link_hash_entry root;
 
+#ifdef INCLUDE_SHMEDIA
+  bfd_vma datalabel_got_offset;
+#endif
+
   /* Number of PC relative relocs copied for this symbol.  */
   struct elf_sh_pcrel_relocs_copied *pcrel_relocs_copied;
 };
@@ -2422,6 +3432,9 @@ sh_elf_link_hash_newfunc (entry, table, string)
   if (ret != (struct elf_sh_link_hash_entry *) NULL)
     {
       ret->pcrel_relocs_copied = NULL;
+#ifdef INCLUDE_SHMEDIA
+      ret->datalabel_got_offset = (bfd_vma) -1;
+#endif
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -2436,14 +3449,14 @@ sh_elf_link_hash_table_create (abfd)
   struct elf_sh_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf_sh_link_hash_table);
 
-  ret = (struct elf_sh_link_hash_table *) bfd_alloc (abfd, amt);
+  ret = (struct elf_sh_link_hash_table *) bfd_malloc (amt);
   if (ret == (struct elf_sh_link_hash_table *) NULL)
     return NULL;
 
   if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
                                       sh_elf_link_hash_newfunc))
     {
-      bfd_release (abfd, ret);
+      free (ret);
       return NULL;
     }
 
@@ -2806,8 +3819,8 @@ sh_elf_size_dynamic_sections (output_bfd, info)
      will not fill them in in the relocate_section routine.  */
   if (info->shared && info->symbolic)
     sh_elf_link_hash_traverse (sh_elf_hash_table (info),
-                                sh_elf_discard_copies,
-                                (PTR) NULL);
+                              sh_elf_discard_copies,
+                              (PTR) NULL);
 
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
@@ -2945,6 +3958,9 @@ sh_elf_discard_copies (h, ignore)
 {
   struct elf_sh_pcrel_relocs_copied *s;
 
+  if (h->root.root.type == bfd_link_hash_warning)
+    h = (struct elf_sh_link_hash_entry *) h->root.root.u.i.link;
+
   /* We only discard relocs for symbols defined in a regular object.  */
   if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
     return true;
@@ -2975,6 +3991,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   bfd *dynobj;
   bfd_vma *local_got_offsets;
   asection *sgot;
+  asection *sgotplt;
   asection *splt;
   asection *sreloc;
 
@@ -2984,6 +4001,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   local_got_offsets = elf_local_got_offsets (input_bfd);
 
   sgot = NULL;
+  sgotplt = NULL;
   splt = NULL;
   sreloc = NULL;
 
@@ -3000,6 +4018,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
       bfd_vma relocation;
       bfd_vma addend = (bfd_vma) 0;
       bfd_reloc_status_type r;
+      int seen_stt_datalabel = 0;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
 
@@ -3017,6 +4036,10 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          || r_type >= R_SH_max
          || (r_type >= (int) R_SH_FIRST_INVALID_RELOC
              && r_type <= (int) R_SH_LAST_INVALID_RELOC)
+         || (   r_type >= (int) R_SH_FIRST_INVALID_RELOC_3
+             && r_type <= (int) R_SH_LAST_INVALID_RELOC_3)
+         || (   r_type >= (int) R_SH_FIRST_INVALID_RELOC_4
+             && r_type <= (int) R_SH_LAST_INVALID_RELOC_4)
          || (r_type >= (int) R_SH_FIRST_INVALID_RELOC_2
              && r_type <= (int) R_SH_LAST_INVALID_RELOC_2))
        {
@@ -3041,6 +4064,14 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          relocation = (sec->output_section->vma
                        + sec->output_offset
                        + sym->st_value);
+         /* A local symbol never has STO_SH5_ISA32, so we don't need
+            datalabel processing here.  Make sure this does not change
+            without notice.  */
+         if ((sym->st_other & STO_SH5_ISA32) != 0)
+           ((*info->callbacks->reloc_dangerous)
+            (info,
+             _("Unexpected STO_SH5_ISA32 on local symbol is not handled"),
+             input_bfd, input_section, rel->r_offset));
          if (info->relocateable)
            {
              /* This is a relocateable link.  We don't have to change
@@ -3101,9 +4132,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
               addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
               msec = sec;
               addend =
-               _bfd_merged_section_offset (output_bfd, &msec,
-                                           elf_section_data (sec)->merge_info,
-                                           sym->st_value + addend, (bfd_vma) 0)
+               _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend)
                - relocation;
              addend += msec->output_section->vma + msec->output_offset;
              bfd_put_32 (input_bfd, addend, contents + rel->r_offset);
@@ -3121,7 +4150,15 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+           {
+#ifdef INCLUDE_SHMEDIA
+             /* If the reference passes a symbol marked with
+                STT_DATALABEL, then any STO_SH5_ISA32 on the final value
+                doesn't count.  */
+             seen_stt_datalabel |= h->type == STT_DATALABEL;
+#endif
+             h = (struct elf_link_hash_entry *) h->root.u.i.link;
+           }
          if (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
            {
@@ -3130,9 +4167,21 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                 We check specially because in some obscure cases
                 sec->output_section will be NULL.  */
              if (r_type == R_SH_GOTPC
-                 || (r_type == R_SH_PLT32
+                 || r_type == R_SH_GOTPC_LOW16
+                 || r_type == R_SH_GOTPC_MEDLOW16
+                 || r_type == R_SH_GOTPC_MEDHI16
+                 || r_type == R_SH_GOTPC_HI16
+                 || ((r_type == R_SH_PLT32
+                      || r_type == R_SH_PLT_LOW16
+                      || r_type == R_SH_PLT_MEDLOW16
+                      || r_type == R_SH_PLT_MEDHI16
+                      || r_type == R_SH_PLT_HI16)
                      && h->plt.offset != (bfd_vma) -1)
-                 || (r_type == R_SH_GOT32
+                 || ((r_type == R_SH_GOT32
+                      || r_type == R_SH_GOT_LOW16
+                      || r_type == R_SH_GOT_MEDLOW16
+                      || r_type == R_SH_GOT_MEDHI16
+                      || r_type == R_SH_GOT_HI16)
                      && elf_hash_table (info)->dynamic_sections_created
                      && (! info->shared
                          || (! info->symbolic && h->dynindx != -1)
@@ -3167,9 +4216,14 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  relocation = 0;
                }
              else
-               relocation = (h->root.u.def.value
+               relocation = ((h->root.u.def.value
                              + sec->output_section->vma
-                             + sec->output_offset);
+                             + sec->output_offset)
+                             /* A STO_SH5_ISA32 causes a "bitor 1" to the
+                                symbol value, unless we've seen
+                                STT_DATALABEL on the way to it.  */
+                             | ((h->other & STO_SH5_ISA32) != 0
+                                && ! seen_stt_datalabel));
            }
          else if (h->root.type == bfd_link_hash_undefweak)
            relocation = 0;
@@ -3240,6 +4294,11 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          break;
 
        default:
+#ifdef INCLUDE_SHMEDIA
+         if (shmedia_prepare_reloc (info, input_bfd, input_section,
+                                    contents, rel, &relocation))
+           goto final_link_relocate;
+#endif
          bfd_set_error (bfd_error_bad_value);
          return false;
 
@@ -3283,35 +4342,23 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                }
 
              skip = false;
-
-             if (elf_section_data (input_section)->stab_info == NULL)
-               outrel.r_offset = rel->r_offset;
-             else
-               {
-                 bfd_vma off;
-
-                 off = (_bfd_stab_section_offset
-                        (output_bfd, &elf_hash_table (info)->stab_info,
-                         input_section,
-                         &elf_section_data (input_section)->stab_info,
-                         rel->r_offset));
-                 if (off == (bfd_vma) -1)
-                   skip = true;
-                 outrel.r_offset = off;
-               }
-
+             relocate = false;
+
+             outrel.r_offset =
+               _bfd_elf_section_offset (output_bfd, info, input_section,
+                                        rel->r_offset);
+             if (outrel.r_offset == (bfd_vma) -1)
+               skip = true;
+             else if (outrel.r_offset == (bfd_vma) -2)
+               skip = true, relocate = true;
              outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);
 
              if (skip)
-               {
-                 memset (&outrel, 0, sizeof outrel);
-                 relocate = false;
-               }
+               memset (&outrel, 0, sizeof outrel);
              else if (r_type == R_SH_REL32)
                {
                  BFD_ASSERT (h != NULL && h->dynindx != -1);
-                 relocate = false;
                  outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_REL32);
                  outrel.r_addend
                    = bfd_get_32 (input_bfd, contents + rel->r_offset);
@@ -3334,7 +4381,6 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  else
                    {
                      BFD_ASSERT (h->dynindx != -1);
-                     relocate = false;
                      outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_DIR32);
                      outrel.r_addend
                        = relocation + bfd_get_32 (input_bfd,
@@ -3357,7 +4403,56 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          goto final_link_relocate;
 
+       case R_SH_GOTPLT32:
+#ifdef INCLUDE_SHMEDIA
+       case R_SH_GOTPLT_LOW16:
+       case R_SH_GOTPLT_MEDLOW16:
+       case R_SH_GOTPLT_MEDHI16:
+       case R_SH_GOTPLT_HI16:
+       case R_SH_GOTPLT10BY4:
+       case R_SH_GOTPLT10BY8:
+#endif
+         /* Relocation is to the entry for this symbol in the
+            procedure linkage table.  */
+
+         if (h == NULL
+             || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+             || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+             || ! info->shared
+             || info->symbolic
+             || h->dynindx == -1
+             || h->plt.offset == (bfd_vma) -1
+             || h->got.offset != (bfd_vma) -1)
+           goto force_got;
+
+         /* Relocation is to the entry for this symbol in the global
+            offset table extension for the procedure linkage table.  */
+         if (sgotplt == NULL)
+           {
+             sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+             BFD_ASSERT (sgotplt != NULL);
+           }
+
+         relocation = (sgotplt->output_offset
+                       + ((h->plt.offset / elf_sh_sizeof_plt (info)
+                           - 1 + 3) * 4));
+
+#ifdef GOT_BIAS
+         relocation -= GOT_BIAS;
+#endif
+
+         goto final_link_relocate;
+
+       force_got:
        case R_SH_GOT32:
+#ifdef INCLUDE_SHMEDIA
+       case R_SH_GOT_LOW16:
+       case R_SH_GOT_MEDLOW16:
+       case R_SH_GOT_MEDHI16:
+       case R_SH_GOT_HI16:
+       case R_SH_GOT10BY4:
+       case R_SH_GOT10BY8:
+#endif
          /* Relocation is to the entry for this symbol in the global
             offset table.  */
          if (sgot == NULL)
@@ -3371,6 +4466,15 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              bfd_vma off;
 
              off = h->got.offset;
+#ifdef INCLUDE_SHMEDIA
+             if (seen_stt_datalabel)
+               {
+                 struct elf_sh_link_hash_entry *hsh;
+
+                 hsh = (struct elf_sh_link_hash_entry *)h;
+                 off = hsh->datalabel_got_offset;
+               }
+#endif
              BFD_ASSERT (off != (bfd_vma) -1);
 
              if (! elf_hash_table (info)->dynamic_sections_created
@@ -3398,7 +4502,17 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                    {
                      bfd_put_32 (output_bfd, relocation,
                                  sgot->contents + off);
-                     h->got.offset |= 1;
+#ifdef INCLUDE_SHMEDIA
+                     if (seen_stt_datalabel)
+                       {
+                         struct elf_sh_link_hash_entry *hsh;
+
+                         hsh = (struct elf_sh_link_hash_entry *)h;
+                         hsh->datalabel_got_offset |= 1;
+                       }
+                     else
+#endif
+                       h->got.offset |= 1;
                    }
                }
 
@@ -3408,10 +4522,27 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            {
              bfd_vma off;
 
+#ifdef INCLUDE_SHMEDIA
+             if (rel->r_addend)
+               {
+                 BFD_ASSERT (local_got_offsets != NULL
+                             && (local_got_offsets[symtab_hdr->sh_info
+                                                   + r_symndx]
+                                 != (bfd_vma) -1));
+
+                 off = local_got_offsets[symtab_hdr->sh_info
+                                         + r_symndx];
+               }
+             else
+               {
+#endif
              BFD_ASSERT (local_got_offsets != NULL
                          && local_got_offsets[r_symndx] != (bfd_vma) -1);
 
              off = local_got_offsets[r_symndx];
+#ifdef INCLUDE_SHMEDIA
+               }
+#endif
 
              /* The offset must always be a multiple of 4.  We use
                 the least significant bit to record whether we have
@@ -3442,15 +4573,30 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      ++srelgot->reloc_count;
                    }
 
-                 local_got_offsets[r_symndx] |= 1;
+#ifdef INCLUDE_SHMEDIA
+                 if (rel->r_addend)
+                   local_got_offsets[symtab_hdr->sh_info + r_symndx] |= 1;
+                 else
+#endif
+                   local_got_offsets[r_symndx] |= 1;
                }
 
              relocation = sgot->output_offset + off;
            }
 
+#ifdef GOT_BIAS
+         relocation -= GOT_BIAS;
+#endif
+
          goto final_link_relocate;
 
        case R_SH_GOTOFF:
+#ifdef INCLUDE_SHMEDIA
+       case R_SH_GOTOFF_LOW16:
+       case R_SH_GOTOFF_MEDLOW16:
+       case R_SH_GOTOFF_MEDHI16:
+       case R_SH_GOTOFF_HI16:
+#endif
          /* Relocation is relative to the start of the global offset
             table.  */
 
@@ -3467,9 +4613,21 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             calculation.  */
          relocation -= sgot->output_section->vma;
 
+#ifdef GOT_BIAS
+         relocation -= GOT_BIAS;
+#endif
+
+         addend = rel->r_addend;
+
          goto final_link_relocate;
 
        case R_SH_GOTPC:
+#ifdef INCLUDE_SHMEDIA
+       case R_SH_GOTPC_LOW16:
+       case R_SH_GOTPC_MEDLOW16:
+       case R_SH_GOTPC_MEDHI16:
+       case R_SH_GOTPC_HI16:
+#endif
          /* Use global offset table as symbol value.  */
 
          if (sgot == NULL)
@@ -3480,9 +4638,21 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
          relocation = sgot->output_section->vma;
 
+#ifdef GOT_BIAS
+         relocation += GOT_BIAS;
+#endif
+
+         addend = rel->r_addend;
+
          goto final_link_relocate;
 
        case R_SH_PLT32:
+#ifdef INCLUDE_SHMEDIA
+       case R_SH_PLT_LOW16:
+       case R_SH_PLT_MEDLOW16:
+       case R_SH_PLT_MEDHI16:
+       case R_SH_PLT_HI16:
+#endif
          /* Relocation is to the entry for this symbol in the
             procedure linkage table.  */
 
@@ -3513,6 +4683,12 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                        + splt->output_offset
                        + h->plt.offset);
 
+#ifdef INCLUDE_SHMEDIA
+         relocation++;
+#endif
+
+         addend = rel->r_addend;
+
          goto final_link_relocate;
 
        case R_SH_LOOP_START:
@@ -3588,8 +4764,7 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
   bfd *input_bfd = input_section->owner;
   asection **sections = NULL;
   Elf_Internal_Rela *internal_relocs = NULL;
-  Elf32_External_Sym *external_syms = NULL;
-  Elf_Internal_Sym *internal_syms = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
 
   /* We only need to handle the case of relaxing, or of having a
      particular set of section contents, specially.  */
@@ -3608,24 +4783,9 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
   if ((input_section->flags & SEC_RELOC) != 0
       && input_section->reloc_count > 0)
     {
-      Elf_Internal_Sym *isymp;
       asection **secpp;
-      Elf32_External_Sym *esym, *esymend;
-      bfd_size_type size;
-
-      if (symtab_hdr->contents != NULL)
-       external_syms = (Elf32_External_Sym *) symtab_hdr->contents;
-      else
-       {
-         size = symtab_hdr->sh_info;
-         size *= sizeof (Elf32_External_Sym);
-         external_syms = (Elf32_External_Sym *) bfd_malloc (size);
-         if (external_syms == NULL && size != 0)
-           goto error_return;
-         if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-             || bfd_bread (external_syms, size, input_bfd) != size)
-           goto error_return;
-       }
+      Elf_Internal_Sym *isym, *isymend;
+      bfd_size_type amt;
 
       internal_relocs = (_bfd_elf32_link_read_relocs
                         (input_bfd, input_section, (PTR) NULL,
@@ -3633,82 +4793,71 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
       if (internal_relocs == NULL)
        goto error_return;
 
-      size = symtab_hdr->sh_info;
-      size *= sizeof (Elf_Internal_Sym);
-      internal_syms = (Elf_Internal_Sym *) bfd_malloc (size);
-      if (internal_syms == NULL && symtab_hdr->sh_info > 0)
-       goto error_return;
+      if (symtab_hdr->sh_info != 0)
+       {
+         isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+         if (isymbuf == NULL)
+           isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
+                                           symtab_hdr->sh_info, 0,
+                                           NULL, NULL, NULL);
+         if (isymbuf == NULL)
+           goto error_return;
+       }
 
-      size = symtab_hdr->sh_info;
-      size *= sizeof (asection *);
-      sections = (asection **) bfd_malloc (size);
-      if (sections == NULL && symtab_hdr->sh_info > 0)
+      amt = symtab_hdr->sh_info;
+      amt *= sizeof (asection *);
+      sections = (asection **) bfd_malloc (amt);
+      if (sections == NULL && amt != 0)
        goto error_return;
 
-      isymp = internal_syms;
-      secpp = sections;
-      esym = external_syms;
-      esymend = esym + symtab_hdr->sh_info;
-      for (; esym < esymend; ++esym, ++isymp, ++secpp)
+      isymend = isymbuf + symtab_hdr->sh_info;
+      for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
        {
          asection *isec;
 
-         bfd_elf32_swap_symbol_in (input_bfd, esym, isymp);
-
-         if (isymp->st_shndx == SHN_UNDEF)
+         if (isym->st_shndx == SHN_UNDEF)
            isec = bfd_und_section_ptr;
-         else if (isymp->st_shndx > 0 && isymp->st_shndx < SHN_LORESERVE)
-           isec = bfd_section_from_elf_index (input_bfd, isymp->st_shndx);
-         else if (isymp->st_shndx == SHN_ABS)
+         else if (isym->st_shndx == SHN_ABS)
            isec = bfd_abs_section_ptr;
-         else if (isymp->st_shndx == SHN_COMMON)
+         else if (isym->st_shndx == SHN_COMMON)
            isec = bfd_com_section_ptr;
          else
-           {
-             /* Who knows?  */
-             isec = NULL;
-           }
+           isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
          *secpp = isec;
        }
 
       if (! sh_elf_relocate_section (output_bfd, link_info, input_bfd,
                                     input_section, data, internal_relocs,
-                                    internal_syms, sections))
+                                    isymbuf, sections))
        goto error_return;
 
       if (sections != NULL)
        free (sections);
-      sections = NULL;
-      if (internal_syms != NULL)
-       free (internal_syms);
-      internal_syms = NULL;
-      if (external_syms != NULL && symtab_hdr->contents == NULL)
-       free (external_syms);
-      external_syms = NULL;
-      if (internal_relocs != elf_section_data (input_section)->relocs)
+      if (isymbuf != NULL
+         && symtab_hdr->contents != (unsigned char *) isymbuf)
+       free (isymbuf);
+      if (elf_section_data (input_section)->relocs != internal_relocs)
        free (internal_relocs);
-      internal_relocs = NULL;
     }
 
   return data;
 
  error_return:
-  if (internal_relocs != NULL
-      && internal_relocs != elf_section_data (input_section)->relocs)
-    free (internal_relocs);
-  if (external_syms != NULL && symtab_hdr->contents == NULL)
-    free (external_syms);
-  if (internal_syms != NULL)
-    free (internal_syms);
   if (sections != NULL)
     free (sections);
+  if (isymbuf != NULL
+      && symtab_hdr->contents != (unsigned char *) isymbuf)
+    free (isymbuf);
+  if (internal_relocs != NULL
+      && elf_section_data (input_section)->relocs != internal_relocs)
+    free (internal_relocs);
   return NULL;
 }
 
 static asection *
-sh_elf_gc_mark_hook (abfd, info, rel, h, sym)
-     bfd *abfd;
+sh_elf_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      Elf_Internal_Rela *rel;
      struct elf_link_hash_entry *h;
@@ -3738,13 +4887,8 @@ sh_elf_gc_mark_hook (abfd, info, rel, h, sym)
        }
     }
   else
-    {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-                && sym->st_shndx != SHN_COMMON))
-       return bfd_section_from_elf_index (abfd, sym->st_shndx);
-    }
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
   return NULL;
 }
 
@@ -3818,9 +4962,32 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
        {
          switch (ELF32_R_TYPE (rel->r_info))
            {
+           case R_SH_GOTPLT32:
            case R_SH_GOT32:
            case R_SH_GOTOFF:
            case R_SH_GOTPC:
+#ifdef INCLUDE_SHMEDIA
+           case R_SH_GOTPLT_LOW16:
+           case R_SH_GOTPLT_MEDLOW16:
+           case R_SH_GOTPLT_MEDHI16:
+           case R_SH_GOTPLT_HI16:
+           case R_SH_GOTPLT10BY4:
+           case R_SH_GOTPLT10BY8:
+           case R_SH_GOT_LOW16:
+           case R_SH_GOT_MEDLOW16:
+           case R_SH_GOT_MEDHI16:
+           case R_SH_GOT_HI16:
+           case R_SH_GOT10BY4:
+           case R_SH_GOT10BY8:
+           case R_SH_GOTOFF_LOW16:
+           case R_SH_GOTOFF_MEDLOW16:
+           case R_SH_GOTOFF_MEDHI16:
+           case R_SH_GOTOFF_HI16:
+           case R_SH_GOTPC_LOW16:
+           case R_SH_GOTPC_MEDLOW16:
+           case R_SH_GOTPC_MEDHI16:
+           case R_SH_GOTPC_HI16:
+#endif
              elf_hash_table (info)->dynobj = dynobj = abfd;
              if (! _bfd_elf_create_got_section (dynobj, info))
                return false;
@@ -3847,7 +5014,16 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
            return false;
          break;
 
+       force_got:
        case R_SH_GOT32:
+#ifdef INCLUDE_SHMEDIA
+       case R_SH_GOT_LOW16:
+       case R_SH_GOT_MEDLOW16:
+       case R_SH_GOT_MEDHI16:
+       case R_SH_GOT_HI16:
+       case R_SH_GOT10BY4:
+       case R_SH_GOT10BY8:
+#endif
          /* This symbol requires a global offset table entry.  */
 
          if (sgot == NULL)
@@ -3878,12 +5054,30 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
 
          if (h != NULL)
            {
+#ifdef INCLUDE_SHMEDIA
+             if (h->type == STT_DATALABEL)
+               {
+                 struct elf_sh_link_hash_entry *hsh;
+
+                 h = (struct elf_link_hash_entry *) h->root.u.i.link;
+                 hsh = (struct elf_sh_link_hash_entry *)h;
+                 if (hsh->datalabel_got_offset != (bfd_vma) -1)
+                   break;
+
+                 hsh->datalabel_got_offset = sgot->_raw_size;
+               }
+             else
+               {
+#endif
              if (h->got.offset != (bfd_vma) -1)
                {
                  /* We have already allocated space in the .got.  */
                  break;
                }
              h->got.offset = sgot->_raw_size;
+#ifdef INCLUDE_SHMEDIA
+               }
+#endif
 
              /* Make sure this symbol is output as a dynamic symbol.  */
              if (h->dynindx == -1)
@@ -3905,19 +5099,46 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
 
                  size = symtab_hdr->sh_info;
                  size *= sizeof (bfd_vma);
+#ifdef INCLUDE_SHMEDIA
+                 /* Reserve space for both the datalabel and
+                    codelabel local GOT offsets.  */
+                 size *= 2;
+#endif
                  local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
                  if (local_got_offsets == NULL)
                    return false;
                  elf_local_got_offsets (abfd) = local_got_offsets;
                  for (i = 0; i < symtab_hdr->sh_info; i++)
                    local_got_offsets[i] = (bfd_vma) -1;
+#ifdef INCLUDE_SHMEDIA
+                 for (; i < 2 * symtab_hdr->sh_info; i++)
+                   local_got_offsets[i] = (bfd_vma) -1;
+#endif
+               }
+#ifdef INCLUDE_SHMEDIA
+             if ((rel->r_addend & 1) != 0)
+               {
+                 if (local_got_offsets[symtab_hdr->sh_info
+                                       + r_symndx] != (bfd_vma) -1)
+                   {
+                     /* We have already allocated space in the .got.  */
+                     break;
+                   }
+                 local_got_offsets[symtab_hdr->sh_info
+                                   + r_symndx] = sgot->_raw_size;
                }
+             else
+               {
+#endif
              if (local_got_offsets[r_symndx] != (bfd_vma) -1)
                {
                  /* We have already allocated space in the .got.  */
                  break;
                }
              local_got_offsets[r_symndx] = sgot->_raw_size;
+#ifdef INCLUDE_SHMEDIA
+               }
+#endif
 
              if (info->shared)
                {
@@ -3932,7 +5153,45 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
 
          break;
 
+       case R_SH_GOTPLT32:
+#ifdef INCLUDE_SHMEDIA
+       case R_SH_GOTPLT_LOW16:
+       case R_SH_GOTPLT_MEDLOW16:
+       case R_SH_GOTPLT_MEDHI16:
+       case R_SH_GOTPLT_HI16:
+       case R_SH_GOTPLT10BY4:
+       case R_SH_GOTPLT10BY8:
+#endif
+         /* If this is a local symbol, we resolve it directly without
+            creating a procedure linkage table entry.  */
+
+         if (h == NULL
+             || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+             || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+             || ! info->shared
+             || info->symbolic
+             || h->dynindx == -1
+             || h->got.offset != (bfd_vma) -1)
+           goto force_got;
+
+         /* Make sure this symbol is output as a dynamic symbol.  */
+         if (h->dynindx == -1)
+           {
+             if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+               return false;
+           }
+
+         h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+
+         break;
+
        case R_SH_PLT32:
+#ifdef INCLUDE_SHMEDIA
+       case R_SH_PLT_LOW16:
+       case R_SH_PLT_MEDLOW16:
+       case R_SH_PLT_MEDHI16:
+       case R_SH_PLT_HI16:
+#endif
          /* This symbol requires a procedure linkage table entry.  We
             actually build the entry in adjust_dynamic_symbol,
             because this might be a case of linking PIC code which is
@@ -4060,6 +5319,7 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
   return true;
 }
 
+#ifndef sh_elf_set_mach_from_flags
 static boolean
 sh_elf_set_mach_from_flags (abfd)
      bfd *abfd;
@@ -4095,7 +5355,9 @@ sh_elf_set_mach_from_flags (abfd)
     }
   return true;
 }
+#endif /* not sh_elf_set_mach_from_flags */
 
+#ifndef sh_elf_set_private_flags
 /* Function to keep SH specific file flags.  */
 
 static boolean
@@ -4110,7 +5372,9 @@ sh_elf_set_private_flags (abfd, flags)
   elf_flags_init (abfd) = true;
   return sh_elf_set_mach_from_flags (abfd);
 }
+#endif /* not sh_elf_set_private_flags */
 
+#ifndef sh_elf_copy_private_data
 /* Copy backend specific data from one object module to another */
 
 static boolean
@@ -4124,7 +5388,9 @@ sh_elf_copy_private_data (ibfd, obfd)
 
   return sh_elf_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
 }
+#endif /* not sh_elf_copy_private_data */
 
+#ifndef sh_elf_merge_private_data
 /* This routine checks for linking big and little endian objects
    together, and for linking sh-dsp with sh3e / sh4 objects.  */
 
@@ -4135,7 +5401,7 @@ sh_elf_merge_private_data (ibfd, obfd)
 {
   flagword old_flags, new_flags;
 
-  if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
+  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
     return false;
 
   if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
@@ -4165,6 +5431,7 @@ sh_elf_merge_private_data (ibfd, obfd)
 
   return sh_elf_set_mach_from_flags (obfd);
 }
+#endif /* not sh_elf_merge_private_data */
 
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
@@ -4211,6 +5478,10 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
         The first three are reserved.  */
       got_offset = (plt_index + 3) * 4;
 
+#ifdef GOT_BIAS
+      got_offset -= GOT_BIAS;
+#endif
+
       /* Fill in the entry in the procedure linkage table.  */
       if (! info->shared)
        {
@@ -4221,6 +5492,19 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
            }
          memcpy (splt->contents + h->plt.offset, elf_sh_plt_entry,
                  elf_sh_sizeof_plt (info));
+#ifdef INCLUDE_SHMEDIA
+         movi_shori_putval (output_bfd,
+                            (sgot->output_section->vma
+                             + sgot->output_offset
+                             + got_offset),
+                            (splt->contents + h->plt.offset
+                             + elf_sh_plt_symbol_offset (info)));
+
+         movi_shori_putval (output_bfd,
+                            (splt->output_section->vma + splt->output_offset),
+                            (splt->contents + h->plt.offset
+                             + elf_sh_plt_plt0_offset (info)));
+#else
          bfd_put_32 (output_bfd,
                      (sgot->output_section->vma
                       + sgot->output_offset
@@ -4232,6 +5516,7 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
                      (splt->output_section->vma + splt->output_offset),
                      (splt->contents + h->plt.offset
                       + elf_sh_plt_plt0_offset (info)));
+#endif
        }
       else
        {
@@ -4243,14 +5528,31 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
            }
          memcpy (splt->contents + h->plt.offset, elf_sh_pic_plt_entry,
                  elf_sh_sizeof_plt (info));
+#ifdef INCLUDE_SHMEDIA
+         movi_shori_putval (output_bfd, got_offset,
+                            (splt->contents + h->plt.offset
+                             + elf_sh_plt_symbol_offset (info)));
+#else
          bfd_put_32 (output_bfd, got_offset,
                      (splt->contents + h->plt.offset
                       + elf_sh_plt_symbol_offset (info)));
+#endif
        }
 
+#ifdef GOT_BIAS
+      got_offset += GOT_BIAS;
+#endif
+
+#ifdef INCLUDE_SHMEDIA
+      movi_shori_putval (output_bfd,
+                        plt_index * sizeof (Elf32_External_Rela),
+                        (splt->contents + h->plt.offset
+                         + elf_sh_plt_reloc_offset (info)));
+#else
       bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
                  (splt->contents + h->plt.offset
                   + elf_sh_plt_reloc_offset (info)));
+#endif
 
       /* Fill in the entry in the global offset table.  */
       bfd_put_32 (output_bfd,
@@ -4266,6 +5568,9 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
                      + got_offset);
       rel.r_info = ELF32_R_INFO (h->dynindx, R_SH_JMP_SLOT);
       rel.r_addend = 0;
+#ifdef GOT_BIAS
+      rel.r_addend = GOT_BIAS;
+#endif
       bfd_elf32_swap_reloca_out (output_bfd, &rel,
                                ((Elf32_External_Rela *) srel->contents
                                 + plt_index));
@@ -4465,12 +5770,20 @@ sh_elf_finish_dynamic_sections (output_bfd, info)
                                       elf_sh_plt0_entry_le);
                }
              memcpy (splt->contents, elf_sh_plt0_entry, PLT_ENTRY_SIZE);
+#ifdef INCLUDE_SHMEDIA
+             movi_shori_putval (output_bfd,
+                                sgot->output_section->vma
+                                + sgot->output_offset,
+                                splt->contents
+                                + elf_sh_plt0_gotplt_offset (info));
+#else
              bfd_put_32 (output_bfd,
                          sgot->output_section->vma + sgot->output_offset + 4,
                          splt->contents + elf_sh_plt0_gotid_offset (info));
              bfd_put_32 (output_bfd,
                          sgot->output_section->vma + sgot->output_offset + 8,
                          splt->contents + elf_sh_plt0_linker_offset (info));
+#endif
            }
 
          /* UnixWare sets the entsize of .plt to 4, although that doesn't
This page took 0.052158 seconds and 4 git commands to generate.