Merge pull request #2319 from RadWolfie/init-exception-manager-early

Move Crash Manager's Init at Beginning of Emulation & Fix Hidden Crash
This commit is contained in:
Luke Usher 2022-02-06 10:56:44 +00:00 committed by GitHub
commit 86022747f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 122 additions and 10 deletions

View File

@ -1017,6 +1017,10 @@ static bool CxbxrKrnlPrepareXbeMap()
void CxbxKrnlEmulate(unsigned int reserved_systems, blocks_reserved_t blocks_reserved)
{
// This is beginning of emulation process start, therefore require to have exception manager initialized
// and capture any crash from this point and beyond. Useful for capture live crash and generate crash report.
g_ExceptionManager = new ExceptionManager();
// First of all, check if the EmuShared version matches the emu version and abort otherwise
char GitVersionEmuShared[GitVersionMaxLength];
g_EmuShared->GetGitVersion(GitVersionEmuShared);
@ -1175,8 +1179,6 @@ void CxbxKrnlEmulate(unsigned int reserved_systems, blocks_reserved_t blocks_res
CxbxrKrnlXbePatchXBEHSig();
g_ExceptionManager = new ExceptionManager(); // If in need to add VEHs, move this line earlier. (just in case)
// Launch the XBE :
{
// Load TLS

View File

@ -389,6 +389,12 @@ ExceptionManager *g_ExceptionManager = nullptr;
ExceptionManager::ExceptionManager()
{
accept_request = true;
// Last call plus show exception error than terminate early.
#ifdef _MSC_VER // Windows' C++ exception is using SEH, we cannot use VEH for error reporter system.
(void)SetUnhandledExceptionFilter(EmuException);
#else // Untested for other platforms, may will behave as expected.
AddVEH(0, EmuException, true);
#endif
}
ExceptionManager::~ExceptionManager()
@ -407,12 +413,6 @@ void ExceptionManager::EmuX86_Init()
{
accept_request = false; // Do not allow add VEH during emulation.
AddVEH(1, lleException, true); // Front line call
// Last call plus show exception error than terminate early.
#ifdef _MSC_VER // Windows' C++ exception is using SEH, we cannot use VEH for error reporter system.
(void)SetUnhandledExceptionFilter(EmuException);
#else // Untested for other platforms, may will behave as expected.
AddVEH(0, EmuException, true);
#endif
}
bool ExceptionManager::AddVEH(unsigned long first, PVECTORED_EXCEPTION_HANDLER veh_handler)

View File

@ -264,6 +264,17 @@ __declspec(naked) void EmuFS_MovEaxFs00()
}
}
__declspec(naked) void EmuFS_MovEaxFs04()
{
__asm
{
call EmuFS_RefreshKPCR
mov eax, fs : [TIB_ArbitraryDataSlot]
mov eax, [eax + 04h]
ret
}
}
__declspec(naked) void EmuFS_MovEaxFs20()
{
__asm
@ -308,6 +319,17 @@ __declspec(naked) void EmuFS_MovEbxFs00()
}
}
__declspec(naked) void EmuFS_MovEbxFs04()
{
__asm
{
call EmuFS_RefreshKPCR
mov ebx, fs : [TIB_ArbitraryDataSlot]
mov ebx, [ebx + 04h]
ret
}
}
__declspec(naked) void EmuFS_MovEcxFs00()
{
__asm
@ -352,6 +374,28 @@ __declspec(naked) void EmuFS_MovEdiFs04()
}
}
__declspec(naked) void EmuFS_MovEdxFs00()
{
__asm
{
call EmuFS_RefreshKPCR
mov edx, fs : [TIB_ArbitraryDataSlot]
mov edx, [edx]
ret
}
}
__declspec(naked) void EmuFS_MovEdxFs04()
{
__asm
{
call EmuFS_RefreshKPCR
mov edx, fs : [TIB_ArbitraryDataSlot]
mov edx, [edx + 04h]
ret
}
}
__declspec(naked) void EmuFS_MovEsiFs00()
{
__asm
@ -363,6 +407,17 @@ __declspec(naked) void EmuFS_MovEsiFs00()
}
}
__declspec(naked) void EmuFS_MovEsiFs04()
{
__asm
{
call EmuFS_RefreshKPCR
mov esi, fs : [TIB_ArbitraryDataSlot]
mov esi, [esi + 04h]
ret
}
}
__declspec(naked) void EmuFS_MovzxEaxBytePtrFs24()
{
// Note : Inlined KeGetCurrentIrql()
@ -417,6 +472,48 @@ __declspec(naked) void EmuFS_MovFs00Ecx()
}
}
__declspec(naked) void EmuFS_MovFs00Edi()
{
// Note : eax must be preserved here, hence the push/pop
__asm
{
call EmuFS_RefreshKPCR
push eax
mov eax, fs : [TIB_ArbitraryDataSlot]
mov [eax], edi
pop eax
ret
}
}
__declspec(naked) void EmuFS_MovFs00Edx()
{
// Note : eax must be preserved here, hence the push/pop
__asm
{
call EmuFS_RefreshKPCR
push eax
mov eax, fs : [TIB_ArbitraryDataSlot]
mov [eax], edx
pop eax
ret
}
}
__declspec(naked) void EmuFS_MovFs00Esi()
{
// Note : eax must be preserved here, hence the push/pop
__asm
{
call EmuFS_RefreshKPCR
push eax
mov eax, fs : [TIB_ArbitraryDataSlot]
mov [eax], esi
pop eax
ret
}
}
__declspec(naked) void EmuFS_MovFs00Esp()
{
// Note : eax must be preserved here, hence the push/pop
@ -485,17 +582,25 @@ void EmuInitFS()
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x0F, 0xB6, 0x05, 0x24, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovzxEaxBytePtrFs24 });// movzx eax, large byte ptr fs:24
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x3B, 0x35, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_CmpEsiFs00 }); // cmp esi, large fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x1D, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEbxFs00 }); // mov ebx, large fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x1D, 0x04, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEbxFs04 }); // mov ebx, large fs:4
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEcxFs00 }); // mov ecx, large fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x0D, 0x04, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEcxFs04 }); // mov ecx, large fs:4
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x3D, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEdiFs00 }); // mov edi, large fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x3D, 0x04, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEdiFs04 }); // mov edi, large fs:4
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x15, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEdxFs00 }); // mov edx, large fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x15, 0x04, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEdxFs04 }); // mov edx, large fs:4
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x35, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEsiFs00 }); // mov esi, large fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8B, 0x35, 0x04, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEsiFs04 }); // mov esi, large fs:4
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x89, 0x1D, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovFs00Ebx }); // mov large fs:0, ebx
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovFs00Ecx }); // mov large fs:0, ecx
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x89, 0x3D, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovFs00Edi }); // mov large fs:0, edi
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x89, 0x15, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovFs00Edx }); // mov large fs:0, edx
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x89, 0x35, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovFs00Esi }); // mov large fs:0, esi
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x89, 0x25, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovFs00Esp }); // mov large fs:0, esp
fsInstructions.push_back(fs_instruction_t { { 0x64, 0x8F, 0x05, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_PopDwordPtrFs00 }); // pop large dword ptr fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0xFF, 0x35, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_PushDwordPtrFs00 }); // push large dword ptr fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEaxFs00 }); // mov eax, large fs:0
fsInstructions.push_back(fs_instruction_t { { 0x64, 0xA1, 0x04, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEaxFs04 }); // mov eax, large fs:4
fsInstructions.push_back(fs_instruction_t { { 0x64, 0xA1, 0x20, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEaxFs20 }); // mov eax, large fs:20
fsInstructions.push_back(fs_instruction_t { { 0x64, 0xA1, 0x28, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEaxFs28 }); // mov eax, large fs:28
fsInstructions.push_back(fs_instruction_t { { 0x64, 0xA1, 0x58, 0x00, 0x00, 0x00 }, (void*)&EmuFS_MovEaxFs58 }); // mov eax, large fs:58
@ -650,8 +755,13 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
// Write the Xbox stack base to the Host, allows ConvertThreadToFiber to work correctly
// Test case: DOA3
__writefsdword(TIB_StackBase, (DWORD)NewPcr->NtTib.StackBase);
__writefsdword(TIB_StackLimit, (DWORD)NewPcr->NtTib.StackLimit);
// NOTE: This is disabled due to cause of corruption to host's TIB and
// silent crash for xbox threads creation.
// Test case:
// * Direct3DCreate9Ex call from inside xbox thread
// * PCSTProxy (used from PsCreateSystemThreadEx export function)
//__writefsdword(TIB_StackBase, (DWORD)NewPcr->NtTib.StackBase);
//__writefsdword(TIB_StackLimit, (DWORD)NewPcr->NtTib.StackLimit);
}
// Set flat address of this PCR