1use binaryninjacore_sys::*;
18
19use crate::binary_view::BinaryView;
20use crate::disassembly::{DisassemblySettings, DisassemblyTextLine};
21use crate::function::{Function, NativeBlock};
22
23use crate::basic_block::BasicBlock;
24use crate::rc::*;
25use crate::render_layer::CoreRenderLayer;
26use crate::string::{raw_to_string, BnString};
27use std::ops::Deref;
28
29pub type LinearDisassemblyLineType = BNLinearDisassemblyLineType;
30pub type LinearViewObjectIdentifierType = BNLinearViewObjectIdentifierType;
31
32pub struct LinearViewObject {
33 pub(crate) handle: *mut BNLinearViewObject,
34}
35
36impl LinearViewObject {
37 pub(crate) unsafe fn from_raw(handle: *mut BNLinearViewObject) -> Self {
38 debug_assert!(!handle.is_null());
39 Self { handle }
40 }
41
42 pub(crate) unsafe fn ref_from_raw(handle: *mut BNLinearViewObject) -> Ref<Self> {
43 debug_assert!(!handle.is_null());
44 Ref::new(Self { handle })
45 }
46
47 pub fn identifier(&self) -> LinearViewObjectIdentifier {
48 let raw = unsafe { BNGetLinearViewObjectIdentifier(self.handle) };
49 LinearViewObjectIdentifier::from_owned_raw(raw)
50 }
51
52 pub fn data_only(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
53 unsafe {
54 let handle = BNCreateLinearViewDataOnly(view.handle, settings.handle);
55 Self::ref_from_raw(handle)
56 }
57 }
58
59 pub fn disassembly(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
60 unsafe {
61 let handle = BNCreateLinearViewDisassembly(view.handle, settings.handle);
62 Self::ref_from_raw(handle)
63 }
64 }
65
66 pub fn lifted_il(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
67 unsafe {
68 let handle = BNCreateLinearViewLiftedIL(view.handle, settings.handle);
69 Self::ref_from_raw(handle)
70 }
71 }
72
73 pub fn llil(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
74 unsafe {
75 let handle = BNCreateLinearViewLowLevelIL(view.handle, settings.handle);
76 Self::ref_from_raw(handle)
77 }
78 }
79
80 pub fn mlil(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
81 unsafe {
82 let handle = BNCreateLinearViewMediumLevelIL(view.handle, settings.handle);
83 Self::ref_from_raw(handle)
84 }
85 }
86
87 pub fn mlil_ssa(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
88 unsafe {
89 let handle = BNCreateLinearViewMediumLevelILSSAForm(view.handle, settings.handle);
90 Self::ref_from_raw(handle)
91 }
92 }
93
94 pub fn hlil(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
95 unsafe {
96 let handle = BNCreateLinearViewHighLevelIL(view.handle, settings.handle);
97 Self::ref_from_raw(handle)
98 }
99 }
100
101 pub fn hlil_ssa(view: &BinaryView, settings: &DisassemblySettings) -> Ref<Self> {
102 unsafe {
103 let handle = BNCreateLinearViewHighLevelILSSAForm(view.handle, settings.handle);
104 Self::ref_from_raw(handle)
105 }
106 }
107
108 pub fn language_representation(
109 view: &BinaryView,
110 settings: &DisassemblySettings,
111 language: &str,
112 ) -> Ref<Self> {
113 unsafe {
114 let language = std::ffi::CString::new(language).unwrap();
115 let handle = BNCreateLinearViewLanguageRepresentation(
116 view.handle,
117 settings.handle,
118 language.as_ptr(),
119 );
120
121 Self::ref_from_raw(handle)
122 }
123 }
124
125 pub fn single_function_disassembly(
126 function: &Function,
127 settings: &DisassemblySettings,
128 ) -> Ref<Self> {
129 unsafe {
130 let handle =
131 BNCreateLinearViewSingleFunctionDisassembly(function.handle, settings.handle);
132 Self::ref_from_raw(handle)
133 }
134 }
135
136 pub fn single_function_lifted_il(
137 function: &Function,
138 settings: &DisassemblySettings,
139 ) -> Ref<Self> {
140 unsafe {
141 let handle = BNCreateLinearViewSingleFunctionLiftedIL(function.handle, settings.handle);
142 Self::ref_from_raw(handle)
143 }
144 }
145
146 pub fn single_function_mlil(function: &Function, settings: &DisassemblySettings) -> Ref<Self> {
147 unsafe {
148 let handle =
149 BNCreateLinearViewSingleFunctionMediumLevelIL(function.handle, settings.handle);
150 Self::ref_from_raw(handle)
151 }
152 }
153
154 pub fn single_function_mlil_ssa(
155 function: &Function,
156 settings: &DisassemblySettings,
157 ) -> Ref<Self> {
158 unsafe {
159 let handle = BNCreateLinearViewSingleFunctionMediumLevelILSSAForm(
160 function.handle,
161 settings.handle,
162 );
163 Self::ref_from_raw(handle)
164 }
165 }
166
167 pub fn single_function_hlil(function: &Function, settings: &DisassemblySettings) -> Ref<Self> {
168 unsafe {
169 let handle =
170 BNCreateLinearViewSingleFunctionHighLevelIL(function.handle, settings.handle);
171 Self::ref_from_raw(handle)
172 }
173 }
174
175 pub fn single_function_hlil_ssa(
176 function: &Function,
177 settings: &DisassemblySettings,
178 ) -> Ref<Self> {
179 unsafe {
180 let handle = BNCreateLinearViewSingleFunctionHighLevelILSSAForm(
181 function.handle,
182 settings.handle,
183 );
184 Self::ref_from_raw(handle)
185 }
186 }
187
188 pub fn single_function_language_representation(
189 function: &Function,
190 settings: &DisassemblySettings,
191 language: &str,
192 ) -> Ref<Self> {
193 unsafe {
194 let language = std::ffi::CString::new(language).unwrap();
195 let handle = BNCreateLinearViewSingleFunctionLanguageRepresentation(
196 function.handle,
197 settings.handle,
198 language.as_ptr(),
199 );
200 Self::ref_from_raw(handle)
201 }
202 }
203
204 pub fn create_cursor(&self) -> Ref<LinearViewCursor> {
205 unsafe {
206 let handle = BNCreateLinearViewCursor(self.handle);
207 LinearViewCursor::ref_from_raw(handle)
208 }
209 }
210}
211
212unsafe impl RefCountable for LinearViewObject {
213 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
214 Ref::new(Self {
215 handle: BNNewLinearViewObjectReference(handle.handle),
216 })
217 }
218
219 unsafe fn dec_ref(handle: &Self) {
220 BNFreeLinearViewObject(handle.handle);
221 }
222}
223
224impl ToOwned for LinearViewObject {
225 type Owned = Ref<Self>;
226
227 fn to_owned(&self) -> Self::Owned {
228 unsafe { RefCountable::inc_ref(self) }
229 }
230}
231
232unsafe impl Send for LinearViewObject {}
233unsafe impl Sync for LinearViewObject {}
234
235#[derive(Clone, PartialEq, Debug)]
236pub struct LinearViewObjectIdentifier {
237 pub name: String,
238 pub ty: LinearViewObjectIdentifierType,
239 pub start: u64,
240 pub end: u64,
241}
242
243impl LinearViewObjectIdentifier {
244 pub fn from_raw(value: &BNLinearViewObjectIdentifier) -> Self {
245 Self {
246 name: raw_to_string(value.name).unwrap(),
247 ty: value.type_,
248 start: value.start,
249 end: value.end,
250 }
251 }
252
253 pub fn from_owned_raw(value: BNLinearViewObjectIdentifier) -> Self {
254 let owned = Self::from_raw(&value);
255 Self::free_raw(value);
256 owned
257 }
258
259 pub fn into_raw(value: Self) -> BNLinearViewObjectIdentifier {
260 let bn_name = BnString::new(value.name);
261 BNLinearViewObjectIdentifier {
262 name: BnString::into_raw(bn_name),
263 type_: value.ty,
264 start: value.start,
265 end: value.end,
266 }
267 }
268
269 pub fn free_raw(value: BNLinearViewObjectIdentifier) {
270 unsafe { BnString::free_raw(value.name) };
271 }
272}
273
274#[derive(Eq)]
276pub struct LinearViewCursor {
277 pub(crate) handle: *mut BNLinearViewCursor,
278}
279
280impl LinearViewCursor {
281 pub(crate) unsafe fn ref_from_raw(handle: *mut BNLinearViewCursor) -> Ref<Self> {
282 debug_assert!(!handle.is_null());
283 Ref::new(Self { handle })
284 }
285
286 pub fn current_object(&self) -> Ref<LinearViewObject> {
288 unsafe {
289 let handle = BNGetLinearViewCursorCurrentObject(self.handle);
290 LinearViewObject::ref_from_raw(handle)
291 }
292 }
293
294 pub fn duplicate(&self) -> Ref<Self> {
295 unsafe {
296 let handle = BNDuplicateLinearViewCursor(self.handle);
297 Self::ref_from_raw(handle)
298 }
299 }
300
301 pub fn before_begin(&self) -> bool {
302 unsafe { BNIsLinearViewCursorBeforeBegin(self.handle) }
303 }
304
305 pub fn after_end(&self) -> bool {
306 unsafe { BNIsLinearViewCursorAfterEnd(self.handle) }
307 }
308
309 pub fn valid(&self) -> bool {
310 !(self.before_begin() || self.after_end())
311 }
312
313 pub fn seek_to_start(&mut self) {
314 unsafe { BNSeekLinearViewCursorToBegin(self.handle) }
315 }
316
317 pub fn seek_to_end(&mut self) {
318 unsafe { BNSeekLinearViewCursorToEnd(self.handle) }
319 }
320
321 pub fn seek_to_address(&mut self, address: u64) {
322 unsafe { BNSeekLinearViewCursorToAddress(self.handle, address) }
323 }
324
325 pub fn ordering_index(&self) -> std::ops::Range<u64> {
326 unsafe {
327 let range = BNGetLinearViewCursorOrderingIndex(self.handle);
328 range.start..range.end
329 }
330 }
331
332 pub fn ordering_index_total(&self) -> u64 {
333 unsafe { BNGetLinearViewCursorOrderingIndexTotal(self.handle) }
334 }
335
336 pub fn seek_to_ordering_index(&mut self, idx: u64) {
337 unsafe { BNSeekLinearViewCursorToAddress(self.handle, idx) }
338 }
339
340 pub fn previous(&mut self) -> bool {
341 unsafe { BNLinearViewCursorPrevious(self.handle) }
342 }
343
344 #[allow(clippy::should_implement_trait)]
347 pub fn next(&mut self) -> bool {
348 unsafe { BNLinearViewCursorNext(self.handle) }
349 }
350
351 pub fn lines(&self) -> Array<LinearDisassemblyLine> {
352 let mut count: usize = 0;
353 unsafe {
354 let handles = BNGetLinearViewCursorLines(self.handle, &mut count);
355 Array::new(handles, count, ())
356 }
357 }
358
359 pub fn render_layers(&self) -> Array<CoreRenderLayer> {
361 let mut count: usize = 0;
362 unsafe {
363 let handles = BNGetLinearViewCursorRenderLayers(self.handle, &mut count);
364 Array::new(handles, count, ())
365 }
366 }
367
368 pub fn add_render_layer(&self, layer: &CoreRenderLayer) {
372 unsafe { BNAddLinearViewCursorRenderLayer(self.handle, layer.handle.as_ptr()) };
373 }
374
375 pub fn remove_render_layer(&self, layer: &CoreRenderLayer) {
377 unsafe { BNRemoveLinearViewCursorRenderLayer(self.handle, layer.handle.as_ptr()) };
378 }
379}
380
381impl PartialEq for LinearViewCursor {
382 fn eq(&self, other: &Self) -> bool {
383 unsafe { BNCompareLinearViewCursors(self.handle, other.handle) == 0 }
384 }
385}
386
387impl PartialOrd for LinearViewCursor {
388 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
389 Some(self.cmp(other))
390 }
391}
392
393impl Ord for LinearViewCursor {
394 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
395 match unsafe { BNCompareLinearViewCursors(self.handle, other.handle) } {
396 i if i < 0 => std::cmp::Ordering::Less,
397 i if i > 0 => std::cmp::Ordering::Greater,
398 _ => std::cmp::Ordering::Equal,
399 }
400 }
401}
402
403unsafe impl RefCountable for LinearViewCursor {
404 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
405 Ref::new(Self {
406 handle: BNNewLinearViewCursorReference(handle.handle),
407 })
408 }
409
410 unsafe fn dec_ref(handle: &Self) {
411 BNFreeLinearViewCursor(handle.handle);
412 }
413}
414
415impl ToOwned for LinearViewCursor {
416 type Owned = Ref<Self>;
417
418 fn to_owned(&self) -> Self::Owned {
419 unsafe { RefCountable::inc_ref(self) }
420 }
421}
422
423unsafe impl Send for LinearViewCursor {}
424unsafe impl Sync for LinearViewCursor {}
425
426#[derive(Clone, PartialEq, Debug, Eq)]
427pub struct LinearDisassemblyLine {
428 pub ty: LinearDisassemblyLineType,
429 pub function: Option<Ref<Function>>,
430 pub basic_block: Option<Ref<BasicBlock<NativeBlock>>>,
431 pub contents: DisassemblyTextLine,
432}
433
434impl LinearDisassemblyLine {
435 pub(crate) unsafe fn from_raw(value: &BNLinearDisassemblyLine) -> Self {
436 let function = if !value.function.is_null() {
437 Some(unsafe { Function::from_raw(value.function).to_owned() })
438 } else {
439 None
440 };
441 let basic_block = if !value.block.is_null() {
442 Some(unsafe { BasicBlock::from_raw(value.block, NativeBlock::new()).to_owned() })
443 } else {
444 None
445 };
446 Self {
447 ty: value.type_,
448 function,
449 basic_block,
450 contents: DisassemblyTextLine::from_raw(&value.contents),
451 }
452 }
453
454 #[allow(unused)]
455 pub(crate) unsafe fn from_owned_raw(value: BNLinearDisassemblyLine) -> Self {
456 let owned = Self::from_raw(&value);
457 Self::free_raw(value);
458 owned
459 }
460
461 pub(crate) fn into_raw(value: Self) -> BNLinearDisassemblyLine {
462 let function_ptr = value
463 .function
464 .map(|f| unsafe { Ref::into_raw(f) }.handle)
465 .unwrap_or(std::ptr::null_mut());
466 let block_ptr = value
467 .basic_block
468 .map(|b| unsafe { Ref::into_raw(b) }.handle)
469 .unwrap_or(std::ptr::null_mut());
470 BNLinearDisassemblyLine {
471 type_: value.ty,
472 function: function_ptr,
473 block: block_ptr,
474 contents: DisassemblyTextLine::into_raw(value.contents),
475 }
476 }
477
478 pub(crate) fn free_raw(value: BNLinearDisassemblyLine) {
479 if !value.function.is_null() {
480 let _ = unsafe { Function::ref_from_raw(value.function) };
481 }
482 if !value.block.is_null() {
483 let _ = unsafe { BasicBlock::ref_from_raw(value.block, NativeBlock::new()) };
484 }
485 DisassemblyTextLine::free_raw(value.contents);
486 }
487}
488
489impl Deref for LinearDisassemblyLine {
490 type Target = DisassemblyTextLine;
491 fn deref(&self) -> &Self::Target {
492 &self.contents
493 }
494}
495
496impl std::fmt::Display for LinearDisassemblyLine {
497 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
498 write!(f, "{}", self.contents)
499 }
500}
501
502impl CoreArrayProvider for LinearDisassemblyLine {
503 type Raw = BNLinearDisassemblyLine;
504 type Context = ();
505 type Wrapped<'a> = LinearDisassemblyLine;
506}
507
508unsafe impl CoreArrayProviderInner for LinearDisassemblyLine {
509 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
510 BNFreeLinearDisassemblyLines(raw, count);
511 }
512
513 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
514 Self::from_raw(raw)
515 }
516}