diff --git a/Cargo.lock b/Cargo.lock index 7b1d6e3..9856663 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,21 +17,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -47,15 +32,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anstream" version = "0.6.17" @@ -156,21 +132,11 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object 0.36.5", + "object", "rustc-demangle", "windows-targets 0.52.6", ] -[[package]] -name = "better-panic" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa9e1d11a268684cbd90ed36370d7577afb6c62d912ddff5c15fc34343e5036" -dependencies = [ - "backtrace", - "console", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -183,18 +149,6 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "block-buffer" version = "0.9.0" @@ -245,21 +199,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_lex 0.2.4", - "indexmap", - "strsim 0.10.0", - "termcolor", - "textwrap", -] - [[package]] name = "clap" version = "4.5.20" @@ -267,7 +206,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", - "clap_derive", ] [[package]] @@ -283,29 +221,8 @@ checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.2", - "strsim 0.11.1", -] - -[[package]] -name = "clap_derive" -version = "4.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.85", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", + "clap_lex", + "strsim", ] [[package]] @@ -314,33 +231,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "console" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" -dependencies = [ - "encode_unicode", - "libc", - "once_cell", - "windows-sys", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -366,15 +262,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - [[package]] name = "crossbeam" version = "0.8.4" @@ -455,12 +342,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - [[package]] name = "exe" version = "0.5.6" @@ -479,31 +360,6 @@ dependencies = [ "widestring", ] -[[package]] -name = "fern" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" -dependencies = [ - "log", -] - -[[package]] -name = "flate2" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "generic-array" version = "0.14.7" @@ -520,17 +376,6 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" -[[package]] -name = "goblin" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" -dependencies = [ - "log", - "plain", - "scroll 0.11.0", -] - [[package]] name = "goblin" version = "0.9.2" @@ -539,21 +384,9 @@ checksum = "53ab3f32d1d77146981dea5d6b1e8fe31eedcb7013e5e00d6ccd1259a4b4d923" dependencies = [ "log", "plain", - "scroll 0.12.0", + "scroll", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -592,25 +425,6 @@ dependencies = [ "cc", ] -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "inflate" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" -dependencies = [ - "adler32", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -632,57 +446,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lancelot" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c881da4146200b58efe507a51803ce5b643059c7154413e9645302b6a84b8c" -dependencies = [ - "ansi_term", - "anyhow", - "bitflags 1.3.2", - "bitvec", - "byteorder", - "goblin 0.6.1", - "lancelot-flirt", - "lazy_static", - "log", - "object 0.30.4", - "regex", - "smallvec", - "smol_str", - "thiserror", - "widestring", - "zydis", -] - -[[package]] -name = "lancelot-flirt" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030dc77778d64330bf958fb0913b56ecb2b98bf54c8c971ba67f6e85e404f4b9" -dependencies = [ - "anyhow", - "better-panic", - "bitflags 1.3.2", - "bitvec", - "chrono", - "clap 3.2.25", - "fern", - "inflate", - "log", - "nom", - "regex", - "smallvec", - "thiserror", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.161" @@ -737,12 +500,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f2dd5c7f8aaf48a76e389068ab25ed80bdbc226b887f9013844c415698c9952" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -806,16 +563,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -849,16 +596,6 @@ dependencies = [ "malloc_buf", ] -[[package]] -name = "object" -version = "0.30.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" -dependencies = [ - "flate2", - "memchr", -] - [[package]] name = "object" version = "0.36.5" @@ -880,12 +617,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "parking_lot" version = "0.12.3" @@ -960,12 +691,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "raw-window-handle" version = "0.5.2" @@ -981,35 +706,6 @@ dependencies = [ "bitflags 2.6.0", ] -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1028,33 +724,13 @@ 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" -dependencies = [ - "scroll_derive 0.11.1", -] - [[package]] name = "scroll" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" dependencies = [ - "scroll_derive 0.12.0", -] - -[[package]] -name = "scroll_derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.85", + "scroll_derive", ] [[package]] @@ -1149,21 +825,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "smol_str" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" -dependencies = [ - "serde", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -1202,12 +863,6 @@ dependencies = [ "serde_repr", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "termcolor" version = "1.4.1" @@ -1217,32 +872,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" - -[[package]] -name = "thiserror" -version = "1.0.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.85", -] - [[package]] name = "time" version = "0.3.36" @@ -1304,11 +933,10 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" name = "vestal" version = "0.1.0" dependencies = [ - "clap 4.5.20", + "clap", "elf", "exe", - "goblin 0.9.2", - "lancelot", + "goblin", "syscalls", ] @@ -1595,24 +1223,3 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "zydis" -version = "3.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc13daee87922e0d6dc6137327be10327ad1cee0515ec775f898206193aaeb8" -dependencies = [ - "bitflags 1.3.2", - "cmake", - "serde", - "serde_derive", -] diff --git a/crates/vestal/Cargo.toml b/crates/vestal/Cargo.toml index db889e0..4c4cce5 100644 --- a/crates/vestal/Cargo.toml +++ b/crates/vestal/Cargo.toml @@ -6,8 +6,9 @@ edition = "2021" [dependencies] exe = "0.5.6" goblin = "0.9.2" -clap = { version = "4.5.4", features = [ "derive" ] } -lancelot = "0.8.6" +clap = { version = "4.5.4", features = [ "cargo" ] } +#lancelot = "0.8.6 + syscalls = "0.6.18" elf = "0.7.4" #falcon = "0.5.5" diff --git a/crates/vestal/src/execute.rs b/crates/vestal/src/execute.rs index c14a8c9..97d604d 100644 --- a/crates/vestal/src/execute.rs +++ b/crates/vestal/src/execute.rs @@ -5,27 +5,35 @@ use std::ffi::CString; use std::str::FromStr; static NAME: &'static [u8] = &[b'\0']; impl Vestal { - pub fn execute_data (&self, data: &[u8]) -> Usually<()> { + pub fn execute_path (&self, path: impl AsRef) -> Usually<()> { + self.inspect_path(path)?; + //let mut not_found = vec![]; + //for (dll, imports) in deps.iter() { + //if let Some(dll) = find_dll(dll)? { + //Self::from_data_dll(dll, |dll_buffer, dll_pe, dll_imports, dll_deps|{ + //Ok(()) + //}); + //for import in imports.iter() { + //println!(" {:8} + {:8} {:32}", import.rva, import.offset, import.name); + //} + //} else { + //println!("- {dll} NOT FOUND"); + //not_found.push(dll); + //} + //} + // TODO: call(main, AEffect::host_callback) Ok(()) } - pub fn execute_path (&self, path: impl AsRef) -> Usually<()> { - Self::from_path(&path, |buffer, pe, main, deps|{ - if let Some(main) = main { - println!("VSTPluginMain: {:?} + {:?}", &main.rva, &main.offset); - } else { - panic!("VSTPluginMain not found. This is not a valid VST plugin."); - } - println!("Imports: {:#?}", &pe.imports.len()); - println!("Dependencies: {:#?}", &deps.len()); - for (dll, imports) in deps.iter() { - println!("- {dll}"); - for import in imports.iter() { - println!(" {:8} + {:8} {:32}", import.rva, import.offset, import.name); - } - } - }) - } } + +fn find_dll (dll: &str) -> Usually>> { + let dll = dll.to_lowercase(); + let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", dll); + let buffer = std::fs::read::(path.clone())?; + println!(" Found: {path} {}b", buffer.len()); + Ok(Some(buffer)) +} + fn make_elf () -> Vec { let mut buffer = vec![0;1024*1024*1024]; // https://wiki.osdev.org/ELF#ELF_Header diff --git a/crates/vestal/src/inspect.rs b/crates/vestal/src/inspect.rs index d7e35d9..4b0855a 100644 --- a/crates/vestal/src/inspect.rs +++ b/crates/vestal/src/inspect.rs @@ -1,23 +1,32 @@ use crate::*; impl Vestal { - pub fn inspect_data (&self, path: impl AsRef) -> Usually<()> { Ok(()) } - pub fn inspect_path (&self, path: impl AsRef) -> Usually<()> { - Self::from_path(&path, |buffer, pe, main, deps|{ - if let Some(main) = main { - println!("VSTPluginMain: {:?} + {:?}", &main.rva, &main.offset); - } else { - panic!("VSTPluginMain not found. This is not a valid VST plugin."); - } - println!("Imports: {:#?}", &pe.imports.len()); - println!("Dependencies: {:#?}", &deps.len()); - for (dll, imports) in deps.iter() { - println!("- {dll}"); - for import in imports.iter() { - println!(" {:8} + {:8} {:32}", import.rva, import.offset, import.name); - } - } - }) + pub fn inspect_path (&self, path: impl AsRef) -> Usually { + let pe = crate::parse::Dll::from_path(path)?; + let pe = pe.with_entrypoint("VSTPluginMain")?; + let main = pe.entrypoint.as_ref().unwrap(); + println!("VSTPluginMain: {:?} + {:?}", &main.rva, &main.offset); + let deps = &pe.imports; + // TODO: load Wine libs + println!("Imports: {:#?}", deps.len()); + Ok((pe, buf)) + //Self::from_path(&path, |buffer, pe, main, deps|{ + + //if let Some(main) = main { + //println!("VSTPluginMain: {:?} + {:?}", &main.rva, &main.offset); + //} else { + //panic!("VSTPluginMain not found. This is not a valid VST plugin."); + //} + //println!("Imports: {:#?}", &pe.imports.len()); + //println!("Dependencies: {:#?}", &deps.len()); + //for (dll, imports) in deps.iter() { + //println!("- {dll}"); + //for import in imports.iter() { + //println!(" {:8} + {:8} {:32}", import.rva, import.offset, import.name); + //} + //} + //Ok(()) + //}) //let image = VecPE::from_disk_file(path)?; //let import_directory = ImportDirectory::parse(&image)?; //for descriptor in import_directory.descriptors { diff --git a/crates/vestal/src/main.rs b/crates/vestal/src/main.rs index 128779f..78e75c0 100644 --- a/crates/vestal/src/main.rs +++ b/crates/vestal/src/main.rs @@ -1,76 +1,172 @@ -mod execute; -mod inspect; +//mod execute; +//mod inspect; mod memrun; -mod parse; -pub(crate) use std::path::Path; +//mod parse; +mod vst; +pub(crate) use std::error::Error; +pub(crate) use std::path::{Path, PathBuf}; +pub(crate) use std::collections::HashMap; +pub(crate) use std::fs::{read, canonicalize}; pub(crate) use goblin::{error, Object, pe::{PE, import::Import, export::Export}}; -use std::collections::HashMap; -use clap::Parser; +use clap::{arg, command, value_parser, ArgAction, Command}; type Usually = Result>; +type Sources = HashMap>; +type Context = HashMap; + +#[derive(Clone)] +struct Dll { + name: String, + path: PathBuf, + data: Vec, +} +impl Dll { + fn pe (&self) -> Usually { + read_pe(slice_shebang(&self.data)) + } +} + fn main () -> Usually<()> { - Vestal::parse().run() + let matches = command!() + .arg(arg!([path] "Path to VST DLL").value_parser(value_parser!(PathBuf))) + .arg(arg!(-i --inspect "Show info, don't run").required(false)) + //.arg(arg!(-s --stub "Provide stub import").required(false)) + .get_matches(); + if let Some(path) = matches.get_one::("path") { + let mut context: Context = HashMap::new(); + read_dll(&mut context, "vestal", &canonicalize(&path)?)?; + Ok(()) + } else { + panic!("Pass a path to a VST DLL.") + } } -#[derive(Debug, Parser)] -#[command(version, about, long_about = None)] -pub enum Vestal { - /// Inspect a DLL - Inspect { path: String }, - /// Load a VST DLL into memory - Execute { path: String }, - /// Load a VST DLL from hashbang - Loader { path: String } +fn read_dll (context: &mut Context, name: &str, path: &PathBuf) -> Usually<()> { + let name = canonical_name(&name); + if context.contains_key(&name) { + return Ok(()) + } + println!("\n(:= \"{}\" {:?})", name, path); + let dll = Dll { name: name.to_string(), data: read(path)?, path: path.into(), }; + println!("(:= \"{}\" {:p}+{})", name, &dll.data, dll.data.len()); + let mut imports = vec![]; + for export in dll.pe()?.exports.iter() { + //println!(" - {:8} + {:?} = {:?}", &export.rva, &export.offset, &export.name); + } + for import in dll.pe()?.imports.iter() { + imports.push(import.dll.to_lowercase()); + } + context.insert(name.to_string(), dll); + for name in imports.iter() { + let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", name); + read_dll(context, name, &PathBuf::from(path))?; + } + Ok(()) } -pub enum Arch { - ThirtyTwo, - SixtyFour, +fn canonical_name (path: impl AsRef) -> String { + path.as_ref().to_path_buf().into_os_string().into_string() + .expect("failed to convert path") + .to_lowercase() } -impl Vestal { - pub fn run (&self) -> Usually<()> { - match self { - Self::Inspect { path } => self.inspect_path(path.as_str()), - Self::Execute { path } => self.execute_path(path.as_str()), - Self::Loader { path } => self.execute_path(path.as_str()), +fn slice_shebang (buffer: &[u8]) -> &[u8] { + let mut index = 2; + let mut slice = false; + if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { + while let Some(c) = buffer.get(index) { + if *c == 0x0a { + slice = true; + break + } + index += 1; } } - pub fn with_path ( - path: &impl AsRef, - cb: impl Fn(&[u8], &PE, Option<&Export>, HashMap>) - ) -> Usually<()> { - println!("Path: {}", path.as_ref().display()); - let buffer = std::fs::read(path.as_ref())?; - Self::with_data(buffer.as_slice(), cb) - } - pub fn with_data ( - buffer: &[u8], - callback: impl Fn(&[u8], &PE, Option<&Export>, HashMap>) - ) -> Usually<()> { - println!("PE: {}b", buffer.len()); - if let Object::PE(ref pe) = Object::parse(buffer)? { - let mut main = None; - let mut imports: HashMap<_, _> = Default::default(); - for import in pe.imports.iter() { - let dll = import.dll.clone(); - if !imports.contains_key(dll) { - imports.insert(dll.to_string(), vec![]); - } - imports.get_mut(dll).unwrap().push(import); - } - for export in pe.exports.iter() { - if let Some("VSTPluginMain") = export.name { - println!("VSTPluginMain: {:?} + {:?}", &export.rva, &export.offset); - main = Some(export); - break - } - } - callback(&buffer, pe, main, imports); - Ok(()) - } else { - Err("not a PE".into()) - } + if slice { + println!("Slice: {index}"); + &buffer[index+1..] + } else { + buffer } } + +fn read_pe (buffer: &[u8]) -> Usually { + if let Object::PE(pe) = Object::parse(buffer)? { + Ok(pe) + } else { + panic!("not a PE") + } +} + +fn find_main <'a> (pe: &'a PE<'a>) -> &'a Export<'a> { + for export in pe.exports.iter() { + if let Some("VSTPluginMain") = export.name { + println!("VSTPluginMain found: {:?} + {:?}", export.rva, export.offset); + return export + } + } + panic!("no VSTPluginMain") +} + +fn resolve_imports ( + sources: &mut Sources, + context: &mut Context, +) -> Usually { + let mut updated: Context = Default::default(); + for (name, dll) in context.iter() { + //if let Some(dll) = dll { + //let imports = &dll.pe.imports; + //for import in dll.pe.imports.iter() { + //let dep = import.dll.to_lowercase(); + //if context.get(&dep).is_none() { + //updated.insert(dep, None); + //} + //} + //} else { + //let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", name); + //let data = read(&path)?; + //updated.insert(name.clone(), Some(Dll { + //name: name.clone(), + //path: path.into(), + //data: data.clone(), + //pe: read_pe(data.as_slice())? + //})); + //} + } + let count = updated.len(); + for (name, library) in updated.into_iter() { + context.insert(name, library); + } + Ok(count) +} + +fn find_dll (dll: &str) -> Option { + Some(format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", dll)) +} + +//#[derive(Debug, Parser)] +//#[command(version, about, long_about = None)] +//pub struct Vestal { + ///// Inspect a DLL + //Inspect { path: String }, + ///// Load a VST DLL into memory + //Execute { path: String }, + ///// Load a VST DLL from hashbang + //Loader { path: String } +//} + +//pub enum Arch { + //ThirtyTwo, + //SixtyFour, +//} + +//impl Vestal { + //pub fn run (&self) -> Usually<()> { + //match self { + //Self::Inspect { path } => { self.inspect_path(path.as_str())?; Ok(()) }, + //Self::Execute { path } => self.execute_path(path.as_str()), + //Self::Loader { path } => self.execute_path(path.as_str()), + //} + //} +//} diff --git a/crates/vestal/src/parse.rs b/crates/vestal/src/parse.rs index 7345702..db6c739 100644 --- a/crates/vestal/src/parse.rs +++ b/crates/vestal/src/parse.rs @@ -1,35 +1,25 @@ use crate::*; -impl Vestal { - pub fn from_path ( - path: &impl AsRef, - cb: impl Fn(&[u8], &PE, Option<&Export>, HashMap>) - ) -> Usually<()> { - println!("Path: {}", path.as_ref().display()); - let buffer = std::fs::read(path.as_ref())?; - Self::from_data(buffer.as_slice(), cb) +pub struct Dll<'a> { + pub buffer: Vec, + pub pe: PE<'a>, + pub entrypoint: Option<&'a Export<'a>>, + pub exports: Vec<&'a Export<'a>>, + pub imports: HashMap>>, +} + +#[derive(Debug)] +pub enum DllError { + NotPE, + NoEntry(String) +} + +impl<'a> Dll<'a> { + pub fn from_path (path: impl AsRef) -> Usually { + Self::from_buffer(std::fs::read(path.as_ref())?) } - - pub fn from_data ( - mut buffer: &[u8], - callback: impl Fn(&[u8], &PE, Option<&Export>, HashMap>) - ) -> Usually<()> { - println!("PE: {}b", buffer.len()); - let mut index = 2; - let mut slice = false; - if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { - while let Some(c) = buffer.get(index) { - if *c == 0x0a { - slice = true; - break - } - index += 1; - } - } - println!("Slice: {slice} {index}"); - let buffer = if slice { &buffer[index+1..] } else { buffer }; - if let Object::PE(ref pe) = Object::parse(buffer)? { - let mut main = None; + pub fn from_buffer (buffer: Vec) -> Usually { + if let Object::PE(pe) = Object::parse(buffer.as_slice())? { let mut imports: HashMap<_, _> = Default::default(); for import in pe.imports.iter() { let dll = import.dll.clone(); @@ -38,17 +28,133 @@ impl Vestal { } imports.get_mut(dll).unwrap().push(import); } + let mut exports: Vec<_> = Default::default(); for export in pe.exports.iter() { - if let Some("VSTPluginMain") = export.name { - main = Some(export); - break - } + exports.push(export) } - callback(&buffer, pe, main, imports); - Ok(()) + Ok(Self { buffer, pe, imports, exports, entrypoint: None }) } else { - Err("not a PE".into()) + Err("not a pe".into()) } } - + pub fn with_entrypoint (self, name: &str) -> Usually { + for export in self.exports.iter() { + if let Some(name) = export.name { + self.entrypoint = Some(export); + return Ok(self) + } + } + return Err(format!("no entrypoint \"{name}\"").into()) + } } + +fn slice_shebang (buffer: Vec) -> Vec { + let mut index = 2; + let mut slice = false; + if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { + while let Some(c) = buffer.get(index) { + if *c == 0x0a { + slice = true; + break + } + index += 1; + } + } + println!("Slice: {slice} {index}"); + if slice { buffer[index+1..].to_vec() } else { buffer } +} + +//impl Vestal { + + //pub fn from_path ( + //path: &impl AsRef, + //cb: impl Fn(&[u8], &PE, Option<&Export>, HashMap>)->Usually<()> + //) -> Usually<()> { + //println!("Path: {}", path.as_ref().display()); + //let buffer = std::fs::read(path.as_ref())?; + //Self::from_data(buffer.as_slice(), cb) + //} + + //pub fn from_data_dll ( + //mut buffer: &[u8], + //callback: impl Fn(&[u8], &PE, Option<&Export>, HashMap>)->Usually<()> + //) -> Usually<()> { + //println!("PE: {}b", buffer.len()); + //let mut index = 2; + //let mut slice = false; + //if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { + //while let Some(c) = buffer.get(index) { + //if *c == 0x0a { + //slice = true; + //break + //} + //index += 1; + //} + //} + //println!("Slice: {slice} {index}"); + //let buffer = if slice { &buffer[index+1..] } else { buffer }; + //if let Object::PE(ref pe) = Object::parse(buffer)? { + //let mut main = None; + //let mut imports: HashMap<_, _> = Default::default(); + //for import in pe.imports.iter() { + //let dll = import.dll.clone(); + //if !imports.contains_key(dll) { + //imports.insert(dll.to_string(), vec![]); + //} + //imports.get_mut(dll).unwrap().push(import); + //} + //for export in pe.exports.iter() { + //if let Some("VSTPluginMain") = export.name { + //main = Some(export); + //break + //} + //} + //callback(&buffer, pe, main, imports); + //Ok(()) + //} else { + //Err("not a PE".into()) + //} + //} + + //pub fn from_data ( + //mut buffer: &[u8], + //callback: impl Fn(&[u8], &PE, Option<&Export>, HashMap>)->Usually<()> + //) -> Usually<()> { + //println!("PE: {}b", buffer.len()); + //let mut index = 2; + //let mut slice = false; + //if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') { + //while let Some(c) = buffer.get(index) { + //if *c == 0x0a { + //slice = true; + //break + //} + //index += 1; + //} + //} + //println!("Slice: {slice} {index}"); + //let buffer = if slice { &buffer[index+1..] } else { buffer }; + //if let Object::PE(ref pe) = Object::parse(buffer)? { + //let mut main = None; + //let mut imports: HashMap<_, _> = Default::default(); + //for import in pe.imports.iter() { + //let dll = import.dll.clone(); + //if !imports.contains_key(dll) { + //imports.insert(dll.to_string(), vec![]); + //} + //imports.get_mut(dll).unwrap().push(import); + //} + //for export in pe.exports.iter() { + //if let Some("VSTPluginMain") = export.name { + //main = Some(export); + //break + //} + //} + //callback(&buffer, pe, main, imports); + //Ok(()) + //} else { + //Err("not a PE".into()) + //} + //} + +//} diff --git a/crates/vestal/src/vst.rs b/crates/vestal/src/vst.rs new file mode 100644 index 0000000..0149be0 --- /dev/null +++ b/crates/vestal/src/vst.rs @@ -0,0 +1,84 @@ +use std::ffi::c_void; +//typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); +#[repr(C)] pub struct AEffect { + magic: [u8; 4], + /// ```c + /// typedef VstIntPtr (VSTCALLBACK *AEffectDispatcherProc) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); + /// ``` + dispatcher: fn(*const AEffect, i32, i32, i32, *mut c_void, f32) -> usize, + /// ```c + /// typedef void (VSTCALLBACK *AEffectProcessProc) (AEffect* effect, float** inputs, float** outputs, VstInt32 sampleFrames); + /// typedef void (VSTCALLBACK *AEffectProcessDoubleProc) (AEffect* effect, double** inputs, double** outputs, VstInt32 sampleFrames); + /// ``` + process: usize, + /// ```c + /// typedef void (VSTCALLBACK *AEffectSetParameterProc) (AEffect* effect, VstInt32 index, float parameter); + /// ``` + set_parameter: usize, + /// ```c + /// typedef float (VSTCALLBACK *AEffectGetParameterProc) (AEffect* effect, VstInt32 index); + /// ``` + get_parameter: usize, + num_programs: i32, + num_params: i32, + num_inputs: i32, + num_outputs: i32, + flags: i32, + resvd1: usize, + resvd2: usize, + initial_delay: i32, + real_qualities: i32, + off_qualities: i32, + io_ratio: f32, + object: usize, + user: usize, + unique_id: i32, + version: i32, + process_replacing: usize, + process_double_replacing: usize, + _future: [u8;56], +} +impl AEffect { + fn null_dispatcher (_: *const AEffect, _: i32, _: i32, _: i32, _: *mut c_void, _: f32) -> usize { + 0 + } + fn host_callback ( + _: *const AEffect, opcode: i32, index: i32, value: i32, ptr: *mut c_void, opt: f32 + ) -> usize { + 0 + } + pub fn run (address: usize) -> Self { + let effect = Self::default(); + // call(address, host_callback) + effect + } +} +impl Default for AEffect { + fn default () -> Self { + Self { + magic: [ b'V', b's', b't', b'P'], + dispatcher: Self::null_dispatcher, + process: 0, + set_parameter: 0, + get_parameter: 0, + num_programs: 0, + num_params: 0, + num_inputs: 0, + num_outputs: 0, + flags: 0, + resvd1: 0, + resvd2: 0, + initial_delay: 0, + real_qualities: 0, + off_qualities: 0, + io_ratio: 0.0, + object: 0, + user: 0, + unique_id: 0, + version: 0, + process_replacing: 0, + process_double_replacing: 0, + _future: [0;56], + } + } +}