diff --git a/Cargo.lock b/Cargo.lock index 197f04c..74bfc59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,6 +210,12 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fnv" version = "1.0.7" @@ -372,6 +378,17 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pdb" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82040a392923abe6279c00ab4aff62d5250d1c8555dc780e4b02783a7aa74863" +dependencies = [ + "fallible-iterator", + "scroll", + "uuid", +] + [[package]] name = "proc-macro2" version = "1.0.86" @@ -493,9 +510,13 @@ name = "rivets-shared" version = "0.1.0" dependencies = [ "abi_stable", + "anyhow", "cpp_demangle", + "pdb", + "serde", "syn 2.0.72", "undname", + "windows", ] [[package]] @@ -519,6 +540,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" + [[package]] name = "semver" version = "1.0.23" @@ -665,6 +692,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" + [[package]] name = "version_check" version = "0.9.5" @@ -693,6 +726,70 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 3893526..5e06cb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rivets-rs" +name = "rivets" version = "0.1.0" edition = "2021" authors = ["Zachary Picco "] @@ -11,7 +11,7 @@ repository = "https://github.com/factorio-rivets/rivets-rs" rivets-macros = { path = "rivets-macros" } rivets-shared = { path = "rivets-shared" } retour = { version = "0.3", features = ["static-detour"] } -abi_stable = "0.11" +dll-syringe = { version = "0.15", features = ["full"] } [lints.clippy] nursery = { level = "warn", priority = -1 } diff --git a/rivets-macros/src/lib.rs b/rivets-macros/src/lib.rs index 7e3a05b..1e1b5e3 100644 --- a/rivets-macros/src/lib.rs +++ b/rivets-macros/src/lib.rs @@ -143,13 +143,10 @@ pub fn detour(attr: TokenStream, item: TokenStream) -> TokenStream { #[allow(unused_variables)] #callback - pub unsafe extern "C" fn hook(address: u64) -> rivets::abi_stable::std_types::RResult<(), rivets::abi_stable::std_types::RBoxError> { - unsafe fn hook(address: u64) -> Result<(), rivets::retour::Error> { - let compiled_function: #cpp_function_header = std::mem::transmute(address); - Detour.initialize(compiled_function, #name)?.enable()?; - Ok(()) - } - hook(address).map_err(|e| rivets::abi_stable::std_types::RBoxError::new(e)).into() + pub unsafe fn hook(address: u64) -> Result<(), rivets::retour::Error> { + let compiled_function: #cpp_function_header = std::mem::transmute(address); + Detour.initialize(compiled_function, #name)?.enable()?; + Ok(()) } } }; @@ -181,15 +178,24 @@ pub fn finalize(_: TokenStream) -> TokenStream { } }); - let vec = quote! { abi_stable::std_types::RVec }; - quote! { - #[rivets::abi_stable::sabi_extern_fn] - #[no_mangle] - pub extern "C" fn rivets_finalize() -> #vec { - let mut hooks: #vec = #vec::new(); - #(#injects)* - hooks + rivets::dll_syringe::payload_procedure! { + fn rivets_finalize(symbol_cache: rivets::SymbolCache) -> Option { + let base_address = match symbol_cache.get_module_base_address() { + Ok(base_address) => base_address, + Err(e) => return Some(format!("{e}")), + }; + + let mut hooks: Vec = Vec::new(); + #(#injects)* + for hook in &hooks { + let inject_result = unsafe { symbol_cache.inject(base_address, hook) }; + if inject_result.is_err() { + return Some(format!("{inject_result:?}")); + } + } + None + } } } .into() diff --git a/rivets-shared/Cargo.lock b/rivets-shared/Cargo.lock index 2201b25..6f9ecb1 100644 --- a/rivets-shared/Cargo.lock +++ b/rivets-shared/Cargo.lock @@ -2,6 +2,54 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "abi_stable" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d6512d3eb05ffe5004c59c206de7f99c34951504056ce23fc953842f12c445" +dependencies = [ + "abi_stable_derive", + "abi_stable_shared", + "const_panic", + "core_extensions", + "crossbeam-channel", + "generational-arena", + "libloading", + "lock_api", + "parking_lot", + "paste", + "repr_offset", + "rustc_version", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "abi_stable_derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7178468b407a4ee10e881bc7a328a65e739f0863615cca4429d43916b05e898" +dependencies = [ + "abi_stable_shared", + "as_derive_utils", + "core_extensions", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", + "typed-arena", +] + +[[package]] +name = "abi_stable_shared" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b5df7688c123e63f4d4d649cba63f2967ba7f7861b1664fca3f77d3dad2b63" +dependencies = [ + "core_extensions", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -14,6 +62,24 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "as_derive_utils" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff3c96645900a44cf11941c111bd08a6573b0e2f9f69bc9264b179d8fae753c4" +dependencies = [ + "core_extensions", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + [[package]] name = "bitflags" version = "2.6.0" @@ -43,6 +109,27 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "const_panic" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b" + +[[package]] +name = "core_extensions" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c71dc07c9721607e7a16108336048ee978c3a8b129294534272e8bac96c0ee" +dependencies = [ + "core_extensions_proc_macros", +] + +[[package]] +name = "core_extensions_proc_macros" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f3b219d28b6e3b4ac87bc1fc522e0803ab22e055da177bff0068c4150c61a6" + [[package]] name = "cpp_demangle" version = "0.4.3" @@ -53,25 +140,19 @@ dependencies = [ ] [[package]] -name = "dirs" -version = "5.0.1" +name = "crossbeam-channel" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "dirs-sys", + "crossbeam-utils", ] [[package]] -name = "dirs-sys" -version = "0.4.1" +name = "crossbeam-utils" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "fallible-iterator" @@ -80,16 +161,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] -name = "getrandom" -version = "0.2.15" +name = "generational-arena" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" dependencies = [ "cfg-if", - "libc", - "wasi", ] +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "libc" version = "0.2.155" @@ -97,13 +182,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] -name = "libredox" -version = "0.1.3" +name = "libloading" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "bitflags", - "libc", + "cfg-if", + "winapi", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", ] [[package]] @@ -119,10 +214,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" [[package]] -name = "option-ext" -version = "0.2.0" +name = "parking_lot" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pdb" @@ -154,14 +272,12 @@ dependencies = [ ] [[package]] -name = "redox_users" -version = "0.4.5" +name = "redox_syscall" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "getrandom", - "libredox", - "thiserror", + "bitflags", ] [[package]] @@ -170,26 +286,60 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +[[package]] +name = "repr_offset" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1070755bd29dffc19d0971cab794e607839ba2ef4b69a9e6fbc8733c1b72ea" +dependencies = [ + "tstr", +] + [[package]] name = "rivets-shared" version = "0.1.0" dependencies = [ + "abi_stable", "anyhow", "cpp_demangle", - "dirs", "pdb", - "proc-macro2", - "syn", + "syn 2.0.72", "undname", - "windows", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "scroll" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" version = "1.0.205" @@ -207,7 +357,19 @@ checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.72", +] + +[[package]] +name = "serde_json" +version = "1.0.124" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", ] [[package]] @@ -216,6 +378,17 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.72" @@ -244,9 +417,30 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.72", +] + +[[package]] +name = "tstr" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8e0294f14baae476d0dd0a2d780b2e24d66e349a9de876f5126777a37bdba7" +dependencies = [ + "tstr_proc_macros", ] +[[package]] +name = "tstr_proc_macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a" + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "undname" version = "1.1.2" @@ -275,98 +469,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.58.0" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets 0.52.6", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "windows-sys" -version = "0.48.0" +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "windows-targets" -version = "0.48.5" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-targets" @@ -374,46 +496,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -426,48 +530,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/rivets-shared/Cargo.toml b/rivets-shared/Cargo.toml index 719b565..9fe56f4 100644 --- a/rivets-shared/Cargo.toml +++ b/rivets-shared/Cargo.toml @@ -10,7 +10,15 @@ repository = "https://github.com/factorio-rivets/rivets" cpp_demangle = "0.4" undname = "1.1" syn = "2.0" -abi_stable = "0.11" +pdb = "0.8" +anyhow = "1.0" +windows = { version = "0.58", features = [ + "Win32", + "Win32_System", + "Win32_System_LibraryLoader", +] } +serde = { version = "1.0", features = ["derive"] } +retour = { version = "0.3", features = ["static-detour"] } [lib] name = "rivets_shared" diff --git a/rivets-shared/src/lib.rs b/rivets-shared/src/lib.rs index f92f159..cc4e0ea 100644 --- a/rivets-shared/src/lib.rs +++ b/rivets-shared/src/lib.rs @@ -1,7 +1,24 @@ -use abi_stable::std_types::{RBoxError, RResult, RString, RVec}; -use abi_stable::StableAbi; +use anyhow::{bail, Result}; use cpp_demangle::Symbol; +use pdb::{FallibleIterator, PDB}; +use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize}; +use std::collections::HashMap; +use std::ffi::{CStr, CString}; +use std::fs::File; +use std::path::Path; use undname::Flags; +use windows::core::PCSTR; +use windows::Win32::System::LibraryLoader::GetModuleHandleA; + +pub trait AsPcstr { + fn as_pcstr(&self) -> PCSTR; +} + +impl AsPcstr for CStr { + fn as_pcstr(&self) -> PCSTR { + PCSTR(self.as_ptr().cast()) + } +} /// Attempts to demangle a mangled MSVC C++ symbol name. First tries MSVC demangling, then falls back to Itanium. #[must_use] @@ -43,15 +60,96 @@ pub fn get_calling_convention(abi: &str) -> Option { /// ``` pub type Opaque = *const std::ffi::c_void; -#[repr(C)] -#[derive(StableAbi)] pub struct RivetsHook { - pub mangled_name: RString, - pub hook: unsafe extern "C" fn(u64) -> RResult<(), RBoxError>, + pub mangled_name: String, + pub hook: unsafe fn(u64) -> Result<(), retour::Error>, } -#[repr(C)] -#[derive(StableAbi)] -pub struct RivetsFinalizeABI { - pub get_hooks: extern "C" fn() -> RVec, +#[derive(SerdeSerialize, SerdeDeserialize)] +pub struct SymbolCache { + symbol_addresses: HashMap, + module_name: String, +} + +impl SymbolCache { + /// Creates a new `SymbolCache` instance. + /// + /// # Arguments + /// * `pdb_path` - The path to the PDB file. + /// * `module_name` - The name of the module to get the base address of. + #[cfg(target_os = "windows")] + pub fn new(pdb_path: impl AsRef, module_name: impl AsRef) -> Result { + use anyhow::Context; + + let file = File::open(&pdb_path).with_context(|| format!("Failed to open factorio.pdb file at path {}. Does this file actually exist? If not, reinstall factorio.", pdb_path.as_ref().display()))?; + let mut pdb = PDB::open(file)?; + + let mut symbol_addresses = HashMap::new(); + let symbol_table = pdb.global_symbols()?; + let address_map = pdb.address_map()?; + + symbol_table + .iter() + .for_each(|symbol| match symbol.parse() { + Ok(pdb::SymbolData::Public(data)) if data.function => { + let rva = data.offset.to_rva(&address_map).unwrap_or_default(); + symbol_addresses.insert(data.name.to_string().into(), rva.0); + Ok(()) + } + Err(e) => Err(e), + _ => Ok(()), + })?; + + Ok(Self { + symbol_addresses, + module_name: module_name.as_ref().to_string(), + }) + } + + #[cfg(target_os = "linux")] + pub fn new(pdb_path: impl AsRef, module_name: &str) -> Result { + todo!(); + } + + pub fn get_function_address(&self, base_address: u64, mangled_name: &str) -> Option { + self.symbol_addresses + .get(mangled_name) + .copied() + .map(|x| base_address + u64::from(x)) + } + + #[cfg(target_os = "windows")] + pub fn get_module_base_address(&self) -> Result { + let module_name = self.module_name.clone(); + let result = unsafe { GetModuleHandleA(CString::new(module_name)?.as_pcstr()) }; + match result { + Ok(handle) => Ok(handle.0 as u64), + Err(err) => bail!(err), + } + } + + #[cfg(target_os = "linux")] + fn get_module_base_address(module_name: &str) -> Result { + todo!(); + } + + /// Injects a detour into a Factorio compiled function. + /// + /// # Arguments + /// * `factorio_path` - The path to the Factorio binary directory. + /// * `function_name` - The name of the function to inject the detour into. + /// * `hook` - The detour function to inject. + /// + /// # Safety + /// todo! + pub unsafe fn inject(&self, base_address: u64, hook: &RivetsHook) -> Result<()> { + let Some(address) = self.get_function_address(base_address, hook.mangled_name.as_str()) else { + bail!( + "Failed to find address for the following mangled function inside the PDB: {}", + hook.mangled_name + ); + }; + + Ok((hook.hook)(address)?) + } } diff --git a/src/lib.rs b/src/lib.rs index d5907f1..da6d89b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,5 +9,5 @@ pub use rivets_macros::*; extern crate rivets_shared; pub use rivets_shared::*; -pub use abi_stable; +pub use dll_syringe; pub use retour;