X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf64-mips.c;h=82186252fdd07e419c1b81760d27aa1c90267a60;hb=09aca9495c4794e586680f359e612ece173148ec;hp=9981bb1c8d3d046e357b058e5a92e733414adb19;hpb=d150b1a28f157a0f75797b184fa87fd4bc6bc2ac;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index 9981bb1c8d..82186252fd 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -1,7 +1,5 @@ /* MIPS-specific support for 64-bit ELF - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1996-2018 Free Software Foundation, Inc. Ian Lance Taylor, Cygnus Support Linker support added by Mark Mitchell, CodeSourcery, LLC. @@ -88,14 +86,8 @@ static void mips_elf64_info_to_howto_rel (bfd *, arelent *, Elf_Internal_Rela *); static void mips_elf64_info_to_howto_rela (bfd *, arelent *, Elf_Internal_Rela *); -static long mips_elf64_get_reloc_upper_bound - (bfd *, asection *); -static long mips_elf64_canonicalize_reloc - (bfd *, asection *, arelent **, asymbol **); static long mips_elf64_get_dynamic_reloc_upper_bound (bfd *); -static long mips_elf64_canonicalize_dynamic_reloc - (bfd *, arelent **, asymbol **); static bfd_boolean mips_elf64_slurp_one_reloc_table (bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type, arelent *, asymbol **, bfd_boolean); @@ -130,8 +122,8 @@ static bfd_boolean elf64_mips_grok_prstatus static bfd_boolean elf64_mips_grok_psinfo (bfd *, Elf_Internal_Note *); -extern const bfd_target bfd_elf64_bigmips_vec; -extern const bfd_target bfd_elf64_littlemips_vec; +extern const bfd_target mips_elf64_be_vec; +extern const bfd_target mips_elf64_le_vec; /* In case we're on a 32-bit machine, construct a 64-bit "-1" value from smaller values. Start with zero, widen, *then* decrement. */ @@ -147,7 +139,7 @@ static reloc_howto_type mips_elf64_howto_table_rel[] = /* No relocation. */ HOWTO (R_MIPS_NONE, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -807,6 +799,100 @@ static reloc_howto_type mips_elf64_howto_table_rel[] = 0x0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ + + EMPTY_HOWTO (52), + EMPTY_HOWTO (53), + EMPTY_HOWTO (54), + EMPTY_HOWTO (55), + EMPTY_HOWTO (56), + EMPTY_HOWTO (57), + EMPTY_HOWTO (58), + EMPTY_HOWTO (59), + + HOWTO (R_MIPS_PC21_S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 21, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC21_S2", /* name */ + TRUE, /* partial_inplace */ + 0x001fffff, /* src_mask */ + 0x001fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PC26_S2, /* 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_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC26_S2", /* name */ + TRUE, /* partial_inplace */ + 0x03ffffff, /* src_mask */ + 0x03ffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PC18_S3, /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 18, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC18_S3", /* name */ + TRUE, /* partial_inplace */ + 0x0003ffff, /* src_mask */ + 0x0003ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PC19_S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC19_S2", /* name */ + TRUE, /* partial_inplace */ + 0x0007ffff, /* src_mask */ + 0x0007ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PCHI16, /* type */ + 16, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PCHI16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PCLO16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PCLO16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + }; /* The relocation table used for SHT_RELA sections. */ @@ -816,7 +902,7 @@ static reloc_howto_type mips_elf64_howto_table_rela[] = /* No relocation. */ HOWTO (R_MIPS_NONE, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -1494,6 +1580,100 @@ static reloc_howto_type mips_elf64_howto_table_rela[] = 0x0, /* src_mask */ 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ + + EMPTY_HOWTO (52), + EMPTY_HOWTO (53), + EMPTY_HOWTO (54), + EMPTY_HOWTO (55), + EMPTY_HOWTO (56), + EMPTY_HOWTO (57), + EMPTY_HOWTO (58), + EMPTY_HOWTO (59), + + HOWTO (R_MIPS_PC21_S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 21, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC21_S2", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x001fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PC26_S2, /* 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_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC26_S2", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x03ffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PC18_S3, /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 18, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC18_S3", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x0003ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PC19_S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC19_S2", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x0007ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PCHI16, /* type */ + 16, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PCHI16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MIPS_PCLO16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PCLO16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + }; static reloc_howto_type mips16_elf64_howto_table_rel[] = @@ -1506,7 +1686,7 @@ static reloc_howto_type mips16_elf64_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - /* This needs complex overflow + /* This needs complex overflow detection, because the upper four bits must match the PC. */ _bfd_mips_elf_generic_reloc, /* special_function */ @@ -1528,7 +1708,7 @@ static reloc_howto_type mips16_elf64_howto_table_rel[] = "R_MIPS16_GPREL", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A MIPS16 reference to the global offset table. */ @@ -1543,7 +1723,7 @@ static reloc_howto_type mips16_elf64_howto_table_rel[] = "R_MIPS16_GOT16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A MIPS16 call through the global offset table. */ @@ -1558,7 +1738,7 @@ static reloc_howto_type mips16_elf64_howto_table_rel[] = "R_MIPS16_CALL16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* MIPS16 high 16 bits of symbol value. */ @@ -1695,6 +1875,21 @@ static reloc_howto_type mips16_elf64_howto_table_rel[] = 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ + + /* MIPS16 16-bit PC-relative branch offset. */ + HOWTO (R_MIPS16_PC16_S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS16_PC16_S1", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ }; static reloc_howto_type mips16_elf64_howto_table_rela[] = @@ -1707,7 +1902,7 @@ static reloc_howto_type mips16_elf64_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - /* This needs complex overflow + /* This needs complex overflow detection, because the upper four bits must match the PC. */ _bfd_mips_elf_generic_reloc, /* special_function */ @@ -1729,7 +1924,7 @@ static reloc_howto_type mips16_elf64_howto_table_rela[] = "R_MIPS16_GPREL", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A MIPS16 reference to the global offset table. */ @@ -1744,7 +1939,7 @@ static reloc_howto_type mips16_elf64_howto_table_rela[] = "R_MIPS16_GOT16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* A MIPS16 call through the global offset table. */ @@ -1759,7 +1954,7 @@ static reloc_howto_type mips16_elf64_howto_table_rela[] = "R_MIPS16_CALL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x0000ffff, /* dst_mask */ + 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ /* MIPS16 high 16 bits of symbol value. */ @@ -1896,6 +2091,21 @@ static reloc_howto_type mips16_elf64_howto_table_rela[] = 0, /* src_mask */ 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ + + /* MIPS16 16-bit PC-relative branch offset. */ + HOWTO (R_MIPS16_PC16_S1, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS16_PC16_S1", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ }; static reloc_howto_type micromips_elf64_howto_table_rel[] = @@ -1912,7 +2122,7 @@ static reloc_howto_type micromips_elf64_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - /* This needs complex overflow + /* This needs complex overflow detection, because the upper four bits must match the PC. */ _bfd_mips_elf_generic_reloc, /* special_function */ @@ -2231,7 +2441,7 @@ static reloc_howto_type micromips_elf64_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - /* This needs complex overflow + /* This needs complex overflow detection, because the upper four bits must match the PC. */ _bfd_mips_elf_generic_reloc, /* special_function */ @@ -2622,6 +2832,23 @@ static reloc_howto_type elf_mips_gnu_rela16_s2 = 0, /* src_mask */ 0x0000ffff, /* dst_mask */ TRUE); /* pcrel_offset */ + +/* 32 bit pc-relative. Used for compact EH tables. */ +static reloc_howto_type elf_mips_gnu_pcrel32 = + HOWTO (R_MIPS_PC32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_PC32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + TRUE); /* pcrel_offset */ + /* Originally a VxWorks extension, but now used for other systems too. */ static reloc_howto_type elf_mips_copy_howto = @@ -2635,8 +2862,8 @@ static reloc_howto_type elf_mips_copy_howto = _bfd_mips_elf_generic_reloc, /* special_function */ "R_MIPS_COPY", /* name */ FALSE, /* partial_inplace */ - 0x0, /* src_mask */ - 0x0, /* dst_mask */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ FALSE); /* pcrel_offset */ /* Originally a VxWorks extension, but now used for other systems too. */ @@ -2651,9 +2878,26 @@ static reloc_howto_type elf_mips_jump_slot_howto = _bfd_mips_elf_generic_reloc, /* special_function */ "R_MIPS_JUMP_SLOT", /* name */ FALSE, /* partial_inplace */ - 0x0, /* src_mask */ - 0x0, /* dst_mask */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ FALSE); /* pcrel_offset */ + +/* Used in EH tables. */ +static reloc_howto_type elf_mips_eh_howto = + HOWTO (R_MIPS_EH, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MIPS_EH", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE); /* pcrel_offset */ + /* Swap in a MIPS 64-bit Rel reloc. */ @@ -3170,7 +3414,13 @@ static const struct elf_reloc_map mips_reloc_map[] = { 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 } + { BFD_RELOC_MIPS_TLS_TPREL_LO16, R_MIPS_TLS_TPREL_LO16 }, + { BFD_RELOC_MIPS_21_PCREL_S2, R_MIPS_PC21_S2 }, + { BFD_RELOC_MIPS_26_PCREL_S2, R_MIPS_PC26_S2 }, + { BFD_RELOC_MIPS_18_PCREL_S3, R_MIPS_PC18_S3 }, + { BFD_RELOC_MIPS_19_PCREL_S2, R_MIPS_PC19_S2 }, + { BFD_RELOC_HI16_S_PCREL, R_MIPS_PCHI16 }, + { BFD_RELOC_LO16_PCREL, R_MIPS_PCLO16 } }; static const struct elf_reloc_map mips16_reloc_map[] = @@ -3189,7 +3439,8 @@ static const struct elf_reloc_map mips16_reloc_map[] = R_MIPS16_TLS_DTPREL_LO16 - R_MIPS16_min }, { BFD_RELOC_MIPS16_TLS_GOTTPREL, R_MIPS16_TLS_GOTTPREL - R_MIPS16_min }, { BFD_RELOC_MIPS16_TLS_TPREL_HI16, R_MIPS16_TLS_TPREL_HI16 - R_MIPS16_min }, - { BFD_RELOC_MIPS16_TLS_TPREL_LO16, R_MIPS16_TLS_TPREL_LO16 - R_MIPS16_min } + { BFD_RELOC_MIPS16_TLS_TPREL_LO16, R_MIPS16_TLS_TPREL_LO16 - R_MIPS16_min }, + { BFD_RELOC_MIPS16_16_PCREL_S1, R_MIPS16_PC16_S1 - R_MIPS16_min } }; static const struct elf_reloc_map micromips_reloc_map[] = @@ -3257,6 +3508,10 @@ 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_32_PCREL: + return &elf_mips_gnu_pcrel32; + case BFD_RELOC_MIPS_EH: + return &elf_mips_eh_howto; case BFD_RELOC_MIPS_COPY: return &elf_mips_copy_howto; case BFD_RELOC_MIPS_JUMP_SLOT: @@ -3304,6 +3559,10 @@ bfd_elf64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 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_gnu_pcrel32.name, r_name) == 0) + return &elf_mips_gnu_pcrel32; + if (strcasecmp (elf_mips_eh_howto.name, r_name) == 0) + return &elf_mips_eh_howto; 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) @@ -3328,6 +3587,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_PC32: + return &elf_mips_gnu_pcrel32; + case R_MIPS_EH: + return &elf_mips_eh_howto; case R_MIPS_COPY: return &elf_mips_copy_howto; case R_MIPS_JUMP_SLOT: @@ -3347,7 +3610,12 @@ mips_elf64_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p) else return &mips16_elf64_howto_table_rel[r_type - R_MIPS16_min]; } - BFD_ASSERT (r_type < (unsigned int) R_MIPS_max); + if (r_type >= R_MIPS_max) + { + _bfd_error_handler (_("unrecognised MIPS reloc number: %d"), r_type); + bfd_set_error (bfd_error_bad_value); + r_type = R_MIPS_NONE; + } if (rela_p) return &mips_elf64_howto_table_rela[r_type]; else @@ -3377,88 +3645,20 @@ mips_elf64_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, /* Since each entry in an SHT_REL or SHT_RELA section can represent up to three relocs, we must tell the user to allocate more space. */ -static long -mips_elf64_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) -{ - return (sec->reloc_count * 3 + 1) * sizeof (arelent *); -} - static long mips_elf64_get_dynamic_reloc_upper_bound (bfd *abfd) { return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 3; } -/* We must also copy more relocations than the corresponding functions - in elf.c would, so the two following functions are slightly - modified from elf.c, that multiply the external relocation count by - 3 to obtain the internal relocation count. */ - -static long -mips_elf64_canonicalize_reloc (bfd *abfd, sec_ptr section, - arelent **relptr, asymbol **symbols) -{ - arelent *tblptr; - unsigned int i; - const struct elf_backend_data *bed = get_elf_backend_data (abfd); - - if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE)) - return -1; - - tblptr = section->relocation; - for (i = 0; i < section->reloc_count * 3; i++) - *relptr++ = tblptr++; - - *relptr = NULL; - - return section->reloc_count * 3; -} - -static long -mips_elf64_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage, - asymbol **syms) -{ - bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean); - asection *s; - long ret; - - if (elf_dynsymtab (abfd) == 0) - { - bfd_set_error (bfd_error_invalid_operation); - return -1; - } - - slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; - ret = 0; - for (s = abfd->sections; s != NULL; s = s->next) - { - if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd) - && (elf_section_data (s)->this_hdr.sh_type == SHT_REL - || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)) - { - arelent *p; - long count, i; - - if (! (*slurp_relocs) (abfd, s, syms, TRUE)) - return -1; - count = s->size / elf_section_data (s)->this_hdr.sh_entsize * 3; - p = s->relocation; - for (i = 0; i < count; i++) - *storage++ = p++; - ret += count; - } - } - - *storage = NULL; - - return ret; -} - /* Read the relocations from one reloc section. This is mostly copied from elfcode.h, except for the changes to expand one external - relocation to 3 internal ones. We must unfortunately set - reloc_count to the number of external relocations, because a lot of - generic code seems to depend on this. */ + relocation to 3 internal ones. To reduce processing effort we + could discard those R_MIPS_NONE relocations that occupy the second + and the third entry of a triplet, as `mips_elf64_write_rel' and + `mips_elf64_write_rela' recreate them in output automagically, + however that would also remove them from `objdump -r' output, + breaking a long-established tradition and likely confusing people. */ static bfd_boolean mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect, @@ -3611,8 +3811,6 @@ mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect, } } - asect->reloc_count += (relent - relents) / 3; - if (allocated != NULL) free (allocated); @@ -3627,8 +3825,7 @@ mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect, /* Read the relocations. On Irix 6, there can be two reloc sections associated with a single data section. This is copied from elfcode.h as well, with changes as small as accounting for 3 - internal relocs per external reloc and resetting reloc_count to - zero before processing the relocs of a section. */ + internal relocs per external reloc. */ static bfd_boolean mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect, @@ -3656,7 +3853,7 @@ mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect, rel_hdr2 = d->rela.hdr; reloc_count2 = (rel_hdr2 ? NUM_SHDR_ENTRIES (rel_hdr2) : 0); - BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2); + BFD_ASSERT (asect->reloc_count == 3 * (reloc_count + reloc_count2)); BFD_ASSERT ((rel_hdr && asect->rel_filepos == rel_hdr->sh_offset) || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset)); @@ -3682,9 +3879,6 @@ mips_elf64_slurp_reloc_table (bfd *abfd, asection *asect, if (relents == NULL) return FALSE; - /* The slurp_one_reloc_table routine increments reloc_count. */ - asect->reloc_count = 0; - if (rel_hdr != NULL && ! mips_elf64_slurp_one_reloc_table (abfd, asect, rel_hdr, reloc_count, @@ -3987,8 +4181,8 @@ mips_elf64_object_p (bfd *abfd) static irix_compat_t elf64_mips_irix_compat (bfd *abfd) { - if ((abfd->xvec == &bfd_elf64_bigmips_vec) - || (abfd->xvec == &bfd_elf64_littlemips_vec)) + if ((abfd->xvec == &mips_elf64_be_vec) + || (abfd->xvec == &mips_elf64_le_vec)) return ict_irix6; else return ict_none; @@ -4034,6 +4228,8 @@ elf64_mips_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) return FALSE; case 136: /* Linux/MIPS - N64 kernel elf_prpsinfo */ + elf_tdata (abfd)->core->pid + = bfd_get_32 (abfd, note->descdata + 24); elf_tdata (abfd)->core->program = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16); elf_tdata (abfd)->core->command @@ -4054,6 +4250,45 @@ elf64_mips_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) return TRUE; } + +/* Write Linux core PRSTATUS note into core file. */ + +static char * +elf64_mips_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, + ...) +{ + switch (note_type) + { + default: + return NULL; + + case NT_PRPSINFO: + BFD_FAIL (); + return NULL; + + case NT_PRSTATUS: + { + char data[480]; + va_list ap; + long pid; + int cursig; + const void *greg; + + va_start (ap, note_type); + memset (data, 0, 112); + pid = va_arg (ap, long); + bfd_put_32 (abfd, pid, data + 32); + cursig = va_arg (ap, int); + bfd_put_16 (abfd, cursig, data + 12); + greg = va_arg (ap, const void *); + memcpy (data + 112, greg, 360); + memset (data + 472, 0, 8); + va_end (ap); + return elfcore_write_note (abfd, buf, bufsiz, + "CORE", note_type, data, sizeof (data)); + } + } +} /* ECOFF swapping routines. These are used when dealing with the .mdebug section, which is in the ECOFF debugging format. */ @@ -4141,6 +4376,8 @@ const struct elf_size_info mips_elf64_size_info = #define elf_backend_collect TRUE #define elf_backend_type_change_ok TRUE #define elf_backend_can_gc_sections TRUE +#define elf_backend_gc_mark_extra_sections \ + _bfd_mips_elf_gc_mark_extra_sections #define elf_info_to_howto mips_elf64_info_to_howto_rela #define elf_info_to_howto_rel mips_elf64_info_to_howto_rel #define elf_backend_object_p mips_elf64_object_p @@ -4177,7 +4414,6 @@ const struct elf_size_info mips_elf64_size_info = _bfd_mips_elf_additional_program_headers #define elf_backend_modify_segment_map _bfd_mips_elf_modify_segment_map #define elf_backend_gc_mark_hook _bfd_mips_elf_gc_mark_hook -#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_ignore_discarded_relocs \ @@ -4191,6 +4427,7 @@ const struct elf_size_info mips_elf64_size_info = #define elf_backend_grok_psinfo elf64_mips_grok_psinfo #define elf_backend_got_header_size (8 * MIPS_RESERVED_GOTNO) +#define elf_backend_want_dynrelro 1 /* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations work better/work only in RELA, so we default to this. */ @@ -4204,6 +4441,7 @@ const struct elf_size_info mips_elf64_size_info = #define elf_backend_sign_extend_vma TRUE #define elf_backend_write_section _bfd_mips_elf_write_section +#define elf_backend_sort_relocs_p _bfd_mips_elf_sort_relocs_p /* We don't set bfd_elf64_bfd_is_local_label_name because the 32-bit MIPS-specific function only applies to IRIX5, which had no 64-bit @@ -4225,40 +4463,13 @@ const struct elf_size_info mips_elf64_size_info = #define bfd_elf64_bfd_print_private_bfd_data \ _bfd_mips_elf_print_private_bfd_data -#define bfd_elf64_get_reloc_upper_bound mips_elf64_get_reloc_upper_bound -#define bfd_elf64_canonicalize_reloc mips_elf64_canonicalize_reloc #define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound -#define bfd_elf64_canonicalize_dynamic_reloc mips_elf64_canonicalize_dynamic_reloc -#define bfd_elf64_bfd_relax_section _bfd_mips_relax_section #define bfd_elf64_mkobject _bfd_mips_elf_mkobject -/* MIPS ELF64 archive functions. */ -#define bfd_elf64_archive_functions -extern bfd_boolean bfd_elf64_archive_slurp_armap - (bfd *); -extern bfd_boolean bfd_elf64_archive_write_armap - (bfd *, unsigned int, struct orl *, unsigned int, int); -#define bfd_elf64_archive_slurp_extended_name_table \ - _bfd_archive_coff_slurp_extended_name_table -#define bfd_elf64_archive_construct_extended_name_table \ - _bfd_archive_coff_construct_extended_name_table -#define bfd_elf64_archive_truncate_arname \ - _bfd_archive_coff_truncate_arname -#define bfd_elf64_archive_read_ar_hdr _bfd_archive_coff_read_ar_hdr -#define bfd_elf64_archive_write_ar_hdr _bfd_archive_coff_write_ar_hdr -#define bfd_elf64_archive_openr_next_archived_file \ - _bfd_archive_coff_openr_next_archived_file -#define bfd_elf64_archive_get_elt_at_index \ - _bfd_archive_coff_get_elt_at_index -#define bfd_elf64_archive_generic_stat_arch_elt \ - _bfd_archive_coff_generic_stat_arch_elt -#define bfd_elf64_archive_update_armap_timestamp \ - _bfd_archive_coff_update_armap_timestamp - /* The SGI style (n)64 NewABI. */ -#define TARGET_LITTLE_SYM bfd_elf64_littlemips_vec +#define TARGET_LITTLE_SYM mips_elf64_le_vec #define TARGET_LITTLE_NAME "elf64-littlemips" -#define TARGET_BIG_SYM bfd_elf64_bigmips_vec +#define TARGET_BIG_SYM mips_elf64_be_vec #define TARGET_BIG_NAME "elf64-bigmips" #define ELF_MAXPAGESIZE 0x10000 @@ -4275,15 +4486,18 @@ extern bfd_boolean bfd_elf64_archive_write_armap #undef ELF_MAXPAGESIZE #undef ELF_COMMONPAGESIZE -#define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_vec +#define TARGET_LITTLE_SYM mips_elf64_trad_le_vec #define TARGET_LITTLE_NAME "elf64-tradlittlemips" -#define TARGET_BIG_SYM bfd_elf64_tradbigmips_vec +#define TARGET_BIG_SYM mips_elf64_trad_be_vec #define TARGET_BIG_NAME "elf64-tradbigmips" #define ELF_MAXPAGESIZE 0x10000 #define ELF_COMMONPAGESIZE 0x1000 #define elf64_bed elf64_tradbed +#undef elf_backend_write_core_note +#define elf_backend_write_core_note elf64_mips_write_core_note + /* Include the target file again for this target. */ #include "elf64-target.h" @@ -4295,27 +4509,17 @@ extern bfd_boolean bfd_elf64_archive_write_armap #undef TARGET_BIG_SYM #undef TARGET_BIG_NAME -#define TARGET_LITTLE_SYM bfd_elf64_tradlittlemips_freebsd_vec +#define TARGET_LITTLE_SYM mips_elf64_tradfbsd_le_vec #define TARGET_LITTLE_NAME "elf64-tradlittlemips-freebsd" -#define TARGET_BIG_SYM bfd_elf64_tradbigmips_freebsd_vec +#define TARGET_BIG_SYM mips_elf64_tradfbsd_be_vec #define TARGET_BIG_NAME "elf64-tradbigmips-freebsd" #undef ELF_OSABI #define ELF_OSABI ELFOSABI_FREEBSD -/* The kernel recognizes executables as valid only if they carry a - "FreeBSD" label in the ELF header. So we put this label on all - executables and (for simplicity) also all other object files. */ - -static void -elf_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) -{ - _bfd_elf_set_osabi (abfd, info); -} - -#undef elf_backend_post_process_headers -#define elf_backend_post_process_headers elf_fbsd_post_process_headers #undef elf64_bed #define elf64_bed elf64_fbsd_tradbed +#undef elf64_mips_write_core_note + #include "elf64-target.h"