summaryrefslogtreecommitdiff
path: root/rust/binaryninjacore-sys
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2021-05-03 18:45:59 -0400
committerKyleMiles <krm504@nyu.edu>2021-05-11 16:53:24 -0400
commit4bd1f6b1477b910b580a0bcfcde118bcefc1ddc0 (patch)
treeb8e18454053a22c3f97645c6c52a0e6b0bc6a4e3 /rust/binaryninjacore-sys
parenteb7a52bf4bd3b19c22f2eadda444ab045c674fe3 (diff)
Easier Building with Rust (now requires nightly)
Diffstat (limited to 'rust/binaryninjacore-sys')
-rw-r--r--rust/binaryninjacore-sys/Cargo.toml5
-rw-r--r--rust/binaryninjacore-sys/build.rs210
-rw-r--r--rust/binaryninjacore-sys/linkhack/linkhack.c20
3 files changed, 68 insertions, 167 deletions
diff --git a/rust/binaryninjacore-sys/Cargo.toml b/rust/binaryninjacore-sys/Cargo.toml
index e06c2db3..4abf89f3 100644
--- a/rust/binaryninjacore-sys/Cargo.toml
+++ b/rust/binaryninjacore-sys/Cargo.toml
@@ -5,7 +5,4 @@ authors = ["Ryan Snyder <ryan@vector35.com>", "Kyle Martin <kyle@vector35.com>"]
build = "build.rs"
[build-dependencies]
-bindgen = "0.57"
-
-[features]
-headless = []
+bindgen = "0.58.1"
diff --git a/rust/binaryninjacore-sys/build.rs b/rust/binaryninjacore-sys/build.rs
index 9457c250..d3b02818 100644
--- a/rust/binaryninjacore-sys/build.rs
+++ b/rust/binaryninjacore-sys/build.rs
@@ -1,26 +1,24 @@
extern crate bindgen;
use std::env;
-use std::path::PathBuf;
-
-#[cfg(any(not(target_os = "linux"), feature = "headless"))]
use std::fs::File;
-#[cfg(any(not(target_os = "linux"), feature = "headless"))]
-use std::io::prelude::*;
-#[cfg(any(not(target_os = "linux"), feature = "headless"))]
+use std::io::BufRead;
use std::io::BufReader;
+use std::path::PathBuf;
#[cfg(target_os = "macos")]
static LASTRUN_PATH: (&str, &str) = ("HOME", "Library/Application Support/Binary Ninja/lastrun");
-#[cfg(all(target_os = "linux", feature = "headless"))]
+#[cfg(target_os = "linux")]
static LASTRUN_PATH: (&str, &str) = ("HOME", ".binaryninja/lastrun");
#[cfg(windows)]
static LASTRUN_PATH: (&str, &str) = ("APPDATA", "Binary Ninja\\lastrun");
-#[cfg(any(not(target_os = "linux"), feature = "headless"))]
+// Check last run location for path to BinaryNinja; Otherwise check the default install locations
fn link_path() -> PathBuf {
+ use std::io::prelude::*;
+
let home = PathBuf::from(env::var(LASTRUN_PATH.0).unwrap());
let lastrun = PathBuf::from(&home).join(LASTRUN_PATH.1);
@@ -48,167 +46,93 @@ fn link_path() -> PathBuf {
fn main() {
println!("cargo:rerun-if-changed=../../binaryninjacore.h");
- // Allow the library search path to be overridden for internal dev builds, but
- // otherwise search the usual install paths
+ //Cargo's output directory
let out_dir = env::var("OUT_DIR").unwrap();
+
+ // Detect for custom Clang or LLVM installations (BN devs/build server)
let llvm_dir = env::var("LIBCLANG_PATH");
let llvm_version = env::var("LLVM_VERSION");
let llvm_install_dir = env::var("LLVM_INSTALL_DIR");
- #[cfg(any(not(target_os = "linux"), feature = "headless"))]
- let link_path = env::var("BINARYNINJADIR")
+ // Use BINARYNINJADIR first for custom BN builds/configurations (BN devs/build server), fallback on defaults
+ let install_path = env::var("BINARYNINJADIR")
.map(PathBuf::from)
.unwrap_or_else(|_| link_path());
- #[cfg(all(unix, feature = "headless"))]
- {
- use std::process::Command;
+ #[cfg(target_os = "linux")]
+ println!(
+ "cargo:rustc-link-arg=-Wl,-rpath,{},-L{},-l:libbinaryninjacore.so.1",
+ install_path.to_str().unwrap(),
+ install_path.to_str().unwrap(),
+ );
- // Spectacularly evil linking hack due to Cargo shortcomings. In a nutshell,
- // due to the inability for our .rlib crate to contribute linker arguments
- // (or even just an rpath!) to our consumers, any resulting binaries will
- // fail to run unless loaded into a process that already has the core loaded.
- //
- // For plugins this restriction is fine as they'll only be loaded by the core;
- // headless binaries on the other hand (consider `cargo test`, too!) will fail
- // because libbinaryninjacore is not in the library path on pretty much any
- // system anywhere. If only we could trick the linker into linking with an
- // absolute path...
- //
- // LOOK ON MY WORKS, YE MIGHTY, AND DESPAIR
- //
- // We build a simple do-nothing library called liblinkhack and add it as a
- // native dependency. Crucially, we ensure that LC_ID_DYLIB (macos) or DT_SONAME
- // (linux) is set to the absolute path of libbinaryninjacore. This has the effect
- // that any binary attempting to link with liblinkhack will have its dependency
- // on liblinkhack recorded as the path to the binaryninja core. Later on, the
- // actual core will get linked and that dependency will be recorded in the normal
- // way.
- //
- // tl;dr we're linking against a fake, shim library that actually results in
- // the binaryninja core getting linked twice, once with an absolute path and once
- // correctly. yes, this is as horrifying as you think it is. no, there is no other
- // way to make `cargo test` work.
- //
- // I'm not happy about it either.
+ #[cfg(not(target_os = "linux"))]
+ println!(
+ "cargo:rustc-link-arg=-Wl,-rpath,{},-L{},-lbinaryninjacore",
+ install_path.to_str().unwrap(),
+ install_path.to_str().unwrap(),
+ );
+ // TODO : Clean this up even more
+ #[warn(unused_assignments)]
+ let is_mac = {
#[cfg(target_os = "macos")]
- Command::new("clang")
- .args(&["-Wl,-dylib", "-o"])
- .arg(&format!("{}/liblinkhack.dylib", out_dir))
- .arg(&format!(
- "-Wl,-install_name,{}/libbinaryninjacore.dylib",
- &link_path.to_str().unwrap()
- ))
- .arg(&format!(
- "{}/linkhack/linkhack.c",
- env::var("CARGO_MANIFEST_DIR").unwrap()
- ))
- .status()
- .unwrap();
-
- #[cfg(target_os = "linux")]
{
- Command::new("gcc")
- .args(&["-shared", "-o"])
- .arg(&format!("{}/liblinkhack.so", out_dir))
- .arg(&format!(
- "-Wl,-soname,{}libbinaryninjacore.so.1",
- &link_path.to_str().unwrap()
- )) // TODO : Check mac to see if I need to remove the extra slash as well
- .arg(&format!(
- "{}/linkhack/linkhack.c",
- env::var("CARGO_MANIFEST_DIR").unwrap()
- ))
- .status()
- .unwrap();
-
- // Linux builds of binaryninja ship with libbinaryninjacore.so.1 in the
- // application folder and no symlink. The linker will attempt to link with
- // libbinaryninjacore.so. Since this is likely going to fail, we detect this
- // ahead of time and create an appropriately named symlink inside of OUT_DIR
- // and add it to the library search path.
- let symlink_target = PathBuf::from(&out_dir).join("libbinaryninjacore.so");
- if !link_path.join("libbinaryninjacore.so").exists() && !symlink_target.exists() {
- use std::os::unix::fs;
- fs::symlink(
- link_path.join("libbinaryninjacore.so.1"),
- PathBuf::from(&out_dir).join("libbinaryninjacore.so"),
- )
- .expect("failed to create required symlink");
- }
+ true
}
+ #[cfg(not(target_os = "macos"))]
+ {
+ false
+ }
+ };
- println!("cargo:rustc-link-lib=linkhack");
- println!("cargo:rustc-link-search={}", out_dir);
- }
-
- #[cfg(any(not(target_os = "linux"), feature = "headless"))]
- {
- println!("cargo:rustc-link-lib=binaryninjacore");
- println!("cargo:rustc-link-search={}", link_path.to_str().unwrap());
- }
-
- #[warn(unused_assignments)]
- let mut is_mac = false;
- #[cfg(target_os = "macos")]
- {
- is_mac = true;
+ let current_line = "#define BN_CURRENT_UI_ABI_VERSION ";
+ let minimum_line = "#define BN_MINIMUM_UI_ABI_VERSION ";
+ let mut current_version = "0".to_string();
+ let mut minimum_version = "0".to_string();
+ let file = File::open("../../ui/uitypes.h").expect("Couldn't open uitypes.h");
+ for line in BufReader::new(file).lines() {
+ let line = line.unwrap();
+ if line.starts_with(current_line) {
+ current_version = (&line[current_line.len()..]).to_owned();
+ } else if line.starts_with(minimum_line) {
+ minimum_version = (&line[minimum_line.len()..]).to_owned();
+ }
}
// Difference between global LLVM/Clang install and custom LLVM/Clang install...
// First option is for the build server, second option is being nice to our dev who have `LLVM_INSTALL_DIR` set, third is for people with "normal" setups (and Macs)
- let bindings;
+ let mut bindings = bindgen::builder()
+ .header("../../binaryninjacore.h")
+ .clang_arg("-std=c++17")
+ .clang_arg("-x")
+ .clang_arg("c++")
+ .size_t_is_usize(true)
+ .generate_comments(false)
+ .allowlist_function("BN.*")
+ .allowlist_var("BN_CURRENT_CORE_ABI_VERSION")
+ .allowlist_var("BN_MINIMUM_CORE_ABI_VERSION")
+ .raw_line(format!(
+ "pub const BN_CURRENT_UI_ABI_VERSION: u32 = {};",
+ current_version
+ ))
+ .raw_line(format!(
+ "pub const BN_MINIMUM_UI_ABI_VERSION: u32 = {};",
+ minimum_version
+ ))
+ .rustified_enum("BN.*");
if let (false, Ok(llvm_dir), Ok(llvm_version)) = (is_mac, llvm_dir, llvm_version) {
let llvm_include_path = format!("-I{}/clang/{}/include", llvm_dir, llvm_version);
- bindings = bindgen::builder()
- .header("../../binaryninjacore.h")
- .clang_arg("-std=c++17")
- .clang_arg("-x")
- .clang_arg("c++")
- .clang_arg(llvm_include_path)
- .size_t_is_usize(true)
- .generate_comments(false)
- .whitelist_function("BN.*")
- .whitelist_var("BN_CURRENT_CORE_ABI_VERSION")
- .whitelist_var("BN_MINIMUM_CORE_ABI_VERSION")
- .rustified_enum("BN.*")
- .generate()
- .expect("Unable to generate bindings");
+ bindings = bindings.clang_arg(llvm_include_path);
} else if let (false, Ok(llvm_install_dir)) = (is_mac, llvm_install_dir) {
let llvm_include_path = format!("-I{}/11.0.0/lib/clang/11.0.0/include", llvm_install_dir);
env::set_var("LIBCLANG_PATH", format!("{}/11.0.0/lib", llvm_install_dir));
- bindings = bindgen::builder()
- .header("../../binaryninjacore.h")
- .clang_arg("-std=c++17")
- .clang_arg("-x")
- .clang_arg("c++")
- .clang_arg(llvm_include_path)
- .size_t_is_usize(true)
- .generate_comments(false)
- .whitelist_function("BN.*")
- .whitelist_var("BN_CURRENT_CORE_ABI_VERSION")
- .whitelist_var("BN_MINIMUM_CORE_ABI_VERSION")
- .rustified_enum("BN.*")
- .generate()
- .expect("Unable to generate bindings");
- } else {
- bindings = bindgen::builder()
- .header("../../binaryninjacore.h")
- .clang_arg("-std=c++17")
- .clang_arg("-x")
- .clang_arg("c++")
- .size_t_is_usize(true)
- .generate_comments(false)
- .whitelist_function("BN.*")
- .whitelist_var("BN_CURRENT_CORE_ABI_VERSION")
- .whitelist_var("BN_MINIMUM_CORE_ABI_VERSION")
- .rustified_enum("BN.*")
- .generate()
- .expect("Unable to generate bindings");
+ bindings = bindings.clang_arg(llvm_include_path);
}
bindings
+ .generate()
+ .expect("Unable to generate bindings")
.write_to_file(PathBuf::from(out_dir).join("bindings.rs"))
.expect("Couldn't write bindings!");
}
diff --git a/rust/binaryninjacore-sys/linkhack/linkhack.c b/rust/binaryninjacore-sys/linkhack/linkhack.c
deleted file mode 100644
index 6d4b3f37..00000000
--- a/rust/binaryninjacore-sys/linkhack/linkhack.c
+++ /dev/null
@@ -1,20 +0,0 @@
-// Have some overlap with likely-called functions so ld on
-// linux doesn't skip linking liblinkhack
-void BNLog() {}
-void BNLogDebug() {}
-void BNLogInfo() {}
-void BNLogWarn() {}
-void BNLogError() {}
-void BNLogAlert() {}
-void BNShutdown() {}
-void BNNewViewReference() {}
-void BNFreeBinaryView() {}
-void BNInitCorePlugins() {}
-void BNAllocString() {}
-void BNFreeString() {}
-void BNRegisterBinaryViewType() {}
-void BNGetArchitectureList() {}
-void BNNewFunctionReference() {}
-void BNFreeFunction() {}
-void BNGetFunctionBasicBlockList() {}
-void BNRegisterArchitecture() {}