X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf64-mips.c;h=312c976db1ab8cb72ee39252e1c9ed904eb9dad0;hb=f8076f98aa05ef1882adf4c9efb77a4a7a539e25;hp=ee5bce6619c698e28114f93ff9c1e84da29cfb72;hpb=7fd91fe0bb0c693070dcfb0f1dcc5a91f393d440;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index ee5bce6619..312c976db1 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -1,25 +1,27 @@ /* MIPS-specific support for 64-bit ELF - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007, 2008 Free Software Foundation, Inc. Ian Lance Taylor, Cygnus Support Linker support added by Mark Mitchell, CodeSourcery, LLC. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file supports the 64-bit MIPS ELF ABI. @@ -40,8 +42,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. . the OldABI version is still lying around and should be removed. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "aout/ar.h" #include "bfdlink.h" @@ -112,8 +114,6 @@ static bfd_reloc_status_type mips_elf64_gprel32_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type mips_elf64_shift6_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); -static bfd_reloc_status_type mips16_jump_reloc - (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_reloc_status_type mips16_gprel_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_boolean mips_elf64_assign_gp @@ -791,6 +791,21 @@ static reloc_howto_type mips_elf64_howto_table_rel[] = 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ + + /* 32 bit relocation with no addend. */ + HOWTO (R_MIPS_GLOB_DAT, /* 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_GLOB_DAT", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ }; /* The relocation table used for SHT_RELA sections. */ @@ -1313,8 +1328,34 @@ static reloc_howto_type mips_elf64_howto_table_rela[] = /* 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), + + 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 */ @@ -1391,8 +1432,22 @@ static reloc_howto_type mips_elf64_howto_table_rela[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ + /* TLS IE dynamic relocations. */ EMPTY_HOWTO (R_MIPS_TLS_TPREL32), - EMPTY_HOWTO (R_MIPS_TLS_TPREL64), + + 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 */ @@ -1423,6 +1478,21 @@ static reloc_howto_type mips_elf64_howto_table_rela[] = 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ + + /* 32 bit relocation with no addend. */ + HOWTO (R_MIPS_GLOB_DAT, /* 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_GLOB_DAT", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ }; static reloc_howto_type mips16_elf64_howto_table_rel[] = @@ -1438,7 +1508,7 @@ static reloc_howto_type mips16_elf64_howto_table_rel[] = /* This needs complex overflow detection, because the upper four bits must match the PC. */ - mips16_jump_reloc, /* special_function */ + _bfd_mips_elf_generic_reloc, /* special_function */ "R_MIPS16_26", /* name */ TRUE, /* partial_inplace */ 0x3ffffff, /* src_mask */ @@ -1460,11 +1530,35 @@ static reloc_howto_type mips16_elf64_howto_table_rel[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* A placeholder for MIPS16 reference to global offset table. */ - EMPTY_HOWTO (R_MIPS16_GOT16), + /* A MIPS16 reference to the global offset table. */ + HOWTO (R_MIPS16_GOT16, /* 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_got16_reloc, /* special_function */ + "R_MIPS16_GOT16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - /* A placeholder for MIPS16 16 bit call through global offset table. */ - EMPTY_HOWTO (R_MIPS16_CALL16), + /* A MIPS16 call through the global offset table. */ + HOWTO (R_MIPS16_CALL16, /* 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_generic_reloc, /* special_function */ + "R_MIPS16_CALL16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* MIPS16 high 16 bits of symbol value. */ HOWTO (R_MIPS16_HI16, /* type */ @@ -1510,7 +1604,7 @@ static reloc_howto_type mips16_elf64_howto_table_rela[] = /* This needs complex overflow detection, because the upper four bits must match the PC. */ - mips16_jump_reloc, /* special_function */ + _bfd_mips_elf_generic_reloc, /* special_function */ "R_MIPS16_26", /* name */ FALSE, /* partial_inplace */ 0x3ffffff, /* src_mask */ @@ -1532,11 +1626,35 @@ static reloc_howto_type mips16_elf64_howto_table_rela[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* A placeholder for MIPS16 reference to global offset table. */ - EMPTY_HOWTO (R_MIPS16_GOT16), + /* A MIPS16 reference to the global offset table. */ + HOWTO (R_MIPS16_GOT16, /* 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_got16_reloc, /* special_function */ + "R_MIPS16_GOT16", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - /* A placeholder for MIPS16 16 bit call through global offset table. */ - EMPTY_HOWTO (R_MIPS16_CALL16), + /* A MIPS16 call through the global offset table. */ + HOWTO (R_MIPS16_CALL16, /* 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_generic_reloc, /* special_function */ + "R_MIPS16_CALL16", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* MIPS16 high 16 bits of symbol value. */ HOWTO (R_MIPS16_HI16, /* type */ @@ -1633,6 +1751,38 @@ static reloc_howto_type elf_mips_gnu_rela16_s2 = 0x0000ffff, /* dst_mask */ TRUE); /* pcrel_offset */ +/* Originally a VxWorks extension, but now used for other systems too. */ +static reloc_howto_type elf_mips_copy_howto = + HOWTO (R_MIPS_COPY, /* type */ + 0, /* rightshift */ + 0, /* this one is variable size */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_COPY", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE); /* pcrel_offset */ + +/* Originally a VxWorks extension, but now used for other systems too. */ +static reloc_howto_type elf_mips_jump_slot_howto = + HOWTO (R_MIPS_JUMP_SLOT, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_JUMP_SLOT", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE); /* pcrel_offset */ + /* Swap in a MIPS 64-bit Rel reloc. */ static void @@ -2044,37 +2194,6 @@ mips_elf64_shift6_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, error_message); } -/* Handle a mips16 jump. */ - -static bfd_reloc_status_type -mips16_jump_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry, - asymbol *symbol, void *data ATTRIBUTE_UNUSED, - asection *input_section, bfd *output_bfd, - char **error_message ATTRIBUTE_UNUSED) -{ - if (output_bfd != NULL - && (symbol->flags & BSF_SECTION_SYM) == 0 - && (! reloc_entry->howto->partial_inplace - || reloc_entry->addend == 0)) - { - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; - } - - /* FIXME. */ - { - static bfd_boolean warned; - - if (! warned) - (*_bfd_error_handler) - (_("Linking mips16 objects into %s format is not supported"), - bfd_get_target (input_section->output_section->owner)); - warned = TRUE; - } - - return bfd_reloc_undefined; -} - /* Handle a mips16 GP relative reloc. */ static bfd_reloc_status_type @@ -2185,6 +2304,8 @@ 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_GOT16, R_MIPS16_GOT16 - R_MIPS16_min }, + { BFD_RELOC_MIPS16_CALL16, R_MIPS16_CALL16 - R_MIPS16_min }, { BFD_RELOC_MIPS16_HI16_S, R_MIPS16_HI16 - R_MIPS16_min }, { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min }, }; @@ -2221,12 +2342,53 @@ bfd_elf64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, return &elf_mips_gnu_vtinherit_howto; case BFD_RELOC_VTABLE_ENTRY: return &elf_mips_gnu_vtentry_howto; + case BFD_RELOC_MIPS_COPY: + return &elf_mips_copy_howto; + case BFD_RELOC_MIPS_JUMP_SLOT: + return &elf_mips_jump_slot_howto; default: bfd_set_error (bfd_error_bad_value); return NULL; } } +static reloc_howto_type * +bfd_elf64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < (sizeof (mips_elf64_howto_table_rela) + / sizeof (mips_elf64_howto_table_rela[0])); i++) + if (mips_elf64_howto_table_rela[i].name != NULL + && strcasecmp (mips_elf64_howto_table_rela[i].name, r_name) == 0) + return &mips_elf64_howto_table_rela[i]; + + for (i = 0; + i < (sizeof (mips16_elf64_howto_table_rela) + / sizeof (mips16_elf64_howto_table_rela[0])); + i++) + if (mips16_elf64_howto_table_rela[i].name != NULL + && strcasecmp (mips16_elf64_howto_table_rela[i].name, r_name) == 0) + return &mips16_elf64_howto_table_rela[i]; + + if (strcasecmp (elf_mips_gnu_vtinherit_howto.name, r_name) == 0) + return &elf_mips_gnu_vtinherit_howto; + if (strcasecmp (elf_mips_gnu_vtentry_howto.name, r_name) == 0) + return &elf_mips_gnu_vtentry_howto; + if (strcasecmp (elf_mips_gnu_rel16_s2.name, r_name) == 0) + return &elf_mips_gnu_rel16_s2; + if (strcasecmp (elf_mips_gnu_rela16_s2.name, r_name) == 0) + return &elf_mips_gnu_rela16_s2; + if (strcasecmp (elf_mips_copy_howto.name, r_name) == 0) + return &elf_mips_copy_howto; + if (strcasecmp (elf_mips_jump_slot_howto.name, r_name) == 0) + return &elf_mips_jump_slot_howto; + + return NULL; +} + /* Given a MIPS Elf_Internal_Rel, fill in an arelent structure. */ static reloc_howto_type * @@ -2243,6 +2405,10 @@ mips_elf64_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p) return &elf_mips_gnu_rela16_s2; else return &elf_mips_gnu_rel16_s2; + case R_MIPS_COPY: + return &elf_mips_copy_howto; + case R_MIPS_JUMP_SLOT: + return &elf_mips_jump_slot_howto; default: if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max) { @@ -3025,6 +3191,7 @@ const struct elf_size_info mips_elf64_size_info = EV_CURRENT, bfd_elf64_write_out_phdrs, bfd_elf64_write_shdrs_and_ehdr, + bfd_elf64_checksum_contents, mips_elf64_write_relocs, bfd_elf64_swap_symbol_in, bfd_elf64_swap_symbol_out, @@ -3059,12 +3226,16 @@ const struct elf_size_info mips_elf64_size_info = #define elf_backend_create_dynamic_sections \ _bfd_mips_elf_create_dynamic_sections #define elf_backend_check_relocs _bfd_mips_elf_check_relocs +#define elf_backend_merge_symbol_attribute \ + _bfd_mips_elf_merge_symbol_attribute +#define elf_backend_get_target_dtag _bfd_mips_elf_get_target_dtag #define elf_backend_adjust_dynamic_symbol \ _bfd_mips_elf_adjust_dynamic_symbol #define elf_backend_always_size_sections \ _bfd_mips_elf_always_size_sections #define elf_backend_size_dynamic_sections \ _bfd_mips_elf_size_dynamic_sections +#define elf_backend_init_index_section _bfd_elf_init_1_index_section #define elf_backend_relocate_section _bfd_mips_elf_relocate_section #define elf_backend_finish_dynamic_symbol \ _bfd_mips_elf_finish_dynamic_symbol @@ -3079,7 +3250,6 @@ const struct elf_size_info mips_elf64_size_info = #define elf_backend_gc_sweep_hook _bfd_mips_elf_gc_sweep_hook #define elf_backend_copy_indirect_symbol \ _bfd_mips_elf_copy_indirect_symbol -#define elf_backend_hide_symbol _bfd_mips_elf_hide_symbol #define elf_backend_ignore_discarded_relocs \ _bfd_mips_elf_ignore_discarded_relocs #define elf_backend_mips_irix_compat elf64_mips_irix_compat @@ -3097,6 +3267,11 @@ const struct elf_size_info mips_elf64_size_info = #define elf_backend_may_use_rel_p 1 #define elf_backend_may_use_rela_p 1 #define elf_backend_default_use_rela_p 1 +#define elf_backend_rela_plts_and_copies_p 0 +#define elf_backend_plt_readonly 1 +#define elf_backend_plt_sym_val _bfd_mips_elf_plt_sym_val + +#define elf_backend_sign_extend_vma TRUE #define elf_backend_write_section _bfd_mips_elf_write_section @@ -3109,6 +3284,7 @@ const struct elf_size_info mips_elf64_size_info = #define bfd_elf64_set_section_contents _bfd_mips_elf_set_section_contents #define bfd_elf64_bfd_get_relocated_section_contents \ _bfd_elf_mips_get_relocated_section_contents +#define bfd_elf64_mkobject _bfd_mips_elf_mkobject #define bfd_elf64_bfd_link_hash_table_create \ _bfd_mips_elf_link_hash_table_create #define bfd_elf64_bfd_final_link _bfd_mips_elf_final_link