summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
Diffstat (limited to 'rust')
-rw-r--r--rust/examples/bndb_to_type_library.rs3
-rw-r--r--rust/examples/create_type_library.rs3
-rw-r--r--rust/examples/dump_type_library.rs4
-rw-r--r--rust/examples/type_printer.rs2
-rw-r--r--rust/src/binary_view.rs11
-rw-r--r--rust/src/collaboration/sync.rs2
-rw-r--r--rust/src/component.rs23
-rw-r--r--rust/src/data_notification.rs3
-rw-r--r--rust/src/language_representation.rs3
-rw-r--r--rust/src/lib.rs5
-rw-r--r--rust/src/platform.rs8
-rw-r--r--rust/src/string.rs9
-rw-r--r--rust/src/types.rs923
-rw-r--r--rust/src/types/archive.rs (renamed from rust/src/type_archive.rs)15
-rw-r--r--rust/src/types/container.rs (renamed from rust/src/type_container.rs)3
-rw-r--r--rust/src/types/enumeration.rs201
-rw-r--r--rust/src/types/library.rs (renamed from rust/src/type_library.rs)0
-rw-r--r--rust/src/types/parser.rs (renamed from rust/src/type_parser.rs)3
-rw-r--r--rust/src/types/printer.rs (renamed from rust/src/type_printer.rs)3
-rw-r--r--rust/src/types/structure.rs696
-rw-r--r--rust/tests/type_archive.rs3
-rw-r--r--rust/tests/type_library.rs3
-rw-r--r--rust/tests/type_parser.rs3
-rw-r--r--rust/tests/type_printer.rs8
24 files changed, 981 insertions, 956 deletions
diff --git a/rust/examples/bndb_to_type_library.rs b/rust/examples/bndb_to_type_library.rs
index 40a184ca..84515cf7 100644
--- a/rust/examples/bndb_to_type_library.rs
+++ b/rust/examples/bndb_to_type_library.rs
@@ -1,8 +1,7 @@
// Usage: cargo run --example bndb_to_type_library <bndb_path> <type_library_path>
use binaryninja::binary_view::BinaryViewExt;
-use binaryninja::type_library::TypeLibrary;
-use binaryninja::types::QualifiedName;
+use binaryninja::types::{QualifiedName, TypeLibrary};
fn main() {
let bndb_path_str = std::env::args().nth(1).expect("No header provided");
diff --git a/rust/examples/create_type_library.rs b/rust/examples/create_type_library.rs
index 35e9b11c..74d93765 100644
--- a/rust/examples/create_type_library.rs
+++ b/rust/examples/create_type_library.rs
@@ -1,8 +1,7 @@
// Usage: cargo run --example create_type_library <header_file_path> <platform> <type_library_path>
use binaryninja::platform::Platform;
-use binaryninja::type_library::TypeLibrary;
-use binaryninja::type_parser::{CoreTypeParser, TypeParser};
+use binaryninja::types::{CoreTypeParser, TypeLibrary, TypeParser};
fn main() {
let header_path_str = std::env::args().nth(1).expect("No header provided");
diff --git a/rust/examples/dump_type_library.rs b/rust/examples/dump_type_library.rs
index 34ca1baf..f7398d28 100644
--- a/rust/examples/dump_type_library.rs
+++ b/rust/examples/dump_type_library.rs
@@ -2,8 +2,8 @@
use binaryninja::binary_view::BinaryView;
use binaryninja::file_metadata::FileMetadata;
-use binaryninja::type_library::TypeLibrary;
-use binaryninja::type_printer::{CoreTypePrinter, TokenEscapingType};
+use binaryninja::types::library::TypeLibrary;
+use binaryninja::types::printer::{CoreTypePrinter, TokenEscapingType};
fn main() {
let type_lib_str = std::env::args().nth(1).expect("No type library provided");
diff --git a/rust/examples/type_printer.rs b/rust/examples/type_printer.rs
index 846e1a09..b88a0233 100644
--- a/rust/examples/type_printer.rs
+++ b/rust/examples/type_printer.rs
@@ -1,4 +1,4 @@
-use binaryninja::type_printer::{CoreTypePrinter, TokenEscapingType};
+use binaryninja::types::printer::{CoreTypePrinter, TokenEscapingType};
use binaryninja::types::{MemberAccess, MemberScope, Structure, StructureMember, Type};
fn main() {
diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs
index a48d0264..459253b9 100644
--- a/rust/src/binary_view.rs
+++ b/rust/src/binary_view.rs
@@ -30,10 +30,12 @@ pub use crate::workflow::AnalysisContext;
use crate::architecture::{Architecture, CoreArchitecture};
use crate::base_detection::BaseAddressDetection;
use crate::basic_block::BasicBlock;
+use crate::binary_view::search::SearchQuery;
use crate::component::Component;
use crate::confidence::Conf;
use crate::data_buffer::DataBuffer;
use crate::debuginfo::DebugInfo;
+use crate::disassembly::DisassemblySettings;
use crate::external_library::{ExternalLibrary, ExternalLocation};
use crate::file_accessor::{Accessor, FileAccessor};
use crate::file_metadata::FileMetadata;
@@ -53,12 +55,12 @@ use crate::settings::Settings;
use crate::string::*;
use crate::symbol::{Symbol, SymbolType};
use crate::tags::{Tag, TagType};
-use crate::type_container::TypeContainer;
-use crate::type_library::TypeLibrary;
use crate::types::{
NamedTypeReference, QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type,
+ TypeArchive, TypeArchiveId, TypeContainer, TypeLibrary,
};
use crate::variable::DataVariable;
+use crate::workflow::Workflow;
use crate::{Endianness, BN_FULL_CONFIDENCE};
use std::collections::HashMap;
use std::ffi::{c_char, c_void, CString};
@@ -67,17 +69,12 @@ use std::ops::Range;
use std::path::{Path, PathBuf};
use std::ptr::NonNull;
use std::{result, slice};
-// TODO : general reorg of modules related to bv
pub mod memory_map;
pub mod reader;
pub mod search;
pub mod writer;
-use crate::binary_view::search::SearchQuery;
-use crate::disassembly::DisassemblySettings;
-use crate::type_archive::{TypeArchive, TypeArchiveId};
-use crate::workflow::Workflow;
pub use memory_map::MemoryMap;
pub use reader::BinaryReader;
pub use writer::BinaryWriter;
diff --git a/rust/src/collaboration/sync.rs b/rust/src/collaboration/sync.rs
index a8006b8b..72c57a46 100644
--- a/rust/src/collaboration/sync.rs
+++ b/rust/src/collaboration/sync.rs
@@ -13,7 +13,7 @@ use crate::progress::{NoProgressCallback, ProgressCallback};
use crate::project::file::ProjectFile;
use crate::rc::Ref;
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_archive::{TypeArchive, TypeArchiveMergeConflict};
+use crate::types::archive::{TypeArchive, TypeArchiveMergeConflict};
/// Get the default directory path for a remote Project. This is based off the Setting for
/// collaboration.directory, the project's id, and the project's remote's id.
diff --git a/rust/src/component.rs b/rust/src/component.rs
index 4c5d5992..f038d5c3 100644
--- a/rust/src/component.rs
+++ b/rust/src/component.rs
@@ -2,7 +2,7 @@ use crate::binary_view::{BinaryView, BinaryViewExt};
use crate::function::Function;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
use crate::string::{BnString, IntoCStr};
-use crate::types::ComponentReferencedType;
+use crate::types::Type;
use std::ffi::c_char;
use std::fmt::Debug;
use std::ptr::NonNull;
@@ -304,3 +304,24 @@ unsafe impl CoreArrayProviderInner for Component {
Guard::new(Self::from_raw(raw_ptr), context)
}
}
+
+// TODO: Remove this struct, or make it not a ZST with a terrible array provider.
+/// ZST used only for `Array<ComponentReferencedType>`.
+pub struct ComponentReferencedType;
+
+impl CoreArrayProvider for ComponentReferencedType {
+ type Raw = *mut BNType;
+ type Context = ();
+ type Wrapped<'a> = &'a Type;
+}
+
+unsafe impl CoreArrayProviderInner for ComponentReferencedType {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNComponentFreeReferencedTypes(raw, count)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ // SAFETY: &*mut BNType == &Type (*mut BNType == Type)
+ std::mem::transmute(raw)
+ }
+}
diff --git a/rust/src/data_notification.rs b/rust/src/data_notification.rs
index 7749e792..d01a5ed3 100644
--- a/rust/src/data_notification.rs
+++ b/rust/src/data_notification.rs
@@ -15,8 +15,7 @@ use crate::section::Section;
use crate::segment::Segment;
use crate::symbol::Symbol;
use crate::tags::{TagReference, TagType};
-use crate::type_archive::TypeArchive;
-use crate::types::{QualifiedName, Type};
+use crate::types::{QualifiedName, Type, TypeArchive};
use crate::variable::DataVariable;
macro_rules! trait_handler {
diff --git a/rust/src/language_representation.rs b/rust/src/language_representation.rs
index 34524b96..d39cb95f 100644
--- a/rust/src/language_representation.rs
+++ b/rust/src/language_representation.rs
@@ -14,8 +14,7 @@ use crate::high_level_il::{HighLevelExpressionIndex, HighLevelILFunction};
use crate::line_formatter::CoreLineFormatter;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable};
use crate::string::{BnString, IntoCStr};
-use crate::type_parser::CoreTypeParser;
-use crate::type_printer::CoreTypePrinter;
+use crate::types::{CoreTypeParser, CoreTypePrinter};
pub type InstructionTextTokenContext = BNInstructionTextTokenContext;
pub type ScopeType = BNScopeType;
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index f3166033..2d9cab27 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -81,11 +81,6 @@ pub mod string;
pub mod symbol;
pub mod tags;
pub mod template_simplifier;
-pub mod type_archive;
-pub mod type_container;
-pub mod type_library;
-pub mod type_parser;
-pub mod type_printer;
pub mod types;
pub mod update;
pub mod variable;
diff --git a/rust/src/platform.rs b/rust/src/platform.rs
index 609f4edc..ed4f49f4 100644
--- a/rust/src/platform.rs
+++ b/rust/src/platform.rs
@@ -14,15 +14,15 @@
//! Contains all information related to the execution environment of the binary, mainly the calling conventions used
-use crate::type_container::TypeContainer;
-use crate::type_parser::{TypeParserError, TypeParserErrorSeverity, TypeParserResult};
use crate::{
architecture::{Architecture, CoreArchitecture},
calling_convention::CoreCallingConvention,
rc::*,
string::*,
- type_library::TypeLibrary,
- types::QualifiedNameAndType,
+ types::{
+ QualifiedNameAndType, TypeContainer, TypeLibrary, TypeParserError, TypeParserErrorSeverity,
+ TypeParserResult,
+ },
};
use binaryninjacore_sys::*;
use std::fmt::Debug;
diff --git a/rust/src/string.rs b/rust/src/string.rs
index c7d541ce..8505cbf5 100644
--- a/rust/src/string.rs
+++ b/rust/src/string.rs
@@ -24,7 +24,6 @@ use std::ops::Deref;
use std::path::{Path, PathBuf};
use crate::rc::*;
-use crate::type_archive::TypeArchiveSnapshotId;
use crate::types::QualifiedName;
// TODO: Remove or refactor this.
@@ -288,14 +287,6 @@ impl IntoCStr for &Path {
}
}
-impl IntoCStr for TypeArchiveSnapshotId {
- type Result = CString;
-
- fn to_cstr(self) -> Self::Result {
- self.to_string().to_cstr()
- }
-}
-
pub trait IntoJson {
type Output: IntoCStr;
diff --git a/rust/src/types.rs b/rust/src/types.rs
index 1387ffb3..cfdc865b 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -11,16 +11,19 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-#![allow(unused)]
-// TODO : More widely enforce the use of ref_from_raw vs just from_raw to simplify internal binding usage? Perhaps remove from_raw functions?
-// TODO : Add documentation and fix examples
-// TODO : Test the get_enumeration and get_structure methods
+pub mod archive;
+pub mod container;
+pub mod enumeration;
+pub mod library;
+pub mod parser;
+pub mod printer;
+pub mod structure;
use binaryninjacore_sys::*;
use crate::{
- architecture::{Architecture, CoreArchitecture},
+ architecture::Architecture,
binary_view::{BinaryView, BinaryViewExt},
calling_convention::CoreCallingConvention,
rc::*,
@@ -29,19 +32,30 @@ use crate::{
use crate::confidence::{Conf, MAX_CONFIDENCE, MIN_CONFIDENCE};
use crate::string::{raw_to_string, strings_to_string_list};
-use crate::type_container::TypeContainer;
use crate::variable::{Variable, VariableSourceType};
use std::borrow::Cow;
use std::num::NonZeroUsize;
use std::ops::{Index, IndexMut};
use std::{
collections::HashSet,
- ffi::CStr,
fmt::{Debug, Display, Formatter},
hash::{Hash, Hasher},
iter::IntoIterator,
};
+pub use archive::{TypeArchive, TypeArchiveId, TypeArchiveSnapshotId};
+pub use container::TypeContainer;
+pub use enumeration::{Enumeration, EnumerationBuilder, EnumerationMember};
+pub use library::TypeLibrary;
+pub use parser::{
+ CoreTypeParser, ParsedType, TypeParser, TypeParserError, TypeParserErrorSeverity,
+ TypeParserResult,
+};
+pub use printer::{CoreTypePrinter, TypePrinter};
+pub use structure::{
+ BaseStructure, InheritedStructureMember, Structure, StructureBuilder, StructureMember,
+};
+
pub type StructureType = BNStructureVariant;
pub type ReferenceType = BNReferenceType;
pub type TypeClass = BNTypeClass;
@@ -970,7 +984,7 @@ impl Debug for Type {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
// You might be tempted to rip this atrocity out and make this more "sensible". READ BELOW!
// Type is a one-size fits all structure, these are actually its fields! If we wanted to
- // omit some fields for different type classes what you really want to do is implement your
+ // omit some fields for different type classes, what you really want to do is implement your
// own formatter. This is supposed to represent the structure entirely, it's not supposed to be pretty!
f.debug_struct("Type")
.field("type_class", &self.type_class())
@@ -1048,27 +1062,6 @@ unsafe impl CoreArrayProviderInner for Type {
}
}
-// TODO: Remove this struct, or make it not a ZST with a terrible array provider.
-/// ZST used only for `Array<ComponentReferencedType>`.
-pub struct ComponentReferencedType;
-
-impl CoreArrayProvider for ComponentReferencedType {
- type Raw = *mut BNType;
- type Context = ();
- type Wrapped<'a> = &'a Type;
-}
-
-unsafe impl CoreArrayProviderInner for ComponentReferencedType {
- unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
- BNComponentFreeReferencedTypes(raw, count)
- }
-
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- // SAFETY: &*mut BNType == &Type (*mut BNType == Type)
- std::mem::transmute(raw)
- }
-}
-
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct FunctionParameter {
pub ty: Conf<Ref<Type>>,
@@ -1105,6 +1098,7 @@ impl FunctionParameter {
}
}
+ #[allow(unused)]
pub(crate) fn from_owned_raw(value: BNFunctionParameter) -> Self {
let owned = Self::from_raw(&value);
Self::free_raw(value);
@@ -1136,875 +1130,6 @@ impl FunctionParameter {
}
}
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct EnumerationMember {
- pub name: String,
- /// The associated constant value for the member.
- pub value: u64,
- /// Whether this is the default member for the associated [`Enumeration`].
- pub default: bool,
-}
-
-impl EnumerationMember {
- pub(crate) fn from_raw(value: &BNEnumerationMember) -> Self {
- Self {
- name: raw_to_string(value.name).unwrap(),
- value: value.value,
- default: value.isDefault,
- }
- }
-
- pub(crate) fn from_owned_raw(value: BNEnumerationMember) -> Self {
- let owned = Self::from_raw(&value);
- Self::free_raw(value);
- owned
- }
-
- pub(crate) fn into_raw(value: Self) -> BNEnumerationMember {
- let bn_name = BnString::new(value.name);
- BNEnumerationMember {
- name: BnString::into_raw(bn_name),
- value: value.value,
- isDefault: value.default,
- }
- }
-
- pub(crate) fn free_raw(value: BNEnumerationMember) {
- unsafe { BnString::free_raw(value.name) };
- }
-
- pub fn new(name: String, value: u64, default: bool) -> Self {
- Self {
- name,
- value,
- default,
- }
- }
-}
-
-#[derive(PartialEq, Eq, Hash)]
-pub struct EnumerationBuilder {
- pub(crate) handle: *mut BNEnumerationBuilder,
-}
-
-impl EnumerationBuilder {
- pub fn new() -> Self {
- Self {
- handle: unsafe { BNCreateEnumerationBuilder() },
- }
- }
-
- pub(crate) unsafe fn from_raw(handle: *mut BNEnumerationBuilder) -> Self {
- Self { handle }
- }
-
- pub fn finalize(&self) -> Ref<Enumeration> {
- unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.handle)) }
- }
-
- pub fn append(&mut self, name: &str) -> &mut Self {
- let name = name.to_cstr();
- unsafe {
- BNAddEnumerationBuilderMember(self.handle, name.as_ref().as_ptr() as _);
- }
- self
- }
-
- pub fn insert(&mut self, name: &str, value: u64) -> &mut Self {
- let name = name.to_cstr();
- unsafe {
- BNAddEnumerationBuilderMemberWithValue(self.handle, name.as_ref().as_ptr() as _, value);
- }
- self
- }
-
- pub fn replace(&mut self, id: usize, name: &str, value: u64) -> &mut Self {
- let name = name.to_cstr();
- unsafe {
- BNReplaceEnumerationBuilderMember(self.handle, id, name.as_ref().as_ptr() as _, value);
- }
- self
- }
-
- pub fn remove(&mut self, id: usize) -> &mut Self {
- unsafe {
- BNRemoveEnumerationBuilderMember(self.handle, id);
- }
-
- self
- }
-
- pub fn members(&self) -> Vec<EnumerationMember> {
- unsafe {
- let mut count = 0;
- let members_raw_ptr = BNGetEnumerationBuilderMembers(self.handle, &mut count);
- let members_raw: &[BNEnumerationMember] =
- std::slice::from_raw_parts(members_raw_ptr, count);
- let members = members_raw
- .iter()
- .map(EnumerationMember::from_raw)
- .collect();
- BNFreeEnumerationMemberList(members_raw_ptr, count);
- members
- }
- }
-}
-
-impl Default for EnumerationBuilder {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl From<&Enumeration> for EnumerationBuilder {
- fn from(enumeration: &Enumeration) -> Self {
- unsafe {
- Self::from_raw(BNCreateEnumerationBuilderFromEnumeration(
- enumeration.handle,
- ))
- }
- }
-}
-
-impl Drop for EnumerationBuilder {
- fn drop(&mut self) {
- unsafe { BNFreeEnumerationBuilder(self.handle) };
- }
-}
-
-#[derive(PartialEq, Eq, Hash)]
-pub struct Enumeration {
- pub(crate) handle: *mut BNEnumeration,
-}
-
-impl Enumeration {
- pub(crate) unsafe fn ref_from_raw(handle: *mut BNEnumeration) -> Ref<Self> {
- debug_assert!(!handle.is_null());
- Ref::new(Self { handle })
- }
-
- pub fn builder() -> EnumerationBuilder {
- EnumerationBuilder::new()
- }
-
- pub fn members(&self) -> Vec<EnumerationMember> {
- unsafe {
- let mut count = 0;
- let members_raw_ptr = BNGetEnumerationMembers(self.handle, &mut count);
- debug_assert!(!members_raw_ptr.is_null());
- let members_raw: &[BNEnumerationMember] =
- std::slice::from_raw_parts(members_raw_ptr, count);
- let members = members_raw
- .iter()
- .map(EnumerationMember::from_raw)
- .collect();
- BNFreeEnumerationMemberList(members_raw_ptr, count);
- members
- }
- }
-}
-
-impl Debug for Enumeration {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("Enumeration")
- .field("members", &self.members())
- .finish()
- }
-}
-
-unsafe impl RefCountable for Enumeration {
- unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
- Self::ref_from_raw(BNNewEnumerationReference(handle.handle))
- }
-
- unsafe fn dec_ref(handle: &Self) {
- BNFreeEnumeration(handle.handle);
- }
-}
-
-impl ToOwned for Enumeration {
- type Owned = Ref<Self>;
-
- fn to_owned(&self) -> Self::Owned {
- unsafe { RefCountable::inc_ref(self) }
- }
-}
-
-#[derive(PartialEq, Eq, Hash)]
-pub struct StructureBuilder {
- pub(crate) handle: *mut BNStructureBuilder,
-}
-
-/// ```no_run
-/// // Includes
-/// # use binaryninja::binary_view::BinaryViewExt;
-/// use binaryninja::types::{MemberAccess, MemberScope, Structure, StructureBuilder, Type};
-///
-/// // Types to use in the members
-/// let field_1_ty = Type::named_int(5, false, "my_weird_int_type");
-/// let field_2_ty = Type::int(4, false);
-/// let field_3_ty = Type::int(8, false);
-///
-/// // Assign those fields
-/// let mut my_custom_struct = StructureBuilder::new();
-/// my_custom_struct
-/// .insert(
-/// &field_1_ty,
-/// "field_1",
-/// 0,
-/// false,
-/// MemberAccess::PublicAccess,
-/// MemberScope::NoScope,
-/// )
-/// .insert(
-/// &field_2_ty,
-/// "field_2",
-/// 5,
-/// false,
-/// MemberAccess::PublicAccess,
-/// MemberScope::NoScope,
-/// )
-/// .insert(
-/// &field_3_ty,
-/// "field_3",
-/// 9,
-/// false,
-/// MemberAccess::PublicAccess,
-/// MemberScope::NoScope,
-/// )
-/// .append(
-/// &field_1_ty,
-/// "field_4",
-/// MemberAccess::PublicAccess,
-/// MemberScope::NoScope,
-/// );
-///
-/// // Convert structure to type
-/// let my_custom_structure_type = Type::structure(&my_custom_struct.finalize());
-///
-/// // Add the struct to the binary view to use in analysis
-/// let bv = binaryninja::load("example").unwrap();
-/// bv.define_user_type("my_custom_struct", &my_custom_structure_type);
-/// ```
-impl StructureBuilder {
- pub fn new() -> Self {
- Self {
- handle: unsafe { BNCreateStructureBuilder() },
- }
- }
-
- pub(crate) unsafe fn from_raw(handle: *mut BNStructureBuilder) -> Self {
- debug_assert!(!handle.is_null());
- Self { handle }
- }
-
- // TODO: Document the width adjustment with alignment.
- pub fn finalize(&self) -> Ref<Structure> {
- let raw_struct_ptr = unsafe { BNFinalizeStructureBuilder(self.handle) };
- unsafe { Structure::ref_from_raw(raw_struct_ptr) }
- }
-
- /// Sets the width of the [`StructureBuilder`] to the new width.
- ///
- /// This will remove all previously inserted members outside the new width. This is done by computing
- /// the member access range (member offset + member width) and if it is larger than the new width
- /// it will be removed.
- pub fn width(&mut self, width: u64) -> &mut Self {
- unsafe {
- BNSetStructureBuilderWidth(self.handle, width);
- }
- self
- }
-
- pub fn alignment(&mut self, alignment: usize) -> &mut Self {
- unsafe {
- BNSetStructureBuilderAlignment(self.handle, alignment);
- }
- self
- }
-
- /// Sets whether the [`StructureBuilder`] is packed.
- ///
- /// If set the alignment of the structure will be `1`. You do not need to set the alignment to `1`.
- pub fn packed(&mut self, packed: bool) -> &mut Self {
- unsafe {
- BNSetStructureBuilderPacked(self.handle, packed);
- }
- self
- }
-
- pub fn structure_type(&mut self, t: StructureType) -> &mut Self {
- unsafe { BNSetStructureBuilderType(self.handle, t) };
- self
- }
-
- pub fn pointer_offset(&mut self, offset: i64) -> &mut Self {
- unsafe { BNSetStructureBuilderPointerOffset(self.handle, offset) };
- self
- }
-
- pub fn propagates_data_var_refs(&mut self, propagates: bool) -> &mut Self {
- unsafe { BNSetStructureBuilderPropagatesDataVariableReferences(self.handle, propagates) };
- self
- }
-
- pub fn base_structures(&mut self, bases: &[BaseStructure]) -> &mut Self {
- let raw_base_structs: Vec<BNBaseStructure> =
- bases.iter().map(BaseStructure::into_owned_raw).collect();
- unsafe {
- BNSetBaseStructuresForStructureBuilder(
- self.handle,
- raw_base_structs.as_ptr() as *mut _,
- raw_base_structs.len(),
- )
- };
- self
- }
-
- /// Append a member at the next available byte offset.
- ///
- /// Otherwise, consider using:
- ///
- /// - [`StructureBuilder::insert_member`]
- /// - [`StructureBuilder::insert`]
- /// - [`StructureBuilder::insert_bitwise`]
- pub fn append<'a, T: Into<Conf<&'a Type>>>(
- &mut self,
- ty: T,
- name: &str,
- access: MemberAccess,
- scope: MemberScope,
- ) -> &mut Self {
- let name = name.to_cstr();
- let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
- unsafe {
- BNAddStructureBuilderMember(
- self.handle,
- &owned_raw_ty,
- name.as_ref().as_ptr() as _,
- access,
- scope,
- );
- }
- self
- }
-
- /// Insert an already constructed [`StructureMember`].
- ///
- /// Otherwise, consider using:
- ///
- /// - [`StructureBuilder::append`]
- /// - [`StructureBuilder::insert`]
- /// - [`StructureBuilder::insert_bitwise`]
- pub fn insert_member(
- &mut self,
- member: StructureMember,
- overwrite_existing: bool,
- ) -> &mut Self {
- self.insert_bitwise(
- &member.ty,
- &member.name,
- member.bit_offset(),
- member.bit_width,
- overwrite_existing,
- member.access,
- member.scope,
- );
- self
- }
-
- /// Inserts a member at the `offset` (in bytes).
- ///
- /// If you need to insert a member at a specific bit within a given byte (like a bitfield), you
- /// can use [`StructureBuilder::insert_bitwise`].
- pub fn insert<'a, T: Into<Conf<&'a Type>>>(
- &mut self,
- ty: T,
- name: &str,
- offset: u64,
- overwrite_existing: bool,
- access: MemberAccess,
- scope: MemberScope,
- ) -> &mut Self {
- self.insert_bitwise(
- ty,
- name,
- offset * 8,
- None,
- overwrite_existing,
- access,
- scope,
- )
- }
-
- /// Inserts a member at `bit_offset` with an optional `bit_width`.
- ///
- /// NOTE: The `bit_offset` is relative to the start of the structure, for example, passing `8` will place
- /// the field at the start of the byte `0x1`.
- pub fn insert_bitwise<'a, T: Into<Conf<&'a Type>>>(
- &mut self,
- ty: T,
- name: &str,
- bit_offset: u64,
- bit_width: Option<u8>,
- overwrite_existing: bool,
- access: MemberAccess,
- scope: MemberScope,
- ) -> &mut Self {
- let name = name.to_cstr();
- let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
- let byte_offset = bit_offset / 8;
- let bit_position = bit_offset % 8;
- unsafe {
- BNAddStructureBuilderMemberAtOffset(
- self.handle,
- &owned_raw_ty,
- name.as_ref().as_ptr() as _,
- byte_offset,
- overwrite_existing,
- access,
- scope,
- bit_position as u8,
- bit_width.unwrap_or(0),
- );
- }
- self
- }
-
- pub fn replace<'a, T: Into<Conf<&'a Type>>>(
- &mut self,
- index: usize,
- ty: T,
- name: &str,
- overwrite_existing: bool,
- ) -> &mut Self {
- let name = name.to_cstr();
- let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
- unsafe {
- BNReplaceStructureBuilderMember(
- self.handle,
- index,
- &owned_raw_ty,
- name.as_ref().as_ptr() as _,
- overwrite_existing,
- )
- }
- self
- }
-
- /// Removes the member at a given index.
- pub fn remove(&mut self, index: usize) -> &mut Self {
- unsafe { BNRemoveStructureBuilderMember(self.handle, index) };
- self
- }
-
- // TODO: We should add BNGetStructureBuilderAlignedWidth
- /// Gets the current **unaligned** width of the structure.
- ///
- /// This cannot be used to accurately get the width of a non-packed structure.
- pub fn current_width(&self) -> u64 {
- unsafe { BNGetStructureBuilderWidth(self.handle) }
- }
-}
-
-impl From<&Structure> for StructureBuilder {
- fn from(structure: &Structure) -> StructureBuilder {
- unsafe { Self::from_raw(BNCreateStructureBuilderFromStructure(structure.handle)) }
- }
-}
-
-impl From<Vec<StructureMember>> for StructureBuilder {
- fn from(members: Vec<StructureMember>) -> StructureBuilder {
- let mut builder = StructureBuilder::new();
- for member in members {
- builder.insert_member(member, false);
- }
- builder
- }
-}
-
-impl Drop for StructureBuilder {
- fn drop(&mut self) {
- unsafe { BNFreeStructureBuilder(self.handle) };
- }
-}
-
-impl Default for StructureBuilder {
- fn default() -> Self {
- Self::new()
- }
-}
-
-#[derive(PartialEq, Eq, Hash)]
-pub struct Structure {
- pub(crate) handle: *mut BNStructure,
-}
-
-impl Structure {
- pub(crate) unsafe fn ref_from_raw(handle: *mut BNStructure) -> Ref<Self> {
- debug_assert!(!handle.is_null());
- Ref::new(Self { handle })
- }
-
- pub fn builder() -> StructureBuilder {
- StructureBuilder::new()
- }
-
- pub fn width(&self) -> u64 {
- unsafe { BNGetStructureWidth(self.handle) }
- }
-
- pub fn structure_type(&self) -> StructureType {
- unsafe { BNGetStructureType(self.handle) }
- }
-
- /// Retrieve the members that are accessible at a given offset.
- ///
- /// The reason for this being plural is that members may overlap and the offset is in bytes
- /// where a bitfield may contain multiple members at the given byte.
- ///
- /// Unions are also represented as structures and will cause this function to return
- /// **all** members that can reach that offset.
- ///
- /// We must pass a [`TypeContainer`] here so that we can resolve base structure members, as they
- /// are treated as members through this function. Typically, you get the [`TypeContainer`]
- /// through the binary view with [`BinaryViewExt::type_container`].
- pub fn members_at_offset(
- &self,
- container: &TypeContainer,
- offset: u64,
- ) -> Vec<StructureMember> {
- self.members_including_inherited(container)
- .into_iter()
- .filter(|m| m.member.is_offset_valid(offset))
- .map(|m| m.member)
- .collect()
- }
-
- /// Return the list of non-inherited structure members.
- ///
- /// If you want to get all members, including ones inherited from base structures,
- /// use [`Structure::members_including_inherited`] instead.
- pub fn members(&self) -> Vec<StructureMember> {
- unsafe {
- let mut count = 0;
- let members_raw_ptr: *mut BNStructureMember =
- BNGetStructureMembers(self.handle, &mut count);
- debug_assert!(!members_raw_ptr.is_null());
- let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
- let members = members_raw.iter().map(StructureMember::from_raw).collect();
- BNFreeStructureMemberList(members_raw_ptr, count);
- members
- }
- }
-
- /// Returns the list of all structure members, including inherited ones.
- ///
- /// Because we must traverse through base structures, we have to provide the [`TypeContainer`];
- /// in most cases it is ok to provide the binary views container via [`BinaryViewExt::type_container`].
- pub fn members_including_inherited(
- &self,
- container: &TypeContainer,
- ) -> Vec<InheritedStructureMember> {
- unsafe {
- let mut count = 0;
- let members_raw_ptr: *mut BNInheritedStructureMember =
- BNGetStructureMembersIncludingInherited(
- self.handle,
- container.handle.as_ptr(),
- &mut count,
- );
- debug_assert!(!members_raw_ptr.is_null());
- let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
- let members = members_raw
- .iter()
- .map(InheritedStructureMember::from_raw)
- .collect();
- BNFreeInheritedStructureMemberList(members_raw_ptr, count);
- members
- }
- }
-
- /// Retrieve the list of base structures for the structure. These base structures are what give
- /// a structure inherited members.
- pub fn base_structures(&self) -> Vec<BaseStructure> {
- let mut count = 0;
- let bases_raw_ptr = unsafe { BNGetBaseStructuresForStructure(self.handle, &mut count) };
- debug_assert!(!bases_raw_ptr.is_null());
- let bases_raw = unsafe { std::slice::from_raw_parts(bases_raw_ptr, count) };
- let bases = bases_raw.iter().map(BaseStructure::from_raw).collect();
- unsafe { BNFreeBaseStructureList(bases_raw_ptr, count) };
- bases
- }
-
- /// Whether the structure is packed or not.
- pub fn is_packed(&self) -> bool {
- unsafe { BNIsStructurePacked(self.handle) }
- }
-
- pub fn alignment(&self) -> usize {
- unsafe { BNGetStructureAlignment(self.handle) }
- }
-}
-
-impl Debug for Structure {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("Structure")
- .field("width", &self.width())
- .field("alignment", &self.alignment())
- .field("packed", &self.is_packed())
- .field("structure_type", &self.structure_type())
- .field("base_structures", &self.base_structures())
- .field("members", &self.members())
- .finish()
- }
-}
-
-unsafe impl RefCountable for Structure {
- unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
- Self::ref_from_raw(BNNewStructureReference(handle.handle))
- }
-
- unsafe fn dec_ref(handle: &Self) {
- BNFreeStructure(handle.handle);
- }
-}
-
-impl ToOwned for Structure {
- type Owned = Ref<Self>;
-
- fn to_owned(&self) -> Self::Owned {
- unsafe { RefCountable::inc_ref(self) }
- }
-}
-
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct StructureMember {
- pub ty: Conf<Ref<Type>>,
- // TODO: Shouldnt this be a QualifiedName? The ffi says no...
- pub name: String,
- /// The byte offset of the member.
- pub offset: u64,
- pub access: MemberAccess,
- pub scope: MemberScope,
- /// The bit position relative to the byte offset.
- pub bit_position: Option<u8>,
- pub bit_width: Option<u8>,
-}
-
-impl StructureMember {
- pub(crate) fn from_raw(value: &BNStructureMember) -> Self {
- Self {
- ty: Conf::new(
- unsafe { Type::from_raw(value.type_) }.to_owned(),
- value.typeConfidence,
- ),
- // TODO: I dislike using this function here.
- name: raw_to_string(value.name as *mut _).unwrap(),
- offset: value.offset,
- access: value.access,
- scope: value.scope,
- bit_position: match value.bitPosition {
- 0 => None,
- _ => Some(value.bitPosition),
- },
- bit_width: match value.bitWidth {
- 0 => None,
- _ => Some(value.bitWidth),
- },
- }
- }
-
- pub(crate) fn from_owned_raw(value: BNStructureMember) -> Self {
- let owned = Self::from_raw(&value);
- Self::free_raw(value);
- owned
- }
-
- pub(crate) fn into_raw(value: Self) -> BNStructureMember {
- let bn_name = BnString::new(value.name);
- BNStructureMember {
- type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
- name: BnString::into_raw(bn_name),
- offset: value.offset,
- typeConfidence: value.ty.confidence,
- access: value.access,
- scope: value.scope,
- bitPosition: value.bit_position.unwrap_or(0),
- bitWidth: value.bit_width.unwrap_or(0),
- }
- }
-
- pub(crate) fn free_raw(value: BNStructureMember) {
- let _ = unsafe { Type::ref_from_raw(value.type_) };
- unsafe { BnString::free_raw(value.name) };
- }
-
- pub fn new(
- ty: Conf<Ref<Type>>,
- name: String,
- offset: u64,
- access: MemberAccess,
- scope: MemberScope,
- ) -> Self {
- Self {
- ty,
- name,
- offset,
- access,
- scope,
- bit_position: None,
- bit_width: None,
- }
- }
-
- pub fn new_bitfield(
- ty: Conf<Ref<Type>>,
- name: String,
- bit_offset: u64,
- bit_width: u8,
- access: MemberAccess,
- scope: MemberScope,
- ) -> Self {
- Self {
- ty,
- name,
- offset: bit_offset / 8,
- access,
- scope,
- bit_position: Some((bit_offset % 8) as u8),
- bit_width: Some(bit_width),
- }
- }
-
- // TODO: Do we count bitwidth here?
- /// Whether the offset within the accessible range of the member.
- pub fn is_offset_valid(&self, offset: u64) -> bool {
- self.offset <= offset && offset < self.offset + self.ty.contents.width()
- }
-
- /// Member offset in bits.
- pub fn bit_offset(&self) -> u64 {
- (self.offset * 8) + self.bit_position.unwrap_or(0) as u64
- }
-}
-
-impl CoreArrayProvider for StructureMember {
- type Raw = BNStructureMember;
- type Context = ();
- type Wrapped<'a> = Self;
-}
-
-unsafe impl CoreArrayProviderInner for StructureMember {
- unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
- BNFreeStructureMemberList(raw, count)
- }
-
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- Self::from_raw(raw)
- }
-}
-
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct InheritedStructureMember {
- pub base: Ref<NamedTypeReference>,
- pub base_offset: u64,
- pub member: StructureMember,
- pub member_index: usize,
-}
-
-impl InheritedStructureMember {
- pub(crate) fn from_raw(value: &BNInheritedStructureMember) -> Self {
- Self {
- base: unsafe { NamedTypeReference::from_raw(value.base) }.to_owned(),
- base_offset: value.baseOffset,
- member: StructureMember::from_raw(&value.member),
- member_index: value.memberIndex,
- }
- }
-
- pub(crate) fn from_owned_raw(value: BNInheritedStructureMember) -> Self {
- let owned = Self::from_raw(&value);
- Self::free_raw(value);
- owned
- }
-
- pub(crate) fn into_raw(value: Self) -> BNInheritedStructureMember {
- BNInheritedStructureMember {
- base: unsafe { Ref::into_raw(value.base) }.handle,
- baseOffset: value.base_offset,
- member: StructureMember::into_raw(value.member),
- memberIndex: value.member_index,
- }
- }
-
- pub(crate) fn free_raw(value: BNInheritedStructureMember) {
- let _ = unsafe { NamedTypeReference::ref_from_raw(value.base) };
- StructureMember::free_raw(value.member);
- }
-
- pub fn new(
- base: Ref<NamedTypeReference>,
- base_offset: u64,
- member: StructureMember,
- member_index: usize,
- ) -> Self {
- Self {
- base,
- base_offset,
- member,
- member_index,
- }
- }
-}
-
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct BaseStructure {
- pub ty: Ref<NamedTypeReference>,
- pub offset: u64,
- pub width: u64,
-}
-
-impl BaseStructure {
- pub(crate) fn from_raw(value: &BNBaseStructure) -> Self {
- Self {
- ty: unsafe { NamedTypeReference::from_raw(value.type_) }.to_owned(),
- offset: value.offset,
- width: value.width,
- }
- }
-
- pub(crate) fn from_owned_raw(value: BNBaseStructure) -> Self {
- let owned = Self::from_raw(&value);
- Self::free_raw(value);
- owned
- }
-
- pub(crate) fn into_raw(value: Self) -> BNBaseStructure {
- BNBaseStructure {
- type_: unsafe { Ref::into_raw(value.ty) }.handle,
- offset: value.offset,
- width: value.width,
- }
- }
-
- pub(crate) fn into_owned_raw(value: &Self) -> BNBaseStructure {
- BNBaseStructure {
- type_: value.ty.handle,
- offset: value.offset,
- width: value.width,
- }
- }
-
- pub(crate) fn free_raw(value: BNBaseStructure) {
- let _ = unsafe { NamedTypeReference::ref_from_raw(value.type_) };
- }
-
- pub fn new(ty: Ref<NamedTypeReference>, offset: u64, width: u64) -> Self {
- Self { ty, offset, width }
- }
-}
-
#[derive(PartialEq, Eq, Hash)]
pub struct NamedTypeReference {
pub(crate) handle: *mut BNNamedTypeReference,
@@ -2435,6 +1560,7 @@ impl QualifiedNameTypeAndId {
}
}
+ #[allow(unused)]
pub(crate) fn from_owned_raw(value: BNQualifiedNameTypeAndId) -> Self {
let owned = Self::from_raw(&value);
Self::free_raw(value);
@@ -2495,6 +1621,7 @@ impl NameAndType {
}
}
+ #[allow(unused)]
pub(crate) fn from_owned_raw(value: BNNameAndType) -> Self {
let owned = Self::from_raw(&value);
Self::free_raw(value);
diff --git a/rust/src/type_archive.rs b/rust/src/types/archive.rs
index 4a047205..15f4cbfe 100644
--- a/rust/src/type_archive.rs
+++ b/rust/src/types/archive.rs
@@ -1,6 +1,6 @@
use crate::progress::{NoProgressCallback, ProgressCallback};
use binaryninjacore_sys::*;
-use std::ffi::{c_char, c_void, CStr};
+use std::ffi::{c_char, c_void, CStr, CString};
use std::fmt::{Debug, Display, Formatter};
use std::hash::Hash;
use std::path::{Path, PathBuf};
@@ -11,8 +11,9 @@ use crate::metadata::Metadata;
use crate::platform::Platform;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_container::TypeContainer;
-use crate::types::{QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type};
+use crate::types::{
+ QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type, TypeContainer,
+};
#[repr(transparent)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -57,6 +58,14 @@ unsafe impl CoreArrayProviderInner for TypeArchiveSnapshotId {
}
}
+impl IntoCStr for TypeArchiveSnapshotId {
+ type Result = CString;
+
+ fn to_cstr(self) -> Self::Result {
+ self.to_string().to_cstr()
+ }
+}
+
/// Type Archives are a collection of types which can be shared between different analysis
/// sessions and are backed by a database file on disk. Their types can be modified, and
/// a history of previous versions of types is stored in snapshots in the archive.
diff --git a/rust/src/type_container.rs b/rust/src/types/container.rs
index e8c915df..5096ac78 100644
--- a/rust/src/type_container.rs
+++ b/rust/src/types/container.rs
@@ -12,8 +12,7 @@ use crate::platform::Platform;
use crate::progress::{NoProgressCallback, ProgressCallback};
use crate::rc::{Array, Ref};
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_parser::{TypeParserError, TypeParserResult};
-use crate::types::{QualifiedName, QualifiedNameAndType, Type};
+use crate::types::{QualifiedName, QualifiedNameAndType, Type, TypeParserError, TypeParserResult};
use binaryninjacore_sys::*;
use std::collections::HashMap;
use std::ffi::{c_char, c_void};
diff --git a/rust/src/types/enumeration.rs b/rust/src/types/enumeration.rs
new file mode 100644
index 00000000..70c266e1
--- /dev/null
+++ b/rust/src/types/enumeration.rs
@@ -0,0 +1,201 @@
+use crate::rc::{Ref, RefCountable};
+use crate::string::{raw_to_string, BnString, IntoCStr};
+use binaryninjacore_sys::*;
+use std::fmt::{Debug, Formatter};
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct EnumerationBuilder {
+ pub(crate) handle: *mut BNEnumerationBuilder,
+}
+
+impl EnumerationBuilder {
+ pub fn new() -> Self {
+ Self {
+ handle: unsafe { BNCreateEnumerationBuilder() },
+ }
+ }
+
+ pub(crate) unsafe fn from_raw(handle: *mut BNEnumerationBuilder) -> Self {
+ Self { handle }
+ }
+
+ pub fn finalize(&self) -> Ref<Enumeration> {
+ unsafe { Enumeration::ref_from_raw(BNFinalizeEnumerationBuilder(self.handle)) }
+ }
+
+ pub fn append(&mut self, name: &str) -> &mut Self {
+ let name = name.to_cstr();
+ unsafe {
+ BNAddEnumerationBuilderMember(self.handle, name.as_ref().as_ptr() as _);
+ }
+ self
+ }
+
+ pub fn insert(&mut self, name: &str, value: u64) -> &mut Self {
+ let name = name.to_cstr();
+ unsafe {
+ BNAddEnumerationBuilderMemberWithValue(self.handle, name.as_ref().as_ptr() as _, value);
+ }
+ self
+ }
+
+ pub fn replace(&mut self, id: usize, name: &str, value: u64) -> &mut Self {
+ let name = name.to_cstr();
+ unsafe {
+ BNReplaceEnumerationBuilderMember(self.handle, id, name.as_ref().as_ptr() as _, value);
+ }
+ self
+ }
+
+ pub fn remove(&mut self, id: usize) -> &mut Self {
+ unsafe {
+ BNRemoveEnumerationBuilderMember(self.handle, id);
+ }
+
+ self
+ }
+
+ pub fn members(&self) -> Vec<EnumerationMember> {
+ unsafe {
+ let mut count = 0;
+ let members_raw_ptr = BNGetEnumerationBuilderMembers(self.handle, &mut count);
+ let members_raw: &[BNEnumerationMember] =
+ std::slice::from_raw_parts(members_raw_ptr, count);
+ let members = members_raw
+ .iter()
+ .map(EnumerationMember::from_raw)
+ .collect();
+ BNFreeEnumerationMemberList(members_raw_ptr, count);
+ members
+ }
+ }
+}
+
+impl Default for EnumerationBuilder {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl From<&Enumeration> for EnumerationBuilder {
+ fn from(enumeration: &Enumeration) -> Self {
+ unsafe {
+ Self::from_raw(BNCreateEnumerationBuilderFromEnumeration(
+ enumeration.handle,
+ ))
+ }
+ }
+}
+
+impl Drop for EnumerationBuilder {
+ fn drop(&mut self) {
+ unsafe { BNFreeEnumerationBuilder(self.handle) };
+ }
+}
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct Enumeration {
+ pub(crate) handle: *mut BNEnumeration,
+}
+
+impl Enumeration {
+ pub(crate) unsafe fn ref_from_raw(handle: *mut BNEnumeration) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
+ Ref::new(Self { handle })
+ }
+
+ pub fn builder() -> EnumerationBuilder {
+ EnumerationBuilder::new()
+ }
+
+ pub fn members(&self) -> Vec<EnumerationMember> {
+ unsafe {
+ let mut count = 0;
+ let members_raw_ptr = BNGetEnumerationMembers(self.handle, &mut count);
+ debug_assert!(!members_raw_ptr.is_null());
+ let members_raw: &[BNEnumerationMember] =
+ std::slice::from_raw_parts(members_raw_ptr, count);
+ let members = members_raw
+ .iter()
+ .map(EnumerationMember::from_raw)
+ .collect();
+ BNFreeEnumerationMemberList(members_raw_ptr, count);
+ members
+ }
+ }
+}
+
+impl Debug for Enumeration {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Enumeration")
+ .field("members", &self.members())
+ .finish()
+ }
+}
+
+unsafe impl RefCountable for Enumeration {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Self::ref_from_raw(BNNewEnumerationReference(handle.handle))
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeEnumeration(handle.handle);
+ }
+}
+
+impl ToOwned for Enumeration {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct EnumerationMember {
+ pub name: String,
+ /// The associated constant value for the member.
+ pub value: u64,
+ /// Whether this is the default member for the associated [`Enumeration`].
+ pub default: bool,
+}
+
+impl EnumerationMember {
+ pub(crate) fn from_raw(value: &BNEnumerationMember) -> Self {
+ Self {
+ name: raw_to_string(value.name).unwrap(),
+ value: value.value,
+ default: value.isDefault,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn from_owned_raw(value: BNEnumerationMember) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ #[allow(unused)]
+ pub(crate) fn into_raw(value: Self) -> BNEnumerationMember {
+ let bn_name = BnString::new(value.name);
+ BNEnumerationMember {
+ name: BnString::into_raw(bn_name),
+ value: value.value,
+ isDefault: value.default,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn free_raw(value: BNEnumerationMember) {
+ unsafe { BnString::free_raw(value.name) };
+ }
+
+ pub fn new(name: String, value: u64, default: bool) -> Self {
+ Self {
+ name,
+ value,
+ default,
+ }
+ }
+}
diff --git a/rust/src/type_library.rs b/rust/src/types/library.rs
index 89f5e48f..89f5e48f 100644
--- a/rust/src/type_library.rs
+++ b/rust/src/types/library.rs
diff --git a/rust/src/type_parser.rs b/rust/src/types/parser.rs
index 8ad0725f..1ee07188 100644
--- a/rust/src/type_parser.rs
+++ b/rust/src/types/parser.rs
@@ -7,8 +7,7 @@ use std::ptr::NonNull;
use crate::platform::Platform;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_container::TypeContainer;
-use crate::types::{QualifiedName, QualifiedNameAndType, Type};
+use crate::types::{QualifiedName, QualifiedNameAndType, Type, TypeContainer};
pub type TypeParserErrorSeverity = BNTypeParserErrorSeverity;
pub type TypeParserOption = BNTypeParserOption;
diff --git a/rust/src/type_printer.rs b/rust/src/types/printer.rs
index a7495f1c..d168434e 100644
--- a/rust/src/type_printer.rs
+++ b/rust/src/types/printer.rs
@@ -5,8 +5,7 @@ use crate::disassembly::InstructionTextToken;
use crate::platform::Platform;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
use crate::string::{raw_to_string, BnString, IntoCStr};
-use crate::type_container::TypeContainer;
-use crate::types::{NamedTypeReference, QualifiedName, QualifiedNameAndType, Type};
+use crate::types::{NamedTypeReference, QualifiedName, QualifiedNameAndType, Type, TypeContainer};
use binaryninjacore_sys::*;
use std::ffi::{c_char, c_int, c_void};
use std::ptr::NonNull;
diff --git a/rust/src/types/structure.rs b/rust/src/types/structure.rs
new file mode 100644
index 00000000..7de466a4
--- /dev/null
+++ b/rust/src/types/structure.rs
@@ -0,0 +1,696 @@
+use crate::confidence::Conf;
+use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable};
+use crate::string::{raw_to_string, BnString, IntoCStr};
+use crate::types::{
+ MemberAccess, MemberScope, NamedTypeReference, StructureType, Type, TypeContainer,
+};
+use binaryninjacore_sys::*;
+use std::fmt::{Debug, Formatter};
+
+// Needed for doc comments
+#[allow(unused)]
+use crate::binary_view::BinaryViewExt;
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct StructureBuilder {
+ pub(crate) handle: *mut BNStructureBuilder,
+}
+
+/// ```no_run
+/// // Includes
+/// # use binaryninja::binary_view::BinaryViewExt;
+/// use binaryninja::types::{MemberAccess, MemberScope, Structure, StructureBuilder, Type};
+///
+/// // Types to use in the members
+/// let field_1_ty = Type::named_int(5, false, "my_weird_int_type");
+/// let field_2_ty = Type::int(4, false);
+/// let field_3_ty = Type::int(8, false);
+///
+/// // Assign those fields
+/// let mut my_custom_struct = StructureBuilder::new();
+/// my_custom_struct
+/// .insert(
+/// &field_1_ty,
+/// "field_1",
+/// 0,
+/// false,
+/// MemberAccess::PublicAccess,
+/// MemberScope::NoScope,
+/// )
+/// .insert(
+/// &field_2_ty,
+/// "field_2",
+/// 5,
+/// false,
+/// MemberAccess::PublicAccess,
+/// MemberScope::NoScope,
+/// )
+/// .insert(
+/// &field_3_ty,
+/// "field_3",
+/// 9,
+/// false,
+/// MemberAccess::PublicAccess,
+/// MemberScope::NoScope,
+/// )
+/// .append(
+/// &field_1_ty,
+/// "field_4",
+/// MemberAccess::PublicAccess,
+/// MemberScope::NoScope,
+/// );
+///
+/// // Convert structure to type
+/// let my_custom_structure_type = Type::structure(&my_custom_struct.finalize());
+///
+/// // Add the struct to the binary view to use in analysis
+/// let bv = binaryninja::load("example").unwrap();
+/// bv.define_user_type("my_custom_struct", &my_custom_structure_type);
+/// ```
+impl StructureBuilder {
+ pub fn new() -> Self {
+ Self {
+ handle: unsafe { BNCreateStructureBuilder() },
+ }
+ }
+
+ pub(crate) unsafe fn from_raw(handle: *mut BNStructureBuilder) -> Self {
+ debug_assert!(!handle.is_null());
+ Self { handle }
+ }
+
+ // TODO: Document the width adjustment with alignment.
+ pub fn finalize(&self) -> Ref<Structure> {
+ let raw_struct_ptr = unsafe { BNFinalizeStructureBuilder(self.handle) };
+ unsafe { Structure::ref_from_raw(raw_struct_ptr) }
+ }
+
+ /// Sets the width of the [`StructureBuilder`] to the new width.
+ ///
+ /// This will remove all previously inserted members outside the new width. This is done by computing
+ /// the member access range (member offset + member width) and if it is larger than the new width
+ /// it will be removed.
+ pub fn width(&mut self, width: u64) -> &mut Self {
+ unsafe {
+ BNSetStructureBuilderWidth(self.handle, width);
+ }
+ self
+ }
+
+ pub fn alignment(&mut self, alignment: usize) -> &mut Self {
+ unsafe {
+ BNSetStructureBuilderAlignment(self.handle, alignment);
+ }
+ self
+ }
+
+ /// Sets whether the [`StructureBuilder`] is packed.
+ ///
+ /// If set the alignment of the structure will be `1`. You do not need to set the alignment to `1`.
+ pub fn packed(&mut self, packed: bool) -> &mut Self {
+ unsafe {
+ BNSetStructureBuilderPacked(self.handle, packed);
+ }
+ self
+ }
+
+ pub fn structure_type(&mut self, t: StructureType) -> &mut Self {
+ unsafe { BNSetStructureBuilderType(self.handle, t) };
+ self
+ }
+
+ pub fn pointer_offset(&mut self, offset: i64) -> &mut Self {
+ unsafe { BNSetStructureBuilderPointerOffset(self.handle, offset) };
+ self
+ }
+
+ pub fn propagates_data_var_refs(&mut self, propagates: bool) -> &mut Self {
+ unsafe { BNSetStructureBuilderPropagatesDataVariableReferences(self.handle, propagates) };
+ self
+ }
+
+ pub fn base_structures(&mut self, bases: &[BaseStructure]) -> &mut Self {
+ let raw_base_structs: Vec<BNBaseStructure> =
+ bases.iter().map(BaseStructure::into_owned_raw).collect();
+ unsafe {
+ BNSetBaseStructuresForStructureBuilder(
+ self.handle,
+ raw_base_structs.as_ptr() as *mut _,
+ raw_base_structs.len(),
+ )
+ };
+ self
+ }
+
+ /// Append a member at the next available byte offset.
+ ///
+ /// Otherwise, consider using:
+ ///
+ /// - [`StructureBuilder::insert_member`]
+ /// - [`StructureBuilder::insert`]
+ /// - [`StructureBuilder::insert_bitwise`]
+ pub fn append<'a, T: Into<Conf<&'a Type>>>(
+ &mut self,
+ ty: T,
+ name: &str,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> &mut Self {
+ let name = name.to_cstr();
+ let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
+ unsafe {
+ BNAddStructureBuilderMember(
+ self.handle,
+ &owned_raw_ty,
+ name.as_ref().as_ptr() as _,
+ access,
+ scope,
+ );
+ }
+ self
+ }
+
+ /// Insert an already constructed [`StructureMember`].
+ ///
+ /// Otherwise, consider using:
+ ///
+ /// - [`StructureBuilder::append`]
+ /// - [`StructureBuilder::insert`]
+ /// - [`StructureBuilder::insert_bitwise`]
+ pub fn insert_member(
+ &mut self,
+ member: StructureMember,
+ overwrite_existing: bool,
+ ) -> &mut Self {
+ self.insert_bitwise(
+ &member.ty,
+ &member.name,
+ member.bit_offset(),
+ member.bit_width,
+ overwrite_existing,
+ member.access,
+ member.scope,
+ );
+ self
+ }
+
+ /// Inserts a member at the `offset` (in bytes).
+ ///
+ /// If you need to insert a member at a specific bit within a given byte (like a bitfield), you
+ /// can use [`StructureBuilder::insert_bitwise`].
+ pub fn insert<'a, T: Into<Conf<&'a Type>>>(
+ &mut self,
+ ty: T,
+ name: &str,
+ offset: u64,
+ overwrite_existing: bool,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> &mut Self {
+ self.insert_bitwise(
+ ty,
+ name,
+ offset * 8,
+ None,
+ overwrite_existing,
+ access,
+ scope,
+ )
+ }
+
+ /// Inserts a member at `bit_offset` with an optional `bit_width`.
+ ///
+ /// NOTE: The `bit_offset` is relative to the start of the structure, for example, passing `8` will place
+ /// the field at the start of the byte `0x1`.
+ pub fn insert_bitwise<'a, T: Into<Conf<&'a Type>>>(
+ &mut self,
+ ty: T,
+ name: &str,
+ bit_offset: u64,
+ bit_width: Option<u8>,
+ overwrite_existing: bool,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> &mut Self {
+ let name = name.to_cstr();
+ let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
+ let byte_offset = bit_offset / 8;
+ let bit_position = bit_offset % 8;
+ unsafe {
+ BNAddStructureBuilderMemberAtOffset(
+ self.handle,
+ &owned_raw_ty,
+ name.as_ref().as_ptr() as _,
+ byte_offset,
+ overwrite_existing,
+ access,
+ scope,
+ bit_position as u8,
+ bit_width.unwrap_or(0),
+ );
+ }
+ self
+ }
+
+ pub fn replace<'a, T: Into<Conf<&'a Type>>>(
+ &mut self,
+ index: usize,
+ ty: T,
+ name: &str,
+ overwrite_existing: bool,
+ ) -> &mut Self {
+ let name = name.to_cstr();
+ let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
+ unsafe {
+ BNReplaceStructureBuilderMember(
+ self.handle,
+ index,
+ &owned_raw_ty,
+ name.as_ref().as_ptr() as _,
+ overwrite_existing,
+ )
+ }
+ self
+ }
+
+ /// Removes the member at a given index.
+ pub fn remove(&mut self, index: usize) -> &mut Self {
+ unsafe { BNRemoveStructureBuilderMember(self.handle, index) };
+ self
+ }
+
+ // TODO: We should add BNGetStructureBuilderAlignedWidth
+ /// Gets the current **unaligned** width of the structure.
+ ///
+ /// This cannot be used to accurately get the width of a non-packed structure.
+ pub fn current_width(&self) -> u64 {
+ unsafe { BNGetStructureBuilderWidth(self.handle) }
+ }
+}
+
+impl From<&Structure> for StructureBuilder {
+ fn from(structure: &Structure) -> StructureBuilder {
+ unsafe { Self::from_raw(BNCreateStructureBuilderFromStructure(structure.handle)) }
+ }
+}
+
+impl From<Vec<StructureMember>> for StructureBuilder {
+ fn from(members: Vec<StructureMember>) -> StructureBuilder {
+ let mut builder = StructureBuilder::new();
+ for member in members {
+ builder.insert_member(member, false);
+ }
+ builder
+ }
+}
+
+impl Drop for StructureBuilder {
+ fn drop(&mut self) {
+ unsafe { BNFreeStructureBuilder(self.handle) };
+ }
+}
+
+impl Default for StructureBuilder {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct Structure {
+ pub(crate) handle: *mut BNStructure,
+}
+
+impl Structure {
+ pub(crate) unsafe fn ref_from_raw(handle: *mut BNStructure) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
+ Ref::new(Self { handle })
+ }
+
+ pub fn builder() -> StructureBuilder {
+ StructureBuilder::new()
+ }
+
+ pub fn width(&self) -> u64 {
+ unsafe { BNGetStructureWidth(self.handle) }
+ }
+
+ pub fn structure_type(&self) -> StructureType {
+ unsafe { BNGetStructureType(self.handle) }
+ }
+
+ /// Retrieve the members that are accessible at a given offset.
+ ///
+ /// The reason for this being plural is that members may overlap and the offset is in bytes
+ /// where a bitfield may contain multiple members at the given byte.
+ ///
+ /// Unions are also represented as structures and will cause this function to return
+ /// **all** members that can reach that offset.
+ ///
+ /// We must pass a [`TypeContainer`] here so that we can resolve base structure members, as they
+ /// are treated as members through this function. Typically, you get the [`TypeContainer`]
+ /// through the binary view with [`BinaryViewExt::type_container`].
+ pub fn members_at_offset(
+ &self,
+ container: &TypeContainer,
+ offset: u64,
+ ) -> Vec<StructureMember> {
+ self.members_including_inherited(container)
+ .into_iter()
+ .filter(|m| m.member.is_offset_valid(offset))
+ .map(|m| m.member)
+ .collect()
+ }
+
+ /// Return the list of non-inherited structure members.
+ ///
+ /// If you want to get all members, including ones inherited from base structures,
+ /// use [`Structure::members_including_inherited`] instead.
+ pub fn members(&self) -> Vec<StructureMember> {
+ unsafe {
+ let mut count = 0;
+ let members_raw_ptr: *mut BNStructureMember =
+ BNGetStructureMembers(self.handle, &mut count);
+ debug_assert!(!members_raw_ptr.is_null());
+ let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
+ let members = members_raw.iter().map(StructureMember::from_raw).collect();
+ BNFreeStructureMemberList(members_raw_ptr, count);
+ members
+ }
+ }
+
+ /// Returns the list of all structure members, including inherited ones.
+ ///
+ /// Because we must traverse through base structures, we have to provide the [`TypeContainer`];
+ /// in most cases it is ok to provide the binary views container via [`BinaryViewExt::type_container`].
+ pub fn members_including_inherited(
+ &self,
+ container: &TypeContainer,
+ ) -> Vec<InheritedStructureMember> {
+ unsafe {
+ let mut count = 0;
+ let members_raw_ptr: *mut BNInheritedStructureMember =
+ BNGetStructureMembersIncludingInherited(
+ self.handle,
+ container.handle.as_ptr(),
+ &mut count,
+ );
+ debug_assert!(!members_raw_ptr.is_null());
+ let members_raw = std::slice::from_raw_parts(members_raw_ptr, count);
+ let members = members_raw
+ .iter()
+ .map(InheritedStructureMember::from_raw)
+ .collect();
+ BNFreeInheritedStructureMemberList(members_raw_ptr, count);
+ members
+ }
+ }
+
+ /// Retrieve the list of base structures for the structure. These base structures are what give
+ /// a structure inherited members.
+ pub fn base_structures(&self) -> Vec<BaseStructure> {
+ let mut count = 0;
+ let bases_raw_ptr = unsafe { BNGetBaseStructuresForStructure(self.handle, &mut count) };
+ debug_assert!(!bases_raw_ptr.is_null());
+ let bases_raw = unsafe { std::slice::from_raw_parts(bases_raw_ptr, count) };
+ let bases = bases_raw.iter().map(BaseStructure::from_raw).collect();
+ unsafe { BNFreeBaseStructureList(bases_raw_ptr, count) };
+ bases
+ }
+
+ /// Whether the structure is packed or not.
+ pub fn is_packed(&self) -> bool {
+ unsafe { BNIsStructurePacked(self.handle) }
+ }
+
+ pub fn alignment(&self) -> usize {
+ unsafe { BNGetStructureAlignment(self.handle) }
+ }
+}
+
+impl Debug for Structure {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Structure")
+ .field("width", &self.width())
+ .field("alignment", &self.alignment())
+ .field("packed", &self.is_packed())
+ .field("structure_type", &self.structure_type())
+ .field("base_structures", &self.base_structures())
+ .field("members", &self.members())
+ .finish()
+ }
+}
+
+unsafe impl RefCountable for Structure {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Self::ref_from_raw(BNNewStructureReference(handle.handle))
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeStructure(handle.handle);
+ }
+}
+
+impl ToOwned for Structure {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct StructureMember {
+ pub ty: Conf<Ref<Type>>,
+ // TODO: Shouldnt this be a QualifiedName? The ffi says no...
+ pub name: String,
+ /// The byte offset of the member.
+ pub offset: u64,
+ pub access: MemberAccess,
+ pub scope: MemberScope,
+ /// The bit position relative to the byte offset.
+ pub bit_position: Option<u8>,
+ pub bit_width: Option<u8>,
+}
+
+impl StructureMember {
+ pub(crate) fn from_raw(value: &BNStructureMember) -> Self {
+ Self {
+ ty: Conf::new(
+ unsafe { Type::from_raw(value.type_) }.to_owned(),
+ value.typeConfidence,
+ ),
+ // TODO: I dislike using this function here.
+ name: raw_to_string(value.name as *mut _).unwrap(),
+ offset: value.offset,
+ access: value.access,
+ scope: value.scope,
+ bit_position: match value.bitPosition {
+ 0 => None,
+ _ => Some(value.bitPosition),
+ },
+ bit_width: match value.bitWidth {
+ 0 => None,
+ _ => Some(value.bitWidth),
+ },
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn from_owned_raw(value: BNStructureMember) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ #[allow(unused)]
+ pub(crate) fn into_raw(value: Self) -> BNStructureMember {
+ let bn_name = BnString::new(value.name);
+ BNStructureMember {
+ type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
+ name: BnString::into_raw(bn_name),
+ offset: value.offset,
+ typeConfidence: value.ty.confidence,
+ access: value.access,
+ scope: value.scope,
+ bitPosition: value.bit_position.unwrap_or(0),
+ bitWidth: value.bit_width.unwrap_or(0),
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn free_raw(value: BNStructureMember) {
+ let _ = unsafe { Type::ref_from_raw(value.type_) };
+ unsafe { BnString::free_raw(value.name) };
+ }
+
+ pub fn new(
+ ty: Conf<Ref<Type>>,
+ name: String,
+ offset: u64,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> Self {
+ Self {
+ ty,
+ name,
+ offset,
+ access,
+ scope,
+ bit_position: None,
+ bit_width: None,
+ }
+ }
+
+ pub fn new_bitfield(
+ ty: Conf<Ref<Type>>,
+ name: String,
+ bit_offset: u64,
+ bit_width: u8,
+ access: MemberAccess,
+ scope: MemberScope,
+ ) -> Self {
+ Self {
+ ty,
+ name,
+ offset: bit_offset / 8,
+ access,
+ scope,
+ bit_position: Some((bit_offset % 8) as u8),
+ bit_width: Some(bit_width),
+ }
+ }
+
+ // TODO: Do we count bitwidth here?
+ /// Whether the offset within the accessible range of the member.
+ pub fn is_offset_valid(&self, offset: u64) -> bool {
+ self.offset <= offset && offset < self.offset + self.ty.contents.width()
+ }
+
+ /// Member offset in bits.
+ pub fn bit_offset(&self) -> u64 {
+ (self.offset * 8) + self.bit_position.unwrap_or(0) as u64
+ }
+}
+
+impl CoreArrayProvider for StructureMember {
+ type Raw = BNStructureMember;
+ type Context = ();
+ type Wrapped<'a> = Self;
+}
+
+unsafe impl CoreArrayProviderInner for StructureMember {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNFreeStructureMemberList(raw, count)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::from_raw(raw)
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct InheritedStructureMember {
+ pub base: Ref<NamedTypeReference>,
+ pub base_offset: u64,
+ pub member: StructureMember,
+ pub member_index: usize,
+}
+
+impl InheritedStructureMember {
+ pub(crate) fn from_raw(value: &BNInheritedStructureMember) -> Self {
+ Self {
+ base: unsafe { NamedTypeReference::from_raw(value.base) }.to_owned(),
+ base_offset: value.baseOffset,
+ member: StructureMember::from_raw(&value.member),
+ member_index: value.memberIndex,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn from_owned_raw(value: BNInheritedStructureMember) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ #[allow(unused)]
+ pub(crate) fn into_raw(value: Self) -> BNInheritedStructureMember {
+ BNInheritedStructureMember {
+ base: unsafe { Ref::into_raw(value.base) }.handle,
+ baseOffset: value.base_offset,
+ member: StructureMember::into_raw(value.member),
+ memberIndex: value.member_index,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn free_raw(value: BNInheritedStructureMember) {
+ let _ = unsafe { NamedTypeReference::ref_from_raw(value.base) };
+ StructureMember::free_raw(value.member);
+ }
+
+ pub fn new(
+ base: Ref<NamedTypeReference>,
+ base_offset: u64,
+ member: StructureMember,
+ member_index: usize,
+ ) -> Self {
+ Self {
+ base,
+ base_offset,
+ member,
+ member_index,
+ }
+ }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct BaseStructure {
+ pub ty: Ref<NamedTypeReference>,
+ pub offset: u64,
+ pub width: u64,
+}
+
+impl BaseStructure {
+ pub(crate) fn from_raw(value: &BNBaseStructure) -> Self {
+ Self {
+ ty: unsafe { NamedTypeReference::from_raw(value.type_) }.to_owned(),
+ offset: value.offset,
+ width: value.width,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn from_owned_raw(value: BNBaseStructure) -> Self {
+ let owned = Self::from_raw(&value);
+ Self::free_raw(value);
+ owned
+ }
+
+ #[allow(unused)]
+ pub(crate) fn into_raw(value: Self) -> BNBaseStructure {
+ BNBaseStructure {
+ type_: unsafe { Ref::into_raw(value.ty) }.handle,
+ offset: value.offset,
+ width: value.width,
+ }
+ }
+
+ pub(crate) fn into_owned_raw(value: &Self) -> BNBaseStructure {
+ BNBaseStructure {
+ type_: value.ty.handle,
+ offset: value.offset,
+ width: value.width,
+ }
+ }
+
+ #[allow(unused)]
+ pub(crate) fn free_raw(value: BNBaseStructure) {
+ let _ = unsafe { NamedTypeReference::ref_from_raw(value.type_) };
+ }
+
+ pub fn new(ty: Ref<NamedTypeReference>, offset: u64, width: u64) -> Self {
+ Self { ty, offset, width }
+ }
+}
diff --git a/rust/tests/type_archive.rs b/rust/tests/type_archive.rs
index 12fcec9d..3e13507e 100644
--- a/rust/tests/type_archive.rs
+++ b/rust/tests/type_archive.rs
@@ -1,7 +1,6 @@
use binaryninja::headless::Session;
use binaryninja::platform::Platform;
-use binaryninja::type_archive::TypeArchive;
-use binaryninja::types::{Type, TypeClass};
+use binaryninja::types::{Type, TypeArchive, TypeClass};
#[test]
fn test_create_archive() {
diff --git a/rust/tests/type_library.rs b/rust/tests/type_library.rs
index 83937386..b8a12870 100644
--- a/rust/tests/type_library.rs
+++ b/rust/tests/type_library.rs
@@ -1,8 +1,7 @@
use binaryninja::binary_view::BinaryViewExt;
use binaryninja::headless::Session;
use binaryninja::platform::Platform;
-use binaryninja::type_library::TypeLibrary;
-use binaryninja::types::{Type, TypeClass};
+use binaryninja::types::{Type, TypeClass, TypeLibrary};
use std::path::PathBuf;
#[test]
diff --git a/rust/tests/type_parser.rs b/rust/tests/type_parser.rs
index d08e7791..64771404 100644
--- a/rust/tests/type_parser.rs
+++ b/rust/tests/type_parser.rs
@@ -1,7 +1,6 @@
use binaryninja::headless::Session;
use binaryninja::platform::Platform;
-use binaryninja::type_parser::{CoreTypeParser, TypeParser, TypeParserError};
-use binaryninja::types::Type;
+use binaryninja::types::{CoreTypeParser, Type, TypeParser, TypeParserError};
use binaryninjacore_sys::BNTypeParserErrorSeverity::ErrorSeverity;
const TEST_TYPES: &str = r#"
diff --git a/rust/tests/type_printer.rs b/rust/tests/type_printer.rs
index 4ff67232..67035376 100644
--- a/rust/tests/type_printer.rs
+++ b/rust/tests/type_printer.rs
@@ -3,12 +3,10 @@ use binaryninja::disassembly::InstructionTextToken;
use binaryninja::headless::Session;
use binaryninja::platform::Platform;
use binaryninja::rc::Ref;
-use binaryninja::type_container::TypeContainer;
-use binaryninja::type_printer::{
- register_type_printer, CoreTypePrinter, TokenEscapingType, TypeDefinitionLine, TypePrinter,
-};
+use binaryninja::types::printer::{register_type_printer, TokenEscapingType, TypeDefinitionLine};
use binaryninja::types::{
- MemberAccess, MemberScope, QualifiedName, Structure, StructureMember, Type,
+ CoreTypePrinter, MemberAccess, MemberScope, QualifiedName, Structure, StructureMember, Type,
+ TypeContainer, TypePrinter,
};
use std::path::PathBuf;