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

Reply via email to