Skip to main content

object/read/macho/
function_starts.rs

1use crate::read::{Bytes, ReadError, Result};
2
3/// Iterator over the function starts in a `LC_FUNCTION_STARTS` load command.
4#[derive(Debug, Default, Clone, Copy)]
5pub struct FunctionStartsIterator<'data> {
6    data: Bytes<'data>,
7    addr: u64,
8}
9
10impl<'data> FunctionStartsIterator<'data> {
11    pub(super) fn new(data: &'data [u8], addr: u64) -> Self {
12        FunctionStartsIterator {
13            data: Bytes(data),
14            addr,
15        }
16    }
17}
18
19impl<'data> FunctionStartsIterator<'data> {
20    /// Returns the next function start address.
21    pub fn next(&mut self) -> Result<Option<u64>> {
22        if self.data.is_empty() {
23            return Ok(None);
24        }
25
26        let result = self.parse();
27        if result.is_err() {
28            self.data = Bytes(&[]);
29        }
30        result
31    }
32
33    fn parse(&mut self) -> Result<Option<u64>> {
34        let delta = self
35            .data
36            .read_uleb128()
37            .read_error("Invalid ULEB128 in LC_FUNCTION_STARTS")?;
38        if delta == 0 {
39            self.data = Bytes(&[]);
40            return Ok(None);
41        }
42
43        self.addr = self
44            .addr
45            .checked_add(delta)
46            .read_error("Address overflow in LC_FUNCTION_STARTS")?;
47        Ok(Some(self.addr))
48    }
49}
50
51impl<'data> Iterator for FunctionStartsIterator<'data> {
52    type Item = Result<u64>;
53
54    fn next(&mut self) -> Option<Self::Item> {
55        self.next().transpose()
56    }
57}