1use crate::common::{DebugArangesOffset, DebugInfoOffset, Encoding, SectionId};
2use crate::endianity::Endianity;
3use crate::read::{
4    EndianSlice, Error, Range, Reader, ReaderAddress, ReaderOffset, Result, Section,
5};
6
7#[derive(Debug, Default, Clone, Copy)]
10pub struct DebugAranges<R> {
11    section: R,
12}
13
14impl<'input, Endian> DebugAranges<EndianSlice<'input, Endian>>
15where
16    Endian: Endianity,
17{
18    pub fn new(section: &'input [u8], endian: Endian) -> Self {
34        DebugAranges {
35            section: EndianSlice::new(section, endian),
36        }
37    }
38}
39
40impl<R: Reader> DebugAranges<R> {
41    pub fn headers(&self) -> ArangeHeaderIter<R> {
45        ArangeHeaderIter {
46            input: self.section.clone(),
47            offset: DebugArangesOffset(R::Offset::from_u8(0)),
48        }
49    }
50
51    pub fn header(&self, offset: DebugArangesOffset<R::Offset>) -> Result<ArangeHeader<R>> {
53        let mut input = self.section.clone();
54        input.skip(offset.0)?;
55        ArangeHeader::parse(&mut input, offset)
56    }
57}
58
59impl<T> DebugAranges<T> {
60    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges<R>
66    where
67        F: FnMut(&'a T) -> R,
68    {
69        borrow(&self.section).into()
70    }
71}
72
73impl<R> Section<R> for DebugAranges<R> {
74    fn id() -> SectionId {
75        SectionId::DebugAranges
76    }
77
78    fn reader(&self) -> &R {
79        &self.section
80    }
81}
82
83impl<R> From<R> for DebugAranges<R> {
84    fn from(section: R) -> Self {
85        DebugAranges { section }
86    }
87}
88
89#[derive(Clone, Debug)]
91pub struct ArangeHeaderIter<R: Reader> {
92    input: R,
93    offset: DebugArangesOffset<R::Offset>,
94}
95
96impl<R: Reader> ArangeHeaderIter<R> {
97    pub fn next(&mut self) -> Result<Option<ArangeHeader<R>>> {
99        if self.input.is_empty() {
100            return Ok(None);
101        }
102
103        let len = self.input.len();
104        match ArangeHeader::parse(&mut self.input, self.offset) {
105            Ok(header) => {
106                self.offset.0 += len - self.input.len();
107                Ok(Some(header))
108            }
109            Err(e) => {
110                self.input.empty();
111                Err(e)
112            }
113        }
114    }
115}
116
117#[cfg(feature = "fallible-iterator")]
118impl<R: Reader> fallible_iterator::FallibleIterator for ArangeHeaderIter<R> {
119    type Item = ArangeHeader<R>;
120    type Error = Error;
121
122    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
123        ArangeHeaderIter::next(self)
124    }
125}
126
127#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct ArangeHeader<R, Offset = <R as Reader>::Offset>
132where
133    R: Reader<Offset = Offset>,
134    Offset: ReaderOffset,
135{
136    offset: DebugArangesOffset<Offset>,
137    encoding: Encoding,
138    length: Offset,
139    debug_info_offset: DebugInfoOffset<Offset>,
140    entries: R,
141}
142
143impl<R, Offset> ArangeHeader<R, Offset>
144where
145    R: Reader<Offset = Offset>,
146    Offset: ReaderOffset,
147{
148    fn parse(input: &mut R, offset: DebugArangesOffset<Offset>) -> Result<Self> {
149        let (length, format) = input.read_initial_length()?;
150        let mut rest = input.split(length)?;
151
152        let version = rest.read_u16()?;
157        if version != 2 && version != 3 {
158            return Err(Error::UnknownVersion(u64::from(version)));
159        }
160
161        let debug_info_offset = rest.read_offset(format).map(DebugInfoOffset)?;
162        let address_size = rest.read_address_size()?;
163        let segment_size = rest.read_u8()?;
164        if segment_size != 0 {
165            return Err(Error::UnsupportedSegmentSize);
166        }
167
168        let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1;
170
171        let tuple_length = address_size
174            .checked_mul(2)
175            .ok_or(Error::UnsupportedAddressSize(address_size))?;
176        if tuple_length == 0 {
177            return Err(Error::UnsupportedAddressSize(address_size));
178        }
179        let padding = if header_length % tuple_length == 0 {
180            0
181        } else {
182            tuple_length - header_length % tuple_length
183        };
184        rest.skip(R::Offset::from_u8(padding))?;
185
186        let encoding = Encoding {
187            format,
188            version,
189            address_size,
190        };
191        Ok(ArangeHeader {
192            offset,
193            encoding,
194            length,
195            debug_info_offset,
196            entries: rest,
197        })
198    }
199
200    #[inline]
202    pub fn offset(&self) -> DebugArangesOffset<Offset> {
203        self.offset
204    }
205
206    #[inline]
208    pub fn length(&self) -> Offset {
209        self.length
210    }
211
212    #[inline]
214    pub fn encoding(&self) -> Encoding {
215        self.encoding
216    }
217
218    #[inline]
220    pub fn debug_info_offset(&self) -> DebugInfoOffset<Offset> {
221        self.debug_info_offset
222    }
223
224    #[inline]
226    pub fn entries(&self) -> ArangeEntryIter<R> {
227        ArangeEntryIter {
228            input: self.entries.clone(),
229            encoding: self.encoding,
230        }
231    }
232}
233
234#[derive(Debug, Clone)]
239pub struct ArangeEntryIter<R: Reader> {
240    input: R,
241    encoding: Encoding,
242}
243
244impl<R: Reader> ArangeEntryIter<R> {
245    pub fn next(&mut self) -> Result<Option<ArangeEntry>> {
252        loop {
253            let raw_entry = match self.next_raw()? {
254                Some(entry) => entry,
255                None => return Ok(None),
256            };
257
258            let entry = self.convert_raw(raw_entry)?;
259            if entry.is_some() {
260                return Ok(entry);
261            }
262        }
263    }
264
265    pub fn next_raw(&mut self) -> Result<Option<ArangeEntry>> {
270        if self.input.is_empty() {
271            return Ok(None);
272        }
273
274        match ArangeEntry::parse(&mut self.input, self.encoding) {
275            Ok(Some(entry)) => Ok(Some(entry)),
276            Ok(None) => {
277                self.input.empty();
278                Ok(None)
279            }
280            Err(e) => {
281                self.input.empty();
282                Err(e)
283            }
284        }
285    }
286
287    #[doc(hidden)]
291    pub fn convert_raw(&self, mut entry: ArangeEntry) -> Result<Option<ArangeEntry>> {
292        let address_size = self.encoding.address_size;
296        let tombstone_address = !0 >> (64 - self.encoding.address_size * 8);
297        if entry.range.begin == tombstone_address {
298            return Ok(None);
299        }
300
301        entry.range.end = entry.range.begin.add_sized(entry.length, address_size)?;
303        Ok(Some(entry))
304    }
305}
306
307#[cfg(feature = "fallible-iterator")]
308impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
309    type Item = ArangeEntry;
310    type Error = Error;
311
312    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
313        ArangeEntryIter::next(self)
314    }
315}
316
317#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
319pub struct ArangeEntry {
320    range: Range,
321    length: u64,
322}
323
324impl ArangeEntry {
325    fn parse<R: Reader>(input: &mut R, encoding: Encoding) -> Result<Option<Self>> {
327        let address_size = encoding.address_size;
328
329        let tuple_length = R::Offset::from_u8(2 * address_size);
330        if tuple_length > input.len() {
331            input.empty();
332            return Ok(None);
333        }
334
335        let begin = input.read_address(address_size)?;
336        let length = input.read_address(address_size)?;
337        let range = Range { begin, end: 0 };
338
339        match (begin, length) {
340            (0, 0) => Self::parse(input, encoding),
344            _ => Ok(Some(ArangeEntry { range, length })),
345        }
346    }
347
348    #[inline]
350    pub fn address(&self) -> u64 {
351        self.range.begin
352    }
353
354    #[inline]
356    pub fn length(&self) -> u64 {
357        self.length
358    }
359
360    #[inline]
362    pub fn range(&self) -> Range {
363        self.range
364    }
365}
366
367#[cfg(test)]
368mod tests {
369    use super::*;
370    use crate::common::{DebugInfoOffset, Format};
371    use crate::endianity::LittleEndian;
372    use crate::read::EndianSlice;
373
374    #[test]
375    fn test_iterate_headers() {
376        #[rustfmt::skip]
377        let buf = [
378            0x1c, 0x00, 0x00, 0x00,
380            0x02, 0x00,
382            0x01, 0x02, 0x03, 0x04,
384            0x04,
386            0x00,
388            0x00, 0x00, 0x00, 0x00,
390            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392
393            0x24, 0x00, 0x00, 0x00,
395            0x02, 0x00,
397            0x11, 0x12, 0x13, 0x14,
399            0x04,
401            0x00,
403            0x00, 0x00, 0x00, 0x00,
405            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408        ];
409
410        let debug_aranges = DebugAranges::new(&buf, LittleEndian);
411        let mut headers = debug_aranges.headers();
412
413        let header = headers
414            .next()
415            .expect("should parse header ok")
416            .expect("should have a header");
417        assert_eq!(header.offset(), DebugArangesOffset(0));
418        assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x0403_0201));
419
420        let header = headers
421            .next()
422            .expect("should parse header ok")
423            .expect("should have a header");
424        assert_eq!(header.offset(), DebugArangesOffset(0x20));
425        assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x1413_1211));
426    }
427
428    #[test]
429    fn test_parse_header_ok() {
430        #[rustfmt::skip]
431        let buf = [
432            0x1c, 0x00, 0x00, 0x00,
434            0x02, 0x00,
436            0x01, 0x02, 0x03, 0x04,
438            0x08,
440            0x00,
442            0x10, 0x00, 0x00, 0x00,
445
446            0x20, 0x00, 0x00, 0x00,
448            0x00, 0x00, 0x00, 0x00,
449            0x00, 0x00, 0x00, 0x00,
450            0x00, 0x00, 0x00, 0x00,
451
452            0x30, 0x00, 0x00, 0x00,
454            0x00, 0x00, 0x00, 0x00,
455            0x00, 0x00, 0x00, 0x00,
456            0x00, 0x00, 0x00, 0x00,
457        ];
458
459        let rest = &mut EndianSlice::new(&buf, LittleEndian);
460
461        let header =
462            ArangeHeader::parse(rest, DebugArangesOffset(0x10)).expect("should parse header ok");
463
464        assert_eq!(
465            *rest,
466            EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
467        );
468        assert_eq!(
469            header,
470            ArangeHeader {
471                offset: DebugArangesOffset(0x10),
472                encoding: Encoding {
473                    format: Format::Dwarf32,
474                    version: 2,
475                    address_size: 8,
476                },
477                length: 0x1c,
478                debug_info_offset: DebugInfoOffset(0x0403_0201),
479                entries: EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian),
480            }
481        );
482    }
483
484    #[test]
485    fn test_parse_header_overflow_error() {
486        #[rustfmt::skip]
487        let buf = [
488            0x20, 0x00, 0x00, 0x00,
490            0x02, 0x00,
492            0x01, 0x02, 0x03, 0x04,
494            0xff,
496            0x00,
498            0x10, 0x00, 0x00, 0x00,
501            0x00, 0x00, 0x00, 0x00,
502
503            0x20, 0x00, 0x00, 0x00,
505            0x00, 0x00, 0x00, 0x00,
506            0x00, 0x00, 0x00, 0x00,
507            0x00, 0x00, 0x00, 0x00,
508
509            0x30, 0x00, 0x00, 0x00,
511            0x00, 0x00, 0x00, 0x00,
512            0x00, 0x00, 0x00, 0x00,
513            0x00, 0x00, 0x00, 0x00,
514        ];
515
516        let rest = &mut EndianSlice::new(&buf, LittleEndian);
517
518        let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
519            .expect_err("should fail to parse header");
520        assert_eq!(error, Error::UnsupportedAddressSize(0xff));
521    }
522
523    #[test]
524    fn test_parse_header_div_by_zero_error() {
525        #[rustfmt::skip]
526        let buf = [
527            0x20, 0x00, 0x00, 0x00,
529            0x02, 0x00,
531            0x01, 0x02, 0x03, 0x04,
533            0x00,
536            0x00,
538            0x10, 0x00, 0x00, 0x00,
541            0x00, 0x00, 0x00, 0x00,
542
543            0x20, 0x00, 0x00, 0x00,
545            0x00, 0x00, 0x00, 0x00,
546            0x00, 0x00, 0x00, 0x00,
547            0x00, 0x00, 0x00, 0x00,
548
549            0x30, 0x00, 0x00, 0x00,
551            0x00, 0x00, 0x00, 0x00,
552            0x00, 0x00, 0x00, 0x00,
553            0x00, 0x00, 0x00, 0x00,
554        ];
555
556        let rest = &mut EndianSlice::new(&buf, LittleEndian);
557
558        let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
559            .expect_err("should fail to parse header");
560        assert_eq!(error, Error::UnsupportedAddressSize(0));
561    }
562
563    #[test]
564    fn test_parse_entry_ok() {
565        let encoding = Encoding {
566            format: Format::Dwarf32,
567            version: 2,
568            address_size: 4,
569        };
570        let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
571        let mut iter = ArangeEntryIter {
572            input: EndianSlice::new(&buf, LittleEndian),
573            encoding,
574        };
575        let entry = iter.next().expect("should parse entry ok");
576        assert_eq!(
577            iter.input,
578            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
579        );
580        assert_eq!(
581            entry,
582            Some(ArangeEntry {
583                range: Range {
584                    begin: 0x0403_0201,
585                    end: 0x0403_0201 + 0x0807_0605,
586                },
587                length: 0x0807_0605,
588            })
589        );
590    }
591
592    #[test]
593    fn test_parse_entry_zero() {
594        let encoding = Encoding {
595            format: Format::Dwarf32,
596            version: 2,
597            address_size: 4,
598        };
599        #[rustfmt::skip]
600        let buf = [
601            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603            0x01, 0x02, 0x03, 0x04,
605            0x05, 0x06, 0x07, 0x08,
607            0x09
609        ];
610        let mut iter = ArangeEntryIter {
611            input: EndianSlice::new(&buf, LittleEndian),
612            encoding,
613        };
614        let entry = iter.next().expect("should parse entry ok");
615        assert_eq!(
616            iter.input,
617            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
618        );
619        assert_eq!(
620            entry,
621            Some(ArangeEntry {
622                range: Range {
623                    begin: 0x0403_0201,
624                    end: 0x0403_0201 + 0x0807_0605,
625                },
626                length: 0x0807_0605,
627            })
628        );
629    }
630
631    #[test]
632    fn test_parse_entry_overflow_32() {
633        let encoding = Encoding {
634            format: Format::Dwarf32,
635            version: 2,
636            address_size: 4,
637        };
638        #[rustfmt::skip]
639        let buf = [
640            0x01, 0x02, 0x03, 0x84,
642            0x05, 0x06, 0x07, 0x88,
644            0x09
646        ];
647        let mut iter = ArangeEntryIter {
648            input: EndianSlice::new(&buf, LittleEndian),
649            encoding,
650        };
651        let entry = iter.next();
652        assert_eq!(
653            iter.input,
654            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
655        );
656        assert_eq!(entry, Err(Error::AddressOverflow));
657    }
658
659    #[test]
660    fn test_parse_entry_overflow_64() {
661        let encoding = Encoding {
662            format: Format::Dwarf32,
663            version: 2,
664            address_size: 8,
665        };
666        #[rustfmt::skip]
667        let buf = [
668            0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x80,
670            0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x80,
672            0x09
674        ];
675        let mut iter = ArangeEntryIter {
676            input: EndianSlice::new(&buf, LittleEndian),
677            encoding,
678        };
679        let entry = iter.next();
680        assert_eq!(
681            iter.input,
682            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
683        );
684        assert_eq!(entry, Err(Error::AddressOverflow));
685    }
686
687    #[test]
688    fn test_parse_entry_tombstone_32() {
689        let encoding = Encoding {
690            format: Format::Dwarf32,
691            version: 2,
692            address_size: 4,
693        };
694        #[rustfmt::skip]
695        let buf = [
696            0xff, 0xff, 0xff, 0xff,
698            0x05, 0x06, 0x07, 0x08,
700            0x01, 0x02, 0x03, 0x04,
702            0x05, 0x06, 0x07, 0x08,
704            0x09
706        ];
707
708        let mut iter = ArangeEntryIter {
709            input: EndianSlice::new(&buf, LittleEndian),
710            encoding,
711        };
712        let entry = iter.next_raw().unwrap();
713        assert_eq!(
714            iter.input,
715            EndianSlice::new(&buf[buf.len() - 9..], LittleEndian)
716        );
717        assert_eq!(
718            entry,
719            Some(ArangeEntry {
720                range: Range {
721                    begin: 0xffff_ffff,
722                    end: 0,
723                },
724                length: 0x0807_0605,
725            })
726        );
727
728        let mut iter = ArangeEntryIter {
729            input: EndianSlice::new(&buf, LittleEndian),
730            encoding,
731        };
732        let entry = iter.next().unwrap();
733        assert_eq!(
734            iter.input,
735            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
736        );
737        assert_eq!(
738            entry,
739            Some(ArangeEntry {
740                range: Range {
741                    begin: 0x0403_0201,
742                    end: 0x0403_0201 + 0x0807_0605,
743                },
744                length: 0x0807_0605,
745            })
746        );
747    }
748
749    #[test]
750    fn test_parse_entry_tombstone_64() {
751        let encoding = Encoding {
752            format: Format::Dwarf32,
753            version: 2,
754            address_size: 8,
755        };
756        #[rustfmt::skip]
757        let buf = [
758            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
760            0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
762            0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
764            0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00,
766            0x09
768        ];
769
770        let mut iter = ArangeEntryIter {
771            input: EndianSlice::new(&buf, LittleEndian),
772            encoding,
773        };
774        let entry = iter.next_raw().unwrap();
775        assert_eq!(
776            iter.input,
777            EndianSlice::new(&buf[buf.len() - 17..], LittleEndian)
778        );
779        assert_eq!(
780            entry,
781            Some(ArangeEntry {
782                range: Range {
783                    begin: 0xffff_ffff_ffff_ffff,
784                    end: 0,
785                },
786                length: 0x0807_0605,
787            })
788        );
789
790        let mut iter = ArangeEntryIter {
791            input: EndianSlice::new(&buf, LittleEndian),
792            encoding,
793        };
794        let entry = iter.next().unwrap();
795        assert_eq!(
796            iter.input,
797            EndianSlice::new(&buf[buf.len() - 1..], LittleEndian)
798        );
799        assert_eq!(
800            entry,
801            Some(ArangeEntry {
802                range: Range {
803                    begin: 0x0403_0201,
804                    end: 0x0403_0201 + 0x0807_0605,
805                },
806                length: 0x0807_0605,
807            })
808        );
809    }
810}