Changeset 97862 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Dec 23, 2022 4:55:57 PM (2 years ago)
- Location:
- trunk/src/VBox/Runtime/common/compiler/vcc
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/compiler/vcc/except-vcc.h
r96559 r97862 120 120 121 121 #ifdef RT_ARCH_AMD64 122 123 122 /** 124 123 * The Visual C++ 2019 layout of the GS_HANDLER_DATA data type for AMD64. … … 150 149 typedef GS_HANDLER_DATA *PGS_HANDLER_DATA; 151 150 typedef GS_HANDLER_DATA const *PCGS_HANDLER_DATA; 152 #endif 151 #endif /* RT_ARCH_AMD64 */ 153 152 154 153 #ifdef RT_ARCH_X86 … … 158 157 #endif 159 158 159 160 #ifdef RT_ARCH_X86 161 162 /** 163 * Exception registration record for _except_handler4 users 164 * (aka EH4_EXCEPTION_REGISTRATION_RECORD). 165 * 166 * This record is emitted immediately following the stack frame setup, i.e. 167 * after doing PUSH EBP and MOV EBP, ESP. So, EBP equals the address following 168 * this structure. 169 */ 170 typedef struct EH4_XCPT_REG_REC_T 171 { 172 /** The saved ESP after setting up the stack frame and before the __try. */ 173 uintptr_t uSavedEsp; 174 PEXCEPTION_POINTERS pXctpPtrs; 175 /** The SEH exception registration record (chained). */ 176 EXCEPTION_REGISTRATION_RECORD XcptRec; 177 uintptr_t uEncodedScopeTable; 178 uint32_t uTryLevel; 179 /* uintptr_t uSavedCallerEbp; */ 180 } EH4_XCPT_REG_REC_T; 181 AssertCompileSize(EH4_XCPT_REG_REC_T, 24); 182 /** Pointer to an exception registration record for _except_handler4 (aka 183 * PEH4_EXCEPTION_REGISTRATION_RECORD). */ 184 typedef EH4_XCPT_REG_REC_T *PEH4_XCPT_REG_REC_T; 185 186 187 /** Exception filter function for _except_handler4 users (aka 188 * PEXCEPTION_FILTER_X86). */ 189 typedef uint32_t (__cdecl *PFN_EH4_XCPT_FILTER_T)(void); 190 /** Exception handler block function for _except_handler4 users (aka 191 * PEXCEPTION_HANDLER_X86). */ 192 typedef void (__cdecl *PFN_EH4_XCPT_HANDLER_T)(void); 193 /** Exception finally block function for _except_handler4 users (aka 194 * PTERMINATION_HANDLER_X86). 195 */ 196 typedef void (__fastcall *PFN_EH4_FINALLY_T)(BOOL fAbend); 197 198 /** 199 * Scope table record describing __try / __except / __finally blocks (aka 200 * EH4_SCOPETABLE_RECORD). 201 */ 202 typedef struct EH4_SCOPE_TAB_REC_T 203 { 204 uint32_t uEnclosingLevel; 205 /** Pointer to the filter sub-function if this is a __try/__except, NULL for 206 * __try/__finally. */ 207 PFN_EH4_XCPT_FILTER_T pfnFilter; 208 union 209 { 210 PFN_EH4_XCPT_HANDLER_T pfnHandler; 211 PFN_EH4_FINALLY_T pfnFinally; 212 }; 213 } EH4_SCOPE_TAB_REC_T; 214 AssertCompileSize(EH4_SCOPE_TAB_REC_T, 12); 215 /** Pointer to a const _except_handler4 scope table entry. */ 216 typedef EH4_SCOPE_TAB_REC_T const *PCEH4_SCOPE_TAB_REC_T; 217 218 /** Special EH4_SCOPE_TAB_REC_T::uEnclosingLevel used to terminate the chain. */ 219 #define EH4_TOPMOST_TRY_LEVEL UINT32_C(0xfffffffe) 220 221 /** 222 * Scope table used by _except_handler4 (aka EH4_SCOPETABLE). 223 */ 224 typedef struct EH4_SCOPE_TAB_T 225 { 226 uint32_t offGSCookie; 227 uint32_t offGSCookieXor; 228 uint32_t offEHCookie; 229 uint32_t offEHCookieXor; 230 EH4_SCOPE_TAB_REC_T aScopeRecords[RT_FLEXIBLE_ARRAY]; 231 } EH4_SCOPE_TAB_T; 232 AssertCompileMemberOffset(EH4_SCOPE_TAB_T, aScopeRecords, 16); 233 /** Pointer to a const _except_handler4 scope table. */ 234 typedef EH4_SCOPE_TAB_T const *PCEH4_SCOPE_TAB_T; 235 236 /** Special EH4_SCOPE_TAB_T::offGSCookie value. */ 237 # define EH4_NO_GS_COOKIE UINT32_C(0xfffffffe) 238 239 #endif /* RT_ARCH_X86 */ 240 241 242 160 243 #if defined(RT_ARCH_AMD64) 161 244 EXCEPTION_DISPOSITION __C_specific_handler(PEXCEPTION_RECORD pXcptRec, PEXCEPTION_REGISTRATION_RECORD pXcptRegRec, -
trunk/src/VBox/Runtime/common/compiler/vcc/except-x86-vcc.cpp
r96407 r97862 41 41 #include <iprt/win/windows.h> 42 42 43 43 #include "except-vcc.h" 44 45 46 /********************************************************************************************************************************* 47 * Global Variables * 48 *********************************************************************************************************************************/ 49 extern "C" uintptr_t __security_cookie; 50 51 52 /********************************************************************************************************************************* 53 * Internal Functions * 54 *********************************************************************************************************************************/ 55 DECLASM(LONG) rtVccEh4DoFiltering(PFN_EH4_XCPT_FILTER_T pfnFilter, uint8_t const *pbFrame); 56 DECLASM(DECL_NO_RETURN(void)) rtVccEh4JumpToHandler(PFN_EH4_XCPT_HANDLER_T pfnHandler, uint8_t const *pbFrame); 57 //DECLASM(void) rtVccEh4DoLocalUnwind(PEXCEPTION_REGISTRATION_RECORD pXcptRegRec, uint32_t uTargetTryLevel, 58 // uint8_t const *pbFrame, uintptr_t *pSecurityCookie); 59 DECLASM(void) rtVccEh4DoGlobalUnwind(PEXCEPTION_RECORD pXcptRec, PEXCEPTION_REGISTRATION_RECORD pXcptRegRec); 60 DECLASM(void) rtVccEh4DoFinally(PFN_EH4_FINALLY_T pfnFinally, bool fAbend, uint8_t const *pbFrame); 61 62 63 static void rtVccEh4DoLocalUnwind(PEXCEPTION_REGISTRATION_RECORD pXcptRegRec, uint32_t uTargetTryLevel, 64 uint8_t const *pbFrame, uintptr_t *pSecurityCookie) 65 { 66 /* 67 * Manually set up exception handler. 68 */ 69 /** @todo */ 70 71 /* 72 * Do the unwinding. 73 */ 74 PEH4_XCPT_REG_REC_T pEh4XcptRegRec = RT_FROM_MEMBER(pXcptRegRec, EH4_XCPT_REG_REC_T, XcptRec); 75 uint32_t uCurTryLevel = pEh4XcptRegRec->uTryLevel; 76 while ( uCurTryLevel != EH4_TOPMOST_TRY_LEVEL 77 && ( uCurTryLevel > uTargetTryLevel 78 || uTargetTryLevel == EH4_TOPMOST_TRY_LEVEL /* if we knew what 0xffffffff meant, this could probably be omitted */ )) 79 { 80 PCEH4_SCOPE_TAB_T const pScopeTable = (PCEH4_SCOPE_TAB_T)(pEh4XcptRegRec->uEncodedScopeTable ^ *pSecurityCookie); 81 PCEH4_SCOPE_TAB_REC_T const pEntry = &pScopeTable->aScopeRecords[uCurTryLevel]; 82 83 pEh4XcptRegRec->uTryLevel = uCurTryLevel = pEntry->uEnclosingLevel; 84 85 /* __finally scope table entries have no filter sub-function. */ 86 if (!pEntry->pfnFilter) 87 { 88 //RTAssertMsg2("rtVccEh4DoLocalUnwind: Calling %p (level %#x)\n", pEntry->pfnFinally, uCurTryLevel); 89 rtVccEh4DoFinally(pEntry->pfnFinally, true /*fAbend*/, pbFrame); 90 91 /* Read the try level again in case it changed... */ 92 uCurTryLevel = pEh4XcptRegRec->uTryLevel; 93 } 94 } 95 96 /* 97 * Deregister exception handler. 98 */ 99 /** @todo */ 100 } 101 102 103 DECLINLINE(void) rtVccValidateExceptionContextRecord(PCONTEXT pCpuCtx) 104 { 105 RT_NOREF(pCpuCtx); 106 /** @todo Implement __exception_validate_context_record .*/ 107 } 108 109 110 DECLINLINE(void) rtVccEh4ValidateCookies(PCEH4_SCOPE_TAB_T pScopeTable, uint8_t const *pbFrame) 111 { 112 if (pScopeTable->offGSCookie != EH4_NO_GS_COOKIE) 113 { 114 uintptr_t uGsCookie = *(uintptr_t const *)&pbFrame[pScopeTable->offGSCookie]; 115 uGsCookie ^= (uintptr_t)&pbFrame[pScopeTable->offGSCookieXor]; 116 __security_check_cookie(uGsCookie); 117 } 118 119 uintptr_t uEhCookie = *(uintptr_t const *)&pbFrame[pScopeTable->offEHCookie]; 120 uEhCookie ^= (uintptr_t)&pbFrame[pScopeTable->offEHCookieXor]; 121 __security_check_cookie(uEhCookie); 122 } 123 124 125 /** 126 * Call exception filters, handlers and unwind code for x86 code. 127 * 128 * This is called for windows' structured exception handling (SEH) in x86 32-bit 129 * code, i.e. the __try/__except/__finally stuff in Visual C++. The compiler 130 * generate scope records for the __try/__except blocks as well as unwind 131 * records for __finally and probably C++ stack object destructors. 132 * 133 * @returns Exception disposition. 134 * @param pXcptRec The exception record. 135 * @param pXcptRegRec The exception registration record, taken to be the frame 136 * address. 137 * @param pCpuCtx The CPU context for the exception. 138 * @param pDispCtx Dispatcher context. 139 */ 44 140 extern "C" __declspec(guard(suppress)) 45 DWORD _except_handler4(PEXCEPTION_RECORD pXcptRec, PEXCEPTION_REGISTRATION_RECORD pXcptRegRec, PCONTEXT pCtxRec, PVOID pvCtx) 46 { 47 RT_NOREF(pXcptRec, pXcptRegRec, pCtxRec, pvCtx); 48 /** @todo */ 49 __debugbreak(); 50 return 0; 51 } 52 141 DWORD _except_handler4(PEXCEPTION_RECORD pXcptRec, PEXCEPTION_REGISTRATION_RECORD pXcptRegRec, PCONTEXT pCpuCtx, PVOID pvCtx) 142 { 143 /* 144 * The registration record (probably chained on FS:[0] like in the OS/2 days) 145 * points to a larger structure specific to _except_handler4. The structure 146 * is planted right after the saved caller EBP value when establishing the 147 * stack frame, so EBP = pXcptRegRec + 1; 148 */ 149 PEH4_XCPT_REG_REC_T const pEh4XcptRegRec = RT_FROM_MEMBER(pXcptRegRec, EH4_XCPT_REG_REC_T, XcptRec); 150 uint8_t * const pbFrame = (uint8_t *)&pEh4XcptRegRec[1]; 151 PCEH4_SCOPE_TAB_T const pScopeTable = (PCEH4_SCOPE_TAB_T)(pEh4XcptRegRec->uEncodedScopeTable ^ __security_cookie); 152 153 /* 154 * Validate the stack cookie and exception context. 155 */ 156 rtVccEh4ValidateCookies(pScopeTable, pbFrame); 157 rtVccValidateExceptionContextRecord(pCpuCtx); 158 159 /* 160 * If dispatching an exception, call the exception filter functions and jump 161 * to the __except blocks if so directed. 162 */ 163 if (IS_DISPATCHING(pXcptRec->ExceptionFlags)) 164 { 165 uint32_t uTryLevel = pEh4XcptRegRec->uTryLevel; 166 //RTAssertMsg2("_except_handler4: dispatch: uTryLevel=%#x\n", uTryLevel); 167 while (uTryLevel != EH4_TOPMOST_TRY_LEVEL) 168 { 169 PCEH4_SCOPE_TAB_REC_T const pEntry = &pScopeTable->aScopeRecords[uTryLevel]; 170 PFN_EH4_XCPT_FILTER_T const pfnFilter = pEntry->pfnFilter; 171 if (pfnFilter) 172 { 173 /* Call the __except filtering expression: */ 174 //RTAssertMsg2("_except_handler4: Calling pfnFilter=%p\n", pfnFilter); 175 EXCEPTION_POINTERS XcptPtrs = { pXcptRec, pCpuCtx }; 176 pEh4XcptRegRec->pXctpPtrs = &XcptPtrs; 177 LONG lRet = rtVccEh4DoFiltering(pfnFilter, pbFrame); 178 pEh4XcptRegRec->pXctpPtrs = NULL; 179 //RTAssertMsg2("_except_handler4: pfnFilter=%p -> %ld\n", pfnFilter, lRet); 180 rtVccEh4ValidateCookies(pScopeTable, pbFrame); 181 182 /* Return if we're supposed to continue execution (the convention 183 it to match negative values rather than the exact defined value): */ 184 AssertCompile(EXCEPTION_CONTINUE_EXECUTION == -1); 185 if (lRet <= EXCEPTION_CONTINUE_EXECUTION) 186 return ExceptionContinueExecution; 187 188 /* Similarly, the handler is executed for any positive value. */ 189 AssertCompile(EXCEPTION_CONTINUE_SEARCH == 0); 190 AssertCompile(EXCEPTION_EXECUTE_HANDLER == 1); 191 if (lRet >= EXCEPTION_EXECUTE_HANDLER) 192 { 193 /* We're about to resume execution in the __except block, so unwind 194 up to it first. */ 195 //RTAssertMsg2("_except_handler4: global unwind\n"); 196 rtVccEh4DoGlobalUnwind(pXcptRec, &pEh4XcptRegRec->XcptRec); 197 if (pEh4XcptRegRec->uTryLevel != EH4_TOPMOST_TRY_LEVEL) 198 { 199 //RTAssertMsg2("_except_handler4: local unwind\n"); 200 rtVccEh4DoLocalUnwind(&pEh4XcptRegRec->XcptRec, uTryLevel, pbFrame, &__security_cookie); 201 } 202 rtVccEh4ValidateCookies(pScopeTable, pbFrame); 203 204 /* Now jump to the __except block. This will _not_ return. */ 205 //RTAssertMsg2("_except_handler4: jumping to __except block %p (level %#x)\n", pEntry->pfnHandler, pEntry->uEnclosingLevel); 206 pEh4XcptRegRec->uTryLevel = pEntry->uEnclosingLevel; 207 rtVccEh4ValidateCookies(pScopeTable, pbFrame); /* paranoia^2 */ 208 209 rtVccEh4JumpToHandler(pEntry->pfnHandler, pbFrame); 210 /* (not reached) */ 211 } 212 } 213 214 /* 215 * Next try level. 216 */ 217 uTryLevel = pEntry->uEnclosingLevel; 218 } 219 } 220 /* 221 * If not dispatching we're unwinding, so we call any __finally blocks. 222 */ 223 else 224 { 225 //RTAssertMsg2("_except_handler4: unwind: uTryLevel=%#x\n", pEh4XcptRegRec->uTryLevel); 226 if (pEh4XcptRegRec->uTryLevel != EH4_TOPMOST_TRY_LEVEL) 227 { 228 rtVccEh4DoLocalUnwind(&pEh4XcptRegRec->XcptRec, EH4_TOPMOST_TRY_LEVEL, pbFrame, &__security_cookie); 229 rtVccEh4ValidateCookies(pScopeTable, pbFrame); 230 } 231 } 232 233 RT_NOREF(pvCtx); 234 return ExceptionContinueSearch; 235 } 236
Note:
See TracChangeset
for help on using the changeset viewer.