* 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.
This commit is contained in:
Daniel Jacobowitz
2005-11-23 14:04:18 +00:00
parent a14199dbd5
commit bad36eacda
25 changed files with 416 additions and 278 deletions

View File

@@ -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;