stackdump_core/
register_data.rs

1//! Module containing the definitions for register data
2
3use arrayvec::ArrayVec;
4use core::fmt::Debug;
5use serde::{Deserialize, Serialize};
6
7/// The identifier that is being used in the byte iterator to be able to differentiate between register data and memory regions
8pub const REGISTER_DATA_IDENTIFIER: u8 = 0x02;
9
10/// A trait for reading registers from a register collection
11///
12/// This
13pub trait RegisterData<RB: funty::Integral>: Debug {
14    /// Try to get the value of the given register.
15    /// Returns None if the register is not present in this collection.
16    fn register(&self, register: gimli::Register) -> Option<RB>;
17    /// Try to get a reference to the given register.
18    /// Returns None if the register is not present in this collection.
19    fn register_ref(&self, register: gimli::Register) -> Option<&RB>;
20    /// Try to get a mutable reference to the given register.
21    /// Returns None if the register is not present in this collection.
22    fn register_mut(&mut self, register: gimli::Register) -> Option<&mut RB>;
23}
24
25/// A collection of registers, backed by a stack allocated array.
26///
27/// SIZE is the maximum amount of registers this collection can hold.
28#[derive(Clone, Debug, Deserialize, Serialize, Default, PartialEq, Eq)]
29pub struct ArrayRegisterData<const SIZE: usize, RB> {
30    /// The DWARF register number of the first register
31    starting_register_number: u16,
32    /// The values of the registers.
33    /// The first value is of the register that is correlated with `starting_register_number`.
34    /// Must be contiguous.
35    registers: ArrayVec<RB, SIZE>,
36}
37
38impl<const SIZE: usize, RB: funty::Integral> ArrayRegisterData<SIZE, RB> {
39    /// Create a new register collection backed by an array
40    ///
41    /// - The registers must be sequential according to the dwarf register numbers.
42    /// - All registers that are in the collection must have their true value.
43    pub fn new(starting_register: gimli::Register, registers: ArrayVec<RB, SIZE>) -> Self {
44        Self {
45            starting_register_number: starting_register.0,
46            registers,
47        }
48    }
49
50    /// Get a byte iterator for this collection.
51    ///
52    /// This iterator can be used to store the collection as bytes or to stream over a network.
53    /// The iterated bytes include the length so that if you use the FromIterator implementation,
54    /// it consumes only the bytes that are part of the collection.
55    /// This means you can chain multiple of these iterators after each other.
56    ///
57    /// ```
58    /// use arrayvec::ArrayVec;
59    /// use stackdump_core::register_data::{ArrayRegisterData, RegisterData};
60    ///
61    /// let regs1 = ArrayRegisterData::<4, u32>::new(stackdump_core::gimli::Arm::R0, ArrayVec::from([1, 2, 3, 4]));
62    /// let regs2 = ArrayRegisterData::<4, u32>::new(stackdump_core::gimli::Arm::R0, ArrayVec::from([5, 6, 7, 8]));
63    ///
64    /// let mut intermediate_buffer = Vec::new();
65    ///
66    /// intermediate_buffer.extend(regs1.bytes());
67    /// intermediate_buffer.extend(regs2.bytes());
68    ///
69    /// let mut intermediate_iter = intermediate_buffer.iter().copied();
70    ///
71    /// assert_eq!(regs1, ArrayRegisterData::<4, u32>::from_iter(&mut intermediate_iter));
72    /// assert_eq!(regs2, ArrayRegisterData::<4, u32>::from_iter(&mut intermediate_iter));
73    /// ```
74    pub fn bytes(&self) -> RegisterDataBytesIterator<'_, RB> {
75        RegisterDataBytesIterator {
76            index: 0,
77            starting_register_number: self.starting_register_number,
78            registers: &self.registers,
79        }
80    }
81}
82
83impl<const SIZE: usize, RB: funty::Integral> RegisterData<RB> for ArrayRegisterData<SIZE, RB> {
84    fn register(&self, register: gimli::Register) -> Option<RB> {
85        let local_register_index = register.0.checked_sub(self.starting_register_number)?;
86        self.registers.get(local_register_index as usize).copied()
87    }
88    fn register_ref(&self, register: gimli::Register) -> Option<&RB> {
89        let local_register_index = register.0.checked_sub(self.starting_register_number)?;
90        self.registers.get(local_register_index as usize)
91    }
92    fn register_mut(&mut self, register: gimli::Register) -> Option<&mut RB> {
93        let local_register_index = register.0.checked_sub(self.starting_register_number)?;
94        self.registers.get_mut(local_register_index as usize)
95    }
96}
97
98impl<const SIZE: usize, RB> FromIterator<u8> for ArrayRegisterData<SIZE, RB>
99where
100    RB: funty::Integral,
101    RB::Bytes: for<'a> TryFrom<&'a [u8]>,
102{
103    fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
104        // Get the iterator. We assume that it is in the same format as the bytes function outputs
105        let mut iter = iter.into_iter();
106
107        assert_eq!(
108            iter.next().unwrap(),
109            REGISTER_DATA_IDENTIFIER,
110            "The given iterator is not for register data"
111        );
112
113        // First the starting number is encoded
114        let starting_register_number =
115            u16::from_le_bytes([iter.next().unwrap(), iter.next().unwrap()]);
116
117        // Second is how many registers there are
118        let register_count = u16::from_le_bytes([iter.next().unwrap(), iter.next().unwrap()]);
119
120        // Create the buffer we're storing the registers in
121        let mut registers = ArrayVec::new();
122
123        // We process everything byte-by-byte generically so every register has an unknown length
124        // So we need to store the bytes temporarily until we have enough to fully read the bytes as a register
125        let register_size = core::mem::size_of::<RB>();
126        let mut register_bytes_buffer = ArrayVec::<u8, 16>::new();
127
128        for byte in (0..register_count as usize * register_size).map(|_| iter.next().unwrap()) {
129            register_bytes_buffer.push(byte);
130
131            if register_bytes_buffer.len() == register_size {
132                registers.push(RB::from_le_bytes(
133                    register_bytes_buffer
134                        .as_slice()
135                        .try_into()
136                        .unwrap_or_else(|_| panic!()),
137                ));
138                register_bytes_buffer = ArrayVec::new();
139            }
140        }
141
142        assert!(register_bytes_buffer.is_empty());
143
144        Self {
145            starting_register_number,
146            registers,
147        }
148    }
149}
150
151/// A collection of registers, backed by a vec.
152#[cfg(feature = "std")]
153#[derive(Clone, Debug, Deserialize, Serialize, Default, PartialEq, Eq)]
154pub struct VecRegisterData<RB> {
155    /// The DWARF register number of the first register
156    starting_register_number: u16,
157    /// The values of the registers.
158    /// The first value is of the register that is correlated with `starting_register_number`.
159    /// Must be contiguous.
160    registers: Vec<RB>,
161}
162
163#[cfg(feature = "std")]
164impl<RB: funty::Integral> VecRegisterData<RB> {
165    /// Create a new register collection backed by a vec
166    ///
167    /// - The registers must be sequential according to the dwarf register numbers.
168    /// - All registers that are in the collection must have their true value.
169    pub fn new(starting_register: gimli::Register, registers: Vec<RB>) -> Self {
170        Self {
171            starting_register_number: starting_register.0,
172            registers,
173        }
174    }
175
176    /// Get a byte iterator for this collection.
177    ///
178    /// This iterator can be used to store the collection as bytes or to stream over a network.
179    /// The iterated bytes include the length so that if you use the FromIterator implementation,
180    /// it consumes only the bytes that are part of the collection.
181    /// This means you can chain multiple of these iterators after each other.
182    ///
183    /// ```
184    /// use arrayvec::ArrayVec;
185    /// use stackdump_core::register_data::{ArrayRegisterData, RegisterData};
186    ///
187    /// let regs1 = ArrayRegisterData::<4, u32>::new(stackdump_core::gimli::Arm::R0, ArrayVec::from([1, 2, 3, 4]));
188    /// let regs2 = ArrayRegisterData::<4, u32>::new(stackdump_core::gimli::Arm::R0, ArrayVec::from([5, 6, 7, 8]));
189    ///
190    /// let mut intermediate_buffer = Vec::new();
191    ///
192    /// intermediate_buffer.extend(regs1.bytes());
193    /// intermediate_buffer.extend(regs2.bytes());
194    ///
195    /// let mut intermediate_iter = intermediate_buffer.iter().copied();
196    ///
197    /// assert_eq!(regs1, ArrayRegisterData::<4, u32>::from_iter(&mut intermediate_iter));
198    /// assert_eq!(regs2, ArrayRegisterData::<4, u32>::from_iter(&mut intermediate_iter));
199    /// ```
200    pub fn bytes(&self) -> RegisterDataBytesIterator<'_, RB> {
201        RegisterDataBytesIterator {
202            index: 0,
203            starting_register_number: self.starting_register_number,
204            registers: &self.registers,
205        }
206    }
207}
208
209#[cfg(feature = "std")]
210impl<RB: funty::Integral> RegisterData<RB> for VecRegisterData<RB> {
211    fn register(&self, register: gimli::Register) -> Option<RB> {
212        let local_register_index = register.0.checked_sub(self.starting_register_number)?;
213        self.registers.get(local_register_index as usize).copied()
214    }
215    fn register_ref(&self, register: gimli::Register) -> Option<&RB> {
216        let local_register_index = register.0.checked_sub(self.starting_register_number)?;
217        self.registers.get(local_register_index as usize)
218    }
219    fn register_mut(&mut self, register: gimli::Register) -> Option<&mut RB> {
220        let local_register_index = register.0.checked_sub(self.starting_register_number)?;
221        self.registers.get_mut(local_register_index as usize)
222    }
223}
224
225#[cfg(feature = "std")]
226impl<RB> FromIterator<u8> for VecRegisterData<RB>
227where
228    RB: funty::Integral,
229    RB::Bytes: for<'a> TryFrom<&'a [u8]>,
230{
231    fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
232        let mut iter = iter.into_iter();
233
234        assert_eq!(
235            iter.next().unwrap(),
236            REGISTER_DATA_IDENTIFIER,
237            "The given iterator is not for register data"
238        );
239
240        let starting_register_number =
241            u16::from_le_bytes([iter.next().unwrap(), iter.next().unwrap()]);
242
243        let register_count = u16::from_le_bytes([iter.next().unwrap(), iter.next().unwrap()]);
244
245        let mut registers = Vec::new();
246        let register_size = core::mem::size_of::<RB>();
247
248        let mut register_bytes_buffer = ArrayVec::<u8, 16>::new();
249
250        for byte in (0..register_count as usize * register_size).map(|_| iter.next().unwrap()) {
251            register_bytes_buffer.push(byte);
252
253            if register_bytes_buffer.len() == register_size {
254                registers.push(RB::from_le_bytes(
255                    register_bytes_buffer
256                        .as_slice()
257                        .try_into()
258                        .unwrap_or_else(|_| panic!()),
259                ));
260                register_bytes_buffer.clear();
261            }
262        }
263
264        assert!(register_bytes_buffer.is_empty());
265
266        Self {
267            starting_register_number,
268            registers,
269        }
270    }
271}
272
273/// An iterator that iterates over the serialized bytes of register data
274pub struct RegisterDataBytesIterator<'a, RB: funty::Integral> {
275    starting_register_number: u16,
276    registers: &'a [RB],
277    index: usize,
278}
279
280impl<'a, RB: funty::Integral> Iterator for RegisterDataBytesIterator<'a, RB> {
281    type Item = u8;
282
283    fn next(&mut self) -> Option<Self::Item> {
284        match self.index {
285            0 => {
286                self.index += 1;
287                Some(REGISTER_DATA_IDENTIFIER)
288            }
289            index @ 1..=2 => {
290                self.index += 1;
291                Some(self.starting_register_number.to_le_bytes()[index - 1])
292            }
293            index @ 3..=4 => {
294                self.index += 1;
295                Some((self.registers.len() as u16).to_le_bytes()[index - 3])
296            }
297            index => {
298                self.index += 1;
299
300                let index = index - 5;
301                let register_size = core::mem::size_of::<RB>();
302                let register_index = index / register_size;
303                let byte_index = index % register_size;
304
305                // We get the number in forced little endian format
306                let le_register = self.registers.get(register_index)?.to_le();
307                // We can take a slice to it because we checked the length and we know it's in little endian
308                let register_slice = unsafe {
309                    core::slice::from_raw_parts(
310                        &le_register as *const RB as *const u8,
311                        register_size,
312                    )
313                };
314                Some(register_slice[byte_index])
315            }
316        }
317    }
318
319    fn size_hint(&self) -> (usize, Option<usize>) {
320        let remaining_length = 5 + core::mem::size_of_val(self.registers) - self.index;
321        (remaining_length, Some(remaining_length))
322    }
323}
324
325impl<'a, RB: funty::Integral> ExactSizeIterator for RegisterDataBytesIterator<'a, RB> {}
326
327#[cfg(test)]
328mod tests {
329    use super::*;
330
331    #[test]
332    fn iterator() {
333        let data = VecRegisterData::new(gimli::Arm::S12, vec![1u32, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
334        let copied_data = VecRegisterData::from_iter(data.bytes());
335
336        assert_eq!(data, copied_data);
337    }
338
339    #[test]
340    fn iterator_length() {
341        let data = VecRegisterData::new(gimli::Arm::S12, vec![1u32, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
342        let iter = data.bytes();
343
344        assert_eq!(iter.len(), iter.count());
345
346        let mut iter = data.bytes();
347        iter.nth(10).unwrap();
348        assert_eq!(iter.len(), iter.count());
349    }
350}