+ /* This reloc does nothing. */
+ HOWTO (R_M32R_NONE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_NONE", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 16 bit absolute relocation. */
+ HOWTO (R_M32R_16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ m32r_elf_generic_reloc,/* special_function */
+ "R_M32R_16", /* name */
+ TRUE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 32 bit absolute relocation. */
+ HOWTO (R_M32R_32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ m32r_elf_generic_reloc,/* special_function */
+ "R_M32R_32", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 24 bit address. */
+ HOWTO (R_M32R_24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ m32r_elf_generic_reloc,/* special_function */
+ "R_M32R_24", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffff, /* src_mask */
+ 0xffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* An PC Relative 10-bit relocation, shifted by 2.
+ This reloc is complicated because relocations are relative to pc & -4.
+ i.e. branches in the right insn slot use the address of the left insn
+ slot for pc. */
+ /* ??? It's not clear whether this should have partial_inplace set or not.
+ Branch relaxing in the assembler can store the addend in the insn,
+ and if bfd_install_relocation gets called the addend may get added
+ again. */
+ HOWTO (R_M32R_10_PCREL, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 10, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ m32r_elf_10_pcrel_reloc, /* special_function */
+ "R_M32R_10_PCREL", /* name */
+ FALSE, /* partial_inplace */
+ 0xff, /* src_mask */
+ 0xff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* A relative 18 bit relocation, right shifted by 2. */
+ HOWTO (R_M32R_18_PCREL, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_18_PCREL", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* A relative 26 bit relocation, right shifted by 2. */
+ /* ??? It's not clear whether this should have partial_inplace set or not.
+ Branch relaxing in the assembler can store the addend in the insn,
+ and if bfd_install_relocation gets called the addend may get added
+ again. */
+ HOWTO (R_M32R_26_PCREL, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_26_PCREL", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffff, /* src_mask */
+ 0xffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* High 16 bits of address when lower 16 is or'd in. */
+ HOWTO (R_M32R_HI16_ULO, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ m32r_elf_hi16_reloc, /* special_function */
+ "R_M32R_HI16_ULO", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* High 16 bits of address when lower 16 is added in. */
+ HOWTO (R_M32R_HI16_SLO, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ m32r_elf_hi16_reloc, /* special_function */
+ "R_M32R_HI16_SLO", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Lower 16 bits of address. */
+ HOWTO (R_M32R_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ m32r_elf_lo16_reloc, /* special_function */
+ "R_M32R_LO16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Small data area 16 bits offset. */
+ HOWTO (R_M32R_SDA16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ m32r_elf_sda16_reloc, /* special_function */
+ "R_M32R_SDA16", /* name */
+ TRUE, /* partial_inplace */ /* FIXME: correct? */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* GNU extension to record C++ vtable hierarchy. */
+ HOWTO (R_M32R_GNU_VTINHERIT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ NULL, /* special_function */
+ "R_M32R_GNU_VTINHERIT", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* GNU extension to record C++ vtable member usage. */
+ HOWTO (R_M32R_GNU_VTENTRY, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_elf_rel_vtable_reloc_fn, /* special_function */
+ "R_M32R_GNU_VTENTRY", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ EMPTY_HOWTO (13),
+ EMPTY_HOWTO (14),
+ EMPTY_HOWTO (15),
+ EMPTY_HOWTO (16),
+ EMPTY_HOWTO (17),
+ EMPTY_HOWTO (18),
+ EMPTY_HOWTO (19),
+ EMPTY_HOWTO (20),
+ EMPTY_HOWTO (21),
+ EMPTY_HOWTO (22),
+ EMPTY_HOWTO (23),
+ EMPTY_HOWTO (24),
+ EMPTY_HOWTO (25),
+ EMPTY_HOWTO (26),
+ EMPTY_HOWTO (27),
+ EMPTY_HOWTO (28),
+ EMPTY_HOWTO (29),
+ EMPTY_HOWTO (30),
+ EMPTY_HOWTO (31),
+ EMPTY_HOWTO (32),
+
+ /* A 16 bit absolute relocation. */
+ HOWTO (R_M32R_16_RELA, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_16_RELA", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 32 bit absolute relocation. */
+ HOWTO (R_M32R_32_RELA, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc,/* special_function */
+ "R_M32R_32_RELA", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 24 bit address. */
+ HOWTO (R_M32R_24_RELA, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ bfd_elf_generic_reloc,/* special_function */
+ "R_M32R_24_RELA", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffff, /* src_mask */
+ 0xffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_M32R_10_PCREL_RELA, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 10, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ m32r_elf_10_pcrel_reloc, /* special_function */
+ "R_M32R_10_PCREL_RELA",/* name */
+ FALSE, /* partial_inplace */
+ 0xff, /* src_mask */
+ 0xff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* A relative 18 bit relocation, right shifted by 2. */
+ HOWTO (R_M32R_18_PCREL_RELA, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_18_PCREL_RELA",/* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* A relative 26 bit relocation, right shifted by 2. */
+ HOWTO (R_M32R_26_PCREL_RELA, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_26_PCREL_RELA",/* name */
+ FALSE, /* partial_inplace */
+ 0xffffff, /* src_mask */
+ 0xffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* High 16 bits of address when lower 16 is or'd in. */
+ HOWTO (R_M32R_HI16_ULO_RELA, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_HI16_ULO_RELA",/* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* High 16 bits of address when lower 16 is added in. */
+ HOWTO (R_M32R_HI16_SLO_RELA, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_HI16_SLO_RELA",/* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Lower 16 bits of address. */
+ HOWTO (R_M32R_LO16_RELA, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_LO16_RELA", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Small data area 16 bits offset. */
+ HOWTO (R_M32R_SDA16_RELA, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_SDA16_RELA", /* name */
+ TRUE, /* partial_inplace */ /* FIXME: correct? */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* GNU extension to record C++ vtable hierarchy. */
+ HOWTO (R_M32R_RELA_GNU_VTINHERIT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ NULL, /* special_function */
+ "R_M32R_RELA_GNU_VTINHERIT", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* GNU extension to record C++ vtable member usage. */
+ HOWTO (R_M32R_RELA_GNU_VTENTRY, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_elf_rel_vtable_reloc_fn, /* special_function */
+ "R_M32R_RELA_GNU_VTENTRY", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 32 bit PC relative relocation. */
+ HOWTO (R_M32R_REL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc,/* special_function */
+ "R_M32R_REL32", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ EMPTY_HOWTO (46),
+ EMPTY_HOWTO (47),
+
+ /* Like R_M32R_24, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_M32R_GOT24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOT24", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffff, /* src_mask */
+ 0xffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like R_M32R_PCREL, but referring to the procedure linkage table
+ entry for the symbol. */
+ HOWTO (R_M32R_26_PLTREL, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_26_PLTREL", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffff, /* src_mask */
+ 0xffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* This is used only by the dynamic linker. The symbol should exist
+ both in the object being run and in some shared library. The
+ dynamic linker copies the data addressed by the symbol from the
+ shared library into the object, because the object being
+ run has to have the data at some particular address. */
+ HOWTO (R_M32R_COPY, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_COPY", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like R_M32R_24, but used when setting global offset table
+ entries. */
+ HOWTO (R_M32R_GLOB_DAT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GLOB_DAT", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Marks a procedure linkage table entry for a symbol. */
+ HOWTO (R_M32R_JMP_SLOT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_JMP_SLOT", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Used only by the dynamic linker. When the object is run, this
+ longword is set to the load address of the object, plus the
+ addend. */
+ HOWTO (R_M32R_RELATIVE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_RELATIVE", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_M32R_GOTOFF, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOTOFF", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffff, /* src_mask */
+ 0xffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* An PC Relative 24-bit relocation used when setting PIC offset
+ table register. */
+ HOWTO (R_M32R_GOTPC24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 24, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOTPC24", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffff, /* src_mask */
+ 0xffffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* Like R_M32R_HI16_ULO, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_M32R_GOT16_HI_ULO, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOT16_HI_ULO", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like R_M32R_HI16_SLO, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_M32R_GOT16_HI_SLO, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOT16_HI_SLO", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like R_M32R_LO16, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_M32R_GOT16_LO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOT16_LO", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* An PC Relative relocation used when setting PIC offset table register.
+ Like R_M32R_HI16_ULO, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_M32R_GOTPC_HI_ULO, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOTPC_HI_ULO", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* An PC Relative relocation used when setting PIC offset table register.
+ Like R_M32R_HI16_SLO, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_M32R_GOTPC_HI_SLO, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOTPC_HI_SLO", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* An PC Relative relocation used when setting PIC offset table register.
+ Like R_M32R_LO16, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_M32R_GOTPC_LO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOTPC_LO", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ HOWTO (R_M32R_GOTOFF_HI_ULO, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOTOFF_HI_ULO",/* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_M32R_GOTOFF_HI_SLO, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOTOFF_HI_SLO",/* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_M32R_GOTOFF_LO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_M32R_GOTOFF_LO", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+};
+
+/* Map BFD reloc types to M32R ELF reloc types. */
+
+struct m32r_reloc_map
+{
+ bfd_reloc_code_real_type bfd_reloc_val;
+ unsigned char elf_reloc_val;
+};
+
+#ifdef USE_M32R_OLD_RELOC
+static const struct m32r_reloc_map m32r_reloc_map_old[] =
+{
+ { BFD_RELOC_NONE, R_M32R_NONE },
+ { BFD_RELOC_16, R_M32R_16 },
+ { BFD_RELOC_32, R_M32R_32 },
+ { BFD_RELOC_M32R_24, R_M32R_24 },
+ { BFD_RELOC_M32R_10_PCREL, R_M32R_10_PCREL },
+ { BFD_RELOC_M32R_18_PCREL, R_M32R_18_PCREL },
+ { BFD_RELOC_M32R_26_PCREL, R_M32R_26_PCREL },
+ { BFD_RELOC_M32R_HI16_ULO, R_M32R_HI16_ULO },
+ { BFD_RELOC_M32R_HI16_SLO, R_M32R_HI16_SLO },
+ { BFD_RELOC_M32R_LO16, R_M32R_LO16 },
+ { BFD_RELOC_M32R_SDA16, R_M32R_SDA16 },
+ { BFD_RELOC_VTABLE_INHERIT, R_M32R_GNU_VTINHERIT },
+ { BFD_RELOC_VTABLE_ENTRY, R_M32R_GNU_VTENTRY },
+};
+#else
+static const struct m32r_reloc_map m32r_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_M32R_NONE },
+ { BFD_RELOC_16, R_M32R_16_RELA },
+ { BFD_RELOC_32, R_M32R_32_RELA },
+ { BFD_RELOC_M32R_24, R_M32R_24_RELA },
+ { BFD_RELOC_M32R_10_PCREL, R_M32R_10_PCREL_RELA },
+ { BFD_RELOC_M32R_18_PCREL, R_M32R_18_PCREL_RELA },
+ { BFD_RELOC_M32R_26_PCREL, R_M32R_26_PCREL_RELA },
+ { BFD_RELOC_M32R_HI16_ULO, R_M32R_HI16_ULO_RELA },
+ { BFD_RELOC_M32R_HI16_SLO, R_M32R_HI16_SLO_RELA },
+ { BFD_RELOC_M32R_LO16, R_M32R_LO16_RELA },
+ { BFD_RELOC_M32R_SDA16, R_M32R_SDA16_RELA },
+ { BFD_RELOC_VTABLE_INHERIT, R_M32R_RELA_GNU_VTINHERIT },
+ { BFD_RELOC_VTABLE_ENTRY, R_M32R_RELA_GNU_VTENTRY },
+ { BFD_RELOC_32_PCREL, R_M32R_REL32 },
+
+ { BFD_RELOC_M32R_GOT24, R_M32R_GOT24 },
+ { BFD_RELOC_M32R_26_PLTREL, R_M32R_26_PLTREL },
+ { BFD_RELOC_M32R_COPY, R_M32R_COPY },
+ { BFD_RELOC_M32R_GLOB_DAT, R_M32R_GLOB_DAT },
+ { BFD_RELOC_M32R_JMP_SLOT, R_M32R_JMP_SLOT },
+ { BFD_RELOC_M32R_RELATIVE, R_M32R_RELATIVE },
+ { BFD_RELOC_M32R_GOTOFF, R_M32R_GOTOFF },
+ { BFD_RELOC_M32R_GOTPC24, R_M32R_GOTPC24 },
+ { BFD_RELOC_M32R_GOT16_HI_ULO, R_M32R_GOT16_HI_ULO },
+ { BFD_RELOC_M32R_GOT16_HI_SLO, R_M32R_GOT16_HI_SLO },
+ { BFD_RELOC_M32R_GOT16_LO, R_M32R_GOT16_LO },
+ { BFD_RELOC_M32R_GOTPC_HI_ULO, R_M32R_GOTPC_HI_ULO },
+ { BFD_RELOC_M32R_GOTPC_HI_SLO, R_M32R_GOTPC_HI_SLO },
+ { BFD_RELOC_M32R_GOTPC_LO, R_M32R_GOTPC_LO },
+ { BFD_RELOC_M32R_GOTOFF_HI_ULO, R_M32R_GOTOFF_HI_ULO },
+ { BFD_RELOC_M32R_GOTOFF_HI_SLO, R_M32R_GOTOFF_HI_SLO },
+ { BFD_RELOC_M32R_GOTOFF_LO, R_M32R_GOTOFF_LO },
+};
+#endif
+
+static reloc_howto_type *
+bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ bfd_reloc_code_real_type code)
+{
+ unsigned int i;
+
+#ifdef USE_M32R_OLD_RELOC
+ for (i = 0;
+ i < sizeof (m32r_reloc_map_old) / sizeof (struct m32r_reloc_map);
+ i++)
+ if (m32r_reloc_map_old[i].bfd_reloc_val == code)
+ return &m32r_elf_howto_table[m32r_reloc_map_old[i].elf_reloc_val];
+
+#else /* ! USE_M32R_OLD_RELOC */
+
+ for (i = 0;
+ i < sizeof (m32r_reloc_map) / sizeof (struct m32r_reloc_map);
+ i++)
+ if (m32r_reloc_map[i].bfd_reloc_val == code)
+ return &m32r_elf_howto_table[m32r_reloc_map[i].elf_reloc_val];
+#endif
+
+ return NULL;
+}
+
+static reloc_howto_type *
+bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (m32r_elf_howto_table) / sizeof (m32r_elf_howto_table[0]);
+ i++)
+ if (m32r_elf_howto_table[i].name != NULL
+ && strcasecmp (m32r_elf_howto_table[i].name, r_name) == 0)
+ return &m32r_elf_howto_table[i];
+
+ return NULL;
+}
+
+/* Set the howto pointer for an M32R ELF reloc. */
+
+static void
+m32r_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *cache_ptr,
+ Elf_Internal_Rela *dst)
+{
+ unsigned int r_type;
+
+ r_type = ELF32_R_TYPE (dst->r_info);
+ BFD_ASSERT (ELF32_R_TYPE(dst->r_info) <= (unsigned int) R_M32R_GNU_VTENTRY);
+ cache_ptr->howto = &m32r_elf_howto_table[r_type];
+}
+
+static void
+m32r_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *cache_ptr,
+ Elf_Internal_Rela *dst)
+{
+ BFD_ASSERT ((ELF32_R_TYPE(dst->r_info) == (unsigned int) R_M32R_NONE)
+ || ((ELF32_R_TYPE(dst->r_info) > (unsigned int) R_M32R_GNU_VTENTRY)
+ && (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_M32R_max)));
+ cache_ptr->howto = &m32r_elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+}
+
+\f
+/* Given a BFD section, try to locate the corresponding ELF section
+ index. */
+
+static bfd_boolean
+_bfd_m32r_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec,
+ int *retval)
+{
+ if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
+ {
+ *retval = SHN_M32R_SCOMMON;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* M32R ELF uses two common sections. One is the usual one, and the other
+ is for small objects. All the small objects are kept together, and then
+ referenced via one register, which yields faster assembler code. It is
+ up to the compiler to emit an instruction to load the register with
+ _SDA_BASE. This is what we use for the small common section. This
+ approach is copied from elf32-mips.c. */
+static asection m32r_elf_scom_section;
+static asymbol m32r_elf_scom_symbol;
+static asymbol *m32r_elf_scom_symbol_ptr;
+
+/* Handle the special M32R section numbers that a symbol may use. */
+
+static void
+_bfd_m32r_elf_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *asym)
+{
+ elf_symbol_type *elfsym = (elf_symbol_type *) asym;
+
+ switch (elfsym->internal_elf_sym.st_shndx)
+ {
+ case SHN_M32R_SCOMMON:
+ if (m32r_elf_scom_section.name == NULL)
+ {
+ /* Initialize the small common section. */
+ m32r_elf_scom_section.name = ".scommon";
+ m32r_elf_scom_section.flags = SEC_IS_COMMON;
+ m32r_elf_scom_section.output_section = &m32r_elf_scom_section;
+ m32r_elf_scom_section.symbol = &m32r_elf_scom_symbol;
+ m32r_elf_scom_section.symbol_ptr_ptr = &m32r_elf_scom_symbol_ptr;
+ m32r_elf_scom_symbol.name = ".scommon";
+ m32r_elf_scom_symbol.flags = BSF_SECTION_SYM;
+ m32r_elf_scom_symbol.section = &m32r_elf_scom_section;
+ m32r_elf_scom_symbol_ptr = &m32r_elf_scom_symbol;
+ }
+ asym->section = &m32r_elf_scom_section;
+ asym->value = elfsym->internal_elf_sym.st_size;
+ break;
+ }
+}
+
+/* Hook called by the linker routine which adds symbols from an object
+ file. We must handle the special M32R section numbers here.
+ We also keep watching for whether we need to create the sdata special
+ linker sections. */
+
+static bfd_boolean
+m32r_elf_add_symbol_hook (bfd *abfd,
+ struct bfd_link_info *info,
+ Elf_Internal_Sym *sym,
+ const char **namep,
+ flagword *flagsp ATTRIBUTE_UNUSED,
+ asection **secp,
+ bfd_vma *valp)
+{
+ if (! info->relocatable
+ && (*namep)[0] == '_' && (*namep)[1] == 'S'
+ && strcmp (*namep, "_SDA_BASE_") == 0
+ && is_elf_hash_table (info->hash))
+ {
+ /* This is simpler than using _bfd_elf_create_linker_section
+ (our needs are simpler than ppc's needs). Also
+ _bfd_elf_create_linker_section currently has a bug where if a .sdata
+ section already exists a new one is created that follows it which
+ screws of _SDA_BASE_ address calcs because output_offset != 0. */
+ struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *bh;
+ asection *s = bfd_get_section_by_name (abfd, ".sdata");
+
+ /* The following code was cobbled from elf32-ppc.c and elflink.c. */
+ if (s == NULL)
+ {
+ flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+
+ s = bfd_make_section_anyway_with_flags (abfd, ".sdata",
+ flags);
+ if (s == NULL)
+ return FALSE;
+ bfd_set_section_alignment (abfd, s, 2);
+ }
+
+ bh = bfd_link_hash_lookup (info->hash, "_SDA_BASE_",
+ FALSE, FALSE, FALSE);
+
+ if ((bh == NULL || bh->type == bfd_link_hash_undefined)
+ && !(_bfd_generic_link_add_one_symbol (info,
+ abfd,
+ "_SDA_BASE_",
+ BSF_GLOBAL,
+ s,
+ (bfd_vma) 32768,
+ NULL,
+ FALSE,
+ get_elf_backend_data (abfd)->collect,
+ &bh)))
+ return FALSE;
+ h = (struct elf_link_hash_entry *) bh;
+ h->type = STT_OBJECT;
+ }
+
+ switch (sym->st_shndx)
+ {
+ case SHN_M32R_SCOMMON:
+ *secp = bfd_make_section_old_way (abfd, ".scommon");
+ (*secp)->flags |= SEC_IS_COMMON;
+ *valp = sym->st_size;
+ break;
+ }
+
+ return TRUE;
+}
+
+/* We have to figure out the SDA_BASE value, so that we can adjust the
+ symbol value correctly. We look up the symbol _SDA_BASE_ in the output
+ BFD. If we can't find it, we're stuck. We cache it in the ELF
+ target data. We don't need to adjust the symbol value for an
+ external symbol if we are producing relocatable output. */
+
+static bfd_reloc_status_type
+m32r_elf_final_sda_base (bfd *output_bfd,
+ struct bfd_link_info *info,
+ const char **error_message,
+ bfd_vma *psb)
+{
+ if (elf_gp (output_bfd) == 0)
+ {
+ struct bfd_link_hash_entry *h;
+
+ h = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", FALSE, FALSE, TRUE);
+ if (h != NULL && h->type == bfd_link_hash_defined)
+ elf_gp (output_bfd) = (h->u.def.value
+ + h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset);
+ else
+ {
+ /* Only get the error once. */
+ *psb = elf_gp (output_bfd) = 4;
+ *error_message =
+ (const char *) _("SDA relocation when _SDA_BASE_ not defined");
+ return bfd_reloc_dangerous;
+ }
+ }
+ *psb = elf_gp (output_bfd);
+ return bfd_reloc_ok;
+}
+\f
+/* Return size of a PLT entry. */
+#define elf_m32r_sizeof_plt(info) PLT_ENTRY_SIZE
+
+/* The m32r linker needs to keep track of the number of relocs that it
+ decides to copy in check_relocs for each symbol. This is so that
+ it can discard PC relative relocs if it doesn't need them when
+ linking with -Bsymbolic. We store the information in a field
+ extending the regular ELF linker hash table. */
+
+/* This structure keeps track of the number of PC relative relocs we
+ have copied for a given symbol. */
+
+struct elf_m32r_pcrel_relocs_copied
+{
+ /* Next section. */
+ struct elf_m32r_pcrel_relocs_copied *next;
+ /* A section in dynobj. */
+ asection *section;
+ /* Number of relocs copied in this section. */
+ bfd_size_type count;
+};
+
+/* The sh linker needs to keep track of the number of relocs that it
+ decides to copy as dynamic relocs in check_relocs for each symbol.
+ This is so that it can later discard them if they are found to be
+ unnecessary. We store the information in a field extending the
+ regular ELF linker hash table. */
+
+struct elf_m32r_dyn_relocs
+{
+ struct elf_m32r_dyn_relocs *next;
+
+ /* The input section of the reloc. */
+ asection *sec;
+
+ /* Total number of relocs copied for the input section. */
+ bfd_size_type count;
+
+ /* Number of pc-relative relocs copied for the input section. */
+ bfd_size_type pc_count;
+};
+
+
+/* m32r ELF linker hash entry. */
+
+struct elf_m32r_link_hash_entry
+{
+ struct elf_link_hash_entry root;
+
+ /* Track dynamic relocs copied for this symbol. */
+ struct elf_m32r_dyn_relocs *dyn_relocs;
+};
+
+/* m32r ELF linker hash table. */
+
+struct elf_m32r_link_hash_table
+{
+ struct elf_link_hash_table root;
+
+ /* Short-cuts to get to dynamic linker sections. */
+ asection *sgot;
+ asection *sgotplt;
+ asection *srelgot;
+ asection *splt;
+ asection *srelplt;
+ asection *sdynbss;
+ asection *srelbss;
+
+ /* Small local sym to section mapping cache. */
+ struct sym_sec_cache sym_sec;
+};
+
+/* Traverse an m32r ELF linker hash table. */
+
+#define m32r_elf_link_hash_traverse(table, func, info) \
+ (elf_link_hash_traverse \
+ (&(table)->root, \
+ (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \
+ (info)))
+
+/* Get the m32r ELF linker hash table from a link_info structure. */
+
+
+#define m32r_elf_hash_table(p) \
+ ((struct elf_m32r_link_hash_table *) ((p)->hash))
+
+/* Create an entry in an m32r ELF linker hash table. */
+
+static struct bfd_hash_entry *
+m32r_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
+{
+ struct elf_m32r_link_hash_entry *ret =
+ (struct elf_m32r_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == NULL)
+ ret = bfd_hash_allocate (table,
+ sizeof (struct elf_m32r_link_hash_entry));
+ if (ret == NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct elf_m32r_link_hash_entry *)
+ _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != NULL)
+ {
+ struct elf_m32r_link_hash_entry *eh;
+
+ eh = (struct elf_m32r_link_hash_entry *) ret;
+ eh->dyn_relocs = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create an m32r ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+m32r_elf_link_hash_table_create (bfd *abfd)
+{
+ struct elf_m32r_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct elf_m32r_link_hash_table);
+
+ ret = bfd_malloc (amt);
+ if (ret == NULL)
+ return NULL;
+
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ m32r_elf_link_hash_newfunc,
+ sizeof (struct elf_m32r_link_hash_entry)))
+ {
+ free (ret);
+ return NULL;
+ }
+
+ ret->sgot = NULL;
+ ret->sgotplt = NULL;
+ ret->srelgot = NULL;
+ ret->splt = NULL;
+ ret->srelplt = NULL;
+ ret->sdynbss = NULL;
+ ret->srelbss = NULL;
+ ret->sym_sec.abfd = NULL;
+
+ return &ret->root.root;
+}
+
+/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
+ shortcuts to them in our hash table. */
+
+static bfd_boolean
+create_got_section (bfd *dynobj, struct bfd_link_info *info)
+{
+ struct elf_m32r_link_hash_table *htab;
+
+ if (! _bfd_elf_create_got_section (dynobj, info))
+ return FALSE;
+
+ htab = m32r_elf_hash_table (info);
+ htab->sgot = bfd_get_section_by_name (dynobj, ".got");
+ htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+ if (! htab->sgot || ! htab->sgotplt)
+ abort ();
+
+ htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY));
+ if (htab->srelgot == NULL
+ || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Create dynamic sections when linking against a dynamic object. */
+
+static bfd_boolean
+m32r_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
+{
+ struct elf_m32r_link_hash_table *htab;
+ flagword flags, pltflags;
+ asection *s;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int ptralign = 2; /* 32bit */
+
+ htab = m32r_elf_hash_table (info);
+
+ /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+ .rel[a].bss sections. */
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+
+ pltflags = flags;
+ pltflags |= SEC_CODE;
+ if (bed->plt_not_loaded)
+ pltflags &= ~ (SEC_LOAD | SEC_HAS_CONTENTS);
+ if (bed->plt_readonly)
+ pltflags |= SEC_READONLY;
+
+ s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
+ htab->splt = s;
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+ return FALSE;
+
+ if (bed->want_plt_sym)
+ {
+ /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
+ .plt section. */
+ struct bfd_link_hash_entry *bh = NULL;
+ struct elf_link_hash_entry *h;
+
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
+ (bfd_vma) 0, NULL, FALSE,
+ get_elf_backend_data (abfd)->collect, &bh)))
+ return FALSE;
+ h = (struct elf_link_hash_entry *) bh;
+ h->def_regular = 1;
+ h->type = STT_OBJECT;
+ htab->root.hplt = h;
+
+ if (info->shared
+ && ! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ s = bfd_make_section_with_flags (abfd,
+ bed->default_use_rela_p ? ".rela.plt" : ".rel.plt",
+ flags | SEC_READONLY);
+ htab->srelplt = s;
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, ptralign))
+ return FALSE;
+
+ if (htab->sgot == NULL
+ && ! create_got_section (abfd, info))
+ return FALSE;
+
+ {
+ const char *secname;
+ char *relname;
+ flagword secflags;
+ asection *sec;
+
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ secflags = bfd_get_section_flags (abfd, sec);
+ if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
+ || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
+ continue;
+ secname = bfd_get_section_name (abfd, sec);
+ relname = bfd_malloc ((bfd_size_type) strlen (secname) + 6);
+ strcpy (relname, ".rela");
+ strcat (relname, secname);
+ if (bfd_get_section_by_name (abfd, secname))
+ continue;
+ s = bfd_make_section_with_flags (abfd, relname,
+ flags | SEC_READONLY);
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, ptralign))
+ return FALSE;
+ }
+ }
+
+ if (bed->want_dynbss)
+ {
+ /* The .dynbss section is a place to put symbols which are defined
+ by dynamic objects, are referenced by regular objects, and are
+ not functions. We must allocate space for them in the process
+ image and use a R_*_COPY reloc to tell the dynamic linker to
+ initialize them at run time. The linker script puts the .dynbss
+ section into the .bss section of the final image. */
+ s = bfd_make_section_with_flags (abfd, ".dynbss",
+ SEC_ALLOC | SEC_LINKER_CREATED);
+ htab->sdynbss = s;
+ if (s == NULL)
+ return FALSE;
+ /* The .rel[a].bss section holds copy relocs. This section is not
+ normally needed. We need to create it here, though, so that the
+ linker will map it to an output section. We can't just create it
+ only if we need it, because we will not know whether we need it
+ until we have seen all the input files, and the first time the
+ main linker code calls BFD after examining all the input files
+ (size_dynamic_sections) the input sections have already been
+ mapped to the output sections. If the section turns out not to
+ be needed, we can discard it later. We will never need this
+ section when generating a shared object, since they do not use
+ copy relocs. */
+ if (! info->shared)
+ {
+ s = bfd_make_section_with_flags (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.bss" : ".rel.bss"),
+ flags | SEC_READONLY);
+ htab->srelbss = s;
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, ptralign))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Copy the extra info we tack onto an elf_link_hash_entry. */
+
+static void
+m32r_elf_copy_indirect_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *dir,
+ struct elf_link_hash_entry *ind)
+{
+ struct elf_m32r_link_hash_entry * edir;
+ struct elf_m32r_link_hash_entry * eind;
+
+ edir = (struct elf_m32r_link_hash_entry *) dir;
+ eind = (struct elf_m32r_link_hash_entry *) ind;
+
+ if (eind->dyn_relocs != NULL)
+ {
+ if (edir->dyn_relocs != NULL)
+ {
+ struct elf_m32r_dyn_relocs **pp;
+ struct elf_m32r_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_m32r_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;
+ }
+
+ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
+}
+
+\f
+/* 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
+m32r_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ struct elf_m32r_link_hash_table *htab;
+ struct elf_m32r_link_hash_entry *eh;
+ struct elf_m32r_dyn_relocs *p;
+ bfd *dynobj;
+ asection *s;
+
+#ifdef DEBUG_PIC
+ printf ("m32r_elf_adjust_dynamic_symbol()\n");
+#endif
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ /* Make sure we know what is going on here. */
+ BFD_ASSERT (dynobj != NULL
+ && (h->needs_plt
+ || h->u.weakdef != NULL
+ || (h->def_dynamic
+ && h->ref_regular
+ && !h->def_regular)));
+
+ /* If this is a function, put it in the procedure linkage table. We
+ will fill in the contents of the procedure linkage table later,
+ when we know the address of the .got section. */
+ if (h->type == STT_FUNC
+ || h->needs_plt)
+ {
+ if (! info->shared
+ && !h->def_dynamic
+ && !h->ref_dynamic
+ && h->root.type != bfd_link_hash_undefweak
+ && h->root.type != bfd_link_hash_undefined)
+ {
+ /* This case can occur if we saw a PLT reloc in an input
+ file, but the symbol was never referred to by a dynamic
+ object. In such a case, we don't actually need to build
+ a procedure linkage table, and we can just do a PCREL
+ reloc instead. */
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+
+ return TRUE;
+ }
+ else
+ h->plt.offset = (bfd_vma) -1;
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->u.weakdef != NULL)
+ {
+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ return TRUE;
+ }
+
+ /* This is a reference to a symbol defined by a dynamic object which
+ is not a function. */
+
+ /* If we are creating a shared library, we must presume that the
+ 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)
+ 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;
+
+ /* If -z nocopyreloc was given, we won't generate them either. */
+ if (info->nocopyreloc)
+ {
+ h->non_got_ref = 0;
+ return TRUE;
+ }
+
+ eh = (struct elf_m32r_link_hash_entry *) h;
+ for (p = eh->dyn_relocs; p != NULL; p = p->next)
+ {
+ s = p->sec->output_section;
+ if (s != NULL && (s->flags & (SEC_READONLY | SEC_HAS_CONTENTS)) != 0)
+ break;
+ }
+
+ /* If we didn't find any dynamic relocs in sections which needs the
+ copy reloc, then we'll be keeping the dynamic relocs and avoiding
+ the copy reloc. */
+ if (p == NULL)
+ {
+ h->non_got_ref = 0;
+ return TRUE;
+ }
+
+ if (h->size == 0)
+ {
+ (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
+ h->root.root.string);
+ return TRUE;
+ }
+
+ /* We must allocate the symbol in our .dynbss section, which will
+ become part of the .bss section of the executable. There will be
+ an entry for this symbol in the .dynsym section. The dynamic
+ object will contain position independent code, so all references
+ from the dynamic object to this symbol will go through the global
+ offset table. The dynamic linker will use the .dynsym entry to
+ determine the address it must put in the global offset table, so
+ both the dynamic object and the regular object will refer to the
+ same memory location for the variable. */
+
+ htab = m32r_elf_hash_table (info);
+ s = htab->sdynbss;
+ BFD_ASSERT (s != NULL);
+
+ /* We must generate a R_M32R_COPY reloc to tell the dynamic linker
+ to copy the initial value out of the dynamic object and into the
+ runtime process image. We need to remember the offset into the
+ .rela.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ {
+ asection *srel;
+
+ srel = htab->srelbss;
+ BFD_ASSERT (srel != NULL);
+ srel->size += sizeof (Elf32_External_Rela);
+ h->needs_copy = 1;
+ }
+
+ return _bfd_elf_adjust_dynamic_copy (h, s);
+}
+
+/* Allocate space in .plt, .got and associated reloc sections for
+ dynamic relocs. */
+
+static bfd_boolean
+allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
+{
+ struct bfd_link_info *info;
+ struct elf_m32r_link_hash_table *htab;
+ struct elf_m32r_link_hash_entry *eh;
+ struct elf_m32r_dyn_relocs *p;
+
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
+
+ if (h->root.type == bfd_link_hash_warning)
+ /* When warning symbols are created, they **replace** the "real"
+ entry in the hash table, thus we never get to see the real
+ symbol in a hash traversal. So look at it now. */
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ info = (struct bfd_link_info *) inf;
+ htab = m32r_elf_hash_table (info);
+
+ eh = (struct elf_m32r_link_hash_entry *) h;
+
+ if (htab->root.dynamic_sections_created
+ && h->plt.refcount > 0)
+ {
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
+ {
+ asection *s = htab->splt;
+
+ /* If this is the first .plt entry, make room for the special
+ first entry. */
+ if (s->size == 0)
+ s->size += PLT_ENTRY_SIZE;
+
+ h->plt.offset = s->size;
+
+ /* If this symbol is not defined in a regular file, and we are
+ not generating a shared library, then set the symbol to this
+ 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
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = h->plt.offset;
+ }
+
+ /* Make room for this entry. */
+ s->size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .got.plt section, which
+ will be placed in the .got section by the linker script. */
+ htab->sgotplt->size += 4;
+
+ /* We also need to make an entry in the .rel.plt section. */
+ htab->srelplt->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->needs_plt = 0;
+ }
+
+ if (h->got.refcount > 0)
+ {
+ asection *s;
+ bfd_boolean dyn;
+
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+
+ s = htab->sgot;
+
+ h->got.offset = s->size;
+ s->size += 4;
+ dyn = htab->root.dynamic_sections_created;
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h))
+ htab->srelgot->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ h->got.offset = (bfd_vma) -1;