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 macOS, 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 macOS, 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
> {
145 /// Return the `.debug_ranges` section.
146 pub fn debug_ranges(&self) -> &DebugRanges
<R
> {
150 /// Replace the `.debug_ranges` section.
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
;
157 /// Return the `.debug_rnglists` section.
158 pub fn debug_rnglists(&self) -> &DebugRngLists
<R
> {
163 impl<T
> RangeLists
<T
> {
164 /// Create a `RangeLists` that references the data in `self`.
166 /// This is useful when `R` implements `Reader` but `T` does not.
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(§ion, gimli::LittleEndian)
179 pub fn borrow
<'a
, F
, R
>(&'a
self, mut borrow
: F
) -> RangeLists
<R
>
181 F
: FnMut(&'a T
) -> R
,
184 debug_ranges
: borrow(&self.debug_ranges
.section
).into(),
185 debug_rnglists
: borrow(&self.debug_rnglists
.section
).into(),
190 impl<R
: Reader
> RangeLists
<R
> {
191 /// Iterate over the `Range` list entries starting at the given offset.
193 /// The `unit_version` and `address_size` must match the compilation unit that the
194 /// offset was contained in.
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.
199 /// Can be [used with
200 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
203 offset
: RangeListsOffset
<R
::Offset
>,
204 unit_encoding
: Encoding
,
206 debug_addr
: &DebugAddr
<R
>,
207 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
208 ) -> Result
<RngListIter
<R
>> {
210 self.raw_ranges(offset
, unit_encoding
)?
,
217 /// Iterate over the `RawRngListEntry`ies starting at the given offset.
219 /// The `unit_encoding` must match the compilation unit that the
220 /// offset was contained in.
222 /// This iterator does not perform any processing of the range entries,
223 /// such as handling base addresses.
225 /// Can be [used with
226 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
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
)
235 (self.debug_rnglists
.section
.clone(), RangeListsFormat
::RLE
)
237 input
.skip(offset
.0)?
;
238 Ok(RawRngListIter
::new(input
, unit_encoding
, format
))
241 /// Returns the `.debug_rnglists` offset at the given `base` and `index`.
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.
246 /// The `index` is the value of a `DW_FORM_rnglistx` attribute.
248 /// The `unit_encoding` must match the compilation unit that the
249 /// index was contained in.
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();
259 input
.skip(R
::Offset
::from_u64(
260 index
.0.into_u
64() * u64::from(format
.word_size()),
264 .map(|x
| RangeListsOffset(base
.0 + x
))
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
)> {
270 .lookup_offset_id(id
)
271 .or_else(|| self.debug_rnglists
.lookup_offset_id(id
))
275 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
276 enum RangeListsFormat
{
277 /// The bare range list format used before DWARF 5.
279 /// The DW_RLE encoded range list format used in DWARF 5.
283 /// A raw iterator over an address range list.
285 /// This iterator does not perform any processing of the range entries,
286 /// such as handling base addresses.
288 pub struct RawRngListIter
<R
: Reader
> {
291 format
: RangeListsFormat
,
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.
301 /// End of range. May be an address or an offset.
304 /// DW_RLE_base_address
309 /// DW_RLE_base_addressx
312 addr
: DebugAddrIndex
<T
>,
314 /// DW_RLE_startx_endx
317 begin
: DebugAddrIndex
<T
>,
319 end
: DebugAddrIndex
<T
>,
321 /// DW_RLE_startx_length
324 begin
: DebugAddrIndex
<T
>,
328 /// DW_RLE_offset_pair
342 /// DW_RLE_start_length
351 impl<T
: ReaderOffset
> RawRngListEntry
<T
> {
352 /// Parse a range entry from `.debug_rnglists`
353 fn parse
<R
: Reader
<Offset
= T
>>(
356 format
: RangeListsFormat
,
357 ) -> Result
<Option
<Self>> {
359 RangeListsFormat
::Bare
=> {
360 let range
= RawRange
::parse(input
, encoding
.address_size
)?
;
361 return Ok(if range
.is_end() {
363 } else if range
.is_base_address(encoding
.address_size
) {
364 Some(RawRngListEntry
::BaseAddress { addr: range.end }
)
366 Some(RawRngListEntry
::AddressOrOffsetPair
{
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
)?
),
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
)?
),
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()?
,
385 constants
::DW_RLE_offset_pair
=> Some(RawRngListEntry
::OffsetPair
{
386 begin
: input
.read_uleb128()?
,
387 end
: input
.read_uleb128()?
,
389 constants
::DW_RLE_base_address
=> Some(RawRngListEntry
::BaseAddress
{
390 addr
: input
.read_address(encoding
.address_size
)?
,
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
)?
,
396 constants
::DW_RLE_start_length
=> Some(RawRngListEntry
::StartLength
{
397 begin
: input
.read_address(encoding
.address_size
)?
,
398 length
: input
.read_uleb128()?
,
401 return Err(Error
::InvalidAddressRange
);
408 impl<R
: Reader
> RawRngListIter
<R
> {
409 /// Construct a `RawRngListIter`.
410 fn new(input
: R
, encoding
: Encoding
, format
: RangeListsFormat
) -> RawRngListIter
<R
> {
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() {
424 match RawRngListEntry
::parse(&mut self.input
, self.encoding
, self.format
) {
439 #[cfg(feature = "fallible-iterator")]
440 impl<R
: Reader
> fallible_iterator
::FallibleIterator
for RawRngListIter
<R
> {
441 type Item
= RawRngListEntry
<R
::Offset
>;
444 fn next(&mut self) -> ::core
::result
::Result
<Option
<Self::Item
>, Self::Error
> {
445 RawRngListIter
::next(self)
449 /// An iterator over an address range list.
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.
455 pub struct RngListIter
<R
: Reader
> {
456 raw
: RawRngListIter
<R
>,
458 debug_addr
: DebugAddr
<R
>,
459 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
462 impl<R
: Reader
> RngListIter
<R
> {
463 /// Construct a `RngListIter`.
465 raw
: RawRngListIter
<R
>,
467 debug_addr
: DebugAddr
<R
>,
468 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
469 ) -> RngListIter
<R
> {
479 fn get_address(&self, index
: DebugAddrIndex
<R
::Offset
>) -> Result
<u64> {
481 .get_address(self.raw
.encoding
.address_size
, self.debug_addr_base
, index
)
484 /// Advance the iterator to the next range.
485 pub fn next(&mut self) -> Result
<Option
<Range
>> {
487 let raw_range
= match self.raw
.next()?
{
488 Some(range
) => range
,
489 None
=> return Ok(None
),
492 let range
= match raw_range
{
493 RawRngListEntry
::BaseAddress { addr }
=> {
494 self.base_address
= addr
;
497 RawRngListEntry
::BaseAddressx { addr }
=> {
498 self.base_address
= self.get_address(addr
)?
;
501 RawRngListEntry
::StartxEndx { begin, end }
=> {
502 let begin
= self.get_address(begin
)?
;
503 let end
= self.get_address(end
)?
;
506 RawRngListEntry
::StartxLength { begin, length }
=> {
507 let begin
= self.get_address(begin
)?
;
508 let end
= begin
+ length
;
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
);
517 RawRngListEntry
::StartEnd { begin, end }
=> Range { begin, end }
,
518 RawRngListEntry
::StartLength { begin, length }
=> Range
{
524 if range
.begin
> range
.end
{
525 self.raw
.input
.empty();
526 return Err(Error
::InvalidAddressRange
);
529 return Ok(Some(range
));
534 #[cfg(feature = "fallible-iterator")]
535 impl<R
: Reader
> fallible_iterator
::FallibleIterator
for RngListIter
<R
> {
539 fn next(&mut self) -> ::core
::result
::Result
<Option
<Self::Item
>, Self::Error
> {
540 RngListIter
::next(self)
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.
550 /// The first address past the end of the range.
555 /// Check if this is a range end entry.
557 /// This will only occur for raw ranges.
559 pub fn is_end(&self) -> bool
{
560 self.begin
== 0 && self.end
== 0
563 /// Check if this is a base address selection entry.
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.
568 pub fn is_base_address(&self, address_size
: u8) -> bool
{
569 self.begin
== !0 >> (64 - address_size
* 8)
572 /// Parse an address range entry from `.debug_ranges` or `.debug_loc`.
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 }
;
583 /// An address range from the `.debug_ranges`, `.debug_rnglists`, or `.debug_aranges` sections.
584 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
586 /// The beginning address of the range.
589 /// The first address past the end of the range.
594 /// Add a base address to this range.
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
;
606 use crate::common
::Format
;
607 use crate::endianity
::LittleEndian
;
608 use crate::test_util
::GimliSectionMethods
;
609 use test_assembler
::{Endian, Label, LabelMaker, Section}
;
612 fn test_rnglists_32() {
613 let encoding
= Encoding
{
614 format
: Format
::Dwarf32
,
618 let section
= Section
::with_endian(Endian
::Little
)
623 let buf
= section
.get_contents().unwrap();
624 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&buf
, LittleEndian
));
625 let debug_addr_base
= DebugAddrBase(0);
627 let start
= Label
::new();
628 let first
= Label
::new();
629 let size
= Label
::new();
631 let section
= Section
::with_endian(Endian
::Little
)
635 .L16(encoding
.version
)
636 .L8(encoding
.address_size
)
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)
649 .L8(6).L32(0x201_0a00).L32(0x201_0b00)
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.
658 .L8(4).uleb(0).uleb(0xffff_ffff)
659 // A BaseAddressx + OffsetPair
661 .L8(4).uleb(0x10100).uleb(0x10200)
663 .L8(2).uleb(1).uleb(2)
665 .L8(3).uleb(3).uleb(0x100)
670 size
.set_const((§ion
.here() - &start
- 4) as u64);
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
)
690 // A base address selection followed by a normal range.
699 // An empty range followed by a normal range.
733 // A range that starts at 0.
742 // A range that starts and ends at 0.
751 // A range that ends at -1.
760 // A BaseAddressx + OffsetPair
788 assert_eq
!(ranges
.next(), Ok(None
));
790 // An offset at the end of buf.
791 let mut ranges
= rnglists
793 RangeListsOffset(buf
.len()),
800 assert_eq
!(ranges
.next(), Ok(None
));
804 fn test_rnglists_64() {
805 let encoding
= Encoding
{
806 format
: Format
::Dwarf64
,
810 let section
= Section
::with_endian(Endian
::Little
)
815 let buf
= section
.get_contents().unwrap();
816 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&buf
, LittleEndian
));
817 let debug_addr_base
= DebugAddrBase(0);
819 let start
= Label
::new();
820 let first
= Label
::new();
821 let size
= Label
::new();
823 let section
= Section
::with_endian(Endian
::Little
)
828 .L16(encoding
.version
)
829 .L8(encoding
.address_size
)
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)
842 .L8(6).L64(0x201_0a00).L64(0x201_0b00)
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.
851 .L8(4).uleb(0).uleb(0xffff_ffff)
852 // A BaseAddressx + OffsetPair
854 .L8(4).uleb(0x10100).uleb(0x10200)
856 .L8(2).uleb(1).uleb(2)
858 .L8(3).uleb(3).uleb(0x100)
863 size
.set_const((§ion
.here() - &start
- 12) as u64);
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
)
883 // A base address selection followed by a normal range.
892 // An empty range followed by a normal range.
926 // A range that starts at 0.
935 // A range that starts and ends at 0.
944 // A range that ends at -1.
953 // A BaseAddressx + OffsetPair
981 assert_eq
!(ranges
.next(), Ok(None
));
983 // An offset at the end of buf.
984 let mut ranges
= rnglists
986 RangeListsOffset(buf
.len()),
993 assert_eq
!(ranges
.next(), Ok(None
));
997 fn test_raw_range() {
998 let range
= RawRange
{
1002 assert
!(!range
.is_end());
1003 assert
!(!range
.is_base_address(4));
1004 assert
!(!range
.is_base_address(8));
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));
1011 let range
= RawRange
{
1015 assert
!(!range
.is_end());
1016 assert
!(range
.is_base_address(4));
1017 assert
!(!range
.is_base_address(8));
1019 let range
= RawRange
{
1020 begin
: 0xffff_ffff_ffff_ffff,
1023 assert
!(!range
.is_end());
1024 assert
!(!range
.is_base_address(4));
1025 assert
!(range
.is_base_address(8));
1029 fn test_ranges_32() {
1030 let start
= Label
::new();
1031 let first
= Label
::new();
1033 let section
= Section
::with_endian(Endian
::Little
)
1034 // A range before the offset.
1036 .L32(0x10000).L32(0x10100)
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.
1048 // A range that ends at -1.
1049 .L32(0xffff_ffff).L32(0x0000_0000)
1050 .L32(0).L32(0xffff_ffff)
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
,
1068 let mut ranges
= rnglists
1069 .ranges(offset
, encoding
, 0x0100_0000, debug_addr
, debug_addr_base
)
1081 // A base address selection followed by a normal range.
1090 // An empty range followed by a normal range.
1106 // A range that starts at 0.
1115 // A range that ends at -1.
1125 assert_eq
!(ranges
.next(), Ok(None
));
1127 // An offset at the end of buf.
1128 let mut ranges
= rnglists
1130 RangeListsOffset(buf
.len()),
1137 assert_eq
!(ranges
.next(), Ok(None
));
1141 fn test_ranges_64() {
1142 let start
= Label
::new();
1143 let first
= Label
::new();
1145 let section
= Section
::with_endian(Endian
::Little
)
1146 // A range before the offset.
1148 .L64(0x10000).L64(0x10100)
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.
1160 // A range that ends at -1.
1161 .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
1162 .L64(0).L64(0xffff_ffff_ffff_ffff)
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
,
1180 let mut ranges
= rnglists
1181 .ranges(offset
, encoding
, 0x0100_0000, debug_addr
, debug_addr_base
)
1193 // A base address selection followed by a normal range.
1202 // An empty range followed by a normal range.
1218 // A range that starts at 0.
1227 // A range that ends at -1.
1232 end
: 0xffff_ffff_ffff_ffff,
1237 assert_eq
!(ranges
.next(), Ok(None
));
1239 // An offset at the end of buf.
1240 let mut ranges
= rnglists
1242 RangeListsOffset(buf
.len()),
1249 assert_eq
!(ranges
.next(), Ok(None
));
1253 fn test_ranges_invalid() {
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);
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
,
1273 // An invalid range.
1274 let mut ranges
= rnglists
1276 RangeListsOffset(0x0),
1283 assert_eq
!(ranges
.next(), Err(Error
::InvalidAddressRange
));
1285 // An invalid range after wrapping.
1286 let mut ranges
= rnglists
1288 RangeListsOffset(0x8),
1295 assert_eq
!(ranges
.next(), Err(Error
::InvalidAddressRange
));
1297 // An invalid offset.
1298 match rnglists
.ranges(
1299 RangeListsOffset(buf
.len() + 1),
1305 Err(Error
::UnexpectedEof(_
)) => {}
1306 otherwise
=> panic
!("Unexpected result: {:?}", otherwise
),
1311 fn test_get_offset() {
1312 for format
in vec
![Format
::Dwarf32
, Format
::Dwarf64
] {
1313 let encoding
= Encoding
{
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
)
1326 .initial_length(format
, &length
, &start
)
1327 .D16(encoding
.version
)
1328 .D8(encoding
.address_size
)
1333 section
= section
.word(format
.word_size(), 1000 + i
);
1335 section
= section
.mark(&end
);
1336 length
.set_const((&end
- &start
) as u64);
1337 let section
= section
.get_contents().unwrap();
1339 let debug_ranges
= DebugRanges
::from(EndianSlice
::new(&[], LittleEndian
));
1340 let debug_rnglists
= DebugRngLists
::from(EndianSlice
::new(§ion
, LittleEndian
));
1341 let ranges
= RangeLists
::new(debug_ranges
, debug_rnglists
);
1343 let base
= DebugRngListsBase((&first
- &zero
) as usize);
1345 ranges
.get_offset(encoding
, base
, DebugRngListsIndex(0)),
1346 Ok(RangeListsOffset(base
.0 + 1000))
1349 ranges
.get_offset(encoding
, base
, DebugRngListsIndex(19)),
1350 Ok(RangeListsOffset(base
.0 + 1019))