Reputation: 1755
I'm aware of the general overview: http://msdn.microsoft.com/en-us/library/dn743843.aspx ; there is plenty of information available on the exception mechanism in win32 and some for win64, but ARM is not so clear.
I would like to know: when a machine exception is generated (memory protection violation), exactly where is control transferred to (so I can set a breakpoint)? Does it transfer into kernel mode? Presumably it looks up the address of a handler from the vector table and transfers there. Does the kernel code perform the SEH unwind, or is the unwind done in user mode? If in user mode, where exactly - part of the .exe, coredll, or elsewhere?
Background
We have a large application which places __try / __except handlers around the top level of each thread in order to log crashes in an informative way. This has worked fine for years on MIPS. We're now porting it to WinCE 7 on ARM, building under VS2008. We found that exceptions would sometimes not be handled properly in release builds. This seems to depend on exactly where in the code the exception is generated (I have a test function which deliberately accesses a NULL pointer to raise a SEH exception, and I'm calling this from various locations in the code).
We're using the /EHsc option to enable SEH. Release builds use /O2 /Os ; removing /O2 makes it work but significantly slower. That leads me to believe that the optimizer is deleting something that's required for SEH to work - but what exactly? Not all functions have the "mov r12, sp ..." prologue, but some that don't still work properly. Is it some error in the PDATA? Is there an upper limit on the number of PDATA entries? Is it normal that the output of "dumpbin /pdata" doesn't have a function name on every line?
By using the debugger (despite release build), I can place a breakpoint at the start of my exception filtering function (called from __except) and observe that it is never entered in the failure case. The program just exits.
Upvotes: 3
Views: 2784
Reputation: 50026
This might be not the exact answer to your question but if your goal is to catch critical hardware exceptions and log its call stack then since Windowce CE 6.0 you can use AddVectoredExceptionHandler. In application I work (vs2005, ARM only) on I am able to get call stacks with the help of this function, also you dont need to add SEH catch/throw, exception handler will always get called.
Upvotes: 1
Reputation: 283793
We're using the /EHsc option to enable SEH
You're supposed to use /EHa
with SEH. /EHsc
allows the compiler to optimize away all exception-handling logic if it can prove that the C++ throw
statement will not be reached inside the block.
Structured Exception Handling __try
and __except
will work even with /EHsc
, but then C++ stack unwinding won't take place for structured exceptions. As a result, global state may be inconsistent after an exception, which may result in the failure of your handler.
Upvotes: 1
Reputation: 25318
I'm not familiar with the low-level kernel details, but pointer to the CRT exception handler is stored in the dwords just before the function:
0001106C DCD _C_specific_handler ; handler function
00011070 DCD _scope_table ; scope table (__try/__except map)
00011074 start
00011074 MOV R12, SP
Maybe put your breakpoint on the _C_specific_handler
and see if it's invoked. The actual function is in COREDLL. If it does get called but does not pass the exception to your code, possibly the scope table info is wrong for some reason.
EDIT: the above applies to WinCE 6 and earlier. Since you mention VS2008, I'm pretty sure WinCE 7 still uses the same exception handling model. The link you mention (unwind code-based) applies to the new, ARMv7-only WinRT kernel (I think Windows Embedded Compact 2013 uses it too).
Upvotes: 1
Reputation: 57749
This is very easy. Type "ARM ARM" into your favorite search engine.
A narrower seach "ARM prefetch exception".
In essence, when the processor tries to fetch data from an undefined memory area, a Data Fetch exception is generated. The processor transfers execution to a predefined address called an exception vector. The rest of the behavior is up to the programmer or OS. For example, on an embedded system, a System Failure function may be called. On a desktop platform, the OS would generate a signal or exception and terminate the program.
Other platforms may have advanced Memory Management Unit (MMU) processors that can have fences. When a program accesses outside of the fenced area, an exeception or interrupt is generated. The region would be programmed into the MMU. This enable an OS to protect regions in memory that a User's program should not access, even though memory does exist.
Accessing undefined regions of memory or memory your program does not have access to is defined as "undefined behavior". This behavior may vary by compiler or platform and there is no standard behavior. Some platforms may generate "signals", others may generate "exceptions", some pass messages, others just crash. If you want portable memory exception handling, you will need to write platform specific code.
Upvotes: 0