1use crate::common::{
2    DebugAddrBase, DebugAddrIndex, DebugRngListsBase, DebugRngListsIndex, DwarfFileType, Encoding,
3    RangeListsOffset, SectionId,
4};
5use crate::constants;
6use crate::endianity::Endianity;
7use crate::read::{
8    lists::ListsHeader, DebugAddr, EndianSlice, Error, Reader, ReaderAddress, ReaderOffset,
9    ReaderOffsetId, Result, Section,
10};
11
12#[derive(Debug, Default, Clone, Copy)]
14pub struct DebugRanges<R> {
15    pub(crate) section: R,
16}
17
18impl<'input, Endian> DebugRanges<EndianSlice<'input, Endian>>
19where
20    Endian: Endianity,
21{
22    pub fn new(section: &'input [u8], endian: Endian) -> Self {
37        Self::from(EndianSlice::new(section, endian))
38    }
39}
40
41impl<T> DebugRanges<T> {
42    pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugRanges<R>
48    where
49        F: FnMut(&'a T) -> R,
50    {
51        borrow(&self.section).into()
52    }
53}
54
55impl<R> Section<R> for DebugRanges<R> {
56    fn id() -> SectionId {
57        SectionId::DebugRanges
58    }
59
60    fn reader(&self) -> &R {
61        &self.section
62    }
63}
64
65impl<R> From<R> for DebugRanges<R> {
66    fn from(section: R) -> Self {
67        DebugRanges { section }
68    }
69}
70
71#[derive(Debug, Default, Clone, Copy)]
74pub struct DebugRngLists<R> {
75    section: R,
76}
77
78impl<'input, Endian> DebugRngLists<EndianSlice<'input, Endian>>
79where
80    Endian: Endianity,
81{
82    pub fn new(section: &'input [u8], endian: Endian) -> Self {
98        Self::from(EndianSlice::new(section, endian))
99    }
100}
101
102impl<T> DebugRngLists<T> {
103    pub(crate) fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugRngLists<R>
109    where
110        F: FnMut(&'a T) -> R,
111    {
112        borrow(&self.section).into()
113    }
114}
115
116impl<R> Section<R> for DebugRngLists<R> {
117    fn id() -> SectionId {
118        SectionId::DebugRngLists
119    }
120
121    fn reader(&self) -> &R {
122        &self.section
123    }
124}
125
126impl<R> From<R> for DebugRngLists<R> {
127    fn from(section: R) -> Self {
128        DebugRngLists { section }
129    }
130}
131
132#[allow(unused)]
133pub(crate) type RngListsHeader = ListsHeader;
134
135impl<Offset> DebugRngListsBase<Offset>
136where
137    Offset: ReaderOffset,
138{
139    pub fn default_for_encoding_and_file(
142        encoding: Encoding,
143        file_type: DwarfFileType,
144    ) -> DebugRngListsBase<Offset> {
145        if encoding.version >= 5 && file_type == DwarfFileType::Dwo {
146            DebugRngListsBase(Offset::from_u8(RngListsHeader::size_for_encoding(encoding)))
150        } else {
151            DebugRngListsBase(Offset::from_u8(0))
152        }
153    }
154}
155
156#[derive(Debug, Default, Clone, Copy)]
158pub struct RangeLists<R> {
159    debug_ranges: DebugRanges<R>,
160    debug_rnglists: DebugRngLists<R>,
161}
162
163impl<R> RangeLists<R> {
164    pub fn new(debug_ranges: DebugRanges<R>, debug_rnglists: DebugRngLists<R>) -> RangeLists<R> {
167        RangeLists {
168            debug_ranges,
169            debug_rnglists,
170        }
171    }
172
173    pub fn debug_ranges(&self) -> &DebugRanges<R> {
175        &self.debug_ranges
176    }
177
178    pub fn set_debug_ranges(&mut self, debug_ranges: DebugRanges<R>) {
182        self.debug_ranges = debug_ranges;
183    }
184
185    pub fn debug_rnglists(&self) -> &DebugRngLists<R> {
187        &self.debug_rnglists
188    }
189}
190
191impl<T> RangeLists<T> {
192    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> RangeLists<R>
198    where
199        F: FnMut(&'a T) -> R,
200    {
201        RangeLists {
202            debug_ranges: borrow(&self.debug_ranges.section).into(),
203            debug_rnglists: borrow(&self.debug_rnglists.section).into(),
204        }
205    }
206}
207
208impl<R: Reader> RangeLists<R> {
209    pub fn ranges(
220        &self,
221        offset: RangeListsOffset<R::Offset>,
222        unit_encoding: Encoding,
223        base_address: u64,
224        debug_addr: &DebugAddr<R>,
225        debug_addr_base: DebugAddrBase<R::Offset>,
226    ) -> Result<RngListIter<R>> {
227        Ok(RngListIter::new(
228            self.raw_ranges(offset, unit_encoding)?,
229            base_address,
230            debug_addr.clone(),
231            debug_addr_base,
232        ))
233    }
234
235    pub fn raw_ranges(
246        &self,
247        offset: RangeListsOffset<R::Offset>,
248        unit_encoding: Encoding,
249    ) -> Result<RawRngListIter<R>> {
250        let (mut input, format) = if unit_encoding.version <= 4 {
251            (self.debug_ranges.section.clone(), RangeListsFormat::Bare)
252        } else {
253            (self.debug_rnglists.section.clone(), RangeListsFormat::Rle)
254        };
255        input.skip(offset.0)?;
256        Ok(RawRngListIter::new(input, unit_encoding, format))
257    }
258
259    pub fn get_offset(
269        &self,
270        unit_encoding: Encoding,
271        base: DebugRngListsBase<R::Offset>,
272        index: DebugRngListsIndex<R::Offset>,
273    ) -> Result<RangeListsOffset<R::Offset>> {
274        let format = unit_encoding.format;
275        let input = &mut self.debug_rnglists.section.clone();
276        input.skip(base.0)?;
277        input.skip(R::Offset::from_u64(
278            index.0.into_u64() * u64::from(format.word_size()),
279        )?)?;
280        input
281            .read_offset(format)
282            .map(|x| RangeListsOffset(base.0 + x))
283    }
284
285    pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)> {
287        self.debug_ranges
288            .lookup_offset_id(id)
289            .or_else(|| self.debug_rnglists.lookup_offset_id(id))
290    }
291}
292
293#[derive(Debug, Clone, Copy, PartialEq, Eq)]
294enum RangeListsFormat {
295    Bare,
297    Rle,
299}
300
301#[derive(Debug)]
306pub struct RawRngListIter<R: Reader> {
307    input: R,
308    encoding: Encoding,
309    format: RangeListsFormat,
310}
311
312#[derive(Clone, Debug)]
314pub enum RawRngListEntry<T> {
315    AddressOrOffsetPair {
317        begin: u64,
319        end: u64,
321    },
322    BaseAddress {
324        addr: u64,
326    },
327    BaseAddressx {
329        addr: DebugAddrIndex<T>,
331    },
332    StartxEndx {
334        begin: DebugAddrIndex<T>,
336        end: DebugAddrIndex<T>,
338    },
339    StartxLength {
341        begin: DebugAddrIndex<T>,
343        length: u64,
345    },
346    OffsetPair {
348        begin: u64,
350        end: u64,
352    },
353    StartEnd {
355        begin: u64,
357        end: u64,
359    },
360    StartLength {
362        begin: u64,
364        length: u64,
366    },
367}
368
369impl<T: ReaderOffset> RawRngListEntry<T> {
370    fn parse<R: Reader<Offset = T>>(
372        input: &mut R,
373        encoding: Encoding,
374        format: RangeListsFormat,
375    ) -> Result<Option<Self>> {
376        Ok(match format {
377            RangeListsFormat::Bare => {
378                let range = RawRange::parse(input, encoding.address_size)?;
379                if range.is_end() {
380                    None
381                } else if range.is_base_address(encoding.address_size) {
382                    Some(RawRngListEntry::BaseAddress { addr: range.end })
383                } else {
384                    Some(RawRngListEntry::AddressOrOffsetPair {
385                        begin: range.begin,
386                        end: range.end,
387                    })
388                }
389            }
390            RangeListsFormat::Rle => match constants::DwRle(input.read_u8()?) {
391                constants::DW_RLE_end_of_list => None,
392                constants::DW_RLE_base_addressx => Some(RawRngListEntry::BaseAddressx {
393                    addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
394                }),
395                constants::DW_RLE_startx_endx => Some(RawRngListEntry::StartxEndx {
396                    begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
397                    end: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
398                }),
399                constants::DW_RLE_startx_length => Some(RawRngListEntry::StartxLength {
400                    begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
401                    length: input.read_uleb128()?,
402                }),
403                constants::DW_RLE_offset_pair => Some(RawRngListEntry::OffsetPair {
404                    begin: input.read_uleb128()?,
405                    end: input.read_uleb128()?,
406                }),
407                constants::DW_RLE_base_address => Some(RawRngListEntry::BaseAddress {
408                    addr: input.read_address(encoding.address_size)?,
409                }),
410                constants::DW_RLE_start_end => Some(RawRngListEntry::StartEnd {
411                    begin: input.read_address(encoding.address_size)?,
412                    end: input.read_address(encoding.address_size)?,
413                }),
414                constants::DW_RLE_start_length => Some(RawRngListEntry::StartLength {
415                    begin: input.read_address(encoding.address_size)?,
416                    length: input.read_uleb128()?,
417                }),
418                entry => {
419                    return Err(Error::UnknownRangeListsEntry(entry));
420                }
421            },
422        })
423    }
424}
425
426impl<R: Reader> RawRngListIter<R> {
427    fn new(input: R, encoding: Encoding, format: RangeListsFormat) -> RawRngListIter<R> {
429        RawRngListIter {
430            input,
431            encoding,
432            format,
433        }
434    }
435
436    pub fn next(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>> {
438        if self.input.is_empty() {
439            return Ok(None);
440        }
441
442        match RawRngListEntry::parse(&mut self.input, self.encoding, self.format) {
443            Ok(range) => {
444                if range.is_none() {
445                    self.input.empty();
446                }
447                Ok(range)
448            }
449            Err(e) => {
450                self.input.empty();
451                Err(e)
452            }
453        }
454    }
455}
456
457#[cfg(feature = "fallible-iterator")]
458impl<R: Reader> fallible_iterator::FallibleIterator for RawRngListIter<R> {
459    type Item = RawRngListEntry<R::Offset>;
460    type Error = Error;
461
462    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
463        RawRngListIter::next(self)
464    }
465}
466
467#[derive(Debug)]
473pub struct RngListIter<R: Reader> {
474    raw: RawRngListIter<R>,
475    base_address: u64,
476    debug_addr: DebugAddr<R>,
477    debug_addr_base: DebugAddrBase<R::Offset>,
478}
479
480impl<R: Reader> RngListIter<R> {
481    fn new(
483        raw: RawRngListIter<R>,
484        base_address: u64,
485        debug_addr: DebugAddr<R>,
486        debug_addr_base: DebugAddrBase<R::Offset>,
487    ) -> RngListIter<R> {
488        RngListIter {
489            raw,
490            base_address,
491            debug_addr,
492            debug_addr_base,
493        }
494    }
495
496    #[inline]
497    fn get_address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
498        self.debug_addr
499            .get_address(self.raw.encoding.address_size, self.debug_addr_base, index)
500    }
501
502    pub fn next(&mut self) -> Result<Option<Range>> {
504        loop {
505            let raw_range = match self.raw.next()? {
506                Some(range) => range,
507                None => return Ok(None),
508            };
509
510            let range = self.convert_raw(raw_range)?;
511            if range.is_some() {
512                return Ok(range);
513            }
514        }
515    }
516
517    #[doc(hidden)]
521    pub fn next_raw(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>> {
522        self.raw.next()
523    }
524
525    #[doc(hidden)]
529    pub fn convert_raw(&mut self, raw_range: RawRngListEntry<R::Offset>) -> Result<Option<Range>> {
530        let address_size = self.raw.encoding.address_size;
531        let mask = u64::ones_sized(address_size);
532        let tombstone = if self.raw.encoding.version <= 4 {
533            mask - 1
534        } else {
535            mask
536        };
537
538        let range = match raw_range {
539            RawRngListEntry::BaseAddress { addr } => {
540                self.base_address = addr;
541                return Ok(None);
542            }
543            RawRngListEntry::BaseAddressx { addr } => {
544                self.base_address = self.get_address(addr)?;
545                return Ok(None);
546            }
547            RawRngListEntry::StartxEndx { begin, end } => {
548                let begin = self.get_address(begin)?;
549                let end = self.get_address(end)?;
550                Range { begin, end }
551            }
552            RawRngListEntry::StartxLength { begin, length } => {
553                let begin = self.get_address(begin)?;
554                let end = begin.wrapping_add_sized(length, address_size);
555                Range { begin, end }
556            }
557            RawRngListEntry::AddressOrOffsetPair { begin, end }
558            | RawRngListEntry::OffsetPair { begin, end } => {
559                if self.base_address == tombstone {
561                    return Ok(None);
562                }
563                let mut range = Range { begin, end };
564                range.add_base_address(self.base_address, self.raw.encoding.address_size);
565                range
566            }
567            RawRngListEntry::StartEnd { begin, end } => Range { begin, end },
568            RawRngListEntry::StartLength { begin, length } => {
569                let end = begin.wrapping_add_sized(length, address_size);
570                Range { begin, end }
571            }
572        };
573
574        if range.begin == tombstone || range.begin >= range.end {
585            return Ok(None);
586        }
587
588        Ok(Some(range))
589    }
590}
591
592#[cfg(feature = "fallible-iterator")]
593impl<R: Reader> fallible_iterator::FallibleIterator for RngListIter<R> {
594    type Item = Range;
595    type Error = Error;
596
597    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
598        RngListIter::next(self)
599    }
600}
601
602#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
604pub(crate) struct RawRange {
605    pub begin: u64,
607
608    pub end: u64,
610}
611
612impl RawRange {
613    #[inline]
615    pub fn is_end(&self) -> bool {
616        self.begin == 0 && self.end == 0
617    }
618
619    #[inline]
624    pub fn is_base_address(&self, address_size: u8) -> bool {
625        self.begin == !0 >> (64 - address_size * 8)
626    }
627
628    #[inline]
630    pub fn parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange> {
631        let begin = input.read_address(address_size)?;
632        let end = input.read_address(address_size)?;
633        let range = RawRange { begin, end };
634        Ok(range)
635    }
636}
637
638#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
640pub struct Range {
641    pub begin: u64,
643
644    pub end: u64,
646}
647
648impl Range {
649    #[inline]
651    pub(crate) fn add_base_address(&mut self, base_address: u64, address_size: u8) {
652        self.begin = base_address.wrapping_add_sized(self.begin, address_size);
653        self.end = base_address.wrapping_add_sized(self.end, address_size);
654    }
655}
656
657#[cfg(test)]
658mod tests {
659    use super::*;
660    use crate::common::Format;
661    use crate::constants::*;
662    use crate::endianity::LittleEndian;
663    use crate::test_util::GimliSectionMethods;
664    use alloc::vec::Vec;
665    use test_assembler::{Endian, Label, LabelMaker, Section};
666
667    #[test]
668    fn test_rnglists() {
669        let format = Format::Dwarf32;
670        for size in [4, 8] {
671            let tombstone = u64::ones_sized(size);
672            let tombstone_0 = 0;
673            let encoding = Encoding {
674                format,
675                version: 5,
676                address_size: size,
677            };
678            let section = Section::with_endian(Endian::Little)
679                .word(size, 0x0300_0000)
680                .word(size, 0x0301_0300)
681                .word(size, 0x0301_0400)
682                .word(size, 0x0301_0500)
683                .word(size, tombstone)
684                .word(size, 0x0301_0600)
685                .word(size, tombstone_0);
686            let buf = section.get_contents().unwrap();
687            let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
688            let debug_addr_base = DebugAddrBase(0);
689
690            let length = Label::new();
691            let start = Label::new();
692            let first = Label::new();
693            let end = Label::new();
694            let mut section = Section::with_endian(Endian::Little)
695                .initial_length(format, &length, &start)
696                .L16(encoding.version)
697                .L8(encoding.address_size)
698                .L8(0)
699                .L32(0)
700                .mark(&first);
701
702            let mut expected_ranges = Vec::new();
703            let mut expect_range = |begin, end| {
704                expected_ranges.push(Range { begin, end });
705            };
706
707            section = section.L8(DW_RLE_offset_pair.0).uleb(0x10200).uleb(0x10300);
709            expect_range(0x0101_0200, 0x0101_0300);
710
711            section = section.L8(DW_RLE_base_address.0).word(size, 0x0200_0000);
712            section = section.L8(DW_RLE_offset_pair.0).uleb(0x10400).uleb(0x10500);
713            expect_range(0x0201_0400, 0x0201_0500);
714
715            section = section
716                .L8(DW_RLE_start_end.0)
717                .word(size, 0x201_0a00)
718                .word(size, 0x201_0b00);
719            expect_range(0x0201_0a00, 0x0201_0b00);
720
721            section = section
722                .L8(DW_RLE_start_length.0)
723                .word(size, 0x201_0c00)
724                .uleb(0x100);
725            expect_range(0x0201_0c00, 0x0201_0d00);
726
727            section = section.L8(DW_RLE_base_address.0).word(size, 0);
729            section = section.L8(DW_RLE_offset_pair.0).uleb(0).uleb(1);
730            expect_range(0, 1);
731
732            section = section.L8(DW_RLE_base_address.0).word(size, 0);
734            section = section.L8(DW_RLE_offset_pair.0).uleb(0).uleb(tombstone);
735            expect_range(0, tombstone);
736
737            section = section.L8(DW_RLE_base_addressx.0).uleb(0);
738            section = section.L8(DW_RLE_offset_pair.0).uleb(0x10100).uleb(0x10200);
739            expect_range(0x0301_0100, 0x0301_0200);
740
741            section = section.L8(DW_RLE_startx_endx.0).uleb(1).uleb(2);
742            expect_range(0x0301_0300, 0x0301_0400);
743
744            section = section.L8(DW_RLE_startx_length.0).uleb(3).uleb(0x100);
745            expect_range(0x0301_0500, 0x0301_0600);
746
747            section = section.L8(DW_RLE_base_addressx.0).uleb(4);
749            section = section.L8(DW_RLE_offset_pair.0).uleb(0x11100).uleb(0x11200);
750
751            section = section.L8(DW_RLE_base_address.0).word(size, tombstone);
752            section = section.L8(DW_RLE_offset_pair.0).uleb(0x11300).uleb(0x11400);
753
754            section = section.L8(DW_RLE_startx_endx.0).uleb(4).uleb(5);
755            section = section.L8(DW_RLE_startx_length.0).uleb(4).uleb(0x100);
756            section = section
757                .L8(DW_RLE_start_end.0)
758                .word(size, tombstone)
759                .word(size, 0x201_1500);
760            section = section
761                .L8(DW_RLE_start_length.0)
762                .word(size, tombstone)
763                .uleb(0x100);
764
765            section = section.L8(DW_RLE_startx_endx.0).uleb(6).uleb(6);
767            section = section
768                .L8(DW_RLE_start_end.0)
769                .word(size, tombstone_0)
770                .word(size, tombstone_0);
771
772            section = section.L8(DW_RLE_base_address.0).word(size, 0);
774            section = section.L8(DW_RLE_offset_pair.0).uleb(0).uleb(0);
775            section = section.L8(DW_RLE_base_address.0).word(size, 0x10000);
776            section = section.L8(DW_RLE_offset_pair.0).uleb(0x1234).uleb(0x1234);
777
778            section = section
780                .L8(DW_RLE_start_end.0)
781                .word(size, 0x201_1600)
782                .word(size, 0x201_1700);
783            expect_range(0x0201_1600, 0x0201_1700);
784
785            section = section.L8(DW_RLE_end_of_list.0);
786            section = section.mark(&end);
787            section = section.word(size, 0x1234_5678);
789            length.set_const((&end - &start) as u64);
790
791            let offset = RangeListsOffset((&first - §ion.start()) as usize);
792            let buf = section.get_contents().unwrap();
793            let debug_ranges = DebugRanges::new(&[], LittleEndian);
794            let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
795            let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
796            let mut ranges = rnglists
797                .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
798                .unwrap();
799
800            for expected_range in expected_ranges {
801                let range = ranges.next();
802                assert_eq!(
803                    range,
804                    Ok(Some(expected_range)),
805                    "read {:x?}, expect {:x?}",
806                    range,
807                    expected_range
808                );
809            }
810            assert_eq!(ranges.next(), Ok(None));
811
812            let mut ranges = rnglists
814                .ranges(
815                    RangeListsOffset(buf.len()),
816                    encoding,
817                    0x0100_0000,
818                    debug_addr,
819                    debug_addr_base,
820                )
821                .unwrap();
822            assert_eq!(ranges.next(), Ok(None));
823        }
824    }
825
826    #[test]
827    fn test_raw_range() {
828        let range = RawRange {
829            begin: 0,
830            end: 0xffff_ffff,
831        };
832        assert!(!range.is_end());
833        assert!(!range.is_base_address(4));
834        assert!(!range.is_base_address(8));
835
836        let range = RawRange { begin: 0, end: 0 };
837        assert!(range.is_end());
838        assert!(!range.is_base_address(4));
839        assert!(!range.is_base_address(8));
840
841        let range = RawRange {
842            begin: 0xffff_ffff,
843            end: 0,
844        };
845        assert!(!range.is_end());
846        assert!(range.is_base_address(4));
847        assert!(!range.is_base_address(8));
848
849        let range = RawRange {
850            begin: 0xffff_ffff_ffff_ffff,
851            end: 0,
852        };
853        assert!(!range.is_end());
854        assert!(!range.is_base_address(4));
855        assert!(range.is_base_address(8));
856    }
857
858    #[test]
859    fn test_ranges() {
860        for size in [4, 8] {
861            let base = u64::ones_sized(size);
862            let tombstone = u64::ones_sized(size) - 1;
863            let start = Label::new();
864            let first = Label::new();
865            let mut section = Section::with_endian(Endian::Little)
866                .mark(&start)
868                .word(size, 0x10000)
869                .word(size, 0x10100)
870                .mark(&first);
871
872            let mut expected_ranges = Vec::new();
873            let mut expect_range = |begin, end| {
874                expected_ranges.push(Range { begin, end });
875            };
876
877            section = section.word(size, 0x10200).word(size, 0x10300);
879            expect_range(0x0101_0200, 0x0101_0300);
880            section = section.word(size, base).word(size, 0x0200_0000);
882            section = section.word(size, 0x10400).word(size, 0x10500);
883            expect_range(0x0201_0400, 0x0201_0500);
884            section = section.word(size, 0x10600).word(size, 0x10600);
886            section = section.word(size, 0x10800).word(size, 0x10900);
887            expect_range(0x0201_0800, 0x0201_0900);
888            section = section.word(size, base).word(size, 0);
890            section = section.word(size, 0).word(size, 1);
891            expect_range(0, 1);
892            section = section.word(size, base).word(size, 0);
894            section = section.word(size, 0).word(size, base);
895            expect_range(0, base);
896            section = section.word(size, tombstone).word(size, tombstone);
898            section = section.word(size, base).word(size, tombstone);
900            section = section.word(size, 0x10a00).word(size, 0x10b00);
901            section = section.word(size, 0).word(size, 0);
903            section = section.word(size, 0x1234_5678);
905
906            let buf = section.get_contents().unwrap();
907            let debug_ranges = DebugRanges::new(&buf, LittleEndian);
908            let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
909            let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
910            let offset = RangeListsOffset((&first - &start) as usize);
911            let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
912            let debug_addr_base = DebugAddrBase(0);
913            let encoding = Encoding {
914                format: Format::Dwarf32,
915                version: 4,
916                address_size: size,
917            };
918            let mut ranges = rnglists
919                .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
920                .unwrap();
921
922            for expected_range in expected_ranges {
923                let range = ranges.next();
924                assert_eq!(
925                    range,
926                    Ok(Some(expected_range)),
927                    "read {:x?}, expect {:x?}",
928                    range,
929                    expected_range
930                );
931            }
932            assert_eq!(ranges.next(), Ok(None));
933
934            let mut ranges = rnglists
936                .ranges(
937                    RangeListsOffset(buf.len()),
938                    encoding,
939                    0x0100_0000,
940                    debug_addr,
941                    debug_addr_base,
942                )
943                .unwrap();
944            assert_eq!(ranges.next(), Ok(None));
945        }
946    }
947
948    #[test]
949    fn test_ranges_invalid() {
950        #[rustfmt::skip]
951        let section = Section::with_endian(Endian::Little)
952            .L32(0x20000).L32(0x10000)
954            .L32(0x20000).L32(0xff01_0000);
956
957        let buf = section.get_contents().unwrap();
958        let debug_ranges = DebugRanges::new(&buf, LittleEndian);
959        let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
960        let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
961        let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
962        let debug_addr_base = DebugAddrBase(0);
963        let encoding = Encoding {
964            format: Format::Dwarf32,
965            version: 4,
966            address_size: 4,
967        };
968
969        let mut ranges = rnglists
971            .ranges(
972                RangeListsOffset(0x0),
973                encoding,
974                0x0100_0000,
975                debug_addr,
976                debug_addr_base,
977            )
978            .unwrap();
979        assert_eq!(ranges.next(), Ok(None));
980
981        let mut ranges = rnglists
983            .ranges(
984                RangeListsOffset(0x8),
985                encoding,
986                0x0100_0000,
987                debug_addr,
988                debug_addr_base,
989            )
990            .unwrap();
991        assert_eq!(ranges.next(), Ok(None));
992
993        match rnglists.ranges(
995            RangeListsOffset(buf.len() + 1),
996            encoding,
997            0x0100_0000,
998            debug_addr,
999            debug_addr_base,
1000        ) {
1001            Err(Error::UnexpectedEof(_)) => {}
1002            otherwise => panic!("Unexpected result: {:?}", otherwise),
1003        }
1004    }
1005
1006    #[test]
1007    fn test_get_offset() {
1008        for format in [Format::Dwarf32, Format::Dwarf64] {
1009            let encoding = Encoding {
1010                format,
1011                version: 5,
1012                address_size: 4,
1013            };
1014
1015            let zero = Label::new();
1016            let length = Label::new();
1017            let start = Label::new();
1018            let first = Label::new();
1019            let end = Label::new();
1020            let mut section = Section::with_endian(Endian::Little)
1021                .mark(&zero)
1022                .initial_length(format, &length, &start)
1023                .D16(encoding.version)
1024                .D8(encoding.address_size)
1025                .D8(0)
1026                .D32(20)
1027                .mark(&first);
1028            for i in 0..20 {
1029                section = section.word(format.word_size(), 1000 + i);
1030            }
1031            section = section.mark(&end);
1032            length.set_const((&end - &start) as u64);
1033            let section = section.get_contents().unwrap();
1034
1035            let debug_ranges = DebugRanges::from(EndianSlice::new(&[], LittleEndian));
1036            let debug_rnglists = DebugRngLists::from(EndianSlice::new(§ion, LittleEndian));
1037            let ranges = RangeLists::new(debug_ranges, debug_rnglists);
1038
1039            let base = DebugRngListsBase((&first - &zero) as usize);
1040            assert_eq!(
1041                ranges.get_offset(encoding, base, DebugRngListsIndex(0)),
1042                Ok(RangeListsOffset(base.0 + 1000))
1043            );
1044            assert_eq!(
1045                ranges.get_offset(encoding, base, DebugRngListsIndex(19)),
1046                Ok(RangeListsOffset(base.0 + 1019))
1047            );
1048        }
1049    }
1050}