diff options
Diffstat (limited to 'bfd/elf32-mips.c')
-rw-r--r-- | bfd/elf32-mips.c | 593 |
1 files changed, 583 insertions, 10 deletions
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 3392207..fd3d4ba 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -832,6 +832,508 @@ static reloc_howto_type elf_mips16_howto_table_rel[] = FALSE), /* pcrel_offset */ }; +static reloc_howto_type elf_micromips_howto_table_rel[] = +{ + EMPTY_HOWTO (130), + EMPTY_HOWTO (131), + EMPTY_HOWTO (132), + + /* 26 bit jump address. */ + HOWTO (R_MICROMIPS_26_S1, /* type */ + 1, /* 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. */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MICROMIPS_26_S1", /* name */ + TRUE, /* partial_inplace */ + 0x3ffffff, /* src_mask */ + 0x3ffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* High 16 bits of symbol value. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_HI16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Low 16 bits of symbol value. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_LO16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* GP relative reference. */ + HOWTO (R_MICROMIPS_GPREL16, /* 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_elf32_gprel16_reloc, /* special_function */ + "R_MICROMIPS_GPREL16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Reference to literal section. */ + HOWTO (R_MICROMIPS_LITERAL, /* 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_elf32_gprel16_reloc, /* special_function */ + "R_MICROMIPS_LITERAL", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Reference to global offset table. */ + HOWTO (R_MICROMIPS_GOT16, /* 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_got16_reloc, /* special_function */ + "R_MICROMIPS_GOT16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* This is for microMIPS branches. */ + HOWTO (R_MICROMIPS_PC7_S1, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 7, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MICROMIPS_PC7_S1", /* name */ + TRUE, /* partial_inplace */ + 0x0000007f, /* src_mask */ + 0x0000007f, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MICROMIPS_PC10_S1, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 10, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MICROMIPS_PC10_S1", /* name */ + TRUE, /* partial_inplace */ + 0x000003ff, /* src_mask */ + 0x000003ff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_MICROMIPS_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_MICROMIPS_PC16_S1", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* 16 bit call through global offset table. */ + HOWTO (R_MICROMIPS_CALL16, /* 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_MICROMIPS_CALL16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + EMPTY_HOWTO (143), + EMPTY_HOWTO (144), + + /* Displacement in the global offset table. */ + HOWTO (R_MICROMIPS_GOT_DISP, /* 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_MICROMIPS_GOT_DISP",/* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Displacement to page pointer in the global offset table. */ + HOWTO (R_MICROMIPS_GOT_PAGE, /* 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_MICROMIPS_GOT_PAGE",/* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Offset from page pointer in the global offset table. */ + HOWTO (R_MICROMIPS_GOT_OFST, /* 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_MICROMIPS_GOT_OFST",/* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* High 16 bits of displacement in global offset table. */ + HOWTO (R_MICROMIPS_GOT_HI16, /* 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_MICROMIPS_GOT_HI16",/* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Low 16 bits of displacement in global offset table. */ + HOWTO (R_MICROMIPS_GOT_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_generic_reloc, /* special_function */ + "R_MICROMIPS_GOT_LO16",/* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 64 bit subtraction. Used in the N32 ABI. */ + HOWTO (R_MICROMIPS_SUB, /* 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_MICROMIPS_SUB", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Get the higher value of a 64 bit addend. */ + HOWTO (R_MICROMIPS_HIGHER, /* 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_MICROMIPS_HIGHER", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Get the highest value of a 64 bit addend. */ + HOWTO (R_MICROMIPS_HIGHEST, /* 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_MICROMIPS_HIGHEST", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* High 16 bits of displacement in global offset table. */ + HOWTO (R_MICROMIPS_CALL_HI16, /* 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_MICROMIPS_CALL_HI16",/* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Low 16 bits of displacement in global offset table. */ + HOWTO (R_MICROMIPS_CALL_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_generic_reloc, /* special_function */ + "R_MICROMIPS_CALL_LO16",/* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Section displacement. */ + HOWTO (R_MICROMIPS_SCN_DISP, /* 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_MICROMIPS_SCN_DISP",/* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Protected jump conversion. This is an optimization hint. No + relocation is required for correctness. */ + HOWTO (R_MICROMIPS_JALR, /* 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_MICROMIPS_JALR", /* name */ + FALSE, /* partial_inplace */ + 0x00000000, /* src_mask */ + 0x00000000, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Low 16 bits of symbol value. Note that the high 16 bits of symbol values + must be zero. This is used for relaxation. */ + HOWTO (R_MICROMIPS_HI0_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_generic_reloc, /* special_function */ + "R_MICROMIPS_HI0_LO16",/* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + EMPTY_HOWTO (158), + EMPTY_HOWTO (159), + EMPTY_HOWTO (160), + EMPTY_HOWTO (161), + + /* TLS general dynamic variable reference. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_TLS_GD", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS local dynamic variable reference. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_TLS_LDM", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS local dynamic offset. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_TLS_DTPREL_HI16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS local dynamic offset. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_TLS_DTPREL_LO16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS thread pointer offset. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_TLS_GOTTPREL", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + EMPTY_HOWTO (167), + EMPTY_HOWTO (168), + + /* TLS thread pointer offset. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_TLS_TPREL_HI16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* TLS thread pointer offset. */ + HOWTO (R_MICROMIPS_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_MICROMIPS_TLS_TPREL_LO16", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + EMPTY_HOWTO (171), + + /* GP- and PC-relative relocations. */ + HOWTO (R_MICROMIPS_GPREL7_S2, /* type */ + 2, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 7, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf32_gprel16_reloc, /* special_function */ + "R_MICROMIPS_GPREL7_S2", /* name */ + TRUE, /* partial_inplace */ + 0x0000007f, /* src_mask */ + 0x0000007f, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_MICROMIPS_PC23_S2, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 23, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + _bfd_mips_elf_generic_reloc, /* special_function */ + "R_MICROMIPS_PC23_S2", /* name */ + TRUE, /* partial_inplace */ + 0x007fffff, /* src_mask */ + 0x007fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ +}; + /* 16 bit offset for pc-relative branches. */ static reloc_howto_type elf_mips_gnu_rel16_s2 = HOWTO (R_MIPS_GNU_REL16_S2, /* type */ @@ -1033,10 +1535,12 @@ _bfd_mips_elf32_gprel16_reloc (bfd *abfd, arelent *reloc_entry, { bfd_boolean relocatable; bfd_reloc_status_type ret; + bfd_byte *location; bfd_vma gp; - /* R_MIPS_LITERAL relocations are defined for local symbols only. */ - if (reloc_entry->howto->type == R_MIPS_LITERAL + /* R_MIPS_LITERAL/R_MICROMIPS_LITERAL relocations are defined for local + symbols only. */ + if (literal_reloc_p (reloc_entry->howto->type) && output_bfd != NULL && (symbol->flags & BSF_SECTION_SYM) == 0 && (symbol->flags & BSF_LOCAL) != 0) @@ -1059,9 +1563,16 @@ _bfd_mips_elf32_gprel16_reloc (bfd *abfd, arelent *reloc_entry, if (ret != bfd_reloc_ok) return ret; - return _bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, - input_section, relocatable, - data, gp); + location = (bfd_byte *) data + reloc_entry->address; + _bfd_mips_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_mips_elf_reloc_shuffle (abfd, reloc_entry->howto->type, !relocatable, + location); + + return ret; } /* Do a R_MIPS_GPREL32 relocation. This is a 32 bit value which must @@ -1219,13 +1730,13 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, return ret; location = (bfd_byte *) data + reloc_entry->address; - _bfd_mips16_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, FALSE, - location); + _bfd_mips_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); + _bfd_mips_elf_reloc_shuffle (abfd, reloc_entry->howto->type, !relocatable, + location); return ret; } @@ -1287,6 +1798,47 @@ static const struct elf_reloc_map mips16_reloc_map[] = { BFD_RELOC_MIPS16_LO16, R_MIPS16_LO16 - R_MIPS16_min }, }; +static const struct elf_reloc_map micromips_reloc_map[] = +{ + { BFD_RELOC_MICROMIPS_JMP, R_MICROMIPS_26_S1 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_HI16_S, R_MICROMIPS_HI16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_LO16, R_MICROMIPS_LO16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_GPREL16, R_MICROMIPS_GPREL16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_LITERAL, R_MICROMIPS_LITERAL - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_GOT16, R_MICROMIPS_GOT16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_7_PCREL_S1, R_MICROMIPS_PC7_S1 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_10_PCREL_S1, R_MICROMIPS_PC10_S1 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_16_PCREL_S1, R_MICROMIPS_PC16_S1 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_CALL16, R_MICROMIPS_CALL16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_GOT_DISP, R_MICROMIPS_GOT_DISP - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_GOT_PAGE, R_MICROMIPS_GOT_PAGE - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_GOT_OFST, R_MICROMIPS_GOT_OFST - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_GOT_HI16, R_MICROMIPS_GOT_HI16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_GOT_LO16, R_MICROMIPS_GOT_LO16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_SUB, R_MICROMIPS_SUB - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_HIGHER, R_MICROMIPS_HIGHER - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_HIGHEST, R_MICROMIPS_HIGHEST - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_CALL_HI16, R_MICROMIPS_CALL_HI16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_CALL_LO16, R_MICROMIPS_CALL_LO16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_SCN_DISP, R_MICROMIPS_SCN_DISP - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_JALR, R_MICROMIPS_JALR - R_MICROMIPS_min }, + /* There is no BFD reloc for R_MICROMIPS_HI0_LO16. */ + { BFD_RELOC_MICROMIPS_TLS_GD, R_MICROMIPS_TLS_GD - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_TLS_LDM, R_MICROMIPS_TLS_LDM - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_TLS_DTPREL_HI16, + R_MICROMIPS_TLS_DTPREL_HI16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_TLS_DTPREL_LO16, + R_MICROMIPS_TLS_DTPREL_LO16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_TLS_GOTTPREL, + R_MICROMIPS_TLS_GOTTPREL - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_TLS_TPREL_HI16, + R_MICROMIPS_TLS_TPREL_HI16 - R_MICROMIPS_min }, + { BFD_RELOC_MICROMIPS_TLS_TPREL_LO16, + R_MICROMIPS_TLS_TPREL_LO16 - R_MICROMIPS_min }, + /* There is no BFD reloc for R_MICROMIPS_GPREL7_S2. */ + /* There is no BFD reloc for R_MICROMIPS_PC23_S2. */ +}; + /* Given a BFD reloc type, return a howto structure. */ static reloc_howto_type * @@ -1295,6 +1847,7 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) unsigned int i; reloc_howto_type *howto_table = elf_mips_howto_table_rel; reloc_howto_type *howto16_table = elf_mips16_howto_table_rel; + reloc_howto_type *howto_micromips_table = elf_micromips_howto_table_rel; for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++) @@ -1310,6 +1863,13 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) return &howto16_table[(int) mips16_reloc_map[i].elf_val]; } + for (i = 0; i < sizeof (micromips_reloc_map) / sizeof (struct elf_reloc_map); + i++) + { + if (micromips_reloc_map[i].bfd_val == code) + return &howto_micromips_table[(int) micromips_reloc_map[i].elf_val]; + } + switch (code) { default: @@ -1361,6 +1921,14 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, && strcasecmp (elf_mips16_howto_table_rel[i].name, r_name) == 0) return &elf_mips16_howto_table_rel[i]; + for (i = 0; + i < (sizeof (elf_micromips_howto_table_rel) + / sizeof (elf_micromips_howto_table_rel[0])); + i++) + if (elf_micromips_howto_table_rel[i].name != NULL + && strcasecmp (elf_micromips_howto_table_rel[i].name, r_name) == 0) + return &elf_micromips_howto_table_rel[i]; + if (strcasecmp (elf_mips_gnu_pcrel32.name, r_name) == 0) return &elf_mips_gnu_pcrel32; if (strcasecmp (elf_mips_gnu_rel16_s2.name, r_name) == 0) @@ -1398,6 +1966,8 @@ mips_elf32_rtype_to_howto (unsigned int r_type, case R_MIPS_JUMP_SLOT: return &elf_mips_jump_slot_howto; default: + if (r_type >= R_MICROMIPS_min && r_type < R_MICROMIPS_max) + return &elf_micromips_howto_table_rel[r_type - R_MICROMIPS_min]; if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max) return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min]; BFD_ASSERT (r_type < (unsigned int) R_MIPS_max); @@ -1422,7 +1992,7 @@ mips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) when we do the relocation, because the symbol manipulations done by the linker may cause us to lose track of the input BFD. */ if (((*cache_ptr->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0 - && (gprel16_reloc_p (r_type) || r_type == (unsigned int) R_MIPS_LITERAL)) + && (gprel16_reloc_p (r_type) || literal_reloc_p (r_type))) cache_ptr->addend = elf_gp (abfd); } @@ -1671,6 +2241,8 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { #define elf_backend_mips_rtype_to_howto mips_elf32_rtype_to_howto #define bfd_elf32_bfd_is_local_label_name \ mips_elf_is_local_label_name +#define bfd_elf32_bfd_is_target_special_symbol \ + _bfd_mips_elf_is_target_special_symbol #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 @@ -1685,6 +2257,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = { #define bfd_elf32_bfd_set_private_flags _bfd_mips_elf_set_private_flags #define bfd_elf32_bfd_print_private_bfd_data \ _bfd_mips_elf_print_private_bfd_data +#define bfd_elf32_bfd_relax_section _bfd_mips_elf_relax_section /* Support for SGI-ish mips targets. */ #define TARGET_LITTLE_SYM bfd_elf32_littlemips_vec |