diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2010-10-19 21:13:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2010-10-19 21:13:25 +0000 |
commit | 7a815afd9b5121ee0f65dc1e1de1c0de6de97679 (patch) | |
tree | f61b968a46c92e81f6de581582cb064bf9dca27d /bfd/elfn32-mips.c | |
parent | 42f6b9ffef1927d55d15075d9e810435c590c404 (diff) | |
download | src-7a815afd9b5121ee0f65dc1e1de1c0de6de97679.tar.gz src-7a815afd9b5121ee0f65dc1e1de1c0de6de97679.zip |
Import the binutils-2_17-branch from the sourceware CVS repository,vendor/binutils/binutils-2_17-branch-20070807-000013
exactly as it was on Tue, 7 Aug 2007 00:00:13 +0000.
Corresponds to git commit b458c361f01f7a257f897d0961d0a379ee999aaa.
This is currently (and most likely forever :) the last commit on this
branch.
Notes
Notes:
svn path=/vendor/binutils/dist/; revision=214082
svn path=/vendor/binutils/binutils-2_17-branch-20070807-000013/; revision=214098; tag=vendor/binutils/binutils-2_17-branch-20070807-000013
Diffstat (limited to 'bfd/elfn32-mips.c')
-rw-r--r-- | bfd/elfn32-mips.c | 592 |
1 files changed, 509 insertions, 83 deletions
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c index 973edd52daf7..b1211f0c65e5 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -1,6 +1,6 @@ /* MIPS-specific support for 32-bit ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003 Free Software Foundation, Inc. + 2003, 2004, 2005 Free Software Foundation, Inc. Most of the information added by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>. @@ -23,7 +23,7 @@ GNU General Public License for more details. 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 handles MIPS ELF targets. SGI Irix 5 uses a slightly different MIPS ELF from other targets. This matters when linking. @@ -262,9 +262,11 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit PC relative reference. */ + /* 16 bit PC relative reference. Note that the ABI document has a typo + and claims R_MIPS_PC16 to be not rightshifted, rendering it useless. + We do the right thing here. */ HOWTO (R_MIPS_PC16, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ @@ -502,7 +504,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = a) It means building the addend from a R_MIPS_HIGHEST/R_MIPS_HIGHER/ R_MIPS_HI16/R_MIPS_LO16 sequence with varying ordering, using fallable heuristics. - b) No other NEwABI toolchain actually emits such relocations. */ + b) No other NewABI toolchain actually emits such relocations. */ EMPTY_HOWTO (R_MIPS_HIGHER), EMPTY_HOWTO (R_MIPS_HIGHEST), @@ -600,6 +602,160 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0x00000000, /* src_mask */ 0x00000000, /* dst_mask */ FALSE), /* pcrel_offset */ + + /* TLS GD/LD dynamic relocations. */ + HOWTO (R_MIPS_TLS_DTPMOD32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_TLS_DTPMOD32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_MIPS_TLS_DTPREL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_TLS_DTPREL32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + 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 */ + + /* TLS IE dynamic relocations. */ + HOWTO (R_MIPS_TLS_TPREL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_TLS_TPREL32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + 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 relocation table used for SHT_RELA sections. */ @@ -759,9 +915,11 @@ static reloc_howto_type elf_mips_howto_table_rela[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit PC relative reference. */ + /* 16 bit PC relative reference. Note that the ABI document has a typo + and claims R_MIPS_PC16 to be not rightshifted, rendering it useless. + We do the right thing here. */ HOWTO (R_MIPS_PC16, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ @@ -1115,12 +1273,167 @@ static reloc_howto_type elf_mips_howto_table_rela[] = "R_MIPS_JALR", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS GD/LD dynamic relocations. */ + HOWTO (R_MIPS_TLS_DTPMOD32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_TLS_DTPMOD32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ + + HOWTO (R_MIPS_TLS_DTPREL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_TLS_DTPREL32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + 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 */ + + /* TLS IE dynamic relocations. */ + HOWTO (R_MIPS_TLS_TPREL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_TLS_TPREL32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + 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 elf_mips16_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) */ @@ -1136,10 +1449,9 @@ static reloc_howto_type elf_mips16_jump_howto = 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) */ @@ -1150,9 +1462,118 @@ static reloc_howto_type elf_mips16_gprel_howto = 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 elf_mips16_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 = @@ -1348,6 +1769,16 @@ mips_elf_literal_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, bfd_reloc_status_type ret; bfd_vma gp; + /* 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) + { + *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. */ if (output_bfd != NULL) relocatable = TRUE; @@ -1425,7 +1856,7 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; - if (reloc_entry->address > input_section->_cooked_size) + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) return bfd_reloc_outofrange; if (reloc_entry->howto->src_mask == 0) @@ -1501,11 +1932,18 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, { 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, we don't want + to change anything. */ + 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; + } if (output_bfd != NULL) relocatable = TRUE; @@ -1520,55 +1958,16 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, if (ret != bfd_reloc_ok) return ret; - if (reloc_entry->address > input_section->_cooked_size) - 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; } /* A mapping from BFD reloc types to MIPS ELF reloc types. */ @@ -1586,7 +1985,7 @@ static const struct elf_reloc_map mips_reloc_map[] = /* There is no BFD reloc for R_MIPS_REL32. */ { BFD_RELOC_CTOR, R_MIPS_32 }, { BFD_RELOC_64, R_MIPS_64 }, - { BFD_RELOC_16_PCREL, R_MIPS_PC16 }, + { BFD_RELOC_16_PCREL_S2, R_MIPS_PC16 }, { BFD_RELOC_HI16_S, R_MIPS_HI16 }, { BFD_RELOC_LO16, R_MIPS_LO16 }, { BFD_RELOC_GPREL16, R_MIPS_GPREL16 }, @@ -1614,7 +2013,28 @@ static const struct elf_reloc_map mips_reloc_map[] = { 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. */ @@ -1627,6 +2047,7 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, /* FIXME: We default to RELA here instead of choosing the right relocation variant. */ reloc_howto_type *howto_table = elf_mips_howto_table_rela; + reloc_howto_type *howto16_table = elf_mips16_howto_table_rela; for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++) @@ -1635,18 +2056,19 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 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: return &elf_mips_gnu_vtentry_howto; - case BFD_RELOC_16_PCREL_S2: - return &elf_mips_gnu_rela16_s2; default: bfd_set_error (bfd_error_bad_value); return NULL; @@ -1660,10 +2082,6 @@ mips_elf_n32_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p) { 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: @@ -1674,6 +2092,13 @@ mips_elf_n32_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p) else return &elf_mips_gnu_rel16_s2; default: + if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max) + { + if (rela_p) + return &elf_mips16_howto_table_rela[r_type - R_MIPS16_min]; + else + return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min]; + } BFD_ASSERT (r_type < (unsigned int) R_MIPS_max); if (rela_p) return &elf_mips_howto_table_rela[r_type]; @@ -1760,7 +2185,7 @@ static bfd_boolean elf32_mips_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; - unsigned int raw_size; + unsigned int size; switch (note->descsz) { @@ -1776,13 +2201,13 @@ elf32_mips_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) /* pr_reg */ offset = 72; - raw_size = 360; + size = 360; break; } /* Make a ".reg/999" section. */ - return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size, + return _bfd_elfcore_make_pseudosection (abfd, ".reg", size, note->descpos + offset); } @@ -1933,6 +2358,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { #define elf_backend_mips_irix_compat elf_n32_mips_irix_compat #define elf_backend_mips_rtype_to_howto mips_elf_n32_rtype_to_howto #define bfd_elf32_find_nearest_line _bfd_mips_elf_find_nearest_line +#define bfd_elf32_find_inliner_info _bfd_mips_elf_find_inliner_info #define bfd_elf32_new_section_hook _bfd_mips_elf_new_section_hook #define bfd_elf32_set_section_contents _bfd_mips_elf_set_section_contents #define bfd_elf32_bfd_get_relocated_section_contents \ |