seh / landing pads

In the past people in #llvm suggested to me I should use landing pads instead of seh when it comes to Windows unless i really need seh. Looking at what gets generated win64 -gnu does use seh but calls the landing pad somehow, while win32 doesn't at all. It looks to me a custom win64 landing pad personality can also deal with things like Access Violation. Is there a way to make win32 also able to catch say access violation but still use landing pads?

Also are there open source Unwind* implementions that work on windows, that anyone knows of?

Yes, it is definitely technically feasible to catch access violations with landingpads, but it will involve writing your own EH personality, probably by starting with the one from libgcc.

The major consideration for whether to use a landingpad EH personality or a funclet-based EH personality is, do you need to be compatible with MSVC EH? That is, do you want destructors in MSVC frames to run if your exception is thrown, and do you want to clean up if an MSVC C++ exception unwinds through your stack frame? If yes, then you need to use the new EH instructions (catchpad). If no, then you’ll get better code if you use landingpad.

I also want to try to unpack what you mean when you say “landing pads instead of seh” and “win64-gnu does use seh but calls the landingpad somehow”. SEH is a very overloaded term. Here are the two things people usually mean by it:

  • The mechanisms used to unwind the stack on Windows, either for 32-bit or 64-bit x86 (.seh_* directives)
  • The MSVC language mechanism for catching non-call exceptions in a structured manner (__try / __except)

Every major compiler on Win64 implements the standard stack unwind information format that Microsoft specified at https://msdn.microsoft.com/en-us/library/0kd71y96.aspx. This corresponds to the .seh_* assembler directives that GCC, gas, and LLVM use on Win64, which is what you’re seeing.

x86_32 Windows uses a less sophisticated unwind mechanism involving a linked list maintained in TLS at fs:00. Sometimes people use SEH to refer to this and related structures.

Yes, it is definitely technically feasible to catch access violations
with landingpads, but it will involve writing your own EH personality,
probably by starting with the one from libgcc.

The major consideration for whether to use a landingpad EH personality
or a funclet-based EH personality is, do you need to be compatible with
MSVC EH? That is, do you want destructors in MSVC frames to run if your
exception is thrown, and do you want to clean up if an MSVC C++
exception unwinds through your stack frame? If yes, then you need to use
the new EH instructions (catchpad). If no, then you'll get better code
if you use landingpad.

I also want to try to unpack what you mean when you say "landing pads
instead of seh" and "win64-gnu does use seh but calls the landingpad
somehow". SEH is a very overloaded term. Here are the two things people
usually mean by it:
- The mechanisms used to unwind the stack on Windows, either for 32-bit
or 64-bit x86 (.seh_* directives)
- The MSVC language mechanism for catching non-call exceptions in a
structured manner (__try / __except)

Every major compiler on Win64 implements the standard stack unwind
information format that Microsoft specified
at x64 exception handling | Microsoft Learn
<Microsoft Learn: Build skills that open doors in your career. This
corresponds to the .seh_* assembler directives that GCC, gas, and LLVM
use on Win64, which is what you're seeing.

thanks for the extensive reply. This sounds exactly like what I want.

x86_32 Windows uses a less sophisticated unwind mechanism involving a
linked list maintained in TLS at fs:00. Sometimes people use SEH to
refer to this and related structures.

But the landingpad stuff on x86_32 won't use fs:00 will it? Can I still use it to catch access violations and other internal exception types?

True, it won't. Clang and GCC typically use DWARF unwind info on
i686-windows-gnu.

I think you can use SetUnhandledExceptionFilter
or AddVectoredExceptionHandler to install a global exception handler for
AVs and traps that calls into the usual _Unwind* EH machinery.