diff options
| author | Mason Reed <mason@vector35.com> | 2025-09-21 21:51:37 -0400 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-10-23 14:29:15 -0400 |
| commit | c35849163319ee606a28eb4d8bfd585b1f4eddcf (patch) | |
| tree | b6e2269effe50de773aecf71fca3f71801067ead /plugins/svd | |
| parent | 24e66649863d724aa532ff884c6f27c141a0eede (diff) | |
Support bitfields in type system
Also adds support for parsing bitfields in PDB, DWARF and SVD plugins
WIP: API needs to be considered more, also need to find type related apis that may need to be rethought.
Diffstat (limited to 'plugins/svd')
| -rw-r--r-- | plugins/svd/src/mapper.rs | 79 |
1 files changed, 4 insertions, 75 deletions
diff --git a/plugins/svd/src/mapper.rs b/plugins/svd/src/mapper.rs index 8846c858..4c49145b 100644 --- a/plugins/svd/src/mapper.rs +++ b/plugins/svd/src/mapper.rs @@ -8,7 +8,7 @@ use binaryninja::segment::{SegmentBuilder, SegmentFlags}; use binaryninja::symbol::{SymbolBuilder, SymbolType}; use binaryninja::types::{ BaseStructure, EnumerationBuilder, MemberAccess, MemberScope, NamedTypeReference, - NamedTypeReferenceClass, StructureBuilder, StructureMember, StructureType, Type, TypeBuilder, + NamedTypeReferenceClass, StructureBuilder, StructureMember, Type, TypeBuilder, }; use std::collections::HashMap; use std::num::NonZeroUsize; @@ -442,53 +442,12 @@ impl DeviceMapper { let type_builder = match ®ister.fields { Some(fields) => { - // Separate bitfields from regular fields. - let (fields, bitfield_items): (Vec<_>, Vec<_>) = - fields.iter().partition(|f| { - byte_aligned(f.bit_range.width) && byte_aligned(f.bit_range.offset) - }); - for field in fields { let field_member = self.field_member(field); let overwrites = true; // TODO: Handle overwrites? register_struct.insert_member(field_member, overwrites); } - if self.settings.add_bitfields { - // The bitfield items need to be coalesced to a map of byte offset to vec of fields. - let mut bitfield_map: HashMap<u64, Vec<&Field>> = HashMap::new(); - - // Sort bitfields by their offset - let mut sorted_bitfields = bitfield_items.iter().collect::<Vec<_>>(); - sorted_bitfields.sort_by_key(|f| f.bit_range.offset); - - // Group bitfields by overlapping bit offsets - let mut current_bit_start = 0; - let mut current_bit_end = 0; - for field in sorted_bitfields { - let bit_start = field.bit_range.offset; - let byte_start = bit_start / 8; - let current_byte_start = current_bit_start / 8; - if current_byte_start != byte_start && current_bit_end < bit_start { - // Make a new bitfield, only if the current field is in a new byte. - current_bit_start = bit_start; - } - current_bit_end = bit_start + field.bit_range.width; - bitfield_map - .entry(current_bit_start as u64) - .or_insert_with(Vec::new) - .push(field); - } - - for (bit_start, fields) in bitfield_map { - // Add each bitfield to the structure! - let byte_start = bit_start / 8; - let bitfield_member = self.bitfield_member(byte_start, fields); - let overwrites = true; // TODO: Handle overwrites? - register_struct.insert_member(bitfield_member, overwrites); - } - } - TypeBuilder::structure(®ister_struct.finalize()) } None if register.derived_from.is_some() => { @@ -559,43 +518,14 @@ impl DeviceMapper { } } - pub fn bitfield_member(&self, byte_offset: u64, fields: Vec<&Field>) -> StructureMember { - let field_ty = self.bitfield_type(byte_offset, fields); - // TODO: Create bitfield name from the fields? - let field_name = format!("bitfield_0x{:x}", byte_offset); - // TODO: This should be like 120 confidence? - let conf_field_ty = Conf::new(field_ty, MAX_CONFIDENCE); - StructureMember::new( - conf_field_ty, - field_name, - byte_offset, - MemberAccess::PublicAccess, - MemberScope::NoScope, - ) - } - - pub fn bitfield_type(&self, byte_offset: u64, fields: Vec<&Field>) -> Ref<Type> { - let mut union_builder = StructureBuilder::new(); - union_builder.structure_type(StructureType::UnionStructureType); - for field in fields { - let mut field_member = self.field_member(field); - // Field members are relative to the union member, so we must remove the union member offset - // from the field member offset to make it relative to the union member. - field_member.offset -= byte_offset; - let overwrites = false; // TODO: Handle overwrites? - union_builder.insert_member(field_member, overwrites); - } - Type::structure(&union_builder.finalize()) - } - pub fn field_member(&self, field: &Field) -> StructureMember { let field_ty = self.field_type(field); let conf_field_ty = Conf::new(field_ty, MAX_CONFIDENCE); - let byte_offset = field.bit_offset() / 8; - StructureMember::new( + StructureMember::new_bitfield( conf_field_ty, field.name.to_owned(), - byte_offset as u64, + field.bit_offset() as u64, + field.bit_width() as u8, MemberAccess::PublicAccess, MemberScope::NoScope, ) @@ -633,7 +563,6 @@ impl DeviceMapper { } pub fn single_field_int_type(&self, field: &FieldInfo) -> Ref<Type> { - // TODO: Binary Ninja is unable to handle bit fields, so we abuse unions. // Get the closest 8-bit aligned integer and use that. let width = field.bit_width(); let byte_aligned_width = byte_width(width); |
