/* MIPS-specific support for 64-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Ian Lance Taylor, Cygnus Support
Linker support added by Mark Mitchell, CodeSourcery, LLC.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/* This file supports the 64-bit MIPS ELF ABI.
/* Protected jump conversion. This is an optimization hint. No
relocation is required for correctness. */
- HOWTO (R_MIPS_JALR, /* type */
+ HOWTO (R_MIPS_JALR, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
_bfd_mips_elf_generic_reloc, /* special_function */
- "R_MIPS_JALR", /* name */
+ "R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x00000000, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ /* TLS relocations. */
+ EMPTY_HOWTO (R_MIPS_TLS_DTPMOD32),
+ EMPTY_HOWTO (R_MIPS_TLS_DTPREL32),
+
+ HOWTO (R_MIPS_TLS_DTPMOD64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_DTPMOD64", /* name */
+ TRUE, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MIPS_TLS_DTPREL64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_DTPREL64", /* name */
+ TRUE, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS general dynamic variable reference. */
+ HOWTO (R_MIPS_TLS_GD, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_GD", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS local dynamic variable reference. */
+ HOWTO (R_MIPS_TLS_LDM, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_LDM", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS local dynamic offset. */
+ HOWTO (R_MIPS_TLS_DTPREL_HI16, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_DTPREL_HI16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS local dynamic offset. */
+ HOWTO (R_MIPS_TLS_DTPREL_LO16, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_DTPREL_LO16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS thread pointer offset. */
+ HOWTO (R_MIPS_TLS_GOTTPREL, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_GOTTPREL", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS IE dynamic relocations. */
+ EMPTY_HOWTO (R_MIPS_TLS_TPREL32),
+
+ HOWTO (R_MIPS_TLS_TPREL64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ _bfd_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_TPREL64", /* name */
+ TRUE, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS thread pointer offset. */
+ HOWTO (R_MIPS_TLS_TPREL_HI16, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_TPREL_HI16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS thread pointer offset. */
+ HOWTO (R_MIPS_TLS_TPREL_LO16, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_TPREL_LO16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
/* The relocation table used for SHT_RELA sections. */
/* Protected jump conversion. This is an optimization hint. No
relocation is required for correctness. */
- HOWTO (R_MIPS_JALR, /* type */
+ HOWTO (R_MIPS_JALR, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
_bfd_mips_elf_generic_reloc, /* special_function */
- "R_MIPS_JALR", /* name */
+ "R_MIPS_JALR", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0x00000000, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ /* TLS relocations. */
+ EMPTY_HOWTO (R_MIPS_TLS_DTPMOD32),
+ EMPTY_HOWTO (R_MIPS_TLS_DTPREL32),
+ EMPTY_HOWTO (R_MIPS_TLS_DTPMOD64),
+ EMPTY_HOWTO (R_MIPS_TLS_DTPREL64),
+
+ /* TLS general dynamic variable reference. */
+ HOWTO (R_MIPS_TLS_GD, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_GD", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS local dynamic variable reference. */
+ HOWTO (R_MIPS_TLS_LDM, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_LDM", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS local dynamic offset. */
+ HOWTO (R_MIPS_TLS_DTPREL_HI16, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_DTPREL_HI16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS local dynamic offset. */
+ HOWTO (R_MIPS_TLS_DTPREL_LO16, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_DTPREL_LO16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS thread pointer offset. */
+ HOWTO (R_MIPS_TLS_GOTTPREL, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_GOTTPREL", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ EMPTY_HOWTO (R_MIPS_TLS_TPREL32),
+ EMPTY_HOWTO (R_MIPS_TLS_TPREL64),
+
+ /* TLS thread pointer offset. */
+ HOWTO (R_MIPS_TLS_TPREL_HI16, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_TPREL_HI16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TLS thread pointer offset. */
+ HOWTO (R_MIPS_TLS_TPREL_LO16, /* 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_mips_elf_generic_reloc, /* special_function */
+ "R_MIPS_TLS_TPREL_LO16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
-/* The reloc used for the mips16 jump instruction. */
-static reloc_howto_type elf_mips16_jump_howto =
+static reloc_howto_type mips16_elf64_howto_table_rel[] =
+{
+ /* The reloc used for the mips16 jump instruction. */
HOWTO (R_MIPS16_26, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
TRUE, /* partial_inplace */
0x3ffffff, /* src_mask */
0x3ffffff, /* dst_mask */
- FALSE); /* pcrel_offset */
+ FALSE), /* pcrel_offset */
-/* The reloc used for the mips16 gprel instruction. */
-static reloc_howto_type elf_mips16_gprel_howto =
+ /* The reloc used for the mips16 gprel instruction. */
HOWTO (R_MIPS16_GPREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
mips16_gprel_reloc, /* special_function */
"R_MIPS16_GPREL", /* name */
TRUE, /* partial_inplace */
- 0x07ff001f, /* src_mask */
- 0x07ff001f, /* dst_mask */
- FALSE); /* pcrel_offset */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A placeholder for MIPS16 reference to global offset table. */
+ EMPTY_HOWTO (R_MIPS16_GOT16),
+
+ /* A placeholder for MIPS16 16 bit call through global offset table. */
+ EMPTY_HOWTO (R_MIPS16_CALL16),
+
+ /* MIPS16 high 16 bits of symbol value. */
+ HOWTO (R_MIPS16_HI16, /* 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_mips_elf_hi16_reloc, /* special_function */
+ "R_MIPS16_HI16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* MIPS16 low 16 bits of symbol value. */
+ HOWTO (R_MIPS16_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 */
+ _bfd_mips_elf_lo16_reloc, /* special_function */
+ "R_MIPS16_LO16", /* name */
+ TRUE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+};
+
+static reloc_howto_type mips16_elf64_howto_table_rela[] =
+{
+ /* The reloc used for the mips16 jump instruction. */
+ HOWTO (R_MIPS16_26, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ /* This needs complex overflow
+ detection, because the upper four
+ bits must match the PC. */
+ mips16_jump_reloc, /* special_function */
+ "R_MIPS16_26", /* name */
+ FALSE, /* partial_inplace */
+ 0x3ffffff, /* src_mask */
+ 0x3ffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The reloc used for the mips16 gprel instruction. */
+ HOWTO (R_MIPS16_GPREL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips16_gprel_reloc, /* special_function */
+ "R_MIPS16_GPREL", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A placeholder for MIPS16 reference to global offset table. */
+ EMPTY_HOWTO (R_MIPS16_GOT16),
+
+ /* A placeholder for MIPS16 16 bit call through global offset table. */
+ EMPTY_HOWTO (R_MIPS16_CALL16),
+
+ /* MIPS16 high 16 bits of symbol value. */
+ HOWTO (R_MIPS16_HI16, /* 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_mips_elf_hi16_reloc, /* special_function */
+ "R_MIPS16_HI16", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* MIPS16 low 16 bits of symbol value. */
+ HOWTO (R_MIPS16_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 */
+ _bfd_mips_elf_lo16_reloc, /* special_function */
+ "R_MIPS16_LO16", /* name */
+ FALSE, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+};
/* GNU extension to record C++ vtable hierarchy */
static reloc_howto_type elf_mips_gnu_vtinherit_howto =
mirel.r_offset = src[0].r_offset;
BFD_ASSERT(src[0].r_offset == src[1].r_offset);
-#if 0
- BFD_ASSERT(src[0].r_offset == src[2].r_offset);
-#endif
mirel.r_type = ELF64_MIPS_R_TYPE (src[0].r_info);
mirel.r_sym = ELF64_R_SYM (src[0].r_info);
bfd_reloc_status_type ret;
bfd_vma gp;
- /* If we're relocating, and this is an external symbol, we don't
- want to change anything. */
+ /* R_MIPS_LITERAL relocations are defined for local symbols only. */
if (output_bfd != NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (symbol->flags & BSF_LOCAL) != 0)
{
- reloc_entry->address += input_section->output_offset;
- return bfd_reloc_ok;
+ *error_message = (char *)
+ _("literal relocation occurs for an external symbol");
+ return bfd_reloc_outofrange;
}
/* FIXME: The entries in the .lit8 and .lit4 sections should be merged. */
bfd_vma relocation;
bfd_vma val;
- /* If we're relocating, and this is an external symbol, we don't want
- to change anything. */
+ /* R_MIPS_GPREL32 relocations are defined for local symbols only. */
if (output_bfd != NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (symbol->flags & BSF_LOCAL) != 0)
output_bfd = symbol->section->output_section->owner;
}
- ret = mips_elf64_final_gp (output_bfd, symbol, relocatable,
- error_message, &gp);
- if (ret != bfd_reloc_ok)
- return ret;
+ ret = mips_elf64_final_gp (output_bfd, symbol, relocatable,
+ error_message, &gp);
+ if (ret != bfd_reloc_ok)
+ return ret;
if (bfd_is_com_section (symbol->section))
relocation = 0;
{
bfd_boolean relocatable;
bfd_reloc_status_type ret;
+ bfd_byte *location;
bfd_vma gp;
- unsigned short extend = 0;
- unsigned short insn = 0;
- bfd_signed_vma val;
- bfd_vma relocation;
- /* If we're relocating, and this is an external symbol with no
- addend, we don't want to change anything. */
+ /* If we're relocating, and this is an external symbol, we don't want
+ to change anything. */
if (output_bfd != NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (symbol->flags & BSF_LOCAL) != 0)
if (ret != bfd_reloc_ok)
return ret;
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
- return bfd_reloc_outofrange;
+ location = (bfd_byte *) data + reloc_entry->address;
+ _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE,
+ location);
+ ret = _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry,
+ input_section, relocatable,
+ data, gp);
+ _bfd_mips16_elf_reloc_shuffle (abfd, reloc_entry->howto->type, !relocatable,
+ location);
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
-
- /* Set val to the offset into the section or symbol. */
- val = reloc_entry->addend;
-
- if (reloc_entry->howto->partial_inplace)
- {
- /* Pick up the mips16 extend instruction and the real instruction. */
- extend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address);
- insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2);
- val += ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
- }
-
- _bfd_mips_elf_sign_extend(val, 16);
-
- /* Adjust val for the final section location and GP value. If we
- are producing relocatable output, we don't want to do this for
- an external symbol. */
- if (! relocatable
- || (symbol->flags & BSF_SECTION_SYM) != 0)
- val += relocation - gp;
-
- if (reloc_entry->howto->partial_inplace)
- {
- bfd_put_16 (abfd,
- (extend & 0xf800) | ((val >> 11) & 0x1f) | (val & 0x7e0),
- (bfd_byte *) data + reloc_entry->address);
- bfd_put_16 (abfd,
- (insn & 0xffe0) | (val & 0x1f),
- (bfd_byte *) data + reloc_entry->address + 2);
- }
- else
- reloc_entry->addend = val;
-
- if (relocatable)
- reloc_entry->address += input_section->output_offset;
- else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
- return bfd_reloc_overflow;
-
- return bfd_reloc_ok;
+ return ret;
}
\f
/* A mapping from BFD reloc types to MIPS ELF reloc types. */
{ BFD_RELOC_MIPS_REL16, R_MIPS_REL16 },
/* Use of R_MIPS_ADD_IMMEDIATE and R_MIPS_PJUMP is deprecated. */
{ BFD_RELOC_MIPS_RELGOT, R_MIPS_RELGOT },
- { BFD_RELOC_MIPS_JALR, R_MIPS_JALR }
+ { BFD_RELOC_MIPS_JALR, R_MIPS_JALR },
+ { BFD_RELOC_MIPS_TLS_DTPMOD32, R_MIPS_TLS_DTPMOD32 },
+ { BFD_RELOC_MIPS_TLS_DTPREL32, R_MIPS_TLS_DTPREL32 },
+ { BFD_RELOC_MIPS_TLS_DTPMOD64, R_MIPS_TLS_DTPMOD64 },
+ { BFD_RELOC_MIPS_TLS_DTPREL64, R_MIPS_TLS_DTPREL64 },
+ { BFD_RELOC_MIPS_TLS_GD, R_MIPS_TLS_GD },
+ { BFD_RELOC_MIPS_TLS_LDM, R_MIPS_TLS_LDM },
+ { BFD_RELOC_MIPS_TLS_DTPREL_HI16, R_MIPS_TLS_DTPREL_HI16 },
+ { BFD_RELOC_MIPS_TLS_DTPREL_LO16, R_MIPS_TLS_DTPREL_LO16 },
+ { BFD_RELOC_MIPS_TLS_GOTTPREL, R_MIPS_TLS_GOTTPREL },
+ { BFD_RELOC_MIPS_TLS_TPREL32, R_MIPS_TLS_TPREL32 },
+ { BFD_RELOC_MIPS_TLS_TPREL64, R_MIPS_TLS_TPREL64 },
+ { BFD_RELOC_MIPS_TLS_TPREL_HI16, R_MIPS_TLS_TPREL_HI16 },
+ { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }
+};
+
+static const struct elf_reloc_map mips16_reloc_map[] =
+{
+ { BFD_RELOC_MIPS16_JMP, R_MIPS16_26 - R_MIPS16_min },
+ { BFD_RELOC_MIPS16_GPREL, R_MIPS16_GPREL - R_MIPS16_min },
+ { BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min },
+ { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min },
};
/* Given a BFD reloc type, return a howto structure. */
/* FIXME: We default to RELA here instead of choosing the right
relocation variant. */
reloc_howto_type *howto_table = mips_elf64_howto_table_rela;
+ reloc_howto_type *howto16_table = mips16_elf64_howto_table_rela;
for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map);
i++)
return &howto_table[(int) mips_reloc_map[i].elf_val];
}
+ for (i = 0; i < sizeof (mips16_reloc_map) / sizeof (struct elf_reloc_map);
+ i++)
+ {
+ if (mips16_reloc_map[i].bfd_val == code)
+ return &howto16_table[(int) mips16_reloc_map[i].elf_val];
+ }
+
switch (code)
{
- case BFD_RELOC_MIPS16_JMP:
- return &elf_mips16_jump_howto;
- case BFD_RELOC_MIPS16_GPREL:
- return &elf_mips16_gprel_howto;
case BFD_RELOC_VTABLE_INHERIT:
return &elf_mips_gnu_vtinherit_howto;
case BFD_RELOC_VTABLE_ENTRY:
{
switch (r_type)
{
- case R_MIPS16_26:
- return &elf_mips16_jump_howto;
- case R_MIPS16_GPREL:
- return &elf_mips16_gprel_howto;
case R_MIPS_GNU_VTINHERIT:
return &elf_mips_gnu_vtinherit_howto;
case R_MIPS_GNU_VTENTRY:
else
return &elf_mips_gnu_rel16_s2;
default:
+ if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
+ {
+ if (rela_p)
+ return &mips16_elf64_howto_table_rela[r_type - R_MIPS16_min];
+ else
+ return &mips16_elf64_howto_table_rel[r_type - R_MIPS16_min];
+ }
BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
if (rela_p)
return &mips_elf64_howto_table_rela[r_type];
case RSS_GP0:
case RSS_LOC:
/* FIXME: I think these need to be handled using
- special howto structures. */
+ special howto structures. */
BFD_ASSERT (0);
break;
sym = *ptr->sym_ptr_ptr;
if (sym == last_sym)
n = last_sym_idx;
+ else if (bfd_is_abs_section (sym->section) && sym->value == 0)
+ n = STN_UNDEF;
else
{
last_sym = sym;
sym = *ptr->sym_ptr_ptr;
if (sym == last_sym)
n = last_sym_idx;
+ else if (bfd_is_abs_section (sym->section) && sym->value == 0)
+ n = STN_UNDEF;
else
{
last_sym = sym;
sizeof (Elf64_External_Sym),
sizeof (Elf64_External_Dyn),
sizeof (Elf_External_Note),
- 4, /* hash-table entry size */
- 3, /* internal relocations per external relocations */
+ 4, /* hash-table entry size */
+ 3, /* internal relocations per external relocations */
64, /* arch_size */
3, /* log_file_align */
ELFCLASS64,
#undef ELF_MAXPAGESIZE
-#define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
-#define TARGET_LITTLE_NAME "elf64-tradlittlemips"
-#define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
-#define TARGET_BIG_NAME "elf64-tradbigmips"
+#define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec
+#define TARGET_LITTLE_NAME "elf64-tradlittlemips"
+#define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec
+#define TARGET_BIG_NAME "elf64-tradbigmips"
/* The SVR4 MIPS ABI says that this should be 0x10000, and Linux uses
page sizes of up to that limit, so we need to respect it. */