From f53db356f53686cb0e4ddb25946b8cff9e82453d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 22 Oct 2010 13:58:13 +0200 Subject: libm/x86: use call instead of jump for wrappers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC can emit prologue/epilogue code for the functions in various different cases: - frame pointers - PIC build (to load ebx for indirect calls/jumps) - forced stack smashing protection If we used jump in such cases, we'd corrupt the call stack and crash. Signed-off-by: Timo Teräs Signed-off-by: Denys Vlasenko --- libm/ldouble_wrappers.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'libm/ldouble_wrappers.c') diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c index bf7ae15f0..f78a97a05 100644 --- a/libm/ldouble_wrappers.c +++ b/libm/ldouble_wrappers.c @@ -61,6 +61,10 @@ long long func##l(long double x) \ * a long double or returning a double). So we can simply jump to func. * Using __GI_func in jump to make optimized intra-library jump. * gcc will still generate a useless "ret" after asm. Oh well... + * + * Update: we do need to use call (instead of tail jump) as gcc can create + * stack frame, and push/modify/pop ebx during PIC build. + * TODO: add conditionals to use tail jump if possible? */ # define WRAPPER1(func) \ long double func##l(long double x) \ @@ -69,7 +73,7 @@ long double func##l(long double x) \ __asm__ ( \ " fldt %1\n" \ " fstpl %1\n" \ - " jmp " __stringify(__GI_##func) "\n" \ + " call " __stringify(__GI_##func) "\n" \ : "=t" (st_top) \ : "m" (x) \ ); \ @@ -82,7 +86,7 @@ int func##l(long double x) \ __asm__ ( \ " fldt %1\n" \ " fstpl %1\n" \ - " jmp " __stringify(__GI_##func) "\n" \ + " call " __stringify(__GI_##func) "\n" \ : "=a" (ret) \ : "m" (x) \ ); \ @@ -95,7 +99,7 @@ long func##l(long double x) \ __asm__ ( \ " fldt %1\n" \ " fstpl %1\n" \ - " jmp " __stringify(__GI_##func) "\n" \ + " call " __stringify(__GI_##func) "\n" \ : "=a" (ret) \ : "m" (x) \ ); \ @@ -108,7 +112,7 @@ long long func##l(long double x) \ __asm__ ( \ " fldt %1\n" \ " fstpl %1\n" \ - " jmp " __stringify(__GI_##func) "\n" \ + " call " __stringify(__GI_##func) "\n" \ : "=A" (ret) \ : "m" (x) \ ); \ -- cgit v1.2.3 From d726ada135fa7324b44b47d1d5fcf3f5317d343c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 31 Oct 2010 01:42:08 +0200 Subject: libm: revert wrong ldouble wrapper hack "fix" Signed-off-by: Denys Vlasenko --- libm/ldouble_wrappers.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'libm/ldouble_wrappers.c') diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c index f78a97a05..80c9ed8b6 100644 --- a/libm/ldouble_wrappers.c +++ b/libm/ldouble_wrappers.c @@ -37,7 +37,7 @@ long long func##l(long double x) \ return func((double) x); \ } -#if defined __i386__ && defined __OPTIMIZE__ +#if defined __i386__ && defined __OPTIMIZE__ && !defined __UCLIBC_HAS_SSP__ # undef WRAPPER1 # undef int_WRAPPER1 # undef long_WRAPPER1 @@ -62,9 +62,11 @@ long long func##l(long double x) \ * Using __GI_func in jump to make optimized intra-library jump. * gcc will still generate a useless "ret" after asm. Oh well... * - * Update: we do need to use call (instead of tail jump) as gcc can create - * stack frame, and push/modify/pop ebx during PIC build. - * TODO: add conditionals to use tail jump if possible? + * If you discover a build mode in which gcc creates a stack frame + * incompatible with this hack, do not "fix" by replacing jmp with call + * in the wrappers. This will make functions use wrong offset + * for accessing on-stack parameter. + * Instead, add more conditions to guarding #if above. */ # define WRAPPER1(func) \ long double func##l(long double x) \ @@ -73,7 +75,7 @@ long double func##l(long double x) \ __asm__ ( \ " fldt %1\n" \ " fstpl %1\n" \ - " call " __stringify(__GI_##func) "\n" \ + " jmp " __stringify(__GI_##func) "\n" \ : "=t" (st_top) \ : "m" (x) \ ); \ @@ -86,7 +88,7 @@ int func##l(long double x) \ __asm__ ( \ " fldt %1\n" \ " fstpl %1\n" \ - " call " __stringify(__GI_##func) "\n" \ + " jmp " __stringify(__GI_##func) "\n" \ : "=a" (ret) \ : "m" (x) \ ); \ @@ -99,7 +101,7 @@ long func##l(long double x) \ __asm__ ( \ " fldt %1\n" \ " fstpl %1\n" \ - " call " __stringify(__GI_##func) "\n" \ + " jmp " __stringify(__GI_##func) "\n" \ : "=a" (ret) \ : "m" (x) \ ); \ @@ -112,7 +114,7 @@ long long func##l(long double x) \ __asm__ ( \ " fldt %1\n" \ " fstpl %1\n" \ - " call " __stringify(__GI_##func) "\n" \ + " jmp " __stringify(__GI_##func) "\n" \ : "=A" (ret) \ : "m" (x) \ ); \ -- cgit v1.2.3 From 195931714a882765af150167115dcc9077da2213 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 31 Oct 2010 03:02:00 +0100 Subject: libm: remove int_WRAPPER_C99 macro, add test which checks that I did not break it Signed-off-by: Denys Vlasenko --- libm/ldouble_wrappers.c | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) (limited to 'libm/ldouble_wrappers.c') diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c index 80c9ed8b6..e2d4d8036 100644 --- a/libm/ldouble_wrappers.c +++ b/libm/ldouble_wrappers.c @@ -122,17 +122,6 @@ long long func##l(long double x) \ } #endif /* __i386__ && __OPTIMIZE__ */ -#if defined __NO_LONG_DOUBLE_MATH -# define int_WRAPPER_C99(func) /* not needed */ -# else -# define int_WRAPPER_C99(func) \ -int func##l(long double x) \ -{ \ - return func((double) x); \ -} \ -libm_hidden_def(func##l) -#endif - /* Implement the following, as defined by SuSv3 */ #if 0 long double acoshl(long double); @@ -508,26 +497,31 @@ long double significandl(long double x) } #endif -#ifdef __DO_C99_MATH__ +#if defined __DO_C99_MATH__ && !defined __NO_LONG_DOUBLE_MATH -#ifdef L___fpclassifyl -int_WRAPPER_C99(__fpclassify) -#endif +# ifdef L___fpclassifyl +int_WRAPPER1(__fpclassify) +libm_hidden_def(__fpclassifyl) +# endif -#ifdef L___finitel -int_WRAPPER_C99(__finite) -#endif +# ifdef L___finitel +int_WRAPPER1(__finite) +libm_hidden_def(__finitel) +# endif -#ifdef L___signbitl -int_WRAPPER_C99(__signbit) -#endif +# ifdef L___signbitl +int_WRAPPER1(__signbit) +libm_hidden_def(__signbitl) +# endif -#ifdef L___isnanl -int_WRAPPER_C99(__isnan) -#endif +# ifdef L___isnanl +int_WRAPPER1(__isnan) +libm_hidden_def(__isnanl) +# endif -#ifdef L___isinfl -int_WRAPPER_C99(__isinf) -#endif +# ifdef L___isinfl +int_WRAPPER1(__isinf) +libm_hidden_def(__isinfl) +# endif #endif -- cgit v1.2.3 From 4d537e8547b8d623e1847cd80d3da455dc52ff85 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 31 Oct 2010 15:58:18 +0100 Subject: libm: disable tail jump trick if __SSP_ALL__ (was using wrong conditional) Thanks, Timo! Signed-off-by: Denys Vlasenko --- libm/ldouble_wrappers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libm/ldouble_wrappers.c') diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c index e2d4d8036..0fe6e8d97 100644 --- a/libm/ldouble_wrappers.c +++ b/libm/ldouble_wrappers.c @@ -37,7 +37,7 @@ long long func##l(long double x) \ return func((double) x); \ } -#if defined __i386__ && defined __OPTIMIZE__ && !defined __UCLIBC_HAS_SSP__ +#if defined __i386__ && defined __OPTIMIZE__ && !defined __SSP_ALL__ # undef WRAPPER1 # undef int_WRAPPER1 # undef long_WRAPPER1 -- cgit v1.2.3 From fff9dae7eb2e9e9a81f73a955d921e7f0e1e9bb5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Nov 2010 07:24:50 +0100 Subject: ldouble_wrappers: remove i386-specific optimization It is deemed too unsafe. Quoting Timo: If I'm building with "-fPIC -pg" it instruments all C functions with profiler stuff which is called via PLT and causes EBX reloads --> crash -fno-omit-frame-pointer is sometimes useful for profiling too --> crash Also the upcoming -fsplit-stack will be broken by this too (that might need additional uclibc support though). And I'm pretty sure there's also other similar compiler features. There's no predefined #defines in gcc for any of these. What I'm trying to say that there are *numerous* situations when the compiler can create stack frame for you without you ever knowing it. And if you want to do a tail jump, you really should be doing it from .S file where you control fully the prologue/epilogue code. (GCC naked attribute does not seem to work on x86.) Signed-off-by: Denys Vlasenko --- libm/ldouble_wrappers.c | 105 ++---------------------------------------------- 1 file changed, 3 insertions(+), 102 deletions(-) (limited to 'libm/ldouble_wrappers.c') diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c index 0fe6e8d97..b98a20181 100644 --- a/libm/ldouble_wrappers.c +++ b/libm/ldouble_wrappers.c @@ -37,91 +37,6 @@ long long func##l(long double x) \ return func((double) x); \ } -#if defined __i386__ && defined __OPTIMIZE__ && !defined __SSP_ALL__ -# undef WRAPPER1 -# undef int_WRAPPER1 -# undef long_WRAPPER1 -# undef long_long_WRAPPER1 -/* gcc 4.3.1 generates really ugly code with redundant pair of store/load: - * sub $0x10,%esp - * fldt 0x14(%esp) - * fstpl 0x8(%esp) - * fldl 0x8(%esp) <-- ?? - * fstpl (%esp) <-- ?? - * call function - * add $0x10,%esp - * ret - * I can hope newer gcc will eliminate that. However, I don't think - * it will be smart enough to reuse argument stack space and use - * jump instead of call. Let's do it by hand. - * The asm below loads long double x into st(0), then stores it back - * to the same location, but as a double. At this point, stack looks - * exactly as "double func(double)" expects it to be. - * The return value is returned in st(0) per ABI in both cases (returning - * a long double or returning a double). So we can simply jump to func. - * Using __GI_func in jump to make optimized intra-library jump. - * gcc will still generate a useless "ret" after asm. Oh well... - * - * If you discover a build mode in which gcc creates a stack frame - * incompatible with this hack, do not "fix" by replacing jmp with call - * in the wrappers. This will make functions use wrong offset - * for accessing on-stack parameter. - * Instead, add more conditions to guarding #if above. - */ -# define WRAPPER1(func) \ -long double func##l(long double x) \ -{ \ - long double st_top; \ - __asm__ ( \ - " fldt %1\n" \ - " fstpl %1\n" \ - " jmp " __stringify(__GI_##func) "\n" \ - : "=t" (st_top) \ - : "m" (x) \ - ); \ - return st_top; \ -} -# define int_WRAPPER1(func) \ -int func##l(long double x) \ -{ \ - int ret; \ - __asm__ ( \ - " fldt %1\n" \ - " fstpl %1\n" \ - " jmp " __stringify(__GI_##func) "\n" \ - : "=a" (ret) \ - : "m" (x) \ - ); \ - return ret; \ -} -# define long_WRAPPER1(func) \ -long func##l(long double x) \ -{ \ - long ret; \ - __asm__ ( \ - " fldt %1\n" \ - " fstpl %1\n" \ - " jmp " __stringify(__GI_##func) "\n" \ - : "=a" (ret) \ - : "m" (x) \ - ); \ - return ret; \ -} -# define long_long_WRAPPER1(func) \ -long long func##l(long double x) \ -{ \ - long long ret; \ - __asm__ ( \ - " fldt %1\n" \ - " fstpl %1\n" \ - " jmp " __stringify(__GI_##func) "\n" \ - : "=A" (ret) \ - : "m" (x) \ - ); \ - return ret; \ -} -#endif /* __i386__ && __OPTIMIZE__ */ - /* Implement the following, as defined by SuSv3 */ #if 0 long double acoshl(long double); @@ -315,12 +230,7 @@ long double frexpl (long double x, int *ex) #endif #ifdef L_gammal -/* WRAPPER1(gamma) won't work, tries to call __GI_xxx, - * and gamma() hasn't got one. */ -long double gammal(long double x) -{ - return (long double) gamma((double) x); -} +WRAPPER1(gamma) #endif #ifdef L_hypotl @@ -362,11 +272,7 @@ WRAPPER1(log1p) #endif #ifdef L_log2l -/* WRAPPER1(log2) won't work */ -long double log2l(long double x) -{ - return (long double) log2((double)x); -} +WRAPPER1(log2) #endif #ifdef L_logbl @@ -489,12 +395,7 @@ WRAPPER1(trunc) #endif #ifdef L_significandl -/* WRAPPER1(significand) won't work, tries to call __GI_xxx, - * and significand() hasn't got one. */ -long double significandl(long double x) -{ - return (long double) significand((double) x); -} +WRAPPER1(significand) #endif #if defined __DO_C99_MATH__ && !defined __NO_LONG_DOUBLE_MATH -- cgit v1.2.3 From 4d7ff2915e5b1050ad16c2ad57ba98c19d6d79d6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Nov 2010 07:35:01 +0100 Subject: ldouble_wrappers: make code less verbose via WRAPPER2 macro Tested: ran testsuite Signed-off-by: Denys Vlasenko --- libm/ldouble_wrappers.c | 60 +++++++++++++------------------------------------ 1 file changed, 16 insertions(+), 44 deletions(-) (limited to 'libm/ldouble_wrappers.c') diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c index b98a20181..118a78f64 100644 --- a/libm/ldouble_wrappers.c +++ b/libm/ldouble_wrappers.c @@ -21,6 +21,11 @@ long double func##l(long double x) \ { \ return (long double) func((double) x); \ } +#define WRAPPER2(func) \ +long double func##l(long double x, long double y) \ +{ \ + return (long double) func((double) x, (double) y); \ +} #define int_WRAPPER1(func) \ int func##l(long double x) \ { \ @@ -115,10 +120,7 @@ WRAPPER1(asin) #endif #ifdef L_atan2l -long double atan2l (long double x, long double y) -{ - return (long double) atan2( (double)x, (double)y ); -} +WRAPPER2(atan2) #endif #ifdef L_atanhl @@ -145,10 +147,7 @@ WRAPPER1(ceil) #endif #ifdef L_copysignl -long double copysignl (long double x, long double y) -{ - return (long double) copysign( (double)x, (double)y ); -} +WRAPPER2(copysign) #endif #ifdef L_coshl @@ -184,10 +183,7 @@ WRAPPER1(fabs) #endif #ifdef L_fdiml -long double fdiml (long double x, long double y) -{ - return (long double) fdim( (double)x, (double)y ); -} +WRAPPER2(fdim) #endif #ifdef L_floorl @@ -202,24 +198,15 @@ long double fmal (long double x, long double y, long double z) #endif #ifdef L_fmaxl -long double fmaxl (long double x, long double y) -{ - return (long double) fmax( (double)x, (double)y ); -} +WRAPPER2(fmax) #endif #ifdef L_fminl -long double fminl (long double x, long double y) -{ - return (long double) fmin( (double)x, (double)y ); -} +WRAPPER2(fmin) #endif #ifdef L_fmodl -long double fmodl (long double x, long double y) -{ - return (long double) fmod( (double)x, (double)y ); -} +WRAPPER2(fmod) #endif #ifdef L_frexpl @@ -234,10 +221,7 @@ WRAPPER1(gamma) #endif #ifdef L_hypotl -long double hypotl (long double x, long double y) -{ - return (long double) hypot( (double)x, (double)y ); -} +WRAPPER2(hypot) #endif #ifdef L_ilogbl @@ -306,33 +290,21 @@ WRAPPER1(nearbyint) #endif #ifdef L_nextafterl -long double nextafterl (long double x, long double y) -{ - return (long double) nextafter( (double)x, (double)y ); -} +WRAPPER2(nextafter) #endif /* Disabled in Makefile.in */ #if 0 /* def L_nexttowardl */ -long double nexttowardl (long double x, long double y) -{ - return (long double) nexttoward( (double)x, (double)y ); -} +WRAPPER2(nexttoward) libm_hidden_def(nexttowardl) #endif #ifdef L_powl -long double powl (long double x, long double y) -{ - return (long double) pow( (double)x, (double)y ); -} +WRAPPER2(pow) #endif #ifdef L_remainderl -long double remainderl (long double x, long double y) -{ - return (long double) remainder( (double)x, (double)y ); -} +WRAPPER2(remainder) #endif #ifdef L_remquol -- cgit v1.2.3