/* 32-bit ELF support for Nios II.
- Copyright (C) 2012, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2015 Free Software Foundation, Inc.
Contributed by Nigel Gray (ngray@altera.com).
Contributed by Mentor Graphics, Inc.
(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 */
0x003fffc0,
FALSE),
- HOWTO (R_NIOS2_TLS_LDO16,
+ 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,
+ 0xffff0000,
+ 0xffff0000,
+ FALSE),
+
+ HOWTO (R_NIOS2_TLS_LDM16,
+ 0,
+ 2,
+ 16,
+ FALSE,
+ 16,
+ complain_overflow_bitfield,
+ bfd_elf_generic_reloc,
+ "R_NIOS2_TLS_LDM16",
+ FALSE,
+ 0xffff0000,
+ 0xffff0000,
+ FALSE),
+
+ HOWTO (R_NIOS2_TLS_LDO16,
+ 0,
+ 2,
+ 16,
+ FALSE,
+ 16,
+ complain_overflow_bitfield,
+ bfd_elf_generic_reloc,
+ "R_NIOS2_TLS_LDO16",
+ FALSE,
+ 0xffff0000,
+ 0xffff0000,
+ FALSE),
+
+ HOWTO (R_NIOS2_TLS_IE16,
+ 0,
+ 2,
+ 16,
+ FALSE,
+ 16,
+ complain_overflow_bitfield,
+ bfd_elf_generic_reloc,
+ "R_NIOS2_TLS_IE16",
+ FALSE,
+ 0xffff0000,
+ 0xffff0000,
+ FALSE),
+
+ HOWTO (R_NIOS2_TLS_LE16,
+ 0,
+ 2,
+ 16,
+ FALSE,
+ 16,
+ complain_overflow_bitfield,
+ bfd_elf_generic_reloc,
+ "R_NIOS2_TLS_LE16",
+ FALSE,
+ 0xffff0000,
+ 0xffff0000,
+ 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,
+ 16,
+ complain_overflow_dont,
+ bfd_elf_generic_reloc,
+ "R_NIOS2_GOT_LO",
+ FALSE,
+ 0xffff0000,
+ 0xffff0000,
+ FALSE),
+
+ HOWTO (R_NIOS2_GOT_HA,
+ 0,
+ 2,
+ 16,
+ FALSE,
+ 16,
+ complain_overflow_dont,
+ bfd_elf_generic_reloc,
+ "R_NIOS2_GOT_HA",
+ FALSE,
+ 0xffff0000,
+ 0xffff0000,
+ FALSE),
+
+ HOWTO (R_NIOS2_CALL_LO,
+ 0,
+ 2,
+ 16,
+ FALSE,
+ 16,
+ complain_overflow_dont,
+ bfd_elf_generic_reloc,
+ "R_NIOS2_CALL_LO",
+ FALSE,
+ 0xffff0000,
+ 0xffff0000,
+ FALSE),
+
+ HOWTO (R_NIOS2_CALL_HA,
0,
2,
16,
FALSE,
- 6,
- complain_overflow_bitfield,
+ 16,
+ complain_overflow_dont,
bfd_elf_generic_reloc,
- "R_NIOS2_TLS_LDO16",
+ "R_NIOS2_CALL_HA",
FALSE,
- 0x003fffc0,
- 0x003fffc0,
+ 0xffff0000,
+ 0xffff0000,
FALSE),
- HOWTO (R_NIOS2_TLS_IE16,
+ 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_bitfield,
+ 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_TLS_IE16",
+ "R_NIOS2_R2_T1I7_2",
FALSE,
- 0x003fffc0,
- 0x003fffc0,
+ 0xfe00,
+ 0xfe00,
FALSE),
- HOWTO (R_NIOS2_TLS_LE16,
+ HOWTO (R_NIOS2_R2_T2I4,
0,
- 2,
- 16,
+ 1,
+ 4,
FALSE,
- 6,
- complain_overflow_bitfield,
+ 12,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_TLS_LE16",
+ "R_NIOS2_R2_T2I4",
FALSE,
- 0x003fffc0,
- 0x003fffc0,
+ 0xf000,
+ 0xf000,
FALSE),
- HOWTO (R_NIOS2_TLS_DTPMOD,
- 0,
- 2,
- 32,
+ HOWTO (R_NIOS2_R2_T2I4_1,
+ 1,
+ 1,
+ 4,
FALSE,
- 0,
- complain_overflow_dont,
+ 12,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_TLS_DTPMOD",
+ "R_NIOS2_R2_T2I4_1",
FALSE,
- 0xffffffff,
- 0xffffffff,
+ 0xf000,
+ 0xf000,
FALSE),
- HOWTO (R_NIOS2_TLS_DTPREL,
- 0,
+ HOWTO (R_NIOS2_R2_T2I4_2,
2,
- 32,
+ 1,
+ 4,
FALSE,
- 0,
- complain_overflow_dont,
+ 12,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_TLS_DTPREL",
+ "R_NIOS2_R2_T2I4_2",
FALSE,
- 0xffffffff,
- 0xffffffff,
+ 0xf000,
+ 0xf000,
FALSE),
- HOWTO (R_NIOS2_TLS_TPREL,
- 0,
+ HOWTO (R_NIOS2_R2_X1I7_2,
2,
- 32,
+ 1,
+ 7,
FALSE,
- 0,
- complain_overflow_dont,
+ 6,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_TLS_TPREL",
+ "R_NIOS2_R2_X1I7_2",
FALSE,
- 0xffffffff,
- 0xffffffff,
+ 0x1fc0,
+ 0x1fc0,
FALSE),
- HOWTO (R_NIOS2_COPY,
+ HOWTO (R_NIOS2_R2_X2L5,
0,
- 2,
- 32,
+ 1,
+ 5,
FALSE,
- 0,
- complain_overflow_dont,
+ 6,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_COPY",
+ "R_NIOS2_R2_X2L5",
FALSE,
- 0,
- 0,
+ 0x07c0,
+ 0x07c0,
FALSE),
- HOWTO (R_NIOS2_GLOB_DAT,
- 0,
+ HOWTO (R_NIOS2_R2_F1I5_2,
2,
- 32,
+ 1,
+ 5,
FALSE,
- 0,
- complain_overflow_dont,
+ 6,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_GLOB_DAT",
+ "R_NIOS2_R2_F1L5_2",
FALSE,
- 0xffffffff,
- 0xffffffff,
+ 0x07c0,
+ 0x07c0,
FALSE),
- HOWTO (R_NIOS2_JUMP_SLOT,
- 0,
+ HOWTO (R_NIOS2_R2_L5I4X1,
2,
- 32,
+ 1,
+ 4,
FALSE,
- 0,
- complain_overflow_dont,
+ 6,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_JUMP_SLOT",
+ "R_NIOS2_R2_L5I4X1",
FALSE,
- 0xffffffff,
- 0xffffffff,
+ 0x03c0,
+ 0x03c0,
FALSE),
- HOWTO (R_NIOS2_RELATIVE,
+ HOWTO (R_NIOS2_R2_T1X1I6,
0,
- 2,
- 32,
+ 1,
+ 6,
FALSE,
- 0,
- complain_overflow_dont,
+ 9,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_RELATIVE",
+ "R_NIOS2_R2_T1X1I6",
FALSE,
- 0xffffffff,
- 0xffffffff,
+ 0x7e00,
+ 0x7e00,
FALSE),
- HOWTO (R_NIOS2_GOTOFF,
- 0,
+ HOWTO (R_NIOS2_R2_T1X1I6_2,
2,
- 32,
+ 2,
+ 6,
FALSE,
- 0,
- complain_overflow_dont,
+ 9,
+ complain_overflow_unsigned,
bfd_elf_generic_reloc,
- "R_NIOS2_GOTOFF",
+ "R_NIOS2_R2_T1I1X6_2",
FALSE,
- 0xffffffff,
- 0xffffffff,
+ 0x7e00,
+ 0x7e00,
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 */
-
/* Add other relocations here. */
};
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. */
};
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},
{BFD_RELOC_NIOS2_RELATIVE, R_NIOS2_RELATIVE},
{BFD_RELOC_NIOS2_GOTOFF, R_NIOS2_GOTOFF},
{BFD_RELOC_NIOS2_CALL26_NOAT, R_NIOS2_CALL26_NOAT},
+ {BFD_RELOC_NIOS2_GOT_LO, R_NIOS2_GOT_LO},
+ {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
a dynamic GOT reloc in shared objects, only a dynamic PLT reloc. Lazy
linking will not work if the dynamic GOT reloc exists.
To check for this condition efficiently, we compare got_types_used against
- CALL16_USED, meaning
- (got_types_used & (GOT16_USED | CALL16_USED)) == CALL16_USED. */
-#define GOT16_USED 1
-#define CALL16_USED 2
+ CALL_USED, meaning
+ (got_types_used & (GOT_USED | CALL_USED)) == CALL_USED.
+ */
+#define GOT_USED 1
+#define CALL_USED 2
unsigned char got_types_used;
};
/* 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;
asection *srelbss;
asection *sbss;
+ /* GOT pointer symbol _gp_got. */
+ struct elf_link_hash_entry *h_gp_got;
+
union {
bfd_signed_vma refcount;
bfd_vma offset;
{
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;
/* 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;
/* 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;
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;
}
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)
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;
}
+#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, bfd *obfd)
+{
+ 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, obfd))
+ 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)
+ (_("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, obfd);
+
+ 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
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)
/* 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;
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;
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;
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);
}
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
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;
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;
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;
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)
}
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. */
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. */
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. */
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. */
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. */
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;
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. */
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. */
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. */
reloc_entry->addend);
}
-
+
/* Implement elf_backend_relocate_section. */
static bfd_boolean
nios2_elf32_relocate_section (bfd *output_bfd,
asection *splt;
asection *sreloc = NULL;
bfd_vma *local_got_offsets;
+ bfd_vma got_base;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
splt = htab->root.splt;
local_got_offsets = elf_local_got_offsets (input_bfd);
+ if (elf32_nios2_hash_table (info)->h_gp_got == NULL)
+ got_base = 0;
+ else
+ got_base = elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value;
+
for (rel = relocs; rel < relend; rel++)
{
reloc_howto_type *howto;
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;
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)
+ rel->r_offset);
else
reloc_address = 0;
-
+
if (howto)
{
switch (howto->type)
"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;
case R_NIOS2_GOT16:
case R_NIOS2_CALL16:
+ case R_NIOS2_GOT_LO:
+ case R_NIOS2_GOT_HA:
+ case R_NIOS2_CALL_LO:
+ case R_NIOS2_CALL_HA:
/* Relocation is to the entry for this symbol in the
global offset table. */
if (sgot == NULL)
bfd_boolean dyn;
eh = (struct elf32_nios2_link_hash_entry *)h;
- use_plt = (eh->got_types_used == CALL16_USED
+ use_plt = (eh->got_types_used == CALL_USED
&& h->plt.offset != (bfd_vma) -1);
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))
bfd_put_32 (output_bfd, relocation,
sgot->contents + off);
- if (info->shared)
+ if (bfd_link_pic (info))
{
asection *srelgot;
Elf_Internal_Rela outrel;
}
}
- 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;
+ relocation = (htab->root.sgotplt->output_offset + off
+ - got_base);
}
else
- relocation = sgot->output_offset + off;
+ relocation = sgot->output_offset + off - got_base;
/* This relocation does not use the addend. */
rel->r_addend = 0;
- r = _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents, rel->r_offset,
- relocation, rel->r_addend);
+ switch (howto->type)
+ {
+ case R_NIOS2_GOT_LO:
+ case R_NIOS2_CALL_LO:
+ r = nios2_elf32_do_lo16_relocate (input_bfd, howto,
+ input_section, contents,
+ rel->r_offset, relocation,
+ rel->r_addend);
+ break;
+ case R_NIOS2_GOT_HA:
+ case R_NIOS2_CALL_HA:
+ r = nios2_elf32_do_hiadj16_relocate (input_bfd, howto,
+ input_section, contents,
+ rel->r_offset,
+ relocation,
+ rel->r_addend);
+ break;
+ default:
+ r = _bfd_final_link_relocate (howto, input_bfd,
+ input_section, contents,
+ rel->r_offset, relocation,
+ rel->r_addend);
+ break;
+ }
break;
case R_NIOS2_GOTOFF_LO:
case R_NIOS2_GOTOFF_HA:
case R_NIOS2_GOTOFF:
- /* Relocation is relative to the start of the
- global offset table. */
+ /* Relocation is relative to the global offset table pointer. */
BFD_ASSERT (sgot != NULL);
if (sgot == NULL)
}
/* Note that sgot->output_offset is not involved in this
- calculation. We always want the start of .got. If we
- define _GLOBAL_OFFSET_TABLE in a different way, as is
- permitted by the ABI, we might have to change this
- calculation. */
+ calculation. We always want the start of .got. */
relocation -= sgot->output_section->vma;
+
+ /* Now we adjust the relocation to be relative to the GOT pointer
+ (the _gp_got symbol), which possibly contains the 0x8000 bias. */
+ relocation -= got_base;
+
switch (howto->type)
{
case R_NIOS2_GOTOFF_LO:
{
/* 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;
htab->tls_ldm_got.offset |= 1;
}
- relocation = (htab->root.sgot->output_offset + off);
+ relocation = htab->root.sgot->output_offset + off - got_base;
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset,
{
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;
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))
if ((tls_type & GOT_TLS_GD) && r_type != R_NIOS2_TLS_GD16)
off += 8;
- relocation = (htab->root.sgot->output_offset + off);
+ relocation = htab->root.sgot->output_offset + off - got_base;
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset,
break;
case R_NIOS2_TLS_LE16:
- if (info->shared && !info->pie)
+ if (bfd_link_dll (info))
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): R_NIOS2_TLS_LE16 relocation not "
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
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);
create_got_section (bfd *dynobj, struct bfd_link_info *info)
{
struct elf32_nios2_link_hash_table *htab;
+ struct elf_link_hash_entry *h;
htab = elf32_nios2_hash_table (info);
if (!bfd_set_section_alignment (dynobj, htab->root.sgotplt, 4))
return FALSE;
+ /* The Nios II ABI specifies that GOT-relative relocations are relative
+ to the linker-created symbol _gp_got, rather than using
+ _GLOBAL_OFFSET_TABLE_ directly. In particular, the latter always
+ points to the base of the GOT while _gp_got may include a bias. */
+ h = _bfd_elf_define_linkage_sym (dynobj, info, htab->root.sgotplt,
+ "_gp_got");
+ elf32_nios2_hash_table (info)->h_gp_got = h;
+ if (h == NULL)
+ return FALSE;
+
return TRUE;
}
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
if (!htab->sdynbss)
return FALSE;
- if (!info->shared)
+ if (!bfd_link_pic (info))
{
htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
if (!htab->srelbss)
_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
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;
switch (r_type)
{
case R_NIOS2_GOT16:
+ case R_NIOS2_GOT_LO:
+ case R_NIOS2_GOT_HA:
case R_NIOS2_CALL16:
+ case R_NIOS2_CALL_LO:
+ case R_NIOS2_CALL_HA:
case R_NIOS2_TLS_GD16:
case R_NIOS2_TLS_IE16:
/* This symbol requires a global offset table entry. */
{
default:
case R_NIOS2_GOT16:
+ case R_NIOS2_GOT_LO:
+ case R_NIOS2_GOT_HA:
case R_NIOS2_CALL16:
+ case R_NIOS2_CALL_LO:
+ case R_NIOS2_CALL_HA:
tls_type = GOT_NORMAL;
break;
case R_NIOS2_TLS_GD16:
}
if (srelgot == NULL
- && (h != NULL || info->shared))
+ && (h != NULL || bfd_link_pic (info)))
{
srelgot = htab->root.srelgot;
BFD_ASSERT (srelgot != NULL);
= (struct elf32_nios2_link_hash_entry *)h;
h->got.refcount++;
old_tls_type = elf32_nios2_hash_entry(h)->tls_type;
- if (r_type == R_NIOS2_CALL16)
+ if (r_type == R_NIOS2_CALL16
+ || r_type == R_NIOS2_CALL_LO
+ || r_type == R_NIOS2_CALL_HA)
{
/* Make sure a plt entry is created for this symbol if
it turns out to be a function defined by a dynamic
h->plt.refcount++;
h->needs_plt = 1;
h->type = STT_FUNC;
- eh->got_types_used |= CALL16_USED;
+ eh->got_types_used |= CALL_USED;
}
else
- eh->got_types_used |= GOT16_USED;
+ eh->got_types_used |= GOT_USED;
}
else
{
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
/* 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;
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;
switch (r_type)
{
case R_NIOS2_GOT16:
+ case R_NIOS2_GOT_LO:
+ case R_NIOS2_GOT_HA:
case R_NIOS2_CALL16:
+ case R_NIOS2_CALL_LO:
+ case R_NIOS2_CALL_HA:
if (h != NULL)
{
if (h->got.refcount > 0)
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);
}
}
- use_plt = (eh->got_types_used == CALL16_USED
+ use_plt = (eh->got_types_used == CALL_USED
&& h->plt.offset != (bfd_vma) -1);
if (!use_plt && h->got.offset != (bfd_vma) -1
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,
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
- /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
+ /* Mark _DYNAMIC, _GLOBAL_OFFSET_TABLE_, and _gp_got as absolute. */
if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || h == elf_hash_table (info)->hgot)
+ || h == elf_hash_table (info)->hgot
+ || h == elf32_nios2_hash_table (info)->h_gp_got)
sym->st_shndx = SHN_ABS;
return TRUE;
{
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
{
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,
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);
}
}
}
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_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;
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;
}
eh = (struct elf32_nios2_link_hash_entry *) h;
- use_plt = (eh->got_types_used == CALL16_USED
+ use_plt = (eh->got_types_used == CALL_USED
&& h->plt.offset != (bfd_vma) -1);
if (h->got.refcount > 0)
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))
{
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);
}
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;
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);
/* 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;
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
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
sym dynamic relocs. */
elf_link_hash_traverse (& htab->root, allocate_dynrelocs, info);
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* If the .got section is more than 0x8000 bytes, we add
+ 0x8000 to the value of _gp_got, so that 16-bit relocations
+ have a greater chance of working. */
+ if (htab->root.sgot->size >= 0x8000
+ && elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value == 0)
+ elf32_nios2_hash_table (info)->h_gp_got->root.u.def.value = 0x8000;
+ }
+
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
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;
#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))
|| !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
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)
/* 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,
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.
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))
{
#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. */
#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
#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"