diff options
author | Geoffrey Keating <geoffk@geoffk.org> | 2000-03-11 02:16:25 +0000 |
---|---|---|
committer | Geoffrey Keating <geoffk@geoffk.org> | 2000-03-11 02:16:25 +0000 |
commit | bb2d6cd7b19cd82313963d2d878a94e6e85a38b6 (patch) | |
tree | 1aa892d4bc8e425e4ef6495561cdb9db2c65abad | |
parent | 88b6bae086d357c92d250d13263feea1c02175a0 (diff) | |
download | ppe42-binutils-bb2d6cd7b19cd82313963d2d878a94e6e85a38b6.tar.gz ppe42-binutils-bb2d6cd7b19cd82313963d2d878a94e6e85a38b6.zip |
In bfd/:
* elf32-mips.c (mips_elf_next_relocation): Rename from
mips_elf_next_lo16_relocation, and generalize to look
for any relocation type.
(elf_mips_howto_table): Make R_MIPS_PC16 pcrel_offset.
(elf_mips_gnu_rel_hi16): Howto for R_MIPS_GNU_REL_HI16.
(elf_mips_gnu_rel_lo16): Howto for R_MIPS_GNU_REL_LO16.
(elf_mips_gnu_rel16_s2): Howto for R_MIPS_GNU_REL16_S2.
(elf_mips_gnu_pcrel64): Howto for R_MIPS_PC64.
(elf_mips_gnu_pcrel32): Howto for R_MIPS_PC32.
(bfd_elf32_bfd_reloc_type_lookup): Add new relocs.
(mips_rtype_to_howto): Likewise.
(mips_elf_calculate_relocation): Handle new relocs.
(_bfd_mips_elf_relocate_section): REL_HI16/REL_LO16 relocs
are paired. The addend for R_MIPS_GNU_REL16_S2
is shifted right two bits.
In gas/:
* config/tc-mips.c (mips_ip): Don't put stuff in .rodata
when embedded-pic.
* config/tc-mips.c (SWITCH_TABLE): The ELF embedded-pic
implementation doesn't have special handling for switch
statements.
(macro_build): Allow for code in sections other than .text.
(macro): Likewise.
(mips_ip): Likewise.
(md_apply_fix): Do pc-relative relocation madness for MIPS ELF.
Don't perform relocs if we will be outputting them.
(tc_gen_reloc): For ELF, just use fx_addnumber for pc-relative
relocations. Allow BFD_RELOC_16_PCREL_S2 relocs when
embedded-pic.
In gas/testsuite/:
* gas/mips/empic.d: New file.
* gas/mips/empic.s: New file.
* gas/mips/mips16-e.d: New file.
* gas/mips/mips16-e.s: New file.
* gas/mips/mips16-f.d: New file.
* gas/mips/mips16-f.s: New file.
* gas/mips/mips.exp: Add empic, mips16-e. Add mips16-f as an
expected failure.
In include/elf:
* mips.h: Add R_MIPS_GNU_REL_HI16, R_MIPS_GNU_REL_LO16,
R_MIPS_GNU_REL16_S2, R_MIPS_PC64 and R_MIPS_PC32 relocation
numbers.
-rw-r--r-- | bfd/ChangeLog | 18 | ||||
-rw-r--r-- | bfd/elf32-mips.c | 164 | ||||
-rw-r--r-- | gas/ChangeLog | 17 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 89 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/empic.d | 155 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/empic.s | 112 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips.exp | 6 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips16-e.d | 41 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips16-e.s | 13 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips16-f.d | 33 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips16-f.s | 6 | ||||
-rw-r--r-- | include/elf/ChangeLog | 6 | ||||
-rw-r--r-- | include/elf/mips.h | 6 |
14 files changed, 636 insertions, 41 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 036cbb6653..aac6e3df2b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,21 @@ +2000-03-10 Geoffrey Keating <geoffk@cygnus.com> + + * elf32-mips.c (mips_elf_next_relocation): Rename from + mips_elf_next_lo16_relocation, and generalize to look + for any relocation type. + (elf_mips_howto_table): Make R_MIPS_PC16 pcrel_offset. + (elf_mips_gnu_rel_hi16): Howto for R_MIPS_GNU_REL_HI16. + (elf_mips_gnu_rel_lo16): Howto for R_MIPS_GNU_REL_LO16. + (elf_mips_gnu_rel16_s2): Howto for R_MIPS_GNU_REL16_S2. + (elf_mips_gnu_pcrel64): Howto for R_MIPS_PC64. + (elf_mips_gnu_pcrel32): Howto for R_MIPS_PC32. + (bfd_elf32_bfd_reloc_type_lookup): Add new relocs. + (mips_rtype_to_howto): Likewise. + (mips_elf_calculate_relocation): Handle new relocs. + (_bfd_mips_elf_relocate_section): REL_HI16/REL_LO16 relocs + are paired. The addend for R_MIPS_GNU_REL16_S2 + is shifted right two bits. + 2000-03-10 Alan Modra <alan@spri.levels.unisa.edu.au> * reloc.c (bfd_perform_relocation): Undo emacs formatting of diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 05c83ac56a..671dcb1d91 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -159,8 +159,9 @@ static boolean mips_elf_record_global_got_symbol struct mips_got_info *)); static bfd_vma mips_elf_got_page PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *)); -static const Elf_Internal_Rela *mips_elf_next_lo16_relocation - PARAMS ((const Elf_Internal_Rela *, const Elf_Internal_Rela *)); +static const Elf_Internal_Rela *mips_elf_next_relocation + PARAMS ((unsigned int, const Elf_Internal_Rela *, + const Elf_Internal_Rela *)); static bfd_reloc_status_type mips_elf_calculate_relocation PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *, const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *, @@ -614,7 +615,7 @@ static reloc_howto_type elf_mips_howto_table[] = true, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - false), /* pcrel_offset */ + true), /* pcrel_offset */ /* 16 bit call through global offset table. */ HOWTO (R_MIPS_CALL16, /* type */ @@ -944,6 +945,87 @@ static reloc_howto_type elf_mips16_gprel_howto = false); /* pcrel_offset */ +/* GNU extensions for embedded-pic. */ +/* High 16 bits of symbol value, pc-relative. */ +static reloc_howto_type elf_mips_gnu_rel_hi16 = + HOWTO (R_MIPS_GNU_REL_HI16, /* 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_hi16_reloc, /* special_function */ + "R_MIPS_GNU_REL_HI16", /* name */ + true, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + true); /* pcrel_offset */ + +/* Low 16 bits of symbol value, pc-relative. */ +static reloc_howto_type elf_mips_gnu_rel_lo16 = + HOWTO (R_MIPS_GNU_REL_LO16, /* 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_lo16_reloc, /* special_function */ + "R_MIPS_GNU_REL_LO16", /* name */ + true, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* 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 */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_GNU_REL16_S2", /* name */ + true, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + true); /* pcrel_offset */ + +/* 64 bit pc-relative. */ +static reloc_howto_type elf_mips_gnu_pcrel64 = + HOWTO (R_MIPS_PC64, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_PC64", /* name */ + true, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + true); /* pcrel_offset */ + +/* 32 bit pc-relative. */ +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_elf_generic_reloc, /* special_function */ + "R_MIPS_PC32", /* name */ + true, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + true); /* pcrel_offset */ + /* GNU extension to record C++ vtable hierarchy */ static reloc_howto_type elf_mips_gnu_vtinherit_howto = HOWTO (R_MIPS_GNU_VTINHERIT, /* type */ @@ -1882,6 +1964,16 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code) return &elf_mips_gnu_vtinherit_howto; case BFD_RELOC_VTABLE_ENTRY: return &elf_mips_gnu_vtentry_howto; + case BFD_RELOC_PCREL_HI16_S: + return &elf_mips_gnu_rel_hi16; + case BFD_RELOC_PCREL_LO16: + return &elf_mips_gnu_rel_lo16; + case BFD_RELOC_16_PCREL_S2: + return &elf_mips_gnu_rel16_s2; + case BFD_RELOC_64_PCREL: + return &elf_mips_gnu_pcrel64; + case BFD_RELOC_32_PCREL: + return &elf_mips_gnu_pcrel32; } } @@ -1905,6 +1997,21 @@ mips_rtype_to_howto (r_type) case R_MIPS_GNU_VTENTRY: return &elf_mips_gnu_vtentry_howto; break; + case R_MIPS_GNU_REL_HI16: + return &elf_mips_gnu_rel_hi16; + break; + case R_MIPS_GNU_REL_LO16: + return &elf_mips_gnu_rel_lo16; + break; + case R_MIPS_GNU_REL16_S2: + return &elf_mips_gnu_rel16_s2; + break; + case R_MIPS_PC64: + return &elf_mips_gnu_pcrel64; + break; + case R_MIPS_PC32: + return &elf_mips_gnu_pcrel32; + break; default: BFD_ASSERT (r_type < (unsigned int) R_MIPS_max); @@ -5444,11 +5551,12 @@ mips_elf_got16_entry (abfd, info, value) return index; } -/* Returns the first R_MIPS_LO16 relocation found, beginning with +/* Returns the first relocation of type r_type found, beginning with RELOCATION. RELEND is one-past-the-end of the relocation table. */ static const Elf_Internal_Rela * -mips_elf_next_lo16_relocation (relocation, relend) +mips_elf_next_relocation (r_type, relocation, relend) + unsigned int r_type; const Elf_Internal_Rela *relocation; const Elf_Internal_Rela *relend; { @@ -5460,7 +5568,7 @@ mips_elf_next_lo16_relocation (relocation, relend) extension in general, as that is useful for GCC. */ while (relocation < relend) { - if (ELF32_R_TYPE (relocation->r_info) == R_MIPS_LO16) + if (ELF32_R_TYPE (relocation->r_info) == r_type) return relocation; ++relocation; @@ -6006,6 +6114,24 @@ mips_elf_calculate_relocation (abfd, value &= howto->dst_mask; break; + case R_MIPS_PC32: + case R_MIPS_PC64: + case R_MIPS_GNU_REL_LO16: + value = symbol + addend - p; + value &= howto->dst_mask; + break; + + case R_MIPS_GNU_REL16_S2: + value = symbol + mips_elf_sign_extend (addend << 2, 18) - p; + overflowed_p = mips_elf_overflow_p (value, 18); + value = (value >> 2) & howto->dst_mask; + break; + + case R_MIPS_GNU_REL_HI16: + value = mips_elf_high (addend + symbol - p); + value &= howto->dst_mask; + break; + case R_MIPS16_26: /* The calculation for R_MIPS_26 is just the same as for an R_MIPS_26. It's only the storage of the relocated field into @@ -6484,6 +6610,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, combination of the addend stored in two different relocations. */ if (r_type == R_MIPS_HI16 + || r_type == R_MIPS_GNU_REL_HI16 || (r_type == R_MIPS_GOT16 && mips_elf_local_relocation_p (input_bfd, rel, local_sections))) @@ -6491,6 +6618,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, bfd_vma l; const Elf_Internal_Rela *lo16_relocation; reloc_howto_type *lo16_howto; + int lo; /* The combined value is the sum of the HI16 addend, left-shifted by sixteen bits, and the LO16 @@ -6498,15 +6626,18 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, a `lui' of the HI16 value, and then an `addiu' of the LO16 value.) - Scan ahead to find a matching R_MIPS_LO16 - relocation. */ + Scan ahead to find a matching LO16 relocation. */ + if (r_type == R_MIPS_GNU_REL_HI16) + lo = R_MIPS_GNU_REL_LO16; + else + lo = R_MIPS_LO16; lo16_relocation - = mips_elf_next_lo16_relocation (rel, relend); + = mips_elf_next_relocation (lo, rel, relend); if (lo16_relocation == NULL) return false; /* Obtain the addend kept there. */ - lo16_howto = mips_rtype_to_howto (R_MIPS_LO16); + lo16_howto = mips_rtype_to_howto (lo); l = mips_elf_obtain_contents (lo16_howto, lo16_relocation, input_bfd, contents); @@ -6554,7 +6685,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, || r_type == R_MIPS_LITERAL) addend -= (_bfd_get_gp_value (output_bfd) - _bfd_get_gp_value (input_bfd)); - else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26) + else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26 + || r_type == R_MIPS_GNU_REL16_S2) /* The addend is stored without its two least significant bits (which are always zero.) In a non-relocateable link, calculate_relocation will do @@ -6570,17 +6702,19 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16, then we only want to write out the high-order 16 bits. The subsequent R_MIPS_LO16 will handle the low-order bits. */ - if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16) + if (r_type == R_MIPS_HI16 || r_type == R_MIPS_GOT16 + || r_type == R_MIPS_GNU_REL_HI16) addend = mips_elf_high (addend); /* If the relocation is for an R_MIPS_26 relocation, then the two low-order bits are not stored in the object file; they are implicitly zero. */ - else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26) + else if (r_type == R_MIPS_26 || r_type == R_MIPS16_26 + || r_type == R_MIPS_GNU_REL16_S2) addend >>= 2; if (rela_relocation_p) /* If this is a RELA relocation, just update the addend. - We have to cast away constness for REL. */ + We have to cast away constness for REL. */ rel->r_addend = addend; else { @@ -6631,7 +6765,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section, case bfd_reloc_undefined: /* mips_elf_calculate_relocation already called the - undefined_symbol callback. There's no real point in + undefined_symbol callback. There's no real point in trying to perform the relocation at this point, so we just skip ahead to the next relocation. */ continue; diff --git a/gas/ChangeLog b/gas/ChangeLog index d9840a18e3..83d680a2e6 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,20 @@ +2000-03-10 Geoffrey Keating <geoffk@cygnus.com> + + * config/tc-mips.c (mips_ip): Don't put stuff in .rodata + when embedded-pic. + + * config/tc-mips.c (SWITCH_TABLE): The ELF embedded-pic + implementation doesn't have special handling for switch + statements. + (macro_build): Allow for code in sections other than .text. + (macro): Likewise. + (mips_ip): Likewise. + (md_apply_fix): Do pc-relative relocation madness for MIPS ELF. + Don't perform relocs if we will be outputting them. + (tc_gen_reloc): For ELF, just use fx_addnumber for pc-relative + relocations. Allow BFD_RELOC_16_PCREL_S2 relocs when + embedded-pic. + 2000-03-09 Catherine Moore <clm@cygnus.com> * config/tc-m32r.c (m32r_fix_adjustable): Look up the diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 9426519c67..5daf89d394 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -2597,7 +2597,6 @@ macro_build (place, counter, ep, name, fmt, va_alist) || r == BFD_RELOC_MIPS_GOT_LO16 || r == BFD_RELOC_MIPS_CALL_LO16 || (ep->X_op == O_subtract - && now_seg == text_section && r == BFD_RELOC_PCREL_LO16)); continue; @@ -2611,7 +2610,6 @@ macro_build (place, counter, ep, name, fmt, va_alist) || r == BFD_RELOC_MIPS_GOT_HI16 || r == BFD_RELOC_MIPS_CALL_HI16)) || (ep->X_op == O_subtract - && now_seg == text_section && r == BFD_RELOC_PCREL_HI16_S))); if (ep->X_op == O_constant) { @@ -4150,23 +4148,23 @@ macro (ip) /* When generating embedded PIC code, we permit expressions of the form la $4,foo-bar - where bar is an address in the .text section. These are used + where bar is an address in the current section. These are used when getting the addresses of functions. We don't permit X_add_number to be non-zero, because if the symbol is external the relaxing code needs to know that any addend is purely the offset to X_op_symbol. */ if (mips_pic == EMBEDDED_PIC && offset_expr.X_op == O_subtract - && now_seg == text_section && (symbol_constant_p (offset_expr.X_op_symbol) - ? S_GET_SEGMENT (offset_expr.X_op_symbol) == text_section + ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg : (symbol_equated_p (offset_expr.X_op_symbol) && (S_GET_SEGMENT (symbol_get_value_expression (offset_expr.X_op_symbol) ->X_add_symbol) - == text_section))) + == now_seg))) && breg == 0 - && offset_expr.X_add_number == 0) + && (offset_expr.X_add_number == 0 + || OUTPUT_FLAVOR == bfd_target_elf_flavour)) { macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u", treg, (int) BFD_RELOC_PCREL_HI16_S); @@ -7666,11 +7664,15 @@ mips_ip (str, ip) default: /* unused default case avoids warnings. */ case 'L': newname = RDATA_SECTION_NAME; - if (USE_GLOBAL_POINTER_OPT && g_switch_value >= 8) + if ((USE_GLOBAL_POINTER_OPT && g_switch_value >= 8) + || mips_pic == EMBEDDED_PIC) newname = ".lit8"; break; case 'F': - newname = RDATA_SECTION_NAME; + if (mips_pic == EMBEDDED_PIC) + newname = ".lit8"; + else + newname = RDATA_SECTION_NAME; break; case 'l': assert (!USE_GLOBAL_POINTER_OPT @@ -7813,9 +7815,8 @@ mips_ip (str, ip) || offset_expr.X_add_number < -0x8000) && (mips_pic != EMBEDDED_PIC || offset_expr.X_op != O_subtract - || now_seg != text_section || (S_GET_SEGMENT (offset_expr.X_op_symbol) - != text_section))) + != now_seg))) break; if (c == 'h' || c == 'H') @@ -9495,6 +9496,7 @@ mips_frob_file () fixup requires the special reloc. */ #define SWITCH_TABLE(fixp) \ ((fixp)->fx_r_type == BFD_RELOC_32 \ + && OUTPUT_FLAVOR != bfd_target_elf_flavour \ && (fixp)->fx_addsy != NULL \ && (fixp)->fx_subsy != NULL \ && S_GET_SEGMENT ((fixp)->fx_addsy) == text_section \ @@ -9542,15 +9544,16 @@ md_apply_fix (fixP, valueP) symbol, we need to adjust the value. */ #ifdef OBJ_ELF if (fixP->fx_addsy != NULL && OUTPUT_FLAVOR == bfd_target_elf_flavour) + { if (S_GET_OTHER (fixP->fx_addsy) == STO_MIPS16 || S_IS_WEAK (fixP->fx_addsy) || (symbol_used_in_reloc_p (fixP->fx_addsy) && (((bfd_get_section_flags (stdoutput, - S_GET_SEGMENT (fixP->fx_addsy)) - & SEC_LINK_ONCE) != 0) - || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)), - ".gnu.linkonce", - sizeof (".gnu.linkonce") - 1)))) + S_GET_SEGMENT (fixP->fx_addsy)) + & SEC_LINK_ONCE) != 0) + || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)), + ".gnu.linkonce", + sizeof (".gnu.linkonce") - 1)))) { value -= S_GET_VALUE (fixP->fx_addsy); @@ -9558,12 +9561,29 @@ md_apply_fix (fixP, valueP) { /* In this case, the bfd_install_relocation routine will incorrectly add the symbol value back in. We just want - the addend to appear in the object file. */ + the addend to appear in the object file. + FIXME: If this makes VALUE zero, we're toast. */ value -= S_GET_VALUE (fixP->fx_addsy); } } -#endif + /* This code was generated using trial and error and so is + fragile and not trustworthy. If you change it, you should + rerun the elf-rel, elf-rel2, and empic testcases and ensure + they still pass. */ + if (fixP->fx_pcrel || fixP->fx_subsy != NULL) + { + value += fixP->fx_frag->fr_address + fixP->fx_where; + + /* BFD's REL handling, for MIPS, is _very_ weird. + This gives the right results, but it can't possibly + be the way things are supposed to work. */ + if (fixP->fx_r_type != BFD_RELOC_16_PCREL_S2 + || S_GET_SEGMENT (fixP->fx_addsy) != undefined_section) + value += fixP->fx_frag->fr_address + fixP->fx_where; + } + } +#endif fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */ @@ -9601,7 +9621,12 @@ md_apply_fix (fixP, valueP) case BFD_RELOC_PCREL_HI16_S: /* The addend for this is tricky if it is internal, so we just do everything here rather than in bfd_install_relocation. */ - if ((symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0) + if (OUTPUT_FLAVOR == bfd_target_elf_flavour + && !fixP->fx_done + && value != 0) + break; + if (fixP->fx_addsy + && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0) { /* For an external symbol adjust by the address to make it pcrel_offset. We use the address of the RELLO reloc @@ -9621,7 +9646,12 @@ md_apply_fix (fixP, valueP) case BFD_RELOC_PCREL_LO16: /* The addend for this is tricky if it is internal, so we just do everything here rather than in bfd_install_relocation. */ - if ((symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0) + if (OUTPUT_FLAVOR == bfd_target_elf_flavour + && !fixP->fx_done + && value != 0) + break; + if (fixP->fx_addsy + && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0) value += fixP->fx_frag->fr_address + fixP->fx_where; buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where; if (target_big_endian) @@ -9704,6 +9734,15 @@ md_apply_fix (fixP, valueP) if ((value & 0x3) != 0) as_bad_where (fixP->fx_file, fixP->fx_line, _("Branch to odd address (%lx)"), value); + + if (!fixP->fx_done && value != 0) + break; + /* If 'value' is zero, the remaining reloc code won't actually + do the store, so it must be done here. This is probably + a bug somewhere. */ + if (!fixP->fx_done) + value -= fixP->fx_frag->fr_address + fixP->fx_where; + value >>= 2; /* update old instruction data */ @@ -11064,6 +11103,8 @@ tc_gen_reloc (section, fixp) as_fatal (_("Double check fx_r_type in tc-mips.c:tc_gen_reloc")); fixp->fx_r_type = BFD_RELOC_GPREL32; } + else if (fixp->fx_pcrel == 0 || OUTPUT_FLAVOR == bfd_target_elf_flavour) + reloc->addend = fixp->fx_addnumber; else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16) { /* We use a special addend for an internal RELLO reloc. */ @@ -11088,8 +11129,6 @@ tc_gen_reloc (section, fixp) + fixp->fx_next->fx_frag->fr_address + fixp->fx_next->fx_where); } - else if (fixp->fx_pcrel == 0) - reloc->addend = fixp->fx_addnumber; else { if (OUTPUT_FLAVOR != bfd_target_aout_flavour) @@ -11228,7 +11267,8 @@ tc_gen_reloc (section, fixp) /* To support a PC relative reloc when generating embedded PIC code for ECOFF, we use a Cygnus extension. We check for that here to make sure that we don't let such a reloc escape normally. */ - if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour + if ((OUTPUT_FLAVOR == bfd_target_ecoff_flavour + || OUTPUT_FLAVOR == bfd_target_elf_flavour) && code == BFD_RELOC_16_PCREL_S2 && mips_pic != EMBEDDED_PIC) reloc->howto = NULL; @@ -11893,6 +11933,3 @@ s_loc (x) symbolP->sy_segment = now_seg; } #endif - - - diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 607c2f67cb..ef99b865cf 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2000-03-10 Geoffrey Keating <geoffk@cygnus.com> + + * gas/mips/empic.d: New file. + * gas/mips/empic.s: New file. + * gas/mips/mips16-e.d: New file. + * gas/mips/mips16-e.s: New file. + * gas/mips/mips16-f.d: New file. + * gas/mips/mips16-f.s: New file. + * gas/mips/mips.exp: Add empic, mips16-e. Add mips16-f as an + expected failure. + 2000-02-25 H.J. Lu <hjl@gnu.org> * gas/i386/general.l: Support a.out and coff. diff --git a/gas/testsuite/gas/mips/empic.d b/gas/testsuite/gas/mips/empic.d new file mode 100644 index 0000000000..3c6b4d43bf --- /dev/null +++ b/gas/testsuite/gas/mips/empic.d @@ -0,0 +1,155 @@ +#objdump: -rst -mmips:4000 +#name: MIPS empic +#as: -membedded-pic -mips3 + +# Check GNU-specific embedded relocs, for ELF. + +.*: +file format elf.*mips.* + +SYMBOL TABLE: +0+0000000 l d \.text 0+0000000 +0+0000000 l d \.data 0+0000000 +0+0000000 l d \.bss 0+0000000 +0+0000000 l d \.foo 0+0000000 +0+0000000 l d \.reginfo 0+0000000 +0+0000000 l d \.mdebug 0+0000000 +0+0000004 l \.text 0+0000000 l2 +0+0000000 \*UND\* 0+0000000 g1 +0+0000000 \*UND\* 0+0000000 g2 +0+0000100 l \.foo 0+0000000 l1 +0+0000034 l \.text 0+0000000 l3 +0+0000098 l \.text 0+0000000 l5 +0+0000004 l \.foo 0+0000000 l4 + + +RELOCATION RECORDS FOR \[\.text\]: +OFFSET TYPE VALUE +0+0000004 R_MIPS_GNU_REL16_S2 g1 +0+000000c R_MIPS_GNU_REL16_S2 g2 +0+0000014 R_MIPS_GNU_REL16_S2 g2 +0+000001c R_MIPS_GNU_REL16_S2 \.foo +0+0000024 R_MIPS_GNU_REL16_S2 \.text +0+000002c R_MIPS_GNU_REL16_S2 \.foo +0+0000034 R_MIPS_GNU_REL16_S2 \.text +0+000003c R_MIPS_GNU_REL_HI16 g1 +0+0000040 R_MIPS_GNU_REL_LO16 g1 +0+0000044 R_MIPS_GNU_REL_HI16 \.foo +0+0000048 R_MIPS_GNU_REL_LO16 \.foo +0+0000050 R_MIPS_32 g1 +0+0000054 R_MIPS_32 \.foo +0+0000058 R_MIPS_32 \.text +0+000005c R_MIPS_PC32 g1 +0+0000060 R_MIPS_PC32 \.foo +0+0000068 R_MIPS_64 g1 +0+0000070 R_MIPS_64 \.foo +0+0000078 R_MIPS_64 \.text +0+0000080 R_MIPS_PC64 g1 +0+0000088 R_MIPS_PC64 \.foo +0+0000098 R_MIPS_GNU_REL16_S2 \.text +0+000009c R_MIPS_GNU_REL16_S2 \.text +0+00000a0 R_MIPS_GNU_REL_HI16 \.text +0+00000a4 R_MIPS_GNU_REL_LO16 \.text +0+00000a8 R_MIPS_GNU_REL_HI16 \.text +0+00000ac R_MIPS_GNU_REL_LO16 \.text +0+00000b0 R_MIPS_32 \.text +0+00000b8 R_MIPS_64 \.text +0+00000cc R_MIPS_GNU_REL16_S2 \.text +0+00000d0 R_MIPS_GNU_REL16_S2 \.text +0+00000d4 R_MIPS_GNU_REL_HI16 \.text +0+00000d8 R_MIPS_GNU_REL_LO16 \.text +0+00000dc R_MIPS_GNU_REL_HI16 \.text +0+00000e0 R_MIPS_GNU_REL_LO16 \.text +0+00000e4 R_MIPS_32 \.text +0+00000f0 R_MIPS_64 \.text + + +RELOCATION RECORDS FOR \[\.foo\]: +OFFSET TYPE VALUE +0+0000004 R_MIPS_GNU_REL_HI16 g1 +0+0000008 R_MIPS_GNU_REL_LO16 g1 +0+000000c R_MIPS_GNU_REL_HI16 \.foo +0+0000010 R_MIPS_GNU_REL_LO16 \.foo +0+0000014 R_MIPS_GNU_REL_HI16 \.text +0+0000018 R_MIPS_GNU_REL_LO16 \.text +0+000001c R_MIPS_GNU_REL_HI16 g1 +0+0000020 R_MIPS_GNU_REL_LO16 g1 +0+0000024 R_MIPS_GNU_REL_HI16 g1 +0+0000028 R_MIPS_GNU_REL_LO16 g1 +0+000002c R_MIPS_GNU_REL_HI16 \.foo +0+0000030 R_MIPS_GNU_REL_LO16 \.foo +0+0000034 R_MIPS_GNU_REL_HI16 \.text +0+0000038 R_MIPS_GNU_REL_LO16 \.text +0+000003c R_MIPS_32 g1 +0+0000040 R_MIPS_32 \.foo +0+0000044 R_MIPS_32 \.text +0+0000048 R_MIPS_PC32 g1 +0+0000050 R_MIPS_PC32 \.text +0+0000058 R_MIPS_64 g1 +0+0000060 R_MIPS_64 \.foo +0+0000068 R_MIPS_64 \.text +0+0000070 R_MIPS_PC64 g1 +0+0000080 R_MIPS_PC64 \.text +0+0000088 R_MIPS_GNU_REL_HI16 g1 +0+000008c R_MIPS_GNU_REL_LO16 g1 +0+0000090 R_MIPS_GNU_REL_HI16 \.foo +0+0000094 R_MIPS_GNU_REL_LO16 \.foo +0+0000098 R_MIPS_GNU_REL_HI16 \.text +0+000009c R_MIPS_GNU_REL_LO16 \.text +0+00000a0 R_MIPS_GNU_REL_HI16 g1 +0+00000a4 R_MIPS_GNU_REL_LO16 g1 +0+00000a8 R_MIPS_GNU_REL_HI16 \.foo +0+00000ac R_MIPS_GNU_REL_LO16 \.foo +0+00000b0 R_MIPS_GNU_REL_HI16 \.text +0+00000b4 R_MIPS_GNU_REL_LO16 \.text +0+00000b8 R_MIPS_32 g1 +0+00000bc R_MIPS_32 \.foo +0+00000c0 R_MIPS_32 \.text +0+00000c4 R_MIPS_PC32 g1 +0+00000cc R_MIPS_PC32 \.text +0+00000d0 R_MIPS_64 g1 +0+00000d8 R_MIPS_64 \.foo +0+00000e0 R_MIPS_64 \.text +0+00000e8 R_MIPS_PC64 g1 +0+00000f8 R_MIPS_PC64 \.text + +Contents of section \.text: + 0000 00000000 0411ffff 00000000 1000ffff .* + 0010 00000000 1000ffff 00000000 0411003f .* + 0020 00000000 04110000 00000000 10000041 .* + 0030 00000000 10000000 00000000 3c030000 .* + 0040 [26]463000c 3c030000 [26]4630114 2403ffd0 .* + 0050 00000000 00000100 00000004 00000028 .* + 0060 0000012c ffffffd0 00000000 00000000 .* + 0070 00000000 00000100 00000000 00000004 .* + 0080 00000000 0000004c 00000000 00000154 .* + 0090 ffffffff ffffffd0 10000032 10000033 .* + 00a0 3c030000 [26]46300d8 3c030000 [26]46300e8 .* + 00b0 000000cc 00000034 00000000 000000cc .* + 00c0 00000000 00000034 00000000 10000032 .* + 00d0 10000033 3c030000 [26]463010c 3c030000 .* + 00e0 [26]463011c 000000cc 00000034 00000000 .* + 00f0 00000000 000000cc 00000000 00000034 .* +Contents of section \.data: +Contents of section \.reginfo: + 0000 80000008 00000000 00000000 00000000 .* + 0010 00000000 00000000 .* +Contents of section \.mdebug: +#... +Contents of section \.foo: + 0000 00000000 3c030000 [26]4630004 3c030000 .* + 0010 [26]463010c 3c030000 [26]4630018 3c030000 .* + 0020 [26]463001c 3c030000 [26]4630024 3c030000 .* + 0030 [26]463012c 3c030000 [26]4630038 00000000 .* + 0040 00000100 00000004 00000044 000000fc .* + 0050 00000050 00000000 00000000 00000000 .* + 0060 00000000 00000100 00000000 00000004 .* + 0070 00000000 0000006c 00000000 000000fc .* + 0080 00000000 00000080 3c030000 [26]463008c .* + 0090 3c030000 [26]4630194 3c030000 [26]46300a0 .* + 00a0 3c030000 [26]46300a4 3c030000 [26]46301ac .* + 00b0 3c030000 [26]46300b8 00000004 00000104 .* + 00c0 00000008 000000c4 00000100 000000d0 .* + 00d0 00000000 00000004 00000000 00000104 .* + 00e0 00000000 00000008 00000000 000000e8 .* + 00f0 00000000 00000100 00000000 000000fc .* + 0100 00000000 .* diff --git a/gas/testsuite/gas/mips/empic.s b/gas/testsuite/gas/mips/empic.s new file mode 100644 index 0000000000..2c485b3568 --- /dev/null +++ b/gas/testsuite/gas/mips/empic.s @@ -0,0 +1,112 @@ +# Check GNU-specific embedded relocs, for ELF. + + .text + .set noreorder + nop +l2: jal g1 # R_MIPS_GNU_REL16_S2 g1 -1 + nop + b g2 # R_MIPS_GNU_REL16_S2 g2 -1 + nop + b g2 # R_MIPS_GNU_REL16_S2 g2 -1 + nop + jal l1 # R_MIPS_GNU_REL16_S2 .foo 3F + nop + jal l2 # R_MIPS_GNU_REL16_S2 .text 0 or -9 + nop + b l1+8 # R_MIPS_GNU_REL16_S2 .foo 41 + nop +l3: + b l2 # R_MIPS_GNU_REL16_S2 .text 0 or -D + nop + la $3,g1-l3 # R_MIPS_GNU_REL_HI16 g1 0 + # R_MIPS_GNU_REL_LO16 g1 C + la $3,l1-l3 # R_MIPS_GNU_REL_HI16 .foo 0 + # R_MIPS_GNU_REL_LO16 .foo 114 + la $3,l2-l3 # -30 + .word g1 # R_MIPS_32 g1 0 + .word l1 # R_MIPS_32 .foo 100 + .word l2 # R_MIPS_32 .text 4 + .word g1-l3 # R_MIPS_PC32 g1 28 + .word l1-l3 # R_MIPS_PC32 .foo 12C + .word l2-l3 # -30 + .align 3 + .dword g1 # R_MIPS_64 g1 0 + .dword l1 # R_MIPS_64 .foo 100 + .dword l2 # R_MIPS_64 .text 4 + .dword g1-l3 # R_MIPS_PC64 g1 4C + .dword l1-l3 # R_MIPS_PC64 .foo 154 + .dword l2-l3 # -30 +l5: + b 2f # R_MIPS_GNU_REL16_S2 .text 32 + b 2f+4 # R_MIPS_GNU_REL16_S2 .text 33 + la $3,2f-l5 # R_MIPS_GNU_REL_HI16 .text 0 + # R_MIPS_GNU_REL_HI16 .text D8 + la $3,2f+8-l5 # R_MIPS_GNU_REL_HI16 .text 0 + # R_MIPS_GNU_REL_HI16 .text E8 + + .word 2f # R_MIPS_32 .text CC + .word 2f-l5 # R_MIPS_PC32 .text EC or 34 + .dword 2f # R_MIPS_64 .text CC + .dword 2f-l5 # R_MIPS_PC64 .text F8 or 34 + nop +2: # at address 0xCC. + b 2b # R_MIPS_GNU_REL16_S2 .text 32 + b 2b+4 # R_MIPS_GNU_REL16_S2 .text 33 + la $3,2b-l5 # R_MIPS_GNU_REL_HI16 .text 0 + # R_MIPS_GNU_REL_HI16 .text 10C + la $3,2b+8-l5 # R_MIPS_GNU_REL_HI16 .text 0 + # R_MIPS_GNU_REL_HI16 .text 11C + .word 2b # R_MIPS_32 .text CC + .word 2b-l5 # R_MIPS_PC32 .text 11C or 34 + nop + .dword 2b # R_MIPS_64 .text CC + .dword 2b-l5 # R_MIPS_PC64 .text 98 or 34 + + .section ".foo","ax",@progbits + nop +l4: + la $3,g1-l4 + la $3,l1-l4 + la $3,l2-l4 + la $3,g1-l4 + + dla $3,g1-l4 + dla $3,l1-l4 + dla $3,l2-l4 + + .word g1 + .word l1 + .word l2 + .word g1-l4 + .word l1-l4 + .word l2-l4 + .dword g1 + .dword l1 + .dword l2 + .dword g1-l4 + .dword l1-l4 + .dword l2-l4 + + la $3,g1-l4+4 + la $3,l1-l4+4 + la $3,l2-l4+4 + + dla $3,g1-l4+4 + dla $3,l1-l4+4 + dla $3,l2-l4+4 + + .word g1+4 + .word l1+4 + .word l2+4 + .word g1-l4+4 + .word l1-l4+4 + .word l2-l4+4 + .dword g1+4 + .dword l1+4 + .dword l2+4 + .dword g1-l4+4 + .dword l1-l4+4 + .dword l2-l4+4 +l1: + + nop diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index f1a0d57d33..6ed1c021fe 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -107,5 +107,11 @@ if [istarget mips*-*-*] then { } { run_dump_test "e32-rel2" } + run_dump_test "empic" + if { !$no_mips16 } { + run_dump_test "mips16-e" + setup_xfail "mips*-*-*" + run_dump_test "mips16-f" + } } } diff --git a/gas/testsuite/gas/mips/mips16-e.d b/gas/testsuite/gas/mips/mips16-e.d new file mode 100644 index 0000000000..1f23f685e1 --- /dev/null +++ b/gas/testsuite/gas/mips/mips16-e.d @@ -0,0 +1,41 @@ +#objdump: -rst -mips16 +#name: MIPS16 reloc +#as: -mips16 + +# Check MIPS16 reloc processing + +.*: +file format elf.*mips.* + +SYMBOL TABLE: +0+0000000 l d \.text 0+0000000 +0+0000000 l d \.data 0+0000000 +0+0000000 l d \.bss 0+0000000 +0+0000000 l d foo 0+0000000 +0+0000000 l d \.reginfo 0+0000000 +0+0000000 l d \.mdebug 0+0000000 +0+0000002 l \.text 0+0000000 0xf0 l1 +0+0000004 l \.text 0+0000000 0xf0 L1.1 +0+0000000 \*UND\* 0+0000000 g1 + + +RELOCATION RECORDS FOR \[foo\]: +OFFSET TYPE VALUE +0+0000000 R_MIPS_32 l1 +0+0000004 R_MIPS_32 l1 +0+0000008 R_MIPS_32 L1.1 +0+000000c R_MIPS_32 L1.1 +0+0000010 R_MIPS_32 g1 +0+0000014 R_MIPS_32 g1 + + +Contents of section \.text: + 0000 65006500 65006500 .* +Contents of section \.data: +Contents of section \.reginfo: + 0000 00000001 00000000 00000000 00000000 .* + 0010 00000000 00000000 .* +Contents of section \.mdebug: +#... +Contents of section foo: + 0000 00000000 00000008 00000000 00000003 .* + 0010 00000000 00000008 .* diff --git a/gas/testsuite/gas/mips/mips16-e.s b/gas/testsuite/gas/mips/mips16-e.s new file mode 100644 index 0000000000..b19d0200c1 --- /dev/null +++ b/gas/testsuite/gas/mips/mips16-e.s @@ -0,0 +1,13 @@ + .set noreorder + .text + nop +l1: nop +1: nop + nop + .section "foo" + .word l1 + .word l1+8 + .word 1b + .word 1b+3 + .word g1 + .word g1+8 diff --git a/gas/testsuite/gas/mips/mips16-f.d b/gas/testsuite/gas/mips/mips16-f.d new file mode 100644 index 0000000000..3a6af1bd5a --- /dev/null +++ b/gas/testsuite/gas/mips/mips16-f.d @@ -0,0 +1,33 @@ +#objdump: -rst -mips16 +#name: MIPS16 reloc 2 +#as: -mips16 + +# Check MIPS16 reloc processing + +.*: +file format elf.*mips.* + +SYMBOL TABLE: +0+0000000 l d \.text 0+0000000 +0+0000000 l d \.data 0+0000000 +0+0000000 l d \.bss 0+0000000 +0+0000000 l d foo 0+0000000 +0+0000000 l d \.reginfo 0+0000000 +0+0000000 l d \.mdebug 0+0000000 +0+0000002 l \.text 0+0000000 0xf0 l1 + + +RELOCATION RECORDS FOR \[foo\]: +OFFSET TYPE VALUE +0+0000000 R_MIPS_32 l1 + + +Contents of section \.text: + 0000 65006500 .* +Contents of section \.data: +Contents of section \.reginfo: + 0000 00000001 00000000 00000000 00000000 .* + 0010 00000000 00000000 .* +Contents of section \.mdebug: +#... +Contents of section foo: + 0000 00000003 .* diff --git a/gas/testsuite/gas/mips/mips16-f.s b/gas/testsuite/gas/mips/mips16-f.s new file mode 100644 index 0000000000..0b254bd794 --- /dev/null +++ b/gas/testsuite/gas/mips/mips16-f.s @@ -0,0 +1,6 @@ + .set noreorder + .text + nop +l1: nop + .section "foo" + .word l1+3 diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 129ad30e2c..5a683e1ee0 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,9 @@ +2000-03-10 Geoffrey Keating <geoffk@cygnus.com> + + * mips.h: Add R_MIPS_GNU_REL_HI16, R_MIPS_GNU_REL_LO16, + R_MIPS_GNU_REL16_S2, R_MIPS_PC64 and R_MIPS_PC32 relocation + numbers. + 2000-02-23 Linas Vepstas <linas@linas.org> * i370.h: New file. diff --git a/include/elf/mips.h b/include/elf/mips.h index 06f836ca0d..1e2a9f99a7 100644 --- a/include/elf/mips.h +++ b/include/elf/mips.h @@ -75,6 +75,12 @@ START_RELOC_NUMBERS (elf_mips_reloc_type) /* These relocs are used for the mips16. */ RELOC_NUMBER (R_MIPS16_26, 100) RELOC_NUMBER (R_MIPS16_GPREL, 101) + /* These are GNU extensions to handle embedded-pic. */ + RELOC_NUMBER (R_MIPS_PC32, 248) + RELOC_NUMBER (R_MIPS_PC64, 249) + RELOC_NUMBER (R_MIPS_GNU_REL16_S2, 250) + RELOC_NUMBER (R_MIPS_GNU_REL_LO16, 251) + RELOC_NUMBER (R_MIPS_GNU_REL_HI16, 252) /* These are GNU extensions to enable C++ vtable garbage collection. */ RELOC_NUMBER (R_MIPS_GNU_VTINHERIT, 253) RELOC_NUMBER (R_MIPS_GNU_VTENTRY, 254) |