2 DebugAddrBase
, DebugAddrIndex
, DebugRngListsBase
, DebugRngListsIndex
, DwarfFileType
, Encoding
,
3 RangeListsOffset
, SectionId
,
6 use crate::endianity
::Endianity
;
8 lists
::ListsHeader
, DebugAddr
, EndianSlice
, Error
, Reader
, ReaderOffset
, ReaderOffsetId
,
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
,
18 impl<'input
, Endian
> DebugRanges
<EndianSlice
<'input
, Endian
>>
22 /// Construct a new `DebugRanges` instance from the data in the `.debug_ranges`
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.
30 /// use gimli::{DebugRanges, LittleEndian};
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);
36 pub fn new(section
: &'input
[u8], endian
: Endian
) -> Self {
37 Self::from(EndianSlice
::new(section
, endian
))
41 impl<R
> Section
<R
> for DebugRanges
<R
> {
42 fn id() -> SectionId
{
43 SectionId
::DebugRanges
46 fn reader(&self) -> &R
{
51 impl<R
> From
<R
> for DebugRanges
<R
> {
52 fn from(section
: R
) -> Self {
53 DebugRanges { section }
57 /// The `DebugRngLists` struct represents the contents of the
58 /// `.debug_rnglists` section.
59 #[derive(Debug, Default, Clone, Copy)]
60 pub struct DebugRngLists
<R
> {
64 impl<'input
, Endian
> DebugRngLists
<EndianSlice
<'input
, Endian
>>
68 /// Construct a new `DebugRngLists` instance from the data in the
69 /// `.debug_rnglists` section.
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.
76 /// use gimli::{DebugRngLists, LittleEndian};
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);
83 pub fn new(section
: &'input
[u8], endian
: Endian
) -> Self {
84 Self::from(EndianSlice
::new(section
, endian
))
88 impl<R
> Section
<R
> for DebugRngLists
<R
> {
89 fn id() -> SectionId
{
90 SectionId
::DebugRngLists
93 fn reader(&self) -> &R
{
98 impl<R
> From
<R
> for DebugRngLists
<R
> {
99 fn from(section
: R
) -> Self {
100 DebugRngLists { section }
105 pub(crate) type RngListsHeader
= ListsHeader
;
107 impl<Offset
> DebugRngListsBase
<Offset
>
109 Offset
: ReaderOffset
,
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(
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
)))
123 DebugRngListsBase(Offset
::from_u8(0))
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
>,
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
> {
146 impl<T
> RangeLists
<T
> {
147 /// Create a `RangeLists` that references the data in `self`.
149 /// This is useful when `R` implements `Reader` but `T` does not.
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(§ion, gimli::LittleEndian)
162 pub fn borrow
<'a
, F
, R
>(&'a
self, mut borrow
: F
) -> RangeLists
<R
>
164 F
: FnMut(&'a T
) -> R
,
167 debug_ranges
: borrow(&self.debug_ranges
.section
).into(),
168 debug_rnglists
: borrow(&self.debug_rnglists
.section
).into(),
173 impl<R
: Reader
> RangeLists
<R
> {
174 /// Iterate over the `Range` list entries starting at the given offset.
176 /// The `unit_version` and `address_size` must match the compilation unit that the
177 /// offset was contained in.
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.
182 /// Can be [used with
183 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
186 offset
: RangeListsOffset
<R
::Offset
>,
187 unit_encoding
: Encoding
,
189 debug_addr
: &DebugAddr
<R
>,
190 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
191 ) -> Result
<RngListIter
<R
>> {
193 self.raw_ranges(offset
, unit_encoding
)?
,
200 /// Iterate over the `RawRngListEntry`ies starting at the given offset.
202 /// The `unit_encoding` must match the compilation unit that the
203 /// offset was contained in.
205 /// This iterator does not perform any processing of the range entries,
206 /// such as handling base addresses.
208 /// Can be [used with
209 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
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
)
218 (self.debug_rnglists
.section
.clone(), RangeListsFormat
::RLE
)
220 input
.skip(offset
.0)?
;
221 Ok(RawRngListIter
::new(input
, unit_encoding
, format
))
224 /// Returns the `.debug_rnglists` offset at the given `base` and `index`.
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.
229 /// The `index` is the value of a `DW_FORM_rnglistx` attribute.
231 /// The `unit_encoding` must match the compilation unit that the
232 /// index was contained in.
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();
242 input
.skip(R
::Offset
::from_u64(
243 index
.0.into_u
64() * u64::from(format
.word_size()),
247 .map(|x
| RangeListsOffset(base
.0 + x
))
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
)> {
253 .lookup_offset_id(id
)
254 .or_else(|| self.debug_rnglists
.lookup_offset_id(id
))
258 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
259 enum RangeListsFormat
{
260 /// The bare range list format used before DWARF 5.
262 /// The DW_RLE encoded range list format used in DWARF 5.
266 /// A raw iterator over an address range list.
268 /// This iterator does not perform any processing of the range entries,
269 /// such as handling base addresses.
271 pub struct RawRngListIter
<R
: Reader
> {
274 format
: RangeListsFormat
,
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.
284 /// End of range. May be an address or an offset.
287 /// DW_RLE_base_address
292 /// DW_RLE_base_addressx
295 addr
: DebugAddrIndex
<T
>,
297 /// DW_RLE_startx_endx
300 begin
: DebugAddrIndex
<T
>,
302 end
: DebugAddrIndex
<T
>,
304 /// DW_RLE_startx_length
307 begin
: DebugAddrIndex
<T
>,
311 /// DW_RLE_offset_pair
325 /// DW_RLE_start_length
334 impl<T
: ReaderOffset
> RawRngListEntry
<T
> {
335 /// Parse a range entry from `.debug_rnglists`
336 fn parse
<R
: Reader
<Offset
= T
>>(
339 format
: RangeListsFormat
,
340 ) -> Result
<Option
<Self>> {
342 RangeListsFormat
::Bare
=> {
343 let range
= RawRange
::parse(input
, encoding
.address_size
)?
;
344 return Ok(if range
.is_end() {
346 } else if range
.is_base_address(encoding
.address_size
) {
347 Some(RawRngListEntry
::BaseAddress { addr: range.end }
)
349 Some(RawRngListEntry
::AddressOrOffsetPair
{
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
)?
),
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
)?
),
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()?
,
368 constants
::DW_RLE_offset_pair
=> Some(RawRngListEntry
::OffsetPair
{
369 begin
: input
.read_uleb128()?
,
370 end
: input
.read_uleb128()?
,
372 constants
::DW_RLE_base_address
=> Some(RawRngListEntry
::BaseAddress
{
373 addr
: input
.read_address(encoding
.address_size
)?
,
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
)?
,
379 constants
::DW_RLE_start_length
=> Some(RawRngListEntry
::StartLength
{
380 begin
: input
.read_address(encoding
.address_size
)?
,
381 length
: input
.read_uleb128()?
,
384 return Err(Error
::InvalidAddressRange
);
391 impl<R
: Reader
> RawRngListIter
<R
> {
392 /// Construct a `RawRngListIter`.
393 fn new(input
: R
, encoding
: Encoding
, format
: RangeListsFormat
) -> RawRngListIter
<R
> {
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() {
407 match RawRngListEntry
::parse(&mut self.input
, self.encoding
, self.format
) {
422 #[cfg(feature = "fallible-iterator")]
423 impl<R
: Reader
> fallible_iterator
::FallibleIterator
for RawRngListIter
<R
> {
424 type Item
= RawRngListEntry
<R
::Offset
>;
427 fn next(&mut self) -> ::core
::result
::Result
<Option
<Self::Item
>, Self::Error
> {
428 RawRngListIter
::next(self)
432 /// An iterator over an address range list.
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.
438 pub struct RngListIter
<R
: Reader
> {
439 raw
: RawRngListIter
<R
>,
441 debug_addr
: DebugAddr
<R
>,
442 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
445 impl<R
: Reader
> RngListIter
<R
> {
446 /// Construct a `RngListIter`.
448 raw
: RawRngListIter
<R
>,
450 debug_addr
: DebugAddr
<R
>,
451 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
452 ) -> RngListIter
<R
> {
462 fn get_address(&self, index
: DebugAddrIndex
<R
::Offset
>) -> Result
<u64> {
464 .get_address(self.raw
.encoding
.address_size
, self.debug_addr_base
, index
)
467 /// Advance the iterator to the next range.
468 pub fn next(&mut self) -> Result
<Option
<Range
>> {
470 let raw_range
= match self.raw
.next()?
{
471 Some(range
) => range
,
472 None
=> return Ok(None
),
475 let range
= match raw_range
{
476 RawRngListEntry
::BaseAddress { addr }
=> {
477 self.base_address
= addr
;
480 RawRngListEntry
::BaseAddressx { addr }
=> {
481 self.base_address
= self.get_address(addr
)?
;
484 RawRngListEntry
::StartxEndx { begin, end }
=> {
485 let begin
= self.get_address(begin
)?
;
486 let end
= self.get_address(end
)?
;
489 RawRngListEntry
::StartxLength { begin, length }
=> {
490 let begin
= self.get_address(begin
)?
;
491 let end
= begin
+ length
;
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
);
500 RawRngListEntry
::StartEnd { begin, end }
=> Range { begin, end }
,
501 RawRngListEntry
::StartLength { begin, length }
=> Range
{
507 if range
.begin
> range
.end
{
508 self.raw
.input
.empty();
509 return Err(Error
::InvalidAddressRange
);
512 return Ok(Some(range
));
517 #[cfg(feature = "fallible-iterator")]
518 impl<R
: Reader
> fallible_iterator
::FallibleIterator
for RngListIter
<R
> {
522 fn next(&mut self) -> ::core
::result
::Result
<Option
<Self::Item
>, Self::Error
> {
523 RngListIter
::next(self)
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.
533 /// The first address past the end of the range.
538 /// Check if this is a range end entry.
540 /// This will only occur for raw ranges.
542 pub fn is_end(&self) -> bool
{
543 self.begin
== 0 && self.end
== 0
546 /// Check if this is a base address selection entry.
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.
551 pub fn is_base_address(&self, address_size
: u8) -> bool
{
552 self.begin
== !0 >> (64 - address_size
* 8)
555 /// Parse an address range entry from `.debug_ranges` or `.debug_loc`.
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 }
;
566 /// An address range from the `.debug_ranges`, `.debug_rnglists`, or `.debug_aranges` sections.
567 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
569 /// The beginning address of the range.
572 /// The first address past the end of the range.
577 /// Add a base address to this range.
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
;
589 use crate::common
::Format
;
590 use crate::endianity
::LittleEndian
;
591 use crate::test_util
::GimliSectionMethods
;
592 use test_assembler
::{Endian, Label, LabelMaker, Section}
;
595 fn test_rnglists_32() {
596 let encoding
= Encoding
{
597 format
: Format
::Dwarf32
,
601 let section
= Section
::with_endian(Endian
::Little
)
606 let buf
= section
.get_contents().unwrap();
607 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&buf
, LittleEndian
));
608 let debug_addr_base
= DebugAddrBase(0);
610 let start
= Label
::new();
611 let first
= Label
::new();
612 let size
= Label
::new();
614 let section
= Section
::with_endian(Endian
::Little
)
618 .L16(encoding
.version
)
619 .L8(encoding
.address_size
)
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)
632 .L8(6).L32(0x201_0a00).L32(0x201_0b00)
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.
641 .L8(4).uleb(0).uleb(0xffff_ffff)
642 // A BaseAddressx + OffsetPair
644 .L8(4).uleb(0x10100).uleb(0x10200)
646 .L8(2).uleb(1).uleb(2)
648 .L8(3).uleb(3).uleb(0x100)
653 size
.set_const((§ion
.here() - &start
- 4) as u64);
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
)
673 // A base address selection followed by a normal range.
682 // An empty range followed by a normal range.
716 // A range that starts at 0.
725 // A range that starts and ends at 0.
734 // A range that ends at -1.
743 // A BaseAddressx + OffsetPair
771 assert_eq
!(ranges
.next(), Ok(None
));
773 // An offset at the end of buf.
774 let mut ranges
= rnglists
776 RangeListsOffset(buf
.len()),
783 assert_eq
!(ranges
.next(), Ok(None
));
787 fn test_rnglists_64() {
788 let encoding
= Encoding
{
789 format
: Format
::Dwarf64
,
793 let section
= Section
::with_endian(Endian
::Little
)
798 let buf
= section
.get_contents().unwrap();
799 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&buf
, LittleEndian
));
800 let debug_addr_base
= DebugAddrBase(0);
802 let start
= Label
::new();
803 let first
= Label
::new();
804 let size
= Label
::new();
806 let section
= Section
::with_endian(Endian
::Little
)
811 .L16(encoding
.version
)
812 .L8(encoding
.address_size
)
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)
825 .L8(6).L64(0x201_0a00).L64(0x201_0b00)
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.
834 .L8(4).uleb(0).uleb(0xffff_ffff)
835 // A BaseAddressx + OffsetPair
837 .L8(4).uleb(0x10100).uleb(0x10200)
839 .L8(2).uleb(1).uleb(2)
841 .L8(3).uleb(3).uleb(0x100)
846 size
.set_const((§ion
.here() - &start
- 12) as u64);
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
)
866 // A base address selection followed by a normal range.
875 // An empty range followed by a normal range.
909 // A range that starts at 0.
918 // A range that starts and ends at 0.
927 // A range that ends at -1.
936 // A BaseAddressx + OffsetPair
964 assert_eq
!(ranges
.next(), Ok(None
));
966 // An offset at the end of buf.
967 let mut ranges
= rnglists
969 RangeListsOffset(buf
.len()),
976 assert_eq
!(ranges
.next(), Ok(None
));
980 fn test_raw_range() {
981 let range
= RawRange
{
985 assert
!(!range
.is_end());
986 assert
!(!range
.is_base_address(4));
987 assert
!(!range
.is_base_address(8));
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));
994 let range
= RawRange
{
998 assert
!(!range
.is_end());
999 assert
!(range
.is_base_address(4));
1000 assert
!(!range
.is_base_address(8));
1002 let range
= RawRange
{
1003 begin
: 0xffff_ffff_ffff_ffff,
1006 assert
!(!range
.is_end());
1007 assert
!(!range
.is_base_address(4));
1008 assert
!(range
.is_base_address(8));
1012 fn test_ranges_32() {
1013 let start
= Label
::new();
1014 let first
= Label
::new();
1016 let section
= Section
::with_endian(Endian
::Little
)
1017 // A range before the offset.
1019 .L32(0x10000).L32(0x10100)
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.
1031 // A range that ends at -1.
1032 .L32(0xffff_ffff).L32(0x0000_0000)
1033 .L32(0).L32(0xffff_ffff)
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
,
1051 let mut ranges
= rnglists
1052 .ranges(offset
, encoding
, 0x0100_0000, debug_addr
, debug_addr_base
)
1064 // A base address selection followed by a normal range.
1073 // An empty range followed by a normal range.
1089 // A range that starts at 0.
1098 // A range that ends at -1.
1108 assert_eq
!(ranges
.next(), Ok(None
));
1110 // An offset at the end of buf.
1111 let mut ranges
= rnglists
1113 RangeListsOffset(buf
.len()),
1120 assert_eq
!(ranges
.next(), Ok(None
));
1124 fn test_ranges_64() {
1125 let start
= Label
::new();
1126 let first
= Label
::new();
1128 let section
= Section
::with_endian(Endian
::Little
)
1129 // A range before the offset.
1131 .L64(0x10000).L64(0x10100)
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.
1143 // A range that ends at -1.
1144 .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
1145 .L64(0).L64(0xffff_ffff_ffff_ffff)
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
,
1163 let mut ranges
= rnglists
1164 .ranges(offset
, encoding
, 0x0100_0000, debug_addr
, debug_addr_base
)
1176 // A base address selection followed by a normal range.
1185 // An empty range followed by a normal range.
1201 // A range that starts at 0.
1210 // A range that ends at -1.
1215 end
: 0xffff_ffff_ffff_ffff,
1220 assert_eq
!(ranges
.next(), Ok(None
));
1222 // An offset at the end of buf.
1223 let mut ranges
= rnglists
1225 RangeListsOffset(buf
.len()),
1232 assert_eq
!(ranges
.next(), Ok(None
));
1236 fn test_ranges_invalid() {
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);
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
,
1256 // An invalid range.
1257 let mut ranges
= rnglists
1259 RangeListsOffset(0x0),
1266 assert_eq
!(ranges
.next(), Err(Error
::InvalidAddressRange
));
1268 // An invalid range after wrapping.
1269 let mut ranges
= rnglists
1271 RangeListsOffset(0x8),
1278 assert_eq
!(ranges
.next(), Err(Error
::InvalidAddressRange
));
1280 // An invalid offset.
1281 match rnglists
.ranges(
1282 RangeListsOffset(buf
.len() + 1),
1288 Err(Error
::UnexpectedEof(_
)) => {}
1289 otherwise
=> panic
!("Unexpected result: {:?}", otherwise
),
1294 fn test_get_offset() {
1295 for format
in vec
![Format
::Dwarf32
, Format
::Dwarf64
] {
1296 let encoding
= Encoding
{
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
)
1309 .initial_length(format
, &length
, &start
)
1310 .D16(encoding
.version
)
1311 .D8(encoding
.address_size
)
1316 section
= section
.word(format
.word_size(), 1000 + i
);
1318 section
= section
.mark(&end
);
1319 length
.set_const((&end
- &start
) as u64);
1320 let section
= section
.get_contents().unwrap();
1322 let debug_ranges
= DebugRanges
::from(EndianSlice
::new(&[], LittleEndian
));
1323 let debug_rnglists
= DebugRngLists
::from(EndianSlice
::new(§ion
, LittleEndian
));
1324 let ranges
= RangeLists
::new(debug_ranges
, debug_rnglists
);
1326 let base
= DebugRngListsBase((&first
- &zero
) as usize);
1328 ranges
.get_offset(encoding
, base
, DebugRngListsIndex(0)),
1329 Ok(RangeListsOffset(base
.0 + 1000))
1332 ranges
.get_offset(encoding
, base
, DebugRngListsIndex(19)),
1333 Ok(RangeListsOffset(base
.0 + 1019))