gimli/read/
rnglists.rs

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/// The raw contents of the `.debug_ranges` section.
13#[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    /// Construct a new `DebugRanges` instance from the data in the `.debug_ranges`
23    /// section.
24    ///
25    /// It is the caller's responsibility to read the `.debug_ranges` section and
26    /// present it as a `&[u8]` slice. That means using some ELF loader on
27    /// Linux, a Mach-O loader on macOS, etc.
28    ///
29    /// ```
30    /// use gimli::{DebugRanges, LittleEndian};
31    ///
32    /// # let buf = [0x00, 0x01, 0x02, 0x03];
33    /// # let read_debug_ranges_section_somehow = || &buf;
34    /// let debug_ranges = DebugRanges::new(read_debug_ranges_section_somehow(), LittleEndian);
35    /// ```
36    pub fn new(section: &'input [u8], endian: Endian) -> Self {
37        Self::from(EndianSlice::new(section, endian))
38    }
39}
40
41impl<T> DebugRanges<T> {
42    /// Create a `DebugRanges` section that references the data in `self`.
43    ///
44    /// This is useful when `R` implements `Reader` but `T` does not.
45    ///
46    /// Used by `DwarfSections::borrow`.
47    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/// The `DebugRngLists` struct represents the contents of the
72/// `.debug_rnglists` section.
73#[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    /// Construct a new `DebugRngLists` instance from the data in the
83    /// `.debug_rnglists` section.
84    ///
85    /// It is the caller's responsibility to read the `.debug_rnglists`
86    /// section and present it as a `&[u8]` slice. That means using some ELF
87    /// loader on Linux, a Mach-O loader on macOS, etc.
88    ///
89    /// ```
90    /// use gimli::{DebugRngLists, LittleEndian};
91    ///
92    /// # let buf = [0x00, 0x01, 0x02, 0x03];
93    /// # let read_debug_rnglists_section_somehow = || &buf;
94    /// let debug_rnglists =
95    ///     DebugRngLists::new(read_debug_rnglists_section_somehow(), LittleEndian);
96    /// ```
97    pub fn new(section: &'input [u8], endian: Endian) -> Self {
98        Self::from(EndianSlice::new(section, endian))
99    }
100}
101
102impl<T> DebugRngLists<T> {
103    /// Create a `DebugRngLists` section that references the data in `self`.
104    ///
105    /// This is useful when `R` implements `Reader` but `T` does not.
106    ///
107    /// Used by `DwarfSections::borrow`.
108    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    /// Returns a `DebugRngListsBase` with the default value of DW_AT_rnglists_base
140    /// for the given `Encoding` and `DwarfFileType`.
141    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            // In .dwo files, the compiler omits the DW_AT_rnglists_base attribute (because there is
147            // only a single unit in the file) but we must skip past the header, which the attribute
148            // would normally do for us.
149            DebugRngListsBase(Offset::from_u8(RngListsHeader::size_for_encoding(encoding)))
150        } else {
151            DebugRngListsBase(Offset::from_u8(0))
152        }
153    }
154}
155
156/// The DWARF data found in `.debug_ranges` and `.debug_rnglists` sections.
157#[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    /// Construct a new `RangeLists` instance from the data in the `.debug_ranges` and
165    /// `.debug_rnglists` sections.
166    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    /// Return the `.debug_ranges` section.
174    pub fn debug_ranges(&self) -> &DebugRanges<R> {
175        &self.debug_ranges
176    }
177
178    /// Replace the `.debug_ranges` section.
179    ///
180    /// This is useful for `.dwo` files when using the GNU split-dwarf extension to DWARF 4.
181    pub fn set_debug_ranges(&mut self, debug_ranges: DebugRanges<R>) {
182        self.debug_ranges = debug_ranges;
183    }
184
185    /// Return the `.debug_rnglists` section.
186    pub fn debug_rnglists(&self) -> &DebugRngLists<R> {
187        &self.debug_rnglists
188    }
189}
190
191impl<T> RangeLists<T> {
192    /// Create a `RangeLists` that references the data in `self`.
193    ///
194    /// This is useful when `R` implements `Reader` but `T` does not.
195    ///
196    /// Used by `Dwarf::borrow`.
197    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    /// Iterate over the `Range` list entries starting at the given offset.
210    ///
211    /// The `unit_version` and `address_size` must match the compilation unit that the
212    /// offset was contained in.
213    ///
214    /// The `base_address` should be obtained from the `DW_AT_low_pc` attribute in the
215    /// `DW_TAG_compile_unit` entry for the compilation unit that contains this range list.
216    ///
217    /// Can be [used with
218    /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
219    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    /// Iterate over the `RawRngListEntry`ies starting at the given offset.
236    ///
237    /// The `unit_encoding` must match the compilation unit that the
238    /// offset was contained in.
239    ///
240    /// This iterator does not perform any processing of the range entries,
241    /// such as handling base addresses.
242    ///
243    /// Can be [used with
244    /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
245    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    /// Returns the `.debug_rnglists` offset at the given `base` and `index`.
260    ///
261    /// The `base` must be the `DW_AT_rnglists_base` value from the compilation unit DIE.
262    /// This is an offset that points to the first entry following the header.
263    ///
264    /// The `index` is the value of a `DW_FORM_rnglistx` attribute.
265    ///
266    /// The `unit_encoding` must match the compilation unit that the
267    /// index was contained in.
268    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    /// Call `Reader::lookup_offset_id` for each section, and return the first match.
286    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    /// The bare range list format used before DWARF 5.
296    Bare,
297    /// The DW_RLE encoded range list format used in DWARF 5.
298    Rle,
299}
300
301/// A raw iterator over an address range list.
302///
303/// This iterator does not perform any processing of the range entries,
304/// such as handling base addresses.
305#[derive(Debug)]
306pub struct RawRngListIter<R: Reader> {
307    input: R,
308    encoding: Encoding,
309    format: RangeListsFormat,
310}
311
312/// A raw entry in .debug_rnglists
313#[derive(Clone, Debug)]
314pub enum RawRngListEntry<T> {
315    /// A range from DWARF version <= 4.
316    AddressOrOffsetPair {
317        /// Start of range. May be an address or an offset.
318        begin: u64,
319        /// End of range. May be an address or an offset.
320        end: u64,
321    },
322    /// DW_RLE_base_address
323    BaseAddress {
324        /// base address
325        addr: u64,
326    },
327    /// DW_RLE_base_addressx
328    BaseAddressx {
329        /// base address
330        addr: DebugAddrIndex<T>,
331    },
332    /// DW_RLE_startx_endx
333    StartxEndx {
334        /// start of range
335        begin: DebugAddrIndex<T>,
336        /// end of range
337        end: DebugAddrIndex<T>,
338    },
339    /// DW_RLE_startx_length
340    StartxLength {
341        /// start of range
342        begin: DebugAddrIndex<T>,
343        /// length of range
344        length: u64,
345    },
346    /// DW_RLE_offset_pair
347    OffsetPair {
348        /// start of range
349        begin: u64,
350        /// end of range
351        end: u64,
352    },
353    /// DW_RLE_start_end
354    StartEnd {
355        /// start of range
356        begin: u64,
357        /// end of range
358        end: u64,
359    },
360    /// DW_RLE_start_length
361    StartLength {
362        /// start of range
363        begin: u64,
364        /// length of range
365        length: u64,
366    },
367}
368
369impl<T: ReaderOffset> RawRngListEntry<T> {
370    /// Parse a range entry from `.debug_rnglists`
371    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    /// Construct a `RawRngListIter`.
428    fn new(input: R, encoding: Encoding, format: RangeListsFormat) -> RawRngListIter<R> {
429        RawRngListIter {
430            input,
431            encoding,
432            format,
433        }
434    }
435
436    /// Advance the iterator to the next range.
437    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/// An iterator over an address range list.
468///
469/// This iterator internally handles processing of base addresses and different
470/// entry types.  Thus, it only returns range entries that are valid
471/// and already adjusted for the base address.
472#[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    /// Construct a `RngListIter`.
482    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    /// Advance the iterator to the next range.
503    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    /// Return the next raw range.
518    ///
519    /// The raw range should be passed to `convert_range`.
520    #[doc(hidden)]
521    pub fn next_raw(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>> {
522        self.raw.next()
523    }
524
525    /// Convert a raw range into a range, and update the state of the iterator.
526    ///
527    /// The raw range should have been obtained from `next_raw`.
528    #[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 {
560                    return Ok(None);
561                }
562                let mut range = Range { begin, end };
563                range.add_base_address(self.base_address, self.raw.encoding.address_size);
564                range
565            }
566            RawRngListEntry::StartEnd { begin, end } => Range { begin, end },
567            RawRngListEntry::StartLength { begin, length } => {
568                let end = begin.wrapping_add_sized(length, address_size);
569                Range { begin, end }
570            }
571        };
572
573        if range.begin == tombstone || range.begin > range.end {
574            return Ok(None);
575        }
576
577        Ok(Some(range))
578    }
579}
580
581#[cfg(feature = "fallible-iterator")]
582impl<R: Reader> fallible_iterator::FallibleIterator for RngListIter<R> {
583    type Item = Range;
584    type Error = Error;
585
586    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
587        RngListIter::next(self)
588    }
589}
590
591/// A raw address range from the `.debug_ranges` section.
592#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
593pub(crate) struct RawRange {
594    /// The beginning address of the range.
595    pub begin: u64,
596
597    /// The first address past the end of the range.
598    pub end: u64,
599}
600
601impl RawRange {
602    /// Check if this is a range end entry.
603    #[inline]
604    pub fn is_end(&self) -> bool {
605        self.begin == 0 && self.end == 0
606    }
607
608    /// Check if this is a base address selection entry.
609    ///
610    /// A base address selection entry changes the base address that subsequent
611    /// range entries are relative to.
612    #[inline]
613    pub fn is_base_address(&self, address_size: u8) -> bool {
614        self.begin == !0 >> (64 - address_size * 8)
615    }
616
617    /// Parse an address range entry from `.debug_ranges` or `.debug_loc`.
618    #[inline]
619    pub fn parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange> {
620        let begin = input.read_address(address_size)?;
621        let end = input.read_address(address_size)?;
622        let range = RawRange { begin, end };
623        Ok(range)
624    }
625}
626
627/// An address range from the `.debug_ranges`, `.debug_rnglists`, or `.debug_aranges` sections.
628#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
629pub struct Range {
630    /// The beginning address of the range.
631    pub begin: u64,
632
633    /// The first address past the end of the range.
634    pub end: u64,
635}
636
637impl Range {
638    /// Add a base address to this range.
639    #[inline]
640    pub(crate) fn add_base_address(&mut self, base_address: u64, address_size: u8) {
641        self.begin = base_address.wrapping_add_sized(self.begin, address_size);
642        self.end = base_address.wrapping_add_sized(self.end, address_size);
643    }
644}
645
646#[cfg(test)]
647mod tests {
648    use super::*;
649    use crate::common::Format;
650    use crate::endianity::LittleEndian;
651    use crate::test_util::GimliSectionMethods;
652    use test_assembler::{Endian, Label, LabelMaker, Section};
653
654    #[test]
655    fn test_rnglists_32() {
656        let tombstone = !0u32;
657        let encoding = Encoding {
658            format: Format::Dwarf32,
659            version: 5,
660            address_size: 4,
661        };
662        let section = Section::with_endian(Endian::Little)
663            .L32(0x0300_0000)
664            .L32(0x0301_0300)
665            .L32(0x0301_0400)
666            .L32(0x0301_0500)
667            .L32(tombstone)
668            .L32(0x0301_0600);
669        let buf = section.get_contents().unwrap();
670        let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
671        let debug_addr_base = DebugAddrBase(0);
672
673        let start = Label::new();
674        let first = Label::new();
675        let size = Label::new();
676        #[rustfmt::skip]
677        let section = Section::with_endian(Endian::Little)
678            // Header
679            .mark(&start)
680            .L32(&size)
681            .L16(encoding.version)
682            .L8(encoding.address_size)
683            .L8(0)
684            .L32(0)
685            .mark(&first)
686            // An OffsetPair using the unit base address.
687            .L8(4).uleb(0x10200).uleb(0x10300)
688            // A base address selection followed by an OffsetPair.
689            .L8(5).L32(0x0200_0000)
690            .L8(4).uleb(0x10400).uleb(0x10500)
691            // An empty OffsetPair followed by a normal OffsetPair.
692            .L8(4).uleb(0x10600).uleb(0x10600)
693            .L8(4).uleb(0x10800).uleb(0x10900)
694            // A StartEnd
695            .L8(6).L32(0x201_0a00).L32(0x201_0b00)
696            // A StartLength
697            .L8(7).L32(0x201_0c00).uleb(0x100)
698            // An OffsetPair that starts at 0.
699            .L8(4).uleb(0).uleb(1)
700            // An OffsetPair that starts and ends at 0.
701            .L8(4).uleb(0).uleb(0)
702            // An OffsetPair that ends at -1.
703            .L8(5).L32(0)
704            .L8(4).uleb(0).uleb(0xffff_ffff)
705            // A BaseAddressx + OffsetPair
706            .L8(1).uleb(0)
707            .L8(4).uleb(0x10100).uleb(0x10200)
708            // A StartxEndx
709            .L8(2).uleb(1).uleb(2)
710            // A StartxLength
711            .L8(3).uleb(3).uleb(0x100)
712
713            // Tombstone entries, all of which should be ignored.
714            // A BaseAddressx that is a tombstone.
715            .L8(1).uleb(4)
716            .L8(4).uleb(0x11100).uleb(0x11200)
717            // A BaseAddress that is a tombstone.
718            .L8(5).L32(tombstone)
719            .L8(4).uleb(0x11300).uleb(0x11400)
720            // A StartxEndx that is a tombstone.
721            .L8(2).uleb(4).uleb(5)
722            // A StartxLength that is a tombstone.
723            .L8(3).uleb(4).uleb(0x100)
724            // A StartEnd that is a tombstone.
725            .L8(6).L32(tombstone).L32(0x201_1500)
726            // A StartLength that is a tombstone.
727            .L8(7).L32(tombstone).uleb(0x100)
728            // A StartEnd (not ignored)
729            .L8(6).L32(0x201_1600).L32(0x201_1700)
730
731            // A range end.
732            .L8(0)
733            // Some extra data.
734            .L32(0xffff_ffff);
735        size.set_const((&section.here() - &start - 4) as u64);
736
737        let buf = section.get_contents().unwrap();
738        let debug_ranges = DebugRanges::new(&[], LittleEndian);
739        let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
740        let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
741        let offset = RangeListsOffset((&first - &start) as usize);
742        let mut ranges = rnglists
743            .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
744            .unwrap();
745
746        // A normal range.
747        assert_eq!(
748            ranges.next(),
749            Ok(Some(Range {
750                begin: 0x0101_0200,
751                end: 0x0101_0300,
752            }))
753        );
754
755        // A base address selection followed by a normal range.
756        assert_eq!(
757            ranges.next(),
758            Ok(Some(Range {
759                begin: 0x0201_0400,
760                end: 0x0201_0500,
761            }))
762        );
763
764        // An empty range followed by a normal range.
765        assert_eq!(
766            ranges.next(),
767            Ok(Some(Range {
768                begin: 0x0201_0600,
769                end: 0x0201_0600,
770            }))
771        );
772        assert_eq!(
773            ranges.next(),
774            Ok(Some(Range {
775                begin: 0x0201_0800,
776                end: 0x0201_0900,
777            }))
778        );
779
780        // A normal range.
781        assert_eq!(
782            ranges.next(),
783            Ok(Some(Range {
784                begin: 0x0201_0a00,
785                end: 0x0201_0b00,
786            }))
787        );
788
789        // A normal range.
790        assert_eq!(
791            ranges.next(),
792            Ok(Some(Range {
793                begin: 0x0201_0c00,
794                end: 0x0201_0d00,
795            }))
796        );
797
798        // A range that starts at 0.
799        assert_eq!(
800            ranges.next(),
801            Ok(Some(Range {
802                begin: 0x0200_0000,
803                end: 0x0200_0001,
804            }))
805        );
806
807        // A range that starts and ends at 0.
808        assert_eq!(
809            ranges.next(),
810            Ok(Some(Range {
811                begin: 0x0200_0000,
812                end: 0x0200_0000,
813            }))
814        );
815
816        // A range that ends at -1.
817        assert_eq!(
818            ranges.next(),
819            Ok(Some(Range {
820                begin: 0x0000_0000,
821                end: 0xffff_ffff,
822            }))
823        );
824
825        // A BaseAddressx + OffsetPair
826        assert_eq!(
827            ranges.next(),
828            Ok(Some(Range {
829                begin: 0x0301_0100,
830                end: 0x0301_0200,
831            }))
832        );
833
834        // A StartxEndx
835        assert_eq!(
836            ranges.next(),
837            Ok(Some(Range {
838                begin: 0x0301_0300,
839                end: 0x0301_0400,
840            }))
841        );
842
843        // A StartxLength
844        assert_eq!(
845            ranges.next(),
846            Ok(Some(Range {
847                begin: 0x0301_0500,
848                end: 0x0301_0600,
849            }))
850        );
851
852        // A StartEnd range following the tombstones
853        assert_eq!(
854            ranges.next(),
855            Ok(Some(Range {
856                begin: 0x0201_1600,
857                end: 0x0201_1700,
858            }))
859        );
860
861        // A range end.
862        assert_eq!(ranges.next(), Ok(None));
863
864        // An offset at the end of buf.
865        let mut ranges = rnglists
866            .ranges(
867                RangeListsOffset(buf.len()),
868                encoding,
869                0x0100_0000,
870                debug_addr,
871                debug_addr_base,
872            )
873            .unwrap();
874        assert_eq!(ranges.next(), Ok(None));
875    }
876
877    #[test]
878    fn test_rnglists_64() {
879        let tombstone = !0u64;
880        let encoding = Encoding {
881            format: Format::Dwarf64,
882            version: 5,
883            address_size: 8,
884        };
885        let section = Section::with_endian(Endian::Little)
886            .L64(0x0300_0000)
887            .L64(0x0301_0300)
888            .L64(0x0301_0400)
889            .L64(0x0301_0500)
890            .L64(tombstone)
891            .L64(0x0301_0600);
892        let buf = section.get_contents().unwrap();
893        let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
894        let debug_addr_base = DebugAddrBase(0);
895
896        let start = Label::new();
897        let first = Label::new();
898        let size = Label::new();
899        #[rustfmt::skip]
900        let section = Section::with_endian(Endian::Little)
901            // Header
902            .mark(&start)
903            .L32(0xffff_ffff)
904            .L64(&size)
905            .L16(encoding.version)
906            .L8(encoding.address_size)
907            .L8(0)
908            .L32(0)
909            .mark(&first)
910            // An OffsetPair using the unit base address.
911            .L8(4).uleb(0x10200).uleb(0x10300)
912            // A base address selection followed by an OffsetPair.
913            .L8(5).L64(0x0200_0000)
914            .L8(4).uleb(0x10400).uleb(0x10500)
915            // An empty OffsetPair followed by a normal OffsetPair.
916            .L8(4).uleb(0x10600).uleb(0x10600)
917            .L8(4).uleb(0x10800).uleb(0x10900)
918            // A StartEnd
919            .L8(6).L64(0x201_0a00).L64(0x201_0b00)
920            // A StartLength
921            .L8(7).L64(0x201_0c00).uleb(0x100)
922            // An OffsetPair that starts at 0.
923            .L8(4).uleb(0).uleb(1)
924            // An OffsetPair that starts and ends at 0.
925            .L8(4).uleb(0).uleb(0)
926            // An OffsetPair that ends at -1.
927            .L8(5).L64(0)
928            .L8(4).uleb(0).uleb(0xffff_ffff)
929            // A BaseAddressx + OffsetPair
930            .L8(1).uleb(0)
931            .L8(4).uleb(0x10100).uleb(0x10200)
932            // A StartxEndx
933            .L8(2).uleb(1).uleb(2)
934            // A StartxLength
935            .L8(3).uleb(3).uleb(0x100)
936
937            // Tombstone entries, all of which should be ignored.
938            // A BaseAddressx that is a tombstone.
939            .L8(1).uleb(4)
940            .L8(4).uleb(0x11100).uleb(0x11200)
941            // A BaseAddress that is a tombstone.
942            .L8(5).L64(tombstone)
943            .L8(4).uleb(0x11300).uleb(0x11400)
944            // A StartxEndx that is a tombstone.
945            .L8(2).uleb(4).uleb(5)
946            // A StartxLength that is a tombstone.
947            .L8(3).uleb(4).uleb(0x100)
948            // A StartEnd that is a tombstone.
949            .L8(6).L64(tombstone).L64(0x201_1500)
950            // A StartLength that is a tombstone.
951            .L8(7).L64(tombstone).uleb(0x100)
952            // A StartEnd (not ignored)
953            .L8(6).L64(0x201_1600).L64(0x201_1700)
954
955            // A range end.
956            .L8(0)
957            // Some extra data.
958            .L32(0xffff_ffff);
959        size.set_const((&section.here() - &start - 12) as u64);
960
961        let buf = section.get_contents().unwrap();
962        let debug_ranges = DebugRanges::new(&[], LittleEndian);
963        let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
964        let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
965        let offset = RangeListsOffset((&first - &start) as usize);
966        let mut ranges = rnglists
967            .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
968            .unwrap();
969
970        // A normal range.
971        assert_eq!(
972            ranges.next(),
973            Ok(Some(Range {
974                begin: 0x0101_0200,
975                end: 0x0101_0300,
976            }))
977        );
978
979        // A base address selection followed by a normal range.
980        assert_eq!(
981            ranges.next(),
982            Ok(Some(Range {
983                begin: 0x0201_0400,
984                end: 0x0201_0500,
985            }))
986        );
987
988        // An empty range followed by a normal range.
989        assert_eq!(
990            ranges.next(),
991            Ok(Some(Range {
992                begin: 0x0201_0600,
993                end: 0x0201_0600,
994            }))
995        );
996        assert_eq!(
997            ranges.next(),
998            Ok(Some(Range {
999                begin: 0x0201_0800,
1000                end: 0x0201_0900,
1001            }))
1002        );
1003
1004        // A normal range.
1005        assert_eq!(
1006            ranges.next(),
1007            Ok(Some(Range {
1008                begin: 0x0201_0a00,
1009                end: 0x0201_0b00,
1010            }))
1011        );
1012
1013        // A normal range.
1014        assert_eq!(
1015            ranges.next(),
1016            Ok(Some(Range {
1017                begin: 0x0201_0c00,
1018                end: 0x0201_0d00,
1019            }))
1020        );
1021
1022        // A range that starts at 0.
1023        assert_eq!(
1024            ranges.next(),
1025            Ok(Some(Range {
1026                begin: 0x0200_0000,
1027                end: 0x0200_0001,
1028            }))
1029        );
1030
1031        // A range that starts and ends at 0.
1032        assert_eq!(
1033            ranges.next(),
1034            Ok(Some(Range {
1035                begin: 0x0200_0000,
1036                end: 0x0200_0000,
1037            }))
1038        );
1039
1040        // A range that ends at -1.
1041        assert_eq!(
1042            ranges.next(),
1043            Ok(Some(Range {
1044                begin: 0x0000_0000,
1045                end: 0xffff_ffff,
1046            }))
1047        );
1048
1049        // A BaseAddressx + OffsetPair
1050        assert_eq!(
1051            ranges.next(),
1052            Ok(Some(Range {
1053                begin: 0x0301_0100,
1054                end: 0x0301_0200,
1055            }))
1056        );
1057
1058        // A StartxEndx
1059        assert_eq!(
1060            ranges.next(),
1061            Ok(Some(Range {
1062                begin: 0x0301_0300,
1063                end: 0x0301_0400,
1064            }))
1065        );
1066
1067        // A StartxLength
1068        assert_eq!(
1069            ranges.next(),
1070            Ok(Some(Range {
1071                begin: 0x0301_0500,
1072                end: 0x0301_0600,
1073            }))
1074        );
1075
1076        // A StartEnd range following the tombstones
1077        assert_eq!(
1078            ranges.next(),
1079            Ok(Some(Range {
1080                begin: 0x0201_1600,
1081                end: 0x0201_1700,
1082            }))
1083        );
1084
1085        // A range end.
1086        assert_eq!(ranges.next(), Ok(None));
1087
1088        // An offset at the end of buf.
1089        let mut ranges = rnglists
1090            .ranges(
1091                RangeListsOffset(buf.len()),
1092                encoding,
1093                0x0100_0000,
1094                debug_addr,
1095                debug_addr_base,
1096            )
1097            .unwrap();
1098        assert_eq!(ranges.next(), Ok(None));
1099    }
1100
1101    #[test]
1102    fn test_raw_range() {
1103        let range = RawRange {
1104            begin: 0,
1105            end: 0xffff_ffff,
1106        };
1107        assert!(!range.is_end());
1108        assert!(!range.is_base_address(4));
1109        assert!(!range.is_base_address(8));
1110
1111        let range = RawRange { begin: 0, end: 0 };
1112        assert!(range.is_end());
1113        assert!(!range.is_base_address(4));
1114        assert!(!range.is_base_address(8));
1115
1116        let range = RawRange {
1117            begin: 0xffff_ffff,
1118            end: 0,
1119        };
1120        assert!(!range.is_end());
1121        assert!(range.is_base_address(4));
1122        assert!(!range.is_base_address(8));
1123
1124        let range = RawRange {
1125            begin: 0xffff_ffff_ffff_ffff,
1126            end: 0,
1127        };
1128        assert!(!range.is_end());
1129        assert!(!range.is_base_address(4));
1130        assert!(range.is_base_address(8));
1131    }
1132
1133    #[test]
1134    fn test_ranges_32() {
1135        let tombstone = !0u32 - 1;
1136        let start = Label::new();
1137        let first = Label::new();
1138        #[rustfmt::skip]
1139        let section = Section::with_endian(Endian::Little)
1140            // A range before the offset.
1141            .mark(&start)
1142            .L32(0x10000).L32(0x10100)
1143            .mark(&first)
1144            // A normal range.
1145            .L32(0x10200).L32(0x10300)
1146            // A base address selection followed by a normal range.
1147            .L32(0xffff_ffff).L32(0x0200_0000)
1148            .L32(0x10400).L32(0x10500)
1149            // An empty range followed by a normal range.
1150            .L32(0x10600).L32(0x10600)
1151            .L32(0x10800).L32(0x10900)
1152            // A range that starts at 0.
1153            .L32(0).L32(1)
1154            // A range that ends at -1.
1155            .L32(0xffff_ffff).L32(0x0000_0000)
1156            .L32(0).L32(0xffff_ffff)
1157            // A normal range with tombstone.
1158            .L32(tombstone).L32(tombstone)
1159            // A base address selection with tombstone followed by a normal range.
1160            .L32(0xffff_ffff).L32(tombstone)
1161            .L32(0x10a00).L32(0x10b00)
1162            // A range end.
1163            .L32(0).L32(0)
1164            // Some extra data.
1165            .L32(0);
1166
1167        let buf = section.get_contents().unwrap();
1168        let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1169        let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1170        let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1171        let offset = RangeListsOffset((&first - &start) as usize);
1172        let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1173        let debug_addr_base = DebugAddrBase(0);
1174        let encoding = Encoding {
1175            format: Format::Dwarf32,
1176            version: 4,
1177            address_size: 4,
1178        };
1179        let mut ranges = rnglists
1180            .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
1181            .unwrap();
1182
1183        // A normal range.
1184        assert_eq!(
1185            ranges.next(),
1186            Ok(Some(Range {
1187                begin: 0x0101_0200,
1188                end: 0x0101_0300,
1189            }))
1190        );
1191
1192        // A base address selection followed by a normal range.
1193        assert_eq!(
1194            ranges.next(),
1195            Ok(Some(Range {
1196                begin: 0x0201_0400,
1197                end: 0x0201_0500,
1198            }))
1199        );
1200
1201        // An empty range followed by a normal range.
1202        assert_eq!(
1203            ranges.next(),
1204            Ok(Some(Range {
1205                begin: 0x0201_0600,
1206                end: 0x0201_0600,
1207            }))
1208        );
1209        assert_eq!(
1210            ranges.next(),
1211            Ok(Some(Range {
1212                begin: 0x0201_0800,
1213                end: 0x0201_0900,
1214            }))
1215        );
1216
1217        // A range that starts at 0.
1218        assert_eq!(
1219            ranges.next(),
1220            Ok(Some(Range {
1221                begin: 0x0200_0000,
1222                end: 0x0200_0001,
1223            }))
1224        );
1225
1226        // A range that ends at -1.
1227        assert_eq!(
1228            ranges.next(),
1229            Ok(Some(Range {
1230                begin: 0x0000_0000,
1231                end: 0xffff_ffff,
1232            }))
1233        );
1234
1235        // A range end.
1236        assert_eq!(ranges.next(), Ok(None));
1237
1238        // An offset at the end of buf.
1239        let mut ranges = rnglists
1240            .ranges(
1241                RangeListsOffset(buf.len()),
1242                encoding,
1243                0x0100_0000,
1244                debug_addr,
1245                debug_addr_base,
1246            )
1247            .unwrap();
1248        assert_eq!(ranges.next(), Ok(None));
1249    }
1250
1251    #[test]
1252    fn test_ranges_64() {
1253        let tombstone = !0u64 - 1;
1254        let start = Label::new();
1255        let first = Label::new();
1256        #[rustfmt::skip]
1257        let section = Section::with_endian(Endian::Little)
1258            // A range before the offset.
1259            .mark(&start)
1260            .L64(0x10000).L64(0x10100)
1261            .mark(&first)
1262            // A normal range.
1263            .L64(0x10200).L64(0x10300)
1264            // A base address selection followed by a normal range.
1265            .L64(0xffff_ffff_ffff_ffff).L64(0x0200_0000)
1266            .L64(0x10400).L64(0x10500)
1267            // An empty range followed by a normal range.
1268            .L64(0x10600).L64(0x10600)
1269            .L64(0x10800).L64(0x10900)
1270            // A range that starts at 0.
1271            .L64(0).L64(1)
1272            // A range that ends at -1.
1273            .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
1274            .L64(0).L64(0xffff_ffff_ffff_ffff)
1275            // A normal range with tombstone.
1276            .L64(tombstone).L64(tombstone)
1277            // A base address selection with tombstone followed by a normal range.
1278            .L64(0xffff_ffff_ffff_ffff).L64(tombstone)
1279            .L64(0x10a00).L64(0x10b00)
1280            // A range end.
1281            .L64(0).L64(0)
1282            // Some extra data.
1283            .L64(0);
1284
1285        let buf = section.get_contents().unwrap();
1286        let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1287        let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1288        let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1289        let offset = RangeListsOffset((&first - &start) as usize);
1290        let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1291        let debug_addr_base = DebugAddrBase(0);
1292        let encoding = Encoding {
1293            format: Format::Dwarf64,
1294            version: 4,
1295            address_size: 8,
1296        };
1297        let mut ranges = rnglists
1298            .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
1299            .unwrap();
1300
1301        // A normal range.
1302        assert_eq!(
1303            ranges.next(),
1304            Ok(Some(Range {
1305                begin: 0x0101_0200,
1306                end: 0x0101_0300,
1307            }))
1308        );
1309
1310        // A base address selection followed by a normal range.
1311        assert_eq!(
1312            ranges.next(),
1313            Ok(Some(Range {
1314                begin: 0x0201_0400,
1315                end: 0x0201_0500,
1316            }))
1317        );
1318
1319        // An empty range followed by a normal range.
1320        assert_eq!(
1321            ranges.next(),
1322            Ok(Some(Range {
1323                begin: 0x0201_0600,
1324                end: 0x0201_0600,
1325            }))
1326        );
1327        assert_eq!(
1328            ranges.next(),
1329            Ok(Some(Range {
1330                begin: 0x0201_0800,
1331                end: 0x0201_0900,
1332            }))
1333        );
1334
1335        // A range that starts at 0.
1336        assert_eq!(
1337            ranges.next(),
1338            Ok(Some(Range {
1339                begin: 0x0200_0000,
1340                end: 0x0200_0001,
1341            }))
1342        );
1343
1344        // A range that ends at -1.
1345        assert_eq!(
1346            ranges.next(),
1347            Ok(Some(Range {
1348                begin: 0x0,
1349                end: 0xffff_ffff_ffff_ffff,
1350            }))
1351        );
1352
1353        // A range end.
1354        assert_eq!(ranges.next(), Ok(None));
1355
1356        // An offset at the end of buf.
1357        let mut ranges = rnglists
1358            .ranges(
1359                RangeListsOffset(buf.len()),
1360                encoding,
1361                0x0100_0000,
1362                debug_addr,
1363                debug_addr_base,
1364            )
1365            .unwrap();
1366        assert_eq!(ranges.next(), Ok(None));
1367    }
1368
1369    #[test]
1370    fn test_ranges_invalid() {
1371        #[rustfmt::skip]
1372        let section = Section::with_endian(Endian::Little)
1373            // An invalid range.
1374            .L32(0x20000).L32(0x10000)
1375            // An invalid range after wrapping.
1376            .L32(0x20000).L32(0xff01_0000);
1377
1378        let buf = section.get_contents().unwrap();
1379        let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1380        let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1381        let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1382        let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1383        let debug_addr_base = DebugAddrBase(0);
1384        let encoding = Encoding {
1385            format: Format::Dwarf32,
1386            version: 4,
1387            address_size: 4,
1388        };
1389
1390        // An invalid range.
1391        let mut ranges = rnglists
1392            .ranges(
1393                RangeListsOffset(0x0),
1394                encoding,
1395                0x0100_0000,
1396                debug_addr,
1397                debug_addr_base,
1398            )
1399            .unwrap();
1400        assert_eq!(ranges.next(), Ok(None));
1401
1402        // An invalid range after wrapping.
1403        let mut ranges = rnglists
1404            .ranges(
1405                RangeListsOffset(0x8),
1406                encoding,
1407                0x0100_0000,
1408                debug_addr,
1409                debug_addr_base,
1410            )
1411            .unwrap();
1412        assert_eq!(ranges.next(), Ok(None));
1413
1414        // An invalid offset.
1415        match rnglists.ranges(
1416            RangeListsOffset(buf.len() + 1),
1417            encoding,
1418            0x0100_0000,
1419            debug_addr,
1420            debug_addr_base,
1421        ) {
1422            Err(Error::UnexpectedEof(_)) => {}
1423            otherwise => panic!("Unexpected result: {:?}", otherwise),
1424        }
1425    }
1426
1427    #[test]
1428    fn test_get_offset() {
1429        for format in [Format::Dwarf32, Format::Dwarf64] {
1430            let encoding = Encoding {
1431                format,
1432                version: 5,
1433                address_size: 4,
1434            };
1435
1436            let zero = Label::new();
1437            let length = Label::new();
1438            let start = Label::new();
1439            let first = Label::new();
1440            let end = Label::new();
1441            let mut section = Section::with_endian(Endian::Little)
1442                .mark(&zero)
1443                .initial_length(format, &length, &start)
1444                .D16(encoding.version)
1445                .D8(encoding.address_size)
1446                .D8(0)
1447                .D32(20)
1448                .mark(&first);
1449            for i in 0..20 {
1450                section = section.word(format.word_size(), 1000 + i);
1451            }
1452            section = section.mark(&end);
1453            length.set_const((&end - &start) as u64);
1454            let section = section.get_contents().unwrap();
1455
1456            let debug_ranges = DebugRanges::from(EndianSlice::new(&[], LittleEndian));
1457            let debug_rnglists = DebugRngLists::from(EndianSlice::new(&section, LittleEndian));
1458            let ranges = RangeLists::new(debug_ranges, debug_rnglists);
1459
1460            let base = DebugRngListsBase((&first - &zero) as usize);
1461            assert_eq!(
1462                ranges.get_offset(encoding, base, DebugRngListsIndex(0)),
1463                Ok(RangeListsOffset(base.0 + 1000))
1464            );
1465            assert_eq!(
1466                ranges.get_offset(encoding, base, DebugRngListsIndex(19)),
1467                Ok(RangeListsOffset(base.0 + 1019))
1468            );
1469        }
1470    }
1471}