diff options
| author | Mason Reed <mason@vector35.com> | 2024-11-11 14:27:21 -0500 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2024-11-11 14:31:53 -0500 |
| commit | 7df5aa809b78c2ed3abc9f6bc3dae9e34b809d32 (patch) | |
| tree | 610876597bf9b9f5cc2fb6027758c7cdc2ab4ea1 /plugins/warp/src/convert.rs | |
| parent | d7a35743ae442e5ae3cc4f98aff78fb04d81b337 (diff) | |
WARP: Cache type references in the view caches
This allows us to free the type references instead of keeping them around forever
Diffstat (limited to 'plugins/warp/src/convert.rs')
| -rw-r--r-- | plugins/warp/src/convert.rs | 37 |
1 files changed, 11 insertions, 26 deletions
diff --git a/plugins/warp/src/convert.rs b/plugins/warp/src/convert.rs index c425bdfe..6f2bf7e3 100644 --- a/plugins/warp/src/convert.rs +++ b/plugins/warp/src/convert.rs @@ -17,6 +17,7 @@ use binaryninja::types::{ StructureType as BNStructureType, Type as BNType, TypeClass as BNTypeClass, }; +use crate::cache::{cached_type_reference, TypeRefID}; use warp::r#type::class::array::ArrayModifiers; use warp::r#type::class::function::{Location, RegisterLocation}; use warp::r#type::class::pointer::PointerAddressing; @@ -26,7 +27,6 @@ use warp::r#type::class::{ EnumerationMember, FloatClass, FunctionClass, FunctionMember, IntegerClass, PointerClass, ReferrerClass, StructureClass, StructureMember, TypeClass, }; -use warp::r#type::guid::TypeGUID; use warp::r#type::Type; use warp::symbol::class::SymbolClass; use warp::symbol::{Symbol, SymbolModifiers}; @@ -121,9 +121,9 @@ pub fn from_bn_type(view: &BinaryView, raw_ty: &BNType, confidence: u8) -> Type from_bn_type_internal(view, &mut HashSet::new(), raw_ty, confidence) } -fn from_bn_type_internal( +pub fn from_bn_type_internal( view: &BinaryView, - visited_refs: &mut HashSet<String>, + visited_refs: &mut HashSet<TypeRefID>, raw_ty: &BNType, confidence: u8, ) -> Type { @@ -318,32 +318,17 @@ fn from_bn_type_internal( } BNTypeClass::NamedTypeReferenceClass => { let raw_ntr = raw_ty.get_named_type_reference().unwrap(); - let ref_id_str = raw_ntr.id().to_string(); - let raw_ntr_ty = raw_ntr.target(view); - if raw_ntr_ty.is_none() || !visited_refs.insert(ref_id_str.clone()) { - let ref_class = ReferrerClass::new(None, Some(raw_ntr.name().to_string())); - TypeClass::Referrer(ref_class) - } else { - use dashmap::DashMap; - use std::sync::Arc; - use std::sync::OnceLock; - static REF_CACHE: OnceLock<Arc<DashMap<String, TypeClass>>> = OnceLock::new(); - let ref_cache = REF_CACHE.get_or_init(|| Arc::new(DashMap::new())); - // Check the cache first before proceeding - if let Some(cached_type) = ref_cache.get(&ref_id_str) { - cached_type.value().to_owned() - } else { - let ntr_ty = - from_bn_type_internal(view, visited_refs, &raw_ntr_ty.unwrap(), confidence); - visited_refs.remove(&ref_id_str); + let ref_id = TypeRefID::from(raw_ntr.as_ref()); + let mut ref_class = ReferrerClass::new(None, Some(raw_ntr.name().to_string())); + if visited_refs.insert(ref_id) { + // This ntr is NOT self-referential, meaning we can deduce a type GUID. + if let Some(computed_ty) = cached_type_reference(view, visited_refs, &raw_ntr) { // NOTE: The GUID here must always equal the same for any given type for this to work effectively. - let ntr_guid = TypeGUID::from(&ntr_ty); - let ref_class = ReferrerClass::new(Some(ntr_guid), ntr_ty.name); - let ntr_ty_class = TypeClass::Referrer(ref_class); - ref_cache.insert(ref_id_str, ntr_ty_class.clone()); - ntr_ty_class + ref_class.guid = Some(computed_ty.guid); } + visited_refs.remove(&ref_id); } + TypeClass::Referrer(ref_class) } BNTypeClass::WideCharTypeClass => { let char_class = CharacterClass { |
