mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Fixes for emscripten
This commit is contained in:
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -161,6 +161,7 @@ jobs:
|
|||||||
- iOS arm64
|
- iOS arm64
|
||||||
- Android x86_64
|
- Android x86_64
|
||||||
- Android arm64-v8a
|
- Android arm64-v8a
|
||||||
|
- Emscripten
|
||||||
configuration:
|
configuration:
|
||||||
- Debug
|
- Debug
|
||||||
- Release
|
- Release
|
||||||
@@ -201,6 +202,9 @@ jobs:
|
|||||||
abi: arm64-v8a
|
abi: arm64-v8a
|
||||||
rust-target: aarch64-linux-android
|
rust-target: aarch64-linux-android
|
||||||
cmake-options: "-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchain/android-ndk.cmake"
|
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:
|
steps:
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -214,6 +218,10 @@ jobs:
|
|||||||
if: "${{ matrix.rust-target }}"
|
if: "${{ matrix.rust-target }}"
|
||||||
run: rustup target add ${{ 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
|
- name: Install Clang
|
||||||
if: "${{ matrix.platform == 'Linux x86_64 Clang' }}"
|
if: "${{ matrix.platform == 'Linux x86_64 Clang' }}"
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -2,7 +2,7 @@
|
|||||||
path = deps/unicorn
|
path = deps/unicorn
|
||||||
url = ../unicorn.git
|
url = ../unicorn.git
|
||||||
shallow = true
|
shallow = true
|
||||||
branch = dev
|
branch = wasm
|
||||||
[submodule "deps/reflect"]
|
[submodule "deps/reflect"]
|
||||||
path = deps/reflect
|
path = deps/reflect
|
||||||
url = https://github.com/qlibs/reflect.git
|
url = https://github.com/qlibs/reflect.git
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
|||||||
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
|
||||||
if(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
|
if(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
|
||||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
||||||
endif()
|
endif()
|
||||||
@@ -49,6 +51,9 @@ if(UNIX)
|
|||||||
momo_add_c_and_cxx_compile_options(
|
momo_add_c_and_cxx_compile_options(
|
||||||
-fvisibility=hidden
|
-fvisibility=hidden
|
||||||
-ftrivial-auto-var-init=zero
|
-ftrivial-auto-var-init=zero
|
||||||
|
#-Wbad-function-cast
|
||||||
|
#-Wcast-function-type
|
||||||
|
-Wno-int-conversion
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -86,6 +91,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)
|
if(MSVC)
|
||||||
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
string(REPLACE "/EHs" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
string(REPLACE "/EHs" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
|
|||||||
6
deps/CMakeLists.txt
vendored
6
deps/CMakeLists.txt
vendored
@@ -1,7 +1,5 @@
|
|||||||
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
set(UNICORN_ARCH "x86" CACHE STRING "")
|
||||||
set(UNICORN_ARCH "x86" CACHE STRING "")
|
add_subdirectory(unicorn)
|
||||||
add_subdirectory(unicorn)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
|
|
||||||
|
|||||||
2
deps/unicorn
vendored
2
deps/unicorn
vendored
Submodule deps/unicorn updated: 73be28b650...b29e3445a4
@@ -1,6 +1,4 @@
|
|||||||
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
add_subdirectory(unicorn-emulator)
|
||||||
add_subdirectory(unicorn-emulator)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (MOMO_ENABLE_RUST_CODE)
|
if (MOMO_ENABLE_RUST_CODE)
|
||||||
add_subdirectory(icicle-emulator)
|
add_subdirectory(icicle-emulator)
|
||||||
|
|||||||
88
src/backends/unicorn-emulator/function_wrapper2.hpp
Normal file
88
src/backends/unicorn-emulator/function_wrapper2.hpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <utils/object.hpp>
|
||||||
|
|
||||||
|
uint32_t resolve_indexed_argument_part(uint32_t* args, size_t& index)
|
||||||
|
{
|
||||||
|
return args[index++];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T resolve_indexed_argument_internal(uint32_t* args, size_t& index)
|
||||||
|
{
|
||||||
|
const auto a1 = resolve_indexed_argument_part(args, index);
|
||||||
|
|
||||||
|
if(sizeof(T) <= sizeof(a1)) {
|
||||||
|
return (T)a1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto a2 = resolve_indexed_argument_part(args, index);
|
||||||
|
|
||||||
|
const auto arg = (a1 | ((uint64_t)a2 << 32));
|
||||||
|
return (T)arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T resolve_indexed_argument(uint32_t* args, size_t& index)
|
||||||
|
{
|
||||||
|
auto arg = resolve_indexed_argument_internal<T>(args, index);
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ReturnType, typename... Args>
|
||||||
|
class function_wrapper2 : public utils::object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using user_data_pointer = void*;
|
||||||
|
using c_function_type = ReturnType(Args..., user_data_pointer);
|
||||||
|
using functor_type = std::function<ReturnType(Args...)>;
|
||||||
|
|
||||||
|
function_wrapper2() = default;
|
||||||
|
|
||||||
|
function_wrapper2(functor_type functor)
|
||||||
|
: functor_(std::make_unique<functor_type>(std::move(functor)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
c_function_type* get_c_function() const
|
||||||
|
{
|
||||||
|
return (c_function_type*)(void*)+[](uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,uint32_t a5,uint32_t a6,uint32_t a7,uint32_t a8,uint32_t a9,uint32_t a10,uint32_t a11,uint32_t a12)-> uint64_t {
|
||||||
|
|
||||||
|
uint32_t real_args[] {
|
||||||
|
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<functor_type*>(user_data))(std::forward<Args>(args)...);
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
std::tuple<Args..., user_data_pointer> func_args{resolve_indexed_argument<std::remove_cv_t<std::remove_reference_t<Args>>>(real_args, index)..., resolve_indexed_argument<user_data_pointer>(real_args, index)};
|
||||||
|
|
||||||
|
(void)index;
|
||||||
|
|
||||||
|
if constexpr(!std::is_void_v<ReturnType>){
|
||||||
|
return (uint64_t)std::apply(lambda, std::move(func_args));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::apply(lambda, std::move(func_args));
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void* get_function() const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(this->get_c_function());
|
||||||
|
}
|
||||||
|
|
||||||
|
user_data_pointer get_user_data() const
|
||||||
|
{
|
||||||
|
return this->functor_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<functor_type> functor_{};
|
||||||
|
};
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "unicorn_hook.hpp"
|
#include "unicorn_hook.hpp"
|
||||||
|
|
||||||
#include "function_wrapper.hpp"
|
#include "function_wrapper.hpp"
|
||||||
|
#include "function_wrapper2.hpp"
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
namespace unicorn
|
namespace unicorn
|
||||||
@@ -385,10 +386,7 @@ namespace unicorn
|
|||||||
|
|
||||||
emulator_hook* hook_instruction(const int instruction_type, instruction_hook_callback callback) override
|
emulator_hook* hook_instruction(const int instruction_type, instruction_hook_callback callback) override
|
||||||
{
|
{
|
||||||
function_wrapper<int, uc_engine*> wrapper([c = std::move(callback)](uc_engine*) {
|
|
||||||
return (c() == instruction_hook_continuation::skip_instruction) ? 1 : 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
unicorn_hook hook{*this};
|
unicorn_hook hook{*this};
|
||||||
auto container = std::make_unique<hook_container>();
|
auto container = std::make_unique<hook_container>();
|
||||||
|
|
||||||
@@ -396,18 +394,39 @@ namespace unicorn
|
|||||||
|
|
||||||
if (inst_type == x64_hookable_instructions::invalid)
|
if (inst_type == x64_hookable_instructions::invalid)
|
||||||
{
|
{
|
||||||
|
function_wrapper<int, uc_engine*> 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(),
|
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN_INVALID, wrapper.get_function(),
|
||||||
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
|
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max()));
|
||||||
}
|
container->add(std::move(wrapper), std::move(hook));
|
||||||
else
|
}
|
||||||
{
|
else if(inst_type == x64_hookable_instructions::syscall){
|
||||||
|
function_wrapper<void, uc_engine*> wrapper([c = std::move(callback)](uc_engine*) {
|
||||||
|
c();
|
||||||
|
});
|
||||||
|
|
||||||
const auto uc_instruction = map_hookable_instruction(inst_type);
|
const auto uc_instruction = map_hookable_instruction(inst_type);
|
||||||
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN, wrapper.get_function(),
|
uce(uc_hook_add(*this, hook.make_reference(), UC_HOOK_INSN, wrapper.get_function(),
|
||||||
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max(),
|
wrapper.get_user_data(), 0, std::numeric_limits<pointer_type>::max(),
|
||||||
uc_instruction));
|
uc_instruction));
|
||||||
}
|
|
||||||
|
|
||||||
container->add(std::move(wrapper), std::move(hook));
|
container->add(std::move(wrapper), std::move(hook));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
function_wrapper<int, uc_engine*> 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<pointer_type>::max(),
|
||||||
|
uc_instruction));
|
||||||
|
|
||||||
|
container->add(std::move(wrapper), std::move(hook));
|
||||||
|
}
|
||||||
|
|
||||||
auto* result = container->as_opaque_hook();
|
auto* result = container->as_opaque_hook();
|
||||||
|
|
||||||
@@ -533,7 +552,7 @@ namespace unicorn
|
|||||||
c(address); //
|
c(address); //
|
||||||
};
|
};
|
||||||
|
|
||||||
function_wrapper<void, uc_engine*, uint64_t, uint32_t> wrapper(std::move(exec_wrapper));
|
function_wrapper2<void, uc_engine*, uint64_t, uint32_t> wrapper(std::move(exec_wrapper));
|
||||||
|
|
||||||
unicorn_hook hook{*this};
|
unicorn_hook hook{*this};
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,9 @@ if(NOT MOMO_ENABLE_CLANG_TIDY)
|
|||||||
target_precompile_headers(windows-emulator PRIVATE std_include.hpp)
|
target_precompile_headers(windows-emulator PRIVATE std_include.hpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
|
||||||
target_link_libraries(windows-emulator PRIVATE
|
target_link_libraries(windows-emulator PRIVATE
|
||||||
unicorn-emulator
|
unicorn-emulator
|
||||||
)
|
)
|
||||||
endif()
|
|
||||||
|
|
||||||
if (MOMO_ENABLE_RUST_CODE)
|
if (MOMO_ENABLE_RUST_CODE)
|
||||||
target_link_libraries(windows-emulator PRIVATE
|
target_link_libraries(windows-emulator PRIVATE
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
#include "cpu_context.hpp"
|
#include "cpu_context.hpp"
|
||||||
|
|
||||||
#ifndef OS_EMSCRIPTEN
|
|
||||||
#include <unicorn_x64_emulator.hpp>
|
#include <unicorn_x64_emulator.hpp>
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MOMO_ENABLE_RUST_CODE
|
#if MOMO_ENABLE_RUST_CODE
|
||||||
#include <icicle_x64_emulator.hpp>
|
#include <icicle_x64_emulator.hpp>
|
||||||
@@ -265,10 +263,6 @@ namespace
|
|||||||
|
|
||||||
std::unique_ptr<x64_emulator> create_default_x64_emulator()
|
std::unique_ptr<x64_emulator> create_default_x64_emulator()
|
||||||
{
|
{
|
||||||
#ifdef OS_EMSCRIPTEN
|
|
||||||
return icicle::create_x64_emulator();
|
|
||||||
#else
|
|
||||||
|
|
||||||
#if MOMO_ENABLE_RUST_CODE
|
#if MOMO_ENABLE_RUST_CODE
|
||||||
const auto* env = getenv("EMULATOR_ICICLE");
|
const auto* env = getenv("EMULATOR_ICICLE");
|
||||||
if (env && (env == "1"sv || env == "true"sv))
|
if (env && (env == "1"sv || env == "true"sv))
|
||||||
@@ -276,8 +270,8 @@ std::unique_ptr<x64_emulator> create_default_x64_emulator()
|
|||||||
return icicle::create_x64_emulator();
|
return icicle::create_x64_emulator();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return unicorn::create_x64_emulator();
|
return unicorn::create_x64_emulator();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
windows_emulator::windows_emulator(application_settings app_settings, const emulator_settings& settings,
|
windows_emulator::windows_emulator(application_settings app_settings, const emulator_settings& settings,
|
||||||
|
|||||||
Reference in New Issue
Block a user