forked from Imagelibrary/binutils-gdb
bfd/
* reloc.c (BFD_RELOC_MIPS16_GOT16, BFD_RELOC_MIPS16_CALL16): Declare. * libbfd.h, bfd-in2.h: Regenerate. * elf32-mips.c (elf_mips16_howto_table_rel): Fill in reserved R_MIPS16_GOT16 and R_MIPS16_CALL16 entries. (mips16_reloc_map): Add mappings. * elf64-mips.c (mips16_elf64_howto_table_rel): Fill in reserved R_MIPS16_GOT16 and R_MIPS16_CALL16 entries. (mips16_elf64_howto_table_rela): Likewise. (mips16_reloc_map): Add mappings. * elfn32-mips.c (elf_mips16_howto_table_rel): Fill in reserved R_MIPS16_GOT16 and R_MIPS16_CALL16 entries. (elf_mips16_howto_table_rela): Likewise. (mips16_reloc_map): Add mappings. * elfxx-mips.c (mips_elf_create_shadow_symbol): New function. (section_allows_mips16_refs_p): Likewise. (mips16_stub_symndx): Likewise. (mips_elf_check_mips16_stubs): Treat the data argument as a bfd_link_info. Mark every dynamic symbol as needing MIPS16 stubs and create a "shadow" symbol for the original MIPS16 definition. (mips16_reloc_p, got16_reloc_p, call16_reloc_p, hi16_reloc_p) (lo16_reloc_p, mips16_call_reloc_p): New functions. (_bfd_mips16_elf_reloc_unshuffle): Use mips16_reloc_p to generalize relocation checks. (_bfd_mips16_elf_reloc_shuffle): Likewise. (_bfd_mips_elf_lo16_reloc): Handle R_MIPS16_GOT16. (mips_elf_got16_entry): Add comment. (mips_elf_calculate_relocation): Use hi16_reloc_p, lo16_reloc_p, mips16_call_reloc_p, call16_reloc_p and got16_reloc_p to generalize relocation checks. Use section_allows_mips16_refs_p instead of mips16_stub_section_p. Handle R_MIPS16_CALL16 and R_MIPS16_GOT16, allowing the former to refer directly to a MIPS16 function if its stub is not needed. (mips16_stub_section_p): Delete. (_bfd_mips_elf_symbol_processing): Convert odd-valued function symbols into even MIPS16 symbols. (mips_elf_add_lo16_rel_addend): Use mips16_reloc_p to generalize a relocation check. (_bfd_mips_elf_check_relocs): Calculate "bed" and "rel_end" earlier in the function. Use mips16_stub_symndx to identify the target function. Avoid out-of-bounds accesses when the stub has no relocations; report an error instead. Use section_allows_mips16_refs_p instead of mips16_stub_section_p. Use mips16_call_reloc_p and got16_reloc_p to generalize relocation checks. Handle R_MIPS16_CALL16 and R_MIPS16_GOT16. Don't create dynamic relocations for absolute references to __gnu_local_gp. (_bfd_mips_elf_always_size_sections): Pass a bfd_link_info as the argument to mips_elf_check_mips16_stubs. Generalize comment. (_bfd_mips_elf_relocate_section): Use hi16_reloc_p and got16_reloc_p to generalize relocation checks. (_bfd_mips_elf_finish_dynamic_symbol): If a dynamic MIPS16 function symbol has a non-MIPS16 stub, redirect the symbol to the stub. Fix an overly long line. Don't give dynamic symbols type STO_MIPS16. (_bfd_mips_elf_gc_sweep_hook): Handle R_MIPS16_CALL16 and R_MIPS16_GOT16. gas/ * config/tc-mips.c (mips16_reloc_p, got16_reloc_p, hi16_reloc_p) (lo16_reloc_p): New functions. (reloc_needs_lo_p): Use hi16_reloc_p and got16_reloc_p to generalize relocation checks. (matching_lo_reloc): New function. (fixup_has_matching_lo_p): Use it. (mips16_mark_labels): Don't clobber a symbol's visibility. (append_insn): Use hi16_reloc_p and lo16_reloc_p. (mips16_ip): Handle BFD_RELOC_MIPS16_GOT16 and BFD_RELOC_MIPS16_CALL16. (md_apply_fix): Likewise. (mips16_percent_op): Add %got and %call16. (mips_frob_file): Use got16_reloc_p to generalize relocation checks. Use matching_lo_reloc. (mips_force_relocation): Use hi16_reloc_p and lo16_reloc_p to generalize relocation checks. (mips_fix_adjustable): Use lo16_reloc_p to generalize relocation checks. gas/testsuite/ * gas/mips/elf-rel8-mips16.d, gas/mips/elf-rel8-mips16.s, * gas/mips/elf-rel9-mips16.d, gas/mips/elf-rel9-mips16.s, * gas/mips/elf-rel13-mips16.d, gas/mips/elf-rel13-mips16.s: New tests. * gas/mips/mips.exp: Run them. ld/testsuite/ * ld-mips-elf/mips16-local-stubs-1.d: Remove stub_for_h3, which was only referenced by the .pdr section, and was not actually needed by code. * ld-mips-elf/mips16-intermix.d: Remove unused static function stubs. * ld-mips-elf/mips16-pic-1a.s, ld-mips-elf/mips16-pic-1b.s, ld-mips-elf/mips16-pic-1-dummy.s, ld-mips-elf/mips16-pic-1.dd, ld-mips-elf/mips16-pic-1.gd, ld-mips-elf/mips16-pic-1.inc, ld-mips-elf/mips16-pic-1.ld, ld-mips-elf/mips16-pic-2a.s, ld-mips-elf/mips16-pic-2b.s, ld-mips-elf/mips16-pic-2.ad, ld-mips-elf/mips16-pic-2.dd, ld-mips-elf/mips16-pic-2.gd, ld-mips-elf/mips16-pic-2.nd, ld-mips-elf/mips16-pic-2.rd: New tests. * ld-mips-elf/mips-elf.exp: Run them.
This commit is contained in:
@@ -2129,6 +2129,46 @@ md_assemble (char *str)
|
||||
}
|
||||
}
|
||||
|
||||
/* Convenience functions for abstracting away the differences between
|
||||
MIPS16 and non-MIPS16 relocations. */
|
||||
|
||||
static inline bfd_boolean
|
||||
mips16_reloc_p (bfd_reloc_code_real_type reloc)
|
||||
{
|
||||
switch (reloc)
|
||||
{
|
||||
case BFD_RELOC_MIPS16_JMP:
|
||||
case BFD_RELOC_MIPS16_GPREL:
|
||||
case BFD_RELOC_MIPS16_GOT16:
|
||||
case BFD_RELOC_MIPS16_CALL16:
|
||||
case BFD_RELOC_MIPS16_HI16_S:
|
||||
case BFD_RELOC_MIPS16_HI16:
|
||||
case BFD_RELOC_MIPS16_LO16:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bfd_boolean
|
||||
got16_reloc_p (bfd_reloc_code_real_type reloc)
|
||||
{
|
||||
return reloc == BFD_RELOC_MIPS_GOT16 || reloc == BFD_RELOC_MIPS16_GOT16;
|
||||
}
|
||||
|
||||
static inline bfd_boolean
|
||||
hi16_reloc_p (bfd_reloc_code_real_type reloc)
|
||||
{
|
||||
return reloc == BFD_RELOC_HI16_S || reloc == BFD_RELOC_MIPS16_HI16_S;
|
||||
}
|
||||
|
||||
static inline bfd_boolean
|
||||
lo16_reloc_p (bfd_reloc_code_real_type reloc)
|
||||
{
|
||||
return reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_MIPS16_LO16;
|
||||
}
|
||||
|
||||
/* Return true if the given relocation might need a matching %lo().
|
||||
This is only "might" because SVR4 R_MIPS_GOT16 relocations only
|
||||
need a matching %lo() when applied to local symbols. */
|
||||
@@ -2137,11 +2177,19 @@ static inline bfd_boolean
|
||||
reloc_needs_lo_p (bfd_reloc_code_real_type reloc)
|
||||
{
|
||||
return (HAVE_IN_PLACE_ADDENDS
|
||||
&& (reloc == BFD_RELOC_HI16_S
|
||||
|| reloc == BFD_RELOC_MIPS16_HI16_S
|
||||
&& (hi16_reloc_p (reloc)
|
||||
/* VxWorks R_MIPS_GOT16 relocs never need a matching %lo();
|
||||
all GOT16 relocations evaluate to "G". */
|
||||
|| (reloc == BFD_RELOC_MIPS_GOT16 && mips_pic != VXWORKS_PIC)));
|
||||
|| (got16_reloc_p (reloc) && mips_pic != VXWORKS_PIC)));
|
||||
}
|
||||
|
||||
/* Return the type of %lo() reloc needed by RELOC, given that
|
||||
reloc_needs_lo_p. */
|
||||
|
||||
static inline bfd_reloc_code_real_type
|
||||
matching_lo_reloc (bfd_reloc_code_real_type reloc)
|
||||
{
|
||||
return mips16_reloc_p (reloc) ? BFD_RELOC_MIPS16_LO16 : BFD_RELOC_LO16;
|
||||
}
|
||||
|
||||
/* Return true if the given fixup is followed by a matching R_MIPS_LO16
|
||||
@@ -2151,8 +2199,7 @@ static inline bfd_boolean
|
||||
fixup_has_matching_lo_p (fixS *fixp)
|
||||
{
|
||||
return (fixp->fx_next != NULL
|
||||
&& (fixp->fx_next->fx_r_type == BFD_RELOC_LO16
|
||||
|| fixp->fx_next->fx_r_type == BFD_RELOC_MIPS16_LO16)
|
||||
&& fixp->fx_next->fx_r_type == matching_lo_reloc (fixp->fx_r_type)
|
||||
&& fixp->fx_addsy == fixp->fx_next->fx_addsy
|
||||
&& fixp->fx_offset == fixp->fx_next->fx_offset);
|
||||
}
|
||||
@@ -2934,8 +2981,6 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||
&& (reloc_type[0] == BFD_RELOC_16
|
||||
|| reloc_type[0] == BFD_RELOC_32
|
||||
|| reloc_type[0] == BFD_RELOC_MIPS_JMP
|
||||
|| reloc_type[0] == BFD_RELOC_HI16_S
|
||||
|| reloc_type[0] == BFD_RELOC_LO16
|
||||
|| reloc_type[0] == BFD_RELOC_GPREL16
|
||||
|| reloc_type[0] == BFD_RELOC_MIPS_LITERAL
|
||||
|| reloc_type[0] == BFD_RELOC_GPREL32
|
||||
@@ -2948,8 +2993,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||
|| reloc_type[0] == BFD_RELOC_MIPS_REL16
|
||||
|| reloc_type[0] == BFD_RELOC_MIPS_RELGOT
|
||||
|| reloc_type[0] == BFD_RELOC_MIPS16_GPREL
|
||||
|| reloc_type[0] == BFD_RELOC_MIPS16_HI16_S
|
||||
|| reloc_type[0] == BFD_RELOC_MIPS16_LO16))
|
||||
|| hi16_reloc_p (reloc_type[0])
|
||||
|| lo16_reloc_p (reloc_type[0])))
|
||||
ip->fixp[0]->fx_no_overflow = 1;
|
||||
|
||||
if (mips_relax.sequence)
|
||||
@@ -10092,6 +10137,8 @@ mips16_ip (char *str, struct mips_cl_insn *ip)
|
||||
/* Stuff the immediate value in now, if we can. */
|
||||
if (imm_expr.X_op == O_constant
|
||||
&& *imm_reloc > BFD_RELOC_UNUSED
|
||||
&& *imm_reloc != BFD_RELOC_MIPS16_GOT16
|
||||
&& *imm_reloc != BFD_RELOC_MIPS16_CALL16
|
||||
&& insn->pinfo != INSN_MACRO)
|
||||
{
|
||||
valueT tmp;
|
||||
@@ -10861,6 +10908,8 @@ static const struct percent_op_match mips16_percent_op[] =
|
||||
{
|
||||
{"%lo", BFD_RELOC_MIPS16_LO16},
|
||||
{"%gprel", BFD_RELOC_MIPS16_GPREL},
|
||||
{"%got", BFD_RELOC_MIPS16_GOT16},
|
||||
{"%call16", BFD_RELOC_MIPS16_CALL16},
|
||||
{"%hi", BFD_RELOC_MIPS16_HI16_S}
|
||||
};
|
||||
|
||||
@@ -11954,7 +12003,7 @@ mips_frob_file (void)
|
||||
|
||||
/* If a GOT16 relocation turns out to be against a global symbol,
|
||||
there isn't supposed to be a matching LO. */
|
||||
if (l->fixp->fx_r_type == BFD_RELOC_MIPS_GOT16
|
||||
if (got16_reloc_p (l->fixp->fx_r_type)
|
||||
&& !pic_need_relax (l->fixp->fx_addsy, l->seg))
|
||||
continue;
|
||||
|
||||
@@ -11972,12 +12021,7 @@ mips_frob_file (void)
|
||||
hi_pos = NULL;
|
||||
lo_pos = NULL;
|
||||
matched_lo_p = FALSE;
|
||||
|
||||
if (l->fixp->fx_r_type == BFD_RELOC_MIPS16_HI16
|
||||
|| l->fixp->fx_r_type == BFD_RELOC_MIPS16_HI16_S)
|
||||
looking_for_rtype = BFD_RELOC_MIPS16_LO16;
|
||||
else
|
||||
looking_for_rtype = BFD_RELOC_LO16;
|
||||
looking_for_rtype = matching_lo_reloc (l->fixp->fx_r_type);
|
||||
|
||||
for (pos = &seginfo->fix_root; *pos != NULL; pos = &(*pos)->fx_next)
|
||||
{
|
||||
@@ -12030,8 +12074,8 @@ mips_force_relocation (fixS *fixp)
|
||||
if (HAVE_NEWABI
|
||||
&& S_GET_SEGMENT (fixp->fx_addsy) == bfd_abs_section_ptr
|
||||
&& (fixp->fx_r_type == BFD_RELOC_MIPS_SUB
|
||||
|| fixp->fx_r_type == BFD_RELOC_HI16_S
|
||||
|| fixp->fx_r_type == BFD_RELOC_LO16))
|
||||
|| hi16_reloc_p (fixp->fx_r_type)
|
||||
|| lo16_reloc_p (fixp->fx_r_type)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -12119,6 +12163,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
||||
case BFD_RELOC_MIPS_CALL_HI16:
|
||||
case BFD_RELOC_MIPS_CALL_LO16:
|
||||
case BFD_RELOC_MIPS16_GPREL:
|
||||
case BFD_RELOC_MIPS16_GOT16:
|
||||
case BFD_RELOC_MIPS16_CALL16:
|
||||
case BFD_RELOC_MIPS16_HI16:
|
||||
case BFD_RELOC_MIPS16_HI16_S:
|
||||
case BFD_RELOC_MIPS16_JMP:
|
||||
@@ -13926,8 +13972,7 @@ mips_fix_adjustable (fixS *fixp)
|
||||
placed anywhere. Rather than break backwards compatibility by changing
|
||||
this, it seems better not to force the issue, and instead keep the
|
||||
original symbol. This will work with either linker behavior. */
|
||||
if ((fixp->fx_r_type == BFD_RELOC_LO16
|
||||
|| fixp->fx_r_type == BFD_RELOC_MIPS16_LO16
|
||||
if ((lo16_reloc_p (fixp->fx_r_type)
|
||||
|| reloc_needs_lo_p (fixp->fx_r_type))
|
||||
&& HAVE_IN_PLACE_ADDENDS
|
||||
&& (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE) != 0)
|
||||
|
||||
Reference in New Issue
Block a user