Dibyendu Majumdar
2015-Apr-28 08:59 UTC
[LLVMdev] MCJIT longjmp failure on Win64 - was Invalid or unaligned stack exception on Windows
On 28 April 2015 at 00:30, Reid Kleckner <rnk at google.com> wrote:> I think Paweł identified the problem. The frames on the stack between the > setjmp and longjmp must have valid unwind information, which is described > here: > https://msdn.microsoft.com/en-us/library/ft9x1kdx.aspx?f=255&MSPPError=-2147217396 > > In particular, it has this line about JITed code: > "For dynamically generated functions [JIT compilers], the runtime to > support these functions must either use RtlInstallFunctionTableCallback or > RtlAddFunctionTable to provide this information to the operating system. > Failure to do so will result in unreliable exception handling and debugging > of processes." > > LLVM does not contain any references to these functions, so I must conclude > that unwinding through LLVM JITed frames on Win64 is not supported. Sorry. > :-( >Now that I know what to look for it seems there are a number of posts on this issue: http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-October/078332.html I am changing the subject so that more people can find this topic. Re your suggestion to use my own longjmp/setjmp - do you mean I should use the LLVM intrinsics? But would they not call the Windows API anyway? I am also wondering if mingw gcc compilers have the same issue. Thanks and Regards Dibyendu
Paweł Bylica
2015-Apr-28 09:43 UTC
[LLVMdev] MCJIT longjmp failure on Win64 - was Invalid or unaligned stack exception on Windows
On Tue, Apr 28, 2015 at 11:01 AM Dibyendu Majumdar <mobile at majumdar.org.uk> wrote:> On 28 April 2015 at 00:30, Reid Kleckner <rnk at google.com> wrote: > > I think Paweł identified the problem. The frames on the stack between the > > setjmp and longjmp must have valid unwind information, which is described > > here: > > > https://msdn.microsoft.com/en-us/library/ft9x1kdx.aspx?f=255&MSPPError=-2147217396 > > > > In particular, it has this line about JITed code: > > "For dynamically generated functions [JIT compilers], the runtime to > > support these functions must either use RtlInstallFunctionTableCallback > or > > RtlAddFunctionTable to provide this information to the operating system. > > Failure to do so will result in unreliable exception handling and > debugging > > of processes." > > > > LLVM does not contain any references to these functions, so I must > conclude > > that unwinding through LLVM JITed frames on Win64 is not supported. > Sorry. > > :-( > > > > Now that I know what to look for it seems there are a number of posts > on this issue: > > http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-October/078332.html > > I am changing the subject so that more people can find this topic. > > > Re your suggestion to use my own longjmp/setjmp - do you mean I should > use the LLVM intrinsics? But would they not call the Windows API > anyway? >I'm not sure what your requirements are. Can you specify why do you need longjmp? The issue is your jump from longjmp call to setjmp location is crossing functions on callstack that were created by MCJIT. Those functions do not have proper stack unwinding information required by longjmp. The callstack looks like: setjmp, MSVC/C++ other code, LLVM MCJIT longjmp, MSVC/C++ Your solutions are: 1. Pull longjmp call from C++ to LLVM IR. LLVM has a convenient intrinsic for that: llvm.longjmp. That solution is a bit fragile as that intrinsic will be lowered to C standard lib call, but if I remember correctly it worked for me. Windows might have 3 different implementation of longjmp: debug and release versions for C++ and C, maybe one of them is less fussy. 2. Pull both longjmp and setjmp to LLVM IR. In that case you can switch from full-featured versions powered by standard library to lightweight builtin versions powered by LLVM (llvm.eh.sjlj.longjmp). Much better portability. In that second case, setting up llvm.eh.sjlj.setjmp correctly is a bit tricky. You need to place some data (as stack pointer) in the jump buffer manually. See http://lists.cs.uiuc.edu/pipermail/llvmdev/2015-February/081961.html I am also wondering if mingw gcc compilers have the same issue.>MinGW has its own implementation of setjmp/longjmp. Its longjmp do not do C++ stack unwinding of course. - Paweł -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150428/087fb117/attachment.html>
Dibyendu Majumdar
2015-Apr-28 10:09 UTC
[LLVMdev] MCJIT longjmp failure on Win64 - was Invalid or unaligned stack exception on Windows
On 28 April 2015 at 10:43, Paweł Bylica <chfast at gmail.com> wrote:> I'm not sure what your requirements are. Can you specify why do you need > longjmp?Lua uses setjmp/longjmp to implement exception handling. It is the Lua infrastructure code that is making these calls. A JIT compiled function does not directly call either - but may call a Lua C function that then invokes longjmp. As the Lua code is written in C - I do not need C++ stack unwinding.> > The issue is your jump from longjmp call to setjmp location is crossing > functions on callstack that were created by MCJIT. Those functions do not > have proper stack unwinding information required by longjmp. The callstack > looks like: > > setjmp, MSVC/C++ > other code, LLVM MCJIT > longjmp, MSVC/C++ > > Your solutions are: > > Pull longjmp call from C++ to LLVM IR. LLVM has a convenient intrinsic for > that: llvm.longjmp. That solution is a bit fragile as that intrinsic will be > lowered to C standard lib call, but if I remember correctly it worked for > me. Windows might have 3 different implementation of longjmp: debug and > release versions for C++ and C, maybe one of them is less fussy. > Pull both longjmp and setjmp to LLVM IR. In that case you can switch from > full-featured versions powered by standard library to lightweight builtin > versions powered by LLVM (llvm.eh.sjlj.longjmp). Much better portability. > In that second case, setting up llvm.eh.sjlj.setjmp correctly is a bit > tricky. You need to place some data (as stack pointer) in the jump buffer > manually. See > http://lists.cs.uiuc.edu/pipermail/llvmdev/2015-February/081961.html >> >> I am also wondering if mingw gcc compilers have the same issue. > > > MinGW has its own implementation of setjmp/longjmp. Its longjmp do not do > C++ stack unwinding of course.So the easiest option seems to be to compile using MingW ... I do not need C++ stack unwinding so that should be fine. I will also look at the built-ins - I can provide a JIT compiled wrapper that can be invoked by the Lua C functions. Many thanks for pointing me to this issue as I was wasting a lot of time trying to figure out if there was a bug in my code that was corrupting the stack. Thanks and Regards Dibyendu