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 /// ## 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 /// ```
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
67impl<R> Section<R> for DebugAddr<R> {
68 fn id() -> SectionId {
69 SectionId::DebugAddr
70 }
71
72 fn reader(&self) -> &R {
73 &self.section
74 }
75}
76
77impl<R> From<R> for DebugAddr<R> {
78 fn from(section: R) -> Self {
79 DebugAddr { section }
80 }
81}
82
83#[cfg(test)]
84mod 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]
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