C++/CX caught exception - how to print the full stack? - windows

I have a Windows Store application (for Windows 8) written in C++/CX and I have wrapped a chunk of my code in a try/catch block.
The catch block is working and catches an exception, but so far I only seem to be able to print out the "message" part of the exception and not the full exception stack:
try
{
...
}
catch(Exception^ e)
{
LogMessage("Exception caught: " + e->ToString());
}
When the exception is caught, the LogMessage outputs only the following text:
"Exception caught: The object already exists"
I've tried e->ToString() and e->Message, but both result in the same output and that does not include the full exception stack.
In C# it seems to be really easy to output the full exception stack, so I am not sure why it seems to be difficult in C++/CX ?

This is difficult in C++/CX because determining what functions would be in the stack requires code to parse debugging symbols. In C#, the CLR does work at runtime to remember which methods are in the stack, but in C++/CX, the names of functions are not recorded in the resulting binary. Put another way, the stack trace you get in C# depends on a C# feature: reflection.
Moreover, an exception may result from a call into code which is a plain COM API, rather than a C++/CX API. In such cases, the exception is generated from an error HRESULT return code underneath, not at the time where the exception is thrown. (Indeed, this is what happens whenever crossing component boundaries; this is handled with plain COM even if both sides of the operation are C++/CX) As such, the stack you would need for a trace is no longer available.
C++ exceptions do not record a stack trace. On the plus side, from native programs you can collect a minidump when an unhandled exception occurs, which lets you view the stack using a debugger if you need to.

Keep in mind that a C++/CX program is pure unmanaged C++ code. The CX language extension only makes it easy to consume WinRT types in your C++ code, it hides the COM implementation details. So it gets the full treatment of the code optimizer. Which does not try to ensure that stack walks can be safely performed. Particularly so in leaf functions that don't throw exceptions. It will readily omit setting the EBP register, the important one that indicates the base of a stack activation frame.
This is not the case in managed code, like C#. Stack walks are very important in a garbage collected runtime environment. The garbage collector must perform them to find object references when it collects garbage. Code Access Security also depends on stack walks. A happy side effect is that it now also becomes very easy to generate a stack trace for an exception. It is even exposed in the framework api, the StackTrace class lets you walk the stack in your own code.
No simple fix for this, you need debugging symbols to have a shot at it. And StackWalk64 from the DbgHelp api. With odds that you still don't get anywhere because the program crashed somewhere in the bowels of a Windows function. Speed trumps convenience in C++.

Related

How can I debug x64 windows exceptions?

I'm curious how Windows handles exceptions. More exactly, how Windows find the catch block of a try / catch. I saw that the compiler makes a separate function in assembly for catch block. Since the catch block was represented by another function in assembly, I couldn't find any correlation between the instruction that was generating the exception and the RUNTIME_FUNCTION entries from .pdata section.
I tried to put a breakpoint on RaiseException, RtlRaiseException and RtlVirtualUnwind but all I could find was the address after the RaiseException call. Tried to debug a divide by 0 exception, but it looks like the debugger has some additional exception handlers and the message in the catch block was not printed.
Any additional information about Stack Unwinding on Windows 64bit are welcome :D.
The exceptions are handled by exception handler routines.
When you add a try/catch block to your C++ code you will see that the compiler added __CxxFrameHandler3 to your import table (providing that the MSVCRT is not statically linked). So this is your exception handler that will be called when an exception occurs in the try block.
Another one __C_specific_handler is imported when you add __try/__except block to your C or C++ code.
There are a few others but these two are used in the C/C++ code.
To answer your question, the best way is to hook (replace the import table pointer with a pointer to your local routine) one of these functions and see how your "handler" will be called when an exception is thrown.
With the goal of finding C++ catch you can set Vectored Exception Handler and set a breakpoint in it. VEH goes before frame-based handlers, so it it not too late:
LONG NTAPI vh(EXCEPTION_POINTERS* ExceptionInfo)
{
return EXCEPTION_CONTINUE_SEARCH;
}
AddVectoredExceptionHandler(TRUE, vh);
Alternatively, if you want to set breakpoint closer to catch block, have __try...__except deeper in call stack than target catch block, in __except expression return EXCEPTION_CONTINUE_SEARCH and have your breakpoint there.

Under what conditions do I need to set up SEH unwind info for an x86-64 assembly function?

The 64-bit Windows ABI defines a generalized exception handling mechanism, which I believe is shared across C++ exceptions and structured exceptions available even in other languages such as C.
If I'm writing an x86-64 assembly routine to be compiled in nasm and linked into a C or C++ library, what accommodations do I need make on Windows in terms of generating unwind info and so on?
I'm not planning on generating any exceptions directly in the assembly code, although I suppose it is possible that the code may get an access violation if a user-supplied buffer is invalid, etc.
I'd like the write the minimum possible to get this to work, especially since it seems that nasm has poor support for generating unwind info and using MASM is not an option for this cross-platform project. I do need to use (hence save and restore) non-volatile registers.
As a general rule, Windows x64 requires all functions to provide unwind information. The only exception is for leaf functions which do not modify rsp and do not modify any nonvolatile registers.
Judging by the context of your question, what you really want to know is the practical consequences of not providing unwind information for your non-leaf assembly functions on x64 Windows. Since C++ exceptions are implemented based on SEH exceptions, when I talk about exceptions below, I mean both all "native" (access violation, something thrown using RaiseException, etc.) and C++ exceptions. Here's a list off the top of my head:
Exceptions won't be able to pass through your function
It's important to note that this point is not about throwing an exception, or an access violation happening directly in your function. Let's say your assembly code calls into a C++ function, which throws an exception. Even if the caller of your assembly function has a matching catch block, it will never be able to catch the exception, as unwinding will stop at your function without the unwind data.
When walking the stack, the stack walk will stop at the function without unwind data (or go astray; the point is, you will get an invalid call stack)
Basicaly, anything that walks the stack is screwed if your function is present on the call stack (debuggers when displaying the call stack, profilers, etc.)
Registered Unhandled Exception Filters will not be called back if an exception gets thrown, and your assembly function is on the call stack
This interferes with anything that relies on UEFs. Custom crash handlers, for instance. Or something potentially more relevant: std::terminate won't be called back in this case, if your program throws a C++ exception, that is unhandled (as it's dictated by the C++ standard). The MSVC runtime uses a UEF to implement this, so this won't work as well.
Are you developing a 3rd party library? If that's the case, the importance of the above points will depend on the use case of your clients.

Why does eclipse debugger only show 1 or 2 lines of the stack followed by 0x0?

On Linux I get nice, healthy, full stack traces. On Windows, however, when something crashes (like a segfault violation), I only get the top one or two lines of the stack, followed by the entry 0x0 (which I cannot expand). This makes it very hard to debug
Probably you should start using WinDBG to debug your program instead of IDE like eclipse. This is very powerful command line tool and its functionality is very similar to GDB.
On Windows, "UnhandledExceptionFilter" function is called when no exception handler is defined to handle the exception that is raised. The function typically passes the exception up to the Ntdll.dll file, which catches and tries to handle it.
EXCEPTION_POINTERS structure does contains the most useful information about what is the exception and where it has occurred which gets passed as one of the parameter of the above function. This information would be used by .exr and .cxr command in WinDBG to get the complete stack trace.
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
ExceptionRecord A pointer to an EXCEPTION_RECORD structure that
contains a machine-independent description of the exception.
ContextRecord A pointer to a CONTEXT structure that contains a
processor-specific description of the state of the processor at the
time of the exception.
For complete steps about how to get the complete back trace and analysis from the dump file(like GDB)or debug session, you may want to read and follow the steps mentioned in the following link:
http://support.microsoft.com/kb/313109

SEH setup for fibers with exception chain validation (SEHOP) active

I'm working on a native fiber/coroutine implementation – fairly standard, for each fiber, a separate stack is allocated, and to switch contexts, registers are pushed onto the source context stack and popped from the target stack. It works well, but now I hit a little problem:
I need SEH to work within a fiber (it's okay if the program terminates or strange things start to happen when an exception goes unhandled until the fiber's last stack frame, it won't). Just saving/restoring FS:[0] (along with FS:[4] and FS:[8], obviously) during the context switch and initially setting FS:[0] for newly allocated fibers to 0xFFFFFFFF (so that the exception handler set after the context switch will be the root of the chain) almost works.
To be precise, it works on all non-server Windows OSes I tested – the problem is that Windows Server 2008 and 2008 R2 have the exception chain validation (SEHOP, SEH overwrite protection) feature enabled by default, which makes RaiseException check if the original handler (somewhere in ntdll.dll) is still the root of the chain, and immediately terminates the program as if no handlers were installed otherwise.
Thus, I'm facing the problem of constructing an appropriate root frame on the stack to keep the validation code happy. Are there any (hidden?) API functions I can call to do that, or do I have to figure out what is needed to keep RtlDispatchException and friends happy and construct the appropriate _EXCEPTION_REGISTRATION entry myself? I can't just reuse the Windows-supplied one from the creating thread because it would be at the wrong address (the SEH implementation also checks if the handler address is in the boundaries given by FS:[4] and FS:[8], and possibly also if the address order is consistent).
Oh, and I'd strongly prefer not to resort to the CreateFiber WinAPI family of functions.
The approach I mentioned in the comments, generating a fake EXCEPTION_REGISTRATION entry pointing to ntdll!FinalExceptionHandler seems to work in practice indeed – at least, that's what we have in the D runtime now, and so far there have been no reports of problems:
https://github.com/D-Programming-Language/druntime/blob/c39de42dd11311844c0ef90953aa65f333ea55ab/src/core/thread.d#L4027

How to see where an exception is caught?

An MFC, C++ application I'm working on seems to be throwing an exception deep inside a device driver. (It's an access violation writing to a NULL pointer from the looks of things. The details of the crash are not what is interesting me right now, however...)
I can get the Visual Studio Debugger to break when the exception occurs through the Exceptions dialog. What I would like to know though is where the exception is being caught. Visual Studio can pass the exception on to the program being debugged, but there doesn't seem to be anyway (that I know of) to single step to the next instruction so I can view the callstack from the exception handler's point of view.
Does anyone know whether it is possible to step to the exception handler that will catch the exception or not?
Cheers,
James
With WinDbg, you can use the !exchain command. With !exchain -c, it will show your C++ destructors and catch blocks. e.g.
Try block 0
Catch block 0, type: module!my_exception `RTTI Type Descriptor'+0 (6071409c)
handler: module!catch_block+582 (6063bcc2)
Then you can set a breakpoint with bp 6063bcc2.
I don't know of a way to do this in Visual Studio.
At the point when the exception is being thrown you should have a call stack available to you in the debugger -- by looking at each stack frame from the point of the throw to main, you should be able to find the first frame with a try/catch block wrapping the call to the next routine in the frame. As long as that try/catch block handles the type of exception being thrown, that's where it'll land.

Resources