From 5c0a1ce5c2e785bbe0f628b90b185524b655e193 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 09:23:20 +0200 Subject: [PATCH 1/9] Build and test MinGW in CI --- .github/workflows/build.yml | 18 +++++++++++-- cmake/compiler-env.cmake | 25 +++++++------------ src/backend-selection/CMakeLists.txt | 2 +- src/backends/CMakeLists.txt | 2 +- .../icicle-bridge/CMakeLists.txt | 4 ++- src/common/CMakeLists.txt | 2 +- src/common/network/address.hpp | 1 - src/fuzzer/CMakeLists.txt | 2 +- 8 files changed, 32 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5eb98ca5..f144feca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -166,6 +166,7 @@ jobs: platform: - Windows x86 - Windows x86_64 + - MinGW x86_64 - Linux x86_64 GCC - Linux x86_64 GCC Sanitizer - Linux x86_64 Clang @@ -190,6 +191,10 @@ jobs: - platform: Windows x86_64 runner: windows-latest devcmd_arch: x64 + - platform: MinGW x86_64 + runner: ubuntu-24.04 + rust-target: x86_64-pc-windows-gnu + cmake-options: "-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchain/mingw-w64.cmake" - platform: Linux x86_64 GCC Sanitizer runner: ubuntu-24.04 cmake-options: "-DMOMO_ENABLE_SANITIZER=On" @@ -251,6 +256,12 @@ jobs: sudo update-alternatives --set cc /usr/bin/clang-${{ matrix.clang-version }} sudo update-alternatives --set c++ /usr/bin/clang++-${{ matrix.clang-version }} + - name: Set up MinGW + uses: egor-tensin/setup-mingw@v2 + if: "${{ startsWith(matrix.platform, 'MinGW') }}" + with: + platform: x64 + - name: Enable Developer Command Prompt uses: ilammy/msvc-dev-cmd@v1.13.0 if: ${{ startsWith(matrix.platform, 'Windows') }} @@ -329,6 +340,7 @@ jobs: platform: - Windows x86 - Windows x86_64 + - MinGW x86_64 - Linux x86_64 GCC - Linux x86_64 GCC Sanitizer - Linux x86_64 Clang @@ -353,6 +365,8 @@ jobs: runner: windows-latest - platform: Windows x86_64 runner: windows-latest + - platform: MinGW x86_64 + runner: windows-latest - platform: Linux x86_64 GCC runner: ubuntu-24.04 - platform: Linux x86_64 GCC Sanitizer @@ -390,7 +404,7 @@ jobs: - name: Download Windows Artifacts uses: pyTooling/download-artifact@v4 - if: "${{ matrix.platform != 'Windows x86_64' }}" + if: "${{ matrix.platform != 'Windows x86_64' && matrix.platform != 'MinGW x86_64' }}" with: name: Windows x86_64 Release Artifacts path: build/${{matrix.preset}}/artifacts @@ -405,7 +419,7 @@ jobs: run: cp build/${{matrix.preset}}/artifacts/test-sample.exe build/${{matrix.preset}}/artifacts/root/filesys/c/ - name: CMake Test - if: ${{ matrix.emulator != 'Icicle' || matrix.platform != 'Windows x86' }} + if: ${{ matrix.emulator != 'Icicle' || (matrix.platform != 'Windows x86' && matrix.platform != 'MinGW x86_64') }} run: cd build/${{matrix.preset}} && ctest --verbose -j env: EMULATOR_ROOT: ${{github.workspace}}/build/${{matrix.preset}}/artifacts/root diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index 1075875e..1918272d 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -25,21 +25,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) ########################################## -if(MINGW) - # Minimum version check for MinGW compiler - set(MINGW_C_COMPILER_MIN_VERSION "14.0.0") - set(MINGW_CXX_COMPILER_MIN_VERSION "14.0.0") - - if (${CMAKE_C_COMPILER_VERSION} VERSION_LESS_EQUAL ${MINGW_C_COMPILER_MIN_VERSION}) - message(FATAL_ERROR "${CMAKE_C_COMPILER} version should >= ${MINGW_C_COMPILER_MIN_VERSION}") - endif() - if (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS_EQUAL ${MINGW_CXX_COMPILER_MIN_VERSION}) - message(FATAL_ERROR "${CMAKE_C_COMPILER} version should >= ${MINGW_CXX_COMPILER_MIN_VERSION}") - endif() - - # MinGW LTO will cause errors in compile stage, We just disable it - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) -elseif(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten") +if(NOT MINGW AND NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten") set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) endif() @@ -53,7 +39,14 @@ endif() ########################################## -if(MOMO_ENABLE_RUST_CODE) +set(MOMO_ENABLE_RUST OFF) +if(MOMO_ENABLE_RUST_CODE AND NOT MINGW AND NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten") + set(MOMO_ENABLE_RUST ON) +endif() + +########################################## + +if(MOMO_ENABLE_RUST) add_compile_definitions(MOMO_ENABLE_RUST_CODE=1) else() add_compile_definitions(MOMO_ENABLE_RUST_CODE=0) diff --git a/src/backend-selection/CMakeLists.txt b/src/backend-selection/CMakeLists.txt index 3a2956d2..a0523c6d 100644 --- a/src/backend-selection/CMakeLists.txt +++ b/src/backend-selection/CMakeLists.txt @@ -16,7 +16,7 @@ target_link_libraries(backend-selection PRIVATE unicorn-emulator ) -if (MOMO_ENABLE_RUST_CODE) +if (MOMO_ENABLE_RUST) target_link_libraries(backend-selection PRIVATE icicle-emulator ) diff --git a/src/backends/CMakeLists.txt b/src/backends/CMakeLists.txt index 12d192df..9c590e1c 100644 --- a/src/backends/CMakeLists.txt +++ b/src/backends/CMakeLists.txt @@ -1,5 +1,5 @@ add_subdirectory(unicorn-emulator) -if (MOMO_ENABLE_RUST_CODE) +if (MOMO_ENABLE_RUST) add_subdirectory(icicle-emulator) endif() diff --git a/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt b/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt index 8399c7bc..8ce651a3 100644 --- a/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt +++ b/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt @@ -13,7 +13,9 @@ endif() set(CARGO_TRIPLE) set(CARGO_OPTIONS) -if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") +if (MINGW) + set(CARGO_TRIPLE "x86_64-pc-windows-gnu") +elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") set(CARGO_TRIPLE "wasm32-unknown-emscripten") elseif(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) set(CARGO_TRIPLE "i686-pc-windows-msvc") diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 036793eb..9423e8f1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -17,7 +17,7 @@ target_link_libraries(emulator-common PUBLIC zlibstatic ) -if(MINGW) +if(WIN) target_link_libraries(emulator-common PUBLIC ws2_32 ) diff --git a/src/common/network/address.hpp b/src/common/network/address.hpp index 6b332699..86415a76 100644 --- a/src/common/network/address.hpp +++ b/src/common/network/address.hpp @@ -34,7 +34,6 @@ #ifdef _WIN32 using socklen_t = int; -#pragma comment(lib, "ws2_32.lib") #endif namespace network diff --git a/src/fuzzer/CMakeLists.txt b/src/fuzzer/CMakeLists.txt index 6fb50eff..0eecd77c 100644 --- a/src/fuzzer/CMakeLists.txt +++ b/src/fuzzer/CMakeLists.txt @@ -19,7 +19,7 @@ target_link_libraries(fuzzer PRIVATE windows-emulator ) -if (MOMO_ENABLE_RUST_CODE) +if (MOMO_ENABLE_RUST) target_link_libraries(fuzzer PRIVATE icicle-emulator ) From c50fdd17a4942fe55133e734bc3cb6450dd24b1f Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 09:52:18 +0200 Subject: [PATCH 2/9] Fix compilation warnings --- cmake/compiler-env.cmake | 8 ++++++ src/backends/unicorn-emulator/unicorn.hpp | 2 ++ src/common/platform/compiler.hpp | 8 ++++-- src/common/platform/file_management.hpp | 6 ++-- src/common/platform/memory.hpp | 34 +++++++++++++---------- src/common/platform/platform.hpp | 4 +-- src/common/platform/process.hpp | 6 +++- src/samples/test-sample/CMakeLists.txt | 2 +- src/samples/test-sample/test.cpp | 12 ++++---- src/windows-emulator/std_include.hpp | 31 --------------------- 10 files changed, 54 insertions(+), 59 deletions(-) diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index 1918272d..c94b21b1 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -63,6 +63,14 @@ endif() ########################################## +if(MINGW) + momo_add_c_and_cxx_compile_options( + -Wno-array-bounds + ) +endif() + +########################################## + if(LINUX) add_link_options( -Wl,--no-undefined diff --git a/src/backends/unicorn-emulator/unicorn.hpp b/src/backends/unicorn-emulator/unicorn.hpp index a129404c..c06ea4f6 100644 --- a/src/backends/unicorn-emulator/unicorn.hpp +++ b/src/backends/unicorn-emulator/unicorn.hpp @@ -10,7 +10,9 @@ #pragma GCC diagnostic ignored "-Wunused-function" #endif +#ifndef NOMINMAX #define NOMINMAX +#endif #include #ifdef __clang__ diff --git a/src/common/platform/compiler.hpp b/src/common/platform/compiler.hpp index 07fc82c2..4d051025 100644 --- a/src/common/platform/compiler.hpp +++ b/src/common/platform/compiler.hpp @@ -20,11 +20,13 @@ #endif #ifdef OS_WINDOWS -#define EXPORT_SYMBOL __declspec(dllexport) -#define IMPORT_SYMBOL __declspec(dllimport) -#define NO_INLINE __declspec(noinline) +#define EXPORT_SYMBOL __declspec(dllexport) +#define IMPORT_SYMBOL __declspec(dllimport) +#define NO_INLINE __declspec(noinline) +#ifndef DECLSPEC_ALIGN #define DECLSPEC_ALIGN(n) __declspec(align(n)) +#endif #define RESTRICTED_POINTER diff --git a/src/common/platform/file_management.hpp b/src/common/platform/file_management.hpp index 60097940..bf43b9d7 100644 --- a/src/common/platform/file_management.hpp +++ b/src/common/platform/file_management.hpp @@ -72,8 +72,10 @@ #define SL_RETURN_SINGLE_ENTRY 0x02 #define SL_NO_CURSOR_UPDATE 0x10 -#define SEC_IMAGE 0x01000000 -#define SEC_RESERVE 0x04000000 +#ifndef SEC_IMAGE +#define SEC_IMAGE 0x01000000 +#define SEC_RESERVE 0x04000000 +#endif typedef enum _FSINFOCLASS { diff --git a/src/common/platform/memory.hpp b/src/common/platform/memory.hpp index 8f6023cd..3ff99657 100644 --- a/src/common/platform/memory.hpp +++ b/src/common/platform/memory.hpp @@ -2,23 +2,24 @@ // NOLINTBEGIN(modernize-use-using) -#define PAGE_EXECUTE 0x10 -#define PAGE_EXECUTE_READ 0x20 -#define PAGE_EXECUTE_READWRITE 0x40 -#define PAGE_EXECUTE_WRITECOPY 0x80 +#define PAGE_EXECUTE 0x10 +#define PAGE_EXECUTE_READ 0x20 +#define PAGE_EXECUTE_READWRITE 0x40 +#define PAGE_EXECUTE_WRITECOPY 0x80 -#define PAGE_NOACCESS 0x01 -#define PAGE_READONLY 0x02 -#define PAGE_READWRITE 0x04 -#define PAGE_WRITECOPY 0x08 +#define PAGE_NOACCESS 0x01 +#define PAGE_READONLY 0x02 +#define PAGE_READWRITE 0x04 +#define PAGE_WRITECOPY 0x08 -#define PAGE_TARGETS_INVALID 0x40000000 -#define PAGE_TARGETS_NO_UPDATE 0x40000000 +#define PAGE_TARGETS_INVALID 0x40000000 +#define PAGE_TARGETS_NO_UPDATE 0x40000000 -#define PAGE_GUARD 0x100 -#define PAGE_NOCACHE 0x200 -#define PAGE_WRITECOMBINE 0x400 +#define PAGE_GUARD 0x100 +#define PAGE_NOCACHE 0x200 +#define PAGE_WRITECOMBINE 0x400 +#ifndef MEM_64K_PAGES #define MEM_COMMIT 0x00001000 #define MEM_RESERVE 0x00002000 #define MEM_DECOMMIT 0x00004000 @@ -37,6 +38,7 @@ #define MEM_DOS_LIM 0x40000000 #define MEM_4MB_PAGES 0x80000000 #define MEM_64K_PAGES (MEM_LARGE_PAGES | MEM_PHYSICAL) +#endif typedef enum _MEMORY_INFORMATION_CLASS { @@ -64,7 +66,11 @@ typedef enum _SECTION_INHERIT ViewUnmap = 2 } SECTION_INHERIT; -typedef struct DECLSPEC_ALIGN(16) _EMU_MEMORY_BASIC_INFORMATION64 +typedef struct +#ifndef __MINGW64__ + DECLSPEC_ALIGN(16) +#endif + _EMU_MEMORY_BASIC_INFORMATION64 { uint64_t BaseAddress; uint64_t AllocationBase; diff --git a/src/common/platform/platform.hpp b/src/common/platform/platform.hpp index 6e8dff89..fc4c1edf 100644 --- a/src/common/platform/platform.hpp +++ b/src/common/platform/platform.hpp @@ -1,6 +1,6 @@ #pragma once -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW64__) #pragma warning(push) #pragma warning(disable : 4201) // nameless struct/union #pragma warning(disable : 4702) // unreachable code @@ -31,6 +31,6 @@ #pragma GCC diagnostic pop #endif -#ifdef OS_WINDOWS +#if defined(_WIN32) && !defined(__MINGW64__) #pragma warning(pop) #endif diff --git a/src/common/platform/process.hpp b/src/common/platform/process.hpp index 0fc6adbb..1234f900 100644 --- a/src/common/platform/process.hpp +++ b/src/common/platform/process.hpp @@ -591,7 +591,11 @@ using NEON128 = struct _NEON128 LONGLONG High; }; -typedef struct DECLSPEC_ALIGN(16) _CONTEXT64 +typedef struct +#if !defined(__MINGW64__) + DECLSPEC_ALIGN(16) +#endif + _CONTEXT64 { DWORD64 P1Home; DWORD64 P2Home; diff --git a/src/samples/test-sample/CMakeLists.txt b/src/samples/test-sample/CMakeLists.txt index 918b772c..cba82b1e 100644 --- a/src/samples/test-sample/CMakeLists.txt +++ b/src/samples/test-sample/CMakeLists.txt @@ -8,7 +8,7 @@ list(SORT SRC_FILES) add_executable(test-sample ${SRC_FILES}) -if(MINGW) +if(WIN) target_link_libraries(test-sample PRIVATE ws2_32) endif() diff --git a/src/samples/test-sample/test.cpp b/src/samples/test-sample/test.cpp index a3ec47ca..6b5cdba6 100644 --- a/src/samples/test-sample/test.cpp +++ b/src/samples/test-sample/test.cpp @@ -9,7 +9,9 @@ #include #include +#ifndef NOMINMAX #define NOMINMAX +#endif #define WIN32_LEAN_AND_MEAN #include @@ -23,8 +25,6 @@ #include #endif -#pragma comment(lib, "ws2_32.lib") - using namespace std::literals; // Externally visible and potentially modifiable state @@ -570,8 +570,10 @@ namespace return false; } - if (sendto(sender, send_data.data(), static_cast(send_data.size()), 0, - reinterpret_cast(&destination), sizeof(destination)) != send_data.size()) + const auto sent_bytes = sendto(sender, send_data.data(), static_cast(send_data.size()), 0, + reinterpret_cast(&destination), sizeof(destination)); + + if (static_cast(sent_bytes) != send_data.size()) { puts("Failed to send data!"); return false; @@ -593,6 +595,7 @@ namespace return send_data == std::string_view(buffer, len); } +#ifndef __MINGW64__ void throw_access_violation() { if (do_the_task) @@ -601,7 +604,6 @@ namespace } } -#ifndef __MINGW64__ bool test_access_violation_exception() { __try diff --git a/src/windows-emulator/std_include.hpp b/src/windows-emulator/std_include.hpp index 05cf0d0b..4162beb2 100644 --- a/src/windows-emulator/std_include.hpp +++ b/src/windows-emulator/std_include.hpp @@ -1,36 +1,5 @@ #pragma once -#ifdef _WIN32 -#pragma warning(push) -#pragma warning(disable : 4005) -#pragma warning(disable : 4127) -#pragma warning(disable : 4201) -#pragma warning(disable : 4244) -#pragma warning(disable : 4245) -#pragma warning(disable : 4324) -#pragma warning(disable : 4458) -#pragma warning(disable : 4471) -#pragma warning(disable : 4505) -#pragma warning(disable : 4702) -#pragma warning(disable : 4996) -#pragma warning(disable : 5054) -#pragma warning(disable : 6011) -#pragma warning(disable : 6297) -#pragma warning(disable : 6385) -#pragma warning(disable : 6386) -#pragma warning(disable : 6387) -#pragma warning(disable : 26110) -#pragma warning(disable : 26451) -#pragma warning(disable : 26444) -#pragma warning(disable : 26451) -#pragma warning(disable : 26489) -#pragma warning(disable : 26495) -#pragma warning(disable : 26498) -#pragma warning(disable : 26812) -#pragma warning(disable : 28020) -#pragma warning(pop) -#endif - #include #include #include From 37dd3875607a897de3a260196a61d08951440d42 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 10:47:42 +0200 Subject: [PATCH 3/9] Fix more warnings --- cmake/sccache.cmake | 20 ++++---- src/analyzer/main.cpp | 67 ++++++++++++++------------ src/fuzzer/main.cpp | 69 ++++++++++++++------------- src/tools/dump-apiset/dump-apiset.cpp | 18 +++---- 4 files changed, 93 insertions(+), 81 deletions(-) diff --git a/cmake/sccache.cmake b/cmake/sccache.cmake index 732330d5..e0cdfdae 100644 --- a/cmake/sccache.cmake +++ b/cmake/sccache.cmake @@ -1,14 +1,16 @@ include_guard() -find_program(SCCACHE sccache) +if(CMAKE_GENERATOR STREQUAL "Ninja") + find_program(SCCACHE sccache) -if (SCCACHE) - file(TO_CMAKE_PATH "${SCCACHE}" SCCACHE) - set(CMAKE_C_COMPILER_LAUNCHER ${SCCACHE}) - set(CMAKE_CXX_COMPILER_LAUNCHER ${SCCACHE}) - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) + if (SCCACHE) + file(TO_CMAKE_PATH "${SCCACHE}" SCCACHE) + set(CMAKE_C_COMPILER_LAUNCHER ${SCCACHE}) + set(CMAKE_CXX_COMPILER_LAUNCHER ${SCCACHE}) + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded) - if(POLICY CMP0141) - cmake_policy(SET CMP0141 NEW) + if(POLICY CMP0141) + cmake_policy(SET CMP0141 NEW) + endif() endif() -endif() +endif() \ No newline at end of file diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index a9690f93..889e78be 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -473,45 +473,50 @@ namespace return options; } + + int run_main(const int argc, char** argv) + { + try + { + auto args = bundle_arguments(argc, argv); + if (args.empty()) + { + print_help(); + return 1; + } + + const auto options = parse_options(args); + + bool result{}; + + do + { + result = run(options, args); + } while (options.use_gdb); + + return result ? 0 : 1; + } + catch (std::exception& e) + { + puts(e.what()); + +#if defined(_WIN32) && 0 + MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR); +#endif + } + + return 1; + } } int main(const int argc, char** argv) { - try - { - auto args = bundle_arguments(argc, argv); - if (args.empty()) - { - print_help(); - return 1; - } - - const auto options = parse_options(args); - - bool result{}; - - do - { - result = run(options, args); - } while (options.use_gdb); - - return result ? 0 : 1; - } - catch (std::exception& e) - { - puts(e.what()); - -#if defined(_WIN32) && 0 - MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR); -#endif - } - - return 1; + return run_main(argc, argv); } #ifdef _WIN32 int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int) { - return main(__argc, __argv); + return run_main(__argc, __argv); } #endif diff --git a/src/fuzzer/main.cpp b/src/fuzzer/main.cpp index 2bb4cb5c..7af4ba2d 100644 --- a/src/fuzzer/main.cpp +++ b/src/fuzzer/main.cpp @@ -166,46 +166,51 @@ namespace forward_emulator(win_emu); run_fuzzer(win_emu); } + + int run_main(const int argc, char** argv) + { + if (argc <= 1) + { + puts("Application not specified!"); + return 1; + } + + // setvbuf(stdout, nullptr, _IOFBF, 0x10000); + if (argc > 2 && argv[1] == "-d"s) + { + use_gdb = true; + } + + try + { + do + { + run(argv[use_gdb ? 2 : 1]); + } while (use_gdb); + + return 0; + } + catch (std::exception& e) + { + puts(e.what()); + +#if defined(_WIN32) && 0 + MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR); +#endif + } + + return 1; + } } int main(const int argc, char** argv) { - if (argc <= 1) - { - puts("Application not specified!"); - return 1; - } - - // setvbuf(stdout, nullptr, _IOFBF, 0x10000); - if (argc > 2 && argv[1] == "-d"s) - { - use_gdb = true; - } - - try - { - do - { - run(argv[use_gdb ? 2 : 1]); - } while (use_gdb); - - return 0; - } - catch (std::exception& e) - { - puts(e.what()); - -#if defined(_WIN32) && 0 - MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR); -#endif - } - - return 1; + return run_main(argc, argv); } #ifdef _WIN32 int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int) { - return main(__argc, __argv); + return run_main(__argc, __argv); } #endif diff --git a/src/tools/dump-apiset/dump-apiset.cpp b/src/tools/dump-apiset/dump-apiset.cpp index 8b18741f..1b2c4ffa 100644 --- a/src/tools/dump-apiset/dump-apiset.cpp +++ b/src/tools/dump-apiset/dump-apiset.cpp @@ -24,14 +24,14 @@ int main() const auto peb = static_cast(GetCurrentProcessPeb()); const auto api_set_map = reinterpret_cast(peb->ApiSetMap); - printf("APISET: 0x%p\n", api_set_map); - printf("Version: %d\n", api_set_map->Version); - printf("Size: %08X\n", api_set_map->Size); - printf("Flags: %08X\n", api_set_map->Flags); - printf("Count: %d\n", api_set_map->Count); - printf("EntryOffset: %08X\n", api_set_map->EntryOffset); - printf("HashOffset: %08X\n", api_set_map->HashOffset); - printf("HashFactor: %08X\n", api_set_map->HashFactor); + printf("APISET: 0x%p\n", static_cast(api_set_map)); + printf("Version: %lu\n", api_set_map->Version); + printf("Size: %08lX\n", api_set_map->Size); + printf("Flags: %08lX\n", api_set_map->Flags); + printf("Count: %lu\n", api_set_map->Count); + printf("EntryOffset: %08lX\n", api_set_map->EntryOffset); + printf("HashOffset: %08lX\n", api_set_map->HashOffset); + printf("HashFactor: %08lX\n", api_set_map->HashFactor); // print_apiset(apiSetMap); // Compress the API-SET binary blob @@ -68,7 +68,7 @@ void print_apiset(PAPI_SET_NAMESPACE api_set_map) std::wstring name(reinterpret_cast(reinterpret_cast(api_set_map) + entry->NameOffset), entry->NameLength / sizeof(wchar_t)); - printf("-----------\n[%05d]: Contract Name: %ls\n", i, name.data()); + printf("-----------\n[%05lu]: Contract Name: %ls\n", i, name.data()); for (ULONG x = 0; x < entry->ValueCount; x++) { From 2e1c1b23c9d48c21a1efb3e4c1928d5c0ed741af Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 11:25:28 +0200 Subject: [PATCH 4/9] Add MinGW smoke test --- .github/workflows/build.yml | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f144feca..29e4a8a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -340,7 +340,6 @@ jobs: platform: - Windows x86 - Windows x86_64 - - MinGW x86_64 - Linux x86_64 GCC - Linux x86_64 GCC Sanitizer - Linux x86_64 Clang @@ -365,8 +364,6 @@ jobs: runner: windows-latest - platform: Windows x86_64 runner: windows-latest - - platform: MinGW x86_64 - runner: windows-latest - platform: Linux x86_64 GCC runner: ubuntu-24.04 - platform: Linux x86_64 GCC Sanitizer @@ -404,7 +401,7 @@ jobs: - name: Download Windows Artifacts uses: pyTooling/download-artifact@v4 - if: "${{ matrix.platform != 'Windows x86_64' && matrix.platform != 'MinGW x86_64' }}" + if: "${{ matrix.platform != 'Windows x86_64' }}" with: name: Windows x86_64 Release Artifacts path: build/${{matrix.preset}}/artifacts @@ -419,7 +416,7 @@ jobs: run: cp build/${{matrix.preset}}/artifacts/test-sample.exe build/${{matrix.preset}}/artifacts/root/filesys/c/ - name: CMake Test - if: ${{ matrix.emulator != 'Icicle' || (matrix.platform != 'Windows x86' && matrix.platform != 'MinGW x86_64') }} + if: ${{ matrix.emulator != 'Icicle' || matrix.platform != 'Windows x86' }} run: cd build/${{matrix.preset}} && ctest --verbose -j env: EMULATOR_ROOT: ${{github.workspace}}/build/${{matrix.preset}}/artifacts/root @@ -487,11 +484,6 @@ jobs: runs-on: ubuntu-24.04 needs: [create-emulation-root, build] steps: - - name: Checkout Source - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Download Artifacts uses: pyTooling/download-artifact@v4 with: @@ -519,6 +511,29 @@ jobs: EMULATOR_ROOT: ${{github.workspace}}/build/release/artifacts/root EMULATOR_VERBOSE: ${{ github.event.inputs.verbose }} + smoke-test-mingw: + name: Smoke Test MinGW x86_64 + runs-on: windows-latest + needs: [create-emulation-root, build] + steps: + - name: Download Artifacts + uses: pyTooling/download-artifact@v4 + with: + name: MinGW x86_64 Release Artifacts + path: build/release/artifacts + + - name: Download Emulation Root + uses: pyTooling/download-artifact@v4 + with: + name: Windows 2022 Emulation Root + path: build/release/artifacts/root + + - name: CMake Test + run: cd build/release/artifacts && ./windows-emulator-test.exe + env: + EMULATOR_ROOT: ${{github.workspace}}/build/release/artifacts/root + EMULATOR_VERBOSE: ${{ github.event.inputs.verbose }} + smoke-test-android: name: Smoke Test Android @@ -666,7 +681,7 @@ jobs: summary: name: Pipeline Summary runs-on: ubuntu-24.04 - needs: [build-page, clang-tidy, build-apiset-dumper, smoke-test-node, smoke-test-android, create-emulation-root, build, test, win-test, verify-formatting] + needs: [build-page, clang-tidy, build-apiset-dumper, smoke-test-node, smoke-test-mingw, smoke-test-android, create-emulation-root, build, test, win-test, verify-formatting] if: always() steps: - uses: geekyeggo/delete-artifact@v5 From 98010268a6d3ddb8ed12a14bf54aa19cd0758959 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 11:50:34 +0200 Subject: [PATCH 5/9] Statically link libraries for mingw --- .github/workflows/build.yml | 3 +++ cmake/compiler-env.cmake | 7 +++++++ src/CMakeLists.txt | 3 --- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 29e4a8a7..7423a956 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -528,6 +528,9 @@ jobs: name: Windows 2022 Emulation Root path: build/release/artifacts/root + - name: Copy Test Sample + run: cp build/release/artifacts/test-sample.exe build/release/artifacts/root/filesys/c/ + - name: CMake Test run: cd build/release/artifacts && ./windows-emulator-test.exe env: diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index c94b21b1..d6d1739e 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -64,6 +64,13 @@ endif() ########################################## if(MINGW) + add_link_options( + -static-libstdc++ + -static-libgcc + -static + -lwinpthread + ) + momo_add_c_and_cxx_compile_options( -Wno-array-bounds ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c71b182..300b763d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,9 +9,6 @@ momo_add_subdirectory_and_get_targets("backends" BACKEND_TARGETS) momo_targets_set_folder("backends" ${BACKEND_TARGETS}) if (NOT MOMO_BUILD_AS_LIBRARY) - if (MINGW) - add_link_options(-static-libstdc++ -static -lwinpthread) - endif() add_subdirectory(analyzer) add_subdirectory(debugger) add_subdirectory(fuzzing-engine) From b6f46454204f03300c7e5c1b32bd55cbd6028233 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 12:40:52 +0200 Subject: [PATCH 6/9] Some more syscalls --- src/common/platform/file_management.hpp | 32 +++++++ src/windows-emulator/syscall_utils.hpp | 9 +- src/windows-emulator/syscalls.cpp | 5 + src/windows-emulator/syscalls/file.cpp | 115 +++++++++++++++++++---- src/windows-emulator/syscalls/object.cpp | 12 ++- 5 files changed, 150 insertions(+), 23 deletions(-) diff --git a/src/common/platform/file_management.hpp b/src/common/platform/file_management.hpp index bf43b9d7..0aa70ccf 100644 --- a/src/common/platform/file_management.hpp +++ b/src/common/platform/file_management.hpp @@ -397,6 +397,11 @@ typedef struct _FILE_BOTH_DIR_INFORMATION } FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; #ifndef OS_WINDOWS +typedef struct _FILE_ID_128 +{ + BYTE Identifier[16]; +} FILE_ID_128, *PFILE_ID_128; + typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE, *PSECURITY_CONTEXT_TRACKING_MODE; typedef struct _SECURITY_QUALITY_OF_SERVICE { @@ -408,6 +413,27 @@ typedef struct _SECURITY_QUALITY_OF_SERVICE #endif +#ifndef _MSC_VER +typedef struct _FILE_STAT_BASIC_INFORMATION +{ + LARGE_INTEGER FileId; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; + ULONG ReparseTag; + ULONG NumberOfLinks; + ULONG DeviceType; + ULONG DeviceCharacteristics; + ULONG Reserved; + LARGE_INTEGER VolumeSerialNumber; + FILE_ID_128 FileId128; +} FILE_STAT_BASIC_INFORMATION, *PFILE_STAT_BASIC_INFORMATION; +#endif + typedef struct _PORT_VIEW64 { ULONG Length; @@ -425,4 +451,10 @@ typedef struct _REMOTE_PORT_VIEW64 EmulatorTraits::PVOID ViewBase; } REMOTE_PORT_VIEW64, *PREMOTE_PORT_VIEW64; +typedef struct _OBJECT_HANDLE_FLAG_INFORMATION +{ + BOOLEAN Inherit; + BOOLEAN ProtectFromClose; +} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION; + // NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) diff --git a/src/windows-emulator/syscall_utils.hpp b/src/windows-emulator/syscall_utils.hpp index a4585d1c..086a4741 100644 --- a/src/windows-emulator/syscall_utils.hpp +++ b/src/windows-emulator/syscall_utils.hpp @@ -217,14 +217,15 @@ NTSTATUS handle_query_internal(x86_64_emulator& emu, const uint64_t buffer, cons return STATUS_SUCCESS; } -template +template + requires(std::is_integral_v) NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length, - const emulator_object return_length, const Action& action) + const emulator_object return_length, const Action& action) { - const auto length_setter = [&](const uint32_t required_size) { + const auto length_setter = [&](const size_t required_size) { if (return_length) { - return_length.write(required_size); + return_length.write(static_cast(required_size)); } }; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 18924636..e30004d4 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -66,6 +66,10 @@ namespace syscalls NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, handle file_handle, emulator_object>> io_status_block, uint64_t file_information, uint32_t length, uint32_t info_class); + NTSTATUS handle_NtQueryInformationByName( + const syscall_context& c, emulator_object>> object_attributes, + emulator_object>> io_status_block, uint64_t file_information, + uint32_t length, uint32_t info_class); NTSTATUS handle_NtReadFile(const syscall_context& c, handle file_handle, uint64_t /*event*/, uint64_t /*apc_routine*/, uint64_t /*apc_context*/, emulator_object>> io_status_block, uint64_t buffer, @@ -1091,6 +1095,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtUserSetProp2); add_handler(NtUserChangeWindowMessageFilterEx); add_handler(NtUserDestroyWindow); + add_handler(NtQueryInformationByName); #undef add_handler } diff --git a/src/windows-emulator/syscalls/file.cpp b/src/windows-emulator/syscalls/file.cpp index 6462e60b..fc323e1f 100644 --- a/src/windows-emulator/syscalls/file.cpp +++ b/src/windows-emulator/syscalls/file.cpp @@ -464,6 +464,98 @@ namespace syscalls return ret(STATUS_NOT_SUPPORTED); } + static std::pair open_file(const file_system& file_sys, const windows_path& path, + const std::u16string& mode) + { + FILE* file{}; + const auto error = open_unicode(&file, file_sys.translate(path), mode); + + if (file) + { + return {file, STATUS_SUCCESS}; + } + + using fh = utils::file_handle; + + switch (error) + { + case ENOENT: + return {fh{}, STATUS_OBJECT_NAME_NOT_FOUND}; + case EACCES: + return {fh{}, STATUS_ACCESS_DENIED}; + case EISDIR: + return {fh{}, STATUS_FILE_IS_A_DIRECTORY}; + default: + return {fh{}, STATUS_NOT_SUPPORTED}; + } + } + + NTSTATUS handle_NtQueryInformationByName( + const syscall_context& c, const emulator_object>> object_attributes, + const emulator_object>> io_status_block, const uint64_t file_information, + const uint32_t length, const uint32_t info_class) + { + IO_STATUS_BLOCK> block{}; + block.Status = STATUS_SUCCESS; + block.Information = 0; + + const auto _ = utils::finally([&] { + if (io_status_block) + { + io_status_block.write(block); + } + }); + + const auto attributes = object_attributes.read(); + auto filename = read_unicode_string(c.emu, attributes.ObjectName); + + c.win_emu.log.print(color::dark_gray, "--> Query file info: %s\n", u16_to_u8(filename).c_str()); // + + const auto ret = [&](const NTSTATUS status) { + block.Status = status; + return status; + }; + + if (info_class == FileStatBasicInformation) + { + block.Information = sizeof(FILE_STAT_BASIC_INFORMATION); + + if (length < block.Information) + { + return ret(STATUS_BUFFER_OVERFLOW); + } + + auto [native_file_handle, status] = open_file(c.win_emu.file_sys, filename, u"r"); + if (status != STATUS_SUCCESS) + { + return ret(status); + } + + struct _stat64 file_stat{}; + if (fstat64(native_file_handle, &file_stat) != 0) + { + return STATUS_INVALID_HANDLE; + } + + FILE_STAT_BASIC_INFORMATION i{}; + + i.CreationTime = utils::convert_unix_to_windows_time(file_stat.st_atime); + i.LastAccessTime = utils::convert_unix_to_windows_time(file_stat.st_atime); + i.LastWriteTime = utils::convert_unix_to_windows_time(file_stat.st_mtime); + i.ChangeTime = i.LastWriteTime; + i.FileAttributes = (file_stat.st_mode & S_IFDIR) != 0 ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; + + c.emu.write_memory(file_information, i); + + return ret(STATUS_SUCCESS); + } + + c.win_emu.log.error("Unsupported query name info class: %X\n", info_class); + c.emu.stop(); + + return ret(STATUS_NOT_SUPPORTED); + } + void commit_file_data(const std::string_view data, emulator& emu, const emulator_object>> io_status_block, const uint64_t buffer) @@ -739,26 +831,13 @@ namespace syscalls return STATUS_NOT_SUPPORTED; } - FILE* file{}; - - const auto error = open_unicode(&file, c.win_emu.file_sys.translate(path), mode); - - if (!file) + auto [native_file_handle, status] = open_file(c.win_emu.file_sys, path, mode); + if (status != STATUS_SUCCESS) { - switch (error) - { - case ENOENT: - return STATUS_OBJECT_NAME_NOT_FOUND; - case EACCES: - return STATUS_ACCESS_DENIED; - case EISDIR: - return STATUS_FILE_IS_A_DIRECTORY; - default: - return STATUS_NOT_SUPPORTED; - } + return status; } - f.handle = file; + f.handle = std::move(native_file_handle); const auto handle = c.proc.files.store(std::move(f)); file_handle.write(handle); @@ -982,4 +1061,4 @@ namespace syscalls (void)fflush(f->handle); return STATUS_SUCCESS; } -} \ No newline at end of file +} diff --git a/src/windows-emulator/syscalls/object.cpp b/src/windows-emulator/syscalls/object.cpp index 7420e43e..024a04b9 100644 --- a/src/windows-emulator/syscalls/object.cpp +++ b/src/windows-emulator/syscalls/object.cpp @@ -99,6 +99,16 @@ namespace syscalls return STATUS_SUCCESS; } + if (object_information_class == ObjectHandleFlagInformation) + { + return handle_query(c.emu, object_information, object_information_length, + return_length, + [&](OBJECT_HANDLE_FLAG_INFORMATION& info) { + info.Inherit = 0; + info.ProtectFromClose = 0; + }); + } + c.win_emu.log.error("Unsupported object info class: %X\n", object_information_class); c.emu.stop(); return STATUS_NOT_SUPPORTED; @@ -176,4 +186,4 @@ namespace syscalls { return STATUS_NOT_SUPPORTED; } -} \ No newline at end of file +} From abfbc3fad35f33a5da612dd113f11417f50c780e Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 14:18:57 +0200 Subject: [PATCH 7/9] Add another test --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7423a956..5b79268a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -532,7 +532,7 @@ jobs: run: cp build/release/artifacts/test-sample.exe build/release/artifacts/root/filesys/c/ - name: CMake Test - run: cd build/release/artifacts && ./windows-emulator-test.exe + run: cd build/release/artifacts && ./analyzer.exe -e root c:/test-sample.exe && ./windows-emulator-test.exe env: EMULATOR_ROOT: ${{github.workspace}}/build/release/artifacts/root EMULATOR_VERBOSE: ${{ github.event.inputs.verbose }} From bc92023652a9e35eff4f8832975295dfa5117516 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 16:30:39 +0200 Subject: [PATCH 8/9] Fix directory enumation with filesystem mappings --- src/windows-emulator/file_system.hpp | 13 ++++ src/windows-emulator/syscalls/file.cpp | 83 +++++++++++++++++--------- src/windows-emulator/windows_path.hpp | 10 ++++ 3 files changed, 78 insertions(+), 28 deletions(-) diff --git a/src/windows-emulator/file_system.hpp b/src/windows-emulator/file_system.hpp index de5a618b..ae5a60dc 100644 --- a/src/windows-emulator/file_system.hpp +++ b/src/windows-emulator/file_system.hpp @@ -56,6 +56,19 @@ class file_system return root; } + template + void access_mapped_entries(const windows_path& win_path, const F& accessor) const + { + for (const auto& mapping : this->mappings_) + { + const auto& mapped_path = mapping.first; + if (!mapped_path.empty() && mapped_path.parent() == win_path) + { + accessor(mapping); + } + } + } + windows_path local_to_windows_path(const std::filesystem::path& local_path) const { const auto absolute_local_path = weakly_canonical(absolute(local_path)); diff --git a/src/windows-emulator/syscalls/file.cpp b/src/windows-emulator/syscalls/file.cpp index fc323e1f..fdeb61ee 100644 --- a/src/windows-emulator/syscalls/file.cpp +++ b/src/windows-emulator/syscalls/file.cpp @@ -17,6 +17,35 @@ namespace syscalls { + namespace + { + std::pair open_file(const file_system& file_sys, const windows_path& path, + const std::u16string& mode) + { + FILE* file{}; + const auto error = open_unicode(&file, file_sys.translate(path), mode); + + if (file) + { + return {file, STATUS_SUCCESS}; + } + + using fh = utils::file_handle; + + switch (error) + { + case ENOENT: + return {fh{}, STATUS_OBJECT_NAME_NOT_FOUND}; + case EACCES: + return {fh{}, STATUS_ACCESS_DENIED}; + case EISDIR: + return {fh{}, STATUS_FILE_IS_A_DIRECTORY}; + default: + return {fh{}, STATUS_NOT_SUPPORTED}; + } + } + } + NTSTATUS handle_NtSetInformationFile(const syscall_context& c, const handle file_handle, const emulator_object>> io_status_block, const uint64_t file_information, const ULONG length, @@ -117,10 +146,13 @@ namespace syscalls } } - std::vector scan_directory(const std::filesystem::path& dir, const std::u16string_view file_mask) + std::vector scan_directory(const file_system& file_sys, const windows_path& win_path, + const std::u16string_view file_mask) { std::vector files{}; + const auto dir = file_sys.translate(win_path); + if (file_mask.empty() || file_mask == u"*") { files.emplace_back(file_entry{.file_path = ".", .is_directory = true}); @@ -142,6 +174,27 @@ namespace syscalls }); } + file_sys.access_mapped_entries(win_path, [&](const std::pair& entry) { + const auto filename = entry.first.leaf(); + + if (!file_mask.empty() && !utils::wildcard::match_filename(filename, file_mask)) + { + return; + } + + const std::filesystem::directory_entry dir_entry(entry.second, ec); + if (ec || !dir_entry.exists()) + { + return; + } + + files.emplace_back(file_entry{ + .file_path = filename, + .file_size = dir_entry.file_size(), + .is_directory = dir_entry.is_directory(), + }); + }); + return files; } @@ -166,7 +219,7 @@ namespace syscalls } f->enumeration_state.emplace(file_enumeration_state{}); - f->enumeration_state->files = scan_directory(c.win_emu.file_sys.translate(f->name), mask); + f->enumeration_state->files = scan_directory(c.win_emu.file_sys, f->name, mask); } auto& enum_state = *f->enumeration_state; @@ -464,32 +517,6 @@ namespace syscalls return ret(STATUS_NOT_SUPPORTED); } - static std::pair open_file(const file_system& file_sys, const windows_path& path, - const std::u16string& mode) - { - FILE* file{}; - const auto error = open_unicode(&file, file_sys.translate(path), mode); - - if (file) - { - return {file, STATUS_SUCCESS}; - } - - using fh = utils::file_handle; - - switch (error) - { - case ENOENT: - return {fh{}, STATUS_OBJECT_NAME_NOT_FOUND}; - case EACCES: - return {fh{}, STATUS_ACCESS_DENIED}; - case EISDIR: - return {fh{}, STATUS_FILE_IS_A_DIRECTORY}; - default: - return {fh{}, STATUS_NOT_SUPPORTED}; - } - } - NTSTATUS handle_NtQueryInformationByName( const syscall_context& c, const emulator_object>> object_attributes, const emulator_object>> io_status_block, const uint64_t file_information, diff --git a/src/windows-emulator/windows_path.hpp b/src/windows-emulator/windows_path.hpp index dea40aab..e2b10ba0 100644 --- a/src/windows-emulator/windows_path.hpp +++ b/src/windows-emulator/windows_path.hpp @@ -224,6 +224,16 @@ class windows_path return {this->drive_, std::move(folders)}; } + std::u16string leaf() const + { + if (this->folders_.empty()) + { + return {}; + } + + return this->folders_.back(); + } + void serialize(utils::buffer_serializer& buffer) const { buffer.write_optional(this->drive_); From c41fc21b13fe2d3c5a4a6f2b1523e471ee9849a6 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 31 May 2025 16:32:08 +0200 Subject: [PATCH 9/9] Change test order --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5b79268a..2f0c5ddc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -532,7 +532,7 @@ jobs: run: cp build/release/artifacts/test-sample.exe build/release/artifacts/root/filesys/c/ - name: CMake Test - run: cd build/release/artifacts && ./analyzer.exe -e root c:/test-sample.exe && ./windows-emulator-test.exe + run: cd build/release/artifacts && ./windows-emulator-test.exe && ./analyzer.exe -e root c:/test-sample.exe env: EMULATOR_ROOT: ${{github.workspace}}/build/release/artifacts/root EMULATOR_VERBOSE: ${{ github.event.inputs.verbose }}