Skip to content

Commit 32b58ea

Browse files
committed
Link core in rust
When linking you must depend on the -sys crate. This is because linker arguments (what says where to find binaryninjacore) are NOT transitive. The top level application crate MUST provide it. For more information see: - rust-lang/cargo#9554 (comment) - oxidecomputer/omicron#225
1 parent a5cdded commit 32b58ea

File tree

22 files changed

+158
-526
lines changed

22 files changed

+158
-526
lines changed

rust/Cargo.lock

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/README.md

+36-12
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
# BinaryNinja-rs
22

3-
<img align="right" src="./under_construction.png" width="175" height="175">
3+
<img align="right" src="./under_construction.png" width="175" height="175" alt="Construction">
44

55
> :warning: **These bindings are in a very early beta, only have partial support for the core APIs and are still actively under development. Compatibility _will_ break and conventions _will_ change! They are being used for core Binary Ninja features however, so we expect much of what is already there to be reliable enough to build on, just don't be surprised if your plugins/scripts need to hit a moving target.**
66
7-
> :warning: This project runs on Rust version `1.83.0`
7+
> :warning: This project requires Rust version `1.83.0`
88
99

1010
## Contributing
1111

1212
:warning: If you're thinking of contributing to the Rust API, we encourage you to join the #rust-api channel in our Slack: https://slack.binary.ninja, especially for large-effort PRs.
13-
Add a "Contributing" section to the Rust API readme
14-
1513

1614
## Dependencies
1715

18-
Having BinaryNinja installed (and your license registered)
19-
Clang
20-
Rust
16+
- Having BinaryNinja installed (and your license registered)
17+
- Clang
18+
- Rust
2119

2220

2321
## How to use
@@ -27,7 +25,7 @@ See [`examples/template`](examples/template) for more details.
2725
### To write a plugin:
2826

2927
`Cargo.toml`:
30-
```
28+
```toml
3129
[lib]
3230
crate-type = ["cdylib"]
3331

@@ -40,15 +38,41 @@ See the `./examples/`. Plugin registration commands are in `binaryninja::comman
4038

4139
### To write a standalone executable:
4240

41+
Writing a standalone executable requires that you link to `binaryninjacore` directly. The process of locating that however
42+
is done for you within the `binaryninjacore-sys` crate. Because linker arguments are _not_ transitive for executables you
43+
must specify them within your `build.rs`.
44+
4345
`Cargo.toml`:
44-
```
46+
```toml
4547
[dependencies]
4648
binaryninja = { git = "https://github.com/Vector35/binaryninja-api.git", branch = "dev"}
49+
# Locates binaryninjacore on your system.
50+
binaryninjacore-sys = { git = "https://github.com/Vector35/binaryninja-api.git", branch = "dev"}
51+
```
52+
53+
`build.rs`:
54+
```rust
55+
fn main() {
56+
let link_path =
57+
std::env::var_os("DEP_BINARYNINJACORE_PATH").expect("DEP_BINARYNINJACORE_PATH specified");
58+
59+
println!("cargo::rustc-link-lib=dylib=binaryninjacore");
60+
println!("cargo::rustc-link-search={}", link_path.to_str().unwrap());
61+
62+
#[cfg(not(target_os = "windows"))]
63+
{
64+
println!(
65+
"cargo::rustc-link-arg=-Wl,-rpath,{0},-L{0}",
66+
link_path.to_string_lossy()
67+
);
68+
}
69+
}
70+
4771
```
4872

49-
All standalone binaries should call both `binaryninja::headless::init()` and `binaryninja::headless::shutdown()`.
50-
All standalone binaries need to provide a `build.rs`.
51-
See [`examples/template`](examples/template) for details.
73+
- All standalone binaries should call both `binaryninja::headless::init()` and `binaryninja::headless::shutdown()`.
74+
- All standalone binaries need to provide a `build.rs`.
75+
- See [`examples/template`](examples/template) for details.
5276

5377
## Docs
5478

rust/binaryninjacore-sys/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "0.1.0"
44
authors = ["Ryan Snyder <[email protected]>", "Kyle Martin <[email protected]>"]
55
build = "build.rs"
66
edition = "2021"
7+
links = "binaryninjacore"
78

89
[build-dependencies]
910
bindgen = "0.71.1"

rust/binaryninjacore-sys/build.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ fn main() {
7474
println!("cargo:rustc-link-search={}", out_dir);
7575
}
7676

77-
println!("cargo:rustc-link-lib=binaryninjacore");
78-
println!("cargo:rustc-link-search={}", link_path.to_str().unwrap());
77+
// Emit the path to binaryninjacore consumers of this crate should pass to the linker.
78+
println!("cargo:path={}", link_path.to_str().unwrap());
7979

8080
let current_line = "#define BN_CURRENT_UI_ABI_VERSION ";
8181
let minimum_line = "#define BN_MINIMUM_UI_ABI_VERSION ";

rust/build.rs

+14
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,18 @@ fn main() {
99
"target/doc/under_construction.png",
1010
);
1111
let _ = std::fs::copy("../docs/img/logo.png", "target/doc/logo.png");
12+
13+
let link_path =
14+
std::env::var_os("DEP_BINARYNINJACORE_PATH").expect("DEP_BINARYNINJACORE_PATH specified");
15+
16+
println!("cargo::rustc-link-lib=dylib=binaryninjacore");
17+
println!("cargo::rustc-link-search={}", link_path.to_str().unwrap());
18+
19+
#[cfg(not(target_os = "windows"))]
20+
{
21+
println!(
22+
"cargo::rustc-link-arg=-Wl,-rpath,{0},-L{0}",
23+
link_path.to_string_lossy()
24+
);
25+
}
1226
}

rust/examples/basic_script/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ edition = "2021"
55

66
[dependencies]
77
binaryninja = {path="../../"}
8+
binaryninjacore-sys = {path="../../binaryninjacore-sys"}

rust/examples/basic_script/build.rs

+11-64
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,15 @@
1-
use std::env;
2-
use std::fs::File;
3-
use std::io::BufReader;
4-
use std::path::PathBuf;
5-
6-
#[cfg(target_os = "macos")]
7-
static LASTRUN_PATH: (&str, &str) = ("HOME", "Library/Application Support/Binary Ninja/lastrun");
8-
9-
#[cfg(target_os = "linux")]
10-
static LASTRUN_PATH: (&str, &str) = ("HOME", ".binaryninja/lastrun");
11-
12-
#[cfg(windows)]
13-
static LASTRUN_PATH: (&str, &str) = ("APPDATA", "Binary Ninja\\lastrun");
14-
15-
// Check last run location for path to BinaryNinja; Otherwise check the default install locations
16-
fn link_path() -> PathBuf {
17-
use std::io::prelude::*;
18-
19-
let home = PathBuf::from(env::var(LASTRUN_PATH.0).unwrap());
20-
let lastrun = PathBuf::from(&home).join(LASTRUN_PATH.1);
21-
22-
File::open(lastrun)
23-
.and_then(|f| {
24-
let mut binja_path = String::new();
25-
let mut reader = BufReader::new(f);
26-
27-
reader.read_line(&mut binja_path)?;
28-
Ok(PathBuf::from(binja_path.trim()))
29-
})
30-
.unwrap_or_else(|_| {
31-
#[cfg(target_os = "macos")]
32-
return PathBuf::from("/Applications/Binary Ninja.app/Contents/MacOS");
33-
34-
#[cfg(target_os = "linux")]
35-
return home.join("binaryninja");
36-
37-
#[cfg(windows)]
38-
return PathBuf::from(env::var("PROGRAMFILES").unwrap())
39-
.join("Vector35\\BinaryNinja\\");
40-
})
41-
}
42-
431
fn main() {
44-
// Use BINARYNINJADIR first for custom BN builds/configurations (BN devs/build server), fallback on defaults
45-
let install_path = env::var("BINARYNINJADIR")
46-
.map(PathBuf::from)
47-
.unwrap_or_else(|_| link_path());
48-
49-
#[cfg(target_os = "linux")]
50-
println!(
51-
"cargo:rustc-link-arg=-Wl,-rpath,{},-L{},-l:libbinaryninjacore.so.1",
52-
install_path.to_str().unwrap(),
53-
install_path.to_str().unwrap(),
54-
);
55-
56-
#[cfg(target_os = "macos")]
57-
println!(
58-
"cargo:rustc-link-arg=-Wl,-rpath,{},-L{},-lbinaryninjacore",
59-
install_path.to_str().unwrap(),
60-
install_path.to_str().unwrap(),
61-
);
62-
63-
#[cfg(target_os = "windows")]
2+
let link_path =
3+
std::env::var_os("DEP_BINARYNINJACORE_PATH").expect("DEP_BINARYNINJACORE_PATH specified");
4+
5+
println!("cargo::rustc-link-lib=dylib=binaryninjacore");
6+
println!("cargo::rustc-link-search={}", link_path.to_str().unwrap());
7+
8+
#[cfg(not(target_os = "windows"))]
649
{
65-
println!("cargo:rustc-link-lib=binaryninjacore");
66-
println!("cargo:rustc-link-search={}", install_path.to_str().unwrap());
10+
println!(
11+
"cargo::rustc-link-arg=-Wl,-rpath,{0},-L{0}",
12+
link_path.to_string_lossy()
13+
);
6714
}
6815
}

rust/examples/decompile/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ edition = "2021"
66

77
[dependencies]
88
binaryninja = {path="../../"}
9+
binaryninjacore-sys = {path="../../binaryninjacore-sys"}
910
clap = { version = "4.5", features = ["derive"] }
1011

rust/examples/decompile/build.rs

+11-64
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,15 @@
1-
use std::env;
2-
use std::fs::File;
3-
use std::io::BufReader;
4-
use std::path::PathBuf;
5-
6-
#[cfg(target_os = "macos")]
7-
static LASTRUN_PATH: (&str, &str) = ("HOME", "Library/Application Support/Binary Ninja/lastrun");
8-
9-
#[cfg(target_os = "linux")]
10-
static LASTRUN_PATH: (&str, &str) = ("HOME", ".binaryninja/lastrun");
11-
12-
#[cfg(windows)]
13-
static LASTRUN_PATH: (&str, &str) = ("APPDATA", "Binary Ninja\\lastrun");
14-
15-
// Check last run location for path to BinaryNinja; Otherwise check the default install locations
16-
fn link_path() -> PathBuf {
17-
use std::io::prelude::*;
18-
19-
let home = PathBuf::from(env::var(LASTRUN_PATH.0).unwrap());
20-
let lastrun = PathBuf::from(&home).join(LASTRUN_PATH.1);
21-
22-
File::open(lastrun)
23-
.and_then(|f| {
24-
let mut binja_path = String::new();
25-
let mut reader = BufReader::new(f);
26-
27-
reader.read_line(&mut binja_path)?;
28-
Ok(PathBuf::from(binja_path.trim()))
29-
})
30-
.unwrap_or_else(|_| {
31-
#[cfg(target_os = "macos")]
32-
return PathBuf::from("/Applications/Binary Ninja.app/Contents/MacOS");
33-
34-
#[cfg(target_os = "linux")]
35-
return home.join("binaryninja");
36-
37-
#[cfg(windows)]
38-
return PathBuf::from(env::var("PROGRAMFILES").unwrap())
39-
.join("Vector35\\BinaryNinja\\");
40-
})
41-
}
42-
431
fn main() {
44-
// Use BINARYNINJADIR first for custom BN builds/configurations (BN devs/build server), fallback on defaults
45-
let install_path = env::var("BINARYNINJADIR")
46-
.map(PathBuf::from)
47-
.unwrap_or_else(|_| link_path());
48-
49-
#[cfg(target_os = "linux")]
50-
println!(
51-
"cargo:rustc-link-arg=-Wl,-rpath,{},-L{},-l:libbinaryninjacore.so.1",
52-
install_path.to_str().unwrap(),
53-
install_path.to_str().unwrap(),
54-
);
55-
56-
#[cfg(target_os = "macos")]
57-
println!(
58-
"cargo:rustc-link-arg=-Wl,-rpath,{},-L{},-lbinaryninjacore",
59-
install_path.to_str().unwrap(),
60-
install_path.to_str().unwrap(),
61-
);
62-
63-
#[cfg(target_os = "windows")]
2+
let link_path =
3+
std::env::var_os("DEP_BINARYNINJACORE_PATH").expect("DEP_BINARYNINJACORE_PATH specified");
4+
5+
println!("cargo::rustc-link-lib=dylib=binaryninjacore");
6+
println!("cargo::rustc-link-search={}", link_path.to_str().unwrap());
7+
8+
#[cfg(not(target_os = "windows"))]
649
{
65-
println!("cargo:rustc-link-lib=binaryninjacore");
66-
println!("cargo:rustc-link-search={}", install_path.to_str().unwrap());
10+
println!(
11+
"cargo::rustc-link-arg=-Wl,-rpath,{0},-L{0}",
12+
link_path.to_string_lossy()
13+
);
6714
}
6815
}

rust/examples/dwarf/dwarf_export/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ crate-type = ["cdylib"]
88

99
[dependencies]
1010
binaryninja = {path="../../../"}
11+
binaryninjacore-sys = {path="../../../binaryninjacore-sys"}
1112
gimli = "^0.31"
1213
log = "^0.4"
1314
object = { version = "0.32.1", features = ["write"] }

0 commit comments

Comments
 (0)