summaryrefslogtreecommitdiff
path: root/rust/src/architecture.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/architecture.rs')
-rw-r--r--rust/src/architecture.rs1581
1 files changed, 974 insertions, 607 deletions
diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs
index 027af77f..09808b39 100644
--- a/rust/src/architecture.rs
+++ b/rust/src/architecture.rs
@@ -17,34 +17,81 @@
// container abstraction to avoid Vec<> (want CoreArchFlagList, CoreArchRegList)
// RegisterInfo purge
use binaryninjacore_sys::*;
-
-use std::{
- borrow::{Borrow, Cow},
- collections::HashMap,
- ffi::{c_char, c_int, CStr, CString},
- hash::Hash,
- mem::{zeroed, MaybeUninit},
- ops, ptr, slice,
-};
+use std::fmt::{Debug, Formatter};
use crate::{
- callingconvention::CallingConvention,
- databuffer::DataBuffer,
+ calling_convention::CoreCallingConvention,
+ data_buffer::DataBuffer,
disassembly::InstructionTextToken,
- llil::{
- get_default_flag_cond_llil, get_default_flag_write_llil, FlagWriteOp, LiftedExpr, Lifter,
- },
+ low_level_il::{MutableLiftedILExpr, MutableLiftedILFunction},
platform::Platform,
rc::*,
relocation::CoreRelocationHandler,
string::BnStrCompatible,
string::*,
- types::{Conf, NameAndType, Type},
- {BranchType, Endianness},
+ types::{NameAndType, Type},
+ Endianness,
+};
+use std::ops::Deref;
+use std::{
+ borrow::{Borrow, Cow},
+ collections::HashMap,
+ ffi::{c_char, c_int, c_void, CStr, CString},
+ fmt::Display,
+ hash::Hash,
+ mem::MaybeUninit,
};
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum BranchInfo {
+use crate::function_recognizer::FunctionRecognizer;
+use crate::relocation::{CustomRelocationHandlerHandle, RelocationHandler};
+
+use crate::confidence::Conf;
+use crate::low_level_il::expression::ValueExpr;
+use crate::low_level_il::lifting::{
+ get_default_flag_cond_llil, get_default_flag_write_llil, LowLevelILFlagWriteOp,
+};
+pub use binaryninjacore_sys::BNFlagRole as FlagRole;
+pub use binaryninjacore_sys::BNImplicitRegisterExtend as ImplicitRegisterExtend;
+pub use binaryninjacore_sys::BNLowLevelILFlagCondition as FlagCondition;
+
+macro_rules! newtype {
+ ($name:ident, $inner_type:ty) => {
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+ pub struct $name(pub $inner_type);
+
+ impl From<$inner_type> for $name {
+ fn from(value: $inner_type) -> Self {
+ Self(value)
+ }
+ }
+
+ impl From<$name> for $inner_type {
+ fn from(value: $name) -> Self {
+ value.0
+ }
+ }
+
+ impl Display for $name {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.0)
+ }
+ }
+ };
+}
+
+newtype!(RegisterId, u32);
+newtype!(RegisterStackId, u32);
+newtype!(FlagId, u32);
+// TODO: Make this NonZero<u32>?
+newtype!(FlagWriteId, u32);
+newtype!(FlagClassId, u32);
+newtype!(FlagGroupId, u32);
+newtype!(IntrinsicId, u32);
+
+#[derive(Default, Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum BranchKind {
+ #[default]
+ Unresolved,
Unconditional(u64),
False(u64),
True(u64),
@@ -53,134 +100,180 @@ pub enum BranchInfo {
SystemCall,
Indirect,
Exception,
- Unresolved,
UserDefined,
}
-pub struct BranchIter<'a>(&'a InstructionInfo, ops::Range<usize>);
-impl<'a> Iterator for BranchIter<'a> {
- type Item = (BranchInfo, Option<CoreArchitecture>);
-
- fn next(&mut self) -> Option<Self::Item> {
- use crate::BranchType::*;
+#[derive(Default, Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct BranchInfo {
+ /// If `None` the target architecture is the same as the branch instruction.
+ pub arch: Option<CoreArchitecture>,
+ pub kind: BranchKind,
+}
- match self.1.next() {
- Some(i) => {
- let target = (self.0).0.branchTarget[i];
- let arch = (self.0).0.branchArch[i];
- let arch = if arch.is_null() {
- None
- } else {
- Some(CoreArchitecture(arch))
- };
+impl BranchInfo {
+ /// Branches to an instruction with the current architecture.
+ pub fn new(kind: BranchKind) -> Self {
+ Self { arch: None, kind }
+ }
- let res = match (self.0).0.branchType[i] {
- UnconditionalBranch => BranchInfo::Unconditional(target),
- FalseBranch => BranchInfo::False(target),
- TrueBranch => BranchInfo::True(target),
- CallDestination => BranchInfo::Call(target),
- FunctionReturn => BranchInfo::FunctionReturn,
- SystemCall => BranchInfo::SystemCall,
- IndirectBranch => BranchInfo::Indirect,
- ExceptionBranch => BranchInfo::Exception,
- UnresolvedBranch => BranchInfo::Unresolved,
- UserDefinedBranch => BranchInfo::UserDefined,
- };
+ /// Branches to an instruction with an explicit architecture.
+ ///
+ /// Use this if your architecture can transition to another architecture with a branch.
+ pub fn new_with_arch(kind: BranchKind, arch: CoreArchitecture) -> Self {
+ Self {
+ arch: Some(arch),
+ kind,
+ }
+ }
- Some((res, arch))
- }
+ pub fn target(&self) -> Option<u64> {
+ match self.kind {
+ BranchKind::Unconditional(target) => Some(target),
+ BranchKind::False(target) => Some(target),
+ BranchKind::True(target) => Some(target),
+ BranchKind::Call(target) => Some(target),
_ => None,
}
}
}
-#[repr(C)]
-pub struct InstructionInfo(BNInstructionInfo);
-impl InstructionInfo {
- pub fn new(len: usize, delay_slots: u8) -> Self {
- InstructionInfo(BNInstructionInfo {
- length: len,
- archTransitionByTargetAddr: false,
- delaySlots: delay_slots,
- branchCount: 0usize,
- branchType: [BranchType::UnresolvedBranch; 3],
- branchTarget: [0u64; 3],
- branchArch: [ptr::null_mut(); 3],
- })
+impl From<BranchInfo> for BNBranchType {
+ fn from(value: BranchInfo) -> Self {
+ match value.kind {
+ BranchKind::Unresolved => BNBranchType::UnresolvedBranch,
+ BranchKind::Unconditional(_) => BNBranchType::UnconditionalBranch,
+ BranchKind::False(_) => BNBranchType::FalseBranch,
+ BranchKind::True(_) => BNBranchType::TrueBranch,
+ BranchKind::Call(_) => BNBranchType::CallDestination,
+ BranchKind::FunctionReturn => BNBranchType::FunctionReturn,
+ BranchKind::SystemCall => BNBranchType::SystemCall,
+ BranchKind::Indirect => BNBranchType::IndirectBranch,
+ BranchKind::Exception => BNBranchType::ExceptionBranch,
+ BranchKind::UserDefined => BNBranchType::UserDefinedBranch,
+ }
}
+}
- pub fn len(&self) -> usize {
- self.0.length
+impl From<BranchKind> for BranchInfo {
+ fn from(value: BranchKind) -> Self {
+ Self {
+ arch: None,
+ kind: value,
+ }
}
+}
- pub fn is_empty(&self) -> bool {
- self.0.length == 0
- }
+/// This is the number of branches that can be specified in an [`InstructionInfo`].
+pub const NUM_BRANCH_INFO: usize = 3;
- pub fn branch_count(&self) -> usize {
- self.0.branchCount
- }
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct InstructionInfo {
+ pub length: usize,
+ // TODO: This field name is really long...
+ pub arch_transition_by_target_addr: bool,
+ pub delay_slots: u8,
+ pub branches: [Option<BranchInfo>; NUM_BRANCH_INFO],
+}
- pub fn delay_slots(&self) -> u8 {
- self.0.delaySlots
+impl InstructionInfo {
+ // TODO: `new_with_delay_slot`?
+ pub fn new(length: usize, delay_slots: u8) -> Self {
+ Self {
+ length,
+ arch_transition_by_target_addr: false,
+ delay_slots,
+ branches: Default::default(),
+ }
}
- pub fn branches(&self) -> BranchIter {
- BranchIter(self, 0..self.branch_count())
+ pub fn add_branch(&mut self, branch_info: impl Into<BranchInfo>) {
+ // Will go through each slot and attempt to add the branch info.
+ // TODO: Return a result with BranchInfoSlotsFilled error.
+ for branch in &mut self.branches {
+ if branch.is_none() {
+ *branch = Some(branch_info.into());
+ return;
+ }
+ }
}
+}
- pub fn allow_arch_transition_by_target_addr(&mut self, transition: bool) {
- self.0.archTransitionByTargetAddr = transition;
+impl From<BNInstructionInfo> for InstructionInfo {
+ fn from(value: BNInstructionInfo) -> Self {
+ // TODO: This is quite ugly, but we destructure the branch info so this will have to do.
+ let mut branch_info = [None; NUM_BRANCH_INFO];
+ #[allow(clippy::needless_range_loop)]
+ for i in 0..value.branchCount.min(NUM_BRANCH_INFO) {
+ let branch_target = value.branchTarget[i];
+ branch_info[i] = Some(BranchInfo {
+ kind: match value.branchType[i] {
+ BNBranchType::UnconditionalBranch => BranchKind::Unconditional(branch_target),
+ BNBranchType::FalseBranch => BranchKind::False(branch_target),
+ BNBranchType::TrueBranch => BranchKind::True(branch_target),
+ BNBranchType::CallDestination => BranchKind::Call(branch_target),
+ BNBranchType::FunctionReturn => BranchKind::FunctionReturn,
+ BNBranchType::SystemCall => BranchKind::SystemCall,
+ BNBranchType::IndirectBranch => BranchKind::Indirect,
+ BNBranchType::ExceptionBranch => BranchKind::Exception,
+ BNBranchType::UnresolvedBranch => BranchKind::Unresolved,
+ BNBranchType::UserDefinedBranch => BranchKind::UserDefined,
+ },
+ arch: if value.branchArch[i].is_null() {
+ None
+ } else {
+ Some(unsafe { CoreArchitecture::from_raw(value.branchArch[i]) })
+ },
+ });
+ }
+ Self {
+ length: value.length,
+ arch_transition_by_target_addr: value.archTransitionByTargetAddr,
+ delay_slots: value.delaySlots,
+ branches: branch_info,
+ }
}
+}
- pub fn add_branch(&mut self, branch: BranchInfo, arch: Option<CoreArchitecture>) {
- if self.0.branchCount < self.0.branchType.len() {
- let idx = self.0.branchCount;
-
- let ty = match branch {
- BranchInfo::Unconditional(t) => {
- self.0.branchTarget[idx] = t;
- BranchType::UnconditionalBranch
- }
- BranchInfo::False(t) => {
- self.0.branchTarget[idx] = t;
- BranchType::FalseBranch
- }
- BranchInfo::True(t) => {
- self.0.branchTarget[idx] = t;
- BranchType::TrueBranch
- }
- BranchInfo::Call(t) => {
- self.0.branchTarget[idx] = t;
- BranchType::CallDestination
- }
- BranchInfo::FunctionReturn => BranchType::FunctionReturn,
- BranchInfo::SystemCall => BranchType::SystemCall,
- BranchInfo::Indirect => BranchType::IndirectBranch,
- BranchInfo::Exception => BranchType::ExceptionBranch,
- BranchInfo::Unresolved => BranchType::UnresolvedBranch,
- BranchInfo::UserDefined => BranchType::UserDefinedBranch,
- };
-
- self.0.branchType[idx] = ty;
- self.0.branchArch[idx] = match arch {
- Some(a) => a.0,
- _ => ptr::null_mut(),
- };
-
- self.0.branchCount += 1;
- } else {
- error!("Attempt to branch to instruction with no additional branch space!");
+impl From<InstructionInfo> for BNInstructionInfo {
+ fn from(value: InstructionInfo) -> Self {
+ let branch_count = value.branches.into_iter().filter(Option::is_some).count();
+ // TODO: This is quite ugly, but we destructure the branch info so this will have to do.
+ let branch_info_0 = value.branches[0].unwrap_or_default();
+ let branch_info_1 = value.branches[1].unwrap_or_default();
+ let branch_info_2 = value.branches[2].unwrap_or_default();
+ Self {
+ length: value.length,
+ branchCount: branch_count,
+ archTransitionByTargetAddr: value.arch_transition_by_target_addr,
+ delaySlots: value.delay_slots,
+ branchType: [
+ branch_info_0.into(),
+ branch_info_1.into(),
+ branch_info_2.into(),
+ ],
+ branchTarget: [
+ branch_info_0.target().unwrap_or_default(),
+ branch_info_1.target().unwrap_or_default(),
+ branch_info_2.target().unwrap_or_default(),
+ ],
+ branchArch: [
+ branch_info_0
+ .arch
+ .map(|a| a.handle)
+ .unwrap_or(std::ptr::null_mut()),
+ branch_info_1
+ .arch
+ .map(|a| a.handle)
+ .unwrap_or(std::ptr::null_mut()),
+ branch_info_2
+ .arch
+ .map(|a| a.handle)
+ .unwrap_or(std::ptr::null_mut()),
+ ],
}
}
}
-use crate::functionrecognizer::FunctionRecognizer;
-use crate::relocation::{CustomRelocationHandlerHandle, RelocationHandler};
-pub use binaryninjacore_sys::BNFlagRole as FlagRole;
-pub use binaryninjacore_sys::BNImplicitRegisterExtend as ImplicitRegisterExtend;
-pub use binaryninjacore_sys::BNLowLevelILFlagCondition as FlagCondition;
-
pub trait RegisterInfo: Sized {
type RegType: Register<InfoType = Self>;
@@ -190,7 +283,7 @@ pub trait RegisterInfo: Sized {
fn implicit_extend(&self) -> ImplicitRegisterExtend;
}
-pub trait Register: Sized + Clone + Copy + Hash + Eq {
+pub trait Register: Debug + Sized + Clone + Copy + Hash + Eq {
type InfoType: RegisterInfo<RegType = Self>;
fn name(&self) -> Cow<str>;
@@ -199,7 +292,7 @@ pub trait Register: Sized + Clone + Copy + Hash + Eq {
/// Unique identifier for this `Register`.
///
/// *MUST* be in the range [0, 0x7fff_ffff]
- fn id(&self) -> u32;
+ fn id(&self) -> RegisterId;
}
pub trait RegisterStackInfo: Sized {
@@ -207,8 +300,8 @@ pub trait RegisterStackInfo: Sized {
type RegType: Register<InfoType = Self::RegInfoType>;
type RegInfoType: RegisterInfo<RegType = Self::RegType>;
- fn storage_regs(&self) -> (Self::RegType, u32);
- fn top_relative_regs(&self) -> Option<(Self::RegType, u32)>;
+ fn storage_regs(&self) -> (Self::RegType, usize);
+ fn top_relative_regs(&self) -> Option<(Self::RegType, usize)>;
fn stack_top_reg(&self) -> Self::RegType;
}
@@ -227,10 +320,10 @@ pub trait RegisterStack: Sized + Clone + Copy {
/// Unique identifier for this `RegisterStack`.
///
/// *MUST* be in the range [0, 0x7fff_ffff]
- fn id(&self) -> u32;
+ fn id(&self) -> RegisterStackId;
}
-pub trait Flag: Sized + Clone + Copy + Hash + Eq {
+pub trait Flag: Debug + Sized + Clone + Copy + Hash + Eq {
type FlagClass: FlagClass;
fn name(&self) -> Cow<str>;
@@ -239,7 +332,7 @@ pub trait Flag: Sized + Clone + Copy + Hash + Eq {
/// Unique identifier for this `Flag`.
///
/// *MUST* be in the range [0, 0x7fff_ffff]
- fn id(&self) -> u32;
+ fn id(&self) -> FlagId;
}
pub trait FlagWrite: Sized + Clone + Copy {
@@ -253,7 +346,7 @@ pub trait FlagWrite: Sized + Clone + Copy {
///
/// *MUST NOT* be 0.
/// *MUST* be in the range [1, 0x7fff_ffff]
- fn id(&self) -> u32;
+ fn id(&self) -> FlagWriteId;
fn flags_written(&self) -> Vec<Self::FlagType>;
}
@@ -265,10 +358,10 @@ pub trait FlagClass: Sized + Clone + Copy + Hash + Eq {
///
/// *MUST NOT* be 0.
/// *MUST* be in the range [1, 0x7fff_ffff]
- fn id(&self) -> u32;
+ fn id(&self) -> FlagClassId;
}
-pub trait FlagGroup: Sized + Clone + Copy {
+pub trait FlagGroup: Debug + Sized + Clone + Copy {
type FlagType: Flag;
type FlagClass: FlagClass;
@@ -277,7 +370,7 @@ pub trait FlagGroup: Sized + Clone + Copy {
/// Unique identifier for this `FlagGroup`.
///
/// *MUST* be in the range [0, 0x7fff_ffff]
- fn id(&self) -> u32;
+ fn id(&self) -> FlagGroupId;
/// Returns the list of flags that need to be resolved in order
/// to take the clean flag resolution path -- at time of writing,
@@ -306,16 +399,22 @@ pub trait FlagGroup: Sized + Clone + Copy {
fn flag_conditions(&self) -> HashMap<Self::FlagClass, FlagCondition>;
}
-pub trait Intrinsic: Sized + Clone + Copy {
+pub trait Intrinsic: Debug + Sized + Clone + Copy {
fn name(&self) -> Cow<str>;
/// Unique identifier for this `Intrinsic`.
- fn id(&self) -> u32;
+ fn id(&self) -> IntrinsicId;
+
+ /// The intrinsic class for this `Intrinsic`.
+ fn class(&self) -> BNIntrinsicClass {
+ BNIntrinsicClass::GeneralIntrinsicClass
+ }
- /// Reeturns the list of the input names and types for this intrinsic.
- fn inputs(&self) -> Vec<Ref<NameAndType>>;
+ // TODO: Maybe just return `(String, Conf<Ref<Type>>)`?
+ /// List of the input names and types for this intrinsic.
+ fn inputs(&self) -> Vec<NameAndType>;
- /// Returns the list of the output types for this intrinsic.
+ /// List of the output types for this intrinsic.
fn outputs(&self) -> Vec<Conf<Ref<Type>>>;
}
@@ -349,7 +448,7 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
fn max_instr_len(&self) -> usize;
fn opcode_display_len(&self) -> usize;
- fn associated_arch_by_addr(&self, addr: &mut u64) -> CoreArchitecture;
+ fn associated_arch_by_addr(&self, addr: u64) -> CoreArchitecture;
fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo>;
fn instruction_text(
@@ -361,7 +460,7 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
&self,
data: &[u8],
addr: u64,
- il: &mut Lifter<Self>,
+ il: &mut MutableLiftedILFunction<Self>,
) -> Option<(usize, bool)>;
/// Fallback flag value calculation path. This method is invoked when the core is unable to
@@ -377,9 +476,9 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
&self,
flag: Self::Flag,
flag_write_type: Self::FlagWrite,
- op: FlagWriteOp<Self::Register>,
- il: &'a mut Lifter<Self>,
- ) -> Option<LiftedExpr<'a, Self>> {
+ op: LowLevelILFlagWriteOp<Self::Register>,
+ il: &'a mut MutableLiftedILFunction<Self>,
+ ) -> Option<MutableLiftedILExpr<'a, Self, ValueExpr>> {
let role = flag.role(flag_write_type.class());
Some(get_default_flag_write_llil(self, role, op, il))
}
@@ -407,8 +506,8 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
&self,
cond: FlagCondition,
class: Option<Self::FlagClass>,
- il: &'a mut Lifter<Self>,
- ) -> Option<LiftedExpr<'a, Self>> {
+ il: &'a mut MutableLiftedILFunction<Self>,
+ ) -> Option<MutableLiftedILExpr<'a, Self, ValueExpr>> {
Some(get_default_flag_cond_llil(self, cond, class, il))
}
@@ -429,8 +528,8 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
fn flag_group_llil<'a>(
&self,
_group: Self::FlagGroup,
- _il: &'a mut Lifter<Self>,
- ) -> Option<LiftedExpr<'a, Self>> {
+ _il: &'a mut MutableLiftedILFunction<Self>,
+ ) -> Option<MutableLiftedILExpr<'a, Self, ValueExpr>> {
None
}
@@ -465,32 +564,32 @@ pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
None
}
- fn register_from_id(&self, id: u32) -> Option<Self::Register>;
+ fn register_from_id(&self, id: RegisterId) -> Option<Self::Register>;
- fn register_stack_from_id(&self, _id: u32) -> Option<Self::RegisterStack> {
+ fn register_stack_from_id(&self, _id: RegisterStackId) -> Option<Self::RegisterStack> {
None
}
- fn flag_from_id(&self, _id: u32) -> Option<Self::Flag> {
+ fn flag_from_id(&self, _id: FlagId) -> Option<Self::Flag> {
None
}
- fn flag_write_from_id(&self, _id: u32) -> Option<Self::FlagWrite> {
+ fn flag_write_from_id(&self, _id: FlagWriteId) -> Option<Self::FlagWrite> {
None
}
- fn flag_class_from_id(&self, _id: u32) -> Option<Self::FlagClass> {
+ fn flag_class_from_id(&self, _id: FlagClassId) -> Option<Self::FlagClass> {
None
}
- fn flag_group_from_id(&self, _id: u32) -> Option<Self::FlagGroup> {
+ fn flag_group_from_id(&self, _id: FlagGroupId) -> Option<Self::FlagGroup> {
None
}
fn intrinsics(&self) -> Vec<Self::Intrinsic> {
Vec::new()
}
- fn intrinsic_class(&self, _id: u32) -> binaryninjacore_sys::BNIntrinsicClass {
- binaryninjacore_sys::BNIntrinsicClass::GeneralIntrinsicClass
+ fn intrinsic_class(&self, _id: IntrinsicId) -> BNIntrinsicClass {
+ BNIntrinsicClass::GeneralIntrinsicClass
}
- fn intrinsic_from_id(&self, _id: u32) -> Option<Self::Intrinsic> {
+ fn intrinsic_from_id(&self, _id: IntrinsicId) -> Option<Self::Intrinsic> {
None
}
@@ -552,10 +651,10 @@ impl<R: Register> RegisterStackInfo for UnusedRegisterStackInfo<R> {
type RegType = R;
type RegInfoType = R::InfoType;
- fn storage_regs(&self) -> (Self::RegType, u32) {
+ fn storage_regs(&self) -> (Self::RegType, usize) {
unreachable!()
}
- fn top_relative_regs(&self) -> Option<(Self::RegType, u32)> {
+ fn top_relative_regs(&self) -> Option<(Self::RegType, usize)> {
unreachable!()
}
fn stack_top_reg(&self) -> Self::RegType {
@@ -571,7 +670,7 @@ impl<R: Register> RegisterStack for UnusedRegisterStack<R> {
fn name(&self) -> Cow<str> {
unreachable!()
}
- fn id(&self) -> u32 {
+ fn id(&self) -> RegisterStackId {
unreachable!()
}
fn info(&self) -> Self::InfoType {
@@ -580,7 +679,7 @@ impl<R: Register> RegisterStack for UnusedRegisterStack<R> {
}
/// Type for architrectures that do not use flags. Will panic if accessed as a flag.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct UnusedFlag;
impl Flag for UnusedFlag {
@@ -591,7 +690,7 @@ impl Flag for UnusedFlag {
fn role(&self, _class: Option<Self::FlagClass>) -> FlagRole {
unreachable!()
}
- fn id(&self) -> u32 {
+ fn id(&self) -> FlagId {
unreachable!()
}
}
@@ -605,7 +704,7 @@ impl FlagWrite for UnusedFlag {
fn class(&self) -> Option<Self> {
unreachable!()
}
- fn id(&self) -> u32 {
+ fn id(&self) -> FlagWriteId {
unreachable!()
}
fn flags_written(&self) -> Vec<Self::FlagType> {
@@ -617,7 +716,7 @@ impl FlagClass for UnusedFlag {
fn name(&self) -> Cow<str> {
unreachable!()
}
- fn id(&self) -> u32 {
+ fn id(&self) -> FlagClassId {
unreachable!()
}
}
@@ -628,7 +727,7 @@ impl FlagGroup for UnusedFlag {
fn name(&self) -> Cow<str> {
unreachable!()
}
- fn id(&self) -> u32 {
+ fn id(&self) -> FlagGroupId {
unreachable!()
}
fn flags_required(&self) -> Vec<Self::FlagType> {
@@ -640,17 +739,17 @@ impl FlagGroup for UnusedFlag {
}
/// Type for architrectures that do not use intrinsics. Will panic if accessed as an intrinsic.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct UnusedIntrinsic;
impl Intrinsic for UnusedIntrinsic {
fn name(&self) -> Cow<str> {
unreachable!()
}
- fn id(&self) -> u32 {
+ fn id(&self) -> IntrinsicId {
unreachable!()
}
- fn inputs(&self) -> Vec<Ref<NameAndType>> {
+ fn inputs(&self) -> Vec<NameAndType> {
unreachable!()
}
fn outputs(&self) -> Vec<Conf<Ref<Type>>> {
@@ -658,39 +757,77 @@ impl Intrinsic for UnusedIntrinsic {
}
}
-pub struct CoreRegisterInfo(*mut BNArchitecture, u32, BNRegisterInfo);
+#[derive(Debug, Copy, Clone)]
+pub struct CoreRegisterInfo {
+ arch: CoreArchitecture,
+ id: RegisterId,
+ info: BNRegisterInfo,
+}
+
+impl CoreRegisterInfo {
+ pub fn new(arch: CoreArchitecture, id: RegisterId, info: BNRegisterInfo) -> Self {
+ Self { arch, id, info }
+ }
+}
+
impl RegisterInfo for CoreRegisterInfo {
type RegType = CoreRegister;
fn parent(&self) -> Option<CoreRegister> {
- if self.1 != self.2.fullWidthRegister {
- Some(CoreRegister(self.0, self.2.fullWidthRegister))
+ if self.id != RegisterId::from(self.info.fullWidthRegister) {
+ Some(CoreRegister::new(
+ self.arch,
+ RegisterId::from(self.info.fullWidthRegister),
+ )?)
} else {
None
}
}
fn size(&self) -> usize {
- self.2.size
+ self.info.size
}
fn offset(&self) -> usize {
- self.2.offset
+ self.info.offset
}
fn implicit_extend(&self) -> ImplicitRegisterExtend {
- self.2.extend
+ self.info.extend
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
-pub struct CoreRegister(*mut BNArchitecture, u32);
+pub struct CoreRegister {
+ arch: CoreArchitecture,
+ id: RegisterId,
+}
+
+impl CoreRegister {
+ pub fn new(arch: CoreArchitecture, id: RegisterId) -> Option<Self> {
+ let register = Self { arch, id };
+ register.is_valid().then_some(register)
+ }
+
+ fn is_valid(&self) -> bool {
+ // We check the name to see if the register is actually valid.
+ let name = unsafe { BNGetArchitectureRegisterName(self.arch.handle, self.id.into()) };
+ match name.is_null() {
+ true => false,
+ false => {
+ unsafe { BNFreeString(name) };
+ true
+ }
+ }
+ }
+}
+
impl Register for CoreRegister {
type InfoType = CoreRegisterInfo;
fn name(&self) -> Cow<str> {
unsafe {
- let name = BNGetArchitectureRegisterName(self.0, self.1);
+ let name = BNGetArchitectureRegisterName(self.arch.handle, self.id.into());
// We need to guarantee ownership, as if we're still
// a Borrowed variant we're about to free the underlying
@@ -705,13 +842,21 @@ impl Register for CoreRegister {
}
fn info(&self) -> CoreRegisterInfo {
- CoreRegisterInfo(self.0, self.1, unsafe {
- BNGetArchitectureRegisterInfo(self.0, self.1)
+ CoreRegisterInfo::new(self.arch, self.id, unsafe {
+ BNGetArchitectureRegisterInfo(self.arch.handle, self.id.into())
})
}
- fn id(&self) -> u32 {
- self.1
+ fn id(&self) -> RegisterId {
+ self.id
+ }
+}
+
+impl Debug for CoreRegister {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("CoreRegister")
+ .field("id", &self.id)
+ .finish()
}
}
@@ -725,43 +870,80 @@ unsafe impl CoreArrayProviderInner for CoreRegister {
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
BNFreeRegisterList(raw)
}
+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
- Self(context.0, *raw)
+ Self::new(*context, RegisterId::from(*raw)).expect("Register list contains valid registers")
}
}
-pub struct CoreRegisterStackInfo(*mut BNArchitecture, BNRegisterStackInfo);
+#[derive(Debug, Copy, Clone)]
+pub struct CoreRegisterStackInfo {
+ arch: CoreArchitecture,
+ // TODO: Wrap BNRegisterStackInfo
+ info: BNRegisterStackInfo,
+}
+
+impl CoreRegisterStackInfo {
+ pub fn new(arch: CoreArchitecture, info: BNRegisterStackInfo) -> Self {
+ Self { arch, info }
+ }
+}
impl RegisterStackInfo for CoreRegisterStackInfo {
type RegStackType = CoreRegisterStack;
type RegType = CoreRegister;
type RegInfoType = CoreRegisterInfo;
- fn storage_regs(&self) -> (Self::RegType, u32) {
+ fn storage_regs(&self) -> (Self::RegType, usize) {
(
- CoreRegister(self.0, self.1.firstStorageReg),
- self.1.storageCount,
+ CoreRegister::new(self.arch, RegisterId::from(self.info.firstStorageReg))
+ .expect("Storage register is valid"),
+ self.info.storageCount as usize,
)
}
- fn top_relative_regs(&self) -> Option<(Self::RegType, u32)> {
- if self.1.topRelativeCount == 0 {
+ fn top_relative_regs(&self) -> Option<(Self::RegType, usize)> {
+ if self.info.topRelativeCount == 0 {
None
} else {
Some((
- CoreRegister(self.0, self.1.firstTopRelativeReg),
- self.1.topRelativeCount,
+ CoreRegister::new(self.arch, RegisterId::from(self.info.firstTopRelativeReg))
+ .expect("Top relative register is valid"),
+ self.info.topRelativeCount as usize,
))
}
}
fn stack_top_reg(&self) -> Self::RegType {
- CoreRegister(self.0, self.1.stackTopReg)
+ CoreRegister::new(self.arch, RegisterId::from(self.info.stackTopReg))
+ .expect("Stack top register is valid")
}
}
-#[derive(Copy, Clone, Eq, PartialEq, Hash)]
-pub struct CoreRegisterStack(*mut BNArchitecture, u32);
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct CoreRegisterStack {
+ arch: CoreArchitecture,
+ id: RegisterStackId,
+}
+
+impl CoreRegisterStack {
+ pub fn new(arch: CoreArchitecture, id: RegisterStackId) -> Option<Self> {
+ let register_stack = Self { arch, id };
+ register_stack.is_valid().then_some(register_stack)
+ }
+
+ fn is_valid(&self) -> bool {
+ // We check the name to see if the stack register is actually valid.
+ let name = unsafe { BNGetArchitectureRegisterStackName(self.arch.handle, self.id.into()) };
+ match name.is_null() {
+ true => false,
+ false => {
+ unsafe { BNFreeString(name) };
+ true
+ }
+ }
+ }
+}
impl RegisterStack for CoreRegisterStack {
type InfoType = CoreRegisterStackInfo;
@@ -770,7 +952,7 @@ impl RegisterStack for CoreRegisterStack {
fn name(&self) -> Cow<str> {
unsafe {
- let name = BNGetArchitectureRegisterStackName(self.0, self.1);
+ let name = BNGetArchitectureRegisterStackName(self.arch.handle, self.id.into());
// We need to guarantee ownership, as if we're still
// a Borrowed variant we're about to free the underlying
@@ -785,24 +967,47 @@ impl RegisterStack for CoreRegisterStack {
}
fn info(&self) -> CoreRegisterStackInfo {
- CoreRegisterStackInfo(self.0, unsafe {
- BNGetArchitectureRegisterStackInfo(self.0, self.1)
+ CoreRegisterStackInfo::new(self.arch, unsafe {
+ BNGetArchitectureRegisterStackInfo(self.arch.handle, self.id.into())
})
}
- fn id(&self) -> u32 {
- self.1
+ fn id(&self) -> RegisterStackId {
+ self.id
+ }
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct CoreFlag {
+ arch: CoreArchitecture,
+ id: FlagId,
+}
+
+impl CoreFlag {
+ pub fn new(arch: CoreArchitecture, id: FlagId) -> Option<Self> {
+ let flag = Self { arch, id };
+ flag.is_valid().then_some(flag)
+ }
+
+ fn is_valid(&self) -> bool {
+ // We check the name to see if the flag is actually valid.
+ let name = unsafe { BNGetArchitectureFlagName(self.arch.handle, self.id.into()) };
+ match name.is_null() {
+ true => false,
+ false => {
+ unsafe { BNFreeString(name) };
+ true
+ }
+ }
}
}
-#[derive(Copy, Clone, Eq, PartialEq, Hash)]
-pub struct CoreFlag(*mut BNArchitecture, u32);
impl Flag for CoreFlag {
type FlagClass = CoreFlagClass;
fn name(&self) -> Cow<str> {
unsafe {
- let name = BNGetArchitectureFlagName(self.0, self.1);
+ let name = BNGetArchitectureFlagName(self.arch.handle, self.id.into());
// We need to guarantee ownership, as if we're still
// a Borrowed variant we're about to free the underlying
@@ -817,28 +1022,52 @@ impl Flag for CoreFlag {
}
fn role(&self, class: Option<CoreFlagClass>) -> FlagRole {
- let class_id = match class {
- Some(class) => class.1,
- _ => 0,
- };
-
- unsafe { BNGetArchitectureFlagRole(self.0, self.1, class_id) }
+ unsafe {
+ BNGetArchitectureFlagRole(
+ self.arch.handle,
+ self.id.into(),
+ class.map(|c| c.id.0).unwrap_or(0),
+ )
+ }
}
- fn id(&self) -> u32 {
- self.1
+ fn id(&self) -> FlagId {
+ self.id
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
-pub struct CoreFlagWrite(*mut BNArchitecture, u32);
+pub struct CoreFlagWrite {
+ arch: CoreArchitecture,
+ id: FlagWriteId,
+}
+
+impl CoreFlagWrite {
+ pub fn new(arch: CoreArchitecture, id: FlagWriteId) -> Option<Self> {
+ let flag_write = Self { arch, id };
+ flag_write.is_valid().then_some(flag_write)
+ }
+
+ fn is_valid(&self) -> bool {
+ // We check the name to see if the flag write is actually valid.
+ let name = unsafe { BNGetArchitectureFlagWriteTypeName(self.arch.handle, self.id.into()) };
+ match name.is_null() {
+ true => false,
+ false => {
+ unsafe { BNFreeString(name) };
+ true
+ }
+ }
+ }
+}
+
impl FlagWrite for CoreFlagWrite {
type FlagType = CoreFlag;
type FlagClass = CoreFlagClass;
fn name(&self) -> Cow<str> {
unsafe {
- let name = BNGetArchitectureFlagWriteTypeName(self.0, self.1);
+ let name = BNGetArchitectureFlagWriteTypeName(self.arch.handle, self.id.into());
// We need to guarantee ownership, as if we're still
// a Borrowed variant we're about to free the underlying
@@ -852,20 +1081,36 @@ impl FlagWrite for CoreFlagWrite {
}
}
- fn id(&self) -> u32 {
- self.1
+ fn class(&self) -> Option<CoreFlagClass> {
+ let class = unsafe {
+ BNGetArchitectureSemanticClassForFlagWriteType(self.arch.handle, self.id.into())
+ };
+
+ match class {
+ 0 => None,
+ class_id => Some(CoreFlagClass::new(self.arch, class_id.into())?),
+ }
+ }
+
+ fn id(&self) -> FlagWriteId {
+ self.id
}
fn flags_written(&self) -> Vec<CoreFlag> {
let mut count: usize = 0;
let regs: *mut u32 = unsafe {
- BNGetArchitectureFlagsWrittenByFlagWriteType(self.0, self.1, &mut count as *mut _)
+ BNGetArchitectureFlagsWrittenByFlagWriteType(
+ self.arch.handle,
+ self.id.into(),
+ &mut count,
+ )
};
let ret = unsafe {
- slice::from_raw_parts_mut(regs, count)
+ std::slice::from_raw_parts(regs, count)
.iter()
- .map(|reg| CoreFlag(self.0, *reg))
+ .map(|id| FlagId::from(*id))
+ .filter_map(|reg| CoreFlag::new(self.arch, reg))
.collect()
};
@@ -875,23 +1120,38 @@ impl FlagWrite for CoreFlagWrite {
ret
}
+}
- fn class(&self) -> Option<CoreFlagClass> {
- let class = unsafe { BNGetArchitectureSemanticClassForFlagWriteType(self.0, self.1) };
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct CoreFlagClass {
+ arch: CoreArchitecture,
+ id: FlagClassId,
+}
- match class {
- 0 => None,
- id => Some(CoreFlagClass(self.0, id)),
+impl CoreFlagClass {
+ pub fn new(arch: CoreArchitecture, id: FlagClassId) -> Option<Self> {
+ let flag = Self { arch, id };
+ flag.is_valid().then_some(flag)
+ }
+
+ fn is_valid(&self) -> bool {
+ // We check the name to see if the flag is actually valid.
+ let name =
+ unsafe { BNGetArchitectureSemanticFlagClassName(self.arch.handle, self.id.into()) };
+ match name.is_null() {
+ true => false,
+ false => {
+ unsafe { BNFreeString(name) };
+ true
+ }
}
}
}
-#[derive(Copy, Clone, Eq, PartialEq, Hash)]
-pub struct CoreFlagClass(*mut BNArchitecture, u32);
impl FlagClass for CoreFlagClass {
fn name(&self) -> Cow<str> {
unsafe {
- let name = BNGetArchitectureSemanticFlagClassName(self.0, self.1);
+ let name = BNGetArchitectureSemanticFlagClassName(self.arch.handle, self.id.into());
// We need to guarantee ownership, as if we're still
// a Borrowed variant we're about to free the underlying
@@ -905,20 +1165,44 @@ impl FlagClass for CoreFlagClass {
}
}
- fn id(&self) -> u32 {
- self.1
+ fn id(&self) -> FlagClassId {
+ self.id
+ }
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct CoreFlagGroup {
+ arch: CoreArchitecture,
+ id: FlagGroupId,
+}
+
+impl CoreFlagGroup {
+ pub fn new(arch: CoreArchitecture, id: FlagGroupId) -> Option<Self> {
+ let flag_group = Self { arch, id };
+ flag_group.is_valid().then_some(flag_group)
+ }
+
+ fn is_valid(&self) -> bool {
+ // We check the name to see if the flag group is actually valid.
+ let name =
+ unsafe { BNGetArchitectureSemanticFlagGroupName(self.arch.handle, self.id.into()) };
+ match name.is_null() {
+ true => false,
+ false => {
+ unsafe { BNFreeString(name) };
+ true
+ }
+ }
}
}
-#[derive(Copy, Clone, Eq, PartialEq)]
-pub struct CoreFlagGroup(*mut BNArchitecture, u32);
impl FlagGroup for CoreFlagGroup {
type FlagType = CoreFlag;
type FlagClass = CoreFlagClass;
fn name(&self) -> Cow<str> {
unsafe {
- let name = BNGetArchitectureSemanticFlagGroupName(self.0, self.1);
+ let name = BNGetArchitectureSemanticFlagGroupName(self.arch.handle, self.id.into());
// We need to guarantee ownership, as if we're still
// a Borrowed variant we're about to free the underlying
@@ -932,20 +1216,25 @@ impl FlagGroup for CoreFlagGroup {
}
}
- fn id(&self) -> u32 {
- self.1
+ fn id(&self) -> FlagGroupId {
+ self.id
}
fn flags_required(&self) -> Vec<CoreFlag> {
let mut count: usize = 0;
let regs: *mut u32 = unsafe {
- BNGetArchitectureFlagsRequiredForSemanticFlagGroup(self.0, self.1, &mut count as *mut _)
+ BNGetArchitectureFlagsRequiredForSemanticFlagGroup(
+ self.arch.handle,
+ self.id.into(),
+ &mut count,
+ )
};
let ret = unsafe {
- slice::from_raw_parts_mut(regs, count)
+ std::slice::from_raw_parts(regs, count)
.iter()
- .map(|reg| CoreFlag(self.0, *reg))
+ .map(|id| FlagId::from(*id))
+ .filter_map(|reg| CoreFlag::new(self.arch, reg))
.collect()
};
@@ -961,18 +1250,18 @@ impl FlagGroup for CoreFlagGroup {
unsafe {
let flag_conds = BNGetArchitectureFlagConditionsForSemanticFlagGroup(
- self.0,
- self.1,
- &mut count as *mut _,
+ self.arch.handle,
+ self.id.into(),
+ &mut count,
);
- let ret = slice::from_raw_parts_mut(flag_conds, count)
+ let ret = std::slice::from_raw_parts_mut(flag_conds, count)
.iter()
- .map(|class_cond| {
- (
- CoreFlagClass(self.0, class_cond.semanticClass),
+ .filter_map(|class_cond| {
+ Some((
+ CoreFlagClass::new(self.arch, class_cond.semanticClass.into())?,
class_cond.condition,
- )
+ ))
})
.collect();
@@ -984,16 +1273,39 @@ impl FlagGroup for CoreFlagGroup {
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub struct CoreIntrinsic(pub(crate) *mut BNArchitecture, pub(crate) u32);
+pub struct CoreIntrinsic {
+ pub arch: CoreArchitecture,
+ pub id: IntrinsicId,
+}
+
+impl CoreIntrinsic {
+ pub fn new(arch: CoreArchitecture, id: IntrinsicId) -> Option<Self> {
+ let intrinsic = Self { arch, id };
+ intrinsic.is_valid().then_some(intrinsic)
+ }
+
+ fn is_valid(&self) -> bool {
+ // We check the name to see if the intrinsic is actually valid.
+ let name = unsafe { BNGetArchitectureIntrinsicName(self.arch.handle, self.id.into()) };
+ match name.is_null() {
+ true => false,
+ false => {
+ unsafe { BNFreeString(name) };
+ true
+ }
+ }
+ }
+}
-impl Intrinsic for crate::architecture::CoreIntrinsic {
+impl Intrinsic for CoreIntrinsic {
fn name(&self) -> Cow<str> {
unsafe {
- let name = BNGetArchitectureIntrinsicName(self.0, self.1);
+ let name = BNGetArchitectureIntrinsicName(self.arch.handle, self.id.into());
// We need to guarantee ownership, as if we're still
// a Borrowed variant we're about to free the underlying
// memory.
+ // TODO: ^ the above assertion nullifies any benefit to passing back Cow tho?
let res = CStr::from_ptr(name);
let res = res.to_string_lossy().into_owned().into();
@@ -1003,19 +1315,23 @@ impl Intrinsic for crate::architecture::CoreIntrinsic {
}
}
- fn id(&self) -> u32 {
- self.1
+ fn id(&self) -> IntrinsicId {
+ self.id
}
- fn inputs(&self) -> Vec<Ref<NameAndType>> {
- let mut count: usize = 0;
+ fn class(&self) -> BNIntrinsicClass {
+ unsafe { BNGetArchitectureIntrinsicClass(self.arch.handle, self.id.into()) }
+ }
+ fn inputs(&self) -> Vec<NameAndType> {
+ let mut count: usize = 0;
unsafe {
- let inputs = BNGetArchitectureIntrinsicInputs(self.0, self.1, &mut count as *mut _);
+ let inputs =
+ BNGetArchitectureIntrinsicInputs(self.arch.handle, self.id.into(), &mut count);
- let ret = slice::from_raw_parts_mut(inputs, count)
+ let ret = std::slice::from_raw_parts_mut(inputs, count)
.iter()
- .map(|x| NameAndType::from_raw(x).to_owned())
+ .map(NameAndType::from_raw)
.collect();
BNFreeNameAndTypeList(inputs, count);
@@ -1026,13 +1342,13 @@ impl Intrinsic for crate::architecture::CoreIntrinsic {
fn outputs(&self) -> Vec<Conf<Ref<Type>>> {
let mut count: usize = 0;
-
unsafe {
- let inputs = BNGetArchitectureIntrinsicOutputs(self.0, self.1, &mut count as *mut _);
+ let inputs =
+ BNGetArchitectureIntrinsicOutputs(self.arch.handle, self.id.into(), &mut count);
- let ret = slice::from_raw_parts_mut(inputs, count)
+ let ret = std::slice::from_raw_parts_mut(inputs, count)
.iter()
- .map(|input| (*input).into())
+ .map(Conf::<Ref<Type>>::from_raw)
.collect();
BNFreeOutputTypeList(inputs, count);
@@ -1042,12 +1358,14 @@ impl Intrinsic for crate::architecture::CoreIntrinsic {
}
}
+// TODO: WTF?!?!?!?
pub struct CoreArchitectureList(*mut *mut BNArchitecture, usize);
-impl ops::Deref for CoreArchitectureList {
+
+impl Deref for CoreArchitectureList {
type Target = [CoreArchitecture];
fn deref(&self) -> &Self::Target {
- unsafe { slice::from_raw_parts_mut(self.0 as *mut CoreArchitecture, self.1) }
+ unsafe { std::slice::from_raw_parts_mut(self.0 as *mut CoreArchitecture, self.1) }
}
}
@@ -1060,37 +1378,41 @@ impl Drop for CoreArchitectureList {
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct CoreArchitecture(pub(crate) *mut BNArchitecture);
-
-unsafe impl Send for CoreArchitecture {}
-unsafe impl Sync for CoreArchitecture {}
+pub struct CoreArchitecture {
+ pub(crate) handle: *mut BNArchitecture,
+}
impl CoreArchitecture {
- pub(crate) unsafe fn from_raw(raw: *mut BNArchitecture) -> Self {
- CoreArchitecture(raw)
+ // TODO: Leave a note on architecture lifetimes. Specifically that they are never freed.
+ pub(crate) unsafe fn from_raw(handle: *mut BNArchitecture) -> Self {
+ debug_assert!(!handle.is_null());
+ CoreArchitecture { handle }
}
pub fn list_all() -> CoreArchitectureList {
let mut count: usize = 0;
- let archs = unsafe { BNGetArchitectureList(&mut count as *mut _) };
+ let archs = unsafe { BNGetArchitectureList(&mut count) };
CoreArchitectureList(archs, count)
}
pub fn by_name(name: &str) -> Option<Self> {
- let res = unsafe { BNGetArchitectureByName(name.into_bytes_with_nul().as_ptr() as *mut _) };
-
- match res.is_null() {
- false => Some(CoreArchitecture(res)),
+ let handle =
+ unsafe { BNGetArchitectureByName(name.into_bytes_with_nul().as_ptr() as *mut _) };
+ match handle.is_null() {
+ false => Some(CoreArchitecture { handle }),
true => None,
}
}
pub fn name(&self) -> BnString {
- unsafe { BnString::from_raw(BNGetArchitectureName(self.0)) }
+ unsafe { BnString::from_raw(BNGetArchitectureName(self.handle)) }
}
}
+unsafe impl Send for CoreArchitecture {}
+unsafe impl Sync for CoreArchitecture {}
+
impl AsRef<CoreArchitecture> for CoreArchitecture {
fn as_ref(&self) -> &Self {
self
@@ -1111,49 +1433,39 @@ impl Architecture for CoreArchitecture {
type Intrinsic = CoreIntrinsic;
fn endianness(&self) -> Endianness {
- unsafe { BNGetArchitectureEndianness(self.0) }
+ unsafe { BNGetArchitectureEndianness(self.handle) }
}
fn address_size(&self) -> usize {
- unsafe { BNGetArchitectureAddressSize(self.0) }
+ unsafe { BNGetArchitectureAddressSize(self.handle) }
}
fn default_integer_size(&self) -> usize {
- unsafe { BNGetArchitectureDefaultIntegerSize(self.0) }
+ unsafe { BNGetArchitectureDefaultIntegerSize(self.handle) }
}
fn instruction_alignment(&self) -> usize {
- unsafe { BNGetArchitectureInstructionAlignment(self.0) }
+ unsafe { BNGetArchitectureInstructionAlignment(self.handle) }
}
fn max_instr_len(&self) -> usize {
- unsafe { BNGetArchitectureMaxInstructionLength(self.0) }
+ unsafe { BNGetArchitectureMaxInstructionLength(self.handle) }
}
fn opcode_display_len(&self) -> usize {
- unsafe { BNGetArchitectureOpcodeDisplayLength(self.0) }
+ unsafe { BNGetArchitectureOpcodeDisplayLength(self.handle) }
}
- fn associated_arch_by_addr(&self, addr: &mut u64) -> CoreArchitecture {
- let arch = unsafe { BNGetAssociatedArchitectureByAddress(self.0, addr as *mut _) };
-
- CoreArchitecture(arch)
+ fn associated_arch_by_addr(&self, addr: u64) -> CoreArchitecture {
+ let handle = unsafe { BNGetAssociatedArchitectureByAddress(self.handle, addr as *mut _) };
+ CoreArchitecture { handle }
}
fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo> {
- let mut info = unsafe { zeroed::<InstructionInfo>() };
- let success = unsafe {
- BNGetInstructionInfo(
- self.0,
- data.as_ptr(),
- addr,
- data.len(),
- &mut (info.0) as *mut _,
- )
- };
-
- if success {
- Some(info)
+ let mut info = BNInstructionInfo::default();
+ if unsafe { BNGetInstructionInfo(self.handle, data.as_ptr(), addr, data.len(), &mut info) }
+ {
+ Some(info.into())
} else {
None
}
@@ -1166,23 +1478,23 @@ impl Architecture for CoreArchitecture {
) -> Option<(usize, Vec<InstructionTextToken>)> {
let mut consumed = data.len();
let mut count: usize = 0;
- let mut result: *mut BNInstructionTextToken = ptr::null_mut();
+ let mut result: *mut BNInstructionTextToken = std::ptr::null_mut();
unsafe {
if BNGetInstructionText(
- self.0,
+ self.handle,
data.as_ptr(),
addr,
- &mut consumed as *mut _,
- &mut result as *mut _,
- &mut count as *mut _,
+ &mut consumed,
+ &mut result,
+ &mut count,
) {
- let vec = slice::from_raw_parts(result, count)
+ let instr_text_tokens = std::slice::from_raw_parts(result, count)
.iter()
- .map(|x| InstructionTextToken::from_raw(x).to_owned())
+ .map(InstructionTextToken::from_raw)
.collect();
BNFreeInstructionText(result, count);
- Some((consumed, vec))
+ Some((consumed, instr_text_tokens))
} else {
None
}
@@ -1193,11 +1505,17 @@ impl Architecture for CoreArchitecture {
&self,
data: &[u8],
addr: u64,
- il: &mut Lifter<Self>,
+ il: &mut MutableLiftedILFunction<Self>,
) -> Option<(usize, bool)> {
let mut size = data.len();
let success = unsafe {
- BNGetInstructionLowLevelIL(self.0, data.as_ptr(), addr, &mut size as *mut _, il.handle)
+ BNGetInstructionLowLevelIL(
+ self.handle,
+ data.as_ptr(),
+ addr,
+ &mut size as *mut _,
+ il.handle,
+ )
};
if !success {
@@ -1211,40 +1529,69 @@ impl Architecture for CoreArchitecture {
&self,
_flag: Self::Flag,
_flag_write: Self::FlagWrite,
- _op: FlagWriteOp<Self::Register>,
- _il: &'a mut Lifter<Self>,
- ) -> Option<LiftedExpr<'a, Self>> {
+ _op: LowLevelILFlagWriteOp<Self::Register>,
+ _il: &'a mut MutableLiftedILFunction<Self>,
+ ) -> Option<MutableLiftedILExpr<'a, Self, ValueExpr>> {
None
}
+ fn flags_required_for_flag_condition(
+ &self,
+ condition: FlagCondition,
+ class: Option<Self::FlagClass>,
+ ) -> Vec<Self::Flag> {
+ let class_id_raw = class.map(|c| c.id().0).unwrap_or(0);
+
+ unsafe {
+ let mut count: usize = 0;
+ let flags = BNGetArchitectureFlagsRequiredForFlagCondition(
+ self.handle,
+ condition,
+ class_id_raw,
+ &mut count,
+ );
+
+ let ret = std::slice::from_raw_parts(flags, count)
+ .iter()
+ .map(|&id| FlagId::from(id))
+ .filter_map(|flag| CoreFlag::new(*self, flag))
+ .collect();
+
+ BNFreeRegisterList(flags);
+
+ ret
+ }
+ }
+
fn flag_cond_llil<'a>(
&self,
_cond: FlagCondition,
_class: Option<Self::FlagClass>,
- _il: &'a mut Lifter<Self>,
- ) -> Option<LiftedExpr<'a, Self>> {
+ _il: &'a mut MutableLiftedILFunction<Self>,
+ ) -> Option<MutableLiftedILExpr<'a, Self, ValueExpr>> {
None
}
fn flag_group_llil<'a>(
&self,
_group: Self::FlagGroup,
- _il: &'a mut Lifter<Self>,
- ) -> Option<LiftedExpr<'a, Self>> {
+ _il: &'a mut MutableLiftedILFunction<Self>,
+ ) -> Option<MutableLiftedILExpr<'a, Self, ValueExpr>> {
None
}
fn registers_all(&self) -> Vec<CoreRegister> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetAllArchitectureRegisters(self.0, &mut count as *mut _);
+ let registers_raw = BNGetAllArchitectureRegisters(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(registers_raw, count)
.iter()
- .map(|reg| CoreRegister(self.0, *reg))
+ .map(|&id| RegisterId::from(id))
+ .filter_map(|reg| CoreRegister::new(*self, reg))
.collect();
- BNFreeRegisterList(regs);
+ BNFreeRegisterList(registers_raw);
ret
}
@@ -1253,14 +1600,15 @@ impl Architecture for CoreArchitecture {
fn registers_full_width(&self) -> Vec<CoreRegister> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetFullWidthArchitectureRegisters(self.0, &mut count as *mut _);
+ let registers_raw = BNGetFullWidthArchitectureRegisters(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(registers_raw, count)
.iter()
- .map(|reg| CoreRegister(self.0, *reg))
+ .map(|&id| RegisterId::from(id))
+ .filter_map(|reg| CoreRegister::new(*self, reg))
.collect();
- BNFreeRegisterList(regs);
+ BNFreeRegisterList(registers_raw);
ret
}
@@ -1269,14 +1617,15 @@ impl Architecture for CoreArchitecture {
fn registers_global(&self) -> Vec<CoreRegister> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetArchitectureGlobalRegisters(self.0, &mut count as *mut _);
+ let registers_raw = BNGetArchitectureGlobalRegisters(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(registers_raw, count)
.iter()
- .map(|reg| CoreRegister(self.0, *reg))
+ .map(|&id| RegisterId::from(id))
+ .filter_map(|reg| CoreRegister::new(*self, reg))
.collect();
- BNFreeRegisterList(regs);
+ BNFreeRegisterList(registers_raw);
ret
}
@@ -1285,14 +1634,15 @@ impl Architecture for CoreArchitecture {
fn registers_system(&self) -> Vec<CoreRegister> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetArchitectureSystemRegisters(self.0, &mut count as *mut _);
+ let registers_raw = BNGetArchitectureSystemRegisters(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(registers_raw, count)
.iter()
- .map(|reg| CoreRegister(self.0, *reg))
+ .map(|&id| RegisterId::from(id))
+ .filter_map(|reg| CoreRegister::new(*self, reg))
.collect();
- BNFreeRegisterList(regs);
+ BNFreeRegisterList(registers_raw);
ret
}
@@ -1301,14 +1651,15 @@ impl Architecture for CoreArchitecture {
fn register_stacks(&self) -> Vec<CoreRegisterStack> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetAllArchitectureRegisterStacks(self.0, &mut count as *mut _);
+ let reg_stacks_raw = BNGetAllArchitectureRegisterStacks(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(reg_stacks_raw, count)
.iter()
- .map(|reg| CoreRegisterStack(self.0, *reg))
+ .map(|&id| RegisterStackId::from(id))
+ .filter_map(|reg_stack| CoreRegisterStack::new(*self, reg_stack))
.collect();
- BNFreeRegisterList(regs);
+ BNFreeRegisterList(reg_stacks_raw);
ret
}
@@ -1317,14 +1668,15 @@ impl Architecture for CoreArchitecture {
fn flags(&self) -> Vec<CoreFlag> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetAllArchitectureFlags(self.0, &mut count as *mut _);
+ let flags_raw = BNGetAllArchitectureFlags(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(flags_raw, count)
.iter()
- .map(|reg| CoreFlag(self.0, *reg))
+ .map(|&id| FlagId::from(id))
+ .filter_map(|flag| CoreFlag::new(*self, flag))
.collect();
- BNFreeRegisterList(regs);
+ BNFreeRegisterList(flags_raw);
ret
}
@@ -1333,14 +1685,15 @@ impl Architecture for CoreArchitecture {
fn flag_write_types(&self) -> Vec<CoreFlagWrite> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetAllArchitectureFlagWriteTypes(self.0, &mut count as *mut _);
+ let flag_writes_raw = BNGetAllArchitectureFlagWriteTypes(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(flag_writes_raw, count)
.iter()
- .map(|reg| CoreFlagWrite(self.0, *reg))
+ .map(|&id| FlagWriteId::from(id))
+ .filter_map(|flag_write| CoreFlagWrite::new(*self, flag_write))
.collect();
- BNFreeRegisterList(regs);
+ BNFreeRegisterList(flag_writes_raw);
ret
}
@@ -1349,14 +1702,15 @@ impl Architecture for CoreArchitecture {
fn flag_classes(&self) -> Vec<CoreFlagClass> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetAllArchitectureSemanticFlagClasses(self.0, &mut count as *mut _);
+ let flag_classes_raw = BNGetAllArchitectureSemanticFlagClasses(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(flag_classes_raw, count)
.iter()
- .map(|reg| CoreFlagClass(self.0, *reg))
+ .map(|&id| FlagClassId::from(id))
+ .filter_map(|flag_class| CoreFlagClass::new(*self, flag_class))
.collect();
- BNFreeRegisterList(regs);
+ BNFreeRegisterList(flag_classes_raw);
ret
}
@@ -1365,117 +1719,81 @@ impl Architecture for CoreArchitecture {
fn flag_groups(&self) -> Vec<CoreFlagGroup> {
unsafe {
let mut count: usize = 0;
- let regs = BNGetAllArchitectureSemanticFlagGroups(self.0, &mut count as *mut _);
+ let flag_groups_raw = BNGetAllArchitectureSemanticFlagGroups(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(regs, count)
+ let ret = std::slice::from_raw_parts(flag_groups_raw, count)
.iter()
- .map(|reg| CoreFlagGroup(self.0, *reg))
+ .map(|&id| FlagGroupId::from(id))
+ .filter_map(|flag_group| CoreFlagGroup::new(*self, flag_group))
.collect();
- BNFreeRegisterList(regs);
-
- ret
- }
- }
-
- fn flags_required_for_flag_condition(
- &self,
- condition: FlagCondition,
- class: Option<Self::FlagClass>,
- ) -> Vec<Self::Flag> {
- let class_id = class.map(|c| c.id()).unwrap_or(0);
-
- unsafe {
- let mut count: usize = 0;
- let flags = BNGetArchitectureFlagsRequiredForFlagCondition(
- self.0,
- condition,
- class_id,
- &mut count as *mut _,
- );
-
- let ret = slice::from_raw_parts_mut(flags, count)
- .iter()
- .map(|flag| CoreFlag(self.0, *flag))
- .collect();
-
- BNFreeRegisterList(flags);
+ BNFreeRegisterList(flag_groups_raw);
ret
}
}
fn stack_pointer_reg(&self) -> Option<CoreRegister> {
- match unsafe { BNGetArchitectureStackPointerRegister(self.0) } {
+ match unsafe { BNGetArchitectureStackPointerRegister(self.handle) } {
0xffff_ffff => None,
- reg => Some(CoreRegister(self.0, reg)),
+ reg => Some(CoreRegister::new(*self, reg.into())?),
}
}
fn link_reg(&self) -> Option<CoreRegister> {
- match unsafe { BNGetArchitectureLinkRegister(self.0) } {
+ match unsafe { BNGetArchitectureLinkRegister(self.handle) } {
0xffff_ffff => None,
- reg => Some(CoreRegister(self.0, reg)),
+ reg => Some(CoreRegister::new(*self, reg.into())?),
}
}
- fn register_from_id(&self, id: u32) -> Option<CoreRegister> {
- // TODO validate in debug builds
- Some(CoreRegister(self.0, id))
+ fn register_from_id(&self, id: RegisterId) -> Option<CoreRegister> {
+ CoreRegister::new(*self, id)
}
- fn register_stack_from_id(&self, id: u32) -> Option<CoreRegisterStack> {
- // TODO validate in debug builds
- Some(CoreRegisterStack(self.0, id))
+ fn register_stack_from_id(&self, id: RegisterStackId) -> Option<CoreRegisterStack> {
+ CoreRegisterStack::new(*self, id)
}
- fn flag_from_id(&self, id: u32) -> Option<CoreFlag> {
- // TODO validate in debug builds
- Some(CoreFlag(self.0, id))
+ fn flag_from_id(&self, id: FlagId) -> Option<CoreFlag> {
+ CoreFlag::new(*self, id)
}
- fn flag_write_from_id(&self, id: u32) -> Option<CoreFlagWrite> {
- // TODO validate in debug builds
- Some(CoreFlagWrite(self.0, id))
+ fn flag_write_from_id(&self, id: FlagWriteId) -> Option<CoreFlagWrite> {
+ CoreFlagWrite::new(*self, id)
}
- fn flag_class_from_id(&self, id: u32) -> Option<CoreFlagClass> {
- // TODO validate in debug builds
- Some(CoreFlagClass(self.0, id))
+ fn flag_class_from_id(&self, id: FlagClassId) -> Option<CoreFlagClass> {
+ CoreFlagClass::new(*self, id)
}
- fn flag_group_from_id(&self, id: u32) -> Option<CoreFlagGroup> {
- // TODO validate in debug builds
- Some(CoreFlagGroup(self.0, id))
+ fn flag_group_from_id(&self, id: FlagGroupId) -> Option<CoreFlagGroup> {
+ CoreFlagGroup::new(*self, id)
}
fn intrinsics(&self) -> Vec<CoreIntrinsic> {
unsafe {
let mut count: usize = 0;
- let intrinsics = BNGetAllArchitectureIntrinsics(self.0, &mut count as *mut _);
+ let intrinsics_raw = BNGetAllArchitectureIntrinsics(self.handle, &mut count);
- let ret = slice::from_raw_parts_mut(intrinsics, count)
+ let intrinsics = std::slice::from_raw_parts_mut(intrinsics_raw, count)
.iter()
- .map(|reg| CoreIntrinsic(self.0, *reg))
+ .map(|&id| IntrinsicId::from(id))
+ .filter_map(|intrinsic| CoreIntrinsic::new(*self, intrinsic))
.collect();
- BNFreeRegisterList(intrinsics);
+ BNFreeRegisterList(intrinsics_raw);
- ret
+ intrinsics
}
}
- fn intrinsic_class(&self, id: u32) -> binaryninjacore_sys::BNIntrinsicClass {
- unsafe { BNGetArchitectureIntrinsicClass(self.0, id) }
- }
-
- fn intrinsic_from_id(&self, id: u32) -> Option<CoreIntrinsic> {
- // TODO validate in debug builds
- Some(CoreIntrinsic(self.0, id))
+ fn intrinsic_from_id(&self, id: IntrinsicId) -> Option<CoreIntrinsic> {
+ CoreIntrinsic::new(*self, id)
}
fn can_assemble(&self) -> bool {
- unsafe { BNCanArchitectureAssemble(self.0) }
+ unsafe { BNCanArchitectureAssemble(self.handle) }
}
fn assemble(&self, code: &str, addr: u64) -> Result<Vec<u8>, String> {
@@ -1485,10 +1803,10 @@ impl Architecture for CoreArchitecture {
Ok(result) => result,
Err(_) => return Err("Result buffer allocation failed".to_string()),
};
- let mut error_raw: *mut c_char = ptr::null_mut();
+ let mut error_raw: *mut c_char = std::ptr::null_mut();
let res = unsafe {
BNAssemble(
- self.0,
+ self.handle,
code.as_ptr(),
addr,
result.as_raw(),
@@ -1510,32 +1828,37 @@ impl Architecture for CoreArchitecture {
fn is_never_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
unsafe {
- BNIsArchitectureNeverBranchPatchAvailable(self.0, data.as_ptr(), addr, data.len())
+ BNIsArchitectureNeverBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
}
}
fn is_always_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
unsafe {
- BNIsArchitectureAlwaysBranchPatchAvailable(self.0, data.as_ptr(), addr, data.len())
+ BNIsArchitectureAlwaysBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
}
}
fn is_invert_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
unsafe {
- BNIsArchitectureInvertBranchPatchAvailable(self.0, data.as_ptr(), addr, data.len())
+ BNIsArchitectureInvertBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
}
}
fn is_skip_and_return_zero_patch_available(&self, data: &[u8], addr: u64) -> bool {
unsafe {
- BNIsArchitectureSkipAndReturnZeroPatchAvailable(self.0, data.as_ptr(), addr, data.len())
+ BNIsArchitectureSkipAndReturnZeroPatchAvailable(
+ self.handle,
+ data.as_ptr(),
+ addr,
+ data.len(),
+ )
}
}
fn is_skip_and_return_value_patch_available(&self, data: &[u8], addr: u64) -> bool {
unsafe {
BNIsArchitectureSkipAndReturnValuePatchAvailable(
- self.0,
+ self.handle,
data.as_ptr(),
addr,
data.len(),
@@ -1544,20 +1867,26 @@ impl Architecture for CoreArchitecture {
}
fn convert_to_nop(&self, data: &mut [u8], addr: u64) -> bool {
- unsafe { BNArchitectureConvertToNop(self.0, data.as_mut_ptr(), addr, data.len()) }
+ unsafe { BNArchitectureConvertToNop(self.handle, data.as_mut_ptr(), addr, data.len()) }
}
fn always_branch(&self, data: &mut [u8], addr: u64) -> bool {
- unsafe { BNArchitectureAlwaysBranch(self.0, data.as_mut_ptr(), addr, data.len()) }
+ unsafe { BNArchitectureAlwaysBranch(self.handle, data.as_mut_ptr(), addr, data.len()) }
}
fn invert_branch(&self, data: &mut [u8], addr: u64) -> bool {
- unsafe { BNArchitectureInvertBranch(self.0, data.as_mut_ptr(), addr, data.len()) }
+ unsafe { BNArchitectureInvertBranch(self.handle, data.as_mut_ptr(), addr, data.len()) }
}
fn skip_and_return_value(&self, data: &mut [u8], addr: u64, value: u64) -> bool {
unsafe {
- BNArchitectureSkipAndReturnValue(self.0, data.as_mut_ptr(), addr, data.len(), value)
+ BNArchitectureSkipAndReturnValue(
+ self.handle,
+ data.as_mut_ptr(),
+ addr,
+ data.len(),
+ value,
+ )
}
}
@@ -1568,30 +1897,33 @@ impl Architecture for CoreArchitecture {
macro_rules! cc_func {
($get_name:ident, $get_api:ident, $set_name:ident, $set_api:ident) => {
- fn $get_name(&self) -> Option<Ref<CallingConvention<Self>>> {
- let handle = self.as_ref();
+ fn $get_name(&self) -> Option<Ref<CoreCallingConvention>> {
+ let arch = self.as_ref();
unsafe {
- let cc = $get_api(handle.0);
+ let cc = $get_api(arch.handle);
if cc.is_null() {
None
} else {
- Some(CallingConvention::ref_from_raw(cc, self.handle()))
+ Some(CoreCallingConvention::ref_from_raw(
+ cc,
+ self.as_ref().handle(),
+ ))
}
}
}
- fn $set_name(&self, cc: &CallingConvention<Self>) {
- let handle = self.as_ref();
+ fn $set_name(&self, cc: &CoreCallingConvention) {
+ let arch = self.as_ref();
assert!(
- cc.arch_handle.borrow().as_ref().0 == handle.0,
+ cc.arch_handle.borrow().as_ref().handle == arch.handle,
"use of calling convention with non-matching architecture!"
);
unsafe {
- $set_api(handle.0, cc.handle);
+ $set_api(arch.handle, cc.handle);
}
}
};
@@ -1603,18 +1935,19 @@ pub trait ArchitectureExt: Architecture {
let name = name.into_bytes_with_nul();
match unsafe {
- BNGetArchitectureRegisterByName(self.as_ref().0, name.as_ref().as_ptr() as *mut _)
+ BNGetArchitectureRegisterByName(self.as_ref().handle, name.as_ref().as_ptr() as *mut _)
} {
0xffff_ffff => None,
- reg => self.register_from_id(reg),
+ reg => self.register_from_id(reg.into()),
}
}
- fn calling_conventions(&self) -> Array<CallingConvention<Self>> {
+ fn calling_conventions(&self) -> Array<CoreCallingConvention> {
unsafe {
let mut count = 0;
- let calling_convs = BNGetArchitectureCallingConventions(self.as_ref().0, &mut count);
- Array::new(calling_convs, count, self.handle())
+ let calling_convs =
+ BNGetArchitectureCallingConventions(self.as_ref().handle, &mut count);
+ Array::new(calling_convs, count, self.as_ref().handle())
}
}
@@ -1648,7 +1981,7 @@ pub trait ArchitectureExt: Architecture {
fn standalone_platform(&self) -> Option<Ref<Platform>> {
unsafe {
- let handle = BNGetArchitectureStandalonePlatform(self.as_ref().0);
+ let handle = BNGetArchitectureStandalonePlatform(self.as_ref().handle);
if handle.is_null() {
return None;
@@ -1665,7 +1998,8 @@ pub trait ArchitectureExt: Architecture {
};
unsafe {
- let handle = BNArchitectureGetRelocationHandler(self.as_ref().0, view_name.as_ptr());
+ let handle =
+ BNArchitectureGetRelocationHandler(self.as_ref().handle, view_name.as_ptr());
if handle.is_null() {
return None;
@@ -1692,7 +2026,7 @@ pub trait ArchitectureExt: Architecture {
where
R: 'static + FunctionRecognizer + Send + Sync + Sized,
{
- crate::functionrecognizer::register_arch_function_recognizer(self.as_ref(), recognizer);
+ crate::function_recognizer::register_arch_function_recognizer(self.as_ref(), recognizer);
}
}
@@ -1704,9 +2038,6 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync + Sized,
F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
{
- use std::mem;
- use std::os::raw::{c_char, c_void};
-
#[repr(C)]
struct ArchitectureBuilder<A, F>
where
@@ -1731,7 +2062,7 @@ where
let create = custom_arch.func.take().unwrap();
custom_arch
.arch
- .write(create(custom_arch_handle, CoreArchitecture(obj)));
+ .write(create(custom_arch_handle, CoreArchitecture::from_raw(obj)));
}
}
@@ -1791,9 +2122,9 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let addr = unsafe { &mut *(addr) };
+ let addr = unsafe { *(addr) };
- custom_arch.associated_arch_by_addr(addr).0
+ custom_arch.associated_arch_by_addr(addr).handle
}
extern "C" fn cb_instruction_info<A>(
@@ -1807,12 +2138,12 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts(data, len) };
- let result = unsafe { &mut *(result as *mut InstructionInfo) };
+ let data = unsafe { std::slice::from_raw_parts(data, len) };
match custom_arch.instruction_info(data, addr) {
Some(info) => {
- result.0 = info.0;
+ // SAFETY: Passed in to be written to
+ unsafe { *result = info.into() };
true
}
None => false,
@@ -1831,28 +2162,35 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts(data, *len) };
+ let data = unsafe { std::slice::from_raw_parts(data, *len) };
let result = unsafe { &mut *result };
let Some((res_size, res_tokens)) = custom_arch.instruction_text(data, addr) else {
return false;
};
- let res_tokens: Box<[_]> = res_tokens.into_boxed_slice();
+ let res_tokens: Box<[BNInstructionTextToken]> = res_tokens
+ .into_iter()
+ .map(InstructionTextToken::into_raw)
+ .collect();
unsafe {
+ // NOTE: Freed with `cb_free_instruction_text`
let res_tokens = Box::leak(res_tokens);
- let r_ptr = res_tokens.as_mut_ptr();
- let r_count = res_tokens.len();
-
- *result = &mut (*r_ptr).0;
- *count = r_count;
+ *result = res_tokens.as_mut_ptr();
+ *count = res_tokens.len();
*len = res_size;
}
true
}
extern "C" fn cb_free_instruction_text(tokens: *mut BNInstructionTextToken, count: usize) {
- let _tokens = unsafe { Box::from_raw(ptr::slice_from_raw_parts_mut(tokens, count)) };
+ unsafe {
+ let raw_tokens = std::slice::from_raw_parts_mut(tokens, count);
+ let boxed_tokens = Box::from_raw(raw_tokens);
+ for token in boxed_tokens {
+ InstructionTextToken::free_raw(token);
+ }
+ }
}
extern "C" fn cb_instruction_llil<A>(
@@ -1870,8 +2208,8 @@ where
handle: ctxt as *mut A,
};
- let data = unsafe { slice::from_raw_parts(data, *len) };
- let mut lifter = unsafe { Lifter::from_raw(custom_arch_handle, il) };
+ let data = unsafe { std::slice::from_raw_parts(data, *len) };
+ let mut lifter = unsafe { MutableLiftedILFunction::from_raw(custom_arch_handle, il) };
match custom_arch.instruction_llil(data, addr, &mut lifter) {
Some((res_len, res_value)) => {
@@ -1888,9 +2226,9 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- match custom_arch.register_from_id(reg) {
- Some(reg) => BnString::new(reg.name().as_ref()).into_raw(),
- None => BnString::new("invalid_reg").into_raw(),
+ match custom_arch.register_from_id(reg.into()) {
+ Some(reg) => BnString::into_raw(BnString::new(reg.name().as_ref())),
+ None => BnString::into_raw(BnString::new("invalid_reg")),
}
}
@@ -1900,9 +2238,9 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- match custom_arch.flag_from_id(flag) {
- Some(flag) => BnString::new(flag.name().as_ref()).into_raw(),
- None => BnString::new("invalid_flag").into_raw(),
+ match custom_arch.flag_from_id(flag.into()) {
+ Some(flag) => BnString::into_raw(BnString::new(flag.name().as_ref())),
+ None => BnString::into_raw(BnString::new("invalid_flag")),
}
}
@@ -1912,9 +2250,9 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- match custom_arch.flag_write_from_id(flag_write) {
- Some(flag_write) => BnString::new(flag_write.name().as_ref()).into_raw(),
- None => BnString::new("invalid_flag_write").into_raw(),
+ match custom_arch.flag_write_from_id(flag_write.into()) {
+ Some(flag_write) => BnString::into_raw(BnString::new(flag_write.name().as_ref())),
+ None => BnString::into_raw(BnString::new("invalid_flag_write")),
}
}
@@ -1924,9 +2262,9 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- match custom_arch.flag_class_from_id(class) {
- Some(class) => BnString::new(class.name().as_ref()).into_raw(),
- None => BnString::new("invalid_flag_class").into_raw(),
+ match custom_arch.flag_class_from_id(class.into()) {
+ Some(class) => BnString::into_raw(BnString::new(class.name().as_ref())),
+ None => BnString::into_raw(BnString::new("invalid_flag_class")),
}
}
@@ -1936,9 +2274,9 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- match custom_arch.flag_group_from_id(group) {
- Some(group) => BnString::new(group.name().as_ref()).into_raw(),
- None => BnString::new("invalid_flag_group").into_raw(),
+ match custom_arch.flag_group_from_id(group.into()) {
+ Some(group) => BnString::into_raw(BnString::new(group.name().as_ref())),
+ None => BnString::into_raw(BnString::new("invalid_flag_group")),
}
}
@@ -1947,16 +2285,16 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut regs: Vec<_> = custom_arch
+ let mut regs: Box<[_]> = custom_arch
.registers_full_width()
.iter()
- .map(|r| r.id())
+ .map(|r| r.id().0)
.collect();
// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
- mem::forget(regs);
+ std::mem::forget(regs);
regs_ptr
}
@@ -1965,12 +2303,16 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut regs: Vec<_> = custom_arch.registers_all().iter().map(|r| r.id()).collect();
+ let mut regs: Box<[_]> = custom_arch
+ .registers_all()
+ .iter()
+ .map(|r| r.id().0)
+ .collect();
// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
- mem::forget(regs);
+ std::mem::forget(regs);
regs_ptr
}
@@ -1979,16 +2321,16 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut regs: Vec<_> = custom_arch
+ let mut regs: Box<[_]> = custom_arch
.registers_global()
.iter()
- .map(|r| r.id())
+ .map(|r| r.id().0)
.collect();
// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
- mem::forget(regs);
+ std::mem::forget(regs);
regs_ptr
}
@@ -1997,16 +2339,16 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut regs: Vec<_> = custom_arch
+ let mut regs: Box<[_]> = custom_arch
.registers_system()
.iter()
- .map(|r| r.id())
+ .map(|r| r.id().0)
.collect();
// SAFETY: `count` is an out parameter
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
- mem::forget(regs);
+ std::mem::forget(regs);
regs_ptr
}
@@ -2015,12 +2357,12 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut flags: Vec<_> = custom_arch.flags().iter().map(|f| f.id()).collect();
+ let mut flags: Box<[_]> = custom_arch.flags().iter().map(|f| f.id().0).collect();
// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let flags_ptr = flags.as_mut_ptr();
- mem::forget(flags);
+ std::mem::forget(flags);
flags_ptr
}
@@ -2029,16 +2371,16 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut flag_writes: Vec<_> = custom_arch
+ let mut flag_writes: Box<[_]> = custom_arch
.flag_write_types()
.iter()
- .map(|f| f.id())
+ .map(|f| f.id().0)
.collect();
// SAFETY: `count` is an out parameter
unsafe { *count = flag_writes.len() };
let flags_ptr = flag_writes.as_mut_ptr();
- mem::forget(flag_writes);
+ std::mem::forget(flag_writes);
flags_ptr
}
@@ -2047,12 +2389,16 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut flag_classes: Vec<_> = custom_arch.flag_classes().iter().map(|f| f.id()).collect();
+ let mut flag_classes: Box<[_]> = custom_arch
+ .flag_classes()
+ .iter()
+ .map(|f| f.id().0)
+ .collect();
// SAFETY: `count` is an out parameter
unsafe { *count = flag_classes.len() };
let flags_ptr = flag_classes.as_mut_ptr();
- mem::forget(flag_classes);
+ std::mem::forget(flag_classes);
flags_ptr
}
@@ -2061,12 +2407,13 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut flag_groups: Vec<_> = custom_arch.flag_groups().iter().map(|f| f.id()).collect();
+ let mut flag_groups: Box<[_]> =
+ custom_arch.flag_groups().iter().map(|f| f.id().0).collect();
// SAFETY: `count` is an out parameter
unsafe { *count = flag_groups.len() };
let flags_ptr = flag_groups.as_mut_ptr();
- mem::forget(flag_groups);
+ std::mem::forget(flag_groups);
flags_ptr
}
@@ -2077,8 +2424,8 @@ where
let custom_arch = unsafe { &*(ctxt as *mut A) };
if let (Some(flag), class) = (
- custom_arch.flag_from_id(flag),
- custom_arch.flag_class_from_id(class),
+ custom_arch.flag_from_id(FlagId(flag)),
+ custom_arch.flag_class_from_id(FlagClassId(class)),
) {
flag.role(class)
} else {
@@ -2096,17 +2443,17 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let class = custom_arch.flag_class_from_id(class);
- let mut flags: Vec<_> = custom_arch
+ let class = custom_arch.flag_class_from_id(FlagClassId(class));
+ let mut flags: Box<[_]> = custom_arch
.flags_required_for_flag_condition(cond, class)
.iter()
- .map(|f| f.id())
+ .map(|f| f.id().0)
.collect();
// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let flags_ptr = flags.as_mut_ptr();
- mem::forget(flags);
+ std::mem::forget(flags);
flags_ptr
}
@@ -2120,19 +2467,19 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- if let Some(group) = custom_arch.flag_group_from_id(group) {
- let mut flags: Vec<_> = group.flags_required().iter().map(|f| f.id()).collect();
+ if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
+ let mut flags: Box<[_]> = group.flags_required().iter().map(|f| f.id().0).collect();
// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let flags_ptr = flags.as_mut_ptr();
- mem::forget(flags);
+ std::mem::forget(flags);
flags_ptr
} else {
unsafe {
*count = 0;
}
- ptr::null_mut()
+ std::ptr::null_mut()
}
}
@@ -2146,26 +2493,26 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- if let Some(group) = custom_arch.flag_group_from_id(group) {
+ if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
let flag_conditions = group.flag_conditions();
- let mut flags = flag_conditions
+ let mut flags: Box<[_]> = flag_conditions
.iter()
.map(|(&class, &condition)| BNFlagConditionForSemanticClass {
- semanticClass: class.id(),
+ semanticClass: class.id().0,
condition,
})
- .collect::<Vec<_>>();
+ .collect();
// SAFETY: `count` is an out parameter
unsafe { *count = flags.len() };
let flags_ptr = flags.as_mut_ptr();
- mem::forget(flags);
+ std::mem::forget(flags);
flags_ptr
} else {
unsafe {
*count = 0;
}
- ptr::null_mut()
+ std::ptr::null_mut()
}
}
@@ -2181,7 +2528,7 @@ where
}
unsafe {
- let flags_ptr = ptr::slice_from_raw_parts_mut(conds, count);
+ let flags_ptr = std::ptr::slice_from_raw_parts_mut(conds, count);
let _flags = Box::from_raw(flags_ptr);
}
}
@@ -2196,20 +2543,23 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- if let Some(write_type) = custom_arch.flag_write_from_id(write_type) {
- let mut flags_written: Vec<_> =
- write_type.flags_written().iter().map(|f| f.id()).collect();
+ if let Some(write_type) = custom_arch.flag_write_from_id(FlagWriteId(write_type)) {
+ let mut flags_written: Box<[_]> = write_type
+ .flags_written()
+ .iter()
+ .map(|f| f.id().0)
+ .collect();
// SAFETY: `count` is an out parameter
unsafe { *count = flags_written.len() };
let flags_ptr = flags_written.as_mut_ptr();
- mem::forget(flags_written);
+ std::mem::forget(flags_written);
flags_ptr
} else {
unsafe {
*count = 0;
}
- ptr::null_mut()
+ std::ptr::null_mut()
}
}
@@ -2222,9 +2572,9 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
custom_arch
- .flag_write_from_id(write_type)
+ .flag_write_from_id(FlagWriteId(write_type))
.map(|w| w.class())
- .and_then(|c| c.map(|c| c.id()))
+ .and_then(|c| c.map(|c| c.id().0))
.unwrap_or(0)
}
@@ -2246,19 +2596,19 @@ where
handle: ctxt as *mut A,
};
- let flag_write = custom_arch.flag_write_from_id(flag_write);
- let flag = custom_arch.flag_from_id(flag);
- let operands = unsafe { slice::from_raw_parts(operands_raw, operand_count) };
- let mut lifter = unsafe { Lifter::from_raw(custom_arch_handle, il) };
+ let flag_write = custom_arch.flag_write_from_id(FlagWriteId(flag_write));
+ let flag = custom_arch.flag_from_id(FlagId(flag));
+ let operands = unsafe { std::slice::from_raw_parts(operands_raw, operand_count) };
+ let mut lifter = unsafe { MutableLiftedILFunction::from_raw(custom_arch_handle, il) };
if let (Some(flag_write), Some(flag)) = (flag_write, flag) {
- if let Some(op) = FlagWriteOp::from_op(custom_arch, size, op, operands) {
+ if let Some(op) = LowLevelILFlagWriteOp::from_op(custom_arch, size, op, operands) {
if let Some(expr) = custom_arch.flag_write_llil(flag, flag_write, op, &mut lifter) {
// TODO verify that returned expr is a bool value
- return expr.expr_idx;
+ return expr.index.0;
}
} else {
- warn!(
+ log::warn!(
"unable to unpack flag write op: {:?} with {} operands",
op,
operands.len()
@@ -2269,7 +2619,7 @@ where
unsafe {
BNGetDefaultArchitectureFlagWriteLowLevelIL(
- custom_arch.as_ref().0,
+ custom_arch.as_ref().handle,
op,
size,
role,
@@ -2281,7 +2631,7 @@ where
} else {
// TODO this should be impossible; requires bad flag/flag_write ids passed in;
// explode more violently
- lifter.unimplemented().expr_idx
+ lifter.unimplemented().index.0
}
}
@@ -2299,15 +2649,15 @@ where
handle: ctxt as *mut A,
};
- let class = custom_arch.flag_class_from_id(class);
+ let class = custom_arch.flag_class_from_id(FlagClassId(class));
- let mut lifter = unsafe { Lifter::from_raw(custom_arch_handle, il) };
+ let mut lifter = unsafe { MutableLiftedILFunction::from_raw(custom_arch_handle, il) };
if let Some(expr) = custom_arch.flag_cond_llil(cond, class, &mut lifter) {
// TODO verify that returned expr is a bool value
- return expr.expr_idx;
+ return expr.index.0;
}
- lifter.unimplemented().expr_idx
+ lifter.unimplemented().index.0
}
extern "C" fn cb_flag_group_llil<A>(
@@ -2323,16 +2673,16 @@ where
handle: ctxt as *mut A,
};
- let mut lifter = unsafe { Lifter::from_raw(custom_arch_handle, il) };
+ let mut lifter = unsafe { MutableLiftedILFunction::from_raw(custom_arch_handle, il) };
- if let Some(group) = custom_arch.flag_group_from_id(group) {
+ if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
if let Some(expr) = custom_arch.flag_group_llil(group, &mut lifter) {
// TODO verify that returned expr is a bool value
- return expr.expr_idx;
+ return expr.index.0;
}
}
- lifter.unimplemented().expr_idx
+ lifter.unimplemented().index.0
}
extern "C" fn cb_free_register_list(_ctxt: *mut c_void, regs: *mut u32, count: usize) {
@@ -2341,7 +2691,7 @@ where
}
unsafe {
- let regs_ptr = ptr::slice_from_raw_parts_mut(regs, count);
+ let regs_ptr = std::ptr::slice_from_raw_parts_mut(regs, count);
let _regs = Box::from_raw(regs_ptr);
}
}
@@ -2353,12 +2703,12 @@ where
let custom_arch = unsafe { &*(ctxt as *mut A) };
let result = unsafe { &mut *result };
- if let Some(reg) = custom_arch.register_from_id(reg) {
+ if let Some(reg) = custom_arch.register_from_id(RegisterId(reg)) {
let info = reg.info();
result.fullWidthRegister = match info.parent() {
- Some(p) => p.id(),
- None => reg.id(),
+ Some(p) => p.id().0,
+ None => reg.id().0,
};
result.offset = info.offset();
@@ -2374,7 +2724,7 @@ where
let custom_arch = unsafe { &*(ctxt as *mut A) };
if let Some(reg) = custom_arch.stack_pointer_reg() {
- reg.id()
+ reg.id().0
} else {
0xffff_ffff
}
@@ -2387,7 +2737,7 @@ where
let custom_arch = unsafe { &*(ctxt as *mut A) };
if let Some(reg) = custom_arch.link_reg() {
- reg.id()
+ reg.id().0
} else {
0xffff_ffff
}
@@ -2399,9 +2749,9 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- match custom_arch.register_stack_from_id(stack) {
- Some(stack) => BnString::new(stack.name().as_ref()).into_raw(),
- None => BnString::new("invalid_reg_stack").into_raw(),
+ match custom_arch.register_stack_from_id(RegisterStackId(stack)) {
+ Some(stack) => BnString::into_raw(BnString::new(stack.name().as_ref())),
+ None => BnString::into_raw(BnString::new("invalid_reg_stack")),
}
}
@@ -2410,16 +2760,16 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut regs: Vec<_> = custom_arch
+ let mut regs: Box<[_]> = custom_arch
.register_stacks()
.iter()
- .map(|r| r.id())
+ .map(|r| r.id().0)
.collect();
// SAFETY: Passed in to be written
unsafe { *count = regs.len() };
let regs_ptr = regs.as_mut_ptr();
- mem::forget(regs);
+ std::mem::forget(regs);
regs_ptr
}
@@ -2433,22 +2783,22 @@ where
let custom_arch = unsafe { &*(ctxt as *mut A) };
let result = unsafe { &mut *result };
- if let Some(stack) = custom_arch.register_stack_from_id(stack) {
+ if let Some(stack) = custom_arch.register_stack_from_id(RegisterStackId(stack)) {
let info = stack.info();
let (reg, count) = info.storage_regs();
- result.firstStorageReg = reg.id();
- result.storageCount = count;
+ result.firstStorageReg = reg.id().0;
+ result.storageCount = count as u32;
if let Some((reg, count)) = info.top_relative_regs() {
- result.firstTopRelativeReg = reg.id();
- result.topRelativeCount = count;
+ result.firstTopRelativeReg = reg.id().0;
+ result.topRelativeCount = count as u32;
} else {
result.firstTopRelativeReg = 0xffff_ffff;
result.topRelativeCount = 0;
}
- result.stackTopReg = info.stack_top_reg().id();
+ result.stackTopReg = info.stack_top_reg().id().0;
}
}
@@ -2457,7 +2807,11 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- custom_arch.intrinsic_class(intrinsic)
+ match custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) {
+ Some(intrinsic) => intrinsic.class(),
+ // TODO: Make this unreachable?
+ None => BNIntrinsicClass::GeneralIntrinsicClass,
+ }
}
extern "C" fn cb_intrinsic_name<A>(ctxt: *mut c_void, intrinsic: u32) -> *mut c_char
@@ -2465,9 +2819,9 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- match custom_arch.intrinsic_from_id(intrinsic) {
- Some(intrinsic) => BnString::new(intrinsic.name().as_ref()).into_raw(),
- None => BnString::new("invalid_intrinsic").into_raw(),
+ match custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) {
+ Some(intrinsic) => BnString::into_raw(BnString::new(intrinsic.name())),
+ None => BnString::into_raw(BnString::new("invalid_intrinsic")),
}
}
@@ -2476,12 +2830,12 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let mut intrinsics: Vec<_> = custom_arch.intrinsics().iter().map(|i| i.id()).collect();
+ let mut intrinsics: Box<[_]> = custom_arch.intrinsics().iter().map(|i| i.id().0).collect();
// SAFETY: Passed in to be written
unsafe { *count = intrinsics.len() };
let intrinsics_ptr = intrinsics.as_mut_ptr();
- mem::forget(intrinsics);
+ std::mem::forget(intrinsics);
intrinsics_ptr
}
@@ -2495,44 +2849,48 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let Some(intrinsic) = custom_arch.intrinsic_from_id(intrinsic) else {
+ let Some(intrinsic) = custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) else {
+ // SAFETY: Passed in to be written
unsafe {
*count = 0;
}
- return ptr::null_mut();
+ return std::ptr::null_mut();
};
let inputs = intrinsic.inputs();
- let mut res: Box<[_]> = inputs
- .into_iter()
- .map(|input| unsafe { Ref::into_raw(input) }.0)
- .collect();
+ // NOTE: The into_raw will leak and be freed later by `cb_free_name_and_types`.
+ let raw_inputs: Box<[_]> = inputs.into_iter().map(NameAndType::into_raw).collect();
+ // SAFETY: Passed in to be written
unsafe {
- *count = res.len();
- if res.is_empty() {
- ptr::null_mut()
- } else {
- let raw = res.as_mut_ptr();
- mem::forget(res);
- raw
- }
+ *count = raw_inputs.len();
+ }
+
+ if raw_inputs.is_empty() {
+ std::ptr::null_mut()
+ } else {
+ // Core is responsible for calling back to `cb_free_name_and_types`.
+ Box::leak(raw_inputs).as_mut_ptr()
}
}
- extern "C" fn cb_free_name_and_types<A>(ctxt: *mut c_void, nt: *mut BNNameAndType, count: usize)
- where
+ extern "C" fn cb_free_name_and_types<A>(
+ _ctxt: *mut c_void,
+ nt: *mut BNNameAndType,
+ count: usize,
+ ) where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
- let _custom_arch = unsafe { &*(ctxt as *mut A) };
+ if nt.is_null() {
+ return;
+ }
- if !nt.is_null() {
- unsafe {
- let name_and_types = Box::from_raw(ptr::slice_from_raw_parts_mut(nt, count));
- for nt in name_and_types.iter() {
- Ref::new(NameAndType::from_raw(nt));
- }
- }
+ // Reconstruct the box and drop.
+ let nt_ptr = std::ptr::slice_from_raw_parts_mut(nt, count);
+ // SAFETY: nt_ptr is a pointer to a Box.
+ let boxed_name_and_types = unsafe { Box::from_raw(nt_ptr) };
+ for nt in boxed_name_and_types {
+ NameAndType::free_raw(nt);
}
}
@@ -2546,25 +2904,31 @@ where
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- if let Some(intrinsic) = custom_arch.intrinsic_from_id(intrinsic) {
- let inputs = intrinsic.outputs();
- let mut res: Box<[_]> = inputs.iter().map(|input| input.as_ref().into()).collect();
-
- unsafe {
- *count = res.len();
- if res.is_empty() {
- ptr::null_mut()
- } else {
- let raw = res.as_mut_ptr();
- mem::forget(res);
- raw
- }
- }
- } else {
+ let Some(intrinsic) = custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) else {
+ // SAFETY: Passed in to be written
unsafe {
*count = 0;
}
- ptr::null_mut()
+ return std::ptr::null_mut();
+ };
+
+ let outputs = intrinsic.outputs();
+ let raw_outputs: Box<[BNTypeWithConfidence]> = outputs
+ .into_iter()
+ // Leaked to be freed later by `cb_free_type_list`.
+ .map(Conf::<Ref<Type>>::into_raw)
+ .collect();
+
+ // SAFETY: Passed in to be written
+ unsafe {
+ *count = raw_outputs.len();
+ }
+
+ if raw_outputs.is_empty() {
+ std::ptr::null_mut()
+ } else {
+ // Core is responsible for calling back to `cb_free_type_list`.
+ Box::leak(raw_outputs).as_mut_ptr()
}
}
@@ -2576,8 +2940,9 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let _custom_arch = unsafe { &*(ctxt as *mut A) };
- if !tl.is_null() {
- let _type_list = unsafe { Box::from_raw(ptr::slice_from_raw_parts_mut(tl, count)) };
+ let boxed_types = unsafe { Box::from_raw(std::ptr::slice_from_raw_parts_mut(tl, count)) };
+ for ty in boxed_types {
+ Conf::<Ref<Type>>::free_raw(ty);
}
}
@@ -2607,20 +2972,20 @@ where
Ok(result) => {
buffer.set_data(&result);
unsafe {
- *errors = BnString::new("").into_raw();
+ *errors = BnString::into_raw(BnString::new(""));
}
true
}
Err(result) => {
unsafe {
- *errors = BnString::new(result).into_raw();
+ *errors = BnString::into_raw(BnString::new(result));
}
false
}
};
// Caller owns the data buffer, don't free it
- mem::forget(buffer);
+ std::mem::forget(buffer);
result
}
@@ -2635,7 +3000,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts(data, len) };
+ let data = unsafe { std::slice::from_raw_parts(data, len) };
custom_arch.is_never_branch_patch_available(data, addr)
}
@@ -2649,7 +3014,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts(data, len) };
+ let data = unsafe { std::slice::from_raw_parts(data, len) };
custom_arch.is_always_branch_patch_available(data, addr)
}
@@ -2663,7 +3028,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts(data, len) };
+ let data = unsafe { std::slice::from_raw_parts(data, len) };
custom_arch.is_invert_branch_patch_available(data, addr)
}
@@ -2677,7 +3042,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts(data, len) };
+ let data = unsafe { std::slice::from_raw_parts(data, len) };
custom_arch.is_skip_and_return_zero_patch_available(data, addr)
}
@@ -2691,7 +3056,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts(data, len) };
+ let data = unsafe { std::slice::from_raw_parts(data, len) };
custom_arch.is_skip_and_return_value_patch_available(data, addr)
}
@@ -2705,7 +3070,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts_mut(data, len) };
+ let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
custom_arch.convert_to_nop(data, addr)
}
@@ -2719,7 +3084,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts_mut(data, len) };
+ let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
custom_arch.always_branch(data, addr)
}
@@ -2733,7 +3098,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts_mut(data, len) };
+ let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
custom_arch.invert_branch(data, addr)
}
@@ -2748,7 +3113,7 @@ where
A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
{
let custom_arch = unsafe { &*(ctxt as *mut A) };
- let data = unsafe { slice::from_raw_parts_mut(data, len) };
+ let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
custom_arch.skip_and_return_value(data, addr, val)
}
@@ -2767,7 +3132,9 @@ where
getAddressSize: Some(cb_address_size::<A>),
getDefaultIntegerSize: Some(cb_default_integer_size::<A>),
getInstructionAlignment: Some(cb_instruction_alignment::<A>),
+ // TODO: Make getOpcodeDisplayLength optional.
getMaxInstructionLength: Some(cb_max_instr_len::<A>),
+ // TODO: Make getOpcodeDisplayLength optional.
getOpcodeDisplayLength: Some(cb_opcode_display_len::<A>),
getAssociatedArchitectureByAddress: Some(cb_associated_arch_by_addr::<A>),
getInstructionInfo: Some(cb_instruction_info::<A>),
@@ -2923,9 +3290,9 @@ pub fn llvm_assemble(
let code = CString::new(code).map_err(|_| "Invalid encoding in code string".to_string())?;
let arch_triple = CString::new(arch_triple)
.map_err(|_| "Invalid encoding in architecture triple string".to_string())?;
- let mut out_bytes: *mut c_char = ptr::null_mut();
+ let mut out_bytes: *mut c_char = std::ptr::null_mut();
let mut out_bytes_len: c_int = 0;
- let mut err_bytes: *mut c_char = ptr::null_mut();
+ let mut err_bytes: *mut c_char = std::ptr::null_mut();
let mut err_len: c_int = 0;
unsafe {
@@ -2950,7 +3317,7 @@ pub fn llvm_assemble(
Vec::new()
} else {
unsafe {
- slice::from_raw_parts(
+ std::slice::from_raw_parts(
out_bytes as *const c_char as *const u8,
out_bytes_len as usize,
)
@@ -2962,7 +3329,7 @@ pub fn llvm_assemble(
"".into()
} else {
String::from_utf8_lossy(unsafe {
- slice::from_raw_parts(err_bytes as *const c_char as *const u8, err_len as usize)
+ std::slice::from_raw_parts(err_bytes as *const c_char as *const u8, err_len as usize)
})
.into_owned()
};