1use crate::common::{DebugAddrBase, DebugAddrIndex, DebugAddrOffset, Encoding, SectionId};
2use crate::read::{Error, 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(
26 &self,
27 address_size: u8,
28 base: DebugAddrBase<R::Offset>,
29 index: DebugAddrIndex<R::Offset>,
30 ) -> Result<u64> {
31 let input = &mut self.section.clone();
32 input.skip(base.0)?;
33 input.skip(R::Offset::from_u64(
34 index.0.into_u64() * u64::from(address_size),
35 )?)?;
36 input.read_address(address_size)
37 }
38
39 pub fn headers(&self) -> AddrHeaderIter<R> {
43 AddrHeaderIter {
44 input: self.section.clone(),
45 offset: DebugAddrOffset(R::Offset::from_u8(0)),
46 }
47 }
48}
49
50impl<T> DebugAddr<T> {
51 pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R>
57 where
58 F: FnMut(&'a T) -> R,
59 {
60 borrow(&self.section).into()
61 }
62}
63
64impl<R> Section<R> for DebugAddr<R> {
65 fn id() -> SectionId {
66 SectionId::DebugAddr
67 }
68
69 fn reader(&self) -> &R {
70 &self.section
71 }
72}
73
74impl<R> From<R> for DebugAddr<R> {
75 fn from(section: R) -> Self {
76 DebugAddr { section }
77 }
78}
79
80#[derive(Clone, Debug)]
82pub struct AddrHeaderIter<R: Reader> {
83 input: R,
84 offset: DebugAddrOffset<R::Offset>,
85}
86
87impl<R: Reader> AddrHeaderIter<R> {
88 pub fn next(&mut self) -> Result<Option<AddrHeader<R>>> {
90 if self.input.is_empty() {
91 return Ok(None);
92 }
93
94 let len = self.input.len();
95 match AddrHeader::parse(&mut self.input, self.offset) {
96 Ok(header) => {
97 self.offset.0 += len - self.input.len();
98 Ok(Some(header))
99 }
100 Err(e) => {
101 self.input.empty();
102 Err(e)
103 }
104 }
105 }
106}
107
108#[cfg(feature = "fallible-iterator")]
109impl<R: Reader> fallible_iterator::FallibleIterator for AddrHeaderIter<R> {
110 type Item = AddrHeader<R>;
111 type Error = Error;
112
113 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
114 AddrHeaderIter::next(self)
115 }
116}
117
118impl<R: Reader> Iterator for AddrHeaderIter<R> {
119 type Item = Result<AddrHeader<R>>;
120
121 fn next(&mut self) -> Option<Self::Item> {
122 AddrHeaderIter::next(self).transpose()
123 }
124}
125
126#[derive(Debug, Clone, PartialEq, Eq)]
130pub struct AddrHeader<R, Offset = <R as Reader>::Offset>
131where
132 R: Reader<Offset = Offset>,
133 Offset: ReaderOffset,
134{
135 offset: DebugAddrOffset<Offset>,
136 encoding: Encoding,
137 length: Offset,
138 entries: R,
139}
140
141impl<R, Offset> AddrHeader<R, Offset>
142where
143 R: Reader<Offset = Offset>,
144 Offset: ReaderOffset,
145{
146 fn parse(input: &mut R, offset: DebugAddrOffset<Offset>) -> Result<Self> {
147 let (length, format) = input.read_initial_length()?;
148 let mut rest = input.split(length)?;
149
150 let version = rest.read_u16()?;
152 if version != 5 {
153 return Err(Error::UnknownVersion(u64::from(version)));
154 }
155
156 let address_size = rest.read_address_size()?;
157 let segment_size = rest.read_u8()?;
158 if segment_size != 0 {
159 return Err(Error::UnsupportedSegmentSize(segment_size));
160 }
161
162 let header_length = format.initial_length_size() + 2 + 1 + 1;
164
165 let tuple_length = address_size;
169 if tuple_length == 0 {
170 return Err(Error::UnsupportedAddressSize(address_size));
171 }
172 let padding = if header_length % tuple_length == 0 {
173 0
174 } else {
175 tuple_length - header_length % tuple_length
176 };
177 rest.skip(R::Offset::from_u8(padding))?;
178
179 let encoding = Encoding {
180 format,
181 version,
182 address_size,
183 };
184 Ok(AddrHeader {
185 offset,
186 encoding,
187 length,
188 entries: rest,
189 })
190 }
191
192 #[inline]
194 pub fn offset(&self) -> DebugAddrOffset<Offset> {
195 self.offset
196 }
197
198 #[inline]
200 pub fn length(&self) -> Offset {
201 self.length
202 }
203
204 #[inline]
206 pub fn encoding(&self) -> Encoding {
207 self.encoding
208 }
209
210 #[inline]
212 pub fn entries(&self) -> AddrEntryIter<R> {
213 AddrEntryIter {
214 input: self.entries.clone(),
215 encoding: self.encoding,
216 }
217 }
218}
219
220#[derive(Debug, Clone)]
222pub struct AddrEntryIter<R: Reader> {
223 input: R,
224 encoding: Encoding,
225}
226
227impl<R: Reader> AddrEntryIter<R> {
228 pub fn next(&mut self) -> Result<Option<u64>> {
235 if self.input.is_empty() {
236 return Ok(None);
237 }
238
239 match self.input.read_address(self.encoding.address_size) {
240 Ok(entry) => Ok(Some(entry)),
241 Err(e) => {
242 self.input.empty();
243 Err(e)
244 }
245 }
246 }
247}
248
249#[cfg(feature = "fallible-iterator")]
250impl<R: Reader> fallible_iterator::FallibleIterator for AddrEntryIter<R> {
251 type Item = u64;
252 type Error = Error;
253
254 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
255 AddrEntryIter::next(self)
256 }
257}
258
259impl<R: Reader> Iterator for AddrEntryIter<R> {
260 type Item = Result<u64>;
261
262 fn next(&mut self) -> Option<Self::Item> {
263 AddrEntryIter::next(self).transpose()
264 }
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270 use crate::read::EndianSlice;
271 use crate::test_util::GimliSectionMethods;
272 use crate::{Format, LittleEndian};
273 use test_assembler::{Endian, Label, LabelMaker, Section};
274
275 #[test]
276 fn test_get_address() {
277 for format in [Format::Dwarf32, Format::Dwarf64] {
278 for address_size in [4, 8] {
279 let zero = Label::new();
280 let length = Label::new();
281 let start = Label::new();
282 let first = Label::new();
283 let end = Label::new();
284 let mut section = Section::with_endian(Endian::Little)
285 .mark(&zero)
286 .initial_length(format, &length, &start)
287 .D16(5)
288 .D8(address_size)
289 .D8(0)
290 .mark(&first);
291 for i in 0..20 {
292 section = section.word(address_size, 1000 + i);
293 }
294 section = section.mark(&end);
295 length.set_const((&end - &start) as u64);
296
297 let section = section.get_contents().unwrap();
298 let debug_addr = DebugAddr::from(EndianSlice::new(§ion, LittleEndian));
299 let base = DebugAddrBase((&first - &zero) as usize);
300
301 assert_eq!(
302 debug_addr.get_address(address_size, base, DebugAddrIndex(0)),
303 Ok(1000)
304 );
305 assert_eq!(
306 debug_addr.get_address(address_size, base, DebugAddrIndex(19)),
307 Ok(1019)
308 );
309 }
310 }
311 }
312
313 #[test]
314 fn test_iterator() {
315 let length = Label::new();
316 let start = Label::new();
317 let end = Label::new();
318 let mut section = Section::with_endian(Endian::Little)
320 .initial_length(Format::Dwarf32, &length, &start)
321 .D16(5) .D8(4) .D8(0) .word(4, 0x12345678)
325 .word(4, 0xdeadbeef)
326 .mark(&end);
327 length.set_const((&end - &start) as u64);
328 let length = Label::new();
330 let start = Label::new();
331 let end = Label::new();
332 section = section
333 .initial_length(Format::Dwarf64, &length, &start)
334 .D16(5) .D8(8) .D8(0) .word(8, 0x123456789abcdef0)
338 .word(8, 0xdeadbeefdeadbeef)
339 .mark(&end);
340 length.set_const((&end - &start) as u64);
341 let section = section.get_contents().unwrap();
342 let debug_addr = DebugAddr::from(EndianSlice::new(§ion, LittleEndian));
343 let mut iter = debug_addr.headers();
344 let first_header = iter.next().unwrap().unwrap();
345 let first_encoding = first_header.encoding();
346 assert_eq!(first_encoding.address_size, 4);
347 assert_eq!(first_encoding.format, Format::Dwarf32);
348 assert_eq!(first_encoding.version, 5);
349 assert_eq!(first_header.length(), 12);
350 let mut first_entries = first_header.entries();
351 assert_eq!(first_entries.next(), Ok(Some(0x12345678)));
352 assert_eq!(first_entries.next(), Ok(Some(0xdeadbeef)));
353 assert_eq!(first_entries.next(), Ok(None));
354 let second_header = iter.next().unwrap().unwrap();
355 let second_encoding = second_header.encoding();
356 assert_eq!(second_encoding.address_size, 8);
357 assert_eq!(second_encoding.format, Format::Dwarf64);
358 assert_eq!(second_encoding.version, 5);
359 assert_eq!(second_header.length(), 20);
360 let mut second_entries = second_header.entries();
361 assert_eq!(second_entries.next(), Ok(Some(0x123456789abcdef0)));
362 assert_eq!(second_entries.next(), Ok(Some(0xdeadbeefdeadbeef)));
363 assert_eq!(second_entries.next(), Ok(None));
364 assert_eq!(iter.next(), Ok(None));
365 }
366}