diff options
author | Daniel Jacobowitz <drow@false.org> | 2005-11-23 14:04:18 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2005-11-23 14:04:18 +0000 |
commit | bad36eacdad37042c4efb1c5fbf48476b47de82b (patch) | |
tree | 09ba18d0af929dc68344a1788a63c3d48f0613e7 /gas/config | |
parent | * elfcode.h (elf_object_p): Delay the setting of start_address (diff) | |
download | binutils-gdb-bad36eacdad37042c4efb1c5fbf48476b47de82b.tar.gz binutils-gdb-bad36eacdad37042c4efb1c5fbf48476b47de82b.tar.bz2 binutils-gdb-bad36eacdad37042c4efb1c5fbf48476b47de82b.zip |
bfd/
* elf32-mips.c (elf_mips_howto_table_rel): Use rightshift 2 for
R_MIPS_PC16.
(mips_reloc_map): Map BFD_RELOC_16_PCREL_S2 to R_MIPS_PC16.
(bfd_elf32_bfd_reloc_type_lookup): Don't handle
BFD_RELOC_16_PCREL_S2.
* elf64-mips.c (mips_elf64_howto_table_rel): Use rightshift 2 for
R_MIPS_PC16.
(mips_elf64_howto_table_rela): Likewise.
(mips_reloc_map): Map BFD_RELOC_16_PCREL_S2 to R_MIPS_PC16.
(bfd_elf64_bfd_reloc_type_lookup): Don't handle
BFD_RELOC_16_PCREL_S2.
* elfn32-mips.c (elf_mips_howto_table_rel): Use rightshift 2 for
R_MIPS_PC16.
(elf_mips_howto_table_rela): Likewise.
(mips_reloc_map): Map BFD_RELOC_16_PCREL_S2 to R_MIPS_PC16.
(bfd_elf32_bfd_reloc_type_lookup): Don't handle
BFD_RELOC_16_PCREL_S2.
* elfxx-mips.c: Formatting fixes.
(mips_elf_calculate_relocation): Handle R_MIPS_GNU_REL16_S2
and R_MIPS_PC16 identically.
gas/
* config/tc-mips.c (append_insn): Handle BFD_RELOC_16_PCREL_S2.
(macro_build): Complain for invalid branch displacements.
(mips_validate_fix): Delete.
(md_apply_fix): Re-add pcrel support for branches. Use consistent
text for misaligned branch targets.
(tc_gen_reloc: Re-add pcrel support for branches. Handle strange
BFD pcrel processing. Remove error for unresolved branches.
* config/tc-mips.h (TC_VALIDATE_FIX, mips_validate_fix): Delete.
gas/testsuite/
* gas/mips/bge.d, gas/mips/bge.s, gas/mips/bgeu.d, gas/mips/bgeu.s,
gas/mips/blt.d, gas/mips/blt.s, gas/mips/bltu.d,
gas/mips/bltu.s: Reactivate external branch tests.
* gas/mips/branch-misc-2.d, gas/mips/branch-misc-2pic.d,
gas/mips/branch-misc-2-64.d, gas/mips/branch-misc-2pic-64.d: New
tests.
* gas/mips/branch-misc-2.l, gas/mips/branch-misc-2pic.l,
gas/testsuite/gas/mips/branch-misc-2pic.s: Remove.
* gas/mips/mips.exp: Adjust branch-misc-2 tests. Add 64-bit
variants.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-mips.c | 144 | ||||
-rw-r--r-- | gas/config/tc-mips.h | 9 |
2 files changed, 43 insertions, 110 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 4f1afeacc69..557fb4007c1 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -2410,7 +2410,16 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, break; case BFD_RELOC_16_PCREL_S2: - goto need_reloc; + if ((address_expr->X_add_number & 3) != 0) + as_bad (_("branch to misaligned address (0x%lx)"), + (unsigned long) address_expr->X_add_number); + if (mips_relax_branch) + goto need_reloc; + if ((address_expr->X_add_number + 0x20000) & ~0x3ffff) + as_bad (_("branch address range overflow (0x%lx)"), + (unsigned long) address_expr->X_add_number); + ip->insn_opcode |= (address_expr->X_add_number >> 2) & 0xffff; + break; default: internalError (); @@ -3139,15 +3148,22 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) case 'p': assert (ep != NULL); + /* * This allows macro() to pass an immediate expression for * creating short branches without creating a symbol. - * Note that the expression still might come from the assembly - * input, in which case the value is not checked for range nor - * is a relocation entry generated (yuck). + * + * We don't allow branch relaxation for these branches, as + * they should only appear in ".set nomacro" anyway. */ if (ep->X_op == O_constant) { + if ((ep->X_add_number & 3) != 0) + as_bad (_("branch to misaligned address (0x%lx)"), + (unsigned long) ep->X_add_number); + if ((ep->X_add_number + 0x20000) & ~0x3ffff) + as_bad (_("branch address range overflow (0x%lx)"), + (unsigned long) ep->X_add_number); insn.insn_opcode |= (ep->X_add_number >> 2) & 0xffff; ep = NULL; } @@ -11361,83 +11377,6 @@ mips_force_relocation (fixS *fixp) return 0; } -/* This hook is called before a fix is simplified. We don't really - decide whether to skip a fix here. Rather, we turn global symbols - used as branch targets into local symbols, such that they undergo - simplification. We can only do this if the symbol is defined and - it is in the same section as the branch. If this doesn't hold, we - emit a better error message than just saying the relocation is not - valid for the selected object format. - - FIXP is the fix-up we're going to try to simplify, SEG is the - segment in which the fix up occurs. The return value should be - non-zero to indicate the fix-up is valid for further - simplifications. */ - -int -mips_validate_fix (struct fix *fixP, asection *seg) -{ - /* There's a lot of discussion on whether it should be possible to - use R_MIPS_PC16 to represent branch relocations. The outcome - seems to be that it can, but gas/bfd are very broken in creating - RELA relocations for this, so for now we only accept branches to - symbols in the same section. Anything else is of dubious value, - since there's no guarantee that at link time the symbol would be - in range. Even for branches to local symbols this is arguably - wrong, since it we assume the symbol is not going to be - overridden, which should be possible per ELF library semantics, - but then, there isn't a dynamic relocation that could be used to - this effect, and the target would likely be out of range as well. - - Unfortunately, it seems that there is too much code out there - that relies on branches to symbols that are global to be resolved - as if they were local, like the IRIX tools do, so we do it as - well, but with a warning so that people are reminded to fix their - code. If we ever get back to using R_MIPS_PC16 for branch - targets, this entire block should go away (and probably the - whole function). */ - - if (fixP->fx_r_type == BFD_RELOC_16_PCREL_S2 - && ((OUTPUT_FLAVOR == bfd_target_ecoff_flavour - || OUTPUT_FLAVOR == bfd_target_elf_flavour) - || bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16_PCREL_S2) == NULL) - && fixP->fx_addsy) - { - if (! S_IS_DEFINED (fixP->fx_addsy)) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("Cannot branch to undefined symbol.")); - /* Avoid any further errors about this fixup. */ - fixP->fx_done = 1; - } - else if (S_GET_SEGMENT (fixP->fx_addsy) != seg) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("Cannot branch to symbol in another section.")); - fixP->fx_done = 1; - } - else if (S_IS_EXTERNAL (fixP->fx_addsy)) - { - symbolS *sym = fixP->fx_addsy; - - if (mips_pic == SVR4_PIC) - as_warn_where (fixP->fx_file, fixP->fx_line, - _("Pretending global symbol used as branch target is local.")); - - fixP->fx_addsy = symbol_create (S_GET_NAME (sym), - S_GET_SEGMENT (sym), - S_GET_VALUE (sym), - symbol_get_frag (sym)); - copy_symbol_attributes (fixP->fx_addsy, sym); - S_CLEAR_EXTERNAL (fixP->fx_addsy); - assert (symbol_resolved_p (sym)); - symbol_mark_resolved (fixP->fx_addsy); - } - } - - return 1; -} - /* Apply a fixup to the object file. */ void @@ -11462,7 +11401,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where); - assert (! fixP->fx_pcrel); + assert (! fixP->fx_pcrel || fixP->fx_r_type == BFD_RELOC_16_PCREL_S2); /* Don't treat parts of a composite relocation as done. There are two reasons for this: @@ -11474,7 +11413,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) constants. The easiest way of dealing with the pathological exceptions is to generate a relocation against STN_UNDEF and leave everything up to the linker. */ - if (fixP->fx_addsy == NULL && fixP->fx_tcbit == 0) + if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel && fixP->fx_tcbit == 0) fixP->fx_done = 1; switch (fixP->fx_r_type) @@ -11519,7 +11458,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_MIPS16_GPREL: case BFD_RELOC_MIPS16_HI16: case BFD_RELOC_MIPS16_HI16_S: - assert (! fixP->fx_pcrel); /* Nothing needed to do. The value comes from the reloc entry */ break; @@ -11589,7 +11527,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_16_PCREL_S2: if ((*valP & 0x3) != 0) as_bad_where (fixP->fx_file, fixP->fx_line, - _("Branch to odd address (%lx)"), (long) *valP); + _("Branch to misaligned address (%lx)"), (long) *valP); /* * We need to save the bits in the instruction since fixup_segment() @@ -13307,8 +13245,24 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - assert (! fixp->fx_pcrel); - reloc->addend = fixp->fx_addnumber; + if (fixp->fx_pcrel) + { + assert (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2); + + /* At this point, fx_addnumber is "symbol offset - pcrel address". + Relocations want only the symbol offset. */ + reloc->addend = fixp->fx_addnumber + reloc->address; + if (OUTPUT_FLAVOR != bfd_target_elf_flavour) + { + /* A gruesome hack which is a result of the gruesome gas + reloc handling. What's worse, for COFF (as opposed to + ECOFF), we might need yet another copy of reloc->address. + See bfd_install_relocation. */ + reloc->addend += reloc->address; + } + } + else + reloc->addend = fixp->fx_addnumber; /* Since the old MIPS ELF ABI uses Rel instead of Rela, encode the vtable entry to be used in the relocation's section offset. */ @@ -13320,18 +13274,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) code = fixp->fx_r_type; - /* To support a PC relative reloc, we used a Cygnus extension. - We check for that here to make sure that we don't let such a - reloc escape normally. (FIXME: This was formerly used by - embedded-PIC support, but is now used by branch handling in - general. That probably should be fixed.) */ - if ((OUTPUT_FLAVOR == bfd_target_ecoff_flavour - || OUTPUT_FLAVOR == bfd_target_elf_flavour) - && code == BFD_RELOC_16_PCREL_S2) - reloc->howto = NULL; - else - reloc->howto = bfd_reloc_type_lookup (stdoutput, code); - + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); if (reloc->howto == NULL) { as_bad_where (fixp->fx_file, fixp->fx_line, @@ -13408,8 +13351,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) exp.X_add_number = fragp->fr_offset; fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal, - 4, &exp, 1, - BFD_RELOC_16_PCREL_S2); + 4, &exp, 1, BFD_RELOC_16_PCREL_S2); fixp->fx_file = fragp->fr_file; fixp->fx_line = fragp->fr_line; diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h index e657f3c5373..bc642b0a177 100644 --- a/gas/config/tc-mips.h +++ b/gas/config/tc-mips.h @@ -122,15 +122,6 @@ extern int mips_force_relocation (struct fix *); #define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \ (! SEG_NORMAL (SEG) || mips_force_relocation (FIX)) -/* We use this to turn branches to global symbols into branches to - local symbols, so that they can be simplified. */ -#define TC_VALIDATE_FIX(fixp, this_segment, skip_label) \ - do \ - if (! mips_validate_fix ((fixp), (this_segment))) \ - goto skip_label; \ - while (0) -extern int mips_validate_fix (struct fix *, asection *); - /* Register mask variables. These are set by the MIPS assembly code and used by ECOFF and possibly other object file formats. */ extern unsigned long mips_gprmask; |