diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2007-06-25 10:13:57 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2007-06-25 10:13:57 +0000 |
commit | b314ec0eae7a778810550ccf87cd92eda7feaf2a (patch) | |
tree | 7c95af55b8663108c70d89bc4eb432cd3d5b4b47 /gas/config/tc-mips.c | |
parent | b6fd0dfb46df6f46eace51d68b9de8318ebe3842 (diff) | |
download | gdb-b314ec0eae7a778810550ccf87cd92eda7feaf2a.zip gdb-b314ec0eae7a778810550ccf87cd92eda7feaf2a.tar.gz gdb-b314ec0eae7a778810550ccf87cd92eda7feaf2a.tar.bz2 |
bfd/
* elfxx-mips.c (mips_elf_calculate_relocation): Allow local stubs
to be used for calls from MIPS16 code.
gas/
* config/tc-mips.h (TC_SYMFIELD_TYPE): New.
* config/tc-mips.c (append_insn): Record which symbols have
R_MIPS16_26 relocations against them.
(mips_fix_adjustable): Don't reduce relocations against such symbols.
ld/testsuite/
* ld-mips-elf/mips16-local-stubs-1.s,
* ld-mips-elf/mips16-local-stubs-1.d: 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 | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 47a4b3c..39f681e 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -2792,6 +2792,11 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, reloc_type[0] == BFD_RELOC_16_PCREL_S2, reloc_type[0]); + /* Tag symbols that have a R_MIPS16_26 relocation against them. */ + if (reloc_type[0] == BFD_RELOC_MIPS16_JMP + && ip->fixp[0]->fx_addsy) + *symbol_get_tc (ip->fixp[0]->fx_addsy) = 1; + /* These relocations can have an addend that won't fit in 4 octets for 64bit assembly. */ if (HAVE_64BIT_GPRS @@ -13612,11 +13617,50 @@ mips_fix_adjustable (fixS *fixp) return 0; #ifdef OBJ_ELF - /* Don't adjust relocations against mips16 symbols, so that the linker - can find them if it needs to set up a stub. */ + /* R_MIPS16_26 relocations against non-MIPS16 functions might resolve + to a floating-point stub. The same is true for non-R_MIPS16_26 + relocations against MIPS16 functions; in this case, the stub becomes + the function's canonical address. + + Floating-point stubs are stored in unique .mips16.call.* or + .mips16.fn.* sections. If a stub T for function F is in section S, + the first relocation in section S must be against F; this is how the + linker determines the target function. All relocations that might + resolve to T must also be against F. We therefore have the following + restrictions, which are given in an intentionally-redundant way: + + 1. We cannot reduce R_MIPS16_26 relocations against non-MIPS16 + symbols. + + 2. We cannot reduce a stub's relocations against non-MIPS16 symbols + if that stub might be used. + + 3. We cannot reduce non-R_MIPS16_26 relocations against MIPS16 + symbols. + + 4. We cannot reduce a stub's relocations against MIPS16 symbols if + that stub might be used. + + There is a further restriction: + + 5. We cannot reduce R_MIPS16_26 relocations against MIPS16 symbols + on targets with in-place addends; the relocation field cannot + encode the low bit. + + For simplicity, we deal with (3)-(5) by not reducing _any_ relocation + against a MIPS16 symbol. + + We deal with (1)-(2) by saying that, if there's a R_MIPS16_26 + relocation against some symbol R, no relocation against R may be + reduced. (Note that this deals with (2) as well as (1) because + relocations against global symbols will never be reduced on ELF + targets.) This approach is a little simpler than trying to detect + stub sections, and gives the "all or nothing" per-symbol consistency + that we have for MIPS16 symbols. */ if (IS_ELF - && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16 - && fixp->fx_subsy == NULL) + && fixp->fx_subsy == NULL + && (S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16 + || *symbol_get_tc (fixp->fx_addsy))) return 0; #endif |