On Thu Jan 23 20:01:19 2025 +0000, Konstantin Demin wrote:
@insn I'd prefer to fix existing code instead of quirking build chain but it's very sophisticated. E.g. I'm unable to build working/sane object file from `dlls/winecrt0/setjmp.c` with LTO enabled due to further linking issues like `undefined reference to '__wine_setjmpex'`. Proposed change (doesn't work though):
--- a/dlls/winecrt0/setjmp.c +++ b/dlls/winecrt0/setjmp.c @@ -25,6 +25,22 @@ #if defined(__GNUC__) || defined(__clang__) +#if (defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)) && !defined(__arm64ec__) +__attribute__((used)) +extern int __cdecl __wine_setjmpex( __wine_jmp_buf *buf, EXCEPTION_REGISTRATION_RECORD *frame ); +__attribute__((used)) +extern void __cdecl __wine_longjmp( __wine_jmp_buf *buf, int retval ); +#endif + +#ifdef __WINE_LTO_BUILD +__attribute__((used)) +static void __wine_lto_fixup( void ) +{ + (void) __wine_setjmpex( NULL, NULL ); + __wine_longjmp( NULL, 0 ); +} +#endif + #if defined(__i386__) __ASM_GLOBAL_FUNC( __wine_setjmpex,
Yeah, LTO is broken with ASM_GLOBAL_FUNC. GCC doesn't parse the asm, so it doesn't know they're defined. When importing a library with an API having same name, it will pull it from the library since it can't find it defined yet. Later, when it actually assembles and links the code (the real link stage, not LTO), it will find two definitions of the API: the ASM_GLOBAL_FUNC one and the one imported.
The issue with winecrt0 is different. When importing a static library it looks to see if any imports are needed from one of its object files. But setjmp.o contains some ASM_GLOBAL_FUNCs so it won't import it because it can't "see" them, so it thinks it's not needed. That's why it gives undefined reference.
I think it's OK to remove LTO for specific object files. But you used it way too much, it should only be needed for like 3-4 modules AFAIK, those with ASM_GLOBAL_FUNC only. The others can be fixed in the code.