Closed bernhardu closed 2 weeks ago
Hi,
I and many others regularly build Wine with llvm-mingw, without running into this issue. So in order to figure out what's going differently, it'd be interesting to know how you set things up differently.
Yes, the <triple>-as
wrapper in llvm-mingw is a rather inaccurate emulation of the GNU as interface - it's actually not a wrapper at all, but just a symlink to plain clang. The fact that you need -c
is one of these known issues. (However, do note that you can pass -c
to GNU as if you want to - it's just not necessary there. So it's possible to craft command lines that work with both tools.) If you want to pass other options to the assembler, there's also a discrepancy between passing options as is, vs using -Wa,<option>
.
So while this is a known issue, it's generally not a very high priority issue, as normally very few things call <triple>-as
directly anyway. And lots of us have been building Wine with llvm-mingw for many years without hitting this issue.
CC @cjacek
Hello, thanks for looking into this issue. Below is my configure command for the 64-bit side. Could this issue just get visible by using x86_64_CC='.../x86_64-w64-mingw32-gcc' instead of x86_64_CC='...clang'?
PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig \
/home/bernhard/wine/configure \
CC='ccache gcc' \
CFLAGS='-g -O2' \
CROSSCFLAGS='-g -O2 -fsanitize=address -Wno-pragma-pack' \
x86_64_CC='ccache /home/bernhard/llvm-mingw_inst/bin/x86_64-w64-mingw32-gcc' \
x86_64_LDFLAGS='-lasan' \
--prefix=/usr \
--with-mingw \
--without-oss \
--enable-win64 \
Unfortuantely I was not able to finish a configure with something like this "--with-mingw='ccache /home/bernhard/llvm-mingw_inst/bin/clang'" and ASan enabled. Therefore I tried the gnu interface and the I got a successful configure step.
If I try now the configure with clang interface it fails with ASan:
PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig \
/home/bernhard/wine/configure \
CC='ccache gcc' \
CFLAGS='-g -O2' \
CROSSCFLAGS='-g -O2 -fsanitize=address -Wno-pragma-pack' \
x86_64_LDFLAGS='-lasan' \
--prefix=/usr \
--with-mingw='ccache /home/bernhard/llvm-mingw_inst/bin/clang' \
--without-oss \
--enable-win64 \
...
checking for otool... no
checking for readelf... readelf
checking whether -Wl,-z,defs works correctly... yes
checking whether the compiler supports -Wl,--export-dynamic... yes
checking whether the compiler supports -static-pie... yes
checking whether ccache /home/bernhard/llvm-mingw_inst/bin/clang supports -target x86_64-windows -fuse-ld=lld -Wl,-subsystem:console -Wl,-WX --no-default-config... no
checking whether ccache /home/bernhard/llvm-mingw_inst/bin/clang supports -target x86_64-windows -fuse-ld=lld -Wl,-subsystem:console -Wl,-WX... no
checking whether ccache /home/bernhard/llvm-mingw_inst/bin/clang works... yes
configure: error: Suitable PE cross-compiler not found, PE files won't be built.
This is an error since --with-mingw was requested.
And the last error in config.log seems to be this:
| #define HAVE_LINUX_VIDEODEV2_H 1
| #define _GNU_SOURCE 1
| /* end confdefs.h. */
| void *__os_arm64x_dispatch_ret = 0;
| int __cdecl mainCRTStartup(void) { return 0; }
configure:10426: result: no
configure:10434: checking whether ccache /home/bernhard/llvm-mingw_inst/bin/clang supports -target x86_64-windows -fuse-ld=lld -Wl,-subsystem:console -Wl,-WX
configure:10449: ccache /home/bernhard/llvm-mingw_inst/bin/clang -o conftest.exe -g -O2 -fsanitize=address -Wno-pragma-pack -nostdlib -nodefaultlibs -target x86_64-windows -fuse-ld=lld -Wl,-subsystem:console -Wl,-WX conftest.c >&5
lld-link: error: could not open '/home/bernhard/llvm-mingw_inst/lib/clang/20/lib/x86_64-unknown-windows-msvc/clang_rt.asan_dynamic.lib': No such file or directory
lld-link: error: could not open '/home/bernhard/llvm-mingw_inst/lib/clang/20/lib/x86_64-unknown-windows-msvc/clang_rt.asan_static_runtime_thunk.lib': No such file or directory
clang: error: linker command failed with exit code 1 (use -v to see invocation)
configure:10449: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "Wine"
For some reason wine looks for a
.../llvm-mingw_inst/lib/clang/20/lib/x86_64-unknown-windows-msvc/clang_rt.asan_dynamic.lib
.
But my build contains just a
.../llvm-mingw_inst/lib/clang/20/lib/windows/libclang_rt.asan_dynamic-x86_64.dll.a
Have I configured my llvm-mingw built wrong or do I miss other wine configure options?
After another look into wine's configure I noticed it detects the target from the clang executables filename ... so I guess I got now an answer to configure successful with clang interface, with ASan enabled:
PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig \
/home/bernhard/wine/configure \
CC='ccache gcc' \
CFLAGS='-g -O2' \
CROSSCFLAGS='-g -O2 -fsanitize=address -Wno-pragma-pack' \
x86_64_CC='ccache /home/bernhard/llvm-mingw_inst/bin/x86_64-w64-mingw32-clang' \
x86_64_LDFLAGS='-lasan' \
--prefix=/usr \
--with-mingw \
--without-oss \
--enable-win64 \
So It looks like it is as simple as not using .../bin/clang
but .../bin/x86_64-w64-mingw32-clang
.
Update: this seems to be still not the silver bullet - because this causes wine to switch again to gnu interface.
(Uses tools/winebuild/winebuild ... -b x86_64-w64-mingw32
instead
of tools/winebuild/winebuild ... -b x86_64-windows
.)
Update: I am sorry, but I found that I still working with llvm-mingw with llvm-project from just a few days, not from the 19.1.3.
Also I was able to get wine configured by following call [1]. But this needs the links [3] in the llvm-mingw install directrory at the bottom, because I found no other way to satisfy the linker, which unconditionally adds the lib files, I guess this happens here.
This build still fails a few central dlls, because they miss linking to e.g. abort function.
Also the configure check has to be modified to get not exectued with the -fsanitize=address
[2], as it does also not provide any linking to e.g. abort function.
Finally the resulting executable of e.g. notepad does crash. But clang in msvc mode seems to default to codeview debug information, and I could not convince it to emit dwarf without failure, so this stops investigating this end ...
(Update: About the dwarf issue lld-link: error: clang_rt.asan_dynamic-x86_64.lib(libclang_rt.asan_dynamic-x86_64.dll): .idata$4 should not refer to special section 0
. First I thought this might be about mixing debug information types, but I guess there is no codeview/pdb involved with this Dll. But this affects just the configure check. Adding -gdwarf-4
, but removing it just for configure, like in [2] makes winedbg showing function names.)
Therefore I find the gnu interface much easier to handle, and received currently more gdb-friendly results.
And, sorry, I fear I got much offtopic, as this issue was just about *-as
behaving differently with the gnu interface,
but the last comments were about exploring the clang interface.
[1]
export PATH=/home/bernhard/llvm-mingw_inst/bin:$PATH
PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig \
/home/bernhard/wine/configure \
CC='ccache clang' \
CFLAGS='-g -O2' \
CROSSCFLAGS='-g -O2 -fsanitize=address -Wno-pragma-pack -gdwarf-4' \
x86_64_CC='ccache clang' \
--prefix=/usr \
--with-mingw \
--without-oss \
--enable-win64 \
--disable-tests \
[2]
--- a/configure
+++ b/configure
@@ -10403,4 +10403,6 @@ else case e in #(
e) ac_wine_try_cflags_saved=$CFLAGS
ac_wine_try_cflags_saved_exeext=$ac_exeext
+CFLAGS="$(echo $CFLAGS | sed 's/-fsanitize=address//g')"
+CFLAGS="$(echo $CFLAGS | sed 's/-gdwarf-4//g')"
CFLAGS="$CFLAGS -nostdlib -nodefaultlibs $llvm_extra_cflags $llvm_cflags --no-default-config"
ac_exeext=".exe"
[3]
ln -s libclang_rt.asan_dynamic-x86_64.dll.a lib/clang/20/lib/windows/clang_rt.asan_dynamic-x86_64.lib
ln -s libclang_rt.asan_dynamic-x86_64.dll.a lib/clang/20/lib/windows/clang_rt.asan_static_runtime_thunk-x86_64.lib
This thread has strayed very far from the original question indeed, so it's probably time to put it to rest. However I'll try to clarify a number of concepts that seem to be unclear here first.
Let's separate the various concerns first. First, how to build Wine in general, with llvm-mingw or other mingw toolchains. And then secondly, building Wine with asan enabled.
If you configure Wine with --with-mingw
(and don't set x86_64_CC
directly), then it mostly ignores the parameter passed to --with-mingw
, as long as it isn't exactly clang
or */clang
- see https://gitlab.winehq.org/wine/wine/-/blob/wine-9.21/configure.ac?ref_type=tags#L806-830.
So if you do this, add the tools to $PATH
and configure with --with-mingw
, it will pick up and use x86_64-w64-mingw32-gcc
from the llvm-mingw frontend wrappers. Building this way just works for me. I also tried building with setting x86_64_CC=/absolute/path/to/llvm-mingw/bin/x86_64-w64-mingw32-gcc
and this also just works. I don't hit any errors with x86_64-w64-mingw32-as
this way.
In both of these scenarios, Wine ends up invoking the llvm-mingw frontend wrappers and running Clang in mingw mode. This constitutes to actually using llvm-mingw, although it doesn't use much else than the compiler and the compiler-rt builtins library, normally.
Secondly, if you configure with --with-mingw=/path/to/llvm-mingw/bin/clang
, then Wine will call the compiler in the form clang -target x86_64-windows
. Now Clang is invoked in MSVC mode (the triple x86_64-windows
is equal to x86_64-windows-msvc
). Now you're not really using llvm-mingw, you're just running the Clang binary. In MSVC mode, it normally doesn't need to link any libgcc or compiler-rt equivalent at all.
Both of these configurations work for me in my tests - I don't run into any error with x86_64-w64-mingw32-as
.
Now secondly, for configuring Wine with asan. I'm not sure if this is a known or supported build configuration at all, in general, or whether there are known issues around it.
However, when building with asan, the compiler will need to link in a prebuilt runtime library for it. The runtime library is different between mingw mode and MSVC mode. llvm-mingw ships with all these runtime libraries built in mingw mode, but not for MSVC mode. So when you build Wine with Clang in MSVC mode, it needs runtime libraries that llvm-mingw obviously doesn't provide - that's why you end up needing to symlink them. Using the mingw built asan libraries in MSVC mode isn't supported - perhaps it's mostly benign and works fine, I dunno, but it's not a configuration that generally is supported.
I tried configuring with something like this:
/home/bernhard/wine/configure \
CC='ccache gcc' \
CFLAGS='-g -O2' \
CROSSCFLAGS='-g -O2 -fsanitize=address -Wno-pragma-pack' \
x86_64_CC='ccache /home/bernhard/llvm-mingw_inst/bin/x86_64-w64-mingw32-gcc' \
x86_64_LDFLAGS='-lasan' \
--prefix=/usr \
--with-mingw \
--without-oss \
--enable-win64 \
And then I indeed hit errors. But the issue seems to be that the configure tests fail to detect almost anything with it - where config.log contains bits like this:
configure:10397: checking whether ccache /path/to/llvm-mingw-20240805-ucrt-ubuntu-20.04-x86_64/bin/x86_64-w64-mingw32-gcc supports -target x86_64-w64-mingw32 -fuse-ld=lld --no-default-config
configure:10412: ccache /path/to/llvm-mingw-20240805-ucrt-ubuntu-20.04-x86_64/bin/x86_64-w64-mingw32-gcc -o conftest.exe -g -O2 -fsanitize=address -Wno-pragma-pack -nostdlib -nodefaultlibs -target x86_64-w64-mingw32 -fuse-ld=lld --no-default-config conftest.c >&5
ld.lld: error: undefined symbol: __asan_init
>>> referenced by /tmp/conftest-677e6d.o:(asan.module_ctor)
ld.lld: error: undefined symbol: __asan_version_mismatch_check_v8
>>> referenced by /tmp/conftest-677e6d.o:(asan.module_ctor)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
So the fact that we're linking with -nostdlib -nodefaultlibs
together with -fsanitize=address
breaks linking.
All in all, this seems to entirely be an issue in how to configure building Wine. And llvm-mingw doesn't provide any runtimes for MSVC mode, even if the compiler executable itself is usable for that mode.
Agreed, this seems to be an issue with the Wine configuration. We shouldn't use those flags in configure checks. The Wine build system will likely need to handle sanitizer flags separately and skip them in modules where extra dependencies pose a problem. This should be managed by Wine's configure
, makedep
and winegcc
.
Regarding the -c
option, we shouldn't need the assembler in this case. Instead, we should use llvm-dlltool
's wrapper for proper delayload support. In any case, the root of the problem isn't a bug in llvm-mingw.
Thanks for taking the time and for the detailed explanations.
I re-checked two configure attempts and found without "-fsanitize=address" winebuild uses in my case *-dlltool
, while with it winebuild gets invoked with "--without-dlltool" and therefore uses *-as
.
Both configure attempts start to differ at following line, the same where I received issues when using the MSVC mode in my previous comments:
checking whether ccache x86_64-w64-mingw32-gcc supports -target x86_64-w64-mingw32 -fuse-ld=lld --no-default-config... no
So I guess we can close this issue then?
Indeed, this issue can be closed. While the emulation of <triple>-as
isn't very exact and that's a known issue, the primary issue here is about how to configure Wine with various incarnations of Clang, and how address sanitizer could be enabled there (and how it currently breaks configure).
I am trying to use llvm-mingw to build a Wine tree, using the "x86_64-w64-mingw32-*" wrappers instead of the clang interface.
This works quite good, except for
x86_64-w64-mingw32-as
.I could get it working by adding a "-c" to the command line. Like here.
But I am not sure how to proceed from here:
Below is the input and output of llvm and gcc based invocations:
Failure without "-c":
Success with "-c":
Success with gcc without "-c":
Success with gcc with "-c":