]> git.lizzy.rs Git - rust.git/blob - src/tools/miri/src/tag_gc.rs
Rollup merge of #101598 - chriswailes:sanitizers, r=nagisa,eholk
[rust.git] / src / tools / miri / src / tag_gc.rs
1 use crate::*;
2 use rustc_data_structures::fx::FxHashSet;
3
4 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
5 pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
6     fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> {
7         let this = self.eval_context_mut();
8         // No reason to do anything at all if stacked borrows is off.
9         if this.machine.stacked_borrows.is_none() {
10             return Ok(());
11         }
12
13         let mut tags = FxHashSet::default();
14
15         for thread in this.machine.threads.iter() {
16             if let Some(Scalar::Ptr(
17                 Pointer { provenance: Provenance::Concrete { sb, .. }, .. },
18                 _,
19             )) = thread.panic_payload
20             {
21                 tags.insert(sb);
22             }
23         }
24
25         self.find_tags_in_tls(&mut tags);
26         self.find_tags_in_memory(&mut tags);
27         self.find_tags_in_locals(&mut tags)?;
28
29         self.remove_unreachable_tags(tags);
30
31         Ok(())
32     }
33
34     fn find_tags_in_tls(&mut self, tags: &mut FxHashSet<SbTag>) {
35         let this = self.eval_context_mut();
36         this.machine.tls.iter(|scalar| {
37             if let Scalar::Ptr(Pointer { provenance: Provenance::Concrete { sb, .. }, .. }, _) =
38                 scalar
39             {
40                 tags.insert(*sb);
41             }
42         });
43     }
44
45     fn find_tags_in_memory(&mut self, tags: &mut FxHashSet<SbTag>) {
46         let this = self.eval_context_mut();
47         this.memory.alloc_map().iter(|it| {
48             for (_id, (_kind, alloc)) in it {
49                 for (_size, prov) in alloc.provenance().iter() {
50                     if let Provenance::Concrete { sb, .. } = prov {
51                         tags.insert(*sb);
52                     }
53                 }
54             }
55         });
56     }
57
58     fn find_tags_in_locals(&mut self, tags: &mut FxHashSet<SbTag>) -> InterpResult<'tcx> {
59         let this = self.eval_context_mut();
60         for frame in this.machine.threads.all_stacks().flatten() {
61             // Handle the return place of each frame
62             if let Ok(return_place) = frame.return_place.try_as_mplace() {
63                 if let Some(Provenance::Concrete { sb, .. }) = return_place.ptr.provenance {
64                     tags.insert(sb);
65                 }
66             }
67
68             for local in frame.locals.iter() {
69                 let LocalValue::Live(value) = local.value else {
70                 continue;
71             };
72                 match value {
73                     Operand::Immediate(Immediate::Scalar(Scalar::Ptr(ptr, _))) =>
74                         if let Provenance::Concrete { sb, .. } = ptr.provenance {
75                             tags.insert(sb);
76                         },
77                     Operand::Immediate(Immediate::ScalarPair(s1, s2)) => {
78                         if let Scalar::Ptr(ptr, _) = s1 {
79                             if let Provenance::Concrete { sb, .. } = ptr.provenance {
80                                 tags.insert(sb);
81                             }
82                         }
83                         if let Scalar::Ptr(ptr, _) = s2 {
84                             if let Provenance::Concrete { sb, .. } = ptr.provenance {
85                                 tags.insert(sb);
86                             }
87                         }
88                     }
89                     Operand::Indirect(MemPlace { ptr, .. }) => {
90                         if let Some(Provenance::Concrete { sb, .. }) = ptr.provenance {
91                             tags.insert(sb);
92                         }
93                     }
94                     Operand::Immediate(Immediate::Uninit)
95                     | Operand::Immediate(Immediate::Scalar(Scalar::Int(_))) => {}
96                 }
97             }
98         }
99
100         Ok(())
101     }
102
103     fn remove_unreachable_tags(&mut self, tags: FxHashSet<SbTag>) {
104         let this = self.eval_context_mut();
105         this.memory.alloc_map().iter(|it| {
106             for (_id, (_kind, alloc)) in it {
107                 alloc
108                     .extra
109                     .stacked_borrows
110                     .as_ref()
111                     .unwrap()
112                     .borrow_mut()
113                     .remove_unreachable_tags(&tags);
114             }
115         });
116     }
117 }