Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/gimli-0.29.0/src/read/addr.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::common::{DebugAddrBase, DebugAddrIndex, SectionId};
2
use crate::read::{Reader, ReaderOffset, Result, Section};
3
4
/// The raw contents of the `.debug_addr` section.
5
#[derive(Debug, Default, Clone, Copy)]
6
pub struct DebugAddr<R> {
7
    section: R,
8
}
9
10
impl<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
0
    pub fn get_address(
29
0
        &self,
30
0
        address_size: u8,
31
0
        base: DebugAddrBase<R::Offset>,
32
0
        index: DebugAddrIndex<R::Offset>,
33
0
    ) -> Result<u64> {
34
0
        let input = &mut self.section.clone();
35
0
        input.skip(base.0)?;
36
0
        input.skip(R::Offset::from_u64(
37
0
            index.0.into_u64() * u64::from(address_size),
38
0
        )?)?;
39
0
        input.read_address(address_size)
40
0
    }
Unexecuted instantiation: <gimli::read::addr::DebugAddr<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::get_address
Unexecuted instantiation: <gimli::read::addr::DebugAddr<_>>::get_address
41
}
42
43
impl<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
0
    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R>
50
0
    where
51
0
        F: FnMut(&'a T) -> R,
52
0
    {
53
0
        borrow(&self.section).into()
54
0
    }
55
}
56
57
impl<R> Section<R> for DebugAddr<R> {
58
0
    fn id() -> SectionId {
59
0
        SectionId::DebugAddr
60
0
    }
Unexecuted instantiation: <gimli::read::addr::DebugAddr<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as gimli::read::Section<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::id
Unexecuted instantiation: <gimli::read::addr::DebugAddr<_> as gimli::read::Section<_>>::id
61
62
0
    fn reader(&self) -> &R {
63
0
        &self.section
64
0
    }
65
}
66
67
impl<R> From<R> for DebugAddr<R> {
68
0
    fn from(section: R) -> Self {
69
0
        DebugAddr { section }
70
0
    }
Unexecuted instantiation: <gimli::read::addr::DebugAddr<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>> as core::convert::From<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::from
Unexecuted instantiation: <gimli::read::addr::DebugAddr<_> as core::convert::From<_>>::from
71
}
72
73
#[cfg(test)]
74
mod 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
}