reduce number of modules

This commit is contained in:
🪞👃🪞 2025-02-19 20:53:51 +02:00
parent 1be712eeab
commit 50e271e71b
9 changed files with 550 additions and 622 deletions

450
Cargo.lock generated
View file

@ -17,6 +17,21 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 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]] [[package]]
name = "android-tzdata" name = "android-tzdata"
version = "0.1.1" version = "0.1.1"
@ -32,6 +47,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.17" version = "0.6.17"
@ -137,6 +161,16 @@ dependencies = [
"windows-targets 0.52.6", "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]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -149,6 +183,18 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 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]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.9.0" version = "0.9.0"
@ -158,6 +204,15 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "borsh"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc"
dependencies = [
"cfg_aliases",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.16.0" version = "3.16.0"
@ -170,6 +225,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.31" version = "1.1.31"
@ -185,6 +246,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.38" version = "0.4.38"
@ -199,6 +266,21 @@ dependencies = [
"windows-targets 0.52.6", "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]] [[package]]
name = "clap" name = "clap"
version = "4.5.20" version = "4.5.20"
@ -221,8 +303,17 @@ checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
"clap_lex", "clap_lex 0.7.2",
"strsim", "strsim 0.11.1",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
] ]
[[package]] [[package]]
@ -231,12 +322,33 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "cmake"
version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.3" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 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]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.4" version = "0.9.4"
@ -262,6 +374,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "crossbeam" name = "crossbeam"
version = "0.8.4" version = "0.8.4"
@ -336,12 +457,24 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]] [[package]]
name = "elf" name = "elf"
version = "0.7.4" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b"
[[package]]
name = "encode_unicode"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
[[package]] [[package]]
name = "exe" name = "exe"
version = "0.5.6" version = "0.5.6"
@ -360,6 +493,31 @@ dependencies = [
"widestring", "widestring",
] ]
[[package]]
name = "fern"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29"
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]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.7" version = "0.14.7"
@ -378,15 +536,21 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]] [[package]]
name = "goblin" name = "goblin"
version = "0.9.2" version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53ab3f32d1d77146981dea5d6b1e8fe31eedcb7013e5e00d6ccd1259a4b4d923" checksum = "daa0a64d21a7eb230583b4c5f4e23b7e4e57974f96620f42a7e75e08ae66d745"
dependencies = [ dependencies = [
"log", "log",
"plain", "plain",
"scroll", "scroll",
] ]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@ -425,12 +589,40 @@ dependencies = [
"cc", "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]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.1" version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.11" version = "1.0.11"
@ -446,6 +638,59 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "lancelot"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f6aefdab78ed7ff3bf239487d76a63483a2ac01ca99a8c7cf5b091351e656e7"
dependencies = [
"ansi_term",
"anyhow",
"bitflags 1.3.2",
"bitvec",
"byteorder",
"chrono",
"goblin",
"lancelot-flirt",
"lazy_static",
"log",
"object",
"prost",
"regex",
"smallvec",
"smol_str",
"thiserror",
"widestring",
"zydis",
]
[[package]]
name = "lancelot-flirt"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a10286b78d281dba7c2534da6c5ef13668e594c62e83495233c858f1877b912a"
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]] [[package]]
name = "libc" name = "libc"
version = "0.2.161" version = "0.2.161"
@ -500,6 +745,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f2dd5c7f8aaf48a76e389068ab25ed80bdbc226b887f9013844c415698c9952" checksum = "6f2dd5c7f8aaf48a76e389068ab25ed80bdbc226b887f9013844c415698c9952"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.8.0" version = "0.8.0"
@ -563,6 +814,16 @@ dependencies = [
"syn 1.0.109", "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]] [[package]]
name = "num-conv" name = "num-conv"
version = "0.1.0" version = "0.1.0"
@ -602,7 +863,9 @@ version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
dependencies = [ dependencies = [
"flate2",
"memchr", "memchr",
"ruzstd",
] ]
[[package]] [[package]]
@ -617,6 +880,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "os_str_bytes"
version = "6.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.3" version = "0.12.3"
@ -675,13 +944,36 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.89" version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "prost"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
dependencies = [
"bytes",
"prost-derive",
]
[[package]]
name = "prost-derive"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
"syn 2.0.98",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.37" version = "1.0.37"
@ -691,6 +983,12 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]] [[package]]
name = "raw-window-handle" name = "raw-window-handle"
version = "0.5.2" version = "0.5.2"
@ -706,12 +1004,50 @@ dependencies = [
"bitflags 2.6.0", "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]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "ruzstd"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f"
dependencies = [
"twox-hash",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.18" version = "1.0.18"
@ -741,7 +1077,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.98",
] ]
[[package]] [[package]]
@ -761,7 +1097,7 @@ checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.98",
] ]
[[package]] [[package]]
@ -784,7 +1120,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.98",
] ]
[[package]] [[package]]
@ -825,6 +1161,28 @@ version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "smol_str"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d"
dependencies = [
"borsh",
"serde",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.1" version = "0.11.1"
@ -844,9 +1202,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.85" version = "2.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -863,6 +1221,12 @@ dependencies = [
"serde_repr", "serde_repr",
] ]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.4.1" version = "1.4.1"
@ -872,6 +1236,32 @@ dependencies = [
"winapi-util", "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 = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.98",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.36" version = "0.3.36"
@ -905,6 +1295,16 @@ dependencies = [
"time-core", "time-core",
] ]
[[package]]
name = "twox-hash"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
dependencies = [
"cfg-if",
"static_assertions",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.17.0" version = "1.17.0"
@ -933,10 +1333,11 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
name = "vestal" name = "vestal"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap 4.5.20",
"elf", "elf",
"exe", "exe",
"goblin", "goblin",
"lancelot",
"syscalls", "syscalls",
] ]
@ -1006,7 +1407,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.98",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1028,7 +1429,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.85", "syn 2.0.98",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1223,3 +1624,24 @@ name = "windows_x86_64_msvc"
version = "0.52.6" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 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",
]

View file

@ -5,10 +5,9 @@ edition = "2021"
[dependencies] [dependencies]
exe = "0.5.6" exe = "0.5.6"
goblin = "0.9.2"
clap = { version = "4.5.4", features = [ "cargo" ] }
#lancelot = "0.8.6
syscalls = "0.6.18"
elf = "0.7.4" elf = "0.7.4"
goblin = "0.9.3"
clap = { version = "4.5.4", features = [ "cargo" ] }
lancelot = "0.9.7"
syscalls = "0.6.18"
#falcon = "0.5.5" #falcon = "0.5.5"

View file

@ -1,3 +1,57 @@
use crate::*;
use exe::pe::{VecPE, PtrPE};
#[derive(Default)]
pub struct PEContext {
dlls: HashMap<String, Dll>,
}
impl PEContext {
pub fn load (&mut self, name: &str, path: &PathBuf) -> Usually<()> {
let name = name.to_lowercase();
if self.dlls.contains_key(&name) {
return Ok(())
}
println!("\n(:= \"{}\" {:?})", name, path);
let dll = Dll::new(name.as_str(), path)?;
println!("(:= \"{}\" {:p}+{})", name, &dll.pe.buf, dll.pe.buf.len());
let mut imports = vec![];
for export in dll.goblin()?.imports.iter() {
//println!(" - {:8} + {:?} = {:?}", &export.rva, &export.offset, &export.name);
}
for import in dll.goblin()?.imports.iter() {
let dll = import.dll.to_lowercase();
println!(" (-> {} {})", &dll, &import.name);
imports.push(dll);
}
self.dlls.insert(name.to_string(), dll);
for name in imports.iter() {
let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", name);
self.load(name, &PathBuf::from(path))?;
}
Ok(())
}
}
struct Dll {
name: String,
path: PathBuf,
bang: Vec<u8>,
pe: PE,
}
impl Dll {
fn new (name: &str, path: &PathBuf) -> Usually<Self> {
let (bang, data) = slice_shebang(read(path)?.as_slice());
let mut pe = PE::from_bytes(data.as_slice())?;
apply_relocations(&mut pe)?;
Ok(Self {
bang,
name: name.to_string(),
path: path.into(),
pe,
})
}
fn goblin (&self) -> Usually<goblin::pe::PE> {
Ok(goblin::pe::PE::parse(self.pe.buf.as_slice())?)
}
}
use std::ffi::c_void; use std::ffi::c_void;
//typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); //typedef VstIntPtr (VSTCALLBACK *audioMasterCallback) (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);
#[repr(C)] pub struct AEffect { #[repr(C)] pub struct AEffect {

View file

@ -1,3 +1,5 @@
use crate::*;
use elf::file::Elf64_Ehdr;
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};
use syscalls::{Sysno, Errno, syscall}; use syscalls::{Sysno, Errno, syscall};
@ -55,3 +57,35 @@ fn run (fd: usize) {
Ok(_) => (), Ok(_) => (),
} }
} }
fn make_elf () -> Vec<u8> {
let mut buffer = vec![0;1024*1024*1024];
// https://wiki.osdev.org/ELF#ELF_Header
buffer[0x00..0x40].copy_from_slice(any_as_u8_slice(&Elf64_Ehdr {
e_ehsize: 0x40, // elf header size,
e_ident: [ // identification data
0x7f, b'E', b'L', b'F', // magic bytes
0x02, // 64-bit, 0x01 is 32-bit
0x01, // little-endian
0x01, // ELF header version
0x00, // SysV ABI
0x00, 0x00, 0x00, 0x00, // unused
0x00, 0x00, 0x00, 0x00, // unused
],
e_version: 0x01, // ELF version
e_type: 0x02, // executable
e_machine: 0x3e, // x86_64, 0x03 = x86
e_flags: 0x00, // TODO machine flags,
e_entry: 0x00, // TODO entry point (from wrapper?)
e_phnum: 0x00, // TODO program headers
e_phentsize: 0x00, // TODO why is there phent in my elf?
e_phoff: 0x00, // TODO program header table offset
e_shnum: 0x00, // TODO section headers
e_shentsize: 0x00, // TODO section header entry size
e_shoff: 0x00, // TODO section header table offset
e_shstrndx: 0x00, // TODO section header table index something something
}));
buffer
}

View file

@ -1,76 +0,0 @@
use crate::*;
use syscalls::{Sysno, syscall};
use elf::file::Elf64_Ehdr;
use std::ffi::CString;
use std::str::FromStr;
static NAME: &'static [u8] = &[b'\0'];
impl Vestal {
pub fn execute_path (&self, path: impl AsRef<Path>) -> 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(())
}
}
fn find_dll (dll: &str) -> Usually<Option<Vec<u8>>> {
let dll = dll.to_lowercase();
let path = format!("/home/user/Lab/Cosmo/wineprefix/drive_c/windows/system32/{}", dll);
let buffer = std::fs::read::<String>(path.clone())?;
println!(" Found: {path} {}b", buffer.len());
Ok(Some(buffer))
}
fn make_elf () -> Vec<u8> {
let mut buffer = vec![0;1024*1024*1024];
// https://wiki.osdev.org/ELF#ELF_Header
buffer[0x00..0x40].copy_from_slice(any_as_u8_slice(&Elf64_Ehdr {
e_ehsize: 0x40, // elf header size,
e_ident: [ // identification data
0x7f, b'E', b'L', b'F', // magic bytes
0x02, // 64-bit, 0x01 is 32-bit
0x01, // little-endian
0x01, // ELF header version
0x00, // SysV ABI
0x00, 0x00, 0x00, 0x00, // unused
0x00, 0x00, 0x00, 0x00, // unused
],
e_version: 0x01, // ELF version
e_type: 0x02, // executable
e_machine: 0x3e, // x86_64, 0x03 = x86
e_flags: 0x00, // TODO machine flags,
e_entry: 0x00, // TODO entry point (from wrapper?)
e_phnum: 0x00, // TODO program headers
e_phentsize: 0x00, // TODO why is there phent in my elf?
e_phoff: 0x00, // TODO program header table offset
e_shnum: 0x00, // TODO section headers
e_shentsize: 0x00, // TODO section header entry size
e_shoff: 0x00, // TODO section header table offset
e_shstrndx: 0x00, // TODO section header table index something something
}));
buffer
}
/// From https://stackoverflow.com/a/42186553
fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
unsafe {
::core::slice::from_raw_parts(
(p as *const T) as *const u8,
::core::mem::size_of::<T>(),
)
}
}

View file

@ -1,43 +0,0 @@
use crate::*;
impl Vestal {
pub fn inspect_path (&self, path: impl AsRef<Path>) -> Usually<crate::parse::Dll> {
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 {
//let name = descriptor.get_name(&image)?.as_str()?;
//println!("\n{name}:");
//for import in descriptor.get_imports(&image).unwrap() {
//match import {
//ImportData::Ordinal(x) => println!("{name} #{x}"),
//ImportData::ImportByName(s) => println!("{name} {s}")
//}
//}
//}
}
}

View file

@ -1,33 +1,14 @@
//mod execute; #![feature(slice_split_once)]
//mod inspect; mod dll;
mod reloc; mod exec;
mod memrun;
//mod parse;
mod vst;
pub(crate) use std::error::Error; pub(crate) use std::error::Error;
pub(crate) use std::path::{Path, PathBuf}; pub(crate) use std::path::{Path, PathBuf};
pub(crate) use std::collections::HashMap; pub(crate) use std::collections::HashMap;
pub(crate) use std::fs::{read, canonicalize}; pub(crate) use std::fs::{read, canonicalize};
pub(crate) use goblin::{error, Object, pe::{PE, import::Import, export::Export}}; pub(crate) use lancelot::loader::pe::{PE, reloc::apply_relocations};
pub(crate) use goblin::{error, Object, pe::{import::Import, export::Export}};
use clap::{arg, command, value_parser, ArgAction, Command}; use clap::{arg, command, value_parser, ArgAction, Command};
type Usually<T> = Result<T, Box<dyn std::error::Error>>; type Usually<T> = Result<T, Box<dyn std::error::Error>>;
type Sources = HashMap<String, Vec<u8>>;
type Context = HashMap<String, Dll>;
#[derive(Clone)]
struct Dll {
name: String,
path: PathBuf,
data: Vec<u8>,
}
impl Dll {
fn pe (&self) -> Usually<PE> {
read_pe(slice_shebang(&self.data))
}
}
fn main () -> Usually<()> { fn main () -> Usually<()> {
let matches = command!() let matches = command!()
.arg(arg!([path] "Path to VST DLL").value_parser(value_parser!(PathBuf))) .arg(arg!([path] "Path to VST DLL").value_parser(value_parser!(PathBuf)))
@ -35,141 +16,32 @@ fn main () -> Usually<()> {
//.arg(arg!(-s --stub <VALUE> "Provide stub import").required(false)) //.arg(arg!(-s --stub <VALUE> "Provide stub import").required(false))
.get_matches(); .get_matches();
if let Some(path) = matches.get_one::<PathBuf>("path") { if let Some(path) = matches.get_one::<PathBuf>("path") {
let mut context: Context = HashMap::new(); let mut context = crate::dll::PEContext::default();
read_dll(&mut context, "vestal", &canonicalize(&path)?)?; context.load("main", &canonicalize(&path)?)?;
Ok(()) Ok(())
} else { } else {
panic!("Pass a path to a VST DLL.") panic!("Pass a path to a VST DLL.")
} }
} }
/// From https://stackoverflow.com/a/42186553
fn read_dll (context: &mut Context, name: &str, path: &PathBuf) -> Usually<()> { pub fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
let name = canonical_name(&name); unsafe {
if context.contains_key(&name) { ::core::slice::from_raw_parts(
return Ok(()) (p as *const T) as *const u8,
::core::mem::size_of::<T>(),
)
} }
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() { /// You can manually patch DLLs by prepending
let dll = import.dll.to_lowercase(); /// a `#!/usr/bin/env vestal` line to them.
println!(" (-> {} {})", &dll, &import.name); pub fn slice_shebang (buffer: &[u8]) -> (Vec<u8>, Vec<u8>) {
imports.push(dll);
}
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(())
}
fn canonical_name (path: impl AsRef<Path>) -> String {
path.as_ref().to_path_buf().into_os_string().into_string()
.expect("failed to convert path")
.to_lowercase()
}
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'!') { if buffer.get(0) == Some(&b'#') && buffer.get(1) == Some(&b'!') {
while let Some(c) = buffer.get(index) { if let Some((bang, data)) = buffer.split_once(|x|*x==0x0a) {
if *c == 0x0a { (bang.to_vec(), data.to_vec())
slice = true;
break
}
index += 1;
}
}
if slice {
println!("Slice: {index}");
&buffer[index+1..]
} else { } else {
buffer (buffer.to_vec(), vec![])
} }
}
fn read_pe (buffer: &[u8]) -> Usually<PE> {
if let Object::PE(pe) = Object::parse(buffer)? {
Ok(pe)
} else { } else {
panic!("not a PE") (vec![], buffer.to_vec())
} }
} }
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<usize> {
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<String> {
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()),
//}
//}
//}

View file

@ -1,160 +0,0 @@
use crate::*;
pub struct Dll<'a> {
pub buffer: Vec<u8>,
pub pe: PE<'a>,
pub entrypoint: Option<&'a Export<'a>>,
pub exports: Vec<&'a Export<'a>>,
pub imports: HashMap<String, Vec<&'a Import<'a>>>,
}
#[derive(Debug)]
pub enum DllError {
NotPE,
NoEntry(String)
}
impl<'a> Dll<'a> {
pub fn from_path (path: impl AsRef<Path>) -> Usually<Self> {
Self::from_buffer(std::fs::read(path.as_ref())?)
}
pub fn from_buffer (buffer: Vec<u8>) -> Usually<Self> {
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();
if !imports.contains_key(dll) {
imports.insert(dll.to_string(), vec![]);
}
imports.get_mut(dll).unwrap().push(import);
}
let mut exports: Vec<_> = Default::default();
for export in pe.exports.iter() {
exports.push(export)
}
Ok(Self { buffer, pe, imports, exports, entrypoint: None })
} else {
Err("not a pe".into())
}
}
pub fn with_entrypoint (self, name: &str) -> Usually<Self> {
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<u8>) -> Vec<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;
}
}
println!("Slice: {slice} {index}");
if slice { buffer[index+1..].to_vec() } else { buffer }
}
//impl Vestal {
//pub fn from_path (
//path: &impl AsRef<Path>,
//cb: impl Fn(&[u8], &PE, Option<&Export>, HashMap<String, Vec<&Import>>)->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<String, Vec<&Import>>)->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<String, Vec<&Import>>)->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())
//}
//}
//}

View file

@ -1,174 +0,0 @@
use crate::*;
/// From https://docs.rs/lancelot/latest/src/lancelot/loader/pe/reloc.rs.html#68-71
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum RelocType {
/// The base relocation is skipped. This type can be used to pad a block.
Abs = 0,
/// The base relocation adds the high 16 bits of the difference to the
/// 16-bit field at offset. The 16-bit field represents the high value of a
/// 32-bit word.
Hi = 1,
/// The base relocation adds the low 16 bits of the difference to the 16-bit
/// field at offset. The 16-bit field represents the low half of a 32-bit
/// word.
Lo = 2,
/// The base relocation applies all 32 bits of the difference to the 32-bit
/// field at offset.
HiLo = 3,
/// The base relocation adds the high 16 bits of the difference to the
/// 16-bit field at offset. The 16-bit field represents the high value of a
/// 32-bit word. The low 16 bits of the 32-bit value are stored in the
/// 16-bit word that follows this base relocation. This means that this base
/// relocation occupies two slots.
HiAdj = 4,
/// The base relocation applies the difference to the 64-bit field at
/// offset.
Dir64 = 10,
}
impl From<u16> for RelocType {
fn from(value: u16) -> Self {
match value {
0 => Self::Abs,
1 => Self::Hi,
2 => Self::Lo,
3 => Self::HiLo,
4 => Self::HiAdj,
10 => Self::Dir64,
_ => panic!("Invalid RelocType value: {}", value),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Relocation {
type_: RelocType,
address: VA,
}
pub struct RelocSectionData {
base_address: VA,
buf: Vec<u8>,
}
pub type VA = u64;
pub type RVA = u64;
impl RelocSectionData {
fn read_u16(&self, offset: usize) -> Usually<u16> {
if offset + 2 > self.buf.len() {
return Err("buffer too small".into())
}
Ok(u16::from_le_bytes([
self.buf[offset + 0],
self.buf[offset + 1],
]))
}
fn read_u32(&self, offset: usize) -> Usually<u32> {
if offset + 4 > self.buf.len() {
return Err("buffer too small".into())
}
Ok(u32::from_le_bytes([
self.buf[offset + 0],
self.buf[offset + 1],
self.buf[offset + 2],
self.buf[offset + 3],
]))
}
pub fn relocations(&self) -> Usually<Vec<Relocation>> {
let mut relocations = vec![];
let mut offset = 0x0;
while offset < self.buf.len() {
let rva = self.read_u32(offset)? as u64;
let size = self.read_u32(offset + 4)? as usize;
println!("(reloc-block rva={rva:x} size={size:x})");
const header_size: usize = 8;
const entry_size: usize = 2;
let entry_count = (size - header_size) / entry_size;
for entry_index in 0..entry_count {
let entry = self.read_u16(offset + header_size + (entry_index * entry_size))?;
let entry_type = RelocType::from(entry >> 12);
let entry_value = (entry & 0x0FFF) as u64;
let address = self.base_address + rva + entry_value;
println!("(reloc-entry addr={address:x} type={entry_type:?})");
relocations.push(Relocation {
type_: entry_type,
address,
});
}
offset += size;
}
Ok(relocations)
}
pub fn from_pe(pe: &PE) -> Usually<Option<RelocSectionData>> {
let opt_header = match pe.header.optional_header {
None => return Ok(None),
Some(opt_header) => opt_header,
};
let reloc_table = match opt_header.data_directories.get_base_relocation_table() {
None => return Ok(None),
Some(reloc_table) => reloc_table,
};
println!(
"(reloc-table {:#x}-{:#x})",
pe.module.address_space.base_address + reloc_table.virtual_address as RVA,
pe.module.address_space.base_address + reloc_table.virtual_address as RVA + reloc_table.size as RVA
);
let buf = pe.module.address_space.read_bytes(
// goblin calls this a "virtual address", but its actually an RVA.
pe.module.address_space.base_address + reloc_table.virtual_address as RVA,
reloc_table.size as usize,
)?;
Ok(Some(RelocSectionData {
base_address: pe.module.address_space.base_address,
buf,
}))
}
}
pub fn apply_relocations(pe: &mut PE) -> Usually<()> {
let opt_header = match pe.optional_header {
None => return Ok(()),
Some(opt_header) => opt_header,
};
let wanted = opt_header.windows_fields.image_base;
let found = pe.module.address_space.base_address;
if wanted == found {
println!("# reloc: no relocations necessary");
return Ok(());
}
let relocations = if let Ok(Some(reloc_data)) = RelocSectionData::from_pe(pe) {
reloc_data.relocations()?
} else {
println!("# reloc: no relocations found");
return Ok(());
};
let delta = (found as i64) - (wanted as i64);
println!("# reloc: applying {} relocations", relocations.len());
for relocation in relocations.iter() {
match relocation.type_ {
// https://github.com/abhisek/Pe-Loader-Sample/blob/9aed4b3f6cd33ef75a0e01c21ea9f81608bf96cf/src/PeLdr.cpp#L44
RelocType::Abs => continue,
RelocType::Dir64 => {
println!("(reloc-dir64 {:x})", relocation.address);
let existing = pe.module.address_space.read_u64(relocation.address)?;
let updated = existing as i64 + delta;
pe.module.address_space.write_u64(relocation.address, updated as u64)?;
}
RelocType::HiLo => {
println!("(reloc-hi-lo)");
let existing = pe.module.address_space.read_u32(relocation.address)?;
let updated = existing + (delta & 0xFFFF_FFFF) as u32;
pe.module.address_space.write_u32(relocation.address, updated)?;
}
RelocType::Hi => {
println!("(reloc-hi)");
let existing = pe.module.address_space.read_u16(relocation.address)?;
let updated = existing + (((delta >> 16) & 0xFFFF) as u16);
pe.module.address_space.write_u16(relocation.address, updated)?;
}
RelocType::Lo => {
println!("(reloc-lo)");
let existing = pe.module.address_space.read_u16(relocation.address)?;
let updated = existing + ((delta & 0xFFFF) as u16);
pe.module.address_space.write_u16(relocation.address, updated)?;
}
_ => unimplemented!(),
};
}
Ok(())
}