Skip to content

On x64, Clang/LLVM doesn't generate the correct scope table for exceptions thrown in the same frame #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
cl91 opened this issue Jun 24, 2022 · 2 comments

Comments

@cl91
Copy link
Owner

cl91 commented Jun 24, 2022

On x64, clang/llvm (version 13.0.1) doesn't seem to generate the correct scope table for the following example

VOID Test() {
    __try {
        asm { "ud2" }
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        DbgPrint("Caught exception");
    }
}

The scope table for the unwind data of Test() is empty (it should have one entry corresponding to the __try block). However the following is OK:

VOID ExceptionalFunction() {
    asm { "ud2" }
}

VOID Test() {
    __try {
        ExceptionalFunction();
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        DbgPrint("Caught exception");
    }
}

Clang correctly generates the scope table for Test() (it has one entry which points to the __try block with the exception filter EXCEPTION_EXECUTE_HANDLER).

Clang/LLVM documentation claims that LLVM does not model asynchronous exceptions so it is currently impossible to catch an asynchronous exception generated in the same frame as the catching __try (x86 uses frame-based SEH instead of table based exception handling so it is OK). Our code is correct (after fixing a bug in the ReactOS code RtlpUnwindInternal --- the leaf function case didn't update the context record correctly) and can correct catch and unwind the second example above.

@cl91
Copy link
Owner Author

cl91 commented Jan 20, 2025

This appears to happen on i386 release build as well.

** 891 		__try {

ntdll.dll`LdrpInitialize:
ntdll.dll[0x10012cc8] <+3272>: movl   $0x0, -0x10(%ebp)

** 892 		    asm { "ud2" }
   893 		    /* PCHAR p = (PCHAR)0x233; */
   894 		    /* *p = 0xd; */

ntdll.dll[0x10012ccf] <+3279>: nop    
ntdll.dll[0x10012cd0] <+3280>: movl   $0xffffffff, -0x10(%ebp) ; imm = 0xFFFFFFFF 
ntdll.dll[0x10012cd7] <+3287>: ud2    

** 895 		} __except(EXCEPTION_EXECUTE_HANDLER) {
   896 		    NtDisplayStringA("EEEEEEEEEEEEEEE\n");
   897 		}

ntdll.dll[0x10012cd9] <+3289>: movl   $0x0, -0x10(%ebp)

   898 	
** 899 		if (InitInfo.DriverProcess) {
   900 		    PLDR_DATA_TABLE_ENTRY WdmDllEntry = NULL;
   901 		    LdrpCheckForLoadedDll("wdm.dll", &WdmDllEntry);

ntdll.dll[0x10012ce0] <+3296>: nop    
ntdll.dll[0x10012ce1] <+3297>: cmpb   $0x0, -0x574(%ebp)

For some reason clang sets the try-scope to -1 before the ud instruction.

@cl91
Copy link
Owner Author

cl91 commented Jan 20, 2025

Appears to be a clang bug: llvm/llvm-project#62606

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant