digitalmars.D.debugger - Catching excecptions in the MSVC debugger when running Win64
- Lewis (31/31) Apr 26 2021 I can't seem to catch a D exception on win64 in the Visual Studio
- Lewis (1/1) Apr 26 2021 Clearly I don't know how to spell exception :P
- Lewis (29/29) Apr 26 2021 Okay, I was able to get the VS debugger to catch exceptions in
- Rainer Schuetze (10/42) Apr 26 2021 Unfortunately, the dmd backend does not use the standard exception
I can't seem to catch a D exception on win64 in the Visual Studio debugger. I'm using: - DMD compiler (2.094.2) - VisualD 1.1.0 - Visual Studio 2019 - Building a Win64 executable - Debugger set to Visual Studio - All Win32 and D exceptions enabled in the Exception Settings window in VS Test code: ``` import std.file : copy; int main() { copy("filethatdoesnotexist.bla", "othernonexistentfile.bla"); return 0; } ``` I've tried manually rebuilding phobos in debug so I can see inside it. I can step into the copy(), all the way until the point where it constructs the FileException object. But the debugger never seems to catch the exception. Instead the debugger breaks in deh_win64_posix.d:493 on the call to terminate() at the end of _d_throwc(). But this just causes the debugger to catch *0xC0000096: Privileged instruction* (presumably due to the hlt instruction inside terminate()), instead of actually understanding the D FileException that got thrown. Nothing is printed to the output window regarding the D exception Is this the expected behaviour? If not, how to I get visual studio to properly catch D exceptions for a win64 executable?
Apr 26 2021
Okay, I was able to get the VS debugger to catch exceptions in win64 by adding a hack to deh_win64_posix.d so that it mimics deh_win32.d. I added the following code above the definition of _d_throwc(): ``` import core.sys.windows.windef : DWORD; extern(Windows) { void RaiseException(DWORD, DWORD, DWORD, void*); } ``` ...and I added the following to _d_throwc() itself, right after it calls _d_createTrace(): ``` template MAKE_EXCEPTION_CODE(int severity, int facility, int exception) { enum int MAKE_EXCEPTION_CODE = (((severity) << 30) | (1 << 29) | (0 << 28) | ((facility) << 16) | (exception)); } enum int STATUS_DIGITAL_MARS_D_EXCEPTION = MAKE_EXCEPTION_CODE!(3,'D',1); enum DWORD EXCEPTION_NONCONTINUABLE = 1; RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION, EXCEPTION_NONCONTINUABLE, 1, cast(void*)&h); ``` With this, the debugger catches exceptions again. This feels like a total hack though. Presumably I'm missing an obvious better solution?
Apr 26 2021
On 27/04/2021 07:43, Lewis wrote:Okay, I was able to get the VS debugger to catch exceptions in win64 by adding a hack to deh_win64_posix.d so that it mimics deh_win32.d. I added the following code above the definition of _d_throwc(): ``` import core.sys.windows.windef : DWORD; extern(Windows) { void RaiseException(DWORD, DWORD, DWORD, void*); } ``` ...and I added the following to _d_throwc() itself, right after it calls _d_createTrace(): ``` template MAKE_EXCEPTION_CODE(int severity, int facility, int exception) { enum int MAKE_EXCEPTION_CODE = (((severity) << 30) | (1 << 29) | (0 << 28) | ((facility) << 16) | (exception)); } enum int STATUS_DIGITAL_MARS_D_EXCEPTION = MAKE_EXCEPTION_CODE!(3,'D',1); enum DWORD EXCEPTION_NONCONTINUABLE = 1; RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION, EXCEPTION_NONCONTINUABLE, 1, cast(void*)&h); ``` With this, the debugger catches exceptions again. This feels like a total hack though. Presumably I'm missing an obvious better solution?Unfortunately, the dmd backend does not use the standard exception mechanism for win64, but some homegrown one adapted from the linux exception handling. That's why the debugger does not recognize the exceptions. Your solution works for catching exceptions, but catch statements will not work with RaiseException. I guess the best option is to set a breakpoint in _d_throwc. LDC uses C++ exceptions, so your debugger should behave as expected when building with LDC.
Apr 26 2021