https://bugs.winehq.org/show_bug.cgi?id=50625
Bug ID: 50625 Summary: Unhandled exception with try/catch Product: Wine Version: 4.12.1 Hardware: arm OS: Linux Status: UNCONFIRMED Severity: critical Priority: P2 Component: ntdll Assignee: wine-bugs@winehq.org Reporter: david.paradis@us.abb.com Distribution: ---
Created attachment 69319 --> https://bugs.winehq.org/attachment.cgi?id=69319 Test Project File
Hello,
I have run into a bug with try/catch blocks throwing an unhandled exception even though I have a catch all.
I have attached a very simple test program that when started calls a method that just throws an exception class back to the caller. This very simple program works great in Windows and throws an unhandled exception in Wine and terminates the program.
This is a critical path to my application as I have incorporated a 3rd party library that uses exceptions for program flow rather than function return codes. Without a fix our application becomes unstable and crashes when an intended exception is thrown.
I would really like a solution for the version of Wine that we are running (4.12.1) as we have Wine running on thousands of remote computers with not easy solution to upgrade to newer versions. I can however deploy patches to Wine.
Thank you for any assistance with addressing this issue as I have spent the last couple days annotating the Wine sources to try and find the root cause without success to this point.
https://bugs.winehq.org/show_bug.cgi?id=50625
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download, source, testcase CC| |nerv@dawncrow.de
--- Comment #1 from Austin English austinenglish@gmail.com --- Hi David,
Given that you're testing on a (relatively) untested platform (arm) _and_ an old version, have you verified that this still occurs in current (6.x) wine (your bug report doesn't specify).
There's obviously no work ongoing on the 4.x branch, but if still present in 6.x, it's worth fixing (and maybe backporting).
Anyway, I can't test this at the moment (maybe this weekend), but CC'ing myself/Andre, as I know he's interested in wine/arm.
https://bugs.winehq.org/show_bug.cgi?id=50625
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Severity|critical |normal
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #2 from David Paradis david.paradis@us.abb.com --- Austin,
Thank you for looking into this. Unfortunately I do not have the easy option of trying this with the latest version. As I put in the description we have several hundred if not more of devices installed around the US that are running 4.12.1 and it is not a simple task to upgrade those devices. We run a building automation system with a piece of hardware running in a remote store. I would like to at some point in the future look at what it will take for us to use the latest, but that is not an option at the moment.
I report a similar but back in Dec for issues with std::mutex that I was able to create my own fix. The bug was closed after fixing it in the upcoming 6.2 release. I was ok with that because I basically put the same fix in myself. With this issue I have not be able to find the root cause to create my own fix.
If you are able to test this in ARM with the 4.12.1 release and let me know what/where to make the fix I have no problem putting that into my code base and testing.
Again, thank you very much for whatever help you are able to give.
https://bugs.winehq.org/show_bug.cgi?id=50625
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |austinenglish@gmail.com
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #3 from Austin English austinenglish@gmail.com --- Sure, I understand that you can't test on all the devices in field, but particularly for a relatively exotic platform (arm), I figured you'd have a test box around that you could try on ;)
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #4 from David Paradis david.paradis@us.abb.com --- Understood.
As you know with ARM there are no pre-built releases. The last time that I had to configure and compile the sources it took nearly 20hrs to build them.
I do have a test box that is my development machine. Trying to get the latest up and running on it would take me the entire weekend to do. If need be I can possibly look into do that next week.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #5 from Alexandre Julliard julliard@winehq.org --- Exception unwinding in native ARM binaries is not implemented, so I'm afraid this is not going to be a simple fix.
It would be helpful if you could attach a compiled binary of the test case.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #6 from David Paradis david.paradis@us.abb.com --- Created attachment 69323 --> https://bugs.winehq.org/attachment.cgi?id=69323 Compiled test application
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #7 from David Paradis david.paradis@us.abb.com --- That is interesting because I have put in place some FIXME messages to see the code path and it gets to the point of raising the exception and then crashes. I would have assumed if it wasn't implemented that there wouldn't be any implementation code in files specifically named /ntdll/signal_arm.c and arm64.c. We are working with a 32bit arm processor.
Do you know whether it has been implemented in the latest versions?
I have attached a compiled 32bit arm test application.
Again thank you for the assistance on this, I really do appreciate any help you can give as this is a critical piece of new functionality that we are in the beginning phase of development on.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #8 from André H. nerv@dawncrow.de --- Please try again with wine 6.22, it's very likely fixed
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #9 from David Paradis david.paradis@us.abb.com --- (In reply to André H. from comment #8)
Please try again with wine 6.22, it's very likely fixed
Thank you Andre. I will download and and try this release and make sure that it is has been addressed.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #10 from David Paradis david.paradis@us.abb.com --- (In reply to David Paradis from comment #9)
(In reply to André H. from comment #8)
Please try again with wine 6.22, it's very likely fixed
Thank you Andre. I will download and and try this release and make sure that it is has been addressed.
Hello Andre,
I have built and am trying to test the SEH unwinding and having some issues.
I am getting the following messages (and lots of them) when my application calls "throw ExceptionClass();". 010c:err:seh:unwind_builtin_dll libunwind not available, unable to unwind
I have done an "apt install libunwind-dev" thinking that, that would fix the issue, but still getting the same result.
This is the command that I am using the configure the Wine sources before doing a make: ./configure --with-xml --with-png --with-netapi --with-gnutls --without-x --without-freetype --without-coreaudio --without-mpg123 --without-pulse --without-sane --without-vdk3d
Am I missing are argument to including the unwind library? I tried to add "--with-libunwind" but that argument was unrecognized.
Again, any help is much appreciated.
Thank you, David Paradis
https://bugs.winehq.org/show_bug.cgi?id=50625
Zebediah Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |z.figura12@gmail.com
--- Comment #11 from Zebediah Figura z.figura12@gmail.com --- The configure flag you're looking for is "--with-unwind", which can be found by running "configure --help".
I suspect you need the multiarch version of libunwind-dev. I'm not sure of the correct code, but I think you want to install libunwind-dev:armhf.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #12 from David Paradis david.paradis@us.abb.com --- (In reply to Zebediah Figura from comment #11)
The configure flag you're looking for is "--with-unwind", which can be found by running "configure --help".
I suspect you need the multiarch version of libunwind-dev. I'm not sure of the correct code, but I think you want to install libunwind-dev:armhf.
Thank you. I will try that right now.
When I ran the install for unwind it did download the armf.deb versions, not the hf.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #13 from David Paradis david.paradis@us.abb.com --- (In reply to Zebediah Figura from comment #11)
The configure flag you're looking for is "--with-unwind", which can be found by running "configure --help".
I suspect you need the multiarch version of libunwind-dev. I'm not sure of the correct code, but I think you want to install libunwind-dev:armhf.
No change in behavior. When I ran ./configure -with-unwind I saw it come across the screen when it was looking for the unwind files to enable it, it reported "no". When I then compile the sources I can see in the dlls/ntdll/linux/signal-arm.c in the unwind_builtin_dll() that the #define for HAVE_LIBUNWIND is still not being defined, if I attempt to force it to be defined it compiles but will not link because the lib is not included on the linker portion of the build.
I see in /usr/include that the libunwind.h file is there and in the /usr/lib/arm-linux-gnueabihf folder that there are several libunwind*.so files present. Not sure why the .configure is disabling the unwind library.
Do you have anything that you could suggest to get this to include it, as everything looks correct?
I am attaching the output of the .configure command as well as the configure log that was auto generated, hopefully those help to understand what is going on.
Again, thank you. David
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #14 from David Paradis david.paradis@us.abb.com --- Created attachment 71180 --> https://bugs.winehq.org/attachment.cgi?id=71180 .Configure auto log
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #15 from David Paradis david.paradis@us.abb.com --- Created attachment 71181 --> https://bugs.winehq.org/attachment.cgi?id=71181 .Configure output redirect
https://bugs.winehq.org/show_bug.cgi?id=50625
André H. nerv@dawncrow.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |martin@martin.st
--- Comment #16 from André H. nerv@dawncrow.de --- CCing Martin https://stackoverflow.com/questions/49438381/getting-linker-errors-when-link... looks similar
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #17 from David Paradis david.paradis@us.abb.com --- (In reply to André H. from comment #16)
CCing Martin https://stackoverflow.com/questions/49438381/getting-linker-errors-when- linking-against-libunwind-for-a-library-in-my-project looks similar
Yes it sounds similar, but when you look at the signal_arm.c file, I attempted to just force the "HAVE_LIBUNWIND" define just before it looked for it to be defined. Inside the ifdef it defines the UNW_LOCAL_ONLY and then includes the header.
I am trying overload the UNWIND_LIBS path when calling .configure to see if that helps.
When I then run make I get the following output:
admin@eSCi-EDP001:~/wine-6.22/dlls/ntdll$ sudo make prefix=/opt/wine install make[1]: Entering directory '/home/admin/wine-6.22' gcc -o dlls/ntdll/ntdll.so -shared -Wl,-Bsymbolic -Wl,-soname,ntdll.so -Wl,-z,defs dlls/ntdll/unix/cdrom.o \ dlls/ntdll/unix/debug.o dlls/ntdll/unix/env.o dlls/ntdll/unix/file.o dlls/ntdll/unix/loader.o \ dlls/ntdll/unix/loadorder.o dlls/ntdll/unix/process.o dlls/ntdll/unix/registry.o \ dlls/ntdll/unix/security.o dlls/ntdll/unix/serial.o dlls/ntdll/unix/server.o \ dlls/ntdll/unix/signal_arm.o dlls/ntdll/unix/signal_arm64.o dlls/ntdll/unix/signal_i386.o \ dlls/ntdll/unix/signal_x86_64.o dlls/ntdll/unix/socket.o dlls/ntdll/unix/sync.o \ dlls/ntdll/unix/system.o dlls/ntdll/unix/tape.o dlls/ntdll/unix/thread.o dlls/ntdll/unix/virtual.o \ dlls/ntdll/unix/version.o -lpthread -ldl dlls/ntdll/unix/signal_arm.o: In function `unwind_builtin_dll': /home/admin/wine-6.22/dlls/ntdll/unix/signal_arm.c:246: undefined reference to `_ULarm_init_local' /home/admin/wine-6.22/dlls/ntdll/unix/signal_arm.c:253: undefined reference to `_ULarm_get_proc_info' /home/admin/wine-6.22/dlls/ntdll/unix/signal_arm.c:277: undefined reference to `_ULarm_step' /home/admin/wine-6.22/dlls/ntdll/unix/signal_arm.c:289: undefined reference to `_ULarm_get_reg' /home/admin/wine-6.22/dlls/ntdll/unix/signal_arm.c:290: undefined reference to `_ULarm_get_reg' /home/admin/wine-6.22/dlls/ntdll/unix/signal_arm.c:291: undefined reference to `_ULarm_get_reg' /home/admin/wine-6.22/dlls/ntdll/unix/signal_arm.c:292: undefined reference to `_ULarm_get_reg' collect2: error: ld returned 1 exit status Makefile:103719: recipe for target 'dlls/ntdll/ntdll.so' failed make[1]: *** [dlls/ntdll/ntdll.so] Error 1 make[1]: Leaving directory '/home/admin/wine-6.22' Makefile:13: recipe for target 'install' failed make: *** [install] Error 2
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #18 from David Paradis david.paradis@us.abb.com --- Because the .configure is not finding and dealing with unwind it is setting the UNWIND_LIBS library define to empty. Even though I have passed in the location of the lib on configure it still seems to be ignoring it.
I am not strong on the whole command line make and how all of the checks get done to determine if the unwind library is present. It appears that the .configure is attempting to compile and include unwind and fails, therefore disabling it. As far as I know I have installed all of the pieces for libunwind-dev and verified that they are present in the /usr/include and lib folders.
At this point I am kind of stumped as to what else to try.
Again, thank you for the assistance
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #19 from Martin Storsjö martin@martin.st --- Can you clarify what distribution (+version) and architecture configuration of it that you're building on?
The core issue shown in the configure log is this:
configure:16584: checking for unw_step configure:16602: gcc -o conftest -g -O2 -mthumb -mfloat-abi=hard conftest.c
&5
/tmp/cc8aT0B2.o: In function `main': /home/admin/wine-6.22/conftest.c:112: undefined reference to `_ULarm_step' collect2: error: ld returned 1 exit status
On an aarch64 install of Ubuntu 20.04, I've installed the libunwind-dev:armhf package, and I configure my build like this: CC="arm-linux-gnueabihf-gcc" ../wine/configure --host=arm-linux-gnueabihf
With such a build, with Wine 6.22, my current suite of exception handling tests pass.
As your build just runs plain "gcc", I would guess that it's a 32 bit distribution. But that doesn't explain the linking error - it sounds like libunwind is built/packaged differently on that architecture. (Building libunwind from source is quite quick and straightforward though.)
However the testcase you've attached here does even when Wine is correctly configured and built with libunwind, as the __CxxFrameHandler function still isn't implemented. If you'd make a build that is linked against the static CRT (/MT instead of /MD) it should work - I tried building it from the source you provided that way, and then it passes.
I can try to have a look at whether it's feasible to implement that function - but I'm not sure if there are other architecture specific bits in the msvcp140.dll and how well that DLL is supported on non-x86 architectures overall.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #20 from Martin Storsjö martin@martin.st --- (In reply to Martin Storsjö from comment #19)
However the testcase you've attached here does even when Wine is correctly configured and built with libunwind, as the __CxxFrameHandler function still isn't implemented. If you'd make a build that is linked against the static CRT (/MT instead of /MD) it should work - I tried building it from the source you provided that way, and then it passes.
I can try to have a look at whether it's feasible to implement that function
- but I'm not sure if there are other architecture specific bits in the
msvcp140.dll and how well that DLL is supported on non-x86 architectures overall.
Sorry for the mixup, this function doesn't have anything to do with msvcp140.dll, it's all msvcrt/ucrtbase.
But in any case, yeah it's unimplemented. Looking at the x86_64 version of it, it's a pretty significant amount of code - I don't think I can make a corresponding arm version in the near future. For now, the simplest solution is to just statically link the CRT for such cases.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #21 from Martin Storsjö martin@martin.st --- Oh, and for the record, a couple known gotchas:
- Unwinding only works in ELF builds, it doesn't work in PE/mingw builds (as LLVM can't generate the necessary unwind info for windows)
- If the ELF parts are built with Clang instead of GCC, one has to apply this fix to libunwind, https://github.com/libunwind/libunwind/commit/971989687f9cf46d9d7f95df593657..., or add "-gdwarf-2" to CFLAGS (e.g. as CFLAGS="-g -gdwarf-2 -O2")
- Because ARM primarily uses a different unwind info format (.ARM.extab sections instead of .eh_frame), libunwind seems to rely on parsing the .debug_frame sections, thus unwinding doesn't work if the wine .so files are stripped
- Latest git versions of libunwind since https://github.com/libunwind/libunwind/commit/a4014f33775321b4106a1134b89020... seem to fail (haven't yet debugged why)
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #22 from Zebediah Figura z.figura12@gmail.com --- FWIW, the configure script tries first to check for unw_step(), and then tries it again linking to UNWIND_LIBS (which defaults to -lunwind). You've quoted the first check, but both fail in the log, and I'm guessing it's the latter that's supposed to work.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #23 from Martin Storsjö martin@martin.st --- (In reply to Zebediah Figura from comment #22)
FWIW, the configure script tries first to check for unw_step(), and then tries it again linking to UNWIND_LIBS (which defaults to -lunwind). You've quoted the first check, but both fail in the log, and I'm guessing it's the latter that's supposed to work.
Oh, indeed. For some reason, the second test doesn’t print any executed command in this log:
configure:16618: checking for unw_step in libunwind configure:16645: result: no
In my logs, I see the successful command here.
Does --with-unwind affect this somehow? (I don’t pass that explicitly, I just let it autodetect it.)
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #24 from David Paradis david.paradis@us.abb.com --- (In reply to Martin Storsjö from comment #23)
(In reply to Zebediah Figura from comment #22)
FWIW, the configure script tries first to check for unw_step(), and then tries it again linking to UNWIND_LIBS (which defaults to -lunwind). You've quoted the first check, but both fail in the log, and I'm guessing it's the latter that's supposed to work.
Oh, indeed. For some reason, the second test doesn’t print any executed command in this log:
configure:16618: checking for unw_step in libunwind configure:16645: result: no
In my logs, I see the successful command here.
Does --with-unwind affect this somehow? (I don’t pass that explicitly, I just let it autodetect it.)
Thank you to everyone that has assisted with this issue. I will try to summarize what I have done. BTW, with all of the suggestions and my kind of hacking away I have been able to get my test application to successfully catch and handle the exception.
This is a remote device that is installed at retail stores across the US and is running a custom Debian linux distro built thru Yacto (I did not build the OS) running on a beagle bones ARM32 architecture.
What I had to do was this: 1) Run the apt install libunwind-dev to get the libs and includes as previously mentioned. 2) Run ./configure with the original set of arguments that I posted on previous comment. In looking thru the configure process, the "unwind" is enabled by default so that it can see if it is available on the system. 3) After the configure, I edited the /include/config.h.in file to comment out the "#undef HAVE_LIBUNWIND" and replace it with "#define HAVE_LIBUNWIND" 4) Then edit the /dlls/ntdll/Makefile.in to add to the EXTRALIBS line the path to the unwind lib at "/usr/lib/arm-linux-gnueabihf/libunwind.so " 5) Then run make and install from the /dlls/ntdll folder 6) Finally, in my project I switched from /MD to /MT for the CRT linking.
Now when I run my program everything works as expected. If I do not do step 3 and 4 then I get the prior messages about libunwind not being available when the exception is thrown in my application.
I don't know why the UNWIND_LIBS variable is not set correctly to properly include the libunwind.so, but if the ./configure process correctly detected my installed libunwind and set the .so path location correctly then I wouldn't have to modify any of the wine files at all. For now, I am ok with doing my own internal documentation for future builds to be make sure that I have these steps documented in the event I have to do this again in the future.
Again, thank you all for the help, it is greatly appreciated.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #25 from David Paradis david.paradis@us.abb.com --- I just wanted to give a quick update now that I have moved forward to production code.
I started to modify my real production code to switch the static CRT library, but unfortunately that is causing my some issues because I have a 3rd party library that using /MD switches and when I attempt to compile my code against that library I have issues unresolved external symbols that are being used in that library related to things like fopen, srand and other MSVCRT functions.
I am going to keep trying to change compiler switches on my project and the 3rd party library, but as of now the requirement to use static linked CRT might be a no go for my solution.
https://bugs.winehq.org/show_bug.cgi?id=50625
--- Comment #26 from David Paradis david.paradis@us.abb.com --- Let me first again thank you all for the assistance with this issue, it is greatly appreciated. Makes me extremely happy that this community is active and addressing issues.
I have successfully been able to upgrade and build the Wine 6.22 sources and all of my companies packages with the CRT as static rather than dynamic. I have also been able to force the 3rd party code to build statically as well and all is now working correctly on my platform. Exceptions thrown in the 3rd party library is being caught successfully in my code.
So, as far as I am concerned this issue is addressed when the projects are configured properly and you have the libunwind-dev package installed.
I had to do the following steps before building Wine on my box in order for it to detect and build against the Libunwind package: * After running the "./configure", edit the "/include/config.h.in" to replace the "#undef HAVE_LIBUNWIND" with "#define HAVE_LIBUNWIND". * Edit the "dlls/ntdll/Makefile.in" to add to the end of the "EXTRALIBS" definition the path libunwind of "/usr/lib/arm-linux-gnueabihf/libunwind.so" * Then on my project side, ensure that the CRuntimeLibrary is static rather than dynamic.