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