]> git.proxmox.com Git - rustc.git/blob - vendor/gimli/src/read/rnglists.rs
New upstream version 1.57.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 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 /// ```
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 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 /// ```
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
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 /// ```
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).
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).
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.
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.
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`
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`.
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.
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
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`.
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]
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.
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
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]
542 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]
551 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]
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`, `.debug_rnglists`, or `.debug_aranges` 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]
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]
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]
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]
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]
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]
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]
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]
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 }