]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf32-nios2.c
Update year range in copyright notice of all files.
[thirdparty/binutils-gdb.git] / bfd / elf32-nios2.c
index a7547e8cfb3df5d3d0f6bbf7fd28bdcc77a99c67..3e4706f35f09aac50bfac1d7ee6be4d01809de4e 100644 (file)
@@ -1,5 +1,5 @@
 /* 32-bit ELF support for Nios II.
-   Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+   Copyright (C) 2012-2017 Free Software Foundation, Inc.
    Contributed by Nigel Gray (ngray@altera.com).
    Contributed by Mentor Graphics, Inc.
 
@@ -68,19 +68,20 @@ static bfd_reloc_status_type nios2_elf32_callr_relocate
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
 
 /* Target vector.  */
-extern const bfd_target bfd_elf32_littlenios2_vec;
-extern const bfd_target bfd_elf32_bignios2_vec;
+extern const bfd_target nios2_elf32_le_vec;
+extern const bfd_target nios2_elf32_be_vec;
 
 /* Offset of tp and dtp pointers from start of TLS block.  */
 #define TP_OFFSET      0x7000
 #define DTP_OFFSET     0x8000
 
-/* The relocation table used for SHT_REL sections.  */
-static reloc_howto_type elf_nios2_howto_table_rel[] = {
+/* The relocation tables used for SHT_REL sections.  There are separate
+   tables for R1 and R2 encodings.  */
+static reloc_howto_type elf_nios2_r1_howto_table_rel[] = {
   /* No relocation.  */
   HOWTO (R_NIOS2_NONE,         /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -479,13 +480,665 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        6,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_TLS_GD16",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_TLS_LDM16,
+        0,
+        2,
+        16,
+        FALSE,
+        6,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_TLS_LDM16",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_TLS_LDO16,
+        0,
+        2,
+        16,
+        FALSE,
+        6,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_TLS_LDO16",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_TLS_IE16,
+        0,
+        2,
+        16,
+        FALSE,
+        6,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_TLS_IE16",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_TLS_LE16,
+        0,
+        2,
+        16,
+        FALSE,
+        6,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_TLS_LE16",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_TLS_DTPMOD,
+        0,
+        2,
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_TLS_DTPMOD",
+        FALSE,
+        0xffffffff,
+        0xffffffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_TLS_DTPREL,
+        0,
+        2,
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_TLS_DTPREL",
+        FALSE,
+        0xffffffff,
+        0xffffffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_TLS_TPREL,
+        0,
+        2,
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_TLS_TPREL",
+        FALSE,
+        0xffffffff,
+        0xffffffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_COPY,
+        0,
+        2,
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_COPY",
+        FALSE,
+        0,
+        0,
+        FALSE),
+
+  HOWTO (R_NIOS2_GLOB_DAT,
+        0,
+        2,
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_GLOB_DAT",
+        FALSE,
+        0xffffffff,
+        0xffffffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_JUMP_SLOT,
+        0,
+        2,
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_JUMP_SLOT",
+        FALSE,
+        0xffffffff,
+        0xffffffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_RELATIVE,
+        0,
+        2,
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_RELATIVE",
+        FALSE,
+        0xffffffff,
+        0xffffffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_GOTOFF,
+        0,
+        2,
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_GOTOFF",
+        FALSE,
+        0xffffffff,
+        0xffffffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_CALL26_NOAT,  /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        26,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        6,                     /* bitpos */
+        complain_overflow_dont,        /* complain on overflow */
+        nios2_elf32_call26_relocate,   /* special function */
+        "R_NIOS2_CALL26_NOAT", /* name */
+        FALSE,                 /* partial_inplace */
+        0xffffffc0,            /* src_mask */
+        0xffffffc0,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  HOWTO (R_NIOS2_GOT_LO,
+        0,
+        2,
+        16,
+        FALSE,
+        6,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_GOT_LO",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_GOT_HA,
+        0,
+        2,
+        16,
+        FALSE,
+        6,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_GOT_HA",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_CALL_LO,
+        0,
+        2,
+        16,
+        FALSE,
+        6,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_CALL_LO",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_CALL_HA,
+        0,
+        2,
+        16,
+        FALSE,
+        6,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_CALL_HA",
+        FALSE,
+        0x003fffc0,
+        0x003fffc0,
+        FALSE),
+
+/* Add other relocations here.  */
+};
+
+static reloc_howto_type elf_nios2_r2_howto_table_rel[] = {
+  /* No relocation.  */
+  HOWTO (R_NIOS2_NONE,         /* type */
+        0,                     /* rightshift */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,        /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_NIOS2_NONE",        /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* 16-bit signed immediate relocation.  */
+  HOWTO (R_NIOS2_S16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        16,                    /* bitpos */
+        complain_overflow_signed,      /* complain on overflow */
+        bfd_elf_generic_reloc, /* special function */
+        "R_NIOS2_S16",         /* name */
+        FALSE,                 /* partial_inplace */
+        0xffff0000,            /* src_mask */
+        0xffff0000,            /* dest_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* 16-bit unsigned immediate relocation.  */
+  HOWTO (R_NIOS2_U16,          /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        16,                    /* bitpos */
+        complain_overflow_unsigned,    /* complain on overflow */
+        bfd_elf_generic_reloc, /* special function */
+        "R_NIOS2_U16",         /* name */
+        FALSE,                 /* partial_inplace */
+        0xffff0000,            /* src_mask */
+        0xffff0000,            /* dest_mask */
+        FALSE),                /* pcrel_offset */
+
+  HOWTO (R_NIOS2_PCREL16,      /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        TRUE,                  /* pc_relative */
+        16,                    /* bitpos */
+        complain_overflow_signed,      /* complain on overflow */
+        nios2_elf32_pcrel16_relocate,  /* special function */
+        "R_NIOS2_PCREL16",     /* name */
+        FALSE,                 /* partial_inplace */
+        0xffff0000,            /* src_mask */
+        0xffff0000,            /* dest_mask */
+        TRUE),                 /* pcrel_offset */
+
+  HOWTO (R_NIOS2_CALL26,       /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        26,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        6,                     /* bitpos */
+        complain_overflow_dont,        /* complain on overflow */
+        nios2_elf32_call26_relocate,   /* special function */
+        "R_NIOS2_CALL26",      /* name */
+        FALSE,                 /* partial_inplace */
+        0xffffffc0,            /* src_mask */
+        0xffffffc0,            /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  HOWTO (R_NIOS2_IMM5,
+        0,
+        2,
+        5,
+        FALSE,
+        21,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_IMM5",
+        FALSE,
+        0x03e00000,
+        0x03e00000,
+        FALSE),
+
+  HOWTO (R_NIOS2_CACHE_OPX,
+        0,
+        2,
+        5,
+        FALSE,
+        11,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_CACHE_OPX",
+        FALSE,
+        0x0000f800,
+        0x0000f800,
+        FALSE),
+
+  HOWTO (R_NIOS2_IMM6,
+        0,
+        2,
+        6,
+        FALSE,
+        26,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_IMM6",
+        FALSE,
+        0xfc000000,
+        0xfc000000,
+        FALSE),
+
+  HOWTO (R_NIOS2_IMM8,
+        0,
+        2,
+        8,
+        FALSE,
+        24,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_IMM8",
+        FALSE,
+        0xff000000,
+        0xff000000,
+        FALSE),
+
+  HOWTO (R_NIOS2_HI16,
+        0,
+        2,
+        32,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        nios2_elf32_hi16_relocate,
+        "R_NIOS2_HI16",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_LO16,
+        0,
+        2,
+        32,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        nios2_elf32_lo16_relocate,
+        "R_NIOS2_LO16",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_HIADJ16,
+        0,
+        2,
+        32,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        nios2_elf32_hiadj16_relocate,
+        "R_NIOS2_HIADJ16",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_BFD_RELOC_32,
+        0,
+        2,                     /* long */
+        32,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_BFD_RELOC32",
+        FALSE,
+        0xffffffff,
+        0xffffffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_BFD_RELOC_16,
+        0,
+        1,                     /* short */
+        16,
+        FALSE,
+        0,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_BFD_RELOC16",
+        FALSE,
+        0x0000ffff,
+        0x0000ffff,
+        FALSE),
+
+  HOWTO (R_NIOS2_BFD_RELOC_8,
+        0,
+        0,                     /* byte */
+        8,
+        FALSE,
+        0,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_BFD_RELOC8",
+        FALSE,
+        0x000000ff,
+        0x000000ff,
+        FALSE),
+
+  HOWTO (R_NIOS2_GPREL,
+        0,
+        2,
+        32,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        nios2_elf32_gprel_relocate,
+        "R_NIOS2_GPREL",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_GNU_VTINHERIT,
+        0,
+        2,                     /* short */
+        0,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        NULL,
+        "R_NIOS2_GNU_VTINHERIT",
+        FALSE,
+        0,
+        0,
+        FALSE),
+
+  HOWTO (R_NIOS2_GNU_VTENTRY,
+        0,
+        2,                     /* byte */
+        0,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        _bfd_elf_rel_vtable_reloc_fn,
+        "R_NIOS2_GNU_VTENTRY",
+        FALSE,
+        0,
+        0,
+        FALSE),
+
+  HOWTO (R_NIOS2_UJMP,
+        0,
+        2,
+        32,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        nios2_elf32_ujmp_relocate,
+        "R_NIOS2_UJMP",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_CJMP,
+        0,
+        2,
+        32,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        nios2_elf32_cjmp_relocate,
+        "R_NIOS2_CJMP",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_CALLR,
+        0,
+        2,
+        32,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        nios2_elf32_callr_relocate,
+        "R_NIOS2_CALLR",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_ALIGN,
+        0,
+        2,
+        0,
+        FALSE,
+        0,
+        complain_overflow_dont,
+        nios2_elf32_ignore_reloc,
+        "R_NIOS2_ALIGN",
+        FALSE,
+        0,
+        0,
+        TRUE),
+
+  HOWTO (R_NIOS2_GOT16,
+        0,
+        2,
+        16,
+        FALSE,
+        16,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_GOT16",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_CALL16,
+        0,
+        2,
+        16,
+        FALSE,
+        16,
+        complain_overflow_bitfield,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_CALL16",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_GOTOFF_LO,
+        0,
+        2,
+        16,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_GOTOFF_LO",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_GOTOFF_HA,
+        0,
+        2,
+        16,
+        FALSE,
+        16,
+        complain_overflow_dont,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_GOTOFF_HA",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_PCREL_LO,
+        0,
+        2,
+        16,
+        TRUE,
+        16,
+        complain_overflow_dont,
+        nios2_elf32_pcrel_lo16_relocate,
+        "R_NIOS2_PCREL_LO",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        TRUE),
+
+  HOWTO (R_NIOS2_PCREL_HA,
+        0,
+        2,
+        16,
+        FALSE, /* This is a PC-relative relocation, but we need to subtract
+                  PC ourselves before the HIADJ.  */
+        16,
+        complain_overflow_dont,
+        nios2_elf32_pcrel_hiadj16_relocate,
+        "R_NIOS2_PCREL_HA",
+        FALSE,
+        0xffff0000,
+        0xffff0000,
+        TRUE),
+
+  HOWTO (R_NIOS2_TLS_GD16,
+        0,
+        2,
+        16,
+        FALSE,
+        16,
         complain_overflow_bitfield,
         bfd_elf_generic_reloc,
         "R_NIOS2_TLS_GD16",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
         FALSE),
 
   HOWTO (R_NIOS2_TLS_LDM16,
@@ -493,13 +1146,13 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        16,
         complain_overflow_bitfield,
         bfd_elf_generic_reloc,
         "R_NIOS2_TLS_LDM16",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
         FALSE),
 
   HOWTO (R_NIOS2_TLS_LDO16,
@@ -507,13 +1160,13 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        16,
         complain_overflow_bitfield,
         bfd_elf_generic_reloc,
         "R_NIOS2_TLS_LDO16",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
         FALSE),
 
   HOWTO (R_NIOS2_TLS_IE16,
@@ -521,13 +1174,13 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        16,
         complain_overflow_bitfield,
         bfd_elf_generic_reloc,
         "R_NIOS2_TLS_IE16",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
         FALSE),
 
   HOWTO (R_NIOS2_TLS_LE16,
@@ -535,13 +1188,13 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        16,
         complain_overflow_bitfield,
         bfd_elf_generic_reloc,
         "R_NIOS2_TLS_LE16",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
         FALSE),
 
   HOWTO (R_NIOS2_TLS_DTPMOD,
@@ -675,13 +1328,13 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        16,
         complain_overflow_dont,
         bfd_elf_generic_reloc,
         "R_NIOS2_GOT_LO",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
         FALSE),
 
   HOWTO (R_NIOS2_GOT_HA,
@@ -689,13 +1342,13 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        16,
         complain_overflow_dont,
         bfd_elf_generic_reloc,
         "R_NIOS2_GOT_HA",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
         FALSE),
 
   HOWTO (R_NIOS2_CALL_LO,
@@ -703,13 +1356,13 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        16,
         complain_overflow_dont,
         bfd_elf_generic_reloc,
         "R_NIOS2_CALL_LO",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
         FALSE),
 
   HOWTO (R_NIOS2_CALL_HA,
@@ -717,13 +1370,195 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
         2,
         16,
         FALSE,
-        6,
+        16,
         complain_overflow_dont,
         bfd_elf_generic_reloc,
         "R_NIOS2_CALL_HA",
         FALSE,
-        0x003fffc0,
-        0x003fffc0,
+        0xffff0000,
+        0xffff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_S12,
+        0,
+        2,
+        12,
+        FALSE,
+        16,
+        complain_overflow_signed,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_S12",
+        FALSE,
+        0x0fff0000,
+        0x0fff0000,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_I10_1_PCREL,
+        1,
+        1,
+        10,
+        TRUE,
+        6,
+        complain_overflow_signed,
+        bfd_elf_generic_reloc,         /* FIXME? */
+        "R_NIOS2_R2_I10_1_PCREL",
+        FALSE,
+        0xffc0,
+        0xffc0,
+        TRUE),
+
+  HOWTO (R_NIOS2_R2_T1I7_1_PCREL,
+        1,
+        1,
+        7,
+        TRUE,
+        9,
+        complain_overflow_signed,
+        bfd_elf_generic_reloc,         /* FIXME? */
+        "R_NIOS2_R2_T1I7_1_PCREL",
+        FALSE,
+        0xfe00,
+        0xfe00,
+        TRUE),
+
+  HOWTO (R_NIOS2_R2_T1I7_2,
+        2,
+        1,
+        7,
+        FALSE,
+        9,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_T1I7_2",
+        FALSE,
+        0xfe00,
+        0xfe00,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_T2I4,
+        0,
+        1,
+        4,
+        FALSE,
+        12,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_T2I4",
+        FALSE,
+        0xf000,
+        0xf000,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_T2I4_1,
+        1,
+        1,
+        4,
+        FALSE,
+        12,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_T2I4_1",
+        FALSE,
+        0xf000,
+        0xf000,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_T2I4_2,
+        2,
+        1,
+        4,
+        FALSE,
+        12,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_T2I4_2",
+        FALSE,
+        0xf000,
+        0xf000,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_X1I7_2,
+        2,
+        1,
+        7,
+        FALSE,
+        6,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_X1I7_2",
+        FALSE,
+        0x1fc0,
+        0x1fc0,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_X2L5,
+        0,
+        1,
+        5,
+        FALSE,
+        6,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_X2L5",
+        FALSE,
+        0x07c0,
+        0x07c0,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_F1I5_2,
+        2,
+        1,
+        5,
+        FALSE,
+        6,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_F1L5_2",
+        FALSE,
+        0x07c0,
+        0x07c0,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_L5I4X1,
+        2,
+        1,
+        4,
+        FALSE,
+        6,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_L5I4X1",
+        FALSE,
+        0x03c0,
+        0x03c0,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_T1X1I6,
+        0,
+        1,
+        6,
+        FALSE,
+        9,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_T1X1I6",
+        FALSE,
+        0x7e00,
+        0x7e00,
+        FALSE),
+
+  HOWTO (R_NIOS2_R2_T1X1I6_2,
+        2,
+        2,
+        6,
+        FALSE,
+        9,
+        complain_overflow_unsigned,
+        bfd_elf_generic_reloc,
+        "R_NIOS2_R2_T1I1X6_2",
+        FALSE,
+        0x7e00,
+        0x7e00,
         FALSE),
 
 /* Add other relocations here.  */
@@ -731,29 +1566,51 @@ static reloc_howto_type elf_nios2_howto_table_rel[] = {
 
 static unsigned char elf_code_to_howto_index[R_NIOS2_ILLEGAL + 1];
 
+
+/* Return true if producing output for a R2 BFD.  */
+#define BFD_IS_R2(abfd) (bfd_get_mach (abfd) == bfd_mach_nios2r2)
+
 /* Return the howto for relocation RTYPE.  */
 static reloc_howto_type *
-lookup_howto (unsigned int rtype)
+lookup_howto (unsigned int rtype, bfd *abfd)
 {
   static int initialized = 0;
   int i;
-  int howto_tbl_size = (int) (sizeof (elf_nios2_howto_table_rel)
-                             / sizeof (elf_nios2_howto_table_rel[0]));
+  /* R2 relocations are a superset of R1, so use that for the lookup
+     table.  */
+  int r1_howto_tbl_size = (int) (sizeof (elf_nios2_r1_howto_table_rel)
+                                / sizeof (elf_nios2_r1_howto_table_rel[0]));
+  int r2_howto_tbl_size = (int) (sizeof (elf_nios2_r2_howto_table_rel)
+                                / sizeof (elf_nios2_r2_howto_table_rel[0]));
 
   if (!initialized)
     {
       initialized = 1;
       memset (elf_code_to_howto_index, 0xff,
              sizeof (elf_code_to_howto_index));
-      for (i = 0; i < howto_tbl_size; i++)
-       elf_code_to_howto_index[elf_nios2_howto_table_rel[i].type] = i;
+      for (i = 0; i < r2_howto_tbl_size; i++)
+       {
+         elf_code_to_howto_index[elf_nios2_r2_howto_table_rel[i].type] = i;
+         if (i < r1_howto_tbl_size)
+           BFD_ASSERT (elf_nios2_r2_howto_table_rel[i].type
+                       == elf_nios2_r1_howto_table_rel[i].type);
+       }
     }
 
   BFD_ASSERT (rtype <= R_NIOS2_ILLEGAL);
   i = elf_code_to_howto_index[rtype];
-  if (i >= howto_tbl_size)
-    return 0;
-  return elf_nios2_howto_table_rel + i;
+  if (BFD_IS_R2 (abfd))
+    {
+      if (i >= r2_howto_tbl_size)
+       return 0;
+      return elf_nios2_r2_howto_table_rel + i;
+    }
+  else
+    {
+      if (i >= r1_howto_tbl_size)
+       return 0;
+      return elf_nios2_r1_howto_table_rel + i;
+    }
 }
 
 /* Map for converting BFD reloc types to Nios II reloc types.  */
@@ -764,6 +1621,7 @@ struct elf_reloc_map
 };
 
 static const struct elf_reloc_map nios2_reloc_map[] = {
+  {BFD_RELOC_NONE, R_NIOS2_NONE},
   {BFD_RELOC_NIOS2_S16, R_NIOS2_S16},
   {BFD_RELOC_NIOS2_U16, R_NIOS2_U16},
   {BFD_RELOC_16_PCREL, R_NIOS2_PCREL16},
@@ -809,6 +1667,19 @@ static const struct elf_reloc_map nios2_reloc_map[] = {
   {BFD_RELOC_NIOS2_GOT_HA, R_NIOS2_GOT_HA},
   {BFD_RELOC_NIOS2_CALL_LO, R_NIOS2_CALL_LO},
   {BFD_RELOC_NIOS2_CALL_HA, R_NIOS2_CALL_HA},
+  {BFD_RELOC_NIOS2_R2_S12, R_NIOS2_R2_S12},
+  {BFD_RELOC_NIOS2_R2_I10_1_PCREL, R_NIOS2_R2_I10_1_PCREL},
+  {BFD_RELOC_NIOS2_R2_T1I7_1_PCREL, R_NIOS2_R2_T1I7_1_PCREL},
+  {BFD_RELOC_NIOS2_R2_T1I7_2, R_NIOS2_R2_T1I7_2},
+  {BFD_RELOC_NIOS2_R2_T2I4, R_NIOS2_R2_T2I4},
+  {BFD_RELOC_NIOS2_R2_T2I4_1, R_NIOS2_R2_T2I4_1},
+  {BFD_RELOC_NIOS2_R2_T2I4_2, R_NIOS2_R2_T2I4_2},
+  {BFD_RELOC_NIOS2_R2_X1I7_2, R_NIOS2_R2_X1I7_2},
+  {BFD_RELOC_NIOS2_R2_X2L5, R_NIOS2_R2_X2L5},
+  {BFD_RELOC_NIOS2_R2_F1I5_2, R_NIOS2_R2_F1I5_2},
+  {BFD_RELOC_NIOS2_R2_L5I4X1, R_NIOS2_R2_L5I4X1},
+  {BFD_RELOC_NIOS2_R2_T1X1I6, R_NIOS2_R2_T1X1I6},
+  {BFD_RELOC_NIOS2_R2_T1X1I6_2, R_NIOS2_R2_T1X1I6_2},
 };
 
 enum elf32_nios2_stub_type
@@ -944,13 +1815,11 @@ struct elf32_nios2_link_hash_table
 
     /* Assorted information used by nios2_elf32_size_stubs.  */
     unsigned int bfd_count;
-    int top_index;
+    unsigned int top_index;
     asection **input_list;
     Elf_Internal_Sym **all_local_syms;
 
     /* Short-cuts to get to dynamic linker sections.  */
-    asection *sdynbss;
-    asection *srelbss;
     asection *sbss;
 
     /* GOT pointer symbol _gp_got.  */
@@ -1034,7 +1903,7 @@ nios2_elf32_install_imm16 (asection *sec, bfd_vma offset, bfd_vma value)
 {
   bfd_vma word = bfd_get_32 (sec->owner, sec->contents + offset);
 
-  BFD_ASSERT(value <= 0xffff);
+  BFD_ASSERT (value <= 0xffff || ((bfd_signed_vma) value) >= -0xffff);
 
   bfd_put_32 (sec->owner, word | ((value & 0xffff) << 6),
              sec->contents + offset);
@@ -1354,9 +2223,10 @@ nios2_add_stub (const char *stub_name,
                                TRUE, FALSE);
   if (hsh == NULL)
     {
-      (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
-                            section->owner,
-                            stub_name);
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%B: cannot create stub entry %s"),
+                         section->owner,
+                         stub_name);
       return NULL;
     }
 
@@ -1374,7 +2244,7 @@ nios2_elf32_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
 {
   bfd *input_bfd;
   unsigned int bfd_count;
-  int top_id, top_index;
+  unsigned int top_id, top_index;
   asection *section;
   asection **input_list, **list;
   bfd_size_type amt;
@@ -1383,7 +2253,7 @@ nios2_elf32_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
   /* Count the number of input BFDs and find the top input section id.  */
   for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
        input_bfd != NULL;
-       input_bfd = input_bfd->link_next)
+       input_bfd = input_bfd->link.next)
     {
       bfd_count += 1;
       for (section = input_bfd->sections;
@@ -1718,7 +2588,7 @@ get_local_syms (bfd *output_bfd ATTRIBUTE_UNUSED, bfd *input_bfd,
   /* Walk over all the input BFDs, swapping in local symbols.  */
   for (bfd_indx = 0;
        input_bfd != NULL;
-       input_bfd = input_bfd->link_next, bfd_indx++)
+       input_bfd = input_bfd->link.next, bfd_indx++)
     {
       Elf_Internal_Shdr *symtab_hdr;
 
@@ -1783,7 +2653,7 @@ nios2_elf32_size_stubs (bfd *output_bfd, bfd *stub_bfd,
 
       for (input_bfd = info->input_bfds, bfd_indx = 0;
           input_bfd != NULL;
-          input_bfd = input_bfd->link_next, bfd_indx++)
+          input_bfd = input_bfd->link.next, bfd_indx++)
        {
          Elf_Internal_Shdr *symtab_hdr;
          asection *section;
@@ -1908,7 +2778,7 @@ nios2_elf32_size_stubs (bfd *output_bfd, bfd *stub_bfd,
                        }
                      else if (hh->root.root.type == bfd_link_hash_undefweak)
                        {
-                         if (! info->shared)
+                         if (! bfd_link_pic (info))
                            continue;
                        }
                      else if (hh->root.root.type == bfd_link_hash_undefined)
@@ -2013,16 +2883,21 @@ nios2_elf32_build_stubs (struct bfd_link_info *info)
   for (stub_sec = htab->stub_bfd->sections;
        stub_sec != NULL;
        stub_sec = stub_sec->next)
-    {
-      bfd_size_type size;
+    /* The stub_bfd may contain non-stub sections if it is also the
+       dynobj.  Any such non-stub sections are created with the
+       SEC_LINKER_CREATED flag set, while stub sections do not
+       have that flag.  Ignore any non-stub sections here.  */
+    if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+      {
+       bfd_size_type size;
 
-      /* Allocate memory to hold the linker stubs.  */
-      size = stub_sec->size;
-      stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
-      if (stub_sec->contents == NULL && size != 0)
-       return FALSE;
-      stub_sec->size = 0;
-    }
+       /* Allocate memory to hold the linker stubs.  */
+       size = stub_sec->size;
+       stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
+       if (stub_sec->contents == NULL && size != 0)
+         return FALSE;
+       stub_sec->size = 0;
+      }
 
   /* Build the stubs as directed by the stub hash table.  */
   table = &htab->bstab;
@@ -2032,50 +2907,129 @@ nios2_elf32_build_stubs (struct bfd_link_info *info)
 }
 
 
+#define is_nios2_elf(bfd) \
+  (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+   && elf_object_id (bfd) == NIOS2_ELF_DATA)
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+nios2_elf32_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
+{
+  bfd *obfd = info->output_bfd;
+  flagword old_flags;
+  flagword new_flags;
+
+  if (!is_nios2_elf (ibfd) || !is_nios2_elf (obfd))
+    return TRUE;
+
+  /* Check if we have the same endianness.  */
+  if (! _bfd_generic_verify_endian_match (ibfd, info))
+    return FALSE;
+
+  new_flags = elf_elfheader (ibfd)->e_flags;
+  old_flags = elf_elfheader (obfd)->e_flags;
+  if (!elf_flags_init (obfd))
+    {
+      /* First call, no flags set.  */
+      elf_flags_init (obfd) = TRUE;
+      elf_elfheader (obfd)->e_flags = new_flags;
+
+      switch (new_flags)
+       {
+       default:
+       case EF_NIOS2_ARCH_R1:
+         bfd_default_set_arch_mach (obfd, bfd_arch_nios2, bfd_mach_nios2r1);
+         break;
+       case EF_NIOS2_ARCH_R2:
+         if (bfd_big_endian (ibfd))
+           {
+             _bfd_error_handler
+               (_("error: %B: Big-endian R2 is not supported."), ibfd);
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
+           }
+         bfd_default_set_arch_mach (obfd, bfd_arch_nios2, bfd_mach_nios2r2);
+         break;
+       }
+    }
+
+  /* Incompatible flags.  */
+  else if (new_flags != old_flags)
+    {
+      /* So far, the only incompatible flags denote incompatible
+        architectures.  */
+      _bfd_error_handler
+       /* xgettext:c-format */
+       (_("error: %B: Conflicting CPU architectures %d/%d"),
+        ibfd, new_flags, old_flags);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  _bfd_elf_merge_object_attributes (ibfd, info);
+
+  return TRUE;
+}
+
+
 /* Implement bfd_elf32_bfd_reloc_type_lookup:
    Given a BFD reloc type, return a howto structure.  */
 static reloc_howto_type *
-nios2_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+nios2_elf32_bfd_reloc_type_lookup (bfd *abfd,
                                   bfd_reloc_code_real_type code)
 {
   int i;
+
   for (i = 0;
        i < (int) (sizeof (nios2_reloc_map) / sizeof (struct elf_reloc_map));
        ++i)
     if (nios2_reloc_map[i].bfd_val == code)
-      return &elf_nios2_howto_table_rel[(int) nios2_reloc_map[i].elf_val];
+      return lookup_howto (nios2_reloc_map[i].elf_val, abfd);
   return NULL;
 }
 
 /* Implement bfd_elf32_bfd_reloc_name_lookup:
    Given a reloc name, return a howto structure.  */
 static reloc_howto_type *
-nios2_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+nios2_elf32_bfd_reloc_name_lookup (bfd *abfd,
                                   const char *r_name)
 {
-  unsigned int i;
-  for (i = 0;
-       i < (sizeof (elf_nios2_howto_table_rel)
-           / sizeof (elf_nios2_howto_table_rel[0]));
-       i++)
-    if (elf_nios2_howto_table_rel[i].name
-       && strcasecmp (elf_nios2_howto_table_rel[i].name, r_name) == 0)
-      return &elf_nios2_howto_table_rel[i];
-
-  return NULL; 
+  int i;
+  reloc_howto_type *howto_tbl;
+  int howto_tbl_size;
+
+  if (BFD_IS_R2 (abfd))
+    {
+      howto_tbl = elf_nios2_r2_howto_table_rel;
+      howto_tbl_size = (int) (sizeof (elf_nios2_r2_howto_table_rel)
+                             / sizeof (elf_nios2_r2_howto_table_rel[0]));
+    }
+  else
+    {
+      howto_tbl = elf_nios2_r1_howto_table_rel;
+      howto_tbl_size = (int) (sizeof (elf_nios2_r1_howto_table_rel)
+                             / sizeof (elf_nios2_r1_howto_table_rel[0]));
+    }
+
+  for (i = 0; i < howto_tbl_size; i++)
+    if (howto_tbl[i].name && strcasecmp (howto_tbl[i].name, r_name) == 0)
+      return howto_tbl + i;
+  return NULL;
 }
 
 /* Implement elf_info_to_howto:
    Given a ELF32 relocation, fill in a arelent structure.  */
 static void
-nios2_elf32_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
+nios2_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr,
                           Elf_Internal_Rela *dst)
 {
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (r_type < R_NIOS2_ILLEGAL);
-  cache_ptr->howto = &elf_nios2_howto_table_rel[r_type];
+  cache_ptr->howto = lookup_howto (r_type, abfd);
 }
 
 /* Return the base VMA address which should be subtracted from real addresses
@@ -2133,7 +3087,15 @@ lookup:
        case bfd_link_hash_defined:
        case bfd_link_hash_defweak:
          gp_found = TRUE;
-         *pgp = lh->u.def.value;
+         {
+           asection *sym_sec = lh->u.def.section;
+           bfd_vma sym_value = lh->u.def.value;
+
+           if (sym_sec->output_section)
+             sym_value = (sym_value + sym_sec->output_offset
+                          + sym_sec->output_section->vma);
+           *pgp = sym_value;
+         }
          break;
        case bfd_link_hash_indirect:
        case bfd_link_hash_warning:
@@ -2167,7 +3129,7 @@ lookup:
    symbol value for an external symbol if we are producing relocatable
    output.  */
 static bfd_reloc_status_type
-nios2_elf_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable, 
+nios2_elf_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable,
                    char **error_message, bfd_vma *pgp)
 {
   if (bfd_is_und_section (symbol->section) && !relocatable)
@@ -2198,9 +3160,9 @@ nios2_elf_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable,
 
 /* Do the relocations that require special handling.  */
 static bfd_reloc_status_type
-nios2_elf32_do_hi16_relocate (bfd *abfd, reloc_howto_type *howto, 
+nios2_elf32_do_hi16_relocate (bfd *abfd, reloc_howto_type *howto,
                              asection *input_section,
-                             bfd_byte *data, bfd_vma offset, 
+                             bfd_byte *data, bfd_vma offset,
                              bfd_vma symbol_value, bfd_vma addend)
 {
   symbol_value = symbol_value + addend;
@@ -2213,7 +3175,7 @@ nios2_elf32_do_hi16_relocate (bfd *abfd, reloc_howto_type *howto,
 static bfd_reloc_status_type
 nios2_elf32_do_lo16_relocate (bfd *abfd, reloc_howto_type *howto,
                              asection *input_section,
-                             bfd_byte *data, bfd_vma offset, 
+                             bfd_byte *data, bfd_vma offset,
                              bfd_vma symbol_value, bfd_vma addend)
 {
   symbol_value = symbol_value + addend;
@@ -2268,10 +3230,10 @@ nios2_elf32_do_pcrel_hiadj16_relocate (bfd *abfd, reloc_howto_type *howto,
 static bfd_reloc_status_type
 nios2_elf32_do_pcrel16_relocate (bfd *abfd, reloc_howto_type *howto,
                                 asection *input_section,
-                                bfd_byte *data, bfd_vma offset, 
+                                bfd_byte *data, bfd_vma offset,
                                 bfd_vma symbol_value, bfd_vma addend)
 {
-  /* NIOS2 pc relative relocations are relative to the next 32-bit instruction 
+  /* NIOS2 pc relative relocations are relative to the next 32-bit instruction
      so we need to subtract 4 before doing a final_link_relocate. */
   symbol_value = symbol_value + addend - 4;
   addend = 0;
@@ -2282,16 +3244,21 @@ nios2_elf32_do_pcrel16_relocate (bfd *abfd, reloc_howto_type *howto,
 static bfd_reloc_status_type
 nios2_elf32_do_call26_relocate (bfd *abfd, reloc_howto_type *howto,
                                asection *input_section,
-                               bfd_byte *data, bfd_vma offset, 
+                               bfd_byte *data, bfd_vma offset,
                                bfd_vma symbol_value, bfd_vma addend)
 {
   /* Check that the relocation is in the same page as the current address.  */
-  if (CALL26_SEGMENT (symbol_value + addend) 
+  if (CALL26_SEGMENT (symbol_value + addend)
       != CALL26_SEGMENT (input_section->output_section->vma
                         + input_section->output_offset
                         + offset))
     return bfd_reloc_overflow;
 
+  /* Check that the target address is correctly aligned on a 4-byte
+     boundary.  */
+  if ((symbol_value + addend) & 0x3)
+    return bfd_reloc_overflow;
+
   return _bfd_final_link_relocate (howto, abfd, input_section,
                                   data, offset, symbol_value, addend);
 }
@@ -2299,7 +3266,7 @@ nios2_elf32_do_call26_relocate (bfd *abfd, reloc_howto_type *howto,
 static bfd_reloc_status_type
 nios2_elf32_do_gprel_relocate (bfd *abfd, reloc_howto_type *howto,
                               asection *input_section,
-                              bfd_byte *data, bfd_vma offset, 
+                              bfd_byte *data, bfd_vma offset,
                               bfd_vma symbol_value, bfd_vma addend)
 {
   /* Because we need the output_bfd, the special handling is done
@@ -2311,7 +3278,7 @@ nios2_elf32_do_gprel_relocate (bfd *abfd, reloc_howto_type *howto,
 static bfd_reloc_status_type
 nios2_elf32_do_ujmp_relocate (bfd *abfd, reloc_howto_type *howto,
                              asection *input_section,
-                             bfd_byte *data, bfd_vma offset, 
+                             bfd_byte *data, bfd_vma offset,
                              bfd_vma symbol_value, bfd_vma addend)
 {
   bfd_vma symbol_lo16, symbol_hi16;
@@ -2334,7 +3301,7 @@ nios2_elf32_do_ujmp_relocate (bfd *abfd, reloc_howto_type *howto,
 static bfd_reloc_status_type
 nios2_elf32_do_cjmp_relocate (bfd *abfd, reloc_howto_type *howto,
                              asection *input_section,
-                             bfd_byte *data, bfd_vma offset, 
+                             bfd_byte *data, bfd_vma offset,
                              bfd_vma symbol_value, bfd_vma addend)
 {
   bfd_vma symbol_lo16, symbol_hi16;
@@ -2357,7 +3324,7 @@ nios2_elf32_do_cjmp_relocate (bfd *abfd, reloc_howto_type *howto,
 static bfd_reloc_status_type
 nios2_elf32_do_callr_relocate (bfd *abfd, reloc_howto_type *howto,
                               asection *input_section,
-                              bfd_byte *data, bfd_vma offset, 
+                              bfd_byte *data, bfd_vma offset,
                               bfd_vma symbol_value, bfd_vma addend)
 {
   bfd_vma symbol_lo16, symbol_hi16;
@@ -2383,9 +3350,9 @@ nios2_elf32_do_callr_relocate (bfd *abfd, reloc_howto_type *howto,
    changes in size of section don't screw up .align.  */
 static bfd_reloc_status_type
 nios2_elf32_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
-                         asymbol *symbol ATTRIBUTE_UNUSED, 
-                         void *data ATTRIBUTE_UNUSED, asection *input_section, 
-                         bfd *output_bfd, 
+                         asymbol *symbol ATTRIBUTE_UNUSED,
+                         void *data ATTRIBUTE_UNUSED, asection *input_section,
+                         bfd *output_bfd,
                          char **error_message ATTRIBUTE_UNUSED)
 {
   if (output_bfd != NULL)
@@ -2394,9 +3361,9 @@ nios2_elf32_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
 }
 
 static bfd_reloc_status_type
-nios2_elf32_hi16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, 
-                          void *data, asection *input_section, 
-                          bfd *output_bfd, 
+nios2_elf32_hi16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+                          void *data, asection *input_section,
+                          bfd *output_bfd,
                           char **error_message ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
@@ -2423,8 +3390,8 @@ nios2_elf32_hi16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 nios2_elf32_lo16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                          void *data, asection *input_section, 
-                          bfd *output_bfd, 
+                          void *data, asection *input_section,
+                          bfd *output_bfd,
                           char **error_message ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
@@ -2451,8 +3418,8 @@ nios2_elf32_lo16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 nios2_elf32_hiadj16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                             void *data, asection *input_section, 
-                             bfd *output_bfd, 
+                             void *data, asection *input_section,
+                             bfd *output_bfd,
                              char **error_message ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
@@ -2531,8 +3498,8 @@ nios2_elf32_pcrel_hiadj16_relocate (bfd *abfd, arelent *reloc_entry,
 
 static bfd_reloc_status_type
 nios2_elf32_pcrel16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                             void *data, asection *input_section, 
-                             bfd *output_bfd, 
+                             void *data, asection *input_section,
+                             bfd *output_bfd,
                              char **error_message ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
@@ -2559,8 +3526,8 @@ nios2_elf32_pcrel16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 nios2_elf32_call26_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                            void *data, asection *input_section, 
-                            bfd *output_bfd, 
+                            void *data, asection *input_section,
+                            bfd *output_bfd,
                             char **error_message ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
@@ -2587,7 +3554,7 @@ nios2_elf32_call26_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 nios2_elf32_gprel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                           void *data, asection *input_section, 
+                           void *data, asection *input_section,
                            bfd *output_bfd, char **msg)
 {
   bfd_vma relocation;
@@ -2635,7 +3602,7 @@ nios2_elf32_gprel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 nios2_elf32_ujmp_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                          void *data, asection *input_section, 
+                          void *data, asection *input_section,
                           bfd *output_bfd, char **msg ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
@@ -2662,7 +3629,7 @@ nios2_elf32_ujmp_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 nios2_elf32_cjmp_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                          void *data, asection *input_section, 
+                          void *data, asection *input_section,
                           bfd *output_bfd, char **msg ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
@@ -2689,7 +3656,7 @@ nios2_elf32_cjmp_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
 static bfd_reloc_status_type
 nios2_elf32_callr_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-                           void *data, asection *input_section, 
+                           void *data, asection *input_section,
                            bfd *output_bfd, char **msg ATTRIBUTE_UNUSED)
 {
   /* This part is from bfd_elf_generic_reloc.  */
@@ -2714,7 +3681,7 @@ nios2_elf32_callr_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
                                        reloc_entry->addend);
 }
 
+
 /* Implement elf_backend_relocate_section.  */
 static bfd_boolean
 nios2_elf32_relocate_section (bfd *output_bfd,
@@ -2761,7 +3728,6 @@ nios2_elf32_relocate_section (bfd *output_bfd,
       struct elf32_nios2_link_hash_entry *eh;
       bfd_vma relocation;
       bfd_vma gp;
-      bfd_vma reloc_address;
       bfd_reloc_status_type r = bfd_reloc_ok;
       const char *name = NULL;
       int r_type;
@@ -2775,7 +3741,7 @@ nios2_elf32_relocate_section (bfd *output_bfd,
       r_type = ELF32_R_TYPE (rel->r_info);
       r_symndx = ELF32_R_SYM (rel->r_info);
 
-      howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
+      howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info), output_bfd);
       h = NULL;
       sym = NULL;
       sec = NULL;
@@ -2801,15 +3767,9 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                                         rel, 1, relend, howto, 0, contents);
 
       /* Nothing more to do unless this is a final link.  */
-      if (info->relocatable)
+      if (bfd_link_relocatable (info))
        continue;
 
-      if (sec && sec->output_section)
-       reloc_address = (sec->output_section->vma + sec->output_offset
-                        + rel->r_offset);
-      else
-       reloc_address = 0;
-               
       if (howto)
        {
          switch (howto->type)
@@ -2858,6 +3818,15 @@ nios2_elf32_relocate_section (bfd *output_bfd,
              /* Turns an absolute address into a gp-relative address.  */
              if (!nios2_elf_assign_gp (output_bfd, &gp, info))
                {
+                 bfd_vma reloc_address;
+
+                 if (sec && sec->output_section)
+                   reloc_address = (sec->output_section->vma
+                                    + sec->output_offset
+                                    + rel->r_offset);
+                 else
+                   reloc_address = 0;
+
                  format = _("global pointer relative relocation at address "
                             "0x%08x when _gp not defined\n");
                  sprintf (msgbuf, format, reloc_address);
@@ -2867,7 +3836,7 @@ nios2_elf32_relocate_section (bfd *output_bfd,
              else
                {
                  bfd_vma symbol_address = rel->r_addend + relocation;
-                 relocation = relocation + rel->r_addend - gp;
+                 relocation = symbol_address - gp;
                  rel->r_addend = 0;
                  if (((signed) relocation < -32768
                       || (signed) relocation > 32767)
@@ -2875,11 +3844,14 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                          || h->root.type == bfd_link_hash_defined
                          || h->root.type == bfd_link_hash_defweak))
                    {
+                     if (h)
+                       name = h->root.root.string;
+                     /* xgettext:c-format */
                      format = _("Unable to reach %s (at 0x%08x) from the "
                                 "global pointer (at 0x%08x) because the "
                                 "offset (%d) is out of the allowed range, "
                                 "-32678 to 32767.\n" );
-                     sprintf (msgbuf, format, name, symbol_address, gp, 
+                     sprintf (msgbuf, format, name, symbol_address, gp,
                               (signed)relocation);
                      msg = msgbuf;
                      r = bfd_reloc_outofrange;
@@ -2890,7 +3862,6 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                                                  rel->r_offset, relocation,
                                                  rel->r_addend);
                }
-
              break;
            case R_NIOS2_UJMP:
              r = nios2_elf32_do_ujmp_relocate (input_bfd, howto,
@@ -3028,8 +3999,10 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                  off = h->got.offset;
                  BFD_ASSERT (off != (bfd_vma) -1);
                  dyn = elf_hash_table (info)->dynamic_sections_created;
-                 if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
-                     || (info->shared
+                 if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+                                                        bfd_link_pic (info),
+                                                        h)
+                     || (bfd_link_pic (info)
                          && SYMBOL_REFERENCES_LOCAL (info, h))
                      || (ELF_ST_VISIBILITY (h->other)
                          && h->root.type == bfd_link_hash_undefweak))
@@ -3073,7 +4046,7 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                      bfd_put_32 (output_bfd, relocation,
                                  sgot->contents + off);
 
-                     if (info->shared)
+                     if (bfd_link_pic (info))
                        {
                          asection *srelgot;
                          Elf_Internal_Rela outrel;
@@ -3097,7 +4070,7 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                    }
                }
 
-             if (use_plt && info->shared)
+             if (use_plt && bfd_link_pic (info))
                {
                  off = ((h->plt.offset - 24) / 12 + 3) * 4;
                  relocation = (htab->root.sgotplt->output_offset + off
@@ -3198,7 +4171,7 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                {
                  /* If we don't know the module number, create a relocation
                     for it.  */
-                 if (info->shared)
+                 if (bfd_link_pic (info))
                    {
                      Elf_Internal_Rela outrel;
                      bfd_byte *loc;
@@ -3245,8 +4218,10 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                  {
                    bfd_boolean dyn;
                    dyn = htab->root.dynamic_sections_created;
-                   if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
-                       && (!info->shared
+                   if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+                                                        bfd_link_pic (info),
+                                                        h)
+                       && (!bfd_link_pic (info)
                            || !SYMBOL_REFERENCES_LOCAL (info, h)))
                      {
                        unresolved_reloc = FALSE;
@@ -3281,7 +4256,7 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                       now, and emit any relocations.  If both an IE GOT and a
                       GD GOT are necessary, we emit the GD first.  */
 
-                   if ((info->shared || indx != 0)
+                   if ((bfd_link_pic (info) || indx != 0)
                        && (h == NULL
                            || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                            || h->root.type != bfd_link_hash_undefweak))
@@ -3390,9 +4365,10 @@ nios2_elf32_relocate_section (bfd *output_bfd,
 
              break;
            case R_NIOS2_TLS_LE16:
-             if (info->shared && !info->pie)
+             if (bfd_link_dll (info))
                {
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
+                   /* xgettext:c-format */
                    (_("%B(%A+0x%lx): R_NIOS2_TLS_LE16 relocation not "
                       "permitted in shared object"),
                     input_bfd, input_section,
@@ -3408,7 +4384,7 @@ nios2_elf32_relocate_section (bfd *output_bfd,
              break;
 
            case R_NIOS2_BFD_RELOC_32:
-             if (info->shared
+             if (bfd_link_pic (info)
                  && (input_section->flags & SEC_ALLOC) != 0
                  && (h == NULL
                      || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@@ -3439,8 +4415,8 @@ nios2_elf32_relocate_section (bfd *output_bfd,
                    memset (&outrel, 0, sizeof outrel);
                  else if (h != NULL
                           && h->dynindx != -1
-                          && (!info->shared
-                              || !info->symbolic
+                          && (!bfd_link_pic (info)
+                              || !SYMBOLIC_BIND (info, h)
                               || !h->def_regular))
                    {
                      outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
@@ -3507,16 +4483,16 @@ nios2_elf32_relocate_section (bfd *output_bfd,
          switch (r)
            {
            case bfd_reloc_overflow:
-             r = info->callbacks->reloc_overflow (info, NULL, name,
-                                                  howto->name, (bfd_vma) 0,
-                                                  input_bfd, input_section,
-                                                  rel->r_offset);
+             (*info->callbacks->reloc_overflow) (info, NULL, name,
+                                                 howto->name, (bfd_vma) 0,
+                                                 input_bfd, input_section,
+                                                 rel->r_offset);
              break;
 
            case bfd_reloc_undefined:
-             r = info->callbacks->undefined_symbol (info, name, input_bfd,
-                                                    input_section,
-                                                    rel->r_offset, TRUE);
+             (*info->callbacks->undefined_symbol) (info, name, input_bfd,
+                                                   input_section,
+                                                   rel->r_offset, TRUE);
              break;
 
            case bfd_reloc_outofrange:
@@ -3542,8 +4518,8 @@ nios2_elf32_relocate_section (bfd *output_bfd,
 
          if (msg)
            {
-             r = info->callbacks->warning
-               (info, msg, name, input_bfd, input_section, rel->r_offset);
+             (*info->callbacks->warning) (info, msg, name, input_bfd,
+                                          input_section, rel->r_offset);
              return FALSE;
            }
        }
@@ -3624,26 +4600,14 @@ nios2_elf32_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
   if (!htab->root.sgot && !create_got_section (dynobj, info))
     return FALSE;
 
-  _bfd_elf_create_dynamic_sections (dynobj, info);
+  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
+    return FALSE;
 
   /* In order for the two loads in a shared object .PLTresolve to share the
      same %hiadj, the start of the PLT (as well as the GOT) must be aligned
      to a 16-byte boundary.  This is because the addresses for these loads
      include the -(.plt+4) PIC correction.  */
-  if (!bfd_set_section_alignment (dynobj, htab->root.splt, 4))
-    return FALSE;
-
-  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
-  if (!htab->sdynbss)
-    return FALSE;
-  if (!info->shared)
-    {
-      htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
-      if (!htab->srelbss)
-       return FALSE;
-    }
-
-  return TRUE;
+  return bfd_set_section_alignment (dynobj, htab->root.splt, 4);
 }
 
 /* Implement elf_backend_copy_indirect_symbol:
@@ -3701,6 +4665,29 @@ nios2_elf32_copy_indirect_symbol (struct bfd_link_info *info,
   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
 
+/* Set the right machine number for a NIOS2 ELF file.  */
+
+static bfd_boolean
+nios2_elf32_object_p (bfd *abfd)
+{
+  unsigned long mach;
+
+  mach = elf_elfheader (abfd)->e_flags;
+
+  switch (mach)
+    {
+    default:
+    case EF_NIOS2_ARCH_R1:
+      bfd_default_set_arch_mach (abfd, bfd_arch_nios2, bfd_mach_nios2r1);
+      break;
+    case EF_NIOS2_ARCH_R2:
+      bfd_default_set_arch_mach (abfd, bfd_arch_nios2, bfd_mach_nios2r2);
+      break;
+    }
+
+  return TRUE;
+}
+
 /* Implement elf_backend_check_relocs:
    Look through the relocs for a section during the first phase.  */
 static bfd_boolean
@@ -3718,7 +4705,7 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info,
   asection *sreloc = NULL;
   bfd_signed_vma *local_got_refcounts;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   dynobj = elf_hash_table (info)->dynobj;
@@ -3805,7 +4792,7 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info,
              }
 
            if (srelgot == NULL
-               && (h != NULL || info->shared))
+               && (h != NULL || bfd_link_pic (info)))
              {
                srelgot = htab->root.srelgot;
                BFD_ASSERT (srelgot != NULL);
@@ -3911,7 +4898,7 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info,
                   sections have not yet been mapped to output sections.
                   Tentatively set the flag for now, and correct in
                   adjust_dynamic_symbol.  */
-             if (!info->shared)
+             if (!bfd_link_pic (info))
                h->non_got_ref = 1;
 
              /* Make sure a plt entry is created for this symbol if it
@@ -3924,11 +4911,11 @@ nios2_elf32_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
          /* If we are creating a shared library, we need to copy the
             reloc into the shared library.  */
-         if (info->shared
+         if (bfd_link_pic (info)
              && (sec->flags & SEC_ALLOC) != 0
              && (r_type == R_NIOS2_BFD_RELOC_32
                  || (h != NULL && ! h->needs_plt
-                     && (! info->symbolic || ! h->def_regular))))
+                     && (! SYMBOLIC_BIND (info, h) || ! h->def_regular))))
            {
              struct elf32_nios2_dyn_relocs *p;
              struct elf32_nios2_dyn_relocs **head;
@@ -4031,7 +5018,7 @@ nios2_elf32_gc_sweep_hook (bfd *abfd,
   const Elf_Internal_Rela *rel, *relend;
   bfd *dynobj;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   elf_section_data (sec)->local_dynrel = NULL;
@@ -4157,7 +5144,7 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd,
       BFD_ASSERT (splt != NULL && sgotplt != NULL && srela != NULL);
 
       /* Emit the PLT entry.  */
-      if (info->shared)
+      if (bfd_link_pic (info))
        {
          nios2_elf32_install_data (splt, nios2_so_plt_entry, h->plt.offset,
                                    3);
@@ -4247,7 +5234,7 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd,
         The entry in the global offset table will already have been
         initialized in the relocate_section function.  */
 
-      if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
+      if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
        {
          rela.r_info = ELF32_R_INFO (0, R_NIOS2_RELATIVE);
          rela.r_addend = bfd_get_signed_32 (output_bfd,
@@ -4288,14 +5275,16 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd,
                  && (h->root.type == bfd_link_hash_defined
                      || h->root.type == bfd_link_hash_defweak));
 
-      s = htab->srelbss;
-      BFD_ASSERT (s != NULL);
-
       rela.r_offset = (h->root.u.def.value
                       + h->root.u.def.section->output_section->vma
                       + h->root.u.def.section->output_offset);
       rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_COPY);
       rela.r_addend = 0;
+      if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+       s = htab->root.sreldynrelro;
+      else
+       s = htab->root.srelbss;
+      BFD_ASSERT (s != NULL);
       loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
       bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
     }
@@ -4348,44 +5337,27 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_PLTGOT:
-             s = htab->root.sgot;
-             BFD_ASSERT (s != NULL);
-             dyn.d_un.d_ptr = s->output_section->vma;
+             s = htab->root.sgotplt;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
            case DT_JMPREL:
              s = htab->root.srelplt;
-             BFD_ASSERT (s != NULL);
-             dyn.d_un.d_ptr = s->output_section->vma;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
            case DT_PLTRELSZ:
              s = htab->root.srelplt;
-             BFD_ASSERT (s != NULL);
              dyn.d_un.d_val = s->size;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
-           case DT_RELASZ:
-             /* The procedure linkage table relocs (DT_JMPREL) should
-                not be included in the overall relocs (DT_RELA).
-                Therefore, we override the DT_RELASZ entry here to
-                make it not include the JMPREL relocs.  Since the
-                linker script arranges for .rela.plt to follow all
-                other relocation sections, we don't have to worry
-                about changing the DT_RELA entry.  */
-             s = htab->root.srelplt;
-             if (s != NULL)
-               dyn.d_un.d_val -= s->size;
-             bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
-             break;
-
            case DT_NIOS2_GP:
-             s = htab->root.sgot;
-             BFD_ASSERT (s != NULL);
-             dyn.d_un.d_ptr = s->output_section->vma + 0x7ff0;
+             s = htab->root.sgotplt;
+             dyn.d_un.d_ptr
+               = s->output_section->vma + s->output_offset + 0x7ff0;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
            }
@@ -4396,14 +5368,19 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd,
        {
          bfd_vma got_address = (sgotplt->output_section->vma
                                 + sgotplt->output_offset);
-         if (info->shared)
+         if (bfd_link_pic (info))
            {
-             bfd_vma corrected = got_address - (splt->output_section->vma
-                                                + splt->output_offset + 4);
+             bfd_vma got_pcrel = got_address - (splt->output_section->vma
+                                                + splt->output_offset);
+             /* Both GOT and PLT must be aligned to a 16-byte boundary
+                for the two loads to share the %hiadj part.  The 4-byte
+                offset for nextpc is accounted for in the %lo offsets
+                on the loads.  */
+             BFD_ASSERT ((got_pcrel & 0xf) == 0);
              nios2_elf32_install_data (splt, nios2_so_plt0_entry, 0, 6);
-             nios2_elf32_install_imm16 (splt, 4, hiadj (corrected));
-             nios2_elf32_install_imm16 (splt, 12, (corrected & 0xffff) + 4);
-             nios2_elf32_install_imm16 (splt, 16, (corrected & 0xffff) + 8);
+             nios2_elf32_install_imm16 (splt, 4, hiadj (got_pcrel));
+             nios2_elf32_install_imm16 (splt, 12, got_pcrel & 0xffff);
+             nios2_elf32_install_imm16 (splt, 16, (got_pcrel + 4) & 0xffff);
            }
          else
            {
@@ -4419,6 +5396,10 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd,
                            6 | ((res_size - (res_offset + 4)) << 6),
                            splt->contents + res_offset);
 
+             /* The GOT must be aligned to a 16-byte boundary for the
+                two loads to share the same %hiadj part.  */
+             BFD_ASSERT ((got_address & 0xf) == 0);
+
              nios2_elf32_install_data (splt, nios2_plt0_entry, res_size, 7);
              nios2_elf32_install_imm16 (splt, res_size, hiadj (res_start));
              nios2_elf32_install_imm16 (splt, res_size + 4,
@@ -4426,9 +5407,9 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd,
              nios2_elf32_install_imm16 (splt, res_size + 12,
                                         hiadj (got_address));
              nios2_elf32_install_imm16 (splt, res_size + 16,
-                                        (got_address & 0xffff) + 4);
+                                        (got_address + 4) & 0xffff);
              nios2_elf32_install_imm16 (splt, res_size + 20,
-                                        (got_address & 0xffff) + 8);
+                                        (got_address + 8) & 0xffff);
            }
        }
     }
@@ -4462,7 +5443,7 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info,
 {
   struct elf32_nios2_link_hash_table *htab;
   bfd *dynobj;
-  asection *s;
+  asection *s, *srel;
   unsigned align2;
 
   htab = elf32_nios2_hash_table (info);
@@ -4525,13 +5506,13 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info,
      only references to the symbol are via the global offset table.
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.  */
-  if (info->shared)
+  if (bfd_link_pic (info))
     return TRUE;
 
   if (h->size == 0)
     {
-      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
-                            h->root.root.string);
+      _bfd_error_handler (_("dynamic variable `%s' is zero size"),
+                         h->root.root.string);
       return TRUE;
     }
 
@@ -4544,19 +5525,22 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info,
      determine the address it must put in the global offset table, so
      both the dynamic object and the regular object will refer to the
      same memory location for the variable.  */
-  s = htab->sdynbss;
-  BFD_ASSERT (s != NULL);
-
   /* We must generate a R_NIOS2_COPY reloc to tell the dynamic linker to
      copy the initial value out of the dynamic object and into the
      runtime process image.  We need to remember the offset into the
      .rela.bss section we are going to use.  */
+  if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+    {
+      s = htab->root.sdynrelro;
+      srel = htab->root.sreldynrelro;
+    }
+  else
+    {
+      s = htab->root.sdynbss;
+      srel = htab->root.srelbss;
+    }
   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
     {
-      asection *srel;
-
-      srel = htab->srelbss;
-      BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf32_External_Rela);
       h->needs_copy = 1;
     }
@@ -4642,14 +5626,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
          && !bfd_elf_link_record_dynamic_symbol (info, h))
        return FALSE;
 
-      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
+      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
        {
          asection *s = htab->root.splt;
 
          /* Allocate room for the header.  */
          if (s->size == 0)
            {
-             if (info->shared)
+             if (bfd_link_pic (info))
                s->size = 24;
              else
                s->size = 28;
@@ -4662,7 +5646,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
             location in the .plt.  This is required to make function
             pointers compare as equal between the normal executable and
             the shared library.  */
-         if (! info->shared
+         if (! bfd_link_pic (info)
              && !h->def_regular)
            {
              h->root.u.def.section = s;
@@ -4730,13 +5714,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
       dyn = htab->root.dynamic_sections_created;
 
       indx = 0;
-      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
-         && (!info->shared
+      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
+         && (!bfd_link_pic (info)
              || !SYMBOL_REFERENCES_LOCAL (info, h)))
        indx = h->dynindx;
 
       if (tls_type != GOT_NORMAL
-         && (info->shared || indx != 0)
+         && (bfd_link_pic (info) || indx != 0)
          && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
              || h->root.type != bfd_link_hash_undefweak))
        {
@@ -4752,7 +5736,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
       else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                || h->root.type != bfd_link_hash_undefweak)
               && !use_plt
-              && (info->shared
+              && (bfd_link_pic (info)
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
        htab->root.srelgot->size += sizeof (Elf32_External_Rela);
     }
@@ -4768,10 +5752,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
      space for pc-relative relocs that have become local due to symbol
      visibility changes.  */
 
-  if (info->shared)
+  if (bfd_link_pic (info))
     {
       if (h->def_regular
-         && (h->forced_local || info->symbolic))
+         && (h->forced_local || SYMBOLIC_BIND (info, h)))
        {
          struct elf32_nios2_dyn_relocs **pp;
 
@@ -4864,7 +5848,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
@@ -4886,7 +5870,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* Set up .got offsets for local syms, and space for local dynamic
      relocs.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     {
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
@@ -4945,7 +5929,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              if (*local_tls_type == GOT_NORMAL)
                s->size += 4;
 
-             if (info->shared || *local_tls_type == GOT_TLS_GD)
+             if (bfd_link_pic (info) || *local_tls_type == GOT_TLS_GD)
                srel->size += sizeof (Elf32_External_Rela);
            }
          else
@@ -4959,7 +5943,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         for R_NIOS2_TLS_LDM16 relocations.  */
       htab->tls_ldm_got.offset = htab->root.sgot->size;
       htab->root.sgot->size += 8;
-      if (info->shared)
+      if (bfd_link_pic (info))
        htab->root.srelgot->size += sizeof (Elf32_External_Rela);
     }
   else
@@ -4996,13 +5980,13 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
         of the dynobj section names depend upon the input files.  */
       name = bfd_get_section_name (dynobj, s);
 
-      if (strcmp (name, ".plt") == 0)
+      if (s == htab->root.splt)
        {
          /* Remember whether there is a PLT.  */
          plt = s->size != 0;
 
          /* Correct for the number of res_N branches.  */
-         if (plt && !info->shared)
+         if (plt && !bfd_link_pic (info))
            {
              htab->res_n_size = (s->size-28) / 3;
              s->size += htab->res_n_size;
@@ -5019,9 +6003,14 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              s->reloc_count = 0;
            }
        }
-      else if (CONST_STRNEQ (name, ".got"))
-       got = s->size != 0;
-      else if (strcmp (name, ".dynbss") != 0)
+      else if (s == htab->root.sgot
+              || s == htab->root.sgotplt)
+       {
+         if (s->size != 0)
+           got = TRUE;
+       }
+      else if (s != htab->root.sdynbss
+              && s != htab->root.sdynrelro)
        /* It's not one of our sections, so don't allocate space.  */
        continue;
 
@@ -5069,7 +6058,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 #define add_dynamic_entry(TAG, VAL) \
   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
-      if (!info->shared && !add_dynamic_entry (DT_DEBUG, 0))
+      if (!bfd_link_pic (info) && !add_dynamic_entry (DT_DEBUG, 0))
        return FALSE;
 
       if (got && !add_dynamic_entry (DT_PLTGOT, 0))
@@ -5087,7 +6076,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))))
        return FALSE;
 
-      if (!info->shared && !add_dynamic_entry (DT_NIOS2_GP, 0))
+      if (!bfd_link_pic (info) && !add_dynamic_entry (DT_NIOS2_GP, 0))
        return FALSE;
 
       if ((info->flags & DF_TEXTREL) != 0
@@ -5099,6 +6088,17 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   return TRUE;
 }
 
+/* Free the derived linker hash table.  */
+static void
+nios2_elf32_link_hash_table_free (bfd *obfd)
+{
+  struct elf32_nios2_link_hash_table *htab
+    = (struct elf32_nios2_link_hash_table *) obfd->link.hash;
+
+  bfd_hash_table_free (&htab->bstab);
+  _bfd_elf_link_hash_table_free (obfd);
+}
+
 /* Implement bfd_elf32_bfd_link_hash_table_create.  */
 static struct bfd_link_hash_table *
 nios2_elf32_link_hash_table_create (bfd *abfd)
@@ -5123,22 +6123,15 @@ nios2_elf32_link_hash_table_create (bfd *abfd)
   /* Init the stub hash table too.  */
   if (!bfd_hash_table_init (&ret->bstab, stub_hash_newfunc,
                            sizeof (struct elf32_nios2_stub_hash_entry)))
-    return NULL;
+    {
+      _bfd_elf_link_hash_table_free (abfd);
+      return NULL;
+    }
+  ret->root.root.hash_table_free = nios2_elf32_link_hash_table_free;
 
   return &ret->root.root;
 }
 
-/* Free the derived linker hash table.  */
-static void
-nios2_elf32_link_hash_table_free (struct bfd_link_hash_table *btab)
-{
-  struct elf32_nios2_link_hash_table *htab
-    = (struct elf32_nios2_link_hash_table *) btab;
-
-  bfd_hash_table_free (&htab->bstab);
-  _bfd_elf_link_hash_table_free (btab);
-}
-
 /* Implement elf_backend_reloc_type_class.  */
 static enum elf_reloc_type_class
 nios2_elf32_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
@@ -5162,8 +6155,8 @@ nios2_elf32_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
 static bfd_boolean
 is_nios2_elf_target (const struct bfd_target *targ)
 {
-  return (targ == &bfd_elf32_littlenios2_vec
-         || targ == &bfd_elf32_bignios2_vec);
+  return (targ == &nios2_elf32_le_vec
+         || targ == &nios2_elf32_be_vec);
 }
 
 /* Implement elf_backend_add_symbol_hook.
@@ -5181,7 +6174,7 @@ nios2_elf_add_symbol_hook (bfd *abfd,
   bfd *dynobj;
 
   if (sym->st_shndx == SHN_COMMON
-      && !info->relocatable
+      && !bfd_link_relocatable (info)
       && sym->st_size <= elf_gp_size (abfd)
       && is_nios2_elf_target (info->output_bfd->xvec))
     {
@@ -5245,8 +6238,9 @@ const struct bfd_elf_special_section elf32_nios2_special_sections[] =
 
 #define bfd_elf32_bfd_link_hash_table_create \
                                          nios2_elf32_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_free \
-                                         nios2_elf32_link_hash_table_free
+
+#define bfd_elf32_bfd_merge_private_bfd_data \
+                                         nios2_elf32_merge_private_bfd_data
 
 /* Relocation table lookup macros.  */
 
@@ -5265,7 +6259,9 @@ const struct bfd_elf_special_section elf32_nios2_special_sections[] =
 #define elf_backend_can_refcount       1
 #define elf_backend_plt_readonly       1
 #define elf_backend_want_got_plt       1
+#define elf_backend_want_dynrelro      1
 #define elf_backend_rela_normal                1
+#define elf_backend_dtrel_excludes_plt 1
 
 #define elf_backend_relocate_section     nios2_elf32_relocate_section
 #define elf_backend_section_flags        nios2_elf32_section_flags
@@ -5284,6 +6280,7 @@ const struct bfd_elf_special_section elf32_nios2_special_sections[] =
 #define elf_backend_size_dynamic_sections nios2_elf32_size_dynamic_sections
 #define elf_backend_add_symbol_hook      nios2_elf_add_symbol_hook
 #define elf_backend_copy_indirect_symbol  nios2_elf32_copy_indirect_symbol
+#define elf_backend_object_p             nios2_elf32_object_p
 
 #define elf_backend_grok_prstatus        nios2_grok_prstatus
 #define elf_backend_grok_psinfo                  nios2_grok_psinfo
@@ -5294,11 +6291,12 @@ const struct bfd_elf_special_section elf32_nios2_special_sections[] =
 
 #define elf_backend_special_sections     elf32_nios2_special_sections
 
-#define TARGET_LITTLE_SYM              bfd_elf32_littlenios2_vec
+#define TARGET_LITTLE_SYM              nios2_elf32_le_vec
 #define TARGET_LITTLE_NAME             "elf32-littlenios2"
-#define TARGET_BIG_SYM                 bfd_elf32_bignios2_vec
+#define TARGET_BIG_SYM                 nios2_elf32_be_vec
 #define TARGET_BIG_NAME                        "elf32-bignios2"
 
 #define elf_backend_got_header_size    12
+#define elf_backend_default_execstack  0
 
 #include "elf32-target.h"