15075f7d7STimo Kreuzer /* 25075f7d7STimo Kreuzer * PROJECT: ReactOS Run-Time Library 35075f7d7STimo Kreuzer * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 45075f7d7STimo Kreuzer * PURPOSE: User-mode exception support for AMD64 55075f7d7STimo Kreuzer * COPYRIGHT: Copyright 2018-2021 Timo Kreuzer <timo.kreuzer@reactos.org> 65075f7d7STimo Kreuzer */ 75075f7d7STimo Kreuzer 85075f7d7STimo Kreuzer /* INCLUDES *****************************************************************/ 95075f7d7STimo Kreuzer 105075f7d7STimo Kreuzer #include <rtl.h> 115075f7d7STimo Kreuzer #define NDEBUG 125075f7d7STimo Kreuzer #include <debug.h> 135075f7d7STimo Kreuzer 145075f7d7STimo Kreuzer /* PUBLIC FUNCTIONS **********************************************************/ 155075f7d7STimo Kreuzer 165075f7d7STimo Kreuzer VOID 175075f7d7STimo Kreuzer NTAPI 185075f7d7STimo Kreuzer RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord) 195075f7d7STimo Kreuzer { 205075f7d7STimo Kreuzer CONTEXT Context; 215075f7d7STimo Kreuzer NTSTATUS Status = STATUS_INVALID_DISPOSITION; 225075f7d7STimo Kreuzer 23e6af7d9dSTimo Kreuzer /* Capture the current context */ 245075f7d7STimo Kreuzer RtlCaptureContext(&Context); 255075f7d7STimo Kreuzer 26e6af7d9dSTimo Kreuzer /* Fix up Context.Rip for the caller */ 27e6af7d9dSTimo Kreuzer Context.Rip = (ULONG64)_ReturnAddress(); 285075f7d7STimo Kreuzer 29e6af7d9dSTimo Kreuzer /* Fix up Context.Rsp for the caller */ 30e6af7d9dSTimo Kreuzer Context.Rsp = (ULONG64)_AddressOfReturnAddress() + 8; 315075f7d7STimo Kreuzer 325075f7d7STimo Kreuzer /* Save the exception address */ 335075f7d7STimo Kreuzer ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip; 345075f7d7STimo Kreuzer 355075f7d7STimo Kreuzer /* Check if user mode debugger is active */ 365075f7d7STimo Kreuzer if (RtlpCheckForActiveDebugger()) 375075f7d7STimo Kreuzer { 385075f7d7STimo Kreuzer /* Raise an exception immediately */ 395075f7d7STimo Kreuzer Status = ZwRaiseException(ExceptionRecord, &Context, TRUE); 405075f7d7STimo Kreuzer } 415075f7d7STimo Kreuzer else 425075f7d7STimo Kreuzer { 435075f7d7STimo Kreuzer /* Dispatch the exception and check if we should continue */ 445075f7d7STimo Kreuzer if (!RtlDispatchException(ExceptionRecord, &Context)) 455075f7d7STimo Kreuzer { 465075f7d7STimo Kreuzer /* Raise the exception */ 475075f7d7STimo Kreuzer Status = ZwRaiseException(ExceptionRecord, &Context, FALSE); 485075f7d7STimo Kreuzer } 495075f7d7STimo Kreuzer else 505075f7d7STimo Kreuzer { 515075f7d7STimo Kreuzer /* Continue, go back to previous context */ 525075f7d7STimo Kreuzer Status = ZwContinue(&Context, FALSE); 535075f7d7STimo Kreuzer } 545075f7d7STimo Kreuzer } 555075f7d7STimo Kreuzer 565075f7d7STimo Kreuzer /* If we returned, raise a status */ 575075f7d7STimo Kreuzer RtlRaiseStatus(Status); 585075f7d7STimo Kreuzer } 595075f7d7STimo Kreuzer 605075f7d7STimo Kreuzer /* 615075f7d7STimo Kreuzer * @unimplemented 625075f7d7STimo Kreuzer */ 635075f7d7STimo Kreuzer PVOID 645075f7d7STimo Kreuzer NTAPI 655075f7d7STimo Kreuzer RtlpGetExceptionAddress(VOID) 665075f7d7STimo Kreuzer { 675075f7d7STimo Kreuzer UNIMPLEMENTED; 685075f7d7STimo Kreuzer return NULL; 695075f7d7STimo Kreuzer } 705075f7d7STimo Kreuzer 713ec1ca9bSTimo Kreuzer BOOLEAN 723ec1ca9bSTimo Kreuzer NTAPI 73*3ba1d82cSKento Oki RtlpUnwindInternal( 743ec1ca9bSTimo Kreuzer _In_opt_ PVOID TargetFrame, 753ec1ca9bSTimo Kreuzer _In_opt_ PVOID TargetIp, 763ec1ca9bSTimo Kreuzer _In_ PEXCEPTION_RECORD ExceptionRecord, 773ec1ca9bSTimo Kreuzer _In_ PVOID ReturnValue, 783ec1ca9bSTimo Kreuzer _In_ PCONTEXT ContextRecord, 793ec1ca9bSTimo Kreuzer _In_opt_ struct _UNWIND_HISTORY_TABLE *HistoryTable, 803ec1ca9bSTimo Kreuzer _In_ ULONG Flags); 813ec1ca9bSTimo Kreuzer 825075f7d7STimo Kreuzer /* 835075f7d7STimo Kreuzer * @unimplemented 845075f7d7STimo Kreuzer */ 855075f7d7STimo Kreuzer BOOLEAN 865075f7d7STimo Kreuzer NTAPI 873ec1ca9bSTimo Kreuzer RtlDispatchException( 883ec1ca9bSTimo Kreuzer _In_ PEXCEPTION_RECORD ExceptionRecord, 893ec1ca9bSTimo Kreuzer _In_ PCONTEXT ContextRecord) 905075f7d7STimo Kreuzer { 913ec1ca9bSTimo Kreuzer BOOLEAN Handled; 923ec1ca9bSTimo Kreuzer 933ec1ca9bSTimo Kreuzer /* Perform vectored exception handling for user mode */ 943ec1ca9bSTimo Kreuzer if (RtlCallVectoredExceptionHandlers(ExceptionRecord, ContextRecord)) 953ec1ca9bSTimo Kreuzer { 963ec1ca9bSTimo Kreuzer /* Exception handled, now call vectored continue handlers */ 973ec1ca9bSTimo Kreuzer RtlCallVectoredContinueHandlers(ExceptionRecord, ContextRecord); 983ec1ca9bSTimo Kreuzer 993ec1ca9bSTimo Kreuzer /* Continue execution */ 1003ec1ca9bSTimo Kreuzer return TRUE; 1013ec1ca9bSTimo Kreuzer } 1023ec1ca9bSTimo Kreuzer 1033ec1ca9bSTimo Kreuzer /* Call the internal unwind routine */ 104*3ba1d82cSKento Oki Handled = RtlpUnwindInternal(NULL, // TargetFrame 1053ec1ca9bSTimo Kreuzer NULL, // TargetIp 1063ec1ca9bSTimo Kreuzer ExceptionRecord, 1073ec1ca9bSTimo Kreuzer 0, // ReturnValue 1083ec1ca9bSTimo Kreuzer ContextRecord, 1093ec1ca9bSTimo Kreuzer NULL, // HistoryTable 1103ec1ca9bSTimo Kreuzer UNW_FLAG_EHANDLER); 1113ec1ca9bSTimo Kreuzer 1123ec1ca9bSTimo Kreuzer /* In user mode, call any registered vectored continue handlers */ 1133ec1ca9bSTimo Kreuzer RtlCallVectoredContinueHandlers(ExceptionRecord, ContextRecord); 1143ec1ca9bSTimo Kreuzer 1153ec1ca9bSTimo Kreuzer return Handled; 1165075f7d7STimo Kreuzer } 117