Add a bundler module for parsing exported symbols
We can use this to detect which plugin formats are supported by a plugin. Otherwise the bundler would be very awkward to use when supporting multiple formats.
This commit is contained in:
parent
fefc2de9ba
commit
d39ebb5b51
38
Cargo.lock
generated
38
Cargo.lock
generated
|
@ -400,6 +400,17 @@ dependencies = [
|
|||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "goblin"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c955ab4e0ad8c843ea653a3d143048b87490d9be56bd7132a435c2407846ac8f"
|
||||
dependencies = [
|
||||
"log",
|
||||
"plain",
|
||||
"scroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
|
@ -665,6 +676,12 @@ version = "0.3.24"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
||||
|
||||
[[package]]
|
||||
name = "plain"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.36"
|
||||
|
@ -728,6 +745,26 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scroll"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da"
|
||||
dependencies = [
|
||||
"scroll_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scroll_derive"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.136"
|
||||
|
@ -1118,6 +1155,7 @@ name = "xtask"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"goblin",
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
|
|
@ -7,5 +7,6 @@ license = "ISC"
|
|||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
goblin = "0.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
toml = "0.5"
|
||||
|
|
|
@ -5,6 +5,8 @@ use std::fs;
|
|||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
mod symbols;
|
||||
|
||||
const USAGE_STRING: &str =
|
||||
"Usage: cargo xtask bundle <package> [--release] [--target <triple>] [--bundle-vst3]";
|
||||
|
||||
|
|
31
xtask/src/symbols.rs
Normal file
31
xtask/src/symbols.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use anyhow::{bail, Context, Result};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
/// Check whether a binary exports the specified symbol. Used to detect the plugin formats supported
|
||||
/// by a plugin library. Returns an error if the binary cuuld not be read. This function will also
|
||||
/// parse non-native binaries.
|
||||
pub fn exported<P: AsRef<Path>>(binary: P, symbol: &str) -> Result<bool> {
|
||||
// Parsing the raw binary instead of relying on nm-like tools makes cross compiling a bit easier
|
||||
let bytes = fs::read(&binary)
|
||||
.with_context(|| format!("Could not read '{}'", binary.as_ref().display()))?;
|
||||
match goblin::Object::parse(&bytes)? {
|
||||
goblin::Object::Elf(obj) => Ok(obj.dynsyms.iter().any(|sym| {
|
||||
!sym.is_import()
|
||||
&& sym.is_function()
|
||||
&& obj.dynstrtab.get_at(sym.st_name) == Some(symbol)
|
||||
})),
|
||||
goblin::Object::Mach(obj) => {
|
||||
let obj = match obj {
|
||||
goblin::mach::Mach::Fat(arches) => arches
|
||||
.get(0)
|
||||
.context("Fat Mach-O binary without any binaries")?,
|
||||
goblin::mach::Mach::Binary(obj) => obj,
|
||||
};
|
||||
|
||||
Ok(obj.exports()?.into_iter().any(|sym| sym.name == symbol))
|
||||
}
|
||||
goblin::Object::PE(obj) => Ok(obj.exports.iter().any(|sym| sym.name == Some(symbol))),
|
||||
obj => bail!("Unsupported object type: {:?}", obj),
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue