From f4dec5d25e8d0b10b18fa1e488b68444661d5843 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 2 Jan 2026 17:45:26 -0800 Subject: [PATCH 1/2] unittests/FEXLinuxTests: Force clang building for tests Necessary to get #5187 passing. --- unittests/FEXLinuxTests/CMakeLists.txt | 2 ++ unittests/FEXLinuxTests/tests/CMakeLists.txt | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/unittests/FEXLinuxTests/CMakeLists.txt b/unittests/FEXLinuxTests/CMakeLists.txt index e3e344e02..7583ffdfe 100644 --- a/unittests/FEXLinuxTests/CMakeLists.txt +++ b/unittests/FEXLinuxTests/CMakeLists.txt @@ -6,6 +6,7 @@ ExternalProject_Add(FEXLinuxTests CMAKE_ARGS "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${X86_64_TOOLCHAIN_FILE}" + "-DENABLE_CLANG_THUNKS=True" "-DBITNESS=64" INSTALL_COMMAND "" BUILD_ALWAYS ON) @@ -17,6 +18,7 @@ ExternalProject_Add(FEXLinuxTests_32 CMAKE_ARGS "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${X86_32_TOOLCHAIN_FILE}" + "-DENABLE_CLANG_THUNKS=True" "-DBITNESS=32" INSTALL_COMMAND "" BUILD_ALWAYS ON) diff --git a/unittests/FEXLinuxTests/tests/CMakeLists.txt b/unittests/FEXLinuxTests/tests/CMakeLists.txt index f4bbee02c..fb390226b 100644 --- a/unittests/FEXLinuxTests/tests/CMakeLists.txt +++ b/unittests/FEXLinuxTests/tests/CMakeLists.txt @@ -3,9 +3,6 @@ project(FEXLinuxTests) set(CMAKE_CXX_STANDARD 20) -unset(CMAKE_C_FLAGS) -unset(CMAKE_CXX_FLAGS) - set(GENERATE_GUEST_INSTALL_TARGETS TRUE) # Use intel masm syntax. ATT style asm syntax is archaic and hard to read. From 7dba1a355234d2ead7aecdc3e2700badb0a70664 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 2 Jan 2026 18:31:20 -0800 Subject: [PATCH 2/2] unittests/FEXLinuxTests: Fix for building with clang --- .../FEXLinuxTests/tests/cpu/cpu_count.cpp | 3 +- .../tests/signal/Syscall_state.32.cpp | 27 +++++----- .../tests/signal/Syscall_state.64.cpp | 49 +++++++++---------- .../tests/signal/SystemInstructions.64.cpp | 4 +- .../tests/signal/x87_state.64.cpp | 41 +++++++++------- 5 files changed, 63 insertions(+), 61 deletions(-) diff --git a/unittests/FEXLinuxTests/tests/cpu/cpu_count.cpp b/unittests/FEXLinuxTests/tests/cpu/cpu_count.cpp index 89f219d0f..84038d6b3 100644 --- a/unittests/FEXLinuxTests/tests/cpu/cpu_count.cpp +++ b/unittests/FEXLinuxTests/tests/cpu/cpu_count.cpp @@ -25,7 +25,8 @@ struct cpuid_fn { cpuid_fn get_cpuid(uint32_t func, uint32_t leaf = 0) { cpuid_fn fn {}; - __cpuid_count(func, leaf, fn.eax, fn.ebx, fn.ecx, fn.edx); + __asm volatile("cpuid" : "=a"(fn.eax), "=b"(fn.ebx), "=c"(fn.ecx), "=d"(fn.edx) : "a"(func), "c"(leaf)); + return fn; } diff --git a/unittests/FEXLinuxTests/tests/signal/Syscall_state.32.cpp b/unittests/FEXLinuxTests/tests/signal/Syscall_state.32.cpp index 7a84c5290..60f6c7f93 100644 --- a/unittests/FEXLinuxTests/tests/signal/Syscall_state.32.cpp +++ b/unittests/FEXLinuxTests/tests/signal/Syscall_state.32.cpp @@ -29,21 +29,21 @@ __attribute__((naked)) void DoZeroRegSyscallFault(CPUState State) { __asm volatile( R"( // Load flags - push dword [esp + %[FlagsOffset]] + push dword ptr [esp + %[FlagsOffset]] popfd // Do getpid syscall. // Overwrites some arguments. // Syscall num - mov eax, qword [esp + %[RAXOffset]] + mov eax, dword ptr [esp + %[RAXOffset]] // Load remaining registers that we can - mov ebx, qword [esp + %[RBXOffset]]; - mov ecx, qword [esp + %[RCXOffset]]; - mov edx, qword [esp + %[RDXOffset]] - mov esi, qword [esp + %[RSIOffset]] - mov edi, qword [esp + %[RDIOffset]]; - mov ebp, qword [esp + %[RBPOffset]]; + mov ebx, dword ptr [esp + %[RBXOffset]]; + mov ecx, dword ptr [esp + %[RCXOffset]]; + mov edx, dword ptr [esp + %[RDXOffset]] + mov esi, dword ptr [esp + %[RSIOffset]] + mov edi, dword ptr [esp + %[RDIOffset]]; + mov ebp, dword ptr [esp + %[RBPOffset]]; // Can't load RSP int 0x80; @@ -54,12 +54,11 @@ __attribute__((naked)) void DoZeroRegSyscallFault(CPUState State) { // We long jump from the signal handler, so this won't continue. )" : - // integers are offset by 8 for some reason. - // But the stack is also offset by 4-bytes due to the call. - : [RAXOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EAX]) - 4), [RDXOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EDX]) - 4), - [RSIOffset] "i"(offsetof(CPUState, Registers[TEST_REG_ESI]) - 4), [RDIOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EDI]) - 4), - [RBXOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EBX]) - 4), [RCXOffset] "i"(offsetof(CPUState, Registers[TEST_REG_ECX]) - 4), - [RBPOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EBP]) - 4), [FlagsOffset] "i"(offsetof(CPUState, eflags) - 4) + // The stack is offset by 4-bytes due to the call. + : [RAXOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EAX]) + 4), [RDXOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EDX]) + 4), + [RSIOffset] "i"(offsetof(CPUState, Registers[TEST_REG_ESI]) + 4), [RDIOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EDI]) + 4), + [RBXOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EBX]) + 4), [RCXOffset] "i"(offsetof(CPUState, Registers[TEST_REG_ECX]) + 4), + [RBPOffset] "i"(offsetof(CPUState, Registers[TEST_REG_EBP]) + 4), [FlagsOffset] "i"(offsetof(CPUState, eflags) + 4) : "memory"); } diff --git a/unittests/FEXLinuxTests/tests/signal/Syscall_state.64.cpp b/unittests/FEXLinuxTests/tests/signal/Syscall_state.64.cpp index 1d152e099..898318315 100644 --- a/unittests/FEXLinuxTests/tests/signal/Syscall_state.64.cpp +++ b/unittests/FEXLinuxTests/tests/signal/Syscall_state.64.cpp @@ -30,32 +30,32 @@ __attribute__((naked)) void DoZeroRegSyscallFault(CPUState* State) { push r15 // Load flags - push qword [rdi + %[FlagsOffset]] + push qword ptr [rdi + %[FlagsOffset]] popfq // Do getpid syscall. // Overwrites some arguments. // Syscall num - mov rax, qword [rdi + %[RAXOffset]] + mov rax, qword ptr [rdi + %[RAXOffset]] // Load remaining registers that we can - mov rbx, qword [rdi + %[RBXOffset]]; - mov rcx, qword [rdi + %[RCXOffset]]; - mov rdx, qword [rdi + %[RDXOffset]] - mov rsi, qword [rdi + %[RSIOffset]] - mov rbp, qword [rdi + %[RBPOffset]]; + mov rbx, qword ptr [rdi + %[RBXOffset]]; + mov rcx, qword ptr [rdi + %[RCXOffset]]; + mov rdx, qword ptr [rdi + %[RDXOffset]] + mov rsi, qword ptr [rdi + %[RSIOffset]] + mov rbp, qword ptr [rdi + %[RBPOffset]]; // Can't load RSP - mov r8, qword [rdi + %[R8Offset]] - mov r9, qword [rdi + %[R9Offset]]; - mov r10, qword [rdi + %[R10Offset]] - mov r11, qword [rdi + %[R11Offset]]; - mov r12, qword [rdi + %[R12Offset]]; - mov r13, qword [rdi + %[R13Offset]]; - mov r14, qword [rdi + %[R14Offset]]; - mov r15, qword [rdi + %[R15Offset]]; + mov r8, qword ptr [rdi + %[R8Offset]] + mov r9, qword ptr [rdi + %[R9Offset]]; + mov r10, qword ptr [rdi + %[R10Offset]] + mov r11, qword ptr [rdi + %[R11Offset]]; + mov r12, qword ptr [rdi + %[R12Offset]]; + mov r13, qword ptr [rdi + %[R13Offset]]; + mov r14, qword ptr [rdi + %[R14Offset]]; + mov r15, qword ptr [rdi + %[R15Offset]]; // Overwrite RDI last. - mov rdi, qword [rdi + %[RDIOffset]]; + mov rdi, qword ptr [rdi + %[RDIOffset]]; syscall; @@ -66,15 +66,14 @@ __attribute__((naked)) void DoZeroRegSyscallFault(CPUState* State) { // We long jump from the signal handler, so this won't continue. )" : - // integers are offset by 8 for some reason. - : [RAXOffset] "i"(offsetof(CPUState, Registers[REG_RAX]) - 8), [RDXOffset] "i"(offsetof(CPUState, Registers[REG_RDX]) - 8), - [R10Offset] "i"(offsetof(CPUState, Registers[REG_R10]) - 8), [R8Offset] "i"(offsetof(CPUState, Registers[REG_R8]) - 8), - [RSIOffset] "i"(offsetof(CPUState, Registers[REG_RSI]) - 8), [RDIOffset] "i"(offsetof(CPUState, Registers[REG_RDI]) - 8), - [RBXOffset] "i"(offsetof(CPUState, Registers[REG_RBX]) - 8), [RCXOffset] "i"(offsetof(CPUState, Registers[REG_RCX]) - 8), - [RBPOffset] "i"(offsetof(CPUState, Registers[REG_RBP]) - 8), [R9Offset] "i"(offsetof(CPUState, Registers[REG_R9]) - 8), - [R11Offset] "i"(offsetof(CPUState, Registers[REG_R11]) - 8), [R12Offset] "i"(offsetof(CPUState, Registers[REG_R12]) - 8), - [R13Offset] "i"(offsetof(CPUState, Registers[REG_R13]) - 8), [R14Offset] "i"(offsetof(CPUState, Registers[REG_R14]) - 8), - [R15Offset] "i"(offsetof(CPUState, Registers[REG_R15]) - 8), [FlagsOffset] "i"(offsetof(CPUState, eflags) - 8) + : [RAXOffset] "i"(offsetof(CPUState, Registers[REG_RAX])), [RDXOffset] "i"(offsetof(CPUState, Registers[REG_RDX])), + [R10Offset] "i"(offsetof(CPUState, Registers[REG_R10])), [R8Offset] "i"(offsetof(CPUState, Registers[REG_R8])), + [RSIOffset] "i"(offsetof(CPUState, Registers[REG_RSI])), [RDIOffset] "i"(offsetof(CPUState, Registers[REG_RDI])), + [RBXOffset] "i"(offsetof(CPUState, Registers[REG_RBX])), [RCXOffset] "i"(offsetof(CPUState, Registers[REG_RCX])), + [RBPOffset] "i"(offsetof(CPUState, Registers[REG_RBP])), [R9Offset] "i"(offsetof(CPUState, Registers[REG_R9])), + [R11Offset] "i"(offsetof(CPUState, Registers[REG_R11])), [R12Offset] "i"(offsetof(CPUState, Registers[REG_R12])), + [R13Offset] "i"(offsetof(CPUState, Registers[REG_R13])), [R14Offset] "i"(offsetof(CPUState, Registers[REG_R14])), + [R15Offset] "i"(offsetof(CPUState, Registers[REG_R15])), [FlagsOffset] "i"(offsetof(CPUState, eflags)) : "memory"); } diff --git a/unittests/FEXLinuxTests/tests/signal/SystemInstructions.64.cpp b/unittests/FEXLinuxTests/tests/signal/SystemInstructions.64.cpp index 1eb51945b..5ff9ac3f8 100644 --- a/unittests/FEXLinuxTests/tests/signal/SystemInstructions.64.cpp +++ b/unittests/FEXLinuxTests/tests/signal/SystemInstructions.64.cpp @@ -73,14 +73,14 @@ TEST(13, "mov dr0, rax", "mov dr0, rax", X86_TRAPNO_GP, 0, 0x80, SIGSEGV); TEST(14, "rdpmc", "rdpmc", X86_TRAPNO_GP, 0, 0x80, SIGSEGV); TEST(15, "sti", "sti", X86_TRAPNO_GP, 0, 0x80, SIGSEGV); TEST(16, "swapgs", "swapgs", X86_TRAPNO_GP, 0, 0x80, SIGSEGV); -TEST(17, "sysret", "sysretd", X86_TRAPNO_GP, 0, 0x80, SIGSEGV); +TEST(17, "sysret", "sysret", X86_TRAPNO_GP, 0, 0x80, SIGSEGV); TEST(18, "wrmsr", "wrmsr", X86_TRAPNO_GP, 0, 0x80, SIGSEGV); // Instructions not implemented TEST(19, "monitor", "monitor", X86_TRAPNO_UD, 0, 2, SIGILL); TEST(20, "mwait", "mwait", X86_TRAPNO_UD, 0, 2, SIGILL); TEST(21, "sysenter", "sysenter", X86_TRAPNO_UD, 0, 2, SIGILL); -TEST(22, "sysexit", "sysexitd", X86_TRAPNO_UD, 0, 2, SIGILL); +TEST(22, "sysexit", "sysexit", X86_TRAPNO_UD, 0, 2, SIGILL); // Differs between dr8 and dr0-7 variants. // dr0-7: SIGSEGV diff --git a/unittests/FEXLinuxTests/tests/signal/x87_state.64.cpp b/unittests/FEXLinuxTests/tests/signal/x87_state.64.cpp index 719a2b0dc..62b5d2d95 100644 --- a/unittests/FEXLinuxTests/tests/signal/x87_state.64.cpp +++ b/unittests/FEXLinuxTests/tests/signal/x87_state.64.cpp @@ -42,13 +42,13 @@ __attribute__((naked, nocf_check)) static void TestFromSignal(const DataStruct* ffreep st(0); // Now load **7** values. Keeping the last one zero and our stack top not wrapped around. - fldt [rdi + (0 * 16)]; - fldt [rdi + (1 * 16)]; - fldt [rdi + (2 * 16)]; - fldt [rdi + (3 * 16)]; - fldt [rdi + (4 * 16)]; - fldt [rdi + (5 * 16)]; - fldt [rdi + (6 * 16)]; + fld tbyte ptr [rdi + (0 * 16)]; + fld tbyte ptr [rdi + (1 * 16)]; + fld tbyte ptr [rdi + (2 * 16)]; + fld tbyte ptr [rdi + (3 * 16)]; + fld tbyte ptr [rdi + (4 * 16)]; + fld tbyte ptr [rdi + (5 * 16)]; + fld tbyte ptr [rdi + (6 * 16)]; hlt; RetInstruction: @@ -86,24 +86,27 @@ __attribute__((naked, nocf_check)) static void TestSetInSignal(DataStruct* data) // Store values until the status word says nothing is left. mov eax, 0; - .1: + +2: + fstsw ax; and eax, (7 << 11); - jz .2; - fstpt [rdi]; + jz 3f; + fstp tbyte ptr [rdi]; add rdi, 16; - jmp .1; - .2: + jmp 2b + +3: // Now load **7** values. Keeping the last one zero and our stack top not wrapped around. - fldt [rdi + (0 * 16)]; - fldt [rdi + (1 * 16)]; - fldt [rdi + (2 * 16)]; - fldt [rdi + (3 * 16)]; - fldt [rdi + (4 * 16)]; - fldt [rdi + (5 * 16)]; - fldt [rdi + (6 * 16)]; + fld tbyte ptr [rdi + (0 * 16)]; + fld tbyte ptr [rdi + (1 * 16)]; + fld tbyte ptr [rdi + (2 * 16)]; + fld tbyte ptr [rdi + (3 * 16)]; + fld tbyte ptr [rdi + (4 * 16)]; + fld tbyte ptr [rdi + (5 * 16)]; + fld tbyte ptr [rdi + (6 * 16)]; ret; )" ::