2 DebugAddrBase
, DebugAddrIndex
, DebugLocListsBase
, DebugLocListsIndex
, DwarfFileType
, Encoding
,
3 LocationListsOffset
, SectionId
,
6 use crate::endianity
::Endianity
;
8 lists
::ListsHeader
, DebugAddr
, EndianSlice
, Error
, Expression
, Range
, RawRange
, Reader
,
9 ReaderOffset
, ReaderOffsetId
, Result
, Section
,
12 /// The raw contents of the `.debug_loc` section.
13 #[derive(Debug, Default, Clone, Copy)]
14 pub struct DebugLoc
<R
> {
15 pub(crate) section
: R
,
18 impl<'input
, Endian
> DebugLoc
<EndianSlice
<'input
, Endian
>>
22 /// Construct a new `DebugLoc` instance from the data in the `.debug_loc`
25 /// It is the caller's responsibility to read the `.debug_loc` 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::{DebugLoc, LittleEndian};
32 /// # let buf = [0x00, 0x01, 0x02, 0x03];
33 /// # let read_debug_loc_section_somehow = || &buf;
34 /// let debug_loc = DebugLoc::new(read_debug_loc_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 DebugLoc
<R
> {
42 fn id() -> SectionId
{
46 fn reader(&self) -> &R
{
51 impl<R
> From
<R
> for DebugLoc
<R
> {
52 fn from(section
: R
) -> Self {
57 /// The `DebugLocLists` struct represents the DWARF data
58 /// found in the `.debug_loclists` section.
59 #[derive(Debug, Default, Clone, Copy)]
60 pub struct DebugLocLists
<R
> {
64 impl<'input
, Endian
> DebugLocLists
<EndianSlice
<'input
, Endian
>>
68 /// Construct a new `DebugLocLists` instance from the data in the `.debug_loclists`
71 /// It is the caller's responsibility to read the `.debug_loclists` section and
72 /// present it as a `&[u8]` slice. That means using some ELF loader on
73 /// Linux, a Mach-O loader on macOS, etc.
76 /// use gimli::{DebugLocLists, LittleEndian};
78 /// # let buf = [0x00, 0x01, 0x02, 0x03];
79 /// # let read_debug_loclists_section_somehow = || &buf;
80 /// let debug_loclists = DebugLocLists::new(read_debug_loclists_section_somehow(), LittleEndian);
82 pub fn new(section
: &'input
[u8], endian
: Endian
) -> Self {
83 Self::from(EndianSlice
::new(section
, endian
))
87 impl<R
> Section
<R
> for DebugLocLists
<R
> {
88 fn id() -> SectionId
{
89 SectionId
::DebugLocLists
92 fn reader(&self) -> &R
{
97 impl<R
> From
<R
> for DebugLocLists
<R
> {
98 fn from(section
: R
) -> Self {
99 DebugLocLists { section }
103 pub(crate) type LocListsHeader
= ListsHeader
;
105 impl<Offset
> DebugLocListsBase
<Offset
>
107 Offset
: ReaderOffset
,
109 /// Returns a `DebugLocListsBase` with the default value of DW_AT_loclists_base
110 /// for the given `Encoding` and `DwarfFileType`.
111 pub fn default_for_encoding_and_file(
113 file_type
: DwarfFileType
,
114 ) -> DebugLocListsBase
<Offset
> {
115 if encoding
.version
>= 5 && file_type
== DwarfFileType
::Dwo
{
116 // In .dwo files, the compiler omits the DW_AT_loclists_base attribute (because there is
117 // only a single unit in the file) but we must skip past the header, which the attribute
118 // would normally do for us.
119 DebugLocListsBase(Offset
::from_u8(LocListsHeader
::size_for_encoding(encoding
)))
121 DebugLocListsBase(Offset
::from_u8(0))
126 /// The DWARF data found in `.debug_loc` and `.debug_loclists` sections.
127 #[derive(Debug, Default, Clone, Copy)]
128 pub struct LocationLists
<R
> {
129 debug_loc
: DebugLoc
<R
>,
130 debug_loclists
: DebugLocLists
<R
>,
133 impl<R
> LocationLists
<R
> {
134 /// Construct a new `LocationLists` instance from the data in the `.debug_loc` and
135 /// `.debug_loclists` sections.
136 pub fn new(debug_loc
: DebugLoc
<R
>, debug_loclists
: DebugLocLists
<R
>) -> LocationLists
<R
> {
144 impl<T
> LocationLists
<T
> {
145 /// Create a `LocationLists` that references the data in `self`.
147 /// This is useful when `R` implements `Reader` but `T` does not.
152 /// # let load_section = || unimplemented!();
153 /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
154 /// let owned_section: gimli::LocationLists<Vec<u8>> = load_section();
155 /// // Create a reference to the DWARF section.
156 /// let section = owned_section.borrow(|section| {
157 /// gimli::EndianSlice::new(§ion, gimli::LittleEndian)
160 pub fn borrow
<'a
, F
, R
>(&'a
self, mut borrow
: F
) -> LocationLists
<R
>
162 F
: FnMut(&'a T
) -> R
,
165 debug_loc
: borrow(&self.debug_loc
.section
).into(),
166 debug_loclists
: borrow(&self.debug_loclists
.section
).into(),
171 impl<R
: Reader
> LocationLists
<R
> {
172 /// Iterate over the `LocationListEntry`s starting at the given offset.
174 /// The `unit_encoding` must match the compilation unit that the
175 /// offset was contained in.
177 /// The `base_address` should be obtained from the `DW_AT_low_pc` attribute in the
178 /// `DW_TAG_compile_unit` entry for the compilation unit that contains this location
181 /// Can be [used with
182 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
185 offset
: LocationListsOffset
<R
::Offset
>,
186 unit_encoding
: Encoding
,
188 debug_addr
: &DebugAddr
<R
>,
189 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
190 ) -> Result
<LocListIter
<R
>> {
192 self.raw_locations(offset
, unit_encoding
)?
,
199 /// Similar to `locations`, but with special handling for .dwo files.
200 /// This should only been used when this `LocationLists` was loaded from a
202 pub fn locations_dwo(
204 offset
: LocationListsOffset
<R
::Offset
>,
205 unit_encoding
: Encoding
,
207 debug_addr
: &DebugAddr
<R
>,
208 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
209 ) -> Result
<LocListIter
<R
>> {
211 self.raw_locations_dwo(offset
, unit_encoding
)?
,
218 /// Iterate over the raw `LocationListEntry`s starting at the given offset.
220 /// The `unit_encoding` must match the compilation unit that the
221 /// offset was contained in.
223 /// This iterator does not perform any processing of the location entries,
224 /// such as handling base addresses.
226 /// Can be [used with
227 /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
228 pub fn raw_locations(
230 offset
: LocationListsOffset
<R
::Offset
>,
231 unit_encoding
: Encoding
,
232 ) -> Result
<RawLocListIter
<R
>> {
233 let (mut input
, format
) = if unit_encoding
.version
<= 4 {
234 (self.debug_loc
.section
.clone(), LocListsFormat
::Bare
)
236 (self.debug_loclists
.section
.clone(), LocListsFormat
::Lle
)
238 input
.skip(offset
.0)?
;
239 Ok(RawLocListIter
::new(input
, unit_encoding
, format
))
242 /// Similar to `raw_locations`, but with special handling for .dwo files.
243 /// This should only been used when this `LocationLists` was loaded from a
245 pub fn raw_locations_dwo(
247 offset
: LocationListsOffset
<R
::Offset
>,
248 unit_encoding
: Encoding
,
249 ) -> Result
<RawLocListIter
<R
>> {
250 let mut input
= if unit_encoding
.version
<= 4 {
251 // In the GNU split dwarf extension the locations are present in the
252 // .debug_loc section but are encoded with the DW_LLE values used
253 // for the DWARF 5 .debug_loclists section.
254 self.debug_loc
.section
.clone()
256 self.debug_loclists
.section
.clone()
258 input
.skip(offset
.0)?
;
259 Ok(RawLocListIter
::new(
266 /// Returns the `.debug_loclists` offset at the given `base` and `index`.
268 /// The `base` must be the `DW_AT_loclists_base` value from the compilation unit DIE.
269 /// This is an offset that points to the first entry following the header.
271 /// The `index` is the value of a `DW_FORM_loclistx` attribute.
274 unit_encoding
: Encoding
,
275 base
: DebugLocListsBase
<R
::Offset
>,
276 index
: DebugLocListsIndex
<R
::Offset
>,
277 ) -> Result
<LocationListsOffset
<R
::Offset
>> {
278 let format
= unit_encoding
.format
;
279 let input
= &mut self.debug_loclists
.section
.clone();
281 input
.skip(R
::Offset
::from_u64(
282 index
.0.into_u
64() * u64::from(format
.word_size()),
286 .map(|x
| LocationListsOffset(base
.0 + x
))
289 /// Call `Reader::lookup_offset_id` for each section, and return the first match.
290 pub fn lookup_offset_id(&self, id
: ReaderOffsetId
) -> Option
<(SectionId
, R
::Offset
)> {
292 .lookup_offset_id(id
)
293 .or_else(|| self.debug_loclists
.lookup_offset_id(id
))
297 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
298 enum LocListsFormat
{
299 /// The bare location list format used before DWARF 5.
301 /// The DW_LLE encoded range list format used in DWARF 5 and the non-standard GNU
302 /// split dwarf extension.
306 /// A raw iterator over a location list.
308 /// This iterator does not perform any processing of the location entries,
309 /// such as handling base addresses.
311 pub struct RawLocListIter
<R
: Reader
> {
314 format
: LocListsFormat
,
317 /// A raw entry in .debug_loclists.
318 #[derive(Clone, Debug)]
319 pub enum RawLocListEntry
<R
: Reader
> {
320 /// A location from DWARF version <= 4.
321 AddressOrOffsetPair
{
322 /// Start of range. May be an address or an offset.
324 /// End of range. May be an address or an offset.
329 /// DW_LLE_base_address
334 /// DW_LLE_base_addressx
337 addr
: DebugAddrIndex
<R
::Offset
>,
339 /// DW_LLE_startx_endx
342 begin
: DebugAddrIndex
<R
::Offset
>,
344 end
: DebugAddrIndex
<R
::Offset
>,
348 /// DW_LLE_startx_length
351 begin
: DebugAddrIndex
<R
::Offset
>,
357 /// DW_LLE_offset_pair
366 /// DW_LLE_default_location
380 /// DW_LLE_start_length
391 fn parse_data
<R
: Reader
>(input
: &mut R
, encoding
: Encoding
) -> Result
<Expression
<R
>> {
392 if encoding
.version
>= 5 {
393 let len
= R
::Offset
::from_u64(input
.read_uleb128()?
)?
;
394 Ok(Expression(input
.split(len
)?
))
396 // In the GNU split-dwarf extension this is a fixed 2 byte value.
397 let len
= R
::Offset
::from_u16(input
.read_u16()?
);
398 Ok(Expression(input
.split(len
)?
))
402 impl<R
: Reader
> RawLocListEntry
<R
> {
403 /// Parse a location list entry from `.debug_loclists`
404 fn parse(input
: &mut R
, encoding
: Encoding
, format
: LocListsFormat
) -> Result
<Option
<Self>> {
406 LocListsFormat
::Bare
=> {
407 let range
= RawRange
::parse(input
, encoding
.address_size
)?
;
410 } else if range
.is_base_address(encoding
.address_size
) {
411 Some(RawLocListEntry
::BaseAddress { addr: range.end }
)
413 let len
= R
::Offset
::from_u16(input
.read_u16()?
);
414 let data
= Expression(input
.split(len
)?
);
415 Some(RawLocListEntry
::AddressOrOffsetPair
{
422 LocListsFormat
::Lle
=> match constants
::DwLle(input
.read_u8()?
) {
423 constants
::DW_LLE_end_of_list
=> None
,
424 constants
::DW_LLE_base_addressx
=> Some(RawLocListEntry
::BaseAddressx
{
425 addr
: DebugAddrIndex(input
.read_uleb128().and_then(R
::Offset
::from_u64
)?
),
427 constants
::DW_LLE_startx_endx
=> Some(RawLocListEntry
::StartxEndx
{
428 begin
: DebugAddrIndex(input
.read_uleb128().and_then(R
::Offset
::from_u64
)?
),
429 end
: DebugAddrIndex(input
.read_uleb128().and_then(R
::Offset
::from_u64
)?
),
430 data
: parse_data(input
, encoding
)?
,
432 constants
::DW_LLE_startx_length
=> Some(RawLocListEntry
::StartxLength
{
433 begin
: DebugAddrIndex(input
.read_uleb128().and_then(R
::Offset
::from_u64
)?
),
434 length
: if encoding
.version
>= 5 {
435 input
.read_uleb128()?
437 // In the GNU split-dwarf extension this is a fixed 4 byte value.
438 input
.read_u32()?
as u64
440 data
: parse_data(input
, encoding
)?
,
442 constants
::DW_LLE_offset_pair
=> Some(RawLocListEntry
::OffsetPair
{
443 begin
: input
.read_uleb128()?
,
444 end
: input
.read_uleb128()?
,
445 data
: parse_data(input
, encoding
)?
,
447 constants
::DW_LLE_default_location
=> Some(RawLocListEntry
::DefaultLocation
{
448 data
: parse_data(input
, encoding
)?
,
450 constants
::DW_LLE_base_address
=> Some(RawLocListEntry
::BaseAddress
{
451 addr
: input
.read_address(encoding
.address_size
)?
,
453 constants
::DW_LLE_start_end
=> Some(RawLocListEntry
::StartEnd
{
454 begin
: input
.read_address(encoding
.address_size
)?
,
455 end
: input
.read_address(encoding
.address_size
)?
,
456 data
: parse_data(input
, encoding
)?
,
458 constants
::DW_LLE_start_length
=> Some(RawLocListEntry
::StartLength
{
459 begin
: input
.read_address(encoding
.address_size
)?
,
460 length
: input
.read_uleb128()?
,
461 data
: parse_data(input
, encoding
)?
,
464 return Err(Error
::InvalidAddressRange
);
471 impl<R
: Reader
> RawLocListIter
<R
> {
472 /// Construct a `RawLocListIter`.
473 fn new(input
: R
, encoding
: Encoding
, format
: LocListsFormat
) -> RawLocListIter
<R
> {
481 /// Advance the iterator to the next location.
482 pub fn next(&mut self) -> Result
<Option
<RawLocListEntry
<R
>>> {
483 if self.input
.is_empty() {
487 match RawLocListEntry
::parse(&mut self.input
, self.encoding
, self.format
) {
502 #[cfg(feature = "fallible-iterator")]
503 impl<R
: Reader
> fallible_iterator
::FallibleIterator
for RawLocListIter
<R
> {
504 type Item
= RawLocListEntry
<R
>;
507 fn next(&mut self) -> ::core
::result
::Result
<Option
<Self::Item
>, Self::Error
> {
508 RawLocListIter
::next(self)
512 /// An iterator over a location list.
514 /// This iterator internally handles processing of base address selection entries
515 /// and list end entries. Thus, it only returns location entries that are valid
516 /// and already adjusted for the base address.
518 pub struct LocListIter
<R
: Reader
> {
519 raw
: RawLocListIter
<R
>,
521 debug_addr
: DebugAddr
<R
>,
522 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
525 impl<R
: Reader
> LocListIter
<R
> {
526 /// Construct a `LocListIter`.
528 raw
: RawLocListIter
<R
>,
530 debug_addr
: DebugAddr
<R
>,
531 debug_addr_base
: DebugAddrBase
<R
::Offset
>,
532 ) -> LocListIter
<R
> {
542 fn get_address(&self, index
: DebugAddrIndex
<R
::Offset
>) -> Result
<u64> {
544 .get_address(self.raw
.encoding
.address_size
, self.debug_addr_base
, index
)
547 /// Advance the iterator to the next location.
548 pub fn next(&mut self) -> Result
<Option
<LocationListEntry
<R
>>> {
550 let raw_loc
= match self.raw
.next()?
{
552 None
=> return Ok(None
),
555 let loc
= self.convert_raw(raw_loc
)?
;
562 /// Return the next raw location.
564 /// The raw location should be passed to `convert_raw`.
566 pub fn next_raw(&mut self) -> Result
<Option
<RawLocListEntry
<R
>>> {
570 /// Convert a raw location into a location, and update the state of the iterator.
572 /// The raw location should have been obtained from `next_raw`.
576 raw_loc
: RawLocListEntry
<R
>,
577 ) -> Result
<Option
<LocationListEntry
<R
>>> {
578 let mask
= !0 >> (64 - self.raw
.encoding
.address_size
* 8);
579 let tombstone
= if self.raw
.encoding
.version
<= 4 {
585 let (range
, data
) = match raw_loc
{
586 RawLocListEntry
::BaseAddress { addr }
=> {
587 self.base_address
= addr
;
590 RawLocListEntry
::BaseAddressx { addr }
=> {
591 self.base_address
= self.get_address(addr
)?
;
594 RawLocListEntry
::StartxEndx { begin, end, data }
=> {
595 let begin
= self.get_address(begin
)?
;
596 let end
= self.get_address(end
)?
;
597 (Range { begin, end }
, data
)
599 RawLocListEntry
::StartxLength
{
604 let begin
= self.get_address(begin
)?
;
605 let end
= begin
.wrapping_add(length
) & mask
;
606 (Range { begin, end }
, data
)
608 RawLocListEntry
::DefaultLocation { data }
=> (
611 end
: u64::max_value(),
615 RawLocListEntry
::AddressOrOffsetPair { begin, end, data }
616 | RawLocListEntry
::OffsetPair { begin, end, data }
=> {
617 if self.base_address
== tombstone
{
620 let mut range
= Range { begin, end }
;
621 range
.add_base_address(self.base_address
, self.raw
.encoding
.address_size
);
624 RawLocListEntry
::StartEnd { begin, end, data }
=> (Range { begin, end }
, data
),
625 RawLocListEntry
::StartLength
{
630 let end
= begin
.wrapping_add(length
) & mask
;
631 (Range { begin, end }
, data
)
635 if range
.begin
== tombstone
{
639 if range
.begin
> range
.end
{
640 self.raw
.input
.empty();
641 return Err(Error
::InvalidLocationAddressRange
);
644 Ok(Some(LocationListEntry { range, data }
))
648 #[cfg(feature = "fallible-iterator")]
649 impl<R
: Reader
> fallible_iterator
::FallibleIterator
for LocListIter
<R
> {
650 type Item
= LocationListEntry
<R
>;
653 fn next(&mut self) -> ::core
::result
::Result
<Option
<Self::Item
>, Self::Error
> {
654 LocListIter
::next(self)
658 /// A location list entry from the `.debug_loc` or `.debug_loclists` sections.
659 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
660 pub struct LocationListEntry
<R
: Reader
> {
661 /// The address range that this location is valid for.
664 /// The data containing a single location description.
665 pub data
: Expression
<R
>,
671 use crate::common
::Format
;
672 use crate::endianity
::LittleEndian
;
673 use crate::read
::{EndianSlice, Range}
;
674 use crate::test_util
::GimliSectionMethods
;
675 use test_assembler
::{Endian, Label, LabelMaker, Section}
;
678 fn test_loclists_32() {
679 let tombstone
= !0u32;
680 let encoding
= Encoding
{
681 format
: Format
::Dwarf32
,
686 let section
= Section
::with_endian(Endian
::Little
)
693 let buf
= section
.get_contents().unwrap();
694 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&buf
, LittleEndian
));
695 let debug_addr_base
= DebugAddrBase(0);
697 let start
= Label
::new();
698 let first
= Label
::new();
699 let size
= Label
::new();
701 let section
= Section
::with_endian(Endian
::Little
)
705 .L16(encoding
.version
)
706 .L8(encoding
.address_size
)
711 .L8(4).uleb(0x10200).uleb(0x10300).uleb(4).L32(2)
712 // A base address selection followed by an OffsetPair.
713 .L8(6).L32(0x0200_0000)
714 .L8(4).uleb(0x10400).uleb(0x10500).uleb(4).L32(3)
715 // An empty OffsetPair followed by a normal OffsetPair.
716 .L8(4).uleb(0x10600).uleb(0x10600).uleb(4).L32(4)
717 .L8(4).uleb(0x10800).uleb(0x10900).uleb(4).L32(5)
719 .L8(7).L32(0x201_0a00).L32(0x201_0b00).uleb(4).L32(6)
721 .L8(8).L32(0x201_0c00).uleb(0x100).uleb(4).L32(7)
722 // An OffsetPair that starts at 0.
723 .L8(4).uleb(0).uleb(1).uleb(4).L32(8)
724 // An OffsetPair that ends at -1.
726 .L8(4).uleb(0).uleb(0xffff_ffff).uleb(4).L32(9)
728 .L8(5).uleb(4).L32(10)
729 // A BaseAddressx + OffsetPair
731 .L8(4).uleb(0x10100).uleb(0x10200).uleb(4).L32(11)
733 .L8(2).uleb(1).uleb(2).uleb(4).L32(12)
735 .L8(3).uleb(3).uleb(0x100).uleb(4).L32(13)
737 // Tombstone entries, all of which should be ignored.
738 // A BaseAddressx that is a tombstone.
740 .L8(4).uleb(0x11100).uleb(0x11200).uleb(4).L32(20)
741 // A BaseAddress that is a tombstone.
742 .L8(6).L32(tombstone
)
743 .L8(4).uleb(0x11300).uleb(0x11400).uleb(4).L32(21)
744 // A StartxEndx that is a tombstone.
745 .L8(2).uleb(4).uleb(5).uleb(4).L32(22)
746 // A StartxLength that is a tombstone.
747 .L8(3).uleb(4).uleb(0x100).uleb(4).L32(23)
748 // A StartEnd that is a tombstone.
749 .L8(7).L32(tombstone
).L32(0x201_1500).uleb(4).L32(24)
750 // A StartLength that is a tombstone.
751 .L8(8).L32(tombstone
).uleb(0x100).uleb(4).L32(25)
752 // A StartEnd (not ignored)
753 .L8(7).L32(0x201_1600).L32(0x201_1700).uleb(4).L32(26)
759 size
.set_const((§ion
.here() - &start
- 4) as u64);
761 let buf
= section
.get_contents().unwrap();
762 let debug_loc
= DebugLoc
::new(&[], LittleEndian
);
763 let debug_loclists
= DebugLocLists
::new(&buf
, LittleEndian
);
764 let loclists
= LocationLists
::new(debug_loc
, debug_loclists
);
765 let offset
= LocationListsOffset((&first
- &start
) as usize);
766 let mut locations
= loclists
767 .locations(offset
, encoding
, 0x0100_0000, debug_addr
, debug_addr_base
)
770 // A normal location.
773 Ok(Some(LocationListEntry
{
778 data
: Expression(EndianSlice
::new(&[2, 0, 0, 0], LittleEndian
)),
782 // A base address selection followed by a normal location.
785 Ok(Some(LocationListEntry
{
790 data
: Expression(EndianSlice
::new(&[3, 0, 0, 0], LittleEndian
)),
794 // An empty location range followed by a normal location.
797 Ok(Some(LocationListEntry
{
802 data
: Expression(EndianSlice
::new(&[4, 0, 0, 0], LittleEndian
)),
807 Ok(Some(LocationListEntry
{
812 data
: Expression(EndianSlice
::new(&[5, 0, 0, 0], LittleEndian
)),
816 // A normal location.
819 Ok(Some(LocationListEntry
{
824 data
: Expression(EndianSlice
::new(&[6, 0, 0, 0], LittleEndian
)),
828 // A normal location.
831 Ok(Some(LocationListEntry
{
836 data
: Expression(EndianSlice
::new(&[7, 0, 0, 0], LittleEndian
)),
840 // A location range that starts at 0.
843 Ok(Some(LocationListEntry
{
848 data
: Expression(EndianSlice
::new(&[8, 0, 0, 0], LittleEndian
)),
852 // A location range that ends at -1.
855 Ok(Some(LocationListEntry
{
860 data
: Expression(EndianSlice
::new(&[9, 0, 0, 0], LittleEndian
)),
864 // A DefaultLocation.
867 Ok(Some(LocationListEntry
{
870 end
: u64::max_value(),
872 data
: Expression(EndianSlice
::new(&[10, 0, 0, 0], LittleEndian
)),
876 // A BaseAddressx + OffsetPair
879 Ok(Some(LocationListEntry
{
884 data
: Expression(EndianSlice
::new(&[11, 0, 0, 0], LittleEndian
)),
891 Ok(Some(LocationListEntry
{
896 data
: Expression(EndianSlice
::new(&[12, 0, 0, 0], LittleEndian
)),
903 Ok(Some(LocationListEntry
{
908 data
: Expression(EndianSlice
::new(&[13, 0, 0, 0], LittleEndian
)),
912 // A StartEnd location following the tombstones
915 Ok(Some(LocationListEntry
{
920 data
: Expression(EndianSlice
::new(&[26, 0, 0, 0], LittleEndian
)),
924 // A location list end.
925 assert_eq
!(locations
.next(), Ok(None
));
927 // An offset at the end of buf.
928 let mut locations
= loclists
930 LocationListsOffset(buf
.len()),
937 assert_eq
!(locations
.next(), Ok(None
));
941 fn test_loclists_64() {
942 let tombstone
= !0u64;
943 let encoding
= Encoding
{
944 format
: Format
::Dwarf64
,
949 let section
= Section
::with_endian(Endian
::Little
)
956 let buf
= section
.get_contents().unwrap();
957 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&buf
, LittleEndian
));
958 let debug_addr_base
= DebugAddrBase(0);
960 let start
= Label
::new();
961 let first
= Label
::new();
962 let size
= Label
::new();
964 let section
= Section
::with_endian(Endian
::Little
)
969 .L16(encoding
.version
)
970 .L8(encoding
.address_size
)
975 .L8(4).uleb(0x10200).uleb(0x10300).uleb(4).L32(2)
976 // A base address selection followed by an OffsetPair.
977 .L8(6).L64(0x0200_0000)
978 .L8(4).uleb(0x10400).uleb(0x10500).uleb(4).L32(3)
979 // An empty OffsetPair followed by a normal OffsetPair.
980 .L8(4).uleb(0x10600).uleb(0x10600).uleb(4).L32(4)
981 .L8(4).uleb(0x10800).uleb(0x10900).uleb(4).L32(5)
983 .L8(7).L64(0x201_0a00).L64(0x201_0b00).uleb(4).L32(6)
985 .L8(8).L64(0x201_0c00).uleb(0x100).uleb(4).L32(7)
986 // An OffsetPair that starts at 0.
987 .L8(4).uleb(0).uleb(1).uleb(4).L32(8)
988 // An OffsetPair that ends at -1.
990 .L8(4).uleb(0).uleb(0xffff_ffff).uleb(4).L32(9)
992 .L8(5).uleb(4).L32(10)
993 // A BaseAddressx + OffsetPair
995 .L8(4).uleb(0x10100).uleb(0x10200).uleb(4).L32(11)
997 .L8(2).uleb(1).uleb(2).uleb(4).L32(12)
999 .L8(3).uleb(3).uleb(0x100).uleb(4).L32(13)
1001 // Tombstone entries, all of which should be ignored.
1002 // A BaseAddressx that is a tombstone.
1004 .L8(4).uleb(0x11100).uleb(0x11200).uleb(4).L32(20)
1005 // A BaseAddress that is a tombstone.
1006 .L8(6).L64(tombstone
)
1007 .L8(4).uleb(0x11300).uleb(0x11400).uleb(4).L32(21)
1008 // A StartxEndx that is a tombstone.
1009 .L8(2).uleb(4).uleb(5).uleb(4).L32(22)
1010 // A StartxLength that is a tombstone.
1011 .L8(3).uleb(4).uleb(0x100).uleb(4).L32(23)
1012 // A StartEnd that is a tombstone.
1013 .L8(7).L64(tombstone
).L64(0x201_1500).uleb(4).L32(24)
1014 // A StartLength that is a tombstone.
1015 .L8(8).L64(tombstone
).uleb(0x100).uleb(4).L32(25)
1016 // A StartEnd (not ignored)
1017 .L8(7).L64(0x201_1600).L64(0x201_1700).uleb(4).L32(26)
1023 size
.set_const((§ion
.here() - &start
- 12) as u64);
1025 let buf
= section
.get_contents().unwrap();
1026 let debug_loc
= DebugLoc
::new(&[], LittleEndian
);
1027 let debug_loclists
= DebugLocLists
::new(&buf
, LittleEndian
);
1028 let loclists
= LocationLists
::new(debug_loc
, debug_loclists
);
1029 let offset
= LocationListsOffset((&first
- &start
) as usize);
1030 let mut locations
= loclists
1031 .locations(offset
, encoding
, 0x0100_0000, debug_addr
, debug_addr_base
)
1034 // A normal location.
1037 Ok(Some(LocationListEntry
{
1042 data
: Expression(EndianSlice
::new(&[2, 0, 0, 0], LittleEndian
)),
1046 // A base address selection followed by a normal location.
1049 Ok(Some(LocationListEntry
{
1054 data
: Expression(EndianSlice
::new(&[3, 0, 0, 0], LittleEndian
)),
1058 // An empty location range followed by a normal location.
1061 Ok(Some(LocationListEntry
{
1066 data
: Expression(EndianSlice
::new(&[4, 0, 0, 0], LittleEndian
)),
1071 Ok(Some(LocationListEntry
{
1076 data
: Expression(EndianSlice
::new(&[5, 0, 0, 0], LittleEndian
)),
1080 // A normal location.
1083 Ok(Some(LocationListEntry
{
1088 data
: Expression(EndianSlice
::new(&[6, 0, 0, 0], LittleEndian
)),
1092 // A normal location.
1095 Ok(Some(LocationListEntry
{
1100 data
: Expression(EndianSlice
::new(&[7, 0, 0, 0], LittleEndian
)),
1104 // A location range that starts at 0.
1107 Ok(Some(LocationListEntry
{
1112 data
: Expression(EndianSlice
::new(&[8, 0, 0, 0], LittleEndian
)),
1116 // A location range that ends at -1.
1119 Ok(Some(LocationListEntry
{
1124 data
: Expression(EndianSlice
::new(&[9, 0, 0, 0], LittleEndian
)),
1128 // A DefaultLocation.
1131 Ok(Some(LocationListEntry
{
1134 end
: u64::max_value(),
1136 data
: Expression(EndianSlice
::new(&[10, 0, 0, 0], LittleEndian
)),
1140 // A BaseAddressx + OffsetPair
1143 Ok(Some(LocationListEntry
{
1148 data
: Expression(EndianSlice
::new(&[11, 0, 0, 0], LittleEndian
)),
1155 Ok(Some(LocationListEntry
{
1160 data
: Expression(EndianSlice
::new(&[12, 0, 0, 0], LittleEndian
)),
1167 Ok(Some(LocationListEntry
{
1172 data
: Expression(EndianSlice
::new(&[13, 0, 0, 0], LittleEndian
)),
1176 // A StartEnd location following the tombstones
1179 Ok(Some(LocationListEntry
{
1184 data
: Expression(EndianSlice
::new(&[26, 0, 0, 0], LittleEndian
)),
1188 // A location list end.
1189 assert_eq
!(locations
.next(), Ok(None
));
1191 // An offset at the end of buf.
1192 let mut locations
= loclists
1194 LocationListsOffset(buf
.len()),
1201 assert_eq
!(locations
.next(), Ok(None
));
1205 fn test_location_list_32() {
1206 let tombstone
= !0u32 - 1;
1207 let start
= Label
::new();
1208 let first
= Label
::new();
1210 let section
= Section
::with_endian(Endian
::Little
)
1211 // A location before the offset.
1213 .L32(0x10000).L32(0x10100).L16(4).L32(1)
1215 // A normal location.
1216 .L32(0x10200).L32(0x10300).L16(4).L32(2)
1217 // A base address selection followed by a normal location.
1218 .L32(0xffff_ffff).L32(0x0200_0000)
1219 .L32(0x10400).L32(0x10500).L16(4).L32(3)
1220 // An empty location range followed by a normal location.
1221 .L32(0x10600).L32(0x10600).L16(4).L32(4)
1222 .L32(0x10800).L32(0x10900).L16(4).L32(5)
1223 // A location range that starts at 0.
1224 .L32(0).L32(1).L16(4).L32(6)
1225 // A location range that ends at -1.
1226 .L32(0xffff_ffff).L32(0x0000_0000)
1227 .L32(0).L32(0xffff_ffff).L16(4).L32(7)
1228 // A normal location with tombstone.
1229 .L32(tombstone
).L32(tombstone
).L16(4).L32(8)
1230 // A base address selection with tombstone followed by a normal location.
1231 .L32(0xffff_ffff).L32(tombstone
)
1232 .L32(0x10a00).L32(0x10b00).L16(4).L32(9)
1233 // A location list end.
1238 let buf
= section
.get_contents().unwrap();
1239 let debug_loc
= DebugLoc
::new(&buf
, LittleEndian
);
1240 let debug_loclists
= DebugLocLists
::new(&[], LittleEndian
);
1241 let loclists
= LocationLists
::new(debug_loc
, debug_loclists
);
1242 let offset
= LocationListsOffset((&first
- &start
) as usize);
1243 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&[], LittleEndian
));
1244 let debug_addr_base
= DebugAddrBase(0);
1245 let encoding
= Encoding
{
1246 format
: Format
::Dwarf32
,
1250 let mut locations
= loclists
1251 .locations(offset
, encoding
, 0x0100_0000, debug_addr
, debug_addr_base
)
1254 // A normal location.
1257 Ok(Some(LocationListEntry
{
1262 data
: Expression(EndianSlice
::new(&[2, 0, 0, 0], LittleEndian
)),
1266 // A base address selection followed by a normal location.
1269 Ok(Some(LocationListEntry
{
1274 data
: Expression(EndianSlice
::new(&[3, 0, 0, 0], LittleEndian
)),
1278 // An empty location range followed by a normal location.
1281 Ok(Some(LocationListEntry
{
1286 data
: Expression(EndianSlice
::new(&[4, 0, 0, 0], LittleEndian
)),
1291 Ok(Some(LocationListEntry
{
1296 data
: Expression(EndianSlice
::new(&[5, 0, 0, 0], LittleEndian
)),
1300 // A location range that starts at 0.
1303 Ok(Some(LocationListEntry
{
1308 data
: Expression(EndianSlice
::new(&[6, 0, 0, 0], LittleEndian
)),
1312 // A location range that ends at -1.
1315 Ok(Some(LocationListEntry
{
1320 data
: Expression(EndianSlice
::new(&[7, 0, 0, 0], LittleEndian
)),
1324 // A location list end.
1325 assert_eq
!(locations
.next(), Ok(None
));
1327 // An offset at the end of buf.
1328 let mut locations
= loclists
1330 LocationListsOffset(buf
.len()),
1337 assert_eq
!(locations
.next(), Ok(None
));
1341 fn test_location_list_64() {
1342 let tombstone
= !0u64 - 1;
1343 let start
= Label
::new();
1344 let first
= Label
::new();
1346 let section
= Section
::with_endian(Endian
::Little
)
1347 // A location before the offset.
1349 .L64(0x10000).L64(0x10100).L16(4).L32(1)
1351 // A normal location.
1352 .L64(0x10200).L64(0x10300).L16(4).L32(2)
1353 // A base address selection followed by a normal location.
1354 .L64(0xffff_ffff_ffff_ffff).L64(0x0200_0000)
1355 .L64(0x10400).L64(0x10500).L16(4).L32(3)
1356 // An empty location range followed by a normal location.
1357 .L64(0x10600).L64(0x10600).L16(4).L32(4)
1358 .L64(0x10800).L64(0x10900).L16(4).L32(5)
1359 // A location range that starts at 0.
1360 .L64(0).L64(1).L16(4).L32(6)
1361 // A location range that ends at -1.
1362 .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
1363 .L64(0).L64(0xffff_ffff_ffff_ffff).L16(4).L32(7)
1364 // A normal location with tombstone.
1365 .L64(tombstone
).L64(tombstone
).L16(4).L32(8)
1366 // A base address selection with tombstone followed by a normal location.
1367 .L64(0xffff_ffff_ffff_ffff).L64(tombstone
)
1368 .L64(0x10a00).L64(0x10b00).L16(4).L32(9)
1369 // A location list end.
1374 let buf
= section
.get_contents().unwrap();
1375 let debug_loc
= DebugLoc
::new(&buf
, LittleEndian
);
1376 let debug_loclists
= DebugLocLists
::new(&[], LittleEndian
);
1377 let loclists
= LocationLists
::new(debug_loc
, debug_loclists
);
1378 let offset
= LocationListsOffset((&first
- &start
) as usize);
1379 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&[], LittleEndian
));
1380 let debug_addr_base
= DebugAddrBase(0);
1381 let encoding
= Encoding
{
1382 format
: Format
::Dwarf64
,
1386 let mut locations
= loclists
1387 .locations(offset
, encoding
, 0x0100_0000, debug_addr
, debug_addr_base
)
1390 // A normal location.
1393 Ok(Some(LocationListEntry
{
1398 data
: Expression(EndianSlice
::new(&[2, 0, 0, 0], LittleEndian
)),
1402 // A base address selection followed by a normal location.
1405 Ok(Some(LocationListEntry
{
1410 data
: Expression(EndianSlice
::new(&[3, 0, 0, 0], LittleEndian
)),
1414 // An empty location range followed by a normal location.
1417 Ok(Some(LocationListEntry
{
1422 data
: Expression(EndianSlice
::new(&[4, 0, 0, 0], LittleEndian
)),
1427 Ok(Some(LocationListEntry
{
1432 data
: Expression(EndianSlice
::new(&[5, 0, 0, 0], LittleEndian
)),
1436 // A location range that starts at 0.
1439 Ok(Some(LocationListEntry
{
1444 data
: Expression(EndianSlice
::new(&[6, 0, 0, 0], LittleEndian
)),
1448 // A location range that ends at -1.
1451 Ok(Some(LocationListEntry
{
1454 end
: 0xffff_ffff_ffff_ffff,
1456 data
: Expression(EndianSlice
::new(&[7, 0, 0, 0], LittleEndian
)),
1460 // A location list end.
1461 assert_eq
!(locations
.next(), Ok(None
));
1463 // An offset at the end of buf.
1464 let mut locations
= loclists
1466 LocationListsOffset(buf
.len()),
1473 assert_eq
!(locations
.next(), Ok(None
));
1477 fn test_locations_invalid() {
1479 let section
= Section
::with_endian(Endian
::Little
)
1480 // An invalid location range.
1481 .L32(0x20000).L32(0x10000).L16(4).L32(1)
1482 // An invalid range after wrapping.
1483 .L32(0x20000).L32(0xff01_0000).L16(4).L32(2);
1485 let buf
= section
.get_contents().unwrap();
1486 let debug_loc
= DebugLoc
::new(&buf
, LittleEndian
);
1487 let debug_loclists
= DebugLocLists
::new(&[], LittleEndian
);
1488 let loclists
= LocationLists
::new(debug_loc
, debug_loclists
);
1489 let debug_addr
= &DebugAddr
::from(EndianSlice
::new(&[], LittleEndian
));
1490 let debug_addr_base
= DebugAddrBase(0);
1491 let encoding
= Encoding
{
1492 format
: Format
::Dwarf32
,
1497 // An invalid location range.
1498 let mut locations
= loclists
1500 LocationListsOffset(0x0),
1507 assert_eq
!(locations
.next(), Err(Error
::InvalidLocationAddressRange
));
1509 // An invalid location range after wrapping.
1510 let mut locations
= loclists
1512 LocationListsOffset(14),
1519 assert_eq
!(locations
.next(), Err(Error
::InvalidLocationAddressRange
));
1521 // An invalid offset.
1522 match loclists
.locations(
1523 LocationListsOffset(buf
.len() + 1),
1529 Err(Error
::UnexpectedEof(_
)) => {}
1530 otherwise
=> panic
!("Unexpected result: {:?}", otherwise
),
1535 fn test_get_offset() {
1536 for format
in vec
![Format
::Dwarf32
, Format
::Dwarf64
] {
1537 let encoding
= Encoding
{
1543 let zero
= Label
::new();
1544 let length
= Label
::new();
1545 let start
= Label
::new();
1546 let first
= Label
::new();
1547 let end
= Label
::new();
1548 let mut section
= Section
::with_endian(Endian
::Little
)
1550 .initial_length(format
, &length
, &start
)
1551 .D16(encoding
.version
)
1552 .D8(encoding
.address_size
)
1557 section
= section
.word(format
.word_size(), 1000 + i
);
1559 section
= section
.mark(&end
);
1560 length
.set_const((&end
- &start
) as u64);
1561 let section
= section
.get_contents().unwrap();
1563 let debug_loc
= DebugLoc
::from(EndianSlice
::new(&[], LittleEndian
));
1564 let debug_loclists
= DebugLocLists
::from(EndianSlice
::new(§ion
, LittleEndian
));
1565 let locations
= LocationLists
::new(debug_loc
, debug_loclists
);
1567 let base
= DebugLocListsBase((&first
- &zero
) as usize);
1569 locations
.get_offset(encoding
, base
, DebugLocListsIndex(0)),
1570 Ok(LocationListsOffset(base
.0 + 1000))
1573 locations
.get_offset(encoding
, base
, DebugLocListsIndex(19)),
1574 Ok(LocationListsOffset(base
.0 + 1019))
1580 fn test_loclists_gnu_v4_split_dwarf() {
1583 0x03, // DW_LLE_startx_length
1584 0x00, // ULEB encoded b7
1585 0x08, 0x00, 0x00, 0x00, // Fixed 4 byte length of 8
1586 0x03, 0x00, // Fixed two byte length of the location
1587 0x11, 0x00, // DW_OP_constu 0
1588 0x9f, // DW_OP_stack_value
1590 //0x99, 0x99, 0x99, 0x99
1592 let data_buf
= [0x11, 0x00, 0x9f];
1593 let expected_data
= EndianSlice
::new(&data_buf
, LittleEndian
);
1594 let debug_loc
= DebugLoc
::new(&buf
, LittleEndian
);
1595 let debug_loclists
= DebugLocLists
::new(&[], LittleEndian
);
1596 let loclists
= LocationLists
::new(debug_loc
, debug_loclists
);
1598 &DebugAddr
::from(EndianSlice
::new(&[0x01, 0x02, 0x03, 0x04], LittleEndian
));
1599 let debug_addr_base
= DebugAddrBase(0);
1600 let encoding
= Encoding
{
1601 format
: Format
::Dwarf32
,
1606 // An invalid location range.
1607 let mut locations
= loclists
1609 LocationListsOffset(0x0),
1618 Ok(Some(LocationListEntry
{
1623 data
: Expression(expected_data
),