]> git.proxmox.com Git - rustc.git/blob - vendor/gimli/src/read/rnglists.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / vendor / gimli / src / read / rnglists.rs
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 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
41 impl<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
51 impl<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)]
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 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(section, endian))
85 }
86 }
87
88 impl<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
98 impl<R> From<R> for DebugRngLists<R> {
99 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`.
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.
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
163 impl<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
190 impl<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)]
276 enum 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)]
288 pub 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)]
296 pub 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
351 impl<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 match format {
359 RangeListsFormat::Bare => {
360 let range = RawRange::parse(input, encoding.address_size)?;
361 return Ok(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 => Ok(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
408 impl<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")]
440 impl<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)]
455 pub 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
462 impl<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 = match raw_range {
493 RawRngListEntry::BaseAddress { addr } => {
494 self.base_address = addr;
495 continue;
496 }
497 RawRngListEntry::BaseAddressx { addr } => {
498 self.base_address = self.get_address(addr)?;
499 continue;
500 }
501 RawRngListEntry::StartxEndx { begin, end } => {
502 let begin = self.get_address(begin)?;
503 let end = self.get_address(end)?;
504 Range { begin, end }
505 }
506 RawRngListEntry::StartxLength { begin, length } => {
507 let begin = self.get_address(begin)?;
508 let end = begin + length;
509 Range { begin, end }
510 }
511 RawRngListEntry::AddressOrOffsetPair { begin, end }
512 | RawRngListEntry::OffsetPair { begin, end } => {
513 let mut range = Range { begin, end };
514 range.add_base_address(self.base_address, self.raw.encoding.address_size);
515 range
516 }
517 RawRngListEntry::StartEnd { begin, end } => Range { begin, end },
518 RawRngListEntry::StartLength { begin, length } => Range {
519 begin,
520 end: begin + length,
521 },
522 };
523
524 if range.begin > range.end {
525 self.raw.input.empty();
526 return Err(Error::InvalidAddressRange);
527 }
528
529 return Ok(Some(range));
530 }
531 }
532 }
533
534 #[cfg(feature = "fallible-iterator")]
535 impl<R: Reader> fallible_iterator::FallibleIterator for RngListIter<R> {
536 type Item = Range;
537 type Error = Error;
538
539 fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
540 RngListIter::next(self)
541 }
542 }
543
544 /// A raw address range from the `.debug_ranges` section.
545 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
546 pub(crate) struct RawRange {
547 /// The beginning address of the range.
548 pub begin: u64,
549
550 /// The first address past the end of the range.
551 pub end: u64,
552 }
553
554 impl RawRange {
555 /// Check if this is a range end entry.
556 ///
557 /// This will only occur for raw ranges.
558 #[inline]
559 pub fn is_end(&self) -> bool {
560 self.begin == 0 && self.end == 0
561 }
562
563 /// Check if this is a base address selection entry.
564 ///
565 /// A base address selection entry changes the base address that subsequent
566 /// range entries are relative to. This will only occur for raw ranges.
567 #[inline]
568 pub fn is_base_address(&self, address_size: u8) -> bool {
569 self.begin == !0 >> (64 - address_size * 8)
570 }
571
572 /// Parse an address range entry from `.debug_ranges` or `.debug_loc`.
573 #[doc(hidden)]
574 #[inline]
575 pub fn parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange> {
576 let begin = input.read_address(address_size)?;
577 let end = input.read_address(address_size)?;
578 let range = RawRange { begin, end };
579 Ok(range)
580 }
581 }
582
583 /// An address range from the `.debug_ranges`, `.debug_rnglists`, or `.debug_aranges` sections.
584 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
585 pub struct Range {
586 /// The beginning address of the range.
587 pub begin: u64,
588
589 /// The first address past the end of the range.
590 pub end: u64,
591 }
592
593 impl Range {
594 /// Add a base address to this range.
595 #[inline]
596 pub(crate) fn add_base_address(&mut self, base_address: u64, address_size: u8) {
597 let mask = !0 >> (64 - address_size * 8);
598 self.begin = base_address.wrapping_add(self.begin) & mask;
599 self.end = base_address.wrapping_add(self.end) & mask;
600 }
601 }
602
603 #[cfg(test)]
604 mod tests {
605 use super::*;
606 use crate::common::Format;
607 use crate::endianity::LittleEndian;
608 use crate::test_util::GimliSectionMethods;
609 use test_assembler::{Endian, Label, LabelMaker, Section};
610
611 #[test]
612 fn test_rnglists_32() {
613 let encoding = Encoding {
614 format: Format::Dwarf32,
615 version: 5,
616 address_size: 4,
617 };
618 let section = Section::with_endian(Endian::Little)
619 .L32(0x0300_0000)
620 .L32(0x0301_0300)
621 .L32(0x0301_0400)
622 .L32(0x0301_0500);
623 let buf = section.get_contents().unwrap();
624 let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
625 let debug_addr_base = DebugAddrBase(0);
626
627 let start = Label::new();
628 let first = Label::new();
629 let size = Label::new();
630 #[rustfmt::skip]
631 let section = Section::with_endian(Endian::Little)
632 // Header
633 .mark(&start)
634 .L32(&size)
635 .L16(encoding.version)
636 .L8(encoding.address_size)
637 .L8(0)
638 .L32(0)
639 .mark(&first)
640 // OffsetPair
641 .L8(4).uleb(0x10200).uleb(0x10300)
642 // A base address selection followed by an OffsetPair.
643 .L8(5).L32(0x0200_0000)
644 .L8(4).uleb(0x10400).uleb(0x10500)
645 // An empty OffsetPair followed by a normal OffsetPair.
646 .L8(4).uleb(0x10600).uleb(0x10600)
647 .L8(4).uleb(0x10800).uleb(0x10900)
648 // A StartEnd
649 .L8(6).L32(0x201_0a00).L32(0x201_0b00)
650 // A StartLength
651 .L8(7).L32(0x201_0c00).uleb(0x100)
652 // An OffsetPair that starts at 0.
653 .L8(4).uleb(0).uleb(1)
654 // An OffsetPair that starts and ends at 0.
655 .L8(4).uleb(0).uleb(0)
656 // An OffsetPair that ends at -1.
657 .L8(5).L32(0)
658 .L8(4).uleb(0).uleb(0xffff_ffff)
659 // A BaseAddressx + OffsetPair
660 .L8(1).uleb(0)
661 .L8(4).uleb(0x10100).uleb(0x10200)
662 // A StartxEndx
663 .L8(2).uleb(1).uleb(2)
664 // A StartxLength
665 .L8(3).uleb(3).uleb(0x100)
666 // A range end.
667 .L8(0)
668 // Some extra data.
669 .L32(0xffff_ffff);
670 size.set_const((&section.here() - &start - 4) as u64);
671
672 let buf = section.get_contents().unwrap();
673 let debug_ranges = DebugRanges::new(&[], LittleEndian);
674 let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
675 let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
676 let offset = RangeListsOffset((&first - &start) as usize);
677 let mut ranges = rnglists
678 .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
679 .unwrap();
680
681 // A normal range.
682 assert_eq!(
683 ranges.next(),
684 Ok(Some(Range {
685 begin: 0x0101_0200,
686 end: 0x0101_0300,
687 }))
688 );
689
690 // A base address selection followed by a normal range.
691 assert_eq!(
692 ranges.next(),
693 Ok(Some(Range {
694 begin: 0x0201_0400,
695 end: 0x0201_0500,
696 }))
697 );
698
699 // An empty range followed by a normal range.
700 assert_eq!(
701 ranges.next(),
702 Ok(Some(Range {
703 begin: 0x0201_0600,
704 end: 0x0201_0600,
705 }))
706 );
707 assert_eq!(
708 ranges.next(),
709 Ok(Some(Range {
710 begin: 0x0201_0800,
711 end: 0x0201_0900,
712 }))
713 );
714
715 // A normal range.
716 assert_eq!(
717 ranges.next(),
718 Ok(Some(Range {
719 begin: 0x0201_0a00,
720 end: 0x0201_0b00,
721 }))
722 );
723
724 // A normal range.
725 assert_eq!(
726 ranges.next(),
727 Ok(Some(Range {
728 begin: 0x0201_0c00,
729 end: 0x0201_0d00,
730 }))
731 );
732
733 // A range that starts at 0.
734 assert_eq!(
735 ranges.next(),
736 Ok(Some(Range {
737 begin: 0x0200_0000,
738 end: 0x0200_0001,
739 }))
740 );
741
742 // A range that starts and ends at 0.
743 assert_eq!(
744 ranges.next(),
745 Ok(Some(Range {
746 begin: 0x0200_0000,
747 end: 0x0200_0000,
748 }))
749 );
750
751 // A range that ends at -1.
752 assert_eq!(
753 ranges.next(),
754 Ok(Some(Range {
755 begin: 0x0000_0000,
756 end: 0xffff_ffff,
757 }))
758 );
759
760 // A BaseAddressx + OffsetPair
761 assert_eq!(
762 ranges.next(),
763 Ok(Some(Range {
764 begin: 0x0301_0100,
765 end: 0x0301_0200,
766 }))
767 );
768
769 // A StartxEndx
770 assert_eq!(
771 ranges.next(),
772 Ok(Some(Range {
773 begin: 0x0301_0300,
774 end: 0x0301_0400,
775 }))
776 );
777
778 // A StartxLength
779 assert_eq!(
780 ranges.next(),
781 Ok(Some(Range {
782 begin: 0x0301_0500,
783 end: 0x0301_0600,
784 }))
785 );
786
787 // A range end.
788 assert_eq!(ranges.next(), Ok(None));
789
790 // An offset at the end of buf.
791 let mut ranges = rnglists
792 .ranges(
793 RangeListsOffset(buf.len()),
794 encoding,
795 0x0100_0000,
796 debug_addr,
797 debug_addr_base,
798 )
799 .unwrap();
800 assert_eq!(ranges.next(), Ok(None));
801 }
802
803 #[test]
804 fn test_rnglists_64() {
805 let encoding = Encoding {
806 format: Format::Dwarf64,
807 version: 5,
808 address_size: 8,
809 };
810 let section = Section::with_endian(Endian::Little)
811 .L64(0x0300_0000)
812 .L64(0x0301_0300)
813 .L64(0x0301_0400)
814 .L64(0x0301_0500);
815 let buf = section.get_contents().unwrap();
816 let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
817 let debug_addr_base = DebugAddrBase(0);
818
819 let start = Label::new();
820 let first = Label::new();
821 let size = Label::new();
822 #[rustfmt::skip]
823 let section = Section::with_endian(Endian::Little)
824 // Header
825 .mark(&start)
826 .L32(0xffff_ffff)
827 .L64(&size)
828 .L16(encoding.version)
829 .L8(encoding.address_size)
830 .L8(0)
831 .L32(0)
832 .mark(&first)
833 // OffsetPair
834 .L8(4).uleb(0x10200).uleb(0x10300)
835 // A base address selection followed by an OffsetPair.
836 .L8(5).L64(0x0200_0000)
837 .L8(4).uleb(0x10400).uleb(0x10500)
838 // An empty OffsetPair followed by a normal OffsetPair.
839 .L8(4).uleb(0x10600).uleb(0x10600)
840 .L8(4).uleb(0x10800).uleb(0x10900)
841 // A StartEnd
842 .L8(6).L64(0x201_0a00).L64(0x201_0b00)
843 // A StartLength
844 .L8(7).L64(0x201_0c00).uleb(0x100)
845 // An OffsetPair that starts at 0.
846 .L8(4).uleb(0).uleb(1)
847 // An OffsetPair that starts and ends at 0.
848 .L8(4).uleb(0).uleb(0)
849 // An OffsetPair that ends at -1.
850 .L8(5).L64(0)
851 .L8(4).uleb(0).uleb(0xffff_ffff)
852 // A BaseAddressx + OffsetPair
853 .L8(1).uleb(0)
854 .L8(4).uleb(0x10100).uleb(0x10200)
855 // A StartxEndx
856 .L8(2).uleb(1).uleb(2)
857 // A StartxLength
858 .L8(3).uleb(3).uleb(0x100)
859 // A range end.
860 .L8(0)
861 // Some extra data.
862 .L32(0xffff_ffff);
863 size.set_const((&section.here() - &start - 12) as u64);
864
865 let buf = section.get_contents().unwrap();
866 let debug_ranges = DebugRanges::new(&[], LittleEndian);
867 let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
868 let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
869 let offset = RangeListsOffset((&first - &start) as usize);
870 let mut ranges = rnglists
871 .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
872 .unwrap();
873
874 // A normal range.
875 assert_eq!(
876 ranges.next(),
877 Ok(Some(Range {
878 begin: 0x0101_0200,
879 end: 0x0101_0300,
880 }))
881 );
882
883 // A base address selection followed by a normal range.
884 assert_eq!(
885 ranges.next(),
886 Ok(Some(Range {
887 begin: 0x0201_0400,
888 end: 0x0201_0500,
889 }))
890 );
891
892 // An empty range followed by a normal range.
893 assert_eq!(
894 ranges.next(),
895 Ok(Some(Range {
896 begin: 0x0201_0600,
897 end: 0x0201_0600,
898 }))
899 );
900 assert_eq!(
901 ranges.next(),
902 Ok(Some(Range {
903 begin: 0x0201_0800,
904 end: 0x0201_0900,
905 }))
906 );
907
908 // A normal range.
909 assert_eq!(
910 ranges.next(),
911 Ok(Some(Range {
912 begin: 0x0201_0a00,
913 end: 0x0201_0b00,
914 }))
915 );
916
917 // A normal range.
918 assert_eq!(
919 ranges.next(),
920 Ok(Some(Range {
921 begin: 0x0201_0c00,
922 end: 0x0201_0d00,
923 }))
924 );
925
926 // A range that starts at 0.
927 assert_eq!(
928 ranges.next(),
929 Ok(Some(Range {
930 begin: 0x0200_0000,
931 end: 0x0200_0001,
932 }))
933 );
934
935 // A range that starts and ends at 0.
936 assert_eq!(
937 ranges.next(),
938 Ok(Some(Range {
939 begin: 0x0200_0000,
940 end: 0x0200_0000,
941 }))
942 );
943
944 // A range that ends at -1.
945 assert_eq!(
946 ranges.next(),
947 Ok(Some(Range {
948 begin: 0x0000_0000,
949 end: 0xffff_ffff,
950 }))
951 );
952
953 // A BaseAddressx + OffsetPair
954 assert_eq!(
955 ranges.next(),
956 Ok(Some(Range {
957 begin: 0x0301_0100,
958 end: 0x0301_0200,
959 }))
960 );
961
962 // A StartxEndx
963 assert_eq!(
964 ranges.next(),
965 Ok(Some(Range {
966 begin: 0x0301_0300,
967 end: 0x0301_0400,
968 }))
969 );
970
971 // A StartxLength
972 assert_eq!(
973 ranges.next(),
974 Ok(Some(Range {
975 begin: 0x0301_0500,
976 end: 0x0301_0600,
977 }))
978 );
979
980 // A range end.
981 assert_eq!(ranges.next(), Ok(None));
982
983 // An offset at the end of buf.
984 let mut ranges = rnglists
985 .ranges(
986 RangeListsOffset(buf.len()),
987 encoding,
988 0x0100_0000,
989 debug_addr,
990 debug_addr_base,
991 )
992 .unwrap();
993 assert_eq!(ranges.next(), Ok(None));
994 }
995
996 #[test]
997 fn test_raw_range() {
998 let range = RawRange {
999 begin: 0,
1000 end: 0xffff_ffff,
1001 };
1002 assert!(!range.is_end());
1003 assert!(!range.is_base_address(4));
1004 assert!(!range.is_base_address(8));
1005
1006 let range = RawRange { begin: 0, end: 0 };
1007 assert!(range.is_end());
1008 assert!(!range.is_base_address(4));
1009 assert!(!range.is_base_address(8));
1010
1011 let range = RawRange {
1012 begin: 0xffff_ffff,
1013 end: 0,
1014 };
1015 assert!(!range.is_end());
1016 assert!(range.is_base_address(4));
1017 assert!(!range.is_base_address(8));
1018
1019 let range = RawRange {
1020 begin: 0xffff_ffff_ffff_ffff,
1021 end: 0,
1022 };
1023 assert!(!range.is_end());
1024 assert!(!range.is_base_address(4));
1025 assert!(range.is_base_address(8));
1026 }
1027
1028 #[test]
1029 fn test_ranges_32() {
1030 let start = Label::new();
1031 let first = Label::new();
1032 #[rustfmt::skip]
1033 let section = Section::with_endian(Endian::Little)
1034 // A range before the offset.
1035 .mark(&start)
1036 .L32(0x10000).L32(0x10100)
1037 .mark(&first)
1038 // A normal range.
1039 .L32(0x10200).L32(0x10300)
1040 // A base address selection followed by a normal range.
1041 .L32(0xffff_ffff).L32(0x0200_0000)
1042 .L32(0x10400).L32(0x10500)
1043 // An empty range followed by a normal range.
1044 .L32(0x10600).L32(0x10600)
1045 .L32(0x10800).L32(0x10900)
1046 // A range that starts at 0.
1047 .L32(0).L32(1)
1048 // A range that ends at -1.
1049 .L32(0xffff_ffff).L32(0x0000_0000)
1050 .L32(0).L32(0xffff_ffff)
1051 // A range end.
1052 .L32(0).L32(0)
1053 // Some extra data.
1054 .L32(0);
1055
1056 let buf = section.get_contents().unwrap();
1057 let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1058 let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1059 let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1060 let offset = RangeListsOffset((&first - &start) as usize);
1061 let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1062 let debug_addr_base = DebugAddrBase(0);
1063 let encoding = Encoding {
1064 format: Format::Dwarf32,
1065 version: 4,
1066 address_size: 4,
1067 };
1068 let mut ranges = rnglists
1069 .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
1070 .unwrap();
1071
1072 // A normal range.
1073 assert_eq!(
1074 ranges.next(),
1075 Ok(Some(Range {
1076 begin: 0x0101_0200,
1077 end: 0x0101_0300,
1078 }))
1079 );
1080
1081 // A base address selection followed by a normal range.
1082 assert_eq!(
1083 ranges.next(),
1084 Ok(Some(Range {
1085 begin: 0x0201_0400,
1086 end: 0x0201_0500,
1087 }))
1088 );
1089
1090 // An empty range followed by a normal range.
1091 assert_eq!(
1092 ranges.next(),
1093 Ok(Some(Range {
1094 begin: 0x0201_0600,
1095 end: 0x0201_0600,
1096 }))
1097 );
1098 assert_eq!(
1099 ranges.next(),
1100 Ok(Some(Range {
1101 begin: 0x0201_0800,
1102 end: 0x0201_0900,
1103 }))
1104 );
1105
1106 // A range that starts at 0.
1107 assert_eq!(
1108 ranges.next(),
1109 Ok(Some(Range {
1110 begin: 0x0200_0000,
1111 end: 0x0200_0001,
1112 }))
1113 );
1114
1115 // A range that ends at -1.
1116 assert_eq!(
1117 ranges.next(),
1118 Ok(Some(Range {
1119 begin: 0x0000_0000,
1120 end: 0xffff_ffff,
1121 }))
1122 );
1123
1124 // A range end.
1125 assert_eq!(ranges.next(), Ok(None));
1126
1127 // An offset at the end of buf.
1128 let mut ranges = rnglists
1129 .ranges(
1130 RangeListsOffset(buf.len()),
1131 encoding,
1132 0x0100_0000,
1133 debug_addr,
1134 debug_addr_base,
1135 )
1136 .unwrap();
1137 assert_eq!(ranges.next(), Ok(None));
1138 }
1139
1140 #[test]
1141 fn test_ranges_64() {
1142 let start = Label::new();
1143 let first = Label::new();
1144 #[rustfmt::skip]
1145 let section = Section::with_endian(Endian::Little)
1146 // A range before the offset.
1147 .mark(&start)
1148 .L64(0x10000).L64(0x10100)
1149 .mark(&first)
1150 // A normal range.
1151 .L64(0x10200).L64(0x10300)
1152 // A base address selection followed by a normal range.
1153 .L64(0xffff_ffff_ffff_ffff).L64(0x0200_0000)
1154 .L64(0x10400).L64(0x10500)
1155 // An empty range followed by a normal range.
1156 .L64(0x10600).L64(0x10600)
1157 .L64(0x10800).L64(0x10900)
1158 // A range that starts at 0.
1159 .L64(0).L64(1)
1160 // A range that ends at -1.
1161 .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
1162 .L64(0).L64(0xffff_ffff_ffff_ffff)
1163 // A range end.
1164 .L64(0).L64(0)
1165 // Some extra data.
1166 .L64(0);
1167
1168 let buf = section.get_contents().unwrap();
1169 let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1170 let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1171 let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1172 let offset = RangeListsOffset((&first - &start) as usize);
1173 let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1174 let debug_addr_base = DebugAddrBase(0);
1175 let encoding = Encoding {
1176 format: Format::Dwarf64,
1177 version: 4,
1178 address_size: 8,
1179 };
1180 let mut ranges = rnglists
1181 .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
1182 .unwrap();
1183
1184 // A normal range.
1185 assert_eq!(
1186 ranges.next(),
1187 Ok(Some(Range {
1188 begin: 0x0101_0200,
1189 end: 0x0101_0300,
1190 }))
1191 );
1192
1193 // A base address selection followed by a normal range.
1194 assert_eq!(
1195 ranges.next(),
1196 Ok(Some(Range {
1197 begin: 0x0201_0400,
1198 end: 0x0201_0500,
1199 }))
1200 );
1201
1202 // An empty range followed by a normal range.
1203 assert_eq!(
1204 ranges.next(),
1205 Ok(Some(Range {
1206 begin: 0x0201_0600,
1207 end: 0x0201_0600,
1208 }))
1209 );
1210 assert_eq!(
1211 ranges.next(),
1212 Ok(Some(Range {
1213 begin: 0x0201_0800,
1214 end: 0x0201_0900,
1215 }))
1216 );
1217
1218 // A range that starts at 0.
1219 assert_eq!(
1220 ranges.next(),
1221 Ok(Some(Range {
1222 begin: 0x0200_0000,
1223 end: 0x0200_0001,
1224 }))
1225 );
1226
1227 // A range that ends at -1.
1228 assert_eq!(
1229 ranges.next(),
1230 Ok(Some(Range {
1231 begin: 0x0,
1232 end: 0xffff_ffff_ffff_ffff,
1233 }))
1234 );
1235
1236 // A range end.
1237 assert_eq!(ranges.next(), Ok(None));
1238
1239 // An offset at the end of buf.
1240 let mut ranges = rnglists
1241 .ranges(
1242 RangeListsOffset(buf.len()),
1243 encoding,
1244 0x0100_0000,
1245 debug_addr,
1246 debug_addr_base,
1247 )
1248 .unwrap();
1249 assert_eq!(ranges.next(), Ok(None));
1250 }
1251
1252 #[test]
1253 fn test_ranges_invalid() {
1254 #[rustfmt::skip]
1255 let section = Section::with_endian(Endian::Little)
1256 // An invalid range.
1257 .L32(0x20000).L32(0x10000)
1258 // An invalid range after wrapping.
1259 .L32(0x20000).L32(0xff01_0000);
1260
1261 let buf = section.get_contents().unwrap();
1262 let debug_ranges = DebugRanges::new(&buf, LittleEndian);
1263 let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
1264 let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
1265 let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
1266 let debug_addr_base = DebugAddrBase(0);
1267 let encoding = Encoding {
1268 format: Format::Dwarf32,
1269 version: 4,
1270 address_size: 4,
1271 };
1272
1273 // An invalid range.
1274 let mut ranges = rnglists
1275 .ranges(
1276 RangeListsOffset(0x0),
1277 encoding,
1278 0x0100_0000,
1279 debug_addr,
1280 debug_addr_base,
1281 )
1282 .unwrap();
1283 assert_eq!(ranges.next(), Err(Error::InvalidAddressRange));
1284
1285 // An invalid range after wrapping.
1286 let mut ranges = rnglists
1287 .ranges(
1288 RangeListsOffset(0x8),
1289 encoding,
1290 0x0100_0000,
1291 debug_addr,
1292 debug_addr_base,
1293 )
1294 .unwrap();
1295 assert_eq!(ranges.next(), Err(Error::InvalidAddressRange));
1296
1297 // An invalid offset.
1298 match rnglists.ranges(
1299 RangeListsOffset(buf.len() + 1),
1300 encoding,
1301 0x0100_0000,
1302 debug_addr,
1303 debug_addr_base,
1304 ) {
1305 Err(Error::UnexpectedEof(_)) => {}
1306 otherwise => panic!("Unexpected result: {:?}", otherwise),
1307 }
1308 }
1309
1310 #[test]
1311 fn test_get_offset() {
1312 for format in vec![Format::Dwarf32, Format::Dwarf64] {
1313 let encoding = Encoding {
1314 format,
1315 version: 5,
1316 address_size: 4,
1317 };
1318
1319 let zero = Label::new();
1320 let length = Label::new();
1321 let start = Label::new();
1322 let first = Label::new();
1323 let end = Label::new();
1324 let mut section = Section::with_endian(Endian::Little)
1325 .mark(&zero)
1326 .initial_length(format, &length, &start)
1327 .D16(encoding.version)
1328 .D8(encoding.address_size)
1329 .D8(0)
1330 .D32(20)
1331 .mark(&first);
1332 for i in 0..20 {
1333 section = section.word(format.word_size(), 1000 + i);
1334 }
1335 section = section.mark(&end);
1336 length.set_const((&end - &start) as u64);
1337 let section = section.get_contents().unwrap();
1338
1339 let debug_ranges = DebugRanges::from(EndianSlice::new(&[], LittleEndian));
1340 let debug_rnglists = DebugRngLists::from(EndianSlice::new(&section, LittleEndian));
1341 let ranges = RangeLists::new(debug_ranges, debug_rnglists);
1342
1343 let base = DebugRngListsBase((&first - &zero) as usize);
1344 assert_eq!(
1345 ranges.get_offset(encoding, base, DebugRngListsIndex(0)),
1346 Ok(RangeListsOffset(base.0 + 1000))
1347 );
1348 assert_eq!(
1349 ranges.get_offset(encoding, base, DebugRngListsIndex(19)),
1350 Ok(RangeListsOffset(base.0 + 1019))
1351 );
1352 }
1353 }
1354 }