From c4e8aa47b451d52ed635f33c48f509140f8337c9 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 23 Apr 2025 12:31:37 +0200 Subject: [PATCH 01/17] Prepare web debugger --- cmake/compiler-env.cmake | 1 + page/public/emulator-worker.js | 4 + src/CMakeLists.txt | 1 + src/debugger/CMakeLists.txt | 23 +++++ src/debugger/main.cpp | 153 ++++++++++++++++++++++++++++++++ src/debugger/resource.rc | 101 +++++++++++++++++++++ src/debugger/resources/icon.ico | Bin 0 -> 5072 bytes src/debugger/std_include.hpp | 31 +++++++ 8 files changed, 314 insertions(+) create mode 100644 src/debugger/CMakeLists.txt create mode 100644 src/debugger/main.cpp create mode 100644 src/debugger/resource.rc create mode 100644 src/debugger/resources/icon.ico create mode 100644 src/debugger/std_include.hpp diff --git a/cmake/compiler-env.cmake b/cmake/compiler-env.cmake index d582dd00..8da06684 100644 --- a/cmake/compiler-env.cmake +++ b/cmake/compiler-env.cmake @@ -92,6 +92,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Emscripten") momo_add_c_and_cxx_compile_options( -fexceptions -ftrivial-auto-var-init=zero + -Wno-dollar-in-identifier-extension ) add_link_options( diff --git a/page/public/emulator-worker.js b/page/public/emulator-worker.js index 4bead2a3..02ee4e87 100644 --- a/page/public/emulator-worker.js +++ b/page/public/emulator-worker.js @@ -32,6 +32,10 @@ function notifyExit(code) { self.close(); } +function getMessageFromQueue() { + return ""; +} + function runEmulation(filesystem, file, options) { globalThis.Module = { arguments: [...options, "-e", "./root", file], diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4492d05c..870f20e1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,7 @@ momo_targets_set_folder("backends" ${BACKEND_TARGETS}) if (NOT MOMO_BUILD_AS_LIBRARY) add_subdirectory(analyzer) + add_subdirectory(debugger) add_subdirectory(fuzzing-engine) add_subdirectory(fuzzer) add_subdirectory(windows-emulator-test) diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt new file mode 100644 index 00000000..ac49ed03 --- /dev/null +++ b/src/debugger/CMakeLists.txt @@ -0,0 +1,23 @@ +file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS + *.cpp + *.hpp + *.rc +) + +list(SORT SRC_FILES) + +add_executable(debugger ${SRC_FILES}) + +momo_assign_source_group(${SRC_FILES}) + +if(NOT MOMO_ENABLE_CLANG_TIDY) + target_precompile_headers(debugger PRIVATE std_include.hpp) +endif() + +target_link_libraries(debugger PRIVATE + windows-emulator +) + +set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT debugger) + +momo_strip_target(debugger) diff --git a/src/debugger/main.cpp b/src/debugger/main.cpp new file mode 100644 index 00000000..ef857bed --- /dev/null +++ b/src/debugger/main.cpp @@ -0,0 +1,153 @@ +#include "std_include.hpp" + +#include +#include + +#ifdef OS_EMSCRIPTEN +#include +#endif + +namespace +{ + void suspend_execution(const std::chrono::milliseconds ms = 0ms) + { +#ifdef OS_EMSCRIPTEN + emscripten_sleep(static_cast(ms.count())); +#else + if (ms > 0ms) + { + std::this_thread::sleep_for(ms); + } + else + { + std::this_thread::yield(); + } +#endif + } + + void sendMessage(const std::string& message) + { +#ifdef OS_EMSCRIPTEN + EM_ASM_( + { + // JavaScript code to handle the message + console.log('Received message from C++: ' + UTF8ToString($0)); + // You can post the message to a message queue or handle it as needed + }, + message.c_str()); +#else + (void)message; +#endif + } + + // Function to receive a message from JavaScript + std::string receiveMessage() + { + /*#ifdef OS_EMSCRIPTEN + // Allocate a buffer to receive the message + char* buffer = (char*)malloc(256); // Adjust size as needed + EM_ASM_( + { + // JavaScript code to retrieve the message + var message = getMessageFromQueue(); // Implement this function in JavaScript + if (message && message.length > 0) + { + stringToUTF8($0, _malloc(lengthBytesUTF8(message) + 1), lengthBytesUTF8(message) + 1); + } + }, + buffer); + + std::string result(buffer); + free(buffer); + return result; + #else*/ + return {}; + // #endif + } + + bool run_emulation(windows_emulator& win_emu) + { + try + { + win_emu.start(); + } + catch (const std::exception& e) + { + win_emu.log.error("Emulation failed at: 0x%" PRIx64 " - %s\n", win_emu.emu().read_instruction_pointer(), + e.what()); + throw; + } + catch (...) + { + win_emu.log.error("Emulation failed at: 0x%" PRIx64 "\n", win_emu.emu().read_instruction_pointer()); + throw; + } + + const auto exit_status = win_emu.process.exit_status; + if (!exit_status.has_value()) + { + win_emu.log.error("Emulation terminated without status!\n"); + return false; + } + + const auto success = *exit_status == STATUS_SUCCESS; + + win_emu.log.disable_output(false); + win_emu.log.print(success ? color::green : color::red, "Emulation terminated with status: %X\n", *exit_status); + + return success; + } + + bool run() + { + (void)&run_emulation; + + for (size_t i = 0; i < 10; ++i) + { + sendMessage("PING"); + + while (true) + { + suspend_execution(0ms); + const auto message = receiveMessage(); + if (message.empty()) + { + puts("EMPTY MSG"); + break; + } + + puts(message.c_str()); + } + + suspend_execution(1s); + } + + return true; + } +} + +int main(const int, char**) +{ + try + { + const auto result = run(); + 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; +} + +#ifdef _WIN32 +int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int) +{ + return main(__argc, __argv); +} +#endif diff --git a/src/debugger/resource.rc b/src/debugger/resource.rc new file mode 100644 index 00000000..8da94cc0 --- /dev/null +++ b/src/debugger/resource.rc @@ -0,0 +1,101 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +2 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "momo5502" + VALUE "FileDescription", "Windows Emulator" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "emulator" + VALUE "LegalCopyright", "All rights reserved." + VALUE "OriginalFilename", "emulator.exe" + VALUE "ProductName", "emulator" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// Binary Data +// + +GLFW_ICON ICON "resources/icon.ico" + + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/debugger/resources/icon.ico b/src/debugger/resources/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b4afb19bf6e0a5ed68896c8e8ddb6c26805835d9 GIT binary patch literal 5072 zcmZQzU}Ruq00Bk@1%_S13=Con3=EwCe(t(JJtJ()9vmT+dV&U=-i*@=AZwb`)~hw{>)iY zEdov)iqs=Q_v+Q|``9wk-`v;s_sM0f@pVfqe^2M%l4D<$c6y!v-MhPX-}j$uoxs+> zXU+CDVoUO+zO(E9?6EZdBJQi-KjV7IZrR;g|3jAQRqcDZJHCF;&))qz_NS)L=XjIS zpm1Yj_VEw)Huv^?sn$1%UGXh+N$E@D+x@?u%~_V-w{!i{z`c(dP95C%eY?pmL%Ubv zxBEhV>l#UY{d4X-Z|$O&p|9OmmJ2wjZb+_uG1+&0%%9V9kFWTvewpRDoncMh=e_NB zZ{J#VPmzI(Z|CyT?;DoSnm231f!d(A$Gc8hzpnp!q`fRR^gTm^M!}gW$Q31JFZaX+;m#LocZm) z6}xsYTs;sjcQ@4hRp#~hx3?#qI8*=W@Y&f{U0GMC`OVy$9elODA@=3}-R|XU!^DLb zNNtQO4&`T;_{`k$Sbly+)S7RF3cWM7f95Ow$nfaEhn>B~SL*b<%KVEz#NK(utik$h z>Baq7|EjmH=bqI2d*&17fGEGJ6-y89S^BMfy;Z*7G^Xvc3RnvD>?e*?Gx$WWKo&SGS{l7nHU(Jd*zWv*`e*KhQUgP%mb6)AU z$-dmFth4srHb3V$J$+ZY&oT2!fA1gBl}~Eio8$8KvtH`?&!?aLsBV)exZ7?!J6)bF z=6_k&>eMw)w^tbE_+7Tydf)nFT3e_2{Ct&X z>{!Vgb@z08MbbR!%@<^sf7`$JQTD1$0$1<3rgJbj{`|IQZt#_V>o;DP*6vOaPHvJ~ z@!yvDRV|mzSP4L>&?Kcwr@2&b9fBFBp4B4K4kGDK7&h5Y4cXnH1 z|K)pAwC_IN6}qRUgP+;v{mQ@bi}jcsCI$YU&%hwC=$kzwgM!Q3dL{;kj$8j(7#ak& z{^w+1P|W%-%)sDu<)1nOL(7W4{tOHpBx#5bo_*Gu;lctM8Bel%U>a5!`0K{J*PFBD zQf=Ln{5uO4uK#gk{@e88J@wtceO0O}Qe~^w%{%`hYn&`j( zy|;fY%m%AykbHGIS*$#JPv0D~s*TY>yO*ZC-ky5Xh&y)w)~Nz3ctC+Cdf?oi)>-T4 z2J6@ERZ&bhy&+X}_rLu6n}XuDtAK(fAT1~6Zt(Wq>VEs4e9!x6EzcVFJ?Q+O`rsoo z_dhO3c$Xa`tYHo^DD_#Br#7>sK@LZYVZHVJzk+)kiWYyfXADSt!&NOI%qGdl^7dPK z%8AzfQ?Kj41I5*piRDI?|IMN!l*KL!YaE@qUp9MpZu73bLbtc|ObdFJ82`M)a^OO% zUgE$q|6t+z zU$+;mOP&Kt1{%i4V+9I05|;hno~l=Rare6gr;Qso-1nXP-|c~c#3$J{hNobw&csAK zaXoOwe($p&Uhp$X?-!n4`#|?{_VEkXyRx{&8Bh1$`p@DpQ}c(}g75Wjdh*kB zXMVK)#<3^Bvp3@1+ST6^JL{zjF0xhrebfh1$hzU>R$Hle^TjLge*Jzb?T?>h!N=-< zR@GUTPefb(4rki>pR<80;d0jQ*m0Am^4HO=*RF}Ke*Lu6n+X)E zqKi&fe}1m}u{Wad^ZTXemY$2>6+hd{lvR?;85BrOZ>sz6^(;58YgcT%tNFw2$I9aY zHeh|noF24X)c&)1{jDFrzp=FSMD_h-1qFJ@jGy_}b}O$t<#yo9@6Rs_CBHu^I`(%e zI2@Yxe04nc_iM}6qRr*UHHEM53N7{dyH*8k-jid;?WWA$V}8v3X+O1+=}YG`rFbA6b>o334VTy8c%C$`9F{pAz*`p>_HVNO~0kC~OW zUpe~ZB5NQ2FZ=hV>D+b3rg+RJ^+wj(d-nq!L5ZCCs9()XW8FV% z_pRb>$Xv@Rz5m8?jmh8?Z7w3k^3){a3iE>P-xB}a0~I+hTJJqOAj~lLdgO`VNf+8c z>Atb#y0QX;#p8CcaUND|jEoH*4};29feGIfJgOKH{uF>xWQ)p6#s%x@w}J{y0U;)b z{rsyWLFL2*0ft|-0cSxPy(XuoIy z`zfq$Lh*mYV&{v&jaS)LFZ*^grmOp3dGr67C13ybae;F4O|#GQ3vcgQWgfA0%lk7Y zUvo6-FbYWit4;f$|K06k!qp3QuQ^wIuNDdTZU2!mA^D$y{=S}72N&J5ljgf&lKu5x z_~LK%kC+eW{WuCzyzjJ}$2aLl&IXQz@D-1mRpwVF2umnFl&QzgPnb*Zw|wkpYIRd zHs#_%+~abcs~E0y_y>t3m!~acHr$J zGX+Kg$($gs3(Py;*XMfYFnpQ2MYmx0n{TVD_PaBJnhgB2r~SHm^58P2@4I*I@n>wP1ihg~%ky#dPEH=0`;zOr=5^6~6QEKXuhc))wKHs)$pc6!~J|No&8 zvDD1@?79GPBX@<;r&0fnBRzQ^X9h)x;>P8i=VyfNd(9BY+hDvr|5@$D=huQR22uk3f z{npOsNa-(pVcBeYeReE zE+x~v*pqr3Zi)=Qe6mYduJ#I--yPt=A;2*4;5o0QRy%HMUUhZ~C^H#zs5Gqd+~j~e0VLx4YMhW&CFzG>~G3u0++U@3cua&7T2j&|GP1Z zS>X(~Jy#;ndKP7dD|4z&-`XViguVCVu6_2m0!tYaa<^@pzS(T~-Cbe({$E}3cm59s zi(j`s$vtV~HSC+aac>sWgUy%AcQ_`Wj-P%$=6G}?xLE%4^6FFT3*YB*O#XJQ)U)Au zo3byV#NB;xZ10xK=E+N$9vI}uhF89h`Bdlppsby@$@~5DH~FA6 zn{s;|^9I9e)!zFPQ|C$M*HpGk8?9cN!505^b@{gUnU+ew4xwFgTcdx!z z`)``>yART4I}To7SI*ua{hDu6^;fxX>Az?Gygvo->=XMxVo>=)z$;v5R+ zQi{x1*4|qimL|=%+<52NPfCnOCf#X&zkj}U#M{quQ`eoY_m9_TkeGBbcEz{y^+o6Y zcAASssOXD1^mwFyT0d+1m4A93?^C7ip0_$Q@5*2(RG54A>HV{2GONFp27VHH9aH*{ z;n4x>(x3IAzbz+Rnt7-H>QUwuX?r&RPubefeEOKq)|q#hUnwz#Xl}OUuXTF+I3Q}* z71;^rp3U!eFl1cSnSRDP>;E(t?m53xa?Q%)S-Q9cD&K_0Z#1mm{pX>BS^4f=I~W3w z#;r+C{e*_j*YFG5Z*ES=Mf2&HlMt1+pFR~ z*{iiyhR!zQ{nAz3dtEe2^}Zv+(*G|GdkNE6hE+|Kh^0Z-H%TXYH^q<@;^ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +// NOLINTNEXTLINE(google-global-names-in-headers) +using namespace std::literals; From 1beb95c2b2aedc654f0b34e7b12ea90b1bc51e74 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 23 Apr 2025 15:13:18 +0200 Subject: [PATCH 02/17] Support thread-switch callback --- src/debugger/main.cpp | 127 +++++++++++++--------- src/windows-emulator/process_context.hpp | 1 + src/windows-emulator/windows_emulator.cpp | 1 + 3 files changed, 78 insertions(+), 51 deletions(-) diff --git a/src/debugger/main.cpp b/src/debugger/main.cpp index ef857bed..d47b87cd 100644 --- a/src/debugger/main.cpp +++ b/src/debugger/main.cpp @@ -7,6 +7,8 @@ #include #endif +#include + namespace { void suspend_execution(const std::chrono::milliseconds ms = 0ms) @@ -25,44 +27,65 @@ namespace #endif } - void sendMessage(const std::string& message) + void send_message(const std::string& message) { #ifdef OS_EMSCRIPTEN - EM_ASM_( - { - // JavaScript code to handle the message - console.log('Received message from C++: ' + UTF8ToString($0)); - // You can post the message to a message queue or handle it as needed - }, - message.c_str()); + // clang-format off + EM_ASM_({ + handleMessage(UTF8ToString($0)); + }, message.c_str()); + // clang-format on #else (void)message; #endif } - // Function to receive a message from JavaScript - std::string receiveMessage() + std::string receive_message() { - /*#ifdef OS_EMSCRIPTEN - // Allocate a buffer to receive the message - char* buffer = (char*)malloc(256); // Adjust size as needed - EM_ASM_( - { - // JavaScript code to retrieve the message - var message = getMessageFromQueue(); // Implement this function in JavaScript - if (message && message.length > 0) - { - stringToUTF8($0, _malloc(lengthBytesUTF8(message) + 1), lengthBytesUTF8(message) + 1); - } - }, - buffer); +#ifdef OS_EMSCRIPTEN + // clang-format off + auto* ptr = EM_ASM_PTR({ + var message = getMessageFromQueue(); + if (!message || message.length == 0) + { + return null; + } - std::string result(buffer); - free(buffer); - return result; - #else*/ + const length = lengthBytesUTF8(message) + 1; + const buffer = _malloc(length); + stringToUTF8(message, buffer, length); + return buffer; + }); + // clang-format on + + if (!ptr) + { + return {}; + } + + const auto _ = utils::finally([&] { + free(ptr); // + }); + + return {reinterpret_cast(ptr)}; +#else return {}; - // #endif +#endif + } + + void handle_messages() + { + while (true) + { + suspend_execution(0ms); + const auto message = receive_message(); + if (message.empty()) + { + break; + } + + puts(message.c_str()); + } } bool run_emulation(windows_emulator& win_emu) @@ -98,39 +121,41 @@ namespace return success; } - bool run() + bool run(const int argc, char** argv) { - (void)&run_emulation; - - for (size_t i = 0; i < 10; ++i) + if (argc < 3) { - sendMessage("PING"); - - while (true) - { - suspend_execution(0ms); - const auto message = receiveMessage(); - if (message.empty()) - { - puts("EMPTY MSG"); - break; - } - - puts(message.c_str()); - } - - suspend_execution(1s); + return false; } - return true; + const emulator_settings settings{ + .emulation_root = argv[1], + }; + + application_settings app_settings{ + .application = argv[2], + }; + + for (int i = 3; i < argc; ++i) + { + app_settings.arguments.push_back(u8_to_u16(argv[i])); + } + + windows_emulator win_emu{app_settings, settings}; + + win_emu.callbacks.on_thread_switch = [&] { + handle_messages(); // + }; + + return run_emulation(win_emu); } } -int main(const int, char**) +int main(const int argc, char** argv) { try { - const auto result = run(); + const auto result = run(argc, argv); return result ? 0 : 1; } catch (std::exception& e) diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 293b7d03..e4dca5fe 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -34,6 +34,7 @@ struct process_context { utils::optional_function on_create_thread{}; utils::optional_function on_thread_terminated{}; + utils::optional_function on_thread_switch{}; }; struct atom_entry diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index c5f90080..037acb66 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -169,6 +169,7 @@ namespace } thread.apc_alertable = false; + win_emu.callbacks.on_thread_switch(); return true; } From 6a302aff691a85776377d1b8017284ed92a1ebab Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 23 Apr 2025 15:30:36 +0200 Subject: [PATCH 03/17] Add nlohmann json --- .gitmodules | 4 ++++ deps/CMakeLists.txt | 4 ++++ deps/json | 1 + src/debugger/CMakeLists.txt | 1 + src/debugger/main.cpp | 28 +++++++++++++++++++++++----- 5 files changed, 33 insertions(+), 5 deletions(-) create mode 160000 deps/json diff --git a/.gitmodules b/.gitmodules index ce0fdeaf..5571083f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,3 +18,7 @@ [submodule "deps/gtest-parallel"] path = deps/gtest-parallel url = https://github.com/google/gtest-parallel.git +[submodule "deps/json"] + path = deps/json + url = https://github.com/nlohmann/json.git + branch = master diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 5ed0c395..28155aed 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -3,6 +3,10 @@ add_subdirectory(unicorn) ########################################## +add_subdirectory(json) + +########################################## + add_library(reflect INTERFACE) target_include_directories(reflect INTERFACE "${CMAKE_CURRENT_LIST_DIR}/reflect" diff --git a/deps/json b/deps/json new file mode 160000 index 00000000..55f93686 --- /dev/null +++ b/deps/json @@ -0,0 +1 @@ +Subproject commit 55f93686c01528224f448c19128836e7df245f72 diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt index ac49ed03..bc63c072 100644 --- a/src/debugger/CMakeLists.txt +++ b/src/debugger/CMakeLists.txt @@ -16,6 +16,7 @@ endif() target_link_libraries(debugger PRIVATE windows-emulator + nlohmann_json ) set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT debugger) diff --git a/src/debugger/main.cpp b/src/debugger/main.cpp index d47b87cd..2cfcab79 100644 --- a/src/debugger/main.cpp +++ b/src/debugger/main.cpp @@ -2,6 +2,7 @@ #include #include +#include #ifdef OS_EMSCRIPTEN #include @@ -73,18 +74,35 @@ namespace #endif } - void handle_messages() + void send_object(const nlohmann::json& json) + { + const std::string res = json.dump(); + send_message(res); + } + + nlohmann::json receive_object() + { + auto message = receive_message(); + if (message.empty()) + { + return {}; + } + + return nlohmann::json::parse(message); + } + + void handle_messages(windows_emulator& win_emu) { while (true) { suspend_execution(0ms); - const auto message = receive_message(); - if (message.empty()) + const auto message = receive_object(); + if (message.is_null()) { break; } - puts(message.c_str()); + puts(message.dump().c_str()); } } @@ -144,7 +162,7 @@ namespace windows_emulator win_emu{app_settings, settings}; win_emu.callbacks.on_thread_switch = [&] { - handle_messages(); // + handle_messages(win_emu); // }; return run_emulation(win_emu); From 1c671da64101d46851d71ba44107442c13913a24 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 27 Apr 2025 17:52:29 +0200 Subject: [PATCH 04/17] Progress --- .gitignore | 2 ++ deps/json | 1 - page/public/emulator-worker.js | 22 ++++++++++++++++++---- 3 files changed, 20 insertions(+), 5 deletions(-) delete mode 160000 deps/json diff --git a/.gitignore b/.gitignore index 6f8dbfac..09cf68f5 100644 --- a/.gitignore +++ b/.gitignore @@ -150,4 +150,6 @@ user*.bat page/public/analyzer.js page/public/analyzer.wasm +page/public/debugger.js +page/public/debugger.wasm page/public/root.zip diff --git a/deps/json b/deps/json deleted file mode 160000 index 55f93686..00000000 --- a/deps/json +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 55f93686c01528224f448c19128836e7df245f72 diff --git a/page/public/emulator-worker.js b/page/public/emulator-worker.js index 02ee4e87..e795f184 100644 --- a/page/public/emulator-worker.js +++ b/page/public/emulator-worker.js @@ -32,15 +32,29 @@ function notifyExit(code) { self.close(); } +var msgQueue = []; + +setInterval(() => { + msgQueue.push("OI YEAH BABY :D"); +}, 2100); + +function handleMessage(message) { + console.log("MSG from C++: " + message); +} + function getMessageFromQueue() { - return ""; + if(msgQueue.length == 0){ + return ""; + } + + return msgQueue.pop(); } function runEmulation(filesystem, file, options) { globalThis.Module = { arguments: [...options, "-e", "./root", file], onRuntimeInitialized: function () { - filesystem.forEach((e) => { + /*filesystem.forEach((e) => { if (e.name.endsWith("/")) { FS.mkdir(e.name.slice(0, -1)); } else { @@ -52,7 +66,7 @@ function runEmulation(filesystem, file, options) { } FS.createDataFile("/" + dirs.join("/"), file, buffer, true, true); } - }); + });*/ }, print: logLine, printErr: logLine, @@ -61,5 +75,5 @@ function runEmulation(filesystem, file, options) { postRun: flushLines, }; - importScripts("./analyzer.js"); + importScripts("./debugger.js"); } From d6abbc7e37f269695626a81c4a9ad117ee672541 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 27 Apr 2025 17:40:51 +0200 Subject: [PATCH 05/17] Prepare flatbuffer support --- .gitmodules | 3 + deps/CMakeLists.txt | 4 +- deps/flatbuffers | 1 + src/debugger/CMakeLists.txt | 2 +- src/debugger/event_handler.cpp | 56 +++++++++++++++ src/debugger/event_handler.hpp | 14 ++++ src/debugger/events.fbs | 0 src/debugger/events.hpp | 38 ++++++++++ src/debugger/main.cpp | 103 +-------------------------- src/debugger/message_transmitter.cpp | 91 +++++++++++++++++++++++ src/debugger/message_transmitter.hpp | 10 +++ 11 files changed, 220 insertions(+), 102 deletions(-) create mode 160000 deps/flatbuffers create mode 100644 src/debugger/event_handler.cpp create mode 100644 src/debugger/event_handler.hpp create mode 100644 src/debugger/events.fbs create mode 100644 src/debugger/events.hpp create mode 100644 src/debugger/message_transmitter.cpp create mode 100644 src/debugger/message_transmitter.hpp diff --git a/.gitmodules b/.gitmodules index 5571083f..6ced4c9d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ path = deps/json url = https://github.com/nlohmann/json.git branch = master +[submodule "deps/flatbuffers"] + path = deps/flatbuffers + url = https://github.com/google/flatbuffers.git diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 28155aed..7476ce45 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -3,7 +3,9 @@ add_subdirectory(unicorn) ########################################## -add_subdirectory(json) +option(FLATBUFFERS_BUILD_TESTS "" OFF) +option(FLATBUFFERS_INSTALL "" OFF) +add_subdirectory(flatbuffers) ########################################## diff --git a/deps/flatbuffers b/deps/flatbuffers new file mode 160000 index 00000000..609c72ca --- /dev/null +++ b/deps/flatbuffers @@ -0,0 +1 @@ +Subproject commit 609c72ca1a7526f444a109bc04f861ad578e833d diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt index bc63c072..ae580125 100644 --- a/src/debugger/CMakeLists.txt +++ b/src/debugger/CMakeLists.txt @@ -16,7 +16,7 @@ endif() target_link_libraries(debugger PRIVATE windows-emulator - nlohmann_json + flatbuffers ) set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT debugger) diff --git a/src/debugger/event_handler.cpp b/src/debugger/event_handler.cpp new file mode 100644 index 00000000..6655ec79 --- /dev/null +++ b/src/debugger/event_handler.cpp @@ -0,0 +1,56 @@ +#include "event_handler.hpp" +#include "events.hpp" + +#include "message_transmitter.hpp" + +namespace debugger +{ + namespace + { + void handle_event(event_context& c, const event& e, const nlohmann::json& obj) + { + switch (e.type) + { + case event_type::pause: + c.win_emu.emu().stop(); + break; + + case event_type::run: + c.resume = true; + break; + + default: + break; + } + } + + void handle_object(event_context& c, const nlohmann::json& obj) + { + try + { + const auto e = obj.get(); + handle_event(c, e, obj); + } + catch (const std::exception& e) + { + puts(e.what()); + } + } + } + + void handle_events(event_context& c) + { + while (true) + { + suspend_execution(0ms); + + const auto obj = receive_object(); + if (obj.is_null()) + { + break; + } + + handle_object(c, obj); + } + } +} \ No newline at end of file diff --git a/src/debugger/event_handler.hpp b/src/debugger/event_handler.hpp new file mode 100644 index 00000000..acdb3fa3 --- /dev/null +++ b/src/debugger/event_handler.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace debugger +{ + struct event_context + { + windows_emulator& win_emu; + bool resume{false}; + }; + + void handle_events(event_context& c); +} diff --git a/src/debugger/events.fbs b/src/debugger/events.fbs new file mode 100644 index 00000000..e69de29b diff --git a/src/debugger/events.hpp b/src/debugger/events.hpp new file mode 100644 index 00000000..da334375 --- /dev/null +++ b/src/debugger/events.hpp @@ -0,0 +1,38 @@ +#pragma once + +namespace debugger +{ + enum class event_type + { + invalid = 0, + pause = 1, + run = 2, + register_request = 3, + register_response = 4, + write_memory_request = 5, + write_memory_response = 6, + read_memory_request = 7, + read_memory_response = 8, + }; + + struct event + { + event_type type{event_type::invalid}; + }; + + template + struct typed_event : event + { + typed_event() + : event{ + .type = Type, + } + { + } + }; + + using pause_event = typed_event; + using run_event = typed_event; + + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(event, type); +} diff --git a/src/debugger/main.cpp b/src/debugger/main.cpp index 2cfcab79..24726083 100644 --- a/src/debugger/main.cpp +++ b/src/debugger/main.cpp @@ -2,110 +2,12 @@ #include #include -#include - -#ifdef OS_EMSCRIPTEN -#include -#endif +#include "event_handler.hpp" #include namespace { - void suspend_execution(const std::chrono::milliseconds ms = 0ms) - { -#ifdef OS_EMSCRIPTEN - emscripten_sleep(static_cast(ms.count())); -#else - if (ms > 0ms) - { - std::this_thread::sleep_for(ms); - } - else - { - std::this_thread::yield(); - } -#endif - } - - void send_message(const std::string& message) - { -#ifdef OS_EMSCRIPTEN - // clang-format off - EM_ASM_({ - handleMessage(UTF8ToString($0)); - }, message.c_str()); - // clang-format on -#else - (void)message; -#endif - } - - std::string receive_message() - { -#ifdef OS_EMSCRIPTEN - // clang-format off - auto* ptr = EM_ASM_PTR({ - var message = getMessageFromQueue(); - if (!message || message.length == 0) - { - return null; - } - - const length = lengthBytesUTF8(message) + 1; - const buffer = _malloc(length); - stringToUTF8(message, buffer, length); - return buffer; - }); - // clang-format on - - if (!ptr) - { - return {}; - } - - const auto _ = utils::finally([&] { - free(ptr); // - }); - - return {reinterpret_cast(ptr)}; -#else - return {}; -#endif - } - - void send_object(const nlohmann::json& json) - { - const std::string res = json.dump(); - send_message(res); - } - - nlohmann::json receive_object() - { - auto message = receive_message(); - if (message.empty()) - { - return {}; - } - - return nlohmann::json::parse(message); - } - - void handle_messages(windows_emulator& win_emu) - { - while (true) - { - suspend_execution(0ms); - const auto message = receive_object(); - if (message.is_null()) - { - break; - } - - puts(message.dump().c_str()); - } - } - bool run_emulation(windows_emulator& win_emu) { try @@ -162,7 +64,8 @@ namespace windows_emulator win_emu{app_settings, settings}; win_emu.callbacks.on_thread_switch = [&] { - handle_messages(win_emu); // + debugger::event_context c{.win_emu = win_emu}; + debugger::handle_events(c); // }; return run_emulation(win_emu); diff --git a/src/debugger/message_transmitter.cpp b/src/debugger/message_transmitter.cpp new file mode 100644 index 00000000..d44df3b4 --- /dev/null +++ b/src/debugger/message_transmitter.cpp @@ -0,0 +1,91 @@ +#include "message_transmitter.hpp" +#include + +#ifdef OS_EMSCRIPTEN +#include +#endif + +namespace debugger +{ + namespace + { + void send_message(const std::string& message) + { +#ifdef OS_EMSCRIPTEN + // clang-format off + EM_ASM_({ + handleMessage(UTF8ToString($0)); + }, message.c_str()); + // clang-format on +#else + (void)message; +#endif + } + + std::string receive_message() + { +#ifdef OS_EMSCRIPTEN + // clang-format off + auto* ptr = EM_ASM_PTR({ + var message = getMessageFromQueue(); + if (!message || message.length == 0) + { + return null; + } + + const length = lengthBytesUTF8(message) + 1; + const buffer = _malloc(length); + stringToUTF8(message, buffer, length); + return buffer; + }); + // clang-format on + + if (!ptr) + { + return {}; + } + + const auto _ = utils::finally([&] { + free(ptr); // + }); + + return {reinterpret_cast(ptr)}; +#else + return {}; +#endif + } + + void send_object(const nlohmann::json& json) + { + const std::string res = json.dump(); + send_message(res); + } + + nlohmann::json receive_object() + { + auto message = receive_message(); + if (message.empty()) + { + return {}; + } + + return nlohmann::json::parse(message); + } + + void suspend_execution(const std::chrono::milliseconds ms) + { +#ifdef OS_EMSCRIPTEN + emscripten_sleep(static_cast(ms.count())); +#else + if (ms > 0ms) + { + std::this_thread::sleep_for(ms); + } + else + { + std::this_thread::yield(); + } +#endif + } + } + } \ No newline at end of file diff --git a/src/debugger/message_transmitter.hpp b/src/debugger/message_transmitter.hpp new file mode 100644 index 00000000..cb30b444 --- /dev/null +++ b/src/debugger/message_transmitter.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace debugger +{ + void suspend_execution(const std::chrono::milliseconds ms = 0ms); + void send_object(const nlohmann::json& json); + nlohmann::json receive_object(); +} From c639f7e1ce03b00e194c743d001624edd04935f3 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 27 Apr 2025 17:55:10 +0200 Subject: [PATCH 06/17] Remove json --- .gitmodules | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 6ced4c9d..eda2e245 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,10 +18,6 @@ [submodule "deps/gtest-parallel"] path = deps/gtest-parallel url = https://github.com/google/gtest-parallel.git -[submodule "deps/json"] - path = deps/json - url = https://github.com/nlohmann/json.git - branch = master [submodule "deps/flatbuffers"] path = deps/flatbuffers url = https://github.com/google/flatbuffers.git From c25133207c58bb66d8f9d196a776cf542595ced6 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 27 Apr 2025 18:24:02 +0200 Subject: [PATCH 07/17] More flatbuffers progress --- src/debugger/CMakeLists.txt | 6 + src/debugger/event_handler.cpp | 2 +- src/debugger/events.fbs | 18 + src/debugger/events.hpp | 38 --- src/debugger/events_generated.hxx | 535 ++++++++++++++++++++++++++++++ 5 files changed, 560 insertions(+), 39 deletions(-) delete mode 100644 src/debugger/events.hpp create mode 100644 src/debugger/events_generated.hxx diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt index ae580125..a5bc4859 100644 --- a/src/debugger/CMakeLists.txt +++ b/src/debugger/CMakeLists.txt @@ -22,3 +22,9 @@ target_link_libraries(debugger PRIVATE set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT debugger) momo_strip_target(debugger) + +add_custom_target(gen_fbs + COMMAND "$" --gen-mutable --gen-object-api --filename-ext hxx --cpp -o "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/events.fbs" +) + +add_dependencies(gen_fbs flatc) \ No newline at end of file diff --git a/src/debugger/event_handler.cpp b/src/debugger/event_handler.cpp index 6655ec79..6c90fcc5 100644 --- a/src/debugger/event_handler.cpp +++ b/src/debugger/event_handler.cpp @@ -1,5 +1,5 @@ #include "event_handler.hpp" -#include "events.hpp" +#include "events_generated.hxx" #include "message_transmitter.hpp" diff --git a/src/debugger/events.fbs b/src/debugger/events.fbs index e69de29b..a0456ceb 100644 --- a/src/debugger/events.fbs +++ b/src/debugger/events.fbs @@ -0,0 +1,18 @@ +namespace Debugger; + +table PauseEvent {} + +table RunEvent { + singleStep: bool; +} + +union Event { + PauseEvent, + RunEvent, +} + +table DebugEvent { + event: Event; +} + +root_type DebugEvent; diff --git a/src/debugger/events.hpp b/src/debugger/events.hpp deleted file mode 100644 index da334375..00000000 --- a/src/debugger/events.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -namespace debugger -{ - enum class event_type - { - invalid = 0, - pause = 1, - run = 2, - register_request = 3, - register_response = 4, - write_memory_request = 5, - write_memory_response = 6, - read_memory_request = 7, - read_memory_response = 8, - }; - - struct event - { - event_type type{event_type::invalid}; - }; - - template - struct typed_event : event - { - typed_event() - : event{ - .type = Type, - } - { - } - }; - - using pause_event = typed_event; - using run_event = typed_event; - - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(event, type); -} diff --git a/src/debugger/events_generated.hxx b/src/debugger/events_generated.hxx new file mode 100644 index 00000000..337dff47 --- /dev/null +++ b/src/debugger/events_generated.hxx @@ -0,0 +1,535 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_EVENTS_DEBUGGER_H_ +#define FLATBUFFERS_GENERATED_EVENTS_DEBUGGER_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 2 && + FLATBUFFERS_VERSION_REVISION == 10, + "Non-compatible flatbuffers version included"); + +namespace Debugger { + +struct PauseEvent; +struct PauseEventBuilder; +struct PauseEventT; + +struct RunEvent; +struct RunEventBuilder; +struct RunEventT; + +struct DebugEvent; +struct DebugEventBuilder; +struct DebugEventT; + +enum Event : uint8_t { + Event_NONE = 0, + Event_PauseEvent = 1, + Event_RunEvent = 2, + Event_MIN = Event_NONE, + Event_MAX = Event_RunEvent +}; + +inline const Event (&EnumValuesEvent())[3] { + static const Event values[] = { + Event_NONE, + Event_PauseEvent, + Event_RunEvent + }; + return values; +} + +inline const char * const *EnumNamesEvent() { + static const char * const names[4] = { + "NONE", + "PauseEvent", + "RunEvent", + nullptr + }; + return names; +} + +inline const char *EnumNameEvent(Event e) { + if (::flatbuffers::IsOutRange(e, Event_NONE, Event_RunEvent)) return ""; + const size_t index = static_cast(e); + return EnumNamesEvent()[index]; +} + +template struct EventTraits { + static const Event enum_value = Event_NONE; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_PauseEvent; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_RunEvent; +}; + +template struct EventUnionTraits { + static const Event enum_value = Event_NONE; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_PauseEvent; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_RunEvent; +}; + +struct EventUnion { + Event type; + void *value; + + EventUnion() : type(Event_NONE), value(nullptr) {} + EventUnion(EventUnion&& u) FLATBUFFERS_NOEXCEPT : + type(Event_NONE), value(nullptr) + { std::swap(type, u.type); std::swap(value, u.value); } + EventUnion(const EventUnion &); + EventUnion &operator=(const EventUnion &u) + { EventUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; } + EventUnion &operator=(EventUnion &&u) FLATBUFFERS_NOEXCEPT + { std::swap(type, u.type); std::swap(value, u.value); return *this; } + ~EventUnion() { Reset(); } + + void Reset(); + + template + void Set(T&& val) { + typedef typename std::remove_reference::type RT; + Reset(); + type = EventUnionTraits::enum_value; + if (type != Event_NONE) { + value = new RT(std::forward(val)); + } + } + + static void *UnPack(const void *obj, Event type, const ::flatbuffers::resolver_function_t *resolver); + ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr) const; + + Debugger::PauseEventT *AsPauseEvent() { + return type == Event_PauseEvent ? + reinterpret_cast(value) : nullptr; + } + const Debugger::PauseEventT *AsPauseEvent() const { + return type == Event_PauseEvent ? + reinterpret_cast(value) : nullptr; + } + Debugger::RunEventT *AsRunEvent() { + return type == Event_RunEvent ? + reinterpret_cast(value) : nullptr; + } + const Debugger::RunEventT *AsRunEvent() const { + return type == Event_RunEvent ? + reinterpret_cast(value) : nullptr; + } +}; + +bool VerifyEvent(::flatbuffers::Verifier &verifier, const void *obj, Event type); +bool VerifyEventVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset> *values, const ::flatbuffers::Vector *types); + +struct PauseEventT : public ::flatbuffers::NativeTable { + typedef PauseEvent TableType; +}; + +struct PauseEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef PauseEventT NativeTableType; + typedef PauseEventBuilder Builder; + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + PauseEventT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(PauseEventT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const PauseEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct PauseEventBuilder { + typedef PauseEvent Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + explicit PauseEventBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreatePauseEvent( + ::flatbuffers::FlatBufferBuilder &_fbb) { + PauseEventBuilder builder_(_fbb); + return builder_.Finish(); +} + +::flatbuffers::Offset CreatePauseEvent(::flatbuffers::FlatBufferBuilder &_fbb, const PauseEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct RunEventT : public ::flatbuffers::NativeTable { + typedef RunEvent TableType; + bool singleStep = false; +}; + +struct RunEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef RunEventT NativeTableType; + typedef RunEventBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SINGLESTEP = 4 + }; + bool singleStep() const { + return GetField(VT_SINGLESTEP, 0) != 0; + } + bool mutate_singleStep(bool _singleStep = 0) { + return SetField(VT_SINGLESTEP, static_cast(_singleStep), 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SINGLESTEP, 1) && + verifier.EndTable(); + } + RunEventT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RunEventT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RunEventBuilder { + typedef RunEvent Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_singleStep(bool singleStep) { + fbb_.AddElement(RunEvent::VT_SINGLESTEP, static_cast(singleStep), 0); + } + explicit RunEventBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateRunEvent( + ::flatbuffers::FlatBufferBuilder &_fbb, + bool singleStep = false) { + RunEventBuilder builder_(_fbb); + builder_.add_singleStep(singleStep); + return builder_.Finish(); +} + +::flatbuffers::Offset CreateRunEvent(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct DebugEventT : public ::flatbuffers::NativeTable { + typedef DebugEvent TableType; + Debugger::EventUnion event{}; +}; + +struct DebugEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef DebugEventT NativeTableType; + typedef DebugEventBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_EVENT_TYPE = 4, + VT_EVENT = 6 + }; + Debugger::Event event_type() const { + return static_cast(GetField(VT_EVENT_TYPE, 0)); + } + const void *event() const { + return GetPointer(VT_EVENT); + } + template const T *event_as() const; + const Debugger::PauseEvent *event_as_PauseEvent() const { + return event_type() == Debugger::Event_PauseEvent ? static_cast(event()) : nullptr; + } + const Debugger::RunEvent *event_as_RunEvent() const { + return event_type() == Debugger::Event_RunEvent ? static_cast(event()) : nullptr; + } + void *mutable_event() { + return GetPointer(VT_EVENT); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_EVENT_TYPE, 1) && + VerifyOffset(verifier, VT_EVENT) && + VerifyEvent(verifier, event(), event_type()) && + verifier.EndTable(); + } + DebugEventT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(DebugEventT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const DebugEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +template<> inline const Debugger::PauseEvent *DebugEvent::event_as() const { + return event_as_PauseEvent(); +} + +template<> inline const Debugger::RunEvent *DebugEvent::event_as() const { + return event_as_RunEvent(); +} + +struct DebugEventBuilder { + typedef DebugEvent Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_event_type(Debugger::Event event_type) { + fbb_.AddElement(DebugEvent::VT_EVENT_TYPE, static_cast(event_type), 0); + } + void add_event(::flatbuffers::Offset event) { + fbb_.AddOffset(DebugEvent::VT_EVENT, event); + } + explicit DebugEventBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateDebugEvent( + ::flatbuffers::FlatBufferBuilder &_fbb, + Debugger::Event event_type = Debugger::Event_NONE, + ::flatbuffers::Offset event = 0) { + DebugEventBuilder builder_(_fbb); + builder_.add_event(event); + builder_.add_event_type(event_type); + return builder_.Finish(); +} + +::flatbuffers::Offset CreateDebugEvent(::flatbuffers::FlatBufferBuilder &_fbb, const DebugEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +inline PauseEventT *PauseEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new PauseEventT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void PauseEvent::UnPackTo(PauseEventT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline ::flatbuffers::Offset PauseEvent::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const PauseEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreatePauseEvent(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreatePauseEvent(::flatbuffers::FlatBufferBuilder &_fbb, const PauseEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const PauseEventT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return Debugger::CreatePauseEvent( + _fbb); +} + +inline RunEventT *RunEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new RunEventT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RunEvent::UnPackTo(RunEventT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = singleStep(); _o->singleStep = _e; } +} + +inline ::flatbuffers::Offset RunEvent::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateRunEvent(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateRunEvent(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const RunEventT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _singleStep = _o->singleStep; + return Debugger::CreateRunEvent( + _fbb, + _singleStep); +} + +inline DebugEventT *DebugEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new DebugEventT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void DebugEvent::UnPackTo(DebugEventT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = event_type(); _o->event.type = _e; } + { auto _e = event(); if (_e) _o->event.value = Debugger::EventUnion::UnPack(_e, event_type(), _resolver); } +} + +inline ::flatbuffers::Offset DebugEvent::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const DebugEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateDebugEvent(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateDebugEvent(::flatbuffers::FlatBufferBuilder &_fbb, const DebugEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const DebugEventT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _event_type = _o->event.type; + auto _event = _o->event.Pack(_fbb); + return Debugger::CreateDebugEvent( + _fbb, + _event_type, + _event); +} + +inline bool VerifyEvent(::flatbuffers::Verifier &verifier, const void *obj, Event type) { + switch (type) { + case Event_NONE: { + return true; + } + case Event_PauseEvent: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_RunEvent: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + default: return true; + } +} + +inline bool VerifyEventVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset> *values, const ::flatbuffers::Vector *types) { + if (!values || !types) return !values && !types; + if (values->size() != types->size()) return false; + for (::flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { + if (!VerifyEvent( + verifier, values->Get(i), types->GetEnum(i))) { + return false; + } + } + return true; +} + +inline void *EventUnion::UnPack(const void *obj, Event type, const ::flatbuffers::resolver_function_t *resolver) { + (void)resolver; + switch (type) { + case Event_PauseEvent: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_RunEvent: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + default: return nullptr; + } +} + +inline ::flatbuffers::Offset EventUnion::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ::flatbuffers::rehasher_function_t *_rehasher) const { + (void)_rehasher; + switch (type) { + case Event_PauseEvent: { + auto ptr = reinterpret_cast(value); + return CreatePauseEvent(_fbb, ptr, _rehasher).Union(); + } + case Event_RunEvent: { + auto ptr = reinterpret_cast(value); + return CreateRunEvent(_fbb, ptr, _rehasher).Union(); + } + default: return 0; + } +} + +inline EventUnion::EventUnion(const EventUnion &u) : type(u.type), value(nullptr) { + switch (type) { + case Event_PauseEvent: { + value = new Debugger::PauseEventT(*reinterpret_cast(u.value)); + break; + } + case Event_RunEvent: { + value = new Debugger::RunEventT(*reinterpret_cast(u.value)); + break; + } + default: + break; + } +} + +inline void EventUnion::Reset() { + switch (type) { + case Event_PauseEvent: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_RunEvent: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + default: break; + } + value = nullptr; + type = Event_NONE; +} + +inline const Debugger::DebugEvent *GetDebugEvent(const void *buf) { + return ::flatbuffers::GetRoot(buf); +} + +inline const Debugger::DebugEvent *GetSizePrefixedDebugEvent(const void *buf) { + return ::flatbuffers::GetSizePrefixedRoot(buf); +} + +inline DebugEvent *GetMutableDebugEvent(void *buf) { + return ::flatbuffers::GetMutableRoot(buf); +} + +inline Debugger::DebugEvent *GetMutableSizePrefixedDebugEvent(void *buf) { + return ::flatbuffers::GetMutableSizePrefixedRoot(buf); +} + +inline bool VerifyDebugEventBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(nullptr); +} + +inline bool VerifySizePrefixedDebugEventBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(nullptr); +} + +inline void FinishDebugEventBuffer( + ::flatbuffers::FlatBufferBuilder &fbb, + ::flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedDebugEventBuffer( + ::flatbuffers::FlatBufferBuilder &fbb, + ::flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +inline std::unique_ptr UnPackDebugEvent( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr(GetDebugEvent(buf)->UnPack(res)); +} + +inline std::unique_ptr UnPackSizePrefixedDebugEvent( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr(GetSizePrefixedDebugEvent(buf)->UnPack(res)); +} + +} // namespace Debugger + +#endif // FLATBUFFERS_GENERATED_EVENTS_DEBUGGER_H_ From bc26ebf1ba10d53a7acbda523b55a3569c922282 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 28 Apr 2025 08:39:23 +0200 Subject: [PATCH 08/17] Better message transmission --- .gitmodules | 3 + deps/CMakeLists.txt | 5 ++ deps/base64 | 1 + page/public/emulator-worker.js | 4 +- src/.clang-format-ignore | 1 + src/debugger/CMakeLists.txt | 1 + src/debugger/event_handler.cpp | 62 ++++++++++++------- src/debugger/main.cpp | 2 - src/debugger/message_transmitter.cpp | 91 ++++++++++++---------------- src/debugger/message_transmitter.hpp | 9 +-- 10 files changed, 97 insertions(+), 82 deletions(-) create mode 160000 deps/base64 create mode 100644 src/.clang-format-ignore diff --git a/.gitmodules b/.gitmodules index eda2e245..39d3ee49 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,3 +21,6 @@ [submodule "deps/flatbuffers"] path = deps/flatbuffers url = https://github.com/google/flatbuffers.git +[submodule "deps/base64"] + path = deps/base64 + url = https://github.com/tobiaslocker/base64.git diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 7476ce45..86da80dd 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -3,6 +3,11 @@ add_subdirectory(unicorn) ########################################## +option(BASE64_ENABLE_TESTING "" OFF) +add_subdirectory(base64) + +########################################## + option(FLATBUFFERS_BUILD_TESTS "" OFF) option(FLATBUFFERS_INSTALL "" OFF) add_subdirectory(flatbuffers) diff --git a/deps/base64 b/deps/base64 new file mode 160000 index 00000000..0d0f5a88 --- /dev/null +++ b/deps/base64 @@ -0,0 +1 @@ +Subproject commit 0d0f5a8849a954d96af7befdb5c4014e78ecc9e2 diff --git a/page/public/emulator-worker.js b/page/public/emulator-worker.js index e795f184..a4983757 100644 --- a/page/public/emulator-worker.js +++ b/page/public/emulator-worker.js @@ -43,10 +43,10 @@ function handleMessage(message) { } function getMessageFromQueue() { - if(msgQueue.length == 0){ + if (msgQueue.length == 0) { return ""; } - + return msgQueue.pop(); } diff --git a/src/.clang-format-ignore b/src/.clang-format-ignore new file mode 100644 index 00000000..9d3995d3 --- /dev/null +++ b/src/.clang-format-ignore @@ -0,0 +1 @@ +**/*.hxx diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt index a5bc4859..12711131 100644 --- a/src/debugger/CMakeLists.txt +++ b/src/debugger/CMakeLists.txt @@ -17,6 +17,7 @@ endif() target_link_libraries(debugger PRIVATE windows-emulator flatbuffers + base64 ) set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT debugger) diff --git a/src/debugger/event_handler.cpp b/src/debugger/event_handler.cpp index 6c90fcc5..e701c621 100644 --- a/src/debugger/event_handler.cpp +++ b/src/debugger/event_handler.cpp @@ -1,21 +1,54 @@ #include "event_handler.hpp" +#include "message_transmitter.hpp" + +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + #include "events_generated.hxx" -#include "message_transmitter.hpp" +#ifdef _MSC_VER +#pragma warning(pop) +#endif namespace debugger { namespace { - void handle_event(event_context& c, const event& e, const nlohmann::json& obj) + std::optional receive_event() { - switch (e.type) + const auto message = receive_message(); + if (message.empty()) { - case event_type::pause: + return std::nullopt; + } + + const auto data = base64::from_base64(message); + + flatbuffers::Verifier verifier(reinterpret_cast(data.data()), data.size()); + if (!Debugger::VerifyDebugEventBuffer(verifier)) + { + return std::nullopt; + } + + Debugger::DebugEventT e{}; + Debugger::GetDebugEvent(data.data())->UnPackTo(&e); + + return {std::move(e)}; + } + + void handle_event(event_context& c, const Debugger::DebugEventT& e) + { + switch (e.event.type) + { + case Debugger::Event_PauseEvent: c.win_emu.emu().stop(); break; - case event_type::run: + case Debugger::Event_RunEvent: c.resume = true; break; @@ -23,19 +56,6 @@ namespace debugger break; } } - - void handle_object(event_context& c, const nlohmann::json& obj) - { - try - { - const auto e = obj.get(); - handle_event(c, e, obj); - } - catch (const std::exception& e) - { - puts(e.what()); - } - } } void handle_events(event_context& c) @@ -44,13 +64,13 @@ namespace debugger { suspend_execution(0ms); - const auto obj = receive_object(); - if (obj.is_null()) + const auto e = receive_event(); + if (!e.has_value()) { break; } - handle_object(c, obj); + handle_event(c, *e); } } } \ No newline at end of file diff --git a/src/debugger/main.cpp b/src/debugger/main.cpp index 24726083..b234f088 100644 --- a/src/debugger/main.cpp +++ b/src/debugger/main.cpp @@ -4,8 +4,6 @@ #include #include "event_handler.hpp" -#include - namespace { bool run_emulation(windows_emulator& win_emu) diff --git a/src/debugger/message_transmitter.cpp b/src/debugger/message_transmitter.cpp index d44df3b4..2e358fbf 100644 --- a/src/debugger/message_transmitter.cpp +++ b/src/debugger/message_transmitter.cpp @@ -1,31 +1,34 @@ #include "message_transmitter.hpp" #include +#include + +#include #ifdef OS_EMSCRIPTEN #include #endif +using namespace std::literals; + namespace debugger { - namespace + void send_message(const std::string& message) { - void send_message(const std::string& message) - { #ifdef OS_EMSCRIPTEN - // clang-format off + // clang-format off EM_ASM_({ handleMessage(UTF8ToString($0)); }, message.c_str()); - // clang-format on + // clang-format on #else - (void)message; + (void)message; #endif - } + } - std::string receive_message() - { + std::string receive_message() + { #ifdef OS_EMSCRIPTEN - // clang-format off + // clang-format off auto* ptr = EM_ASM_PTR({ var message = getMessageFromQueue(); if (!message || message.length == 0) @@ -38,54 +41,36 @@ namespace debugger stringToUTF8(message, buffer, length); return buffer; }); - // clang-format on + // clang-format on - if (!ptr) - { - return {}; - } - - const auto _ = utils::finally([&] { - free(ptr); // - }); - - return {reinterpret_cast(ptr)}; -#else + if (!ptr) + { return {}; -#endif } - void send_object(const nlohmann::json& json) - { - const std::string res = json.dump(); - send_message(res); - } + const auto _ = utils::finally([&] { + free(ptr); // + }); - nlohmann::json receive_object() - { - auto message = receive_message(); - if (message.empty()) - { - return {}; - } - - return nlohmann::json::parse(message); - } - - void suspend_execution(const std::chrono::milliseconds ms) - { -#ifdef OS_EMSCRIPTEN - emscripten_sleep(static_cast(ms.count())); + return {reinterpret_cast(ptr)}; #else - if (ms > 0ms) - { - std::this_thread::sleep_for(ms); - } - else - { - std::this_thread::yield(); - } + return {}; #endif - } } - } \ No newline at end of file + + void suspend_execution(const std::chrono::milliseconds ms) + { +#ifdef OS_EMSCRIPTEN + emscripten_sleep(static_cast(ms.count())); +#else + if (ms > 0ms) + { + std::this_thread::sleep_for(ms); + } + else + { + std::this_thread::yield(); + } +#endif + } +} \ No newline at end of file diff --git a/src/debugger/message_transmitter.hpp b/src/debugger/message_transmitter.hpp index cb30b444..8aa95a2b 100644 --- a/src/debugger/message_transmitter.hpp +++ b/src/debugger/message_transmitter.hpp @@ -1,10 +1,11 @@ #pragma once -#include +#include +#include namespace debugger { - void suspend_execution(const std::chrono::milliseconds ms = 0ms); - void send_object(const nlohmann::json& json); - nlohmann::json receive_object(); + void suspend_execution(std::chrono::milliseconds ms = std::chrono::milliseconds(0)); + void send_message(const std::string& message); + std::string receive_message(); } From 9ab282c2cfe9faaaf8bf29754485a992f28f4a5c Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 28 Apr 2025 11:11:00 +0200 Subject: [PATCH 09/17] Prepare TS flatbuffer support --- deps/CMakeLists.txt | 4 + page/.prettierignore | 1 + page/package-lock.json | 7 ++ page/package.json | 1 + page/src/emulator.ts | 67 +++++++++++++++-- page/src/fb/debugger.ts | 8 ++ page/src/fb/debugger/debug-event.ts | 109 ++++++++++++++++++++++++++++ page/src/fb/debugger/event.ts | 38 ++++++++++ page/src/fb/debugger/pause-event.ts | 56 ++++++++++++++ page/src/fb/debugger/run-event.ts | 85 ++++++++++++++++++++++ page/src/fb/events.ts | 5 ++ page/tsconfig.app.json | 4 +- src/debugger/CMakeLists.txt | 4 +- src/debugger/events.fbs | 2 +- src/debugger/events_generated.hxx | 28 +++---- 15 files changed, 393 insertions(+), 26 deletions(-) create mode 100644 page/src/fb/debugger.ts create mode 100644 page/src/fb/debugger/debug-event.ts create mode 100644 page/src/fb/debugger/event.ts create mode 100644 page/src/fb/debugger/pause-event.ts create mode 100644 page/src/fb/debugger/run-event.ts create mode 100644 page/src/fb/events.ts diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 86da80dd..ff723c69 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -12,6 +12,10 @@ option(FLATBUFFERS_BUILD_TESTS "" OFF) option(FLATBUFFERS_INSTALL "" OFF) add_subdirectory(flatbuffers) +if(MSVC) +target_compile_options(flatc PRIVATE /MD) +endif() + ########################################## add_library(reflect INTERFACE) diff --git a/page/.prettierignore b/page/.prettierignore index e17b023c..f16c6412 100644 --- a/page/.prettierignore +++ b/page/.prettierignore @@ -1,2 +1,3 @@ # Ignore artifacts: dist +src/fb/ \ No newline at end of file diff --git a/page/package-lock.json b/page/package-lock.json index 5510ce20..845dbe87 100644 --- a/page/package-lock.json +++ b/page/package-lock.json @@ -22,6 +22,7 @@ "@types/react-window": "^1.8.8", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "flatbuffers": "^25.2.10", "jszip": "^3.10.1", "lucide-react": "^0.503.0", "react": "^19.0.0", @@ -3595,6 +3596,12 @@ "node": ">=16" } }, + "node_modules/flatbuffers": { + "version": "25.2.10", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.2.10.tgz", + "integrity": "sha512-7JlN9ZvLDG1McO3kbX0k4v+SUAg48L1rIwEvN6ZQl/eCtgJz9UylTMzE9wrmYrcorgxm3CX/3T/w5VAub99UUw==", + "license": "Apache-2.0" + }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", diff --git a/page/package.json b/page/package.json index 25100305..13ae4aca 100644 --- a/page/package.json +++ b/page/package.json @@ -24,6 +24,7 @@ "@types/react-window": "^1.8.8", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "flatbuffers": "^25.2.10", "jszip": "^3.10.1", "lucide-react": "^0.503.0", "react": "^19.0.0", diff --git a/page/src/emulator.ts b/page/src/emulator.ts index ce38da34..0ea8fc5b 100644 --- a/page/src/emulator.ts +++ b/page/src/emulator.ts @@ -1,6 +1,10 @@ import { createDefaultSettings, Settings, translateSettings } from "./settings"; import { FileEntry } from "./zip-file"; +import * as flatbuffers from "flatbuffers"; +import * as fbDebugger from "@/fb/debugger"; +import * as fbDebuggerEvent from "@/fb/debugger/event"; + type LogHandler = (lines: string[]) => void; export interface UserFile { @@ -8,6 +12,35 @@ export interface UserFile { data: ArrayBuffer; } +function base64Encode(uint8Array: Uint8Array): string { + let binaryString = ""; + for (let i = 0; i < uint8Array.byteLength; i++) { + binaryString += String.fromCharCode(uint8Array[i]); + } + + return btoa(binaryString); +} + +function base64Decode(data: string) { + const binaryString = atob(data); + + const len = binaryString.length; + const bytes = new Uint8Array(len); + + for (let i = 0; i < len; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + + return bytes; +} + +function decodeEvent(data: string) { + const array = base64Decode(data); + const buffer = new flatbuffers.ByteBuffer(array); + const event = fbDebugger.DebugEvent.getRootAsDebugEvent(buffer); + return event.unpack(); +} + export class Emulator { filesystem: FileEntry[]; logHandler: LogHandler; @@ -30,13 +63,7 @@ export class Emulator { /*new URL('./emulator-worker.js', import.meta.url)*/ "./emulator-worker.js", ); - this.worker.onmessage = (event: MessageEvent) => { - if (event.data.message == "log") { - this.logHandler(event.data.data); - } else if (event.data.message == "end") { - this.terminateResolve(0); - } - }; + this.worker.onmessage = this._onMessage.bind(this); } start( @@ -72,4 +99,30 @@ export class Emulator { onTerminate() { return this.terminatePromise; } + + sendEvent(event: fbDebugger.DebugEventT) { + const builder = new flatbuffers.Builder(1024); + fbDebugger.DebugEvent.finishDebugEventBuffer(builder, event.pack(builder)); + + const message = base64Encode(builder.asUint8Array()); + + this.worker.postMessage({ + message: "event", + data: message, + }); + } + + _onMessage(event: MessageEvent) { + if (event.data.message == "log") { + this.logHandler(event.data.data); + } else if (event.data.message == "event") { + this._onEvent(decodeEvent(event.data.data)); + } else if (event.data.message == "end") { + this.terminateResolve(0); + } + } + + _onEvent(event: fbDebugger.DebugEventT) { + console.log(event); + } } diff --git a/page/src/fb/debugger.ts b/page/src/fb/debugger.ts new file mode 100644 index 00000000..347b04f6 --- /dev/null +++ b/page/src/fb/debugger.ts @@ -0,0 +1,8 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +export { DebugEvent, DebugEventT } from './debugger/debug-event.js'; +export { Event } from './debugger/event.js'; +export { PauseEvent, PauseEventT } from './debugger/pause-event.js'; +export { RunEvent, RunEventT } from './debugger/run-event.js'; diff --git a/page/src/fb/debugger/debug-event.ts b/page/src/fb/debugger/debug-event.ts new file mode 100644 index 00000000..a34e10e9 --- /dev/null +++ b/page/src/fb/debugger/debug-event.ts @@ -0,0 +1,109 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { Event, unionToEvent, unionListToEvent } from '../debugger/event.js'; +import { PauseEvent, PauseEventT } from '../debugger/pause-event.js'; +import { RunEvent, RunEventT } from '../debugger/run-event.js'; + + +export class DebugEvent implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):DebugEvent { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsDebugEvent(bb:flatbuffers.ByteBuffer, obj?:DebugEvent):DebugEvent { + return (obj || new DebugEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsDebugEvent(bb:flatbuffers.ByteBuffer, obj?:DebugEvent):DebugEvent { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new DebugEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +eventType():Event { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint8(this.bb_pos + offset) : Event.NONE; +} + +event(obj:any):any|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__union(obj, this.bb_pos + offset) : null; +} + +static startDebugEvent(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addEventType(builder:flatbuffers.Builder, eventType:Event) { + builder.addFieldInt8(0, eventType, Event.NONE); +} + +static addEvent(builder:flatbuffers.Builder, eventOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, eventOffset, 0); +} + +static endDebugEvent(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static finishDebugEventBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) { + builder.finish(offset); +} + +static finishSizePrefixedDebugEventBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) { + builder.finish(offset, undefined, true); +} + +static createDebugEvent(builder:flatbuffers.Builder, eventType:Event, eventOffset:flatbuffers.Offset):flatbuffers.Offset { + DebugEvent.startDebugEvent(builder); + DebugEvent.addEventType(builder, eventType); + DebugEvent.addEvent(builder, eventOffset); + return DebugEvent.endDebugEvent(builder); +} + +unpack(): DebugEventT { + return new DebugEventT( + this.eventType(), + (() => { + const temp = unionToEvent(this.eventType(), this.event.bind(this)); + if(temp === null) { return null; } + return temp.unpack() + })() + ); +} + + +unpackTo(_o: DebugEventT): void { + _o.eventType = this.eventType(); + _o.event = (() => { + const temp = unionToEvent(this.eventType(), this.event.bind(this)); + if(temp === null) { return null; } + return temp.unpack() + })(); +} +} + +export class DebugEventT implements flatbuffers.IGeneratedObject { +constructor( + public eventType: Event = Event.NONE, + public event: PauseEventT|RunEventT|null = null +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + const event = builder.createObjectOffset(this.event); + + return DebugEvent.createDebugEvent(builder, + this.eventType, + event + ); +} +} diff --git a/page/src/fb/debugger/event.ts b/page/src/fb/debugger/event.ts new file mode 100644 index 00000000..1949c08e --- /dev/null +++ b/page/src/fb/debugger/event.ts @@ -0,0 +1,38 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import { PauseEvent, PauseEventT } from '../debugger/pause-event.js'; +import { RunEvent, RunEventT } from '../debugger/run-event.js'; + + +export enum Event { + NONE = 0, + PauseEvent = 1, + RunEvent = 2 +} + +export function unionToEvent( + type: Event, + accessor: (obj:PauseEvent|RunEvent) => PauseEvent|RunEvent|null +): PauseEvent|RunEvent|null { + switch(Event[type]) { + case 'NONE': return null; + case 'PauseEvent': return accessor(new PauseEvent())! as PauseEvent; + case 'RunEvent': return accessor(new RunEvent())! as RunEvent; + default: return null; + } +} + +export function unionListToEvent( + type: Event, + accessor: (index: number, obj:PauseEvent|RunEvent) => PauseEvent|RunEvent|null, + index: number +): PauseEvent|RunEvent|null { + switch(Event[type]) { + case 'NONE': return null; + case 'PauseEvent': return accessor(index, new PauseEvent())! as PauseEvent; + case 'RunEvent': return accessor(index, new RunEvent())! as RunEvent; + default: return null; + } +} diff --git a/page/src/fb/debugger/pause-event.ts b/page/src/fb/debugger/pause-event.ts new file mode 100644 index 00000000..ea56222b --- /dev/null +++ b/page/src/fb/debugger/pause-event.ts @@ -0,0 +1,56 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class PauseEvent implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):PauseEvent { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsPauseEvent(bb:flatbuffers.ByteBuffer, obj?:PauseEvent):PauseEvent { + return (obj || new PauseEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsPauseEvent(bb:flatbuffers.ByteBuffer, obj?:PauseEvent):PauseEvent { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new PauseEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static startPauseEvent(builder:flatbuffers.Builder) { + builder.startObject(0); +} + +static endPauseEvent(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createPauseEvent(builder:flatbuffers.Builder):flatbuffers.Offset { + PauseEvent.startPauseEvent(builder); + return PauseEvent.endPauseEvent(builder); +} + +unpack(): PauseEventT { + return new PauseEventT(); +} + + +unpackTo(_o: PauseEventT): void {} +} + +export class PauseEventT implements flatbuffers.IGeneratedObject { +constructor(){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return PauseEvent.createPauseEvent(builder); +} +} diff --git a/page/src/fb/debugger/run-event.ts b/page/src/fb/debugger/run-event.ts new file mode 100644 index 00000000..9502e4d5 --- /dev/null +++ b/page/src/fb/debugger/run-event.ts @@ -0,0 +1,85 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class RunEvent implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):RunEvent { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsRunEvent(bb:flatbuffers.ByteBuffer, obj?:RunEvent):RunEvent { + return (obj || new RunEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsRunEvent(bb:flatbuffers.ByteBuffer, obj?:RunEvent):RunEvent { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new RunEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +singleStep():boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false; +} + +mutate_single_step(value:boolean):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeInt8(this.bb_pos + offset, +value); + return true; +} + +static startRunEvent(builder:flatbuffers.Builder) { + builder.startObject(1); +} + +static addSingleStep(builder:flatbuffers.Builder, singleStep:boolean) { + builder.addFieldInt8(0, +singleStep, +false); +} + +static endRunEvent(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createRunEvent(builder:flatbuffers.Builder, singleStep:boolean):flatbuffers.Offset { + RunEvent.startRunEvent(builder); + RunEvent.addSingleStep(builder, singleStep); + return RunEvent.endRunEvent(builder); +} + +unpack(): RunEventT { + return new RunEventT( + this.singleStep() + ); +} + + +unpackTo(_o: RunEventT): void { + _o.singleStep = this.singleStep(); +} +} + +export class RunEventT implements flatbuffers.IGeneratedObject { +constructor( + public singleStep: boolean = false +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return RunEvent.createRunEvent(builder, + this.singleStep + ); +} +} diff --git a/page/src/fb/events.ts b/page/src/fb/events.ts new file mode 100644 index 00000000..f21dacb2 --- /dev/null +++ b/page/src/fb/events.ts @@ -0,0 +1,5 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +export * as Debugger from './debugger.js'; diff --git a/page/tsconfig.app.json b/page/tsconfig.app.json index 9f0a5124..0f468d74 100644 --- a/page/tsconfig.app.json +++ b/page/tsconfig.app.json @@ -17,8 +17,8 @@ /* Linting */ "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, + "noUnusedLocals": false, + "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, "baseUrl": ".", diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt index 12711131..a0cf3db5 100644 --- a/src/debugger/CMakeLists.txt +++ b/src/debugger/CMakeLists.txt @@ -25,7 +25,7 @@ set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT debugger) momo_strip_target(debugger) add_custom_target(gen_fbs + DEPENDS flatc COMMAND "$" --gen-mutable --gen-object-api --filename-ext hxx --cpp -o "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/events.fbs" + COMMAND "$" --gen-mutable --gen-object-api --ts -o "${PROJECT_SOURCE_DIR}/page/src/fb" "${CMAKE_CURRENT_LIST_DIR}/events.fbs" ) - -add_dependencies(gen_fbs flatc) \ No newline at end of file diff --git a/src/debugger/events.fbs b/src/debugger/events.fbs index a0456ceb..15095c10 100644 --- a/src/debugger/events.fbs +++ b/src/debugger/events.fbs @@ -3,7 +3,7 @@ namespace Debugger; table PauseEvent {} table RunEvent { - singleStep: bool; + single_step: bool; } union Event { diff --git a/src/debugger/events_generated.hxx b/src/debugger/events_generated.hxx index 337dff47..3e9be171 100644 --- a/src/debugger/events_generated.hxx +++ b/src/debugger/events_generated.hxx @@ -176,24 +176,24 @@ inline ::flatbuffers::Offset CreatePauseEvent( struct RunEventT : public ::flatbuffers::NativeTable { typedef RunEvent TableType; - bool singleStep = false; + bool single_step = false; }; struct RunEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { typedef RunEventT NativeTableType; typedef RunEventBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SINGLESTEP = 4 + VT_SINGLE_STEP = 4 }; - bool singleStep() const { - return GetField(VT_SINGLESTEP, 0) != 0; + bool single_step() const { + return GetField(VT_SINGLE_STEP, 0) != 0; } - bool mutate_singleStep(bool _singleStep = 0) { - return SetField(VT_SINGLESTEP, static_cast(_singleStep), 0); + bool mutate_single_step(bool _single_step = 0) { + return SetField(VT_SINGLE_STEP, static_cast(_single_step), 0); } bool Verify(::flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyField(verifier, VT_SINGLESTEP, 1) && + VerifyField(verifier, VT_SINGLE_STEP, 1) && verifier.EndTable(); } RunEventT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -205,8 +205,8 @@ struct RunEventBuilder { typedef RunEvent Table; ::flatbuffers::FlatBufferBuilder &fbb_; ::flatbuffers::uoffset_t start_; - void add_singleStep(bool singleStep) { - fbb_.AddElement(RunEvent::VT_SINGLESTEP, static_cast(singleStep), 0); + void add_single_step(bool single_step) { + fbb_.AddElement(RunEvent::VT_SINGLE_STEP, static_cast(single_step), 0); } explicit RunEventBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { @@ -221,9 +221,9 @@ struct RunEventBuilder { inline ::flatbuffers::Offset CreateRunEvent( ::flatbuffers::FlatBufferBuilder &_fbb, - bool singleStep = false) { + bool single_step = false) { RunEventBuilder builder_(_fbb); - builder_.add_singleStep(singleStep); + builder_.add_single_step(single_step); return builder_.Finish(); } @@ -342,7 +342,7 @@ inline RunEventT *RunEvent::UnPack(const ::flatbuffers::resolver_function_t *_re inline void RunEvent::UnPackTo(RunEventT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; - { auto _e = singleStep(); _o->singleStep = _e; } + { auto _e = single_step(); _o->single_step = _e; } } inline ::flatbuffers::Offset RunEvent::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { @@ -353,10 +353,10 @@ inline ::flatbuffers::Offset CreateRunEvent(::flatbuffers::FlatBufferB (void)_rehasher; (void)_o; struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const RunEventT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; - auto _singleStep = _o->singleStep; + auto _single_step = _o->single_step; return Debugger::CreateRunEvent( _fbb, - _singleStep); + _single_step); } inline DebugEventT *DebugEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { From f411ad8d93130594de9f3b81e48fb0dde4f473e1 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 28 Apr 2025 13:37:16 +0200 Subject: [PATCH 10/17] Prepare communication --- page/public/emulator-worker.js | 19 +- page/src/Playground.tsx | 3 + page/src/emulator.ts | 18 + page/src/fb/debugger.ts | 7 +- page/src/fb/debugger/debug-event.ts | 8 +- page/src/fb/debugger/event.ts | 32 +- page/src/fb/debugger/get-state-request.ts | 56 ++ page/src/fb/debugger/get-state-response.ts | 86 +++ page/src/fb/debugger/pause-event.ts | 56 -- page/src/fb/debugger/pause-request.ts | 56 ++ .../debugger/{run-event.ts => run-request.ts} | 34 +- page/src/fb/debugger/state.ts | 9 + src/debugger/event_handler.cpp | 73 ++- src/debugger/event_handler.hpp | 9 +- src/debugger/events.fbs | 22 +- src/debugger/events_generated.hxx | 514 ++++++++++++++---- 16 files changed, 774 insertions(+), 228 deletions(-) create mode 100644 page/src/fb/debugger/get-state-request.ts create mode 100644 page/src/fb/debugger/get-state-response.ts delete mode 100644 page/src/fb/debugger/pause-event.ts create mode 100644 page/src/fb/debugger/pause-request.ts rename page/src/fb/debugger/{run-event.ts => run-request.ts} (51%) create mode 100644 page/src/fb/debugger/state.ts diff --git a/page/public/emulator-worker.js b/page/public/emulator-worker.js index a4983757..91f9725f 100644 --- a/page/public/emulator-worker.js +++ b/page/public/emulator-worker.js @@ -1,11 +1,16 @@ var logLines = []; var lastFlush = new Date().getTime(); +var msgQueue = []; + onmessage = async (event) => { const data = event.data; if (data.message == "run") { const payload = data.data; runEmulation(payload.filesystem, payload.file, payload.options); + } else if (data.message == "event") { + const payload = data.data; + msgQueue.push(payload); } }; @@ -32,14 +37,8 @@ function notifyExit(code) { self.close(); } -var msgQueue = []; - -setInterval(() => { - msgQueue.push("OI YEAH BABY :D"); -}, 2100); - function handleMessage(message) { - console.log("MSG from C++: " + message); + postMessage({ message: "event", data: message }); } function getMessageFromQueue() { @@ -52,9 +51,9 @@ function getMessageFromQueue() { function runEmulation(filesystem, file, options) { globalThis.Module = { - arguments: [...options, "-e", "./root", file], + arguments: ["./root", file], onRuntimeInitialized: function () { - /*filesystem.forEach((e) => { + filesystem.forEach((e) => { if (e.name.endsWith("/")) { FS.mkdir(e.name.slice(0, -1)); } else { @@ -66,7 +65,7 @@ function runEmulation(filesystem, file, options) { } FS.createDataFile("/" + dirs.join("/"), file, buffer, true, true); } - });*/ + }); }, print: logLine, printErr: logLine, diff --git a/page/src/Playground.tsx b/page/src/Playground.tsx index e86061e7..6e018ef5 100644 --- a/page/src/Playground.tsx +++ b/page/src/Playground.tsx @@ -116,6 +116,9 @@ export function Playground() { + diff --git a/page/src/emulator.ts b/page/src/emulator.ts index 0ea8fc5b..61a0024f 100644 --- a/page/src/emulator.ts +++ b/page/src/emulator.ts @@ -112,6 +112,24 @@ export class Emulator { }); } + pause() { + this.sendEvent( + new fbDebugger.DebugEventT( + fbDebugger.Event.PauseRequest, + new fbDebugger.PauseRequestT(), + ), + ); + } + + resume() { + this.sendEvent( + new fbDebugger.DebugEventT( + fbDebugger.Event.RunRequest, + new fbDebugger.RunRequestT(), + ), + ); + } + _onMessage(event: MessageEvent) { if (event.data.message == "log") { this.logHandler(event.data.data); diff --git a/page/src/fb/debugger.ts b/page/src/fb/debugger.ts index 347b04f6..ffde813b 100644 --- a/page/src/fb/debugger.ts +++ b/page/src/fb/debugger.ts @@ -4,5 +4,8 @@ export { DebugEvent, DebugEventT } from './debugger/debug-event.js'; export { Event } from './debugger/event.js'; -export { PauseEvent, PauseEventT } from './debugger/pause-event.js'; -export { RunEvent, RunEventT } from './debugger/run-event.js'; +export { GetStateRequest, GetStateRequestT } from './debugger/get-state-request.js'; +export { GetStateResponse, GetStateResponseT } from './debugger/get-state-response.js'; +export { PauseRequest, PauseRequestT } from './debugger/pause-request.js'; +export { RunRequest, RunRequestT } from './debugger/run-request.js'; +export { State } from './debugger/state.js'; diff --git a/page/src/fb/debugger/debug-event.ts b/page/src/fb/debugger/debug-event.ts index a34e10e9..96367434 100644 --- a/page/src/fb/debugger/debug-event.ts +++ b/page/src/fb/debugger/debug-event.ts @@ -5,8 +5,10 @@ import * as flatbuffers from 'flatbuffers'; import { Event, unionToEvent, unionListToEvent } from '../debugger/event.js'; -import { PauseEvent, PauseEventT } from '../debugger/pause-event.js'; -import { RunEvent, RunEventT } from '../debugger/run-event.js'; +import { GetStateRequest, GetStateRequestT } from '../debugger/get-state-request.js'; +import { GetStateResponse, GetStateResponseT } from '../debugger/get-state-response.js'; +import { PauseRequest, PauseRequestT } from '../debugger/pause-request.js'; +import { RunRequest, RunRequestT } from '../debugger/run-request.js'; export class DebugEvent implements flatbuffers.IUnpackableObject { @@ -94,7 +96,7 @@ unpackTo(_o: DebugEventT): void { export class DebugEventT implements flatbuffers.IGeneratedObject { constructor( public eventType: Event = Event.NONE, - public event: PauseEventT|RunEventT|null = null + public event: GetStateRequestT|GetStateResponseT|PauseRequestT|RunRequestT|null = null ){} diff --git a/page/src/fb/debugger/event.ts b/page/src/fb/debugger/event.ts index 1949c08e..6d5d0bbb 100644 --- a/page/src/fb/debugger/event.ts +++ b/page/src/fb/debugger/event.ts @@ -2,37 +2,45 @@ /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ -import { PauseEvent, PauseEventT } from '../debugger/pause-event.js'; -import { RunEvent, RunEventT } from '../debugger/run-event.js'; +import { GetStateRequest, GetStateRequestT } from '../debugger/get-state-request.js'; +import { GetStateResponse, GetStateResponseT } from '../debugger/get-state-response.js'; +import { PauseRequest, PauseRequestT } from '../debugger/pause-request.js'; +import { RunRequest, RunRequestT } from '../debugger/run-request.js'; export enum Event { NONE = 0, - PauseEvent = 1, - RunEvent = 2 + PauseRequest = 1, + RunRequest = 2, + GetStateRequest = 3, + GetStateResponse = 4 } export function unionToEvent( type: Event, - accessor: (obj:PauseEvent|RunEvent) => PauseEvent|RunEvent|null -): PauseEvent|RunEvent|null { + accessor: (obj:GetStateRequest|GetStateResponse|PauseRequest|RunRequest) => GetStateRequest|GetStateResponse|PauseRequest|RunRequest|null +): GetStateRequest|GetStateResponse|PauseRequest|RunRequest|null { switch(Event[type]) { case 'NONE': return null; - case 'PauseEvent': return accessor(new PauseEvent())! as PauseEvent; - case 'RunEvent': return accessor(new RunEvent())! as RunEvent; + case 'PauseRequest': return accessor(new PauseRequest())! as PauseRequest; + case 'RunRequest': return accessor(new RunRequest())! as RunRequest; + case 'GetStateRequest': return accessor(new GetStateRequest())! as GetStateRequest; + case 'GetStateResponse': return accessor(new GetStateResponse())! as GetStateResponse; default: return null; } } export function unionListToEvent( type: Event, - accessor: (index: number, obj:PauseEvent|RunEvent) => PauseEvent|RunEvent|null, + accessor: (index: number, obj:GetStateRequest|GetStateResponse|PauseRequest|RunRequest) => GetStateRequest|GetStateResponse|PauseRequest|RunRequest|null, index: number -): PauseEvent|RunEvent|null { +): GetStateRequest|GetStateResponse|PauseRequest|RunRequest|null { switch(Event[type]) { case 'NONE': return null; - case 'PauseEvent': return accessor(index, new PauseEvent())! as PauseEvent; - case 'RunEvent': return accessor(index, new RunEvent())! as RunEvent; + case 'PauseRequest': return accessor(index, new PauseRequest())! as PauseRequest; + case 'RunRequest': return accessor(index, new RunRequest())! as RunRequest; + case 'GetStateRequest': return accessor(index, new GetStateRequest())! as GetStateRequest; + case 'GetStateResponse': return accessor(index, new GetStateResponse())! as GetStateResponse; default: return null; } } diff --git a/page/src/fb/debugger/get-state-request.ts b/page/src/fb/debugger/get-state-request.ts new file mode 100644 index 00000000..8ec9ff10 --- /dev/null +++ b/page/src/fb/debugger/get-state-request.ts @@ -0,0 +1,56 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class GetStateRequest implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):GetStateRequest { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsGetStateRequest(bb:flatbuffers.ByteBuffer, obj?:GetStateRequest):GetStateRequest { + return (obj || new GetStateRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsGetStateRequest(bb:flatbuffers.ByteBuffer, obj?:GetStateRequest):GetStateRequest { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new GetStateRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static startGetStateRequest(builder:flatbuffers.Builder) { + builder.startObject(0); +} + +static endGetStateRequest(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createGetStateRequest(builder:flatbuffers.Builder):flatbuffers.Offset { + GetStateRequest.startGetStateRequest(builder); + return GetStateRequest.endGetStateRequest(builder); +} + +unpack(): GetStateRequestT { + return new GetStateRequestT(); +} + + +unpackTo(_o: GetStateRequestT): void {} +} + +export class GetStateRequestT implements flatbuffers.IGeneratedObject { +constructor(){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return GetStateRequest.createGetStateRequest(builder); +} +} diff --git a/page/src/fb/debugger/get-state-response.ts b/page/src/fb/debugger/get-state-response.ts new file mode 100644 index 00000000..f429791b --- /dev/null +++ b/page/src/fb/debugger/get-state-response.ts @@ -0,0 +1,86 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + +import { State } from '../debugger/state.js'; + + +export class GetStateResponse implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):GetStateResponse { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsGetStateResponse(bb:flatbuffers.ByteBuffer, obj?:GetStateResponse):GetStateResponse { + return (obj || new GetStateResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsGetStateResponse(bb:flatbuffers.ByteBuffer, obj?:GetStateResponse):GetStateResponse { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new GetStateResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +state():State { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : State.None; +} + +mutate_state(value:State):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint32(this.bb_pos + offset, value); + return true; +} + +static startGetStateResponse(builder:flatbuffers.Builder) { + builder.startObject(1); +} + +static addState(builder:flatbuffers.Builder, state:State) { + builder.addFieldInt32(0, state, State.None); +} + +static endGetStateResponse(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createGetStateResponse(builder:flatbuffers.Builder, state:State):flatbuffers.Offset { + GetStateResponse.startGetStateResponse(builder); + GetStateResponse.addState(builder, state); + return GetStateResponse.endGetStateResponse(builder); +} + +unpack(): GetStateResponseT { + return new GetStateResponseT( + this.state() + ); +} + + +unpackTo(_o: GetStateResponseT): void { + _o.state = this.state(); +} +} + +export class GetStateResponseT implements flatbuffers.IGeneratedObject { +constructor( + public state: State = State.None +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return GetStateResponse.createGetStateResponse(builder, + this.state + ); +} +} diff --git a/page/src/fb/debugger/pause-event.ts b/page/src/fb/debugger/pause-event.ts deleted file mode 100644 index ea56222b..00000000 --- a/page/src/fb/debugger/pause-event.ts +++ /dev/null @@ -1,56 +0,0 @@ -// automatically generated by the FlatBuffers compiler, do not modify - -/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ - -import * as flatbuffers from 'flatbuffers'; - - - -export class PauseEvent implements flatbuffers.IUnpackableObject { - bb: flatbuffers.ByteBuffer|null = null; - bb_pos = 0; - __init(i:number, bb:flatbuffers.ByteBuffer):PauseEvent { - this.bb_pos = i; - this.bb = bb; - return this; -} - -static getRootAsPauseEvent(bb:flatbuffers.ByteBuffer, obj?:PauseEvent):PauseEvent { - return (obj || new PauseEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); -} - -static getSizePrefixedRootAsPauseEvent(bb:flatbuffers.ByteBuffer, obj?:PauseEvent):PauseEvent { - bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); - return (obj || new PauseEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); -} - -static startPauseEvent(builder:flatbuffers.Builder) { - builder.startObject(0); -} - -static endPauseEvent(builder:flatbuffers.Builder):flatbuffers.Offset { - const offset = builder.endObject(); - return offset; -} - -static createPauseEvent(builder:flatbuffers.Builder):flatbuffers.Offset { - PauseEvent.startPauseEvent(builder); - return PauseEvent.endPauseEvent(builder); -} - -unpack(): PauseEventT { - return new PauseEventT(); -} - - -unpackTo(_o: PauseEventT): void {} -} - -export class PauseEventT implements flatbuffers.IGeneratedObject { -constructor(){} - - -pack(builder:flatbuffers.Builder): flatbuffers.Offset { - return PauseEvent.createPauseEvent(builder); -} -} diff --git a/page/src/fb/debugger/pause-request.ts b/page/src/fb/debugger/pause-request.ts new file mode 100644 index 00000000..1aa4564c --- /dev/null +++ b/page/src/fb/debugger/pause-request.ts @@ -0,0 +1,56 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class PauseRequest implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):PauseRequest { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsPauseRequest(bb:flatbuffers.ByteBuffer, obj?:PauseRequest):PauseRequest { + return (obj || new PauseRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsPauseRequest(bb:flatbuffers.ByteBuffer, obj?:PauseRequest):PauseRequest { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new PauseRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static startPauseRequest(builder:flatbuffers.Builder) { + builder.startObject(0); +} + +static endPauseRequest(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createPauseRequest(builder:flatbuffers.Builder):flatbuffers.Offset { + PauseRequest.startPauseRequest(builder); + return PauseRequest.endPauseRequest(builder); +} + +unpack(): PauseRequestT { + return new PauseRequestT(); +} + + +unpackTo(_o: PauseRequestT): void {} +} + +export class PauseRequestT implements flatbuffers.IGeneratedObject { +constructor(){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return PauseRequest.createPauseRequest(builder); +} +} diff --git a/page/src/fb/debugger/run-event.ts b/page/src/fb/debugger/run-request.ts similarity index 51% rename from page/src/fb/debugger/run-event.ts rename to page/src/fb/debugger/run-request.ts index 9502e4d5..d974c1ae 100644 --- a/page/src/fb/debugger/run-event.ts +++ b/page/src/fb/debugger/run-request.ts @@ -6,22 +6,22 @@ import * as flatbuffers from 'flatbuffers'; -export class RunEvent implements flatbuffers.IUnpackableObject { +export class RunRequest implements flatbuffers.IUnpackableObject { bb: flatbuffers.ByteBuffer|null = null; bb_pos = 0; - __init(i:number, bb:flatbuffers.ByteBuffer):RunEvent { + __init(i:number, bb:flatbuffers.ByteBuffer):RunRequest { this.bb_pos = i; this.bb = bb; return this; } -static getRootAsRunEvent(bb:flatbuffers.ByteBuffer, obj?:RunEvent):RunEvent { - return (obj || new RunEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +static getRootAsRunRequest(bb:flatbuffers.ByteBuffer, obj?:RunRequest):RunRequest { + return (obj || new RunRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); } -static getSizePrefixedRootAsRunEvent(bb:flatbuffers.ByteBuffer, obj?:RunEvent):RunEvent { +static getSizePrefixedRootAsRunRequest(bb:flatbuffers.ByteBuffer, obj?:RunRequest):RunRequest { bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); - return (obj || new RunEvent()).__init(bb.readInt32(bb.position()) + bb.position(), bb); + return (obj || new RunRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); } singleStep():boolean { @@ -40,7 +40,7 @@ mutate_single_step(value:boolean):boolean { return true; } -static startRunEvent(builder:flatbuffers.Builder) { +static startRunRequest(builder:flatbuffers.Builder) { builder.startObject(1); } @@ -48,37 +48,37 @@ static addSingleStep(builder:flatbuffers.Builder, singleStep:boolean) { builder.addFieldInt8(0, +singleStep, +false); } -static endRunEvent(builder:flatbuffers.Builder):flatbuffers.Offset { +static endRunRequest(builder:flatbuffers.Builder):flatbuffers.Offset { const offset = builder.endObject(); return offset; } -static createRunEvent(builder:flatbuffers.Builder, singleStep:boolean):flatbuffers.Offset { - RunEvent.startRunEvent(builder); - RunEvent.addSingleStep(builder, singleStep); - return RunEvent.endRunEvent(builder); +static createRunRequest(builder:flatbuffers.Builder, singleStep:boolean):flatbuffers.Offset { + RunRequest.startRunRequest(builder); + RunRequest.addSingleStep(builder, singleStep); + return RunRequest.endRunRequest(builder); } -unpack(): RunEventT { - return new RunEventT( +unpack(): RunRequestT { + return new RunRequestT( this.singleStep() ); } -unpackTo(_o: RunEventT): void { +unpackTo(_o: RunRequestT): void { _o.singleStep = this.singleStep(); } } -export class RunEventT implements flatbuffers.IGeneratedObject { +export class RunRequestT implements flatbuffers.IGeneratedObject { constructor( public singleStep: boolean = false ){} pack(builder:flatbuffers.Builder): flatbuffers.Offset { - return RunEvent.createRunEvent(builder, + return RunRequest.createRunRequest(builder, this.singleStep ); } diff --git a/page/src/fb/debugger/state.ts b/page/src/fb/debugger/state.ts new file mode 100644 index 00000000..01be2fac --- /dev/null +++ b/page/src/fb/debugger/state.ts @@ -0,0 +1,9 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +export enum State { + None = 0, + Running = 1, + Paused = 2 +} diff --git a/src/debugger/event_handler.cpp b/src/debugger/event_handler.cpp index e701c621..b6d65591 100644 --- a/src/debugger/event_handler.cpp +++ b/src/debugger/event_handler.cpp @@ -40,16 +40,64 @@ namespace debugger return {std::move(e)}; } + void send_event(const Debugger::DebugEventT& event) + { + flatbuffers::FlatBufferBuilder fbb{}; + fbb.Finish(Debugger::DebugEvent::Pack(fbb, &event)); + + const std::string_view buffer(reinterpret_cast(fbb.GetBufferPointer()), fbb.GetSize()); + const auto message = base64::to_base64(buffer); + + send_message(message); + } + + template + requires(!std::is_same_v, Debugger::DebugEventT>) + void send_event(T event) + { + Debugger::DebugEventT e{}; + e.event.Set(std::move(event)); + send_event(e); + } + + Debugger::State translate_state(const emulation_state state) + { + switch (state) + { + case emulation_state::paused: + return Debugger::State_Paused; + + case emulation_state::none: + case emulation_state::running: + return Debugger::State_Running; + + default: + return Debugger::State_None; + } + } + + void handle_get_state_request(const event_context& c) + { + Debugger::GetStateResponseT stateResponse{}; + stateResponse.state = translate_state(c.state); + + send_event(stateResponse); + } + void handle_event(event_context& c, const Debugger::DebugEventT& e) { switch (e.event.type) { - case Debugger::Event_PauseEvent: - c.win_emu.emu().stop(); + case Debugger::Event_PauseRequest: + c.state = emulation_state::paused; break; - case Debugger::Event_RunEvent: - c.resume = true; + case Debugger::Event_RunRequest: + c.state = emulation_state::running; + break; + + case Debugger::Event_GetStateRequest: + handle_get_state_request(c); break; default: @@ -58,7 +106,7 @@ namespace debugger } } - void handle_events(event_context& c) + void handle_events_once(event_context& c) { while (true) { @@ -73,4 +121,19 @@ namespace debugger handle_event(c, *e); } } + + void handle_events(event_context& c) + { + while (true) + { + handle_events_once(c); + + if (c.state != emulation_state::paused) + { + break; + } + + suspend_execution(2ms); + } + } } \ No newline at end of file diff --git a/src/debugger/event_handler.hpp b/src/debugger/event_handler.hpp index acdb3fa3..0e052fe6 100644 --- a/src/debugger/event_handler.hpp +++ b/src/debugger/event_handler.hpp @@ -4,10 +4,17 @@ namespace debugger { + enum class emulation_state + { + none, + running, + paused, + }; + struct event_context { windows_emulator& win_emu; - bool resume{false}; + emulation_state state{emulation_state::none}; }; void handle_events(event_context& c); diff --git a/src/debugger/events.fbs b/src/debugger/events.fbs index 15095c10..76c502ed 100644 --- a/src/debugger/events.fbs +++ b/src/debugger/events.fbs @@ -1,14 +1,28 @@ namespace Debugger; -table PauseEvent {} +table GetStateRequest {} -table RunEvent { +enum State : uint32 { + None = 0, + Running, + Paused, +} + +table GetStateResponse { + state: State; +} + +table PauseRequest {} + +table RunRequest { single_step: bool; } union Event { - PauseEvent, - RunEvent, + PauseRequest, + RunRequest, + GetStateRequest, + GetStateResponse, } table DebugEvent { diff --git a/src/debugger/events_generated.hxx b/src/debugger/events_generated.hxx index 3e9be171..82cc1b9f 100644 --- a/src/debugger/events_generated.hxx +++ b/src/debugger/events_generated.hxx @@ -15,47 +15,94 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && namespace Debugger { -struct PauseEvent; -struct PauseEventBuilder; -struct PauseEventT; +struct GetStateRequest; +struct GetStateRequestBuilder; +struct GetStateRequestT; -struct RunEvent; -struct RunEventBuilder; -struct RunEventT; +struct GetStateResponse; +struct GetStateResponseBuilder; +struct GetStateResponseT; + +struct PauseRequest; +struct PauseRequestBuilder; +struct PauseRequestT; + +struct RunRequest; +struct RunRequestBuilder; +struct RunRequestT; struct DebugEvent; struct DebugEventBuilder; struct DebugEventT; -enum Event : uint8_t { - Event_NONE = 0, - Event_PauseEvent = 1, - Event_RunEvent = 2, - Event_MIN = Event_NONE, - Event_MAX = Event_RunEvent +enum State : uint32_t { + State_None = 0, + State_Running = 1, + State_Paused = 2, + State_MIN = State_None, + State_MAX = State_Paused }; -inline const Event (&EnumValuesEvent())[3] { +inline const State (&EnumValuesState())[3] { + static const State values[] = { + State_None, + State_Running, + State_Paused + }; + return values; +} + +inline const char * const *EnumNamesState() { + static const char * const names[4] = { + "None", + "Running", + "Paused", + nullptr + }; + return names; +} + +inline const char *EnumNameState(State e) { + if (::flatbuffers::IsOutRange(e, State_None, State_Paused)) return ""; + const size_t index = static_cast(e); + return EnumNamesState()[index]; +} + +enum Event : uint8_t { + Event_NONE = 0, + Event_PauseRequest = 1, + Event_RunRequest = 2, + Event_GetStateRequest = 3, + Event_GetStateResponse = 4, + Event_MIN = Event_NONE, + Event_MAX = Event_GetStateResponse +}; + +inline const Event (&EnumValuesEvent())[5] { static const Event values[] = { Event_NONE, - Event_PauseEvent, - Event_RunEvent + Event_PauseRequest, + Event_RunRequest, + Event_GetStateRequest, + Event_GetStateResponse }; return values; } inline const char * const *EnumNamesEvent() { - static const char * const names[4] = { + static const char * const names[6] = { "NONE", - "PauseEvent", - "RunEvent", + "PauseRequest", + "RunRequest", + "GetStateRequest", + "GetStateResponse", nullptr }; return names; } inline const char *EnumNameEvent(Event e) { - if (::flatbuffers::IsOutRange(e, Event_NONE, Event_RunEvent)) return ""; + if (::flatbuffers::IsOutRange(e, Event_NONE, Event_GetStateResponse)) return ""; const size_t index = static_cast(e); return EnumNamesEvent()[index]; } @@ -64,24 +111,40 @@ template struct EventTraits { static const Event enum_value = Event_NONE; }; -template<> struct EventTraits { - static const Event enum_value = Event_PauseEvent; +template<> struct EventTraits { + static const Event enum_value = Event_PauseRequest; }; -template<> struct EventTraits { - static const Event enum_value = Event_RunEvent; +template<> struct EventTraits { + static const Event enum_value = Event_RunRequest; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_GetStateRequest; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_GetStateResponse; }; template struct EventUnionTraits { static const Event enum_value = Event_NONE; }; -template<> struct EventUnionTraits { - static const Event enum_value = Event_PauseEvent; +template<> struct EventUnionTraits { + static const Event enum_value = Event_PauseRequest; }; -template<> struct EventUnionTraits { - static const Event enum_value = Event_RunEvent; +template<> struct EventUnionTraits { + static const Event enum_value = Event_RunRequest; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_GetStateRequest; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_GetStateResponse; }; struct EventUnion { @@ -114,74 +177,184 @@ struct EventUnion { static void *UnPack(const void *obj, Event type, const ::flatbuffers::resolver_function_t *resolver); ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr) const; - Debugger::PauseEventT *AsPauseEvent() { - return type == Event_PauseEvent ? - reinterpret_cast(value) : nullptr; + Debugger::PauseRequestT *AsPauseRequest() { + return type == Event_PauseRequest ? + reinterpret_cast(value) : nullptr; } - const Debugger::PauseEventT *AsPauseEvent() const { - return type == Event_PauseEvent ? - reinterpret_cast(value) : nullptr; + const Debugger::PauseRequestT *AsPauseRequest() const { + return type == Event_PauseRequest ? + reinterpret_cast(value) : nullptr; } - Debugger::RunEventT *AsRunEvent() { - return type == Event_RunEvent ? - reinterpret_cast(value) : nullptr; + Debugger::RunRequestT *AsRunRequest() { + return type == Event_RunRequest ? + reinterpret_cast(value) : nullptr; } - const Debugger::RunEventT *AsRunEvent() const { - return type == Event_RunEvent ? - reinterpret_cast(value) : nullptr; + const Debugger::RunRequestT *AsRunRequest() const { + return type == Event_RunRequest ? + reinterpret_cast(value) : nullptr; + } + Debugger::GetStateRequestT *AsGetStateRequest() { + return type == Event_GetStateRequest ? + reinterpret_cast(value) : nullptr; + } + const Debugger::GetStateRequestT *AsGetStateRequest() const { + return type == Event_GetStateRequest ? + reinterpret_cast(value) : nullptr; + } + Debugger::GetStateResponseT *AsGetStateResponse() { + return type == Event_GetStateResponse ? + reinterpret_cast(value) : nullptr; + } + const Debugger::GetStateResponseT *AsGetStateResponse() const { + return type == Event_GetStateResponse ? + reinterpret_cast(value) : nullptr; } }; bool VerifyEvent(::flatbuffers::Verifier &verifier, const void *obj, Event type); bool VerifyEventVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset> *values, const ::flatbuffers::Vector *types); -struct PauseEventT : public ::flatbuffers::NativeTable { - typedef PauseEvent TableType; +struct GetStateRequestT : public ::flatbuffers::NativeTable { + typedef GetStateRequest TableType; }; -struct PauseEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef PauseEventT NativeTableType; - typedef PauseEventBuilder Builder; +struct GetStateRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef GetStateRequestT NativeTableType; + typedef GetStateRequestBuilder Builder; bool Verify(::flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && verifier.EndTable(); } - PauseEventT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; - void UnPackTo(PauseEventT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; - static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const PauseEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + GetStateRequestT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(GetStateRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const GetStateRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); }; -struct PauseEventBuilder { - typedef PauseEvent Table; +struct GetStateRequestBuilder { + typedef GetStateRequest Table; ::flatbuffers::FlatBufferBuilder &fbb_; ::flatbuffers::uoffset_t start_; - explicit PauseEventBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + explicit GetStateRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ::flatbuffers::Offset Finish() { + ::flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); + auto o = ::flatbuffers::Offset(end); return o; } }; -inline ::flatbuffers::Offset CreatePauseEvent( +inline ::flatbuffers::Offset CreateGetStateRequest( ::flatbuffers::FlatBufferBuilder &_fbb) { - PauseEventBuilder builder_(_fbb); + GetStateRequestBuilder builder_(_fbb); return builder_.Finish(); } -::flatbuffers::Offset CreatePauseEvent(::flatbuffers::FlatBufferBuilder &_fbb, const PauseEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +::flatbuffers::Offset CreateGetStateRequest(::flatbuffers::FlatBufferBuilder &_fbb, const GetStateRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); -struct RunEventT : public ::flatbuffers::NativeTable { - typedef RunEvent TableType; +struct GetStateResponseT : public ::flatbuffers::NativeTable { + typedef GetStateResponse TableType; + Debugger::State state = Debugger::State_None; +}; + +struct GetStateResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef GetStateResponseT NativeTableType; + typedef GetStateResponseBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_STATE = 4 + }; + Debugger::State state() const { + return static_cast(GetField(VT_STATE, 0)); + } + bool mutate_state(Debugger::State _state = static_cast(0)) { + return SetField(VT_STATE, static_cast(_state), 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_STATE, 4) && + verifier.EndTable(); + } + GetStateResponseT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(GetStateResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const GetStateResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct GetStateResponseBuilder { + typedef GetStateResponse Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_state(Debugger::State state) { + fbb_.AddElement(GetStateResponse::VT_STATE, static_cast(state), 0); + } + explicit GetStateResponseBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateGetStateResponse( + ::flatbuffers::FlatBufferBuilder &_fbb, + Debugger::State state = Debugger::State_None) { + GetStateResponseBuilder builder_(_fbb); + builder_.add_state(state); + return builder_.Finish(); +} + +::flatbuffers::Offset CreateGetStateResponse(::flatbuffers::FlatBufferBuilder &_fbb, const GetStateResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct PauseRequestT : public ::flatbuffers::NativeTable { + typedef PauseRequest TableType; +}; + +struct PauseRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef PauseRequestT NativeTableType; + typedef PauseRequestBuilder Builder; + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + PauseRequestT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(PauseRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const PauseRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct PauseRequestBuilder { + typedef PauseRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + explicit PauseRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreatePauseRequest( + ::flatbuffers::FlatBufferBuilder &_fbb) { + PauseRequestBuilder builder_(_fbb); + return builder_.Finish(); +} + +::flatbuffers::Offset CreatePauseRequest(::flatbuffers::FlatBufferBuilder &_fbb, const PauseRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct RunRequestT : public ::flatbuffers::NativeTable { + typedef RunRequest TableType; bool single_step = false; }; -struct RunEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef RunEventT NativeTableType; - typedef RunEventBuilder Builder; +struct RunRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef RunRequestT NativeTableType; + typedef RunRequestBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_SINGLE_STEP = 4 }; @@ -196,38 +369,38 @@ struct RunEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VerifyField(verifier, VT_SINGLE_STEP, 1) && verifier.EndTable(); } - RunEventT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; - void UnPackTo(RunEventT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; - static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + RunRequestT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RunRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RunRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); }; -struct RunEventBuilder { - typedef RunEvent Table; +struct RunRequestBuilder { + typedef RunRequest Table; ::flatbuffers::FlatBufferBuilder &fbb_; ::flatbuffers::uoffset_t start_; void add_single_step(bool single_step) { - fbb_.AddElement(RunEvent::VT_SINGLE_STEP, static_cast(single_step), 0); + fbb_.AddElement(RunRequest::VT_SINGLE_STEP, static_cast(single_step), 0); } - explicit RunEventBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + explicit RunRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ::flatbuffers::Offset Finish() { + ::flatbuffers::Offset Finish() { const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); + auto o = ::flatbuffers::Offset(end); return o; } }; -inline ::flatbuffers::Offset CreateRunEvent( +inline ::flatbuffers::Offset CreateRunRequest( ::flatbuffers::FlatBufferBuilder &_fbb, bool single_step = false) { - RunEventBuilder builder_(_fbb); + RunRequestBuilder builder_(_fbb); builder_.add_single_step(single_step); return builder_.Finish(); } -::flatbuffers::Offset CreateRunEvent(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +::flatbuffers::Offset CreateRunRequest(::flatbuffers::FlatBufferBuilder &_fbb, const RunRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); struct DebugEventT : public ::flatbuffers::NativeTable { typedef DebugEvent TableType; @@ -248,11 +421,17 @@ struct DebugEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { return GetPointer(VT_EVENT); } template const T *event_as() const; - const Debugger::PauseEvent *event_as_PauseEvent() const { - return event_type() == Debugger::Event_PauseEvent ? static_cast(event()) : nullptr; + const Debugger::PauseRequest *event_as_PauseRequest() const { + return event_type() == Debugger::Event_PauseRequest ? static_cast(event()) : nullptr; } - const Debugger::RunEvent *event_as_RunEvent() const { - return event_type() == Debugger::Event_RunEvent ? static_cast(event()) : nullptr; + const Debugger::RunRequest *event_as_RunRequest() const { + return event_type() == Debugger::Event_RunRequest ? static_cast(event()) : nullptr; + } + const Debugger::GetStateRequest *event_as_GetStateRequest() const { + return event_type() == Debugger::Event_GetStateRequest ? static_cast(event()) : nullptr; + } + const Debugger::GetStateResponse *event_as_GetStateResponse() const { + return event_type() == Debugger::Event_GetStateResponse ? static_cast(event()) : nullptr; } void *mutable_event() { return GetPointer(VT_EVENT); @@ -269,12 +448,20 @@ struct DebugEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const DebugEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); }; -template<> inline const Debugger::PauseEvent *DebugEvent::event_as() const { - return event_as_PauseEvent(); +template<> inline const Debugger::PauseRequest *DebugEvent::event_as() const { + return event_as_PauseRequest(); } -template<> inline const Debugger::RunEvent *DebugEvent::event_as() const { - return event_as_RunEvent(); +template<> inline const Debugger::RunRequest *DebugEvent::event_as() const { + return event_as_RunRequest(); +} + +template<> inline const Debugger::GetStateRequest *DebugEvent::event_as() const { + return event_as_GetStateRequest(); +} + +template<> inline const Debugger::GetStateResponse *DebugEvent::event_as() const { + return event_as_GetStateResponse(); } struct DebugEventBuilder { @@ -310,51 +497,100 @@ inline ::flatbuffers::Offset CreateDebugEvent( ::flatbuffers::Offset CreateDebugEvent(::flatbuffers::FlatBufferBuilder &_fbb, const DebugEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); -inline PauseEventT *PauseEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { - auto _o = std::unique_ptr(new PauseEventT()); +inline GetStateRequestT *GetStateRequest::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new GetStateRequestT()); UnPackTo(_o.get(), _resolver); return _o.release(); } -inline void PauseEvent::UnPackTo(PauseEventT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { +inline void GetStateRequest::UnPackTo(GetStateRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; } -inline ::flatbuffers::Offset PauseEvent::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const PauseEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { - return CreatePauseEvent(_fbb, _o, _rehasher); +inline ::flatbuffers::Offset GetStateRequest::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const GetStateRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateGetStateRequest(_fbb, _o, _rehasher); } -inline ::flatbuffers::Offset CreatePauseEvent(::flatbuffers::FlatBufferBuilder &_fbb, const PauseEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { +inline ::flatbuffers::Offset CreateGetStateRequest(::flatbuffers::FlatBufferBuilder &_fbb, const GetStateRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; - struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const PauseEventT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; - return Debugger::CreatePauseEvent( + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const GetStateRequestT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return Debugger::CreateGetStateRequest( _fbb); } -inline RunEventT *RunEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { - auto _o = std::unique_ptr(new RunEventT()); +inline GetStateResponseT *GetStateResponse::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new GetStateResponseT()); UnPackTo(_o.get(), _resolver); return _o.release(); } -inline void RunEvent::UnPackTo(RunEventT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { +inline void GetStateResponse::UnPackTo(GetStateResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = state(); _o->state = _e; } +} + +inline ::flatbuffers::Offset GetStateResponse::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const GetStateResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateGetStateResponse(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateGetStateResponse(::flatbuffers::FlatBufferBuilder &_fbb, const GetStateResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const GetStateResponseT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _state = _o->state; + return Debugger::CreateGetStateResponse( + _fbb, + _state); +} + +inline PauseRequestT *PauseRequest::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new PauseRequestT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void PauseRequest::UnPackTo(PauseRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline ::flatbuffers::Offset PauseRequest::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const PauseRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreatePauseRequest(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreatePauseRequest(::flatbuffers::FlatBufferBuilder &_fbb, const PauseRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const PauseRequestT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return Debugger::CreatePauseRequest( + _fbb); +} + +inline RunRequestT *RunRequest::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new RunRequestT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RunRequest::UnPackTo(RunRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; { auto _e = single_step(); _o->single_step = _e; } } -inline ::flatbuffers::Offset RunEvent::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { - return CreateRunEvent(_fbb, _o, _rehasher); +inline ::flatbuffers::Offset RunRequest::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RunRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateRunRequest(_fbb, _o, _rehasher); } -inline ::flatbuffers::Offset CreateRunEvent(::flatbuffers::FlatBufferBuilder &_fbb, const RunEventT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { +inline ::flatbuffers::Offset CreateRunRequest(::flatbuffers::FlatBufferBuilder &_fbb, const RunRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { (void)_rehasher; (void)_o; - struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const RunEventT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const RunRequestT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _single_step = _o->single_step; - return Debugger::CreateRunEvent( + return Debugger::CreateRunRequest( _fbb, _single_step); } @@ -393,12 +629,20 @@ inline bool VerifyEvent(::flatbuffers::Verifier &verifier, const void *obj, Even case Event_NONE: { return true; } - case Event_PauseEvent: { - auto ptr = reinterpret_cast(obj); + case Event_PauseRequest: { + auto ptr = reinterpret_cast(obj); return verifier.VerifyTable(ptr); } - case Event_RunEvent: { - auto ptr = reinterpret_cast(obj); + case Event_RunRequest: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_GetStateRequest: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_GetStateResponse: { + auto ptr = reinterpret_cast(obj); return verifier.VerifyTable(ptr); } default: return true; @@ -420,12 +664,20 @@ inline bool VerifyEventVector(::flatbuffers::Verifier &verifier, const ::flatbuf inline void *EventUnion::UnPack(const void *obj, Event type, const ::flatbuffers::resolver_function_t *resolver) { (void)resolver; switch (type) { - case Event_PauseEvent: { - auto ptr = reinterpret_cast(obj); + case Event_PauseRequest: { + auto ptr = reinterpret_cast(obj); return ptr->UnPack(resolver); } - case Event_RunEvent: { - auto ptr = reinterpret_cast(obj); + case Event_RunRequest: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_GetStateRequest: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_GetStateResponse: { + auto ptr = reinterpret_cast(obj); return ptr->UnPack(resolver); } default: return nullptr; @@ -435,13 +687,21 @@ inline void *EventUnion::UnPack(const void *obj, Event type, const ::flatbuffers inline ::flatbuffers::Offset EventUnion::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ::flatbuffers::rehasher_function_t *_rehasher) const { (void)_rehasher; switch (type) { - case Event_PauseEvent: { - auto ptr = reinterpret_cast(value); - return CreatePauseEvent(_fbb, ptr, _rehasher).Union(); + case Event_PauseRequest: { + auto ptr = reinterpret_cast(value); + return CreatePauseRequest(_fbb, ptr, _rehasher).Union(); } - case Event_RunEvent: { - auto ptr = reinterpret_cast(value); - return CreateRunEvent(_fbb, ptr, _rehasher).Union(); + case Event_RunRequest: { + auto ptr = reinterpret_cast(value); + return CreateRunRequest(_fbb, ptr, _rehasher).Union(); + } + case Event_GetStateRequest: { + auto ptr = reinterpret_cast(value); + return CreateGetStateRequest(_fbb, ptr, _rehasher).Union(); + } + case Event_GetStateResponse: { + auto ptr = reinterpret_cast(value); + return CreateGetStateResponse(_fbb, ptr, _rehasher).Union(); } default: return 0; } @@ -449,12 +709,20 @@ inline ::flatbuffers::Offset EventUnion::Pack(::flatbuffers::FlatBufferBui inline EventUnion::EventUnion(const EventUnion &u) : type(u.type), value(nullptr) { switch (type) { - case Event_PauseEvent: { - value = new Debugger::PauseEventT(*reinterpret_cast(u.value)); + case Event_PauseRequest: { + value = new Debugger::PauseRequestT(*reinterpret_cast(u.value)); break; } - case Event_RunEvent: { - value = new Debugger::RunEventT(*reinterpret_cast(u.value)); + case Event_RunRequest: { + value = new Debugger::RunRequestT(*reinterpret_cast(u.value)); + break; + } + case Event_GetStateRequest: { + value = new Debugger::GetStateRequestT(*reinterpret_cast(u.value)); + break; + } + case Event_GetStateResponse: { + value = new Debugger::GetStateResponseT(*reinterpret_cast(u.value)); break; } default: @@ -464,13 +732,23 @@ inline EventUnion::EventUnion(const EventUnion &u) : type(u.type), value(nullptr inline void EventUnion::Reset() { switch (type) { - case Event_PauseEvent: { - auto ptr = reinterpret_cast(value); + case Event_PauseRequest: { + auto ptr = reinterpret_cast(value); delete ptr; break; } - case Event_RunEvent: { - auto ptr = reinterpret_cast(value); + case Event_RunRequest: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_GetStateRequest: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_GetStateResponse: { + auto ptr = reinterpret_cast(value); delete ptr; break; } From f7e91fc64e96a532d2c1edaf894ee62671405b8e Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 28 Apr 2025 14:03:37 +0200 Subject: [PATCH 11/17] Support reading and writing memory --- page/src/fb/debugger.ts | 4 + page/src/fb/debugger/debug-event.ts | 6 +- page/src/fb/debugger/event.ts | 26 +- page/src/fb/debugger/read-memory-request.ts | 110 +++ page/src/fb/debugger/read-memory-response.ts | 123 ++++ page/src/fb/debugger/write-memory-request.ts | 123 ++++ page/src/fb/debugger/write-memory-response.ts | 135 ++++ src/debugger/event_handler.cpp | 57 +- src/debugger/events.fbs | 25 + src/debugger/events_generated.hxx | 647 +++++++++++++++++- 10 files changed, 1240 insertions(+), 16 deletions(-) create mode 100644 page/src/fb/debugger/read-memory-request.ts create mode 100644 page/src/fb/debugger/read-memory-response.ts create mode 100644 page/src/fb/debugger/write-memory-request.ts create mode 100644 page/src/fb/debugger/write-memory-response.ts diff --git a/page/src/fb/debugger.ts b/page/src/fb/debugger.ts index ffde813b..babc30f3 100644 --- a/page/src/fb/debugger.ts +++ b/page/src/fb/debugger.ts @@ -7,5 +7,9 @@ export { Event } from './debugger/event.js'; export { GetStateRequest, GetStateRequestT } from './debugger/get-state-request.js'; export { GetStateResponse, GetStateResponseT } from './debugger/get-state-response.js'; export { PauseRequest, PauseRequestT } from './debugger/pause-request.js'; +export { ReadMemoryRequest, ReadMemoryRequestT } from './debugger/read-memory-request.js'; +export { ReadMemoryResponse, ReadMemoryResponseT } from './debugger/read-memory-response.js'; export { RunRequest, RunRequestT } from './debugger/run-request.js'; export { State } from './debugger/state.js'; +export { WriteMemoryRequest, WriteMemoryRequestT } from './debugger/write-memory-request.js'; +export { WriteMemoryResponse, WriteMemoryResponseT } from './debugger/write-memory-response.js'; diff --git a/page/src/fb/debugger/debug-event.ts b/page/src/fb/debugger/debug-event.ts index 96367434..afb57ec2 100644 --- a/page/src/fb/debugger/debug-event.ts +++ b/page/src/fb/debugger/debug-event.ts @@ -8,7 +8,11 @@ import { Event, unionToEvent, unionListToEvent } from '../debugger/event.js'; import { GetStateRequest, GetStateRequestT } from '../debugger/get-state-request.js'; import { GetStateResponse, GetStateResponseT } from '../debugger/get-state-response.js'; import { PauseRequest, PauseRequestT } from '../debugger/pause-request.js'; +import { ReadMemoryRequest, ReadMemoryRequestT } from '../debugger/read-memory-request.js'; +import { ReadMemoryResponse, ReadMemoryResponseT } from '../debugger/read-memory-response.js'; import { RunRequest, RunRequestT } from '../debugger/run-request.js'; +import { WriteMemoryRequest, WriteMemoryRequestT } from '../debugger/write-memory-request.js'; +import { WriteMemoryResponse, WriteMemoryResponseT } from '../debugger/write-memory-response.js'; export class DebugEvent implements flatbuffers.IUnpackableObject { @@ -96,7 +100,7 @@ unpackTo(_o: DebugEventT): void { export class DebugEventT implements flatbuffers.IGeneratedObject { constructor( public eventType: Event = Event.NONE, - public event: GetStateRequestT|GetStateResponseT|PauseRequestT|RunRequestT|null = null + public event: GetStateRequestT|GetStateResponseT|PauseRequestT|ReadMemoryRequestT|ReadMemoryResponseT|RunRequestT|WriteMemoryRequestT|WriteMemoryResponseT|null = null ){} diff --git a/page/src/fb/debugger/event.ts b/page/src/fb/debugger/event.ts index 6d5d0bbb..6b249b2b 100644 --- a/page/src/fb/debugger/event.ts +++ b/page/src/fb/debugger/event.ts @@ -5,7 +5,11 @@ import { GetStateRequest, GetStateRequestT } from '../debugger/get-state-request.js'; import { GetStateResponse, GetStateResponseT } from '../debugger/get-state-response.js'; import { PauseRequest, PauseRequestT } from '../debugger/pause-request.js'; +import { ReadMemoryRequest, ReadMemoryRequestT } from '../debugger/read-memory-request.js'; +import { ReadMemoryResponse, ReadMemoryResponseT } from '../debugger/read-memory-response.js'; import { RunRequest, RunRequestT } from '../debugger/run-request.js'; +import { WriteMemoryRequest, WriteMemoryRequestT } from '../debugger/write-memory-request.js'; +import { WriteMemoryResponse, WriteMemoryResponseT } from '../debugger/write-memory-response.js'; export enum Event { @@ -13,34 +17,46 @@ export enum Event { PauseRequest = 1, RunRequest = 2, GetStateRequest = 3, - GetStateResponse = 4 + GetStateResponse = 4, + WriteMemoryRequest = 5, + WriteMemoryResponse = 6, + ReadMemoryRequest = 7, + ReadMemoryResponse = 8 } export function unionToEvent( type: Event, - accessor: (obj:GetStateRequest|GetStateResponse|PauseRequest|RunRequest) => GetStateRequest|GetStateResponse|PauseRequest|RunRequest|null -): GetStateRequest|GetStateResponse|PauseRequest|RunRequest|null { + accessor: (obj:GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse) => GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|null +): GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|null { switch(Event[type]) { case 'NONE': return null; case 'PauseRequest': return accessor(new PauseRequest())! as PauseRequest; case 'RunRequest': return accessor(new RunRequest())! as RunRequest; case 'GetStateRequest': return accessor(new GetStateRequest())! as GetStateRequest; case 'GetStateResponse': return accessor(new GetStateResponse())! as GetStateResponse; + case 'WriteMemoryRequest': return accessor(new WriteMemoryRequest())! as WriteMemoryRequest; + case 'WriteMemoryResponse': return accessor(new WriteMemoryResponse())! as WriteMemoryResponse; + case 'ReadMemoryRequest': return accessor(new ReadMemoryRequest())! as ReadMemoryRequest; + case 'ReadMemoryResponse': return accessor(new ReadMemoryResponse())! as ReadMemoryResponse; default: return null; } } export function unionListToEvent( type: Event, - accessor: (index: number, obj:GetStateRequest|GetStateResponse|PauseRequest|RunRequest) => GetStateRequest|GetStateResponse|PauseRequest|RunRequest|null, + accessor: (index: number, obj:GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse) => GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|null, index: number -): GetStateRequest|GetStateResponse|PauseRequest|RunRequest|null { +): GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|null { switch(Event[type]) { case 'NONE': return null; case 'PauseRequest': return accessor(index, new PauseRequest())! as PauseRequest; case 'RunRequest': return accessor(index, new RunRequest())! as RunRequest; case 'GetStateRequest': return accessor(index, new GetStateRequest())! as GetStateRequest; case 'GetStateResponse': return accessor(index, new GetStateResponse())! as GetStateResponse; + case 'WriteMemoryRequest': return accessor(index, new WriteMemoryRequest())! as WriteMemoryRequest; + case 'WriteMemoryResponse': return accessor(index, new WriteMemoryResponse())! as WriteMemoryResponse; + case 'ReadMemoryRequest': return accessor(index, new ReadMemoryRequest())! as ReadMemoryRequest; + case 'ReadMemoryResponse': return accessor(index, new ReadMemoryResponse())! as ReadMemoryResponse; default: return null; } } diff --git a/page/src/fb/debugger/read-memory-request.ts b/page/src/fb/debugger/read-memory-request.ts new file mode 100644 index 00000000..5779ac60 --- /dev/null +++ b/page/src/fb/debugger/read-memory-request.ts @@ -0,0 +1,110 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class ReadMemoryRequest implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):ReadMemoryRequest { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsReadMemoryRequest(bb:flatbuffers.ByteBuffer, obj?:ReadMemoryRequest):ReadMemoryRequest { + return (obj || new ReadMemoryRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsReadMemoryRequest(bb:flatbuffers.ByteBuffer, obj?:ReadMemoryRequest):ReadMemoryRequest { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new ReadMemoryRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +address():bigint { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint64(this.bb_pos + offset) : BigInt('0'); +} + +mutate_address(value:bigint):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint64(this.bb_pos + offset, value); + return true; +} + +size():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +mutate_size(value:number):boolean { + const offset = this.bb!.__offset(this.bb_pos, 6); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint32(this.bb_pos + offset, value); + return true; +} + +static startReadMemoryRequest(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addAddress(builder:flatbuffers.Builder, address:bigint) { + builder.addFieldInt64(0, address, BigInt('0')); +} + +static addSize(builder:flatbuffers.Builder, size:number) { + builder.addFieldInt32(1, size, 0); +} + +static endReadMemoryRequest(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createReadMemoryRequest(builder:flatbuffers.Builder, address:bigint, size:number):flatbuffers.Offset { + ReadMemoryRequest.startReadMemoryRequest(builder); + ReadMemoryRequest.addAddress(builder, address); + ReadMemoryRequest.addSize(builder, size); + return ReadMemoryRequest.endReadMemoryRequest(builder); +} + +unpack(): ReadMemoryRequestT { + return new ReadMemoryRequestT( + this.address(), + this.size() + ); +} + + +unpackTo(_o: ReadMemoryRequestT): void { + _o.address = this.address(); + _o.size = this.size(); +} +} + +export class ReadMemoryRequestT implements flatbuffers.IGeneratedObject { +constructor( + public address: bigint = BigInt('0'), + public size: number = 0 +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return ReadMemoryRequest.createReadMemoryRequest(builder, + this.address, + this.size + ); +} +} diff --git a/page/src/fb/debugger/read-memory-response.ts b/page/src/fb/debugger/read-memory-response.ts new file mode 100644 index 00000000..9e0b38c1 --- /dev/null +++ b/page/src/fb/debugger/read-memory-response.ts @@ -0,0 +1,123 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class ReadMemoryResponse implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):ReadMemoryResponse { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsReadMemoryResponse(bb:flatbuffers.ByteBuffer, obj?:ReadMemoryResponse):ReadMemoryResponse { + return (obj || new ReadMemoryResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsReadMemoryResponse(bb:flatbuffers.ByteBuffer, obj?:ReadMemoryResponse):ReadMemoryResponse { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new ReadMemoryResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +address():bigint { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint64(this.bb_pos + offset) : BigInt('0'); +} + +mutate_address(value:bigint):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint64(this.bb_pos + offset, value); + return true; +} + +data(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint8(this.bb!.__vector(this.bb_pos + offset) + index) : 0; +} + +dataLength():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +dataArray():Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? new Uint8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +static startReadMemoryResponse(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addAddress(builder:flatbuffers.Builder, address:bigint) { + builder.addFieldInt64(0, address, BigInt('0')); +} + +static addData(builder:flatbuffers.Builder, dataOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, dataOffset, 0); +} + +static createDataVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset { + builder.startVector(1, data.length, 1); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt8(data[i]!); + } + return builder.endVector(); +} + +static startDataVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(1, numElems, 1); +} + +static endReadMemoryResponse(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createReadMemoryResponse(builder:flatbuffers.Builder, address:bigint, dataOffset:flatbuffers.Offset):flatbuffers.Offset { + ReadMemoryResponse.startReadMemoryResponse(builder); + ReadMemoryResponse.addAddress(builder, address); + ReadMemoryResponse.addData(builder, dataOffset); + return ReadMemoryResponse.endReadMemoryResponse(builder); +} + +unpack(): ReadMemoryResponseT { + return new ReadMemoryResponseT( + this.address(), + this.bb!.createScalarList(this.data.bind(this), this.dataLength()) + ); +} + + +unpackTo(_o: ReadMemoryResponseT): void { + _o.address = this.address(); + _o.data = this.bb!.createScalarList(this.data.bind(this), this.dataLength()); +} +} + +export class ReadMemoryResponseT implements flatbuffers.IGeneratedObject { +constructor( + public address: bigint = BigInt('0'), + public data: (number)[] = [] +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + const data = ReadMemoryResponse.createDataVector(builder, this.data); + + return ReadMemoryResponse.createReadMemoryResponse(builder, + this.address, + data + ); +} +} diff --git a/page/src/fb/debugger/write-memory-request.ts b/page/src/fb/debugger/write-memory-request.ts new file mode 100644 index 00000000..3d669553 --- /dev/null +++ b/page/src/fb/debugger/write-memory-request.ts @@ -0,0 +1,123 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class WriteMemoryRequest implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):WriteMemoryRequest { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsWriteMemoryRequest(bb:flatbuffers.ByteBuffer, obj?:WriteMemoryRequest):WriteMemoryRequest { + return (obj || new WriteMemoryRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsWriteMemoryRequest(bb:flatbuffers.ByteBuffer, obj?:WriteMemoryRequest):WriteMemoryRequest { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new WriteMemoryRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +address():bigint { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint64(this.bb_pos + offset) : BigInt('0'); +} + +mutate_address(value:bigint):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint64(this.bb_pos + offset, value); + return true; +} + +data(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint8(this.bb!.__vector(this.bb_pos + offset) + index) : 0; +} + +dataLength():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +dataArray():Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? new Uint8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +static startWriteMemoryRequest(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addAddress(builder:flatbuffers.Builder, address:bigint) { + builder.addFieldInt64(0, address, BigInt('0')); +} + +static addData(builder:flatbuffers.Builder, dataOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, dataOffset, 0); +} + +static createDataVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset { + builder.startVector(1, data.length, 1); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt8(data[i]!); + } + return builder.endVector(); +} + +static startDataVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(1, numElems, 1); +} + +static endWriteMemoryRequest(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createWriteMemoryRequest(builder:flatbuffers.Builder, address:bigint, dataOffset:flatbuffers.Offset):flatbuffers.Offset { + WriteMemoryRequest.startWriteMemoryRequest(builder); + WriteMemoryRequest.addAddress(builder, address); + WriteMemoryRequest.addData(builder, dataOffset); + return WriteMemoryRequest.endWriteMemoryRequest(builder); +} + +unpack(): WriteMemoryRequestT { + return new WriteMemoryRequestT( + this.address(), + this.bb!.createScalarList(this.data.bind(this), this.dataLength()) + ); +} + + +unpackTo(_o: WriteMemoryRequestT): void { + _o.address = this.address(); + _o.data = this.bb!.createScalarList(this.data.bind(this), this.dataLength()); +} +} + +export class WriteMemoryRequestT implements flatbuffers.IGeneratedObject { +constructor( + public address: bigint = BigInt('0'), + public data: (number)[] = [] +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + const data = WriteMemoryRequest.createDataVector(builder, this.data); + + return WriteMemoryRequest.createWriteMemoryRequest(builder, + this.address, + data + ); +} +} diff --git a/page/src/fb/debugger/write-memory-response.ts b/page/src/fb/debugger/write-memory-response.ts new file mode 100644 index 00000000..700f9444 --- /dev/null +++ b/page/src/fb/debugger/write-memory-response.ts @@ -0,0 +1,135 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class WriteMemoryResponse implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):WriteMemoryResponse { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsWriteMemoryResponse(bb:flatbuffers.ByteBuffer, obj?:WriteMemoryResponse):WriteMemoryResponse { + return (obj || new WriteMemoryResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsWriteMemoryResponse(bb:flatbuffers.ByteBuffer, obj?:WriteMemoryResponse):WriteMemoryResponse { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new WriteMemoryResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +address():bigint { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint64(this.bb_pos + offset) : BigInt('0'); +} + +mutate_address(value:bigint):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint64(this.bb_pos + offset, value); + return true; +} + +size():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +mutate_size(value:number):boolean { + const offset = this.bb!.__offset(this.bb_pos, 6); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint32(this.bb_pos + offset, value); + return true; +} + +success():boolean { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false; +} + +mutate_success(value:boolean):boolean { + const offset = this.bb!.__offset(this.bb_pos, 8); + + if (offset === 0) { + return false; + } + + this.bb!.writeInt8(this.bb_pos + offset, +value); + return true; +} + +static startWriteMemoryResponse(builder:flatbuffers.Builder) { + builder.startObject(3); +} + +static addAddress(builder:flatbuffers.Builder, address:bigint) { + builder.addFieldInt64(0, address, BigInt('0')); +} + +static addSize(builder:flatbuffers.Builder, size:number) { + builder.addFieldInt32(1, size, 0); +} + +static addSuccess(builder:flatbuffers.Builder, success:boolean) { + builder.addFieldInt8(2, +success, +false); +} + +static endWriteMemoryResponse(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createWriteMemoryResponse(builder:flatbuffers.Builder, address:bigint, size:number, success:boolean):flatbuffers.Offset { + WriteMemoryResponse.startWriteMemoryResponse(builder); + WriteMemoryResponse.addAddress(builder, address); + WriteMemoryResponse.addSize(builder, size); + WriteMemoryResponse.addSuccess(builder, success); + return WriteMemoryResponse.endWriteMemoryResponse(builder); +} + +unpack(): WriteMemoryResponseT { + return new WriteMemoryResponseT( + this.address(), + this.size(), + this.success() + ); +} + + +unpackTo(_o: WriteMemoryResponseT): void { + _o.address = this.address(); + _o.size = this.size(); + _o.success = this.success(); +} +} + +export class WriteMemoryResponseT implements flatbuffers.IGeneratedObject { +constructor( + public address: bigint = BigInt('0'), + public size: number = 0, + public success: boolean = false +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return WriteMemoryResponse.createWriteMemoryResponse(builder, + this.address, + this.size, + this.success + ); +} +} diff --git a/src/debugger/event_handler.cpp b/src/debugger/event_handler.cpp index b6d65591..8569078d 100644 --- a/src/debugger/event_handler.cpp +++ b/src/debugger/event_handler.cpp @@ -76,12 +76,51 @@ namespace debugger } } - void handle_get_state_request(const event_context& c) + void handle_get_state(const event_context& c) { - Debugger::GetStateResponseT stateResponse{}; - stateResponse.state = translate_state(c.state); + Debugger::GetStateResponseT response{}; + response.state = translate_state(c.state); - send_event(stateResponse); + send_event(response); + } + + void handle_read_memory(const event_context& c, const Debugger::ReadMemoryRequestT& request) + { + std::vector buffer{}; + buffer.resize(request.size); + const auto res = c.win_emu.memory.try_read_memory(request.address, buffer.data(), buffer.size()); + + Debugger::ReadMemoryResponseT response{}; + response.address = request.address; + + if (res) + { + response.data = std::move(buffer); + } + + send_event(std::move(response)); + } + + void handle_write_memory(const event_context& c, const Debugger::WriteMemoryRequestT& request) + { + bool success{}; + + try + { + c.win_emu.memory.write_memory(request.address, request.data.data(), request.data.size()); + success = true; + } + catch (...) + { + success = false; + } + + Debugger::WriteMemoryResponseT response{}; + response.address = request.address; + response.size = static_cast(request.data.size()); + response.success = success; + + send_event(response); } void handle_event(event_context& c, const Debugger::DebugEventT& e) @@ -97,7 +136,15 @@ namespace debugger break; case Debugger::Event_GetStateRequest: - handle_get_state_request(c); + handle_get_state(c); + break; + + case Debugger::Event_ReadMemoryRequest: + handle_read_memory(c, *e.event.AsReadMemoryRequest()); + break; + + case Debugger::Event_WriteMemoryRequest: + handle_write_memory(c, *e.event.AsWriteMemoryRequest()); break; default: diff --git a/src/debugger/events.fbs b/src/debugger/events.fbs index 76c502ed..d676b441 100644 --- a/src/debugger/events.fbs +++ b/src/debugger/events.fbs @@ -18,11 +18,36 @@ table RunRequest { single_step: bool; } +table WriteMemoryRequest { + address: uint64; + data: [ubyte]; +} + +table WriteMemoryResponse { + address: uint64; + size: uint32; + success: bool; +} + +table ReadMemoryRequest { + address: uint64; + size: uint32; +} + +table ReadMemoryResponse { + address: uint64; + data: [ubyte]; +} + union Event { PauseRequest, RunRequest, GetStateRequest, GetStateResponse, + WriteMemoryRequest, + WriteMemoryResponse, + ReadMemoryRequest, + ReadMemoryResponse, } table DebugEvent { diff --git a/src/debugger/events_generated.hxx b/src/debugger/events_generated.hxx index 82cc1b9f..c2f80331 100644 --- a/src/debugger/events_generated.hxx +++ b/src/debugger/events_generated.hxx @@ -31,6 +31,22 @@ struct RunRequest; struct RunRequestBuilder; struct RunRequestT; +struct WriteMemoryRequest; +struct WriteMemoryRequestBuilder; +struct WriteMemoryRequestT; + +struct WriteMemoryResponse; +struct WriteMemoryResponseBuilder; +struct WriteMemoryResponseT; + +struct ReadMemoryRequest; +struct ReadMemoryRequestBuilder; +struct ReadMemoryRequestT; + +struct ReadMemoryResponse; +struct ReadMemoryResponseBuilder; +struct ReadMemoryResponseT; + struct DebugEvent; struct DebugEventBuilder; struct DebugEventT; @@ -74,35 +90,47 @@ enum Event : uint8_t { Event_RunRequest = 2, Event_GetStateRequest = 3, Event_GetStateResponse = 4, + Event_WriteMemoryRequest = 5, + Event_WriteMemoryResponse = 6, + Event_ReadMemoryRequest = 7, + Event_ReadMemoryResponse = 8, Event_MIN = Event_NONE, - Event_MAX = Event_GetStateResponse + Event_MAX = Event_ReadMemoryResponse }; -inline const Event (&EnumValuesEvent())[5] { +inline const Event (&EnumValuesEvent())[9] { static const Event values[] = { Event_NONE, Event_PauseRequest, Event_RunRequest, Event_GetStateRequest, - Event_GetStateResponse + Event_GetStateResponse, + Event_WriteMemoryRequest, + Event_WriteMemoryResponse, + Event_ReadMemoryRequest, + Event_ReadMemoryResponse }; return values; } inline const char * const *EnumNamesEvent() { - static const char * const names[6] = { + static const char * const names[10] = { "NONE", "PauseRequest", "RunRequest", "GetStateRequest", "GetStateResponse", + "WriteMemoryRequest", + "WriteMemoryResponse", + "ReadMemoryRequest", + "ReadMemoryResponse", nullptr }; return names; } inline const char *EnumNameEvent(Event e) { - if (::flatbuffers::IsOutRange(e, Event_NONE, Event_GetStateResponse)) return ""; + if (::flatbuffers::IsOutRange(e, Event_NONE, Event_ReadMemoryResponse)) return ""; const size_t index = static_cast(e); return EnumNamesEvent()[index]; } @@ -127,6 +155,22 @@ template<> struct EventTraits { static const Event enum_value = Event_GetStateResponse; }; +template<> struct EventTraits { + static const Event enum_value = Event_WriteMemoryRequest; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_WriteMemoryResponse; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_ReadMemoryRequest; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_ReadMemoryResponse; +}; + template struct EventUnionTraits { static const Event enum_value = Event_NONE; }; @@ -147,6 +191,22 @@ template<> struct EventUnionTraits { static const Event enum_value = Event_GetStateResponse; }; +template<> struct EventUnionTraits { + static const Event enum_value = Event_WriteMemoryRequest; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_WriteMemoryResponse; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_ReadMemoryRequest; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_ReadMemoryResponse; +}; + struct EventUnion { Event type; void *value; @@ -209,6 +269,38 @@ struct EventUnion { return type == Event_GetStateResponse ? reinterpret_cast(value) : nullptr; } + Debugger::WriteMemoryRequestT *AsWriteMemoryRequest() { + return type == Event_WriteMemoryRequest ? + reinterpret_cast(value) : nullptr; + } + const Debugger::WriteMemoryRequestT *AsWriteMemoryRequest() const { + return type == Event_WriteMemoryRequest ? + reinterpret_cast(value) : nullptr; + } + Debugger::WriteMemoryResponseT *AsWriteMemoryResponse() { + return type == Event_WriteMemoryResponse ? + reinterpret_cast(value) : nullptr; + } + const Debugger::WriteMemoryResponseT *AsWriteMemoryResponse() const { + return type == Event_WriteMemoryResponse ? + reinterpret_cast(value) : nullptr; + } + Debugger::ReadMemoryRequestT *AsReadMemoryRequest() { + return type == Event_ReadMemoryRequest ? + reinterpret_cast(value) : nullptr; + } + const Debugger::ReadMemoryRequestT *AsReadMemoryRequest() const { + return type == Event_ReadMemoryRequest ? + reinterpret_cast(value) : nullptr; + } + Debugger::ReadMemoryResponseT *AsReadMemoryResponse() { + return type == Event_ReadMemoryResponse ? + reinterpret_cast(value) : nullptr; + } + const Debugger::ReadMemoryResponseT *AsReadMemoryResponse() const { + return type == Event_ReadMemoryResponse ? + reinterpret_cast(value) : nullptr; + } }; bool VerifyEvent(::flatbuffers::Verifier &verifier, const void *obj, Event type); @@ -402,6 +494,320 @@ inline ::flatbuffers::Offset CreateRunRequest( ::flatbuffers::Offset CreateRunRequest(::flatbuffers::FlatBufferBuilder &_fbb, const RunRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct WriteMemoryRequestT : public ::flatbuffers::NativeTable { + typedef WriteMemoryRequest TableType; + uint64_t address = 0; + std::vector data{}; +}; + +struct WriteMemoryRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef WriteMemoryRequestT NativeTableType; + typedef WriteMemoryRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ADDRESS = 4, + VT_DATA = 6 + }; + uint64_t address() const { + return GetField(VT_ADDRESS, 0); + } + bool mutate_address(uint64_t _address = 0) { + return SetField(VT_ADDRESS, _address, 0); + } + const ::flatbuffers::Vector *data() const { + return GetPointer *>(VT_DATA); + } + ::flatbuffers::Vector *mutable_data() { + return GetPointer<::flatbuffers::Vector *>(VT_DATA); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ADDRESS, 8) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && + verifier.EndTable(); + } + WriteMemoryRequestT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(WriteMemoryRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WriteMemoryRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct WriteMemoryRequestBuilder { + typedef WriteMemoryRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_address(uint64_t address) { + fbb_.AddElement(WriteMemoryRequest::VT_ADDRESS, address, 0); + } + void add_data(::flatbuffers::Offset<::flatbuffers::Vector> data) { + fbb_.AddOffset(WriteMemoryRequest::VT_DATA, data); + } + explicit WriteMemoryRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateWriteMemoryRequest( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint64_t address = 0, + ::flatbuffers::Offset<::flatbuffers::Vector> data = 0) { + WriteMemoryRequestBuilder builder_(_fbb); + builder_.add_address(address); + builder_.add_data(data); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateWriteMemoryRequestDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint64_t address = 0, + const std::vector *data = nullptr) { + auto data__ = data ? _fbb.CreateVector(*data) : 0; + return Debugger::CreateWriteMemoryRequest( + _fbb, + address, + data__); +} + +::flatbuffers::Offset CreateWriteMemoryRequest(::flatbuffers::FlatBufferBuilder &_fbb, const WriteMemoryRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct WriteMemoryResponseT : public ::flatbuffers::NativeTable { + typedef WriteMemoryResponse TableType; + uint64_t address = 0; + uint32_t size = 0; + bool success = false; +}; + +struct WriteMemoryResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef WriteMemoryResponseT NativeTableType; + typedef WriteMemoryResponseBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ADDRESS = 4, + VT_SIZE = 6, + VT_SUCCESS = 8 + }; + uint64_t address() const { + return GetField(VT_ADDRESS, 0); + } + bool mutate_address(uint64_t _address = 0) { + return SetField(VT_ADDRESS, _address, 0); + } + uint32_t size() const { + return GetField(VT_SIZE, 0); + } + bool mutate_size(uint32_t _size = 0) { + return SetField(VT_SIZE, _size, 0); + } + bool success() const { + return GetField(VT_SUCCESS, 0) != 0; + } + bool mutate_success(bool _success = 0) { + return SetField(VT_SUCCESS, static_cast(_success), 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ADDRESS, 8) && + VerifyField(verifier, VT_SIZE, 4) && + VerifyField(verifier, VT_SUCCESS, 1) && + verifier.EndTable(); + } + WriteMemoryResponseT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(WriteMemoryResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WriteMemoryResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct WriteMemoryResponseBuilder { + typedef WriteMemoryResponse Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_address(uint64_t address) { + fbb_.AddElement(WriteMemoryResponse::VT_ADDRESS, address, 0); + } + void add_size(uint32_t size) { + fbb_.AddElement(WriteMemoryResponse::VT_SIZE, size, 0); + } + void add_success(bool success) { + fbb_.AddElement(WriteMemoryResponse::VT_SUCCESS, static_cast(success), 0); + } + explicit WriteMemoryResponseBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateWriteMemoryResponse( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint64_t address = 0, + uint32_t size = 0, + bool success = false) { + WriteMemoryResponseBuilder builder_(_fbb); + builder_.add_address(address); + builder_.add_size(size); + builder_.add_success(success); + return builder_.Finish(); +} + +::flatbuffers::Offset CreateWriteMemoryResponse(::flatbuffers::FlatBufferBuilder &_fbb, const WriteMemoryResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReadMemoryRequestT : public ::flatbuffers::NativeTable { + typedef ReadMemoryRequest TableType; + uint64_t address = 0; + uint32_t size = 0; +}; + +struct ReadMemoryRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef ReadMemoryRequestT NativeTableType; + typedef ReadMemoryRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ADDRESS = 4, + VT_SIZE = 6 + }; + uint64_t address() const { + return GetField(VT_ADDRESS, 0); + } + bool mutate_address(uint64_t _address = 0) { + return SetField(VT_ADDRESS, _address, 0); + } + uint32_t size() const { + return GetField(VT_SIZE, 0); + } + bool mutate_size(uint32_t _size = 0) { + return SetField(VT_SIZE, _size, 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ADDRESS, 8) && + VerifyField(verifier, VT_SIZE, 4) && + verifier.EndTable(); + } + ReadMemoryRequestT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReadMemoryRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReadMemoryRequestBuilder { + typedef ReadMemoryRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_address(uint64_t address) { + fbb_.AddElement(ReadMemoryRequest::VT_ADDRESS, address, 0); + } + void add_size(uint32_t size) { + fbb_.AddElement(ReadMemoryRequest::VT_SIZE, size, 0); + } + explicit ReadMemoryRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateReadMemoryRequest( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint64_t address = 0, + uint32_t size = 0) { + ReadMemoryRequestBuilder builder_(_fbb); + builder_.add_address(address); + builder_.add_size(size); + return builder_.Finish(); +} + +::flatbuffers::Offset CreateReadMemoryRequest(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReadMemoryResponseT : public ::flatbuffers::NativeTable { + typedef ReadMemoryResponse TableType; + uint64_t address = 0; + std::vector data{}; +}; + +struct ReadMemoryResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef ReadMemoryResponseT NativeTableType; + typedef ReadMemoryResponseBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_ADDRESS = 4, + VT_DATA = 6 + }; + uint64_t address() const { + return GetField(VT_ADDRESS, 0); + } + bool mutate_address(uint64_t _address = 0) { + return SetField(VT_ADDRESS, _address, 0); + } + const ::flatbuffers::Vector *data() const { + return GetPointer *>(VT_DATA); + } + ::flatbuffers::Vector *mutable_data() { + return GetPointer<::flatbuffers::Vector *>(VT_DATA); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ADDRESS, 8) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && + verifier.EndTable(); + } + ReadMemoryResponseT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReadMemoryResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReadMemoryResponseBuilder { + typedef ReadMemoryResponse Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_address(uint64_t address) { + fbb_.AddElement(ReadMemoryResponse::VT_ADDRESS, address, 0); + } + void add_data(::flatbuffers::Offset<::flatbuffers::Vector> data) { + fbb_.AddOffset(ReadMemoryResponse::VT_DATA, data); + } + explicit ReadMemoryResponseBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateReadMemoryResponse( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint64_t address = 0, + ::flatbuffers::Offset<::flatbuffers::Vector> data = 0) { + ReadMemoryResponseBuilder builder_(_fbb); + builder_.add_address(address); + builder_.add_data(data); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateReadMemoryResponseDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint64_t address = 0, + const std::vector *data = nullptr) { + auto data__ = data ? _fbb.CreateVector(*data) : 0; + return Debugger::CreateReadMemoryResponse( + _fbb, + address, + data__); +} + +::flatbuffers::Offset CreateReadMemoryResponse(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct DebugEventT : public ::flatbuffers::NativeTable { typedef DebugEvent TableType; Debugger::EventUnion event{}; @@ -433,6 +839,18 @@ struct DebugEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { const Debugger::GetStateResponse *event_as_GetStateResponse() const { return event_type() == Debugger::Event_GetStateResponse ? static_cast(event()) : nullptr; } + const Debugger::WriteMemoryRequest *event_as_WriteMemoryRequest() const { + return event_type() == Debugger::Event_WriteMemoryRequest ? static_cast(event()) : nullptr; + } + const Debugger::WriteMemoryResponse *event_as_WriteMemoryResponse() const { + return event_type() == Debugger::Event_WriteMemoryResponse ? static_cast(event()) : nullptr; + } + const Debugger::ReadMemoryRequest *event_as_ReadMemoryRequest() const { + return event_type() == Debugger::Event_ReadMemoryRequest ? static_cast(event()) : nullptr; + } + const Debugger::ReadMemoryResponse *event_as_ReadMemoryResponse() const { + return event_type() == Debugger::Event_ReadMemoryResponse ? static_cast(event()) : nullptr; + } void *mutable_event() { return GetPointer(VT_EVENT); } @@ -464,6 +882,22 @@ template<> inline const Debugger::GetStateResponse *DebugEvent::event_as inline const Debugger::WriteMemoryRequest *DebugEvent::event_as() const { + return event_as_WriteMemoryRequest(); +} + +template<> inline const Debugger::WriteMemoryResponse *DebugEvent::event_as() const { + return event_as_WriteMemoryResponse(); +} + +template<> inline const Debugger::ReadMemoryRequest *DebugEvent::event_as() const { + return event_as_ReadMemoryRequest(); +} + +template<> inline const Debugger::ReadMemoryResponse *DebugEvent::event_as() const { + return event_as_ReadMemoryResponse(); +} + struct DebugEventBuilder { typedef DebugEvent Table; ::flatbuffers::FlatBufferBuilder &fbb_; @@ -595,6 +1029,125 @@ inline ::flatbuffers::Offset CreateRunRequest(::flatbuffers::FlatBuf _single_step); } +inline WriteMemoryRequestT *WriteMemoryRequest::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new WriteMemoryRequestT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void WriteMemoryRequest::UnPackTo(WriteMemoryRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = address(); _o->address = _e; } + { auto _e = data(); if (_e) { _o->data.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->data.begin()); } } +} + +inline ::flatbuffers::Offset WriteMemoryRequest::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WriteMemoryRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateWriteMemoryRequest(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateWriteMemoryRequest(::flatbuffers::FlatBufferBuilder &_fbb, const WriteMemoryRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const WriteMemoryRequestT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _address = _o->address; + auto _data = _o->data.size() ? _fbb.CreateVector(_o->data) : 0; + return Debugger::CreateWriteMemoryRequest( + _fbb, + _address, + _data); +} + +inline WriteMemoryResponseT *WriteMemoryResponse::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new WriteMemoryResponseT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void WriteMemoryResponse::UnPackTo(WriteMemoryResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = address(); _o->address = _e; } + { auto _e = size(); _o->size = _e; } + { auto _e = success(); _o->success = _e; } +} + +inline ::flatbuffers::Offset WriteMemoryResponse::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WriteMemoryResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateWriteMemoryResponse(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateWriteMemoryResponse(::flatbuffers::FlatBufferBuilder &_fbb, const WriteMemoryResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const WriteMemoryResponseT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _address = _o->address; + auto _size = _o->size; + auto _success = _o->success; + return Debugger::CreateWriteMemoryResponse( + _fbb, + _address, + _size, + _success); +} + +inline ReadMemoryRequestT *ReadMemoryRequest::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReadMemoryRequestT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReadMemoryRequest::UnPackTo(ReadMemoryRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = address(); _o->address = _e; } + { auto _e = size(); _o->size = _e; } +} + +inline ::flatbuffers::Offset ReadMemoryRequest::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateReadMemoryRequest(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateReadMemoryRequest(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const ReadMemoryRequestT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _address = _o->address; + auto _size = _o->size; + return Debugger::CreateReadMemoryRequest( + _fbb, + _address, + _size); +} + +inline ReadMemoryResponseT *ReadMemoryResponse::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReadMemoryResponseT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReadMemoryResponse::UnPackTo(ReadMemoryResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = address(); _o->address = _e; } + { auto _e = data(); if (_e) { _o->data.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->data.begin()); } } +} + +inline ::flatbuffers::Offset ReadMemoryResponse::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateReadMemoryResponse(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateReadMemoryResponse(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const ReadMemoryResponseT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _address = _o->address; + auto _data = _o->data.size() ? _fbb.CreateVector(_o->data) : 0; + return Debugger::CreateReadMemoryResponse( + _fbb, + _address, + _data); +} + inline DebugEventT *DebugEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { auto _o = std::unique_ptr(new DebugEventT()); UnPackTo(_o.get(), _resolver); @@ -645,6 +1198,22 @@ inline bool VerifyEvent(::flatbuffers::Verifier &verifier, const void *obj, Even auto ptr = reinterpret_cast(obj); return verifier.VerifyTable(ptr); } + case Event_WriteMemoryRequest: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_WriteMemoryResponse: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_ReadMemoryRequest: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_ReadMemoryResponse: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } default: return true; } } @@ -680,6 +1249,22 @@ inline void *EventUnion::UnPack(const void *obj, Event type, const ::flatbuffers auto ptr = reinterpret_cast(obj); return ptr->UnPack(resolver); } + case Event_WriteMemoryRequest: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_WriteMemoryResponse: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_ReadMemoryRequest: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_ReadMemoryResponse: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } default: return nullptr; } } @@ -703,6 +1288,22 @@ inline ::flatbuffers::Offset EventUnion::Pack(::flatbuffers::FlatBufferBui auto ptr = reinterpret_cast(value); return CreateGetStateResponse(_fbb, ptr, _rehasher).Union(); } + case Event_WriteMemoryRequest: { + auto ptr = reinterpret_cast(value); + return CreateWriteMemoryRequest(_fbb, ptr, _rehasher).Union(); + } + case Event_WriteMemoryResponse: { + auto ptr = reinterpret_cast(value); + return CreateWriteMemoryResponse(_fbb, ptr, _rehasher).Union(); + } + case Event_ReadMemoryRequest: { + auto ptr = reinterpret_cast(value); + return CreateReadMemoryRequest(_fbb, ptr, _rehasher).Union(); + } + case Event_ReadMemoryResponse: { + auto ptr = reinterpret_cast(value); + return CreateReadMemoryResponse(_fbb, ptr, _rehasher).Union(); + } default: return 0; } } @@ -725,6 +1326,22 @@ inline EventUnion::EventUnion(const EventUnion &u) : type(u.type), value(nullptr value = new Debugger::GetStateResponseT(*reinterpret_cast(u.value)); break; } + case Event_WriteMemoryRequest: { + value = new Debugger::WriteMemoryRequestT(*reinterpret_cast(u.value)); + break; + } + case Event_WriteMemoryResponse: { + value = new Debugger::WriteMemoryResponseT(*reinterpret_cast(u.value)); + break; + } + case Event_ReadMemoryRequest: { + value = new Debugger::ReadMemoryRequestT(*reinterpret_cast(u.value)); + break; + } + case Event_ReadMemoryResponse: { + value = new Debugger::ReadMemoryResponseT(*reinterpret_cast(u.value)); + break; + } default: break; } @@ -752,6 +1369,26 @@ inline void EventUnion::Reset() { delete ptr; break; } + case Event_WriteMemoryRequest: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_WriteMemoryResponse: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_ReadMemoryRequest: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_ReadMemoryResponse: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } default: break; } value = nullptr; From 0828bec9adfde9196d1f3322f98456c02677501b Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 28 Apr 2025 14:18:23 +0200 Subject: [PATCH 12/17] Support reading registers --- page/src/fb/debugger.ts | 4 + page/src/fb/debugger/debug-event.ts | 6 +- page/src/fb/debugger/event.ts | 26 +- page/src/fb/debugger/read-register-request.ts | 85 +++ .../src/fb/debugger/read-register-response.ts | 123 ++++ .../src/fb/debugger/write-register-request.ts | 123 ++++ .../fb/debugger/write-register-response.ts | 135 ++++ src/debugger/event_handler.cpp | 47 ++ src/debugger/events.fbs | 24 + src/debugger/events_generated.hxx | 630 +++++++++++++++++- 10 files changed, 1192 insertions(+), 11 deletions(-) create mode 100644 page/src/fb/debugger/read-register-request.ts create mode 100644 page/src/fb/debugger/read-register-response.ts create mode 100644 page/src/fb/debugger/write-register-request.ts create mode 100644 page/src/fb/debugger/write-register-response.ts diff --git a/page/src/fb/debugger.ts b/page/src/fb/debugger.ts index babc30f3..c5f2befb 100644 --- a/page/src/fb/debugger.ts +++ b/page/src/fb/debugger.ts @@ -9,7 +9,11 @@ export { GetStateResponse, GetStateResponseT } from './debugger/get-state-respon export { PauseRequest, PauseRequestT } from './debugger/pause-request.js'; export { ReadMemoryRequest, ReadMemoryRequestT } from './debugger/read-memory-request.js'; export { ReadMemoryResponse, ReadMemoryResponseT } from './debugger/read-memory-response.js'; +export { ReadRegisterRequest, ReadRegisterRequestT } from './debugger/read-register-request.js'; +export { ReadRegisterResponse, ReadRegisterResponseT } from './debugger/read-register-response.js'; export { RunRequest, RunRequestT } from './debugger/run-request.js'; export { State } from './debugger/state.js'; export { WriteMemoryRequest, WriteMemoryRequestT } from './debugger/write-memory-request.js'; export { WriteMemoryResponse, WriteMemoryResponseT } from './debugger/write-memory-response.js'; +export { WriteRegisterRequest, WriteRegisterRequestT } from './debugger/write-register-request.js'; +export { WriteRegisterResponse, WriteRegisterResponseT } from './debugger/write-register-response.js'; diff --git a/page/src/fb/debugger/debug-event.ts b/page/src/fb/debugger/debug-event.ts index afb57ec2..9be99bfa 100644 --- a/page/src/fb/debugger/debug-event.ts +++ b/page/src/fb/debugger/debug-event.ts @@ -10,9 +10,13 @@ import { GetStateResponse, GetStateResponseT } from '../debugger/get-state-respo import { PauseRequest, PauseRequestT } from '../debugger/pause-request.js'; import { ReadMemoryRequest, ReadMemoryRequestT } from '../debugger/read-memory-request.js'; import { ReadMemoryResponse, ReadMemoryResponseT } from '../debugger/read-memory-response.js'; +import { ReadRegisterRequest, ReadRegisterRequestT } from '../debugger/read-register-request.js'; +import { ReadRegisterResponse, ReadRegisterResponseT } from '../debugger/read-register-response.js'; import { RunRequest, RunRequestT } from '../debugger/run-request.js'; import { WriteMemoryRequest, WriteMemoryRequestT } from '../debugger/write-memory-request.js'; import { WriteMemoryResponse, WriteMemoryResponseT } from '../debugger/write-memory-response.js'; +import { WriteRegisterRequest, WriteRegisterRequestT } from '../debugger/write-register-request.js'; +import { WriteRegisterResponse, WriteRegisterResponseT } from '../debugger/write-register-response.js'; export class DebugEvent implements flatbuffers.IUnpackableObject { @@ -100,7 +104,7 @@ unpackTo(_o: DebugEventT): void { export class DebugEventT implements flatbuffers.IGeneratedObject { constructor( public eventType: Event = Event.NONE, - public event: GetStateRequestT|GetStateResponseT|PauseRequestT|ReadMemoryRequestT|ReadMemoryResponseT|RunRequestT|WriteMemoryRequestT|WriteMemoryResponseT|null = null + public event: GetStateRequestT|GetStateResponseT|PauseRequestT|ReadMemoryRequestT|ReadMemoryResponseT|ReadRegisterRequestT|ReadRegisterResponseT|RunRequestT|WriteMemoryRequestT|WriteMemoryResponseT|WriteRegisterRequestT|WriteRegisterResponseT|null = null ){} diff --git a/page/src/fb/debugger/event.ts b/page/src/fb/debugger/event.ts index 6b249b2b..fde2a752 100644 --- a/page/src/fb/debugger/event.ts +++ b/page/src/fb/debugger/event.ts @@ -7,9 +7,13 @@ import { GetStateResponse, GetStateResponseT } from '../debugger/get-state-respo import { PauseRequest, PauseRequestT } from '../debugger/pause-request.js'; import { ReadMemoryRequest, ReadMemoryRequestT } from '../debugger/read-memory-request.js'; import { ReadMemoryResponse, ReadMemoryResponseT } from '../debugger/read-memory-response.js'; +import { ReadRegisterRequest, ReadRegisterRequestT } from '../debugger/read-register-request.js'; +import { ReadRegisterResponse, ReadRegisterResponseT } from '../debugger/read-register-response.js'; import { RunRequest, RunRequestT } from '../debugger/run-request.js'; import { WriteMemoryRequest, WriteMemoryRequestT } from '../debugger/write-memory-request.js'; import { WriteMemoryResponse, WriteMemoryResponseT } from '../debugger/write-memory-response.js'; +import { WriteRegisterRequest, WriteRegisterRequestT } from '../debugger/write-register-request.js'; +import { WriteRegisterResponse, WriteRegisterResponseT } from '../debugger/write-register-response.js'; export enum Event { @@ -21,13 +25,17 @@ export enum Event { WriteMemoryRequest = 5, WriteMemoryResponse = 6, ReadMemoryRequest = 7, - ReadMemoryResponse = 8 + ReadMemoryResponse = 8, + WriteRegisterRequest = 9, + WriteRegisterResponse = 10, + ReadRegisterRequest = 11, + ReadRegisterResponse = 12 } export function unionToEvent( type: Event, - accessor: (obj:GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse) => GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|null -): GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|null { + accessor: (obj:GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|ReadRegisterRequest|ReadRegisterResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|WriteRegisterRequest|WriteRegisterResponse) => GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|ReadRegisterRequest|ReadRegisterResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|WriteRegisterRequest|WriteRegisterResponse|null +): GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|ReadRegisterRequest|ReadRegisterResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|WriteRegisterRequest|WriteRegisterResponse|null { switch(Event[type]) { case 'NONE': return null; case 'PauseRequest': return accessor(new PauseRequest())! as PauseRequest; @@ -38,15 +46,19 @@ export function unionToEvent( case 'WriteMemoryResponse': return accessor(new WriteMemoryResponse())! as WriteMemoryResponse; case 'ReadMemoryRequest': return accessor(new ReadMemoryRequest())! as ReadMemoryRequest; case 'ReadMemoryResponse': return accessor(new ReadMemoryResponse())! as ReadMemoryResponse; + case 'WriteRegisterRequest': return accessor(new WriteRegisterRequest())! as WriteRegisterRequest; + case 'WriteRegisterResponse': return accessor(new WriteRegisterResponse())! as WriteRegisterResponse; + case 'ReadRegisterRequest': return accessor(new ReadRegisterRequest())! as ReadRegisterRequest; + case 'ReadRegisterResponse': return accessor(new ReadRegisterResponse())! as ReadRegisterResponse; default: return null; } } export function unionListToEvent( type: Event, - accessor: (index: number, obj:GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse) => GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|null, + accessor: (index: number, obj:GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|ReadRegisterRequest|ReadRegisterResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|WriteRegisterRequest|WriteRegisterResponse) => GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|ReadRegisterRequest|ReadRegisterResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|WriteRegisterRequest|WriteRegisterResponse|null, index: number -): GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|null { +): GetStateRequest|GetStateResponse|PauseRequest|ReadMemoryRequest|ReadMemoryResponse|ReadRegisterRequest|ReadRegisterResponse|RunRequest|WriteMemoryRequest|WriteMemoryResponse|WriteRegisterRequest|WriteRegisterResponse|null { switch(Event[type]) { case 'NONE': return null; case 'PauseRequest': return accessor(index, new PauseRequest())! as PauseRequest; @@ -57,6 +69,10 @@ export function unionListToEvent( case 'WriteMemoryResponse': return accessor(index, new WriteMemoryResponse())! as WriteMemoryResponse; case 'ReadMemoryRequest': return accessor(index, new ReadMemoryRequest())! as ReadMemoryRequest; case 'ReadMemoryResponse': return accessor(index, new ReadMemoryResponse())! as ReadMemoryResponse; + case 'WriteRegisterRequest': return accessor(index, new WriteRegisterRequest())! as WriteRegisterRequest; + case 'WriteRegisterResponse': return accessor(index, new WriteRegisterResponse())! as WriteRegisterResponse; + case 'ReadRegisterRequest': return accessor(index, new ReadRegisterRequest())! as ReadRegisterRequest; + case 'ReadRegisterResponse': return accessor(index, new ReadRegisterResponse())! as ReadRegisterResponse; default: return null; } } diff --git a/page/src/fb/debugger/read-register-request.ts b/page/src/fb/debugger/read-register-request.ts new file mode 100644 index 00000000..71980ad8 --- /dev/null +++ b/page/src/fb/debugger/read-register-request.ts @@ -0,0 +1,85 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class ReadRegisterRequest implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):ReadRegisterRequest { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsReadRegisterRequest(bb:flatbuffers.ByteBuffer, obj?:ReadRegisterRequest):ReadRegisterRequest { + return (obj || new ReadRegisterRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsReadRegisterRequest(bb:flatbuffers.ByteBuffer, obj?:ReadRegisterRequest):ReadRegisterRequest { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new ReadRegisterRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +register():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +mutate_register(value:number):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint32(this.bb_pos + offset, value); + return true; +} + +static startReadRegisterRequest(builder:flatbuffers.Builder) { + builder.startObject(1); +} + +static addRegister(builder:flatbuffers.Builder, register:number) { + builder.addFieldInt32(0, register, 0); +} + +static endReadRegisterRequest(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createReadRegisterRequest(builder:flatbuffers.Builder, register:number):flatbuffers.Offset { + ReadRegisterRequest.startReadRegisterRequest(builder); + ReadRegisterRequest.addRegister(builder, register); + return ReadRegisterRequest.endReadRegisterRequest(builder); +} + +unpack(): ReadRegisterRequestT { + return new ReadRegisterRequestT( + this.register() + ); +} + + +unpackTo(_o: ReadRegisterRequestT): void { + _o.register = this.register(); +} +} + +export class ReadRegisterRequestT implements flatbuffers.IGeneratedObject { +constructor( + public register: number = 0 +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return ReadRegisterRequest.createReadRegisterRequest(builder, + this.register + ); +} +} diff --git a/page/src/fb/debugger/read-register-response.ts b/page/src/fb/debugger/read-register-response.ts new file mode 100644 index 00000000..9d2d6c86 --- /dev/null +++ b/page/src/fb/debugger/read-register-response.ts @@ -0,0 +1,123 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class ReadRegisterResponse implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):ReadRegisterResponse { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsReadRegisterResponse(bb:flatbuffers.ByteBuffer, obj?:ReadRegisterResponse):ReadRegisterResponse { + return (obj || new ReadRegisterResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsReadRegisterResponse(bb:flatbuffers.ByteBuffer, obj?:ReadRegisterResponse):ReadRegisterResponse { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new ReadRegisterResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +register():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +mutate_register(value:number):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint32(this.bb_pos + offset, value); + return true; +} + +data(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint8(this.bb!.__vector(this.bb_pos + offset) + index) : 0; +} + +dataLength():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +dataArray():Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? new Uint8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +static startReadRegisterResponse(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addRegister(builder:flatbuffers.Builder, register:number) { + builder.addFieldInt32(0, register, 0); +} + +static addData(builder:flatbuffers.Builder, dataOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, dataOffset, 0); +} + +static createDataVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset { + builder.startVector(1, data.length, 1); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt8(data[i]!); + } + return builder.endVector(); +} + +static startDataVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(1, numElems, 1); +} + +static endReadRegisterResponse(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createReadRegisterResponse(builder:flatbuffers.Builder, register:number, dataOffset:flatbuffers.Offset):flatbuffers.Offset { + ReadRegisterResponse.startReadRegisterResponse(builder); + ReadRegisterResponse.addRegister(builder, register); + ReadRegisterResponse.addData(builder, dataOffset); + return ReadRegisterResponse.endReadRegisterResponse(builder); +} + +unpack(): ReadRegisterResponseT { + return new ReadRegisterResponseT( + this.register(), + this.bb!.createScalarList(this.data.bind(this), this.dataLength()) + ); +} + + +unpackTo(_o: ReadRegisterResponseT): void { + _o.register = this.register(); + _o.data = this.bb!.createScalarList(this.data.bind(this), this.dataLength()); +} +} + +export class ReadRegisterResponseT implements flatbuffers.IGeneratedObject { +constructor( + public register: number = 0, + public data: (number)[] = [] +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + const data = ReadRegisterResponse.createDataVector(builder, this.data); + + return ReadRegisterResponse.createReadRegisterResponse(builder, + this.register, + data + ); +} +} diff --git a/page/src/fb/debugger/write-register-request.ts b/page/src/fb/debugger/write-register-request.ts new file mode 100644 index 00000000..6e81a3f8 --- /dev/null +++ b/page/src/fb/debugger/write-register-request.ts @@ -0,0 +1,123 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class WriteRegisterRequest implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):WriteRegisterRequest { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsWriteRegisterRequest(bb:flatbuffers.ByteBuffer, obj?:WriteRegisterRequest):WriteRegisterRequest { + return (obj || new WriteRegisterRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsWriteRegisterRequest(bb:flatbuffers.ByteBuffer, obj?:WriteRegisterRequest):WriteRegisterRequest { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new WriteRegisterRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +register():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +mutate_register(value:number):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint32(this.bb_pos + offset, value); + return true; +} + +data(index: number):number|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint8(this.bb!.__vector(this.bb_pos + offset) + index) : 0; +} + +dataLength():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +} + +dataArray():Uint8Array|null { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? new Uint8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +} + +static startWriteRegisterRequest(builder:flatbuffers.Builder) { + builder.startObject(2); +} + +static addRegister(builder:flatbuffers.Builder, register:number) { + builder.addFieldInt32(0, register, 0); +} + +static addData(builder:flatbuffers.Builder, dataOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, dataOffset, 0); +} + +static createDataVector(builder:flatbuffers.Builder, data:number[]|Uint8Array):flatbuffers.Offset { + builder.startVector(1, data.length, 1); + for (let i = data.length - 1; i >= 0; i--) { + builder.addInt8(data[i]!); + } + return builder.endVector(); +} + +static startDataVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(1, numElems, 1); +} + +static endWriteRegisterRequest(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createWriteRegisterRequest(builder:flatbuffers.Builder, register:number, dataOffset:flatbuffers.Offset):flatbuffers.Offset { + WriteRegisterRequest.startWriteRegisterRequest(builder); + WriteRegisterRequest.addRegister(builder, register); + WriteRegisterRequest.addData(builder, dataOffset); + return WriteRegisterRequest.endWriteRegisterRequest(builder); +} + +unpack(): WriteRegisterRequestT { + return new WriteRegisterRequestT( + this.register(), + this.bb!.createScalarList(this.data.bind(this), this.dataLength()) + ); +} + + +unpackTo(_o: WriteRegisterRequestT): void { + _o.register = this.register(); + _o.data = this.bb!.createScalarList(this.data.bind(this), this.dataLength()); +} +} + +export class WriteRegisterRequestT implements flatbuffers.IGeneratedObject { +constructor( + public register: number = 0, + public data: (number)[] = [] +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + const data = WriteRegisterRequest.createDataVector(builder, this.data); + + return WriteRegisterRequest.createWriteRegisterRequest(builder, + this.register, + data + ); +} +} diff --git a/page/src/fb/debugger/write-register-response.ts b/page/src/fb/debugger/write-register-response.ts new file mode 100644 index 00000000..839edc55 --- /dev/null +++ b/page/src/fb/debugger/write-register-response.ts @@ -0,0 +1,135 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */ + +import * as flatbuffers from 'flatbuffers'; + + + +export class WriteRegisterResponse implements flatbuffers.IUnpackableObject { + bb: flatbuffers.ByteBuffer|null = null; + bb_pos = 0; + __init(i:number, bb:flatbuffers.ByteBuffer):WriteRegisterResponse { + this.bb_pos = i; + this.bb = bb; + return this; +} + +static getRootAsWriteRegisterResponse(bb:flatbuffers.ByteBuffer, obj?:WriteRegisterResponse):WriteRegisterResponse { + return (obj || new WriteRegisterResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +static getSizePrefixedRootAsWriteRegisterResponse(bb:flatbuffers.ByteBuffer, obj?:WriteRegisterResponse):WriteRegisterResponse { + bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH); + return (obj || new WriteRegisterResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb); +} + +register():number { + const offset = this.bb!.__offset(this.bb_pos, 4); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +mutate_register(value:number):boolean { + const offset = this.bb!.__offset(this.bb_pos, 4); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint32(this.bb_pos + offset, value); + return true; +} + +size():number { + const offset = this.bb!.__offset(this.bb_pos, 6); + return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0; +} + +mutate_size(value:number):boolean { + const offset = this.bb!.__offset(this.bb_pos, 6); + + if (offset === 0) { + return false; + } + + this.bb!.writeUint32(this.bb_pos + offset, value); + return true; +} + +success():boolean { + const offset = this.bb!.__offset(this.bb_pos, 8); + return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false; +} + +mutate_success(value:boolean):boolean { + const offset = this.bb!.__offset(this.bb_pos, 8); + + if (offset === 0) { + return false; + } + + this.bb!.writeInt8(this.bb_pos + offset, +value); + return true; +} + +static startWriteRegisterResponse(builder:flatbuffers.Builder) { + builder.startObject(3); +} + +static addRegister(builder:flatbuffers.Builder, register:number) { + builder.addFieldInt32(0, register, 0); +} + +static addSize(builder:flatbuffers.Builder, size:number) { + builder.addFieldInt32(1, size, 0); +} + +static addSuccess(builder:flatbuffers.Builder, success:boolean) { + builder.addFieldInt8(2, +success, +false); +} + +static endWriteRegisterResponse(builder:flatbuffers.Builder):flatbuffers.Offset { + const offset = builder.endObject(); + return offset; +} + +static createWriteRegisterResponse(builder:flatbuffers.Builder, register:number, size:number, success:boolean):flatbuffers.Offset { + WriteRegisterResponse.startWriteRegisterResponse(builder); + WriteRegisterResponse.addRegister(builder, register); + WriteRegisterResponse.addSize(builder, size); + WriteRegisterResponse.addSuccess(builder, success); + return WriteRegisterResponse.endWriteRegisterResponse(builder); +} + +unpack(): WriteRegisterResponseT { + return new WriteRegisterResponseT( + this.register(), + this.size(), + this.success() + ); +} + + +unpackTo(_o: WriteRegisterResponseT): void { + _o.register = this.register(); + _o.size = this.size(); + _o.success = this.success(); +} +} + +export class WriteRegisterResponseT implements flatbuffers.IGeneratedObject { +constructor( + public register: number = 0, + public size: number = 0, + public success: boolean = false +){} + + +pack(builder:flatbuffers.Builder): flatbuffers.Offset { + return WriteRegisterResponse.createWriteRegisterResponse(builder, + this.register, + this.size, + this.success + ); +} +} diff --git a/src/debugger/event_handler.cpp b/src/debugger/event_handler.cpp index 8569078d..d607d239 100644 --- a/src/debugger/event_handler.cpp +++ b/src/debugger/event_handler.cpp @@ -123,6 +123,45 @@ namespace debugger send_event(response); } + void handle_read_register(const event_context& c, const Debugger::ReadRegisterRequestT& request) + { + uint8_t buffer[512]{}; + const auto res = + c.win_emu.emu().read_register(static_cast(request.register_), buffer, sizeof(buffer)); + + const auto size = std::min(sizeof(buffer), res); + + Debugger::ReadRegisterResponseT response{}; + response.register_ = request.register_; + response.data.assign(buffer, buffer + size); + + send_event(std::move(response)); + } + + void handle_write_register(const event_context& c, const Debugger::WriteRegisterRequestT& request) + { + bool success{}; + size_t size = request.data.size(); + + try + { + size = c.win_emu.emu().write_register(static_cast(request.register_), request.data.data(), + request.data.size()); + success = true; + } + catch (...) + { + success = false; + } + + Debugger::WriteRegisterResponseT response{}; + response.register_ = request.register_; + response.size = static_cast(size); + response.success = success; + + send_event(response); + } + void handle_event(event_context& c, const Debugger::DebugEventT& e) { switch (e.event.type) @@ -147,6 +186,14 @@ namespace debugger handle_write_memory(c, *e.event.AsWriteMemoryRequest()); break; + case Debugger::Event_ReadRegisterRequest: + handle_read_register(c, *e.event.AsReadRegisterRequest()); + break; + + case Debugger::Event_WriteRegisterRequest: + handle_write_register(c, *e.event.AsWriteRegisterRequest()); + break; + default: break; } diff --git a/src/debugger/events.fbs b/src/debugger/events.fbs index d676b441..4c17f9a4 100644 --- a/src/debugger/events.fbs +++ b/src/debugger/events.fbs @@ -39,6 +39,26 @@ table ReadMemoryResponse { data: [ubyte]; } +table WriteRegisterRequest { + register: uint32; + data: [ubyte]; +} + +table WriteRegisterResponse { + register: uint32; + size: uint32; + success: bool; +} + +table ReadRegisterRequest { + register: uint32; +} + +table ReadRegisterResponse { + register: uint32; + data: [ubyte]; +} + union Event { PauseRequest, RunRequest, @@ -48,6 +68,10 @@ union Event { WriteMemoryResponse, ReadMemoryRequest, ReadMemoryResponse, + WriteRegisterRequest, + WriteRegisterResponse, + ReadRegisterRequest, + ReadRegisterResponse, } table DebugEvent { diff --git a/src/debugger/events_generated.hxx b/src/debugger/events_generated.hxx index c2f80331..5c56b8c5 100644 --- a/src/debugger/events_generated.hxx +++ b/src/debugger/events_generated.hxx @@ -47,6 +47,22 @@ struct ReadMemoryResponse; struct ReadMemoryResponseBuilder; struct ReadMemoryResponseT; +struct WriteRegisterRequest; +struct WriteRegisterRequestBuilder; +struct WriteRegisterRequestT; + +struct WriteRegisterResponse; +struct WriteRegisterResponseBuilder; +struct WriteRegisterResponseT; + +struct ReadRegisterRequest; +struct ReadRegisterRequestBuilder; +struct ReadRegisterRequestT; + +struct ReadRegisterResponse; +struct ReadRegisterResponseBuilder; +struct ReadRegisterResponseT; + struct DebugEvent; struct DebugEventBuilder; struct DebugEventT; @@ -94,11 +110,15 @@ enum Event : uint8_t { Event_WriteMemoryResponse = 6, Event_ReadMemoryRequest = 7, Event_ReadMemoryResponse = 8, + Event_WriteRegisterRequest = 9, + Event_WriteRegisterResponse = 10, + Event_ReadRegisterRequest = 11, + Event_ReadRegisterResponse = 12, Event_MIN = Event_NONE, - Event_MAX = Event_ReadMemoryResponse + Event_MAX = Event_ReadRegisterResponse }; -inline const Event (&EnumValuesEvent())[9] { +inline const Event (&EnumValuesEvent())[13] { static const Event values[] = { Event_NONE, Event_PauseRequest, @@ -108,13 +128,17 @@ inline const Event (&EnumValuesEvent())[9] { Event_WriteMemoryRequest, Event_WriteMemoryResponse, Event_ReadMemoryRequest, - Event_ReadMemoryResponse + Event_ReadMemoryResponse, + Event_WriteRegisterRequest, + Event_WriteRegisterResponse, + Event_ReadRegisterRequest, + Event_ReadRegisterResponse }; return values; } inline const char * const *EnumNamesEvent() { - static const char * const names[10] = { + static const char * const names[14] = { "NONE", "PauseRequest", "RunRequest", @@ -124,13 +148,17 @@ inline const char * const *EnumNamesEvent() { "WriteMemoryResponse", "ReadMemoryRequest", "ReadMemoryResponse", + "WriteRegisterRequest", + "WriteRegisterResponse", + "ReadRegisterRequest", + "ReadRegisterResponse", nullptr }; return names; } inline const char *EnumNameEvent(Event e) { - if (::flatbuffers::IsOutRange(e, Event_NONE, Event_ReadMemoryResponse)) return ""; + if (::flatbuffers::IsOutRange(e, Event_NONE, Event_ReadRegisterResponse)) return ""; const size_t index = static_cast(e); return EnumNamesEvent()[index]; } @@ -171,6 +199,22 @@ template<> struct EventTraits { static const Event enum_value = Event_ReadMemoryResponse; }; +template<> struct EventTraits { + static const Event enum_value = Event_WriteRegisterRequest; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_WriteRegisterResponse; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_ReadRegisterRequest; +}; + +template<> struct EventTraits { + static const Event enum_value = Event_ReadRegisterResponse; +}; + template struct EventUnionTraits { static const Event enum_value = Event_NONE; }; @@ -207,6 +251,22 @@ template<> struct EventUnionTraits { static const Event enum_value = Event_ReadMemoryResponse; }; +template<> struct EventUnionTraits { + static const Event enum_value = Event_WriteRegisterRequest; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_WriteRegisterResponse; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_ReadRegisterRequest; +}; + +template<> struct EventUnionTraits { + static const Event enum_value = Event_ReadRegisterResponse; +}; + struct EventUnion { Event type; void *value; @@ -301,6 +361,38 @@ struct EventUnion { return type == Event_ReadMemoryResponse ? reinterpret_cast(value) : nullptr; } + Debugger::WriteRegisterRequestT *AsWriteRegisterRequest() { + return type == Event_WriteRegisterRequest ? + reinterpret_cast(value) : nullptr; + } + const Debugger::WriteRegisterRequestT *AsWriteRegisterRequest() const { + return type == Event_WriteRegisterRequest ? + reinterpret_cast(value) : nullptr; + } + Debugger::WriteRegisterResponseT *AsWriteRegisterResponse() { + return type == Event_WriteRegisterResponse ? + reinterpret_cast(value) : nullptr; + } + const Debugger::WriteRegisterResponseT *AsWriteRegisterResponse() const { + return type == Event_WriteRegisterResponse ? + reinterpret_cast(value) : nullptr; + } + Debugger::ReadRegisterRequestT *AsReadRegisterRequest() { + return type == Event_ReadRegisterRequest ? + reinterpret_cast(value) : nullptr; + } + const Debugger::ReadRegisterRequestT *AsReadRegisterRequest() const { + return type == Event_ReadRegisterRequest ? + reinterpret_cast(value) : nullptr; + } + Debugger::ReadRegisterResponseT *AsReadRegisterResponse() { + return type == Event_ReadRegisterResponse ? + reinterpret_cast(value) : nullptr; + } + const Debugger::ReadRegisterResponseT *AsReadRegisterResponse() const { + return type == Event_ReadRegisterResponse ? + reinterpret_cast(value) : nullptr; + } }; bool VerifyEvent(::flatbuffers::Verifier &verifier, const void *obj, Event type); @@ -808,6 +900,306 @@ inline ::flatbuffers::Offset CreateReadMemoryResponseDirect( ::flatbuffers::Offset CreateReadMemoryResponse(::flatbuffers::FlatBufferBuilder &_fbb, const ReadMemoryResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct WriteRegisterRequestT : public ::flatbuffers::NativeTable { + typedef WriteRegisterRequest TableType; + uint32_t register_ = 0; + std::vector data{}; +}; + +struct WriteRegisterRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef WriteRegisterRequestT NativeTableType; + typedef WriteRegisterRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_REGISTER_ = 4, + VT_DATA = 6 + }; + uint32_t register_() const { + return GetField(VT_REGISTER_, 0); + } + bool mutate_register_(uint32_t _register_ = 0) { + return SetField(VT_REGISTER_, _register_, 0); + } + const ::flatbuffers::Vector *data() const { + return GetPointer *>(VT_DATA); + } + ::flatbuffers::Vector *mutable_data() { + return GetPointer<::flatbuffers::Vector *>(VT_DATA); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_REGISTER_, 4) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && + verifier.EndTable(); + } + WriteRegisterRequestT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(WriteRegisterRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WriteRegisterRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct WriteRegisterRequestBuilder { + typedef WriteRegisterRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_register_(uint32_t register_) { + fbb_.AddElement(WriteRegisterRequest::VT_REGISTER_, register_, 0); + } + void add_data(::flatbuffers::Offset<::flatbuffers::Vector> data) { + fbb_.AddOffset(WriteRegisterRequest::VT_DATA, data); + } + explicit WriteRegisterRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateWriteRegisterRequest( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t register_ = 0, + ::flatbuffers::Offset<::flatbuffers::Vector> data = 0) { + WriteRegisterRequestBuilder builder_(_fbb); + builder_.add_data(data); + builder_.add_register_(register_); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateWriteRegisterRequestDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t register_ = 0, + const std::vector *data = nullptr) { + auto data__ = data ? _fbb.CreateVector(*data) : 0; + return Debugger::CreateWriteRegisterRequest( + _fbb, + register_, + data__); +} + +::flatbuffers::Offset CreateWriteRegisterRequest(::flatbuffers::FlatBufferBuilder &_fbb, const WriteRegisterRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct WriteRegisterResponseT : public ::flatbuffers::NativeTable { + typedef WriteRegisterResponse TableType; + uint32_t register_ = 0; + uint32_t size = 0; + bool success = false; +}; + +struct WriteRegisterResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef WriteRegisterResponseT NativeTableType; + typedef WriteRegisterResponseBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_REGISTER_ = 4, + VT_SIZE = 6, + VT_SUCCESS = 8 + }; + uint32_t register_() const { + return GetField(VT_REGISTER_, 0); + } + bool mutate_register_(uint32_t _register_ = 0) { + return SetField(VT_REGISTER_, _register_, 0); + } + uint32_t size() const { + return GetField(VT_SIZE, 0); + } + bool mutate_size(uint32_t _size = 0) { + return SetField(VT_SIZE, _size, 0); + } + bool success() const { + return GetField(VT_SUCCESS, 0) != 0; + } + bool mutate_success(bool _success = 0) { + return SetField(VT_SUCCESS, static_cast(_success), 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_REGISTER_, 4) && + VerifyField(verifier, VT_SIZE, 4) && + VerifyField(verifier, VT_SUCCESS, 1) && + verifier.EndTable(); + } + WriteRegisterResponseT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(WriteRegisterResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WriteRegisterResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct WriteRegisterResponseBuilder { + typedef WriteRegisterResponse Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_register_(uint32_t register_) { + fbb_.AddElement(WriteRegisterResponse::VT_REGISTER_, register_, 0); + } + void add_size(uint32_t size) { + fbb_.AddElement(WriteRegisterResponse::VT_SIZE, size, 0); + } + void add_success(bool success) { + fbb_.AddElement(WriteRegisterResponse::VT_SUCCESS, static_cast(success), 0); + } + explicit WriteRegisterResponseBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateWriteRegisterResponse( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t register_ = 0, + uint32_t size = 0, + bool success = false) { + WriteRegisterResponseBuilder builder_(_fbb); + builder_.add_size(size); + builder_.add_register_(register_); + builder_.add_success(success); + return builder_.Finish(); +} + +::flatbuffers::Offset CreateWriteRegisterResponse(::flatbuffers::FlatBufferBuilder &_fbb, const WriteRegisterResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReadRegisterRequestT : public ::flatbuffers::NativeTable { + typedef ReadRegisterRequest TableType; + uint32_t register_ = 0; +}; + +struct ReadRegisterRequest FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef ReadRegisterRequestT NativeTableType; + typedef ReadRegisterRequestBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_REGISTER_ = 4 + }; + uint32_t register_() const { + return GetField(VT_REGISTER_, 0); + } + bool mutate_register_(uint32_t _register_ = 0) { + return SetField(VT_REGISTER_, _register_, 0); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_REGISTER_, 4) && + verifier.EndTable(); + } + ReadRegisterRequestT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReadRegisterRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReadRegisterRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReadRegisterRequestBuilder { + typedef ReadRegisterRequest Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_register_(uint32_t register_) { + fbb_.AddElement(ReadRegisterRequest::VT_REGISTER_, register_, 0); + } + explicit ReadRegisterRequestBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateReadRegisterRequest( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t register_ = 0) { + ReadRegisterRequestBuilder builder_(_fbb); + builder_.add_register_(register_); + return builder_.Finish(); +} + +::flatbuffers::Offset CreateReadRegisterRequest(::flatbuffers::FlatBufferBuilder &_fbb, const ReadRegisterRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct ReadRegisterResponseT : public ::flatbuffers::NativeTable { + typedef ReadRegisterResponse TableType; + uint32_t register_ = 0; + std::vector data{}; +}; + +struct ReadRegisterResponse FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef ReadRegisterResponseT NativeTableType; + typedef ReadRegisterResponseBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_REGISTER_ = 4, + VT_DATA = 6 + }; + uint32_t register_() const { + return GetField(VT_REGISTER_, 0); + } + bool mutate_register_(uint32_t _register_ = 0) { + return SetField(VT_REGISTER_, _register_, 0); + } + const ::flatbuffers::Vector *data() const { + return GetPointer *>(VT_DATA); + } + ::flatbuffers::Vector *mutable_data() { + return GetPointer<::flatbuffers::Vector *>(VT_DATA); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_REGISTER_, 4) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && + verifier.EndTable(); + } + ReadRegisterResponseT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ReadRegisterResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReadRegisterResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ReadRegisterResponseBuilder { + typedef ReadRegisterResponse Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_register_(uint32_t register_) { + fbb_.AddElement(ReadRegisterResponse::VT_REGISTER_, register_, 0); + } + void add_data(::flatbuffers::Offset<::flatbuffers::Vector> data) { + fbb_.AddOffset(ReadRegisterResponse::VT_DATA, data); + } + explicit ReadRegisterResponseBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateReadRegisterResponse( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t register_ = 0, + ::flatbuffers::Offset<::flatbuffers::Vector> data = 0) { + ReadRegisterResponseBuilder builder_(_fbb); + builder_.add_data(data); + builder_.add_register_(register_); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset CreateReadRegisterResponseDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t register_ = 0, + const std::vector *data = nullptr) { + auto data__ = data ? _fbb.CreateVector(*data) : 0; + return Debugger::CreateReadRegisterResponse( + _fbb, + register_, + data__); +} + +::flatbuffers::Offset CreateReadRegisterResponse(::flatbuffers::FlatBufferBuilder &_fbb, const ReadRegisterResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct DebugEventT : public ::flatbuffers::NativeTable { typedef DebugEvent TableType; Debugger::EventUnion event{}; @@ -851,6 +1243,18 @@ struct DebugEvent FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { const Debugger::ReadMemoryResponse *event_as_ReadMemoryResponse() const { return event_type() == Debugger::Event_ReadMemoryResponse ? static_cast(event()) : nullptr; } + const Debugger::WriteRegisterRequest *event_as_WriteRegisterRequest() const { + return event_type() == Debugger::Event_WriteRegisterRequest ? static_cast(event()) : nullptr; + } + const Debugger::WriteRegisterResponse *event_as_WriteRegisterResponse() const { + return event_type() == Debugger::Event_WriteRegisterResponse ? static_cast(event()) : nullptr; + } + const Debugger::ReadRegisterRequest *event_as_ReadRegisterRequest() const { + return event_type() == Debugger::Event_ReadRegisterRequest ? static_cast(event()) : nullptr; + } + const Debugger::ReadRegisterResponse *event_as_ReadRegisterResponse() const { + return event_type() == Debugger::Event_ReadRegisterResponse ? static_cast(event()) : nullptr; + } void *mutable_event() { return GetPointer(VT_EVENT); } @@ -898,6 +1302,22 @@ template<> inline const Debugger::ReadMemoryResponse *DebugEvent::event_as inline const Debugger::WriteRegisterRequest *DebugEvent::event_as() const { + return event_as_WriteRegisterRequest(); +} + +template<> inline const Debugger::WriteRegisterResponse *DebugEvent::event_as() const { + return event_as_WriteRegisterResponse(); +} + +template<> inline const Debugger::ReadRegisterRequest *DebugEvent::event_as() const { + return event_as_ReadRegisterRequest(); +} + +template<> inline const Debugger::ReadRegisterResponse *DebugEvent::event_as() const { + return event_as_ReadRegisterResponse(); +} + struct DebugEventBuilder { typedef DebugEvent Table; ::flatbuffers::FlatBufferBuilder &fbb_; @@ -1148,6 +1568,122 @@ inline ::flatbuffers::Offset CreateReadMemoryResponse(::flat _data); } +inline WriteRegisterRequestT *WriteRegisterRequest::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new WriteRegisterRequestT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void WriteRegisterRequest::UnPackTo(WriteRegisterRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = register_(); _o->register_ = _e; } + { auto _e = data(); if (_e) { _o->data.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->data.begin()); } } +} + +inline ::flatbuffers::Offset WriteRegisterRequest::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WriteRegisterRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateWriteRegisterRequest(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateWriteRegisterRequest(::flatbuffers::FlatBufferBuilder &_fbb, const WriteRegisterRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const WriteRegisterRequestT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _register_ = _o->register_; + auto _data = _o->data.size() ? _fbb.CreateVector(_o->data) : 0; + return Debugger::CreateWriteRegisterRequest( + _fbb, + _register_, + _data); +} + +inline WriteRegisterResponseT *WriteRegisterResponse::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new WriteRegisterResponseT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void WriteRegisterResponse::UnPackTo(WriteRegisterResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = register_(); _o->register_ = _e; } + { auto _e = size(); _o->size = _e; } + { auto _e = success(); _o->success = _e; } +} + +inline ::flatbuffers::Offset WriteRegisterResponse::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WriteRegisterResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateWriteRegisterResponse(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateWriteRegisterResponse(::flatbuffers::FlatBufferBuilder &_fbb, const WriteRegisterResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const WriteRegisterResponseT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _register_ = _o->register_; + auto _size = _o->size; + auto _success = _o->success; + return Debugger::CreateWriteRegisterResponse( + _fbb, + _register_, + _size, + _success); +} + +inline ReadRegisterRequestT *ReadRegisterRequest::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReadRegisterRequestT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReadRegisterRequest::UnPackTo(ReadRegisterRequestT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = register_(); _o->register_ = _e; } +} + +inline ::flatbuffers::Offset ReadRegisterRequest::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReadRegisterRequestT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateReadRegisterRequest(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateReadRegisterRequest(::flatbuffers::FlatBufferBuilder &_fbb, const ReadRegisterRequestT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const ReadRegisterRequestT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _register_ = _o->register_; + return Debugger::CreateReadRegisterRequest( + _fbb, + _register_); +} + +inline ReadRegisterResponseT *ReadRegisterResponse::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new ReadRegisterResponseT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ReadRegisterResponse::UnPackTo(ReadRegisterResponseT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = register_(); _o->register_ = _e; } + { auto _e = data(); if (_e) { _o->data.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->data.begin()); } } +} + +inline ::flatbuffers::Offset ReadRegisterResponse::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReadRegisterResponseT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateReadRegisterResponse(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset CreateReadRegisterResponse(::flatbuffers::FlatBufferBuilder &_fbb, const ReadRegisterResponseT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const ReadRegisterResponseT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _register_ = _o->register_; + auto _data = _o->data.size() ? _fbb.CreateVector(_o->data) : 0; + return Debugger::CreateReadRegisterResponse( + _fbb, + _register_, + _data); +} + inline DebugEventT *DebugEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { auto _o = std::unique_ptr(new DebugEventT()); UnPackTo(_o.get(), _resolver); @@ -1214,6 +1750,22 @@ inline bool VerifyEvent(::flatbuffers::Verifier &verifier, const void *obj, Even auto ptr = reinterpret_cast(obj); return verifier.VerifyTable(ptr); } + case Event_WriteRegisterRequest: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_WriteRegisterResponse: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_ReadRegisterRequest: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Event_ReadRegisterResponse: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } default: return true; } } @@ -1265,6 +1817,22 @@ inline void *EventUnion::UnPack(const void *obj, Event type, const ::flatbuffers auto ptr = reinterpret_cast(obj); return ptr->UnPack(resolver); } + case Event_WriteRegisterRequest: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_WriteRegisterResponse: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_ReadRegisterRequest: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Event_ReadRegisterResponse: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } default: return nullptr; } } @@ -1304,6 +1872,22 @@ inline ::flatbuffers::Offset EventUnion::Pack(::flatbuffers::FlatBufferBui auto ptr = reinterpret_cast(value); return CreateReadMemoryResponse(_fbb, ptr, _rehasher).Union(); } + case Event_WriteRegisterRequest: { + auto ptr = reinterpret_cast(value); + return CreateWriteRegisterRequest(_fbb, ptr, _rehasher).Union(); + } + case Event_WriteRegisterResponse: { + auto ptr = reinterpret_cast(value); + return CreateWriteRegisterResponse(_fbb, ptr, _rehasher).Union(); + } + case Event_ReadRegisterRequest: { + auto ptr = reinterpret_cast(value); + return CreateReadRegisterRequest(_fbb, ptr, _rehasher).Union(); + } + case Event_ReadRegisterResponse: { + auto ptr = reinterpret_cast(value); + return CreateReadRegisterResponse(_fbb, ptr, _rehasher).Union(); + } default: return 0; } } @@ -1342,6 +1926,22 @@ inline EventUnion::EventUnion(const EventUnion &u) : type(u.type), value(nullptr value = new Debugger::ReadMemoryResponseT(*reinterpret_cast(u.value)); break; } + case Event_WriteRegisterRequest: { + value = new Debugger::WriteRegisterRequestT(*reinterpret_cast(u.value)); + break; + } + case Event_WriteRegisterResponse: { + value = new Debugger::WriteRegisterResponseT(*reinterpret_cast(u.value)); + break; + } + case Event_ReadRegisterRequest: { + value = new Debugger::ReadRegisterRequestT(*reinterpret_cast(u.value)); + break; + } + case Event_ReadRegisterResponse: { + value = new Debugger::ReadRegisterResponseT(*reinterpret_cast(u.value)); + break; + } default: break; } @@ -1389,6 +1989,26 @@ inline void EventUnion::Reset() { delete ptr; break; } + case Event_WriteRegisterRequest: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_WriteRegisterResponse: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_ReadRegisterRequest: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Event_ReadRegisterResponse: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } default: break; } value = nullptr; From 99f2f47e623f420384248bf4520a2d8553903ba4 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 28 Apr 2025 14:58:08 +0200 Subject: [PATCH 13/17] Support toggling emulation state --- page/public/emulator-worker.js | 2 +- page/src/Playground.tsx | 37 +++++++++++--- page/src/components/status-indicator.tsx | 42 +++++++++++---- page/src/emulator.ts | 65 +++++++++++++++++++++++- src/debugger/event_handler.cpp | 10 ++-- 5 files changed, 130 insertions(+), 26 deletions(-) diff --git a/page/public/emulator-worker.js b/page/public/emulator-worker.js index 91f9725f..feeee17d 100644 --- a/page/public/emulator-worker.js +++ b/page/public/emulator-worker.js @@ -46,7 +46,7 @@ function getMessageFromQueue() { return ""; } - return msgQueue.pop(); + return msgQueue.shift(); } function runEmulation(filesystem, file, options) { diff --git a/page/src/Playground.tsx b/page/src/Playground.tsx index 6e018ef5..ea949959 100644 --- a/page/src/Playground.tsx +++ b/page/src/Playground.tsx @@ -1,4 +1,4 @@ -import { useState, useRef } from "react"; +import { useState, useRef, useReducer } from "react"; import { Output } from "@/components/output"; import { AppSidebar } from "@/components/app-sidebar"; @@ -10,7 +10,7 @@ import { } from "@/components/ui/sidebar"; import { Button } from "./components/ui/button"; -import { Emulator, UserFile } from "./emulator"; +import { Emulator, UserFile, EmulationState } from "./emulator"; import { getFilesystem } from "./filesystem"; import "./App.css"; @@ -23,7 +23,7 @@ import { import { createDefaultSettings } from "./settings"; import { SettingsMenu } from "./components/settings-menu"; -import { PlayFill, StopFill, GearFill } from "react-bootstrap-icons"; +import { PlayFill, StopFill, GearFill, PauseFill } from "react-bootstrap-icons"; import { StatusIndicator } from "./components/status-indicator"; import { Header } from "./Header"; @@ -64,6 +64,7 @@ export function Playground() { const output = useRef(null); const [settings, setSettings] = useState(createDefaultSettings()); const [emulator, setEmulator] = useState(null); + const [, forceUpdate] = useReducer((x) => x + 1, 0); function logLine(line: string) { output.current?.logLine(line); @@ -73,6 +74,18 @@ export function Playground() { output.current?.logLines(lines); } + function isEmulatorPaused() { + return emulator && emulator.getState() == EmulationState.Paused; + } + + function toggleEmulatorState() { + if (isEmulatorPaused()) { + emulator?.resume(); + } else { + emulator?.pause(); + } + } + async function createEmulator(userFile: UserFile | null = null) { emulator?.stop(); output.current?.clear(); @@ -83,7 +96,7 @@ export function Playground() { logLine(`Processing filesystem (${current}/${total}): ${file}`); }); - const new_emulator = new Emulator(fs, logLines); + const new_emulator = new Emulator(fs, logLines, (_) => forceUpdate()); new_emulator.onTerminate().then(() => setEmulator(null)); setEmulator(new_emulator); @@ -116,8 +129,16 @@ export function Playground() { - @@ -131,7 +152,9 @@ export function Playground() {
- +
diff --git a/page/src/components/status-indicator.tsx b/page/src/components/status-indicator.tsx index 4bd469b5..1b627bbd 100644 --- a/page/src/components/status-indicator.tsx +++ b/page/src/components/status-indicator.tsx @@ -1,28 +1,48 @@ import { Badge } from "@/components/ui/badge"; import { CircleFill } from "react-bootstrap-icons"; +import { EmulationState as State } from "@/emulator"; + +function getStateName(state: State) { + switch (state) { + case State.Stopped: + return "Stopped"; + case State.Paused: + return "Paused"; + case State.Running: + return "Running"; + default: + return ""; + } +} + +function getStateColor(state: State) { + switch (state) { + case State.Stopped: + return "bg-orange-600"; + case State.Paused: + return "bg-amber-500"; + case State.Running: + return "bg-lime-600"; + default: + return ""; + } +} export interface StatusIndicatorProps { - running: boolean; + state: State; } export function StatusIndicator(props: StatusIndicatorProps) { - const getText = () => { - return props.running ? " Running" : " Stopped"; - }; - - const getColor = () => { - return props.running ? "bg-lime-600" : "bg-orange-600"; - }; - return ( - {getText()} + {getStateName(props.state)} ); } diff --git a/page/src/emulator.ts b/page/src/emulator.ts index 61a0024f..123dc823 100644 --- a/page/src/emulator.ts +++ b/page/src/emulator.ts @@ -12,6 +12,12 @@ export interface UserFile { data: ArrayBuffer; } +export enum EmulationState { + Stopped, + Paused, + Running, +} + function base64Encode(uint8Array: Uint8Array): string { let binaryString = ""; for (let i = 0; i < uint8Array.byteLength; i++) { @@ -41,17 +47,26 @@ function decodeEvent(data: string) { return event.unpack(); } +type StateChangeHandler = (state: EmulationState) => void; + export class Emulator { filesystem: FileEntry[]; logHandler: LogHandler; + stateChangeHandler: StateChangeHandler; terminatePromise: Promise; terminateResolve: (value: number | null) => void; terminateReject: (reason?: any) => void; worker: Worker; + state: EmulationState = EmulationState.Stopped; - constructor(filesystem: FileEntry[], logHandler: LogHandler) { + constructor( + filesystem: FileEntry[], + logHandler: LogHandler, + stateChangeHandler: StateChangeHandler, + ) { this.filesystem = filesystem; this.logHandler = logHandler; + this.stateChangeHandler = stateChangeHandler; this.terminateResolve = () => {}; this.terminateReject = () => {}; this.terminatePromise = new Promise((resolve, reject) => { @@ -81,6 +96,7 @@ export class Emulator { }); } + this._setState(EmulationState.Running); this.worker.postMessage({ message: "run", data: { @@ -91,6 +107,19 @@ export class Emulator { }); } + updateState() { + this.sendEvent( + new fbDebugger.DebugEventT( + fbDebugger.Event.GetStateRequest, + new fbDebugger.GetStateRequestT(), + ), + ); + } + + getState() { + return this.state; + } + stop() { this.worker.terminate(); this.terminateResolve(null); @@ -119,6 +148,8 @@ export class Emulator { new fbDebugger.PauseRequestT(), ), ); + + this.updateState(); } resume() { @@ -128,6 +159,8 @@ export class Emulator { new fbDebugger.RunRequestT(), ), ); + + this.updateState(); } _onMessage(event: MessageEvent) { @@ -136,11 +169,39 @@ export class Emulator { } else if (event.data.message == "event") { this._onEvent(decodeEvent(event.data.data)); } else if (event.data.message == "end") { + this._setState(EmulationState.Stopped); this.terminateResolve(0); } } _onEvent(event: fbDebugger.DebugEventT) { - console.log(event); + switch (event.eventType) { + case fbDebugger.Event.GetStateResponse: + this._handle_state_response( + event.event as fbDebugger.GetStateResponseT, + ); + break; + } + } + + _setState(state: EmulationState) { + this.state = state; + this.stateChangeHandler(this.state); + } + + _handle_state_response(response: fbDebugger.GetStateResponseT) { + switch (response.state) { + case fbDebugger.State.None: + this._setState(EmulationState.Stopped); + break; + + case fbDebugger.State.Paused: + this._setState(EmulationState.Paused); + break; + + case fbDebugger.State.Running: + this._setState(EmulationState.Running); + break; + } } } diff --git a/src/debugger/event_handler.cpp b/src/debugger/event_handler.cpp index d607d239..72d24bd2 100644 --- a/src/debugger/event_handler.cpp +++ b/src/debugger/event_handler.cpp @@ -125,15 +125,15 @@ namespace debugger void handle_read_register(const event_context& c, const Debugger::ReadRegisterRequestT& request) { - uint8_t buffer[512]{}; - const auto res = - c.win_emu.emu().read_register(static_cast(request.register_), buffer, sizeof(buffer)); + std::array buffer{}; + const auto res = c.win_emu.emu().read_register(static_cast(request.register_), buffer.data(), + buffer.size()); - const auto size = std::min(sizeof(buffer), res); + const auto size = std::min(buffer.size(), res); Debugger::ReadRegisterResponseT response{}; response.register_ = request.register_; - response.data.assign(buffer, buffer + size); + response.data.assign(buffer.data(), buffer.data() + size); send_event(std::move(response)); } From c2916cde592590ee56e374b832769b6814446bf4 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 28 Apr 2025 15:28:11 +0200 Subject: [PATCH 14/17] Add resizable pannels --- page/package-lock.json | 11 ++++++ page/package.json | 1 + page/src/components/ui/resizable.tsx | 54 ++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 page/src/components/ui/resizable.tsx diff --git a/page/package-lock.json b/page/package-lock.json index 845dbe87..3c9c9f3f 100644 --- a/page/package-lock.json +++ b/page/package-lock.json @@ -29,6 +29,7 @@ "react-bootstrap-icons": "^1.11.5", "react-dom": "^19.0.0", "react-helmet": "^6.1.0", + "react-resizable-panels": "^2.1.9", "react-router-dom": "^7.5.2", "react-window": "^1.8.11", "tailwind-merge": "^3.2.0", @@ -4632,6 +4633,16 @@ } } }, + "node_modules/react-resizable-panels": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.9.tgz", + "integrity": "sha512-z77+X08YDIrgAes4jl8xhnUu1LNIRp4+E7cv4xHmLOxxUPO/ML7PSrE813b90vj7xvQ1lcf7g2uA9GeMZonjhQ==", + "license": "MIT", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/react-router": { "version": "7.5.2", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.5.2.tgz", diff --git a/page/package.json b/page/package.json index 13ae4aca..0cc70745 100644 --- a/page/package.json +++ b/page/package.json @@ -31,6 +31,7 @@ "react-bootstrap-icons": "^1.11.5", "react-dom": "^19.0.0", "react-helmet": "^6.1.0", + "react-resizable-panels": "^2.1.9", "react-router-dom": "^7.5.2", "react-window": "^1.8.11", "tailwind-merge": "^3.2.0", diff --git a/page/src/components/ui/resizable.tsx b/page/src/components/ui/resizable.tsx new file mode 100644 index 00000000..c9556348 --- /dev/null +++ b/page/src/components/ui/resizable.tsx @@ -0,0 +1,54 @@ +import * as React from "react"; +import { GripVerticalIcon } from "lucide-react"; +import * as ResizablePrimitive from "react-resizable-panels"; + +import { cn } from "@/lib/utils"; + +function ResizablePanelGroup({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function ResizablePanel({ + ...props +}: React.ComponentProps) { + return ; +} + +function ResizableHandle({ + withHandle, + className, + ...props +}: React.ComponentProps & { + withHandle?: boolean; +}) { + return ( + div]:rotate-90", + className, + )} + {...props} + > + {withHandle && ( +
+ +
+ )} +
+ ); +} + +export { ResizablePanelGroup, ResizablePanel, ResizableHandle }; From 312c8aeeaf8b428b2b490a2d30eca4b64db61f02 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 28 Apr 2025 21:02:13 +0200 Subject: [PATCH 15/17] UI progress --- page/index.html | 2 ++ page/src/App.css | 21 ++++++++---- page/src/Playground.tsx | 60 ++++++++++++++++++++++++++-------- page/src/components/output.tsx | 2 +- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/page/index.html b/page/index.html index 912a7881..aa03edd1 100644 --- a/page/index.html +++ b/page/index.html @@ -12,6 +12,8 @@ Sogen - Windows User Space Emulator + + { return new Promise((resolve, reject) => { @@ -117,19 +122,19 @@ export function Playground() { -
- - - - - - @@ -157,8 +162,35 @@ export function Playground() { />
-
- +
+ + {/* Left */} + Disassembly + + {/* Middle */} + + + {/* Middle - Top */} + + + + + {/* Middle - Bottom */} + Memory + + + + {/* Right */} + + + {/* Right - Top */} + Registers + + {/* Right - Bottom */} + Stack + + +
diff --git a/page/src/components/output.tsx b/page/src/components/output.tsx index a9c3677d..05489c48 100644 --- a/page/src/components/output.tsx +++ b/page/src/components/output.tsx @@ -238,7 +238,7 @@ export class Output extends React.Component { width={this.state.width} height={this.state.height} itemCount={this.state.lines.length} - itemSize={20} + itemSize={16} > {({ index, style }) => { const line = this.state.lines[index]; From fd6d4f04201841af63a09937493967a9499d9559 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Tue, 29 Apr 2025 09:19:14 +0200 Subject: [PATCH 16/17] Slight style changes --- page/index.html | 2 +- page/package-lock.json | 70 +++++++ page/package.json | 1 + page/src/App.css | 45 +++- page/src/Playground.tsx | 101 +++++---- page/src/components/output.tsx | 2 +- page/src/components/ui/button.tsx | 4 +- page/src/components/ui/dropdown-menu.tsx | 255 +++++++++++++++++++++++ 8 files changed, 429 insertions(+), 51 deletions(-) create mode 100644 page/src/components/ui/dropdown-menu.tsx diff --git a/page/index.html b/page/index.html index aa03edd1..e751201f 100644 --- a/page/index.html +++ b/page/index.html @@ -12,7 +12,7 @@ Sogen - Windows User Space Emulator - + { return new Promise((resolve, reject) => { const fileInput = document.createElement("input"); @@ -125,23 +142,52 @@ export function Playground() {
- + + + Run Application + + + createEmulator()}> + + Select Sample + + loadAndRunUserFile()}> + + Seelct your .exe + + + + + + - - - @@ -162,35 +208,8 @@ export function Playground() { />
-
- - {/* Left */} - Disassembly - - {/* Middle */} - - - {/* Middle - Top */} - - - - - {/* Middle - Bottom */} - Memory - - - - {/* Right */} - - - {/* Right - Top */} - Registers - - {/* Right - Bottom */} - Stack - - - +
+
diff --git a/page/src/components/output.tsx b/page/src/components/output.tsx index 05489c48..a9c3677d 100644 --- a/page/src/components/output.tsx +++ b/page/src/components/output.tsx @@ -238,7 +238,7 @@ export class Output extends React.Component { width={this.state.width} height={this.state.height} itemCount={this.state.lines.length} - itemSize={16} + itemSize={20} > {({ index, style }) => { const line = this.state.lines[index]; diff --git a/page/src/components/ui/button.tsx b/page/src/components/ui/button.tsx index 2adaf00d..d0f87271 100644 --- a/page/src/components/ui/button.tsx +++ b/page/src/components/ui/button.tsx @@ -10,13 +10,13 @@ const buttonVariants = cva( variants: { variant: { default: - "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", + "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90 fancy-primary", destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", secondary: - "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", + "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80 fancy-secondary", ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", diff --git a/page/src/components/ui/dropdown-menu.tsx b/page/src/components/ui/dropdown-menu.tsx new file mode 100644 index 00000000..fe5ed99e --- /dev/null +++ b/page/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,255 @@ +import * as React from "react"; +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +function DropdownMenu({ + ...props +}: React.ComponentProps) { + return ; +} + +function DropdownMenuPortal({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ); +} + +function DropdownMenuGroup({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuItem({ + className, + inset, + variant = "default", + ...props +}: React.ComponentProps & { + inset?: boolean; + variant?: "default" | "destructive"; +}) { + return ( + + ); +} + +function DropdownMenuCheckboxItem({ + className, + children, + checked, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ); +} + +function DropdownMenuRadioGroup({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuRadioItem({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ); +} + +function DropdownMenuLabel({ + className, + inset, + ...props +}: React.ComponentProps & { + inset?: boolean; +}) { + return ( + + ); +} + +function DropdownMenuSeparator({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuShortcut({ + className, + ...props +}: React.ComponentProps<"span">) { + return ( + + ); +} + +function DropdownMenuSub({ + ...props +}: React.ComponentProps) { + return ; +} + +function DropdownMenuSubTrigger({ + className, + inset, + children, + ...props +}: React.ComponentProps & { + inset?: boolean; +}) { + return ( + + {children} + + + ); +} + +function DropdownMenuSubContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +export { + DropdownMenu, + DropdownMenuPortal, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuLabel, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuSub, + DropdownMenuSubTrigger, + DropdownMenuSubContent, +}; From 5ed3036d53338acfce2d110bcc4bfe68b2613c2f Mon Sep 17 00:00:00 2001 From: momo5502 Date: Tue, 29 Apr 2025 09:25:25 +0200 Subject: [PATCH 17/17] Integrate debugger into analyzer --- page/public/emulator-worker.js | 4 +- src/analyzer/CMakeLists.txt | 1 + src/analyzer/main.cpp | 12 ++++ src/debugger/CMakeLists.txt | 12 +--- src/debugger/main.cpp | 97 ------------------------------ src/debugger/resource.rc | 101 -------------------------------- src/debugger/resources/icon.ico | Bin 5072 -> 0 bytes src/debugger/std_include.hpp | 31 ---------- 8 files changed, 18 insertions(+), 240 deletions(-) delete mode 100644 src/debugger/main.cpp delete mode 100644 src/debugger/resource.rc delete mode 100644 src/debugger/resources/icon.ico delete mode 100644 src/debugger/std_include.hpp diff --git a/page/public/emulator-worker.js b/page/public/emulator-worker.js index feeee17d..c3804f53 100644 --- a/page/public/emulator-worker.js +++ b/page/public/emulator-worker.js @@ -51,7 +51,7 @@ function getMessageFromQueue() { function runEmulation(filesystem, file, options) { globalThis.Module = { - arguments: ["./root", file], + arguments: [...options, "-e", "./root", file], onRuntimeInitialized: function () { filesystem.forEach((e) => { if (e.name.endsWith("/")) { @@ -74,5 +74,5 @@ function runEmulation(filesystem, file, options) { postRun: flushLines, }; - importScripts("./debugger.js"); + importScripts("./analyzer.js"); } diff --git a/src/analyzer/CMakeLists.txt b/src/analyzer/CMakeLists.txt index 0cfffb61..036e614e 100644 --- a/src/analyzer/CMakeLists.txt +++ b/src/analyzer/CMakeLists.txt @@ -16,6 +16,7 @@ endif() target_link_libraries(analyzer PRIVATE reflect + debugger windows-emulator windows-gdb-stub ) diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index ec943fa0..b95bd429 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -6,6 +6,10 @@ #include "object_watching.hpp" #include "snapshot.hpp" +#ifdef OS_EMSCRIPTEN +#include +#endif + #include #include @@ -249,6 +253,14 @@ namespace bool run(const analysis_options& options, const std::span args) { const auto win_emu = setup_emulator(options, args); + +#ifdef OS_EMSCRIPTEN + win_emu->callbacks.on_thread_switch = [&] { + debugger::event_context c{.win_emu = *win_emu}; + debugger::handle_events(c); // + }; +#endif + win_emu->log.log("Using emulator: %s\n", win_emu->emu().get_name().c_str()); (void)&watch_system_objects; diff --git a/src/debugger/CMakeLists.txt b/src/debugger/CMakeLists.txt index a0cf3db5..6fb70a5a 100644 --- a/src/debugger/CMakeLists.txt +++ b/src/debugger/CMakeLists.txt @@ -6,25 +6,19 @@ file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS list(SORT SRC_FILES) -add_executable(debugger ${SRC_FILES}) +add_library(debugger ${SRC_FILES}) momo_assign_source_group(${SRC_FILES}) -if(NOT MOMO_ENABLE_CLANG_TIDY) - target_precompile_headers(debugger PRIVATE std_include.hpp) -endif() - target_link_libraries(debugger PRIVATE windows-emulator flatbuffers base64 ) -set_property(GLOBAL PROPERTY VS_STARTUP_PROJECT debugger) +target_include_directories(debugger INTERFACE "${CMAKE_CURRENT_LIST_DIR}") -momo_strip_target(debugger) - -add_custom_target(gen_fbs +add_custom_target(generate-flatbuffer DEPENDS flatc COMMAND "$" --gen-mutable --gen-object-api --filename-ext hxx --cpp -o "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/events.fbs" COMMAND "$" --gen-mutable --gen-object-api --ts -o "${PROJECT_SOURCE_DIR}/page/src/fb" "${CMAKE_CURRENT_LIST_DIR}/events.fbs" diff --git a/src/debugger/main.cpp b/src/debugger/main.cpp deleted file mode 100644 index b234f088..00000000 --- a/src/debugger/main.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "std_include.hpp" - -#include -#include -#include "event_handler.hpp" - -namespace -{ - bool run_emulation(windows_emulator& win_emu) - { - try - { - win_emu.start(); - } - catch (const std::exception& e) - { - win_emu.log.error("Emulation failed at: 0x%" PRIx64 " - %s\n", win_emu.emu().read_instruction_pointer(), - e.what()); - throw; - } - catch (...) - { - win_emu.log.error("Emulation failed at: 0x%" PRIx64 "\n", win_emu.emu().read_instruction_pointer()); - throw; - } - - const auto exit_status = win_emu.process.exit_status; - if (!exit_status.has_value()) - { - win_emu.log.error("Emulation terminated without status!\n"); - return false; - } - - const auto success = *exit_status == STATUS_SUCCESS; - - win_emu.log.disable_output(false); - win_emu.log.print(success ? color::green : color::red, "Emulation terminated with status: %X\n", *exit_status); - - return success; - } - - bool run(const int argc, char** argv) - { - if (argc < 3) - { - return false; - } - - const emulator_settings settings{ - .emulation_root = argv[1], - }; - - application_settings app_settings{ - .application = argv[2], - }; - - for (int i = 3; i < argc; ++i) - { - app_settings.arguments.push_back(u8_to_u16(argv[i])); - } - - windows_emulator win_emu{app_settings, settings}; - - win_emu.callbacks.on_thread_switch = [&] { - debugger::event_context c{.win_emu = win_emu}; - debugger::handle_events(c); // - }; - - return run_emulation(win_emu); - } -} - -int main(const int argc, char** argv) -{ - try - { - const auto result = run(argc, argv); - 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; -} - -#ifdef _WIN32 -int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int) -{ - return main(__argc, __argv); -} -#endif diff --git a/src/debugger/resource.rc b/src/debugger/resource.rc deleted file mode 100644 index 8da94cc0..00000000 --- a/src/debugger/resource.rc +++ /dev/null @@ -1,101 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "windows.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "#include ""windows.h""\r\n" - "\0" -END - -2 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,0 - PRODUCTVERSION 1,0,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE VFT_DLL - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "momo5502" - VALUE "FileDescription", "Windows Emulator" - VALUE "FileVersion", "1.0.0.0" - VALUE "InternalName", "emulator" - VALUE "LegalCopyright", "All rights reserved." - VALUE "OriginalFilename", "emulator.exe" - VALUE "ProductName", "emulator" - VALUE "ProductVersion", "1.0.0.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -///////////////////////////////////////////////////////////////////////////// -// -// Binary Data -// - -GLFW_ICON ICON "resources/icon.ico" - - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src/debugger/resources/icon.ico b/src/debugger/resources/icon.ico deleted file mode 100644 index b4afb19bf6e0a5ed68896c8e8ddb6c26805835d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5072 zcmZQzU}Ruq00Bk@1%_S13=Con3=EwCe(t(JJtJ()9vmT+dV&U=-i*@=AZwb`)~hw{>)iY zEdov)iqs=Q_v+Q|``9wk-`v;s_sM0f@pVfqe^2M%l4D<$c6y!v-MhPX-}j$uoxs+> zXU+CDVoUO+zO(E9?6EZdBJQi-KjV7IZrR;g|3jAQRqcDZJHCF;&))qz_NS)L=XjIS zpm1Yj_VEw)Huv^?sn$1%UGXh+N$E@D+x@?u%~_V-w{!i{z`c(dP95C%eY?pmL%Ubv zxBEhV>l#UY{d4X-Z|$O&p|9OmmJ2wjZb+_uG1+&0%%9V9kFWTvewpRDoncMh=e_NB zZ{J#VPmzI(Z|CyT?;DoSnm231f!d(A$Gc8hzpnp!q`fRR^gTm^M!}gW$Q31JFZaX+;m#LocZm) z6}xsYTs;sjcQ@4hRp#~hx3?#qI8*=W@Y&f{U0GMC`OVy$9elODA@=3}-R|XU!^DLb zNNtQO4&`T;_{`k$Sbly+)S7RF3cWM7f95Ow$nfaEhn>B~SL*b<%KVEz#NK(utik$h z>Baq7|EjmH=bqI2d*&17fGEGJ6-y89S^BMfy;Z*7G^Xvc3RnvD>?e*?Gx$WWKo&SGS{l7nHU(Jd*zWv*`e*KhQUgP%mb6)AU z$-dmFth4srHb3V$J$+ZY&oT2!fA1gBl}~Eio8$8KvtH`?&!?aLsBV)exZ7?!J6)bF z=6_k&>eMw)w^tbE_+7Tydf)nFT3e_2{Ct&X z>{!Vgb@z08MbbR!%@<^sf7`$JQTD1$0$1<3rgJbj{`|IQZt#_V>o;DP*6vOaPHvJ~ z@!yvDRV|mzSP4L>&?Kcwr@2&b9fBFBp4B4K4kGDK7&h5Y4cXnH1 z|K)pAwC_IN6}qRUgP+;v{mQ@bi}jcsCI$YU&%hwC=$kzwgM!Q3dL{;kj$8j(7#ak& z{^w+1P|W%-%)sDu<)1nOL(7W4{tOHpBx#5bo_*Gu;lctM8Bel%U>a5!`0K{J*PFBD zQf=Ln{5uO4uK#gk{@e88J@wtceO0O}Qe~^w%{%`hYn&`j( zy|;fY%m%AykbHGIS*$#JPv0D~s*TY>yO*ZC-ky5Xh&y)w)~Nz3ctC+Cdf?oi)>-T4 z2J6@ERZ&bhy&+X}_rLu6n}XuDtAK(fAT1~6Zt(Wq>VEs4e9!x6EzcVFJ?Q+O`rsoo z_dhO3c$Xa`tYHo^DD_#Br#7>sK@LZYVZHVJzk+)kiWYyfXADSt!&NOI%qGdl^7dPK z%8AzfQ?Kj41I5*piRDI?|IMN!l*KL!YaE@qUp9MpZu73bLbtc|ObdFJ82`M)a^OO% zUgE$q|6t+z zU$+;mOP&Kt1{%i4V+9I05|;hno~l=Rare6gr;Qso-1nXP-|c~c#3$J{hNobw&csAK zaXoOwe($p&Uhp$X?-!n4`#|?{_VEkXyRx{&8Bh1$`p@DpQ}c(}g75Wjdh*kB zXMVK)#<3^Bvp3@1+ST6^JL{zjF0xhrebfh1$hzU>R$Hle^TjLge*Jzb?T?>h!N=-< zR@GUTPefb(4rki>pR<80;d0jQ*m0Am^4HO=*RF}Ke*Lu6n+X)E zqKi&fe}1m}u{Wad^ZTXemY$2>6+hd{lvR?;85BrOZ>sz6^(;58YgcT%tNFw2$I9aY zHeh|noF24X)c&)1{jDFrzp=FSMD_h-1qFJ@jGy_}b}O$t<#yo9@6Rs_CBHu^I`(%e zI2@Yxe04nc_iM}6qRr*UHHEM53N7{dyH*8k-jid;?WWA$V}8v3X+O1+=}YG`rFbA6b>o334VTy8c%C$`9F{pAz*`p>_HVNO~0kC~OW zUpe~ZB5NQ2FZ=hV>D+b3rg+RJ^+wj(d-nq!L5ZCCs9()XW8FV% z_pRb>$Xv@Rz5m8?jmh8?Z7w3k^3){a3iE>P-xB}a0~I+hTJJqOAj~lLdgO`VNf+8c z>Atb#y0QX;#p8CcaUND|jEoH*4};29feGIfJgOKH{uF>xWQ)p6#s%x@w}J{y0U;)b z{rsyWLFL2*0ft|-0cSxPy(XuoIy z`zfq$Lh*mYV&{v&jaS)LFZ*^grmOp3dGr67C13ybae;F4O|#GQ3vcgQWgfA0%lk7Y zUvo6-FbYWit4;f$|K06k!qp3QuQ^wIuNDdTZU2!mA^D$y{=S}72N&J5ljgf&lKu5x z_~LK%kC+eW{WuCzyzjJ}$2aLl&IXQz@D-1mRpwVF2umnFl&QzgPnb*Zw|wkpYIRd zHs#_%+~abcs~E0y_y>t3m!~acHr$J zGX+Kg$($gs3(Py;*XMfYFnpQ2MYmx0n{TVD_PaBJnhgB2r~SHm^58P2@4I*I@n>wP1ihg~%ky#dPEH=0`;zOr=5^6~6QEKXuhc))wKHs)$pc6!~J|No&8 zvDD1@?79GPBX@<;r&0fnBRzQ^X9h)x;>P8i=VyfNd(9BY+hDvr|5@$D=huQR22uk3f z{npOsNa-(pVcBeYeReE zE+x~v*pqr3Zi)=Qe6mYduJ#I--yPt=A;2*4;5o0QRy%HMUUhZ~C^H#zs5Gqd+~j~e0VLx4YMhW&CFzG>~G3u0++U@3cua&7T2j&|GP1Z zS>X(~Jy#;ndKP7dD|4z&-`XViguVCVu6_2m0!tYaa<^@pzS(T~-Cbe({$E}3cm59s zi(j`s$vtV~HSC+aac>sWgUy%AcQ_`Wj-P%$=6G}?xLE%4^6FFT3*YB*O#XJQ)U)Au zo3byV#NB;xZ10xK=E+N$9vI}uhF89h`Bdlppsby@$@~5DH~FA6 zn{s;|^9I9e)!zFPQ|C$M*HpGk8?9cN!505^b@{gUnU+ew4xwFgTcdx!z z`)``>yART4I}To7SI*ua{hDu6^;fxX>Az?Gygvo->=XMxVo>=)z$;v5R+ zQi{x1*4|qimL|=%+<52NPfCnOCf#X&zkj}U#M{quQ`eoY_m9_TkeGBbcEz{y^+o6Y zcAASssOXD1^mwFyT0d+1m4A93?^C7ip0_$Q@5*2(RG54A>HV{2GONFp27VHH9aH*{ z;n4x>(x3IAzbz+Rnt7-H>QUwuX?r&RPubefeEOKq)|q#hUnwz#Xl}OUuXTF+I3Q}* z71;^rp3U!eFl1cSnSRDP>;E(t?m53xa?Q%)S-Q9cD&K_0Z#1mm{pX>BS^4f=I~W3w z#;r+C{e*_j*YFG5Z*ES=Mf2&HlMt1+pFR~ z*{iiyhR!zQ{nAz3dtEe2^}Zv+(*G|GdkNE6hE+|Kh^0Z-H%TXYH^q<@;^ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -// NOLINTNEXTLINE(google-global-names-in-headers) -using namespace std::literals;