From b314ec0eae7a778810550ccf87cd92eda7feaf2a Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 25 Jun 2007 10:13:57 +0000 Subject: 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. --- bfd/ChangeLog | 5 ++ bfd/elfxx-mips.c | 3 +- gas/ChangeLog | 7 ++ gas/config/tc-mips.c | 52 ++++++++++- gas/config/tc-mips.h | 3 + ld/testsuite/ChangeLog | 6 ++ ld/testsuite/ld-mips-elf/mips-elf.exp | 2 + ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d | 114 ++++++++++++++++++++++++ ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s | 49 ++++++++++ 9 files changed, 235 insertions(+), 6 deletions(-) create mode 100644 ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d create mode 100644 ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 258fd6f..6b396db 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2007-06-25 Richard Sandiford + + * elfxx-mips.c (mips_elf_calculate_relocation): Allow local stubs + to be used for calls from MIPS16 code. + 2007-06-23 Andreas Schwab * configure.in (--with-separate-debug-dir): New option. diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 1bccb33..dafd607 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -4092,8 +4092,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, /* If this is a 16-bit call to a 32- or 64-bit function with a stub, we need to redirect the call to the stub. */ else if (r_type == R_MIPS16_26 && !info->relocatable - && h != NULL - && ((h->call_stub != NULL || h->call_fp_stub != NULL) + && ((h != NULL && (h->call_stub != NULL || h->call_fp_stub != NULL)) || (local_p && elf_tdata (input_bfd)->local_call_stubs != NULL && elf_tdata (input_bfd)->local_call_stubs[r_symndx] != NULL)) diff --git a/gas/ChangeLog b/gas/ChangeLog index c713436..19a28fa 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2007-06-25 Richard Sandiford + + * 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. + 2007-06-22 Sterling Augustine * config/tc-xtensa.c (xg_assembly_relax): Comment termination rules. 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 diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h index 5a1e830..117417c 100644 --- a/gas/config/tc-mips.h +++ b/gas/config/tc-mips.h @@ -61,6 +61,9 @@ extern void mips_handle_align (struct frag *); struct insn_label_list; #define TC_SEGMENT_INFO_TYPE struct insn_label_list * +/* This field is nonzero if the symbol is the target of a MIPS16 jump. */ +#define TC_SYMFIELD_TYPE int + /* Tell assembler that we have an itbl_mips.h header file to include. */ #define HAVE_ITBL_CPU diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 9cd711a..e3e557e 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-06-25 Richard Sandiford + + * 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. + 2007-06-19 H.J. Lu PR ld/4590 diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index d022c8d..eab8678 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -269,3 +269,5 @@ set mips16_intermix_test { } run_ld_link_tests $mips16_intermix_test + +run_dump_test "mips16-local-stubs-1" diff --git a/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d b/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d new file mode 100644 index 0000000..9990493 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d @@ -0,0 +1,114 @@ +#name: MIPS16 interlinking for local functions 1 +#source: mips16-local-stubs-1.s +#as: -mips4 +#ld: -Ttext 0x20000000 -e caller1 +#objdump: -dr +#... +Disassembly of section \.text: + +20000000 : +20000000: 03e00008 jr ra +20000004: 00000000 nop + +20000008 : +20000008: 03e00008 jr ra +2000000c: 00000000 nop + +20000010

: +20000010: e820 jr ra +20000012: 6500 nop + +20000014 : +20000014: 03e00008 jr ra +20000018: 00000000 nop + +2000001c : +2000001c: 03e00008 jr ra +20000020: 00000000 nop + +20000024

: +20000024: e820 jr ra +20000026: 6500 nop + +20000028 : +20000028: 03e00008 jr ra +2000002c: 00000000 nop + +20000030 : +20000030: 03e00008 jr ra +20000034: 00000000 nop + +20000038

: +20000038: e820 jr ra +2000003a: 6500 nop + +2000003c : +2000003c: 0c000000 jal 20000000 +20000040: 00000000 nop +20000044: 0c000005 jal 20000014 +20000048: 00000000 nop +2000004c: 0c000002 jal 20000008 +20000050: 00000000 nop +20000054: 0c000007 jal 2000001c +20000058: 00000000 nop +2000005c: 0c000024 jal 20000090 +20000060: 00000000 nop +20000064: 0c000028 jal 200000a0 +20000068: 00000000 nop + +2000006c : +2000006c: 1c00 0030 jalx 200000c0 +20000070: 6500 nop +20000072: 1c00 0038 jalx 200000e0 +20000076: 6500 nop +20000078: 1c00 0034 jalx 200000d0 +2000007c: 6500 nop +2000007e: 1c00 003c jalx 200000f0 +20000082: 6500 nop +20000084: 1800 0004 jal 20000010

+20000088: 6500 nop +2000008a: 1800 0009 jal 20000024

+2000008e: 6500 nop + +20000090 : +20000090: 3c012000 lui at,0x2000 +20000094: 24210011 addiu at,at,17 +20000098: 00200008 jr at +2000009c: 00000000 nop + +200000a0 : +200000a0: 3c012000 lui at,0x2000 +200000a4: 24210025 addiu at,at,37 +200000a8: 00200008 jr at +200000ac: 00000000 nop + +# This isn't actually called, but is referenced from the .pdr section. +200000b0 : +200000b0: 3c012000 lui at,0x2000 +200000b4: 24210039 addiu at,at,57 +200000b8: 00200008 jr at +200000bc: 00000000 nop + +200000c0 : +200000c0: 3c012000 lui at,0x2000 +200000c4: 24210000 addiu at,at,0 +200000c8: 00200008 jr at +200000cc: 00000000 nop + +200000d0 : +200000d0: 3c012000 lui at,0x2000 +200000d4: 24210008 addiu at,at,8 +200000d8: 00200008 jr at +200000dc: 00000000 nop + +200000e0 : +200000e0: 3c012000 lui at,0x2000 +200000e4: 24210014 addiu at,at,20 +200000e8: 00200008 jr at +200000ec: 00000000 nop + +200000f0 : +200000f0: 3c012000 lui at,0x2000 +200000f4: 2421001c addiu at,at,28 +200000f8: 00200008 jr at +200000fc: 00000000 nop diff --git a/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s b/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s new file mode 100644 index 0000000..9904402 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s @@ -0,0 +1,49 @@ + .macro makestub,type,func,section + .text + .set \type + .type \func,@function + .ent \func +\func: + jr $31 + .end \func + + .section \section,"ax",@progbits + .set nomips16 + .type stub_for_\func,@function + .ent stub_for_\func +stub_for_\func: + .set noat + la $1,\func + jr $1 + .set at + .end stub_for_\func + .endm + + .macro makestubs,id + makestub nomips16,f\id,.mips16.call.F\id + makestub nomips16,g\id,.mips16.call.fp.G\id + makestub mips16,h\id,.mips16.fn.H\id + .endm + + .macro makecaller,type,func + .text + .set \type + .globl \func + .type \func,@function + .ent \func +\func: + jal f1 + jal f2 + jal g1 + jal g2 + jal h1 + jal h2 + .end \func + .endm + + makestubs 1 + makestubs 2 + makestubs 3 + + makecaller nomips16,caller1 + makecaller mips16,caller2 -- cgit v1.1