Skip to main content

gimli/read/
addr.rs

1use crate::common::{DebugAddrBase, DebugAddrIndex, DebugAddrOffset, Encoding, SectionId};
2use crate::read::{Error, Reader, ReaderOffset, Result, Section};
3
4/// The raw contents of the `.debug_addr` section.
5#[derive(Debug, Default, Clone, Copy)]
6pub struct DebugAddr<R> {
7    section: R,
8}
9
10impl<R: Reader> DebugAddr<R> {
11    /// Returns the address at the given `base` and `index`.
12    ///
13    /// A set of addresses in the `.debug_addr` section consists of a header
14    /// followed by a series of addresses.
15    ///
16    /// The `base` must be the `DW_AT_addr_base` value from the compilation unit DIE.
17    /// This is an offset that points to the first address following the header.
18    ///
19    /// The `index` is the value of a `DW_FORM_addrx` attribute.
20    ///
21    /// The `address_size` must be the size of the address for the compilation unit.
22    /// This value must also match the header. However, note that we do not parse the
23    /// header to validate this, since locating the header is unreliable, and the GNU
24    /// extensions do not emit it.
25    pub fn get_address(
26        &self,
27        address_size: u8,
28        base: DebugAddrBase<R::Offset>,
29        index: DebugAddrIndex<R::Offset>,
30    ) -> Result<u64> {
31        let input = &mut self.section.clone();
32        input.skip(base.0)?;
33        input.skip(R::Offset::from_u64(
34            index.0.into_u64() * u64::from(address_size),
35        )?)?;
36        input.read_address(address_size)
37    }
38
39    /// Iterate the sets of entries in the `.debug_addr` section.
40    ///
41    /// Each set of entries belongs to a single unit.
42    pub fn headers(&self) -> AddrHeaderIter<R> {
43        AddrHeaderIter {
44            input: self.section.clone(),
45            offset: DebugAddrOffset(R::Offset::from_u8(0)),
46        }
47    }
48}
49
50impl<T> DebugAddr<T> {
51    /// Create a `DebugAddr` section that references the data in `self`.
52    ///
53    /// This is useful when `R` implements `Reader` but `T` does not.
54    ///
55    /// Used by `DwarfSections::borrow`.
56    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R>
57    where
58        F: FnMut(&'a T) -> R,
59    {
60        borrow(&self.section).into()
61    }
62}
63
64impl<R> Section<R> for DebugAddr<R> {
65    fn id() -> SectionId {
66        SectionId::DebugAddr
67    }
68
69    fn reader(&self) -> &R {
70        &self.section
71    }
72}
73
74impl<R> From<R> for DebugAddr<R> {
75    fn from(section: R) -> Self {
76        DebugAddr { section }
77    }
78}
79
80/// An iterator over the headers of a `.debug_addr` section.
81#[derive(Clone, Debug)]
82pub struct AddrHeaderIter<R: Reader> {
83    input: R,
84    offset: DebugAddrOffset<R::Offset>,
85}
86
87impl<R: Reader> AddrHeaderIter<R> {
88    /// Advance the iterator to the next header.
89    pub fn next(&mut self) -> Result<Option<AddrHeader<R>>> {
90        if self.input.is_empty() {
91            return Ok(None);
92        }
93
94        let len = self.input.len();
95        match AddrHeader::parse(&mut self.input, self.offset) {
96            Ok(header) => {
97                self.offset.0 += len - self.input.len();
98                Ok(Some(header))
99            }
100            Err(e) => {
101                self.input.empty();
102                Err(e)
103            }
104        }
105    }
106}
107
108#[cfg(feature = "fallible-iterator")]
109impl<R: Reader> fallible_iterator::FallibleIterator for AddrHeaderIter<R> {
110    type Item = AddrHeader<R>;
111    type Error = Error;
112
113    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
114        AddrHeaderIter::next(self)
115    }
116}
117
118impl<R: Reader> Iterator for AddrHeaderIter<R> {
119    type Item = Result<AddrHeader<R>>;
120
121    fn next(&mut self) -> Option<Self::Item> {
122        AddrHeaderIter::next(self).transpose()
123    }
124}
125
126/// A header for a set of entries in the `.debug_addr` section.
127///
128/// These entries all belong to a single unit.
129#[derive(Debug, Clone, PartialEq, Eq)]
130pub struct AddrHeader<R, Offset = <R as Reader>::Offset>
131where
132    R: Reader<Offset = Offset>,
133    Offset: ReaderOffset,
134{
135    offset: DebugAddrOffset<Offset>,
136    encoding: Encoding,
137    length: Offset,
138    entries: R,
139}
140
141impl<R, Offset> AddrHeader<R, Offset>
142where
143    R: Reader<Offset = Offset>,
144    Offset: ReaderOffset,
145{
146    fn parse(input: &mut R, offset: DebugAddrOffset<Offset>) -> Result<Self> {
147        let (length, format) = input.read_initial_length()?;
148        let mut rest = input.split(length)?;
149
150        // Check the version. The DWARF 5 spec says that this is always 5.
151        let version = rest.read_u16()?;
152        if version != 5 {
153            return Err(Error::UnknownVersion(u64::from(version)));
154        }
155
156        let address_size = rest.read_address_size()?;
157        let segment_size = rest.read_u8()?;
158        if segment_size != 0 {
159            return Err(Error::UnsupportedSegmentSize(segment_size));
160        }
161
162        // unit_length + version + address_size + segment_size
163        let header_length = format.initial_length_size() + 2 + 1 + 1;
164
165        // The first tuple following the header in each set begins at an offset that is
166        // a multiple of the size of a single tuple (that is, the size of a segment,
167        // which must be zero, and an address).
168        let tuple_length = address_size;
169        if tuple_length == 0 {
170            return Err(Error::UnsupportedAddressSize(address_size));
171        }
172        let padding = if header_length % tuple_length == 0 {
173            0
174        } else {
175            tuple_length - header_length % tuple_length
176        };
177        rest.skip(R::Offset::from_u8(padding))?;
178
179        let encoding = Encoding {
180            format,
181            version,
182            address_size,
183        };
184        Ok(AddrHeader {
185            offset,
186            encoding,
187            length,
188            entries: rest,
189        })
190    }
191
192    /// Return the offset of this header within the `.debug_addr` section.
193    #[inline]
194    pub fn offset(&self) -> DebugAddrOffset<Offset> {
195        self.offset
196    }
197
198    /// Return the length of this set of entries, including the header.
199    #[inline]
200    pub fn length(&self) -> Offset {
201        self.length
202    }
203
204    /// Return the encoding parameters for this set of entries.
205    #[inline]
206    pub fn encoding(&self) -> Encoding {
207        self.encoding
208    }
209
210    /// Return the address entries in this set.
211    #[inline]
212    pub fn entries(&self) -> AddrEntryIter<R> {
213        AddrEntryIter {
214            input: self.entries.clone(),
215            encoding: self.encoding,
216        }
217    }
218}
219
220/// An iterator over the addresses from a `.debug_addr` section.
221#[derive(Debug, Clone)]
222pub struct AddrEntryIter<R: Reader> {
223    input: R,
224    encoding: Encoding,
225}
226
227impl<R: Reader> AddrEntryIter<R> {
228    /// Advance the iterator and return the next address.
229    ///
230    /// Returns the newly parsed address as `Ok(Some(addr))`. Returns `Ok(None)`
231    /// when iteration is complete and all addresses have already been parsed and
232    /// yielded. If an error occurs while parsing the next address, then this error
233    /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`.
234    pub fn next(&mut self) -> Result<Option<u64>> {
235        if self.input.is_empty() {
236            return Ok(None);
237        }
238
239        match self.input.read_address(self.encoding.address_size) {
240            Ok(entry) => Ok(Some(entry)),
241            Err(e) => {
242                self.input.empty();
243                Err(e)
244            }
245        }
246    }
247}
248
249#[cfg(feature = "fallible-iterator")]
250impl<R: Reader> fallible_iterator::FallibleIterator for AddrEntryIter<R> {
251    type Item = u64;
252    type Error = Error;
253
254    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
255        AddrEntryIter::next(self)
256    }
257}
258
259impl<R: Reader> Iterator for AddrEntryIter<R> {
260    type Item = Result<u64>;
261
262    fn next(&mut self) -> Option<Self::Item> {
263        AddrEntryIter::next(self).transpose()
264    }
265}
266
267#[cfg(test)]
268mod tests {
269    use super::*;
270    use crate::read::EndianSlice;
271    use crate::test_util::GimliSectionMethods;
272    use crate::{Format, LittleEndian};
273    use test_assembler::{Endian, Label, LabelMaker, Section};
274
275    #[test]
276    fn test_get_address() {
277        for format in [Format::Dwarf32, Format::Dwarf64] {
278            for address_size in [4, 8] {
279                let zero = Label::new();
280                let length = Label::new();
281                let start = Label::new();
282                let first = Label::new();
283                let end = Label::new();
284                let mut section = Section::with_endian(Endian::Little)
285                    .mark(&zero)
286                    .initial_length(format, &length, &start)
287                    .D16(5)
288                    .D8(address_size)
289                    .D8(0)
290                    .mark(&first);
291                for i in 0..20 {
292                    section = section.word(address_size, 1000 + i);
293                }
294                section = section.mark(&end);
295                length.set_const((&end - &start) as u64);
296
297                let section = section.get_contents().unwrap();
298                let debug_addr = DebugAddr::from(EndianSlice::new(&section, LittleEndian));
299                let base = DebugAddrBase((&first - &zero) as usize);
300
301                assert_eq!(
302                    debug_addr.get_address(address_size, base, DebugAddrIndex(0)),
303                    Ok(1000)
304                );
305                assert_eq!(
306                    debug_addr.get_address(address_size, base, DebugAddrIndex(19)),
307                    Ok(1019)
308                );
309            }
310        }
311    }
312
313    #[test]
314    fn test_iterator() {
315        let length = Label::new();
316        let start = Label::new();
317        let end = Label::new();
318        // First CU.
319        let mut section = Section::with_endian(Endian::Little)
320            .initial_length(Format::Dwarf32, &length, &start)
321            .D16(5) // Version
322            .D8(4) // Address size
323            .D8(0) // Segment size
324            .word(4, 0x12345678)
325            .word(4, 0xdeadbeef)
326            .mark(&end);
327        length.set_const((&end - &start) as u64);
328        // Second CU.
329        let length = Label::new();
330        let start = Label::new();
331        let end = Label::new();
332        section = section
333            .initial_length(Format::Dwarf64, &length, &start)
334            .D16(5) // Version
335            .D8(8) // Address size
336            .D8(0) // Segment size
337            .word(8, 0x123456789abcdef0)
338            .word(8, 0xdeadbeefdeadbeef)
339            .mark(&end);
340        length.set_const((&end - &start) as u64);
341        let section = section.get_contents().unwrap();
342        let debug_addr = DebugAddr::from(EndianSlice::new(&section, LittleEndian));
343        let mut iter = debug_addr.headers();
344        let first_header = iter.next().unwrap().unwrap();
345        let first_encoding = first_header.encoding();
346        assert_eq!(first_encoding.address_size, 4);
347        assert_eq!(first_encoding.format, Format::Dwarf32);
348        assert_eq!(first_encoding.version, 5);
349        assert_eq!(first_header.length(), 12);
350        let mut first_entries = first_header.entries();
351        assert_eq!(first_entries.next(), Ok(Some(0x12345678)));
352        assert_eq!(first_entries.next(), Ok(Some(0xdeadbeef)));
353        assert_eq!(first_entries.next(), Ok(None));
354        let second_header = iter.next().unwrap().unwrap();
355        let second_encoding = second_header.encoding();
356        assert_eq!(second_encoding.address_size, 8);
357        assert_eq!(second_encoding.format, Format::Dwarf64);
358        assert_eq!(second_encoding.version, 5);
359        assert_eq!(second_header.length(), 20);
360        let mut second_entries = second_header.entries();
361        assert_eq!(second_entries.next(), Ok(Some(0x123456789abcdef0)));
362        assert_eq!(second_entries.next(), Ok(Some(0xdeadbeefdeadbeef)));
363        assert_eq!(second_entries.next(), Ok(None));
364        assert_eq!(iter.next(), Ok(None));
365    }
366}