X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bfd%2Felfn32-mips.c;h=49cf8981919eca201d70e9afbd80f6e394581b3a;hb=b0b648d1e639a2a9ba405ff5adbcbebbbf8212ac;hp=973edd52daf735e018dfba52f912f17e50cf187e;hpb=a5dd37ab655106440e987830db5111b43f271ecc;p=external%2Fbinutils.git diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c index 973edd5..49cf898 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -47,6 +47,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define ECOFF_SIGNED_32 #include "ecoffswap.h" +static bfd_reloc_status_type mips_elf_generic_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static bfd_reloc_status_type mips_elf_hi16_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static bfd_reloc_status_type mips_elf_lo16_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static bfd_reloc_status_type mips_elf_got16_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); static bfd_boolean mips_elf_assign_gp (bfd *, bfd_vma *); static bfd_reloc_status_type mips_elf_final_gp @@ -87,6 +95,10 @@ static irix_compat_t elf_n32_mips_irix_compat extern const bfd_target bfd_elf32_nbigmips_vec; extern const bfd_target bfd_elf32_nlittlemips_vec; +static asection *prev_reloc_section = NULL; +static bfd_vma prev_reloc_address = -1; +static bfd_vma prev_reloc_addend = 0; + /* Nonzero if ABFD is using the N32 ABI. */ #define ABI_N32_P(abfd) \ ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0) @@ -114,7 +126,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_NONE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -129,7 +141,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -144,7 +156,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_32", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -159,7 +171,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_REL32", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -177,7 +189,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = /* This needs complex overflow detection, because the upper four bits must match the PC + 4. */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_26", /* name */ TRUE, /* partial_inplace */ 0x03ffffff, /* src_mask */ @@ -189,13 +201,13 @@ static reloc_howto_type elf_mips_howto_table_rel[] = /* High 16 bits of symbol value. */ HOWTO (R_MIPS_HI16, /* type */ - 16, /* rightshift */ + 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_hi16_reloc, /* special_function */ + mips_elf_hi16_reloc, /* special_function */ "R_MIPS_HI16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -210,7 +222,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_lo16_reloc, /* special_function */ + mips_elf_lo16_reloc, /* special_function */ "R_MIPS_LO16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -255,7 +267,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_got16_reloc, /* special_function */ + mips_elf_got16_reloc, /* special_function */ "R_MIPS_GOT16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -270,7 +282,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_PC16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -285,7 +297,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -321,7 +333,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 6, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SHIFT5", /* name */ TRUE, /* partial_inplace */ 0x000007c0, /* src_mask */ @@ -351,7 +363,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_64", /* name */ TRUE, /* partial_inplace */ MINUS_ONE, /* src_mask */ @@ -366,7 +378,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_DISP", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -381,7 +393,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_PAGE", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -396,7 +408,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_OFST", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -411,7 +423,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_HI16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -426,7 +438,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_LO16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -441,7 +453,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SUB", /* name */ TRUE, /* partial_inplace */ MINUS_ONE, /* src_mask */ @@ -457,7 +469,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_INSERT_A", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -474,7 +486,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_INSERT_B", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -490,7 +502,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_DELETE", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -514,7 +526,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL_HI16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -529,7 +541,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL_LO16", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -544,7 +556,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SCN_DISP", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -558,7 +570,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_REL16", /* name */ TRUE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -578,7 +590,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_RELGOT", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -594,7 +606,7 @@ static reloc_howto_type elf_mips_howto_table_rel[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_JALR", /* name */ FALSE, /* partial_inplace */ 0x00000000, /* src_mask */ @@ -614,7 +626,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_NONE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -629,7 +641,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -644,7 +656,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -659,7 +671,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_REL32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -677,7 +689,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = /* This needs complex overflow detection, because the upper 36 bits must match the PC + 4. */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_26", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -692,7 +704,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_HI16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -707,7 +719,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_LO16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -752,7 +764,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_got16_reloc, /* special_function */ "R_MIPS_GOT16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -767,7 +779,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_PC16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -782,7 +794,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -816,7 +828,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 6, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SHIFT5", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -846,7 +858,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -861,7 +873,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_DISP", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -876,7 +888,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_PAGE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -891,7 +903,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_OFST", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -906,7 +918,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_HI16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -921,7 +933,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GOT_LO16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -936,7 +948,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SUB", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -952,7 +964,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_INSERT_A", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -969,7 +981,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_INSERT_B", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -985,7 +997,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_DELETE", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1000,7 +1012,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_HIGHER", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1015,7 +1027,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_HIGHEST", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1030,7 +1042,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL_HI16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1045,7 +1057,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_CALL_LO16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1060,7 +1072,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_SCN_DISP", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1075,7 +1087,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_REL16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1095,7 +1107,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_RELGOT", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1111,7 +1123,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_JALR", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -1195,7 +1207,7 @@ static reloc_howto_type elf_mips_gnu_rel16_s2 = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GNU_REL16_S2", /* name */ TRUE, /* partial_inplace */ 0x0000ffff, /* src_mask */ @@ -1211,13 +1223,224 @@ static reloc_howto_type elf_mips_gnu_rela16_s2 = TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ - _bfd_mips_elf_generic_reloc, /* special_function */ + mips_elf_generic_reloc, /* special_function */ "R_MIPS_GNU_REL16_S2", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ 0x0000ffff, /* dst_mask */ TRUE); /* pcrel_offset */ +/* This is derived from bfd_elf_generic_reloc. NewABI allows us to have + several relocations against the same address. The addend is derived + from the addends of preceding relocations. If we don't need to + do something special, we simply keep track of the addend. */ + +#define GET_RELOC_ADDEND(obfd, sym, entry, sec) \ +{ \ + /* If we're relocating, and this is an external symbol, we don't \ + want to change anything. */ \ + if ((obfd) != NULL \ + && ((sym)->flags & BSF_SECTION_SYM) == 0 \ + && (! (entry)->howto->partial_inplace \ + || (entry)->addend == 0)) \ + { \ + (entry)->address += (sec)->output_offset; \ + return bfd_reloc_ok; \ + } \ + \ + /* The addend of combined relocs is remembered and left for \ + subsequent relocs. */ \ + if (prev_reloc_address != (entry)->address \ + || prev_reloc_section != (sec)) \ + { \ + prev_reloc_section = (sec); \ + prev_reloc_address = (entry)->address; \ + prev_reloc_addend = (entry)->addend; \ + } \ + else \ + (entry)->addend = prev_reloc_addend; \ +} + +#define SET_RELOC_ADDEND(entry) \ +{ \ + prev_reloc_addend = (entry)->addend; \ +} + +static bfd_reloc_status_type +mips_elf_generic_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) +{ + GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section) + + return bfd_reloc_continue; +} + +/* Do a R_MIPS_HI16 relocation. This has to be done in combination + with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to + the HI16. Here we just save the information we need; we do the + actual relocation when we see the LO16. + + MIPS ELF requires that the LO16 immediately follow the HI16. As a + GNU extension, for non-pc-relative relocations, we permit an + arbitrary number of HI16 relocs to be associated with a single LO16 + reloc. This extension permits gcc to output the HI and LO relocs + itself. + + This cannot be done for PC-relative relocations because both the HI16 + and LO16 parts of the relocations must be done relative to the LO16 + part, and there can be carry to or borrow from the HI16 part. */ + +struct mips_hi16 +{ + struct mips_hi16 *next; + bfd_byte *addr; + bfd_vma addend; +}; + +/* FIXME: This should not be a static variable. */ + +static struct mips_hi16 *mips_hi16_list; + +static bfd_reloc_status_type +mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry, + asymbol *symbol, void *data, asection *input_section, + bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) +{ + bfd_reloc_status_type ret; + bfd_vma relocation; + struct mips_hi16 *n; + + GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section) + + ret = bfd_reloc_ok; + + if (bfd_is_und_section (symbol->section) && output_bfd == NULL) + ret = bfd_reloc_undefined; + + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + relocation += reloc_entry->addend; + + if (reloc_entry->address > input_section->_cooked_size) + return bfd_reloc_outofrange; + + /* Save the information, and let LO16 do the actual relocation. */ + n = bfd_malloc (sizeof *n); + if (n == NULL) + return bfd_reloc_outofrange; + n->addr = (bfd_byte *) data + reloc_entry->address; + n->addend = relocation; + n->next = mips_hi16_list; + mips_hi16_list = n; + + if (output_bfd != NULL) + reloc_entry->address += input_section->output_offset; + + return ret; +} + +/* Do a R_MIPS_LO16 relocation. This is a straightforward 16 bit + inplace relocation; this function exists in order to do the + R_MIPS_HI16 relocation described above. */ + +static bfd_reloc_status_type +mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, + void *data, asection *input_section, bfd *output_bfd, + char **error_message) +{ + if (mips_hi16_list != NULL) + { + struct mips_hi16 *l; + + l = mips_hi16_list; + while (l != NULL) + { + unsigned long insn; + unsigned long val; + unsigned long vallo; + struct mips_hi16 *next; + + /* Do the HI16 relocation. Note that we actually don't need + to know anything about the LO16 itself, except where to + find the low 16 bits of the addend needed by the LO16. */ + insn = bfd_get_32 (abfd, l->addr); + vallo = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + + /* The low order 16 bits are always treated as a signed + value. */ + vallo = ((vallo & 0xffff) ^ 0x8000) - 0x8000; + val = ((insn & 0xffff) << 16) + vallo; + val += l->addend; + + /* If PC-relative, we need to subtract out the address of the LO + half of the HI/LO. (The actual relocation is relative + to that instruction.) */ + if (reloc_entry->howto->pc_relative) + val -= reloc_entry->address; + + /* At this point, "val" has the value of the combined HI/LO + pair. If the low order 16 bits (which will be used for + the LO16 insn) are negative, then we will need an + adjustment for the high order 16 bits. */ + val += 0x8000; + val = (val >> 16) & 0xffff; + + insn &= ~ (bfd_vma) 0xffff; + insn |= val; + bfd_put_32 (abfd, insn, l->addr); + + next = l->next; + free (l); + l = next; + } + + mips_hi16_list = NULL; + } + + /* Now do the LO16 reloc in the usual way. */ + return mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); +} + +/* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset + table used for PIC code. If the symbol is an external symbol, the + instruction is modified to contain the offset of the appropriate + entry in the global offset table. If the symbol is a section + symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit + addends are combined to form the real addend against the section + symbol; the GOT16 is modified to contain the offset of an entry in + the global offset table, and the LO16 is modified to offset it + appropriately. Thus an offset larger than 16 bits requires a + modified value in the global offset table. + + This implementation suffices for the assembler, but the linker does + not yet know how to create global offset tables. */ + +static bfd_reloc_status_type +mips_elf_got16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, + void *data, asection *input_section, bfd *output_bfd, + char **error_message) +{ + /* If we're relocating, and this is a local symbol, we can handle it + just like an R_MIPS_HI16. */ + if (output_bfd != NULL + && ((symbol->flags & BSF_SECTION_SYM) != 0 + || (symbol->flags & BSF_LOCAL) == 0)) + return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); + + /* Otherwise we try to handle it as R_MIPS_GOT_DISP. */ + return mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); +} + /* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a dangerous relocation. */ @@ -1319,6 +1542,8 @@ mips_elf_gprel16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry, bfd_reloc_status_type ret; bfd_vma gp; + GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section) + if (output_bfd != NULL) relocatable = TRUE; else @@ -1348,6 +1573,8 @@ mips_elf_literal_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, bfd_reloc_status_type ret; bfd_vma gp; + GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section) + /* FIXME: The entries in the .lit8 and .lit4 sections should be merged. */ if (output_bfd != NULL) relocatable = TRUE; @@ -1379,6 +1606,8 @@ mips_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, bfd_reloc_status_type ret; bfd_vma gp; + GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section) + /* R_MIPS_GPREL32 relocations are defined for local symbols only. */ if (output_bfd != NULL && (symbol->flags & BSF_SECTION_SYM) == 0 @@ -1455,33 +1684,36 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, the rest is at bits 6-10. The bitpos already got right by the howto. */ static bfd_reloc_status_type -mips_elf_shift6_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - void *data, asection *input_section, bfd *output_bfd, - char **error_message) +mips_elf_shift6_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) { + GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section) + if (reloc_entry->howto->partial_inplace) { reloc_entry->addend = ((reloc_entry->addend & 0x00007c0) | (reloc_entry->addend & 0x00000800) >> 9); } - return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, - error_message); + SET_RELOC_ADDEND (reloc_entry) + + return bfd_reloc_continue; } /* Handle a mips16 jump. */ static bfd_reloc_status_type -mips16_jump_reloc (bfd *abfd ATTRIBUTE_UNUSED, - arelent *reloc_entry ATTRIBUTE_UNUSED, - asymbol *symbol ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED, - asection *input_section, bfd *output_bfd ATTRIBUTE_UNUSED, +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) { static bfd_boolean warned = FALSE; + GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section) + /* FIXME. */ if (! warned) (*_bfd_error_handler) @@ -1507,6 +1739,8 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, bfd_signed_vma val; bfd_vma relocation; + GET_RELOC_ADDEND (output_bfd, symbol, reloc_entry, input_section) + if (output_bfd != NULL) relocatable = TRUE; else @@ -1570,6 +1804,9 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, return bfd_reloc_ok; } + +#undef GET_RELOC_ADDEND +#undef SET_RELOC_ADDEND /* A mapping from BFD reloc types to MIPS ELF reloc types. */ @@ -1873,6 +2110,11 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { #define ELF_ARCH bfd_arch_mips #define ELF_MACHINE_CODE EM_MIPS +/* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses + a value of 0x1000, and we are compatible. + FIXME: How does this affect NewABI? */ +#define ELF_MAXPAGESIZE 0x1000 + #define elf_backend_collect TRUE #define elf_backend_type_change_ok TRUE #define elf_backend_can_gc_sections TRUE @@ -1954,30 +2196,20 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { #define TARGET_BIG_SYM bfd_elf32_nbigmips_vec #define TARGET_BIG_NAME "elf32-nbigmips" -/* The SVR4 MIPS ABI says that this should be 0x10000, but Irix 5 uses - a value of 0x1000, and we are compatible. - FIXME: How does this affect NewABI? */ -#define ELF_MAXPAGESIZE 0x1000 - #include "elf32-target.h" /* Support for traditional mips targets using n32 ABI. */ +#define INCLUDED_TARGET_FILE /* More a type of flag. */ + #undef TARGET_LITTLE_SYM #undef TARGET_LITTLE_NAME #undef TARGET_BIG_SYM #undef TARGET_BIG_NAME -#undef ELF_MAXPAGESIZE - #define TARGET_LITTLE_SYM bfd_elf32_ntradlittlemips_vec #define TARGET_LITTLE_NAME "elf32-ntradlittlemips" #define TARGET_BIG_SYM bfd_elf32_ntradbigmips_vec #define TARGET_BIG_NAME "elf32-ntradbigmips" -/* 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. */ -#define ELF_MAXPAGESIZE 0x10000 -#define elf32_bed elf32_tradbed - /* Include the target file again for this target. */ #include "elf32-target.h"