1use super::*;
2use crate::{stack_frame::StackFrameInfo, unit_info::UnitInfo};
3use gimli::UnitOffset;
4use probe_rs::Error;
5use probe_rs_target::MemoryRange;
6use serde::{Serialize, Serializer};
7use std::{
8 collections::{BTreeMap, btree_map::Entry},
9 ops::Range,
10};
11
12#[derive(Debug, Clone, PartialEq)]
14pub struct VariableCache {
15 root_variable_key: ObjectRef,
16
17 variable_hash_map: BTreeMap<ObjectRef, Variable>,
18}
19
20impl Serialize for VariableCache {
21 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
22 where
23 S: Serializer,
24 {
25 use serde::ser::SerializeStruct;
26
27 #[derive(Serialize)]
29 struct VariableTreeNode<'c> {
30 name: &'c VariableName,
31 type_name: &'c VariableType,
32 value: String,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
36 source_location: Option<SourceLocation>,
37 #[serde(skip_serializing_if = "Vec::is_empty")]
39 children: Vec<VariableTreeNode<'c>>,
40 }
41
42 fn recurse_cache(variable_cache: &VariableCache) -> VariableTreeNode {
43 let root_node = variable_cache.root_variable();
44
45 VariableTreeNode {
46 name: &root_node.name,
47 type_name: &root_node.type_name,
48 value: root_node.to_string(variable_cache),
49 source_location: root_node.source_location.clone(),
50 children: recurse_variables(variable_cache, root_node.variable_key, None),
51 }
52 }
53
54 fn recurse_variables(
56 variable_cache: &VariableCache,
57 parent_variable_key: ObjectRef,
58 max_children: Option<usize>,
59 ) -> Vec<VariableTreeNode> {
60 let mut children = variable_cache.get_children(parent_variable_key);
61
62 let mut out = Vec::new();
63
64 loop {
65 if let Some(max_count) = max_children {
66 if out.len() >= max_count {
67 let remaining = children.clone().count();
69 if remaining > 1 {
70 break;
71 }
72 }
73 }
74 let Some(child_variable) = children.next() else {
75 break;
76 };
77
78 out.push(VariableTreeNode {
79 name: &child_variable.name,
80 type_name: &child_variable.type_name,
81 value: child_variable.to_string(variable_cache),
82 children: recurse_variables(
83 variable_cache,
84 child_variable.variable_key,
85 child_variable.type_name.inner().is_array().then_some(50),
87 ),
88 source_location: child_variable.source_location.clone(),
89 });
90 }
91
92 let remaining = children.count();
93 if remaining > 0 {
94 out.push(VariableTreeNode {
95 name: &VariableName::Artifical,
96 type_name: &VariableType::Unknown,
97 value: format!("... and {} more", remaining),
98 children: Vec::new(),
99 source_location: None,
100 });
101 }
102
103 out
104 }
105
106 let mut state = serializer.serialize_struct("Variables", 1)?;
107 state.serialize_field("Child Variables", &recurse_cache(self))?;
108 state.end()
109 }
110}
111
112impl VariableCache {
113 fn new(mut variable: Variable) -> Self {
114 let key = get_object_reference();
115
116 variable.variable_key = key;
117
118 VariableCache {
119 root_variable_key: key,
120 variable_hash_map: BTreeMap::from([(key, variable)]),
121 }
122 }
123
124 pub fn new_dwarf_cache(
132 entries_offset: UnitOffset,
133 name: VariableName,
134 unit_info: &UnitInfo,
135 ) -> Result<Self, DebugError> {
136 let mut static_root_variable = Variable::new(Some(unit_info));
137 static_root_variable.variable_node_type =
138 VariableNodeType::DirectLookup(unit_info.debug_info_offset()?, entries_offset);
139 static_root_variable.name = name;
140
141 Ok(VariableCache::new(static_root_variable))
142 }
143
144 pub fn new_static_cache() -> Self {
148 let mut static_root_variable = Variable::new(None);
149 static_root_variable.variable_node_type = VariableNodeType::UnitsLookup;
150 static_root_variable.name = VariableName::StaticScopeRoot;
151
152 VariableCache::new(static_root_variable)
153 }
154
155 pub fn root_variable(&self) -> &Variable {
157 &self.variable_hash_map[&self.root_variable_key]
158 }
159
160 pub fn len(&self) -> usize {
163 self.variable_hash_map.len()
164 }
165
166 pub fn is_empty(&self) -> bool {
168 self.variable_hash_map.is_empty()
169 }
170
171 pub fn create_variable(
173 &mut self,
174 parent_key: ObjectRef,
175 unit_info: Option<&UnitInfo>,
176 ) -> Result<Variable, DebugError> {
177 if !self.variable_hash_map.contains_key(&parent_key) {
179 return Err(DebugError::Other(format!(
180 "VariableCache: Attempted to add a new variable with non existent `parent_key`: {:?}. Please report this as a bug",
181 parent_key
182 )));
183 }
184
185 let mut variable_to_add = Variable::new(unit_info);
186 variable_to_add.parent_key = parent_key;
187
188 variable_to_add.variable_key = get_object_reference();
190
191 tracing::trace!(
192 "VariableCache: Add Variable: key={:?}, parent={:?}, name={:?}",
193 variable_to_add.variable_key,
194 variable_to_add.parent_key,
195 &variable_to_add.name
196 );
197
198 match self.variable_hash_map.entry(variable_to_add.variable_key) {
199 Entry::Occupied(_) => {
200 return Err(DebugError::Other(format!(
201 "Attempt to insert a new `Variable`:{:?} with a duplicate cache key: {:?}. Please report this as a bug.",
202 variable_to_add.name, variable_to_add.variable_key
203 )));
204 }
205 Entry::Vacant(entry) => {
206 entry.insert(variable_to_add.clone());
207 }
208 }
209
210 Ok(variable_to_add)
211 }
212
213 pub fn add_variable(
218 &mut self,
219 parent_key: ObjectRef,
220 cache_variable: &mut Variable,
221 ) -> Result<(), DebugError> {
222 if !self.variable_hash_map.contains_key(&parent_key) {
224 return Err(DebugError::Other(format!(
225 "VariableCache: Attempted to add a new variable: {} with non existent `parent_key`: {:?}. Please report this as a bug",
226 cache_variable.name, parent_key
227 )));
228 }
229
230 cache_variable.parent_key = parent_key;
231
232 if cache_variable.variable_key != ObjectRef::Invalid {
233 return Err(DebugError::Other(format!(
234 "VariableCache: Attempted to add a new variable: {} with already set key: {:?}. Please report this as a bug",
235 cache_variable.name, cache_variable.variable_key
236 )));
237 }
238
239 cache_variable.variable_key = get_object_reference();
241
242 tracing::trace!(
243 "VariableCache: Add Variable: key={:?}, parent={:?}, name={:?}",
244 cache_variable.variable_key,
245 cache_variable.parent_key,
246 cache_variable.name
247 );
248
249 if let Some(old_variable) = self
250 .variable_hash_map
251 .insert(cache_variable.variable_key, cache_variable.clone())
252 {
253 return Err(DebugError::Other(format!(
254 "Attempt to insert a new `Variable`:{:?} with a duplicate cache key: {:?}. Please report this as a bug.",
255 cache_variable.name, old_variable.variable_key
256 )));
257 }
258
259 Ok(())
260 }
261
262 pub fn update_variable(&mut self, cache_variable: &Variable) -> Result<(), DebugError> {
266 tracing::trace!(
268 "VariableCache: Update Variable, key={:?}, name={:?}",
269 cache_variable.variable_key,
270 &cache_variable.name
271 );
272
273 let Some(prev_entry) = self.variable_hash_map.get_mut(&cache_variable.variable_key) else {
274 return Err(DebugError::Other(format!(
275 "Attempt to update an existing `Variable`:{:?} with a non-existent cache key: {:?}. Please report this as a bug.",
276 cache_variable.name, cache_variable.variable_key
277 )));
278 };
279
280 if cache_variable != prev_entry {
281 tracing::trace!("Updated: {:?}", cache_variable);
282 tracing::trace!("Previous: {:?}", prev_entry);
283 *prev_entry = cache_variable.clone();
284 }
285
286 Ok(())
287 }
288
289 pub fn get_variable_by_key(&self, variable_key: ObjectRef) -> Option<Variable> {
291 self.variable_hash_map.get(&variable_key).cloned()
292 }
293
294 pub fn get_variable_by_name_and_parent(
297 &self,
298 variable_name: &VariableName,
299 parent_key: ObjectRef,
300 ) -> Option<Variable> {
301 let child_variables = self.variable_hash_map.values().filter(|child_variable| {
302 &child_variable.name == variable_name && child_variable.parent_key == parent_key
303 });
304
305 let mut first_iter = child_variables.clone();
307 let first = first_iter.next();
308 let more = first_iter.next().is_some();
309
310 if more {
311 let (last_index, last) = child_variables.enumerate().last().unwrap();
312 tracing::error!(
313 "Found {} variables with parent_key={:?} and name={}. Please report this as a bug.",
314 last_index + 1,
315 parent_key,
316 variable_name
317 );
318 Some(last.clone())
319 } else {
320 first.cloned()
321 }
322 }
323
324 pub fn get_variable_by_name(&self, variable_name: &VariableName) -> Option<Variable> {
328 let mut child_variables = self
329 .variable_hash_map
330 .values()
331 .filter(|child_variable| child_variable.name.eq(variable_name));
332
333 let first = child_variables.next();
334 let more = child_variables.next().is_some();
335
336 if more {
337 tracing::warn!(
338 "Found {} variables with name={}. Please report this as a bug.",
339 self.variable_hash_map.len(),
340 variable_name
341 );
342 }
343
344 first.cloned()
345 }
346
347 pub fn get_children(&self, parent_key: ObjectRef) -> impl Iterator<Item = &Variable> + Clone {
350 self.variable_hash_map
351 .values()
352 .filter(move |child_variable| child_variable.parent_key == parent_key)
353 }
354
355 pub fn has_children(&self, parent_variable: &Variable) -> bool {
357 self.get_children(parent_variable.variable_key)
358 .next()
359 .is_some()
360 }
361
362 pub fn adopt_grand_children(
369 &mut self,
370 parent_variable: &Variable,
371 obsolete_child_variable: &Variable,
372 ) -> Result<(), Error> {
373 if obsolete_child_variable.type_name == VariableType::Unknown
374 || obsolete_child_variable.variable_node_type != VariableNodeType::DoNotRecurse
375 {
376 self.variable_hash_map
378 .values_mut()
379 .filter(|search_variable| {
380 search_variable.parent_key == obsolete_child_variable.variable_key
381 })
382 .for_each(|grand_child| grand_child.parent_key = parent_variable.variable_key);
383 self.remove_cache_entry(obsolete_child_variable.variable_key)?;
385 }
386 Ok(())
387 }
388
389 pub fn remove_cache_entry_children(
391 &mut self,
392 parent_variable_key: ObjectRef,
393 ) -> Result<(), Error> {
394 let children = self
395 .variable_hash_map
396 .values()
397 .filter(|child_variable| child_variable.parent_key == parent_variable_key)
398 .cloned()
399 .collect::<Vec<Variable>>();
400
401 for child in children {
402 self.remove_cache_entry(child.variable_key)?;
403 }
404
405 Ok(())
406 }
407 pub fn remove_cache_entry(&mut self, variable_key: ObjectRef) -> Result<(), Error> {
409 self.remove_cache_entry_children(variable_key)?;
410 if self.variable_hash_map.remove(&variable_key).is_none() {
411 return Err(Error::Other(format!(
412 "Failed to remove a `VariableCache` entry with key: {:?}. Please report this as a bug.",
413 variable_key
414 )));
415 };
416 Ok(())
417 }
418 pub fn recurse_deferred_variables(
422 &mut self,
423 debug_info: &DebugInfo,
424 memory: &mut dyn MemoryInterface,
425 max_recursion_depth: usize,
426 frame_info: StackFrameInfo<'_>,
427 ) {
428 let mut parent_variable = self.root_variable().clone();
429
430 self.recurse_deferred_variables_internal(
431 debug_info,
432 memory,
433 &mut parent_variable,
434 max_recursion_depth,
435 0,
436 frame_info,
437 )
438 }
439
440 fn recurse_deferred_variables_internal(
441 &mut self,
442 debug_info: &DebugInfo,
443 memory: &mut dyn MemoryInterface,
444 parent_variable: &mut Variable,
445 max_recursion_depth: usize,
446 current_recursion_depth: usize,
447 frame_info: StackFrameInfo<'_>,
448 ) {
449 if current_recursion_depth >= max_recursion_depth {
450 return;
451 }
452
453 if debug_info
454 .cache_deferred_variables(self, memory, parent_variable, frame_info)
455 .is_err()
456 {
457 return;
458 };
459
460 let children: Vec<_> = self
461 .get_children(parent_variable.variable_key)
462 .cloned()
463 .collect();
464
465 for mut child in children {
466 self.recurse_deferred_variables_internal(
467 debug_info,
468 memory,
469 &mut child,
470 max_recursion_depth,
471 current_recursion_depth + 1,
472 frame_info,
473 );
474 }
475 }
476
477 pub fn get_discrete_memory_ranges(&self) -> Vec<Range<u64>> {
480 let mut memory_ranges: Vec<Range<u64>> = Vec::new();
481 for variable in self.variable_hash_map.values() {
482 if let Some(mut memory_range) = variable.memory_range() {
483 memory_range.align_to_32_bits();
486 if !memory_ranges.contains(&memory_range) {
487 memory_ranges.push(memory_range);
488 }
489 }
490
491 if matches!(variable.type_name, VariableType::Struct(ref name) if name == "&str") {
494 let children: Vec<_> = self.get_children(variable.variable_key).collect();
495 if !children.is_empty() {
496 let string_length = match children.iter().find(|child_variable| {
497 matches!(child_variable.name, VariableName::Named(ref name) if name == "length")
498 }) {
499 Some(string_length) => {
500 if string_length.is_valid() {
501 string_length.to_string(self).parse().unwrap_or(0_usize)
502 } else {
503 0_usize
504 }
505 }
506 None => 0_usize,
507 };
508 let string_location = match children.iter().find(|child_variable| {
509 matches!(child_variable.name, VariableName::Named(ref name ) if name == "data_ptr")
510 }) {
511 Some(location_value) => {
512 let mut child_variables =
513 self.get_children(location_value.variable_key);
514 if let Some(first_child) = child_variables.next() {
515 first_child
516 .memory_location
517 .memory_address()
518 .unwrap_or(0_u64)
519 } else {
520 0_u64
521 }
522 }
523 None => 0_u64,
524 };
525 if string_location == 0 || string_length == 0 {
526 tracing::warn!(
529 "Failed to find string location or length for variable: {:?}",
530 variable
531 );
532 } else {
533 let mut memory_range =
534 string_location..(string_location + string_length as u64);
535 memory_range.align_to_32_bits();
538 if !memory_ranges.contains(&memory_range) {
539 memory_ranges.push(memory_range);
540 }
541 }
542 }
543 }
544 }
545 memory_ranges
546 }
547}
548
549#[cfg(test)]
550mod test {
551 use termtree::Tree;
552
553 use crate::{
554 Variable, VariableCache, VariableLocation, VariableName, VariableNodeType, VariableType,
555 VariantRole,
556 };
557
558 fn show_tree(cache: &VariableCache) {
559 let tree = build_tree(cache, cache.root_variable());
560
561 println!("{}", tree);
562 }
563
564 fn build_tree(cache: &VariableCache, variable: &Variable) -> Tree<String> {
565 let mut entry = Tree::new(format!(
566 "{:?}: name={:?}, type={:?}, value={:?}",
567 variable.variable_key,
568 variable.name,
569 variable.type_name,
570 variable.to_string(cache)
571 ));
572
573 let children = cache.get_children(variable.variable_key);
574
575 for child in children {
576 entry.push(build_tree(cache, child));
577 }
578
579 entry
580 }
581
582 #[test]
583 fn static_cache() {
584 let c = VariableCache::new_static_cache();
585
586 let cache_variable = c.root_variable();
587
588 println!("{:#?}", cache_variable);
589
590 assert_eq!(cache_variable.name, VariableName::StaticScopeRoot);
592 assert_eq!(cache_variable.type_name, VariableType::Unknown);
593 assert_eq!(
594 cache_variable.variable_node_type,
595 VariableNodeType::UnitsLookup
596 );
597
598 assert_eq!(cache_variable.to_string(&c), "<unknown>");
599
600 assert_eq!(cache_variable.source_location, None);
601 assert_eq!(cache_variable.memory_location, VariableLocation::Unknown);
602 assert_eq!(cache_variable.byte_size, None);
603 assert_eq!(cache_variable.role, VariantRole::NonVariant);
604 }
605
606 #[test]
607 fn find_children() {
608 let mut cache = VariableCache::new_static_cache();
609 let root_key = cache.root_variable().variable_key;
610
611 let var_1 = cache.create_variable(root_key, None).unwrap();
612
613 let var_2 = cache.create_variable(root_key, None).unwrap();
614
615 let children: Vec<_> = cache.get_children(root_key).collect();
616
617 let expected_children = vec![&var_1, &var_2];
618
619 assert_eq!(children, expected_children);
620 }
621
622 #[test]
623 fn find_entry() {
624 let mut cache = VariableCache::new_static_cache();
625 let root_key = cache.root_variable().variable_key;
626
627 let var_1 = cache.create_variable(root_key, None).unwrap();
628
629 let _var_2 = cache.create_variable(root_key, None).unwrap();
630
631 assert_eq!(cache.get_variable_by_key(var_1.variable_key), Some(var_1));
632 }
633
634 fn build_test_tree() -> (VariableCache, Vec<Variable>) {
651 let mut cache = VariableCache::new_static_cache();
652 let root_key = cache.root_variable().variable_key;
653
654 let var_1 = cache.create_variable(root_key, None).unwrap();
655
656 let var_2 = cache.create_variable(root_key, None).unwrap();
657
658 let var_3 = cache.create_variable(var_2.variable_key, None).unwrap();
659
660 let var_4 = cache.create_variable(var_2.variable_key, None).unwrap();
661
662 let var_5 = cache.create_variable(var_3.variable_key, None).unwrap();
663
664 let var_6 = cache.create_variable(root_key, None).unwrap();
665
666 let var_7 = cache.create_variable(var_6.variable_key, None).unwrap();
667
668 assert_eq!(cache.len(), 8);
669
670 let variables = vec![
671 cache.root_variable().clone(),
672 var_1,
673 var_2,
674 var_3,
675 var_4,
676 var_5,
677 var_6,
678 var_7,
679 ];
680
681 (cache, variables)
682 }
683
684 #[test]
685 fn remove_entry() {
686 let (mut cache, vars) = build_test_tree();
687
688 cache.remove_cache_entry(vars[1].variable_key).unwrap();
690 assert!(cache.get_variable_by_key(vars[1].variable_key).is_none());
691 assert_eq!(cache.len(), 7);
692
693 cache.remove_cache_entry(vars[6].variable_key).unwrap();
695 assert!(cache.get_variable_by_key(vars[6].variable_key).is_none());
696 assert!(cache.get_variable_by_key(vars[7].variable_key).is_none());
697 assert_eq!(cache.len(), 5);
698
699 cache.remove_cache_entry(vars[2].variable_key).unwrap();
701 assert!(cache.get_variable_by_key(vars[2].variable_key).is_none());
702 assert!(cache.get_variable_by_key(vars[3].variable_key).is_none());
703 assert!(cache.get_variable_by_key(vars[4].variable_key).is_none());
704 assert!(cache.get_variable_by_key(vars[5].variable_key).is_none());
705 assert_eq!(cache.len(), 1);
706 }
707
708 #[test]
709 fn find_entry_by_name() {
710 let (mut cache, mut vars) = build_test_tree();
711 let non_unique_name = VariableName::Named("non_unique_name".to_string());
712 let unique_name = VariableName::Named("unique_name".to_string());
713
714 show_tree(&cache);
715
716 vars[3].name = non_unique_name.clone();
717 cache.update_variable(&vars[3]).unwrap();
718
719 show_tree(&cache);
720
721 vars[4].name = unique_name.clone();
722 cache.update_variable(&vars[4]).unwrap();
723
724 show_tree(&cache);
725
726 vars[6].name = non_unique_name.clone();
727 cache.update_variable(&vars[6]).unwrap();
728
729 show_tree(&cache);
730
731 assert!(vars[3].variable_key < vars[6].variable_key);
732
733 let var_3 = cache.get_variable_by_name(&non_unique_name).unwrap();
734 assert_eq!(&var_3, &vars[3]);
735
736 let var_4 = cache.get_variable_by_name(&unique_name).unwrap();
737 assert_eq!(&var_4, &vars[4]);
738
739 let var_6 = cache
740 .get_variable_by_name_and_parent(&non_unique_name, vars[6].parent_key)
741 .unwrap();
742 assert_eq!(&var_6, &vars[6]);
743 }
744
745 #[test]
746 fn adopt_grand_children() {
747 let (mut cache, mut vars) = build_test_tree();
748
749 cache.adopt_grand_children(&vars[2], &vars[3]).unwrap();
750
751 assert!(cache.get_variable_by_key(vars[3].variable_key).is_none());
752
753 let new_children: Vec<_> = cache.get_children(vars[2].variable_key).collect();
754
755 vars[5].parent_key = vars[2].variable_key;
756
757 assert_eq!(new_children, vec![&vars[4], &vars[5]]);
758 }
759}