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.
get_address( &self, address_size: u8, base: DebugAddrBase<R::Offset>, index: DebugAddrIndex<R::Offset>, ) -> Result<u64>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 
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     /// ## Example Usage
49     ///
50     /// ```rust,no_run
51     /// # let load_section = || unimplemented!();
52     /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
53     /// let owned_section: gimli::DebugAddr<Vec<u8>> = load_section();
54     /// // Create a reference to the DWARF section.
55     /// let section = owned_section.borrow(|section| {
56     ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
57     /// });
58     /// ```
borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R> where F: FnMut(&'a T) -> R,59     pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R>
60     where
61         F: FnMut(&'a T) -> R,
62     {
63         borrow(&self.section).into()
64     }
65 }
66 
67 impl<R> Section<R> for DebugAddr<R> {
id() -> SectionId68     fn id() -> SectionId {
69         SectionId::DebugAddr
70     }
71 
reader(&self) -> &R72     fn reader(&self) -> &R {
73         &self.section
74     }
75 }
76 
77 impl<R> From<R> for DebugAddr<R> {
from(section: R) -> Self78     fn from(section: R) -> Self {
79         DebugAddr { section }
80     }
81 }
82 
83 #[cfg(test)]
84 mod tests {
85     use super::*;
86     use crate::read::EndianSlice;
87     use crate::test_util::GimliSectionMethods;
88     use crate::{Format, LittleEndian};
89     use test_assembler::{Endian, Label, LabelMaker, Section};
90 
91     #[test]
test_get_address()92     fn test_get_address() {
93         for format in vec![Format::Dwarf32, Format::Dwarf64] {
94             for address_size in vec![4, 8] {
95                 let zero = Label::new();
96                 let length = Label::new();
97                 let start = Label::new();
98                 let first = Label::new();
99                 let end = Label::new();
100                 let mut section = Section::with_endian(Endian::Little)
101                     .mark(&zero)
102                     .initial_length(format, &length, &start)
103                     .D16(5)
104                     .D8(address_size)
105                     .D8(0)
106                     .mark(&first);
107                 for i in 0..20 {
108                     section = section.word(address_size, 1000 + i);
109                 }
110                 section = section.mark(&end);
111                 length.set_const((&end - &start) as u64);
112 
113                 let section = section.get_contents().unwrap();
114                 let debug_addr = DebugAddr::from(EndianSlice::new(&section, LittleEndian));
115                 let base = DebugAddrBase((&first - &zero) as usize);
116 
117                 assert_eq!(
118                     debug_addr.get_address(address_size, base, DebugAddrIndex(0)),
119                     Ok(1000)
120                 );
121                 assert_eq!(
122                     debug_addr.get_address(address_size, base, DebugAddrIndex(19)),
123                     Ok(1019)
124                 );
125             }
126         }
127     }
128 }
129