mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 07:08:01 +08:00
* config/tc-mips.c (mips_validate_fix): New function.
* config/tc-mips.h (TC_VALIDATE_FIX): Define. (mips_validate_fix): Declare.
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
2003-03-12 Alexandre Oliva <aoliva@redhat.com>
|
||||||
|
|
||||||
|
* config/tc-mips.c (mips_validate_fix): New function.
|
||||||
|
* config/tc-mips.h (TC_VALIDATE_FIX): Define.
|
||||||
|
(mips_validate_fix): Declare.
|
||||||
|
|
||||||
2003-03-12 Alexandre Oliva <aoliva@redhat.com>
|
2003-03-12 Alexandre Oliva <aoliva@redhat.com>
|
||||||
|
|
||||||
* Reverted 2003-03-02's patch.
|
* Reverted 2003-03-02's patch.
|
||||||
|
@ -11026,6 +11026,85 @@ mips_force_relocation (fixp)
|
|||||||
|| fixp->fx_r_type == BFD_RELOC_PCREL_LO16));
|
|| fixp->fx_r_type == BFD_RELOC_PCREL_LO16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 (fixP, seg)
|
||||||
|
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)
|
||||||
|
&& mips_pic != EMBEDDED_PIC)
|
||||||
|
|| 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef OBJ_ELF
|
#ifdef OBJ_ELF
|
||||||
static int
|
static int
|
||||||
mips_need_elf_addend_fixup (fixP)
|
mips_need_elf_addend_fixup (fixP)
|
||||||
|
@ -140,6 +140,15 @@ extern int mips_fix_adjustable PARAMS ((struct fix *));
|
|||||||
#define TC_FORCE_RELOCATION(FIX) mips_force_relocation (FIX)
|
#define TC_FORCE_RELOCATION(FIX) mips_force_relocation (FIX)
|
||||||
extern int mips_force_relocation PARAMS ((struct fix *));
|
extern int mips_force_relocation PARAMS ((struct 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 PARAMS ((struct fix *, asection *));
|
||||||
|
|
||||||
/* Register mask variables. These are set by the MIPS assembly code
|
/* Register mask variables. These are set by the MIPS assembly code
|
||||||
and used by ECOFF and possibly other object file formats. */
|
and used by ECOFF and possibly other object file formats. */
|
||||||
extern unsigned long mips_gprmask;
|
extern unsigned long mips_gprmask;
|
||||||
|
Reference in New Issue
Block a user