[GHC] #6079: SEH exception handler not implemented on Win64

GHC ghc-devs at haskell.org
Mon Jan 26 22:45:45 UTC 2015


#6079: SEH exception handler not implemented on Win64
-------------------------------------+-------------------------------------
        Reporter:  igloo             |                   Owner:  Phyx-
            Type:  bug               |                  Status:  new
        Priority:  normal            |               Milestone:  7.12.1
       Component:  Runtime System    |                 Version:  7.5
      Resolution:                    |                Keywords:
Operating System:  Windows           |            Architecture:  x86_64
 Type of failure:  None/Unknown      |  (amd64)
      Blocked By:                    |               Test Case:  derefnull,
 Related Tickets:                    |  divbyzero
                                     |                Blocking:
                                     |  Differential Revisions:
-------------------------------------+-------------------------------------

Comment (by Phyx-):

 Summary of what's changed and how It affects the GHC side of things:

 on x86 SEH handling was done via the stack. On a thread FS[0] would always
 point to the SEH linked list. It was also prone to buffer overflows and
 made it hard to share error handlers.

 on x64 it was cleaned up a bit and the EH information is now stored in the
 the PE headers in tables. instead of an EH covering an entire thread until
 popped, you know have to explicitly specify the rva (relative virtual
 address) of the region to which the EH should apply.

 Microsoft compilers calculate this information at compile time from the
 !__try, !__catch and !__except1 symbols and this information is statically
 added to the PE file. GCC's implementation works by dynamically
 manipulating the table (using '''RtlAddFunctionTable''' and related
 functions).

 It's implemented in MingW64 from version 4.6.2 (current version of msys2
 ships with newer version so should be fine) and is based on GAS's
 implementation
 http://code.google.com/p/propgcc/source/browse/binutils/gas/config/obj-
 coff-seh.h

 The only way to use this is inline assembly in gcc:

 BEGIN_CATCH and END_CATCH theoretically become:

 >long CALLBACK !__hs_exception_handler(EXCEPTION_POINTERS
 *exception_data);

 >#define BEGIN_CATCH asm (".l_start:\n" \
 >                         "\t.seh_handler !__C_specific_handler,
 @except\n" \
 >                         "\t.seh_handlerdata\n" \
 >                         "\t.long 1\n" \
 >                         "\t.rva .l_start, .l_end,
 !__hs_exception_handler, .l_end\n" \
 >                         "\t.text" \
 >                        );

 > #define END_CATCH asm ("nop\n" \
 >                        "\t.l_end:\n" \
 >                        "\tnop\n" \
 >                        );

 everything between the .l_start and .l_end label is covered by the
 function !__hs_exception_handler.


 {{{
 The interesting part here is the line "\t.rva .l_startw, .l_endw,
 _gnu_exception_handler ,.l_endw\n".  The first rva is the
 start-address of the first instruction within try-block,
 the next is the end-address of the try-block (be aware that it needs
 to +1 after end of last instruction in try-block). The third rva is
 the handler to be called, and the fourth is the address of the
 finally-block.

 }}}

 (NOTE: the \t are only for indenting if viewing the dissassembly generated
 from gcc with -S)

 ---

 Implementation wise, a few things make it difficult:
 1) the function real_main() in RtsMain is decorated with !__noreturn!__,
 this makes GCC perform dead code elimination and remove the END_CATCH, the
 linker will then refuse to link as the .l_end label will be missing.

 Instead moving the BEGIN_CATCH and END_CATCH blocks inside the real_main
 to appropriate positions allows it all to work.

 ---

 I have the changes implemented but the handler is not being called for
 some reason. I will figure out what's wrong and create a patch. I'm
 concerned that when linking, the .l_end label is put in a position that
 does not cover the user code, in which case this implementation would
 probably get more complex

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/6079#comment:10>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list