Skip to content

Commit 56a3340

Browse files
committed
Initial commit for NIF inspection tool
1 parent 87ecea9 commit 56a3340

File tree

6 files changed

+269
-1
lines changed

6 files changed

+269
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ members = [
1010
"rustler_tests/native/rustler_serde_test",
1111
"rustler_tests/native/dynamic_load",
1212
"rustler_tests/native/rustler_compile_tests",
13-
"rustler_benchmarks/native/benchmark",
13+
"rustler_benchmarks/native/benchmark", "rustler_tool",
1414
]
1515
default-members = [
1616
"rustler",

rustler_tool/.cargo/config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[target.x86_64-unknown-linux-gnu]
2+
rustflags = [ "-C", "link-args=-Wl,-export-dynamic" ]

rustler_tool/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "rustler_tool"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
clap = { version = "4.5", features = [ "derive" ] }
8+
libloading = "0.8"
9+
rustler_sys = { version = "2.4.0", path = "../rustler_sys" }

rustler_tool/src/fake_symbols.rs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#[no_mangle]
2+
pub static enif_alloc: usize = 0;
3+
#[no_mangle]
4+
pub static enif_alloc_binary: usize = 0;
5+
#[no_mangle]
6+
pub static enif_alloc_env: usize = 0;
7+
#[no_mangle]
8+
pub static enif_binary_to_term: usize = 0;
9+
#[no_mangle]
10+
pub static enif_clear_env: usize = 0;
11+
#[no_mangle]
12+
pub static enif_compare: usize = 0;
13+
#[no_mangle]
14+
pub static enif_consume_timeslice: usize = 0;
15+
#[no_mangle]
16+
pub static enif_free: usize = 0;
17+
#[no_mangle]
18+
pub static enif_free_env: usize = 0;
19+
#[no_mangle]
20+
pub static enif_get_atom: usize = 0;
21+
#[no_mangle]
22+
pub static enif_get_atom_length: usize = 0;
23+
#[no_mangle]
24+
pub static enif_get_double: usize = 0;
25+
#[no_mangle]
26+
pub static enif_get_int: usize = 0;
27+
#[no_mangle]
28+
pub static enif_get_list_cell: usize = 0;
29+
#[no_mangle]
30+
pub static enif_get_list_length: usize = 0;
31+
#[no_mangle]
32+
pub static enif_get_local_pid: usize = 0;
33+
#[no_mangle]
34+
pub static enif_get_long: usize = 0;
35+
#[no_mangle]
36+
pub static enif_get_map_size: usize = 0;
37+
#[no_mangle]
38+
pub static enif_get_map_value: usize = 0;
39+
#[no_mangle]
40+
pub static enif_get_resource: usize = 0;
41+
#[no_mangle]
42+
pub static enif_get_tuple: usize = 0;
43+
#[no_mangle]
44+
pub static enif_get_uint: usize = 0;
45+
#[no_mangle]
46+
pub static enif_get_ulong: usize = 0;
47+
#[no_mangle]
48+
pub static enif_hash: usize = 0;
49+
#[no_mangle]
50+
pub static enif_inspect_binary: usize = 0;
51+
#[no_mangle]
52+
pub static enif_inspect_iolist_as_binary: usize = 0;
53+
#[no_mangle]
54+
pub static enif_is_atom: usize = 0;
55+
#[no_mangle]
56+
pub static enif_is_binary: usize = 0;
57+
#[no_mangle]
58+
pub static enif_is_empty_list: usize = 0;
59+
#[no_mangle]
60+
pub static enif_is_fun: usize = 0;
61+
#[no_mangle]
62+
pub static enif_is_identical: usize = 0;
63+
#[no_mangle]
64+
pub static enif_is_list: usize = 0;
65+
#[no_mangle]
66+
pub static enif_is_map: usize = 0;
67+
#[no_mangle]
68+
pub static enif_is_number: usize = 0;
69+
#[no_mangle]
70+
pub static enif_is_pid: usize = 0;
71+
#[no_mangle]
72+
pub static enif_is_port: usize = 0;
73+
#[no_mangle]
74+
pub static enif_is_process_alive: usize = 0;
75+
#[no_mangle]
76+
pub static enif_is_ref: usize = 0;
77+
#[no_mangle]
78+
pub static enif_is_tuple: usize = 0;
79+
#[no_mangle]
80+
pub static enif_make_atom_len: usize = 0;
81+
#[no_mangle]
82+
pub static enif_make_badarg: usize = 0;
83+
#[no_mangle]
84+
pub static enif_make_binary: usize = 0;
85+
#[no_mangle]
86+
pub static enif_make_copy: usize = 0;
87+
#[no_mangle]
88+
pub static enif_make_double: usize = 0;
89+
#[no_mangle]
90+
pub static enif_make_existing_atom_len: usize = 0;
91+
#[no_mangle]
92+
pub static enif_make_int: usize = 0;
93+
#[no_mangle]
94+
pub static enif_make_list_cell: usize = 0;
95+
#[no_mangle]
96+
pub static enif_make_list_from_array: usize = 0;
97+
#[no_mangle]
98+
pub static enif_make_long: usize = 0;
99+
#[no_mangle]
100+
pub static enif_make_map_from_arrays: usize = 0;
101+
#[no_mangle]
102+
pub static enif_make_map_put: usize = 0;
103+
#[no_mangle]
104+
pub static enif_make_map_remove: usize = 0;
105+
#[no_mangle]
106+
pub static enif_make_map_update: usize = 0;
107+
#[no_mangle]
108+
pub static enif_make_new_binary: usize = 0;
109+
#[no_mangle]
110+
pub static enif_make_new_map: usize = 0;
111+
#[no_mangle]
112+
pub static enif_make_reverse_list: usize = 0;
113+
#[no_mangle]
114+
pub static enif_make_sub_binary: usize = 0;
115+
#[no_mangle]
116+
pub static enif_make_tuple_from_array: usize = 0;
117+
#[no_mangle]
118+
pub static enif_make_uint: usize = 0;
119+
#[no_mangle]
120+
pub static enif_make_ulong: usize = 0;
121+
#[no_mangle]
122+
pub static enif_map_iterator_create: usize = 0;
123+
#[no_mangle]
124+
pub static enif_map_iterator_destroy: usize = 0;
125+
#[no_mangle]
126+
pub static enif_map_iterator_get_pair: usize = 0;
127+
#[no_mangle]
128+
pub static enif_map_iterator_next: usize = 0;
129+
#[no_mangle]
130+
pub static enif_map_iterator_prev: usize = 0;
131+
#[no_mangle]
132+
pub static enif_open_resource_type: usize = 0;
133+
#[no_mangle]
134+
pub static enif_raise_exception: usize = 0;
135+
#[no_mangle]
136+
pub static enif_realloc_binary: usize = 0;
137+
#[no_mangle]
138+
pub static enif_release_binary: usize = 0;
139+
#[no_mangle]
140+
pub static enif_schedule_nif: usize = 0;
141+
#[no_mangle]
142+
pub static enif_self: usize = 0;
143+
#[no_mangle]
144+
pub static enif_snprintf: usize = 0;
145+
#[no_mangle]
146+
pub static enif_term_to_binary: usize = 0;
147+
#[no_mangle]
148+
pub static enif_term_type: usize = 0;

rustler_tool/src/main.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#[cfg(unix)]
2+
mod fake_symbols;
3+
mod nif;
4+
5+
use std::path::PathBuf;
6+
7+
use clap::{Parser, Subcommand};
8+
9+
use crate::nif::NifLibrary;
10+
11+
#[derive(Parser)]
12+
#[command(version, about, long_about = None)]
13+
struct Cli {
14+
#[command(subcommand)]
15+
command: Option<Commands>,
16+
}
17+
18+
#[derive(Subcommand)]
19+
enum Commands {
20+
/// does testing things
21+
Nif { path: PathBuf },
22+
}
23+
24+
fn main() {
25+
let cli = Cli::parse();
26+
27+
match &cli.command {
28+
Some(Commands::Nif { path }) => {
29+
println!("Extracting nifs from {:?}", path);
30+
31+
let lib = NifLibrary::load(&path).unwrap();
32+
33+
println!("Found library {} with nifs", lib.name);
34+
for nif in lib.nifs {
35+
println!(" {}/{}", nif.name, nif.arity);
36+
}
37+
}
38+
None => {
39+
panic!("No command given")
40+
}
41+
}
42+
}

rustler_tool/src/nif.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use libloading::{Library, Symbol};
2+
use rustler_sys::ErlNifEntry;
3+
use std::ffi::CStr;
4+
use std::path::{Path, PathBuf};
5+
6+
pub struct Nif {
7+
pub name: String,
8+
pub arity: usize,
9+
pub flags: usize,
10+
}
11+
12+
pub struct NifLibrary {
13+
pub path: PathBuf,
14+
pub name: String,
15+
pub nifs: Vec<Nif>,
16+
}
17+
18+
#[cfg(unix)]
19+
unsafe fn maybe_call_nif_init(
20+
lib: &Library,
21+
) -> Result<*const ErlNifEntry, Box<dyn std::error::Error>> {
22+
let func: Symbol<unsafe extern "C" fn() -> *const ErlNifEntry> = lib.get(b"nif_init")?;
23+
24+
Ok(func())
25+
}
26+
27+
#[cfg(windows)]
28+
unsafe fn maybe_call_nif_init(
29+
lib: &Library,
30+
) -> Result<*const ErlNifEntry, Box<dyn std::error::Error>> {
31+
use rustler_sys::TWinDynNifCallbacks;
32+
static NULL_CALLBACKS: TWinDynNifCallbacks = TWinDynNifCallbacks {};
33+
let func: Symbol<unsafe extern "C" fn(*mut TWinDynNifCallbacks) -> *const ErlNifEntry> =
34+
lib.get(b"nif_init")?;
35+
36+
func(&NULL_CALLBACKS)
37+
}
38+
39+
impl NifLibrary {
40+
pub fn load(path: &Path) -> Result<NifLibrary, Box<dyn std::error::Error>> {
41+
unsafe {
42+
let lib = Library::new(&path)?;
43+
let entry = maybe_call_nif_init(&lib)?;
44+
45+
let name = CStr::from_ptr((*entry).name).to_str()?.to_string();
46+
let nif_array =
47+
std::slice::from_raw_parts((*entry).funcs, (*entry).num_of_funcs as usize);
48+
49+
let nifs = nif_array
50+
.into_iter()
51+
.filter_map(|f| {
52+
Some(Nif {
53+
name: CStr::from_ptr((*f).name).to_str().ok()?.to_string(),
54+
arity: (*f).arity as usize,
55+
flags: (*f).flags as usize,
56+
})
57+
})
58+
.collect();
59+
60+
Ok(NifLibrary {
61+
path: path.to_path_buf(),
62+
name,
63+
nifs,
64+
})
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)