1#![allow(clippy::needless_lifetimes)]
76
77use std::marker::PhantomData;
78use std::sync::{Mutex, MutexGuard, OnceLock};
79
80pub mod bookmarks;
81pub mod decompiler;
82pub mod func;
83pub mod idb;
84pub mod insn;
85pub mod license;
86pub mod meta;
87pub mod name;
88pub mod plugin;
89pub mod processor;
90pub mod segment;
91pub mod strings;
92pub mod xref;
93
94pub use idalib_sys as ffi;
95
96pub use ffi::IDAError;
97pub use idb::IDB;
98#[cfg(not(feature = "plugin"))]
99pub use idb::IDBOpenOptions;
100pub use license::{LicenseId, is_valid_license, license_id};
101#[cfg(feature = "plugin")]
102pub use plugin::{IDAPlugin, PluginFlags};
103
104#[cfg(feature = "plugin")]
105pub use idalib_macros::plugin;
106
107pub type Address = u64;
108pub struct AddressFlags<'a> {
109 flags: ffi::bytes::flags64_t,
110 _marker: PhantomData<&'a IDB>,
111}
112
113impl<'a> AddressFlags<'a> {
114 pub(crate) fn new(flags: ffi::bytes::flags64_t) -> Self {
115 Self {
116 flags,
117 _marker: PhantomData,
118 }
119 }
120
121 pub fn is_code(&self) -> bool {
122 unsafe { ffi::bytes::is_code(self.flags) }
123 }
124
125 pub fn is_data(&self) -> bool {
126 unsafe { ffi::bytes::is_data(self.flags) }
127 }
128}
129
130pub struct IDA;
131
132impl IDA {
133 pub fn new(_: &IDB) -> Self {
134 Self
137 }
138
139 pub fn msg(&self, message: impl AsRef<str>) -> Result<(), IDAError> {
140 unsafe { ffi::ida::msg(message) }
141 }
142}
143
144#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
145pub struct IDAVersion {
146 major: i32,
147 minor: i32,
148 build: i32,
149}
150
151impl IDAVersion {
152 pub fn major(&self) -> i32 {
153 self.major
154 }
155
156 pub fn minor(&self) -> i32 {
157 self.minor
158 }
159
160 pub fn build(&self) -> i32 {
161 self.build
162 }
163}
164
165static INIT: OnceLock<Mutex<()>> = OnceLock::new();
166
167#[cfg(not(any(target_os = "windows", feature = "plugin")))]
168unsafe extern "C" {
169 static mut batch: std::ffi::c_char;
170}
171
172pub(crate) type IDARuntimeHandle = MutexGuard<'static, ()>;
173
174#[cfg(not(feature = "plugin"))]
175pub fn force_batch_mode() {
176 #[cfg(not(target_os = "windows"))]
177 unsafe {
178 batch = 1;
179 }
180}
181
182#[cfg(feature = "plugin")]
183pub fn init_library() -> &'static Mutex<()> {
184 INIT.get_or_init(|| Mutex::new(()))
185}
186
187#[cfg(not(feature = "plugin"))]
188pub fn init_library() -> &'static Mutex<()> {
189 INIT.get_or_init(|| {
190 force_batch_mode();
191 ffi::ida::init_library().expect("IDA initialised successfully");
192 Mutex::new(())
193 })
194}
195
196pub(crate) fn prepare_library() -> IDARuntimeHandle {
197 let mutex = init_library();
198 mutex.lock().unwrap()
199}
200
201#[cfg(not(feature = "plugin"))]
202pub fn enable_console_messages(enabled: bool) {
203 init_library();
204 ffi::ida::enable_console_messages(enabled);
205}
206
207pub fn version() -> Result<IDAVersion, IDAError> {
208 ffi::ida::library_version().map(|(major, minor, build)| IDAVersion {
209 major,
210 minor,
211 build,
212 })
213}