4 ms·
> Traps don't quite work the way you'd want in C [1]; there's no way to catch a trap that occurs in a specific region of code. Ah, unless you're in NT land, wh
by trentnelson 8y ago
> Traps don't quite work the way you'd want in C [1]; there's no way to catch a trap that occurs in a specific region of code.
Ah, unless you're in NT land, which makes lexical scoping of traps very easy: https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285e313894adc89e4e/PerfectHashTable/Chm_01.c#L843 https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285...
//
// Verify the guard page is working properly by wrapping an attempt to
// write to it in a structured exception handler that will catch the
// access violation trap.
//
// N.B. We only do this if we're not actively being debugged, as the
// traps get dispatched to the debugger engine first as part of
// the "first-pass" handling logic of the kernel.
//
if (!IsDebuggerPresent()) {
CaughtException = FALSE;
TRY_PROBE_MEMORY{
*Unusable = 1;
} CATCH_EXCEPTION_ACCESS_VIOLATION{
CaughtException = TRUE;
}
ASSERT(CaughtException);
}
The helper #defines: https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285e313894adc89e4e/Rtl/Rtl.h#L389 https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285..., e.g.
#define TRY_TSX __try
#define TRY_AVX __try
#define TRY_AVX512 __try
#define TRY_AVX_ALIGNED __try
#define TRY_AVX_UNALIGNED __try
#define TRY_SSE42 __try
#define TRY_SSE42_ALIGNED __try
#define TRY_SSE42_UNALIGNED __try
#define TRY_PROBE_MEMORY __try
#define TRY_MAPPED_MEMORY_OP __try
#define CATCH_EXCEPTION_ILLEGAL_INSTRUCTION __except( \
GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH \
)
#define CATCH_EXCEPTION_ACCESS_VIOLATION __except( \
GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH \
)
#define CATCH_STATUS_IN_PAGE_ERROR __except( \
GetExceptionCode() == STATUS_IN_PAGE_ERROR ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH \
)
#define CATCH_STATUS_IN_PAGE_ERROR_OR_ACCESS_VIOLATION __except( \
GetExceptionCode() == STATUS_IN_PAGE_ERROR || \
GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH \
)
Also allows you to do fun things like this for testing if you can do an AVX512 op (although this is not the supported way of doing things):
#pragma optimize("", off)
static
NOINLINE
VOID
CanWeUseAvx512(PBOOLEAN UseAvx512Pointer)
{
BOOLEAN UseAvx512 = TRUE;
TRY_AVX512 {
ZMMWORD Test1 = _mm512_set1_epi64(1);
ZMMWORD Test2 = _mm512_add_epi64(Test1, Test1);
UNREFERENCED_PARAMETER(Test2);
} CATCH_EXCEPTION_ILLEGAL_INSTRUCTION{
UseAvx512 = FALSE;
}
*UseAvx512Pointer = UseAvx512;
}
#pragma optimize("", on)
https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285e313894adc89e4e/Rtl/Rtl.h#L6784 https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285...
The structured exception handling protocol used by NT is really quite elegant.