Hi,

 As originally signalled here:

http://gcc.gnu.org/ml/gcc-patches/2012-02/msg00140.html

here is a change to prevent MIPS16 stub calls from being made through the 
PLT by making them hidden.  This is needed to avoid $2 and possibly $3 
from being clobbered by MIPS16 code in the PLT.  Originally I thought only 
return stubs were affected, but I have since realised all the libgcc stubs 
rely on $2, so none can be called via the PLT.  This breakage can be 
triggered by linking with the `-shared-libgcc' option; otherwise libgcc.a 
code is used avoiding the problem.

 Since these stubs are a preexisting interface I have decided there is no 
need to go through the pain of link-once functions as you did for 
__mips16_rdhwr.  I think we'd only need them if we changed the API, at 
which point we'd have to keep current libgcc bits for preexisting object 
code anyway.  For the same reason this change retains libgcc_s.so bits for 
preexisting executables and shared libraries, but stops them being 
exported for new static links so that libgcc.a bits are always used 
instead.

 I have tested this change for the mips-linux-gnu target and o32/MIPS32r2 
multilib with `-mips16' and `-shared-libgcc' options.  There have been no 
regressions to a plain `-mips16' run whereas as it stands we have 
numerous.  OK to apply?

 BTW, what's the "Check for MicroMIPS support." note seen in the 
config.host piece of the patch referring to?

2013-08-01  Maciej W. Rozycki  <ma...@codesourcery.com>
            Catherine Moore  <c...@codesourcery.com>

        libgcc/
        * config/mips/mips16.S (RET_FUNCTION): Rename to...
        (_RET_FUNCTION): ... this.
        (RET_FUNCTION): New macro.
        (CALL_STUB_NO_RET): Rename to...
        (_CALL_STUB_NO_RET): ... this.
        (CALL_STUB_NO_RET): New macro.
        (CALL_STUB_RET): Rename to...
        (_CALL_STUB_RET): ... this.
        (CALL_STUB_RET): New macro.
        * config.host <mips*-*-linux>: For non-R5900 add t-slibgcc-libgcc
        to tmake_file.

  Maciej

gcc-mips16-hidden-stub.diff
Index: gcc-fsf-trunk-quilt/libgcc/config.host
===================================================================
--- gcc-fsf-trunk-quilt.orig/libgcc/config.host 2013-07-31 17:48:35.000000000 
+0100
+++ gcc-fsf-trunk-quilt/libgcc/config.host      2013-07-31 17:50:02.438694583 
+0100
@@ -742,13 +742,13 @@ mips*-*-linux*)                           # Linux MIPS, 
either 
        tmake_file="${tmake_file} t-crtfm"
        # Check for MicroMIPS support.
        case ${host} in
-               mips64r5900* | mipsr5900*)
-                       # The MIPS16 support code uses floating point
-                       # instructions that are not supported on r5900.
-                       ;;
-               *)
-                       tmake_file="${tmake_file} mips/t-mips16"
-                       ;;
+         mips64r5900* | mipsr5900*)
+           # The MIPS16 support code uses floating point
+           # instructions that are not supported on r5900.
+           ;;
+         *)
+           tmake_file="${tmake_file} mips/t-mips16 t-slibgcc-libgcc"
+           ;;
        esac
        md_unwind_header=mips/linux-unwind.h
        if test "${ac_cv_sizeof_long_double}" = 16; then
Index: gcc-fsf-trunk-quilt/libgcc/config/mips/mips16.S
===================================================================
--- gcc-fsf-trunk-quilt.orig/libgcc/config/mips/mips16.S        2013-07-31 
17:48:35.000000000 +0100
+++ gcc-fsf-trunk-quilt/libgcc/config/mips/mips16.S     2013-07-31 
17:58:30.058731920 +0100
@@ -479,14 +479,34 @@ STARTFN (__mips16_fix_truncdfsi)
 #endif
 #endif /* !__mips_single_float */
 
+/* We don't export stubs from libgcc_s.so and always require static
+   versions to be pulled from libgcc.a as needed because they use $2
+   and possibly $3 as arguments, diverging from the standard SysV ABI,
+   and as such would require severe pessimisation of MIPS16 PLT entries
+   just for this single special case.
+
+   For compatibility with old binaries that used safe standard MIPS PLT
+   entries and referred to these functions we still export them at
+   version GCC_4.4.0 for run-time loading only.  /*
+
 /* Define a function NAME that moves a return value of mode MODE from
    FPRs to GPRs.  */
 
-#define RET_FUNCTION(NAME, MODE)       \
+#define _RET_FUNCTION(NAME, MODE)      \
 STARTFN (NAME);                                \
        MOVE_##MODE##_RET (t, $31);     \
        ENDFN (NAME)
 
+#ifdef SHARED
+#define RET_FUNCTION(NAME, MODE)               \
+       _RET_FUNCTION (NAME##_compat, MODE);    \
+       .symver NAME##_compat, NAME##@GCC_4.4.0
+#else
+#define RET_FUNCTION(NAME, MODE)               \
+       _RET_FUNCTION (NAME, MODE);             \
+       .hidden NAME
+#endif
+
 #ifdef L_m16retsf
 RET_FUNCTION (__mips16_ret_sf, SF)
 #endif
@@ -525,7 +545,7 @@ RET_FUNCTION (__mips16_ret_dc, DC)
    pointer.  They must copy the floating point arguments from the GPRs
    to FPRs and then call function $2.  */
 
-#define CALL_STUB_NO_RET(NAME, CODE)   \
+#define _CALL_STUB_NO_RET(NAME, CODE)  \
 STARTFN (NAME);                                \
        STUB_ARGS_##CODE;               \
        .set    noreorder;              \
@@ -534,6 +554,16 @@ STARTFN (NAME);                            \
        .set    reorder;                \
        ENDFN (NAME)
 
+#ifdef SHARED
+#define CALL_STUB_NO_RET(NAME, CODE)                   \
+       _CALL_STUB_NO_RET (NAME##_compat, CODE);        \
+       .symver NAME##_compat, NAME##@GCC_4.4.0
+#else
+#define CALL_STUB_NO_RET(NAME, CODE)                   \
+       _CALL_STUB_NO_RET (NAME, CODE);                 \
+       .hidden NAME
+#endif
+
 #ifdef L_m16stub1
 CALL_STUB_NO_RET (__mips16_call_stub_1, 1)
 #endif
@@ -574,7 +604,7 @@ CALL_STUB_NO_RET (__mips16_call_stub_10,
    being called is 16 bits, in which case the copy is unnecessary;
    however, it's faster to always do the copy.  */
 
-#define CALL_STUB_RET(NAME, CODE, MODE)                                        
\
+#define _CALL_STUB_RET(NAME, CODE, MODE)                               \
 STARTFN (NAME);                                                                
\
        .cfi_startproc;                                                 \
        /* Create a fake CFA 4 bytes below the stack pointer.  */       \
@@ -593,6 +623,16 @@ STARTFN (NAME);                                            
                \
        .cfi_endproc;                                                   \
        ENDFN (NAME)
 
+#ifdef SHARED
+#define CALL_STUB_RET(NAME, CODE, MODE)                        \
+       _CALL_STUB_RET (NAME##_compat, CODE, MODE);     \
+       .symver NAME##_compat, NAME##@GCC_4.4.0
+#else
+#define CALL_STUB_RET(NAME, CODE, MODE)                        \
+       _CALL_STUB_RET (NAME, CODE, MODE);              \
+       .hidden NAME
+#endif
+
 /* First, instantiate the single-float set.  */
 
 #ifdef L_m16stubsf0

Reply via email to