This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fixing MIPS16 vs LA25 stubs


Hi Richard,
The MIPS16 code has some complicated relations with LA25 stubs
(LUI/ADDUI $25 sequences added by BFD when calling from non-PIC to PIC).

Current PLT support is capable of adding (either prepending or separate
stub) LA25 sequences to create $t9 on entry of a PIC callee. However,
when the called routine is MIPS16 code with a FP-stub (stub is 32-bit),
then we have, for example:

int main (void)
{
  return __fixdfdi (0.0);  // libgcc function
}

Build as:
mips-linux-gnu-gcc -c -O2 testcase.c    # build as 32-bit
mips-linux-gnu-gcc -mips16 testcase.o   # link with MIPS16 libs
./a.out
Segmentation fault

Disassembly:
00400930 <__fn_stub___fixdfdi>:
  400930:       3c1c0002        lui     gp,0x2
  400934:       279c8100        addiu   gp,gp,-32512
  400938:       0399e021        addu    gp,gp,t9
  40093c:       8f998024        lw      t9,-32732(gp)  <--segfault
  400940:       27390621        addiu   t9,t9,1569
  400944:       44056000        mfc1    a1,$f12
  400948:       03200008        jr      t9
  40094c:       44046800        mfc1    a0,$f13

The call is from main:
00400610 <main>:
  400610:       44806000        mtc1    zero,$f12
  400614:       0810024c        j       400930 <__fn_stub___fixdfdi>
  400618:       44806800        mtc1    zero,$f13
  40061c:       00000000        nop

The actual __fixdfdi body, which is MIPS16 code:
00400620 <__fixdfdi>:
  400620:       f000 6a02       li      v0,2
  400624:       f410 0b0c       la      v1,3f8a30 <_DYNAMIC-0x774c>
  400628:       f400 3240       sll     v0,16
  40062c:       e269            addu    v0,v1
  40062e:       659a            move    gp,v0
  400630:       64f6            save    48,ra,s0-s1
  ...

The problem is that 'la $25' headers/trampolines are needed for the
"stub", which is 32-bit code and calculates $gp using $t9, not the
MIPS16 function itself (which as the BFD support already correctly
determines, are never needed due to MIPS16's PC-relative capabilities).
Also note that this problem is avoided when -mno-plt is used.


My patch attached here modifies the LA25 insertion to accommodate the
case where we have a "MIPS16 function with a kept 32-bit stub", and uses
the stub as the point of insertion. The correctly linked results are now
like:
00400610 <main>:
  400610:       44806000        mtc1    zero,$f12
  400614:       0810024c        j       400930 <.pic.__fixdfdi>
  400618:       44806800        mtc1    zero,$f13
  40061c:       00000000        nop
...
00400930 <.pic.__fixdfdi>:
  400930:       3c190040        lui     t9,0x40
  400934:       27390938        addiu   t9,t9,2360

00400938 <__fn_stub___fixdfdi>:
  400938:       3c1c0002        lui     gp,0x2
  40093c:       279c80f8        addiu   gp,gp,-32520
  400940:       0399e021        addu    gp,gp,t9
  400944:       8f998024        lw      t9,-32732(gp)
  400948:       27390621        addiu   t9,t9,1569
  40094c:       44056000        mfc1    a1,$f12
  400950:       03200008        jr      t9
  400954:       44046800        mfc1    a0,$f13

Which should be correctly generated "stub of stub" code :)  This is for
the 32-bit->16-bit case. There's also some handling to skip the LA25
stub for 16-bit->16-bit case.

Thanks,
Chung-Lin

2011-12-10  Chung-Lin Tang  <cltang@codesourcery.com>
	    Catherine Moore  <clm@codesourcery.com>
	    Sandra Loosemore  <sandra@codesourcery.com>

        * elfxx-mips.c (mips_elf_local_pic_function_p): Return true when
        H is a MIPS16 function with a kept 32-bit stub. Update comments.
        (mips_elf_add_la25_intro): Use MIPS16 stub section as place of
        insertion when it exists.
        (mips_elf_add_la25_stub): Always use LUI/ADDIU prepending for
        MIPS16 stubs. Update comments.
        (mips_elf_calculate_relocation): Redirect relocation to point to
        the LA25 stub if it exists, instead of the MIPS16 stub. Don't
	use la25 stub for mips16->mips16 calls.
        (mips_elf_create_la25_stub): Change $25 target calculation to
        base on MIPS16 stub if it exists.



Attachment: la25.diff
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]