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