1use crate::common::{DebugAddrBase, DebugAddrIndex, SectionId};
2use crate::read::{Reader, ReaderOffset, Result, Section};
3
4#[derive(Debug, Default, Clone, Copy)]
6pub struct DebugAddr<R> {
7 section: R,
8}
9
10impl<R: Reader> DebugAddr<R> {
11 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 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(§ion, 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}