Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Will other exception mode other than dwarf be provided? #4

Closed
farta1986 opened this issue Mar 15, 2020 · 18 comments
Closed

Will other exception mode other than dwarf be provided? #4

farta1986 opened this issue Mar 15, 2020 · 18 comments

Comments

@farta1986
Copy link

farta1986 commented Mar 15, 2020

Thanks a lot for your hard work first. As far as I know for x86_64, it seems SEH is more widely used and doesn't have major week points compared to dwarf. Is there a reason to choose dwarf and not privde an SEH version?

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 15, 2020

Hi, not really. I used dwarf to standardize the compilation between 32-bit and 64-bit.
If there are good arguments for what is the best exception handling I am open for suggestions.
Note that I am looking for the best performance. Choosing the exception handling may impact performance and memory usage.

@farta1986
Copy link
Author

farta1986 commented Mar 16, 2020

As far as I know the one who cause performace concern is sjlj, as it introducde some overhead even in happy path. For 32-bit SEH is not avaliable for gcc (it seems due to some non-tech reasons such as patents), but for 64-bit it's OK. SEH is native windows exception model, there shouldn't be any performace problem about it.

The major concern for dwarf is about compatibility. As dwarf is likely different from other compilers' (MSVC) model, application will likely to crash or not to pass exceptions correctly if an exception throwed by dwarf code is passing throw non-dwarf codes. This could happen when you're linking with 3rd party binary libs.

So for best performace, it is suggested to use dwarf for 32-bit and SEH for 64-bit.

@tomay3000
Copy link

tomay3000 commented Mar 17, 2020

Good job, but it would be better if you provide SJLJ exception model for 32-bits in addition, for compatibility reasons (I personally use MinGW-W64 v6.0.0 GCC v8.1.0) and would be happy to upgrade using your builds if you do so.

TIA.

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 18, 2020

I'm open to suggestions.
I suppose I can change the gcc configure options --with-dwarf2 --disable-sjlj-exceptions to --without-dwarf2 --enable-sjlj-exceptions to build a version with SJLJ.
But I don't see any options for SEH in gcc. How do I build with SEH?

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 18, 2020

Note: the patent on SEH seems to have expired, see: https://patents.google.com/patent/US5628016

@tomay3000
Copy link

tomay3000 commented Mar 19, 2020

I'm open to suggestions.
I suppose I can change the gcc configure options --with-dwarf2 --disable-sjlj-exceptions to --without-dwarf2 --enable-sjlj-exceptions to build a version with SJLJ.
But I don't see any options for SEH in gcc. How do I build with SEH?

I guess so.

According to this: https://github.com/msys2/MINGW-packages/blob/master/mingw-w64-gcc/PKGBUILD:

SEH is the default for 64-bits and needs no options at all:

case "${CARCH}" in
    i686)
      local _conf="--disable-sjlj-exceptions --with-dwarf2"
      LDFLAGS+=" -Wl,--large-address-aware"
      local _arch=i686
    ;;

    x86_64)
      local _arch=x86-64
      local _conf=""
    ;;
  esac

So,

For 32-bits:

There are two options DWARF or SJLJ.

And, for 64-bits:

There are two options too SEH or SJLJ.

Also take a look here:
https://stackoverflow.com/questions/15670169/what-is-difference-between-sjlj-vs-dwarf-vs-seh

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 19, 2020

Just did a first attempt with gcc configure options --without-dwarf2 --enable-sjlj-exceptions, but this test:

echo -e "#include <iostream>\n#ifdef __USING_SJLJ_EXCEPTIONS__\n#define ANSWER \"yes\"\n#else\n#define ANSWER \"no\"\
n#endif\nint main() {\nstd::cout << \"SJLJ: \" << ANSWER << std::endl;\nreturn 0;\n}" | g++ -xc++ -mconsole - -otest_sj
lj.exe && test_sjlj.exe && rm -f test_sjlj.exe

returned: SJLJ: no
Do you have a better way of testing it's actually a working SJLJ build?

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 19, 2020

Now I compiled the while environment again with this first attempt build and I get this result (on 64-bit):

# echo -e "#include <iostream>\n#ifdef __USING_SJLJ_EXCEPTIONS__\n#define ANSWER \"yes\"\n#else\n#define ANSWER \"no\"\n#endif\nint main() {\nstd::cout << \"SJLJ: \" << ANSWER << std::endl;\nreturn 0;\n}" | g++ -xc++ -mconsole - -otest_sjlj.exe && test_sjlj.exe && rm -f test_sjlj.exe
SJLJ: yes
# echo -e "#include <iostream>\n#ifdef __SEH__\n#define ANSWER \"yes\"\n#else\n#define ANSWER \"no\"\n#endif\nint main() {\nstd::cout << \"SEH: \" << ANSWER << std::endl;\nreturn 0;\n}" | g++ -xc++ -mconsole - -otest_seh.exe && test_seh.exe && rm -f test_seh.exe
SEH: yes

Is it possible this compiler supports both SJLJ and SEH?
I do see both libgcc_s_sjlj-1.dll and libgcc_s_seh-1.dll are present.

Note that the earlier dwarf builds also already defined SEH. Were they supporting both dwarf and SEH? I'm not an exception handling expert so this is a bit confusing to me.

Do you think I should publish my latest SJLJ build attempt based on the above information?

@farta1986
Copy link
Author

farta1986 commented Mar 19, 2020

I'm not an expert of it either. I guess although theoretically a compiler can support generating both SJLJ and SEH, but at least there should be command line argument or sth passed to it to tell it which one is chosen. In this case there's no such thing, so I don't think these 2 binaries are using different exception mode. Perhaps we can compile a short demo with exception and output assembly instructions to check what exactly is done for it.

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 19, 2020

I'm more of a C programmer than C++ and exceptions are not really my thing.
If you could build such a demo/test application to determine if it's using dwarf/sjlj/seh that would be great.

I have just published my SJLJ build here in case you want to give it a go:
https://github.com/brechtsanders/winlibs_mingw/releases/tag/9.3.0-7.0.0-sjlj-r2

@tomay3000
Copy link

tomay3000 commented Mar 20, 2020

Do you have a better way of testing it's actually a working SJLJ build?

Normally you should issue: gcc -v and it tells you what exception model it uses.
This is what the official MinGW-w64 v6.0.0 GCC v8.1.0 outputs:
Untitled

Is it possible this compiler supports both SJLJ and SEH?

I don't think so, it the one or the other.

I do see both libgcc_s_sjlj-1.dll and libgcc_s_seh-1.dll are present.

Note that the earlier dwarf builds also already defined SEH. Were they supporting both dwarf and SEH? I'm not an exception handling expert so this is a bit confusing to me.

May be they are leftovers from the previous build.

Note:

DWARF is only for 32-bits.
SJLJ is for both 32-bits and 64-bits.
SEH is only for 64-bits.
And you don't have to specify --without-dwarf2 when building for 64-bits.

I gave your builds a try, they seems SJLJ builds when issuing gcc -v:

Untitled 2

Untitled 3

And using Dependency Walker http://www.dependencywalker.com/ to check the dependencies of libstdc++-6.dll it revealed that it depends on libgcc_s_sjlj-1.dll for both: 32-bits and 64-bits:
Untitled 4

Untitled 6

So, what libgcc_s_dw2-1.dll for 32-bits and libgcc_s_seh-1.dll for 64-bits are doing here?
Untitled 5

Untitled 7

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 22, 2020

Hi,
It seems like there must have been some leftover thing depending on other exception handling.
The 3rd iteration build at https://github.com/brechtsanders/winlibs_mingw/releases/tag/9.3.0-7.0.0-sjlj-r3 seems good.
32-bit:

$ gcc -v
Using built-in specs.
COLLECT_GCC=D:\Prog\winlibs32-sjlj-9.3.0\mingw32\bin\gcc.exe
COLLECT_LTO_WRAPPER=d:/prog/winlibs32-sjlj-9.3.0/mingw32/bin/../libexec/gcc/i686-w64-mingw32/9.3.0/lto-wrapper.exe
Target: i686-w64-mingw32
Configured with: ./configure --prefix=/R/winlibs32-sjlj-9.3.0/inst_gcc-9.3.0/share/gcc --build=i686-w64-mingw32 --host=i686-w64-mingw32 --with-pkgversion='MinGW-W64 i686-posix-sjlj, built by Brecht Sanders' --with-tune=generic --enable-checking=release --enable-threads=posix --without-dwarf2 --enable-sjlj-exceptions --disable-libunwind-exceptions --enable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --enable-default-ssp --disable-rpath --disable-libstdcxx-pch --enable-libstdcxx-time=yes --disable-libstdcxx-debug --disable-version-specific-runtime-libs --with-stabs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++,d --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite --enable-mingw-wildcard --with-mpc=/d/Prog/winlibs32-sjlj-9.3.0/custombuilt --with-mpfr=/d/Prog/winlibs32-sjlj-9.3.0/custombuilt --with-gmp=/d/Prog/winlibs32-sjlj-9.3.0/custombuilt --with-isl=/d/Prog/winlibs32-sjlj-9.3.0/custombuilt --enable-install-libiberty --enable-__cxa_atexit --without-included-gettext --with-diagnostics-color=auto --with-libiconv --with-system-zlib --with-build-sysroot=/R/winlibs32-sjlj-9.3.0/gcc-9.3.0/mingw-w64 --enable-large-address-aware
Thread model: posix
gcc version 9.3.0 (MinGW-W64 i686-posix-sjlj, built by Brecht Sanders)
$ echo -e "#include <iostream>\n#ifdef __USING_SJLJ_EXCEPTIONS__\n#define ANSWER \"yes\"\n#else\n#define ANSWER \"no\"\n#endif\nint main() {\nstd::cout << \"SJLJ: \" << ANSWER << std::endl;\nreturn 0;\n}" | g++ -xc++ -mconsole - -otest_sjlj.exe && test_sjlj.exe && rm -f test_sjlj.exe
SJLJ: yes
$ echo -e "#include <iostream>\n#ifdef __SEH__\n#define ANSWER \"yes\"\n#else\n#define ANSWER \"no\"\n#endif\nint main() {\nstd::cout << \"SEH: \" << ANSWER << std::endl;\nreturn 0;\n}" | g++ -xc++ -mconsole - -otest_seh.exe && test_seh.exe && rm -f test_seh.exe
SEH: no

64-bit:

$ gcc -v
Using built-in specs.
COLLECT_GCC=D:\Prog\winlibs64-sjlj-9.3.0\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=d:/prog/winlibs64-sjlj-9.3.0/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/9.3.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ./configure --prefix=/R/winlibs64-sjlj-9.3.0/inst_gcc-9.3.0/share/gcc --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --with-pkgversion='MinGW-W64 x86_64-posix-sjlj, built by Brecht Sanders' --with-tune=generic --enable-checking=release --enable-threads=posix --without-dwarf2 --enable-sjlj-exceptions --disable-libunwind-exceptions --enable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --enable-default-ssp --disable-rpath --disable-libstdcxx-pch --enable-libstdcxx-time=yes --disable-libstdcxx-debug --disable-version-specific-runtime-libs --with-stabs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++,d --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite --enable-mingw-wildcard --with-mpc=/d/Prog/winlibs64-sjlj-9.3.0/custombuilt --with-mpfr=/d/Prog/winlibs64-sjlj-9.3.0/custombuilt --with-gmp=/d/Prog/winlibs64-sjlj-9.3.0/custombuilt --with-isl=/d/Prog/winlibs64-sjlj-9.3.0/custombuilt --enable-install-libiberty --enable-__cxa_atexit --without-included-gettext --with-diagnostics-color=auto --with-libiconv --with-system-zlib --with-build-sysroot=/R/winlibs64-sjlj-9.3.0/gcc-9.3.0/mingw-w64
Thread model: posix
gcc version 9.3.0 (MinGW-W64 x86_64-posix-sjlj, built by Brecht Sanders)
$ echo -e "#include <iostream>\n#ifdef __USING_SJLJ_EXCEPTIONS__\n#define ANSWER \"yes\"\n#else\n#define ANSWER \"no\"\n#endif\nint main() {\nstd::cout << \"SJLJ: \" << ANSWER << std::endl;\nreturn 0;\n}" | g++ -xc++ -mconsole - -otest_sjlj.exe && test_sjlj.exe && rm -f test_sjlj.exe
SJLJ: yes
$ echo -e "#include <iostream>\n#ifdef __SEH__\n#define ANSWER \"yes\"\n#else\n#define ANSWER \"no\"\n#endif\nint main() {\nstd::cout << \"SEH: \" << ANSWER << std::endl;\nreturn 0;\n}" | g++ -xc++ -mconsole - -otest_seh.exe && test_seh.exe && rm -f test_seh.exe
SEH: yes

In 64-bit __SEH__ seems to be defined. Maybe it supports SEH too? If there is a simple test program to test this I would love to try it.

My initial thought was to only provide one version, as it's confusing to many people what to use (win32 or posix threads, dwarf/SEH or SJLJ exceptions).
And looking at the download stats from https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/ it appears most downloaded versions are posix+dwarf/SEH.
And like you said earlier dwarf/SEH is the best choice from a performance point of view.
Can you tell me what the reason is people are specifically looking for SJLJ?

@tomay3000
Copy link

tomay3000 commented Mar 22, 2020

Hi,
It seems like there must have been some leftover thing depending on other exception handling.
The 3rd iteration build at https://github.com/brechtsanders/winlibs_mingw/releases/tag/9.3.0-7.0.0-sjlj-r3 seems good.

Good, progress.

In 64-bit __SEH__ seems to be defined. Maybe it supports SEH too? If there is a simple test program to test this I would love to try it.

Idon't know about this.

My initial thought was to only provide one version, as it's confusing to many people what to use (win32 or posix threads, dwarf/SEH or SJLJ exceptions).
And looking at the download stats from https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/ it appears most downloaded versions are posix+dwarf/SEH.
And like you said earlier dwarf/SEH is the best choice from a performance point of view.
Can you tell me what the reason is people are specifically looking for SJLJ?

The most used threading model is posix.
And , the most used exception handling for 64-bits is SEH.
But for 32-bits, there are preferences:
If you want performance, you should go for DWARF, where performance here is not that big deal compared to SJLJ. But if you want compatibility and stability especially when linking against MSVC libraries, then you should go for SJLJ.

SJLJ can handle all exception traversal between GCC and MSVC callbacks, but DWARF can't do it properly and sometimes leads to applications crashing.

So, as a summary:

For 64-bits, SEH is the default and the most implemented in most of all MinGW-w64 builds.
As for 32-bits, I see:
Arch Linux, The official MinGW-w64, TDM-GCC, Code::Blocks, wxWidgets, Me myself, and more use the SJLJ exception model.

And The official MinGW-w64, and Msys2 uses DWARF.
as for Cygwin I haven't used it for decades.

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 22, 2020

I don't have intention of mixing MSVC with GCC as I generally think its a bad idea that should be avoided. My goal is to make a large repository with packages all built in the same environment.

I understand that if I want a single choice, your recommendation is:

  • 32-bit: SJLJ
  • 64-bit: SEH

@farta1986
Copy link
Author

farta1986 commented Mar 23, 2020

I don't have intention of mixing MSVC with GCC as I generally think its a bad idea that should be avoided. My goal is to make a large repository with packages all built in the same environment.

I understand that if I want a single choice, your recommendation is:

  • 32-bit: SJLJ
  • 64-bit: SEH

If there's no intention of MSVC/GCC mixing maybe it will be better to choose dwarf for 32 bit. As SJLJ will introduce overhead in happy path while dwarf won't.

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 23, 2020

Ok, so the final conclusion for me is:

  • 32-bit: dwarf
  • 64-bit: SEH
    Which is exactly what I was doing before, so no change.

@farta1986
Copy link
Author

farta1986 commented Mar 26, 2020

Ok, so the final conclusion for me is:

  • 32-bit: dwarf
  • 64-bit: SEH
    Which is exactly what I was doing before, so no change.

Yeah, thank you. Maybe we need to be aware of configure for future releases to prevent confusing version information.

PS C:\mingw\winlibs\mingw64\bin> .\gcc.exe --version
gcc.exe (MinGW-W64 x86_64-posix-dwarf, built by Brecht Sanders) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

This release is actually an SEH version.

@brechtsanders
Copy link
Owner

brechtsanders commented Mar 26, 2020

Good point. I changed my build script so the next release will be correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants