idalib/
lib.rs

1//! # idalib
2//!
3//! idalib is a Rust library providing idiomatic bindings for the IDA SDK, enabling the development
4//! of standalone analysis tools using IDA v9.x’s idalib.
5//!
6//! ## Usage
7//!
8//! To use idalib, add it as a dependency in your `Cargo.toml` and include a `build.rs` file in
9//! your project to properly link against IDA:
10//!
11//! ```toml
12//! [dependencies]
13//! idalib = "0.6"
14//!
15//! [build-dependencies]
16//! idalib-build = "0.6"
17//! ```
18//!
19//! Here is a basic example of a `build.rs` file:
20//!
21//! ```rust,ignore
22//! fn main() -> Result<(), Box<dyn std::error::Error>> {
23//!     idalib_build::configure_linkage()?;
24//!     Ok(())
25//! }
26//! ```
27//!
28//! This script uses the `idalib-build` crate to automatically configure the linkage against IDA.
29//! Ensure that the environment variables `IDASDKDIR` and optionally `IDADIR` are set to point to
30//! your IDA SDK and installation directories, respectively.
31//!
32//! ## Setting Environment Variables
33//!
34//! ### On Linux/macOS
35//!
36//! You can set the environment variables in your terminal session or add them to your shell
37//! configuration file (e.g., `.bashrc`, `.zshrc`):
38//!
39//! ```sh,ignore
40//! export IDASDKDIR=/path/to/ida/sdk
41//! export IDADIR=/path/to/ida/installation
42//! ```
43//!
44//! ### On Windows
45//!
46//! Set environment variables using Command Prompt, PowerShell, or System Properties.
47//!
48//! **Command Prompt:**
49//! ```cmd
50//! set IDASDKDIR=C:\path\to\ida\sdk
51//! set IDADIR=C:\path\to\ida\installation
52//! ```
53//!
54//! **PowerShell:**
55//! ```powershell,ignore
56//! $env:IDASDKDIR = "C:\path\to\ida\sdk"
57//! $env:IDADIR = "C:\path\to\ida\installation"
58//! ```
59//!
60//! **System Properties:**
61//! Go to "Environment Variables" in System Properties and add `IDASDKDIR` and `IDADIR`.
62//!
63//! ## Example
64//!
65//! Here's a simple example of how to use idalib:
66//!
67//! ```rust,ignore
68//! use idalib::idb::IDB;
69//!
70//! fn main() -> Result<(), Box<dyn std::error::Error>> {
71//!     let idb = IDB::open("/path/to/binary")?;
72//!     // Perform analysis...
73//!     Ok(())
74//! }
75//! ```
76//!
77#![allow(clippy::needless_lifetimes)]
78
79use std::ffi::c_char;
80use std::marker::PhantomData;
81use std::sync::{Mutex, MutexGuard, OnceLock};
82
83pub mod bookmarks;
84pub mod decompiler;
85pub mod func;
86pub mod idb;
87pub mod insn;
88pub mod license;
89pub mod meta;
90pub mod name;
91pub mod plugin;
92pub mod processor;
93pub mod segment;
94pub mod strings;
95pub mod xref;
96
97pub use idalib_sys as ffi;
98
99pub use ffi::IDAError;
100pub use idb::{IDB, IDBOpenOptions};
101pub use license::{LicenseId, is_valid_license, license_id};
102
103pub type Address = u64;
104pub struct AddressFlags<'a> {
105    flags: ffi::bytes::flags64_t,
106    _marker: PhantomData<&'a IDB>,
107}
108
109impl<'a> AddressFlags<'a> {
110    pub(crate) fn new(flags: ffi::bytes::flags64_t) -> Self {
111        Self {
112            flags,
113            _marker: PhantomData,
114        }
115    }
116
117    pub fn is_code(&self) -> bool {
118        unsafe { ffi::bytes::is_code(self.flags) }
119    }
120
121    pub fn is_data(&self) -> bool {
122        unsafe { ffi::bytes::is_data(self.flags) }
123    }
124}
125
126#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
127pub struct IDAVersion {
128    major: i32,
129    minor: i32,
130    build: i32,
131}
132
133impl IDAVersion {
134    pub fn major(&self) -> i32 {
135        self.major
136    }
137
138    pub fn minor(&self) -> i32 {
139        self.minor
140    }
141
142    pub fn build(&self) -> i32 {
143        self.build
144    }
145}
146
147static INIT: OnceLock<Mutex<()>> = OnceLock::new();
148
149#[cfg(not(target_os = "windows"))]
150unsafe extern "C" {
151    static mut batch: c_char;
152}
153
154pub(crate) type IDARuntimeHandle = MutexGuard<'static, ()>;
155
156pub fn force_batch_mode() {
157    #[cfg(not(target_os = "windows"))]
158    unsafe {
159        batch = 1;
160    }
161}
162
163pub fn init_library() -> &'static Mutex<()> {
164    INIT.get_or_init(|| {
165        force_batch_mode();
166        ffi::ida::init_library().expect("IDA initialised successfully");
167        Mutex::new(())
168    })
169}
170
171pub(crate) fn prepare_library() -> IDARuntimeHandle {
172    let mutex = init_library();
173    mutex.lock().unwrap()
174}
175
176pub fn enable_console_messages(enabled: bool) {
177    init_library();
178    ffi::ida::enable_console_messages(enabled);
179}
180
181pub fn version() -> Result<IDAVersion, IDAError> {
182    ffi::ida::library_version().map(|(major, minor, build)| IDAVersion {
183        major,
184        minor,
185        build,
186    })
187}