binaryninja/
architecture.rs

1// Copyright 2021-2026 Vector 35 Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Architectures provide disassembly, lifting, and associated metadata about a CPU to inform
16//! analysis and decompilation.
17//!
18//! For more information see the [`Architecture`] trait and the [`CoreArchitecture`] structure for
19//! querying already registered architectures.
20
21// RegisterInfo purge
22use binaryninjacore_sys::*;
23use std::fmt::{Debug, Formatter};
24
25use crate::{
26    calling_convention::CoreCallingConvention,
27    data_buffer::DataBuffer,
28    disassembly::InstructionTextToken,
29    ffi::INVALID_REGISTER,
30    function::{Function, Location, NativeBlock},
31    platform::Platform,
32    rc::*,
33    relocation::CoreRelocationHandler,
34    string::{IntoCStr, *},
35    types::{NameAndType, Type},
36    Endianness,
37};
38use std::collections::{HashMap, HashSet};
39use std::ops::Deref;
40use std::{
41    borrow::Borrow,
42    ffi::{c_char, c_void, CString},
43    hash::Hash,
44    mem::MaybeUninit,
45};
46
47use std::ptr::NonNull;
48
49use crate::function_recognizer::FunctionRecognizer;
50use crate::relocation::{CustomRelocationHandlerHandle, RelocationHandler};
51
52use crate::basic_block::BasicBlock;
53use crate::confidence::Conf;
54use crate::logger::Logger;
55use crate::low_level_il::expression::ValueExpr;
56use crate::low_level_il::lifting::{
57    get_default_flag_cond_llil, get_default_flag_write_llil, LowLevelILFlagWriteOp,
58};
59use crate::low_level_il::{LowLevelILMutableExpression, LowLevelILMutableFunction};
60
61pub mod basic_block;
62pub mod branches;
63pub mod flag;
64pub mod instruction;
65pub mod intrinsic;
66pub mod register;
67
68// Re-export all the submodules to keep from breaking everyone's code.
69// We split these out just to clarify each part, not necessarily to enforce an extra namespace.
70pub use basic_block::*;
71pub use branches::*;
72pub use flag::*;
73pub use instruction::*;
74pub use intrinsic::*;
75pub use register::*;
76
77/// The [`Architecture`] trait is the backbone of Binary Ninja's analysis capabilities. It tells the
78/// core how to interpret the machine code into LLIL, a generic intermediate representation for
79/// program analysis.
80///
81/// To add support for a new Instruction Set Architecture (ISA), you must implement this trait and
82/// register it. The core analysis loop relies on your implementation for three critical stages:
83///
84/// 1.  **Disassembly ([`Architecture::instruction_text`])**: Machine code into human-readable text (e.g., `55` -> `push rbp`).
85/// 2.  **Control Flow Analysis ([`Architecture::instruction_info`])**: Identifying where execution goes next (e.g., "This is a `call` instruction, it targets address `0x401000`").
86/// 3.  **Lifting ([`Architecture::instruction_llil`])**: Translating machine code into **Low Level Intermediate Language (LLIL)**, which enables decompilation and automated analysis.
87pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
88    type Handle: Borrow<Self> + Clone;
89
90    /// The [`RegisterInfo`] associated with this architecture.
91    type RegisterInfo: RegisterInfo<RegType = Self::Register>;
92
93    /// The [`Register`] associated with this architecture.
94    type Register: Register<InfoType = Self::RegisterInfo>;
95
96    /// The [`RegisterStackInfo`] associated with this architecture.
97    ///
98    /// You may only set this to [`UnusedRegisterStack`] if [`Self::RegisterStack`] is as well.
99    type RegisterStackInfo: RegisterStackInfo<
100        RegType = Self::Register,
101        RegInfoType = Self::RegisterInfo,
102        RegStackType = Self::RegisterStack,
103    >;
104
105    /// The [`RegisterStack`] associated with this architecture.
106    ///
107    /// If you do not override [`Architecture::register_stack_from_id`] and [`Architecture::register_stacks`],
108    /// you may set this to [`UnusedRegisterStack`].
109    type RegisterStack: RegisterStack<
110        InfoType = Self::RegisterStackInfo,
111        RegType = Self::Register,
112        RegInfoType = Self::RegisterInfo,
113    >;
114
115    /// The [`Flag`] associated with this architecture.
116    ///
117    /// If you do not override [`Architecture::flag_from_id`] and [`Architecture::flags`], you may
118    /// set this to [`UnusedFlag`].
119    type Flag: Flag<FlagClass = Self::FlagClass>;
120
121    /// The [`FlagWrite`] associated with this architecture.
122    ///
123    /// Can only be set to [`UnusedFlag`] if [`Self::Flag`] is as well. Otherwise, it is expected that
124    /// this points to a custom [`FlagWrite`] with the following functions defined:
125    ///
126    /// - [`Architecture::flag_write_types`]
127    /// - [`Architecture::flag_write_from_id`]
128    type FlagWrite: FlagWrite<FlagType = Self::Flag, FlagClass = Self::FlagClass>;
129
130    /// The [`FlagClass`] associated with this architecture.
131    ///
132    /// Can only be set to [`UnusedFlag`] if [`Self::Flag`] is as well. Otherwise, it is expected that
133    /// this points to a custom [`FlagClass`] with the following functions defined:
134    ///
135    /// - [`Architecture::flag_classes`]
136    /// - [`Architecture::flag_class_from_id`]
137    type FlagClass: FlagClass;
138
139    /// The [`FlagGroup`] associated with this architecture.
140    ///
141    /// Can only be set to [`UnusedFlag`] if [`Self::Flag`] is as well. Otherwise, it is expected that
142    /// this points to a custom [`FlagGroup`] with the following functions defined:
143    ///
144    /// - [`Architecture::flag_groups`]
145    /// - [`Architecture::flag_group_from_id`]
146    type FlagGroup: FlagGroup<FlagType = Self::Flag, FlagClass = Self::FlagClass>;
147
148    type Intrinsic: Intrinsic;
149
150    fn endianness(&self) -> Endianness;
151    fn address_size(&self) -> usize;
152    fn default_integer_size(&self) -> usize;
153    fn instruction_alignment(&self) -> usize;
154
155    /// The maximum length of an instruction in bytes. This is used to determine the size of the buffer
156    /// given to callbacks such as [`Architecture::instruction_info`], [`Architecture::instruction_text`]
157    /// and [`Architecture::instruction_llil`].
158    ///
159    /// NOTE: The maximum **CANNOT** be greater than 256.
160    fn max_instr_len(&self) -> usize;
161
162    /// How many bytes to display in the opcode space before displaying a `...`, typically set to
163    /// the [`Architecture::max_instr_len`], however, can be overridden to display a truncated opcode.
164    fn opcode_display_len(&self) -> usize {
165        self.max_instr_len()
166    }
167
168    /// In binaries with multiple architectures, you may wish to associate a specific architecture
169    /// with a given virtual address. This can be seen in armv7 where odd addresses are associated
170    /// with the thumb architecture.
171    fn associated_arch_by_addr(&self, _addr: u64) -> CoreArchitecture {
172        *self.as_ref()
173    }
174
175    /// Returns the [`InstructionInfo`] at the given virtual address with `data`.
176    ///
177    /// The [`InstructionInfo`] object should always fill the proper length and branches if not, the
178    /// next instruction will likely be incorrect.
179    fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo>;
180
181    /// Disassembles a raw byte sequence into a human-readable list of text tokens.
182    ///
183    /// This function is responsible for the visual representation of assembly instructions.
184    /// It does *not* define semantics (use [`Architecture::instruction_llil`] for that);
185    /// it simply tells the UI how to print the instruction.
186    ///
187    /// # Returns
188    ///
189    /// An `Option` containing a tuple:
190    ///
191    /// * `usize`: The size of the decoded instruction in bytes. Is used to advance to the next instruction.
192    /// * `Vec<InstructionTextToken>`: A list of text tokens representing the instruction.
193    ///
194    /// Returns `None` if the bytes do not form a valid instruction.
195    fn instruction_text(
196        &self,
197        data: &[u8],
198        addr: u64,
199    ) -> Option<(usize, Vec<InstructionTextToken>)>;
200
201    /// Disassembles a raw byte sequence into a human-readable list of text tokens.
202    ///
203    /// This function is responsible for the visual representation of assembly instructions.
204    /// It does *not* define semantics (use [`Architecture::instruction_llil`] for that);
205    /// it simply tells the UI how to print the instruction. This variant includes contextual data, which
206    /// can be produced by analyze_basic_blocks
207    ///
208    /// # Returns
209    ///
210    /// An `Option` containing a tuple:
211    ///
212    /// * `usize`: The size of the decoded instruction in bytes. Is used to advance to the next instruction.
213    /// * `Vec<InstructionTextToken>`: A list of text tokens representing the instruction.
214    ///
215    /// Returns `None` if the bytes do not form a valid instruction.
216    fn instruction_text_with_context(
217        &self,
218        data: &[u8],
219        addr: u64,
220        _context: Option<NonNull<c_void>>,
221    ) -> Option<(usize, Vec<InstructionTextToken>)> {
222        self.instruction_text(data, addr)
223    }
224
225    // TODO: Why do we need to return a boolean here? Does `None` not represent the same thing?
226    /// Appends arbitrary low-level il instructions to `il`.
227    ///
228    /// If `None` is returned, no instructions were appended and the data is invalid. If `Some` is returned,
229    /// the instructions consumed length is returned (necessary for variable length instruction decoding).
230    fn instruction_llil(
231        &self,
232        data: &[u8],
233        addr: u64,
234        il: &LowLevelILMutableFunction,
235    ) -> Option<(usize, bool)>;
236
237    /// Performs basic block recovery and commits the results to the function analysis.
238    ///
239    /// NOTE: Only implement this method if function-level analysis is required. Otherwise, do not
240    /// implement to let default basic block analysis take place.
241    fn analyze_basic_blocks(
242        &self,
243        function: &mut Function,
244        context: &mut BasicBlockAnalysisContext,
245    ) {
246        unsafe {
247            BNArchitectureDefaultAnalyzeBasicBlocks(function.handle, context.handle);
248        }
249    }
250
251    fn lift_function(
252        &self,
253        function: LowLevelILMutableFunction,
254        context: &mut FunctionLifterContext,
255    ) -> bool {
256        unsafe { BNArchitectureDefaultLiftFunction(function.handle, context.handle) }
257    }
258
259    /// Fallback flag value calculation path. This method is invoked when the core is unable to
260    /// recover the flag using semantics and resorts to emitting instructions that explicitly set each
261    /// observed flag to the value of an expression returned by this function.
262    ///
263    /// This function *MUST NOT* append instructions that have side effects.
264    ///
265    /// This function *MUST NOT* observe the values of other flags.
266    ///
267    /// This function *MUST* return `None` or an expression representing a boolean value.
268    fn flag_write_llil<'a>(
269        &self,
270        flag: Self::Flag,
271        flag_write_type: Self::FlagWrite,
272        op: LowLevelILFlagWriteOp<Self::Register>,
273        il: &'a LowLevelILMutableFunction,
274    ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
275        let role = flag.role(flag_write_type.class());
276        Some(get_default_flag_write_llil(self, role, op, il))
277    }
278
279    /// Determines what flags need to be examined to attempt automatic recovery of the flag uses semantics.
280    ///
281    /// If automatic recovery is not possible, the [`Architecture::flag_cond_llil`] method will be invoked
282    /// to give this [`Architecture`] implementation arbitrary control over the expression to be evaluated.
283    fn flags_required_for_flag_condition(
284        &self,
285        _condition: FlagCondition,
286        _class: Option<Self::FlagClass>,
287    ) -> Vec<Self::Flag> {
288        Vec::new()
289    }
290
291    /// This function *MUST NOT* append instructions that have side effects.
292    ///
293    /// This function *MUST NOT* observe the values of flags not returned by
294    /// `flags_required_for_flag_condition`.
295    ///
296    /// This function *MUST* return `None` or an expression representing a boolean value.
297    fn flag_cond_llil<'a>(
298        &self,
299        cond: FlagCondition,
300        class: Option<Self::FlagClass>,
301        il: &'a LowLevelILMutableFunction,
302    ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
303        Some(get_default_flag_cond_llil(self, cond, class, il))
304    }
305
306    /// Performs fallback resolution when the core was unable to recover the semantics of a
307    /// `LLIL_FLAG_GROUP` expression. This occurs when multiple instructions may have set the flags
308    /// at the flag group query, or when the `FlagGroup::flag_conditions()` map doesn't have an entry
309    /// for the `FlagClass` associated with the `FlagWrite` type of the expression that last set
310    /// the flags required by the `FlagGroup` `group`.
311    ///
312    /// In this fallback path, the `Architecture` must generate the boolean expression in terms of
313    /// the values of that flags returned by `group`'s `flags_required` method.
314    ///
315    /// This function must return an expression representing a boolean (as in, size of `0`) value.
316    /// It is not allowed to add any instructions that can cause side effects.
317    ///
318    /// This function must not observe the values of any flag not returned by `group`'s
319    /// `flags_required` method.
320    fn flag_group_llil<'a>(
321        &self,
322        _group: Self::FlagGroup,
323        _il: &'a LowLevelILMutableFunction,
324    ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
325        None
326    }
327
328    fn registers_all(&self) -> Vec<Self::Register>;
329
330    fn register_from_id(&self, id: RegisterId) -> Option<Self::Register>;
331
332    fn registers_full_width(&self) -> Vec<Self::Register>;
333
334    // TODO: Document the difference between global and system registers.
335    fn registers_global(&self) -> Vec<Self::Register> {
336        Vec::new()
337    }
338
339    // TODO: Document the difference between global and system registers.
340    fn registers_system(&self) -> Vec<Self::Register> {
341        Vec::new()
342    }
343
344    fn stack_pointer_reg(&self) -> Option<Self::Register>;
345
346    fn link_reg(&self) -> Option<Self::Register> {
347        None
348    }
349
350    /// List of concrete register stacks for this architecture.
351    ///
352    /// You **must** override the following functions as well:
353    ///
354    /// - [`Architecture::register_stack_from_id`]
355    fn register_stacks(&self) -> Vec<Self::RegisterStack> {
356        Vec::new()
357    }
358
359    /// Get the [`Self::RegisterStack`] associated with the given [`RegisterStackId`].
360    ///
361    /// You **must** override the following functions as well:
362    ///
363    /// - [`Architecture::register_stacks`]
364    fn register_stack_from_id(&self, _id: RegisterStackId) -> Option<Self::RegisterStack> {
365        None
366    }
367
368    /// List of concrete flags for this architecture.
369    ///
370    /// You **must** override the following functions as well:
371    ///
372    /// - [`Architecture::flag_from_id`]
373    /// - [`Architecture::flag_write_types`]
374    /// - [`Architecture::flag_write_from_id`]
375    /// - [`Architecture::flag_classes`]
376    /// - [`Architecture::flag_class_from_id`]
377    /// - [`Architecture::flag_groups`]
378    /// - [`Architecture::flag_group_from_id`]
379    fn flags(&self) -> Vec<Self::Flag> {
380        Vec::new()
381    }
382
383    /// Get the [`Self::Flag`] associated with the given [`FlagId`].
384    ///
385    /// You **must** override the following functions as well:
386    ///
387    /// - [`Architecture::flags`]
388    /// - [`Architecture::flag_write_types`]
389    /// - [`Architecture::flag_write_from_id`]
390    /// - [`Architecture::flag_classes`]
391    /// - [`Architecture::flag_class_from_id`]
392    /// - [`Architecture::flag_groups`]
393    /// - [`Architecture::flag_group_from_id`]
394    fn flag_from_id(&self, _id: FlagId) -> Option<Self::Flag> {
395        None
396    }
397
398    /// List of concrete flag write types for this architecture.
399    ///
400    /// You **must** override the following functions as well:
401    ///
402    /// - [`Architecture::flags`]
403    /// - [`Architecture::flag_from_id`]
404    /// - [`Architecture::flag_write_from_id`]
405    /// - [`Architecture::flag_classes`]
406    /// - [`Architecture::flag_class_from_id`]
407    /// - [`Architecture::flag_groups`]
408    /// - [`Architecture::flag_group_from_id`]
409    fn flag_write_types(&self) -> Vec<Self::FlagWrite> {
410        Vec::new()
411    }
412
413    /// Get the [`Self::FlagWrite`] associated with the given [`FlagWriteId`].
414    ///
415    /// You **must** override the following functions as well:
416    ///
417    /// - [`Architecture::flags`]
418    /// - [`Architecture::flag_from_id`]
419    /// - [`Architecture::flag_write_types`]
420    /// - [`Architecture::flag_classes`]
421    /// - [`Architecture::flag_class_from_id`]
422    /// - [`Architecture::flag_groups`]
423    /// - [`Architecture::flag_group_from_id`]
424    fn flag_write_from_id(&self, _id: FlagWriteId) -> Option<Self::FlagWrite> {
425        None
426    }
427
428    /// List of concrete flag classes for this architecture.
429    ///
430    /// You **must** override the following functions as well:
431    ///
432    /// - [`Architecture::flags`]
433    /// - [`Architecture::flag_from_id`]
434    /// - [`Architecture::flag_write_from_id`]
435    /// - [`Architecture::flag_class_from_id`]
436    /// - [`Architecture::flag_groups`]
437    /// - [`Architecture::flag_group_from_id`]
438    fn flag_classes(&self) -> Vec<Self::FlagClass> {
439        Vec::new()
440    }
441
442    /// Get the [`Self::FlagClass`] associated with the given [`FlagClassId`].
443    ///
444    /// You **must** override the following functions as well:
445    ///
446    /// - [`Architecture::flags`]
447    /// - [`Architecture::flag_from_id`]
448    /// - [`Architecture::flag_write_from_id`]
449    /// - [`Architecture::flag_classes`]
450    /// - [`Architecture::flag_groups`]
451    /// - [`Architecture::flag_group_from_id`]
452    fn flag_class_from_id(&self, _id: FlagClassId) -> Option<Self::FlagClass> {
453        None
454    }
455
456    /// List of concrete flag groups for this architecture.
457    ///
458    /// You **must** override the following functions as well:
459    ///
460    /// - [`Architecture::flags`]
461    /// - [`Architecture::flag_from_id`]
462    /// - [`Architecture::flag_write_from_id`]
463    /// - [`Architecture::flag_classes`]
464    /// - [`Architecture::flag_class_from_id`]
465    /// - [`Architecture::flag_group_from_id`]
466    fn flag_groups(&self) -> Vec<Self::FlagGroup> {
467        Vec::new()
468    }
469
470    /// Get the [`Self::FlagGroup`] associated with the given [`FlagGroupId`].
471    ///
472    /// You **must** override the following functions as well:
473    ///
474    /// - [`Architecture::flags`]
475    /// - [`Architecture::flag_from_id`]
476    /// - [`Architecture::flag_write_from_id`]
477    /// - [`Architecture::flag_classes`]
478    /// - [`Architecture::flag_class_from_id`]
479    /// - [`Architecture::flag_groups`]
480    fn flag_group_from_id(&self, _id: FlagGroupId) -> Option<Self::FlagGroup> {
481        None
482    }
483
484    /// List of concrete intrinsics for this architecture.
485    ///
486    /// You **must** override the following functions as well:
487    ///
488    /// - [`Architecture::intrinsic_from_id`]
489    fn intrinsics(&self) -> Vec<Self::Intrinsic> {
490        Vec::new()
491    }
492
493    fn intrinsic_class(&self, _id: IntrinsicId) -> BNIntrinsicClass {
494        BNIntrinsicClass::GeneralIntrinsicClass
495    }
496
497    /// Get the [`Self::Intrinsic`] associated with the given [`IntrinsicId`].
498    ///
499    /// You **must** override the following functions as well:
500    ///
501    /// - [`Architecture::intrinsics`]
502    fn intrinsic_from_id(&self, _id: IntrinsicId) -> Option<Self::Intrinsic> {
503        None
504    }
505
506    /// Let the UI display this patch option.
507    ///
508    /// If set to true, you must override [`Architecture::assemble`].
509    fn can_assemble(&self) -> bool {
510        false
511    }
512
513    /// Assemble the code at the specified address and return the machine code in bytes.
514    ///
515    /// If overridden, you must set [`Architecture::can_assemble`] to `true`.
516    fn assemble(&self, _code: &str, _addr: u64) -> Result<Vec<u8>, String> {
517        Err("Assemble unsupported".into())
518    }
519
520    /// Let the UI display this patch option.
521    ///
522    /// If set to true, you must override [`Architecture::invert_branch`].
523    fn is_never_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
524        self.is_invert_branch_patch_available(data, addr)
525    }
526
527    /// Let the UI display this patch option.
528    ///
529    /// If set to true, you must override [`Architecture::always_branch`].
530    fn is_always_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool {
531        false
532    }
533
534    /// Let the UI display this patch option.
535    ///
536    /// If set to true, you must override [`Architecture::invert_branch`].
537    fn is_invert_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool {
538        false
539    }
540
541    /// Let the UI display this patch option.
542    ///
543    /// If set to true, you must override [`Architecture::skip_and_return_value`].
544    fn is_skip_and_return_zero_patch_available(&self, data: &[u8], addr: u64) -> bool {
545        self.is_skip_and_return_value_patch_available(data, addr)
546    }
547
548    /// Let the UI display this patch option.
549    ///
550    /// If set to true, you must override [`Architecture::skip_and_return_value`].
551    fn is_skip_and_return_value_patch_available(&self, _data: &[u8], _addr: u64) -> bool {
552        false
553    }
554
555    fn convert_to_nop(&self, _data: &mut [u8], _addr: u64) -> bool {
556        false
557    }
558
559    /// Patch the instruction to always branch.
560    ///
561    /// If overridden, you must also override [`Architecture::is_always_branch_patch_available`].
562    fn always_branch(&self, _data: &mut [u8], _addr: u64) -> bool {
563        false
564    }
565
566    /// Patch the instruction to invert the branch condition.
567    ///
568    /// If overridden, you must also override [`Architecture::is_invert_branch_patch_available`].
569    fn invert_branch(&self, _data: &mut [u8], _addr: u64) -> bool {
570        false
571    }
572
573    /// Patch the instruction to skip and return value.
574    ///
575    /// If overridden, you must also override [`Architecture::is_skip_and_return_value_patch_available`].
576    fn skip_and_return_value(&self, _data: &mut [u8], _addr: u64, _value: u64) -> bool {
577        false
578    }
579
580    fn handle(&self) -> Self::Handle;
581}
582
583pub trait ArchitectureWithFunctionContext: Architecture {
584    type FunctionArchContext: Send + Sync + 'static;
585
586    fn instruction_text_with_typed_context(
587        &self,
588        data: &[u8],
589        addr: u64,
590        _context: Option<&Self::FunctionArchContext>,
591    ) -> Option<(usize, Vec<InstructionTextToken>)> {
592        self.instruction_text(data, addr)
593    }
594}
595
596pub struct FunctionLifterContext {
597    pub(crate) handle: *mut BNFunctionLifterContext,
598    pub function: Ref<LowLevelILMutableFunction>,
599    pub platform: Ref<Platform>,
600    pub logger: Ref<Logger>,
601    pub blocks: Vec<Ref<BasicBlock<NativeBlock>>>,
602    pub no_return_calls: HashSet<Location>,
603    pub contextual_returns: HashMap<Location, bool>,
604    pub inlined_remapping: HashMap<Location, Location>,
605    pub user_indirect_branches: HashMap<Location, HashSet<Location>>,
606    pub auto_indirect_branches: HashMap<Location, HashSet<Location>>,
607    pub inlined_calls: HashSet<u64>,
608}
609
610unsafe fn lifter_context_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
611    if len == 0 {
612        &[]
613    } else {
614        debug_assert!(!ptr.is_null());
615        unsafe { std::slice::from_raw_parts(ptr, len) }
616    }
617}
618
619impl FunctionLifterContext {
620    pub unsafe fn from_raw(
621        function: *mut BNLowLevelILFunction,
622        handle: *mut BNFunctionLifterContext,
623    ) -> Self {
624        Self::from_raw_with_arch(function, handle, None)
625    }
626
627    pub(crate) unsafe fn from_raw_with_arch(
628        function: *mut BNLowLevelILFunction,
629        handle: *mut BNFunctionLifterContext,
630        arch: Option<CoreArchitecture>,
631    ) -> Self {
632        debug_assert!(!function.is_null());
633        debug_assert!(!handle.is_null());
634        let flc_ref = &*handle;
635        let platform = unsafe { Platform::ref_from_raw(BNNewPlatformReference(flc_ref.platform)) };
636        let logger = unsafe { Logger::ref_from_raw(BNNewLoggerReference(flc_ref.logger)) };
637
638        let mut blocks = Vec::new();
639        for i in 0..flc_ref.basicBlockCount {
640            let block = unsafe {
641                Some(BasicBlock::ref_from_raw(
642                    BNNewBasicBlockReference(*flc_ref.basicBlocks.add(i)),
643                    NativeBlock::new(),
644                ))
645            };
646
647            blocks.push(block.unwrap());
648        }
649
650        let raw_no_return_calls: &[BNArchitectureAndAddress] =
651            lifter_context_slice(flc_ref.noReturnCalls, flc_ref.noReturnCallsCount);
652        let no_return_calls: HashSet<Location> =
653            raw_no_return_calls.iter().map(Location::from).collect();
654
655        let raw_contextual_return_locs: &[BNArchitectureAndAddress] = unsafe {
656            lifter_context_slice(
657                flc_ref.contextualFunctionReturnLocations,
658                flc_ref.contextualFunctionReturnCount,
659            )
660        };
661        let raw_contextual_return_vals: &[bool] = unsafe {
662            lifter_context_slice(
663                flc_ref.contextualFunctionReturnValues,
664                flc_ref.contextualFunctionReturnCount,
665            )
666        };
667        let contextual_returns: HashMap<Location, bool> = raw_contextual_return_locs
668            .iter()
669            .map(Location::from)
670            .zip(raw_contextual_return_vals.iter().copied())
671            .collect();
672
673        let inlined_remapping: HashMap<Location, Location> = {
674            let raw_inline_remap_locs: &[BNArchitectureAndAddress] = lifter_context_slice(
675                flc_ref.inlinedRemappingKeys,
676                flc_ref.inlinedRemappingEntryCount,
677            );
678
679            let raw_inline_remap_dests: &[BNArchitectureAndAddress] = lifter_context_slice(
680                flc_ref.inlinedRemappingValues,
681                flc_ref.inlinedRemappingEntryCount,
682            );
683
684            raw_inline_remap_locs
685                .iter()
686                .map(Location::from)
687                .zip(raw_inline_remap_dests.iter().map(Location::from))
688                .collect()
689        };
690
691        let mut user_indirect_branches: HashMap<Location, HashSet<Location>> = HashMap::new();
692        let mut auto_indirect_branches: HashMap<Location, HashSet<Location>> = HashMap::new();
693        for i in 0..flc_ref.indirectBranchesCount {
694            let entry = unsafe { *flc_ref.indirectBranches.add(i) };
695            let src = Location::new(
696                Some(CoreArchitecture::from_raw(entry.sourceArch)),
697                entry.sourceAddr,
698            );
699            let dest = Location::new(
700                Some(CoreArchitecture::from_raw(entry.destArch)),
701                entry.destAddr,
702            );
703            if entry.autoDefined {
704                auto_indirect_branches.entry(src).or_default().insert(dest);
705            } else {
706                user_indirect_branches.entry(src).or_default().insert(dest);
707            }
708        }
709
710        let inlined_calls: HashSet<u64> =
711            lifter_context_slice(flc_ref.inlinedCalls, flc_ref.inlinedCallsCount)
712                .iter()
713                .copied()
714                .collect();
715
716        FunctionLifterContext {
717            handle,
718            function: LowLevelILMutableFunction::ref_from_raw_with_arch(
719                BNNewLowLevelILFunctionReference(function),
720                arch,
721            ),
722            platform,
723            logger,
724            blocks,
725            no_return_calls,
726            contextual_returns,
727            inlined_remapping,
728            user_indirect_branches,
729            auto_indirect_branches,
730            inlined_calls,
731        }
732    }
733
734    pub fn prepare_block_translation(
735        &self,
736        func: &LowLevelILMutableFunction,
737        arch: &CoreArchitecture,
738        address: u64,
739    ) {
740        unsafe {
741            BNPrepareBlockTranslation(func.handle, arch.handle, address);
742        }
743    }
744
745    pub fn get_function_arch_context<A: ArchitectureWithFunctionContext>(
746        &self,
747        _arch: &A,
748    ) -> Option<&A::FunctionArchContext> {
749        unsafe {
750            let ptr = (*self.handle).functionArchContext;
751            if ptr.is_null() {
752                None
753            } else {
754                Some(&*(ptr as *const A::FunctionArchContext))
755            }
756        }
757    }
758}
759
760// TODO: WTF?!?!?!?
761pub struct CoreArchitectureList(*mut *mut BNArchitecture, usize);
762
763impl Deref for CoreArchitectureList {
764    type Target = [CoreArchitecture];
765
766    fn deref(&self) -> &Self::Target {
767        unsafe { std::slice::from_raw_parts_mut(self.0 as *mut CoreArchitecture, self.1) }
768    }
769}
770
771impl Drop for CoreArchitectureList {
772    fn drop(&mut self) {
773        unsafe {
774            BNFreeArchitectureList(self.0);
775        }
776    }
777}
778
779#[derive(Copy, Clone, Eq, PartialEq, Hash)]
780pub struct CoreArchitecture {
781    pub(crate) handle: *mut BNArchitecture,
782}
783
784impl CoreArchitecture {
785    // TODO: Leave a note on architecture lifetimes. Specifically that they are never freed.
786    pub unsafe fn from_raw(handle: *mut BNArchitecture) -> Self {
787        debug_assert!(!handle.is_null());
788        CoreArchitecture { handle }
789    }
790
791    pub fn list_all() -> CoreArchitectureList {
792        let mut count: usize = 0;
793        let archs = unsafe { BNGetArchitectureList(&mut count) };
794
795        CoreArchitectureList(archs, count)
796    }
797
798    pub fn by_name(name: &str) -> Option<Self> {
799        let name = name.to_cstr();
800        let handle = unsafe { BNGetArchitectureByName(name.as_ptr()) };
801        match handle.is_null() {
802            false => Some(CoreArchitecture { handle }),
803            true => None,
804        }
805    }
806
807    pub fn name(&self) -> String {
808        unsafe { BnString::into_string(BNGetArchitectureName(self.handle)) }
809    }
810
811    pub fn register_stack_for_register(&self, reg: CoreRegister) -> Option<CoreRegisterStack> {
812        match unsafe { BNGetArchitectureRegisterStackForRegister(self.handle, reg.id().0) } {
813            INVALID_REGISTER => None,
814            reg_stack => CoreRegisterStack::new(*self, RegisterStackId::from(reg_stack)),
815        }
816    }
817}
818
819unsafe impl Send for CoreArchitecture {}
820unsafe impl Sync for CoreArchitecture {}
821
822impl AsRef<CoreArchitecture> for CoreArchitecture {
823    fn as_ref(&self) -> &Self {
824        self
825    }
826}
827
828impl Architecture for CoreArchitecture {
829    type Handle = Self;
830
831    type RegisterInfo = CoreRegisterInfo;
832    type Register = CoreRegister;
833    type RegisterStackInfo = CoreRegisterStackInfo;
834    type RegisterStack = CoreRegisterStack;
835    type Flag = CoreFlag;
836    type FlagWrite = CoreFlagWrite;
837    type FlagClass = CoreFlagClass;
838    type FlagGroup = CoreFlagGroup;
839    type Intrinsic = CoreIntrinsic;
840
841    fn endianness(&self) -> Endianness {
842        unsafe { BNGetArchitectureEndianness(self.handle) }
843    }
844
845    fn address_size(&self) -> usize {
846        unsafe { BNGetArchitectureAddressSize(self.handle) }
847    }
848
849    fn default_integer_size(&self) -> usize {
850        unsafe { BNGetArchitectureDefaultIntegerSize(self.handle) }
851    }
852
853    fn instruction_alignment(&self) -> usize {
854        unsafe { BNGetArchitectureInstructionAlignment(self.handle) }
855    }
856
857    fn max_instr_len(&self) -> usize {
858        unsafe { BNGetArchitectureMaxInstructionLength(self.handle) }
859    }
860
861    fn opcode_display_len(&self) -> usize {
862        unsafe { BNGetArchitectureOpcodeDisplayLength(self.handle) }
863    }
864
865    fn associated_arch_by_addr(&self, addr: u64) -> CoreArchitecture {
866        let handle = unsafe { BNGetAssociatedArchitectureByAddress(self.handle, addr as *mut _) };
867        CoreArchitecture { handle }
868    }
869
870    fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo> {
871        let mut info = BNInstructionInfo::default();
872        if unsafe { BNGetInstructionInfo(self.handle, data.as_ptr(), addr, data.len(), &mut info) }
873        {
874            Some(info.into())
875        } else {
876            None
877        }
878    }
879
880    fn instruction_text(
881        &self,
882        data: &[u8],
883        addr: u64,
884    ) -> Option<(usize, Vec<InstructionTextToken>)> {
885        let mut consumed = data.len();
886        let mut count: usize = 0;
887        let mut result: *mut BNInstructionTextToken = std::ptr::null_mut();
888
889        unsafe {
890            if BNGetInstructionText(
891                self.handle,
892                data.as_ptr(),
893                addr,
894                &mut consumed,
895                &mut result,
896                &mut count,
897            ) {
898                let instr_text_tokens = std::slice::from_raw_parts(result, count)
899                    .iter()
900                    .map(InstructionTextToken::from_raw)
901                    .collect();
902                BNFreeInstructionText(result, count);
903                Some((consumed, instr_text_tokens))
904            } else {
905                None
906            }
907        }
908    }
909
910    fn instruction_text_with_context(
911        &self,
912        data: &[u8],
913        addr: u64,
914        context: Option<NonNull<c_void>>,
915    ) -> Option<(usize, Vec<InstructionTextToken>)> {
916        let mut consumed = data.len();
917        let mut count: usize = 0;
918        let mut result: *mut BNInstructionTextToken = std::ptr::null_mut();
919        let ctx_ptr: *mut c_void = context.map_or(std::ptr::null_mut(), |p| p.as_ptr());
920        unsafe {
921            if BNGetInstructionTextWithContext(
922                self.handle,
923                data.as_ptr(),
924                addr,
925                &mut consumed,
926                ctx_ptr,
927                &mut result,
928                &mut count,
929            ) {
930                let instr_text_tokens = std::slice::from_raw_parts(result, count)
931                    .iter()
932                    .map(InstructionTextToken::from_raw)
933                    .collect();
934                BNFreeInstructionText(result, count);
935                Some((consumed, instr_text_tokens))
936            } else {
937                None
938            }
939        }
940    }
941
942    fn instruction_llil(
943        &self,
944        data: &[u8],
945        addr: u64,
946        il: &LowLevelILMutableFunction,
947    ) -> Option<(usize, bool)> {
948        let mut size = data.len();
949        let success = unsafe {
950            BNGetInstructionLowLevelIL(
951                self.handle,
952                data.as_ptr(),
953                addr,
954                &mut size as *mut _,
955                il.handle,
956            )
957        };
958
959        if !success {
960            None
961        } else {
962            Some((size, true))
963        }
964    }
965
966    /// Performs basic block recovery and commits the results to the function analysis.
967    ///
968    /// NOTE: Only implement this method if function-level analysis is required. Otherwise, do not
969    /// implement to let default basic block analysis take place.
970    ///
971    /// NOTE: The default implementation exists in C++ here: <https://github.com/Vector35/binaryninja-api/blob/dev/defaultabb.cpp>
972    fn analyze_basic_blocks(
973        &self,
974        function: &mut Function,
975        context: &mut BasicBlockAnalysisContext,
976    ) {
977        unsafe {
978            BNArchitectureAnalyzeBasicBlocks(self.handle, function.handle, context.handle);
979        }
980    }
981
982    fn lift_function(
983        &self,
984        function: LowLevelILMutableFunction,
985        context: &mut FunctionLifterContext,
986    ) -> bool {
987        unsafe { BNArchitectureLiftFunction(self.handle, function.handle, context.handle) }
988    }
989
990    fn flag_write_llil<'a>(
991        &self,
992        _flag: Self::Flag,
993        _flag_write: Self::FlagWrite,
994        _op: LowLevelILFlagWriteOp<Self::Register>,
995        _il: &'a LowLevelILMutableFunction,
996    ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
997        None
998    }
999
1000    fn flags_required_for_flag_condition(
1001        &self,
1002        condition: FlagCondition,
1003        class: Option<Self::FlagClass>,
1004    ) -> Vec<Self::Flag> {
1005        let class_id_raw = class.map(|c| c.id().0).unwrap_or(0);
1006
1007        unsafe {
1008            let mut count: usize = 0;
1009            let flags = BNGetArchitectureFlagsRequiredForFlagCondition(
1010                self.handle,
1011                condition,
1012                class_id_raw,
1013                &mut count,
1014            );
1015
1016            let ret = std::slice::from_raw_parts(flags, count)
1017                .iter()
1018                .map(|&id| FlagId::from(id))
1019                .filter_map(|flag| CoreFlag::new(*self, flag))
1020                .collect();
1021
1022            BNFreeRegisterList(flags);
1023
1024            ret
1025        }
1026    }
1027
1028    fn flag_cond_llil<'a>(
1029        &self,
1030        _cond: FlagCondition,
1031        _class: Option<Self::FlagClass>,
1032        _il: &'a LowLevelILMutableFunction,
1033    ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
1034        None
1035    }
1036
1037    fn flag_group_llil<'a>(
1038        &self,
1039        _group: Self::FlagGroup,
1040        _il: &'a LowLevelILMutableFunction,
1041    ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
1042        None
1043    }
1044
1045    fn registers_all(&self) -> Vec<CoreRegister> {
1046        unsafe {
1047            let mut count: usize = 0;
1048            let registers_raw = BNGetAllArchitectureRegisters(self.handle, &mut count);
1049
1050            let ret = std::slice::from_raw_parts(registers_raw, count)
1051                .iter()
1052                .map(|&id| RegisterId::from(id))
1053                .filter_map(|reg| CoreRegister::new(*self, reg))
1054                .collect();
1055
1056            BNFreeRegisterList(registers_raw);
1057
1058            ret
1059        }
1060    }
1061
1062    fn register_from_id(&self, id: RegisterId) -> Option<CoreRegister> {
1063        CoreRegister::new(*self, id)
1064    }
1065
1066    fn registers_full_width(&self) -> Vec<CoreRegister> {
1067        unsafe {
1068            let mut count: usize = 0;
1069            let registers_raw = BNGetFullWidthArchitectureRegisters(self.handle, &mut count);
1070
1071            let ret = std::slice::from_raw_parts(registers_raw, count)
1072                .iter()
1073                .map(|&id| RegisterId::from(id))
1074                .filter_map(|reg| CoreRegister::new(*self, reg))
1075                .collect();
1076
1077            BNFreeRegisterList(registers_raw);
1078
1079            ret
1080        }
1081    }
1082
1083    fn registers_global(&self) -> Vec<CoreRegister> {
1084        unsafe {
1085            let mut count: usize = 0;
1086            let registers_raw = BNGetArchitectureGlobalRegisters(self.handle, &mut count);
1087
1088            let ret = std::slice::from_raw_parts(registers_raw, count)
1089                .iter()
1090                .map(|&id| RegisterId::from(id))
1091                .filter_map(|reg| CoreRegister::new(*self, reg))
1092                .collect();
1093
1094            BNFreeRegisterList(registers_raw);
1095
1096            ret
1097        }
1098    }
1099
1100    fn registers_system(&self) -> Vec<CoreRegister> {
1101        unsafe {
1102            let mut count: usize = 0;
1103            let registers_raw = BNGetArchitectureSystemRegisters(self.handle, &mut count);
1104
1105            let ret = std::slice::from_raw_parts(registers_raw, count)
1106                .iter()
1107                .map(|&id| RegisterId::from(id))
1108                .filter_map(|reg| CoreRegister::new(*self, reg))
1109                .collect();
1110
1111            BNFreeRegisterList(registers_raw);
1112
1113            ret
1114        }
1115    }
1116
1117    fn stack_pointer_reg(&self) -> Option<CoreRegister> {
1118        match unsafe { BNGetArchitectureStackPointerRegister(self.handle) } {
1119            INVALID_REGISTER => None,
1120            reg => Some(CoreRegister::new(*self, reg.into())?),
1121        }
1122    }
1123
1124    fn link_reg(&self) -> Option<CoreRegister> {
1125        match unsafe { BNGetArchitectureLinkRegister(self.handle) } {
1126            INVALID_REGISTER => None,
1127            reg => Some(CoreRegister::new(*self, reg.into())?),
1128        }
1129    }
1130
1131    fn register_stacks(&self) -> Vec<CoreRegisterStack> {
1132        unsafe {
1133            let mut count: usize = 0;
1134            let reg_stacks_raw = BNGetAllArchitectureRegisterStacks(self.handle, &mut count);
1135
1136            let ret = std::slice::from_raw_parts(reg_stacks_raw, count)
1137                .iter()
1138                .map(|&id| RegisterStackId::from(id))
1139                .filter_map(|reg_stack| CoreRegisterStack::new(*self, reg_stack))
1140                .collect();
1141
1142            BNFreeRegisterList(reg_stacks_raw);
1143
1144            ret
1145        }
1146    }
1147
1148    fn register_stack_from_id(&self, id: RegisterStackId) -> Option<CoreRegisterStack> {
1149        CoreRegisterStack::new(*self, id)
1150    }
1151
1152    fn flags(&self) -> Vec<CoreFlag> {
1153        unsafe {
1154            let mut count: usize = 0;
1155            let flags_raw = BNGetAllArchitectureFlags(self.handle, &mut count);
1156
1157            let ret = std::slice::from_raw_parts(flags_raw, count)
1158                .iter()
1159                .map(|&id| FlagId::from(id))
1160                .filter_map(|flag| CoreFlag::new(*self, flag))
1161                .collect();
1162
1163            BNFreeRegisterList(flags_raw);
1164
1165            ret
1166        }
1167    }
1168
1169    fn flag_from_id(&self, id: FlagId) -> Option<CoreFlag> {
1170        CoreFlag::new(*self, id)
1171    }
1172
1173    fn flag_write_types(&self) -> Vec<CoreFlagWrite> {
1174        unsafe {
1175            let mut count: usize = 0;
1176            let flag_writes_raw = BNGetAllArchitectureFlagWriteTypes(self.handle, &mut count);
1177
1178            let ret = std::slice::from_raw_parts(flag_writes_raw, count)
1179                .iter()
1180                .map(|&id| FlagWriteId::from(id))
1181                .filter_map(|flag_write| CoreFlagWrite::new(*self, flag_write))
1182                .collect();
1183
1184            BNFreeRegisterList(flag_writes_raw);
1185
1186            ret
1187        }
1188    }
1189
1190    fn flag_write_from_id(&self, id: FlagWriteId) -> Option<CoreFlagWrite> {
1191        CoreFlagWrite::new(*self, id)
1192    }
1193
1194    fn flag_classes(&self) -> Vec<CoreFlagClass> {
1195        unsafe {
1196            let mut count: usize = 0;
1197            let flag_classes_raw = BNGetAllArchitectureSemanticFlagClasses(self.handle, &mut count);
1198
1199            let ret = std::slice::from_raw_parts(flag_classes_raw, count)
1200                .iter()
1201                .map(|&id| FlagClassId::from(id))
1202                .filter_map(|flag_class| CoreFlagClass::new(*self, flag_class))
1203                .collect();
1204
1205            BNFreeRegisterList(flag_classes_raw);
1206
1207            ret
1208        }
1209    }
1210
1211    fn flag_class_from_id(&self, id: FlagClassId) -> Option<CoreFlagClass> {
1212        CoreFlagClass::new(*self, id)
1213    }
1214
1215    fn flag_groups(&self) -> Vec<CoreFlagGroup> {
1216        unsafe {
1217            let mut count: usize = 0;
1218            let flag_groups_raw = BNGetAllArchitectureSemanticFlagGroups(self.handle, &mut count);
1219
1220            let ret = std::slice::from_raw_parts(flag_groups_raw, count)
1221                .iter()
1222                .map(|&id| FlagGroupId::from(id))
1223                .filter_map(|flag_group| CoreFlagGroup::new(*self, flag_group))
1224                .collect();
1225
1226            BNFreeRegisterList(flag_groups_raw);
1227
1228            ret
1229        }
1230    }
1231
1232    fn flag_group_from_id(&self, id: FlagGroupId) -> Option<CoreFlagGroup> {
1233        CoreFlagGroup::new(*self, id)
1234    }
1235
1236    fn intrinsics(&self) -> Vec<CoreIntrinsic> {
1237        unsafe {
1238            let mut count: usize = 0;
1239            let intrinsics_raw = BNGetAllArchitectureIntrinsics(self.handle, &mut count);
1240
1241            let intrinsics = std::slice::from_raw_parts_mut(intrinsics_raw, count)
1242                .iter()
1243                .map(|&id| IntrinsicId::from(id))
1244                .filter_map(|intrinsic| CoreIntrinsic::new(*self, intrinsic))
1245                .collect();
1246
1247            BNFreeRegisterList(intrinsics_raw);
1248
1249            intrinsics
1250        }
1251    }
1252
1253    fn intrinsic_from_id(&self, id: IntrinsicId) -> Option<CoreIntrinsic> {
1254        CoreIntrinsic::new(*self, id)
1255    }
1256
1257    fn can_assemble(&self) -> bool {
1258        unsafe { BNCanArchitectureAssemble(self.handle) }
1259    }
1260
1261    fn assemble(&self, code: &str, addr: u64) -> Result<Vec<u8>, String> {
1262        let code = CString::new(code).map_err(|_| "Invalid encoding in code string".to_string())?;
1263
1264        let result = DataBuffer::new(&[]);
1265        // TODO: This is actually a list of errors.
1266        let mut error_raw: *mut c_char = std::ptr::null_mut();
1267        let res = unsafe {
1268            BNAssemble(
1269                self.handle,
1270                code.as_ptr(),
1271                addr,
1272                result.as_raw(),
1273                &mut error_raw as *mut *mut c_char,
1274            )
1275        };
1276
1277        let error = raw_to_string(error_raw);
1278        unsafe {
1279            BNFreeString(error_raw);
1280        }
1281
1282        if res {
1283            Ok(result.get_data().to_vec())
1284        } else {
1285            Err(error.unwrap_or_else(|| "Assemble failed".into()))
1286        }
1287    }
1288
1289    fn is_never_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
1290        unsafe {
1291            BNIsArchitectureNeverBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
1292        }
1293    }
1294
1295    fn is_always_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
1296        unsafe {
1297            BNIsArchitectureAlwaysBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
1298        }
1299    }
1300
1301    fn is_invert_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
1302        unsafe {
1303            BNIsArchitectureInvertBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
1304        }
1305    }
1306
1307    fn is_skip_and_return_zero_patch_available(&self, data: &[u8], addr: u64) -> bool {
1308        unsafe {
1309            BNIsArchitectureSkipAndReturnZeroPatchAvailable(
1310                self.handle,
1311                data.as_ptr(),
1312                addr,
1313                data.len(),
1314            )
1315        }
1316    }
1317
1318    fn is_skip_and_return_value_patch_available(&self, data: &[u8], addr: u64) -> bool {
1319        unsafe {
1320            BNIsArchitectureSkipAndReturnValuePatchAvailable(
1321                self.handle,
1322                data.as_ptr(),
1323                addr,
1324                data.len(),
1325            )
1326        }
1327    }
1328
1329    fn convert_to_nop(&self, data: &mut [u8], addr: u64) -> bool {
1330        unsafe { BNArchitectureConvertToNop(self.handle, data.as_mut_ptr(), addr, data.len()) }
1331    }
1332
1333    fn always_branch(&self, data: &mut [u8], addr: u64) -> bool {
1334        unsafe { BNArchitectureAlwaysBranch(self.handle, data.as_mut_ptr(), addr, data.len()) }
1335    }
1336
1337    fn invert_branch(&self, data: &mut [u8], addr: u64) -> bool {
1338        unsafe { BNArchitectureInvertBranch(self.handle, data.as_mut_ptr(), addr, data.len()) }
1339    }
1340
1341    fn skip_and_return_value(&self, data: &mut [u8], addr: u64, value: u64) -> bool {
1342        unsafe {
1343            BNArchitectureSkipAndReturnValue(
1344                self.handle,
1345                data.as_mut_ptr(),
1346                addr,
1347                data.len(),
1348                value,
1349            )
1350        }
1351    }
1352
1353    fn handle(&self) -> CoreArchitecture {
1354        *self
1355    }
1356}
1357
1358impl Debug for CoreArchitecture {
1359    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1360        f.debug_struct("CoreArchitecture")
1361            .field("name", &self.name())
1362            .field("endianness", &self.endianness())
1363            .field("address_size", &self.address_size())
1364            .field("instruction_alignment", &self.instruction_alignment())
1365            .finish()
1366    }
1367}
1368
1369macro_rules! cc_func {
1370    ($get_name:ident, $get_api:ident, $set_name:ident, $set_api:ident) => {
1371        fn $get_name(&self) -> Option<Ref<CoreCallingConvention>> {
1372            let arch = self.as_ref();
1373
1374            unsafe {
1375                let cc = $get_api(arch.handle);
1376
1377                if cc.is_null() {
1378                    None
1379                } else {
1380                    Some(CoreCallingConvention::ref_from_raw(
1381                        cc,
1382                        self.as_ref().handle(),
1383                    ))
1384                }
1385            }
1386        }
1387
1388        fn $set_name(&self, cc: &CoreCallingConvention) {
1389            let arch = self.as_ref();
1390
1391            assert!(
1392                cc.arch_handle.borrow().as_ref().handle == arch.handle,
1393                "use of calling convention with non-matching architecture!"
1394            );
1395
1396            unsafe {
1397                $set_api(arch.handle, cc.handle);
1398            }
1399        }
1400    };
1401}
1402
1403/// Contains helper methods for all types implementing 'Architecture'
1404pub trait ArchitectureExt: Architecture {
1405    fn register_by_name(&self, name: &str) -> Option<Self::Register> {
1406        let name = name.to_cstr();
1407
1408        match unsafe { BNGetArchitectureRegisterByName(self.as_ref().handle, name.as_ptr()) } {
1409            INVALID_REGISTER => None,
1410            reg => self.register_from_id(reg.into()),
1411        }
1412    }
1413
1414    fn calling_convention_by_name(&self, name: &str) -> Option<Ref<CoreCallingConvention>> {
1415        let name = name.to_cstr();
1416        unsafe {
1417            let result = NonNull::new(BNGetArchitectureCallingConventionByName(
1418                self.as_ref().handle,
1419                name.as_ptr(),
1420            ))?;
1421            Some(CoreCallingConvention::ref_from_raw(
1422                result.as_ptr(),
1423                self.as_ref().handle(),
1424            ))
1425        }
1426    }
1427
1428    fn calling_conventions(&self) -> Array<CoreCallingConvention> {
1429        unsafe {
1430            let mut count = 0;
1431            let calling_convs =
1432                BNGetArchitectureCallingConventions(self.as_ref().handle, &mut count);
1433            Array::new(calling_convs, count, self.as_ref().handle())
1434        }
1435    }
1436
1437    cc_func!(
1438        get_default_calling_convention,
1439        BNGetArchitectureDefaultCallingConvention,
1440        set_default_calling_convention,
1441        BNSetArchitectureDefaultCallingConvention
1442    );
1443
1444    cc_func!(
1445        get_cdecl_calling_convention,
1446        BNGetArchitectureCdeclCallingConvention,
1447        set_cdecl_calling_convention,
1448        BNSetArchitectureCdeclCallingConvention
1449    );
1450
1451    cc_func!(
1452        get_stdcall_calling_convention,
1453        BNGetArchitectureStdcallCallingConvention,
1454        set_stdcall_calling_convention,
1455        BNSetArchitectureStdcallCallingConvention
1456    );
1457
1458    cc_func!(
1459        get_fastcall_calling_convention,
1460        BNGetArchitectureFastcallCallingConvention,
1461        set_fastcall_calling_convention,
1462        BNSetArchitectureFastcallCallingConvention
1463    );
1464
1465    fn standalone_platform(&self) -> Option<Ref<Platform>> {
1466        unsafe {
1467            let handle = BNGetArchitectureStandalonePlatform(self.as_ref().handle);
1468
1469            if handle.is_null() {
1470                return None;
1471            }
1472
1473            Some(Platform::ref_from_raw(handle))
1474        }
1475    }
1476
1477    fn relocation_handler(&self, view_name: &str) -> Option<Ref<CoreRelocationHandler>> {
1478        let view_name = match CString::new(view_name) {
1479            Ok(view_name) => view_name,
1480            Err(_) => return None,
1481        };
1482
1483        unsafe {
1484            let handle =
1485                BNArchitectureGetRelocationHandler(self.as_ref().handle, view_name.as_ptr());
1486
1487            if handle.is_null() {
1488                return None;
1489            }
1490
1491            Some(CoreRelocationHandler::ref_from_raw(handle))
1492        }
1493    }
1494
1495    fn register_relocation_handler<R, F>(&self, name: &str, func: F)
1496    where
1497        R: 'static
1498            + RelocationHandler<Handle = CustomRelocationHandlerHandle<R>>
1499            + Send
1500            + Sync
1501            + Sized,
1502        F: FnOnce(CustomRelocationHandlerHandle<R>, CoreRelocationHandler) -> R,
1503    {
1504        crate::relocation::register_relocation_handler(self.as_ref(), name, func);
1505    }
1506
1507    fn register_function_recognizer<R>(&self, recognizer: R)
1508    where
1509        R: 'static + FunctionRecognizer + Send + Sync + Sized,
1510    {
1511        crate::function_recognizer::register_arch_function_recognizer(self.as_ref(), recognizer);
1512    }
1513}
1514
1515impl<T: Architecture> ArchitectureExt for T {}
1516
1517/// Registers a new architecture with the given name.
1518///
1519/// NOTE: This function should only be called within `CorePluginInit`.
1520pub fn register_architecture<A, F>(name: &str, func: F) -> &'static A
1521where
1522    A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync + Sized,
1523    F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
1524{
1525    register_architecture_impl(name, func, |_| {})
1526}
1527
1528fn register_architecture_impl<A, F, C>(name: &str, func: F, customize: C) -> &'static A
1529where
1530    A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync + Sized,
1531    F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
1532    C: FnOnce(&mut BNCustomArchitecture),
1533{
1534    #[repr(C)]
1535    struct ArchitectureBuilder<A, F>
1536    where
1537        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1538        F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
1539    {
1540        arch: MaybeUninit<A>,
1541        func: Option<F>,
1542    }
1543
1544    extern "C" fn cb_init<A, F>(ctxt: *mut c_void, obj: *mut BNArchitecture)
1545    where
1546        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1547        F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
1548    {
1549        unsafe {
1550            let custom_arch = &mut *(ctxt as *mut ArchitectureBuilder<A, F>);
1551            let custom_arch_handle = CustomArchitectureHandle {
1552                handle: ctxt as *mut A,
1553            };
1554
1555            let create = custom_arch.func.take().unwrap();
1556            custom_arch
1557                .arch
1558                .write(create(custom_arch_handle, CoreArchitecture::from_raw(obj)));
1559        }
1560    }
1561
1562    extern "C" fn cb_endianness<A>(ctxt: *mut c_void) -> BNEndianness
1563    where
1564        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1565    {
1566        let custom_arch = unsafe { &*(ctxt as *mut A) };
1567        custom_arch.endianness()
1568    }
1569
1570    extern "C" fn cb_address_size<A>(ctxt: *mut c_void) -> usize
1571    where
1572        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1573    {
1574        let custom_arch = unsafe { &*(ctxt as *mut A) };
1575        custom_arch.address_size()
1576    }
1577
1578    extern "C" fn cb_default_integer_size<A>(ctxt: *mut c_void) -> usize
1579    where
1580        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1581    {
1582        let custom_arch = unsafe { &*(ctxt as *mut A) };
1583        custom_arch.default_integer_size()
1584    }
1585
1586    extern "C" fn cb_instruction_alignment<A>(ctxt: *mut c_void) -> usize
1587    where
1588        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1589    {
1590        let custom_arch = unsafe { &*(ctxt as *mut A) };
1591        custom_arch.instruction_alignment()
1592    }
1593
1594    extern "C" fn cb_max_instr_len<A>(ctxt: *mut c_void) -> usize
1595    where
1596        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1597    {
1598        let custom_arch = unsafe { &*(ctxt as *mut A) };
1599        custom_arch.max_instr_len()
1600    }
1601
1602    extern "C" fn cb_opcode_display_len<A>(ctxt: *mut c_void) -> usize
1603    where
1604        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1605    {
1606        let custom_arch = unsafe { &*(ctxt as *mut A) };
1607        custom_arch.opcode_display_len()
1608    }
1609
1610    extern "C" fn cb_associated_arch_by_addr<A>(
1611        ctxt: *mut c_void,
1612        addr: *mut u64,
1613    ) -> *mut BNArchitecture
1614    where
1615        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1616    {
1617        let custom_arch = unsafe { &*(ctxt as *mut A) };
1618        let addr = unsafe { *(addr) };
1619
1620        custom_arch.associated_arch_by_addr(addr).handle
1621    }
1622
1623    extern "C" fn cb_instruction_info<A>(
1624        ctxt: *mut c_void,
1625        data: *const u8,
1626        addr: u64,
1627        len: usize,
1628        result: *mut BNInstructionInfo,
1629    ) -> bool
1630    where
1631        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1632    {
1633        let custom_arch = unsafe { &*(ctxt as *mut A) };
1634        let data = unsafe { std::slice::from_raw_parts(data, len) };
1635
1636        match custom_arch.instruction_info(data, addr) {
1637            Some(info) => {
1638                // SAFETY: Passed in to be written to
1639                unsafe { *result = info.into() };
1640                true
1641            }
1642            None => false,
1643        }
1644    }
1645
1646    extern "C" fn cb_get_instruction_text<A>(
1647        ctxt: *mut c_void,
1648        data: *const u8,
1649        addr: u64,
1650        len: *mut usize,
1651        result: *mut *mut BNInstructionTextToken,
1652        count: *mut usize,
1653    ) -> bool
1654    where
1655        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1656    {
1657        let custom_arch = unsafe { &*(ctxt as *mut A) };
1658        let data = unsafe { std::slice::from_raw_parts(data, *len) };
1659        let result = unsafe { &mut *result };
1660
1661        let Some((res_size, res_tokens)) = custom_arch.instruction_text(data, addr) else {
1662            return false;
1663        };
1664
1665        let res_tokens: Box<[BNInstructionTextToken]> = res_tokens
1666            .into_iter()
1667            .map(InstructionTextToken::into_raw)
1668            .collect();
1669        unsafe {
1670            // NOTE: Freed with `cb_free_instruction_text`
1671            let res_tokens = Box::leak(res_tokens);
1672            *result = res_tokens.as_mut_ptr();
1673            *count = res_tokens.len();
1674            *len = res_size;
1675        }
1676        true
1677    }
1678
1679    pub unsafe extern "C" fn cb_get_instruction_text_with_context<A>(
1680        ctxt: *mut c_void,
1681        data: *const u8,
1682        addr: u64,
1683        len: *mut usize,
1684        context: *mut c_void,
1685        result: *mut *mut BNInstructionTextToken,
1686        count: *mut usize,
1687    ) -> bool
1688    where
1689        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1690    {
1691        let custom_arch = unsafe { &*(ctxt as *mut A) };
1692        let data = unsafe { std::slice::from_raw_parts(data, *len) };
1693        let result = unsafe { &mut *result };
1694        let context = NonNull::new(context);
1695
1696        let Some((res_size, res_tokens)) =
1697            custom_arch.instruction_text_with_context(data, addr, context)
1698        else {
1699            return false;
1700        };
1701
1702        let res_tokens: Box<[BNInstructionTextToken]> = res_tokens
1703            .into_iter()
1704            .map(InstructionTextToken::into_raw)
1705            .collect();
1706        unsafe {
1707            // NOTE: Freed with `cb_free_instruction_text`
1708            let res_tokens = Box::leak(res_tokens);
1709            *result = res_tokens.as_mut_ptr();
1710            *count = res_tokens.len();
1711            *len = res_size;
1712        }
1713        true
1714    }
1715
1716    extern "C" fn cb_free_instruction_text(tokens: *mut BNInstructionTextToken, count: usize) {
1717        unsafe {
1718            let raw_tokens = std::slice::from_raw_parts_mut(tokens, count);
1719            let boxed_tokens = Box::from_raw(raw_tokens);
1720            for token in boxed_tokens {
1721                InstructionTextToken::free_raw(token);
1722            }
1723        }
1724    }
1725
1726    extern "C" fn cb_instruction_llil<A>(
1727        ctxt: *mut c_void,
1728        data: *const u8,
1729        addr: u64,
1730        len: *mut usize,
1731        il: *mut BNLowLevelILFunction,
1732    ) -> bool
1733    where
1734        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1735    {
1736        let custom_arch = unsafe { &*(ctxt as *mut A) };
1737        let data = unsafe { std::slice::from_raw_parts(data, *len) };
1738        let lifter = unsafe {
1739            LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref()))
1740        };
1741
1742        match custom_arch.instruction_llil(data, addr, &lifter) {
1743            Some((res_len, res_value)) => {
1744                unsafe { *len = res_len };
1745                res_value
1746            }
1747            None => false,
1748        }
1749    }
1750
1751    extern "C" fn cb_analyze_basic_blocks<A>(
1752        ctxt: *mut c_void,
1753        function: *mut BNFunction,
1754        context: *mut BNBasicBlockAnalysisContext,
1755    ) where
1756        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1757    {
1758        let custom_arch = unsafe { &*(ctxt as *mut A) };
1759        let mut function = unsafe { Function::from_raw(function) };
1760        let mut context: BasicBlockAnalysisContext =
1761            unsafe { BasicBlockAnalysisContext::from_raw(context) };
1762        custom_arch.analyze_basic_blocks(&mut function, &mut context);
1763    }
1764
1765    extern "C" fn cb_lift_function<A>(
1766        ctxt: *mut c_void,
1767        function: *mut BNLowLevelILFunction,
1768        context: *mut BNFunctionLifterContext,
1769    ) -> bool
1770    where
1771        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1772    {
1773        let custom_arch = unsafe { &*(ctxt as *mut A) };
1774        let llil = unsafe {
1775            LowLevelILMutableFunction::from_raw_with_arch(function, Some(*custom_arch.as_ref()))
1776        };
1777
1778        let mut ctx = unsafe {
1779            FunctionLifterContext::from_raw_with_arch(
1780                function,
1781                context,
1782                Some(*custom_arch.as_ref()),
1783            )
1784        };
1785        custom_arch.lift_function(llil, &mut ctx)
1786    }
1787
1788    extern "C" fn cb_reg_name<A>(ctxt: *mut c_void, reg: u32) -> *mut c_char
1789    where
1790        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1791    {
1792        let custom_arch = unsafe { &*(ctxt as *mut A) };
1793
1794        match custom_arch.register_from_id(reg.into()) {
1795            Some(reg) => BnString::into_raw(BnString::new(reg.name().as_ref())),
1796            None => BnString::into_raw(BnString::new("invalid_reg")),
1797        }
1798    }
1799
1800    extern "C" fn cb_flag_name<A>(ctxt: *mut c_void, flag: u32) -> *mut c_char
1801    where
1802        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1803    {
1804        let custom_arch = unsafe { &*(ctxt as *mut A) };
1805
1806        match custom_arch.flag_from_id(flag.into()) {
1807            Some(flag) => BnString::into_raw(BnString::new(flag.name().as_ref())),
1808            None => BnString::into_raw(BnString::new("invalid_flag")),
1809        }
1810    }
1811
1812    extern "C" fn cb_flag_write_name<A>(ctxt: *mut c_void, flag_write: u32) -> *mut c_char
1813    where
1814        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1815    {
1816        let custom_arch = unsafe { &*(ctxt as *mut A) };
1817
1818        match custom_arch.flag_write_from_id(flag_write.into()) {
1819            Some(flag_write) => BnString::into_raw(BnString::new(flag_write.name().as_ref())),
1820            None => BnString::into_raw(BnString::new("invalid_flag_write")),
1821        }
1822    }
1823
1824    extern "C" fn cb_semantic_flag_class_name<A>(ctxt: *mut c_void, class: u32) -> *mut c_char
1825    where
1826        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1827    {
1828        let custom_arch = unsafe { &*(ctxt as *mut A) };
1829
1830        match custom_arch.flag_class_from_id(class.into()) {
1831            Some(class) => BnString::into_raw(BnString::new(class.name().as_ref())),
1832            None => BnString::into_raw(BnString::new("invalid_flag_class")),
1833        }
1834    }
1835
1836    extern "C" fn cb_semantic_flag_group_name<A>(ctxt: *mut c_void, group: u32) -> *mut c_char
1837    where
1838        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1839    {
1840        let custom_arch = unsafe { &*(ctxt as *mut A) };
1841
1842        match custom_arch.flag_group_from_id(group.into()) {
1843            Some(group) => BnString::into_raw(BnString::new(group.name().as_ref())),
1844            None => BnString::into_raw(BnString::new("invalid_flag_group")),
1845        }
1846    }
1847
1848    extern "C" fn cb_registers_full_width<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1849    where
1850        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1851    {
1852        let custom_arch = unsafe { &*(ctxt as *mut A) };
1853        let mut regs: Box<[_]> = custom_arch
1854            .registers_full_width()
1855            .iter()
1856            .map(|r| r.id().0)
1857            .collect();
1858
1859        // SAFETY: `count` is an out parameter
1860        unsafe { *count = regs.len() };
1861        let regs_ptr = regs.as_mut_ptr();
1862        std::mem::forget(regs);
1863        regs_ptr
1864    }
1865
1866    extern "C" fn cb_registers_all<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1867    where
1868        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1869    {
1870        let custom_arch = unsafe { &*(ctxt as *mut A) };
1871        let mut regs: Box<[_]> = custom_arch
1872            .registers_all()
1873            .iter()
1874            .map(|r| r.id().0)
1875            .collect();
1876
1877        // SAFETY: `count` is an out parameter
1878        unsafe { *count = regs.len() };
1879        let regs_ptr = regs.as_mut_ptr();
1880        std::mem::forget(regs);
1881        regs_ptr
1882    }
1883
1884    extern "C" fn cb_registers_global<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1885    where
1886        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1887    {
1888        let custom_arch = unsafe { &*(ctxt as *mut A) };
1889        let mut regs: Box<[_]> = custom_arch
1890            .registers_global()
1891            .iter()
1892            .map(|r| r.id().0)
1893            .collect();
1894
1895        // SAFETY: `count` is an out parameter
1896        unsafe { *count = regs.len() };
1897        let regs_ptr = regs.as_mut_ptr();
1898        std::mem::forget(regs);
1899        regs_ptr
1900    }
1901
1902    extern "C" fn cb_registers_system<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1903    where
1904        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1905    {
1906        let custom_arch = unsafe { &*(ctxt as *mut A) };
1907        let mut regs: Box<[_]> = custom_arch
1908            .registers_system()
1909            .iter()
1910            .map(|r| r.id().0)
1911            .collect();
1912
1913        // SAFETY: `count` is an out parameter
1914        unsafe { *count = regs.len() };
1915        let regs_ptr = regs.as_mut_ptr();
1916        std::mem::forget(regs);
1917        regs_ptr
1918    }
1919
1920    extern "C" fn cb_flags<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1921    where
1922        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1923    {
1924        let custom_arch = unsafe { &*(ctxt as *mut A) };
1925        let mut flags: Box<[_]> = custom_arch.flags().iter().map(|f| f.id().0).collect();
1926
1927        // SAFETY: `count` is an out parameter
1928        unsafe { *count = flags.len() };
1929        let flags_ptr = flags.as_mut_ptr();
1930        std::mem::forget(flags);
1931        flags_ptr
1932    }
1933
1934    extern "C" fn cb_flag_write_types<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1935    where
1936        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1937    {
1938        let custom_arch = unsafe { &*(ctxt as *mut A) };
1939        let mut flag_writes: Box<[_]> = custom_arch
1940            .flag_write_types()
1941            .iter()
1942            .map(|f| f.id().0)
1943            .collect();
1944
1945        // SAFETY: `count` is an out parameter
1946        unsafe { *count = flag_writes.len() };
1947        let flags_ptr = flag_writes.as_mut_ptr();
1948        std::mem::forget(flag_writes);
1949        flags_ptr
1950    }
1951
1952    extern "C" fn cb_semantic_flag_classes<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1953    where
1954        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1955    {
1956        let custom_arch = unsafe { &*(ctxt as *mut A) };
1957        let mut flag_classes: Box<[_]> = custom_arch
1958            .flag_classes()
1959            .iter()
1960            .map(|f| f.id().0)
1961            .collect();
1962
1963        // SAFETY: `count` is an out parameter
1964        unsafe { *count = flag_classes.len() };
1965        let flags_ptr = flag_classes.as_mut_ptr();
1966        std::mem::forget(flag_classes);
1967        flags_ptr
1968    }
1969
1970    extern "C" fn cb_semantic_flag_groups<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1971    where
1972        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1973    {
1974        let custom_arch = unsafe { &*(ctxt as *mut A) };
1975        let mut flag_groups: Box<[_]> =
1976            custom_arch.flag_groups().iter().map(|f| f.id().0).collect();
1977
1978        // SAFETY: `count` is an out parameter
1979        unsafe { *count = flag_groups.len() };
1980        let flags_ptr = flag_groups.as_mut_ptr();
1981        std::mem::forget(flag_groups);
1982        flags_ptr
1983    }
1984
1985    extern "C" fn cb_flag_role<A>(ctxt: *mut c_void, flag: u32, class: u32) -> BNFlagRole
1986    where
1987        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1988    {
1989        let custom_arch = unsafe { &*(ctxt as *mut A) };
1990
1991        if let (Some(flag), class) = (
1992            custom_arch.flag_from_id(FlagId(flag)),
1993            custom_arch.flag_class_from_id(FlagClassId(class)),
1994        ) {
1995            flag.role(class)
1996        } else {
1997            FlagRole::SpecialFlagRole
1998        }
1999    }
2000
2001    extern "C" fn cb_flags_required_for_flag_cond<A>(
2002        ctxt: *mut c_void,
2003        cond: BNLowLevelILFlagCondition,
2004        class: u32,
2005        count: *mut usize,
2006    ) -> *mut u32
2007    where
2008        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2009    {
2010        let custom_arch = unsafe { &*(ctxt as *mut A) };
2011        let class = custom_arch.flag_class_from_id(FlagClassId(class));
2012        let mut flags: Box<[_]> = custom_arch
2013            .flags_required_for_flag_condition(cond, class)
2014            .iter()
2015            .map(|f| f.id().0)
2016            .collect();
2017
2018        // SAFETY: `count` is an out parameter
2019        unsafe { *count = flags.len() };
2020        let flags_ptr = flags.as_mut_ptr();
2021        std::mem::forget(flags);
2022        flags_ptr
2023    }
2024
2025    extern "C" fn cb_flags_required_for_semantic_flag_group<A>(
2026        ctxt: *mut c_void,
2027        group: u32,
2028        count: *mut usize,
2029    ) -> *mut u32
2030    where
2031        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2032    {
2033        let custom_arch = unsafe { &*(ctxt as *mut A) };
2034
2035        if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
2036            let mut flags: Box<[_]> = group.flags_required().iter().map(|f| f.id().0).collect();
2037
2038            // SAFETY: `count` is an out parameter
2039            unsafe { *count = flags.len() };
2040            let flags_ptr = flags.as_mut_ptr();
2041            std::mem::forget(flags);
2042            flags_ptr
2043        } else {
2044            unsafe {
2045                *count = 0;
2046            }
2047            std::ptr::null_mut()
2048        }
2049    }
2050
2051    extern "C" fn cb_flag_conditions_for_semantic_flag_group<A>(
2052        ctxt: *mut c_void,
2053        group: u32,
2054        count: *mut usize,
2055    ) -> *mut BNFlagConditionForSemanticClass
2056    where
2057        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2058    {
2059        let custom_arch = unsafe { &*(ctxt as *mut A) };
2060
2061        if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
2062            let flag_conditions = group.flag_conditions();
2063            let mut flags: Box<[_]> = flag_conditions
2064                .iter()
2065                .map(|(&class, &condition)| BNFlagConditionForSemanticClass {
2066                    semanticClass: class.id().0,
2067                    condition,
2068                })
2069                .collect();
2070
2071            // SAFETY: `count` is an out parameter
2072            unsafe { *count = flags.len() };
2073            let flags_ptr = flags.as_mut_ptr();
2074            std::mem::forget(flags);
2075            flags_ptr
2076        } else {
2077            unsafe {
2078                *count = 0;
2079            }
2080            std::ptr::null_mut()
2081        }
2082    }
2083
2084    extern "C" fn cb_free_flag_conditions_for_semantic_flag_group<A>(
2085        _ctxt: *mut c_void,
2086        conds: *mut BNFlagConditionForSemanticClass,
2087        count: usize,
2088    ) where
2089        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2090    {
2091        if conds.is_null() {
2092            return;
2093        }
2094
2095        unsafe {
2096            let flags_ptr = std::ptr::slice_from_raw_parts_mut(conds, count);
2097            let _flags = Box::from_raw(flags_ptr);
2098        }
2099    }
2100
2101    extern "C" fn cb_flags_written_by_write_type<A>(
2102        ctxt: *mut c_void,
2103        write_type: u32,
2104        count: *mut usize,
2105    ) -> *mut u32
2106    where
2107        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2108    {
2109        let custom_arch = unsafe { &*(ctxt as *mut A) };
2110
2111        if let Some(write_type) = custom_arch.flag_write_from_id(FlagWriteId(write_type)) {
2112            let mut flags_written: Box<[_]> = write_type
2113                .flags_written()
2114                .iter()
2115                .map(|f| f.id().0)
2116                .collect();
2117
2118            // SAFETY: `count` is an out parameter
2119            unsafe { *count = flags_written.len() };
2120            let flags_ptr = flags_written.as_mut_ptr();
2121            std::mem::forget(flags_written);
2122            flags_ptr
2123        } else {
2124            unsafe {
2125                *count = 0;
2126            }
2127            std::ptr::null_mut()
2128        }
2129    }
2130
2131    extern "C" fn cb_semantic_class_for_flag_write_type<A>(
2132        ctxt: *mut c_void,
2133        write_type: u32,
2134    ) -> u32
2135    where
2136        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2137    {
2138        let custom_arch = unsafe { &*(ctxt as *mut A) };
2139        custom_arch
2140            .flag_write_from_id(FlagWriteId(write_type))
2141            .map(|w| w.class())
2142            .and_then(|c| c.map(|c| c.id().0))
2143            .unwrap_or(0)
2144    }
2145
2146    extern "C" fn cb_flag_write_llil<A>(
2147        ctxt: *mut c_void,
2148        op: BNLowLevelILOperation,
2149        size: usize,
2150        flag_write: u32,
2151        flag: u32,
2152        operands_raw: *mut BNRegisterOrConstant,
2153        operand_count: usize,
2154        il: *mut BNLowLevelILFunction,
2155    ) -> usize
2156    where
2157        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2158    {
2159        let custom_arch = unsafe { &*(ctxt as *mut A) };
2160        let flag_write = custom_arch.flag_write_from_id(FlagWriteId(flag_write));
2161        let flag = custom_arch.flag_from_id(FlagId(flag));
2162        let operands = unsafe { std::slice::from_raw_parts(operands_raw, operand_count) };
2163        let lifter = unsafe {
2164            LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref()))
2165        };
2166
2167        if let (Some(flag_write), Some(flag)) = (flag_write, flag) {
2168            if let Some(op) = LowLevelILFlagWriteOp::from_op(custom_arch, size, op, operands) {
2169                if let Some(expr) = custom_arch.flag_write_llil(flag, flag_write, op, &lifter) {
2170                    // TODO verify that returned expr is a bool value
2171                    return expr.index.0;
2172                }
2173            } else {
2174                tracing::warn!(
2175                    "unable to unpack flag write op: {:?} with {} operands",
2176                    op,
2177                    operands.len()
2178                );
2179            }
2180
2181            let role = flag.role(flag_write.class());
2182
2183            unsafe {
2184                BNGetDefaultArchitectureFlagWriteLowLevelIL(
2185                    custom_arch.as_ref().handle,
2186                    op,
2187                    size,
2188                    role,
2189                    operands_raw,
2190                    operand_count,
2191                    il,
2192                )
2193            }
2194        } else {
2195            // TODO this should be impossible; requires bad flag/flag_write ids passed in;
2196            // explode more violently
2197            lifter.unimplemented().index.0
2198        }
2199    }
2200
2201    extern "C" fn cb_flag_cond_llil<A>(
2202        ctxt: *mut c_void,
2203        cond: FlagCondition,
2204        class: u32,
2205        il: *mut BNLowLevelILFunction,
2206    ) -> usize
2207    where
2208        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2209    {
2210        let custom_arch = unsafe { &*(ctxt as *mut A) };
2211        let class = custom_arch.flag_class_from_id(FlagClassId(class));
2212
2213        let lifter = unsafe {
2214            LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref()))
2215        };
2216        if let Some(expr) = custom_arch.flag_cond_llil(cond, class, &lifter) {
2217            // TODO verify that returned expr is a bool value
2218            return expr.index.0;
2219        }
2220
2221        lifter.unimplemented().index.0
2222    }
2223
2224    extern "C" fn cb_flag_group_llil<A>(
2225        ctxt: *mut c_void,
2226        group: u32,
2227        il: *mut BNLowLevelILFunction,
2228    ) -> usize
2229    where
2230        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2231    {
2232        let custom_arch = unsafe { &*(ctxt as *mut A) };
2233        let lifter = unsafe {
2234            LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref()))
2235        };
2236
2237        if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
2238            if let Some(expr) = custom_arch.flag_group_llil(group, &lifter) {
2239                // TODO verify that returned expr is a bool value
2240                return expr.index.0;
2241            }
2242        }
2243
2244        lifter.unimplemented().index.0
2245    }
2246
2247    extern "C" fn cb_free_register_list(_ctxt: *mut c_void, regs: *mut u32, count: usize) {
2248        if regs.is_null() {
2249            return;
2250        }
2251
2252        unsafe {
2253            let regs_ptr = std::ptr::slice_from_raw_parts_mut(regs, count);
2254            let _regs = Box::from_raw(regs_ptr);
2255        }
2256    }
2257
2258    extern "C" fn cb_register_info<A>(ctxt: *mut c_void, reg: u32, result: *mut BNRegisterInfo)
2259    where
2260        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2261    {
2262        let custom_arch = unsafe { &*(ctxt as *mut A) };
2263        let result = unsafe { &mut *result };
2264
2265        if let Some(reg) = custom_arch.register_from_id(RegisterId(reg)) {
2266            let info = reg.info();
2267
2268            result.fullWidthRegister = match info.parent() {
2269                Some(p) => p.id().0,
2270                None => reg.id().0,
2271            };
2272
2273            result.offset = info.offset();
2274            result.size = info.size();
2275            result.extend = info.implicit_extend().into();
2276        }
2277    }
2278
2279    extern "C" fn cb_stack_pointer<A>(ctxt: *mut c_void) -> u32
2280    where
2281        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2282    {
2283        let custom_arch = unsafe { &*(ctxt as *mut A) };
2284
2285        if let Some(reg) = custom_arch.stack_pointer_reg() {
2286            reg.id().0
2287        } else {
2288            INVALID_REGISTER
2289        }
2290    }
2291
2292    extern "C" fn cb_link_reg<A>(ctxt: *mut c_void) -> u32
2293    where
2294        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2295    {
2296        let custom_arch = unsafe { &*(ctxt as *mut A) };
2297
2298        if let Some(reg) = custom_arch.link_reg() {
2299            reg.id().0
2300        } else {
2301            INVALID_REGISTER
2302        }
2303    }
2304
2305    extern "C" fn cb_reg_stack_name<A>(ctxt: *mut c_void, stack: u32) -> *mut c_char
2306    where
2307        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2308    {
2309        let custom_arch = unsafe { &*(ctxt as *mut A) };
2310
2311        match custom_arch.register_stack_from_id(RegisterStackId(stack)) {
2312            Some(stack) => BnString::into_raw(BnString::new(stack.name().as_ref())),
2313            None => BnString::into_raw(BnString::new("invalid_reg_stack")),
2314        }
2315    }
2316
2317    extern "C" fn cb_reg_stacks<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2318    where
2319        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2320    {
2321        let custom_arch = unsafe { &*(ctxt as *mut A) };
2322        let mut regs: Box<[_]> = custom_arch
2323            .register_stacks()
2324            .iter()
2325            .map(|r| r.id().0)
2326            .collect();
2327
2328        // SAFETY: Passed in to be written
2329        unsafe { *count = regs.len() };
2330        let regs_ptr = regs.as_mut_ptr();
2331        std::mem::forget(regs);
2332        regs_ptr
2333    }
2334
2335    extern "C" fn cb_reg_stack_info<A>(
2336        ctxt: *mut c_void,
2337        stack: u32,
2338        result: *mut BNRegisterStackInfo,
2339    ) where
2340        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2341    {
2342        let custom_arch = unsafe { &*(ctxt as *mut A) };
2343        let result = unsafe { &mut *result };
2344
2345        if let Some(stack) = custom_arch.register_stack_from_id(RegisterStackId(stack)) {
2346            let info = stack.info();
2347
2348            let (reg, count) = info.storage_regs();
2349            result.firstStorageReg = reg.id().0;
2350            result.storageCount = count as u32;
2351
2352            if let Some((reg, count)) = info.top_relative_regs() {
2353                result.firstTopRelativeReg = reg.id().0;
2354                result.topRelativeCount = count as u32;
2355            } else {
2356                result.firstTopRelativeReg = INVALID_REGISTER;
2357                result.topRelativeCount = 0;
2358            }
2359
2360            result.stackTopReg = info.stack_top_reg().id().0;
2361        }
2362    }
2363
2364    extern "C" fn cb_intrinsic_class<A>(ctxt: *mut c_void, intrinsic: u32) -> BNIntrinsicClass
2365    where
2366        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2367    {
2368        let custom_arch = unsafe { &*(ctxt as *mut A) };
2369        match custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) {
2370            Some(intrinsic) => intrinsic.class(),
2371            // TODO: Make this unreachable?
2372            None => BNIntrinsicClass::GeneralIntrinsicClass,
2373        }
2374    }
2375
2376    extern "C" fn cb_intrinsic_name<A>(ctxt: *mut c_void, intrinsic: u32) -> *mut c_char
2377    where
2378        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2379    {
2380        let custom_arch = unsafe { &*(ctxt as *mut A) };
2381        match custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) {
2382            Some(intrinsic) => BnString::into_raw(BnString::new(intrinsic.name())),
2383            None => BnString::into_raw(BnString::new("invalid_intrinsic")),
2384        }
2385    }
2386
2387    extern "C" fn cb_intrinsics<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2388    where
2389        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2390    {
2391        let custom_arch = unsafe { &*(ctxt as *mut A) };
2392        let mut intrinsics: Box<[_]> = custom_arch.intrinsics().iter().map(|i| i.id().0).collect();
2393
2394        // SAFETY: Passed in to be written
2395        unsafe { *count = intrinsics.len() };
2396        let intrinsics_ptr = intrinsics.as_mut_ptr();
2397        std::mem::forget(intrinsics);
2398        intrinsics_ptr
2399    }
2400
2401    extern "C" fn cb_intrinsic_inputs<A>(
2402        ctxt: *mut c_void,
2403        intrinsic: u32,
2404        count: *mut usize,
2405    ) -> *mut BNNameAndType
2406    where
2407        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2408    {
2409        let custom_arch = unsafe { &*(ctxt as *mut A) };
2410
2411        let Some(intrinsic) = custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) else {
2412            // SAFETY: Passed in to be written
2413            unsafe {
2414                *count = 0;
2415            }
2416            return std::ptr::null_mut();
2417        };
2418
2419        let inputs = intrinsic.inputs();
2420        // NOTE: The into_raw will leak and be freed later by `cb_free_name_and_types`.
2421        let raw_inputs: Box<[_]> = inputs.into_iter().map(NameAndType::into_raw).collect();
2422
2423        // SAFETY: Passed in to be written
2424        unsafe {
2425            *count = raw_inputs.len();
2426        }
2427
2428        if raw_inputs.is_empty() {
2429            std::ptr::null_mut()
2430        } else {
2431            // Core is responsible for calling back to `cb_free_name_and_types`.
2432            Box::leak(raw_inputs).as_mut_ptr()
2433        }
2434    }
2435
2436    extern "C" fn cb_free_name_and_types<A>(
2437        _ctxt: *mut c_void,
2438        nt: *mut BNNameAndType,
2439        count: usize,
2440    ) where
2441        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2442    {
2443        if nt.is_null() {
2444            return;
2445        }
2446
2447        // Reconstruct the box and drop.
2448        let nt_ptr = std::ptr::slice_from_raw_parts_mut(nt, count);
2449        // SAFETY: nt_ptr is a pointer to a Box.
2450        let boxed_name_and_types = unsafe { Box::from_raw(nt_ptr) };
2451        for nt in boxed_name_and_types {
2452            NameAndType::free_raw(nt);
2453        }
2454    }
2455
2456    extern "C" fn cb_intrinsic_outputs<A>(
2457        ctxt: *mut c_void,
2458        intrinsic: u32,
2459        count: *mut usize,
2460    ) -> *mut BNTypeWithConfidence
2461    where
2462        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2463    {
2464        let custom_arch = unsafe { &*(ctxt as *mut A) };
2465
2466        let Some(intrinsic) = custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) else {
2467            // SAFETY: Passed in to be written
2468            unsafe {
2469                *count = 0;
2470            }
2471            return std::ptr::null_mut();
2472        };
2473
2474        let outputs = intrinsic.outputs();
2475        let raw_outputs: Box<[BNTypeWithConfidence]> = outputs
2476            .into_iter()
2477            // Leaked to be freed later by `cb_free_type_list`.
2478            .map(Conf::<Ref<Type>>::into_raw)
2479            .collect();
2480
2481        // SAFETY: Passed in to be written
2482        unsafe {
2483            *count = raw_outputs.len();
2484        }
2485
2486        if raw_outputs.is_empty() {
2487            std::ptr::null_mut()
2488        } else {
2489            // Core is responsible for calling back to `cb_free_type_list`.
2490            Box::leak(raw_outputs).as_mut_ptr()
2491        }
2492    }
2493
2494    extern "C" fn cb_free_type_list<A>(
2495        ctxt: *mut c_void,
2496        tl: *mut BNTypeWithConfidence,
2497        count: usize,
2498    ) where
2499        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2500    {
2501        let _custom_arch = unsafe { &*(ctxt as *mut A) };
2502        if !tl.is_null() {
2503            let boxed_types =
2504                unsafe { Box::from_raw(std::ptr::slice_from_raw_parts_mut(tl, count)) };
2505            for ty in boxed_types {
2506                Conf::<Ref<Type>>::free_raw(ty);
2507            }
2508        }
2509    }
2510
2511    extern "C" fn cb_can_assemble<A>(ctxt: *mut c_void) -> bool
2512    where
2513        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2514    {
2515        let custom_arch = unsafe { &*(ctxt as *mut A) };
2516        custom_arch.can_assemble()
2517    }
2518
2519    extern "C" fn cb_assemble<A>(
2520        ctxt: *mut c_void,
2521        code: *const c_char,
2522        addr: u64,
2523        buffer: *mut BNDataBuffer,
2524        errors: *mut *mut c_char,
2525    ) -> bool
2526    where
2527        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2528    {
2529        let custom_arch = unsafe { &*(ctxt as *mut A) };
2530        let code = raw_to_string(code).unwrap_or("".into());
2531        let mut buffer = DataBuffer::from_raw(buffer);
2532
2533        let result = match custom_arch.assemble(&code, addr) {
2534            Ok(result) => {
2535                buffer.set_data(&result);
2536                unsafe {
2537                    *errors = BnString::into_raw(BnString::new(""));
2538                }
2539                true
2540            }
2541            Err(result) => {
2542                unsafe {
2543                    *errors = BnString::into_raw(BnString::new(result));
2544                }
2545                false
2546            }
2547        };
2548
2549        // Caller owns the data buffer, don't free it
2550        std::mem::forget(buffer);
2551
2552        result
2553    }
2554
2555    extern "C" fn cb_is_never_branch_patch_available<A>(
2556        ctxt: *mut c_void,
2557        data: *const u8,
2558        addr: u64,
2559        len: usize,
2560    ) -> bool
2561    where
2562        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2563    {
2564        let custom_arch = unsafe { &*(ctxt as *mut A) };
2565        let data = unsafe { std::slice::from_raw_parts(data, len) };
2566        custom_arch.is_never_branch_patch_available(data, addr)
2567    }
2568
2569    extern "C" fn cb_is_always_branch_patch_available<A>(
2570        ctxt: *mut c_void,
2571        data: *const u8,
2572        addr: u64,
2573        len: usize,
2574    ) -> bool
2575    where
2576        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2577    {
2578        let custom_arch = unsafe { &*(ctxt as *mut A) };
2579        let data = unsafe { std::slice::from_raw_parts(data, len) };
2580        custom_arch.is_always_branch_patch_available(data, addr)
2581    }
2582
2583    extern "C" fn cb_is_invert_branch_patch_available<A>(
2584        ctxt: *mut c_void,
2585        data: *const u8,
2586        addr: u64,
2587        len: usize,
2588    ) -> bool
2589    where
2590        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2591    {
2592        let custom_arch = unsafe { &*(ctxt as *mut A) };
2593        let data = unsafe { std::slice::from_raw_parts(data, len) };
2594        custom_arch.is_invert_branch_patch_available(data, addr)
2595    }
2596
2597    extern "C" fn cb_is_skip_and_return_zero_patch_available<A>(
2598        ctxt: *mut c_void,
2599        data: *const u8,
2600        addr: u64,
2601        len: usize,
2602    ) -> bool
2603    where
2604        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2605    {
2606        let custom_arch = unsafe { &*(ctxt as *mut A) };
2607        let data = unsafe { std::slice::from_raw_parts(data, len) };
2608        custom_arch.is_skip_and_return_zero_patch_available(data, addr)
2609    }
2610
2611    extern "C" fn cb_is_skip_and_return_value_patch_available<A>(
2612        ctxt: *mut c_void,
2613        data: *const u8,
2614        addr: u64,
2615        len: usize,
2616    ) -> bool
2617    where
2618        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2619    {
2620        let custom_arch = unsafe { &*(ctxt as *mut A) };
2621        let data = unsafe { std::slice::from_raw_parts(data, len) };
2622        custom_arch.is_skip_and_return_value_patch_available(data, addr)
2623    }
2624
2625    extern "C" fn cb_convert_to_nop<A>(
2626        ctxt: *mut c_void,
2627        data: *mut u8,
2628        addr: u64,
2629        len: usize,
2630    ) -> bool
2631    where
2632        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2633    {
2634        let custom_arch = unsafe { &*(ctxt as *mut A) };
2635        let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
2636        custom_arch.convert_to_nop(data, addr)
2637    }
2638
2639    extern "C" fn cb_always_branch<A>(
2640        ctxt: *mut c_void,
2641        data: *mut u8,
2642        addr: u64,
2643        len: usize,
2644    ) -> bool
2645    where
2646        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2647    {
2648        let custom_arch = unsafe { &*(ctxt as *mut A) };
2649        let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
2650        custom_arch.always_branch(data, addr)
2651    }
2652
2653    extern "C" fn cb_invert_branch<A>(
2654        ctxt: *mut c_void,
2655        data: *mut u8,
2656        addr: u64,
2657        len: usize,
2658    ) -> bool
2659    where
2660        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2661    {
2662        let custom_arch = unsafe { &*(ctxt as *mut A) };
2663        let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
2664        custom_arch.invert_branch(data, addr)
2665    }
2666
2667    extern "C" fn cb_skip_and_return_value<A>(
2668        ctxt: *mut c_void,
2669        data: *mut u8,
2670        addr: u64,
2671        len: usize,
2672        val: u64,
2673    ) -> bool
2674    where
2675        A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2676    {
2677        let custom_arch = unsafe { &*(ctxt as *mut A) };
2678        let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
2679        custom_arch.skip_and_return_value(data, addr, val)
2680    }
2681
2682    let name = name.to_cstr();
2683
2684    let uninit_arch = ArchitectureBuilder {
2685        arch: MaybeUninit::zeroed(),
2686        func: Some(func),
2687    };
2688
2689    let raw = Box::into_raw(Box::new(uninit_arch));
2690    let mut custom_arch = BNCustomArchitecture {
2691        context: raw as *mut _,
2692        init: Some(cb_init::<A, F>),
2693        getEndianness: Some(cb_endianness::<A>),
2694        getAddressSize: Some(cb_address_size::<A>),
2695        getDefaultIntegerSize: Some(cb_default_integer_size::<A>),
2696        getInstructionAlignment: Some(cb_instruction_alignment::<A>),
2697        // TODO: Make getOpcodeDisplayLength optional.
2698        getMaxInstructionLength: Some(cb_max_instr_len::<A>),
2699        // TODO: Make getOpcodeDisplayLength optional.
2700        getOpcodeDisplayLength: Some(cb_opcode_display_len::<A>),
2701        getAssociatedArchitectureByAddress: Some(cb_associated_arch_by_addr::<A>),
2702        getInstructionInfo: Some(cb_instruction_info::<A>),
2703        getInstructionText: Some(cb_get_instruction_text::<A>),
2704        getInstructionTextWithContext: Some(cb_get_instruction_text_with_context::<A>),
2705        freeInstructionText: Some(cb_free_instruction_text),
2706        getInstructionLowLevelIL: Some(cb_instruction_llil::<A>),
2707        analyzeBasicBlocks: Some(cb_analyze_basic_blocks::<A>),
2708        liftFunction: Some(cb_lift_function::<A>),
2709        freeFunctionArchContext: None,
2710
2711        getRegisterName: Some(cb_reg_name::<A>),
2712        getFlagName: Some(cb_flag_name::<A>),
2713        getFlagWriteTypeName: Some(cb_flag_write_name::<A>),
2714        getSemanticFlagClassName: Some(cb_semantic_flag_class_name::<A>),
2715        getSemanticFlagGroupName: Some(cb_semantic_flag_group_name::<A>),
2716
2717        getFullWidthRegisters: Some(cb_registers_full_width::<A>),
2718        getAllRegisters: Some(cb_registers_all::<A>),
2719        getAllFlags: Some(cb_flags::<A>),
2720        getAllFlagWriteTypes: Some(cb_flag_write_types::<A>),
2721        getAllSemanticFlagClasses: Some(cb_semantic_flag_classes::<A>),
2722        getAllSemanticFlagGroups: Some(cb_semantic_flag_groups::<A>),
2723
2724        getFlagRole: Some(cb_flag_role::<A>),
2725        getFlagsRequiredForFlagCondition: Some(cb_flags_required_for_flag_cond::<A>),
2726
2727        getFlagsRequiredForSemanticFlagGroup: Some(cb_flags_required_for_semantic_flag_group::<A>),
2728        getFlagConditionsForSemanticFlagGroup: Some(
2729            cb_flag_conditions_for_semantic_flag_group::<A>,
2730        ),
2731        freeFlagConditionsForSemanticFlagGroup: Some(
2732            cb_free_flag_conditions_for_semantic_flag_group::<A>,
2733        ),
2734
2735        getFlagsWrittenByFlagWriteType: Some(cb_flags_written_by_write_type::<A>),
2736        getSemanticClassForFlagWriteType: Some(cb_semantic_class_for_flag_write_type::<A>),
2737
2738        getFlagWriteLowLevelIL: Some(cb_flag_write_llil::<A>),
2739        getFlagConditionLowLevelIL: Some(cb_flag_cond_llil::<A>),
2740        getSemanticFlagGroupLowLevelIL: Some(cb_flag_group_llil::<A>),
2741
2742        freeRegisterList: Some(cb_free_register_list),
2743        getRegisterInfo: Some(cb_register_info::<A>),
2744        getStackPointerRegister: Some(cb_stack_pointer::<A>),
2745        getLinkRegister: Some(cb_link_reg::<A>),
2746        getGlobalRegisters: Some(cb_registers_global::<A>),
2747        getSystemRegisters: Some(cb_registers_system::<A>),
2748
2749        getRegisterStackName: Some(cb_reg_stack_name::<A>),
2750        getAllRegisterStacks: Some(cb_reg_stacks::<A>),
2751        getRegisterStackInfo: Some(cb_reg_stack_info::<A>),
2752
2753        getIntrinsicClass: Some(cb_intrinsic_class::<A>),
2754        getIntrinsicName: Some(cb_intrinsic_name::<A>),
2755        getAllIntrinsics: Some(cb_intrinsics::<A>),
2756        getIntrinsicInputs: Some(cb_intrinsic_inputs::<A>),
2757        freeNameAndTypeList: Some(cb_free_name_and_types::<A>),
2758        getIntrinsicOutputs: Some(cb_intrinsic_outputs::<A>),
2759        freeTypeList: Some(cb_free_type_list::<A>),
2760
2761        canAssemble: Some(cb_can_assemble::<A>),
2762        assemble: Some(cb_assemble::<A>),
2763
2764        isNeverBranchPatchAvailable: Some(cb_is_never_branch_patch_available::<A>),
2765        isAlwaysBranchPatchAvailable: Some(cb_is_always_branch_patch_available::<A>),
2766        isInvertBranchPatchAvailable: Some(cb_is_invert_branch_patch_available::<A>),
2767        isSkipAndReturnZeroPatchAvailable: Some(cb_is_skip_and_return_zero_patch_available::<A>),
2768        isSkipAndReturnValuePatchAvailable: Some(cb_is_skip_and_return_value_patch_available::<A>),
2769
2770        convertToNop: Some(cb_convert_to_nop::<A>),
2771        alwaysBranch: Some(cb_always_branch::<A>),
2772        invertBranch: Some(cb_invert_branch::<A>),
2773        skipAndReturnValue: Some(cb_skip_and_return_value::<A>),
2774    };
2775
2776    customize(&mut custom_arch);
2777
2778    unsafe {
2779        let res = BNRegisterArchitecture(name.as_ptr(), &mut custom_arch as *mut _);
2780        assert!(!res.is_null());
2781
2782        (*raw).arch.assume_init_mut()
2783    }
2784}
2785
2786pub fn register_architecture_with_function_context<A, F>(name: &str, func: F) -> &'static A
2787where
2788    A: 'static
2789        + ArchitectureWithFunctionContext<Handle = CustomArchitectureHandle<A>>
2790        + Send
2791        + Sync
2792        + Sized,
2793    F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
2794{
2795    unsafe extern "C" fn cb_free_function_arch_context_typed<A>(
2796        _ctxt: *mut c_void,
2797        context: *mut c_void,
2798    ) where
2799        A: 'static
2800            + ArchitectureWithFunctionContext<Handle = CustomArchitectureHandle<A>>
2801            + Send
2802            + Sync,
2803    {
2804        if context.is_null() {
2805            return;
2806        }
2807        // The context was allocated via Box::into_raw in set_function_arch_context,
2808        // so we reconstruct the Box here and let it drop.
2809        let _ = unsafe { Box::from_raw(context as *mut A::FunctionArchContext) };
2810    }
2811
2812    unsafe extern "C" fn cb_get_instruction_text_with_context_typed<A>(
2813        ctxt: *mut c_void,
2814        data: *const u8,
2815        addr: u64,
2816        len: *mut usize,
2817        context: *mut c_void,
2818        result: *mut *mut BNInstructionTextToken,
2819        count: *mut usize,
2820    ) -> bool
2821    where
2822        A: 'static
2823            + ArchitectureWithFunctionContext<Handle = CustomArchitectureHandle<A>>
2824            + Send
2825            + Sync,
2826    {
2827        let custom_arch = unsafe { &*(ctxt as *mut A) };
2828        let data = unsafe { std::slice::from_raw_parts(data, *len) };
2829        let result = unsafe { &mut *result };
2830        let typed_context: Option<&A::FunctionArchContext> = if context.is_null() {
2831            None
2832        } else {
2833            Some(unsafe { &*(context as *const A::FunctionArchContext) })
2834        };
2835
2836        let Some((res_size, res_tokens)) =
2837            custom_arch.instruction_text_with_typed_context(data, addr, typed_context)
2838        else {
2839            return false;
2840        };
2841
2842        let res_tokens: Box<[BNInstructionTextToken]> = res_tokens
2843            .into_iter()
2844            .map(InstructionTextToken::into_raw)
2845            .collect();
2846        unsafe {
2847            let res_tokens = Box::leak(res_tokens);
2848            *result = res_tokens.as_mut_ptr();
2849            *count = res_tokens.len();
2850            *len = res_size;
2851        }
2852        true
2853    }
2854
2855    register_architecture_impl(name, func, |custom_arch| {
2856        custom_arch.freeFunctionArchContext = Some(cb_free_function_arch_context_typed::<A>);
2857        custom_arch.getInstructionTextWithContext =
2858            Some(cb_get_instruction_text_with_context_typed::<A>);
2859    })
2860}
2861
2862#[derive(Debug)]
2863pub struct CustomArchitectureHandle<A>
2864where
2865    A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2866{
2867    handle: *mut A,
2868}
2869
2870unsafe impl<A> Send for CustomArchitectureHandle<A> where
2871    A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync
2872{
2873}
2874
2875unsafe impl<A> Sync for CustomArchitectureHandle<A> where
2876    A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync
2877{
2878}
2879
2880impl<A> Clone for CustomArchitectureHandle<A>
2881where
2882    A: 'static + Architecture<Handle = Self> + Send + Sync,
2883{
2884    fn clone(&self) -> Self {
2885        *self
2886    }
2887}
2888
2889impl<A> Copy for CustomArchitectureHandle<A> where
2890    A: 'static + Architecture<Handle = Self> + Send + Sync
2891{
2892}
2893
2894impl<A> Borrow<A> for CustomArchitectureHandle<A>
2895where
2896    A: 'static + Architecture<Handle = Self> + Send + Sync,
2897{
2898    fn borrow(&self) -> &A {
2899        unsafe { &*self.handle }
2900    }
2901}