gdb: fix vfork with multiple threads
[deliverable/binutils-gdb.git] / bfd / elf32-or1k.c
index a7fe0a9c7c55414a1bcb213e0a953b5982d7f0c8..4ae7f324d33f6b0af3d0465145da4a52cbb2429f 100644 (file)
@@ -1,5 +1,5 @@
 /* Or1k-specific support for 32-bit ELF.
-   Copyright (C) 2001-2020 Free Software Foundation, Inc.
+   Copyright (C) 2001-2021 Free Software Foundation, Inc.
    Contributed for OR32 by Johan Rydberg, jrydberg@opencores.org
 
    PIC parts added by Stefan Kristiansson, stefan.kristiansson@saunalahti.fi,
 #define N_ONES(X)      (((bfd_vma)2 << (X)) - 1)
 
 #define PLT_ENTRY_SIZE 16
+#define PLT_ENTRY_SIZE_LARGE (6*4)
+#define PLT_MAX_INSN_COUNT 6
 
 #define OR1K_MOVHI(D)          (0x18000000 | (D << 21))
 #define OR1K_ADRP(D)           (0x08000000 | (D << 21))
 #define OR1K_LWZ(D,A)          (0x84000000 | (D << 21) | (A << 16))
+#define OR1K_ADD(D,A,B)                (0xE0000000 | (D << 21) | (A << 16) | (B << 11))
+#define OR1K_ORI(D,A)          (0xA8000000 | (D << 21) | (A << 16))
 #define OR1K_ORI0(D)           (0xA8000000 | (D << 21))
 #define OR1K_JR(B)             (0x44000000 | (B << 11))
 #define OR1K_NOP               0x15000000
@@ -47,593 +51,593 @@ static reloc_howto_type or1k_elf_howto_table[] =
         0,                     /* rightshift */
         3,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_NONE",         /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_32,
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_unsigned, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_32",           /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_16,
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_unsigned, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_16",           /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_8,
         0,                     /* rightshift */
         0,                     /* size (0 = byte, 1 = short, 2 = long) */
         8,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_unsigned, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_8",            /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0xff,                  /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_LO_16_IN_INSN, /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_LO_16_IN_INSN", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_HI_16_IN_INSN, /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_HI_16_IN_INSN", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* A PC relative 26 bit relocation, right shifted by 2.  */
   HOWTO (R_OR1K_INSN_REL_26, /* type */
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         26,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_INSN_REL_26", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0x03ffffff,            /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   /* GNU extension to record C++ vtable hierarchy.  */
   HOWTO (R_OR1K_GNU_VTINHERIT, /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         NULL,                  /* special_function */
         "R_OR1K_GNU_VTINHERIT", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* GNU extension to record C++ vtable member usage.  */
   HOWTO (R_OR1K_GNU_VTENTRY, /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_elf_rel_vtable_reloc_fn, /* special_function */
         "R_OR1K_GNU_VTENTRY", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_32_PCREL,
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_32_PCREL",     /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0xffffffff,            /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   HOWTO (R_OR1K_16_PCREL,
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_16_PCREL",     /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0xffff,                /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   HOWTO (R_OR1K_8_PCREL,
         0,                     /* rightshift */
         0,                     /* size (0 = byte, 1 = short, 2 = long) */
         8,                     /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_8_PCREL",      /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0xff,                  /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
    HOWTO (R_OR1K_GOTPC_HI16,   /* Type.  */
         16,                    /* Rightshift.  */
         2,                     /* Size (0 = byte, 1 = short, 2 = long).  */
         16,                    /* Bitsize.  */
-        TRUE,                  /* PC_relative.  */
+        true,                  /* PC_relative.  */
         0,                     /* Bitpos.  */
         complain_overflow_dont, /* Complain on overflow.  */
         bfd_elf_generic_reloc, /* Special Function.  */
         "R_OR1K_GOTPC_HI16",   /* Name.  */
-        FALSE,         /* Partial Inplace.  */
+        false,         /* Partial Inplace.  */
         0,                     /* Source Mask.  */
         0xffff,                /* Dest Mask.  */
-        TRUE),                 /* PC relative offset?  */
+        true),                 /* PC relative offset?  */
 
    HOWTO (R_OR1K_GOTPC_LO16,   /* Type.  */
         0,                     /* Rightshift.  */
         2,                     /* Size (0 = byte, 1 = short, 2 = long).  */
         16,                    /* Bitsize.  */
-        TRUE,                  /* PC_relative.  */
+        true,                  /* PC_relative.  */
         0,                     /* Bitpos.  */
         complain_overflow_dont, /* Complain on overflow.  */
         bfd_elf_generic_reloc, /* Special Function.  */
         "R_OR1K_GOTPC_LO16",   /* Name.  */
-        FALSE,         /* Partial Inplace.  */
+        false,         /* Partial Inplace.  */
         0,                     /* Source Mask.  */
         0xffff,                /* Dest Mask.  */
-        TRUE),                 /* PC relative offset?  */
+        true),                 /* PC relative offset?  */
 
   HOWTO (R_OR1K_GOT16,         /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_GOT16",        /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* A 26 bit PLT relocation.  Shifted by 2.  */
   HOWTO (R_OR1K_PLT26,         /* Type.  */
         2,                     /* Rightshift.  */
         2,                     /* Size (0 = byte, 1 = short, 2 = long).  */
         26,                    /* Bitsize.  */
-        TRUE,                  /* pc_relative.  */
+        true,                  /* pc_relative.  */
         0,                     /* Bitpos.  */
         complain_overflow_signed, /* Complain on overflow.  */
         bfd_elf_generic_reloc, /* Special Function.  */
         "R_OR1K_PLT26",        /* Name.  */
-        FALSE,                 /* Partial Inplace.  */
+        false,                 /* Partial Inplace.  */
         0,                     /* Source Mask.  */
         0x03ffffff,            /* Dest Mask.  */
-        TRUE),                 /* PC relative offset?  */
+        true),                 /* PC relative offset?  */
 
   HOWTO (R_OR1K_GOTOFF_HI16,   /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_GOTOFF_HI16",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_GOTOFF_LO16,   /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_GOTOFF_LO16",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_COPY,          /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_COPY",         /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_GLOB_DAT,      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_GLOB_DAT",     /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_JMP_SLOT,      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_JMP_SLOT",     /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_RELATIVE,      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_RELATIVE",     /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_GD_HI16,   /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_GD_HI16",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_GD_LO16,   /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_GD_LO16",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LDM_HI16,  /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LDM_HI16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LDM_LO16,  /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LDM_LO16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LDO_HI16,  /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LDO_HI16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LDO_LO16,  /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LDO_LO16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_IE_HI16,   /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_IE_HI16",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_IE_LO16,   /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_IE_LO16",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LE_HI16,   /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LE_HI16",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LE_LO16,   /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LE_LO16",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_TPOFF,     /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_TPOFF",    /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_DTPOFF,    /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_DTPOFF",   /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_DTPMOD,    /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_DTPMOD",   /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_AHI16,         /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_AHI16",        /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_GOTOFF_AHI16,  /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_GOTOFF_AHI16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_IE_AHI16,   /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_IE_AHI16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LE_AHI16,  /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LE_AHI16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_SLO16,         /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_SLO16",        /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_GOTOFF_SLO16,  /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_GOTOFF_SLO16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LE_SLO16,   /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LE_SLO16", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* A page relative 21 bit relocation, right shifted by 13, aligned.
      Note that this is *page* relative, not pc relative.  The idea is
@@ -644,170 +648,184 @@ static reloc_howto_type or1k_elf_howto_table[] =
         13,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         21,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_PCREL_PG21",   /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0x001fffff,            /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   HOWTO (R_OR1K_GOT_PG21,       /* type */
         13,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         21,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_GOT_PG21",     /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0x001fffff,            /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_GD_PG21,    /* type */
         13,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         21,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_GD_PG21",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0x001fffff,            /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LDM_PG21,   /* type */
         13,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         21,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_LDM_PG21", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0x001fffff,            /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_IE_PG21,    /* type */
         13,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         21,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_IE_PG21",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0x001fffff,            /* dst_mask */
-        TRUE),                 /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   HOWTO (R_OR1K_LO13,          /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_LO13",         /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_GOT_LO13,       /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_GOT_LO13",     /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_GD_LO13,    /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_GD_LO13",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_LDM_LO13,   /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLD_LDM_LO13", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_TLS_IE_LO13,    /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_TLS_IE_LO13",  /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   HOWTO (R_OR1K_SLO13,         /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_OR1K_SLO13",        /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0x0,                   /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* A 26 bit PLT relocation, using ADRP.  Shifted by 2.  */
   HOWTO (R_OR1K_PLTA26,                /* Type.  */
         2,                     /* Rightshift.  */
         2,                     /* Size (0 = byte, 1 = short, 2 = long).  */
         26,                    /* Bitsize.  */
-        TRUE,                  /* pc_relative.  */
+        true,                  /* pc_relative.  */
         0,                     /* Bitpos.  */
         complain_overflow_signed, /* Complain on overflow.  */
         bfd_elf_generic_reloc, /* Special Function.  */
         "R_OR1K_PLTA26",       /* Name.  */
-        FALSE,                 /* Partial Inplace.  */
+        false,                 /* Partial Inplace.  */
         0,                     /* Source Mask.  */
         0x03ffffff,            /* Dest Mask.  */
-        TRUE),                 /* PC relative offset?  */
+        true),                 /* PC relative offset?  */
+
+  HOWTO (R_OR1K_GOT_AHI16,     /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_OR1K_GOT_AHI16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
 };
 
 /* Map BFD reloc types to Or1k ELF reloc types.  */
@@ -871,6 +889,7 @@ static const struct or1k_reloc_map or1k_reloc_map[] =
   { BFD_RELOC_OR1K_TLS_IE_LO13,        R_OR1K_TLS_IE_LO13 },
   { BFD_RELOC_OR1K_SLO13,      R_OR1K_SLO13 },
   { BFD_RELOC_OR1K_PLTA26,     R_OR1K_PLTA26 },
+  { BFD_RELOC_OR1K_GOT_AHI16,  R_OR1K_GOT_AHI16 },
 };
 
 /* tls_type is a mask used to track how each symbol is accessed,
@@ -892,9 +911,8 @@ struct elf_or1k_link_hash_entry
 {
   struct elf_link_hash_entry root;
 
-  /* Track dynamic relocs copied for this symbol.  */
-  struct elf_dyn_relocs *dyn_relocs;
-
+  /* For calculating PLT size.  */
+  bfd_vma plt_index;
   /* Track type of TLS access.  */
   unsigned char tls_type;
 };
@@ -919,18 +937,27 @@ struct elf_or1k_link_hash_table
 {
   struct elf_link_hash_table root;
 
-  /* Small local sym to section mapping cache.  */
-  struct sym_cache sym_sec;
-
-  bfd_boolean saw_plta;
+  bfd_vma plt_count;
+  bool saw_plta;
 };
 
+static size_t
+elf_or1k_plt_entry_size (bfd_vma plt_index)
+{
+  bfd_vma plt_reloc;
+
+  plt_reloc = plt_index * sizeof (Elf32_External_Rela);
+
+  return (plt_reloc > 0xffff) ? PLT_ENTRY_SIZE_LARGE : PLT_ENTRY_SIZE;
+}
+
 /* Get the ELF linker hash table from a link_info structure.  */
 #define or1k_elf_hash_table(p) \
-  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
-   == OR1K_ELF_DATA ? ((struct elf_or1k_link_hash_table *) ((p)->hash)) : NULL)
+  ((is_elf_hash_table ((p)->hash)                                      \
+    && elf_hash_table_id (elf_hash_table (p)) == OR1K_ELF_DATA)                \
+   ? (struct elf_or1k_link_hash_table *) (p)->hash : NULL)
 
-static bfd_boolean
+static bool
 elf_or1k_mkobject (bfd *abfd)
 {
   return bfd_elf_allocate_object (abfd, sizeof (struct elf_or1k_obj_tdata),
@@ -964,7 +991,6 @@ or1k_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
       struct elf_or1k_link_hash_entry *eh;
 
       eh = (struct elf_or1k_link_hash_entry *) ret;
-      eh->dyn_relocs = NULL;
       eh->tls_type = TLS_UNKNOWN;
     }
 
@@ -1030,7 +1056,7 @@ or1k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 
 /* Set the howto pointer for an Or1k ELF reloc.  */
 
-static bfd_boolean
+static bool
 or1k_info_to_howto_rela (bfd * abfd,
                         arelent * cache_ptr,
                         Elf_Internal_Rela * dst)
@@ -1044,15 +1070,15 @@ or1k_info_to_howto_rela (bfd * abfd,
       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
                          abfd, r_type);
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
   cache_ptr->howto = & or1k_elf_howto_table[r_type];
-  return TRUE;
+  return true;
 }
 
 /* Return the relocation value for @tpoff relocations..  */
 static bfd_vma
-tpoff (struct bfd_link_info *info, bfd_vma address, bfd_boolean dynamic)
+tpoff (struct bfd_link_info *info, bfd_vma address, bool dynamic)
 {
   struct elf_link_hash_table *htab = elf_hash_table (info);
   bfd_vma base;
@@ -1117,6 +1143,7 @@ or1k_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
   switch (howto->type)
     {
     case R_OR1K_AHI16:
+    case R_OR1K_GOT_AHI16:
     case R_OR1K_GOTOFF_AHI16:
     case R_OR1K_TLS_IE_AHI16:
     case R_OR1K_TLS_LE_AHI16:
@@ -1248,7 +1275,7 @@ or1k_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd,
    section, which means that the addend must be adjusted
    accordingly.  */
 
-static bfd_boolean
+static int
 or1k_elf_relocate_section (bfd *output_bfd,
                           struct bfd_link_info *info,
                           bfd *input_bfd,
@@ -1267,10 +1294,11 @@ or1k_elf_relocate_section (bfd *output_bfd,
   bfd_vma *local_got_offsets;
   asection *sgot, *splt;
   bfd_vma plt_base, got_base, got_sym_value;
-  bfd_boolean ret_val = TRUE;
+  bool ret_val = true;
+  bool saw_gotha = false;
 
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   local_got_offsets = elf_local_got_offsets (input_bfd);
 
@@ -1321,7 +1349,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
            (_("%pB: unknown relocation type %d"),
             input_bfd, (int) r_type);
          bfd_set_error (bfd_error_bad_value);
-         ret_val = FALSE;
+         ret_val = false;
          continue;
        }
 
@@ -1342,7 +1370,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
        }
       else
        {
-         bfd_boolean unresolved_reloc, warned, ignored;
+         bool unresolved_reloc, warned, ignored;
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
@@ -1375,10 +1403,11 @@ or1k_elf_relocate_section (bfd *output_bfd,
                (_("%pB: addend should be zero for plt relocations"),
                 input_bfd);
              bfd_set_error (bfd_error_bad_value);
-             ret_val = FALSE;
+             ret_val = false;
            }
          break;
 
+       case R_OR1K_GOT_AHI16:
        case R_OR1K_GOT16:
        case R_OR1K_GOT_PG21:
        case R_OR1K_GOT_LO13:
@@ -1390,7 +1419,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
          BFD_ASSERT (sgot != NULL);
          if (h != NULL)
            {
-             bfd_boolean dyn;
+             bool dyn;
 
              off = h->got.offset;
              BFD_ASSERT (off != (bfd_vma) -1);
@@ -1470,9 +1499,20 @@ or1k_elf_relocate_section (bfd *output_bfd,
            /* The GOT_PG21 and GOT_LO13 relocs are pc-relative,
               while the GOT16 reloc is GOT relative.  */
            relocation = got_base + off;
-           if (r_type == R_OR1K_GOT16)
+           if (r_type == R_OR1K_GOT16
+               || r_type == R_OR1K_GOT_AHI16)
              relocation -= got_sym_value;
 
+           if (r_type == R_OR1K_GOT_AHI16)
+             saw_gotha = true;
+
+           /* If we have a R_OR1K_GOT16 followed by a R_OR1K_GOT_AHI16
+              relocation we assume the code is doing the right thing to avoid
+              overflows.  Here we mask the lower 16-bit of the relocation to
+              avoid overflow validation failures.  */
+           if (r_type == R_OR1K_GOT16 && saw_gotha)
+             relocation &= 0xffff;
+
          /* Addend should be zero.  */
          if (rel->r_addend != 0)
            {
@@ -1480,7 +1520,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
                (_("%pB: addend should be zero for got relocations"),
                 input_bfd);
              bfd_set_error (bfd_error_bad_value);
-             ret_val = FALSE;
+             ret_val = false;
            }
          }
          break;
@@ -1496,7 +1536,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
              _bfd_error_handler
                (_("%pB: gotoff relocation against dynamic symbol %s"),
                 input_bfd, h->root.root.string);
-             ret_val = FALSE;
+             ret_val = false;
              bfd_set_error (bfd_error_bad_value);
            }
          relocation -= got_sym_value;
@@ -1513,7 +1553,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
              _bfd_error_handler
                (_("%pB: pc-relative relocation against dynamic symbol %s"),
                 input_bfd, name);
-             ret_val = FALSE;
+             ret_val = false;
              bfd_set_error (bfd_error_bad_value);
            }
          break;
@@ -1527,7 +1567,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
              _bfd_error_handler
                (_("%pB: non-pic relocation against symbol %s"),
                 input_bfd, name);
-             ret_val = FALSE;
+             ret_val = false;
              bfd_set_error (bfd_error_bad_value);
            }
          break;
@@ -1558,7 +1598,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
              {
                Elf_Internal_Rela outrel;
                bfd_byte *loc;
-               bfd_boolean skip;
+               bool skip;
 
                /* When generating a shared object, these relocations
                   are copied into the output file to be resolved at run
@@ -1566,15 +1606,15 @@ or1k_elf_relocate_section (bfd *output_bfd,
 
                BFD_ASSERT (sreloc != NULL);
 
-               skip = FALSE;
+               skip = 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;
+                 skip = true;
                else if (outrel.r_offset == (bfd_vma) -2)
-                 skip = TRUE;
+                 skip = true;
                outrel.r_offset += (input_section->output_section->vma
                                    + input_section->output_offset);
 
@@ -1612,7 +1652,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
            (_("%pB: support for local dynamic not implemented"),
             input_bfd);
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
 
        case R_OR1K_TLS_GD_HI16:
        case R_OR1K_TLS_GD_LO16:
@@ -1628,7 +1668,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
            Elf_Internal_Rela rela;
            asection *srelgot;
            bfd_byte *loc;
-           bfd_boolean dynamic;
+           bool dynamic;
            int indx = 0;
            unsigned char tls_type;
 
@@ -1674,8 +1714,8 @@ or1k_elf_relocate_section (bfd *output_bfd,
 
            if (h != NULL)
              {
-               bfd_boolean dyn = htab->root.dynamic_sections_created;
-               bfd_boolean pic = bfd_link_pic (info);
+               bool dyn = htab->root.dynamic_sections_created;
+               bool pic = bfd_link_pic (info);
 
                if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, pic, h)
                    && (!pic || !SYMBOL_REFERENCES_LOCAL (info, h)))
@@ -1791,7 +1831,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
            (_("%pB: will not resolve runtime TLS relocation"),
             input_bfd);
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
 
        default:
          break;
@@ -1814,7 +1854,7 @@ or1k_elf_relocate_section (bfd *output_bfd,
 
            case bfd_reloc_undefined:
              (*info->callbacks->undefined_symbol)
-               (info, name, input_bfd, input_section, rel->r_offset, TRUE);
+               (info, name, input_bfd, input_section, rel->r_offset, true);
              break;
 
            case bfd_reloc_outofrange:
@@ -1866,7 +1906,7 @@ or1k_elf_gc_mark_hook (asection *sec,
 
 /* Look through the relocs for a section during the first phase.  */
 
-static bfd_boolean
+static bool
 or1k_elf_check_relocs (bfd *abfd,
                       struct bfd_link_info *info,
                       asection *sec,
@@ -1882,23 +1922,14 @@ or1k_elf_check_relocs (bfd *abfd,
   asection *sreloc = NULL;
 
   if (bfd_link_relocatable (info))
-    return TRUE;
-
-  /* Don't do anything special with non-loaded, non-alloced sections.
-     In particular, any relocs in such sections should not affect GOT
-     and PLT reference counting (ie. we don't allow them to create GOT
-     or PLT entries), there's no possibility or desire to optimize TLS
-     relocs, and there's not much point in propagating relocs to shared
-     libs that the dynamic linker won't relocate.  */
-  if ((sec->flags & SEC_ALLOC) == 0)
-    return TRUE;
+    return true;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
 
   htab = or1k_elf_hash_table (info);
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   dynobj = htab->root.dynobj;
 
@@ -1971,7 +2002,7 @@ or1k_elf_check_relocs (bfd *abfd,
              size = symtab_hdr->sh_info;
              local_tls_type = bfd_zalloc (abfd, size);
              if (local_tls_type == NULL)
-               return FALSE;
+               return false;
              elf_or1k_local_tls_type (abfd) = local_tls_type;
            }
          local_tls_type[r_symndx] |= tls_type;
@@ -1983,19 +2014,19 @@ or1k_elf_check_relocs (bfd *abfd,
             Reconstruct it for later use during GC.  */
        case R_OR1K_GNU_VTINHERIT:
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-           return FALSE;
+           return false;
          break;
 
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_OR1K_GNU_VTENTRY:
          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-           return FALSE;
+           return false;
          break;
 
          /* This relocation requires .plt entry.  */
        case R_OR1K_PLTA26:
-         htab->saw_plta = TRUE;
+         htab->saw_plta = true;
          /* FALLTHRU */
        case R_OR1K_PLT26:
          if (h != NULL)
@@ -2005,6 +2036,7 @@ or1k_elf_check_relocs (bfd *abfd,
            }
          break;
 
+       case R_OR1K_GOT_AHI16:
        case R_OR1K_GOT16:
        case R_OR1K_GOT_PG21:
        case R_OR1K_GOT_LO13:
@@ -2033,7 +2065,7 @@ or1k_elf_check_relocs (bfd *abfd,
                      size *= sizeof (bfd_signed_vma);
                      local_got_refcounts = bfd_zalloc (abfd, size);
                      if (local_got_refcounts == NULL)
-                       return FALSE;
+                       return false;
                      elf_local_got_refcounts (abfd) = local_got_refcounts;
                    }
                  local_got_refcounts[r_symndx] += 1;
@@ -2049,7 +2081,7 @@ or1k_elf_check_relocs (bfd *abfd,
              if (dynobj == NULL)
                htab->root.dynobj = dynobj = abfd;
              if (!_bfd_elf_create_got_section (dynobj, info))
-               return FALSE;
+               return false;
            }
          break;
 
@@ -2123,9 +2155,9 @@ or1k_elf_check_relocs (bfd *abfd,
 
                    name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
                    if (name == NULL)
-                     return FALSE;
+                     return false;
 
-                   if (strncmp (name, ".rela", 5) != 0
+                   if (!startswith (name, ".rela")
                        || strcmp (bfd_section_name (sec), name + 5) != 0)
                      {
                        _bfd_error_handler
@@ -2142,10 +2174,10 @@ or1k_elf_check_relocs (bfd *abfd,
                    if (sreloc == NULL)
                      {
                        sreloc = _bfd_elf_make_dynamic_reloc_section
-                         (sec, dynobj, 2, abfd, /*rela?*/ TRUE);
+                         (sec, dynobj, 2, abfd, /*rela?*/ true);
 
                        if (sreloc == NULL)
-                         return FALSE;
+                         return false;
                      }
                    elf_section_data (sec)->sreloc = sreloc;
                  }
@@ -2153,7 +2185,7 @@ or1k_elf_check_relocs (bfd *abfd,
                /* If this is a global symbol, we count the number of
                   relocations we need for this symbol.  */
                if (h != NULL)
-                 head = &((struct elf_or1k_link_hash_entry *) h)->dyn_relocs;
+                 head = &h->dyn_relocs;
                else
                  {
                    /* Track dynamic relocs needed for local syms too.
@@ -2164,14 +2196,14 @@ or1k_elf_check_relocs (bfd *abfd,
                    Elf_Internal_Sym *isym;
                    void *vpp;
 
-                   isym = bfd_sym_from_r_symndx (&htab->sym_sec,
+                   isym = bfd_sym_from_r_symndx (&htab->root.sym_cache,
                                                  abfd, r_symndx);
                    if (isym == NULL)
-                     return FALSE;
+                     return false;
 
                    s = bfd_section_from_elf_index (abfd, isym->st_shndx);
                    if (s == NULL)
-                     return FALSE;
+                     return false;
 
                    vpp = &elf_section_data (s)->local_dynrel;
                    head = (struct elf_dyn_relocs **) vpp;
@@ -2186,7 +2218,7 @@ or1k_elf_check_relocs (bfd *abfd,
                    sec_relocs = ((struct elf_dyn_relocs *)
                                  bfd_alloc (htab->root.dynobj, amt));
                    if (sec_relocs == NULL)
-                     return FALSE;
+                     return false;
                    sec_relocs->next = *head;
                    *head = sec_relocs;
                    sec_relocs->sec = sec;
@@ -2203,42 +2235,55 @@ or1k_elf_check_relocs (bfd *abfd,
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 static void
-or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insn1,
-                     unsigned insn2, unsigned insn3, unsigned insnj)
+or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insnj,
+                     unsigned insns[], size_t insn_count)
 {
   unsigned nodelay = elf_elfheader (output_bfd)->e_flags & EF_OR1K_NODELAY;
-  unsigned insn4;
+  unsigned output_insns[PLT_MAX_INSN_COUNT];
+
+  /* Copy instructions into the output buffer.  */
+  for (size_t i = 0; i < insn_count; i++)
+    output_insns[i] = insns[i];
 
   /* Honor the no-delay-slot setting.  */
-  if (insn3 == OR1K_NOP)
+  if (insns[insn_count-1] == OR1K_NOP)
     {
-      insn4 = insn3;
+      unsigned slot1, slot2;
+
       if (nodelay)
-       insn3 = insnj;
+       slot1 = insns[insn_count-2], slot2 = insnj;
       else
-       insn3 = insn2, insn2 = insnj;
+       slot1 = insnj, slot2 = insns[insn_count-2];
+
+      output_insns[insn_count-2] = slot1;
+      output_insns[insn_count-1] = slot2;
+      output_insns[insn_count]   = OR1K_NOP;
     }
   else
     {
+      unsigned slot1, slot2;
+
       if (nodelay)
-       insn4 = insnj;
+       slot1 = insns[insn_count-1], slot2 = insnj;
       else
-       insn4 = insn3, insn3 = insnj;
+       slot1 = insnj, slot2 = insns[insn_count-1];
+
+      output_insns[insn_count-1] = slot1;
+      output_insns[insn_count]   = slot2;
     }
 
-  bfd_put_32 (output_bfd, insn1, contents);
-  bfd_put_32 (output_bfd, insn2, contents + 4);
-  bfd_put_32 (output_bfd, insn3, contents + 8);
-  bfd_put_32 (output_bfd, insn4, contents + 12);
+  /* Write out the output buffer.  */
+  for (size_t i = 0; i < (insn_count+1); i++)
+    bfd_put_32 (output_bfd, output_insns[i], contents + (i*4));
 }
 
 /* Finish up the dynamic sections.  */
 
-static bfd_boolean
+static bool
 or1k_elf_finish_dynamic_sections (bfd *output_bfd,
                                  struct bfd_link_info *info)
 {
@@ -2248,7 +2293,7 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd,
 
   htab = or1k_elf_hash_table (info);
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   dynobj = htab->root.dynobj;
 
@@ -2300,7 +2345,8 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd,
       splt = htab->root.splt;
       if (splt && splt->size > 0)
        {
-         unsigned plt0, plt1, plt2;
+         unsigned plt[PLT_MAX_INSN_COUNT];
+         size_t plt_insn_count = 3;
          bfd_vma got_addr = sgot->output_section->vma + sgot->output_offset;
 
          /* Note we force 16 byte alignment on the .got, so that
@@ -2311,27 +2357,27 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd,
              bfd_vma pc = splt->output_section->vma + splt->output_offset;
              unsigned pa = ((got_addr >> 13) - (pc >> 13)) & 0x1fffff;
              unsigned po = got_addr & 0x1fff;
-             plt0 = OR1K_ADRP(12) | pa;
-             plt1 = OR1K_LWZ(15,12) | (po + 8);
-             plt2 = OR1K_LWZ(12,12) | (po + 4);
+             plt[0] = OR1K_ADRP(12) | pa;
+             plt[1] = OR1K_LWZ(15,12) | (po + 8);
+             plt[2] = OR1K_LWZ(12,12) | (po + 4);
            }
          else if (bfd_link_pic (info))
            {
-             plt0 = OR1K_LWZ(15, 16) | 8;      /* .got+8 */
-             plt1 = OR1K_LWZ(12, 16) | 4;      /* .got+4 */
-             plt2 = OR1K_NOP;
+             plt[0] = OR1K_LWZ(15, 16) | 8;    /* .got+8 */
+             plt[1] = OR1K_LWZ(12, 16) | 4;    /* .got+4 */
+             plt[2] = OR1K_NOP;
            }
          else
            {
              unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff;
              unsigned lo = got_addr & 0xffff;
-             plt0 = OR1K_MOVHI(12) | ha;
-             plt1 = OR1K_LWZ(15,12) | (lo + 8);
-             plt2 = OR1K_LWZ(12,12) | (lo + 4);
+             plt[0] = OR1K_MOVHI(12) | ha;
+             plt[1] = OR1K_LWZ(15,12) | (lo + 8);
+             plt[2] = OR1K_LWZ(12,12) | (lo + 4);
            }
 
-         or1k_write_plt_entry (output_bfd, splt->contents,
-                               plt0, plt1, plt2, OR1K_JR(15));
+         or1k_write_plt_entry (output_bfd, splt->contents, OR1K_JR(15),
+                               plt, plt_insn_count);
 
          elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
        }
@@ -2353,13 +2399,13 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd,
   if (htab->root.sgot && htab->root.sgot->size > 0)
     elf_section_data (htab->root.sgot->output_section)->this_hdr.sh_entsize = 4;
 
-  return TRUE;
+  return true;
 }
 
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
-static bfd_boolean
+static bool
 or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
                                struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
@@ -2370,11 +2416,12 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
 
   htab = or1k_elf_hash_table (info);
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   if (h->plt.offset != (bfd_vma) -1)
     {
-      unsigned int plt0, plt1, plt2;
+      unsigned int plt[PLT_MAX_INSN_COUNT];
+      size_t plt_insn_count = 3;
       asection *splt;
       asection *sgot;
       asection *srela;
@@ -2386,6 +2433,7 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
       bfd_vma got_offset;
       bfd_vma got_addr;
       Elf_Internal_Rela rela;
+      bool large_plt_entry;
 
       /* This symbol has an entry in the procedure linkage table.  Set
         it up.  */
@@ -2403,10 +2451,13 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
         corresponds to this symbol.  This is the index of this symbol
         in all the symbols for which we are making plt entries.  The
         first entry in the procedure linkage table is reserved.  */
-      plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
+      plt_index = ((struct elf_or1k_link_hash_entry *) h)->plt_index;
       plt_addr = plt_base_addr + h->plt.offset;
       plt_reloc = plt_index * sizeof (Elf32_External_Rela);
 
+      large_plt_entry = (elf_or1k_plt_entry_size (plt_index)
+                        == PLT_ENTRY_SIZE_LARGE);
+
       /* Get the offset into the .got table of the entry that
        corresponds to this function.  Each .got entry is 4 bytes.
        The first three are reserved.  */
@@ -2418,27 +2469,57 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
        {
          unsigned pa = ((got_addr >> 13) - (plt_addr >> 13)) & 0x1fffff;
          unsigned po = (got_addr & 0x1fff);
-         plt0 = OR1K_ADRP(12) | pa;
-         plt1 = OR1K_LWZ(12,12) | po;
-         plt2 = OR1K_ORI0(11) | plt_reloc;
+         plt[0] = OR1K_ADRP(12) | pa;
+         plt[1] = OR1K_LWZ(12,12) | po;
+         plt[2] = OR1K_ORI0(11) | plt_reloc;
        }
       else if (bfd_link_pic (info))
        {
-         plt0 = OR1K_LWZ(12,16) | got_offset;
-         plt1 = OR1K_ORI0(11) | plt_reloc;
-         plt2 = OR1K_NOP;
+         if (large_plt_entry)
+           {
+             unsigned gotha = ((got_offset + 0x8000) >> 16) & 0xffff;
+             unsigned got = got_offset & 0xffff;
+             unsigned pltrelhi = (plt_reloc >> 16) & 0xffff;
+             unsigned pltrello = plt_reloc & 0xffff;
+
+             plt[0] = OR1K_MOVHI(12) | gotha;
+             plt[1] = OR1K_ADD(12,12,16);
+             plt[2] = OR1K_LWZ(12,12) | got;
+             plt[3] = OR1K_MOVHI(11) | pltrelhi;
+             plt[4] = OR1K_ORI(11,11) | pltrello;
+             plt_insn_count = 5;
+           }
+         else
+           {
+             plt[0] = OR1K_LWZ(12,16) | got_offset;
+             plt[1] = OR1K_ORI0(11) | plt_reloc;
+             plt[2] = OR1K_NOP;
+           }
        }
       else
        {
          unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff;
          unsigned lo = got_addr & 0xffff;
-         plt0 = OR1K_MOVHI(12) | ha;
-         plt1 = OR1K_LWZ(12,12) | lo;
-         plt2 = OR1K_ORI0(11) | plt_reloc;
+         plt[0] = OR1K_MOVHI(12) | ha;
+         plt[1] = OR1K_LWZ(12,12) | lo;
+         plt[2] = OR1K_ORI0(11) | plt_reloc;
+       }
+
+      /* For large code model we fixup the non-PIC PLT relocation instructions
+        here.  */
+      if (large_plt_entry && !bfd_link_pic (info))
+       {
+         unsigned pltrelhi = (plt_reloc >> 16) & 0xffff;
+         unsigned pltrello = plt_reloc & 0xffff;
+
+         plt[2] = OR1K_MOVHI(11) | pltrelhi;
+         plt[3] = OR1K_ORI(11,11) | pltrello;
+         plt[4] = OR1K_NOP;
+         plt_insn_count = 5;
        }
 
       or1k_write_plt_entry (output_bfd, splt->contents + h->plt.offset,
-                           plt0, plt1, plt2, OR1K_JR(12));
+                           OR1K_JR(12), plt, plt_insn_count);
 
       /* Fill in the entry in the global offset table.  We initialize it to
         point to the top of the plt.  This is done to lazy lookup the actual
@@ -2534,7 +2615,7 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
       || h == htab->root.hgot)
     sym->st_shndx = SHN_ABS;
 
-  return TRUE;
+  return true;
 }
 
 static enum elf_reloc_type_class
@@ -2551,33 +2632,13 @@ or1k_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
     }
 }
 
-/* Find dynamic relocs for H that apply to read-only sections.  */
-
-static asection *
-readonly_dynrelocs (struct elf_link_hash_entry *h)
-{
-  struct elf_dyn_relocs *sec_relocs;
-  struct elf_or1k_link_hash_entry *eh = (struct elf_or1k_link_hash_entry *) h;
-
-  for (sec_relocs = eh->dyn_relocs;
-       sec_relocs != NULL;
-       sec_relocs = sec_relocs->next)
-    {
-      asection *s = sec_relocs->sec->output_section;
-
-      if (s != NULL && (s->flags & SEC_READONLY) != 0)
-       return sec_relocs->sec;
-    }
-  return NULL;
-}
-
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
    change the definition to something the rest of the link can
    understand.  */
 
-static bfd_boolean
+static bool
 or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *h)
 {
@@ -2601,11 +2662,10 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   if (h->type == STT_FUNC
       || h->needs_plt)
     {
-      if (! bfd_link_pic (info)
-         && !h->def_dynamic
-         && !h->ref_dynamic
-         && h->root.type != bfd_link_hash_undefweak
-         && h->root.type != bfd_link_hash_undefined)
+      if (h->plt.refcount <= 0
+         || (SYMBOL_CALLS_LOCAL (info, h)
+         || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+             && h->root.type == bfd_link_hash_undefweak)))
        {
          /* This case can occur if we saw a PLT reloc in an input
             file, but the symbol was never referred to by a dynamic
@@ -2616,7 +2676,7 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
          h->needs_plt = 0;
        }
 
-      return TRUE;
+      return true;
     }
   else
     h->plt.offset = (bfd_vma) -1;
@@ -2630,7 +2690,7 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       BFD_ASSERT (def->root.type == bfd_link_hash_defined);
       h->root.u.def.section = def->root.u.def.section;
       h->root.u.def.value = def->root.u.def.value;
-      return TRUE;
+      return true;
     }
 
   /* This is a reference to a symbol defined by a dynamic object which
@@ -2641,26 +2701,26 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      For such cases we need not do anything here; the relocations will
      be handled correctly by relocate_section.  */
   if (bfd_link_pic (info))
-    return TRUE;
+    return true;
 
   /* If there are no references to this symbol that do not use the
      GOT, we don't need to generate a copy reloc.  */
   if (!h->non_got_ref)
-    return TRUE;
+    return true;
 
   /* If -z nocopyreloc was given, we won't generate them either.  */
   if (info->nocopyreloc)
     {
       h->non_got_ref = 0;
-      return TRUE;
+      return true;
     }
 
   /* If we don't find any dynamic relocs in read-only sections, then
      we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
-  if (!readonly_dynrelocs (h))
+  if (!_bfd_elf_readonly_dynrelocs (h))
     {
       h->non_got_ref = 0;
-      return TRUE;
+      return true;
     }
 
   /* We must allocate the symbol in our .dynbss section, which will
@@ -2675,7 +2735,7 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   htab = or1k_elf_hash_table (info);
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   /* We must generate a R_OR1K_COPY reloc to tell the dynamic linker
      to copy the initial value out of the dynamic object and into the
@@ -2714,26 +2774,26 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
 static void
 or1k_set_got_and_rela_sizes (const unsigned char tls_type,
-                            const bfd_boolean dynamic,
+                            const bool dynamic,
                             bfd_vma *got_size,
                             bfd_vma *rela_size)
 {
-  bfd_boolean is_tls_entry = FALSE;
+  bool is_tls_entry = false;
 
   /* TLS GD requires two GOT entries and two relocs.  */
   if ((tls_type & TLS_GD) != 0)
     {
       *got_size += 8;
-      is_tls_entry = TRUE;
+      is_tls_entry = true;
     }
 
   if ((tls_type & TLS_IE) != 0)
     {
       *got_size += 4;
-      is_tls_entry = TRUE;
+      is_tls_entry = true;
     }
 
-  if (is_tls_entry == FALSE)
+  if (!is_tls_entry)
     *got_size += 4;
 
   if (dynamic)
@@ -2744,7 +2804,7 @@ or1k_set_got_and_rela_sizes (const unsigned char tls_type,
       if ((tls_type & TLS_IE) != 0)
        *rela_size += sizeof (Elf32_External_Rela);
 
-      if (is_tls_entry == FALSE)
+      if (!is_tls_entry)
        *rela_size += sizeof (Elf32_External_Rela);
     }
 }
@@ -2753,23 +2813,20 @@ or1k_set_got_and_rela_sizes (const unsigned char tls_type,
 /* Allocate space in .plt, .got and associated reloc sections for
    dynamic relocs.  */
 
-static bfd_boolean
+static bool
 allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 {
   struct bfd_link_info *info;
   struct elf_or1k_link_hash_table *htab;
-  struct elf_or1k_link_hash_entry *eh;
   struct elf_dyn_relocs *sec_relocs;
 
   if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
+    return true;
 
   info = (struct bfd_link_info *) inf;
   htab = or1k_elf_hash_table (info);
   if (htab == NULL)
-    return FALSE;
-
-  eh = (struct elf_or1k_link_hash_entry *) h;
+    return false;
 
   if (htab->root.dynamic_sections_created
       && h->plt.refcount > 0)
@@ -2780,17 +2837,22 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
          && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
+           return false;
        }
 
       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
        {
          asection *splt = htab->root.splt;
+         bfd_vma plt_index;
+
+         /* Track the index of our plt entry for use in calculating size.  */
+         plt_index = htab->plt_count++;
+         ((struct elf_or1k_link_hash_entry *) h)->plt_index = plt_index;
 
          /* If this is the first .plt entry, make room for the special
             first entry.  */
          if (splt->size == 0)
-           splt->size = PLT_ENTRY_SIZE;
+           splt->size = elf_or1k_plt_entry_size (plt_index);
 
          h->plt.offset = splt->size;
 
@@ -2807,7 +2869,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
            }
 
          /* Make room for this entry.  */
-         splt->size += PLT_ENTRY_SIZE;
+         splt->size += elf_or1k_plt_entry_size (plt_index);
 
          /* We also need to make an entry in the .got.plt section, which
             will be placed in the .got section by the linker script.  */
@@ -2831,7 +2893,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   if (h->got.refcount > 0)
     {
       asection *sgot;
-      bfd_boolean dyn;
+      bool dyn;
       unsigned char tls_type;
 
       /* Make sure this symbol is output as a dynamic symbol.
@@ -2840,7 +2902,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
          && !h->forced_local)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
+           return false;
        }
 
       sgot = htab->root.sgot;
@@ -2857,8 +2919,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   else
     h->got.offset = (bfd_vma) -1;
 
-  if (eh->dyn_relocs == NULL)
-    return TRUE;
+  if (h->dyn_relocs == NULL)
+    return true;
 
   /* In the shared -Bsymbolic case, discard space allocated for
      dynamic pc-relative relocs against symbols which turn out to be
@@ -2872,7 +2934,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
        {
          struct elf_dyn_relocs **pp;
 
-         for (pp = &eh->dyn_relocs; (sec_relocs = *pp) != NULL;)
+         for (pp = &h->dyn_relocs; (sec_relocs = *pp) != NULL;)
            {
              sec_relocs->count -= sec_relocs->pc_count;
              sec_relocs->pc_count = 0;
@@ -2885,11 +2947,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
-      if (eh->dyn_relocs != NULL
+      if (h->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
        {
          if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-           eh->dyn_relocs = NULL;
+           h->dyn_relocs = NULL;
 
          /* Make sure undefined weak symbols are output as a dynamic
             symbol in PIEs.  */
@@ -2897,7 +2959,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
                   && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+               return false;
            }
        }
     }
@@ -2920,7 +2982,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
              && !h->forced_local)
            {
              if (! bfd_elf_link_record_dynamic_symbol (info, h))
-               return FALSE;
+               return false;
            }
 
          /* If that succeeded, we know we'll be keeping all the
@@ -2929,13 +2991,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
            goto keep;
        }
 
-      eh->dyn_relocs = NULL;
+      h->dyn_relocs = NULL;
 
     keep: ;
     }
 
   /* Finally, allocate space.  */
-  for (sec_relocs = eh->dyn_relocs;
+  for (sec_relocs = h->dyn_relocs;
        sec_relocs != NULL;
        sec_relocs = sec_relocs->next)
     {
@@ -2943,51 +3005,24 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       sreloc->size += sec_relocs->count * sizeof (Elf32_External_Rela);
     }
 
-  return TRUE;
-}
-
-/* Set DF_TEXTREL if we find any dynamic relocs that apply to
-   read-only sections.  */
-
-static bfd_boolean
-maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
-{
-  asection *sec;
-
-  if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
-
-  sec = readonly_dynrelocs (h);
-  if (sec != NULL)
-    {
-      struct bfd_link_info *info = (struct bfd_link_info *) info_p;
-
-      info->flags |= DF_TEXTREL;
-      info->callbacks->minfo
-       (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"),
-        sec->owner, h->root.root.string, sec);
-
-      /* Not an error, just cut short the traversal.  */
-      return FALSE;
-    }
-  return TRUE;
+  return true;
 }
 
 /* Set the sizes of the dynamic sections.  */
 
-static bfd_boolean
+static bool
 or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                                struct bfd_link_info *info)
 {
   struct elf_or1k_link_hash_table *htab;
   bfd *dynobj;
   asection *s;
-  bfd_boolean relocs;
+  bool relocs;
   bfd *ibfd;
 
   htab = or1k_elf_hash_table (info);
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   dynobj = htab->root.dynobj;
   BFD_ASSERT (dynobj != NULL);
@@ -3084,7 +3119,7 @@ or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
-  relocs = FALSE;
+  relocs = false;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LINKER_CREATED) == 0)
@@ -3099,10 +3134,10 @@ or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
-      else if (CONST_STRNEQ (bfd_section_name (s), ".rela"))
+      else if (startswith (bfd_section_name (s), ".rela"))
        {
          if (s->size != 0 && s != htab->root.srelplt)
-           relocs = TRUE;
+           relocs = true;
 
          /* We use the reloc_count field as a counter if we need
             to copy relocs into the output file.  */
@@ -3138,57 +3173,10 @@ or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       s->contents = bfd_zalloc (dynobj, s->size);
 
       if (s->contents == NULL)
-       return FALSE;
+       return false;
     }
 
-  if (htab->root.dynamic_sections_created)
-    {
-      /* Add some entries to the .dynamic section.  We fill in the
-        values later, in or1k_elf_finish_dynamic_sections, but we
-        must add the entries now so that we get the correct size for
-        the .dynamic section.  The DT_DEBUG entry is filled in by the
-        dynamic linker and used by the debugger.  */
-#define add_dynamic_entry(TAG, VAL) \
-  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
-
-     if (bfd_link_executable (info))
-       {
-        if (! add_dynamic_entry (DT_DEBUG, 0))
-          return FALSE;
-       }
-
-     if (htab->root.splt->size != 0)
-       {
-        if (! add_dynamic_entry (DT_PLTGOT, 0)
-            || ! add_dynamic_entry (DT_PLTRELSZ, 0)
-            || ! add_dynamic_entry (DT_PLTREL, DT_RELA)
-            || ! add_dynamic_entry (DT_JMPREL, 0))
-          return FALSE;
-       }
-
-     if (relocs)
-       {
-        if (! add_dynamic_entry (DT_RELA, 0)
-            || ! add_dynamic_entry (DT_RELASZ, 0)
-            || ! add_dynamic_entry (DT_RELAENT,
-                                    sizeof (Elf32_External_Rela)))
-          return FALSE;
-
-        /* If any dynamic relocs apply to a read-only section,
-           then we need a DT_TEXTREL entry.  */
-        if ((info->flags & DF_TEXTREL) == 0)
-          elf_link_hash_traverse (&htab->root, maybe_set_textrel, info);
-
-        if ((info->flags & DF_TEXTREL) != 0)
-          {
-            if (! add_dynamic_entry (DT_TEXTREL, 0))
-              return FALSE;
-          }
-       }
-    }
-
-#undef add_dynamic_entry
-  return TRUE;
+  return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs);
 }
 
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
@@ -3204,37 +3192,6 @@ or1k_elf_copy_indirect_symbol (struct bfd_link_info *info,
   edir = (struct elf_or1k_link_hash_entry *) dir;
   eind = (struct elf_or1k_link_hash_entry *) ind;
 
-  if (eind->dyn_relocs != NULL)
-    {
-      if (edir->dyn_relocs != NULL)
-       {
-         struct elf_dyn_relocs **pp;
-         struct elf_dyn_relocs *p;
-
-         /* Add reloc counts against the indirect sym to the direct sym
-            list.  Merge any entries against the same section.  */
-         for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
-           {
-             struct elf_dyn_relocs *q;
-
-             for (q = edir->dyn_relocs; q != NULL; q = q->next)
-               if (q->sec == p->sec)
-                 {
-                   q->pc_count += p->pc_count;
-                   q->count += p->count;
-                   *pp = p->next;
-                   break;
-                 }
-             if (q == NULL)
-               pp = &p->next;
-           }
-         *pp = edir->dyn_relocs;
-       }
-
-      edir->dyn_relocs = eind->dyn_relocs;
-      eind->dyn_relocs = NULL;
-    }
-
   if (ind->root.type == bfd_link_hash_indirect)
     {
       if (dir->got.refcount <= 0)
@@ -3249,7 +3206,7 @@ or1k_elf_copy_indirect_symbol (struct bfd_link_info *info,
 
 /* Set the right machine number.  */
 
-static bfd_boolean
+static bool
 or1k_elf_object_p (bfd *abfd)
 {
   unsigned long mach = bfd_mach_or1k;
@@ -3262,7 +3219,7 @@ or1k_elf_object_p (bfd *abfd)
 
 /* Store the machine number in the flags field.  */
 
-static bfd_boolean
+static bool
 or1k_elf_final_write_processing (bfd *abfd)
 {
   switch (bfd_get_mach (abfd))
@@ -3277,21 +3234,21 @@ or1k_elf_final_write_processing (bfd *abfd)
   return _bfd_elf_final_write_processing (abfd);
 }
 
-static bfd_boolean
+static bool
 or1k_elf_set_private_flags (bfd *abfd, flagword flags)
 {
   BFD_ASSERT (!elf_flags_init (abfd)
              || elf_elfheader (abfd)->e_flags == flags);
 
   elf_elfheader (abfd)->e_flags = flags;
-  elf_flags_init (abfd) = TRUE;
-  return TRUE;
+  elf_flags_init (abfd) = true;
+  return true;
 }
 
 /* Make sure all input files are consistent with respect to
    EF_OR1K_NODELAY flag setting.  */
 
-static bfd_boolean
+static bool
 elf32_or1k_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 {
   bfd *obfd = info->output_bfd;
@@ -3303,18 +3260,18 @@ elf32_or1k_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return TRUE;
+    return true;
 
   if (!elf_flags_init (obfd))
     {
-      elf_flags_init (obfd) = TRUE;
+      elf_flags_init (obfd) = true;
       elf_elfheader (obfd)->e_flags = in_flags;
 
-      return TRUE;
+      return true;
     }
 
   if (in_flags == out_flags)
-    return TRUE;
+    return true;
 
   if ((in_flags & EF_OR1K_NODELAY) != (out_flags & EF_OR1K_NODELAY))
     {
@@ -3323,16 +3280,16 @@ elf32_or1k_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
         ibfd, "EF_OR1K_NODELAY");
 
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
 
-  return TRUE;
+  return true;
 
 }
 
 /* Implement elf_backend_grok_prstatus:
    Support for core dump NOTE sections.  */
-static bfd_boolean
+static bool
 or1k_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   int offset;
@@ -3341,7 +3298,7 @@ or1k_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
   switch (note->descsz)
     {
     default:
-      return FALSE;
+      return false;
 
     case 212:        /* Linux/OpenRISC */
       /* pr_cursig */
@@ -3363,13 +3320,13 @@ or1k_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 }
 
 /* Implement elf_backend_grok_psinfo.  */
-static bfd_boolean
+static bool
 or1k_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 {
   switch (note->descsz)
     {
     default:
-      return FALSE;
+      return false;
 
     case 128:        /* Linux/OpenRISC elf_prpsinfo */
       elf_tdata (abfd)->core->program
@@ -3378,7 +3335,7 @@ or1k_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
        = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
     }
 
-  return TRUE;
+  return true;
 }
 
 
This page took 0.080576 seconds and 4 git commands to generate.