On Monday 19 August 2024 19:19:11 Pali Rohár wrote: > On Monday 19 August 2024 13:50:14 Martin Storsjö wrote: > > On Sat, 17 Aug 2024, Pali Rohár wrote: > > > > > On Monday 05 August 2024 17:00:20 LIU Hao wrote: > > > > 在 2024-08-05 00:44, Pali Rohár 写道: > > > > > _init_scprintf: > > > > > ... > > > > > .def __vscprintf; .scl 2; .type 32; .endef > > > > > .def _init_scprintf; .scl 2; .type 32; .endef > > > > > > > > > > It is correct that _init_scprintf has two ".def" lines? > > > > > > > > Probably not... If it is declared elsewhere, we might want to remove > > > > the `.def` directive from assembly. > > > > > > > > And whatever scl (storage class) it appears in the symbol table probably > > > > does not matter. The symbol shall not escape that .o file, and that's > > > > all. > > > > > > > > > > > > -- > > > > Best regards, > > > > LIU Hao > > > > > > I run 'nm' on the original version and new version (without static). The > > > original version is: > > > > > > 00000000 b .bss > > > 00000000 d .data > > > 00000010 t _emu_scprintf > > > U __imp__GetModuleHandleW@4 > > > U __imp__GetProcAddress@8 > > > 00000000 D __imp___scprintf > > > 00000000 t _init_scprintf > > > 00000000 r .rdata > > > 00000000 r .rdata$zzz > > > 00000030 t _resolve_scprintf > > > 00000007 T __scprintf > > > 00000000 t .text > > > U __vscprintf > > > > > > And the difference between original a new is: > > > > > > @@ -4,7 +4,7 @@ > > > U __imp__GetModuleHandleW@4 > > > U __imp__GetProcAddress@8 > > > 00000000 D __imp___scprintf > > > -00000000 t _init_scprintf > > > +00000000 T _init_scprintf > > > 00000000 r .rdata > > > 00000000 r .rdata$zzz > > > 00000030 t _resolve_scprintf > > > > > > When static is removed then init_scprintf is marked with uppercase T, > > > same as _scprintf. So it looks like that for GNU binutils, the > > > init_scprintf is global / exported when static keyword is not present. > > > > > > So it looks like that the symbol can escape from the .o file and can be > > > referenced by other files. > > > > Indeed. > > > > But the original issue - a function which on the C level is declared static, > > but actually isn't defined anywhere in the C code, sounds a bit problematic > > indeed; I would not be surprised if the compiler would complain about it, > > possibly in LTO modes as well. And if not now, then possibly in future > > compiler versions. > > Is not there a documented way how to write such code for gcc and clang? > Because inline assembly in C code is supported for both gcc and clang.
What about attribute naked? For I386 it is supported since gcc 8. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25967 https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#index-naked-function-attribute_002c-x86 Per gcc documentation assembler instructions without operands are supported in naked functions, so something like this could be ok. What do you think? diff --git a/mingw-w64-crt/stdio/_scprintf.c b/mingw-w64-crt/stdio/_scprintf.c index 42f2e5f231a4..fca6f325e13c 100644 --- a/mingw-w64-crt/stdio/_scprintf.c +++ b/mingw-w64-crt/stdio/_scprintf.c @@ -51,9 +51,17 @@ static void resolve_scprintf(void) /* gcc does not provide an easy way to call another variadic function with reusing current arguments * this source file is used only on i386, so do this function redirect via inline i386 assembly */ #define ASM_SYM(sym) __MINGW64_STRINGIFY(__MINGW_USYMBOL(sym)) + +#if !defined(__GNUC__) || __GNUC__ >= 8 + __attribute__((naked)) +static int __cdecl init_scprintf(const char * __restrict__ __UNUSED_PARAM(format), ...) +{ +asm ( +#else asm ( ".def\t" ASM_SYM(init_scprintf) ";\t.scl\t3;\t.type\t32;\t.endef\n" ASM_SYM(init_scprintf) ":\n\t" +#endif "pushal\n\t" "call\t" ASM_SYM(resolve_scprintf) "\n\t" "popal\n\t" @@ -63,5 +71,9 @@ ASM_SYM(init_scprintf) ":\n\t" ASM_SYM(_scprintf) ":\n\t" "jmp\t*" ASM_SYM(__MINGW_IMP_SYMBOL(_scprintf)) ); +#if !defined(__GNUC__) || __GNUC__ >= 8 +__builtin_unreachable(); +} +#endif #endif I'm just not sure if is safe to mark format argument as __UNUSED_PARAM, but without it gcc generates warning: mingw-w64-crt/stdio/_scprintf.c: In function ‘init_scprintf’: mingw-w64-crt/stdio/_scprintf.c:57:60: warning: unused parameter ‘format’ [-Wunused-parameter] static int __cdecl init_scprintf(const char * __restrict__ format, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ How are supposed to be defined naked functions with parameters which are used in inline assembly by inspecting stack itself (without referencing C parameters)? > > I think the safest way to handle it would be to make the symbol non-static, > > which would require giving it a prefix starting with __ (and maybe a full > > __mingw prefix). > > > > // Martin _______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public