From 83753b718a93e703ff05b24fd87a0bdd54f56bb7 Mon Sep 17 00:00:00 2001 From: godzie44 Date: Tue, 11 Jun 2024 21:40:36 +0300 Subject: [PATCH] refactoring(debugger): - rename `TypeIdentity` into `TypeId` - add `TypeIdenty` type - name + namespace - use type `TypeIdenty` in `VariableIR` instead of just name --- src/debugger/debugee/dwarf/mod.rs | 2 +- src/debugger/debugee/dwarf/type.rs | 217 ++++++++++++++---- src/debugger/variable/mod.rs | 171 +++++++------- src/debugger/variable/render.rs | 63 ++--- src/debugger/variable/specialization/btree.rs | 32 +-- src/debugger/variable/specialization/mod.rs | 76 +++--- src/debugger/watchpoint.rs | 3 +- src/ui/console/variable.rs | 20 +- src/ui/tui/components/variables.rs | 2 +- tests/debugger/io.rs | 2 +- tests/debugger/variables.rs | 38 +-- 11 files changed, 378 insertions(+), 248 deletions(-) diff --git a/src/debugger/debugee/dwarf/mod.rs b/src/debugger/debugee/dwarf/mod.rs index 4a3b278..4423f86 100644 --- a/src/debugger/debugee/dwarf/mod.rs +++ b/src/debugger/debugee/dwarf/mod.rs @@ -868,7 +868,7 @@ impl AsAllocatedData for ParameterDie { } } -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct NamespaceHierarchy(Vec); impl Deref for NamespaceHierarchy { diff --git a/src/debugger/debugee/dwarf/type.rs b/src/debugger/debugee/dwarf/type.rs index d339409..507abee 100644 --- a/src/debugger/debugee/dwarf/type.rs +++ b/src/debugger/debugee/dwarf/type.rs @@ -20,7 +20,75 @@ use strum_macros::Display; use uuid::Uuid; /// Type identifier. -pub type TypeIdentity = DieRef; +pub type TypeId = DieRef; + +/// Type name with namespace. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default)] +pub struct TypeIdentity { + namespace: NamespaceHierarchy, + name: Option, +} + +impl TypeIdentity { + /// Create type identity with empty namespace. + #[inline(always)] + pub fn no_namespace(name: impl ToString) -> Self { + Self { + namespace: Default::default(), + name: Some(name.to_string()), + } + } + + /// Create type identity for an unknown type. + #[inline(always)] + pub fn unknown() -> Self { + Self { + namespace: Default::default(), + name: None, + } + } + + /// True whether a type is unknown. + #[inline(always)] + pub fn is_unknown(&self) -> bool { + self.name.is_none() + } + + #[inline(always)] + pub fn name(&self) -> Option<&str> { + self.name.as_deref() + } + + /// Return formatted type name. + #[inline(always)] + pub fn name_fmt(&self) -> &str { + self.name().unwrap_or("unknown") + } + + /// Create address type name. + #[inline(always)] + pub fn as_address_type(&self) -> TypeIdentity { + TypeIdentity { + namespace: self.namespace.clone(), + name: Some(format!("&{}", self.name_fmt())), + } + } + + /// Create dereferenced type name. + #[inline(always)] + pub fn as_deref_type(&self) -> TypeIdentity { + TypeIdentity { + namespace: self.namespace.clone(), + name: Some(format!("*{}", self.name_fmt())), + } + } + + /// Create array type name from element type name. + #[inline(always)] + pub fn as_array_type(&self) -> TypeIdentity { + TypeIdentity::no_namespace(format!("[{}]", self.name_fmt())) + } +} pub struct EvaluationContext<'a> { pub evaluator: &'a ExpressionEvaluator<'a>, @@ -62,7 +130,7 @@ pub enum MemberLocation { pub struct StructureMember { pub in_struct_location: Option, pub name: Option, - pub type_ref: Option, + pub type_ref: Option, } impl StructureMember { @@ -145,7 +213,7 @@ pub enum UpperBound { pub struct ArrayType { pub namespaces: NamespaceHierarchy, byte_size: Option, - pub element_type: Option, + pub element_type: Option, lower_bound: ArrayBoundValue, upper_bound: Option, byte_size_memo: Cell>, @@ -156,7 +224,7 @@ impl ArrayType { pub fn new( namespaces: NamespaceHierarchy, byte_size: Option, - element_type: Option, + element_type: Option, lower_bound: ArrayBoundValue, upper_bound: Option, ) -> Self { @@ -215,6 +283,15 @@ pub struct ScalarType { pub encoding: Option, } +impl ScalarType { + pub fn identity(&self) -> TypeIdentity { + TypeIdentity { + namespace: self.namespaces.clone(), + name: self.name.clone(), + } + } +} + /// List of type modifiers #[derive(Display, Clone, Copy, PartialEq)] #[strum(serialize_all = "snake_case")] @@ -234,20 +311,20 @@ pub enum TypeDeclaration { namespaces: NamespaceHierarchy, name: Option, byte_size: Option, - discr_type: Option, + discr_type: Option, enumerators: HashMap, }, Pointer { namespaces: NamespaceHierarchy, name: Option, - target_type: Option, + target_type: Option, }, Structure { namespaces: NamespaceHierarchy, name: Option, byte_size: Option, members: Vec, - type_params: HashMap>, + type_params: HashMap>, }, Union { namespaces: NamespaceHierarchy, @@ -266,63 +343,113 @@ pub enum TypeDeclaration { Subroutine { namespaces: NamespaceHierarchy, name: Option, - return_type: Option, + return_type: Option, }, ModifiedType { modifier: CModifier, namespaces: NamespaceHierarchy, name: Option, - inner: Option, + inner: Option, }, } /// Type representation. This is a graph of types where vertexes is a type declaration and edges -/// is a dependencies between types. Type linking implemented by `TypeIdentity` references. +/// is a dependencies between types. Type linking implemented by `TypeId` references. /// Root is an identity of a main type. #[derive(Clone)] pub struct ComplexType { - pub types: HashMap, - pub root: TypeIdentity, + pub types: HashMap, + pub root: TypeId, } impl ComplexType { - /// Returns name of some of type existed in a complex type. - pub fn type_name(&self, typ: TypeIdentity) -> Option { - match &self.types.get(&typ)? { - TypeDeclaration::Scalar(s) => s.name.clone(), - TypeDeclaration::Structure { name, .. } => name.clone(), - TypeDeclaration::Array(arr) => Some(format!( - "[{}]", - arr.element_type - .and_then(|t| self.type_name(t)) - .unwrap_or("unknown".to_string()) - )), - TypeDeclaration::CStyleEnum { name, .. } => name.clone(), - TypeDeclaration::RustEnum { name, .. } => name.clone(), - TypeDeclaration::Pointer { name, .. } => name.clone(), - TypeDeclaration::Union { name, .. } => name.clone(), - TypeDeclaration::Subroutine { name, .. } => name.clone(), + /// Return name of some of a type existed in a complex type. + pub fn identity(&self, typ: TypeId) -> TypeIdentity { + let Some(r#type) = self.types.get(&typ) else { + return TypeIdentity::unknown(); + }; + + match r#type { + TypeDeclaration::Scalar(s) => s.identity(), + TypeDeclaration::Structure { + name, namespaces, .. + } => TypeIdentity { + namespace: namespaces.clone(), + name: name.as_ref().cloned(), + }, + TypeDeclaration::Array(arr) => { + let el_ident = arr.element_type.map(|t| self.identity(t)); + let name = format!( + "[{}]", + el_ident + .as_ref() + .map(|ident| ident.name_fmt()) + .unwrap_or("unknown") + ); + + TypeIdentity { + namespace: arr.namespaces.clone(), + name: Some(name.to_string()), + } + } + TypeDeclaration::CStyleEnum { + name, namespaces, .. + } => TypeIdentity { + namespace: namespaces.clone(), + name: name.as_ref().cloned(), + }, + TypeDeclaration::RustEnum { + name, namespaces, .. + } => TypeIdentity { + namespace: namespaces.clone(), + name: name.as_ref().cloned(), + }, + TypeDeclaration::Pointer { + name, namespaces, .. + } => TypeIdentity { + namespace: namespaces.clone(), + name: name.as_ref().cloned(), + }, + TypeDeclaration::Union { + name, namespaces, .. + } => TypeIdentity { + namespace: namespaces.clone(), + name: name.as_ref().cloned(), + }, + TypeDeclaration::Subroutine { + name, namespaces, .. + } => TypeIdentity { + namespace: namespaces.clone(), + name: name.as_ref().cloned(), + }, TypeDeclaration::ModifiedType { modifier, + namespaces, name, inner, .. } => match name { - None => inner.and_then(|inner_id| { - self.type_name(inner_id) - .map(|name| format!("{modifier} {name}")) - }), - Some(n) => Some(n.clone()), + None => { + let name = inner.map(|inner_id| { + let ident = self.identity(inner_id); + format!("{modifier} {name}", name = ident.name_fmt()) + }); + + TypeIdentity { + namespace: namespaces.clone(), + name, + } + } + Some(n) => TypeIdentity { + namespace: namespaces.clone(), + name: Some(n.to_string()), + }, }, } } /// Returns size of some of type existed in a complex type. - pub fn type_size_in_bytes( - &self, - eval_ctx: &EvaluationContext, - typ: TypeIdentity, - ) -> Option { + pub fn type_size_in_bytes(&self, eval_ctx: &EvaluationContext, typ: TypeId) -> Option { match &self.types.get(&typ)? { TypeDeclaration::Scalar(s) => s.byte_size, TypeDeclaration::Structure { byte_size, .. } => *byte_size, @@ -339,7 +466,7 @@ impl ComplexType { } /// Visit type children in bfs order, `start_at` - identity of root type. - pub fn bfs_iterator(&self, start_at: TypeIdentity) -> BfsIterator { + pub fn bfs_iterator(&self, start_at: TypeId) -> BfsIterator { BfsIterator { complex_type: self, queue: VecDeque::from([start_at]), @@ -351,7 +478,7 @@ impl ComplexType { /// Note that this iterator may be infinite. pub struct BfsIterator<'a> { complex_type: &'a ComplexType, - queue: VecDeque, + queue: VecDeque, } impl<'a> Iterator for BfsIterator<'a> { @@ -428,8 +555,8 @@ impl<'a> Iterator for BfsIterator<'a> { /// Dwarf DIE parser. pub struct TypeParser { - known_type_ids: HashSet, - processed_types: HashMap, + known_type_ids: HashSet, + processed_types: HashMap, } impl TypeParser { @@ -442,7 +569,7 @@ impl TypeParser { } /// Parse a `ComplexType` from a DIEs. - pub fn parse(self, ctx_die: ContextualDieRef<'_, T>, root_id: TypeIdentity) -> ComplexType { + pub fn parse(self, ctx_die: ContextualDieRef<'_, T>, root_id: TypeId) -> ComplexType { let mut this = self; this.parse_inner(ctx_die, root_id); ComplexType { @@ -909,5 +1036,5 @@ impl TypeParser { } /// A cache structure for types. -/// Every type identifies by its `TypeIdentity` and dwarf unit uuid. -pub type TypeCache = HashMap<(Uuid, TypeIdentity), ComplexType>; +/// Every type identified by its `TypeId` and DWARF unit uuid. +pub type TypeCache = HashMap<(Uuid, TypeId), ComplexType>; diff --git a/src/debugger/variable/mod.rs b/src/debugger/variable/mod.rs index eb6f01c..7569e6c 100644 --- a/src/debugger/variable/mod.rs +++ b/src/debugger/variable/mod.rs @@ -1,5 +1,5 @@ use crate::debugger::debugee::dwarf::r#type::{ - ArrayType, CModifier, EvaluationContext, ScalarType, StructureMember, TypeIdentity, + ArrayType, CModifier, EvaluationContext, ScalarType, StructureMember, TypeId, TypeIdentity, }; use crate::debugger::debugee::dwarf::r#type::{ComplexType, TypeDeclaration}; use crate::debugger::debugee::dwarf::{AsAllocatedData, ContextualDieRef, NamespaceHierarchy}; @@ -39,8 +39,8 @@ pub enum AssumeError { NoType(&'static str), #[error("underline data not a string")] DataNotAString(#[from] FromUtf8Error), - #[error("undefined size of type `{0}`")] - UnknownSize(String), + #[error("undefined size of type `{}`", .0.name_fmt())] + UnknownSize(TypeIdentity), #[error("type parameter `{0}` not found")] TypeParameterNotFound(&'static str), #[error("unknown type for type parameter `{0}`")] @@ -61,8 +61,8 @@ pub enum ParsingError { ReadDebugeeMemory(#[from] nix::Error), } -/// Identifier of debugee variables. -/// Consists of the name and namespace of the variable. +/// Identifier of a variable. +/// Consists name and namespace of the variable. #[derive(Clone, Default, PartialEq)] pub struct VariableIdentity { namespace: NamespaceHierarchy, @@ -185,8 +185,8 @@ pub struct ScalarVariable { pub identity: VariableIdentity, pub value: Option, pub raw_address: Option, - pub type_name: Option, - pub type_id: Option, + pub type_ident: TypeIdentity, + pub type_id: Option, } impl ScalarVariable { @@ -211,12 +211,12 @@ impl ScalarVariable { #[derive(Clone, Default, PartialEq)] pub struct StructVariable { pub identity: VariableIdentity, - pub type_name: Option, - pub type_id: Option, + pub type_ident: TypeIdentity, + pub type_id: Option, /// Structure members. Each represents by variable IR. pub members: Vec, /// Map of type parameters of a structure type. - pub type_params: HashMap>, + pub type_params: HashMap>, pub raw_address: Option, } @@ -224,8 +224,8 @@ pub struct StructVariable { #[derive(Clone, PartialEq)] pub struct ArrayVariable { pub identity: VariableIdentity, - pub type_name: Option, - pub type_id: Option, + pub type_ident: TypeIdentity, + pub type_id: Option, /// Array items. Each represents by variable IR. pub items: Option>, pub raw_address: Option, @@ -252,8 +252,8 @@ impl ArrayVariable { #[derive(Clone, PartialEq)] pub struct CEnumVariable { pub identity: VariableIdentity, - pub type_name: Option, - pub type_id: Option, + pub type_ident: TypeIdentity, + pub type_id: Option, /// String representation of selected variant. pub value: Option, pub raw_address: Option, @@ -263,8 +263,8 @@ pub struct CEnumVariable { #[derive(Clone, PartialEq)] pub struct RustEnumVariable { pub identity: VariableIdentity, - pub type_name: Option, - pub type_id: Option, + pub type_ident: TypeIdentity, + pub type_id: Option, /// Variable IR representation of selected variant. pub value: Option>, pub raw_address: Option, @@ -274,12 +274,12 @@ pub struct RustEnumVariable { #[derive(Clone, PartialEq)] pub struct PointerVariable { pub identity: VariableIdentity, - pub type_name: Option, - pub type_id: Option, + pub type_ident: TypeIdentity, + pub type_id: Option, /// Raw pointer to underline value. pub value: Option<*const ()>, /// Underline type identity. - pub target_type: Option, + pub target_type: Option, pub target_type_size: Option, pub raw_address: Option, } @@ -369,10 +369,7 @@ impl PointerVariable { identity, items: Some(items), type_id: None, - type_name: parser - .r#type - .type_name(target_type) - .map(|t| format!("[{t}]")), + type_ident: parser.r#type.identity(target_type).as_array_type(), raw_address: Some(base_addr), })) }) @@ -383,8 +380,8 @@ impl PointerVariable { #[derive(Clone, PartialEq)] pub struct SubroutineVariable { pub identity: VariableIdentity, - pub type_id: Option, - pub return_type_name: Option, + pub type_id: Option, + pub return_type_ident: Option, pub address: Option, } @@ -392,8 +389,8 @@ pub struct SubroutineVariable { #[derive(Clone, PartialEq)] pub struct CModifiedVariable { pub identity: VariableIdentity, - pub type_name: Option, - pub type_id: Option, + pub type_ident: TypeIdentity, + pub type_id: Option, pub modifier: CModifier, pub value: Option>, pub address: Option, @@ -439,7 +436,7 @@ impl VariableIR { } } - pub fn type_identity(&self) -> Option { + pub fn type_id(&self) -> Option { match self { VariableIR::Scalar(s) => s.type_id, VariableIR::Struct(s) => s.type_id, @@ -636,18 +633,18 @@ impl VariableIR { let addr = self.in_memory_location()?; Some(VariableIR::Pointer(PointerVariable { identity: VariableIdentity::no_namespace(None), - type_name: Some(format!("&{}", self.r#type())), + type_ident: self.r#type().as_address_type(), value: Some(addr as *const ()), - target_type: self.type_identity(), + target_type: self.type_id(), target_type_size: self - .type_identity() + .type_id() .and_then(|t| variable_parser.r#type.type_size_in_bytes(eval_ctx, t)), raw_address: None, type_id: None, })) } - /// Return variable field, `None` if get field is not allowed for variable type. + /// Return variable field, `None` if field is not allowed for a variable type. /// Supported: structures, rust-style enums, hashmaps, btree-maps. fn field(self, field_name: &str) -> Option { match self { @@ -735,7 +732,7 @@ impl VariableIR { Some(VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some("contains".to_string())), type_id: None, - type_name: Some("bool".to_string()), + type_ident: TypeIdentity::no_namespace("bool"), value: Some(SupportedScalar::Bool(found)), raw_address: None, })) @@ -1025,7 +1022,7 @@ impl<'a> VariableParser<'a> { &self, identity: VariableIdentity, data: Option, - type_id: TypeIdentity, + type_id: TypeId, r#type: &ScalarType, ) -> ScalarVariable { fn render_scalar(data: Option) -> Option { @@ -1111,7 +1108,7 @@ impl<'a> VariableParser<'a> { ScalarVariable { identity, - type_name: r#type.name.clone(), + type_ident: r#type.identity(), type_id: Some(type_id), value: value_view, raw_address: in_debugee_loc, @@ -1123,8 +1120,8 @@ impl<'a> VariableParser<'a> { eval_ctx: &EvaluationContext, identity: VariableIdentity, data: Option, - type_id: TypeIdentity, - type_params: HashMap>, + type_id: TypeId, + type_params: HashMap>, members: &[StructureMember], ) -> StructVariable { let children = members @@ -1135,7 +1132,7 @@ impl<'a> VariableParser<'a> { StructVariable { identity, type_id: Some(type_id), - type_name: self.r#type.type_name(type_id), + type_ident: self.r#type.identity(type_id), members: children, type_params, raw_address: data.and_then(|d| d.address), @@ -1171,7 +1168,7 @@ impl<'a> VariableParser<'a> { eval_ctx: &EvaluationContext, identity: VariableIdentity, data: Option, - type_id: TypeIdentity, + type_id: TypeId, array_decl: &ArrayType, ) -> ArrayVariable { let items = array_decl.bounds(eval_ctx).and_then(|bounds| { @@ -1220,7 +1217,7 @@ impl<'a> VariableParser<'a> { identity, items, type_id: Some(type_id), - type_name: self.r#type.type_name(type_id), + type_ident: self.r#type.identity(type_id), raw_address: data.and_then(|d| d.address), } } @@ -1230,8 +1227,8 @@ impl<'a> VariableParser<'a> { eval_ctx: &EvaluationContext, identity: VariableIdentity, data: Option, - type_id: TypeIdentity, - discr_type: Option, + type_id: TypeId, + discr_type: Option, enumerators: &HashMap, ) -> CEnumVariable { let in_debugee_loc = data.as_ref().and_then(|d| d.address); @@ -1254,7 +1251,7 @@ impl<'a> VariableParser<'a> { CEnumVariable { identity, - type_name: self.r#type.type_name(type_id), + type_ident: self.r#type.identity(type_id), type_id: Some(type_id), value: value.and_then(|val| enumerators.get(&val).cloned()), raw_address: in_debugee_loc, @@ -1266,7 +1263,7 @@ impl<'a> VariableParser<'a> { eval_ctx: &EvaluationContext, identity: VariableIdentity, data: Option, - type_id: TypeIdentity, + type_id: TypeId, discr_member: Option<&StructureMember>, enumerators: &HashMap, StructureMember>, ) -> RustEnumVariable { @@ -1292,7 +1289,7 @@ impl<'a> VariableParser<'a> { RustEnumVariable { identity, type_id: Some(type_id), - type_name: self.r#type.type_name(type_id), + type_ident: self.r#type.identity(type_id), value: enumerator, raw_address: data.and_then(|d| d.address), } @@ -1302,22 +1299,24 @@ impl<'a> VariableParser<'a> { &self, identity: VariableIdentity, data: Option, - type_id: TypeIdentity, - target_type: Option, + type_id: TypeId, + target_type: Option, ) -> PointerVariable { let mb_ptr = data .as_ref() .map(|v| scalar_from_bytes::<*const ()>(&v.raw_data)); + let mut type_ident = self.r#type.identity(type_id); + if type_ident.is_unknown() { + if let Some(target_type) = target_type { + type_ident = self.r#type.identity(target_type).as_deref_type(); + } + } + PointerVariable { identity, type_id: Some(type_id), - type_name: self.r#type.type_name(type_id).or_else(|| { - Some(format!( - "*{deref_type}", - deref_type = self.r#type.type_name(target_type?)? - )) - }), + type_ident, value: mb_ptr, target_type, target_type_size: None, @@ -1330,7 +1329,7 @@ impl<'a> VariableParser<'a> { eval_ctx: &EvaluationContext, identity: VariableIdentity, data: Option, - type_id: TypeIdentity, + type_id: TypeId, ) -> VariableIR { match &self.r#type.types[&type_id] { TypeDeclaration::Scalar(scalar_type) => { @@ -1522,11 +1521,11 @@ impl<'a> VariableParser<'a> { VariableIR::Struct(struct_var) } TypeDeclaration::Subroutine { return_type, .. } => { - let ret_type = return_type.and_then(|t_id| self.r#type.type_name(t_id)); + let ret_type = return_type.map(|t_id| self.r#type.identity(t_id)); let fn_var = SubroutineVariable { identity, type_id: Some(type_id), - return_type_name: ret_type, + return_type_ident: ret_type, address: data.and_then(|d| d.address), }; VariableIR::Subroutine(fn_var) @@ -1538,7 +1537,7 @@ impl<'a> VariableParser<'a> { VariableIR::CModifiedVariable(CModifiedVariable { identity: identity.clone(), type_id: Some(type_id), - type_name: self.r#type.type_name(type_id), + type_ident: self.r#type.identity(type_id), modifier: *modifier, value: inner.map(|inner_type| { Box::new(self.parse_inner(eval_ctx, identity, data, inner_type)) @@ -1667,19 +1666,19 @@ mod test { TestCase { variable: VariableIR::Struct(StructVariable { identity: VariableIdentity::no_namespace(Some("struct_1".to_owned())), - type_name: None, + type_ident: TypeIdentity::unknown(), type_id: None, members: vec![ VariableIR::Array(ArrayVariable { identity: VariableIdentity::no_namespace(Some("array_1".to_owned())), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), items: Some(vec![ VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some( "scalar_1".to_owned(), )), - type_name: None, + type_ident: TypeIdentity::unknown(), value: None, raw_address: None, type_id: None, @@ -1688,7 +1687,7 @@ mod test { identity: VariableIdentity::no_namespace(Some( "scalar_2".to_owned(), )), - type_name: None, + type_ident: TypeIdentity::unknown(), value: None, raw_address: None, type_id: None, @@ -1698,14 +1697,14 @@ mod test { }), VariableIR::Array(ArrayVariable { identity: VariableIdentity::no_namespace(Some("array_2".to_owned())), - type_name: None, + type_ident: TypeIdentity::unknown(), type_id: None, items: Some(vec![ VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some( "scalar_3".to_owned(), )), - type_name: None, + type_ident: TypeIdentity::unknown(), value: None, raw_address: None, type_id: None, @@ -1714,7 +1713,7 @@ mod test { identity: VariableIdentity::no_namespace(Some( "scalar_4".to_owned(), )), - type_name: None, + type_ident: TypeIdentity::unknown(), value: None, raw_address: None, type_id: None, @@ -1735,19 +1734,19 @@ mod test { variable: VariableIR::Struct(StructVariable { identity: VariableIdentity::no_namespace(Some("struct_1".to_owned())), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), members: vec![ VariableIR::Struct(StructVariable { identity: VariableIdentity::no_namespace(Some("struct_2".to_owned())), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), members: vec![ VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some( "scalar_1".to_owned(), )), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), value: None, raw_address: None, }), @@ -1756,13 +1755,13 @@ mod test { "enum_1".to_owned(), )), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), value: Some(Box::new(VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some( "scalar_2".to_owned(), )), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), value: None, raw_address: None, }))), @@ -1773,7 +1772,7 @@ mod test { "scalar_3".to_owned(), )), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), value: None, raw_address: None, }), @@ -1784,7 +1783,7 @@ mod test { VariableIR::Pointer(PointerVariable { identity: VariableIdentity::no_namespace(Some("pointer_1".to_owned())), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), value: None, target_type: None, target_type_size: None, @@ -1835,7 +1834,7 @@ mod test { VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(name.map(ToString::to_string)), type_id: None, - type_name: Some(type_name.into()), + type_ident: TypeIdentity::no_namespace(type_name), value: Some(scalar), raw_address: None, }) @@ -1873,19 +1872,19 @@ mod test { structure: StructVariable { identity: VariableIdentity::no_namespace(name.map(ToString::to_string)), type_id: None, - type_name: Some("vec".to_string()), + type_ident: TypeIdentity::no_namespace("vec"), members: vec![ VariableIR::Array(ArrayVariable { identity: VariableIdentity::default(), type_id: None, - type_name: Some("[item]".to_string()), + type_ident: TypeIdentity::no_namespace("[item]"), items: Some(items), raw_address: None, }), VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some("cap".to_string())), type_id: None, - type_name: Some("usize".to_owned()), + type_ident: TypeIdentity::no_namespace("usize"), value: Some(SupportedScalar::Usize(items_len)), raw_address: None, }), @@ -1920,7 +1919,7 @@ mod test { VariableIR::Specialized(SpecializedVariableIR::HashSet { set: Some(HashSetVariable { identity: VariableIdentity::no_namespace(name.map(ToString::to_string)), - type_name: Some("hashset".to_string()), + type_ident: TypeIdentity::no_namespace("hashset"), items, }), original: StructVariable { @@ -1934,7 +1933,7 @@ mod test { VariableIR::Specialized(SpecializedVariableIR::BTreeSet { set: Some(HashSetVariable { identity: VariableIdentity::no_namespace(name.map(ToString::to_string)), - type_name: Some("btreeset".to_string()), + type_ident: TypeIdentity::no_namespace("btreeset"), items, }), original: StructVariable { @@ -2009,7 +2008,7 @@ mod test { identity: VariableIdentity::default(), target_type: None, type_id: None, - type_name: Some("ptr".into()), + type_ident: TypeIdentity::no_namespace("ptr"), value: Some(123usize as *const ()), raw_address: None, target_type_size: None, @@ -2022,7 +2021,7 @@ mod test { identity: VariableIdentity::default(), target_type: None, type_id: None, - type_name: Some("MyPtr".into()), + type_ident: TypeIdentity::no_namespace("MyPtr"), value: Some(123usize as *const ()), raw_address: None, target_type_size: None, @@ -2034,7 +2033,7 @@ mod test { variable: VariableIR::CEnum(CEnumVariable { identity: VariableIdentity::default(), type_id: None, - type_name: Some("MyEnum".into()), + type_ident: TypeIdentity::no_namespace("MyEnum"), value: Some("Variant1".into()), raw_address: None, }), @@ -2048,15 +2047,15 @@ mod test { variable: VariableIR::RustEnum(RustEnumVariable { identity: VariableIdentity::default(), type_id: None, - type_name: Some("MyEnum".into()), + type_ident: TypeIdentity::no_namespace("MyEnum"), value: Some(Box::new(VariableIR::Struct(StructVariable { identity: VariableIdentity::no_namespace(Some("Variant1".to_string())), type_id: None, - type_name: None, + type_ident: TypeIdentity::unknown(), members: vec![VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some("Variant1".to_string())), type_id: None, - type_name: Some("int".into()), + type_ident: TypeIdentity::no_namespace("int"), value: Some(SupportedScalar::I64(100)), raw_address: None, })], @@ -2368,7 +2367,7 @@ mod test { variable: VariableIR::Array(ArrayVariable { identity: Default::default(), type_id: None, - type_name: Some("array_str".to_string()), + type_ident: TypeIdentity::no_namespace("array_str"), items: Some(vec![ make_str_var_ir(None, "ab"), make_str_var_ir(None, "cd"), @@ -2415,7 +2414,7 @@ mod test { variable: VariableIR::Struct(StructVariable { identity: Default::default(), type_id: None, - type_name: Some("MyStruct".to_string()), + type_ident: TypeIdentity::no_namespace("MyStruct"), members: vec![ make_str_var_ir(Some("str_field"), "str1"), make_vector_var_ir( @@ -2503,7 +2502,7 @@ mod test { variable: VariableIR::Struct(StructVariable { identity: Default::default(), type_id: None, - type_name: Some("MyTuple".to_string()), + type_ident: TypeIdentity::no_namespace("MyTuple"), members: vec![ make_str_var_ir(None, "str1"), make_vector_var_ir( diff --git a/src/debugger/variable/render.rs b/src/debugger/variable/render.rs index 0531072..5c0098a 100644 --- a/src/debugger/variable/render.rs +++ b/src/debugger/variable/render.rs @@ -1,5 +1,7 @@ +use crate::debugger::debugee::dwarf::r#type::TypeIdentity; use crate::debugger::variable::SpecializedVariableIR; use crate::debugger::variable::VariableIR; +use once_cell::sync::Lazy; use std::borrow::Cow; use std::fmt::{Debug, Formatter}; @@ -48,7 +50,7 @@ impl<'a> Debug for ValueLayout<'a> { pub trait RenderRepr { fn name(&self) -> String; - fn r#type(&self) -> &str; + fn r#type(&self) -> &TypeIdentity; fn value(&self) -> Option; } @@ -57,59 +59,62 @@ impl RenderRepr for VariableIR { self.identity().to_string() } - fn r#type(&self) -> &str { - let r#type = match self { - VariableIR::Scalar(s) => &s.type_name, - VariableIR::Struct(s) => &s.type_name, - VariableIR::Array(a) => &a.type_name, - VariableIR::CEnum(e) => &e.type_name, - VariableIR::RustEnum(e) => &e.type_name, - VariableIR::Pointer(p) => &p.type_name, + fn r#type(&self) -> &TypeIdentity { + static STRING_TYPE: Lazy = Lazy::new(|| TypeIdentity::no_namespace("String")); + static STR_TYPE: Lazy = Lazy::new(|| TypeIdentity::no_namespace("&str")); + static UNKNOWN_TYPE: Lazy = Lazy::new(TypeIdentity::unknown); + + match self { + VariableIR::Scalar(s) => &s.type_ident, + VariableIR::Struct(s) => &s.type_ident, + VariableIR::Array(a) => &a.type_ident, + VariableIR::CEnum(e) => &e.type_ident, + VariableIR::RustEnum(e) => &e.type_ident, + VariableIR::Pointer(p) => &p.type_ident, VariableIR::Specialized(spec) => match spec { SpecializedVariableIR::Vector { vec, original } | SpecializedVariableIR::VecDeque { vec, original } => match vec { - None => &original.type_name, - Some(v) => &v.structure.type_name, + None => &original.type_ident, + Some(v) => &v.structure.type_ident, }, - SpecializedVariableIR::String { .. } => return "String", - SpecializedVariableIR::Str { .. } => return "&str", + SpecializedVariableIR::String { .. } => return &STRING_TYPE, + SpecializedVariableIR::Str { .. } => return &STR_TYPE, SpecializedVariableIR::Tls { tls_var: value, original, .. } => match value { - None => &original.type_name, + None => &original.type_ident, Some(v) => &v.inner_type, }, SpecializedVariableIR::HashMap { map, original } => match map { - None => &original.type_name, - Some(map) => &map.type_name, + None => &original.type_ident, + Some(map) => &map.type_ident, }, SpecializedVariableIR::HashSet { set, original } => match set { - None => &original.type_name, - Some(set) => &set.type_name, + None => &original.type_ident, + Some(set) => &set.type_ident, }, SpecializedVariableIR::BTreeMap { map, original } => match map { - None => &original.type_name, - Some(map) => &map.type_name, + None => &original.type_ident, + Some(map) => &map.type_ident, }, SpecializedVariableIR::BTreeSet { set, original } => match set { - None => &original.type_name, - Some(set) => &set.type_name, + None => &original.type_ident, + Some(set) => &set.type_ident, }, SpecializedVariableIR::Cell { original, .. } - | SpecializedVariableIR::RefCell { original, .. } => &original.type_name, + | SpecializedVariableIR::RefCell { original, .. } => &original.type_ident, SpecializedVariableIR::Rc { original, .. } - | SpecializedVariableIR::Arc { original, .. } => &original.type_name, - SpecializedVariableIR::Uuid { original, .. } => &original.type_name, + | SpecializedVariableIR::Arc { original, .. } => &original.type_ident, + SpecializedVariableIR::Uuid { original, .. } => &original.type_ident, }, VariableIR::Subroutine(_) => { // currently this line is unreachable cause dereference fn pointer is forbidden - &None + &UNKNOWN_TYPE } - VariableIR::CModifiedVariable(v) => &v.type_name, - }; - r#type.as_deref().unwrap_or("unknown") + VariableIR::CModifiedVariable(v) => &v.type_ident, + } } fn value(&self) -> Option { diff --git a/src/debugger/variable/specialization/btree.rs b/src/debugger/variable/specialization/btree.rs index 879a489..4119c89 100644 --- a/src/debugger/variable/specialization/btree.rs +++ b/src/debugger/variable/specialization/btree.rs @@ -1,6 +1,6 @@ use crate::debugger; use crate::debugger::debugee::dwarf::r#type::{ - ComplexType, EvaluationContext, StructureMember, TypeIdentity, + ComplexType, EvaluationContext, StructureMember, TypeId, TypeIdentity, }; use crate::debugger::variable::select::ObjectBinaryRepr; use crate::debugger::variable::AssumeError::NoType; @@ -37,9 +37,9 @@ impl LeafNodeMarkup { /// `value_type_id` as an id of V type. Result node are closest to type with id `map_id`. fn from_type( r#type: &ComplexType, - map_id: TypeIdentity, - key_type_id: TypeIdentity, - value_type_id: TypeIdentity, + map_id: TypeId, + key_type_id: TypeId, + value_type_id: TypeId, ) -> Option { let mut iterator = r#type.bfs_iterator(map_id); @@ -100,9 +100,9 @@ impl InternalNodeMarkup { /// `value_type_id` as an id of V type. Result node are closest to type with id `map_id`. fn from_type( r#type: &ComplexType, - map_id: TypeIdentity, - key_type_id: TypeIdentity, - value_type_id: TypeIdentity, + map_id: TypeId, + key_type_id: TypeId, + value_type_id: TypeId, ) -> Option { let mut iterator = r#type.bfs_iterator(map_id); @@ -451,8 +451,8 @@ pub struct BTreeReflection<'a> { internal_markup: InternalNodeMarkup, leaf_markup: LeafNodeMarkup, r#type: &'a ComplexType, - k_type_id: TypeIdentity, - v_type_id: TypeIdentity, + k_type_id: TypeId, + v_type_id: TypeId, } impl<'a> BTreeReflection<'a> { @@ -461,9 +461,9 @@ impl<'a> BTreeReflection<'a> { r#type: &'a ComplexType, root_ptr: *const (), root_height: usize, - map_id: TypeIdentity, - k_type_id: TypeIdentity, - v_type_id: TypeIdentity, + map_id: TypeId, + k_type_id: TypeId, + v_type_id: TypeId, ) -> Result { Ok(Self { root: root_ptr, @@ -509,11 +509,15 @@ impl<'a> BTreeReflection<'a> { let k_size = self .r#type .type_size_in_bytes(eval_ctx, self.k_type_id) - .ok_or(AssumeError::UnknownSize("btree key type".into()))?; + .ok_or(AssumeError::UnknownSize(TypeIdentity::no_namespace( + "btree key type", + )))?; let v_size = self .r#type .type_size_in_bytes(eval_ctx, self.v_type_id) - .ok_or(AssumeError::UnknownSize("btree value type".into()))?; + .ok_or(AssumeError::UnknownSize(TypeIdentity::no_namespace( + "btree value type", + )))?; Ok(KVIterator { reflection: self, diff --git a/src/debugger/variable/specialization/mod.rs b/src/debugger/variable/specialization/mod.rs index 9325614..d0a826e 100644 --- a/src/debugger/variable/specialization/mod.rs +++ b/src/debugger/variable/specialization/mod.rs @@ -1,7 +1,7 @@ mod btree; mod hashbrown; -use crate::debugger::debugee::dwarf::r#type::{EvaluationContext, TypeIdentity}; +use crate::debugger::debugee::dwarf::r#type::{EvaluationContext, TypeId, TypeIdentity}; use crate::debugger::variable::render::RenderRepr; use crate::debugger::variable::select::ObjectBinaryRepr; use crate::debugger::variable::specialization::btree::BTreeReflection; @@ -81,14 +81,14 @@ pub struct StringVariable { #[derive(Clone, PartialEq)] pub struct HashMapVariable { pub identity: VariableIdentity, - pub type_name: Option, + pub type_ident: TypeIdentity, pub kv_items: Vec<(VariableIR, VariableIR)>, } #[derive(Clone, PartialEq)] pub struct HashSetVariable { pub identity: VariableIdentity, - pub type_name: Option, + pub type_ident: TypeIdentity, pub items: Vec, } @@ -102,7 +102,7 @@ pub struct StrVariable { pub struct TlsVariable { pub identity: VariableIdentity, pub inner_value: Option>, - pub inner_type: Option, + pub inner_type: TypeIdentity, } #[derive(Clone, PartialEq)] @@ -185,7 +185,7 @@ impl SpecializedVariableIR { } } - pub(super) fn type_id(&self) -> Option { + pub(super) fn type_id(&self) -> Option { match self { SpecializedVariableIR::Vector { original, .. } => original.type_id, SpecializedVariableIR::VecDeque { original, .. } => original.type_id, @@ -289,7 +289,7 @@ impl<'a> VariableParserExtension<'a> { &self, eval_ctx: &EvaluationContext, structure: StructVariable, - type_params: &HashMap>, + type_params: &HashMap>, ) -> SpecializedVariableIR { SpecializedVariableIR::Vector { vec: weak_error!(self @@ -303,7 +303,7 @@ impl<'a> VariableParserExtension<'a> { &self, eval_ctx: &EvaluationContext, ir: VariableIR, - type_params: &HashMap>, + type_params: &HashMap>, ) -> Result { let inner_type = type_params .get("T") @@ -320,9 +320,7 @@ impl<'a> VariableParserExtension<'a> { let el_type = self.parser.r#type; let el_type_size = el_type .type_size_in_bytes(eval_ctx, inner_type) - .ok_or(UnknownSize( - el_type.type_name(inner_type).unwrap_or_default(), - ))? as usize; + .ok_or(UnknownSize(el_type.identity(inner_type)))? as usize; let raw_data = debugger::read_memory_by_pid( eval_ctx.expl_ctx.pid_on_focus(), @@ -362,16 +360,12 @@ impl<'a> VariableParserExtension<'a> { structure: StructVariable { identity: ir.identity().clone(), type_id: None, - type_name: Some(ir.r#type().to_owned()), + type_ident: ir.r#type().clone(), members: vec![ VariableIR::Array(ArrayVariable { identity: VariableIdentity::no_namespace(Some("buf".to_owned())), type_id: None, - type_name: self - .parser - .r#type - .type_name(inner_type) - .map(|tp| format!("[{tp}]")), + type_ident: self.parser.r#type.identity(inner_type).as_array_type(), items: Some(items), // set to `None` because the address operator unavailable for spec vars raw_address: None, @@ -379,7 +373,7 @@ impl<'a> VariableParserExtension<'a> { VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some("cap".to_owned())), type_id: None, - type_name: Some("usize".to_owned()), + type_ident: TypeIdentity::no_namespace("usize"), value: Some(SupportedScalar::Usize(cap as usize)), // set to `None` because the address operator unavailable for spec vars raw_address: None, @@ -395,7 +389,7 @@ impl<'a> VariableParserExtension<'a> { pub fn parse_tls( &self, structure: StructVariable, - type_params: &HashMap>, + type_params: &HashMap>, ) -> SpecializedVariableIR { SpecializedVariableIR::Tls { tls_var: weak_error!(self @@ -408,7 +402,7 @@ impl<'a> VariableParserExtension<'a> { fn parse_tls_inner( &self, ir: VariableIR, - type_params: &HashMap>, + type_params: &HashMap>, ) -> Result { // we assume that tls variable name represents in dwarf // as namespace flowed before "__getit" namespace @@ -430,9 +424,9 @@ impl<'a> VariableParserExtension<'a> { let inner_option = inner.assume_field_as_rust_enum("value")?; let inner_value = inner_option.value.ok_or(IncompleteInterp("value"))?; - // we assume that dwarf representation of tls variable contains ::Option + // we assume that DWARF representation of tls variable contains ::Option if let VariableIR::Struct(opt_variant) = inner_value.as_ref() { - let tls_value = if opt_variant.type_name.as_deref() == Some("None") { + let tls_value = if opt_variant.type_ident.name() == Some("None") { None } else { Some(Box::new( @@ -447,7 +441,7 @@ impl<'a> VariableParserExtension<'a> { return Ok(TlsVariable { identity: VariableIdentity::no_namespace(name), inner_value: tls_value, - inner_type: self.parser.r#type.type_name(inner_type), + inner_type: self.parser.r#type.identity(inner_type), }); } @@ -487,7 +481,7 @@ impl<'a> VariableParserExtension<'a> { let r#type = self.parser.r#type; let kv_size = r#type .type_size_in_bytes(eval_ctx, kv_type) - .ok_or(UnknownSize(r#type.type_name(kv_type).unwrap_or_default()))?; + .ok_or(UnknownSize(r#type.identity(kv_type)))?; let reflection = HashmapReflection::new(ctrl as *mut u8, bucket_mask as usize, kv_size as usize); @@ -524,7 +518,7 @@ impl<'a> VariableParserExtension<'a> { Ok(HashMapVariable { identity: ir.identity().clone(), - type_name: Some(ir.r#type().to_owned()), + type_ident: ir.r#type().to_owned(), kv_items, }) } @@ -561,7 +555,7 @@ impl<'a> VariableParserExtension<'a> { .parser .r#type .type_size_in_bytes(eval_ctx, kv_type) - .ok_or_else(|| UnknownSize(r#type.type_name(kv_type).unwrap_or_default()))?; + .ok_or_else(|| UnknownSize(r#type.identity(kv_type)))?; let reflection = HashmapReflection::new(ctrl as *mut u8, bucket_mask as usize, kv_size as usize); @@ -598,7 +592,7 @@ impl<'a> VariableParserExtension<'a> { Ok(HashSetVariable { identity: ir.identity().clone(), - type_name: Some(ir.r#type().to_owned()), + type_ident: ir.r#type().to_owned(), items, }) } @@ -607,8 +601,8 @@ impl<'a> VariableParserExtension<'a> { &self, eval_ctx: &EvaluationContext, structure: StructVariable, - identity: TypeIdentity, - type_params: &HashMap>, + identity: TypeId, + type_params: &HashMap>, ) -> SpecializedVariableIR { SpecializedVariableIR::BTreeMap { map: weak_error!(self @@ -627,8 +621,8 @@ impl<'a> VariableParserExtension<'a> { &self, eval_ctx: &EvaluationContext, ir: VariableIR, - identity: TypeIdentity, - type_params: &HashMap>, + identity: TypeId, + type_params: &HashMap>, ) -> Result { let height = ir.assume_field_as_scalar_number("height")?; let ptr = ir.assume_field_as_pointer("pointer")?; @@ -674,7 +668,7 @@ impl<'a> VariableParserExtension<'a> { Ok(HashMapVariable { identity: ir.identity().clone(), - type_name: Some(ir.r#type().to_owned()), + type_ident: ir.r#type().to_owned(), kv_items, }) } @@ -707,7 +701,7 @@ impl<'a> VariableParserExtension<'a> { Ok(HashSetVariable { identity: ir.identity().clone(), - type_name: Some(ir.r#type().to_owned()), + type_ident: ir.r#type().to_owned(), items: inner_map.kv_items.into_iter().map(|(k, _)| k).collect(), }) } @@ -716,7 +710,7 @@ impl<'a> VariableParserExtension<'a> { &self, eval_ctx: &EvaluationContext, structure: StructVariable, - type_params: &HashMap>, + type_params: &HashMap>, ) -> SpecializedVariableIR { SpecializedVariableIR::VecDeque { vec: weak_error!(self @@ -734,7 +728,7 @@ impl<'a> VariableParserExtension<'a> { &self, eval_ctx: &EvaluationContext, ir: VariableIR, - type_params: &HashMap>, + type_params: &HashMap>, ) -> Result { let inner_type = type_params .get("T") @@ -746,7 +740,7 @@ impl<'a> VariableParserExtension<'a> { let r#type = self.parser.r#type; let el_type_size = r#type .type_size_in_bytes(eval_ctx, inner_type) - .ok_or_else(|| UnknownSize(r#type.type_name(inner_type).unwrap_or_default()))? + .ok_or_else(|| UnknownSize(r#type.identity(inner_type)))? as usize; let cap = if el_type_size == 0 { usize::MAX @@ -799,16 +793,12 @@ impl<'a> VariableParserExtension<'a> { structure: StructVariable { identity: ir.identity().clone(), type_id: None, - type_name: Some(ir.r#type().to_owned()), + type_ident: ir.r#type().to_owned(), members: vec![ VariableIR::Array(ArrayVariable { identity: VariableIdentity::no_namespace(Some("buf".to_owned())), type_id: None, - type_name: self - .parser - .r#type - .type_name(inner_type) - .map(|tp| format!("[{tp}]")), + type_ident: self.parser.r#type.identity(inner_type).as_array_type(), items: Some(items), // set to `None` because the address operator unavailable for spec vars raw_address: None, @@ -816,7 +806,7 @@ impl<'a> VariableParserExtension<'a> { VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some("cap".to_owned())), type_id: None, - type_name: Some("usize".to_owned()), + type_ident: TypeIdentity::no_namespace("usize"), value: Some(SupportedScalar::Usize(if el_type_size == 0 { 0 } else { @@ -891,7 +881,7 @@ impl<'a> VariableParserExtension<'a> { Ok(VariableIR::Struct(StructVariable { identity: ir.identity().clone(), type_id: None, - type_name: Some(ir.r#type().to_owned()), + type_ident: ir.r#type().to_owned(), members: vec![borrow, value.clone()], type_params: Default::default(), // set to `None` because the address operator unavailable for spec vars diff --git a/src/debugger/watchpoint.rs b/src/debugger/watchpoint.rs index 1599f53..e55bb83 100644 --- a/src/debugger/watchpoint.rs +++ b/src/debugger/watchpoint.rs @@ -1,5 +1,6 @@ use crate::debugger::address::{GlobalAddress, RelocatedAddress}; use crate::debugger::breakpoint::{Breakpoint, BreakpointRegistry}; +use crate::debugger::debugee::dwarf::r#type::TypeIdentity; use crate::debugger::debugee::tracee::TraceeCtl; use crate::debugger::debugee::tracer::WatchpointHitType; use crate::debugger::debugee::{Debugee, Location}; @@ -96,7 +97,7 @@ impl AddressTarget { VariableIR::Scalar(ScalarVariable { identity: VariableIdentity::no_namespace(Some("data".to_string())), value: Some(u), - type_name: Some(t.to_string()), + type_ident: TypeIdentity::no_namespace(t), type_id: None, raw_address: None, }) diff --git a/src/ui/console/variable.rs b/src/ui/console/variable.rs index 01446ff..8f58d39 100644 --- a/src/ui/console/variable.rs +++ b/src/ui/console/variable.rs @@ -31,21 +31,25 @@ pub fn render_variable_ir(view: &VariableIR, depth: usize) -> String { match view.value() { Some(value) => match value { ValueLayout::PreRendered(rendered_value) => match view { - VariableIR::CEnum(_) => format!("{}::{}", view.r#type(), rendered_value), - _ => format!("{}({})", view.r#type(), rendered_value), + VariableIR::CEnum(_) => format!("{}::{}", view.r#type().name_fmt(), rendered_value), + _ => format!("{}({})", view.r#type().name_fmt(), rendered_value), }, ValueLayout::Referential { addr } => { format!( "{} [{}]", - view.r#type(), + view.r#type().name_fmt(), RelocatedAddress::from(addr as usize) ) } ValueLayout::Wrapped(val) => { - format!("{}::{}", view.r#type(), render_variable_ir(val, depth)) + format!( + "{}::{}", + view.r#type().name_fmt(), + render_variable_ir(val, depth) + ) } ValueLayout::Structure { members } => { - let mut render = format!("{} {{", view.r#type()); + let mut render = format!("{} {{", view.r#type().name_fmt()); let tabs = TAB.repeat(depth + 1); @@ -61,7 +65,7 @@ pub fn render_variable_ir(view: &VariableIR, depth: usize) -> String { format!("{render}\n{}}}", TAB.repeat(depth)) } ValueLayout::Map(kv_children) => { - let mut render = format!("{} {{", view.r#type()); + let mut render = format!("{} {{", view.r#type().name_fmt()); let tabs = TAB.repeat(depth + 1); @@ -77,7 +81,7 @@ pub fn render_variable_ir(view: &VariableIR, depth: usize) -> String { format!("{render}\n{}}}", TAB.repeat(depth)) } ValueLayout::List { members, indexed } => { - let mut render = format!("{} {{", view.r#type()); + let mut render = format!("{} {{", view.r#type().name_fmt()); let tabs = TAB.repeat(depth + 1); @@ -97,6 +101,6 @@ pub fn render_variable_ir(view: &VariableIR, depth: usize) -> String { format!("{render}\n{}}}", TAB.repeat(depth)) } }, - None => format!("{}(unknown)", view.r#type()), + None => format!("{}(unknown)", view.r#type().name_fmt()), } } diff --git a/src/ui/tui/components/variables.rs b/src/ui/tui/components/variables.rs index 7f52079..27a3e0b 100644 --- a/src/ui/tui/components/variables.rs +++ b/src/ui/tui/components/variables.rs @@ -71,7 +71,7 @@ impl Variables { select_path: Option, ) -> Node> { let name = var.name(); - let typ = var.r#type(); + let typ = var.r#type().name_fmt(); // recursion guard if recursion >= MAX_RECURSION { diff --git a/tests/debugger/io.rs b/tests/debugger/io.rs index 7c35019..0743a49 100644 --- a/tests/debugger/io.rs +++ b/tests/debugger/io.rs @@ -78,7 +78,7 @@ fn test_read_value_u64() { assert_eq!(vars.len(), 5); assert_eq!(vars[4].name(), "s"); - assert_eq!(vars[4].r#type(), "i64"); + assert_eq!(vars[4].r#type().name_fmt(), "i64"); let _six = "6".to_string(); assert!(matches!( vars[4].value().unwrap(), diff --git a/tests/debugger/variables.rs b/tests/debugger/variables.rs index a92f720..283e396 100644 --- a/tests/debugger/variables.rs +++ b/tests/debugger/variables.rs @@ -23,7 +23,7 @@ pub fn assert_scalar( panic!("not a scalar"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); assert_eq!(scalar.value, exp_val); } @@ -37,7 +37,7 @@ fn assert_struct( panic!("not a struct"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); for (i, member) in structure.members.iter().enumerate() { for_each_member(i, member) } @@ -53,7 +53,7 @@ fn assert_array( panic!("not a array"); }; assert_eq!(array.identity.name.as_ref().unwrap(), exp_name); - assert_eq!(array.type_name.as_ref().unwrap(), exp_type); + assert_eq!(array.type_ident.name_fmt(), exp_type); for (i, item) in array.items.as_ref().unwrap_or(&vec![]).iter().enumerate() { for_each_item(i, item) } @@ -64,7 +64,7 @@ fn assert_c_enum(var: &VariableIR, exp_name: &str, exp_type: &str, exp_value: Op panic!("not a c_enum"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); assert_eq!(c_enum.value, exp_value); } @@ -78,7 +78,7 @@ fn assert_rust_enum( panic!("not a c_enum"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); with_value(rust_enum.value.as_ref().unwrap()); } @@ -87,7 +87,7 @@ fn assert_pointer(var: &VariableIR, exp_name: &str, exp_type: &str) { panic!("not a pointer"); }; assert_eq!(var.name(), exp_name); - assert_eq!(ptr.type_name.as_ref().unwrap(), exp_type); + assert_eq!(ptr.type_ident.name_fmt(), exp_type); } fn assert_vec( @@ -104,7 +104,7 @@ fn assert_vec( panic!("not a vector"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); let VariableIR::Scalar(capacity) = &vector.structure.members[1] else { panic!("no capacity"); }; @@ -148,7 +148,7 @@ fn assert_init_tls( panic!("not a tls"); }; assert_eq!(tls.identity.name.as_ref().unwrap(), exp_name); - assert_eq!(tls.inner_type.as_ref().unwrap(), exp_type); + assert_eq!(tls.inner_type.name_fmt(), exp_type); with_var(tls.inner_value.as_ref().unwrap()); } @@ -160,7 +160,7 @@ fn assert_uninit_tls(var: &VariableIR, exp_name: &str, exp_type: &str) { panic!("not a tls"); }; assert_eq!(tls.identity.name.as_ref().unwrap(), exp_name); - assert_eq!(tls.inner_type.as_ref().unwrap(), exp_type); + assert_eq!(tls.inner_type.name_fmt(), exp_type); assert!(tls.inner_value.is_none()); } @@ -177,7 +177,7 @@ fn assert_hashmap( panic!("not a hashmap"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); let mut items = map.kv_items.clone(); items.sort_by(|v1, v2| { let k1_render = format!("{:?}", v1.0.value()); @@ -200,7 +200,7 @@ fn assert_hashset( panic!("not a hashset"); }; assert_eq!(set.identity.name.as_ref().unwrap(), exp_name); - assert_eq!(set.type_name.as_ref().unwrap(), exp_type); + assert_eq!(set.type_ident.name_fmt(), exp_type); let mut items = set.items.clone(); items.sort_by(|v1, v2| { let k1_render = format!("{:?}", v1.value()); @@ -223,7 +223,7 @@ fn assert_btree_map( panic!("not a BTreeMap"); }; assert_eq!(map.identity.name.as_ref().unwrap(), exp_name); - assert_eq!(map.type_name.as_ref().unwrap(), exp_type); + assert_eq!(map.type_ident.name_fmt(), exp_type); with_kv_items(&map.kv_items); } @@ -240,7 +240,7 @@ fn assert_btree_set( panic!("not a BTreeSet"); }; assert_eq!(set.identity.name.as_ref().unwrap(), exp_name); - assert_eq!(set.type_name.as_ref().unwrap(), exp_type); + assert_eq!(set.type_ident.name_fmt(), exp_type); with_items(&set.items); } @@ -259,7 +259,7 @@ fn assert_vec_deque( panic!("not a VecDeque"); }; assert_eq!(vector.structure.identity.name.as_ref().unwrap(), exp_name); - assert_eq!(vector.structure.type_name.as_ref().unwrap(), exp_type); + assert_eq!(vector.structure.type_ident.name_fmt(), exp_type); let VariableIR::Scalar(capacity) = &vector.structure.members[1] else { panic!("no capacity"); }; @@ -277,7 +277,7 @@ fn assert_cell( panic!("not a Cell"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); with_value(value.as_ref().unwrap()); } @@ -293,7 +293,7 @@ fn assert_refcell( panic!("not a Cell"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); let value = &**value.as_ref().unwrap(); let VariableIR::Struct(as_struct) = value else { panic!("not a struct") @@ -314,7 +314,7 @@ fn assert_rc(var: &VariableIR, exp_name: &str, exp_type: &str) { panic!("not an rc"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); } fn assert_arc(var: &VariableIR, exp_name: &str, exp_type: &str) { @@ -322,7 +322,7 @@ fn assert_arc(var: &VariableIR, exp_name: &str, exp_type: &str) { panic!("not an arc"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); } fn assert_uuid(var: &VariableIR, exp_name: &str, exp_type: &str) { @@ -330,7 +330,7 @@ fn assert_uuid(var: &VariableIR, exp_name: &str, exp_type: &str) { panic!("not an uuid"); }; assert_eq!(var.name(), exp_name); - assert_eq!(var.r#type(), exp_type); + assert_eq!(var.r#type().name_fmt(), exp_type); } #[test]