Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/gimli-0.29.0/src/read/dwarf.rs
Line
Count
Source (jump to first uncovered line)
1
use alloc::string::String;
2
use alloc::sync::Arc;
3
4
use crate::common::{
5
    DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineStrOffset, DebugLocListsBase,
6
    DebugLocListsIndex, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
7
    DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwarfFileType, DwoId, Encoding,
8
    LocationListsOffset, RangeListsOffset, RawRangeListsOffset, SectionId, UnitSectionOffset,
9
};
10
use crate::constants;
11
use crate::read::{
12
    Abbreviations, AbbreviationsCache, AbbreviationsCacheStrategy, AttributeValue, DebugAbbrev,
13
    DebugAddr, DebugAranges, DebugCuIndex, DebugInfo, DebugInfoUnitHeadersIter, DebugLine,
14
    DebugLineStr, DebugLoc, DebugLocLists, DebugRanges, DebugRngLists, DebugStr, DebugStrOffsets,
15
    DebugTuIndex, DebugTypes, DebugTypesUnitHeadersIter, DebuggingInformationEntry, EntriesCursor,
16
    EntriesRaw, EntriesTree, Error, IncompleteLineProgram, LocListIter, LocationLists, Range,
17
    RangeLists, RawLocListIter, RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result,
18
    RngListIter, Section, UnitHeader, UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType,
19
};
20
21
/// All of the commonly used DWARF sections.
22
///
23
/// This is useful for storing sections when `T` does not implement `Reader`.
24
/// It can be used to create a `Dwarf` that references the data in `self`.
25
/// If `T` does implement `Reader`, then use `Dwarf` directly.
26
///
27
/// ## Example Usage
28
///
29
/// It can be useful to load DWARF sections into owned data structures,
30
/// such as `Vec`. However, we do not implement the `Reader` trait
31
/// for `Vec`, because it would be very inefficient, but this trait
32
/// is required for all of the methods that parse the DWARF data.
33
/// So we first load the DWARF sections into `Vec`s, and then use
34
/// `borrow` to create `Reader`s that reference the data.
35
///
36
/// ```rust,no_run
37
/// # fn example() -> Result<(), gimli::Error> {
38
/// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
39
/// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
40
/// let dwarf_sections: gimli::DwarfSections<Vec<u8>> = gimli::DwarfSections::load(loader)?;
41
/// // Create references to the DWARF sections.
42
/// let dwarf: gimli::Dwarf<_> = dwarf_sections.borrow(|section| {
43
///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
44
/// });
45
/// # unreachable!()
46
/// # }
47
/// ```
48
#[derive(Debug)]
49
pub struct DwarfSections<T> {
50
    /// The `.debug_abbrev` section.
51
    pub debug_abbrev: DebugAbbrev<T>,
52
    /// The `.debug_addr` section.
53
    pub debug_addr: DebugAddr<T>,
54
    /// The `.debug_aranges` section.
55
    pub debug_aranges: DebugAranges<T>,
56
    /// The `.debug_info` section.
57
    pub debug_info: DebugInfo<T>,
58
    /// The `.debug_line` section.
59
    pub debug_line: DebugLine<T>,
60
    /// The `.debug_line_str` section.
61
    pub debug_line_str: DebugLineStr<T>,
62
    /// The `.debug_str` section.
63
    pub debug_str: DebugStr<T>,
64
    /// The `.debug_str_offsets` section.
65
    pub debug_str_offsets: DebugStrOffsets<T>,
66
    /// The `.debug_types` section.
67
    pub debug_types: DebugTypes<T>,
68
    /// The `.debug_loc` section.
69
    pub debug_loc: DebugLoc<T>,
70
    /// The `.debug_loclists` section.
71
    pub debug_loclists: DebugLocLists<T>,
72
    /// The `.debug_ranges` section.
73
    pub debug_ranges: DebugRanges<T>,
74
    /// The `.debug_rnglists` section.
75
    pub debug_rnglists: DebugRngLists<T>,
76
}
77
78
impl<T> DwarfSections<T> {
79
    /// Try to load the DWARF sections using the given loader function.
80
    ///
81
    /// `section` loads a DWARF section from the object file.
82
    /// It should return an empty section if the section does not exist.
83
0
    pub fn load<F, E>(mut section: F) -> core::result::Result<Self, E>
84
0
    where
85
0
        F: FnMut(SectionId) -> core::result::Result<T, E>,
86
0
    {
87
0
        Ok(DwarfSections {
88
0
            // Section types are inferred.
89
0
            debug_abbrev: Section::load(&mut section)?,
90
0
            debug_addr: Section::load(&mut section)?,
91
0
            debug_aranges: Section::load(&mut section)?,
92
0
            debug_info: Section::load(&mut section)?,
93
0
            debug_line: Section::load(&mut section)?,
94
0
            debug_line_str: Section::load(&mut section)?,
95
0
            debug_str: Section::load(&mut section)?,
96
0
            debug_str_offsets: Section::load(&mut section)?,
97
0
            debug_types: Section::load(&mut section)?,
98
0
            debug_loc: Section::load(&mut section)?,
99
0
            debug_loclists: Section::load(&mut section)?,
100
0
            debug_ranges: Section::load(&mut section)?,
101
0
            debug_rnglists: Section::load(&mut section)?,
102
        })
103
0
    }
Unexecuted instantiation: <gimli::read::dwarf::DwarfSections<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load::<<backtrace::symbolize::gimli::Context>::new::{closure#0}, ()>
Unexecuted instantiation: <gimli::read::dwarf::DwarfSections<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load::<<backtrace::symbolize::gimli::Context>::new::{closure#1}, ()>
Unexecuted instantiation: <gimli::read::dwarf::DwarfSections<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load::<backtrace::symbolize::gimli::elf::handle_split_dwarf::{closure#0}, ()>
Unexecuted instantiation: <gimli::read::dwarf::DwarfSections<_>>::load::<_, _>
104
105
    /// Create a `Dwarf` structure that references the data in `self`.
106
0
    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf<R>
107
0
    where
108
0
        F: FnMut(&'a T) -> R,
109
0
    {
110
0
        Dwarf::from_sections(DwarfSections {
111
0
            debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
112
0
            debug_addr: self.debug_addr.borrow(&mut borrow),
113
0
            debug_aranges: self.debug_aranges.borrow(&mut borrow),
114
0
            debug_info: self.debug_info.borrow(&mut borrow),
115
0
            debug_line: self.debug_line.borrow(&mut borrow),
116
0
            debug_line_str: self.debug_line_str.borrow(&mut borrow),
117
0
            debug_str: self.debug_str.borrow(&mut borrow),
118
0
            debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
119
0
            debug_types: self.debug_types.borrow(&mut borrow),
120
0
            debug_loc: self.debug_loc.borrow(&mut borrow),
121
0
            debug_loclists: self.debug_loclists.borrow(&mut borrow),
122
0
            debug_ranges: self.debug_ranges.borrow(&mut borrow),
123
0
            debug_rnglists: self.debug_rnglists.borrow(&mut borrow),
124
0
        })
125
0
    }
126
127
    /// Create a `Dwarf` structure that references the data in `self` and `sup`.
128
    ///
129
    /// This is like `borrow`, but also includes the supplementary object file.
130
    /// This is useful when `R` implements `Reader` but `T` does not.
131
    ///
132
    /// ## Example Usage
133
    ///
134
    /// ```rust,no_run
135
    /// # fn example() -> Result<(), gimli::Error> {
136
    /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
137
    /// # let sup_loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
138
    /// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
139
    /// let dwarf_sections: gimli::DwarfSections<Vec<u8>> = gimli::DwarfSections::load(loader)?;
140
    /// let dwarf_sup_sections: gimli::DwarfSections<Vec<u8>> = gimli::DwarfSections::load(sup_loader)?;
141
    /// // Create references to the DWARF sections.
142
    /// let dwarf = dwarf_sections.borrow_with_sup(&dwarf_sup_sections, |section| {
143
    ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
144
    /// });
145
    /// # unreachable!()
146
    /// # }
147
    /// ```
148
0
    pub fn borrow_with_sup<'a, F, R>(&'a self, sup: &'a Self, mut borrow: F) -> Dwarf<R>
149
0
    where
150
0
        F: FnMut(&'a T) -> R,
151
0
    {
152
0
        let mut dwarf = self.borrow(&mut borrow);
153
0
        dwarf.set_sup(sup.borrow(&mut borrow));
154
0
        dwarf
155
0
    }
156
}
157
158
/// All of the commonly used DWARF sections, and other common information.
159
#[derive(Debug, Default)]
160
pub struct Dwarf<R> {
161
    /// The `.debug_abbrev` section.
162
    pub debug_abbrev: DebugAbbrev<R>,
163
164
    /// The `.debug_addr` section.
165
    pub debug_addr: DebugAddr<R>,
166
167
    /// The `.debug_aranges` section.
168
    pub debug_aranges: DebugAranges<R>,
169
170
    /// The `.debug_info` section.
171
    pub debug_info: DebugInfo<R>,
172
173
    /// The `.debug_line` section.
174
    pub debug_line: DebugLine<R>,
175
176
    /// The `.debug_line_str` section.
177
    pub debug_line_str: DebugLineStr<R>,
178
179
    /// The `.debug_str` section.
180
    pub debug_str: DebugStr<R>,
181
182
    /// The `.debug_str_offsets` section.
183
    pub debug_str_offsets: DebugStrOffsets<R>,
184
185
    /// The `.debug_types` section.
186
    pub debug_types: DebugTypes<R>,
187
188
    /// The location lists in the `.debug_loc` and `.debug_loclists` sections.
189
    pub locations: LocationLists<R>,
190
191
    /// The range lists in the `.debug_ranges` and `.debug_rnglists` sections.
192
    pub ranges: RangeLists<R>,
193
194
    /// The type of this file.
195
    pub file_type: DwarfFileType,
196
197
    /// The DWARF sections for a supplementary object file.
198
    pub sup: Option<Arc<Dwarf<R>>>,
199
200
    /// A cache of previously parsed abbreviations for units in this file.
201
    pub abbreviations_cache: AbbreviationsCache,
202
}
203
204
impl<T> Dwarf<T> {
205
    /// Try to load the DWARF sections using the given loader function.
206
    ///
207
    /// `section` loads a DWARF section from the object file.
208
    /// It should return an empty section if the section does not exist.
209
    ///
210
    /// After loading, the user should set the `file_type` field and
211
    /// call `load_sup` if required.
212
0
    pub fn load<F, E>(section: F) -> core::result::Result<Self, E>
213
0
    where
214
0
        F: FnMut(SectionId) -> core::result::Result<T, E>,
215
0
    {
216
0
        let sections = DwarfSections::load(section)?;
217
0
        Ok(Self::from_sections(sections))
218
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load::<<backtrace::symbolize::gimli::Context>::new::{closure#0}, ()>
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load::<<backtrace::symbolize::gimli::Context>::new::{closure#1}, ()>
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load::<backtrace::symbolize::gimli::elf::handle_split_dwarf::{closure#0}, ()>
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::load::<_, _>
219
220
    /// Load the DWARF sections from the supplementary object file.
221
    ///
222
    /// `section` operates the same as for `load`.
223
    ///
224
    /// Sets `self.sup`, replacing any previous value.
225
0
    pub fn load_sup<F, E>(&mut self, section: F) -> core::result::Result<(), E>
226
0
    where
227
0
        F: FnMut(SectionId) -> core::result::Result<T, E>,
228
0
    {
229
0
        self.set_sup(Self::load(section)?);
230
0
        Ok(())
231
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load_sup::<<backtrace::symbolize::gimli::Context>::new::{closure#1}, ()>
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::load_sup::<_, _>
232
233
    /// Create a `Dwarf` structure from the given sections.
234
    ///
235
    /// The caller should set the `file_type` and `sup` fields if required.
236
0
    fn from_sections(sections: DwarfSections<T>) -> Self {
237
0
        Dwarf {
238
0
            debug_abbrev: sections.debug_abbrev,
239
0
            debug_addr: sections.debug_addr,
240
0
            debug_aranges: sections.debug_aranges,
241
0
            debug_info: sections.debug_info,
242
0
            debug_line: sections.debug_line,
243
0
            debug_line_str: sections.debug_line_str,
244
0
            debug_str: sections.debug_str,
245
0
            debug_str_offsets: sections.debug_str_offsets,
246
0
            debug_types: sections.debug_types,
247
0
            locations: LocationLists::new(sections.debug_loc, sections.debug_loclists),
248
0
            ranges: RangeLists::new(sections.debug_ranges, sections.debug_rnglists),
249
0
            file_type: DwarfFileType::Main,
250
0
            sup: None,
251
0
            abbreviations_cache: AbbreviationsCache::new(),
252
0
        }
253
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::from_sections
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::from_sections
254
255
    /// Create a `Dwarf` structure that references the data in `self`.
256
    ///
257
    /// This is useful when `R` implements `Reader` but `T` does not.
258
    ///
259
    /// ## Example Usage
260
    ///
261
    /// It can be useful to load DWARF sections into owned data structures,
262
    /// such as `Vec`. However, we do not implement the `Reader` trait
263
    /// for `Vec`, because it would be very inefficient, but this trait
264
    /// is required for all of the methods that parse the DWARF data.
265
    /// So we first load the DWARF sections into `Vec`s, and then use
266
    /// `borrow` to create `Reader`s that reference the data.
267
    ///
268
    /// ```rust,no_run
269
    /// # fn example() -> Result<(), gimli::Error> {
270
    /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
271
    /// # let sup_loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
272
    /// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
273
    /// let mut owned_dwarf: gimli::Dwarf<Vec<u8>> = gimli::Dwarf::load(loader)?;
274
    /// owned_dwarf.load_sup(sup_loader)?;
275
    /// // Create references to the DWARF sections.
276
    /// let dwarf = owned_dwarf.borrow(|section| {
277
    ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
278
    /// });
279
    /// # unreachable!()
280
    /// # }
281
    /// ```
282
    #[deprecated(note = "use `DwarfSections::borrow` instead")]
283
0
    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf<R>
284
0
    where
285
0
        F: FnMut(&'a T) -> R,
286
0
    {
287
0
        Dwarf {
288
0
            debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
289
0
            debug_addr: self.debug_addr.borrow(&mut borrow),
290
0
            debug_aranges: self.debug_aranges.borrow(&mut borrow),
291
0
            debug_info: self.debug_info.borrow(&mut borrow),
292
0
            debug_line: self.debug_line.borrow(&mut borrow),
293
0
            debug_line_str: self.debug_line_str.borrow(&mut borrow),
294
0
            debug_str: self.debug_str.borrow(&mut borrow),
295
0
            debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
296
0
            debug_types: self.debug_types.borrow(&mut borrow),
297
0
            locations: self.locations.borrow(&mut borrow),
298
0
            ranges: self.ranges.borrow(&mut borrow),
299
0
            file_type: self.file_type,
300
0
            sup: self.sup().map(|sup| Arc::new(sup.borrow(borrow))),
301
0
            abbreviations_cache: AbbreviationsCache::new(),
302
0
        }
303
0
    }
304
305
    /// Store the DWARF sections for the supplementary object file.
306
0
    pub fn set_sup(&mut self, sup: Dwarf<T>) {
307
0
        self.sup = Some(Arc::new(sup));
308
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::set_sup
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::set_sup
309
310
    /// Return a reference to the DWARF sections for the supplementary object file.
311
0
    pub fn sup(&self) -> Option<&Dwarf<T>> {
312
0
        self.sup.as_ref().map(Arc::as_ref)
313
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::sup
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::sup
314
}
315
316
impl<R: Reader> Dwarf<R> {
317
    /// Parse abbreviations and store them in the cache.
318
    ///
319
    /// This will iterate over the units in `self.debug_info` to determine the
320
    /// abbreviations offsets.
321
    ///
322
    /// Errors during parsing abbreviations are also stored in the cache.
323
    /// Errors during iterating over the units are ignored.
324
0
    pub fn populate_abbreviations_cache(&mut self, strategy: AbbreviationsCacheStrategy) {
325
0
        self.abbreviations_cache
326
0
            .populate(strategy, &self.debug_abbrev, self.debug_info.units());
327
0
    }
328
329
    /// Iterate the unit headers in the `.debug_info` section.
330
    ///
331
    /// Can be [used with
332
    /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
333
    #[inline]
334
0
    pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
335
0
        self.debug_info.units()
336
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::units
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::units
337
338
    /// Construct a new `Unit` from the given unit header.
339
    #[inline]
340
0
    pub fn unit(&self, header: UnitHeader<R>) -> Result<Unit<R>> {
341
0
        Unit::new(self, header)
342
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::unit
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::unit
343
344
    /// Iterate the type-unit headers in the `.debug_types` section.
345
    ///
346
    /// Can be [used with
347
    /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
348
    #[inline]
349
0
    pub fn type_units(&self) -> DebugTypesUnitHeadersIter<R> {
350
0
        self.debug_types.units()
351
0
    }
352
353
    /// Parse the abbreviations for a compilation unit.
354
    #[inline]
355
0
    pub fn abbreviations(&self, unit: &UnitHeader<R>) -> Result<Arc<Abbreviations>> {
356
0
        self.abbreviations_cache
357
0
            .get(&self.debug_abbrev, unit.debug_abbrev_offset())
358
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::abbreviations
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::abbreviations
359
360
    /// Return the string offset at the given index.
361
    #[inline]
362
0
    pub fn string_offset(
363
0
        &self,
364
0
        unit: &Unit<R>,
365
0
        index: DebugStrOffsetsIndex<R::Offset>,
366
0
    ) -> Result<DebugStrOffset<R::Offset>> {
367
0
        self.debug_str_offsets
368
0
            .get_str_offset(unit.header.format(), unit.str_offsets_base, index)
369
0
    }
370
371
    /// Return the string at the given offset in `.debug_str`.
372
    #[inline]
373
0
    pub fn string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
374
0
        self.debug_str.get_str(offset)
375
0
    }
376
377
    /// Return the string at the given offset in `.debug_line_str`.
378
    #[inline]
379
0
    pub fn line_string(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
380
0
        self.debug_line_str.get_str(offset)
381
0
    }
382
383
    /// Return an attribute value as a string slice.
384
    ///
385
    /// If the attribute value is one of:
386
    ///
387
    /// - an inline `DW_FORM_string` string
388
    /// - a `DW_FORM_strp` reference to an offset into the `.debug_str` section
389
    /// - a `DW_FORM_strp_sup` reference to an offset into a supplementary
390
    /// object file
391
    /// - a `DW_FORM_line_strp` reference to an offset into the `.debug_line_str`
392
    /// section
393
    /// - a `DW_FORM_strx` index into the `.debug_str_offsets` entries for the unit
394
    ///
395
    /// then return the attribute's string value. Returns an error if the attribute
396
    /// value does not have a string form, or if a string form has an invalid value.
397
0
    pub fn attr_string(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<R> {
398
0
        match attr {
399
0
            AttributeValue::String(string) => Ok(string),
400
0
            AttributeValue::DebugStrRef(offset) => self.debug_str.get_str(offset),
401
0
            AttributeValue::DebugStrRefSup(offset) => {
402
0
                if let Some(sup) = self.sup() {
403
0
                    sup.debug_str.get_str(offset)
404
                } else {
405
0
                    Err(Error::ExpectedStringAttributeValue)
406
                }
407
            }
408
0
            AttributeValue::DebugLineStrRef(offset) => self.debug_line_str.get_str(offset),
409
0
            AttributeValue::DebugStrOffsetsIndex(index) => {
410
0
                let offset = self.debug_str_offsets.get_str_offset(
411
0
                    unit.header.format(),
412
0
                    unit.str_offsets_base,
413
0
                    index,
414
0
                )?;
415
0
                self.debug_str.get_str(offset)
416
            }
417
0
            _ => Err(Error::ExpectedStringAttributeValue),
418
        }
419
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::attr_string
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::attr_string
420
421
    /// Return the address at the given index.
422
0
    pub fn address(&self, unit: &Unit<R>, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
423
0
        self.debug_addr
424
0
            .get_address(unit.encoding().address_size, unit.addr_base, index)
425
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::address
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::address
426
427
    /// Try to return an attribute value as an address.
428
    ///
429
    /// If the attribute value is one of:
430
    ///
431
    /// - a `DW_FORM_addr`
432
    /// - a `DW_FORM_addrx` index into the `.debug_addr` entries for the unit
433
    ///
434
    /// then return the address.
435
    /// Returns `None` for other forms.
436
0
    pub fn attr_address(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<Option<u64>> {
437
0
        match attr {
438
0
            AttributeValue::Addr(addr) => Ok(Some(addr)),
439
0
            AttributeValue::DebugAddrIndex(index) => self.address(unit, index).map(Some),
440
0
            _ => Ok(None),
441
        }
442
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::attr_address
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::attr_address
443
444
    /// Return the range list offset for the given raw offset.
445
    ///
446
    /// This handles adding `DW_AT_GNU_ranges_base` if required.
447
0
    pub fn ranges_offset_from_raw(
448
0
        &self,
449
0
        unit: &Unit<R>,
450
0
        offset: RawRangeListsOffset<R::Offset>,
451
0
    ) -> RangeListsOffset<R::Offset> {
452
0
        if self.file_type == DwarfFileType::Dwo && unit.header.version() < 5 {
453
0
            RangeListsOffset(offset.0.wrapping_add(unit.rnglists_base.0))
454
        } else {
455
0
            RangeListsOffset(offset.0)
456
        }
457
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::ranges_offset_from_raw
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::ranges_offset_from_raw
458
459
    /// Return the range list offset at the given index.
460
0
    pub fn ranges_offset(
461
0
        &self,
462
0
        unit: &Unit<R>,
463
0
        index: DebugRngListsIndex<R::Offset>,
464
0
    ) -> Result<RangeListsOffset<R::Offset>> {
465
0
        self.ranges
466
0
            .get_offset(unit.encoding(), unit.rnglists_base, index)
467
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::ranges_offset
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::ranges_offset
468
469
    /// Iterate over the `RangeListEntry`s starting at the given offset.
470
0
    pub fn ranges(
471
0
        &self,
472
0
        unit: &Unit<R>,
473
0
        offset: RangeListsOffset<R::Offset>,
474
0
    ) -> Result<RngListIter<R>> {
475
0
        self.ranges.ranges(
476
0
            offset,
477
0
            unit.encoding(),
478
0
            unit.low_pc,
479
0
            &self.debug_addr,
480
0
            unit.addr_base,
481
0
        )
482
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::ranges
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::ranges
483
484
    /// Iterate over the `RawRngListEntry`ies starting at the given offset.
485
0
    pub fn raw_ranges(
486
0
        &self,
487
0
        unit: &Unit<R>,
488
0
        offset: RangeListsOffset<R::Offset>,
489
0
    ) -> Result<RawRngListIter<R>> {
490
0
        self.ranges.raw_ranges(offset, unit.encoding())
491
0
    }
492
493
    /// Try to return an attribute value as a range list offset.
494
    ///
495
    /// If the attribute value is one of:
496
    ///
497
    /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections
498
    /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit
499
    ///
500
    /// then return the range list offset of the range list.
501
    /// Returns `None` for other forms.
502
0
    pub fn attr_ranges_offset(
503
0
        &self,
504
0
        unit: &Unit<R>,
505
0
        attr: AttributeValue<R>,
506
0
    ) -> Result<Option<RangeListsOffset<R::Offset>>> {
507
0
        match attr {
508
0
            AttributeValue::RangeListsRef(offset) => {
509
0
                Ok(Some(self.ranges_offset_from_raw(unit, offset)))
510
            }
511
0
            AttributeValue::DebugRngListsIndex(index) => self.ranges_offset(unit, index).map(Some),
512
0
            _ => Ok(None),
513
        }
514
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::attr_ranges_offset
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::attr_ranges_offset
515
516
    /// Try to return an attribute value as a range list entry iterator.
517
    ///
518
    /// If the attribute value is one of:
519
    ///
520
    /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections
521
    /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit
522
    ///
523
    /// then return an iterator over the entries in the range list.
524
    /// Returns `None` for other forms.
525
0
    pub fn attr_ranges(
526
0
        &self,
527
0
        unit: &Unit<R>,
528
0
        attr: AttributeValue<R>,
529
0
    ) -> Result<Option<RngListIter<R>>> {
530
0
        match self.attr_ranges_offset(unit, attr)? {
531
0
            Some(offset) => Ok(Some(self.ranges(unit, offset)?)),
532
0
            None => Ok(None),
533
        }
534
0
    }
535
536
    /// Return an iterator for the address ranges of a `DebuggingInformationEntry`.
537
    ///
538
    /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges`.
539
0
    pub fn die_ranges(
540
0
        &self,
541
0
        unit: &Unit<R>,
542
0
        entry: &DebuggingInformationEntry<R>,
543
0
    ) -> Result<RangeIter<R>> {
544
0
        let mut low_pc = None;
545
0
        let mut high_pc = None;
546
0
        let mut size = None;
547
0
        let mut attrs = entry.attrs();
548
0
        while let Some(attr) = attrs.next()? {
549
0
            match attr.name() {
550
                constants::DW_AT_low_pc => {
551
                    low_pc = Some(
552
0
                        self.attr_address(unit, attr.value())?
553
0
                            .ok_or(Error::UnsupportedAttributeForm)?,
554
                    );
555
                }
556
0
                constants::DW_AT_high_pc => match attr.value() {
557
0
                    AttributeValue::Udata(val) => size = Some(val),
558
0
                    attr => {
559
0
                        high_pc = Some(
560
0
                            self.attr_address(unit, attr)?
561
0
                                .ok_or(Error::UnsupportedAttributeForm)?,
562
                        );
563
                    }
564
                },
565
                constants::DW_AT_ranges => {
566
0
                    if let Some(list) = self.attr_ranges(unit, attr.value())? {
567
0
                        return Ok(RangeIter(RangeIterInner::List(list)));
568
0
                    }
569
                }
570
0
                _ => {}
571
            }
572
        }
573
0
        let range = low_pc.and_then(|begin| {
574
0
            let end = size.map(|size| begin + size).or(high_pc);
575
0
            // TODO: perhaps return an error if `end` is `None`
576
0
            end.map(|end| Range { begin, end })
577
0
        });
578
0
        Ok(RangeIter(RangeIterInner::Single(range)))
579
0
    }
580
581
    /// Return an iterator for the address ranges of a `Unit`.
582
    ///
583
    /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges` of the
584
    /// root `DebuggingInformationEntry`.
585
0
    pub fn unit_ranges(&self, unit: &Unit<R>) -> Result<RangeIter<R>> {
586
0
        let mut cursor = unit.header.entries(&unit.abbreviations);
587
0
        cursor.next_dfs()?;
588
0
        let root = cursor.current().ok_or(Error::MissingUnitDie)?;
589
0
        self.die_ranges(unit, root)
590
0
    }
591
592
    /// Return the location list offset at the given index.
593
0
    pub fn locations_offset(
594
0
        &self,
595
0
        unit: &Unit<R>,
596
0
        index: DebugLocListsIndex<R::Offset>,
597
0
    ) -> Result<LocationListsOffset<R::Offset>> {
598
0
        self.locations
599
0
            .get_offset(unit.encoding(), unit.loclists_base, index)
600
0
    }
601
602
    /// Iterate over the `LocationListEntry`s starting at the given offset.
603
0
    pub fn locations(
604
0
        &self,
605
0
        unit: &Unit<R>,
606
0
        offset: LocationListsOffset<R::Offset>,
607
0
    ) -> Result<LocListIter<R>> {
608
0
        match self.file_type {
609
0
            DwarfFileType::Main => self.locations.locations(
610
0
                offset,
611
0
                unit.encoding(),
612
0
                unit.low_pc,
613
0
                &self.debug_addr,
614
0
                unit.addr_base,
615
0
            ),
616
0
            DwarfFileType::Dwo => self.locations.locations_dwo(
617
0
                offset,
618
0
                unit.encoding(),
619
0
                unit.low_pc,
620
0
                &self.debug_addr,
621
0
                unit.addr_base,
622
0
            ),
623
        }
624
0
    }
625
626
    /// Iterate over the raw `LocationListEntry`s starting at the given offset.
627
0
    pub fn raw_locations(
628
0
        &self,
629
0
        unit: &Unit<R>,
630
0
        offset: LocationListsOffset<R::Offset>,
631
0
    ) -> Result<RawLocListIter<R>> {
632
0
        match self.file_type {
633
0
            DwarfFileType::Main => self.locations.raw_locations(offset, unit.encoding()),
634
0
            DwarfFileType::Dwo => self.locations.raw_locations_dwo(offset, unit.encoding()),
635
        }
636
0
    }
637
638
    /// Try to return an attribute value as a location list offset.
639
    ///
640
    /// If the attribute value is one of:
641
    ///
642
    /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections
643
    /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit
644
    ///
645
    /// then return the location list offset of the location list.
646
    /// Returns `None` for other forms.
647
0
    pub fn attr_locations_offset(
648
0
        &self,
649
0
        unit: &Unit<R>,
650
0
        attr: AttributeValue<R>,
651
0
    ) -> Result<Option<LocationListsOffset<R::Offset>>> {
652
0
        match attr {
653
0
            AttributeValue::LocationListsRef(offset) => Ok(Some(offset)),
654
0
            AttributeValue::DebugLocListsIndex(index) => {
655
0
                self.locations_offset(unit, index).map(Some)
656
            }
657
0
            _ => Ok(None),
658
        }
659
0
    }
660
661
    /// Try to return an attribute value as a location list entry iterator.
662
    ///
663
    /// If the attribute value is one of:
664
    ///
665
    /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections
666
    /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit
667
    ///
668
    /// then return an iterator over the entries in the location list.
669
    /// Returns `None` for other forms.
670
0
    pub fn attr_locations(
671
0
        &self,
672
0
        unit: &Unit<R>,
673
0
        attr: AttributeValue<R>,
674
0
    ) -> Result<Option<LocListIter<R>>> {
675
0
        match self.attr_locations_offset(unit, attr)? {
676
0
            Some(offset) => Ok(Some(self.locations(unit, offset)?)),
677
0
            None => Ok(None),
678
        }
679
0
    }
680
681
    /// Call `Reader::lookup_offset_id` for each section, and return the first match.
682
    ///
683
    /// The first element of the tuple is `true` for supplementary sections.
684
0
    pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(bool, SectionId, R::Offset)> {
685
0
        None.or_else(|| self.debug_abbrev.lookup_offset_id(id))
686
0
            .or_else(|| self.debug_addr.lookup_offset_id(id))
687
0
            .or_else(|| self.debug_aranges.lookup_offset_id(id))
688
0
            .or_else(|| self.debug_info.lookup_offset_id(id))
689
0
            .or_else(|| self.debug_line.lookup_offset_id(id))
690
0
            .or_else(|| self.debug_line_str.lookup_offset_id(id))
691
0
            .or_else(|| self.debug_str.lookup_offset_id(id))
692
0
            .or_else(|| self.debug_str_offsets.lookup_offset_id(id))
693
0
            .or_else(|| self.debug_types.lookup_offset_id(id))
694
0
            .or_else(|| self.locations.lookup_offset_id(id))
695
0
            .or_else(|| self.ranges.lookup_offset_id(id))
696
0
            .map(|(id, offset)| (false, id, offset))
697
0
            .or_else(|| {
698
0
                self.sup()
699
0
                    .and_then(|sup| sup.lookup_offset_id(id))
700
0
                    .map(|(_, id, offset)| (true, id, offset))
701
0
            })
702
0
    }
703
704
    /// Returns a string representation of the given error.
705
    ///
706
    /// This uses information from the DWARF sections to provide more information in some cases.
707
0
    pub fn format_error(&self, err: Error) -> String {
708
0
        #[allow(clippy::single_match)]
709
0
        match err {
710
0
            Error::UnexpectedEof(id) => match self.lookup_offset_id(id) {
711
0
                Some((sup, section, offset)) => {
712
0
                    return format!(
713
0
                        "{} at {}{}+0x{:x}",
714
0
                        err,
715
0
                        section.name(),
716
0
                        if sup { "(sup)" } else { "" },
717
0
                        offset.into_u64(),
718
                    );
719
                }
720
0
                None => {}
721
            },
722
0
            _ => {}
723
        }
724
0
        err.description().into()
725
0
    }
726
}
727
728
impl<R: Clone> Dwarf<R> {
729
    /// Assuming `self` was loaded from a .dwo, take the appropriate
730
    /// sections from `parent` (which contains the skeleton unit for this
731
    /// dwo) such as `.debug_addr` and merge them into this `Dwarf`.
732
0
    pub fn make_dwo(&mut self, parent: &Dwarf<R>) {
733
0
        self.file_type = DwarfFileType::Dwo;
734
0
        // These sections are always taken from the parent file and not the dwo.
735
0
        self.debug_addr = parent.debug_addr.clone();
736
0
        // .debug_rnglists comes from the DWO, .debug_ranges comes from the
737
0
        // parent file.
738
0
        self.ranges
739
0
            .set_debug_ranges(parent.ranges.debug_ranges().clone());
740
0
        self.sup = parent.sup.clone();
741
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::make_dwo
Unexecuted instantiation: <gimli::read::dwarf::Dwarf<_>>::make_dwo
742
}
743
744
/// The sections from a `.dwp` file.
745
///
746
/// This is useful for storing sections when `T` does not implement `Reader`.
747
/// It can be used to create a `DwarfPackage` that references the data in `self`.
748
/// If `T` does implement `Reader`, then use `DwarfPackage` directly.
749
///
750
/// ## Example Usage
751
///
752
/// It can be useful to load DWARF sections into owned data structures,
753
/// such as `Vec`. However, we do not implement the `Reader` trait
754
/// for `Vec`, because it would be very inefficient, but this trait
755
/// is required for all of the methods that parse the DWARF data.
756
/// So we first load the DWARF sections into `Vec`s, and then use
757
/// `borrow` to create `Reader`s that reference the data.
758
///
759
/// ```rust,no_run
760
/// # fn example() -> Result<(), gimli::Error> {
761
/// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
762
/// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
763
/// let dwp_sections: gimli::DwarfPackageSections<Vec<u8>> = gimli::DwarfPackageSections::load(loader)?;
764
/// // Create references to the DWARF sections.
765
/// let dwp: gimli::DwarfPackage<_> = dwp_sections.borrow(
766
///     |section| gimli::EndianSlice::new(&section, gimli::LittleEndian),
767
///     gimli::EndianSlice::new(&[], gimli::LittleEndian),
768
/// )?;
769
/// # unreachable!()
770
/// # }
771
/// ```
772
#[derive(Debug)]
773
pub struct DwarfPackageSections<T> {
774
    /// The `.debug_cu_index` section.
775
    pub cu_index: DebugCuIndex<T>,
776
    /// The `.debug_tu_index` section.
777
    pub tu_index: DebugTuIndex<T>,
778
    /// The `.debug_abbrev.dwo` section.
779
    pub debug_abbrev: DebugAbbrev<T>,
780
    /// The `.debug_info.dwo` section.
781
    pub debug_info: DebugInfo<T>,
782
    /// The `.debug_line.dwo` section.
783
    pub debug_line: DebugLine<T>,
784
    /// The `.debug_str.dwo` section.
785
    pub debug_str: DebugStr<T>,
786
    /// The `.debug_str_offsets.dwo` section.
787
    pub debug_str_offsets: DebugStrOffsets<T>,
788
    /// The `.debug_loc.dwo` section.
789
    ///
790
    /// Only present when using GNU split-dwarf extension to DWARF 4.
791
    pub debug_loc: DebugLoc<T>,
792
    /// The `.debug_loclists.dwo` section.
793
    pub debug_loclists: DebugLocLists<T>,
794
    /// The `.debug_rnglists.dwo` section.
795
    pub debug_rnglists: DebugRngLists<T>,
796
    /// The `.debug_types.dwo` section.
797
    ///
798
    /// Only present when using GNU split-dwarf extension to DWARF 4.
799
    pub debug_types: DebugTypes<T>,
800
}
801
802
impl<T> DwarfPackageSections<T> {
803
    /// Try to load the `.dwp` sections using the given loader function.
804
    ///
805
    /// `section` loads a DWARF section from the object file.
806
    /// It should return an empty section if the section does not exist.
807
0
    pub fn load<F, E>(mut section: F) -> core::result::Result<Self, E>
808
0
    where
809
0
        F: FnMut(SectionId) -> core::result::Result<T, E>,
810
0
        E: From<Error>,
811
0
    {
812
0
        Ok(DwarfPackageSections {
813
0
            // Section types are inferred.
814
0
            cu_index: Section::load(&mut section)?,
815
0
            tu_index: Section::load(&mut section)?,
816
0
            debug_abbrev: Section::load(&mut section)?,
817
0
            debug_info: Section::load(&mut section)?,
818
0
            debug_line: Section::load(&mut section)?,
819
0
            debug_str: Section::load(&mut section)?,
820
0
            debug_str_offsets: Section::load(&mut section)?,
821
0
            debug_loc: Section::load(&mut section)?,
822
0
            debug_loclists: Section::load(&mut section)?,
823
0
            debug_rnglists: Section::load(&mut section)?,
824
0
            debug_types: Section::load(&mut section)?,
825
        })
826
0
    }
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackageSections<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load::<<backtrace::symbolize::gimli::Context>::new::{closure#2}, gimli::read::Error>
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackageSections<_>>::load::<_, _>
827
828
    /// Create a `DwarfPackage` structure that references the data in `self`.
829
0
    pub fn borrow<'a, F, R>(&'a self, mut borrow: F, empty: R) -> Result<DwarfPackage<R>>
830
0
    where
831
0
        F: FnMut(&'a T) -> R,
832
0
        R: Reader,
833
0
    {
834
0
        DwarfPackage::from_sections(
835
0
            DwarfPackageSections {
836
0
                cu_index: self.cu_index.borrow(&mut borrow),
837
0
                tu_index: self.tu_index.borrow(&mut borrow),
838
0
                debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
839
0
                debug_info: self.debug_info.borrow(&mut borrow),
840
0
                debug_line: self.debug_line.borrow(&mut borrow),
841
0
                debug_str: self.debug_str.borrow(&mut borrow),
842
0
                debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
843
0
                debug_loc: self.debug_loc.borrow(&mut borrow),
844
0
                debug_loclists: self.debug_loclists.borrow(&mut borrow),
845
0
                debug_rnglists: self.debug_rnglists.borrow(&mut borrow),
846
0
                debug_types: self.debug_types.borrow(&mut borrow),
847
0
            },
848
0
            empty,
849
0
        )
850
0
    }
851
}
852
853
/// The sections from a `.dwp` file, with parsed indices.
854
#[derive(Debug)]
855
pub struct DwarfPackage<R: Reader> {
856
    /// The compilation unit index in the `.debug_cu_index` section.
857
    pub cu_index: UnitIndex<R>,
858
859
    /// The type unit index in the `.debug_tu_index` section.
860
    pub tu_index: UnitIndex<R>,
861
862
    /// The `.debug_abbrev.dwo` section.
863
    pub debug_abbrev: DebugAbbrev<R>,
864
865
    /// The `.debug_info.dwo` section.
866
    pub debug_info: DebugInfo<R>,
867
868
    /// The `.debug_line.dwo` section.
869
    pub debug_line: DebugLine<R>,
870
871
    /// The `.debug_str.dwo` section.
872
    pub debug_str: DebugStr<R>,
873
874
    /// The `.debug_str_offsets.dwo` section.
875
    pub debug_str_offsets: DebugStrOffsets<R>,
876
877
    /// The `.debug_loc.dwo` section.
878
    ///
879
    /// Only present when using GNU split-dwarf extension to DWARF 4.
880
    pub debug_loc: DebugLoc<R>,
881
882
    /// The `.debug_loclists.dwo` section.
883
    pub debug_loclists: DebugLocLists<R>,
884
885
    /// The `.debug_rnglists.dwo` section.
886
    pub debug_rnglists: DebugRngLists<R>,
887
888
    /// The `.debug_types.dwo` section.
889
    ///
890
    /// Only present when using GNU split-dwarf extension to DWARF 4.
891
    pub debug_types: DebugTypes<R>,
892
893
    /// An empty section.
894
    ///
895
    /// Used when creating `Dwarf<R>`.
896
    pub empty: R,
897
}
898
899
impl<R: Reader> DwarfPackage<R> {
900
    /// Try to load the `.dwp` sections using the given loader function.
901
    ///
902
    /// `section` loads a DWARF section from the object file.
903
    /// It should return an empty section if the section does not exist.
904
0
    pub fn load<F, E>(section: F, empty: R) -> core::result::Result<Self, E>
905
0
    where
906
0
        F: FnMut(SectionId) -> core::result::Result<R, E>,
907
0
        E: From<Error>,
908
0
    {
909
0
        let sections = DwarfPackageSections::load(section)?;
910
0
        Ok(Self::from_sections(sections, empty)?)
911
0
    }
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::load::<<backtrace::symbolize::gimli::Context>::new::{closure#2}, gimli::read::Error>
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<_>>::load::<_, _>
912
913
    /// Create a `DwarfPackage` structure from the given sections.
914
0
    fn from_sections(sections: DwarfPackageSections<R>, empty: R) -> Result<Self> {
915
0
        Ok(DwarfPackage {
916
0
            cu_index: sections.cu_index.index()?,
917
0
            tu_index: sections.tu_index.index()?,
918
0
            debug_abbrev: sections.debug_abbrev,
919
0
            debug_info: sections.debug_info,
920
0
            debug_line: sections.debug_line,
921
0
            debug_str: sections.debug_str,
922
0
            debug_str_offsets: sections.debug_str_offsets,
923
0
            debug_loc: sections.debug_loc,
924
0
            debug_loclists: sections.debug_loclists,
925
0
            debug_rnglists: sections.debug_rnglists,
926
0
            debug_types: sections.debug_types,
927
0
            empty,
928
        })
929
0
    }
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::from_sections
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<_>>::from_sections
930
931
    /// Find the compilation unit with the given DWO identifier and return its section
932
    /// contributions.
933
    ///
934
    /// ## Example Usage
935
    ///
936
    /// ```rust,no_run
937
    /// # fn example<R: gimli::Reader>(
938
    /// #        dwarf: &gimli::Dwarf<R>,
939
    /// #        dwp: &gimli::DwarfPackage<R>,
940
    /// #        dwo_id: gimli::DwoId,
941
    /// # ) -> Result<(), gimli::Error> {
942
    /// if let Some(dwo) = dwp.find_cu(dwo_id, dwarf)? {
943
    ///    let dwo_header = dwo.units().next()?.expect("DWO should have one unit");
944
    ///    let dwo_unit = dwo.unit(dwo_header)?;
945
    ///    // Do something with `dwo_unit`.
946
    /// }
947
    /// # unreachable!()
948
    /// # }
949
0
    pub fn find_cu(&self, id: DwoId, parent: &Dwarf<R>) -> Result<Option<Dwarf<R>>> {
950
0
        let row = match self.cu_index.find(id.0) {
951
0
            Some(row) => row,
952
0
            None => return Ok(None),
953
        };
954
0
        self.cu_sections(row, parent).map(Some)
955
0
    }
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::find_cu
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<_>>::find_cu
956
957
    /// Find the type unit with the given type signature and return its section
958
    /// contributions.
959
0
    pub fn find_tu(
960
0
        &self,
961
0
        signature: DebugTypeSignature,
962
0
        parent: &Dwarf<R>,
963
0
    ) -> Result<Option<Dwarf<R>>> {
964
0
        let row = match self.tu_index.find(signature.0) {
965
0
            Some(row) => row,
966
0
            None => return Ok(None),
967
        };
968
0
        self.tu_sections(row, parent).map(Some)
969
0
    }
970
971
    /// Return the section contributions of the compilation unit at the given index.
972
    ///
973
    /// The index must be in the range `1..cu_index.unit_count`.
974
    ///
975
    /// This function should only be needed by low level parsers.
976
0
    pub fn cu_sections(&self, index: u32, parent: &Dwarf<R>) -> Result<Dwarf<R>> {
977
0
        self.sections(self.cu_index.sections(index)?, parent)
978
0
    }
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::cu_sections
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<_>>::cu_sections
979
980
    /// Return the section contributions of the compilation unit at the given index.
981
    ///
982
    /// The index must be in the range `1..tu_index.unit_count`.
983
    ///
984
    /// This function should only be needed by low level parsers.
985
0
    pub fn tu_sections(&self, index: u32, parent: &Dwarf<R>) -> Result<Dwarf<R>> {
986
0
        self.sections(self.tu_index.sections(index)?, parent)
987
0
    }
988
989
    /// Return the section contributions of a unit.
990
    ///
991
    /// This function should only be needed by low level parsers.
992
0
    pub fn sections(
993
0
        &self,
994
0
        sections: UnitIndexSectionIterator<R>,
995
0
        parent: &Dwarf<R>,
996
0
    ) -> Result<Dwarf<R>> {
997
0
        let mut abbrev_offset = 0;
998
0
        let mut abbrev_size = 0;
999
0
        let mut info_offset = 0;
1000
0
        let mut info_size = 0;
1001
0
        let mut line_offset = 0;
1002
0
        let mut line_size = 0;
1003
0
        let mut loc_offset = 0;
1004
0
        let mut loc_size = 0;
1005
0
        let mut loclists_offset = 0;
1006
0
        let mut loclists_size = 0;
1007
0
        let mut str_offsets_offset = 0;
1008
0
        let mut str_offsets_size = 0;
1009
0
        let mut rnglists_offset = 0;
1010
0
        let mut rnglists_size = 0;
1011
0
        let mut types_offset = 0;
1012
0
        let mut types_size = 0;
1013
0
        for section in sections {
1014
0
            match section.section {
1015
0
                SectionId::DebugAbbrev => {
1016
0
                    abbrev_offset = section.offset;
1017
0
                    abbrev_size = section.size;
1018
0
                }
1019
0
                SectionId::DebugInfo => {
1020
0
                    info_offset = section.offset;
1021
0
                    info_size = section.size;
1022
0
                }
1023
0
                SectionId::DebugLine => {
1024
0
                    line_offset = section.offset;
1025
0
                    line_size = section.size;
1026
0
                }
1027
0
                SectionId::DebugLoc => {
1028
0
                    loc_offset = section.offset;
1029
0
                    loc_size = section.size;
1030
0
                }
1031
0
                SectionId::DebugLocLists => {
1032
0
                    loclists_offset = section.offset;
1033
0
                    loclists_size = section.size;
1034
0
                }
1035
0
                SectionId::DebugStrOffsets => {
1036
0
                    str_offsets_offset = section.offset;
1037
0
                    str_offsets_size = section.size;
1038
0
                }
1039
0
                SectionId::DebugRngLists => {
1040
0
                    rnglists_offset = section.offset;
1041
0
                    rnglists_size = section.size;
1042
0
                }
1043
0
                SectionId::DebugTypes => {
1044
0
                    types_offset = section.offset;
1045
0
                    types_size = section.size;
1046
0
                }
1047
0
                SectionId::DebugMacro | SectionId::DebugMacinfo => {
1048
0
                    // These are valid but we can't parse these yet.
1049
0
                }
1050
0
                _ => return Err(Error::UnknownIndexSection),
1051
            }
1052
        }
1053
1054
0
        let debug_abbrev = self.debug_abbrev.dwp_range(abbrev_offset, abbrev_size)?;
1055
0
        let debug_info = self.debug_info.dwp_range(info_offset, info_size)?;
1056
0
        let debug_line = self.debug_line.dwp_range(line_offset, line_size)?;
1057
0
        let debug_loc = self.debug_loc.dwp_range(loc_offset, loc_size)?;
1058
0
        let debug_loclists = self
1059
0
            .debug_loclists
1060
0
            .dwp_range(loclists_offset, loclists_size)?;
1061
0
        let debug_str_offsets = self
1062
0
            .debug_str_offsets
1063
0
            .dwp_range(str_offsets_offset, str_offsets_size)?;
1064
0
        let debug_rnglists = self
1065
0
            .debug_rnglists
1066
0
            .dwp_range(rnglists_offset, rnglists_size)?;
1067
0
        let debug_types = self.debug_types.dwp_range(types_offset, types_size)?;
1068
1069
0
        let debug_str = self.debug_str.clone();
1070
0
1071
0
        let debug_addr = parent.debug_addr.clone();
1072
0
        let debug_ranges = parent.ranges.debug_ranges().clone();
1073
0
1074
0
        let debug_aranges = self.empty.clone().into();
1075
0
        let debug_line_str = self.empty.clone().into();
1076
0
1077
0
        Ok(Dwarf {
1078
0
            debug_abbrev,
1079
0
            debug_addr,
1080
0
            debug_aranges,
1081
0
            debug_info,
1082
0
            debug_line,
1083
0
            debug_line_str,
1084
0
            debug_str,
1085
0
            debug_str_offsets,
1086
0
            debug_types,
1087
0
            locations: LocationLists::new(debug_loc, debug_loclists),
1088
0
            ranges: RangeLists::new(debug_ranges, debug_rnglists),
1089
0
            file_type: DwarfFileType::Dwo,
1090
0
            sup: parent.sup.clone(),
1091
0
            abbreviations_cache: AbbreviationsCache::new(),
1092
0
        })
1093
0
    }
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::sections
Unexecuted instantiation: <gimli::read::dwarf::DwarfPackage<_>>::sections
1094
}
1095
1096
/// All of the commonly used information for a unit in the `.debug_info` or `.debug_types`
1097
/// sections.
1098
#[derive(Debug)]
1099
pub struct Unit<R, Offset = <R as Reader>::Offset>
1100
where
1101
    R: Reader<Offset = Offset>,
1102
    Offset: ReaderOffset,
1103
{
1104
    /// The header of the unit.
1105
    pub header: UnitHeader<R, Offset>,
1106
1107
    /// The parsed abbreviations for the unit.
1108
    pub abbreviations: Arc<Abbreviations>,
1109
1110
    /// The `DW_AT_name` attribute of the unit.
1111
    pub name: Option<R>,
1112
1113
    /// The `DW_AT_comp_dir` attribute of the unit.
1114
    pub comp_dir: Option<R>,
1115
1116
    /// The `DW_AT_low_pc` attribute of the unit. Defaults to 0.
1117
    pub low_pc: u64,
1118
1119
    /// The `DW_AT_str_offsets_base` attribute of the unit. Defaults to 0.
1120
    pub str_offsets_base: DebugStrOffsetsBase<Offset>,
1121
1122
    /// The `DW_AT_addr_base` attribute of the unit. Defaults to 0.
1123
    pub addr_base: DebugAddrBase<Offset>,
1124
1125
    /// The `DW_AT_loclists_base` attribute of the unit. Defaults to 0.
1126
    pub loclists_base: DebugLocListsBase<Offset>,
1127
1128
    /// The `DW_AT_rnglists_base` attribute of the unit. Defaults to 0.
1129
    pub rnglists_base: DebugRngListsBase<Offset>,
1130
1131
    /// The line number program of the unit.
1132
    pub line_program: Option<IncompleteLineProgram<R, Offset>>,
1133
1134
    /// The DWO ID of a skeleton unit or split compilation unit.
1135
    pub dwo_id: Option<DwoId>,
1136
}
1137
1138
impl<R: Reader> Unit<R> {
1139
    /// Construct a new `Unit` from the given unit header.
1140
    #[inline]
1141
0
    pub fn new(dwarf: &Dwarf<R>, header: UnitHeader<R>) -> Result<Self> {
1142
0
        let abbreviations = dwarf.abbreviations(&header)?;
1143
0
        Self::new_with_abbreviations(dwarf, header, abbreviations)
1144
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Unit<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::new
Unexecuted instantiation: <gimli::read::dwarf::Unit<_>>::new
1145
1146
    /// Construct a new `Unit` from the given unit header and abbreviations.
1147
    ///
1148
    /// The abbreviations for this call can be obtained using `dwarf.abbreviations(&header)`.
1149
    /// The caller may implement caching to reuse the `Abbreviations` across units with the
1150
    /// same `header.debug_abbrev_offset()` value.
1151
    #[inline]
1152
0
    pub fn new_with_abbreviations(
1153
0
        dwarf: &Dwarf<R>,
1154
0
        header: UnitHeader<R>,
1155
0
        abbreviations: Arc<Abbreviations>,
1156
0
    ) -> Result<Self> {
1157
0
        let mut unit = Unit {
1158
0
            abbreviations,
1159
0
            name: None,
1160
0
            comp_dir: None,
1161
0
            low_pc: 0,
1162
0
            str_offsets_base: DebugStrOffsetsBase::default_for_encoding_and_file(
1163
0
                header.encoding(),
1164
0
                dwarf.file_type,
1165
0
            ),
1166
0
            // NB: Because the .debug_addr section never lives in a .dwo, we can assume its base is always 0 or provided.
1167
0
            addr_base: DebugAddrBase(R::Offset::from_u8(0)),
1168
0
            loclists_base: DebugLocListsBase::default_for_encoding_and_file(
1169
0
                header.encoding(),
1170
0
                dwarf.file_type,
1171
0
            ),
1172
0
            rnglists_base: DebugRngListsBase::default_for_encoding_and_file(
1173
0
                header.encoding(),
1174
0
                dwarf.file_type,
1175
0
            ),
1176
0
            line_program: None,
1177
0
            dwo_id: match header.type_() {
1178
0
                UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => Some(dwo_id),
1179
0
                _ => None,
1180
            },
1181
0
            header,
1182
0
        };
1183
0
        let mut name = None;
1184
0
        let mut comp_dir = None;
1185
0
        let mut line_program_offset = None;
1186
0
        let mut low_pc_attr = None;
1187
0
1188
0
        {
1189
0
            let mut cursor = unit.header.entries(&unit.abbreviations);
1190
0
            cursor.next_dfs()?;
1191
0
            let root = cursor.current().ok_or(Error::MissingUnitDie)?;
1192
0
            let mut attrs = root.attrs();
1193
0
            while let Some(attr) = attrs.next()? {
1194
0
                match attr.name() {
1195
0
                    constants::DW_AT_name => {
1196
0
                        name = Some(attr.value());
1197
0
                    }
1198
0
                    constants::DW_AT_comp_dir => {
1199
0
                        comp_dir = Some(attr.value());
1200
0
                    }
1201
0
                    constants::DW_AT_low_pc => {
1202
0
                        low_pc_attr = Some(attr.value());
1203
0
                    }
1204
                    constants::DW_AT_stmt_list => {
1205
0
                        if let AttributeValue::DebugLineRef(offset) = attr.value() {
1206
0
                            line_program_offset = Some(offset);
1207
0
                        }
1208
                    }
1209
                    constants::DW_AT_str_offsets_base => {
1210
0
                        if let AttributeValue::DebugStrOffsetsBase(base) = attr.value() {
1211
0
                            unit.str_offsets_base = base;
1212
0
                        }
1213
                    }
1214
                    constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
1215
0
                        if let AttributeValue::DebugAddrBase(base) = attr.value() {
1216
0
                            unit.addr_base = base;
1217
0
                        }
1218
                    }
1219
                    constants::DW_AT_loclists_base => {
1220
0
                        if let AttributeValue::DebugLocListsBase(base) = attr.value() {
1221
0
                            unit.loclists_base = base;
1222
0
                        }
1223
                    }
1224
                    constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
1225
0
                        if let AttributeValue::DebugRngListsBase(base) = attr.value() {
1226
0
                            unit.rnglists_base = base;
1227
0
                        }
1228
                    }
1229
                    constants::DW_AT_GNU_dwo_id => {
1230
0
                        if unit.dwo_id.is_none() {
1231
0
                            if let AttributeValue::DwoId(dwo_id) = attr.value() {
1232
0
                                unit.dwo_id = Some(dwo_id);
1233
0
                            }
1234
0
                        }
1235
                    }
1236
0
                    _ => {}
1237
                }
1238
            }
1239
        }
1240
1241
0
        unit.name = match name {
1242
0
            Some(val) => dwarf.attr_string(&unit, val).ok(),
1243
0
            None => None,
1244
        };
1245
0
        unit.comp_dir = match comp_dir {
1246
0
            Some(val) => dwarf.attr_string(&unit, val).ok(),
1247
0
            None => None,
1248
        };
1249
0
        unit.line_program = match line_program_offset {
1250
0
            Some(offset) => Some(dwarf.debug_line.program(
1251
0
                offset,
1252
0
                unit.header.address_size(),
1253
0
                unit.comp_dir.clone(),
1254
0
                unit.name.clone(),
1255
0
            )?),
1256
0
            None => None,
1257
        };
1258
0
        if let Some(low_pc_attr) = low_pc_attr {
1259
0
            if let Some(addr) = dwarf.attr_address(&unit, low_pc_attr)? {
1260
0
                unit.low_pc = addr;
1261
0
            }
1262
0
        }
1263
0
        Ok(unit)
1264
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Unit<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::new_with_abbreviations
Unexecuted instantiation: <gimli::read::dwarf::Unit<_>>::new_with_abbreviations
1265
1266
    /// Return the encoding parameters for this unit.
1267
    #[inline]
1268
0
    pub fn encoding(&self) -> Encoding {
1269
0
        self.header.encoding()
1270
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Unit<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::encoding
Unexecuted instantiation: <gimli::read::dwarf::Unit<_>>::encoding
1271
1272
    /// Read the `DebuggingInformationEntry` at the given offset.
1273
0
    pub fn entry(&self, offset: UnitOffset<R::Offset>) -> Result<DebuggingInformationEntry<R>> {
1274
0
        self.header.entry(&self.abbreviations, offset)
1275
0
    }
1276
1277
    /// Navigate this unit's `DebuggingInformationEntry`s.
1278
    #[inline]
1279
0
    pub fn entries(&self) -> EntriesCursor<R> {
1280
0
        self.header.entries(&self.abbreviations)
1281
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Unit<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::entries
Unexecuted instantiation: <gimli::read::dwarf::Unit<_>>::entries
1282
1283
    /// Navigate this unit's `DebuggingInformationEntry`s
1284
    /// starting at the given offset.
1285
    #[inline]
1286
0
    pub fn entries_at_offset(&self, offset: UnitOffset<R::Offset>) -> Result<EntriesCursor<R>> {
1287
0
        self.header.entries_at_offset(&self.abbreviations, offset)
1288
0
    }
1289
1290
    /// Navigate this unit's `DebuggingInformationEntry`s as a tree
1291
    /// starting at the given offset.
1292
    #[inline]
1293
0
    pub fn entries_tree(&self, offset: Option<UnitOffset<R::Offset>>) -> Result<EntriesTree<R>> {
1294
0
        self.header.entries_tree(&self.abbreviations, offset)
1295
0
    }
1296
1297
    /// Read the raw data that defines the Debugging Information Entries.
1298
    #[inline]
1299
0
    pub fn entries_raw(&self, offset: Option<UnitOffset<R::Offset>>) -> Result<EntriesRaw<R>> {
1300
0
        self.header.entries_raw(&self.abbreviations, offset)
1301
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Unit<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::entries_raw
Unexecuted instantiation: <gimli::read::dwarf::Unit<_>>::entries_raw
1302
1303
    /// Copy attributes that are subject to relocation from another unit. This is intended
1304
    /// to be used to copy attributes from a skeleton compilation unit to the corresponding
1305
    /// split compilation unit.
1306
0
    pub fn copy_relocated_attributes(&mut self, other: &Unit<R>) {
1307
0
        self.low_pc = other.low_pc;
1308
0
        self.addr_base = other.addr_base;
1309
0
        if self.header.version() < 5 {
1310
0
            self.rnglists_base = other.rnglists_base;
1311
0
        }
1312
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Unit<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::copy_relocated_attributes
Unexecuted instantiation: <gimli::read::dwarf::Unit<_>>::copy_relocated_attributes
1313
1314
    /// Find the dwo name (if any) for this unit, automatically handling the differences
1315
    /// between the standardized DWARF 5 split DWARF format and the pre-DWARF 5 GNU
1316
    /// extension.
1317
    ///
1318
    /// The returned value is relative to this unit's `comp_dir`.
1319
0
    pub fn dwo_name(&self) -> Result<Option<AttributeValue<R>>> {
1320
0
        let mut entries = self.entries();
1321
0
        entries.next_entry()?;
1322
0
        let entry = entries.current().ok_or(Error::MissingUnitDie)?;
1323
0
        if self.header.version() < 5 {
1324
0
            entry.attr_value(constants::DW_AT_GNU_dwo_name)
1325
        } else {
1326
0
            entry.attr_value(constants::DW_AT_dwo_name)
1327
        }
1328
0
    }
Unexecuted instantiation: <gimli::read::dwarf::Unit<gimli::read::endian_slice::EndianSlice<gimli::endianity::LittleEndian>>>::dwo_name
Unexecuted instantiation: <gimli::read::dwarf::Unit<_>>::dwo_name
1329
}
1330
1331
impl<T: ReaderOffset> UnitSectionOffset<T> {
1332
    /// Convert an offset to be relative to the start of the given unit,
1333
    /// instead of relative to the start of the section.
1334
    /// Returns `None` if the offset is not within the unit entries.
1335
0
    pub fn to_unit_offset<R>(&self, unit: &Unit<R>) -> Option<UnitOffset<T>>
1336
0
    where
1337
0
        R: Reader<Offset = T>,
1338
0
    {
1339
0
        let (offset, unit_offset) = match (self, unit.header.offset()) {
1340
            (
1341
0
                UnitSectionOffset::DebugInfoOffset(offset),
1342
0
                UnitSectionOffset::DebugInfoOffset(unit_offset),
1343
0
            ) => (offset.0, unit_offset.0),
1344
            (
1345
0
                UnitSectionOffset::DebugTypesOffset(offset),
1346
0
                UnitSectionOffset::DebugTypesOffset(unit_offset),
1347
0
            ) => (offset.0, unit_offset.0),
1348
0
            _ => return None,
1349
        };
1350
0
        let offset = match offset.checked_sub(unit_offset) {
1351
0
            Some(offset) => UnitOffset(offset),
1352
0
            None => return None,
1353
        };
1354
0
        if !unit.header.is_valid_offset(offset) {
1355
0
            return None;
1356
0
        }
1357
0
        Some(offset)
1358
0
    }
1359
}
1360
1361
impl<T: ReaderOffset> UnitOffset<T> {
1362
    /// Convert an offset to be relative to the start of the .debug_info section,
1363
    /// instead of relative to the start of the given compilation unit.
1364
    ///
1365
    /// Does not check that the offset is valid.
1366
0
    pub fn to_unit_section_offset<R>(&self, unit: &Unit<R>) -> UnitSectionOffset<T>
1367
0
    where
1368
0
        R: Reader<Offset = T>,
1369
0
    {
1370
0
        match unit.header.offset() {
1371
0
            UnitSectionOffset::DebugInfoOffset(unit_offset) => {
1372
0
                DebugInfoOffset(unit_offset.0 + self.0).into()
1373
            }
1374
0
            UnitSectionOffset::DebugTypesOffset(unit_offset) => {
1375
0
                DebugTypesOffset(unit_offset.0 + self.0).into()
1376
            }
1377
        }
1378
0
    }
1379
}
1380
1381
/// An iterator for the address ranges of a `DebuggingInformationEntry`.
1382
///
1383
/// Returned by `Dwarf::die_ranges` and `Dwarf::unit_ranges`.
1384
#[derive(Debug)]
1385
pub struct RangeIter<R: Reader>(RangeIterInner<R>);
1386
1387
#[derive(Debug)]
1388
enum RangeIterInner<R: Reader> {
1389
    Single(Option<Range>),
1390
    List(RngListIter<R>),
1391
}
1392
1393
impl<R: Reader> Default for RangeIter<R> {
1394
0
    fn default() -> Self {
1395
0
        RangeIter(RangeIterInner::Single(None))
1396
0
    }
1397
}
1398
1399
impl<R: Reader> RangeIter<R> {
1400
    /// Advance the iterator to the next range.
1401
0
    pub fn next(&mut self) -> Result<Option<Range>> {
1402
0
        match self.0 {
1403
0
            RangeIterInner::Single(ref mut range) => Ok(range.take()),
1404
0
            RangeIterInner::List(ref mut list) => list.next(),
1405
        }
1406
0
    }
1407
}
1408
1409
#[cfg(feature = "fallible-iterator")]
1410
impl<R: Reader> fallible_iterator::FallibleIterator for RangeIter<R> {
1411
    type Item = Range;
1412
    type Error = Error;
1413
1414
    #[inline]
1415
    fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
1416
        RangeIter::next(self)
1417
    }
1418
}
1419
1420
#[cfg(test)]
1421
mod tests {
1422
    use super::*;
1423
    use crate::read::EndianSlice;
1424
    use crate::{Endianity, LittleEndian};
1425
1426
    /// Ensure that `Dwarf<R>` is covariant wrt R.
1427
    #[test]
1428
    fn test_dwarf_variance() {
1429
        /// This only needs to compile.
1430
        fn _f<'a: 'b, 'b, E: Endianity>(x: Dwarf<EndianSlice<'a, E>>) -> Dwarf<EndianSlice<'b, E>> {
1431
            x
1432
        }
1433
    }
1434
1435
    /// Ensure that `Unit<R>` is covariant wrt R.
1436
    #[test]
1437
    fn test_dwarf_unit_variance() {
1438
        /// This only needs to compile.
1439
        fn _f<'a: 'b, 'b, E: Endianity>(x: Unit<EndianSlice<'a, E>>) -> Unit<EndianSlice<'b, E>> {
1440
            x
1441
        }
1442
    }
1443
1444
    #[test]
1445
    fn test_send() {
1446
        fn assert_is_send<T: Send>() {}
1447
        assert_is_send::<Dwarf<EndianSlice<LittleEndian>>>();
1448
        assert_is_send::<Unit<EndianSlice<LittleEndian>>>();
1449
    }
1450
1451
    #[test]
1452
    fn test_format_error() {
1453
        let dwarf_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap();
1454
        let sup_sections = DwarfSections::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap();
1455
        let dwarf = dwarf_sections.borrow_with_sup(&sup_sections, |section| {
1456
            EndianSlice::new(section, LittleEndian)
1457
        });
1458
1459
        match dwarf.debug_str.get_str(DebugStrOffset(1)) {
1460
            Ok(r) => panic!("Unexpected str {:?}", r),
1461
            Err(e) => {
1462
                assert_eq!(
1463
                    dwarf.format_error(e),
1464
                    "Hit the end of input before it was expected at .debug_str+0x1"
1465
                );
1466
            }
1467
        }
1468
        match dwarf.sup().unwrap().debug_str.get_str(DebugStrOffset(1)) {
1469
            Ok(r) => panic!("Unexpected str {:?}", r),
1470
            Err(e) => {
1471
                assert_eq!(
1472
                    dwarf.format_error(e),
1473
                    "Hit the end of input before it was expected at .debug_str(sup)+0x1"
1474
                );
1475
            }
1476
        }
1477
        assert_eq!(dwarf.format_error(Error::Io), Error::Io.description());
1478
    }
1479
}