diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5f06e03d..a6860204 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -161,6 +161,7 @@ jobs: - iOS arm64 - Android x86_64 - Android arm64-v8a + - Emscripten configuration: - Debug - Release @@ -201,6 +202,9 @@ jobs: abi: arm64-v8a rust-target: aarch64-linux-android cmake-options: "-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchain/android-ndk.cmake" + - platform: Emscripten + runner: ubuntu-24.04 + cmake-options: "-DMOMO_ENABLE_RUST_CODE=Off -DCMAKE_TOOLCHAIN_FILE=$(dirname $(which emcc))/cmake/Modules/Platform/Emscripten.cmake" steps: - name: Checkout Source uses: actions/checkout@v4 @@ -214,6 +218,10 @@ jobs: if: "${{ matrix.rust-target }}" run: rustup target add ${{ matrix.rust-target }} + - name: Install Emscripten + if: "${{ matrix.platform == 'Emscripten' }}" + uses: mymindstorm/setup-emsdk@v14 + - name: Install Clang if: "${{ matrix.platform == 'Linux x86_64 Clang' }}" run: | @@ -473,10 +481,88 @@ jobs: arch: ${{matrix.architecture}} script: "adb push build/${{matrix.preset}}/artifacts/* /data/local/tmp && adb shell \"cd /data/local/tmp && export LD_LIBRARY_PATH=. && chmod +x ./analyzer && EMULATOR_ICICLE=${{ matrix.emulator == 'Icicle' }} ./analyzer -e ./root c:/test-sample.exe\"" + build-page: + name: Build Page + runs-on: ubuntu-latest + needs: [create-emulation-root, build] + permissions: + contents: read + pages: write + id-token: write + steps: + - name: Checkout Source + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Download Emscripten Artifacts + uses: pyTooling/download-artifact@v4 + with: + name: Emscripten Release Artifacts + path: build/release/artifacts + + - name: Download Windows Artifacts + uses: pyTooling/download-artifact@v4 + with: + name: Windows 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: Copy Sample + run: cp ./build/release/artifacts/test-sample.exe build/release/artifacts/root/filesys/c/ + + - name: Create Emulation Root zip + run: cd ./build/release/artifacts && zip -r "${{github.workspace}}/page/root.zip" ./root + + - name: Copy Files + run: | + cp ./build/release/artifacts/analyzer.js ./page/ + cp ./build/release/artifacts/analyzer.wasm ./page/ + + - name: Upload Page Artifacts + uses: pyTooling/upload-artifact@v4 + with: + name: Page Artifacts + working-directory: page/ + path: "*" + + deploy-page: + name: Deploy Page + runs-on: ubuntu-latest + needs: [build-page, summary] + if: github.repository_owner == 'momo5502' && github.event_name == 'push' && github.ref == 'refs/heads/main' + permissions: + contents: read + pages: write + id-token: write + steps: + - name: Download Page Artifacts + uses: pyTooling/download-artifact@v4 + with: + name: Page Artifacts + path: ./page/ + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./page + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + summary: name: Pipeline Summary runs-on: ubuntu-24.04 - needs: [clang-tidy, build-apiset-dumper, smoke-test-android, create-emulation-root, build, test, win-test, verify-formatting] + needs: [build-page, clang-tidy, build-apiset-dumper, smoke-test-android, create-emulation-root, build, test, win-test, verify-formatting] if: always() steps: - uses: geekyeggo/delete-artifact@v5 diff --git a/.gitmodules b/.gitmodules index 9c5a000b..ce0fdeaf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,7 +2,7 @@ path = deps/unicorn url = ../unicorn.git shallow = true - branch = dev + branch = wasm [submodule "deps/reflect"] path = deps/reflect url = https://github.com/qlibs/reflect.git diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index 9238fee4..c5b49138 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -22,7 +22,12 @@ cmake_policy(SET CMP0069 NEW) set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) + +########################################## + +if(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten") + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +endif() ########################################## @@ -83,6 +88,22 @@ endif() ########################################## +if(CMAKE_SYSTEM_NAME MATCHES "Emscripten") + add_link_options( + -sALLOW_MEMORY_GROWTH=1 + -sASSERTIONS + -sWASM_BIGINT + -sENVIRONMENT=web + -sUSE_OFFSET_CONVERTER + -sEXCEPTION_CATCHING_ALLOWED=[..] + -sEXIT_RUNTIME + #-lnodefs.js -sNODERAWFS=1 + #-sASYNCIFY +) +endif() + +########################################## + if(MSVC) string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE "/EHs" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") diff --git a/cmake/toolchain/emscripten.cmake b/cmake/toolchain/emscripten.cmake new file mode 100644 index 00000000..761a920a --- /dev/null +++ b/cmake/toolchain/emscripten.cmake @@ -0,0 +1,40 @@ +set(CMAKE_SYSTEM_NAME Emscripten) +set(CMAKE_SYSTEM_VERSION 1) + +# Specify the cross-compilers +set(CMAKE_C_COMPILER emcc) +set(CMAKE_CXX_COMPILER em++) + +# Set the Emscripten root directory +set(EMSCRIPTEN_ROOT_PATH $ENV{EMSDK}/upstream/emscripten) + +# Set the Emscripten toolchain file +set(CMAKE_SYSROOT ${EMSCRIPTEN_ROOT_PATH}/system) + +# Set the Emscripten include directories +set(CMAKE_FIND_ROOT_PATH ${EMSCRIPTEN_ROOT_PATH}/system/include) + +# Set the Emscripten library directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# Set the Emscripten linker +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_SDL=2 -s USE_SDL_MIXER=2") + +# Set the Emscripten runtime +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --shell-file shell_minimal.html") + +# Set the Emscripten optimization flags +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") + +# Set the Emscripten debug flags +set(CMAKE_BUILD_TYPE Release) + +# Set the Emscripten output format +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -o .html") + +# Set the Emscripten file extensions +set(CMAKE_EXECUTABLE_SUFFIX ".js") + +# Set the Emscripten runtime options +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXPORTED_FUNCTIONS='[_main]' -s EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'") \ No newline at end of file diff --git a/cmake/utils.cmake b/cmake/utils.cmake index 4c9dc09b..9b96e990 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -335,7 +335,7 @@ function(momo_strip_target target) return() endif() - if(MSVC OR MOMO_ENABLE_SANITIZER OR CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android") + if(MSVC OR MOMO_ENABLE_SANITIZER OR CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME MATCHES "Emscripten") return() endif() diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 19217d54..5ed0c395 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,5 +1,4 @@ set(UNICORN_ARCH "x86" CACHE STRING "") - add_subdirectory(unicorn) ########################################## diff --git a/deps/unicorn b/deps/unicorn index 73be28b6..6b329651 160000 --- a/deps/unicorn +++ b/deps/unicorn @@ -1 +1 @@ -Subproject commit 73be28b6509d0cbf3333071aec4efbb9be1f1e59 +Subproject commit 6b32965144d4ff91eb303beed0ec938ad467f33b diff --git a/page/bigboiii.webp b/page/bigboiii.webp new file mode 100644 index 00000000..15089347 Binary files /dev/null and b/page/bigboiii.webp differ diff --git a/page/emulator.js b/page/emulator.js new file mode 100644 index 00000000..04ebf177 --- /dev/null +++ b/page/emulator.js @@ -0,0 +1,35 @@ +onmessage = async (event) => { + const data = event.data; + if (data.message == "run") { + runEmulation(data.data); + } +}; + +function logLine(text) { + postMessage(text); +} + +function runEmulation(filesystem) { + globalThis.Module = { + arguments: ["-b", "-c", "-e", "./root", "c:/test-sample.exe",], + onRuntimeInitialized: function () { + filesystem.forEach(e => { + if (e.name.endsWith("/")) { + FS.mkdir(e.name.slice(0, -1)); + } else { + const dirs = e.name.split("/") + const file = dirs.pop(); + const buffer = new Uint8Array(e.data); + FS.createDataFile("/" + dirs.join('/'), file, buffer, true, true); + } + }) + }, + print: logLine, + printErr: logLine, + postRun: () => { + self.close(); + }, + }; + + importScripts('./analyzer.js?1'); +} diff --git a/page/index.html b/page/index.html new file mode 100644 index 00000000..0b0f2fae --- /dev/null +++ b/page/index.html @@ -0,0 +1,432 @@ + + + + + + + Windows User Space Emulator + + + + + + +
+ + + +
+
+
+
+
+
+
+
+ Windows User Space Emulator +
+
+
+
+
+ +
+ Start Emulation + + GitHub +
+ + + \ No newline at end of file diff --git a/page/noise.webp b/page/noise.webp new file mode 100644 index 00000000..50fa5984 Binary files /dev/null and b/page/noise.webp differ diff --git a/page/why-eclipse.svg b/page/why-eclipse.svg new file mode 100644 index 00000000..e12b0893 --- /dev/null +++ b/page/why-eclipse.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/page/why-eclipse2.svg b/page/why-eclipse2.svg new file mode 100644 index 00000000..99d0621b --- /dev/null +++ b/page/why-eclipse2.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt b/src/backends/icicle-emulator/icicle-bridge/CMakeLists.txt index 73ea9f1d..d64c0d21 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(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) +if (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") elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS") set(CARGO_TRIPLE "aarch64-apple-ios") diff --git a/src/backends/icicle-emulator/icicle-bridge/Cargo.lock b/src/backends/icicle-emulator/icicle-bridge/Cargo.lock index 0cd2e74e..b507e56c 100644 --- a/src/backends/icicle-emulator/icicle-bridge/Cargo.lock +++ b/src/backends/icicle-emulator/icicle-bridge/Cargo.lock @@ -43,30 +43,12 @@ version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" -[[package]] -name = "arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - [[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.9.0" @@ -86,12 +68,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - [[package]] name = "bytemuck" version = "1.22.0" @@ -113,148 +89,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "cranelift" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27711210499725bafe52c320a988e27283e6cf477ee8edac57e8275bef8ea550" -dependencies = [ - "cranelift-codegen", - "cranelift-frontend", - "cranelift-module", -] - -[[package]] -name = "cranelift-bforest" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540b193ff98b825a1f250a75b3118911af918a734154c69d80bcfcf91e7e9522" -dependencies = [ - "cranelift-entity", -] - -[[package]] -name = "cranelift-bitset" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cb269598b9557ab942d687d3c1086d77c4b50dcf35813f3a65ba306fd42279" - -[[package]] -name = "cranelift-codegen" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46566d7c83a8bff4150748d66020f4c7224091952aa4b4df1ec4959c39d937a1" -dependencies = [ - "bumpalo", - "cranelift-bforest", - "cranelift-bitset", - "cranelift-codegen-meta", - "cranelift-codegen-shared", - "cranelift-control", - "cranelift-entity", - "cranelift-isle", - "gimli", - "hashbrown 0.14.5", - "log", - "regalloc2", - "rustc-hash", - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cranelift-codegen-meta" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2df8a86a34236cc75a8a6a271973da779c2aeb36c43b6e14da474cf931317082" -dependencies = [ - "cranelift-codegen-shared", -] - -[[package]] -name = "cranelift-codegen-shared" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf75340b6a57b7c7c1b74f10d3d90883ee6d43a554be8131a4046c2ebcf5eb65" - -[[package]] -name = "cranelift-control" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e84495bc5d23d86aad8c86f8ade4af765b94882af60d60e271d3153942f1978" -dependencies = [ - "arbitrary", -] - -[[package]] -name = "cranelift-entity" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963c17147b80df351965e57c04d20dbedc85bcaf44c3436780a59a3f1ff1b1c2" -dependencies = [ - "cranelift-bitset", -] - -[[package]] -name = "cranelift-frontend" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727f02acbc4b4cb2ba38a6637101d579db50190df1dd05168c68e762851a3dd5" -dependencies = [ - "cranelift-codegen", - "log", - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cranelift-isle" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b00cc2e03c748f2531eea01c871f502b909d30295fdcad43aec7bf5c5b4667" - -[[package]] -name = "cranelift-jit" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f74630af581f32b99c8f4e06ee45799383ecc0795e3ff8aa86b7584bb2d643fd" -dependencies = [ - "anyhow", - "cranelift-codegen", - "cranelift-control", - "cranelift-entity", - "cranelift-module", - "cranelift-native", - "libc", - "log", - "region", - "target-lexicon", - "wasmtime-jit-icache-coherence", - "windows-sys 0.59.0", -] - -[[package]] -name = "cranelift-module" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aaa16c4f18a15be310df221ea544f516acc42fc58ca96e09a3d08651744efa1" -dependencies = [ - "anyhow", - "cranelift-codegen", - "cranelift-control", -] - -[[package]] -name = "cranelift-native" -version = "0.113.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbeaf978dc7c1a2de8bbb9162510ed218eb156697bc45590b8fbdd69bb08e8de" -dependencies = [ - "cranelift-codegen", - "libc", - "target-lexicon", -] - [[package]] name = "crc32fast" version = "1.4.2" @@ -276,16 +110,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "errno" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "fallible-iterator" version = "0.3.0" @@ -340,15 +164,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.15.2" @@ -370,12 +185,12 @@ dependencies = [ [[package]] name = "icicle-cpu" version = "0.1.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "addr2line", "ahash", "anyhow", - "bitflags 2.9.0", + "bitflags", "bytemuck", "gimli", "half", @@ -387,30 +202,12 @@ dependencies = [ "tracing", ] -[[package]] -name = "icicle-jit" -version = "0.2.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" -dependencies = [ - "cranelift", - "cranelift-codegen", - "cranelift-jit", - "cranelift-module", - "cranelift-native", - "icicle-cpu", - "memoffset", - "pcode", - "target-lexicon", - "tracing", - "wasmtime-jit-debug", -] - [[package]] name = "icicle-linux" version = "0.1.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ - "bitflags 2.9.0", + "bitflags", "bstr", "bytemuck", "icicle-cpu", @@ -424,7 +221,7 @@ dependencies = [ [[package]] name = "icicle-mem" version = "0.3.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "ahash", "tracing", @@ -433,11 +230,10 @@ dependencies = [ [[package]] name = "icicle-vm" version = "0.2.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "anyhow", "icicle-cpu", - "icicle-jit", "icicle-linux", "ihex", "object", @@ -464,7 +260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown", ] [[package]] @@ -473,27 +269,12 @@ version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - [[package]] name = "memchr" version = "2.7.4" @@ -509,15 +290,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "miniz_oxide" version = "0.8.8" @@ -535,7 +307,7 @@ checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", "flate2", - "hashbrown 0.15.2", + "hashbrown", "indexmap", "memchr", "ruzstd", @@ -550,7 +322,7 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "pcode" version = "0.2.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" [[package]] name = "pin-project-lite" @@ -576,31 +348,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "regalloc2" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0" -dependencies = [ - "hashbrown 0.14.5", - "log", - "rustc-hash", - "slice-group-by", - "smallvec", -] - -[[package]] -name = "region" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" -dependencies = [ - "bitflags 1.3.2", - "libc", - "mach2", - "windows-sys 0.52.0", -] - [[package]] name = "ron" version = "0.8.1" @@ -608,7 +355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64", - "bitflags 2.9.0", + "bitflags", "serde", "serde_derive", ] @@ -619,25 +366,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - [[package]] name = "ruzstd" version = "0.7.3" @@ -682,7 +410,7 @@ dependencies = [ [[package]] name = "sleigh-compile" version = "0.3.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "pcode", "serde", @@ -695,23 +423,17 @@ dependencies = [ [[package]] name = "sleigh-parse" version = "0.3.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" [[package]] name = "sleigh-runtime" version = "0.1.0" -source = "git+https://github.com/icicle-emu/icicle-emu#fe930922ea1ec39578ee545ccced61649f3da00a" +source = "git+https://github.com/momo5502/icicle-emu#70c9ed338d931da705a4a7a8ec2110cc677d970c" dependencies = [ "pcode", "sleigh-parse", ] -[[package]] -name = "slice-group-by" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" - [[package]] name = "smallvec" version = "1.15.0" @@ -817,122 +539,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasmtime-jit-debug" -version = "26.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02a0118d471de665565ed200bc56673eaa10cc8e223dfe2cef5d50ed0d9d143" -dependencies = [ - "object", - "rustix", - "wasmtime-versioned-export-macros", -] - -[[package]] -name = "wasmtime-jit-icache-coherence" -version = "26.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da47fba49af72581bc0dc67c8faaf5ee550e6f106e285122a184a675193701a5" -dependencies = [ - "anyhow", - "cfg-if", - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "wasmtime-versioned-export-macros" -version = "26.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8efb877c9e5e67239d4553bb44dd2a34ae5cfb728f3cf2c5e64439c6ca6ee7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "xml-rs" version = "0.8.25" diff --git a/src/backends/icicle-emulator/icicle-bridge/Cargo.toml b/src/backends/icicle-emulator/icicle-bridge/Cargo.toml index 8019c2b2..f74bf4cf 100644 --- a/src/backends/icicle-emulator/icicle-bridge/Cargo.toml +++ b/src/backends/icicle-emulator/icicle-bridge/Cargo.toml @@ -7,6 +7,6 @@ edition = "2024" crate-type = ["staticlib"] [dependencies] -icicle-vm = { git = "https://github.com/icicle-emu/icicle-emu" } -icicle-cpu = { git = "https://github.com/icicle-emu/icicle-emu" } -pcode = { git = "https://github.com/icicle-emu/icicle-emu" } +icicle-vm = { git = "https://github.com/momo5502/icicle-emu" } +icicle-cpu = { git = "https://github.com/momo5502/icicle-emu" } +pcode = { git = "https://github.com/momo5502/icicle-emu" } diff --git a/src/backends/icicle-emulator/icicle_x64_emulator.cpp b/src/backends/icicle-emulator/icicle_x64_emulator.cpp index d6296d76..46276f22 100644 --- a/src/backends/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/backends/icicle-emulator/icicle_x64_emulator.cpp @@ -25,8 +25,8 @@ extern "C" int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length); int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length); int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); - int32_t icicle_save_registers(icicle_emulator*, data_accessor_func* accessor, void* accessor_data); - int32_t icicle_restore_registers(icicle_emulator*, const void* data, size_t length); + void icicle_save_registers(icicle_emulator*, data_accessor_func* accessor, void* accessor_data); + void icicle_restore_registers(icicle_emulator*, const void* data, size_t length); uint32_t icicle_add_syscall_hook(icicle_emulator*, raw_func* callback, void* data); uint32_t icicle_add_interrupt_hook(icicle_emulator*, interrupt_func* callback, void* data); uint32_t icicle_add_execution_hook(icicle_emulator*, uint64_t address, ptr_func* callback, void* data); diff --git a/src/backends/unicorn-emulator/function_wrapper_tcg.hpp b/src/backends/unicorn-emulator/function_wrapper_tcg.hpp new file mode 100644 index 00000000..4cdaed8a --- /dev/null +++ b/src/backends/unicorn-emulator/function_wrapper_tcg.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include + +#include + +template +T resolve_indexed_argument_internal(const std::array& args, size_t& index) +{ + const auto a1 = args[index++]; + + if constexpr (sizeof(T) <= sizeof(a1) || sizeof(size_t) > 4) + { + return T(a1); + } + else + { + const auto a2 = args[index++]; + + const auto arg = (a1 | (static_cast(a2) << 32)); + return T(arg); + } +} + +template +T resolve_indexed_argument(const std::array& args, size_t& index) +{ + auto arg = resolve_indexed_argument_internal(args, index); + return arg; +} + +template +class function_wrapper_tcg : public utils::object +{ + public: + using user_data_pointer = void*; + using c_function_type = ReturnType(Args..., user_data_pointer); + using functor_type = std::function; + + function_wrapper_tcg() = default; + + function_wrapper_tcg(functor_type functor) + : functor_(std::make_unique(std::move(functor))) + { + } + + c_function_type* get_c_function() const + { + auto* func = +[](const size_t a1, const size_t a2, const size_t a3, const size_t a4, const size_t a5, + const size_t a6, const size_t a7, const size_t a8, const size_t a9, const size_t a10, + const size_t a11, const size_t a12) -> uint64_t { + const std::array arguments = {a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12}; + + const auto lambda = +[](Args... args, user_data_pointer user_data) -> ReturnType { + return (*static_cast(user_data))(std::forward(args)...); + }; + + size_t index = 0; + std::tuple func_args{ + resolve_indexed_argument>>(arguments, index)..., + resolve_indexed_argument(arguments, index)}; + + (void)index; + + if constexpr (!std::is_void_v) + { + return uint64_t(std::apply(lambda, std::move(func_args))); + } + + std::apply(lambda, std::move(func_args)); + return 0; + }; + + return reinterpret_cast(reinterpret_cast(func)); + } + + void* get_function() const + { + return reinterpret_cast(this->get_c_function()); + } + + user_data_pointer get_user_data() const + { + return this->functor_.get(); + } + + private: + std::unique_ptr functor_{}; +}; diff --git a/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp b/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp index 6c449b13..5be03b90 100644 --- a/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/backends/unicorn-emulator/unicorn_x64_emulator.cpp @@ -7,6 +7,7 @@ #include "unicorn_hook.hpp" #include "function_wrapper.hpp" +#include "function_wrapper_tcg.hpp" #include namespace unicorn @@ -385,10 +386,6 @@ namespace unicorn emulator_hook* hook_instruction(const int instruction_type, instruction_hook_callback callback) override { - function_wrapper wrapper([c = std::move(callback)](uc_engine*) { - return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0; - }); - unicorn_hook hook{*this}; auto container = std::make_unique(); @@ -396,18 +393,38 @@ namespace unicorn if (inst_type == x64_hookable_instructions::invalid) { + function_wrapper wrapper([c = std::move(callback)](uc_engine*) { + return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0; + }); + uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN_INVALID, wrapper.get_function(), wrapper.get_user_data(), 0, std::numeric_limits::max())); + container->add(std::move(wrapper), std::move(hook)); } - else + else if (inst_type == x64_hookable_instructions::syscall) { + function_wrapper wrapper([c = std::move(callback)](uc_engine*) { c(); }); + const auto uc_instruction = map_hookable_instruction(inst_type); uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN, wrapper.get_function(), wrapper.get_user_data(), 0, std::numeric_limits::max(), uc_instruction)); - } - container->add(std::move(wrapper), std::move(hook)); + container->add(std::move(wrapper), std::move(hook)); + } + else + { + function_wrapper wrapper([c = std::move(callback)](uc_engine*) { + return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0; + }); + + const auto uc_instruction = map_hookable_instruction(inst_type); + uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN, wrapper.get_function(), + wrapper.get_user_data(), 0, std::numeric_limits::max(), + uc_instruction)); + + container->add(std::move(wrapper), std::move(hook)); + } auto* result = container->as_opaque_hook(); @@ -533,7 +550,7 @@ namespace unicorn c(address); // }; - function_wrapper wrapper(std::move(exec_wrapper)); + function_wrapper_tcg wrapper(std::move(exec_wrapper)); unicorn_hook hook{*this}; diff --git a/src/common/platform/compiler.hpp b/src/common/platform/compiler.hpp index 5cece6a8..07fc82c2 100644 --- a/src/common/platform/compiler.hpp +++ b/src/common/platform/compiler.hpp @@ -13,6 +13,8 @@ #define OS_MAC #elif defined(__linux__) #define OS_LINUX +#elif defined(__EMSCRIPTEN__) +#define OS_EMSCRIPTEN #else #error "Unsupported platform" #endif diff --git a/src/common/platform/kernel_mapped.hpp b/src/common/platform/kernel_mapped.hpp index 931c5d35..221545fb 100644 --- a/src/common/platform/kernel_mapped.hpp +++ b/src/common/platform/kernel_mapped.hpp @@ -883,6 +883,7 @@ typedef struct _KERNEL_USER_TIMES struct THREAD_TLS_INFO { ULONG Flags; + uint32_t _Padding; union { diff --git a/src/common/platform/unicode.hpp b/src/common/platform/unicode.hpp index f76bac36..f9cf9561 100644 --- a/src/common/platform/unicode.hpp +++ b/src/common/platform/unicode.hpp @@ -8,6 +8,7 @@ struct UNICODE_STRING { USHORT Length; USHORT MaximumLength; + uint32_t _Padding; EMULATOR_CAST(typename Traits::PVOID, char16_t*) Buffer; }; diff --git a/src/windows-emulator-test/emulation_test_utils.hpp b/src/windows-emulator-test/emulation_test_utils.hpp index a399702c..d972de71 100644 --- a/src/windows-emulator-test/emulation_test_utils.hpp +++ b/src/windows-emulator-test/emulation_test_utils.hpp @@ -4,7 +4,7 @@ #include #include -#include "static_socket_factory.hpp" +#include #define ASSERT_NOT_TERMINATED(win_emu) \ do \ diff --git a/src/windows-emulator/logger.cpp b/src/windows-emulator/logger.cpp index ea4dc2ee..72e18404 100644 --- a/src/windows-emulator/logger.cpp +++ b/src/windows-emulator/logger.cpp @@ -6,16 +6,19 @@ namespace { #ifdef _WIN32 -#define COLOR(win, posix) win +#define COLOR(win, posix, web) win using color_type = WORD; +#elif defined(__EMSCRIPTEN__) +#define COLOR(win, posix, web) web + using color_type = const char*; #else -#define COLOR(win, posix) posix +#define COLOR(win, posix, web) posix using color_type = const char*; #endif color_type get_reset_color() { - return COLOR(7, "\033[0m"); + return COLOR(7, "\033[0m", ""); } color_type get_color_type(const color c) @@ -25,23 +28,23 @@ namespace switch (c) { case black: - return COLOR(0x8, "\033[0;90m"); + return COLOR(0x8, "\033[0;90m", ""); case red: - return COLOR(0xC, "\033[0;91m"); + return COLOR(0xC, "\033[0;91m", ""); case green: - return COLOR(0xA, "\033[0;92m"); + return COLOR(0xA, "\033[0;92m", ""); case yellow: - return COLOR(0xE, "\033[0;93m"); + return COLOR(0xE, "\033[0;93m", ""); case blue: - return COLOR(0x9, "\033[0;94m"); + return COLOR(0x9, "\033[0;94m", ""); case cyan: - return COLOR(0xB, "\033[0;96m"); + return COLOR(0xB, "\033[0;96m", ""); case pink: - return COLOR(0xD, "\033[0;95m"); + return COLOR(0xD, "\033[0;95m", ""); case white: - return COLOR(0xF, "\033[0;97m"); + return COLOR(0xF, "\033[0;97m", ""); case dark_gray: - return COLOR(0x8, "\033[0;97m"); + return COLOR(0x8, "\033[0;97m", ""); case gray: default: return get_reset_color(); diff --git a/src/windows-emulator/module/module_mapping.cpp b/src/windows-emulator/module/module_mapping.cpp index 84c3ccd0..8f433809 100644 --- a/src/windows-emulator/module/module_mapping.cpp +++ b/src/windows-emulator/module/module_mapping.cpp @@ -259,7 +259,7 @@ mapped_module map_module_from_file(memory_manager& memory, std::filesystem::path const auto data = utils::io::read_file(file); if (data.empty()) { - throw std::runtime_error("Bad file data"); + throw std::runtime_error("Bad file data: " + file.string()); } return map_module_from_data(memory, data, std::move(file)); diff --git a/src/windows-emulator-test/static_socket_factory.cpp b/src/windows-emulator/network/static_socket_factory.cpp similarity index 100% rename from src/windows-emulator-test/static_socket_factory.cpp rename to src/windows-emulator/network/static_socket_factory.cpp diff --git a/src/windows-emulator-test/static_socket_factory.hpp b/src/windows-emulator/network/static_socket_factory.hpp similarity index 73% rename from src/windows-emulator-test/static_socket_factory.hpp rename to src/windows-emulator/network/static_socket_factory.hpp index 6f162869..5b27faef 100644 --- a/src/windows-emulator-test/static_socket_factory.hpp +++ b/src/windows-emulator/network/static_socket_factory.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "socket_factory.hpp" namespace network { diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 4cb8b45f..99aef9cf 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -16,6 +16,8 @@ #include "exception_dispatch.hpp" #include "apiset/apiset.hpp" +#include "network/static_socket_factory.hpp" + constexpr auto MAX_INSTRUCTIONS_PER_TIME_SLICE = 100000; namespace @@ -257,7 +259,11 @@ namespace return std::move(interfaces.socket_factory); } +#ifdef OS_EMSCRIPTEN + return network::create_static_socket_factory(); +#else return std::make_unique(); +#endif } }