diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2008-08-06 19:44:47 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2008-08-06 19:44:47 +0000 |
commit | 738e53487d7edb6b7428b889dcb0721d3d9e2c43 (patch) | |
tree | 6d055845fb85211181d8a9e38a0fa8076e990443 /gas/config/tc-mips.c | |
parent | d57a3c85f6eee87b04852e98cce75af080969951 (diff) | |
download | gdb-738e53487d7edb6b7428b889dcb0721d3d9e2c43.zip gdb-738e53487d7edb6b7428b889dcb0721d3d9e2c43.tar.gz gdb-738e53487d7edb6b7428b889dcb0721d3d9e2c43.tar.bz2 |
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.
Diffstat (limited to 'gas/config/tc-mips.c')
-rw-r--r-- | gas/config/tc-mips.c | 85 |
1 files changed, 65 insertions, 20 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 1e2adc3..c03cca2 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -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) |