From 2275a6257a253edaeda539d9b9f88c830051f2ea Mon Sep 17 00:00:00 2001 From: Louis Caron Date: Fri, 13 Feb 2026 10:43:20 +0100 Subject: [PATCH 1/3] fix: walk down type ref debug info when matching symbols Signed-off-by: Louis Caron --- src/symbol.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/symbol.rs b/src/symbol.rs index 7db141b..1de44e5 100644 --- a/src/symbol.rs +++ b/src/symbol.rs @@ -322,6 +322,7 @@ fn find_membertype<'a>( } let elementaddr = address + (multi_index as u64 * stride); + let arraytype = arraytype.get_reference(&debug_data.types); find_membertype( arraytype, debug_data, From f4e578a38f4bd7377981960436860d46d00a9f7b Mon Sep 17 00:00:00 2001 From: Louis Caron Date: Sun, 15 Feb 2026 13:58:36 +0100 Subject: [PATCH 2/3] feat: add a recursion over typerefs when resolving types Signed-off-by: Louis Caron --- src/debuginfo/mod.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 2c17285..f45c8f0 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -170,10 +170,20 @@ impl TypeInfo { } pub(crate) fn get_reference<'a>(&'a self, types: &'a HashMap) -> &'a Self { - if let DbgDataType::TypeRef(dbginfo_offset, _) = &self.datatype { - types.get(dbginfo_offset).unwrap_or(self) - } else { - self + let mut current: &'a TypeInfo = self; + loop { + match ¤t.datatype { + DbgDataType::TypeRef(dbginfo_offset, _) => { + // Try to follow the reference; if missing, stop and return current + let next = types.get(dbginfo_offset); + + match next { + Some(t) => current = t, + None => return current, // broken ref: stop here + } + } + _ => return current, // reached a concrete type + } } } From 5dabd4955affe340dedcb255abf5cc9b78bdd9e7 Mon Sep 17 00:00:00 2001 From: Louis Caron Date: Fri, 13 Feb 2026 13:58:51 +0100 Subject: [PATCH 3/3] feat: add unit test for typeref debug data Signed-off-by: Louis Caron --- src/symbol.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/src/symbol.rs b/src/symbol.rs index 1de44e5..10c2b63 100644 --- a/src/symbol.rs +++ b/src/symbol.rs @@ -553,6 +553,89 @@ mod test { assert!(result3.is_err()); } + #[test] + fn test_find_symbol_in_nested_typerefs() { + let mut dbgdata = DebugData { + types: HashMap::new(), + typenames: HashMap::new(), + variables: IndexMap::new(), + demangled_names: HashMap::new(), + unit_names: Vec::new(), + sections: HashMap::new(), + }; + + dbgdata.types.insert( + 86352, + TypeInfo { + name: Some("shorttype".to_string()), + datatype: DbgDataType::Sint16, + unit_idx: 0, + dbginfo_offset: 86352, + }, + ); + dbgdata.types.insert( + 86353, + TypeInfo { + name: Some("consttype".to_string()), + datatype: DbgDataType::TypeRef(86352, 2), + unit_idx: 0, + dbginfo_offset: 86353, + }, + ); + dbgdata.types.insert( + 86310, + TypeInfo { + name: Some("constshortarraytype".to_string()), + unit_idx: 0, + datatype: DbgDataType::Array { + size: 20, + dim: vec![10], + stride:2, + arraytype: Box::new(TypeInfo { + name: Some("constshorttype".to_string()), + unit_idx: 0, + datatype: DbgDataType::TypeRef(86353, 2), + dbginfo_offset: 86309, + }) + }, + dbginfo_offset: 86310, + }, + ); + dbgdata.variables.insert( + "variable".to_string(), + vec![crate::debuginfo::VarInfo { + address: 0x00ca_fe00, + typeref: 86310, + unit_idx: 0, + function: None, + namespaces: vec![], + }], + ); + + // try the different array indexing notations + let result: Result, String> = find_symbol("variable._0_", &dbgdata); + assert!(result.is_ok()); + let symbolinfo = result.unwrap(); + assert!(symbolinfo.address == 0x00ca_fe00); + assert!(matches!(symbolinfo.typeinfo.datatype, DbgDataType::Sint16)); + let result: Result, String> = find_symbol("variable[0]", &dbgdata); + assert!(result.is_ok()); + assert!(result.unwrap().address == 0x00ca_fe00); + let result: Result, String> = find_symbol("variable[1]", &dbgdata); + assert!(result.is_ok()); + assert!(result.unwrap().address == 0x00ca_fe02); + let result: Result, String> = find_symbol("variable[9]", &dbgdata); + assert!(result.is_ok()); + assert!(result.unwrap().address == 0x00ca_fe12); + + // there should not be a result if the symbol name contains extra unmatched components + let result: Result, String> = find_symbol("variable[0].three", &dbgdata); + assert!(result.is_err()); + // there should not be a result if the symbol name goes outside array boundaries + let result: Result, String> = find_symbol("variable[10]", &dbgdata); + assert!(result.is_err()); + } + #[test] fn test_select_varinfo() { let mut debug_data = DebugData {