gimli/read/
addr.rs

1use crate::common::{DebugAddrBase, DebugAddrIndex, SectionId};
2use crate::read::{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    // TODO: add an iterator over the sets of addresses in the section.
12    // This is not needed for common usage of the section though.
13
14    /// Returns the address at the given `base` and `index`.
15    ///
16    /// A set of addresses in the `.debug_addr` section consists of a header
17    /// followed by a series of addresses.
18    ///
19    /// The `base` must be the `DW_AT_addr_base` value from the compilation unit DIE.
20    /// This is an offset that points to the first address following the header.
21    ///
22    /// The `index` is the value of a `DW_FORM_addrx` attribute.
23    ///
24    /// The `address_size` must be the size of the address for the compilation unit.
25    /// This value must also match the header. However, note that we do not parse the
26    /// header to validate this, since locating the header is unreliable, and the GNU
27    /// extensions do not emit it.
28    pub fn get_address(
29        &self,
30        address_size: u8,
31        base: DebugAddrBase<R::Offset>,
32        index: DebugAddrIndex<R::Offset>,
33    ) -> Result<u64> {
34        let input = &mut self.section.clone();
35        input.skip(base.0)?;
36        input.skip(R::Offset::from_u64(
37            index.0.into_u64() * u64::from(address_size),
38        )?)?;
39        input.read_address(address_size)
40    }
41}
42
43impl<T> DebugAddr<T> {
44    /// Create a `DebugAddr` section that references the data in `self`.
45    ///
46    /// This is useful when `R` implements `Reader` but `T` does not.
47    ///
48    /// Used by `DwarfSections::borrow`.
49    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R>
50    where
51        F: FnMut(&'a T) -> R,
52    {
53        borrow(&self.section).into()
54    }
55}
56
57impl<R> Section<R> for DebugAddr<R> {
58    fn id() -> SectionId {
59        SectionId::DebugAddr
60    }
61
62    fn reader(&self) -> &R {
63        &self.section
64    }
65}
66
67impl<R> From<R> for DebugAddr<R> {
68    fn from(section: R) -> Self {
69        DebugAddr { section }
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76    use crate::read::EndianSlice;
77    use crate::test_util::GimliSectionMethods;
78    use crate::{Format, LittleEndian};
79    use test_assembler::{Endian, Label, LabelMaker, Section};
80
81    #[test]
82    fn test_get_address() {
83        for format in [Format::Dwarf32, Format::Dwarf64] {
84            for address_size in [4, 8] {
85                let zero = Label::new();
86                let length = Label::new();
87                let start = Label::new();
88                let first = Label::new();
89                let end = Label::new();
90                let mut section = Section::with_endian(Endian::Little)
91                    .mark(&zero)
92                    .initial_length(format, &length, &start)
93                    .D16(5)
94                    .D8(address_size)
95                    .D8(0)
96                    .mark(&first);
97                for i in 0..20 {
98                    section = section.word(address_size, 1000 + i);
99                }
100                section = section.mark(&end);
101                length.set_const((&end - &start) as u64);
102
103                let section = section.get_contents().unwrap();
104                let debug_addr = DebugAddr::from(EndianSlice::new(&section, LittleEndian));
105                let base = DebugAddrBase((&first - &zero) as usize);
106
107                assert_eq!(
108                    debug_addr.get_address(address_size, base, DebugAddrIndex(0)),
109                    Ok(1000)
110                );
111                assert_eq!(
112                    debug_addr.get_address(address_size, base, DebugAddrIndex(19)),
113                    Ok(1019)
114                );
115            }
116        }
117    }
118}