Add some utility stuff
This commit is contained in:
parent
9ae3c1a18c
commit
36dc7fe6ea
|
@ -150,6 +150,16 @@ dependencies = [
|
|||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41fdbd1df62156fbc5945f4762632564d7d038153091c3fcf1067f6aef7cff92"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.29"
|
||||
|
@ -181,10 +191,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "skidscan"
|
||||
version = "0.1.1"
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89c52ddc5d6dde2bbb702e353d78c059cbbe07f15189ead0b7ac7da49b44bacc"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
|
||||
[[package]]
|
||||
name = "skidscan"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ddb509ef676cf26d1eac42416142360a15862275770dfada57e9b150244912"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"skidscan-macros",
|
||||
|
@ -193,10 +209,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "skidscan-macros"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c98a622ae309bfbfe69e99bbf9e8ce23efc15817eda4bda1369bbb3eea668f83"
|
||||
checksum = "881ef2150f0e4e2a855bb661a3ecd621ab1b6aa07b34aef941d1bd37b4267e8d"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
@ -217,6 +234,35 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.14.0"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#[macro_export]
|
||||
/// Common pattern for detouring.
|
||||
macro_rules! __vtable_offset {
|
||||
($name:ident = {
|
||||
win64: $win64:literal,
|
||||
|
@ -22,7 +23,8 @@ macro_rules! __vtable_offset {
|
|||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! __vtable_func {
|
||||
/// Common pattern for detouring.
|
||||
macro_rules! __gmod_func {
|
||||
($ty:ident = extern fn($($ident:ident: $arg:ty),*) $(-> $rtn:ty)?) => {
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type $ty = extern "fastcall" fn($($ident: $arg),*) $(-> $rtn)?;
|
||||
|
@ -36,6 +38,7 @@ macro_rules! __vtable_func {
|
|||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Common pattern for detouring.
|
||||
macro_rules! __hook_func {
|
||||
($ty:ident = extern fn $fn:ident($($ident:ident: $arg:ty),*) $(-> $rtn:ty)? $code:block) => {
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
|
@ -56,4 +59,50 @@ macro_rules! __hook_func {
|
|||
#[cfg(all(target_os = "linux", target_pointer_width = "32"))]
|
||||
extern "C" fn $fn($($ident: $arg),*) $(-> $rtn)? $code
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Common pattern for detouring.
|
||||
macro_rules! find_gmod_signature {
|
||||
(($library:ident, $library_path:ident), @EXPORT = $export:literal) => {
|
||||
$library.get($export).ok().map(|func: Symbol<'static, _>| *func)
|
||||
};
|
||||
|
||||
(($library:ident, $library_path:ident), @SIG = $sig:literal) => {
|
||||
$crate::sigscan::signature!($sig).scan_module($library_path).ok().map(|x| std::mem::transmute(x))
|
||||
};
|
||||
|
||||
(($library:ident, $library_path:ident) -> {
|
||||
win64_x86_64: [$($win64_x86_64:tt)+],
|
||||
win32_x86_64: [$($win32_x86_64:tt)+],
|
||||
|
||||
linux64_x86_64: [$($linux64_x86_64:tt)+],
|
||||
linux32_x86_64: [$($linux32_x86_64:tt)+],
|
||||
|
||||
win32: [$($win32:tt)+],
|
||||
linux32: [$($linux32:tt)+],
|
||||
}) => {{
|
||||
let x86_64 = $crate::is_x86_64();
|
||||
if x86_64 {
|
||||
#[cfg(all(target_os = "windows", target_pointer_width = "64"))] {
|
||||
$crate::find_gmod_signature!(($library, $library_path), $($win64_x86_64)+)
|
||||
}
|
||||
#[cfg(all(target_os = "windows", target_pointer_width = "32"))] {
|
||||
$crate::find_gmod_signature!(($library, $library_path), $($win32_x86_64)+)
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_pointer_width = "64"))] {
|
||||
$crate::find_gmod_signature!(($library, $library_path), $($linux64_x86_64)+)
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_pointer_width = "32"))] {
|
||||
$crate::find_gmod_signature!(($library, $library_path), $($linux32_x86_64)+)
|
||||
}
|
||||
} else {
|
||||
#[cfg(target_os = "windows")] {
|
||||
$crate::find_gmod_signature!(($library, $library_path), $($win32)+)
|
||||
}
|
||||
#[cfg(target_os = "linux")] {
|
||||
$crate::find_gmod_signature!(($library, $library_path), $($linux32)+)
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
102
gmod/src/lib.rs
102
gmod/src/lib.rs
|
@ -14,4 +14,104 @@ pub mod lua;
|
|||
pub mod msgc;
|
||||
|
||||
/// Advanced dark magic utilities
|
||||
pub mod hax;
|
||||
pub mod hax;
|
||||
|
||||
/// Returns whether this client is running the x86-64 branch
|
||||
///
|
||||
/// Current implementation checks the LuaJIT version exported by lua_shared
|
||||
pub fn is_x86_64() -> bool {
|
||||
lua::LUA_SHARED.x86_64
|
||||
}
|
||||
|
||||
/// Opens & returns a shared library loaded by Garry's Mod using the raw path to the module.
|
||||
///
|
||||
/// # Example
|
||||
/// ```no_run
|
||||
/// // This would only work on Windows x86-64 branch in 64-bit mode
|
||||
/// let (engine, engine_path): (gmod::libloading::Library, &'static str) = open_library_srv!("bin/win64/engine.dll").expect("Failed to open engine.dll!");
|
||||
/// println!("Opened engine.dll from: {}", engine_path);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! open_library_raw {
|
||||
($($path:literal),+) => {
|
||||
::gmod::libloading::Library::new(concat!($($path),+)).map(|lib| (lib, concat!($($path),+)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Opens & returns a shared library loaded by Garry's Mod, in "server mode" (will prioritize _srv.so on Linux main branch)
|
||||
///
|
||||
/// Respects 32-bit/64-bit main/x86-64 branches and finds the correct library.
|
||||
///
|
||||
/// # Example
|
||||
/// ```no_run
|
||||
/// let (engine, engine_path): (gmod::libloading::Library, &'static str) = open_library_srv!("engine").expect("Failed to open engine.dll!");
|
||||
/// println!("Opened engine.dll from: {}", engine_path);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! open_library_srv {
|
||||
($name:literal) => {{
|
||||
#[cfg(not(all(any(target_os = "windows", target_os = "linux"), any(target_pointer_width = "32", target_pointer_width = "64"))))] {
|
||||
compile_error!("Unsupported platform");
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "windows", target_pointer_width = "64"))] {
|
||||
::gmod::open_library_raw!("bin/win64/", $name, ".dll")
|
||||
}
|
||||
#[cfg(all(target_os = "windows", target_pointer_width = "32"))] {
|
||||
::gmod::open_library_raw!("bin/", $name, ".dll")
|
||||
.or_else(|_| ::gmod::open_library_raw!("garrysmod/bin/", $name, ".dll"))
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", target_pointer_width = "64"))] {
|
||||
::gmod::open_library_raw!("bin/linux64/", $name, ".so")
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/linux64/lib", $name, ".so"))
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_pointer_width = "32"))] {
|
||||
::gmod::open_library_raw!("bin/linux32/", $name, ".so")
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/linux32/lib", $name, ".so"))
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/", $name, "_srv.so"))
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/lib", $name, "_srv.so"))
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/", $name, ".so"))
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/lib", $name, ".so"))
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// Opens & returns a shared library loaded by Garry's Mod. You are most likely looking for `open_library_srv!`, as this will prioritize non-_srv.so libraries on Linux main branch.
|
||||
///
|
||||
/// Respects 32-bit/64-bit main/x86-64 branches and finds the correct library.
|
||||
///
|
||||
/// # Example
|
||||
/// ```no_run
|
||||
/// let (engine, engine_path): (gmod::libloading::Library, &'static str) = open_library!("engine").expect("Failed to open engine.dll!");
|
||||
/// println!("Opened engine.dll from: {}", engine_path);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! open_library {
|
||||
($name:literal) => {{
|
||||
#[cfg(not(all(any(target_os = "windows", target_os = "linux"), any(target_pointer_width = "32", target_pointer_width = "64"))))] {
|
||||
compile_error!("Unsupported platform");
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "windows", target_pointer_width = "64"))] {
|
||||
::gmod::open_library_raw!("bin/win64/", $name, ".dll")
|
||||
}
|
||||
#[cfg(all(target_os = "windows", target_pointer_width = "32"))] {
|
||||
::gmod::open_library_raw!("bin/", $name, ".dll")
|
||||
.or_else(|_| ::gmod::open_library_raw!("garrysmod/bin/", $name, ".dll"))
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", target_pointer_width = "64"))] {
|
||||
::gmod::open_library_raw!("bin/linux64/", $name, ".so")
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/linux64/lib", $name, ".so"))
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_pointer_width = "32"))] {
|
||||
::gmod::open_library_raw!("bin/linux32/", $name, ".so")
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/linux32/lib", $name, ".so"))
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/", $name, ".so"))
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/lib", $name, ".so"))
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/", $name, "_srv.so"))
|
||||
.or_else(|_| ::gmod::open_library_raw!("bin/lib", $name, "_srv.so"))
|
||||
}
|
||||
}};
|
||||
}
|
|
@ -69,10 +69,12 @@ impl LuaError {
|
|||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub(super) static ref LUA_SHARED: LuaShared = LuaShared::import();
|
||||
pub(crate) static ref LUA_SHARED: LuaShared = LuaShared::import();
|
||||
}
|
||||
|
||||
pub(super) struct LuaShared {
|
||||
pub(crate) struct LuaShared {
|
||||
pub x86_64: bool,
|
||||
|
||||
pub lual_loadfile: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState, path: LuaString) -> i32>,
|
||||
pub lual_loadstring: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState, path: LuaString) -> i32>,
|
||||
pub lua_getfield: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState, index: i32, k: LuaString)>,
|
||||
|
@ -132,6 +134,8 @@ impl LuaShared {
|
|||
}
|
||||
|
||||
Self {
|
||||
x86_64: library.get::<unsafe extern "C-unwind" fn()>(b"luaJIT_version_2_1_0_beta3\0").is_ok(),
|
||||
|
||||
lual_loadfile: find_symbol!("luaL_loadfile"),
|
||||
lual_loadstring: find_symbol!("luaL_loadstring"),
|
||||
lua_getfield: find_symbol!("lua_getfield"),
|
||||
|
|
Loading…
Reference in New Issue