1 use crate::common::{
2     DebugAddrBase, DebugAddrIndex, DebugRngListsBase, DebugRngListsIndex, DwarfFileType, Encoding,
3     RangeListsOffset, SectionId,
4 };
5 use crate::constants;
6 use crate::endianity::Endianity;
7 use crate::read::{
8     lists::ListsHeader, DebugAddr, EndianSlice, Error, Reader, ReaderOffset, ReaderOffsetId,
9     Result, Section,
10 };
11 
12 /// The raw contents of the `.debug_ranges` section.
13 #[derive(Debug, Default, Clone, Copy)]
14 pub struct DebugRanges<R> {
15     pub(crate) section: R,
16 }
17 
18 impl<'input, Endian> DebugRanges<EndianSlice<'input, Endian>>
19 where
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 OSX, 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     /// ```
new(section: &'input [u8], endian: Endian) -> Self36     pub fn new(section: &'input [u8], endian: Endian) -> Self {
37         Self::from(EndianSlice::new(section, endian))
38     }
39 }
40 
41 impl<R> Section<R> for DebugRanges<R> {
id() -> SectionId42     fn id() -> SectionId {
43         SectionId::DebugRanges
44     }
45 
reader(&self) -> &R46     fn reader(&self) -> &R {
47         &self.section
48     }
49 }
50 
51 impl<R> From<R> for DebugRanges<R> {
from(section: R) -> Self52     fn from(section: R) -> Self {
53         DebugRanges { section }
54     }
55 }
56 
57 /// The `DebugRngLists` struct represents the contents of the
58 /// `.debug_rnglists` section.
59 #[derive(Debug, Default, Clone, Copy)]
60 pub struct DebugRngLists<R> {
61     section: R,
62 }
63 
64 impl<'input, Endian> DebugRngLists<EndianSlice<'input, Endian>>
65 where
66     Endian: Endianity,
67 {
68     /// Construct a new `DebugRngLists` instance from the data in the
69     /// `.debug_rnglists` section.
70     ///
71     /// It is the caller's responsibility to read the `.debug_rnglists`
72     /// section and present it as a `&[u8]` slice. That means using some ELF
73     /// loader on Linux, a Mach-O loader on OSX, etc.
74     ///
75     /// ```
76     /// use gimli::{DebugRngLists, LittleEndian};
77     ///
78     /// # let buf = [0x00, 0x01, 0x02, 0x03];
79     /// # let read_debug_rnglists_section_somehow = || &buf;
80     /// let debug_rnglists =
81     ///     DebugRngLists::new(read_debug_rnglists_section_somehow(), LittleEndian);
82     /// ```
new(section: &'input [u8], endian: Endian) -> Self83     pub fn new(section: &'input [u8], endian: Endian) -> Self {
84         Self::from(EndianSlice::new(section, endian))
85     }
86 }
87 
88 impl<R> Section<R> for DebugRngLists<R> {
id() -> SectionId89     fn id() -> SectionId {
90         SectionId::DebugRngLists
91     }
92 
reader(&self) -> &R93     fn reader(&self) -> &R {
94         &self.section
95     }
96 }
97 
98 impl<R> From<R> for DebugRngLists<R> {
from(section: R) -> Self99     fn from(section: R) -> Self {
100         DebugRngLists { section }
101     }
102 }
103 
104 #[allow(unused)]
105 pub(crate) type RngListsHeader = ListsHeader;
106 
107 impl<Offset> DebugRngListsBase<Offset>
108 where
109     Offset: ReaderOffset,
110 {
111     /// Returns a `DebugRngListsBase` with the default value of DW_AT_rnglists_base
112     /// for the given `Encoding` and `DwarfFileType`.
default_for_encoding_and_file( encoding: Encoding, file_type: DwarfFileType, ) -> DebugRngListsBase<Offset>113     pub fn default_for_encoding_and_file(
114         encoding: Encoding,
115         file_type: DwarfFileType,
116     ) -> DebugRngListsBase<Offset> {
117         if encoding.version >= 5 && file_type == DwarfFileType::Dwo {
118             // In .dwo files, the compiler omits the DW_AT_rnglists_base attribute (because there is
119             // only a single unit in the file) but we must skip past the header, which the attribute
120             // would normally do for us.
121             DebugRngListsBase(Offset::from_u8(RngListsHeader::size_for_encoding(encoding)))
122         } else {
123             DebugRngListsBase(Offset::from_u8(0))
124         }
125     }
126 }
127 
128 /// The DWARF data found in `.debug_ranges` and `.debug_rnglists` sections.
129 #[derive(Debug, Default, Clone, Copy)]
130 pub struct RangeLists<R> {
131     debug_ranges: DebugRanges<R>,
132     debug_rnglists: DebugRngLists<R>,
133 }
134 
135 impl<R> RangeLists<R> {
136     /// Construct a new `RangeLists` instance from the data in the `.debug_ranges` and
137     /// `.debug_rnglists` sections.
new(debug_ranges: DebugRanges<R>, debug_rnglists: DebugRngLists<R>) -> RangeLists<R>138     pub fn new(debug_ranges: DebugRanges<R>, debug_rnglists: DebugRngLists<R>) -> RangeLists<R> {
139         RangeLists {
140             debug_ranges,
141             debug_rnglists,
142         }
143     }
144 }
145 
146 impl<T> RangeLists<T> {
147     /// Create a `RangeLists` that references the data in `self`.
148     ///
149     /// This is useful when `R` implements `Reader` but `T` does not.
150     ///
151     /// ## Example Usage
152     ///
153     /// ```rust,no_run
154     /// # let load_section = || unimplemented!();
155     /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
156     /// let owned_section: gimli::RangeLists<Vec<u8>> = load_section();
157     /// // Create a reference to the DWARF section.
158     /// let section = owned_section.borrow(|section| {
159     ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
160     /// });
161     /// ```
borrow<'a, F, R>(&'a self, mut borrow: F) -> RangeLists<R> where F: FnMut(&'a T) -> R,162     pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> RangeLists<R>
163     where
164         F: FnMut(&'a T) -> R,
165     {
166         RangeLists {
167             debug_ranges: borrow(&self.debug_ranges.section).into(),
168             debug_rnglists: borrow(&self.debug_rnglists.section).into(),
169         }
170     }
171 }
172 
173 impl<R: Reader> RangeLists<R> {
174     /// Iterate over the `Range` list entries starting at the given offset.
175     ///
176     /// The `unit_version` and `address_size` must match the compilation unit that the
177     /// offset was contained in.
178     ///
179     /// The `base_address` should be obtained from the `DW_AT_low_pc` attribute in the
180     /// `DW_TAG_compile_unit` entry for the compilation unit that contains this range list.
181     ///
182     /// Can be [used with
183     /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
ranges( &self, offset: RangeListsOffset<R::Offset>, unit_encoding: Encoding, base_address: u64, debug_addr: &DebugAddr<R>, debug_addr_base: DebugAddrBase<R::Offset>, ) -> Result<RngListIter<R>>184     pub fn ranges(
185         &self,
186         offset: RangeListsOffset<R::Offset>,
187         unit_encoding: Encoding,
188         base_address: u64,
189         debug_addr: &DebugAddr<R>,
190         debug_addr_base: DebugAddrBase<R::Offset>,
191     ) -> Result<RngListIter<R>> {
192         Ok(RngListIter::new(
193             self.raw_ranges(offset, unit_encoding)?,
194             base_address,
195             debug_addr.clone(),
196             debug_addr_base,
197         ))
198     }
199 
200     /// Iterate over the `RawRngListEntry`ies starting at the given offset.
201     ///
202     /// The `unit_encoding` must match the compilation unit that the
203     /// offset was contained in.
204     ///
205     /// This iterator does not perform any processing of the range entries,
206     /// such as handling base addresses.
207     ///
208     /// Can be [used with
209     /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
raw_ranges( &self, offset: RangeListsOffset<R::Offset>, unit_encoding: Encoding, ) -> Result<RawRngListIter<R>>210     pub fn raw_ranges(
211         &self,
212         offset: RangeListsOffset<R::Offset>,
213         unit_encoding: Encoding,
214     ) -> Result<RawRngListIter<R>> {
215         let (mut input, format) = if unit_encoding.version <= 4 {
216             (self.debug_ranges.section.clone(), RangeListsFormat::Bare)
217         } else {
218             (self.debug_rnglists.section.clone(), RangeListsFormat::RLE)
219         };
220         input.skip(offset.0)?;
221         Ok(RawRngListIter::new(input, unit_encoding, format))
222     }
223 
224     /// Returns the `.debug_rnglists` offset at the given `base` and `index`.
225     ///
226     /// The `base` must be the `DW_AT_rnglists_base` value from the compilation unit DIE.
227     /// This is an offset that points to the first entry following the header.
228     ///
229     /// The `index` is the value of a `DW_FORM_rnglistx` attribute.
230     ///
231     /// The `unit_encoding` must match the compilation unit that the
232     /// index was contained in.
get_offset( &self, unit_encoding: Encoding, base: DebugRngListsBase<R::Offset>, index: DebugRngListsIndex<R::Offset>, ) -> Result<RangeListsOffset<R::Offset>>233     pub fn get_offset(
234         &self,
235         unit_encoding: Encoding,
236         base: DebugRngListsBase<R::Offset>,
237         index: DebugRngListsIndex<R::Offset>,
238     ) -> Result<RangeListsOffset<R::Offset>> {
239         let format = unit_encoding.format;
240         let input = &mut self.debug_rnglists.section.clone();
241         input.skip(base.0)?;
242         input.skip(R::Offset::from_u64(
243             index.0.into_u64() * u64::from(format.word_size()),
244         )?)?;
245         input
246             .read_offset(format)
247             .map(|x| RangeListsOffset(base.0 + x))
248     }
249 
250     /// Call `Reader::lookup_offset_id` for each section, and return the first match.
lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)>251     pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)> {
252         self.debug_ranges
253             .lookup_offset_id(id)
254             .or_else(|| self.debug_rnglists.lookup_offset_id(id))
255     }
256 }
257 
258 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
259 enum RangeListsFormat {
260     /// The bare range list format used before DWARF 5.
261     Bare,
262     /// The DW_RLE encoded range list format used in DWARF 5.
263     RLE,
264 }
265 
266 /// A raw iterator over an address range list.
267 ///
268 /// This iterator does not perform any processing of the range entries,
269 /// such as handling base addresses.
270 #[derive(Debug)]
271 pub struct RawRngListIter<R: Reader> {
272     input: R,
273     encoding: Encoding,
274     format: RangeListsFormat,
275 }
276 
277 /// A raw entry in .debug_rnglists
278 #[derive(Clone, Debug)]
279 pub enum RawRngListEntry<T> {
280     /// A range from DWARF version <= 4.
281     AddressOrOffsetPair {
282         /// Start of range. May be an address or an offset.
283         begin: u64,
284         /// End of range. May be an address or an offset.
285         end: u64,
286     },
287     /// DW_RLE_base_address
288     BaseAddress {
289         /// base address
290         addr: u64,
291     },
292     /// DW_RLE_base_addressx
293     BaseAddressx {
294         /// base address
295         addr: DebugAddrIndex<T>,
296     },
297     /// DW_RLE_startx_endx
298     StartxEndx {
299         /// start of range
300         begin: DebugAddrIndex<T>,
301         /// end of range
302         end: DebugAddrIndex<T>,
303     },
304     /// DW_RLE_startx_length
305     StartxLength {
306         /// start of range
307         begin: DebugAddrIndex<T>,
308         /// length of range
309         length: u64,
310     },
311     /// DW_RLE_offset_pair
312     OffsetPair {
313         /// start of range
314         begin: u64,
315         /// end of range
316         end: u64,
317     },
318     /// DW_RLE_start_end
319     StartEnd {
320         /// start of range
321         begin: u64,
322         /// end of range
323         end: u64,
324     },
325     /// DW_RLE_start_length
326     StartLength {
327         /// start of range
328         begin: u64,
329         /// length of range
330         length: u64,
331     },
332 }
333 
334 impl<T: ReaderOffset> RawRngListEntry<T> {
335     /// Parse a range entry from `.debug_rnglists`
parse<R: Reader<Offset = T>>( input: &mut R, encoding: Encoding, format: RangeListsFormat, ) -> Result<Option<Self>>336     fn parse<R: Reader<Offset = T>>(
337         input: &mut R,
338         encoding: Encoding,
339         format: RangeListsFormat,
340     ) -> Result<Option<Self>> {
341         match format {
342             RangeListsFormat::Bare => {
343                 let range = RawRange::parse(input, encoding.address_size)?;
344                 return Ok(if range.is_end() {
345                     None
346                 } else if range.is_base_address(encoding.address_size) {
347                     Some(RawRngListEntry::BaseAddress { addr: range.end })
348                 } else {
349                     Some(RawRngListEntry::AddressOrOffsetPair {
350                         begin: range.begin,
351                         end: range.end,
352                     })
353                 });
354             }
355             RangeListsFormat::RLE => Ok(match constants::DwRle(input.read_u8()?) {
356                 constants::DW_RLE_end_of_list => None,
357                 constants::DW_RLE_base_addressx => Some(RawRngListEntry::BaseAddressx {
358                     addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
359                 }),
360                 constants::DW_RLE_startx_endx => Some(RawRngListEntry::StartxEndx {
361                     begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
362                     end: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
363                 }),
364                 constants::DW_RLE_startx_length => Some(RawRngListEntry::StartxLength {
365                     begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
366                     length: input.read_uleb128()?,
367                 }),
368                 constants::DW_RLE_offset_pair => Some(RawRngListEntry::OffsetPair {
369                     begin: input.read_uleb128()?,
370                     end: input.read_uleb128()?,
371                 }),
372                 constants::DW_RLE_base_address => Some(RawRngListEntry::BaseAddress {
373                     addr: input.read_address(encoding.address_size)?,
374                 }),
375                 constants::DW_RLE_start_end => Some(RawRngListEntry::StartEnd {
376                     begin: input.read_address(encoding.address_size)?,
377                     end: input.read_address(encoding.address_size)?,
378                 }),
379                 constants::DW_RLE_start_length => Some(RawRngListEntry::StartLength {
380                     begin: input.read_address(encoding.address_size)?,
381                     length: input.read_uleb128()?,
382                 }),
383                 _ => {
384                     return Err(Error::InvalidAddressRange);
385                 }
386             }),
387         }
388     }
389 }
390 
391 impl<R: Reader> RawRngListIter<R> {
392     /// Construct a `RawRngListIter`.
new(input: R, encoding: Encoding, format: RangeListsFormat) -> RawRngListIter<R>393     fn new(input: R, encoding: Encoding, format: RangeListsFormat) -> RawRngListIter<R> {
394         RawRngListIter {
395             input,
396             encoding,
397             format,
398         }
399     }
400 
401     /// Advance the iterator to the next range.
next(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>>402     pub fn next(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>> {
403         if self.input.is_empty() {
404             return Ok(None);
405         }
406 
407         match RawRngListEntry::parse(&mut self.input, self.encoding, self.format) {
408             Ok(range) => {
409                 if range.is_none() {
410                     self.input.empty();
411                 }
412                 Ok(range)
413             }
414             Err(e) => {
415                 self.input.empty();
416                 Err(e)
417             }
418         }
419     }
420 }
421 
422 #[cfg(feature = "fallible-iterator")]
423 impl<R: Reader> fallible_iterator::FallibleIterator for RawRngListIter<R> {
424     type Item = RawRngListEntry<R::Offset>;
425     type Error = Error;
426 
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>427     fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
428         RawRngListIter::next(self)
429     }
430 }
431 
432 /// An iterator over an address range list.
433 ///
434 /// This iterator internally handles processing of base addresses and different
435 /// entry types.  Thus, it only returns range entries that are valid
436 /// and already adjusted for the base address.
437 #[derive(Debug)]
438 pub struct RngListIter<R: Reader> {
439     raw: RawRngListIter<R>,
440     base_address: u64,
441     debug_addr: DebugAddr<R>,
442     debug_addr_base: DebugAddrBase<R::Offset>,
443 }
444 
445 impl<R: Reader> RngListIter<R> {
446     /// Construct a `RngListIter`.
new( raw: RawRngListIter<R>, base_address: u64, debug_addr: DebugAddr<R>, debug_addr_base: DebugAddrBase<R::Offset>, ) -> RngListIter<R>447     fn new(
448         raw: RawRngListIter<R>,
449         base_address: u64,
450         debug_addr: DebugAddr<R>,
451         debug_addr_base: DebugAddrBase<R::Offset>,
452     ) -> RngListIter<R> {
453         RngListIter {
454             raw,
455             base_address,
456             debug_addr,
457             debug_addr_base,
458         }
459     }
460 
461     #[inline]
get_address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64>462     fn get_address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
463         self.debug_addr
464             .get_address(self.raw.encoding.address_size, self.debug_addr_base, index)
465     }
466 
467     /// Advance the iterator to the next range.
next(&mut self) -> Result<Option<Range>>468     pub fn next(&mut self) -> Result<Option<Range>> {
469         loop {
470             let raw_range = match self.raw.next()? {
471                 Some(range) => range,
472                 None => return Ok(None),
473             };
474 
475             let range = match raw_range {
476                 RawRngListEntry::BaseAddress { addr } => {
477                     self.base_address = addr;
478                     continue;
479                 }
480                 RawRngListEntry::BaseAddressx { addr } => {
481                     self.base_address = self.get_address(addr)?;
482                     continue;
483                 }
484                 RawRngListEntry::StartxEndx { begin, end } => {
485                     let begin = self.get_address(begin)?;
486                     let end = self.get_address(end)?;
487                     Range { begin, end }
488                 }
489                 RawRngListEntry::StartxLength { begin, length } => {
490                     let begin = self.get_address(begin)?;
491                     let end = begin + length;
492                     Range { begin, end }
493                 }
494                 RawRngListEntry::AddressOrOffsetPair { begin, end }
495                 | RawRngListEntry::OffsetPair { begin, end } => {
496                     let mut range = Range { begin, end };
497                     range.add_base_address(self.base_address, self.raw.encoding.address_size);
498                     range
499                 }
500                 RawRngListEntry::StartEnd { begin, end } => Range { begin, end },
501                 RawRngListEntry::StartLength { begin, length } => Range {
502                     begin,
503                     end: begin + length,
504                 },
505             };
506 
507             if range.begin > range.end {
508                 self.raw.input.empty();
509                 return Err(Error::InvalidAddressRange);
510             }
511 
512             return Ok(Some(range));
513         }
514     }
515 }
516 
517 #[cfg(feature = "fallible-iterator")]
518 impl<R: Reader> fallible_iterator::FallibleIterator for RngListIter<R> {
519     type Item = Range;
520     type Error = Error;
521 
next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error>522     fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
523         RngListIter::next(self)
524     }
525 }
526 
527 /// A raw address range from the `.debug_ranges` section.
528 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
529 pub(crate) struct RawRange {
530     /// The beginning address of the range.
531     pub begin: u64,
532 
533     /// The first address past the end of the range.
534     pub end: u64,
535 }
536 
537 impl RawRange {
538     /// Check if this is a range end entry.
539     ///
540     /// This will only occur for raw ranges.
541     #[inline]
is_end(&self) -> bool542     pub fn is_end(&self) -> bool {
543         self.begin == 0 && self.end == 0
544     }
545 
546     /// Check if this is a base address selection entry.
547     ///
548     /// A base address selection entry changes the base address that subsequent
549     /// range entries are relative to.  This will only occur for raw ranges.
550     #[inline]
is_base_address(&self, address_size: u8) -> bool551     pub fn is_base_address(&self, address_size: u8) -> bool {
552         self.begin == !0 >> (64 - address_size * 8)
553     }
554 
555     /// Parse an address range entry from `.debug_ranges` or `.debug_loc`.
556     #[doc(hidden)]
557     #[inline]
parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange>558     pub fn parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange> {
559         let begin = input.read_address(address_size)?;
560         let end = input.read_address(address_size)?;
561         let range = RawRange { begin, end };
562         Ok(range)
563     }
564 }
565 
566 /// An address range from the `.debug_ranges` or `.debug_rnglists` sections.
567 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
568 pub struct Range {
569     /// The beginning address of the range.
570     pub begin: u64,
571 
572     /// The first address past the end of the range.
573     pub end: u64,
574 }
575 
576 impl Range {
577     /// Add a base address to this range.
578     #[inline]
add_base_address(&mut self, base_address: u64, address_size: u8)579     pub(crate) fn add_base_address(&mut self, base_address: u64, address_size: u8) {
580         let mask = !0 >> (64 - address_size * 8);
581         self.begin = base_address.wrapping_add(self.begin) & mask;
582         self.end = base_address.wrapping_add(self.end) & mask;
583     }
584 }
585 
586 #[cfg(test)]
587 mod tests {
588     use super::*;
589     use crate::common::Format;
590     use crate::endianity::LittleEndian;
591     use crate::test_util::GimliSectionMethods;
592     use test_assembler::{Endian, Label, LabelMaker, Section};
593 
594     #[test]
test_rnglists_32()595     fn test_rnglists_32() {
596         let encoding = Encoding {
597             format: Format::Dwarf32,
598             version: 5,
599             address_size: 4,
600         };
601         let section = Section::with_endian(Endian::Little)
602             .L32(0x0300_0000)
603             .L32(0x0301_0300)
604             .L32(0x0301_0400)
605             .L32(0x0301_0500);
606         let buf = section.get_contents().unwrap();
607         let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
608         let debug_addr_base = DebugAddrBase(0);
609 
610         let start = Label::new();
611         let first = Label::new();
612         let size = Label::new();
613         #[rustfmt::skip]
614         let section = Section::with_endian(Endian::Little)
615             // Header
616             .mark(&start)
617             .L32(&size)
618             .L16(encoding.version)
619             .L8(encoding.address_size)
620             .L8(0)
621             .L32(0)
622             .mark(&first)
623             // OffsetPair
624             .L8(4).uleb(0x10200).uleb(0x10300)
625             // A base address selection followed by an OffsetPair.
626             .L8(5).L32(0x0200_0000)
627             .L8(4).uleb(0x10400).uleb(0x10500)
628             // An empty OffsetPair followed by a normal OffsetPair.
629             .L8(4).uleb(0x10600).uleb(0x10600)
630             .L8(4).uleb(0x10800).uleb(0x10900)
631             // A StartEnd
632             .L8(6).L32(0x201_0a00).L32(0x201_0b00)
633             // A StartLength
634             .L8(7).L32(0x201_0c00).uleb(0x100)
635             // An OffsetPair that starts at 0.
636             .L8(4).uleb(0).uleb(1)
637             // An OffsetPair that starts and ends at 0.
638             .L8(4).uleb(0).uleb(0)
639             // An OffsetPair that ends at -1.
640             .L8(5).L32(0)
641             .L8(4).uleb(0).uleb(0xffff_ffff)
642             // A BaseAddressx + OffsetPair
643             .L8(1).uleb(0)
644             .L8(4).uleb(0x10100).uleb(0x10200)
645             // A StartxEndx
646             .L8(2).uleb(1).uleb(2)
647             // A StartxLength
648             .L8(3).uleb(3).uleb(0x100)
649             // A range end.
650             .L8(0)
651             // Some extra data.
652             .L32(0xffff_ffff);
653         size.set_const((&section.here() - &start - 4) as u64);
654 
655         let buf = section.get_contents().unwrap();
656         let debug_ranges = DebugRanges::new(&[], LittleEndian);
657         let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
658         let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
659         let offset = RangeListsOffset((&first - &start) as usize);
660         let mut ranges = rnglists
661             .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
662             .unwrap();
663 
664         // A normal range.
665         assert_eq!(
666             ranges.next(),
667             Ok(Some(Range {
668                 begin: 0x0101_0200,
669                 end: 0x0101_0300,
670             }))
671         );
672 
673         // A base address selection followed by a normal range.
674         assert_eq!(
675             ranges.next(),
676             Ok(Some(Range {
677                 begin: 0x0201_0400,
678                 end: 0x0201_0500,
679             }))
680         );
681 
682         // An empty range followed by a normal range.
683         assert_eq!(
684             ranges.next(),
685             Ok(Some(Range {
686                 begin: 0x0201_0600,
687                 end: 0x0201_0600,
688             }))
689         );
690         assert_eq!(
691             ranges.next(),
692             Ok(Some(Range {
693                 begin: 0x0201_0800,
694                 end: 0x0201_0900,
695             }))
696         );
697 
698         // A normal range.
699         assert_eq!(
700             ranges.next(),
701             Ok(Some(Range {
702                 begin: 0x0201_0a00,
703                 end: 0x0201_0b00,
704             }))
705         );
706 
707         // A normal range.
708         assert_eq!(
709             ranges.next(),
710             Ok(Some(Range {
711                 begin: 0x0201_0c00,
712                 end: 0x0201_0d00,
713             }))
714         );
715 
716         // A range that starts at 0.
717         assert_eq!(
718             ranges.next(),
719             Ok(Some(Range {
720                 begin: 0x0200_0000,
721                 end: 0x0200_0001,
722             }))
723         );
724 
725         // A range that starts and ends at 0.
726         assert_eq!(
727             ranges.next(),
728             Ok(Some(Range {
729                 begin: 0x0200_0000,
730                 end: 0x0200_0000,
731             }))
732         );
733 
734         // A range that ends at -1.
735         assert_eq!(
736             ranges.next(),
737             Ok(Some(Range {
738                 begin: 0x0000_0000,
739                 end: 0xffff_ffff,
740             }))
741         );
742 
743         // A BaseAddressx + OffsetPair
744         assert_eq!(
745             ranges.next(),
746             Ok(Some(Range {
747                 begin: 0x0301_0100,
748                 end: 0x0301_0200,
749             }))
750         );
751 
752         // A StartxEndx
753         assert_eq!(
754             ranges.next(),
755             Ok(Some(Range {
756                 begin: 0x0301_0300,
757                 end: 0x0301_0400,
758             }))
759         );
760 
761         // A StartxLength
762         assert_eq!(
763             ranges.next(),
764             Ok(Some(Range {
765                 begin: 0x0301_0500,
766                 end: 0x0301_0600,
767             }))
768         );
769 
770         // A range end.
771         assert_eq!(ranges.next(), Ok(None));
772 
773         // An offset at the end of buf.
774         let mut ranges = rnglists
775             .ranges(
776                 RangeListsOffset(buf.len()),
777                 encoding,
778                 0x0100_0000,
779                 debug_addr,
780                 debug_addr_base,
781             )
782             .unwrap();
783         assert_eq!(ranges.next(), Ok(None));
784     }
785 
786     #[test]
test_rnglists_64()787     fn test_rnglists_64() {
788         let encoding = Encoding {
789             format: Format::Dwarf64,
790             version: 5,
791             address_size: 8,
792         };
793         let section = Section::with_endian(Endian::Little)
794             .L64(0x0300_0000)
795             .L64(0x0301_0300)
796             .L64(0x0301_0400)
797             .L64(0x0301_0500);
798         let buf = section.get_contents().unwrap();
799         let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
800         let debug_addr_base = DebugAddrBase(0);
801 
802         let start = Label::new();
803         let first = Label::new();
804         let size = Label::new();
805         #[rustfmt::skip]
806         let section = Section::with_endian(Endian::Little)
807             // Header
808             .mark(&start)
809             .L32(0xffff_ffff)
810             .L64(&size)
811             .L16(encoding.version)
812             .L8(encoding.address_size)
813             .L8(0)
814             .L32(0)
815             .mark(&first)
816             // OffsetPair
817             .L8(4).uleb(0x10200).uleb(0x10300)
818             // A base address selection followed by an OffsetPair.
819             .L8(5).L64(0x0200_0000)
820             .L8(4).uleb(0x10400).uleb(0x10500)
821             // An empty OffsetPair followed by a normal OffsetPair.
822             .L8(4).uleb(0x10600).uleb(0x10600)
823             .L8(4).uleb(0x10800).uleb(0x10900)
824             // A StartEnd
825             .L8(6).L64(0x201_0a00).L64(0x201_0b00)
826             // A StartLength
827             .L8(7).L64(0x201_0c00).uleb(0x100)
828             // An OffsetPair that starts at 0.
829             .L8(4).uleb(0).uleb(1)
830             // An OffsetPair that starts and ends at 0.
831             .L8(4).uleb(0).uleb(0)
832             // An OffsetPair that ends at -1.
833             .L8(5).L64(0)
834             .L8(4).uleb(0).uleb(0xffff_ffff)
835             // A BaseAddressx + OffsetPair
836             .L8(1).uleb(0)
837             .L8(4).uleb(0x10100).uleb(0x10200)
838             // A StartxEndx
839             .L8(2).uleb(1).uleb(2)
840             // A StartxLength
841             .L8(3).uleb(3).uleb(0x100)
842             // A range end.
843             .L8(0)
844             // Some extra data.
845             .L32(0xffff_ffff);
846         size.set_const((&section.here() - &start - 12) as u64);
847 
848         let buf = section.get_contents().unwrap();
849         let debug_ranges = DebugRanges::new(&[], LittleEndian);
850         let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
851         let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
852         let offset = RangeListsOffset((&first - &start) as usize);
853         let mut ranges = rnglists
854             .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
855             .unwrap();
856 
857         // A normal range.
858         assert_eq!(
859             ranges.next(),
860             Ok(Some(Range {
861                 begin: 0x0101_0200,
862                 end: 0x0101_0300,
863             }))
864         );
865 
866         // A base address selection followed by a normal range.
867         assert_eq!(
868             ranges.next(),
869             Ok(Some(Range {
870                 begin: 0x0201_0400,
871                 end: 0x0201_0500,
872             }))
873         );
874 
875         // An empty range followed by a normal range.
876         assert_eq!(
877             ranges.next(),
878             Ok(Some(Range {
879                 begin: 0x0201_0600,
880                 end: 0x0201_0600,
881             }))
882         );
883         assert_eq!(
884             ranges.next(),
885             Ok(Some(Range {
886                 begin: 0x0201_0800,
887                 end: 0x0201_0900,
888             }))
889         );
890 
891         // A normal range.
892         assert_eq!(
893             ranges.next(),
894             Ok(Some(Range {
895                 begin: 0x0201_0a00,
896                 end: 0x0201_0b00,
897             }))
898         );
899 
900         // A normal range.
901         assert_eq!(
902             ranges.next(),
903             Ok(Some(Range {
904                 begin: 0x0201_0c00,
905                 end: 0x0201_0d00,
906             }))
907         );
908 
909         // A range that starts at 0.
910         assert_eq!(
911             ranges.next(),
912             Ok(Some(Range {
913                 begin: 0x0200_0000,
914                 end: 0x0200_0001,
915             }))
916         );
917 
918         // A range that starts and ends at 0.
919         assert_eq!(
920             ranges.next(),
921             Ok(Some(Range {
922                 begin: 0x0200_0000,
923                 end: 0x0200_0000,
924             }))
925         );
926 
927         // A range that ends at -1.
928         assert_eq!(
929             ranges.next(),
930             Ok(Some(Range {
931                 begin: 0x0000_0000,
932                 end: 0xffff_ffff,
933             }))
934         );
935 
936         // A BaseAddressx + OffsetPair
937         assert_eq!(
938             ranges.next(),
939             Ok(Some(Range {
940                 begin: 0x0301_0100,
941                 end: 0x0301_0200,
942             }))
943         );
944 
945         // A StartxEndx
946         assert_eq!(
947             ranges.next(),
948             Ok(Some(Range {
949                 begin: 0x0301_0300,
950                 end: 0x0301_0400,
951             }))
952         );
953 
954         // A StartxLength
955         assert_eq!(
956             ranges.next(),
957             Ok(Some(Range {
958                 begin: 0x0301_0500,
959                 end: 0x0301_0600,
960             }))
961         );
962 
963         // A range end.
964         assert_eq!(ranges.next(), Ok(None));
965 
966         // An offset at the end of buf.
967         let mut ranges = rnglists
968             .ranges(
969                 RangeListsOffset(buf.len()),
970                 encoding,
971                 0x0100_0000,
972                 debug_addr,
973                 debug_addr_base,
974             )
975             .unwrap();
976         assert_eq!(ranges.next(), Ok(None));
977     }
978 
979     #[test]
test_raw_range()980     fn test_raw_range() {
981         let range = RawRange {
982             begin: 0,
983             end: 0xffff_ffff,
984         };
985         assert!(!range.is_end());
986         assert!(!range.is_base_address(4));
987         assert!(!range.is_base_address(8));
988 
989         let range = RawRange { begin: 0, end: 0 };
990         assert!(range.is_end());
991         assert!(!range.is_base_address(4));
992         assert!(!range.is_base_address(8));
993 
994         let range = RawRange {
995             begin: 0xffff_ffff,
996             end: 0,
997         };
998         assert!(!range.is_end());
999         assert!(range.is_base_address(4));
1000         assert!(!range.is_base_address(8));
1001 
1002         let range = RawRange {
1003             begin: 0xffff_ffff_ffff_ffff,
1004             end: 0,
1005         };
1006         assert!(!range.is_end());
1007         assert!(!range.is_base_address(4));
1008         assert!(range.is_base_address(8));
1009     }
1010 
1011     #[test]
test_ranges_32()1012     fn test_ranges_32() {
1013         let start = Label::new();
1014         let first = Label::new();
1015         #[rustfmt::skip]
1016         let section = Section::with_endian(Endian::Little)
1017             // A range before the offset.
1018             .mark(&start)
1019             .L32(0x10000).L32(0x10100)
1020             .mark(&first)
1021             // A normal range.
1022             .L32(0x10200).L32(0x10300)
1023             // A base address selection followed by a normal range.
1024             .L32(0xffff_ffff).L32(0x0200_0000)
1025             .L32(0x10400).L32(0x10500)
1026             // An empty range followed by a normal range.
1027             .L32(0x10600).L32(0x10600)
1028             .L32(0x10800).L32(0x10900)
1029             // A range that starts at 0.
1030             .L32(0).L32(1)
1031             // A range that ends at -1.
1032             .L32(0xffff_ffff).L32(0x0000_0000)
1033             .L32(0).L32(0xffff_ffff)
1034             // A range end.
1035             .L32(0).L32(0)
1036             // Some extra data.
1037             .L32(0);
1038 
1039         let buf = section.get_contents().unwrap();
1040         let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1041         let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1042         let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1043         let offset = RangeListsOffset((&first - &start) as usize);
1044         let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1045         let debug_addr_base = DebugAddrBase(0);
1046         let encoding = Encoding {
1047             format: Format::Dwarf32,
1048             version: 4,
1049             address_size: 4,
1050         };
1051         let mut ranges = rnglists
1052             .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
1053             .unwrap();
1054 
1055         // A normal range.
1056         assert_eq!(
1057             ranges.next(),
1058             Ok(Some(Range {
1059                 begin: 0x0101_0200,
1060                 end: 0x0101_0300,
1061             }))
1062         );
1063 
1064         // A base address selection followed by a normal range.
1065         assert_eq!(
1066             ranges.next(),
1067             Ok(Some(Range {
1068                 begin: 0x0201_0400,
1069                 end: 0x0201_0500,
1070             }))
1071         );
1072 
1073         // An empty range followed by a normal range.
1074         assert_eq!(
1075             ranges.next(),
1076             Ok(Some(Range {
1077                 begin: 0x0201_0600,
1078                 end: 0x0201_0600,
1079             }))
1080         );
1081         assert_eq!(
1082             ranges.next(),
1083             Ok(Some(Range {
1084                 begin: 0x0201_0800,
1085                 end: 0x0201_0900,
1086             }))
1087         );
1088 
1089         // A range that starts at 0.
1090         assert_eq!(
1091             ranges.next(),
1092             Ok(Some(Range {
1093                 begin: 0x0200_0000,
1094                 end: 0x0200_0001,
1095             }))
1096         );
1097 
1098         // A range that ends at -1.
1099         assert_eq!(
1100             ranges.next(),
1101             Ok(Some(Range {
1102                 begin: 0x0000_0000,
1103                 end: 0xffff_ffff,
1104             }))
1105         );
1106 
1107         // A range end.
1108         assert_eq!(ranges.next(), Ok(None));
1109 
1110         // An offset at the end of buf.
1111         let mut ranges = rnglists
1112             .ranges(
1113                 RangeListsOffset(buf.len()),
1114                 encoding,
1115                 0x0100_0000,
1116                 debug_addr,
1117                 debug_addr_base,
1118             )
1119             .unwrap();
1120         assert_eq!(ranges.next(), Ok(None));
1121     }
1122 
1123     #[test]
test_ranges_64()1124     fn test_ranges_64() {
1125         let start = Label::new();
1126         let first = Label::new();
1127         #[rustfmt::skip]
1128         let section = Section::with_endian(Endian::Little)
1129             // A range before the offset.
1130             .mark(&start)
1131             .L64(0x10000).L64(0x10100)
1132             .mark(&first)
1133             // A normal range.
1134             .L64(0x10200).L64(0x10300)
1135             // A base address selection followed by a normal range.
1136             .L64(0xffff_ffff_ffff_ffff).L64(0x0200_0000)
1137             .L64(0x10400).L64(0x10500)
1138             // An empty range followed by a normal range.
1139             .L64(0x10600).L64(0x10600)
1140             .L64(0x10800).L64(0x10900)
1141             // A range that starts at 0.
1142             .L64(0).L64(1)
1143             // A range that ends at -1.
1144             .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
1145             .L64(0).L64(0xffff_ffff_ffff_ffff)
1146             // A range end.
1147             .L64(0).L64(0)
1148             // Some extra data.
1149             .L64(0);
1150 
1151         let buf = section.get_contents().unwrap();
1152         let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1153         let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1154         let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1155         let offset = RangeListsOffset((&first - &start) as usize);
1156         let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1157         let debug_addr_base = DebugAddrBase(0);
1158         let encoding = Encoding {
1159             format: Format::Dwarf64,
1160             version: 4,
1161             address_size: 8,
1162         };
1163         let mut ranges = rnglists
1164             .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
1165             .unwrap();
1166 
1167         // A normal range.
1168         assert_eq!(
1169             ranges.next(),
1170             Ok(Some(Range {
1171                 begin: 0x0101_0200,
1172                 end: 0x0101_0300,
1173             }))
1174         );
1175 
1176         // A base address selection followed by a normal range.
1177         assert_eq!(
1178             ranges.next(),
1179             Ok(Some(Range {
1180                 begin: 0x0201_0400,
1181                 end: 0x0201_0500,
1182             }))
1183         );
1184 
1185         // An empty range followed by a normal range.
1186         assert_eq!(
1187             ranges.next(),
1188             Ok(Some(Range {
1189                 begin: 0x0201_0600,
1190                 end: 0x0201_0600,
1191             }))
1192         );
1193         assert_eq!(
1194             ranges.next(),
1195             Ok(Some(Range {
1196                 begin: 0x0201_0800,
1197                 end: 0x0201_0900,
1198             }))
1199         );
1200 
1201         // A range that starts at 0.
1202         assert_eq!(
1203             ranges.next(),
1204             Ok(Some(Range {
1205                 begin: 0x0200_0000,
1206                 end: 0x0200_0001,
1207             }))
1208         );
1209 
1210         // A range that ends at -1.
1211         assert_eq!(
1212             ranges.next(),
1213             Ok(Some(Range {
1214                 begin: 0x0,
1215                 end: 0xffff_ffff_ffff_ffff,
1216             }))
1217         );
1218 
1219         // A range end.
1220         assert_eq!(ranges.next(), Ok(None));
1221 
1222         // An offset at the end of buf.
1223         let mut ranges = rnglists
1224             .ranges(
1225                 RangeListsOffset(buf.len()),
1226                 encoding,
1227                 0x0100_0000,
1228                 debug_addr,
1229                 debug_addr_base,
1230             )
1231             .unwrap();
1232         assert_eq!(ranges.next(), Ok(None));
1233     }
1234 
1235     #[test]
test_ranges_invalid()1236     fn test_ranges_invalid() {
1237         #[rustfmt::skip]
1238         let section = Section::with_endian(Endian::Little)
1239             // An invalid range.
1240             .L32(0x20000).L32(0x10000)
1241             // An invalid range after wrapping.
1242             .L32(0x20000).L32(0xff01_0000);
1243 
1244         let buf = section.get_contents().unwrap();
1245         let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1246         let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1247         let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1248         let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1249         let debug_addr_base = DebugAddrBase(0);
1250         let encoding = Encoding {
1251             format: Format::Dwarf32,
1252             version: 4,
1253             address_size: 4,
1254         };
1255 
1256         // An invalid range.
1257         let mut ranges = rnglists
1258             .ranges(
1259                 RangeListsOffset(0x0),
1260                 encoding,
1261                 0x0100_0000,
1262                 debug_addr,
1263                 debug_addr_base,
1264             )
1265             .unwrap();
1266         assert_eq!(ranges.next(), Err(Error::InvalidAddressRange));
1267 
1268         // An invalid range after wrapping.
1269         let mut ranges = rnglists
1270             .ranges(
1271                 RangeListsOffset(0x8),
1272                 encoding,
1273                 0x0100_0000,
1274                 debug_addr,
1275                 debug_addr_base,
1276             )
1277             .unwrap();
1278         assert_eq!(ranges.next(), Err(Error::InvalidAddressRange));
1279 
1280         // An invalid offset.
1281         match rnglists.ranges(
1282             RangeListsOffset(buf.len() + 1),
1283             encoding,
1284             0x0100_0000,
1285             debug_addr,
1286             debug_addr_base,
1287         ) {
1288             Err(Error::UnexpectedEof(_)) => {}
1289             otherwise => panic!("Unexpected result: {:?}", otherwise),
1290         }
1291     }
1292 
1293     #[test]
test_get_offset()1294     fn test_get_offset() {
1295         for format in vec![Format::Dwarf32, Format::Dwarf64] {
1296             let encoding = Encoding {
1297                 format,
1298                 version: 5,
1299                 address_size: 4,
1300             };
1301 
1302             let zero = Label::new();
1303             let length = Label::new();
1304             let start = Label::new();
1305             let first = Label::new();
1306             let end = Label::new();
1307             let mut section = Section::with_endian(Endian::Little)
1308                 .mark(&zero)
1309                 .initial_length(format, &length, &start)
1310                 .D16(encoding.version)
1311                 .D8(encoding.address_size)
1312                 .D8(0)
1313                 .D32(20)
1314                 .mark(&first);
1315             for i in 0..20 {
1316                 section = section.word(format.word_size(), 1000 + i);
1317             }
1318             section = section.mark(&end);
1319             length.set_const((&end - &start) as u64);
1320             let section = section.get_contents().unwrap();
1321 
1322             let debug_ranges = DebugRanges::from(EndianSlice::new(&[], LittleEndian));
1323             let debug_rnglists = DebugRngLists::from(EndianSlice::new(&section, LittleEndian));
1324             let ranges = RangeLists::new(debug_ranges, debug_rnglists);
1325 
1326             let base = DebugRngListsBase((&first - &zero) as usize);
1327             assert_eq!(
1328                 ranges.get_offset(encoding, base, DebugRngListsIndex(0)),
1329                 Ok(RangeListsOffset(base.0 + 1000))
1330             );
1331             assert_eq!(
1332                 ranges.get_offset(encoding, base, DebugRngListsIndex(19)),
1333                 Ok(RangeListsOffset(base.0 + 1019))
1334             );
1335         }
1336     }
1337 }
1338